@real-router/ssr-data-plugin 0.2.0 → 0.2.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 +12 -14
- package/dist/cjs/index.d.ts +4 -4
- package/dist/cjs/index.d.ts.map +1 -1
- package/dist/cjs/index.js +1 -1
- package/dist/cjs/index.js.map +1 -1
- package/dist/esm/index.d.mts +4 -4
- package/dist/esm/index.d.mts.map +1 -1
- package/dist/esm/index.mjs +1 -1
- package/dist/esm/index.mjs.map +1 -1
- package/package.json +5 -2
- package/src/factory.ts +4 -12
- package/src/index.ts +3 -5
package/README.md
CHANGED
|
@@ -15,7 +15,7 @@ const data = await loadRouteData(state.name, state.params); // manual
|
|
|
15
15
|
// With plugin:
|
|
16
16
|
router.usePlugin(ssrDataPluginFactory(loaders));
|
|
17
17
|
const state = await router.start(url);
|
|
18
|
-
const data =
|
|
18
|
+
const data = state.context.data; // loaded automatically
|
|
19
19
|
```
|
|
20
20
|
|
|
21
21
|
## Installation
|
|
@@ -24,7 +24,7 @@ const data = router.getRouteData(); // loaded automatically
|
|
|
24
24
|
npm install @real-router/ssr-data-plugin
|
|
25
25
|
```
|
|
26
26
|
|
|
27
|
-
**Peer
|
|
27
|
+
**Peer dependencies:** `@real-router/core`, `@real-router/types`
|
|
28
28
|
|
|
29
29
|
## Quick Start
|
|
30
30
|
|
|
@@ -46,7 +46,7 @@ const router = cloneRouter(baseRouter, { isAuthenticated: true });
|
|
|
46
46
|
router.usePlugin(ssrDataPluginFactory(loaders));
|
|
47
47
|
|
|
48
48
|
const state = await router.start(url);
|
|
49
|
-
const data =
|
|
49
|
+
const data = state.context.data; // data loaded by matching loader
|
|
50
50
|
|
|
51
51
|
const html = renderToString(<App />);
|
|
52
52
|
router.dispose();
|
|
@@ -66,27 +66,25 @@ const loaders: DataLoaderMap = {
|
|
|
66
66
|
};
|
|
67
67
|
```
|
|
68
68
|
|
|
69
|
-
Routes without a matching loader produce no data — `
|
|
69
|
+
Routes without a matching loader produce no data — `state.context.data` is `undefined`.
|
|
70
70
|
|
|
71
|
-
##
|
|
71
|
+
## Accessing Data
|
|
72
72
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
| Method | Returns | Description |
|
|
76
|
-
| ---------------------- | --------- | ------------------------------------------ |
|
|
77
|
-
| `getRouteData(state?)` | `unknown` | Get loaded data for current or given state |
|
|
73
|
+
After `await router.start(url)`, data is available on the returned state's context:
|
|
78
74
|
|
|
79
75
|
```typescript
|
|
80
|
-
router.
|
|
81
|
-
|
|
76
|
+
const state = await router.start(url);
|
|
77
|
+
const data = state.context.data; // loaded data, or undefined if no loader matched
|
|
82
78
|
```
|
|
83
79
|
|
|
80
|
+
The plugin claims the `"data"` namespace on `state.context` via the [claim-based API](https://github.com/greydragon888/real-router/wiki/plugin-architecture). Module augmentation on `@real-router/types` provides type safety for `state.context.data`.
|
|
81
|
+
|
|
84
82
|
## SSR-Only by Design
|
|
85
83
|
|
|
86
84
|
This plugin intercepts `start()` only — not `navigate()`. In SSR, the flow is:
|
|
87
85
|
|
|
88
86
|
```
|
|
89
|
-
cloneRouter → usePlugin → start(url) → data loaded →
|
|
87
|
+
cloneRouter → usePlugin → start(url) → data loaded → state.context.data → renderToString
|
|
90
88
|
```
|
|
91
89
|
|
|
92
90
|
Client-side navigation and data fetching is the application's responsibility (React Query, Suspense, `useEffect`, etc.).
|
|
@@ -96,7 +94,7 @@ Client-side navigation and data fetching is the application's responsibility (Re
|
|
|
96
94
|
```typescript
|
|
97
95
|
const unsubscribe = router.usePlugin(ssrDataPluginFactory(loaders));
|
|
98
96
|
|
|
99
|
-
// Later —
|
|
97
|
+
// Later — releases "data" namespace claim and stops data loading
|
|
100
98
|
unsubscribe();
|
|
101
99
|
```
|
|
102
100
|
|
package/dist/cjs/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Params, PluginFactory
|
|
1
|
+
import { Params, PluginFactory } from "@real-router/core";
|
|
2
2
|
|
|
3
3
|
//#region src/types.d.ts
|
|
4
4
|
type DataLoaderFn = (params: Params) => Promise<unknown>;
|
|
@@ -8,9 +8,9 @@ type DataLoaderMap = Record<string, DataLoaderFn>;
|
|
|
8
8
|
declare function ssrDataPluginFactory(loaders: DataLoaderMap): PluginFactory;
|
|
9
9
|
//#endregion
|
|
10
10
|
//#region src/index.d.ts
|
|
11
|
-
declare module "@real-router/
|
|
12
|
-
interface
|
|
13
|
-
|
|
11
|
+
declare module "@real-router/types" {
|
|
12
|
+
interface StateContext {
|
|
13
|
+
data?: unknown;
|
|
14
14
|
}
|
|
15
15
|
} //# sourceMappingURL=index.d.ts.map
|
|
16
16
|
//#endregion
|
package/dist/cjs/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../../src/types.ts","../../src/factory.ts","../../src/index.ts"],"mappings":";;;KAEY,YAAA,IAAgB,MAAA,EAAQ,MAAA,KAAW,OAAA;AAAA,KAEnC,aAAA,GAAgB,MAAA,SAAe,YAAA;;;iBCG3B,oBAAA,CAAqB,OAAA,EAAS,aAAA,GAAgB,aAAA;;;;
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../../src/types.ts","../../src/factory.ts","../../src/index.ts"],"mappings":";;;KAEY,YAAA,IAAgB,MAAA,EAAQ,MAAA,KAAW,OAAA;AAAA,KAEnC,aAAA,GAAgB,MAAA,SAAe,YAAA;;;iBCG3B,oBAAA,CAAqB,OAAA,EAAS,aAAA,GAAgB,aAAA;;;;YCFlD,YAAA;IACR,IAAA;EAAA;AAAA"}
|
package/dist/cjs/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});let e=require(`@real-router/core/api`);const t=`[@real-router/ssr-data-plugin]`;function n(e){if(typeof e!=`object`||!e)throw TypeError(`${t} loaders must be a non-null object`);for(let[n,r]of Object.entries(e))if(typeof r!=`function`)throw TypeError(`${t} loader for route "${n}" must be a function`)}function r(t){return n(t),n=>{let r=(0,e.getPluginApi)(n),i=
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});let e=require(`@real-router/core/api`);const t=`[@real-router/ssr-data-plugin]`;function n(e){if(typeof e!=`object`||!e)throw TypeError(`${t} loaders must be a non-null object`);for(let[n,r]of Object.entries(e))if(typeof r!=`function`)throw TypeError(`${t} loader for route "${n}" must be a function`)}function r(t){return n(t),n=>{let r=(0,e.getPluginApi)(n),i=r.claimContextNamespace(`data`),a=r.addInterceptor(`start`,async(e,n)=>{let r=await e(n);return Object.hasOwn(t,r.name)&&i.write(r,await t[r.name](r.params)),r});return{teardown(){a(),i.release()}}}}exports.ssrDataPluginFactory=r;
|
|
2
2
|
//# sourceMappingURL=index.js.map
|
package/dist/cjs/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../src/constants.ts","../../src/validation.ts","../../src/factory.ts"],"sourcesContent":["export const LOGGER_CONTEXT = \"ssr-data-plugin\";\n\nexport const ERROR_PREFIX = `[@real-router/${LOGGER_CONTEXT}]`;\n","import { ERROR_PREFIX } from \"./constants\";\n\nimport type { DataLoaderMap } from \"./types\";\n\nexport function validateLoaders(\n loaders: unknown,\n): asserts loaders is DataLoaderMap {\n if (loaders === null || typeof loaders !== \"object\") {\n throw new TypeError(`${ERROR_PREFIX} loaders must be a non-null object`);\n }\n\n for (const [key, value] of Object.entries(\n loaders as Record<string, unknown>,\n )) {\n if (typeof value !== \"function\") {\n throw new TypeError(\n `${ERROR_PREFIX} loader for route \"${key}\" must be a function`,\n );\n }\n }\n}\n","import { getPluginApi } from \"@real-router/core/api\";\n\nimport { validateLoaders } from \"./validation\";\n\nimport type { DataLoaderMap } from \"./types\";\nimport type {
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../src/constants.ts","../../src/validation.ts","../../src/factory.ts"],"sourcesContent":["export const LOGGER_CONTEXT = \"ssr-data-plugin\";\n\nexport const ERROR_PREFIX = `[@real-router/${LOGGER_CONTEXT}]`;\n","import { ERROR_PREFIX } from \"./constants\";\n\nimport type { DataLoaderMap } from \"./types\";\n\nexport function validateLoaders(\n loaders: unknown,\n): asserts loaders is DataLoaderMap {\n if (loaders === null || typeof loaders !== \"object\") {\n throw new TypeError(`${ERROR_PREFIX} loaders must be a non-null object`);\n }\n\n for (const [key, value] of Object.entries(\n loaders as Record<string, unknown>,\n )) {\n if (typeof value !== \"function\") {\n throw new TypeError(\n `${ERROR_PREFIX} loader for route \"${key}\" must be a function`,\n );\n }\n }\n}\n","import { getPluginApi } from \"@real-router/core/api\";\n\nimport { validateLoaders } from \"./validation\";\n\nimport type { DataLoaderMap } from \"./types\";\nimport type { PluginFactory, Plugin } from \"@real-router/core\";\n\nexport function ssrDataPluginFactory(loaders: DataLoaderMap): PluginFactory {\n validateLoaders(loaders);\n\n return (router): Plugin => {\n const api = getPluginApi(router);\n const claim = api.claimContextNamespace(\"data\");\n\n const removeStartInterceptor = api.addInterceptor(\n \"start\",\n async (next, path) => {\n const state = await next(path);\n\n if (Object.hasOwn(loaders, state.name)) {\n claim.write(state, await loaders[state.name](state.params));\n }\n\n return state;\n },\n );\n\n return {\n teardown() {\n removeStartInterceptor();\n claim.release();\n },\n };\n };\n}\n"],"mappings":"0GAAA,MAEa,EAAe,iCCE5B,SAAgB,EACd,EACkC,CAClC,GAAwB,OAAO,GAAY,WAAvC,EACF,MAAU,UAAU,GAAG,EAAa,oCAAoC,CAG1E,IAAK,GAAM,CAAC,EAAK,KAAU,OAAO,QAChC,EACD,CACC,GAAI,OAAO,GAAU,WACnB,MAAU,UACR,GAAG,EAAa,qBAAqB,EAAI,sBAC1C,CCVP,SAAgB,EAAqB,EAAuC,CAG1E,OAFA,EAAgB,EAAQ,CAEhB,GAAmB,CACzB,IAAM,GAAA,EAAA,EAAA,cAAmB,EAAO,CAC1B,EAAQ,EAAI,sBAAsB,OAAO,CAEzC,EAAyB,EAAI,eACjC,QACA,MAAO,EAAM,IAAS,CACpB,IAAM,EAAQ,MAAM,EAAK,EAAK,CAM9B,OAJI,OAAO,OAAO,EAAS,EAAM,KAAK,EACpC,EAAM,MAAM,EAAO,MAAM,EAAQ,EAAM,MAAM,EAAM,OAAO,CAAC,CAGtD,GAEV,CAED,MAAO,CACL,UAAW,CACT,GAAwB,CACxB,EAAM,SAAS,EAElB"}
|
package/dist/esm/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Params, PluginFactory
|
|
1
|
+
import { Params, PluginFactory } from "@real-router/core";
|
|
2
2
|
|
|
3
3
|
//#region src/types.d.ts
|
|
4
4
|
type DataLoaderFn = (params: Params) => Promise<unknown>;
|
|
@@ -8,9 +8,9 @@ type DataLoaderMap = Record<string, DataLoaderFn>;
|
|
|
8
8
|
declare function ssrDataPluginFactory(loaders: DataLoaderMap): PluginFactory;
|
|
9
9
|
//#endregion
|
|
10
10
|
//#region src/index.d.ts
|
|
11
|
-
declare module "@real-router/
|
|
12
|
-
interface
|
|
13
|
-
|
|
11
|
+
declare module "@real-router/types" {
|
|
12
|
+
interface StateContext {
|
|
13
|
+
data?: unknown;
|
|
14
14
|
}
|
|
15
15
|
} //# sourceMappingURL=index.d.ts.map
|
|
16
16
|
//#endregion
|
package/dist/esm/index.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../../src/types.ts","../../src/factory.ts","../../src/index.ts"],"mappings":";;;KAEY,YAAA,IAAgB,MAAA,EAAQ,MAAA,KAAW,OAAA;AAAA,KAEnC,aAAA,GAAgB,MAAA,SAAe,YAAA;;;iBCG3B,oBAAA,CAAqB,OAAA,EAAS,aAAA,GAAgB,aAAA;;;;
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../../src/types.ts","../../src/factory.ts","../../src/index.ts"],"mappings":";;;KAEY,YAAA,IAAgB,MAAA,EAAQ,MAAA,KAAW,OAAA;AAAA,KAEnC,aAAA,GAAgB,MAAA,SAAe,YAAA;;;iBCG3B,oBAAA,CAAqB,OAAA,EAAS,aAAA,GAAgB,aAAA;;;;YCFlD,YAAA;IACR,IAAA;EAAA;AAAA"}
|
package/dist/esm/index.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{getPluginApi as e}from"@real-router/core/api";const t=`[@real-router/ssr-data-plugin]`;function n(e){if(typeof e!=`object`||!e)throw TypeError(`${t} loaders must be a non-null object`);for(let[n,r]of Object.entries(e))if(typeof r!=`function`)throw TypeError(`${t} loader for route "${n}" must be a function`)}function r(t){return n(t),n=>{let r=e(n),i=
|
|
1
|
+
import{getPluginApi as e}from"@real-router/core/api";const t=`[@real-router/ssr-data-plugin]`;function n(e){if(typeof e!=`object`||!e)throw TypeError(`${t} loaders must be a non-null object`);for(let[n,r]of Object.entries(e))if(typeof r!=`function`)throw TypeError(`${t} loader for route "${n}" must be a function`)}function r(t){return n(t),n=>{let r=e(n),i=r.claimContextNamespace(`data`),a=r.addInterceptor(`start`,async(e,n)=>{let r=await e(n);return Object.hasOwn(t,r.name)&&i.write(r,await t[r.name](r.params)),r});return{teardown(){a(),i.release()}}}}export{r as ssrDataPluginFactory};
|
|
2
2
|
//# sourceMappingURL=index.mjs.map
|
package/dist/esm/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":[],"sources":["../../src/constants.ts","../../src/validation.ts","../../src/factory.ts"],"sourcesContent":["export const LOGGER_CONTEXT = \"ssr-data-plugin\";\n\nexport const ERROR_PREFIX = `[@real-router/${LOGGER_CONTEXT}]`;\n","import { ERROR_PREFIX } from \"./constants\";\n\nimport type { DataLoaderMap } from \"./types\";\n\nexport function validateLoaders(\n loaders: unknown,\n): asserts loaders is DataLoaderMap {\n if (loaders === null || typeof loaders !== \"object\") {\n throw new TypeError(`${ERROR_PREFIX} loaders must be a non-null object`);\n }\n\n for (const [key, value] of Object.entries(\n loaders as Record<string, unknown>,\n )) {\n if (typeof value !== \"function\") {\n throw new TypeError(\n `${ERROR_PREFIX} loader for route \"${key}\" must be a function`,\n );\n }\n }\n}\n","import { getPluginApi } from \"@real-router/core/api\";\n\nimport { validateLoaders } from \"./validation\";\n\nimport type { DataLoaderMap } from \"./types\";\nimport type {
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../../src/constants.ts","../../src/validation.ts","../../src/factory.ts"],"sourcesContent":["export const LOGGER_CONTEXT = \"ssr-data-plugin\";\n\nexport const ERROR_PREFIX = `[@real-router/${LOGGER_CONTEXT}]`;\n","import { ERROR_PREFIX } from \"./constants\";\n\nimport type { DataLoaderMap } from \"./types\";\n\nexport function validateLoaders(\n loaders: unknown,\n): asserts loaders is DataLoaderMap {\n if (loaders === null || typeof loaders !== \"object\") {\n throw new TypeError(`${ERROR_PREFIX} loaders must be a non-null object`);\n }\n\n for (const [key, value] of Object.entries(\n loaders as Record<string, unknown>,\n )) {\n if (typeof value !== \"function\") {\n throw new TypeError(\n `${ERROR_PREFIX} loader for route \"${key}\" must be a function`,\n );\n }\n }\n}\n","import { getPluginApi } from \"@real-router/core/api\";\n\nimport { validateLoaders } from \"./validation\";\n\nimport type { DataLoaderMap } from \"./types\";\nimport type { PluginFactory, Plugin } from \"@real-router/core\";\n\nexport function ssrDataPluginFactory(loaders: DataLoaderMap): PluginFactory {\n validateLoaders(loaders);\n\n return (router): Plugin => {\n const api = getPluginApi(router);\n const claim = api.claimContextNamespace(\"data\");\n\n const removeStartInterceptor = api.addInterceptor(\n \"start\",\n async (next, path) => {\n const state = await next(path);\n\n if (Object.hasOwn(loaders, state.name)) {\n claim.write(state, await loaders[state.name](state.params));\n }\n\n return state;\n },\n );\n\n return {\n teardown() {\n removeStartInterceptor();\n claim.release();\n },\n };\n };\n}\n"],"mappings":"qDAAA,MAEa,EAAe,iCCE5B,SAAgB,EACd,EACkC,CAClC,GAAwB,OAAO,GAAY,WAAvC,EACF,MAAU,UAAU,GAAG,EAAa,oCAAoC,CAG1E,IAAK,GAAM,CAAC,EAAK,KAAU,OAAO,QAChC,EACD,CACC,GAAI,OAAO,GAAU,WACnB,MAAU,UACR,GAAG,EAAa,qBAAqB,EAAI,sBAC1C,CCVP,SAAgB,EAAqB,EAAuC,CAG1E,OAFA,EAAgB,EAAQ,CAEhB,GAAmB,CACzB,IAAM,EAAM,EAAa,EAAO,CAC1B,EAAQ,EAAI,sBAAsB,OAAO,CAEzC,EAAyB,EAAI,eACjC,QACA,MAAO,EAAM,IAAS,CACpB,IAAM,EAAQ,MAAM,EAAK,EAAK,CAM9B,OAJI,OAAO,OAAO,EAAS,EAAM,KAAK,EACpC,EAAM,MAAM,EAAO,MAAM,EAAQ,EAAM,MAAM,EAAM,OAAO,CAAC,CAGtD,GAEV,CAED,MAAO,CACL,UAAW,CACT,GAAwB,CACxB,EAAM,SAAS,EAElB"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@real-router/ssr-data-plugin",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"type": "commonjs",
|
|
5
5
|
"description": "SSR per-route data loading plugin for Real-Router",
|
|
6
6
|
"main": "./dist/cjs/index.js",
|
|
@@ -36,8 +36,11 @@
|
|
|
36
36
|
},
|
|
37
37
|
"homepage": "https://github.com/greydragon888/real-router",
|
|
38
38
|
"sideEffects": false,
|
|
39
|
+
"dependencies": {
|
|
40
|
+
"@real-router/types": "^0.34.0"
|
|
41
|
+
},
|
|
39
42
|
"peerDependencies": {
|
|
40
|
-
"@real-router/core": "^0.
|
|
43
|
+
"@real-router/core": "^0.48.0"
|
|
41
44
|
},
|
|
42
45
|
"scripts": {
|
|
43
46
|
"test": "vitest",
|
package/src/factory.ts
CHANGED
|
@@ -3,14 +3,14 @@ import { getPluginApi } from "@real-router/core/api";
|
|
|
3
3
|
import { validateLoaders } from "./validation";
|
|
4
4
|
|
|
5
5
|
import type { DataLoaderMap } from "./types";
|
|
6
|
-
import type {
|
|
6
|
+
import type { PluginFactory, Plugin } from "@real-router/core";
|
|
7
7
|
|
|
8
8
|
export function ssrDataPluginFactory(loaders: DataLoaderMap): PluginFactory {
|
|
9
9
|
validateLoaders(loaders);
|
|
10
10
|
|
|
11
11
|
return (router): Plugin => {
|
|
12
12
|
const api = getPluginApi(router);
|
|
13
|
-
const
|
|
13
|
+
const claim = api.claimContextNamespace("data");
|
|
14
14
|
|
|
15
15
|
const removeStartInterceptor = api.addInterceptor(
|
|
16
16
|
"start",
|
|
@@ -18,25 +18,17 @@ export function ssrDataPluginFactory(loaders: DataLoaderMap): PluginFactory {
|
|
|
18
18
|
const state = await next(path);
|
|
19
19
|
|
|
20
20
|
if (Object.hasOwn(loaders, state.name)) {
|
|
21
|
-
|
|
21
|
+
claim.write(state, await loaders[state.name](state.params));
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
return state;
|
|
25
25
|
},
|
|
26
26
|
);
|
|
27
27
|
|
|
28
|
-
const removeExtensions = api.extendRouter({
|
|
29
|
-
getRouteData(state?: State): unknown {
|
|
30
|
-
const routeState = state ?? router.getState();
|
|
31
|
-
|
|
32
|
-
return routeState ? (dataStore.get(routeState) ?? null) : null;
|
|
33
|
-
},
|
|
34
|
-
});
|
|
35
|
-
|
|
36
28
|
return {
|
|
37
29
|
teardown() {
|
|
38
30
|
removeStartInterceptor();
|
|
39
|
-
|
|
31
|
+
claim.release();
|
|
40
32
|
},
|
|
41
33
|
};
|
|
42
34
|
};
|
package/src/index.ts
CHANGED
|
@@ -1,11 +1,9 @@
|
|
|
1
|
-
import type { State } from "@real-router/core";
|
|
2
|
-
|
|
3
1
|
export type { DataLoaderMap, DataLoaderFn } from "./types";
|
|
4
2
|
|
|
5
3
|
export { ssrDataPluginFactory } from "./factory";
|
|
6
4
|
|
|
7
|
-
declare module "@real-router/
|
|
8
|
-
interface
|
|
9
|
-
|
|
5
|
+
declare module "@real-router/types" {
|
|
6
|
+
interface StateContext {
|
|
7
|
+
data?: unknown;
|
|
10
8
|
}
|
|
11
9
|
}
|