egg-ts-helper
Version:
egg typescript helper
152 lines (136 loc) • 4.71 kB
text/typescript
/**
* Getting plugin info in child_process to prevent effecting egg application( splitting scopes ).
*/
import fs from 'node:fs';
import path from 'node:path';
import { execFileSync } from 'node:child_process';
import { pathToFileURL } from 'node:url';
import { eggInfoPath } from '../config';
import * as utils from '../utils';
const cwd = process.cwd();
const eggInfo: utils.EggInfoResult = {};
const startTime = Date.now();
if (utils.checkMaybeIsTsProj(cwd)) {
// only require ts-node in ts project
const tsconfigPath = path.resolve(cwd, './tsconfig.json');
if (fs.existsSync(tsconfigPath)) {
require('ts-node').register(utils.readJson5(tsconfigPath));
} else {
require('ts-node/register');
}
}
async function main() {
const pkg = utils.getPkgInfo(cwd);
// try to read postinstall script env.ETS_SCRIPT_FRAMEWORK, let egg-bin can auto set the default framework
const framework = (pkg.egg || {}).framework || process.env.ETS_SCRIPT_FRAMEWORK || 'egg';
if (pkg.type === 'module') {
const saveEggInfoPath = path.join(__dirname, '../../save_egg_info.mjs');
console.warn('[egg-ts-helper] use esm script to save egg info, %o', saveEggInfoPath);
const frameworkPath = getFrameworkPath(cwd, framework);
const esmLoader = pathToFileURL(require.resolve('ts-node/esm')).href;
execFileSync(process.execPath, [ '--no-warnings', '--loader', esmLoader, saveEggInfoPath, cwd, frameworkPath, eggInfoPath ], {
env: {
...process.env,
EGG_TS_ENABLE: 'true',
VITEST: 'true',
},
});
return;
}
const loader = getLoader(cwd, framework);
if (loader) {
try {
await loader.loadPlugin();
} catch (e) {
console.warn('[egg-ts-helper] WARN loader.loadPlugin() error: %s, cwd: %s, framework: %s',
e, cwd, framework);
// do nothing
}
// hack loadFile, ignore config file without customLoader for faster booting
mockFn(loader, 'loadFile', (filepath: string) => {
if (filepath && filepath.substring(filepath.lastIndexOf(path.sep) + 1).startsWith('config.')) {
const fileContent = fs.readFileSync(filepath, 'utf-8');
if (!fileContent.includes('customLoader')) return;
}
return true;
});
try {
await loader.loadConfig();
} catch (e) {
console.warn('[egg-ts-helper] WARN loader.loadConfig() error: %s, cwd: %s, framework: %s',
e, cwd, framework);
// do nothing
}
eggInfo.plugins = loader.allPlugins;
eggInfo.config = loader.config;
eggInfo.eggPaths = loader.eggPaths;
eggInfo.timing = Date.now() - startTime;
}
utils.writeFileSync(eggInfoPath, JSON.stringify(eggInfo));
}
/* istanbul ignore next */
function noop() {}
function mockFn(obj, name, fn) {
const oldFn = obj[name];
obj[name] = (...args) => {
const result = fn.apply(obj, args);
if (result) return oldFn.apply(obj, args);
};
}
function getFrameworkPath(baseDir: string, framework: string) {
let frameworkPath = '';
try {
frameworkPath = require.resolve(`${framework}/package.json`, { paths: [ baseDir ] });
frameworkPath = path.dirname(frameworkPath);
} catch {
// ignore error
}
if (!frameworkPath) {
frameworkPath = path.join(baseDir, 'node_modules', framework);
}
return frameworkPath;
}
function getLoader(baseDir: string, framework: string) {
const frameworkPath = getFrameworkPath(baseDir, framework);
const eggCore = findEggCore(baseDir, frameworkPath);
if (!eggCore) {
console.warn('[egg-ts-helper] WARN cannot find @eggjs/core from frameworkPath: %s', frameworkPath);
return;
}
const EggLoader = eggCore.EggLoader;
const egg = utils.requireFile(frameworkPath) || utils.requireFile(framework);
if (!egg || !egg.Application || !EggLoader) return;
process.env.EGG_SERVER_ENV = 'local';
return new EggLoader({
baseDir,
logger: {
debug: noop,
info: noop,
warn: noop,
error: noop,
},
app: Object.create(egg.Application.prototype),
});
}
function findEggCore(baseDir: string, frameworkPath: string, eggCorePkgName = '@eggjs/core') {
let eggCorePath = '';
try {
eggCorePath = require.resolve(eggCorePkgName, { paths: [ frameworkPath ] });
} catch {
// ignore error
}
if (!eggCorePath) {
eggCorePath = path.join(baseDir, 'node_modules', eggCorePkgName);
if (!fs.existsSync(eggCorePath)) {
eggCorePath = path.join(frameworkPath, 'node_modules', eggCorePkgName);
}
}
// try to load egg-core in cwd
const eggCore = utils.requireFile(eggCorePath);
if (!eggCore) {
// try to resolve egg-core
return utils.requireFile(eggCorePkgName);
}
return eggCore;
}
main();