2022-05-19 00:40:55 +08:00
|
|
|
const net = require('net');
|
|
|
|
const chalk = require('chalk');
|
|
|
|
const execa = require('execa');
|
2023-09-15 08:51:20 +08:00
|
|
|
const fg = require('fast-glob');
|
2023-11-27 09:07:16 +08:00
|
|
|
const { dirname, join, resolve, sep } = require('path');
|
2022-05-19 00:40:55 +08:00
|
|
|
const { readFile, writeFile } = require('fs').promises;
|
2023-09-15 08:51:20 +08:00
|
|
|
const { existsSync, mkdirSync, cpSync, writeFileSync } = require('fs');
|
2022-05-19 00:40:55 +08:00
|
|
|
|
|
|
|
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();
|
|
|
|
};
|
|
|
|
|
2022-09-18 14:10:01 +08:00
|
|
|
const isProd = () => {
|
|
|
|
const { APP_PACKAGE_ROOT } = process.env;
|
2023-08-02 00:07:52 +08:00
|
|
|
const file = `${APP_PACKAGE_ROOT}/lib/index.js`;
|
2022-09-18 14:10:01 +08:00
|
|
|
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;
|
|
|
|
|
2022-05-19 00:40:55 +08:00
|
|
|
exports.nodeCheck = () => {
|
|
|
|
if (!exports.hasTsNode()) {
|
|
|
|
console.log('Please install all dependencies');
|
|
|
|
console.log(chalk.yellow('$ yarn install'));
|
2022-09-18 14:10:01 +08:00
|
|
|
process.exit(1);
|
2022-05-19 00:40:55 +08:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2023-11-27 09:07:16 +08:00
|
|
|
exports.run = (command, args, options = {}) => {
|
|
|
|
return execa(command, args, {
|
2022-05-19 00:40:55 +08:00
|
|
|
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 () => {
|
2023-09-13 12:21:29 +08:00
|
|
|
const { APP_PACKAGE_ROOT, SERVER_TSCONFIG_PATH } = process.env;
|
2022-05-19 00:40:55 +08:00
|
|
|
|
|
|
|
if (exports.isDev()) {
|
|
|
|
const argv = [
|
2023-07-27 10:29:07 +08:00
|
|
|
'--tsconfig',
|
2023-09-13 12:21:29 +08:00
|
|
|
SERVER_TSCONFIG_PATH,
|
2022-05-19 00:40:55 +08:00
|
|
|
'-r',
|
|
|
|
'tsconfig-paths/register',
|
2023-08-02 00:07:52 +08:00
|
|
|
`${APP_PACKAGE_ROOT}/src/index.ts`,
|
2022-05-19 00:40:55 +08:00
|
|
|
'install',
|
|
|
|
'-s',
|
|
|
|
];
|
2023-07-27 10:29:07 +08:00
|
|
|
await exports.run('tsx', argv);
|
2022-09-18 14:10:01 +08:00
|
|
|
} else if (isProd()) {
|
2023-08-02 00:07:52 +08:00
|
|
|
const file = `${APP_PACKAGE_ROOT}/lib/index.js`;
|
2022-09-18 14:10:01 +08:00
|
|
|
const argv = [file, 'install', '-s'];
|
2022-05-19 00:40:55 +08:00
|
|
|
await exports.run('node', argv);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
exports.runAppCommand = async (command, args = []) => {
|
2023-09-13 12:21:29 +08:00
|
|
|
const { APP_PACKAGE_ROOT, SERVER_TSCONFIG_PATH } = process.env;
|
2022-05-19 00:40:55 +08:00
|
|
|
|
|
|
|
if (exports.isDev()) {
|
|
|
|
const argv = [
|
2023-07-27 10:29:07 +08:00
|
|
|
'--tsconfig',
|
2023-09-13 12:21:29 +08:00
|
|
|
SERVER_TSCONFIG_PATH,
|
2022-05-19 00:40:55 +08:00
|
|
|
'-r',
|
|
|
|
'tsconfig-paths/register',
|
2023-08-02 00:07:52 +08:00
|
|
|
`${APP_PACKAGE_ROOT}/src/index.ts`,
|
2022-05-19 00:40:55 +08:00
|
|
|
command,
|
|
|
|
...args,
|
|
|
|
];
|
2023-07-27 10:29:07 +08:00
|
|
|
await exports.run('tsx', argv);
|
2022-09-18 14:10:01 +08:00
|
|
|
} else if (isProd()) {
|
2023-08-02 00:07:52 +08:00
|
|
|
const argv = [`${APP_PACKAGE_ROOT}/lib/index.js`, command, ...args];
|
2022-05-19 00:40:55 +08:00
|
|
|
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']);
|
2022-06-17 14:21:56 +08:00
|
|
|
const versions = new Function(`return (${stdout})`)();
|
2022-05-19 00:40:55 +08:00
|
|
|
return versions[versions.length - 1];
|
|
|
|
};
|
2023-08-02 00:07:52 +08:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
};
|
2023-09-15 08:51:20 +08:00
|
|
|
|
|
|
|
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);
|
2023-11-27 09:07:16 +08:00
|
|
|
const relativePath = packageDir
|
|
|
|
.slice(cwdLength + 1)
|
|
|
|
.split(sep)
|
|
|
|
.join('/');
|
2023-09-15 08:51:20 +08:00
|
|
|
paths[packageJsonName] = [`${relativePath}/src`];
|
2023-09-23 10:52:14 +08:00
|
|
|
paths[`${packageJsonName}/client`] = [`${relativePath}/src/client`];
|
2023-09-15 08:51:20 +08:00
|
|
|
});
|
|
|
|
|
|
|
|
const tsConfigJsonPath = join(cwd, './tsconfig.paths.json');
|
|
|
|
const content = { compilerOptions: { paths } };
|
|
|
|
writeFileSync(tsConfigJsonPath, JSON.stringify(content, null, 2), 'utf-8');
|
|
|
|
return content;
|
|
|
|
};
|