@bleedingdev/modern-js-bff-effect 3.9.0-ultramodern.8 → 3.9.3-ultramodern.1

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 (109) hide show
  1. package/dist/cjs/assembly.js +2 -2
  2. package/dist/cjs/data-platform/batch/options.js +48 -0
  3. package/dist/cjs/data-platform/batch/queue.js +48 -83
  4. package/dist/cjs/effect/context.js +28 -4
  5. package/dist/cjs/effect/edge-dispatcher.js +19 -19
  6. package/dist/cjs/effect/edge.js +26 -6
  7. package/dist/cjs/effect/entry-shape.js +38 -10
  8. package/dist/cjs/effect/handler/batch-handler.js +2 -3
  9. package/dist/cjs/effect/handler/batch.js +0 -9
  10. package/dist/cjs/effect/handler/http.js +1 -1
  11. package/dist/cjs/effect/handler/openapi.js +3 -3
  12. package/dist/cjs/effect/handler/rpc.js +2 -2
  13. package/dist/cjs/effect/handler.js +26 -26
  14. package/dist/cjs/effect/index.js +8 -8
  15. package/dist/cjs/effect/module.js +6 -2
  16. package/dist/cjs/effect/operation-context.js +3 -7
  17. package/dist/cjs/effect/rpcSerialization.js +1 -3
  18. package/dist/cjs/effect-client/cross-project.js +8 -11
  19. package/dist/cjs/effect-client/index.js +10 -10
  20. package/dist/cjs/microvertical-api.js +1 -1
  21. package/dist/esm/assembly.mjs +1 -1
  22. package/dist/esm/data-platform/batch/options.mjs +10 -0
  23. package/dist/esm/data-platform/batch/queue.mjs +48 -83
  24. package/dist/esm/effect/context.mjs +21 -6
  25. package/dist/esm/effect/edge-dispatcher.mjs +5 -5
  26. package/dist/esm/effect/edge.mjs +2 -0
  27. package/dist/esm/effect/entry-shape-registry.mjs +2 -2
  28. package/dist/esm/effect/entry-shape.mjs +27 -4
  29. package/dist/esm/effect/handler/batch-handler.mjs +3 -4
  30. package/dist/esm/effect/handler/batch.mjs +1 -7
  31. package/dist/esm/effect/handler/http.mjs +1 -1
  32. package/dist/esm/effect/handler/openapi.mjs +2 -2
  33. package/dist/esm/effect/handler/rpc.mjs +2 -2
  34. package/dist/esm/effect/handler.mjs +6 -6
  35. package/dist/esm/effect/index.mjs +1 -1
  36. package/dist/esm/effect/module.mjs +5 -1
  37. package/dist/esm/effect/operation-context.mjs +2 -3
  38. package/dist/esm/effect/rpcSerialization.mjs +1 -3
  39. package/dist/esm/effect-client/cross-project.mjs +8 -11
  40. package/dist/esm/effect-client/index.mjs +5 -5
  41. package/dist/esm/microvertical-api.mjs +1 -1
  42. package/dist/esm-node/assembly.mjs +1 -1
  43. package/dist/esm-node/data-platform/batch/options.mjs +11 -0
  44. package/dist/esm-node/data-platform/batch/queue.mjs +48 -83
  45. package/dist/esm-node/effect/context.mjs +21 -6
  46. package/dist/esm-node/effect/edge-dispatcher.mjs +5 -5
  47. package/dist/esm-node/effect/edge.mjs +2 -0
  48. package/dist/esm-node/effect/entry-shape.mjs +27 -4
  49. package/dist/esm-node/effect/handler/batch-handler.mjs +3 -4
  50. package/dist/esm-node/effect/handler/batch.mjs +1 -7
  51. package/dist/esm-node/effect/handler/http.mjs +1 -1
  52. package/dist/esm-node/effect/handler/openapi.mjs +2 -2
  53. package/dist/esm-node/effect/handler/rpc.mjs +2 -2
  54. package/dist/esm-node/effect/handler.mjs +6 -6
  55. package/dist/esm-node/effect/index.mjs +1 -1
  56. package/dist/esm-node/effect/module.mjs +5 -1
  57. package/dist/esm-node/effect/operation-context.mjs +2 -3
  58. package/dist/esm-node/effect/rpcSerialization.mjs +1 -3
  59. package/dist/esm-node/effect-client/cross-project.mjs +8 -11
  60. package/dist/esm-node/effect-client/index.mjs +5 -5
  61. package/dist/esm-node/microvertical-api.mjs +1 -1
  62. package/dist/types/assembly.d.ts +2 -2
  63. package/dist/types/data-platform/batch/options.d.ts +7 -0
  64. package/dist/types/data-platform/batch/queue.d.ts +0 -1
  65. package/dist/types/effect/context.d.ts +14 -1
  66. package/dist/types/effect/edge-dispatcher.d.ts +4 -4
  67. package/dist/types/effect/edge.d.ts +2 -0
  68. package/dist/types/effect/entry-shape.d.ts +14 -0
  69. package/dist/types/effect/handler/batch.d.ts +0 -1
  70. package/dist/types/effect/handler/definition.d.ts +2 -2
  71. package/dist/types/effect/handler/http.d.ts +2 -2
  72. package/dist/types/effect/handler/openapi.d.ts +2 -2
  73. package/dist/types/effect/handler/rpc.d.ts +1 -1
  74. package/dist/types/effect/handler/types.d.ts +5 -5
  75. package/dist/types/effect/handler.d.ts +5 -5
  76. package/dist/types/effect/module.d.ts +2 -1
  77. package/dist/types/effect/operation-context.d.ts +0 -1
  78. package/dist/types/effect/rpcSerialization.d.ts +1 -1
  79. package/dist/types/effect-client/cross-project.d.ts +2 -2
  80. package/dist/types/effect-client/index.d.ts +6 -6
  81. package/dist/types/microvertical-api.d.ts +4 -4
  82. package/package.json +39 -45
  83. package/src/assembly.ts +3 -2
  84. package/src/data-platform/batch/options.ts +20 -0
  85. package/src/data-platform/batch/queue.ts +61 -89
  86. package/src/effect/context.ts +64 -12
  87. package/src/effect/edge-dispatcher.ts +13 -12
  88. package/src/effect/edge.ts +5 -0
  89. package/src/effect/entry-shape.ts +97 -7
  90. package/src/effect/handler/batch-handler.ts +6 -12
  91. package/src/effect/handler/batch.ts +0 -12
  92. package/src/effect/handler/definition.ts +2 -3
  93. package/src/effect/handler/http.ts +4 -3
  94. package/src/effect/handler/openapi.ts +2 -2
  95. package/src/effect/handler/rpc.ts +3 -2
  96. package/src/effect/handler/types.ts +6 -12
  97. package/src/effect/handler.ts +5 -5
  98. package/src/effect/index.ts +1 -1
  99. package/src/effect/module.ts +8 -1
  100. package/src/effect/operation-context.ts +1 -5
  101. package/src/effect/rpcSerialization.ts +1 -3
  102. package/src/effect-client/cross-project.ts +11 -16
  103. package/src/effect-client/index.ts +11 -15
  104. package/src/microvertical-api.ts +1 -1
  105. package/dist/cjs/effect/edge-context.js +0 -61
  106. package/dist/esm/effect/edge-context.mjs +0 -14
  107. package/dist/esm-node/effect/edge-context.mjs +0 -15
  108. package/dist/types/effect/edge-context.d.ts +0 -5
  109. package/src/effect/edge-context.ts +0 -51
