@alepha/react 0.6.10 → 0.7.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/README.md +1 -1
- package/dist/index.browser.cjs +21 -20
- package/dist/index.browser.js +2 -3
- package/dist/index.cjs +168 -82
- package/dist/index.d.ts +415 -232
- package/dist/index.js +146 -62
- package/dist/{useActive-4QlZKGbw.cjs → useRouterState-AdK-XeM2.cjs} +358 -170
- package/dist/{useActive-ClUsghB5.js → useRouterState-qoMq7Y9J.js} +358 -172
- package/package.json +11 -10
- package/src/components/ClientOnly.tsx +35 -0
- package/src/components/ErrorBoundary.tsx +72 -0
- package/src/components/ErrorViewer.tsx +161 -0
- package/src/components/Link.tsx +10 -4
- package/src/components/NestedView.tsx +28 -4
- package/src/descriptors/$page.ts +143 -38
- package/src/errors/RedirectionError.ts +4 -1
- package/src/hooks/RouterHookApi.ts +58 -35
- package/src/hooks/useAlepha.ts +12 -0
- package/src/hooks/useClient.ts +8 -6
- package/src/hooks/useInject.ts +3 -9
- package/src/hooks/useQueryParams.ts +4 -7
- package/src/hooks/useRouter.ts +6 -0
- package/src/index.browser.ts +1 -1
- package/src/index.shared.ts +11 -4
- package/src/index.ts +7 -4
- package/src/providers/BrowserRouterProvider.ts +27 -33
- package/src/providers/PageDescriptorProvider.ts +90 -40
- package/src/providers/ReactBrowserProvider.ts +21 -27
- package/src/providers/ReactServerProvider.ts +215 -77
- package/dist/index.browser.cjs.map +0 -1
- package/dist/index.browser.js.map +0 -1
- package/dist/index.cjs.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/useActive-4QlZKGbw.cjs.map +0 -1
- package/dist/useActive-ClUsghB5.js.map +0 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import * as _alepha_core from '@alepha/core';
|
|
2
|
-
import {
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
import
|
|
6
|
-
import react__default, { ReactNode, FC, AnchorHTMLAttributes } from 'react';
|
|
2
|
+
import { TSchema as TSchema$1, KIND, OPTIONS, Static as Static$1, Async, Alepha, Service, TObject as TObject$1 } from '@alepha/core';
|
|
3
|
+
import { ServerRoute, ApiLinksResponse, HttpClient, ClientScope, HttpVirtualClient, ServerRouterProvider, ServerTimingProvider, ServerHandler, ServerRequest } from '@alepha/server';
|
|
4
|
+
import * as React from 'react';
|
|
5
|
+
import React__default, { PropsWithChildren, ReactNode, FC, ErrorInfo, AnchorHTMLAttributes } from 'react';
|
|
7
6
|
import { Root } from 'react-dom/client';
|
|
8
7
|
import { RouterProvider, Route } from '@alepha/router';
|
|
9
8
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
@@ -126,7 +125,294 @@ interface TSchema extends TKind, SchemaOptions {
|
|
|
126
125
|
static: unknown;
|
|
127
126
|
}
|
|
128
127
|
|
|
128
|
+
interface ClientOnlyProps {
|
|
129
|
+
fallback?: ReactNode;
|
|
130
|
+
disabled?: boolean;
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* A small utility component that renders its children only on the client side.
|
|
134
|
+
*
|
|
135
|
+
* Optionally, you can provide a fallback React node that will be rendered.
|
|
136
|
+
*
|
|
137
|
+
* You should use this component when
|
|
138
|
+
* - you have code that relies on browser-specific APIs
|
|
139
|
+
* - you want to avoid server-side rendering for a specific part of your application
|
|
140
|
+
* - you want to prevent pre-rendering of a component
|
|
141
|
+
*/
|
|
142
|
+
declare const ClientOnly: (props: PropsWithChildren<ClientOnlyProps>) => ReactNode;
|
|
143
|
+
|
|
144
|
+
declare const KEY = "PAGE";
|
|
145
|
+
interface PageConfigSchema {
|
|
146
|
+
query?: TSchema$1;
|
|
147
|
+
params?: TSchema$1;
|
|
148
|
+
}
|
|
149
|
+
type TPropsDefault = any;
|
|
150
|
+
type TPropsParentDefault = {};
|
|
151
|
+
interface PageDescriptorOptions<TConfig extends PageConfigSchema = PageConfigSchema, TProps extends object = TPropsDefault, TPropsParent extends object = TPropsParentDefault> extends Pick<ServerRoute, "cache"> {
|
|
152
|
+
/**
|
|
153
|
+
* Name your page.
|
|
154
|
+
*
|
|
155
|
+
* @default Descriptor key
|
|
156
|
+
*/
|
|
157
|
+
name?: string;
|
|
158
|
+
/**
|
|
159
|
+
* Optional description of the page.
|
|
160
|
+
*/
|
|
161
|
+
description?: string;
|
|
162
|
+
/**
|
|
163
|
+
* Add a pathname to the page.
|
|
164
|
+
*
|
|
165
|
+
* Pathname can contain parameters, like `/post/:slug`.
|
|
166
|
+
*
|
|
167
|
+
* @default ""
|
|
168
|
+
*/
|
|
169
|
+
path?: string;
|
|
170
|
+
/**
|
|
171
|
+
* Add an input schema to define:
|
|
172
|
+
* - `params`: parameters from the pathname.
|
|
173
|
+
* - `query`: query parameters from the URL.
|
|
174
|
+
*/
|
|
175
|
+
schema?: TConfig;
|
|
176
|
+
/**
|
|
177
|
+
* Load data before rendering the page.
|
|
178
|
+
*
|
|
179
|
+
* This function receives
|
|
180
|
+
* - the request context and
|
|
181
|
+
* - the parent props (if page has a parent)
|
|
182
|
+
*
|
|
183
|
+
* In SSR, the returned data will be serialized and sent to the client, then reused during the client-side hydration.
|
|
184
|
+
*
|
|
185
|
+
* Resolve can be stopped by throwing an error, which will be handled by the `errorHandler` function.
|
|
186
|
+
* It's common to throw a `NotFoundError` to display a 404 page.
|
|
187
|
+
*
|
|
188
|
+
* RedirectError can be thrown to redirect the user to another page.
|
|
189
|
+
*/
|
|
190
|
+
resolve?: (context: PageResolve<TConfig, TPropsParent>) => Async<TProps>;
|
|
191
|
+
/**
|
|
192
|
+
* The component to render when the page is loaded.
|
|
193
|
+
*
|
|
194
|
+
* If `lazy` is defined, this will be ignored.
|
|
195
|
+
* Prefer using `lazy` to improve the initial loading time.
|
|
196
|
+
*/
|
|
197
|
+
component?: FC<TProps & TPropsParent>;
|
|
198
|
+
/**
|
|
199
|
+
* Lazy load the component when the page is loaded.
|
|
200
|
+
*
|
|
201
|
+
* It's recommended to use this for components to improve the initial loading time
|
|
202
|
+
* and enable code-splitting.
|
|
203
|
+
*/
|
|
204
|
+
lazy?: () => Promise<{
|
|
205
|
+
default: FC<TProps & TPropsParent>;
|
|
206
|
+
}>;
|
|
207
|
+
/**
|
|
208
|
+
* Set some children pages and make the page a parent page.
|
|
209
|
+
*
|
|
210
|
+
* /!\ Parent page can't be rendered directly. /!\
|
|
211
|
+
*
|
|
212
|
+
* If you still want to render at this pathname, add a child page with an empty path.
|
|
213
|
+
*/
|
|
214
|
+
children?: Array<{
|
|
215
|
+
[OPTIONS]: PageDescriptorOptions;
|
|
216
|
+
}>;
|
|
217
|
+
parent?: {
|
|
218
|
+
[OPTIONS]: PageDescriptorOptions<PageConfigSchema, TPropsParent>;
|
|
219
|
+
};
|
|
220
|
+
can?: () => boolean;
|
|
221
|
+
head?: Head$1 | ((props: TProps, previous?: Head$1) => Head$1);
|
|
222
|
+
errorHandler?: (error: Error) => ReactNode;
|
|
223
|
+
prerender?: boolean | {
|
|
224
|
+
entries?: Array<Partial<PageRequestConfig<TConfig>>>;
|
|
225
|
+
};
|
|
226
|
+
/**
|
|
227
|
+
* If true, the page will be rendered on the client-side.
|
|
228
|
+
*/
|
|
229
|
+
client?: boolean | ClientOnlyProps;
|
|
230
|
+
}
|
|
231
|
+
interface PageDescriptor<TConfig extends PageConfigSchema = PageConfigSchema, TProps extends object = TPropsDefault, TPropsParent extends object = TPropsParentDefault> {
|
|
232
|
+
[KIND]: typeof KEY;
|
|
233
|
+
[OPTIONS]: PageDescriptorOptions<TConfig, TProps, TPropsParent>;
|
|
234
|
+
/**
|
|
235
|
+
* For testing or build purposes, this will render the page (with or without the HTML layout) and return the HTML and context.
|
|
236
|
+
* Only valid for server-side rendering, it will throw an error if called on the client-side.
|
|
237
|
+
*/
|
|
238
|
+
render: (options?: PageDescriptorRenderOptions) => Promise<PageDescriptorRenderResult>;
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* Main descriptor for defining a React route in the application.
|
|
242
|
+
*/
|
|
243
|
+
declare const $page: {
|
|
244
|
+
<TConfig extends PageConfigSchema = PageConfigSchema, TProps extends object = any, TPropsParent extends object = TPropsParentDefault>(options: PageDescriptorOptions<TConfig, TProps, TPropsParent>): PageDescriptor<TConfig, TProps, TPropsParent>;
|
|
245
|
+
[KIND]: string;
|
|
246
|
+
};
|
|
247
|
+
interface PageDescriptorRenderOptions {
|
|
248
|
+
params?: Record<string, string>;
|
|
249
|
+
query?: Record<string, string>;
|
|
250
|
+
withLayout?: boolean;
|
|
251
|
+
}
|
|
252
|
+
interface PageDescriptorRenderResult {
|
|
253
|
+
html: string;
|
|
254
|
+
context: PageReactContext;
|
|
255
|
+
}
|
|
129
256
|
interface Head$1 {
|
|
257
|
+
title?: string;
|
|
258
|
+
description?: string;
|
|
259
|
+
titleSeparator?: string;
|
|
260
|
+
htmlAttributes?: Record<string, string>;
|
|
261
|
+
bodyAttributes?: Record<string, string>;
|
|
262
|
+
meta?: Array<{
|
|
263
|
+
name: string;
|
|
264
|
+
content: string;
|
|
265
|
+
}>;
|
|
266
|
+
keywords?: string[];
|
|
267
|
+
author?: string;
|
|
268
|
+
robots?: string;
|
|
269
|
+
themeColor?: string;
|
|
270
|
+
viewport?: string | {
|
|
271
|
+
width?: string;
|
|
272
|
+
height?: string;
|
|
273
|
+
initialScale?: string;
|
|
274
|
+
maximumScale?: string;
|
|
275
|
+
userScalable?: "no" | "yes" | "0" | "1";
|
|
276
|
+
interactiveWidget?: "resizes-visual" | "resizes-content" | "overlays-content";
|
|
277
|
+
};
|
|
278
|
+
og?: {
|
|
279
|
+
title?: string;
|
|
280
|
+
description?: string;
|
|
281
|
+
image?: string;
|
|
282
|
+
url?: string;
|
|
283
|
+
type?: string;
|
|
284
|
+
};
|
|
285
|
+
twitter?: {
|
|
286
|
+
card?: string;
|
|
287
|
+
title?: string;
|
|
288
|
+
description?: string;
|
|
289
|
+
image?: string;
|
|
290
|
+
site?: string;
|
|
291
|
+
};
|
|
292
|
+
}
|
|
293
|
+
interface PageRequestConfig<TConfig extends PageConfigSchema = PageConfigSchema> {
|
|
294
|
+
params: TConfig["params"] extends TSchema$1 ? Static$1<TConfig["params"]> : Record<string, string>;
|
|
295
|
+
query: TConfig["query"] extends TSchema$1 ? Static$1<TConfig["query"]> : Record<string, string>;
|
|
296
|
+
}
|
|
297
|
+
type PageResolve<TConfig extends PageConfigSchema = PageConfigSchema, TPropsParent extends object = TPropsParentDefault> = PageRequestConfig<TConfig> & TPropsParent & PageReactContext;
|
|
298
|
+
|
|
299
|
+
declare const envSchema$2: _alepha_core.TObject<{
|
|
300
|
+
REACT_STRICT_MODE: TBoolean;
|
|
301
|
+
}>;
|
|
302
|
+
declare module "@alepha/core" {
|
|
303
|
+
interface Env extends Partial<Static$1<typeof envSchema$2>> {
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
declare class PageDescriptorProvider {
|
|
307
|
+
protected readonly log: _alepha_core.Logger;
|
|
308
|
+
protected readonly env: {
|
|
309
|
+
REACT_STRICT_MODE: boolean;
|
|
310
|
+
};
|
|
311
|
+
protected readonly alepha: Alepha;
|
|
312
|
+
protected readonly pages: PageRoute[];
|
|
313
|
+
getPages(): PageRoute[];
|
|
314
|
+
page(name: string): PageRoute;
|
|
315
|
+
url(name: string, options?: {
|
|
316
|
+
params?: Record<string, string>;
|
|
317
|
+
base?: string;
|
|
318
|
+
}): URL;
|
|
319
|
+
root(state: RouterState, context: PageReactContext): ReactNode;
|
|
320
|
+
createLayers(route: PageRoute, request: PageRequest): Promise<CreateLayersResult>;
|
|
321
|
+
protected getErrorHandler(route: PageRoute): ((error: Error) => ReactNode) | undefined;
|
|
322
|
+
protected createElement(page: PageRoute, props: Record<string, any>): Promise<ReactNode>;
|
|
323
|
+
protected fillHead(page: PageRoute, ctx: PageRequest, props: Record<string, any>): void;
|
|
324
|
+
renderError(error: Error): ReactNode;
|
|
325
|
+
renderEmptyView(): ReactNode;
|
|
326
|
+
href(page: {
|
|
327
|
+
options: {
|
|
328
|
+
name?: string;
|
|
329
|
+
};
|
|
330
|
+
}, params?: Record<string, any>): string;
|
|
331
|
+
compile(path: string, params?: Record<string, string>): string;
|
|
332
|
+
protected renderView(index: number, path: string, view: ReactNode | undefined, page: PageRoute): ReactNode;
|
|
333
|
+
protected readonly configure: _alepha_core.HookDescriptor<"configure">;
|
|
334
|
+
protected map(pages: Array<{
|
|
335
|
+
value: {
|
|
336
|
+
[OPTIONS]: PageDescriptorOptions;
|
|
337
|
+
};
|
|
338
|
+
}>, target: {
|
|
339
|
+
[OPTIONS]: PageDescriptorOptions;
|
|
340
|
+
}): PageRouteEntry;
|
|
341
|
+
add(entry: PageRouteEntry): void;
|
|
342
|
+
protected createMatch(page: PageRoute): string;
|
|
343
|
+
protected _next: number;
|
|
344
|
+
protected nextId(): string;
|
|
345
|
+
}
|
|
346
|
+
declare const isPageRoute: (it: any) => it is PageRoute;
|
|
347
|
+
interface PageRouteEntry extends Omit<PageDescriptorOptions, "children" | "parent"> {
|
|
348
|
+
children?: PageRouteEntry[];
|
|
349
|
+
}
|
|
350
|
+
interface PageRoute extends PageRouteEntry {
|
|
351
|
+
type: "page";
|
|
352
|
+
name: string;
|
|
353
|
+
parent?: PageRoute;
|
|
354
|
+
match: string;
|
|
355
|
+
}
|
|
356
|
+
interface Layer {
|
|
357
|
+
config?: {
|
|
358
|
+
query?: Record<string, any>;
|
|
359
|
+
params?: Record<string, any>;
|
|
360
|
+
context?: Record<string, any>;
|
|
361
|
+
};
|
|
362
|
+
name: string;
|
|
363
|
+
props?: Record<string, any>;
|
|
364
|
+
error?: Error;
|
|
365
|
+
part?: string;
|
|
366
|
+
element: ReactNode;
|
|
367
|
+
index: number;
|
|
368
|
+
path: string;
|
|
369
|
+
}
|
|
370
|
+
type PreviousLayerData = Omit<Layer, "element" | "index" | "path">;
|
|
371
|
+
interface AnchorProps {
|
|
372
|
+
href: string;
|
|
373
|
+
onClick: (ev: any) => any;
|
|
374
|
+
}
|
|
375
|
+
interface RouterState {
|
|
376
|
+
pathname: string;
|
|
377
|
+
search: string;
|
|
378
|
+
layers: Array<Layer>;
|
|
379
|
+
}
|
|
380
|
+
interface TransitionOptions {
|
|
381
|
+
state?: RouterState;
|
|
382
|
+
previous?: PreviousLayerData[];
|
|
383
|
+
context?: PageReactContext;
|
|
384
|
+
}
|
|
385
|
+
interface RouterStackItem {
|
|
386
|
+
route: PageRoute;
|
|
387
|
+
config?: Record<string, any>;
|
|
388
|
+
props?: Record<string, any>;
|
|
389
|
+
error?: Error;
|
|
390
|
+
}
|
|
391
|
+
interface RouterRenderResult {
|
|
392
|
+
state: RouterState;
|
|
393
|
+
context: PageReactContext;
|
|
394
|
+
redirect?: string;
|
|
395
|
+
}
|
|
396
|
+
interface PageRequest extends PageReactContext {
|
|
397
|
+
params: Record<string, any>;
|
|
398
|
+
query: Record<string, string>;
|
|
399
|
+
previous?: PreviousLayerData[];
|
|
400
|
+
}
|
|
401
|
+
interface CreateLayersResult extends RouterState {
|
|
402
|
+
redirect?: string;
|
|
403
|
+
}
|
|
404
|
+
/**
|
|
405
|
+
* It's like RouterState, but publicly available in React context.
|
|
406
|
+
* This is where we store all plugin data!
|
|
407
|
+
*/
|
|
408
|
+
interface PageReactContext {
|
|
409
|
+
url: URL;
|
|
410
|
+
head: Head$1;
|
|
411
|
+
onError: (error: Error) => ReactNode;
|
|
412
|
+
links?: ApiLinksResponse;
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
interface Head {
|
|
130
416
|
title?: string;
|
|
131
417
|
htmlAttributes?: Record<string, string>;
|
|
132
418
|
bodyAttributes?: Record<string, string>;
|
|
@@ -136,14 +422,14 @@ interface Head$1 {
|
|
|
136
422
|
}>;
|
|
137
423
|
}
|
|
138
424
|
declare class ServerHeadProvider {
|
|
139
|
-
renderHead(template: string, head: Head
|
|
425
|
+
renderHead(template: string, head: Head): string;
|
|
140
426
|
mergeAttributes(existing: string, attrs: Record<string, string>): string;
|
|
141
427
|
parseAttributes(attrStr: string): Record<string, string>;
|
|
142
428
|
escapeHtml(str: string): string;
|
|
143
429
|
}
|
|
144
430
|
|
|
145
431
|
declare class BrowserHeadProvider {
|
|
146
|
-
renderHead(document: Document, head: Head
|
|
432
|
+
renderHead(document: Document, head: Head): void;
|
|
147
433
|
}
|
|
148
434
|
|
|
149
435
|
interface BrowserRoute extends Route {
|
|
@@ -156,7 +442,7 @@ declare class BrowserRouterProvider extends RouterProvider<BrowserRoute> {
|
|
|
156
442
|
add(entry: PageRouteEntry): void;
|
|
157
443
|
protected readonly configure: _alepha_core.HookDescriptor<"configure">;
|
|
158
444
|
transition(url: URL, options?: TransitionOptions): Promise<RouterRenderResult>;
|
|
159
|
-
root(state: RouterState, context
|
|
445
|
+
root(state: RouterState, context: PageReactContext): ReactNode;
|
|
160
446
|
}
|
|
161
447
|
|
|
162
448
|
declare const envSchema$1: _alepha_core.TObject<{
|
|
@@ -193,10 +479,7 @@ declare class ReactBrowserProvider {
|
|
|
193
479
|
protected render(options?: {
|
|
194
480
|
url?: string;
|
|
195
481
|
previous?: PreviousLayerData[];
|
|
196
|
-
}): Promise<
|
|
197
|
-
url: string;
|
|
198
|
-
head: Head;
|
|
199
|
-
}>;
|
|
482
|
+
}): Promise<RouterRenderResult>;
|
|
200
483
|
/**
|
|
201
484
|
* Get embedded layers from the server.
|
|
202
485
|
*
|
|
@@ -218,17 +501,45 @@ declare class ReactBrowserProvider {
|
|
|
218
501
|
interface RouterGoOptions {
|
|
219
502
|
replace?: boolean;
|
|
220
503
|
match?: TransitionOptions;
|
|
504
|
+
params?: Record<string, string>;
|
|
221
505
|
}
|
|
222
506
|
interface ReactHydrationState {
|
|
223
|
-
layers?: PreviousLayerData
|
|
224
|
-
links?:
|
|
507
|
+
layers?: Array<PreviousLayerData>;
|
|
508
|
+
links?: ApiLinksResponse;
|
|
225
509
|
}
|
|
226
510
|
|
|
511
|
+
interface NestedViewProps {
|
|
512
|
+
children?: ReactNode;
|
|
513
|
+
}
|
|
514
|
+
/**
|
|
515
|
+
* A component that renders the current view of the nested router layer.
|
|
516
|
+
*
|
|
517
|
+
* To be simple, it renders the `element` of the current child page of a parent page.
|
|
518
|
+
*
|
|
519
|
+
* @example
|
|
520
|
+
* ```tsx
|
|
521
|
+
* import { NestedView } from "@alepha/react";
|
|
522
|
+
*
|
|
523
|
+
* class App {
|
|
524
|
+
* parent = $page({
|
|
525
|
+
* component: () => <NestedView />,
|
|
526
|
+
* });
|
|
527
|
+
*
|
|
528
|
+
* child = $page({
|
|
529
|
+
* parent: this.root,
|
|
530
|
+
* component: () => <div>Child Page</div>,
|
|
531
|
+
* });
|
|
532
|
+
* }
|
|
533
|
+
* ```
|
|
534
|
+
*/
|
|
535
|
+
declare const NestedView: (props: NestedViewProps) => react_jsx_runtime.JSX.Element;
|
|
536
|
+
|
|
227
537
|
declare class RouterHookApi {
|
|
538
|
+
private readonly pages;
|
|
228
539
|
private readonly state;
|
|
229
540
|
private readonly layer;
|
|
230
541
|
private readonly browser?;
|
|
231
|
-
constructor(state: RouterState, layer: {
|
|
542
|
+
constructor(pages: PageRoute[], state: RouterState, layer: {
|
|
232
543
|
path: string;
|
|
233
544
|
}, browser?: ReactBrowserProvider | undefined);
|
|
234
545
|
/**
|
|
@@ -264,29 +575,24 @@ declare class RouterHookApi {
|
|
|
264
575
|
*/
|
|
265
576
|
createHref(pathname: HrefLike, layer?: {
|
|
266
577
|
path: string;
|
|
578
|
+
}, options?: {
|
|
579
|
+
params?: Record<string, any>;
|
|
267
580
|
}): string;
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
* @param path
|
|
277
|
-
*/
|
|
278
|
-
createAnchorProps(path: string): AnchorProps;
|
|
581
|
+
go(path: string, options?: RouterGoOptions): Promise<void>;
|
|
582
|
+
go<T extends object>(path: keyof VirtualRouter<T>, options?: RouterGoOptions): Promise<void>;
|
|
583
|
+
anchor(path: string, options?: {
|
|
584
|
+
params?: Record<string, any>;
|
|
585
|
+
}): AnchorProps;
|
|
586
|
+
anchor<T extends object>(path: keyof VirtualRouter<T>, options?: {
|
|
587
|
+
params?: Record<string, any>;
|
|
588
|
+
}): AnchorProps;
|
|
279
589
|
/**
|
|
280
590
|
* Set query params.
|
|
281
591
|
*
|
|
282
592
|
* @param record
|
|
283
593
|
* @param options
|
|
284
594
|
*/
|
|
285
|
-
setQueryParams(record: Record<string, any
|
|
286
|
-
/**
|
|
287
|
-
* If true, this will merge current query params with the new ones.
|
|
288
|
-
*/
|
|
289
|
-
merge?: boolean;
|
|
595
|
+
setQueryParams(record: Record<string, any> | ((queryParams: Record<string, any>) => Record<string, any>), options?: {
|
|
290
596
|
/**
|
|
291
597
|
* If true, this will add a new entry to the history stack.
|
|
292
598
|
*/
|
|
@@ -299,190 +605,57 @@ type HrefLike = string | {
|
|
|
299
605
|
name?: string;
|
|
300
606
|
};
|
|
301
607
|
};
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
interface PageConfigSchema {
|
|
305
|
-
query?: TSchema$1;
|
|
306
|
-
params?: TSchema$1;
|
|
307
|
-
}
|
|
308
|
-
type TPropsDefault = any;
|
|
309
|
-
type TPropsParentDefault = object;
|
|
310
|
-
interface PageDescriptorOptions<TConfig extends PageConfigSchema = PageConfigSchema, TProps extends object = TPropsDefault, TPropsParent extends object = TPropsParentDefault> {
|
|
311
|
-
name?: string;
|
|
312
|
-
path?: string;
|
|
313
|
-
schema?: TConfig;
|
|
314
|
-
resolve?: (config: PageResolve<TConfig, TPropsParent>) => Async<TProps>;
|
|
315
|
-
component?: FC<TProps & TPropsParent>;
|
|
316
|
-
lazy?: () => Promise<{
|
|
317
|
-
default: FC<TProps & TPropsParent>;
|
|
318
|
-
}>;
|
|
319
|
-
children?: Array<{
|
|
320
|
-
[OPTIONS]: PageDescriptorOptions;
|
|
321
|
-
}>;
|
|
322
|
-
parent?: {
|
|
323
|
-
[OPTIONS]: PageDescriptorOptions<any, TPropsParent>;
|
|
324
|
-
};
|
|
325
|
-
can?: () => boolean;
|
|
326
|
-
head?: Head | ((props: TProps, previous?: Head) => Head);
|
|
327
|
-
errorHandler?: FC<{
|
|
328
|
-
error: Error;
|
|
329
|
-
url: string;
|
|
330
|
-
}>;
|
|
331
|
-
}
|
|
332
|
-
interface PageDescriptor<TConfig extends PageConfigSchema = PageConfigSchema, TProps extends object = TPropsDefault, TPropsParent extends object = TPropsParentDefault> {
|
|
333
|
-
[KIND]: typeof KEY;
|
|
334
|
-
[OPTIONS]: PageDescriptorOptions<TConfig, TProps, TPropsParent>;
|
|
335
|
-
render: (options?: {
|
|
336
|
-
params?: Record<string, string>;
|
|
337
|
-
query?: Record<string, string>;
|
|
338
|
-
}) => Promise<string>;
|
|
339
|
-
go: () => void;
|
|
340
|
-
createAnchorProps: (routerHook: RouterHookApi) => {
|
|
341
|
-
href: string;
|
|
342
|
-
onClick: () => void;
|
|
343
|
-
};
|
|
344
|
-
can: () => boolean;
|
|
345
|
-
}
|
|
346
|
-
declare const $page: {
|
|
347
|
-
<TConfig extends PageConfigSchema = PageConfigSchema, TProps extends object = any, TPropsParent extends object = object>(options: PageDescriptorOptions<TConfig, TProps, TPropsParent>): PageDescriptor<TConfig, TProps, TPropsParent>;
|
|
348
|
-
[KIND]: string;
|
|
608
|
+
type VirtualRouter<T> = {
|
|
609
|
+
[K in keyof T as T[K] extends PageDescriptor ? K : never]: T[K];
|
|
349
610
|
};
|
|
350
|
-
interface Head {
|
|
351
|
-
title?: string;
|
|
352
|
-
titleSeparator?: string;
|
|
353
|
-
htmlAttributes?: Record<string, string>;
|
|
354
|
-
bodyAttributes?: Record<string, string>;
|
|
355
|
-
meta?: Array<{
|
|
356
|
-
name: string;
|
|
357
|
-
content: string;
|
|
358
|
-
}>;
|
|
359
|
-
}
|
|
360
|
-
interface PageRequestConfig<TConfig extends PageConfigSchema = PageConfigSchema> {
|
|
361
|
-
params: TConfig["params"] extends TSchema$1 ? Static$1<TConfig["params"]> : Record<string, string>;
|
|
362
|
-
query: TConfig["query"] extends TSchema$1 ? Static$1<TConfig["query"]> : Record<string, string>;
|
|
363
|
-
}
|
|
364
|
-
type PageResolve<TConfig extends PageConfigSchema = PageConfigSchema, TPropsParent extends object = TPropsParentDefault> = PageRequestConfig<TConfig> & TPropsParent & PageResolveContext;
|
|
365
|
-
interface PageResolveContext {
|
|
366
|
-
url: URL;
|
|
367
|
-
head: Head;
|
|
368
|
-
}
|
|
369
611
|
|
|
370
|
-
declare class
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
protected readonly pages: PageRoute[];
|
|
374
|
-
getPages(): PageRoute[];
|
|
375
|
-
page(name: string): PageRoute;
|
|
376
|
-
root(state: RouterState, context?: PageReactContext): ReactNode;
|
|
377
|
-
createLayers(route: PageRoute, request: PageRequest): Promise<CreateLayersResult>;
|
|
378
|
-
protected getErrorHandler(route: PageRoute): react.FC<{
|
|
379
|
-
error: Error;
|
|
380
|
-
url: string;
|
|
381
|
-
}> | undefined;
|
|
382
|
-
protected createElement(page: PageRoute, props: Record<string, any>): Promise<ReactNode>;
|
|
383
|
-
protected fillHead(page: PageRoute, ctx: PageRequest, props: Record<string, any>): void;
|
|
384
|
-
renderError(e: Error): ReactNode;
|
|
385
|
-
renderEmptyView(): ReactNode;
|
|
386
|
-
href(page: {
|
|
387
|
-
options: {
|
|
388
|
-
name?: string;
|
|
389
|
-
};
|
|
390
|
-
}, params?: Record<string, any>): string;
|
|
391
|
-
compile(path: string, params?: Record<string, string>): string;
|
|
392
|
-
protected renderView(index: number, path: string, view?: ReactNode): ReactNode;
|
|
393
|
-
protected readonly configure: _alepha_core.HookDescriptor<"configure">;
|
|
394
|
-
protected map(pages: Array<{
|
|
395
|
-
value: {
|
|
396
|
-
[OPTIONS]: PageDescriptorOptions;
|
|
397
|
-
};
|
|
398
|
-
}>, target: {
|
|
399
|
-
[OPTIONS]: PageDescriptorOptions;
|
|
400
|
-
}): PageRouteEntry;
|
|
401
|
-
add(entry: PageRouteEntry): void;
|
|
402
|
-
protected createMatch(page: PageRoute): string;
|
|
403
|
-
protected _next: number;
|
|
404
|
-
protected nextId(): string;
|
|
405
|
-
}
|
|
406
|
-
declare const isPageRoute: (it: any) => it is PageRoute;
|
|
407
|
-
interface PageRouteEntry extends Omit<PageDescriptorOptions, "children" | "parent"> {
|
|
408
|
-
children?: PageRouteEntry[];
|
|
409
|
-
}
|
|
410
|
-
interface PageRoute extends PageRouteEntry {
|
|
411
|
-
type: "page";
|
|
412
|
-
name: string;
|
|
413
|
-
parent?: PageRoute;
|
|
414
|
-
match: string;
|
|
415
|
-
}
|
|
416
|
-
interface Layer {
|
|
417
|
-
config?: {
|
|
418
|
-
query?: Record<string, any>;
|
|
419
|
-
params?: Record<string, any>;
|
|
420
|
-
context?: Record<string, any>;
|
|
421
|
-
};
|
|
422
|
-
name: string;
|
|
423
|
-
props?: Record<string, any>;
|
|
424
|
-
error?: Error;
|
|
425
|
-
part?: string;
|
|
426
|
-
element: ReactNode;
|
|
427
|
-
index: number;
|
|
428
|
-
path: string;
|
|
429
|
-
}
|
|
430
|
-
type PreviousLayerData = Omit<Layer, "element">;
|
|
431
|
-
interface AnchorProps {
|
|
432
|
-
href?: string;
|
|
433
|
-
onClick?: (ev: any) => any;
|
|
434
|
-
}
|
|
435
|
-
interface RouterState {
|
|
436
|
-
pathname: string;
|
|
437
|
-
search: string;
|
|
438
|
-
layers: Array<Layer>;
|
|
439
|
-
head: Head;
|
|
612
|
+
declare class RedirectionError extends Error {
|
|
613
|
+
readonly page: HrefLike;
|
|
614
|
+
constructor(page: HrefLike);
|
|
440
615
|
}
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
616
|
+
|
|
617
|
+
/**
|
|
618
|
+
* Props for the ErrorBoundary component.
|
|
619
|
+
*/
|
|
620
|
+
interface ErrorBoundaryProps {
|
|
621
|
+
/**
|
|
622
|
+
* Fallback React node to render when an error is caught.
|
|
623
|
+
* If not provided, a default error message will be shown.
|
|
624
|
+
*/
|
|
625
|
+
fallback: (error: Error) => ReactNode;
|
|
626
|
+
/**
|
|
627
|
+
* Optional callback that receives the error and error info.
|
|
628
|
+
* Use this to log errors to a monitoring service.
|
|
629
|
+
*/
|
|
630
|
+
onError?: (error: Error, info: ErrorInfo) => void;
|
|
445
631
|
}
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
632
|
+
/**
|
|
633
|
+
* State of the ErrorBoundary component.
|
|
634
|
+
*/
|
|
635
|
+
interface ErrorBoundaryState {
|
|
450
636
|
error?: Error;
|
|
451
637
|
}
|
|
452
|
-
interface RouterRenderResult {
|
|
453
|
-
redirect?: string;
|
|
454
|
-
layers: Layer[];
|
|
455
|
-
head: Head;
|
|
456
|
-
element: ReactNode;
|
|
457
|
-
}
|
|
458
|
-
interface PageRequest extends PageReactContext {
|
|
459
|
-
url: URL;
|
|
460
|
-
params: Record<string, any>;
|
|
461
|
-
query: Record<string, string>;
|
|
462
|
-
head: Head;
|
|
463
|
-
previous?: PreviousLayerData[];
|
|
464
|
-
}
|
|
465
|
-
interface CreateLayersResult extends RouterState {
|
|
466
|
-
redirect?: string;
|
|
467
|
-
}
|
|
468
|
-
interface PageReactContext {
|
|
469
|
-
links?: HttpClientLink[];
|
|
470
|
-
}
|
|
471
|
-
|
|
472
|
-
interface NestedViewProps {
|
|
473
|
-
children?: ReactNode;
|
|
474
|
-
}
|
|
475
638
|
/**
|
|
476
|
-
*
|
|
477
|
-
*
|
|
478
|
-
* @param props
|
|
479
|
-
* @constructor
|
|
639
|
+
* A reusable error boundary for catching rendering errors
|
|
640
|
+
* in any part of the React component tree.
|
|
480
641
|
*/
|
|
481
|
-
declare
|
|
642
|
+
declare class ErrorBoundary extends React__default.Component<PropsWithChildren<ErrorBoundaryProps>, ErrorBoundaryState> {
|
|
643
|
+
constructor(props: ErrorBoundaryProps);
|
|
644
|
+
/**
|
|
645
|
+
* Update state so the next render shows the fallback UI.
|
|
646
|
+
*/
|
|
647
|
+
static getDerivedStateFromError(error: Error): ErrorBoundaryState;
|
|
648
|
+
/**
|
|
649
|
+
* Lifecycle method called when an error is caught.
|
|
650
|
+
* You can log the error or perform side effects here.
|
|
651
|
+
*/
|
|
652
|
+
componentDidCatch(error: Error, info: ErrorInfo): void;
|
|
653
|
+
render(): ReactNode;
|
|
654
|
+
}
|
|
482
655
|
|
|
483
656
|
interface LinkProps extends AnchorHTMLAttributes<HTMLAnchorElement> {
|
|
484
657
|
to: string | PageDescriptor;
|
|
485
|
-
children?:
|
|
658
|
+
children?: React__default.ReactNode;
|
|
486
659
|
}
|
|
487
660
|
declare const Link: (props: LinkProps) => react_jsx_runtime.JSX.Element | null;
|
|
488
661
|
|
|
@@ -491,18 +664,27 @@ interface RouterContextValue {
|
|
|
491
664
|
state: RouterState;
|
|
492
665
|
context: PageReactContext;
|
|
493
666
|
}
|
|
494
|
-
declare const RouterContext:
|
|
667
|
+
declare const RouterContext: React.Context<RouterContextValue | undefined>;
|
|
495
668
|
|
|
496
669
|
interface RouterLayerContextValue {
|
|
497
670
|
index: number;
|
|
498
671
|
path: string;
|
|
499
672
|
}
|
|
500
|
-
declare const RouterLayerContext:
|
|
673
|
+
declare const RouterLayerContext: React.Context<RouterLayerContextValue | undefined>;
|
|
501
674
|
|
|
502
|
-
declare const
|
|
675
|
+
declare const useActive: (path: HrefLike) => UseActiveHook;
|
|
676
|
+
interface UseActiveHook {
|
|
677
|
+
isActive: boolean;
|
|
678
|
+
anchorProps: AnchorProps;
|
|
679
|
+
isPending: boolean;
|
|
680
|
+
name?: string;
|
|
681
|
+
}
|
|
503
682
|
|
|
504
|
-
declare const
|
|
505
|
-
|
|
683
|
+
declare const useAlepha: () => Alepha;
|
|
684
|
+
|
|
685
|
+
declare const useClient: <T extends object>(_scope?: ClientScope) => HttpVirtualClient<T>;
|
|
686
|
+
|
|
687
|
+
declare const useInject: <T extends object>(clazz: Service<T>) => T;
|
|
506
688
|
|
|
507
689
|
interface UseQueryParamsHookOptions {
|
|
508
690
|
format?: "base64" | "querystring";
|
|
@@ -528,23 +710,10 @@ declare const useRouterEvents: (opts?: {
|
|
|
528
710
|
|
|
529
711
|
declare const useRouterState: () => RouterState;
|
|
530
712
|
|
|
531
|
-
declare const useActive: (path: HrefLike) => UseActiveHook;
|
|
532
|
-
interface UseActiveHook {
|
|
533
|
-
isActive: boolean;
|
|
534
|
-
anchorProps: AnchorProps;
|
|
535
|
-
isPending: boolean;
|
|
536
|
-
name?: string;
|
|
537
|
-
}
|
|
538
|
-
|
|
539
|
-
declare class RedirectionError extends Error {
|
|
540
|
-
readonly page: HrefLike;
|
|
541
|
-
constructor(page: HrefLike);
|
|
542
|
-
}
|
|
543
|
-
|
|
544
713
|
declare const envSchema: TObject<{
|
|
545
714
|
REACT_SERVER_DIST: TString;
|
|
546
715
|
REACT_SERVER_PREFIX: TString;
|
|
547
|
-
REACT_SSR_ENABLED: TBoolean
|
|
716
|
+
REACT_SSR_ENABLED: TOptional<TBoolean>;
|
|
548
717
|
REACT_ROOT_ID: TString;
|
|
549
718
|
}>;
|
|
550
719
|
declare module "@alepha/core" {
|
|
@@ -562,31 +731,42 @@ declare class ReactServerProvider {
|
|
|
562
731
|
protected readonly serverStaticProvider: ServerStaticProvider;
|
|
563
732
|
protected readonly serverRouterProvider: ServerRouterProvider;
|
|
564
733
|
protected readonly headProvider: ServerHeadProvider;
|
|
734
|
+
protected readonly serverTimingProvider: ServerTimingProvider;
|
|
565
735
|
protected readonly env: {
|
|
736
|
+
REACT_SSR_ENABLED?: boolean | undefined;
|
|
566
737
|
REACT_ROOT_ID: string;
|
|
567
738
|
REACT_SERVER_DIST: string;
|
|
568
739
|
REACT_SERVER_PREFIX: string;
|
|
569
|
-
REACT_SSR_ENABLED: boolean;
|
|
570
740
|
};
|
|
571
741
|
protected readonly ROOT_DIV_REGEX: RegExp;
|
|
572
|
-
|
|
573
|
-
|
|
742
|
+
readonly onConfigure: _alepha_core.HookDescriptor<"configure">;
|
|
743
|
+
get template(): string | undefined;
|
|
744
|
+
protected registerPages(templateLoader: TemplateLoader): Promise<void>;
|
|
574
745
|
protected getPublicDirectory(): string;
|
|
575
746
|
protected configureStaticServer(root: string): Promise<void>;
|
|
576
|
-
protected configureVite(): Promise<void>;
|
|
577
|
-
|
|
747
|
+
protected configureVite(ssrEnabled: boolean): Promise<void>;
|
|
748
|
+
/**
|
|
749
|
+
* For testing purposes, creates a render function that can be used.
|
|
750
|
+
*/
|
|
751
|
+
protected createRenderFunction(name: string, withIndex?: boolean): (options?: {
|
|
578
752
|
params?: Record<string, string>;
|
|
579
753
|
query?: Record<string, string>;
|
|
580
|
-
}) => Promise<
|
|
581
|
-
|
|
582
|
-
|
|
754
|
+
}) => Promise<{
|
|
755
|
+
context: PageRequest;
|
|
756
|
+
html: string;
|
|
757
|
+
}>;
|
|
758
|
+
protected createHandler(page: PageRoute, templateLoader: TemplateLoader): ServerHandler;
|
|
759
|
+
renderToHtml(template: string, state: RouterState, context: PageReactContext): string;
|
|
760
|
+
protected fillTemplate(response: {
|
|
583
761
|
html: string;
|
|
584
762
|
}, app: string, script: string): void;
|
|
585
763
|
}
|
|
764
|
+
type TemplateLoader = () => Promise<string | undefined>;
|
|
586
765
|
|
|
587
766
|
declare module "@alepha/core" {
|
|
588
767
|
interface Hooks {
|
|
589
768
|
"react:browser:render": {
|
|
769
|
+
state: RouterState;
|
|
590
770
|
context: PageReactContext;
|
|
591
771
|
hydration?: ReactHydrationState;
|
|
592
772
|
};
|
|
@@ -596,6 +776,7 @@ declare module "@alepha/core" {
|
|
|
596
776
|
};
|
|
597
777
|
"react:transition:begin": {
|
|
598
778
|
state: RouterState;
|
|
779
|
+
context: PageReactContext;
|
|
599
780
|
};
|
|
600
781
|
"react:transition:success": {
|
|
601
782
|
state: RouterState;
|
|
@@ -603,9 +784,11 @@ declare module "@alepha/core" {
|
|
|
603
784
|
"react:transition:error": {
|
|
604
785
|
error: Error;
|
|
605
786
|
state: RouterState;
|
|
787
|
+
context: PageReactContext;
|
|
606
788
|
};
|
|
607
789
|
"react:transition:end": {
|
|
608
790
|
state: RouterState;
|
|
791
|
+
context: PageReactContext;
|
|
609
792
|
};
|
|
610
793
|
}
|
|
611
794
|
}
|
|
@@ -614,4 +797,4 @@ declare class ReactModule {
|
|
|
614
797
|
constructor();
|
|
615
798
|
}
|
|
616
799
|
|
|
617
|
-
export { $page, type AnchorProps, type CreateLayersResult, type Head, type HrefLike, type Layer, Link, NestedView, type PageConfigSchema, type PageDescriptor, type PageDescriptorOptions, PageDescriptorProvider, type PageReactContext, type PageRequest, type PageRequestConfig, type PageResolve, type
|
|
800
|
+
export { $page, type AnchorProps, ClientOnly, type CreateLayersResult, ErrorBoundary, type Head$1 as Head, type HrefLike, type Layer, Link, NestedView, type PageConfigSchema, type PageDescriptor, type PageDescriptorOptions, PageDescriptorProvider, type PageDescriptorRenderOptions, type PageDescriptorRenderResult, type PageReactContext, type PageRequest, type PageRequestConfig, type PageResolve, type PageRoute, type PageRouteEntry, type PreviousLayerData, ReactBrowserProvider, type ReactHydrationState, ReactModule, ReactServerProvider, RedirectionError, RouterContext, type RouterContextValue, type RouterGoOptions, RouterHookApi, RouterLayerContext, type RouterLayerContextValue, type RouterRenderResult, type RouterStackItem, type RouterState, type TPropsDefault, type TPropsParentDefault, type TransitionOptions, type UseActiveHook, type UseQueryParamsHookOptions, type VirtualRouter, envSchema, isPageRoute, useActive, useAlepha, useClient, useInject, useQueryParams, useRouter, useRouterEvents, useRouterState };
|