@ctxo/cli 0.9.1 → 0.9.3
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.
|
@@ -494,6 +494,39 @@ function detectFromLockfileWalkUp(startDir) {
|
|
|
494
494
|
}
|
|
495
495
|
return null;
|
|
496
496
|
}
|
|
497
|
+
function readWorkspaceLinks(projectRoot) {
|
|
498
|
+
const links = /* @__PURE__ */ new Set();
|
|
499
|
+
const pkgPath = join3(projectRoot, "package.json");
|
|
500
|
+
if (!existsSync4(pkgPath)) return links;
|
|
501
|
+
try {
|
|
502
|
+
const pkg = JSON.parse(readFileSync3(pkgPath, "utf-8"));
|
|
503
|
+
for (const group of [pkg.dependencies, pkg.devDependencies, pkg.peerDependencies, pkg.optionalDependencies]) {
|
|
504
|
+
if (!group) continue;
|
|
505
|
+
for (const [name, spec] of Object.entries(group)) {
|
|
506
|
+
if (typeof spec === "string" && spec.startsWith("workspace:")) {
|
|
507
|
+
links.add(name);
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
return links;
|
|
512
|
+
} catch {
|
|
513
|
+
return links;
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
function isWorkspaceRoot(projectRoot) {
|
|
517
|
+
if (existsSync4(join3(projectRoot, "pnpm-workspace.yaml"))) return true;
|
|
518
|
+
const pkgPath = join3(projectRoot, "package.json");
|
|
519
|
+
if (!existsSync4(pkgPath)) return false;
|
|
520
|
+
try {
|
|
521
|
+
const pkg = JSON.parse(readFileSync3(pkgPath, "utf-8"));
|
|
522
|
+
const ws = pkg.workspaces;
|
|
523
|
+
if (Array.isArray(ws) && ws.length > 0) return true;
|
|
524
|
+
if (ws && typeof ws === "object" && Array.isArray(ws.packages)) return true;
|
|
525
|
+
return false;
|
|
526
|
+
} catch {
|
|
527
|
+
return false;
|
|
528
|
+
}
|
|
529
|
+
}
|
|
497
530
|
function buildInstallCommand(manager, packages, options = {}) {
|
|
498
531
|
if (packages.length === 0) {
|
|
499
532
|
throw new Error("buildInstallCommand requires at least one package");
|
|
@@ -505,10 +538,13 @@ function buildInstallCommand(manager, packages, options = {}) {
|
|
|
505
538
|
args: options.global ? ["install", "-g", ...packages] : ["install", "-D", ...packages]
|
|
506
539
|
};
|
|
507
540
|
case "pnpm":
|
|
508
|
-
|
|
509
|
-
command: "pnpm",
|
|
510
|
-
|
|
511
|
-
|
|
541
|
+
if (options.global) {
|
|
542
|
+
return { command: "pnpm", args: ["add", "-g", ...packages] };
|
|
543
|
+
}
|
|
544
|
+
if (options.workspaceRoot) {
|
|
545
|
+
return { command: "pnpm", args: ["add", "-D", "-w", ...packages] };
|
|
546
|
+
}
|
|
547
|
+
return { command: "pnpm", args: ["add", "-D", ...packages] };
|
|
512
548
|
case "yarn":
|
|
513
549
|
return {
|
|
514
550
|
command: "yarn",
|
|
@@ -525,12 +561,18 @@ function buildInstallCommand(manager, packages, options = {}) {
|
|
|
525
561
|
// src/core/install/run-package-manager.ts
|
|
526
562
|
import { spawn } from "child_process";
|
|
527
563
|
function runPackageManager(command, args, cwd) {
|
|
564
|
+
const resolved = resolveBinary(command);
|
|
528
565
|
return new Promise((resolve4, reject) => {
|
|
529
|
-
const child = spawn(
|
|
566
|
+
const child = spawn(resolved, [...args], { cwd, stdio: "inherit", shell: false });
|
|
530
567
|
child.on("exit", (code) => resolve4(code ?? 0));
|
|
531
568
|
child.on("error", (err) => reject(err));
|
|
532
569
|
});
|
|
533
570
|
}
|
|
571
|
+
function resolveBinary(command) {
|
|
572
|
+
if (process.platform !== "win32") return command;
|
|
573
|
+
if (command === "bun") return "bun.exe";
|
|
574
|
+
return `${command}.cmd`;
|
|
575
|
+
}
|
|
534
576
|
|
|
535
577
|
// src/cli/install-command.ts
|
|
536
578
|
var InstallCommand = class {
|
|
@@ -570,7 +612,8 @@ var InstallCommand = class {
|
|
|
570
612
|
(lang) => options.version ? `${officialPluginFor(lang)}@${options.version}` : officialPluginFor(lang)
|
|
571
613
|
);
|
|
572
614
|
const invocation = buildInstallCommand(resolution.manager, specifiers, {
|
|
573
|
-
global: options.global
|
|
615
|
+
global: options.global,
|
|
616
|
+
workspaceRoot: !options.global && isWorkspaceRoot(this.projectRoot)
|
|
574
617
|
});
|
|
575
618
|
const plan = {
|
|
576
619
|
languages: resolvedLangs,
|
|
@@ -3608,7 +3651,7 @@ var DoctorCommand = class {
|
|
|
3608
3651
|
this.ctxoRoot = join22(projectRoot, ".ctxo");
|
|
3609
3652
|
}
|
|
3610
3653
|
async run(options = {}) {
|
|
3611
|
-
const { getVersion: getVersion2 } = await import("./cli-router-
|
|
3654
|
+
const { getVersion: getVersion2 } = await import("./cli-router-CQJ7CN6E.js");
|
|
3612
3655
|
console.error(`ctxo v${getVersion2()} \u2014 health check
|
|
3613
3656
|
`);
|
|
3614
3657
|
const checks = [
|
|
@@ -4014,6 +4057,11 @@ function computePackageStates(installed, results) {
|
|
|
4014
4057
|
function selectInstallTargets(states) {
|
|
4015
4058
|
return states.filter((s) => s.status === "update" && typeof s.latest === "string").filter((s) => isSafeVersionSpecifier(s.latest)).map((s) => ({ name: s.name, version: s.latest }));
|
|
4016
4059
|
}
|
|
4060
|
+
function markWorkspaceLinks(states, workspaceLinkNames) {
|
|
4061
|
+
return states.map(
|
|
4062
|
+
(s) => workspaceLinkNames.has(s.name) ? { ...s, status: "workspace", latest: null } : s
|
|
4063
|
+
);
|
|
4064
|
+
}
|
|
4017
4065
|
var SAFE_SPECIFIER_RE = /^[0-9A-Za-z.+-]+$/;
|
|
4018
4066
|
function isSafeVersionSpecifier(version) {
|
|
4019
4067
|
return SAFE_SPECIFIER_RE.test(version);
|
|
@@ -4032,17 +4080,20 @@ function formatText(report) {
|
|
|
4032
4080
|
lines.push(`All ${total} package${total === 1 ? "" : "s"} are up to date.`);
|
|
4033
4081
|
return lines.join("\n");
|
|
4034
4082
|
}
|
|
4083
|
+
const latestCell = (p) => {
|
|
4084
|
+
if (p.status === "workspace") return "(local)";
|
|
4085
|
+
return p.latest ?? "(not found)";
|
|
4086
|
+
};
|
|
4035
4087
|
const nameCol = Math.max(7, ...report.packages.map((p) => p.name.length));
|
|
4036
4088
|
const curCol = Math.max(7, ...report.packages.map((p) => p.current.length));
|
|
4037
|
-
const latestCol = Math.max(15, ...report.packages.map((p) => (p
|
|
4089
|
+
const latestCol = Math.max(15, ...report.packages.map((p) => latestCell(p).length));
|
|
4038
4090
|
lines.push(
|
|
4039
4091
|
`${"PACKAGE".padEnd(nameCol)} ${"CURRENT".padEnd(curCol)} ${`LATEST (${report.channel})`.padEnd(latestCol)} STATUS`
|
|
4040
4092
|
);
|
|
4041
4093
|
for (const pkg of report.packages) {
|
|
4042
|
-
const latestText = pkg.latest ?? "(not found)";
|
|
4043
4094
|
const statusText = renderStatus(pkg, report.channel);
|
|
4044
4095
|
lines.push(
|
|
4045
|
-
`${pkg.name.padEnd(nameCol)} ${pkg.current.padEnd(curCol)} ${
|
|
4096
|
+
`${pkg.name.padEnd(nameCol)} ${pkg.current.padEnd(curCol)} ${latestCell(pkg).padEnd(latestCol)} ${statusText}`
|
|
4046
4097
|
);
|
|
4047
4098
|
}
|
|
4048
4099
|
if (report.plan && report.strategy === "execute") {
|
|
@@ -4064,6 +4115,8 @@ function renderStatus(pkg, reportChannel) {
|
|
|
4064
4115
|
return "up to date";
|
|
4065
4116
|
case "ahead":
|
|
4066
4117
|
return "ahead of registry";
|
|
4118
|
+
case "workspace":
|
|
4119
|
+
return "workspace link";
|
|
4067
4120
|
case "unknown":
|
|
4068
4121
|
return pkg.reason === "registry-404" ? "skipped" : `error${pkg.reason ? ` (${pkg.reason})` : ""}`;
|
|
4069
4122
|
case "update":
|
|
@@ -4114,7 +4167,8 @@ var UpdateCommand = class {
|
|
|
4114
4167
|
this.deps.setExitCode?.(1);
|
|
4115
4168
|
return;
|
|
4116
4169
|
}
|
|
4117
|
-
const
|
|
4170
|
+
const rawStates = computePackageStates(installed, results);
|
|
4171
|
+
const states = markWorkspaceLinks(rawStates, readWorkspaceLinks(this.projectRoot));
|
|
4118
4172
|
const targets = selectInstallTargets(states);
|
|
4119
4173
|
const cliVersion = getVersion();
|
|
4120
4174
|
const channel = detectChannel(cliVersion);
|
|
@@ -4158,7 +4212,10 @@ var UpdateCommand = class {
|
|
|
4158
4212
|
});
|
|
4159
4213
|
const specifiers = targets.map((t) => `${t.name}@${t.version}`);
|
|
4160
4214
|
const useGlobal = options.global || !this.projectHasCtxoDep();
|
|
4161
|
-
const invocation = buildInstallCommand(resolution.manager, specifiers, {
|
|
4215
|
+
const invocation = buildInstallCommand(resolution.manager, specifiers, {
|
|
4216
|
+
global: useGlobal,
|
|
4217
|
+
workspaceRoot: !useGlobal && isWorkspaceRoot(this.projectRoot)
|
|
4218
|
+
});
|
|
4162
4219
|
return {
|
|
4163
4220
|
manager: resolution.manager,
|
|
4164
4221
|
managerSource: resolution.source,
|
|
@@ -4491,4 +4548,4 @@ export {
|
|
|
4491
4548
|
getVersion,
|
|
4492
4549
|
locateGitRoot
|
|
4493
4550
|
};
|
|
4494
|
-
//# sourceMappingURL=cli-router-
|
|
4551
|
+
//# sourceMappingURL=cli-router-CQJ7CN6E.js.map
|