@alepha/react 0.7.0 → 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.
Files changed (35) hide show
  1. package/README.md +1 -1
  2. package/dist/index.browser.cjs +21 -21
  3. package/dist/index.browser.js +2 -3
  4. package/dist/index.cjs +151 -83
  5. package/dist/index.d.ts +360 -205
  6. package/dist/index.js +129 -62
  7. package/dist/{useActive-DjpZBEuB.cjs → useRouterState-AdK-XeM2.cjs} +270 -81
  8. package/dist/{useActive-BX41CqY8.js → useRouterState-qoMq7Y9J.js} +272 -84
  9. package/package.json +11 -10
  10. package/src/components/ClientOnly.tsx +35 -0
  11. package/src/components/ErrorBoundary.tsx +1 -1
  12. package/src/components/ErrorViewer.tsx +161 -0
  13. package/src/components/Link.tsx +9 -3
  14. package/src/components/NestedView.tsx +18 -3
  15. package/src/descriptors/$page.ts +139 -30
  16. package/src/errors/RedirectionError.ts +4 -1
  17. package/src/hooks/RouterHookApi.ts +42 -5
  18. package/src/hooks/useAlepha.ts +12 -0
  19. package/src/hooks/useClient.ts +8 -6
  20. package/src/hooks/useInject.ts +2 -2
  21. package/src/hooks/useQueryParams.ts +1 -1
  22. package/src/hooks/useRouter.ts +6 -0
  23. package/src/index.browser.ts +1 -1
  24. package/src/index.shared.ts +11 -5
  25. package/src/index.ts +3 -4
  26. package/src/providers/BrowserRouterProvider.ts +1 -1
  27. package/src/providers/PageDescriptorProvider.ts +72 -21
  28. package/src/providers/ReactBrowserProvider.ts +5 -8
  29. package/src/providers/ReactServerProvider.ts +197 -80
  30. package/dist/index.browser.cjs.map +0 -1
  31. package/dist/index.browser.js.map +0 -1
  32. package/dist/index.cjs.map +0 -1
  33. package/dist/index.js.map +0 -1
  34. package/dist/useActive-BX41CqY8.js.map +0 -1
  35. package/dist/useActive-DjpZBEuB.cjs.map +0 -1
package/dist/index.d.ts CHANGED
@@ -1,9 +1,8 @@
1
1
  import * as _alepha_core from '@alepha/core';
2
- import { Alepha, Static as Static$1, TSchema as TSchema$1, KIND, OPTIONS, Async, Class, TObject as TObject$1 } from '@alepha/core';
3
- import * as _alepha_server from '@alepha/server';
4
- import { HttpClientLink, HttpClient, ApiLinksResponse, ServerRouterProvider, ServerHandler, ServerRequest } from '@alepha/server';
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';
5
4
  import * as React from 'react';
6
- import React__default, { ReactNode, FC, AnchorHTMLAttributes, PropsWithChildren, ErrorInfo } 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,215 +125,137 @@ interface TSchema extends TKind, SchemaOptions {
126
125
  static: unknown;
127
126
  }
128
127
 
