@bleedingdev/modern-js-plugin-bff-extensions 3.9.0-ultramodern.11 → 3.9.0-ultramodern.13

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 (77) hide show
  1. package/README.md +3 -3
  2. package/dist/cjs/backend-federation/identity.js +23 -22
  3. package/dist/cjs/backend-federation/node-evaluator.js +48 -0
  4. package/dist/cjs/backend-federation/node.js +2 -2
  5. package/dist/cjs/backend-federation-manifest/node.js +2 -2
  6. package/dist/cjs/backend-federation-manifest/validation.js +11 -7
  7. package/dist/cjs/cross-project-policy/node.js +8 -28
  8. package/dist/cjs/{effect-adapter → effect-server}/cross-project-policy.js +5 -5
  9. package/dist/cjs/effect-server/entry.js +63 -0
  10. package/dist/cjs/{effect-adapter → effect-server}/error-response.js +4 -4
  11. package/dist/cjs/effect-server/index.js +199 -0
  12. package/dist/cjs/effect-source-loader/built-entry.js +4 -5
  13. package/dist/cjs/effect-source-loader/loader.js +2 -1
  14. package/dist/cjs/effect-source-loader/operation-contracts.js +8 -31
  15. package/dist/cjs/effect-source-loader/paths.js +38 -10
  16. package/dist/esm/backend-federation/identity.mjs +18 -23
  17. package/dist/esm/backend-federation/node-evaluator.mjs +7 -0
  18. package/dist/esm/backend-federation/node.mjs +2 -2
  19. package/dist/esm/backend-federation-manifest/node.mjs +2 -2
  20. package/dist/esm/backend-federation-manifest/validation.mjs +12 -8
  21. package/dist/esm/cross-project-policy/node.mjs +9 -19
  22. package/dist/esm/{effect-adapter → effect-server}/cross-project-policy.mjs +3 -3
  23. package/dist/esm/effect-server/entry.mjs +15 -0
  24. package/dist/esm/{effect-adapter → effect-server}/error-response.mjs +2 -2
  25. package/dist/esm/effect-server/index.mjs +151 -0
  26. package/dist/esm/effect-source-loader/built-entry.mjs +5 -6
  27. package/dist/esm/effect-source-loader/loader.mjs +2 -1
  28. package/dist/esm/effect-source-loader/operation-contracts.mjs +10 -33
  29. package/dist/esm/effect-source-loader/paths.mjs +30 -11
  30. package/dist/esm-node/backend-federation/identity.mjs +18 -23
  31. package/dist/esm-node/backend-federation/node-evaluator.mjs +8 -0
  32. package/dist/esm-node/backend-federation/node.mjs +2 -2
  33. package/dist/esm-node/backend-federation-manifest/node.mjs +2 -2
  34. package/dist/esm-node/backend-federation-manifest/validation.mjs +12 -8
  35. package/dist/esm-node/cross-project-policy/node.mjs +9 -19
  36. package/dist/esm-node/{effect-adapter → effect-server}/cross-project-policy.mjs +3 -3
  37. package/dist/esm-node/effect-server/entry.mjs +16 -0
  38. package/dist/esm-node/{effect-adapter → effect-server}/error-response.mjs +2 -2
  39. package/dist/esm-node/effect-server/index.mjs +152 -0
  40. package/dist/esm-node/effect-source-loader/built-entry.mjs +5 -6
  41. package/dist/esm-node/effect-source-loader/loader.mjs +2 -1
  42. package/dist/esm-node/effect-source-loader/operation-contracts.mjs +10 -33
  43. package/dist/esm-node/effect-source-loader/paths.mjs +30 -11
  44. package/dist/types/backend-federation/identity.d.ts +3 -6
  45. package/dist/types/backend-federation/node-evaluator.d.ts +2 -0
  46. package/dist/types/cross-project-policy/node.d.ts +2 -2
  47. package/dist/types/effect-server/cross-project-policy.d.ts +5 -0
  48. package/dist/types/{effect-adapter → effect-server}/entry.d.ts +1 -1
  49. package/dist/types/effect-server/error-response.d.ts +2 -0
  50. package/dist/types/effect-server/index.d.ts +4 -0
  51. package/dist/types/effect-source-loader/paths.d.ts +20 -2
  52. package/package.json +27 -27
  53. package/src/backend-federation/identity.ts +39 -47
  54. package/src/backend-federation/node-evaluator.ts +13 -0
  55. package/src/backend-federation/node.ts +2 -3
  56. package/src/backend-federation-manifest/node.ts +2 -3
  57. package/src/backend-federation-manifest/validation.ts +22 -29
  58. package/src/cross-project-policy/node.ts +7 -38
  59. package/src/{effect-adapter → effect-server}/cross-project-policy.ts +8 -2
  60. package/src/effect-server/entry.ts +18 -0
  61. package/src/{effect-adapter → effect-server}/error-response.ts +1 -1
  62. package/src/effect-server/index.ts +242 -0
  63. package/src/effect-source-loader/built-entry.ts +11 -9
  64. package/src/effect-source-loader/loader.ts +10 -5
  65. package/src/effect-source-loader/operation-contracts.ts +7 -41
  66. package/src/effect-source-loader/paths.ts +55 -21
  67. package/dist/cjs/effect-adapter/entry.js +0 -99
  68. package/dist/cjs/effect-adapter/index.js +0 -194
  69. package/dist/esm/effect-adapter/entry.mjs +0 -51
  70. package/dist/esm/effect-adapter/index.mjs +0 -143
  71. package/dist/esm-node/effect-adapter/entry.mjs +0 -52
  72. package/dist/esm-node/effect-adapter/index.mjs +0 -144
  73. package/dist/types/effect-adapter/cross-project-policy.d.ts +0 -4
  74. package/dist/types/effect-adapter/error-response.d.ts +0 -2
  75. package/dist/types/effect-adapter/index.d.ts +0 -21
  76. package/src/effect-adapter/entry.ts +0 -96
  77. package/src/effect-adapter/index.ts +0 -251
