@bleedingdev/modern-js-bff-effect 3.9.0-ultramodern.2 → 3.9.0-ultramodern.21

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 (142) hide show
  1. package/README.md +20 -4
  2. package/dist/cjs/assembly.js +50 -0
  3. package/dist/cjs/{effect-client/guards.js → data-platform/batch/options.js} +13 -9
  4. package/dist/cjs/data-platform/batch/queue.js +48 -83
  5. package/dist/cjs/data-platform/trace.js +2 -2
  6. package/dist/cjs/effect/context.js +28 -4
  7. package/dist/cjs/effect/edge-dispatcher.js +12 -12
  8. package/dist/cjs/effect/edge.js +36 -3
  9. package/dist/cjs/effect/endpoint-contracts.js +3 -4
  10. package/dist/cjs/effect/entry-shape.js +40 -12
  11. package/dist/cjs/effect/generated-entry.js +57 -0
  12. package/dist/cjs/effect/handler/batch-handler.js +7 -7
  13. package/dist/cjs/effect/handler/batch.js +8 -10
  14. package/dist/cjs/effect/handler/definition.js +1 -21
  15. package/dist/cjs/effect/index.js +8 -8
  16. package/dist/cjs/effect/module.js +8 -4
  17. package/dist/cjs/effect/operation-context.js +10 -14
  18. package/dist/cjs/effect/rpcSerialization.js +0 -2
  19. package/dist/cjs/effect-client/cross-project.js +89 -0
  20. package/dist/cjs/effect-client/index.js +5 -3
  21. package/dist/cjs/microvertical-api.js +120 -0
  22. package/dist/esm/assembly.mjs +12 -0
  23. package/dist/esm/data-platform/batch/options.mjs +10 -0
  24. package/dist/esm/data-platform/batch/queue.mjs +48 -83
  25. package/dist/esm/data-platform/trace.mjs +1 -1
  26. package/dist/esm/effect/context.mjs +21 -6
  27. package/dist/esm/effect/edge-dispatcher.mjs +6 -6
  28. package/dist/esm/effect/edge.mjs +3 -0
  29. package/dist/esm/effect/endpoint-contracts.mjs +2 -3
  30. package/dist/esm/effect/entry-shape-registry.mjs +2 -2
  31. package/dist/esm/effect/entry-shape.mjs +29 -6
  32. package/dist/esm/effect/generated-entry.mjs +19 -0
  33. package/dist/esm/effect/handler/batch-handler.mjs +8 -8
  34. package/dist/esm/effect/handler/batch.mjs +9 -8
  35. package/dist/esm/effect/handler/definition.mjs +1 -21
  36. package/dist/esm/effect/index.mjs +1 -1
  37. package/dist/esm/effect/module.mjs +8 -4
  38. package/dist/esm/effect/operation-context.mjs +3 -4
  39. package/dist/esm/effect/rpcSerialization.mjs +0 -2
  40. package/dist/esm/effect-client/cross-project.mjs +51 -0
  41. package/dist/esm/effect-client/index.mjs +4 -2
  42. package/dist/esm/microvertical-api.mjs +67 -0
  43. package/dist/esm-node/assembly.mjs +13 -0
  44. package/dist/esm-node/data-platform/batch/options.mjs +11 -0
  45. package/dist/esm-node/data-platform/batch/queue.mjs +48 -83
  46. package/dist/esm-node/data-platform/trace.mjs +1 -1
  47. package/dist/esm-node/effect/context.mjs +21 -6
  48. package/dist/esm-node/effect/edge-dispatcher.mjs +6 -6
  49. package/dist/esm-node/effect/edge.mjs +3 -0
  50. package/dist/esm-node/effect/endpoint-contracts.mjs +2 -3
  51. package/dist/esm-node/effect/entry-shape.mjs +29 -6
  52. package/dist/esm-node/effect/generated-entry.mjs +20 -0
  53. package/dist/esm-node/effect/handler/batch-handler.mjs +8 -8
  54. package/dist/esm-node/effect/handler/batch.mjs +9 -8
  55. package/dist/esm-node/effect/handler/definition.mjs +1 -21
  56. package/dist/esm-node/effect/index.mjs +1 -1
  57. package/dist/esm-node/effect/module.mjs +8 -4
  58. package/dist/esm-node/effect/operation-context.mjs +3 -4
  59. package/dist/esm-node/effect/rpcSerialization.mjs +0 -2
  60. package/dist/esm-node/effect-client/cross-project.mjs +52 -0
  61. package/dist/esm-node/effect-client/index.mjs +4 -2
  62. package/dist/esm-node/microvertical-api.mjs +68 -0
  63. package/dist/types/assembly.d.ts +10 -0
  64. package/dist/types/data-platform/batch/options.d.ts +7 -0
  65. package/dist/types/data-platform/batch/queue.d.ts +0 -1
  66. package/dist/types/effect/context.d.ts +15 -2
  67. package/dist/types/effect/edge-dispatcher.d.ts +3 -3
  68. package/dist/types/effect/edge.d.ts +3 -0
  69. package/dist/types/effect/endpoint-contracts.d.ts +2 -20
  70. package/dist/types/effect/entry-shape.d.ts +16 -2
  71. package/dist/types/effect/generated-entry.d.ts +7 -0
  72. package/dist/types/effect/handler/batch.d.ts +7 -2
  73. package/dist/types/effect/handler/types.d.ts +2 -17
  74. package/dist/types/effect/handler.d.ts +1 -1
  75. package/dist/types/effect/module.d.ts +2 -1
  76. package/dist/types/effect/operation-context.d.ts +1 -2
  77. package/dist/types/effect-client/cross-project.d.ts +10 -0
  78. package/dist/types/effect-client/index.d.ts +7 -4
  79. package/dist/types/microvertical-api.d.ts +65 -0
  80. package/package.json +47 -42
  81. package/src/assembly.ts +43 -0
  82. package/src/data-platform/batch/options.ts +20 -0
  83. package/src/data-platform/batch/queue.ts +63 -92
  84. package/src/data-platform/trace.ts +1 -1
  85. package/src/effect/context.ts +64 -12
  86. package/src/effect/edge-dispatcher.ts +14 -11
  87. package/src/effect/edge.ts +6 -0
  88. package/src/effect/endpoint-contracts.ts +3 -24
  89. package/src/effect/entry-shape.ts +105 -10
  90. package/src/effect/generated-entry.ts +36 -0
  91. package/src/effect/handler/batch-handler.ts +27 -28
  92. package/src/effect/handler/batch.ts +9 -13
  93. package/src/effect/handler/definition.ts +0 -45
  94. package/src/effect/handler/http.ts +2 -2
  95. package/src/effect/handler/types.ts +3 -32
  96. package/src/effect/handler.ts +0 -1
  97. package/src/effect/index.ts +1 -1
  98. package/src/effect/module.ts +11 -4
  99. package/src/effect/operation-context.ts +2 -6
  100. package/src/effect/rpcSerialization.ts +0 -2
  101. package/src/effect-client/cross-project.ts +104 -0
  102. package/src/effect-client/index.ts +17 -7
  103. package/src/microvertical-api.ts +102 -0
  104. package/dist/cjs/effect/edge-context.js +0 -61
  105. package/dist/cjs/effect-client/batch.js +0 -73
  106. package/dist/cjs/effect-client/envelope.js +0 -145
  107. package/dist/cjs/effect-client/request-context.js +0 -64
  108. package/dist/cjs/effect-client/request.js +0 -66
  109. package/dist/cjs/effect-client/runtime.js +0 -100
  110. package/dist/cjs/effect-client/types.js +0 -18
  111. package/dist/esm/effect/edge-context.mjs +0 -14
  112. package/dist/esm/effect-client/batch.mjs +0 -35
  113. package/dist/esm/effect-client/envelope.mjs +0 -104
  114. package/dist/esm/effect-client/guards.mjs +0 -3
  115. package/dist/esm/effect-client/request-context.mjs +0 -23
  116. package/dist/esm/effect-client/request.mjs +0 -28
  117. package/dist/esm/effect-client/runtime.mjs +0 -62
  118. package/dist/esm/effect-client/types.mjs +0 -0
  119. package/dist/esm-node/effect/edge-context.mjs +0 -15
  120. package/dist/esm-node/effect-client/batch.mjs +0 -36
  121. package/dist/esm-node/effect-client/envelope.mjs +0 -105
  122. package/dist/esm-node/effect-client/guards.mjs +0 -4
  123. package/dist/esm-node/effect-client/request-context.mjs +0 -24
  124. package/dist/esm-node/effect-client/request.mjs +0 -29
  125. package/dist/esm-node/effect-client/runtime.mjs +0 -63
  126. package/dist/esm-node/effect-client/types.mjs +0 -1
  127. package/dist/types/effect/edge-context.d.ts +0 -5
  128. package/dist/types/effect-client/batch.d.ts +0 -2
  129. package/dist/types/effect-client/envelope.d.ts +0 -15
  130. package/dist/types/effect-client/guards.d.ts +0 -2
  131. package/dist/types/effect-client/request-context.d.ts +0 -3
  132. package/dist/types/effect-client/request.d.ts +0 -1
  133. package/dist/types/effect-client/runtime.d.ts +0 -5
  134. package/dist/types/effect-client/types.d.ts +0 -68
  135. package/src/effect/edge-context.ts +0 -51
  136. package/src/effect-client/batch.ts +0 -50
  137. package/src/effect-client/envelope.ts +0 -238
  138. package/src/effect-client/guards.ts +0 -6
  139. package/src/effect-client/request-context.ts +0 -54
  140. package/src/effect-client/request.ts +0 -51
  141. package/src/effect-client/runtime.ts +0 -122
  142. package/src/effect-client/types.ts +0 -84
