@bleedingdev/modern-js-plugin-bff 3.5.0-ultramodern.99 → 3.8.1-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 (86) hide show
  1. package/dist/cjs/cli/compress.js +1 -1
  2. package/dist/cjs/cli/generator.js +106 -97
  3. package/dist/cjs/cli/serverGlobalVars.js +43 -57
  4. package/dist/cjs/cli.js +6 -2
  5. package/dist/cjs/loader.js +6 -5
  6. package/dist/cjs/runtime/effect/adapter/cross-project-policy.js +17 -12
  7. package/dist/cjs/runtime/effect/adapter/entry.js +13 -5
  8. package/dist/cjs/runtime/effect/adapter/error-response.js +11 -9
  9. package/dist/cjs/runtime/effect/adapter.js +2 -2
  10. package/dist/cjs/runtime/effect/backend-federation/load.js +26 -17
  11. package/dist/cjs/runtime/effect/backend-federation/plugin.js +12 -2
  12. package/dist/cjs/runtime/effect/backend-federation/remotes.js +5 -4
  13. package/dist/cjs/runtime/effect/backend-federation/runtime.js +80 -16
  14. package/dist/cjs/runtime/effect/edge-dispatcher.js +148 -0
  15. package/dist/cjs/runtime/effect/edge.js +19 -100
  16. package/dist/cjs/runtime/effect/handler/definition.js +1 -0
  17. package/dist/cjs/runtime/effect/handler/http.js +17 -6
  18. package/dist/cjs/utils/crossProjectApiPlugin.js +21 -2
  19. package/dist/cjs/utils/effect-client-generator/generator.js +17 -16
  20. package/dist/cjs/utils/effect-client-generator/paths.js +4 -15
  21. package/dist/cjs/utils/effect-client-generator/rendering.js +8 -19
  22. package/dist/cjs/utils/effect-client-generator/runtime.js +15 -32
  23. package/dist/cjs/utils/effectSourceLoader.js +70 -10
  24. package/dist/cjs/utils/pluginGenerator.js +4 -4
  25. package/dist/esm/cli/compress.mjs +1 -1
  26. package/dist/esm/cli/generator.mjs +108 -98
  27. package/dist/esm/cli/serverGlobalVars.mjs +44 -48
  28. package/dist/esm/cli.mjs +2 -0
  29. package/dist/esm/loader.mjs +6 -5
  30. package/dist/esm/runtime/effect/adapter/cross-project-policy.mjs +17 -12
  31. package/dist/esm/runtime/effect/adapter/entry.mjs +13 -5
  32. package/dist/esm/runtime/effect/adapter/error-response.mjs +11 -9
  33. package/dist/esm/runtime/effect/adapter.mjs +3 -3
  34. package/dist/esm/runtime/effect/backend-federation/load.mjs +26 -17
  35. package/dist/esm/runtime/effect/backend-federation/plugin.mjs +12 -2
  36. package/dist/esm/runtime/effect/backend-federation/remotes.mjs +5 -4
  37. package/dist/esm/runtime/effect/backend-federation/runtime.mjs +80 -16
  38. package/dist/esm/runtime/effect/edge-dispatcher.mjs +38 -0
  39. package/dist/esm/runtime/effect/edge.mjs +1 -38
  40. package/dist/esm/runtime/effect/handler/definition.mjs +1 -0
  41. package/dist/esm/runtime/effect/handler/http.mjs +17 -6
  42. package/dist/esm/utils/crossProjectApiPlugin.mjs +16 -3
  43. package/dist/esm/utils/effect-client-generator/generator.mjs +17 -16
  44. package/dist/esm/utils/effect-client-generator/paths.mjs +5 -6
  45. package/dist/esm/utils/effect-client-generator/rendering.mjs +9 -10
  46. package/dist/esm/utils/effect-client-generator/runtime.mjs +16 -23
  47. package/dist/esm/utils/effectSourceLoader.mjs +69 -12
  48. package/dist/esm/utils/pluginGenerator.mjs +5 -5
  49. package/dist/esm-node/cli/compress.mjs +1 -1
  50. package/dist/esm-node/cli/generator.mjs +108 -98
  51. package/dist/esm-node/cli/serverGlobalVars.mjs +44 -48
  52. package/dist/esm-node/cli.mjs +2 -0
  53. package/dist/esm-node/loader.mjs +6 -5
  54. package/dist/esm-node/runtime/effect/adapter/cross-project-policy.mjs +17 -12
  55. package/dist/esm-node/runtime/effect/adapter/entry.mjs +13 -5
  56. package/dist/esm-node/runtime/effect/adapter/error-response.mjs +11 -9
  57. package/dist/esm-node/runtime/effect/adapter.mjs +3 -3
  58. package/dist/esm-node/runtime/effect/backend-federation/load.mjs +26 -17
  59. package/dist/esm-node/runtime/effect/backend-federation/plugin.mjs +12 -2
  60. package/dist/esm-node/runtime/effect/backend-federation/remotes.mjs +5 -4
  61. package/dist/esm-node/runtime/effect/backend-federation/runtime.mjs +80 -16
  62. package/dist/esm-node/runtime/effect/edge-dispatcher.mjs +39 -0
  63. package/dist/esm-node/runtime/effect/edge.mjs +1 -38
  64. package/dist/esm-node/runtime/effect/handler/definition.mjs +1 -0
  65. package/dist/esm-node/runtime/effect/handler/http.mjs +17 -6
  66. package/dist/esm-node/utils/crossProjectApiPlugin.mjs +16 -3
  67. package/dist/esm-node/utils/effect-client-generator/generator.mjs +17 -16
  68. package/dist/esm-node/utils/effect-client-generator/paths.mjs +5 -6
  69. package/dist/esm-node/utils/effect-client-generator/rendering.mjs +9 -10
  70. package/dist/esm-node/utils/effect-client-generator/runtime.mjs +16 -23
  71. package/dist/esm-node/utils/effectSourceLoader.mjs +69 -12
  72. package/dist/esm-node/utils/pluginGenerator.mjs +5 -5
  73. package/dist/types/cli/generator.d.ts +2 -2
  74. package/dist/types/cli/serverGlobalVars.d.ts +4 -2
  75. package/dist/types/cli.d.ts +1 -0
  76. package/dist/types/runtime/effect/adapter/cross-project-policy.d.ts +1 -1
  77. package/dist/types/runtime/effect/backend-federation/runtime.d.ts +1 -1
  78. package/dist/types/runtime/effect/edge-dispatcher.d.ts +26 -0
  79. package/dist/types/runtime/effect/edge.d.ts +1 -26
  80. package/dist/types/runtime/effect/handler/definition.d.ts +2 -12
  81. package/dist/types/runtime/effect/handler/http.d.ts +2 -1
  82. package/dist/types/runtime/effect/handler/types.d.ts +5 -0
  83. package/dist/types/utils/crossProjectApiPlugin.d.ts +2 -0
  84. package/dist/types/utils/effectSourceLoader.d.ts +10 -0
  85. package/dist/types/utils/pluginGenerator.d.ts +3 -1
  86. package/package.json +34 -18
