waku 0.20.0-beta.2 → 0.20.0

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.
package/README.md CHANGED
@@ -49,11 +49,11 @@ import db from 'some-db';
49
49
 
50
50
  import { Gallery } from '../components/gallery.js';
51
51
 
52
- export default async function StorePage() {
52
+ export const Store = async () => {
53
53
  const products = await db.query('SELECT * FROM products');
54
54
 
55
55
  return <Gallery products={products} />;
56
- }
56
+ };
57
57
  ```
58
58
 
59
59
  #### Client components
@@ -145,11 +145,11 @@ To learn more about the modern React architecture, we recommend [Making Sense of
145
145
 
146
146
  Waku provides a familiar file-based “pages router” experience built for the modern React server components era.
147
147
 
148
- Its underlying [low-level API](https://github.com/dai-shi/waku/blob/main/docs/minimal-api.mdx) is also available for those that prefer programmatic routing. This documentation covers file-baesed routing since many React developers prefer it, but please feel free to try both and see which you like more.
148
+ Its underlying [low-level API](https://github.com/dai-shi/waku/blob/main/docs/create-pages.mdx) is also available for those that prefer programmatic routing. This documentation covers file-based routing since many React developers prefer it, but please feel free to try both and see which you prefer.
149
149
 
150
150
  ### Overview
151
151
 
152
- The directory for file-based routing in Waku projects is `./src/pages`. Layouts and pages can be created as easily as making a new file with two exports: a default function for the React component and a named `getConfig` function to specify the render method and other configuration details.
152
+ The directory for file-based routing in Waku projects is `./src/pages`. Layouts and pages can be created by making a new file with two exports: a default function for the React component and a named `getConfig` function that returns a configuration object including the render method and other options.
153
153
 
154
154
  Waku currently supports two rendering options: `'static'` for static prerendering (SSG) or `'dynamic'` for server-side rendering (SSR).
155
155
 
@@ -158,6 +158,9 @@ For example, you can statically prerender a global header and footer in the root
158
158
  ```tsx
159
159
  // ./src/pages/_layout.tsx
160
160
 
161
+ import { Header } from '../components/header.js';
162
+ import { Footer } from '../components/footer.js';
163
+
161
164
  // Create root layout