@@ -0,0 +1,120 @@
1
+ "use strict";
2
+ var __webpack_require__ = {};
3
+ (()=>{
4
+ __webpack_require__.d = (exports1, getters, values)=>{
5
+ var define = (defs, kind)=>{
6
+ for(var key in defs)if (__webpack_require__.o(defs, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
7
+ enumerable: true,
8
+ [kind]: defs[key]
9
+ });
10
+ };
11
+ define(getters, "get");
12
+ define(values, "value");
13
+ };
14
+ })();
15
+ (()=>{
16
+ __webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
17
+ })();
18
+ (()=>{
19
+ __webpack_require__.r = (exports1)=>{
20
+ if ("u" > typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
21
+ value: 'Module'
22
+ });
23
+ Object.defineProperty(exports1, '__esModule', {
24
+ value: true
25
+ });
26
+ };
27
+ })();
28
+ var __webpack_exports__ = {};
29
+ __webpack_require__.r(__webpack_exports__);
30
+ __webpack_require__.d(__webpack_exports__, {
31
+ MicroVerticalBuildMarkerSchema: ()=>MicroVerticalBuildMarkerSchema,
32
+ MicroVerticalOperationContextSchema: ()=>MicroVerticalOperationContextSchema,
33
+ MicroVerticalOperationSourceSchema: ()=>MicroVerticalOperationSourceSchema,
34
+ MicroVerticalReadinessSchema: ()=>MicroVerticalReadinessSchema,
35
+ createMicroVerticalOperationContext: ()=>createMicroVerticalOperationContext,
36
+ microVerticalOperationAttributes: ()=>microVerticalOperationAttributes
37
+ });
38
+ const external_effect_namespaceObject = require("effect");
39
+ const MicroVerticalAppIdSchema = external_effect_namespaceObject.Schema.String.pipe(external_effect_namespaceObject.Schema.brand('MicroVerticalAppId'), external_effect_namespaceObject.Schema.decodeTo(external_effect_namespaceObject.Schema.String));
40
+ const MicroVerticalUnitIdSchema = external_effect_namespaceObject.Schema.String.pipe(external_effect_namespaceObject.Schema.brand('MicroVerticalUnitId'), external_effect_namespaceObject.Schema.decodeTo(external_effect_namespaceObject.Schema.String));
41
+ const MicroVerticalOperationIdSchema = external_effect_namespaceObject.Schema.String.pipe(external_effect_namespaceObject.Schema.brand('MicroVerticalOperationId'), external_effect_namespaceObject.Schema.decodeTo(external_effect_namespaceObject.Schema.String));
42
+ const MicroVerticalTraceIdSchema = external_effect_namespaceObject.Schema.String.pipe(external_effect_namespaceObject.Schema.brand('MicroVerticalTraceId'), external_effect_namespaceObject.Schema.decodeTo(external_effect_namespaceObject.Schema.String));
43
+ const MicroVerticalBuildMarkerSchema = external_effect_namespaceObject.Schema.Struct({
44
+ appId: MicroVerticalAppIdSchema,
45
+ build: external_effect_namespaceObject.Schema.String,
46
+ buildMarker: external_effect_namespaceObject.Schema.String,
47
+ deployProfile: external_effect_namespaceObject.Schema.String,
48
+ packageName: external_effect_namespaceObject.Schema.String,
49
+ sourceRevision: external_effect_namespaceObject.Schema.String,
50
+ surface: external_effect_namespaceObject.Schema.String,
51
+ unitId: MicroVerticalUnitIdSchema,
52
+ version: external_effect_namespaceObject.Schema.String
53
+ });
54
+ const MicroVerticalReadinessSchema = external_effect_namespaceObject.Schema.Struct({
55
+ checks: external_effect_namespaceObject.Schema.Struct({
56
+ api: external_effect_namespaceObject.Schema.Literal('ready'),
57
+ moduleFederation: external_effect_namespaceObject.Schema.Literal('ready'),
58
+ ssr: external_effect_namespaceObject.Schema.Literal('ready'),
59
+ translations: external_effect_namespaceObject.Schema.Literal('ready')
60
+ }),
61
+ marker: MicroVerticalBuildMarkerSchema,
62
+ status: external_effect_namespaceObject.Schema.Literal('ready'),
63
+ versionSkew: external_effect_namespaceObject.Schema.Literal('none')
64
+ });
65
+ const MicroVerticalOperationSourceSchema = external_effect_namespaceObject.Schema.Literals([
66
+ 'client',
67
+ 'server',
68
+ 'generated-client',
69
+ 'effect-server',
70
+ 'data-platform',
71
+ 'unknown'
72
+ ]);
73
+ const MicroVerticalOperationContextSchema = external_effect_namespaceObject.Schema.Struct({
74
+ method: external_effect_namespaceObject.Schema.String,
75
+ operationId: MicroVerticalOperationIdSchema,
76
+ routePath: external_effect_namespaceObject.Schema.String,
77
+ source: MicroVerticalOperationSourceSchema,
78
+ traceId: external_effect_namespaceObject.Schema.optionalKey(MicroVerticalTraceIdSchema)
79
+ });
80
+ const createMicroVerticalOperationContext = (input)=>{
81
+ const context = {
82
+ method: input.method,
83
+ operationId: input.operationId,
84
+ routePath: input.routePath,
85
+ source: 'generated-client'
86
+ };
87
+ return void 0 === input.traceId ? context : {
88
+ ...context,
89
+ traceId: input.traceId
90
+ };
91
+ };
92
+ const microVerticalOperationAttributes = (operationContext)=>{
93
+ const attributes = {
94
+ 'modernjs.operation.id': operationContext.operationId,
95
+ 'modernjs.operation.method': operationContext.method,
96
+ 'modernjs.operation.route': operationContext.routePath,
97
+ 'modernjs.operation.source': operationContext.source
98
+ };
99
+ return void 0 === operationContext.traceId ? attributes : {
100
+ ...attributes,
101
+ 'modernjs.trace.id': operationContext.traceId
102
+ };
103
+ };
104
+ exports.MicroVerticalBuildMarkerSchema = __webpack_exports__.MicroVerticalBuildMarkerSchema;
105
+ exports.MicroVerticalOperationContextSchema = __webpack_exports__.MicroVerticalOperationContextSchema;
106
+ exports.MicroVerticalOperationSourceSchema = __webpack_exports__.MicroVerticalOperationSourceSchema;
107
+ exports.MicroVerticalReadinessSchema = __webpack_exports__.MicroVerticalReadinessSchema;
108
+ exports.createMicroVerticalOperationContext = __webpack_exports__.createMicroVerticalOperationContext;
109
+ exports.microVerticalOperationAttributes = __webpack_exports__.microVerticalOperationAttributes;
110
+ for(var __rspack_i in __webpack_exports__)if (-1 === [
111
+ "MicroVerticalBuildMarkerSchema",
112
+ "MicroVerticalOperationContextSchema",
113
+ "MicroVerticalOperationSourceSchema",
114
+ "MicroVerticalReadinessSchema",
115
+ "createMicroVerticalOperationContext",
116
+ "microVerticalOperationAttributes"
117
+ ].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
118
+ Object.defineProperty(exports, '__esModule', {
119
+ value: true
120
+ });
@@ -0,0 +1,12 @@
1
+ import { HttpApiBuilder } from "effect/unstable/httpapi";
2
+ import { defineEffectBff } from "./effect/handler/definition.mjs";
3
+ import * as __rspack_external_effect_Layer_69c46453 from "effect/Layer";
4
+ const assembleEffectBffRuntime = ({ api, handlers, transport })=>{
5
+ const apiLayer = HttpApiBuilder.layer(api).pipe(__rspack_external_effect_Layer_69c46453.provide(handlers));
6
+ const layer = void 0 === transport ? apiLayer : apiLayer.pipe(__rspack_external_effect_Layer_69c46453.merge(transport));
7
+ return defineEffectBff({
8
+ api,
9
+ layer
10
+ });
11
+ };
12
+ export { assembleEffectBffRuntime };
@@ -0,0 +1,10 @@
1
+ function normalizeBatchLimits(options = {}) {
2
+ return {
3
+ maxBatchSize: Math.max(1, options.maxBatchSize ?? 16),
4
+ maxBatchBytes: Math.max(1024, options.maxBatchBytes ?? 65536),
5
+ allowedMethods: new Set((void 0 !== options.allowedMethods && options.allowedMethods.length > 0 ? options.allowedMethods : [
6
+ 'GET'
7
+ ]).map((method)=>method.toUpperCase()))
8
+ };
9
+ }
10
+ export { normalizeBatchLimits };
@@ -1,5 +1,6 @@
1
1
  import { stableStringify } from "../codec.mjs";
2
2
  import { DEFAULT_DATA_BATCH_HEADER } from "../types.mjs";
3
+ import { normalizeBatchLimits } from "./options.mjs";
3
4
  import { decodeBatchBody, isNullBodyStatus } from "./protocol.mjs";
4
5
  import { createBatchId, measureTextBytes, normalizeMethod, shouldBatchRequest, toHeaderRecord, toRequestBody } from "./request.mjs";
5
6
  import { isBatchResponsePayload, parseResponseLikeCreateRequest } from "./response.mjs";
@@ -78,7 +79,6 @@ class BatchBucketRegistry {
78
79
  if (existing) return existing;
79
80
  const next = {
80
81
  items: [],
81
- bytes: 0,
82
82
  batchId: createBatchId(),
83
83
  sentAt: Date.now(),
84
84
  timer: null,
@@ -97,12 +97,8 @@ class BatchBucketRegistry {
97
97
  }
98
98
  function createBatchTransportQueue({ options, baseFetch, bucketRegistry }) {
99
99
  const flushIntervalMs = Math.max(0, options.flushIntervalMs ?? 8);
100
- const maxBatchSize = Math.max(1, options.maxBatchSize ?? 16);
101
- const maxBatchBytes = Math.max(1024, options.maxBatchBytes ?? 65536);
100
+ const { maxBatchSize, maxBatchBytes, allowedMethods } = normalizeBatchLimits(options);
102
101
  const requestTimeoutMs = options.requestTimeoutMs;
103
- const allowedMethods = new Set((options.allowedMethods && options.allowedMethods.length > 0 ? options.allowedMethods : [
104
- 'GET'
105
- ]).map((method)=>method.toUpperCase()));
106
102
  const onEvent = options.onEvent;
107
103
  const buckets = bucketRegistry ?? new BatchBucketRegistry();
108
104
  const pendingByKey = new Map();
@@ -135,7 +131,6 @@ function createBatchTransportQueue({ options, baseFetch, bucketRegistry }) {
135
131
  const index = bucket.items.indexOf(request);
136
132
  if (-1 === index) return;
137
133
  bucket.items.splice(index, 1);
138
- bucket.bytes = measurePayload(bucket, bucket.items);
139
134
  if (0 === bucket.items.length && bucket.timer) {
140
135
  clearTimeout(bucket.timer);
141
136
  bucket.timer = null;
@@ -177,7 +172,11 @@ function createBatchTransportQueue({ options, baseFetch, bucketRegistry }) {
177
172
  if (!SAFE_REPLAY_METHODS.has(request.item.method)) throw new Error(`Batch result is unknown for ${request.item.method}; automatic replay is disabled (${reason}).`);
178
173
  return runSingle(request);
179
174
  };
180
- const settleAmbiguousBatchRequests = (items, reason)=>settleRequests(items, (request)=>runAfterAmbiguousBatch(request, reason));
175
+ const finishFlush = (bucketKey, bucket)=>{
176
+ bucket.flushing = false;
177
+ if (bucket.items.length > 0 && !bucket.timer) flushBucket(bucketKey);
178
+ buckets.releaseIfIdle(bucketKey, bucket);
179
+ };
181
180
  const flushBucket = async (bucketKey)=>{
182
181
  const bucket = buckets.get(bucketKey);
183
182
  if (!bucket || bucket.flushing) return;
@@ -194,7 +193,6 @@ function createBatchTransportQueue({ options, baseFetch, bucketRegistry }) {
194
193
  sentAt: bucket.sentAt
195
194
  };
196
195
  bucket.items = [];
197
- bucket.bytes = 0;
198
196
  rotatePayloadIdentity(bucket);
199
197
  const firstItem = items[0];
200
198
  if (!firstItem) {
@@ -210,14 +208,25 @@ function createBatchTransportQueue({ options, baseFetch, bucketRegistry }) {
210
208
  size: items.length,
211
209
  reason: disabledEndpoints.has(endpoint) ? 'batch-disabled' : void 0
212
210
  });
213
- await settleRequests(items, runSingle);
214
- bucket.flushing = false;
215
- if (bucket.items.length > 0 && !bucket.timer) flushBucket(bucketKey);
216
- buckets.releaseIfIdle(bucketKey, bucket);
211
+ try {
212
+ await settleRequests(items, runSingle);
213
+ } finally{
214
+ finishFlush(bucketKey, bucket);
215
+ }
217
216
  return;
218
217
  }
219
218
  const payload = createPayload(payloadIdentity, items);
220
219
  const batchId = payload.batchId;
220
+ const settleAmbiguousBatchRequests = (reason)=>{
221
+ emitDataBatchTransportEvent(onEvent, {
222
+ type: 'fallback',
223
+ endpoint,
224
+ batchId,
225
+ size: items.length,
226
+ reason
227
+ });
228
+ return settleRequests(items, (request)=>runAfterAmbiguousBatch(request, reason));
229
+ };
221
230
  emitDataBatchTransportEvent(onEvent, {
222
231
  type: 'flush',
223
232
  endpoint,
@@ -268,42 +277,13 @@ function createBatchTransportQueue({ options, baseFetch, bucketRegistry }) {
268
277
  batchId,
269
278
  reason: `batch-endpoint-unavailable-${String(response.status)}`
270
279
  });
271
- } else emitDataBatchTransportEvent(onEvent, {
272
- type: 'fallback',
273
- endpoint,
274
- batchId,
275
- size: items.length,
276
- reason: `batch-response-${String(response.status)}`
277
- });
278
- await settleAmbiguousBatchRequests(items, `batch-response-${String(response.status)}`);
279
- bucket.flushing = false;
280
+ await settleRequests(items, (request)=>runAfterAmbiguousBatch(request, `batch-response-${String(response.status)}`));
281
+ } else await settleAmbiguousBatchRequests(`batch-response-${String(response.status)}`);
280
282
  return;
281
283
  }
282
284
  const result = await runWithSignal(controller.signal, async ()=>response.json());
283
- if (!isBatchResponsePayload(result)) {
284
- emitDataBatchTransportEvent(onEvent, {
285
- type: 'fallback',
286
- endpoint,
287
- batchId,
288
- size: items.length,
289
- reason: 'invalid-batch-response'
290
- });
291
- await settleAmbiguousBatchRequests(items, 'invalid-batch-response');
292
- bucket.flushing = false;
293
- return;
294
- }
295
- if (result.batchId !== batchId) {
296
- emitDataBatchTransportEvent(onEvent, {
297
- type: 'fallback',
298
- endpoint,
299
- batchId,
300
- size: items.length,
301
- reason: 'mismatched-batch-id'
302
- });
303
- await settleAmbiguousBatchRequests(items, 'mismatched-batch-id');
304
- bucket.flushing = false;
305
- return;
306
- }
285
+ if (!isBatchResponsePayload(result)) return void await settleAmbiguousBatchRequests('invalid-batch-response');
286
+ if (result.batchId !== batchId) return void await settleAmbiguousBatchRequests('mismatched-batch-id');
307
287
  const itemMap = new Map();
308
288
  for (const item of result.items)itemMap.set(item.id, item);
309
289
  await settleRequests(items, async (request)=>{
@@ -327,19 +307,10 @@ function createBatchTransportQueue({ options, baseFetch, bucketRegistry }) {
327
307
  });
328
308
  return;
329
309
  }
330
- emitDataBatchTransportEvent(onEvent, {
331
- type: 'fallback',
332
- endpoint,
333
- batchId,
334
- size: items.length,
335
- reason: 'batch-transport-error'
336
- });
337
- await settleAmbiguousBatchRequests(items, 'batch-transport-error');
310
+ await settleAmbiguousBatchRequests('batch-transport-error');
338
311
  } finally{
339
312
  for (const item of items)item.abortBatchIfUnused = void 0;
340
- bucket.flushing = false;
341
- if (bucket.items.length > 0 && !bucket.timer) flushBucket(bucketKey);
342
- buckets.releaseIfIdle(bucketKey, bucket);
313
+ finishFlush(bucketKey, bucket);
343
314
  }
344
315
  };
345
316
  const pendingReadPromises = new Map();
@@ -363,7 +334,20 @@ function createBatchTransportQueue({ options, baseFetch, bucketRegistry }) {
363
334
  const sourceSignal = initDefinesSignal ? initSignal ?? void 0 : sourceRequest?.signal;
364
335
  const requestUrl = toAbsoluteUrl(input);
365
336
  const endpoint = normalizeBatchEndpoint(requestUrl, options.endpoint).toString();
337
+ const itemHeaders = {
338
+ ...headers
339
+ };
340
+ delete itemHeaders.authorization;
341
+ delete itemHeaders.cookie;
366
342
  return {
343
+ itemHeaders,
344
+ itemPath: `${requestUrl.pathname}${requestUrl.search}`,
345
+ bucketKey: stableStringify({
346
+ endpoint,
347
+ authorization: headers.authorization ?? null,
348
+ cookie: headers.cookie ?? null,
349
+ credentials
350
+ }),
367
351
  requestUrl,
368
352
  endpoint,
369
353
  method,
@@ -396,22 +380,11 @@ function createBatchTransportQueue({ options, baseFetch, bucketRegistry }) {
396
380
  batchEndpoint: request.endpoint,
397
381
  requestUrl: request.requestUrl
398
382
  })) return;
399
- const itemHeaders = {
400
- ...request.headers
401
- };
402
- delete itemHeaders.authorization;
403
- delete itemHeaders.cookie;
404
- const bucketKey = stableStringify({
405
- endpoint: request.endpoint,
406
- authorization: request.headers.authorization ?? null,
407
- cookie: request.headers.cookie ?? null,
408
- credentials: request.credentials
409
- });
410
383
  return stableStringify({
411
- bucketKey,
412
- path: `${request.requestUrl.pathname}${request.requestUrl.search}`,
384
+ bucketKey: request.bucketKey,
385
+ path: request.itemPath,
413
386
  method: request.method,
414
- headers: itemHeaders,
387
+ headers: request.itemHeaders,
415
388
  body: null
416
389
  });
417
390
  };
@@ -429,26 +402,19 @@ function createBatchTransportQueue({ options, baseFetch, bucketRegistry }) {
429
402
  const itemId = `${Date.now().toString(36)}_${nextItemId.toString(36)}_${Math.random().toString(16).slice(2, 8)}`;
430
403
  nextItemId += 1;
431
404
  const itemHeaders = {
432
- ...request.headers
405
+ ...request.itemHeaders
433
406
  };
434
- delete itemHeaders.authorization;
435
- delete itemHeaders.cookie;
436
407
  if (preparedBody.body && preparedBody.inferredContentType && !itemHeaders['content-type']) itemHeaders['content-type'] = preparedBody.inferredContentType;
437
408
  const item = {
438
409
  id: itemId,
439
- path: `${request.requestUrl.pathname}${request.requestUrl.search}`,
410
+ path: request.itemPath,
440
411
  method: request.method,
441
412
  headers: itemHeaders,
442
413
  ...preparedBody.body ? {
443
414
  body: preparedBody.body
444
415
  } : {}
445
416
  };
446
- const bucketKey = stableStringify({
447
- endpoint: request.endpoint,
448
- authorization: request.headers.authorization ?? null,
449
- cookie: request.headers.cookie ?? null,
450
- credentials: request.credentials
451
- });
417
+ const { bucketKey } = request;
452
418
  const key = stableStringify({
453
419
  bucketKey,
454
420
  path: item.path,
@@ -542,13 +508,12 @@ function createBatchTransportQueue({ options, baseFetch, bucketRegistry }) {
542
508
  }
543
509
  }
544
510
  bucket.items.push(queued);
545
- bucket.bytes = measurePayload(bucket, bucket.items);
546
511
  emitDataBatchTransportEvent(onEvent, {
547
512
  type: 'enqueue',
548
513
  endpoint: request.endpoint,
549
514
  size: bucket.items.length
550
515
  });
551
- if (bucket.items.length >= maxBatchSize || bucket.bytes >= maxBatchBytes) {
516
+ if (bucket.items.length >= maxBatchSize || measurePayload(bucket, bucket.items) >= maxBatchBytes) {
552
517
  flushBucket(bucketKey);
553
518
  return queued.promise;
554
519
  }
@@ -1,4 +1,4 @@
1
- import { parseTraceparent } from "@modern-js/create-request";
1
+ import { parseTraceparent } from "@modern-js/runtime-extensions/request-context";
2
2
  function isAllZeroHex(value) {
3
3
  return /^0+$/.test(value);
4
4
  }
@@ -1,12 +1,27 @@
1
- import { AsyncLocalStorage } from "node:async_hooks";
2
- import { createEffectOperationContext, kEffectContextStorage } from "./operation-context.mjs";
3
1
  const globalStore = globalThis;
4
- const effectContextStorage = globalStore[kEffectContextStorage] ?? (globalStore[kEffectContextStorage] = new AsyncLocalStorage());
5
- const runWithEffectContext = (context, cb)=>effectContextStorage.run(context, cb);
2
+ const asyncHooks = globalStore.process?.getBuiltinModule?.('node:async_hooks');
3
+ const AsyncLocalStorage = asyncHooks?.AsyncLocalStorage;
4
+ if ('function' != typeof AsyncLocalStorage) throw new Error('[BFF][Effect] The edge runtime must provide AsyncLocalStorage. Enable Node.js compatibility or the nodejs_als compatibility flag.');
5
+ const EFFECT_BFF_CONTEXT_STORAGE_SHARE = '@modern-js/bff-effect/context-storage';
6
+ let effectContextStorage = new AsyncLocalStorage();
7
+ let effectContextStorageUsed = false;
8
+ const usedEffectContextStorage = ()=>{
9
+ effectContextStorageUsed = true;
10
+ return effectContextStorage;
11
+ };
12
+ const runWithEffectContext = (context, cb)=>usedEffectContextStorage().run(context, cb);
6
13
  const useEffectContext = ()=>{
7
- const context = effectContextStorage.getStore();
14
+ const context = usedEffectContextStorage().getStore();
8
15
  if (!context) throw new Error("Can't call useEffectContext out of Effect runtime scope");
9
16
  return context;
10
17
  };
18
+ const getEffectContextStorage = ()=>effectContextStorage;
19
+ function adoptEffectContextStorage(storage) {
20
+ const candidate = storage;
21
+ if ('function' != typeof candidate?.run || 'function' != typeof candidate.getStore) throw new Error(`[BFF][Effect] Share ${EFFECT_BFF_CONTEXT_STORAGE_SHARE} must provide an AsyncLocalStorage.`);
22
+ if (effectContextStorageUsed && candidate !== effectContextStorage) throw new Error('[BFF][Effect] A backend federation container received the host request storage after an Effect API already used its own. Evaluate exposes only after container init().');
23
+ effectContextStorage = candidate;
24
+ }
11
25
  const useOperationContext = ()=>useEffectContext().operationContext;
12
- export { createEffectOperationContext, runWithEffectContext, useEffectContext, useOperationContext };
26
+ export { createEffectOperationContext } from "./operation-context.mjs";
27
+ export { EFFECT_BFF_CONTEXT_STORAGE_SHARE, adoptEffectContextStorage, getEffectContextStorage, runWithEffectContext, useEffectContext, useOperationContext };
@@ -1,10 +1,10 @@
1
- import { evaluateCrossProjectPolicy, resolveCrossProjectRequestObservation } from "@modern-js/bff-core/security/cross-project-policy";
1
+ import { runWithEffectContext, useEffectContext, useOperationContext } from "@modern-js/bff-effect/context";
2
+ import { evaluateCrossProjectPolicy, resolveCrossProjectRequestObservation } from "@modern-js/server-runtime-extensions/bff-policy";
3
+ import * as __rspack_external_effect_Effect_41060786 from "effect/Effect";
2
4
  import { toHeaderRecord } from "../headers.mjs";
3
5
  import { dispatchEffectBffRequestWithContext } from "./dispatch.mjs";
4
- import { runWithEffectContext, useEffectContext, useOperationContext } from "./edge-context.mjs";
5
6
  import { resolveEffectBffModuleHandler } from "./module.mjs";
6
7
  import * as __rspack_external_effect_Config_76cfa59d from "effect/Config";
7
- import * as __rspack_external_effect_Effect_41060786 from "effect/Effect";
8
8
  import * as __rspack_external_effect_Layer_69c46453 from "effect/Layer";
9
9
  import * as __rspack_external_effect_Option_0498e63a from "effect/Option";
10
10
  import * as __rspack_external_effect_Schema_6065f72d from "effect/Schema";
@@ -90,9 +90,9 @@ async function createEffectBffEdgeDispatcher(options) {
90
90
  dispose: ()=>{
91
91
  disposePromise ??= (async ()=>{
92
92
  acceptingRequests = false;
93
- if (activeDispatches > 0) await new Promise((resolve)=>{
94
- resolveDrain = resolve;
95
- });
93
+ if (activeDispatches > 0) await __rspack_external_effect_Effect_41060786.runPromise(__rspack_external_effect_Effect_41060786.callback((resume)=>{
94
+ resolveDrain = ()=>resume(__rspack_external_effect_Effect_41060786["void"]);
95
+ }));
96
96
  await loaded.dispose?.();
97
97
  })();
98
98
  return disposePromise;
@@ -1 +1,4 @@
1
1
  export * from "./edge-dispatcher.mjs";
2
+ export { EFFECT_BFF_CONTEXT_STORAGE_SHARE } from "@modern-js/bff-effect/context";
3
+ export { EFFECT_BFF_HANDLER_FACTORY_REGISTRY_SHARE, adoptEffectBffShareScope } from "./entry-shape.mjs";
4
+ export { createEffectBffEdgeDispatcherFactory } from "./generated-entry.mjs";
@@ -1,8 +1,7 @@
1
- import { createOperationContractHash } from "@modern-js/bff-core";
1
+ import { createOperationContractHash } from "@modern-js/server-runtime-extensions/bff-policy/node";
2
2
  import { classifyEffectBffEntryModule, isValidatorAwareHandlerFactory } from "./entry-shape.mjs";
3
3
  function resolveEffectEndpointName(endpoint) {
4
4
  if ('string' == typeof endpoint.identifier && endpoint.identifier) return endpoint.identifier;
5
- if ('string' == typeof endpoint.name && endpoint.name) return endpoint.name;
6
5
  return '';
7
6
  }
8
7
  function ensureLeadingSlash(pathname) {
@@ -60,7 +59,7 @@ async function extractHttpApiFromModule(mod, isHttpApi) {
60
59
  isValidatorAwareHandlerFactory: isValidatorAwareHandlerFactory,
61
60
  isHttpApi
62
61
  });
63
- return !facts?.legacyShape && facts?.api !== void 0 && facts.hasRuntimeLayer && (void 0 === facts.createHandler || facts.createHandlerValidatorAware) ? facts.api : null;
62
+ return !facts?.unsupportedShape && facts?.api !== void 0 && facts.hasRuntimeLayer && (void 0 === facts.createHandler || facts.createHandlerValidatorAware) ? facts.api : null;
64
63
  }
65
64
  function createEffectEndpointContractHash(endpoint, requestId) {
66
65
  return createOperationContractHash(createEffectOperationContractSource(endpoint), requestId);
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  import { __webpack_require__ } from "../rslib-runtime~1.mjs";
3
3
  __webpack_require__.add({
4
- 1970 (module) {
4
+ Oz (module) {
5
5
  const validatorAwareHandlerFactories = new WeakSet();
6
6
  module.exports = {
7
7
  register (factory) {
@@ -14,4 +14,4 @@ __webpack_require__.add({
14
14
  };
15
15
  }
16
16
  });
17
- __webpack_require__("1970");
17
+ __webpack_require__("Oz");
@@ -1,3 +1,5 @@
1
+ import { EFFECT_BFF_CONTEXT_STORAGE_SHARE, adoptEffectContextStorage } from "@modern-js/bff-effect/context";
2
+ const EFFECT_BFF_HANDLER_FACTORY_REGISTRY_SHARE = '@modern-js/bff-effect/handler-factory-registry';
1
3
  function createLocalValidatorAwareHandlerFactoryRegistry() {
2
4
  const factories = new WeakSet();
3
5
  return {
@@ -10,12 +12,33 @@ function createLocalValidatorAwareHandlerFactoryRegistry() {
10
12
  }
11
13
  };
12
14
  }
13
- const validatorAwareHandlerFactoryRegistry = createLocalValidatorAwareHandlerFactoryRegistry();
15
+ let validatorAwareHandlerFactoryRegistry;
16
+ function handlerFactoryRegistry() {
17
+ validatorAwareHandlerFactoryRegistry ??= createLocalValidatorAwareHandlerFactoryRegistry();
18
+ return validatorAwareHandlerFactoryRegistry;
19
+ }
20
+ const adoptShared = (shareScope, name, adopt)=>{
21
+ const versions = 'object' == typeof shareScope && null !== shareScope ? shareScope[name] : void 0;
22
+ const shared = void 0 === versions ? void 0 : Object.values(versions)[0];
23
+ if ('function' != typeof shared?.get) return Promise.resolve();
24
+ return Promise.resolve(shared.get()).then((factory)=>adopt('function' == typeof factory ? factory() : void 0));
25
+ };
26
+ function adoptEffectBffShareScope(shareScope) {
27
+ return Promise.all([
28
+ adoptShared(shareScope, EFFECT_BFF_HANDLER_FACTORY_REGISTRY_SHARE, (registry)=>adoptHandlerFactoryRegistry(registry)),
29
+ adoptShared(shareScope, EFFECT_BFF_CONTEXT_STORAGE_SHARE, adoptEffectContextStorage)
30
+ ]).then(()=>void 0);
31
+ }
32
+ function adoptHandlerFactoryRegistry(registry) {
33
+ if ('function' != typeof registry?.register || 'function' != typeof registry.is) throw new Error(`[BFF][Effect] Share ${EFFECT_BFF_HANDLER_FACTORY_REGISTRY_SHARE} must provide a handler factory registry.`);
34
+ if (void 0 !== validatorAwareHandlerFactoryRegistry && validatorAwareHandlerFactoryRegistry !== registry) throw new Error('[BFF][Effect] A backend federation container received the host handler factory registry after an Effect API already used its own. Evaluate exposes only after container init().');
35
+ validatorAwareHandlerFactoryRegistry = registry;
36
+ }
14
37
  function registerValidatorAwareHandlerFactory(factory) {
15
- return validatorAwareHandlerFactoryRegistry.register(factory);
38
+ return handlerFactoryRegistry().register(factory);
16
39
  }
17
40
  function isValidatorAwareHandlerFactory(factory) {
18
- return validatorAwareHandlerFactoryRegistry.is(factory);
41
+ return handlerFactoryRegistry().is(factory);
19
42
  }
20
43
  const strictEffectApproachMessage = '[BFF][Effect] strictEffectApproach is enforced: Effect API entries export defineEffectBff(...) or { api, layer } HttpApi module. Raw handler exports, default request handlers, unbranded custom createHandler factories not valid Effect API entries.';
21
44
  function isEffectEntryRecord(value) {
@@ -34,13 +57,13 @@ function classifyEffectBffEntryModule(value, predicates) {
34
57
  if (predicates.isRequestHandler(module.handler)) return createEntryShapeFacts(module, predicates, '`handler` export');
35
58
  return createEntryShapeFacts(module, predicates);
36
59
  }
37
- function createEntryShapeFacts(module, predicates, legacyShape) {
60
+ function createEntryShapeFacts(module, predicates, unsupportedShape) {
38
61
  const createHandler = 'function' == typeof module.createHandler ? module.createHandler : void 0;
39
62
  const api = predicates.isHttpApi(module.api) ? module.api : void 0;
40
63
  const hasRuntimeLayer = void 0 !== module.layer;
41
64
  return {
42
65
  module,
43
- legacyShape,
66
+ unsupportedShape,
44
67
  createHandler,
45
68
  createHandlerValidatorAware: void 0 !== createHandler && predicates.isValidatorAwareHandlerFactory(createHandler),
46
69
  api,
@@ -48,4 +71,4 @@ function createEntryShapeFacts(module, predicates, legacyShape) {
48
71
  hasRuntimeLayer
49
72
  };
50
73
  }
51
- export { classifyEffectBffEntryModule, isValidatorAwareHandlerFactory, registerValidatorAwareHandlerFactory, strictEffectApproachMessage };
74
+ export { EFFECT_BFF_HANDLER_FACTORY_REGISTRY_SHARE, adoptEffectBffShareScope, classifyEffectBffEntryModule, isValidatorAwareHandlerFactory, registerValidatorAwareHandlerFactory, strictEffectApproachMessage };
@@ -0,0 +1,19 @@
1
+ import { createEffectBffEdgeDispatcher } from "./edge-dispatcher.mjs";
2
+ function createEffectBffEdgeDispatcherFactory(module, generatedOperationContracts) {
3
+ return (options)=>{
4
+ const policy = options?.crossProjectPolicy;
5
+ const crossProjectPolicy = null == policy || null === policy.expectedOperationContracts || 'object' != typeof policy.expectedOperationContracts || Array.isArray(policy.expectedOperationContracts) ? policy : {
6
+ ...policy,
7
+ expectedOperationContracts: {
8
+ ...policy.expectedOperationContracts,
9
+ ...generatedOperationContracts
10
+ }
11
+ };
12
+ return createEffectBffEdgeDispatcher({
13
+ ...options,
14
+ crossProjectPolicy,
15
+ module
16
+ });
17
+ };
18
+ }
19
+ export { createEffectBffEdgeDispatcherFactory };
@@ -1,7 +1,9 @@
1
1
  import { DEFAULT_DATA_BATCH_HEADER, DEFAULT_DATA_ENVELOPE_HEADER, decodeRequestEnvelopeHeader, isPlainObject, normalizeMethod } from "../../data-platform/index.mjs";
2
+ import { normalizeBatchLimits } from "../../data-platform/batch/options.mjs";
2
3
  import { decodeBatchBody, isBatchBody, toBatchResponseItem } from "../../data-platform/batch/protocol.mjs";
3
- import { BatchItemTimeoutError, createBatchValidationResponse, isBatchRequestPayload, mapWithConcurrency, normalizeBatchAllowedMethods, normalizeBatchPath, promiseWithTimeout, toBatchItemError } from "./batch.mjs";
4
+ import { BatchItemTimeoutError, createBatchValidationResponse, isBatchRequestPayload, mapWithConcurrency, normalizeBatchPath, promiseWithTimeout, toBatchItemError } from "./batch.mjs";
4
5
  import { getMountedPrefixFromContext, removeMountedPrefixFromBatchPath } from "./routing.mjs";
6
+ import * as __rspack_external_effect_Effect_41060786 from "effect/Effect";
5
7
  const HOP_BY_HOP_BATCH_ITEM_HEADERS = new Set([
6
8
  'connection',
7
9
  'keep-alive',
@@ -90,11 +92,9 @@ function createDataPlatformBatchRequestHandler(options) {
90
92
  const dataPlatformBatchOptions = options.dataPlatform?.batch;
91
93
  const batchEnabled = dataPlatformBatchOptions?.enabled !== false;
92
94
  const batchPath = normalizeBatchPath(dataPlatformBatchOptions?.endpoint);
93
- const batchMaxSize = Math.max(1, dataPlatformBatchOptions?.maxBatchSize ?? 16);
94
- const batchMaxBytes = Math.max(1024, dataPlatformBatchOptions?.maxBatchBytes ?? 65536);
95
+ const { maxBatchSize: batchMaxSize, maxBatchBytes: batchMaxBytes, allowedMethods: batchAllowedMethods } = normalizeBatchLimits(dataPlatformBatchOptions);
95
96
  const batchConcurrency = Math.max(1, dataPlatformBatchOptions?.maxConcurrency ?? 4);
96
97
  const batchItemTimeoutMs = Math.max(0, dataPlatformBatchOptions?.requestTimeoutMs ?? 10000);
97
- const batchAllowedMethods = normalizeBatchAllowedMethods(dataPlatformBatchOptions?.allowedMethods);
98
98
  const envelopeHeader = options.dataPlatform?.envelopeHeader || DEFAULT_DATA_ENVELOPE_HEADER;
99
99
  const normalizedEnvelopeHeader = envelopeHeader.toLowerCase();
100
100
  const handle = async (request, context)=>{
@@ -184,25 +184,25 @@ function createDataPlatformBatchRequestHandler(options) {
184
184
  return toBatchResponseItem(itemId, itemResponse, 'HEAD' === itemMethod);
185
185
  } catch (error) {
186
186
  if (error instanceof BatchItemTimeoutError) {
187
- console.error({
187
+ __rspack_external_effect_Effect_41060786.runSync(__rspack_external_effect_Effect_41060786.logError({
188
188
  event: 'bff.batch.item.timeout',
189
189
  batchId: payload.batchId,
190
190
  itemId,
191
191
  method: itemMethod,
192
192
  path: itemPathname,
193
193
  errorName: error.name
194
- });
194
+ }));
195
195
  return toBatchItemError(itemId, 504, 'Batch item request timed out');
196
196
  }
197
197
  if (error instanceof Response) return toBatchResponseItem(itemId, error, 'HEAD' === itemMethod);
198
- console.error({
198
+ __rspack_external_effect_Effect_41060786.runSync(__rspack_external_effect_Effect_41060786.logError({
199
199
  event: 'bff.batch.item.failure',
200
200
  batchId: payload.batchId,
201
201
  itemId,
202
202
  method: itemMethod,
203
203
  path: itemPathname,
204
204
  errorName: error instanceof Error ? error.name : 'UnknownError'
205
- });
205
+ }));
206
206
  return toBatchItemError(itemId, 500, 'Internal Server Error');
207
207
  } finally{
208
208
  request.signal.removeEventListener('abort', abortFromBatchRequest);