Skip to content

Commit

Permalink
refactor: add more case for esm and fix load module when file is json
Browse files Browse the repository at this point in the history
  • Loading branch information
czy88840616 committed Jul 29, 2023
1 parent 920e472 commit f02c734
Show file tree
Hide file tree
Showing 25 changed files with 274 additions and 96 deletions.
13 changes: 12 additions & 1 deletion packages/bootstrap/src/bootstrap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,12 @@ import {
MidwayApplicationManager,
initializeGlobalApplicationContext,
destroyGlobalApplicationContext,
loadModule,
isTypeScriptEnvironment,
} from '@midwayjs/core';
import { join } from 'path';
import { IMidwayLogger, MidwayBaseLogger } from '@midwayjs/logger';
import { createContextManager } from '@midwayjs/async-hooks-context-manager';
import { isTypeScriptEnvironment } from './util';
import {
ChildProcessEventBus,
ThreadEventBus,
Expand Down Expand Up @@ -46,6 +47,16 @@ export class BootstrapStarter {
}
}

if (!this.globalOptions.fileLoadMode) {
const pkgJSON = await loadModule(join(this.appDir, 'package.json'), {
safeLoad: true,
enableCache: false,
});

this.globalOptions.fileLoadMode =
pkgJSON?.type === 'module' ? 'esm' : 'commonjs';
}

