@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.
Files changed (216) hide show
  1. package/README.md +25 -5
  2. package/dist/cjs/backend-federation/edge-runtime.js +3 -15
  3. package/dist/cjs/backend-federation/edge.js +9 -10
  4. package/dist/cjs/backend-federation/identity.js +26 -31
  5. package/dist/cjs/backend-federation/index.js +5 -5
  6. package/dist/cjs/backend-federation/integrity-plugin.js +112 -0
  7. package/dist/cjs/backend-federation/load.js +3 -13
  8. package/dist/cjs/backend-federation/node-shared.js +85 -0
  9. package/dist/cjs/backend-federation/node.js +6 -1
  10. package/dist/cjs/backend-federation/plugin.js +40 -21
  11. package/dist/cjs/backend-federation/runtime.js +16 -84
  12. package/dist/cjs/backend-federation/validate-loaded.js +2 -4
  13. package/dist/cjs/backend-federation-manifest/load.js +40 -12
  14. package/dist/cjs/backend-federation-manifest/metadata.js +3 -3
  15. package/dist/cjs/backend-federation-manifest/node.js +3 -1
  16. package/dist/cjs/backend-federation-manifest/remote.js +3 -9
  17. package/dist/cjs/backend-federation-manifest/validation.js +16 -12
  18. package/dist/cjs/cross-project-policy/evaluation.js +3 -3
  19. package/dist/cjs/cross-project-policy/node.js +11 -30
  20. package/dist/cjs/{backend-federation/legacy-warning.js → cross-project-policy/producer-runtime.js} +23 -5
  21. package/dist/cjs/{effect-adapter → effect-server}/cross-project-policy.js +5 -5
  22. package/dist/cjs/effect-server/entry.js +63 -0
  23. package/dist/cjs/{effect-adapter → effect-server}/error-response.js +4 -4
  24. package/dist/cjs/effect-server/index.js +199 -0
  25. package/dist/cjs/{client-generator → effect-source-loader}/built-entry.js +5 -6
  26. package/dist/cjs/{client-generator/runtime.js → effect-source-loader/http-api-runtime.js} +12 -20
  27. package/dist/cjs/effect-source-loader/index.js +18 -6
  28. package/dist/cjs/effect-source-loader/loader.js +17 -30
  29. package/dist/cjs/effect-source-loader/operation-contracts.js +60 -0
  30. package/dist/cjs/effect-source-loader/paths.js +90 -0
  31. package/dist/cjs/effect-source-loader/rspack-loader.js +73 -0
  32. package/dist/cjs/effect-source-loader/worker-runtime-source.js +71 -0
  33. package/dist/cjs/effect-source-loader/worker-runtime-wrapper.js +7 -50
  34. package/dist/cjs/hono/cross-project-policy.js +2 -1
  35. package/dist/cjs/{client-generator/paths.js → hono/node.js} +14 -25
  36. package/dist/esm/backend-federation/edge-runtime.mjs +2 -11
  37. package/dist/esm/backend-federation/edge.mjs +5 -6
  38. package/dist/esm/backend-federation/identity.mjs +21 -32
  39. package/dist/esm/backend-federation/index.mjs +1 -1
  40. package/dist/esm/backend-federation/integrity-plugin.mjs +68 -0
  41. package/dist/esm/backend-federation/load.mjs +2 -12
  42. package/dist/esm/backend-federation/node-shared.mjs +41 -0
  43. package/dist/esm/backend-federation/node.mjs +4 -2
  44. package/dist/esm/backend-federation/plugin.mjs +37 -18
  45. package/dist/esm/backend-federation/runtime.mjs +16 -84
  46. package/dist/esm/backend-federation/validate-loaded.mjs +2 -4
  47. package/dist/esm/backend-federation-manifest/load.mjs +40 -12
  48. package/dist/esm/backend-federation-manifest/metadata.mjs +1 -1
  49. package/dist/esm/backend-federation-manifest/node.mjs +3 -1
  50. package/dist/esm/backend-federation-manifest/remote.mjs +2 -8
  51. package/dist/esm/backend-federation-manifest/validation.mjs +15 -11
  52. package/dist/esm/cross-project-policy/evaluation.mjs +1 -1
  53. package/dist/esm/cross-project-policy/node.mjs +10 -19
  54. package/dist/esm/cross-project-policy/producer-runtime.mjs +20 -0
  55. package/dist/esm/{effect-adapter → effect-server}/cross-project-policy.mjs +3 -3
  56. package/dist/esm/effect-server/entry.mjs +15 -0
  57. package/dist/esm/{effect-adapter → effect-server}/error-response.mjs +2 -2
  58. package/dist/esm/effect-server/index.mjs +151 -0
  59. package/dist/esm/{client-generator → effect-source-loader}/built-entry.mjs +6 -7
  60. package/dist/esm/effect-source-loader/http-api-runtime.mjs +19 -0
  61. package/dist/esm/effect-source-loader/index.mjs +5 -2
  62. package/dist/esm/effect-source-loader/loader.mjs +17 -30
  63. package/dist/esm/effect-source-loader/operation-contracts.mjs +22 -0
  64. package/dist/esm/effect-source-loader/paths.mjs +43 -0
  65. package/dist/esm/effect-source-loader/rspack-loader.mjs +35 -0
  66. package/dist/esm/effect-source-loader/worker-runtime-source.mjs +23 -0
  67. package/dist/esm/effect-source-loader/worker-runtime-wrapper.mjs +5 -45
  68. package/dist/esm/hono/cross-project-policy.mjs +2 -1
  69. package/dist/esm-node/backend-federation/edge-runtime.mjs +2 -11
  70. package/dist/esm-node/backend-federation/edge.mjs +5 -6
  71. package/dist/esm-node/backend-federation/identity.mjs +21 -32
  72. package/dist/esm-node/backend-federation/index.mjs +1 -1
  73. package/dist/esm-node/backend-federation/integrity-plugin.mjs +69 -0
  74. package/dist/esm-node/backend-federation/load.mjs +2 -12
  75. package/dist/esm-node/backend-federation/node-shared.mjs +42 -0
  76. package/dist/esm-node/backend-federation/node.mjs +4 -2
  77. package/dist/esm-node/backend-federation/plugin.mjs +37 -18
  78. package/dist/esm-node/backend-federation/runtime.mjs +16 -84
  79. package/dist/esm-node/backend-federation/validate-loaded.mjs +2 -4
  80. package/dist/esm-node/backend-federation-manifest/load.mjs +40 -12
  81. package/dist/esm-node/backend-federation-manifest/metadata.mjs +1 -1
  82. package/dist/esm-node/backend-federation-manifest/node.mjs +3 -1
  83. package/dist/esm-node/backend-federation-manifest/remote.mjs +2 -8
  84. package/dist/esm-node/backend-federation-manifest/validation.mjs +15 -11
  85. package/dist/esm-node/cross-project-policy/evaluation.mjs +1 -1
  86. package/dist/esm-node/cross-project-policy/node.mjs +10 -19
  87. package/dist/esm-node/cross-project-policy/producer-runtime.mjs +21 -0
  88. package/dist/esm-node/{effect-adapter → effect-server}/cross-project-policy.mjs +3 -3
  89. package/dist/esm-node/effect-server/entry.mjs +16 -0
  90. package/dist/esm-node/{effect-adapter → effect-server}/error-response.mjs +2 -2
  91. package/dist/esm-node/effect-server/index.mjs +152 -0
  92. package/dist/esm-node/{client-generator → effect-source-loader}/built-entry.mjs +6 -7
  93. package/dist/esm-node/effect-source-loader/http-api-runtime.mjs +20 -0
  94. package/dist/esm-node/effect-source-loader/index.mjs +5 -2
  95. package/dist/esm-node/effect-source-loader/loader.mjs +17 -30
  96. package/dist/esm-node/effect-source-loader/operation-contracts.mjs +23 -0
  97. package/dist/esm-node/effect-source-loader/paths.mjs +44 -0
  98. package/dist/esm-node/effect-source-loader/rspack-loader.mjs +37 -0
  99. package/dist/esm-node/effect-source-loader/worker-runtime-source.mjs +24 -0
  100. package/dist/esm-node/effect-source-loader/worker-runtime-wrapper.mjs +5 -45
  101. package/dist/esm-node/hono/cross-project-policy.mjs +2 -1
  102. package/dist/esm-node/hono/node.mjs +14 -0
  103. package/dist/types/backend-federation/edge-runtime.d.ts +0 -5
  104. package/dist/types/backend-federation/edge.d.ts +5 -5
  105. package/dist/types/backend-federation/identity.d.ts +4 -16
  106. package/dist/types/backend-federation/index.d.ts +1 -1
  107. package/dist/types/backend-federation/integrity-plugin.d.ts +13 -0
  108. package/dist/types/backend-federation/load.d.ts +1 -7
  109. package/dist/types/backend-federation/node-shared.d.ts +20 -0
  110. package/dist/types/backend-federation/node.d.ts +4 -3
  111. package/dist/types/backend-federation/plugin.d.ts +4 -0
  112. package/dist/types/backend-federation/types.d.ts +3 -14
  113. package/dist/types/backend-federation/validate-loaded.d.ts +1 -2
  114. package/dist/types/backend-federation-manifest/metadata.d.ts +0 -6
  115. package/dist/types/backend-federation-manifest/types.d.ts +2 -1
  116. package/dist/types/cross-project-policy/evaluation.d.ts +1 -1
  117. package/dist/types/cross-project-policy/node.d.ts +3 -2
  118. package/dist/types/cross-project-policy/producer-runtime.d.ts +20 -0
  119. package/dist/types/effect-server/cross-project-policy.d.ts +5 -0
  120. package/dist/types/effect-server/entry.d.ts +3 -0
  121. package/dist/types/effect-server/error-response.d.ts +2 -0
  122. package/dist/types/effect-server/index.d.ts +4 -0
  123. package/dist/types/effect-source-loader/index.d.ts +5 -2
  124. package/dist/types/effect-source-loader/operation-contracts.d.ts +8 -0
  125. package/dist/types/effect-source-loader/paths.d.ts +23 -0
  126. package/dist/types/effect-source-loader/rspack-loader.d.ts +9 -0
  127. package/dist/types/effect-source-loader/worker-runtime-source.d.ts +4 -0
  128. package/dist/types/effect-source-loader/worker-runtime-wrapper.d.ts +4 -22
  129. package/dist/types/hono/node.d.ts +4 -0
  130. package/package.json +64 -36
  131. package/src/backend-federation/edge-runtime.ts +2 -13
  132. package/src/backend-federation/edge.ts +16 -21
  133. package/src/backend-federation/identity.ts +39 -65
  134. package/src/backend-federation/index.ts +1 -1
  135. package/src/backend-federation/integrity-plugin.ts +157 -0
  136. package/src/backend-federation/load.ts +7 -35
  137. package/src/backend-federation/node-shared.ts +76 -0
  138. package/src/backend-federation/node.ts +7 -14
  139. package/src/backend-federation/plugin.ts +73 -25
  140. package/src/backend-federation/runtime.ts +16 -90
  141. package/src/backend-federation/types.ts +3 -18
  142. package/src/backend-federation/validate-loaded.ts +2 -7
  143. package/src/backend-federation-manifest/load.ts +93 -38
  144. package/src/backend-federation-manifest/metadata.ts +1 -7
  145. package/src/backend-federation-manifest/node.ts +3 -2
  146. package/src/backend-federation-manifest/remote.ts +1 -7
  147. package/src/backend-federation-manifest/types.ts +2 -0
  148. package/src/backend-federation-manifest/validation.ts +29 -39
  149. package/src/cross-project-policy/evaluation.ts +1 -1
  150. package/src/cross-project-policy/node.ts +10 -41
  151. package/src/cross-project-policy/producer-runtime.ts +43 -0
  152. package/src/{effect-adapter → effect-server}/cross-project-policy.ts +8 -2
  153. package/src/effect-server/entry.ts +18 -0
  154. package/src/{effect-adapter → effect-server}/error-response.ts +1 -1
  155. package/src/effect-server/index.ts +242 -0
  156. package/src/{client-generator → effect-source-loader}/built-entry.ts +12 -12
  157. package/src/effect-source-loader/http-api-runtime.ts +39 -0
  158. package/src/effect-source-loader/index.ts +8 -5
  159. package/src/effect-source-loader/loader.ts +47 -52
  160. package/src/effect-source-loader/operation-contracts.ts +38 -0
  161. package/src/effect-source-loader/paths.ts +74 -0
  162. package/src/effect-source-loader/rspack-loader.ts +71 -0
  163. package/src/effect-source-loader/worker-runtime-source.ts +34 -0
  164. package/src/effect-source-loader/worker-runtime-wrapper.ts +5 -75
  165. package/src/hono/cross-project-policy.ts +2 -1
  166. package/src/hono/node.ts +24 -0
  167. package/dist/cjs/backend-federation/entry.js +0 -94
  168. package/dist/cjs/client-generator/generator.js +0 -73
  169. package/dist/cjs/client-generator/index.js +0 -54
  170. package/dist/cjs/client-generator/rendering.js +0 -253
  171. package/dist/cjs/client-generator/types.js +0 -18
  172. package/dist/cjs/effect-adapter/entry.js +0 -98
  173. package/dist/cjs/effect-adapter/index.js +0 -187
  174. package/dist/esm/backend-federation/entry.mjs +0 -56
  175. package/dist/esm/backend-federation/legacy-warning.mjs +0 -2
  176. package/dist/esm/client-generator/generator.mjs +0 -32
  177. package/dist/esm/client-generator/index.mjs +0 -3
  178. package/dist/esm/client-generator/paths.mjs +0 -24
  179. package/dist/esm/client-generator/rendering.mjs +0 -209
  180. package/dist/esm/client-generator/runtime.mjs +0 -27
  181. package/dist/esm/client-generator/types.mjs +0 -0
  182. package/dist/esm/effect-adapter/entry.mjs +0 -50
  183. package/dist/esm/effect-adapter/index.mjs +0 -139
  184. package/dist/esm-node/backend-federation/entry.mjs +0 -57
  185. package/dist/esm-node/backend-federation/legacy-warning.mjs +0 -3
  186. package/dist/esm-node/client-generator/generator.mjs +0 -33
  187. package/dist/esm-node/client-generator/index.mjs +0 -4
  188. package/dist/esm-node/client-generator/paths.mjs +0 -25
  189. package/dist/esm-node/client-generator/rendering.mjs +0 -210
  190. package/dist/esm-node/client-generator/runtime.mjs +0 -29
  191. package/dist/esm-node/client-generator/types.mjs +0 -1
  192. package/dist/esm-node/effect-adapter/entry.mjs +0 -51
  193. package/dist/esm-node/effect-adapter/index.mjs +0 -140
  194. package/dist/types/backend-federation/entry.d.ts +0 -2
  195. package/dist/types/backend-federation/legacy-warning.d.ts +0 -1
  196. package/dist/types/client-generator/generator.d.ts +0 -3
  197. package/dist/types/client-generator/index.d.ts +0 -4
  198. package/dist/types/client-generator/paths.d.ts +0 -5
  199. package/dist/types/client-generator/rendering.d.ts +0 -24
  200. package/dist/types/client-generator/types.d.ts +0 -33
  201. package/dist/types/effect-adapter/cross-project-policy.d.ts +0 -4
  202. package/dist/types/effect-adapter/entry.d.ts +0 -2
  203. package/dist/types/effect-adapter/error-response.d.ts +0 -2
  204. package/dist/types/effect-adapter/index.d.ts +0 -19
  205. package/src/backend-federation/entry.ts +0 -125
  206. package/src/backend-federation/legacy-warning.ts +0 -2
  207. package/src/client-generator/generator.ts +0 -52
  208. package/src/client-generator/index.ts +0 -10
  209. package/src/client-generator/paths.ts +0 -40
  210. package/src/client-generator/rendering.ts +0 -307
  211. package/src/client-generator/runtime.ts +0 -69
  212. package/src/client-generator/types.ts +0 -35
  213. package/src/effect-adapter/entry.ts +0 -95
  214. package/src/effect-adapter/index.ts +0 -246
  215. /package/dist/types/{client-generator → effect-source-loader}/built-entry.d.ts +0 -0
  216. /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 = upath.relative(appDirectory, sourceEntry);
