Skip to content

Commit

Permalink
feat(router): fs-router support apiDir configurability (#1295)
Browse files Browse the repository at this point in the history
resolves #1293

---------

Co-authored-by: Tyler <[email protected]>
Co-authored-by: Daishi Kato <[email protected]>
  • Loading branch information
3 people authored Mar 7, 2025
1 parent a1185ac commit f4976e3
Show file tree
Hide file tree
Showing 6 changed files with 29 additions and 12 deletions.
2 changes: 1 addition & 1 deletion examples/11_fs-router/src/entries.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,5 @@ export default fsRouter(
import.meta.url,
(file: string) =>
import.meta.glob('./pages/**/*.{tsx,ts}')[`./pages/${file}`]?.(),
'pages',
{ pagesDir: 'pages', apiDir: 'api' },
);
2 changes: 1 addition & 1 deletion examples/12_nossr/src/entries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { unstable_fsRouter as fsRouter } from 'waku/router/server';
const router = fsRouter(
import.meta.url,
(file) => import.meta.glob('./pages/**/*.tsx')[`./pages/${file}`]?.(),
'pages',
{ pagesDir: 'pages', apiDir: 'api' },
);

export default defineEntries({
Expand Down
5 changes: 5 additions & 0 deletions packages/waku/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@ export interface Config {
* Defaults to "pages".
*/
pagesDir?: string;
/**
* The api directory inside pagesDir.
* Defaults to "api".
*/
apiDir?: string;
/**
* The private directory relative to root.
* This folder will contain files that should be read only on the server.
Expand Down
1 change: 1 addition & 0 deletions packages/waku/src/lib/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export async function resolveConfigDev(config: Config) {
srcDir: 'src',
distDir: 'dist',
pagesDir: 'pages',
apiDir: 'api',
privateDir: 'private',
rscBase: 'RSC',
middleware: DEFAULT_MIDDLEWARE,
Expand Down
14 changes: 7 additions & 7 deletions packages/waku/src/lib/plugins/vite-plugin-rsc-managed.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ const stripExt = (fname: string) => {
const getManagedEntries = (
filePath: string,
srcDir: string,
pagesDir: string,
options: { pagesDir: string; apiDir: string },
) => `
import { unstable_fsRouter as fsRouter } from 'waku/router/server';
Expand All @@ -20,7 +20,7 @@ export default fsRouter(
(file) => import.meta.glob('/${srcDir}/pages/**/*.{${EXTENSIONS.map((ext) =>
ext.replace(/^\./, ''),
).join(',')}}')[\`/${srcDir}/pages/\${file}\`]?.(),
'${pagesDir}',
{ pagesDir: '${options.pagesDir}', apiDir: '${options.apiDir}' },
);
`;

Expand All @@ -42,6 +42,7 @@ export function rscManagedPlugin(opts: {
basePath: string;
srcDir: string;
pagesDir: string;
apiDir: string;
addEntriesToInput?: boolean;
addMainToInput?: boolean;
}): Plugin {
Expand Down Expand Up @@ -87,11 +88,10 @@ export function rscManagedPlugin(opts: {
},
load(id) {
if (id === '\0' + entriesFile + '.js') {
return getManagedEntries(
entriesFile + '.js',
opts.srcDir,
opts.pagesDir,
);
return getManagedEntries(entriesFile + '.js', opts.srcDir, {
apiDir: opts.apiDir,
pagesDir: opts.pagesDir,
});
}
if (id === '\0' + mainFile + '.js' || id === '\0' + mainPath + '.js') {
return getManagedMain();
Expand Down
17 changes: 14 additions & 3 deletions packages/waku/src/router/fs-router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,15 @@ const DO_NOT_BUNDLE = '';
export function unstable_fsRouter(
importMetaUrl: string,
loadPage: (file: string) => Promise<any> | undefined,
pages: string,
options: {
/** e.g. `"pages"` will detect pages in `src/pages`. */
pagesDir: string;
/**
* e.g. `"api"` will detect pages in `src/pages/api`. Or, if `options.pagesDir`
* is `"foo"`, then it will detect pages in `src/foo/api`.
*/
apiDir: string;
},
) {
const buildOptions = unstable_getBuildOptions();
return createPages(
Expand All @@ -31,7 +39,10 @@ export function unstable_fsRouter(
import(/* @vite-ignore */ DO_NOT_BUNDLE + 'node:path'),
import(/* @vite-ignore */ DO_NOT_BUNDLE + 'node:url'),
]);
const pagesDir = join(dirname(fileURLToPath(importMetaUrl)), pages);
const pagesDir = join(
dirname(fileURLToPath(importMetaUrl)),
options.pagesDir,
);
files = await readdir(pagesDir, {
encoding: 'utf8',
recursive: true,
Expand Down Expand Up @@ -82,7 +93,7 @@ export function unstable_fsRouter(
throw new Error(
'Page file cannot be named [path]. This will conflict with the path prop of the page component.',
);
} else if (pathItems.at(0) === 'api') {
} else if (pathItems.at(0) === options.apiDir) {
if (config?.render === 'static') {
if (Object.keys(mod).length !== 2 || !mod.GET) {
console.warn(
Expand Down

0 comments on commit f4976e3

Please sign in to comment.