@bleedingdev/modern-js-plugin-bff 3.2.0-ultramodern.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (88) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +26 -0
  3. package/cli.js +1 -0
  4. package/dist/cjs/cli.js +294 -0
  5. package/dist/cjs/constants.js +48 -0
  6. package/dist/cjs/index.js +58 -0
  7. package/dist/cjs/loader.js +106 -0
  8. package/dist/cjs/runtime/create-request/index.js +48 -0
  9. package/dist/cjs/runtime/data-platform/index.js +693 -0
  10. package/dist/cjs/runtime/effect/adapter.js +311 -0
  11. package/dist/cjs/runtime/effect/context.js +48 -0
  12. package/dist/cjs/runtime/effect/index.js +608 -0
  13. package/dist/cjs/runtime/effect-client/index.js +178 -0
  14. package/dist/cjs/runtime/hono/adapter.js +168 -0
  15. package/dist/cjs/runtime/hono/index.js +65 -0
  16. package/dist/cjs/runtime/hono/operators.js +68 -0
  17. package/dist/cjs/server.js +179 -0
  18. package/dist/cjs/utils/clientGenerator.js +342 -0
  19. package/dist/cjs/utils/createHonoRoutes.js +138 -0
  20. package/dist/cjs/utils/crossProjectApiPlugin.js +118 -0
  21. package/dist/cjs/utils/effectClientGenerator.js +673 -0
  22. package/dist/cjs/utils/pluginGenerator.js +73 -0
  23. package/dist/cjs/utils/runtimeGenerator.js +133 -0
  24. package/dist/esm/cli.mjs +245 -0
  25. package/dist/esm/constants.mjs +11 -0
  26. package/dist/esm/index.mjs +1 -0
  27. package/dist/esm/loader.mjs +62 -0
  28. package/dist/esm/runtime/create-request/index.mjs +1 -0
  29. package/dist/esm/runtime/data-platform/index.mjs +599 -0
  30. package/dist/esm/runtime/effect/adapter.mjs +267 -0
  31. package/dist/esm/runtime/effect/context.mjs +11 -0
  32. package/dist/esm/runtime/effect/index.mjs +438 -0
  33. package/dist/esm/runtime/effect-client/index.mjs +90 -0
  34. package/dist/esm/runtime/hono/adapter.mjs +124 -0
  35. package/dist/esm/runtime/hono/index.mjs +2 -0
  36. package/dist/esm/runtime/hono/operators.mjs +31 -0
  37. package/dist/esm/server.mjs +135 -0
  38. package/dist/esm/utils/clientGenerator.mjs +293 -0
  39. package/dist/esm/utils/createHonoRoutes.mjs +92 -0
  40. package/dist/esm/utils/crossProjectApiPlugin.mjs +54 -0
  41. package/dist/esm/utils/effectClientGenerator.mjs +623 -0
  42. package/dist/esm/utils/pluginGenerator.mjs +29 -0
  43. package/dist/esm/utils/runtimeGenerator.mjs +89 -0
  44. package/dist/esm-node/cli.mjs +249 -0
  45. package/dist/esm-node/constants.mjs +12 -0
  46. package/dist/esm-node/index.mjs +2 -0
  47. package/dist/esm-node/loader.mjs +64 -0
  48. package/dist/esm-node/runtime/create-request/index.mjs +2 -0
  49. package/dist/esm-node/runtime/data-platform/index.mjs +600 -0
  50. package/dist/esm-node/runtime/effect/adapter.mjs +269 -0
  51. package/dist/esm-node/runtime/effect/context.mjs +12 -0
  52. package/dist/esm-node/runtime/effect/index.mjs +439 -0
  53. package/dist/esm-node/runtime/effect-client/index.mjs +91 -0
  54. package/dist/esm-node/runtime/hono/adapter.mjs +125 -0
  55. package/dist/esm-node/runtime/hono/index.mjs +3 -0
  56. package/dist/esm-node/runtime/hono/operators.mjs +32 -0
  57. package/dist/esm-node/server.mjs +136 -0
  58. package/dist/esm-node/utils/clientGenerator.mjs +294 -0
  59. package/dist/esm-node/utils/createHonoRoutes.mjs +93 -0
  60. package/dist/esm-node/utils/crossProjectApiPlugin.mjs +55 -0
  61. package/dist/esm-node/utils/effectClientGenerator.mjs +625 -0
  62. package/dist/esm-node/utils/pluginGenerator.mjs +33 -0
  63. package/dist/esm-node/utils/runtimeGenerator.mjs +91 -0
  64. package/dist/types/cli.d.ts +3 -0
  65. package/dist/types/constants.d.ts +2 -0
  66. package/dist/types/index.d.ts +1 -0
  67. package/dist/types/loader.d.ts +27 -0
  68. package/dist/types/runtime/create-request/index.d.ts +2 -0
  69. package/dist/types/runtime/data-platform/index.d.ts +187 -0
  70. package/dist/types/runtime/effect/adapter.d.ts +22 -0
  71. package/dist/types/runtime/effect/context.d.ts +8 -0
  72. package/dist/types/runtime/effect/index.d.ts +171 -0
  73. package/dist/types/runtime/effect-client/index.d.ts +47 -0
  74. package/dist/types/runtime/hono/adapter.d.ts +19 -0
  75. package/dist/types/runtime/hono/index.d.ts +2 -0
  76. package/dist/types/runtime/hono/operators.d.ts +10 -0
  77. package/dist/types/server.d.ts +3 -0
  78. package/dist/types/utils/clientGenerator.d.ts +37 -0
  79. package/dist/types/utils/createHonoRoutes.d.ts +10 -0
  80. package/dist/types/utils/crossProjectApiPlugin.d.ts +9 -0
  81. package/dist/types/utils/effectClientGenerator.d.ts +27 -0
  82. package/dist/types/utils/pluginGenerator.d.ts +9 -0
  83. package/dist/types/utils/runtimeGenerator.d.ts +7 -0
  84. package/docs/data-platform-architecture.md +61 -0
  85. package/package.json +172 -0
  86. package/rslib.config.mts +4 -0
  87. package/rstest.config.mts +10 -0
  88. package/server.js +1 -0
