@bleedingdev/modern-js-bff-core 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.
- package/LICENSE +21 -0
- package/README.md +26 -0
- package/dist/cjs/api.js +88 -0
- package/dist/cjs/client/generateClient.js +136 -0
- package/dist/cjs/client/index.js +58 -0
- package/dist/cjs/client/result.js +56 -0
- package/dist/cjs/compatible.js +18 -0
- package/dist/cjs/contracts/eventContracts.js +68 -0
- package/dist/cjs/errors/http.js +50 -0
- package/dist/cjs/index.js +229 -0
- package/dist/cjs/operators/http.js +220 -0
- package/dist/cjs/router/constants.js +68 -0
- package/dist/cjs/router/index.js +284 -0
- package/dist/cjs/router/types.js +18 -0
- package/dist/cjs/router/utils.js +97 -0
- package/dist/cjs/security/crossProjectPolicy.js +137 -0
- package/dist/cjs/security/operationContracts.js +100 -0
- package/dist/cjs/types.js +88 -0
- package/dist/cjs/utils/alias.js +108 -0
- package/dist/cjs/utils/debug.js +37 -0
- package/dist/cjs/utils/index.js +101 -0
- package/dist/cjs/utils/meta.js +48 -0
- package/dist/cjs/utils/storage.js +64 -0
- package/dist/cjs/utils/validate.js +82 -0
- package/dist/esm/api.mjs +44 -0
- package/dist/esm/client/generateClient.mjs +99 -0
- package/dist/esm/client/index.mjs +1 -0
- package/dist/esm/client/result.mjs +19 -0
- package/dist/esm/compatible.mjs +0 -0
- package/dist/esm/contracts/eventContracts.mjs +28 -0
- package/dist/esm/errors/http.mjs +13 -0
- package/dist/esm/index.mjs +10 -0
- package/dist/esm/operators/http.mjs +135 -0
- package/dist/esm/router/constants.mjs +19 -0
- package/dist/esm/router/index.mjs +192 -0
- package/dist/esm/router/types.mjs +0 -0
- package/dist/esm/router/utils.mjs +41 -0
- package/dist/esm/security/crossProjectPolicy.mjs +94 -0
- package/dist/esm/security/operationContracts.mjs +57 -0
- package/dist/esm/types.mjs +39 -0
- package/dist/esm/utils/alias.mjs +57 -0
- package/dist/esm/utils/debug.mjs +3 -0
- package/dist/esm/utils/index.mjs +5 -0
- package/dist/esm/utils/meta.mjs +5 -0
- package/dist/esm/utils/storage.mjs +30 -0
- package/dist/esm/utils/validate.mjs +32 -0
- package/dist/esm-node/api.mjs +45 -0
- package/dist/esm-node/client/generateClient.mjs +101 -0
- package/dist/esm-node/client/index.mjs +2 -0
- package/dist/esm-node/client/result.mjs +20 -0
- package/dist/esm-node/compatible.mjs +1 -0
- package/dist/esm-node/contracts/eventContracts.mjs +29 -0
- package/dist/esm-node/errors/http.mjs +14 -0
- package/dist/esm-node/index.mjs +11 -0
- package/dist/esm-node/operators/http.mjs +136 -0
- package/dist/esm-node/router/constants.mjs +20 -0
- package/dist/esm-node/router/index.mjs +193 -0
- package/dist/esm-node/router/types.mjs +1 -0
- package/dist/esm-node/router/utils.mjs +42 -0
- package/dist/esm-node/security/crossProjectPolicy.mjs +95 -0
- package/dist/esm-node/security/operationContracts.mjs +58 -0
- package/dist/esm-node/types.mjs +40 -0
- package/dist/esm-node/utils/alias.mjs +58 -0
- package/dist/esm-node/utils/debug.mjs +4 -0
- package/dist/esm-node/utils/index.mjs +6 -0
- package/dist/esm-node/utils/meta.mjs +6 -0
- package/dist/esm-node/utils/storage.mjs +31 -0
- package/dist/esm-node/utils/validate.mjs +33 -0
- package/dist/types/api.d.ts +6 -0
- package/dist/types/client/generateClient.d.ts +21 -0
- package/dist/types/client/index.d.ts +1 -0
- package/dist/types/client/result.d.ts +15 -0
- package/dist/types/compatible.d.ts +9 -0
- package/dist/types/contracts/eventContracts.d.ts +22 -0
- package/dist/types/errors/http.d.ts +8 -0
- package/dist/types/index.d.ts +11 -0
- package/dist/types/operators/http.d.ts +44 -0
- package/dist/types/router/constants.d.ts +6 -0
- package/dist/types/router/index.d.ts +49 -0
- package/dist/types/router/types.d.ts +18 -0
- package/dist/types/router/utils.d.ts +10 -0
- package/dist/types/security/crossProjectPolicy.d.ts +30 -0
- package/dist/types/security/operationContracts.d.ts +28 -0
- package/dist/types/types.d.ts +64 -0
- package/dist/types/utils/alias.d.ts +7 -0
- package/dist/types/utils/debug.d.ts +1 -0
- package/dist/types/utils/index.d.ts +5 -0
- package/dist/types/utils/meta.d.ts +4 -0
- package/dist/types/utils/storage.d.ts +5 -0
- package/dist/types/utils/validate.d.ts +5 -0
- package/package.json +68 -0
- package/rslib.config.mts +4 -0
- package/rstest.config.mts +10 -0
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __webpack_modules__ = {
|
|
3
|
+
"../types" (module) {
|
|
4
|
+
module.exports = require("../types.js");
|
|
5
|
+
},
|
|
6
|
+
"../utils" (module) {
|
|
7
|
+
module.exports = require("../utils/index.js");
|
|
8
|
+
},
|
|
9
|
+
"./constants" (module) {
|
|
10
|
+
module.exports = require("./constants.js");
|
|
11
|
+
},
|
|
12
|
+
"./types" (module) {
|
|
13
|
+
module.exports = require("./types.js");
|
|
14
|
+
},
|
|
15
|
+
"./utils?198b" (module) {
|
|
16
|
+
module.exports = require("./utils.js");
|
|
17
|
+
},
|
|
18
|
+
"@modern-js/utils" (module) {
|
|
19
|
+
module.exports = require("@modern-js/utils");
|
|
20
|
+
},
|
|
21
|
+
path (module) {
|
|
22
|
+
module.exports = require("path");
|
|
23
|
+
},
|
|
24
|
+
"reflect-metadata" (module) {
|
|
25
|
+
module.exports = require("reflect-metadata");
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
var __webpack_module_cache__ = {};
|
|
29
|
+
function __webpack_require__(moduleId) {
|
|
30
|
+
var cachedModule = __webpack_module_cache__[moduleId];
|
|
31
|
+
if (void 0 !== cachedModule) return cachedModule.exports;
|
|
32
|
+
var module = __webpack_module_cache__[moduleId] = {
|
|
33
|
+
exports: {}
|
|
34
|
+
};
|
|
35
|
+
__webpack_modules__[moduleId](module, module.exports, __webpack_require__);
|
|
36
|
+
return module.exports;
|
|
37
|
+
}
|
|
38
|
+
(()=>{
|
|
39
|
+
__webpack_require__.n = (module)=>{
|
|
40
|
+
var getter = module && module.__esModule ? ()=>module['default'] : ()=>module;
|
|
41
|
+
__webpack_require__.d(getter, {
|
|
42
|
+
a: getter
|
|
43
|
+
});
|
|
44
|
+
return getter;
|
|
45
|
+
};
|
|
46
|
+
})();
|
|
47
|
+
(()=>{
|
|
48
|
+
__webpack_require__.d = (exports1, definition)=>{
|
|
49
|
+
for(var key in definition)if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
|
|
50
|
+
enumerable: true,
|
|
51
|
+
get: definition[key]
|
|
52
|
+
});
|
|
53
|
+
};
|
|
54
|
+
})();
|
|
55
|
+
(()=>{
|
|
56
|
+
__webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
|
|
57
|
+
})();
|
|
58
|
+
(()=>{
|
|
59
|
+
__webpack_require__.r = (exports1)=>{
|
|
60
|
+
if ("u" > typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
|
|
61
|
+
value: 'Module'
|
|
62
|
+
});
|
|
63
|
+
Object.defineProperty(exports1, '__esModule', {
|
|
64
|
+
value: true
|
|
65
|
+
});
|
|
66
|
+
};
|
|
67
|
+
})();
|
|
68
|
+
var __webpack_exports__ = {};
|
|
69
|
+
(()=>{
|
|
70
|
+
__webpack_require__.r(__webpack_exports__);
|
|
71
|
+
__webpack_require__.d(__webpack_exports__, {
|
|
72
|
+
ApiRouter: ()=>ApiRouter
|
|
73
|
+
});
|
|
74
|
+
var _modern_js_utils__rspack_import_0 = __webpack_require__("@modern-js/utils");
|
|
75
|
+
var path__rspack_import_1 = __webpack_require__("path");
|
|
76
|
+
var path__rspack_import_1_default = /*#__PURE__*/ __webpack_require__.n(path__rspack_import_1);
|
|
77
|
+
__webpack_require__("reflect-metadata");
|
|
78
|
+
var _types__rspack_import_3 = __webpack_require__("../types");
|
|
79
|
+
var _utils__rspack_import_4 = __webpack_require__("../utils");
|
|
80
|
+
var _constants__rspack_import_5 = __webpack_require__("./constants");
|
|
81
|
+
var _utils__rspack_import_6 = __webpack_require__("./utils?198b");
|
|
82
|
+
var __rspack_reexport = {};
|
|
83
|
+
for(const __rspack_import_key in _constants__rspack_import_5)if ([
|
|
84
|
+
"ApiRouter",
|
|
85
|
+
"default"
|
|
86
|
+
].indexOf(__rspack_import_key) < 0) __rspack_reexport[__rspack_import_key] = ()=>_constants__rspack_import_5[__rspack_import_key];
|
|
87
|
+
__webpack_require__.d(__webpack_exports__, __rspack_reexport);
|
|
88
|
+
var _types__rspack_import_7 = __webpack_require__("./types");
|
|
89
|
+
var __rspack_reexport = {};
|
|
90
|
+
for(const __rspack_import_key in _types__rspack_import_7)if ([
|
|
91
|
+
"ApiRouter",
|
|
92
|
+
"default"
|
|
93
|
+
].indexOf(__rspack_import_key) < 0) __rspack_reexport[__rspack_import_key] = ()=>_types__rspack_import_7[__rspack_import_key];
|
|
94
|
+
__webpack_require__.d(__webpack_exports__, __rspack_reexport);
|
|
95
|
+
class ApiRouter {
|
|
96
|
+
isExistLambda() {
|
|
97
|
+
return this.existLambdaDir;
|
|
98
|
+
}
|
|
99
|
+
getLambdaDir() {
|
|
100
|
+
return this.lambdaDir;
|
|
101
|
+
}
|
|
102
|
+
isApiFile(filename) {
|
|
103
|
+
if (this.apiFiles.includes(filename)) return true;
|
|
104
|
+
return false;
|
|
105
|
+
}
|
|
106
|
+
async getSingleModuleHandlers(filename) {
|
|
107
|
+
const moduleInfo = await this.getModuleInfo(filename);
|
|
108
|
+
if (moduleInfo) return this.getModuleHandlerInfos(moduleInfo);
|
|
109
|
+
return null;
|
|
110
|
+
}
|
|
111
|
+
getHandlerInfo(filename, originFuncName, handler) {
|
|
112
|
+
const httpMethod = this.getHttpMethod(originFuncName, handler);
|
|
113
|
+
const routeName = this.getRouteName(filename, handler);
|
|
114
|
+
const action = this.getAction(handler);
|
|
115
|
+
const responseObj = {
|
|
116
|
+
handler,
|
|
117
|
+
name: originFuncName,
|
|
118
|
+
httpMethod,
|
|
119
|
+
routeName,
|
|
120
|
+
filename,
|
|
121
|
+
routePath: this.getRoutePath(this.prefix, routeName)
|
|
122
|
+
};
|
|
123
|
+
if (action) responseObj.action = action;
|
|
124
|
+
if (httpMethod && routeName) return responseObj;
|
|
125
|
+
return null;
|
|
126
|
+
}
|
|
127
|
+
getSafeRoutePath(filename, handler) {
|
|
128
|
+
this.loadApiFiles();
|
|
129
|
+
this.validateValidApifile(filename);
|
|
130
|
+
return this.getRouteName(filename, handler);
|
|
131
|
+
}
|
|
132
|
+
getRouteName(filename, handler) {
|
|
133
|
+
if (handler) {
|
|
134
|
+
const trigger = Reflect.getMetadata(_types__rspack_import_3.OperatorType.Trigger, handler);
|
|
135
|
+
if (trigger && trigger.type === _types__rspack_import_3.TriggerType.Http) {
|
|
136
|
+
if (!trigger.path) throw new Error(`The http trigger ${trigger.name} needs to specify a path`);
|
|
137
|
+
return trigger.path;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
let routePath = (0, _utils__rspack_import_6.getPathFromFilename)(this.lambdaDir, filename);
|
|
141
|
+
if ('inputParams' === this.httpMethodDecider) if (routePath.endsWith('/')) routePath += `${handler?.name}`;
|
|
142
|
+
else routePath += `/${handler?.name}`;
|
|
143
|
+
return routePath;
|
|
144
|
+
}
|
|
145
|
+
getHttpMethod(originHandlerName, handler) {
|
|
146
|
+
if (handler) {
|
|
147
|
+
const trigger = Reflect.getMetadata(_types__rspack_import_3.OperatorType.Trigger, handler);
|
|
148
|
+
if (trigger && _types__rspack_import_3.httpMethods.includes(trigger.method)) return trigger.method;
|
|
149
|
+
}
|
|
150
|
+
if ('functionName' === this.httpMethodDecider) {
|
|
151
|
+
const upperName = originHandlerName.toUpperCase();
|
|
152
|
+
switch(upperName){
|
|
153
|
+
case 'GET':
|
|
154
|
+
return _types__rspack_import_3.HttpMethod.Get;
|
|
155
|
+
case 'POST':
|
|
156
|
+
return _types__rspack_import_3.HttpMethod.Post;
|
|
157
|
+
case 'PUT':
|
|
158
|
+
return _types__rspack_import_3.HttpMethod.Put;
|
|
159
|
+
case 'DELETE':
|
|
160
|
+
case 'DEL':
|
|
161
|
+
return _types__rspack_import_3.HttpMethod.Delete;
|
|
162
|
+
case 'CONNECT':
|
|
163
|
+
return _types__rspack_import_3.HttpMethod.Connect;
|
|
164
|
+
case 'TRACE':
|
|
165
|
+
return _types__rspack_import_3.HttpMethod.Trace;
|
|
166
|
+
case 'PATCH':
|
|
167
|
+
return _types__rspack_import_3.HttpMethod.Patch;
|
|
168
|
+
case 'OPTIONS':
|
|
169
|
+
return _types__rspack_import_3.HttpMethod.Options;
|
|
170
|
+
case 'DEFAULT':
|
|
171
|
+
return _types__rspack_import_3.HttpMethod.Get;
|
|
172
|
+
default:
|
|
173
|
+
if ('test' !== process.env.NODE_ENV) _modern_js_utils__rspack_import_0.logger.warn(`Only api handlers are allowd to be exported, please remove the function ${originHandlerName} from exports`);
|
|
174
|
+
return null;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
if (!handler) return null;
|
|
178
|
+
if ('function' == typeof handler && handler.length > 0) return _types__rspack_import_3.HttpMethod.Post;
|
|
179
|
+
return _types__rspack_import_3.HttpMethod.Get;
|
|
180
|
+
}
|
|
181
|
+
getAction(handler) {
|
|
182
|
+
if (handler) {
|
|
183
|
+
const trigger = Reflect.getMetadata(_types__rspack_import_3.OperatorType.Trigger, handler);
|
|
184
|
+
if (trigger?.action) return trigger.action;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
loadApiFiles() {
|
|
188
|
+
if (!this.existLambdaDir) return [];
|
|
189
|
+
const apiFiles = this.apiFiles = (0, _utils__rspack_import_6.getFiles)(this.lambdaDir, _constants__rspack_import_5.API_FILE_RULES);
|
|
190
|
+
return apiFiles;
|
|
191
|
+
}
|
|
192
|
+
getApiFiles() {
|
|
193
|
+
if (!this.existLambdaDir) return [];
|
|
194
|
+
if (this.apiFiles.length > 0) return this.apiFiles;
|
|
195
|
+
return this.loadApiFiles();
|
|
196
|
+
}
|
|
197
|
+
async getApiHandlers() {
|
|
198
|
+
const filenames = this.getApiFiles();
|
|
199
|
+
const moduleInfos = await this.getModuleInfos(filenames);
|
|
200
|
+
const apiHandlers = this.getHandlerInfos(moduleInfos);
|
|
201
|
+
(0, _utils__rspack_import_4.debug)('apiHandlers', apiHandlers.length, apiHandlers);
|
|
202
|
+
return apiHandlers;
|
|
203
|
+
}
|
|
204
|
+
initPrefix(prefix) {
|
|
205
|
+
if ('/' === prefix) return '';
|
|
206
|
+
return prefix || '/api';
|
|
207
|
+
}
|
|
208
|
+
validateAbsolute(filename, paramsName) {
|
|
209
|
+
if ('string' == typeof filename && !path__rspack_import_1_default().isAbsolute(filename)) throw new Error(`The ${paramsName} ${filename} is not a abolute path`);
|
|
210
|
+
}
|
|
211
|
+
async getModuleInfos(filenames) {
|
|
212
|
+
const moduleInfos = await Promise.all(filenames.map((filename)=>this.getModuleInfo(filename)));
|
|
213
|
+
return moduleInfos.filter(Boolean);
|
|
214
|
+
}
|
|
215
|
+
async getModuleInfo(filename) {
|
|
216
|
+
try {
|
|
217
|
+
const module = await (0, _utils__rspack_import_6.requireHandlerModule)(filename);
|
|
218
|
+
return {
|
|
219
|
+
filename,
|
|
220
|
+
module
|
|
221
|
+
};
|
|
222
|
+
} catch (err) {
|
|
223
|
+
if ('production' === process.env.NODE_ENV) {
|
|
224
|
+
const error = new Error(`Failed to load BFF module '${filename}': ${err.message}`, {
|
|
225
|
+
cause: err
|
|
226
|
+
});
|
|
227
|
+
throw error;
|
|
228
|
+
}
|
|
229
|
+
console.error(`Failed to load BFF module '${filename}':`, err);
|
|
230
|
+
return null;
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
getHandlerInfos(moduleInfos) {
|
|
234
|
+
let apiHandlers = [];
|
|
235
|
+
moduleInfos.forEach((moduleInfo)=>{
|
|
236
|
+
const handlerInfos = this.getModuleHandlerInfos(moduleInfo);
|
|
237
|
+
if (handlerInfos) apiHandlers = apiHandlers.concat(handlerInfos);
|
|
238
|
+
});
|
|
239
|
+
const sortedHandlers = (0, _utils__rspack_import_6.sortRoutes)(apiHandlers);
|
|
240
|
+
return sortedHandlers;
|
|
241
|
+
}
|
|
242
|
+
getModuleHandlerInfos(moduleInfo) {
|
|
243
|
+
const { module, filename } = moduleInfo;
|
|
244
|
+
const { httpMethodDecider } = this;
|
|
245
|
+
return Object.entries(module).filter(([, handler])=>'function' == typeof handler).map(([key])=>{
|
|
246
|
+
const handler = module[key];
|
|
247
|
+
if ('inputParams' === httpMethodDecider) Object.assign(handler, {
|
|
248
|
+
[_utils__rspack_import_4.INPUT_PARAMS_DECIDER]: true
|
|
249
|
+
});
|
|
250
|
+
const handlerInfo = this.getHandlerInfo(filename, key, handler);
|
|
251
|
+
return handlerInfo;
|
|
252
|
+
}).filter((handlerInfo)=>Boolean(handlerInfo));
|
|
253
|
+
}
|
|
254
|
+
validateValidApifile(filename) {
|
|
255
|
+
if (!this.apiFiles.includes(filename)) throw new Error(`The ${filename} is not a valid api file.`);
|
|
256
|
+
}
|
|
257
|
+
getRoutePath(prefix, routeName) {
|
|
258
|
+
const finalRouteName = '/' === routeName ? '' : routeName;
|
|
259
|
+
if ('' === prefix && '' === finalRouteName) return '/';
|
|
260
|
+
return `${prefix}${finalRouteName}`;
|
|
261
|
+
}
|
|
262
|
+
constructor({ appDir, apiDir, lambdaDir, prefix, isBuild, httpMethodDecider = 'functionName' }){
|
|
263
|
+
this.apiFiles = [];
|
|
264
|
+
this.getExactLambdaDir = (apiDir, originLambdaDir)=>originLambdaDir || path__rspack_import_1_default().join(apiDir, _constants__rspack_import_5.FRAMEWORK_MODE_LAMBDA_DIR);
|
|
265
|
+
this.validateAbsolute(apiDir, 'apiDir');
|
|
266
|
+
this.validateAbsolute(lambdaDir, 'lambdaDir');
|
|
267
|
+
this.prefix = this.initPrefix(prefix);
|
|
268
|
+
this.appDir = appDir;
|
|
269
|
+
this.apiDir = apiDir;
|
|
270
|
+
this.httpMethodDecider = httpMethodDecider;
|
|
271
|
+
this.isBuild = isBuild;
|
|
272
|
+
this.lambdaDir = this.getExactLambdaDir(this.apiDir, lambdaDir);
|
|
273
|
+
this.existLambdaDir = _modern_js_utils__rspack_import_0.fs.existsSync(this.lambdaDir);
|
|
274
|
+
(0, _utils__rspack_import_4.debug)("apiDir:", this.apiDir, "lambdaDir:", this.lambdaDir);
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
})();
|
|
278
|
+
exports.ApiRouter = __webpack_exports__.ApiRouter;
|
|
279
|
+
for(var __rspack_i in __webpack_exports__)if (-1 === [
|
|
280
|
+
"ApiRouter"
|
|
281
|
+
].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
|
|
282
|
+
Object.defineProperty(exports, '__esModule', {
|
|
283
|
+
value: true
|
|
284
|
+
});
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __webpack_require__ = {};
|
|
3
|
+
(()=>{
|
|
4
|
+
__webpack_require__.r = (exports1)=>{
|
|
5
|
+
if ("u" > typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
|
|
6
|
+
value: 'Module'
|
|
7
|
+
});
|
|
8
|
+
Object.defineProperty(exports1, '__esModule', {
|
|
9
|
+
value: true
|
|
10
|
+
});
|
|
11
|
+
};
|
|
12
|
+
})();
|
|
13
|
+
var __webpack_exports__ = {};
|
|
14
|
+
__webpack_require__.r(__webpack_exports__);
|
|
15
|
+
for(var __rspack_i in __webpack_exports__)exports[__rspack_i] = __webpack_exports__[__rspack_i];
|
|
16
|
+
Object.defineProperty(exports, '__esModule', {
|
|
17
|
+
value: true
|
|
18
|
+
});
|
|
@@ -0,0 +1,97 @@
|
|
|
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
|
+
getFiles: ()=>getFiles,
|
|
37
|
+
getPathFromFilename: ()=>getPathFromFilename,
|
|
38
|
+
isHandler: ()=>isHandler,
|
|
39
|
+
requireHandlerModule: ()=>requireHandlerModule,
|
|
40
|
+
sortRoutes: ()=>sortRoutes
|
|
41
|
+
});
|
|
42
|
+
const utils_namespaceObject = require("@modern-js/utils");
|
|
43
|
+
const external_path_namespaceObject = require("path");
|
|
44
|
+
var external_path_default = /*#__PURE__*/ __webpack_require__.n(external_path_namespaceObject);
|
|
45
|
+
const external_constants_js_namespaceObject = require("./constants.js");
|
|
46
|
+
const getFiles = (lambdaDir, rules)=>utils_namespaceObject.globby.sync(rules, {
|
|
47
|
+
cwd: lambdaDir,
|
|
48
|
+
gitignore: true
|
|
49
|
+
}).map((file)=>external_path_default().resolve(lambdaDir, file));
|
|
50
|
+
const getPathFromFilename = (baseDir, filename)=>{
|
|
51
|
+
const relativeName = filename.substring(baseDir.length);
|
|
52
|
+
const relativePath = relativeName.split('.').slice(0, -1).join('.');
|
|
53
|
+
const nameSplit = relativePath.split(external_path_default().sep).map((item)=>{
|
|
54
|
+
if (item.length > 2) {
|
|
55
|
+
if (item.startsWith('[') && item.endsWith(']')) return `:${item.substring(1, item.length - 1)}`;
|
|
56
|
+
}
|
|
57
|
+
return item;
|
|
58
|
+
});
|
|
59
|
+
const name = nameSplit.join('/');
|
|
60
|
+
const finalName = name.endsWith(external_constants_js_namespaceObject.INDEX_SUFFIX) ? name.substring(0, name.length - external_constants_js_namespaceObject.INDEX_SUFFIX.length) : name;
|
|
61
|
+
return clearRouteName(finalName);
|
|
62
|
+
};
|
|
63
|
+
const clearRouteName = (routeName)=>{
|
|
64
|
+
let finalRouteName = routeName.trim();
|
|
65
|
+
if (!finalRouteName.startsWith('/')) finalRouteName = `/${finalRouteName}`;
|
|
66
|
+
if (finalRouteName.length > 1 && finalRouteName.endsWith('/')) finalRouteName = finalRouteName.substring(0, finalRouteName.length - 1);
|
|
67
|
+
return finalRouteName;
|
|
68
|
+
};
|
|
69
|
+
const isHandler = (input)=>input && 'function' == typeof input;
|
|
70
|
+
const isFunction = (input)=>input && '[object Function]' === ({}).toString.call(input);
|
|
71
|
+
const requireHandlerModule = async (modulePath)=>{
|
|
72
|
+
const module = await (0, utils_namespaceObject.compatibleRequire)(modulePath, false);
|
|
73
|
+
if (isFunction(module)) return {
|
|
74
|
+
default: module
|
|
75
|
+
};
|
|
76
|
+
return module;
|
|
77
|
+
};
|
|
78
|
+
const routeValue = (routePath)=>{
|
|
79
|
+
if (routePath.includes(':')) return 11;
|
|
80
|
+
return 1;
|
|
81
|
+
};
|
|
82
|
+
const sortRoutes = (apiHandlers)=>apiHandlers.sort((handlerA, handlerB)=>routeValue(handlerA.routeName) - routeValue(handlerB.routeName));
|
|
83
|
+
exports.getFiles = __webpack_exports__.getFiles;
|
|
84
|
+
exports.getPathFromFilename = __webpack_exports__.getPathFromFilename;
|
|
85
|
+
exports.isHandler = __webpack_exports__.isHandler;
|
|
86
|
+
exports.requireHandlerModule = __webpack_exports__.requireHandlerModule;
|
|
87
|
+
exports.sortRoutes = __webpack_exports__.sortRoutes;
|
|
88
|
+
for(var __rspack_i in __webpack_exports__)if (-1 === [
|
|
89
|
+
"getFiles",
|
|
90
|
+
"getPathFromFilename",
|
|
91
|
+
"isHandler",
|
|
92
|
+
"requireHandlerModule",
|
|
93
|
+
"sortRoutes"
|
|
94
|
+
].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
|
|
95
|
+
Object.defineProperty(exports, '__esModule', {
|
|
96
|
+
value: true
|
|
97
|
+
});
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __webpack_require__ = {};
|
|
3
|
+
(()=>{
|
|
4
|
+
__webpack_require__.d = (exports1, definition)=>{
|
|
5
|
+
for(var key in definition)if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
|
|
6
|
+
enumerable: true,
|
|
7
|
+
get: definition[key]
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
})();
|
|
11
|
+
(()=>{
|
|
12
|
+
__webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
|
|
13
|
+
})();
|
|
14
|
+
(()=>{
|
|
15
|
+
__webpack_require__.r = (exports1)=>{
|
|
16
|
+
if ("u" > typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
|
|
17
|
+
value: 'Module'
|
|
18
|
+
});
|
|
19
|
+
Object.defineProperty(exports1, '__esModule', {
|
|
20
|
+
value: true
|
|
21
|
+
});
|
|
22
|
+
};
|
|
23
|
+
})();
|
|
24
|
+
var __webpack_exports__ = {};
|
|
25
|
+
__webpack_require__.r(__webpack_exports__);
|
|
26
|
+
__webpack_require__.d(__webpack_exports__, {
|
|
27
|
+
BFF_ENVELOPE_HEADER: ()=>BFF_ENVELOPE_HEADER,
|
|
28
|
+
BFF_OPERATION_CONTEXT_DETAIL_HEADER: ()=>BFF_OPERATION_CONTEXT_DETAIL_HEADER,
|
|
29
|
+
BFF_OPERATION_CONTEXT_HEADER: ()=>BFF_OPERATION_CONTEXT_HEADER,
|
|
30
|
+
evaluateCrossProjectPolicy: ()=>evaluateCrossProjectPolicy
|
|
31
|
+
});
|
|
32
|
+
const BFF_ENVELOPE_HEADER = 'x-modernjs-bff-envelope';
|
|
33
|
+
const BFF_OPERATION_CONTEXT_HEADER = 'x-operation-id';
|
|
34
|
+
const BFF_OPERATION_CONTEXT_DETAIL_HEADER = 'x-modernjs-bff-operation-context';
|
|
35
|
+
const DEFAULT_DENY_STATUS = 403;
|
|
36
|
+
const normalizeHeaderName = (headerName, fallback)=>(headerName || fallback).trim().toLowerCase();
|
|
37
|
+
const normalizeStatusCode = (statusCode)=>{
|
|
38
|
+
if ('number' == typeof statusCode && Number.isFinite(statusCode) && statusCode >= 400 && statusCode <= 599) return Math.floor(statusCode);
|
|
39
|
+
return DEFAULT_DENY_STATUS;
|
|
40
|
+
};
|
|
41
|
+
const readHeader = (headers, headerName)=>{
|
|
42
|
+
const lowerHeaderName = headerName.toLowerCase();
|
|
43
|
+
for (const [name, value] of Object.entries(headers || {}))if (name.toLowerCase() === lowerHeaderName) {
|
|
44
|
+
if (Array.isArray(value)) return value.length > 0 ? String(value[0]) : void 0;
|
|
45
|
+
if (null == value) return;
|
|
46
|
+
return String(value);
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
const extractNamespace = (requestId)=>requestId.split(/[/:.]/)[0]?.trim().toLowerCase();
|
|
50
|
+
const createViolation = (reason, message, status)=>({
|
|
51
|
+
code: 'BFF_CROSS_PROJECT_POLICY_DENIED',
|
|
52
|
+
reason,
|
|
53
|
+
message,
|
|
54
|
+
status
|
|
55
|
+
});
|
|
56
|
+
const evaluateCrossProjectPolicy = (headers, policy)=>{
|
|
57
|
+
if (!policy?.enabled) return null;
|
|
58
|
+
const status = normalizeStatusCode(policy.denyStatus);
|
|
59
|
+
const requireEnvelope = policy.requireEnvelope ?? true;
|
|
60
|
+
const requireOperationContext = policy.requireOperationContext ?? true;
|
|
61
|
+
const requireOperationContextDetails = policy.requireOperationContextDetails ?? true;
|
|
62
|
+
const requireOperationSchemaHash = policy.requireOperationSchemaHash ?? true;
|
|
63
|
+
const requireOperationVersion = policy.requireOperationVersion ?? true;
|
|
64
|
+
const allowUnknownOperations = policy.allowUnknownOperations ?? false;
|
|
65
|
+
const envelopeHeader = normalizeHeaderName(policy.envelopeHeader, BFF_ENVELOPE_HEADER);
|
|
66
|
+
const operationContextHeader = normalizeHeaderName(policy.operationContextHeader, BFF_OPERATION_CONTEXT_HEADER);
|
|
67
|
+
const operationContextDetailHeader = normalizeHeaderName(policy.operationContextDetailHeader, BFF_OPERATION_CONTEXT_DETAIL_HEADER);
|
|
68
|
+
const envelopeRaw = readHeader(headers, envelopeHeader);
|
|
69
|
+
if (!envelopeRaw) {
|
|
70
|
+
if (!requireEnvelope) return null;
|
|
71
|
+
return createViolation('missing_envelope', `Missing cross-project envelope header "${envelopeHeader}"`, status);
|
|
72
|
+
}
|
|
73
|
+
let envelope;
|
|
74
|
+
try {
|
|
75
|
+
const parsed = JSON.parse(envelopeRaw);
|
|
76
|
+
if (!parsed || 'object' != typeof parsed) throw new Error('invalid envelope object');
|
|
77
|
+
envelope = parsed;
|
|
78
|
+
} catch (_error) {
|
|
79
|
+
return createViolation('invalid_envelope', `Invalid cross-project envelope header "${envelopeHeader}"`, status);
|
|
80
|
+
}
|
|
81
|
+
const requestId = String(envelope.requestId || '').trim();
|
|
82
|
+
if (!requestId) return createViolation('missing_request_id', 'Cross-project envelope does not include a valid requestId', status);
|
|
83
|
+
const namespaces = (policy.allowedNamespaces || []).map((item)=>item.trim().toLowerCase()).filter(Boolean);
|
|
84
|
+
if (namespaces.length > 0) {
|
|
85
|
+
const namespace = extractNamespace(requestId);
|
|
86
|
+
if (!namespace || !namespaces.includes(namespace)) return createViolation('namespace_not_allowed', `Producer namespace "${namespace || 'unknown'}" is not allowed`, status);
|
|
87
|
+
}
|
|
88
|
+
if (requireOperationContext) {
|
|
89
|
+
const operationContext = readHeader(headers, operationContextHeader);
|
|
90
|
+
if (!operationContext) return createViolation('missing_operation_context', `Missing operation context header "${operationContextHeader}"`, status);
|
|
91
|
+
if (!operationContext.startsWith(`${requestId}:`)) return createViolation('operation_context_mismatch', `Operation context header "${operationContextHeader}" does not match requestId "${requestId}"`, status);
|
|
92
|
+
const operationContextDetailsRaw = readHeader(headers, operationContextDetailHeader);
|
|
93
|
+
if (!operationContextDetailsRaw) {
|
|
94
|
+
if (requireOperationContextDetails) return createViolation('missing_operation_context_details', `Missing operation context details header "${operationContextDetailHeader}"`, status);
|
|
95
|
+
return null;
|
|
96
|
+
}
|
|
97
|
+
let operationContextDetails;
|
|
98
|
+
try {
|
|
99
|
+
const parsed = JSON.parse(operationContextDetailsRaw);
|
|
100
|
+
if (!parsed || 'object' != typeof parsed || Array.isArray(parsed)) throw new Error('invalid operation context details object');
|
|
101
|
+
operationContextDetails = parsed;
|
|
102
|
+
} catch (_error) {
|
|
103
|
+
return createViolation('invalid_operation_context_details', `Invalid operation context details header "${operationContextDetailHeader}"`, status);
|
|
104
|
+
}
|
|
105
|
+
const detailRequestId = String(operationContextDetails.requestId || '').trim();
|
|
106
|
+
if (detailRequestId && detailRequestId !== requestId) return createViolation('operation_context_details_request_id_mismatch', `Operation context details requestId "${detailRequestId}" does not match envelope requestId "${requestId}"`, status);
|
|
107
|
+
const detailSchemaHash = String(operationContextDetails.schemaHash || '').trim();
|
|
108
|
+
if (requireOperationSchemaHash && !detailSchemaHash) return createViolation('missing_operation_schema_hash', `Operation context details header "${operationContextDetailHeader}" must include schemaHash`, status);
|
|
109
|
+
const detailOperationVersion = operationContextDetails.operationVersion;
|
|
110
|
+
if (requireOperationVersion && 'number' != typeof detailOperationVersion) return createViolation('missing_operation_version', `Operation context details header "${operationContextDetailHeader}" must include operationVersion`, status);
|
|
111
|
+
const expectedContracts = policy.expectedOperationContracts;
|
|
112
|
+
if (expectedContracts && 'object' == typeof expectedContracts && Object.keys(expectedContracts).length > 0) {
|
|
113
|
+
const method = String(operationContextDetails.method || '').toUpperCase();
|
|
114
|
+
const routePath = String(operationContextDetails.routePath || '').trim();
|
|
115
|
+
const operationId = String(operationContextDetails.operationId || '').trim();
|
|
116
|
+
const expectedContract = expectedContracts[`${method}:${routePath}`] || expectedContracts[`operation:${operationId}`];
|
|
117
|
+
if (expectedContract) {
|
|
118
|
+
if (expectedContract.schemaHash && detailSchemaHash && expectedContract.schemaHash !== detailSchemaHash) return createViolation('operation_schema_hash_mismatch', `Operation schema hash mismatch for "${operationId || `${method}:${routePath}`}"`, status);
|
|
119
|
+
if ('number' == typeof expectedContract.operationVersion && 'number' == typeof detailOperationVersion && expectedContract.operationVersion !== detailOperationVersion) return createViolation('operation_version_mismatch', `Operation version mismatch for "${operationId || `${method}:${routePath}`}"`, status);
|
|
120
|
+
} else if (!allowUnknownOperations) return createViolation('unknown_operation_contract', `No expected operation contract found for operation "${operationId || `${method}:${routePath}`}"`, status);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
return null;
|
|
124
|
+
};
|
|
125
|
+
exports.BFF_ENVELOPE_HEADER = __webpack_exports__.BFF_ENVELOPE_HEADER;
|
|
126
|
+
exports.BFF_OPERATION_CONTEXT_DETAIL_HEADER = __webpack_exports__.BFF_OPERATION_CONTEXT_DETAIL_HEADER;
|
|
127
|
+
exports.BFF_OPERATION_CONTEXT_HEADER = __webpack_exports__.BFF_OPERATION_CONTEXT_HEADER;
|
|
128
|
+
exports.evaluateCrossProjectPolicy = __webpack_exports__.evaluateCrossProjectPolicy;
|
|
129
|
+
for(var __rspack_i in __webpack_exports__)if (-1 === [
|
|
130
|
+
"BFF_ENVELOPE_HEADER",
|
|
131
|
+
"BFF_OPERATION_CONTEXT_DETAIL_HEADER",
|
|
132
|
+
"BFF_OPERATION_CONTEXT_HEADER",
|
|
133
|
+
"evaluateCrossProjectPolicy"
|
|
134
|
+
].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
|
|
135
|
+
Object.defineProperty(exports, '__esModule', {
|
|
136
|
+
value: true
|
|
137
|
+
});
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __webpack_require__ = {};
|
|
3
|
+
(()=>{
|
|
4
|
+
__webpack_require__.d = (exports1, definition)=>{
|
|
5
|
+
for(var key in definition)if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
|
|
6
|
+
enumerable: true,
|
|
7
|
+
get: definition[key]
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
})();
|
|
11
|
+
(()=>{
|
|
12
|
+
__webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
|
|
13
|
+
})();
|
|
14
|
+
(()=>{
|
|
15
|
+
__webpack_require__.r = (exports1)=>{
|
|
16
|
+
if ("u" > typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
|
|
17
|
+
value: 'Module'
|
|
18
|
+
});
|
|
19
|
+
Object.defineProperty(exports1, '__esModule', {
|
|
20
|
+
value: true
|
|
21
|
+
});
|
|
22
|
+
};
|
|
23
|
+
})();
|
|
24
|
+
var __webpack_exports__ = {};
|
|
25
|
+
__webpack_require__.r(__webpack_exports__);
|
|
26
|
+
__webpack_require__.d(__webpack_exports__, {
|
|
27
|
+
DEFAULT_OPERATION_VERSION: ()=>DEFAULT_OPERATION_VERSION,
|
|
28
|
+
buildOperationContractMap: ()=>buildOperationContractMap,
|
|
29
|
+
createOperationEntries: ()=>createOperationEntries,
|
|
30
|
+
createOperationSchemaHash: ()=>createOperationSchemaHash
|
|
31
|
+
});
|
|
32
|
+
const external_crypto_namespaceObject = require("crypto");
|
|
33
|
+
const DEFAULT_OPERATION_VERSION = 1;
|
|
34
|
+
const createOperationEntries = (handlers)=>handlers.map((item)=>({
|
|
35
|
+
name: item.name,
|
|
36
|
+
httpMethod: String(item.httpMethod || '').toUpperCase(),
|
|
37
|
+
routePath: item.routePath
|
|
38
|
+
})).sort((a, b)=>{
|
|
39
|
+
const keyA = `${a.routePath}:${a.httpMethod}:${a.name}`;
|
|
40
|
+
const keyB = `${b.routePath}:${b.httpMethod}:${b.name}`;
|
|
41
|
+
return keyA.localeCompare(keyB);
|
|
42
|
+
});
|
|
43
|
+
const createOperationSchemaHash = (operationEntries, requestId)=>(0, external_crypto_namespaceObject.createHash)('sha256').update(JSON.stringify({
|
|
44
|
+
operations: operationEntries.map((item)=>({
|
|
45
|
+
name: item.name,
|
|
46
|
+
httpMethod: item.httpMethod,
|
|
47
|
+
routePath: item.routePath
|
|
48
|
+
})),
|
|
49
|
+
requestId
|
|
50
|
+
})).digest('hex');
|
|
51
|
+
const buildOperationContractMap = ({ handlers, requestId })=>{
|
|
52
|
+
const normalizedRequestId = 'string' == typeof requestId && requestId.trim().length > 0 ? requestId.trim() : 'default';
|
|
53
|
+
const byModule = new Map();
|
|
54
|
+
handlers.forEach((item)=>{
|
|
55
|
+
const moduleId = 'string' == typeof item.filename && item.filename.length > 0 ? item.filename : '__anonymous__';
|
|
56
|
+
const group = byModule.get(moduleId) || [];
|
|
57
|
+
group.push({
|
|
58
|
+
name: item.name,
|
|
59
|
+
httpMethod: item.httpMethod.toUpperCase(),
|
|
60
|
+
routePath: item.routePath,
|
|
61
|
+
filename: item.filename
|
|
62
|
+
});
|
|
63
|
+
byModule.set(moduleId, group);
|
|
64
|
+
});
|
|
65
|
+
const contracts = {};
|
|
66
|
+
byModule.forEach((moduleEntries)=>{
|
|
67
|
+
const entries = createOperationEntries(moduleEntries);
|
|
68
|
+
const schemaHash = createOperationSchemaHash(entries, normalizedRequestId);
|
|
69
|
+
const filename = moduleEntries[0]?.filename;
|
|
70
|
+
entries.forEach((entry)=>{
|
|
71
|
+
const operationId = `${normalizedRequestId}:${entry.name}`;
|
|
72
|
+
const contract = {
|
|
73
|
+
requestId: normalizedRequestId,
|
|
74
|
+
operationVersion: DEFAULT_OPERATION_VERSION,
|
|
75
|
+
schemaHash,
|
|
76
|
+
method: entry.httpMethod,
|
|
77
|
+
routePath: entry.routePath,
|
|
78
|
+
operationId,
|
|
79
|
+
handlerName: entry.name,
|
|
80
|
+
filename
|
|
81
|
+
};
|
|
82
|
+
contracts[`${entry.httpMethod}:${entry.routePath}`] = contract;
|
|
83
|
+
contracts[`operation:${operationId}`] = contract;
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
return contracts;
|
|
87
|
+
};
|
|
88
|
+
exports.DEFAULT_OPERATION_VERSION = __webpack_exports__.DEFAULT_OPERATION_VERSION;
|
|
89
|
+
exports.buildOperationContractMap = __webpack_exports__.buildOperationContractMap;
|
|
90
|
+
exports.createOperationEntries = __webpack_exports__.createOperationEntries;
|
|
91
|
+
exports.createOperationSchemaHash = __webpack_exports__.createOperationSchemaHash;
|
|
92
|
+
for(var __rspack_i in __webpack_exports__)if (-1 === [
|
|
93
|
+
"DEFAULT_OPERATION_VERSION",
|
|
94
|
+
"buildOperationContractMap",
|
|
95
|
+
"createOperationEntries",
|
|
96
|
+
"createOperationSchemaHash"
|
|
97
|
+
].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
|
|
98
|
+
Object.defineProperty(exports, '__esModule', {
|
|
99
|
+
value: true
|
|
100
|
+
});
|