@@ -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,13 +1,13 @@
1
+ import { runWithEffectContext, useEffectContext, useOperationContext } from "@modern-js/bff-effect/context";
1
2
  import { evaluateCrossProjectPolicy, resolveCrossProjectRequestObservation } from "@modern-js/server-runtime-extensions/bff-policy";
2
3
  import * as __rspack_external_effect_Effect_41060786 from "effect/Effect";
3
4
  import { toHeaderRecord } from "../headers.mjs";
4
5
  import { dispatchEffectBffRequestWithContext } from "./dispatch.mjs";
5
- import { runWithEffectContext, useEffectContext, useOperationContext } from "./edge-context.mjs";
6
6
  import { resolveEffectBffModuleHandler } from "./module.mjs";
7
7
  import * as __rspack_external_effect_Config_76cfa59d from "effect/Config";
8
- import * as __rspack_external_effect_Layer_69c46453 from "effect/Layer";
9
8
  import * as __rspack_external_effect_Option_0498e63a from "effect/Option";
10
9
  import * as __rspack_external_effect_Schema_6065f72d from "effect/Schema";
10
+ import * as __rspack_external_effect_Layer_69c46453 from "effect/Layer";
11
11
  const NORMALIZED_POLICY_BOOLEAN_FIELDS = [
12
12
  'enabled',
13
13
  'requireEnvelope',
@@ -107,9 +107,9 @@ async function createEffectBffEdgeHandler(options) {
107
107
  dispose: dispatcher.dispose
108
108
  };
109
109
  }
110
- export { Cookies, Etag, FetchHttpClient, FindMyWay, Headers, HttpBody, HttpClient, HttpClientError, HttpClientRequest, HttpClientResponse, HttpEffect, HttpIncomingMessage, HttpMethod, HttpMiddleware, HttpPlatform, HttpRouter, HttpServer, HttpServerError, HttpServerRequest, HttpServerRespondable, HttpServerResponse, HttpStaticServer, HttpStatus, HttpTraceContext, Multipart, MultipartParser, Template, Url, UrlParams } from "effect/unstable/http";
111
- export { HttpApi, HttpApiBuilder, HttpApiClient, HttpApiEndpoint, HttpApiError, HttpApiGroup, HttpApiMiddleware, HttpApiSchema, HttpApiSecurity, HttpApiTest, OpenApi } from "effect/unstable/httpapi";
112
- export { Rpc, RpcClient, RpcClientError, RpcGroup, RpcMessage, RpcMiddleware, RpcSchema, RpcSerialization, RpcServer, RpcTest, RpcWorker, Utils } from "effect/unstable/rpc";
110
+ export { Cookies, Etag, FetchHttpClient, FindMyWay, Headers, HttpBody, HttpClient, HttpClientError, HttpClientRequest, HttpClientResponse, HttpEffect, HttpIncomingMessage, HttpMethod, HttpMiddleware, HttpPlatform, HttpRouter, HttpServer, HttpServerError, HttpServerRequest, HttpServerRespondable, HttpServerResponse, HttpStaticServer, HttpStatus, HttpTraceContext, Multipart, MultipartParser, Template, Url, UrlParams } from "effect/http";
111
+ export { HttpApi, HttpApiBuilder, HttpApiClient, HttpApiEndpoint, HttpApiError, HttpApiGroup, HttpApiMiddleware, HttpApiSchema, HttpApiSecurity, HttpApiTest, OpenApi } from "effect/http-api";
112
+ export { Rpc, RpcClient, RpcClientError, RpcGroup, RpcMessage, RpcMiddleware, RpcSchema, RpcSerialization, RpcServer, RpcTest, RpcWorker, Utils } from "effect/rpc";
113
113
  export { createHttpApiHandler, defineEffectBff, defineEffectRpcBff } from "./handler.mjs";
