@midwayjs/core 4.0.0-beta.11 → 4.0.0-beta.13

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 (44) hide show
  1. package/dist/baseFramework.js +18 -1
  2. package/dist/common/asyncContextManager.js +0 -1
  3. package/dist/common/dataSourceManager.d.ts +1 -1
  4. package/dist/common/fileDetector.d.ts +1 -0
  5. package/dist/common/fileDetector.js +26 -0
  6. package/dist/common/webGenerator.js +3 -1
  7. package/dist/config/config.default.d.ts +2 -2
  8. package/dist/config/config.default.js +6 -1
  9. package/dist/context/componentLoader.js +1 -1
  10. package/dist/context/container.js +7 -0
  11. package/dist/decorator/common/tracer.d.ts +9 -0
  12. package/dist/decorator/common/tracer.js +18 -0
  13. package/dist/decorator/constant.d.ts +1 -0
  14. package/dist/decorator/constant.js +2 -1
  15. package/dist/decorator/index.d.ts +1 -0
  16. package/dist/decorator/index.js +1 -0
  17. package/dist/decorator/metadataManager.js +0 -2
  18. package/dist/decorator/web/requestMapping.d.ts +4 -0
  19. package/dist/decorator/web/requestMapping.js +14 -3
  20. package/dist/error/framework.d.ts +13 -1
  21. package/dist/error/framework.js +3 -1
  22. package/dist/functional/adapter.d.ts +4 -0
  23. package/dist/functional/adapter.js +7 -0
  24. package/dist/functional/api.d.ts +68 -0
  25. package/dist/functional/api.js +262 -0
  26. package/dist/functional/constants.d.ts +3 -0
  27. package/dist/functional/constants.js +6 -0
  28. package/dist/functional/hooks.js +0 -1
  29. package/dist/functional/index.d.ts +3 -0
  30. package/dist/functional/index.js +7 -1
  31. package/dist/index.d.ts +1 -0
  32. package/dist/index.js +3 -1
  33. package/dist/interface.d.ts +29 -3
  34. package/dist/interface.js +1 -1
  35. package/dist/service/configService.js +0 -1
  36. package/dist/service/lifeCycleService.js +3 -1
  37. package/dist/service/traceService.d.ts +49 -0
  38. package/dist/service/traceService.js +306 -0
  39. package/dist/service/webRouterService.d.ts +40 -0
  40. package/dist/service/webRouterService.js +197 -45
  41. package/dist/setup.js +4 -0
  42. package/dist/util/index.d.ts +1 -0
  43. package/dist/util/index.js +78 -2
  44. package/package.json +3 -2
@@ -18,12 +18,14 @@ const pathToRegexp_1 = require("../util/pathToRegexp");
18
18
  const types_1 = require("../util/types");
19
19
  const interface_1 = require("../interface");
20
20
  const metadataManager_1 = require("../decorator/metadataManager");
21
+ const loggerService_1 = require("./loggerService");
21
22
  const debug = util.debuglog('midway:debug');
