ai-yuca 1.6.3 → 1.6.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [1.6.4] - 2026-06-08
4
+
5
+ ### Added
6
+ - 新增 `pm2-release` 命令,可读取项目 `package.json` 的 `ai-yuca.pm2Release` 配置,统一执行 PM2 远程 `setup` / `deploy`。
7
+ - `pm2-release` 支持运行时生成临时 PM2 ecosystem 配置,项目侧只需维护 `package.json` 的发布差异配置。
8
+ - `pm2-release` 支持 SSH alias 预检、SSH ControlMaster 复用、发布 ref 覆盖、PM2 命令覆盖,以及 test/prod/all 目标。
9
+
3
10
  ## [1.6.3] - 2026-06-05
4
11
 
5
12
  ### Added
package/README.md CHANGED
@@ -39,6 +39,9 @@ ai-yuca upload-config
39
39
  # 部署到测试环境
40
40
  ai-yuca deploy -e test
41
41
 
42
+ # 通过 PM2 发布当前项目
43
+ ai-yuca pm2-release deploy prod
44
+
42
45
  # 压缩图片
43
46
  ai-yuca sharp -s ./assets -o ./assets-compressed -q 80
44
47
 
@@ -59,6 +62,7 @@ ai-yuca proxy-upload-image -f ./logo.png --raw
59
62
  | `download` | 从 GCP 存储桶下载文件或目录 |
60
63
  | `upload-config` | 基于 `vs.config.json` 批量上传 |
61
64
  | `deploy` | 一键部署到指定环境 |
65
+ | `pm2-release` | 读取项目配置并通过 PM2 远程发布 |
62
66
  | `init` | 交互生成或更新 `vs.config.json` |
63
67
  | `sharp` | 使用 sharp 本地压缩 jpg/png/webp |
64
68
  | `tinify` | 使用 Tinify API 压缩 jpg/png/webp |
@@ -182,6 +186,59 @@ ai-yuca deploy -e test --show-config
182
186
  ai-yuca deploy -e test --replace-config-name-with-package
