@bleedingdev/modern-js-plugin-bff 3.5.0-ultramodern.98 → 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.
- package/dist/cjs/cli/compress.js +1 -1
- package/dist/cjs/cli/generator.js +106 -97
- package/dist/cjs/cli/serverGlobalVars.js +43 -57
- package/dist/cjs/cli.js +6 -2
- package/dist/cjs/loader.js +6 -5
- package/dist/cjs/runtime/effect/adapter/cross-project-policy.js +17 -12
- package/dist/cjs/runtime/effect/adapter/entry.js +13 -5
- package/dist/cjs/runtime/effect/adapter/error-response.js +11 -9
- package/dist/cjs/runtime/effect/adapter.js +2 -2
- package/dist/cjs/runtime/effect/backend-federation/load.js +26 -17
- package/dist/cjs/runtime/effect/backend-federation/plugin.js +12 -2
- package/dist/cjs/runtime/effect/backend-federation/remotes.js +5 -4
- package/dist/cjs/runtime/effect/backend-federation/runtime.js +80 -16
- package/dist/cjs/runtime/effect/edge-dispatcher.js +148 -0
- package/dist/cjs/runtime/effect/edge.js +19 -100
- package/dist/cjs/runtime/effect/endpoint-contracts.js +6 -1
- package/dist/cjs/runtime/effect/handler/definition.js +1 -0
- package/dist/cjs/runtime/effect/handler/http.js +17 -6
- package/dist/cjs/runtime/hono/adapter.js +32 -79
- package/dist/cjs/server.js +19 -30
- package/dist/cjs/utils/client-generator/write-package.js +1 -1
- package/dist/cjs/utils/crossProjectApiPlugin.js +21 -2
- package/dist/cjs/utils/effect-client-generator/generator.js +17 -16
- package/dist/cjs/utils/effect-client-generator/paths.js +4 -15
- package/dist/cjs/utils/effect-client-generator/rendering.js +8 -19
- package/dist/cjs/utils/effect-client-generator/runtime.js +15 -32
- package/dist/cjs/utils/effectSourceLoader.js +70 -10
- package/dist/cjs/utils/pluginGenerator.js +4 -4
- package/dist/esm/cli/compress.mjs +1 -1
- package/dist/esm/cli/generator.mjs +108 -98
- package/dist/esm/cli/serverGlobalVars.mjs +44 -48
- package/dist/esm/cli.mjs +2 -0
- package/dist/esm/loader.mjs +6 -5
- package/dist/esm/runtime/effect/adapter/cross-project-policy.mjs +17 -12
- package/dist/esm/runtime/effect/adapter/entry.mjs +13 -5
- package/dist/esm/runtime/effect/adapter/error-response.mjs +11 -9
- package/dist/esm/runtime/effect/adapter.mjs +3 -3
- package/dist/esm/runtime/effect/backend-federation/load.mjs +26 -17
- package/dist/esm/runtime/effect/backend-federation/plugin.mjs +12 -2
- package/dist/esm/runtime/effect/backend-federation/remotes.mjs +5 -4
- package/dist/esm/runtime/effect/backend-federation/runtime.mjs +80 -16
- package/dist/esm/runtime/effect/edge-dispatcher.mjs +38 -0
- package/dist/esm/runtime/effect/edge.mjs +1 -38
- package/dist/esm/runtime/effect/endpoint-contracts.mjs +6 -1
- package/dist/esm/runtime/effect/handler/definition.mjs +1 -0
- package/dist/esm/runtime/effect/handler/http.mjs +17 -6
- package/dist/esm/runtime/hono/adapter.mjs +33 -80
- package/dist/esm/server.mjs +18 -29
- package/dist/esm/utils/client-generator/write-package.mjs +1 -1
- package/dist/esm/utils/crossProjectApiPlugin.mjs +16 -3
- package/dist/esm/utils/effect-client-generator/generator.mjs +17 -16
- package/dist/esm/utils/effect-client-generator/paths.mjs +5 -6
- package/dist/esm/utils/effect-client-generator/rendering.mjs +9 -10
- package/dist/esm/utils/effect-client-generator/runtime.mjs +16 -23
- package/dist/esm/utils/effectSourceLoader.mjs +69 -12
- package/dist/esm/utils/pluginGenerator.mjs +5 -5
- package/dist/esm-node/cli/compress.mjs +1 -1
- package/dist/esm-node/cli/generator.mjs +108 -98
- package/dist/esm-node/cli/serverGlobalVars.mjs +44 -48
- package/dist/esm-node/cli.mjs +2 -0
- package/dist/esm-node/loader.mjs +6 -5
- package/dist/esm-node/runtime/effect/adapter/cross-project-policy.mjs +17 -12
- package/dist/esm-node/runtime/effect/adapter/entry.mjs +13 -5
- package/dist/esm-node/runtime/effect/adapter/error-response.mjs +11 -9
- package/dist/esm-node/runtime/effect/adapter.mjs +3 -3
- package/dist/esm-node/runtime/effect/backend-federation/load.mjs +26 -17
- package/dist/esm-node/runtime/effect/backend-federation/plugin.mjs +12 -2
- package/dist/esm-node/runtime/effect/backend-federation/remotes.mjs +5 -4
- package/dist/esm-node/runtime/effect/backend-federation/runtime.mjs +80 -16
- package/dist/esm-node/runtime/effect/edge-dispatcher.mjs +39 -0
- package/dist/esm-node/runtime/effect/edge.mjs +1 -38
- package/dist/esm-node/runtime/effect/endpoint-contracts.mjs +6 -1
- package/dist/esm-node/runtime/effect/handler/definition.mjs +1 -0
- package/dist/esm-node/runtime/effect/handler/http.mjs +17 -6
- package/dist/esm-node/runtime/hono/adapter.mjs +33 -80
- package/dist/esm-node/server.mjs +18 -29
- package/dist/esm-node/utils/client-generator/write-package.mjs +1 -1
- package/dist/esm-node/utils/crossProjectApiPlugin.mjs +16 -3
- package/dist/esm-node/utils/effect-client-generator/generator.mjs +17 -16
- package/dist/esm-node/utils/effect-client-generator/paths.mjs +5 -6
- package/dist/esm-node/utils/effect-client-generator/rendering.mjs +9 -10
- package/dist/esm-node/utils/effect-client-generator/runtime.mjs +16 -23
- package/dist/esm-node/utils/effectSourceLoader.mjs +69 -12
- package/dist/esm-node/utils/pluginGenerator.mjs +5 -5
- package/dist/types/cli/generator.d.ts +2 -2
- package/dist/types/cli/serverGlobalVars.d.ts +4 -2
- package/dist/types/cli.d.ts +1 -0
- package/dist/types/runtime/effect/adapter/cross-project-policy.d.ts +1 -1
- package/dist/types/runtime/effect/backend-federation/runtime.d.ts +1 -1
- package/dist/types/runtime/effect/edge-dispatcher.d.ts +26 -0
- package/dist/types/runtime/effect/edge.d.ts +1 -26
- package/dist/types/runtime/effect/endpoint-contracts.d.ts +6 -0
- package/dist/types/runtime/effect/handler/definition.d.ts +2 -12
- package/dist/types/runtime/effect/handler/http.d.ts +3 -2
- package/dist/types/runtime/effect/handler/openapi.d.ts +1 -1
- package/dist/types/runtime/effect/handler/types.d.ts +10 -5
- package/dist/types/runtime/effect-client/index.d.ts +1 -1
- package/dist/types/runtime/hono/adapter.d.ts +14 -8
- package/dist/types/utils/crossProjectApiPlugin.d.ts +2 -0
- package/dist/types/utils/effectSourceLoader.d.ts +10 -0
- package/dist/types/utils/pluginGenerator.d.ts +3 -1
- package/package.json +44 -16
package/dist/esm/server.mjs
CHANGED
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
import { ApiRouter } from "@modern-js/bff-core";
|
|
2
2
|
import { API_DIR, isFunction, isWebOnly } from "@modern-js/utils";
|
|
3
3
|
import path from "path";
|
|
4
|
-
import { EffectAdapter } from "./runtime/effect/adapter.mjs";
|
|
5
4
|
import { HonoAdapter } from "./runtime/hono/adapter.mjs";
|
|
6
|
-
const
|
|
7
|
-
hono: [
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
effect:
|
|
11
|
-
|
|
12
|
-
|
|
5
|
+
const RUNTIME_ADAPTER_LOADERS = {
|
|
6
|
+
hono: async (api)=>[
|
|
7
|
+
new HonoAdapter(api)
|
|
8
|
+
],
|
|
9
|
+
effect: async (api)=>{
|
|
10
|
+
const { EffectAdapter } = await import("./runtime/effect/adapter.mjs");
|
|
11
|
+
return [
|
|
12
|
+
new EffectAdapter(api)
|
|
13
|
+
];
|
|
14
|
+
}
|
|
13
15
|
};
|
|
14
16
|
const normalizePrefixList = (prefix)=>{
|
|
15
17
|
if (Array.isArray(prefix)) return prefix.filter(Boolean);
|
|
@@ -22,9 +24,6 @@ function resolveRuntimeFramework(runtimeFramework) {
|
|
|
22
24
|
return 'hono' === runtimeFramework ? 'hono' : 'effect';
|
|
23
25
|
}
|
|
24
26
|
class Storage {
|
|
25
|
-
reset() {
|
|
26
|
-
this.middlewares = [];
|
|
27
|
-
}
|
|
28
27
|
constructor(){
|
|
29
28
|
this.middlewares = [];
|
|
30
29
|
}
|
|
@@ -36,7 +35,6 @@ const server = ()=>({
|
|
|
36
35
|
let apiRouter = null;
|
|
37
36
|
const appContext = api.getServerContext();
|
|
38
37
|
const runtimeFramework = resolveRuntimeFramework(appContext.bffRuntimeFramework);
|
|
39
|
-
const runtimeAdapters = RUNTIME_ADAPTER_FACTORIES[runtimeFramework].map((createAdapter)=>createAdapter(api));
|
|
40
38
|
api.onPrepare(async ()=>{
|
|
41
39
|
const appContext = api.getServerContext();
|
|
42
40
|
const { render } = appContext;
|
|
@@ -82,29 +80,20 @@ const server = ()=>({
|
|
|
82
80
|
]
|
|
83
81
|
});
|
|
84
82
|
}
|
|
83
|
+
const runtimeAdapters = await RUNTIME_ADAPTER_LOADERS[runtimeFramework](api);
|
|
85
84
|
await Promise.all(runtimeAdapters.map((adapter)=>adapter.registerMiddleware({
|
|
86
85
|
prefix,
|
|
87
86
|
enableHandleWeb
|
|
88
87
|
})));
|
|
89
88
|
});
|
|
90
89
|
api.onReset(async ({ event })=>{
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
if ('file-change' === event.type) {
|
|
99
|
-
if ('hono' === runtimeFramework && apiRouter) {
|
|
100
|
-
const apiHandlerInfos = await apiRouter.getApiHandlers();
|
|
101
|
-
const appContext = api.getServerContext();
|
|
102
|
-
api.updateServerContext({
|
|
103
|
-
...appContext,
|
|
104
|
-
apiHandlerInfos
|
|
105
|
-
});
|
|
106
|
-
}
|
|
107
|
-
await Promise.all(runtimeAdapters.map((adapter)=>adapter.onApiHandlersUpdated?.()));
|
|
90
|
+
if ('file-change' === event.type && apiRouter) {
|
|
91
|
+
const appContext = api.getServerContext();
|
|
92
|
+
const apiHandlerInfos = await apiRouter.getApiHandlers();
|
|
93
|
+
api.updateServerContext({
|
|
94
|
+
...appContext,
|
|
95
|
+
apiHandlerInfos
|
|
96
|
+
});
|
|
108
97
|
}
|
|
109
98
|
});
|
|
110
99
|
const prepareApiServer = async (input, next)=>{
|
|
@@ -69,6 +69,6 @@ async function setPackage(files, appDirectory, relativeDistPath) {
|
|
|
69
69
|
}
|
|
70
70
|
});
|
|
71
71
|
mergePackageJson(packageJson, addFiles, typesVersions, exports, relativeDistPath);
|
|
72
|
-
await fs.promises.writeFile(packagePath, JSON.stringify(packageJson, null, 2));
|
|
72
|
+
await fs.promises.writeFile(packagePath, `${JSON.stringify(packageJson, null, 2)}\n`);
|
|
73
73
|
}
|
|
74
74
|
export { setPackage, writeClientModuleBoundary };
|
|
@@ -5,6 +5,8 @@ const API_DIR = '{apiDirectory}';
|
|
|
5
5
|
const LAMBDA_DIR = '{lambdaDirectory}';
|
|
6
6
|
const DIST_DIR = '{distDirectory}';
|
|
7
7
|
const RUNTIME_FRAMEWORK = '{runtimeFramework}';
|
|
8
|
+
const EFFECT_ENTRY = '{effectEntry}';
|
|
9
|
+
const OPERATION_CONTRACTS_JSON = '{operationContracts}';
|
|
8
10
|
const NODE_MODULES = 'node_modules';
|
|
9
11
|
const crossProjectApiPlugin = ()=>({
|
|
10
12
|
name: '@modern-js/plugin-independent-bff',
|
|
@@ -16,7 +18,8 @@ const crossProjectApiPlugin = ()=>({
|
|
|
16
18
|
const { appDirectory: originAppDirectory } = api.getAppContext();
|
|
17
19
|
const sdkPath = path.join(originAppDirectory, NODE_MODULES, PACKAGE_NAME);
|
|
18
20
|
const sdkDistPath = path.join(sdkPath, DIST_DIR);
|
|
19
|
-
const
|
|
21
|
+
const effectEntry = EFFECT_ENTRY ? path.join(sdkDistPath, EFFECT_ENTRY) : void 0;
|
|
22
|
+
const apiDirectory = effectEntry ? path.dirname(effectEntry) : path.join(sdkDistPath, API_DIR);
|
|
20
23
|
const lambdaDirectory = path.resolve(sdkDistPath, LAMBDA_DIR);
|
|
21
24
|
api.updateAppContext({
|
|
22
25
|
apiDirectory,
|
|
@@ -31,10 +34,16 @@ const crossProjectApiPlugin = ()=>({
|
|
|
31
34
|
}
|
|
32
35
|
const configuredRuntimeFramework = config?.bff?.runtimeFramework;
|
|
33
36
|
if (configuredRuntimeFramework && configuredRuntimeFramework !== RUNTIME_FRAMEWORK) throw new Error(`[${PACKAGE_NAME}] Runtime framework mismatch for cross-project BFF. Detected "${configuredRuntimeFramework}", but producer SDK requires "${RUNTIME_FRAMEWORK}".`);
|
|
37
|
+
resolvedConfig.bff ??= {};
|
|
34
38
|
resolvedConfig.bff.prefix = PREFIX;
|
|
35
39
|
resolvedConfig.bff.runtimeFramework = RUNTIME_FRAMEWORK;
|
|
40
|
+
if (EFFECT_ENTRY) resolvedConfig.bff.effect = {
|
|
41
|
+
...resolvedConfig.bff.effect,
|
|
42
|
+
entry: effectEntry
|
|
43
|
+
};
|
|
36
44
|
resolvedConfig.bff.isCrossProjectServer = true;
|
|
37
45
|
resolvedConfig.bff.requestId = resolvedConfig.bff.requestId || config?.bff?.requestId || PACKAGE_NAME || 'default';
|
|
46
|
+
const generatedOperationContracts = "{operationContracts}" === OPERATION_CONTRACTS_JSON ? {} : JSON.parse(OPERATION_CONTRACTS_JSON);
|
|
38
47
|
resolvedConfig.bff.crossProjectPolicy = {
|
|
39
48
|
...resolvedConfig.bff.crossProjectPolicy || {},
|
|
40
49
|
enabled: resolvedConfig.bff.crossProjectPolicy?.enabled ?? true,
|
|
@@ -43,7 +52,11 @@ const crossProjectApiPlugin = ()=>({
|
|
|
43
52
|
requireOperationContextDetails: resolvedConfig.bff.crossProjectPolicy?.requireOperationContextDetails ?? true,
|
|
44
53
|
requireOperationSchemaHash: resolvedConfig.bff.crossProjectPolicy?.requireOperationSchemaHash ?? true,
|
|
45
54
|
requireOperationVersion: resolvedConfig.bff.crossProjectPolicy?.requireOperationVersion ?? true,
|
|
46
|
-
allowUnknownOperations: resolvedConfig.bff.crossProjectPolicy?.allowUnknownOperations ?? false
|
|
55
|
+
allowUnknownOperations: resolvedConfig.bff.crossProjectPolicy?.allowUnknownOperations ?? false,
|
|
56
|
+
expectedOperationContracts: {
|
|
57
|
+
...resolvedConfig.bff.crossProjectPolicy?.expectedOperationContracts || {},
|
|
58
|
+
...generatedOperationContracts
|
|
59
|
+
}
|
|
47
60
|
};
|
|
48
61
|
return resolvedConfig;
|
|
49
62
|
});
|
|
@@ -51,4 +64,4 @@ const crossProjectApiPlugin = ()=>({
|
|
|
51
64
|
});
|
|
52
65
|
const utils_crossProjectApiPlugin = crossProjectApiPlugin;
|
|
53
66
|
export default utils_crossProjectApiPlugin;
|
|
54
|
-
export { API_DIR, DIST_DIR, LAMBDA_DIR, PACKAGE_NAME, PREFIX, RUNTIME_FRAMEWORK, crossProjectApiPlugin };
|
|
67
|
+
export { API_DIR, DIST_DIR, EFFECT_ENTRY, LAMBDA_DIR, OPERATION_CONTRACTS_JSON, PACKAGE_NAME, PREFIX, RUNTIME_FRAMEWORK, crossProjectApiPlugin };
|
|
@@ -2,26 +2,27 @@ import { logger } from "@modern-js/utils";
|
|
|
2
2
|
import { collectEffectEndpoints } from "../../runtime/effect/endpoint-contracts.mjs";
|
|
3
3
|
import { renderEffectClientCode, renderEffectClientDeclaration } from "./rendering.mjs";
|
|
4
4
|
import { getHttpApiRuntime, loadEffectApi } from "./runtime.mjs";
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
function generateEffectClient(options) {
|
|
6
|
+
return loadEffectApi({
|
|
7
7
|
appDir: options.appDir,
|
|
8
8
|
resourcePath: options.resourcePath,
|
|
9
9
|
onDependency: options.onDependency
|
|
10
|
+
}).then((api)=>{
|
|
11
|
+
if (null === api) {
|
|
12
|
+
logger.warn(`[BFF][Effect] Failed to generate client for ${options.resourcePath}: unable to resolve exported HttpApi.`);
|
|
13
|
+
return null;
|
|
14
|
+
}
|
|
15
|
+
return getHttpApiRuntime().then((httpApiRuntime)=>{
|
|
16
|
+
const endpoints = collectEffectEndpoints(httpApiRuntime.reflect, api, options.prefix);
|
|
17
|
+
return {
|
|
18
|
+
code: renderEffectClientCode(endpoints, options),
|
|
19
|
+
declaration: renderEffectClientDeclaration(endpoints),
|
|
20
|
+
endpoints
|
|
21
|
+
};
|
|
22
|
+
});
|
|
10
23
|
});
|
|
11
|
-
if (!api) {
|
|
12
|
-
logger.warn(`[BFF][Effect] Failed to generate client for ${options.resourcePath}: unable to resolve exported HttpApi.`);
|
|
13
|
-
return null;
|
|
14
|
-
}
|
|
15
|
-
const httpApiRuntime = await getHttpApiRuntime();
|
|
16
|
-
const endpoints = collectEffectEndpoints(httpApiRuntime.reflect, api, options.prefix);
|
|
17
|
-
return {
|
|
18
|
-
code: renderEffectClientCode(endpoints, options),
|
|
19
|
-
declaration: renderEffectClientDeclaration(endpoints),
|
|
20
|
-
endpoints
|
|
21
|
-
};
|
|
22
24
|
}
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
return artifacts ? artifacts.code : null;
|
|
25
|
+
function generateEffectClientCode(options) {
|
|
26
|
+
return generateEffectClient(options).then((artifacts)=>null === artifacts ? null : artifacts.code);
|
|
26
27
|
}
|
|
27
28
|
export { generateEffectClient, generateEffectClientCode };
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { findExists, fs } from "@modern-js/utils";
|
|
2
|
-
import path from "path";
|
|
1
|
+
import { findExists, fs, upath } from "@modern-js/utils";
|
|
3
2
|
const JS_OR_TS_EXTS = [
|
|
4
3
|
'.js',
|
|
5
4
|
'.jsx',
|
|
@@ -13,13 +12,13 @@ const JS_OR_TS_EXTS = [
|
|
|
13
12
|
function resolveEffectEntryFile(options) {
|
|
14
13
|
const { appDir, apiDir, effectEntry } = options;
|
|
15
14
|
const resolveEntry = (entryWithoutExt)=>{
|
|
16
|
-
if (
|
|
15
|
+
if ('' !== upath.extname(entryWithoutExt)) return fs.existsSync(entryWithoutExt) ? entryWithoutExt : void 0;
|
|
17
16
|
return findExists(JS_OR_TS_EXTS.map((ext)=>`${entryWithoutExt}${ext}`));
|
|
18
17
|
};
|
|
19
|
-
if (effectEntry) {
|
|
20
|
-
const entryWithoutExt =
|
|
18
|
+
if (void 0 !== effectEntry && '' !== effectEntry) {
|
|
19
|
+
const entryWithoutExt = upath.isAbsolute(effectEntry) ? effectEntry : upath.resolve(appDir, effectEntry);
|
|
21
20
|
return resolveEntry(entryWithoutExt);
|
|
22
21
|
}
|
|
23
|
-
return resolveEntry(
|
|
22
|
+
return resolveEntry(upath.resolve(apiDir, 'index'));
|
|
24
23
|
}
|
|
25
24
|
export { resolveEffectEntryFile };
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { deriveOperationVersion } from "@modern-js/bff-core";
|
|
2
|
-
import { fs } from "@modern-js/utils";
|
|
3
|
-
import path from "path";
|
|
2
|
+
import { fs, upath } from "@modern-js/utils";
|
|
4
3
|
import { createEffectEndpointContractHash, ensureLeadingSlash, normalizeEffectPrefix } from "../../runtime/effect/endpoint-contracts.mjs";
|
|
5
4
|
const DEFAULT_REQUEST_CREATOR = '@modern-js/plugin-bff/client';
|
|
6
5
|
const EFFECT_CLIENT_RUNTIME_IMPORT = '@modern-js/plugin-bff/effect-client-runtime';
|
|
@@ -13,17 +12,17 @@ function isAbsoluteUrl(value) {
|
|
|
13
12
|
}
|
|
14
13
|
}
|
|
15
14
|
function resolveBatchEndpoint(prefix, endpoint) {
|
|
16
|
-
const value = endpoint || '/_data/batch';
|
|
15
|
+
const value = void 0 === endpoint || '' === endpoint ? '/_data/batch' : endpoint;
|
|
17
16
|
if (isAbsoluteUrl(value)) return value;
|
|
18
17
|
const normalizedPrefix = normalizeEffectPrefix(prefix);
|
|
19
18
|
const normalizedEndpoint = ensureLeadingSlash(value);
|
|
20
|
-
if (
|
|
19
|
+
if ('' === normalizedPrefix) return normalizedEndpoint;
|
|
21
20
|
if (normalizedEndpoint === normalizedPrefix || normalizedEndpoint.startsWith(`${normalizedPrefix}/`)) return normalizedEndpoint;
|
|
22
21
|
return `${normalizedPrefix}${'/' === normalizedEndpoint ? '' : normalizedEndpoint}`;
|
|
23
22
|
}
|
|
24
23
|
function getPackageInfo(appDir) {
|
|
25
24
|
try {
|
|
26
|
-
const packageJsonPath =
|
|
25
|
+
const packageJsonPath = upath.resolve(appDir, './package.json');
|
|
27
26
|
const packageJson = fs.readJSONSync(packageJsonPath);
|
|
28
27
|
return {
|
|
29
28
|
name: packageJson.name,
|
|
@@ -38,9 +37,9 @@ function renderEffectClientCode(endpoints, options) {
|
|
|
38
37
|
const httpMethodDecider = options.httpMethodDecider || 'functionName';
|
|
39
38
|
const packageInfo = getPackageInfo(options.appDir);
|
|
40
39
|
const packageName = packageInfo.name;
|
|
41
|
-
const dataPlatformAppNamespace = packageName || 'unknown-app';
|
|
42
|
-
const requestId = 'bundle' === options.target ? packageName
|
|
43
|
-
const normalizedRequestId = requestId || 'default';
|
|
40
|
+
const dataPlatformAppNamespace = void 0 === packageName || '' === packageName ? 'unknown-app' : packageName;
|
|
41
|
+
const requestId = 'bundle' === options.target ? void 0 !== packageName && '' !== packageName ? packageName : void 0 : void 0;
|
|
42
|
+
const normalizedRequestId = void 0 === requestId || '' === requestId ? 'default' : requestId;
|
|
44
43
|
const operationVersion = deriveOperationVersion(packageInfo.version);
|
|
45
44
|
const batchConfig = options.dataPlatformBatch;
|
|
46
45
|
const batchEndpoint = resolveBatchEndpoint(options.prefix, batchConfig?.endpoint);
|
|
@@ -57,7 +56,7 @@ function renderEffectClientCode(endpoints, options) {
|
|
|
57
56
|
};
|
|
58
57
|
const config = {
|
|
59
58
|
appNamespace: dataPlatformAppNamespace,
|
|
60
|
-
...requestId ? {
|
|
59
|
+
...void 0 !== requestId && '' !== requestId ? {
|
|
61
60
|
requestId
|
|
62
61
|
} : {},
|
|
63
62
|
port: options.port,
|
|
@@ -71,7 +70,7 @@ function renderEffectClientCode(endpoints, options) {
|
|
|
71
70
|
maxBatchSize: batchConfig?.maxBatchSize ?? 16,
|
|
72
71
|
maxBatchBytes: batchConfig?.maxBatchBytes ?? 65536,
|
|
73
72
|
requestTimeoutMs: batchConfig?.requestTimeoutMs ?? 10000,
|
|
74
|
-
allowedMethods: batchConfig?.allowedMethods && batchConfig.allowedMethods.length > 0 ? batchConfig.allowedMethods : [
|
|
73
|
+
allowedMethods: batchConfig?.allowedMethods !== void 0 && batchConfig.allowedMethods.length > 0 ? batchConfig.allowedMethods : [
|
|
75
74
|
'GET'
|
|
76
75
|
]
|
|
77
76
|
}
|
|
@@ -1,34 +1,27 @@
|
|
|
1
|
-
import { compatibleRequire } from "@modern-js/utils";
|
|
2
|
-
import path from "path";
|
|
1
|
+
import { compatibleRequire, upath } from "@modern-js/utils";
|
|
3
2
|
import { extractHttpApiFromModule } from "../../runtime/effect/endpoint-contracts.mjs";
|
|
4
3
|
import { loadEffectSourceModule } from "../effectSourceLoader.mjs";
|
|
5
4
|
let httpApiRuntimePromise;
|
|
6
5
|
function isRecord(value) {
|
|
7
6
|
return 'object' == typeof value && null !== value;
|
|
8
7
|
}
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
if (isRecord(mod) && isRecord(mod.HttpApi)) {
|
|
22
|
-
const maybeHttpApi = mod.HttpApi;
|
|
23
|
-
if ('function' == typeof maybeHttpApi.isHttpApi && 'function' == typeof maybeHttpApi.reflect) return maybeHttpApi;
|
|
24
|
-
}
|
|
8
|
+
function isHttpApiRuntime(value) {
|
|
9
|
+
return isRecord(value) && 'function' == typeof value.isHttpApi && 'function' == typeof value.reflect;
|
|
10
|
+
}
|
|
11
|
+
function getHttpApiRuntime() {
|
|
12
|
+
if (void 0 === httpApiRuntimePromise) httpApiRuntimePromise = compatibleRequire('effect/unstable/httpapi', false).catch((error)=>{
|
|
13
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
14
|
+
if (!message.includes("Cannot find module 'effect/unstable/httpapi'")) throw error;
|
|
15
|
+
const effectPackageJson = require.resolve('effect/package.json');
|
|
16
|
+
const effectHttpApiRuntimePath = upath.join(upath.dirname(effectPackageJson), 'dist', 'unstable', 'httpapi', 'index.js');
|
|
17
|
+
return compatibleRequire(effectHttpApiRuntimePath, false);
|
|
18
|
+
}).then((mod)=>{
|
|
19
|
+
if (isRecord(mod) && isHttpApiRuntime(mod.HttpApi)) return mod.HttpApi;
|
|
25
20
|
throw new Error('[BFF][Effect] Unable to resolve HttpApi runtime from effect/unstable/httpapi.');
|
|
26
|
-
})
|
|
21
|
+
});
|
|
27
22
|
return httpApiRuntimePromise;
|
|
28
23
|
}
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
const mod = await loadEffectSourceModule(options);
|
|
32
|
-
return extractHttpApiFromModule(mod, httpApiRuntime.isHttpApi);
|
|
24
|
+
function loadEffectApi(options) {
|
|
25
|
+
return getHttpApiRuntime().then((httpApiRuntime)=>loadEffectSourceModule(options).then((mod)=>extractHttpApiFromModule(mod, httpApiRuntime.isHttpApi)));
|
|
33
26
|
}
|
|
34
27
|
export { getHttpApiRuntime, loadEffectApi };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import node_crypto from "node:crypto";
|
|
2
2
|
import node_fs from "node:fs";
|
|
3
|
-
import { builtinModules } from "node:module";
|
|
3
|
+
import { builtinModules, createRequire } from "node:module";
|
|
4
4
|
import node_path from "node:path";
|
|
5
5
|
import { pathToFileURL } from "node:url";
|
|
6
6
|
import { build, transform } from "esbuild";
|
|
@@ -75,10 +75,29 @@ const nodeBuiltins = new Set([
|
|
|
75
75
|
...builtinModules.map((name)=>`node:${name}`)
|
|
76
76
|
]);
|
|
77
77
|
const dependencyResolutionMarker = 'modern-js-effect-dependency-resolution';
|
|
78
|
+
async function isEsmOnlyFile(filename) {
|
|
79
|
+
const extension = node_path.extname(filename).toLowerCase();
|
|
80
|
+
if ('.mjs' === extension || '.mts' === extension) return true;
|
|
81
|
+
if ('.cjs' === extension || '.cts' === extension) return false;
|
|
82
|
+
let directory = node_path.dirname(filename);
|
|
83
|
+
while(true){
|
|
84
|
+
const packagePath = node_path.join(directory, 'package.json');
|
|
85
|
+
try {
|
|
86
|
+
const packageJson = JSON.parse(await node_fs.promises.readFile(packagePath, 'utf8'));
|
|
87
|
+
return 'module' === packageJson.type;
|
|
88
|
+
} catch (error) {
|
|
89
|
+
if (!error || 'object' != typeof error || !('code' in error) || 'ENOENT' !== error.code) throw error;
|
|
90
|
+
}
|
|
91
|
+
const parent = node_path.dirname(directory);
|
|
92
|
+
if (parent === directory) return false;
|
|
93
|
+
directory = parent;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
78
96
|
function isBareSpecifier(specifier) {
|
|
79
97
|
return !specifier.startsWith('.') && !specifier.startsWith('/') && !node_path.isAbsolute(specifier);
|
|
80
98
|
}
|
|
81
|
-
function externalizeInstalledDependencies() {
|
|
99
|
+
function externalizeInstalledDependencies(options) {
|
|
100
|
+
const runtimeRequire = createRequire(node_path.join(options.runtimeResolveDir, '__modern_effect_entry.cjs'));
|
|
82
101
|
return {
|
|
83
102
|
name: 'modern-js-effect-installed-dependencies',
|
|
84
103
|
setup (buildApi) {
|
|
@@ -108,19 +127,46 @@ function externalizeInstalledDependencies() {
|
|
|
108
127
|
path: args.path
|
|
109
128
|
};
|
|
110
129
|
const realPath = await node_fs.promises.realpath(resolution.path).catch(()=>resolution.path);
|
|
111
|
-
if (realPath.includes(`${node_path.sep}node_modules${node_path.sep}`))
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
130
|
+
if (realPath.includes(`${node_path.sep}node_modules${node_path.sep}`)) {
|
|
131
|
+
const runtimeResolution = await buildApi.resolve(args.path, {
|
|
132
|
+
importer: '',
|
|
133
|
+
kind: args.kind,
|
|
134
|
+
namespace: 'file',
|
|
135
|
+
pluginData: {
|
|
136
|
+
[dependencyResolutionMarker]: true
|
|
137
|
+
},
|
|
138
|
+
resolveDir: options.runtimeResolveDir
|
|
139
|
+
});
|
|
140
|
+
if (0 === runtimeResolution.errors.length && runtimeResolution.path) {
|
|
141
|
+
if ('cjs' === options.format) {
|
|
142
|
+
let requiredPath;
|
|
143
|
+
try {
|
|
144
|
+
requiredPath = runtimeRequire.resolve(args.path);
|
|
145
|
+
} catch {
|
|
146
|
+
requiredPath = runtimeResolution.path;
|
|
147
|
+
}
|
|
148
|
+
if (await isEsmOnlyFile(requiredPath)) return {
|
|
149
|
+
namespace: resolution.namespace,
|
|
150
|
+
path: resolution.path,
|
|
151
|
+
pluginData: resolution.pluginData,
|
|
152
|
+
sideEffects: resolution.sideEffects,
|
|
153
|
+
suffix: resolution.suffix,
|
|
154
|
+
warnings: resolution.warnings
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
return {
|
|
158
|
+
external: true,
|
|
159
|
+
path: args.path
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
}
|
|
115
163
|
return {
|
|
116
164
|
namespace: resolution.namespace,
|
|
117
165
|
path: resolution.path,
|
|
118
166
|
pluginData: resolution.pluginData,
|
|
119
167
|
sideEffects: resolution.sideEffects,
|
|
120
168
|
suffix: resolution.suffix,
|
|
121
|
-
warnings: resolution.warnings
|
|
122
|
-
watchDirs: resolution.watchDirs,
|
|
123
|
-
watchFiles: resolution.watchFiles
|
|
169
|
+
warnings: resolution.warnings
|
|
124
170
|
};
|
|
125
171
|
});
|
|
126
172
|
}
|
|
@@ -139,7 +185,10 @@ async function bundleEffectEntryForNode(options) {
|
|
|
139
185
|
outfile: options.entryPath,
|
|
140
186
|
platform: 'node',
|
|
141
187
|
plugins: [
|
|
142
|
-
externalizeInstalledDependencies(
|
|
188
|
+
externalizeInstalledDependencies({
|
|
189
|
+
format: options.format,
|
|
190
|
+
runtimeResolveDir: options.appDir
|
|
191
|
+
}),
|
|
143
192
|
preserveSourceModuleSemantics()
|
|
144
193
|
],
|
|
145
194
|
target: 'node20'
|
|
@@ -155,6 +204,11 @@ function normalizeImportedModule(module) {
|
|
|
155
204
|
if (1 === Object.keys(namespace).length && null !== commonJsModule && 'object' == typeof commonJsModule && true === commonJsModule.__esModule) return commonJsModule;
|
|
156
205
|
return module;
|
|
157
206
|
}
|
|
207
|
+
async function loadEffectBuiltModule(resourcePath) {
|
|
208
|
+
const canonicalPath = await node_fs.promises.realpath(node_path.resolve(resourcePath));
|
|
209
|
+
if (!await isEsmOnlyFile(canonicalPath)) return createRequire(canonicalPath)(canonicalPath);
|
|
210
|
+
return normalizeImportedModule(await dynamicImport(pathToFileURL(canonicalPath).href));
|
|
211
|
+
}
|
|
158
212
|
async function loadEffectSourceModule(options) {
|
|
159
213
|
const resourcePath = node_path.resolve(options.resourcePath);
|
|
160
214
|
const appDir = node_path.resolve(options.appDir ?? node_path.dirname(resourcePath));
|
|
@@ -181,7 +235,10 @@ async function loadEffectSourceModule(options) {
|
|
|
181
235
|
outfile: outputPath,
|
|
182
236
|
platform: 'node',
|
|
183
237
|
plugins: [
|
|
184
|
-
externalizeInstalledDependencies(
|
|
238
|
+
externalizeInstalledDependencies({
|
|
239
|
+
format: 'esm',
|
|
240
|
+
runtimeResolveDir: appDir
|
|
241
|
+
}),
|
|
185
242
|
preserveSourceModuleSemantics()
|
|
186
243
|
],
|
|
187
244
|
sourcemap: 'inline',
|
|
@@ -196,4 +253,4 @@ async function loadEffectSourceModule(options) {
|
|
|
196
253
|
const revision = node_crypto.createHash('sha256').update(output).digest('hex');
|
|
197
254
|
return normalizeImportedModule(await dynamicImport(`${pathToFileURL(outputPath).href}?v=${revision}`));
|
|
198
255
|
}
|
|
199
|
-
export { bundleEffectEntryForNode, loadEffectSourceModule };
|
|
256
|
+
export { bundleEffectEntryForNode, loadEffectBuiltModule, loadEffectSourceModule };
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
import { fs, logger, normalizeToPosixPath } from "@modern-js/utils";
|
|
2
2
|
import path from "path";
|
|
3
|
-
import { API_DIR, DIST_DIR, LAMBDA_DIR, PACKAGE_NAME, PREFIX, RUNTIME_FRAMEWORK } from "./crossProjectApiPlugin.mjs";
|
|
4
|
-
function replaceContent(source, packageName, prefix, relativeDistPath, relativeApiPath, relativeLambdaPath, runtimeFramework) {
|
|
5
|
-
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);
|
|
3
|
+
import { API_DIR, DIST_DIR, EFFECT_ENTRY, LAMBDA_DIR, OPERATION_CONTRACTS_JSON, PACKAGE_NAME, PREFIX, RUNTIME_FRAMEWORK } from "./crossProjectApiPlugin.mjs";
|
|
4
|
+
function replaceContent(source, packageName, prefix, relativeDistPath, relativeApiPath, relativeLambdaPath, runtimeFramework, relativeEffectEntry, operationContracts) {
|
|
5
|
+
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)));
|
|
6
6
|
return updatedSource;
|
|
7
7
|
}
|
|
8
|
-
async function pluginGenerator({ prefix, appDirectory, relativeDistPath, relativeApiPath, relativeLambdaPath, runtimeFramework }) {
|
|
8
|
+
async function pluginGenerator({ prefix, appDirectory, relativeDistPath, relativeApiPath, relativeLambdaPath, runtimeFramework, relativeEffectEntry, operationContracts }) {
|
|
9
9
|
try {
|
|
10
10
|
const packageContent = await fs.readFile(path.resolve(appDirectory, './package.json'), 'utf8');
|
|
11
11
|
const packageJson = JSON.parse(packageContent);
|
|
12
12
|
const pluginDir = path.resolve(appDirectory, `./${relativeDistPath}`, 'plugin');
|
|
13
13
|
const pluginPath = path.join(pluginDir, 'index.js');
|
|
14
14
|
const pluginTemplate = await fs.readFile(path.resolve(__dirname, 'crossProjectApiPlugin.js'), 'utf8');
|
|
15
|
-
const updatedPlugin = replaceContent(pluginTemplate, packageJson.name, prefix, relativeDistPath, relativeApiPath, relativeLambdaPath, runtimeFramework);
|
|
15
|
+
const updatedPlugin = replaceContent(pluginTemplate, packageJson.name, prefix, relativeDistPath, relativeApiPath, relativeLambdaPath, runtimeFramework, relativeEffectEntry, operationContracts);
|
|
16
16
|
await fs.ensureFile(pluginPath);
|
|
17
17
|
await fs.writeFile(pluginPath, updatedPlugin);
|
|
18
18
|
const typeContent = `import type { AppTools, CliPlugin } from '@modern-js/app-tools';
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import "node:module";
|
|
2
2
|
import { normalizePrefixList } from "./prefix.mjs";
|
|
3
3
|
const createCompressConfig = (devServer, prefix)=>{
|
|
4
|
-
if (
|
|
4
|
+
if (void 0 === devServer || 'object' != typeof devServer || Array.isArray(devServer)) return;
|
|
5
5
|
const { compress } = devServer;
|
|
6
6
|
if (void 0 === compress || true === compress) {
|
|
7
7
|
const prefixes = normalizePrefixList(prefix);
|