@rigkit/cli 0.2.6 → 0.2.8
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 +12 -3
- package/package.json +4 -7
- package/src/cli.test.ts +139 -7
- package/src/cli.ts +699 -235
- package/src/completion.test.ts +144 -13
- package/src/completion.ts +435 -81
- package/src/init.ts +6 -4
- package/src/project.test.ts +33 -3
- package/src/project.ts +99 -11
- package/src/run-logger.test.ts +92 -0
- package/src/run-logger.ts +203 -0
- package/src/run-presenter.ts +176 -299
- package/src/ui.ts +159 -0
- package/src/version.ts +1 -1
- package/src/remote-project.test.ts +0 -55
- package/src/remote-project.ts +0 -225
package/src/completion.test.ts
CHANGED
|
@@ -16,7 +16,7 @@ describe("CLI completion", () => {
|
|
|
16
16
|
});
|
|
17
17
|
|
|
18
18
|
expect(items.map((item) => item.value)).toEqual(["api", "web"]);
|
|
19
|
-
expect(items[0]?.description).toBe("
|
|
19
|
+
expect(items[0]?.description).toBe("created 2h ago");
|
|
20
20
|
});
|
|
21
21
|
});
|
|
22
22
|
|
|
@@ -33,20 +33,93 @@ describe("CLI completion", () => {
|
|
|
33
33
|
});
|
|
34
34
|
});
|
|
35
35
|
|
|
36
|
-
test("respects -
|
|
36
|
+
test("respects -chdir when completing workspace targets", async () => {
|
|
37
37
|
const parentDir = mkdtempSync(join(tmpdir(), "rigkit-completion-parent-"));
|
|
38
38
|
const projectDir = join(parentDir, "project");
|
|
39
39
|
await withWorkspaceRuntime({ projectDir, cleanupDir: parentDir }, async () => {
|
|
40
40
|
const items = await completeRig({
|
|
41
41
|
cwd: parentDir,
|
|
42
|
-
words: ["rig", "-
|
|
43
|
-
currentIndex:
|
|
42
|
+
words: ["rig", "-chdir=project", "run", ""],
|
|
43
|
+
currentIndex: 3,
|
|
44
44
|
});
|
|
45
45
|
|
|
46
46
|
expect(items.map((item) => item.value)).toEqual(["api", "web"]);
|
|
47
47
|
});
|
|
48
48
|
});
|
|
49
49
|
|
|
50
|
+
test("completes project directories for -chdir", async () => {
|
|
51
|
+
const cwd = mkdtempSync(join(tmpdir(), "rigkit-completion-dirs-"));
|
|
52
|
+
mkdirSync(join(cwd, "examples", "global-fragments"), { recursive: true });
|
|
53
|
+
|
|
54
|
+
try {
|
|
55
|
+
const roots = await completeRig({
|
|
56
|
+
cwd,
|
|
57
|
+
words: ["rig", "-chdir="],
|
|
58
|
+
currentIndex: 1,
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
expect(roots).toContainEqual({
|
|
62
|
+
value: "-chdir=examples/",
|
|
63
|
+
description: "directory",
|
|
64
|
+
noSpace: true,
|
|
65
|
+
group: "Paths",
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
const nested = await completeRig({
|
|
69
|
+
cwd,
|
|
70
|
+
words: ["rig", "-chdir=examples/g"],
|
|
71
|
+
currentIndex: 1,
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
expect(nested).toContainEqual({
|
|
75
|
+
value: "-chdir=examples/global-fragments/",
|
|
76
|
+
description: "directory",
|
|
77
|
+
noSpace: true,
|
|
78
|
+
group: "Paths",
|
|
79
|
+
});
|
|
80
|
+
} finally {
|
|
81
|
+
rmSync(cwd, { recursive: true, force: true });
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
test("completes named config files", async () => {
|
|
86
|
+
const cwd = mkdtempSync(join(tmpdir(), "rigkit-completion-configs-"));
|
|
87
|
+
writeFileSync(join(cwd, "api.rig.config.ts"), "export default {}\n");
|
|
88
|
+
writeFileSync(join(cwd, "web.rig.config.ts"), "export default {}\n");
|
|
89
|
+
|
|
90
|
+
try {
|
|
91
|
+
const items = await completeRig({
|
|
92
|
+
cwd,
|
|
93
|
+
words: ["rig", "-config="],
|
|
94
|
+
currentIndex: 1,
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
expect(items.map((item) => item.value)).toEqual(["-config=api.rig.config.ts", "-config=web.rig.config.ts"]);
|
|
98
|
+
} finally {
|
|
99
|
+
rmSync(cwd, { recursive: true, force: true });
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
test("respects -chdir when completing config files", async () => {
|
|
104
|
+
const cwd = mkdtempSync(join(tmpdir(), "rigkit-completion-configs-"));
|
|
105
|
+
const projectDir = join(cwd, "global-fragments");
|
|
106
|
+
mkdirSync(projectDir, { recursive: true });
|
|
107
|
+
writeFileSync(join(projectDir, "api.rig.config.ts"), "export default {}\n");
|
|
108
|
+
writeFileSync(join(projectDir, "worker.rig.config.ts"), "export default {}\n");
|
|
109
|
+
|
|
110
|
+
try {
|
|
111
|
+
const items = await completeRig({
|
|
112
|
+
cwd,
|
|
113
|
+
words: ["rig", "-chdir=global-fragments", "-config="],
|
|
114
|
+
currentIndex: 2,
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
expect(items.map((item) => item.value)).toEqual(["-config=api.rig.config.ts", "-config=worker.rig.config.ts"]);
|
|
118
|
+
} finally {
|
|
119
|
+
rmSync(cwd, { recursive: true, force: true });
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
|
|
50
123
|
test("completes workspace operation targets", async () => {
|
|
51
124
|
const projectDir = mkdtempSync(join(tmpdir(), "rigkit-completion-"));
|
|
52
125
|
await withWorkspaceRuntime({ projectDir }, async () => {
|
|
@@ -56,7 +129,7 @@ describe("CLI completion", () => {
|
|
|
56
129
|
currentIndex: 2,
|
|
57
130
|
});
|
|
58
131
|
expect(roots.map((item) => item.value)).toEqual(["api", "web"]);
|
|
59
|
-
expect(roots[0]).toMatchObject({ description: "
|
|
132
|
+
expect(roots[0]).toMatchObject({ description: "created 2h ago" });
|
|
60
133
|
|
|
61
134
|
const exactWorkspace = await completeRig({
|
|
62
135
|
cwd: projectDir,
|
|
@@ -81,6 +154,26 @@ describe("CLI completion", () => {
|
|
|
81
154
|
});
|
|
82
155
|
});
|
|
83
156
|
|
|
157
|
+
test("completes rm workspace targets and confirmation flags", async () => {
|
|
158
|
+
const projectDir = mkdtempSync(join(tmpdir(), "rigkit-completion-"));
|
|
159
|
+
await withWorkspaceRuntime({ projectDir }, async () => {
|
|
160
|
+
const workspaces = await completeRig({
|
|
161
|
+
cwd: projectDir,
|
|
162
|
+
words: ["rig", "rm", ""],
|
|
163
|
+
currentIndex: 2,
|
|
164
|
+
});
|
|
165
|
+
expect(workspaces.map((item) => item.value)).toEqual(["api", "web"]);
|
|
166
|
+
|
|
167
|
+
const flags = await completeRig({
|
|
168
|
+
cwd: projectDir,
|
|
169
|
+
words: ["rig", "rm", "api", "-"],
|
|
170
|
+
currentIndex: 3,
|
|
171
|
+
});
|
|
172
|
+
expect(flags.map((item) => item.value)).toContain("-y");
|
|
173
|
+
expect(flags.map((item) => item.value)).toContain("--yes");
|
|
174
|
+
});
|
|
175
|
+
});
|
|
176
|
+
|
|
84
177
|
test("completes top-level project commands at the root command position", async () => {
|
|
85
178
|
const projectDir = mkdtempSync(join(tmpdir(), "rigkit-completion-"));
|
|
86
179
|
await withWorkspaceRuntime({ projectDir }, async () => {
|
|
@@ -94,25 +187,63 @@ describe("CLI completion", () => {
|
|
|
94
187
|
});
|
|
95
188
|
});
|
|
96
189
|
|
|
190
|
+
test("completes cache at the root command position after global options", async () => {
|
|
191
|
+
const items = await completeRig({
|
|
192
|
+
cwd: process.cwd(),
|
|
193
|
+
words: ["rig", "-config=api.rig.config.ts", "c"],
|
|
194
|
+
currentIndex: 2,
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
expect(items.map((item) => item.value)).toEqual(["create", "cache", "completion"]);
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
test("completes cache subcommands and flags", async () => {
|
|
201
|
+
const subcommands = await completeRig({
|
|
202
|
+
cwd: process.cwd(),
|
|
203
|
+
words: ["rig", "cache", ""],
|
|
204
|
+
currentIndex: 2,
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
expect(subcommands.map((item) => item.value)).toEqual(["ls", "clear"]);
|
|
208
|
+
|
|
209
|
+
const clearFlags = await completeRig({
|
|
210
|
+
cwd: process.cwd(),
|
|
211
|
+
words: ["rig", "cache", "clear", "--"],
|
|
212
|
+
currentIndex: 3,
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
expect(clearFlags.map((item) => item.value)).toEqual([
|
|
216
|
+
"--local",
|
|
217
|
+
"--global",
|
|
218
|
+
"--all",
|
|
219
|
+
"--json",
|
|
220
|
+
]);
|
|
221
|
+
});
|
|
222
|
+
|
|
97
223
|
test("formats shell completion items", () => {
|
|
98
224
|
const items = [{ value: "api", description: "vm-api" }];
|
|
99
225
|
|
|
100
226
|
expect(formatCompletionItems(items, "bash")).toBe("api");
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
227
|
+
// zsh wire format is `value\tdescription\tmarker\tgroup`. Empty trailing
|
|
228
|
+
// fields are kept so the shell-side parser can index positionally.
|
|
229
|
+
expect(formatCompletionItems(items, "zsh")).toBe("api\tvm-api\t\t");
|
|
230
|
+
expect(formatCompletionItems(
|
|
231
|
+
[{ value: "api", description: "workspace smoke", noSpace: true, group: "Workspaces" }],
|
|
232
|
+
"zsh",
|
|
233
|
+
)).toBe("api\tworkspace smoke\tnospace\tWorkspaces");
|
|
104
234
|
expect(renderCompletionScript("zsh")).toContain("rig __complete");
|
|
105
|
-
expect(renderCompletionScript("zsh")).toContain("
|
|
106
|
-
expect(renderCompletionScript("zsh")).toContain(
|
|
235
|
+
expect(renderCompletionScript("zsh")).toContain("_describe");
|
|
236
|
+
expect(renderCompletionScript("zsh")).toContain(":completion:*:rig:*:descriptions");
|
|
237
|
+
expect(renderCompletionScript("zsh")).toContain("compdef _rig rig");
|
|
107
238
|
});
|
|
108
239
|
|
|
109
240
|
test("formats workspace ages", () => {
|
|
110
241
|
const now = Date.parse("2026-05-14T12:00:00.000Z");
|
|
111
242
|
|
|
112
243
|
expect(formatWorkspaceAge("2026-05-14T11:59:45.000Z", now)).toBe("just now");
|
|
113
|
-
expect(formatWorkspaceAge("2026-05-14T11:30:00.000Z", now)).toBe("30m
|
|
114
|
-
expect(formatWorkspaceAge("2026-05-14T09:00:00.000Z", now)).toBe("3h
|
|
115
|
-
expect(formatWorkspaceAge("2026-05-11T12:00:00.000Z", now)).toBe("3d
|
|
244
|
+
expect(formatWorkspaceAge("2026-05-14T11:30:00.000Z", now)).toBe("30m ago");
|
|
245
|
+
expect(formatWorkspaceAge("2026-05-14T09:00:00.000Z", now)).toBe("3h ago");
|
|
246
|
+
expect(formatWorkspaceAge("2026-05-11T12:00:00.000Z", now)).toBe("3d ago");
|
|
116
247
|
expect(formatWorkspaceAge("not-a-date", now)).toBeUndefined();
|
|
117
248
|
});
|
|
118
249
|
|