@urateam/cli 0.1.40 → 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.
- package/dist/__tests__/service-unit.test.d.ts +2 -0
- package/dist/__tests__/service-unit.test.d.ts.map +1 -0
- package/dist/__tests__/service-unit.test.js +65 -0
- package/dist/__tests__/service-unit.test.js.map +1 -0
- package/dist/__tests__/service.test.d.ts +2 -0
- package/dist/__tests__/service.test.d.ts.map +1 -0
- package/dist/__tests__/service.test.js +193 -0
- package/dist/__tests__/service.test.js.map +1 -0
- package/dist/commands/service.d.ts +13 -0
- package/dist/commands/service.d.ts.map +1 -0
- package/dist/commands/service.js +164 -0
- package/dist/commands/service.js.map +1 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/lib/service-unit.d.ts +25 -0
- package/dist/lib/service-unit.d.ts.map +1 -0
- package/dist/lib/service-unit.js +67 -0
- package/dist/lib/service-unit.js.map +1 -0
- package/package.json +3 -3
|
@@ -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 @@
|
|
|
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,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `ura service install` / `ura service uninstall`
|
|
3
|
+
*
|
|
4
|
+
* Generates a platform-appropriate service unit (launchd plist on macOS,
|
|
5
|
+
* systemd-user unit on Linux) so the user-level daemon auto-starts on login.
|
|
6
|
+
* Mirrors what `deploy/USER_LEVEL_INSTALL.md` previously documented as
|
|
7
|
+
* copy-paste blocks. Idempotent: refuses to overwrite an existing unit
|
|
8
|
+
* (operator must uninstall first). `--dry-run` prints the unit content
|
|
9
|
+
* without touching the filesystem.
|
|
10
|
+
*/
|
|
11
|
+
import { Command } from "commander";
|
|
12
|
+
export declare const serviceCommand: Command;
|
|
13
|
+
//# sourceMappingURL=service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../src/commands/service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAwGpC,eAAO,MAAM,cAAc,SAE1B,CAAC"}
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `ura service install` / `ura service uninstall`
|
|
3
|
+
*
|
|
4
|
+
* Generates a platform-appropriate service unit (launchd plist on macOS,
|
|
5
|
+
* systemd-user unit on Linux) so the user-level daemon auto-starts on login.
|
|
6
|
+
* Mirrors what `deploy/USER_LEVEL_INSTALL.md` previously documented as
|
|
7
|
+
* copy-paste blocks. Idempotent: refuses to overwrite an existing unit
|
|
8
|
+
* (operator must uninstall first). `--dry-run` prints the unit content
|
|
9
|
+
* without touching the filesystem.
|
|
10
|
+
*/
|
|
11
|
+
import { Command } from "commander";
|
|
12
|
+
import { execFile } from "node:child_process";
|
|
13
|
+
import { existsSync, mkdirSync, rmSync, writeFileSync, } from "node:fs";
|
|
14
|
+
import { homedir, userInfo } from "node:os";
|
|
15
|
+
import { dirname, join } from "node:path";
|
|
16
|
+
import { promisify } from "node:util";
|
|
17
|
+
import { renderLaunchdPlist, renderSystemdUserUnit, SERVICE_LABEL, SYSTEMD_UNIT_BASENAME, } from "../lib/service-unit.js";
|
|
18
|
+
import { createDb, logAuditEvent, serviceInstalledEvent, serviceUninstalledEvent, } from "@urateam/core";
|
|
19
|
+
import { resolveUserLevelHome, userLevelDataDir, } from "../lib/user-level-config.js";
|
|
20
|
+
const execFileP = promisify(execFile);
|
|
21
|
+
function detectPlatform() {
|
|
22
|
+
if (process.platform === "darwin")
|
|
23
|
+
return "darwin";
|
|
24
|
+
if (process.platform === "linux")
|
|
25
|
+
return "linux";
|
|
26
|
+
throw new Error(`ura service: unsupported platform '${process.platform}'. ` +
|
|
27
|
+
`Only macOS (launchd) and Linux (systemd-user) are supported. ` +
|
|
28
|
+
`For other platforms, see the manual service-setup snippets in ` +
|
|
29
|
+
`deploy/USER_LEVEL_INSTALL.md.`);
|
|
30
|
+
}
|
|
31
|
+
function unitPath(platform) {
|
|
32
|
+
if (platform === "darwin") {
|
|
33
|
+
return join(homedir(), "Library", "LaunchAgents", `${SERVICE_LABEL}.plist`);
|
|
34
|
+
}
|
|
35
|
+
return join(homedir(), ".config", "systemd", "user", SYSTEMD_UNIT_BASENAME);
|
|
36
|
+
}
|
|
37
|
+
function buildInput() {
|
|
38
|
+
// Resolve the binary the operator invoked us as — that's what the service
|
|
39
|
+
// unit should re-launch. `process.argv[1]` is the `ura` script (commander's
|
|
40
|
+
// entry point); it's already absolute when invoked via the npm-installed
|
|
41
|
+
// shim. Fall back to the common npm-global location if anything looks off.
|
|
42
|
+
let binaryPath = process.argv[1] ?? "/usr/local/bin/ura";
|
|
43
|
+
if (!binaryPath.startsWith("/"))
|
|
44
|
+
binaryPath = "/usr/local/bin/ura";
|
|
45
|
+
const home = resolveUserLevelHome();
|
|
46
|
+
return {
|
|
47
|
+
binaryPath,
|
|
48
|
+
urateamHome: home,
|
|
49
|
+
envFilePath: join(home, ".env"),
|
|
50
|
+
stdoutPath: join(userLevelDataDir(), "daemon.log"),
|
|
51
|
+
stderrPath: join(userLevelDataDir(), "daemon.err.log"),
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
async function tryEmitAuditEvent(args) {
|
|
55
|
+
// Opportunistic: only writes when the daemon DB already exists. CLI commands
|
|
56
|
+
// can run before the daemon has ever started, so the DB may not be there
|
|
57
|
+
// yet. Never throws — audit failure must not break the install.
|
|
58
|
+
try {
|
|
59
|
+
const dbPath = join(userLevelDataDir(), "urateam.db");
|
|
60
|
+
if (!existsSync(dbPath))
|
|
61
|
+
return;
|
|
62
|
+
const db = await createDb({ connectionString: dbPath });
|
|
63
|
+
const actor = `cli:${userInfo().username ?? "unknown"}`;
|
|
64
|
+
const builder = args.eventType === "installed"
|
|
65
|
+
? serviceInstalledEvent
|
|
66
|
+
: serviceUninstalledEvent;
|
|
67
|
+
const evt = builder({
|
|
68
|
+
platform: args.platform,
|
|
69
|
+
unitPath: args.unitPath,
|
|
70
|
+
actor,
|
|
71
|
+
});
|
|
72
|
+
// License-gated path — `logAuditEvent` is a no-op when `audit-log` is
|
|
73
|
+
// unlicensed. Service-install events are an Enterprise-tier operational
|
|
74
|
+
// signal; OSS / Pro deployments simply drop them.
|
|
75
|
+
await logAuditEvent(db, evt);
|
|
76
|
+
}
|
|
77
|
+
catch {
|
|
78
|
+
// Audit must never crash the install — swallow.
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
export const serviceCommand = new Command("service").description("Manage the urateam launchd/systemd service unit");
|
|
82
|
+
serviceCommand
|
|
83
|
+
.command("install")
|
|
84
|
+
.description("Install the platform service unit (launchd on macOS, systemd-user on Linux)")
|
|
85
|
+
.option("--dry-run", "Print the unit content; do not write or load it")
|
|
86
|
+
.action(async (opts) => {
|
|
87
|
+
const platform = detectPlatform();
|
|
88
|
+
const input = buildInput();
|
|
89
|
+
const dest = unitPath(platform);
|
|
90
|
+
const content = platform === "darwin"
|
|
91
|
+
? renderLaunchdPlist(input)
|
|
92
|
+
: renderSystemdUserUnit(input);
|
|
93
|
+
if (opts.dryRun) {
|
|
94
|
+
console.log(`# Would write: ${dest}`);
|
|
95
|
+
console.log(content);
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
if (existsSync(dest)) {
|
|
99
|
+
console.log(`ura service install: ${dest} already exists. ` +
|
|
100
|
+
`Run 'ura service uninstall' first if you want to reinstall.`);
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
mkdirSync(dirname(dest), { recursive: true });
|
|
104
|
+
writeFileSync(dest, content);
|
|
105
|
+
if (platform === "darwin") {
|
|
106
|
+
await execFileP("launchctl", ["load", "-w", dest]);
|
|
107
|
+
await execFileP("launchctl", ["start", SERVICE_LABEL]);
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
await execFileP("systemctl", ["--user", "daemon-reload"]);
|
|
111
|
+
await execFileP("systemctl", [
|
|
112
|
+
"--user",
|
|
113
|
+
"enable",
|
|
114
|
+
"--now",
|
|
115
|
+
SYSTEMD_UNIT_BASENAME,
|
|
116
|
+
]);
|
|
117
|
+
}
|
|
118
|
+
console.log(`ura service install: wrote ${dest} and started the service.`);
|
|
119
|
+
await tryEmitAuditEvent({
|
|
120
|
+
eventType: "installed",
|
|
121
|
+
platform,
|
|
122
|
+
unitPath: dest,
|
|
123
|
+
});
|
|
124
|
+
});
|
|
125
|
+
serviceCommand
|
|
126
|
+
.command("uninstall")
|
|
127
|
+
.description("Remove the platform service unit and stop the service")
|
|
128
|
+
.action(async () => {
|
|
129
|
+
const platform = detectPlatform();
|
|
130
|
+
const dest = unitPath(platform);
|
|
131
|
+
if (!existsSync(dest)) {
|
|
132
|
+
console.log(`ura service uninstall: ${dest} not installed — nothing to remove.`);
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
if (platform === "darwin") {
|
|
136
|
+
try {
|
|
137
|
+
await execFileP("launchctl", ["unload", "-w", dest]);
|
|
138
|
+
}
|
|
139
|
+
catch {
|
|
140
|
+
// unit may have been unloaded already — best-effort stop
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
else {
|
|
144
|
+
try {
|
|
145
|
+
await execFileP("systemctl", [
|
|
146
|
+
"--user",
|
|
147
|
+
"disable",
|
|
148
|
+
"--now",
|
|
149
|
+
SYSTEMD_UNIT_BASENAME,
|
|
150
|
+
]);
|
|
151
|
+
}
|
|
152
|
+
catch {
|
|
153
|
+
// unit may have been disabled already — best-effort stop
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
rmSync(dest, { force: true });
|
|
157
|
+
console.log(`ura service uninstall: removed ${dest}.`);
|
|
158
|
+
await tryEmitAuditEvent({
|
|
159
|
+
eventType: "uninstalled",
|
|
160
|
+
platform,
|
|
161
|
+
unitPath: dest,
|
|
162
|
+
});
|
|
163
|
+
});
|
|
164
|
+
//# sourceMappingURL=service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service.js","sourceRoot":"","sources":["../../src/commands/service.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -28,6 +28,7 @@ import { stopCommand, haltCommand } from "./commands/control.js";
|
|
|
28
28
|
import { initCommand } from "./commands/init.js";
|
|
29
29
|
import { repoCommand } from "./commands/repo.js";
|
|
30
30
|
import { uninstallCommand } from "./commands/uninstall.js";
|
|
31
|
+
import { serviceCommand } from "./commands/service.js";
|
|
31
32
|
const program = new Command();
|
|
32
33
|
program
|
|
33
34
|
.name("ura")
|
|
@@ -46,5 +47,6 @@ program.addCommand(haltCommand);
|
|
|
46
47
|
program.addCommand(initCommand);
|
|
47
48
|
program.addCommand(repoCommand);
|
|
48
49
|
program.addCommand(uninstallCommand);
|
|
50
|
+
program.addCommand(serviceCommand);
|
|
49
51
|
program.parse();
|
|
50
52
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,oCAAoC;AACpC,4EAA4E;AAC5E,2EAA2E;AAC3E,mEAAmE;AACnE,6EAA6E;AAC7E,oEAAoE;AACpE,IAAI,CAAC;IACH,OAAO,CAAC,WAAW,EAAE,CAAC;AACxB,CAAC;AAAC,OAAO,GAAY,EAAE,CAAC;IACtB,MAAM,IAAI,GAAI,GAA6B,EAAE,IAAI,CAAC;IAClD,IAAI,IAAI,KAAK,QAAQ,EAAE,CAAC;QACtB,OAAO,CAAC,IAAI,CACV,qCAAqC,OAAO,CAAC,GAAG,EAAE,KAChD,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CACjD,EAAE,CACH,CAAC;IACJ,CAAC;AACH,CAAC;AAED,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACjE,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,oCAAoC;AACpC,4EAA4E;AAC5E,2EAA2E;AAC3E,mEAAmE;AACnE,6EAA6E;AAC7E,oEAAoE;AACpE,IAAI,CAAC;IACH,OAAO,CAAC,WAAW,EAAE,CAAC;AACxB,CAAC;AAAC,OAAO,GAAY,EAAE,CAAC;IACtB,MAAM,IAAI,GAAI,GAA6B,EAAE,IAAI,CAAC;IAClD,IAAI,IAAI,KAAK,QAAQ,EAAE,CAAC;QACtB,OAAO,CAAC,IAAI,CACV,qCAAqC,OAAO,CAAC,GAAG,EAAE,KAChD,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CACjD,EAAE,CACH,CAAC;IACJ,CAAC;AACH,CAAC;AAED,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACjE,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAEvD,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,KAAK,CAAC;KACX,WAAW,CAAC,aAAa,CAAC;KAC1B,OAAO,CAAC,iBAAiB,EAAE,CAAC,CAAC;AAEhC,OAAO,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;AAC/B,OAAO,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;AAC/B,OAAO,CAAC,UAAU,CAAC,cAAc,CAAC,CAAC;AACnC,OAAO,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;AAClC,OAAO,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC;AACjC,OAAO,CAAC,UAAU,CAAC,cAAc,CAAC,CAAC;AACnC,OAAO,CAAC,UAAU,CAAC,cAAc,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;AACrD,OAAO,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC;AACjC,OAAO,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;AAChC,OAAO,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;AAChC,OAAO,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;AAChC,OAAO,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;AAChC,OAAO,CAAC,UAAU,CAAC,gBAAgB,CAAC,CAAC;AACrC,OAAO,CAAC,UAAU,CAAC,cAAc,CAAC,CAAC;AAEnC,OAAO,CAAC,KAAK,EAAE,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure unit-file generators for `ura service install`.
|
|
3
|
+
*
|
|
4
|
+
* Both generators are I/O-free string functions so they can be unit-tested
|
|
5
|
+
* without touching the filesystem and so `--dry-run` can print the would-be
|
|
6
|
+
* unit content without mutating anything. The shape mirrors what
|
|
7
|
+
* `deploy/USER_LEVEL_INSTALL.md` previously documented as copy-paste blocks.
|
|
8
|
+
*/
|
|
9
|
+
export interface ServiceUnitInput {
|
|
10
|
+
/** Absolute path to the `ura` binary (e.g. `/usr/local/bin/ura`). */
|
|
11
|
+
binaryPath: string;
|
|
12
|
+
/** Resolved `$URATEAM_HOME` — propagated into the service environment. */
|
|
13
|
+
urateamHome: string;
|
|
14
|
+
/** Path to the `.env` file the daemon should read at startup. */
|
|
15
|
+
envFilePath: string;
|
|
16
|
+
/** Stdout log path (launchd `StandardOutPath` / systemd `StandardOutput`). */
|
|
17
|
+
stdoutPath: string;
|
|
18
|
+
/** Stderr log path (launchd `StandardErrorPath` / systemd `StandardError`). */
|
|
19
|
+
stderrPath: string;
|
|
20
|
+
}
|
|
21
|
+
export declare function renderLaunchdPlist(opts: ServiceUnitInput): string;
|
|
22
|
+
export declare function renderSystemdUserUnit(opts: ServiceUnitInput): string;
|
|
23
|
+
export declare const SERVICE_LABEL = "com.urateam.daemon";
|
|
24
|
+
export declare const SYSTEMD_UNIT_BASENAME = "urateam.service";
|
|
25
|
+
//# sourceMappingURL=service-unit.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service-unit.d.ts","sourceRoot":"","sources":["../../src/lib/service-unit.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,MAAM,WAAW,gBAAgB;IAC/B,qEAAqE;IACrE,UAAU,EAAE,MAAM,CAAC;IACnB,0EAA0E;IAC1E,WAAW,EAAE,MAAM,CAAC;IACpB,iEAAiE;IACjE,WAAW,EAAE,MAAM,CAAC;IACpB,8EAA8E;IAC9E,UAAU,EAAE,MAAM,CAAC;IACnB,+EAA+E;IAC/E,UAAU,EAAE,MAAM,CAAC;CACpB;AAID,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,gBAAgB,GAAG,MAAM,CAgCjE;AAED,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,gBAAgB,GAAG,MAAM,CAqBpE;AAED,eAAO,MAAM,aAAa,uBAAgB,CAAC;AAC3C,eAAO,MAAM,qBAAqB,oBAAoB,CAAC"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure unit-file generators for `ura service install`.
|
|
3
|
+
*
|
|
4
|
+
* Both generators are I/O-free string functions so they can be unit-tested
|
|
5
|
+
* without touching the filesystem and so `--dry-run` can print the would-be
|
|
6
|
+
* unit content without mutating anything. The shape mirrors what
|
|
7
|
+
* `deploy/USER_LEVEL_INSTALL.md` previously documented as copy-paste blocks.
|
|
8
|
+
*/
|
|
9
|
+
const LAUNCHD_LABEL = "com.urateam.daemon";
|
|
10
|
+
export function renderLaunchdPlist(opts) {
|
|
11
|
+
return [
|
|
12
|
+
`<?xml version="1.0" encoding="UTF-8"?>`,
|
|
13
|
+
`<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">`,
|
|
14
|
+
`<plist version="1.0">`,
|
|
15
|
+
`<dict>`,
|
|
16
|
+
` <key>Label</key>`,
|
|
17
|
+
` <string>${LAUNCHD_LABEL}</string>`,
|
|
18
|
+
` <key>ProgramArguments</key>`,
|
|
19
|
+
` <array>`,
|
|
20
|
+
` <string>${opts.binaryPath}</string>`,
|
|
21
|
+
` <string>start</string>`,
|
|
22
|
+
` </array>`,
|
|
23
|
+
` <key>WorkingDirectory</key>`,
|
|
24
|
+
` <string>${opts.urateamHome}</string>`,
|
|
25
|
+
` <key>EnvironmentVariables</key>`,
|
|
26
|
+
` <dict>`,
|
|
27
|
+
` <key>URATEAM_HOME</key>`,
|
|
28
|
+
` <string>${opts.urateamHome}</string>`,
|
|
29
|
+
` </dict>`,
|
|
30
|
+
` <key>RunAtLoad</key>`,
|
|
31
|
+
` <true/>`,
|
|
32
|
+
` <key>KeepAlive</key>`,
|
|
33
|
+
` <true/>`,
|
|
34
|
+
` <key>StandardOutPath</key>`,
|
|
35
|
+
` <string>${opts.stdoutPath}</string>`,
|
|
36
|
+
` <key>StandardErrorPath</key>`,
|
|
37
|
+
` <string>${opts.stderrPath}</string>`,
|
|
38
|
+
`</dict>`,
|
|
39
|
+
`</plist>`,
|
|
40
|
+
``,
|
|
41
|
+
].join("\n");
|
|
42
|
+
}
|
|
43
|
+
export function renderSystemdUserUnit(opts) {
|
|
44
|
+
return [
|
|
45
|
+
`[Unit]`,
|
|
46
|
+
`Description=urateam user-level daemon`,
|
|
47
|
+
`After=network.target`,
|
|
48
|
+
``,
|
|
49
|
+
`[Service]`,
|
|
50
|
+
`Type=simple`,
|
|
51
|
+
`WorkingDirectory=${opts.urateamHome}`,
|
|
52
|
+
`EnvironmentFile=${opts.envFilePath}`,
|
|
53
|
+
`Environment=URATEAM_HOME=${opts.urateamHome}`,
|
|
54
|
+
`ExecStart=${opts.binaryPath} start`,
|
|
55
|
+
`StandardOutput=append:${opts.stdoutPath}`,
|
|
56
|
+
`StandardError=append:${opts.stderrPath}`,
|
|
57
|
+
`Restart=always`,
|
|
58
|
+
`RestartSec=5`,
|
|
59
|
+
``,
|
|
60
|
+
`[Install]`,
|
|
61
|
+
`WantedBy=default.target`,
|
|
62
|
+
``,
|
|
63
|
+
].join("\n");
|
|
64
|
+
}
|
|
65
|
+
export const SERVICE_LABEL = LAUNCHD_LABEL;
|
|
66
|
+
export const SYSTEMD_UNIT_BASENAME = "urateam.service";
|
|
67
|
+
//# sourceMappingURL=service-unit.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service-unit.js","sourceRoot":"","sources":["../../src/lib/service-unit.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAeH,MAAM,aAAa,GAAG,oBAAoB,CAAC;AAE3C,MAAM,UAAU,kBAAkB,CAAC,IAAsB;IACvD,OAAO;QACL,wCAAwC;QACxC,wGAAwG;QACxG,uBAAuB;QACvB,QAAQ;QACR,oBAAoB;QACpB,aAAa,aAAa,WAAW;QACrC,+BAA+B;QAC/B,WAAW;QACX,eAAe,IAAI,CAAC,UAAU,WAAW;QACzC,4BAA4B;QAC5B,YAAY;QACZ,+BAA+B;QAC/B,aAAa,IAAI,CAAC,WAAW,WAAW;QACxC,mCAAmC;QACnC,UAAU;QACV,6BAA6B;QAC7B,eAAe,IAAI,CAAC,WAAW,WAAW;QAC1C,WAAW;QACX,wBAAwB;QACxB,WAAW;QACX,wBAAwB;QACxB,WAAW;QACX,8BAA8B;QAC9B,aAAa,IAAI,CAAC,UAAU,WAAW;QACvC,gCAAgC;QAChC,aAAa,IAAI,CAAC,UAAU,WAAW;QACvC,SAAS;QACT,UAAU;QACV,EAAE;KACH,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,IAAsB;IAC1D,OAAO;QACL,QAAQ;QACR,uCAAuC;QACvC,sBAAsB;QACtB,EAAE;QACF,WAAW;QACX,aAAa;QACb,oBAAoB,IAAI,CAAC,WAAW,EAAE;QACtC,mBAAmB,IAAI,CAAC,WAAW,EAAE;QACrC,4BAA4B,IAAI,CAAC,WAAW,EAAE;QAC9C,aAAa,IAAI,CAAC,UAAU,QAAQ;QACpC,yBAAyB,IAAI,CAAC,UAAU,EAAE;QAC1C,wBAAwB,IAAI,CAAC,UAAU,EAAE;QACzC,gBAAgB;QAChB,cAAc;QACd,EAAE;QACF,WAAW;QACX,yBAAyB;QACzB,EAAE;KACH,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC;AAED,MAAM,CAAC,MAAM,aAAa,GAAG,aAAa,CAAC;AAC3C,MAAM,CAAC,MAAM,qBAAqB,GAAG,iBAAiB,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@urateam/cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.41",
|
|
4
4
|
"license": "BUSL-1.1",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -23,8 +23,8 @@
|
|
|
23
23
|
"commander": "^13.1.0",
|
|
24
24
|
"postgres": "^3.4.0",
|
|
25
25
|
"zod": "^4.3.6",
|
|
26
|
-
"@urateam/core": "0.1.
|
|
27
|
-
"@urateam/dashboard": "0.1.
|
|
26
|
+
"@urateam/core": "0.1.39",
|
|
27
|
+
"@urateam/dashboard": "0.1.39"
|
|
28
28
|
},
|
|
29
29
|
"devDependencies": {
|
|
30
30
|
"@types/better-sqlite3": "^7.6.0",
|