@alepha/react 0.14.3 → 0.15.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 +10 -0
- package/dist/auth/index.browser.js +29 -14
- package/dist/auth/index.browser.js.map +1 -1
- package/dist/auth/index.d.ts +4 -4
- package/dist/auth/index.d.ts.map +1 -1
- package/dist/auth/index.js +950 -194
- package/dist/auth/index.js.map +1 -1
- package/dist/core/index.d.ts +118 -118
- package/dist/core/index.d.ts.map +1 -1
- package/dist/form/index.d.ts +27 -28
- package/dist/form/index.d.ts.map +1 -1
- package/dist/head/index.browser.js +59 -19
- package/dist/head/index.browser.js.map +1 -1
- package/dist/head/index.d.ts +105 -576
- package/dist/head/index.d.ts.map +1 -1
- package/dist/head/index.js +91 -87
- package/dist/head/index.js.map +1 -1
- package/dist/i18n/index.d.ts +33 -33
- package/dist/i18n/index.d.ts.map +1 -1
- package/dist/router/index.browser.js +30 -15
- package/dist/router/index.browser.js.map +1 -1
- package/dist/router/index.d.ts +827 -403
- package/dist/router/index.d.ts.map +1 -1
- package/dist/router/index.js +951 -195
- package/dist/router/index.js.map +1 -1
- package/dist/websocket/index.d.ts +38 -39
- package/dist/websocket/index.d.ts.map +1 -1
- package/package.json +5 -5
- package/src/auth/__tests__/$auth.spec.ts +10 -11
- package/src/core/__tests__/Router.spec.tsx +4 -4
- package/src/head/{__tests__/expandSeo.spec.ts → helpers/SeoExpander.spec.ts} +1 -1
- package/src/head/index.ts +10 -28
- package/src/head/providers/BrowserHeadProvider.browser.spec.ts +1 -76
- package/src/head/providers/BrowserHeadProvider.ts +25 -19
- package/src/head/providers/HeadProvider.ts +76 -10
- package/src/head/providers/ServerHeadProvider.ts +22 -138
- package/src/router/__tests__/page-head-browser.browser.spec.ts +91 -0
- package/src/router/__tests__/page-head.spec.ts +44 -0
- package/src/{head → router}/__tests__/seo-head.spec.ts +2 -2
- package/src/router/atoms/ssrManifestAtom.ts +60 -0
- package/src/router/constants/PAGE_PRELOAD_KEY.ts +6 -0
- package/src/router/errors/Redirection.ts +1 -1
- package/src/router/index.shared.ts +1 -0
- package/src/router/index.ts +16 -2
- package/src/router/primitives/$page.browser.spec.tsx +15 -15
- package/src/router/primitives/$page.spec.tsx +18 -18
- package/src/router/primitives/$page.ts +46 -10
- package/src/router/providers/ReactBrowserProvider.ts +14 -29
- package/src/router/providers/ReactBrowserRouterProvider.ts +5 -0
- package/src/router/providers/ReactPageProvider.ts +11 -4
- package/src/router/providers/ReactServerProvider.ts +321 -316
- package/src/router/providers/ReactServerTemplateProvider.ts +793 -0
- package/src/router/providers/SSRManifestProvider.ts +365 -0
- package/src/router/services/ReactPageServerService.ts +5 -3
- package/src/router/services/ReactRouter.ts +3 -3
- package/src/head/__tests__/page-head.spec.ts +0 -39
- package/src/head/providers/ServerHeadProvider.spec.ts +0 -163
package/dist/router/index.d.ts
CHANGED
|
@@ -1,21 +1,20 @@
|
|
|
1
1
|
import { ClientOnlyProps } from "@alepha/react";
|
|
2
|
-
import * as
|
|
2
|
+
import * as alepha1 from "alepha";
|
|
3
3
|
import { Alepha, AlephaError, Async, KIND, Primitive, Static, TObject, TSchema } from "alepha";
|
|
4
4
|
import { DateTimeProvider } from "alepha/datetime";
|
|
5
5
|
import * as alepha_logger0 from "alepha/logger";
|
|
6
6
|
import { LinkProvider } from "alepha/server/links";
|
|
7
|
+
import { BrowserHeadProvider, Head, ServerHeadProvider, SimpleHead } from "@alepha/react/head";
|
|
7
8
|
import { Route, RouterProvider } from "alepha/router";
|
|
8
9
|
import * as react0 from "react";
|
|
9
10
|
import { AnchorHTMLAttributes, CSSProperties, FC, ReactNode } from "react";
|
|
10
11
|
import * as react_jsx_runtime0 from "react/jsx-runtime";
|
|
11
|
-
import * as alepha_server0 from "alepha/server";
|
|
12
12
|
import { ServerHandler, ServerRequest, ServerRouterProvider, ServerTimingProvider } from "alepha/server";
|
|
13
|
+
import { FileSystemProvider } from "alepha/file";
|
|
13
14
|
import { ServerStaticProvider } from "alepha/server/static";
|
|
14
|
-
import * as alepha_server_cache0 from "alepha/server/cache";
|
|
15
15
|
import { ServerRouteCache } from "alepha/server/cache";
|
|
16
16
|
|
|
17
17
|
//#region ../../src/router/errors/Redirection.d.ts
|
|
18
|
-
|
|
19
18
|
/**
|
|
20
19
|
* Used for Redirection during the page loading.
|
|
21
20
|
*
|
|
@@ -26,7 +25,7 @@ import { ServerRouteCache } from "alepha/server/cache";
|
|
|
26
25
|
* import { Redirection } from "@alepha/react";
|
|
27
26
|
*
|
|
28
27
|
* const MyPage = $page({
|
|
29
|
-
*
|
|
28
|
+
* loader: async () => {
|
|
30
29
|
* if (needRedirect) {
|
|
31
30
|
* throw new Redirection("/new-path");
|
|
32
31
|
* }
|
|
@@ -40,11 +39,11 @@ declare class Redirection extends AlephaError {
|
|
|
40
39
|
}
|
|
41
40
|
//#endregion
|
|
42
41
|
//#region ../../src/router/providers/ReactPageProvider.d.ts
|
|
43
|
-
declare const envSchema$
|
|
44
|
-
REACT_STRICT_MODE:
|
|
42
|
+
declare const envSchema$1: alepha1.TObject<{
|
|
43
|
+
REACT_STRICT_MODE: alepha1.TBoolean;
|
|
45
44
|
}>;
|
|
46
45
|
declare module "alepha" {
|
|
47
|
-
interface Env extends Partial<Static<typeof envSchema$
|
|
46
|
+
interface Env extends Partial<Static<typeof envSchema$1>> {}
|
|
48
47
|
}
|
|
49
48
|
/**
|
|
50
49
|
* Handle page routes for React applications. (Browser and Server)
|
|
@@ -70,10 +69,10 @@ declare class ReactPageProvider {
|
|
|
70
69
|
root(state: ReactRouterState): ReactNode;
|
|
71
70
|
protected convertStringObjectToObject: (schema?: TSchema, value?: any) => any;
|
|
72
71
|
/**
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
72
|
+
* Create a new RouterState based on a given route and request.
|
|
73
|
+
* This method resolves the layers for the route, applying any query and params schemas defined in the route.
|
|
74
|
+
* It also handles errors and redirects.
|
|
75
|
+
*/
|
|
77
76
|
createLayers(route: PageRoute, state: ReactRouterState, previous?: PreviousLayerData[]): Promise<CreateLayersResult>;
|
|
78
77
|
protected getErrorHandler(route: PageRoute): ErrorHandler | undefined;
|
|
79
78
|
protected createElement(page: PageRoute, props: Record<string, any>): Promise<ReactNode>;
|
|
@@ -86,7 +85,7 @@ declare class ReactPageProvider {
|
|
|
86
85
|
}, params?: Record<string, any>): string;
|
|
87
86
|
compile(path: string, params?: Record<string, string>): string;
|
|
88
87
|
protected renderView(index: number, path: string, view: ReactNode | undefined, page: PageRoute): ReactNode;
|
|
89
|
-
protected readonly configure:
|
|
88
|
+
protected readonly configure: alepha1.HookPrimitive<"configure">;
|
|
90
89
|
protected map(pages: Array<PagePrimitive>, target: PagePrimitive): PageRouteEntry;
|
|
91
90
|
add(entry: PageRouteEntry): void;
|
|
92
91
|
protected createMatch(page: PageRoute): string;
|
|
@@ -99,9 +98,9 @@ interface PageRouteEntry extends Omit<PagePrimitiveOptions, "children" | "parent
|
|
|
99
98
|
}
|
|
100
99
|
interface ConcretePageRoute extends PageRoute {
|
|
101
100
|
/**
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
101
|
+
* When exported, static routes can be split into multiple pages with different params.
|
|
102
|
+
* We replace 'name' by the new name for each static entry, and old 'name' becomes 'staticName'.
|
|
103
|
+
*/
|
|
105
104
|
staticName?: string;
|
|
106
105
|
params?: Record<string, string>;
|
|
107
106
|
}
|
|
@@ -134,29 +133,34 @@ interface AnchorProps {
|
|
|
134
133
|
}
|
|
135
134
|
interface ReactRouterState {
|
|
136
135
|
/**
|
|
137
|
-
|
|
138
|
-
|
|
136
|
+
* Stack of layers for the current page.
|
|
137
|
+
*/
|
|
139
138
|
layers: Array<Layer>;
|
|
140
139
|
/**
|
|
141
|
-
|
|
142
|
-
|
|
140
|
+
* URL of the current page.
|
|
141
|
+
*/
|
|
143
142
|
url: URL;
|
|
144
143
|
/**
|
|
145
|
-
|
|
146
|
-
|
|
144
|
+
* Error handler for the current page.
|
|
145
|
+
*/
|
|
147
146
|
onError: ErrorHandler;
|
|
148
147
|
/**
|
|
149
|
-
|
|
150
|
-
|
|
148
|
+
* Params extracted from the URL for the current page.
|
|
149
|
+
*/
|
|
151
150
|
params: Record<string, any>;
|
|
152
151
|
/**
|
|
153
|
-
|
|
154
|
-
|
|
152
|
+
* Query parameters extracted from the URL for the current page.
|
|
153
|
+
*/
|
|
155
154
|
query: Record<string, string>;
|
|
156
155
|
/**
|
|
157
|
-
|
|
158
|
-
|
|
156
|
+
* Optional meta information associated with the current page.
|
|
157
|
+
*/
|
|
159
158
|
meta: Record<string, any>;
|
|
159
|
+
/**
|
|
160
|
+
* Head configuration for the current page (title, meta tags, etc.).
|
|
161
|
+
* Populated by HeadProvider during SSR.
|
|
162
|
+
*/
|
|
163
|
+
head: Head;
|
|
160
164
|
name?: string;
|
|
161
165
|
}
|
|
162
166
|
interface RouterStackItem {
|
|
@@ -186,6 +190,14 @@ declare abstract class ReactPageService {
|
|
|
186
190
|
render(name: string, options?: PagePrimitiveRenderOptions): Promise<PagePrimitiveRenderResult>;
|
|
187
191
|
}
|
|
188
192
|
//#endregion
|
|
193
|
+
//#region ../../src/router/constants/PAGE_PRELOAD_KEY.d.ts
|
|
194
|
+
/**
|
|
195
|
+
* Symbol key for SSR module preloading path.
|
|
196
|
+
* Using Symbol.for() allows the Vite plugin to inject this at build time.
|
|
197
|
+
* @internal
|
|
198
|
+
*/
|
|
199
|
+
declare const PAGE_PRELOAD_KEY: unique symbol;
|
|
200
|
+
//#endregion
|
|
189
201
|
//#region ../../src/router/primitives/$page.d.ts
|
|
190
202
|
/**
|
|
191
203
|
* Main primitive for defining a React route in the application.
|
|
@@ -199,7 +211,7 @@ declare abstract class ReactPageService {
|
|
|
199
211
|
* - Type-safe URL parameter and query string validation
|
|
200
212
|
*
|
|
201
213
|
* **Data Loading**
|
|
202
|
-
* - Server-side data fetching with the `
|
|
214
|
+
* - Server-side data fetching with the `loader` function
|
|
203
215
|
* - Automatic serialization and hydration for SSR
|
|
204
216
|
* - Access to request context, URL params, and parent data
|
|
205
217
|
*
|
|
@@ -236,7 +248,7 @@ declare abstract class ReactPageService {
|
|
|
236
248
|
* params: t.object({ id: t.integer() }),
|
|
237
249
|
* query: t.object({ tab: t.optional(t.text()) })
|
|
238
250
|
* },
|
|
239
|
-
*
|
|
251
|
+
* loader: async ({ params }) => {
|
|
240
252
|
* const user = await userApi.getUser(params.id);
|
|
241
253
|
* return { user };
|
|
242
254
|
* },
|
|
@@ -249,7 +261,7 @@ declare abstract class ReactPageService {
|
|
|
249
261
|
* const projectSection = $page({
|
|
250
262
|
* path: "/projects/:id",
|
|
251
263
|
* children: () => [projectBoard, projectSettings],
|
|
252
|
-
*
|
|
264
|
+
* loader: async ({ params }) => {
|
|
253
265
|
* const project = await projectApi.get(params.id);
|
|
254
266
|
* return { project };
|
|
255
267
|
* },
|
|
@@ -268,7 +280,7 @@ declare abstract class ReactPageService {
|
|
|
268
280
|
* static: {
|
|
269
281
|
* entries: posts.map(p => ({ params: { slug: p.slug } }))
|
|
270
282
|
* },
|
|
271
|
-
*
|
|
283
|
+
* loader: async ({ params }) => {
|
|
272
284
|
* const post = await loadPost(params.slug);
|
|
273
285
|
* return { post };
|
|
274
286
|
* }
|
|
@@ -281,184 +293,215 @@ declare const $page: {
|
|
|
281
293
|
};
|
|
282
294
|
interface PagePrimitiveOptions<TConfig extends PageConfigSchema = PageConfigSchema, TProps extends object = TPropsDefault, TPropsParent extends object = TPropsParentDefault> {
|
|
283
295
|
/**
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
296
|
+
* Identifier name for the page. Must be unique.
|
|
297
|
+
*
|
|
298
|
+
* @default Primitive key
|
|
299
|
+
*/
|
|
288
300
|
name?: string;
|
|
289
301
|
/**
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
302
|
+
* Add a pathname to the page.
|
|
303
|
+
*
|
|
304
|
+
* Pathname can contain parameters, like `/post/:slug`.
|
|
305
|
+
*
|
|
306
|
+
* @default ""
|
|
307
|
+
*/
|
|
296
308
|
path?: string;
|
|
297
309
|
/**
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
310
|
+
* Add an input schema to define:
|
|
311
|
+
* - `params`: parameters from the pathname.
|
|
312
|
+
* - `query`: query parameters from the URL.
|
|
313
|
+
*/
|
|
302
314
|
schema?: TConfig;
|
|
303
315
|
/**
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
/**
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
316
|
+
* Load data before rendering the page.
|
|
317
|
+
*
|
|
318
|
+
* This function receives
|
|
319
|
+
* - the request context (params, query, etc.)
|
|
320
|
+
* - the parent props (if page has a parent)
|
|
321
|
+
*
|
|
322
|
+
* > In SSR, the returned data will be serialized and sent to the client, then reused during the client-side hydration.
|
|
323
|
+
*
|
|
324
|
+
* Loader can be stopped by throwing an error, which will be handled by the `errorHandler` function.
|
|
325
|
+
* It's common to throw a `NotFoundError` to display a 404 page.
|
|
326
|
+
*
|
|
327
|
+
* RedirectError can be thrown to redirect the user to another page.
|
|
328
|
+
*/
|
|
329
|
+
loader?: (context: PageLoader<TConfig, TPropsParent>) => Async<TProps>;
|
|
330
|
+
/**
|
|
331
|
+
* Default props to pass to the component when rendering the page.
|
|
332
|
+
*
|
|
333
|
+
* Resolved props from the `resolve` function will override these default props.
|
|
334
|
+
*/
|
|
323
335
|
props?: () => Partial<TProps>;
|
|
324
336
|
/**
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
337
|
+
* The component to render when the page is loaded.
|
|
338
|
+
*
|
|
339
|
+
* If `lazy` is defined, this will be ignored.
|
|
340
|
+
* Prefer using `lazy` to improve the initial loading time.
|
|
341
|
+
*/
|
|
330
342
|
component?: FC<TProps & TPropsParent>;
|
|
331
343
|
/**
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
344
|
+
* Lazy load the component when the page is loaded.
|
|
345
|
+
*
|
|
346
|
+
* It's recommended to use this for components to improve the initial loading time
|
|
347
|
+
* and enable code-splitting.
|
|
348
|
+
*/
|
|
337
349
|
lazy?: () => Promise<{
|
|
338
350
|
default: FC<TProps & TPropsParent>;
|
|
339
351
|
}>;
|
|
340
352
|
/**
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
353
|
+
* Attach child pages to create nested routes.
|
|
354
|
+
* This will make the page a parent route.
|
|
355
|
+
*/
|
|
344
356
|
children?: Array<PagePrimitive> | (() => Array<PagePrimitive>);
|
|
345
357
|
/**
|
|
346
|
-
|
|
347
|
-
|
|
358
|
+
* Define a parent page for nested routing.
|
|
359
|
+
*/
|
|
348
360
|
parent?: PagePrimitive<PageConfigSchema, TPropsParent, any>;
|
|
349
361
|
/**
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
362
|
+
* Function to determine if the page can be accessed.
|
|
363
|
+
*
|
|
364
|
+
* If it returns false, the page will not be accessible and a 403 Forbidden error will be returned.
|
|
365
|
+
* This function can be used to implement permission-based access control.
|
|
366
|
+
*/
|
|
355
367
|
can?: () => boolean;
|
|
356
368
|
/**
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
369
|
+
* Catch any error from the `loader` function or during `rendering`.
|
|
370
|
+
*
|
|
371
|
+
* Expected to return one of the following:
|
|
372
|
+
* - a ReactNode to render an error page
|
|
373
|
+
* - a Redirection to redirect the user
|
|
374
|
+
* - undefined to let the error propagate
|
|
375
|
+
*
|
|
376
|
+
* If not defined, the error will be thrown and handled by the server or client error handler.
|
|
377
|
+
* If a leaf $page does not define an error handler, the error can be caught by parent pages.
|
|
378
|
+
*
|
|
379
|
+
* @example Catch a 404 from API and render a custom not found component:
|
|
380
|
+
* ```ts
|
|
381
|
+
* loader: async ({ params, query }) => {
|
|
382
|
+
* api.fetch("/api/resource", { params, query });
|
|
383
|
+
* },
|
|
384
|
+
* errorHandler: (error, context) => {
|
|
385
|
+
* if (HttpError.is(error, 404)) {
|
|
386
|
+
* return <ResourceNotFound />;
|
|
387
|
+
* }
|
|
388
|
+
* }
|
|
389
|
+
* ```
|
|
390
|
+
*
|
|
391
|
+
* @example Catch an 401 error and redirect the user to the login page:
|
|
392
|
+
* ```ts
|
|
393
|
+
* loader: async ({ params, query }) => {
|
|
394
|
+
* // but the user is not authenticated
|
|
395
|
+
* api.fetch("/api/resource", { params, query });
|
|
396
|
+
* },
|
|
397
|
+
* errorHandler: (error, context) => {
|
|
398
|
+
* if (HttpError.is(error, 401)) {
|
|
399
|
+
* // throwing a Redirection is also valid!
|
|
400
|
+
* return new Redirection("/login");
|
|
401
|
+
* }
|
|
402
|
+
* }
|
|
403
|
+
* ```
|
|
404
|
+
*/
|
|
393
405
|
errorHandler?: ErrorHandler;
|
|
394
406
|
/**
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
407
|
+
* If true, the page will be considered as a static page, immutable and cacheable.
|
|
408
|
+
* Replace boolean by an object to define static entries. (e.g. list of params/query)
|
|
409
|
+
*
|
|
410
|
+
* Browser-side: it only works with `alepha/vite`, which can pre-render the page at build time.
|
|
411
|
+
*
|
|
412
|
+
* Server-side: It will act as timeless cached page. You can use `cache` to configure the cache behavior.
|
|
413
|
+
*/
|
|
402
414
|
static?: boolean | {
|
|
403
415
|
entries?: Array<Partial<PageRequestConfig<TConfig>>>;
|
|
404
416
|
};
|
|
405
417
|
cache?: ServerRouteCache;
|
|
406
418
|
/**
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
419
|
+
* If true, force the page to be rendered only on the client-side (browser).
|
|
420
|
+
* It uses the `<ClientOnly/>` component to render the page.
|
|
421
|
+
*/
|
|
410
422
|
client?: boolean | ClientOnlyProps;
|
|
411
423
|
/**
|
|
412
|
-
|
|
413
|
-
|
|
424
|
+
* Called before the server response is sent to the client. (server only)
|
|
425
|
+
*/
|
|
414
426
|
onServerResponse?: (request: ServerRequest) => unknown;
|
|
415
427
|
/**
|
|
416
|
-
|
|
417
|
-
|
|
428
|
+
* Called when user leaves the page. (browser only)
|
|
429
|
+
*/
|
|
418
430
|
onLeave?: () => void;
|
|
419
431
|
/**
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
432
|
+
* @experimental
|
|
433
|
+
*
|
|
434
|
+
* Add a css animation when the page is loaded or unloaded.
|
|
435
|
+
* It uses CSS animations, so you need to define the keyframes in your CSS.
|
|
436
|
+
*
|
|
437
|
+
* @example Simple animation name
|
|
438
|
+
* ```ts
|
|
439
|
+
* animation: "fadeIn"
|
|
440
|
+
* ```
|
|
441
|
+
*
|
|
442
|
+
* CSS example:
|
|
443
|
+
* ```css
|
|
444
|
+
* @keyframes fadeIn {
|
|
445
|
+
* from { opacity: 0; }
|
|
446
|
+
* to { opacity: 1; }
|
|
447
|
+
* }
|
|
448
|
+
* ```
|
|
449
|
+
*
|
|
450
|
+
* @example Detailed animation
|
|
451
|
+
* ```ts
|
|
452
|
+
* animation: {
|
|
453
|
+
* enter: { name: "fadeIn", duration: 300 },
|
|
454
|
+
* exit: { name: "fadeOut", duration: 200, timing: "ease-in-out" },
|
|
455
|
+
* }
|
|
456
|
+
* ```
|
|
457
|
+
*
|
|
458
|
+
* @example Only exit animation
|
|
459
|
+
* ```ts
|
|
460
|
+
* animation: {
|
|
461
|
+
* exit: "fadeOut"
|
|
462
|
+
* }
|
|
463
|
+
* ```
|
|
464
|
+
*
|
|
465
|
+
* @example With custom timing function
|
|
466
|
+
* ```ts
|
|
467
|
+
* animation: {
|
|
468
|
+
* enter: { name: "fadeIn", duration: 300, timing: "cubic-bezier(0.4, 0, 0.2, 1)" },
|
|
469
|
+
* exit: { name: "fadeOut", duration: 200, timing: "ease-in-out" },
|
|
470
|
+
* }
|
|
471
|
+
* ```
|
|
472
|
+
*/
|
|
461
473
|
animation?: PageAnimation;
|
|
474
|
+
/**
|
|
475
|
+
* Head configuration for the page (title, meta tags, etc.).
|
|
476
|
+
*
|
|
477
|
+
* Can be a static object or a function that receives resolved props.
|
|
478
|
+
*
|
|
479
|
+
* @example Static head
|
|
480
|
+
* ```ts
|
|
481
|
+
* head: {
|
|
482
|
+
* title: "My Page",
|
|
483
|
+
* description: "Page description",
|
|
484
|
+
* }
|
|
485
|
+
* ```
|
|
486
|
+
*
|
|
487
|
+
* @example Dynamic head based on props
|
|
488
|
+
* ```ts
|
|
489
|
+
* head: (props) => ({
|
|
490
|
+
* title: props.user.name,
|
|
491
|
+
* description: `Profile of ${props.user.name}`,
|
|
492
|
+
* })
|
|
493
|
+
* ```
|
|
494
|
+
*/
|
|
495
|
+
head?: Head | ((props: TProps, previous?: Head) => Head);
|
|
496
|
+
/**
|
|
497
|
+
* Source path for SSR module preloading.
|
|
498
|
+
*
|
|
499
|
+
* This is automatically injected by the viteAlephaPreload plugin.
|
|
500
|
+
* It maps to the source file path used in Vite's SSR manifest.
|
|
501
|
+
*
|
|
502
|
+
* @internal
|
|
503
|
+
*/
|
|
504
|
+
[PAGE_PRELOAD_KEY]?: string;
|
|
462
505
|
}
|
|
463
506
|
type ErrorHandler = (error: Error, state: ReactRouterState) => ReactNode | Redirection | undefined;
|
|
464
507
|
declare class PagePrimitive<TConfig extends PageConfigSchema = PageConfigSchema, TProps extends object = TPropsDefault, TPropsParent extends object = TPropsParentDefault> extends Primitive<PagePrimitiveOptions<TConfig, TProps, TPropsParent>> {
|
|
@@ -466,11 +509,11 @@ declare class PagePrimitive<TConfig extends PageConfigSchema = PageConfigSchema,
|
|
|
466
509
|
protected onInit(): void;
|
|
467
510
|
get name(): string;
|
|
468
511
|
/**
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
512
|
+
* For testing or build purposes.
|
|
513
|
+
*
|
|
514
|
+
* This will render the page (HTML layout included or not) and return the HTML + context.
|
|
515
|
+
* Only valid for server-side rendering, it will throw an error if called on the client-side.
|
|
516
|
+
*/
|
|
474
517
|
render(options?: PagePrimitiveRenderOptions): Promise<PagePrimitiveRenderResult>;
|
|
475
518
|
fetch(options?: PagePrimitiveRenderOptions): Promise<{
|
|
476
519
|
html: string;
|
|
@@ -489,11 +532,11 @@ interface PagePrimitiveRenderOptions {
|
|
|
489
532
|
params?: Record<string, string>;
|
|
490
533
|
query?: Record<string, string>;
|
|
491
534
|
/**
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
535
|
+
* If true, the HTML layout will be included in the response.
|
|
536
|
+
* If false, only the page content will be returned.
|
|
537
|
+
*
|
|
538
|
+
* @default true
|
|
539
|
+
*/
|
|
497
540
|
html?: boolean;
|
|
498
541
|
hydration?: boolean;
|
|
499
542
|
}
|
|
@@ -506,7 +549,7 @@ interface PageRequestConfig<TConfig extends PageConfigSchema = PageConfigSchema>
|
|
|
506
549
|
params: TConfig["params"] extends TSchema ? Static<TConfig["params"]> : Record<string, string>;
|
|
507
550
|
query: TConfig["query"] extends TSchema ? Static<TConfig["query"]> : Record<string, string>;
|
|
508
551
|
}
|
|
509
|
-
type
|
|
552
|
+
type PageLoader<TConfig extends PageConfigSchema = PageConfigSchema, TPropsParent extends object = TPropsParentDefault> = PageRequestConfig<TConfig> & TPropsParent & Omit<ReactRouterState, "layers" | "onError">;
|
|
510
553
|
type PageAnimation = PageAnimationObject | ((state: ReactRouterState) => PageAnimationObject | undefined);
|
|
511
554
|
type PageAnimationObject = CssAnimationName | {
|
|
512
555
|
enter?: CssAnimation | CssAnimationName;
|
|
@@ -530,67 +573,13 @@ declare class ReactBrowserRouterProvider extends RouterProvider<BrowserRoute> {
|
|
|
530
573
|
protected readonly log: alepha_logger0.Logger;
|
|
531
574
|
protected readonly alepha: Alepha;
|
|
532
575
|
protected readonly pageApi: ReactPageProvider;
|
|
576
|
+
protected readonly browserHeadProvider: BrowserHeadProvider;
|
|
533
577
|
add(entry: PageRouteEntry): void;
|
|
534
|
-
protected readonly configure:
|
|
578
|
+
protected readonly configure: alepha1.HookPrimitive<"configure">;
|
|
535
579
|
transition(url: URL, previous?: PreviousLayerData[], meta?: {}): Promise<string | void>;
|
|
536
580
|
root(state: ReactRouterState): ReactNode;
|
|
537
581
|
}
|
|
538
582
|
//#endregion
|
|
539
|
-
//#region ../../src/core/components/ClientOnly.d.ts
|
|
540
|
-
interface ClientOnlyProps$1 {
|
|
541
|
-
fallback?: ReactNode;
|
|
542
|
-
disabled?: boolean;
|
|
543
|
-
}
|
|
544
|
-
//#endregion
|
|
545
|
-
//#region ../../src/core/index.d.ts
|
|
546
|
-
declare module "alepha" {
|
|
547
|
-
interface Hooks {
|
|
548
|
-
/**
|
|
549
|
-
* Fires when a user action is starting.
|
|
550
|
-
* Action can be a form submission, a route transition, or a custom action.
|
|
551
|
-
*/
|
|
552
|
-
"react:action:begin": {
|
|
553
|
-
type: string;
|
|
554
|
-
id?: string;
|
|
555
|
-
};
|
|
556
|
-
/**
|
|
557
|
-
* Fires when a user action has succeeded.
|
|
558
|
-
* Action can be a form submission, a route transition, or a custom action.
|
|
559
|
-
*/
|
|
560
|
-
"react:action:success": {
|
|
561
|
-
type: string;
|
|
562
|
-
id?: string;
|
|
563
|
-
};
|
|
564
|
-
/**
|
|
565
|
-
* Fires when a user action has failed.
|
|
566
|
-
* Action can be a form submission, a route transition, or a custom action.
|
|
567
|
-
*/
|
|
568
|
-
"react:action:error": {
|
|
569
|
-
type: string;
|
|
570
|
-
id?: string;
|
|
571
|
-
error: Error;
|
|
572
|
-
};
|
|
573
|
-
/**
|
|
574
|
-
* Fires when a user action has completed, regardless of success or failure.
|
|
575
|
-
* Action can be a form submission, a route transition, or a custom action.
|
|
576
|
-
*/
|
|
577
|
-
"react:action:end": {
|
|
578
|
-
type: string;
|
|
579
|
-
id?: string;
|
|
580
|
-
};
|
|
581
|
-
}
|
|
582
|
-
}
|
|
583
|
-
/**
|
|
584
|
-
* Provides full-stack React development with declarative routing, server-side rendering, and client-side hydration.
|
|
585
|
-
*
|
|
586
|
-
* The React module enables building modern React applications using the `$page` primitive on class properties.
|
|
587
|
-
* It delivers seamless server-side rendering, automatic code splitting, and client-side navigation with full
|
|
588
|
-
* type safety and schema validation for route parameters and data.
|
|
589
|
-
*
|
|
590
|
-
* @see {@link $page}
|
|
591
|
-
* @module alepha.react
|
|
592
|
-
*/
|
|
593
|
-
//#endregion
|
|
594
583
|
//#region ../../src/router/services/ReactRouter.d.ts
|
|
595
584
|
interface RouterGoOptions {
|
|
596
585
|
replace?: boolean;
|
|
@@ -598,8 +587,8 @@ interface RouterGoOptions {
|
|
|
598
587
|
query?: Record<string, string>;
|
|
599
588
|
meta?: Record<string, any>;
|
|
600
589
|
/**
|
|
601
|
-
|
|
602
|
-
|
|
590
|
+
* Recreate the whole page, ignoring the current state.
|
|
591
|
+
*/
|
|
603
592
|
force?: boolean;
|
|
604
593
|
}
|
|
605
594
|
/**
|
|
@@ -607,7 +596,7 @@ interface RouterGoOptions {
|
|
|
607
596
|
*
|
|
608
597
|
* Can be safely used server-side, but most methods will be no-op.
|
|
609
598
|
*/
|
|
610
|
-
declare class ReactRouter<T
|
|
599
|
+
declare class ReactRouter<T extends object> {
|
|
611
600
|
protected readonly alepha: Alepha;
|
|
612
601
|
protected readonly pageApi: ReactPageProvider;
|
|
613
602
|
get state(): ReactRouterState;
|
|
@@ -617,69 +606,18 @@ declare class ReactRouter<T$1 extends object> {
|
|
|
617
606
|
isActive(href: string, options?: {
|
|
618
607
|
startWith?: boolean;
|
|
619
608
|
}): boolean;
|
|
620
|
-
node(name: keyof VirtualRouter<T
|
|
609
|
+
node(name: keyof VirtualRouter<T> | string, config?: {
|
|
621
610
|
params?: Record<string, any>;
|
|
622
611
|
query?: Record<string, any>;
|
|
623
|
-
}):
|
|
624
|
-
|
|
625
|
-
children: undefined;
|
|
626
|
-
type: "page";
|
|
627
|
-
name: string;
|
|
628
|
-
parent?: PageRoute;
|
|
629
|
-
match: string;
|
|
630
|
-
path?: string | undefined;
|
|
631
|
-
schema?: PageConfigSchema | undefined;
|
|
632
|
-
resolve?: ((context: PageResolve<PageConfigSchema, TPropsParentDefault>) => any) | undefined;
|
|
633
|
-
props?: (() => Partial<any>) | undefined;
|
|
634
|
-
component?: react0.FC<any> | undefined;
|
|
635
|
-
lazy?: (() => Promise<{
|
|
636
|
-
default: react0.FC<any>;
|
|
637
|
-
}>) | undefined;
|
|
638
|
-
can?: (() => boolean) | undefined;
|
|
639
|
-
errorHandler?: ErrorHandler | undefined;
|
|
640
|
-
static?: boolean | {
|
|
641
|
-
entries?: Partial<PageRequestConfig<PageConfigSchema>>[] | undefined;
|
|
642
|
-
} | undefined;
|
|
643
|
-
cache?: alepha_server_cache0.ServerRouteCache | undefined;
|
|
644
|
-
client?: (boolean | ClientOnlyProps$1) | undefined;
|
|
645
|
-
onServerResponse?: ((request: alepha_server0.ServerRequest) => unknown) | undefined;
|
|
646
|
-
onLeave?: (() => void) | undefined;
|
|
647
|
-
animation?: PageAnimation | undefined;
|
|
648
|
-
} | {
|
|
649
|
-
label: any;
|
|
650
|
-
href: string;
|
|
651
|
-
children: undefined;
|
|
652
|
-
type: "page";
|
|
653
|
-
name: string;
|
|
654
|
-
parent?: PageRoute;
|
|
655
|
-
match: string;
|
|
656
|
-
path?: string | undefined;
|
|
657
|
-
schema?: PageConfigSchema | undefined;
|
|
658
|
-
resolve?: ((context: PageResolve<PageConfigSchema, TPropsParentDefault>) => any) | undefined;
|
|
659
|
-
props?: (() => Partial<any>) | undefined;
|
|
660
|
-
component?: react0.FC<any> | undefined;
|
|
661
|
-
lazy?: (() => Promise<{
|
|
662
|
-
default: react0.FC<any>;
|
|
663
|
-
}>) | undefined;
|
|
664
|
-
can?: (() => boolean) | undefined;
|
|
665
|
-
errorHandler?: ErrorHandler | undefined;
|
|
666
|
-
static?: boolean | {
|
|
667
|
-
entries?: Partial<PageRequestConfig<PageConfigSchema>>[] | undefined;
|
|
668
|
-
} | undefined;
|
|
669
|
-
cache?: alepha_server_cache0.ServerRouteCache | undefined;
|
|
670
|
-
client?: (boolean | ClientOnlyProps$1) | undefined;
|
|
671
|
-
onServerResponse?: ((request: alepha_server0.ServerRequest) => unknown) | undefined;
|
|
672
|
-
onLeave?: (() => void) | undefined;
|
|
673
|
-
animation?: PageAnimation | undefined;
|
|
674
|
-
};
|
|
675
|
-
path(name: keyof VirtualRouter<T$1> | string, config?: {
|
|
612
|
+
}): any;
|
|
613
|
+
path(name: keyof VirtualRouter<T> | string, config?: {
|
|
676
614
|
params?: Record<string, any>;
|
|
677
615
|
query?: Record<string, any>;
|
|
678
616
|
}): string;
|
|
679
617
|
/**
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
618
|
+
* Reload the current page.
|
|
619
|
+
* This is equivalent to calling `go()` with the current pathname and search.
|
|
620
|
+
*/
|
|
683
621
|
reload(): Promise<void>;
|
|
684
622
|
getURL(): URL;
|
|
685
623
|
get location(): Location;
|
|
@@ -690,37 +628,31 @@ declare class ReactRouter<T$1 extends object> {
|
|
|
690
628
|
forward(): Promise<void>;
|
|
691
629
|
invalidate(props?: Record<string, any>): Promise<void>;
|
|
692
630
|
go(path: string, options?: RouterGoOptions): Promise<void>;
|
|
693
|
-
go(path: keyof VirtualRouter<T
|
|
631
|
+
go(path: keyof VirtualRouter<T>, options?: RouterGoOptions): Promise<void>;
|
|
694
632
|
anchor(path: string, options?: RouterGoOptions): AnchorProps;
|
|
695
|
-
anchor(path: keyof VirtualRouter<T
|
|
633
|
+
anchor(path: keyof VirtualRouter<T>, options?: RouterGoOptions): AnchorProps;
|
|
696
634
|
base(path: string): string;
|
|
697
635
|
/**
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
636
|
+
* Set query params.
|
|
637
|
+
*
|
|
638
|
+
* @param record
|
|
639
|
+
* @param options
|
|
640
|
+
*/
|
|
703
641
|
setQueryParams(record: Record<string, any> | ((queryParams: Record<string, any>) => Record<string, any>), options?: {
|
|
704
642
|
/**
|
|
705
|
-
|
|
706
|
-
|
|
643
|
+
* If true, this will add a new entry to the history stack.
|
|
644
|
+
*/
|
|
707
645
|
push?: boolean;
|
|
708
646
|
}): void;
|
|
709
647
|
}
|
|
710
|
-
type VirtualRouter<T
|
|
648
|
+
type VirtualRouter<T> = { [K in keyof T as T[K] extends PagePrimitive ? K : never]: T[K] };
|
|
711
649
|
//#endregion
|
|
712
650
|
//#region ../../src/router/providers/ReactBrowserProvider.d.ts
|
|
713
|
-
declare const envSchema$1: alepha12.TObject<{
|
|
714
|
-
REACT_ROOT_ID: alepha12.TString;
|
|
715
|
-
}>;
|
|
716
|
-
declare module "alepha" {
|
|
717
|
-
interface Env extends Partial<Static<typeof envSchema$1>> {}
|
|
718
|
-
}
|
|
719
651
|
/**
|
|
720
652
|
* React browser renderer configuration atom
|
|
721
653
|
*/
|
|
722
|
-
declare const reactBrowserOptions:
|
|
723
|
-
scrollRestoration:
|
|
654
|
+
declare const reactBrowserOptions: alepha1.Atom<alepha1.TObject<{
|
|
655
|
+
scrollRestoration: alepha1.TUnsafe<"top" | "manual">;
|
|
724
656
|
}>, "alepha.react.browser.options">;
|
|
725
657
|
type ReactBrowserRendererOptions = Static<typeof reactBrowserOptions.schema>;
|
|
726
658
|
declare module "alepha" {
|
|
@@ -729,17 +661,16 @@ declare module "alepha" {
|
|
|
729
661
|
}
|
|
730
662
|
}
|
|
731
663
|
declare class ReactBrowserProvider {
|
|
732
|
-
protected readonly env: {
|
|
733
|
-
REACT_ROOT_ID: string;
|
|
734
|
-
};
|
|
735
664
|
protected readonly log: alepha_logger0.Logger;
|
|
736
665
|
protected readonly client: LinkProvider;
|
|
737
666
|
protected readonly alepha: Alepha;
|
|
738
667
|
protected readonly router: ReactBrowserRouterProvider;
|
|
739
668
|
protected readonly dateTimeProvider: DateTimeProvider;
|
|
669
|
+
protected readonly browserHeadProvider: BrowserHeadProvider;
|
|
740
670
|
protected readonly options: Readonly<{
|
|
741
671
|
scrollRestoration: "top" | "manual";
|
|
742
672
|
}>;
|
|
673
|
+
get rootId(): string;
|
|
743
674
|
protected getRootElement(): HTMLElement;
|
|
744
675
|
transitioning?: {
|
|
745
676
|
to: string;
|
|
@@ -747,16 +678,16 @@ declare class ReactBrowserProvider {
|
|
|
747
678
|
};
|
|
748
679
|
get state(): ReactRouterState;
|
|
749
680
|
/**
|
|
750
|
-
|
|
751
|
-
|
|
681
|
+
* Accessor for Document DOM API.
|
|
682
|
+
*/
|
|
752
683
|
get document(): Document;
|
|
753
684
|
/**
|
|
754
|
-
|
|
755
|
-
|
|
685
|
+
* Accessor for History DOM API.
|
|
686
|
+
*/
|
|
756
687
|
get history(): History;
|
|
757
688
|
/**
|
|
758
|
-
|
|
759
|
-
|
|
689
|
+
* Accessor for Location DOM API.
|
|
690
|
+
*/
|
|
760
691
|
get location(): Location;
|
|
761
692
|
get base(): string;
|
|
762
693
|
get url(): string;
|
|
@@ -765,11 +696,11 @@ declare class ReactBrowserProvider {
|
|
|
765
696
|
go(url: string, options?: RouterGoOptions): Promise<void>;
|
|
766
697
|
protected render(options?: RouterRenderOptions): Promise<void>;
|
|
767
698
|
/**
|
|
768
|
-
|
|
769
|
-
|
|
699
|
+
* Get embedded layers from the server.
|
|
700
|
+
*/
|
|
770
701
|
protected getHydrationState(): ReactHydrationState | undefined;
|
|
771
|
-
protected readonly onTransitionEnd:
|
|
772
|
-
readonly ready:
|
|
702
|
+
protected readonly onTransitionEnd: alepha1.HookPrimitive<"react:transition:end">;
|
|
703
|
+
readonly ready: alepha1.HookPrimitive<"ready">;
|
|
773
704
|
}
|
|
774
705
|
type ReactHydrationState = {
|
|
775
706
|
layers?: Array<PreviousLayerData>;
|
|
@@ -1138,7 +1069,7 @@ interface UseActiveHook {
|
|
|
1138
1069
|
/**
|
|
1139
1070
|
* Hook to manage query parameters in the URL using a defined schema.
|
|
1140
1071
|
*/
|
|
1141
|
-
declare const useQueryParams: <T
|
|
1072
|
+
declare const useQueryParams: <T extends TObject>(schema: T, options?: UseQueryParamsHookOptions) => [Partial<Static<T>>, (data: Static<T>) => void];
|
|
1142
1073
|
interface UseQueryParamsHookOptions {
|
|
1143
1074
|
format?: "base64" | "querystring";
|
|
1144
1075
|
key?: string;
|
|
@@ -1160,57 +1091,484 @@ interface UseQueryParamsHookOptions {
|
|
|
1160
1091
|
* const router = useRouter<App>();
|
|
1161
1092
|
* router.go("home"); // typesafe
|
|
1162
1093
|
*/
|
|
1163
|
-
declare const useRouter: <T
|
|
1094
|
+
declare const useRouter: <T extends object = any>() => ReactRouter<T>;
|
|
1164
1095
|
//#endregion
|
|
1165
1096
|
//#region ../../src/router/hooks/useRouterState.d.ts
|
|
1166
1097
|
declare const useRouterState: () => ReactRouterState;
|
|
1167
1098
|
//#endregion
|
|
1168
|
-
//#region ../../src/router/providers/
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1099
|
+
//#region ../../src/router/providers/ReactServerTemplateProvider.d.ts
|
|
1100
|
+
/**
|
|
1101
|
+
* Handles HTML template parsing, preprocessing, and streaming for SSR.
|
|
1102
|
+
*
|
|
1103
|
+
* Responsibilities:
|
|
1104
|
+
* - Parse template once at startup into logical slots
|
|
1105
|
+
* - Pre-encode static parts as Uint8Array for zero-copy streaming
|
|
1106
|
+
* - Render dynamic parts (attributes, head content) efficiently
|
|
1107
|
+
* - Build hydration data for client-side rehydration
|
|
1108
|
+
*
|
|
1109
|
+
* This provider is injected into ReactServerProvider to handle all
|
|
1110
|
+
* template-related operations, keeping ReactServerProvider focused
|
|
1111
|
+
* on request handling and React rendering coordination.
|
|
1112
|
+
*/
|
|
1113
|
+
declare class ReactServerTemplateProvider {
|
|
1114
|
+
protected readonly log: alepha_logger0.Logger;
|
|
1115
|
+
protected readonly alepha: Alepha;
|
|
1116
|
+
/**
|
|
1117
|
+
* Shared TextEncoder instance - reused across all requests.
|
|
1118
|
+
*/
|
|
1119
|
+
protected readonly encoder: TextEncoder;
|
|
1120
|
+
/**
|
|
1121
|
+
* Pre-encoded common strings for streaming.
|
|
1122
|
+
*/
|
|
1123
|
+
protected readonly ENCODED: {
|
|
1124
|
+
readonly HYDRATION_PREFIX: Uint8Array<ArrayBuffer>;
|
|
1125
|
+
readonly HYDRATION_SUFFIX: Uint8Array<ArrayBuffer>;
|
|
1126
|
+
readonly EMPTY: Uint8Array<ArrayBuffer>;
|
|
1127
|
+
};
|
|
1128
|
+
/**
|
|
1129
|
+
* Cached template slots - parsed once, reused for all requests.
|
|
1130
|
+
*/
|
|
1131
|
+
protected slots: TemplateSlots | null;
|
|
1132
|
+
/**
|
|
1133
|
+
* Root element ID for React mounting.
|
|
1134
|
+
*/
|
|
1135
|
+
get rootId(): string;
|
|
1136
|
+
/**
|
|
1137
|
+
* Regex pattern for matching the root div and extracting its content.
|
|
1138
|
+
*/
|
|
1139
|
+
get rootDivRegex(): RegExp;
|
|
1140
|
+
/**
|
|
1141
|
+
* Extract the content inside the root div from HTML.
|
|
1142
|
+
*
|
|
1143
|
+
* @param html - Full HTML string
|
|
1144
|
+
* @returns The content inside the root div, or undefined if not found
|
|
1145
|
+
*/
|
|
1146
|
+
extractRootContent(html: string): string | undefined;
|
|
1147
|
+
/**
|
|
1148
|
+
* Check if template has been parsed and slots are available.
|
|
1149
|
+
*/
|
|
1150
|
+
isReady(): boolean;
|
|
1151
|
+
/**
|
|
1152
|
+
* Get the parsed template slots.
|
|
1153
|
+
* Throws if template hasn't been parsed yet.
|
|
1154
|
+
*/
|
|
1155
|
+
getSlots(): TemplateSlots;
|
|
1156
|
+
/**
|
|
1157
|
+
* Parse an HTML template into logical slots for efficient streaming.
|
|
1158
|
+
*
|
|
1159
|
+
* This should be called once during server startup/configuration.
|
|
1160
|
+
* The parsed slots are cached and reused for all requests.
|
|
1161
|
+
*
|
|
1162
|
+
* @param template - The HTML template string (typically index.html)
|
|
1163
|
+
*/
|
|
1164
|
+
parseTemplate(template: string): TemplateSlots;
|
|
1165
|
+
/**
|
|
1166
|
+
* Parse HTML attributes string into a record.
|
|
1167
|
+
*
|
|
1168
|
+
* Handles: key="value", key='value', key=value, and boolean key
|
|
1169
|
+
*/
|
|
1170
|
+
protected parseAttributes(attrStr: string): Record<string, string>;
|
|
1171
|
+
/**
|
|
1172
|
+
* Render attributes record to HTML string.
|
|
1173
|
+
*
|
|
1174
|
+
* @param attrs - Attributes to render
|
|
1175
|
+
* @returns HTML attribute string like ` lang="en" class="dark"`
|
|
1176
|
+
*/
|
|
1177
|
+
renderAttributes(attrs: Record<string, string>): string;
|
|
1178
|
+
/**
|
|
1179
|
+
* Render merged HTML attributes (original + dynamic).
|
|
1180
|
+
*/
|
|
1181
|
+
renderMergedHtmlAttrs(dynamicAttrs?: Record<string, string>): string;
|
|
1182
|
+
/**
|
|
1183
|
+
* Render merged body attributes (original + dynamic).
|
|
1184
|
+
*/
|
|
1185
|
+
renderMergedBodyAttrs(dynamicAttrs?: Record<string, string>): string;
|
|
1186
|
+
/**
|
|
1187
|
+
* Render head content (title, meta, link, script tags).
|
|
1188
|
+
*
|
|
1189
|
+
* @param head - Head data to render
|
|
1190
|
+
* @param includeOriginal - Whether to include original head content
|
|
1191
|
+
* @returns HTML string with head content
|
|
1192
|
+
*/
|
|
1193
|
+
renderHeadContent(head?: SimpleHead, includeOriginal?: boolean): string;
|
|
1194
|
+
/**
|
|
1195
|
+
* Render a meta tag.
|
|
1196
|
+
*/
|
|
1197
|
+
protected renderMetaTag(meta: {
|
|
1198
|
+
name?: string;
|
|
1199
|
+
property?: string;
|
|
1200
|
+
content: string;
|
|
1201
|
+
}): string;
|
|
1202
|
+
/**
|
|
1203
|
+
* Render a link tag.
|
|
1204
|
+
*/
|
|
1205
|
+
protected renderLinkTag(link: {
|
|
1206
|
+
rel: string;
|
|
1207
|
+
href: string;
|
|
1208
|
+
as?: string;
|
|
1209
|
+
crossorigin?: string;
|
|
1210
|
+
}): string;
|
|
1211
|
+
/**
|
|
1212
|
+
* Render a script tag.
|
|
1213
|
+
*/
|
|
1214
|
+
protected renderScriptTag(script: Record<string, string | boolean>): string;
|
|
1215
|
+
/**
|
|
1216
|
+
* Escape HTML special characters.
|
|
1217
|
+
*/
|
|
1218
|
+
escapeHtml(str: string): string;
|
|
1219
|
+
/**
|
|
1220
|
+
* Safely serialize data to JSON for embedding in HTML.
|
|
1221
|
+
* Escapes characters that could break out of script tags.
|
|
1222
|
+
*/
|
|
1223
|
+
safeJsonSerialize(data: unknown): string;
|
|
1224
|
+
/**
|
|
1225
|
+
* Build hydration data from router state.
|
|
1226
|
+
*
|
|
1227
|
+
* This creates the data structure that will be serialized to window.__ssr
|
|
1228
|
+
* for client-side rehydration.
|
|
1229
|
+
*/
|
|
1230
|
+
buildHydrationData(state: ReactRouterState): HydrationData;
|
|
1231
|
+
/**
|
|
1232
|
+
* Encode a string to Uint8Array using the shared encoder.
|
|
1233
|
+
*/
|
|
1234
|
+
encode(str: string): Uint8Array;
|
|
1235
|
+
/**
|
|
1236
|
+
* Get the pre-encoded hydration script prefix.
|
|
1237
|
+
*/
|
|
1238
|
+
get hydrationPrefix(): Uint8Array;
|
|
1239
|
+
/**
|
|
1240
|
+
* Get the pre-encoded hydration script suffix.
|
|
1241
|
+
*/
|
|
1242
|
+
get hydrationSuffix(): Uint8Array;
|
|
1243
|
+
/**
|
|
1244
|
+
* Create a ReadableStream that streams the HTML template with React content.
|
|
1245
|
+
*
|
|
1246
|
+
* This is the main entry point for SSR streaming. It:
|
|
1247
|
+
* 1. Sends <head> immediately (browser starts downloading assets)
|
|
1248
|
+
* 2. Streams React content as it renders
|
|
1249
|
+
* 3. Appends hydration script and closing tags
|
|
1250
|
+
*
|
|
1251
|
+
* @param reactStream - ReadableStream from renderToReadableStream
|
|
1252
|
+
* @param state - Router state with head data
|
|
1253
|
+
* @param options - Streaming options
|
|
1254
|
+
*/
|
|
1255
|
+
createHtmlStream(reactStream: ReadableStream<Uint8Array>, state: ReactRouterState, options?: {
|
|
1256
|
+
hydration?: boolean;
|
|
1257
|
+
onError?: (error: unknown) => void;
|
|
1258
|
+
}): ReadableStream<Uint8Array>;
|
|
1259
|
+
/**
|
|
1260
|
+
* Early head content for preloading.
|
|
1261
|
+
*
|
|
1262
|
+
* Contains entry assets (JS + CSS) that are always required and can be
|
|
1263
|
+
* sent before page loaders run.
|
|
1264
|
+
*/
|
|
1265
|
+
protected earlyHeadContent: string;
|
|
1266
|
+
/**
|
|
1267
|
+
* Set the early head content (entry script + CSS).
|
|
1268
|
+
*
|
|
1269
|
+
* Also strips these assets from the original head content to avoid duplicates,
|
|
1270
|
+
* since we're moving them to the early phase.
|
|
1271
|
+
*
|
|
1272
|
+
* @param content - HTML string with entry assets
|
|
1273
|
+
* @param entryAssets - Entry asset paths to strip from original head
|
|
1274
|
+
*/
|
|
1275
|
+
setEarlyHeadContent(content: string, entryAssets?: {
|
|
1276
|
+
js?: string;
|
|
1277
|
+
css: string[];
|
|
1278
|
+
}): void;
|
|
1279
|
+
/**
|
|
1280
|
+
* Escape special regex characters in a string.
|
|
1281
|
+
*/
|
|
1282
|
+
protected escapeRegExp(str: string): string;
|
|
1283
|
+
/**
|
|
1284
|
+
* Create an optimized HTML stream with early head streaming.
|
|
1285
|
+
*
|
|
1286
|
+
* This version sends critical assets (entry.js, CSS) BEFORE page loaders run,
|
|
1287
|
+
* allowing the browser to start downloading them immediately.
|
|
1288
|
+
*
|
|
1289
|
+
* Flow:
|
|
1290
|
+
* 1. Send DOCTYPE, <html>, <head> open, entry preloads (IMMEDIATE)
|
|
1291
|
+
* 2. Run async work (createLayers, etc.)
|
|
1292
|
+
* 3. Send rest of head, body, React content, hydration
|
|
1293
|
+
*
|
|
1294
|
+
* @param globalHead - Global head with htmlAttributes (from $head primitives)
|
|
1295
|
+
* @param asyncWork - Async function to run between early head and rest of stream
|
|
1296
|
+
* @param options - Streaming options
|
|
1297
|
+
*/
|
|
1298
|
+
createEarlyHtmlStream(globalHead: SimpleHead, asyncWork: () => Promise<{
|
|
1299
|
+
state: ReactRouterState;
|
|
1300
|
+
reactStream: ReadableStream<Uint8Array>;
|
|
1301
|
+
} | {
|
|
1302
|
+
redirect: string;
|
|
1303
|
+
} | null>, options?: {
|
|
1304
|
+
hydration?: boolean;
|
|
1305
|
+
onError?: (error: unknown) => void;
|
|
1306
|
+
}): ReadableStream<Uint8Array>;
|
|
1179
1307
|
}
|
|
1180
1308
|
/**
|
|
1181
|
-
*
|
|
1309
|
+
* Template slots - the template split into logical parts for efficient streaming.
|
|
1310
|
+
*
|
|
1311
|
+
* Static parts are pre-encoded as Uint8Array for zero-copy streaming.
|
|
1312
|
+
* Dynamic parts (attributes, head content) are kept as strings/objects for merging.
|
|
1313
|
+
*/
|
|
1314
|
+
interface TemplateSlots {
|
|
1315
|
+
doctype: Uint8Array;
|
|
1316
|
+
htmlOpen: Uint8Array;
|
|
1317
|
+
htmlClose: Uint8Array;
|
|
1318
|
+
headOpen: Uint8Array;
|
|
1319
|
+
headClose: Uint8Array;
|
|
1320
|
+
bodyOpen: Uint8Array;
|
|
1321
|
+
bodyClose: Uint8Array;
|
|
1322
|
+
rootOpen: Uint8Array;
|
|
1323
|
+
rootClose: Uint8Array;
|
|
1324
|
+
scriptClose: Uint8Array;
|
|
1325
|
+
htmlOriginalAttrs: Record<string, string>;
|
|
1326
|
+
bodyOriginalAttrs: Record<string, string>;
|
|
1327
|
+
headOriginalContent: string;
|
|
1328
|
+
beforeRoot: string;
|
|
1329
|
+
afterRoot: string;
|
|
1330
|
+
}
|
|
1331
|
+
/**
|
|
1332
|
+
* Hydration state that gets serialized to window.__ssr
|
|
1182
1333
|
*/
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1334
|
+
interface HydrationData {
|
|
1335
|
+
layers: Array<{
|
|
1336
|
+
data?: unknown;
|
|
1337
|
+
error?: {
|
|
1338
|
+
name: string;
|
|
1339
|
+
message: string;
|
|
1340
|
+
stack?: string;
|
|
1341
|
+
};
|
|
1342
|
+
}>;
|
|
1343
|
+
[key: string]: unknown;
|
|
1344
|
+
}
|
|
1345
|
+
//#endregion
|
|
1346
|
+
//#region ../../src/router/atoms/ssrManifestAtom.d.ts
|
|
1347
|
+
/**
|
|
1348
|
+
* Schema for the SSR manifest atom.
|
|
1349
|
+
*/
|
|
1350
|
+
declare const ssrManifestAtomSchema: alepha1.TObject<{
|
|
1351
|
+
/**
|
|
1352
|
+
* Preload manifest mapping short keys to source paths.
|
|
1353
|
+
* Generated by viteAlephaSsrPreload plugin at build time.
|
|
1354
|
+
*/
|
|
1355
|
+
preload: alepha1.TOptional<alepha1.TRecord<"^.*$", alepha1.TString>>;
|
|
1356
|
+
/**
|
|
1357
|
+
* SSR manifest mapping source files to their required chunks.
|
|
1358
|
+
*/
|
|
1359
|
+
ssr: alepha1.TOptional<alepha1.TRecord<"^.*$", alepha1.TArray<alepha1.TString>>>;
|
|
1360
|
+
/**
|
|
1361
|
+
* Client manifest mapping source files to their output information.
|
|
1362
|
+
*/
|
|
1363
|
+
client: alepha1.TOptional<alepha1.TRecord<"^.*$", alepha1.TObject<{
|
|
1364
|
+
file: alepha1.TString;
|
|
1365
|
+
src: alepha1.TOptional<alepha1.TString>;
|
|
1366
|
+
isEntry: alepha1.TOptional<alepha1.TBoolean>;
|
|
1367
|
+
isDynamicEntry: alepha1.TOptional<alepha1.TBoolean>;
|
|
1368
|
+
imports: alepha1.TOptional<alepha1.TArray<alepha1.TString>>;
|
|
1369
|
+
dynamicImports: alepha1.TOptional<alepha1.TArray<alepha1.TString>>;
|
|
1370
|
+
css: alepha1.TOptional<alepha1.TArray<alepha1.TString>>;
|
|
1371
|
+
assets: alepha1.TOptional<alepha1.TArray<alepha1.TString>>;
|
|
1372
|
+
}>>>;
|
|
1373
|
+
}>;
|
|
1374
|
+
/**
|
|
1375
|
+
* Type for the SSR manifest schema.
|
|
1376
|
+
*/
|
|
1377
|
+
type SsrManifestAtomSchema = typeof ssrManifestAtomSchema;
|
|
1378
|
+
//#endregion
|
|
1379
|
+
//#region ../../src/router/providers/SSRManifestProvider.d.ts
|
|
1380
|
+
/**
|
|
1381
|
+
* Provider for SSR manifest data used for module preloading.
|
|
1382
|
+
*
|
|
1383
|
+
* The manifest is populated at build time by embedding data into the
|
|
1384
|
+
* generated index.js via the ssrManifestAtom. This eliminates filesystem
|
|
1385
|
+
* reads at runtime, making it optimal for serverless deployments.
|
|
1386
|
+
*
|
|
1387
|
+
* Manifest files are generated during `vite build`:
|
|
1388
|
+
* - manifest.json (client manifest)
|
|
1389
|
+
* - ssr-manifest.json (SSR manifest)
|
|
1390
|
+
* - preload-manifest.json (from viteAlephaSsrPreload plugin)
|
|
1391
|
+
*/
|
|
1392
|
+
declare class SSRManifestProvider {
|
|
1393
|
+
protected readonly alepha: Alepha;
|
|
1394
|
+
/**
|
|
1395
|
+
* Get the manifest from the store at runtime.
|
|
1396
|
+
* This ensures the manifest is available even when set after module load.
|
|
1397
|
+
*/
|
|
1398
|
+
protected get manifest(): Static<SsrManifestAtomSchema>;
|
|
1399
|
+
/**
|
|
1400
|
+
* Get the preload manifest.
|
|
1401
|
+
*/
|
|
1402
|
+
protected get preloadManifest(): PreloadManifest | undefined;
|
|
1403
|
+
/**
|
|
1404
|
+
* Get the SSR manifest.
|
|
1405
|
+
*/
|
|
1406
|
+
protected get ssrManifest(): SSRManifest | undefined;
|
|
1407
|
+
/**
|
|
1408
|
+
* Get the client manifest.
|
|
1409
|
+
*/
|
|
1410
|
+
protected get clientManifest(): ClientManifest | undefined;
|
|
1411
|
+
/**
|
|
1412
|
+
* Resolve a preload key to its source path.
|
|
1413
|
+
*
|
|
1414
|
+
* The key is a short hash injected by viteAlephaSsrPreload plugin,
|
|
1415
|
+
* which maps to the full source path in the preload manifest.
|
|
1416
|
+
*
|
|
1417
|
+
* @param key - Short hash key (e.g., "a1b2c3d4")
|
|
1418
|
+
* @returns Source path (e.g., "src/pages/UserDetail.tsx") or undefined
|
|
1419
|
+
*/
|
|
1420
|
+
resolvePreloadKey(key: string): string | undefined;
|
|
1421
|
+
/**
|
|
1422
|
+
* Get all chunks required for a source file, including transitive dependencies.
|
|
1423
|
+
*
|
|
1424
|
+
* Uses the client manifest to recursively resolve all imported chunks,
|
|
1425
|
+
* not just the direct chunks from the SSR manifest.
|
|
1426
|
+
*
|
|
1427
|
+
* @param sourcePath - Source file path (e.g., "src/pages/Home.tsx")
|
|
1428
|
+
* @returns Array of chunk URLs to preload, or empty array if not found
|
|
1429
|
+
*/
|
|
1430
|
+
getChunks(sourcePath: string): string[];
|
|
1431
|
+
/**
|
|
1432
|
+
* Find manifest entry for a source path, trying different extensions.
|
|
1433
|
+
*/
|
|
1434
|
+
protected findManifestEntry(sourcePath: string): {
|
|
1435
|
+
file: string;
|
|
1436
|
+
src?: string;
|
|
1437
|
+
isEntry?: boolean;
|
|
1438
|
+
isDynamicEntry?: boolean;
|
|
1439
|
+
imports?: string[];
|
|
1440
|
+
dynamicImports?: string[];
|
|
1441
|
+
css?: string[];
|
|
1442
|
+
assets?: string[];
|
|
1443
|
+
} | undefined;
|
|
1444
|
+
/**
|
|
1445
|
+
* Recursively collect all chunk URLs for a manifest entry.
|
|
1446
|
+
*/
|
|
1447
|
+
protected collectChunksRecursive(key: string, chunks: Set<string>, visited: Set<string>): void;
|
|
1448
|
+
/**
|
|
1449
|
+
* Fallback to SSR manifest for chunk lookup.
|
|
1450
|
+
*/
|
|
1451
|
+
protected getChunksFromSSRManifest(sourcePath: string): string[];
|
|
1452
|
+
/**
|
|
1453
|
+
* Collect modulepreload links for a route and its parent chain.
|
|
1454
|
+
*/
|
|
1455
|
+
collectPreloadLinks(route: PageRoute): Array<{
|
|
1456
|
+
rel: string;
|
|
1457
|
+
href: string;
|
|
1458
|
+
as?: string;
|
|
1459
|
+
crossorigin?: string;
|
|
1460
|
+
}>;
|
|
1461
|
+
/**
|
|
1462
|
+
* Get all chunks for multiple source files.
|
|
1463
|
+
*
|
|
1464
|
+
* @param sourcePaths - Array of source file paths
|
|
1465
|
+
* @returns Deduplicated array of chunk URLs
|
|
1466
|
+
*/
|
|
1467
|
+
getChunksForMultiple(sourcePaths: string[]): string[];
|
|
1468
|
+
/**
|
|
1469
|
+
* Check if manifests are loaded and available.
|
|
1470
|
+
*/
|
|
1471
|
+
isAvailable(): boolean;
|
|
1472
|
+
/**
|
|
1473
|
+
* Cached entry assets - computed once at first access.
|
|
1474
|
+
*/
|
|
1475
|
+
protected cachedEntryAssets: EntryAssets | null;
|
|
1476
|
+
/**
|
|
1477
|
+
* Get the entry point assets (main entry.js and associated CSS files).
|
|
1478
|
+
*
|
|
1479
|
+
* These assets are always required for all pages and can be preloaded
|
|
1480
|
+
* before page-specific loaders run.
|
|
1481
|
+
*
|
|
1482
|
+
* @returns Entry assets with js and css paths, or null if manifest unavailable
|
|
1483
|
+
*/
|
|
1484
|
+
getEntryAssets(): EntryAssets | null;
|
|
1485
|
+
/**
|
|
1486
|
+
* Build preload link tags for entry assets.
|
|
1487
|
+
*
|
|
1488
|
+
* @returns Array of link objects ready to be rendered
|
|
1489
|
+
*/
|
|
1490
|
+
getEntryPreloadLinks(): Array<{
|
|
1491
|
+
rel: string;
|
|
1492
|
+
href: string;
|
|
1493
|
+
as?: string;
|
|
1494
|
+
crossorigin?: string;
|
|
1188
1495
|
}>;
|
|
1189
|
-
}>, "alepha.react.server.options">;
|
|
1190
|
-
type ReactServerProviderOptions = Static<typeof reactServerOptions.schema>;
|
|
1191
|
-
declare module "alepha" {
|
|
1192
|
-
interface State {
|
|
1193
|
-
[reactServerOptions.key]: ReactServerProviderOptions;
|
|
1194
|
-
}
|
|
1195
1496
|
}
|
|
1497
|
+
/**
|
|
1498
|
+
* Entry assets structure containing the main entry JS and associated CSS files.
|
|
1499
|
+
*/
|
|
1500
|
+
interface EntryAssets {
|
|
1501
|
+
/** Main entry JavaScript file (e.g., "/assets/entry.abc123.js") */
|
|
1502
|
+
js?: string;
|
|
1503
|
+
/** Associated CSS files (e.g., ["/assets/style.abc123.css"]) */
|
|
1504
|
+
css: string[];
|
|
1505
|
+
}
|
|
1506
|
+
/**
|
|
1507
|
+
* SSR Manifest structure from Vite.
|
|
1508
|
+
* Maps source file paths to their required chunks/assets.
|
|
1509
|
+
*/
|
|
1510
|
+
type SSRManifest = Record<string, string[]>;
|
|
1511
|
+
/**
|
|
1512
|
+
* Client manifest structure from Vite.
|
|
1513
|
+
* Maps source files to their output information.
|
|
1514
|
+
*/
|
|
1515
|
+
interface ClientManifest {
|
|
1516
|
+
[key: string]: {
|
|
1517
|
+
file: string;
|
|
1518
|
+
src?: string;
|
|
1519
|
+
isEntry?: boolean;
|
|
1520
|
+
isDynamicEntry?: boolean;
|
|
1521
|
+
imports?: string[];
|
|
1522
|
+
dynamicImports?: string[];
|
|
1523
|
+
css?: string[];
|
|
1524
|
+
assets?: string[];
|
|
1525
|
+
};
|
|
1526
|
+
}
|
|
1527
|
+
/**
|
|
1528
|
+
* Preload manifest mapping short keys to source paths.
|
|
1529
|
+
* Generated by viteAlephaSsrPreload plugin at build time.
|
|
1530
|
+
*/
|
|
1531
|
+
type PreloadManifest = Record<string, string>;
|
|
1532
|
+
//#endregion
|
|
1533
|
+
//#region ../../src/router/providers/ReactServerProvider.d.ts
|
|
1196
1534
|
/**
|
|
1197
1535
|
* React server provider responsible for SSR and static file serving.
|
|
1198
1536
|
*
|
|
1199
|
-
*
|
|
1537
|
+
* Coordinates between:
|
|
1538
|
+
* - ReactPageProvider: Page routing and layer resolution
|
|
1539
|
+
* - ReactServerTemplateProvider: HTML template parsing and streaming
|
|
1540
|
+
* - ServerHeadProvider: Head content management
|
|
1541
|
+
* - SSRManifestProvider: Module preload link collection
|
|
1542
|
+
*
|
|
1543
|
+
* Uses `react-dom/server` under the hood.
|
|
1200
1544
|
*/
|
|
1201
1545
|
declare class ReactServerProvider {
|
|
1546
|
+
/**
|
|
1547
|
+
* SSR response headers - pre-allocated to avoid object creation per request.
|
|
1548
|
+
*/
|
|
1549
|
+
protected readonly SSR_HEADERS: {
|
|
1550
|
+
readonly "content-type": "text/html";
|
|
1551
|
+
readonly "cache-control": "no-store, no-cache, must-revalidate, proxy-revalidate";
|
|
1552
|
+
readonly pragma: "no-cache";
|
|
1553
|
+
readonly expires: "0";
|
|
1554
|
+
};
|
|
1555
|
+
protected readonly fs: FileSystemProvider;
|
|
1202
1556
|
protected readonly log: alepha_logger0.Logger;
|
|
1203
1557
|
protected readonly alepha: Alepha;
|
|
1204
1558
|
protected readonly env: {
|
|
1205
1559
|
REACT_SSR_ENABLED?: boolean | undefined;
|
|
1206
|
-
REACT_ROOT_ID: string;
|
|
1207
1560
|
};
|
|
1208
1561
|
protected readonly pageApi: ReactPageProvider;
|
|
1562
|
+
protected readonly templateProvider: ReactServerTemplateProvider;
|
|
1563
|
+
protected readonly serverHeadProvider: ServerHeadProvider;
|
|
1209
1564
|
protected readonly serverStaticProvider: ServerStaticProvider;
|
|
1210
1565
|
protected readonly serverRouterProvider: ServerRouterProvider;
|
|
1211
1566
|
protected readonly serverTimingProvider: ServerTimingProvider;
|
|
1212
|
-
readonly
|
|
1213
|
-
|
|
1567
|
+
protected readonly ssrManifestProvider: SSRManifestProvider;
|
|
1568
|
+
/**
|
|
1569
|
+
* Cached check for ServerLinksProvider - avoids has() lookup per request.
|
|
1570
|
+
*/
|
|
1571
|
+
protected hasServerLinksProvider: boolean;
|
|
1214
1572
|
protected readonly options: Readonly<{
|
|
1215
1573
|
publicDir: string;
|
|
1216
1574
|
staticServer: {
|
|
@@ -1219,40 +1577,103 @@ declare class ReactServerProvider {
|
|
|
1219
1577
|
};
|
|
1220
1578
|
}>;
|
|
1221
1579
|
/**
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
readonly onConfigure:
|
|
1580
|
+
* Configure the React server provider.
|
|
1581
|
+
*/
|
|
1582
|
+
readonly onConfigure: alepha1.HookPrimitive<"configure">;
|
|
1583
|
+
/**
|
|
1584
|
+
* Get the current HTML template.
|
|
1585
|
+
*/
|
|
1225
1586
|
get template(): string;
|
|
1587
|
+
/**
|
|
1588
|
+
* Register all pages as server routes.
|
|
1589
|
+
*/
|
|
1226
1590
|
protected registerPages(templateLoader: TemplateLoader): Promise<void>;
|
|
1227
1591
|
/**
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1592
|
+
* Set up early head content with entry assets.
|
|
1593
|
+
*
|
|
1594
|
+
* This content is sent immediately when streaming starts, before page loaders run,
|
|
1595
|
+
* allowing the browser to start downloading entry.js and CSS files early.
|
|
1596
|
+
*
|
|
1597
|
+
* Uses <script type="module"> instead of <link rel="modulepreload"> for JS
|
|
1598
|
+
* because the script needs to execute anyway - this way the browser starts
|
|
1599
|
+
* downloading, parsing, AND will execute as soon as ready.
|
|
1600
|
+
*
|
|
1601
|
+
* Also strips these assets from the original template head to avoid duplicates.
|
|
1602
|
+
*/
|
|
1603
|
+
protected setupEarlyHeadContent(): void;
|
|
1604
|
+
/**
|
|
1605
|
+
* Get the public directory path where static files are located.
|
|
1606
|
+
*/
|
|
1607
|
+
protected getPublicDirectory(): Promise<string>;
|
|
1231
1608
|
/**
|
|
1232
|
-
|
|
1233
|
-
|
|
1609
|
+
* Configure the static file server to serve files from the given root directory.
|
|
1610
|
+
*/
|
|
1234
1611
|
protected configureStaticServer(root: string): Promise<void>;
|
|
1235
1612
|
/**
|
|
1236
|
-
|
|
1237
|
-
|
|
1613
|
+
* Configure Vite for SSR in development mode.
|
|
1614
|
+
*/
|
|
1238
1615
|
protected configureVite(ssrEnabled: boolean): Promise<void>;
|
|
1239
1616
|
/**
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
render(name: string, options?: PagePrimitiveRenderOptions): Promise<PagePrimitiveRenderResult>;
|
|
1617
|
+
* Create the request handler for a page route.
|
|
1618
|
+
*/
|
|
1243
1619
|
protected createHandler(route: PageRoute, templateLoader: TemplateLoader): ServerHandler;
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1620
|
+
/**
|
|
1621
|
+
* Core page rendering logic shared between SSR handler and static prerendering.
|
|
1622
|
+
*
|
|
1623
|
+
* Handles:
|
|
1624
|
+
* - Layer resolution (loaders)
|
|
1625
|
+
* - Redirect detection
|
|
1626
|
+
* - Head content filling
|
|
1627
|
+
* - Preload link collection
|
|
1628
|
+
* - React stream rendering
|
|
1629
|
+
*
|
|
1630
|
+
* @param route - The page route to render
|
|
1631
|
+
* @param state - The router state
|
|
1632
|
+
* @returns Render result with redirect or React stream
|
|
1633
|
+
*/
|
|
1634
|
+
protected renderPage(route: PageRoute, state: ReactRouterState): Promise<{
|
|
1635
|
+
redirect?: string;
|
|
1636
|
+
reactStream?: ReadableStream<Uint8Array>;
|
|
1637
|
+
}>;
|
|
1638
|
+
/**
|
|
1639
|
+
* For testing purposes, renders a page to HTML string.
|
|
1640
|
+
* Uses the same streaming code path as production, then collects to string.
|
|
1641
|
+
*
|
|
1642
|
+
* @param name - Page name to render
|
|
1643
|
+
* @param options - Render options (params, query, html, hydration)
|
|
1644
|
+
*/
|
|
1645
|
+
render(name: string, options?: PagePrimitiveRenderOptions): Promise<PagePrimitiveRenderResult>;
|
|
1646
|
+
/**
|
|
1647
|
+
* Collect a ReadableStream into a string.
|
|
1648
|
+
*/
|
|
1649
|
+
protected streamToString(stream: ReadableStream<Uint8Array>): Promise<string>;
|
|
1249
1650
|
}
|
|
1250
1651
|
type TemplateLoader = () => Promise<string | undefined>;
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1652
|
+
declare const envSchema: alepha1.TObject<{
|
|
1653
|
+
REACT_SSR_ENABLED: alepha1.TOptional<alepha1.TBoolean>;
|
|
1654
|
+
}>;
|
|
1655
|
+
declare module "alepha" {
|
|
1656
|
+
interface Env extends Partial<Static<typeof envSchema>> {}
|
|
1657
|
+
interface State {
|
|
1658
|
+
"alepha.react.server.ssr"?: boolean;
|
|
1659
|
+
"alepha.react.server.template"?: string;
|
|
1660
|
+
}
|
|
1661
|
+
}
|
|
1662
|
+
/**
|
|
1663
|
+
* React server provider configuration atom
|
|
1664
|
+
*/
|
|
1665
|
+
declare const reactServerOptions: alepha1.Atom<alepha1.TObject<{
|
|
1666
|
+
publicDir: alepha1.TString;
|
|
1667
|
+
staticServer: alepha1.TObject<{
|
|
1668
|
+
disabled: alepha1.TBoolean;
|
|
1669
|
+
path: alepha1.TString;
|
|
1670
|
+
}>;
|
|
1671
|
+
}>, "alepha.react.server.options">;
|
|
1672
|
+
type ReactServerProviderOptions = Static<typeof reactServerOptions.schema>;
|
|
1673
|
+
declare module "alepha" {
|
|
1674
|
+
interface State {
|
|
1675
|
+
[reactServerOptions.key]: ReactServerProviderOptions;
|
|
1676
|
+
}
|
|
1256
1677
|
}
|
|
1257
1678
|
//#endregion
|
|
1258
1679
|
//#region ../../src/router/index.d.ts
|
|
@@ -1262,23 +1683,26 @@ declare module "alepha" {
|
|
|
1262
1683
|
}
|
|
1263
1684
|
interface Hooks {
|
|
1264
1685
|
/**
|
|
1265
|
-
|
|
1266
|
-
|
|
1686
|
+
* Fires when the React application is starting to be rendered on the server.
|
|
1687
|
+
*/
|
|
1267
1688
|
"react:server:render:begin": {
|
|
1268
1689
|
request?: ServerRequest;
|
|
1269
1690
|
state: ReactRouterState;
|
|
1270
1691
|
};
|
|
1271
1692
|
/**
|
|
1272
|
-
|
|
1273
|
-
|
|
1693
|
+
* Fires when the React application has been rendered on the server.
|
|
1694
|
+
*/
|
|
1274
1695
|
"react:server:render:end": {
|
|
1275
1696
|
request?: ServerRequest;
|
|
1276
1697
|
state: ReactRouterState;
|
|
1277
1698
|
html: string;
|
|
1278
1699
|
};
|
|
1279
1700
|
/**
|
|
1280
|
-
|
|
1281
|
-
|
|
1701
|
+
* Fires when the React application is being rendered on the browser.
|
|
1702
|
+
*
|
|
1703
|
+
* Note: this one is not really necessary, it's a hack because we need to isolate renderer from server code in order
|
|
1704
|
+
* to avoid including react-dom/client in server bundles.
|
|
1705
|
+
*/
|
|
1282
1706
|
"react:browser:render": {
|
|
1283
1707
|
root: HTMLElement;
|
|
1284
1708
|
element: ReactNode;
|
|
@@ -1286,29 +1710,29 @@ declare module "alepha" {
|
|
|
1286
1710
|
hydration?: ReactHydrationState;
|
|
1287
1711
|
};
|
|
1288
1712
|
/**
|
|
1289
|
-
|
|
1290
|
-
|
|
1713
|
+
* Fires when a route transition is starting.
|
|
1714
|
+
*/
|
|
1291
1715
|
"react:transition:begin": {
|
|
1292
1716
|
previous: ReactRouterState;
|
|
1293
1717
|
state: ReactRouterState;
|
|
1294
1718
|
animation?: PageAnimation;
|
|
1295
1719
|
};
|
|
1296
1720
|
/**
|
|
1297
|
-
|
|
1298
|
-
|
|
1721
|
+
* Fires when a route transition has succeeded.
|
|
1722
|
+
*/
|
|
1299
1723
|
"react:transition:success": {
|
|
1300
1724
|
state: ReactRouterState;
|
|
1301
1725
|
};
|
|
1302
1726
|
/**
|
|
1303
|
-
|
|
1304
|
-
|
|
1727
|
+
* Fires when a route transition has failed.
|
|
1728
|
+
*/
|
|
1305
1729
|
"react:transition:error": {
|
|
1306
1730
|
state: ReactRouterState;
|
|
1307
1731
|
error: Error;
|
|
1308
1732
|
};
|
|
1309
1733
|
/**
|
|
1310
|
-
|
|
1311
|
-
|
|
1734
|
+
* Fires when a route transition has completed, regardless of success or failure.
|
|
1735
|
+
*/
|
|
1312
1736
|
"react:transition:end": {
|
|
1313
1737
|
state: ReactRouterState;
|
|
1314
1738
|
};
|
|
@@ -1321,14 +1745,14 @@ declare module "alepha" {
|
|
|
1321
1745
|
* - URL pattern matching with parameters (e.g., `/users/:id`)
|
|
1322
1746
|
* - Nested routing with parent-child relationships
|
|
1323
1747
|
* - Type-safe URL parameter and query string validation
|
|
1324
|
-
* - Server-side data fetching with the `
|
|
1748
|
+
* - Server-side data fetching with the `loader` function
|
|
1325
1749
|
* - Lazy loading and code splitting
|
|
1326
1750
|
* - Page animations and error handling
|
|
1327
1751
|
*
|
|
1328
1752
|
* @see {@link $page}
|
|
1329
1753
|
* @module alepha.react.router
|
|
1330
1754
|
*/
|
|
1331
|
-
declare const AlephaReactRouter:
|
|
1755
|
+
declare const AlephaReactRouter: alepha1.Service<alepha1.Module>;
|
|
1332
1756
|
//#endregion
|
|
1333
|
-
export { $page, AlephaReactRouter, AnchorProps, ConcretePageRoute, CreateLayersResult, ErrorHandler, ErrorViewer, Layer, Link, type LinkProps, _default as NestedView, NestedViewProps, NotFound, PageAnimation, PageConfigSchema, PagePrimitive, PagePrimitiveOptions, PagePrimitiveRenderOptions, PagePrimitiveRenderResult, PageRequestConfig,
|
|
1757
|
+
export { $page, AlephaReactRouter, AnchorProps, ClientManifest, ConcretePageRoute, CreateLayersResult, EntryAssets, ErrorHandler, ErrorViewer, HydrationData, Layer, Link, type LinkProps, _default as NestedView, NestedViewProps, NotFound, PAGE_PRELOAD_KEY, PageAnimation, PageConfigSchema, PageLoader, PagePrimitive, PagePrimitiveOptions, PagePrimitiveRenderOptions, PagePrimitiveRenderResult, PageRequestConfig, PageRoute, PageRouteEntry, PreloadManifest, PreviousLayerData, ReactBrowserProvider, ReactBrowserRendererOptions, ReactHydrationState, ReactPageProvider, ReactPageService, ReactRouter, ReactRouterState, ReactServerProvider, ReactServerProviderOptions, ReactServerTemplateProvider, Redirection, type RouterGoOptions, RouterLayerContext, RouterLayerContextValue, RouterRenderOptions, RouterStackItem, SSRManifest, SSRManifestProvider, TPropsDefault, TPropsParentDefault, TemplateSlots, TransitionOptions, UseActiveHook, UseActiveOptions, UseQueryParamsHookOptions, VirtualRouter, isPageRoute, reactBrowserOptions, reactServerOptions, useActive, useQueryParams, useRouter, useRouterState };
|
|
1334
1758
|
//# sourceMappingURL=index.d.ts.map
|