@bleedingdev/modern-js-plugin-bff-extensions 3.9.0-ultramodern.9 → 3.9.3-ultramodern.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +21 -4
- package/dist/cjs/backend-federation/edge.js +1 -1
- package/dist/cjs/backend-federation/identity.js +23 -22
- package/dist/cjs/backend-federation/integrity-plugin.js +112 -0
- package/dist/cjs/backend-federation/node-shared.js +85 -0
- package/dist/cjs/backend-federation/node.js +6 -1
- package/dist/cjs/backend-federation/plugin.js +40 -21
- package/dist/cjs/backend-federation/runtime.js +16 -84
- package/dist/cjs/backend-federation-manifest/load.js +31 -5
- package/dist/cjs/backend-federation-manifest/node.js +3 -1
- package/dist/cjs/backend-federation-manifest/remote.js +1 -7
- package/dist/cjs/backend-federation-manifest/validation.js +11 -7
- package/dist/cjs/cross-project-policy/node.js +8 -28
- package/dist/cjs/{effect-adapter → effect-server}/cross-project-policy.js +9 -9
- package/dist/cjs/effect-server/entry.js +63 -0
- package/dist/cjs/{effect-adapter → effect-server}/error-response.js +4 -4
- package/dist/cjs/effect-server/index.js +200 -0
- package/dist/cjs/effect-source-loader/built-entry.js +4 -5
- package/dist/cjs/effect-source-loader/http-api-runtime.js +4 -4
- package/dist/cjs/effect-source-loader/loader.js +10 -2
- package/dist/cjs/effect-source-loader/operation-contracts.js +8 -31
- package/dist/cjs/effect-source-loader/paths.js +38 -10
- package/dist/cjs/server-global-vars/index.js +61 -0
- package/dist/esm/backend-federation/edge.mjs +1 -1
- package/dist/esm/backend-federation/identity.mjs +18 -23
- package/dist/esm/backend-federation/integrity-plugin.mjs +68 -0
- package/dist/esm/backend-federation/node-shared.mjs +41 -0
- package/dist/esm/backend-federation/node.mjs +4 -2
- package/dist/esm/backend-federation/plugin.mjs +37 -18
- package/dist/esm/backend-federation/runtime.mjs +16 -84
- package/dist/esm/backend-federation-manifest/load.mjs +31 -5
- package/dist/esm/backend-federation-manifest/node.mjs +3 -1
- package/dist/esm/backend-federation-manifest/remote.mjs +1 -7
- package/dist/esm/backend-federation-manifest/validation.mjs +12 -8
- package/dist/esm/cross-project-policy/node.mjs +9 -19
- package/dist/esm/{effect-adapter → effect-server}/cross-project-policy.mjs +4 -4
- package/dist/esm/effect-server/entry.mjs +15 -0
- package/dist/esm/{effect-adapter → effect-server}/error-response.mjs +2 -2
- package/dist/esm/effect-server/index.mjs +152 -0
- package/dist/esm/effect-source-loader/built-entry.mjs +5 -6
- package/dist/esm/effect-source-loader/http-api-runtime.mjs +1 -1
- package/dist/esm/effect-source-loader/loader.mjs +10 -2
- package/dist/esm/effect-source-loader/operation-contracts.mjs +10 -33
- package/dist/esm/effect-source-loader/paths.mjs +30 -11
- package/dist/esm/server-global-vars/index.mjs +23 -0
- package/dist/esm-node/backend-federation/edge.mjs +1 -1
- package/dist/esm-node/backend-federation/identity.mjs +18 -23
- package/dist/esm-node/backend-federation/integrity-plugin.mjs +69 -0
- package/dist/esm-node/backend-federation/node-shared.mjs +42 -0
- package/dist/esm-node/backend-federation/node.mjs +4 -2
- package/dist/esm-node/backend-federation/plugin.mjs +37 -18
- package/dist/esm-node/backend-federation/runtime.mjs +16 -84
- package/dist/esm-node/backend-federation-manifest/load.mjs +31 -5
- package/dist/esm-node/backend-federation-manifest/node.mjs +3 -1
- package/dist/esm-node/backend-federation-manifest/remote.mjs +1 -7
- package/dist/esm-node/backend-federation-manifest/validation.mjs +12 -8
- package/dist/esm-node/cross-project-policy/node.mjs +9 -19
- package/dist/esm-node/{effect-adapter → effect-server}/cross-project-policy.mjs +4 -4
- package/dist/esm-node/effect-server/entry.mjs +16 -0
- package/dist/esm-node/{effect-adapter → effect-server}/error-response.mjs +2 -2
- package/dist/esm-node/effect-server/index.mjs +153 -0
- package/dist/esm-node/effect-source-loader/built-entry.mjs +5 -6
- package/dist/esm-node/effect-source-loader/http-api-runtime.mjs +1 -1
- package/dist/esm-node/effect-source-loader/loader.mjs +10 -2
- package/dist/esm-node/effect-source-loader/operation-contracts.mjs +10 -33
- package/dist/esm-node/effect-source-loader/paths.mjs +30 -11
- package/dist/esm-node/server-global-vars/index.mjs +24 -0
- package/dist/types/backend-federation/edge.d.ts +4 -2
- package/dist/types/backend-federation/identity.d.ts +3 -6
- package/dist/types/backend-federation/integrity-plugin.d.ts +13 -0
- package/dist/types/backend-federation/node-shared.d.ts +20 -0
- package/dist/types/backend-federation/node.d.ts +3 -0
- package/dist/types/backend-federation/plugin.d.ts +4 -0
- package/dist/types/backend-federation/types.d.ts +2 -7
- package/dist/types/backend-federation-manifest/types.d.ts +2 -1
- package/dist/types/cross-project-policy/node.d.ts +2 -2
- package/dist/types/effect-server/cross-project-policy.d.ts +5 -0
- package/dist/types/{effect-adapter → effect-server}/entry.d.ts +1 -1
- package/dist/types/effect-server/error-response.d.ts +2 -0
- package/dist/types/effect-server/index.d.ts +4 -0
- package/dist/types/effect-source-loader/http-api-runtime.d.ts +2 -0
- package/dist/types/effect-source-loader/loader.d.ts +3 -0
- package/dist/types/effect-source-loader/operation-contracts.d.ts +2 -0
- package/dist/types/effect-source-loader/paths.d.ts +20 -2
- package/dist/types/hono/node.d.ts +1 -1
- package/dist/types/server-global-vars/index.d.ts +11 -0
- package/package.json +47 -33
- package/src/backend-federation/edge.ts +7 -4
- package/src/backend-federation/identity.ts +39 -47
- package/src/backend-federation/integrity-plugin.ts +157 -0
- package/src/backend-federation/load.ts +0 -1
- package/src/backend-federation/node-shared.ts +76 -0
- package/src/backend-federation/node.ts +7 -3
- package/src/backend-federation/plugin.ts +73 -25
- package/src/backend-federation/runtime.ts +16 -90
- package/src/backend-federation/types.ts +2 -11
- package/src/backend-federation-manifest/load.ts +76 -27
- package/src/backend-federation-manifest/node.ts +3 -2
- package/src/backend-federation-manifest/remote.ts +0 -6
- package/src/backend-federation-manifest/types.ts +2 -0
- package/src/backend-federation-manifest/validation.ts +22 -29
- package/src/cross-project-policy/node.ts +7 -38
- package/src/{effect-adapter → effect-server}/cross-project-policy.ts +9 -3
- package/src/effect-server/entry.ts +18 -0
- package/src/{effect-adapter → effect-server}/error-response.ts +1 -1
- package/src/effect-server/index.ts +243 -0
- package/src/effect-source-loader/built-entry.ts +11 -9
- package/src/effect-source-loader/http-api-runtime.ts +3 -1
- package/src/effect-source-loader/loader.ts +24 -6
- package/src/effect-source-loader/operation-contracts.ts +9 -41
- package/src/effect-source-loader/paths.ts +55 -21
- package/src/effect-source-loader/rspack-loader.ts +0 -1
- package/src/server-global-vars/index.ts +46 -0
- package/dist/cjs/backend-federation/entry.js +0 -94
- package/dist/cjs/effect-adapter/entry.js +0 -99
- package/dist/cjs/effect-adapter/index.js +0 -194
- package/dist/esm/backend-federation/entry.mjs +0 -56
- package/dist/esm/effect-adapter/entry.mjs +0 -51
- package/dist/esm/effect-adapter/index.mjs +0 -143
- package/dist/esm-node/backend-federation/entry.mjs +0 -57
- package/dist/esm-node/effect-adapter/entry.mjs +0 -52
- package/dist/esm-node/effect-adapter/index.mjs +0 -144
- package/dist/types/backend-federation/entry.d.ts +0 -2
- package/dist/types/effect-adapter/cross-project-policy.d.ts +0 -4
- package/dist/types/effect-adapter/error-response.d.ts +0 -2
- package/dist/types/effect-adapter/index.d.ts +0 -21
- package/src/backend-federation/entry.ts +0 -125
- package/src/effect-adapter/entry.ts +0 -96
- package/src/effect-adapter/index.ts +0 -251
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { fs, upath as path } from '@modern-js/utils';
|
|
2
2
|
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
import {
|
|
4
|
+
emittedEffectEntry,
|
|
5
|
+
relativeEffectAppPath,
|
|
6
|
+
resolveEffectEntryFile,
|
|
7
|
+
} from './paths';
|
|
6
8
|
|
|
7
9
|
export function resolveBuiltEffectEntry(
|
|
8
10
|
appDirectory: string,
|
|
@@ -12,15 +14,15 @@ export function resolveBuiltEffectEntry(
|
|
|
12
14
|
if (sourceEntry === undefined || sourceEntry.length === 0) {
|
|
13
15
|
return undefined;
|
|
14
16
|
}
|
|
15
|
-
const relativeEntry =
|
|
16
|
-
if (relativeEntry ===
|
|
17
|
+
const relativeEntry = relativeEffectAppPath(appDirectory, sourceEntry);
|
|
18
|
+
if (relativeEntry === undefined) {
|
|
17
19
|
throw new Error(
|
|
18
20
|
`Effect BFF entry must be inside the application directory: ${sourceEntry}`,
|
|
19
21
|
);
|
|
20
22
|
}
|
|
21
|
-
const builtEntry =
|
|
22
|
-
.resolve(distDirectory, relativeEntry)
|
|
23
|
-
|
|
23
|
+
const builtEntry = emittedEffectEntry(
|
|
24
|
+
path.resolve(distDirectory, relativeEntry),
|
|
25
|
+
);
|
|
24
26
|
return fs.existsSync(builtEntry) ? builtEntry : undefined;
|
|
25
27
|
}
|
|
26
28
|
|
|
@@ -62,7 +64,7 @@ export function resolveEffectEntryPaths(options: {
|
|
|
62
64
|
});
|
|
63
65
|
const relativeEffectEntry =
|
|
64
66
|
sourceEffectEntry !== undefined && sourceEffectEntry.length > 0
|
|
65
|
-
? path.relative(appDir, sourceEffectEntry)
|
|
67
|
+
? emittedEffectEntry(path.relative(appDir, sourceEffectEntry))
|
|
66
68
|
: '';
|
|
67
69
|
return { sourceEffectEntry, relativeEffectEntry };
|
|
68
70
|
}
|
|
@@ -3,7 +3,8 @@ import {
|
|
|
3
3
|
type HttpApiLike,
|
|
4
4
|
type HttpApiReflect,
|
|
5
5
|
} from '@modern-js/bff-effect/effect';
|
|
6
|
-
import { HttpApi } from 'effect/
|
|
6
|
+
import { HttpApi } from 'effect/http-api';
|
|
7
|
+
import type { ServerGlobalVarsOptions } from '../server-global-vars';
|
|
7
8
|
import { loadEffectSourceModule } from './loader';
|
|
8
9
|
|
|
9
10
|
type HttpApiRuntime = {
|
|
@@ -29,6 +30,7 @@ export function getHttpApiRuntime(): Promise<HttpApiRuntime> {
|
|
|
29
30
|
export function loadEffectApi(options: {
|
|
30
31
|
appDir: string;
|
|
31
32
|
resourcePath: string;
|
|
33
|
+
globalVars?: ServerGlobalVarsOptions;
|
|
32
34
|
onDependency?: (dependency: string) => void;
|
|
33
35
|
}): Promise<HttpApiLike | null> {
|
|
34
36
|
return getHttpApiRuntime().then(httpApiRuntime =>
|
|
@@ -12,8 +12,12 @@ import {
|
|
|
12
12
|
type Plugin,
|
|
13
13
|
transform,
|
|
14
14
|
} from 'esbuild';
|
|
15
|
+
import {
|
|
16
|
+
type ServerGlobalVarsOptions,
|
|
17
|
+
serializeServerGlobalVars,
|
|
18
|
+
} from '../server-global-vars';
|
|
15
19
|
|
|
16
|
-
const NODE_TARGET = 'node26.
|
|
20
|
+
const NODE_TARGET = 'node26.10';
|
|
17
21
|
const SOURCE_LOADERS = new Map<string, Loader>([
|
|
18
22
|
['.js', 'js'],
|
|
19
23
|
['.jsx', 'jsx'],
|
|
@@ -28,6 +32,8 @@ const SOURCE_LOADERS = new Map<string, Loader>([
|
|
|
28
32
|
export type EffectSourceLoaderOptions = {
|
|
29
33
|
resourcePath: string;
|
|
30
34
|
appDir?: string;
|
|
35
|
+
/** `source.globalVars`, replaced in the loaded source graph. */
|
|
36
|
+
globalVars?: ServerGlobalVarsOptions;
|
|
31
37
|
onDependency?: (dependency: string) => void;
|
|
32
38
|
};
|
|
33
39
|
|
|
@@ -79,6 +85,9 @@ const nodeBuiltins = new Set([
|
|
|
79
85
|
...builtinModules.map(name => `node:${name}`),
|
|
80
86
|
]);
|
|
81
87
|
const dependencyResolutionMarker = 'modern-js-effect-dependency-resolution';
|
|
88
|
+
// The BFF server runs lambdas inside these packages' Effect context storage.
|
|
89
|
+
// A bundled copy would own a second storage that the server never enters.
|
|
90
|
+
const BFF_RUNTIME_PACKAGE = /^@modern-js\/(?:bff-effect|plugin-bff)(?:\/|$)/;
|
|
82
91
|
|
|
83
92
|
async function isEsmOnlyFile(filename: string) {
|
|
84
93
|
const extension = path.extname(filename).toLowerCase();
|
|
@@ -125,10 +134,9 @@ function isBareSpecifier(specifier: string) {
|
|
|
125
134
|
}
|
|
126
135
|
|
|
127
136
|
/**
|
|
128
|
-
* Keep installed
|
|
129
|
-
*
|
|
130
|
-
*
|
|
131
|
-
* generated entry is relocatable and directly executable by Node 26.7.
|
|
137
|
+
* Keep installed executable dependencies external to preserve runtime identity.
|
|
138
|
+
* Source requiring compilation is bundled even when pnpm injects a workspace
|
|
139
|
+
* package into node_modules: Node does not strip types inside that directory.
|
|
132
140
|
*/
|
|
133
141
|
function externalizeInstalledDependencies(options: {
|
|
134
142
|
runtimeResolveDir: string;
|
|
@@ -137,6 +145,9 @@ function externalizeInstalledDependencies(options: {
|
|
|
137
145
|
name: 'modern-js-effect-installed-dependencies',
|
|
138
146
|
setup(buildApi) {
|
|
139
147
|
buildApi.onResolve({ filter: /.*/ }, async args => {
|
|
148
|
+
if (BFF_RUNTIME_PACKAGE.test(args.path)) {
|
|
149
|
+
return { external: true, path: args.path };
|
|
150
|
+
}
|
|
140
151
|
if (
|
|
141
152
|
!isBareSpecifier(args.path) ||
|
|
142
153
|
nodeBuiltins.has(args.path) ||
|
|
@@ -167,7 +178,13 @@ function externalizeInstalledDependencies(options: {
|
|
|
167
178
|
const realPath = await fs.promises
|
|
168
179
|
.realpath(resolution.path)
|
|
169
180
|
.catch(() => resolution.path);
|
|
170
|
-
|
|
181
|
+
const loader = SOURCE_LOADERS.get(path.extname(realPath).toLowerCase());
|
|
182
|
+
if (
|
|
183
|
+
realPath.includes(`${path.sep}node_modules${path.sep}`) &&
|
|
184
|
+
loader !== 'ts' &&
|
|
185
|
+
loader !== 'tsx' &&
|
|
186
|
+
loader !== 'jsx'
|
|
187
|
+
) {
|
|
171
188
|
const runtimeResolution = await buildApi.resolve(args.path, {
|
|
172
189
|
importer: '',
|
|
173
190
|
kind: args.kind,
|
|
@@ -341,6 +358,7 @@ export async function loadEffectSourceModule(
|
|
|
341
358
|
js: `import { createRequire as __modernCreateEffectRequire } from 'node:module'; const require = __modernCreateEffectRequire(${JSON.stringify(pathToFileURL(resourcePath).href)});`,
|
|
342
359
|
},
|
|
343
360
|
bundle: true,
|
|
361
|
+
define: serializeServerGlobalVars(options.globalVars),
|
|
344
362
|
entryPoints: [resourcePath],
|
|
345
363
|
format: 'esm',
|
|
346
364
|
jsx: 'automatic',
|
|
@@ -4,48 +4,19 @@ import {
|
|
|
4
4
|
} from '@modern-js/bff-effect/effect';
|
|
5
5
|
import {
|
|
6
6
|
buildOperationContractMap,
|
|
7
|
-
|
|
7
|
+
resolveOperationProducer,
|
|
8
8
|
} from '@modern-js/server-runtime-extensions/bff-policy/node';
|
|
9
|
-
import {
|
|
9
|
+
import { upath as path } from '@modern-js/utils';
|
|
10
|
+
import type { ServerGlobalVarsOptions } from '../server-global-vars';
|
|
10
11
|
import { getHttpApiRuntime, loadEffectApi } from './http-api-runtime';
|
|
11
12
|
|
|
12
|
-
function getPackageInfo(
|
|
13
|
-
resourcePath: string,
|
|
14
|
-
appDir: string,
|
|
15
|
-
onDependency?: (dependency: string) => void,
|
|
16
|
-
): { name?: string; version?: string } {
|
|
17
|
-
for (const startDir of [path.dirname(resourcePath), appDir]) {
|
|
18
|
-
let current = path.resolve(startDir);
|
|
19
|
-
for (let depth = 0; depth < 32; depth += 1) {
|
|
20
|
-
const packageJsonPath = path.join(current, 'package.json');
|
|
21
|
-
if (fs.existsSync(packageJsonPath)) {
|
|
22
|
-
onDependency?.(packageJsonPath);
|
|
23
|
-
try {
|
|
24
|
-
const packageJson = fs.readJSONSync(packageJsonPath) as {
|
|
25
|
-
name?: string;
|
|
26
|
-
version?: string;
|
|
27
|
-
};
|
|
28
|
-
return { name: packageJson.name, version: packageJson.version };
|
|
29
|
-
} catch {
|
|
30
|
-
return {};
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
const parent = path.dirname(current);
|
|
34
|
-
if (parent === current) {
|
|
35
|
-
break;
|
|
36
|
-
}
|
|
37
|
-
current = parent;
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
return {};
|
|
41
|
-
}
|
|
42
|
-
|
|
43
13
|
/** Derives server policy metadata without emitting or typing a client. */
|
|
44
14
|
export async function resolveEffectOperationContracts(options: {
|
|
45
15
|
appDir: string;
|
|
46
16
|
resourcePath: string;
|
|
47
17
|
prefix: string;
|
|
48
18
|
requestId?: string;
|
|
19
|
+
globalVars?: ServerGlobalVarsOptions;
|
|
49
20
|
onDependency?: (dependency: string) => void;
|
|
50
21
|
}) {
|
|
51
22
|
const api = await loadEffectApi(options);
|
|
@@ -58,15 +29,12 @@ export async function resolveEffectOperationContracts(options: {
|
|
|
58
29
|
api,
|
|
59
30
|
options.prefix,
|
|
60
31
|
);
|
|
61
|
-
const packageInfo = getPackageInfo(
|
|
62
|
-
options.resourcePath,
|
|
63
|
-
options.appDir,
|
|
64
|
-
options.onDependency,
|
|
65
|
-
);
|
|
66
|
-
const requestId = options.requestId?.trim() || packageInfo.name || 'default';
|
|
67
32
|
return buildOperationContractMap({
|
|
68
33
|
handlers: toOperationContractSources(endpoints),
|
|
69
|
-
|
|
70
|
-
|
|
34
|
+
...resolveOperationProducer({
|
|
35
|
+
directories: [path.dirname(options.resourcePath), options.appDir],
|
|
36
|
+
requestId: options.requestId,
|
|
37
|
+
onDependency: options.onDependency,
|
|
38
|
+
}),
|
|
71
39
|
});
|
|
72
40
|
}
|
|
@@ -9,32 +9,66 @@ const JS_OR_TS_EXTS = [
|
|
|
9
9
|
'.mts',
|
|
10
10
|
'.cjs',
|
|
11
11
|
'.cts',
|
|
12
|
-
]
|
|
12
|
+
];
|
|
13
13
|
|
|
14
|
-
export
|
|
14
|
+
export const emittedEffectEntry = (entry: string) =>
|
|
15
|
+
entry.replace(/\.(?:[cm]?ts|tsx|jsx)$/u, '.js');
|
|
16
|
+
|
|
17
|
+
export function relativeEffectAppPath(appDir: string, entry: string) {
|
|
18
|
+
const relative = path.relative(appDir, entry);
|
|
19
|
+
return relative === '..' ||
|
|
20
|
+
relative.startsWith('../') ||
|
|
21
|
+
relative.split('/').includes('node_modules')
|
|
22
|
+
? undefined
|
|
23
|
+
: relative;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function existingEntry(entry: string): string | undefined {
|
|
27
|
+
return path.extname(entry)
|
|
28
|
+
? fs.existsSync(entry)
|
|
29
|
+
? entry
|
|
30
|
+
: undefined
|
|
31
|
+
: findExists(JS_OR_TS_EXTS.map(ext => `${entry}${ext}`)) || undefined;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
type EffectEntryOptions = {
|
|
15
35
|
appDir: string;
|
|
16
36
|
apiDir: string;
|
|
17
37
|
effectEntry?: string;
|
|
18
|
-
}
|
|
19
|
-
|
|
38
|
+
};
|
|
39
|
+
export type EffectEntry =
|
|
40
|
+
| { kind: 'app-source'; path: string | undefined }
|
|
41
|
+
| { kind: 'built-output'; path: string | undefined }
|
|
42
|
+
| { kind: 'external-sdk'; path: string | undefined };
|
|
20
43
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
if (effectEntry !== undefined && effectEntry !== '') {
|
|
33
|
-
const entryWithoutExt = path.isAbsolute(effectEntry)
|
|
34
|
-
? effectEntry
|
|
35
|
-
: path.resolve(appDir, effectEntry);
|
|
36
|
-
return resolveEntry(entryWithoutExt);
|
|
44
|
+
/** Classify ownership before resolving files: production works without source. */
|
|
45
|
+
export function resolveEffectEntry(
|
|
46
|
+
options: EffectEntryOptions & { distDir?: string },
|
|
47
|
+
): EffectEntry {
|
|
48
|
+
const { appDir, apiDir, effectEntry, distDir } = options;
|
|
49
|
+
const entry = path.resolve(appDir, effectEntry || path.join(apiDir, 'index'));
|
|
50
|
+
if (distDir && relativeEffectAppPath(distDir, entry) !== undefined) {
|
|
51
|
+
return {
|
|
52
|
+
kind: 'built-output',
|
|
53
|
+
path: existingEntry(emittedEffectEntry(entry)),
|
|
54
|
+
};
|
|
37
55
|
}
|
|
56
|
+
const relative = relativeEffectAppPath(appDir, entry);
|
|
57
|
+
if (relative === undefined) {
|
|
58
|
+
return { kind: 'external-sdk', path: existingEntry(entry) };
|
|
59
|
+
}
|
|
60
|
+
return distDir
|
|
61
|
+
? {
|
|
62
|
+
kind: 'built-output',
|
|
63
|
+
path: existingEntry(
|
|
64
|
+
emittedEffectEntry(path.resolve(distDir, relative)),
|
|
65
|
+
),
|
|
66
|
+
}
|
|
67
|
+
: { kind: 'app-source', path: existingEntry(entry) };
|
|
68
|
+
}
|
|
38
69
|
|
|
39
|
-
|
|
70
|
+
export function resolveEffectEntryFile(
|
|
71
|
+
options: EffectEntryOptions,
|
|
72
|
+
): string | undefined {
|
|
73
|
+
return resolveEffectEntry(options).path;
|
|
40
74
|
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
ServerGlobalVars,
|
|
3
|
+
ServerGlobalVarsContext,
|
|
4
|
+
ServerSourceConfigExtension,
|
|
5
|
+
} from '@modern-js/runtime-extensions/server-config';
|
|
6
|
+
import { applyOptionsChain } from '@modern-js/utils';
|
|
7
|
+
|
|
8
|
+
export type ServerGlobalVarsOptions = ServerSourceConfigExtension['globalVars'];
|
|
9
|
+
|
|
10
|
+
/** Each global name mapped to the JSON source text that replaces it. */
|
|
11
|
+
export type SerializedServerGlobalVars = Record<string, string>;
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Resolves `source.globalVars` for BFF server code and serializes every value
|
|
15
|
+
* to the JSON text that replaces it. Dev source loading and build output use
|
|
16
|
+
* this one function, so both see the same values. A value without an exact
|
|
17
|
+
* JSON form (such as `undefined`, a function or a BigInt) is rejected.
|
|
18
|
+
*/
|
|
19
|
+
export const serializeServerGlobalVars = (
|
|
20
|
+
options: ServerGlobalVarsOptions,
|
|
21
|
+
): SerializedServerGlobalVars => {
|
|
22
|
+
const globalVars = applyOptionsChain<
|
|
23
|
+
ServerGlobalVars,
|
|
24
|
+
ServerGlobalVarsContext
|
|
25
|
+
>({}, options, { env: 'server', target: 'node' });
|
|
26
|
+
|
|
27
|
+
return Object.fromEntries(
|
|
28
|
+
Object.entries(globalVars).map(([key, value]) => {
|
|
29
|
+
let serialized: string | undefined;
|
|
30
|
+
try {
|
|
31
|
+
serialized = JSON.stringify(value);
|
|
32
|
+
} catch (error) {
|
|
33
|
+
throw new Error(
|
|
34
|
+
`source.globalVars["${key}"] cannot be serialized exactly for BFF server code.`,
|
|
35
|
+
{ cause: error },
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
if (serialized === undefined) {
|
|
39
|
+
throw new Error(
|
|
40
|
+
`source.globalVars["${key}"] cannot be serialized exactly for BFF server code.`,
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
return [key, serialized];
|
|
44
|
+
}),
|
|
45
|
+
);
|
|
46
|
+
};
|
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __webpack_require__ = {};
|
|
3
|
-
(()=>{
|
|
4
|
-
__webpack_require__.d = (exports1, getters, values)=>{
|
|
5
|
-
var define = (defs, kind)=>{
|
|
6
|
-
for(var key in defs)if (__webpack_require__.o(defs, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
|
|
7
|
-
enumerable: true,
|
|
8
|
-
[kind]: defs[key]
|
|
9
|
-
});
|
|
10
|
-
};
|
|
11
|
-
define(getters, "get");
|
|
12
|
-
define(values, "value");
|
|
13
|
-
};
|
|
14
|
-
})();
|
|
15
|
-
(()=>{
|
|
16
|
-
__webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
|
|
17
|
-
})();
|
|
18
|
-
(()=>{
|
|
19
|
-
__webpack_require__.r = (exports1)=>{
|
|
20
|
-
if ("u" > typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
|
|
21
|
-
value: 'Module'
|
|
22
|
-
});
|
|
23
|
-
Object.defineProperty(exports1, '__esModule', {
|
|
24
|
-
value: true
|
|
25
|
-
});
|
|
26
|
-
};
|
|
27
|
-
})();
|
|
28
|
-
var __webpack_exports__ = {};
|
|
29
|
-
__webpack_require__.r(__webpack_exports__);
|
|
30
|
-
__webpack_require__.d(__webpack_exports__, {
|
|
31
|
-
loadBackendFederationExpose: ()=>loadBackendFederationExpose
|
|
32
|
-
});
|
|
33
|
-
const backend_federation_security_namespaceObject = require("@modern-js/server-runtime-extensions/backend-federation-security");
|
|
34
|
-
const external_utils_js_namespaceObject = require("./utils.js");
|
|
35
|
-
function decodeDataUrl(url) {
|
|
36
|
-
const commaIndex = url.indexOf(',');
|
|
37
|
-
if (commaIndex < 0) throw new Error('[BFF][Effect] Invalid backend federation data URL entry.');
|
|
38
|
-
return decodeURIComponent(url.slice(commaIndex + 1));
|
|
39
|
-
}
|
|
40
|
-
async function readCommonJsEntrySource(remote) {
|
|
41
|
-
if (remote.entry.startsWith('data:')) return decodeDataUrl(remote.entry);
|
|
42
|
-
throw new Error(`[BFF][Effect] Backend federation remote ${remote.name} cannot load CommonJS entry ${remote.entry}.`);
|
|
43
|
-
}
|
|
44
|
-
async function importModuleEntry(remote) {
|
|
45
|
-
const entry = await import(remote.entry);
|
|
46
|
-
return entry.default ?? entry;
|
|
47
|
-
}
|
|
48
|
-
async function resolvePluginEntry(remote, plugins) {
|
|
49
|
-
for (const plugin of plugins ?? []){
|
|
50
|
-
const loadEntry = plugin.loadEntry;
|
|
51
|
-
if ('function' != typeof loadEntry) continue;
|
|
52
|
-
const entry = await loadEntry({
|
|
53
|
-
remoteInfo: remote
|
|
54
|
-
});
|
|
55
|
-
if (entry) return entry;
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
async function loadBackendFederationEntry(remote, options) {
|
|
59
|
-
const requiresVerification = Boolean(remote.verification || options.entryPolicy?.expected);
|
|
60
|
-
const isNetworkEntry = /^https?:\/\//iu.test(remote.entry);
|
|
61
|
-
if (isNetworkEntry && !requiresVerification) throw new Error(`[BFF][Effect] Backend federation remote ${remote.name} requires verified entry bytes before network execution.`);
|
|
62
|
-
if (requiresVerification) return (0, backend_federation_security_namespaceObject.loadVerifiedBackendFederationEntry)({
|
|
63
|
-
...options.entryPolicy,
|
|
64
|
-
remote,
|
|
65
|
-
...remote.verification ? {
|
|
66
|
-
verification: remote.verification
|
|
67
|
-
} : {}
|
|
68
|
-
});
|
|
69
|
-
const pluginEntry = await resolvePluginEntry(remote, options.plugins);
|
|
70
|
-
if (pluginEntry) return pluginEntry;
|
|
71
|
-
if (remote.entryGlobalName) {
|
|
72
|
-
const globalEntry = globalThis[remote.entryGlobalName];
|
|
73
|
-
if ((0, external_utils_js_namespaceObject.isRecord)(globalEntry)) return globalEntry;
|
|
74
|
-
}
|
|
75
|
-
if ('module' === remote.type || remote.entry.startsWith('file:')) return importModuleEntry(remote);
|
|
76
|
-
return (0, backend_federation_security_namespaceObject.evaluateBackendFederationCommonJsEntry)(remote, new TextEncoder().encode(await readCommonJsEntrySource(remote)), options.entryPolicy?.evaluateCommonJs);
|
|
77
|
-
}
|
|
78
|
-
async function loadBackendFederationExpose(remote, expose, options) {
|
|
79
|
-
const entry = await loadBackendFederationEntry(remote, options);
|
|
80
|
-
if ('function' == typeof entry.init) await entry.init({
|
|
81
|
-
hostName: options.hostName
|
|
82
|
-
});
|
|
83
|
-
if ('function' != typeof entry.get) throw new Error(`[BFF][Effect] Backend federation remote ${remote.name} entry must expose get().`);
|
|
84
|
-
const factory = await entry.get(expose);
|
|
85
|
-
if ('function' != typeof factory) throw new Error(`[BFF][Effect] Backend federation expose ${remote.name}/${(0, external_utils_js_namespaceObject.normalizeExpose)(expose)} must load factory function.`);
|
|
86
|
-
return factory();
|
|
87
|
-
}
|
|
88
|
-
exports.loadBackendFederationExpose = __webpack_exports__.loadBackendFederationExpose;
|
|
89
|
-
for(var __rspack_i in __webpack_exports__)if (-1 === [
|
|
90
|
-
"loadBackendFederationExpose"
|
|
91
|
-
].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
|
|
92
|
-
Object.defineProperty(exports, '__esModule', {
|
|
93
|
-
value: true
|
|
94
|
-
});
|
|
@@ -1,99 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __webpack_require__ = {};
|
|
3
|
-
(()=>{
|
|
4
|
-
__webpack_require__.n = (module)=>{
|
|
5
|
-
var getter = module && module.__esModule ? ()=>module['default'] : ()=>module;
|
|
6
|
-
__webpack_require__.d(getter, {
|
|
7
|
-
a: getter
|
|
8
|
-
});
|
|
9
|
-
return getter;
|
|
10
|
-
};
|
|
11
|
-
})();
|
|
12
|
-
(()=>{
|
|
13
|
-
__webpack_require__.d = (exports1, getters, values)=>{
|
|
14
|
-
var define = (defs, kind)=>{
|
|
15
|
-
for(var key in defs)if (__webpack_require__.o(defs, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
|
|
16
|
-
enumerable: true,
|
|
17
|
-
[kind]: defs[key]
|
|
18
|
-
});
|
|
19
|
-
};
|
|
20
|
-
define(getters, "get");
|
|
21
|
-
define(values, "value");
|
|
22
|
-
};
|
|
23
|
-
})();
|
|
24
|
-
(()=>{
|
|
25
|
-
__webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
|
|
26
|
-
})();
|
|
27
|
-
(()=>{
|
|
28
|
-
__webpack_require__.r = (exports1)=>{
|
|
29
|
-
if ("u" > typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
|
|
30
|
-
value: 'Module'
|
|
31
|
-
});
|
|
32
|
-
Object.defineProperty(exports1, '__esModule', {
|
|
33
|
-
value: true
|
|
34
|
-
});
|
|
35
|
-
};
|
|
36
|
-
})();
|
|
37
|
-
var __webpack_exports__ = {};
|
|
38
|
-
__webpack_require__.r(__webpack_exports__);
|
|
39
|
-
__webpack_require__.d(__webpack_exports__, {
|
|
40
|
-
resolveEffectAdapterEntryFile: ()=>resolveEffectAdapterEntryFile
|
|
41
|
-
});
|
|
42
|
-
const external_node_path_namespaceObject = require("node:path");
|
|
43
|
-
var external_node_path_default = /*#__PURE__*/ __webpack_require__.n(external_node_path_namespaceObject);
|
|
44
|
-
require("@modern-js/server-runtime-extensions/server-config");
|
|
45
|
-
const utils_namespaceObject = require("@modern-js/utils");
|
|
46
|
-
const JS_OR_TS_EXTS = [
|
|
47
|
-
'.js',
|
|
48
|
-
'.jsx',
|
|
49
|
-
'.ts',
|
|
50
|
-
'.tsx',
|
|
51
|
-
'.mjs',
|
|
52
|
-
'.mts',
|
|
53
|
-
'.cjs',
|
|
54
|
-
'.cts'
|
|
55
|
-
];
|
|
56
|
-
function resolveJsOrTsEntry(entryWithoutOrWithExt) {
|
|
57
|
-
const extension = external_node_path_default().extname(entryWithoutOrWithExt);
|
|
58
|
-
if (JS_OR_TS_EXTS.includes(extension)) return utils_namespaceObject.fs.existsSync(entryWithoutOrWithExt) ? entryWithoutOrWithExt : void 0;
|
|
59
|
-
return (0, utils_namespaceObject.findExists)(JS_OR_TS_EXTS.map((ext)=>`${entryWithoutOrWithExt}${ext}`)) || void 0;
|
|
60
|
-
}
|
|
61
|
-
function builtEntryPath(entryPath) {
|
|
62
|
-
return entryPath.replace(/\.(?:[cm]?ts|tsx|jsx)$/u, '.js');
|
|
63
|
-
}
|
|
64
|
-
function relativeAppPath(appDirectory, entryPath) {
|
|
65
|
-
const relativePath = external_node_path_default().relative(appDirectory, entryPath);
|
|
66
|
-
return '..' === relativePath || relativePath.startsWith(`..${external_node_path_default().sep}`) ? void 0 : relativePath;
|
|
67
|
-
}
|
|
68
|
-
function isDependencyPath(relativePath) {
|
|
69
|
-
return relativePath?.split(/[\\/]/u).includes('node_modules') ?? false;
|
|
70
|
-
}
|
|
71
|
-
function resolveEffectAdapterEntryFile(api) {
|
|
72
|
-
const { appDirectory, apiDirectory, distDirectory } = api.getServerContext();
|
|
73
|
-
const appRoot = external_node_path_default().resolve(appDirectory || process.cwd());
|
|
74
|
-
const productionRoot = (0, utils_namespaceObject.isProd)() && distDirectory ? external_node_path_default().resolve(distDirectory) : void 0;
|
|
75
|
-
const configuredEntry = api.getServerConfig()?.bff?.effect?.entry;
|
|
76
|
-
if (configuredEntry) {
|
|
77
|
-
const sourceEntry = external_node_path_default().isAbsolute(configuredEntry) ? configuredEntry : external_node_path_default().resolve(appRoot, configuredEntry);
|
|
78
|
-
if (productionRoot) {
|
|
79
|
-
const relativeEntry = relativeAppPath(appRoot, sourceEntry);
|
|
80
|
-
if (void 0 === relativeEntry || isDependencyPath(relativeEntry)) return resolveJsOrTsEntry(sourceEntry);
|
|
81
|
-
return relativeEntry ? resolveJsOrTsEntry(builtEntryPath(external_node_path_default().resolve(productionRoot, relativeEntry))) : void 0;
|
|
82
|
-
}
|
|
83
|
-
return resolveJsOrTsEntry(sourceEntry);
|
|
84
|
-
}
|
|
85
|
-
const resolvedApiDirectory = external_node_path_default().resolve(appRoot, apiDirectory || utils_namespaceObject.API_DIR);
|
|
86
|
-
const productionApiDirectory = productionRoot ? void 0 !== relativeAppPath(productionRoot, resolvedApiDirectory) ? resolvedApiDirectory : (()=>{
|
|
87
|
-
const relativeApiDirectory = relativeAppPath(appRoot, resolvedApiDirectory);
|
|
88
|
-
if (isDependencyPath(relativeApiDirectory)) return resolvedApiDirectory;
|
|
89
|
-
return relativeApiDirectory ? external_node_path_default().resolve(productionRoot, relativeApiDirectory) : void 0;
|
|
90
|
-
})() : resolvedApiDirectory;
|
|
91
|
-
return productionApiDirectory ? resolveJsOrTsEntry(external_node_path_default().resolve(productionApiDirectory, 'index')) : void 0;
|
|
92
|
-
}
|
|
93
|
-
exports.resolveEffectAdapterEntryFile = __webpack_exports__.resolveEffectAdapterEntryFile;
|
|
94
|
-
for(var __rspack_i in __webpack_exports__)if (-1 === [
|
|
95
|
-
"resolveEffectAdapterEntryFile"
|
|
96
|
-
].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
|
|
97
|
-
Object.defineProperty(exports, '__esModule', {
|
|
98
|
-
value: true
|
|
99
|
-
});
|