@modern-js/bff-core 2.69.5 → 3.0.0-alpha.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 (77) hide show
  1. package/dist/cjs/api.js +82 -78
  2. package/dist/cjs/client/generateClient.js +90 -76
  3. package/dist/cjs/client/index.js +55 -19
  4. package/dist/cjs/client/result.js +51 -42
  5. package/dist/cjs/compatible.js +17 -15
  6. package/dist/cjs/errors/http.js +43 -34
  7. package/dist/cjs/index.js +169 -54
  8. package/dist/cjs/operators/http.js +213 -212
  9. package/dist/cjs/router/constants.js +63 -57
  10. package/dist/cjs/router/index.js +271 -291
  11. package/dist/cjs/router/types.js +17 -15
  12. package/dist/cjs/router/utils.js +90 -92
  13. package/dist/cjs/types.js +84 -71
  14. package/dist/cjs/utils/alias.js +100 -103
  15. package/dist/cjs/utils/debug.js +34 -26
  16. package/dist/cjs/utils/index.js +98 -34
  17. package/dist/cjs/utils/meta.js +45 -38
  18. package/dist/cjs/utils/storage.js +58 -68
  19. package/dist/cjs/utils/validate.js +73 -72
  20. package/dist/esm/api.mjs +44 -0
  21. package/dist/esm/client/generateClient.mjs +60 -0
  22. package/dist/esm/client/result.mjs +19 -0
  23. package/dist/esm/compatible.mjs +0 -0
  24. package/dist/esm/errors/http.mjs +13 -0
  25. package/dist/esm/index.mjs +8 -0
  26. package/dist/esm/operators/http.mjs +135 -0
  27. package/dist/esm/router/constants.mjs +19 -0
  28. package/dist/esm/router/index.mjs +186 -0
  29. package/dist/esm/router/types.mjs +0 -0
  30. package/dist/esm/router/utils.mjs +42 -0
  31. package/dist/esm/types.mjs +39 -0
  32. package/dist/esm/utils/alias.mjs +57 -0
  33. package/dist/esm/utils/debug.mjs +3 -0
  34. package/dist/esm/utils/{index.js → index.mjs} +2 -4
  35. package/dist/esm/utils/meta.mjs +5 -0
  36. package/dist/esm/utils/storage.mjs +30 -0
  37. package/dist/esm/utils/validate.mjs +32 -0
  38. package/dist/esm-node/api.mjs +44 -0
  39. package/dist/esm-node/client/generateClient.mjs +60 -0
  40. package/dist/esm-node/client/index.mjs +1 -0
  41. package/dist/esm-node/client/result.mjs +19 -0
  42. package/dist/esm-node/errors/http.mjs +13 -0
  43. package/dist/esm-node/index.mjs +8 -0
  44. package/dist/esm-node/operators/http.mjs +135 -0
  45. package/dist/esm-node/router/constants.mjs +19 -0
  46. package/dist/esm-node/router/index.mjs +186 -0
  47. package/dist/esm-node/router/utils.mjs +42 -0
  48. package/dist/esm-node/types.mjs +39 -0
  49. package/dist/esm-node/utils/alias.mjs +57 -0
  50. package/dist/esm-node/utils/debug.mjs +3 -0
  51. package/dist/esm-node/utils/index.mjs +6 -0
  52. package/dist/esm-node/utils/meta.mjs +5 -0
  53. package/dist/esm-node/utils/storage.mjs +30 -0
  54. package/dist/esm-node/utils/validate.mjs +32 -0
  55. package/dist/types/client/generateClient.d.ts +1 -1
  56. package/dist/types/router/constants.d.ts +0 -10
  57. package/dist/types/router/index.d.ts +0 -5
  58. package/package.json +18 -18
  59. package/rslib.config.mts +4 -0
  60. package/dist/esm/api.js +0 -50
  61. package/dist/esm/client/generateClient.js +0 -60
  62. package/dist/esm/client/result.js +0 -22
  63. package/dist/esm/errors/http.js +0 -16
  64. package/dist/esm/index.js +0 -19
  65. package/dist/esm/operators/http.js +0 -178
  66. package/dist/esm/router/constants.js +0 -32
  67. package/dist/esm/router/index.js +0 -261
  68. package/dist/esm/router/utils.js +0 -62
  69. package/dist/esm/types.js +0 -46
  70. package/dist/esm/utils/alias.js +0 -75
  71. package/dist/esm/utils/debug.js +0 -5
  72. package/dist/esm/utils/meta.js +0 -14
  73. package/dist/esm/utils/storage.js +0 -40
  74. package/dist/esm/utils/validate.js +0 -45
  75. /package/dist/esm/client/{index.js → index.mjs} +0 -0
  76. /package/dist/{esm/compatible.js → esm-node/compatible.mjs} +0 -0
  77. /package/dist/{esm/router/types.js → esm-node/router/types.mjs} +0 -0