@@ -0,0 +1,73 @@
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, definition)=>{
14
+ for(var key in definition)if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
15
+ enumerable: true,
16
+ get: definition[key]
17
+ });
18
+ };
19
+ })();
20
+ (()=>{
21
+ __webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
22
+ })();
23
+ (()=>{
24
+ __webpack_require__.r = (exports1)=>{
25
+ if ("u" > typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
26
+ value: 'Module'
27
+ });
28
+ Object.defineProperty(exports1, '__esModule', {
29
+ value: true
30
+ });
31
+ };
32
+ })();
33
+ var __webpack_exports__ = {};
34
+ __webpack_require__.r(__webpack_exports__);
35
+ __webpack_require__.d(__webpack_exports__, {
36
+ default: ()=>utils_pluginGenerator
37
+ });
38
+ const utils_namespaceObject = require("@modern-js/utils");
39
+ const external_path_namespaceObject = require("path");
40
+ var external_path_default = /*#__PURE__*/ __webpack_require__.n(external_path_namespaceObject);
41
+ const external_crossProjectApiPlugin_js_namespaceObject = require("./crossProjectApiPlugin.js");
42
+ function replaceContent(source, packageName, prefix, relativeDistPath, relativeApiPath, relativeLambdaPath, runtimeFramework) {
43
+ const updatedSource = source.replace(new RegExp(external_crossProjectApiPlugin_js_namespaceObject.PACKAGE_NAME, 'g'), packageName).replace(new RegExp(external_crossProjectApiPlugin_js_namespaceObject.PREFIX, 'g'), prefix).replace(new RegExp(external_crossProjectApiPlugin_js_namespaceObject.DIST_DIR, 'g'), (0, utils_namespaceObject.normalizeToPosixPath)(relativeDistPath)).replace(new RegExp(external_crossProjectApiPlugin_js_namespaceObject.API_DIR, 'g'), (0, utils_namespaceObject.normalizeToPosixPath)(relativeApiPath)).replace(new RegExp(external_crossProjectApiPlugin_js_namespaceObject.LAMBDA_DIR, 'g'), (0, utils_namespaceObject.normalizeToPosixPath)(relativeLambdaPath)).replace(new RegExp(external_crossProjectApiPlugin_js_namespaceObject.RUNTIME_FRAMEWORK, 'g'), runtimeFramework);
44
+ return updatedSource;
45
+ }
46
+ async function pluginGenerator({ prefix, appDirectory, relativeDistPath, relativeApiPath, relativeLambdaPath, runtimeFramework }) {
47
+ try {
48
+ const packageContent = await utils_namespaceObject.fs.readFile(external_path_default().resolve(appDirectory, './package.json'), 'utf8');
49
+ const packageJson = JSON.parse(packageContent);
50
+ const pluginDir = external_path_default().resolve(appDirectory, `./${relativeDistPath}`, 'plugin');
51
+ const pluginPath = external_path_default().join(pluginDir, 'index.js');
52
+ const pluginTemplate = await utils_namespaceObject.fs.readFile(external_path_default().resolve(__dirname, 'crossProjectApiPlugin.js'), 'utf8');
53
+ const updatedPlugin = replaceContent(pluginTemplate, packageJson.name, prefix, relativeDistPath, relativeApiPath, relativeLambdaPath, runtimeFramework);
54
+ await utils_namespaceObject.fs.ensureFile(pluginPath);
55
+ await utils_namespaceObject.fs.writeFile(pluginPath, updatedPlugin);
56
+ const typeContent = `import type { AppTools, CliPlugin } from '@modern-js/app-tools';
57
+ export declare const crossProjectApiPlugin: () => CliPlugin<AppTools>`;
58
+ const pluginTypePath = external_path_default().join(pluginDir, 'index.d.ts');
59
+ await utils_namespaceObject.fs.ensureFile(pluginTypePath);
60
+ await utils_namespaceObject.fs.writeFile(pluginTypePath, typeContent);
61
+ utils_namespaceObject.logger.info('Api plugin generate succeed');
62
+ } catch (error) {
63
+ utils_namespaceObject.logger.error('Api plugin generate failed:', error);
64
+ }
65
+ }
66
+ const utils_pluginGenerator = pluginGenerator;
67
+ exports["default"] = __webpack_exports__["default"];
68
+ for(var __rspack_i in __webpack_exports__)if (-1 === [
69
+ "default"
70
+ ].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
71
+ Object.defineProperty(exports, '__esModule', {
72
+ value: true
73
+ });
@@ -0,0 +1,133 @@
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, definition)=>{
14
+ for(var key in definition)if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
15
+ enumerable: true,
16
+ get: definition[key]
17
+ });
18
+ };
19
+ })();
20
+ (()=>{
21
+ __webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
22
+ })();
23
+ (()=>{
24
+ __webpack_require__.r = (exports1)=>{
25
+ if ("u" > typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
26
+ value: 'Module'
27
+ });
28
+ Object.defineProperty(exports1, '__esModule', {
29
+ value: true
30
+ });
31
+ };
32
+ })();
33
+ var __webpack_exports__ = {};
34
+ __webpack_require__.r(__webpack_exports__);
35
+ __webpack_require__.d(__webpack_exports__, {
36
+ default: ()=>utils_runtimeGenerator
37
+ });
38
+ const utils_namespaceObject = require("@modern-js/utils");
39
+ const external_path_namespaceObject = require("path");
40
+ var external_path_default = /*#__PURE__*/ __webpack_require__.n(external_path_namespaceObject);
41
+ const getPackageName = (appDirectory)=>{
42
+ try {
43
+ const packageJsonPath = external_path_default().resolve(appDirectory, './package.json');
44
+ const packageJson = require(packageJsonPath);
45
+ return packageJson.name;
46
+ } catch (error) {
47
+ return;
48
+ }
49
+ };
50
+ async function runtimeGenerator({ runtime, appDirectory, relativeDistPath, packageName }) {
51
+ const pluginDir = external_path_default().resolve(appDirectory, `./${relativeDistPath}`, 'runtime');
52
+ const requestId = packageName || getPackageName(appDirectory) || process.env.npm_package_name || 'default';
53
+ const runtimeImportPath = JSON.stringify(runtime);
54
+ const requestIdValue = JSON.stringify(requestId);
55
+ const source = `const { configure: _configure } = require(${runtimeImportPath});
56
+ const defaultSecureOptions = {
57
+ requestId: ${requestIdValue},
58
+ requireEnvelope: true,
59
+ identityBinding: {
60
+ enabled: true,
61
+ strict: true,
62
+ },
63
+ operationContract: {
64
+ enabled: true,
65
+ strict: true,
66
+ requireSchemaHash: true,
67
+ requireOperationVersion: true,
68
+ },
69
+ };
70
+ const initProducerClient = (options) => {
71
+ return _configure({
72
+ ...defaultSecureOptions,
73
+ ...options,
74
+ identityBinding: {
75
+ ...defaultSecureOptions.identityBinding,
76
+ ...(options && options.identityBinding ? options.identityBinding : {}),
77
+ },
78
+ operationContract: {
79
+ ...defaultSecureOptions.operationContract,
80
+ ...(options && options.operationContract ? options.operationContract : {}),
81
+ },
82
+ });
83
+ }
84
+ const configure = initProducerClient;
85
+ Object.defineProperty(exports, '__esModule', { value: true });
86
+ exports.initProducerClient = initProducerClient;
87
+ exports.configure = configure;
88
+ `;
89
+ const pluginPath = external_path_default().join(pluginDir, 'index.js');
90
+ await utils_namespaceObject.fs.ensureFile(pluginPath);
91
+ await utils_namespaceObject.fs.writeFile(pluginPath, source);
92
+ const tsSource = `type ProducerRuntimeModule = typeof import(${runtimeImportPath});
93
+ type ProducerClientOptions = ProducerRuntimeModule extends {
94
+ configure: (options: infer TOptions) => unknown;
95
+ }
96
+ ? TOptions
97
+ : {
98
+ request?: typeof fetch;
99
+ interceptor?: (request: typeof fetch) => typeof fetch;
100
+ allowedHeaders?: string[];
101
+ requireEnvelope?: boolean;
102
+ allowCrossOriginEnvelope?: boolean;
103
+ identityBinding?: {
104
+ enabled?: boolean;
105
+ strict?: boolean;
106
+ protectedHeaders?: string[];
107
+ };
108
+ operationContract?: {
109
+ enabled?: boolean;
110
+ strict?: boolean;
111
+ requireSchemaHash?: boolean;
112
+ requireOperationVersion?: boolean;
113
+ };
114
+ setDomain?: (ops?: {
115
+ target: 'server' | 'browser';
116
+ requestId?: string;
117
+ }) => string;
118
+ requestId?: string;
119
+ };
120
+ export declare const initProducerClient: (options: ProducerClientOptions) => void;
121
+ export declare const configure: typeof initProducerClient;`;
122
+ const pluginTypePath = external_path_default().join(pluginDir, 'index.d.ts');
123
+ await utils_namespaceObject.fs.ensureFile(pluginTypePath);
124
+ await utils_namespaceObject.fs.writeFile(pluginTypePath, tsSource);
125
+ }
126
+ const utils_runtimeGenerator = runtimeGenerator;
127
+ exports["default"] = __webpack_exports__["default"];
128
+ for(var __rspack_i in __webpack_exports__)if (-1 === [
129
+ "default"
130
+ ].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
131
+ Object.defineProperty(exports, '__esModule', {
132
+ value: true
133
+ });
@@ -0,0 +1,245 @@
1
+ import { ApiRouter } from "@modern-js/bff-core";
2
+ import { compile } from "@modern-js/server-utils";
3
+ import { API_DIR, DEFAULT_API_PREFIX, SHARED_DIR, fs, normalizeOutputPath, resolveServerTsconfig } from "@modern-js/utils";
4
+ import path from "path";
5
+ import clientGenerator from "./utils/clientGenerator.mjs";
6
+ import pluginGenerator from "./utils/pluginGenerator.mjs";
7
+ import runtimeGenerator from "./utils/runtimeGenerator.mjs";
8
+ const RUNTIME_CREATE_REQUEST = '@modern-js/plugin-bff/client';
9
+ const WATCHABLE_EXTENSIONS = [
10
+ '.ts',
11
+ '.tsx',
12
+ '.js',
13
+ '.jsx',
14
+ '.mts',
15
+ '.cts',
16
+ '.mjs',
17
+ '.cjs',
18
+ '.json'
19
+ ];
20
+ const isWatchableBffFile = (filename)=>WATCHABLE_EXTENSIONS.some((ext)=>filename.endsWith(ext));
21
+ const normalizePrefixList = (prefix)=>{
22
+ if (Array.isArray(prefix)) return prefix.filter(Boolean);
23
+ return [
24
+ prefix || DEFAULT_API_PREFIX
25
+ ];
26
+ };
27
+ const getPrimaryPrefix = (prefix)=>normalizePrefixList(prefix)[0] || DEFAULT_API_PREFIX;
28
+ const bffPlugin = ()=>({
29
+ name: '@modern-js/plugin-bff',
30
+ setup: (api)=>{
31
+ {
32
+ const appContext = api.getAppContext();
33
+ const userRuntimeFramework = api.getConfig()?.bff?.runtimeFramework;
34
+ api.updateAppContext({
35
+ ...appContext,
36
+ bffRuntimeFramework: 'hono' === userRuntimeFramework ? 'hono' : 'effect'
37
+ });
38
+ }
39
+ const compileApi = async ()=>{
40
+ const { appDirectory, distDirectory, apiDirectory, sharedDirectory, moduleType } = api.getAppContext();
41
+ const modernConfig = api.getNormalizedConfig();
42
+ const distDir = path.resolve(distDirectory);
43
+ const apiDir = apiDirectory || path.resolve(appDirectory, API_DIR);
44
+ const sharedDir = sharedDirectory || path.resolve(appDirectory, SHARED_DIR);
45
+ const tsconfigPath = resolveServerTsconfig(appDirectory, modernConfig?.server?.tsconfigPath);
46
+ const sourceDirs = [];
47
+ if (await fs.pathExists(apiDir)) sourceDirs.push(apiDir);
48
+ if (await fs.pathExists(sharedDir)) sourceDirs.push(sharedDir);
49
+ const { alias } = modernConfig.source;
50
+ const { alias: resolveAlias } = modernConfig.resolve;
51
+ if (sourceDirs.length > 0) {
52
+ const combinedAlias = [].concat(alias ?? []).concat(resolveAlias ?? []);
53
+ await compile(appDirectory, {
54
+ alias: combinedAlias
55
+ }, {
56
+ sourceDirs,
57
+ distDir,
58
+ tsconfigPath,
59
+ moduleType,
60
+ throwErrorInsteadOfExit: true
61
+ });
62
+ }
63
+ };
64
+ const generator = async ()=>{
65
+ const { appDirectory, apiDirectory, lambdaDirectory, port, bffRuntimeFramework } = api.getAppContext();
66
+ const modernConfig = api.getNormalizedConfig();
67
+ const relativeDistPath = modernConfig?.output?.distPath?.root || 'dist';
68
+ const { bff } = modernConfig || {};
69
+ const prefix = getPrimaryPrefix(bff?.prefix);
70
+ const httpMethodDecider = bff?.httpMethodDecider;
71
+ const apiRouter = new ApiRouter({
72
+ apiDir: apiDirectory,
73
+ appDir: appDirectory,
74
+ lambdaDir: lambdaDirectory,
75
+ prefix,
76
+ httpMethodDecider,
77
+ isBuild: true
78
+ });
79
+ const lambdaDir = apiRouter.getLambdaDir();
80
+ const existLambda = apiRouter.isExistLambda();
81
+ const runtime = bff?.runtimeCreateRequest || RUNTIME_CREATE_REQUEST;
82
+ const relativeApiPath = path.relative(appDirectory, apiDirectory);
83
+ const relativeLambdaPath = path.relative(appDirectory, lambdaDir);
84
+ await pluginGenerator({
85
+ prefix,
86
+ appDirectory,
87
+ relativeDistPath,
88
+ relativeApiPath,
89
+ relativeLambdaPath,
90
+ runtimeFramework: 'hono' === bffRuntimeFramework ? 'hono' : 'effect'
91
+ });
92
+ await clientGenerator({
93
+ prefix,
94
+ appDir: appDirectory,
95
+ apiDir: apiDirectory,
96
+ lambdaDir,
97
+ existLambda,
98
+ port,
99
+ requestCreator: bff?.requestCreator,
100
+ httpMethodDecider,
101
+ relativeDistPath,
102
+ relativeApiPath,
103
+ bffRuntimeFramework,
104
+ effectEntry: bff?.effect?.entry,
105
+ effectDataPlatformBatch: bff?.effect?.dataPlatform?.batch
106
+ });
107
+ await runtimeGenerator({
108
+ runtime,
109
+ appDirectory,
110
+ relativeDistPath
111
+ });
112
+ };
113
+ const handleCrossProjectInvocation = async (isBuild = false)=>{
114
+ const { bff } = api.getNormalizedConfig();
115
+ if (bff?.crossProject) {
116
+ if (!isBuild) await compileApi();
117
+ await generator();
118
+ }
119
+ };
120
+ const isHono = ()=>{
121
+ const { bffRuntimeFramework } = api.getAppContext();
122
+ return 'hono' === bffRuntimeFramework;
123
+ };
124
+ const createCompressConfig = (devServer, prefix)=>{
125
+ if (!devServer || 'object' != typeof devServer || Array.isArray(devServer)) return;
126
+ const { compress } = devServer;
127
+ if (void 0 === compress || true === compress) {
128
+ const prefixes = normalizePrefixList(prefix);
129
+ return {
130
+ filter: (req)=>!prefixes.some((item)=>req.url?.includes(item))
131
+ };
132
+ }
133
+ if (false === compress) return false;
134
+ return compress;
135
+ };
136
+ api.config(async ()=>{
137
+ const devServer = api.getConfig()?.tools?.devServer;
138
+ const prefix = api.getConfig()?.bff?.prefix || DEFAULT_API_PREFIX;
139
+ const compress = createCompressConfig(devServer, prefix);
140
+ return {
141
+ tools: {
142
+ devServer: {
143
+ compress
144
+ },
145
+ bundlerChain: (chain, { CHAIN_ID, isServer })=>{
146
+ const { port, appDirectory, apiDirectory, lambdaDirectory, bffRuntimeFramework } = api.getAppContext();
147
+ const modernConfig = api.getNormalizedConfig();
148
+ const { bff } = modernConfig || {};
149
+ const prefix = getPrimaryPrefix(bff?.prefix);
150
+ const httpMethodDecider = bff?.httpMethodDecider;
151
+ const apiRouter = new ApiRouter({
152
+ apiDir: apiDirectory,
153
+ appDir: appDirectory,
154
+ lambdaDir: lambdaDirectory,
155
+ prefix,
156
+ httpMethodDecider,
157
+ isBuild: true
158
+ });
159
+ const lambdaDir = apiRouter.getLambdaDir();
160
+ const existLambda = apiRouter.isExistLambda();
161
+ const apiRegexp = new RegExp(normalizeOutputPath(`${apiDirectory}${path.sep}.*(.[tj]s)$`));
162
+ const name = isServer ? 'server' : 'client';
163
+ const sourceExt = 'mjs';
164
+ const loaderPath = path.join(__dirname, `loader.${sourceExt}`);
165
+ chain.module.rule(CHAIN_ID.RULE.JS).exclude.add(apiRegexp);
166
+ chain.module.rule('js-bff-api').test(apiRegexp).use('custom-loader').loader(loaderPath.replace(/\\/g, '/')).options({
167
+ prefix,
168
+ appDir: appDirectory,
169
+ apiDir: apiDirectory,
170
+ lambdaDir,
171
+ existLambda,
172
+ port,
173
+ target: name,
174
+ requestCreator: bff?.requestCreator,
175
+ httpMethodDecider,
176
+ bffRuntimeFramework,
177
+ effectEntry: bff?.effect?.entry,
178
+ effectDataPlatformBatch: bff?.effect?.dataPlatform?.batch
179
+ });
180
+ }
181
+ }
182
+ };
183
+ });
184
+ api.modifyServerRoutes(({ routes })=>{
185
+ const modernConfig = api.getNormalizedConfig();
186
+ const { bff } = modernConfig || {};
187
+ const prefix = bff?.prefix || '/api';
188
+ const prefixList = [];
189
+ if (Array.isArray(prefix)) prefixList.push(...prefix);
190
+ else prefixList.push(prefix);
191
+ const apiServerRoutes = prefixList.map((pre)=>({
192
+ urlPath: pre,
193
+ isApi: true,
194
+ entryPath: '',
195
+ isSPA: false,
196
+ isSSR: false
197
+ }));
198
+ if (!isHono() && bff?.enableHandleWeb) return {
199
+ routes: routes.map((route)=>({
200
+ ...route,
201
+ isApi: true
202
+ })).concat(apiServerRoutes)
203
+ };
204
+ return {
205
+ routes: routes.concat(apiServerRoutes)
206
+ };
207
+ });
208
+ api._internalServerPlugins(({ plugins })=>{
209
+ plugins.push({
210
+ name: '@modern-js/plugin-bff/server-plugin'
211
+ });
212
+ return {
213
+ plugins
214
+ };
215
+ });
216
+ api.onBeforeDev(async ()=>{
217
+ await handleCrossProjectInvocation();
218
+ });
219
+ api.onAfterBuild(async ()=>{
220
+ await compileApi();
221
+ await handleCrossProjectInvocation(true);
222
+ });
223
+ api.addWatchFiles(async ()=>{
224
+ const appContext = api.getAppContext();
225
+ const config = api.getNormalizedConfig();
226
+ if (config?.bff?.crossProject) return [
227
+ appContext.apiDirectory,
228
+ appContext.sharedDirectory
229
+ ].filter(Boolean);
230
+ return [];
231
+ });
232
+ api.onFileChanged(async (e)=>{
233
+ const { filename, eventType, isPrivate } = e;
234
+ const { appDirectory, apiDirectory, sharedDirectory } = api.getAppContext();
235
+ const relativeApiPath = path.relative(appDirectory, apiDirectory);
236
+ const relativeSharedPath = sharedDirectory ? path.relative(appDirectory, sharedDirectory) : '';
237
+ const isApiFile = filename.startsWith(`${relativeApiPath}/`);
238
+ const isSharedFile = relativeSharedPath ? filename.startsWith(`${relativeSharedPath}/`) : false;
239
+ if (!isPrivate && ('add' === eventType || 'change' === eventType || 'unlink' === eventType) && (isApiFile || isSharedFile) && isWatchableBffFile(filename)) await handleCrossProjectInvocation();
240
+ });
241
+ }
242
+ });
243
+ const cli = bffPlugin;
244
+ export default cli;
245
+ export { bffPlugin };
@@ -0,0 +1,11 @@
1
+ const API_APP_NAME = '_app';
2
+ const BUILD_FILES = [
3
+ '**/*.[tj]sx?',
4
+ '!**/*.test.jsx?',
5
+ '!**/*.test.tsx?',
6
+ '!**/*.spec.jsx?',
7
+ '!**/*.spec.tsx?',
8
+ '!__tests__/*.tsx?',
9
+ '!__tests__/*.jsx?'
10
+ ];
11
+ export { API_APP_NAME, BUILD_FILES };
@@ -0,0 +1 @@
1
+ export * from "./constants.mjs";
@@ -0,0 +1,62 @@
1
+ import { generateClient } from "@modern-js/bff-core";
2
+ import { logger } from "@modern-js/utils";
3
+ import path from "path";
4
+ import { generateEffectClientCode, resolveEffectEntryFile } from "./utils/effectClientGenerator.mjs";
5
+ async function loader(source) {
6
+ this.cacheable();
7
+ const { resourcePath } = this;
8
+ delete require.cache[resourcePath];
9
+ const callback = this.async();
10
+ const draftOptions = this.getOptions();
11
+ const effectEntryFile = resolveEffectEntryFile({
12
+ appDir: draftOptions.appDir,
13
+ apiDir: draftOptions.apiDir,
14
+ effectEntry: draftOptions.effectEntry
15
+ });
16
+ if ('effect' === draftOptions.bffRuntimeFramework && effectEntryFile && path.resolve(effectEntryFile) === path.resolve(resourcePath)) {
17
+ const code = await generateEffectClientCode({
18
+ appDir: draftOptions.appDir,
19
+ apiDir: draftOptions.apiDir,
20
+ resourcePath,
21
+ prefix: Array.isArray(draftOptions.prefix) ? draftOptions.prefix[0] : draftOptions.prefix,
22
+ port: Number(draftOptions.port),
23
+ target: draftOptions.target,
24
+ requestCreator: draftOptions.requestCreator,
25
+ httpMethodDecider: draftOptions.httpMethodDecider,
26
+ dataPlatformBatch: draftOptions.effectDataPlatformBatch
27
+ });
28
+ if (code) return void callback(void 0, code);
29
+ callback(void 0, `throw new Error('Failed to generate Effect client for ${resourcePath}')`);
30
+ return;
31
+ }
32
+ const warning = `The file ${resourcePath} is not allowed to be imported in src directory, only API definition files are allowed.`;
33
+ if (!draftOptions.existLambda) {
34
+ logger.warn(warning);
35
+ callback(null, `throw new Error('${warning}')`);
36
+ return;
37
+ }
38
+ const options = {
39
+ prefix: Array.isArray(draftOptions.prefix) ? draftOptions.prefix[0] : draftOptions.prefix,
40
+ appDir: draftOptions.appDir,
41
+ apiDir: draftOptions.apiDir,
42
+ lambdaDir: draftOptions.lambdaDir,
43
+ target: draftOptions.target,
44
+ port: Number(draftOptions.port),
45
+ source,
46
+ resourcePath,
47
+ httpMethodDecider: draftOptions.httpMethodDecider
48
+ };
49
+ const { lambdaDir } = draftOptions;
50
+ if (!resourcePath.startsWith(lambdaDir)) {
51
+ logger.warn(warning);
52
+ callback(null, `throw new Error('${warning}')`);
53
+ return;
54
+ }
55
+ if (draftOptions.fetcher) options.fetcher = draftOptions.fetcher;
56
+ if (draftOptions.requestCreator) options.requestCreator = draftOptions.requestCreator;
57
+ options.requireResolve = require.resolve;
58
+ const result = await generateClient(options);
59
+ callback(void 0, result.isOk ? result.value : `throw new Error('${result.value}')`);
60
+ }
61
+ const src_loader = loader;
62
+ export default src_loader;
@@ -0,0 +1 @@
1
+ export { configure, createRequest, createRequestContextHeaders, createRequestContextSnapshot, createUploader } from "@modern-js/create-request";