tsdk
Version:
Type-safe API development and code share tool for TypeScript projects.
213 lines (211 loc) • 12.5 kB
JavaScript
;
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __rest = (this && this.__rest) || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.webpackBuild = exports.tsdkConfigFilePath = void 0;
const child_process_1 = require("child_process");
const fs_extra_1 = __importDefault(require("fs-extra"));
const path_1 = __importDefault(require("path"));
const typescript_1 = __importDefault(require("typescript"));
const webpack_1 = __importDefault(require("webpack"));
const webpack_node_externals_1 = __importDefault(require("webpack-node-externals"));
const get_pkg_manager_1 = require("./get-pkg-manager");
exports.tsdkConfigFilePath = path_1.default.join(process.cwd(), 'tsdk.config.js');
const defaultMainName = 'default';
const distProjects = 'dist-projects';
// npx tsdk --nest build
// npx tsdk --nest build [name] [name]
// npx tsdk --nest build all
function run() {
return __awaiter(this, void 0, void 0, function* () {
const idx = process.argv.findIndex((i) => i === '--names');
const command = process.argv[idx - 1];
const _names = process.argv.filter((item, index) => index > idx);
const { projects } = yield getNestProjectsConfig();
const names = _names.find((i) => i === 'all') ? Object.keys(projects) : _names;
if (names.length === 0) {
names.push(defaultMainName);
}
const cwd = process.cwd();
if (command === 'build') {
const tsconfig = typescript_1.default.readConfigFile(path_1.default.resolve(cwd, 'tsconfig.json'), typescript_1.default.sys.readFile).config;
const outDir = path_1.default.normalize(tsconfig.compilerOptions.outDir);
const include = tsconfig.include || [];
const sourceMap = tsconfig.compilerOptions.sourceMap;
// remove dist folder before build
yield Promise.all([
fs_extra_1.default.remove(path_1.default.resolve(cwd, distProjects)),
fs_extra_1.default.remove(path_1.default.resolve(cwd, outDir)),
]);
console.log(`\n[${command}]: ${names.join(', ')}`);
yield copyProdPackageJSON(path_1.default.resolve(cwd, distProjects), undefined, 'default-root');
const npmCMDs = (0, get_pkg_manager_1.getNpmCommand)(cwd);
yield Promise.all(names.map((name) => {
if (!projects[name]) {
const msg = `\`${name}\` not exists in \`nest-cli.json\``;
console.warn(msg);
throw new Error(msg);
}
return new Promise((resolve, reject) => {
setTimeout(() => __awaiter(this, void 0, void 0, function* () {
console.log(`\n[${command} ${name}] Run: \`${npmCMDs.runCmd} nest ${command} ${name}\`\n`);
try {
(0, child_process_1.execSync)(`${npmCMDs.runCmd} nest ${command} ${name}`, { stdio: 'inherit' });
console.log(`[${command} ${name}] Success: \`${npmCMDs.runCmd} nest ${command} ${name}\` and start webpack build`);
}
catch (e) {
console.log(`[${command} ${name}] Run: \`${npmCMDs.runCmd} nest ${command} ${name}\` error: `, e);
console.log('\n');
reject(e);
return;
}
const nestProjectConfig = projects[name];
const nodeExternalsParams = nestProjectConfig.nodeExternalsParams;
try {
const output = Object.assign(Object.assign({}, nestProjectConfig.output), { filename: nestProjectConfig.entryFile.endsWith('.js')
? nestProjectConfig.entryFile
: path_1.default.basename(nestProjectConfig.entryFile).replace('.ts', '') + '.js', path: path_1.default.resolve(cwd, distProjects, `dist-${name}`) });
if (include.length === 0) {
nestProjectConfig.entryFile = path_1.default.join(nestProjectConfig.sourceRoot, path_1.default.basename(nestProjectConfig.entryFile));
}
let entry = path_1.default.resolve(cwd, outDir, nestProjectConfig.entryFile.replace('.ts', '.js'));
const entryExists = yield fs_extra_1.default.pathExists(entry.indexOf('.js') > -1 ? entry : entry + '.js');
if (!entryExists) {
const errorMsg = `[${command} ${name}] Entry not found: \`${entry}\``;
const tmpEntry = entry.indexOf('src') > -1
? path_1.default.normalize(path_1.default
.resolve(cwd, outDir, nestProjectConfig.entryFile.replace('.ts', '.js'))
.replace('src', ''))
: path_1.default.resolve(cwd, outDir, 'src', nestProjectConfig.entryFile.replace('.ts', '.js'));
const tmpEntryExists = yield fs_extra_1.default.pathExists(tmpEntry.indexOf('.js') > -1 ? tmpEntry : tmpEntry + '.js');
if (tmpEntryExists) {
entry = tmpEntry;
console.log(`\n${errorMsg}, use another entry: \`${entry}\``);
}
else {
throw new Error(`${errorMsg}`);
}
}
yield webpackBuild(Object.assign(Object.assign({ name,
entry, mode: nestProjectConfig.mode || 'production', target: nestProjectConfig.target || 'node' }, (nestProjectConfig.externals ? { externals: nestProjectConfig.externals } : {})), { nodeExternalsParams, devtool: sourceMap ? 'source-map' : nestProjectConfig.devtool, // nestProjectConfig.devtool, 'source-map'
output }));
console.log(`\n[${command} ${name}] Success webpack build, output: ./${path_1.default.join(distProjects, `dist-${name}`, output.filename)}`);
yield copyProdPackageJSON(path_1.default.join(cwd, distProjects, `dist-${name}`), JSON.stringify(Object.assign(Object.assign({}, pkgContent), { name: pkgContent.name + '-' + name, scripts: {
start: 'cross-env NODE_ENV=production node ./main',
} }), null, 2), name);
resolve(nestProjectConfig);
}
catch (e) {
console.log(`[${command} ${name}] Webpack build error: `, e);
reject(e);
}
}), 0);
});
}));
}
});
}
run().catch((e) => {
console.log(e);
});
function getNestProjectsConfig() {
return __awaiter(this, void 0, void 0, function* () {
const cwd = process.cwd();
const nestjsFilepath = path_1.default.resolve(cwd, require(exports.tsdkConfigFilePath).monorepoRoot || './', 'node_modules/@nestjs/cli/package.json');
const nestjsFilepathExists = yield fs_extra_1.default.pathExists(nestjsFilepath);
if (!nestjsFilepathExists) {
// check again without `monorepoRoot`
const nestjsFilepath = path_1.default.resolve(cwd, 'node_modules/@nestjs/cli/package.json');
const nestjsFilepathExists = yield fs_extra_1.default.pathExists(nestjsFilepath);
if (!nestjsFilepathExists)
throw new Error(`install \`@nestjs/cli\` first`);
}
const nestConfigFilepath = path_1.default.resolve(cwd, './nest-cli.json');
const exists = yield fs_extra_1.default.pathExists(nestConfigFilepath);
if (!exists) {
// throw new Error(`nest-cli.json doesn't exists: ${nestConfigFilepath}`);
}
const content = yield fs_extra_1.default.readFile(nestConfigFilepath, 'utf8');
const nestConfig = exists ? JSON.parse(content) : {};
const defaultMainConfig = Object.assign({ type: 'application', root: './', sourceRoot: 'src', entryFile: 'main', compilerOptions: Object.assign({ webpack: false, tsConfigPath: 'tsconfig.json' }, nestConfig.compilerOptions) }, nestConfig);
return {
projects: Object.assign(Object.assign({}, nestConfig.projects), { [defaultMainName]: defaultMainConfig }),
};
});
}
/**
* in order to ignore built-in modules like path, fs, etc.
* add `externalsPresets: { node: true },`, default is ignore all built-in modules.
*
* in order to ignore all modules in node_modules folder, default is ignore all node_modules.
* if you dont want ignore modules in node_modules, you can add `externals: []`
*
* @Example:
webpackBuild({
name: 'nestjs-todo',
entry: './dist/modules/nestjs-todo/main.js',
mode: 'production',
devtool: "source-map",
externals: undefined, // build all node_modules into one file
target: 'node',
output: {
path: path.resolve(process.cwd(), 'dist-nestjs-todo'),
filename: 'main.js',
},
})
*/
function webpackBuild(_a) {
var { nodeExternalsParams } = _a, webpackConfig = __rest(_a, ["nodeExternalsParams"]);
return new Promise((resolve, reject) => {
(0, webpack_1.default)(Object.assign({ externalsPresets: { node: true }, externals: [(0, webpack_node_externals_1.default)(nodeExternalsParams)] }, webpackConfig), (err, stats) => {
if (err || (stats === null || stats === void 0 ? void 0 : stats.hasErrors())) {
const error = (stats === null || stats === void 0 ? void 0 : stats.compilation.errors) ? stats === null || stats === void 0 ? void 0 : stats.compilation.errors : err;
console.log(`${webpackConfig.name} build error: `, error);
reject(error);
}
else {
resolve('done');
}
});
});
}
exports.webpackBuild = webpackBuild;
let pkgContent = {};
function copyProdPackageJSON(dir, content, name) {
return __awaiter(this, void 0, void 0, function* () {
if (!Object.keys(pkgContent).length) {
const fileContent = yield fs_extra_1.default.readFile(path_1.default.resolve(process.cwd(), 'package.json'), 'utf8');
const pkgJson = JSON.parse(fileContent);
['devDependencies', 'license', 'author', 'keywords', 'files'].forEach((k) => {
delete pkgJson[k];
});
pkgContent = Object.assign({}, pkgJson);
}
if (dir) {
yield fs_extra_1.default.ensureDir(dir);
yield fs_extra_1.default.writeFile(path_1.default.resolve(dir, 'package.json'), content ||
JSON.stringify(Object.assign(Object.assign({}, pkgContent), { name: pkgContent.name + '-' + name, scripts: {} }), null, 2));
}
});
}