@@ -0,0 +1,60 @@
1
+ import { resolve } from "path";
2
+ import { ApiRouter } from "../router/index.mjs";
3
+ import { Err, Ok } from "./result.mjs";
4
+ const getPackageName = (appDir)=>{
5
+ try {
6
+ const packageJsonPath = resolve(appDir, './package.json');
7
+ const packageJson = require(packageJsonPath);
8
+ return packageJson.name;
9
+ } catch (error) {
10
+ return;
11
+ }
12
+ };
13
+ const DEFAULT_CLIENT_REQUEST_CREATOR = '@modern-js/create-request';
14
+ const INNER_CLIENT_REQUEST_CREATOR = '@modern-js/plugin-bff/client';
15
+ const generateClient = async ({ appDir, resourcePath, apiDir, lambdaDir, prefix, port, target, requestCreator, fetcher, requireResolve = require.resolve, httpMethodDecider, domain })=>{
16
+ requestCreator = requestCreator || INNER_CLIENT_REQUEST_CREATOR;
17
+ const apiRouter = new ApiRouter({
18
+ appDir,
19
+ apiDir,
20
+ lambdaDir,
21
+ prefix,
22
+ httpMethodDecider
23
+ });
24
+ const handlerInfos = await apiRouter.getSingleModuleHandlers(resourcePath);
25
+ if (!handlerInfos) return Err(`generate client error: Cannot require module ${resourcePath}`);
26
+ let handlersCode = '';
27
+ for (const handlerInfo of handlerInfos){
28
+ const { name, httpMethod, routePath, action } = handlerInfo;
29
+ let exportStatement = `var ${name} =`;
30
+ if ('default' === name.toLowerCase()) exportStatement = 'default';
31
+ const upperHttpMethod = httpMethod.toUpperCase();
32
+ const routeName = routePath;
33
+ const requestId = 'bundle' === target ? getPackageName(appDir) || process.env.npm_package_name : void 0;
34
+ if ('upload' === action) {
35
+ const requestOptions = {
36
+ path: routeName,
37
+ domain,
38
+ requestId
39
+ };
40
+ handlersCode += `export ${exportStatement} createUploader(${JSON.stringify(requestOptions)});`;
41
+ } else {
42
+ const portValue = 'server' === target ? `process.env.PORT || ${String(port)}` : String(port);
43
+ const optionsStr = `{
44
+ path: '${routeName}',
45
+ method: '${upperHttpMethod}',
46
+ port: ${portValue},
47
+ httpMethodDecider: '${httpMethodDecider || 'functionName'}'
48
+ ${domain ? `, domain: '${domain}'` : ''}
49
+ ${fetcher ? ", fetch: 'fetch'" : ''}
50
+ ${requestId ? `, requestId: '${requestId}'` : ''}
51
+ }`.replace(/\n\s*/g, '');
52
+ handlersCode += `export ${exportStatement} createRequest(${optionsStr});
53
+ `;
54
+ }
55
+ }
56
+ const importCode = `import { createRequest${handlerInfos.find((i)=>'upload' === i.action) ? ', createUploader' : ''} } from '${requestCreator}';
57
+ ${fetcher ? `import { fetch } from '${fetcher}';\n` : ''}`;
58
+ return Ok(`${importCode}\n${handlersCode}`);
59
+ };
60
+ export { DEFAULT_CLIENT_REQUEST_CREATOR, INNER_CLIENT_REQUEST_CREATOR, generateClient };
@@ -0,0 +1 @@
1
+ export * from "./generateClient.mjs";
@@ -0,0 +1,19 @@
1
+ const Err = (value)=>{
2
+ const err = {
3
+ kind: 'Err',
4
+ value,
5
+ isErr: true,
6
+ isOk: false
7
+ };
8
+ return err;
9
+ };
10
+ const Ok = (value)=>{
11
+ const ok = {
12
+ kind: 'Ok',
13
+ value,
14
+ isErr: false,
15
+ isOk: true
16
+ };
17
+ return ok;
18
+ };
19
+ export { Err, Ok };
@@ -0,0 +1,13 @@
1
+ class HttpError extends Error {
2
+ constructor(status, message){
3
+ super(message);
4
+ this.status = status;
5
+ }
6
+ }
7
+ class ValidationError extends HttpError {
8
+ constructor(status, message){
9
+ super(status, message);
10
+ this.code = 'VALIDATION_ERROR';
11
+ }
12
+ }
13
+ export { HttpError, ValidationError };
@@ -0,0 +1,8 @@
1
+ import { Api } from "./api.mjs";
2
+ import { HttpError, ValidationError } from "./errors/http.mjs";
3
+ import { HANDLER_WITH_META, INPUT_PARAMS_DECIDER, createStorage, getRelativeRuntimePath, isInputParamsDeciderHandler, isWithMetaHandler, registerPaths } from "./utils/index.mjs";
4
+ export * from "./router/index.mjs";
5
+ export * from "./types.mjs";
6
+ export * from "./client/index.mjs";
7
+ export * from "./operators/http.mjs";
8
+ export { Api, HANDLER_WITH_META, HttpError, INPUT_PARAMS_DECIDER, ValidationError, createStorage, getRelativeRuntimePath, isInputParamsDeciderHandler, isWithMetaHandler, registerPaths };
@@ -0,0 +1,135 @@
1
+ import { ValidationError } from "../errors/http.mjs";
2
+ import { HttpMetadata, HttpMethod, OperatorType, ResponseMetaType, TriggerType } from "../types.mjs";
3
+ const validateInput = async (schema, input)=>{
4
+ try {
5
+ return await schema.parseAsync(input);
6
+ } catch (error) {
7
+ if ('name' in error && 'ZodError' === error.name) throw new ValidationError(400, error.message);
8
+ throw error;
9
+ }
10
+ };
11
+ const createHttpOperator = (method)=>(urlPath)=>({
12
+ name: method,
13
+ metadata ({ setMetadata }) {
14
+ setMetadata(OperatorType.Trigger, {
15
+ type: TriggerType.Http,
16
+ path: urlPath,
17
+ method
18
+ });
19
+ }
20
+ });
21
+ const Get = createHttpOperator(HttpMethod.Get);
22
+ const Post = createHttpOperator(HttpMethod.Post);
23
+ const Put = createHttpOperator(HttpMethod.Put);
24
+ const Delete = createHttpOperator(HttpMethod.Delete);
25
+ const Connect = createHttpOperator(HttpMethod.Connect);
26
+ const Trace = createHttpOperator(HttpMethod.Trace);
27
+ const Patch = createHttpOperator(HttpMethod.Patch);
28
+ const Options = createHttpOperator(HttpMethod.Options);
29
+ const Head = createHttpOperator(HttpMethod.Head);
30
+ const Data = (schema)=>({
31
+ name: HttpMetadata.Data,
32
+ metadata ({ setMetadata }) {
33
+ setMetadata(HttpMetadata.Data, schema);
34
+ },
35
+ async validate (helper, next) {
36
+ const { inputs: { data } } = helper;
37
+ helper.inputs = {
38
+ ...helper.inputs,
39
+ data: await validateInput(schema, data)
40
+ };
41
+ return next();
42
+ }
43
+ });
44
+ const Query = (schema)=>({
45
+ name: HttpMetadata.Query,
46
+ metadata ({ setMetadata }) {
47
+ setMetadata(HttpMetadata.Query, schema);
48
+ },
49
+ async validate (helper, next) {
50
+ const { inputs: { query } } = helper;
51
+ helper.inputs = {
52
+ ...helper.inputs,
53
+ query: await validateInput(schema, query)
54
+ };
55
+ return next();
56
+ }
57
+ });
58
+ const Params = (schema)=>({
59
+ name: HttpMetadata.Params,
60
+ metadata ({ setMetadata }) {
61
+ setMetadata(HttpMetadata.Params, schema);
62
+ },
63
+ async validate (helper, next) {
64
+ const { inputs: { params } } = helper;
65
+ helper.inputs = {
66
+ ...helper.inputs,
67
+ params: await validateInput(schema, params)
68
+ };
69
+ return next();
70
+ }
71
+ });
72
+ const Headers = (schema)=>({
73
+ name: HttpMetadata.Headers,
74
+ metadata ({ setMetadata }) {
75
+ setMetadata(HttpMetadata.Headers, schema);
76
+ },
77
+ async validate (helper, next) {
78
+ const { inputs: { headers } } = helper;
79
+ helper.inputs = {
80
+ ...helper.inputs,
81
+ headers: await validateInput(schema, headers)
82
+ };
83
+ return next();
84
+ }
85
+ });
86
+ const setResponseMeta = (helper, type, value)=>{
87
+ const responseMetaData = helper.getMetadata(HttpMetadata.Response) || [];
88
+ helper.setMetadata(HttpMetadata.Response, [
89
+ ...responseMetaData,
90
+ {
91
+ type,
92
+ value
93
+ }
94
+ ]);
95
+ };
96
+ const HttpCode = (statusCode)=>({
97
+ name: 'HttpCode',
98
+ metadata (helper) {
99
+ setResponseMeta(helper, ResponseMetaType.StatusCode, statusCode);
100
+ }
101
+ });
102
+ const SetHeaders = (headers)=>({
103
+ name: 'SetHeaders',
104
+ metadata (helper) {
105
+ setResponseMeta(helper, ResponseMetaType.Headers, headers);
106
+ }
107
+ });
108
+ const Redirect = (url)=>({
109
+ name: 'Redirect',
110
+ metadata (helper) {
111
+ setResponseMeta(helper, ResponseMetaType.Redirect, url);
112
+ }
113
+ });
114
+ const Upload = (urlPath, schema)=>({
115
+ name: 'Upload',
116
+ metadata ({ setMetadata }) {
117
+ setMetadata(OperatorType.Trigger, {
118
+ type: TriggerType.Http,
119
+ path: urlPath,
120
+ method: HttpMethod.Post,
121
+ action: 'upload'
122
+ });
123
+ setMetadata(HttpMetadata.Files, schema);
124
+ },
125
+ async validate (helper, next) {
126
+ if (!schema) return next();
127
+ const { inputs: { formData: files } } = helper;
128
+ helper.inputs = {
129
+ ...helper.inputs,
130
+ files: await validateInput(schema, files)
131
+ };
132
+ return next();
133
+ }
134
+ });
135
+ export { Connect, Data, Delete, Get, Head, Headers, HttpCode, Options, Params, Patch, Post, Put, Query, Redirect, SetHeaders, Trace, Upload, createHttpOperator };
@@ -0,0 +1,19 @@
1
+ import { HttpMethod } from "../types.mjs";
2
+ const AllHttpMethods = Object.values(HttpMethod);
3
+ const FRAMEWORK_MODE_LAMBDA_DIR = 'lambda';
4
+ const FRAMEWORK_MODE_APP_DIR = 'app';
5
+ const INDEX_SUFFIX = 'index';
6
+ const API_DIR = 'api';
7
+ const API_FILE_RULES = [
8
+ '**/*.[tj]s',
9
+ '!**/_*',
10
+ '!**/_*/**/*.[tj]s',
11
+ '!**/*.test.js',
12
+ '!**/*.test.ts',
13
+ '!**/*.d.ts',
14
+ '!__test__/*.ts',
15
+ '!__tests__/*.ts',
16
+ '!node_modules/**',
17
+ '!bootstrap.jsx'
18
+ ];
19
+ export { API_DIR, API_FILE_RULES, AllHttpMethods, FRAMEWORK_MODE_APP_DIR, FRAMEWORK_MODE_LAMBDA_DIR, INDEX_SUFFIX };
@@ -0,0 +1,186 @@
1
+ import path from "path";
2
+ import { fs, logger } from "@modern-js/utils";
3
+ import "reflect-metadata";
4
+ import { HttpMethod, OperatorType, TriggerType, httpMethods } from "../types.mjs";
5
+ import { INPUT_PARAMS_DECIDER, debug } from "../utils/index.mjs";
6
+ import { API_FILE_RULES, FRAMEWORK_MODE_LAMBDA_DIR } from "./constants.mjs";
7
+ import { getFiles, getPathFromFilename, requireHandlerModule, sortRoutes } from "./utils.mjs";
8
+ export * from "./types.mjs";
9
+ export * from "./constants.mjs";
10
+ class ApiRouter {
11
+ isExistLambda() {
12
+ return this.existLambdaDir;
13
+ }
14
+ getLambdaDir() {
15
+ return this.lambdaDir;
16
+ }
17
+ isApiFile(filename) {
18
+ if (this.apiFiles.includes(filename)) return true;
19
+ return false;
20
+ }
21
+ async getSingleModuleHandlers(filename) {
22
+ const moduleInfo = await this.getModuleInfo(filename);
23
+ if (moduleInfo) return this.getModuleHandlerInfos(moduleInfo);
24
+ return null;
25
+ }
26
+ getHandlerInfo(filename, originFuncName, handler) {
27
+ const httpMethod = this.getHttpMethod(originFuncName, handler);
28
+ const routeName = this.getRouteName(filename, handler);
29
+ const action = this.getAction(handler);
30
+ const responseObj = {
31
+ handler,
32
+ name: originFuncName,
33
+ httpMethod,
34
+ routeName,
35
+ filename,
36
+ routePath: this.getRoutePath(this.prefix, routeName)
37
+ };
38
+ if (action) responseObj.action = action;
39
+ if (httpMethod && routeName) return responseObj;
40
+ return null;
41
+ }
42
+ getSafeRoutePath(filename, handler) {
43
+ this.loadApiFiles();
44
+ this.validateValidApifile(filename);
45
+ return this.getRouteName(filename, handler);
46
+ }
47
+ getRouteName(filename, handler) {
48
+ if (handler) {
49
+ const trigger = Reflect.getMetadata(OperatorType.Trigger, handler);
50
+ if (trigger && trigger.type === TriggerType.Http) {
51
+ if (!trigger.path) throw new Error(`The http trigger ${trigger.name} needs to specify a path`);
52
+ return trigger.path;
53
+ }
54
+ }
55
+ let routePath = getPathFromFilename(this.lambdaDir, filename);
56
+ if ('inputParams' === this.httpMethodDecider) if (routePath.endsWith('/')) routePath += `${handler?.name}`;
57
+ else routePath += `/${handler?.name}`;
58
+ return routePath;
59
+ }
60
+ getHttpMethod(originHandlerName, handler) {
61
+ if (handler) {
62
+ const trigger = Reflect.getMetadata(OperatorType.Trigger, handler);
63
+ if (trigger && httpMethods.includes(trigger.method)) return trigger.method;
64
+ }
65
+ if ('functionName' === this.httpMethodDecider) {
66
+ const upperName = originHandlerName.toUpperCase();
67
+ switch(upperName){
68
+ case 'GET':
69
+ return HttpMethod.Get;
70
+ case 'POST':
71
+ return HttpMethod.Post;
72
+ case 'PUT':
73
+ return HttpMethod.Put;
74
+ case 'DELETE':
75
+ case 'DEL':
76
+ return HttpMethod.Delete;
77
+ case 'CONNECT':
78
+ return HttpMethod.Connect;
79
+ case 'TRACE':
80
+ return HttpMethod.Trace;
81
+ case 'PATCH':
82
+ return HttpMethod.Patch;
83
+ case 'OPTIONS':
84
+ return HttpMethod.Options;
85
+ case 'DEFAULT':
86
+ return HttpMethod.Get;
87
+ default:
88
+ if ('test' !== process.env.NODE_ENV) logger.warn(`Only api handlers are allowd to be exported, please remove the function ${originHandlerName} from exports`);
89
+ return null;
90
+ }
91
+ }
92
+ if (!handler) return null;
93
+ if ('function' == typeof handler && handler.length > 0) return HttpMethod.Post;
94
+ return HttpMethod.Get;
95
+ }
96
+ getAction(handler) {
97
+ if (handler) {
98
+ const trigger = Reflect.getMetadata(OperatorType.Trigger, handler);
99
+ if (trigger?.action) return trigger.action;
100
+ }
101
+ }
102
+ loadApiFiles() {
103
+ if (!this.existLambdaDir) return [];
104
+ const apiFiles = this.apiFiles = getFiles(this.lambdaDir, API_FILE_RULES);
105
+ return apiFiles;
106
+ }
107
+ getApiFiles() {
108
+ if (!this.existLambdaDir) return [];
109
+ if (this.apiFiles.length > 0) return this.apiFiles;
110
+ return this.loadApiFiles();
111
+ }
112
+ async getApiHandlers() {
113
+ const filenames = this.getApiFiles();
114
+ const moduleInfos = await this.getModuleInfos(filenames);
115
+ const apiHandlers = this.getHandlerInfos(moduleInfos);
116
+ debug('apiHandlers', apiHandlers.length, apiHandlers);
117
+ return apiHandlers;
118
+ }
119
+ initPrefix(prefix) {
120
+ if ('/' === prefix) return '';
121
+ return prefix || '/api';
122
+ }
123
+ validateAbsolute(filename, paramsName) {
124
+ if ('string' == typeof filename && !path.isAbsolute(filename)) throw new Error(`The ${paramsName} ${filename} is not a abolute path`);
125
+ }
126
+ async getModuleInfos(filenames) {
127
+ return Promise.all(filenames.map((filename)=>this.getModuleInfo(filename)).filter((moduleInfo)=>Boolean(moduleInfo)));
128
+ }
129
+ async getModuleInfo(filename) {
130
+ try {
131
+ const module = await requireHandlerModule(filename);
132
+ return {
133
+ filename,
134
+ module
135
+ };
136
+ } catch (err) {
137
+ if ('production' === process.env.NODE_ENV) throw err;
138
+ console.error(err);
139
+ return null;
140
+ }
141
+ }
142
+ getHandlerInfos(moduleInfos) {
143
+ let apiHandlers = [];
144
+ moduleInfos.forEach((moduleInfo)=>{
145
+ const handlerInfos = this.getModuleHandlerInfos(moduleInfo);
146
+ if (handlerInfos) apiHandlers = apiHandlers.concat(handlerInfos);
147
+ });
148
+ const sortedHandlers = sortRoutes(apiHandlers);
149
+ return sortedHandlers;
150
+ }
151
+ getModuleHandlerInfos(moduleInfo) {
152
+ const { module, filename } = moduleInfo;
153
+ const { httpMethodDecider } = this;
154
+ return Object.entries(module).filter(([, handler])=>'function' == typeof handler).map(([key])=>{
155
+ const handler = module[key];
156
+ if ('inputParams' === httpMethodDecider) Object.assign(handler, {
157
+ [INPUT_PARAMS_DECIDER]: true
158
+ });
159
+ const handlerInfo = this.getHandlerInfo(filename, key, handler);
160
+ return handlerInfo;
161
+ }).filter((handlerInfo)=>Boolean(handlerInfo));
162
+ }
163
+ validateValidApifile(filename) {
164
+ if (!this.apiFiles.includes(filename)) throw new Error(`The ${filename} is not a valid api file.`);
165
+ }
166
+ getRoutePath(prefix, routeName) {
167
+ const finalRouteName = '/' === routeName ? '' : routeName;
168
+ if ('' === prefix && '' === finalRouteName) return '/';
169
+ return `${prefix}${finalRouteName}`;
170
+ }
171
+ constructor({ appDir, apiDir, lambdaDir, prefix, isBuild, httpMethodDecider = 'functionName' }){
172
+ this.apiFiles = [];
173
+ this.getExactLambdaDir = (apiDir, originLambdaDir)=>originLambdaDir || path.join(apiDir, FRAMEWORK_MODE_LAMBDA_DIR);
174
+ this.validateAbsolute(apiDir, 'apiDir');
175
+ this.validateAbsolute(lambdaDir, 'lambdaDir');
176
+ this.prefix = this.initPrefix(prefix);
177
+ this.appDir = appDir;
178
+ this.apiDir = apiDir;
179
+ this.httpMethodDecider = httpMethodDecider;
180
+ this.isBuild = isBuild;
181
+ this.lambdaDir = this.getExactLambdaDir(this.apiDir, lambdaDir);
182
+ this.existLambdaDir = fs.existsSync(this.lambdaDir);
183
+ debug("apiDir:", this.apiDir, "lambdaDir:", this.lambdaDir);
184
+ }
185
+ }
186
+ export { ApiRouter };
@@ -0,0 +1,42 @@
1
+ import path from "path";
2
+ import { compatibleRequire, globby } from "@modern-js/utils";
3
+ import { INDEX_SUFFIX } from "./constants.mjs";
4
+ const getFiles = (lambdaDir, rules)=>globby.sync(rules, {
5
+ cwd: lambdaDir,
6
+ gitignore: true
7
+ }).map((file)=>path.resolve(lambdaDir, file));
8
+ const getPathFromFilename = (baseDir, filename)=>{
9
+ const relativeName = filename.substring(baseDir.length);
10
+ const relativePath = relativeName.split('.').slice(0, -1).join('.');
11
+ const nameSplit = relativePath.split(path.sep).map((item)=>{
12
+ if (item.length > 2) {
13
+ if (item.startsWith('[') && item.endsWith(']')) return `:${item.substring(1, item.length - 1)}`;
14
+ }
15
+ return item;
16
+ });
17
+ const name = nameSplit.join('/');
18
+ const finalName = name.endsWith(INDEX_SUFFIX) ? name.substring(0, name.length - INDEX_SUFFIX.length) : name;
19
+ return clearRouteName(finalName);
20
+ };
21
+ const clearRouteName = (routeName)=>{
22
+ let finalRouteName = routeName.trim();
23
+ if (!finalRouteName.startsWith('/')) finalRouteName = `/${finalRouteName}`;
24
+ if (finalRouteName.length > 1 && finalRouteName.endsWith('/')) finalRouteName = finalRouteName.substring(0, finalRouteName.length - 1);
25
+ return finalRouteName;
26
+ };
27
+ const isHandler = (input)=>input && 'function' == typeof input;
28
+ const isFunction = (input)=>input && '[object Function]' === ({}).toString.call(input);
29
+ const requireHandlerModule = async (modulePath)=>{
30
+ const originRequire = 'test' === process.env.NODE_ENV ? jest.requireActual : compatibleRequire;
31
+ const module = await originRequire(modulePath, false);
32
+ if (isFunction(module)) return {
33
+ default: module
34
+ };
35
+ return module;
36
+ };
37
+ const routeValue = (routePath)=>{
38
+ if (routePath.includes(':')) return 11;
39
+ return 1;
40
+ };
41
+ const sortRoutes = (apiHandlers)=>apiHandlers.sort((handlerA, handlerB)=>routeValue(handlerA.routeName) - routeValue(handlerB.routeName));
42
+ export { getFiles, getPathFromFilename, isHandler, requireHandlerModule, sortRoutes };
@@ -0,0 +1,39 @@
1
+ var types_OperatorType = /*#__PURE__*/ function(OperatorType) {
2
+ OperatorType[OperatorType["Trigger"] = 0] = "Trigger";
3
+ OperatorType[OperatorType["Middleware"] = 1] = "Middleware";
4
+ return OperatorType;
5
+ }({});
6
+ var types_TriggerType = /*#__PURE__*/ function(TriggerType) {
7
+ TriggerType[TriggerType["Http"] = 0] = "Http";
8
+ return TriggerType;
9
+ }({});
10
+ var types_HttpMetadata = /*#__PURE__*/ function(HttpMetadata) {
11
+ HttpMetadata["Method"] = "METHOD";
12
+ HttpMetadata["Data"] = "DATA";
13
+ HttpMetadata["Query"] = "QUERY";
14
+ HttpMetadata["Params"] = "PARAMS";
15
+ HttpMetadata["Headers"] = "HEADERS";
16
+ HttpMetadata["Response"] = "RESPONSE";
17
+ HttpMetadata["Files"] = "Files";
18
+ return HttpMetadata;
19
+ }({});
20
+ var types_ResponseMetaType = /*#__PURE__*/ function(ResponseMetaType) {
21
+ ResponseMetaType[ResponseMetaType["StatusCode"] = 0] = "StatusCode";
22
+ ResponseMetaType[ResponseMetaType["Redirect"] = 1] = "Redirect";
23
+ ResponseMetaType[ResponseMetaType["Headers"] = 2] = "Headers";
24
+ return ResponseMetaType;
25
+ }({});
26
+ var types_HttpMethod = /*#__PURE__*/ function(HttpMethod) {
27
+ HttpMethod["Get"] = "GET";
28
+ HttpMethod["Post"] = "POST";
29
+ HttpMethod["Put"] = "PUT";
30
+ HttpMethod["Delete"] = "DELETE";
31
+ HttpMethod["Connect"] = "CONNECT";
32
+ HttpMethod["Trace"] = "TRACE";
33
+ HttpMethod["Patch"] = "PATCH";
34
+ HttpMethod["Options"] = "OPTIONS";
35
+ HttpMethod["Head"] = "HEAD";
36
+ return HttpMethod;
37
+ }({});
38
+ const httpMethods = Object.values(types_HttpMethod);
39
+ export { types_HttpMetadata as HttpMetadata, types_HttpMethod as HttpMethod, types_OperatorType as OperatorType, types_ResponseMetaType as ResponseMetaType, types_TriggerType as TriggerType, httpMethods };
@@ -0,0 +1,57 @@
1
+ import fs from "fs";
2
+ import module_0 from "module";
3
+ import { platform } from "os";
4
+ import { isAbsolute, join, relative } from "path";
5
+ const getRelativeRuntimePath = (appDirectory, serverRuntimePath)=>{
6
+ let relativeRuntimePath = '';
7
+ relativeRuntimePath = 'win32' === platform() ? `../${relative(appDirectory, serverRuntimePath)}` : join('../', relative(appDirectory, serverRuntimePath));
8
+ if ('development' === process.env.NODE_ENV || 'test' === process.env.NODE_ENV) relativeRuntimePath = `./${relative(appDirectory, serverRuntimePath)}`;
9
+ return relativeRuntimePath;
10
+ };
11
+ const sortByLongestPrefix = (arr)=>arr.concat().sort((a, b)=>b.length - a.length);
12
+ const createMatchPath = (paths)=>{
13
+ const sortedKeys = sortByLongestPrefix(Object.keys(paths));
14
+ const sortedPaths = {};
15
+ sortedKeys.forEach((key)=>{
16
+ sortedPaths[key] = paths[key];
17
+ });
18
+ return (request)=>{
19
+ const found = Object.keys(sortedPaths).find((key)=>request.startsWith(key));
20
+ if (found) {
21
+ let foundPaths = sortedPaths[found];
22
+ if (!Array.isArray(foundPaths)) foundPaths = [
23
+ foundPaths
24
+ ];
25
+ foundPaths = foundPaths.filter((foundPath)=>isAbsolute(foundPath));
26
+ for (const p of foundPaths){
27
+ const foundPath = request.replace(found, p);
28
+ if (fs.existsSync(foundPath)) return foundPath;
29
+ }
30
+ return request.replace(found, foundPaths[0]);
31
+ }
32
+ return null;
33
+ };
34
+ };
35
+ const registerPaths = (paths)=>{
36
+ const originalResolveFilename = module_0._resolveFilename;
37
+ const { builtinModules } = module_0;
38
+ const matchPath = createMatchPath(paths);
39
+ module_0._resolveFilename = function(request, _parent) {
40
+ const isCoreModule = builtinModules.includes(request);
41
+ if (!isCoreModule) {
42
+ const matched = matchPath(request);
43
+ if (matched) {
44
+ const modifiedArguments = [
45
+ matched,
46
+ ...[].slice.call(arguments, 1)
47
+ ];
48
+ return originalResolveFilename.apply(this, modifiedArguments);
49
+ }
50
+ }
51
+ return originalResolveFilename.apply(this, arguments);
52
+ };
53
+ return ()=>{
54
+ module_0._resolveFilename = originalResolveFilename;
55
+ };
56
+ };
57
+ export { createMatchPath, getRelativeRuntimePath, registerPaths };
@@ -0,0 +1,3 @@
1
+ import { createDebugger } from "@modern-js/utils";
2
+ const debug = createDebugger('bff');
3
+ export { debug };
@@ -0,0 +1,6 @@
1
+ import { debug } from "./debug.mjs";
2
+ export * from "./storage.mjs";
3
+ export * from "./alias.mjs";
4
+ export * from "./meta.mjs";
5
+ export * from "./validate.mjs";
6
+ export { debug };
@@ -0,0 +1,5 @@
1
+ const HANDLER_WITH_META = 'HANDLER_WITH_META';
2
+ const INPUT_PARAMS_DECIDER = 'INPUT_PARAMS_DECIDER';
3
+ const isWithMetaHandler = (handler)=>'function' == typeof handler && handler[HANDLER_WITH_META];
4
+ const isInputParamsDeciderHandler = (handler)=>'function' == typeof handler && handler[INPUT_PARAMS_DECIDER];
5
+ export { HANDLER_WITH_META, INPUT_PARAMS_DECIDER, isInputParamsDeciderHandler, isWithMetaHandler };
@@ -0,0 +1,30 @@
1
+ import { AsyncLocalStorage } from "async_hooks";
2
+ const createStorage = ()=>{
3
+ let storage;
4
+ if (void 0 !== AsyncLocalStorage) storage = new AsyncLocalStorage();
5
+ const run = (context, cb)=>{
6
+ if (!storage) throw new Error(`Unable to use async_hook, please confirm the node version >= 12.17
7
+ `);
8
+ return new Promise((resolve, reject)=>{
9
+ storage.run(context, ()=>{
10
+ try {
11
+ return resolve(cb());
12
+ } catch (error) {
13
+ return reject(error);
14
+ }
15
+ });
16
+ });
17
+ };
18
+ const useContext = ()=>{
19
+ if (!storage) throw new Error(`Unable to use async_hook, please confirm the node version >= 12.17
20
+ `);
21
+ const context = storage.getStore();
22
+ if (!context) throw new Error("Can't call useContext out of scope, it should be placed in the bff function");
23
+ return context;
24
+ };
25
+ return {
26
+ run,
27
+ useContext
28
+ };
29
+ };
30
+ export { createStorage };
@@ -0,0 +1,32 @@
1
+ import util from "util";
2
+ const getTypeErrorMessage = (actual)=>{
3
+ let msg = '';
4
+ if (null == actual) msg += `. Received ${actual}`;
5
+ else if ('function' == typeof actual && actual.name) msg += `. Received function ${actual.name}`;
6
+ else if ('object' == typeof actual) if (actual.constructor?.name) msg += `. Received an instance of ${actual.constructor.name}`;
7
+ else {
8
+ const inspected = util.inspect(actual, {
9
+ depth: -1
10
+ });
11
+ msg += `. Received ${inspected}`;
12
+ }
13
+ else {
14
+ let inspected = util.inspect(actual, {
15
+ colors: false
16
+ });
17
+ if (inspected.length > 25) inspected = `${inspected.slice(0, 25)}...`;
18
+ msg += `. Received type ${typeof actual} (${inspected})`;
19
+ }
20
+ return msg;
21
+ };
22
+ class ERR_INVALID_ARG_TYPE extends Error {
23
+ constructor(funcName, expectedType, actual){
24
+ const message = `[ERR_INVALID_ARG_TYPE]: The '${funcName}' argument must be of type ${expectedType}${getTypeErrorMessage(actual)}`;
25
+ super(message);
26
+ }
27
+ }
28
+ const validateFunction = (maybeFunc, name)=>{
29
+ if ('function' != typeof maybeFunc) throw new ERR_INVALID_ARG_TYPE(name, 'function', maybeFunc);
30
+ return true;
31
+ };
32
+ export { ERR_INVALID_ARG_TYPE, getTypeErrorMessage, validateFunction };