183
187
  ```
184
188
 
189
+ ### PM2 远程发布
190
+
191
+ `pm2-release` 读取当前项目 `package.json` 的 `ai-yuca.pm2Release` 配置,用于把多个前端项目统一到一套 PM2 发布命令。命令会先检查本机 SSH alias 是否配置了有效 `HostName`,再运行时生成临时 PM2 ecosystem 配置并复用 SSH master 连接执行 PM2;项目内不需要保留 `ecosystem.config.cjs`。
192
+
193
+ ```bash
194
+ # 初始化 test 和 prod 远端目录
195
+ ai-yuca pm2-release setup
196
+
197
+ # 发布测试环境
198
+ ai-yuca pm2-release deploy test
199
+
200
+ # 发布生产环境
201
+ ai-yuca pm2-release deploy prod
202
+
203
+ # 指定分支或 ref
204
+ ai-yuca pm2-release deploy test --ref feat_xxx
205
+ ai-yuca pm2-release deploy prod --ref origin/main
206
+ ```
207
+
208
+ `package.json` 配置示例:
209
+
210
+ ```json
211
+ {
212
+ "scripts": {
213
+ "pm2:setup": "ai-yuca pm2-release setup",
214
+ "pm2:deploy": "ai-yuca pm2-release deploy prod",
215
+ "pm2:deploy:test": "ai-yuca pm2-release deploy test"
216
+ },
217
+ "ai-yuca": {
218
+ "pm2Release": {
219
+ "repo": "git@github.com:HEchooo/project.git",
220
+ "packageManager": "pnpm",
221
+ "pm2Command": "pnpm exec pm2",
222
+ "deployName": "server",
223
+ "environments": {
224
+ "test": {
225
+ "hosts": "test",
226
+ "path": "/home/echooo/fed/project-test",
227
+ "ref": "origin/main",
228
+ "script": "ai:test"
229
+ },
230
+ "prod": {
231
+ "hosts": "test",
232
+ "path": "/home/echooo/fed/project",
233
+ "ref": "origin/main",
234
+ "script": "ai"
235
+ }
236
+ }
237
+ }
238
+ }
239
+ }
240
+ ```
241
+
185
242
  ## 资源处理
186
243
 
187
244
  ### sharp 本地压缩
package/dist/bin/cli.js CHANGED
@@ -59,6 +59,7 @@ const gKeys_1 = require("../src/gKeys");
59
59
  const font_1 = require("../src/font");
60
60
  const ico_1 = require("../src/ico");
61
61
  const proxyUploadImage_1 = require("../src/proxyUploadImage");
62
+ const pm2Release_1 = require("../src/pm2Release");
62
63
  const program = new commander_1.Command();
63
64
  // 设置版本和描述
64
65
  program
@@ -230,6 +231,33 @@ program
230
231
  process.exit(1);
231
232
  }
232
233
  });
234
+ // 添加 PM2 远程发布命令
235
+ program
236
+ .command('pm2-release')
237
+ .description('通过当前项目 package.json 的 ai-yuca.pm2Release 配置执行 PM2 远程发布')
238
+ .argument('<action>', '操作类型:setup 或 deploy')
239
+ .argument('[target]', '发布目标:test、prod 或 all,setup 默认 all,deploy 默认 prod')
240
+ .option('-c, --config <path>', '指定 package.json 路径,默认向上查找当前项目 package.json')
241
+ .option('--ref <ref>', '指定发布分支或 ref,例如 main、origin/main、refs/heads/main')
242
+ .option('--env-name <name>', '覆盖注入到 PM2_DEPLOY_ENV 的环境名')
243
+ .option('--package-manager <name>', '覆盖 PM2 执行器推断,支持 npm 或 pnpm')
244
+ .option('--pm2-command <command>', '自定义 PM2 命令,例如 "pnpm exec pm2" 或 "npx pm2"')
245
+ .action((action, target, options) => {
246
+ try {
247
+ if (action !== 'setup' && action !== 'deploy') {
248
+ throw new Error('action 只能是 setup 或 deploy。');
249
+ }
250
+ const resolvedTarget = target || (action === 'setup' ? 'all' : 'prod');
251
+ if (resolvedTarget !== 'test' && resolvedTarget !== 'prod' && resolvedTarget !== 'all') {
252
+ throw new Error('target 只能是 test、prod 或 all。');
253
+ }
254
+ (0, pm2Release_1.pm2Release)(action, resolvedTarget, options);
255
+ }
256
+ catch (err) {
257
+ console.error(`PM2 发布错误: ${err instanceof Error ? err.message : String(err)}`);
258
+ process.exit(1);
259
+ }
260
+ });
233
261
  // 使用从types导入的UploadCommandOptions接口
234
262
  // 添加upload命令
235
263
  program
package/dist/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ai-yuca",
3
- "version": "1.6.3",
3
+ "version": "1.6.4",
4
4
  "description": "一个用AI生成的开发辅助工具",
5
5
  "main": "dist/src/index.js",
6
6
  "types": "dist/src/index.d.ts",
@@ -0,0 +1,2 @@
1
+ import { Pm2ReleaseAction, Pm2ReleaseCommandOptions, Pm2ReleaseTarget } from './types/pm2Release';
2
+ export declare function pm2Release(action: Pm2ReleaseAction, target: Pm2ReleaseTarget | 'all', options?: Pm2ReleaseCommandOptions): void;
@@ -0,0 +1,321 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.pm2Release = pm2Release;
37
+ const fs = __importStar(require("fs"));
38
+ const os = __importStar(require("os"));
39
+ const path = __importStar(require("path"));
40
+ const child_process_1 = require("child_process");
41
+ function readJson(filePath) {
42
+ return JSON.parse(fs.readFileSync(filePath, 'utf8'));
43
+ }
44
+ function findPackageJson(startDir) {
45
+ let currentDir = path.resolve(startDir);
46
+ while (true) {
47
+ const packagePath = path.join(currentDir, 'package.json');
48
+ if (fs.existsSync(packagePath)) {
49
+ return packagePath;
50
+ }
51
+ const parentDir = path.dirname(currentDir);
52
+ if (parentDir === currentDir) {
53
+ throw new Error('未找到 package.json,请在项目根目录或子目录中执行。');
54
+ }
55
+ currentDir = parentDir;
56
+ }
57
+ }
58
+ function normalizeRef(ref) {
59
+ if (ref.startsWith('origin/') || ref.startsWith('refs/')) {
60
+ return ref;
61
+ }
62
+ return `origin/${ref}`;
63
+ }
64
+ function normalizeHosts(hosts) {
65
+ const hostList = Array.isArray(hosts) ? hosts : (hosts || 'test').split(',');
66
+ return hostList.map((host) => host.trim()).filter(Boolean);
67
+ }
68
+ function getRepoUrl(packageRoot, config) {
69
+ if (config.repo) {
70
+ return config.repo;
71
+ }
72
+ try {
73
+ return (0, child_process_1.execFileSync)('git', ['remote', 'get-url', 'origin'], {
74
+ cwd: packageRoot,
75
+ encoding: 'utf8',
76
+ stdio: ['ignore', 'pipe', 'pipe'],
77
+ }).trim();
78
+ }
79
+ catch (_a) {
80
+ throw new Error('未检测到 git origin,请在 package.json 的 ai-yuca.pm2Release.repo 中配置仓库地址。');
81
+ }
82
+ }
83
+ function buildSshControlPath(config, projectName, packageRoot) {
84
+ if (config.sshControlPath) {
85
+ return config.sshControlPath;
86
+ }
87
+ const controlDir = config.sshControlDir || process.env.PM2_SSH_CONTROL_DIR || '/tmp';
88
+ fs.mkdirSync(controlDir, { recursive: true });
89
+ if (controlDir !== '/tmp') {
90
+ fs.chmodSync(controlDir, 0o700);
91
+ }
92
+ // ControlPath 使用项目名隔离,避免多个项目共享 master 连接时互相覆盖。
93
+ const safeName = projectName || path.basename(packageRoot);
94
+ return path.join(controlDir, `${safeName}-pm2-%C`);
95
+ }
96
+ function ensureSshAliases(hosts) {
97
+ var _a;
98
+ for (const host of hosts) {
99
+ let sshConfig = '';
100
+ try {
101
+ sshConfig = (0, child_process_1.execFileSync)('ssh', ['-G', host], { encoding: 'utf8', stdio: ['ignore', 'pipe', 'pipe'] });
102
+ }
103
+ catch (_b) {
104
+ throw new Error(`未找到 ssh 配置别名: ${host},请先在 ~/.ssh/config 中配置 Host ${host}。`);
105
+ }
106
+ const hostname = (_a = sshConfig
107
+ .split('\n')
108
+ .map((line) => line.trim().split(/\s+/))
109
+ .find(([key]) => key === 'hostname')) === null || _a === void 0 ? void 0 : _a[1];
110
+ if (!hostname || hostname === host) {
111
+ throw new Error(`ssh ${host} 未配置有效 HostName,请先在 ~/.ssh/config 中配置 Host ${host}。`);
112
+ }
113
+ }
114
+ }
115
+ function warmSshMaster(hosts, controlPath) {
116
+ for (const host of hosts) {
117
+ const sharedOptions = [
118
+ '-o',
119
+ 'ControlMaster=auto',
120
+ '-o',
121
+ 'ControlPersist=10m',
122
+ '-o',
123
+ `ControlPath=${controlPath}`,
124
+ ];
125
+ try {
126
+ (0, child_process_1.execFileSync)('ssh', [...sharedOptions, '-O', 'check', host], { stdio: 'ignore' });
127
+ continue;
128
+ }
129
+ catch (_a) {
130
+ // check 失败时建立 master 连接,后续 PM2 可复用登录态。
131
+ }
132
+ try {
133
+ (0, child_process_1.execFileSync)('ssh', ['-MNf', '-o', 'ControlMaster=yes', '-o', 'ControlPersist=10m', '-o', `ControlPath=${controlPath}`, host], {
134
+ stdio: 'inherit',
135
+ });
136
+ }
137
+ catch (_b) {
138
+ console.warn(`SSH master 连接预热失败,继续由 PM2 直接连接: ${host}`);
139
+ }
140
+ }
141
+ }
142
+ function shellQuote(value) {
143
+ return `'${value.replace(/'/g, `'\\''`)}'`;
144
+ }
145
+ function hasRemoteSource(hosts, controlPath, deployPath) {
146
+ const sourcePath = path.posix.join(deployPath, 'source', '.git');
147
+ for (const host of hosts) {
148
+ try {
149
+ const output = (0, child_process_1.execFileSync)('ssh', [
150
+ '-o',
151
+ 'ControlMaster=auto',
152
+ '-o',
153
+ 'ControlPersist=10m',
154
+ '-o',
155
+ `ControlPath=${controlPath}`,
156
+ host,
157
+ 'sh',
158
+ '-lc',
159
+ `test -d ${shellQuote(sourcePath)} && echo exists || echo missing`,
160
+ ], { encoding: 'utf8', stdio: ['ignore', 'pipe', 'pipe'] }).trim();
161
+ if (!output.split(/\s+/).includes('exists')) {
162
+ return false;
163
+ }
164
+ }
165
+ catch (_a) {
166
+ return false;
167
+ }
168
+ }
169
+ return true;
170
+ }
171
+ function getPm2Command(config, options) {
172
+ const command = options.pm2Command || config.pm2Command;
173
+ if (command) {
174
+ const [bin, ...args] = command.split(/\s+/).filter(Boolean);
175
+ return [bin, args];
176
+ }
177
+ const packageManager = options.packageManager || config.packageManager || 'npm';
178
+ if (packageManager === 'pnpm') {
179
+ return ['pnpm', ['exec', 'pm2']];
180
+ }
181
+ return ['npx', ['pm2']];
182
+ }
183
+ function getInstallCommand(config) {
184
+ if (config.installCommand) {
185
+ return config.installCommand;
186
+ }
187
+ return config.packageManager === 'pnpm' ? 'pnpm install --frozen-lockfile' : 'npm ci';
188
+ }
189
+ function getRunCommand(config) {
190
+ if (config.runCommand) {
191
+ return config.runCommand;
192
+ }
193
+ return config.packageManager === 'pnpm' ? 'pnpm run' : 'npm run';
194
+ }
195
+ function escapeJsString(value) {
196
+ return value.replace(/\\/g, '\\\\').replace(/'/g, "\\'");
197
+ }
198
+ function createTempEcosystem(packageRoot, packageJson, config, controlPath) {
199
+ const projectName = packageJson.name || path.basename(packageRoot);
200
+ const repo = getRepoUrl(packageRoot, config);
201
+ const prodConfig = getEnvConfig(config, 'prod');
202
+ const prodHosts = normalizeHosts(prodConfig.hosts).join(',');
203
+ const prodRef = normalizeRef(prodConfig.ref || 'origin/main');
204
+ const prodScript = prodConfig.script || 'ai';
205
+ const installCommand = getInstallCommand(config);
206
+ const runCommand = getRunCommand(config);
207
+ const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'ai-yuca-pm2-'));
208
+ const ecosystemPath = path.join(tempDir, 'ecosystem.config.cjs');
209
+ const content = `const REPO = '${escapeJsString(repo)}';
210
+ const DEPLOY_HOST = (process.env.PM2_DEPLOY_HOST || '${escapeJsString(prodHosts || 'test')}')
211
+ .split(',')
212
+ .map((host) => host.trim())
213
+ .filter(Boolean);
214
+ const DEPLOY_PATH = process.env.PM2_DEPLOY_PATH || '${escapeJsString(prodConfig.path)}';
215
+ const DEPLOY_REF = process.env.PM2_DEPLOY_REF || '${escapeJsString(prodRef)}';
216
+ const DEPLOY_ENV = process.env.PM2_DEPLOY_ENV || 'prod';
217
+ const DEPLOY_SCRIPT = process.env.PM2_DEPLOY_SCRIPT || '${escapeJsString(prodScript)}';
218
+ const SSH_CONTROL_PATH =
219
+ process.env.PM2_SSH_CONTROL_PATH || '${escapeJsString(controlPath)}';
220
+ const SSH_OPTIONS = [
221
+ 'ControlMaster=auto',
222
+ 'ControlPersist=10m',
223
+ \`ControlPath=\${SSH_CONTROL_PATH}\`,
224
+ ];
225
+
226
+ const withNvm = (command) =>
227
+ [
228
+ '. ~/.nvm/nvm.sh',
229
+ 'corepack enable',
230
+ 'export PATH=$(pnpm config get global-bin-dir 2>/dev/null || npm config get prefix)/bin:$HOME/.npm-global/bin:$HOME/.local/bin:$PATH',
231
+ \`echo pm2-release-env=\${DEPLOY_ENV} script=\${DEPLOY_SCRIPT} path=$PWD\`,
232
+ 'echo node=$(command -v node) pnpm=$(command -v pnpm || true) npm=$(command -v npm) ai-yuca=$(command -v ai-yuca || true)',
233
+ command,
234
+ ].join(' && ');
235
+
236
+ module.exports = {
237
+ deploy: {
238
+ server: {
239
+ host: DEPLOY_HOST.length === 1 ? DEPLOY_HOST[0] : DEPLOY_HOST,
240
+ ref: DEPLOY_REF,
241
+ repo: REPO,
242
+ path: DEPLOY_PATH,
243
+ // 发布目标由 ai-yuca pm2-release 注入,避免项目维护 ecosystem.config.cjs。
244
+ ssh_options: SSH_OPTIONS,
245
+ 'post-deploy': withNvm(
246
+ \`${escapeJsString(installCommand)} && ${escapeJsString(runCommand)} \${DEPLOY_SCRIPT}\`,
247
+ ),
248
+ },
249
+ },
250
+ };
251
+ `;
252
+ fs.writeFileSync(ecosystemPath, content);
253
+ return ecosystemPath;
254
+ }
255
+ function getEnvConfig(config, target) {
256
+ var _a;
257
+ const envConfig = (_a = config.environments) === null || _a === void 0 ? void 0 : _a[target];
258
+ if (!(envConfig === null || envConfig === void 0 ? void 0 : envConfig.path)) {
259
+ throw new Error(`pm2Release.environments.${target}.path 不能为空。`);
260
+ }
261
+ return envConfig;
262
+ }
263
+ function runPm2(packageRoot, packageJson, config, action, target, options) {
264
+ const envConfig = getEnvConfig(config, target);
265
+ const hosts = normalizeHosts(envConfig.hosts);
266
+ const controlPath = buildSshControlPath(config, packageJson.name || '', packageRoot);
267
+ const deployName = config.deployName || 'server';
268
+ const ref = normalizeRef(options.ref || envConfig.ref || 'origin/main');
269
+ const script = envConfig.script || (target === 'test' ? 'ai:test' : 'ai');
270
+ const [pm2Bin, pm2Args] = getPm2Command(config, options);
271
+ const ecosystem = createTempEcosystem(packageRoot, packageJson, config, controlPath);
272
+ ensureSshAliases(hosts);
273
+ warmSshMaster(hosts, controlPath);
274
+ const env = {
275
+ ...process.env,
276
+ PM2_DEPLOY_HOST: hosts.join(','),
277
+ PM2_DEPLOY_PATH: envConfig.path,
278
+ PM2_DEPLOY_REF: action === 'setup' ? normalizeRef(envConfig.setupRef || ref) : ref,
279
+ PM2_DEPLOY_ENV: options.envName || target,
280
+ PM2_DEPLOY_SCRIPT: action === 'setup' ? envConfig.setupScript || script : script,
281
+ PM2_SSH_CONTROL_PATH: controlPath,
282
+ };
283
+ console.log(`PM2 ${action} target: env=${target} host=${hosts.join(',')} path=${envConfig.path} script=${env.PM2_DEPLOY_SCRIPT} ref=${env.PM2_DEPLOY_REF}`);
284
+ if (action === 'setup' && hasRemoteSource(hosts, controlPath, envConfig.path)) {
285
+ console.log(`PM2 setup skipped: ${envConfig.path}/source already exists on ${hosts.join(',')}`);
286
+ return;
287
+ }
288
+ try {
289
+ const args = [...pm2Args, 'deploy', ecosystem, deployName];
290
+ if (action === 'setup') {
291
+ args.push('setup');
292
+ }
293
+ else {
294
+ args.push('--force');
295
+ }
296
+ (0, child_process_1.execFileSync)(pm2Bin, args, {
297
+ cwd: packageRoot,
298
+ env,
299
+ stdio: 'inherit',
300
+ });
301
+ }
302
+ finally {
303
+ fs.rmSync(path.dirname(ecosystem), { recursive: true, force: true });
304
+ }
305
+ }
306
+ function pm2Release(action, target, options = {}) {
307
+ var _a;
308
+ const packagePath = options.config
309
+ ? path.resolve(options.config)
310
+ : findPackageJson(process.cwd());
311
+ const packageRoot = path.dirname(packagePath);
312
+ const packageJson = readJson(packagePath);
313
+ const config = (_a = packageJson['ai-yuca']) === null || _a === void 0 ? void 0 : _a.pm2Release;
314
+ if (!config) {
315
+ throw new Error('package.json 缺少 ai-yuca.pm2Release 配置。');
316
+ }
317
+ const targets = target === 'all' ? ['test', 'prod'] : [target];
318
+ for (const releaseTarget of targets) {
319
+ runPm2(packageRoot, packageJson, config, action, releaseTarget, options);
320
+ }
321
+ }
@@ -16,3 +16,4 @@ export * from './gKeys';
16
16
  export * from './font';
