@bleedingdev/modern-js-plugin-bff-extensions 3.9.0-ultramodern.2 → 3.9.0-ultramodern.20
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 +25 -5
- package/dist/cjs/backend-federation/edge-runtime.js +3 -15
- package/dist/cjs/backend-federation/edge.js +9 -10
- package/dist/cjs/backend-federation/identity.js +26 -31
- package/dist/cjs/backend-federation/index.js +5 -5
- package/dist/cjs/backend-federation/integrity-plugin.js +112 -0
- package/dist/cjs/backend-federation/load.js +3 -13
- package/dist/cjs/backend-federation/node-shared.js +85 -0
- package/dist/cjs/backend-federation/node.js +6 -1
- package/dist/cjs/backend-federation/plugin.js +40 -21
- package/dist/cjs/backend-federation/runtime.js +16 -84
- package/dist/cjs/backend-federation/validate-loaded.js +2 -4
- package/dist/cjs/backend-federation-manifest/load.js +40 -12
- package/dist/cjs/backend-federation-manifest/metadata.js +3 -3
- package/dist/cjs/backend-federation-manifest/node.js +3 -1
- package/dist/cjs/backend-federation-manifest/remote.js +3 -9
- package/dist/cjs/backend-federation-manifest/validation.js +16 -12
- package/dist/cjs/cross-project-policy/evaluation.js +3 -3
- package/dist/cjs/cross-project-policy/node.js +11 -30
- package/dist/cjs/{backend-federation/legacy-warning.js → cross-project-policy/producer-runtime.js} +23 -5
- package/dist/cjs/{effect-adapter → effect-server}/cross-project-policy.js +5 -5
- package/dist/cjs/effect-server/entry.js +63 -0
- package/dist/cjs/{effect-adapter → effect-server}/error-response.js +4 -4
- package/dist/cjs/effect-server/index.js +199 -0
- package/dist/cjs/{client-generator → effect-source-loader}/built-entry.js +5 -6
- package/dist/cjs/{client-generator/runtime.js → effect-source-loader/http-api-runtime.js} +12 -20
- package/dist/cjs/effect-source-loader/index.js +18 -6
- package/dist/cjs/effect-source-loader/loader.js +17 -30
- package/dist/cjs/effect-source-loader/operation-contracts.js +60 -0
- package/dist/cjs/effect-source-loader/paths.js +90 -0
- package/dist/cjs/effect-source-loader/rspack-loader.js +73 -0
- package/dist/cjs/effect-source-loader/worker-runtime-source.js +71 -0
- package/dist/cjs/effect-source-loader/worker-runtime-wrapper.js +7 -50
- package/dist/cjs/hono/cross-project-policy.js +2 -1
- package/dist/cjs/{client-generator/paths.js → hono/node.js} +14 -25
- package/dist/esm/backend-federation/edge-runtime.mjs +2 -11
- package/dist/esm/backend-federation/edge.mjs +5 -6
- package/dist/esm/backend-federation/identity.mjs +21 -32
- package/dist/esm/backend-federation/index.mjs +1 -1
- package/dist/esm/backend-federation/integrity-plugin.mjs +68 -0
- package/dist/esm/backend-federation/load.mjs +2 -12
- package/dist/esm/backend-federation/node-shared.mjs +41 -0
- package/dist/esm/backend-federation/node.mjs +4 -2
- package/dist/esm/backend-federation/plugin.mjs +37 -18
- package/dist/esm/backend-federation/runtime.mjs +16 -84
- package/dist/esm/backend-federation/validate-loaded.mjs +2 -4
- package/dist/esm/backend-federation-manifest/load.mjs +40 -12
- package/dist/esm/backend-federation-manifest/metadata.mjs +1 -1
- package/dist/esm/backend-federation-manifest/node.mjs +3 -1
- package/dist/esm/backend-federation-manifest/remote.mjs +2 -8
- package/dist/esm/backend-federation-manifest/validation.mjs +15 -11
- package/dist/esm/cross-project-policy/evaluation.mjs +1 -1
- package/dist/esm/cross-project-policy/node.mjs +10 -19
- package/dist/esm/cross-project-policy/producer-runtime.mjs +20 -0
- package/dist/esm/{effect-adapter → effect-server}/cross-project-policy.mjs +3 -3
- package/dist/esm/effect-server/entry.mjs +15 -0
- package/dist/esm/{effect-adapter → effect-server}/error-response.mjs +2 -2
- package/dist/esm/effect-server/index.mjs +151 -0
- package/dist/esm/{client-generator → effect-source-loader}/built-entry.mjs +6 -7
- package/dist/esm/effect-source-loader/http-api-runtime.mjs +19 -0
- package/dist/esm/effect-source-loader/index.mjs +5 -2
- package/dist/esm/effect-source-loader/loader.mjs +17 -30
- package/dist/esm/effect-source-loader/operation-contracts.mjs +22 -0
- package/dist/esm/effect-source-loader/paths.mjs +43 -0
- package/dist/esm/effect-source-loader/rspack-loader.mjs +35 -0
- package/dist/esm/effect-source-loader/worker-runtime-source.mjs +23 -0
- package/dist/esm/effect-source-loader/worker-runtime-wrapper.mjs +5 -45
- package/dist/esm/hono/cross-project-policy.mjs +2 -1
- package/dist/esm-node/backend-federation/edge-runtime.mjs +2 -11
- package/dist/esm-node/backend-federation/edge.mjs +5 -6
- package/dist/esm-node/backend-federation/identity.mjs +21 -32
- package/dist/esm-node/backend-federation/index.mjs +1 -1
- package/dist/esm-node/backend-federation/integrity-plugin.mjs +69 -0
- package/dist/esm-node/backend-federation/load.mjs +2 -12
- package/dist/esm-node/backend-federation/node-shared.mjs +42 -0
- package/dist/esm-node/backend-federation/node.mjs +4 -2
- package/dist/esm-node/backend-federation/plugin.mjs +37 -18
- package/dist/esm-node/backend-federation/runtime.mjs +16 -84
- package/dist/esm-node/backend-federation/validate-loaded.mjs +2 -4
- package/dist/esm-node/backend-federation-manifest/load.mjs +40 -12
- package/dist/esm-node/backend-federation-manifest/metadata.mjs +1 -1
- package/dist/esm-node/backend-federation-manifest/node.mjs +3 -1
- package/dist/esm-node/backend-federation-manifest/remote.mjs +2 -8
- package/dist/esm-node/backend-federation-manifest/validation.mjs +15 -11
- package/dist/esm-node/cross-project-policy/evaluation.mjs +1 -1
- package/dist/esm-node/cross-project-policy/node.mjs +10 -19
- package/dist/esm-node/cross-project-policy/producer-runtime.mjs +21 -0
- package/dist/esm-node/{effect-adapter → effect-server}/cross-project-policy.mjs +3 -3
- package/dist/esm-node/effect-server/entry.mjs +16 -0
- package/dist/esm-node/{effect-adapter → effect-server}/error-response.mjs +2 -2
- package/dist/esm-node/effect-server/index.mjs +152 -0
- package/dist/esm-node/{client-generator → effect-source-loader}/built-entry.mjs +6 -7
- package/dist/esm-node/effect-source-loader/http-api-runtime.mjs +20 -0
- package/dist/esm-node/effect-source-loader/index.mjs +5 -2
- package/dist/esm-node/effect-source-loader/loader.mjs +17 -30
- package/dist/esm-node/effect-source-loader/operation-contracts.mjs +23 -0
- package/dist/esm-node/effect-source-loader/paths.mjs +44 -0
- package/dist/esm-node/effect-source-loader/rspack-loader.mjs +37 -0
- package/dist/esm-node/effect-source-loader/worker-runtime-source.mjs +24 -0
- package/dist/esm-node/effect-source-loader/worker-runtime-wrapper.mjs +5 -45
- package/dist/esm-node/hono/cross-project-policy.mjs +2 -1
- package/dist/esm-node/hono/node.mjs +14 -0
- package/dist/types/backend-federation/edge-runtime.d.ts +0 -5
- package/dist/types/backend-federation/edge.d.ts +5 -5
- package/dist/types/backend-federation/identity.d.ts +4 -16
- package/dist/types/backend-federation/index.d.ts +1 -1
- package/dist/types/backend-federation/integrity-plugin.d.ts +13 -0
- package/dist/types/backend-federation/load.d.ts +1 -7
- package/dist/types/backend-federation/node-shared.d.ts +20 -0
- package/dist/types/backend-federation/node.d.ts +4 -3
- package/dist/types/backend-federation/plugin.d.ts +4 -0
- package/dist/types/backend-federation/types.d.ts +3 -14
- package/dist/types/backend-federation/validate-loaded.d.ts +1 -2
- package/dist/types/backend-federation-manifest/metadata.d.ts +0 -6
- package/dist/types/backend-federation-manifest/types.d.ts +2 -1
- package/dist/types/cross-project-policy/evaluation.d.ts +1 -1
- package/dist/types/cross-project-policy/node.d.ts +3 -2
- package/dist/types/cross-project-policy/producer-runtime.d.ts +20 -0
- package/dist/types/effect-server/cross-project-policy.d.ts +5 -0
- package/dist/types/effect-server/entry.d.ts +3 -0
- package/dist/types/effect-server/error-response.d.ts +2 -0
- package/dist/types/effect-server/index.d.ts +4 -0
- package/dist/types/effect-source-loader/index.d.ts +5 -2
- package/dist/types/effect-source-loader/operation-contracts.d.ts +8 -0
- package/dist/types/effect-source-loader/paths.d.ts +23 -0
- package/dist/types/effect-source-loader/rspack-loader.d.ts +9 -0
- package/dist/types/effect-source-loader/worker-runtime-source.d.ts +4 -0
- package/dist/types/effect-source-loader/worker-runtime-wrapper.d.ts +4 -22
- package/dist/types/hono/node.d.ts +4 -0
- package/package.json +64 -36
- package/src/backend-federation/edge-runtime.ts +2 -13
- package/src/backend-federation/edge.ts +16 -21
- package/src/backend-federation/identity.ts +39 -65
- package/src/backend-federation/index.ts +1 -1
- package/src/backend-federation/integrity-plugin.ts +157 -0
- package/src/backend-federation/load.ts +7 -35
- package/src/backend-federation/node-shared.ts +76 -0
- package/src/backend-federation/node.ts +7 -14
- package/src/backend-federation/plugin.ts +73 -25
- package/src/backend-federation/runtime.ts +16 -90
- package/src/backend-federation/types.ts +3 -18
- package/src/backend-federation/validate-loaded.ts +2 -7
- package/src/backend-federation-manifest/load.ts +93 -38
- package/src/backend-federation-manifest/metadata.ts +1 -7
- package/src/backend-federation-manifest/node.ts +3 -2
- package/src/backend-federation-manifest/remote.ts +1 -7
- package/src/backend-federation-manifest/types.ts +2 -0
- package/src/backend-federation-manifest/validation.ts +29 -39
- package/src/cross-project-policy/evaluation.ts +1 -1
- package/src/cross-project-policy/node.ts +10 -41
- package/src/cross-project-policy/producer-runtime.ts +43 -0
- package/src/{effect-adapter → effect-server}/cross-project-policy.ts +8 -2
- package/src/effect-server/entry.ts +18 -0
- package/src/{effect-adapter → effect-server}/error-response.ts +1 -1
- package/src/effect-server/index.ts +242 -0
- package/src/{client-generator → effect-source-loader}/built-entry.ts +12 -12
- package/src/effect-source-loader/http-api-runtime.ts +39 -0
- package/src/effect-source-loader/index.ts +8 -5
- package/src/effect-source-loader/loader.ts +47 -52
- package/src/effect-source-loader/operation-contracts.ts +38 -0
- package/src/effect-source-loader/paths.ts +74 -0
- package/src/effect-source-loader/rspack-loader.ts +71 -0
- package/src/effect-source-loader/worker-runtime-source.ts +34 -0
- package/src/effect-source-loader/worker-runtime-wrapper.ts +5 -75
- package/src/hono/cross-project-policy.ts +2 -1
- package/src/hono/node.ts +24 -0
- package/dist/cjs/backend-federation/entry.js +0 -94
- package/dist/cjs/client-generator/generator.js +0 -73
- package/dist/cjs/client-generator/index.js +0 -54
- package/dist/cjs/client-generator/rendering.js +0 -253
- package/dist/cjs/client-generator/types.js +0 -18
- package/dist/cjs/effect-adapter/entry.js +0 -98
- package/dist/cjs/effect-adapter/index.js +0 -187
- package/dist/esm/backend-federation/entry.mjs +0 -56
- package/dist/esm/backend-federation/legacy-warning.mjs +0 -2
- package/dist/esm/client-generator/generator.mjs +0 -32
- package/dist/esm/client-generator/index.mjs +0 -3
- package/dist/esm/client-generator/paths.mjs +0 -24
- package/dist/esm/client-generator/rendering.mjs +0 -209
- package/dist/esm/client-generator/runtime.mjs +0 -27
- package/dist/esm/client-generator/types.mjs +0 -0
- package/dist/esm/effect-adapter/entry.mjs +0 -50
- package/dist/esm/effect-adapter/index.mjs +0 -139
- package/dist/esm-node/backend-federation/entry.mjs +0 -57
- package/dist/esm-node/backend-federation/legacy-warning.mjs +0 -3
- package/dist/esm-node/client-generator/generator.mjs +0 -33
- package/dist/esm-node/client-generator/index.mjs +0 -4
- package/dist/esm-node/client-generator/paths.mjs +0 -25
- package/dist/esm-node/client-generator/rendering.mjs +0 -210
- package/dist/esm-node/client-generator/runtime.mjs +0 -29
- package/dist/esm-node/client-generator/types.mjs +0 -1
- package/dist/esm-node/effect-adapter/entry.mjs +0 -51
- package/dist/esm-node/effect-adapter/index.mjs +0 -140
- package/dist/types/backend-federation/entry.d.ts +0 -2
- package/dist/types/backend-federation/legacy-warning.d.ts +0 -1
- package/dist/types/client-generator/generator.d.ts +0 -3
- package/dist/types/client-generator/index.d.ts +0 -4
- package/dist/types/client-generator/paths.d.ts +0 -5
- package/dist/types/client-generator/rendering.d.ts +0 -24
- package/dist/types/client-generator/types.d.ts +0 -33
- package/dist/types/effect-adapter/cross-project-policy.d.ts +0 -4
- package/dist/types/effect-adapter/entry.d.ts +0 -2
- package/dist/types/effect-adapter/error-response.d.ts +0 -2
- package/dist/types/effect-adapter/index.d.ts +0 -19
- package/src/backend-federation/entry.ts +0 -125
- package/src/backend-federation/legacy-warning.ts +0 -2
- package/src/client-generator/generator.ts +0 -52
- package/src/client-generator/index.ts +0 -10
- package/src/client-generator/paths.ts +0 -40
- package/src/client-generator/rendering.ts +0 -307
- package/src/client-generator/runtime.ts +0 -69
- package/src/client-generator/types.ts +0 -35
- package/src/effect-adapter/entry.ts +0 -95
- package/src/effect-adapter/index.ts +0 -246
- /package/dist/types/{client-generator → effect-source-loader}/built-entry.d.ts +0 -0
- /package/dist/types/{client-generator/runtime.d.ts → effect-source-loader/http-api-runtime.d.ts} +0 -0
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import "node:module";
|
|
2
|
+
import node_path from "node:path";
|
|
3
|
+
import "@modern-js/server-runtime-extensions/server-config";
|
|
4
|
+
import { dispatchEffectBffRequest, resolveEffectBffModuleHandler, useEffectContext } from "@modern-js/bff-effect/effect";
|
|
5
|
+
import { resolveOperationProducer } from "@modern-js/server-runtime-extensions/bff-policy/node";
|
|
6
|
+
import { createDisposableServerRuntimeHandle, registerServerRuntimeDisposer } from "@modern-js/server-runtime-extensions/runtime-lifecycle";
|
|
7
|
+
import { fs, isProd, logger } from "@modern-js/utils";
|
|
8
|
+
import { checkCrossProjectPolicyForRequest } from "../cross-project-policy/evaluation.mjs";
|
|
9
|
+
import { loadEffectBuiltModule, loadEffectSourceModule } from "../effect-source-loader/loader.mjs";
|
|
10
|
+
import { resolveEffectServerCrossProjectPolicy } from "./cross-project-policy.mjs";
|
|
11
|
+
import { resolveEffectServerEntryFile } from "./entry.mjs";
|
|
12
|
+
import { createEffectServerRuntimeErrorResponse } from "./error-response.mjs";
|
|
13
|
+
const EFFECT_MIDDLEWARE_BEFORE = [
|
|
14
|
+
'custom-server-hook',
|
|
15
|
+
'custom-server-middleware',
|
|
16
|
+
'render'
|
|
17
|
+
];
|
|
18
|
+
const effect_server = ()=>({
|
|
19
|
+
name: '@modern-js/plugin-bff-extensions/effect-server',
|
|
20
|
+
setup (api) {
|
|
21
|
+
const runtimeFramework = api.getServerContext().bffRuntimeFramework;
|
|
22
|
+
if ('effect' !== runtimeFramework) throw new Error(`Effect BFF server plugin requires Effect; received "${runtimeFramework}".`);
|
|
23
|
+
let handler = null;
|
|
24
|
+
let unregisterRuntimeDisposer;
|
|
25
|
+
let prefix = '/api';
|
|
26
|
+
let prefixes = [
|
|
27
|
+
'/api'
|
|
28
|
+
];
|
|
29
|
+
let matchingPrefixes = [
|
|
30
|
+
'/api'
|
|
31
|
+
];
|
|
32
|
+
let retired = false;
|
|
33
|
+
const dispose = async ()=>{
|
|
34
|
+
retired = true;
|
|
35
|
+
unregisterRuntimeDisposer?.();
|
|
36
|
+
unregisterRuntimeDisposer = void 0;
|
|
37
|
+
const previous = handler;
|
|
38
|
+
handler = null;
|
|
39
|
+
await previous?.dispose();
|
|
40
|
+
};
|
|
41
|
+
const loadHandler = async ()=>{
|
|
42
|
+
const entryFile = resolveEffectServerEntryFile(api);
|
|
43
|
+
if (!entryFile || !await fs.pathExists(entryFile)) {
|
|
44
|
+
handler = null;
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
const { appDirectory } = api.getServerContext();
|
|
48
|
+
let mod;
|
|
49
|
+
try {
|
|
50
|
+
mod = await (isProd() ? loadEffectBuiltModule(entryFile) : loadEffectSourceModule({
|
|
51
|
+
resourcePath: entryFile,
|
|
52
|
+
appDir: appDirectory || node_path.dirname(entryFile)
|
|
53
|
+
}));
|
|
54
|
+
} catch (error) {
|
|
55
|
+
logger.error(`[BFF][Effect] Failed to load Effect entry: ${entryFile}\n${String(error)}`);
|
|
56
|
+
throw error;
|
|
57
|
+
}
|
|
58
|
+
const producer = resolveOperationProducer({
|
|
59
|
+
directories: [
|
|
60
|
+
node_path.dirname(entryFile),
|
|
61
|
+
appDirectory
|
|
62
|
+
],
|
|
63
|
+
requestId: api.getServerConfig()?.bff?.requestId
|
|
64
|
+
});
|
|
65
|
+
const crossProjectPolicies = new Map(await Promise.all(prefixes.map(async (prefix)=>[
|
|
66
|
+
prefix,
|
|
67
|
+
await resolveEffectServerCrossProjectPolicy(api, prefix, mod, producer)
|
|
68
|
+
])));
|
|
69
|
+
const effectConfig = api.getServerConfig()?.bff?.effect;
|
|
70
|
+
const loaded = await resolveEffectBffModuleHandler(mod, {
|
|
71
|
+
openapi: effectConfig?.openapi,
|
|
72
|
+
dataPlatform: effectConfig?.dataPlatform,
|
|
73
|
+
validateRequest: (request)=>{
|
|
74
|
+
const { path: mountedPathname } = useEffectContext();
|
|
75
|
+
const prefix = matchingPrefixes.find((item)=>'/' === item || mountedPathname === item || mountedPathname.startsWith(`${item}/`));
|
|
76
|
+
if (!prefix) return null;
|
|
77
|
+
const requestUrl = new URL(request.url);
|
|
78
|
+
if ('/' !== prefix) requestUrl.pathname = '/' === requestUrl.pathname ? prefix : `${prefix}${requestUrl.pathname}`;
|
|
79
|
+
return checkCrossProjectPolicyForRequest(new Request(requestUrl, request), crossProjectPolicies.get(prefix));
|
|
80
|
+
},
|
|
81
|
+
onWarning: (message)=>logger.warn(message)
|
|
82
|
+
});
|
|
83
|
+
if (!loaded) {
|
|
84
|
+
const error = new Error(`[BFF][Effect] Invalid Effect entry module: ${entryFile}. Export defineEffectBff(...) or a { api, layer } HttpApi module.`);
|
|
85
|
+
logger.warn(error.message);
|
|
86
|
+
throw error;
|
|
87
|
+
}
|
|
88
|
+
const candidateOwner = {};
|
|
89
|
+
if (loaded.dispose) registerServerRuntimeDisposer(candidateOwner, loaded.dispose);
|
|
90
|
+
const candidate = createDisposableServerRuntimeHandle(candidateOwner, loaded.handler);
|
|
91
|
+
if (retired) {
|
|
92
|
+
await candidate.dispose();
|
|
93
|
+
throw new Error('Cannot initialize a retired Effect server.');
|
|
94
|
+
}
|
|
95
|
+
handler = candidate;
|
|
96
|
+
};
|
|
97
|
+
api.onPrepare(async ()=>{
|
|
98
|
+
const { middlewares: globalMiddlewares } = api.getServerContext();
|
|
99
|
+
const configuredPrefix = api.getServerConfig()?.bff?.prefix;
|
|
100
|
+
const enableHandleWeb = api.getServerConfig()?.bff?.enableHandleWeb;
|
|
101
|
+
const configuredPrefixes = Array.isArray(configuredPrefix) ? configuredPrefix.filter(Boolean) : [
|
|
102
|
+
configuredPrefix || '/api'
|
|
103
|
+
];
|
|
104
|
+
prefixes = [
|
|
105
|
+
...new Set(configuredPrefixes.length > 0 ? configuredPrefixes : [
|
|
106
|
+
'/api'
|
|
107
|
+
])
|
|
108
|
+
];
|
|
109
|
+
matchingPrefixes = [
|
|
110
|
+
...prefixes
|
|
111
|
+
].sort((left, right)=>right.length - left.length);
|
|
112
|
+
prefix = prefixes[0] || '/api';
|
|
113
|
+
const { serverBase } = api.getServerContext();
|
|
114
|
+
if (serverBase) unregisterRuntimeDisposer = registerServerRuntimeDisposer(serverBase, dispose);
|
|
115
|
+
try {
|
|
116
|
+
await loadHandler();
|
|
117
|
+
} catch (error) {
|
|
118
|
+
await dispose();
|
|
119
|
+
throw error;
|
|
120
|
+
}
|
|
121
|
+
const middlewarePrefixes = enableHandleWeb ? [
|
|
122
|
+
prefix
|
|
123
|
+
] : matchingPrefixes;
|
|
124
|
+
const middlewares = middlewarePrefixes.map((middlewarePrefix)=>({
|
|
125
|
+
name: 'effect-api-handler',
|
|
126
|
+
path: enableHandleWeb ? '*' : `${middlewarePrefix}/*`,
|
|
127
|
+
method: 'all',
|
|
128
|
+
order: 'post',
|
|
129
|
+
before: EFFECT_MIDDLEWARE_BEFORE,
|
|
130
|
+
handler: async (context, next)=>{
|
|
131
|
+
const activeHandler = handler;
|
|
132
|
+
if (!activeHandler) {
|
|
133
|
+
if (enableHandleWeb) return void await next();
|
|
134
|
+
return createEffectServerRuntimeErrorResponse(api, new Error('[BFF][Effect] Missing Effect entry. Define api/index or configure bff.effect.entry.'), context);
|
|
135
|
+
}
|
|
136
|
+
const mountedPrefix = enableHandleWeb ? matchingPrefixes.find((item)=>'/' === item || context.req.path === item || context.req.path.startsWith(`${item}/`)) || prefix : middlewarePrefix;
|
|
137
|
+
const response = await dispatchEffectBffRequest(activeHandler, context.req.raw, {
|
|
138
|
+
prefix: mountedPrefix,
|
|
139
|
+
env: context.env,
|
|
140
|
+
path: context.req.path,
|
|
141
|
+
method: context.req.method,
|
|
142
|
+
onError: (error)=>createEffectServerRuntimeErrorResponse(api, error, context)
|
|
143
|
+
});
|
|
144
|
+
if (404 === response.status && enableHandleWeb) return void await next();
|
|
145
|
+
return new Response(response.body, response);
|
|
146
|
+
}
|
|
147
|
+
}));
|
|
148
|
+
globalMiddlewares.push(...middlewares);
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
});
|
|
152
|
+
export default effect_server;
|
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
import "node:module";
|
|
2
2
|
import { fs, upath } from "@modern-js/utils";
|
|
3
|
-
import { resolveEffectEntryFile } from "./paths.mjs";
|
|
4
|
-
const BUILT_ENTRY_EXT = /\.(?:[cm]?ts|tsx|jsx)$/u;
|
|
3
|
+
import { emittedEffectEntry, relativeEffectAppPath, resolveEffectEntryFile } from "./paths.mjs";
|
|
5
4
|
function resolveBuiltEffectEntry(appDirectory, distDirectory, sourceEntry) {
|
|
6
5
|
if (void 0 === sourceEntry || 0 === sourceEntry.length) return;
|
|
7
|
-
const relativeEntry =
|
|
8
|
-
if (
|
|
9
|
-
const builtEntry = upath.resolve(distDirectory, relativeEntry)
|
|
6
|
+
const relativeEntry = relativeEffectAppPath(appDirectory, sourceEntry);
|
|
7
|
+
if (void 0 === relativeEntry) throw new Error(`Effect BFF entry must be inside the application directory: ${sourceEntry}`);
|
|
8
|
+
const builtEntry = emittedEffectEntry(upath.resolve(distDirectory, relativeEntry));
|
|
10
9
|
return fs.existsSync(builtEntry) ? builtEntry : void 0;
|
|
11
10
|
}
|
|
12
11
|
async function bundleBuiltEffectEntryForNode(options) {
|
|
@@ -18,7 +17,7 @@ async function bundleBuiltEffectEntryForNode(options) {
|
|
|
18
17
|
});
|
|
19
18
|
const builtEntry = resolveBuiltEffectEntry(appDir, distDir, sourceEntry);
|
|
20
19
|
if (void 0 === builtEntry || 0 === builtEntry.length) throw new Error(`Effect BFF entry was not emitted into ${distDir}: ${sourceEntry ?? upath.resolve(apiDir, 'index')}`);
|
|
21
|
-
const { bundleEffectEntryForNode } = await import("
|
|
20
|
+
const { bundleEffectEntryForNode } = await import("./loader.mjs");
|
|
22
21
|
return bundleEffectEntryForNode({
|
|
23
22
|
appDir,
|
|
24
23
|
entryPath: builtEntry,
|
|
@@ -32,7 +31,7 @@ function resolveEffectEntryPaths(options) {
|
|
|
32
31
|
apiDir,
|
|
33
32
|
effectEntry
|
|
34
33
|
});
|
|
35
|
-
const relativeEffectEntry = void 0 !== sourceEffectEntry && sourceEffectEntry.length > 0 ? upath.relative(appDir, sourceEffectEntry)
|
|
34
|
+
const relativeEffectEntry = void 0 !== sourceEffectEntry && sourceEffectEntry.length > 0 ? emittedEffectEntry(upath.relative(appDir, sourceEffectEntry)) : '';
|
|
36
35
|
return {
|
|
37
36
|
sourceEffectEntry,
|
|
38
37
|
relativeEffectEntry
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import "node:module";
|
|
2
|
+
import { extractHttpApiFromModule } from "@modern-js/bff-effect/effect";
|
|
3
|
+
import { HttpApi } from "effect/unstable/httpapi";
|
|
4
|
+
import { loadEffectSourceModule } from "./loader.mjs";
|
|
5
|
+
function getHttpApiRuntime() {
|
|
6
|
+
return Promise.resolve({
|
|
7
|
+
isHttpApi: HttpApi.isHttpApi,
|
|
8
|
+
reflect: (api, handlers)=>{
|
|
9
|
+
if (!HttpApi.isHttpApi(api)) throw new TypeError('[BFF][Effect] Expected an HttpApi contract.');
|
|
10
|
+
HttpApi.reflect(api, {
|
|
11
|
+
onGroup: handlers.onGroup ?? (()=>{}),
|
|
12
|
+
onEndpoint: handlers.onEndpoint
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
function loadEffectApi(options) {
|
|
18
|
+
return getHttpApiRuntime().then((httpApiRuntime)=>loadEffectSourceModule(options).then((mod)=>extractHttpApiFromModule(mod, httpApiRuntime.isHttpApi)));
|
|
19
|
+
}
|
|
20
|
+
export { getHttpApiRuntime, loadEffectApi };
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import "node:module";
|
|
2
|
-
export {
|
|
2
|
+
export { bundleBuiltEffectEntryForNode, resolveEffectEntryPaths } from "./built-entry.mjs";
|
|
3
3
|
export { bundleEffectEntryForNode } from "./loader.mjs";
|
|
4
|
-
export {
|
|
4
|
+
export { resolveEffectOperationContracts } from "./operation-contracts.mjs";
|
|
5
|
+
export { resolveEffectEntryFile } from "./paths.mjs";
|
|
6
|
+
export { bundleEffectWorkerRuntimeSource } from "./worker-runtime-source.mjs";
|
|
7
|
+
export { generateEffectWorkerRuntimeWrapper } from "./worker-runtime-wrapper.mjs";
|
|
@@ -48,16 +48,18 @@ function preserveSourceModuleSemantics() {
|
|
|
48
48
|
name: 'modern-js-effect-source-semantics',
|
|
49
49
|
setup (buildApi) {
|
|
50
50
|
buildApi.onLoad({
|
|
51
|
-
filter: /\.[cm]?[jt]sx
|
|
51
|
+
filter: /\.[cm]?[jt]sx?$/,
|
|
52
|
+
namespace: 'file'
|
|
52
53
|
}, async (args)=>{
|
|
53
54
|
const loader = sourceLoader(args);
|
|
54
55
|
if (!loader) return;
|
|
55
56
|
const source = await node_fs.promises.readFile(args.path, 'utf8');
|
|
57
|
+
const canonicalSourcePath = await node_fs.promises.realpath(args.path);
|
|
56
58
|
const compiled = await transform(source, {
|
|
57
59
|
define: {
|
|
58
|
-
__dirname: JSON.stringify(node_path.dirname(
|
|
59
|
-
__filename: JSON.stringify(
|
|
60
|
-
'import.meta.url': JSON.stringify(pathToFileURL(
|
|
60
|
+
__dirname: JSON.stringify(node_path.dirname(canonicalSourcePath)),
|
|
61
|
+
__filename: JSON.stringify(canonicalSourcePath),
|
|
62
|
+
'import.meta.url': JSON.stringify(pathToFileURL(canonicalSourcePath).href)
|
|
61
63
|
},
|
|
62
64
|
jsx: 'automatic',
|
|
63
65
|
loader,
|
|
@@ -78,6 +80,7 @@ const nodeBuiltins = new Set([
|
|
|
78
80
|
...builtinModules.map((name)=>`node:${name}`)
|
|
79
81
|
]);
|
|
80
82
|
const dependencyResolutionMarker = 'modern-js-effect-dependency-resolution';
|
|
83
|
+
const BFF_RUNTIME_PACKAGE = /^@modern-js\/(?:bff-effect|plugin-bff)(?:\/|$)/;
|
|
81
84
|
async function isEsmOnlyFile(filename) {
|
|
82
85
|
const extension = node_path.extname(filename).toLowerCase();
|
|
83
86
|
if ('.mjs' === extension || '.mts' === extension) return true;
|
|
@@ -100,13 +103,16 @@ function isBareSpecifier(specifier) {
|
|
|
100
103
|
return !specifier.startsWith('.') && !specifier.startsWith('/') && !node_path.isAbsolute(specifier);
|
|
101
104
|
}
|
|
102
105
|
function externalizeInstalledDependencies(options) {
|
|
103
|
-
const runtimeRequire = createRequire(node_path.join(options.runtimeResolveDir, '__modern_effect_entry.cjs'));
|
|
104
106
|
return {
|
|
105
107
|
name: 'modern-js-effect-installed-dependencies',
|
|
106
108
|
setup (buildApi) {
|
|
107
109
|
buildApi.onResolve({
|
|
108
110
|
filter: /.*/
|
|
109
111
|
}, async (args)=>{
|
|
112
|
+
if (BFF_RUNTIME_PACKAGE.test(args.path)) return {
|
|
113
|
+
external: true,
|
|
114
|
+
path: args.path
|
|
115
|
+
};
|
|
110
116
|
if (!isBareSpecifier(args.path) || nodeBuiltins.has(args.path) || args.pluginData?.[dependencyResolutionMarker] === true) return nodeBuiltins.has(args.path) ? {
|
|
111
117
|
external: true,
|
|
112
118
|
path: args.path
|
|
@@ -130,7 +136,8 @@ function externalizeInstalledDependencies(options) {
|
|
|
130
136
|
path: args.path
|
|
131
137
|
};
|
|
132
138
|
const realPath = await node_fs.promises.realpath(resolution.path).catch(()=>resolution.path);
|
|
133
|
-
|
|
139
|
+
const loader = SOURCE_LOADERS.get(node_path.extname(realPath).toLowerCase());
|
|
140
|
+
if (realPath.includes(`${node_path.sep}node_modules${node_path.sep}`) && 'ts' !== loader && 'tsx' !== loader && 'jsx' !== loader) {
|
|
134
141
|
const runtimeResolution = await buildApi.resolve(args.path, {
|
|
135
142
|
importer: '',
|
|
136
143
|
kind: args.kind,
|
|
@@ -140,28 +147,10 @@ function externalizeInstalledDependencies(options) {
|
|
|
140
147
|
},
|
|
141
148
|
resolveDir: options.runtimeResolveDir
|
|
142
149
|
});
|
|
143
|
-
if (0 === runtimeResolution.errors.length && runtimeResolution.path) {
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
requiredPath = runtimeRequire.resolve(args.path);
|
|
148
|
-
} catch {
|
|
149
|
-
requiredPath = runtimeResolution.path;
|
|
150
|
-
}
|
|
151
|
-
if (await isEsmOnlyFile(requiredPath)) return {
|
|
152
|
-
namespace: resolution.namespace,
|
|
153
|
-
path: resolution.path,
|
|
154
|
-
pluginData: resolution.pluginData,
|
|
155
|
-
sideEffects: resolution.sideEffects,
|
|
156
|
-
suffix: resolution.suffix,
|
|
157
|
-
warnings: resolution.warnings
|
|
158
|
-
};
|
|
159
|
-
}
|
|
160
|
-
return {
|
|
161
|
-
external: true,
|
|
162
|
-
path: args.path
|
|
163
|
-
};
|
|
164
|
-
}
|
|
150
|
+
if (0 === runtimeResolution.errors.length && runtimeResolution.path) return {
|
|
151
|
+
external: true,
|
|
152
|
+
path: args.path
|
|
153
|
+
};
|
|
165
154
|
}
|
|
166
155
|
return {
|
|
167
156
|
namespace: resolution.namespace,
|
|
@@ -189,7 +178,6 @@ async function bundleEffectEntryForNode(options) {
|
|
|
189
178
|
platform: 'node',
|
|
190
179
|
plugins: [
|
|
191
180
|
externalizeInstalledDependencies({
|
|
192
|
-
format: options.format,
|
|
193
181
|
runtimeResolveDir: options.appDir
|
|
194
182
|
}),
|
|
195
183
|
preserveSourceModuleSemantics()
|
|
@@ -263,7 +251,6 @@ async function loadEffectSourceModule(options) {
|
|
|
263
251
|
platform: 'node',
|
|
264
252
|
plugins: [
|
|
265
253
|
externalizeInstalledDependencies({
|
|
266
|
-
format: 'esm',
|
|
267
254
|
runtimeResolveDir: appDir
|
|
268
255
|
}),
|
|
269
256
|
preserveSourceModuleSemantics()
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import "node:module";
|
|
2
|
+
import { collectEffectEndpoints, toOperationContractSources } from "@modern-js/bff-effect/effect";
|
|
3
|
+
import { buildOperationContractMap, resolveOperationProducer } from "@modern-js/server-runtime-extensions/bff-policy/node";
|
|
4
|
+
import { upath } from "@modern-js/utils";
|
|
5
|
+
import { getHttpApiRuntime, loadEffectApi } from "./http-api-runtime.mjs";
|
|
6
|
+
async function resolveEffectOperationContracts(options) {
|
|
7
|
+
const api = await loadEffectApi(options);
|
|
8
|
+
if (null === api) return null;
|
|
9
|
+
const runtime = await getHttpApiRuntime();
|
|
10
|
+
const endpoints = collectEffectEndpoints(runtime.reflect, api, options.prefix);
|
|
11
|
+
return buildOperationContractMap({
|
|
12
|
+
handlers: toOperationContractSources(endpoints),
|
|
13
|
+
...resolveOperationProducer({
|
|
14
|
+
directories: [
|
|
15
|
+
upath.dirname(options.resourcePath),
|
|
16
|
+
options.appDir
|
|
17
|
+
],
|
|
18
|
+
requestId: options.requestId,
|
|
19
|
+
onDependency: options.onDependency
|
|
20
|
+
})
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
export { resolveEffectOperationContracts };
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import "node:module";
|
|
2
|
+
import { findExists, fs, upath } from "@modern-js/utils";
|
|
3
|
+
const JS_OR_TS_EXTS = [
|
|
4
|
+
'.js',
|
|
5
|
+
'.jsx',
|
|
6
|
+
'.ts',
|
|
7
|
+
'.tsx',
|
|
8
|
+
'.mjs',
|
|
9
|
+
'.mts',
|
|
10
|
+
'.cjs',
|
|
11
|
+
'.cts'
|
|
12
|
+
];
|
|
13
|
+
const emittedEffectEntry = (entry)=>entry.replace(/\.(?:[cm]?ts|tsx|jsx)$/u, '.js');
|
|
14
|
+
function relativeEffectAppPath(appDir, entry) {
|
|
15
|
+
const relative = upath.relative(appDir, entry);
|
|
16
|
+
return '..' === relative || relative.startsWith('../') || relative.split('/').includes('node_modules') ? void 0 : relative;
|
|
17
|
+
}
|
|
18
|
+
function existingEntry(entry) {
|
|
19
|
+
return upath.extname(entry) ? fs.existsSync(entry) ? entry : void 0 : findExists(JS_OR_TS_EXTS.map((ext)=>`${entry}${ext}`)) || void 0;
|
|
20
|
+
}
|
|
21
|
+
function resolveEffectEntry(options) {
|
|
22
|
+
const { appDir, apiDir, effectEntry, distDir } = options;
|
|
23
|
+
const entry = upath.resolve(appDir, effectEntry || upath.join(apiDir, 'index'));
|
|
24
|
+
if (distDir && void 0 !== relativeEffectAppPath(distDir, entry)) return {
|
|
25
|
+
kind: 'built-output',
|
|
26
|
+
path: existingEntry(emittedEffectEntry(entry))
|
|
27
|
+
};
|
|
28
|
+
const relative = relativeEffectAppPath(appDir, entry);
|
|
29
|
+
if (void 0 === relative) return {
|
|
30
|
+
kind: 'external-sdk',
|
|
31
|
+
path: existingEntry(entry)
|
|
32
|
+
};
|
|
33
|
+
return distDir ? {
|
|
34
|
+
kind: 'built-output',
|
|
35
|
+
path: existingEntry(emittedEffectEntry(upath.resolve(distDir, relative)))
|
|
36
|
+
} : {
|
|
37
|
+
kind: 'app-source',
|
|
38
|
+
path: existingEntry(entry)
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
function resolveEffectEntryFile(options) {
|
|
42
|
+
return resolveEffectEntry(options).path;
|
|
43
|
+
}
|
|
44
|
+
export { emittedEffectEntry, relativeEffectAppPath, resolveEffectEntry, resolveEffectEntryFile };
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import __rslib_shim_module__ from "node:module";
|
|
2
|
+
const require = /*#__PURE__*/ __rslib_shim_module__.createRequire(/*#__PURE__*/ (()=>import.meta.url)());
|
|
3
|
+
import { realpathSync } from "node:fs";
|
|
4
|
+
import { bundleEffectWorkerRuntimeSource, generateEffectWorkerRuntimeWrapper, resolveEffectEntryFile } from "./index.mjs";
|
|
5
|
+
async function loader(source) {
|
|
6
|
+
this.cacheable();
|
|
7
|
+
delete require.cache[this.resourcePath];
|
|
8
|
+
const callback = this.async();
|
|
9
|
+
try {
|
|
10
|
+
const options = this.getOptions();
|
|
11
|
+
const entry = resolveEffectEntryFile(options);
|
|
12
|
+
if (!entry || realpathSync(entry) !== realpathSync(this.resourcePath)) throw new Error(`Unexpected Effect BFF loader resource: ${this.resourcePath}`);
|
|
13
|
+
const query = new URLSearchParams(this.resourceQuery);
|
|
14
|
+
if (query.has('modern-bff-runtime-source')) {
|
|
15
|
+
const { transform } = await import("@swc/core");
|
|
16
|
+
const transformed = await transform(source, {
|
|
17
|
+
filename: this.resourcePath,
|
|
18
|
+
sourceMaps: false,
|
|
19
|
+
jsc: {
|
|
20
|
+
parser: {
|
|
21
|
+
syntax: "typescript",
|
|
22
|
+
tsx: /\.[jt]sx$/.test(this.resourcePath)
|
|
23
|
+
},
|
|
24
|
+
target: 'es2024'
|
|
25
|
+
},
|
|
26
|
+
module: {
|
|
27
|
+
type: 'es6'
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
callback(void 0, await bundleEffectWorkerRuntimeSource(transformed.code, this.resourcePath, this));
|
|
31
|
+
} else if (query.has('modern-bff-runtime')) callback(void 0, await generateEffectWorkerRuntimeWrapper(this, options, this.resourcePath));
|
|
32
|
+
else throw new Error('Effect BFF entries are server-only. Import the shared HttpApi contract and use HttpApiClient.make (or makeEffectHttpApiClient) for a fully inferred client.');
|
|
33
|
+
} catch (error) {
|
|
34
|
+
callback(error instanceof Error ? error : new Error(String(error)));
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
export default loader;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import "node:module";
|
|
2
|
+
import node_path from "node:path";
|
|
3
|
+
import { build } from "esbuild";
|
|
4
|
+
async function bundleEffectWorkerRuntimeSource(source, resourcePath, loader) {
|
|
5
|
+
const result = await build({
|
|
6
|
+
absWorkingDir: node_path.dirname(resourcePath),
|
|
7
|
+
bundle: true,
|
|
8
|
+
format: 'esm',
|
|
9
|
+
metafile: true,
|
|
10
|
+
packages: 'external',
|
|
11
|
+
platform: 'neutral',
|
|
12
|
+
stdin: {
|
|
13
|
+
contents: source,
|
|
14
|
+
loader: 'js',
|
|
15
|
+
resolveDir: node_path.dirname(resourcePath),
|
|
16
|
+
sourcefile: resourcePath
|
|
17
|
+
},
|
|
18
|
+
target: 'es2024',
|
|
19
|
+
write: false
|
|
20
|
+
});
|
|
21
|
+
for (const dependency of Object.keys(result.metafile.inputs))if ('<stdin>' !== dependency) loader.addDependency(node_path.resolve(node_path.dirname(resourcePath), dependency));
|
|
22
|
+
return result.outputFiles[0].text;
|
|
23
|
+
}
|
|
24
|
+
export { bundleEffectWorkerRuntimeSource };
|
|
@@ -1,57 +1,17 @@
|
|
|
1
1
|
import "node:module";
|
|
2
|
+
import { resolveEffectOperationContracts } from "./operation-contracts.mjs";
|
|
2
3
|
async function generateEffectWorkerRuntimeWrapper(loader, options, resourcePath) {
|
|
3
|
-
const
|
|
4
|
-
const artifacts = await generateEffectClient({
|
|
4
|
+
const operationContracts = await resolveEffectOperationContracts({
|
|
5
5
|
appDir: options.appDir,
|
|
6
|
-
apiDir: options.apiDir,
|
|
7
6
|
resourcePath,
|
|
8
7
|
prefix: options.prefix,
|
|
9
|
-
port: Number(options.port),
|
|
10
|
-
target: 'bundle',
|
|
11
8
|
requestId: options.requestId,
|
|
12
|
-
requestCreator: options.requestCreator,
|
|
13
|
-
httpMethodDecider: options.httpMethodDecider,
|
|
14
|
-
dataPlatformBatch: options.effectDataPlatformBatch,
|
|
15
9
|
onDependency: (dependency)=>loader.addDependency(dependency)
|
|
16
10
|
});
|
|
17
11
|
const sourceRequest = `${resourcePath}?modern-bff-runtime-source`;
|
|
18
|
-
const operationContracts = artifacts?.operationContracts ?? {};
|
|
19
12
|
return `import * as effectBffModule from ${JSON.stringify(sourceRequest)};
|
|
20
|
-
import {
|
|
21
|
-
|
|
22
|
-
const __generatedOperationContracts = ${JSON.stringify(operationContracts)};
|
|
23
|
-
|
|
24
|
-
const __mergeGeneratedOperationContracts = policy => {
|
|
25
|
-
if (
|
|
26
|
-
!policy ||
|
|
27
|
-
!policy.expectedOperationContracts ||
|
|
28
|
-
typeof policy.expectedOperationContracts !== 'object' ||
|
|
29
|
-
Array.isArray(policy.expectedOperationContracts)
|
|
30
|
-
) {
|
|
31
|
-
return policy;
|
|
32
|
-
}
|
|
33
|
-
return {
|
|
34
|
-
...policy,
|
|
35
|
-
expectedOperationContracts: {
|
|
36
|
-
...policy.expectedOperationContracts,
|
|
37
|
-
...__generatedOperationContracts,
|
|
38
|
-
},
|
|
39
|
-
};
|
|
40
|
-
};
|
|
41
|
-
|
|
42
|
-
export const __modern_create_effect_bff_dispatcher = options =>
|
|
43
|
-
createEffectBffEdgeDispatcher({
|
|
44
|
-
...options,
|
|
45
|
-
crossProjectPolicy: __mergeGeneratedOperationContracts(
|
|
46
|
-
options?.crossProjectPolicy,
|
|
47
|
-
),
|
|
48
|
-
module: effectBffModule,
|
|
49
|
-
});
|
|
13
|
+
import { createEffectBffEdgeDispatcherFactory } from '@modern-js/bff-effect/effect-edge';
|
|
14
|
+
export const __modern_create_effect_bff_dispatcher = createEffectBffEdgeDispatcherFactory(effectBffModule, ${JSON.stringify(operationContracts ?? {})});
|
|
50
15
|
`;
|
|
51
16
|
}
|
|
52
|
-
|
|
53
|
-
const { generateEffectClient } = await import("../client-generator/generator.mjs");
|
|
54
|
-
const artifacts = await generateEffectClient(options);
|
|
55
|
-
return null === artifacts ? null : artifacts.code;
|
|
56
|
-
}
|
|
57
|
-
export { generateEffectClientCode, generateEffectWorkerRuntimeWrapper };
|
|
17
|
+
export { generateEffectWorkerRuntimeWrapper };
|
|
@@ -6,6 +6,7 @@ const createHonoCrossProjectPolicyMiddleware = (policy, routePath)=>async functi
|
|
|
6
6
|
routePath
|
|
7
7
|
});
|
|
8
8
|
if (denial) return denial;
|
|
9
|
-
|
|
9
|
+
const result = await next();
|
|
10
|
+
return result instanceof Response ? result : void 0;
|
|
10
11
|
};
|
|
11
12
|
export { createHonoCrossProjectPolicyMiddleware };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import "node:module";
|
|
2
|
+
import { logger } from "@modern-js/utils";
|
|
3
|
+
import { resolveAdapterCrossProjectPolicy } from "../cross-project-policy/node.mjs";
|
|
4
|
+
import { bindHonoRouteHandlers } from "./bind-route-handlers.mjs";
|
|
5
|
+
const createHonoRouteBinder = (api, handlers)=>{
|
|
6
|
+
const policy = resolveAdapterCrossProjectPolicy(api, handlers);
|
|
7
|
+
return (options)=>bindHonoRouteHandlers({
|
|
8
|
+
...options,
|
|
9
|
+
policy,
|
|
10
|
+
onError: api.getServerConfig()?.onError,
|
|
11
|
+
reportError: (error)=>logger.error(error)
|
|
12
|
+
});
|
|
13
|
+
};
|
|
14
|
+
export { createHonoRouteBinder };
|
|
@@ -33,14 +33,9 @@ type BackendFederationEdgeRuntimeBaseOptions = {
|
|
|
33
33
|
export type BackendFederationEdgeRuntimeOptions = BackendFederationEdgeRuntimeBaseOptions & {
|
|
34
34
|
expected: BackendFederationExpectedIdentity;
|
|
35
35
|
};
|
|
36
|
-
type EdgeRuntimeLoadOptions = BackendFederationEdgeRuntimeBaseOptions & {
|
|
37
|
-
allowMissingIdentityMetadata?: boolean;
|
|
38
|
-
expected?: BackendFederationExpectedIdentity;
|
|
39
|
-
};
|
|
40
36
|
export type BackendFederationEdgeRuntime = {
|
|
41
37
|
loadRemote<T>(request: string): Promise<T>;
|
|
42
38
|
};
|
|
43
39
|
export declare function createBackendFederationLoadEntryPlugin(options: BackendFederationEdgeLoadEntryPluginOptions): BackendFederationEdgeLoadEntryPlugin;
|
|
44
40
|
export declare function createBackendFederationRuntime(options: BackendFederationEdgeRuntimeOptions): BackendFederationEdgeRuntime;
|
|
45
|
-
export declare function createBackendFederationRuntimeForLoad(options: EdgeRuntimeLoadOptions): BackendFederationEdgeRuntime;
|
|
46
41
|
export {};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { BACKEND_FEDERATION_CONTRACT_VERSION, BACKEND_FEDERATION_EFFECT_EXPOSE, BACKEND_FEDERATION_MANIFEST_FILE, BACKEND_FEDERATION_NODE_ADAPTER_VERSION } from '@modern-js/
|
|
1
|
+
import { BACKEND_FEDERATION_CONTRACT_VERSION, BACKEND_FEDERATION_EFFECT_EXPOSE, BACKEND_FEDERATION_MANIFEST_FILE, BACKEND_FEDERATION_NODE_ADAPTER_VERSION } from '@modern-js/backend-federation-contracts';
|
|
2
2
|
import { type BackendFederationEdgeLoadEntryPlugin, type BackendFederationEdgeLoadEntryPluginOptions, type BackendFederationEdgeRemote, type BackendFederationEdgeRuntimeOptions } from './edge-runtime.js';
|
|
3
3
|
import type { BackendFederatedEffectApiModule, BackendFederationLoadOptions, BackendFederationIdentityLoadOptions as UniversalBackendFederationIdentityLoadOptions } from './types.js';
|
|
4
4
|
export { type BackendFederationEdgeLoadEntryPlugin, type BackendFederationEdgeLoadEntryPluginOptions, type BackendFederationEdgeRemote, type BackendFederationEdgeRuntime, type BackendFederationEdgeRuntimeOptions, createBackendFederationLoadEntryPlugin, createBackendFederationRuntime, } from './edge-runtime.js';
|
|
@@ -8,21 +8,21 @@ export { BACKEND_FEDERATION_CONTRACT_VERSION, BACKEND_FEDERATION_EFFECT_EXPOSE,
|
|
|
8
8
|
export type BackendFederationRemote = BackendFederationEdgeRemote;
|
|
9
9
|
export type BackendFederationRuntimeOptions = BackendFederationEdgeRuntimeOptions;
|
|
10
10
|
export type BackendFederationLoadEntryPluginOptions = BackendFederationEdgeLoadEntryPluginOptions;
|
|
11
|
-
export type EdgeBackendFederationLoadOptions = Omit<BackendFederationLoadOptions, 'entryPolicy' | 'plugins' | 'remote' | 'remotes' | 'runtime'> & {
|
|
11
|
+
export type EdgeBackendFederationLoadOptions = Omit<BackendFederationLoadOptions, 'entryPolicy' | 'plugins' | 'remote' | 'remotes' | 'runtime' | 'shared'> & {
|
|
12
12
|
entryPolicy?: never;
|
|
13
13
|
plugins?: BackendFederationEdgeLoadEntryPlugin[];
|
|
14
14
|
remote?: BackendFederationEdgeRemote;
|
|
15
15
|
remotes?: BackendFederationEdgeRemote[];
|
|
16
16
|
runtime?: never;
|
|
17
|
+
shared?: never;
|
|
17
18
|
};
|
|
18
|
-
export type EdgeBackendFederationIdentityLoadOptions = Omit<UniversalBackendFederationIdentityLoadOptions, 'entryPolicy' | 'plugins' | 'remote' | 'remotes' | 'runtime'> & {
|
|
19
|
+
export type EdgeBackendFederationIdentityLoadOptions = Omit<UniversalBackendFederationIdentityLoadOptions, 'entryPolicy' | 'plugins' | 'remote' | 'remotes' | 'runtime' | 'shared'> & {
|
|
19
20
|
entryPolicy?: never;
|
|
20
21
|
plugins?: BackendFederationEdgeLoadEntryPlugin[];
|
|
21
22
|
remote?: BackendFederationEdgeRemote;
|
|
22
23
|
remotes?: BackendFederationEdgeRemote[];
|
|
23
24
|
runtime?: never;
|
|
25
|
+
shared?: never;
|
|
24
26
|
};
|
|
25
27
|
export type BackendFederationIdentityLoadOptions = EdgeBackendFederationIdentityLoadOptions;
|
|
26
28
|
export declare function loadBackendFederatedEffectApi(options: EdgeBackendFederationIdentityLoadOptions): Promise<BackendFederatedEffectApiModule>;
|
|
27
|
-
/** @deprecated Pass `expected` delivery-unit identity. */
|
|
28
|
-
export declare function loadBackendFederatedEffectApi(options: EdgeBackendFederationLoadOptions): Promise<BackendFederatedEffectApiModule>;
|
|
@@ -11,20 +11,8 @@ export type BackendFederationIdentityIssue = {
|
|
|
11
11
|
path: string;
|
|
12
12
|
message: string;
|
|
13
13
|
};
|
|
14
|
-
/**
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
* Missing identity metadata is an error: with an expectation present there is
|
|
19
|
-
* no legacy escape hatch.
|
|
20
|
-
*/
|
|
21
|
-
export declare function validateExpectedBackendFederationIdentity(loaded: unknown, expected: BackendFederationExpectedIdentity, options?: {
|
|
22
|
-
/**
|
|
23
|
-
* Tolerate exposes that declare no identity metadata (legacy modules).
|
|
24
|
-
* Mismatching declared values still fail. Used by the manifest adapter,
|
|
25
|
-
* whose manifest-side identity is already validated against `expected`;
|
|
26
|
-
* the raw identity-aware loader is strict.
|
|
27
|
-
*/
|
|
28
|
-
allowMissingIdentityMetadata?: boolean;
|
|
29
|
-
}): BackendFederationIdentityIssue[];
|
|
14
|
+
/** Decode independently at each received-manifest / executed-expose boundary. */
|
|
15
|
+
export declare function backendFederationCompatibility(loaded: unknown): Record<string, unknown> | undefined;
|
|
16
|
+
export declare function validateBackendFederationCompatibility(compatibility: Record<string, unknown>, expected: Record<string, string | undefined>): BackendFederationIdentityIssue[];
|
|
17
|
+
export declare function validateExpectedBackendFederationIdentity(loaded: unknown, expected: BackendFederationExpectedIdentity): BackendFederationIdentityIssue[];
|
|
30
18
|
export declare function formatBackendFederationIdentityIssues(issues: BackendFederationIdentityIssue[]): string;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { BACKEND_FEDERATION_CONTRACT_VERSION, BACKEND_FEDERATION_EFFECT_EXPOSE, BACKEND_FEDERATION_MANIFEST_FILE, BACKEND_FEDERATION_NODE_ADAPTER_VERSION } from '@modern-js/
|
|
1
|
+
import { BACKEND_FEDERATION_CONTRACT_VERSION, BACKEND_FEDERATION_EFFECT_EXPOSE, BACKEND_FEDERATION_MANIFEST_FILE, BACKEND_FEDERATION_NODE_ADAPTER_VERSION } from '@modern-js/backend-federation-contracts';
|
|
2
2
|
export { type BackendFederationExpectedIdentity, type BackendFederationIdentityIssue, validateExpectedBackendFederationIdentity, } from './identity.js';
|
|
3
3
|
export { createBackendFederationLoadEntryPlugin } from './plugin.js';
|
|
4
4
|
export { createBackendFederationRuntime } from './runtime.js';
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Module, type ModuleFederation, type ModuleFederationRuntimePlugin } from '@module-federation/runtime';
|
|
2
|
+
import type { BackendFederationEntryExports, BackendFederationRemote, BackendFederationRuntimeOptions } from './types.js';
|
|
3
|
+
type RemoteInfo = ConstructorParameters<typeof Module>[0]['remoteInfo'];
|
|
4
|
+
export declare const PROVIDED_ENTRY_SCHEME: RegExp;
|
|
5
|
+
export declare function registerRemoteContainer(origin: ModuleFederation, remoteInfo: RemoteInfo, container: BackendFederationEntryExports): void;
|
|
6
|
+
/**
|
|
7
|
+
* Loads each configured remote once per runtime and registers the resulting
|
|
8
|
+
* container with that runtime only, so Module Federation initializes it with
|
|
9
|
+
* the runtime's own share scope. Registered last, it replaces any container a
|
|
10
|
+
* caller plugin supplied for a scheme it owns.
|
|
11
|
+
*/
|
|
12
|
+
export declare function createBackendFederationIntegrityPlugin(options: BackendFederationRuntimeOptions, remotes: readonly BackendFederationRemote[]): ModuleFederationRuntimePlugin;
|
|
13
|
+
export {};
|