@@ -1,7 +1,7 @@
1
1
  import "node:module";
2
2
  import node_crypto from "node:crypto";
3
3
  import node_fs from "node:fs";
4
- import { builtinModules } from "node:module";
4
+ import { builtinModules, createRequire } from "node:module";
5
5
  import node_path from "node:path";
6
6
  import { pathToFileURL } from "node:url";
7
7
  import { build, transform } from "esbuild";
@@ -76,10 +76,29 @@ const nodeBuiltins = new Set([
76
76
  ...builtinModules.map((name)=>`node:${name}`)
77
77
  ]);
78
78
  const dependencyResolutionMarker = 'modern-js-effect-dependency-resolution';
79
+ async function isEsmOnlyFile(filename) {
80
+ const extension = node_path.extname(filename).toLowerCase();
81
+ if ('.mjs' === extension || '.mts' === extension) return true;
82
+ if ('.cjs' === extension || '.cts' === extension) return false;
83
+ let directory = node_path.dirname(filename);
84
+ while(true){
85
+ const packagePath = node_path.join(directory, 'package.json');
86
+ try {
87
+ const packageJson = JSON.parse(await node_fs.promises.readFile(packagePath, 'utf8'));
88
+ return 'module' === packageJson.type;
89
+ } catch (error) {
90
+ if (!error || 'object' != typeof error || !('code' in error) || 'ENOENT' !== error.code) throw error;
91
+ }
92
+ const parent = node_path.dirname(directory);
93
+ if (parent === directory) return false;
94
+ directory = parent;
95
+ }
96
+ }
79
97
  function isBareSpecifier(specifier) {
80
98
  return !specifier.startsWith('.') && !specifier.startsWith('/') && !node_path.isAbsolute(specifier);
81
99
  }