17
17
  export * from './ico';
18
18
  export * from './proxyUploadImage';
19
+ export * from './pm2Release';
@@ -40,3 +40,4 @@ __exportStar(require("./gKeys"), exports);
40
40
  __exportStar(require("./font"), exports);
41
41
  __exportStar(require("./ico"), exports);
42
42
  __exportStar(require("./proxyUploadImage"), exports);
43
+ __exportStar(require("./pm2Release"), exports);
@@ -0,0 +1,31 @@
1
+ export type Pm2ReleaseAction = 'setup' | 'deploy';
2
+ export type Pm2ReleaseTarget = 'test' | 'prod';
3
+ export interface Pm2ReleaseCommandOptions {
4
+ config?: string;
5
+ packageManager?: string;
6
+ pm2Command?: string;
7
+ envName?: string;
8
+ ref?: string;
9
+ }
10
+ export interface Pm2ReleaseEnvConfig {
11
+ hosts?: string | string[];
12
+ path: string;
13
+ ref?: string;
14
+ script?: string;
15
+ setupRef?: string;
16
+ setupScript?: string;
17
+ }
18
+ export interface Pm2ReleaseConfig {
19
+ repo?: string;
20
+ deployName?: string;
21
+ sshControlDir?: string;
22
+ sshControlPath?: string;
23
+ packageManager?: string;
24
+ pm2Command?: string;
25
+ installCommand?: string;
26
+ runCommand?: string;
27
+ environments: {
28
+ test: Pm2ReleaseEnvConfig;
29
+ prod: Pm2ReleaseEnvConfig;
30
+ };
31
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ai-yuca",
3
- "version": "1.6.3",
3
+ "version": "1.6.4",
4
4
  "description": "一个用AI生成的开发辅助工具",
5
5
  "main": "dist/src/index.js",
6
6
  "types": "dist/src/index.d.ts",