Repository: dai-shi/waku
Pull request #1034 (2024-12-06 04:45:37)

fix(new_createPages): path prop for dynamic layouts only and fix type
This change marks the type of static layouts to not receive `path` as a prop. For layouts to receive `path` as a prop, currently this will need to be made dynamic.

this also includes a fix to new_createPages where we consider the pattern of the staticPaths with slug paths to be the same pattern across each use of a staticPath as it is return from `getPathConfig`

vercel[bot]: [vc]: #Y+2aCljpahp5wMj1y+Jr09BCmTFDp3Zi9N9ZmHWC57k=:eyJpc01vbm9yZXBvIjp0cnVlLCJ0eXBlIjoiZ2l0aHViIiwicHJvamVjdHMiOlt7Im5hbWUiOiJ3YWt1Iiwicm9vdERpcmVjdG9yeSI6bnVsbCwiaW5zcGVjdG9yVXJsIjoiaHR0cHM6Ly92ZXJjZWwuY29tL2RhaXNoaXMtcHJvamVjdHMvd2FrdS85SjdWR01qNkRQS0QzdkJFRkF6OUF4QllHVGVmIiwicHJldmlld1VybCI6Indha3UtZ2l0LWZvcmstdHlsZXJzYXlzaGktbGF5b3V0LXBhdGgtcHJvcC1kYWlzaGlzLXByb2plY3RzLnZlcmNlbC5hcHAiLCJuZXh0Q29tbWl0U3RhdHVzIjoiUEVORElORyJ9XX0=
**The latest updates on your projects**. Learn more about [Vercel for Git ↗︎](https://vercel.link/github-learn-more)

| Name | Status | Preview | Updated (UTC) |
| :--- | :----- | :------ | :------ |
| **waku** | 🔄 Building ([Inspect](https://vercel.com/daishis-projects/waku/9J7VGMj6DPKD3vBEFAz9AxBYGTef)) | [Visit Preview](https://waku-git-fork-tylersayshi-layout-path-prop-daishis-projects.vercel.app) | Dec 6, 2024 4:45am |


codesandbox-ci[bot]: This pull request is automatically built and testable in [CodeSandbox](https://codesandbox.io).

  To see build info of the built libraries, click [here](https://ci.codesandbox.io/status/dai-shi/waku/pr/1034/builds/567804) or the icon next to each commit SHA.
dai-shi: @tylersayshi Can you please summarize changes in the PR description?

Patch:
diff --git a/packages/waku/src/router/create-pages.ts b/packages/waku/src/router/create-pages.ts
index 324a3a21..37f855eb 100644
--- a/packages/waku/src/router/create-pages.ts
+++ b/packages/waku/src/router/create-pages.ts
@@ -144,13 +144,21 @@ export type CreatePage = <
   'unstable_disableSSR'
 >;
 
-export type CreateLayout = <Path extends string>(layout: {
-  render: 'static' | 'dynamic';
-  path: PathWithoutSlug<Path>;
-  component: FunctionComponent<
-    Omit<RouteProps, 'query'> & { children: ReactNode }
-  >;
-}) => void;
+export type CreateLayout = <Path extends string>(
+  layout:
+    | {
+        render: 'dynamic';
+        path: PathWithoutSlug<Path>;
+        component: FunctionComponent<
+          Pick<RouteProps, 'path'> & { children: ReactNode }
+        >;
+      }
+    | {
+        render: 'static';
+        path: PathWithoutSlug<Path>;
+        component: FunctionComponent<{ children: ReactNode }>;
+      },
+) => void;
 
 type RootItem = {
   render: 'static' | 'dynamic';
@@ -483,7 +491,10 @@ export const new_createPages = <
 ) => {
   let configured = false;
 
-  const staticPathMap = new Map<string, PathSpec>();
+  const staticPathMap = new Map<
+    string,
+    { literalSpec: PathSpec; originalSpec?: PathSpec }
+  >();
   const dynamicPagePathMap = new Map<
     string,
     [PathSpec, FunctionComponent<any>]
@@ -552,7 +563,7 @@ export const new_createPages = <
       return { numSlugs, numWildcards };
     })();
     if (page.render === 'static' && numSlugs === 0) {
-      staticPathMap.set(page.path, pathSpec);
+      staticPathMap.set(page.path, { literalSpec: pathSpec });
       const id = joinPath(page.path, 'page').replace(/^\//, '');
       registerStaticComponent(id, page.component);
     } else if (
@@ -587,10 +598,10 @@ export const new_createPages = <
               break;
           }
         });
-        staticPathMap.set(
-          '/' + pathItems.join('/'),
-          pathItems.map((name) => ({ type: 'literal', name })),
-        );
+        staticPathMap.set('/' + pathItems.join('/'), {
+          literalSpec: pathItems.map((name) => ({ type: 'literal', name })),
+          originalSpec: pathSpec,
+        });
         const id = joinPath(...pathItems, 'page');
         const WrappedComponent = (props: Record<string, unknown>) =>
           createElement(page.component as any, { ...props, ...mapping });
@@ -686,12 +697,14 @@ export const new_createPages = <
       }[] = [];
       const rootIsStatic = !rootItem || rootItem.render === 'static';
 
-      for (const [path, pathSpec] of staticPathMap) {
-        const noSsr = noSsrSet.has(pathSpec);
+      for (const [path, { literalSpec, originalSpec }] of staticPathMap) {
+        const noSsr = noSsrSet.has(literalSpec);
 
-        const pattern = path2regexp(parsePathWithSlug(path));
+        const pattern = originalSpec
+          ? path2regexp(originalSpec)
+          : path2regexp(literalSpec);
 
-        const layoutPaths = getLayouts(pathSpec);
+        const layoutPaths = getLayouts(literalSpec);
 
         const elements = {
           ...layoutPaths.reduce<Record<string, { isStatic: boolean }>>(
@@ -709,7 +722,7 @@ export const new_createPages = <
 
         paths.push({
           pattern,
-          path: pathSpec,
+          path: literalSpec,
           routeElement: {
             isStatic: true,
           },
@@ -791,7 +804,7 @@ export const new_createPages = <
         ),
         [`page:${routePath}`]: createElement(
           pageComponent,
-          { ...mapping, ...(query ? { query } : {}) },
+          { ...mapping, ...(query ? { query } : {}), path },
           createElement(Children),
         ),
       };
@@ -803,10 +816,16 @@ export const new_createPages = <
           dynamicLayoutPathMap.get(segment)?.[1] ??
           staticComponentMap.get(joinPath(segment, 'layout').slice(1)); // feels like a hack
 
+        const isDynamic = !dynamicLayoutPathMap.has(segment);
+
         // always true
         if (layout) {
           const id = 'layout:' + segment;
-          result[id] = createElement(layout, null, createElement(Children));
+          result[id] = createElement(
+            layout,
+            isDynamic ? { path } : null,
+            createElement(Children),
+          );
         }
       }
 


Test patch:
diff --git a/packages/waku/tests/create-pages.test.ts b/packages/waku/tests/create-pages.test.ts
index 392cfc05..60b781dd 100644
--- a/packages/waku/tests/create-pages.test.ts
+++ b/packages/waku/tests/create-pages.test.ts
@@ -703,7 +703,7 @@ describe('createPages', () => {
             type: 'literal',
           },
         ],
-        pattern: '^/test/w/x$',
+        pattern: '^/test/([^/]+)/([^/]+)$',
       },
       {
         elements: {
@@ -726,7 +726,7 @@ describe('createPages', () => {
             type: 'literal',
           },
         ],
-        pattern: '^/test/y/z$',
+        pattern: '^/test/([^/]+)/([^/]+)$',
       },
     ]);
     const route = await renderRoute('/test/y/z', {
@@ -813,7 +813,7 @@ describe('createPages', () => {
             type: 'literal',
           },
         ],
-        pattern: '^/test/a/b$',
+        pattern: '^/test/(.*)$',
       },
     ]);
     const route = await renderRoute('/test/a/b', {
@@ -1024,7 +1024,7 @@ describe('createPages', () => {
           'page:/server/static/static-echo': { isStatic: true },
         },
         routeElement: { isStatic: true },
-        pattern: '^/server/static/static-echo$',
+        pattern: '^/server/static/([^/]+)$',
         path: [
           {
             type: 'literal',
@@ -1047,7 +1047,7 @@ describe('createPages', () => {
           'page:/server/static/static-echo-2': { isStatic: true },
         },
         routeElement: { isStatic: true },
-        pattern: '^/server/static/static-echo-2$',
+        pattern: '^/server/static/([^/]+)$',
         path: [
           {
             type: 'literal',
@@ -1070,7 +1070,7 @@ describe('createPages', () => {
           'page:/server/static/static-echo/static-echo-2': { isStatic: true },
         },
         routeElement: { isStatic: true },
-        pattern: '^/server/static/static-echo/static-echo-2$',
+        pattern: '^/server/static/([^/]+)/([^/]+)$',
         path: [
           {
             type: 'literal',
@@ -1097,7 +1097,7 @@ describe('createPages', () => {
           'page:/server/static/hello/hello-2': { isStatic: true },
         },
         routeElement: { isStatic: true },
-        pattern: '^/server/static/hello/hello-2$',
+        pattern: '^/server/static/([^/]+)/([^/]+)$',
         path: [
           {
             type: 'literal',
@@ -1124,7 +1124,7 @@ describe('createPages', () => {
           'page:/static/wild/bar': { isStatic: true },
         },
         routeElement: { isStatic: true },
-        pattern: '^/static/wild/bar$',
+        pattern: '^/static/wild/(.*)$',
         path: [
           {
             type: 'literal',
@@ -1147,7 +1147,7 @@ describe('createPages', () => {
           'page:/static/wild/hello/hello-2': { isStatic: true },
         },
         routeElement: { isStatic: true },
-        pattern: '^/static/wild/hello/hello-2$',
+        pattern: '^/static/wild/(.*)$',
         path: [
           {
             type: 'literal',
@@ -1174,7 +1174,7 @@ describe('createPages', () => {
           'page:/static/wild/foo/foo-2/foo-3': { isStatic: true },
         },
         routeElement: { isStatic: true },
-        pattern: '^/static/wild/foo/foo-2/foo-3$',
+        pattern: '^/static/wild/(.*)$',
         path: [
           {
             type: 'literal',