@dbx-tools/cli-service 0.9.36
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/LICENSE +202 -0
- package/README.md +68 -0
- package/index.ts +14 -0
- package/lib/index.d.ts +10 -0
- package/lib/index.js +11 -0
- package/lib/src/_config.d.ts +3 -0
- package/lib/src/_config.js +17 -0
- package/lib/src/_control.d.ts +10 -0
- package/lib/src/_control.js +107 -0
- package/lib/src/_host.d.ts +1 -0
- package/lib/src/_host.js +221 -0
- package/lib/src/_package.d.ts +12 -0
- package/lib/src/_package.js +140 -0
- package/lib/src/_paths.d.ts +17 -0
- package/lib/src/_paths.js +55 -0
- package/lib/src/_runtime.d.ts +2 -0
- package/lib/src/_runtime.js +49 -0
- package/lib/src/_startup.d.ts +11 -0
- package/lib/src/_startup.js +81 -0
- package/lib/src/cli.d.ts +19 -0
- package/lib/src/cli.js +61 -0
- package/lib/src/definition.d.ts +82 -0
- package/lib/src/definition.js +91 -0
- package/lib/src/service.d.ts +101 -0
- package/lib/src/service.js +296 -0
- package/lib/tsconfig.tsbuildinfo +1 -0
- package/package.json +92 -0
- package/src/_config.ts +22 -0
- package/src/_control.ts +127 -0
- package/src/_host.ts +249 -0
- package/src/_package.ts +152 -0
- package/src/_paths.ts +104 -0
- package/src/_runtime.ts +66 -0
- package/src/_startup.ts +106 -0
- package/src/cli.ts +89 -0
- package/src/definition.ts +119 -0
- package/src/service.ts +472 -0
package/lib/src/_host.js
ADDED
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
import { closeSync, openSync } from "node:fs";
|
|
3
|
+
import { appendFile, mkdir } from "node:fs/promises";
|
|
4
|
+
import { dirname, join } from "node:path";
|
|
5
|
+
import * as systrayModule from "systray2";
|
|
6
|
+
import { readServiceDefinition } from "./_config.js";
|
|
7
|
+
import { closeServiceControl, listenForServiceControl, } from "./_control.js";
|
|
8
|
+
import { defaultRuntimeContext, resolveServicePaths } from "./_paths.js";
|
|
9
|
+
const CHILD_STOP_TIMEOUT_MILLISECONDS = 5_000;
|
|
10
|
+
const SysTray = systrayConstructor();
|
|
11
|
+
function systrayConstructor() {
|
|
12
|
+
const loaded = systrayModule.default;
|
|
13
|
+
if (typeof loaded === "function")
|
|
14
|
+
return loaded;
|
|
15
|
+
const nested = loaded && typeof loaded === "object" ? loaded.default : undefined;
|
|
16
|
+
if (typeof nested === "function")
|
|
17
|
+
return nested;
|
|
18
|
+
throw new TypeError("systray2 did not provide a constructor");
|
|
19
|
+
}
|
|
20
|
+
class CliServiceHost {
|
|
21
|
+
definition;
|
|
22
|
+
paths;
|
|
23
|
+
requestStop;
|
|
24
|
+
tray;
|
|
25
|
+
service;
|
|
26
|
+
control;
|
|
27
|
+
stopping = false;
|
|
28
|
+
constructor(definition, paths, requestStop) {
|
|
29
|
+
this.definition = definition;
|
|
30
|
+
this.paths = paths;
|
|
31
|
+
this.requestStop = requestStop;
|
|
32
|
+
}
|
|
33
|
+
async start() {
|
|
34
|
+
await mkdir(this.paths.directory, { recursive: true });
|
|
35
|
+
this.service = this.definition.command
|
|
36
|
+
? this.startProcess(this.definition.command, true)
|
|
37
|
+
: undefined;
|
|
38
|
+
this.tray = this.createTray();
|
|
39
|
+
await this.tray.ready();
|
|
40
|
+
this.tray.onError((error) => {
|
|
41
|
+
void logError(this.paths.hostLog, error);
|
|
42
|
+
this.requestStop();
|
|
43
|
+
});
|
|
44
|
+
this.tray.onExit((code, signal) => {
|
|
45
|
+
if (this.stopping)
|
|
46
|
+
return;
|
|
47
|
+
void logMessage(this.paths.hostLog, `system tray exited (${signal ?? String(code)})`);
|
|
48
|
+
this.requestStop();
|
|
49
|
+
});
|
|
50
|
+
await this.tray.onClick((action) => {
|
|
51
|
+
const item = action.item;
|
|
52
|
+
item.click?.();
|
|
53
|
+
});
|
|
54
|
+
this.control = await listenForServiceControl(this.paths.controlAddress, () => this.status(), this.requestStop);
|
|
55
|
+
}
|
|
56
|
+
async stop() {
|
|
57
|
+
if (this.stopping)
|
|
58
|
+
return;
|
|
59
|
+
this.stopping = true;
|
|
60
|
+
if (this.control) {
|
|
61
|
+
await closeServiceControl(this.control, this.paths.controlAddress);
|
|
62
|
+
this.control = undefined;
|
|
63
|
+
}
|
|
64
|
+
if (this.tray) {
|
|
65
|
+
if (this.tray.process.exitCode === null && this.tray.process.signalCode === null) {
|
|
66
|
+
await this.tray.kill(false);
|
|
67
|
+
}
|
|
68
|
+
this.tray = undefined;
|
|
69
|
+
}
|
|
70
|
+
if (this.service) {
|
|
71
|
+
await stopProcess(this.service);
|
|
72
|
+
this.service = undefined;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
status() {
|
|
76
|
+
return {
|
|
77
|
+
running: true,
|
|
78
|
+
pid: process.pid,
|
|
79
|
+
...(this.service?.pid ? { servicePid: this.service.pid } : {}),
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
startProcess(command, managed) {
|
|
83
|
+
if (!command.executable) {
|
|
84
|
+
throw new Error("installed service commands require an executable");
|
|
85
|
+
}
|
|
86
|
+
const logDescriptor = openSync(this.paths.processLog, "a");
|
|
87
|
+
const child = spawn(command.executable, command.arguments ?? [], {
|
|
88
|
+
cwd: command.cwd,
|
|
89
|
+
env: { ...process.env, ...command.environment },
|
|
90
|
+
stdio: ["ignore", logDescriptor, logDescriptor],
|
|
91
|
+
});
|
|
92
|
+
closeSync(logDescriptor);
|
|
93
|
+
child.once("error", (error) => {
|
|
94
|
+
void logError(this.paths.hostLog, error);
|
|
95
|
+
if (managed)
|
|
96
|
+
this.requestStop();
|
|
97
|
+
});
|
|
98
|
+
child.once("exit", (code, signal) => {
|
|
99
|
+
if (!this.stopping && managed) {
|
|
100
|
+
void logMessage(this.paths.hostLog, `managed service exited (${signal ?? String(code)})`);
|
|
101
|
+
this.requestStop();
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
return child;
|
|
105
|
+
}
|
|
106
|
+
createTray() {
|
|
107
|
+
return new SysTray({
|
|
108
|
+
menu: {
|
|
109
|
+
icon: this.definition.icon,
|
|
110
|
+
title: "",
|
|
111
|
+
tooltip: `${this.definition.name} ${this.definition.version}`,
|
|
112
|
+
items: this.menuItems(),
|
|
113
|
+
isTemplateIcon: this.definition.isTemplateIcon,
|
|
114
|
+
},
|
|
115
|
+
debug: false,
|
|
116
|
+
copyDir: false,
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
menuItems() {
|
|
120
|
+
const custom = (this.definition.menu ?? []).map((item) => this.menuItem(item));
|
|
121
|
+
return [
|
|
122
|
+
{
|
|
123
|
+
title: `${this.definition.name} - ${this.definition.version}`,
|
|
124
|
+
tooltip: "",
|
|
125
|
+
enabled: false,
|
|
126
|
+
},
|
|
127
|
+
...custom,
|
|
128
|
+
{ ...SysTray.separator },
|
|
129
|
+
{
|
|
130
|
+
title: "Quit",
|
|
131
|
+
tooltip: `Stop ${this.definition.name}`,
|
|
132
|
+
click: this.requestStop,
|
|
133
|
+
},
|
|
134
|
+
];
|
|
135
|
+
}
|
|
136
|
+
menuItem(item) {
|
|
137
|
+
if (item.type === "separator")
|
|
138
|
+
return { ...SysTray.separator };
|
|
139
|
+
if (item.type === "url") {
|
|
140
|
+
return {
|
|
141
|
+
title: item.label,
|
|
142
|
+
tooltip: item.url,
|
|
143
|
+
click: () => {
|
|
144
|
+
this.openUrl(item.url);
|
|
145
|
+
},
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
return {
|
|
149
|
+
title: item.label,
|
|
150
|
+
tooltip: "",
|
|
151
|
+
click: () => {
|
|
152
|
+
const child = this.startProcess(item.command, false);
|
|
153
|
+
child.unref();
|
|
154
|
+
},
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
openUrl(url) {
|
|
158
|
+
const command = process.platform === "darwin"
|
|
159
|
+
? { executable: "open", arguments: [url] }
|
|
160
|
+
: process.platform === "win32"
|
|
161
|
+
? {
|
|
162
|
+
executable: "rundll32.exe",
|
|
163
|
+
arguments: ["url.dll,FileProtocolHandler", url],
|
|
164
|
+
}
|
|
165
|
+
: { executable: "xdg-open", arguments: [url] };
|
|
166
|
+
const child = this.startProcess(command, false);
|
|
167
|
+
child.unref();
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
async function runCliServiceHost(configFile) {
|
|
171
|
+
process.chdir(dirname(process.execPath));
|
|
172
|
+
const definition = await readServiceDefinition(configFile);
|
|
173
|
+
const runtime = defaultRuntimeContext();
|
|
174
|
+
const paths = resolveServicePaths(definition, runtime);
|
|
175
|
+
let requestStop = () => { };
|
|
176
|
+
const stopped = new Promise((resolve) => {
|
|
177
|
+
requestStop = resolve;
|
|
178
|
+
});
|
|
179
|
+
const host = new CliServiceHost(definition, paths, requestStop);
|
|
180
|
+
process.once("SIGINT", requestStop);
|
|
181
|
+
process.once("SIGTERM", requestStop);
|
|
182
|
+
try {
|
|
183
|
+
await host.start();
|
|
184
|
+
await stopped;
|
|
185
|
+
}
|
|
186
|
+
finally {
|
|
187
|
+
await host.stop();
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
async function stopProcess(child) {
|
|
191
|
+
if (child.exitCode !== null || child.signalCode !== null)
|
|
192
|
+
return;
|
|
193
|
+
const exited = new Promise((resolve) => child.once("exit", () => resolve()));
|
|
194
|
+
child.kill("SIGTERM");
|
|
195
|
+
const timedOut = new Promise((resolve) => {
|
|
196
|
+
setTimeout(() => resolve("timeout"), CHILD_STOP_TIMEOUT_MILLISECONDS);
|
|
197
|
+
});
|
|
198
|
+
if ((await Promise.race([exited, timedOut])) === "timeout") {
|
|
199
|
+
child.kill("SIGKILL");
|
|
200
|
+
await exited;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
async function logError(path, error) {
|
|
204
|
+
await logMessage(path, error instanceof Error ? (error.stack ?? error.message) : String(error));
|
|
205
|
+
}
|
|
206
|
+
async function logMessage(path, message) {
|
|
207
|
+
await mkdir(dirname(path), { recursive: true });
|
|
208
|
+
await appendFile(path, `${new Date().toISOString()} ${message}\n`, "utf8");
|
|
209
|
+
}
|
|
210
|
+
function argumentValue(name) {
|
|
211
|
+
const index = process.argv.indexOf(name);
|
|
212
|
+
return index >= 0 ? process.argv[index + 1] : undefined;
|
|
213
|
+
}
|
|
214
|
+
const configFile = argumentValue("--service-config");
|
|
215
|
+
if (configFile) {
|
|
216
|
+
void runCliServiceHost(configFile).catch(async (error) => {
|
|
217
|
+
await logError(join(dirname(configFile), "host.log"), error);
|
|
218
|
+
process.exitCode = 1;
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiX2hvc3QuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvX2hvc3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLEtBQUssRUFBcUIsTUFBTSxvQkFBb0IsQ0FBQztBQUM5RCxPQUFPLEVBQUUsU0FBUyxFQUFFLFFBQVEsRUFBRSxNQUFNLFNBQVMsQ0FBQztBQUM5QyxPQUFPLEVBQUUsVUFBVSxFQUFFLEtBQUssRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBQ3JELE9BQU8sRUFBRSxPQUFPLEVBQUUsSUFBSSxFQUFFLE1BQU0sV0FBVyxDQUFDO0FBRTFDLE9BQU8sS0FBSyxhQUFhLE1BQU0sVUFBVSxDQUFDO0FBSTFDLE9BQU8sRUFBRSxxQkFBcUIsRUFBRSxNQUFNLGNBQWMsQ0FBQztBQUNyRCxPQUFPLEVBQ0wsbUJBQW1CLEVBQ25CLHVCQUF1QixHQUV4QixNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQUUscUJBQXFCLEVBQUUsbUJBQW1CLEVBQXFCLE1BQU0sYUFBYSxDQUFDO0FBRzVGLE1BQU0sK0JBQStCLEdBQUcsS0FBSyxDQUFDO0FBQzlDLE1BQU0sT0FBTyxHQUFHLGtCQUFrQixFQUFFLENBQUM7QUFNckMsU0FBUyxrQkFBa0I7SUFDekIsTUFBTSxNQUFNLEdBQVksYUFBYSxDQUFDLE9BQU8sQ0FBQztJQUM5QyxJQUFJLE9BQU8sTUFBTSxLQUFLLFVBQVU7UUFBRSxPQUFPLE1BQTRCLENBQUM7SUFDdEUsTUFBTSxNQUFNLEdBQ1YsTUFBTSxJQUFJLE9BQU8sTUFBTSxLQUFLLFFBQVEsQ0FBQyxDQUFDLENBQUUsTUFBZ0MsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQztJQUMvRixJQUFJLE9BQU8sTUFBTSxLQUFLLFVBQVU7UUFBRSxPQUFPLE1BQTRCLENBQUM7SUFDdEUsTUFBTSxJQUFJLFNBQVMsQ0FBQyx3Q0FBd0MsQ0FBQyxDQUFDO0FBQ2hFLENBQUM7QUFFRCxNQUFNLGNB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QUFNLFFBQVEsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLFVBQVUsQ0FBQyxFQUFFLFVBQVUsQ0FBQyxFQUFFLEtBQUssQ0FBQyxDQUFDO1FBQzdELE9BQU8sQ0FBQyxRQUFRLEdBQUcsQ0FBQyxDQUFDO0lBQ3ZCLENBQUMsQ0FBQyxDQUFDO0FBQ0wsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IHNwYXduLCB0eXBlIENoaWxkUHJvY2VzcyB9IGZyb20gXCJub2RlOmNoaWxkX3Byb2Nlc3NcIjtcbmltcG9ydCB7IGNsb3NlU3luYywgb3BlblN5bmMgfSBmcm9tIFwibm9kZTpmc1wiO1xuaW1wb3J0IHsgYXBwZW5kRmlsZSwgbWtkaXIgfSBmcm9tIFwibm9kZTpmcy9wcm9taXNlc1wiO1xuaW1wb3J0IHsgZGlybmFtZSwgam9pbiB9IGZyb20gXCJub2RlOnBhdGhcIjtcblxuaW1wb3J0ICogYXMgc3lzdHJheU1vZHVsZSBmcm9tIFwic3lzdHJheTJcIjtcbmltcG9ydCB0eXBlIFN5c1RyYXlUeXBlIGZyb20gXCJzeXN0cmF5MlwiO1xuaW1wb3J0IHR5cGUgeyBNZW51SXRlbSB9IGZyb20gXCJzeXN0cmF5MlwiO1xuXG5pbXBvcnQgeyByZWFkU2VydmljZURlZmluaXRpb24gfSBmcm9tIFwiLi9fY29uZmlnLnRzXCI7XG5pbXBvcnQge1xuICBjbG9zZVNlcnZpY2VDb250cm9sLFxuICBsaXN0ZW5Gb3JTZXJ2aWNlQ29udHJvbCxcbiAgdHlwZSBTZXJ2aWNlQ29udHJvbFJlc3BvbnNlLFxufSBmcm9tIFwiLi9fY29udHJvbC50c1wiO1xuaW1wb3J0IHsgZGVmYXVsdFJ1bnRpbWVDb250ZXh0LCByZXNvbHZlU2VydmljZVBhdGhzLCB0eXBlIFNlcnZpY2VQYXRocyB9IGZyb20gXCIuL19wYXRocy50c1wiO1xuaW1wb3J0IHR5cGUgeyBDbGlTZXJ2aWNlQ29tbWFuZCwgQ2xpU2VydmljZURlZmluaXRpb24sIENsaVNlcnZpY2VNZW51SXRlbSB9IGZyb20gXCIuL2RlZmluaXRpb24udHNcIjtcblxuY29uc3QgQ0hJTERfU1RPUF9USU1FT1VUX01JTExJU0VDT05EUyA9IDVfMDAwO1xuY29uc3QgU3lzVHJheSA9IHN5c3RyYXlDb25zdHJ1Y3RvcigpO1xuXG5pbnRlcmZhY2UgQWN0aW9uTWVudUl0ZW0gZXh0ZW5kcyBNZW51SXRlbSB7XG4gIHJlYWRvbmx5IGNsaWNrPzogKCkgPT4gdm9pZDtcbn1cblxuZnVuY3Rpb24gc3lzdHJheUNvbnN0cnVjdG9yKCk6IHR5cGVvZiBTeXNUcmF5VHlwZSB7XG4gIGNvbnN0IGxvYWRlZDogdW5rbm93biA9IHN5c3RyYXlNb2R1bGUuZGVmYXVsdDtcbiAgaWYgKHR5cGVvZiBsb2FkZWQgPT09IFwiZnVuY3Rpb25cIikgcmV0dXJuIGxvYWRlZCBhcyB0eXBlb2YgU3lzVHJheVR5cGU7XG4gIGNvbnN0IG5lc3RlZCA9XG4gICAgbG9hZGVkICYmIHR5cGVvZiBsb2FkZWQgPT09IFwib2JqZWN0XCIgPyAobG9hZGVkIGFzIHsgZGVmYXVsdD86IHVua25vd24gfSkuZGVmYXVsdCA6IHVuZGVmaW5lZDtcbiAgaWYgKHR5cGVvZiBuZXN0ZWQgPT09IFwiZnVuY3Rpb25cIikgcmV0dXJuIG5lc3RlZCBhcyB0eXBlb2YgU3lzVHJheVR5cGU7XG4gIHRocm93IG5ldyBUeXBlRXJyb3IoXCJzeXN0cmF5MiBkaWQgbm90IHByb3ZpZGUgYSBjb25zdHJ1Y3RvclwiKTtcbn1cblxuY2xhc3MgQ2xpU2VydmljZUhvc3Qge1xuICBwcml2YXRlIHJlYWRvbmx5IGRlZmluaXRpb246IENsaVNlcnZpY2VEZWZpbml0aW9uO1xuICBwcml2YXRlIHJlYWRvbmx5IHBhdGhzOiBTZXJ2aWNlUGF0aHM7XG4gIHByaXZhdGUgcmVhZG9ubHkgcmVxdWVzdFN0b3A6ICgpID0+IHZvaWQ7XG4gIHByaXZhdGUgdHJheT86IFN5c1RyYXlUeXBlO1xuICBwcml2YXRlIHNlcnZpY2U/OiBDaGlsZFByb2Nlc3M7XG4gIHByaXZhdGUgY29udHJvbD86IEF3YWl0ZWQ8UmV0dXJuVHlwZTx0eXBlb2YgbGlzdGVuRm9yU2VydmljZUNvbnRyb2w+PjtcbiAgcHJpdmF0ZSBzdG9wcGluZyA9IGZhbHNlO1xuXG4gIGNvbnN0cnVjdG9yKGRlZmluaXRpb246IENsaVNlcnZpY2VEZWZpbml0aW9uLCBwYXRoczogU2VydmljZVBhdGhzLCByZXF1ZXN0U3RvcDogKCkgPT4gdm9pZCkge1xuICAgIHRoaXMuZGVmaW5pdGlvbiA9IGRlZmluaXRpb247XG4gICAgdGhpcy5wYXRocyA9IHBhdGhzO1xuICAgIHRoaXMucmVxdWVzdFN0b3AgPSByZXF1ZXN0U3RvcDtcbiAgfVxuXG4gIGFzeW5jIHN0YXJ0KCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGF3YWl0IG1rZGlyKHRoaXMucGF0aHMuZGlyZWN0b3J5LCB7IHJlY3Vyc2l2ZTogdHJ1ZSB9KTtcbiAgICB0aGlzLnNlcnZpY2UgPSB0aGlzLmRlZmluaXRpb24uY29tbWFuZFxuICAgICAgPyB0aGlzLnN0YXJ0UHJvY2Vzcyh0aGlzLmRlZmluaXRpb24uY29tbWFuZCwgdHJ1ZSlcbiAgICAgIDogdW5kZWZpbmVkO1xuICAgIHRoaXMudHJheSA9IHRoaXMuY3JlYXRlVHJheSgpO1xuICAgIGF3YWl0IHRoaXMudHJheS5yZWFkeSgpO1xuICAgIHRoaXMudHJheS5vbkVycm9yKChlcnJvcikgPT4ge1xuICAgICAgdm9pZCBsb2dFcnJvcih0aGlzLnBhdGhzLmhvc3RMb2csIGVycm9yKTtcbiAgICAgIHRoaXMucmVxdWVzdFN0b3AoKTtcbiAgICB9KTtcbiAgICB0aGlzLnRyYXkub25FeGl0KChjb2RlLCBzaWduYWwpID0+IHtcbiAgICAgIGlmICh0aGlzLnN0b3BwaW5nKSByZXR1cm47XG4gICAgICB2b2lkIGxvZ01lc3NhZ2UodGhpcy5wYXRocy5ob3N0TG9nLCBgc3lzdGVtIHRyYXkgZXhpdGVkICgke3NpZ25hbCA/PyBTdHJpbmcoY29kZSl9KWApO1xuICAgICAgdGhpcy5yZXF1ZXN0U3RvcCgpO1xuICAgIH0pO1xuICAgIGF3YWl0IHRoaXMudHJheS5vbkNsaWNrKChhY3Rpb24pID0+IHtcbiAgICAgIGNvbnN0IGl0ZW0gPSBhY3Rpb24uaXRlbSBhcyBBY3Rpb25NZW51SXRlbTtcbiAgICAgIGl0ZW0uY2xpY2s/LigpO1xuICAgIH0pO1xuICAgIHRoaXMuY29udHJvbCA9IGF3YWl0IGxpc3RlbkZvclNlcnZpY2VDb250cm9sKFxuICAgICAgdGhpcy5wYXRocy5jb250cm9sQWRkcmVzcyxcbiAgICAgICgpID0+IHRoaXMuc3RhdHVzKCksXG4gICAgICB0aGlzLnJlcXVlc3RTdG9wLFxuICAgICk7XG4gIH1cblxuICBhc3luYyBzdG9wKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGlmICh0aGlzLnN0b3BwaW5nKSByZXR1cm47XG4gICAgdGhpcy5zdG9wcGluZyA9IHRydWU7XG4gICAgaWYgKHRoaXMuY29udHJvbCkge1xuICAgICAgYXdhaXQgY2xvc2VTZXJ2aWNlQ29udHJvbCh0aGlzLmNvbnRyb2wsIHRoaXMucGF0aHMuY29udHJvbEFkZHJlc3MpO1xuICAgICAgdGhpcy5jb250cm9sID0gdW5kZWZpbmVkO1xuICAgIH1cbiAgICBpZiAodGhpcy50cmF5KSB7XG4gICAgICBpZiAodGhpcy50cmF5LnByb2Nlc3MuZXhpdENvZGUgPT09IG51bGwgJiYgdGhpcy50cmF5LnByb2Nlc3Muc2lnbmFsQ29kZSA9PT0gbnVsbCkge1xuICAgICAgICBhd2FpdCB0aGlzLnRyYXkua2lsbChmYWxzZSk7XG4gICAgICB9XG4gICAgICB0aGlzLnRyYXkgPSB1bmRlZmluZWQ7XG4gICAgfVxuICAgIGlmICh0aGlzLnNlcnZpY2UpIHtcbiAgICAgIGF3YWl0IHN0b3BQcm9jZXNzKHRoaXMuc2VydmljZSk7XG4gICAgICB0aGlzLnNlcnZpY2UgPSB1bmRlZmluZWQ7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBzdGF0dXMoKTogU2VydmljZUNvbnRyb2xSZXNwb25zZSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIHJ1bm5pbmc6IHRydWUsXG4gICAgICBwaWQ6IHByb2Nlc3MucGlkLFxuICAgICAgLi4uKHRoaXMuc2VydmljZT8ucGlkID8geyBzZXJ2aWNlUGlkOiB0aGlzLnNlcnZpY2UucGlkIH0gOiB7fSksXG4gICAgfTtcbiAgfVxuXG4gIHByaXZhdGUgc3RhcnRQcm9jZXNzKGNvbW1hbmQ6IENsaVNlcnZpY2VDb21tYW5kLCBtYW5hZ2VkOiBib29sZWFuKTogQ2hpbGRQcm9jZXNzIHtcbiAgICBpZiAoIWNvbW1hbmQuZXhlY3V0YWJsZSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiaW5zdGFsbGVkIHNlcnZpY2UgY29tbWFuZHMgcmVxdWlyZSBhbiBleGVjdXRhYmxlXCIpO1xuICAgIH1cbiAgICBjb25zdCBsb2dEZXNjcmlwdG9yID0gb3BlblN5bmModGhpcy5wYXRocy5wcm9jZXNzTG9nLCBcImFcIik7XG4gICAgY29uc3QgY2hpbGQgPSBzcGF3bihjb21tYW5kLmV4ZWN1dGFibGUsIGNvbW1hbmQuYXJndW1lbnRzID8/IFtdLCB7XG4gICAgICBjd2Q6IGNvbW1hbmQuY3dkLFxuICAgICAgZW52OiB7IC4uLnByb2Nlc3MuZW52LCAuLi5jb21tYW5kLmVudmlyb25tZW50IH0sXG4gICAgICBzdGRpbzogW1wiaWdub3JlXCIsIGxvZ0Rlc2NyaXB0b3IsIGxvZ0Rlc2NyaXB0b3JdLFxuICAgIH0pO1xuICAgIGNsb3NlU3luYyhsb2dEZXNjcmlwdG9yKTtcbiAgICBjaGlsZC5vbmNlKFwiZXJyb3JcIiwgKGVycm9yKSA9PiB7XG4gICAgICB2b2lkIGxvZ0Vycm9yKHRoaXMucGF0aHMuaG9zdExvZywgZXJyb3IpO1xuICAgICAgaWYgKG1hbmFnZWQpIHRoaXMucmVxdWVzdFN0b3AoKTtcbiAgICB9KTtcbiAgICBjaGlsZC5vbmNlKFwiZXhpdFwiLCAoY29kZSwgc2lnbmFsKSA9PiB7XG4gICAgICBpZiAoIXRoaXMuc3RvcHBpbmcgJiYgbWFuYWdlZCkge1xuICAgICAgICB2b2lkIGxvZ01lc3NhZ2UodGhpcy5wYXRocy5ob3N0TG9nLCBgbWFuYWdlZCBzZXJ2aWNlIGV4aXRlZCAoJHtzaWduYWwgPz8gU3RyaW5nKGNvZGUpfSlgKTtcbiAgICAgICAgdGhpcy5yZXF1ZXN0U3RvcCgpO1xuICAgICAgfVxuICAgIH0pO1xuICAgIHJldHVybiBjaGlsZDtcbiAgfVxuXG4gIHByaXZhdGUgY3JlYXRlVHJheSgpOiBTeXNUcmF5VHlwZSB7XG4gICAgcmV0dXJuIG5ldyBTeXNUcmF5KHtcbiAgICAgIG1lbnU6IHtcbiAgICAgICAgaWNvbjogdGhpcy5kZWZpbml0aW9uLmljb24sXG4gICAgICAgIHRpdGxlOiBcIlwiLFxuICAgICAgICB0b29sdGlwOiBgJHt0aGlzLmRlZmluaXRpb24ubmFtZX0gJHt0aGlzLmRlZmluaXRpb24udmVyc2lvbn1gLFxuICAgICAgICBpdGVtczogdGhpcy5tZW51SXRlbXMoKSxcbiAgICAgICAgaXNUZW1wbGF0ZUljb246IHRoaXMuZGVmaW5pdGlvbi5pc1RlbXBsYXRlSWNvbixcbiAgICAgIH0sXG4gICAgICBkZWJ1ZzogZmFsc2UsXG4gICAgICBjb3B5RGlyOiBmYWxzZSxcbiAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgbWVudUl0ZW1zKCk6IEFjdGlvbk1lbnVJdGVtW10ge1xuICAgIGNvbnN0IGN1c3RvbSA9ICh0aGlzLmRlZmluaXRpb24ubWVudSA/PyBbXSkubWFwKChpdGVtKSA9PiB0aGlzLm1lbnVJdGVtKGl0ZW0pKTtcbiAgICByZXR1cm4gW1xuICAgICAge1xuICAgICAgICB0aXRsZTogYCR7dGhpcy5kZWZpbml0aW9uLm5hbWV9IC0gJHt0aGlzLmRlZmluaXRpb24udmVyc2lvbn1gLFxuICAgICAgICB0b29sdGlwOiBcIlwiLFxuICAgICAgICBlbmFibGVkOiBmYWxzZSxcbiAgICAgIH0sXG4gICAgICAuLi5jdXN0b20sXG4gICAgICB7IC4uLlN5c1RyYXkuc2VwYXJhdG9yIH0sXG4gICAgICB7XG4gICAgICAgIHRpdGxlOiBcIlF1aXRcIixcbiAgICAgICAgdG9vbHRpcDogYFN0b3AgJHt0aGlzLmRlZmluaXRpb24ubmFtZX1gLFxuICAgICAgICBjbGljazogdGhpcy5yZXF1ZXN0U3RvcCxcbiAgICAgIH0sXG4gICAgXTtcbiAgfVxuXG4gIHByaXZhdGUgbWVudUl0ZW0oaXRlbTogQ2xpU2VydmljZU1lbnVJdGVtKTogQWN0aW9uTWVudUl0ZW0ge1xuICAgIGlmIChpdGVtLnR5cGUgPT09IFwic2VwYXJhdG9yXCIpIHJldHVybiB7IC4uLlN5c1RyYXkuc2VwYXJhdG9yIH07XG4gICAgaWYgKGl0ZW0udHlwZSA9PT0gXCJ1cmxcIikge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgdGl0bGU6IGl0ZW0ubGFiZWwsXG4gICAgICAgIHRvb2x0aXA6IGl0ZW0udXJsLFxuICAgICAgICBjbGljazogKCkgPT4ge1xuICAgICAgICAgIHRoaXMub3BlblVybChpdGVtLnVybCk7XG4gICAgICAgIH0sXG4gICAgICB9O1xuICAgIH1cbiAgICByZXR1cm4ge1xuICAgICAgdGl0bGU6IGl0ZW0ubGFiZWwsXG4gICAgICB0b29sdGlwOiBcIlwiLFxuICAgICAgY2xpY2s6ICgpID0+IHtcbiAgICAgICAgY29uc3QgY2hpbGQgPSB0aGlzLnN0YXJ0UHJvY2VzcyhpdGVtLmNvbW1hbmQsIGZhbHNlKTtcbiAgICAgICAgY2hpbGQudW5yZWYoKTtcbiAgICAgIH0sXG4gICAgfTtcbiAgfVxuXG4gIHByaXZhdGUgb3BlblVybCh1cmw6IHN0cmluZyk6IHZvaWQge1xuICAgIGNvbnN0IGNvbW1hbmQgPVxuICAgICAgcHJvY2Vzcy5wbGF0Zm9ybSA9PT0gXCJkYXJ3aW5cIlxuICAgICAgICA/IHsgZXhlY3V0YWJsZTogXCJvcGVuXCIsIGFyZ3VtZW50czogW3VybF0gfVxuICAgICAgICA6IHByb2Nlc3MucGxhdGZvcm0gPT09IFwid2luMzJcIlxuICAgICAgICAgID8ge1xuICAgICAgICAgICAgICBleGVjdXRhYmxlOiBcInJ1bmRsbDMyLmV4ZVwiLFxuICAgICAgICAgICAgICBhcmd1bWVudHM6IFtcInVybC5kbGwsRmlsZVByb3RvY29sSGFuZGxlclwiLCB1cmxdLFxuICAgICAgICAgICAgfVxuICAgICAgICAgIDogeyBleGVjdXRhYmxlOiBcInhkZy1vcGVuXCIsIGFyZ3VtZW50czogW3VybF0gfTtcbiAgICBjb25zdCBjaGlsZCA9IHRoaXMuc3RhcnRQcm9jZXNzKGNvbW1hbmQsIGZhbHNlKTtcbiAgICBjaGlsZC51bnJlZigpO1xuICB9XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHJ1bkNsaVNlcnZpY2VIb3N0KGNvbmZpZ0ZpbGU6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICBwcm9jZXNzLmNoZGlyKGRpcm5hbWUocHJvY2Vzcy5leGVjUGF0aCkpO1xuICBjb25zdCBkZWZpbml0aW9uID0gYXdhaXQgcmVhZFNlcnZpY2VEZWZpbml0aW9uKGNvbmZpZ0ZpbGUpO1xuICBjb25zdCBydW50aW1lID0gZGVmYXVsdFJ1bnRpbWVDb250ZXh0KCk7XG4gIGNvbnN0IHBhdGhzID0gcmVzb2x2ZVNlcnZpY2VQYXRocyhkZWZpbml0aW9uLCBydW50aW1lKTtcbiAgbGV0IHJlcXVlc3RTdG9wOiAoKSA9PiB2b2lkID0gKCkgPT4ge307XG4gIGNvbnN0IHN0b3BwZWQgPSBuZXcgUHJvbWlzZTx2b2lkPigocmVzb2x2ZSkgPT4ge1xuICAgIHJlcXVlc3RTdG9wID0gcmVzb2x2ZTtcbiAgfSk7XG4gIGNvbnN0IGhvc3QgPSBuZXcgQ2xpU2VydmljZUhvc3QoZGVmaW5pdGlvbiwgcGF0aHMsIHJlcXVlc3RTdG9wKTtcbiAgcHJvY2Vzcy5vbmNlKFwiU0lHSU5UXCIsIHJlcXVlc3RTdG9wKTtcbiAgcHJvY2Vzcy5vbmNlKFwiU0lHVEVSTVwiLCByZXF1ZXN0U3RvcCk7XG4gIHRyeSB7XG4gICAgYXdhaXQgaG9zdC5zdGFydCgpO1xuICAgIGF3YWl0IHN0b3BwZWQ7XG4gIH0gZmluYWxseSB7XG4gICAgYXdhaXQgaG9zdC5zdG9wKCk7XG4gIH1cbn1cblxuYXN5bmMgZnVuY3Rpb24gc3RvcFByb2Nlc3MoY2hpbGQ6IENoaWxkUHJvY2Vzcyk6IFByb21pc2U8dm9pZD4ge1xuICBpZiAoY2hpbGQuZXhpdENvZGUgIT09IG51bGwgfHwgY2hpbGQuc2lnbmFsQ29kZSAhPT0gbnVsbCkgcmV0dXJuO1xuICBjb25zdCBleGl0ZWQgPSBuZXcgUHJvbWlzZTx2b2lkPigocmVzb2x2ZSkgPT4gY2hpbGQub25jZShcImV4aXRcIiwgKCkgPT4gcmVzb2x2ZSgpKSk7XG4gIGNoaWxkLmtpbGwoXCJTSUdURVJNXCIpO1xuICBjb25zdCB0aW1lZE91dCA9IG5ldyBQcm9taXNlPFwidGltZW91dFwiPigocmVzb2x2ZSkgPT4ge1xuICAgIHNldFRpbWVvdXQoKCkgPT4gcmVzb2x2ZShcInRpbWVvdXRcIiksIENISUxEX1NUT1BfVElNRU9VVF9NSUxMSVNFQ09ORFMpO1xuICB9KTtcbiAgaWYgKChhd2FpdCBQcm9taXNlLnJhY2UoW2V4aXRlZCwgdGltZWRPdXRdKSkgPT09IFwidGltZW91dFwiKSB7XG4gICAgY2hpbGQua2lsbChcIlNJR0tJTExcIik7XG4gICAgYXdhaXQgZXhpdGVkO1xuICB9XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGxvZ0Vycm9yKHBhdGg6IHN0cmluZywgZXJyb3I6IHVua25vd24pOiBQcm9taXNlPHZvaWQ+IHtcbiAgYXdhaXQgbG9nTWVzc2FnZShwYXRoLCBlcnJvciBpbnN0YW5jZW9mIEVycm9yID8gKGVycm9yLnN0YWNrID8/IGVycm9yLm1lc3NhZ2UpIDogU3RyaW5nKGVycm9yKSk7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGxvZ01lc3NhZ2UocGF0aDogc3RyaW5nLCBtZXNzYWdlOiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgYXdhaXQgbWtkaXIoZGlybmFtZShwYXRoKSwgeyByZWN1cnNpdmU6IHRydWUgfSk7XG4gIGF3YWl0IGFwcGVuZEZpbGUocGF0aCwgYCR7bmV3IERhdGUoKS50b0lTT1N0cmluZygpfSAke21lc3NhZ2V9XFxuYCwgXCJ1dGY4XCIpO1xufVxuXG5mdW5jdGlvbiBhcmd1bWVudFZhbHVlKG5hbWU6IHN0cmluZyk6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gIGNvbnN0IGluZGV4ID0gcHJvY2Vzcy5hcmd2LmluZGV4T2YobmFtZSk7XG4gIHJldHVybiBpbmRleCA+PSAwID8gcHJvY2Vzcy5hcmd2W2luZGV4ICsgMV0gOiB1bmRlZmluZWQ7XG59XG5cbmNvbnN0IGNvbmZpZ0ZpbGUgPSBhcmd1bWVudFZhbHVlKFwiLS1zZXJ2aWNlLWNvbmZpZ1wiKTtcbmlmIChjb25maWdGaWxlKSB7XG4gIHZvaWQgcnVuQ2xpU2VydmljZUhvc3QoY29uZmlnRmlsZSkuY2F0Y2goYXN5bmMgKGVycm9yOiB1bmtub3duKSA9PiB7XG4gICAgYXdhaXQgbG9nRXJyb3Ioam9pbihkaXJuYW1lKGNvbmZpZ0ZpbGUpLCBcImhvc3QubG9nXCIpLCBlcnJvcik7XG4gICAgcHJvY2Vzcy5leGl0Q29kZSA9IDE7XG4gIH0pO1xufVxuIl19
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export interface ServicePackage {
|
|
2
|
+
readonly directory: string;
|
|
3
|
+
readonly name: string;
|
|
4
|
+
readonly version: string;
|
|
5
|
+
bin(name?: string): string;
|
|
6
|
+
dependencies(): Readonly<Record<string, string>>;
|
|
7
|
+
}
|
|
8
|
+
export declare function resolveServicePackage(reference: string, cwd?: string): ServicePackage;
|
|
9
|
+
export declare function servicePackageDefaults(pkg: ServicePackage): {
|
|
10
|
+
id: string;
|
|
11
|
+
name: string;
|
|
12
|
+
};
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
2
|
+
import { createRequire } from "node:module";
|
|
3
|
+
import { dirname, isAbsolute, join, resolve } from "node:path";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
5
|
+
import * as projectUtils from "@dbx-tools/core/project-utils";
|
|
6
|
+
export function resolveServicePackage(reference, cwd = process.cwd()) {
|
|
7
|
+
const local = localManifest(reference);
|
|
8
|
+
if (local)
|
|
9
|
+
return servicePackage(local);
|
|
10
|
+
const name = reference;
|
|
11
|
+
const installed = installedManifest(name);
|
|
12
|
+
if (installed)
|
|
13
|
+
return servicePackage(installed, name);
|
|
14
|
+
const root = projectUtils.root(cwd);
|
|
15
|
+
if (!root)
|
|
16
|
+
throw new Error(`could not resolve package: ${name}`);
|
|
17
|
+
const manifest = readRecord(join(root, "package.json"));
|
|
18
|
+
const workspaces = Array.isArray(manifest.workspaces) ? manifest.workspaces : [];
|
|
19
|
+
for (const member of workspaces) {
|
|
20
|
+
if (typeof member !== "string" || /[*?[\]{}]/.test(member))
|
|
21
|
+
continue;
|
|
22
|
+
const path = join(root, member, "package.json");
|
|
23
|
+
if (!existsSync(path))
|
|
24
|
+
continue;
|
|
25
|
+
const candidate = readRecord(path);
|
|
26
|
+
if (candidate.name === name)
|
|
27
|
+
return servicePackage(path, name);
|
|
28
|
+
}
|
|
29
|
+
throw new Error(`could not resolve installed or workspace package: ${name}`);
|
|
30
|
+
}
|
|
31
|
+
export function servicePackageDefaults(pkg) {
|
|
32
|
+
const segments = pkg.name.replace(/^@/, "").split("/");
|
|
33
|
+
const rawName = segments.at(-1);
|
|
34
|
+
const rawScope = segments.length > 1 ? segments[0].split("-")[0] : "";
|
|
35
|
+
const name = rawName.replace(/^cli-/, "").replaceAll("-", " ");
|
|
36
|
+
return {
|
|
37
|
+
id: pkg.name
|
|
38
|
+
.replace(/^@/, "")
|
|
39
|
+
.replaceAll("/", ".")
|
|
40
|
+
.replace(/[^a-z0-9._-]+/gi, "-"),
|
|
41
|
+
name: [rawScope, name].filter(Boolean).join(" "),
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
function localManifest(reference) {
|
|
45
|
+
let path;
|
|
46
|
+
if (reference.startsWith("file:")) {
|
|
47
|
+
path = fileURLToPath(reference);
|
|
48
|
+
}
|
|
49
|
+
else if (isAbsolute(reference)) {
|
|
50
|
+
path = reference;
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
return undefined;
|
|
54
|
+
}
|
|
55
|
+
let current = existsSync(path) ? dirname(path) : path;
|
|
56
|
+
while (true) {
|
|
57
|
+
const manifest = join(current, "package.json");
|
|
58
|
+
if (existsSync(manifest))
|
|
59
|
+
return manifest;
|
|
60
|
+
const parent = dirname(current);
|
|
61
|
+
if (parent === current)
|
|
62
|
+
return undefined;
|
|
63
|
+
current = parent;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
function installedManifest(name) {
|
|
67
|
+
try {
|
|
68
|
+
return createRequire(import.meta.url).resolve(`${name}/package.json`);
|
|
69
|
+
}
|
|
70
|
+
catch (error) {
|
|
71
|
+
if (error.code === "MODULE_NOT_FOUND")
|
|
72
|
+
return undefined;
|
|
73
|
+
throw error;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
function servicePackage(manifestPath, expectedName) {
|
|
77
|
+
const manifest = readRecord(manifestPath);
|
|
78
|
+
if (typeof manifest.name !== "string" || !manifest.name) {
|
|
79
|
+
throw new Error(`package has no name: ${manifestPath}`);
|
|
80
|
+
}
|
|
81
|
+
if (expectedName && manifest.name !== expectedName) {
|
|
82
|
+
throw new Error(`resolved package name does not match ${expectedName}: ${manifestPath}`);
|
|
83
|
+
}
|
|
84
|
+
if (typeof manifest.version !== "string" || !manifest.version) {
|
|
85
|
+
throw new Error(`package has no version: ${manifestPath}`);
|
|
86
|
+
}
|
|
87
|
+
const directory = dirname(manifestPath);
|
|
88
|
+
return {
|
|
89
|
+
directory,
|
|
90
|
+
name: manifest.name,
|
|
91
|
+
version: manifest.version,
|
|
92
|
+
bin(name) {
|
|
93
|
+
return resolveBin(directory, manifest.bin, name);
|
|
94
|
+
},
|
|
95
|
+
dependencies() {
|
|
96
|
+
const dependencies = isRecord(manifest.dependencies)
|
|
97
|
+
? Object.keys(manifest.dependencies)
|
|
98
|
+
: [];
|
|
99
|
+
const require = createRequire(manifestPath);
|
|
100
|
+
return Object.fromEntries(dependencies.map((dependency) => {
|
|
101
|
+
const path = require.resolve(`${dependency}/package.json`);
|
|
102
|
+
const resolved = readRecord(path);
|
|
103
|
+
if (typeof resolved.version !== "string" || !resolved.version) {
|
|
104
|
+
throw new Error(`dependency has no version: ${path}`);
|
|
105
|
+
}
|
|
106
|
+
return [dependency, resolved.version];
|
|
107
|
+
}));
|
|
108
|
+
},
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
function resolveBin(directory, value, name) {
|
|
112
|
+
if (typeof value === "string") {
|
|
113
|
+
if (name)
|
|
114
|
+
throw new Error(`package exposes one unnamed bin, not ${name}`);
|
|
115
|
+
return resolve(directory, value);
|
|
116
|
+
}
|
|
117
|
+
if (!isRecord(value))
|
|
118
|
+
throw new Error("package has no bin");
|
|
119
|
+
if (name) {
|
|
120
|
+
const target = value[name];
|
|
121
|
+
if (typeof target !== "string")
|
|
122
|
+
throw new Error(`package has no bin named ${name}`);
|
|
123
|
+
return resolve(directory, target);
|
|
124
|
+
}
|
|
125
|
+
const targets = Object.values(value).filter((target) => typeof target === "string");
|
|
126
|
+
if (targets.length !== 1) {
|
|
127
|
+
throw new Error("package has multiple bins; command.binName is required");
|
|
128
|
+
}
|
|
129
|
+
return resolve(directory, targets[0]);
|
|
130
|
+
}
|
|
131
|
+
function readRecord(path) {
|
|
132
|
+
const value = JSON.parse(readFileSync(path, "utf8"));
|
|
133
|
+
if (!isRecord(value))
|
|
134
|
+
throw new Error(`package manifest is not an object: ${path}`);
|
|
135
|
+
return value;
|
|
136
|
+
}
|
|
137
|
+
function isRecord(value) {
|
|
138
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
139
|
+
}
|
|
140
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiX3BhY2thZ2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvX3BhY2thZ2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFVBQVUsRUFBRSxZQUFZLEVBQUUsTUFBTSxTQUFTLENBQUM7QUFDbkQsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUM1QyxPQUFPLEVBQUUsT0FBTyxFQUFFLFVBQVUsRUFBRSxJQUFJLEVBQUUsT0FBTyxFQUFFLE1BQU0sV0FBVyxDQUFDO0FBQy9ELE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxVQUFVLENBQUM7QUFFekMsT0FBTyxLQUFLLFlBQVksTUFBTSwrQkFBK0IsQ0FBQztBQVU5RCxNQUFNLFVBQVUscUJBQXFCLENBQ25DLFNBQWlCLEVBQ2pCLE1BQWMsT0FBTyxDQUFDLEdBQUcsRUFBRTtJQUUzQixNQUFNLEtBQUssR0FBRyxhQUFhLENBQUMsU0FBUyxDQUFDLENBQUM7SUFDdkMsSUFBSSxLQUFLO1FBQUUsT0FBTyxjQUFjLENBQUMsS0FBSyxDQUFDLENBQUM7SUFFeEMsTUFBTSxJQUFJLEdBQUcsU0FBUyxDQUFDO0lBQ3ZCLE1BQU0sU0FBUyxHQUFHLGlCQUFpQixDQUFDLElBQUksQ0FBQyxDQUFDO0lBQzFDLElBQUksU0FBUztRQUFFLE9BQU8sY0FBYyxDQUFDLFNBQVMsRUFBRSxJQUFJLENBQUMsQ0FBQztJQUV0RCxNQUFNLElBQUksR0FBRyxZQUFZLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQ3BDLElBQUksQ0FBQyxJQUFJO1FBQUUsTUFBTSxJQUFJLEtBQUssQ0FBQyw4QkFBOEIsSUFBSSxFQUFFLENBQUMsQ0FBQztJQUNqRSxNQUFNLFFBQVEsR0FBRyxVQUFVLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxjQUFjLENBQUMsQ0FBQyxDQUFDO0lBQ3hELE1BQU0sVUFBVSxHQUFHLEtBQUssQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7SUFDakYsS0FBSyxNQUFNLE1BQU0sSUFBSSxVQUFVLEVBQUUsQ0FBQztRQUNoQyxJQUFJLE9BQU8sTUFBTSxLQUFLLFFBQVEsSUFBSSxXQUFXLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQztZQUFFLFNBQVM7UUFDckUsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLElBQUksRUFBRSxNQUFNLEVBQUUsY0FBYyxDQUFDLENBQUM7UUFDaEQsSUFBSSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUM7WUFBRSxTQUFTO1FBQ2hDLE1BQU0sU0FBUyxHQUFHLFVBQVUsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUNuQyxJQUFJLFNBQVMsQ0FBQyxJQUFJLEtBQUssSUFBSTtZQUFFLE9BQU8sY0FBYyxDQUFDLElBQUksRUFBRSxJQUFJLENBQUMsQ0FBQztJQUNqRSxDQUFDO0lBQ0QsTUFBTSxJQUFJLEtBQUssQ0FBQyxxREFBcUQsSUFBSSxFQUFFLENBQUMsQ0FBQztBQUMvRSxDQUFDO0FBRUQsTUFBTSxVQUFVLHNCQUFzQixDQUFDLEdBQW1CO0lBSXhELE1BQU0sUUFBUSxHQUFHLEdBQUcsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDdkQsTUFBTSxPQUFPLEdBQUcsUUFBUSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBRSxDQUFDO0lBQ2pDLE1BQU0sUUFBUSxHQUFHLFFBQVEsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFFLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7SUFDeEUsTUFBTSxJQUFJLEdBQUcsT0FBTyxDQUFDLE9BQU8sQ0FBQyxPQUFPLEVBQUUsRUFBRSxDQUFDLENBQUMsVUFBVSxDQUFDLEdBQUcsRUFBRSxHQUFHLENBQUMsQ0FBQztJQUMvRCxPQUFPO1FBQ0wsRUFBRSxFQUFFLEdBQUcsQ0FBQyxJQUFJO2FBQ1QsT0FBTyxDQUFDLElBQUksRUFBRSxFQUFFLENBQUM7YUFDakIsVUFBVSxDQUFDLEdBQUcsRUFBRSxHQUFHLENBQUM7YUFDcEIsT0FBTyxDQUFDLGlCQUFpQixFQUFFLEdBQUcsQ0FBQztRQUNsQyxJQUFJLEVBQUUsQ0FBQyxRQUFRLEVBQUUsSUFBSSxDQUFDLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUM7S0FDakQsQ0FBQztBQUNKLENBQUM7QUFFRCxTQUFTLGFBQWEsQ0FBQyxTQUFpQjtJQUN0QyxJQUFJLElBQVksQ0FBQztJQUNqQixJQUFJLFNBQVMsQ0FBQyxVQUFVLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQztRQUNsQyxJQUFJLEdBQUcsYUFBYSxDQUFDLFNBQVMsQ0FBQyxDQUFDO0lBQ2xDLENBQUM7U0FBTSxJQUFJLFVBQVUsQ0FBQyxTQUFTLENBQUMsRUFBRSxDQUFDO1FBQ2pDLElBQUksR0FBRyxTQUFTLENBQUM7SUFDbkIsQ0FBQztTQUFNLENBQUM7UUFDTixPQUFPLFNBQVMsQ0FBQztJQUNuQixDQUFDO0lBQ0QsSUFBSSxPQUFPLEdBQUcsVUFBVSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQztJQUN0RCxPQUFPLElBQUksRUFBRSxDQUFDO1FBQ1osTUFBTSxRQUFRLEdBQUcsSUFBSSxDQUFDLE9BQU8sRUFBRSxjQUFjLENBQUMsQ0FBQztRQUMvQyxJQUFJLFVBQVUsQ0FBQyxRQUFRLENBQUM7WUFBRSxPQUFPLFFBQVEsQ0FBQztRQUMxQyxNQUFNLE1BQU0sR0FBRyxPQUFPLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDaEMsSUFBSSxNQUFNLEtBQUssT0FBTztZQUFFLE9BQU8sU0FBUyxDQUFDO1FBQ3pDLE9BQU8sR0FBRyxNQUFNLENBQUM7SUFDbkIsQ0FBQztBQUNILENBQUM7QUFFRCxTQUFTLGlCQUFpQixDQUFDLElBQVk7SUFDckMsSUFBSSxDQUFDO1FBQ0gsT0FBTyxhQUFhLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxPQUFPLENBQUMsR0FBRyxJQUFJLGVBQWUsQ0FBQyxDQUFDO0lBQ3hFLENBQUM7SUFBQyxPQUFPLEtBQUssRUFBRSxDQUFDO1FBQ2YsSUFBSyxLQUErQixDQUFDLElBQUksS0FBSyxrQkFBa0I7WUFBRSxPQUFPLFNBQVMsQ0FBQztRQUNuRixNQUFNLEtBQUssQ0FBQztJQUNkLENBQUM7QUFDSCxDQUFDO0FBRUQsU0FBUyxjQUFjLENBQUMsWUFBb0IsRUFBRSxZQUFxQjtJQUNqRSxNQUFNLFFBQVEsR0FBRyxVQUFVLENBQUMsWUFBWSxDQUFDLENBQUM7SUFDMUMsSUFBSSxPQUFPLFFBQVEsQ0FBQyxJQUFJLEtBQUssUUFBUSxJQUFJLENBQUMsUUFBUSxDQUFDLElBQUksRUFBRSxDQUFDO1FBQ3hELE1BQU0sSUFBSSxLQUFLLENBQUMsd0JBQXdCLFlBQVksRUFBRSxDQUFDLENBQUM7SUFDMUQsQ0FBQztJQUNELElBQUksWUFBWSxJQUFJLFFBQVEsQ0FBQyxJQUFJLEtBQUssWUFBWSxFQUFFLENBQUM7UUFDbkQsTUFBTSxJQUFJLEtBQUssQ0FBQyx3Q0FBd0MsWUFBWSxLQUFLLFlBQVksRUFBRSxDQUFDLENBQUM7SUFDM0YsQ0FBQztJQUNELElBQUksT0FBTyxRQUFRLENBQUMsT0FBTyxLQUFLLFFBQVEsSUFBSSxDQUFDLFFBQVEsQ0FBQyxPQUFPLEVBQUUsQ0FBQztRQUM5RCxNQUFNLElBQUksS0FBSyxDQUFDLDJCQUEyQixZQUFZLEVBQUUsQ0FBQyxDQUFDO0lBQzdELENBQUM7SUFDRCxNQUFNLFNBQVMsR0FBRyxPQUFPLENBQUMsWUFBWSxDQUFDLENBQUM7SUFDeEMsT0FBTztRQUNMLFNBQVM7UUFDVCxJQUFJLEVBQUUsUUFBUSxDQUFDLElBQUk7UUFDbkIsT0FBTyxFQUFFLFFBQVEsQ0FBQyxPQUFPO1FBQ3pCLEdBQUcsQ0FBQyxJQUFJO1lBQ04sT0FBTyxVQUFVLENBQUMsU0FBUyxFQUFFLFFBQVEsQ0FBQyxHQUFHLEVBQUUsSUFBSSxDQUFDLENBQUM7UUFDbkQsQ0FBQztRQUNELFlBQVk7WUFDVixNQUFNLFlBQVksR0FBRyxRQUFRLENBQUMsUUFBUSxDQUFDLFlBQVksQ0FBQztnQkFDbEQsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLFlBQVksQ0FBQztnQkFDcEMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztZQUNQLE1BQU0sT0FBTyxHQUFHLGFBQWEsQ0FBQyxZQUFZLENBQUMsQ0FBQztZQUM1QyxPQUFPLE1BQU0sQ0FBQyxXQUFXLENBQ3ZCLFlBQVksQ0FBQyxHQUFHLENBQUMsQ0FBQyxVQUFVLEVBQUUsRUFBRTtnQkFDOUIsTUFBTSxJQUFJLEdBQUcsT0FBTyxDQUFDLE9BQU8sQ0FBQyxHQUFHLFVBQVUsZUFBZSxDQUFDLENBQUM7Z0JBQzNELE1BQU0sUUFBUSxHQUFHLFVBQVUsQ0FBQyxJQUFJLENBQUMsQ0FBQztnQkFDbEMsSUFBSSxPQUFPLFFBQVEsQ0FBQyxPQUFPLEtBQUssUUFBUSxJQUFJLENBQUMsUUFBUSxDQUFDLE9BQU8sRUFBRSxDQUFDO29CQUM5RCxNQUFNLElBQUksS0FBSyxDQUFDLDhCQUE4QixJQUFJLEVBQUUsQ0FBQyxDQUFDO2dCQUN4RCxDQUFDO2dCQUNELE9BQU8sQ0FBQyxVQUFVLEVBQUUsUUFBUSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1lBQ3hDLENBQUMsQ0FBQyxDQUNILENBQUM7UUFDSixDQUFDO0tBQ0YsQ0FBQztBQUNKLENBQUM7QUFFRCxTQUFTLFVBQVUsQ0FBQyxTQUFpQixFQUFFLEtBQWMsRUFBRSxJQUFhO0lBQ2xFLElBQUksT0FBTyxLQUFLLEtBQUssUUFBUSxFQUFFLENBQUM7UUFDOUIsSUFBSSxJQUFJO1lBQUUsTUFBTSxJQUFJLEtBQUssQ0FBQyx3Q0FBd0MsSUFBSSxFQUFFLENBQUMsQ0FBQztRQUMxRSxPQUFPLE9BQU8sQ0FBQyxTQUFTLEVBQUUsS0FBSyxDQUFDLENBQUM7SUFDbkMsQ0FBQztJQUNELElBQUksQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDO1FBQUUsTUFBTSxJQUFJLEtBQUssQ0FBQyxvQkFBb0IsQ0FBQyxDQUFDO0lBQzVELElBQUksSUFBSSxFQUFFLENBQUM7UUFDVCxNQUFNLE1BQU0sR0FBRyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDM0IsSUFBSSxPQUFPLE1BQU0sS0FBSyxRQUFRO1lBQUUsTUFBTSxJQUFJLEtBQUssQ0FBQyw0QkFBNEIsSUFBSSxFQUFFLENBQUMsQ0FBQztRQUNwRixPQUFPLE9BQU8sQ0FBQyxTQUFTLEVBQUUsTUFBTSxDQUFDLENBQUM7SUFDcEMsQ0FBQztJQUNELE1BQU0sT0FBTyxHQUFHLE1BQU0sQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsTUFBTSxDQUN6QyxDQUFDLE1BQU0sRUFBb0IsRUFBRSxDQUFDLE9BQU8sTUFBTSxLQUFLLFFBQVEsQ0FDekQsQ0FBQztJQUNGLElBQUksT0FBTyxDQUFDLE1BQU0sS0FBSyxDQUFDLEVBQUUsQ0FBQztRQUN6QixNQUFNLElBQUksS0FBSyxDQUFDLHdEQUF3RCxDQUFDLENBQUM7SUFDNUUsQ0FBQztJQUNELE9BQU8sT0FBTyxDQUFDLFNBQVMsRUFBRSxPQUFPLENBQUMsQ0FBQyxDQUFFLENBQUMsQ0FBQztBQUN6QyxDQUFDO0FBRUQsU0FBUyxVQUFVLENBQUMsSUFBWTtJQUM5QixNQUFNLEtBQUssR0FBWSxJQUFJLENBQUMsS0FBSyxDQUFDLFlBQVksQ0FBQyxJQUFJLEVBQUUsTUFBTSxDQUFDLENBQUMsQ0FBQztJQUM5RCxJQUFJLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQztRQUFFLE1BQU0sSUFBSSxLQUFLLENBQUMsc0NBQXNDLElBQUksRUFBRSxDQUFDLENBQUM7SUFDcEYsT0FBTyxLQUFLLENBQUM7QUFDZixDQUFDO0FBRUQsU0FBUyxRQUFRLENBQUMsS0FBYztJQUM5QixPQUFPLEtBQUssS0FBSyxJQUFJLElBQUksT0FBTyxLQUFLLEtBQUssUUFBUSxJQUFJLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQztBQUM5RSxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgZXhpc3RzU3luYywgcmVhZEZpbGVTeW5jIH0gZnJvbSBcIm5vZGU6ZnNcIjtcbmltcG9ydCB7IGNyZWF0ZVJlcXVpcmUgfSBmcm9tIFwibm9kZTptb2R1bGVcIjtcbmltcG9ydCB7IGRpcm5hbWUsIGlzQWJzb2x1dGUsIGpvaW4sIHJlc29sdmUgfSBmcm9tIFwibm9kZTpwYXRoXCI7XG5pbXBvcnQgeyBmaWxlVVJMVG9QYXRoIH0gZnJvbSBcIm5vZGU6dXJsXCI7XG5cbmltcG9ydCAqIGFzIHByb2plY3RVdGlscyBmcm9tIFwiQGRieC10b29scy9jb3JlL3Byb2plY3QtdXRpbHNcIjtcblxuZXhwb3J0IGludGVyZmFjZSBTZXJ2aWNlUGFja2FnZSB7XG4gIHJlYWRvbmx5IGRpcmVjdG9yeTogc3RyaW5nO1xuICByZWFkb25seSBuYW1lOiBzdHJpbmc7XG4gIHJlYWRvbmx5IHZlcnNpb246IHN0cmluZztcbiAgYmluKG5hbWU/OiBzdHJpbmcpOiBzdHJpbmc7XG4gIGRlcGVuZGVuY2llcygpOiBSZWFkb25seTxSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+Pjtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHJlc29sdmVTZXJ2aWNlUGFja2FnZShcbiAgcmVmZXJlbmNlOiBzdHJpbmcsXG4gIGN3ZDogc3RyaW5nID0gcHJvY2Vzcy5jd2QoKSxcbik6IFNlcnZpY2VQYWNrYWdlIHtcbiAgY29uc3QgbG9jYWwgPSBsb2NhbE1hbmlmZXN0KHJlZmVyZW5jZSk7XG4gIGlmIChsb2NhbCkgcmV0dXJuIHNlcnZpY2VQYWNrYWdlKGxvY2FsKTtcblxuICBjb25zdCBuYW1lID0gcmVmZXJlbmNlO1xuICBjb25zdCBpbnN0YWxsZWQgPSBpbnN0YWxsZWRNYW5pZmVzdChuYW1lKTtcbiAgaWYgKGluc3RhbGxlZCkgcmV0dXJuIHNlcnZpY2VQYWNrYWdlKGluc3RhbGxlZCwgbmFtZSk7XG5cbiAgY29uc3Qgcm9vdCA9IHByb2plY3RVdGlscy5yb290KGN3ZCk7XG4gIGlmICghcm9vdCkgdGhyb3cgbmV3IEVycm9yKGBjb3VsZCBub3QgcmVzb2x2ZSBwYWNrYWdlOiAke25hbWV9YCk7XG4gIGNvbnN0IG1hbmlmZXN0ID0gcmVhZFJlY29yZChqb2luKHJvb3QsIFwicGFja2FnZS5qc29uXCIpKTtcbiAgY29uc3Qgd29ya3NwYWNlcyA9IEFycmF5LmlzQXJyYXkobWFuaWZlc3Qud29ya3NwYWNlcykgPyBtYW5pZmVzdC53b3Jrc3BhY2VzIDogW107XG4gIGZvciAoY29uc3QgbWVtYmVyIG9mIHdvcmtzcGFjZXMpIHtcbiAgICBpZiAodHlwZW9mIG1lbWJlciAhPT0gXCJzdHJpbmdcIiB8fCAvWyo/W1xcXXt9XS8udGVzdChtZW1iZXIpKSBjb250aW51ZTtcbiAgICBjb25zdCBwYXRoID0gam9pbihyb290LCBtZW1iZXIsIFwicGFja2FnZS5qc29uXCIpO1xuICAgIGlmICghZXhpc3RzU3luYyhwYXRoKSkgY29udGludWU7XG4gICAgY29uc3QgY2FuZGlkYXRlID0gcmVhZFJlY29yZChwYXRoKTtcbiAgICBpZiAoY2FuZGlkYXRlLm5hbWUgPT09IG5hbWUpIHJldHVybiBzZXJ2aWNlUGFja2FnZShwYXRoLCBuYW1lKTtcbiAgfVxuICB0aHJvdyBuZXcgRXJyb3IoYGNvdWxkIG5vdCByZXNvbHZlIGluc3RhbGxlZCBvciB3b3Jrc3BhY2UgcGFja2FnZTogJHtuYW1lfWApO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gc2VydmljZVBhY2thZ2VEZWZhdWx0cyhwa2c6IFNlcnZpY2VQYWNrYWdlKToge1xuICBpZDogc3RyaW5nO1xuICBuYW1lOiBzdHJpbmc7XG59IHtcbiAgY29uc3Qgc2VnbWVudHMgPSBwa2cubmFtZS5yZXBsYWNlKC9eQC8sIFwiXCIpLnNwbGl0KFwiL1wiKTtcbiAgY29uc3QgcmF3TmFtZSA9IHNlZ21lbnRzLmF0KC0xKSE7XG4gIGNvbnN0IHJhd1Njb3BlID0gc2VnbWVudHMubGVuZ3RoID4gMSA/IHNlZ21lbnRzWzBdIS5zcGxpdChcIi1cIilbMF0hIDogXCJcIjtcbiAgY29uc3QgbmFtZSA9IHJhd05hbWUucmVwbGFjZSgvXmNsaS0vLCBcIlwiKS5yZXBsYWNlQWxsKFwiLVwiLCBcIiBcIik7XG4gIHJldHVybiB7XG4gICAgaWQ6IHBrZy5uYW1lXG4gICAgICAucmVwbGFjZSgvXkAvLCBcIlwiKVxuICAgICAgLnJlcGxhY2VBbGwoXCIvXCIsIFwiLlwiKVxuICAgICAgLnJlcGxhY2UoL1teYS16MC05Ll8tXSsvZ2ksIFwiLVwiKSxcbiAgICBuYW1lOiBbcmF3U2NvcGUsIG5hbWVdLmZpbHRlcihCb29sZWFuKS5qb2luKFwiIFwiKSxcbiAgfTtcbn1cblxuZnVuY3Rpb24gbG9jYWxNYW5pZmVzdChyZWZlcmVuY2U6IHN0cmluZyk6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gIGxldCBwYXRoOiBzdHJpbmc7XG4gIGlmIChyZWZlcmVuY2Uuc3RhcnRzV2l0aChcImZpbGU6XCIpKSB7XG4gICAgcGF0aCA9IGZpbGVVUkxUb1BhdGgocmVmZXJlbmNlKTtcbiAgfSBlbHNlIGlmIChpc0Fic29sdXRlKHJlZmVyZW5jZSkpIHtcbiAgICBwYXRoID0gcmVmZXJlbmNlO1xuICB9IGVsc2Uge1xuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH1cbiAgbGV0IGN1cnJlbnQgPSBleGlzdHNTeW5jKHBhdGgpID8gZGlybmFtZShwYXRoKSA6IHBhdGg7XG4gIHdoaWxlICh0cnVlKSB7XG4gICAgY29uc3QgbWFuaWZlc3QgPSBqb2luKGN1cnJlbnQsIFwicGFja2FnZS5qc29uXCIpO1xuICAgIGlmIChleGlzdHNTeW5jKG1hbmlmZXN0KSkgcmV0dXJuIG1hbmlmZXN0O1xuICAgIGNvbnN0IHBhcmVudCA9IGRpcm5hbWUoY3VycmVudCk7XG4gICAgaWYgKHBhcmVudCA9PT0gY3VycmVudCkgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICBjdXJyZW50ID0gcGFyZW50O1xuICB9XG59XG5cbmZ1bmN0aW9uIGluc3RhbGxlZE1hbmlmZXN0KG5hbWU6IHN0cmluZyk6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gIHRyeSB7XG4gICAgcmV0dXJuIGNyZWF0ZVJlcXVpcmUoaW1wb3J0Lm1ldGEudXJsKS5yZXNvbHZlKGAke25hbWV9L3BhY2thZ2UuanNvbmApO1xuICB9IGNhdGNoIChlcnJvcikge1xuICAgIGlmICgoZXJyb3IgYXMgTm9kZUpTLkVycm5vRXhjZXB0aW9uKS5jb2RlID09PSBcIk1PRFVMRV9OT1RfRk9VTkRcIikgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICB0aHJvdyBlcnJvcjtcbiAgfVxufVxuXG5mdW5jdGlvbiBzZXJ2aWNlUGFja2FnZShtYW5pZmVzdFBhdGg6IHN0cmluZywgZXhwZWN0ZWROYW1lPzogc3RyaW5nKTogU2VydmljZVBhY2thZ2Uge1xuICBjb25zdCBtYW5pZmVzdCA9IHJlYWRSZWNvcmQobWFuaWZlc3RQYXRoKTtcbiAgaWYgKHR5cGVvZiBtYW5pZmVzdC5uYW1lICE9PSBcInN0cmluZ1wiIHx8ICFtYW5pZmVzdC5uYW1lKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBwYWNrYWdlIGhhcyBubyBuYW1lOiAke21hbmlmZXN0UGF0aH1gKTtcbiAgfVxuICBpZiAoZXhwZWN0ZWROYW1lICYmIG1hbmlmZXN0Lm5hbWUgIT09IGV4cGVjdGVkTmFtZSkge1xuICAgIHRocm93IG5ldyBFcnJvcihgcmVzb2x2ZWQgcGFja2FnZSBuYW1lIGRvZXMgbm90IG1hdGNoICR7ZXhwZWN0ZWROYW1lfTogJHttYW5pZmVzdFBhdGh9YCk7XG4gIH1cbiAgaWYgKHR5cGVvZiBtYW5pZmVzdC52ZXJzaW9uICE9PSBcInN0cmluZ1wiIHx8ICFtYW5pZmVzdC52ZXJzaW9uKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBwYWNrYWdlIGhhcyBubyB2ZXJzaW9uOiAke21hbmlmZXN0UGF0aH1gKTtcbiAgfVxuICBjb25zdCBkaXJlY3RvcnkgPSBkaXJuYW1lKG1hbmlmZXN0UGF0aCk7XG4gIHJldHVybiB7XG4gICAgZGlyZWN0b3J5LFxuICAgIG5hbWU6IG1hbmlmZXN0Lm5hbWUsXG4gICAgdmVyc2lvbjogbWFuaWZlc3QudmVyc2lvbixcbiAgICBiaW4obmFtZSkge1xuICAgICAgcmV0dXJuIHJlc29sdmVCaW4oZGlyZWN0b3J5LCBtYW5pZmVzdC5iaW4sIG5hbWUpO1xuICAgIH0sXG4gICAgZGVwZW5kZW5jaWVzKCkge1xuICAgICAgY29uc3QgZGVwZW5kZW5jaWVzID0gaXNSZWNvcmQobWFuaWZlc3QuZGVwZW5kZW5jaWVzKVxuICAgICAgICA/IE9iamVjdC5rZXlzKG1hbmlmZXN0LmRlcGVuZGVuY2llcylcbiAgICAgICAgOiBbXTtcbiAgICAgIGNvbnN0IHJlcXVpcmUgPSBjcmVhdGVSZXF1aXJlKG1hbmlmZXN0UGF0aCk7XG4gICAgICByZXR1cm4gT2JqZWN0LmZyb21FbnRyaWVzKFxuICAgICAgICBkZXBlbmRlbmNpZXMubWFwKChkZXBlbmRlbmN5KSA9PiB7XG4gICAgICAgICAgY29uc3QgcGF0aCA9IHJlcXVpcmUucmVzb2x2ZShgJHtkZXBlbmRlbmN5fS9wYWNrYWdlLmpzb25gKTtcbiAgICAgICAgICBjb25zdCByZXNvbHZlZCA9IHJlYWRSZWNvcmQocGF0aCk7XG4gICAgICAgICAgaWYgKHR5cGVvZiByZXNvbHZlZC52ZXJzaW9uICE9PSBcInN0cmluZ1wiIHx8ICFyZXNvbHZlZC52ZXJzaW9uKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYGRlcGVuZGVuY3kgaGFzIG5vIHZlcnNpb246ICR7cGF0aH1gKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIFtkZXBlbmRlbmN5LCByZXNvbHZlZC52ZXJzaW9uXTtcbiAgICAgICAgfSksXG4gICAgICApO1xuICAgIH0sXG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVCaW4oZGlyZWN0b3J5OiBzdHJpbmcsIHZhbHVlOiB1bmtub3duLCBuYW1lPzogc3RyaW5nKTogc3RyaW5nIHtcbiAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gXCJzdHJpbmdcIikge1xuICAgIGlmIChuYW1lKSB0aHJvdyBuZXcgRXJyb3IoYHBhY2thZ2UgZXhwb3NlcyBvbmUgdW5uYW1lZCBiaW4sIG5vdCAke25hbWV9YCk7XG4gICAgcmV0dXJuIHJlc29sdmUoZGlyZWN0b3J5LCB2YWx1ZSk7XG4gIH1cbiAgaWYgKCFpc1JlY29yZCh2YWx1ZSkpIHRocm93IG5ldyBFcnJvcihcInBhY2thZ2UgaGFzIG5vIGJpblwiKTtcbiAgaWYgKG5hbWUpIHtcbiAgICBjb25zdCB0YXJnZXQgPSB2YWx1ZVtuYW1lXTtcbiAgICBpZiAodHlwZW9mIHRhcmdldCAhPT0gXCJzdHJpbmdcIikgdGhyb3cgbmV3IEVycm9yKGBwYWNrYWdlIGhhcyBubyBiaW4gbmFtZWQgJHtuYW1lfWApO1xuICAgIHJldHVybiByZXNvbHZlKGRpcmVjdG9yeSwgdGFyZ2V0KTtcbiAgfVxuICBjb25zdCB0YXJnZXRzID0gT2JqZWN0LnZhbHVlcyh2YWx1ZSkuZmlsdGVyKFxuICAgICh0YXJnZXQpOiB0YXJnZXQgaXMgc3RyaW5nID0+IHR5cGVvZiB0YXJnZXQgPT09IFwic3RyaW5nXCIsXG4gICk7XG4gIGlmICh0YXJnZXRzLmxlbmd0aCAhPT0gMSkge1xuICAgIHRocm93IG5ldyBFcnJvcihcInBhY2thZ2UgaGFzIG11bHRpcGxlIGJpbnM7IGNvbW1hbmQuYmluTmFtZSBpcyByZXF1aXJlZFwiKTtcbiAgfVxuICByZXR1cm4gcmVzb2x2ZShkaXJlY3RvcnksIHRhcmdldHNbMF0hKTtcbn1cblxuZnVuY3Rpb24gcmVhZFJlY29yZChwYXRoOiBzdHJpbmcpOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiB7XG4gIGNvbnN0IHZhbHVlOiB1bmtub3duID0gSlNPTi5wYXJzZShyZWFkRmlsZVN5bmMocGF0aCwgXCJ1dGY4XCIpKTtcbiAgaWYgKCFpc1JlY29yZCh2YWx1ZSkpIHRocm93IG5ldyBFcnJvcihgcGFja2FnZSBtYW5pZmVzdCBpcyBub3QgYW4gb2JqZWN0OiAke3BhdGh9YCk7XG4gIHJldHVybiB2YWx1ZTtcbn1cblxuZnVuY3Rpb24gaXNSZWNvcmQodmFsdWU6IHVua25vd24pOiB2YWx1ZSBpcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiB7XG4gIHJldHVybiB2YWx1ZSAhPT0gbnVsbCAmJiB0eXBlb2YgdmFsdWUgPT09IFwib2JqZWN0XCIgJiYgIUFycmF5LmlzQXJyYXkodmFsdWUpO1xufVxuIl19
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { CliServiceDefinition } from "./definition.ts";
|
|
2
|
+
export interface ServiceRuntimeContext {
|
|
3
|
+
readonly platform: NodeJS.Platform;
|
|
4
|
+
readonly environment: Readonly<NodeJS.ProcessEnv>;
|
|
5
|
+
readonly homeDirectory: string;
|
|
6
|
+
readonly temporaryDirectory: string;
|
|
7
|
+
}
|
|
8
|
+
export interface ServicePaths {
|
|
9
|
+
readonly directory: string;
|
|
10
|
+
readonly configFile: string;
|
|
11
|
+
readonly hostLog: string;
|
|
12
|
+
readonly processLog: string;
|
|
13
|
+
readonly controlAddress: string;
|
|
14
|
+
readonly startupFile: string;
|
|
15
|
+
}
|
|
16
|
+
export declare function defaultRuntimeContext(): ServiceRuntimeContext;
|
|
17
|
+
export declare function resolveServicePaths(definition: CliServiceDefinition, runtime: ServiceRuntimeContext): ServicePaths;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { homedir, tmpdir } from "node:os";
|
|
3
|
+
import { isAbsolute, join, resolve } from "node:path";
|
|
4
|
+
export function defaultRuntimeContext() {
|
|
5
|
+
return {
|
|
6
|
+
platform: process.platform,
|
|
7
|
+
environment: process.env,
|
|
8
|
+
homeDirectory: homedir(),
|
|
9
|
+
temporaryDirectory: tmpdir(),
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
export function resolveServicePaths(definition, runtime) {
|
|
13
|
+
const directory = definition.dataDirectory
|
|
14
|
+
? resolve(definition.dataDirectory)
|
|
15
|
+
: join(configurationRoot(runtime), definition.id);
|
|
16
|
+
return {
|
|
17
|
+
directory,
|
|
18
|
+
configFile: join(directory, "service.json"),
|
|
19
|
+
hostLog: join(directory, "host.log"),
|
|
20
|
+
processLog: join(directory, "service.log"),
|
|
21
|
+
controlAddress: controlAddress(definition.id, runtime),
|
|
22
|
+
startupFile: startupFile(definition.id, runtime),
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
function configurationRoot(runtime) {
|
|
26
|
+
if (runtime.platform === "darwin") {
|
|
27
|
+
return join(runtime.homeDirectory, "Library", "Application Support");
|
|
28
|
+
}
|
|
29
|
+
if (runtime.platform === "win32") {
|
|
30
|
+
return resolveEnvironmentPath(runtime.environment.APPDATA, join(runtime.homeDirectory, "AppData", "Roaming"));
|
|
31
|
+
}
|
|
32
|
+
return resolveEnvironmentPath(runtime.environment.XDG_CONFIG_HOME, join(runtime.homeDirectory, ".config"));
|
|
33
|
+
}
|
|
34
|
+
function controlAddress(id, runtime) {
|
|
35
|
+
const token = createHash("sha256").update(id).digest("hex").slice(0, 16);
|
|
36
|
+
if (runtime.platform === "win32") {
|
|
37
|
+
return `\\\\.\\pipe\\dbx-tools-cli-service-${token}`;
|
|
38
|
+
}
|
|
39
|
+
return join(runtime.temporaryDirectory, `dbx-tools-cli-service-${token}.sock`);
|
|
40
|
+
}
|
|
41
|
+
function startupFile(id, runtime) {
|
|
42
|
+
if (runtime.platform === "darwin") {
|
|
43
|
+
return join(runtime.homeDirectory, "Library", "LaunchAgents", `${id}.plist`);
|
|
44
|
+
}
|
|
45
|
+
if (runtime.platform === "win32") {
|
|
46
|
+
return join(resolveEnvironmentPath(runtime.environment.APPDATA, join(runtime.homeDirectory, "AppData", "Roaming")), "Microsoft", "Windows", "Start Menu", "Programs", "Startup", `${id}.cmd`);
|
|
47
|
+
}
|
|
48
|
+
return join(resolveEnvironmentPath(runtime.environment.XDG_CONFIG_HOME, join(runtime.homeDirectory, ".config")), "autostart", `${id}.desktop`);
|
|
49
|
+
}
|
|
50
|
+
function resolveEnvironmentPath(value, fallback) {
|
|
51
|
+
if (!value)
|
|
52
|
+
return fallback;
|
|
53
|
+
return isAbsolute(value) ? value : resolve(value);
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiX3BhdGhzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL19wYXRocy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sYUFBYSxDQUFDO0FBQ3pDLE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFBTSxFQUFFLE1BQU0sU0FBUyxDQUFDO0FBQzFDLE9BQU8sRUFBRSxVQUFVLEVBQUUsSUFBSSxFQUFFLE9BQU8sRUFBRSxNQUFNLFdBQVcsQ0FBQztBQW9CdEQsTUFBTSxVQUFVLHFCQUFxQjtJQUNuQyxPQUFPO1FBQ0wsUUFBUSxFQUFFLE9BQU8sQ0FBQyxRQUFRO1FBQzFCLFdBQVcsRUFBRSxPQUFPLENBQUMsR0FBRztRQUN4QixhQUFhLEVBQUUsT0FBTyxFQUFFO1FBQ3hCLGtCQUFrQixFQUFFLE1BQU0sRUFBRTtLQUM3QixDQUFDO0FBQ0osQ0FBQztBQUVELE1BQU0sVUFBVSxtQkFBbUIsQ0FDakMsVUFBZ0MsRUFDaEMsT0FBOEI7SUFFOUIsTUFBTSxTQUFTLEdBQUcsVUFBVSxDQUFDLGFBQWE7UUFDeEMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxVQUFVLENBQUMsYUFBYSxDQUFDO1FBQ25DLENBQUMsQ0FBQyxJQUFJLENBQUMsaUJBQWlCLENBQUMsT0FBTyxDQUFDLEVBQUUsVUFBVSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQ3BELE9BQU87UUFDTCxTQUFTO1FBQ1QsVUFBVSxFQUFFLElBQUksQ0FBQyxTQUFTLEVBQUUsY0FBYyxDQUFDO1FBQzNDLE9BQU8sRUFBRSxJQUFJLENBQUMsU0FBUyxFQUFFLFVBQVUsQ0FBQztRQUNwQyxVQUFVLEVBQUUsSUFBSSxDQUFDLFNBQVMsRUFBRSxhQUFhLENBQUM7UUFDMUMsY0FBYyxFQUFFLGNBQWMsQ0FBQyxVQUFVLENBQUMsRUFBRSxFQUFFLE9BQU8sQ0FBQztRQUN0RCxXQUFXLEVBQUUsV0FBVyxDQUFDLFVBQVUsQ0FBQyxFQUFFLEVBQUUsT0FBTyxDQUFDO0tBQ2pELENBQUM7QUFDSixDQUFDO0FBRUQsU0FBUyxpQkFBaUIsQ0FBQyxPQUE4QjtJQUN2RCxJQUFJLE9BQU8sQ0FBQyxRQUFRLEtBQUssUUFBUSxFQUFFLENBQUM7UUFDbEMsT0FBTyxJQUFJLENBQUMsT0FBTyxDQUFDLGFBQWEsRUFBRSxTQUFTLEVBQUUscUJBQXFCLENBQUMsQ0FBQztJQUN2RSxDQUFDO0lBQ0QsSUFBSSxPQUFPLENBQUMsUUFBUSxLQUFLLE9BQU8sRUFBRSxDQUFDO1FBQ2pDLE9BQU8sc0JBQXNCLENBQzNCLE9BQU8sQ0FBQyxXQUFXLENBQUMsT0FBTyxFQUMzQixJQUFJLENBQUMsT0FBTyxDQUFDLGFBQWEsRUFBRSxTQUFTLEVBQUUsU0FBUyxDQUFDLENBQ2xELENBQUM7SUFDSixDQUFDO0lBQ0QsT0FBTyxzQkFBc0IsQ0FDM0IsT0FBTyxDQUFDLFdBQVcsQ0FBQyxlQUFlLEVBQ25DLElBQUksQ0FBQyxPQUFPLENBQUMsYUFBYSxFQUFFLFNBQVMsQ0FBQyxDQUN2QyxDQUFDO0FBQ0osQ0FBQztBQUVELFNBQVMsY0FBYyxDQUFDLEVBQVUsRUFBRSxPQUE4QjtJQUNoRSxNQUFNLEtBQUssR0FBRyxVQUFVLENBQUMsUUFBUSxDQUFDLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDO0lBQ3pFLElBQUksT0FBTyxDQUFDLFFBQVEsS0FBSyxPQUFPLEVBQUUsQ0FBQztRQUNqQyxPQUFPLHNDQUFzQyxLQUFLLEVBQUUsQ0FBQztJQUN2RCxDQUFDO0lBQ0QsT0FBTyxJQUFJLENBQUMsT0FBTyxDQUFDLGtCQUFrQixFQUFFLHlCQUF5QixLQUFLLE9BQU8sQ0FBQyxDQUFDO0FBQ2pGLENBQUM7QUFFRCxTQUFTLFdBQVcsQ0FBQyxFQUFVLEVBQUUsT0FBOEI7SUFDN0QsSUFBSSxPQUFPLENBQUMsUUFBUSxLQUFLLFFBQVEsRUFBRSxDQUFDO1FBQ2xDLE9BQU8sSUFBSSxDQUFDLE9BQU8sQ0FBQyxhQUFhLEVBQUUsU0FBUyxFQUFFLGNBQWMsRUFBRSxHQUFHLEVBQUUsUUFBUSxDQUFDLENBQUM7SUFDL0UsQ0FBQztJQUNELElBQUksT0FBTyxDQUFDLFFBQVEsS0FBSyxPQUFPLEVBQUUsQ0FBQztRQUNqQyxPQUFPLElBQUksQ0FDVCxzQkFBc0IsQ0FDcEIsT0FBTyxDQUFDLFdBQVcsQ0FBQyxPQUFPLEVBQzNCLElBQUksQ0FBQyxPQUFPLENBQUMsYUFBYSxFQUFFLFNBQVMsRUFBRSxTQUFTLENBQUMsQ0FDbEQsRUFDRCxXQUFXLEVBQ1gsU0FBUyxFQUNULFlBQVksRUFDWixVQUFVLEVBQ1YsU0FBUyxFQUNULEdBQUcsRUFBRSxNQUFNLENBQ1osQ0FBQztJQUNKLENBQUM7SUFDRCxPQUFPLElBQUksQ0FDVCxzQkFBc0IsQ0FDcEIsT0FBTyxDQUFDLFdBQVcsQ0FBQyxlQUFlLEVBQ25DLElBQUksQ0FBQyxPQUFPLENBQUMsYUFBYSxFQUFFLFNBQVMsQ0FBQyxDQUN2QyxFQUNELFdBQVcsRUFDWCxHQUFHLEVBQUUsVUFBVSxDQUNoQixDQUFDO0FBQ0osQ0FBQztBQUVELFNBQVMsc0JBQXNCLENBQUMsS0FBeUIsRUFBRSxRQUFnQjtJQUN6RSxJQUFJLENBQUMsS0FBSztRQUFFLE9BQU8sUUFBUSxDQUFDO0lBQzVCLE9BQU8sVUFBVSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQztBQUNwRCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgY3JlYXRlSGFzaCB9IGZyb20gXCJub2RlOmNyeXB0b1wiO1xuaW1wb3J0IHsgaG9tZWRpciwgdG1wZGlyIH0gZnJvbSBcIm5vZGU6b3NcIjtcbmltcG9ydCB7IGlzQWJzb2x1dGUsIGpvaW4sIHJlc29sdmUgfSBmcm9tIFwibm9kZTpwYXRoXCI7XG5cbmltcG9ydCB0eXBlIHsgQ2xpU2VydmljZURlZmluaXRpb24gfSBmcm9tIFwiLi9kZWZpbml0aW9uLnRzXCI7XG5cbmV4cG9ydCBpbnRlcmZhY2UgU2VydmljZVJ1bnRpbWVDb250ZXh0IHtcbiAgcmVhZG9ubHkgcGxhdGZvcm06IE5vZGVKUy5QbGF0Zm9ybTtcbiAgcmVhZG9ubHkgZW52aXJvbm1lbnQ6IFJlYWRvbmx5PE5vZGVKUy5Qcm9jZXNzRW52PjtcbiAgcmVhZG9ubHkgaG9tZURpcmVjdG9yeTogc3RyaW5nO1xuICByZWFkb25seSB0ZW1wb3JhcnlEaXJlY3Rvcnk6IHN0cmluZztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBTZXJ2aWNlUGF0aHMge1xuICByZWFkb25seSBkaXJlY3Rvcnk6IHN0cmluZztcbiAgcmVhZG9ubHkgY29uZmlnRmlsZTogc3RyaW5nO1xuICByZWFkb25seSBob3N0TG9nOiBzdHJpbmc7XG4gIHJlYWRvbmx5IHByb2Nlc3NMb2c6IHN0cmluZztcbiAgcmVhZG9ubHkgY29udHJvbEFkZHJlc3M6IHN0cmluZztcbiAgcmVhZG9ubHkgc3RhcnR1cEZpbGU6IHN0cmluZztcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGRlZmF1bHRSdW50aW1lQ29udGV4dCgpOiBTZXJ2aWNlUnVudGltZUNvbnRleHQge1xuICByZXR1cm4ge1xuICAgIHBsYXRmb3JtOiBwcm9jZXNzLnBsYXRmb3JtLFxuICAgIGVudmlyb25tZW50OiBwcm9jZXNzLmVudixcbiAgICBob21lRGlyZWN0b3J5OiBob21lZGlyKCksXG4gICAgdGVtcG9yYXJ5RGlyZWN0b3J5OiB0bXBkaXIoKSxcbiAgfTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHJlc29sdmVTZXJ2aWNlUGF0aHMoXG4gIGRlZmluaXRpb246IENsaVNlcnZpY2VEZWZpbml0aW9uLFxuICBydW50aW1lOiBTZXJ2aWNlUnVudGltZUNvbnRleHQsXG4pOiBTZXJ2aWNlUGF0aHMge1xuICBjb25zdCBkaXJlY3RvcnkgPSBkZWZpbml0aW9uLmRhdGFEaXJlY3RvcnlcbiAgICA/IHJlc29sdmUoZGVmaW5pdGlvbi5kYXRhRGlyZWN0b3J5KVxuICAgIDogam9pbihjb25maWd1cmF0aW9uUm9vdChydW50aW1lKSwgZGVmaW5pdGlvbi5pZCk7XG4gIHJldHVybiB7XG4gICAgZGlyZWN0b3J5LFxuICAgIGNvbmZpZ0ZpbGU6IGpvaW4oZGlyZWN0b3J5LCBcInNlcnZpY2UuanNvblwiKSxcbiAgICBob3N0TG9nOiBqb2luKGRpcmVjdG9yeSwgXCJob3N0LmxvZ1wiKSxcbiAgICBwcm9jZXNzTG9nOiBqb2luKGRpcmVjdG9yeSwgXCJzZXJ2aWNlLmxvZ1wiKSxcbiAgICBjb250cm9sQWRkcmVzczogY29udHJvbEFkZHJlc3MoZGVmaW5pdGlvbi5pZCwgcnVudGltZSksXG4gICAgc3RhcnR1cEZpbGU6IHN0YXJ0dXBGaWxlKGRlZmluaXRpb24uaWQsIHJ1bnRpbWUpLFxuICB9O1xufVxuXG5mdW5jdGlvbiBjb25maWd1cmF0aW9uUm9vdChydW50aW1lOiBTZXJ2aWNlUnVudGltZUNvbnRleHQpOiBzdHJpbmcge1xuICBpZiAocnVudGltZS5wbGF0Zm9ybSA9PT0gXCJkYXJ3aW5cIikge1xuICAgIHJldHVybiBqb2luKHJ1bnRpbWUuaG9tZURpcmVjdG9yeSwgXCJMaWJyYXJ5XCIsIFwiQXBwbGljYXRpb24gU3VwcG9ydFwiKTtcbiAgfVxuICBpZiAocnVudGltZS5wbGF0Zm9ybSA9PT0gXCJ3aW4zMlwiKSB7XG4gICAgcmV0dXJuIHJlc29sdmVFbnZpcm9ubWVudFBhdGgoXG4gICAgICBydW50aW1lLmVudmlyb25tZW50LkFQUERBVEEsXG4gICAgICBqb2luKHJ1bnRpbWUuaG9tZURpcmVjdG9yeSwgXCJBcHBEYXRhXCIsIFwiUm9hbWluZ1wiKSxcbiAgICApO1xuICB9XG4gIHJldHVybiByZXNvbHZlRW52aXJvbm1lbnRQYXRoKFxuICAgIHJ1bnRpbWUuZW52aXJvbm1lbnQuWERHX0NPTkZJR19IT01FLFxuICAgIGpvaW4ocnVudGltZS5ob21lRGlyZWN0b3J5LCBcIi5jb25maWdcIiksXG4gICk7XG59XG5cbmZ1bmN0aW9uIGNvbnRyb2xBZGRyZXNzKGlkOiBzdHJpbmcsIHJ1bnRpbWU6IFNlcnZpY2VSdW50aW1lQ29udGV4dCk6IHN0cmluZyB7XG4gIGNvbnN0IHRva2VuID0gY3JlYXRlSGFzaChcInNoYTI1NlwiKS51cGRhdGUoaWQpLmRpZ2VzdChcImhleFwiKS5zbGljZSgwLCAxNik7XG4gIGlmIChydW50aW1lLnBsYXRmb3JtID09PSBcIndpbjMyXCIpIHtcbiAgICByZXR1cm4gYFxcXFxcXFxcLlxcXFxwaXBlXFxcXGRieC10b29scy1jbGktc2VydmljZS0ke3Rva2VufWA7XG4gIH1cbiAgcmV0dXJuIGpvaW4ocnVudGltZS50ZW1wb3JhcnlEaXJlY3RvcnksIGBkYngtdG9vbHMtY2xpLXNlcnZpY2UtJHt0b2tlbn0uc29ja2ApO1xufVxuXG5mdW5jdGlvbiBzdGFydHVwRmlsZShpZDogc3RyaW5nLCBydW50aW1lOiBTZXJ2aWNlUnVudGltZUNvbnRleHQpOiBzdHJpbmcge1xuICBpZiAocnVudGltZS5wbGF0Zm9ybSA9PT0gXCJkYXJ3aW5cIikge1xuICAgIHJldHVybiBqb2luKHJ1bnRpbWUuaG9tZURpcmVjdG9yeSwgXCJMaWJyYXJ5XCIsIFwiTGF1bmNoQWdlbnRzXCIsIGAke2lkfS5wbGlzdGApO1xuICB9XG4gIGlmIChydW50aW1lLnBsYXRmb3JtID09PSBcIndpbjMyXCIpIHtcbiAgICByZXR1cm4gam9pbihcbiAgICAgIHJlc29sdmVFbnZpcm9ubWVudFBhdGgoXG4gICAgICAgIHJ1bnRpbWUuZW52aXJvbm1lbnQuQVBQREFUQSxcbiAgICAgICAgam9pbihydW50aW1lLmhvbWVEaXJlY3RvcnksIFwiQXBwRGF0YVwiLCBcIlJvYW1pbmdcIiksXG4gICAgICApLFxuICAgICAgXCJNaWNyb3NvZnRcIixcbiAgICAgIFwiV2luZG93c1wiLFxuICAgICAgXCJTdGFydCBNZW51XCIsXG4gICAgICBcIlByb2dyYW1zXCIsXG4gICAgICBcIlN0YXJ0dXBcIixcbiAgICAgIGAke2lkfS5jbWRgLFxuICAgICk7XG4gIH1cbiAgcmV0dXJuIGpvaW4oXG4gICAgcmVzb2x2ZUVudmlyb25tZW50UGF0aChcbiAgICAgIHJ1bnRpbWUuZW52aXJvbm1lbnQuWERHX0NPTkZJR19IT01FLFxuICAgICAgam9pbihydW50aW1lLmhvbWVEaXJlY3RvcnksIFwiLmNvbmZpZ1wiKSxcbiAgICApLFxuICAgIFwiYXV0b3N0YXJ0XCIsXG4gICAgYCR7aWR9LmRlc2t0b3BgLFxuICApO1xufVxuXG5mdW5jdGlvbiByZXNvbHZlRW52aXJvbm1lbnRQYXRoKHZhbHVlOiBzdHJpbmcgfCB1bmRlZmluZWQsIGZhbGxiYWNrOiBzdHJpbmcpOiBzdHJpbmcge1xuICBpZiAoIXZhbHVlKSByZXR1cm4gZmFsbGJhY2s7XG4gIHJldHVybiBpc0Fic29sdXRlKHZhbHVlKSA/IHZhbHVlIDogcmVzb2x2ZSh2YWx1ZSk7XG59XG4iXX0=
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import * as exec from "@dbx-tools/core/exec";
|
|
4
|
+
export function externalRuntimePackages(dependencies) {
|
|
5
|
+
return Object.keys(dependencies).filter((name) => !name.startsWith("@dbx-tools/"));
|
|
6
|
+
}
|
|
7
|
+
export async function installServiceRuntime(bunExecutable, directory, dependencies) {
|
|
8
|
+
await mkdir(directory, { recursive: true });
|
|
9
|
+
const manifestPath = join(directory, "package.json");
|
|
10
|
+
const current = await readOptionalRecord(manifestPath);
|
|
11
|
+
await writeFile(manifestPath, `${JSON.stringify({
|
|
12
|
+
...current,
|
|
13
|
+
name: "@dbx-tools/service-runtime",
|
|
14
|
+
private: true,
|
|
15
|
+
dependencies: {
|
|
16
|
+
...stringRecord(current.dependencies),
|
|
17
|
+
...dependencies,
|
|
18
|
+
},
|
|
19
|
+
}, null, 2)}\n`, "utf8");
|
|
20
|
+
await exec.spawn(bunExecutable, ["install", "--production", "--cwd", directory], {
|
|
21
|
+
check: true,
|
|
22
|
+
cwd: directory,
|
|
23
|
+
stdin: "ignore",
|
|
24
|
+
stdout: "capture",
|
|
25
|
+
stderr: "capture",
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
async function readOptionalRecord(path) {
|
|
29
|
+
try {
|
|
30
|
+
const value = JSON.parse(await readFile(path, "utf8"));
|
|
31
|
+
if (!isRecord(value))
|
|
32
|
+
throw new Error(`JSON file is not an object: ${path}`);
|
|
33
|
+
return value;
|
|
34
|
+
}
|
|
35
|
+
catch (error) {
|
|
36
|
+
if (error.code === "ENOENT")
|
|
37
|
+
return {};
|
|
38
|
+
throw error;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
function stringRecord(value) {
|
|
42
|
+
if (!isRecord(value))
|
|
43
|
+
return {};
|
|
44
|
+
return Object.fromEntries(Object.entries(value).filter((entry) => typeof entry[1] === "string"));
|
|
45
|
+
}
|
|
46
|
+
function isRecord(value) {
|
|
47
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiX3J1bnRpbWUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvX3J1bnRpbWUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLEtBQUssRUFBRSxRQUFRLEVBQUUsU0FBUyxFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFDOUQsT0FBTyxFQUFFLElBQUksRUFBRSxNQUFNLFdBQVcsQ0FBQztBQUVqQyxPQUFPLEtBQUssSUFBSSxNQUFNLHNCQUFzQixDQUFDO0FBRTdDLE1BQU0sVUFBVSx1QkFBdUIsQ0FBQyxZQUE4QztJQUNwRixPQUFPLE1BQU0sQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsYUFBYSxDQUFDLENBQUMsQ0FBQztBQUNyRixDQUFDO0FBRUQsTUFBTSxDQUFDLEtBQUssVUFBVSxxQkFBcUIsQ0FDekMsYUFBcUIsRUFDckIsU0FBaUIsRUFDakIsWUFBOEM7SUFFOUMsTUFBTSxLQUFLLENBQUMsU0FBUyxFQUFFLEVBQUUsU0FBUyxFQUFFLElBQUksRUFBRSxDQUFDLENBQUM7SUFDNUMsTUFBTSxZQUFZLEdBQUcsSUFBSSxDQUFDLFNBQVMsRUFBRSxjQUFjLENBQUMsQ0FBQztJQUNyRCxNQUFNLE9BQU8sR0FBRyxNQUFNLGtCQUFrQixDQUFDLFlBQVksQ0FBQyxDQUFDO0lBQ3ZELE1BQU0sU0FBUyxDQUNiLFlBQVksRUFDWixHQUFHLElBQUksQ0FBQyxTQUFTLENBQ2Y7UUFDRSxHQUFHLE9BQU87UUFDVixJQUFJLEVBQUUsNEJBQTRCO1FBQ2xDLE9BQU8sRUFBRSxJQUFJO1FBQ2IsWUFBWSxFQUFFO1lBQ1osR0FBRyxZQUFZLENBQUMsT0FBTyxDQUFDLFlBQVksQ0FBQztZQUNyQyxHQUFHLFlBQVk7U0FDaEI7S0FDRixFQUNELElBQUksRUFDSixDQUFDLENBQ0YsSUFBSSxFQUNMLE1BQU0sQ0FDUCxDQUFDO0lBQ0YsTUFBTSxJQUFJLENBQUMsS0FBSyxDQUFDLGFBQWEsRUFBRSxDQUFDLFNBQVMsRUFBRSxjQUFjLEVBQUUsT0FBTyxFQUFFLFNBQVMsQ0FBQyxFQUFFO1FBQy9FLEtBQUssRUFBRSxJQUFJO1FBQ1gsR0FBRyxFQUFFLFNBQVM7UUFDZCxLQUFLLEVBQUUsUUFBUTtRQUNmLE1BQU0sRUFBRSxTQUFTO1FBQ2pCLE1BQU0sRUFBRSxTQUFTO0tBQ2xCLENBQUMsQ0FBQztBQUNMLENBQUM7QUFFRCxLQUFLLFVBQVUsa0JBQWtCLENBQUMsSUFBWTtJQUM1QyxJQUFJLENBQUM7UUFDSCxNQUFNLEtBQUssR0FBWSxJQUFJLENBQUMsS0FBSyxDQUFDLE1BQU0sUUFBUSxDQUFDLElBQUksRUFBRSxNQUFNLENBQUMsQ0FBQyxDQUFDO1FBQ2hFLElBQUksQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDO1lBQUUsTUFBTSxJQUFJLEtBQUssQ0FBQywrQkFBK0IsSUFBSSxFQUFFLENBQUMsQ0FBQztRQUM3RSxPQUFPLEtBQUssQ0FBQztJQUNmLENBQUM7SUFBQyxPQUFPLEtBQUssRUFBRSxDQUFDO1FBQ2YsSUFBSyxLQUErQixDQUFDLElBQUksS0FBSyxRQUFRO1lBQUUsT0FBTyxFQUFFLENBQUM7UUFDbEUsTUFBTSxLQUFLLENBQUM7SUFDZCxDQUFDO0FBQ0gsQ0FBQztBQUVELFNBQVMsWUFBWSxDQUFDLEtBQWM7SUFDbEMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUM7UUFBRSxPQUFPLEVBQUUsQ0FBQztJQUNoQyxPQUFPLE1BQU0sQ0FBQyxXQUFXLENBQ3ZCLE1BQU0sQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLENBQUMsTUFBTSxDQUMxQixDQUFDLEtBQUssRUFBNkIsRUFBRSxDQUFDLE9BQU8sS0FBSyxDQUFDLENBQUMsQ0FBQyxLQUFLLFFBQVEsQ0FDbkUsQ0FDRixDQUFDO0FBQ0osQ0FBQztBQUVELFNBQVMsUUFBUSxDQUFDLEtBQWM7SUFDOUIsT0FBTyxLQUFLLEtBQUssSUFBSSxJQUFJLE9BQU8sS0FBSyxLQUFLLFFBQVEsSUFBSSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLENBQUM7QUFDOUUsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IG1rZGlyLCByZWFkRmlsZSwgd3JpdGVGaWxlIH0gZnJvbSBcIm5vZGU6ZnMvcHJvbWlzZXNcIjtcbmltcG9ydCB7IGpvaW4gfSBmcm9tIFwibm9kZTpwYXRoXCI7XG5cbmltcG9ydCAqIGFzIGV4ZWMgZnJvbSBcIkBkYngtdG9vbHMvY29yZS9leGVjXCI7XG5cbmV4cG9ydCBmdW5jdGlvbiBleHRlcm5hbFJ1bnRpbWVQYWNrYWdlcyhkZXBlbmRlbmNpZXM6IFJlYWRvbmx5PFJlY29yZDxzdHJpbmcsIHN0cmluZz4+KTogc3RyaW5nW10ge1xuICByZXR1cm4gT2JqZWN0LmtleXMoZGVwZW5kZW5jaWVzKS5maWx0ZXIoKG5hbWUpID0+ICFuYW1lLnN0YXJ0c1dpdGgoXCJAZGJ4LXRvb2xzL1wiKSk7XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBpbnN0YWxsU2VydmljZVJ1bnRpbWUoXG4gIGJ1bkV4ZWN1dGFibGU6IHN0cmluZyxcbiAgZGlyZWN0b3J5OiBzdHJpbmcsXG4gIGRlcGVuZGVuY2llczogUmVhZG9ubHk8UmVjb3JkPHN0cmluZywgc3RyaW5nPj4sXG4pOiBQcm9taXNlPHZvaWQ+IHtcbiAgYXdhaXQgbWtkaXIoZGlyZWN0b3J5LCB7IHJlY3Vyc2l2ZTogdHJ1ZSB9KTtcbiAgY29uc3QgbWFuaWZlc3RQYXRoID0gam9pbihkaXJlY3RvcnksIFwicGFja2FnZS5qc29uXCIpO1xuICBjb25zdCBjdXJyZW50ID0gYXdhaXQgcmVhZE9wdGlvbmFsUmVjb3JkKG1hbmlmZXN0UGF0aCk7XG4gIGF3YWl0IHdyaXRlRmlsZShcbiAgICBtYW5pZmVzdFBhdGgsXG4gICAgYCR7SlNPTi5zdHJpbmdpZnkoXG4gICAgICB7XG4gICAgICAgIC4uLmN1cnJlbnQsXG4gICAgICAgIG5hbWU6IFwiQGRieC10b29scy9zZXJ2aWNlLXJ1bnRpbWVcIixcbiAgICAgICAgcHJpdmF0ZTogdHJ1ZSxcbiAgICAgICAgZGVwZW5kZW5jaWVzOiB7XG4gICAgICAgICAgLi4uc3RyaW5nUmVjb3JkKGN1cnJlbnQuZGVwZW5kZW5jaWVzKSxcbiAgICAgICAgICAuLi5kZXBlbmRlbmNpZXMsXG4gICAgICAgIH0sXG4gICAgICB9LFxuICAgICAgbnVsbCxcbiAgICAgIDIsXG4gICAgKX1cXG5gLFxuICAgIFwidXRmOFwiLFxuICApO1xuICBhd2FpdCBleGVjLnNwYXduKGJ1bkV4ZWN1dGFibGUsIFtcImluc3RhbGxcIiwgXCItLXByb2R1Y3Rpb25cIiwgXCItLWN3ZFwiLCBkaXJlY3RvcnldLCB7XG4gICAgY2hlY2s6IHRydWUsXG4gICAgY3dkOiBkaXJlY3RvcnksXG4gICAgc3RkaW46IFwiaWdub3JlXCIsXG4gICAgc3Rkb3V0OiBcImNhcHR1cmVcIixcbiAgICBzdGRlcnI6IFwiY2FwdHVyZVwiLFxuICB9KTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gcmVhZE9wdGlvbmFsUmVjb3JkKHBhdGg6IHN0cmluZyk6IFByb21pc2U8UmVjb3JkPHN0cmluZywgdW5rbm93bj4+IHtcbiAgdHJ5IHtcbiAgICBjb25zdCB2YWx1ZTogdW5rbm93biA9IEpTT04ucGFyc2UoYXdhaXQgcmVhZEZpbGUocGF0aCwgXCJ1dGY4XCIpKTtcbiAgICBpZiAoIWlzUmVjb3JkKHZhbHVlKSkgdGhyb3cgbmV3IEVycm9yKGBKU09OIGZpbGUgaXMgbm90IGFuIG9iamVjdDogJHtwYXRofWApO1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICBpZiAoKGVycm9yIGFzIE5vZGVKUy5FcnJub0V4Y2VwdGlvbikuY29kZSA9PT0gXCJFTk9FTlRcIikgcmV0dXJuIHt9O1xuICAgIHRocm93IGVycm9yO1xuICB9XG59XG5cbmZ1bmN0aW9uIHN0cmluZ1JlY29yZCh2YWx1ZTogdW5rbm93bik6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4ge1xuICBpZiAoIWlzUmVjb3JkKHZhbHVlKSkgcmV0dXJuIHt9O1xuICByZXR1cm4gT2JqZWN0LmZyb21FbnRyaWVzKFxuICAgIE9iamVjdC5lbnRyaWVzKHZhbHVlKS5maWx0ZXIoXG4gICAgICAoZW50cnkpOiBlbnRyeSBpcyBbc3RyaW5nLCBzdHJpbmddID0+IHR5cGVvZiBlbnRyeVsxXSA9PT0gXCJzdHJpbmdcIixcbiAgICApLFxuICApO1xufVxuXG5mdW5jdGlvbiBpc1JlY29yZCh2YWx1ZTogdW5rbm93bik6IHZhbHVlIGlzIFJlY29yZDxzdHJpbmcsIHVua25vd24+IHtcbiAgcmV0dXJuIHZhbHVlICE9PSBudWxsICYmIHR5cGVvZiB2YWx1ZSA9PT0gXCJvYmplY3RcIiAmJiAhQXJyYXkuaXNBcnJheSh2YWx1ZSk7XG59XG4iXX0=
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ServicePaths, ServiceRuntimeContext } from "./_paths.ts";
|
|
2
|
+
import type { CliServiceDefinition } from "./definition.ts";
|
|
3
|
+
export interface ServiceLaunch {
|
|
4
|
+
readonly executable: string;
|
|
5
|
+
readonly arguments: readonly string[];
|
|
6
|
+
}
|
|
7
|
+
export declare function installStartup(definition: CliServiceDefinition, paths: ServicePaths, runtime: ServiceRuntimeContext, launch: ServiceLaunch): Promise<void>;
|
|
8
|
+
export declare function removeStartup(paths: ServicePaths): Promise<void>;
|
|
9
|
+
export declare function renderLaunchAgent(definition: CliServiceDefinition, launch: ServiceLaunch): string;
|
|
10
|
+
export declare function renderDesktopEntry(definition: CliServiceDefinition, launch: ServiceLaunch): string;
|
|
11
|
+
export declare function renderWindowsStartup(launch: ServiceLaunch): string;
|