add envision-cli 0.0.6
This commit is contained in:
parent
35cec990c6
commit
2145fca826
4
.npmrc
4
.npmrc
@ -1,3 +1,3 @@
|
|||||||
|
//npm.xiongxiao.me/:_authToken=${ME_NPM_TOKEN}
|
||||||
@abearxiong:registry=https://npm.pkg.github.com
|
@abearxiong:registry=https://npm.pkg.github.com
|
||||||
//registry.npmjs.org/:_authToken=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
|
//registry.npmjs.org/:_authToken=${NPM_TOKEN}
|
||||||
@kevisual:registry=https://npm.xiongxiao.me
|
|
14
package.json
14
package.json
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@kevisual/envision-cli",
|
"name": "@kevisual/envision-cli",
|
||||||
"version": "0.0.5",
|
"version": "0.0.6",
|
||||||
"description": "envision command tools",
|
"description": "envision command tools",
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
@ -29,7 +29,7 @@
|
|||||||
"@rollup/plugin-json": "^6.1.0",
|
"@rollup/plugin-json": "^6.1.0",
|
||||||
"@rollup/plugin-node-resolve": "^15.3.0",
|
"@rollup/plugin-node-resolve": "^15.3.0",
|
||||||
"@rollup/plugin-typescript": "^12.1.1",
|
"@rollup/plugin-typescript": "^12.1.1",
|
||||||
"@types/node": "^22.8.6",
|
"@types/node": "^22.10.1",
|
||||||
"chalk": "^5.3.0",
|
"chalk": "^5.3.0",
|
||||||
"commander": "^12.1.0",
|
"commander": "^12.1.0",
|
||||||
"fast-glob": "^3.3.2",
|
"fast-glob": "^3.3.2",
|
||||||
@ -37,14 +37,14 @@
|
|||||||
"form-data": "^4.0.1",
|
"form-data": "^4.0.1",
|
||||||
"glob": "^11.0.0",
|
"glob": "^11.0.0",
|
||||||
"ignore": "^6.0.2",
|
"ignore": "^6.0.2",
|
||||||
"inquirer": "^12.0.1",
|
"inquirer": "^12.1.0",
|
||||||
"rimraf": "^6.0.1",
|
"rimraf": "^6.0.1",
|
||||||
"rollup": "^4.24.3",
|
"rollup": "^4.27.4",
|
||||||
"rollup-plugin-dts": "^6.1.1",
|
"rollup-plugin-dts": "^6.1.1",
|
||||||
"rollup-plugin-esbuild": "^6.1.1",
|
"rollup-plugin-esbuild": "^6.1.1",
|
||||||
"tar": "^7.4.3",
|
"tar": "^7.4.3",
|
||||||
"tslib": "^2.8.1",
|
"tslib": "^2.8.1",
|
||||||
"typescript": "^5.6.3"
|
"typescript": "^5.7.2"
|
||||||
},
|
},
|
||||||
"resolutions": {
|
"resolutions": {
|
||||||
"picomatch": "^4"
|
"picomatch": "^4"
|
||||||
@ -56,10 +56,10 @@
|
|||||||
"access": "public"
|
"access": "public"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@kevisual/router": "^0.0.3",
|
"@kevisual/router": "^0.0.5",
|
||||||
"pg-hstore": "^2.3.4",
|
"pg-hstore": "^2.3.4",
|
||||||
"sequelize": "^6.37.5",
|
"sequelize": "^6.37.5",
|
||||||
"sqlite3": "^5.1.7",
|
"sqlite3": "^5.1.7",
|
||||||
"vite": "^5.4.10"
|
"vite": "^6.0.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,45 @@ import fs from 'fs';
|
|||||||
import { chalk } from '@/module/chalk.ts';
|
import { chalk } from '@/module/chalk.ts';
|
||||||
import inquirer from 'inquirer';
|
import inquirer from 'inquirer';
|
||||||
|
|
||||||
|
// 设置工作目录
|
||||||
|
const setWorkdir = async (options: { workdir: string }) => {
|
||||||
|
const execPath = process.cwd();
|
||||||
|
let flag = false;
|
||||||
|
let config = getConfig();
|
||||||
|
const workdir = options.workdir;
|
||||||
|
if (workdir) {
|
||||||
|
let finalPath: string;
|
||||||
|
if (workdir.startsWith('/')) {
|
||||||
|
// 如果以 / 开头,处理为绝对路径
|
||||||
|
finalPath = workdir;
|
||||||
|
} else {
|
||||||
|
// 否则,处理为相对路径
|
||||||
|
finalPath = path.join(execPath, workdir);
|
||||||
|
}
|
||||||
|
if (!checkFileExists(finalPath)) {
|
||||||
|
console.log('路径不存在');
|
||||||
|
fs.mkdirSync(finalPath, { recursive: true });
|
||||||
|
}
|
||||||
|
const answers = await inquirer.prompt([
|
||||||
|
{
|
||||||
|
type: 'confirm',
|
||||||
|
name: 'confirm',
|
||||||
|
message: `Are you sure you want to set the workdir to: ${finalPath}?`,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
if (answers.confirm) {
|
||||||
|
flag = true;
|
||||||
|
config.workdir = finalPath;
|
||||||
|
console.log(chalk.green(`set workdir success:`, finalPath));
|
||||||
|
} else {
|
||||||
|
console.log('Cancel set workdir');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (flag) {
|
||||||
|
writeConfig(config);
|
||||||
|
}
|
||||||
|
};
|
||||||
const command = new Command('config')
|
const command = new Command('config')
|
||||||
.description('')
|
.description('')
|
||||||
.option('-d, --dev <dev>', 'Specify dev')
|
.option('-d, --dev <dev>', 'Specify dev')
|
||||||
@ -14,7 +53,7 @@ const command = new Command('config')
|
|||||||
.option('-v --value <value>', 'value')
|
.option('-v --value <value>', 'value')
|
||||||
.option('-w --workdir <path>', 'web config')
|
.option('-w --workdir <path>', 'web config')
|
||||||
.action(async (options) => {
|
.action(async (options) => {
|
||||||
const { dev, list, workdir } = options || {};
|
const { dev, workdir } = options || {};
|
||||||
let config = getConfig();
|
let config = getConfig();
|
||||||
let flag = false;
|
let flag = false;
|
||||||
const execPath = process.cwd();
|
const execPath = process.cwd();
|
||||||
@ -107,11 +146,29 @@ const setCommand = new Command('set')
|
|||||||
when: () => value === 'not_input',
|
when: () => value === 'not_input',
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
if (answer.value === 'not_input') {
|
||||||
|
value = '';
|
||||||
|
}
|
||||||
value = answer.value || value;
|
value = answer.value || value;
|
||||||
|
if (key === 'workdir') {
|
||||||
|
await setWorkdir({ workdir: value });
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (key && value) {
|
if (key && value) {
|
||||||
flag = true;
|
flag = true;
|
||||||
console.log(chalk.green(`set ${key} success:`, value));
|
if (key === 'dev') {
|
||||||
config[key] = value;
|
if (value === 'true') {
|
||||||
|
config.dev = true;
|
||||||
|
} else {
|
||||||
|
config.dev = false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
config[key] = value;
|
||||||
|
}
|
||||||
|
console.log(chalk.green(`set ${key} success:`, config.key));
|
||||||
|
} else if (key) {
|
||||||
|
flag = true;
|
||||||
|
delete config[key];
|
||||||
}
|
}
|
||||||
if (flag) {
|
if (flag) {
|
||||||
writeConfig(config);
|
writeConfig(config);
|
||||||
@ -144,6 +201,19 @@ const getCommand = new Command('get')
|
|||||||
});
|
});
|
||||||
command.addCommand(getCommand);
|
command.addCommand(getCommand);
|
||||||
|
|
||||||
|
const removeCommand = new Command('remove')
|
||||||
|
.argument('<key>')
|
||||||
|
.description('remove config')
|
||||||
|
.action(async (key) => {
|
||||||
|
const config = getConfig();
|
||||||
|
if (key) {
|
||||||
|
delete config[key];
|
||||||
|
writeConfig(config);
|
||||||
|
console.log(chalk.green(`remove ${key} success`));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
command.addCommand(removeCommand);
|
||||||
|
|
||||||
const list = new Command('list').action(async () => {
|
const list = new Command('list').action(async () => {
|
||||||
const config = getConfig();
|
const config = getConfig();
|
||||||
console.log(chalk.green('config', JSON.stringify(config, null, 2)));
|
console.log(chalk.green('config', JSON.stringify(config, null, 2)));
|
||||||
|
@ -1,22 +1,23 @@
|
|||||||
import fs from 'fs/promises';
|
import fs, { createReadStream } from 'fs';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import * as tar from 'tar';
|
import * as tar from 'tar';
|
||||||
import glob from 'fast-glob';
|
import glob from 'fast-glob';
|
||||||
import { program, Command } from '@/program.ts';
|
import { program, Command } from '@/program.ts';
|
||||||
import { getConfig } from '@/module/index.ts';
|
import { getBaseURL, getConfig } from '@/module/index.ts';
|
||||||
import { fileIsExist } from '@/uitls/file.ts';
|
import { fileIsExist } from '@/uitls/file.ts';
|
||||||
import ignore from 'ignore';
|
import ignore from 'ignore';
|
||||||
|
import FormData from 'form-data';
|
||||||
|
|
||||||
// 查找文件(忽略大小写)
|
// 查找文件(忽略大小写)
|
||||||
async function findFileInsensitive(targetFile: string): Promise<string | null> {
|
async function findFileInsensitive(targetFile: string): Promise<string | null> {
|
||||||
const files = await fs.readdir('.');
|
const files = fs.readdirSync('.');
|
||||||
const matchedFile = files.find((file) => file.toLowerCase() === targetFile.toLowerCase());
|
const matchedFile = files.find((file) => file.toLowerCase() === targetFile.toLowerCase());
|
||||||
return matchedFile || null;
|
return matchedFile || null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 递归收集文件信息
|
// 递归收集文件信息
|
||||||
async function collectFileInfo(filePath: string, baseDir = '.'): Promise<any[]> {
|
async function collectFileInfo(filePath: string, baseDir = '.'): Promise<any[]> {
|
||||||
const stats = await fs.stat(filePath);
|
const stats = fs.statSync(filePath);
|
||||||
const relativePath = path.relative(baseDir, filePath);
|
const relativePath = path.relative(baseDir, filePath);
|
||||||
|
|
||||||
if (stats.isFile()) {
|
if (stats.isFile()) {
|
||||||
@ -24,7 +25,7 @@ async function collectFileInfo(filePath: string, baseDir = '.'): Promise<any[]>
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (stats.isDirectory()) {
|
if (stats.isDirectory()) {
|
||||||
const files = await fs.readdir(filePath);
|
const files = fs.readdirSync(filePath);
|
||||||
const results = await Promise.all(files.map((file) => collectFileInfo(path.join(filePath, file), baseDir)));
|
const results = await Promise.all(files.map((file) => collectFileInfo(path.join(filePath, file), baseDir)));
|
||||||
return results.flat();
|
return results.flat();
|
||||||
}
|
}
|
||||||
@ -37,7 +38,7 @@ async function loadNpmIgnore(cwd: string): Promise<ignore.Ignore> {
|
|||||||
const ig = ignore.default();
|
const ig = ignore.default();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const content = await fs.readFile(npmIgnorePath, 'utf-8');
|
const content = fs.readFileSync(npmIgnorePath, 'utf-8');
|
||||||
ig.add(content);
|
ig.add(content);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.warn('.npmignore not found, using default ignore rules');
|
console.warn('.npmignore not found, using default ignore rules');
|
||||||
@ -68,14 +69,14 @@ const pack = async () => {
|
|||||||
const cwd = process.cwd();
|
const cwd = process.cwd();
|
||||||
const collection: Record<string, any> = {};
|
const collection: Record<string, any> = {};
|
||||||
const packageJsonPath = path.join(cwd, 'package.json');
|
const packageJsonPath = path.join(cwd, 'package.json');
|
||||||
if (!(await fileIsExist(packageJsonPath))) {
|
if (!fileIsExist(packageJsonPath)) {
|
||||||
console.error('package.json not found');
|
console.error('package.json not found');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let packageJson;
|
let packageJson;
|
||||||
try {
|
try {
|
||||||
const packageContent = await fs.readFile(packageJsonPath, 'utf-8');
|
const packageContent = fs.readFileSync(packageJsonPath, 'utf-8');
|
||||||
packageJson = JSON.parse(packageContent);
|
packageJson = JSON.parse(packageContent);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Invalid package.json:', error);
|
console.error('Invalid package.json:', error);
|
||||||
@ -139,6 +140,11 @@ const pack = async () => {
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error creating tarball:', error);
|
console.error('Error creating tarball:', error);
|
||||||
}
|
}
|
||||||
|
const readme = await findFileInsensitive('README.md');
|
||||||
|
if (readme) {
|
||||||
|
const readmeContent = fs.readFileSync(readme, 'utf-8');
|
||||||
|
collection.readme = readmeContent;
|
||||||
|
}
|
||||||
return { collection, outputFilePath };
|
return { collection, outputFilePath };
|
||||||
};
|
};
|
||||||
const packByIgnore = async () => {
|
const packByIgnore = async () => {
|
||||||
@ -148,7 +154,7 @@ const packByIgnore = async () => {
|
|||||||
const packageJsonPath = path.join(cwd, 'package.json');
|
const packageJsonPath = path.join(cwd, 'package.json');
|
||||||
let packageJson;
|
let packageJson;
|
||||||
try {
|
try {
|
||||||
const packageContent = await fs.readFile(packageJsonPath, 'utf-8');
|
const packageContent = fs.readFileSync(packageJsonPath, 'utf-8');
|
||||||
packageJson = JSON.parse(packageContent);
|
packageJson = JSON.parse(packageContent);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Invalid package.json:', error);
|
console.error('Invalid package.json:', error);
|
||||||
@ -195,6 +201,11 @@ const packByIgnore = async () => {
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error creating tarball:', error);
|
console.error('Error creating tarball:', error);
|
||||||
}
|
}
|
||||||
|
const readme = await findFileInsensitive('README.md');
|
||||||
|
if (readme) {
|
||||||
|
const readmeContent = fs.readFileSync(readme, 'utf-8');
|
||||||
|
collection.readme = readmeContent;
|
||||||
|
}
|
||||||
return { collection, outputFilePath };
|
return { collection, outputFilePath };
|
||||||
};
|
};
|
||||||
const publishCommand = new Command('publish')
|
const publishCommand = new Command('publish')
|
||||||
@ -204,13 +215,66 @@ const publishCommand = new Command('publish')
|
|||||||
.action(async (options) => {
|
.action(async (options) => {
|
||||||
const { key, version } = options;
|
const { key, version } = options;
|
||||||
const config = await getConfig();
|
const config = await getConfig();
|
||||||
const form = new FormData();
|
|
||||||
console.log('发布逻辑实现', { key, version, config });
|
console.log('发布逻辑实现', { key, version, config });
|
||||||
});
|
});
|
||||||
|
const uploadFiles = async (filePath: string, collection: any): Promise<any> => {
|
||||||
|
const config = await getConfig();
|
||||||
|
const form = new FormData();
|
||||||
|
const filename = path.basename(filePath);
|
||||||
|
try {
|
||||||
|
console.log('upload file', filePath);
|
||||||
|
form.append('file', createReadStream(filePath));
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error reading file:', error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
form.append('collection', JSON.stringify(collection));
|
||||||
|
console.log('upload file', filename);
|
||||||
|
return await new Promise((resolve) => {
|
||||||
|
const _baseURL = getBaseURL();
|
||||||
|
const url = new URL(_baseURL);
|
||||||
|
console.log('upload url', url.hostname, url.protocol, url.port);
|
||||||
|
form.submit(
|
||||||
|
{
|
||||||
|
path: '/api/micro-app/upload',
|
||||||
|
host: url.hostname,
|
||||||
|
protocol: url.protocol as any,
|
||||||
|
port: url.port,
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
Authorization: 'Bearer ' + config.token,
|
||||||
|
...form.getHeaders(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
(err, res) => {
|
||||||
|
if (err) {
|
||||||
|
console.error('Error uploading file:', err.message);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.log('upload success');
|
||||||
|
// 处理服务器响应
|
||||||
|
let body = '';
|
||||||
|
res.on('data', (chunk) => {
|
||||||
|
body += chunk;
|
||||||
|
});
|
||||||
|
|
||||||
|
res.on('end', () => {
|
||||||
|
try {
|
||||||
|
const res = JSON.parse(body);
|
||||||
|
console.log('upload success', res);
|
||||||
|
resolve(res);
|
||||||
|
} catch (e) {
|
||||||
|
resolve({ code: 500, message: body });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
);
|
||||||
|
});
|
||||||
|
};
|
||||||
const packCommand = new Command('pack')
|
const packCommand = new Command('pack')
|
||||||
.description('打包应用, 默认使用 package.json 中的 files 字段')
|
.description('打包应用, 默认使用 package.json 中的 files 字段')
|
||||||
.option('-i, --ignore', '使用 .npmignore 文件模式去忽略文件进行打包, 不需要package.json中的files字段')
|
.option('-i, --ignore', '使用 .npmignore 文件模式去忽略文件进行打包, 不需要package.json中的files字段')
|
||||||
|
.option('-p, --publish', '打包并发布')
|
||||||
.action(async (opts) => {
|
.action(async (opts) => {
|
||||||
let value: { collection: Record<string, any>; outputFilePath: string };
|
let value: { collection: Record<string, any>; outputFilePath: string };
|
||||||
if (opts.ignore) {
|
if (opts.ignore) {
|
||||||
@ -218,6 +282,11 @@ const packCommand = new Command('pack')
|
|||||||
} else {
|
} else {
|
||||||
value = await pack();
|
value = await pack();
|
||||||
}
|
}
|
||||||
|
if (opts.publish && value?.collection) {
|
||||||
|
console.log('\n\npublish');
|
||||||
|
const { collection, outputFilePath } = value;
|
||||||
|
await uploadFiles(outputFilePath, collection);
|
||||||
|
}
|
||||||
//
|
//
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -3,7 +3,16 @@ import { getConfig } from './get-config.ts';
|
|||||||
const config = getConfig();
|
const config = getConfig();
|
||||||
export const baseURL = config?.baseURL || 'https://envision.xiongxiao.me';
|
export const baseURL = config?.baseURL || 'https://envision.xiongxiao.me';
|
||||||
export const getBaseURL = () => {
|
export const getBaseURL = () => {
|
||||||
if (config?.dev) {
|
if (typeof config?.dev === 'undefined') {
|
||||||
|
return baseURL;
|
||||||
|
}
|
||||||
|
if (typeof config?.dev === 'string') {
|
||||||
|
if (config?.dev === 'true') {
|
||||||
|
return 'http://localhost:4002';
|
||||||
|
}
|
||||||
|
return baseURL;
|
||||||
|
}
|
||||||
|
if (config?.dev === true) {
|
||||||
return 'http://localhost:4002';
|
return 'http://localhost:4002';
|
||||||
}
|
}
|
||||||
return baseURL;
|
return baseURL;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user