114
114
  export { createEffectOperationContext } from "./operation-context.mjs";
115
115
  export { __rspack_external_effect_Config_76cfa59d as Config, __rspack_external_effect_Effect_41060786 as Effect, __rspack_external_effect_Layer_69c46453 as Layer, __rspack_external_effect_Option_0498e63a as Option, __rspack_external_effect_Schema_6065f72d as Schema, createEffectBffEdgeDispatcher, createEffectBffEdgeHandler, createEffectBffTestHandler, dispatchEffectBffRequest, runWithEffectContext, useEffectContext, useOperationContext };
@@ -1,2 +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";
2
4
  export { createEffectBffEdgeDispatcherFactory } from "./generated-entry.mjs";
@@ -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) {
@@ -48,4 +71,4 @@ function createEntryShapeFacts(module, predicates, unsupportedShape) {
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 };
@@ -1,6 +1,7 @@
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";
5
6
  import * as __rspack_external_effect_Effect_41060786 from "effect/Effect";
6
7
  const HOP_BY_HOP_BATCH_ITEM_HEADERS = new Set([
@@ -91,11 +92,9 @@ function createDataPlatformBatchRequestHandler(options) {
91
92
  const dataPlatformBatchOptions = options.dataPlatform?.batch;
92
93
  const batchEnabled = dataPlatformBatchOptions?.enabled !== false;
93
94
  const batchPath = normalizeBatchPath(dataPlatformBatchOptions?.endpoint);
94
- const batchMaxSize = Math.max(1, dataPlatformBatchOptions?.maxBatchSize ?? 16);
95
- const batchMaxBytes = Math.max(1024, dataPlatformBatchOptions?.maxBatchBytes ?? 65536);
95
+ const { maxBatchSize: batchMaxSize, maxBatchBytes: batchMaxBytes, allowedMethods: batchAllowedMethods } = normalizeBatchLimits(dataPlatformBatchOptions);
96
96
  const batchConcurrency = Math.max(1, dataPlatformBatchOptions?.maxConcurrency ?? 4);
97
97
  const batchItemTimeoutMs = Math.max(0, dataPlatformBatchOptions?.requestTimeoutMs ?? 10000);
98
- const batchAllowedMethods = normalizeBatchAllowedMethods(dataPlatformBatchOptions?.allowedMethods);
99
98
  const envelopeHeader = options.dataPlatform?.envelopeHeader || DEFAULT_DATA_ENVELOPE_HEADER;
100
99
  const normalizedEnvelopeHeader = envelopeHeader.toLowerCase();
101
100
  const handle = async (request, context)=>{
@@ -6,12 +6,6 @@ function normalizeBatchPath(pathname) {
6
6
  if (!pathname.startsWith('/')) return `/${pathname}`;
7
7
  return pathname;
8
8
  }
9
- function normalizeBatchAllowedMethods(allowedMethods) {
10
- const source = Array.isArray(allowedMethods) && allowedMethods.length > 0 ? allowedMethods : [
11
- 'GET'
12
- ];
13
- return new Set(source.map((method)=>method.toUpperCase()));
14
- }
15
9
  function isBatchRequestPayload(value) {
16
10
  return isPlainObject(value) && 2 === value.protocolVersion && 'string' == typeof value.batchId && 'number' == typeof value.sentAt && Array.isArray(value.items);
17
11
  }
@@ -109,4 +103,4 @@ async function mapWithConcurrency(items, concurrency, mapper) {
109
103
  return output;
110
104
  }
111
105
  export { toHeaderRecord } from "../../headers.mjs";
112
- export { BatchItemTimeoutError, createBatchValidationResponse, isBatchRequestPayload, mapWithConcurrency, normalizeBatchAllowedMethods, normalizeBatchPath, prepareJsonRequestBody, promiseWithTimeout, toBatchItemError };
106
+ export { BatchItemTimeoutError, createBatchValidationResponse, isBatchRequestPayload, mapWithConcurrency, normalizeBatchPath, prepareJsonRequestBody, promiseWithTimeout, toBatchItemError };
@@ -1,4 +1,4 @@
1
- import { HttpRouter, HttpServer } from "effect/unstable/http";
1
+ import { HttpRouter, HttpServer } from "effect/http";
2
2
  import { prepareJsonRequestBody } from "./batch.mjs";
3
3
  import { createDataPlatformBatchRequestHandler } from "./batch-handler.mjs";
4
4
  import { validateDataPlatformRequestEnvelope } from "./envelope.mjs";
@@ -1,5 +1,5 @@
1
- import { HttpRouter, HttpServerResponse } from "effect/unstable/http";
2
- import { OpenApi } from "effect/unstable/httpapi";
1
+ import { HttpRouter, HttpServerResponse } from "effect/http";
2
+ import { OpenApi } from "effect/http-api";
3
3
  const DEFAULT_OPENAPI_PATH = '/openapi.json';
4
4
  function normalizeOpenApiPath(pathname) {
5
5
  if (!pathname.startsWith('/')) return `/${pathname}`;
@@ -1,5 +1,5 @@
1
- import { HttpRouter } from "effect/unstable/http";
2
- import { RpcServer } from "effect/unstable/rpc";
1
+ import { HttpRouter } from "effect/http";
2
+ import { RpcServer } from "effect/rpc";
3
3
  import { getRpcSerializationLayer } from "../rpcSerialization.mjs";
4
4
  import * as __rspack_external_effect_Layer_69c46453 from "effect/Layer";
5
5
  function normalizeRpcPath(pathname) {
@@ -1,13 +1,13 @@
1
1
  import * as __rspack_external_effect_Config_76cfa59d from "effect/Config";
2
2
  import * as __rspack_external_effect_Effect_41060786 from "effect/Effect";
3
- import * as __rspack_external_effect_Layer_69c46453 from "effect/Layer";
4
3
  import * as __rspack_external_effect_Option_0498e63a from "effect/Option";
5
4
  import * as __rspack_external_effect_Schema_6065f72d from "effect/Schema";
6
- export * from "effect/unstable/http";
7
- export * from "effect/unstable/httpapi";
8
- export * from "effect/unstable/rpc";
9
- export { HttpTraceContext } from "effect/unstable/http";
10
- export { HttpApiBuilder } from "effect/unstable/httpapi";
5
+ import * as __rspack_external_effect_Layer_69c46453 from "effect/Layer";
6
+ export * from "effect/http";
7
+ export * from "effect/http-api";
8
+ export * from "effect/rpc";
9
+ export { HttpTraceContext } from "effect/http";
10
+ export { HttpApiBuilder } from "effect/http-api";
11
11
  export { defineEffectBff, defineEffectRpcBff } from "./handler/definition.mjs";
12
12
  export { createHttpApiHandler } from "./handler/http.mjs";
13
13
  export { __rspack_external_effect_Config_76cfa59d as Config, __rspack_external_effect_Effect_41060786 as Effect, __rspack_external_effect_Layer_69c46453 as Layer, __rspack_external_effect_Option_0498e63a as Option, __rspack_external_effect_Schema_6065f72d as Schema };
@@ -1,7 +1,7 @@
1
1
  import * as __rspack_external__effect_opentelemetry_66324c75 from "@effect/opentelemetry";
2
2
  export * from "./endpoint-contracts.mjs";
3
3
  export * from "./handler.mjs";
4
- export { createEffectOperationContext, runWithEffectContext, useEffectContext, useOperationContext } from "./context.mjs";
4
+ export { createEffectOperationContext, runWithEffectContext, useEffectContext, useOperationContext } from "@modern-js/bff-effect/context";
5
5
  export { createEffectBffEdgeHandler, createEffectBffTestHandler, dispatchEffectBffRequest } from "./edge.mjs";
6
6
  export { resolveEffectBffModuleHandler } from "./module.mjs";
7
7
  export { __rspack_external__effect_opentelemetry_66324c75 as OpenTelemetry };
@@ -1,4 +1,4 @@
1
- import { HttpApi } from "effect/unstable/httpapi";
1
+ import { HttpApi } from "effect/http-api";
2
2
  import { classifyEffectBffEntryModule, isValidatorAwareHandlerFactory, strictEffectApproachMessage } from "./entry-shape.mjs";
3
3
  import { createHttpApiHandler } from "./handler.mjs";
4
4
  function isRequestHandler(value) {
@@ -42,6 +42,10 @@ function resolveClassifiedEffectBffModuleHandler(facts, options = {}) {
42
42
  if (facts.unsupportedShape) {
43
43
  if (rejectUnsupportedEffectModuleShape(options, facts.unsupportedShape)) return null;
44
44
  }
45
+ if (void 0 !== facts.module.rpc && !facts.createHandlerValidatorAware) {
46
+ rejectUnsupportedEffectModuleShape(options, 'unbranded RPC runtime');
47
+ return null;
48
+ }
45
49
  if ('function' == typeof facts.createHandler) {
46
50
  if (facts.createHandlerValidatorAware) {
47
51
  const factory = facts.createHandler;
@@ -1,5 +1,4 @@
1
1
  import { BFF_LOCALE_HEADER, BFF_OPERATION_CONTEXT_DETAIL_HEADER, BFF_OPERATION_CONTEXT_HEADER, BFF_TRACEPARENT_HEADER, parseTraceparent } from "@modern-js/runtime-extensions/request-context";
2
- const kEffectContextStorage = Symbol.for('modernjs.plugin-bff.effectContextStorage');
3
2
  const readHeader = (headers, header)=>{
4
3
  const value = headers.get(header);
5
4
  return value && value.length > 0 ? value : void 0;
@@ -54,7 +53,7 @@ const createEffectOperationContext = ({ request, path, method })=>{
54
53
  } : {},
55
54
  routePath: servicePath,
56
55
  method: (method || request.method || 'GET').toUpperCase(),
57
- source: 'effect-adapter',
56
+ source: 'effect-server',
58
57
  ...path && path !== servicePath ? {
59
58
  attributes: {
60
59
  mountedPath: path
@@ -72,4 +71,4 @@ const createEffectOperationContext = ({ request, path, method })=>{
72
71
  } : {}
73
72
  };
74
73
  };
75
- export { createEffectOperationContext, kEffectContextStorage };
74
+ export { createEffectOperationContext };
@@ -1,4 +1,4 @@
1
- import { RpcSerialization } from "effect/unstable/rpc";
1
+ import { RpcSerialization } from "effect/rpc";
2
2
  function getRpcSerializationLayer(serialization) {
3
3
  switch(serialization){
4
4
  case 'ndjson':
@@ -7,8 +7,6 @@ function getRpcSerializationLayer(serialization) {
7
7
  return RpcSerialization.layerJsonRpc();
8
8
  case 'ndJsonRpc':
9
9
  return RpcSerialization.layerNdJsonRpc();
10
- case 'msgPack':
11
- return RpcSerialization.layerMsgPack;
12
10
  default:
13
11
  return RpcSerialization.layerJsonRpc();
14
12
  }
@@ -1,6 +1,6 @@
1
- import { BFF_ENVELOPE_HEADER, BFF_OPERATION_CONTEXT_DETAIL_HEADER, BFF_OPERATION_CONTEXT_HEADER, resolveCrossProjectRequestObservation } from "@modern-js/server-runtime-extensions/bff-policy";
2
- import { HttpClient, HttpClientRequest } from "effect/unstable/http";
3
- import { HttpApi } from "effect/unstable/httpapi";
1
+ import { BFF_ENVELOPE_HEADER, BFF_OPERATION_CONTEXT_DETAIL_HEADER, BFF_OPERATION_CONTEXT_HEADER, digestOperationContract, resolveCrossProjectRequestObservation } from "@modern-js/server-runtime-extensions/bff-policy";
2
+ import { HttpClient, HttpClientRequest } from "effect/http";
3
+ import { HttpApi } from "effect/http-api";
4
4
  import * as __rspack_external_effect_Effect_41060786 from "effect/Effect";
5
5
  import * as __rspack_external_effect_Schema_6065f72d from "effect/Schema";
6
6
  const encodeJson = __rspack_external_effect_Schema_6065f72d.encodeSync(__rspack_external_effect_Schema_6065f72d.fromJsonString(__rspack_external_effect_Schema_6065f72d.Unknown));
@@ -30,14 +30,11 @@ function withCrossProjectPolicy(api, options, client) {
30
30
  const contract = observed && contracts[`${observed.method}:${observed.routePath}`];
31
31
  if (void 0 === contract) return __rspack_external_effect_Effect_41060786.die(new Error('[BFF][Effect] Request has no matching shared operation contract.'));
32
32
  return __rspack_external_effect_Effect_41060786.gen(function*() {
33
- const input = encodeJson({
34
- httpMethod: contract.method,
35
- name: contract.name,
36
- requestId: options.requestId,
37
- routePath: contract.routePath
38
- });
39
- const digest = yield* __rspack_external_effect_Effect_41060786.promise(()=>globalThis.crypto.subtle.digest('SHA-256', new TextEncoder().encode(input)));
40
- const schemaHash = Array.from(new Uint8Array(digest), (value)=>value.toString(16).padStart(2, '0')).join('');
33
+ const schemaHash = yield* __rspack_external_effect_Effect_41060786.promise(()=>digestOperationContract({
34
+ httpMethod: contract.method,
35
+ name: contract.name,
36
+ routePath: contract.routePath
37
+ }, options.requestId));
41
38
  return request.pipe(HttpClientRequest.setHeader(BFF_ENVELOPE_HEADER, encodeJson({
42
39
  requestId: options.requestId
43
40
  })), HttpClientRequest.setHeader(BFF_OPERATION_CONTEXT_HEADER, contract.operationId), HttpClientRequest.setHeader(BFF_OPERATION_CONTEXT_DETAIL_HEADER, encodeJson({
@@ -1,13 +1,13 @@
1
1
  import { createRequestContextHeaders } from "@modern-js/runtime-extensions/request-context";
2
2
  import * as __rspack_external_effect_Effect_41060786 from "effect/Effect";
3
+ import { FetchHttpClient, HttpClient, HttpClientRequest } from "effect/http";
4
+ import { HttpApi, HttpApiClient, HttpApiEndpoint, HttpApiGroup, HttpApiSchema } from "effect/http-api";
3
5
  import * as __rspack_external_effect_Layer_69c46453 from "effect/Layer";
4
- import { FetchHttpClient, HttpClient, HttpClientRequest } from "effect/unstable/http";
5
- import { HttpApi, HttpApiClient, HttpApiEndpoint, HttpApiGroup, HttpApiSchema } from "effect/unstable/httpapi";
6
- import { Rpc, RpcClient, RpcGroup, RpcSchema, RpcSerialization } from "effect/unstable/rpc";
6
+ import { Rpc, RpcClient, RpcGroup, RpcSchema, RpcSerialization } from "effect/rpc";
7
7
  import { getRpcSerializationLayer } from "../effect/rpcSerialization.mjs";
8
8
  import { withCrossProjectPolicy } from "./cross-project.mjs";
9
+ import * as __rspack_external_effect_http_HttpClientError_13c197e3 from "effect/http/HttpClientError";
9
10
  import * as __rspack_external_effect_Schema_6065f72d from "effect/Schema";
10
- import * as __rspack_external_effect_unstable_http_HttpClientError_4b9eaee6 from "effect/unstable/http/HttpClientError";
11
11
  import * as __rspack_external_effect_Data_2b3f4efb from "effect/Data";
12
12
  import * as __rspack_external_effect_Exit_1ca64b33 from "effect/Exit";
13
13
  import * as __rspack_external_effect_ManagedRuntime_bfe218e3 from "effect/ManagedRuntime";
@@ -109,4 +109,4 @@ function makeEffectRpcClient(group, options) {
109
109
  });
110
110
  }
111
111
  const runEffectRequest = __rspack_external_effect_Effect_41060786.runPromise;
112
- export { EffectRpcClientError, HttpApi, HttpApiClient, HttpApiEndpoint, HttpApiGroup, HttpApiSchema, Rpc, RpcClient, RpcGroup, RpcSchema, RpcSerialization, __rspack_external_effect_Effect_41060786 as Effect, __rspack_external_effect_Layer_69c46453 as Layer, __rspack_external_effect_Schema_6065f72d as Schema, __rspack_external_effect_unstable_http_HttpClientError_4b9eaee6 as HttpClientError, makeEffectHttpApiClient, makeEffectRpcClient, mask, runEffectRequest, runEffectView, view };
112
+ export { EffectRpcClientError, HttpApi, HttpApiClient, HttpApiEndpoint, HttpApiGroup, HttpApiSchema, Rpc, RpcClient, RpcGroup, RpcSchema, RpcSerialization, __rspack_external_effect_Effect_41060786 as Effect, __rspack_external_effect_Layer_69c46453 as Layer, __rspack_external_effect_Schema_6065f72d as Schema, __rspack_external_effect_http_HttpClientError_13c197e3 as HttpClientError, makeEffectHttpApiClient, makeEffectRpcClient, mask, runEffectRequest, runEffectView, view };
@@ -29,7 +29,7 @@ const MicroVerticalOperationSourceSchema = Schema.Literals([
29
29
  'client',
30
30
  'server',
31
31
  'generated-client',
32
- 'effect-adapter',
32
+ 'effect-server',
33
33
  'data-platform',
34
34
  'unknown'
35
35
  ]);
@@ -1,5 +1,5 @@
1
1
  import "node:module";
2
- import { HttpApiBuilder } from "effect/unstable/httpapi";
2
+ import { HttpApiBuilder } from "effect/http-api";
3
3
  import { defineEffectBff } from "./effect/handler/definition.mjs";
4
4
  import * as __rspack_external_effect_Layer_69c46453 from "effect/Layer";
5
5
  const assembleEffectBffRuntime = ({ api, handlers, transport })=>{
@@ -0,0 +1,11 @@
1
+ import "node:module";
2
+ function normalizeBatchLimits(options = {}) {
3
+ return {
4
+ maxBatchSize: Math.max(1, options.maxBatchSize ?? 16),
5
+ maxBatchBytes: Math.max(1024, options.maxBatchBytes ?? 65536),
6
+ allowedMethods: new Set((void 0 !== options.allowedMethods && options.allowedMethods.length > 0 ? options.allowedMethods : [
7
+ 'GET'
8
+ ]).map((method)=>method.toUpperCase()))
9
+ };
10
+ }
11
+ export { normalizeBatchLimits };
@@ -1,6 +1,7 @@
1
1
  import "node:module";
2
2
  import { stableStringify } from "../codec.mjs";
3
3
  import { DEFAULT_DATA_BATCH_HEADER } from "../types.mjs";
4
+ import { normalizeBatchLimits } from "./options.mjs";
4
5
  import { decodeBatchBody, isNullBodyStatus } from "./protocol.mjs";
5
6
  import { createBatchId, measureTextBytes, normalizeMethod, shouldBatchRequest, toHeaderRecord, toRequestBody } from "./request.mjs";
6
7
  import { isBatchResponsePayload, parseResponseLikeCreateRequest } from "./response.mjs";
@@ -79,7 +80,6 @@ class BatchBucketRegistry {
79
80
  if (existing) return existing;
80
81
  const next = {
81
82
  items: [],
82
- bytes: 0,
83
83
  batchId: createBatchId(),
84
84
  sentAt: Date.now(),
85
85
  timer: null,
@@ -98,12 +98,8 @@ class BatchBucketRegistry {
98
98
  }
99
99
  function createBatchTransportQueue({ options, baseFetch, bucketRegistry }) {
100
100
  const flushIntervalMs = Math.max(0, options.flushIntervalMs ?? 8);
101
- const maxBatchSize = Math.max(1, options.maxBatchSize ?? 16);
102
- const maxBatchBytes = Math.max(1024, options.maxBatchBytes ?? 65536);
101
+ const { maxBatchSize, maxBatchBytes, allowedMethods } = normalizeBatchLimits(options);
103
102
  const requestTimeoutMs = options.requestTimeoutMs;
104
- const allowedMethods = new Set((options.allowedMethods && options.allowedMethods.length > 0 ? options.allowedMethods : [
105
- 'GET'
106
- ]).map((method)=>method.toUpperCase()));
107
103
  const onEvent = options.onEvent;
108
104
  const buckets = bucketRegistry ?? new BatchBucketRegistry();
109
105
  const pendingByKey = new Map();
@@ -136,7 +132,6 @@ function createBatchTransportQueue({ options, baseFetch, bucketRegistry }) {
136
132
  const index = bucket.items.indexOf(request);
137
133
  if (-1 === index) return;
138
134
  bucket.items.splice(index, 1);
139
- bucket.bytes = measurePayload(bucket, bucket.items);
140
135
  if (0 === bucket.items.length && bucket.timer) {
141
136
  clearTimeout(bucket.timer);
142
137
  bucket.timer = null;
@@ -178,7 +173,11 @@ function createBatchTransportQueue({ options, baseFetch, bucketRegistry }) {
178
173
  if (!SAFE_REPLAY_METHODS.has(request.item.method)) throw new Error(`Batch result is unknown for ${request.item.method}; automatic replay is disabled (${reason}).`);
179
174
  return runSingle(request);
180
175
  };
181
- const settleAmbiguousBatchRequests = (items, reason)=>settleRequests(items, (request)=>runAfterAmbiguousBatch(request, reason));
176
+ const finishFlush = (bucketKey, bucket)=>{
177
+ bucket.flushing = false;
178
+ if (bucket.items.length > 0 && !bucket.timer) flushBucket(bucketKey);
179
+ buckets.releaseIfIdle(bucketKey, bucket);
180
+ };
182
181
  const flushBucket = async (bucketKey)=>{
183
182
  const bucket = buckets.get(bucketKey);
184
183
  if (!bucket || bucket.flushing) return;
@@ -195,7 +194,6 @@ function createBatchTransportQueue({ options, baseFetch, bucketRegistry }) {
195
194
  sentAt: bucket.sentAt
196
195
  };
197
196
  bucket.items = [];
198
- bucket.bytes = 0;
199
197
  rotatePayloadIdentity(bucket);
200
198
  const firstItem = items[0];
201
199
  if (!firstItem) {
@@ -211,14 +209,25 @@ function createBatchTransportQueue({ options, baseFetch, bucketRegistry }) {
211
209
  size: items.length,
212
210
  reason: disabledEndpoints.has(endpoint) ? 'batch-disabled' : void 0
213
211
  });
214
- await settleRequests(items, runSingle);
215
- bucket.flushing = false;
216
- if (bucket.items.length > 0 && !bucket.timer) flushBucket(bucketKey);
217
- buckets.releaseIfIdle(bucketKey, bucket);
212
+ try {
213
+ await settleRequests(items, runSingle);
214
+ } finally{
215
+ finishFlush(bucketKey, bucket);
216
+ }
218
217
  return;
219
218
  }
220
219
  const payload = createPayload(payloadIdentity, items);
221
220
  const batchId = payload.batchId;
221
+ const settleAmbiguousBatchRequests = (reason)=>{
222
+ emitDataBatchTransportEvent(onEvent, {
223
+ type: 'fallback',
224
+ endpoint,
225
+ batchId,
226
+ size: items.length,
227
+ reason
228
+ });
229
+ return settleRequests(items, (request)=>runAfterAmbiguousBatch(request, reason));
230
+ };
222
231
  emitDataBatchTransportEvent(onEvent, {
223
232
  type: 'flush',
224
233
  endpoint,
@@ -269,42 +278,13 @@ function createBatchTransportQueue({ options, baseFetch, bucketRegistry }) {
269
278
  batchId,
270
279
  reason: `batch-endpoint-unavailable-${String(response.status)}`
271
280
  });
272
- } else emitDataBatchTransportEvent(onEvent, {
273
- type: 'fallback',
274
- endpoint,
275
- batchId,
276
- size: items.length,
277
- reason: `batch-response-${String(response.status)}`
278
- });
279
- await settleAmbiguousBatchRequests(items, `batch-response-${String(response.status)}`);
280
- bucket.flushing = false;
281
+ await settleRequests(items, (request)=>runAfterAmbiguousBatch(request, `batch-response-${String(response.status)}`));
282
+ } else await settleAmbiguousBatchRequests(`batch-response-${String(response.status)}`);
281
283
  return;
282
284
  }
283
285
  const result = await runWithSignal(controller.signal, async ()=>response.json());
284
- if (!isBatchResponsePayload(result)) {
285
- emitDataBatchTransportEvent(onEvent, {
286
- type: 'fallback',
287
- endpoint,
288
- batchId,
289
- size: items.length,
290
- reason: 'invalid-batch-response'
291
- });
292
- await settleAmbiguousBatchRequests(items, 'invalid-batch-response');
293
- bucket.flushing = false;
294
- return;
295
- }
296
- if (result.batchId !== batchId) {
297
- emitDataBatchTransportEvent(onEvent, {
298
- type: 'fallback',
299
- endpoint,
300
- batchId,
301
- size: items.length,
302
- reason: 'mismatched-batch-id'
303
- });
304
- await settleAmbiguousBatchRequests(items, 'mismatched-batch-id');
305
- bucket.flushing = false;
306
- return;
307
- }
286
+ if (!isBatchResponsePayload(result)) return void await settleAmbiguousBatchRequests('invalid-batch-response');
287
+ if (result.batchId !== batchId) return void await settleAmbiguousBatchRequests('mismatched-batch-id');
308
288
  const itemMap = new Map();
309
289
  for (const item of result.items)itemMap.set(item.id, item);
310
290
  await settleRequests(items, async (request)=>{
@@ -328,19 +308,10 @@ function createBatchTransportQueue({ options, baseFetch, bucketRegistry }) {
328
308
  });
329
309
  return;
330
310
  }
331
- emitDataBatchTransportEvent(onEvent, {
332
- type: 'fallback',
333
- endpoint,
334
- batchId,
335
- size: items.length,
336
- reason: 'batch-transport-error'
337
- });
338
- await settleAmbiguousBatchRequests(items, 'batch-transport-error');
311
+ await settleAmbiguousBatchRequests('batch-transport-error');
339
312
  } finally{
340
313
  for (const item of items)item.abortBatchIfUnused = void 0;
341
- bucket.flushing = false;
342
- if (bucket.items.length > 0 && !bucket.timer) flushBucket(bucketKey);
343
- buckets.releaseIfIdle(bucketKey, bucket);
314
+ finishFlush(bucketKey, bucket);
344
315
  }
345
316
  };
346
317
  const pendingReadPromises = new Map();
@@ -364,7 +335,20 @@ function createBatchTransportQueue({ options, baseFetch, bucketRegistry }) {
364
335
  const sourceSignal = initDefinesSignal ? initSignal ?? void 0 : sourceRequest?.signal;
365
336
  const requestUrl = toAbsoluteUrl(input);
366
337
  const endpoint = normalizeBatchEndpoint(requestUrl, options.endpoint).toString();
338
+ const itemHeaders = {
339
+ ...headers
340
+ };
341
+ delete itemHeaders.authorization;
342
+ delete itemHeaders.cookie;
367
343
  return {
344
+ itemHeaders,
345
+ itemPath: `${requestUrl.pathname}${requestUrl.search}`,
346
+ bucketKey: stableStringify({
347
+ endpoint,
348
+ authorization: headers.authorization ?? null,
349
+ cookie: headers.cookie ?? null,
350
+ credentials
351
+ }),
368
352
  requestUrl,
369
353
  endpoint,
370
354
  method,
@@ -397,22 +381,11 @@ function createBatchTransportQueue({ options, baseFetch, bucketRegistry }) {
397
381
  batchEndpoint: request.endpoint,
398
382
  requestUrl: request.requestUrl
399
383
  })) return;
400
- const itemHeaders = {
401
- ...request.headers
402
- };
403
- delete itemHeaders.authorization;
404
- delete itemHeaders.cookie;
405
- const bucketKey = stableStringify({
406
- endpoint: request.endpoint,
407
- authorization: request.headers.authorization ?? null,
408
- cookie: request.headers.cookie ?? null,
409
- credentials: request.credentials
410
- });
411
384
  return stableStringify({
412
- bucketKey,
413
- path: `${request.requestUrl.pathname}${request.requestUrl.search}`,
385
+ bucketKey: request.bucketKey,
386
+ path: request.itemPath,
414
387
  method: request.method,
415
- headers: itemHeaders,
388
+ headers: request.itemHeaders,
416
389
  body: null
417
390
  });
418
391
  };
@@ -430,26 +403,19 @@ function createBatchTransportQueue({ options, baseFetch, bucketRegistry }) {
430
403
  const itemId = `${Date.now().toString(36)}_${nextItemId.toString(36)}_${Math.random().toString(16).slice(2, 8)}`;
431
404
  nextItemId += 1;
432
405
  const itemHeaders = {
433
- ...request.headers
406
+ ...request.itemHeaders
434
407
  };
435
- delete itemHeaders.authorization;
436
- delete itemHeaders.cookie;
437
408
  if (preparedBody.body && preparedBody.inferredContentType && !itemHeaders['content-type']) itemHeaders['content-type'] = preparedBody.inferredContentType;
438
409
  const item = {
439
410
  id: itemId,
440
- path: `${request.requestUrl.pathname}${request.requestUrl.search}`,
411
+ path: request.itemPath,
441
412
  method: request.method,
442
413
  headers: itemHeaders,
443
414
  ...preparedBody.body ? {
444
415
  body: preparedBody.body
445
416
  } : {}
446
417
  };
447
- const bucketKey = stableStringify({
448
- endpoint: request.endpoint,
449
- authorization: request.headers.authorization ?? null,
450
- cookie: request.headers.cookie ?? null,
451
- credentials: request.credentials
452
- });
418
+ const { bucketKey } = request;
453
419
  const key = stableStringify({
454
420
  bucketKey,
455
421
  path: item.path,
@@ -543,13 +509,12 @@ function createBatchTransportQueue({ options, baseFetch, bucketRegistry }) {
543
509
  }
544
510
  }
545
511
  bucket.items.push(queued);
546
- bucket.bytes = measurePayload(bucket, bucket.items);
547
512
  emitDataBatchTransportEvent(onEvent, {
548
513
  type: 'enqueue',
549
514
  endpoint: request.endpoint,
550
515
  size: bucket.items.length
551
516
  });
552
- if (bucket.items.length >= maxBatchSize || bucket.bytes >= maxBatchBytes) {
517
+ if (bucket.items.length >= maxBatchSize || measurePayload(bucket, bucket.items) >= maxBatchBytes) {
553
518
  flushBucket(bucketKey);
554
519
  return queued.promise;
555
520
  }