@bleedingdev/modern-js-plugin-bff-extensions 3.8.3-ultramodern.2

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 (228) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +29 -0
  3. package/dist/cjs/backend-federation/edge-runtime.js +230 -0
  4. package/dist/cjs/backend-federation/edge.js +80 -0
  5. package/dist/cjs/backend-federation/entry.js +94 -0
  6. package/dist/cjs/backend-federation/identity.js +82 -0
  7. package/dist/cjs/backend-federation/index.js +61 -0
  8. package/dist/cjs/backend-federation/legacy-warning.js +40 -0
  9. package/dist/cjs/backend-federation/load.js +72 -0
  10. package/dist/cjs/backend-federation/node.js +50 -0
  11. package/dist/cjs/backend-federation/plugin.js +63 -0
  12. package/dist/cjs/backend-federation/remotes.js +51 -0
  13. package/dist/cjs/backend-federation/runtime.js +128 -0
  14. package/dist/cjs/backend-federation/types.js +18 -0
  15. package/dist/cjs/backend-federation/utils.js +48 -0
  16. package/dist/cjs/backend-federation/validate-loaded.js +56 -0
  17. package/dist/cjs/backend-federation-manifest/errors.js +83 -0
  18. package/dist/cjs/backend-federation-manifest/index.js +48 -0
  19. package/dist/cjs/backend-federation-manifest/load.js +173 -0
  20. package/dist/cjs/backend-federation-manifest/metadata.js +101 -0
  21. package/dist/cjs/backend-federation-manifest/node.js +50 -0
  22. package/dist/cjs/backend-federation-manifest/reference.js +132 -0
  23. package/dist/cjs/backend-federation-manifest/remote.js +81 -0
  24. package/dist/cjs/backend-federation-manifest/types.js +18 -0
  25. package/dist/cjs/backend-federation-manifest/validation.js +110 -0
  26. package/dist/cjs/client-generator/built-entry.js +84 -0
  27. package/dist/cjs/client-generator/generator.js +73 -0
  28. package/dist/cjs/client-generator/index.js +54 -0
  29. package/dist/cjs/client-generator/paths.js +62 -0
  30. package/dist/cjs/client-generator/rendering.js +253 -0
  31. package/dist/cjs/client-generator/runtime.js +68 -0
  32. package/dist/cjs/client-generator/types.js +18 -0
  33. package/dist/cjs/cross-project-generation/index.js +40 -0
  34. package/dist/cjs/cross-project-generation/render.js +53 -0
  35. package/dist/cjs/cross-project-policy/evaluation.js +75 -0
  36. package/dist/cjs/cross-project-policy/index.js +40 -0
  37. package/dist/cjs/cross-project-policy/node.js +76 -0
  38. package/dist/cjs/effect-adapter/cross-project-policy.js +64 -0
  39. package/dist/cjs/effect-adapter/entry.js +98 -0
  40. package/dist/cjs/effect-adapter/error-response.js +75 -0
  41. package/dist/cjs/effect-adapter/index.js +187 -0
  42. package/dist/cjs/effect-source-loader/index.js +51 -0
  43. package/dist/cjs/effect-source-loader/loader.js +341 -0
  44. package/dist/cjs/effect-source-loader/worker-runtime-wrapper.js +97 -0
  45. package/dist/cjs/hono/bind-route-handlers.js +76 -0
  46. package/dist/cjs/hono/cross-project-policy.js +48 -0
  47. package/dist/cjs/hono/index.js +40 -0
  48. package/dist/esm/backend-federation/edge-runtime.mjs +186 -0
  49. package/dist/esm/backend-federation/edge.mjs +21 -0
  50. package/dist/esm/backend-federation/entry.mjs +56 -0
  51. package/dist/esm/backend-federation/identity.mjs +41 -0
  52. package/dist/esm/backend-federation/index.mjs +4 -0
  53. package/dist/esm/backend-federation/legacy-warning.mjs +2 -0
  54. package/dist/esm/backend-federation/load.mjs +34 -0
  55. package/dist/esm/backend-federation/node.mjs +12 -0
  56. package/dist/esm/backend-federation/plugin.mjs +25 -0
  57. package/dist/esm/backend-federation/remotes.mjs +13 -0
  58. package/dist/esm/backend-federation/runtime.mjs +90 -0
  59. package/dist/esm/backend-federation/types.mjs +0 -0
  60. package/dist/esm/backend-federation/utils.mjs +7 -0
  61. package/dist/esm/backend-federation/validate-loaded.mjs +18 -0
  62. package/dist/esm/backend-federation-manifest/errors.mjs +32 -0
  63. package/dist/esm/backend-federation-manifest/index.mjs +3 -0
  64. package/dist/esm/backend-federation-manifest/load.mjs +135 -0
  65. package/dist/esm/backend-federation-manifest/metadata.mjs +42 -0
  66. package/dist/esm/backend-federation-manifest/node.mjs +12 -0
  67. package/dist/esm/backend-federation-manifest/reference.mjs +88 -0
  68. package/dist/esm/backend-federation-manifest/remote.mjs +43 -0
  69. package/dist/esm/backend-federation-manifest/types.mjs +0 -0
  70. package/dist/esm/backend-federation-manifest/validation.mjs +66 -0
  71. package/dist/esm/client-generator/built-entry.mjs +40 -0
  72. package/dist/esm/client-generator/generator.mjs +32 -0
  73. package/dist/esm/client-generator/index.mjs +3 -0
  74. package/dist/esm/client-generator/paths.mjs +24 -0
  75. package/dist/esm/client-generator/rendering.mjs +209 -0
  76. package/dist/esm/client-generator/runtime.mjs +27 -0
  77. package/dist/esm/client-generator/types.mjs +0 -0
  78. package/dist/esm/cross-project-generation/index.mjs +1 -0
  79. package/dist/esm/cross-project-generation/render.mjs +15 -0
  80. package/dist/esm/cross-project-policy/evaluation.mjs +34 -0
  81. package/dist/esm/cross-project-policy/index.mjs +1 -0
  82. package/dist/esm/cross-project-policy/node.mjs +28 -0
  83. package/dist/esm/effect-adapter/cross-project-policy.mjs +26 -0
  84. package/dist/esm/effect-adapter/entry.mjs +50 -0
  85. package/dist/esm/effect-adapter/error-response.mjs +37 -0
  86. package/dist/esm/effect-adapter/index.mjs +139 -0
  87. package/dist/esm/effect-source-loader/index.mjs +3 -0
  88. package/dist/esm/effect-source-loader/loader.mjs +285 -0
  89. package/dist/esm/effect-source-loader/worker-runtime-wrapper.mjs +56 -0
  90. package/dist/esm/hono/bind-route-handlers.mjs +38 -0
  91. package/dist/esm/hono/cross-project-policy.mjs +10 -0
  92. package/dist/esm/hono/index.mjs +1 -0
  93. package/dist/esm-node/backend-federation/edge-runtime.mjs +187 -0
  94. package/dist/esm-node/backend-federation/edge.mjs +22 -0
  95. package/dist/esm-node/backend-federation/entry.mjs +57 -0
  96. package/dist/esm-node/backend-federation/identity.mjs +42 -0
  97. package/dist/esm-node/backend-federation/index.mjs +5 -0
  98. package/dist/esm-node/backend-federation/legacy-warning.mjs +3 -0
  99. package/dist/esm-node/backend-federation/load.mjs +35 -0
  100. package/dist/esm-node/backend-federation/node.mjs +13 -0
  101. package/dist/esm-node/backend-federation/plugin.mjs +26 -0
  102. package/dist/esm-node/backend-federation/remotes.mjs +14 -0
  103. package/dist/esm-node/backend-federation/runtime.mjs +91 -0
  104. package/dist/esm-node/backend-federation/types.mjs +1 -0
  105. package/dist/esm-node/backend-federation/utils.mjs +8 -0
  106. package/dist/esm-node/backend-federation/validate-loaded.mjs +19 -0
  107. package/dist/esm-node/backend-federation-manifest/errors.mjs +33 -0
  108. package/dist/esm-node/backend-federation-manifest/index.mjs +4 -0
  109. package/dist/esm-node/backend-federation-manifest/load.mjs +136 -0
  110. package/dist/esm-node/backend-federation-manifest/metadata.mjs +43 -0
  111. package/dist/esm-node/backend-federation-manifest/node.mjs +13 -0
  112. package/dist/esm-node/backend-federation-manifest/reference.mjs +89 -0
  113. package/dist/esm-node/backend-federation-manifest/remote.mjs +44 -0
  114. package/dist/esm-node/backend-federation-manifest/types.mjs +1 -0
  115. package/dist/esm-node/backend-federation-manifest/validation.mjs +67 -0
  116. package/dist/esm-node/client-generator/built-entry.mjs +41 -0
  117. package/dist/esm-node/client-generator/generator.mjs +33 -0
  118. package/dist/esm-node/client-generator/index.mjs +4 -0
  119. package/dist/esm-node/client-generator/paths.mjs +25 -0
  120. package/dist/esm-node/client-generator/rendering.mjs +210 -0
  121. package/dist/esm-node/client-generator/runtime.mjs +29 -0
  122. package/dist/esm-node/client-generator/types.mjs +1 -0
  123. package/dist/esm-node/cross-project-generation/index.mjs +2 -0
  124. package/dist/esm-node/cross-project-generation/render.mjs +16 -0
  125. package/dist/esm-node/cross-project-policy/evaluation.mjs +35 -0
  126. package/dist/esm-node/cross-project-policy/index.mjs +2 -0
  127. package/dist/esm-node/cross-project-policy/node.mjs +29 -0
  128. package/dist/esm-node/effect-adapter/cross-project-policy.mjs +27 -0
  129. package/dist/esm-node/effect-adapter/entry.mjs +51 -0
  130. package/dist/esm-node/effect-adapter/error-response.mjs +38 -0
  131. package/dist/esm-node/effect-adapter/index.mjs +140 -0
  132. package/dist/esm-node/effect-source-loader/index.mjs +4 -0
  133. package/dist/esm-node/effect-source-loader/loader.mjs +286 -0
  134. package/dist/esm-node/effect-source-loader/worker-runtime-wrapper.mjs +57 -0
  135. package/dist/esm-node/hono/bind-route-handlers.mjs +39 -0
  136. package/dist/esm-node/hono/cross-project-policy.mjs +11 -0
  137. package/dist/esm-node/hono/index.mjs +2 -0
  138. package/dist/types/backend-federation/edge-runtime.d.ts +46 -0
  139. package/dist/types/backend-federation/edge.d.ts +28 -0
  140. package/dist/types/backend-federation/entry.d.ts +2 -0
  141. package/dist/types/backend-federation/identity.d.ts +30 -0
  142. package/dist/types/backend-federation/index.d.ts +6 -0
  143. package/dist/types/backend-federation/legacy-warning.d.ts +1 -0
  144. package/dist/types/backend-federation/load.d.ts +13 -0
  145. package/dist/types/backend-federation/node.d.ts +4 -0
  146. package/dist/types/backend-federation/plugin.d.ts +3 -0
  147. package/dist/types/backend-federation/remotes.d.ts +2 -0
  148. package/dist/types/backend-federation/runtime.d.ts +3 -0
  149. package/dist/types/backend-federation/types.d.ts +76 -0
  150. package/dist/types/backend-federation/utils.d.ts +2 -0
  151. package/dist/types/backend-federation/validate-loaded.d.ts +8 -0
  152. package/dist/types/backend-federation-manifest/errors.d.ts +11 -0
  153. package/dist/types/backend-federation-manifest/index.d.ts +5 -0
  154. package/dist/types/backend-federation-manifest/load.d.ts +3 -0
  155. package/dist/types/backend-federation-manifest/metadata.d.ts +18 -0
  156. package/dist/types/backend-federation-manifest/node.d.ts +3 -0
  157. package/dist/types/backend-federation-manifest/reference.d.ts +4 -0
  158. package/dist/types/backend-federation-manifest/remote.d.ts +3 -0
  159. package/dist/types/backend-federation-manifest/types.d.ts +49 -0
  160. package/dist/types/backend-federation-manifest/validation.d.ts +5 -0
  161. package/dist/types/client-generator/built-entry.d.ts +16 -0
  162. package/dist/types/client-generator/generator.d.ts +3 -0
  163. package/dist/types/client-generator/index.d.ts +4 -0
  164. package/dist/types/client-generator/paths.d.ts +5 -0
  165. package/dist/types/client-generator/rendering.d.ts +24 -0
  166. package/dist/types/client-generator/runtime.d.ts +12 -0
  167. package/dist/types/client-generator/types.d.ts +33 -0
  168. package/dist/types/cross-project-generation/index.d.ts +1 -0
  169. package/dist/types/cross-project-generation/render.d.ts +1 -0
  170. package/dist/types/cross-project-policy/evaluation.d.ts +4 -0
  171. package/dist/types/cross-project-policy/index.d.ts +1 -0
  172. package/dist/types/cross-project-policy/node.d.ts +4 -0
  173. package/dist/types/effect-adapter/cross-project-policy.d.ts +4 -0
  174. package/dist/types/effect-adapter/entry.d.ts +2 -0
  175. package/dist/types/effect-adapter/error-response.d.ts +2 -0
  176. package/dist/types/effect-adapter/index.d.ts +19 -0
  177. package/dist/types/effect-source-loader/index.d.ts +3 -0
  178. package/dist/types/effect-source-loader/loader.d.ts +17 -0
  179. package/dist/types/effect-source-loader/worker-runtime-wrapper.d.ts +25 -0
  180. package/dist/types/hono/bind-route-handlers.d.ts +10 -0
  181. package/dist/types/hono/cross-project-policy.d.ts +3 -0
  182. package/dist/types/hono/index.d.ts +1 -0
  183. package/package.json +213 -0
  184. package/src/backend-federation/edge-runtime.ts +258 -0
  185. package/src/backend-federation/edge.ts +128 -0
  186. package/src/backend-federation/entry.ts +125 -0
  187. package/src/backend-federation/identity.ts +97 -0
  188. package/src/backend-federation/index.ts +30 -0
  189. package/src/backend-federation/legacy-warning.ts +2 -0
  190. package/src/backend-federation/load.ts +102 -0
  191. package/src/backend-federation/node.ts +33 -0
  192. package/src/backend-federation/plugin.ts +35 -0
  193. package/src/backend-federation/remotes.ts +17 -0
  194. package/src/backend-federation/runtime.ts +99 -0
  195. package/src/backend-federation/types.ts +103 -0
  196. package/src/backend-federation/utils.ts +7 -0
  197. package/src/backend-federation/validate-loaded.ts +72 -0
  198. package/src/backend-federation-manifest/errors.ts +85 -0
  199. package/src/backend-federation-manifest/index.ts +11 -0
  200. package/src/backend-federation-manifest/load.ts +266 -0
  201. package/src/backend-federation-manifest/metadata.ts +73 -0
  202. package/src/backend-federation-manifest/node.ts +19 -0
  203. package/src/backend-federation-manifest/reference.ts +240 -0
  204. package/src/backend-federation-manifest/remote.ts +102 -0
  205. package/src/backend-federation-manifest/types.ts +73 -0
  206. package/src/backend-federation-manifest/validation.ts +255 -0
  207. package/src/client-generator/built-entry.ts +70 -0
  208. package/src/client-generator/generator.ts +52 -0
  209. package/src/client-generator/index.ts +10 -0
  210. package/src/client-generator/paths.ts +40 -0
  211. package/src/client-generator/rendering.ts +307 -0
  212. package/src/client-generator/runtime.ts +69 -0
  213. package/src/client-generator/types.ts +35 -0
  214. package/src/cross-project-generation/index.ts +1 -0
  215. package/src/cross-project-generation/render.ts +14 -0
  216. package/src/cross-project-policy/evaluation.ts +70 -0
  217. package/src/cross-project-policy/index.ts +1 -0
  218. package/src/cross-project-policy/node.ts +63 -0
  219. package/src/effect-adapter/cross-project-policy.ts +63 -0
  220. package/src/effect-adapter/entry.ts +95 -0
  221. package/src/effect-adapter/error-response.ts +68 -0
  222. package/src/effect-adapter/index.ts +246 -0
  223. package/src/effect-source-loader/index.ts +6 -0
  224. package/src/effect-source-loader/loader.ts +397 -0
  225. package/src/effect-source-loader/worker-runtime-wrapper.ts +90 -0
  226. package/src/hono/bind-route-handlers.ts +62 -0
  227. package/src/hono/cross-project-policy.ts +26 -0
  228. package/src/hono/index.ts +4 -0