package/package.json CHANGED
@@ -18,7 +18,7 @@
18
18
  "modern.js",
19
19
  "ultramodern.js"
20
20
  ],
21
- "version": "3.9.0-ultramodern.11",
21
+ "version": "3.9.0-ultramodern.13",
22
22
  "files": [
23
23
  "dist",
24
24
  "src"
@@ -50,13 +50,13 @@
50
50
  },
51
51
  "default": "./dist/cjs/cross-project-generation/index.js"
52
52
  },
53
- "./effect-adapter": {
54
- "types": "./dist/types/effect-adapter/index.d.ts",
53
+ "./effect-server": {
54
+ "types": "./dist/types/effect-server/index.d.ts",
55
55
  "node": {
56
- "import": "./dist/esm-node/effect-adapter/index.mjs",
57
- "require": "./dist/cjs/effect-adapter/index.js"
56
+ "import": "./dist/esm-node/effect-server/index.mjs",
57
+ "require": "./dist/cjs/effect-server/index.js"
58
58
  },
59
- "default": "./dist/cjs/effect-adapter/index.js"
59
+ "default": "./dist/cjs/effect-server/index.js"
60
60
  },
61
61
  "./effect-source-loader": {
62
62
  "types": "./dist/types/effect-source-loader/index.d.ts",
@@ -147,9 +147,9 @@
147
147
  "./dist/types/cross-project-generation/index.d.ts",
148
148
  "./src/cross-project-generation/index.ts"
149
149
  ],
150
- "effect-adapter": [
151
- "./dist/types/effect-adapter/index.d.ts",
152
- "./src/effect-adapter/index.ts"
150
+ "effect-server": [
151
+ "./dist/types/effect-server/index.d.ts",
152
+ "./src/effect-server/index.ts"
153
153
  ],
154
154
  "effect-source-loader": [
155
155
  "./dist/types/effect-source-loader/index.d.ts",
@@ -193,21 +193,21 @@
193
193
  "node": ">=26.7.0"
194
194
  },
195
195
  "dependencies": {
196
- "@modern-js/backend-federation-contracts": "npm:@bleedingdev/modern-js-backend-federation-contracts@3.9.0-ultramodern.11",
197
- "@modern-js/bff-core": "npm:@bleedingdev/modern-js-bff-core@3.9.0-ultramodern.11",
198
- "@modern-js/bff-effect": "npm:@bleedingdev/modern-js-bff-effect@3.9.0-ultramodern.11",
199
- "@modern-js/runtime-extensions": "npm:@bleedingdev/modern-js-runtime-extensions@3.9.0-ultramodern.11",
200
- "@modern-js/server-core": "npm:@bleedingdev/modern-js-server-core@3.9.0-ultramodern.11",
201
- "@modern-js/server-runtime-extensions": "npm:@bleedingdev/modern-js-server-runtime-extensions@3.9.0-ultramodern.11",
202
- "@modern-js/types": "npm:@bleedingdev/modern-js-types@3.9.0-ultramodern.11",
203
- "@modern-js/utils": "npm:@bleedingdev/modern-js-utils@3.9.0-ultramodern.11",
204
- "@module-federation/runtime": "2.9.0",
196
+ "@modern-js/backend-federation-contracts": "npm:@bleedingdev/modern-js-backend-federation-contracts@3.9.0-ultramodern.13",
197
+ "@modern-js/bff-core": "npm:@bleedingdev/modern-js-bff-core@3.9.0-ultramodern.13",
198
+ "@modern-js/bff-effect": "npm:@bleedingdev/modern-js-bff-effect@3.9.0-ultramodern.13",
199
+ "@modern-js/runtime-extensions": "npm:@bleedingdev/modern-js-runtime-extensions@3.9.0-ultramodern.13",
200
+ "@modern-js/server-core": "npm:@bleedingdev/modern-js-server-core@3.9.0-ultramodern.13",
201
+ "@modern-js/server-runtime-extensions": "npm:@bleedingdev/modern-js-server-runtime-extensions@3.9.0-ultramodern.13",
202
+ "@modern-js/types": "npm:@bleedingdev/modern-js-types@3.9.0-ultramodern.13",
203
+ "@modern-js/utils": "npm:@bleedingdev/modern-js-utils@3.9.0-ultramodern.13",
204
+ "@module-federation/runtime": "npm:@bleedingdev/mf-runtime@2.9.1",
205
205
  "@swc/core": "1.16.2",
206
206
  "esbuild": "^0.28.2"
207
207
  },
208
208
  "peerDependencies": {
209
- "@effect/opentelemetry": "4.0.0-rc.112",
210
- "effect": "4.0.0-rc.112"
209
+ "@effect/opentelemetry": "4.0.0-rc.117",
210
+ "effect": "4.0.0-rc.117"
211
211
  },
212
212
  "peerDependenciesMeta": {
213
213
  "@effect/opentelemetry": {
@@ -218,15 +218,15 @@
218
218
  }
219
219
  },
220
220
  "devDependencies": {
221
- "@effect/opentelemetry": "4.0.0-rc.112",
222
- "@modern-js/plugin": "npm:@bleedingdev/modern-js-plugin@3.9.0-ultramodern.11",
223
- "@rsbuild/core": "2.2.3",
224
- "@rslib/core": "1.0.0",
221
+ "@effect/opentelemetry": "4.0.0-rc.117",
222
+ "@modern-js/plugin": "npm:@bleedingdev/modern-js-plugin@3.9.0-ultramodern.13",
223
+ "@rsbuild/core": "2.2.9",
224
+ "@rslib/core": "1.0.2",
225
225
  "@scripts/rstest-config": "2.66.0",
226
- "@types/node": "^26.4.1",
227
- "@types/react": "^19.2.18",
226
+ "@types/node": "^26.6.2",
227
+ "@types/react": "^19.3.0",
228
228
  "@typescript/native-preview": "7.0.0-dev.20260707.2",
229
- "effect": "4.0.0-rc.112"
229
+ "effect": "npm:@bleedingdev/effect@4.0.0-rc.117"
230
230
  },
231
231
  "sideEffects": false,
232
232
  "publishConfig": {
@@ -17,59 +17,51 @@ export type BackendFederationIdentityIssue = {
17
17
  message: string;
18
18
  };
19
19
 
20
- /**
21
- * Shared expected-identity validation for loaded backend federation modules.
22
- * Compares the expose's `backendFederationContract.compatibility` identity
23
- * (`unitId`, `build`) against the consumer's expected delivery-unit identity.
24
- * Missing identity metadata is an error.
25
- */
26
- export function validateExpectedBackendFederationIdentity(
27
- loaded: unknown,
28
- expected: BackendFederationExpectedIdentity,
29
- ): BackendFederationIdentityIssue[] {
30
- const issues: BackendFederationIdentityIssue[] = [];
20
+ /** Decode independently at each received-manifest / executed-expose boundary. */
21
+ export function backendFederationCompatibility(loaded: unknown) {
31
22
  const contract = isRecord(loaded)
32
23
  ? loaded.backendFederationContract
33
24
  : undefined;
34
25
  const compatibility = isRecord(contract) ? contract.compatibility : undefined;
26
+ return isRecord(compatibility) ? compatibility : undefined;
27
+ }
35
28
 
36
- if (!isRecord(compatibility)) {
37
- return [
38
- {
39
- path: 'backendFederationContract.compatibility',
40
- message:
41
- 'loaded module declares no compatibility metadata; delivery-unit identity cannot be validated',
42
- },
43
- ];
44
- }
45
-
46
- const unitId = compatibility.unitId;
47
- if (typeof unitId !== 'string' || unitId.length === 0) {
48
- issues.push({
49
- path: 'backendFederationContract.compatibility.unitId',
50
- message: `missing delivery-unit id; expected ${expected.unitId}`,
51
- });
52
- } else if (unitId !== expected.unitId) {
53
- issues.push({
54
- path: 'backendFederationContract.compatibility.unitId',
55
- message: `expected ${expected.unitId}, received ${unitId}`,
56
- });
57
- }
58
-
59
- const build = compatibility.build;
60
- if (typeof build !== 'string' || build.length === 0) {
61
- issues.push({
62
- path: 'backendFederationContract.compatibility.build',
63
- message: `missing build marker; expected ${expected.buildMarker}`,
64
- });
65
- } else if (build !== expected.buildMarker) {
66
- issues.push({
67
- path: 'backendFederationContract.compatibility.build',
68
- message: `expected ${expected.buildMarker}, received ${build}`,
69
- });
70
- }
29
+ export function validateBackendFederationCompatibility(
30
+ compatibility: Record<string, unknown>,
31
+ expected: Record<string, string | undefined>,
32
+ ): BackendFederationIdentityIssue[] {
33
+ return Object.entries(expected).flatMap(([field, value]) =>
34
+ value === undefined ||
35
+ (typeof compatibility[field] === 'string' &&
36
+ compatibility[field].length > 0 &&
37
+ compatibility[field] === value)
38
+ ? []
39
+ : [
40
+ {
41
+ path: `backendFederationContract.compatibility.${field}`,
42
+ message: `expected ${value}, received ${typeof compatibility[field] === 'string' ? compatibility[field] : typeof compatibility[field]}`,
43
+ },
44
+ ],
45
+ );
46
+ }
71
47
 
72
- return issues;
48
+ export function validateExpectedBackendFederationIdentity(
49
+ loaded: unknown,
50
+ expected: BackendFederationExpectedIdentity,
51
+ ): BackendFederationIdentityIssue[] {
52
+ const compatibility = backendFederationCompatibility(loaded);
53
+ return compatibility
54
+ ? validateBackendFederationCompatibility(compatibility, {
55
+ unitId: expected.unitId,
56
+ build: expected.buildMarker,
57
+ })
58
+ : [
59
+ {
60
+ path: 'backendFederationContract.compatibility',
61
+ message:
62
+ 'loaded module declares no compatibility metadata; delivery-unit identity cannot be validated',
63
+ },
64
+ ];
73
65
  }
74
66
 
75
67
  export function formatBackendFederationIdentityIssues(
@@ -0,0 +1,13 @@
1
+ import { createRequire } from 'node:module';
2
+ import { evaluateNodeBackendFederationCommonJs } from '@modern-js/server-runtime-extensions/backend-federation-security/node';
3
+
4
+ const fromAdapter = createRequire(import.meta.url);
5
+ const fromEffectPackage = createRequire(
6
+ fromAdapter.resolve('@modern-js/bff-effect/package.json'),
7
+ );
8
+ const privateRegistry = fromEffectPackage(`#effect-entry-shape-${'registry'}`);
9
+
10
+ export const evaluateEffectBackendFederationCommonJs = (
11
+ source: Parameters<typeof evaluateNodeBackendFederationCommonJs>[0],
12
+ context: Parameters<typeof evaluateNodeBackendFederationCommonJs>[1],
13
+ ) => evaluateNodeBackendFederationCommonJs(source, context, privateRegistry);
@@ -1,6 +1,5 @@
1
- import { evaluateNodeBackendFederationCommonJs } from '@modern-js/server-runtime-extensions/backend-federation-security/node';
2
-
3
1
  import { loadBackendFederatedEffectApi as loadUniversalBackendFederatedEffectApi } from './load';
2
+ import { evaluateEffectBackendFederationCommonJs } from './node-evaluator';
4
3
  import type {
5
4
  BackendFederatedEffectApiModule,
6
5
  BackendFederationIdentityLoadOptions,
@@ -16,7 +15,7 @@ export function loadBackendFederatedEffectApi(
16
15
  ...options.entryPolicy,
17
16
  evaluateCommonJs:
18
17
  options.entryPolicy?.evaluateCommonJs ??
19
- evaluateNodeBackendFederationCommonJs,
18
+ evaluateEffectBackendFederationCommonJs,
20
19
  },
21
20
  });
22
21
  }
@@ -1,6 +1,5 @@
1
- import { evaluateNodeBackendFederationCommonJs } from '@modern-js/server-runtime-extensions/backend-federation-security/node';
2
-
3
1
  import type { BackendFederatedEffectApiModule } from '../backend-federation';
2
+ import { evaluateEffectBackendFederationCommonJs } from '../backend-federation/node-evaluator';
4
3
  import { loadBackendFederatedEffectApiFromManifest as loadUniversalBackendFederatedEffectApiFromManifest } from './load';
5
4
  import type { BackendFederationManifestAdapterOptions } from './types';
6
5
 
@@ -13,7 +12,7 @@ export function loadBackendFederatedEffectApiFromManifest(
13
12
  ...options.entryPolicy,
14
13
  evaluateCommonJs:
15
14
  options.entryPolicy?.evaluateCommonJs ??
16
- evaluateNodeBackendFederationCommonJs,
15
+ evaluateEffectBackendFederationCommonJs,
17
16
  },
18
17
  });
19
18
  }
