@jvittechs/jai1-cli 0.1.83 → 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 +534 -128
- 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") {
|
|
@@ -7539,7 +7942,8 @@ function createKitCreateCommand() {
|
|
|
7539
7942
|
const hookExecutor = new HookExecutor(targetDir, variables);
|
|
7540
7943
|
await hookExecutor.run(kit.config.hooks.postInit);
|
|
7541
7944
|
}
|
|
7542
|
-
|
|
7945
|
+
const shouldPromptIdeSync = kit.config.ide?.promptSync !== false;
|
|
7946
|
+
if (!options.skipIde && shouldPromptIdeSync) {
|
|
7543
7947
|
const ideChoices = [
|
|
7544
7948
|
{ name: "Cursor", value: "cursor" },
|
|
7545
7949
|
{ name: "Windsurf", value: "windsurf" },
|
|
@@ -7554,7 +7958,7 @@ function createKitCreateCommand() {
|
|
|
7554
7958
|
}
|
|
7555
7959
|
} else {
|
|
7556
7960
|
const defaultTargets = kit.config.ide?.defaultTargets || [];
|
|
7557
|
-
const answer = await
|
|
7961
|
+
const answer = await checkbox4({
|
|
7558
7962
|
message: "Ch\u1ECDn IDE \u0111\u1EC3 sync framework:",
|
|
7559
7963
|
choices: ideChoices.map((c) => ({
|
|
7560
7964
|
...c,
|
|
@@ -7581,7 +7985,7 @@ function createKitCreateCommand() {
|
|
|
7581
7985
|
async function applyVariableSubstitution(dir, variables) {
|
|
7582
7986
|
const files = await getAllFiles(dir);
|
|
7583
7987
|
for (const file of files) {
|
|
7584
|
-
let content = await
|
|
7988
|
+
let content = await fs11.readFile(file, "utf-8");
|
|
7585
7989
|
let modified = false;
|
|
7586
7990
|
for (const [key, value] of Object.entries(variables)) {
|
|
7587
7991
|
const regex = new RegExp(`\\{\\{${key}\\}\\}`, "g");
|
|
@@ -7591,13 +7995,13 @@ async function applyVariableSubstitution(dir, variables) {
|
|
|
7591
7995
|
}
|
|
7592
7996
|
}
|
|
7593
7997
|
if (modified) {
|
|
7594
|
-
await
|
|
7998
|
+
await fs11.writeFile(file, content, "utf-8");
|
|
7595
7999
|
}
|
|
7596
8000
|
}
|
|
7597
8001
|
}
|
|
7598
8002
|
async function getAllFiles(dir) {
|
|
7599
8003
|
const files = [];
|
|
7600
|
-
const entries = await
|
|
8004
|
+
const entries = await fs11.readdir(dir, { withFileTypes: true });
|
|
7601
8005
|
for (const entry of entries) {
|
|
7602
8006
|
const fullPath = join5(dir, entry.name);
|
|
7603
8007
|
if (entry.isDirectory()) {
|
|
@@ -7613,7 +8017,7 @@ async function getAllFiles(dir) {
|
|
|
7613
8017
|
|
|
7614
8018
|
// src/commands/kit/index.ts
|
|
7615
8019
|
function createKitCommand() {
|
|
7616
|
-
const cmd = new
|
|
8020
|
+
const cmd = new Command34("kit").description("Manage starter kits for new projects").action(() => {
|
|
7617
8021
|
cmd.help();
|
|
7618
8022
|
});
|
|
7619
8023
|
cmd.addCommand(createKitListCommand());
|
|
@@ -7623,10 +8027,10 @@ function createKitCommand() {
|
|
|
7623
8027
|
}
|
|
7624
8028
|
|
|
7625
8029
|
// src/commands/upgrade.ts
|
|
7626
|
-
import { Command as
|
|
7627
|
-
import { confirm as
|
|
7628
|
-
import { execSync } from "child_process";
|
|
7629
|
-
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 = {
|
|
7630
8034
|
yellow: "\x1B[33m",
|
|
7631
8035
|
green: "\x1B[32m",
|
|
7632
8036
|
cyan: "\x1B[36m",
|
|
@@ -7635,7 +8039,7 @@ var colors2 = {
|
|
|
7635
8039
|
bold: "\x1B[1m"
|
|
7636
8040
|
};
|
|
7637
8041
|
function createUpgradeCommand() {
|
|
7638
|
-
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) => {
|
|
7639
8043
|
await handleUpgrade(options);
|
|
7640
8044
|
});
|
|
7641
8045
|
}
|
|
@@ -7646,7 +8050,7 @@ async function handleUpgrade(options) {
|
|
|
7646
8050
|
throw new ValidationError('Not initialized. Run "jai1 auth" first.');
|
|
7647
8051
|
}
|
|
7648
8052
|
try {
|
|
7649
|
-
console.log(`${
|
|
8053
|
+
console.log(`${colors3.cyan}\u{1F50D} Checking for updates...${colors3.reset}`);
|
|
7650
8054
|
const response = await fetch(`${config.apiUrl}/api/versions/client`, {
|
|
7651
8055
|
headers: {
|
|
7652
8056
|
"JAI1-Access-Key": config.accessKey
|
|
@@ -7661,47 +8065,47 @@ async function handleUpgrade(options) {
|
|
|
7661
8065
|
const latestVersion = data.version;
|
|
7662
8066
|
const currentVersion = package_default.version;
|
|
7663
8067
|
console.log(`
|
|
7664
|
-
${
|
|
7665
|
-
console.log(`${
|
|
8068
|
+
${colors3.bold}Current version:${colors3.reset} ${currentVersion}`);
|
|
8069
|
+
console.log(`${colors3.bold}Latest version:${colors3.reset} ${latestVersion}
|
|
7666
8070
|
`);
|
|
7667
8071
|
if (!isNewerVersion2(latestVersion, currentVersion)) {
|
|
7668
|
-
console.log(`${
|
|
8072
|
+
console.log(`${colors3.green}\u2705 You're already on the latest version!${colors3.reset}
|
|
7669
8073
|
`);
|
|
7670
8074
|
return;
|
|
7671
8075
|
}
|
|
7672
|
-
console.log(`${
|
|
7673
|
-
console.log(`${
|
|
7674
|
-
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}
|
|
7675
8079
|
`);
|
|
7676
8080
|
if (options.check) {
|
|
7677
|
-
console.log(`${
|
|
8081
|
+
console.log(`${colors3.cyan}Run "jai1 upgrade" to install the latest version.${colors3.reset}
|
|
7678
8082
|
`);
|
|
7679
8083
|
return;
|
|
7680
8084
|
}
|
|
7681
8085
|
if (!options.force) {
|
|
7682
|
-
const shouldUpdate = await
|
|
8086
|
+
const shouldUpdate = await confirm5({
|
|
7683
8087
|
message: "Update to the latest version now?",
|
|
7684
8088
|
default: true
|
|
7685
8089
|
});
|
|
7686
8090
|
if (!shouldUpdate) {
|
|
7687
|
-
console.log(`${
|
|
8091
|
+
console.log(`${colors3.yellow}\u23F8\uFE0F Upgrade cancelled.${colors3.reset}
|
|
7688
8092
|
`);
|
|
7689
8093
|
return;
|
|
7690
8094
|
}
|
|
7691
8095
|
}
|
|
7692
8096
|
console.log(`
|
|
7693
|
-
${
|
|
8097
|
+
${colors3.cyan}\u{1F4E5} Installing latest version...${colors3.reset}
|
|
7694
8098
|
`);
|
|
7695
8099
|
try {
|
|
7696
8100
|
const packageManager2 = detectPackageManager();
|
|
7697
8101
|
const installCommand = getInstallCommand(packageManager2);
|
|
7698
|
-
console.log(`${
|
|
7699
|
-
|
|
8102
|
+
console.log(`${colors3.cyan}Using ${packageManager2}...${colors3.reset}`);
|
|
8103
|
+
execSync2(installCommand, {
|
|
7700
8104
|
stdio: "inherit",
|
|
7701
8105
|
env: { ...process.env, FORCE_COLOR: "1" }
|
|
7702
8106
|
});
|
|
7703
8107
|
console.log(`
|
|
7704
|
-
${
|
|
8108
|
+
${colors3.green}\u2705 Successfully upgraded to version ${latestVersion}!${colors3.reset}
|
|
7705
8109
|
`);
|
|
7706
8110
|
trackAction("upgrade", {
|
|
7707
8111
|
from_version: currentVersion,
|
|
@@ -7711,17 +8115,17 @@ ${colors2.green}\u2705 Successfully upgraded to version ${latestVersion}!${color
|
|
|
7711
8115
|
disableUpdateCheck();
|
|
7712
8116
|
} catch (error) {
|
|
7713
8117
|
console.error(`
|
|
7714
|
-
${
|
|
7715
|
-
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}
|
|
7716
8120
|
`);
|
|
7717
|
-
console.error(`${
|
|
8121
|
+
console.error(`${colors3.yellow}\u{1F4A1} You can try manually upgrading with:${colors3.reset}`);
|
|
7718
8122
|
const manualCommands = {
|
|
7719
8123
|
npm: `npm install -g @jvittechs/jai1-cli@latest`,
|
|
7720
8124
|
pnpm: `pnpm add -g @jvittechs/jai1-cli@latest`,
|
|
7721
8125
|
yarn: `yarn global add @jvittechs/jai1-cli@latest`,
|
|
7722
8126
|
bun: `bun add -g @jvittechs/jai1-cli@latest`
|
|
7723
8127
|
};
|
|
7724
|
-
console.error(` ${
|
|
8128
|
+
console.error(` ${colors3.cyan}${manualCommands[packageManager]}${colors3.reset}
|
|
7725
8129
|
`);
|
|
7726
8130
|
throw error;
|
|
7727
8131
|
}
|
|
@@ -7745,7 +8149,7 @@ function isNewerVersion2(remote, local) {
|
|
|
7745
8149
|
}
|
|
7746
8150
|
function detectPackageManager() {
|
|
7747
8151
|
try {
|
|
7748
|
-
const jai1Path =
|
|
8152
|
+
const jai1Path = execSync2("which jai1 || where jai1", {
|
|
7749
8153
|
encoding: "utf-8",
|
|
7750
8154
|
stdio: ["pipe", "pipe", "ignore"]
|
|
7751
8155
|
}).trim();
|
|
@@ -7783,11 +8187,11 @@ function getInstallCommand(packageManager2) {
|
|
|
7783
8187
|
}
|
|
7784
8188
|
|
|
7785
8189
|
// src/commands/clean.ts
|
|
7786
|
-
import { Command as
|
|
7787
|
-
import { confirm as
|
|
8190
|
+
import { Command as Command36 } from "commander";
|
|
8191
|
+
import { confirm as confirm6, select as select3 } from "@inquirer/prompts";
|
|
7788
8192
|
import { join as join6 } from "path";
|
|
7789
8193
|
function createCleanCommand() {
|
|
7790
|
-
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) => {
|
|
7791
8195
|
await handleClean(options);
|
|
7792
8196
|
});
|
|
7793
8197
|
}
|
|
@@ -7882,7 +8286,7 @@ async function cleanTarget(target, skipConfirm) {
|
|
|
7882
8286
|
}
|
|
7883
8287
|
const countStr = info.count ? ` (${info.count} items)` : "";
|
|
7884
8288
|
if (!skipConfirm) {
|
|
7885
|
-
const confirmed = await
|
|
8289
|
+
const confirmed = await confirm6({
|
|
7886
8290
|
message: `Delete ${target.name}${countStr}?`,
|
|
7887
8291
|
default: false
|
|
7888
8292
|
});
|
|
@@ -7900,7 +8304,7 @@ async function cleanTarget(target, skipConfirm) {
|
|
|
7900
8304
|
}
|
|
7901
8305
|
|
|
7902
8306
|
// src/commands/redmine/check.ts
|
|
7903
|
-
import { Command as
|
|
8307
|
+
import { Command as Command37 } from "commander";
|
|
7904
8308
|
|
|
7905
8309
|
// src/services/redmine-config.service.ts
|
|
7906
8310
|
import { readFile as readFile6 } from "fs/promises";
|
|
@@ -8001,7 +8405,7 @@ var RedmineConfigService = class {
|
|
|
8001
8405
|
// src/api.ts
|
|
8002
8406
|
import { fetch as fetch2 } from "undici";
|
|
8003
8407
|
import pRetry2 from "p-retry";
|
|
8004
|
-
import
|
|
8408
|
+
import pLimit3 from "p-limit";
|
|
8005
8409
|
var RedmineApiError = class extends Error {
|
|
8006
8410
|
constructor(message, status, response) {
|
|
8007
8411
|
super(message);
|
|
@@ -8019,10 +8423,10 @@ var RedmineApiClient = class {
|
|
|
8019
8423
|
this.baseUrl = config.baseUrl.replace(/\/$/, "");
|
|
8020
8424
|
this.apiAccessToken = config.apiAccessToken;
|
|
8021
8425
|
this.retryConfig = config.defaults.retry;
|
|
8022
|
-
this.concurrencyLimit =
|
|
8426
|
+
this.concurrencyLimit = pLimit3(config.defaults.concurrency);
|
|
8023
8427
|
}
|
|
8024
|
-
async request(
|
|
8025
|
-
const url = `${this.baseUrl}${
|
|
8428
|
+
async request(path8, options = {}) {
|
|
8429
|
+
const url = `${this.baseUrl}${path8}`;
|
|
8026
8430
|
const headers = {
|
|
8027
8431
|
"X-Redmine-API-Key": this.apiAccessToken,
|
|
8028
8432
|
"Content-Type": "application/json",
|
|
@@ -8083,8 +8487,8 @@ var RedmineApiClient = class {
|
|
|
8083
8487
|
if (include && include.length > 0) {
|
|
8084
8488
|
params.append("include", include.join(","));
|
|
8085
8489
|
}
|
|
8086
|
-
const
|
|
8087
|
-
return this.request(
|
|
8490
|
+
const path8 = `/issues/${issueId}.json${params.toString() ? `?${params.toString()}` : ""}`;
|
|
8491
|
+
return this.request(path8);
|
|
8088
8492
|
}
|
|
8089
8493
|
async getIssues(projectId, options = {}) {
|
|
8090
8494
|
const params = new URLSearchParams();
|
|
@@ -8104,8 +8508,8 @@ var RedmineApiClient = class {
|
|
|
8104
8508
|
if (options.updatedSince) {
|
|
8105
8509
|
params.append("updated_on", `>=${options.updatedSince}`);
|
|
8106
8510
|
}
|
|
8107
|
-
const
|
|
8108
|
-
return this.request(
|
|
8511
|
+
const path8 = `/issues.json?${params.toString()}`;
|
|
8512
|
+
return this.request(path8);
|
|
8109
8513
|
}
|
|
8110
8514
|
async getAllIssues(projectId, options = {}) {
|
|
8111
8515
|
const pageSize = options.pageSize || 100;
|
|
@@ -8207,7 +8611,7 @@ async function checkConnectivity(config) {
|
|
|
8207
8611
|
|
|
8208
8612
|
// src/commands/redmine/check.ts
|
|
8209
8613
|
function createRedmineCheckCommand() {
|
|
8210
|
-
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) => {
|
|
8211
8615
|
await handleRedmineCheck(options);
|
|
8212
8616
|
});
|
|
8213
8617
|
return cmd;
|
|
@@ -8235,7 +8639,7 @@ async function handleRedmineCheck(options) {
|
|
|
8235
8639
|
}
|
|
8236
8640
|
|
|
8237
8641
|
// src/commands/redmine/sync-issue.ts
|
|
8238
|
-
import { Command as
|
|
8642
|
+
import { Command as Command38 } from "commander";
|
|
8239
8643
|
|
|
8240
8644
|
// src/sync-issue.ts
|
|
8241
8645
|
import { resolve as resolve3, relative } from "path";
|
|
@@ -8611,7 +9015,7 @@ function extractIssueIdFromUrl(url) {
|
|
|
8611
9015
|
|
|
8612
9016
|
// src/commands/redmine/sync-issue.ts
|
|
8613
9017
|
function createSyncIssueCommand() {
|
|
8614
|
-
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) => {
|
|
8615
9019
|
await handleSyncIssue(options);
|
|
8616
9020
|
});
|
|
8617
9021
|
return cmd;
|
|
@@ -8655,7 +9059,7 @@ async function handleSyncIssue(options) {
|
|
|
8655
9059
|
}
|
|
8656
9060
|
|
|
8657
9061
|
// src/commands/redmine/sync-project.ts
|
|
8658
|
-
import { Command as
|
|
9062
|
+
import { Command as Command39 } from "commander";
|
|
8659
9063
|
|
|
8660
9064
|
// src/sync-project.ts
|
|
8661
9065
|
async function syncProject(config, options = {}) {
|
|
@@ -8725,7 +9129,7 @@ async function syncProject(config, options = {}) {
|
|
|
8725
9129
|
|
|
8726
9130
|
// src/commands/redmine/sync-project.ts
|
|
8727
9131
|
function createSyncProjectCommand() {
|
|
8728
|
-
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) => {
|
|
8729
9133
|
await handleSyncProject(options);
|
|
8730
9134
|
});
|
|
8731
9135
|
return cmd;
|
|
@@ -8780,12 +9184,12 @@ async function handleSyncProject(options) {
|
|
|
8780
9184
|
}
|
|
8781
9185
|
|
|
8782
9186
|
// src/commands/framework/info.ts
|
|
8783
|
-
import { Command as
|
|
8784
|
-
import { promises as
|
|
9187
|
+
import { Command as Command40 } from "commander";
|
|
9188
|
+
import { promises as fs12 } from "fs";
|
|
8785
9189
|
import { join as join7 } from "path";
|
|
8786
9190
|
import { homedir as homedir5 } from "os";
|
|
8787
9191
|
function createInfoCommand() {
|
|
8788
|
-
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) => {
|
|
8789
9193
|
await handleInfo(options);
|
|
8790
9194
|
});
|
|
8791
9195
|
return cmd;
|
|
@@ -8833,7 +9237,7 @@ function maskKey3(key) {
|
|
|
8833
9237
|
async function getProjectStatus2() {
|
|
8834
9238
|
const projectJai1 = join7(process.cwd(), ".jai1");
|
|
8835
9239
|
try {
|
|
8836
|
-
await
|
|
9240
|
+
await fs12.access(projectJai1);
|
|
8837
9241
|
return { exists: true, version: "Synced" };
|
|
8838
9242
|
} catch {
|
|
8839
9243
|
return { exists: false };
|
|
@@ -8841,10 +9245,10 @@ async function getProjectStatus2() {
|
|
|
8841
9245
|
}
|
|
8842
9246
|
|
|
8843
9247
|
// src/commands/self-update.ts
|
|
8844
|
-
import { Command as
|
|
8845
|
-
import { confirm as
|
|
8846
|
-
import { execSync as
|
|
8847
|
-
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 = {
|
|
8848
9252
|
yellow: "\x1B[33m",
|
|
8849
9253
|
green: "\x1B[32m",
|
|
8850
9254
|
cyan: "\x1B[36m",
|
|
@@ -8853,7 +9257,7 @@ var colors3 = {
|
|
|
8853
9257
|
bold: "\x1B[1m"
|
|
8854
9258
|
};
|
|
8855
9259
|
function createSelfUpdateCommand() {
|
|
8856
|
-
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) => {
|
|
8857
9261
|
await handleSelfUpdate(options);
|
|
8858
9262
|
});
|
|
8859
9263
|
}
|
|
@@ -8864,7 +9268,7 @@ async function handleSelfUpdate(options) {
|
|
|
8864
9268
|
throw new ValidationError('Not initialized. Run "jai1 auth" first.');
|
|
8865
9269
|
}
|
|
8866
9270
|
try {
|
|
8867
|
-
console.log(`${
|
|
9271
|
+
console.log(`${colors4.cyan}\u{1F50D} Checking for updates...${colors4.reset}`);
|
|
8868
9272
|
const response = await fetch(`${config.apiUrl}/api/versions/client`, {
|
|
8869
9273
|
headers: {
|
|
8870
9274
|
"JAI1-Access-Key": config.accessKey
|
|
@@ -8879,47 +9283,47 @@ async function handleSelfUpdate(options) {
|
|
|
8879
9283
|
const latestVersion = data.version;
|
|
8880
9284
|
const currentVersion = package_default.version;
|
|
8881
9285
|
console.log(`
|
|
8882
|
-
${
|
|
8883
|
-
console.log(`${
|
|
9286
|
+
${colors4.bold}Current version:${colors4.reset} ${currentVersion}`);
|
|
9287
|
+
console.log(`${colors4.bold}Latest version:${colors4.reset} ${latestVersion}
|
|
8884
9288
|
`);
|
|
8885
9289
|
if (!isNewerVersion3(latestVersion, currentVersion)) {
|
|
8886
|
-
console.log(`${
|
|
9290
|
+
console.log(`${colors4.green}\u2705 You're already on the latest version!${colors4.reset}
|
|
8887
9291
|
`);
|
|
8888
9292
|
return;
|
|
8889
9293
|
}
|
|
8890
|
-
console.log(`${
|
|
8891
|
-
console.log(`${
|
|
8892
|
-
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}
|
|
8893
9297
|
`);
|
|
8894
9298
|
if (options.check) {
|
|
8895
|
-
console.log(`${
|
|
9299
|
+
console.log(`${colors4.cyan}Run "jai1 self-update" to install the latest version.${colors4.reset}
|
|
8896
9300
|
`);
|
|
8897
9301
|
return;
|
|
8898
9302
|
}
|
|
8899
9303
|
if (!options.force) {
|
|
8900
|
-
const shouldUpdate = await
|
|
9304
|
+
const shouldUpdate = await confirm7({
|
|
8901
9305
|
message: "Update to the latest version now?",
|
|
8902
9306
|
default: true
|
|
8903
9307
|
});
|
|
8904
9308
|
if (!shouldUpdate) {
|
|
8905
|
-
console.log(`${
|
|
9309
|
+
console.log(`${colors4.yellow}\u23F8\uFE0F Update cancelled.${colors4.reset}
|
|
8906
9310
|
`);
|
|
8907
9311
|
return;
|
|
8908
9312
|
}
|
|
8909
9313
|
}
|
|
8910
9314
|
console.log(`
|
|
8911
|
-
${
|
|
9315
|
+
${colors4.cyan}\u{1F4E5} Installing latest version...${colors4.reset}
|
|
8912
9316
|
`);
|
|
8913
9317
|
try {
|
|
8914
9318
|
const packageManager2 = detectPackageManager2();
|
|
8915
9319
|
const installCommand = getInstallCommand2(packageManager2);
|
|
8916
|
-
console.log(`${
|
|
8917
|
-
|
|
9320
|
+
console.log(`${colors4.cyan}Using ${packageManager2}...${colors4.reset}`);
|
|
9321
|
+
execSync3(installCommand, {
|
|
8918
9322
|
stdio: "inherit",
|
|
8919
9323
|
env: { ...process.env, FORCE_COLOR: "1" }
|
|
8920
9324
|
});
|
|
8921
9325
|
console.log(`
|
|
8922
|
-
${
|
|
9326
|
+
${colors4.green}\u2705 Successfully updated to version ${latestVersion}!${colors4.reset}
|
|
8923
9327
|
`);
|
|
8924
9328
|
trackAction("self_update", {
|
|
8925
9329
|
from_version: currentVersion,
|
|
@@ -8929,11 +9333,11 @@ ${colors3.green}\u2705 Successfully updated to version ${latestVersion}!${colors
|
|
|
8929
9333
|
disableUpdateCheck();
|
|
8930
9334
|
} catch (error) {
|
|
8931
9335
|
console.error(`
|
|
8932
|
-
${
|
|
8933
|
-
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}
|
|
8934
9338
|
`);
|
|
8935
|
-
console.error(`${
|
|
8936
|
-
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}
|
|
8937
9341
|
`);
|
|
8938
9342
|
throw error;
|
|
8939
9343
|
}
|
|
@@ -8961,17 +9365,17 @@ function detectPackageManager2() {
|
|
|
8961
9365
|
if (userAgent.includes("yarn")) return "yarn";
|
|
8962
9366
|
if (userAgent.includes("bun")) return "bun";
|
|
8963
9367
|
try {
|
|
8964
|
-
|
|
9368
|
+
execSync3("pnpm --version", { stdio: "ignore" });
|
|
8965
9369
|
return "pnpm";
|
|
8966
9370
|
} catch {
|
|
8967
9371
|
}
|
|
8968
9372
|
try {
|
|
8969
|
-
|
|
9373
|
+
execSync3("yarn --version", { stdio: "ignore" });
|
|
8970
9374
|
return "yarn";
|
|
8971
9375
|
} catch {
|
|
8972
9376
|
}
|
|
8973
9377
|
try {
|
|
8974
|
-
|
|
9378
|
+
execSync3("bun --version", { stdio: "ignore" });
|
|
8975
9379
|
return "bun";
|
|
8976
9380
|
} catch {
|
|
8977
9381
|
}
|
|
@@ -8993,10 +9397,10 @@ function getInstallCommand2(packageManager2) {
|
|
|
8993
9397
|
}
|
|
8994
9398
|
|
|
8995
9399
|
// src/commands/clear-backups.ts
|
|
8996
|
-
import { Command as
|
|
8997
|
-
import { confirm as
|
|
9400
|
+
import { Command as Command42 } from "commander";
|
|
9401
|
+
import { confirm as confirm8 } from "@inquirer/prompts";
|
|
8998
9402
|
function createClearBackupsCommand() {
|
|
8999
|
-
return new
|
|
9403
|
+
return new Command42("clear-backups").description("Clear backup files").option("-y, --yes", "Skip confirmation").action(async (options) => {
|
|
9000
9404
|
const service = new ComponentsService();
|
|
9001
9405
|
const backups = await service.listBackups(process.cwd());
|
|
9002
9406
|
if (backups.length === 0) {
|
|
@@ -9012,7 +9416,7 @@ function createClearBackupsCommand() {
|
|
|
9012
9416
|
}
|
|
9013
9417
|
console.log();
|
|
9014
9418
|
if (!options.yes) {
|
|
9015
|
-
const ok = await
|
|
9419
|
+
const ok = await confirm8({ message: "Delete all backups?", default: false });
|
|
9016
9420
|
if (!ok) return;
|
|
9017
9421
|
}
|
|
9018
9422
|
await service.clearBackups(process.cwd());
|
|
@@ -9021,10 +9425,10 @@ function createClearBackupsCommand() {
|
|
|
9021
9425
|
}
|
|
9022
9426
|
|
|
9023
9427
|
// src/commands/vscode/index.ts
|
|
9024
|
-
import { Command as
|
|
9025
|
-
import { checkbox as
|
|
9026
|
-
import
|
|
9027
|
-
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";
|
|
9028
9432
|
import { existsSync as existsSync3 } from "fs";
|
|
9029
9433
|
var PERFORMANCE_GROUPS2 = {
|
|
9030
9434
|
telemetry: {
|
|
@@ -9161,7 +9565,7 @@ var PERFORMANCE_GROUPS2 = {
|
|
|
9161
9565
|
}
|
|
9162
9566
|
};
|
|
9163
9567
|
function createVSCodeCommand() {
|
|
9164
|
-
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");
|
|
9165
9569
|
vscodeCommand.action(async () => {
|
|
9166
9570
|
await interactiveMode2();
|
|
9167
9571
|
});
|
|
@@ -9229,7 +9633,7 @@ async function selectGroupsToApply2(action) {
|
|
|
9229
9633
|
value: key
|
|
9230
9634
|
}));
|
|
9231
9635
|
try {
|
|
9232
|
-
const selectedGroups = await
|
|
9636
|
+
const selectedGroups = await checkbox5({
|
|
9233
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):`,
|
|
9234
9638
|
choices
|
|
9235
9639
|
});
|
|
@@ -9244,8 +9648,8 @@ async function selectGroupsToApply2(action) {
|
|
|
9244
9648
|
}
|
|
9245
9649
|
}
|
|
9246
9650
|
async function applyGroups2(groupKeys, action) {
|
|
9247
|
-
const vscodeDir =
|
|
9248
|
-
const settingsPath =
|
|
9651
|
+
const vscodeDir = path7.join(process.cwd(), ".vscode");
|
|
9652
|
+
const settingsPath = path7.join(vscodeDir, "settings.json");
|
|
9249
9653
|
const invalidGroups = groupKeys.filter((key) => !PERFORMANCE_GROUPS2[key]);
|
|
9250
9654
|
if (invalidGroups.length > 0) {
|
|
9251
9655
|
console.log(`
|
|
@@ -9254,18 +9658,18 @@ async function applyGroups2(groupKeys, action) {
|
|
|
9254
9658
|
return;
|
|
9255
9659
|
}
|
|
9256
9660
|
if (!existsSync3(vscodeDir)) {
|
|
9257
|
-
await
|
|
9661
|
+
await fs13.mkdir(vscodeDir, { recursive: true });
|
|
9258
9662
|
console.log("\u{1F4C1} \u0110\xE3 t\u1EA1o th\u01B0 m\u1EE5c .vscode/");
|
|
9259
9663
|
}
|
|
9260
9664
|
let currentSettings = {};
|
|
9261
9665
|
if (existsSync3(settingsPath)) {
|
|
9262
9666
|
try {
|
|
9263
|
-
const content = await
|
|
9667
|
+
const content = await fs13.readFile(settingsPath, "utf-8");
|
|
9264
9668
|
currentSettings = JSON.parse(content);
|
|
9265
9669
|
console.log("\u{1F4C4} \u0110\xE3 \u0111\u1ECDc c\xE0i \u0111\u1EB7t hi\u1EC7n t\u1EA1i t\u1EEB settings.json");
|
|
9266
9670
|
} catch {
|
|
9267
9671
|
console.warn("\u26A0\uFE0F Kh\xF4ng th\u1EC3 \u0111\u1ECDc settings.json (c\xF3 th\u1EC3 ch\u1EE9a comments).");
|
|
9268
|
-
const confirmOverwrite = await
|
|
9672
|
+
const confirmOverwrite = await confirm9({
|
|
9269
9673
|
message: "Ghi \u0111\xE8 file settings.json hi\u1EC7n t\u1EA1i?",
|
|
9270
9674
|
default: false
|
|
9271
9675
|
});
|
|
@@ -9300,19 +9704,19 @@ async function applyGroups2(groupKeys, action) {
|
|
|
9300
9704
|
}
|
|
9301
9705
|
}
|
|
9302
9706
|
}
|
|
9303
|
-
await
|
|
9707
|
+
await fs13.writeFile(settingsPath, JSON.stringify(newSettings, null, 2));
|
|
9304
9708
|
console.log(`
|
|
9305
9709
|
\u2705 \u0110\xE3 c\u1EADp nh\u1EADt c\xE0i \u0111\u1EB7t VSCode t\u1EA1i: ${settingsPath}`);
|
|
9306
9710
|
console.log("\u{1F4A1} M\u1EB9o: Kh\u1EDFi \u0111\u1ED9ng l\u1EA1i VSCode \u0111\u1EC3 \xE1p d\u1EE5ng c\xE1c thay \u0111\u1ED5i.");
|
|
9307
9711
|
}
|
|
9308
9712
|
async function resetSettings2(groupKeys) {
|
|
9309
|
-
const vscodeDir =
|
|
9310
|
-
const settingsPath =
|
|
9713
|
+
const vscodeDir = path7.join(process.cwd(), ".vscode");
|
|
9714
|
+
const settingsPath = path7.join(vscodeDir, "settings.json");
|
|
9311
9715
|
if (!existsSync3(settingsPath)) {
|
|
9312
9716
|
console.log("\n\u26A0\uFE0F Kh\xF4ng t\xECm th\u1EA5y file settings.json");
|
|
9313
9717
|
return;
|
|
9314
9718
|
}
|
|
9315
|
-
const confirmReset = await
|
|
9719
|
+
const confirmReset = await confirm9({
|
|
9316
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(", ")}?`,
|
|
9317
9721
|
default: false
|
|
9318
9722
|
});
|
|
@@ -9321,7 +9725,7 @@ async function resetSettings2(groupKeys) {
|
|
|
9321
9725
|
return;
|
|
9322
9726
|
}
|
|
9323
9727
|
if (groupKeys.length === 0) {
|
|
9324
|
-
await
|
|
9728
|
+
await fs13.unlink(settingsPath);
|
|
9325
9729
|
console.log("\n\u2705 \u0110\xE3 x\xF3a file settings.json");
|
|
9326
9730
|
} else {
|
|
9327
9731
|
await applyGroups2(groupKeys, "disable");
|
|
@@ -9332,9 +9736,9 @@ async function resetSettings2(groupKeys) {
|
|
|
9332
9736
|
// src/commands/guide.ts
|
|
9333
9737
|
import React40 from "react";
|
|
9334
9738
|
import { render as render6 } from "ink";
|
|
9335
|
-
import { Command as
|
|
9739
|
+
import { Command as Command44 } from "commander";
|
|
9336
9740
|
function createGuideCommand() {
|
|
9337
|
-
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) => {
|
|
9338
9742
|
const { waitUntilExit } = render6(
|
|
9339
9743
|
React40.createElement(GuideApp, {
|
|
9340
9744
|
initialTopic: options.topic,
|
|
@@ -9351,9 +9755,9 @@ function createGuideCommand() {
|
|
|
9351
9755
|
// src/commands/context.ts
|
|
9352
9756
|
import React41 from "react";
|
|
9353
9757
|
import { render as render7 } from "ink";
|
|
9354
|
-
import { Command as
|
|
9758
|
+
import { Command as Command45 } from "commander";
|
|
9355
9759
|
function createContextCommand() {
|
|
9356
|
-
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) => {
|
|
9357
9761
|
let initialIDE;
|
|
9358
9762
|
if (options.ide) {
|
|
9359
9763
|
const validIDEs = ["cursor", "windsurf", "antigravity", "jai1"];
|
|
@@ -9430,10 +9834,10 @@ async function printStats2() {
|
|
|
9430
9834
|
}
|
|
9431
9835
|
|
|
9432
9836
|
// src/commands/migrate-ide.ts
|
|
9433
|
-
import { Command as
|
|
9434
|
-
import { checkbox as
|
|
9837
|
+
import { Command as Command46 } from "commander";
|
|
9838
|
+
import { checkbox as checkbox6, confirm as confirm10 } from "@inquirer/prompts";
|
|
9435
9839
|
function createMigrateIdeCommand() {
|
|
9436
|
-
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) => {
|
|
9437
9841
|
await runMigrateIde(options);
|
|
9438
9842
|
});
|
|
9439
9843
|
return cmd;
|
|
@@ -9461,7 +9865,7 @@ async function runMigrateIde(options) {
|
|
|
9461
9865
|
value: ide
|
|
9462
9866
|
};
|
|
9463
9867
|
});
|
|
9464
|
-
selectedIdes = await
|
|
9868
|
+
selectedIdes = await checkbox6({
|
|
9465
9869
|
message: "Ch\u1ECDn IDE(s) \u0111\u1EC3 migrate (SPACE \u0111\u1EC3 ch\u1ECDn, ENTER \u0111\u1EC3 x\xE1c nh\u1EADn):",
|
|
9466
9870
|
choices: ideChoices
|
|
9467
9871
|
});
|
|
@@ -9480,7 +9884,7 @@ async function runMigrateIde(options) {
|
|
|
9480
9884
|
{ name: `Workflows (${content.workflows.length} files)`, value: "workflows" },
|
|
9481
9885
|
{ name: `Commands (${content.commands.length} files)`, value: "commands" }
|
|
9482
9886
|
];
|
|
9483
|
-
selectedTypes = await
|
|
9887
|
+
selectedTypes = await checkbox6({
|
|
9484
9888
|
message: "Ch\u1ECDn content types \u0111\u1EC3 migrate:",
|
|
9485
9889
|
choices: typeChoices
|
|
9486
9890
|
});
|
|
@@ -9502,7 +9906,7 @@ async function runMigrateIde(options) {
|
|
|
9502
9906
|
if (options.dryRun) {
|
|
9503
9907
|
console.log("\u{1F50D} DRY RUN - No files will be written\n");
|
|
9504
9908
|
}
|
|
9505
|
-
const confirmed = await
|
|
9909
|
+
const confirmed = await confirm10({
|
|
9506
9910
|
message: "Proceed with migration?",
|
|
9507
9911
|
default: true
|
|
9508
9912
|
});
|
|
@@ -9539,7 +9943,7 @@ async function runMigrateIde(options) {
|
|
|
9539
9943
|
}
|
|
9540
9944
|
|
|
9541
9945
|
// src/cli.ts
|
|
9542
|
-
var program = new
|
|
9946
|
+
var program = new Command47();
|
|
9543
9947
|
if (process.argv.includes("-v") || process.argv.includes("--version")) {
|
|
9544
9948
|
console.log(package_default.version);
|
|
9545
9949
|
if (!process.argv.includes("--skip-update-check")) {
|
|
@@ -9561,12 +9965,13 @@ program.addCommand(createOpenAiKeysCommand());
|
|
|
9561
9965
|
program.addCommand(createStatsCommand());
|
|
9562
9966
|
program.addCommand(createTranslateCommand());
|
|
9563
9967
|
program.addCommand(createUtilsCommand());
|
|
9968
|
+
program.addCommand(createDepsCommand());
|
|
9564
9969
|
program.addCommand(createKitCommand());
|
|
9565
9970
|
program.addCommand(createUpgradeCommand());
|
|
9566
9971
|
program.addCommand(createCleanCommand());
|
|
9567
|
-
var redmineCommand = new
|
|
9972
|
+
var redmineCommand = new Command47("redmine").description("Redmine context sync commands");
|
|
9568
9973
|
redmineCommand.addCommand(createRedmineCheckCommand());
|
|
9569
|
-
var syncCommand = new
|
|
9974
|
+
var syncCommand = new Command47("sync").description("Sync Redmine issues to markdown files");
|
|
9570
9975
|
syncCommand.addCommand(createSyncIssueCommand());
|
|
9571
9976
|
syncCommand.addCommand(createSyncProjectCommand());
|
|
9572
9977
|
redmineCommand.addCommand(syncCommand);
|
|
@@ -9606,6 +10011,7 @@ program.on("command:*", (operands) => {
|
|
|
9606
10011
|
console.error(" translate Translate text, files, or folders using AI");
|
|
9607
10012
|
console.error("");
|
|
9608
10013
|
console.error(" \u{1F6E0}\uFE0F Developer Utilities");
|
|
10014
|
+
console.error(" deps Manage project dependencies");
|
|
9609
10015
|
console.error(" utils Developer tools (password, uuid, hash, jwt, etc.)");
|
|
9610
10016
|
console.error("");
|
|
9611
10017
|
console.error(" \u{1F527} Maintenance");
|