162
165
  export default async function RootLayout({ children }) {
163
166
  return (
@@ -186,6 +189,7 @@ export default async function HomePage() {
186
189
  return (
187
190
  <div>
188
191
  <h1>{data.someDynamicTitle}</h1>
192
+ <div>{data.someDynamicContent}</div>
189
193
  </div>
190
194
  );
191
195
  }
@@ -205,7 +209,7 @@ export const getConfig = async () => {
205
209
 
206
210
  #### Single routes
207
211
 
208
- Pages can be rendered as a single route (e.g., `/about.tsx` or `/blog.tsx`).
212
+ Pages can be rendered as a single route (e.g., `/about` or `/blog`).
209
213
 
210
214
  ```tsx
211
215
  // ./src/pages/about.tsx
@@ -223,7 +227,7 @@ export const getConfig = async () => {
223
227
  ```
224
228
 
225
229
  ```tsx
226
- // ./src/pages/blog.tsx
230
+ // ./src/pages/blog/index.tsx
227
231
 
228
232
  // Create blog index page
229
233
  export default async function BlogIndexPage() {
@@ -239,7 +243,7 @@ export const getConfig = async () => {
239
243
 
240
244
  #### Segment routes
241
245
 
242
- Pages can also render a segment route (e.g., `/blog/[slug].tsx`). The rendered React component automatically receives a prop named by the segment (e.g, `slug`) with the value of the rendered route (e.g., `'introducing-waku'`). If statically prerendering a segment route at build time, a `staticPaths` array must also be provided.
246
+ Pages can also render a segment route (e.g., `/blog/[slug]`). The rendered React component automatically receives a prop named by the segment (e.g, `slug`) with the value of the rendered segment (e.g., `'introducing-waku'`). If statically prerendering a segment route at build time, a `staticPaths` array must also be provided.
243
247
 
244
248
  ```tsx
245
249
  // ./src/pages/blog/[slug].tsx
@@ -264,7 +268,7 @@ export const getConfig = async () => {
264
268
  ```
265
269
 
266
270
  ```tsx
267
- // ./src/pages/shop/[category].tsx
271
+ // ./src/pages/shop/[category]/index.tsx
268
272
 
269
273
  // Create product category pages
270
274
  export default async function ProductCategoryPage({ category }) {
@@ -316,7 +320,7 @@ const getStaticPaths = async () => {
316
320
 
317
321
  #### Nested segment routes
318
322
 
319
- Routes can contain multiple segments (e.g., `/shop/[category]/[product].tsx`).
323
+ Routes can contain multiple segments (e.g., `/shop/[category]/[product]`).
320
324
 
321
325
  ```tsx
322
326
  // ./src/pages/shop/[category]/[product].tsx
@@ -347,8 +351,8 @@ export const getConfig = async () => {
347
351
  return {
348
352
  render: 'static',
349
353
  staticPaths: [
350
- ['someCategory', 'someProduct'],
351
- ['someCategory', 'anotherProduct'],
354
+ ['some-category', 'some-product'],
355
+ ['some-category', 'another-product'],
352
356
  ],
353
357
  };
354
358
  };
@@ -356,7 +360,7 @@ export const getConfig = async () => {
356
360
 
357
361
  #### Catch-all routes
358
362
 
359
- Catch-all or "wildcard" routes (e.g., `/app/[...catchAll].tsx`) have indefinite segments. Wildcard routes receive a prop with segment values as an ordered array.
363
+ Catch-all or "wildcard" routes (e.g., `/app/[...catchAll]`) have indefinite segments. Wildcard routes receive a prop with segment values as an ordered array.
360
364
 
361
365
  For example, the `/app/profile/settings` route would receive a `catchAll` prop with the value `['profile', 'settings']`. These values can then be used to determine what to render in the component.
362
366
 
@@ -381,7 +385,7 @@ Layouts are created with a special `_layout.tsx` file name and wrap the entire r
381
385
 
382
386
  #### Root layout
383
387
 
384
- The root layout placed at `./src/pages/_layout.tsx` is especially useful. It can be used for setting global styles, global metadata, global providers, global data, and global components, such as a header and footer.
388
+ The root layout placed at `./pages/_layout.tsx` is especially useful. It can be used for setting global styles, global metadata, global providers, global data, and global components, such as a header and footer.
385
389
 
386
390
  ```tsx
387
391
  // ./src/pages/_layout.tsx
@@ -395,14 +399,20 @@ import { Footer } from '../components/footer.js';
395
399
  export default async function RootLayout({ children }) {
396
400
  return (
397
401
  <Providers>
398
- <meta property="og:image" content="/images/preview.png" />
399
402
  <link rel="icon" type="image/png" href="/images/favicon.png" />
403
+ <meta property="og:image" content="/images/opengraph.png" />
400
404
  <Header />
401
405
  <main>{children}</main>
402
406
  <Footer />
403
407
  </Providers>
404
408
  );
405
409
  }
410
+
411
+ export const getConfig = async () => {
412
+ return {
413
+ render: 'static',
414
+ };
415
+ };
406
416
  ```
407
417
 
408
418
  ```tsx
@@ -420,7 +430,7 @@ export const Providers = ({ children }) => {
420
430
 
421
431
  #### Other layouts
422
432
 
423
- Layouts are also helpful further down the tree. For example, you could add a layout at `./src/pages/blog/_layout.tsx` to add a sidebar to both the blog index and all blog article pages.
433
+ Layouts are also helpful further down the tree. For example, you could add a layout at `./pages/blog/_layout.tsx` to add a sidebar to both the blog index and all blog article pages.
424
434
 
425
435
  ```tsx
426
436
  // ./src/pages/blog/_layout.tsx
@@ -435,10 +445,18 @@ export default async function BlogLayout({ children }) {
435
445
  </div>
436
446
  );
437
447
  }
448
+
449
+ export const getConfig = async () => {
450
+ return {
451
+ render: 'static',
452
+ };
453
+ };
438
454
  ```
439
455
 
440
456
  ## Navigation
441
457
 
458
+ ### Link
459
+
442
460
  Internal links should be made with the Waku `<Link />` component. It accepts a `to` prop for the destination, which is automatically prefetched ahead of the navigation.
443
461
 
444
462
  ```tsx
@@ -455,56 +473,64 @@ export default async function HomePage() {
455
473
  }
456
474
  ```
457
475
 
458
- ## Static assets
476
+ ### useRouter
459
477
 
460
- Static assets such as images, fonts, stylesheets, and scripts can be placed in a special `./public` folder of the Waku project root directory. The public directory structure is served relative to the `/` base path.
478
+ The `useRouter` hook can be used to inspect the current route or perform programmatic navigation.
461
479
 
462
- For example, an image added to `./public/images/logo.svg` can be rendered via `<img src="/images/logo.svg" />`.
480
+ #### router properties
463
481
 
464
- ## File system
465
-
466
- Files placed in a special `./private` folder of the Waku project root directory can be securely accessed in React server components.
482
+ The `router` object has a `value` property with two additional properties related to the current route: `path` (string) and `searchParams` ([URLSearchParams](https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams)).
467
483
 
468
484
  ```tsx
469
- export default async function HomePage() {
470
- const file = readFileSync('./private/README.md', 'utf8');
471
- /* ... */
472
- }
473
- ```
474
-
475
- ## Data fetching
476
-
477
- ### Server
478
-
479
- All of the wonderful patterns of React server components are supported. For example, you can compile MDX files or perform code syntax highlighting on the server with zero impact on the client bundle size.
485
+ 'use client';
480
486
 
481
- ```tsx
482
- // ./src/pages/blog/[slug].tsx
483
- import { MDX } from '../../components/mdx.js';
484
- import { getArticle } from '../../lib/get-article.js';
487
+ import { useRouter_UNSTABLE as useRouter } from 'waku';
485
488
 
486
- export default async function BlogArticlePage({ slug }) {
487
- const article = await getArticle(slug);
489
+ export const Component = () => {
490
+ const router = useRouter();
491
+ const { path, searchParams } = router.value;
488
492
 
489
493
  return (
490
494
  <>
491
- <title>{article.frontmatter.title}</title>
492
- <h1>{article.frontmatter.title}</h1>
493
- <MDX>{article.content}</MDX>
495
+ <div>current path: {path}</div>
496
+ <div>current searchParams: {searchParams.toString()}</div>
494
497
  </>
495
498
  );
496
- }
499
+ };
497
500
  ```
498
501
 
499
- ### Client
502
+ #### router methods
500
503
 
501
- Data should be fetched on the server when possible for the best user experience, but all data fetching libraries such as React Query should be compatible with Waku.
504
+ The `router` object also contains several methods for programmatic navigation:
502
505
 
503
- ## State management
506
+ - `router.push(to: string)` - navigate to the provided route
504
507
 
505
- We recommend [Jotai](https://jotai.org) for global React state management based on the atomic model's performance and scalability, but Waku should be compatible with all React state management libraries such as Zustand and Valtio.
508
+ - `router.prefetch(to: string)` - prefetch the provided route
506
509
 
507
- We're exploring a deeper integration of atomic state management into Waku to achieve the performance and developer experience of signals while preserving React's declarative programming model.
510
+ - `router.replace(to: string)` - replace the current history entry
511
+
512
+ - `router.reload()` - reload the current route
513
+
514
+ - `router.back()` - navigate to the previous entry in the session history
515
+
516
+ - `router.forward()` - navigate to the next entry in the session history
517
+
518
+ ```tsx
519
+ 'use client';
520
+
521
+ import { useRouter_UNSTABLE as useRouter } from 'waku';
522
+
523
+ export const Component = () => {
524
+ const router = useRouter();
525
+
526
+ return (
527
+ <>
528
+ <button onClick={() => router.push('/')}>Home</button>
529
+ <button onClick={() => router.back()}>Back</button>
530
+ </>
531
+ );
532
+ };
533
+ ```
508
534
 
509
535
  ## Metadata
510
536
 
@@ -515,12 +541,18 @@ Waku automatically hoists any title, meta, and link tags to the document head. S
515
541
  export default async function RootLayout({ children }) {
516
542
  return (
517
543
  <>
518
- <meta property="og:image" content="/images/preview.png" />
519
544
  <link rel="icon" type="image/png" href="/images/favicon.png" />
545
+ <meta property="og:image" content="/images/opengraph.png" />
520
546
  {children}
521
547
  </>
522
548
  );
523
549
  }
550
+
551
+ export const getConfig = async () => {
552
+ return {
553
+ render: 'static',
554
+ };
555
+ };
524
556
  ```
525
557
 
526
558
  ```tsx
@@ -535,6 +567,12 @@ export default async function HomePage() {
535
567
  </>
536
568
  );
537
569
  }
570
+
571
+ export const getConfig = async () => {
572
+ return {
573
+ render: 'static',
574
+ };
575
+ };
538
576
  ```
539
577
 
540
578
  Metadata could also be generated programmatically.
@@ -564,6 +602,12 @@ const Head = async () => {
564
602
  const getMetadata = async () => {
565
603
  /* ... */
566
604
  };
605
+
606
+ export const getConfig = async () => {
607
+ return {
608
+ render: 'static',
609
+ };
610
+ };
567
611
  ```
568
612
 
569
613
  ## Styling
@@ -579,6 +623,12 @@ import '../styles.css';
579
623
  export default async function RootLayout({ children }) {
580
624
  return <main>{children}</main>;
581
625
  }
626
+
627
+ export const getConfig = async () => {
628
+ return {
629
+ render: 'static',
630
+ };
631
+ };
582
632
  ```
583
633
 
584
634
  ```css
@@ -605,6 +655,72 @@ export default {
605
655
  };
606
656
  ```
607
657
 
658
+ ## Static assets
659
+
660
+ Static assets such as images, fonts, stylesheets, and scripts can be placed in a special `./public` folder of the Waku project root directory. The public directory structure is served relative to the `/` base path.
661
+
662
+ For example, an image added to `./public/images/logo.svg` can be rendered via `<img src="/images/logo.svg" />`.
663
+
664
+ ## File system
665
+
666
+ Files placed in a special `./private` folder of the Waku project root directory can be securely accessed in React server components.
667
+
668
+ ```tsx
669
+ export default async function HomePage() {
670
+ const file = readFileSync('./private/README.md', 'utf8');
671
+ /* ... */
672
+ }
673
+
674
+ export const getConfig = async () => {
675
+ return {
676
+ render: 'static',
677
+ };
678
+ };
679
+ ```
680
+
681
+ ## Data fetching
682
+
683
+ ### Server
684
+
685
+ All of the wonderful patterns of React server components are supported. For example, you can compile MDX files or perform code syntax highlighting on the server with zero impact on the client bundle size.
686
+
687
+ ```tsx
688
+ // ./src/pages/blog/[slug].tsx
689
+ import { MDX } from '../../components/mdx.js';
690
+ import { getArticle, getStaticPaths } from '../../lib/blog.js';
691
+
692
+ export default async function BlogArticlePage({ slug }) {
693
+ const article = await getArticle(slug);
694
+
695
+ return (
696
+ <>
697
+ <title>{article.frontmatter.title}</title>
698
+ <h1>{article.frontmatter.title}</h1>
699
+ <MDX>{article.content}</MDX>
700
+ </>
701
+ );
702
+ }
703
+
704
+ export const getConfig = async () => {
705
+ const staticPaths = await getStaticPaths();
706
+
707
+ return {
708
+ render: 'static',
709
+ staticPaths,
710
+ };
711
+ };
712
+ ```
713
+
714
+ ### Client
715
+
716
+ Data should be fetched on the server when possible for the best user experience, but all data fetching libraries such as React Query should be compatible with Waku.
717
+
718
+ ## State management
719
+
720
+ We recommend [Jotai](https://jotai.org) for global React state management based on the atomic model's performance and scalability, but Waku should be compatible with all React state management libraries such as Zustand and Valtio.
721
+
722
+ We're exploring a deeper integration of atomic state management into Waku to achieve the performance and developer experience of signals while preserving React's declarative programming model.
723
+
608
724
  ## Environment variables
609
725
 
610
726
  It's important to distinguish environment variables that must be kept secret from those that can be made public.
@@ -27,6 +27,34 @@ export function rscDelegatePlugin(callback) {
27
27
  let mode = 'development';
28
28
  let base = '/';
29
29
  let server;
30
+ const updateStyle = async (id, importer)=>{
31
+ const resolvedSource = await server.pluginContainer.resolveId(id, importer, {
32
+ ssr: true
33
+ });
34
+ if (resolvedSource?.id) {
35
+ const { default: source } = await server.ssrLoadModule(resolvedSource.id);
36
+ const transformedResult = await server.transformRequest(resolvedSource.id);
37
+ if (transformedResult) {
38
+ moduleImports.add(resolvedSource.id);
39
+ callback({
40
+ type: 'custom',
41
+ event: 'module-import',
42
+ data: {
43
+ ...transformedResult,
44
+ source,
45
+ id: resolvedSource.id,
46
+ css: true
47
+ }
48
+ });
49
+ }
50
+ }
51
+ };
52
+ const styleFiles = new Map(); // id -> importer
53
+ const updateAllStyles = async ()=>{
54
+ for (const [id, importer] of styleFiles){
55
+ await updateStyle(id, importer);
56
+ }
57
+ };
30
58
  return {
31
59
  name: 'rsc-delegate-plugin',
32
60
  configResolved (config) {
@@ -38,6 +66,7 @@ export function rscDelegatePlugin(callback) {
38
66
  },
39
67
  async handleHotUpdate (ctx) {
40
68
  if (mode === 'development') {
69
+ await updateAllStyles(); // FIXME is this too aggressive?
41
70
  if (moduleImports.has(ctx.file)) {
42
71
  // re-inject
43
72
  const transformedResult = await server.transformRequest(ctx.file);
@@ -84,26 +113,8 @@ export function rscDelegatePlugin(callback) {
84
113
  data: source
85
114
  });
86
115
  } else if (CSS_LANGS_RE.test(item.source.value)) {
87
- const resolvedSource = await server.pluginContainer.resolveId(item.source.value, id, {
88
- ssr: true
89
- });
90
- if (resolvedSource?.id) {
91
- const { default: source } = await server.ssrLoadModule(resolvedSource.id);
92
- const transformedResult = await server.transformRequest(resolvedSource.id);
93
- if (transformedResult) {
94
- moduleImports.add(resolvedSource.id);
95
- callback({
96
- type: 'custom',
97
- event: 'module-import',
98
- data: {
99
- ...transformedResult,
100
- source,
101
- id: resolvedSource.id,
102
- css: true
103
- }
104
- });
105
- }
106
- }
116
+ styleFiles.set(item.source.value, id);
117
+ await updateStyle(item.source.value, id);
107
118
  }
108
119
  }
109
120
  }
@@ -1,4 +1,4 @@
1
- import { joinPath, fileURLToFilePath, decodeFilePathFromAbsolute } from '../utils/path.js';
1
+ import { joinPath, fileURLToFilePath, decodeFilePathFromAbsolute, filePathToFileURL } from '../utils/path.js';
2
2
  const injectingHmrCode = `
3
3
  import { createHotContext as __vite__createHotContext } from "/@vite/client";
4
4
  import.meta.hot = __vite__createHotContext(import.meta.url);
@@ -22,7 +22,7 @@ if (import.meta.hot && !globalThis.__WAKU_HMR_CONFIGURED__) {
22
22
  document.head.appendChild(script);
23
23
  // avoid HMR flash by first applying the new and removing the old styles
24
24
  if (style) {
25
- queueMicrotask(style.remove);
25
+ queueMicrotask(() => style.parentElement?.removeChild(style));
26
26
  }
27
27
  });
28
28
  }
@@ -91,6 +91,18 @@ export function rscHmrPlugin() {
91
91
  }
92
92
  `);
93
93
  }
94
+ },
95
+ handleHotUpdate ({ file }) {
96
+ const moduleLoading = globalThis.__webpack_module_loading__;
97
+ const moduleCache = globalThis.__webpack_module_cache__;
98
+ const id = filePathToFileURL(file);
99
+ if (moduleLoading.has(id) && moduleCache.has(id)) {
100
+ moduleLoading.delete(id);
101
+ moduleCache.delete(id);
102
+ moduleLoading.set(id, viteServer.ssrLoadModule(file).then((m)=>{
103
+ moduleCache.set(id, m);
104
+ }));
105
+ }
94
106
  }
95
107
  };
96
108
  }
@@ -124,12 +136,12 @@ function hotImport(viteServer, source) {
124
136
  const modulePendingMap = new WeakMap();
125
137
  function moduleImport(viteServer, result) {
126
138
  const hot = viteHot(viteServer);
127
- let sourceSet = modulePendingMap.get(hot);
128
- if (!sourceSet) {
129
- sourceSet = new Set();
130
- modulePendingMap.set(hot, sourceSet);
139
+ let sources = modulePendingMap.get(hot);
140
+ if (!sources) {
141
+ sources = new Map();
142
+ modulePendingMap.set(hot, sources);
131
143
  }
132
- sourceSet.add(result);
144
+ sources.set(result.id, result);
133
145
  hot.send({
134
146
  type: 'custom',
135
147
  event: 'module-import',
@@ -138,13 +150,13 @@ function moduleImport(viteServer, result) {
138
150
  }
139
151
  async function generateInitialScripts(viteServer) {
140
152
  const hot = viteHot(viteServer);
141
- const sourceSet = modulePendingMap.get(hot);
142
- if (!sourceSet) {
153
+ const sources = modulePendingMap.get(hot);
154
+ if (!sources) {
143
155
  return [];
144
156
  }
145
157
  const scripts = [];
146
158
  let injectedBlockingViteClient = false;
147
- for (const result of sourceSet){
159
+ for (const result of sources.values()){
148
160
  // CSS modules do not support result.source (empty) since ssr-transforming them gives the css keys
149
161
  // and client-transforming them gives the script tag for injecting them.
150
162
  if (result.id.endsWith('.module.css')) {
@@ -148,13 +148,14 @@ export const renderHtml = async (opts)=>{
148
148
  get (_target, filePath) {
149
149
  return new Proxy({}, {
150
150
  get (_target, name) {
151
- const file = filePath.slice(config.basePath.length);
152
- // TODO too long, we need to refactor this logic
153
151
  if (isDev) {
154
- const filePath = file.startsWith('@fs/') ? file.slice('@fs'.length) : encodeFilePathToAbsolute(joinPath(opts.rootDir, file.split('?')[0]));
152
+ // TODO too long, we need to refactor this logic
153
+ let file = filePath.slice(config.basePath.length);
154
+ file = file.split('?')[0];
155
+ file = file.startsWith('@fs/') ? file.slice('@fs'.length) : encodeFilePathToAbsolute(joinPath(opts.rootDir, file));
155
156
  const wakuDist = joinPath(fileURLToFilePath(import.meta.url), '../../..');
156
- if (filePath.startsWith(wakuDist)) {
157
- const id = 'waku' + filePath.slice(wakuDist.length).replace(/\.\w+$/, '');
157
+ if (file.startsWith(wakuDist)) {
158
+ const id = 'waku' + file.slice(wakuDist.length).replace(/\.\w+$/, '');
158
159
  if (!moduleLoading.has(id)) {
159
160
  moduleLoading.set(id, import(/* @vite-ignore */ id).then((m)=>{
160
161
  moduleCache.set(id, m);
@@ -168,7 +169,7 @@ export const renderHtml = async (opts)=>{
168
169
  name
169
170
  };
170
171
  }
171
- const id = filePathToFileURL(filePath);
172
+ const id = filePathToFileURL(file);
172
173
  if (!moduleLoading.has(id)) {
173
174
  moduleLoading.set(id, opts.loadServerFile(id).then((m)=>{
174
175
  moduleCache.set(id, m);
@@ -183,7 +184,7 @@ export const renderHtml = async (opts)=>{
183
184
  };
184
185
  }
185
186
  // !isDev
186
- const id = file;
187
+ const id = filePath.slice(config.basePath.length);
187
188
  if (!moduleLoading.has(id)) {
188
189
  moduleLoading.set(id, opts.loadModule(joinPath(config.ssrDir, id)).then((m)=>{
189
190
  moduleCache.set(id, m);
package/dist/main.d.ts CHANGED
@@ -1,3 +1,3 @@
1
- export { Link } from 'waku/router/client';
1
+ export { Link, useRouter_UNSTABLE } from 'waku/router/client';
2
2
  export { createPages } from 'waku/router/server';
3
3
  export { getEnv } from 'waku/server';
package/dist/main.js CHANGED
@@ -1,3 +1,3 @@
1
- export { Link } from 'waku/router/client';
1
+ export { Link, useRouter_UNSTABLE } from 'waku/router/client';
2
2
  export { createPages } from 'waku/router/server';
3
3
  export { getEnv } from 'waku/server';
@@ -5,15 +5,15 @@ declare global {
5
5
  readonly env: Record<string, string>;
6
6
  }
7
7
  }
8
- declare const parseLocation: () => RouteProps;
9
- type ChangeLocation = (path?: string, searchParams?: URLSearchParams, options?: {
10
- hash?: string;
11
- method?: 'pushState' | 'replaceState' | false;
12
- scrollTo?: ScrollToOptions | false;
13
- unstable_skipRefetch?: boolean;
14
- }) => void;
15
- export declare function useChangeLocation(): ChangeLocation;
16
- export declare function useLocation(): RouteProps;
8
+ export declare function useRouter_UNSTABLE(): {
9
+ value: RouteProps;
10
+ push: (to: string) => void;
11
+ replace: (to: string) => void;
12
+ reload: () => void;
13
+ back: () => void;
14
+ forward: () => void;
15
+ prefetch: (to: string) => void;
16
+ };
17
17
  export type LinkProps = {
18
18
  to: string;
19
19
  pending?: ReactNode;
@@ -24,7 +24,7 @@ export type LinkProps = {
24
24
  export declare function Link({ to, children, pending, notPending, unstable_prefetchOnEnter, ...props }: LinkProps): ReactElement;
25
25
  type RouterData = [
26
26
  shouldSkip?: ShouldSkip,
27
- locationListners?: Set<(pathname: string, searchParams: URLSearchParams) => void>
27
+ locationListners?: Set<(pathname: string, searchParamsString: string) => void>
28
28
  ];
29
29
  export declare function Router({ routerData }: {
30
30
  routerData?: RouterData | undefined;
@@ -39,9 +39,9 @@ export declare function Router({ routerData }: {
39
39
  * ServerRouter for SSR
40
40
  * This is not a public API.
41
41
  */
42
- export declare function ServerRouter({ children, loc, }: {
42
+ export declare function ServerRouter({ children, route, }: {
43
43
  children: ReactNode;
44
- loc: ReturnType<typeof parseLocation>;
44
+ route: RouteProps;
45
45
  }): import("react").FunctionComponentElement<{
46
46
  children?: ReactNode;
47
47
  }>;