@bleedingdev/modern-js-plugin-bff 3.9.0-ultramodern.2 → 3.9.0-ultramodern.21
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/generator.js +118 -117
- package/dist/cjs/cli.js +12 -7
- package/dist/cjs/loader.js +9 -65
- package/dist/cjs/runtime/create-request/index.js +0 -6
- package/dist/cjs/runtime/hono/adapter.js +8 -12
- package/dist/cjs/server.js +41 -50
- package/dist/cjs/utils/client-generator/files.js +1 -1
- package/dist/cjs/utils/client-generator/generate.js +46 -45
- package/dist/cjs/utils/client-generator/package-json.js +2 -2
- package/dist/cjs/utils/client-generator/write-package.js +18 -1
- package/dist/cjs/utils/createHonoRoutes.js +1 -1
- package/dist/cjs/utils/crossProjectApiPlugin.js +26 -83
- package/dist/cjs/utils/pluginGenerator.js +26 -26
- package/dist/cjs/utils/runtimeGenerator.js +26 -75
- package/dist/esm/cli/generator.mjs +121 -120
- package/dist/esm/cli.mjs +12 -7
- package/dist/esm/loader.mjs +9 -55
- package/dist/esm/runtime/create-request/index.mjs +1 -1
- package/dist/esm/runtime/hono/adapter.mjs +8 -12
- package/dist/esm/server.mjs +42 -51
- package/dist/esm/utils/client-generator/files.mjs +1 -1
- package/dist/esm/utils/client-generator/generate.mjs +47 -46
- package/dist/esm/utils/client-generator/package-json.mjs +3 -3
- package/dist/esm/utils/client-generator/write-package.mjs +18 -1
- package/dist/esm/utils/createHonoRoutes.mjs +1 -1
- package/dist/esm/utils/crossProjectApiPlugin.mjs +24 -54
- package/dist/esm/utils/pluginGenerator.mjs +23 -25
- package/dist/esm/utils/runtimeGenerator.mjs +23 -74
- package/dist/esm-node/cli/generator.mjs +121 -120
- package/dist/esm-node/cli.mjs +12 -7
- package/dist/esm-node/loader.mjs +9 -55
- package/dist/esm-node/runtime/create-request/index.mjs +1 -1
- package/dist/esm-node/runtime/hono/adapter.mjs +8 -12
- package/dist/esm-node/server.mjs +42 -51
- package/dist/esm-node/utils/client-generator/files.mjs +1 -1
- package/dist/esm-node/utils/client-generator/generate.mjs +47 -46
- package/dist/esm-node/utils/client-generator/package-json.mjs +3 -3
- package/dist/esm-node/utils/client-generator/write-package.mjs +18 -1
- package/dist/esm-node/utils/createHonoRoutes.mjs +1 -1
- package/dist/esm-node/utils/crossProjectApiPlugin.mjs +24 -54
- package/dist/esm-node/utils/pluginGenerator.mjs +23 -28
- package/dist/esm-node/utils/runtimeGenerator.mjs +24 -76
- package/dist/types/cli/generator.d.ts +2 -2
- package/dist/types/loader.d.ts +1 -11
- package/dist/types/runtime/create-request/index.d.ts +1 -3
- package/dist/types/runtime/hono/adapter.d.ts +9 -2
- package/dist/types/server.d.ts +4 -1
- package/dist/types/utils/client-generator/generate.d.ts +8 -12
- package/dist/types/utils/client-generator/write-package.d.ts +1 -1
- package/dist/types/utils/crossProjectApiPlugin.d.ts +18 -12
- package/dist/types/utils/pluginGenerator.d.ts +6 -7
- package/dist/types/utils/runtimeGenerator.d.ts +6 -3
- package/package.json +31 -124
- package/dist/cjs/cli/serverGlobalVars.js +0 -113
- package/dist/cjs/runtime/data-platform/index.js +0 -62
- package/dist/cjs/runtime/effect/edge-dispatcher.js +0 -62
- package/dist/cjs/runtime/effect/edge.js +0 -69
- package/dist/cjs/runtime/effect/index.js +0 -305
- package/dist/cjs/runtime/effect-client/index.js +0 -62
- package/dist/cjs/runtime/effect-client/runtime.js +0 -62
- package/dist/esm/cli/serverGlobalVars.mjs +0 -72
- package/dist/esm/runtime/data-platform/index.mjs +0 -1
- package/dist/esm/runtime/effect/edge-dispatcher.mjs +0 -1
- package/dist/esm/runtime/effect/edge.mjs +0 -2
- package/dist/esm/runtime/effect/index.mjs +0 -16
- package/dist/esm/runtime/effect-client/index.mjs +0 -1
- package/dist/esm/runtime/effect-client/runtime.mjs +0 -1
- package/dist/esm-node/cli/serverGlobalVars.mjs +0 -73
- package/dist/esm-node/runtime/data-platform/index.mjs +0 -2
- package/dist/esm-node/runtime/effect/edge-dispatcher.mjs +0 -2
- package/dist/esm-node/runtime/effect/edge.mjs +0 -3
- package/dist/esm-node/runtime/effect/index.mjs +0 -17
- package/dist/esm-node/runtime/effect-client/index.mjs +0 -2
- package/dist/esm-node/runtime/effect-client/runtime.mjs +0 -2
- package/dist/types/cli/serverGlobalVars.d.ts +0 -6
- package/dist/types/runtime/data-platform/index.d.ts +0 -1
- package/dist/types/runtime/effect/edge-dispatcher.d.ts +0 -1
- package/dist/types/runtime/effect/edge.d.ts +0 -2
- package/dist/types/runtime/effect/index.d.ts +0 -15
- package/dist/types/runtime/effect-client/index.d.ts +0 -1
- package/dist/types/runtime/effect-client/runtime.d.ts +0 -1
|
@@ -1,132 +1,133 @@
|
|
|
1
|
-
import { ApiRouter
|
|
1
|
+
import { ApiRouter } from "@modern-js/bff-core";
|
|
2
2
|
import { compile } from "@modern-js/server-utils";
|
|
3
3
|
import { API_DIR, SHARED_DIR, fs, resolveServerTsconfig, upath } from "@modern-js/utils";
|
|
4
4
|
import clientGenerator from "../utils/clientGenerator.mjs";
|
|
5
|
-
import pluginGenerator from "../utils/pluginGenerator.mjs";
|
|
6
|
-
import runtimeGenerator from "../utils/runtimeGenerator.mjs";
|
|
5
|
+
import pluginGenerator, { renderBffPlugin } from "../utils/pluginGenerator.mjs";
|
|
6
|
+
import runtimeGenerator, { renderBffRuntime } from "../utils/runtimeGenerator.mjs";
|
|
7
7
|
import { getPrimaryPrefix } from "./prefix.mjs";
|
|
8
|
-
import { serializeServerGlobalVars, transformServerGlobalVars } from "./serverGlobalVars.mjs";
|
|
9
8
|
const RUNTIME_CREATE_REQUEST = '@modern-js/plugin-bff/client';
|
|
10
9
|
const createBffGenerator = (api)=>{
|
|
11
|
-
const compileApi = ()=>
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
format: 'module' === moduleType ? 'esm' : 'cjs'
|
|
46
|
-
});
|
|
47
|
-
});
|
|
48
|
-
});
|
|
10
|
+
const compileApi = async ()=>{
|
|
11
|
+
const { appDirectory, distDirectory, apiDirectory, sharedDirectory, moduleType } = api.getAppContext();
|
|
12
|
+
const config = api.getNormalizedConfig();
|
|
13
|
+
const distDir = upath.resolve(distDirectory);
|
|
14
|
+
const apiDir = apiDirectory || upath.resolve(appDirectory, API_DIR);
|
|
15
|
+
const sharedDir = sharedDirectory || upath.resolve(appDirectory, SHARED_DIR);
|
|
16
|
+
const tsconfigPath = resolveServerTsconfig(appDirectory, config.server?.tsconfigPath);
|
|
17
|
+
const sourceDirs = [];
|
|
18
|
+
for (const directory of [
|
|
19
|
+
apiDir,
|
|
20
|
+
sharedDir
|
|
21
|
+
])if (await fs.pathExists(directory)) sourceDirs.push(directory);
|
|
22
|
+
if (0 === sourceDirs.length) return;
|
|
23
|
+
const combinedAlias = [].concat(config.source.alias ?? []).concat(config.resolve.alias ?? []);
|
|
24
|
+
const context = {
|
|
25
|
+
appDirectory,
|
|
26
|
+
apiDirectory: apiDir,
|
|
27
|
+
sourceDirectories: sourceDirs,
|
|
28
|
+
outputDirectories: sourceDirs.map((directory)=>upath.resolve(distDir, upath.relative(appDirectory, directory))),
|
|
29
|
+
distDirectory: distDir,
|
|
30
|
+
tsconfigPath,
|
|
31
|
+
moduleType
|
|
32
|
+
};
|
|
33
|
+
const hooks = api.getHooks();
|
|
34
|
+
await hooks.onBeforeBffCompile.call(context);
|
|
35
|
+
await compile(appDirectory, {
|
|
36
|
+
alias: combinedAlias
|
|
37
|
+
}, {
|
|
38
|
+
sourceDirs,
|
|
39
|
+
distDir,
|
|
40
|
+
tsconfigPath,
|
|
41
|
+
moduleType,
|
|
42
|
+
excludeFiles: api.getAppContext().serverCompileExcludedFiles,
|
|
43
|
+
throwErrorInsteadOfExit: true
|
|
49
44
|
});
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
const lambdaDir = apiRouter.getLambdaDir();
|
|
66
|
-
const existLambda = apiRouter.isExistLambda();
|
|
67
|
-
const packageJson = fs.readJSONSync(upath.resolve(appDirectory, 'package.json'));
|
|
68
|
-
const requestId = bff?.requestId || packageJson.name || packageName || 'default';
|
|
69
|
-
const operationContractsPromise = 'effect' !== bffRuntimeFramework && existLambda ? apiRouter.getApiHandlers().then((handlers)=>buildOperationContractMap({
|
|
70
|
-
handlers,
|
|
71
|
-
requestId,
|
|
72
|
-
operationVersion: deriveOperationVersion(packageJson.version)
|
|
73
|
-
})) : Promise.resolve({});
|
|
74
|
-
const runtime = bff?.runtimeCreateRequest || RUNTIME_CREATE_REQUEST;
|
|
75
|
-
const relativeApiPath = upath.relative(appDirectory, apiDirectory);
|
|
76
|
-
const relativeLambdaPath = upath.relative(appDirectory, lambdaDir);
|
|
77
|
-
const { sourceEffectEntry, relativeEffectEntry } = 'effect' === bffRuntimeFramework ? (await import("@modern-js/plugin-bff-extensions/client-generator")).resolveEffectEntryPaths({
|
|
78
|
-
appDir: appDirectory,
|
|
79
|
-
apiDir: apiDirectory,
|
|
80
|
-
effectEntry: bff?.effect?.entry
|
|
81
|
-
}) : {
|
|
82
|
-
sourceEffectEntry: void 0,
|
|
83
|
-
relativeEffectEntry: ''
|
|
84
|
-
};
|
|
85
|
-
const clientGenerationPromise = clientGenerator({
|
|
86
|
-
prefix,
|
|
87
|
-
appDir: appDirectory,
|
|
88
|
-
apiDir: apiDirectory,
|
|
89
|
-
lambdaDir,
|
|
90
|
-
existLambda,
|
|
91
|
-
port,
|
|
92
|
-
requestId,
|
|
93
|
-
requestCreator: bff?.requestCreator,
|
|
94
|
-
httpMethodDecider,
|
|
95
|
-
relativeDistPath,
|
|
96
|
-
relativeApiPath,
|
|
97
|
-
apiFiles: apiRouter.getApiFiles(),
|
|
98
|
-
bffRuntimeFramework,
|
|
99
|
-
effectEntry: bff?.effect?.entry,
|
|
100
|
-
effectDataPlatformBatch: bff?.effect?.dataPlatform?.batch
|
|
101
|
-
});
|
|
102
|
-
return Promise.all([
|
|
103
|
-
operationContractsPromise,
|
|
104
|
-
clientGenerationPromise
|
|
105
|
-
]).then(([lambdaContracts, generatedEffectClient])=>{
|
|
106
|
-
if ('effect' === bffRuntimeFramework && null === generatedEffectClient) throw new Error(`Effect cross-project client generation failed for ${sourceEffectEntry ?? apiDirectory}.`);
|
|
107
|
-
const operationContracts = 'effect' === bffRuntimeFramework ? generatedEffectClient?.operationContracts ?? {} : lambdaContracts;
|
|
108
|
-
return pluginGenerator({
|
|
109
|
-
prefix,
|
|
110
|
-
appDirectory,
|
|
111
|
-
requestId,
|
|
112
|
-
relativeDistPath,
|
|
113
|
-
relativeApiPath,
|
|
114
|
-
relativeLambdaPath,
|
|
115
|
-
runtimeFramework: 'hono' === bffRuntimeFramework ? 'hono' : 'effect',
|
|
116
|
-
relativeEffectEntry,
|
|
117
|
-
operationContracts
|
|
118
|
-
}).then(()=>runtimeGenerator({
|
|
119
|
-
runtime,
|
|
120
|
-
appDirectory,
|
|
121
|
-
relativeDistPath
|
|
122
|
-
}));
|
|
123
|
-
});
|
|
45
|
+
await hooks.onAfterBffCompile.call(context);
|
|
46
|
+
};
|
|
47
|
+
const generate = async ()=>{
|
|
48
|
+
const { appDirectory, apiDirectory, lambdaDirectory, port, packageName } = api.getAppContext();
|
|
49
|
+
const config = api.getNormalizedConfig();
|
|
50
|
+
const relativeDistPath = config.output?.distPath?.root || 'dist';
|
|
51
|
+
const bff = config.bff;
|
|
52
|
+
const prefix = getPrimaryPrefix(bff?.prefix);
|
|
53
|
+
const apiRouter = new ApiRouter({
|
|
54
|
+
apiDir: apiDirectory,
|
|
55
|
+
appDir: appDirectory,
|
|
56
|
+
lambdaDir: lambdaDirectory,
|
|
57
|
+
prefix,
|
|
58
|
+
httpMethodDecider: bff?.httpMethodDecider,
|
|
59
|
+
isBuild: true
|
|
124
60
|
});
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
61
|
+
const lambdaDir = apiRouter.getLambdaDir();
|
|
62
|
+
const packageJson = await fs.readJSON(upath.resolve(appDirectory, 'package.json'));
|
|
63
|
+
const generation = {
|
|
64
|
+
appDirectory,
|
|
65
|
+
apiDirectory,
|
|
66
|
+
lambdaDirectory: lambdaDir,
|
|
67
|
+
existLambda: apiRouter.isExistLambda(),
|
|
68
|
+
apiFiles: apiRouter.getApiFiles(),
|
|
69
|
+
relativeDistPath,
|
|
70
|
+
prefix,
|
|
71
|
+
port,
|
|
72
|
+
requestId: bff?.requestId || packageJson.name || packageName || 'default',
|
|
73
|
+
requestCreator: bff?.requestCreator,
|
|
74
|
+
httpMethodDecider: bff?.httpMethodDecider
|
|
75
|
+
};
|
|
76
|
+
const pluginOptions = {
|
|
77
|
+
prefix,
|
|
78
|
+
appDirectory,
|
|
79
|
+
relativeDistPath,
|
|
80
|
+
relativeApiPath: upath.relative(appDirectory, apiDirectory),
|
|
81
|
+
relativeLambdaPath: upath.relative(appDirectory, lambdaDir)
|
|
82
|
+
};
|
|
83
|
+
const runtimeOptions = {
|
|
84
|
+
runtime: bff?.runtimeCreateRequest || RUNTIME_CREATE_REQUEST,
|
|
85
|
+
appDirectory,
|
|
86
|
+
relativeDistPath
|
|
87
|
+
};
|
|
88
|
+
const hooks = api.getHooks();
|
|
89
|
+
await clientGenerator({
|
|
90
|
+
prefix,
|
|
91
|
+
appDir: appDirectory,
|
|
92
|
+
apiDir: apiDirectory,
|
|
93
|
+
lambdaDir,
|
|
94
|
+
existLambda: generation.existLambda,
|
|
95
|
+
apiFiles: [
|
|
96
|
+
...generation.apiFiles
|
|
97
|
+
],
|
|
98
|
+
port,
|
|
99
|
+
requestId: generation.requestId,
|
|
100
|
+
requestCreator: generation.requestCreator,
|
|
101
|
+
clientCodegenPlugin: bff?.clientCodegenPlugin,
|
|
102
|
+
httpMethodDecider: generation.httpMethodDecider,
|
|
103
|
+
relativeDistPath,
|
|
104
|
+
relativeApiPath: pluginOptions.relativeApiPath
|
|
105
|
+
}, {
|
|
106
|
+
generation,
|
|
107
|
+
modifyArtifacts: async (context)=>{
|
|
108
|
+
const result = await hooks.modifyBffClientArtifacts.call(context);
|
|
109
|
+
if (result.generation !== generation) throw new Error('modifyBffClientArtifacts must preserve generation identity.');
|
|
110
|
+
return result;
|
|
111
|
+
},
|
|
112
|
+
beforePublish: async ()=>{
|
|
113
|
+
const entries = await hooks.modifyBffGeneratedEntries.call({
|
|
114
|
+
generation,
|
|
115
|
+
plugin: await renderBffPlugin(pluginOptions),
|
|
116
|
+
runtime: renderBffRuntime(runtimeOptions),
|
|
117
|
+
packageDependencies: {}
|
|
118
|
+
});
|
|
119
|
+
if (entries.generation !== generation) throw new Error('modifyBffGeneratedEntries must preserve generation identity.');
|
|
120
|
+
await pluginGenerator(pluginOptions, entries.plugin);
|
|
121
|
+
await runtimeGenerator(runtimeOptions, entries.runtime);
|
|
122
|
+
return entries.packageDependencies;
|
|
123
|
+
}
|
|
129
124
|
});
|
|
125
|
+
};
|
|
126
|
+
const handleCrossProjectInvocation = async (isBuild = false)=>{
|
|
127
|
+
if (api.getNormalizedConfig().bff?.crossProject !== true) return;
|
|
128
|
+
if (!isBuild) await compileApi();
|
|
129
|
+
await generate();
|
|
130
|
+
};
|
|
130
131
|
return {
|
|
131
132
|
compileApi,
|
|
132
133
|
generate,
|
package/dist/esm/cli.mjs
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { ApiRouter } from "@modern-js/bff-core";
|
|
2
|
+
import { createAsyncHook } from "@modern-js/plugin";
|
|
2
3
|
import { normalizeOutputPath } from "@modern-js/utils";
|
|
3
4
|
import path from "path";
|
|
4
5
|
import { createCompressConfig } from "./cli/compress.mjs";
|
|
@@ -7,13 +8,19 @@ import { getPrimaryPrefix } from "./cli/prefix.mjs";
|
|
|
7
8
|
import { isWatchableBffFile } from "./cli/watch.mjs";
|
|
8
9
|
const bffPlugin = ()=>({
|
|
9
10
|
name: '@modern-js/plugin-bff',
|
|
11
|
+
registryHooks: {
|
|
12
|
+
onBeforeBffCompile: createAsyncHook(),
|
|
13
|
+
onAfterBffCompile: createAsyncHook(),
|
|
14
|
+
modifyBffClientArtifacts: createAsyncHook(),
|
|
15
|
+
modifyBffGeneratedEntries: createAsyncHook()
|
|
16
|
+
},
|
|
10
17
|
setup: (api)=>{
|
|
11
18
|
{
|
|
12
19
|
const appContext = api.getAppContext();
|
|
13
20
|
const userRuntimeFramework = api.getConfig()?.bff?.runtimeFramework;
|
|
14
21
|
api.updateAppContext({
|
|
15
22
|
...appContext,
|
|
16
|
-
bffRuntimeFramework:
|
|
23
|
+
bffRuntimeFramework: userRuntimeFramework ?? 'hono'
|
|
17
24
|
});
|
|
18
25
|
}
|
|
19
26
|
const { compileApi, handleCrossProjectInvocation } = createBffGenerator(api);
|
|
@@ -31,7 +38,7 @@ const bffPlugin = ()=>({
|
|
|
31
38
|
compress
|
|
32
39
|
},
|
|
33
40
|
bundlerChain: (chain, { CHAIN_ID, isServer })=>{
|
|
34
|
-
const { port, appDirectory, apiDirectory, lambdaDirectory
|
|
41
|
+
const { port, appDirectory, apiDirectory, lambdaDirectory } = api.getAppContext();
|
|
35
42
|
const modernConfig = api.getNormalizedConfig();
|
|
36
43
|
const { bff } = modernConfig || {};
|
|
37
44
|
const prefix = getPrimaryPrefix(bff?.prefix);
|
|
@@ -61,10 +68,8 @@ const bffPlugin = ()=>({
|
|
|
61
68
|
requestId: bff?.requestId,
|
|
62
69
|
target: name,
|
|
63
70
|
requestCreator: bff?.requestCreator,
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
effectEntry: bff?.effect?.entry,
|
|
67
|
-
effectDataPlatformBatch: bff?.effect?.dataPlatform?.batch
|
|
71
|
+
clientCodegenPlugin: bff?.clientCodegenPlugin,
|
|
72
|
+
httpMethodDecider
|
|
68
73
|
});
|
|
69
74
|
}
|
|
70
75
|
}
|
|
@@ -116,7 +121,7 @@ const bffPlugin = ()=>({
|
|
|
116
121
|
appContext.apiDirectory,
|
|
117
122
|
appContext.sharedDirectory
|
|
118
123
|
].filter(Boolean);
|
|
119
|
-
return [];
|
|
124
|
+
else return [];
|
|
120
125
|
});
|
|
121
126
|
api.onFileChanged(async (e)=>{
|
|
122
127
|
const { filename, eventType, isPrivate } = e;
|
package/dist/esm/loader.mjs
CHANGED
|
@@ -1,64 +1,12 @@
|
|
|
1
1
|
import { generateClient } from "@modern-js/bff-core";
|
|
2
|
-
import { generateEffectClientCode, generateEffectWorkerRuntimeWrapper, resolveEffectEntryFile } from "@modern-js/plugin-bff-extensions/effect-source-loader";
|
|
3
2
|
import { logger } from "@modern-js/utils";
|
|
4
|
-
import path from "path";
|
|
5
|
-
const EFFECT_BFF_WORKER_RUNTIME_QUERY = 'modern-bff-runtime';
|
|
6
|
-
const EFFECT_BFF_WORKER_RUNTIME_SOURCE_QUERY = 'modern-bff-runtime-source';
|
|
7
3
|
const createErrorModule = (message)=>`throw new Error(${JSON.stringify(message)});`;
|
|
8
|
-
async function transformEffectRuntimeSource(source, filename) {
|
|
9
|
-
const swc = await import("@swc/core");
|
|
10
|
-
const result = await swc.transform(source, {
|
|
11
|
-
filename,
|
|
12
|
-
sourceMaps: false,
|
|
13
|
-
jsc: {
|
|
14
|
-
parser: {
|
|
15
|
-
syntax: "typescript",
|
|
16
|
-
tsx: filename.endsWith('.tsx') || filename.endsWith('.jsx')
|
|
17
|
-
},
|
|
18
|
-
target: 'es2024'
|
|
19
|
-
},
|
|
20
|
-
module: {
|
|
21
|
-
type: 'es6'
|
|
22
|
-
}
|
|
23
|
-
});
|
|
24
|
-
return result.code;
|
|
25
|
-
}
|
|
26
4
|
async function loader(source) {
|
|
27
5
|
this.cacheable();
|
|
28
6
|
const { resourcePath } = this;
|
|
29
7
|
delete require.cache[resourcePath];
|
|
30
8
|
const callback = this.async();
|
|
31
9
|
const draftOptions = this.getOptions();
|
|
32
|
-
const resourceQueries = new URLSearchParams(this.resourceQuery);
|
|
33
|
-
const effectEntryFile = resolveEffectEntryFile({
|
|
34
|
-
appDir: draftOptions.appDir,
|
|
35
|
-
apiDir: draftOptions.apiDir,
|
|
36
|
-
effectEntry: draftOptions.effectEntry
|
|
37
|
-
});
|
|
38
|
-
if ('effect' === draftOptions.bffRuntimeFramework && effectEntryFile && path.resolve(effectEntryFile) === path.resolve(resourcePath) && resourceQueries.has(EFFECT_BFF_WORKER_RUNTIME_SOURCE_QUERY)) {
|
|
39
|
-
const code = await transformEffectRuntimeSource(source, resourcePath);
|
|
40
|
-
callback(void 0, code);
|
|
41
|
-
return;
|
|
42
|
-
}
|
|
43
|
-
if ('effect' === draftOptions.bffRuntimeFramework && effectEntryFile && path.resolve(effectEntryFile) === path.resolve(resourcePath) && resourceQueries.has(EFFECT_BFF_WORKER_RUNTIME_QUERY)) return void callback(void 0, await generateEffectWorkerRuntimeWrapper(this, draftOptions, resourcePath));
|
|
44
|
-
if ('effect' === draftOptions.bffRuntimeFramework && effectEntryFile && path.resolve(effectEntryFile) === path.resolve(resourcePath)) {
|
|
45
|
-
const code = await generateEffectClientCode({
|
|
46
|
-
appDir: draftOptions.appDir,
|
|
47
|
-
apiDir: draftOptions.apiDir,
|
|
48
|
-
resourcePath,
|
|
49
|
-
prefix: Array.isArray(draftOptions.prefix) ? draftOptions.prefix[0] : draftOptions.prefix,
|
|
50
|
-
port: Number(draftOptions.port),
|
|
51
|
-
target: draftOptions.target,
|
|
52
|
-
requestId: draftOptions.requestId,
|
|
53
|
-
requestCreator: draftOptions.requestCreator,
|
|
54
|
-
httpMethodDecider: draftOptions.httpMethodDecider,
|
|
55
|
-
dataPlatformBatch: draftOptions.effectDataPlatformBatch,
|
|
56
|
-
onDependency: (dependency)=>this.addDependency(dependency)
|
|
57
|
-
});
|
|
58
|
-
if (code) return void callback(void 0, code);
|
|
59
|
-
callback(new Error(`Failed to generate Effect client for ${resourcePath}`));
|
|
60
|
-
return;
|
|
61
|
-
}
|
|
62
10
|
const warning = `The file ${resourcePath} is not allowed to be imported in src directory, only API definition files are allowed.`;
|
|
63
11
|
if (!draftOptions.existLambda) {
|
|
64
12
|
logger.warn(warning);
|
|
@@ -74,7 +22,9 @@ async function loader(source) {
|
|
|
74
22
|
port: Number(draftOptions.port),
|
|
75
23
|
source,
|
|
76
24
|
resourcePath,
|
|
77
|
-
httpMethodDecider: draftOptions.httpMethodDecider
|
|
25
|
+
httpMethodDecider: draftOptions.httpMethodDecider,
|
|
26
|
+
clientCodegenPlugin: draftOptions.clientCodegenPlugin,
|
|
27
|
+
requestId: draftOptions.requestId
|
|
78
28
|
};
|
|
79
29
|
const { lambdaDir } = draftOptions;
|
|
80
30
|
if (!resourcePath.startsWith(lambdaDir)) {
|
|
@@ -85,8 +35,12 @@ async function loader(source) {
|
|
|
85
35
|
if (draftOptions.fetcher) options.fetcher = draftOptions.fetcher;
|
|
86
36
|
if (draftOptions.requestCreator) options.requestCreator = draftOptions.requestCreator;
|
|
87
37
|
options.requireResolve = require.resolve;
|
|
88
|
-
|
|
89
|
-
|
|
38
|
+
try {
|
|
39
|
+
const result = await generateClient(options);
|
|
40
|
+
callback(void 0, result.isOk ? result.value : createErrorModule(result.value));
|
|
41
|
+
} catch (error) {
|
|
42
|
+
callback(error instanceof Error ? error : new Error(String(error)));
|
|
43
|
+
}
|
|
90
44
|
}
|
|
91
45
|
const src_loader = loader;
|
|
92
46
|
export default src_loader;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export { configure, createRequest,
|
|
1
|
+
export { configure, createRequest, createUploader } from "@modern-js/create-request";
|
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
import { resolveAdapterCrossProjectPolicy } from "@modern-js/plugin-bff-extensions/cross-project-policy";
|
|
2
|
-
import { bindHonoRouteHandlers } from "@modern-js/plugin-bff-extensions/hono";
|
|
3
|
-
import { logger } from "@modern-js/utils";
|
|
4
1
|
import createHonoRoutes from "../../utils/createHonoRoutes.mjs";
|
|
5
2
|
const before = [
|
|
6
3
|
'custom-server-hook',
|
|
@@ -8,7 +5,8 @@ const before = [
|
|
|
8
5
|
'render'
|
|
9
6
|
];
|
|
10
7
|
class HonoAdapter {
|
|
11
|
-
constructor(api){
|
|
8
|
+
constructor(api, createRouteBinder){
|
|
9
|
+
this.createRouteBinder = createRouteBinder;
|
|
12
10
|
this.apiMiddleware = [];
|
|
13
11
|
this.isHono = true;
|
|
14
12
|
this.setHandlers = async ()=>{
|
|
@@ -16,25 +14,23 @@ class HonoAdapter {
|
|
|
16
14
|
const { apiHandlerInfos } = this.api.getServerContext();
|
|
17
15
|
const handlers = apiHandlerInfos ?? [];
|
|
18
16
|
const honoHandlers = createHonoRoutes(handlers);
|
|
19
|
-
const
|
|
17
|
+
const bindRoute = this.createRouteBinder?.(this.api, handlers);
|
|
18
|
+
if (this.createRouteBinder && 'function' != typeof bindRoute) throw new TypeError('Hono route binder factory must return a function.');
|
|
20
19
|
this.apiMiddleware = honoHandlers.map(({ path, method, handler })=>({
|
|
21
20
|
name: 'hono-bff-api',
|
|
22
21
|
path,
|
|
23
22
|
method,
|
|
24
|
-
handler:
|
|
23
|
+
handler: bindRoute ? bindRoute({
|
|
25
24
|
handler,
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
onError: this.api.getServerConfig()?.onError,
|
|
29
|
-
reportError: (error)=>logger.error(error)
|
|
30
|
-
}),
|
|
25
|
+
routePath: path
|
|
26
|
+
}) : handler,
|
|
31
27
|
order: 'post',
|
|
32
28
|
before: before
|
|
33
29
|
}));
|
|
34
30
|
};
|
|
35
31
|
this.registerMiddleware = async (_options)=>{
|
|
36
32
|
const { bffRuntimeFramework } = this.api.getServerContext();
|
|
37
|
-
if ('hono' !== bffRuntimeFramework) {
|
|
33
|
+
if (void 0 !== bffRuntimeFramework && 'hono' !== bffRuntimeFramework) {
|
|
38
34
|
this.isHono = false;
|
|
39
35
|
return;
|
|
40
36
|
}
|
package/dist/esm/server.mjs
CHANGED
|
@@ -1,18 +1,7 @@
|
|
|
1
1
|
import { ApiRouter } from "@modern-js/bff-core";
|
|
2
|
-
import { API_DIR, isFunction, isWebOnly } from "@modern-js/utils";
|
|
2
|
+
import { API_DIR, compatibleRequire, isFunction, isWebOnly, tryResolve } from "@modern-js/utils";
|
|
3
3
|
import path from "path";
|
|
4
4
|
import { HonoAdapter } from "./runtime/hono/adapter.mjs";
|
|
5
|
-
const RUNTIME_ADAPTER_LOADERS = {
|
|
6
|
-
hono: async (api)=>[
|
|
7
|
-
new HonoAdapter(api)
|
|
8
|
-
],
|
|
9
|
-
effect: async (api)=>{
|
|
10
|
-
const { EffectAdapter } = await import("@modern-js/plugin-bff-extensions/effect-adapter");
|
|
11
|
-
return [
|
|
12
|
-
new EffectAdapter(api)
|
|
13
|
-
];
|
|
14
|
-
}
|
|
15
|
-
};
|
|
16
5
|
const normalizePrefixList = (prefix)=>{
|
|
17
6
|
if (Array.isArray(prefix)) return prefix.filter(Boolean);
|
|
18
7
|
return [
|
|
@@ -20,21 +9,19 @@ const normalizePrefixList = (prefix)=>{
|
|
|
20
9
|
];
|
|
21
10
|
};
|
|
22
11
|
const getPrimaryPrefix = (prefix)=>normalizePrefixList(prefix)[0] || '/api';
|
|
23
|
-
function resolveRuntimeFramework(runtimeFramework) {
|
|
24
|
-
return 'hono' === runtimeFramework ? 'hono' : 'effect';
|
|
25
|
-
}
|
|
26
12
|
class Storage {
|
|
27
13
|
constructor(){
|
|
28
14
|
this.middlewares = [];
|
|
29
15
|
}
|
|
30
16
|
}
|
|
31
|
-
const server = ()=>({
|
|
17
|
+
const server = (options = {})=>({
|
|
32
18
|
name: '@modern-js/plugin-bff',
|
|
33
19
|
setup: (api)=>{
|
|
34
20
|
const storage = new Storage();
|
|
35
21
|
let apiRouter = null;
|
|
36
22
|
const appContext = api.getServerContext();
|
|
37
|
-
const runtimeFramework =
|
|
23
|
+
const runtimeFramework = appContext.bffRuntimeFramework ?? 'hono';
|
|
24
|
+
if ('hono' !== runtimeFramework) throw new Error(`Native BFF server plugin requires Hono; received "${runtimeFramework}".`);
|
|
38
25
|
api.onPrepare(async ()=>{
|
|
39
26
|
const appContext = api.getServerContext();
|
|
40
27
|
const { render } = appContext;
|
|
@@ -50,41 +37,46 @@ const server = ()=>({
|
|
|
50
37
|
const httpMethodDecider = config?.bff?.httpMethodDecider;
|
|
51
38
|
const { distDirectory: pwd, middlewares: globalMiddlewares } = api.getServerContext();
|
|
52
39
|
const webOnly = await isWebOnly();
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
httpMethodDecider
|
|
67
|
-
});
|
|
68
|
-
}
|
|
69
|
-
if (handler && isFunction(handler)) globalMiddlewares.push({
|
|
70
|
-
name: 'bind-bff',
|
|
71
|
-
handler: (c, next)=>{
|
|
72
|
-
if (!prefixList.some((item)=>c.req.path.startsWith(item)) && !enableHandleWeb) return next();
|
|
73
|
-
return handler(c, next);
|
|
74
|
-
},
|
|
75
|
-
order: 'post',
|
|
76
|
-
before: [
|
|
77
|
-
'custom-server-hook',
|
|
78
|
-
'custom-server-middleware',
|
|
79
|
-
'render'
|
|
80
|
-
]
|
|
40
|
+
let handler;
|
|
41
|
+
if (webOnly) handler = async (c, next)=>{
|
|
42
|
+
c.body('');
|
|
43
|
+
await next();
|
|
44
|
+
};
|
|
45
|
+
else {
|
|
46
|
+
const runner = api.getHooks();
|
|
47
|
+
const renderHandler = enableHandleWeb ? render : null;
|
|
48
|
+
handler = await runner.prepareApiServer.call({
|
|
49
|
+
pwd: pwd,
|
|
50
|
+
prefix,
|
|
51
|
+
render: renderHandler,
|
|
52
|
+
httpMethodDecider
|
|
81
53
|
});
|
|
82
54
|
}
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
enableHandleWeb
|
|
87
|
-
|
|
55
|
+
if (handler && isFunction(handler)) globalMiddlewares.push({
|
|
56
|
+
name: 'bind-bff',
|
|
57
|
+
handler: (c, next)=>{
|
|
58
|
+
if (!prefixList.some((item)=>c.req.path.startsWith(item)) && !enableHandleWeb) return next();
|
|
59
|
+
return handler(c, next);
|
|
60
|
+
},
|
|
61
|
+
order: 'post',
|
|
62
|
+
before: [
|
|
63
|
+
'custom-server-hook',
|
|
64
|
+
'custom-server-middleware',
|
|
65
|
+
'render'
|
|
66
|
+
]
|
|
67
|
+
});
|
|
68
|
+
let createHonoRouteBinder;
|
|
69
|
+
if (void 0 !== options.honoRouteBinder) {
|
|
70
|
+
if ('string' != typeof options.honoRouteBinder || '' === options.honoRouteBinder.trim()) throw new Error('The Hono BFF route binder must be a module specifier.');
|
|
71
|
+
const context = api.getServerContext();
|
|
72
|
+
const module = await compatibleRequire(tryResolve(options.honoRouteBinder, context.appDirectory || context.distDirectory || process.cwd()), false);
|
|
73
|
+
if (!module || 'function' != typeof module.createHonoRouteBinder) throw new Error(`BFF route binder module "${options.honoRouteBinder}" must export createHonoRouteBinder.`);
|
|
74
|
+
createHonoRouteBinder = module.createHonoRouteBinder;
|
|
75
|
+
}
|
|
76
|
+
await new HonoAdapter(api, createHonoRouteBinder).registerMiddleware({
|
|
77
|
+
prefix,
|
|
78
|
+
enableHandleWeb
|
|
79
|
+
});
|
|
88
80
|
});
|
|
89
81
|
api.onReset(async ({ event })=>{
|
|
90
82
|
if ('file-change' === event.type && apiRouter) {
|
|
@@ -97,7 +89,6 @@ const server = ()=>({
|
|
|
97
89
|
}
|
|
98
90
|
});
|
|
99
91
|
const prepareApiServer = async (input, next)=>{
|
|
100
|
-
if ('hono' !== runtimeFramework) return next(input);
|
|
101
92
|
const { pwd, prefix, httpMethodDecider } = input;
|
|
102
93
|
const defaultApiDirectory = path.resolve(pwd, API_DIR);
|
|
103
94
|
const appContext = api.getServerContext();
|
|
@@ -18,7 +18,7 @@ function createFileDetails(options) {
|
|
|
18
18
|
const relativePath = path.relative(baseDirectory, resourcePath);
|
|
19
19
|
const parsedPath = path.parse(relativePath);
|
|
20
20
|
const targetDir = posixJoin(`./${relativeDistPath}/${CLIENT_DIR}`, parsedPath.dir, `${parsedPath.name}.js`);
|
|
21
|
-
const absTargetDir = path.resolve(targetDir);
|
|
21
|
+
const absTargetDir = path.resolve(appDirectory, targetDir);
|
|
22
22
|
const relativePathFromAppDirectory = path.relative(appDirectory, path.dirname(resourcePath));
|
|
23
23
|
const typesFilePath = posixJoin(`./${relativeDistPath}`, relativePathFromAppDirectory, `${parsedPath.name}.d.ts`);
|
|
24
24
|
return {
|