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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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,4 +1,6 @@
1
1
  // @effect-diagnostics anyUnknownInErrorContext:off asyncFunction:off strictBooleanExpressions:off
2
+
3
+ import { runWithEffectContext } from '@modern-js/bff-effect/context';
2
4
  import {
3
5
  evaluateCrossProjectPolicy,
4
6
  type NormalizedCrossProjectPolicy,
@@ -10,7 +12,6 @@ import {
10
12
  type DispatchEffectBffRequestOptions,
11
13
  dispatchEffectBffRequestWithContext,
12
14
  } from './dispatch';
13
- import { runWithEffectContext } from './edge-context';
14
15
  import type {
15
16
  EffectBffOpenApiConfig,
16
17
  EffectDataPlatformValidationOptions,
@@ -22,11 +23,13 @@ import {
22
23
  } from './module';
23
24
  import type { EffectContext } from './operation-context';
24
25
 
26
+ export {
27
+ runWithEffectContext,
28
+ useEffectContext,
29
+ useOperationContext,
30
+ } from '@modern-js/bff-effect/context';
25
31
  export * as Config from 'effect/Config';
26
32
  export * as Effect from 'effect/Effect';
27
- export * as Layer from 'effect/Layer';
28
- export * as Option from 'effect/Option';
29
- export * as Schema from 'effect/Schema';
30
33
  export {
31
34
  Cookies,
32
35
  Etag,
@@ -57,7 +60,7 @@ export {
57
60
  Template,
58
61
  Url,
59
62
  UrlParams,
60
- } from 'effect/unstable/http';
63
+ } from 'effect/http';
61
64
  export {
62
65
  HttpApi,
63
66
  HttpApiBuilder,
@@ -70,7 +73,9 @@ export {
70
73
  HttpApiSecurity,
71
74
  HttpApiTest,
72
75
  OpenApi,
73
- } from 'effect/unstable/httpapi';
76
+ } from 'effect/http-api';
77
+ export * as Layer from 'effect/Layer';
78
+ export * as Option from 'effect/Option';
74
79
  export {
75
80
  Rpc,
76
81
  RpcClient,
@@ -84,12 +89,8 @@ export {
84
89
  RpcTest,
85
90
  RpcWorker,
86
91
  Utils,
87
- } from 'effect/unstable/rpc';
88
- export {
89
- runWithEffectContext,
90
- useEffectContext,
91
- useOperationContext,
92
- } from './edge-context';
92
+ } from 'effect/rpc';
93
+ export * as Schema from 'effect/Schema';
93
94
  export type {
94
95
  EffectApiClientFromApi,
95
96
  EffectBffDefinition,
@@ -1,2 +1,7 @@
1
+ export { EFFECT_BFF_CONTEXT_STORAGE_SHARE } from '@modern-js/bff-effect/context';
1
2
  export * from './edge-dispatcher';
3
+ export {
4
+ adoptEffectBffShareScope,
5
+ EFFECT_BFF_HANDLER_FACTORY_REGISTRY_SHARE,
6
+ } from './entry-shape';
2
7
  export { createEffectBffEdgeDispatcherFactory } from './generated-entry';
@@ -1,8 +1,21 @@
1
+ import {
2
+ adoptEffectContextStorage,
3
+ EFFECT_BFF_CONTEXT_STORAGE_SHARE,
4
+ } from '@modern-js/bff-effect/context';
5
+ import type { EffectRpcBffDefinition } from './handler/types';
6
+
1
7
  type ValidatorAwareHandlerFactoryRegistry = {
2
8
  register<TFactory extends Function>(factory: TFactory): TFactory;
3
9
  is(factory: unknown): boolean;
4
10
  };
5
11
 
12
+ /**
13
+ * Module Federation share through which a backend federation host hands its
14
+ * package-private handler factory registry to the containers it initializes.
15
+ */
16
+ export const EFFECT_BFF_HANDLER_FACTORY_REGISTRY_SHARE =
17
+ '@modern-js/bff-effect/handler-factory-registry';
18
+
6
19
  function createLocalValidatorAwareHandlerFactoryRegistry(): ValidatorAwareHandlerFactoryRegistry {
7
20
  const factories = new WeakSet<Function>();
8
21
  return {
@@ -19,6 +32,8 @@ function createLocalValidatorAwareHandlerFactoryRegistry(): ValidatorAwareHandle
19
32
  function loadNodeValidatorAwareHandlerFactoryRegistry(): ValidatorAwareHandlerFactoryRegistry {
20
33
  const moduleUrl = import.meta.url;
21
34
  if (typeof moduleUrl !== 'string' || !moduleUrl.startsWith('file:')) {
35
+ // A bundled backend federation container has no file URL; its host share
36
+ // arrives through adoptEffectBffShareScope() during container init.
22
37
  return createLocalValidatorAwareHandlerFactoryRegistry();
23
38
  }
24
39
 
@@ -44,15 +59,90 @@ function loadNodeValidatorAwareHandlerFactoryRegistry(): ValidatorAwareHandlerFa
44
59
 
45
60
  declare const __MODERN_EFFECT_NODE_RUNTIME__: boolean;
46
61
 
47
- const validatorAwareHandlerFactoryRegistry =
48
- typeof __MODERN_EFFECT_NODE_RUNTIME__ !== 'undefined' &&
49
- __MODERN_EFFECT_NODE_RUNTIME__
50
- ? loadNodeValidatorAwareHandlerFactoryRegistry()
51
- : createLocalValidatorAwareHandlerFactoryRegistry();
62
+ let validatorAwareHandlerFactoryRegistry:
63
+ | ValidatorAwareHandlerFactoryRegistry
64
+ | undefined;
65
+
66
+ function handlerFactoryRegistry(): ValidatorAwareHandlerFactoryRegistry {
67
+ validatorAwareHandlerFactoryRegistry ??=
68
+ typeof __MODERN_EFFECT_NODE_RUNTIME__ !== 'undefined' &&
69
+ __MODERN_EFFECT_NODE_RUNTIME__
70
+ ? loadNodeValidatorAwareHandlerFactoryRegistry()
71
+ : createLocalValidatorAwareHandlerFactoryRegistry();
72
+ return validatorAwareHandlerFactoryRegistry;
73
+ }
74
+
75
+ type SharedVersions = Record<string, { get?: () => unknown } | undefined>;
76
+
77
+ const adoptShared = (
78
+ shareScope: unknown,
79
+ name: string,
80
+ adopt: (value: unknown) => void,
81
+ ): Promise<void> => {
82
+ const versions =
83
+ typeof shareScope === 'object' && shareScope !== null
84
+ ? (shareScope as Record<string, SharedVersions | undefined>)[name]
85
+ : undefined;
86
+ const shared =
87
+ versions === undefined ? undefined : Object.values(versions)[0];
88
+ if (typeof shared?.get !== 'function') {
89
+ return Promise.resolve();
90
+ }
91
+ return Promise.resolve(shared.get()).then(factory =>
92
+ adopt(typeof factory === 'function' ? factory() : undefined),
93
+ );
94
+ };
95
+
96
+ /**
97
+ * @internal Called by generated backend federation containers from `init()`,
98
+ * before any expose evaluates, so factories created by `defineEffectBff`
99
+ * register with the host's registry and endpoints read the host's request
100
+ * storage instead of bundle-local ones.
101
+ */
102
+ export function adoptEffectBffShareScope(shareScope: unknown): Promise<void> {
103
+ return Promise.all([
104
+ adoptShared(
105
+ shareScope,
106
+ EFFECT_BFF_HANDLER_FACTORY_REGISTRY_SHARE,
107
+ registry =>
108
+ adoptHandlerFactoryRegistry(
109
+ registry as ValidatorAwareHandlerFactoryRegistry | undefined,
110
+ ),
111
+ ),
112
+ adoptShared(
113
+ shareScope,
114
+ EFFECT_BFF_CONTEXT_STORAGE_SHARE,
115
+ adoptEffectContextStorage,
116
+ ),
117
+ ]).then(() => undefined);
118
+ }
119
+
120
+ function adoptHandlerFactoryRegistry(
121
+ registry: ValidatorAwareHandlerFactoryRegistry | undefined,
122
+ ): void {
123
+ if (
124
+ typeof registry?.register !== 'function' ||
125
+ typeof registry.is !== 'function'
126
+ ) {
127
+ throw new Error(
128
+ `[BFF][Effect] Share ${EFFECT_BFF_HANDLER_FACTORY_REGISTRY_SHARE} must provide a handler factory registry.`,
129
+ );
130
+ }
131
+ if (
132
+ validatorAwareHandlerFactoryRegistry !== undefined &&
133
+ validatorAwareHandlerFactoryRegistry !== registry
134
+ ) {
135
+ throw new Error(
136
+ '[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().',
137
+ );
138
+ }
139
+ validatorAwareHandlerFactoryRegistry = registry;
140
+ }
52
141
 
53
142
  type EffectBffEntryModule = {
54
143
  api?: unknown;
55
144
  layer?: unknown;
145
+ rpc?: EffectRpcBffDefinition;
56
146
  handler?: unknown;
57
147
  createHandler?: unknown;
58
148
  default?: unknown;
@@ -82,7 +172,7 @@ type EffectBffEntryShapePredicates = {
82
172
  export function registerValidatorAwareHandlerFactory<TFactory extends Function>(
83
173
  factory: TFactory,
84
174
  ): TFactory {
85
- return validatorAwareHandlerFactoryRegistry.register(factory);
175
+ return handlerFactoryRegistry().register(factory);
86
176
  }
87
177
 
88
178
  /**
@@ -90,7 +180,7 @@ export function registerValidatorAwareHandlerFactory<TFactory extends Function>(
90
180
  * therefore forwards strict cross-project validation into createHttpApiHandler.
91
181
  */
92
182
  export function isValidatorAwareHandlerFactory(factory: unknown): boolean {
93
- return validatorAwareHandlerFactoryRegistry.is(factory);
183
+ return handlerFactoryRegistry().is(factory);
94
184
  }
95
185
 
96
186
  export const strictEffectApproachMessage =
@@ -8,6 +8,7 @@ import {
8
8
  isPlainObject,
9
9
  normalizeMethod as normalizeItemMethod,
10
10
  } from '../../data-platform';
11
+ import { normalizeBatchLimits } from '../../data-platform/batch/options';
11
12
  import {
12
13
  decodeBatchBody,
13
14
  isBatchBody,
@@ -18,7 +19,6 @@ import {
18
19
  createBatchValidationResponse,
19
20
  isBatchRequestPayload,
20
21
  mapWithConcurrency,
21
- normalizeBatchAllowedMethods,
22
22
  normalizeBatchPath,
23
23
  promiseWithTimeout,
24
24
  toBatchItemError,
@@ -129,14 +129,11 @@ export function createDataPlatformBatchRequestHandler<TContext>(options: {
129
129
  const dataPlatformBatchOptions = options.dataPlatform?.batch;
130
130
  const batchEnabled = dataPlatformBatchOptions?.enabled !== false;
131
131
  const batchPath = normalizeBatchPath(dataPlatformBatchOptions?.endpoint);
132
- const batchMaxSize = Math.max(
133
- 1,
134
- dataPlatformBatchOptions?.maxBatchSize ?? 16,
135
- );
136
- const batchMaxBytes = Math.max(
137
- 1024,
138
- dataPlatformBatchOptions?.maxBatchBytes ?? 64 * 1024,
139
- );
132
+ const {
133
+ maxBatchSize: batchMaxSize,
134
+ maxBatchBytes: batchMaxBytes,
135
+ allowedMethods: batchAllowedMethods,
136
+ } = normalizeBatchLimits(dataPlatformBatchOptions);
140
137
  const batchConcurrency = Math.max(
141
138
  1,
142
139
  dataPlatformBatchOptions?.maxConcurrency ?? 4,
@@ -145,9 +142,6 @@ export function createDataPlatformBatchRequestHandler<TContext>(options: {
145
142
  0,
146
143
  dataPlatformBatchOptions?.requestTimeoutMs ?? 10_000,
147
144
  );
148
- const batchAllowedMethods = normalizeBatchAllowedMethods(
149
- dataPlatformBatchOptions?.allowedMethods,
150
- );
151
145
  const envelopeHeader =
152
146
  options.dataPlatform?.envelopeHeader || DEFAULT_DATA_ENVELOPE_HEADER;
153
147
  const normalizedEnvelopeHeader = envelopeHeader.toLowerCase();
@@ -6,11 +6,9 @@ import {
6
6
  type DataBatchResponseItem,
7
7
  DEFAULT_DATA_BATCH_ENDPOINT,
8
8
  isPlainObject,
9
- measureTextBytes,
10
9
  normalizeMethod as normalizeItemMethod,
11
10
  } from '../../data-platform';
12
11
  import { encodeBatchText } from '../../data-platform/batch/protocol';
13
- import { toHeaderRecord } from '../../headers';
14
12
 
15
13
  export { toHeaderRecord } from '../../headers';
16
14
 
@@ -24,16 +22,6 @@ export function normalizeBatchPath(pathname: string | undefined) {
24
22
  return pathname as `/${string}`;
25
23
  }
26
24
 
27
- export function normalizeBatchAllowedMethods(
28
- allowedMethods: string[] | undefined,
29
- ) {
30
- const source =
31
- Array.isArray(allowedMethods) && allowedMethods.length > 0
32
- ? allowedMethods
33
- : ['GET'];
34
- return new Set(source.map(method => method.toUpperCase()));
35
- }
36
-
37
25
  type ParsedBatchRequestPayload = Omit<DataBatchRequestPayload, 'items'> & {
38
26
  items: unknown[];
39
27
  };
@@ -1,6 +1,6 @@
1
1
  // @effect-diagnostics anyUnknownInErrorContext:off asyncFunction:off globalDate:off globalTimers:off newPromise:off strictBooleanExpressions:off
2
- import type { HttpApi } from 'effect/unstable/httpapi';
3
- import type { Rpc } from 'effect/unstable/rpc';
2
+ import type { HttpApi } from 'effect/http-api';
3
+ import type { Rpc } from 'effect/rpc';
4
4
 
5
5
  import { registerValidatorAwareHandlerFactory } from '../entry-shape';
6
6
  import { mergeDataPlatformOptions } from './envelope';
@@ -10,7 +10,6 @@ import type {
10
10
  EffectBffDefinition,
11
11
  EffectBffHandlerFactory,
12
12
  EffectBffRuntime,
13
- EffectDataPlatformValidationOptions,
14
13
  EffectRpcBffDefinition,
15
14
  EffectRpcBffHandlerFactory,
16
15
  EffectRpcRuntimeLayer,
@@ -1,8 +1,9 @@
1
1
  // @effect-diagnostics anyUnknownInErrorContext:off asyncFunction:off globalDate:off globalTimers:off newPromise:off strictBooleanExpressions:off
2
+
3
+ import { HttpRouter, HttpServer } from 'effect/http';
4
+ import type { HttpApi } from 'effect/http-api';
2
5
  import * as Layer from 'effect/Layer';
3
- import { HttpRouter, HttpServer } from 'effect/unstable/http';
4
- import type { HttpApi } from 'effect/unstable/httpapi';
5
- import type { Rpc } from 'effect/unstable/rpc';
6
+ import type { Rpc } from 'effect/rpc';
6
7
 
7
8
  import { prepareJsonRequestBody } from './batch';
8
9
  import { createDataPlatformBatchRequestHandler } from './batch-handler';
@@ -1,6 +1,6 @@
1
1
  // @effect-diagnostics anyUnknownInErrorContext:off asyncFunction:off globalDate:off globalTimers:off newPromise:off strictBooleanExpressions:off
2
- import { HttpRouter, HttpServerResponse } from 'effect/unstable/http';
3
- import { type HttpApi, OpenApi } from 'effect/unstable/httpapi';
2
+ import { HttpRouter, HttpServerResponse } from 'effect/http';
3
+ import { type HttpApi, OpenApi } from 'effect/http-api';
4
4
 
5
5
  import type { EffectBffOpenApiConfig } from './types';
6
6
 
@@ -1,7 +1,8 @@
1
1
  // @effect-diagnostics anyUnknownInErrorContext:off asyncFunction:off globalDate:off globalTimers:off newPromise:off strictBooleanExpressions:off
2
+
3
+ import { HttpRouter } from 'effect/http';
2
4
  import * as Layer from 'effect/Layer';
3
- import { HttpRouter } from 'effect/unstable/http';
4
- import { type Rpc, RpcServer } from 'effect/unstable/rpc';
5
+ import { type Rpc, RpcServer } from 'effect/rpc';
5
6
 
6
7
  import { getRpcSerializationLayer } from '../rpcSerialization';
7
8
  import type { EffectRpcBffDefinition } from './types';
@@ -1,15 +1,10 @@
1
1
  // @effect-diagnostics anyUnknownInErrorContext:off asyncFunction:off globalDate:off globalTimers:off newPromise:off strictBooleanExpressions:off
2
2
  import type { FileSystem, Path } from 'effect';
3
3
  import * as Context from 'effect/Context';
4
- import type * as EffectType from 'effect/Effect';
4
+ import type { Etag, HttpPlatform, HttpRouter } from 'effect/http';
5
+ import type { HttpApi, HttpApiClient, HttpApiGroup } from 'effect/http-api';
5
6
  import type * as Layer from 'effect/Layer';
6
- import type { Etag, HttpPlatform, HttpRouter } from 'effect/unstable/http';
7
- import type {
8
- HttpApi,
9
- HttpApiClient,
10
- HttpApiGroup,
11
- } from 'effect/unstable/httpapi';
12
- import type { Rpc, RpcGroup } from 'effect/unstable/rpc';
7
+ import type { Rpc, RpcGroup } from 'effect/rpc';
13
8
 
14
9
  import type { createHttpApiHandler } from './http';
15
10
  import type { createRpcApiHandler } from './rpc';
@@ -43,8 +38,7 @@ export type EffectRpcSerialization =
43
38
  | 'json'
44
39
  | 'ndjson'
45
40
  | 'jsonRpc'
46
- | 'ndJsonRpc'
47
- | 'msgPack';
41
+ | 'ndJsonRpc';
48
42
 
49
43
  export type EffectRpcRuntimeLayer<TRpcs extends Rpc.Any = Rpc.Any> =
50
44
  Layer.Layer<
@@ -201,8 +195,8 @@ export type EffectRequestInterceptor = (options: {
201
195
  }) => Response | Promise<Response>;
202
196
 
203
197
  export type EffectBffHandlerFactory<
204
- TApi extends HttpApi.Constraint = HttpApi.Top,
205
- TLayer extends EffectRuntimeLayer = EffectRuntimeLayer,
198
+ _TApi extends HttpApi.Constraint = HttpApi.Top,
199
+ _TLayer extends EffectRuntimeLayer = EffectRuntimeLayer,
206
200
  > = (options?: {
207
201
  openapi?: EffectBffOpenApiConfig;
208
202
  rpc?: Partial<EffectRpcBffHandlerOptions>;
@@ -1,14 +1,14 @@
1
1
  // @effect-diagnostics anyUnknownInErrorContext:off asyncFunction:off globalDate:off globalTimers:off newPromise:off strictBooleanExpressions:off
2
2
  export * as Config from 'effect/Config';
3
3
  export * as Effect from 'effect/Effect';
4
+ export * from 'effect/http';
5
+ export { HttpTraceContext } from 'effect/http';
6
+ export * from 'effect/http-api';
7
+ export { HttpApiBuilder } from 'effect/http-api';
4
8
  export * as Layer from 'effect/Layer';
5
9
  export * as Option from 'effect/Option';
10
+ export * from 'effect/rpc';
6
11
  export * as Schema from 'effect/Schema';
7
- export * from 'effect/unstable/http';
8
- export { HttpTraceContext } from 'effect/unstable/http';
9
- export * from 'effect/unstable/httpapi';
10
- export { HttpApiBuilder } from 'effect/unstable/httpapi';
11
- export * from 'effect/unstable/rpc';
12
12
 
13
13
  export { defineEffectBff, defineEffectRpcBff } from './handler/definition';
14
14
  export { createHttpApiHandler } from './handler/http';
@@ -6,7 +6,7 @@ export {
6
6
  runWithEffectContext,
7
7
  useEffectContext,
8
8
  useOperationContext,
9
- } from './context';
9
+ } from '@modern-js/bff-effect/context';
10
10
  export {
11
11
  createEffectBffEdgeHandler,
12
12
  createEffectBffTestHandler,
@@ -1,6 +1,6 @@
1
1
  // @effect-diagnostics strictBooleanExpressions:off
2
2
  import type * as EffectServiceContext from 'effect/Context';
3
- import { HttpApi } from 'effect/unstable/httpapi';
3
+ import { HttpApi } from 'effect/http-api';
4
4
  import {
5
5
  classifyEffectBffEntryModule,
6
6
  type EffectBffEntryShapeFacts,
@@ -12,6 +12,7 @@ import {
12
12
  type EffectBffOpenApiConfig,
13
13
  type EffectDataPlatformValidationOptions,
14
14
  type EffectRequestValidator,
15
+ type EffectRpcBffDefinition,
15
16
  type EffectRuntimeLayer,
16
17
  } from './handler';
17
18
  import type { EffectContext } from './operation-context';
@@ -33,6 +34,7 @@ export type EffectBffHandlerFactory = (options?: {
33
34
  export type EffectApiModule = {
34
35
  api?: unknown;
35
36
  layer?: unknown;
37
+ rpc?: EffectRpcBffDefinition;
36
38
  handler?: EffectBffRequestHandler;
37
39
  createHandler?: EffectBffHandlerFactory;
38
40
  default?: unknown;
@@ -125,6 +127,11 @@ function resolveClassifiedEffectBffModuleHandler(
125
127
  }
126
128
  }
127
129
 
130
+ if (facts.module.rpc !== undefined && !facts.createHandlerValidatorAware) {
131
+ rejectUnsupportedEffectModuleShape(options, 'unbranded RPC runtime');
132
+ return null;
133
+ }
134
+
128
135
  if (typeof facts.createHandler === 'function') {
129
136
  if (facts.createHandlerValidatorAware) {
130
137
  const factory = facts.createHandler as EffectBffHandlerFactory;
@@ -21,10 +21,6 @@ export type EffectContextStorage = {
21
21
  run: <TResult>(value: EffectContext, cb: () => TResult) => TResult;
22
22
  };
23
23
 
24
- export const kEffectContextStorage = Symbol.for(
25
- 'modernjs.plugin-bff.effectContextStorage',
26
- );
27
-
28
24
  export type CreateEffectOperationContextOptions = Omit<
29
25
  EffectContext,
30
26
  'operationContext'
@@ -128,7 +124,7 @@ export const createEffectOperationContext = ({
128
124
  : {}),
129
125
  routePath: servicePath,
130
126
  method: (method || request.method || 'GET').toUpperCase(),
131
- source: 'effect-adapter',
127
+ source: 'effect-server',
132
128
  ...(path && path !== servicePath
133
129
  ? { attributes: { mountedPath: path } }
134
130
  : {}),
@@ -1,4 +1,4 @@
1
- import { RpcSerialization } from 'effect/unstable/rpc';
1
+ import { RpcSerialization } from 'effect/rpc';
2
2
 
3
3
  import type { EffectRpcSerialization } from './handler/types';
4
4
 
@@ -12,8 +12,6 @@ export function getRpcSerializationLayer(
12
12
  return RpcSerialization.layerJsonRpc();
13
13
  case 'ndJsonRpc':
14
14
  return RpcSerialization.layerNdJsonRpc();
15
- case 'msgPack':
16
- return RpcSerialization.layerMsgPack;
17
15
  default:
18
16
  return RpcSerialization.layerJsonRpc();
19
17
  }
@@ -2,6 +2,7 @@ import {
2
2
  BFF_ENVELOPE_HEADER,
3
3
  BFF_OPERATION_CONTEXT_DETAIL_HEADER,
4
4
  BFF_OPERATION_CONTEXT_HEADER,
5
+ digestOperationContract,
5
6
  resolveCrossProjectRequestObservation,
6
7
  } from '@modern-js/server-runtime-extensions/bff-policy';
7
8
  import * as Effect from 'effect/Effect';
@@ -9,8 +10,8 @@ import * as Schema from 'effect/Schema';
9
10
 
10
11
  const encodeJson = Schema.encodeSync(Schema.fromJsonString(Schema.Unknown));
11
12
 
12
- import { HttpClient, HttpClientRequest } from 'effect/unstable/http';
13
- import { HttpApi, type HttpApiGroup } from 'effect/unstable/httpapi';
13
+ import { HttpClient, HttpClientRequest } from 'effect/http';
14
+ import { HttpApi, type HttpApiGroup } from 'effect/http-api';
14
15
 
15
16
  export interface EffectCrossProjectClientOptions {
16
17
  requestId: string;
@@ -66,22 +67,16 @@ export function withCrossProjectPolicy<
66
67
  );
67
68
  }
68
69
  return Effect.gen(function* () {
69
- // Canonical field order matches the server's route-identity SHA-256.
70
- const input = encodeJson({
71
- httpMethod: contract.method,
72
- name: contract.name,
73
- requestId: options.requestId,
74
- routePath: contract.routePath,
75
- });
76
- const digest = yield* Effect.promise(() =>
77
- globalThis.crypto.subtle.digest(
78
- 'SHA-256',
79
- new TextEncoder().encode(input),
70
+ const schemaHash = yield* Effect.promise(() =>
71
+ digestOperationContract(
72
+ {
73
+ httpMethod: contract.method,
74
+ name: contract.name,
75
+ routePath: contract.routePath,
76
+ },
77
+ options.requestId,
80
78
  ),
81
79
  );
82
- const schemaHash = Array.from(new Uint8Array(digest), value =>
83
- value.toString(16).padStart(2, '0'),
84
- ).join('');
85
80
  return request.pipe(
86
81
  HttpClientRequest.setHeader(
87
82
  BFF_ENVELOPE_HEADER,
@@ -6,28 +6,25 @@ import {
6
6
  import * as Data from 'effect/Data';
7
7
  import * as Effect from 'effect/Effect';
8
8
  import * as Exit from 'effect/Exit';
9
- import * as Layer from 'effect/Layer';
10
- import * as ManagedRuntime from 'effect/ManagedRuntime';
11
- import * as Scope from 'effect/Scope';
12
- import {
13
- FetchHttpClient,
14
- HttpClient,
15
- HttpClientRequest,
16
- } from 'effect/unstable/http';
9
+ import { FetchHttpClient, HttpClient, HttpClientRequest } from 'effect/http';
17
10
  import {
18
11
  HttpApi,
19
12
  HttpApiClient,
20
13
  HttpApiEndpoint,
21
14
  HttpApiGroup,
22
15
  HttpApiSchema,
23
- } from 'effect/unstable/httpapi';
16
+ } from 'effect/http-api';
17
+ import * as Layer from 'effect/Layer';
18
+ import * as ManagedRuntime from 'effect/ManagedRuntime';
24
19
  import {
25
20
  Rpc,
26
21
  RpcClient,
22
+ RpcClientError,
27
23
  RpcGroup,
28
24
  RpcSchema,
29
25
  RpcSerialization,
30
- } from 'effect/unstable/rpc';
26
+ } from 'effect/rpc';
27
+ import * as Scope from 'effect/Scope';
31
28
 
32
29
  import { getRpcSerializationLayer } from '../effect/rpcSerialization';
33
30
  import {
@@ -36,9 +33,9 @@ import {
36
33
  } from './cross-project';
37
34
 
38
35
  export * as Effect from 'effect/Effect';
36
+ export * as HttpClientError from 'effect/http/HttpClientError';
39
37
  export * as Layer from 'effect/Layer';
40
38
  export * as Schema from 'effect/Schema';
41
- export * as HttpClientError from 'effect/unstable/http/HttpClientError';
42
39
  export type { EffectCrossProjectClientOptions } from './cross-project';
43
40
  export {
44
41
  HttpApi,
@@ -106,8 +103,7 @@ export type EffectRpcSerialization =
106
103
  | 'json'
107
104
  | 'ndjson'
108
105
  | 'jsonRpc'
109
- | 'ndJsonRpc'
110
- | 'msgPack';
106
+ | 'ndJsonRpc';
111
107
 
112
108
  export class EffectRpcClientError extends Data.TaggedError(
113
109
  'EffectRpcClientError',
@@ -138,8 +134,8 @@ export type EffectRpcClientHandle<
138
134
  Rpcs extends Rpc.Any,
139
135
  Flatten extends boolean = false,
140
136
  > = (Flatten extends true
141
- ? RpcClient.RpcClient.Flat<Rpcs, unknown>
142
- : RpcClient.RpcClient<Rpcs, unknown>) & {
137
+ ? RpcClient.RpcClient.Flat<Rpcs, RpcClientError.RpcClientError>
138
+ : RpcClient.RpcClient<Rpcs, RpcClientError.RpcClientError>) & {
143
139
  dispose: () => Promise<void>;
144
140
  };
145
141
 
@@ -48,7 +48,7 @@ export const MicroVerticalOperationSourceSchema = Schema.Literals([
48
48
  'client',
49
49
  'server',
50
50
  'generated-client',
51
- 'effect-adapter',
51
+ 'effect-server',
52
52
  'data-platform',
53
53
  'unknown',
54
54
  ]);