@buzola/router 0.0.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.
- package/dist/__tests__/create-page.test.d.ts +2 -0
- package/dist/__tests__/create-page.test.d.ts.map +1 -0
- package/dist/__tests__/create-page.test.js +457 -0
- package/dist/__tests__/create-page.test.js.map +1 -0
- package/dist/__tests__/define-routes.test.d.ts +2 -0
- package/dist/__tests__/define-routes.test.d.ts.map +1 -0
- package/dist/__tests__/define-routes.test.js +42 -0
- package/dist/__tests__/define-routes.test.js.map +1 -0
- package/dist/__tests__/matcher.test.d.ts +2 -0
- package/dist/__tests__/matcher.test.d.ts.map +1 -0
- package/dist/__tests__/matcher.test.js +108 -0
- package/dist/__tests__/matcher.test.js.map +1 -0
- package/dist/__tests__/router.test.d.ts +2 -0
- package/dist/__tests__/router.test.d.ts.map +1 -0
- package/dist/__tests__/router.test.js +327 -0
- package/dist/__tests__/router.test.js.map +1 -0
- package/dist/__tests__/type-safety.test.d.ts +15 -0
- package/dist/__tests__/type-safety.test.d.ts.map +1 -0
- package/dist/__tests__/type-safety.test.js +163 -0
- package/dist/__tests__/type-safety.test.js.map +1 -0
- package/dist/__tests__/types.test.d.ts +2 -0
- package/dist/__tests__/types.test.d.ts.map +1 -0
- package/dist/__tests__/types.test.js +22 -0
- package/dist/__tests__/types.test.js.map +1 -0
- package/dist/define/create-page.d.ts +87 -0
- package/dist/define/create-page.d.ts.map +1 -0
- package/dist/define/create-page.js +305 -0
- package/dist/define/create-page.js.map +1 -0
- package/dist/define/define-routes.d.ts +34 -0
- package/dist/define/define-routes.d.ts.map +1 -0
- package/dist/define/define-routes.js +53 -0
- package/dist/define/define-routes.js.map +1 -0
- package/dist/engine/matcher.d.ts +8 -0
- package/dist/engine/matcher.d.ts.map +1 -0
- package/dist/engine/matcher.js +79 -0
- package/dist/engine/matcher.js.map +1 -0
- package/dist/engine/navigation-adapter.d.ts +13 -0
- package/dist/engine/navigation-adapter.d.ts.map +1 -0
- package/dist/engine/navigation-adapter.js +156 -0
- package/dist/engine/navigation-adapter.js.map +1 -0
- package/dist/engine/route-tree.d.ts +21 -0
- package/dist/engine/route-tree.d.ts.map +1 -0
- package/dist/engine/route-tree.js +95 -0
- package/dist/engine/route-tree.js.map +1 -0
- package/dist/engine/router.d.ts +162 -0
- package/dist/engine/router.d.ts.map +1 -0
- package/dist/engine/router.js +400 -0
- package/dist/engine/router.js.map +1 -0
- package/dist/engine/schema.d.ts +46 -0
- package/dist/engine/schema.d.ts.map +1 -0
- package/dist/engine/schema.js +110 -0
- package/dist/engine/schema.js.map +1 -0
- package/dist/engine/types.d.ts +183 -0
- package/dist/engine/types.d.ts.map +1 -0
- package/dist/engine/types.js +2 -0
- package/dist/engine/types.js.map +1 -0
- package/dist/engine/utils.d.ts +7 -0
- package/dist/engine/utils.d.ts.map +1 -0
- package/dist/engine/utils.js +17 -0
- package/dist/engine/utils.js.map +1 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -0
- package/dist/react/context.d.ts +21 -0
- package/dist/react/context.d.ts.map +1 -0
- package/dist/react/context.js +7 -0
- package/dist/react/context.js.map +1 -0
- package/dist/react/error-boundary.d.ts +24 -0
- package/dist/react/error-boundary.d.ts.map +1 -0
- package/dist/react/error-boundary.js +37 -0
- package/dist/react/error-boundary.js.map +1 -0
- package/dist/react/hooks.d.ts +85 -0
- package/dist/react/hooks.d.ts.map +1 -0
- package/dist/react/hooks.js +161 -0
- package/dist/react/hooks.js.map +1 -0
- package/dist/react/index.d.ts +12 -0
- package/dist/react/index.d.ts.map +1 -0
- package/dist/react/index.js +7 -0
- package/dist/react/index.js.map +1 -0
- package/dist/react/link.d.ts +42 -0
- package/dist/react/link.d.ts.map +1 -0
- package/dist/react/link.js +38 -0
- package/dist/react/link.js.map +1 -0
- package/dist/react/outlet.d.ts +13 -0
- package/dist/react/outlet.d.ts.map +1 -0
- package/dist/react/outlet.js +46 -0
- package/dist/react/outlet.js.map +1 -0
- package/dist/react/provider.d.ts +22 -0
- package/dist/react/provider.d.ts.map +1 -0
- package/dist/react/provider.js +37 -0
- package/dist/react/provider.js.map +1 -0
- package/package.json +29 -0
- package/src/__tests__/create-page.test.ts +588 -0
- package/src/__tests__/matcher.test.ts +127 -0
- package/src/__tests__/router.test.ts +424 -0
- package/src/__tests__/type-safety.test.tsx +207 -0
- package/src/define/create-page.tsx +472 -0
- package/src/engine/matcher.ts +88 -0
- package/src/engine/navigation-adapter.ts +191 -0
- package/src/engine/route-tree.ts +129 -0
- package/src/engine/router.ts +471 -0
- package/src/engine/schema.ts +130 -0
- package/src/engine/types.ts +203 -0
- package/src/engine/utils.ts +16 -0
- package/src/env.d.ts +120 -0
- package/src/index.ts +61 -0
- package/src/react/context.ts +24 -0
- package/src/react/error-boundary.tsx +56 -0
- package/src/react/hooks.ts +211 -0
- package/src/react/index.ts +16 -0
- package/src/react/link.tsx +93 -0
- package/src/react/outlet.tsx +67 -0
- package/src/react/provider.tsx +60 -0
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { describe, expect, it } from 'bun:test';
|
|
3
|
+
import React from 'react';
|
|
4
|
+
import { createPage } from '../define/create-page.js';
|
|
5
|
+
// ─── Helper ─────────────────────────────────────────────────────────────────
|
|
6
|
+
function mockSchema() {
|
|
7
|
+
return { '~standard': { version: 1, vendor: 'test', validate: (v) => ({ value: v }) } };
|
|
8
|
+
}
|
|
9
|
+
// ─── createPage().route() type safety ───────────────────────────────────────
|
|
10
|
+
describe('createPage route type safety', () => {
|
|
11
|
+
it('allows static route without params', () => {
|
|
12
|
+
const _page = createPage().route('/about').render(() => null);
|
|
13
|
+
expect(true).toBe(true);
|
|
14
|
+
});
|
|
15
|
+
it('rejects dynamic route without params', () => {
|
|
16
|
+
// @ts-expect-error — :id in route but no .params() defined
|
|
17
|
+
const _page = createPage().route('/users/:id').render(() => null);
|
|
18
|
+
expect(true).toBe(true);
|
|
19
|
+
});
|
|
20
|
+
it('allows dynamic route when param is in schema', () => {
|
|
21
|
+
const _page = createPage()
|
|
22
|
+
.params(mockSchema())
|
|
23
|
+
.route('/users/:id')
|
|
24
|
+
.render(({ params }) => null);
|
|
25
|
+
expect(true).toBe(true);
|
|
26
|
+
});
|
|
27
|
+
it('rejects dynamic route when param is not in schema', () => {
|
|
28
|
+
const _page = createPage()
|
|
29
|
+
.params(mockSchema())
|
|
30
|
+
// @ts-expect-error — :id is not a key of { userId: string }
|
|
31
|
+
.route('/users/:id')
|
|
32
|
+
.render(({ params }) => null);
|
|
33
|
+
expect(true).toBe(true);
|
|
34
|
+
});
|
|
35
|
+
it('allows multiple route params when all are in schema', () => {
|
|
36
|
+
const _page = createPage()
|
|
37
|
+
.params(mockSchema())
|
|
38
|
+
.route('/users/:userId/posts/:postId')
|
|
39
|
+
.render(({ params }) => null);
|
|
40
|
+
expect(true).toBe(true);
|
|
41
|
+
});
|
|
42
|
+
it('rejects when one route param is missing from schema', () => {
|
|
43
|
+
const _page = createPage()
|
|
44
|
+
.params(mockSchema())
|
|
45
|
+
// @ts-expect-error — :postId is not in { userId: string }
|
|
46
|
+
.route('/users/:userId/posts/:postId')
|
|
47
|
+
.render(({ params }) => null);
|
|
48
|
+
expect(true).toBe(true);
|
|
49
|
+
});
|
|
50
|
+
it('allows schema params that are not in route (they become query params)', () => {
|
|
51
|
+
const _page = createPage()
|
|
52
|
+
.params(mockSchema())
|
|
53
|
+
.route('/users/:userId')
|
|
54
|
+
.render(({ params }) => null);
|
|
55
|
+
expect(true).toBe(true);
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
// ─── createPage().catch() type safety ────────────────────────────────────────
|
|
59
|
+
describe('createPage catch type safety', () => {
|
|
60
|
+
it('.catch() is available before .render()', () => {
|
|
61
|
+
const _page = createPage()
|
|
62
|
+
.catch(({ error }) => _jsx("div", { children: error.message }))
|
|
63
|
+
.render(() => null);
|
|
64
|
+
expect(true).toBe(true);
|
|
65
|
+
});
|
|
66
|
+
it('.catch() is available after .route()', () => {
|
|
67
|
+
const _page = createPage()
|
|
68
|
+
.route('/about')
|
|
69
|
+
.catch(({ error }) => _jsx("div", { children: error.message }))
|
|
70
|
+
.render(() => null);
|
|
71
|
+
expect(true).toBe(true);
|
|
72
|
+
});
|
|
73
|
+
it('no .catch() after .catch()', () => {
|
|
74
|
+
const withCatch = createPage().catch(({ error }) => _jsx("div", { children: error.message }));
|
|
75
|
+
// @ts-expect-error — .catch() should not be available after .catch()
|
|
76
|
+
withCatch.catch;
|
|
77
|
+
expect(true).toBe(true);
|
|
78
|
+
});
|
|
79
|
+
it('no .loader() after .catch()', () => {
|
|
80
|
+
const withCatch = createPage().catch(({ error }) => _jsx("div", { children: error.message }));
|
|
81
|
+
// @ts-expect-error — .loader() should not be available after .catch()
|
|
82
|
+
withCatch.loader;
|
|
83
|
+
expect(true).toBe(true);
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
// ─── LinkProps ──────────────────────────────────────────────────────────────
|
|
87
|
+
describe('LinkProps type safety', () => {
|
|
88
|
+
it('static page does not require params', () => {
|
|
89
|
+
const _a = { to: 'home' };
|
|
90
|
+
const _b = { to: 'about' };
|
|
91
|
+
expect(true).toBe(true);
|
|
92
|
+
});
|
|
93
|
+
it('static page rejects params', () => {
|
|
94
|
+
// @ts-expect-error — static page should not accept params
|
|
95
|
+
const _a = { to: 'about', params: { foo: 'bar' } };
|
|
96
|
+
expect(true).toBe(true);
|
|
97
|
+
});
|
|
98
|
+
it('dynamic page requires params', () => {
|
|
99
|
+
const _a = { to: 'users/detail', params: { userId: '1' } };
|
|
100
|
+
// @ts-expect-error — missing required params
|
|
101
|
+
const _b = { to: 'users/detail' };
|
|
102
|
+
expect(true).toBe(true);
|
|
103
|
+
});
|
|
104
|
+
it('dynamic page requires correct param names', () => {
|
|
105
|
+
// @ts-expect-error — wrong param name
|
|
106
|
+
const _a = { to: 'users/detail', params: { id: '1' } };
|
|
107
|
+
expect(true).toBe(true);
|
|
108
|
+
});
|
|
109
|
+
it('multi-param page requires all params', () => {
|
|
110
|
+
const _a = {
|
|
111
|
+
to: 'users/posts',
|
|
112
|
+
params: { userId: '1', postId: '2' },
|
|
113
|
+
};
|
|
114
|
+
const _b = {
|
|
115
|
+
to: 'users/posts',
|
|
116
|
+
// @ts-expect-error — missing postId
|
|
117
|
+
params: { userId: '1' },
|
|
118
|
+
};
|
|
119
|
+
expect(true).toBe(true);
|
|
120
|
+
});
|
|
121
|
+
it('rejects unregistered pages', () => {
|
|
122
|
+
// @ts-expect-error — page not in BuzolaPageMap
|
|
123
|
+
const _a = { to: 'unknown' };
|
|
124
|
+
expect(true).toBe(true);
|
|
125
|
+
});
|
|
126
|
+
});
|
|
127
|
+
// ─── Link JSX usage (generic inference) ─────────────────────────────────────
|
|
128
|
+
import { Link } from '../react/link.js';
|
|
129
|
+
describe('Link JSX generic inference', () => {
|
|
130
|
+
it('accepts static page without params', () => {
|
|
131
|
+
const _el = _jsx(Link, { to: "home", children: "Home" });
|
|
132
|
+
const _el2 = _jsx(Link, { to: "about", children: "About" });
|
|
133
|
+
expect(true).toBe(true);
|
|
134
|
+
});
|
|
135
|
+
it('rejects params on static page', () => {
|
|
136
|
+
// @ts-expect-error — static page should not accept params
|
|
137
|
+
const _el = _jsx(Link, { to: "about", params: { foo: 'bar' }, children: "About" });
|
|
138
|
+
expect(true).toBe(true);
|
|
139
|
+
});
|
|
140
|
+
it('requires params on dynamic page', () => {
|
|
141
|
+
const _el = _jsx(Link, { to: "users/detail", params: { userId: '1' }, children: "User" });
|
|
142
|
+
// @ts-expect-error — missing required params
|
|
143
|
+
const _el2 = _jsx(Link, { to: "users/detail", children: "User" });
|
|
144
|
+
expect(true).toBe(true);
|
|
145
|
+
});
|
|
146
|
+
it('rejects wrong param names', () => {
|
|
147
|
+
// @ts-expect-error — wrong param name
|
|
148
|
+
const _el = _jsx(Link, { to: "users/detail", params: { id: '1' }, children: "User" });
|
|
149
|
+
expect(true).toBe(true);
|
|
150
|
+
});
|
|
151
|
+
it('requires all params for multi-param page', () => {
|
|
152
|
+
const _ok = _jsx(Link, { to: "users/posts", params: { userId: '1', postId: '2' }, children: "Post" });
|
|
153
|
+
// @ts-expect-error — missing postId
|
|
154
|
+
const _bad = _jsx(Link, { to: "users/posts", params: { userId: '1' }, children: "Post" });
|
|
155
|
+
expect(true).toBe(true);
|
|
156
|
+
});
|
|
157
|
+
it('rejects unregistered pages', () => {
|
|
158
|
+
// @ts-expect-error — page not in BuzolaPageMap
|
|
159
|
+
const _el = _jsx(Link, { to: "nope", children: "Nope" });
|
|
160
|
+
expect(true).toBe(true);
|
|
161
|
+
});
|
|
162
|
+
});
|
|
163
|
+
//# sourceMappingURL=type-safety.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"type-safety.test.js","sourceRoot":"","sources":["../../src/__tests__/type-safety.test.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/types.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { describe, expect, it } from 'bun:test';
|
|
2
|
+
describe('ParamsForPath type', () => {
|
|
3
|
+
it('extracts no params from static paths', () => {
|
|
4
|
+
// Type-level test: this should compile without error
|
|
5
|
+
const _test = {};
|
|
6
|
+
expect(true).toBe(true);
|
|
7
|
+
});
|
|
8
|
+
it('extracts a single param', () => {
|
|
9
|
+
const _test = { userId: 'abc' };
|
|
10
|
+
expect(_test.userId).toBe('abc');
|
|
11
|
+
});
|
|
12
|
+
it('extracts multiple params', () => {
|
|
13
|
+
const _test = { userId: '1', postId: '2' };
|
|
14
|
+
expect(_test.userId).toBe('1');
|
|
15
|
+
expect(_test.postId).toBe('2');
|
|
16
|
+
});
|
|
17
|
+
it('handles root path', () => {
|
|
18
|
+
const _test = {};
|
|
19
|
+
expect(true).toBe(true);
|
|
20
|
+
});
|
|
21
|
+
});
|
|
22
|
+
//# sourceMappingURL=types.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.test.js","sourceRoot":"","sources":["../../src/__tests__/types.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,UAAU,CAAA;AAG/C,QAAQ,CAAC,oBAAoB,EAAE,GAAG,EAAE;IACnC,EAAE,CAAC,sCAAsC,EAAE,GAAG,EAAE;QAC/C,qDAAqD;QACrD,MAAM,KAAK,GAA4B,EAAwB,CAAA;QAC/D,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IACxB,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,yBAAyB,EAAE,GAAG,EAAE;QAClC,MAAM,KAAK,GAAoC,EAAE,MAAM,EAAE,KAAK,EAAE,CAAA;QAChE,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IACjC,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,0BAA0B,EAAE,GAAG,EAAE;QACnC,MAAM,KAAK,GAAkD,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,CAAA;QACzF,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;QAC9B,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;IAC/B,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,mBAAmB,EAAE,GAAG,EAAE;QAC5B,MAAM,KAAK,GAAuB,EAAwB,CAAA;QAC1D,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IACxB,CAAC,CAAC,CAAA;AACH,CAAC,CAAC,CAAA"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { type ComponentType } from 'react';
|
|
2
|
+
import { type ParamLiteral } from '../engine/schema';
|
|
3
|
+
import type { RouteComponent, StandardSchema } from '../engine/types';
|
|
4
|
+
export interface PageProps<TParams> {
|
|
5
|
+
params: TParams;
|
|
6
|
+
}
|
|
7
|
+
export interface CatchContext {
|
|
8
|
+
error: Error;
|
|
9
|
+
retry: () => void;
|
|
10
|
+
}
|
|
11
|
+
type CatchHandler = React.ReactNode | ((ctx: CatchContext) => React.ReactNode);
|
|
12
|
+
export interface ParamMeta {
|
|
13
|
+
name: string;
|
|
14
|
+
optional: boolean;
|
|
15
|
+
array: boolean;
|
|
16
|
+
}
|
|
17
|
+
export interface PageDefinition<TParams = Record<string, never>> {
|
|
18
|
+
__buzolaPage: true;
|
|
19
|
+
component: RouteComponent;
|
|
20
|
+
route?: string;
|
|
21
|
+
paramsSchema?: StandardSchema;
|
|
22
|
+
paramsMeta: ParamMeta[];
|
|
23
|
+
loader?: (ctx: {
|
|
24
|
+
params: any;
|
|
25
|
+
}) => Promise<unknown>;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Extract dynamic parameter names from a route pattern at the type level.
|
|
29
|
+
* "/users/:userId/posts/:postId" → "userId" | "postId"
|
|
30
|
+
* "/:slug+" → "slug"
|
|
31
|
+
*/
|
|
32
|
+
type ExtractRouteParams<T extends string> = T extends `${string}:${infer Param}/${infer Rest}` ? (Param extends `${infer P}+` ? P : Param) | ExtractRouteParams<Rest> : T extends `${string}:${infer Param}` ? (Param extends `${infer P}+` ? P : Param) : never;
|
|
33
|
+
type ParamField = StandardSchema | ParamLiteral;
|
|
34
|
+
type ParamsShape = Record<string, ParamField>;
|
|
35
|
+
type ScalarType<T extends string> = T extends 'string' ? string : T extends 'number' ? number : T extends 'uuid' ? string : never;
|
|
36
|
+
type LiteralToType<L extends string> = L extends `?${infer Base}[]` ? ScalarType<Base>[] | undefined : L extends `${infer Base}[]` ? ScalarType<Base>[] : L extends `?${infer Base}` ? ScalarType<Base> | undefined : ScalarType<L>;
|
|
37
|
+
type InferShape<T extends ParamsShape> = {
|
|
38
|
+
[K in keyof T]: T[K] extends StandardSchema<infer V> ? V : T[K] extends string ? LiteralToType<T[K]> : never;
|
|
39
|
+
};
|
|
40
|
+
interface WithCatch<TParams, TRenderProps> {
|
|
41
|
+
route<R extends string>(pattern: [ExtractRouteParams<R>] extends [keyof TParams & string] ? R : never): {
|
|
42
|
+
render(fn: ComponentType<TRenderProps>): PageDefinition<TParams>;
|
|
43
|
+
};
|
|
44
|
+
render(fn: ComponentType<TRenderProps>): PageDefinition<TParams>;
|
|
45
|
+
}
|
|
46
|
+
interface WithRoute<TParams, TRenderProps> {
|
|
47
|
+
catch(handler: CatchHandler): WithCatch<TParams, TRenderProps>;
|
|
48
|
+
route<R extends string>(pattern: [ExtractRouteParams<R>] extends [keyof TParams & string] ? R : never): {
|
|
49
|
+
catch(handler: CatchHandler): {
|
|
50
|
+
render(fn: ComponentType<TRenderProps>): PageDefinition<TParams>;
|
|
51
|
+
};
|
|
52
|
+
render(fn: ComponentType<TRenderProps>): PageDefinition<TParams>;
|
|
53
|
+
};
|
|
54
|
+
render(fn: ComponentType<TRenderProps>): PageDefinition<TParams>;
|
|
55
|
+
}
|
|
56
|
+
interface WithLoaderChain<TParams, TData> extends WithRoute<TParams, PageProps<TParams> & {
|
|
57
|
+
data: TData;
|
|
58
|
+
invalidate: () => void;
|
|
59
|
+
isLoading: boolean;
|
|
60
|
+
}> {
|
|
61
|
+
loader<TNew extends Record<string, unknown>>(fn: (ctx: {
|
|
62
|
+
params: TParams;
|
|
63
|
+
}) => Promise<TNew>): WithLoaderChain<TParams, TData & TNew>;
|
|
64
|
+
}
|
|
65
|
+
interface WithLoader<TParams> extends WithRoute<TParams, PageProps<TParams>> {
|
|
66
|
+
loader<TData extends Record<string, unknown>>(fn: (ctx: {
|
|
67
|
+
params: TParams;
|
|
68
|
+
}) => Promise<TData>): WithLoaderChain<TParams, TData>;
|
|
69
|
+
}
|
|
70
|
+
interface PageBuilder {
|
|
71
|
+
params<T extends ParamsShape>(shape: T): WithLoader<InferShape<T>>;
|
|
72
|
+
params<T extends Record<string, unknown>>(schema: StandardSchema<T>): WithLoader<T>;
|
|
73
|
+
loader<TData extends Record<string, unknown>>(fn: (ctx: {
|
|
74
|
+
params: Record<string, never>;
|
|
75
|
+
}) => Promise<TData>): WithLoaderChain<Record<string, never>, TData>;
|
|
76
|
+
catch(handler: CatchHandler): WithCatch<Record<string, never>, PageProps<Record<string, never>>>;
|
|
77
|
+
route<R extends string>(pattern: [ExtractRouteParams<R>] extends [never] ? R : never): {
|
|
78
|
+
catch(handler: CatchHandler): {
|
|
79
|
+
render(fn: ComponentType<PageProps<Record<string, never>>>): PageDefinition;
|
|
80
|
+
};
|
|
81
|
+
render(fn: ComponentType<PageProps<Record<string, never>>>): PageDefinition;
|
|
82
|
+
};
|
|
83
|
+
render(fn: ComponentType<PageProps<Record<string, never>>>): PageDefinition;
|
|
84
|
+
}
|
|
85
|
+
export declare function createPage(): PageBuilder;
|
|
86
|
+
export {};
|
|
87
|
+
//# sourceMappingURL=create-page.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create-page.d.ts","sourceRoot":"","sources":["../../src/define/create-page.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { use, useCallback, useEffect, useMemo, useReducer, useState } from 'react';
|
|
3
|
+
import { isOptionalSchema, resolveParamLiteral } from '../engine/schema';
|
|
4
|
+
import { extractParamNames } from '../engine/utils';
|
|
5
|
+
import { RouteContext, RouterContext } from '../react/context';
|
|
6
|
+
import { ErrorBoundary } from '../react/error-boundary';
|
|
7
|
+
function isStandardSchema(value) {
|
|
8
|
+
return '~standard' in value;
|
|
9
|
+
}
|
|
10
|
+
function resolveParamsInput(input) {
|
|
11
|
+
if (isStandardSchema(input)) {
|
|
12
|
+
return {
|
|
13
|
+
schema: input,
|
|
14
|
+
paramsMeta: input.__buzolaKeys ?? [],
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
const shape = input;
|
|
18
|
+
const paramsMeta = [];
|
|
19
|
+
const fieldSchemas = {};
|
|
20
|
+
for (const [name, field] of Object.entries(shape)) {
|
|
21
|
+
if (typeof field === 'string') {
|
|
22
|
+
const resolved = resolveParamLiteral(field);
|
|
23
|
+
fieldSchemas[name] = resolved.schema;
|
|
24
|
+
paramsMeta.push({ name, optional: resolved.optional, array: resolved.array });
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
fieldSchemas[name] = field;
|
|
28
|
+
paramsMeta.push({ name, optional: isOptionalSchema(field), array: false });
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
const schema = {
|
|
32
|
+
'~standard': {
|
|
33
|
+
version: 1,
|
|
34
|
+
vendor: 'buzola',
|
|
35
|
+
validate: (v) => {
|
|
36
|
+
const record = (v ?? {});
|
|
37
|
+
const result = {};
|
|
38
|
+
for (const [key, fs] of Object.entries(fieldSchemas)) {
|
|
39
|
+
const r = fs['~standard'].validate(record[key]);
|
|
40
|
+
if ('issues' in r)
|
|
41
|
+
return r;
|
|
42
|
+
result[key] = r.value;
|
|
43
|
+
}
|
|
44
|
+
return { value: result };
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
};
|
|
48
|
+
return { schema, paramsMeta };
|
|
49
|
+
}
|
|
50
|
+
function combineLoaders(loaders) {
|
|
51
|
+
if (loaders.length === 0)
|
|
52
|
+
return undefined;
|
|
53
|
+
if (loaders.length === 1)
|
|
54
|
+
return loaders[0];
|
|
55
|
+
return async (ctx) => Object.assign({}, ...await Promise.all(loaders.map(fn => fn(ctx))));
|
|
56
|
+
}
|
|
57
|
+
// ─── Component factory ──────────────────────────────────────────────────────
|
|
58
|
+
function createPageComponent(schema, paramsMeta, loaderFn, routePattern, RenderComponent, catchHandler) {
|
|
59
|
+
const arrayParams = new Set(paramsMeta.filter(m => m.array).map(m => m.name));
|
|
60
|
+
// Loader promise cache lives in the closure, outside React's render cycle.
|
|
61
|
+
// This is critical: when use() suspends during the initial render, React
|
|
62
|
+
// discards all uncommitted hook state (useRef, useState, useMemo).
|
|
63
|
+
// On retry, hooks reinitialize, and useMemo/useRef would create a new promise,
|
|
64
|
+
// causing an infinite suspend loop. The closure cache survives this.
|
|
65
|
+
// Active load state (current URL)
|
|
66
|
+
let activeUrlHref = null;
|
|
67
|
+
let activeCacheKey = null;
|
|
68
|
+
let activePromise = null;
|
|
69
|
+
let activeResolvedData = undefined;
|
|
70
|
+
let hasResolved = false;
|
|
71
|
+
let pendingBackgroundKey = null;
|
|
72
|
+
// LRU cache for previously visited URLs (url → resolved data)
|
|
73
|
+
const staleDataCache = new Map();
|
|
74
|
+
function evictStaleCache(maxSize) {
|
|
75
|
+
while (staleDataCache.size > maxSize) {
|
|
76
|
+
const first = staleDataCache.keys().next().value;
|
|
77
|
+
staleDataCache.delete(first);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
function BuzolaPage() {
|
|
81
|
+
const routeContext = use(RouteContext);
|
|
82
|
+
if (!routeContext) {
|
|
83
|
+
throw new Error('createPage component must be used within a <BuzolaProvider>');
|
|
84
|
+
}
|
|
85
|
+
const router = use(RouterContext);
|
|
86
|
+
const params = useMemo(() => {
|
|
87
|
+
const { state, matches, params: pathParams } = routeContext;
|
|
88
|
+
const currentMatch = matches.find(m => m.node.component === BuzolaPage);
|
|
89
|
+
const pathParamNames = new Set(currentMatch ? extractParamNames(currentMatch.node.fullPath) : []);
|
|
90
|
+
const merged = {};
|
|
91
|
+
if (arrayParams.size > 0) {
|
|
92
|
+
for (const name of arrayParams) {
|
|
93
|
+
if (pathParamNames.has(name))
|
|
94
|
+
continue;
|
|
95
|
+
const values = [
|
|
96
|
+
...state.location.searchParams.getAll(name),
|
|
97
|
+
...state.location.searchParams.getAll(`${name}[]`),
|
|
98
|
+
];
|
|
99
|
+
if (values.length > 0)
|
|
100
|
+
merged[name] = values;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
state.location.searchParams.forEach((value, key) => {
|
|
104
|
+
const cleanKey = key.endsWith('[]') ? key.slice(0, -2) : key;
|
|
105
|
+
if (!pathParamNames.has(cleanKey) && !(cleanKey in merged)) {
|
|
106
|
+
merged[cleanKey] = value;
|
|
107
|
+
}
|
|
108
|
+
});
|
|
109
|
+
for (const [key, value] of Object.entries(pathParams)) {
|
|
110
|
+
if (arrayParams.has(key)) {
|
|
111
|
+
merged[key] = value.split(',');
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
merged[key] = value;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
if (schema) {
|
|
118
|
+
const result = schema['~standard'].validate(merged);
|
|
119
|
+
if ('issues' in result) {
|
|
120
|
+
throw new Error(`Page params validation failed: ${result.issues.map(i => i.message).join(', ')}`);
|
|
121
|
+
}
|
|
122
|
+
return result.value;
|
|
123
|
+
}
|
|
124
|
+
return merged;
|
|
125
|
+
}, [routeContext]);
|
|
126
|
+
const [loaderKey, setLoaderKey] = useState(0);
|
|
127
|
+
const [, forceUpdate] = useReducer(x => x + 1, 0);
|
|
128
|
+
const invalidate = useCallback(() => setLoaderKey(k => k + 1), []);
|
|
129
|
+
// Subscribe to router-level invalidation
|
|
130
|
+
useEffect(() => {
|
|
131
|
+
if (!router)
|
|
132
|
+
return;
|
|
133
|
+
return router.onInvalidate(() => setLoaderKey(k => k + 1));
|
|
134
|
+
}, [router]);
|
|
135
|
+
const cacheSize = router?.loaderCacheSize ?? 0;
|
|
136
|
+
let data = undefined;
|
|
137
|
+
let isLoading = false;
|
|
138
|
+
if (loaderFn) {
|
|
139
|
+
const currentUrlHref = routeContext.state.location.href;
|
|
140
|
+
const cacheKey = `${currentUrlHref}:${loaderKey}`;
|
|
141
|
+
// URL changed — save old data to stale cache, restore from stale cache if available
|
|
142
|
+
if (activeUrlHref !== null && activeUrlHref !== currentUrlHref) {
|
|
143
|
+
if (hasResolved && activeResolvedData !== undefined) {
|
|
144
|
+
staleDataCache.set(activeUrlHref, activeResolvedData);
|
|
145
|
+
evictStaleCache(cacheSize);
|
|
146
|
+
}
|
|
147
|
+
if (staleDataCache.has(currentUrlHref)) {
|
|
148
|
+
activeResolvedData = staleDataCache.get(currentUrlHref);
|
|
149
|
+
staleDataCache.delete(currentUrlHref);
|
|
150
|
+
hasResolved = true;
|
|
151
|
+
}
|
|
152
|
+
else {
|
|
153
|
+
hasResolved = false;
|
|
154
|
+
activeResolvedData = undefined;
|
|
155
|
+
}
|
|
156
|
+
pendingBackgroundKey = null;
|
|
157
|
+
}
|
|
158
|
+
else if (activeUrlHref === null && staleDataCache.has(currentUrlHref)) {
|
|
159
|
+
// Remount — restore from stale cache
|
|
160
|
+
activeResolvedData = staleDataCache.get(currentUrlHref);
|
|
161
|
+
staleDataCache.delete(currentUrlHref);
|
|
162
|
+
hasResolved = true;
|
|
163
|
+
}
|
|
164
|
+
activeUrlHref = currentUrlHref;
|
|
165
|
+
if (activeCacheKey === cacheKey) {
|
|
166
|
+
// Cache hit — check if background load is pending
|
|
167
|
+
if (pendingBackgroundKey === cacheKey) {
|
|
168
|
+
data = activeResolvedData;
|
|
169
|
+
isLoading = true;
|
|
170
|
+
}
|
|
171
|
+
else {
|
|
172
|
+
// Either resolved or first-time suspend
|
|
173
|
+
if (hasResolved) {
|
|
174
|
+
data = activeResolvedData;
|
|
175
|
+
}
|
|
176
|
+
else {
|
|
177
|
+
data = use(activePromise);
|
|
178
|
+
activeResolvedData = data;
|
|
179
|
+
hasResolved = true;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
else if (hasResolved) {
|
|
184
|
+
// Cache key changed + we have stale data → background reload (SWR)
|
|
185
|
+
const promise = loaderFn({ params });
|
|
186
|
+
activeCacheKey = cacheKey;
|
|
187
|
+
activePromise = promise;
|
|
188
|
+
pendingBackgroundKey = cacheKey;
|
|
189
|
+
data = activeResolvedData;
|
|
190
|
+
isLoading = true;
|
|
191
|
+
promise.then((result) => {
|
|
192
|
+
// Only apply if this is still the active load
|
|
193
|
+
if (activeCacheKey === cacheKey) {
|
|
194
|
+
activeResolvedData = result;
|
|
195
|
+
pendingBackgroundKey = null;
|
|
196
|
+
forceUpdate();
|
|
197
|
+
}
|
|
198
|
+
}, (error) => {
|
|
199
|
+
// Store rejected promise so use() triggers ErrorBoundary
|
|
200
|
+
if (activeCacheKey === cacheKey) {
|
|
201
|
+
activePromise = promise;
|
|
202
|
+
hasResolved = false;
|
|
203
|
+
pendingBackgroundKey = null;
|
|
204
|
+
forceUpdate();
|
|
205
|
+
}
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
else {
|
|
209
|
+
// No stale data — first load, suspend via use()
|
|
210
|
+
const promise = loaderFn({ params });
|
|
211
|
+
activeCacheKey = cacheKey;
|
|
212
|
+
activePromise = promise;
|
|
213
|
+
data = use(promise);
|
|
214
|
+
activeResolvedData = data;
|
|
215
|
+
hasResolved = true;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
// On unmount, save active data to stale cache and reset active state
|
|
219
|
+
useEffect(() => {
|
|
220
|
+
return () => {
|
|
221
|
+
if (hasResolved && activeResolvedData !== undefined && activeUrlHref) {
|
|
222
|
+
staleDataCache.set(activeUrlHref, activeResolvedData);
|
|
223
|
+
evictStaleCache(cacheSize);
|
|
224
|
+
}
|
|
225
|
+
hasResolved = false;
|
|
226
|
+
activeResolvedData = undefined;
|
|
227
|
+
activeCacheKey = null;
|
|
228
|
+
activePromise = null;
|
|
229
|
+
pendingBackgroundKey = null;
|
|
230
|
+
activeUrlHref = null;
|
|
231
|
+
};
|
|
232
|
+
}, []);
|
|
233
|
+
return _jsx(RenderComponent, { params: params, data: data, invalidate: invalidate, isLoading: isLoading });
|
|
234
|
+
}
|
|
235
|
+
function BuzolaPageWithCatch() {
|
|
236
|
+
const routeContext = use(RouteContext);
|
|
237
|
+
const [retryCount, setRetryCount] = useState(0);
|
|
238
|
+
const retry = useCallback(() => setRetryCount(c => c + 1), []);
|
|
239
|
+
const resetKey = `${routeContext?.state.location.href ?? ''}:${retryCount}`;
|
|
240
|
+
const boundFallback = typeof catchHandler === 'function'
|
|
241
|
+
? (error) => catchHandler({ error, retry })
|
|
242
|
+
: catchHandler;
|
|
243
|
+
return (_jsx(ErrorBoundary, { fallback: boundFallback, resetKey: resetKey, children: _jsx(BuzolaPage, {}, retryCount) }));
|
|
244
|
+
}
|
|
245
|
+
const component = catchHandler ? BuzolaPageWithCatch : BuzolaPage;
|
|
246
|
+
return {
|
|
247
|
+
__buzolaPage: true,
|
|
248
|
+
component: component,
|
|
249
|
+
route: routePattern,
|
|
250
|
+
paramsSchema: schema,
|
|
251
|
+
paramsMeta,
|
|
252
|
+
loader: loaderFn,
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
function withCatchAndRender(schema, paramsMeta, loaders, catchHandler) {
|
|
256
|
+
return {
|
|
257
|
+
route(pattern) {
|
|
258
|
+
return {
|
|
259
|
+
render(fn) {
|
|
260
|
+
return createPageComponent(schema, paramsMeta, combineLoaders(loaders), pattern, fn, catchHandler);
|
|
261
|
+
},
|
|
262
|
+
};
|
|
263
|
+
},
|
|
264
|
+
render(fn) {
|
|
265
|
+
return createPageComponent(schema, paramsMeta, combineLoaders(loaders), undefined, fn, catchHandler);
|
|
266
|
+
},
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
function withRouteAndRender(schema, paramsMeta, loaders) {
|
|
270
|
+
return {
|
|
271
|
+
loader(loaderFn) {
|
|
272
|
+
return withRouteAndRender(schema, paramsMeta, [...loaders, loaderFn]);
|
|
273
|
+
},
|
|
274
|
+
catch(handler) {
|
|
275
|
+
return withCatchAndRender(schema, paramsMeta, loaders, handler);
|
|
276
|
+
},
|
|
277
|
+
route(pattern) {
|
|
278
|
+
return {
|
|
279
|
+
catch(handler) {
|
|
280
|
+
return {
|
|
281
|
+
render(fn) {
|
|
282
|
+
return createPageComponent(schema, paramsMeta, combineLoaders(loaders), pattern, fn, handler);
|
|
283
|
+
},
|
|
284
|
+
};
|
|
285
|
+
},
|
|
286
|
+
render(fn) {
|
|
287
|
+
return createPageComponent(schema, paramsMeta, combineLoaders(loaders), pattern, fn);
|
|
288
|
+
},
|
|
289
|
+
};
|
|
290
|
+
},
|
|
291
|
+
render(fn) {
|
|
292
|
+
return createPageComponent(schema, paramsMeta, combineLoaders(loaders), undefined, fn);
|
|
293
|
+
},
|
|
294
|
+
};
|
|
295
|
+
}
|
|
296
|
+
export function createPage() {
|
|
297
|
+
return {
|
|
298
|
+
params(input) {
|
|
299
|
+
const { schema, paramsMeta } = resolveParamsInput(input);
|
|
300
|
+
return withRouteAndRender(schema, paramsMeta, []);
|
|
301
|
+
},
|
|
302
|
+
...withRouteAndRender(undefined, [], []),
|
|
303
|
+
};
|
|
304
|
+
}
|
|
305
|
+
//# sourceMappingURL=create-page.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create-page.js","sourceRoot":"","sources":["../../src/define/create-page.tsx"],"names":[],"mappings":"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"}
|