8
- if ('..' === relativeEntry || relativeEntry.startsWith(`..${upath.sep}`)) throw new Error(`Effect BFF entry must be inside the application directory: ${sourceEntry}`);
9
- const builtEntry = upath.resolve(distDirectory, relativeEntry).replace(BUILT_ENTRY_EXT, '.js');
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("../effect-source-loader/loader.mjs");
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).replace(BUILT_ENTRY_EXT, '.js') : '';
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 { resolveEffectEntryFile } from "../client-generator/paths.mjs";
2
+ export { bundleBuiltEffectEntryForNode, resolveEffectEntryPaths } from "./built-entry.mjs";
3
3
  export { bundleEffectEntryForNode } from "./loader.mjs";
4
- export { generateEffectClientCode, generateEffectWorkerRuntimeWrapper } from "./worker-runtime-wrapper.mjs";
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(args.path)),
59
- __filename: JSON.stringify(args.path),
60
- 'import.meta.url': JSON.stringify(pathToFileURL(args.path).href)
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
- if (realPath.includes(`${node_path.sep}node_modules${node_path.sep}`)) {
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
- if ('cjs' === options.format) {
145
- let requiredPath;
146
- try {
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 { generateEffectClient } = await import("../client-generator/generator.mjs");
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 { createEffectBffEdgeDispatcher } from '@modern-js/plugin-bff/effect-edge/dispatcher';
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
- async function generateEffectClientCode(options) {
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
- return next();
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/utils/universal';
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
- * Shared expected-identity validation for loaded backend federation modules.
16
- * Compares the expose's `backendFederationContract.compatibility` identity
17
- * (`unitId`, `build`) against the consumer's expected delivery-unit identity.
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/utils/universal';
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 {};