@urateam/cli 0.1.39 → 0.1.41

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.
Files changed (61) hide show
  1. package/dist/__tests__/init.test.d.ts +2 -0
  2. package/dist/__tests__/init.test.d.ts.map +1 -0
  3. package/dist/__tests__/init.test.js +65 -0
  4. package/dist/__tests__/init.test.js.map +1 -0
  5. package/dist/__tests__/repo.test.d.ts +2 -0
  6. package/dist/__tests__/repo.test.d.ts.map +1 -0
  7. package/dist/__tests__/repo.test.js +191 -0
  8. package/dist/__tests__/repo.test.js.map +1 -0
  9. package/dist/__tests__/service-unit.test.d.ts +2 -0
  10. package/dist/__tests__/service-unit.test.d.ts.map +1 -0
  11. package/dist/__tests__/service-unit.test.js +65 -0
  12. package/dist/__tests__/service-unit.test.js.map +1 -0
  13. package/dist/__tests__/service.test.d.ts +2 -0
  14. package/dist/__tests__/service.test.d.ts.map +1 -0
  15. package/dist/__tests__/service.test.js +193 -0
  16. package/dist/__tests__/service.test.js.map +1 -0
  17. package/dist/__tests__/start-user-level-fallback.test.d.ts +2 -0
  18. package/dist/__tests__/start-user-level-fallback.test.d.ts.map +1 -0
  19. package/dist/__tests__/start-user-level-fallback.test.js +191 -0
  20. package/dist/__tests__/start-user-level-fallback.test.js.map +1 -0
  21. package/dist/__tests__/uninstall.test.d.ts +2 -0
  22. package/dist/__tests__/uninstall.test.d.ts.map +1 -0
  23. package/dist/__tests__/uninstall.test.js +51 -0
  24. package/dist/__tests__/uninstall.test.js.map +1 -0
  25. package/dist/__tests__/user-level-config.test.d.ts +2 -0
  26. package/dist/__tests__/user-level-config.test.d.ts.map +1 -0
  27. package/dist/__tests__/user-level-config.test.js +92 -0
  28. package/dist/__tests__/user-level-config.test.js.map +1 -0
  29. package/dist/commands/init.d.ts +11 -0
  30. package/dist/commands/init.d.ts.map +1 -0
  31. package/dist/commands/init.js +27 -0
  32. package/dist/commands/init.js.map +1 -0
  33. package/dist/commands/repo.d.ts +7 -0
  34. package/dist/commands/repo.d.ts.map +1 -0
  35. package/dist/commands/repo.js +126 -0
  36. package/dist/commands/repo.js.map +1 -0
  37. package/dist/commands/service.d.ts +13 -0
  38. package/dist/commands/service.d.ts.map +1 -0
  39. package/dist/commands/service.js +164 -0
  40. package/dist/commands/service.js.map +1 -0
  41. package/dist/commands/start.d.ts.map +1 -1
  42. package/dist/commands/start.js +25 -0
  43. package/dist/commands/start.js.map +1 -1
  44. package/dist/commands/uninstall.d.ts +17 -0
  45. package/dist/commands/uninstall.d.ts.map +1 -0
  46. package/dist/commands/uninstall.js +38 -0
  47. package/dist/commands/uninstall.js.map +1 -0
  48. package/dist/index.js +8 -0
  49. package/dist/index.js.map +1 -1
  50. package/dist/lib/build-repo-configs.d.ts.map +1 -1
  51. package/dist/lib/build-repo-configs.js +85 -27
  52. package/dist/lib/build-repo-configs.js.map +1 -1
  53. package/dist/lib/service-unit.d.ts +25 -0
  54. package/dist/lib/service-unit.d.ts.map +1 -0
  55. package/dist/lib/service-unit.js +67 -0
  56. package/dist/lib/service-unit.js.map +1 -0
  57. package/dist/lib/user-level-config.d.ts +70 -0
  58. package/dist/lib/user-level-config.d.ts.map +1 -0
  59. package/dist/lib/user-level-config.js +91 -0
  60. package/dist/lib/user-level-config.js.map +1 -0
  61. package/package.json +4 -3
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=init.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/init.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,65 @@
1
+ /**
2
+ * `ura init` — bootstrap a user-level urateam install.
3
+ *
4
+ * Creates `~/.urateam/` (or `$URATEAM_HOME`) with an empty `config.json`,
5
+ * a `data/` directory for the SQLite DB, and a `repos/` directory for
6
+ * managed clones. Idempotent: re-running on an already-initialized
7
+ * directory leaves the existing config untouched.
8
+ */
9
+ import { describe, it, expect, beforeEach, afterEach, vi } from "vitest";
10
+ import { mkdtempSync, rmSync, existsSync, readFileSync, writeFileSync, } from "node:fs";
11
+ import { join } from "node:path";
12
+ import { tmpdir } from "node:os";
13
+ import { initCommand } from "../commands/init.js";
14
+ describe("ura init", () => {
15
+ let tmp;
16
+ beforeEach(() => {
17
+ tmp = mkdtempSync(join(tmpdir(), "ura-init-"));
18
+ process.env.URATEAM_HOME = tmp;
19
+ });
20
+ afterEach(() => {
21
+ delete process.env.URATEAM_HOME;
22
+ rmSync(tmp, { recursive: true, force: true });
23
+ });
24
+ it("creates config.json, data/, repos/ under URATEAM_HOME", async () => {
25
+ await initCommand.parseAsync([], { from: "user" });
26
+ expect(existsSync(join(tmp, "config.json"))).toBe(true);
27
+ expect(existsSync(join(tmp, "data"))).toBe(true);
28
+ expect(existsSync(join(tmp, "repos"))).toBe(true);
29
+ });
30
+ it("seeds config.json with version=1 and an empty repos array", async () => {
31
+ await initCommand.parseAsync([], { from: "user" });
32
+ const raw = JSON.parse(readFileSync(join(tmp, "config.json"), "utf8"));
33
+ expect(raw.version).toBe(1);
34
+ expect(raw.repos).toEqual([]);
35
+ });
36
+ it("is idempotent: re-running does not overwrite an existing config", async () => {
37
+ await initCommand.parseAsync([], { from: "user" });
38
+ const path = join(tmp, "config.json");
39
+ const mutated = {
40
+ version: 1,
41
+ repos: [
42
+ {
43
+ url: "https://github.com/o/r.git",
44
+ path: "/tmp/r",
45
+ defaultBranch: "main",
46
+ testCommand: "pnpm test",
47
+ buildCommand: "pnpm build",
48
+ },
49
+ ],
50
+ };
51
+ writeFileSync(path, JSON.stringify(mutated));
52
+ await initCommand.parseAsync([], { from: "user" });
53
+ const after = JSON.parse(readFileSync(path, "utf8"));
54
+ expect(after.repos).toHaveLength(1);
55
+ });
56
+ it("prints the location it created on first run", async () => {
57
+ const spy = vi.spyOn(console, "log").mockImplementation(() => { });
58
+ await initCommand.parseAsync([], { from: "user" });
59
+ const out = spy.mock.calls.flat().join("\n");
60
+ expect(out).toContain(tmp);
61
+ expect(out).toMatch(/ura repo add/);
62
+ spy.mockRestore();
63
+ });
64
+ });
65
+ //# sourceMappingURL=init.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.test.js","sourceRoot":"","sources":["../../src/__tests__/init.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=repo.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repo.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/repo.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,191 @@
1
+ /**
2
+ * `ura repo {add,list,remove}` — manage repos in the user-level config.
3
+ *
4
+ * `add`: clones the repo into `~/.urateam/repos/<slug>` and appends to
5
+ * `config.json`. Slug derived from the URL's trailing path
6
+ * (foo/bar.git → bar).
7
+ * `list`: prints each configured repo.
8
+ * `remove`: filters the repo out of `config.json`. The clone on disk is
9
+ * preserved by default — `--purge` deletes it.
10
+ *
11
+ * Tests stub `cloneRepo` (from `@urateam/core`) so they don't touch the
12
+ * network or git.
13
+ */
14
+ import { describe, it, expect, beforeEach, afterEach, vi } from "vitest";
15
+ import { mkdtempSync, rmSync, mkdirSync, writeFileSync, existsSync, } from "node:fs";
16
+ import { join } from "node:path";
17
+ import { tmpdir } from "node:os";
18
+ import { repoCommand } from "../commands/repo.js";
19
+ import { readUserLevelConfig, writeUserLevelConfig, } from "../lib/user-level-config.js";
20
+ vi.mock("@urateam/core", async () => {
21
+ const actual = await vi.importActual("@urateam/core");
22
+ return {
23
+ ...actual,
24
+ cloneRepo: vi.fn(async (url, dest) => {
25
+ mkdirSync(dest, { recursive: true });
26
+ writeFileSync(join(dest, ".cloned"), url);
27
+ }),
28
+ };
29
+ });
30
+ describe("ura repo add", () => {
31
+ let tmp;
32
+ beforeEach(() => {
33
+ tmp = mkdtempSync(join(tmpdir(), "ura-repo-"));
34
+ process.env.URATEAM_HOME = tmp;
35
+ writeUserLevelConfig({ version: 1, repos: [] });
36
+ });
37
+ afterEach(() => {
38
+ delete process.env.URATEAM_HOME;
39
+ rmSync(tmp, { recursive: true, force: true });
40
+ });
41
+ it("clones into ~/.urateam/repos/<slug> and appends to config.json", async () => {
42
+ await repoCommand.parseAsync(["add", "https://github.com/foo/bar.git"], { from: "user" });
43
+ const cfg = readUserLevelConfig();
44
+ expect(cfg?.repos).toHaveLength(1);
45
+ expect(cfg?.repos[0].url).toBe("https://github.com/foo/bar.git");
46
+ expect(cfg?.repos[0].path).toBe(join(tmp, "repos", "bar"));
47
+ expect(cfg?.repos[0].defaultBranch).toBe("main");
48
+ });
49
+ it("rejects duplicate URLs", async () => {
50
+ await repoCommand.parseAsync(["add", "https://github.com/foo/bar.git"], { from: "user" });
51
+ await expect(repoCommand.parseAsync(["add", "https://github.com/foo/bar.git"], { from: "user" })).rejects.toThrow(/already configured/i);
52
+ });
53
+ it("derives slug from .git URL trailing path (foo/bar.git → bar)", async () => {
54
+ await repoCommand.parseAsync(["add", "git@github.com:org/awesome-tool.git"], { from: "user" });
55
+ expect(readUserLevelConfig()?.repos[0].path).toContain("awesome-tool");
56
+ });
57
+ it("accepts --branch override", async () => {
58
+ await repoCommand.parseAsync([
59
+ "add",
60
+ "https://github.com/foo/bar.git",
61
+ "--branch",
62
+ "develop",
63
+ ], { from: "user" });
64
+ expect(readUserLevelConfig()?.repos[0].defaultBranch).toBe("develop");
65
+ });
66
+ it("accepts --team and --label-pattern", async () => {
67
+ await repoCommand.parseAsync([
68
+ "add",
69
+ "https://github.com/foo/bar.git",
70
+ "--team",
71
+ "team-abc",
72
+ "--label-pattern",
73
+ "auto-implement",
74
+ ], { from: "user" });
75
+ const repo = readUserLevelConfig()?.repos[0];
76
+ expect(repo?.teamId).toBe("team-abc");
77
+ expect(repo?.labelPattern).toBe("auto-implement");
78
+ });
79
+ it("errors when 'ura init' has not been run", async () => {
80
+ // Wipe the seeded config so the next call sees a clean slate.
81
+ rmSync(tmp, { recursive: true, force: true });
82
+ mkdirSync(tmp, { recursive: true });
83
+ await expect(repoCommand.parseAsync(["add", "https://github.com/foo/bar.git"], { from: "user" })).rejects.toThrow(/ura init/i);
84
+ });
85
+ });
86
+ describe("ura repo list", () => {
87
+ let tmp;
88
+ beforeEach(() => {
89
+ tmp = mkdtempSync(join(tmpdir(), "ura-list-"));
90
+ process.env.URATEAM_HOME = tmp;
91
+ writeUserLevelConfig({
92
+ version: 1,
93
+ repos: [
94
+ {
95
+ url: "https://github.com/a/x.git",
96
+ path: "/p/x",
97
+ defaultBranch: "main",
98
+ testCommand: "pnpm test",
99
+ buildCommand: "pnpm build",
100
+ },
101
+ {
102
+ url: "https://github.com/a/y.git",
103
+ path: "/p/y",
104
+ defaultBranch: "main",
105
+ testCommand: "pnpm test",
106
+ buildCommand: "pnpm build",
107
+ },
108
+ ],
109
+ });
110
+ });
111
+ afterEach(() => {
112
+ delete process.env.URATEAM_HOME;
113
+ rmSync(tmp, { recursive: true, force: true });
114
+ });
115
+ it("prints each repo's url + path on its own line", async () => {
116
+ const spy = vi.spyOn(console, "log").mockImplementation(() => { });
117
+ await repoCommand.parseAsync(["list"], { from: "user" });
118
+ const lines = spy.mock.calls.flat().join("\n");
119
+ expect(lines).toContain("https://github.com/a/x.git");
120
+ expect(lines).toContain("https://github.com/a/y.git");
121
+ spy.mockRestore();
122
+ });
123
+ it("prints an empty-state message when no repos are configured", async () => {
124
+ writeUserLevelConfig({ version: 1, repos: [] });
125
+ const spy = vi.spyOn(console, "log").mockImplementation(() => { });
126
+ await repoCommand.parseAsync(["list"], { from: "user" });
127
+ expect(spy.mock.calls.flat().join("\n")).toMatch(/no repos/i);
128
+ spy.mockRestore();
129
+ });
130
+ });
131
+ describe("ura repo remove", () => {
132
+ let tmp;
133
+ beforeEach(() => {
134
+ tmp = mkdtempSync(join(tmpdir(), "ura-remove-"));
135
+ process.env.URATEAM_HOME = tmp;
136
+ writeUserLevelConfig({
137
+ version: 1,
138
+ repos: [
139
+ {
140
+ url: "https://github.com/a/x.git",
141
+ path: join(tmp, "repos", "x"),
142
+ defaultBranch: "main",
143
+ testCommand: "pnpm test",
144
+ buildCommand: "pnpm build",
145
+ },
146
+ ],
147
+ });
148
+ mkdirSync(join(tmp, "repos", "x"), { recursive: true });
149
+ });
150
+ afterEach(() => {
151
+ delete process.env.URATEAM_HOME;
152
+ rmSync(tmp, { recursive: true, force: true });
153
+ });
154
+ it("removes the matching entry from config.json", async () => {
155
+ await repoCommand.parseAsync(["remove", "x"], { from: "user" });
156
+ expect(readUserLevelConfig()?.repos).toHaveLength(0);
157
+ });
158
+ it("preserves the clone on disk by default (no --purge)", async () => {
159
+ await repoCommand.parseAsync(["remove", "x"], { from: "user" });
160
+ expect(existsSync(join(tmp, "repos", "x"))).toBe(true);
161
+ });
162
+ it("deletes the clone when --purge is passed", async () => {
163
+ await repoCommand.parseAsync(["remove", "x", "--purge"], {
164
+ from: "user",
165
+ });
166
+ expect(existsSync(join(tmp, "repos", "x"))).toBe(false);
167
+ });
168
+ it("errors when the slug does not match any configured repo", async () => {
169
+ await expect(repoCommand.parseAsync(["remove", "nonexistent"], { from: "user" })).rejects.toThrow(/not found/i);
170
+ });
171
+ it("refuses to --purge a path outside URATEAM_HOME (hand-edited config safety)", async () => {
172
+ // Simulate a hand-edited config.json with a dangerous path. The path's
173
+ // basename ("etc-fake-sensitive") must match the slug arg so the entry
174
+ // is found; the test exercises the path-safety guard, not the
175
+ // slug-lookup path.
176
+ writeUserLevelConfig({
177
+ version: 1,
178
+ repos: [
179
+ {
180
+ url: "https://github.com/a/etc-fake-sensitive.git",
181
+ path: "/tmp/SAFETY_TEST_DO_NOT_DELETE/etc-fake-sensitive",
182
+ defaultBranch: "main",
183
+ testCommand: "pnpm test",
184
+ buildCommand: "pnpm build",
185
+ },
186
+ ],
187
+ });
188
+ await expect(repoCommand.parseAsync(["remove", "etc-fake-sensitive", "--purge"], { from: "user" })).rejects.toThrow(/refusing to delete/i);
189
+ });
190
+ });
191
+ //# sourceMappingURL=repo.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repo.test.js","sourceRoot":"","sources":["../../src/__tests__/repo.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=service-unit.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"service-unit.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/service-unit.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,65 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import { renderLaunchdPlist, renderSystemdUserUnit, } from "../lib/service-unit.js";
3
+ const FIXTURE = {
4
+ binaryPath: "/usr/local/bin/ura",
5
+ urateamHome: "/Users/x/.urateam",
6
+ envFilePath: "/Users/x/.urateam/.env",
7
+ stdoutPath: "/Users/x/.urateam/data/daemon.log",
8
+ stderrPath: "/Users/x/.urateam/data/daemon.err.log",
9
+ };
10
+ describe("renderLaunchdPlist", () => {
11
+ it("includes the binary path under ProgramArguments", () => {
12
+ const out = renderLaunchdPlist(FIXTURE);
13
+ expect(out).toContain("<string>/usr/local/bin/ura</string>");
14
+ expect(out).toContain("<string>start</string>");
15
+ });
16
+ it("propagates URATEAM_HOME via EnvironmentVariables", () => {
17
+ const out = renderLaunchdPlist(FIXTURE);
18
+ expect(out).toContain("<key>URATEAM_HOME</key>");
19
+ expect(out).toContain("<string>/Users/x/.urateam</string>");
20
+ });
21
+ it("sets RunAtLoad and KeepAlive", () => {
22
+ const out = renderLaunchdPlist(FIXTURE);
23
+ expect(out).toMatch(/<key>RunAtLoad<\/key>\s*<true\/>/);
24
+ expect(out).toMatch(/<key>KeepAlive<\/key>\s*<true\/>/);
25
+ });
26
+ it("emits stdout and stderr log paths", () => {
27
+ const out = renderLaunchdPlist(FIXTURE);
28
+ expect(out).toContain("/Users/x/.urateam/data/daemon.log");
29
+ expect(out).toContain("/Users/x/.urateam/data/daemon.err.log");
30
+ });
31
+ it("starts with the XML declaration", () => {
32
+ expect(renderLaunchdPlist(FIXTURE).startsWith('<?xml version="1.0"')).toBe(true);
33
+ });
34
+ it("is deterministic — same input produces byte-for-byte same output", () => {
35
+ expect(renderLaunchdPlist(FIXTURE)).toBe(renderLaunchdPlist(FIXTURE));
36
+ });
37
+ it("matches the canonical snapshot", () => {
38
+ expect(renderLaunchdPlist(FIXTURE)).toMatchSnapshot();
39
+ });
40
+ });
41
+ describe("renderSystemdUserUnit", () => {
42
+ it("uses simple service type", () => {
43
+ expect(renderSystemdUserUnit(FIXTURE)).toContain("Type=simple");
44
+ });
45
+ it("sets ExecStart to the binary + 'start'", () => {
46
+ expect(renderSystemdUserUnit(FIXTURE)).toContain("ExecStart=/usr/local/bin/ura start");
47
+ });
48
+ it("propagates URATEAM_HOME via Environment", () => {
49
+ const out = renderSystemdUserUnit(FIXTURE);
50
+ expect(out).toContain("Environment=URATEAM_HOME=/Users/x/.urateam");
51
+ });
52
+ it("sets EnvironmentFile to the resolved .env path", () => {
53
+ expect(renderSystemdUserUnit(FIXTURE)).toContain("EnvironmentFile=/Users/x/.urateam/.env");
54
+ });
55
+ it("uses WantedBy=default.target so user-mode systemd picks it up", () => {
56
+ expect(renderSystemdUserUnit(FIXTURE)).toContain("WantedBy=default.target");
57
+ });
58
+ it("sets Restart=always", () => {
59
+ expect(renderSystemdUserUnit(FIXTURE)).toContain("Restart=always");
60
+ });
61
+ it("matches the canonical snapshot", () => {
62
+ expect(renderSystemdUserUnit(FIXTURE)).toMatchSnapshot();
63
+ });
64
+ });
65
+ //# sourceMappingURL=service-unit.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"service-unit.test.js","sourceRoot":"","sources":["../../src/__tests__/service-unit.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=service.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"service.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/service.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,193 @@
1
+ import { describe, it, expect, beforeEach, afterEach, vi } from "vitest";
2
+ import { mkdtempSync, rmSync, existsSync, readFileSync, writeFileSync, mkdirSync, } from "node:fs";
3
+ import { join } from "node:path";
4
+ import { tmpdir } from "node:os";
5
+ const execFileMock = vi.fn(async (_cmd, _args) => ({
6
+ stdout: "",
7
+ stderr: "",
8
+ }));
9
+ vi.mock("node:child_process", async () => {
10
+ const actual = await vi.importActual("node:child_process");
11
+ return {
12
+ ...actual,
13
+ execFile: (cmd, args, cb) => {
14
+ execFileMock(cmd, args)
15
+ .then((r) => cb(null, r.stdout, r.stderr))
16
+ .catch((e) => cb(e));
17
+ },
18
+ };
19
+ });
20
+ let fakeHome;
21
+ vi.mock("node:os", async () => {
22
+ const actual = await vi.importActual("node:os");
23
+ return {
24
+ ...actual,
25
+ homedir: () => fakeHome,
26
+ userInfo: () => ({ username: "tester" }),
27
+ };
28
+ });
29
+ const { serviceCommand } = await import("../commands/service.js");
30
+ describe("ura service install (darwin)", () => {
31
+ let tmp;
32
+ let originalPlatform;
33
+ beforeEach(() => {
34
+ tmp = mkdtempSync(join(tmpdir(), "ura-service-"));
35
+ fakeHome = tmp;
36
+ mkdirSync(join(tmp, "Library", "LaunchAgents"), { recursive: true });
37
+ mkdirSync(join(tmp, ".urateam", "data"), { recursive: true });
38
+ process.env.URATEAM_HOME = join(tmp, ".urateam");
39
+ originalPlatform = Object.getOwnPropertyDescriptor(process, "platform");
40
+ Object.defineProperty(process, "platform", { value: "darwin" });
41
+ execFileMock.mockClear();
42
+ });
43
+ afterEach(() => {
44
+ delete process.env.URATEAM_HOME;
45
+ Object.defineProperty(process, "platform", originalPlatform);
46
+ rmSync(tmp, { recursive: true, force: true });
47
+ });
48
+ it("writes the plist and loads it via launchctl", async () => {
49
+ await serviceCommand.parseAsync(["install"], { from: "user" });
50
+ const plist = join(tmp, "Library", "LaunchAgents", "com.urateam.daemon.plist");
51
+ expect(existsSync(plist)).toBe(true);
52
+ const content = readFileSync(plist, "utf8");
53
+ expect(content).toContain("<key>Label</key>");
54
+ expect(content).toContain("com.urateam.daemon");
55
+ const launchctlCalls = execFileMock.mock.calls.filter(([cmd]) => cmd === "launchctl");
56
+ expect(launchctlCalls.length).toBeGreaterThanOrEqual(1);
57
+ expect(launchctlCalls.some(([, args]) => args.includes("load"))).toBe(true);
58
+ });
59
+ it("--dry-run prints the plist and writes nothing", async () => {
60
+ const spy = vi.spyOn(console, "log").mockImplementation(() => { });
61
+ await serviceCommand.parseAsync(["install", "--dry-run"], { from: "user" });
62
+ const plist = join(tmp, "Library", "LaunchAgents", "com.urateam.daemon.plist");
63
+ expect(existsSync(plist)).toBe(false);
64
+ const out = spy.mock.calls.flat().join("\n");
65
+ expect(out).toContain("<?xml");
66
+ expect(out).toContain("com.urateam.daemon");
67
+ expect(execFileMock).not.toHaveBeenCalled();
68
+ spy.mockRestore();
69
+ });
70
+ it("is idempotent: skips when the plist already exists", async () => {
71
+ const plist = join(tmp, "Library", "LaunchAgents", "com.urateam.daemon.plist");
72
+ writeFileSync(plist, "<!-- existing -->");
73
+ const spy = vi.spyOn(console, "log").mockImplementation(() => { });
74
+ await serviceCommand.parseAsync(["install"], { from: "user" });
75
+ expect(readFileSync(plist, "utf8")).toBe("<!-- existing -->");
76
+ expect(spy.mock.calls.flat().join("\n")).toMatch(/already exists/i);
77
+ expect(execFileMock).not.toHaveBeenCalled();
78
+ spy.mockRestore();
79
+ });
80
+ });
81
+ describe("ura service install (linux)", () => {
82
+ let tmp;
83
+ let originalPlatform;
84
+ beforeEach(() => {
85
+ tmp = mkdtempSync(join(tmpdir(), "ura-service-"));
86
+ fakeHome = tmp;
87
+ mkdirSync(join(tmp, ".config", "systemd", "user"), { recursive: true });
88
+ mkdirSync(join(tmp, ".urateam", "data"), { recursive: true });
89
+ process.env.URATEAM_HOME = join(tmp, ".urateam");
90
+ originalPlatform = Object.getOwnPropertyDescriptor(process, "platform");
91
+ Object.defineProperty(process, "platform", { value: "linux" });
92
+ execFileMock.mockClear();
93
+ });
94
+ afterEach(() => {
95
+ delete process.env.URATEAM_HOME;
96
+ Object.defineProperty(process, "platform", originalPlatform);
97
+ rmSync(tmp, { recursive: true, force: true });
98
+ });
99
+ it("writes the systemd unit and runs daemon-reload + enable --now", async () => {
100
+ await serviceCommand.parseAsync(["install"], { from: "user" });
101
+ const unit = join(tmp, ".config", "systemd", "user", "urateam.service");
102
+ expect(existsSync(unit)).toBe(true);
103
+ expect(readFileSync(unit, "utf8")).toContain("ExecStart=");
104
+ const systemctlCalls = execFileMock.mock.calls.filter(([cmd]) => cmd === "systemctl");
105
+ expect(systemctlCalls.some(([, args]) => args.includes("daemon-reload"))).toBe(true);
106
+ expect(systemctlCalls.some(([, args]) => args.includes("enable") && args.includes("urateam.service"))).toBe(true);
107
+ });
108
+ });
109
+ describe("ura service install (unsupported platform)", () => {
110
+ let originalPlatform;
111
+ beforeEach(() => {
112
+ originalPlatform = Object.getOwnPropertyDescriptor(process, "platform");
113
+ Object.defineProperty(process, "platform", { value: "win32" });
114
+ });
115
+ afterEach(() => {
116
+ Object.defineProperty(process, "platform", originalPlatform);
117
+ });
118
+ it("fails with a clear message", async () => {
119
+ await expect(serviceCommand.parseAsync(["install"], { from: "user" })).rejects.toThrow(/unsupported platform/i);
120
+ });
121
+ });
122
+ describe("ura service uninstall (linux)", () => {
123
+ let tmp;
124
+ let originalPlatform;
125
+ beforeEach(() => {
126
+ tmp = mkdtempSync(join(tmpdir(), "ura-service-"));
127
+ fakeHome = tmp;
128
+ mkdirSync(join(tmp, ".config", "systemd", "user"), { recursive: true });
129
+ originalPlatform = Object.getOwnPropertyDescriptor(process, "platform");
130
+ Object.defineProperty(process, "platform", { value: "linux" });
131
+ execFileMock.mockClear();
132
+ });
133
+ afterEach(() => {
134
+ Object.defineProperty(process, "platform", originalPlatform);
135
+ rmSync(tmp, { recursive: true, force: true });
136
+ });
137
+ it("disables and deletes the unit when present", async () => {
138
+ const unit = join(tmp, ".config", "systemd", "user", "urateam.service");
139
+ writeFileSync(unit, "[Unit]\n");
140
+ await serviceCommand.parseAsync(["uninstall"], { from: "user" });
141
+ expect(existsSync(unit)).toBe(false);
142
+ expect(execFileMock.mock.calls.some(([cmd, args]) => cmd === "systemctl" &&
143
+ args.includes("disable") &&
144
+ args.includes("urateam.service"))).toBe(true);
145
+ });
146
+ it("is a no-op when the unit is already absent", async () => {
147
+ const spy = vi.spyOn(console, "log").mockImplementation(() => { });
148
+ await serviceCommand.parseAsync(["uninstall"], { from: "user" });
149
+ expect(spy.mock.calls.flat().join("\n")).toMatch(/not installed/i);
150
+ expect(execFileMock).not.toHaveBeenCalled();
151
+ spy.mockRestore();
152
+ });
153
+ it("still deletes the unit when systemctl disable fails (best-effort stop)", async () => {
154
+ const unit = join(tmp, ".config", "systemd", "user", "urateam.service");
155
+ writeFileSync(unit, "[Unit]\n");
156
+ execFileMock.mockImplementationOnce(async () => {
157
+ throw new Error("Failed to disable urateam.service: not loaded");
158
+ });
159
+ await serviceCommand.parseAsync(["uninstall"], { from: "user" });
160
+ expect(existsSync(unit)).toBe(false);
161
+ });
162
+ });
163
+ describe("ura service uninstall (darwin)", () => {
164
+ let tmp;
165
+ let originalPlatform;
166
+ beforeEach(() => {
167
+ tmp = mkdtempSync(join(tmpdir(), "ura-service-"));
168
+ fakeHome = tmp;
169
+ mkdirSync(join(tmp, "Library", "LaunchAgents"), { recursive: true });
170
+ originalPlatform = Object.getOwnPropertyDescriptor(process, "platform");
171
+ Object.defineProperty(process, "platform", { value: "darwin" });
172
+ execFileMock.mockClear();
173
+ });
174
+ afterEach(() => {
175
+ Object.defineProperty(process, "platform", originalPlatform);
176
+ rmSync(tmp, { recursive: true, force: true });
177
+ });
178
+ it("unloads and deletes the plist when present", async () => {
179
+ const plist = join(tmp, "Library", "LaunchAgents", "com.urateam.daemon.plist");
180
+ writeFileSync(plist, "<!-- existing -->");
181
+ await serviceCommand.parseAsync(["uninstall"], { from: "user" });
182
+ expect(existsSync(plist)).toBe(false);
183
+ expect(execFileMock.mock.calls.some(([cmd, args]) => cmd === "launchctl" && args.includes("unload"))).toBe(true);
184
+ });
185
+ it("is a no-op when the plist is already absent", async () => {
186
+ const spy = vi.spyOn(console, "log").mockImplementation(() => { });
187
+ await serviceCommand.parseAsync(["uninstall"], { from: "user" });
188
+ expect(spy.mock.calls.flat().join("\n")).toMatch(/not installed/i);
189
+ expect(execFileMock).not.toHaveBeenCalled();
190
+ spy.mockRestore();
191
+ });
192
+ });
193
+ //# sourceMappingURL=service.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"service.test.js","sourceRoot":"","sources":["../../src/__tests__/service.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=start-user-level-fallback.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"start-user-level-fallback.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/start-user-level-fallback.test.ts"],"names":[],"mappings":""}