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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -21,6 +21,13 @@ upstream Modern.js project.
21
21
  - `/backend-federation-manifest` exposes manifest contracts and resolution,
22
22
  while
23
23
  `/backend-federation-manifest/node` enables its hardened Node evaluator.
24
+ `loadBackendFederatedEffectApiFromManifest` enforces one shared
25
+ manifest-plus-entry load deadline (default 10s, override via `timeoutMs`,
26
+ 0 to opt out) instead of resetting a fresh timeout per network hop. The
27
+ load settles on that shared deadline/abort even when a caller-pinned
28
+ `loadEntry` plugin, its `init`/`get`, or a custom runtime's `loadRemote`
29
+ never settles; it cannot stop that uncooperative work from still running,
30
+ only stop waiting on it.
24
31
 
25
32
  Effect and its OpenTelemetry integration are exact-cohort optional peers. A
26
33
  Hono-only consumer can import `/hono` without installing Effect.
@@ -37,6 +37,7 @@ const external_metadata_js_namespaceObject = require("./metadata.js");
37
37
  const external_reference_js_namespaceObject = require("./reference.js");
38
38
  const external_remote_js_namespaceObject = require("./remote.js");
39
39
  const external_validation_js_namespaceObject = require("./validation.js");
40
+ const DEFAULT_SHARED_MANIFEST_LOAD_TIMEOUT_MS = 10000;
40
41
  function createManifestLoadScope(options) {
41
42
  const controller = new AbortController();
42
43
  const policyTimeouts = [
@@ -48,7 +49,8 @@ function createManifestLoadScope(options) {
48
49
  ...policyTimeouts
49
50
  ].filter((timeout)=>void 0 !== timeout);
50
51
  for (const timeout of configuredTimeouts)if (!Number.isSafeInteger(timeout) || timeout < 0) throw new external_errors_js_namespaceObject.BackendFederationManifestAdapterError('manifest_invalid', '[BFF][Effect] Backend federation timeoutMs must be a non-negative safe integer.');
51
- const timeoutMs = options.timeoutMs ?? (policyTimeouts.length > 0 ? Math.min(...policyTimeouts) : 0);
52
+ const positivePolicyTimeouts = policyTimeouts.filter((timeout)=>timeout > 0);
53
+ const timeoutMs = options.timeoutMs ?? (0 === policyTimeouts.length ? DEFAULT_SHARED_MANIFEST_LOAD_TIMEOUT_MS : positivePolicyTimeouts.length > 0 ? Math.min(...positivePolicyTimeouts) : 0);
52
54
  const inputSignals = [
53
55
  options.signal,
54
56
  options.manifestPolicy?.signal,
@@ -102,6 +104,27 @@ function isCallerPinnedStaticRemote(options, remote) {
102
104
  function throwIfManifestLoadAborted(signal) {
103
105
  if (signal.aborted) throw new external_errors_js_namespaceObject.BackendFederationManifestAdapterError('remote_unavailable', '[BFF][Effect] Backend federation load was aborted before remote execution.', signal.reason);
104
106
  }
107
+ function settleOnSharedAbort(promise, signal) {
108
+ if (signal.aborted) {
109
+ promise.catch(()=>{});
110
+ throwIfManifestLoadAborted(signal);
111
+ }
112
+ let onAbort;
113
+ const aborted = new Promise((_resolve, reject)=>{
114
+ onAbort = ()=>{
115
+ reject(new external_errors_js_namespaceObject.BackendFederationManifestAdapterError('remote_unavailable', '[BFF][Effect] Backend federation load was aborted before remote execution.', signal.reason));
116
+ };
117
+ signal.addEventListener('abort', onAbort, {
118
+ once: true
119
+ });
120
+ });
121
+ return Promise.race([
122
+ promise,
123
+ aborted
124
+ ]).finally(()=>{
125
+ if (onAbort) signal.removeEventListener('abort', onAbort);
126
+ });
127
+ }
105
128
  async function loadBackendFederatedEffectApiFromManifest(options) {
106
129
  let manifest;
107
130
  let remote;
@@ -109,7 +132,7 @@ async function loadBackendFederatedEffectApiFromManifest(options) {
109
132
  try {
110
133
  scope = createManifestLoadScope(options);
111
134
  throwIfManifestLoadAborted(scope.signal);
112
- manifest = await (0, external_reference_js_namespaceObject.loadBackendFederationManifest)({
135
+ manifest = await settleOnSharedAbort((0, external_reference_js_namespaceObject.loadBackendFederationManifest)({
113
136
  ...options,
114
137
  manifestPolicy: {
115
138
  ...options.manifestPolicy,
@@ -118,7 +141,7 @@ async function loadBackendFederatedEffectApiFromManifest(options) {
118
141
  },
119
142
  signal: scope.signal,
120
143
  timeoutMs: 0
121
- });
144
+ }), scope.signal);
122
145
  (0, external_validation_js_namespaceObject.validateBackendFederationManifest)(manifest, options.expected);
123
146
  remote = (0, external_remote_js_namespaceObject.resolveBackendFederationRemoteFromManifest)(manifest, options.remote);
124
147
  throwIfManifestLoadAborted(scope.signal);
@@ -132,7 +155,7 @@ async function loadBackendFederatedEffectApiFromManifest(options) {
132
155
  const unitId = (0, external_metadata_js_namespaceObject.stringValue)(deliveryUnit.boundary?.unitId) ?? (0, external_metadata_js_namespaceObject.stringValue)(deliveryUnit.top?.unitId);
133
156
  const buildMarker = (0, external_metadata_js_namespaceObject.stringValue)(deliveryUnit.boundary?.buildMarker);
134
157
  if (!unitId || !buildMarker) throw new external_errors_js_namespaceObject.BackendFederationManifestAdapterError('manifest_invalid', 'Backend federation manifest requires delivery-unit identity.');
135
- const loaded = await (0, load_js_namespaceObject.loadBackendFederatedEffectApi)({
158
+ const loaded = await settleOnSharedAbort((0, load_js_namespaceObject.loadBackendFederatedEffectApi)({
136
159
  hostName: options.hostName,
137
160
  remote,
138
161
  ...options.plugins ? {
@@ -152,7 +175,7 @@ async function loadBackendFederatedEffectApiFromManifest(options) {
152
175
  }
153
176
  }).catch((error)=>{
154
177
  throw new external_errors_js_namespaceObject.BackendFederationManifestAdapterError(scope?.timedOut() === true ? 'timeout' : (0, external_validation_js_namespaceObject.classifyLoadError)(error), `[BFF][Effect] Backend federation remote ${remote?.name ?? 'unknown'} could not load ${remote?.expose ?? index_js_namespaceObject.BACKEND_FEDERATION_EFFECT_EXPOSE}.`, error);
155
- });
178
+ }), scope.signal);
156
179
  (0, external_validation_js_namespaceObject.validateLoadedBackendFederationContract)(loaded, manifest, remote);
157
180
  return loaded;
158
181
  } catch (error) {
@@ -5,6 +5,7 @@ import { backendFederationMetadata, manifestDeliveryUnit, stringValue, versionBo
5
5
  import { loadBackendFederationManifest } from "./reference.mjs";
6
6
  import { resolveBackendFederationRemoteFromManifest } from "./remote.mjs";
7
7
  import { classifyLoadError, validateBackendFederationManifest, validateLoadedBackendFederationContract } from "./validation.mjs";
8
+ const DEFAULT_SHARED_MANIFEST_LOAD_TIMEOUT_MS = 10000;
8
9
  function createManifestLoadScope(options) {
9
10
  const controller = new AbortController();
10
11
  const policyTimeouts = [
@@ -16,7 +17,8 @@ function createManifestLoadScope(options) {
16
17
  ...policyTimeouts
17
18
  ].filter((timeout)=>void 0 !== timeout);
18
19
  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 positivePolicyTimeouts = policyTimeouts.filter((timeout)=>timeout > 0);
21
+ const timeoutMs = options.timeoutMs ?? (0 === policyTimeouts.length ? DEFAULT_SHARED_MANIFEST_LOAD_TIMEOUT_MS : positivePolicyTimeouts.length > 0 ? Math.min(...positivePolicyTimeouts) : 0);
20
22
  const inputSignals = [
21
23
  options.signal,
22
24
  options.manifestPolicy?.signal,
@@ -70,6 +72,27 @@ function isCallerPinnedStaticRemote(options, remote) {
70
72
  function throwIfManifestLoadAborted(signal) {
71
73
  if (signal.aborted) throw new BackendFederationManifestAdapterError('remote_unavailable', '[BFF][Effect] Backend federation load was aborted before remote execution.', signal.reason);
72
74
  }
75
+ function settleOnSharedAbort(promise, signal) {
76
+ if (signal.aborted) {
77
+ promise.catch(()=>{});
78
+ throwIfManifestLoadAborted(signal);
79
+ }
80
+ let onAbort;
81
+ const aborted = new Promise((_resolve, reject)=>{
82
+ onAbort = ()=>{
83
+ reject(new BackendFederationManifestAdapterError('remote_unavailable', '[BFF][Effect] Backend federation load was aborted before remote execution.', signal.reason));
84
+ };
85
+ signal.addEventListener('abort', onAbort, {
86
+ once: true
87
+ });
88
+ });
89
+ return Promise.race([
90
+ promise,
91
+ aborted
92
+ ]).finally(()=>{
93
+ if (onAbort) signal.removeEventListener('abort', onAbort);
94
+ });
95
+ }
73
96
  async function loadBackendFederatedEffectApiFromManifest(options) {
74
97
  let manifest;
75
98
  let remote;
@@ -77,7 +100,7 @@ async function loadBackendFederatedEffectApiFromManifest(options) {
77
100
  try {
78
101
  scope = createManifestLoadScope(options);
79
102
  throwIfManifestLoadAborted(scope.signal);
80
- manifest = await loadBackendFederationManifest({
103
+ manifest = await settleOnSharedAbort(loadBackendFederationManifest({
81
104
  ...options,
82
105
  manifestPolicy: {
83
106
  ...options.manifestPolicy,
@@ -86,7 +109,7 @@ async function loadBackendFederatedEffectApiFromManifest(options) {
86
109
  },
87
110
  signal: scope.signal,
88
111
  timeoutMs: 0
89
- });
112
+ }), scope.signal);
90
113
  validateBackendFederationManifest(manifest, options.expected);
91
114
  remote = resolveBackendFederationRemoteFromManifest(manifest, options.remote);
92
115
  throwIfManifestLoadAborted(scope.signal);
@@ -100,7 +123,7 @@ async function loadBackendFederatedEffectApiFromManifest(options) {
100
123
  const unitId = stringValue(deliveryUnit.boundary?.unitId) ?? stringValue(deliveryUnit.top?.unitId);
101
124
  const buildMarker = stringValue(deliveryUnit.boundary?.buildMarker);
102
125
  if (!unitId || !buildMarker) throw new BackendFederationManifestAdapterError('manifest_invalid', 'Backend federation manifest requires delivery-unit identity.');
103
- const loaded = await loadBackendFederatedEffectApi({
126
+ const loaded = await settleOnSharedAbort(loadBackendFederatedEffectApi({
104
127
  hostName: options.hostName,
105
128
  remote,
106
129
  ...options.plugins ? {
@@ -120,7 +143,7 @@ async function loadBackendFederatedEffectApiFromManifest(options) {
120
143
  }
121
144
  }).catch((error)=>{
122
145
  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);
123
- });
146
+ }), scope.signal);
124
147
  validateLoadedBackendFederationContract(loaded, manifest, remote);
125
148
  return loaded;
126
149
  } catch (error) {
@@ -6,6 +6,7 @@ import { backendFederationMetadata, manifestDeliveryUnit, stringValue, versionBo
6
6
  import { loadBackendFederationManifest } from "./reference.mjs";
7
7
  import { resolveBackendFederationRemoteFromManifest } from "./remote.mjs";
8
8
  import { classifyLoadError, validateBackendFederationManifest, validateLoadedBackendFederationContract } from "./validation.mjs";
9
+ const DEFAULT_SHARED_MANIFEST_LOAD_TIMEOUT_MS = 10000;
9
10
  function createManifestLoadScope(options) {
10
11
  const controller = new AbortController();
11
12
  const policyTimeouts = [
@@ -17,7 +18,8 @@ function createManifestLoadScope(options) {
17
18
  ...policyTimeouts
18
19
  ].filter((timeout)=>void 0 !== timeout);
19
20
  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.');
20
- const timeoutMs = options.timeoutMs ?? (policyTimeouts.length > 0 ? Math.min(...policyTimeouts) : 0);
21
+ const positivePolicyTimeouts = policyTimeouts.filter((timeout)=>timeout > 0);
22
+ const timeoutMs = options.timeoutMs ?? (0 === policyTimeouts.length ? DEFAULT_SHARED_MANIFEST_LOAD_TIMEOUT_MS : positivePolicyTimeouts.length > 0 ? Math.min(...positivePolicyTimeouts) : 0);
21
23
  const inputSignals = [
22
24
  options.signal,
23
25
  options.manifestPolicy?.signal,
@@ -71,6 +73,27 @@ function isCallerPinnedStaticRemote(options, remote) {
71
73
  function throwIfManifestLoadAborted(signal) {
72
74
  if (signal.aborted) throw new BackendFederationManifestAdapterError('remote_unavailable', '[BFF][Effect] Backend federation load was aborted before remote execution.', signal.reason);
73
75
  }
76
+ function settleOnSharedAbort(promise, signal) {
77
+ if (signal.aborted) {
78
+ promise.catch(()=>{});
79
+ throwIfManifestLoadAborted(signal);
80
+ }
81
+ let onAbort;
82
+ const aborted = new Promise((_resolve, reject)=>{
83
+ onAbort = ()=>{
84
+ reject(new BackendFederationManifestAdapterError('remote_unavailable', '[BFF][Effect] Backend federation load was aborted before remote execution.', signal.reason));
85
+ };
86
+ signal.addEventListener('abort', onAbort, {
87
+ once: true
88
+ });
89
+ });
90
+ return Promise.race([
91
+ promise,
92
+ aborted
93
+ ]).finally(()=>{
94
+ if (onAbort) signal.removeEventListener('abort', onAbort);
95
+ });
96
+ }
74
97
  async function loadBackendFederatedEffectApiFromManifest(options) {
75
98
  let manifest;
76
99
  let remote;
@@ -78,7 +101,7 @@ async function loadBackendFederatedEffectApiFromManifest(options) {
78
101
  try {
79
102
  scope = createManifestLoadScope(options);
80
103
  throwIfManifestLoadAborted(scope.signal);
81
- manifest = await loadBackendFederationManifest({
104
+ manifest = await settleOnSharedAbort(loadBackendFederationManifest({
82
105
  ...options,
83
106
  manifestPolicy: {
84
107
  ...options.manifestPolicy,
@@ -87,7 +110,7 @@ async function loadBackendFederatedEffectApiFromManifest(options) {
87
110
  },
88
111
  signal: scope.signal,
89
112
  timeoutMs: 0
90
- });
113
+ }), scope.signal);
91
114
  validateBackendFederationManifest(manifest, options.expected);
92
115
  remote = resolveBackendFederationRemoteFromManifest(manifest, options.remote);
93
116
  throwIfManifestLoadAborted(scope.signal);
@@ -101,7 +124,7 @@ async function loadBackendFederatedEffectApiFromManifest(options) {
101
124
  const unitId = stringValue(deliveryUnit.boundary?.unitId) ?? stringValue(deliveryUnit.top?.unitId);
102
125
  const buildMarker = stringValue(deliveryUnit.boundary?.buildMarker);
103
126
  if (!unitId || !buildMarker) throw new BackendFederationManifestAdapterError('manifest_invalid', 'Backend federation manifest requires delivery-unit identity.');
104
- const loaded = await loadBackendFederatedEffectApi({
127
+ const loaded = await settleOnSharedAbort(loadBackendFederatedEffectApi({
105
128
  hostName: options.hostName,
106
129
  remote,
107
130
  ...options.plugins ? {
@@ -121,7 +144,7 @@ async function loadBackendFederatedEffectApiFromManifest(options) {
121
144
  }
122
145
  }).catch((error)=>{
123
146
  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);
124
- });
147
+ }), scope.signal);
125
148
  validateLoadedBackendFederationContract(loaded, manifest, remote);
126
149
  return loaded;
127
150
  } catch (error) {
package/package.json CHANGED
@@ -18,7 +18,7 @@
18
18
  "modern.js",
19
19
  "ultramodern.js"
20
20
  ],
21
- "version": "3.9.0-ultramodern.10",
21
+ "version": "3.9.0-ultramodern.11",
22
22
  "files": [
23
23
  "dist",
24
24
  "src"
@@ -193,14 +193,14 @@
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.10",
197
- "@modern-js/bff-core": "npm:@bleedingdev/modern-js-bff-core@3.9.0-ultramodern.10",
198
- "@modern-js/bff-effect": "npm:@bleedingdev/modern-js-bff-effect@3.9.0-ultramodern.10",
199
- "@modern-js/runtime-extensions": "npm:@bleedingdev/modern-js-runtime-extensions@3.9.0-ultramodern.10",
200
- "@modern-js/server-core": "npm:@bleedingdev/modern-js-server-core@3.9.0-ultramodern.10",
201
- "@modern-js/server-runtime-extensions": "npm:@bleedingdev/modern-js-server-runtime-extensions@3.9.0-ultramodern.10",
202
- "@modern-js/types": "npm:@bleedingdev/modern-js-types@3.9.0-ultramodern.10",
203
- "@modern-js/utils": "npm:@bleedingdev/modern-js-utils@3.9.0-ultramodern.10",
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
204
  "@module-federation/runtime": "2.9.0",
205
205
  "@swc/core": "1.16.2",
206
206
  "esbuild": "^0.28.2"
@@ -219,7 +219,7 @@
219
219
  },
220
220
  "devDependencies": {
221
221
  "@effect/opentelemetry": "4.0.0-rc.112",
222
- "@modern-js/plugin": "npm:@bleedingdev/modern-js-plugin@3.9.0-ultramodern.10",
222
+ "@modern-js/plugin": "npm:@bleedingdev/modern-js-plugin@3.9.0-ultramodern.11",
223
223
  "@rsbuild/core": "2.2.3",
224
224
  "@rslib/core": "1.0.0",
225
225
  "@scripts/rstest-config": "2.66.0",
@@ -25,6 +25,10 @@ import {
25
25
  validateLoadedBackendFederationContract,
26
26
  } from './validation';
27
27
 
28
+ // One manifest+entry budget. Explicit outer 0 opts out; nested 0 cannot
29
+ // disable a positive nested deadline.
30
+ const DEFAULT_SHARED_MANIFEST_LOAD_TIMEOUT_MS = 10_000;
31
+
28
32
  function createManifestLoadScope(
29
33
  options: BackendFederationManifestAdapterOptions,
30
34
  ) {
@@ -44,9 +48,14 @@ function createManifestLoadScope(
44
48
  );
45
49
  }
46
50
  }
51
+ const positivePolicyTimeouts = policyTimeouts.filter(timeout => timeout > 0);
47
52
  const timeoutMs =
48
53
  options.timeoutMs ??
49
- (policyTimeouts.length > 0 ? Math.min(...policyTimeouts) : 0);
54
+ (policyTimeouts.length === 0
55
+ ? DEFAULT_SHARED_MANIFEST_LOAD_TIMEOUT_MS
56
+ : positivePolicyTimeouts.length > 0
57
+ ? Math.min(...positivePolicyTimeouts)
58
+ : 0);
50
59
  const inputSignals = [
51
60
  options.signal,
52
61
  options.manifestPolicy?.signal,
@@ -140,6 +149,39 @@ function throwIfManifestLoadAborted(signal: AbortSignal) {
140
149
  }
141
150
  }
142
151
 
152
+ // Stop waiting even when trusted plugin work ignores cancellation. The race
153
+ // observes late rejections; it cannot stop that work from running.
154
+ function settleOnSharedAbort<T>(
155
+ promise: Promise<T>,
156
+ signal: AbortSignal,
157
+ ): Promise<T> {
158
+ if (signal.aborted) {
159
+ // Observe work even when the pre-aborted path never reaches Promise.race.
160
+ promise.catch(() => {});
161
+ throwIfManifestLoadAborted(signal);
162
+ }
163
+
164
+ let onAbort: (() => void) | undefined;
165
+ const aborted = new Promise<never>((_resolve, reject) => {
166
+ onAbort = () => {
167
+ reject(
168
+ new BackendFederationManifestAdapterError(
169
+ 'remote_unavailable',
170
+ '[BFF][Effect] Backend federation load was aborted before remote execution.',
171
+ signal.reason,
172
+ ),
173
+ );
174
+ };
175
+ signal.addEventListener('abort', onAbort, { once: true });
176
+ });
177
+
178
+ return Promise.race([promise, aborted]).finally(() => {
179
+ if (onAbort) {
180
+ signal.removeEventListener('abort', onAbort);
181
+ }
182
+ });
183
+ }
184
+
143
185
  export async function loadBackendFederatedEffectApiFromManifest(
144
186
  options: BackendFederationManifestAdapterOptions,
145
187
  ): Promise<BackendFederatedEffectApiModule> {
@@ -150,16 +192,19 @@ export async function loadBackendFederatedEffectApiFromManifest(
150
192
  try {
151
193
  scope = createManifestLoadScope(options);
152
194
  throwIfManifestLoadAborted(scope.signal);
153
- manifest = await loadBackendFederationManifest({
154
- ...options,
155
- manifestPolicy: {
156
- ...options.manifestPolicy,
195
+ manifest = await settleOnSharedAbort(
196
+ loadBackendFederationManifest({
197
+ ...options,
198
+ manifestPolicy: {
199
+ ...options.manifestPolicy,
200
+ signal: scope.signal,
201
+ timeoutMs: 0,
202
+ },
157
203
  signal: scope.signal,
158
204
  timeoutMs: 0,
159
- },
160
- signal: scope.signal,
161
- timeoutMs: 0,
162
- });
205
+ }),
206
+ scope.signal,
207
+ );
163
208
  validateBackendFederationManifest(manifest, options.expected);
164
209
  remote = resolveBackendFederationRemoteFromManifest(
165
210
  manifest,
@@ -223,24 +268,27 @@ export async function loadBackendFederatedEffectApiFromManifest(
223
268
  'manifest_invalid',
224
269
  'Backend federation manifest requires delivery-unit identity.',
225
270
  );
226
- const loaded = await loadBackendFederatedEffectApi({
227
- hostName: options.hostName,
228
- remote,
229
- ...(options.plugins ? { plugins: options.plugins } : {}),
230
- entryPolicy: {
231
- ...options.entryPolicy,
232
- signal: scope.signal,
233
- timeoutMs: 0,
234
- },
235
- ...(options.runtime ? { runtime: options.runtime } : {}),
236
- expected: { unitId, buildMarker },
237
- }).catch((error: unknown) => {
238
- throw new BackendFederationManifestAdapterError(
239
- scope?.timedOut() === true ? 'timeout' : classifyLoadError(error),
240
- `[BFF][Effect] Backend federation remote ${remote?.name ?? 'unknown'} could not load ${remote?.expose ?? BACKEND_FEDERATION_EFFECT_EXPOSE}.`,
241
- error,
242
- );
243
- });
271
+ const loaded = await settleOnSharedAbort(
272
+ loadBackendFederatedEffectApi({
273
+ hostName: options.hostName,
274
+ remote,
275
+ ...(options.plugins ? { plugins: options.plugins } : {}),
276
+ entryPolicy: {
277
+ ...options.entryPolicy,
278
+ signal: scope.signal,
279
+ timeoutMs: 0,
280
+ },
281
+ ...(options.runtime ? { runtime: options.runtime } : {}),
282
+ expected: { unitId, buildMarker },
283
+ }).catch((error: unknown) => {
284
+ throw new BackendFederationManifestAdapterError(
285
+ scope?.timedOut() === true ? 'timeout' : classifyLoadError(error),
286
+ `[BFF][Effect] Backend federation remote ${remote?.name ?? 'unknown'} could not load ${remote?.expose ?? BACKEND_FEDERATION_EFFECT_EXPOSE}.`,
287
+ error,
288
+ );
289
+ }),
290
+ scope.signal,
291
+ );
244
292
 
245
293
  validateLoadedBackendFederationContract(loaded, manifest, remote);
246
294