@fluojs/react 0.1.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/LICENSE +21 -0
- package/README.ko.md +715 -0
- package/README.md +729 -0
- package/dist/client/errors.d.ts +12 -0
- package/dist/client/errors.d.ts.map +1 -0
- package/dist/client/errors.js +19 -0
- package/dist/client/hooks.d.ts +38 -0
- package/dist/client/hooks.d.ts.map +1 -0
- package/dist/client/hooks.js +56 -0
- package/dist/client/link.d.ts +13 -0
- package/dist/client/link.d.ts.map +1 -0
- package/dist/client/link.js +39 -0
- package/dist/client/provider.d.ts +12 -0
- package/dist/client/provider.d.ts.map +1 -0
- package/dist/client/provider.js +54 -0
- package/dist/client/search-params.d.ts +17 -0
- package/dist/client/search-params.d.ts.map +1 -0
- package/dist/client/search-params.js +39 -0
- package/dist/client/snapshot.d.ts +15 -0
- package/dist/client/snapshot.d.ts.map +1 -0
- package/dist/client/snapshot.js +57 -0
- package/dist/client/store.d.ts +26 -0
- package/dist/client/store.d.ts.map +1 -0
- package/dist/client/store.js +138 -0
- package/dist/client/types.d.ts +63 -0
- package/dist/client/types.d.ts.map +1 -0
- package/dist/client/types.js +1 -0
- package/dist/client.d.ts +9 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +5 -0
- package/dist/decorators.d.ts +80 -0
- package/dist/decorators.d.ts.map +1 -0
- package/dist/decorators.js +194 -0
- package/dist/experimental/rsc-diagnostics.d.ts +13 -0
- package/dist/experimental/rsc-diagnostics.d.ts.map +1 -0
- package/dist/experimental/rsc-diagnostics.js +58 -0
- package/dist/experimental/rsc-flight-response.d.ts +15 -0
- package/dist/experimental/rsc-flight-response.d.ts.map +1 -0
- package/dist/experimental/rsc-flight-response.js +76 -0
- package/dist/experimental/rsc-manifest.d.ts +13 -0
- package/dist/experimental/rsc-manifest.d.ts.map +1 -0
- package/dist/experimental/rsc-manifest.js +88 -0
- package/dist/experimental/rsc-types.d.ts +118 -0
- package/dist/experimental/rsc-types.d.ts.map +1 -0
- package/dist/experimental/rsc-types.js +50 -0
- package/dist/experimental/rsc.d.ts +11 -0
- package/dist/experimental/rsc.d.ts.map +1 -0
- package/dist/experimental/rsc.js +8 -0
- package/dist/experimental/server-functions-client.d.ts +14 -0
- package/dist/experimental/server-functions-client.d.ts.map +1 -0
- package/dist/experimental/server-functions-client.js +120 -0
- package/dist/experimental/server-functions-configuration.d.ts +17 -0
- package/dist/experimental/server-functions-configuration.d.ts.map +1 -0
- package/dist/experimental/server-functions-configuration.js +68 -0
- package/dist/experimental/server-functions-errors.d.ts +19 -0
- package/dist/experimental/server-functions-errors.d.ts.map +1 -0
- package/dist/experimental/server-functions-errors.js +22 -0
- package/dist/experimental/server-functions-reference.d.ts +22 -0
- package/dist/experimental/server-functions-reference.d.ts.map +1 -0
- package/dist/experimental/server-functions-reference.js +76 -0
- package/dist/experimental/server-functions-serialization.d.ts +37 -0
- package/dist/experimental/server-functions-serialization.d.ts.map +1 -0
- package/dist/experimental/server-functions-serialization.js +158 -0
- package/dist/experimental/server-functions-server.d.ts +14 -0
- package/dist/experimental/server-functions-server.d.ts.map +1 -0
- package/dist/experimental/server-functions-server.js +176 -0
- package/dist/experimental/server-functions-types.d.ts +86 -0
- package/dist/experimental/server-functions-types.d.ts.map +1 -0
- package/dist/experimental/server-functions-types.js +35 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +4 -0
- package/dist/module.d.ts +40 -0
- package/dist/module.d.ts.map +1 -0
- package/dist/module.js +58 -0
- package/dist/render-stream.d.ts +27 -0
- package/dist/render-stream.d.ts.map +1 -0
- package/dist/render-stream.js +135 -0
- package/dist/render.d.ts +50 -0
- package/dist/render.d.ts.map +1 -0
- package/dist/render.js +201 -0
- package/dist/server-entry.d.ts +87 -0
- package/dist/server-entry.d.ts.map +1 -0
- package/dist/server-entry.js +126 -0
- package/dist/types.d.ts +11 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +1 -0
- package/dist/vite/asset-utils.d.ts +57 -0
- package/dist/vite/asset-utils.d.ts.map +1 -0
- package/dist/vite/asset-utils.js +184 -0
- package/dist/vite/create-asset-manifest.d.ts +9 -0
- package/dist/vite/create-asset-manifest.d.ts.map +1 -0
- package/dist/vite/create-asset-manifest.js +127 -0
- package/dist/vite/diagnostics.d.ts +27 -0
- package/dist/vite/diagnostics.d.ts.map +1 -0
- package/dist/vite/diagnostics.js +47 -0
- package/dist/vite/parse-manifest.d.ts +18 -0
- package/dist/vite/parse-manifest.d.ts.map +1 -0
- package/dist/vite/parse-manifest.js +168 -0
- package/dist/vite/types.d.ts +187 -0
- package/dist/vite/types.d.ts.map +1 -0
- package/dist/vite/types.js +59 -0
- package/dist/vite.d.ts +3 -0
- package/dist/vite.d.ts.map +1 -0
- package/dist/vite.js +1 -0
- package/package.json +68 -0
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export { ReactClientNavigationError, ReactClientRouterContextError } from './client/errors.js';
|
|
2
|
+
export type { ReactClientNavigationErrorCode } from './client/errors.js';
|
|
3
|
+
export { useNavigation, useParams, usePathname, useRouter, useRouterState, useSearchParams, } from './client/hooks.js';
|
|
4
|
+
export { Link } from './client/link.js';
|
|
5
|
+
export type { LinkProps } from './client/link.js';
|
|
6
|
+
export { ReactClientRouterProvider } from './client/provider.js';
|
|
7
|
+
export { createReactRouteSnapshot } from './client/snapshot.js';
|
|
8
|
+
export type { ReactClientRouterProviderProps, ReactNavigationSnapshot, ReactNavigationStatus, ReactNavigationType, ReactReadonlySearchParams, ReactRouteSnapshot, ReactRouteSnapshotInput, ReactRouter, } from './client/types.js';
|
|
9
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,0BAA0B,EAAE,6BAA6B,EAAE,MAAM,oBAAoB,CAAC;AAC/F,YAAY,EAAE,8BAA8B,EAAE,MAAM,oBAAoB,CAAC;AACzE,OAAO,EACL,aAAa,EACb,SAAS,EACT,WAAW,EACX,SAAS,EACT,cAAc,EACd,eAAe,GAChB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AACxC,YAAY,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,yBAAyB,EAAE,MAAM,sBAAsB,CAAC;AACjE,OAAO,EAAE,wBAAwB,EAAE,MAAM,sBAAsB,CAAC;AAChE,YAAY,EACV,8BAA8B,EAC9B,uBAAuB,EACvB,qBAAqB,EACrB,mBAAmB,EACnB,yBAAyB,EACzB,kBAAkB,EAClB,uBAAuB,EACvB,WAAW,GACZ,MAAM,mBAAmB,CAAC"}
|
package/dist/client.js
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { ReactClientNavigationError, ReactClientRouterContextError } from './client/errors.js';
|
|
2
|
+
export { useNavigation, useParams, usePathname, useRouter, useRouterState, useSearchParams } from './client/hooks.js';
|
|
3
|
+
export { Link } from './client/link.js';
|
|
4
|
+
export { ReactClientRouterProvider } from './client/provider.js';
|
|
5
|
+
export { createReactRouteSnapshot } from './client/snapshot.js';
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import type { MetadataPropertyKey } from '@fluojs/core';
|
|
2
|
+
type StandardClassDecoratorFn = (value: Function, context: ClassDecoratorContext) => void;
|
|
3
|
+
type StandardMethodDecoratorFn = (value: Function, context: ClassMethodDecoratorContext) => void;
|
|
4
|
+
type LegacyClassDecoratorFn = (target: Function) => void;
|
|
5
|
+
type LegacyMethodDecoratorFn = (target: object, propertyKey: MetadataPropertyKey, descriptor?: PropertyDescriptor) => void;
|
|
6
|
+
type ClassDecoratorLike = StandardClassDecoratorFn & LegacyClassDecoratorFn;
|
|
7
|
+
type MethodDecoratorLike = StandardMethodDecoratorFn & LegacyMethodDecoratorFn;
|
|
8
|
+
/**
|
|
9
|
+
* Additional render-facing metadata stored by `@Path(...)` for the future React renderer.
|
|
10
|
+
*
|
|
11
|
+
* @remarks
|
|
12
|
+
* These options are intentionally runtime-neutral. They are recorded for diagnostics and
|
|
13
|
+
* later rendering integration without changing HTTP route matching, route grammar, DTO
|
|
14
|
+
* binding, validation, or request dispatch.
|
|
15
|
+
*/
|
|
16
|
+
export type ReactPathOptions = Readonly<Record<string, unknown>>;
|
|
17
|
+
/**
|
|
18
|
+
* React router marker metadata written by `@Router(...)`.
|
|
19
|
+
*/
|
|
20
|
+
export type ReactRouterMetadata = {
|
|
21
|
+
/** Marker that distinguishes React routers from plain HTTP controllers. */
|
|
22
|
+
readonly kind: 'router';
|
|
23
|
+
/** Base path also written to the HTTP controller metadata. */
|
|
24
|
+
readonly basePath: string;
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* React render metadata written by `@Path(...)`.
|
|
28
|
+
*/
|
|
29
|
+
export type ReactPathMetadata = {
|
|
30
|
+
/** Marker that distinguishes React page handlers from plain HTTP routes. */
|
|
31
|
+
readonly kind: 'path';
|
|
32
|
+
/** Route path also written to the HTTP `GET` metadata. */
|
|
33
|
+
readonly path: string;
|
|
34
|
+
/** Optional render-facing metadata for the future React rendering layer. */
|
|
35
|
+
readonly options?: ReactPathOptions;
|
|
36
|
+
};
|
|
37
|
+
/**
|
|
38
|
+
* Marks a class as a React router while writing equivalent HTTP controller metadata.
|
|
39
|
+
*
|
|
40
|
+
* @remarks
|
|
41
|
+
* `@Router(...)` is a lexical React facade over `@fluojs/http` `@Controller(...)`
|
|
42
|
+
* metadata. URL matching, route grammar, duplicate-route detection, guards,
|
|
43
|
+
* interceptors, middleware, DTO binding, and request lifecycle remain owned by
|
|
44
|
+
* the HTTP runtime.
|
|
45
|
+
*
|
|
46
|
+
* @param basePath Base path shared by React page handlers declared on the class.
|
|
47
|
+
* @returns A class decorator that writes HTTP controller metadata plus React router marker metadata.
|
|
48
|
+
*/
|
|
49
|
+
export declare function Router(basePath?: string): ClassDecoratorLike;
|
|
50
|
+
/**
|
|
51
|
+
* Marks a method as a React page route while writing equivalent HTTP `GET` route metadata.
|
|
52
|
+
*
|
|
53
|
+
* @remarks
|
|
54
|
+
* `@Path(...)` is a lexical React facade over `@fluojs/http` `@Get(...)` metadata.
|
|
55
|
+
* React page paths inherit the HTTP route grammar: literal segments and full-segment
|
|
56
|
+
* `:param` placeholders only. The optional `options` value is metadata for future
|
|
57
|
+
* render integrations; it does not create a React-owned matcher or `routes: []` table.
|
|
58
|
+
*
|
|
59
|
+
* @param path Route path relative to the containing `@Router(...)` base path.
|
|
60
|
+
* @param options Optional render-facing metadata for the future React rendering layer.
|
|
61
|
+
* @returns A method decorator that writes HTTP `GET` metadata plus React path metadata.
|
|
62
|
+
*/
|
|
63
|
+
export declare function Path(path: string, options?: ReactPathOptions): MethodDecoratorLike;
|
|
64
|
+
/**
|
|
65
|
+
* Reads React router marker metadata from a router class.
|
|
66
|
+
*
|
|
67
|
+
* @param routerToken Router class decorated with `@Router(...)`.
|
|
68
|
+
* @returns A defensive metadata snapshot, or `undefined` when the class is not a React router.
|
|
69
|
+
*/
|
|
70
|
+
export declare function getReactRouterMetadata(routerToken: Function): ReactRouterMetadata | undefined;
|
|
71
|
+
/**
|
|
72
|
+
* Reads React render metadata from a router method.
|
|
73
|
+
*
|
|
74
|
+
* @param routerToken Router class containing the decorated method.
|
|
75
|
+
* @param propertyKey Method property key decorated with `@Path(...)`.
|
|
76
|
+
* @returns A defensive metadata snapshot, or `undefined` when the method is not a React page route.
|
|
77
|
+
*/
|
|
78
|
+
export declare function getReactPathMetadata(routerToken: Function, propertyKey: MetadataPropertyKey): ReactPathMetadata | undefined;
|
|
79
|
+
export {};
|
|
80
|
+
//# sourceMappingURL=decorators.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decorators.d.ts","sourceRoot":"","sources":["../src/decorators.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAIxD,KAAK,wBAAwB,GAAG,CAAC,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,qBAAqB,KAAK,IAAI,CAAC;AAC1F,KAAK,yBAAyB,GAAG,CAAC,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,2BAA2B,KAAK,IAAI,CAAC;AACjG,KAAK,sBAAsB,GAAG,CAAC,MAAM,EAAE,QAAQ,KAAK,IAAI,CAAC;AACzD,KAAK,uBAAuB,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,mBAAmB,EAAE,UAAU,CAAC,EAAE,kBAAkB,KAAK,IAAI,CAAC;AAC3H,KAAK,kBAAkB,GAAG,wBAAwB,GAAG,sBAAsB,CAAC;AAC5E,KAAK,mBAAmB,GAAG,yBAAyB,GAAG,uBAAuB,CAAC;AAQ/E;;;;;;;GAOG;AACH,MAAM,MAAM,gBAAgB,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;AAEjE;;GAEG;AACH,MAAM,MAAM,mBAAmB,GAAG;IAChC,2EAA2E;IAC3E,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IACxB,8DAA8D;IAC9D,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,iBAAiB,GAAG;IAC9B,4EAA4E;IAC5E,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,0DAA0D;IAC1D,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,4EAA4E;IAC5E,QAAQ,CAAC,OAAO,CAAC,EAAE,gBAAgB,CAAC;CACrC,CAAC;AA4IF;;;;;;;;;;;GAWG;AACH,wBAAgB,MAAM,CAAC,QAAQ,SAAK,GAAG,kBAAkB,CAgBxD;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,mBAAmB,CAsBlF;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,WAAW,EAAE,QAAQ,GAAG,mBAAmB,GAAG,SAAS,CAI7F;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAClC,WAAW,EAAE,QAAQ,EACrB,WAAW,EAAE,mBAAmB,GAC/B,iBAAiB,GAAG,SAAS,CAK/B"}
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
import { getStandardMetadataBag } from '@fluojs/core/internal';
|
|
2
|
+
import { Controller, Get } from '@fluojs/http';
|
|
3
|
+
const reactRouterMetadataKey = Symbol.for('fluo.react.router');
|
|
4
|
+
const reactPathMetadataKey = Symbol.for('fluo.react.path');
|
|
5
|
+
const legacyRouterMetadataStore = new WeakMap();
|
|
6
|
+
const legacyPathMetadataStore = new WeakMap();
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Additional render-facing metadata stored by `@Path(...)` for the future React renderer.
|
|
10
|
+
*
|
|
11
|
+
* @remarks
|
|
12
|
+
* These options are intentionally runtime-neutral. They are recorded for diagnostics and
|
|
13
|
+
* later rendering integration without changing HTTP route matching, route grammar, DTO
|
|
14
|
+
* binding, validation, or request dispatch.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* React router marker metadata written by `@Router(...)`.
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* React render metadata written by `@Path(...)`.
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
function isStandardDecoratorContext(value) {
|
|
26
|
+
return typeof value === 'object' && value !== null && Reflect.get(value, 'kind') !== undefined;
|
|
27
|
+
}
|
|
28
|
+
function isStandardClassDecoratorContext(value) {
|
|
29
|
+
return isStandardDecoratorContext(value) && Reflect.get(value, 'kind') === 'class';
|
|
30
|
+
}
|
|
31
|
+
function isStandardMethodDecoratorContext(value) {
|
|
32
|
+
return isStandardDecoratorContext(value) && Reflect.get(value, 'kind') === 'method';
|
|
33
|
+
}
|
|
34
|
+
function isMetadataPropertyKey(value) {
|
|
35
|
+
return typeof value === 'string' || typeof value === 'symbol';
|
|
36
|
+
}
|
|
37
|
+
function cloneReactPathOptions(options) {
|
|
38
|
+
return options === undefined ? undefined : {
|
|
39
|
+
...options
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
function createReactRouterMetadata(basePath) {
|
|
43
|
+
return {
|
|
44
|
+
basePath,
|
|
45
|
+
kind: 'router'
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
function createReactPathMetadata(path, options) {
|
|
49
|
+
const clonedOptions = cloneReactPathOptions(options);
|
|
50
|
+
if (clonedOptions === undefined) {
|
|
51
|
+
return {
|
|
52
|
+
kind: 'path',
|
|
53
|
+
path
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
return {
|
|
57
|
+
kind: 'path',
|
|
58
|
+
options: clonedOptions,
|
|
59
|
+
path
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
function cloneReactRouterMetadata(metadata) {
|
|
63
|
+
return createReactRouterMetadata(metadata.basePath);
|
|
64
|
+
}
|
|
65
|
+
function cloneReactPathMetadata(metadata) {
|
|
66
|
+
return createReactPathMetadata(metadata.path, metadata.options);
|
|
67
|
+
}
|
|
68
|
+
function getMetadataObject(metadata) {
|
|
69
|
+
return typeof metadata === 'object' && metadata !== null ? metadata : {};
|
|
70
|
+
}
|
|
71
|
+
function defineStandardReactRouterMetadata(metadata, value) {
|
|
72
|
+
Reflect.set(getMetadataObject(metadata), reactRouterMetadataKey, cloneReactRouterMetadata(value));
|
|
73
|
+
}
|
|
74
|
+
function getStandardReactPathMap(metadata) {
|
|
75
|
+
const bag = getMetadataObject(metadata);
|
|
76
|
+
const current = Reflect.get(bag, reactPathMetadataKey);
|
|
77
|
+
if (current instanceof Map) {
|
|
78
|
+
return current;
|
|
79
|
+
}
|
|
80
|
+
const created = new Map();
|
|
81
|
+
Reflect.set(bag, reactPathMetadataKey, created);
|
|
82
|
+
return created;
|
|
83
|
+
}
|
|
84
|
+
function defineStandardReactPathMetadata(metadata, propertyKey, value) {
|
|
85
|
+
getStandardReactPathMap(metadata).set(propertyKey, cloneReactPathMetadata(value));
|
|
86
|
+
}
|
|
87
|
+
function defineLegacyReactPathMetadata(target, propertyKey, value) {
|
|
88
|
+
let routeMap = legacyPathMetadataStore.get(target);
|
|
89
|
+
if (!routeMap) {
|
|
90
|
+
routeMap = new Map();
|
|
91
|
+
legacyPathMetadataStore.set(target, routeMap);
|
|
92
|
+
}
|
|
93
|
+
routeMap.set(propertyKey, cloneReactPathMetadata(value));
|
|
94
|
+
}
|
|
95
|
+
function isReactRouterMetadata(value) {
|
|
96
|
+
return typeof value === 'object' && value !== null && Reflect.get(value, 'kind') === 'router' && typeof Reflect.get(value, 'basePath') === 'string';
|
|
97
|
+
}
|
|
98
|
+
function isReactPathOptions(value) {
|
|
99
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
100
|
+
}
|
|
101
|
+
function isReactPathMetadata(value) {
|
|
102
|
+
const options = typeof value === 'object' && value !== null ? Reflect.get(value, 'options') : undefined;
|
|
103
|
+
return typeof value === 'object' && value !== null && Reflect.get(value, 'kind') === 'path' && typeof Reflect.get(value, 'path') === 'string' && (options === undefined || isReactPathOptions(options));
|
|
104
|
+
}
|
|
105
|
+
function getStandardReactRouterMetadata(routerToken) {
|
|
106
|
+
const value = getStandardMetadataBag(routerToken)?.[reactRouterMetadataKey];
|
|
107
|
+
return isReactRouterMetadata(value) ? value : undefined;
|
|
108
|
+
}
|
|
109
|
+
function getStandardReactPathMetadata(routerToken, propertyKey) {
|
|
110
|
+
const routeMap = getStandardMetadataBag(routerToken)?.[reactPathMetadataKey];
|
|
111
|
+
if (!(routeMap instanceof Map)) {
|
|
112
|
+
return undefined;
|
|
113
|
+
}
|
|
114
|
+
const value = routeMap.get(propertyKey);
|
|
115
|
+
return isReactPathMetadata(value) ? value : undefined;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Marks a class as a React router while writing equivalent HTTP controller metadata.
|
|
120
|
+
*
|
|
121
|
+
* @remarks
|
|
122
|
+
* `@Router(...)` is a lexical React facade over `@fluojs/http` `@Controller(...)`
|
|
123
|
+
* metadata. URL matching, route grammar, duplicate-route detection, guards,
|
|
124
|
+
* interceptors, middleware, DTO binding, and request lifecycle remain owned by
|
|
125
|
+
* the HTTP runtime.
|
|
126
|
+
*
|
|
127
|
+
* @param basePath Base path shared by React page handlers declared on the class.
|
|
128
|
+
* @returns A class decorator that writes HTTP controller metadata plus React router marker metadata.
|
|
129
|
+
*/
|
|
130
|
+
export function Router(basePath = '') {
|
|
131
|
+
const httpDecorator = Controller(basePath);
|
|
132
|
+
const metadata = createReactRouterMetadata(basePath);
|
|
133
|
+
const decorator = (target, context) => {
|
|
134
|
+
Reflect.apply(httpDecorator, undefined, context === undefined ? [target] : [target, context]);
|
|
135
|
+
if (isStandardClassDecoratorContext(context)) {
|
|
136
|
+
defineStandardReactRouterMetadata(context.metadata, metadata);
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
legacyRouterMetadataStore.set(target, cloneReactRouterMetadata(metadata));
|
|
140
|
+
};
|
|
141
|
+
return decorator;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Marks a method as a React page route while writing equivalent HTTP `GET` route metadata.
|
|
146
|
+
*
|
|
147
|
+
* @remarks
|
|
148
|
+
* `@Path(...)` is a lexical React facade over `@fluojs/http` `@Get(...)` metadata.
|
|
149
|
+
* React page paths inherit the HTTP route grammar: literal segments and full-segment
|
|
150
|
+
* `:param` placeholders only. The optional `options` value is metadata for future
|
|
151
|
+
* render integrations; it does not create a React-owned matcher or `routes: []` table.
|
|
152
|
+
*
|
|
153
|
+
* @param path Route path relative to the containing `@Router(...)` base path.
|
|
154
|
+
* @param options Optional render-facing metadata for the future React rendering layer.
|
|
155
|
+
* @returns A method decorator that writes HTTP `GET` metadata plus React path metadata.
|
|
156
|
+
*/
|
|
157
|
+
export function Path(path, options) {
|
|
158
|
+
const httpDecorator = Get(path);
|
|
159
|
+
const metadata = createReactPathMetadata(path, options);
|
|
160
|
+
const decorator = (valueOrTarget, contextOrPropertyKey, descriptor) => {
|
|
161
|
+
Reflect.apply(httpDecorator, undefined, [valueOrTarget, contextOrPropertyKey, descriptor]);
|
|
162
|
+
if (isStandardMethodDecoratorContext(contextOrPropertyKey)) {
|
|
163
|
+
defineStandardReactPathMetadata(contextOrPropertyKey.metadata, contextOrPropertyKey.name, metadata);
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
if (isMetadataPropertyKey(contextOrPropertyKey)) {
|
|
167
|
+
defineLegacyReactPathMetadata(valueOrTarget, contextOrPropertyKey, metadata);
|
|
168
|
+
}
|
|
169
|
+
};
|
|
170
|
+
return decorator;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Reads React router marker metadata from a router class.
|
|
175
|
+
*
|
|
176
|
+
* @param routerToken Router class decorated with `@Router(...)`.
|
|
177
|
+
* @returns A defensive metadata snapshot, or `undefined` when the class is not a React router.
|
|
178
|
+
*/
|
|
179
|
+
export function getReactRouterMetadata(routerToken) {
|
|
180
|
+
const metadata = legacyRouterMetadataStore.get(routerToken) ?? getStandardReactRouterMetadata(routerToken);
|
|
181
|
+
return metadata ? cloneReactRouterMetadata(metadata) : undefined;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Reads React render metadata from a router method.
|
|
186
|
+
*
|
|
187
|
+
* @param routerToken Router class containing the decorated method.
|
|
188
|
+
* @param propertyKey Method property key decorated with `@Path(...)`.
|
|
189
|
+
* @returns A defensive metadata snapshot, or `undefined` when the method is not a React page route.
|
|
190
|
+
*/
|
|
191
|
+
export function getReactPathMetadata(routerToken, propertyKey) {
|
|
192
|
+
const metadata = legacyPathMetadataStore.get(routerToken.prototype)?.get(propertyKey) ?? getStandardReactPathMetadata(routerToken, propertyKey);
|
|
193
|
+
return metadata ? cloneReactPathMetadata(metadata) : undefined;
|
|
194
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { type ReactRscEnvironmentOptions, type ReactRscSupportResult } from './rsc-types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Inspects whether an application-owned RSC runtime and build adapter satisfy the prototype contract.
|
|
4
|
+
*
|
|
5
|
+
* @remarks
|
|
6
|
+
* The experimental policy accepts only exact `19.2.6` versions. Version ranges and canary builds
|
|
7
|
+
* are rejected because React Flight renderer internals must remain aligned with React and React DOM.
|
|
8
|
+
*
|
|
9
|
+
* @param options Installed React versions plus explicit runtime and build-adapter capabilities.
|
|
10
|
+
* @returns A successful result or stable diagnostics for every unsupported boundary.
|
|
11
|
+
*/
|
|
12
|
+
export declare function inspectReactRscEnvironment(options: ReactRscEnvironmentOptions): ReactRscSupportResult;
|
|
13
|
+
//# sourceMappingURL=rsc-diagnostics.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rsc-diagnostics.d.ts","sourceRoot":"","sources":["../../src/experimental/rsc-diagnostics.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,0BAA0B,EAC/B,KAAK,qBAAqB,EAC3B,MAAM,gBAAgB,CAAC;AAExB;;;;;;;;;GASG;AACH,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,0BAA0B,GAAG,qBAAqB,CAgDrG"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { REACT_RSC_DIAGNOSTIC_CODES, REACT_RSC_SUPPORTED_VERSION } from './rsc-types.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Inspects whether an application-owned RSC runtime and build adapter satisfy the prototype contract.
|
|
5
|
+
*
|
|
6
|
+
* @remarks
|
|
7
|
+
* The experimental policy accepts only exact `19.2.6` versions. Version ranges and canary builds
|
|
8
|
+
* are rejected because React Flight renderer internals must remain aligned with React and React DOM.
|
|
9
|
+
*
|
|
10
|
+
* @param options Installed React versions plus explicit runtime and build-adapter capabilities.
|
|
11
|
+
* @returns A successful result or stable diagnostics for every unsupported boundary.
|
|
12
|
+
*/
|
|
13
|
+
export function inspectReactRscEnvironment(options) {
|
|
14
|
+
const diagnostics = [];
|
|
15
|
+
if (options.reactVersion !== REACT_RSC_SUPPORTED_VERSION) {
|
|
16
|
+
diagnostics.push({
|
|
17
|
+
code: REACT_RSC_DIAGNOSTIC_CODES.unsupportedReactVersion,
|
|
18
|
+
message: `Experimental RSC requires react@${REACT_RSC_SUPPORTED_VERSION} exactly; received "${options.reactVersion}".`
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
if (options.reactDomVersion !== REACT_RSC_SUPPORTED_VERSION) {
|
|
22
|
+
diagnostics.push({
|
|
23
|
+
code: REACT_RSC_DIAGNOSTIC_CODES.unsupportedReactDomVersion,
|
|
24
|
+
message: `Experimental RSC requires react-dom@${REACT_RSC_SUPPORTED_VERSION} exactly; received "${options.reactDomVersion}".`
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
if (options.flightRendererVersion !== REACT_RSC_SUPPORTED_VERSION) {
|
|
28
|
+
diagnostics.push({
|
|
29
|
+
code: REACT_RSC_DIAGNOSTIC_CODES.unsupportedFlightRendererVersion,
|
|
30
|
+
message: `Experimental RSC requires the Flight renderer at ${REACT_RSC_SUPPORTED_VERSION} exactly; received "${options.flightRendererVersion}".`
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
if (!options.runtime.webStreams) {
|
|
34
|
+
diagnostics.push({
|
|
35
|
+
code: REACT_RSC_DIAGNOSTIC_CODES.unsupportedRuntime,
|
|
36
|
+
message: `Runtime "${options.runtime.name}" cannot host experimental RSC because Web ReadableStream support is unavailable.`
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
if (!options.build.clientReferenceManifest) {
|
|
40
|
+
diagnostics.push({
|
|
41
|
+
code: REACT_RSC_DIAGNOSTIC_CODES.missingClientReferenceManifest,
|
|
42
|
+
message: `Build adapter "${options.build.name}" did not provide a client-reference manifest.`
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
if (!options.build.serverClientModuleMap) {
|
|
46
|
+
diagnostics.push({
|
|
47
|
+
code: REACT_RSC_DIAGNOSTIC_CODES.missingServerClientModuleMap,
|
|
48
|
+
message: `Build adapter "${options.build.name}" did not provide a server-to-client module map.`
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
return diagnostics.length === 0 ? {
|
|
52
|
+
diagnostics: [],
|
|
53
|
+
ok: true
|
|
54
|
+
} : {
|
|
55
|
+
diagnostics,
|
|
56
|
+
ok: false
|
|
57
|
+
};
|
|
58
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { type ReactFlightPayload, type ReactFlightResponse, type ReactFlightResponseOptions } from './rsc-types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Creates an experimental Flight payload response for an ordinary fluo HTTP handler.
|
|
4
|
+
*
|
|
5
|
+
* @remarks
|
|
6
|
+
* The caller owns Flight encoding. Returning this entry from `@Get(...)`, `@Post(...)`, or
|
|
7
|
+
* `@Path(...)` keeps route matching, middleware, guards, interceptors, request scopes, and adapter
|
|
8
|
+
* response writing in the existing fluo HTTP dispatcher. A stream payload is consumed once.
|
|
9
|
+
*
|
|
10
|
+
* @param payload Application-encoded Flight bytes, text, or Web `ReadableStream`.
|
|
11
|
+
* @param options Optional status and headers applied after ordinary route success metadata.
|
|
12
|
+
* @returns A response entry recognized by the existing fluo HTTP dispatch response policy.
|
|
13
|
+
*/
|
|
14
|
+
export declare function createReactFlightResponse(payload: ReactFlightPayload, options?: ReactFlightResponseOptions): ReactFlightResponse;
|
|
15
|
+
//# sourceMappingURL=rsc-flight-response.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rsc-flight-response.d.ts","sourceRoot":"","sources":["../../src/experimental/rsc-flight-response.ts"],"names":[],"mappings":"AAOA,OAAO,EAEL,KAAK,kBAAkB,EACvB,KAAK,mBAAmB,EAExB,KAAK,0BAA0B,EAChC,MAAM,gBAAgB,CAAC;AA6ExB;;;;;;;;;;;GAWG;AACH,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,kBAAkB,EAC3B,OAAO,GAAE,0BAA+B,GACvC,mBAAmB,CAarB"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { collectReadableStream, pipeReadableStream, throwIfReactRequestAborted } from '../render-stream.js';
|
|
2
|
+
import { REACT_RSC_FLIGHT_CONTENT_TYPE } from './rsc-types.js';
|
|
3
|
+
const responseWriterKey = Symbol.for('fluo.http.responseWriter');
|
|
4
|
+
function cloneHeaders(headers) {
|
|
5
|
+
const snapshot = {};
|
|
6
|
+
for (const [name, value] of Object.entries(headers ?? {})) {
|
|
7
|
+
snapshot[name] = typeof value === 'string' ? value : [...value];
|
|
8
|
+
}
|
|
9
|
+
return snapshot;
|
|
10
|
+
}
|
|
11
|
+
function clonePayload(payload) {
|
|
12
|
+
return payload instanceof Uint8Array ? new Uint8Array(payload) : payload;
|
|
13
|
+
}
|
|
14
|
+
function isBufferedPayload(payload) {
|
|
15
|
+
return typeof payload === 'string' || payload instanceof Uint8Array;
|
|
16
|
+
}
|
|
17
|
+
function applyFlightResponseMetadata(entry, context) {
|
|
18
|
+
context.applySuccessResponseMetadata();
|
|
19
|
+
if (entry.status !== undefined) {
|
|
20
|
+
context.response.setStatus(entry.status);
|
|
21
|
+
}
|
|
22
|
+
for (const [name, value] of Object.entries(entry.headers)) {
|
|
23
|
+
if (name.toLowerCase() === 'content-type') {
|
|
24
|
+
continue;
|
|
25
|
+
}
|
|
26
|
+
context.response.setHeader(name, typeof value === 'string' ? value : [...value]);
|
|
27
|
+
}
|
|
28
|
+
context.response.setHeader('Content-Type', REACT_RSC_FLIGHT_CONTENT_TYPE);
|
|
29
|
+
}
|
|
30
|
+
async function writeReactFlightResponse(entry, context) {
|
|
31
|
+
throwIfReactRequestAborted(context.requestContext.request);
|
|
32
|
+
if (isBufferedPayload(entry.payload)) {
|
|
33
|
+
applyFlightResponseMetadata(entry, context);
|
|
34
|
+
await context.response.send(entry.payload);
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
const responseStream = context.response.stream;
|
|
38
|
+
if (!responseStream) {
|
|
39
|
+
const body = await collectReadableStream(entry.payload, context.requestContext.request);
|
|
40
|
+
throwIfReactRequestAborted(context.requestContext.request);
|
|
41
|
+
applyFlightResponseMetadata(entry, context);
|
|
42
|
+
await context.response.send(body);
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
applyFlightResponseMetadata(entry, context);
|
|
46
|
+
context.response.committed = true;
|
|
47
|
+
responseStream.flush?.();
|
|
48
|
+
await pipeReadableStream(entry.payload, responseStream, context.requestContext.request);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Creates an experimental Flight payload response for an ordinary fluo HTTP handler.
|
|
53
|
+
*
|
|
54
|
+
* @remarks
|
|
55
|
+
* The caller owns Flight encoding. Returning this entry from `@Get(...)`, `@Post(...)`, or
|
|
56
|
+
* `@Path(...)` keeps route matching, middleware, guards, interceptors, request scopes, and adapter
|
|
57
|
+
* response writing in the existing fluo HTTP dispatcher. A stream payload is consumed once.
|
|
58
|
+
*
|
|
59
|
+
* @param payload Application-encoded Flight bytes, text, or Web `ReadableStream`.
|
|
60
|
+
* @param options Optional status and headers applied after ordinary route success metadata.
|
|
61
|
+
* @returns A response entry recognized by the existing fluo HTTP dispatch response policy.
|
|
62
|
+
*/
|
|
63
|
+
export function createReactFlightResponse(payload, options = {}) {
|
|
64
|
+
const entry = {
|
|
65
|
+
headers: cloneHeaders(options.headers),
|
|
66
|
+
payload: clonePayload(payload),
|
|
67
|
+
...(options.status !== undefined ? {
|
|
68
|
+
status: options.status
|
|
69
|
+
} : {})
|
|
70
|
+
};
|
|
71
|
+
Object.defineProperty(entry, responseWriterKey, {
|
|
72
|
+
enumerable: false,
|
|
73
|
+
value: context => writeReactFlightResponse(entry, context)
|
|
74
|
+
});
|
|
75
|
+
return entry;
|
|
76
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { type ReactRscManifestInput, type ReactRscManifestResult } from './rsc-types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Validates and snapshots an application-owned RSC client-reference manifest and module map.
|
|
4
|
+
*
|
|
5
|
+
* @remarks
|
|
6
|
+
* This seam is bundler-neutral and does not scan files, generate chunks, load React internals, or
|
|
7
|
+
* model Server Functions. An application build adapter must provide both explicit inputs.
|
|
8
|
+
*
|
|
9
|
+
* @param input Client references and server module mappings produced by the application build.
|
|
10
|
+
* @returns A defensive manifest snapshot or stable diagnostics for invalid mappings.
|
|
11
|
+
*/
|
|
12
|
+
export declare function createReactRscManifest(input: ReactRscManifestInput): ReactRscManifestResult;
|
|
13
|
+
//# sourceMappingURL=rsc-manifest.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rsc-manifest.d.ts","sourceRoot":"","sources":["../../src/experimental/rsc-manifest.ts"],"names":[],"mappings":"AAAA,OAAO,EAML,KAAK,qBAAqB,EAC1B,KAAK,sBAAsB,EAE5B,MAAM,gBAAgB,CAAC;AA4ExB;;;;;;;;;GASG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,qBAAqB,GAAG,sBAAsB,CAa3F"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { REACT_RSC_DIAGNOSTIC_CODES } from './rsc-types.js';
|
|
2
|
+
function cloneClientReferences(clientReferences) {
|
|
3
|
+
const snapshot = {};
|
|
4
|
+
Object.setPrototypeOf(snapshot, null);
|
|
5
|
+
for (const [referenceId, reference] of Object.entries(clientReferences)) {
|
|
6
|
+
snapshot[referenceId] = {
|
|
7
|
+
...(reference.async !== undefined ? {
|
|
8
|
+
async: reference.async
|
|
9
|
+
} : {}),
|
|
10
|
+
chunks: [...reference.chunks],
|
|
11
|
+
id: reference.id,
|
|
12
|
+
name: reference.name
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
return snapshot;
|
|
16
|
+
}
|
|
17
|
+
function cloneServerClientModuleMap(serverClientModuleMap) {
|
|
18
|
+
const snapshot = {};
|
|
19
|
+
Object.setPrototypeOf(snapshot, null);
|
|
20
|
+
for (const [serverModuleId, exportMappings] of Object.entries(serverClientModuleMap)) {
|
|
21
|
+
const exportSnapshot = {};
|
|
22
|
+
Object.setPrototypeOf(exportSnapshot, null);
|
|
23
|
+
for (const [exportName, clientReferenceId] of Object.entries(exportMappings)) {
|
|
24
|
+
exportSnapshot[exportName] = clientReferenceId;
|
|
25
|
+
}
|
|
26
|
+
snapshot[serverModuleId] = exportSnapshot;
|
|
27
|
+
}
|
|
28
|
+
return snapshot;
|
|
29
|
+
}
|
|
30
|
+
function validateManifest(input) {
|
|
31
|
+
const diagnostics = [];
|
|
32
|
+
if (Object.keys(input.clientReferences).length === 0) {
|
|
33
|
+
diagnostics.push({
|
|
34
|
+
code: REACT_RSC_DIAGNOSTIC_CODES.emptyClientReferenceManifest,
|
|
35
|
+
message: 'The experimental RSC client-reference manifest must contain at least one reference.',
|
|
36
|
+
path: 'clientReferences'
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
if (Object.keys(input.serverClientModuleMap).length === 0) {
|
|
40
|
+
diagnostics.push({
|
|
41
|
+
code: REACT_RSC_DIAGNOSTIC_CODES.emptyServerClientModuleMap,
|
|
42
|
+
message: 'The experimental RSC server-to-client module map must contain at least one server module.',
|
|
43
|
+
path: 'serverClientModuleMap'
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
for (const [serverModuleId, exportMappings] of Object.entries(input.serverClientModuleMap)) {
|
|
47
|
+
for (const [exportName, clientReferenceId] of Object.entries(exportMappings)) {
|
|
48
|
+
if (Object.hasOwn(input.clientReferences, clientReferenceId)) {
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
diagnostics.push({
|
|
52
|
+
code: REACT_RSC_DIAGNOSTIC_CODES.unknownClientReference,
|
|
53
|
+
message: `Server module "${serverModuleId}" export "${exportName}" maps to unknown client reference "${clientReferenceId}".`,
|
|
54
|
+
path: `serverClientModuleMap.${serverModuleId}.${exportName}`
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return diagnostics;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Validates and snapshots an application-owned RSC client-reference manifest and module map.
|
|
63
|
+
*
|
|
64
|
+
* @remarks
|
|
65
|
+
* This seam is bundler-neutral and does not scan files, generate chunks, load React internals, or
|
|
66
|
+
* model Server Functions. An application build adapter must provide both explicit inputs.
|
|
67
|
+
*
|
|
68
|
+
* @param input Client references and server module mappings produced by the application build.
|
|
69
|
+
* @returns A defensive manifest snapshot or stable diagnostics for invalid mappings.
|
|
70
|
+
*/
|
|
71
|
+
export function createReactRscManifest(input) {
|
|
72
|
+
const diagnostics = validateManifest(input);
|
|
73
|
+
if (diagnostics.length > 0) {
|
|
74
|
+
return {
|
|
75
|
+
diagnostics,
|
|
76
|
+
ok: false
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
const manifest = {
|
|
80
|
+
clientReferences: cloneClientReferences(input.clientReferences),
|
|
81
|
+
serverClientModuleMap: cloneServerClientModuleMap(input.serverClientModuleMap)
|
|
82
|
+
};
|
|
83
|
+
return {
|
|
84
|
+
diagnostics: [],
|
|
85
|
+
manifest,
|
|
86
|
+
ok: true
|
|
87
|
+
};
|
|
88
|
+
}
|