waku 0.26.0 → 0.26.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/README.md +217 -6
  2. package/dist/lib/middleware/context.js +5 -32
  3. package/dist/lib/middleware/context.js.map +1 -1
  4. package/dist/lib/renderers/utils.d.ts +0 -2
  5. package/dist/lib/renderers/utils.js +0 -26
  6. package/dist/lib/renderers/utils.js.map +1 -1
  7. package/dist/lib/utils/stream.d.ts +0 -2
  8. package/dist/lib/utils/stream.js +0 -29
  9. package/dist/lib/utils/stream.js.map +1 -1
  10. package/dist/lib/vite-plugins/fs-router-typegen.js +6 -0
  11. package/dist/lib/vite-plugins/fs-router-typegen.js.map +1 -1
  12. package/dist/lib/vite-rsc/cli.js +1 -1
  13. package/dist/lib/vite-rsc/cli.js.map +1 -1
  14. package/dist/lib/vite-rsc/deploy/aws-lambda/plugin.js +1 -1
  15. package/dist/lib/vite-rsc/deploy/aws-lambda/plugin.js.map +1 -1
  16. package/dist/lib/vite-rsc/deploy/cloudflare/plugin.js +1 -1
  17. package/dist/lib/vite-rsc/deploy/cloudflare/plugin.js.map +1 -1
  18. package/dist/lib/vite-rsc/deploy/deno/plugin.js +1 -1
  19. package/dist/lib/vite-rsc/deploy/deno/plugin.js.map +1 -1
  20. package/dist/lib/vite-rsc/deploy/netlify/plugin.js +1 -1
  21. package/dist/lib/vite-rsc/deploy/netlify/plugin.js.map +1 -1
  22. package/dist/lib/vite-rsc/deploy/partykit/plugin.js +1 -1
  23. package/dist/lib/vite-rsc/deploy/partykit/plugin.js.map +1 -1
  24. package/dist/lib/vite-rsc/deploy/vercel/plugin.js +17 -8
  25. package/dist/lib/vite-rsc/deploy/vercel/plugin.js.map +1 -1
  26. package/dist/lib/vite-rsc/plugin.js +9 -12
  27. package/dist/lib/vite-rsc/plugin.js.map +1 -1
  28. package/dist/lib/vite-rsc/ssr.js +6 -2
  29. package/dist/lib/vite-rsc/ssr.js.map +1 -1
  30. package/dist/lib/vite-types.d.js.map +1 -1
  31. package/dist/minimal/client.js +1 -1
  32. package/dist/minimal/client.js.map +1 -1
  33. package/dist/router/client.js +18 -6
  34. package/dist/router/client.js.map +1 -1
  35. package/dist/router/common.js +8 -2
  36. package/dist/router/common.js.map +1 -1
  37. package/dist/router/create-pages.js +1 -1
  38. package/dist/router/create-pages.js.map +1 -1
  39. package/dist/types.d.js.map +1 -1
  40. package/package.json +9 -9
  41. package/dist/lib/utils/swc.d.ts +0 -9
  42. package/dist/lib/utils/swc.js +0 -16
  43. package/dist/lib/utils/swc.js.map +0 -1
package/README.md CHANGED
@@ -415,6 +415,107 @@ export const getConfig = async () => {
415
415
  };
416
416
  ```
417
417
 
418
+ #### Group routes
419
+
420
+ Group routes allow you to organize routes into logical groups without affecting the URL structure. They're created by wrapping directory names in parentheses (e.g., `(group)`). This is particularly useful for sharing layouts across multiple routes while keeping the URL clean.
421
+
422
+ For example, you might want a home page at `/` that doesn't use a shared layout, but all other routes should share a common layout. This can be achieved by grouping those routes:
423
+
424
+ ```
425
+ ├── (main)
426
+ │ ├── _layout.tsx
427
+ │ ├── about.tsx
428
+ │ └── contact.tsx
429
+ └── index.tsx
430
+ ```
431
+
432
+ In this structure, `/about` and `/contact` will use the layout from `(main)/_layout.tsx`, but `/` (from `index.tsx`) will not.
433
+
434
+ ```tsx
435
+ // ./src/pages/(main)/_layout.tsx
436
+ import { Header } from '../../components/header';
437
+ import { Footer } from '../../components/footer';
438
+
439
+ // Create shared layout for main pages
440
+ export default async function MainLayout({ children }) {
441
+ return (
442
+ <>
443
+ <Header />
444
+ <main>{children}</main>
445
+ <Footer />
446
+ </>
447
+ );
448
+ }
449
+
450
+ export const getConfig = async () => {
451
+ return {
452
+ render: 'static',
453
+ } as const;
454
+ };
455
+ ```
456
+
457
+ ```tsx
458
+ // ./src/pages/(main)/about.tsx
459
+ export default async function AboutPage() {
460
+ return <h1>About Us</h1>;
461
+ }
462
+
463
+ export const getConfig = async () => {
464
+ return {
465
+ render: 'static',
466
+ } as const;
467
+ };
468
+ ```
469
+
470
+ Group routes can be nested to create complex layout compositions. For instance, you could have a static layout at the group level and a dynamic layout nested within:
471
+
472
+ ```
473
+ (main)
474
+ ├── (dynamic)
475
+ │ ├── _layout.tsx # dynamic layout
476
+ │ ├── dashboard.tsx
477
+ │ └── profile.tsx
478
+ └── _layout.tsx # static layout
479
+ ```
480
+
481
+ This allows for fine-grained control over rendering modes - some work can be done at build time (`static`) while other work happens at runtime (`dynamic`).
482
+
483
+ ```tsx
484
+ // ./src/pages/(main)/_layout.tsx
485
+ // Static layout - runs at build time
486
+ export default async function MainLayout({ children }) {
487
+ return <div className="main-container">{children}</div>;
488
+ }
489
+
490
+ export const getConfig = async () => {
491
+ return {
492
+ render: 'static',
493
+ } as const;
494
+ };
495
+ ```
496
+
497
+ ```tsx
498
+ // ./src/pages/(main)/(dynamic)/_layout.tsx
499
+ // Dynamic layout - runs at request time
500
+ export default async function DynamicLayout({ children }) {
501
+ const userData = await fetchUserData(); // Dynamic data fetching
502
+
503
+ return (
504
+ <div className="dynamic-container">
505
+ <UserContext.Provider value={userData}>{children}</UserContext.Provider>
506
+ </div>
507
+ );
508
+ }
509
+
510
+ export const getConfig = async () => {
511
+ return {
512
+ render: 'dynamic',
513
+ } as const;
514
+ };
515
+ ```
516
+
517
+ Group routes are especially powerful for organizing complex applications where different sections need different layouts, state management, or data requirements while maintaining clean URLs.
518
+
418
519
  ### Layouts
419
520
 
420
521
  Layouts are created with a special `_layout.tsx` file name and wrap the entire route and its descendents. They must accept a `children` prop of type `ReactNode`. While not required, you will typically want at least a root layout.
@@ -513,6 +614,113 @@ export const getConfig = async () => {
513
614
  };
514
615
  ```
515
616
 
617
+ ### Slices
618
+
619
+ Slices are reusable components that are defined in the `src/pages/_slices` directory. They allow you to compose pages by assembling components like normal React components while specifying alternate rendering patterns.
620
+
621
+ #### Creating slices
622
+
623
+ Slices are created by placing files in the `src/pages/_slices` directory. The slice ID corresponds to the filename, and nested slices use the full path as the ID.
624
+
625
+ ```
626
+ src/pages
627
+ ├── _slices
628
+ │ ├── one.tsx
629
+ │ ├── two.tsx
630
+ │ └── nested
631
+ │ └── three.tsx
632
+ └── some-page.tsx
633
+ ```
634
+
635
+ Each slice file exports a default React component and a `getConfig` function that specifies the render method.
636
+
637
+ ```tsx
638
+ // ./src/pages/_slices/one.tsx
639
+
640
+ // Create slice component
641
+ export default function SliceOne() {
642
+ return <p>🍕</p>;
643
+ }
644
+
645
+ export const getConfig = () => {
646
+ return {
647
+ render: 'static', // default is 'static'
648
+ };
649
+ };
650
+ ```
651
+
652
+ ```tsx
653
+ // ./src/pages/_slices/nested/three.tsx
654
+
655
+ // Create nested slice component
656
+ export default function SliceThree() {
657
+ return <p>🍰</p>;
658
+ }
659
+
660
+ export const getConfig = () => {
661
+ return {
662
+ render: 'dynamic',
663
+ };
664
+ };
665
+ ```
666
+
667
+ #### Using slices
668
+
669
+ Slices are used in pages and layouts by importing the `Slice` component from Waku and specifying the slice ID. The `slices` array in the page's `getConfig` must include all slice IDs used on that page.
670
+
671
+ ```tsx
672
+ // ./src/pages/some-page.tsx
673
+ import { Slice } from 'waku';
674
+
675
+ // Create page with slices
676
+ export default function SomePage() {
677
+ return (
678
+ <div>
679
+ <Slice id="one" />
680
+ <Slice id="two" />
681
+ <Slice id="nested/three" />
682
+ </div>
683
+ );
684
+ }
685
+
686
+ export const getConfig = () => {
687
+ return {
688
+ render: 'static',
689
+ slices: ['one', 'two', 'nested/three'],
690
+ };
691
+ };
692
+ ```
693
+
694
+ #### Lazy slices
695
+
696
+ Lazy slices allow components to be requested independently from the page they are used on, similar to Astro's server islands feature. This is useful for components that will be dynamically rendered on otherwise static pages.
697
+
698
+ Lazy slices are marked with the `lazy` prop and can include a `fallback` component to display while loading.
699
+
700
+ ```tsx
701
+ // ./src/pages/some-page.tsx
702
+ import { Slice } from 'waku';
703
+
704
+ // Create page with lazy slice
705
+ export default function SomePage() {
706
+ return (
707
+ <div>
708
+ <Slice id="one" />
709
+ <Slice id="two" lazy fallback={<p>Two is loading...</p>} />
710
+ </div>
711
+ );
712
+ }
713
+
714
+ export const getConfig = () => {
715
+ return {
716
+ render: 'static',
717
+ slices: ['one'], // Note: 'two' is lazy, so it is not included
718
+ };
719
+ };
720
+ ```
721
+
722
+ This allows you to have a `dynamic` slice component while keeping the rest of the page static.
723
+
516
724
  ## Navigation