@@ -0,0 +1,42 @@
1
+ import "node:module";
2
+ import { isRecord } from "./utils.mjs";
3
+ function validateExpectedBackendFederationIdentity(loaded, expected, options = {}) {
4
+ const allowMissing = true === options.allowMissingIdentityMetadata;
5
+ const issues = [];
6
+ const contract = isRecord(loaded) ? loaded.backendFederationContract : void 0;
7
+ const compatibility = isRecord(contract) ? contract.compatibility : void 0;
8
+ if (!isRecord(compatibility)) {
9
+ if (allowMissing) return [];
10
+ return [
11
+ {
12
+ path: 'backendFederationContract.compatibility',
13
+ message: 'loaded module declares no compatibility metadata; delivery-unit identity cannot be validated'
14
+ }
15
+ ];
16
+ }
17
+ const unitId = compatibility.unitId;
18
+ if ('string' != typeof unitId || 0 === unitId.length) {
19
+ if (!allowMissing) issues.push({
20
+ path: 'backendFederationContract.compatibility.unitId',
21
+ message: `missing delivery-unit id; expected ${expected.unitId}`
22
+ });
23
+ } else if (unitId !== expected.unitId) issues.push({
24
+ path: 'backendFederationContract.compatibility.unitId',
25
+ message: `expected ${expected.unitId}, received ${unitId}`
26
+ });
27
+ const build = compatibility.build;
28
+ if ('string' != typeof build || 0 === build.length) {
29
+ if (!allowMissing) issues.push({
30
+ path: 'backendFederationContract.compatibility.build',
31
+ message: `missing build marker; expected ${expected.buildMarker}`
32
+ });
33
+ } else if (build !== expected.buildMarker) issues.push({
34
+ path: 'backendFederationContract.compatibility.build',
35
+ message: `expected ${expected.buildMarker}, received ${build}`
36
+ });
37
+ return issues;
38
+ }
39
+ function formatBackendFederationIdentityIssues(issues) {
40
+ return issues.map((issue)=>`${issue.path}: ${issue.message}`).join('; ');
41
+ }
42
+ export { formatBackendFederationIdentityIssues, validateExpectedBackendFederationIdentity };
@@ -0,0 +1,5 @@
1
+ import "node:module";
2
+ export { BACKEND_FEDERATION_CONTRACT_VERSION, BACKEND_FEDERATION_EFFECT_EXPOSE, BACKEND_FEDERATION_MANIFEST_FILE, BACKEND_FEDERATION_NODE_ADAPTER_VERSION } from "@modern-js/utils/universal";
3
+ export { validateExpectedBackendFederationIdentity } from "./identity.mjs";
4
+ export { createBackendFederationLoadEntryPlugin } from "./plugin.mjs";
5
+ export { createBackendFederationRuntime } from "./runtime.mjs";
@@ -0,0 +1,3 @@
1
+ import "node:module";
2
+ const LEGACY_LOAD_WARNING = '[BFF][Effect] loadBackendFederatedEffectApi was called without an expected delivery-unit identity (expected.unitId + expected.buildMarker). Identity-less public backend loads are deprecated (ADR-0019/MV-G23) and will be rejected in a future major.';
3
+ export { LEGACY_LOAD_WARNING };
@@ -0,0 +1,35 @@
1
+ import "node:module";
2
+ import { BACKEND_FEDERATION_EFFECT_EXPOSE } from "@modern-js/utils/universal";
3
+ import { LEGACY_LOAD_WARNING } from "./legacy-warning.mjs";
4
+ import { collectRemotes } from "./remotes.mjs";
5
+ import { createBackendFederationRuntime } from "./runtime.mjs";
6
+ import { normalizeExpose } from "./utils.mjs";
7
+ import { validateLoadedBackendFederatedEffectApi } from "./validate-loaded.mjs";
8
+ import * as __rspack_external_effect_Effect_41060786 from "effect/Effect";
9
+ import * as __rspack_external_effect_Logger_1691a01b from "effect/Logger";
10
+ const legacyWarningLogger = __rspack_external_effect_Logger_1691a01b.withLeveledConsole(__rspack_external_effect_Logger_1691a01b.formatLogFmt);
11
+ function warnLegacyLoad() {
12
+ __rspack_external_effect_Effect_41060786.runSync(__rspack_external_effect_Effect_41060786.provideService(__rspack_external_effect_Effect_41060786.logWarning(LEGACY_LOAD_WARNING), __rspack_external_effect_Logger_1691a01b.CurrentLoggers, new Set([
13
+ legacyWarningLogger
14
+ ])));
15
+ }
16
+ function loadBackendFederatedEffectApi(options) {
17
+ const remoteName = options.remote?.name ?? options.remoteName;
18
+ if (void 0 === remoteName || 0 === remoteName.length) return Promise.reject(new Error('[BFF][Effect] Missing backend federation remote name.'));
19
+ if (void 0 === options.expected) warnLegacyLoad();
20
+ if (void 0 !== options.runtime) {
21
+ const configuredRemote = collectRemotes(options).find((remote)=>remote.name === remoteName);
22
+ if (void 0 === configuredRemote || !/^(?:binding|service|static):/u.test(configuredRemote.entry)) return Promise.reject(new Error('[BFF][Effect] A custom Module Federation runtime requires a caller-pinned static or service-binding remote and cannot execute network backend federation entries.'));
23
+ if (void 0 !== configuredRemote.verification || options.entryPolicy?.expected !== void 0) return Promise.reject(new Error('[BFF][Effect] A custom Module Federation runtime cannot bypass verified backend entry loading.'));
24
+ }
25
+ const runtime = options.runtime ?? createBackendFederationRuntime(options);
26
+ const expose = options.expose ?? options.remote?.expose ?? BACKEND_FEDERATION_EFFECT_EXPOSE;
27
+ const remoteRequest = `${remoteName}/${normalizeExpose(expose)}`;
28
+ return runtime.loadRemote(remoteRequest).then((loaded)=>validateLoadedBackendFederatedEffectApi(loaded, {
29
+ allowMissingIdentityMetadata: options.allowMissingIdentityMetadata,
30
+ expected: options.expected,
31
+ remoteName,
32
+ remoteRequest
33
+ }));
34
+ }
35
+ export { loadBackendFederatedEffectApi };
@@ -0,0 +1,13 @@
1
+ import "node:module";
2
+ import { evaluateNodeBackendFederationCommonJs } from "@modern-js/server-runtime-extensions/backend-federation-security/node";
3
+ import { loadBackendFederatedEffectApi } from "./load.mjs";
4
+ function node_loadBackendFederatedEffectApi(options) {
5
+ return loadBackendFederatedEffectApi({
6
+ ...options,
7
+ entryPolicy: {
8
+ ...options.entryPolicy,
9
+ evaluateCommonJs: options.entryPolicy?.evaluateCommonJs ?? evaluateNodeBackendFederationCommonJs
10
+ }
11
+ });
12
+ }
13
+ export { node_loadBackendFederatedEffectApi as loadBackendFederatedEffectApi };
@@ -0,0 +1,26 @@
1
+ import "node:module";
2
+ function createBackendFederationLoadEntryPlugin(options) {
3
+ return {
4
+ name: 'modernjs-backend-federation-load-entry',
5
+ loadEntry ({ remoteInfo }) {
6
+ return Promise.resolve(options.resolveEntry({
7
+ name: remoteInfo.name,
8
+ entry: remoteInfo.entry,
9
+ type: remoteInfo.type,
10
+ entryGlobalName: remoteInfo.entryGlobalName,
11
+ shareScope: remoteInfo.shareScope
12
+ })).then((entry)=>{
13
+ if (void 0 === entry) return;
14
+ return {
15
+ get (id) {
16
+ return ()=>Promise.resolve(entry.get(id)).then((factory)=>factory());
17
+ },
18
+ init (...args) {
19
+ return entry.init?.(...args);
20
+ }
21
+ };
22
+ });
23
+ }
24
+ };
25
+ }
26
+ export { createBackendFederationLoadEntryPlugin };
@@ -0,0 +1,14 @@
1
+ import "node:module";
2
+ function collectRemotes(options) {
3
+ const remotes = [
4
+ ...options.remotes ?? []
5
+ ];
6
+ const configuredRemote = options.remote;
7
+ if (void 0 !== configuredRemote) {
8
+ const existingIndex = remotes.findIndex((remote)=>remote.name === configuredRemote.name);
9
+ if (existingIndex >= 0) remotes[existingIndex] = configuredRemote;
10
+ else remotes.push(configuredRemote);
11
+ }
12
+ return remotes;
13
+ }
14
+ export { collectRemotes };
@@ -0,0 +1,91 @@
1
+ import "node:module";
2
+ import { ModuleFederation } from "@module-federation/runtime";
3
+ import { loadBackendFederationExpose } from "./entry.mjs";
4
+ import { createBackendFederationLoadEntryPlugin } from "./plugin.mjs";
5
+ import { collectRemotes } from "./remotes.mjs";
6
+ function _check_private_redeclaration(obj, privateCollection) {
7
+ if (privateCollection.has(obj)) throw new TypeError("Cannot initialize the same private elements twice on an object");
8
+ }
9
+ function _class_apply_descriptor_get(receiver, descriptor) {
10
+ if (descriptor.get) return descriptor.get.call(receiver);
11
+ return descriptor.value;
12
+ }
13
+ function _class_apply_descriptor_set(receiver, descriptor, value) {
14
+ if (descriptor.set) descriptor.set.call(receiver, value);
15
+ else {
16
+ if (!descriptor.writable) throw new TypeError("attempted to set read only private field");
17
+ descriptor.value = value;
18
+ }
19
+ }
20
+ function _class_extract_field_descriptor(receiver, privateMap, action) {
21
+ if (!privateMap.has(receiver)) throw new TypeError("attempted to " + action + " private field on non-instance");
22
+ return privateMap.get(receiver);
23
+ }
24
+ function _class_private_field_get(receiver, privateMap) {
25
+ var descriptor = _class_extract_field_descriptor(receiver, privateMap, "get");
26
+ return _class_apply_descriptor_get(receiver, descriptor);
27
+ }
28
+ function _class_private_field_init(obj, privateMap, value) {
29
+ _check_private_redeclaration(obj, privateMap);
30
+ privateMap.set(obj, value);
31
+ }
32
+ function _class_private_field_set(receiver, privateMap, value) {
33
+ var descriptor = _class_extract_field_descriptor(receiver, privateMap, "set");
34
+ _class_apply_descriptor_set(receiver, descriptor, value);
35
+ return value;
36
+ }
37
+ let nextRuntimeId = 0;
38
+ function parseRemoteRequest(request) {
39
+ const [remoteName, ...exposeParts] = request.split('/');
40
+ if (void 0 === remoteName || 0 === remoteName.length || 0 === exposeParts.length) return;
41
+ return remoteName;
42
+ }
43
+ function createLocalEntryPlugin(options, remotes) {
44
+ return createBackendFederationLoadEntryPlugin({
45
+ resolveEntry (resolvedRemote) {
46
+ const remote = remotes.find((candidate)=>candidate.name === resolvedRemote.name);
47
+ if (void 0 === remote) return;
48
+ return {
49
+ get (expose) {
50
+ return ()=>loadBackendFederationExpose(remote, expose, options);
51
+ }
52
+ };
53
+ }
54
+ });
55
+ }
56
+ function isolateRegisteredRemoteEntries(remotes) {
57
+ const runtimeId = nextRuntimeId;
58
+ nextRuntimeId += 1;
59
+ return remotes.map((remote)=>({
60
+ ...remote,
61
+ entry: `${remote.entry}#modernjs-backend-runtime-${runtimeId}`
62
+ }));
63
+ }
64
+ var _remoteNames = /*#__PURE__*/ new WeakMap();
65
+ class BackendFederationRuntime extends ModuleFederation {
66
+ loadRemote(request, loadOptions) {
67
+ const remoteName = parseRemoteRequest(request);
68
+ if (void 0 === remoteName) return Promise.reject(new Error(`[BFF][Effect] Invalid backend federation request ${request}.`));
69
+ if (!_class_private_field_get(this, _remoteNames).has(remoteName)) return Promise.reject(new Error(`[BFF][Effect] Missing backend federation remote ${remoteName}.`));
70
+ return super.loadRemote(request, loadOptions);
71
+ }
72
+ constructor(options, remotes){
73
+ super({
74
+ name: options.hostName,
75
+ remotes: isolateRegisteredRemoteEntries(remotes),
76
+ shared: {},
77
+ plugins: [
78
+ createLocalEntryPlugin(options, remotes)
79
+ ]
80
+ }), _class_private_field_init(this, _remoteNames, {
81
+ writable: true,
82
+ value: void 0
83
+ });
84
+ _class_private_field_set(this, _remoteNames, new Set(remotes.map((remote)=>remote.name)));
85
+ }
86
+ }
87
+ function createBackendFederationRuntime(options) {
88
+ const remotes = collectRemotes(options);
89
+ return new BackendFederationRuntime(options, remotes);
90
+ }
91
+ export { createBackendFederationRuntime };
@@ -0,0 +1 @@
1
+ import "node:module";
@@ -0,0 +1,8 @@
1
+ import "node:module";
2
+ function normalizeExpose(expose) {
3
+ return expose.replace(/^\.\//u, '');
4
+ }
5
+ function isRecord(value) {
6
+ return 'object' == typeof value && null !== value;
7
+ }
8
+ export { isRecord, normalizeExpose };
@@ -0,0 +1,19 @@
1
+ import "node:module";
2
+ import { formatBackendFederationIdentityIssues, validateExpectedBackendFederationIdentity } from "./identity.mjs";
3
+ import { isRecord } from "./utils.mjs";
4
+ function validateLoadedBackendFederatedEffectApi(loaded, options) {
5
+ if (!isRecord(loaded)) throw new Error(`[BFF][Effect] Backend federation expose ${options.remoteRequest} must load an object module.`);
6
+ const backendContract = loaded.backendFederationContract;
7
+ if (!isRecord(backendContract) || true !== backendContract.strictEffectApproach) throw new Error(`[BFF][Effect] Backend federation expose ${options.remoteRequest} must expose strict Effect metadata (strictEffectApproach: true).`);
8
+ if ('effect' !== backendContract.runtimeFramework) throw new Error(`[BFF][Effect] Backend federation expose ${options.remoteRequest} must expose strict Effect metadata (runtimeFramework: "effect").`);
9
+ if ('string' == typeof backendContract.name && backendContract.name !== options.remoteName) throw new Error(`[BFF][Effect] Backend federation expose ${options.remoteRequest} metadata name mismatch: expected ${options.remoteName}, received ${backendContract.name}.`);
10
+ if (!('runtime' in loaded)) throw new Error(`[BFF][Effect] Backend federation expose ${options.remoteRequest} must expose runtime.`);
11
+ if (void 0 !== options.expected) {
12
+ const issues = validateExpectedBackendFederationIdentity(loaded, options.expected, {
13
+ allowMissingIdentityMetadata: true === options.allowMissingIdentityMetadata
14
+ });
15
+ if (issues.length > 0) throw new Error(`[BFF][Effect] Backend federation expose ${options.remoteRequest} delivery-unit identity mismatch: ${formatBackendFederationIdentityIssues(issues)}.`);
16
+ }
17
+ return loaded;
18
+ }
19
+ export { validateLoadedBackendFederatedEffectApi };
@@ -0,0 +1,33 @@
1
+ import "node:module";
2
+ const BACKEND_FEDERATION_MANIFEST_ADAPTER_FAILURE_EVENT = 'modernjs:microvertical-server-fallback';
3
+ class BackendFederationManifestAdapterError extends Error {
4
+ constructor(code, message, cause, details){
5
+ super(message), this.failureEvent = BACKEND_FEDERATION_MANIFEST_ADAPTER_FAILURE_EVENT;
6
+ this.name = 'BackendFederationManifestAdapterError';
7
+ this.code = code;
8
+ if (details) this.details = details;
9
+ if (void 0 !== cause) this.cause = cause;
10
+ }
11
+ }
12
+ function assertManifestAdapter(condition, code, message) {
13
+ if (!condition) throw new BackendFederationManifestAdapterError(code, message);
14
+ }
15
+ function assertVersionValue(actual, expected, label, details) {
16
+ if (void 0 === expected) return;
17
+ if (actual !== expected) throw new BackendFederationManifestAdapterError('version_mismatch', `[BFF][Effect] Backend federation ${label} mismatch: expected ${expected}, received ${actual ?? 'undefined'}.`, void 0, {
18
+ label,
19
+ expected,
20
+ received: actual,
21
+ ...details
22
+ });
23
+ }
24
+ function assertConsistentValue(left, right, label, details) {
25
+ if (void 0 === left || void 0 === right || left === right) return;
26
+ throw new BackendFederationManifestAdapterError('version_mismatch', `[BFF][Effect] Backend federation ${label} mismatch: expected ${left}, received ${right}.`, void 0, {
27
+ label,
28
+ expected: left,
29
+ received: right,
30
+ ...details
31
+ });
32
+ }
33
+ export { BACKEND_FEDERATION_MANIFEST_ADAPTER_FAILURE_EVENT, BackendFederationManifestAdapterError, assertConsistentValue, assertManifestAdapter, assertVersionValue };
@@ -0,0 +1,4 @@
1
+ import "node:module";
2
+ export { BackendFederationManifestAdapterError } from "./errors.mjs";
3
+ export { loadBackendFederationManifest } from "./reference.mjs";
4
+ export { resolveBackendFederationRemoteFromManifest } from "./remote.mjs";
@@ -0,0 +1,136 @@
1
+ import "node:module";
2
+ import { BACKEND_FEDERATION_EFFECT_EXPOSE } from "../backend-federation/index.mjs";
3
+ import { loadBackendFederatedEffectApi } from "../backend-federation/load.mjs";
4
+ import { BackendFederationManifestAdapterError } from "./errors.mjs";
5
+ import { loadBackendFederationManifest } from "./reference.mjs";
6
+ import { resolveBackendFederationRemoteFromManifest } from "./remote.mjs";
7
+ import { classifyLoadError, validateBackendFederationManifest, validateLoadedBackendFederationContract } from "./validation.mjs";
8
+ function createManifestLoadScope(options) {
9
+ const controller = new AbortController();
10
+ const policyTimeouts = [
11
+ options.manifestPolicy?.timeoutMs,
12
+ options.entryPolicy?.timeoutMs
13
+ ].filter((timeout)=>void 0 !== timeout);
14
+ const configuredTimeouts = [
15
+ options.timeoutMs,
16
+ ...policyTimeouts
17
+ ].filter((timeout)=>void 0 !== timeout);
18
+ for (const timeout of configuredTimeouts)if (!Number.isSafeInteger(timeout) || timeout < 0) throw new BackendFederationManifestAdapterError('manifest_invalid', '[BFF][Effect] Backend federation timeoutMs must be a non-negative safe integer.');
19
+ const timeoutMs = options.timeoutMs ?? (policyTimeouts.length > 0 ? Math.min(...policyTimeouts) : 0);
20
+ const inputSignals = [
21
+ options.signal,
22
+ options.manifestPolicy?.signal,
23
+ options.entryPolicy?.signal
24
+ ].filter((signal)=>void 0 !== signal);
25
+ const abortListeners = [];
26
+ let timedOut = false;
27
+ const forwardAbort = (signal)=>{
28
+ controller.abort(signal.reason);
29
+ };
30
+ for (const signal of inputSignals){
31
+ if (signal.aborted) {
32
+ forwardAbort(signal);
33
+ break;
34
+ }
35
+ const listener = ()=>forwardAbort(signal);
36
+ abortListeners.push([
37
+ signal,
38
+ listener
39
+ ]);
40
+ signal.addEventListener('abort', listener, {
41
+ once: true
42
+ });
43
+ }
44
+ const timeout = timeoutMs > 0 ? setTimeout(()=>{
45
+ if (controller.signal.aborted) return;
46
+ timedOut = true;
47
+ controller.abort(new BackendFederationManifestAdapterError('timeout', `[BFF][Effect] Backend federation load timed out after ${timeoutMs}ms.`));
48
+ }, timeoutMs) : void 0;
49
+ return {
50
+ cleanup () {
51
+ if (timeout) clearTimeout(timeout);
52
+ for (const [signal, listener] of abortListeners)signal.removeEventListener('abort', listener);
53
+ },
54
+ signal: controller.signal,
55
+ timedOut: ()=>timedOut,
56
+ timeoutMs
57
+ };
58
+ }
59
+ function isRemoteManifestReference(options) {
60
+ if (void 0 !== options.manifest || options.manifestPath) return false;
61
+ return Boolean(options.manifestUrl || options.manifestEnv);
62
+ }
63
+ function hasPinnedRemoteEntryExpectation(options) {
64
+ const expected = options.entryPolicy?.expected;
65
+ return 'number' == typeof expected?.byteLength && 'string' == typeof expected.entryUrl && 'string' == typeof expected.remoteName && 'string' == typeof expected.sha256;
66
+ }
67
+ function isCallerPinnedStaticRemote(options, remote) {
68
+ return options.remote?.entry === remote.entry && options.remote?.name === remote.name && /^(?:binding|service|static):/u.test(remote.entry);
69
+ }
70
+ function throwIfManifestLoadAborted(signal) {
71
+ if (signal.aborted) throw new BackendFederationManifestAdapterError('remote_unavailable', '[BFF][Effect] Backend federation load was aborted before remote execution.', signal.reason);
72
+ }
73
+ async function loadBackendFederatedEffectApiFromManifest(options) {
74
+ let manifest;
75
+ let remote;
76
+ let scope;
77
+ try {
78
+ scope = createManifestLoadScope(options);
79
+ throwIfManifestLoadAborted(scope.signal);
80
+ manifest = await loadBackendFederationManifest({
81
+ ...options,
82
+ manifestPolicy: {
83
+ ...options.manifestPolicy,
84
+ signal: scope.signal,
85
+ timeoutMs: 0
86
+ },
87
+ signal: scope.signal,
88
+ timeoutMs: 0
89
+ });
90
+ validateBackendFederationManifest(manifest, options.expected);
91
+ remote = resolveBackendFederationRemoteFromManifest(manifest, options.remote);
92
+ throwIfManifestLoadAborted(scope.signal);
93
+ const remoteManifest = isRemoteManifestReference(options);
94
+ if (remoteManifest && void 0 !== options.runtime) throw new BackendFederationManifestAdapterError('manifest_invalid', `[BFF][Effect] Backend federation remote ${remote.name} cannot use a custom runtime selected by a network manifest.`);
95
+ if (remoteManifest && !/^https?:\/\//iu.test(remote.entry) && !isCallerPinnedStaticRemote(options, remote)) throw new BackendFederationManifestAdapterError('manifest_invalid', `[BFF][Effect] Backend federation network manifests cannot select local, global, or plugin entry ${remote.entry}. Pin a static/service binding in caller configuration or use a verified HTTP(S) entry.`);
96
+ if (remoteManifest && /^https?:\/\//iu.test(remote.entry) && !hasPinnedRemoteEntryExpectation(options)) throw new BackendFederationManifestAdapterError('manifest_invalid', `[BFF][Effect] Backend federation remote ${remote.name} from a network manifest requires caller-pinned entryUrl, remoteName, sha256, and byteLength values.`);
97
+ if (/^https?:\/\//iu.test(remote.entry) && void 0 === remote.verification && options.entryPolicy?.expected === void 0) throw new BackendFederationManifestAdapterError('manifest_invalid', `[BFF][Effect] Backend federation remote ${remote.name} requires entry.sha256 and entry.byteLength before network execution.`);
98
+ if (/^https?:\/\//iu.test(remote.entry) && void 0 !== options.runtime) throw new BackendFederationManifestAdapterError('manifest_invalid', `[BFF][Effect] Backend federation remote ${remote.name} cannot use a custom runtime for network entry execution.`);
99
+ const loaded = await loadBackendFederatedEffectApi({
100
+ hostName: options.hostName,
101
+ remote,
102
+ ...options.plugins ? {
103
+ plugins: options.plugins
104
+ } : {},
105
+ entryPolicy: {
106
+ ...options.entryPolicy,
107
+ signal: scope.signal,
108
+ timeoutMs: 0
109
+ },
110
+ ...options.runtime ? {
111
+ runtime: options.runtime
112
+ } : {},
113
+ ...options.expected?.unitId && options.expected.buildMarker ? {
114
+ expected: {
115
+ unitId: options.expected.unitId,
116
+ buildMarker: options.expected.buildMarker
117
+ },
118
+ allowMissingIdentityMetadata: true
119
+ } : {}
120
+ }).catch((error)=>{
121
+ throw new BackendFederationManifestAdapterError(scope?.timedOut() === true ? 'timeout' : classifyLoadError(error), `[BFF][Effect] Backend federation remote ${remote?.name ?? 'unknown'} could not load ${remote?.expose ?? BACKEND_FEDERATION_EFFECT_EXPOSE}.`, error);
122
+ });
123
+ validateLoadedBackendFederationContract(loaded, manifest, remote);
124
+ return loaded;
125
+ } catch (error) {
126
+ const adapterError = scope?.timedOut() === true ? new BackendFederationManifestAdapterError('timeout', `[BFF][Effect] Backend federation load timed out after ${scope.timeoutMs}ms.`, error) : error instanceof BackendFederationManifestAdapterError ? error : new BackendFederationManifestAdapterError('remote_unavailable', '[BFF][Effect] Backend federation manifest adapter failed.', error);
127
+ if (options.fallback) return options.fallback(adapterError, {
128
+ manifest,
129
+ remote
130
+ });
131
+ throw adapterError;
132
+ } finally{
133
+ scope?.cleanup();
134
+ }
135
+ }
136
+ export { loadBackendFederatedEffectApiFromManifest };
@@ -0,0 +1,43 @@
1
+ import "node:module";
2
+ import { backendFederationMetadata, backendFederationVersionBoundary } from "@modern-js/utils/universal";
3
+ function stringValue(value) {
4
+ return 'string' == typeof value && value.length > 0 ? value : void 0;
5
+ }
6
+ function isRecord(value) {
7
+ return 'object' == typeof value && null !== value;
8
+ }
9
+ function recordField(value, field) {
10
+ const fieldValue = value?.[field];
11
+ return isRecord(fieldValue) ? fieldValue : void 0;
12
+ }
13
+ function resolveRemoteEntryFromMetadata(manifest) {
14
+ const metaData = recordField(manifest, 'metaData');
15
+ const remoteEntry = recordField(metaData, 'remoteEntry');
16
+ const publicPath = stringValue(metaData?.publicPath) ?? stringValue(metaData?.ssrPublicPath);
17
+ const entryName = stringValue(remoteEntry?.name);
18
+ if (!publicPath || !entryName) return;
19
+ const entryPath = stringValue(remoteEntry?.path) ?? '';
20
+ const normalizedBase = publicPath.replace(/\/+$/u, '');
21
+ const normalizedPath = entryPath.replace(/^\/+|\/+$/gu, '');
22
+ return [
23
+ normalizedBase,
24
+ normalizedPath,
25
+ entryName
26
+ ].filter(Boolean).join('/');
27
+ }
28
+ function metadata_backendFederationMetadata(manifest) {
29
+ return backendFederationMetadata(manifest);
30
+ }
31
+ function versionBoundaryMetadata(manifest) {
32
+ return backendFederationVersionBoundary(manifest);
33
+ }
34
+ function deliveryUnitMetadata(record) {
35
+ return recordField(record, 'deliveryUnit');
36
+ }
37
+ function manifestDeliveryUnit(backendFederation, boundary) {
38
+ return {
39
+ boundary: deliveryUnitMetadata(boundary),
40
+ top: deliveryUnitMetadata(backendFederation)
41
+ };
42
+ }
43
+ export { deliveryUnitMetadata, isRecord, manifestDeliveryUnit, metadata_backendFederationMetadata as backendFederationMetadata, recordField, resolveRemoteEntryFromMetadata, stringValue, versionBoundaryMetadata };
@@ -0,0 +1,13 @@
1
+ import "node:module";
2
+ import { evaluateNodeBackendFederationCommonJs } from "@modern-js/server-runtime-extensions/backend-federation-security/node";
3
+ import { loadBackendFederatedEffectApiFromManifest } from "./load.mjs";
4
+ function node_loadBackendFederatedEffectApiFromManifest(options) {
5
+ return loadBackendFederatedEffectApiFromManifest({
6
+ ...options,
7
+ entryPolicy: {
8
+ ...options.entryPolicy,
9
+ evaluateCommonJs: options.entryPolicy?.evaluateCommonJs ?? evaluateNodeBackendFederationCommonJs
10
+ }
11
+ });
12
+ }
13
+ export { node_loadBackendFederatedEffectApiFromManifest as loadBackendFederatedEffectApiFromManifest };
@@ -0,0 +1,89 @@
1
+ import "node:module";
2
+ import { BackendFederationRemoteEntryError, loadBoundedBackendFederationResource, redactBackendFederationUrl } from "@modern-js/server-runtime-extensions/backend-federation-security";
3
+ import { BACKEND_FEDERATION_MANIFEST_FILE } from "../backend-federation/index.mjs";
4
+ import { BackendFederationManifestAdapterError, assertManifestAdapter } from "./errors.mjs";
5
+ import { isRecord } from "./metadata.mjs";
6
+ function getProcessEnv() {
7
+ return "u" > typeof process ? process.env : void 0;
8
+ }
9
+ function resolveManifestReferenceSource(options) {
10
+ if (options.manifestPath) return 'path';
11
+ if (options.manifestUrl) return 'url';
12
+ if (options.manifestEnv) return 'env';
13
+ }
14
+ function resolveBackendFederationManifestReference(options) {
15
+ if (options.manifestPath) return options.manifestPath;
16
+ if (options.manifestUrl) return options.manifestUrl;
17
+ if (!options.manifestEnv) return;
18
+ return options.env?.[options.manifestEnv] ?? getProcessEnv()?.[options.manifestEnv];
19
+ }
20
+ function assertExpectedIdentityForReference(options, source) {
21
+ if (void 0 === source || 'path' === source) return;
22
+ if (options.expected?.unitId && options.expected.buildMarker) return;
23
+ throw new BackendFederationManifestAdapterError('version_mismatch', `[BFF][Effect] Backend federation ${source} manifest references require expected.unitId and expected.buildMarker.`, void 0, {
24
+ label: 'expected.deliveryUnit',
25
+ expected: 'unitId + buildMarker',
26
+ received: options.expected,
27
+ referenceSource: source
28
+ });
29
+ }
30
+ function isHttpUrl(value) {
31
+ return /^https?:\/\//iu.test(value);
32
+ }
33
+ function referenceForDiagnostics(reference) {
34
+ return isHttpUrl(reference) ? redactBackendFederationUrl(reference) : '[local manifest]';
35
+ }
36
+ async function readFileReference(reference) {
37
+ const [{ fileURLToPath }, fs] = await Promise.all([
38
+ import("node:url"),
39
+ import("node:fs/promises")
40
+ ]);
41
+ const filePath = reference.startsWith('file:') ? fileURLToPath(reference) : reference;
42
+ return fs.readFile(filePath, 'utf8');
43
+ }
44
+ async function withTimeout(promise, timeoutMs, label) {
45
+ if (!timeoutMs || timeoutMs <= 0) return promise;
46
+ let timeout;
47
+ try {
48
+ return await Promise.race([
49
+ promise,
50
+ new Promise((_, reject)=>{
51
+ timeout = setTimeout(()=>{
52
+ reject(new BackendFederationManifestAdapterError('timeout', `[BFF][Effect] ${label} timed out after ${timeoutMs}ms.`));
53
+ }, timeoutMs);
54
+ })
55
+ ]);
56
+ } finally{
57
+ if (timeout) clearTimeout(timeout);
58
+ }
59
+ }
60
+ async function loadBackendFederationManifest(options) {
61
+ if (options.manifest) return options.manifest;
62
+ const reference = resolveBackendFederationManifestReference(options);
63
+ if (!reference) throw new BackendFederationManifestAdapterError('manifest_unavailable', `[BFF][Effect] Backend federation manifest reference is missing. Pass manifest, manifestPath, manifestUrl, or manifestEnv for ${BACKEND_FEDERATION_MANIFEST_FILE}.`);
64
+ assertExpectedIdentityForReference(options, resolveManifestReferenceSource(options));
65
+ const referenceSource = resolveManifestReferenceSource(options);
66
+ if ('path' === referenceSource && isHttpUrl(reference)) throw new BackendFederationManifestAdapterError('manifest_unavailable', '[BFF][Effect] Backend federation manifestPath must identify an explicit local file. Use manifestUrl for HTTP(S) manifests.');
67
+ if (('url' === referenceSource || 'env' === referenceSource) && !isHttpUrl(reference)) throw new BackendFederationManifestAdapterError('manifest_unavailable', `[BFF][Effect] Backend federation ${referenceSource} manifest references must use HTTP(S). Use manifestPath for an explicit local file.`);
68
+ try {
69
+ const diagnosticReference = referenceForDiagnostics(reference);
70
+ const source = isHttpUrl(reference) ? new TextDecoder('utf-8', {
71
+ fatal: true
72
+ }).decode(await loadBoundedBackendFederationResource(reference, {
73
+ allowInsecureHttp: options.manifestPolicy?.allowInsecureHttp === true,
74
+ fetch: options.fetch,
75
+ kind: 'manifest',
76
+ maxBytes: options.manifestPolicy?.maxBytes,
77
+ signal: options.manifestPolicy?.signal ?? options.signal,
78
+ timeoutMs: options.manifestPolicy?.timeoutMs ?? options.timeoutMs
79
+ })) : await withTimeout(readFileReference(reference), options.manifestPolicy?.timeoutMs ?? options.timeoutMs, 'Backend federation local manifest');
80
+ const manifest = JSON.parse(source);
81
+ assertManifestAdapter(isRecord(manifest), 'manifest_invalid', `[BFF][Effect] Backend federation manifest ${diagnosticReference} must be a JSON object.`);
82
+ return manifest;
83
+ } catch (error) {
84
+ if (error instanceof BackendFederationManifestAdapterError) throw error;
85
+ if (error instanceof BackendFederationRemoteEntryError) throw new BackendFederationManifestAdapterError('timeout' === error.code ? 'timeout' : 'manifest_unavailable', `[BFF][Effect] ${error.message}`, error, error.details);
86
+ throw new BackendFederationManifestAdapterError('manifest_unavailable', `[BFF][Effect] Backend federation manifest ${referenceForDiagnostics(reference)} could not be loaded.`, error);
87
+ }
88
+ }
89
+ export { loadBackendFederationManifest, resolveBackendFederationManifestReference, withTimeout };
@@ -0,0 +1,44 @@
1
+ import "node:module";
2
+ import { BackendFederationRemoteEntryError, resolveBackendFederationRemoteEntryVerification } from "@modern-js/server-runtime-extensions/backend-federation-security";
3
+ import { backendFederationExposeNames } from "@modern-js/utils/universal";
4
+ import { BACKEND_FEDERATION_EFFECT_EXPOSE } from "../backend-federation/index.mjs";
5
+ import { BackendFederationManifestAdapterError, assertManifestAdapter } from "./errors.mjs";
6
+ import { backendFederationMetadata, recordField, resolveRemoteEntryFromMetadata, stringValue } from "./metadata.mjs";
7
+ function resolveBackendFederationRemoteFromManifest(manifest, remoteOverride = {}) {
8
+ const backendFederation = backendFederationMetadata(manifest);
9
+ const entry = recordField(manifest, 'entry');
10
+ const metaData = recordField(manifest, 'metaData');
11
+ const remoteEntry = recordField(metaData, 'remoteEntry');
12
+ const remoteName = remoteOverride.name ?? stringValue(backendFederation?.name) ?? stringValue(manifest.name) ?? stringValue(manifest.id);
13
+ const manifestEntryUrl = stringValue(backendFederation?.containerEntry) ?? stringValue(entry?.url) ?? resolveRemoteEntryFromMetadata(manifest);
14
+ const remoteEntryUrl = remoteOverride.entry ?? manifestEntryUrl;
15
+ const remoteType = remoteOverride.type ?? stringValue(backendFederation?.remoteType) ?? stringValue(entry?.type) ?? stringValue(remoteEntry?.type) ?? 'module';
16
+ const expose = remoteOverride.expose ?? backendFederationExposeNames(backendFederation)[0] ?? BACKEND_FEDERATION_EFFECT_EXPOSE;
17
+ let verification;
18
+ try {
19
+ const manifestVerification = resolveBackendFederationRemoteEntryVerification(manifest);
20
+ verification = remoteOverride.verification ?? (remoteEntryUrl === manifestEntryUrl ? manifestVerification : void 0);
21
+ } catch (cause) {
22
+ if (cause instanceof BackendFederationRemoteEntryError) throw new BackendFederationManifestAdapterError('identity_mismatch' === cause.code ? 'version_mismatch' : 'manifest_invalid', `[BFF][Effect] ${cause.message}`, cause, cause.details);
23
+ throw cause;
24
+ }
25
+ assertManifestAdapter(remoteName, 'manifest_invalid', '[BFF][Effect] Backend federation manifest must declare a remote name.');
26
+ assertManifestAdapter(remoteEntryUrl, 'manifest_invalid', '[BFF][Effect] Backend federation manifest must declare a backend remote entry URL.');
27
+ assertManifestAdapter(expose === BACKEND_FEDERATION_EFFECT_EXPOSE, 'manifest_invalid', `[BFF][Effect] Backend federation manifest expose must be ${BACKEND_FEDERATION_EFFECT_EXPOSE}.`);
28
+ return {
29
+ name: remoteName,
30
+ entry: remoteEntryUrl,
31
+ type: remoteType,
32
+ ...verification ? {
33
+ verification
34
+ } : {},
35
+ ...remoteOverride.entryGlobalName ? {
36
+ entryGlobalName: remoteOverride.entryGlobalName
37
+ } : {},
38
+ expose,
39
+ ...remoteOverride.shareScope ? {
40
+ shareScope: remoteOverride.shareScope
41
+ } : {}
42
+ };
43
+ }
44
+ export { resolveBackendFederationRemoteFromManifest };
@@ -0,0 +1 @@
1
+ import "node:module";