this.applicationContext = await initializeGlobalApplicationContext({
asyncContextManager: createContextManager(),
...this.globalOptions,
Expand Down
1 change: 0 additions & 1 deletion packages/bootstrap/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
export * from './interface';
export { isTypeScriptEnvironment } from './util';
export { Bootstrap, BootstrapStarter } from './bootstrap';
export { ClusterManager } from './manager/cp';
export { AbstractForkManager } from './manager/base';
Expand Down
2 changes: 1 addition & 1 deletion packages/bootstrap/src/manager/cp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { ClusterOptions } from '../interface';
import { AbstractForkManager } from './base';
const cluster = require('cluster');
import { debuglog } from 'util';
import { isTypeScriptEnvironment } from '../util';
import { isTypeScriptEnvironment } from '@midwayjs/core';

const debug = debuglog('midway:bootstrap');

Expand Down
2 changes: 1 addition & 1 deletion packages/bootstrap/src/manager/thread.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { ThreadOptions } from '../interface';
import { AbstractForkManager } from './base';
import { Worker, isMainThread, SHARE_ENV } from 'worker_threads';
import { ThreadEventBus } from '@midwayjs/event-bus';
import { isTypeScriptEnvironment } from '../util';
import { isTypeScriptEnvironment } from '@midwayjs/core';

export class ThreadManager extends AbstractForkManager<Worker, ThreadOptions> {
private workerExitListener;
Expand Down
9 changes: 0 additions & 9 deletions packages/bootstrap/src/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,3 @@ export async function sleep(timeout) {
setTimeout(resolve, timeout);
});
}

export function isTypeScriptEnvironment() {
const TS_MODE_PROCESS_FLAG: string = process.env.MIDWAY_TS_MODE;
if ('false' === TS_MODE_PROCESS_FLAG) {
return false;
}
// eslint-disable-next-line node/no-deprecated-api
return TS_MODE_PROCESS_FLAG === 'true' || !!require.extensions['.ts'];
}
2 changes: 1 addition & 1 deletion packages/core/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@midwayjs/core",
"version": "3.11.12",
"version": "3.12.0-beta.1",
"description": "midway core",
"main": "dist/index",
"typings": "dist/index.d.ts",
Expand Down
5 changes: 4 additions & 1 deletion packages/core/src/common/fileDetector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { run } from '@midwayjs/glob';
import { MidwayDuplicateClassNameError } from '../error';
import { DEFAULT_PATTERN, IGNORE_PATTERN } from '../constants';
import { getProviderName } from '../decorator';
import { loadModule } from '../util';

export abstract class AbstractFileDetector<T> implements IFileDetector {
options: T;
Expand Down Expand Up @@ -157,7 +158,9 @@ export class CommonJSFileDetector extends AbstractFileDetector<{
};

for (const file of fileResults) {
const exports = await import(file);
const exports = await loadModule(file, {
loadMode: 'esm',
});
// add module to set
container.bindClass(exports, {
namespace: this.options.namespace,
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ export {
pathMatching,
wrapMiddleware,
wrapAsync,
isTypeScriptEnvironment,
} from './util/';
export { extend } from './util/extend';
export * from './util/webRouterParam';
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1020,6 +1020,7 @@ export interface IMidwayBootstrapOptions {
*/
configurationModule?: any | any[];
imports?: any | any[];
fileLoadType?: 'esm' | 'commonjs';
moduleDetector?: IFileDetector | false;
logger?: boolean | ILogger;
/**
Expand Down
9 changes: 6 additions & 3 deletions packages/core/src/service/informationService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {
getCurrentEnvironment,
getUserHome,
isDevelopmentEnvironment,
safeRequire,
loadModule,
} from '../util';
import { dirname, join } from 'path';
import { Provide, Inject, Init, Scope } from '../decorator';
Expand All @@ -20,12 +20,15 @@ export class MidwayInformationService implements IInformationService {
protected baseDir: string;

@Init()
protected init() {
protected async init() {
if (this.baseDir) {
if (!this.appDir) {
this.appDir = dirname(this.baseDir);
}
this.pkg = safeRequire(join(this.appDir, 'package.json')) || {};
this.pkg =
(await loadModule(join(this.appDir, 'package.json'), {
safeLoad: true,
})) || {};
} else {
this.pkg = {};
}
Expand Down
32 changes: 19 additions & 13 deletions packages/core/src/setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,11 @@ import {
MidwayApplicationManager,
MidwayMockService,
MidwayWebRouterService,
loadModule,
ESModuleFileDetector,
CommonJSFileDetector,
loadModule,
safeRequire,
isTypeScriptEnvironment,
} from './';
import defaultConfig from './config/config.default';
import {
Expand Down Expand Up @@ -144,33 +145,38 @@ export async function prepareGlobalApplicationContext(

debug('[core]: set default file detector');

if (!globalOptions.fileLoadType) {
globalOptions.fileLoadType = 'commonjs';
}

// set module detector
if (globalOptions.moduleDetector !== false) {
const pkgJSON = await loadModule(join(appDir, 'package.json'), {
safeLoad: true,
enableCache: false,
});

const loadMode = pkgJSON?.type === 'module' ? 'esm' : 'commonjs';
debug('[core]: module load mode = %s', loadMode);
debug('[core]: set file load mode = %s', globalOptions.fileLoadType);

// set default entry file
if (!globalOptions.imports) {
globalOptions.imports = [
await loadModule(join(baseDir, 'configuration'), {
loadMode,
safeLoad: true,
}),
await loadModule(
join(
baseDir,
`configuration${isTypeScriptEnvironment() ? '.ts' : '.js'}`
),
{
loadMode: globalOptions.fileLoadType,
safeLoad: true,
}
),
];
}
if (globalOptions.moduleDetector === undefined) {
if (loadMode === 'esm') {
if (globalOptions.fileLoadType === 'esm') {
applicationContext.setFileDetector(
new ESModuleFileDetector({
loadDir: baseDir,
ignore: globalOptions.ignore ?? [],
})
);
globalOptions.fileLoadType = 'esm';
} else {
applicationContext.setFileDetector(
new CommonJSFileDetector({
Expand Down
19 changes: 18 additions & 1 deletion packages/core/src/util/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,14 @@ export const loadModule = async (
if (options.loadMode === 'commonjs') {
return require(p);
} else {
return await import(p);
// if json file, import need add options
if (p.endsWith('.json')) {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
return (await import(p, { assert: { type: 'json' } })).default;
} else {
return await import(p);
}
}
} else {
const content = readFileSync(p, {
Expand Down Expand Up @@ -504,6 +511,15 @@ export function toAsyncFunction<T extends (...args) => any>(
}
}

export function isTypeScriptEnvironment() {
const TS_MODE_PROCESS_FLAG: string = process.env.MIDWAY_TS_MODE;
if ('false' === TS_MODE_PROCESS_FLAG) {
return false;
}
// eslint-disable-next-line node/no-deprecated-api
return TS_MODE_PROCESS_FLAG === 'true' || !!require.extensions['.ts'];
}

export const Utils = {
sleep,
getParamNames,
Expand All @@ -514,4 +530,5 @@ export const Utils = {
toAsyncFunction,
safeStringify,
safeParse,
isTypeScriptEnvironment,
};
8 changes: 8 additions & 0 deletions packages/core/test/util/esm-fixtures/clz-default.mts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
class User {}

class UserService {}

export default {
User,
UserService,
}
3 changes: 3 additions & 0 deletions packages/core/test/util/esm-fixtures/clz.mts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export class User {}

export class UserService {}
3 changes: 3 additions & 0 deletions packages/core/test/util/esm-fixtures/data.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"test": 1
}
21 changes: 21 additions & 0 deletions packages/core/test/util/esm-fixtures/esm.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { createRequire } from 'module';
import assert from 'assert';

// console.log(import.meta.url);
const require = createRequire(import.meta.url);
// 这里要用 dist,因为 esm 会找最近的 pkg,而 src 目录最近的 pkg 是 commonjs,会报错
const { loadModule } = require('../../../dist/');

// console.log(url);
const clzDefault = await loadModule(new URL('./clz-default.mts', import.meta.url).pathname, { loadMode: 'esm' });
assert(clzDefault.default.User.name === 'User');

const clz = await loadModule(new URL('./clz.mts', import.meta.url).pathname, { loadMode: 'esm' });
assert(clz.User.name === 'User');

const data = await loadModule(new URL('./data.json', import.meta.url).pathname, { loadMode: 'esm'});
assert(data.test === 1);

const dataNoCache = await loadModule(new URL('./data.json', import.meta.url).pathname, { loadMode: 'esm', enableCache: false});
assert(dataNoCache.test === 1);
process.send('ready');
15 changes: 15 additions & 0 deletions packages/core/test/util/esm-fixtures/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"compilerOptions": {
"target": "ESNext",
"module": "ESNext",
"moduleResolution": "NodeNext",
"baseUrl": "./",
"esModuleInterop": true
},
"include": [
"*.mts",
],
"ts-node": {
"esm": true,
}
}
35 changes: 34 additions & 1 deletion packages/core/test/util/util.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,12 @@ import {
delegateTargetProperties,
transformRequestObjectByType,
isIncludeProperty,
delegateTargetAllPrototypeMethod
delegateTargetAllPrototypeMethod,
loadModule, sleep
} from '../../src/util';
import { PathFileUtil } from '../../src';
import * as EventEmitter from 'events';
import { fork } from 'child_process';

describe('/test/util/util.test.ts', () => {

Expand All @@ -26,6 +28,37 @@ describe('/test/util/util.test.ts', () => {
assert.strictEqual(safeRequire('../fixtures/dir/bbb/nok.js'), undefined);
});

it('should test loadModule', async () => {
expect(await loadModule(join(__dirname, '../fixtures/dir/nok.js'), {safeLoad: true})).toBeUndefined();
expect(await loadModule('../fixtures/dir/bbb/nok.js', {safeLoad: true})).toBeUndefined();
});

it('should test load modle with esm', async () => {
let child = fork('esm.mjs', [], {
cwd: join(__dirname, './esm-fixtures'),
execArgv: [
'--loader',
'ts-node/esm',
]
});

child.on('close', (code) => {
if (code !== 0) {
console.log(`process exited with code ${code}`);
}
});

await new Promise<void>((resolve, reject) => {
child.on('message', (ready) => {
if (ready === 'ready') {
resolve();
}
});
});

await sleep(1000);
});

it('should safeGet be ok', () => {
const fn = safelyGet(['a', 'b']);
assert.deepEqual(2, fn({a: {b: 2}}), 'safelyGet one argument not ok');
Expand Down
10 changes: 1 addition & 9 deletions packages/faas/src/starter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,7 @@ import {
} from '@midwayjs/core';
import { MidwayFaaSFramework } from './framework';
import { join } from 'path';

function isTypeScriptEnvironment() {
const TS_MODE_PROCESS_FLAG: string = process.env.MIDWAY_TS_MODE;
if ('false' === TS_MODE_PROCESS_FLAG) {
return false;
}
// eslint-disable-next-line node/no-deprecated-api
return TS_MODE_PROCESS_FLAG === 'true' || !!require.extensions['.ts'];
}
import { isTypeScriptEnvironment } from '@midwayjs/core';

export abstract class AbstractBootstrapStarter {
protected applicationContext;
Expand Down
Loading

0 comments on commit f02c734

Please sign in to comment.