129
- interface Head$1 {
130
- title?: string;
131
- htmlAttributes?: Record<string, string>;
132
- bodyAttributes?: Record<string, string>;
133
- meta?: Array<{
134
- name: string;
135
- content: string;
136
- }>;
137
- }
138
- declare class ServerHeadProvider {
139
- renderHead(template: string, head: Head$1): string;
140
- mergeAttributes(existing: string, attrs: Record<string, string>): string;
141
- parseAttributes(attrStr: string): Record<string, string>;
142
- escapeHtml(str: string): string;
143
- }
144
-
145
- declare class BrowserHeadProvider {
146
- renderHead(document: Document, head: Head$1): void;
147
- }
148
-
149
- interface BrowserRoute extends Route {
150
- page: PageRoute;
151
- }
152
- declare class BrowserRouterProvider extends RouterProvider<BrowserRoute> {
153
- protected readonly log: _alepha_core.Logger;
154
- protected readonly alepha: Alepha;
155
- protected readonly pageDescriptorProvider: PageDescriptorProvider;
156
- add(entry: PageRouteEntry): void;
157
- protected readonly configure: _alepha_core.HookDescriptor<"configure">;
158
- transition(url: URL, options?: TransitionOptions): Promise<RouterRenderResult>;
159
- root(state: RouterState, context: PageReactContext): ReactNode;
128
+ interface ClientOnlyProps {
129
+ fallback?: ReactNode;
130
+ disabled?: boolean;
160
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;
161
143
 
162
- declare const envSchema$1: _alepha_core.TObject<{
163
- REACT_ROOT_ID: TString;
164
- }>;
165
- declare module "@alepha/core" {
166
- interface Env extends Partial<Static$1<typeof envSchema$1>> {
167
- }
144
+ declare const KEY = "PAGE";
145
+ interface PageConfigSchema {
146
+ query?: TSchema$1;
147
+ params?: TSchema$1;
168
148
  }
169
- declare class ReactBrowserProvider {
170
- protected readonly log: _alepha_core.Logger;
171
- protected readonly client: HttpClient;
172
- protected readonly alepha: Alepha;
173
- protected readonly router: BrowserRouterProvider;
174
- protected readonly headProvider: BrowserHeadProvider;
175
- protected readonly env: {
176
- REACT_ROOT_ID: string;
177
- };
178
- protected root: Root;
179
- transitioning?: {
180
- to: string;
181
- };
182
- state: RouterState;
183
- get document(): Document;
184
- get history(): History;
185
- get url(): string;
186
- invalidate(props?: Record<string, any>): Promise<void>;
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"> {
187
152
  /**
153
+ * Name your page.
188
154
  *
189
- * @param url
190
- * @param options
155
+ * @default Descriptor key
191
156
  */
192
- go(url: string, options?: RouterGoOptions): Promise<void>;
193
- protected render(options?: {
194
- url?: string;
195
- previous?: PreviousLayerData[];
196
- }): Promise<RouterRenderResult>;
157
+ name?: string;
197
158
  /**
198
- * Get embedded layers from the server.
199
- *
200
- * @protected
159
+ * Optional description of the page.
201
160
  */
202
- protected getHydrationState(): ReactHydrationState | undefined;
161
+ description?: string;
203
162
  /**
163
+ * Add a pathname to the page.
204
164
  *
205
- * @protected
206
- */
207
- protected getRootElement(): HTMLElement;
208
- /**
165
+ * Pathname can contain parameters, like `/post/:slug`.
209
166
  *
210
- * @protected
167
+ * @default ""
211
168
  */
212
- readonly ready: _alepha_core.HookDescriptor<"ready">;
213
- readonly onTransitionEnd: _alepha_core.HookDescriptor<"react:transition:end">;
214
- }
215
- interface RouterGoOptions {
216
- replace?: boolean;
217
- match?: TransitionOptions;
218
- params?: Record<string, string>;
219
- }
220
- interface ReactHydrationState {
221
- layers?: PreviousLayerData[];
222
- links?: HttpClientLink[];
223
- }
224
-
225
- declare class RouterHookApi {
226
- private readonly state;
227
- private readonly layer;
228
- private readonly browser?;
229
- constructor(state: RouterState, layer: {
230
- path: string;
231
- }, browser?: ReactBrowserProvider | undefined);
232
- /**
233
- *
234
- */
235
- get current(): RouterState;
169
+ path?: string;
236
170
  /**
237
- *
171
+ * Add an input schema to define:
172
+ * - `params`: parameters from the pathname.
173
+ * - `query`: query parameters from the URL.
238
174
  */
239
- get pathname(): string;
175
+ schema?: TConfig;
240
176
  /**
177
+ * Load data before rendering the page.
241
178
  *
242
- */
243
- get query(): Record<string, string>;
244
- /**
179
+ * This function receives
180
+ * - the request context and
181
+ * - the parent props (if page has a parent)
245
182
  *
246
- */
247
- back(): Promise<void>;
248
- /**
183
+ * In SSR, the returned data will be serialized and sent to the client, then reused during the client-side hydration.
249
184
  *
250
- */
251
- forward(): Promise<void>;
252
- /**
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.
253
187
  *
254
- * @param props
188
+ * RedirectError can be thrown to redirect the user to another page.
255
189
  */
256
- invalidate(props?: Record<string, any>): Promise<void>;
190
+ resolve?: (context: PageResolve<TConfig, TPropsParent>) => Async<TProps>;
257
191
  /**
258
- * Create a valid href for the given pathname.
192
+ * The component to render when the page is loaded.
259
193
  *
260
- * @param pathname
261
- * @param layer
194
+ * If `lazy` is defined, this will be ignored.
195
+ * Prefer using `lazy` to improve the initial loading time.
262
196
  */
263
- createHref(pathname: HrefLike, layer?: {
264
- path: string;
265
- }): string;
266
- go(path: string, options?: RouterGoOptions): Promise<void>;
267
- go<T extends object>(path: keyof VirtualRouter<T>, options?: RouterGoOptions): Promise<void>;
268
- anchor(path: string): AnchorProps;
197
+ component?: FC<TProps & TPropsParent>;
269
198
  /**
270
- * Set query params.
199
+ * Lazy load the component when the page is loaded.
271
200
  *
272
- * @param record
273
- * @param options
201
+ * It's recommended to use this for components to improve the initial loading time
202
+ * and enable code-splitting.
274
203
  */
275
- setQueryParams(record: Record<string, any> | ((queryParams: Record<string, any>) => Record<string, any>), options?: {
276
- /**
277
- * If true, this will add a new entry to the history stack.
278
- */
279
- push?: boolean;
280
- }): void;
281
- }
282
- type HrefLike = string | {
283
- options: {
284
- path?: string;
285
- name?: string;
286
- };
287
- };
288
- type VirtualRouter<T> = {
289
- [K in keyof T as T[K] extends PageDescriptor ? K : never]: T[K];
290
- };
291
-
292
- declare const KEY = "PAGE";
293
- interface PageConfigSchema {
294
- query?: TSchema$1;
295
- params?: TSchema$1;
296
- }
297
- type TPropsDefault = any;
298
- type TPropsParentDefault = object;
299
- interface PageDescriptorOptions<TConfig extends PageConfigSchema = PageConfigSchema, TProps extends object = TPropsDefault, TPropsParent extends object = TPropsParentDefault> {
300
- name?: string;
301
- path?: string;
302
- schema?: TConfig;
303
- resolve?: (config: PageResolve<TConfig, TPropsParent>) => Async<TProps>;
304
- component?: FC<TProps & TPropsParent>;
305
204
  lazy?: () => Promise<{
306
205
  default: FC<TProps & TPropsParent>;
307
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
+ */
308
214
  children?: Array<{
309
215
  [OPTIONS]: PageDescriptorOptions;
310
216
  }>;
311
217
  parent?: {
312
- [OPTIONS]: PageDescriptorOptions<any, TPropsParent>;
218
+ [OPTIONS]: PageDescriptorOptions<PageConfigSchema, TPropsParent>;
313
219
  };
314
220
  can?: () => boolean;
315
- head?: Head | ((props: TProps, previous?: Head) => Head);
221
+ head?: Head$1 | ((props: TProps, previous?: Head$1) => Head$1);
316
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;
317
230
  }
318
231
  interface PageDescriptor<TConfig extends PageConfigSchema = PageConfigSchema, TProps extends object = TPropsDefault, TPropsParent extends object = TPropsParentDefault> {
319
232
  [KIND]: typeof KEY;
320
233
  [OPTIONS]: PageDescriptorOptions<TConfig, TProps, TPropsParent>;
321
- render: (options?: {
322
- params?: Record<string, string>;
323
- query?: Record<string, string>;
324
- }) => Promise<string>;
325
- go: () => void;
326
- createAnchorProps: (routerHook: RouterHookApi) => {
327
- href: string;
328
- onClick: () => void;
329
- };
330
- can: () => boolean;
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>;
331
239
  }
240
+ /**
241
+ * Main descriptor for defining a React route in the application.
242
+ */
332
243
  declare const $page: {
333
- <TConfig extends PageConfigSchema = PageConfigSchema, TProps extends object = any, TPropsParent extends object = object>(options: PageDescriptorOptions<TConfig, TProps, TPropsParent>): PageDescriptor<TConfig, TProps, TPropsParent>;
244
+ <TConfig extends PageConfigSchema = PageConfigSchema, TProps extends object = any, TPropsParent extends object = TPropsParentDefault>(options: PageDescriptorOptions<TConfig, TProps, TPropsParent>): PageDescriptor<TConfig, TProps, TPropsParent>;
334
245
  [KIND]: string;
335
246
  };
336
- interface Head {
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
+ }
256
+ interface Head$1 {
337
257
  title?: string;
258
+ description?: string;
338
259
  titleSeparator?: string;
339
260
  htmlAttributes?: Record<string, string>;
340
261
  bodyAttributes?: Record<string, string>;
@@ -342,6 +263,32 @@ interface Head {
342
263
  name: string;
343
264
  content: string;
344
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
+ };
345
292
  }
346
293
  interface PageRequestConfig<TConfig extends PageConfigSchema = PageConfigSchema> {
347
294
  params: TConfig["params"] extends TSchema$1 ? Static$1<TConfig["params"]> : Record<string, string>;
@@ -349,18 +296,32 @@ interface PageRequestConfig<TConfig extends PageConfigSchema = PageConfigSchema>
349
296
  }
350
297
  type PageResolve<TConfig extends PageConfigSchema = PageConfigSchema, TPropsParent extends object = TPropsParentDefault> = PageRequestConfig<TConfig> & TPropsParent & PageReactContext;
351
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
+ }
352
306
  declare class PageDescriptorProvider {
353
307
  protected readonly log: _alepha_core.Logger;
308
+ protected readonly env: {
309
+ REACT_STRICT_MODE: boolean;
310
+ };
354
311
  protected readonly alepha: Alepha;
355
312
  protected readonly pages: PageRoute[];
356
313
  getPages(): PageRoute[];
357
314
  page(name: string): PageRoute;
315
+ url(name: string, options?: {
316
+ params?: Record<string, string>;
317
+ base?: string;
318
+ }): URL;
358
319
  root(state: RouterState, context: PageReactContext): ReactNode;
359
320
  createLayers(route: PageRoute, request: PageRequest): Promise<CreateLayersResult>;
360
321
  protected getErrorHandler(route: PageRoute): ((error: Error) => ReactNode) | undefined;
361
322
  protected createElement(page: PageRoute, props: Record<string, any>): Promise<ReactNode>;
362
323
  protected fillHead(page: PageRoute, ctx: PageRequest, props: Record<string, any>): void;
363
- renderError(e: Error): ReactNode;
324
+ renderError(error: Error): ReactNode;
364
325
  renderEmptyView(): ReactNode;
365
326
  href(page: {
366
327
  options: {
@@ -368,7 +329,7 @@ declare class PageDescriptorProvider {
368
329
  };
369
330
  }, params?: Record<string, any>): string;
370
331
  compile(path: string, params?: Record<string, string>): string;
371
- protected renderView(index: number, path: string, view?: ReactNode): ReactNode;
332
+ protected renderView(index: number, path: string, view: ReactNode | undefined, page: PageRoute): ReactNode;
372
333
  protected readonly configure: _alepha_core.HookDescriptor<"configure">;
373
334
  protected map(pages: Array<{
374
335
  value: {
@@ -406,7 +367,7 @@ interface Layer {
406
367
  index: number;
407
368
  path: string;
408
369
  }
409
- type PreviousLayerData = Omit<Layer, "element">;
370
+ type PreviousLayerData = Omit<Layer, "element" | "index" | "path">;
410
371
  interface AnchorProps {
411
372
  href: string;
412
373
  onClick: (ev: any) => any;
@@ -446,27 +407,212 @@ interface CreateLayersResult extends RouterState {
446
407
  */
447
408
  interface PageReactContext {
448
409
  url: URL;
449
- head: Head;
410
+ head: Head$1;
450
411
  onError: (error: Error) => ReactNode;
451
412
  links?: ApiLinksResponse;
452
413
  }
453
414
 
415
+ interface Head {
416
+ title?: string;
417
+ htmlAttributes?: Record<string, string>;
418
+ bodyAttributes?: Record<string, string>;
419
+ meta?: Array<{
420
+ name: string;
421
+ content: string;
422
+ }>;
423
+ }
424
+ declare class ServerHeadProvider {
425
+ renderHead(template: string, head: Head): string;
426
+ mergeAttributes(existing: string, attrs: Record<string, string>): string;
427
+ parseAttributes(attrStr: string): Record<string, string>;
428
+ escapeHtml(str: string): string;
429
+ }
430
+
431
+ declare class BrowserHeadProvider {
432
+ renderHead(document: Document, head: Head): void;
433
+ }
434
+
435
+ interface BrowserRoute extends Route {
436
+ page: PageRoute;
437
+ }
438
+ declare class BrowserRouterProvider extends RouterProvider<BrowserRoute> {
439
+ protected readonly log: _alepha_core.Logger;
440
+ protected readonly alepha: Alepha;
441
+ protected readonly pageDescriptorProvider: PageDescriptorProvider;
442
+ add(entry: PageRouteEntry): void;
443
+ protected readonly configure: _alepha_core.HookDescriptor<"configure">;
444
+ transition(url: URL, options?: TransitionOptions): Promise<RouterRenderResult>;
445
+ root(state: RouterState, context: PageReactContext): ReactNode;
446
+ }
447
+
448
+ declare const envSchema$1: _alepha_core.TObject<{
449
+ REACT_ROOT_ID: TString;
450
+ }>;
451
+ declare module "@alepha/core" {
452
+ interface Env extends Partial<Static$1<typeof envSchema$1>> {
453
+ }
454
+ }
455
+ declare class ReactBrowserProvider {
456
+ protected readonly log: _alepha_core.Logger;
457
+ protected readonly client: HttpClient;
458
+ protected readonly alepha: Alepha;
459
+ protected readonly router: BrowserRouterProvider;
460
+ protected readonly headProvider: BrowserHeadProvider;
461
+ protected readonly env: {
462
+ REACT_ROOT_ID: string;
463
+ };
464
+ protected root: Root;
465
+ transitioning?: {
466
+ to: string;
467
+ };
468
+ state: RouterState;
469
+ get document(): Document;
470
+ get history(): History;
471
+ get url(): string;
472
+ invalidate(props?: Record<string, any>): Promise<void>;
473
+ /**
474
+ *
475
+ * @param url
476
+ * @param options
477
+ */
478
+ go(url: string, options?: RouterGoOptions): Promise<void>;
479
+ protected render(options?: {
480
+ url?: string;
481
+ previous?: PreviousLayerData[];
482
+ }): Promise<RouterRenderResult>;
483
+ /**
484
+ * Get embedded layers from the server.
485
+ *
486
+ * @protected
487
+ */
488
+ protected getHydrationState(): ReactHydrationState | undefined;
489
+ /**
490
+ *
491
+ * @protected
492
+ */
493
+ protected getRootElement(): HTMLElement;
494
+ /**
495
+ *
496
+ * @protected
497
+ */
498
+ readonly ready: _alepha_core.HookDescriptor<"ready">;
499
+ readonly onTransitionEnd: _alepha_core.HookDescriptor<"react:transition:end">;
500
+ }
501
+ interface RouterGoOptions {
502
+ replace?: boolean;
503
+ match?: TransitionOptions;
504
+ params?: Record<string, string>;
505
+ }
506
+ interface ReactHydrationState {
507
+ layers?: Array<PreviousLayerData>;
508
+ links?: ApiLinksResponse;
509
+ }
510
+
454
511
  interface NestedViewProps {
455
512
  children?: ReactNode;
456
513
  }
457
514
  /**
458
- * Nested view component
515
+ * A component that renders the current view of the nested router layer.
459
516
  *
460
- * @param props
461
- * @constructor
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
+ * ```
462
534
  */
463
535
  declare const NestedView: (props: NestedViewProps) => react_jsx_runtime.JSX.Element;
464
536
 
465
- interface LinkProps extends AnchorHTMLAttributes<HTMLAnchorElement> {
466
- to: string | PageDescriptor;
467
- children?: React__default.ReactNode;
537
+ declare class RouterHookApi {
538
+ private readonly pages;
539
+ private readonly state;
540
+ private readonly layer;
541
+ private readonly browser?;
542
+ constructor(pages: PageRoute[], state: RouterState, layer: {
543
+ path: string;
544
+ }, browser?: ReactBrowserProvider | undefined);
545
+ /**
546
+ *
547
+ */
548
+ get current(): RouterState;
549
+ /**
550
+ *
551
+ */
552
+ get pathname(): string;
553
+ /**
554
+ *
555
+ */
556
+ get query(): Record<string, string>;
557
+ /**
558
+ *
559
+ */
560
+ back(): Promise<void>;
561
+ /**
562
+ *
563
+ */
564
+ forward(): Promise<void>;
565
+ /**
566
+ *
567
+ * @param props
568
+ */
569
+ invalidate(props?: Record<string, any>): Promise<void>;
570
+ /**
571
+ * Create a valid href for the given pathname.
572
+ *
573
+ * @param pathname
574
+ * @param layer
575
+ */
576
+ createHref(pathname: HrefLike, layer?: {
577
+ path: string;
578
+ }, options?: {
579
+ params?: Record<string, any>;
580
+ }): string;
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;
589
+ /**
590
+ * Set query params.
591
+ *
592
+ * @param record
593
+ * @param options
594
+ */
595
+ setQueryParams(record: Record<string, any> | ((queryParams: Record<string, any>) => Record<string, any>), options?: {
596
+ /**
597
+ * If true, this will add a new entry to the history stack.
598
+ */
599
+ push?: boolean;
600
+ }): void;
601
+ }
602
+ type HrefLike = string | {
603
+ options: {
604
+ path?: string;
605
+ name?: string;
606
+ };
607
+ };
608
+ type VirtualRouter<T> = {
609
+ [K in keyof T as T[K] extends PageDescriptor ? K : never]: T[K];
610
+ };
611
+
612
+ declare class RedirectionError extends Error {
613
+ readonly page: HrefLike;
614
+ constructor(page: HrefLike);
468
615
  }
469
- declare const Link: (props: LinkProps) => react_jsx_runtime.JSX.Element | null;
470
616
 
471
617
  /**
472
618
  * Props for the ErrorBoundary component.
@@ -507,6 +653,12 @@ declare class ErrorBoundary extends React__default.Component<PropsWithChildren<E
507
653
  render(): ReactNode;
508
654
  }
509
655
 
656
+ interface LinkProps extends AnchorHTMLAttributes<HTMLAnchorElement> {
657
+ to: string | PageDescriptor;
658
+ children?: React__default.ReactNode;
659
+ }
660
+ declare const Link: (props: LinkProps) => react_jsx_runtime.JSX.Element | null;
661
+
510
662
  interface RouterContextValue {
511
663
  alepha: Alepha;
512
664
  state: RouterState;
@@ -520,10 +672,19 @@ interface RouterLayerContextValue {
520
672
  }
521
673
  declare const RouterLayerContext: React.Context<RouterLayerContextValue | undefined>;
522
674
 
523
- declare const useInject: <T extends object>(clazz: Class<T>) => T;
675
+ declare const useActive: (path: HrefLike) => UseActiveHook;
676
+ interface UseActiveHook {
677
+ isActive: boolean;
678
+ anchorProps: AnchorProps;
679
+ isPending: boolean;
680
+ name?: string;
681
+ }
682
+
683
+ declare const useAlepha: () => Alepha;
684
+
685
+ declare const useClient: <T extends object>(_scope?: ClientScope) => HttpVirtualClient<T>;
524
686
 
525
- declare const useClient: () => HttpClient;
526
- declare const useApi: <T extends object>() => _alepha_server.HttpVirtualClient<T>;
687
+ declare const useInject: <T extends object>(clazz: Service<T>) => T;
527
688
 
528
689
  interface UseQueryParamsHookOptions {
529
690
  format?: "base64" | "querystring";
@@ -549,23 +710,10 @@ declare const useRouterEvents: (opts?: {
549
710
 
550
711
  declare const useRouterState: () => RouterState;
551
712
 
552
- declare const useActive: (path: HrefLike) => UseActiveHook;
553
- interface UseActiveHook {
554
- isActive: boolean;
555
- anchorProps: AnchorProps;
556
- isPending: boolean;
557
- name?: string;
558
- }
559
-
560
- declare class RedirectionError extends Error {
561
- readonly page: HrefLike;
562
- constructor(page: HrefLike);
563
- }
564
-
565
713
  declare const envSchema: TObject<{
566
714
  REACT_SERVER_DIST: TString;
567
715
  REACT_SERVER_PREFIX: TString;
568
- REACT_SSR_ENABLED: TBoolean;
716
+ REACT_SSR_ENABLED: TOptional<TBoolean>;
569
717
  REACT_ROOT_ID: TString;
570
718
  }>;
571
719
  declare module "@alepha/core" {
@@ -583,30 +731,37 @@ declare class ReactServerProvider {
583
731
  protected readonly serverStaticProvider: ServerStaticProvider;
584
732
  protected readonly serverRouterProvider: ServerRouterProvider;
585
733
  protected readonly headProvider: ServerHeadProvider;
734
+ protected readonly serverTimingProvider: ServerTimingProvider;
586
735
  protected readonly env: {
736
+ REACT_SSR_ENABLED?: boolean | undefined;
587
737
  REACT_ROOT_ID: string;
588
738
  REACT_SERVER_DIST: string;
589
739
  REACT_SERVER_PREFIX: string;
590
- REACT_SSR_ENABLED: boolean;
591
740
  };
592
741
  protected readonly ROOT_DIV_REGEX: RegExp;
593
- protected readonly configure: _alepha_core.HookDescriptor<"configure">;
594
- protected registerPages(templateLoader: () => Promise<string | undefined>): Promise<void>;
742
+ readonly onConfigure: _alepha_core.HookDescriptor<"configure">;
743
+ get template(): string | undefined;
744
+ protected registerPages(templateLoader: TemplateLoader): Promise<void>;
595
745
  protected getPublicDirectory(): string;
596
746
  protected configureStaticServer(root: string): Promise<void>;
597
- protected configureVite(): Promise<void>;
747
+ protected configureVite(ssrEnabled: boolean): Promise<void>;
598
748
  /**
599
749
  * For testing purposes, creates a render function that can be used.
600
750
  */
601
- protected createRenderFunction(name: string): (options?: {
751
+ protected createRenderFunction(name: string, withIndex?: boolean): (options?: {
602
752
  params?: Record<string, string>;
603
753
  query?: Record<string, string>;
604
- }) => Promise<string>;
605
- protected createHandler(page: PageRoute, templateLoader: () => Promise<string | undefined>): ServerHandler;
606
- fillTemplate(response: {
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: {
607
761
  html: string;
608
762
  }, app: string, script: string): void;
609
763
  }
764
+ type TemplateLoader = () => Promise<string | undefined>;
610
765
 
611
766
  declare module "@alepha/core" {
612
767
  interface Hooks {
@@ -642,4 +797,4 @@ declare class ReactModule {
642
797
  constructor();
643
798
  }
644
799
 
645
- export { $page, type AnchorProps, type CreateLayersResult, ErrorBoundary, type Head, type HrefLike, type Layer, Link, NestedView, type PageConfigSchema, type PageDescriptor, type PageDescriptorOptions, PageDescriptorProvider, 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, useApi, useClient, useInject, useQueryParams, useRouter, useRouterEvents, useRouterState };
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 };