82
- function externalizeInstalledDependencies() {
100
+ function externalizeInstalledDependencies(options) {
101
+ const runtimeRequire = createRequire(node_path.join(options.runtimeResolveDir, '__modern_effect_entry.cjs'));
83
102
  return {
84
103
  name: 'modern-js-effect-installed-dependencies',
85
104
  setup (buildApi) {
@@ -109,19 +128,46 @@ function externalizeInstalledDependencies() {
109
128
  path: args.path
110
129
  };
111
130
  const realPath = await node_fs.promises.realpath(resolution.path).catch(()=>resolution.path);
112
- if (realPath.includes(`${node_path.sep}node_modules${node_path.sep}`)) return {
113
- external: true,
114
- path: args.path
115
- };
131
+ if (realPath.includes(`${node_path.sep}node_modules${node_path.sep}`)) {
132
+ const runtimeResolution = await buildApi.resolve(args.path, {
133
+ importer: '',
134
+ kind: args.kind,
135
+ namespace: 'file',
136
+ pluginData: {
137
+ [dependencyResolutionMarker]: true
138
+ },
139
+ resolveDir: options.runtimeResolveDir
140
+ });
141
+ if (0 === runtimeResolution.errors.length && runtimeResolution.path) {
142
+ if ('cjs' === options.format) {
143
+ let requiredPath;
144
+ try {
145
+ requiredPath = runtimeRequire.resolve(args.path);
146
+ } catch {
147
+ requiredPath = runtimeResolution.path;
148
+ }
149
+ if (await isEsmOnlyFile(requiredPath)) return {
150
+ namespace: resolution.namespace,
151
+ path: resolution.path,
152
+ pluginData: resolution.pluginData,
153
+ sideEffects: resolution.sideEffects,
154
+ suffix: resolution.suffix,
155
+ warnings: resolution.warnings
156
+ };
157
+ }
158
+ return {
159
+ external: true,
160
+ path: args.path
161
+ };
162
+ }
163
+ }
116
164
  return {
117
165
  namespace: resolution.namespace,
118
166
  path: resolution.path,
119
167
  pluginData: resolution.pluginData,
120
168
  sideEffects: resolution.sideEffects,
121
169
  suffix: resolution.suffix,
122
- warnings: resolution.warnings,
123
- watchDirs: resolution.watchDirs,
124
- watchFiles: resolution.watchFiles
170
+ warnings: resolution.warnings
125
171
  };
126
172
  });
127
173
  }
@@ -140,7 +186,10 @@ async function bundleEffectEntryForNode(options) {
140
186
  outfile: options.entryPath,
141
187
  platform: 'node',
142
188
  plugins: [
143
- externalizeInstalledDependencies(),
189
+ externalizeInstalledDependencies({
190
+ format: options.format,
191
+ runtimeResolveDir: options.appDir
192
+ }),
144
193
  preserveSourceModuleSemantics()
145
194
  ],
146
195
  target: 'node20'
@@ -156,6 +205,11 @@ function normalizeImportedModule(module) {
156
205
  if (1 === Object.keys(namespace).length && null !== commonJsModule && 'object' == typeof commonJsModule && true === commonJsModule.__esModule) return commonJsModule;
157
206
  return module;
158
207
  }
208
+ async function loadEffectBuiltModule(resourcePath) {
209
+ const canonicalPath = await node_fs.promises.realpath(node_path.resolve(resourcePath));
210
+ if (!await isEsmOnlyFile(canonicalPath)) return createRequire(canonicalPath)(canonicalPath);
211
+ return normalizeImportedModule(await dynamicImport(pathToFileURL(canonicalPath).href));
212
+ }
159
213
  async function loadEffectSourceModule(options) {
160
214
  const resourcePath = node_path.resolve(options.resourcePath);
161
215
  const appDir = node_path.resolve(options.appDir ?? node_path.dirname(resourcePath));
@@ -182,7 +236,10 @@ async function loadEffectSourceModule(options) {
182
236
  outfile: outputPath,
183
237
  platform: 'node',
184
238
  plugins: [
185
- externalizeInstalledDependencies(),
239
+ externalizeInstalledDependencies({
240
+ format: 'esm',
241
+ runtimeResolveDir: appDir
242
+ }),
186
243
  preserveSourceModuleSemantics()
187
244
  ],
188
245
  sourcemap: 'inline',
@@ -197,4 +254,4 @@ async function loadEffectSourceModule(options) {
197
254
  const revision = node_crypto.createHash('sha256').update(output).digest('hex');
198
255
  return normalizeImportedModule(await dynamicImport(`${pathToFileURL(outputPath).href}?v=${revision}`));
199
256
  }
200
- export { bundleEffectEntryForNode, loadEffectSourceModule };
257
+ export { bundleEffectEntryForNode, loadEffectBuiltModule, loadEffectSourceModule };
@@ -1,22 +1,22 @@
1
1
  import "node:module";
2
2
  import { fs, logger, normalizeToPosixPath } from "@modern-js/utils";
3
3
  import path from "path";
4
- import { API_DIR, DIST_DIR, LAMBDA_DIR, PACKAGE_NAME, PREFIX, RUNTIME_FRAMEWORK } from "./crossProjectApiPlugin.mjs";
4
+ import { API_DIR, DIST_DIR, EFFECT_ENTRY, LAMBDA_DIR, OPERATION_CONTRACTS_JSON, PACKAGE_NAME, PREFIX, RUNTIME_FRAMEWORK } from "./crossProjectApiPlugin.mjs";
5
5
  import { fileURLToPath as __rspack_fileURLToPath } from "node:url";
6
6
  import { dirname as __rspack_dirname } from "node:path";
7
7
  var __rspack_import_meta_dirname__ = __rspack_dirname(__rspack_fileURLToPath(import.meta.url));
8
- function replaceContent(source, packageName, prefix, relativeDistPath, relativeApiPath, relativeLambdaPath, runtimeFramework) {
9
- const updatedSource = source.replace(new RegExp(PACKAGE_NAME, 'g'), packageName).replace(new RegExp(PREFIX, 'g'), prefix).replace(new RegExp(DIST_DIR, 'g'), normalizeToPosixPath(relativeDistPath)).replace(new RegExp(API_DIR, 'g'), normalizeToPosixPath(relativeApiPath)).replace(new RegExp(LAMBDA_DIR, 'g'), normalizeToPosixPath(relativeLambdaPath)).replace(new RegExp(RUNTIME_FRAMEWORK, 'g'), runtimeFramework);
8
+ function replaceContent(source, packageName, prefix, relativeDistPath, relativeApiPath, relativeLambdaPath, runtimeFramework, relativeEffectEntry, operationContracts) {
9
+ const updatedSource = source.replace(new RegExp(PACKAGE_NAME, 'g'), packageName).replace(new RegExp(PREFIX, 'g'), prefix).replace(new RegExp(DIST_DIR, 'g'), normalizeToPosixPath(relativeDistPath)).replace(new RegExp(API_DIR, 'g'), normalizeToPosixPath(relativeApiPath)).replace(new RegExp(LAMBDA_DIR, 'g'), normalizeToPosixPath(relativeLambdaPath)).replace(new RegExp(RUNTIME_FRAMEWORK, 'g'), runtimeFramework).replace(new RegExp(EFFECT_ENTRY, 'g'), normalizeToPosixPath(relativeEffectEntry)).replace(`'${OPERATION_CONTRACTS_JSON}'`, ()=>JSON.stringify(JSON.stringify(operationContracts)));
10
10
  return updatedSource;
11
11
  }
12
- async function pluginGenerator({ prefix, appDirectory, relativeDistPath, relativeApiPath, relativeLambdaPath, runtimeFramework }) {
12
+ async function pluginGenerator({ prefix, appDirectory, relativeDistPath, relativeApiPath, relativeLambdaPath, runtimeFramework, relativeEffectEntry, operationContracts }) {
13
13
  try {
14
14
  const packageContent = await fs.readFile(path.resolve(appDirectory, './package.json'), 'utf8');
15
15
  const packageJson = JSON.parse(packageContent);
16
16
  const pluginDir = path.resolve(appDirectory, `./${relativeDistPath}`, 'plugin');
17
17
  const pluginPath = path.join(pluginDir, 'index.js');
18
18
  const pluginTemplate = await fs.readFile(path.resolve(__rspack_import_meta_dirname__, 'crossProjectApiPlugin.js'), 'utf8');
19
- const updatedPlugin = replaceContent(pluginTemplate, packageJson.name, prefix, relativeDistPath, relativeApiPath, relativeLambdaPath, runtimeFramework);
19
+ const updatedPlugin = replaceContent(pluginTemplate, packageJson.name, prefix, relativeDistPath, relativeApiPath, relativeLambdaPath, runtimeFramework, relativeEffectEntry, operationContracts);
20
20
  await fs.ensureFile(pluginPath);
21
21
  await fs.writeFile(pluginPath, updatedPlugin);
22
22
  const typeContent = `import type { AppTools, CliPlugin } from '@modern-js/app-tools';
@@ -1,7 +1,7 @@
1
1
  import type { AppTools } from '@modern-js/app-tools';
2
2
  import type { CLIPluginAPI } from '@modern-js/plugin';
3
3
  export declare const createBffGenerator: (api: CLIPluginAPI<AppTools>) => {
4
- compileApi: () => Promise<void>;
4
+ compileApi: () => Promise<void | undefined>;
5
5
  generate: () => Promise<void>;
6
- handleCrossProjectInvocation: (isBuild?: boolean) => Promise<void>;
6
+ handleCrossProjectInvocation: (isBuild?: boolean) => Promise<void | undefined>;
7
7
  };
@@ -1,4 +1,6 @@
1
+ import type { AppTools } from '@modern-js/app-tools';
1
2
  type SerializedGlobalVars = Record<string, string>;
2
- export declare const serializeServerGlobalVars: (options: unknown) => SerializedGlobalVars;
3
- export declare const transformServerGlobalVars: (outputDirectories: string[], globalVars: SerializedGlobalVars) => Promise<void>;
3
+ type ServerGlobalVarsOptions = NonNullable<NonNullable<AppTools['config']>['source']>['globalVars'];
4
+ export declare const serializeServerGlobalVars: (options: ServerGlobalVarsOptions) => SerializedGlobalVars;
5
+ export declare const transformServerGlobalVars: (outputDirectories: string[], globalVars: SerializedGlobalVars) => Promise<undefined>;
4
6
  export {};
@@ -1,2 +1,3 @@
1
1
  import type { AppTools, CliPlugin } from '@modern-js/app-tools';
2
2
  export declare const bffPlugin: () => CliPlugin<AppTools>;
3
+ export default bffPlugin;
@@ -1,4 +1,4 @@
1
1
  import type { ServerPluginAPI } from '@modern-js/server-core';
2
2
  import { type ResolvedCrossProjectPolicy } from '../../../utils/crossProjectServerPolicy';
3
3
  import type { EffectApiModule } from '../module';
4
- export declare function resolveEffectAdapterCrossProjectPolicy(api: ServerPluginAPI, prefix: string, mod: EffectApiModule | null): Promise<ResolvedCrossProjectPolicy>;
4
+ export declare function resolveEffectAdapterCrossProjectPolicy(api: ServerPluginAPI, prefix: string, mod: EffectApiModule | null): Promise<ResolvedCrossProjectPolicy | undefined>;
@@ -1,3 +1,3 @@
1
- import type { ModuleFederation } from '@module-federation/runtime';
1
+ import { ModuleFederation } from '@module-federation/runtime';
2
2
  import type { BackendFederationRuntimeOptions } from './types';
3
3
  export declare function createBackendFederationRuntime(options: BackendFederationRuntimeOptions): ModuleFederation;
@@ -0,0 +1,26 @@
1
+ import { type DispatchEffectBffRequestOptions } from './dispatch';
2
+ import type { EffectBffOpenApiConfig, EffectDataPlatformValidationOptions } from './handler';
3
+ import { type EffectApiModule, type EffectBffRequestHandler } from './module';
4
+ import type { EffectContext } from './operation-context';
5
+ export { runWithEffectContext, useEffectContext, useOperationContext, } from './edge-context';
6
+ export * from './handler';
7
+ export { type CreateEffectOperationContextOptions, createEffectOperationContext, type EffectContext, } from './operation-context';
8
+ export type EffectBffEdgeDispatchOptions = Omit<DispatchEffectBffRequestOptions, 'runWithEffectContext'>;
9
+ export type EffectBffEdgeHandlerOptions = {
10
+ module: EffectApiModule;
11
+ prefix?: string;
12
+ openapi?: EffectBffOpenApiConfig;
13
+ dataPlatform?: EffectDataPlatformValidationOptions;
14
+ onError?: (error: unknown, context: EffectContext) => Promise<Response> | Response;
15
+ onWarning?: (message: string) => void;
16
+ };
17
+ export declare function dispatchEffectBffRequest(handler: EffectBffRequestHandler, request: Request, options?: EffectBffEdgeDispatchOptions): Promise<Response>;
18
+ export declare function createEffectBffEdgeDispatcher(options: EffectBffEdgeHandlerOptions): Promise<{
19
+ dispatch: (request: Request, dispatchOptions?: Omit<EffectBffEdgeDispatchOptions, 'prefix' | 'onError'>) => Promise<Response>;
20
+ dispose: () => Promise<void>;
21
+ }>;
22
+ export declare const createEffectBffTestHandler: typeof createEffectBffEdgeHandler;
23
+ export declare function createEffectBffEdgeHandler(options: EffectBffEdgeHandlerOptions): Promise<{
24
+ handler: (request: Request, dispatchOptions?: Omit<EffectBffEdgeDispatchOptions, 'prefix' | 'onError'>) => Promise<Response>;
25
+ dispose: () => Promise<void>;
26
+ }>;
@@ -1,27 +1,2 @@
1
- import { type DispatchEffectBffRequestOptions } from './dispatch';
2
- import type { EffectBffOpenApiConfig, EffectDataPlatformValidationOptions } from './handler';
3
- import { type EffectApiModule, type EffectBffRequestHandler } from './module';
4
- import type { EffectContext } from './operation-context';
5
1
  export { BACKEND_FEDERATION_CONTRACT_VERSION, BACKEND_FEDERATION_EFFECT_EXPOSE, BACKEND_FEDERATION_MANIFEST_FILE, BACKEND_FEDERATION_NODE_ADAPTER_VERSION, type BackendFederatedEffectApiModule, type BackendFederationEntryExports, type BackendFederationExpectedIdentity, type BackendFederationIdentityIssue, type BackendFederationIdentityLoadOptions, type BackendFederationLoadEntryPluginOptions, type BackendFederationRemote, type BackendFederationRuntimeOptions, createBackendFederationLoadEntryPlugin, createBackendFederationRuntime, loadBackendFederatedEffectApi, validateExpectedBackendFederationIdentity, } from './backend-federation';
6
- export { runWithEffectContext, useEffectContext, useOperationContext, } from './edge-context';
7
- export * from './handler';
8
- export { type CreateEffectOperationContextOptions, createEffectOperationContext, type EffectContext, } from './operation-context';
9
- export type EffectBffEdgeDispatchOptions = Omit<DispatchEffectBffRequestOptions, 'runWithEffectContext'>;
10
- export type EffectBffEdgeHandlerOptions = {
11
- module: EffectApiModule;
12
- prefix?: string;
13
- openapi?: EffectBffOpenApiConfig;
14
- dataPlatform?: EffectDataPlatformValidationOptions;
15
- onError?: (error: unknown, context: EffectContext) => Promise<Response> | Response;
16
- onWarning?: (message: string) => void;
17
- };
18
- export declare function dispatchEffectBffRequest(handler: EffectBffRequestHandler, request: Request, options?: EffectBffEdgeDispatchOptions): Promise<Response>;
19
- export declare function createEffectBffEdgeDispatcher(options: EffectBffEdgeHandlerOptions): Promise<{
20
- dispatch: (request: Request, dispatchOptions?: Omit<EffectBffEdgeDispatchOptions, 'prefix' | 'onError'>) => Promise<Response>;
21
- dispose: () => Promise<void>;
22
- }>;
23
- export declare const createEffectBffTestHandler: typeof createEffectBffEdgeHandler;
24
- export declare function createEffectBffEdgeHandler(options: EffectBffEdgeHandlerOptions): Promise<{
25
- handler: (request: Request, dispatchOptions?: Omit<EffectBffEdgeDispatchOptions, 'prefix' | 'onError'>) => Promise<Response>;
26
- dispose: () => Promise<void>;
27
- }>;
2
+ export * from './edge-dispatcher';
@@ -1,17 +1,7 @@
1
1
  import type { HttpApi } from 'effect/unstable/httpapi';
2
2
  import type { Rpc } from 'effect/unstable/rpc';
3
- import type { EffectBffRuntime, EffectDataPlatformValidationOptions, EffectRpcBffDefinition, EffectRpcBffHandlerFactory, EffectRpcRuntimeLayer, EffectRuntimeLayer } from './types';
4
- export declare function defineEffectBff<TApi extends HttpApi.Constraint, TLayer extends EffectRuntimeLayer, TRpcs extends Rpc.Any = Rpc.Any>(definition: {
5
- api: TApi;
6
- layer: TLayer;
7
- rpc?: EffectRpcBffDefinition<TRpcs>;
8
- dataPlatform?: EffectDataPlatformValidationOptions;
9
- }): {
10
- api: TApi;
11
- layer: TLayer;
12
- rpc?: EffectRpcBffDefinition<TRpcs>;
13
- dataPlatform?: EffectDataPlatformValidationOptions;
14
- } & EffectBffRuntime<TApi, TLayer>;
3
+ import type { EffectBffDefinition, EffectBffRuntime, EffectRpcBffDefinition, EffectRpcBffHandlerFactory, EffectRpcRuntimeLayer, EffectRuntimeLayer } from './types';
4
+ export declare function defineEffectBff<TApi extends HttpApi.Constraint, TLayer extends EffectRuntimeLayer, TRpcs extends Rpc.Any = Rpc.Any>(definition: EffectBffDefinition<TApi, TLayer, TRpcs>): EffectBffDefinition<TApi, TLayer, TRpcs> & EffectBffRuntime<TApi, TLayer>;
15
5
  export declare function defineEffectRpcBff<TRpcs extends Rpc.Any = Rpc.Any, TLayer extends EffectRpcRuntimeLayer<TRpcs> = EffectRpcRuntimeLayer<TRpcs>>(definition: EffectRpcBffDefinition<TRpcs, TLayer>): EffectRpcBffDefinition<TRpcs, TLayer> & {
16
6
  createHandler: EffectRpcBffHandlerFactory<TRpcs>;
17
7
  };
@@ -1,12 +1,13 @@
1
1
  import type { HttpApi } from 'effect/unstable/httpapi';
2
2
  import type { Rpc } from 'effect/unstable/rpc';
3
- import type { EffectBffOpenApiConfig, EffectDataPlatformValidationOptions, EffectRequestValidator, EffectRpcBffDefinition, EffectRuntimeLayer } from './types';
3
+ import type { EffectBffOpenApiConfig, EffectDataPlatformValidationOptions, EffectRequestInterceptor, EffectRequestValidator, EffectRpcBffDefinition, EffectRuntimeLayer } from './types';
4
4
  export declare function createHttpApiHandler<TApi extends HttpApi.Constraint = HttpApi.Top, TRpcs extends Rpc.Any = Rpc.Any>(options: {
5
5
  api: TApi;
6
6
  layer: EffectRuntimeLayer;
7
7
  openapi?: EffectBffOpenApiConfig;
8
8
  rpc?: EffectRpcBffDefinition<TRpcs>;
9
9
  dataPlatform?: EffectDataPlatformValidationOptions;
10
+ interceptRequest?: EffectRequestInterceptor;
10
11
  validateRequest?: EffectRequestValidator;
11
12
  }): {
12
13
  handler: (request: Request, context?: Parameters<(request: globalThis.Request, context: import("effect/Context").Context<unknown>) => Promise<Response>>[1]) => Promise<Response>;
@@ -35,6 +35,7 @@ export type EffectBffDefinition<TApi extends HttpApi.Constraint = HttpApi.Top, T
35
35
  layer: TLayer;
36
36
  rpc?: EffectRpcBffDefinition<TRpcs>;
37
37
  dataPlatform?: EffectDataPlatformValidationOptions;
38
+ interceptRequest?: EffectRequestInterceptor;
38
39
  };
39
40
  export type EffectDataPlatformSelectionValidationOptions = {
40
41
  maxDepth?: number;
@@ -131,6 +132,10 @@ export type EffectDataPlatformValidationOptions = {
131
132
  * cannot bypass it.
132
133
  */
133
134
  export type EffectRequestValidator = (request: Request) => Response | null | undefined;
135
+ export type EffectRequestInterceptor = (options: {
136
+ request: Request;
137
+ next: () => Promise<Response>;
138
+ }) => Response | Promise<Response>;
134
139
  export type EffectBffHandlerFactory<TApi extends HttpApi.Constraint = HttpApi.Top, TLayer extends EffectRuntimeLayer = EffectRuntimeLayer> = (options?: {
135
140
  openapi?: EffectBffOpenApiConfig;
136
141
  rpc?: Partial<EffectRpcBffHandlerOptions>;
@@ -5,5 +5,7 @@ export declare const API_DIR = "{apiDirectory}";
5
5
  export declare const LAMBDA_DIR = "{lambdaDirectory}";
6
6
  export declare const DIST_DIR = "{distDirectory}";
7
7
  export declare const RUNTIME_FRAMEWORK: string;
8
+ export declare const EFFECT_ENTRY = "{effectEntry}";
9
+ export declare const OPERATION_CONTRACTS_JSON = "{operationContracts}";
8
10
  export declare const crossProjectApiPlugin: () => CliPlugin<AppTools>;
9
11
  export default crossProjectApiPlugin;
@@ -8,6 +8,16 @@ export declare function bundleEffectEntryForNode(options: {
8
8
  entryPath: string;
9
9
  format: 'cjs' | 'esm';
10
10
  }): Promise<void>;
11
+ /**
12
+ * Loads the relocatable artifact emitted by the production BFF build.
13
+ *
14
+ * Production entries have already been compiled and bundled by
15
+ * `bundleEffectEntryForNode`. Loading that artifact through the development
16
+ * source-graph bundler a second time changes its module format and can strip
17
+ * CommonJS runtime globals from bundled dependencies. Keep the built module's
18
+ * native Node boundary intact instead.
19
+ */
20
+ export declare function loadEffectBuiltModule(resourcePath: string): Promise<unknown>;
11
21
  /**
12
22
  * Loads an Effect source entry as native ESM while keeping its complete local
13
23
  * source graph observable by the framework watcher.
@@ -1,9 +1,11 @@
1
- declare function pluginGenerator({ prefix, appDirectory, relativeDistPath, relativeApiPath, relativeLambdaPath, runtimeFramework, }: {
1
+ declare function pluginGenerator({ prefix, appDirectory, relativeDistPath, relativeApiPath, relativeLambdaPath, runtimeFramework, relativeEffectEntry, operationContracts, }: {
2
2
  prefix: string;
3
3
  appDirectory: string;
4
4
  relativeDistPath: string;
5
5
  relativeApiPath: string;
6
6
  relativeLambdaPath: string;
7
7
  runtimeFramework: 'hono' | 'effect';
8
+ relativeEffectEntry: string;
9
+ operationContracts: Record<string, unknown>;
8
10
  }): Promise<void>;
9
11
  export default pluginGenerator;
package/package.json CHANGED
@@ -17,7 +17,7 @@
17
17
  "modern",
18
18
  "modern.js"
19
19
  ],
20
- "version": "3.5.0-ultramodern.99",
20
+ "version": "3.8.1-ultramodern.1",
21
21
  "types": "./dist/types/cli.d.ts",
22
22
  "main": "./dist/cjs/cli.js",
23
23
  "exports": {
@@ -80,9 +80,22 @@
80
80
  },
81
81
  "./effect-edge": {
82
82
  "types": "./dist/types/runtime/effect/edge.d.ts",
83
+ "node": {
84
+ "import": "./dist/esm-node/runtime/effect/edge.mjs",
85
+ "require": "./dist/cjs/runtime/effect/edge.js"
86
+ },
83
87
  "import": "./dist/esm/runtime/effect/edge.mjs",
84
88
  "default": "./dist/esm/runtime/effect/edge.mjs"
85
89
  },
90
+ "./effect-edge/dispatcher": {
91
+ "types": "./dist/types/runtime/effect/edge-dispatcher.d.ts",
92
+ "node": {
93
+ "import": "./dist/esm-node/runtime/effect/edge-dispatcher.mjs",
94
+ "require": "./dist/cjs/runtime/effect/edge-dispatcher.js"
95
+ },
96
+ "import": "./dist/esm/runtime/effect/edge-dispatcher.mjs",
97
+ "default": "./dist/esm/runtime/effect/edge-dispatcher.mjs"
98
+ },
86
99
  "./effect-client": {
87
100
  "types": "./dist/types/runtime/effect-client/index.d.ts",
88
101
  "node": {
@@ -138,6 +151,9 @@
138
151
  "effect-edge": [
139
152
  "./dist/types/runtime/effect/edge.d.ts"
140
153
  ],
154
+ "effect-edge/dispatcher": [
155
+ "./dist/types/runtime/effect/edge-dispatcher.d.ts"
156
+ ],
141
157
  "effect-client": [
142
158
  "./dist/types/runtime/effect-client/index.d.ts"
143
159
  ],
@@ -153,13 +169,13 @@
153
169
  }
154
170
  },
155
171
  "dependencies": {
156
- "@modern-js/bff-core": "npm:@bleedingdev/modern-js-bff-core@3.5.0-ultramodern.99",
157
- "@modern-js/builder": "npm:@bleedingdev/modern-js-builder@3.5.0-ultramodern.99",
158
- "@modern-js/create-request": "npm:@bleedingdev/modern-js-create-request@3.5.0-ultramodern.99",
159
- "@modern-js/server-core": "npm:@bleedingdev/modern-js-server-core@3.5.0-ultramodern.99",
160
- "@modern-js/server-utils": "npm:@bleedingdev/modern-js-server-utils@3.5.0-ultramodern.99",
161
- "@modern-js/utils": "npm:@bleedingdev/modern-js-utils@3.5.0-ultramodern.99",
162
- "@module-federation/runtime": "2.8.0",
172
+ "@modern-js/bff-core": "npm:@bleedingdev/modern-js-bff-core@3.8.1-ultramodern.1",
173
+ "@modern-js/builder": "npm:@bleedingdev/modern-js-builder@3.8.1-ultramodern.1",
174
+ "@modern-js/create-request": "npm:@bleedingdev/modern-js-create-request@3.8.1-ultramodern.1",
175
+ "@modern-js/server-core": "npm:@bleedingdev/modern-js-server-core@3.8.1-ultramodern.1",
176
+ "@modern-js/server-utils": "npm:@bleedingdev/modern-js-server-utils@3.8.1-ultramodern.1",
177
+ "@modern-js/utils": "npm:@bleedingdev/modern-js-utils@3.8.1-ultramodern.1",
178
+ "@module-federation/runtime": "2.8.2",
163
179
  "@opentelemetry/api": "1.9.1",
164
180
  "@opentelemetry/api-logs": "0.220.0",
165
181
  "@opentelemetry/resources": "2.9.0",
@@ -176,8 +192,8 @@
176
192
  "type-is": "^2.1.0"
177
193
  },
178
194
  "peerDependencies": {
179
- "@effect/opentelemetry": "4.0.0-beta.102",
180
- "effect": "4.0.0-beta.102"
195
+ "@effect/opentelemetry": "4.0.0-beta.107",
196
+ "effect": "4.0.0-beta.107"
181
197
  },
182
198
  "peerDependenciesMeta": {
183
199
  "@effect/opentelemetry": {
@@ -188,20 +204,20 @@
188
204
  }
189
205
  },
190
206
  "devDependencies": {
191
- "@effect/opentelemetry": "4.0.0-beta.102",
192
- "@modern-js/app-tools": "npm:@bleedingdev/modern-js-app-tools@3.5.0-ultramodern.99",
193
- "@modern-js/bff-runtime": "npm:@bleedingdev/modern-js-bff-runtime@3.5.0-ultramodern.99",
194
- "@modern-js/plugin": "npm:@bleedingdev/modern-js-plugin@3.5.0-ultramodern.99",
195
- "@modern-js/runtime": "npm:@bleedingdev/modern-js-runtime@3.5.0-ultramodern.99",
196
- "@modern-js/types": "npm:@bleedingdev/modern-js-types@3.5.0-ultramodern.99",
207
+ "@effect/opentelemetry": "4.0.0-beta.107",
208
+ "@modern-js/app-tools": "npm:@bleedingdev/modern-js-app-tools@3.8.1-ultramodern.1",
209
+ "@modern-js/bff-runtime": "npm:@bleedingdev/modern-js-bff-runtime@3.8.1-ultramodern.1",
210
+ "@modern-js/plugin": "npm:@bleedingdev/modern-js-plugin@3.8.1-ultramodern.1",
211
+ "@modern-js/runtime": "npm:@bleedingdev/modern-js-runtime@3.8.1-ultramodern.1",
212
+ "@modern-js/types": "npm:@bleedingdev/modern-js-types@3.8.1-ultramodern.1",
197
213
  "@rsbuild/core": "2.1.5",
198
214
  "@rslib/core": "0.23.2",
199
215
  "@scripts/rstest-config": "2.66.0",
200
- "@types/node": "^26.1.1",
216
+ "@types/node": "^26.2.0",
201
217
  "@types/qs": "^6.15.1",
202
218
  "@types/type-is": "^1.6.7",
203
219
  "@typescript/native-preview": "7.0.0-dev.20260707.2",
204
- "effect": "4.0.0-beta.102",
220
+ "effect": "4.0.0-beta.107",
205
221
  "memfs": "^4.64.0",
206
222
  "typescript": "^7.0.2",
207
223
  "zod": "^4.4.3"