22
23
  let MidwayWebRouterService = class MidwayWebRouterService {
23
24
  options;
24
25
  isReady = false;
25
26
  routes = new Map();
26
27
  routesPriority = [];
28
+ loggerService;
27
29
  constructor(options = {}) {
28
30
  this.options = options;
29
31
  }
@@ -33,7 +35,40 @@ let MidwayWebRouterService = class MidwayWebRouterService {
33
35
  }
34
36
  analyzeController() {
35
37
  const controllerModules = decorator_1.DecoratorManager.listModule(decorator_1.CONTROLLER_KEY);
38
+ const dedupedControllerModules = [];
39
+ const functionalControllerIndexMap = new Map();
36
40
  for (const module of controllerModules) {
41
+ const isFunctionalController = !!metadataManager_1.MetadataManager.getOwnMetadata(decorator_1.FUNCTIONAL_API_CONTROLLER_KEY, module);
42
+ if (!isFunctionalController) {
43
+ dedupedControllerModules.push(module);
44
+ continue;
45
+ }
46
+ const controllerOption = metadataManager_1.MetadataManager.getOwnMetadata(decorator_1.CONTROLLER_KEY, module);
47
+ const webRouterInfo = metadataManager_1.MetadataManager.getOwnMetadata(decorator_1.WEB_ROUTER_KEY, module);
48
+ if (!controllerOption || !webRouterInfo) {
49
+ dedupedControllerModules.push(module);
50
+ continue;
51
+ }
52
+ // Deduplicate only when controller prefix + route signatures are exactly the same.
53
+ // This keeps "double evaluation of same module" safe while preserving distinct APIs
54
+ // that happen to share class name or route method names.
55
+ const routeSignatures = webRouterInfo
56
+ .map(item => {
57
+ return `${(item.requestMethod || '').toLowerCase()}|${String(item.path || '/')}|${item.routerName || ''}|${item.method || ''}`;
58
+ })
59
+ .sort()
60
+ .join(';');
61
+ const controllerSignature = `${controllerOption.prefix || '/'}::${routeSignatures}`;
62
+ const existingIndex = functionalControllerIndexMap.get(controllerSignature);
63
+ if (typeof existingIndex === 'number') {
64
+ dedupedControllerModules[existingIndex] = module;
65
+ }
66
+ else {
67
+ functionalControllerIndexMap.set(controllerSignature, dedupedControllerModules.length);
68
+ dedupedControllerModules.push(module);
69
+ }
70
+ }
71
+ for (const module of dedupedControllerModules) {
37
72
  const controllerOption = metadataManager_1.MetadataManager.getOwnMetadata(decorator_1.CONTROLLER_KEY, module);
38
73
  this.addController(module, controllerOption, this.options.includeFunctionRouter);
39
74
  }
@@ -72,41 +107,37 @@ let MidwayWebRouterService = class MidwayWebRouterService {
72
107
  debug(`[core]: Found Controller ${controllerId}.`);
73
108
  const id = decorator_1.DecoratorManager.getProviderUUId(controllerClz);
74
109
  controllerOption.routerOptions = controllerOption.routerOptions || {};
75
- let priority;
76
110
  // implement middleware in controller
77
111
  const middleware = controllerOption.routerOptions.middleware;
78
112
  const controllerIgnoreGlobalPrefix = !!controllerOption.routerOptions?.ignoreGlobalPrefix;
79
- let prefix = (0, util_1.joinURLPath)(this.options.globalPrefix, controllerOption.prefix || '/');
80
- const ignorePrefix = controllerOption.prefix || '/';
81
- // if controller set ignore global prefix, all router will be ignore too.
82
- if (controllerIgnoreGlobalPrefix) {
83
- prefix = ignorePrefix;
84
- }
113
+ const controllerVersion = controllerOption.routerOptions?.version;
114
+ const controllerVersionType = controllerVersion
115
+ ? controllerOption.routerOptions?.versionType || 'URI'
116
+ : undefined;
117
+ const controllerVersionPrefix = controllerVersionType === 'URI'
118
+ ? controllerOption.routerOptions?.versionPrefix || 'v'
119
+ : controllerOption.routerOptions?.versionPrefix;
120
+ let prefixWithGlobal = (0, util_1.joinURLPath)(this.options.globalPrefix, controllerOption.prefix || '/');
121
+ const rawIgnorePrefix = controllerOption.prefix || '/';
122
+ let ignorePrefix = rawIgnorePrefix;
85
123
  // Apply version prefix for URI versioning
86
- if (controllerOption.routerOptions?.version &&
87
- (!controllerOption.routerOptions?.versionType ||
88
- controllerOption.routerOptions?.versionType === 'URI')) {
89
- const versionPrefix = controllerOption.routerOptions?.versionPrefix || 'v';
90
- const version = Array.isArray(controllerOption.routerOptions.version)
91
- ? controllerOption.routerOptions.version[0]
92
- : controllerOption.routerOptions.version;
93
- const versionedPrefix = `/${versionPrefix}${version}`;
94
- if (controllerIgnoreGlobalPrefix) {
95
- prefix = (0, util_1.joinURLPath)(versionedPrefix, ignorePrefix);
96
- }
97
- else {
98
- prefix = (0, util_1.joinURLPath)(this.options.globalPrefix, versionedPrefix, controllerOption.prefix || '/');
99
- }
124
+ if (controllerVersion && controllerVersionType === 'URI') {
125
+ const version = Array.isArray(controllerVersion)
126
+ ? controllerVersion[0]
127
+ : controllerVersion;
128
+ const versionedPrefix = `/${controllerVersionPrefix}${version}`;
129
+ prefixWithGlobal = (0, util_1.joinURLPath)(this.options.globalPrefix, versionedPrefix, controllerOption.prefix || '/');
130
+ ignorePrefix = (0, util_1.joinURLPath)(versionedPrefix, rawIgnorePrefix);
100
131
  }
101
- if (/\*/.test(prefix)) {
102
- throw new error_1.MidwayCommonError(`Router prefix ${prefix} can't set string with *`);
132
+ if (/\*/.test(prefixWithGlobal)) {
133
+ throw new error_1.MidwayCommonError(`Router prefix ${prefixWithGlobal} can't set string with *`);
103
134
  }
104
- // set prefix
105
- if (!this.routes.has(prefix)) {
106
- this.routes.set(prefix, []);
135
+ // set prefix with global
136
+ if (!this.routes.has(prefixWithGlobal)) {
137
+ this.routes.set(prefixWithGlobal, []);
107
138
  this.routesPriority.push({
108
- prefix,
109
- priority: prefix === '/' && priority === undefined ? -999 : 0,
139
+ prefix: prefixWithGlobal,
140
+ priority: prefixWithGlobal === '/' ? -999 : 0,
110
141
  middleware,
111
142
  routerOptions: controllerOption.routerOptions,
112
143
  controllerId,
@@ -117,31 +148,43 @@ let MidwayWebRouterService = class MidwayWebRouterService {
117
148
  // 不同的 controller,可能会有相同的 prefix,一旦 options 不同,就要报错
118
149
  if (middleware && middleware.length > 0) {
119
150
  const originRoute = this.routesPriority.filter(el => {
120
- return el.prefix === prefix;
151
+ return el.prefix === prefixWithGlobal;
121
152
  })[0];
122
- throw new error_1.MidwayDuplicateControllerOptionsError(prefix, controllerId, originRoute.controllerId);
153
+ throw new error_1.MidwayDuplicateControllerOptionsError(prefixWithGlobal, controllerId, originRoute.controllerId);
123
154
  }
124
155
  }
125
- // set ignorePrefix
126
- if (!this.routes.has(ignorePrefix)) {
127
- this.routes.set(ignorePrefix, []);
128
- this.routesPriority.push({
129
- prefix: ignorePrefix,
130
- priority: ignorePrefix === '/' && priority === undefined ? -999 : 0,
131
- middleware,
132
- routerOptions: controllerOption.routerOptions,
133
- controllerId,
134
- routerModule: controllerClz,
135
- });
136
- }
137
156
  const webRouterInfo = metadataManager_1.MetadataManager.getOwnMetadata(decorator_1.WEB_ROUTER_KEY, controllerClz);
157
+ const hasRouteIgnoreGlobalPrefix = !!webRouterInfo &&
158
+ webRouterInfo.some(route => route?.ignoreGlobalPrefix === true);
159
+ // set ignorePrefix only when it can be matched
160
+ if (controllerIgnoreGlobalPrefix || hasRouteIgnoreGlobalPrefix) {
161
+ if (!this.routes.has(ignorePrefix)) {
162
+ this.routes.set(ignorePrefix, []);
163
+ this.routesPriority.push({
164
+ prefix: ignorePrefix,
165
+ priority: ignorePrefix === '/' ? -999 : 0,
166
+ middleware,
167
+ routerOptions: controllerOption.routerOptions,
168
+ controllerId,
169
+ routerModule: controllerClz,
170
+ });
171
+ }
172
+ }
138
173
  if (webRouterInfo && typeof webRouterInfo[Symbol.iterator] === 'function') {
139
174
  for (const webRouter of webRouterInfo) {
175
+ const isRouteIgnoreGlobalPrefixConfigured = webRouter.__ignoreGlobalPrefixConfigured === true;
140
176
  const routeArgsInfo = metadataManager_1.MetadataManager.getOwnMetadata(decorator_1.WEB_ROUTER_PARAM_KEY, controllerClz, webRouter.method) || [];
141
177
  const routerResponseData = metadataManager_1.MetadataManager.getOwnMetadata(decorator_1.WEB_RESPONSE_KEY, controllerClz, webRouter.method) || [];
142
178
  const data = {
143
179
  id,
144
- prefix: webRouter.ignoreGlobalPrefix ? ignorePrefix : prefix,
180
+ // route-level value overrides controller default when explicitly set
181
+ prefix: isRouteIgnoreGlobalPrefixConfigured
182
+ ? webRouter.ignoreGlobalPrefix
183
+ ? ignorePrefix
184
+ : prefixWithGlobal
185
+ : controllerIgnoreGlobalPrefix
186
+ ? ignorePrefix
187
+ : prefixWithGlobal,
145
188
  routerName: webRouter.routerName || '',
146
189
  url: webRouter.path,
147
190
  requestMethod: webRouter.requestMethod,
@@ -157,12 +200,30 @@ let MidwayWebRouterService = class MidwayWebRouterService {
157
200
  requestMetadata: routeArgsInfo,
158
201
  responseMetadata: routerResponseData,
159
202
  };
203
+ const isFunctionalController = !!metadataManager_1.MetadataManager.getOwnMetadata(decorator_1.FUNCTIONAL_API_CONTROLLER_KEY, controllerClz);
204
+ if (isFunctionalController) {
205
+ data.source = 'functional';
206
+ }
207
+ if (isRouteIgnoreGlobalPrefixConfigured ||
208
+ controllerIgnoreGlobalPrefix) {
209
+ const resolvedIgnoreGlobalPrefix = isRouteIgnoreGlobalPrefixConfigured
210
+ ? !!webRouter.ignoreGlobalPrefix
211
+ : controllerIgnoreGlobalPrefix;
212
+ if (resolvedIgnoreGlobalPrefix) {
213
+ data.ignoreGlobalPrefix = true;
214
+ }
215
+ }
216
+ if (controllerVersion) {
217
+ data.version = controllerVersion;
218
+ data.versionType = controllerVersionType;
219
+ data.versionPrefix = controllerVersionPrefix;
220
+ }
160
221
  if (functionMeta) {
161
222
  // get function information
162
223
  data.functionName = controllerId + '-' + webRouter.method;
163
224
  data.functionTriggerName = interface_1.ServerlessTriggerType.HTTP;
164
225
  data.functionTriggerMetadata = {
165
- path: (0, util_1.joinURLPath)(prefix, webRouter.path.toString()),
226
+ path: (0, util_1.joinURLPath)(data.prefix, webRouter.path.toString()),
166
227
  method: webRouter.requestMethod,
167
228
  };
168
229
  data.functionMetadata = {
@@ -315,6 +376,29 @@ let MidwayWebRouterService = class MidwayWebRouterService {
315
376
  }
316
377
  return matchedRouterInfo;
317
378
  }
379
+ async getRouteManifest() {
380
+ const routes = await this.getFlattenRouterTable();
381
+ const manifest = routes.map(route => ({
382
+ source: route.source ?? 'decorator',
383
+ operationId: this.getOperationId(route),
384
+ controllerId: route.controllerId,
385
+ controllerPrefix: route.prefix || '',
386
+ method: route.requestMethod,
387
+ path: route.url?.toString() || '',
388
+ fullPath: route.fullUrl || '',
389
+ routerName: route.routerName,
390
+ middlewareCount: (route.middleware?.length || 0) +
391
+ (route.controllerMiddleware?.length || 0),
392
+ ignoreGlobalPrefix: !!route.ignoreGlobalPrefix,
393
+ version: route.version,
394
+ versionType: route.versionType,
395
+ versionPrefix: route.versionPrefix,
396
+ summary: route.summary,
397
+ description: route.description,
398
+ }));
399
+ this.checkDuplicateOperationId(manifest);
400
+ return manifest;
401
+ }
318
402
  checkDuplicateAndPush(prefix, routerInfo) {
319
403
  const prefixList = this.routes.get(prefix);
320
404
  const matched = prefixList.filter(item => {
@@ -324,7 +408,25 @@ let MidwayWebRouterService = class MidwayWebRouterService {
324
408
  item.requestMethod === routerInfo.requestMethod);
325
409
  });
326
410
  if (matched && matched.length) {
327
- throw new error_1.MidwayDuplicateRouteError(`${routerInfo.requestMethod} ${routerInfo.url}`, `${matched[0].handlerName}`, `${routerInfo.handlerName}`);
411
+ const existingRoute = matched[0];
412
+ const fullPath = existingRoute.fullUrl ||
413
+ (typeof routerInfo.url === 'string'
414
+ ? (0, util_1.joinURLPath)(prefix, routerInfo.url)
415
+ : `${prefix}${routerInfo.url?.toString() || ''}`);
416
+ const payload = {
417
+ code: 'MIDWAY_DUPLICATE_ROUTE',
418
+ method: (routerInfo.requestMethod || '').toUpperCase(),
419
+ fullPath,
420
+ existing: {
421
+ source: existingRoute.source ?? 'decorator',
422
+ handler: this.getRouterHandlerIdentity(existingRoute),
423
+ },
424
+ current: {
425
+ source: routerInfo.source ?? 'decorator',
426
+ handler: this.getRouterHandlerIdentity(routerInfo),
427
+ },
428
+ };
429
+ throw new error_1.MidwayDuplicateRouteError(`${routerInfo.requestMethod} ${routerInfo.url}`, payload.existing.handler, payload.current.handler, payload);
328
430
  }
329
431
  // format url
330
432
  if (!routerInfo.fullUrlFlattenString &&
@@ -339,9 +441,59 @@ let MidwayWebRouterService = class MidwayWebRouterService {
339
441
  }
340
442
  }
341
443
  prefixList.push(routerInfo);
444
+ this.logRouteLoaded(routerInfo);
445
+ }
446
+ logRouteLoaded(routerInfo) {
447
+ const fullPath = routerInfo.fullUrl ||
448
+ (typeof routerInfo.url === 'string'
449
+ ? (0, util_1.joinURLPath)(routerInfo.prefix || '', routerInfo.url)
450
+ : `${routerInfo.prefix || ''}${routerInfo.url?.toString() || ''}`);
451
+ const logger = this.loggerService?.getLogger('appLogger');
452
+ if (!logger || typeof logger.info !== 'function') {
453
+ return;
454
+ }
455
+ logger.info('[midway:router] loaded route %s %s -> %s (%s)', (routerInfo.requestMethod || 'ALL').toUpperCase(), fullPath, this.getRouterHandlerIdentity(routerInfo), routerInfo.source ?? 'decorator');
456
+ }
457
+ getRouterHandlerIdentity(routerInfo) {
458
+ if (routerInfo.handlerName) {
459
+ return routerInfo.handlerName;
460
+ }
461
+ if (typeof routerInfo.method === 'string') {
462
+ return routerInfo.controllerId
463
+ ? `${routerInfo.controllerId}.${routerInfo.method}`
464
+ : routerInfo.method;
465
+ }
466
+ if (typeof routerInfo.method === 'function') {
467
+ return routerInfo.method.name || 'anonymous';
468
+ }
469
+ return 'unknown';
470
+ }
471
+ getOperationId(routeInfo) {
472
+ if (routeInfo.routerName) {
473
+ return routeInfo.routerName;
474
+ }
475
+ const fullPath = routeInfo.fullUrl || routeInfo.url?.toString() || '/';
476
+ return `${(routeInfo.requestMethod || 'all').toLowerCase()}_${fullPath
477
+ .toLowerCase()
478
+ .replace(/[^a-z0-9]+/g, '_')
479
+ .replace(/^_+|_+$/g, '')}`;
480
+ }
481
+ checkDuplicateOperationId(manifest) {
482
+ const operationMap = new Map();
483
+ for (const route of manifest) {
484
+ const exist = operationMap.get(route.operationId);
485
+ if (exist) {
486
+ throw new error_1.MidwayCommonError(`Duplicate operationId "${route.operationId}" between "${exist.method.toUpperCase()} ${exist.fullPath}" and "${route.method.toUpperCase()} ${route.fullPath}"`);
487
+ }
488
+ operationMap.set(route.operationId, route);
489
+ }
342
490
  }
343
491
  };
344
492
  exports.MidwayWebRouterService = MidwayWebRouterService;
493
+ __decorate([
494
+ (0, decorator_1.Inject)(),
495
+ __metadata("design:type", loggerService_1.MidwayLoggerService)
496
+ ], MidwayWebRouterService.prototype, "loggerService", void 0);
345
497
  exports.MidwayWebRouterService = MidwayWebRouterService = __decorate([
346
498
  (0, decorator_1.Provide)(),
347
499
  (0, decorator_1.Scope)(interface_1.ScopeEnum.Singleton),
package/dist/setup.js CHANGED
@@ -9,6 +9,7 @@ const config_default_1 = require("./config/config.default");
9
9
  const util = require("util");
10
10
  const slsFunctionService_1 = require("./service/slsFunctionService");
11
11
  const healthService_1 = require("./service/healthService");
12
+ const traceService_1 = require("./service/traceService");
12
13
  const componentLoader_1 = require("./context/componentLoader");
13
14
  const util_1 = require("./util");
14
15
  const asyncContextManager_1 = require("./common/asyncContextManager");
@@ -48,6 +49,8 @@ async function initializeGlobalApplicationContext(globalOptions) {
48
49
  applicationContext,
49
50
  globalOptions,
50
51
  ]);
52
+ printStepDebugInfo('Init tracing');
53
+ await applicationContext.getAsync(traceService_1.MidwayTraceService);
51
54
  performanceManager_1.MidwayInitializerPerformanceManager.markEnd(performanceManager_1.MidwayInitializerPerformanceManager.MEASURE_KEYS.FRAMEWORK_PREPARE);
52
55
  printStepDebugInfo('Init lifecycle');
53
56
  performanceManager_1.MidwayInitializerPerformanceManager.markStart(performanceManager_1.MidwayInitializerPerformanceManager.MEASURE_KEYS.LIFECYCLE_PREPARE);
@@ -141,6 +144,7 @@ async function prepareGlobalApplicationContextAsync(globalOptions) {
141
144
  applicationContext.bindClass(slsFunctionService_1.MidwayServerlessFunctionService);
142
145
  applicationContext.bindClass(healthService_1.MidwayHealthService);
143
146
  applicationContext.bindClass(_1.MidwayPriorityManager);
147
+ applicationContext.bindClass(traceService_1.MidwayTraceService);
144
148
  printStepDebugInfo('Init MidwayConfigService, MidwayAspectService and MidwayDecoratorService');
145
149
  // init default environment
146
150
  const environmentService = applicationContext.get(_1.MidwayEnvironmentService);
@@ -29,6 +29,7 @@ export declare const loadModule: (p: string, options?: {
29
29
  safeLoad?: boolean;
30
30
  warnOnLoadError?: boolean;
31
31
  extraModuleRoot?: string[];
32
+ importQuery?: string;
32
33
  }) => Promise<any>;
33
34
  /**
34
35
  * load module sync, and it must be commonjs mode
@@ -38,6 +38,79 @@ const pathFileUtil_1 = require("./pathFileUtil");
38
38
  const metadataManager_1 = require("../decorator/metadataManager");
39
39
  const decorator_1 = require("../decorator");
40
40
  const debug = (0, util_1.debuglog)('midway:debug');
41
+ function resolveRelativeEsmSpecifierFallback(importerFile, specifier) {
42
+ if (!specifier ||
43
+ (!specifier.startsWith('./') && !specifier.startsWith('../'))) {
44
+ return undefined;
45
+ }
46
+ const absolute = (0, path_1.resolve)((0, path_1.dirname)(importerFile), specifier);
47
+ const candidates = [];
48
+ if (/\.(mjs|cjs|js)$/i.test(specifier)) {
49
+ candidates.push(absolute.replace(/\.(mjs|cjs|js)$/i, '.mts'), absolute.replace(/\.(mjs|cjs|js)$/i, '.cts'), absolute.replace(/\.(mjs|cjs|js)$/i, '.ts'), absolute.replace(/\.(mjs|cjs|js)$/i, '.tsx'));
50
+ }
51
+ else if (!/\.[a-z0-9]+$/i.test(specifier)) {
52
+ candidates.push(`${absolute}.mts`, `${absolute}.cts`, `${absolute}.ts`, `${absolute}.tsx`, (0, path_1.join)(absolute, 'index.mts'), (0, path_1.join)(absolute, 'index.cts'), (0, path_1.join)(absolute, 'index.ts'), (0, path_1.join)(absolute, 'index.tsx'));
53
+ }
54
+ for (const item of candidates) {
55
+ if ((0, fs_1.existsSync)(item)) {
56
+ const normalized = item.split(path_1.sep).join('/');
57
+ const baseDir = (0, path_1.dirname)(importerFile).split(path_1.sep).join('/');
58
+ if (normalized.startsWith(baseDir + '/')) {
59
+ return './' + normalized.slice(baseDir.length + 1);
60
+ }
61
+ return specifier;
62
+ }
63
+ }
64
+ return undefined;
65
+ }
66
+ function rewriteEsmSourceWithSpecifierFallback(importerFile, source) {
67
+ let changed = false;
68
+ const rewriteByPattern = (pattern, input) => {
69
+ return input.replace(pattern, (full, head, spec, tail) => {
70
+ const fallback = resolveRelativeEsmSpecifierFallback(importerFile, spec);
71
+ if (!fallback || fallback === spec) {
72
+ return full;
73
+ }
74
+ changed = true;
75
+ return `${head}${fallback}${tail}`;
76
+ });
77
+ };
78
+ let output = source;
79
+ output = rewriteByPattern(/(from\s+['"])([^'"]+)(['"])/g, output);
80
+ output = rewriteByPattern(/(import\s*\(\s*['"])([^'"]+)(['"]\s*\))/g, output);
81
+ return changed ? output : source;
82
+ }
83
+ async function importWithSpecifierFallback(p, fileUrl, importQuery) {
84
+ try {
85
+ return await import(fileUrl.href);
86
+ }
87
+ catch (originErr) {
88
+ const source = (0, fs_1.readFileSync)(p, { encoding: 'utf-8' });
89
+ const rewritten = rewriteEsmSourceWithSpecifierFallback(p, source);
90
+ if (rewritten === source) {
91
+ throw originErr;
92
+ }
93
+ const tmpFile = `${p}.mw-esm-fallback-${Date.now()}-${Math.random()
94
+ .toString(36)
95
+ .slice(2)}.ts`;
96
+ (0, fs_1.writeFileSync)(tmpFile, rewritten, { encoding: 'utf-8' });
97
+ try {
98
+ const tmpUrl = (0, url_1.pathToFileURL)(tmpFile);
99
+ if (importQuery) {
100
+ tmpUrl.searchParams.set('mwImportQuery', importQuery);
101
+ }
102
+ return await import(tmpUrl.href);
103
+ }
104
+ finally {
105
+ try {
106
+ (0, fs_1.unlinkSync)(tmpFile);
107
+ }
108
+ catch {
109
+ // ignore cleanup failure
110
+ }
111
+ }
112
+ }
113
+ }
41
114
  /**
42
115
  * @since 2.0.0
43
116
  * @param env
@@ -121,7 +194,11 @@ const loadModule = async (p, options = {}) => {
121
194
  return (await import(p, { with: { type: 'json' } })).default;
122
195
  }
123
196
  else {
124
- return await import((0, url_1.pathToFileURL)(p).href);
197
+ const fileUrl = (0, url_1.pathToFileURL)(p);
198
+ if (options.importQuery) {
199
+ fileUrl.searchParams.set('mwImportQuery', options.importQuery);
200
+ }
201
+ return await importWithSpecifierFallback(p, fileUrl, options.importQuery);
125
202
  }
126
203
  }
127
204
  }
@@ -540,7 +617,6 @@ function isTypeScriptEnvironment() {
540
617
  if ('false' === TS_MODE_PROCESS_FLAG) {
541
618
  return false;
542
619
  }
543
- // eslint-disable-next-line node/no-deprecated-api
544
620
  return TS_MODE_PROCESS_FLAG === 'true' || !!require.extensions['.ts'];
545
621
  }
546
622
  function getFileNameWithSuffix(fileName) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@midwayjs/core",
3
- "version": "4.0.0-beta.11",
3
+ "version": "4.0.0-beta.13",
4
4
  "description": "midway core",
5
5
  "main": "dist/index.js",
6
6
  "typings": "dist/index.d.ts",
@@ -31,6 +31,7 @@
31
31
  },
32
32
  "dependencies": {
33
33
  "@midwayjs/glob": "^1.0.2",
34
+ "@opentelemetry/api": "1.9.0",
34
35
  "picomatch": "2.3.1",
35
36
  "reflect-metadata": "0.2.2"
36
37
  },
@@ -61,5 +62,5 @@
61
62
  "types": "./dist/functional/index.d.ts"
62
63
  }
63
64
  },
64
- "gitHead": "6ef05719ca6e900f1ec34aff7a5c5a9614358c50"
65
+ "gitHead": "9a38b66a84a6880370cac90d737f94f9c5f2f256"
65
66
  }