Skip to content

Commit

Permalink
Add feature for resolvers to exist outside of Blitz root (#3953)
Browse files Browse the repository at this point in the history
Co-authored-by: Paul Moss <[email protected]>
Co-authored-by: Brandon Bayer <[email protected]>
Co-authored-by: Dillon Raphael <[email protected]>
  • Loading branch information
4 people authored Nov 14, 2022
1 parent d250346 commit ed2b0e2
Show file tree
Hide file tree
Showing 11 changed files with 101 additions and 17 deletions.
5 changes: 5 additions & 0 deletions .changeset/olive-dragons-drum.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@blitzjs/rpc": patch
---

Add ability to put your query and mutation resolvers in a separate monorepo folder, allowing you to use them in multiple apps.
3 changes: 0 additions & 3 deletions integration-tests/no-suspense/app/queries/getBasic.ts

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default async function getNoSuspenseBasic() {
return "basic-result"
}
4 changes: 2 additions & 2 deletions integration-tests/no-suspense/pages/use-query.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import getBasic from "../app/queries/getBasic"
import getNoSuspenseBasic from "../app/queries/getNoSuspenseBasic"
import {useQuery} from "@blitzjs/rpc"
import React from "react"

function Content() {
const [result, {isFetching}] = useQuery(getBasic, undefined)
const [result, {isFetching}] = useQuery(getNoSuspenseBasic, undefined)

if (isFetching) {
return <>Loading...</>
Expand Down
6 changes: 5 additions & 1 deletion integration-tests/react-query-utils/next.config.js
Original file line number Diff line number Diff line change
@@ -1,2 +1,6 @@
const {withBlitz} = require("@blitzjs/next")
module.exports = withBlitz({})
module.exports = withBlitz({
blitz: {
includeRPCFolders: ["../no-suspense/app"],
},
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import {getQueryData, useQuery} from "@blitzjs/rpc"
import {Suspense, useState} from "react"
import getNoSuspenseBasic from "../../no-suspense/app/queries/getNoSuspenseBasic"

function Content() {
const [data] = useQuery(getNoSuspenseBasic, undefined)
const [newData, setNewData] = useState<string>()
return (
<div>
<div>{data}</div>
{newData && <div id="new-data">{newData}</div>}
<button
id="button"
onClick={async () => {
const newData = getQueryData(getNoSuspenseBasic, undefined)
setNewData(newData)
}}
>
Call getQueryData
</button>
</div>
)
}

function PageWithGetQueryData() {
return (
<div id="page">
<Suspense fallback={"Loading..."}>
<Content />
</Suspense>
</div>
)
}

export default PageWithGetQueryData
19 changes: 19 additions & 0 deletions integration-tests/react-query-utils/test/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,25 @@ const runTests = () => {
)
})

describe("get query data from monorepo", () => {
it(
"should work",
async () => {
const browser = await webdriver(appPort, "/page-with-monorepo-query")

browser.waitForElementByCss("#button", 0)
await browser.elementByCss("#button").click()

browser.waitForElementByCss("#new-data", 0)
const newText = await browser.elementByCss("#new-data").text()
expect(newText).toMatch(/basic-result/)

if (browser) await browser.close()
},
5000 * 60 * 2,
)
})

describe("prefetch infinite query", () => {
it(
"should work",
Expand Down
2 changes: 2 additions & 0 deletions packages/blitz-next/src/index-server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,7 @@ export const setupBlitzServer = ({plugins, onError, logger}: SetupBlitzOptions)
export interface BlitzConfig extends NextConfig {
blitz?: {
resolverPath?: ResolverPathOptions
includeRPCFolders?: string[]
customServer?: {
hotReload?: boolean
}
Expand Down Expand Up @@ -252,6 +253,7 @@ export function withBlitz(nextConfig: BlitzConfig = {}) {
webpackConfig: config,
webpackRuleOptions: {
resolverPath: nextConfig.blitz?.resolverPath,
includeRPCFolders: nextConfig.blitz?.includeRPCFolders,
},
})
if (typeof nextConfig.webpack === "function") {
Expand Down
1 change: 1 addition & 0 deletions packages/blitz-rpc/src/index-server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ const loaderServerResolvers = resolve(dir, "./loader-server-resolvers.cjs")

interface WebpackRuleOptions {
resolverPath: ResolverPathOptions | undefined
includeRPCFolders: string[] | undefined
}

interface WebpackRule {
Expand Down
39 changes: 28 additions & 11 deletions packages/blitz-rpc/src/loader-server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,13 @@ export async function loader(this: Loader, input: string): Promise<string> {
const compiler = this._compiler!
const id = this.resource
const root = this._compiler!.context
const rpcFolders = this.query.includeRPCFolders ? this.query.includeRPCFolders : []

const isSSR = compiler.name === "server"
if (isSSR) {
this.cacheable(false)

const resolvers = await collectResolvers(root, ["ts", "js"])
const resolvers = await collectResolvers(root, rpcFolders, ["ts", "js"])
return await transformBlitzRpcServer(
input,
toPosixPath(id),
Expand Down Expand Up @@ -56,17 +57,30 @@ export async function transformBlitzRpcServer(
let code = blitzImport + src
code += "\n\n"
for (let resolverFilePath of resolvers) {
const relativeResolverPath = slash(relative(dirname(id), join(root, resolverFilePath)))
const routePath = convertPageFilePathToRoutePath(resolverFilePath, options?.resolverPath)
code += `__internal_addBlitzRpcResolver('${routePath}',() => import('${relativeResolverPath}'));`
const routePath = convertPageFilePathToRoutePath(slash(resolverFilePath), options?.resolverPath)

code += `__internal_addBlitzRpcResolver('${routePath}',() => import('${slash(
resolverFilePath,
)}'));`
code += "\n"
}
// console.log("NEW CODE", code)
return code
}

export function collectResolvers(directory: string, pageExtensions: string[]): Promise<string[]> {
return recursiveFindResolvers(directory, buildPageExtensionRegex(pageExtensions))
export function collectResolvers(
directory: string,
rpcFolders: string[],
pageExtensions: string[],
): Promise<string[]> {
return recursiveFindResolvers(
directory,
buildPageExtensionRegex(pageExtensions),
undefined,
[],
directory,
rpcFolders,
)
}

export async function recursiveFindResolvers(
Expand All @@ -75,11 +89,13 @@ export async function recursiveFindResolvers(
ignore?: RegExp,
arr: string[] = [],
rootDir: string = dir,
rpcFolders: string[] = [],
): Promise<string[]> {
let folders = await promises.readdir(dir)

if (dir === rootDir) {
folders = folders.filter((folder) => topLevelFoldersThatMayContainResolvers.includes(folder))
folders.push(...rpcFolders)
}

await Promise.all(
Expand All @@ -90,17 +106,18 @@ export async function recursiveFindResolvers(
const pathStat = await promises.stat(absolutePath)

if (pathStat.isDirectory()) {
await recursiveFindResolvers(absolutePath, filter, ignore, arr, rootDir)
return
if (!absolutePath.includes("node_modules")) {
await recursiveFindResolvers(absolutePath, filter, ignore, arr, rootDir)
return
}
}

if (!filter.test(part)) {
return
}

const relativeFromRoot = absolutePath.replace(rootDir, "")
if (getIsRpcFile(relativeFromRoot)) {
arr.push(relativeFromRoot)
if (getIsRpcFile(absolutePath)) {
arr.push(absolutePath)
return
}
}),
Expand Down
1 change: 1 addition & 0 deletions packages/blitz-rpc/src/loader-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {ResolverPathOptions} from "./index-server"

export interface LoaderOptions {
resolverPath: ResolverPathOptions
includeRPCFolders?: string[]
}

export interface Loader {
Expand Down

0 comments on commit ed2b0e2

Please sign in to comment.