feat: 添加publish
This commit is contained in:
parent
da6211299b
commit
a117281b9e
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@kevisual/envision-cli",
|
||||
"version": "0.0.10",
|
||||
"version": "0.0.13",
|
||||
"description": "envision command tools",
|
||||
"main": "dist/index.js",
|
||||
"type": "module",
|
||||
@ -35,7 +35,6 @@
|
||||
"fast-glob": "^3.3.2",
|
||||
"filesize": "^10.1.6",
|
||||
"form-data": "^4.0.1",
|
||||
"glob": "^11.0.0",
|
||||
"ignore": "^6.0.2",
|
||||
"inquirer": "^12.1.0",
|
||||
"rimraf": "^6.0.1",
|
||||
|
3
pnpm-lock.yaml
generated
3
pnpm-lock.yaml
generated
@ -66,9 +66,6 @@ importers:
|
||||
form-data:
|
||||
specifier: ^4.0.1
|
||||
version: 4.0.1
|
||||
glob:
|
||||
specifier: ^11.0.0
|
||||
version: 11.0.0
|
||||
ignore:
|
||||
specifier: ^6.0.2
|
||||
version: 6.0.2
|
||||
|
@ -1,11 +1,14 @@
|
||||
import { program as app, Command } from '@/program.ts';
|
||||
import { glob } from 'glob';
|
||||
import glob from 'fast-glob';
|
||||
import path from 'path';
|
||||
import fs from 'fs';
|
||||
import FormData from 'form-data';
|
||||
import { baseURL, getBaseURL } from '@/module/query.ts';
|
||||
import { getBaseURL, query } from '@/module/query.ts';
|
||||
import { getConfig } from '@/module/index.ts';
|
||||
import inquirer from 'inquirer';
|
||||
import { packLib, unpackLib } from './publish.ts';
|
||||
import chalk from 'chalk';
|
||||
import { installDeps } from '@/uitls/npm.ts';
|
||||
|
||||
const command = new Command('deploy')
|
||||
.description('把前端文件传到服务器')
|
||||
@ -37,8 +40,8 @@ const command = new Command('deploy')
|
||||
const pwd = process.cwd();
|
||||
const directory = path.join(pwd, filePath);
|
||||
const gPath = path.join(directory, '**/*');
|
||||
const files = await glob(gPath, { cwd: pwd, ignore: ['node_modules/**/*'], nodir: true });
|
||||
const _relativeFiles = files.map((file) => file.replace(directory + '/', ''));
|
||||
const files = await glob(gPath, { cwd: pwd, ignore: ['node_modules/**/*'], onlyFiles: true });
|
||||
const _relativeFiles = files.map((file) => path.relative(directory, file));
|
||||
console.log('upload Files', _relativeFiles);
|
||||
console.log('upload Files Key', key, version);
|
||||
if (!yes) {
|
||||
@ -124,8 +127,40 @@ app.addCommand(command);
|
||||
|
||||
const local = new Command('local')
|
||||
.description('本地部署')
|
||||
.option('-k, --key <key>', 'key')
|
||||
.action(() => {
|
||||
.argument('<key>', 'key')
|
||||
.option('-i, --ignore', '使用 .npmignore 文件模式去忽略文件进行打包, 不需要package.json中的files字段')
|
||||
.option('-u, --update', 'query查询 127.0.0.1:11015/api/router?path=local-apps&key=detect')
|
||||
.action(async (key, opts) => {
|
||||
console.log('local deploy');
|
||||
const { outputFilePath } = await packLib(opts?.ignore);
|
||||
const mainAppPath = getConfig().mainAppPath;
|
||||
const appsPath = getConfig().appsPath || path.join(mainAppPath, 'apps');
|
||||
if (!key) {
|
||||
console.error(chalk.red('key is required'));
|
||||
return;
|
||||
}
|
||||
const appPath = path.join(appsPath, key);
|
||||
if (!fs.existsSync(appPath)) {
|
||||
fs.mkdirSync(appPath, { recursive: true });
|
||||
}
|
||||
// 复制应用到apps目录下
|
||||
if (outputFilePath) {
|
||||
await unpackLib(outputFilePath, appPath);
|
||||
fs.unlinkSync(outputFilePath);
|
||||
installDeps({ appPath });
|
||||
if (opts?.update) {
|
||||
const res = await query.post(
|
||||
{ path: 'local-apps', key: 'detect' },
|
||||
{
|
||||
url: `http://127.0.0.1:11015/api/router?path=local-apps&key=detect`,
|
||||
},
|
||||
);
|
||||
if (res.code === 200) {
|
||||
console.log('local deploy success');
|
||||
} else {
|
||||
console.error('local deploy failed', res.message);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
app.addCommand(local);
|
||||
|
@ -4,7 +4,8 @@ import path from 'path';
|
||||
import fs from 'fs';
|
||||
import { chalk } from '@/module/chalk.ts';
|
||||
import inquirer from 'inquirer';
|
||||
import { spawn, spawnSync } from 'child_process';
|
||||
import { spawn } from 'child_process';
|
||||
import { installDeps } from '@/uitls/npm.ts';
|
||||
|
||||
const command = new Command('init').description('初始化应用').action((optison) => {
|
||||
console.log('init');
|
||||
@ -17,6 +18,7 @@ const setMainAppConfig = async (mainAppPath: string) => {
|
||||
config.mainAppPath = mainAppPath;
|
||||
writeConfig(config);
|
||||
};
|
||||
|
||||
const initMain = async () => {
|
||||
const mainAppPath = path.join(envisionPath, 'main-app');
|
||||
const pkgPath = path.join(mainAppPath, 'package.json');
|
||||
@ -26,34 +28,29 @@ const initMain = async () => {
|
||||
name: 'main-app',
|
||||
version: '1.0.0',
|
||||
type: 'module',
|
||||
main: 'dist/app.mjs',
|
||||
scripts: {
|
||||
start: 'node dist/app.mjs',
|
||||
},
|
||||
dependencies: {
|
||||
'@kevisual/router': 'latest',
|
||||
'@kevisual/local-app-manager': 'latest',
|
||||
'@kevisual/use-config': 'latest',
|
||||
},
|
||||
};
|
||||
fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2));
|
||||
console.log(chalk.green('初始化 main-app 成功'));
|
||||
}
|
||||
// 在对应的路径,安装依赖
|
||||
const needDeps = ['@kevisual/router', '@kevisual/local-app-manager', '@kevisual/use-config'];
|
||||
let hasPnpm = false;
|
||||
try {
|
||||
spawnSync('pnpm', ['--version']);
|
||||
hasPnpm = true;
|
||||
} catch (e) {
|
||||
hasPnpm = false;
|
||||
}
|
||||
for (let dep of needDeps) {
|
||||
console.log(chalk.green('安装依赖', dep));
|
||||
const npm = hasPnpm ? 'pnpm' : 'npm';
|
||||
spawnSync(npm, ['install', dep], { cwd: mainAppPath, stdio: 'inherit' });
|
||||
}
|
||||
installDeps({ appPath: mainAppPath, sync: true });
|
||||
// 创建 dist/app.mjs
|
||||
const code = `import { App } from '@kevisual/router';
|
||||
import { app as LocalApp } from '@kevisual/local-app-manager';
|
||||
import { useConfig } from '@kevisual/use-config';
|
||||
const config = useConfig();
|
||||
const app = new App();
|
||||
app.importApp(LocalApp);
|
||||
const host = config.host || '127.0.0.1';
|
||||
app.listen(config.port, host, () => {
|
||||
console.log(\`app is running on http://\${host}:\${config.port}\`);
|
||||
LocalApp.listen(config.port, host, () => {
|
||||
console.log(\`LocalApp is running on http://\${host}:\${config.port}\`);
|
||||
});
|
||||
`;
|
||||
const codeDistPath = path.join(mainAppPath, 'dist');
|
||||
@ -92,6 +89,7 @@ app.listen(config.port, host, () => {
|
||||
//
|
||||
console.log(chalk.green('创建 app.config.json5 成功'));
|
||||
setMainAppConfig(mainAppPath);
|
||||
writeConfig({ ...getConfig(), appsPath: answers.appsPath });
|
||||
};
|
||||
const checkPid = (pid: number) => {
|
||||
try {
|
||||
@ -124,6 +122,8 @@ const mainApp = new Command('main')
|
||||
if (options.init) {
|
||||
await initMain();
|
||||
return;
|
||||
} else {
|
||||
console.warn(chalk.yellow('请使用 --init 初始化 main 应用'));
|
||||
}
|
||||
const runChild = () => {
|
||||
const logDir = path.join(envisionPath, 'log');
|
||||
@ -173,7 +173,7 @@ const mainApp = new Command('main')
|
||||
}
|
||||
}
|
||||
runChild();
|
||||
} else if (options.stop) {
|
||||
} else if (options.exit) {
|
||||
if (config.mainAppPid) {
|
||||
// 检查是否有进程
|
||||
if (checkPid(config.mainAppPid)) {
|
||||
|
@ -6,6 +6,7 @@ import { fileIsExist } from '@/uitls/file.ts';
|
||||
import { getConfig } from '@/module/get-config.ts';
|
||||
import fs from 'fs';
|
||||
import inquirer from 'inquirer';
|
||||
import { checkPnpm } from '@/uitls/npm.ts';
|
||||
|
||||
const command = new Command('npm').description('npm command show publish and set .npmrc').action(async (options) => {});
|
||||
const publish = new Command('publish')
|
||||
@ -165,5 +166,32 @@ const remove = new Command('remove').description('remove .npmrc').action(async (
|
||||
});
|
||||
command.addCommand(remove);
|
||||
|
||||
//
|
||||
const install = new Command('install')
|
||||
.option('-n, --noproxy', 'no proxy')
|
||||
.description('npm install 使用 proxy代理去下载')
|
||||
.action(async (options) => {
|
||||
const cwd = process.cwd();
|
||||
const config = getConfig();
|
||||
let setEnv = {};
|
||||
const proxyEnv = {
|
||||
https_proxy: 'http://127.0.0.1:7890',
|
||||
http_proxy: 'http://127.0.0.1:7890',
|
||||
all_proxy: 'socks5://127.0.0.1:7890',
|
||||
...config?.proxy,
|
||||
};
|
||||
setEnv = {
|
||||
...proxyEnv,
|
||||
};
|
||||
if (options?.noproxy) {
|
||||
setEnv = {};
|
||||
}
|
||||
if (checkPnpm()) {
|
||||
spawn('pnpm', ['i'], { stdio: 'inherit', cwd: cwd, env: { ...process.env, ...setEnv } });
|
||||
} else {
|
||||
spawn('npm', ['i'], { stdio: 'inherit', cwd: cwd, env: { ...process.env, ...setEnv } });
|
||||
}
|
||||
});
|
||||
command.addCommand(install);
|
||||
|
||||
// program 添加npm 的命令
|
||||
program.addCommand(command);
|
||||
|
@ -65,7 +65,7 @@ async function getFiles(cwd: string, patterns: string[]): Promise<string[]> {
|
||||
return filteredFiles;
|
||||
}
|
||||
|
||||
const pack = async () => {
|
||||
export const pack = async () => {
|
||||
const cwd = process.cwd();
|
||||
const collection: Record<string, any> = {};
|
||||
const packageJsonPath = path.join(cwd, 'package.json');
|
||||
@ -120,6 +120,7 @@ const pack = async () => {
|
||||
collection.files = allFiles;
|
||||
collection.packageJson = packageJson;
|
||||
collection.totalSize = totalSize;
|
||||
collection.tags = packageJson.app?.tags || packageJson.keywords || [];
|
||||
|
||||
console.log('\nTarball Details');
|
||||
console.log(`name: ${packageJson.name}`);
|
||||
@ -147,7 +148,7 @@ const pack = async () => {
|
||||
}
|
||||
return { collection, outputFilePath };
|
||||
};
|
||||
const packByIgnore = async () => {
|
||||
export const packByIgnore = async () => {
|
||||
let collection: Record<string, any> = {};
|
||||
const cwd = process.cwd();
|
||||
const patterns = ['**/*']; // 匹配所有文件
|
||||
@ -184,6 +185,7 @@ const packByIgnore = async () => {
|
||||
collection.files = allFiles;
|
||||
collection.packageJson = packageJson;
|
||||
collection.totalSize = totalSize;
|
||||
collection.tags = packageJson.app?.tags || packageJson.keywords || [];
|
||||
|
||||
console.log('\nTarball Details');
|
||||
console.log(`package size: ${packageSize}`);
|
||||
@ -208,6 +210,22 @@ const packByIgnore = async () => {
|
||||
}
|
||||
return { collection, outputFilePath };
|
||||
};
|
||||
export const packLib = async (ignore: boolean = false) => {
|
||||
if (ignore) {
|
||||
return await packByIgnore();
|
||||
}
|
||||
return await pack();
|
||||
};
|
||||
export const unpackLib = async (filePath: string, cwd: string) => {
|
||||
try {
|
||||
await tar.x({
|
||||
file: filePath,
|
||||
cwd: cwd,
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Error extracting tarball:', error);
|
||||
}
|
||||
};
|
||||
const publishCommand = new Command('publish')
|
||||
.description('发布应用')
|
||||
.option('-k, --key <key>', '应用 key')
|
||||
@ -276,12 +294,7 @@ const packCommand = new Command('pack')
|
||||
.option('-i, --ignore', '使用 .npmignore 文件模式去忽略文件进行打包, 不需要package.json中的files字段')
|
||||
.option('-p, --publish', '打包并发布')
|
||||
.action(async (opts) => {
|
||||
let value: { collection: Record<string, any>; outputFilePath: string };
|
||||
if (opts.ignore) {
|
||||
value = await packByIgnore();
|
||||
} else {
|
||||
value = await pack();
|
||||
}
|
||||
let value: { collection: Record<string, any>; outputFilePath: string } = await packLib(opts.ignore);
|
||||
if (opts.publish && value?.collection) {
|
||||
console.log('\n\npublish');
|
||||
const { collection, outputFilePath } = value;
|
||||
|
30
src/uitls/npm.ts
Normal file
30
src/uitls/npm.ts
Normal file
@ -0,0 +1,30 @@
|
||||
import { spawn, spawnSync } from 'child_process';
|
||||
|
||||
export const checkPnpm = () => {
|
||||
try {
|
||||
spawnSync('pnpm', ['--version']);
|
||||
return true;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
type InstallDepsOptions = {
|
||||
appPath: string;
|
||||
isProduction?: boolean;
|
||||
sync?: boolean;
|
||||
};
|
||||
export const installDeps = (opts: InstallDepsOptions) => {
|
||||
const { appPath } = opts;
|
||||
const isProduction = opts.isProduction ?? true;
|
||||
const params = ['i'];
|
||||
if (isProduction) {
|
||||
params.push('--production');
|
||||
}
|
||||
const syncSpawn = opts.sync ? spawnSync : spawn;
|
||||
if (checkPnpm()) {
|
||||
syncSpawn('pnpm', params, { cwd: appPath, stdio: 'inherit', env: process.env });
|
||||
} else {
|
||||
syncSpawn('npm', params, { cwd: appPath, stdio: 'inherit', env: process.env });
|
||||
}
|
||||
};
|
Loading…
x
Reference in New Issue
Block a user