517
725
 
518
726
  ### Link
@@ -673,7 +881,7 @@ export const getConfig = async () => {
673
881
 
674
882
  ### Global styles
675
883
 
676
- Install any required dev dependencies (e.g., `npm i -D tailwindcss @tailwindcss/postcss postcss`) and set up any required configuration (e.g., `postcss.config.js`). Then create your global stylesheet (e.g., `./src/styles.css`) and import it into the root layout.
884
+ Install any required dev dependencies (e.g., `npm i -D tailwindcss @tailwindcss/vite`) and set up any required configuration (e.g., `waku.config.ts`). Then create your global stylesheet (e.g., `./src/styles.css`) and import it into the root layout.
677
885
 
678
886
  ```tsx
679
887
  // ./src/pages/_layout.tsx
@@ -696,12 +904,15 @@ export const getConfig = async () => {
696
904
  ```
697
905
 
698
906
  ```js
699
- // ./postcss.config.js
700
- export default {
701
- plugins: {
702
- '@tailwindcss/postcss': {},
907
+ // ./waku.config.ts
908
+ import { defineConfig } from 'waku/config';
909
+ import tailwindcss from '@tailwindcss/vite';
910
+
911
+ export default defineConfig({
912
+ vite: {
913
+ plugins: [tailwindcss()],
703
914
  },
704
- };
915
+ });
705
916
  ```
706
917
 
707
918
  ## Static assets
@@ -1,50 +1,23 @@
1
- const setContextStorage = (storage)=>{
2
- globalThis.__WAKU_MIDDLEWARE_CONTEXT_STORAGE__ ||= storage;
3
- };
4
- const getContextStorage = ()=>{
5
- return globalThis.__WAKU_MIDDLEWARE_CONTEXT_STORAGE__;
6
- };
7
- try {
8
- const { AsyncLocalStorage } = await import('node:async_hooks');
9
- setContextStorage(new AsyncLocalStorage());
10
- } catch {
11
- console.warn('AsyncLocalStorage is not available');
12
- }
13
- let previousContext;
14
- let currentContext;
15
- const runWithContext = (context, fn)=>{
16
- const contextStorage = getContextStorage();
17
- if (contextStorage) {
18
- return contextStorage.run(context, fn);
19
- }
20
- previousContext = currentContext;
21
- currentContext = context;
22
- try {
23
- return fn();
24
- } finally{
25
- currentContext = previousContext;
26
- }
27
- };
1
+ import { AsyncLocalStorage } from 'node:async_hooks';
2
+ const contextStorage = new AsyncLocalStorage();
28
3
  export const context = ()=>{
29
4
  return async (ctx, next)=>{
30
5
  const context = {
31
6
  req: ctx.req,
32
7
  data: ctx.data
33
8
  };
34
- return runWithContext(context, next);
9
+ return contextStorage.run(context, next);
35
10
  };
36
11
  };
37
12
  export function getContext() {
38
- const contextStorage = getContextStorage();
39
- const context = contextStorage?.getStore() ?? currentContext;
13
+ const context = contextStorage.getStore();
40
14
  if (!context) {
41
15
  throw new Error('Context is not available. Make sure to use the context middleware. For now, Context is not available during the build time.');
42
16
  }
43
17
  return context;
44
18
  }
45
19
  export function getContextData() {
46
- const contextStorage = getContextStorage();
47
- const context = contextStorage?.getStore() ?? currentContext;
20
+ const context = contextStorage.getStore();
48
21
  if (!context) {
49
22
  return {};
50
23
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/lib/middleware/context.ts"],"sourcesContent":["import type { AsyncLocalStorage as AsyncLocalStorageType } from 'node:async_hooks';\n\nimport type { Middleware } from './types.js';\n\ntype Context = {\n readonly req: Request;\n readonly data: Record<string, unknown>;\n};\n\nconst setContextStorage = (storage: AsyncLocalStorageType<Context>) => {\n (globalThis as any).__WAKU_MIDDLEWARE_CONTEXT_STORAGE__ ||= storage;\n};\n\nconst getContextStorage = (): AsyncLocalStorageType<Context> => {\n return (globalThis as any).__WAKU_MIDDLEWARE_CONTEXT_STORAGE__;\n};\n\ntry {\n const { AsyncLocalStorage } = await import('node:async_hooks');\n setContextStorage(new AsyncLocalStorage());\n} catch {\n console.warn('AsyncLocalStorage is not available');\n}\n\nlet previousContext: Context | undefined;\nlet currentContext: Context | undefined;\n\nconst runWithContext = <T>(context: Context, fn: () => T): T => {\n const contextStorage = getContextStorage();\n if (contextStorage) {\n return contextStorage.run(context, fn);\n }\n previousContext = currentContext;\n currentContext = context;\n try {\n return fn();\n } finally {\n currentContext = previousContext;\n }\n};\n\nexport const context: Middleware = () => {\n return async (ctx, next) => {\n const context: Context = {\n req: ctx.req,\n data: ctx.data,\n };\n return runWithContext(context, next);\n };\n};\n\nexport function getContext() {\n const contextStorage = getContextStorage();\n const context = contextStorage?.getStore() ?? currentContext;\n if (!context) {\n throw new Error(\n 'Context is not available. Make sure to use the context middleware. For now, Context is not available during the build time.',\n );\n }\n return context;\n}\n\nexport function getContextData(): Record<string, unknown> {\n const contextStorage = getContextStorage();\n const context = contextStorage?.getStore() ?? currentContext;\n if (!context) {\n return {};\n }\n return context.data;\n}\n"],"names":["setContextStorage","storage","globalThis","__WAKU_MIDDLEWARE_CONTEXT_STORAGE__","getContextStorage","AsyncLocalStorage","console","warn","previousContext","currentContext","runWithContext","context","fn","contextStorage","run","ctx","next","req","data","getContext","getStore","Error","getContextData"],"mappings":"AASA,MAAMA,oBAAoB,CAACC;IACxBC,WAAmBC,mCAAmC,KAAKF;AAC9D;AAEA,MAAMG,oBAAoB;IACxB,OAAO,AAACF,WAAmBC,mCAAmC;AAChE;AAEA,IAAI;IACF,MAAM,EAAEE,iBAAiB,EAAE,GAAG,MAAM,MAAM,CAAC;IAC3CL,kBAAkB,IAAIK;AACxB,EAAE,OAAM;IACNC,QAAQC,IAAI,CAAC;AACf;AAEA,IAAIC;AACJ,IAAIC;AAEJ,MAAMC,iBAAiB,CAAIC,SAAkBC;IAC3C,MAAMC,iBAAiBT;IACvB,IAAIS,gBAAgB;QAClB,OAAOA,eAAeC,GAAG,CAACH,SAASC;IACrC;IACAJ,kBAAkBC;IAClBA,iBAAiBE;IACjB,IAAI;QACF,OAAOC;IACT,SAAU;QACRH,iBAAiBD;IACnB;AACF;AAEA,OAAO,MAAMG,UAAsB;IACjC,OAAO,OAAOI,KAAKC;QACjB,MAAML,UAAmB;YACvBM,KAAKF,IAAIE,GAAG;YACZC,MAAMH,IAAIG,IAAI;QAChB;QACA,OAAOR,eAAeC,SAASK;IACjC;AACF,EAAE;AAEF,OAAO,SAASG;IACd,MAAMN,iBAAiBT;IACvB,MAAMO,UAAUE,gBAAgBO,cAAcX;IAC9C,IAAI,CAACE,SAAS;QACZ,MAAM,IAAIU,MACR;IAEJ;IACA,OAAOV;AACT;AAEA,OAAO,SAASW;IACd,MAAMT,iBAAiBT;IACvB,MAAMO,UAAUE,gBAAgBO,cAAcX;IAC9C,IAAI,CAACE,SAAS;QACZ,OAAO,CAAC;IACV;IACA,OAAOA,QAAQO,IAAI;AACrB"}
1
+ {"version":3,"sources":["../../../src/lib/middleware/context.ts"],"sourcesContent":["import { AsyncLocalStorage } from 'node:async_hooks';\nimport type { Middleware } from './types.js';\n\ntype Context = {\n readonly req: Request;\n readonly data: Record<string, unknown>;\n};\n\nconst contextStorage = new AsyncLocalStorage<Context>();\n\nexport const context: Middleware = () => {\n return async (ctx, next) => {\n const context: Context = {\n req: ctx.req,\n data: ctx.data,\n };\n return contextStorage.run(context, next);\n };\n};\n\nexport function getContext() {\n const context = contextStorage.getStore();\n if (!context) {\n throw new Error(\n 'Context is not available. Make sure to use the context middleware. For now, Context is not available during the build time.',\n );\n }\n return context;\n}\n\nexport function getContextData(): Record<string, unknown> {\n const context = contextStorage.getStore();\n if (!context) {\n return {};\n }\n return context.data;\n}\n"],"names":["AsyncLocalStorage","contextStorage","context","ctx","next","req","data","run","getContext","getStore","Error","getContextData"],"mappings":"AAAA,SAASA,iBAAiB,QAAQ,mBAAmB;AAQrD,MAAMC,iBAAiB,IAAID;AAE3B,OAAO,MAAME,UAAsB;IACjC,OAAO,OAAOC,KAAKC;QACjB,MAAMF,UAAmB;YACvBG,KAAKF,IAAIE,GAAG;YACZC,MAAMH,IAAIG,IAAI;QAChB;QACA,OAAOL,eAAeM,GAAG,CAACL,SAASE;IACrC;AACF,EAAE;AAEF,OAAO,SAASI;IACd,MAAMN,UAAUD,eAAeQ,QAAQ;IACvC,IAAI,CAACP,SAAS;QACZ,MAAM,IAAIQ,MACR;IAEJ;IACA,OAAOR;AACT;AAEA,OAAO,SAASS;IACd,MAAMT,UAAUD,eAAeQ,QAAQ;IACvC,IAAI,CAACP,SAAS;QACZ,OAAO,CAAC;IACV;IACA,OAAOA,QAAQI,IAAI;AACrB"}
@@ -2,5 +2,3 @@ export declare const encodeRscPath: (rscPath: string) => string;
2
2
  export declare const decodeRscPath: (rscPath: string) => string;
3
3
  export declare const encodeFuncId: (funcId: string) => string;
4
4
  export declare const decodeFuncId: (encoded: string) => string | null;
5
- export declare const generatePrefetchCode: (basePrefix: string, rscPaths: Iterable<string>, moduleIds: Iterable<string>) => string;
6
- export declare const deepFreeze: (x: unknown) => void;
@@ -58,31 +58,5 @@ export const decodeFuncId = (encoded)=>{
58
58
  }
59
59
  return file + '#' + name;
60
60
  };
61
- export const generatePrefetchCode = (basePrefix, rscPaths, moduleIds)=>{
62
- const rscPathArray = Array.from(rscPaths);
63
- let code = '';
64
- if (rscPathArray.length) {
65
- code += `
66
- globalThis.__WAKU_PREFETCHED__ = {
67
- ${rscPathArray.map((rscPath)=>{
68
- const url = basePrefix + encodeRscPath(rscPath);
69
- return ` '${rscPath}': fetch('${url}'),`;
70
- }).join('\n')}
71
- };`;
72
- }
73
- for (const moduleId of moduleIds){
74
- code += `
75
- import('${moduleId}');`;
76
- }
77
- return code;
78
- };
79
- export const deepFreeze = (x)=>{
80
- if (typeof x === 'object' && x !== null) {
81
- Object.freeze(x);
82
- for (const value of Object.values(x)){
83
- deepFreeze(value);
84
- }
85
- }
86
- };
87
61
 
88
62
  //# sourceMappingURL=utils.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/lib/renderers/utils.ts"],"sourcesContent":["// This file should not include Node specific code.\n\nexport const encodeRscPath = (rscPath: string) => {\n if (rscPath.startsWith('_')) {\n throw new Error('rscPath must not start with `_`: ' + rscPath);\n }\n if (rscPath.endsWith('_')) {\n throw new Error('rscPath must not end with `_`: ' + rscPath);\n }\n if (rscPath === '') {\n rscPath = '_';\n }\n if (rscPath.startsWith('/')) {\n rscPath = '_' + rscPath;\n }\n if (rscPath.endsWith('/')) {\n rscPath += '_';\n }\n return rscPath + '.txt';\n};\n\nexport const decodeRscPath = (rscPath: string) => {\n if (!rscPath.endsWith('.txt')) {\n const err = new Error('Invalid encoded rscPath');\n (err as any).statusCode = 400;\n throw err;\n }\n rscPath = rscPath.slice(0, -'.txt'.length);\n if (rscPath.startsWith('_')) {\n rscPath = rscPath.slice(1);\n }\n if (rscPath.endsWith('_')) {\n rscPath = rscPath.slice(0, -1);\n }\n return rscPath;\n};\n\nconst FUNC_PREFIX = 'F/';\n\nexport const encodeFuncId = (funcId: string) => {\n const [file, name] = funcId.split('#') as [string, string];\n if (name.includes('/')) {\n throw new Error('Function name must not include `/`: ' + name);\n }\n if (file.startsWith('_')) {\n throw new Error('File must not start with `_`: ' + file);\n }\n if (file.startsWith('/')) {\n return FUNC_PREFIX + '_' + file + '/' + name;\n }\n return FUNC_PREFIX + file + '/' + name;\n};\n\nexport const decodeFuncId = (encoded: string) => {\n if (!encoded.startsWith(FUNC_PREFIX)) {\n return null;\n }\n const index = encoded.lastIndexOf('/');\n const file = encoded.slice(FUNC_PREFIX.length, index);\n const name = encoded.slice(index + 1);\n if (file.startsWith('_')) {\n return file.slice(1) + '#' + name;\n }\n return file + '#' + name;\n};\n\nexport const generatePrefetchCode = (\n basePrefix: string,\n rscPaths: Iterable<string>,\n moduleIds: Iterable<string>,\n) => {\n const rscPathArray = Array.from(rscPaths);\n let code = '';\n if (rscPathArray.length) {\n code += `\nglobalThis.__WAKU_PREFETCHED__ = {\n${rscPathArray\n .map((rscPath) => {\n const url = basePrefix + encodeRscPath(rscPath);\n return ` '${rscPath}': fetch('${url}'),`;\n })\n .join('\\n')}\n};`;\n }\n for (const moduleId of moduleIds) {\n code += `\nimport('${moduleId}');`;\n }\n return code;\n};\n\nexport const deepFreeze = (x: unknown): void => {\n if (typeof x === 'object' && x !== null) {\n Object.freeze(x);\n for (const value of Object.values(x)) {\n deepFreeze(value);\n }\n }\n};\n"],"names":["encodeRscPath","rscPath","startsWith","Error","endsWith","decodeRscPath","err","statusCode","slice","length","FUNC_PREFIX","encodeFuncId","funcId","file","name","split","includes","decodeFuncId","encoded","index","lastIndexOf","generatePrefetchCode","basePrefix","rscPaths","moduleIds","rscPathArray","Array","from","code","map","url","join","moduleId","deepFreeze","x","Object","freeze","value","values"],"mappings":"AAAA,mDAAmD;AAEnD,OAAO,MAAMA,gBAAgB,CAACC;IAC5B,IAAIA,QAAQC,UAAU,CAAC,MAAM;QAC3B,MAAM,IAAIC,MAAM,sCAAsCF;IACxD;IACA,IAAIA,QAAQG,QAAQ,CAAC,MAAM;QACzB,MAAM,IAAID,MAAM,oCAAoCF;IACtD;IACA,IAAIA,YAAY,IAAI;QAClBA,UAAU;IACZ;IACA,IAAIA,QAAQC,UAAU,CAAC,MAAM;QAC3BD,UAAU,MAAMA;IAClB;IACA,IAAIA,QAAQG,QAAQ,CAAC,MAAM;QACzBH,WAAW;IACb;IACA,OAAOA,UAAU;AACnB,EAAE;AAEF,OAAO,MAAMI,gBAAgB,CAACJ;IAC5B,IAAI,CAACA,QAAQG,QAAQ,CAAC,SAAS;QAC7B,MAAME,MAAM,IAAIH,MAAM;QACrBG,IAAYC,UAAU,GAAG;QAC1B,MAAMD;IACR;IACAL,UAAUA,QAAQO,KAAK,CAAC,GAAG,CAAC,OAAOC,MAAM;IACzC,IAAIR,QAAQC,UAAU,CAAC,MAAM;QAC3BD,UAAUA,QAAQO,KAAK,CAAC;IAC1B;IACA,IAAIP,QAAQG,QAAQ,CAAC,MAAM;QACzBH,UAAUA,QAAQO,KAAK,CAAC,GAAG,CAAC;IAC9B;IACA,OAAOP;AACT,EAAE;AAEF,MAAMS,cAAc;AAEpB,OAAO,MAAMC,eAAe,CAACC;IAC3B,MAAM,CAACC,MAAMC,KAAK,GAAGF,OAAOG,KAAK,CAAC;IAClC,IAAID,KAAKE,QAAQ,CAAC,MAAM;QACtB,MAAM,IAAIb,MAAM,yCAAyCW;IAC3D;IACA,IAAID,KAAKX,UAAU,CAAC,MAAM;QACxB,MAAM,IAAIC,MAAM,mCAAmCU;IACrD;IACA,IAAIA,KAAKX,UAAU,CAAC,MAAM;QACxB,OAAOQ,cAAc,MAAMG,OAAO,MAAMC;IAC1C;IACA,OAAOJ,cAAcG,OAAO,MAAMC;AACpC,EAAE;AAEF,OAAO,MAAMG,eAAe,CAACC;IAC3B,IAAI,CAACA,QAAQhB,UAAU,CAACQ,cAAc;QACpC,OAAO;IACT;IACA,MAAMS,QAAQD,QAAQE,WAAW,CAAC;IAClC,MAAMP,OAAOK,QAAQV,KAAK,CAACE,YAAYD,MAAM,EAAEU;IAC/C,MAAML,OAAOI,QAAQV,KAAK,CAACW,QAAQ;IACnC,IAAIN,KAAKX,UAAU,CAAC,MAAM;QACxB,OAAOW,KAAKL,KAAK,CAAC,KAAK,MAAMM;IAC/B;IACA,OAAOD,OAAO,MAAMC;AACtB,EAAE;AAEF,OAAO,MAAMO,uBAAuB,CAClCC,YACAC,UACAC;IAEA,MAAMC,eAAeC,MAAMC,IAAI,CAACJ;IAChC,IAAIK,OAAO;IACX,IAAIH,aAAahB,MAAM,EAAE;QACvBmB,QAAQ,CAAC;;AAEb,EAAEH,aACCI,GAAG,CAAC,CAAC5B;YACJ,MAAM6B,MAAMR,aAAatB,cAAcC;YACvC,OAAO,CAAC,GAAG,EAAEA,QAAQ,UAAU,EAAE6B,IAAI,GAAG,CAAC;QAC3C,GACCC,IAAI,CAAC,MAAM;EACZ,CAAC;IACD;IACA,KAAK,MAAMC,YAAYR,UAAW;QAChCI,QAAQ,CAAC;QACL,EAAEI,SAAS,GAAG,CAAC;IACrB;IACA,OAAOJ;AACT,EAAE;AAEF,OAAO,MAAMK,aAAa,CAACC;IACzB,IAAI,OAAOA,MAAM,YAAYA,MAAM,MAAM;QACvCC,OAAOC,MAAM,CAACF;QACd,KAAK,MAAMG,SAASF,OAAOG,MAAM,CAACJ,GAAI;YACpCD,WAAWI;QACb;IACF;AACF,EAAE"}
1
+ {"version":3,"sources":["../../../src/lib/renderers/utils.ts"],"sourcesContent":["// This file should not include Node specific code.\n\nexport const encodeRscPath = (rscPath: string) => {\n if (rscPath.startsWith('_')) {\n throw new Error('rscPath must not start with `_`: ' + rscPath);\n }\n if (rscPath.endsWith('_')) {\n throw new Error('rscPath must not end with `_`: ' + rscPath);\n }\n if (rscPath === '') {\n rscPath = '_';\n }\n if (rscPath.startsWith('/')) {\n rscPath = '_' + rscPath;\n }\n if (rscPath.endsWith('/')) {\n rscPath += '_';\n }\n return rscPath + '.txt';\n};\n\nexport const decodeRscPath = (rscPath: string) => {\n if (!rscPath.endsWith('.txt')) {\n const err = new Error('Invalid encoded rscPath');\n (err as any).statusCode = 400;\n throw err;\n }\n rscPath = rscPath.slice(0, -'.txt'.length);\n if (rscPath.startsWith('_')) {\n rscPath = rscPath.slice(1);\n }\n if (rscPath.endsWith('_')) {\n rscPath = rscPath.slice(0, -1);\n }\n return rscPath;\n};\n\nconst FUNC_PREFIX = 'F/';\n\nexport const encodeFuncId = (funcId: string) => {\n const [file, name] = funcId.split('#') as [string, string];\n if (name.includes('/')) {\n throw new Error('Function name must not include `/`: ' + name);\n }\n if (file.startsWith('_')) {\n throw new Error('File must not start with `_`: ' + file);\n }\n if (file.startsWith('/')) {\n return FUNC_PREFIX + '_' + file + '/' + name;\n }\n return FUNC_PREFIX + file + '/' + name;\n};\n\nexport const decodeFuncId = (encoded: string) => {\n if (!encoded.startsWith(FUNC_PREFIX)) {\n return null;\n }\n const index = encoded.lastIndexOf('/');\n const file = encoded.slice(FUNC_PREFIX.length, index);\n const name = encoded.slice(index + 1);\n if (file.startsWith('_')) {\n return file.slice(1) + '#' + name;\n }\n return file + '#' + name;\n};\n"],"names":["encodeRscPath","rscPath","startsWith","Error","endsWith","decodeRscPath","err","statusCode","slice","length","FUNC_PREFIX","encodeFuncId","funcId","file","name","split","includes","decodeFuncId","encoded","index","lastIndexOf"],"mappings":"AAAA,mDAAmD;AAEnD,OAAO,MAAMA,gBAAgB,CAACC;IAC5B,IAAIA,QAAQC,UAAU,CAAC,MAAM;QAC3B,MAAM,IAAIC,MAAM,sCAAsCF;IACxD;IACA,IAAIA,QAAQG,QAAQ,CAAC,MAAM;QACzB,MAAM,IAAID,MAAM,oCAAoCF;IACtD;IACA,IAAIA,YAAY,IAAI;QAClBA,UAAU;IACZ;IACA,IAAIA,QAAQC,UAAU,CAAC,MAAM;QAC3BD,UAAU,MAAMA;IAClB;IACA,IAAIA,QAAQG,QAAQ,CAAC,MAAM;QACzBH,WAAW;IACb;IACA,OAAOA,UAAU;AACnB,EAAE;AAEF,OAAO,MAAMI,gBAAgB,CAACJ;IAC5B,IAAI,CAACA,QAAQG,QAAQ,CAAC,SAAS;QAC7B,MAAME,MAAM,IAAIH,MAAM;QACrBG,IAAYC,UAAU,GAAG;QAC1B,MAAMD;IACR;IACAL,UAAUA,QAAQO,KAAK,CAAC,GAAG,CAAC,OAAOC,MAAM;IACzC,IAAIR,QAAQC,UAAU,CAAC,MAAM;QAC3BD,UAAUA,QAAQO,KAAK,CAAC;IAC1B;IACA,IAAIP,QAAQG,QAAQ,CAAC,MAAM;QACzBH,UAAUA,QAAQO,KAAK,CAAC,GAAG,CAAC;IAC9B;IACA,OAAOP;AACT,EAAE;AAEF,MAAMS,cAAc;AAEpB,OAAO,MAAMC,eAAe,CAACC;IAC3B,MAAM,CAACC,MAAMC,KAAK,GAAGF,OAAOG,KAAK,CAAC;IAClC,IAAID,KAAKE,QAAQ,CAAC,MAAM;QACtB,MAAM,IAAIb,MAAM,yCAAyCW;IAC3D;IACA,IAAID,KAAKX,UAAU,CAAC,MAAM;QACxB,MAAM,IAAIC,MAAM,mCAAmCU;IACrD;IACA,IAAIA,KAAKX,UAAU,CAAC,MAAM;QACxB,OAAOQ,cAAc,MAAMG,OAAO,MAAMC;IAC1C;IACA,OAAOJ,cAAcG,OAAO,MAAMC;AACpC,EAAE;AAEF,OAAO,MAAMG,eAAe,CAACC;IAC3B,IAAI,CAACA,QAAQhB,UAAU,CAACQ,cAAc;QACpC,OAAO;IACT;IACA,MAAMS,QAAQD,QAAQE,WAAW,CAAC;IAClC,MAAMP,OAAOK,QAAQV,KAAK,CAACE,YAAYD,MAAM,EAAEU;IAC/C,MAAML,OAAOI,QAAQV,KAAK,CAACW,QAAQ;IACnC,IAAIN,KAAKX,UAAU,CAAC,MAAM;QACxB,OAAOW,KAAKL,KAAK,CAAC,KAAK,MAAMM;IAC/B;IACA,OAAOD,OAAO,MAAMC;AACtB,EAAE"}
@@ -1,3 +1 @@
1
- export declare const concatUint8Arrays: (arrs: Uint8Array[]) => Uint8Array;
2
- export declare const streamToString: (stream: ReadableStream) => Promise<string>;
3
1
  export declare const stringToStream: (str: string) => ReadableStream;
@@ -1,33 +1,4 @@
1
1
  // Utility functions for web streams (not Node.js streams)
2
- export const concatUint8Arrays = (arrs)=>{
3
- const len = arrs.reduce((acc, arr)=>acc + arr.length, 0);
4
- const array = new Uint8Array(len);
5
- let offset = 0;
6
- for (const arr of arrs){
7
- array.set(arr, offset);
8
- offset += arr.length;
9
- }
10
- return array;
11
- };
12
- export const streamToString = async (stream)=>{
13
- const decoder = new TextDecoder();
14
- const reader = stream.getReader();
15
- const outs = [];
16
- let result;
17
- do {
18
- result = await reader.read();
19
- if (result.value) {
20
- if (!(result.value instanceof Uint8Array)) {
21
- throw new Error('Unexepected buffer type');
22
- }
23
- outs.push(decoder.decode(result.value, {
24
- stream: true
25
- }));
26
- }
27
- }while (!result.done)
28
- outs.push(decoder.decode());
29
- return outs.join('');
30
- };
31
2
  export const stringToStream = (str)=>{
32
3
  const encoder = new TextEncoder();
33
4
  return new ReadableStream({
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/lib/utils/stream.ts"],"sourcesContent":["// Utility functions for web streams (not Node.js streams)\n\nexport const concatUint8Arrays = (arrs: Uint8Array[]): Uint8Array => {\n const len = arrs.reduce((acc, arr) => acc + arr.length, 0);\n const array = new Uint8Array(len);\n let offset = 0;\n for (const arr of arrs) {\n array.set(arr, offset);\n offset += arr.length;\n }\n return array;\n};\n\nexport const streamToString = async (\n stream: ReadableStream,\n): Promise<string> => {\n const decoder = new TextDecoder();\n const reader = stream.getReader();\n const outs: string[] = [];\n let result: ReadableStreamReadResult<unknown>;\n do {\n result = await reader.read();\n if (result.value) {\n if (!(result.value instanceof Uint8Array)) {\n throw new Error('Unexepected buffer type');\n }\n outs.push(decoder.decode(result.value, { stream: true }));\n }\n } while (!result.done);\n outs.push(decoder.decode());\n return outs.join('');\n};\n\nexport const stringToStream = (str: string): ReadableStream => {\n const encoder = new TextEncoder();\n return new ReadableStream({\n start(controller) {\n controller.enqueue(encoder.encode(str));\n controller.close();\n },\n });\n};\n"],"names":["concatUint8Arrays","arrs","len","reduce","acc","arr","length","array","Uint8Array","offset","set","streamToString","stream","decoder","TextDecoder","reader","getReader","outs","result","read","value","Error","push","decode","done","join","stringToStream","str","encoder","TextEncoder","ReadableStream","start","controller","enqueue","encode","close"],"mappings":"AAAA,0DAA0D;AAE1D,OAAO,MAAMA,oBAAoB,CAACC;IAChC,MAAMC,MAAMD,KAAKE,MAAM,CAAC,CAACC,KAAKC,MAAQD,MAAMC,IAAIC,MAAM,EAAE;IACxD,MAAMC,QAAQ,IAAIC,WAAWN;IAC7B,IAAIO,SAAS;IACb,KAAK,MAAMJ,OAAOJ,KAAM;QACtBM,MAAMG,GAAG,CAACL,KAAKI;QACfA,UAAUJ,IAAIC,MAAM;IACtB;IACA,OAAOC;AACT,EAAE;AAEF,OAAO,MAAMI,iBAAiB,OAC5BC;IAEA,MAAMC,UAAU,IAAIC;IACpB,MAAMC,SAASH,OAAOI,SAAS;IAC/B,MAAMC,OAAiB,EAAE;IACzB,IAAIC;IACJ,GAAG;QACDA,SAAS,MAAMH,OAAOI,IAAI;QAC1B,IAAID,OAAOE,KAAK,EAAE;YAChB,IAAI,CAAEF,CAAAA,OAAOE,KAAK,YAAYZ,UAAS,GAAI;gBACzC,MAAM,IAAIa,MAAM;YAClB;YACAJ,KAAKK,IAAI,CAACT,QAAQU,MAAM,CAACL,OAAOE,KAAK,EAAE;gBAAER,QAAQ;YAAK;QACxD;IACF,QAAS,CAACM,OAAOM,IAAI,CAAE;IACvBP,KAAKK,IAAI,CAACT,QAAQU,MAAM;IACxB,OAAON,KAAKQ,IAAI,CAAC;AACnB,EAAE;AAEF,OAAO,MAAMC,iBAAiB,CAACC;IAC7B,MAAMC,UAAU,IAAIC;IACpB,OAAO,IAAIC,eAAe;QACxBC,OAAMC,UAAU;YACdA,WAAWC,OAAO,CAACL,QAAQM,MAAM,CAACP;YAClCK,WAAWG,KAAK;QAClB;IACF;AACF,EAAE"}
1
+ {"version":3,"sources":["../../../src/lib/utils/stream.ts"],"sourcesContent":["// Utility functions for web streams (not Node.js streams)\n\nexport const stringToStream = (str: string): ReadableStream => {\n const encoder = new TextEncoder();\n return new ReadableStream({\n start(controller) {\n controller.enqueue(encoder.encode(str));\n controller.close();\n },\n });\n};\n"],"names":["stringToStream","str","encoder","TextEncoder","ReadableStream","start","controller","enqueue","encode","close"],"mappings":"AAAA,0DAA0D;AAE1D,OAAO,MAAMA,iBAAiB,CAACC;IAC7B,MAAMC,UAAU,IAAIC;IACpB,OAAO,IAAIC,eAAe;QACxBC,OAAMC,UAAU;YACdA,WAAWC,OAAO,CAACL,QAAQM,MAAM,CAACP;YAClCK,WAAWG,KAAK;QAClB;IACF;AACF,EAAE"}
@@ -183,6 +183,12 @@ declare module 'waku/router' {
183
183
  }
184
184
  await updateGeneratedFile();
185
185
  });
186
+ server.watcher.on('unlink', async (file)=>{
187
+ if (!outputFile || outputFile.endsWith(file)) {
188
+ return;
189
+ }
190
+ await updateGeneratedFile();
191
+ });
186
192
  void updateGeneratedFile();
187
193
  }
188
194
  };
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/lib/vite-plugins/fs-router-typegen.ts"],"sourcesContent":["import type { Plugin } from 'vite';\nimport { readdir, writeFile } from 'node:fs/promises';\nimport { existsSync, readFileSync } from 'node:fs';\nimport { SRC_SERVER_ENTRY, EXTENSIONS } from '../builder/constants.js';\nimport { joinPath } from '../utils/path.js';\nimport { isIgnoredPath } from '../utils/fs-router.js';\nimport { getGrouplessPath } from '../utils/create-pages.js';\nimport * as swc from '@swc/core';\n\nconst SRC_PAGES = 'pages';\n\n// https://tc39.es/ecma262/multipage/ecmascript-language-lexical-grammar.html#sec-names-and-keywords\n// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Lexical_grammar#identifiers\n// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Lexical_grammar#reserved_words\nexport function toIdentifier(input: string): string {\n // Strip the file extension\n let identifier = input.includes('.')\n ? input.split('.').slice(0, -1).join('.')\n : input;\n // Replace any characters besides letters, numbers, underscores, and dollar signs with underscores\n identifier = identifier.replace(/[^\\p{L}\\p{N}_$]/gu, '_');\n // Ensure it starts with a letter\n if (/^\\d/.test(identifier)) {\n identifier = '_' + identifier;\n }\n // Turn it into PascalCase\n // Since the first letter is uppercased, it will not be a reserved word\n return (\n 'File_' +\n identifier\n .split('_')\n .map((part) => {\n if (part[0] === undefined) {\n return '';\n }\n return part[0].toUpperCase() + part.slice(1);\n })\n .join('')\n );\n}\n\nexport function getImportModuleNames(filePaths: string[]): {\n [k: string]: string;\n} {\n const moduleNameCount: { [k: string]: number } = {};\n const moduleNames: { [k: string]: string } = {};\n for (const filePath of filePaths) {\n let identifier = toIdentifier(filePath);\n moduleNameCount[identifier] = (moduleNameCount[identifier] ?? -1) + 1;\n if (moduleNameCount[identifier]) {\n identifier = `${identifier}_${moduleNameCount[identifier]}`;\n }\n try {\n moduleNames[filePath.replace(/^\\//, '')] = identifier;\n } catch (e) {\n console.log(e);\n }\n }\n return moduleNames;\n}\n\nexport const fsRouterTypegenPlugin = (opts: { srcDir: string }): Plugin => {\n let entriesFilePossibilities: string[] | undefined;\n let pagesDir: string | undefined;\n let outputFile: string | undefined;\n\n return {\n name: 'vite-plugin-fs-router-typegen',\n apply: 'serve',\n async configResolved(config) {\n pagesDir = joinPath(config.root, opts.srcDir, SRC_PAGES);\n entriesFilePossibilities = EXTENSIONS.map((ext) =>\n joinPath(config.root, opts.srcDir, SRC_SERVER_ENTRY + ext),\n );\n outputFile = joinPath(config.root, opts.srcDir, 'pages.gen.ts');\n },\n configureServer(server) {\n if (\n !entriesFilePossibilities ||\n !pagesDir ||\n !outputFile ||\n entriesFilePossibilities.some((entriesFile) =>\n existsSync(entriesFile),\n ) ||\n !existsSync(pagesDir)\n ) {\n return;\n }\n\n // Recursively collect `.tsx` files in the given directory\n const collectFiles = async (\n dir: string,\n files: string[] = [],\n ): Promise<string[]> => {\n // TODO revisit recursive option for readdir once more stable\n // https://nodejs.org/docs/latest-v20.x/api/fs.html#direntparentpath\n const entries = await readdir(dir, { withFileTypes: true });\n for (const entry of entries) {\n const fullPath = joinPath(dir, entry.name);\n if (entry.isDirectory()) {\n await collectFiles(fullPath, files);\n } else {\n if (entry.name.endsWith('.tsx')) {\n files.push(pagesDir ? fullPath.slice(pagesDir.length) : fullPath);\n }\n }\n }\n return files;\n };\n\n const fileExportsGetConfig = (filePath: string) => {\n if (!pagesDir) {\n return false;\n }\n const file = swc.parseSync(readFileSync(pagesDir + filePath, 'utf8'), {\n syntax: 'typescript',\n tsx: true,\n });\n\n return file.body.some((node) => {\n if (node.type === 'ExportNamedDeclaration') {\n return node.specifiers.some(\n (specifier) =>\n specifier.type === 'ExportSpecifier' &&\n !specifier.isTypeOnly &&\n ((!specifier.exported &&\n specifier.orig.value === 'getConfig') ||\n specifier.exported?.value === 'getConfig'),\n );\n }\n\n return (\n node.type === 'ExportDeclaration' &&\n ((node.declaration.type === 'VariableDeclaration' &&\n node.declaration.declarations.some(\n (decl) =>\n decl.id.type === 'Identifier' &&\n decl.id.value === 'getConfig',\n )) ||\n (node.declaration.type === 'FunctionDeclaration' &&\n node.declaration.identifier.value === 'getConfig'))\n );\n });\n };\n\n const generateFile = (filePaths: string[]): string | null => {\n const fileInfo: { path: string; src: string; hasGetConfig: boolean }[] =\n [];\n const moduleNames = getImportModuleNames(filePaths);\n\n for (const filePath of filePaths) {\n // where to import the component from\n const src = filePath.replace(/^\\//, '');\n let hasGetConfig = false;\n try {\n hasGetConfig = fileExportsGetConfig(filePath);\n } catch {\n return null;\n }\n\n if (\n filePath.endsWith('/_layout.tsx') ||\n isIgnoredPath(filePath.split('/'))\n ) {\n continue;\n } else if (filePath.endsWith('/index.tsx')) {\n const path = filePath.slice(0, -'/index.tsx'.length);\n fileInfo.push({\n path: getGrouplessPath(path) || '/',\n src,\n hasGetConfig,\n });\n } else {\n fileInfo.push({\n path: getGrouplessPath(filePath.replace('.tsx', '')),\n src,\n hasGetConfig,\n });\n }\n }\n\n let result = `// deno-fmt-ignore-file\n// biome-ignore format: generated types do not need formatting\n// prettier-ignore\nimport type { PathsForPages, GetConfigResponse } from 'waku/router';\\n\\n`;\n\n for (const file of fileInfo) {\n const moduleName = moduleNames[file.src];\n if (file.hasGetConfig) {\n result += `// prettier-ignore\\nimport type { getConfig as ${moduleName}_getConfig } from './${SRC_PAGES}/${file.src.replace('.tsx', '')}';\\n`;\n }\n }\n\n result += `\\n// prettier-ignore\\ntype Page =\\n`;\n\n for (const file of fileInfo) {\n const moduleName = moduleNames[file.src];\n if (file.hasGetConfig) {\n result += `| ({ path: '${file.path}' } & GetConfigResponse<typeof ${moduleName}_getConfig>)\\n`;\n } else {\n result += `| { path: '${file.path}'; render: 'dynamic' }\\n`;\n }\n }\n\n result =\n result.slice(0, -1) +\n `;\n\n// prettier-ignore\ndeclare module 'waku/router' {\n interface RouteConfig {\n paths: PathsForPages<Page>;\n }\n interface CreatePagesConfig {\n pages: Page;\n }\n}\n`;\n\n return result;\n };\n\n const updateGeneratedFile = async () => {\n if (!pagesDir || !outputFile) {\n return;\n }\n const files = await collectFiles(pagesDir);\n if (!files.length) {\n return;\n }\n const generation = generateFile(files);\n if (!generation) {\n // skip failures\n return;\n }\n await writeFile(outputFile, generation, 'utf-8');\n };\n\n server.watcher.on('change', async (file) => {\n if (!outputFile || outputFile.endsWith(file)) {\n return;\n }\n\n await updateGeneratedFile();\n });\n server.watcher.on('add', async (file) => {\n if (!outputFile || outputFile.endsWith(file)) {\n return;\n }\n\n await updateGeneratedFile();\n });\n\n void updateGeneratedFile();\n },\n };\n};\n"],"names":["readdir","writeFile","existsSync","readFileSync","SRC_SERVER_ENTRY","EXTENSIONS","joinPath","isIgnoredPath","getGrouplessPath","swc","SRC_PAGES","toIdentifier","input","identifier","includes","split","slice","join","replace","test","map","part","undefined","toUpperCase","getImportModuleNames","filePaths","moduleNameCount","moduleNames","filePath","e","console","log","fsRouterTypegenPlugin","opts","entriesFilePossibilities","pagesDir","outputFile","name","apply","configResolved","config","root","srcDir","ext","configureServer","server","some","entriesFile","collectFiles","dir","files","entries","withFileTypes","entry","fullPath","isDirectory","endsWith","push","length","fileExportsGetConfig","file","parseSync","syntax","tsx","body","node","type","specifiers","specifier","isTypeOnly","exported","orig","value","declaration","declarations","decl","id","generateFile","fileInfo","src","hasGetConfig","path","result","moduleName","updateGeneratedFile","generation","watcher","on"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/lib/vite-plugins/fs-router-typegen.ts"],"sourcesContent":["import type { Plugin } from 'vite';\nimport { readdir, writeFile } from 'node:fs/promises';\nimport { existsSync, readFileSync } from 'node:fs';\nimport { SRC_SERVER_ENTRY, EXTENSIONS } from '../builder/constants.js';\nimport { joinPath } from '../utils/path.js';\nimport { isIgnoredPath } from '../utils/fs-router.js';\nimport { getGrouplessPath } from '../utils/create-pages.js';\nimport * as swc from '@swc/core';\n\nconst SRC_PAGES = 'pages';\n\n// https://tc39.es/ecma262/multipage/ecmascript-language-lexical-grammar.html#sec-names-and-keywords\n// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Lexical_grammar#identifiers\n// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Lexical_grammar#reserved_words\nexport function toIdentifier(input: string): string {\n // Strip the file extension\n let identifier = input.includes('.')\n ? input.split('.').slice(0, -1).join('.')\n : input;\n // Replace any characters besides letters, numbers, underscores, and dollar signs with underscores\n identifier = identifier.replace(/[^\\p{L}\\p{N}_$]/gu, '_');\n // Ensure it starts with a letter\n if (/^\\d/.test(identifier)) {\n identifier = '_' + identifier;\n }\n // Turn it into PascalCase\n // Since the first letter is uppercased, it will not be a reserved word\n return (\n 'File_' +\n identifier\n .split('_')\n .map((part) => {\n if (part[0] === undefined) {\n return '';\n }\n return part[0].toUpperCase() + part.slice(1);\n })\n .join('')\n );\n}\n\nexport function getImportModuleNames(filePaths: string[]): {\n [k: string]: string;\n} {\n const moduleNameCount: { [k: string]: number } = {};\n const moduleNames: { [k: string]: string } = {};\n for (const filePath of filePaths) {\n let identifier = toIdentifier(filePath);\n moduleNameCount[identifier] = (moduleNameCount[identifier] ?? -1) + 1;\n if (moduleNameCount[identifier]) {\n identifier = `${identifier}_${moduleNameCount[identifier]}`;\n }\n try {\n moduleNames[filePath.replace(/^\\//, '')] = identifier;\n } catch (e) {\n console.log(e);\n }\n }\n return moduleNames;\n}\n\nexport const fsRouterTypegenPlugin = (opts: { srcDir: string }): Plugin => {\n let entriesFilePossibilities: string[] | undefined;\n let pagesDir: string | undefined;\n let outputFile: string | undefined;\n\n return {\n name: 'vite-plugin-fs-router-typegen',\n apply: 'serve',\n async configResolved(config) {\n pagesDir = joinPath(config.root, opts.srcDir, SRC_PAGES);\n entriesFilePossibilities = EXTENSIONS.map((ext) =>\n joinPath(config.root, opts.srcDir, SRC_SERVER_ENTRY + ext),\n );\n outputFile = joinPath(config.root, opts.srcDir, 'pages.gen.ts');\n },\n configureServer(server) {\n if (\n !entriesFilePossibilities ||\n !pagesDir ||\n !outputFile ||\n entriesFilePossibilities.some((entriesFile) =>\n existsSync(entriesFile),\n ) ||\n !existsSync(pagesDir)\n ) {\n return;\n }\n\n // Recursively collect `.tsx` files in the given directory\n const collectFiles = async (\n dir: string,\n files: string[] = [],\n ): Promise<string[]> => {\n // TODO revisit recursive option for readdir once more stable\n // https://nodejs.org/docs/latest-v20.x/api/fs.html#direntparentpath\n const entries = await readdir(dir, { withFileTypes: true });\n for (const entry of entries) {\n const fullPath = joinPath(dir, entry.name);\n if (entry.isDirectory()) {\n await collectFiles(fullPath, files);\n } else {\n if (entry.name.endsWith('.tsx')) {\n files.push(pagesDir ? fullPath.slice(pagesDir.length) : fullPath);\n }\n }\n }\n return files;\n };\n\n const fileExportsGetConfig = (filePath: string) => {\n if (!pagesDir) {\n return false;\n }\n const file = swc.parseSync(readFileSync(pagesDir + filePath, 'utf8'), {\n syntax: 'typescript',\n tsx: true,\n });\n\n return file.body.some((node) => {\n if (node.type === 'ExportNamedDeclaration') {\n return node.specifiers.some(\n (specifier) =>\n specifier.type === 'ExportSpecifier' &&\n !specifier.isTypeOnly &&\n ((!specifier.exported &&\n specifier.orig.value === 'getConfig') ||\n specifier.exported?.value === 'getConfig'),\n );\n }\n\n return (\n node.type === 'ExportDeclaration' &&\n ((node.declaration.type === 'VariableDeclaration' &&\n node.declaration.declarations.some(\n (decl) =>\n decl.id.type === 'Identifier' &&\n decl.id.value === 'getConfig',\n )) ||\n (node.declaration.type === 'FunctionDeclaration' &&\n node.declaration.identifier.value === 'getConfig'))\n );\n });\n };\n\n const generateFile = (filePaths: string[]): string | null => {\n const fileInfo: { path: string; src: string; hasGetConfig: boolean }[] =\n [];\n const moduleNames = getImportModuleNames(filePaths);\n\n for (const filePath of filePaths) {\n // where to import the component from\n const src = filePath.replace(/^\\//, '');\n let hasGetConfig = false;\n try {\n hasGetConfig = fileExportsGetConfig(filePath);\n } catch {\n return null;\n }\n\n if (\n filePath.endsWith('/_layout.tsx') ||\n isIgnoredPath(filePath.split('/'))\n ) {\n continue;\n } else if (filePath.endsWith('/index.tsx')) {\n const path = filePath.slice(0, -'/index.tsx'.length);\n fileInfo.push({\n path: getGrouplessPath(path) || '/',\n src,\n hasGetConfig,\n });\n } else {\n fileInfo.push({\n path: getGrouplessPath(filePath.replace('.tsx', '')),\n src,\n hasGetConfig,\n });\n }\n }\n\n let result = `// deno-fmt-ignore-file\n// biome-ignore format: generated types do not need formatting\n// prettier-ignore\nimport type { PathsForPages, GetConfigResponse } from 'waku/router';\\n\\n`;\n\n for (const file of fileInfo) {\n const moduleName = moduleNames[file.src];\n if (file.hasGetConfig) {\n result += `// prettier-ignore\\nimport type { getConfig as ${moduleName}_getConfig } from './${SRC_PAGES}/${file.src.replace('.tsx', '')}';\\n`;\n }\n }\n\n result += `\\n// prettier-ignore\\ntype Page =\\n`;\n\n for (const file of fileInfo) {\n const moduleName = moduleNames[file.src];\n if (file.hasGetConfig) {\n result += `| ({ path: '${file.path}' } & GetConfigResponse<typeof ${moduleName}_getConfig>)\\n`;\n } else {\n result += `| { path: '${file.path}'; render: 'dynamic' }\\n`;\n }\n }\n\n result =\n result.slice(0, -1) +\n `;\n\n// prettier-ignore\ndeclare module 'waku/router' {\n interface RouteConfig {\n paths: PathsForPages<Page>;\n }\n interface CreatePagesConfig {\n pages: Page;\n }\n}\n`;\n\n return result;\n };\n\n const updateGeneratedFile = async () => {\n if (!pagesDir || !outputFile) {\n return;\n }\n const files = await collectFiles(pagesDir);\n if (!files.length) {\n return;\n }\n const generation = generateFile(files);\n if (!generation) {\n // skip failures\n return;\n }\n await writeFile(outputFile, generation, 'utf-8');\n };\n\n server.watcher.on('change', async (file) => {\n if (!outputFile || outputFile.endsWith(file)) {\n return;\n }\n\n await updateGeneratedFile();\n });\n server.watcher.on('add', async (file) => {\n if (!outputFile || outputFile.endsWith(file)) {\n return;\n }\n\n await updateGeneratedFile();\n });\n server.watcher.on('unlink', async (file) => {\n if (!outputFile || outputFile.endsWith(file)) {\n return;\n }\n\n await updateGeneratedFile();\n });\n\n void updateGeneratedFile();\n },\n };\n};\n"],"names":["readdir","writeFile","existsSync","readFileSync","SRC_SERVER_ENTRY","EXTENSIONS","joinPath","isIgnoredPath","getGrouplessPath","swc","SRC_PAGES","toIdentifier","input","identifier","includes","split","slice","join","replace","test","map","part","undefined","toUpperCase","getImportModuleNames","filePaths","moduleNameCount","moduleNames","filePath","e","console","log","fsRouterTypegenPlugin","opts","entriesFilePossibilities","pagesDir","outputFile","name","apply","configResolved","config","root","srcDir","ext","configureServer","server","some","entriesFile","collectFiles","dir","files","entries","withFileTypes","entry","fullPath","isDirectory","endsWith","push","length","fileExportsGetConfig","file","parseSync","syntax","tsx","body","node","type","specifiers","specifier","isTypeOnly","exported","orig","value","declaration","declarations","decl","id","generateFile","fileInfo","src","hasGetConfig","path","result","moduleName","updateGeneratedFile","generation","watcher","on"],"mappings":"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"}
@@ -64,7 +64,7 @@ export async function cli(cmd, flags) {
64
64
  const port = parseInt(flags.port || '8080', 10);
65
65
  const { serve } = await import('@hono/node-server');
66
66
  const distDir = rscPluginOptions.config?.distDir ?? 'dist';
67
- const entry = await import(pathToFileURL(path.resolve(distDir, 'rsc', 'index.js')).href);
67
+ const entry = await import(pathToFileURL(path.resolve(distDir, 'server', 'index.js')).href);
68
68
  await startServer(port);
69
69
  function startServer(port) {
70
70
  return new Promise((resolve, reject)=>{
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/lib/vite-rsc/cli.ts"],"sourcesContent":["import * as vite from 'vite';\nimport { rscPlugin } from './plugin.js';\nimport type { Flags, RscPluginOptions } from './plugin.js';\nimport type { Config } from '../../config.js';\nimport { existsSync } from 'node:fs';\nimport path from 'node:path';\nimport { pathToFileURL } from 'node:url';\n\nasync function loadConfig(): Promise<Config | undefined> {\n let config: Config | undefined;\n if (existsSync('waku.config.ts') || existsSync('waku.config.js')) {\n const imported = await vite.runnerImport<{ default: Config }>(\n '/waku.config',\n );\n config = imported.module.default;\n }\n return config;\n}\n\nasync function startDevServer(\n port: number,\n rscPluginOptions: RscPluginOptions,\n) {\n const server = await vite.createServer({\n configFile: false,\n plugins: [rscPlugin(rscPluginOptions)],\n server: { port },\n });\n await server.listen();\n const url = server.resolvedUrls!['local'];\n port = Number(url[0]?.match(/:(\\d+)/)?.[1]) || port;\n console.log(`ready: Listening on ${url}`);\n const watcher = server.watcher;\n watcher.on('change', handleConfigChange);\n watcher.on('unlink', handleConfigChange);\n watcher.on('add', handleConfigChange);\n\n async function handleConfigChange(changedFile: string) {\n const dirname = path.dirname(changedFile);\n const filename = path.basename(changedFile);\n if (\n dirname === process.cwd() &&\n (filename === 'waku.config.ts' || filename === 'waku.config.js')\n ) {\n console.log(`Waku configuration file changed, restarting server...`);\n await server.close();\n await startDevServer(port, {\n ...rscPluginOptions,\n config: await loadConfig(),\n });\n }\n }\n}\n\nexport async function cli(\n cmd: 'dev' | 'build' | 'start',\n flags: { port?: string } & Flags,\n) {\n // set NODE_ENV before runnerImport https://github.com/vitejs/vite/issues/20299\n process.env.NODE_ENV ??= cmd === 'dev' ? 'development' : 'production';\n\n const rscPluginOptions: RscPluginOptions = {\n flags,\n config: await loadConfig(),\n };\n\n if (cmd === 'dev') {\n const port = parseInt(flags.port || '3000', 10);\n await startDevServer(port, rscPluginOptions);\n } else if (cmd === 'build') {\n const builder = await vite.createBuilder({\n configFile: false,\n plugins: [rscPlugin(rscPluginOptions)],\n });\n await builder.buildApp();\n } else if (cmd === 'start') {\n const port = parseInt(flags.port || '8080', 10);\n const { serve } = await import('@hono/node-server');\n const distDir = rscPluginOptions.config?.distDir ?? 'dist';\n const entry: typeof import('../vite-entries/entry.server.js') =\n await import(\n pathToFileURL(path.resolve(distDir, 'rsc', 'index.js')).href\n );\n await startServer(port);\n function startServer(port: number) {\n return new Promise<void>((resolve, reject) => {\n const server = serve({ fetch: entry.default, port }, () => {\n console.log(`ready: Listening on http://localhost:${port}/`);\n resolve();\n });\n server.on('error', (err: NodeJS.ErrnoException) => {\n if (err.code === 'EADDRINUSE') {\n console.log(\n `warn: Port ${port} is in use, trying ${port + 1} instead.`,\n );\n startServer(port + 1)\n .then(resolve)\n .catch(reject);\n } else {\n console.error(`Failed to start server: ${err.message}`);\n }\n });\n });\n }\n }\n}\n"],"names":["vite","rscPlugin","existsSync","path","pathToFileURL","loadConfig","config","imported","runnerImport","module","default","startDevServer","port","rscPluginOptions","server","createServer","configFile","plugins","listen","url","resolvedUrls","Number","match","console","log","watcher","on","handleConfigChange","changedFile","dirname","filename","basename","process","cwd","close","cli","cmd","flags","env","NODE_ENV","parseInt","builder","createBuilder","buildApp","serve","distDir","entry","resolve","href","startServer","Promise","reject","fetch","err","code","then","catch","error","message"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/lib/vite-rsc/cli.ts"],"sourcesContent":["import * as vite from 'vite';\nimport { rscPlugin } from './plugin.js';\nimport type { Flags, RscPluginOptions } from './plugin.js';\nimport type { Config } from '../../config.js';\nimport { existsSync } from 'node:fs';\nimport path from 'node:path';\nimport { pathToFileURL } from 'node:url';\n\nasync function loadConfig(): Promise<Config | undefined> {\n let config: Config | undefined;\n if (existsSync('waku.config.ts') || existsSync('waku.config.js')) {\n const imported = await vite.runnerImport<{ default: Config }>(\n '/waku.config',\n );\n config = imported.module.default;\n }\n return config;\n}\n\nasync function startDevServer(\n port: number,\n rscPluginOptions: RscPluginOptions,\n) {\n const server = await vite.createServer({\n configFile: false,\n plugins: [rscPlugin(rscPluginOptions)],\n server: { port },\n });\n await server.listen();\n const url = server.resolvedUrls!['local'];\n port = Number(url[0]?.match(/:(\\d+)/)?.[1]) || port;\n console.log(`ready: Listening on ${url}`);\n const watcher = server.watcher;\n watcher.on('change', handleConfigChange);\n watcher.on('unlink', handleConfigChange);\n watcher.on('add', handleConfigChange);\n\n async function handleConfigChange(changedFile: string) {\n const dirname = path.dirname(changedFile);\n const filename = path.basename(changedFile);\n if (\n dirname === process.cwd() &&\n (filename === 'waku.config.ts' || filename === 'waku.config.js')\n ) {\n console.log(`Waku configuration file changed, restarting server...`);\n await server.close();\n await startDevServer(port, {\n ...rscPluginOptions,\n config: await loadConfig(),\n });\n }\n }\n}\n\nexport async function cli(\n cmd: 'dev' | 'build' | 'start',\n flags: { port?: string } & Flags,\n) {\n // set NODE_ENV before runnerImport https://github.com/vitejs/vite/issues/20299\n process.env.NODE_ENV ??= cmd === 'dev' ? 'development' : 'production';\n\n const rscPluginOptions: RscPluginOptions = {\n flags,\n config: await loadConfig(),\n };\n\n if (cmd === 'dev') {\n const port = parseInt(flags.port || '3000', 10);\n await startDevServer(port, rscPluginOptions);\n } else if (cmd === 'build') {\n const builder = await vite.createBuilder({\n configFile: false,\n plugins: [rscPlugin(rscPluginOptions)],\n });\n await builder.buildApp();\n } else if (cmd === 'start') {\n const port = parseInt(flags.port || '8080', 10);\n const { serve } = await import('@hono/node-server');\n const distDir = rscPluginOptions.config?.distDir ?? 'dist';\n const entry: typeof import('../vite-entries/entry.server.js') =\n await import(\n pathToFileURL(path.resolve(distDir, 'server', 'index.js')).href\n );\n await startServer(port);\n function startServer(port: number) {\n return new Promise<void>((resolve, reject) => {\n const server = serve({ fetch: entry.default, port }, () => {\n console.log(`ready: Listening on http://localhost:${port}/`);\n resolve();\n });\n server.on('error', (err: NodeJS.ErrnoException) => {\n if (err.code === 'EADDRINUSE') {\n console.log(\n `warn: Port ${port} is in use, trying ${port + 1} instead.`,\n );\n startServer(port + 1)\n .then(resolve)\n .catch(reject);\n } else {\n console.error(`Failed to start server: ${err.message}`);\n }\n });\n });\n }\n }\n}\n"],"names":["vite","rscPlugin","existsSync","path","pathToFileURL","loadConfig","config","imported","runnerImport","module","default","startDevServer","port","rscPluginOptions","server","createServer","configFile","plugins","listen","url","resolvedUrls","Number","match","console","log","watcher","on","handleConfigChange","changedFile","dirname","filename","basename","process","cwd","close","cli","cmd","flags","env","NODE_ENV","parseInt","builder","createBuilder","buildApp","serve","distDir","entry","resolve","href","startServer","Promise","reject","fetch","err","code","then","catch","error","message"],"mappings":"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"}
@@ -37,7 +37,7 @@ export function deployAwsLambdaPlugin(deployOptions) {
37
37
  };
38
38
  }
39
39
  async function build({ opts }) {
40
- writeFileSync(path.join(opts.distDir, SERVE_JS), `export { handler } from './rsc/index.js';\n`);
40
+ writeFileSync(path.join(opts.distDir, SERVE_JS), `export { handler } from './server/index.js';\n`);
41
41
  writeFileSync(path.join(opts.distDir, 'package.json'), JSON.stringify({
42
42
  type: 'module'
43
43
  }, null, 2));
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../src/lib/vite-rsc/deploy/aws-lambda/plugin.ts"],"sourcesContent":["import { type Plugin, type ResolvedConfig } from 'vite';\nimport { writeFileSync } from 'node:fs';\nimport path from 'node:path';\nimport type { Config } from '../../../../config.js';\nimport { fileURLToPath } from 'node:url';\n\nconst __dirname = fileURLToPath(new URL('.', import.meta.url));\nconst SERVER_ENTRY = path.join(__dirname, 'entry.js');\nconst SERVE_JS = 'serve-aws-lambda.js';\n\nexport function deployAwsLambdaPlugin(deployOptions: {\n config: Required<Config>;\n streaming: boolean;\n}): Plugin {\n return {\n name: 'waku:deploy-aws-lambda',\n config() {\n return {\n environments: {\n rsc: {\n build: {\n rollupOptions: {\n input: {\n index: SERVER_ENTRY,\n },\n },\n },\n define: {\n 'import.meta.env.WAKU_AWS_LAMBDA_STREAMING': JSON.stringify(\n deployOptions.streaming,\n ),\n },\n },\n },\n };\n },\n buildApp: {\n order: 'post',\n async handler(builder) {\n await build({\n config: builder.config,\n opts: deployOptions.config,\n });\n },\n },\n };\n}\n\nasync function build({\n opts,\n}: {\n config: ResolvedConfig;\n opts: Required<Config>;\n}) {\n writeFileSync(\n path.join(opts.distDir, SERVE_JS),\n `export { handler } from './rsc/index.js';\\n`,\n );\n writeFileSync(\n path.join(opts.distDir, 'package.json'),\n JSON.stringify({ type: 'module' }, null, 2),\n );\n}\n"],"names":["writeFileSync","path","fileURLToPath","__dirname","URL","url","SERVER_ENTRY","join","SERVE_JS","deployAwsLambdaPlugin","deployOptions","name","config","environments","rsc","build","rollupOptions","input","index","define","JSON","stringify","streaming","buildApp","order","handler","builder","opts","distDir","type"],"mappings":"AACA,SAASA,aAAa,QAAQ,UAAU;AACxC,OAAOC,UAAU,YAAY;AAE7B,SAASC,aAAa,QAAQ,WAAW;AAEzC,MAAMC,YAAYD,cAAc,IAAIE,IAAI,KAAK,YAAYC,GAAG;AAC5D,MAAMC,eAAeL,KAAKM,IAAI,CAACJ,WAAW;AAC1C,MAAMK,WAAW;AAEjB,OAAO,SAASC,sBAAsBC,aAGrC;IACC,OAAO;QACLC,MAAM;QACNC;YACE,OAAO;gBACLC,cAAc;oBACZC,KAAK;wBACHC,OAAO;4BACLC,eAAe;gCACbC,OAAO;oCACLC,OAAOZ;gCACT;4BACF;wBACF;wBACAa,QAAQ;4BACN,6CAA6CC,KAAKC,SAAS,CACzDX,cAAcY,SAAS;wBAE3B;oBACF;gBACF;YACF;QACF;QACAC,UAAU;YACRC,OAAO;YACP,MAAMC,SAAQC,OAAO;gBACnB,MAAMX,MAAM;oBACVH,QAAQc,QAAQd,MAAM;oBACtBe,MAAMjB,cAAcE,MAAM;gBAC5B;YACF;QACF;IACF;AACF;AAEA,eAAeG,MAAM,EACnBY,IAAI,EAIL;IACC3B,cACEC,KAAKM,IAAI,CAACoB,KAAKC,OAAO,EAAEpB,WACxB,CAAC,2CAA2C,CAAC;IAE/CR,cACEC,KAAKM,IAAI,CAACoB,KAAKC,OAAO,EAAE,iBACxBR,KAAKC,SAAS,CAAC;QAAEQ,MAAM;IAAS,GAAG,MAAM;AAE7C"}
1
+ {"version":3,"sources":["../../../../../src/lib/vite-rsc/deploy/aws-lambda/plugin.ts"],"sourcesContent":["import { type Plugin, type ResolvedConfig } from 'vite';\nimport { writeFileSync } from 'node:fs';\nimport path from 'node:path';\nimport type { Config } from '../../../../config.js';\nimport { fileURLToPath } from 'node:url';\n\nconst __dirname = fileURLToPath(new URL('.', import.meta.url));\nconst SERVER_ENTRY = path.join(__dirname, 'entry.js');\nconst SERVE_JS = 'serve-aws-lambda.js';\n\nexport function deployAwsLambdaPlugin(deployOptions: {\n config: Required<Config>;\n streaming: boolean;\n}): Plugin {\n return {\n name: 'waku:deploy-aws-lambda',\n config() {\n return {\n environments: {\n rsc: {\n build: {\n rollupOptions: {\n input: {\n index: SERVER_ENTRY,\n },\n },\n },\n define: {\n 'import.meta.env.WAKU_AWS_LAMBDA_STREAMING': JSON.stringify(\n deployOptions.streaming,\n ),\n },\n },\n },\n };\n },\n buildApp: {\n order: 'post',\n async handler(builder) {\n await build({\n config: builder.config,\n opts: deployOptions.config,\n });\n },\n },\n };\n}\n\nasync function build({\n opts,\n}: {\n config: ResolvedConfig;\n opts: Required<Config>;\n}) {\n writeFileSync(\n path.join(opts.distDir, SERVE_JS),\n `export { handler } from './server/index.js';\\n`,\n );\n writeFileSync(\n path.join(opts.distDir, 'package.json'),\n JSON.stringify({ type: 'module' }, null, 2),\n );\n}\n"],"names":["writeFileSync","path","fileURLToPath","__dirname","URL","url","SERVER_ENTRY","join","SERVE_JS","deployAwsLambdaPlugin","deployOptions","name","config","environments","rsc","build","rollupOptions","input","index","define","JSON","stringify","streaming","buildApp","order","handler","builder","opts","distDir","type"],"mappings":"AACA,SAASA,aAAa,QAAQ,UAAU;AACxC,OAAOC,UAAU,YAAY;AAE7B,SAASC,aAAa,QAAQ,WAAW;AAEzC,MAAMC,YAAYD,cAAc,IAAIE,IAAI,KAAK,YAAYC,GAAG;AAC5D,MAAMC,eAAeL,KAAKM,IAAI,CAACJ,WAAW;AAC1C,MAAMK,WAAW;AAEjB,OAAO,SAASC,sBAAsBC,aAGrC;IACC,OAAO;QACLC,MAAM;QACNC;YACE,OAAO;gBACLC,cAAc;oBACZC,KAAK;wBACHC,OAAO;4BACLC,eAAe;gCACbC,OAAO;oCACLC,OAAOZ;gCACT;4BACF;wBACF;wBACAa,QAAQ;4BACN,6CAA6CC,KAAKC,SAAS,CACzDX,cAAcY,SAAS;wBAE3B;oBACF;gBACF;YACF;QACF;QACAC,UAAU;YACRC,OAAO;YACP,MAAMC,SAAQC,OAAO;gBACnB,MAAMX,MAAM;oBACVH,QAAQc,QAAQd,MAAM;oBACtBe,MAAMjB,cAAcE,MAAM;gBAC5B;YACF;QACF;IACF;AACF;AAEA,eAAeG,MAAM,EACnBY,IAAI,EAIL;IACC3B,cACEC,KAAKM,IAAI,CAACoB,KAAKC,OAAO,EAAEpB,WACxB,CAAC,8CAA8C,CAAC;IAElDR,cACEC,KAAKM,IAAI,CAACoB,KAAKC,OAAO,EAAE,iBACxBR,KAAKC,SAAS,CAAC;QAAEQ,MAAM;IAAS,GAAG,MAAM;AAE7C"}
@@ -56,7 +56,7 @@ async function build({ config, opts }) {
56
56
  const outDir = path.join(rootDir, opts.distDir);
57
57
  const assetsDistDir = path.join(outDir, 'assets');
58
58
  const workerDistDir = path.join(outDir, 'worker');
59
- writeFileSync(path.join(outDir, SERVE_JS), `export { default } from './rsc/index.js';\n`);
59
+ writeFileSync(path.join(outDir, SERVE_JS), `export { default } from './server/index.js';\n`);
60
60
  separatePublicAssetsFromFunctions({
61
61
  outDir,
62
62
  assetsDir: assetsDistDir,