@@ -10,6 +10,11 @@ import {
10
10
  type BackendFederatedEffectApiModule,
11
11
  type BackendFederationRemote,
12
12
  } from '../backend-federation';
13
+ import {
14
+ backendFederationCompatibility,
15
+ formatBackendFederationIdentityIssues,
16
+ validateBackendFederationCompatibility,
17
+ } from '../backend-federation/identity';
13
18
  import {
14
19
  assertConsistentValue,
15
20
  assertManifestAdapter,
@@ -19,7 +24,6 @@ import {
19
24
  import {
20
25
  backendFederationMetadata,
21
26
  manifestDeliveryUnit,
22
- recordField,
23
27
  stringValue,
24
28
  versionBoundaryMetadata,
25
29
  } from './metadata';
@@ -166,7 +170,7 @@ export function validateLoadedBackendFederationContract(
166
170
  const loadedContract = loaded.backendFederationContract;
167
171
  const backendFederation = backendFederationMetadata(manifest);
168
172
  const boundary = versionBoundaryMetadata(manifest);
169
- const compatibility = recordField(loadedContract, 'compatibility');
173
+ const compatibility = backendFederationCompatibility(loaded);
170
174
 
171
175
  assertManifestAdapter(
172
176
  compatibility,
@@ -186,26 +190,6 @@ export function validateLoadedBackendFederationContract(
186
190
  remote.name,
187
191
  'expose name',
188
192
  );
189
- assertVersionValue(
190
- stringValue(compatibility.contractVersion),
191
- stringValue(backendFederation?.contractVersion),
192
- 'expose contractVersion',
193
- );
194
- assertVersionValue(
195
- stringValue(compatibility.nodeAdapterVersion),
196
- stringValue(backendFederation?.nodeAdapterVersion),
197
- 'expose nodeAdapterVersion',
198
- );
199
- assertVersionValue(
200
- stringValue(compatibility.packageName),
201
- stringValue(boundary?.packageName),
202
- 'expose packageName',
203
- );
204
- assertVersionValue(
205
- stringValue(compatibility.build),
206
- stringValue(boundary?.buildVersion),
207
- 'expose buildVersion',
208
- );
209
193
 
210
194
  const deliveryUnit = manifestDeliveryUnit(backendFederation, boundary);
211
195
  const manifestUnitId =
@@ -213,15 +197,24 @@ export function validateLoadedBackendFederationContract(
213
197
  stringValue(deliveryUnit.top?.unitId);
214
198
  const manifestBuildMarker = stringValue(deliveryUnit.boundary?.buildMarker);
215
199
 
216
- assertVersionValue(
217
- stringValue(compatibility.unitId),
218
- manifestUnitId,
219
- 'deliveryUnit.unitId vs expose compatibility.unitId',
220
- );
200
+ const issues = validateBackendFederationCompatibility(compatibility, {
201
+ contractVersion: stringValue(backendFederation?.contractVersion),
202
+ nodeAdapterVersion: stringValue(backendFederation?.nodeAdapterVersion),
203
+ packageName: stringValue(boundary?.packageName),
204
+ unitId: manifestUnitId,
205
+ build: manifestBuildMarker ?? stringValue(boundary?.buildVersion),
206
+ });
207
+ // Manifest validation establishes buildVersion/buildMarker consistency; the
208
+ // executed expose is still checked independently against that trusted record.
221
209
  assertVersionValue(
222
210
  stringValue(compatibility.build),
223
- manifestBuildMarker,
224
- 'deliveryUnit.buildMarker vs expose compatibility.build',
211
+ stringValue(boundary?.buildVersion),
212
+ 'expose buildVersion',
213
+ );
214
+ assertManifestAdapter(
215
+ issues.length === 0,
216
+ 'version_mismatch',
217
+ `[BFF][Effect] ${formatBackendFederationIdentityIssues(issues)}.`,
225
218
  );
226
219
  }
227
220
 
@@ -1,48 +1,17 @@
1
- import { readFileSync } from 'node:fs';
2
- import path from 'node:path';
3
1
  import '@modern-js/server-runtime-extensions/server-config';
4
2
  import type { ServerPluginAPI } from '@modern-js/server-core';
5
3
  import {
6
- deriveOperationVersion,
7
4
  type OperationContractSource,
8
5
  resolveCrossProjectPolicy,
6
+ resolveOperationProducer,
9
7
  } from '@modern-js/server-runtime-extensions/bff-policy/node';
10
8
 
11
9
  import type { ResolvedCrossProjectPolicy } from './evaluation';
12
10
 
13
- const readNearestPackageVersion = (
14
- startDir: string | undefined,
15
- ): string | undefined => {
16
- if (!startDir) {
17
- return undefined;
18
- }
19
-
20
- let current = path.resolve(startDir);
21
- for (let depth = 0; depth < 10; depth += 1) {
22
- try {
23
- const packageJson = JSON.parse(
24
- readFileSync(path.join(current, 'package.json'), 'utf8'),
25
- ) as { version?: unknown };
26
- if (typeof packageJson.version === 'string') {
27
- return packageJson.version;
28
- }
29
- } catch {
30
- // The producer package may be nested below its package.json.
31
- }
32
-
33
- const parent = path.dirname(current);
34
- if (parent === current) {
35
- return undefined;
36
- }
37
- current = parent;
38
- }
39
-
40
- return undefined;
41
- };
42
-
43
11
  export const resolveAdapterCrossProjectPolicy = (
44
12
  api: ServerPluginAPI,
45
13
  handlers: OperationContractSource[],
14
+ producer?: ReturnType<typeof resolveOperationProducer>,
46
15
  ): ResolvedCrossProjectPolicy | undefined => {
47
16
  const bff = api.getServerConfig()?.bff;
48
17
  const { apiDirectory, appDirectory } = api.getServerContext() as {
@@ -53,11 +22,11 @@ export const resolveAdapterCrossProjectPolicy = (
53
22
  return resolveCrossProjectPolicy({
54
23
  crossProjectPolicy: bff?.crossProjectPolicy,
55
24
  handlers,
56
- requestId: bff?.requestId,
57
25
  isCrossProjectServer: bff?.isCrossProjectServer,
58
- operationVersion: deriveOperationVersion(
59
- readNearestPackageVersion(apiDirectory) ??
60
- readNearestPackageVersion(appDirectory),
61
- ),
26
+ ...(producer ??
27
+ resolveOperationProducer({
28
+ directories: [apiDirectory, appDirectory],
29
+ requestId: bff?.requestId || 'default',
30
+ })),
62
31
  });
63
32
  };
@@ -6,16 +6,18 @@ import {
6
6
  toOperationContractSources,
7
7
  } from '@modern-js/bff-effect/effect';
8
8
  import type { ServerPluginAPI } from '@modern-js/server-core';
9
+ import type { resolveOperationProducer } from '@modern-js/server-runtime-extensions/bff-policy/node';
9
10
  import { logger } from '@modern-js/utils';
10
11
  import { HttpApi } from 'effect/unstable/httpapi';
11
12
 
12
13
  import { resolveAdapterCrossProjectPolicy } from '../cross-project-policy';
13
14
  import type { ResolvedCrossProjectPolicy } from '../cross-project-policy/evaluation';
14
15
 
15
- export function resolveEffectAdapterCrossProjectPolicy(
16
+ export function resolveEffectServerCrossProjectPolicy(
16
17
  api: ServerPluginAPI,
17
18
  prefix: string,
18
19
  mod: EffectApiModule | null,
20
+ producer?: ReturnType<typeof resolveOperationProducer>,
19
21
  ): Promise<ResolvedCrossProjectPolicy | undefined> {
20
22
  const contractSourcesPromise =
21
23
  mod === null
@@ -52,7 +54,11 @@ export function resolveEffectAdapterCrossProjectPolicy(
52
54
  });
53
55
 
54
56
  return contractSourcesPromise.then(contractSources => {
55
- const policy = resolveAdapterCrossProjectPolicy(api, contractSources);
57
+ const policy = resolveAdapterCrossProjectPolicy(
58
+ api,
59
+ contractSources,
60
+ producer,
61
+ );
56
62
  if (policy?.enabled === true && contractSources.length === 0) {
57
63
  logger.warn(
58
64
  '[BFF][Effect] Cross-project policy enabled but no HttpApi endpoints could be reflected; requests fail operation-contract matching unless allowUnknownOperations is enabled.',
@@ -0,0 +1,18 @@
1
+ // @effect-diagnostics nodeBuiltinImport:off strictBooleanExpressions:off
2
+ import path from 'node:path';
3
+ import '@modern-js/server-runtime-extensions/server-config';
4
+ import type { ServerPluginAPI } from '@modern-js/server-core';
5
+ import { API_DIR, isProd } from '@modern-js/utils';
6
+ import { resolveEffectEntry } from '../effect-source-loader/paths';
7
+
8
+ export function resolveEffectServerEntryFile(api: ServerPluginAPI) {
9
+ const { appDirectory, apiDirectory, distDirectory } = api.getServerContext();
10
+ const appDir = path.resolve(appDirectory || process.cwd());
11
+ return resolveEffectEntry({
12
+ appDir,
13
+ apiDir: path.resolve(appDir, apiDirectory || API_DIR),
14
+ effectEntry: api.getServerConfig()?.bff?.effect?.entry,
15
+ distDir:
16
+ isProd() && distDirectory ? path.resolve(distDirectory) : undefined,
17
+ }).path;
18
+ }
@@ -2,7 +2,7 @@ import { createSafeFailureResponse } from '@modern-js/runtime-extensions/safe-fa
2
2
  import type { Context, ServerPluginAPI } from '@modern-js/server-core';
3
3
  import { logger } from '@modern-js/utils';
4
4
 
5
- export function createEffectAdapterRuntimeErrorResponse(
5
+ export function createEffectServerRuntimeErrorResponse(
6
6
  api: ServerPluginAPI,
7
7
  error: unknown,
8
8
  context: Context,