@jvittechs/jai1-cli 0.1.84 → 0.1.85
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/README.md +2 -2
- package/dist/cli.js +532 -127
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// src/cli.ts
|
|
4
|
-
import { Command as
|
|
4
|
+
import { Command as Command47 } from "commander";
|
|
5
5
|
|
|
6
6
|
// src/errors/index.ts
|
|
7
7
|
var Jai1Error = class extends Error {
|
|
@@ -33,7 +33,7 @@ var NetworkError = class extends Jai1Error {
|
|
|
33
33
|
// package.json
|
|
34
34
|
var package_default = {
|
|
35
35
|
name: "@jvittechs/jai1-cli",
|
|
36
|
-
version: "0.1.
|
|
36
|
+
version: "0.1.85",
|
|
37
37
|
description: "A unified CLI tool for JV-IT TECHS developers to manage Jai1 Framework. Please contact TeamAI for usage instructions.",
|
|
38
38
|
type: "module",
|
|
39
39
|
bin: {
|
|
@@ -7238,14 +7238,417 @@ Quick Usage:
|
|
|
7238
7238
|
return utilsCommand;
|
|
7239
7239
|
}
|
|
7240
7240
|
|
|
7241
|
+
// src/commands/deps/index.ts
|
|
7242
|
+
import { Command as Command30 } from "commander";
|
|
7243
|
+
|
|
7244
|
+
// src/commands/deps/upgrade.ts
|
|
7245
|
+
import { Command as Command29 } from "commander";
|
|
7246
|
+
import { checkbox as checkbox3, confirm as confirm4 } from "@inquirer/prompts";
|
|
7247
|
+
|
|
7248
|
+
// src/services/deps.service.ts
|
|
7249
|
+
import { promises as fs9 } from "fs";
|
|
7250
|
+
import path6 from "path";
|
|
7251
|
+
import { execSync } from "child_process";
|
|
7252
|
+
import pLimit2 from "p-limit";
|
|
7253
|
+
var DepsService = class {
|
|
7254
|
+
versionCache = /* @__PURE__ */ new Map();
|
|
7255
|
+
/**
|
|
7256
|
+
* Đọc package.json từ thư mục
|
|
7257
|
+
*/
|
|
7258
|
+
async readPackageJson(cwd) {
|
|
7259
|
+
const pkgPath = path6.join(cwd, "package.json");
|
|
7260
|
+
try {
|
|
7261
|
+
const content = await fs9.readFile(pkgPath, "utf-8");
|
|
7262
|
+
return JSON.parse(content);
|
|
7263
|
+
} catch (error) {
|
|
7264
|
+
if (error.code === "ENOENT") {
|
|
7265
|
+
throw new Error("Kh\xF4ng t\xECm th\u1EA5y package.json trong th\u01B0 m\u1EE5c hi\u1EC7n t\u1EA1i");
|
|
7266
|
+
}
|
|
7267
|
+
throw new Error(`L\u1ED7i \u0111\u1ECDc package.json: ${error.message}`);
|
|
7268
|
+
}
|
|
7269
|
+
}
|
|
7270
|
+
/**
|
|
7271
|
+
* Lấy version mới nhất từ npm registry
|
|
7272
|
+
*/
|
|
7273
|
+
async fetchLatestVersion(packageName) {
|
|
7274
|
+
if (this.versionCache.has(packageName)) {
|
|
7275
|
+
return this.versionCache.get(packageName);
|
|
7276
|
+
}
|
|
7277
|
+
try {
|
|
7278
|
+
const response = await fetch(
|
|
7279
|
+
`https://registry.npmjs.org/${encodeURIComponent(packageName)}/latest`,
|
|
7280
|
+
{ signal: AbortSignal.timeout(1e4) }
|
|
7281
|
+
);
|
|
7282
|
+
if (!response.ok) {
|
|
7283
|
+
return null;
|
|
7284
|
+
}
|
|
7285
|
+
const data = await response.json();
|
|
7286
|
+
this.versionCache.set(packageName, data.version);
|
|
7287
|
+
return data.version;
|
|
7288
|
+
} catch {
|
|
7289
|
+
return null;
|
|
7290
|
+
}
|
|
7291
|
+
}
|
|
7292
|
+
/**
|
|
7293
|
+
* Fetch nhiều packages cùng lúc với giới hạn concurrent
|
|
7294
|
+
*/
|
|
7295
|
+
async fetchBulkVersions(packages, onProgress) {
|
|
7296
|
+
const limit = pLimit2(10);
|
|
7297
|
+
const total = packages.length;
|
|
7298
|
+
let completed = 0;
|
|
7299
|
+
const results = await Promise.all(
|
|
7300
|
+
packages.map(
|
|
7301
|
+
(pkg) => limit(async () => {
|
|
7302
|
+
const latest = await this.fetchLatestVersion(pkg.name);
|
|
7303
|
+
completed++;
|
|
7304
|
+
onProgress?.(completed, total);
|
|
7305
|
+
if (!latest) {
|
|
7306
|
+
return null;
|
|
7307
|
+
}
|
|
7308
|
+
const currentClean = this.stripSemverPrefix(pkg.current);
|
|
7309
|
+
const canUpgrade = this.isNewerVersion(latest, currentClean);
|
|
7310
|
+
return {
|
|
7311
|
+
name: pkg.name,
|
|
7312
|
+
current: pkg.current,
|
|
7313
|
+
latest,
|
|
7314
|
+
latestWithPrefix: this.preserveSemverPrefix(pkg.current, latest),
|
|
7315
|
+
type: pkg.type,
|
|
7316
|
+
canUpgrade
|
|
7317
|
+
};
|
|
7318
|
+
})
|
|
7319
|
+
)
|
|
7320
|
+
);
|
|
7321
|
+
return results.filter((r) => r !== null && r.canUpgrade);
|
|
7322
|
+
}
|
|
7323
|
+
/**
|
|
7324
|
+
* Loại bỏ semver prefix (^, ~, >=, etc.)
|
|
7325
|
+
*/
|
|
7326
|
+
stripSemverPrefix(version) {
|
|
7327
|
+
return version.replace(/^[~^>=<]+/, "");
|
|
7328
|
+
}
|
|
7329
|
+
/**
|
|
7330
|
+
* Giữ nguyên semver prefix khi upgrade
|
|
7331
|
+
*/
|
|
7332
|
+
preserveSemverPrefix(current, latest) {
|
|
7333
|
+
const match = current.match(/^([~^>=<]*)/);
|
|
7334
|
+
const prefix = match?.[1] || "";
|
|
7335
|
+
return prefix + latest;
|
|
7336
|
+
}
|
|
7337
|
+
/**
|
|
7338
|
+
* So sánh version để xác định có cần upgrade không
|
|
7339
|
+
*/
|
|
7340
|
+
isNewerVersion(remote, local) {
|
|
7341
|
+
const remoteParts = remote.split(".").map(Number);
|
|
7342
|
+
const localParts = local.split(".").map(Number);
|
|
7343
|
+
for (let i = 0; i < 3; i++) {
|
|
7344
|
+
const r = remoteParts[i] || 0;
|
|
7345
|
+
const l = localParts[i] || 0;
|
|
7346
|
+
if (r > l) return true;
|
|
7347
|
+
if (r < l) return false;
|
|
7348
|
+
}
|
|
7349
|
+
return false;
|
|
7350
|
+
}
|
|
7351
|
+
/**
|
|
7352
|
+
* Detect package manager từ lock files
|
|
7353
|
+
* Priority:
|
|
7354
|
+
* 1. Lock file trong project
|
|
7355
|
+
* 2. pnpm nếu có cài đặt trong máy
|
|
7356
|
+
* 3. npm (fallback)
|
|
7357
|
+
*/
|
|
7358
|
+
async detectPackageManager(cwd) {
|
|
7359
|
+
const lockFiles = [
|
|
7360
|
+
{ file: "pnpm-lock.yaml", pm: "pnpm" },
|
|
7361
|
+
{ file: "yarn.lock", pm: "yarn" },
|
|
7362
|
+
{ file: "bun.lockb", pm: "bun" },
|
|
7363
|
+
{ file: "package-lock.json", pm: "npm" }
|
|
7364
|
+
];
|
|
7365
|
+
for (const { file, pm } of lockFiles) {
|
|
7366
|
+
try {
|
|
7367
|
+
await fs9.access(path6.join(cwd, file));
|
|
7368
|
+
return pm;
|
|
7369
|
+
} catch {
|
|
7370
|
+
}
|
|
7371
|
+
}
|
|
7372
|
+
const userAgent = process.env.npm_config_user_agent || "";
|
|
7373
|
+
if (userAgent.includes("pnpm")) return "pnpm";
|
|
7374
|
+
if (userAgent.includes("yarn")) return "yarn";
|
|
7375
|
+
if (userAgent.includes("bun")) return "bun";
|
|
7376
|
+
if (userAgent.includes("npm")) return "npm";
|
|
7377
|
+
if (this.isCommandAvailable("pnpm")) return "pnpm";
|
|
7378
|
+
return "npm";
|
|
7379
|
+
}
|
|
7380
|
+
/**
|
|
7381
|
+
* Kiểm tra command có sẵn trong hệ thống không
|
|
7382
|
+
*/
|
|
7383
|
+
isCommandAvailable(command) {
|
|
7384
|
+
try {
|
|
7385
|
+
execSync(`${command} --version`, {
|
|
7386
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
7387
|
+
});
|
|
7388
|
+
return true;
|
|
7389
|
+
} catch {
|
|
7390
|
+
return false;
|
|
7391
|
+
}
|
|
7392
|
+
}
|
|
7393
|
+
/**
|
|
7394
|
+
* Tạo command để upgrade packages
|
|
7395
|
+
*/
|
|
7396
|
+
getUpgradeCommands(packages, pm) {
|
|
7397
|
+
const deps = packages.filter((p) => p.type === "dep");
|
|
7398
|
+
const devDeps = packages.filter((p) => p.type === "dev");
|
|
7399
|
+
const formatPackages = (pkgs) => pkgs.map((p) => `${p.name}@${p.latestWithPrefix}`).join(" ");
|
|
7400
|
+
let depsCmd = null;
|
|
7401
|
+
let devDepsCmd = null;
|
|
7402
|
+
if (deps.length > 0) {
|
|
7403
|
+
const pkgList = formatPackages(deps);
|
|
7404
|
+
switch (pm) {
|
|
7405
|
+
case "pnpm":
|
|
7406
|
+
depsCmd = `pnpm add ${pkgList}`;
|
|
7407
|
+
break;
|
|
7408
|
+
case "yarn":
|
|
7409
|
+
depsCmd = `yarn add ${pkgList}`;
|
|
7410
|
+
break;
|
|
7411
|
+
case "bun":
|
|
7412
|
+
depsCmd = `bun add ${pkgList}`;
|
|
7413
|
+
break;
|
|
7414
|
+
default:
|
|
7415
|
+
depsCmd = `npm install ${pkgList}`;
|
|
7416
|
+
}
|
|
7417
|
+
}
|
|
7418
|
+
if (devDeps.length > 0) {
|
|
7419
|
+
const pkgList = formatPackages(devDeps);
|
|
7420
|
+
switch (pm) {
|
|
7421
|
+
case "pnpm":
|
|
7422
|
+
devDepsCmd = `pnpm add -D ${pkgList}`;
|
|
7423
|
+
break;
|
|
7424
|
+
case "yarn":
|
|
7425
|
+
devDepsCmd = `yarn add -D ${pkgList}`;
|
|
7426
|
+
break;
|
|
7427
|
+
case "bun":
|
|
7428
|
+
devDepsCmd = `bun add -D ${pkgList}`;
|
|
7429
|
+
break;
|
|
7430
|
+
default:
|
|
7431
|
+
devDepsCmd = `npm install -D ${pkgList}`;
|
|
7432
|
+
}
|
|
7433
|
+
}
|
|
7434
|
+
return { deps: depsCmd, devDeps: devDepsCmd };
|
|
7435
|
+
}
|
|
7436
|
+
/**
|
|
7437
|
+
* Thực thi upgrade command
|
|
7438
|
+
*/
|
|
7439
|
+
executeUpgrade(command) {
|
|
7440
|
+
execSync(command, {
|
|
7441
|
+
stdio: "inherit",
|
|
7442
|
+
env: { ...process.env, FORCE_COLOR: "1" }
|
|
7443
|
+
});
|
|
7444
|
+
}
|
|
7445
|
+
};
|
|
7446
|
+
|
|
7447
|
+
// src/commands/deps/upgrade.ts
|
|
7448
|
+
var colors2 = {
|
|
7449
|
+
yellow: "\x1B[33m",
|
|
7450
|
+
green: "\x1B[32m",
|
|
7451
|
+
cyan: "\x1B[36m",
|
|
7452
|
+
red: "\x1B[31m",
|
|
7453
|
+
gray: "\x1B[90m",
|
|
7454
|
+
reset: "\x1B[0m",
|
|
7455
|
+
bold: "\x1B[1m",
|
|
7456
|
+
dim: "\x1B[2m"
|
|
7457
|
+
};
|
|
7458
|
+
function createDepsUpgradeCommand() {
|
|
7459
|
+
return new Command29("upgrade").description("Upgrade npm packages l\xEAn version m\u1EDBi nh\u1EA5t").option("--check", "Ch\u1EC9 ki\u1EC3m tra, kh\xF4ng upgrade").option("--all", "Upgrade t\u1EA5t c\u1EA3 kh\xF4ng c\u1EA7n ch\u1ECDn").option("--deps-only", "Ch\u1EC9 upgrade dependencies").option("--dev-only", "Ch\u1EC9 upgrade devDependencies").action(async (options) => {
|
|
7460
|
+
await handleDepsUpgrade(options);
|
|
7461
|
+
});
|
|
7462
|
+
}
|
|
7463
|
+
async function handleDepsUpgrade(options) {
|
|
7464
|
+
const depsService = new DepsService();
|
|
7465
|
+
const cwd = process.cwd();
|
|
7466
|
+
try {
|
|
7467
|
+
console.log(`
|
|
7468
|
+
${colors2.cyan}\u{1F50D} \u0110ang \u0111\u1ECDc package.json...${colors2.reset}`);
|
|
7469
|
+
const pkg = await depsService.readPackageJson(cwd);
|
|
7470
|
+
const packagesToCheck = [];
|
|
7471
|
+
if (!options.devOnly && pkg.dependencies) {
|
|
7472
|
+
for (const [name, version] of Object.entries(pkg.dependencies)) {
|
|
7473
|
+
if (isNpmVersion(version)) {
|
|
7474
|
+
packagesToCheck.push({ name, current: version, type: "dep" });
|
|
7475
|
+
}
|
|
7476
|
+
}
|
|
7477
|
+
}
|
|
7478
|
+
if (!options.depsOnly && pkg.devDependencies) {
|
|
7479
|
+
for (const [name, version] of Object.entries(pkg.devDependencies)) {
|
|
7480
|
+
if (isNpmVersion(version)) {
|
|
7481
|
+
packagesToCheck.push({ name, current: version, type: "dev" });
|
|
7482
|
+
}
|
|
7483
|
+
}
|
|
7484
|
+
}
|
|
7485
|
+
if (packagesToCheck.length === 0) {
|
|
7486
|
+
console.log(`${colors2.yellow}\u26A0\uFE0F Kh\xF4ng t\xECm th\u1EA5y packages \u0111\u1EC3 ki\u1EC3m tra${colors2.reset}
|
|
7487
|
+
`);
|
|
7488
|
+
return;
|
|
7489
|
+
}
|
|
7490
|
+
const depsCount = packagesToCheck.filter((p) => p.type === "dep").length;
|
|
7491
|
+
const devCount = packagesToCheck.filter((p) => p.type === "dev").length;
|
|
7492
|
+
console.log(
|
|
7493
|
+
`${colors2.bold}\u{1F4E6} T\xECm th\u1EA5y ${depsCount} dependencies v\xE0 ${devCount} devDependencies${colors2.reset}
|
|
7494
|
+
`
|
|
7495
|
+
);
|
|
7496
|
+
console.log(`${colors2.cyan}\u23F3 Ki\u1EC3m tra phi\xEAn b\u1EA3n m\u1EDBi nh\u1EA5t...${colors2.reset}`);
|
|
7497
|
+
const upgradablePackages = await depsService.fetchBulkVersions(
|
|
7498
|
+
packagesToCheck,
|
|
7499
|
+
(completed, total) => {
|
|
7500
|
+
const progress = Math.round(completed / total * 100);
|
|
7501
|
+
const bar = "\u2588".repeat(Math.floor(progress / 5)) + "\u2591".repeat(20 - Math.floor(progress / 5));
|
|
7502
|
+
process.stdout.write(`\r[${bar}] ${completed}/${total} packages`);
|
|
7503
|
+
}
|
|
7504
|
+
);
|
|
7505
|
+
console.log("\n");
|
|
7506
|
+
if (upgradablePackages.length === 0) {
|
|
7507
|
+
console.log(`${colors2.green}\u2705 T\u1EA5t c\u1EA3 packages \u0111\xE3 l\xE0 phi\xEAn b\u1EA3n m\u1EDBi nh\u1EA5t!${colors2.reset}
|
|
7508
|
+
`);
|
|
7509
|
+
return;
|
|
7510
|
+
}
|
|
7511
|
+
displayUpgradeTable(upgradablePackages);
|
|
7512
|
+
if (options.check) {
|
|
7513
|
+
console.log(
|
|
7514
|
+
`${colors2.cyan}\u{1F4A1} Ch\u1EA1y "jai1 deps upgrade" \u0111\u1EC3 ti\u1EBFn h\xE0nh upgrade.${colors2.reset}
|
|
7515
|
+
`
|
|
7516
|
+
);
|
|
7517
|
+
return;
|
|
7518
|
+
}
|
|
7519
|
+
let selectedPackages;
|
|
7520
|
+
if (options.all) {
|
|
7521
|
+
selectedPackages = upgradablePackages;
|
|
7522
|
+
console.log(`${colors2.cyan}\u{1F4CB} \u0110\xE3 ch\u1ECDn t\u1EA5t c\u1EA3 ${selectedPackages.length} packages${colors2.reset}
|
|
7523
|
+
`);
|
|
7524
|
+
} else {
|
|
7525
|
+
try {
|
|
7526
|
+
const selected = await checkbox3({
|
|
7527
|
+
message: "Ch\u1ECDn packages \u0111\u1EC3 upgrade (ESC \u0111\u1EC3 h\u1EE7y):",
|
|
7528
|
+
choices: upgradablePackages.map((pkg2) => ({
|
|
7529
|
+
name: `${pkg2.name} (${pkg2.current} \u2192 ${pkg2.latestWithPrefix}) [${pkg2.type}]`,
|
|
7530
|
+
value: pkg2.name,
|
|
7531
|
+
checked: true
|
|
7532
|
+
// Mặc định chọn tất cả
|
|
7533
|
+
})),
|
|
7534
|
+
instructions: "\u2191\u2193 navigate \u2022 space select \u2022 a all \u2022 i invert \u2022 \u23CE submit \u2022 esc cancel"
|
|
7535
|
+
});
|
|
7536
|
+
if (selected.length === 0) {
|
|
7537
|
+
console.log(`${colors2.yellow}\u23F8\uFE0F Kh\xF4ng c\xF3 packages n\xE0o \u0111\u01B0\u1EE3c ch\u1ECDn${colors2.reset}
|
|
7538
|
+
`);
|
|
7539
|
+
return;
|
|
7540
|
+
}
|
|
7541
|
+
selectedPackages = upgradablePackages.filter((pkg2) => selected.includes(pkg2.name));
|
|
7542
|
+
} catch {
|
|
7543
|
+
console.log(`
|
|
7544
|
+
${colors2.yellow}\u23F8\uFE0F \u0110\xE3 h\u1EE7y${colors2.reset}
|
|
7545
|
+
`);
|
|
7546
|
+
return;
|
|
7547
|
+
}
|
|
7548
|
+
}
|
|
7549
|
+
let shouldProceed;
|
|
7550
|
+
try {
|
|
7551
|
+
shouldProceed = await confirm4({
|
|
7552
|
+
message: `Ti\u1EBFn h\xE0nh upgrade ${selectedPackages.length} packages?`,
|
|
7553
|
+
default: true
|
|
7554
|
+
});
|
|
7555
|
+
} catch {
|
|
7556
|
+
console.log(`
|
|
7557
|
+
${colors2.yellow}\u23F8\uFE0F \u0110\xE3 h\u1EE7y${colors2.reset}
|
|
7558
|
+
`);
|
|
7559
|
+
return;
|
|
7560
|
+
}
|
|
7561
|
+
if (!shouldProceed) {
|
|
7562
|
+
console.log(`${colors2.yellow}\u23F8\uFE0F Upgrade \u0111\xE3 h\u1EE7y${colors2.reset}
|
|
7563
|
+
`);
|
|
7564
|
+
return;
|
|
7565
|
+
}
|
|
7566
|
+
const pm = await depsService.detectPackageManager(cwd);
|
|
7567
|
+
console.log(`
|
|
7568
|
+
${colors2.cyan}\u{1F527} Package manager: ${pm}${colors2.reset}`);
|
|
7569
|
+
console.log(`${colors2.cyan}\u{1F4E5} \u0110ang upgrade...${colors2.reset}
|
|
7570
|
+
`);
|
|
7571
|
+
const commands = depsService.getUpgradeCommands(selectedPackages, pm);
|
|
7572
|
+
try {
|
|
7573
|
+
if (commands.deps) {
|
|
7574
|
+
console.log(`${colors2.dim}$ ${commands.deps}${colors2.reset}
|
|
7575
|
+
`);
|
|
7576
|
+
depsService.executeUpgrade(commands.deps);
|
|
7577
|
+
}
|
|
7578
|
+
if (commands.devDeps) {
|
|
7579
|
+
console.log(`
|
|
7580
|
+
${colors2.dim}$ ${commands.devDeps}${colors2.reset}
|
|
7581
|
+
`);
|
|
7582
|
+
depsService.executeUpgrade(commands.devDeps);
|
|
7583
|
+
}
|
|
7584
|
+
console.log(
|
|
7585
|
+
`
|
|
7586
|
+
${colors2.green}\u2705 \u0110\xE3 upgrade ${selectedPackages.length} packages th\xE0nh c\xF4ng!${colors2.reset}
|
|
7587
|
+
`
|
|
7588
|
+
);
|
|
7589
|
+
} catch (error) {
|
|
7590
|
+
console.error(`
|
|
7591
|
+
${colors2.red}\u274C L\u1ED7i khi upgrade:${colors2.reset}`);
|
|
7592
|
+
console.error(`${colors2.red}${error.message}${colors2.reset}
|
|
7593
|
+
`);
|
|
7594
|
+
console.log(`${colors2.yellow}\u{1F4A1} B\u1EA1n c\xF3 th\u1EC3 th\u1EED upgrade th\u1EE7 c\xF4ng:${colors2.reset}`);
|
|
7595
|
+
if (commands.deps) console.log(` ${colors2.cyan}${commands.deps}${colors2.reset}`);
|
|
7596
|
+
if (commands.devDeps) console.log(` ${colors2.cyan}${commands.devDeps}${colors2.reset}`);
|
|
7597
|
+
console.log("");
|
|
7598
|
+
process.exit(1);
|
|
7599
|
+
}
|
|
7600
|
+
} catch (error) {
|
|
7601
|
+
console.error(`
|
|
7602
|
+
${colors2.red}\u274C ${error.message}${colors2.reset}
|
|
7603
|
+
`);
|
|
7604
|
+
process.exit(1);
|
|
7605
|
+
}
|
|
7606
|
+
}
|
|
7607
|
+
function isNpmVersion(version) {
|
|
7608
|
+
if (version.startsWith("git") || version.startsWith("github") || version.startsWith("file:") || version.startsWith("link:") || version.startsWith("workspace:") || version.includes("://")) {
|
|
7609
|
+
return false;
|
|
7610
|
+
}
|
|
7611
|
+
return true;
|
|
7612
|
+
}
|
|
7613
|
+
function displayUpgradeTable(packages) {
|
|
7614
|
+
console.log(`${colors2.bold}\u{1F4CA} C\xF3 th\u1EC3 upgrade:${colors2.reset}
|
|
7615
|
+
`);
|
|
7616
|
+
const nameWidth = Math.max(7, ...packages.map((p) => p.name.length));
|
|
7617
|
+
const currentWidth = Math.max(8, ...packages.map((p) => p.current.length));
|
|
7618
|
+
const latestWidth = Math.max(8, ...packages.map((p) => p.latestWithPrefix.length));
|
|
7619
|
+
const header = `\u2502 ${"Package".padEnd(nameWidth)} \u2502 ${"Hi\u1EC7n t\u1EA1i".padEnd(currentWidth)} \u2502 ${"M\u1EDBi nh\u1EA5t".padEnd(latestWidth)} \u2502 Lo\u1EA1i \u2502`;
|
|
7620
|
+
const separator = `\u251C${"\u2500".repeat(nameWidth + 2)}\u253C${"\u2500".repeat(currentWidth + 2)}\u253C${"\u2500".repeat(latestWidth + 2)}\u253C\u2500\u2500\u2500\u2500\u2500\u2500\u2524`;
|
|
7621
|
+
const topBorder = `\u250C${"\u2500".repeat(nameWidth + 2)}\u252C${"\u2500".repeat(currentWidth + 2)}\u252C${"\u2500".repeat(latestWidth + 2)}\u252C\u2500\u2500\u2500\u2500\u2500\u2500\u2510`;
|
|
7622
|
+
const bottomBorder = `\u2514${"\u2500".repeat(nameWidth + 2)}\u2534${"\u2500".repeat(currentWidth + 2)}\u2534${"\u2500".repeat(latestWidth + 2)}\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2518`;
|
|
7623
|
+
console.log(topBorder);
|
|
7624
|
+
console.log(header);
|
|
7625
|
+
console.log(separator);
|
|
7626
|
+
for (const pkg of packages) {
|
|
7627
|
+
const typeLabel = pkg.type === "dep" ? "dep " : "dev ";
|
|
7628
|
+
const typeColor = pkg.type === "dep" ? colors2.cyan : colors2.yellow;
|
|
7629
|
+
console.log(
|
|
7630
|
+
`\u2502 ${pkg.name.padEnd(nameWidth)} \u2502 ${colors2.gray}${pkg.current.padEnd(currentWidth)}${colors2.reset} \u2502 ${colors2.green}${pkg.latestWithPrefix.padEnd(latestWidth)}${colors2.reset} \u2502 ${typeColor}${typeLabel}${colors2.reset}\u2502`
|
|
7631
|
+
);
|
|
7632
|
+
}
|
|
7633
|
+
console.log(bottomBorder);
|
|
7634
|
+
console.log("");
|
|
7635
|
+
}
|
|
7636
|
+
|
|
7637
|
+
// src/commands/deps/index.ts
|
|
7638
|
+
function createDepsCommand() {
|
|
7639
|
+
const depsCommand = new Command30("deps").description("Qu\u1EA3n l\xFD dependencies trong project");
|
|
7640
|
+
depsCommand.addCommand(createDepsUpgradeCommand());
|
|
7641
|
+
return depsCommand;
|
|
7642
|
+
}
|
|
7643
|
+
|
|
7241
7644
|
// src/commands/kit/index.ts
|
|
7242
|
-
import { Command as
|
|
7645
|
+
import { Command as Command34 } from "commander";
|
|
7243
7646
|
|
|
7244
7647
|
// src/commands/kit/list.ts
|
|
7245
|
-
import { Command as
|
|
7648
|
+
import { Command as Command31 } from "commander";
|
|
7246
7649
|
|
|
7247
7650
|
// src/services/starter-kit.service.ts
|
|
7248
|
-
import { promises as
|
|
7651
|
+
import { promises as fs10 } from "fs";
|
|
7249
7652
|
import { join as join4 } from "path";
|
|
7250
7653
|
import AdmZip from "adm-zip";
|
|
7251
7654
|
var StarterKitService = class {
|
|
@@ -7294,22 +7697,22 @@ var StarterKitService = class {
|
|
|
7294
7697
|
}
|
|
7295
7698
|
if (onProgress) onProgress(30);
|
|
7296
7699
|
const tmpDir = join4(process.env.TMPDIR || "/tmp", "jai1-kits");
|
|
7297
|
-
await
|
|
7700
|
+
await fs10.mkdir(tmpDir, { recursive: true });
|
|
7298
7701
|
const tmpFile = join4(tmpDir, `${slug}.zip`);
|
|
7299
7702
|
const buffer = await response.arrayBuffer();
|
|
7300
|
-
await
|
|
7703
|
+
await fs10.writeFile(tmpFile, Buffer.from(buffer));
|
|
7301
7704
|
if (onProgress) onProgress(60);
|
|
7302
7705
|
const zip = new AdmZip(tmpFile);
|
|
7303
|
-
await
|
|
7706
|
+
await fs10.mkdir(targetDir, { recursive: true });
|
|
7304
7707
|
zip.extractAllTo(targetDir, true);
|
|
7305
7708
|
if (onProgress) onProgress(100);
|
|
7306
|
-
await
|
|
7709
|
+
await fs10.unlink(tmpFile);
|
|
7307
7710
|
}
|
|
7308
7711
|
};
|
|
7309
7712
|
|
|
7310
7713
|
// src/commands/kit/list.ts
|
|
7311
7714
|
function createKitListCommand() {
|
|
7312
|
-
return new
|
|
7715
|
+
return new Command31("list").description("List available starter kits").option("-c, --category <category>", "Filter by category (backend, frontend, fullstack)").option("-s, --search <term>", "Search kits by name or description").action(async (options) => {
|
|
7313
7716
|
const configService = new ConfigService();
|
|
7314
7717
|
const config = await configService.load();
|
|
7315
7718
|
if (!config) {
|
|
@@ -7346,9 +7749,9 @@ function createKitListCommand() {
|
|
|
7346
7749
|
}
|
|
7347
7750
|
|
|
7348
7751
|
// src/commands/kit/info.ts
|
|
7349
|
-
import { Command as
|
|
7752
|
+
import { Command as Command32 } from "commander";
|
|
7350
7753
|
function createKitInfoCommand() {
|
|
7351
|
-
return new
|
|
7754
|
+
return new Command32("info").description("Show detailed information about a starter kit").argument("<slug>", "Starter kit slug").action(async (slug) => {
|
|
7352
7755
|
const configService = new ConfigService();
|
|
7353
7756
|
const config = await configService.load();
|
|
7354
7757
|
if (!config) {
|
|
@@ -7397,10 +7800,10 @@ Post-Init Commands:`);
|
|
|
7397
7800
|
}
|
|
7398
7801
|
|
|
7399
7802
|
// src/commands/kit/create.ts
|
|
7400
|
-
import { Command as
|
|
7401
|
-
import { promises as
|
|
7803
|
+
import { Command as Command33 } from "commander";
|
|
7804
|
+
import { promises as fs11 } from "fs";
|
|
7402
7805
|
import { join as join5 } from "path";
|
|
7403
|
-
import { select as select2, input, checkbox as
|
|
7806
|
+
import { select as select2, input, checkbox as checkbox4 } from "@inquirer/prompts";
|
|
7404
7807
|
import { execa as execa2 } from "execa";
|
|
7405
7808
|
|
|
7406
7809
|
// src/services/hook-executor.service.ts
|
|
@@ -7442,7 +7845,7 @@ var HookExecutor = class {
|
|
|
7442
7845
|
|
|
7443
7846
|
// src/commands/kit/create.ts
|
|
7444
7847
|
function createKitCreateCommand() {
|
|
7445
|
-
return new
|
|
7848
|
+
return new Command33("create").description("Create a new project from a starter kit").argument("<slug>", "Starter kit slug").argument("[directory]", "Project directory (default: ./<slug>)").option("-y, --yes", "Auto mode - use defaults, no prompts").option("--name <name>", "Project name").option("--skip-install", "Skip dependency installation").option("--skip-git", "Skip git initialization").option("--skip-framework", "Skip framework apply").option("--skip-ide", "Skip IDE sync").action(async (slug, directory, options) => {
|
|
7446
7849
|
const configService = new ConfigService();
|
|
7447
7850
|
const config = await configService.load();
|
|
7448
7851
|
if (!config) {
|
|
@@ -7464,7 +7867,7 @@ function createKitCreateCommand() {
|
|
|
7464
7867
|
}
|
|
7465
7868
|
const targetDir = directory || join5(process.cwd(), options.name || slug);
|
|
7466
7869
|
try {
|
|
7467
|
-
await
|
|
7870
|
+
await fs11.access(targetDir);
|
|
7468
7871
|
throw new Error(`Directory already exists: ${targetDir}`);
|
|
7469
7872
|
} catch (error) {
|
|
7470
7873
|
if (error.code !== "ENOENT") {
|
|
@@ -7555,7 +7958,7 @@ function createKitCreateCommand() {
|
|
|
7555
7958
|
}
|
|
7556
7959
|
} else {
|
|
7557
7960
|
const defaultTargets = kit.config.ide?.defaultTargets || [];
|
|
7558
|
-
const answer = await
|
|
7961
|
+
const answer = await checkbox4({
|
|
7559
7962
|
message: "Ch\u1ECDn IDE \u0111\u1EC3 sync framework:",
|
|
7560
7963
|
choices: ideChoices.map((c) => ({
|
|
7561
7964
|
...c,
|
|
@@ -7582,7 +7985,7 @@ function createKitCreateCommand() {
|
|
|
7582
7985
|
async function applyVariableSubstitution(dir, variables) {
|
|
7583
7986
|
const files = await getAllFiles(dir);
|
|
7584
7987
|
for (const file of files) {
|
|
7585
|
-
let content = await
|
|
7988
|
+
let content = await fs11.readFile(file, "utf-8");
|
|
7586
7989
|
let modified = false;
|
|
7587
7990
|
for (const [key, value] of Object.entries(variables)) {
|
|
7588
7991
|
const regex = new RegExp(`\\{\\{${key}\\}\\}`, "g");
|
|
@@ -7592,13 +7995,13 @@ async function applyVariableSubstitution(dir, variables) {
|
|
|
7592
7995
|
}
|
|
7593
7996
|
}
|
|
7594
7997
|
if (modified) {
|
|
7595
|
-
await
|
|
7998
|
+
await fs11.writeFile(file, content, "utf-8");
|
|
7596
7999
|
}
|
|
7597
8000
|
}
|
|
7598
8001
|
}
|
|
7599
8002
|
async function getAllFiles(dir) {
|
|
7600
8003
|
const files = [];
|
|
7601
|
-
const entries = await
|
|
8004
|
+
const entries = await fs11.readdir(dir, { withFileTypes: true });
|
|
7602
8005
|
for (const entry of entries) {
|
|
7603
8006
|
const fullPath = join5(dir, entry.name);
|
|
7604
8007
|
if (entry.isDirectory()) {
|
|
@@ -7614,7 +8017,7 @@ async function getAllFiles(dir) {
|
|
|
7614
8017
|
|
|
7615
8018
|
// src/commands/kit/index.ts
|
|
7616
8019
|
function createKitCommand() {
|
|
7617
|
-
const cmd = new
|
|
8020
|
+
const cmd = new Command34("kit").description("Manage starter kits for new projects").action(() => {
|
|
7618
8021
|
cmd.help();
|
|
7619
8022
|
});
|
|
7620
8023
|
cmd.addCommand(createKitListCommand());
|
|
@@ -7624,10 +8027,10 @@ function createKitCommand() {
|
|
|
7624
8027
|
}
|
|
7625
8028
|
|
|
7626
8029
|
// src/commands/upgrade.ts
|
|
7627
|
-
import { Command as
|
|
7628
|
-
import { confirm as
|
|
7629
|
-
import { execSync } from "child_process";
|
|
7630
|
-
var
|
|
8030
|
+
import { Command as Command35 } from "commander";
|
|
8031
|
+
import { confirm as confirm5 } from "@inquirer/prompts";
|
|
8032
|
+
import { execSync as execSync2 } from "child_process";
|
|
8033
|
+
var colors3 = {
|
|
7631
8034
|
yellow: "\x1B[33m",
|
|
7632
8035
|
green: "\x1B[32m",
|
|
7633
8036
|
cyan: "\x1B[36m",
|
|
@@ -7636,7 +8039,7 @@ var colors2 = {
|
|
|
7636
8039
|
bold: "\x1B[1m"
|
|
7637
8040
|
};
|
|
7638
8041
|
function createUpgradeCommand() {
|
|
7639
|
-
return new
|
|
8042
|
+
return new Command35("upgrade").description("Upgrade jai1-client to the latest version").option("--check", "Only check for updates without installing").option("--force", "Force upgrade without confirmation").action(async (options) => {
|
|
7640
8043
|
await handleUpgrade(options);
|
|
7641
8044
|
});
|
|
7642
8045
|
}
|
|
@@ -7647,7 +8050,7 @@ async function handleUpgrade(options) {
|
|
|
7647
8050
|
throw new ValidationError('Not initialized. Run "jai1 auth" first.');
|
|
7648
8051
|
}
|
|
7649
8052
|
try {
|
|
7650
|
-
console.log(`${
|
|
8053
|
+
console.log(`${colors3.cyan}\u{1F50D} Checking for updates...${colors3.reset}`);
|
|
7651
8054
|
const response = await fetch(`${config.apiUrl}/api/versions/client`, {
|
|
7652
8055
|
headers: {
|
|
7653
8056
|
"JAI1-Access-Key": config.accessKey
|
|
@@ -7662,47 +8065,47 @@ async function handleUpgrade(options) {
|
|
|
7662
8065
|
const latestVersion = data.version;
|
|
7663
8066
|
const currentVersion = package_default.version;
|
|
7664
8067
|
console.log(`
|
|
7665
|
-
${
|
|
7666
|
-
console.log(`${
|
|
8068
|
+
${colors3.bold}Current version:${colors3.reset} ${currentVersion}`);
|
|
8069
|
+
console.log(`${colors3.bold}Latest version:${colors3.reset} ${latestVersion}
|
|
7667
8070
|
`);
|
|
7668
8071
|
if (!isNewerVersion2(latestVersion, currentVersion)) {
|
|
7669
|
-
console.log(`${
|
|
8072
|
+
console.log(`${colors3.green}\u2705 You're already on the latest version!${colors3.reset}
|
|
7670
8073
|
`);
|
|
7671
8074
|
return;
|
|
7672
8075
|
}
|
|
7673
|
-
console.log(`${
|
|
7674
|
-
console.log(`${
|
|
7675
|
-
console.log(`${
|
|
8076
|
+
console.log(`${colors3.yellow}\u256D\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u256E${colors3.reset}`);
|
|
8077
|
+
console.log(`${colors3.yellow}\u2502${colors3.reset} ${colors3.bold}\u2B06\uFE0F Update available!${colors3.reset} ${currentVersion} \u2192 ${colors3.cyan}${latestVersion}${colors3.reset} ${colors3.yellow}\u2502${colors3.reset}`);
|
|
8078
|
+
console.log(`${colors3.yellow}\u2570\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u256F${colors3.reset}
|
|
7676
8079
|
`);
|
|
7677
8080
|
if (options.check) {
|
|
7678
|
-
console.log(`${
|
|
8081
|
+
console.log(`${colors3.cyan}Run "jai1 upgrade" to install the latest version.${colors3.reset}
|
|
7679
8082
|
`);
|
|
7680
8083
|
return;
|
|
7681
8084
|
}
|
|
7682
8085
|
if (!options.force) {
|
|
7683
|
-
const shouldUpdate = await
|
|
8086
|
+
const shouldUpdate = await confirm5({
|
|
7684
8087
|
message: "Update to the latest version now?",
|
|
7685
8088
|
default: true
|
|
7686
8089
|
});
|
|
7687
8090
|
if (!shouldUpdate) {
|
|
7688
|
-
console.log(`${
|
|
8091
|
+
console.log(`${colors3.yellow}\u23F8\uFE0F Upgrade cancelled.${colors3.reset}
|
|
7689
8092
|
`);
|
|
7690
8093
|
return;
|
|
7691
8094
|
}
|
|
7692
8095
|
}
|
|
7693
8096
|
console.log(`
|
|
7694
|
-
${
|
|
8097
|
+
${colors3.cyan}\u{1F4E5} Installing latest version...${colors3.reset}
|
|
7695
8098
|
`);
|
|
7696
8099
|
try {
|
|
7697
8100
|
const packageManager2 = detectPackageManager();
|
|
7698
8101
|
const installCommand = getInstallCommand(packageManager2);
|
|
7699
|
-
console.log(`${
|
|
7700
|
-
|
|
8102
|
+
console.log(`${colors3.cyan}Using ${packageManager2}...${colors3.reset}`);
|
|
8103
|
+
execSync2(installCommand, {
|
|
7701
8104
|
stdio: "inherit",
|
|
7702
8105
|
env: { ...process.env, FORCE_COLOR: "1" }
|
|
7703
8106
|
});
|
|
7704
8107
|
console.log(`
|
|
7705
|
-
${
|
|
8108
|
+
${colors3.green}\u2705 Successfully upgraded to version ${latestVersion}!${colors3.reset}
|
|
7706
8109
|
`);
|
|
7707
8110
|
trackAction("upgrade", {
|
|
7708
8111
|
from_version: currentVersion,
|
|
@@ -7712,17 +8115,17 @@ ${colors2.green}\u2705 Successfully upgraded to version ${latestVersion}!${color
|
|
|
7712
8115
|
disableUpdateCheck();
|
|
7713
8116
|
} catch (error) {
|
|
7714
8117
|
console.error(`
|
|
7715
|
-
${
|
|
7716
|
-
console.error(`${
|
|
8118
|
+
${colors3.red}\u274C Upgrade failed!${colors3.reset}`);
|
|
8119
|
+
console.error(`${colors3.red}Error: ${error instanceof Error ? error.message : "Unknown error"}${colors3.reset}
|
|
7717
8120
|
`);
|
|
7718
|
-
console.error(`${
|
|
8121
|
+
console.error(`${colors3.yellow}\u{1F4A1} You can try manually upgrading with:${colors3.reset}`);
|
|
7719
8122
|
const manualCommands = {
|
|
7720
8123
|
npm: `npm install -g @jvittechs/jai1-cli@latest`,
|
|
7721
8124
|
pnpm: `pnpm add -g @jvittechs/jai1-cli@latest`,
|
|
7722
8125
|
yarn: `yarn global add @jvittechs/jai1-cli@latest`,
|
|
7723
8126
|
bun: `bun add -g @jvittechs/jai1-cli@latest`
|
|
7724
8127
|
};
|
|
7725
|
-
console.error(` ${
|
|
8128
|
+
console.error(` ${colors3.cyan}${manualCommands[packageManager]}${colors3.reset}
|
|
7726
8129
|
`);
|
|
7727
8130
|
throw error;
|
|
7728
8131
|
}
|
|
@@ -7746,7 +8149,7 @@ function isNewerVersion2(remote, local) {
|
|
|
7746
8149
|
}
|
|
7747
8150
|
function detectPackageManager() {
|
|
7748
8151
|
try {
|
|
7749
|
-
const jai1Path =
|
|
8152
|
+
const jai1Path = execSync2("which jai1 || where jai1", {
|
|
7750
8153
|
encoding: "utf-8",
|
|
7751
8154
|
stdio: ["pipe", "pipe", "ignore"]
|
|
7752
8155
|
}).trim();
|
|
@@ -7784,11 +8187,11 @@ function getInstallCommand(packageManager2) {
|
|
|
7784
8187
|
}
|
|
7785
8188
|
|
|
7786
8189
|
// src/commands/clean.ts
|
|
7787
|
-
import { Command as
|
|
7788
|
-
import { confirm as
|
|
8190
|
+
import { Command as Command36 } from "commander";
|
|
8191
|
+
import { confirm as confirm6, select as select3 } from "@inquirer/prompts";
|
|
7789
8192
|
import { join as join6 } from "path";
|
|
7790
8193
|
function createCleanCommand() {
|
|
7791
|
-
return new
|
|
8194
|
+
return new Command36("clean").description("Clean up backups, cache, and temporary files").option("-y, --yes", "Skip confirmation").option("--backups", "Clean only backup files").option("--all", "Clean all (backups + cache)").action(async (options) => {
|
|
7792
8195
|
await handleClean(options);
|
|
7793
8196
|
});
|
|
7794
8197
|
}
|
|
@@ -7883,7 +8286,7 @@ async function cleanTarget(target, skipConfirm) {
|
|
|
7883
8286
|
}
|
|
7884
8287
|
const countStr = info.count ? ` (${info.count} items)` : "";
|
|
7885
8288
|
if (!skipConfirm) {
|
|
7886
|
-
const confirmed = await
|
|
8289
|
+
const confirmed = await confirm6({
|
|
7887
8290
|
message: `Delete ${target.name}${countStr}?`,
|
|
7888
8291
|
default: false
|
|
7889
8292
|
});
|
|
@@ -7901,7 +8304,7 @@ async function cleanTarget(target, skipConfirm) {
|
|
|
7901
8304
|
}
|
|
7902
8305
|
|
|
7903
8306
|
// src/commands/redmine/check.ts
|
|
7904
|
-
import { Command as
|
|
8307
|
+
import { Command as Command37 } from "commander";
|
|
7905
8308
|
|
|
7906
8309
|
// src/services/redmine-config.service.ts
|
|
7907
8310
|
import { readFile as readFile6 } from "fs/promises";
|
|
@@ -8002,7 +8405,7 @@ var RedmineConfigService = class {
|
|
|
8002
8405
|
// src/api.ts
|
|
8003
8406
|
import { fetch as fetch2 } from "undici";
|
|
8004
8407
|
import pRetry2 from "p-retry";
|
|
8005
|
-
import
|
|
8408
|
+
import pLimit3 from "p-limit";
|
|
8006
8409
|
var RedmineApiError = class extends Error {
|
|
8007
8410
|
constructor(message, status, response) {
|
|
8008
8411
|
super(message);
|
|
@@ -8020,10 +8423,10 @@ var RedmineApiClient = class {
|
|
|
8020
8423
|
this.baseUrl = config.baseUrl.replace(/\/$/, "");
|
|
8021
8424
|
this.apiAccessToken = config.apiAccessToken;
|
|
8022
8425
|
this.retryConfig = config.defaults.retry;
|
|
8023
|
-
this.concurrencyLimit =
|
|
8426
|
+
this.concurrencyLimit = pLimit3(config.defaults.concurrency);
|
|
8024
8427
|
}
|
|
8025
|
-
async request(
|
|
8026
|
-
const url = `${this.baseUrl}${
|
|
8428
|
+
async request(path8, options = {}) {
|
|
8429
|
+
const url = `${this.baseUrl}${path8}`;
|
|
8027
8430
|
const headers = {
|
|
8028
8431
|
"X-Redmine-API-Key": this.apiAccessToken,
|
|
8029
8432
|
"Content-Type": "application/json",
|
|
@@ -8084,8 +8487,8 @@ var RedmineApiClient = class {
|
|
|
8084
8487
|
if (include && include.length > 0) {
|
|
8085
8488
|
params.append("include", include.join(","));
|
|
8086
8489
|
}
|
|
8087
|
-
const
|
|
8088
|
-
return this.request(
|
|
8490
|
+
const path8 = `/issues/${issueId}.json${params.toString() ? `?${params.toString()}` : ""}`;
|
|
8491
|
+
return this.request(path8);
|
|
8089
8492
|
}
|
|
8090
8493
|
async getIssues(projectId, options = {}) {
|
|
8091
8494
|
const params = new URLSearchParams();
|
|
@@ -8105,8 +8508,8 @@ var RedmineApiClient = class {
|
|
|
8105
8508
|
if (options.updatedSince) {
|
|
8106
8509
|
params.append("updated_on", `>=${options.updatedSince}`);
|
|
8107
8510
|
}
|
|
8108
|
-
const
|
|
8109
|
-
return this.request(
|
|
8511
|
+
const path8 = `/issues.json?${params.toString()}`;
|
|
8512
|
+
return this.request(path8);
|
|
8110
8513
|
}
|
|
8111
8514
|
async getAllIssues(projectId, options = {}) {
|
|
8112
8515
|
const pageSize = options.pageSize || 100;
|
|
@@ -8208,7 +8611,7 @@ async function checkConnectivity(config) {
|
|
|
8208
8611
|
|
|
8209
8612
|
// src/commands/redmine/check.ts
|
|
8210
8613
|
function createRedmineCheckCommand() {
|
|
8211
|
-
const cmd = new
|
|
8614
|
+
const cmd = new Command37("check").description("Check Redmine connectivity").option("-c, --config <path>", "Config file path", "redmine.config.yaml").option("--json", "Output as JSON").action(async (options) => {
|
|
8212
8615
|
await handleRedmineCheck(options);
|
|
8213
8616
|
});
|
|
8214
8617
|
return cmd;
|
|
@@ -8236,7 +8639,7 @@ async function handleRedmineCheck(options) {
|
|
|
8236
8639
|
}
|
|
8237
8640
|
|
|
8238
8641
|
// src/commands/redmine/sync-issue.ts
|
|
8239
|
-
import { Command as
|
|
8642
|
+
import { Command as Command38 } from "commander";
|
|
8240
8643
|
|
|
8241
8644
|
// src/sync-issue.ts
|
|
8242
8645
|
import { resolve as resolve3, relative } from "path";
|
|
@@ -8612,7 +9015,7 @@ function extractIssueIdFromUrl(url) {
|
|
|
8612
9015
|
|
|
8613
9016
|
// src/commands/redmine/sync-issue.ts
|
|
8614
9017
|
function createSyncIssueCommand() {
|
|
8615
|
-
const cmd = new
|
|
9018
|
+
const cmd = new Command38("issue").description("Sync a single issue").option("-i, --id <number>", "Issue ID").option("-u, --url <url>", "Issue URL").option("--dry-run", "Preview without making changes").option("-c, --config <path>", "Config file path").option("-o, --output-dir <path>", "Output directory").option("--json", "Output as JSON").action(async (options) => {
|
|
8616
9019
|
await handleSyncIssue(options);
|
|
8617
9020
|
});
|
|
8618
9021
|
return cmd;
|
|
@@ -8656,7 +9059,7 @@ async function handleSyncIssue(options) {
|
|
|
8656
9059
|
}
|
|
8657
9060
|
|
|
8658
9061
|
// src/commands/redmine/sync-project.ts
|
|
8659
|
-
import { Command as
|
|
9062
|
+
import { Command as Command39 } from "commander";
|
|
8660
9063
|
|
|
8661
9064
|
// src/sync-project.ts
|
|
8662
9065
|
async function syncProject(config, options = {}) {
|
|
@@ -8726,7 +9129,7 @@ async function syncProject(config, options = {}) {
|
|
|
8726
9129
|
|
|
8727
9130
|
// src/commands/redmine/sync-project.ts
|
|
8728
9131
|
function createSyncProjectCommand() {
|
|
8729
|
-
const cmd = new
|
|
9132
|
+
const cmd = new Command39("project").description("Sync all issues in a project").option("-s, --status <status>", "Filter by status (default: *)", "*").option("--updated-since <date>", "Only sync issues updated since YYYY-MM-DD").option("--concurrency <number>", "Number of concurrent requests").option("--page-size <number>", "Page size for API requests").option("--dry-run", "Preview without making changes").option("-c, --config <path>", "Config file path").option("-o, --output-dir <path>", "Output directory").option("--json", "Output as JSON").action(async (options) => {
|
|
8730
9133
|
await handleSyncProject(options);
|
|
8731
9134
|
});
|
|
8732
9135
|
return cmd;
|
|
@@ -8781,12 +9184,12 @@ async function handleSyncProject(options) {
|
|
|
8781
9184
|
}
|
|
8782
9185
|
|
|
8783
9186
|
// src/commands/framework/info.ts
|
|
8784
|
-
import { Command as
|
|
8785
|
-
import { promises as
|
|
9187
|
+
import { Command as Command40 } from "commander";
|
|
9188
|
+
import { promises as fs12 } from "fs";
|
|
8786
9189
|
import { join as join7 } from "path";
|
|
8787
9190
|
import { homedir as homedir5 } from "os";
|
|
8788
9191
|
function createInfoCommand() {
|
|
8789
|
-
const cmd = new
|
|
9192
|
+
const cmd = new Command40("info").description("Show jai1-client configuration and status").option("--json", "Output as JSON").option("--verbose", "Show detailed information").action(async (options) => {
|
|
8790
9193
|
await handleInfo(options);
|
|
8791
9194
|
});
|
|
8792
9195
|
return cmd;
|
|
@@ -8834,7 +9237,7 @@ function maskKey3(key) {
|
|
|
8834
9237
|
async function getProjectStatus2() {
|
|
8835
9238
|
const projectJai1 = join7(process.cwd(), ".jai1");
|
|
8836
9239
|
try {
|
|
8837
|
-
await
|
|
9240
|
+
await fs12.access(projectJai1);
|
|
8838
9241
|
return { exists: true, version: "Synced" };
|
|
8839
9242
|
} catch {
|
|
8840
9243
|
return { exists: false };
|
|
@@ -8842,10 +9245,10 @@ async function getProjectStatus2() {
|
|
|
8842
9245
|
}
|
|
8843
9246
|
|
|
8844
9247
|
// src/commands/self-update.ts
|
|
8845
|
-
import { Command as
|
|
8846
|
-
import { confirm as
|
|
8847
|
-
import { execSync as
|
|
8848
|
-
var
|
|
9248
|
+
import { Command as Command41 } from "commander";
|
|
9249
|
+
import { confirm as confirm7 } from "@inquirer/prompts";
|
|
9250
|
+
import { execSync as execSync3 } from "child_process";
|
|
9251
|
+
var colors4 = {
|
|
8849
9252
|
yellow: "\x1B[33m",
|
|
8850
9253
|
green: "\x1B[32m",
|
|
8851
9254
|
cyan: "\x1B[36m",
|
|
@@ -8854,7 +9257,7 @@ var colors3 = {
|
|
|
8854
9257
|
bold: "\x1B[1m"
|
|
8855
9258
|
};
|
|
8856
9259
|
function createSelfUpdateCommand() {
|
|
8857
|
-
return new
|
|
9260
|
+
return new Command41("self-update").description("Update jai1-client to the latest version").option("--check", "Only check for updates without installing").option("--force", "Force update without confirmation").action(async (options) => {
|
|
8858
9261
|
await handleSelfUpdate(options);
|
|
8859
9262
|
});
|
|
8860
9263
|
}
|
|
@@ -8865,7 +9268,7 @@ async function handleSelfUpdate(options) {
|
|
|
8865
9268
|
throw new ValidationError('Not initialized. Run "jai1 auth" first.');
|
|
8866
9269
|
}
|
|
8867
9270
|
try {
|
|
8868
|
-
console.log(`${
|
|
9271
|
+
console.log(`${colors4.cyan}\u{1F50D} Checking for updates...${colors4.reset}`);
|
|
8869
9272
|
const response = await fetch(`${config.apiUrl}/api/versions/client`, {
|
|
8870
9273
|
headers: {
|
|
8871
9274
|
"JAI1-Access-Key": config.accessKey
|
|
@@ -8880,47 +9283,47 @@ async function handleSelfUpdate(options) {
|
|
|
8880
9283
|
const latestVersion = data.version;
|
|
8881
9284
|
const currentVersion = package_default.version;
|
|
8882
9285
|
console.log(`
|
|
8883
|
-
${
|
|
8884
|
-
console.log(`${
|
|
9286
|
+
${colors4.bold}Current version:${colors4.reset} ${currentVersion}`);
|
|
9287
|
+
console.log(`${colors4.bold}Latest version:${colors4.reset} ${latestVersion}
|
|
8885
9288
|
`);
|
|
8886
9289
|
if (!isNewerVersion3(latestVersion, currentVersion)) {
|
|
8887
|
-
console.log(`${
|
|
9290
|
+
console.log(`${colors4.green}\u2705 You're already on the latest version!${colors4.reset}
|
|
8888
9291
|
`);
|
|
8889
9292
|
return;
|
|
8890
9293
|
}
|
|
8891
|
-
console.log(`${
|
|
8892
|
-
console.log(`${
|
|
8893
|
-
console.log(`${
|
|
9294
|
+
console.log(`${colors4.yellow}\u256D\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u256E${colors4.reset}`);
|
|
9295
|
+
console.log(`${colors4.yellow}\u2502${colors4.reset} ${colors4.bold}\u2B06\uFE0F Update available!${colors4.reset} ${currentVersion} \u2192 ${colors4.cyan}${latestVersion}${colors4.reset} ${colors4.yellow}\u2502${colors4.reset}`);
|
|
9296
|
+
console.log(`${colors4.yellow}\u2570\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u256F${colors4.reset}
|
|
8894
9297
|
`);
|
|
8895
9298
|
if (options.check) {
|
|
8896
|
-
console.log(`${
|
|
9299
|
+
console.log(`${colors4.cyan}Run "jai1 self-update" to install the latest version.${colors4.reset}
|
|
8897
9300
|
`);
|
|
8898
9301
|
return;
|
|
8899
9302
|
}
|
|
8900
9303
|
if (!options.force) {
|
|
8901
|
-
const shouldUpdate = await
|
|
9304
|
+
const shouldUpdate = await confirm7({
|
|
8902
9305
|
message: "Update to the latest version now?",
|
|
8903
9306
|
default: true
|
|
8904
9307
|
});
|
|
8905
9308
|
if (!shouldUpdate) {
|
|
8906
|
-
console.log(`${
|
|
9309
|
+
console.log(`${colors4.yellow}\u23F8\uFE0F Update cancelled.${colors4.reset}
|
|
8907
9310
|
`);
|
|
8908
9311
|
return;
|
|
8909
9312
|
}
|
|
8910
9313
|
}
|
|
8911
9314
|
console.log(`
|
|
8912
|
-
${
|
|
9315
|
+
${colors4.cyan}\u{1F4E5} Installing latest version...${colors4.reset}
|
|
8913
9316
|
`);
|
|
8914
9317
|
try {
|
|
8915
9318
|
const packageManager2 = detectPackageManager2();
|
|
8916
9319
|
const installCommand = getInstallCommand2(packageManager2);
|
|
8917
|
-
console.log(`${
|
|
8918
|
-
|
|
9320
|
+
console.log(`${colors4.cyan}Using ${packageManager2}...${colors4.reset}`);
|
|
9321
|
+
execSync3(installCommand, {
|
|
8919
9322
|
stdio: "inherit",
|
|
8920
9323
|
env: { ...process.env, FORCE_COLOR: "1" }
|
|
8921
9324
|
});
|
|
8922
9325
|
console.log(`
|
|
8923
|
-
${
|
|
9326
|
+
${colors4.green}\u2705 Successfully updated to version ${latestVersion}!${colors4.reset}
|
|
8924
9327
|
`);
|
|
8925
9328
|
trackAction("self_update", {
|
|
8926
9329
|
from_version: currentVersion,
|
|
@@ -8930,11 +9333,11 @@ ${colors3.green}\u2705 Successfully updated to version ${latestVersion}!${colors
|
|
|
8930
9333
|
disableUpdateCheck();
|
|
8931
9334
|
} catch (error) {
|
|
8932
9335
|
console.error(`
|
|
8933
|
-
${
|
|
8934
|
-
console.error(`${
|
|
9336
|
+
${colors4.red}\u274C Update failed!${colors4.reset}`);
|
|
9337
|
+
console.error(`${colors4.red}Error: ${error instanceof Error ? error.message : "Unknown error"}${colors4.reset}
|
|
8935
9338
|
`);
|
|
8936
|
-
console.error(`${
|
|
8937
|
-
console.error(` ${
|
|
9339
|
+
console.error(`${colors4.yellow}\u{1F4A1} You can try manually updating with:${colors4.reset}`);
|
|
9340
|
+
console.error(` ${colors4.cyan}npm install -g @jvittechs/jai1-cli@latest${colors4.reset}
|
|
8938
9341
|
`);
|
|
8939
9342
|
throw error;
|
|
8940
9343
|
}
|
|
@@ -8962,17 +9365,17 @@ function detectPackageManager2() {
|
|
|
8962
9365
|
if (userAgent.includes("yarn")) return "yarn";
|
|
8963
9366
|
if (userAgent.includes("bun")) return "bun";
|
|
8964
9367
|
try {
|
|
8965
|
-
|
|
9368
|
+
execSync3("pnpm --version", { stdio: "ignore" });
|
|
8966
9369
|
return "pnpm";
|
|
8967
9370
|
} catch {
|
|
8968
9371
|
}
|
|
8969
9372
|
try {
|
|
8970
|
-
|
|
9373
|
+
execSync3("yarn --version", { stdio: "ignore" });
|
|
8971
9374
|
return "yarn";
|
|
8972
9375
|
} catch {
|
|
8973
9376
|
}
|
|
8974
9377
|
try {
|
|
8975
|
-
|
|
9378
|
+
execSync3("bun --version", { stdio: "ignore" });
|
|
8976
9379
|
return "bun";
|
|
8977
9380
|
} catch {
|
|
8978
9381
|
}
|
|
@@ -8994,10 +9397,10 @@ function getInstallCommand2(packageManager2) {
|
|
|
8994
9397
|
}
|
|
8995
9398
|
|
|
8996
9399
|
// src/commands/clear-backups.ts
|
|
8997
|
-
import { Command as
|
|
8998
|
-
import { confirm as
|
|
9400
|
+
import { Command as Command42 } from "commander";
|
|
9401
|
+
import { confirm as confirm8 } from "@inquirer/prompts";
|
|
8999
9402
|
function createClearBackupsCommand() {
|
|
9000
|
-
return new
|
|
9403
|
+
return new Command42("clear-backups").description("Clear backup files").option("-y, --yes", "Skip confirmation").action(async (options) => {
|
|
9001
9404
|
const service = new ComponentsService();
|
|
9002
9405
|
const backups = await service.listBackups(process.cwd());
|
|
9003
9406
|
if (backups.length === 0) {
|
|
@@ -9013,7 +9416,7 @@ function createClearBackupsCommand() {
|
|
|
9013
9416
|
}
|
|
9014
9417
|
console.log();
|
|
9015
9418
|
if (!options.yes) {
|
|
9016
|
-
const ok = await
|
|
9419
|
+
const ok = await confirm8({ message: "Delete all backups?", default: false });
|
|
9017
9420
|
if (!ok) return;
|
|
9018
9421
|
}
|
|
9019
9422
|
await service.clearBackups(process.cwd());
|
|
@@ -9022,10 +9425,10 @@ function createClearBackupsCommand() {
|
|
|
9022
9425
|
}
|
|
9023
9426
|
|
|
9024
9427
|
// src/commands/vscode/index.ts
|
|
9025
|
-
import { Command as
|
|
9026
|
-
import { checkbox as
|
|
9027
|
-
import
|
|
9028
|
-
import
|
|
9428
|
+
import { Command as Command43 } from "commander";
|
|
9429
|
+
import { checkbox as checkbox5, confirm as confirm9, select as select4 } from "@inquirer/prompts";
|
|
9430
|
+
import fs13 from "fs/promises";
|
|
9431
|
+
import path7 from "path";
|
|
9029
9432
|
import { existsSync as existsSync3 } from "fs";
|
|
9030
9433
|
var PERFORMANCE_GROUPS2 = {
|
|
9031
9434
|
telemetry: {
|
|
@@ -9162,7 +9565,7 @@ var PERFORMANCE_GROUPS2 = {
|
|
|
9162
9565
|
}
|
|
9163
9566
|
};
|
|
9164
9567
|
function createVSCodeCommand() {
|
|
9165
|
-
const vscodeCommand = new
|
|
9568
|
+
const vscodeCommand = new Command43("vscode").description("Qu\u1EA3n l\xFD c\xE0i \u0111\u1EB7t VSCode cho d\u1EF1 \xE1n hi\u1EC7n t\u1EA1i");
|
|
9166
9569
|
vscodeCommand.action(async () => {
|
|
9167
9570
|
await interactiveMode2();
|
|
9168
9571
|
});
|
|
@@ -9230,7 +9633,7 @@ async function selectGroupsToApply2(action) {
|
|
|
9230
9633
|
value: key
|
|
9231
9634
|
}));
|
|
9232
9635
|
try {
|
|
9233
|
-
const selectedGroups = await
|
|
9636
|
+
const selectedGroups = await checkbox5({
|
|
9234
9637
|
message: `Ch\u1ECDn c\xE1c nh\xF3m \u0111\u1EC3 ${action === "enable" ? "enable" : "disable"} (SPACE \u0111\u1EC3 ch\u1ECDn, ENTER \u0111\u1EC3 x\xE1c nh\u1EADn):`,
|
|
9235
9638
|
choices
|
|
9236
9639
|
});
|
|
@@ -9245,8 +9648,8 @@ async function selectGroupsToApply2(action) {
|
|
|
9245
9648
|
}
|
|
9246
9649
|
}
|
|
9247
9650
|
async function applyGroups2(groupKeys, action) {
|
|
9248
|
-
const vscodeDir =
|
|
9249
|
-
const settingsPath =
|
|
9651
|
+
const vscodeDir = path7.join(process.cwd(), ".vscode");
|
|
9652
|
+
const settingsPath = path7.join(vscodeDir, "settings.json");
|
|
9250
9653
|
const invalidGroups = groupKeys.filter((key) => !PERFORMANCE_GROUPS2[key]);
|
|
9251
9654
|
if (invalidGroups.length > 0) {
|
|
9252
9655
|
console.log(`
|
|
@@ -9255,18 +9658,18 @@ async function applyGroups2(groupKeys, action) {
|
|
|
9255
9658
|
return;
|
|
9256
9659
|
}
|
|
9257
9660
|
if (!existsSync3(vscodeDir)) {
|
|
9258
|
-
await
|
|
9661
|
+
await fs13.mkdir(vscodeDir, { recursive: true });
|
|
9259
9662
|
console.log("\u{1F4C1} \u0110\xE3 t\u1EA1o th\u01B0 m\u1EE5c .vscode/");
|
|
9260
9663
|
}
|
|
9261
9664
|
let currentSettings = {};
|
|
9262
9665
|
if (existsSync3(settingsPath)) {
|
|
9263
9666
|
try {
|
|
9264
|
-
const content = await
|
|
9667
|
+
const content = await fs13.readFile(settingsPath, "utf-8");
|
|
9265
9668
|
currentSettings = JSON.parse(content);
|
|
9266
9669
|
console.log("\u{1F4C4} \u0110\xE3 \u0111\u1ECDc c\xE0i \u0111\u1EB7t hi\u1EC7n t\u1EA1i t\u1EEB settings.json");
|
|
9267
9670
|
} catch {
|
|
9268
9671
|
console.warn("\u26A0\uFE0F Kh\xF4ng th\u1EC3 \u0111\u1ECDc settings.json (c\xF3 th\u1EC3 ch\u1EE9a comments).");
|
|
9269
|
-
const confirmOverwrite = await
|
|
9672
|
+
const confirmOverwrite = await confirm9({
|
|
9270
9673
|
message: "Ghi \u0111\xE8 file settings.json hi\u1EC7n t\u1EA1i?",
|
|
9271
9674
|
default: false
|
|
9272
9675
|
});
|
|
@@ -9301,19 +9704,19 @@ async function applyGroups2(groupKeys, action) {
|
|
|
9301
9704
|
}
|
|
9302
9705
|
}
|
|
9303
9706
|
}
|
|
9304
|
-
await
|
|
9707
|
+
await fs13.writeFile(settingsPath, JSON.stringify(newSettings, null, 2));
|
|
9305
9708
|
console.log(`
|
|
9306
9709
|
\u2705 \u0110\xE3 c\u1EADp nh\u1EADt c\xE0i \u0111\u1EB7t VSCode t\u1EA1i: ${settingsPath}`);
|
|
9307
9710
|
console.log("\u{1F4A1} M\u1EB9o: Kh\u1EDFi \u0111\u1ED9ng l\u1EA1i VSCode \u0111\u1EC3 \xE1p d\u1EE5ng c\xE1c thay \u0111\u1ED5i.");
|
|
9308
9711
|
}
|
|
9309
9712
|
async function resetSettings2(groupKeys) {
|
|
9310
|
-
const vscodeDir =
|
|
9311
|
-
const settingsPath =
|
|
9713
|
+
const vscodeDir = path7.join(process.cwd(), ".vscode");
|
|
9714
|
+
const settingsPath = path7.join(vscodeDir, "settings.json");
|
|
9312
9715
|
if (!existsSync3(settingsPath)) {
|
|
9313
9716
|
console.log("\n\u26A0\uFE0F Kh\xF4ng t\xECm th\u1EA5y file settings.json");
|
|
9314
9717
|
return;
|
|
9315
9718
|
}
|
|
9316
|
-
const confirmReset = await
|
|
9719
|
+
const confirmReset = await confirm9({
|
|
9317
9720
|
message: groupKeys.length === 0 ? "Reset T\u1EA4T C\u1EA2 settings v\u1EC1 m\u1EB7c \u0111\u1ECBnh (x\xF3a to\xE0n b\u1ED9 file)?" : `Reset c\xE1c nh\xF3m: ${groupKeys.join(", ")}?`,
|
|
9318
9721
|
default: false
|
|
9319
9722
|
});
|
|
@@ -9322,7 +9725,7 @@ async function resetSettings2(groupKeys) {
|
|
|
9322
9725
|
return;
|
|
9323
9726
|
}
|
|
9324
9727
|
if (groupKeys.length === 0) {
|
|
9325
|
-
await
|
|
9728
|
+
await fs13.unlink(settingsPath);
|
|
9326
9729
|
console.log("\n\u2705 \u0110\xE3 x\xF3a file settings.json");
|
|
9327
9730
|
} else {
|
|
9328
9731
|
await applyGroups2(groupKeys, "disable");
|
|
@@ -9333,9 +9736,9 @@ async function resetSettings2(groupKeys) {
|
|
|
9333
9736
|
// src/commands/guide.ts
|
|
9334
9737
|
import React40 from "react";
|
|
9335
9738
|
import { render as render6 } from "ink";
|
|
9336
|
-
import { Command as
|
|
9739
|
+
import { Command as Command44 } from "commander";
|
|
9337
9740
|
function createGuideCommand() {
|
|
9338
|
-
const cmd = new
|
|
9741
|
+
const cmd = new Command44("guide").description("Interactive guide center for Agentic Coding").option("--topic <topic>", "Open specific topic (intro, rules, workflows, prompts, skills)").action(async (options) => {
|
|
9339
9742
|
const { waitUntilExit } = render6(
|
|
9340
9743
|
React40.createElement(GuideApp, {
|
|
9341
9744
|
initialTopic: options.topic,
|
|
@@ -9352,9 +9755,9 @@ function createGuideCommand() {
|
|
|
9352
9755
|
// src/commands/context.ts
|
|
9353
9756
|
import React41 from "react";
|
|
9354
9757
|
import { render as render7 } from "ink";
|
|
9355
|
-
import { Command as
|
|
9758
|
+
import { Command as Command45 } from "commander";
|
|
9356
9759
|
function createContextCommand() {
|
|
9357
|
-
const cmd = new
|
|
9760
|
+
const cmd = new Command45("context").description("Kh\xE1m ph\xE1 v\xE0 qu\u1EA3n l\xFD context d\u1EF1 \xE1n cho c\xE1c IDE").option("--ide <ide>", "M\u1EDF tr\u1EF1c ti\u1EBFp IDE c\u1EE5 th\u1EC3 (cursor, windsurf, antigravity, jai1)").option("--type <type>", "Hi\u1EC3n th\u1ECB lo\u1EA1i context c\u1EE5 th\u1EC3 (rules, workflows, skills, agents, prompts)").option("--stats", "Hi\u1EC3n th\u1ECB th\u1ED1ng k\xEA context (non-interactive)").action(async (options) => {
|
|
9358
9761
|
let initialIDE;
|
|
9359
9762
|
if (options.ide) {
|
|
9360
9763
|
const validIDEs = ["cursor", "windsurf", "antigravity", "jai1"];
|
|
@@ -9431,10 +9834,10 @@ async function printStats2() {
|
|
|
9431
9834
|
}
|
|
9432
9835
|
|
|
9433
9836
|
// src/commands/migrate-ide.ts
|
|
9434
|
-
import { Command as
|
|
9435
|
-
import { checkbox as
|
|
9837
|
+
import { Command as Command46 } from "commander";
|
|
9838
|
+
import { checkbox as checkbox6, confirm as confirm10 } from "@inquirer/prompts";
|
|
9436
9839
|
function createMigrateIdeCommand() {
|
|
9437
|
-
const cmd = new
|
|
9840
|
+
const cmd = new Command46("migrate-ide").description("Migrate .jai1 rules v\xE0 workflows sang IDEs (Cursor, Windsurf, Claude Code, etc.)").option("--ide <ides...>", "Target IDEs (cursor, windsurf, antigravity, claudecode, opencode)").option("--type <types...>", "Content types (rules, workflows, commands)").option("--dry-run", "Preview changes without writing files").action(async (options) => {
|
|
9438
9841
|
await runMigrateIde(options);
|
|
9439
9842
|
});
|
|
9440
9843
|
return cmd;
|
|
@@ -9462,7 +9865,7 @@ async function runMigrateIde(options) {
|
|
|
9462
9865
|
value: ide
|
|
9463
9866
|
};
|
|
9464
9867
|
});
|
|
9465
|
-
selectedIdes = await
|
|
9868
|
+
selectedIdes = await checkbox6({
|
|
9466
9869
|
message: "Ch\u1ECDn IDE(s) \u0111\u1EC3 migrate (SPACE \u0111\u1EC3 ch\u1ECDn, ENTER \u0111\u1EC3 x\xE1c nh\u1EADn):",
|
|
9467
9870
|
choices: ideChoices
|
|
9468
9871
|
});
|
|
@@ -9481,7 +9884,7 @@ async function runMigrateIde(options) {
|
|
|
9481
9884
|
{ name: `Workflows (${content.workflows.length} files)`, value: "workflows" },
|
|
9482
9885
|
{ name: `Commands (${content.commands.length} files)`, value: "commands" }
|
|
9483
9886
|
];
|
|
9484
|
-
selectedTypes = await
|
|
9887
|
+
selectedTypes = await checkbox6({
|
|
9485
9888
|
message: "Ch\u1ECDn content types \u0111\u1EC3 migrate:",
|
|
9486
9889
|
choices: typeChoices
|
|
9487
9890
|
});
|
|
@@ -9503,7 +9906,7 @@ async function runMigrateIde(options) {
|
|
|
9503
9906
|
if (options.dryRun) {
|
|
9504
9907
|
console.log("\u{1F50D} DRY RUN - No files will be written\n");
|
|
9505
9908
|
}
|
|
9506
|
-
const confirmed = await
|
|
9909
|
+
const confirmed = await confirm10({
|
|
9507
9910
|
message: "Proceed with migration?",
|
|
9508
9911
|
default: true
|
|
9509
9912
|
});
|
|
@@ -9540,7 +9943,7 @@ async function runMigrateIde(options) {
|
|
|
9540
9943
|
}
|
|
9541
9944
|
|
|
9542
9945
|
// src/cli.ts
|
|
9543
|
-
var program = new
|
|
9946
|
+
var program = new Command47();
|
|
9544
9947
|
if (process.argv.includes("-v") || process.argv.includes("--version")) {
|
|
9545
9948
|
console.log(package_default.version);
|
|
9546
9949
|
if (!process.argv.includes("--skip-update-check")) {
|
|
@@ -9562,12 +9965,13 @@ program.addCommand(createOpenAiKeysCommand());
|
|
|
9562
9965
|
program.addCommand(createStatsCommand());
|
|
9563
9966
|
program.addCommand(createTranslateCommand());
|
|
9564
9967
|
program.addCommand(createUtilsCommand());
|
|
9968
|
+
program.addCommand(createDepsCommand());
|
|
9565
9969
|
program.addCommand(createKitCommand());
|
|
9566
9970
|
program.addCommand(createUpgradeCommand());
|
|
9567
9971
|
program.addCommand(createCleanCommand());
|
|
9568
|
-
var redmineCommand = new
|
|
9972
|
+
var redmineCommand = new Command47("redmine").description("Redmine context sync commands");
|
|
9569
9973
|
redmineCommand.addCommand(createRedmineCheckCommand());
|
|
9570
|
-
var syncCommand = new
|
|
9974
|
+
var syncCommand = new Command47("sync").description("Sync Redmine issues to markdown files");
|
|
9571
9975
|
syncCommand.addCommand(createSyncIssueCommand());
|
|
9572
9976
|
syncCommand.addCommand(createSyncProjectCommand());
|
|
9573
9977
|
redmineCommand.addCommand(syncCommand);
|
|
@@ -9607,6 +10011,7 @@ program.on("command:*", (operands) => {
|
|
|
9607
10011
|
console.error(" translate Translate text, files, or folders using AI");
|
|
9608
10012
|
console.error("");
|
|
9609
10013
|
console.error(" \u{1F6E0}\uFE0F Developer Utilities");
|
|
10014
|
+
console.error(" deps Manage project dependencies");
|
|
9610
10015
|
console.error(" utils Developer tools (password, uuid, hash, jwt, etc.)");
|
|
9611
10016
|
console.error("");
|
|
9612
10017
|
console.error(" \u{1F527} Maintenance");
|