tachybase_todo/packages/core/cli/src/util.js
jack zhang 9e5e96b9e4
fix: improve build (#2643)
* fix: client lib require wrapper

* fix: bug

* fix: add tsconfig.paths.json

* fix: collection dir not exists

* fix: improve...

* fix: update yarn.lock

* fix: db.sync

* fix: bugs

* fix: bugs

* fix: bugs

* fix: bugs && allow user custom build config

* docs: user custom config docs

* refactor: custom user build config

* fix: bugs

* fix: build plugin-client bug

---------

Co-authored-by: chenos <chenlinxh@gmail.com>
2023-09-15 08:51:20 +08:00

207 lines
5.5 KiB
JavaScript

const net = require('net');
const chalk = require('chalk');
const execa = require('execa');
const fg = require('fast-glob');
const { dirname, join, resolve } = require('path');
const { readFile, writeFile } = require('fs').promises;
const { existsSync, mkdirSync, cpSync, writeFileSync } = require('fs');
exports.isPackageValid = (package) => {
try {
require.resolve(package);
return true;
} catch (error) {
return false;
}
};
exports.hasCorePackages = () => {
const coreDir = resolve(process.cwd(), 'packages/core/build');
return existsSync(coreDir);
};
exports.hasTsNode = () => {
return exports.isPackageValid('ts-node/dist/bin');
};
exports.isDev = function isDev() {
if (process.env.APP_ENV === 'production') {
return false;
}
return exports.hasTsNode();
};
const isProd = () => {
const { APP_PACKAGE_ROOT } = process.env;
const file = `${APP_PACKAGE_ROOT}/lib/index.js`;
if (!existsSync(resolve(process.cwd(), file))) {
console.log('For production environment, please build the code first.');
console.log();
console.log(chalk.yellow('$ yarn build'));
console.log();
process.exit(1);
}
return true;
};
exports.isProd = isProd;
exports.nodeCheck = () => {
if (!exports.hasTsNode()) {
console.log('Please install all dependencies');
console.log(chalk.yellow('$ yarn install'));
process.exit(1);
}
};
exports.run = (command, argv, options = {}) => {
return execa(command, argv, {
shell: true,
stdio: 'inherit',
...options,
env: {
...process.env,
...options.env,
},
});
};
exports.isPortReachable = async (port, { timeout = 1000, host } = {}) => {
const promise = new Promise((resolve, reject) => {
const socket = new net.Socket();
const onError = () => {
socket.destroy();
reject();
};
socket.setTimeout(timeout);
socket.once('error', onError);
socket.once('timeout', onError);
socket.connect(port, host, () => {
socket.end();
resolve();
});
});
try {
await promise;
return true;
} catch (_) {
return false;
}
};
exports.postCheck = async (opts) => {
const port = opts.port || process.env.APP_PORT;
const result = await exports.isPortReachable(port);
if (result) {
console.error(chalk.red(`post already in use ${port}`));
process.exit(1);
}
};
exports.runInstall = async () => {
const { APP_PACKAGE_ROOT, SERVER_TSCONFIG_PATH } = process.env;
if (exports.isDev()) {
const argv = [
'--tsconfig',
SERVER_TSCONFIG_PATH,
'-r',
'tsconfig-paths/register',
`${APP_PACKAGE_ROOT}/src/index.ts`,
'install',
'-s',
];
await exports.run('tsx', argv);
} else if (isProd()) {
const file = `${APP_PACKAGE_ROOT}/lib/index.js`;
const argv = [file, 'install', '-s'];
await exports.run('node', argv);
}
};
exports.runAppCommand = async (command, args = []) => {
const { APP_PACKAGE_ROOT, SERVER_TSCONFIG_PATH } = process.env;
if (exports.isDev()) {
const argv = [
'--tsconfig',
SERVER_TSCONFIG_PATH,
'-r',
'tsconfig-paths/register',
`${APP_PACKAGE_ROOT}/src/index.ts`,
command,
...args,
];
await exports.run('tsx', argv);
} else if (isProd()) {
const argv = [`${APP_PACKAGE_ROOT}/lib/index.js`, command, ...args];
await exports.run('node', argv);
}
};
exports.promptForTs = () => {
console.log(chalk.green('WAIT: ') + 'TypeScript compiling...');
};
exports.updateJsonFile = async (target, fn) => {
const content = await readFile(target, 'utf-8');
const json = JSON.parse(content);
await writeFile(target, JSON.stringify(fn(json), null, 2), 'utf-8');
};
exports.getVersion = async () => {
const { stdout } = await execa('npm', ['v', '@nocobase/app-server', 'versions']);
const versions = new Function(`return (${stdout})`)();
return versions[versions.length - 1];
};
exports.generateAppDir = function generateAppDir() {
const appPkgPath = dirname(dirname(require.resolve('@nocobase/app/src/index.ts')));
const appDevDir = resolve(process.cwd(), './storage/.app-dev');
if (exports.isDev() && !exports.hasCorePackages() && appPkgPath.includes('node_modules')) {
if (!existsSync(appDevDir)) {
mkdirSync(appDevDir, { force: true, recursive: true });
cpSync(appPkgPath, appDevDir, {
recursive: true,
force: true,
});
}
process.env.APP_PACKAGE_ROOT = appDevDir;
} else {
process.env.APP_PACKAGE_ROOT = appPkgPath;
}
};
exports.genTsConfigPaths = function genTsConfigPaths() {
const cwd = process.cwd();
const cwdLength = cwd.length;
const paths = {
'@@/*': ['.dumi/tmp/*'],
};
const packages = fg.sync(['packages/*/*/package.json', 'packages/*/*/*/package.json'], {
absolute: true,
onlyFiles: true,
});
packages.forEach((packageFile) => {
const packageJsonName = require(packageFile).name;
const packageDir = dirname(packageFile);
const relativePath = packageDir.slice(cwdLength + 1).replace(/\\/, '/');
const hasClient = fg.sync(['client', 'client.ts', 'client.tsx', 'client.js', 'client.jsx'], {
cwd: join(packageDir, 'src'),
}).length;
if (hasClient) {
paths[`${packageJsonName}/client`] = [`${relativePath}/src/client`];
}
paths[packageJsonName] = [`${relativePath}/src`];
});
const tsConfigJsonPath = join(cwd, './tsconfig.paths.json');
const content = { compilerOptions: { paths } };
writeFileSync(tsConfigJsonPath, JSON.stringify(content, null, 2), 'utf-8');
return content;
};