@specific.dev/cli 0.1.42 → 0.1.43
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/admin/404/index.html +1 -1
- package/dist/admin/404.html +1 -1
- package/dist/admin/__next.__PAGE__.txt +2 -2
- package/dist/admin/__next._full.txt +3 -3
- package/dist/admin/__next._head.txt +1 -1
- package/dist/admin/__next._index.txt +2 -2
- package/dist/admin/__next._tree.txt +2 -2
- package/dist/admin/_next/static/chunks/1da818a0086b4acf.css +3 -0
- package/dist/admin/_next/static/chunks/cba5c081fc9dc612.js +2 -0
- package/dist/admin/_not-found/__next._full.txt +2 -2
- package/dist/admin/_not-found/__next._head.txt +1 -1
- package/dist/admin/_not-found/__next._index.txt +2 -2
- package/dist/admin/_not-found/__next._not-found.__PAGE__.txt +1 -1
- package/dist/admin/_not-found/__next._not-found.txt +1 -1
- package/dist/admin/_not-found/__next._tree.txt +2 -2
- package/dist/admin/_not-found/index.html +1 -1
- package/dist/admin/_not-found/index.txt +2 -2
- package/dist/admin/databases/__next._full.txt +2 -2
- package/dist/admin/databases/__next._head.txt +1 -1
- package/dist/admin/databases/__next._index.txt +2 -2
- package/dist/admin/databases/__next._tree.txt +2 -2
- package/dist/admin/databases/__next.databases.__PAGE__.txt +1 -1
- package/dist/admin/databases/__next.databases.txt +1 -1
- package/dist/admin/databases/index.html +1 -1
- package/dist/admin/databases/index.txt +2 -2
- package/dist/admin/index.html +1 -1
- package/dist/admin/index.txt +3 -3
- package/dist/cli.js +1391 -1038
- package/dist/docs/index.md +1 -0
- package/dist/docs/integrations/temporal.md +89 -0
- package/dist/docs/services.md +4 -2
- package/package.json +1 -1
- package/dist/admin/_next/static/chunks/237926899f121e8a.js +0 -2
- package/dist/admin/_next/static/chunks/2ca8ab35893ba132.css +0 -3
- /package/dist/admin/_next/static/{w-7TGbUFVs5LhUxmBNTTr → 3dGrdrrH7RVk5ixe6lgRQ}/_buildManifest.js +0 -0
- /package/dist/admin/_next/static/{w-7TGbUFVs5LhUxmBNTTr → 3dGrdrrH7RVk5ixe6lgRQ}/_clientMiddlewareManifest.json +0 -0
- /package/dist/admin/_next/static/{w-7TGbUFVs5LhUxmBNTTr → 3dGrdrrH7RVk5ixe6lgRQ}/_ssgManifest.js +0 -0
package/dist/cli.js
CHANGED
|
@@ -11,9 +11,16 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
|
|
|
11
11
|
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
12
12
|
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
13
13
|
});
|
|
14
|
+
var __esm = (fn, res) => function __init() {
|
|
15
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
16
|
+
};
|
|
14
17
|
var __commonJS = (cb, mod) => function __require2() {
|
|
15
18
|
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
16
19
|
};
|
|
20
|
+
var __export = (target, all) => {
|
|
21
|
+
for (var name in all)
|
|
22
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
23
|
+
};
|
|
17
24
|
var __copyProps = (to, from, except, desc) => {
|
|
18
25
|
if (from && typeof from === "object" || typeof from === "function") {
|
|
19
26
|
for (let key of __getOwnPropNames(from))
|
|
@@ -31,6 +38,712 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
31
38
|
mod
|
|
32
39
|
));
|
|
33
40
|
|
|
41
|
+
// ../../node_modules/is-docker/index.js
|
|
42
|
+
import fs4 from "node:fs";
|
|
43
|
+
function hasDockerEnv() {
|
|
44
|
+
try {
|
|
45
|
+
fs4.statSync("/.dockerenv");
|
|
46
|
+
return true;
|
|
47
|
+
} catch {
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
function hasDockerCGroup() {
|
|
52
|
+
try {
|
|
53
|
+
return fs4.readFileSync("/proc/self/cgroup", "utf8").includes("docker");
|
|
54
|
+
} catch {
|
|
55
|
+
return false;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
function isDocker() {
|
|
59
|
+
if (isDockerCached === void 0) {
|
|
60
|
+
isDockerCached = hasDockerEnv() || hasDockerCGroup();
|
|
61
|
+
}
|
|
62
|
+
return isDockerCached;
|
|
63
|
+
}
|
|
64
|
+
var isDockerCached;
|
|
65
|
+
var init_is_docker = __esm({
|
|
66
|
+
"../../node_modules/is-docker/index.js"() {
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
// ../../node_modules/is-inside-container/index.js
|
|
71
|
+
import fs5 from "node:fs";
|
|
72
|
+
function isInsideContainer() {
|
|
73
|
+
if (cachedResult === void 0) {
|
|
74
|
+
cachedResult = hasContainerEnv() || isDocker();
|
|
75
|
+
}
|
|
76
|
+
return cachedResult;
|
|
77
|
+
}
|
|
78
|
+
var cachedResult, hasContainerEnv;
|
|
79
|
+
var init_is_inside_container = __esm({
|
|
80
|
+
"../../node_modules/is-inside-container/index.js"() {
|
|
81
|
+
init_is_docker();
|
|
82
|
+
hasContainerEnv = () => {
|
|
83
|
+
try {
|
|
84
|
+
fs5.statSync("/run/.containerenv");
|
|
85
|
+
return true;
|
|
86
|
+
} catch {
|
|
87
|
+
return false;
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
// ../../node_modules/is-wsl/index.js
|
|
94
|
+
import process2 from "node:process";
|
|
95
|
+
import os3 from "node:os";
|
|
96
|
+
import fs6 from "node:fs";
|
|
97
|
+
var isWsl, is_wsl_default;
|
|
98
|
+
var init_is_wsl = __esm({
|
|
99
|
+
"../../node_modules/is-wsl/index.js"() {
|
|
100
|
+
init_is_inside_container();
|
|
101
|
+
isWsl = () => {
|
|
102
|
+
if (process2.platform !== "linux") {
|
|
103
|
+
return false;
|
|
104
|
+
}
|
|
105
|
+
if (os3.release().toLowerCase().includes("microsoft")) {
|
|
106
|
+
if (isInsideContainer()) {
|
|
107
|
+
return false;
|
|
108
|
+
}
|
|
109
|
+
return true;
|
|
110
|
+
}
|
|
111
|
+
try {
|
|
112
|
+
return fs6.readFileSync("/proc/version", "utf8").toLowerCase().includes("microsoft") ? !isInsideContainer() : false;
|
|
113
|
+
} catch {
|
|
114
|
+
return false;
|
|
115
|
+
}
|
|
116
|
+
};
|
|
117
|
+
is_wsl_default = process2.env.__IS_WSL_TEST__ ? isWsl : isWsl();
|
|
118
|
+
}
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
// ../../node_modules/powershell-utils/index.js
|
|
122
|
+
import process3 from "node:process";
|
|
123
|
+
import { Buffer as Buffer2 } from "node:buffer";
|
|
124
|
+
import { promisify } from "node:util";
|
|
125
|
+
import childProcess from "node:child_process";
|
|
126
|
+
var execFile, powerShellPath, executePowerShell;
|
|
127
|
+
var init_powershell_utils = __esm({
|
|
128
|
+
"../../node_modules/powershell-utils/index.js"() {
|
|
129
|
+
execFile = promisify(childProcess.execFile);
|
|
130
|
+
powerShellPath = () => `${process3.env.SYSTEMROOT || process3.env.windir || String.raw`C:\Windows`}\\System32\\WindowsPowerShell\\v1.0\\powershell.exe`;
|
|
131
|
+
executePowerShell = async (command, options2 = {}) => {
|
|
132
|
+
const {
|
|
133
|
+
powerShellPath: psPath,
|
|
134
|
+
...execFileOptions
|
|
135
|
+
} = options2;
|
|
136
|
+
const encodedCommand = executePowerShell.encodeCommand(command);
|
|
137
|
+
return execFile(
|
|
138
|
+
psPath ?? powerShellPath(),
|
|
139
|
+
[
|
|
140
|
+
...executePowerShell.argumentsPrefix,
|
|
141
|
+
encodedCommand
|
|
142
|
+
],
|
|
143
|
+
{
|
|
144
|
+
encoding: "utf8",
|
|
145
|
+
...execFileOptions
|
|
146
|
+
}
|
|
147
|
+
);
|
|
148
|
+
};
|
|
149
|
+
executePowerShell.argumentsPrefix = [
|
|
150
|
+
"-NoProfile",
|
|
151
|
+
"-NonInteractive",
|
|
152
|
+
"-ExecutionPolicy",
|
|
153
|
+
"Bypass",
|
|
154
|
+
"-EncodedCommand"
|
|
155
|
+
];
|
|
156
|
+
executePowerShell.encodeCommand = (command) => Buffer2.from(command, "utf16le").toString("base64");
|
|
157
|
+
executePowerShell.escapeArgument = (value) => `'${String(value).replaceAll("'", "''")}'`;
|
|
158
|
+
}
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
// ../../node_modules/wsl-utils/utilities.js
|
|
162
|
+
function parseMountPointFromConfig(content) {
|
|
163
|
+
for (const line of content.split("\n")) {
|
|
164
|
+
if (/^\s*#/.test(line)) {
|
|
165
|
+
continue;
|
|
166
|
+
}
|
|
167
|
+
const match = /^\s*root\s*=\s*(?<mountPoint>"[^"]*"|'[^']*'|[^#]*)/.exec(line);
|
|
168
|
+
if (!match) {
|
|
169
|
+
continue;
|
|
170
|
+
}
|
|
171
|
+
return match.groups.mountPoint.trim().replaceAll(/^["']|["']$/g, "");
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
var init_utilities = __esm({
|
|
175
|
+
"../../node_modules/wsl-utils/utilities.js"() {
|
|
176
|
+
}
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
// ../../node_modules/wsl-utils/index.js
|
|
180
|
+
import { promisify as promisify2 } from "node:util";
|
|
181
|
+
import childProcess2 from "node:child_process";
|
|
182
|
+
import fs7, { constants as fsConstants } from "node:fs/promises";
|
|
183
|
+
var execFile2, wslDrivesMountPoint, powerShellPathFromWsl, powerShellPath2, canAccessPowerShellPromise, canAccessPowerShell, wslDefaultBrowser, convertWslPathToWindows;
|
|
184
|
+
var init_wsl_utils = __esm({
|
|
185
|
+
"../../node_modules/wsl-utils/index.js"() {
|
|
186
|
+
init_is_wsl();
|
|
187
|
+
init_powershell_utils();
|
|
188
|
+
init_utilities();
|
|
189
|
+
init_is_wsl();
|
|
190
|
+
execFile2 = promisify2(childProcess2.execFile);
|
|
191
|
+
wslDrivesMountPoint = /* @__PURE__ */ (() => {
|
|
192
|
+
const defaultMountPoint = "/mnt/";
|
|
193
|
+
let mountPoint;
|
|
194
|
+
return async function() {
|
|
195
|
+
if (mountPoint) {
|
|
196
|
+
return mountPoint;
|
|
197
|
+
}
|
|
198
|
+
const configFilePath = "/etc/wsl.conf";
|
|
199
|
+
let isConfigFileExists = false;
|
|
200
|
+
try {
|
|
201
|
+
await fs7.access(configFilePath, fsConstants.F_OK);
|
|
202
|
+
isConfigFileExists = true;
|
|
203
|
+
} catch {
|
|
204
|
+
}
|
|
205
|
+
if (!isConfigFileExists) {
|
|
206
|
+
return defaultMountPoint;
|
|
207
|
+
}
|
|
208
|
+
const configContent = await fs7.readFile(configFilePath, { encoding: "utf8" });
|
|
209
|
+
const parsedMountPoint = parseMountPointFromConfig(configContent);
|
|
210
|
+
if (parsedMountPoint === void 0) {
|
|
211
|
+
return defaultMountPoint;
|
|
212
|
+
}
|
|
213
|
+
mountPoint = parsedMountPoint;
|
|
214
|
+
mountPoint = mountPoint.endsWith("/") ? mountPoint : `${mountPoint}/`;
|
|
215
|
+
return mountPoint;
|
|
216
|
+
};
|
|
217
|
+
})();
|
|
218
|
+
powerShellPathFromWsl = async () => {
|
|
219
|
+
const mountPoint = await wslDrivesMountPoint();
|
|
220
|
+
return `${mountPoint}c/Windows/System32/WindowsPowerShell/v1.0/powershell.exe`;
|
|
221
|
+
};
|
|
222
|
+
powerShellPath2 = is_wsl_default ? powerShellPathFromWsl : powerShellPath;
|
|
223
|
+
canAccessPowerShell = async () => {
|
|
224
|
+
canAccessPowerShellPromise ??= (async () => {
|
|
225
|
+
try {
|
|
226
|
+
const psPath = await powerShellPath2();
|
|
227
|
+
await fs7.access(psPath, fsConstants.X_OK);
|
|
228
|
+
return true;
|
|
229
|
+
} catch {
|
|
230
|
+
return false;
|
|
231
|
+
}
|
|
232
|
+
})();
|
|
233
|
+
return canAccessPowerShellPromise;
|
|
234
|
+
};
|
|
235
|
+
wslDefaultBrowser = async () => {
|
|
236
|
+
const psPath = await powerShellPath2();
|
|
237
|
+
const command = String.raw`(Get-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\Shell\Associations\UrlAssociations\http\UserChoice").ProgId`;
|
|
238
|
+
const { stdout } = await executePowerShell(command, { powerShellPath: psPath });
|
|
239
|
+
return stdout.trim();
|
|
240
|
+
};
|
|
241
|
+
convertWslPathToWindows = async (path22) => {
|
|
242
|
+
if (/^[a-z]+:\/\//i.test(path22)) {
|
|
243
|
+
return path22;
|
|
244
|
+
}
|
|
245
|
+
try {
|
|
246
|
+
const { stdout } = await execFile2("wslpath", ["-aw", path22], { encoding: "utf8" });
|
|
247
|
+
return stdout.trim();
|
|
248
|
+
} catch {
|
|
249
|
+
return path22;
|
|
250
|
+
}
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
// ../../node_modules/define-lazy-prop/index.js
|
|
256
|
+
function defineLazyProperty(object, propertyName, valueGetter) {
|
|
257
|
+
const define = (value) => Object.defineProperty(object, propertyName, { value, enumerable: true, writable: true });
|
|
258
|
+
Object.defineProperty(object, propertyName, {
|
|
259
|
+
configurable: true,
|
|
260
|
+
enumerable: true,
|
|
261
|
+
get() {
|
|
262
|
+
const result = valueGetter();
|
|
263
|
+
define(result);
|
|
264
|
+
return result;
|
|
265
|
+
},
|
|
266
|
+
set(value) {
|
|
267
|
+
define(value);
|
|
268
|
+
}
|
|
269
|
+
});
|
|
270
|
+
return object;
|
|
271
|
+
}
|
|
272
|
+
var init_define_lazy_prop = __esm({
|
|
273
|
+
"../../node_modules/define-lazy-prop/index.js"() {
|
|
274
|
+
}
|
|
275
|
+
});
|
|
276
|
+
|
|
277
|
+
// ../../node_modules/default-browser-id/index.js
|
|
278
|
+
import { promisify as promisify3 } from "node:util";
|
|
279
|
+
import process4 from "node:process";
|
|
280
|
+
import { execFile as execFile3 } from "node:child_process";
|
|
281
|
+
async function defaultBrowserId() {
|
|
282
|
+
if (process4.platform !== "darwin") {
|
|
283
|
+
throw new Error("macOS only");
|
|
284
|
+
}
|
|
285
|
+
const { stdout } = await execFileAsync("defaults", ["read", "com.apple.LaunchServices/com.apple.launchservices.secure", "LSHandlers"]);
|
|
286
|
+
const match = /LSHandlerRoleAll = "(?!-)(?<id>[^"]+?)";\s+?LSHandlerURLScheme = (?:http|https);/.exec(stdout);
|
|
287
|
+
const browserId = match?.groups.id ?? "com.apple.Safari";
|
|
288
|
+
if (browserId === "com.apple.safari") {
|
|
289
|
+
return "com.apple.Safari";
|
|
290
|
+
}
|
|
291
|
+
return browserId;
|
|
292
|
+
}
|
|
293
|
+
var execFileAsync;
|
|
294
|
+
var init_default_browser_id = __esm({
|
|
295
|
+
"../../node_modules/default-browser-id/index.js"() {
|
|
296
|
+
execFileAsync = promisify3(execFile3);
|
|
297
|
+
}
|
|
298
|
+
});
|
|
299
|
+
|
|
300
|
+
// ../../node_modules/run-applescript/index.js
|
|
301
|
+
import process5 from "node:process";
|
|
302
|
+
import { promisify as promisify4 } from "node:util";
|
|
303
|
+
import { execFile as execFile4, execFileSync } from "node:child_process";
|
|
304
|
+
async function runAppleScript(script, { humanReadableOutput = true, signal } = {}) {
|
|
305
|
+
if (process5.platform !== "darwin") {
|
|
306
|
+
throw new Error("macOS only");
|
|
307
|
+
}
|
|
308
|
+
const outputArguments = humanReadableOutput ? [] : ["-ss"];
|
|
309
|
+
const execOptions = {};
|
|
310
|
+
if (signal) {
|
|
311
|
+
execOptions.signal = signal;
|
|
312
|
+
}
|
|
313
|
+
const { stdout } = await execFileAsync2("osascript", ["-e", script, outputArguments], execOptions);
|
|
314
|
+
return stdout.trim();
|
|
315
|
+
}
|
|
316
|
+
var execFileAsync2;
|
|
317
|
+
var init_run_applescript = __esm({
|
|
318
|
+
"../../node_modules/run-applescript/index.js"() {
|
|
319
|
+
execFileAsync2 = promisify4(execFile4);
|
|
320
|
+
}
|
|
321
|
+
});
|
|
322
|
+
|
|
323
|
+
// ../../node_modules/bundle-name/index.js
|
|
324
|
+
async function bundleName(bundleId) {
|
|
325
|
+
return runAppleScript(`tell application "Finder" to set app_path to application file id "${bundleId}" as string
|
|
326
|
+
tell application "System Events" to get value of property list item "CFBundleName" of property list file (app_path & ":Contents:Info.plist")`);
|
|
327
|
+
}
|
|
328
|
+
var init_bundle_name = __esm({
|
|
329
|
+
"../../node_modules/bundle-name/index.js"() {
|
|
330
|
+
init_run_applescript();
|
|
331
|
+
}
|
|
332
|
+
});
|
|
333
|
+
|
|
334
|
+
// ../../node_modules/default-browser/windows.js
|
|
335
|
+
import { promisify as promisify5 } from "node:util";
|
|
336
|
+
import { execFile as execFile5 } from "node:child_process";
|
|
337
|
+
async function defaultBrowser(_execFileAsync = execFileAsync3) {
|
|
338
|
+
const { stdout } = await _execFileAsync("reg", [
|
|
339
|
+
"QUERY",
|
|
340
|
+
" HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\Shell\\Associations\\UrlAssociations\\http\\UserChoice",
|
|
341
|
+
"/v",
|
|
342
|
+
"ProgId"
|
|
343
|
+
]);
|
|
344
|
+
const match = /ProgId\s*REG_SZ\s*(?<id>\S+)/.exec(stdout);
|
|
345
|
+
if (!match) {
|
|
346
|
+
throw new UnknownBrowserError(`Cannot find Windows browser in stdout: ${JSON.stringify(stdout)}`);
|
|
347
|
+
}
|
|
348
|
+
const { id } = match.groups;
|
|
349
|
+
const browser = windowsBrowserProgIds[id];
|
|
350
|
+
if (!browser) {
|
|
351
|
+
throw new UnknownBrowserError(`Unknown browser ID: ${id}`);
|
|
352
|
+
}
|
|
353
|
+
return browser;
|
|
354
|
+
}
|
|
355
|
+
var execFileAsync3, windowsBrowserProgIds, _windowsBrowserProgIdMap, UnknownBrowserError;
|
|
356
|
+
var init_windows = __esm({
|
|
357
|
+
"../../node_modules/default-browser/windows.js"() {
|
|
358
|
+
execFileAsync3 = promisify5(execFile5);
|
|
359
|
+
windowsBrowserProgIds = {
|
|
360
|
+
MSEdgeHTM: { name: "Edge", id: "com.microsoft.edge" },
|
|
361
|
+
// The missing `L` is correct.
|
|
362
|
+
MSEdgeBHTML: { name: "Edge Beta", id: "com.microsoft.edge.beta" },
|
|
363
|
+
MSEdgeDHTML: { name: "Edge Dev", id: "com.microsoft.edge.dev" },
|
|
364
|
+
AppXq0fevzme2pys62n3e0fbqa7peapykr8v: { name: "Edge", id: "com.microsoft.edge.old" },
|
|
365
|
+
ChromeHTML: { name: "Chrome", id: "com.google.chrome" },
|
|
366
|
+
ChromeBHTML: { name: "Chrome Beta", id: "com.google.chrome.beta" },
|
|
367
|
+
ChromeDHTML: { name: "Chrome Dev", id: "com.google.chrome.dev" },
|
|
368
|
+
ChromiumHTM: { name: "Chromium", id: "org.chromium.Chromium" },
|
|
369
|
+
BraveHTML: { name: "Brave", id: "com.brave.Browser" },
|
|
370
|
+
BraveBHTML: { name: "Brave Beta", id: "com.brave.Browser.beta" },
|
|
371
|
+
BraveDHTML: { name: "Brave Dev", id: "com.brave.Browser.dev" },
|
|
372
|
+
BraveSSHTM: { name: "Brave Nightly", id: "com.brave.Browser.nightly" },
|
|
373
|
+
FirefoxURL: { name: "Firefox", id: "org.mozilla.firefox" },
|
|
374
|
+
OperaStable: { name: "Opera", id: "com.operasoftware.Opera" },
|
|
375
|
+
VivaldiHTM: { name: "Vivaldi", id: "com.vivaldi.Vivaldi" },
|
|
376
|
+
"IE.HTTP": { name: "Internet Explorer", id: "com.microsoft.ie" }
|
|
377
|
+
};
|
|
378
|
+
_windowsBrowserProgIdMap = new Map(Object.entries(windowsBrowserProgIds));
|
|
379
|
+
UnknownBrowserError = class extends Error {
|
|
380
|
+
};
|
|
381
|
+
}
|
|
382
|
+
});
|
|
383
|
+
|
|
384
|
+
// ../../node_modules/default-browser/index.js
|
|
385
|
+
import { promisify as promisify6 } from "node:util";
|
|
386
|
+
import process6 from "node:process";
|
|
387
|
+
import { execFile as execFile6 } from "node:child_process";
|
|
388
|
+
async function defaultBrowser2() {
|
|
389
|
+
if (process6.platform === "darwin") {
|
|
390
|
+
const id = await defaultBrowserId();
|
|
391
|
+
const name = await bundleName(id);
|
|
392
|
+
return { name, id };
|
|
393
|
+
}
|
|
394
|
+
if (process6.platform === "linux") {
|
|
395
|
+
const { stdout } = await execFileAsync4("xdg-mime", ["query", "default", "x-scheme-handler/http"]);
|
|
396
|
+
const id = stdout.trim();
|
|
397
|
+
const name = titleize(id.replace(/.desktop$/, "").replace("-", " "));
|
|
398
|
+
return { name, id };
|
|
399
|
+
}
|
|
400
|
+
if (process6.platform === "win32") {
|
|
401
|
+
return defaultBrowser();
|
|
402
|
+
}
|
|
403
|
+
throw new Error("Only macOS, Linux, and Windows are supported");
|
|
404
|
+
}
|
|
405
|
+
var execFileAsync4, titleize;
|
|
406
|
+
var init_default_browser = __esm({
|
|
407
|
+
"../../node_modules/default-browser/index.js"() {
|
|
408
|
+
init_default_browser_id();
|
|
409
|
+
init_bundle_name();
|
|
410
|
+
init_windows();
|
|
411
|
+
init_windows();
|
|
412
|
+
execFileAsync4 = promisify6(execFile6);
|
|
413
|
+
titleize = (string) => string.toLowerCase().replaceAll(/(?:^|\s|-)\S/g, (x) => x.toUpperCase());
|
|
414
|
+
}
|
|
415
|
+
});
|
|
416
|
+
|
|
417
|
+
// ../../node_modules/is-in-ssh/index.js
|
|
418
|
+
import process7 from "node:process";
|
|
419
|
+
var isInSsh, is_in_ssh_default;
|
|
420
|
+
var init_is_in_ssh = __esm({
|
|
421
|
+
"../../node_modules/is-in-ssh/index.js"() {
|
|
422
|
+
isInSsh = Boolean(process7.env.SSH_CONNECTION || process7.env.SSH_CLIENT || process7.env.SSH_TTY);
|
|
423
|
+
is_in_ssh_default = isInSsh;
|
|
424
|
+
}
|
|
425
|
+
});
|
|
426
|
+
|
|
427
|
+
// ../../node_modules/open/index.js
|
|
428
|
+
var open_exports = {};
|
|
429
|
+
__export(open_exports, {
|
|
430
|
+
apps: () => apps,
|
|
431
|
+
default: () => open_default,
|
|
432
|
+
openApp: () => openApp
|
|
433
|
+
});
|
|
434
|
+
import process8 from "node:process";
|
|
435
|
+
import path4 from "node:path";
|
|
436
|
+
import { fileURLToPath } from "node:url";
|
|
437
|
+
import childProcess3 from "node:child_process";
|
|
438
|
+
import fs8, { constants as fsConstants2 } from "node:fs/promises";
|
|
439
|
+
function detectArchBinary(binary) {
|
|
440
|
+
if (typeof binary === "string" || Array.isArray(binary)) {
|
|
441
|
+
return binary;
|
|
442
|
+
}
|
|
443
|
+
const { [arch]: archBinary } = binary;
|
|
444
|
+
if (!archBinary) {
|
|
445
|
+
throw new Error(`${arch} is not supported`);
|
|
446
|
+
}
|
|
447
|
+
return archBinary;
|
|
448
|
+
}
|
|
449
|
+
function detectPlatformBinary({ [platform2]: platformBinary }, { wsl } = {}) {
|
|
450
|
+
if (wsl && is_wsl_default) {
|
|
451
|
+
return detectArchBinary(wsl);
|
|
452
|
+
}
|
|
453
|
+
if (!platformBinary) {
|
|
454
|
+
throw new Error(`${platform2} is not supported`);
|
|
455
|
+
}
|
|
456
|
+
return detectArchBinary(platformBinary);
|
|
457
|
+
}
|
|
458
|
+
var fallbackAttemptSymbol, __dirname, localXdgOpenPath, platform2, arch, tryEachApp, baseOpen, open, openApp, apps, open_default;
|
|
459
|
+
var init_open = __esm({
|
|
460
|
+
"../../node_modules/open/index.js"() {
|
|
461
|
+
init_wsl_utils();
|
|
462
|
+
init_powershell_utils();
|
|
463
|
+
init_define_lazy_prop();
|
|
464
|
+
init_default_browser();
|
|
465
|
+
init_is_inside_container();
|
|
466
|
+
init_is_in_ssh();
|
|
467
|
+
fallbackAttemptSymbol = Symbol("fallbackAttempt");
|
|
468
|
+
__dirname = import.meta.url ? path4.dirname(fileURLToPath(import.meta.url)) : "";
|
|
469
|
+
localXdgOpenPath = path4.join(__dirname, "xdg-open");
|
|
470
|
+
({ platform: platform2, arch } = process8);
|
|
471
|
+
tryEachApp = async (apps2, opener) => {
|
|
472
|
+
if (apps2.length === 0) {
|
|
473
|
+
return;
|
|
474
|
+
}
|
|
475
|
+
const errors = [];
|
|
476
|
+
for (const app of apps2) {
|
|
477
|
+
try {
|
|
478
|
+
return await opener(app);
|
|
479
|
+
} catch (error) {
|
|
480
|
+
errors.push(error);
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
throw new AggregateError(errors, "Failed to open in all supported apps");
|
|
484
|
+
};
|
|
485
|
+
baseOpen = async (options2) => {
|
|
486
|
+
options2 = {
|
|
487
|
+
wait: false,
|
|
488
|
+
background: false,
|
|
489
|
+
newInstance: false,
|
|
490
|
+
allowNonzeroExitCode: false,
|
|
491
|
+
...options2
|
|
492
|
+
};
|
|
493
|
+
const isFallbackAttempt = options2[fallbackAttemptSymbol] === true;
|
|
494
|
+
delete options2[fallbackAttemptSymbol];
|
|
495
|
+
if (Array.isArray(options2.app)) {
|
|
496
|
+
return tryEachApp(options2.app, (singleApp) => baseOpen({
|
|
497
|
+
...options2,
|
|
498
|
+
app: singleApp,
|
|
499
|
+
[fallbackAttemptSymbol]: true
|
|
500
|
+
}));
|
|
501
|
+
}
|
|
502
|
+
let { name: app, arguments: appArguments = [] } = options2.app ?? {};
|
|
503
|
+
appArguments = [...appArguments];
|
|
504
|
+
if (Array.isArray(app)) {
|
|
505
|
+
return tryEachApp(app, (appName) => baseOpen({
|
|
506
|
+
...options2,
|
|
507
|
+
app: {
|
|
508
|
+
name: appName,
|
|
509
|
+
arguments: appArguments
|
|
510
|
+
},
|
|
511
|
+
[fallbackAttemptSymbol]: true
|
|
512
|
+
}));
|
|
513
|
+
}
|
|
514
|
+
if (app === "browser" || app === "browserPrivate") {
|
|
515
|
+
const ids = {
|
|
516
|
+
"com.google.chrome": "chrome",
|
|
517
|
+
"google-chrome.desktop": "chrome",
|
|
518
|
+
"com.brave.browser": "brave",
|
|
519
|
+
"org.mozilla.firefox": "firefox",
|
|
520
|
+
"firefox.desktop": "firefox",
|
|
521
|
+
"com.microsoft.msedge": "edge",
|
|
522
|
+
"com.microsoft.edge": "edge",
|
|
523
|
+
"com.microsoft.edgemac": "edge",
|
|
524
|
+
"microsoft-edge.desktop": "edge",
|
|
525
|
+
"com.apple.safari": "safari"
|
|
526
|
+
};
|
|
527
|
+
const flags = {
|
|
528
|
+
chrome: "--incognito",
|
|
529
|
+
brave: "--incognito",
|
|
530
|
+
firefox: "--private-window",
|
|
531
|
+
edge: "--inPrivate"
|
|
532
|
+
// Safari doesn't support private mode via command line
|
|
533
|
+
};
|
|
534
|
+
let browser;
|
|
535
|
+
if (is_wsl_default) {
|
|
536
|
+
const progId = await wslDefaultBrowser();
|
|
537
|
+
const browserInfo = _windowsBrowserProgIdMap.get(progId);
|
|
538
|
+
browser = browserInfo ?? {};
|
|
539
|
+
} else {
|
|
540
|
+
browser = await defaultBrowser2();
|
|
541
|
+
}
|
|
542
|
+
if (browser.id in ids) {
|
|
543
|
+
const browserName = ids[browser.id.toLowerCase()];
|
|
544
|
+
if (app === "browserPrivate") {
|
|
545
|
+
if (browserName === "safari") {
|
|
546
|
+
throw new Error("Safari doesn't support opening in private mode via command line");
|
|
547
|
+
}
|
|
548
|
+
appArguments.push(flags[browserName]);
|
|
549
|
+
}
|
|
550
|
+
return baseOpen({
|
|
551
|
+
...options2,
|
|
552
|
+
app: {
|
|
553
|
+
name: apps[browserName],
|
|
554
|
+
arguments: appArguments
|
|
555
|
+
}
|
|
556
|
+
});
|
|
557
|
+
}
|
|
558
|
+
throw new Error(`${browser.name} is not supported as a default browser`);
|
|
559
|
+
}
|
|
560
|
+
let command;
|
|
561
|
+
const cliArguments = [];
|
|
562
|
+
const childProcessOptions = {};
|
|
563
|
+
let shouldUseWindowsInWsl = false;
|
|
564
|
+
if (is_wsl_default && !isInsideContainer() && !is_in_ssh_default && !app) {
|
|
565
|
+
shouldUseWindowsInWsl = await canAccessPowerShell();
|
|
566
|
+
}
|
|
567
|
+
if (platform2 === "darwin") {
|
|
568
|
+
command = "open";
|
|
569
|
+
if (options2.wait) {
|
|
570
|
+
cliArguments.push("--wait-apps");
|
|
571
|
+
}
|
|
572
|
+
if (options2.background) {
|
|
573
|
+
cliArguments.push("--background");
|
|
574
|
+
}
|
|
575
|
+
if (options2.newInstance) {
|
|
576
|
+
cliArguments.push("--new");
|
|
577
|
+
}
|
|
578
|
+
if (app) {
|
|
579
|
+
cliArguments.push("-a", app);
|
|
580
|
+
}
|
|
581
|
+
} else if (platform2 === "win32" || shouldUseWindowsInWsl) {
|
|
582
|
+
command = await powerShellPath2();
|
|
583
|
+
cliArguments.push(...executePowerShell.argumentsPrefix);
|
|
584
|
+
if (!is_wsl_default) {
|
|
585
|
+
childProcessOptions.windowsVerbatimArguments = true;
|
|
586
|
+
}
|
|
587
|
+
if (is_wsl_default && options2.target) {
|
|
588
|
+
options2.target = await convertWslPathToWindows(options2.target);
|
|
589
|
+
}
|
|
590
|
+
const encodedArguments = ["$ProgressPreference = 'SilentlyContinue';", "Start"];
|
|
591
|
+
if (options2.wait) {
|
|
592
|
+
encodedArguments.push("-Wait");
|
|
593
|
+
}
|
|
594
|
+
if (app) {
|
|
595
|
+
encodedArguments.push(executePowerShell.escapeArgument(app));
|
|
596
|
+
if (options2.target) {
|
|
597
|
+
appArguments.push(options2.target);
|
|
598
|
+
}
|
|
599
|
+
} else if (options2.target) {
|
|
600
|
+
encodedArguments.push(executePowerShell.escapeArgument(options2.target));
|
|
601
|
+
}
|
|
602
|
+
if (appArguments.length > 0) {
|
|
603
|
+
appArguments = appArguments.map((argument) => executePowerShell.escapeArgument(argument));
|
|
604
|
+
encodedArguments.push("-ArgumentList", appArguments.join(","));
|
|
605
|
+
}
|
|
606
|
+
options2.target = executePowerShell.encodeCommand(encodedArguments.join(" "));
|
|
607
|
+
if (!options2.wait) {
|
|
608
|
+
childProcessOptions.stdio = "ignore";
|
|
609
|
+
}
|
|
610
|
+
} else {
|
|
611
|
+
if (app) {
|
|
612
|
+
command = app;
|
|
613
|
+
} else {
|
|
614
|
+
const isBundled = !__dirname || __dirname === "/";
|
|
615
|
+
let exeLocalXdgOpen = false;
|
|
616
|
+
try {
|
|
617
|
+
await fs8.access(localXdgOpenPath, fsConstants2.X_OK);
|
|
618
|
+
exeLocalXdgOpen = true;
|
|
619
|
+
} catch {
|
|
620
|
+
}
|
|
621
|
+
const useSystemXdgOpen = process8.versions.electron ?? (platform2 === "android" || isBundled || !exeLocalXdgOpen);
|
|
622
|
+
command = useSystemXdgOpen ? "xdg-open" : localXdgOpenPath;
|
|
623
|
+
}
|
|
624
|
+
if (appArguments.length > 0) {
|
|
625
|
+
cliArguments.push(...appArguments);
|
|
626
|
+
}
|
|
627
|
+
if (!options2.wait) {
|
|
628
|
+
childProcessOptions.stdio = "ignore";
|
|
629
|
+
childProcessOptions.detached = true;
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
if (platform2 === "darwin" && appArguments.length > 0) {
|
|
633
|
+
cliArguments.push("--args", ...appArguments);
|
|
634
|
+
}
|
|
635
|
+
if (options2.target) {
|
|
636
|
+
cliArguments.push(options2.target);
|
|
637
|
+
}
|
|
638
|
+
const subprocess = childProcess3.spawn(command, cliArguments, childProcessOptions);
|
|
639
|
+
if (options2.wait) {
|
|
640
|
+
return new Promise((resolve7, reject) => {
|
|
641
|
+
subprocess.once("error", reject);
|
|
642
|
+
subprocess.once("close", (exitCode) => {
|
|
643
|
+
if (!options2.allowNonzeroExitCode && exitCode !== 0) {
|
|
644
|
+
reject(new Error(`Exited with code ${exitCode}`));
|
|
645
|
+
return;
|
|
646
|
+
}
|
|
647
|
+
resolve7(subprocess);
|
|
648
|
+
});
|
|
649
|
+
});
|
|
650
|
+
}
|
|
651
|
+
if (isFallbackAttempt) {
|
|
652
|
+
return new Promise((resolve7, reject) => {
|
|
653
|
+
subprocess.once("error", reject);
|
|
654
|
+
subprocess.once("spawn", () => {
|
|
655
|
+
subprocess.once("close", (exitCode) => {
|
|
656
|
+
subprocess.off("error", reject);
|
|
657
|
+
if (exitCode !== 0) {
|
|
658
|
+
reject(new Error(`Exited with code ${exitCode}`));
|
|
659
|
+
return;
|
|
660
|
+
}
|
|
661
|
+
subprocess.unref();
|
|
662
|
+
resolve7(subprocess);
|
|
663
|
+
});
|
|
664
|
+
});
|
|
665
|
+
});
|
|
666
|
+
}
|
|
667
|
+
subprocess.unref();
|
|
668
|
+
return new Promise((resolve7, reject) => {
|
|
669
|
+
subprocess.once("error", reject);
|
|
670
|
+
subprocess.once("spawn", () => {
|
|
671
|
+
subprocess.off("error", reject);
|
|
672
|
+
resolve7(subprocess);
|
|
673
|
+
});
|
|
674
|
+
});
|
|
675
|
+
};
|
|
676
|
+
open = (target, options2) => {
|
|
677
|
+
if (typeof target !== "string") {
|
|
678
|
+
throw new TypeError("Expected a `target`");
|
|
679
|
+
}
|
|
680
|
+
return baseOpen({
|
|
681
|
+
...options2,
|
|
682
|
+
target
|
|
683
|
+
});
|
|
684
|
+
};
|
|
685
|
+
openApp = (name, options2) => {
|
|
686
|
+
if (typeof name !== "string" && !Array.isArray(name)) {
|
|
687
|
+
throw new TypeError("Expected a valid `name`");
|
|
688
|
+
}
|
|
689
|
+
const { arguments: appArguments = [] } = options2 ?? {};
|
|
690
|
+
if (appArguments !== void 0 && appArguments !== null && !Array.isArray(appArguments)) {
|
|
691
|
+
throw new TypeError("Expected `appArguments` as Array type");
|
|
692
|
+
}
|
|
693
|
+
return baseOpen({
|
|
694
|
+
...options2,
|
|
695
|
+
app: {
|
|
696
|
+
name,
|
|
697
|
+
arguments: appArguments
|
|
698
|
+
}
|
|
699
|
+
});
|
|
700
|
+
};
|
|
701
|
+
apps = {
|
|
702
|
+
browser: "browser",
|
|
703
|
+
browserPrivate: "browserPrivate"
|
|
704
|
+
};
|
|
705
|
+
defineLazyProperty(apps, "chrome", () => detectPlatformBinary({
|
|
706
|
+
darwin: "google chrome",
|
|
707
|
+
win32: "chrome",
|
|
708
|
+
// `chromium-browser` is the older deb package name used by Ubuntu/Debian before snap.
|
|
709
|
+
linux: ["google-chrome", "google-chrome-stable", "chromium", "chromium-browser"]
|
|
710
|
+
}, {
|
|
711
|
+
wsl: {
|
|
712
|
+
ia32: "/mnt/c/Program Files (x86)/Google/Chrome/Application/chrome.exe",
|
|
713
|
+
x64: ["/mnt/c/Program Files/Google/Chrome/Application/chrome.exe", "/mnt/c/Program Files (x86)/Google/Chrome/Application/chrome.exe"]
|
|
714
|
+
}
|
|
715
|
+
}));
|
|
716
|
+
defineLazyProperty(apps, "brave", () => detectPlatformBinary({
|
|
717
|
+
darwin: "brave browser",
|
|
718
|
+
win32: "brave",
|
|
719
|
+
linux: ["brave-browser", "brave"]
|
|
720
|
+
}, {
|
|
721
|
+
wsl: {
|
|
722
|
+
ia32: "/mnt/c/Program Files (x86)/BraveSoftware/Brave-Browser/Application/brave.exe",
|
|
723
|
+
x64: ["/mnt/c/Program Files/BraveSoftware/Brave-Browser/Application/brave.exe", "/mnt/c/Program Files (x86)/BraveSoftware/Brave-Browser/Application/brave.exe"]
|
|
724
|
+
}
|
|
725
|
+
}));
|
|
726
|
+
defineLazyProperty(apps, "firefox", () => detectPlatformBinary({
|
|
727
|
+
darwin: "firefox",
|
|
728
|
+
win32: String.raw`C:\Program Files\Mozilla Firefox\firefox.exe`,
|
|
729
|
+
linux: "firefox"
|
|
730
|
+
}, {
|
|
731
|
+
wsl: "/mnt/c/Program Files/Mozilla Firefox/firefox.exe"
|
|
732
|
+
}));
|
|
733
|
+
defineLazyProperty(apps, "edge", () => detectPlatformBinary({
|
|
734
|
+
darwin: "microsoft edge",
|
|
735
|
+
win32: "msedge",
|
|
736
|
+
linux: ["microsoft-edge", "microsoft-edge-dev"]
|
|
737
|
+
}, {
|
|
738
|
+
wsl: "/mnt/c/Program Files (x86)/Microsoft/Edge/Application/msedge.exe"
|
|
739
|
+
}));
|
|
740
|
+
defineLazyProperty(apps, "safari", () => detectPlatformBinary({
|
|
741
|
+
darwin: "Safari"
|
|
742
|
+
}));
|
|
743
|
+
open_default = open;
|
|
744
|
+
}
|
|
745
|
+
});
|
|
746
|
+
|
|
34
747
|
// ../../node_modules/hcl2-json-parser/dist/index.js
|
|
35
748
|
var require_dist = __commonJS({
|
|
36
749
|
"../../node_modules/hcl2-json-parser/dist/index.js"(exports, module) {
|
|
@@ -41,8 +754,8 @@ var require_dist = __commonJS({
|
|
|
41
754
|
var $global, $module, $NaN = NaN;
|
|
42
755
|
if ("undefined" != typeof window ? $global = window : "undefined" != typeof self ? $global = self : "undefined" != typeof global ? ($global = global).require = __require : $global = this, void 0 === $global || void 0 === $global.Array) throw new Error("no global object found");
|
|
43
756
|
if ("undefined" != typeof module && ($module = module), !$global.fs && $global.require) try {
|
|
44
|
-
var
|
|
45
|
-
"object" == typeof
|
|
757
|
+
var fs25 = $global.require("fs");
|
|
758
|
+
"object" == typeof fs25 && null !== fs25 && 0 !== Object.keys(fs25).length && ($global.fs = fs25);
|
|
46
759
|
} catch (e) {
|
|
47
760
|
}
|
|
48
761
|
if (!$global.fs) {
|
|
@@ -182233,8 +182946,8 @@ var require_dist = __commonJS({
|
|
|
182233
182946
|
import { Command } from "commander";
|
|
182234
182947
|
|
|
182235
182948
|
// src/commands/init.tsx
|
|
182236
|
-
import React2, { useState
|
|
182237
|
-
import { render as render2, Text as Text2, Box as Box2, useInput, useApp
|
|
182949
|
+
import React2, { useState, useEffect } from "react";
|
|
182950
|
+
import { render as render2, Text as Text2, Box as Box2, useInput, useApp } from "ink";
|
|
182238
182951
|
import "ink-spinner";
|
|
182239
182952
|
import * as fs10 from "fs";
|
|
182240
182953
|
import * as path6 from "path";
|
|
@@ -182407,7 +183120,7 @@ function generateCertificate(domain, keys = []) {
|
|
|
182407
183120
|
|
|
182408
183121
|
// src/lib/analytics/index.ts
|
|
182409
183122
|
import { PostHog } from "posthog-node";
|
|
182410
|
-
import * as
|
|
183123
|
+
import * as os5 from "os";
|
|
182411
183124
|
import * as crypto from "crypto";
|
|
182412
183125
|
|
|
182413
183126
|
// src/lib/project/config.ts
|
|
@@ -182452,7 +183165,7 @@ function writeProjectId(projectId, projectDir = process.cwd()) {
|
|
|
182452
183165
|
// src/lib/auth/credentials.ts
|
|
182453
183166
|
import * as fs9 from "fs";
|
|
182454
183167
|
import * as path5 from "path";
|
|
182455
|
-
import * as
|
|
183168
|
+
import * as os4 from "os";
|
|
182456
183169
|
|
|
182457
183170
|
// src/lib/auth/errors.ts
|
|
182458
183171
|
var RefreshTokenExpiredError = class extends Error {
|
|
@@ -182525,642 +183238,22 @@ async function refreshAccessToken(refreshToken) {
|
|
|
182525
183238
|
}
|
|
182526
183239
|
|
|
182527
183240
|
// src/lib/auth/login.tsx
|
|
182528
|
-
import React
|
|
182529
|
-
import { render, Box, Text
|
|
183241
|
+
import React from "react";
|
|
183242
|
+
import { render, Box, Text } from "ink";
|
|
182530
183243
|
import Spinner from "ink-spinner";
|
|
182531
183244
|
|
|
182532
|
-
// ../../node_modules/open/index.js
|
|
182533
|
-
import process8 from "node:process";
|
|
182534
|
-
import path3 from "node:path";
|
|
182535
|
-
import { fileURLToPath } from "node:url";
|
|
182536
|
-
import childProcess3 from "node:child_process";
|
|
182537
|
-
import fs7, { constants as fsConstants2 } from "node:fs/promises";
|
|
182538
|
-
|
|
182539
|
-
// ../../node_modules/wsl-utils/index.js
|
|
182540
|
-
import { promisify as promisify2 } from "node:util";
|
|
182541
|
-
import childProcess2 from "node:child_process";
|
|
182542
|
-
import fs6, { constants as fsConstants } from "node:fs/promises";
|
|
182543
|
-
|
|
182544
|
-
// ../../node_modules/is-wsl/index.js
|
|
182545
|
-
import process2 from "node:process";
|
|
182546
|
-
import os2 from "node:os";
|
|
182547
|
-
import fs5 from "node:fs";
|
|
182548
|
-
|
|
182549
|
-
// ../../node_modules/is-inside-container/index.js
|
|
182550
|
-
import fs4 from "node:fs";
|
|
182551
|
-
|
|
182552
|
-
// ../../node_modules/is-docker/index.js
|
|
182553
|
-
import fs3 from "node:fs";
|
|
182554
|
-
var isDockerCached;
|
|
182555
|
-
function hasDockerEnv() {
|
|
182556
|
-
try {
|
|
182557
|
-
fs3.statSync("/.dockerenv");
|
|
182558
|
-
return true;
|
|
182559
|
-
} catch {
|
|
182560
|
-
return false;
|
|
182561
|
-
}
|
|
182562
|
-
}
|
|
182563
|
-
function hasDockerCGroup() {
|
|
182564
|
-
try {
|
|
182565
|
-
return fs3.readFileSync("/proc/self/cgroup", "utf8").includes("docker");
|
|
182566
|
-
} catch {
|
|
182567
|
-
return false;
|
|
182568
|
-
}
|
|
182569
|
-
}
|
|
182570
|
-
function isDocker() {
|
|
182571
|
-
if (isDockerCached === void 0) {
|
|
182572
|
-
isDockerCached = hasDockerEnv() || hasDockerCGroup();
|
|
182573
|
-
}
|
|
182574
|
-
return isDockerCached;
|
|
182575
|
-
}
|
|
182576
|
-
|
|
182577
|
-
// ../../node_modules/is-inside-container/index.js
|
|
182578
|
-
var cachedResult;
|
|
182579
|
-
var hasContainerEnv = () => {
|
|
182580
|
-
try {
|
|
182581
|
-
fs4.statSync("/run/.containerenv");
|
|
182582
|
-
return true;
|
|
182583
|
-
} catch {
|
|
182584
|
-
return false;
|
|
182585
|
-
}
|
|
182586
|
-
};
|
|
182587
|
-
function isInsideContainer() {
|
|
182588
|
-
if (cachedResult === void 0) {
|
|
182589
|
-
cachedResult = hasContainerEnv() || isDocker();
|
|
182590
|
-
}
|
|
182591
|
-
return cachedResult;
|
|
182592
|
-
}
|
|
182593
|
-
|
|
182594
|
-
// ../../node_modules/is-wsl/index.js
|
|
182595
|
-
var isWsl = () => {
|
|
182596
|
-
if (process2.platform !== "linux") {
|
|
182597
|
-
return false;
|
|
182598
|
-
}
|
|
182599
|
-
if (os2.release().toLowerCase().includes("microsoft")) {
|
|
182600
|
-
if (isInsideContainer()) {
|
|
182601
|
-
return false;
|
|
182602
|
-
}
|
|
182603
|
-
return true;
|
|
182604
|
-
}
|
|
182605
|
-
try {
|
|
182606
|
-
return fs5.readFileSync("/proc/version", "utf8").toLowerCase().includes("microsoft") ? !isInsideContainer() : false;
|
|
182607
|
-
} catch {
|
|
182608
|
-
return false;
|
|
182609
|
-
}
|
|
182610
|
-
};
|
|
182611
|
-
var is_wsl_default = process2.env.__IS_WSL_TEST__ ? isWsl : isWsl();
|
|
182612
|
-
|
|
182613
|
-
// ../../node_modules/powershell-utils/index.js
|
|
182614
|
-
import process3 from "node:process";
|
|
182615
|
-
import { Buffer as Buffer2 } from "node:buffer";
|
|
182616
|
-
import { promisify } from "node:util";
|
|
182617
|
-
import childProcess from "node:child_process";
|
|
182618
|
-
var execFile = promisify(childProcess.execFile);
|
|
182619
|
-
var powerShellPath = () => `${process3.env.SYSTEMROOT || process3.env.windir || String.raw`C:\Windows`}\\System32\\WindowsPowerShell\\v1.0\\powershell.exe`;
|
|
182620
|
-
var executePowerShell = async (command, options2 = {}) => {
|
|
182621
|
-
const {
|
|
182622
|
-
powerShellPath: psPath,
|
|
182623
|
-
...execFileOptions
|
|
182624
|
-
} = options2;
|
|
182625
|
-
const encodedCommand = executePowerShell.encodeCommand(command);
|
|
182626
|
-
return execFile(
|
|
182627
|
-
psPath ?? powerShellPath(),
|
|
182628
|
-
[
|
|
182629
|
-
...executePowerShell.argumentsPrefix,
|
|
182630
|
-
encodedCommand
|
|
182631
|
-
],
|
|
182632
|
-
{
|
|
182633
|
-
encoding: "utf8",
|
|
182634
|
-
...execFileOptions
|
|
182635
|
-
}
|
|
182636
|
-
);
|
|
182637
|
-
};
|
|
182638
|
-
executePowerShell.argumentsPrefix = [
|
|
182639
|
-
"-NoProfile",
|
|
182640
|
-
"-NonInteractive",
|
|
182641
|
-
"-ExecutionPolicy",
|
|
182642
|
-
"Bypass",
|
|
182643
|
-
"-EncodedCommand"
|
|
182644
|
-
];
|
|
182645
|
-
executePowerShell.encodeCommand = (command) => Buffer2.from(command, "utf16le").toString("base64");
|
|
182646
|
-
executePowerShell.escapeArgument = (value) => `'${String(value).replaceAll("'", "''")}'`;
|
|
182647
|
-
|
|
182648
|
-
// ../../node_modules/wsl-utils/utilities.js
|
|
182649
|
-
function parseMountPointFromConfig(content) {
|
|
182650
|
-
for (const line of content.split("\n")) {
|
|
182651
|
-
if (/^\s*#/.test(line)) {
|
|
182652
|
-
continue;
|
|
182653
|
-
}
|
|
182654
|
-
const match = /^\s*root\s*=\s*(?<mountPoint>"[^"]*"|'[^']*'|[^#]*)/.exec(line);
|
|
182655
|
-
if (!match) {
|
|
182656
|
-
continue;
|
|
182657
|
-
}
|
|
182658
|
-
return match.groups.mountPoint.trim().replaceAll(/^["']|["']$/g, "");
|
|
182659
|
-
}
|
|
182660
|
-
}
|
|
182661
|
-
|
|
182662
|
-
// ../../node_modules/wsl-utils/index.js
|
|
182663
|
-
var execFile2 = promisify2(childProcess2.execFile);
|
|
182664
|
-
var wslDrivesMountPoint = /* @__PURE__ */ (() => {
|
|
182665
|
-
const defaultMountPoint = "/mnt/";
|
|
182666
|
-
let mountPoint;
|
|
182667
|
-
return async function() {
|
|
182668
|
-
if (mountPoint) {
|
|
182669
|
-
return mountPoint;
|
|
182670
|
-
}
|
|
182671
|
-
const configFilePath = "/etc/wsl.conf";
|
|
182672
|
-
let isConfigFileExists = false;
|
|
182673
|
-
try {
|
|
182674
|
-
await fs6.access(configFilePath, fsConstants.F_OK);
|
|
182675
|
-
isConfigFileExists = true;
|
|
182676
|
-
} catch {
|
|
182677
|
-
}
|
|
182678
|
-
if (!isConfigFileExists) {
|
|
182679
|
-
return defaultMountPoint;
|
|
182680
|
-
}
|
|
182681
|
-
const configContent = await fs6.readFile(configFilePath, { encoding: "utf8" });
|
|
182682
|
-
const parsedMountPoint = parseMountPointFromConfig(configContent);
|
|
182683
|
-
if (parsedMountPoint === void 0) {
|
|
182684
|
-
return defaultMountPoint;
|
|
182685
|
-
}
|
|
182686
|
-
mountPoint = parsedMountPoint;
|
|
182687
|
-
mountPoint = mountPoint.endsWith("/") ? mountPoint : `${mountPoint}/`;
|
|
182688
|
-
return mountPoint;
|
|
182689
|
-
};
|
|
182690
|
-
})();
|
|
182691
|
-
var powerShellPathFromWsl = async () => {
|
|
182692
|
-
const mountPoint = await wslDrivesMountPoint();
|
|
182693
|
-
return `${mountPoint}c/Windows/System32/WindowsPowerShell/v1.0/powershell.exe`;
|
|
182694
|
-
};
|
|
182695
|
-
var powerShellPath2 = is_wsl_default ? powerShellPathFromWsl : powerShellPath;
|
|
182696
|
-
var canAccessPowerShellPromise;
|
|
182697
|
-
var canAccessPowerShell = async () => {
|
|
182698
|
-
canAccessPowerShellPromise ??= (async () => {
|
|
182699
|
-
try {
|
|
182700
|
-
const psPath = await powerShellPath2();
|
|
182701
|
-
await fs6.access(psPath, fsConstants.X_OK);
|
|
182702
|
-
return true;
|
|
182703
|
-
} catch {
|
|
182704
|
-
return false;
|
|
182705
|
-
}
|
|
182706
|
-
})();
|
|
182707
|
-
return canAccessPowerShellPromise;
|
|
182708
|
-
};
|
|
182709
|
-
var wslDefaultBrowser = async () => {
|
|
182710
|
-
const psPath = await powerShellPath2();
|
|
182711
|
-
const command = String.raw`(Get-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\Shell\Associations\UrlAssociations\http\UserChoice").ProgId`;
|
|
182712
|
-
const { stdout } = await executePowerShell(command, { powerShellPath: psPath });
|
|
182713
|
-
return stdout.trim();
|
|
182714
|
-
};
|
|
182715
|
-
var convertWslPathToWindows = async (path22) => {
|
|
182716
|
-
if (/^[a-z]+:\/\//i.test(path22)) {
|
|
182717
|
-
return path22;
|
|
182718
|
-
}
|
|
182719
|
-
try {
|
|
182720
|
-
const { stdout } = await execFile2("wslpath", ["-aw", path22], { encoding: "utf8" });
|
|
182721
|
-
return stdout.trim();
|
|
182722
|
-
} catch {
|
|
182723
|
-
return path22;
|
|
182724
|
-
}
|
|
182725
|
-
};
|
|
182726
|
-
|
|
182727
|
-
// ../../node_modules/define-lazy-prop/index.js
|
|
182728
|
-
function defineLazyProperty(object, propertyName, valueGetter) {
|
|
182729
|
-
const define = (value) => Object.defineProperty(object, propertyName, { value, enumerable: true, writable: true });
|
|
182730
|
-
Object.defineProperty(object, propertyName, {
|
|
182731
|
-
configurable: true,
|
|
182732
|
-
enumerable: true,
|
|
182733
|
-
get() {
|
|
182734
|
-
const result = valueGetter();
|
|
182735
|
-
define(result);
|
|
182736
|
-
return result;
|
|
182737
|
-
},
|
|
182738
|
-
set(value) {
|
|
182739
|
-
define(value);
|
|
182740
|
-
}
|
|
182741
|
-
});
|
|
182742
|
-
return object;
|
|
182743
|
-
}
|
|
182744
|
-
|
|
182745
|
-
// ../../node_modules/default-browser/index.js
|
|
182746
|
-
import { promisify as promisify6 } from "node:util";
|
|
182747
|
-
import process6 from "node:process";
|
|
182748
|
-
import { execFile as execFile6 } from "node:child_process";
|
|
182749
|
-
|
|
182750
|
-
// ../../node_modules/default-browser-id/index.js
|
|
182751
|
-
import { promisify as promisify3 } from "node:util";
|
|
182752
|
-
import process4 from "node:process";
|
|
182753
|
-
import { execFile as execFile3 } from "node:child_process";
|
|
182754
|
-
var execFileAsync = promisify3(execFile3);
|
|
182755
|
-
async function defaultBrowserId() {
|
|
182756
|
-
if (process4.platform !== "darwin") {
|
|
182757
|
-
throw new Error("macOS only");
|
|
182758
|
-
}
|
|
182759
|
-
const { stdout } = await execFileAsync("defaults", ["read", "com.apple.LaunchServices/com.apple.launchservices.secure", "LSHandlers"]);
|
|
182760
|
-
const match = /LSHandlerRoleAll = "(?!-)(?<id>[^"]+?)";\s+?LSHandlerURLScheme = (?:http|https);/.exec(stdout);
|
|
182761
|
-
const browserId = match?.groups.id ?? "com.apple.Safari";
|
|
182762
|
-
if (browserId === "com.apple.safari") {
|
|
182763
|
-
return "com.apple.Safari";
|
|
182764
|
-
}
|
|
182765
|
-
return browserId;
|
|
182766
|
-
}
|
|
182767
|
-
|
|
182768
|
-
// ../../node_modules/run-applescript/index.js
|
|
182769
|
-
import process5 from "node:process";
|
|
182770
|
-
import { promisify as promisify4 } from "node:util";
|
|
182771
|
-
import { execFile as execFile4, execFileSync } from "node:child_process";
|
|
182772
|
-
var execFileAsync2 = promisify4(execFile4);
|
|
182773
|
-
async function runAppleScript(script, { humanReadableOutput = true, signal } = {}) {
|
|
182774
|
-
if (process5.platform !== "darwin") {
|
|
182775
|
-
throw new Error("macOS only");
|
|
182776
|
-
}
|
|
182777
|
-
const outputArguments = humanReadableOutput ? [] : ["-ss"];
|
|
182778
|
-
const execOptions = {};
|
|
182779
|
-
if (signal) {
|
|
182780
|
-
execOptions.signal = signal;
|
|
182781
|
-
}
|
|
182782
|
-
const { stdout } = await execFileAsync2("osascript", ["-e", script, outputArguments], execOptions);
|
|
182783
|
-
return stdout.trim();
|
|
182784
|
-
}
|
|
182785
|
-
|
|
182786
|
-
// ../../node_modules/bundle-name/index.js
|
|
182787
|
-
async function bundleName(bundleId) {
|
|
182788
|
-
return runAppleScript(`tell application "Finder" to set app_path to application file id "${bundleId}" as string
|
|
182789
|
-
tell application "System Events" to get value of property list item "CFBundleName" of property list file (app_path & ":Contents:Info.plist")`);
|
|
182790
|
-
}
|
|
182791
|
-
|
|
182792
|
-
// ../../node_modules/default-browser/windows.js
|
|
182793
|
-
import { promisify as promisify5 } from "node:util";
|
|
182794
|
-
import { execFile as execFile5 } from "node:child_process";
|
|
182795
|
-
var execFileAsync3 = promisify5(execFile5);
|
|
182796
|
-
var windowsBrowserProgIds = {
|
|
182797
|
-
MSEdgeHTM: { name: "Edge", id: "com.microsoft.edge" },
|
|
182798
|
-
// The missing `L` is correct.
|
|
182799
|
-
MSEdgeBHTML: { name: "Edge Beta", id: "com.microsoft.edge.beta" },
|
|
182800
|
-
MSEdgeDHTML: { name: "Edge Dev", id: "com.microsoft.edge.dev" },
|
|
182801
|
-
AppXq0fevzme2pys62n3e0fbqa7peapykr8v: { name: "Edge", id: "com.microsoft.edge.old" },
|
|
182802
|
-
ChromeHTML: { name: "Chrome", id: "com.google.chrome" },
|
|
182803
|
-
ChromeBHTML: { name: "Chrome Beta", id: "com.google.chrome.beta" },
|
|
182804
|
-
ChromeDHTML: { name: "Chrome Dev", id: "com.google.chrome.dev" },
|
|
182805
|
-
ChromiumHTM: { name: "Chromium", id: "org.chromium.Chromium" },
|
|
182806
|
-
BraveHTML: { name: "Brave", id: "com.brave.Browser" },
|
|
182807
|
-
BraveBHTML: { name: "Brave Beta", id: "com.brave.Browser.beta" },
|
|
182808
|
-
BraveDHTML: { name: "Brave Dev", id: "com.brave.Browser.dev" },
|
|
182809
|
-
BraveSSHTM: { name: "Brave Nightly", id: "com.brave.Browser.nightly" },
|
|
182810
|
-
FirefoxURL: { name: "Firefox", id: "org.mozilla.firefox" },
|
|
182811
|
-
OperaStable: { name: "Opera", id: "com.operasoftware.Opera" },
|
|
182812
|
-
VivaldiHTM: { name: "Vivaldi", id: "com.vivaldi.Vivaldi" },
|
|
182813
|
-
"IE.HTTP": { name: "Internet Explorer", id: "com.microsoft.ie" }
|
|
182814
|
-
};
|
|
182815
|
-
var _windowsBrowserProgIdMap = new Map(Object.entries(windowsBrowserProgIds));
|
|
182816
|
-
var UnknownBrowserError = class extends Error {
|
|
182817
|
-
};
|
|
182818
|
-
async function defaultBrowser(_execFileAsync = execFileAsync3) {
|
|
182819
|
-
const { stdout } = await _execFileAsync("reg", [
|
|
182820
|
-
"QUERY",
|
|
182821
|
-
" HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\Shell\\Associations\\UrlAssociations\\http\\UserChoice",
|
|
182822
|
-
"/v",
|
|
182823
|
-
"ProgId"
|
|
182824
|
-
]);
|
|
182825
|
-
const match = /ProgId\s*REG_SZ\s*(?<id>\S+)/.exec(stdout);
|
|
182826
|
-
if (!match) {
|
|
182827
|
-
throw new UnknownBrowserError(`Cannot find Windows browser in stdout: ${JSON.stringify(stdout)}`);
|
|
182828
|
-
}
|
|
182829
|
-
const { id } = match.groups;
|
|
182830
|
-
const browser = windowsBrowserProgIds[id];
|
|
182831
|
-
if (!browser) {
|
|
182832
|
-
throw new UnknownBrowserError(`Unknown browser ID: ${id}`);
|
|
182833
|
-
}
|
|
182834
|
-
return browser;
|
|
182835
|
-
}
|
|
182836
|
-
|
|
182837
|
-
// ../../node_modules/default-browser/index.js
|
|
182838
|
-
var execFileAsync4 = promisify6(execFile6);
|
|
182839
|
-
var titleize = (string) => string.toLowerCase().replaceAll(/(?:^|\s|-)\S/g, (x) => x.toUpperCase());
|
|
182840
|
-
async function defaultBrowser2() {
|
|
182841
|
-
if (process6.platform === "darwin") {
|
|
182842
|
-
const id = await defaultBrowserId();
|
|
182843
|
-
const name = await bundleName(id);
|
|
182844
|
-
return { name, id };
|
|
182845
|
-
}
|
|
182846
|
-
if (process6.platform === "linux") {
|
|
182847
|
-
const { stdout } = await execFileAsync4("xdg-mime", ["query", "default", "x-scheme-handler/http"]);
|
|
182848
|
-
const id = stdout.trim();
|
|
182849
|
-
const name = titleize(id.replace(/.desktop$/, "").replace("-", " "));
|
|
182850
|
-
return { name, id };
|
|
182851
|
-
}
|
|
182852
|
-
if (process6.platform === "win32") {
|
|
182853
|
-
return defaultBrowser();
|
|
182854
|
-
}
|
|
182855
|
-
throw new Error("Only macOS, Linux, and Windows are supported");
|
|
182856
|
-
}
|
|
182857
|
-
|
|
182858
|
-
// ../../node_modules/is-in-ssh/index.js
|
|
182859
|
-
import process7 from "node:process";
|
|
182860
|
-
var isInSsh = Boolean(process7.env.SSH_CONNECTION || process7.env.SSH_CLIENT || process7.env.SSH_TTY);
|
|
182861
|
-
var is_in_ssh_default = isInSsh;
|
|
182862
|
-
|
|
182863
|
-
// ../../node_modules/open/index.js
|
|
182864
|
-
var fallbackAttemptSymbol = Symbol("fallbackAttempt");
|
|
182865
|
-
var __dirname = import.meta.url ? path3.dirname(fileURLToPath(import.meta.url)) : "";
|
|
182866
|
-
var localXdgOpenPath = path3.join(__dirname, "xdg-open");
|
|
182867
|
-
var { platform: platform2, arch } = process8;
|
|
182868
|
-
var tryEachApp = async (apps2, opener) => {
|
|
182869
|
-
if (apps2.length === 0) {
|
|
182870
|
-
return;
|
|
182871
|
-
}
|
|
182872
|
-
const errors = [];
|
|
182873
|
-
for (const app of apps2) {
|
|
182874
|
-
try {
|
|
182875
|
-
return await opener(app);
|
|
182876
|
-
} catch (error) {
|
|
182877
|
-
errors.push(error);
|
|
182878
|
-
}
|
|
182879
|
-
}
|
|
182880
|
-
throw new AggregateError(errors, "Failed to open in all supported apps");
|
|
182881
|
-
};
|
|
182882
|
-
var baseOpen = async (options2) => {
|
|
182883
|
-
options2 = {
|
|
182884
|
-
wait: false,
|
|
182885
|
-
background: false,
|
|
182886
|
-
newInstance: false,
|
|
182887
|
-
allowNonzeroExitCode: false,
|
|
182888
|
-
...options2
|
|
182889
|
-
};
|
|
182890
|
-
const isFallbackAttempt = options2[fallbackAttemptSymbol] === true;
|
|
182891
|
-
delete options2[fallbackAttemptSymbol];
|
|
182892
|
-
if (Array.isArray(options2.app)) {
|
|
182893
|
-
return tryEachApp(options2.app, (singleApp) => baseOpen({
|
|
182894
|
-
...options2,
|
|
182895
|
-
app: singleApp,
|
|
182896
|
-
[fallbackAttemptSymbol]: true
|
|
182897
|
-
}));
|
|
182898
|
-
}
|
|
182899
|
-
let { name: app, arguments: appArguments = [] } = options2.app ?? {};
|
|
182900
|
-
appArguments = [...appArguments];
|
|
182901
|
-
if (Array.isArray(app)) {
|
|
182902
|
-
return tryEachApp(app, (appName) => baseOpen({
|
|
182903
|
-
...options2,
|
|
182904
|
-
app: {
|
|
182905
|
-
name: appName,
|
|
182906
|
-
arguments: appArguments
|
|
182907
|
-
},
|
|
182908
|
-
[fallbackAttemptSymbol]: true
|
|
182909
|
-
}));
|
|
182910
|
-
}
|
|
182911
|
-
if (app === "browser" || app === "browserPrivate") {
|
|
182912
|
-
const ids = {
|
|
182913
|
-
"com.google.chrome": "chrome",
|
|
182914
|
-
"google-chrome.desktop": "chrome",
|
|
182915
|
-
"com.brave.browser": "brave",
|
|
182916
|
-
"org.mozilla.firefox": "firefox",
|
|
182917
|
-
"firefox.desktop": "firefox",
|
|
182918
|
-
"com.microsoft.msedge": "edge",
|
|
182919
|
-
"com.microsoft.edge": "edge",
|
|
182920
|
-
"com.microsoft.edgemac": "edge",
|
|
182921
|
-
"microsoft-edge.desktop": "edge",
|
|
182922
|
-
"com.apple.safari": "safari"
|
|
182923
|
-
};
|
|
182924
|
-
const flags = {
|
|
182925
|
-
chrome: "--incognito",
|
|
182926
|
-
brave: "--incognito",
|
|
182927
|
-
firefox: "--private-window",
|
|
182928
|
-
edge: "--inPrivate"
|
|
182929
|
-
// Safari doesn't support private mode via command line
|
|
182930
|
-
};
|
|
182931
|
-
let browser;
|
|
182932
|
-
if (is_wsl_default) {
|
|
182933
|
-
const progId = await wslDefaultBrowser();
|
|
182934
|
-
const browserInfo = _windowsBrowserProgIdMap.get(progId);
|
|
182935
|
-
browser = browserInfo ?? {};
|
|
182936
|
-
} else {
|
|
182937
|
-
browser = await defaultBrowser2();
|
|
182938
|
-
}
|
|
182939
|
-
if (browser.id in ids) {
|
|
182940
|
-
const browserName = ids[browser.id.toLowerCase()];
|
|
182941
|
-
if (app === "browserPrivate") {
|
|
182942
|
-
if (browserName === "safari") {
|
|
182943
|
-
throw new Error("Safari doesn't support opening in private mode via command line");
|
|
182944
|
-
}
|
|
182945
|
-
appArguments.push(flags[browserName]);
|
|
182946
|
-
}
|
|
182947
|
-
return baseOpen({
|
|
182948
|
-
...options2,
|
|
182949
|
-
app: {
|
|
182950
|
-
name: apps[browserName],
|
|
182951
|
-
arguments: appArguments
|
|
182952
|
-
}
|
|
182953
|
-
});
|
|
182954
|
-
}
|
|
182955
|
-
throw new Error(`${browser.name} is not supported as a default browser`);
|
|
182956
|
-
}
|
|
182957
|
-
let command;
|
|
182958
|
-
const cliArguments = [];
|
|
182959
|
-
const childProcessOptions = {};
|
|
182960
|
-
let shouldUseWindowsInWsl = false;
|
|
182961
|
-
if (is_wsl_default && !isInsideContainer() && !is_in_ssh_default && !app) {
|
|
182962
|
-
shouldUseWindowsInWsl = await canAccessPowerShell();
|
|
182963
|
-
}
|
|
182964
|
-
if (platform2 === "darwin") {
|
|
182965
|
-
command = "open";
|
|
182966
|
-
if (options2.wait) {
|
|
182967
|
-
cliArguments.push("--wait-apps");
|
|
182968
|
-
}
|
|
182969
|
-
if (options2.background) {
|
|
182970
|
-
cliArguments.push("--background");
|
|
182971
|
-
}
|
|
182972
|
-
if (options2.newInstance) {
|
|
182973
|
-
cliArguments.push("--new");
|
|
182974
|
-
}
|
|
182975
|
-
if (app) {
|
|
182976
|
-
cliArguments.push("-a", app);
|
|
182977
|
-
}
|
|
182978
|
-
} else if (platform2 === "win32" || shouldUseWindowsInWsl) {
|
|
182979
|
-
command = await powerShellPath2();
|
|
182980
|
-
cliArguments.push(...executePowerShell.argumentsPrefix);
|
|
182981
|
-
if (!is_wsl_default) {
|
|
182982
|
-
childProcessOptions.windowsVerbatimArguments = true;
|
|
182983
|
-
}
|
|
182984
|
-
if (is_wsl_default && options2.target) {
|
|
182985
|
-
options2.target = await convertWslPathToWindows(options2.target);
|
|
182986
|
-
}
|
|
182987
|
-
const encodedArguments = ["$ProgressPreference = 'SilentlyContinue';", "Start"];
|
|
182988
|
-
if (options2.wait) {
|
|
182989
|
-
encodedArguments.push("-Wait");
|
|
182990
|
-
}
|
|
182991
|
-
if (app) {
|
|
182992
|
-
encodedArguments.push(executePowerShell.escapeArgument(app));
|
|
182993
|
-
if (options2.target) {
|
|
182994
|
-
appArguments.push(options2.target);
|
|
182995
|
-
}
|
|
182996
|
-
} else if (options2.target) {
|
|
182997
|
-
encodedArguments.push(executePowerShell.escapeArgument(options2.target));
|
|
182998
|
-
}
|
|
182999
|
-
if (appArguments.length > 0) {
|
|
183000
|
-
appArguments = appArguments.map((argument) => executePowerShell.escapeArgument(argument));
|
|
183001
|
-
encodedArguments.push("-ArgumentList", appArguments.join(","));
|
|
183002
|
-
}
|
|
183003
|
-
options2.target = executePowerShell.encodeCommand(encodedArguments.join(" "));
|
|
183004
|
-
if (!options2.wait) {
|
|
183005
|
-
childProcessOptions.stdio = "ignore";
|
|
183006
|
-
}
|
|
183007
|
-
} else {
|
|
183008
|
-
if (app) {
|
|
183009
|
-
command = app;
|
|
183010
|
-
} else {
|
|
183011
|
-
const isBundled = !__dirname || __dirname === "/";
|
|
183012
|
-
let exeLocalXdgOpen = false;
|
|
183013
|
-
try {
|
|
183014
|
-
await fs7.access(localXdgOpenPath, fsConstants2.X_OK);
|
|
183015
|
-
exeLocalXdgOpen = true;
|
|
183016
|
-
} catch {
|
|
183017
|
-
}
|
|
183018
|
-
const useSystemXdgOpen = process8.versions.electron ?? (platform2 === "android" || isBundled || !exeLocalXdgOpen);
|
|
183019
|
-
command = useSystemXdgOpen ? "xdg-open" : localXdgOpenPath;
|
|
183020
|
-
}
|
|
183021
|
-
if (appArguments.length > 0) {
|
|
183022
|
-
cliArguments.push(...appArguments);
|
|
183023
|
-
}
|
|
183024
|
-
if (!options2.wait) {
|
|
183025
|
-
childProcessOptions.stdio = "ignore";
|
|
183026
|
-
childProcessOptions.detached = true;
|
|
183027
|
-
}
|
|
183028
|
-
}
|
|
183029
|
-
if (platform2 === "darwin" && appArguments.length > 0) {
|
|
183030
|
-
cliArguments.push("--args", ...appArguments);
|
|
183031
|
-
}
|
|
183032
|
-
if (options2.target) {
|
|
183033
|
-
cliArguments.push(options2.target);
|
|
183034
|
-
}
|
|
183035
|
-
const subprocess = childProcess3.spawn(command, cliArguments, childProcessOptions);
|
|
183036
|
-
if (options2.wait) {
|
|
183037
|
-
return new Promise((resolve7, reject) => {
|
|
183038
|
-
subprocess.once("error", reject);
|
|
183039
|
-
subprocess.once("close", (exitCode) => {
|
|
183040
|
-
if (!options2.allowNonzeroExitCode && exitCode !== 0) {
|
|
183041
|
-
reject(new Error(`Exited with code ${exitCode}`));
|
|
183042
|
-
return;
|
|
183043
|
-
}
|
|
183044
|
-
resolve7(subprocess);
|
|
183045
|
-
});
|
|
183046
|
-
});
|
|
183047
|
-
}
|
|
183048
|
-
if (isFallbackAttempt) {
|
|
183049
|
-
return new Promise((resolve7, reject) => {
|
|
183050
|
-
subprocess.once("error", reject);
|
|
183051
|
-
subprocess.once("spawn", () => {
|
|
183052
|
-
subprocess.once("close", (exitCode) => {
|
|
183053
|
-
subprocess.off("error", reject);
|
|
183054
|
-
if (exitCode !== 0) {
|
|
183055
|
-
reject(new Error(`Exited with code ${exitCode}`));
|
|
183056
|
-
return;
|
|
183057
|
-
}
|
|
183058
|
-
subprocess.unref();
|
|
183059
|
-
resolve7(subprocess);
|
|
183060
|
-
});
|
|
183061
|
-
});
|
|
183062
|
-
});
|
|
183063
|
-
}
|
|
183064
|
-
subprocess.unref();
|
|
183065
|
-
return new Promise((resolve7, reject) => {
|
|
183066
|
-
subprocess.once("error", reject);
|
|
183067
|
-
subprocess.once("spawn", () => {
|
|
183068
|
-
subprocess.off("error", reject);
|
|
183069
|
-
resolve7(subprocess);
|
|
183070
|
-
});
|
|
183071
|
-
});
|
|
183072
|
-
};
|
|
183073
|
-
var open = (target, options2) => {
|
|
183074
|
-
if (typeof target !== "string") {
|
|
183075
|
-
throw new TypeError("Expected a `target`");
|
|
183076
|
-
}
|
|
183077
|
-
return baseOpen({
|
|
183078
|
-
...options2,
|
|
183079
|
-
target
|
|
183080
|
-
});
|
|
183081
|
-
};
|
|
183082
|
-
function detectArchBinary(binary) {
|
|
183083
|
-
if (typeof binary === "string" || Array.isArray(binary)) {
|
|
183084
|
-
return binary;
|
|
183085
|
-
}
|
|
183086
|
-
const { [arch]: archBinary } = binary;
|
|
183087
|
-
if (!archBinary) {
|
|
183088
|
-
throw new Error(`${arch} is not supported`);
|
|
183089
|
-
}
|
|
183090
|
-
return archBinary;
|
|
183091
|
-
}
|
|
183092
|
-
function detectPlatformBinary({ [platform2]: platformBinary }, { wsl } = {}) {
|
|
183093
|
-
if (wsl && is_wsl_default) {
|
|
183094
|
-
return detectArchBinary(wsl);
|
|
183095
|
-
}
|
|
183096
|
-
if (!platformBinary) {
|
|
183097
|
-
throw new Error(`${platform2} is not supported`);
|
|
183098
|
-
}
|
|
183099
|
-
return detectArchBinary(platformBinary);
|
|
183100
|
-
}
|
|
183101
|
-
var apps = {
|
|
183102
|
-
browser: "browser",
|
|
183103
|
-
browserPrivate: "browserPrivate"
|
|
183104
|
-
};
|
|
183105
|
-
defineLazyProperty(apps, "chrome", () => detectPlatformBinary({
|
|
183106
|
-
darwin: "google chrome",
|
|
183107
|
-
win32: "chrome",
|
|
183108
|
-
// `chromium-browser` is the older deb package name used by Ubuntu/Debian before snap.
|
|
183109
|
-
linux: ["google-chrome", "google-chrome-stable", "chromium", "chromium-browser"]
|
|
183110
|
-
}, {
|
|
183111
|
-
wsl: {
|
|
183112
|
-
ia32: "/mnt/c/Program Files (x86)/Google/Chrome/Application/chrome.exe",
|
|
183113
|
-
x64: ["/mnt/c/Program Files/Google/Chrome/Application/chrome.exe", "/mnt/c/Program Files (x86)/Google/Chrome/Application/chrome.exe"]
|
|
183114
|
-
}
|
|
183115
|
-
}));
|
|
183116
|
-
defineLazyProperty(apps, "brave", () => detectPlatformBinary({
|
|
183117
|
-
darwin: "brave browser",
|
|
183118
|
-
win32: "brave",
|
|
183119
|
-
linux: ["brave-browser", "brave"]
|
|
183120
|
-
}, {
|
|
183121
|
-
wsl: {
|
|
183122
|
-
ia32: "/mnt/c/Program Files (x86)/BraveSoftware/Brave-Browser/Application/brave.exe",
|
|
183123
|
-
x64: ["/mnt/c/Program Files/BraveSoftware/Brave-Browser/Application/brave.exe", "/mnt/c/Program Files (x86)/BraveSoftware/Brave-Browser/Application/brave.exe"]
|
|
183124
|
-
}
|
|
183125
|
-
}));
|
|
183126
|
-
defineLazyProperty(apps, "firefox", () => detectPlatformBinary({
|
|
183127
|
-
darwin: "firefox",
|
|
183128
|
-
win32: String.raw`C:\Program Files\Mozilla Firefox\firefox.exe`,
|
|
183129
|
-
linux: "firefox"
|
|
183130
|
-
}, {
|
|
183131
|
-
wsl: "/mnt/c/Program Files/Mozilla Firefox/firefox.exe"
|
|
183132
|
-
}));
|
|
183133
|
-
defineLazyProperty(apps, "edge", () => detectPlatformBinary({
|
|
183134
|
-
darwin: "microsoft edge",
|
|
183135
|
-
win32: "msedge",
|
|
183136
|
-
linux: ["microsoft-edge", "microsoft-edge-dev"]
|
|
183137
|
-
}, {
|
|
183138
|
-
wsl: "/mnt/c/Program Files (x86)/Microsoft/Edge/Application/msedge.exe"
|
|
183139
|
-
}));
|
|
183140
|
-
defineLazyProperty(apps, "safari", () => detectPlatformBinary({
|
|
183141
|
-
darwin: "Safari"
|
|
183142
|
-
}));
|
|
183143
|
-
var open_default = open;
|
|
183144
|
-
|
|
183145
183245
|
// src/lib/dev/debug-logger.ts
|
|
183146
|
-
import * as
|
|
183147
|
-
import * as
|
|
183246
|
+
import * as fs3 from "fs";
|
|
183247
|
+
import * as os2 from "os";
|
|
183248
|
+
import * as path3 from "path";
|
|
183148
183249
|
var DEBUG_LOG_PATH = ".specific/debug.log";
|
|
183149
183250
|
var logStream = null;
|
|
183150
|
-
function getLogStream() {
|
|
183151
|
-
if (logStream) {
|
|
183152
|
-
return logStream;
|
|
183153
|
-
}
|
|
183154
|
-
const logPath = path4.join(process.cwd(), DEBUG_LOG_PATH);
|
|
183155
|
-
fs8.mkdirSync(path4.dirname(logPath), { recursive: true });
|
|
183156
|
-
logStream = fs8.createWriteStream(logPath, { flags: "a" });
|
|
183157
|
-
return logStream;
|
|
183158
|
-
}
|
|
183159
183251
|
function writeLog(source, message) {
|
|
183160
|
-
const
|
|
183252
|
+
const logPath = path3.join(os2.homedir(), DEBUG_LOG_PATH);
|
|
183253
|
+
fs3.mkdirSync(path3.dirname(logPath), { recursive: true });
|
|
183161
183254
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
183162
183255
|
const line = message.endsWith("\n") ? message : message + "\n";
|
|
183163
|
-
|
|
183256
|
+
fs3.appendFileSync(logPath, `[${timestamp}] [${source}] ${line}`);
|
|
183164
183257
|
}
|
|
183165
183258
|
function pipeProcess(source, proc) {
|
|
183166
183259
|
proc.stdout?.on("data", (data) => {
|
|
@@ -183471,127 +183564,169 @@ var ApiClient = class {
|
|
|
183471
183564
|
}
|
|
183472
183565
|
};
|
|
183473
183566
|
|
|
183567
|
+
// src/lib/auth/login-flow.ts
|
|
183568
|
+
function runLoginFlow(options2) {
|
|
183569
|
+
const { setState, isReauthentication } = options2;
|
|
183570
|
+
let cancelled = false;
|
|
183571
|
+
async function run() {
|
|
183572
|
+
try {
|
|
183573
|
+
setState({ phase: "initiating" });
|
|
183574
|
+
writeLog("auth", "Starting login flow");
|
|
183575
|
+
if (isReauthentication) {
|
|
183576
|
+
clearUserCredentials();
|
|
183577
|
+
}
|
|
183578
|
+
writeLog("auth", "Initiating device authorization with WorkOS");
|
|
183579
|
+
const deviceAuth = await initiateDeviceAuthorization();
|
|
183580
|
+
writeLog(
|
|
183581
|
+
"auth",
|
|
183582
|
+
`Device authorization received: user_code=${deviceAuth.user_code}`
|
|
183583
|
+
);
|
|
183584
|
+
if (cancelled) return;
|
|
183585
|
+
setState({
|
|
183586
|
+
phase: "waiting-for-browser",
|
|
183587
|
+
userCode: deviceAuth.user_code,
|
|
183588
|
+
verificationUri: deviceAuth.verification_uri_complete
|
|
183589
|
+
});
|
|
183590
|
+
const { default: open3 } = await Promise.resolve().then(() => (init_open(), open_exports));
|
|
183591
|
+
await open3(deviceAuth.verification_uri_complete);
|
|
183592
|
+
const token = await pollUntilToken(deviceAuth, () => cancelled);
|
|
183593
|
+
if (cancelled || !token) return;
|
|
183594
|
+
writeLog("auth", "Fetching user info from platform API...");
|
|
183595
|
+
const client2 = new ApiClient(token.access_token);
|
|
183596
|
+
const user = await client2.getMe();
|
|
183597
|
+
writeLog("auth", `User info received: id=${user.id}`);
|
|
183598
|
+
if (cancelled) return;
|
|
183599
|
+
writeLog("auth", "Writing credentials to disk...");
|
|
183600
|
+
writeUserCredentials({
|
|
183601
|
+
accessToken: token.access_token,
|
|
183602
|
+
refreshToken: token.refresh_token,
|
|
183603
|
+
expiresAt: Date.now() + token.expires_in * 1e3,
|
|
183604
|
+
userId: user.id
|
|
183605
|
+
});
|
|
183606
|
+
writeLog("auth", "Credentials written successfully");
|
|
183607
|
+
setState({ phase: "success", email: token.user.email });
|
|
183608
|
+
writeLog("auth", "Login flow completed successfully");
|
|
183609
|
+
} catch (err) {
|
|
183610
|
+
if (cancelled) return;
|
|
183611
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
183612
|
+
writeLog("auth", `Login error: ${message}`);
|
|
183613
|
+
setState({ phase: "error", message });
|
|
183614
|
+
}
|
|
183615
|
+
}
|
|
183616
|
+
run();
|
|
183617
|
+
return {
|
|
183618
|
+
cancel: () => {
|
|
183619
|
+
cancelled = true;
|
|
183620
|
+
}
|
|
183621
|
+
};
|
|
183622
|
+
}
|
|
183623
|
+
async function pollUntilToken(deviceAuth, isCancelled) {
|
|
183624
|
+
let interval = deviceAuth.interval * 1e3;
|
|
183625
|
+
const expiresAt = Date.now() + deviceAuth.expires_in * 1e3;
|
|
183626
|
+
while (!isCancelled() && Date.now() < expiresAt) {
|
|
183627
|
+
await sleep(interval);
|
|
183628
|
+
if (isCancelled()) return null;
|
|
183629
|
+
writeLog(
|
|
183630
|
+
"auth",
|
|
183631
|
+
`Polling for token (timeRemaining=${Math.round((expiresAt - Date.now()) / 1e3)}s)`
|
|
183632
|
+
);
|
|
183633
|
+
const response = await pollForToken(deviceAuth.device_code);
|
|
183634
|
+
writeLog(
|
|
183635
|
+
"auth",
|
|
183636
|
+
`Poll response: ${JSON.stringify(response).substring(0, 200)}`
|
|
183637
|
+
);
|
|
183638
|
+
if (!("error" in response)) {
|
|
183639
|
+
writeLog("auth", "Token received successfully from WorkOS");
|
|
183640
|
+
return response;
|
|
183641
|
+
}
|
|
183642
|
+
if (response.error === "slow_down") {
|
|
183643
|
+
interval += 1e3;
|
|
183644
|
+
writeLog("auth", `Slowing down, new interval: ${interval}ms`);
|
|
183645
|
+
} else if (response.error !== "authorization_pending") {
|
|
183646
|
+
throw new Error(`Authentication failed: ${response.error}`);
|
|
183647
|
+
}
|
|
183648
|
+
}
|
|
183649
|
+
if (!isCancelled()) {
|
|
183650
|
+
throw new Error("Authentication timed out. Please try again.");
|
|
183651
|
+
}
|
|
183652
|
+
return null;
|
|
183653
|
+
}
|
|
183654
|
+
function sleep(ms) {
|
|
183655
|
+
return new Promise((resolve7) => setTimeout(resolve7, ms));
|
|
183656
|
+
}
|
|
183657
|
+
|
|
183474
183658
|
// src/lib/auth/login.tsx
|
|
183659
|
+
function LoginUI({
|
|
183660
|
+
state,
|
|
183661
|
+
isReauthentication
|
|
183662
|
+
}) {
|
|
183663
|
+
if (state.phase === "error") {
|
|
183664
|
+
return /* @__PURE__ */ React.createElement(Text, { color: "red" }, "Error: ", state.message);
|
|
183665
|
+
}
|
|
183666
|
+
if (state.phase === "success") {
|
|
183667
|
+
return /* @__PURE__ */ React.createElement(Text, { color: "green" }, isReauthentication ? "Re-authenticated" : "Logged in", " as ", state.email);
|
|
183668
|
+
}
|
|
183669
|
+
return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column", gap: 1 }, isReauthentication && /* @__PURE__ */ React.createElement(Text, { color: "yellow" }, "Session expired. Please log in again."), /* @__PURE__ */ React.createElement(Text, { bold: true }, "Log in to Specific"), state.phase === "waiting-for-browser" ? /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(Box, { flexDirection: "column" }, /* @__PURE__ */ React.createElement(Text, null, "Your authentication code:", " ", /* @__PURE__ */ React.createElement(Text, { color: "cyan", bold: true }, state.userCode))), /* @__PURE__ */ React.createElement(Box, null, /* @__PURE__ */ React.createElement(Text, { color: "blue" }, /* @__PURE__ */ React.createElement(Spinner, { type: "dots" })), /* @__PURE__ */ React.createElement(Text, null, " Waiting for authentication in browser...")), /* @__PURE__ */ React.createElement(Text, { dimColor: true }, "If the browser didn't open, visit: ", state.verificationUri)) : /* @__PURE__ */ React.createElement(Box, null, /* @__PURE__ */ React.createElement(Text, { color: "blue" }, /* @__PURE__ */ React.createElement(Spinner, { type: "dots" })), /* @__PURE__ */ React.createElement(Text, null, " Initiating login...")));
|
|
183670
|
+
}
|
|
183475
183671
|
function performLogin(options2 = {}) {
|
|
183476
183672
|
return new Promise((resolve7) => {
|
|
183673
|
+
let currentState = { phase: "initiating" };
|
|
183674
|
+
let flowHandle;
|
|
183477
183675
|
const instance = render(
|
|
183478
183676
|
/* @__PURE__ */ React.createElement(
|
|
183479
|
-
|
|
183677
|
+
LoginUI,
|
|
183480
183678
|
{
|
|
183481
|
-
|
|
183482
|
-
|
|
183483
|
-
instance.unmount();
|
|
183484
|
-
resolve7(result);
|
|
183485
|
-
}
|
|
183679
|
+
state: currentState,
|
|
183680
|
+
isReauthentication: options2.isReauthentication
|
|
183486
183681
|
}
|
|
183487
183682
|
)
|
|
183488
183683
|
);
|
|
183489
|
-
|
|
183490
|
-
|
|
183491
|
-
|
|
183492
|
-
|
|
183493
|
-
|
|
183494
|
-
|
|
183495
|
-
|
|
183496
|
-
|
|
183497
|
-
|
|
183498
|
-
|
|
183499
|
-
|
|
183500
|
-
|
|
183501
|
-
|
|
183502
|
-
|
|
183503
|
-
|
|
183504
|
-
|
|
183505
|
-
|
|
183506
|
-
|
|
183507
|
-
|
|
183508
|
-
|
|
183509
|
-
setUserCode(deviceAuth.user_code);
|
|
183510
|
-
setVerificationUri(deviceAuth.verification_uri_complete);
|
|
183511
|
-
setPhase("waiting");
|
|
183512
|
-
await open_default(deviceAuth.verification_uri_complete);
|
|
183513
|
-
let pollInterval = deviceAuth.interval * 1e3;
|
|
183514
|
-
const expiresAt = Date.now() + deviceAuth.expires_in * 1e3;
|
|
183515
|
-
const poll = async () => {
|
|
183516
|
-
if (cancelled || Date.now() > expiresAt) {
|
|
183517
|
-
if (!cancelled && Date.now() > expiresAt) {
|
|
183518
|
-
setError("Authentication timed out. Please try again.");
|
|
183519
|
-
setPhase("error");
|
|
183520
|
-
}
|
|
183521
|
-
return;
|
|
183522
|
-
}
|
|
183523
|
-
try {
|
|
183524
|
-
const response = await pollForToken(deviceAuth.device_code);
|
|
183525
|
-
if (cancelled) return;
|
|
183526
|
-
if ("error" in response) {
|
|
183527
|
-
if (response.error === "authorization_pending") {
|
|
183528
|
-
pollTimeoutId = setTimeout(poll, pollInterval);
|
|
183529
|
-
} else if (response.error === "slow_down") {
|
|
183530
|
-
pollInterval += 1e3;
|
|
183531
|
-
pollTimeoutId = setTimeout(poll, pollInterval);
|
|
183532
|
-
} else {
|
|
183533
|
-
setError(`Authentication failed: ${response.error}`);
|
|
183534
|
-
setPhase("error");
|
|
183535
|
-
}
|
|
183536
|
-
} else {
|
|
183537
|
-
const successResponse = response;
|
|
183538
|
-
const expiresAt2 = Date.now() + successResponse.expires_in * 1e3;
|
|
183539
|
-
const client2 = new ApiClient(successResponse.access_token);
|
|
183540
|
-
const user = await client2.getMe();
|
|
183541
|
-
writeUserCredentials({
|
|
183542
|
-
accessToken: successResponse.access_token,
|
|
183543
|
-
refreshToken: successResponse.refresh_token,
|
|
183544
|
-
expiresAt: expiresAt2,
|
|
183545
|
-
userId: user.id
|
|
183546
|
-
});
|
|
183547
|
-
setUserEmail(successResponse.user.email);
|
|
183548
|
-
setPhase("success");
|
|
183684
|
+
const cleanup = () => {
|
|
183685
|
+
flowHandle?.cancel();
|
|
183686
|
+
instance.unmount();
|
|
183687
|
+
};
|
|
183688
|
+
const handleExit = () => {
|
|
183689
|
+
cleanup();
|
|
183690
|
+
process.exit(0);
|
|
183691
|
+
};
|
|
183692
|
+
process.on("SIGINT", handleExit);
|
|
183693
|
+
process.on("SIGTERM", handleExit);
|
|
183694
|
+
flowHandle = runLoginFlow({
|
|
183695
|
+
isReauthentication: options2.isReauthentication,
|
|
183696
|
+
setState: (newState) => {
|
|
183697
|
+
currentState = newState;
|
|
183698
|
+
instance.rerender(
|
|
183699
|
+
/* @__PURE__ */ React.createElement(
|
|
183700
|
+
LoginUI,
|
|
183701
|
+
{
|
|
183702
|
+
state: currentState,
|
|
183703
|
+
isReauthentication: options2.isReauthentication
|
|
183549
183704
|
}
|
|
183550
|
-
|
|
183551
|
-
|
|
183552
|
-
|
|
183553
|
-
|
|
183554
|
-
|
|
183555
|
-
|
|
183556
|
-
|
|
183557
|
-
|
|
183558
|
-
|
|
183559
|
-
|
|
183560
|
-
|
|
183705
|
+
)
|
|
183706
|
+
);
|
|
183707
|
+
if (newState.phase === "success") {
|
|
183708
|
+
setTimeout(() => {
|
|
183709
|
+
process.off("SIGINT", handleExit);
|
|
183710
|
+
process.off("SIGTERM", handleExit);
|
|
183711
|
+
instance.unmount();
|
|
183712
|
+
resolve7({ success: true, userEmail: newState.email });
|
|
183713
|
+
}, 100);
|
|
183714
|
+
} else if (newState.phase === "error") {
|
|
183715
|
+
setTimeout(() => {
|
|
183716
|
+
process.off("SIGINT", handleExit);
|
|
183717
|
+
process.off("SIGTERM", handleExit);
|
|
183718
|
+
instance.unmount();
|
|
183719
|
+
resolve7({ success: false, error: new Error(newState.message) });
|
|
183720
|
+
}, 100);
|
|
183721
|
+
}
|
|
183561
183722
|
}
|
|
183562
|
-
}
|
|
183563
|
-
|
|
183564
|
-
return () => {
|
|
183565
|
-
cancelled = true;
|
|
183566
|
-
if (pollTimeoutId) clearTimeout(pollTimeoutId);
|
|
183567
|
-
};
|
|
183568
|
-
}, [phase, isReauthentication]);
|
|
183569
|
-
useEffect(() => {
|
|
183570
|
-
if (phase === "success") {
|
|
183571
|
-
const timer = setTimeout(() => {
|
|
183572
|
-
onComplete({ success: true, userEmail });
|
|
183573
|
-
}, 100);
|
|
183574
|
-
return () => clearTimeout(timer);
|
|
183575
|
-
}
|
|
183576
|
-
if (phase === "error") {
|
|
183577
|
-
const timer = setTimeout(() => {
|
|
183578
|
-
onComplete({ success: false, error: new Error(error) });
|
|
183579
|
-
}, 100);
|
|
183580
|
-
return () => clearTimeout(timer);
|
|
183581
|
-
}
|
|
183582
|
-
}, [phase, userEmail, error, onComplete]);
|
|
183583
|
-
if (phase === "error") {
|
|
183584
|
-
return /* @__PURE__ */ React.createElement(Text, { color: "red" }, "Error: ", error);
|
|
183585
|
-
}
|
|
183586
|
-
if (phase === "success") {
|
|
183587
|
-
return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column" }, /* @__PURE__ */ React.createElement(Text, { color: "green" }, isReauthentication ? "Re-authenticated" : "Logged in", " as ", userEmail), /* @__PURE__ */ React.createElement(Text, { dimColor: true }, "Credentials saved to ~/.specific/credentials.json"));
|
|
183588
|
-
}
|
|
183589
|
-
return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column", gap: 1 }, isReauthentication && /* @__PURE__ */ React.createElement(Text, { color: "yellow" }, "Session expired. Please log in again."), /* @__PURE__ */ React.createElement(Text, { bold: true }, "Log in to Specific"), userCode ? /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(Box, { flexDirection: "column" }, /* @__PURE__ */ React.createElement(Text, null, "Your authentication code:", " ", /* @__PURE__ */ React.createElement(Text, { color: "cyan", bold: true }, userCode))), /* @__PURE__ */ React.createElement(Box, null, /* @__PURE__ */ React.createElement(Text, { color: "blue" }, /* @__PURE__ */ React.createElement(Spinner, { type: "dots" })), /* @__PURE__ */ React.createElement(Text, null, " Waiting for authentication in browser...")), /* @__PURE__ */ React.createElement(Text, { dimColor: true }, "If the browser didn't open, visit: ", verificationUri)) : /* @__PURE__ */ React.createElement(Box, null, /* @__PURE__ */ React.createElement(Text, { color: "blue" }, /* @__PURE__ */ React.createElement(Spinner, { type: "dots" })), /* @__PURE__ */ React.createElement(Text, null, " Initiating login...")));
|
|
183723
|
+
});
|
|
183724
|
+
});
|
|
183590
183725
|
}
|
|
183591
183726
|
|
|
183592
183727
|
// src/lib/auth/credentials.ts
|
|
183593
183728
|
function getUserCredentialsDir() {
|
|
183594
|
-
return path5.join(
|
|
183729
|
+
return path5.join(os4.homedir(), ".specific");
|
|
183595
183730
|
}
|
|
183596
183731
|
function getCredentialsPath() {
|
|
183597
183732
|
return path5.join(getUserCredentialsDir(), "credentials.json");
|
|
@@ -183675,7 +183810,7 @@ function isEnabled() {
|
|
|
183675
183810
|
}
|
|
183676
183811
|
function getAnonymousId() {
|
|
183677
183812
|
if (anonymousId) return anonymousId;
|
|
183678
|
-
const machineId = `${
|
|
183813
|
+
const machineId = `${os5.hostname()}-${os5.userInfo().username}`;
|
|
183679
183814
|
anonymousId = crypto.createHash("sha256").update(machineId).digest("hex").slice(0, 16);
|
|
183680
183815
|
return anonymousId;
|
|
183681
183816
|
}
|
|
@@ -183708,7 +183843,7 @@ function trackEvent(event, properties) {
|
|
|
183708
183843
|
event,
|
|
183709
183844
|
properties: {
|
|
183710
183845
|
...properties,
|
|
183711
|
-
cli_version: "0.1.
|
|
183846
|
+
cli_version: "0.1.43",
|
|
183712
183847
|
platform: process.platform,
|
|
183713
183848
|
node_version: process.version,
|
|
183714
183849
|
project_id: getProjectId(),
|
|
@@ -183889,8 +184024,8 @@ function configureAgents(checked) {
|
|
|
183889
184024
|
return { agents, git, showManualInstructions: !!checked["other"] };
|
|
183890
184025
|
}
|
|
183891
184026
|
function InitUI() {
|
|
183892
|
-
const { exit } =
|
|
183893
|
-
const [initialState] =
|
|
184027
|
+
const { exit } = useApp();
|
|
184028
|
+
const [initialState] = useState(() => {
|
|
183894
184029
|
const detected = detectExistingAgents();
|
|
183895
184030
|
const hasDetected = Object.keys(detected).length > 0;
|
|
183896
184031
|
return {
|
|
@@ -183899,19 +184034,19 @@ function InitUI() {
|
|
|
183899
184034
|
// Focus submit if any detected
|
|
183900
184035
|
};
|
|
183901
184036
|
});
|
|
183902
|
-
const [phase, setPhase] =
|
|
184037
|
+
const [phase, setPhase] = useState(
|
|
183903
184038
|
() => caFilesExist() ? "agents" : "installing-ca"
|
|
183904
184039
|
);
|
|
183905
|
-
const [caInstallPhase, setCaInstallPhase] =
|
|
183906
|
-
const [focusedIndex, setFocusedIndex] =
|
|
183907
|
-
const [checked, setChecked] =
|
|
184040
|
+
const [caInstallPhase, setCaInstallPhase] = useState(() => caFilesExist() ? "done" : "installing");
|
|
184041
|
+
const [focusedIndex, setFocusedIndex] = useState(initialState.focusedIndex);
|
|
184042
|
+
const [checked, setChecked] = useState(
|
|
183908
184043
|
initialState.detected
|
|
183909
184044
|
);
|
|
183910
|
-
const [result, setResult] =
|
|
183911
|
-
const [tlsResult, setTlsResult] =
|
|
184045
|
+
const [result, setResult] = useState(null);
|
|
184046
|
+
const [tlsResult, setTlsResult] = useState(
|
|
183912
184047
|
caFilesExist() ? { status: "success" } : null
|
|
183913
184048
|
);
|
|
183914
|
-
|
|
184049
|
+
useEffect(() => {
|
|
183915
184050
|
if (phase === "installing-ca" && caInstallPhase === "installing") {
|
|
183916
184051
|
installCA();
|
|
183917
184052
|
}
|
|
@@ -183956,7 +184091,7 @@ function InitUI() {
|
|
|
183956
184091
|
setPhase("done");
|
|
183957
184092
|
}
|
|
183958
184093
|
});
|
|
183959
|
-
|
|
184094
|
+
useEffect(() => {
|
|
183960
184095
|
if (phase === "done") {
|
|
183961
184096
|
const timer = setTimeout(() => {
|
|
183962
184097
|
exit();
|
|
@@ -184031,7 +184166,7 @@ function resolveDocPath(path22) {
|
|
|
184031
184166
|
}
|
|
184032
184167
|
|
|
184033
184168
|
// src/commands/check.tsx
|
|
184034
|
-
import React3, { useState as
|
|
184169
|
+
import React3, { useState as useState2, useEffect as useEffect2 } from "react";
|
|
184035
184170
|
import { render as render3, Text as Text3, Box as Box3 } from "ink";
|
|
184036
184171
|
import Spinner3 from "ink-spinner";
|
|
184037
184172
|
import * as fs11 from "fs";
|
|
@@ -184369,6 +184504,22 @@ function parseStorage(data) {
|
|
|
184369
184504
|
}
|
|
184370
184505
|
return result;
|
|
184371
184506
|
}
|
|
184507
|
+
function parseConfigDevBlock(dev) {
|
|
184508
|
+
if (!dev) {
|
|
184509
|
+
return void 0;
|
|
184510
|
+
}
|
|
184511
|
+
const devArray = Array.isArray(dev) ? dev : [dev];
|
|
184512
|
+
const devObj = devArray[0];
|
|
184513
|
+
if (!devObj || typeof devObj !== "object" || Array.isArray(devObj)) {
|
|
184514
|
+
return void 0;
|
|
184515
|
+
}
|
|
184516
|
+
const fieldObj = devObj;
|
|
184517
|
+
const result = {};
|
|
184518
|
+
if (fieldObj.default !== void 0) {
|
|
184519
|
+
result.default = String(fieldObj.default);
|
|
184520
|
+
}
|
|
184521
|
+
return Object.keys(result).length > 0 ? result : void 0;
|
|
184522
|
+
}
|
|
184372
184523
|
function parseConfigs(configData) {
|
|
184373
184524
|
if (!configData || typeof configData !== "object" || Array.isArray(configData)) {
|
|
184374
184525
|
return [];
|
|
@@ -184377,6 +184528,7 @@ function parseConfigs(configData) {
|
|
|
184377
184528
|
for (const [name, fieldsArray] of Object.entries(configData)) {
|
|
184378
184529
|
const fields = Array.isArray(fieldsArray) ? fieldsArray[0] : fieldsArray;
|
|
184379
184530
|
if (!fields || typeof fields !== "object" || Array.isArray(fields)) {
|
|
184531
|
+
configs.push({ name });
|
|
184380
184532
|
continue;
|
|
184381
184533
|
}
|
|
184382
184534
|
const fieldObj = fields;
|
|
@@ -184384,10 +184536,30 @@ function parseConfigs(configData) {
|
|
|
184384
184536
|
if (fieldObj.default) {
|
|
184385
184537
|
config.default = String(fieldObj.default);
|
|
184386
184538
|
}
|
|
184539
|
+
const dev = parseConfigDevBlock(fieldObj.dev);
|
|
184540
|
+
if (dev) {
|
|
184541
|
+
config.dev = dev;
|
|
184542
|
+
}
|
|
184387
184543
|
configs.push(config);
|
|
184388
184544
|
}
|
|
184389
184545
|
return configs;
|
|
184390
184546
|
}
|
|
184547
|
+
function parseSecretDevBlock(dev) {
|
|
184548
|
+
if (!dev) {
|
|
184549
|
+
return void 0;
|
|
184550
|
+
}
|
|
184551
|
+
const devArray = Array.isArray(dev) ? dev : [dev];
|
|
184552
|
+
const devObj = devArray[0];
|
|
184553
|
+
if (!devObj || typeof devObj !== "object" || Array.isArray(devObj)) {
|
|
184554
|
+
return void 0;
|
|
184555
|
+
}
|
|
184556
|
+
const fieldObj = devObj;
|
|
184557
|
+
const result = {};
|
|
184558
|
+
if (fieldObj.required !== void 0) {
|
|
184559
|
+
result.required = fieldObj.required === true;
|
|
184560
|
+
}
|
|
184561
|
+
return Object.keys(result).length > 0 ? result : void 0;
|
|
184562
|
+
}
|
|
184391
184563
|
function parseSecrets(secretData) {
|
|
184392
184564
|
if (!secretData || typeof secretData !== "object" || Array.isArray(secretData)) {
|
|
184393
184565
|
return [];
|
|
@@ -184404,6 +184576,10 @@ function parseSecrets(secretData) {
|
|
|
184404
184576
|
if (typeof fieldObj.length === "number") {
|
|
184405
184577
|
secret.length = fieldObj.length;
|
|
184406
184578
|
}
|
|
184579
|
+
const dev = parseSecretDevBlock(fieldObj.dev);
|
|
184580
|
+
if (dev) {
|
|
184581
|
+
secret.dev = dev;
|
|
184582
|
+
}
|
|
184407
184583
|
}
|
|
184408
184584
|
secrets.push(secret);
|
|
184409
184585
|
}
|
|
@@ -184517,8 +184693,8 @@ function validateEndpointReferences(config) {
|
|
|
184517
184693
|
|
|
184518
184694
|
// src/commands/check.tsx
|
|
184519
184695
|
function CheckUI() {
|
|
184520
|
-
const [state, setState] =
|
|
184521
|
-
|
|
184696
|
+
const [state, setState] = useState2({ status: "loading" });
|
|
184697
|
+
useEffect2(() => {
|
|
184522
184698
|
async function load() {
|
|
184523
184699
|
const configPath = path7.join(process.cwd(), "specific.hcl");
|
|
184524
184700
|
if (!fs11.existsSync(configPath)) {
|
|
@@ -184558,8 +184734,8 @@ function checkCommand() {
|
|
|
184558
184734
|
}
|
|
184559
184735
|
|
|
184560
184736
|
// src/commands/dev.tsx
|
|
184561
|
-
import
|
|
184562
|
-
import { render as render4, Text as
|
|
184737
|
+
import React6, { useState as useState5, useEffect as useEffect3, useRef } from "react";
|
|
184738
|
+
import { render as render4, Text as Text6, Box as Box6, useApp as useApp2, Static } from "ink";
|
|
184563
184739
|
import Spinner4 from "ink-spinner";
|
|
184564
184740
|
import * as fs19 from "fs";
|
|
184565
184741
|
import * as path16 from "path";
|
|
@@ -186384,7 +186560,7 @@ var StablePortAllocator = class {
|
|
|
186384
186560
|
import * as fs14 from "fs";
|
|
186385
186561
|
import * as path10 from "path";
|
|
186386
186562
|
import * as net from "net";
|
|
186387
|
-
import * as
|
|
186563
|
+
import * as os7 from "os";
|
|
186388
186564
|
import { spawn } from "child_process";
|
|
186389
186565
|
|
|
186390
186566
|
// src/lib/bin/types.ts
|
|
@@ -186424,15 +186600,15 @@ var ExtractionError = class extends Error {
|
|
|
186424
186600
|
// src/lib/bin/manager.ts
|
|
186425
186601
|
import * as fs13 from "fs";
|
|
186426
186602
|
import * as path9 from "path";
|
|
186427
|
-
import * as
|
|
186603
|
+
import * as os6 from "os";
|
|
186428
186604
|
import { createReadStream } from "fs";
|
|
186429
186605
|
import { createTarExtractor, extractTo } from "tar-vern";
|
|
186430
186606
|
function getBinBaseDir() {
|
|
186431
|
-
return path9.join(
|
|
186607
|
+
return path9.join(os6.homedir(), ".specific", "bin");
|
|
186432
186608
|
}
|
|
186433
186609
|
function getPlatformInfo() {
|
|
186434
|
-
const platform5 =
|
|
186435
|
-
const arch3 =
|
|
186610
|
+
const platform5 = os6.platform();
|
|
186611
|
+
const arch3 = os6.arch();
|
|
186436
186612
|
if (platform5 !== "darwin" && platform5 !== "linux") {
|
|
186437
186613
|
throw new Error(
|
|
186438
186614
|
`Unsupported platform: ${platform5}. Only macOS and Linux are supported.`
|
|
@@ -186700,7 +186876,7 @@ function getLibraryEnv(binary) {
|
|
|
186700
186876
|
if (!binary.libraryPath) {
|
|
186701
186877
|
return {};
|
|
186702
186878
|
}
|
|
186703
|
-
const platform5 =
|
|
186879
|
+
const platform5 = os7.platform();
|
|
186704
186880
|
if (platform5 === "darwin") {
|
|
186705
186881
|
return { DYLD_LIBRARY_PATH: binary.libraryPath };
|
|
186706
186882
|
} else if (platform5 === "linux") {
|
|
@@ -186879,7 +187055,7 @@ async function waitForTcpPort(host, port, timeoutMs = 3e4) {
|
|
|
186879
187055
|
if (isOpen) {
|
|
186880
187056
|
return;
|
|
186881
187057
|
}
|
|
186882
|
-
await
|
|
187058
|
+
await sleep2(100);
|
|
186883
187059
|
}
|
|
186884
187060
|
throw new Error(`Port ${port} did not become available within timeout`);
|
|
186885
187061
|
}
|
|
@@ -186920,7 +187096,7 @@ async function stopProcess(proc) {
|
|
|
186920
187096
|
}, 2e3);
|
|
186921
187097
|
});
|
|
186922
187098
|
}
|
|
186923
|
-
function
|
|
187099
|
+
function sleep2(ms) {
|
|
186924
187100
|
return new Promise((resolve7) => setTimeout(resolve7, ms));
|
|
186925
187101
|
}
|
|
186926
187102
|
|
|
@@ -186986,7 +187162,7 @@ async function saveGeneratedSecret(name, value) {
|
|
|
186986
187162
|
}
|
|
186987
187163
|
await writeFile(GENERATED_SECRETS_FILE, JSON.stringify(secrets, null, 2) + "\n");
|
|
186988
187164
|
}
|
|
186989
|
-
async function prepareSecrets(secretsConfig) {
|
|
187165
|
+
async function prepareSecrets(secretsConfig, isDevMode = false) {
|
|
186990
187166
|
const userSecrets = await loadSecrets();
|
|
186991
187167
|
const generatedSecrets = await loadGeneratedSecrets();
|
|
186992
187168
|
const finalSecrets = /* @__PURE__ */ new Map();
|
|
@@ -187003,10 +187179,57 @@ async function prepareSecrets(secretsConfig) {
|
|
|
187003
187179
|
await saveGeneratedSecret(secretDef.name, generatedValue);
|
|
187004
187180
|
}
|
|
187005
187181
|
finalSecrets.set(secretDef.name, generatedValue);
|
|
187182
|
+
continue;
|
|
187183
|
+
}
|
|
187184
|
+
if (isDevMode && secretDef.dev?.required === false) {
|
|
187185
|
+
finalSecrets.set(secretDef.name, "");
|
|
187186
|
+
continue;
|
|
187006
187187
|
}
|
|
187007
187188
|
}
|
|
187008
187189
|
return finalSecrets;
|
|
187009
187190
|
}
|
|
187191
|
+
var HEADER_COMMENT = "# Do not commit this file - it contains secrets\n\n";
|
|
187192
|
+
async function saveSecret(name, value) {
|
|
187193
|
+
let content = "";
|
|
187194
|
+
if (existsSync10(SECRETS_FILE)) {
|
|
187195
|
+
content = await readFile(SECRETS_FILE, "utf-8");
|
|
187196
|
+
} else {
|
|
187197
|
+
content = HEADER_COMMENT;
|
|
187198
|
+
}
|
|
187199
|
+
const escapedValue = value.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
|
|
187200
|
+
const secretPattern = new RegExp(`^${name}\\s*=\\s*"[^"]*"\\s*$`, "m");
|
|
187201
|
+
if (secretPattern.test(content)) {
|
|
187202
|
+
content = content.replace(secretPattern, `${name} = "${escapedValue}"`);
|
|
187203
|
+
} else {
|
|
187204
|
+
content = content.trimEnd() + `
|
|
187205
|
+
${name} = "${escapedValue}"
|
|
187206
|
+
`;
|
|
187207
|
+
}
|
|
187208
|
+
await writeFile(SECRETS_FILE, content);
|
|
187209
|
+
}
|
|
187210
|
+
function findUsedSecrets(services, isDevMode) {
|
|
187211
|
+
const used = /* @__PURE__ */ new Set();
|
|
187212
|
+
for (const service of services) {
|
|
187213
|
+
const mergedEnv = isDevMode ? { ...service.env, ...service.dev?.env } : service.env;
|
|
187214
|
+
for (const value of Object.values(mergedEnv ?? {})) {
|
|
187215
|
+
if (typeof value === "object" && value.type === "secret") {
|
|
187216
|
+
used.add(value.name);
|
|
187217
|
+
}
|
|
187218
|
+
}
|
|
187219
|
+
}
|
|
187220
|
+
return used;
|
|
187221
|
+
}
|
|
187222
|
+
function findMissingSecrets(secretsDef, preparedSecrets, usedSecrets) {
|
|
187223
|
+
const missing = [];
|
|
187224
|
+
for (const secret of secretsDef) {
|
|
187225
|
+
if (secret.generated) continue;
|
|
187226
|
+
if (usedSecrets && !usedSecrets.has(secret.name)) continue;
|
|
187227
|
+
if (!preparedSecrets.has(secret.name)) {
|
|
187228
|
+
missing.push(secret.name);
|
|
187229
|
+
}
|
|
187230
|
+
}
|
|
187231
|
+
return missing;
|
|
187232
|
+
}
|
|
187010
187233
|
|
|
187011
187234
|
// src/lib/config/parser.ts
|
|
187012
187235
|
var import_hcl2_json_parser3 = __toESM(require_dist(), 1);
|
|
@@ -187034,7 +187257,28 @@ async function loadConfigs() {
|
|
|
187034
187257
|
const content = await readFile2(CONFIG_FILE, "utf-8");
|
|
187035
187258
|
return await parseConfigFile(content);
|
|
187036
187259
|
}
|
|
187037
|
-
async function
|
|
187260
|
+
async function saveConfig(name, value) {
|
|
187261
|
+
let content = "";
|
|
187262
|
+
if (existsSync11(CONFIG_FILE)) {
|
|
187263
|
+
content = await readFile2(CONFIG_FILE, "utf-8");
|
|
187264
|
+
} else {
|
|
187265
|
+
content = `# Configuration values for this project
|
|
187266
|
+
# These values override defaults defined in specific.hcl
|
|
187267
|
+
|
|
187268
|
+
`;
|
|
187269
|
+
}
|
|
187270
|
+
const escapedValue = value.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
|
|
187271
|
+
const configPattern = new RegExp(`^${name}\\s*=\\s*"[^"]*"\\s*$`, "m");
|
|
187272
|
+
if (configPattern.test(content)) {
|
|
187273
|
+
content = content.replace(configPattern, `${name} = "${escapedValue}"`);
|
|
187274
|
+
} else {
|
|
187275
|
+
content = content.trimEnd() + `
|
|
187276
|
+
${name} = "${escapedValue}"
|
|
187277
|
+
`;
|
|
187278
|
+
}
|
|
187279
|
+
await writeFile2(CONFIG_FILE, content);
|
|
187280
|
+
}
|
|
187281
|
+
async function prepareConfigs(configsDef, environmentOverrides, isDevMode = false) {
|
|
187038
187282
|
const userConfigs = await loadConfigs();
|
|
187039
187283
|
const finalConfigs = /* @__PURE__ */ new Map();
|
|
187040
187284
|
for (const configDef of configsDef) {
|
|
@@ -187048,13 +187292,36 @@ async function prepareConfigs(configsDef, environmentOverrides) {
|
|
|
187048
187292
|
finalConfigs.set(configDef.name, envOverride);
|
|
187049
187293
|
continue;
|
|
187050
187294
|
}
|
|
187051
|
-
|
|
187052
|
-
|
|
187295
|
+
const effectiveDefault = isDevMode && configDef.dev?.default !== void 0 ? configDef.dev.default : configDef.default;
|
|
187296
|
+
if (effectiveDefault !== void 0) {
|
|
187297
|
+
finalConfigs.set(configDef.name, effectiveDefault);
|
|
187053
187298
|
continue;
|
|
187054
187299
|
}
|
|
187055
187300
|
}
|
|
187056
187301
|
return finalConfigs;
|
|
187057
187302
|
}
|
|
187303
|
+
function findUsedConfigs(services, isDevMode) {
|
|
187304
|
+
const used = /* @__PURE__ */ new Set();
|
|
187305
|
+
for (const service of services) {
|
|
187306
|
+
const mergedEnv = isDevMode ? { ...service.env, ...service.dev?.env } : service.env;
|
|
187307
|
+
for (const value of Object.values(mergedEnv ?? {})) {
|
|
187308
|
+
if (typeof value === "object" && value.type === "config") {
|
|
187309
|
+
used.add(value.name);
|
|
187310
|
+
}
|
|
187311
|
+
}
|
|
187312
|
+
}
|
|
187313
|
+
return used;
|
|
187314
|
+
}
|
|
187315
|
+
function findMissingConfigs(configsDef, preparedConfigs, usedConfigs) {
|
|
187316
|
+
const missing = [];
|
|
187317
|
+
for (const config of configsDef) {
|
|
187318
|
+
if (usedConfigs && !usedConfigs.has(config.name)) continue;
|
|
187319
|
+
if (!preparedConfigs.has(config.name)) {
|
|
187320
|
+
missing.push(config.name);
|
|
187321
|
+
}
|
|
187322
|
+
}
|
|
187323
|
+
return missing;
|
|
187324
|
+
}
|
|
187058
187325
|
|
|
187059
187326
|
// src/lib/dev/env-resolver.ts
|
|
187060
187327
|
var MissingSecretError = class extends Error {
|
|
@@ -187124,7 +187391,7 @@ function resolveEnvValue(value, resources, secrets, configs, servicePort, servic
|
|
|
187124
187391
|
}
|
|
187125
187392
|
switch (serviceRef.attribute) {
|
|
187126
187393
|
case "url":
|
|
187127
|
-
return `
|
|
187394
|
+
return `localhost:${endpoint.port}`;
|
|
187128
187395
|
case "host":
|
|
187129
187396
|
return "localhost";
|
|
187130
187397
|
case "port":
|
|
@@ -187983,7 +188250,7 @@ async function waitForTcpPort2(host, port, timeoutMs = 3e4) {
|
|
|
187983
188250
|
if (isOpen) {
|
|
187984
188251
|
return;
|
|
187985
188252
|
}
|
|
187986
|
-
await
|
|
188253
|
+
await sleep3(100);
|
|
187987
188254
|
}
|
|
187988
188255
|
throw new Error(`Electric port ${port} did not become available within timeout`);
|
|
187989
188256
|
}
|
|
@@ -188024,7 +188291,7 @@ async function stopProcess2(proc) {
|
|
|
188024
188291
|
}, 2e3);
|
|
188025
188292
|
});
|
|
188026
188293
|
}
|
|
188027
|
-
function
|
|
188294
|
+
function sleep3(ms) {
|
|
188028
188295
|
return new Promise((resolve7) => setTimeout(resolve7, ms));
|
|
188029
188296
|
}
|
|
188030
188297
|
|
|
@@ -188102,7 +188369,7 @@ async function waitForTcpPort3(host, port, timeoutMs = 3e4) {
|
|
|
188102
188369
|
if (isOpen) {
|
|
188103
188370
|
return;
|
|
188104
188371
|
}
|
|
188105
|
-
await
|
|
188372
|
+
await sleep4(100);
|
|
188106
188373
|
}
|
|
188107
188374
|
throw new Error(
|
|
188108
188375
|
`Drizzle Gateway port ${port} did not become available within timeout`
|
|
@@ -188145,7 +188412,7 @@ async function stopProcess3(proc) {
|
|
|
188145
188412
|
}, 2e3);
|
|
188146
188413
|
});
|
|
188147
188414
|
}
|
|
188148
|
-
function
|
|
188415
|
+
function sleep4(ms) {
|
|
188149
188416
|
return new Promise((resolve7) => setTimeout(resolve7, ms));
|
|
188150
188417
|
}
|
|
188151
188418
|
|
|
@@ -188340,7 +188607,7 @@ function watchConfigFile(configPath, debounceMs, onChange) {
|
|
|
188340
188607
|
// src/lib/dev/proxy-registry.ts
|
|
188341
188608
|
import * as fs18 from "fs";
|
|
188342
188609
|
import * as path15 from "path";
|
|
188343
|
-
import * as
|
|
188610
|
+
import * as os8 from "os";
|
|
188344
188611
|
var ProxyRegistryManager = class {
|
|
188345
188612
|
proxyDir;
|
|
188346
188613
|
ownerPath;
|
|
@@ -188349,7 +188616,7 @@ var ProxyRegistryManager = class {
|
|
|
188349
188616
|
isOwner = false;
|
|
188350
188617
|
registryWatcher = null;
|
|
188351
188618
|
constructor() {
|
|
188352
|
-
this.proxyDir = path15.join(
|
|
188619
|
+
this.proxyDir = path15.join(os8.homedir(), ".specific", "proxy");
|
|
188353
188620
|
this.ownerPath = path15.join(this.proxyDir, "owner.json");
|
|
188354
188621
|
this.registryPath = path15.join(this.proxyDir, "registry.json");
|
|
188355
188622
|
this.lockPath = path15.join(this.proxyDir, "registry.lock");
|
|
@@ -188659,11 +188926,58 @@ var ProxyRegistryManager = class {
|
|
|
188659
188926
|
}
|
|
188660
188927
|
};
|
|
188661
188928
|
|
|
188929
|
+
// src/lib/ui/SecretInput.tsx
|
|
188930
|
+
import React4, { useState as useState3 } from "react";
|
|
188931
|
+
import { Box as Box4, Text as Text4, useInput as useInput2 } from "ink";
|
|
188932
|
+
function SecretInput({ secretName, onSubmit, onCancel }) {
|
|
188933
|
+
const [value, setValue] = useState3("");
|
|
188934
|
+
useInput2((input, key) => {
|
|
188935
|
+
if (key.return) {
|
|
188936
|
+
if (value.trim() !== "") {
|
|
188937
|
+
onSubmit(value);
|
|
188938
|
+
}
|
|
188939
|
+
} else if (key.escape) {
|
|
188940
|
+
onCancel();
|
|
188941
|
+
} else if (key.backspace || key.delete) {
|
|
188942
|
+
setValue((prev) => prev.slice(0, -1));
|
|
188943
|
+
} else if (!key.ctrl && !key.meta && input) {
|
|
188944
|
+
setValue((prev) => prev + input);
|
|
188945
|
+
}
|
|
188946
|
+
});
|
|
188947
|
+
return /* @__PURE__ */ React4.createElement(Box4, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React4.createElement(Text4, null, "Enter value for secret ", /* @__PURE__ */ React4.createElement(Text4, { color: "cyan" }, secretName), ":"), /* @__PURE__ */ React4.createElement(Box4, null, /* @__PURE__ */ React4.createElement(Text4, { color: "cyan" }, "> "), /* @__PURE__ */ React4.createElement(Text4, null, value.length > 0 ? "*".repeat(value.length) : ""), /* @__PURE__ */ React4.createElement(Text4, { color: "gray" }, "|")), /* @__PURE__ */ React4.createElement(Text4, { dimColor: true }, "(Press Enter to save, Esc to cancel)"));
|
|
188948
|
+
}
|
|
188949
|
+
|
|
188950
|
+
// src/lib/ui/ConfigInput.tsx
|
|
188951
|
+
import React5, { useState as useState4 } from "react";
|
|
188952
|
+
import { Box as Box5, Text as Text5, useInput as useInput3 } from "ink";
|
|
188953
|
+
function ConfigInput({ configName, onSubmit, onCancel }) {
|
|
188954
|
+
const [value, setValue] = useState4("");
|
|
188955
|
+
useInput3((input, key) => {
|
|
188956
|
+
if (key.return) {
|
|
188957
|
+
if (value.trim() !== "") {
|
|
188958
|
+
onSubmit(value);
|
|
188959
|
+
}
|
|
188960
|
+
} else if (key.escape) {
|
|
188961
|
+
onCancel();
|
|
188962
|
+
} else if (key.backspace || key.delete) {
|
|
188963
|
+
setValue((prev) => prev.slice(0, -1));
|
|
188964
|
+
} else if (!key.ctrl && !key.meta && input) {
|
|
188965
|
+
setValue((prev) => prev + input);
|
|
188966
|
+
}
|
|
188967
|
+
});
|
|
188968
|
+
return /* @__PURE__ */ React5.createElement(Box5, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React5.createElement(Text5, null, "Enter value for config ", /* @__PURE__ */ React5.createElement(Text5, { color: "cyan" }, configName), ":"), /* @__PURE__ */ React5.createElement(Box5, null, /* @__PURE__ */ React5.createElement(Text5, { color: "cyan" }, "> "), /* @__PURE__ */ React5.createElement(Text5, null, value), /* @__PURE__ */ React5.createElement(Text5, { color: "gray" }, "|")), /* @__PURE__ */ React5.createElement(Text5, { dimColor: true }, "(Press Enter to save, Esc to cancel)"));
|
|
188969
|
+
}
|
|
188970
|
+
|
|
188971
|
+
// src/lib/ui/interactive.ts
|
|
188972
|
+
function isInteractive() {
|
|
188973
|
+
return process.stdin.isTTY === true && process.stdout.isTTY === true;
|
|
188974
|
+
}
|
|
188975
|
+
|
|
188662
188976
|
// src/commands/dev.tsx
|
|
188663
188977
|
var COLORS = ["cyan", "yellow", "green", "magenta", "blue"];
|
|
188664
188978
|
function DevUI({ instanceKey }) {
|
|
188665
|
-
const { exit } =
|
|
188666
|
-
const [state, setState] =
|
|
188979
|
+
const { exit } = useApp2();
|
|
188980
|
+
const [state, setState] = useState5(() => {
|
|
188667
188981
|
const caExists = caFilesExist();
|
|
188668
188982
|
return {
|
|
188669
188983
|
status: caExists ? "loading" : "installing-ca",
|
|
@@ -188676,7 +188990,7 @@ function DevUI({ instanceKey }) {
|
|
|
188676
188990
|
isProxyOwner: false
|
|
188677
188991
|
};
|
|
188678
188992
|
});
|
|
188679
|
-
|
|
188993
|
+
useEffect3(() => {
|
|
188680
188994
|
if (state.status === "installing-ca" && state.caInstallPhase === "installing") {
|
|
188681
188995
|
installCA();
|
|
188682
188996
|
}
|
|
@@ -188709,8 +189023,8 @@ function DevUI({ instanceKey }) {
|
|
|
188709
189023
|
const adminServerRef = useRef(null);
|
|
188710
189024
|
const servicesRef = useRef([]);
|
|
188711
189025
|
const resourcesRef = useRef(/* @__PURE__ */ new Map());
|
|
188712
|
-
const [reloadTrigger, setReloadTrigger] =
|
|
188713
|
-
const [readyToStart, setReadyToStart] =
|
|
189026
|
+
const [reloadTrigger, setReloadTrigger] = useState5(0);
|
|
189027
|
+
const [readyToStart, setReadyToStart] = useState5(() => caFilesExist());
|
|
188714
189028
|
const shutdown2 = async () => {
|
|
188715
189029
|
if (shuttingDown.current) return;
|
|
188716
189030
|
shuttingDown.current = true;
|
|
@@ -188802,7 +189116,7 @@ function DevUI({ instanceKey }) {
|
|
|
188802
189116
|
}));
|
|
188803
189117
|
setReloadTrigger((t) => t + 1);
|
|
188804
189118
|
};
|
|
188805
|
-
|
|
189119
|
+
useEffect3(() => {
|
|
188806
189120
|
const handleSignal = () => {
|
|
188807
189121
|
if (shuttingDown.current) {
|
|
188808
189122
|
writeLog("system", "Force shutting down");
|
|
@@ -188831,13 +189145,13 @@ function DevUI({ instanceKey }) {
|
|
|
188831
189145
|
process.off("SIGTERM", handleSignal);
|
|
188832
189146
|
};
|
|
188833
189147
|
}, []);
|
|
188834
|
-
|
|
189148
|
+
useEffect3(() => {
|
|
188835
189149
|
if (state.status === "running" && !startTimeRef.current) {
|
|
188836
189150
|
startTimeRef.current = Date.now();
|
|
188837
189151
|
trackEvent("dev_started");
|
|
188838
189152
|
}
|
|
188839
189153
|
}, [state.status]);
|
|
188840
|
-
|
|
189154
|
+
useEffect3(() => {
|
|
188841
189155
|
if (state.status !== "running") return;
|
|
188842
189156
|
const configPath = path16.join(process.cwd(), "specific.hcl");
|
|
188843
189157
|
const watcher = watchConfigFile(configPath, 1e3, () => {
|
|
@@ -188872,7 +189186,66 @@ function DevUI({ instanceKey }) {
|
|
|
188872
189186
|
]
|
|
188873
189187
|
}));
|
|
188874
189188
|
};
|
|
188875
|
-
|
|
189189
|
+
const handleSecretSubmit = async (value) => {
|
|
189190
|
+
const currentSecret = state.missingSecrets?.[state.currentSecretIndex ?? 0];
|
|
189191
|
+
if (!currentSecret) return;
|
|
189192
|
+
await saveSecret(currentSecret, value);
|
|
189193
|
+
const nextIndex = (state.currentSecretIndex ?? 0) + 1;
|
|
189194
|
+
if (nextIndex < (state.missingSecrets?.length ?? 0)) {
|
|
189195
|
+
setState((s) => ({
|
|
189196
|
+
...s,
|
|
189197
|
+
currentSecretIndex: nextIndex
|
|
189198
|
+
}));
|
|
189199
|
+
} else if (state.missingConfigs && state.missingConfigs.length > 0) {
|
|
189200
|
+
setState((s) => ({
|
|
189201
|
+
...s,
|
|
189202
|
+
status: "awaiting-configs",
|
|
189203
|
+
missingSecrets: void 0,
|
|
189204
|
+
currentSecretIndex: void 0,
|
|
189205
|
+
currentConfigIndex: 0
|
|
189206
|
+
}));
|
|
189207
|
+
} else {
|
|
189208
|
+
setState((s) => ({
|
|
189209
|
+
...s,
|
|
189210
|
+
status: "loading",
|
|
189211
|
+
missingSecrets: void 0,
|
|
189212
|
+
currentSecretIndex: void 0
|
|
189213
|
+
}));
|
|
189214
|
+
setReloadTrigger((t) => t + 1);
|
|
189215
|
+
}
|
|
189216
|
+
};
|
|
189217
|
+
const handleConfigSubmit = async (value) => {
|
|
189218
|
+
const currentConfig = state.missingConfigs?.[state.currentConfigIndex ?? 0];
|
|
189219
|
+
if (!currentConfig) return;
|
|
189220
|
+
await saveConfig(currentConfig, value);
|
|
189221
|
+
const nextIndex = (state.currentConfigIndex ?? 0) + 1;
|
|
189222
|
+
if (nextIndex < (state.missingConfigs?.length ?? 0)) {
|
|
189223
|
+
setState((s) => ({
|
|
189224
|
+
...s,
|
|
189225
|
+
currentConfigIndex: nextIndex
|
|
189226
|
+
}));
|
|
189227
|
+
} else {
|
|
189228
|
+
setState((s) => ({
|
|
189229
|
+
...s,
|
|
189230
|
+
status: "loading",
|
|
189231
|
+
missingConfigs: void 0,
|
|
189232
|
+
currentConfigIndex: void 0
|
|
189233
|
+
}));
|
|
189234
|
+
setReloadTrigger((t) => t + 1);
|
|
189235
|
+
}
|
|
189236
|
+
};
|
|
189237
|
+
const handleInputCancel = () => {
|
|
189238
|
+
setState((s) => ({
|
|
189239
|
+
...s,
|
|
189240
|
+
status: "error",
|
|
189241
|
+
error: "Startup cancelled - required values not provided",
|
|
189242
|
+
missingSecrets: void 0,
|
|
189243
|
+
currentSecretIndex: void 0,
|
|
189244
|
+
missingConfigs: void 0,
|
|
189245
|
+
currentConfigIndex: void 0
|
|
189246
|
+
}));
|
|
189247
|
+
};
|
|
189248
|
+
useEffect3(() => {
|
|
188876
189249
|
if (!readyToStart) {
|
|
188877
189250
|
return;
|
|
188878
189251
|
}
|
|
@@ -189047,8 +189420,50 @@ function DevUI({ instanceKey }) {
|
|
|
189047
189420
|
}
|
|
189048
189421
|
}
|
|
189049
189422
|
if (cancelled) return;
|
|
189050
|
-
const secrets = await prepareSecrets(config2.secrets);
|
|
189051
|
-
const configs = await prepareConfigs(config2.configs);
|
|
189423
|
+
const secrets = await prepareSecrets(config2.secrets, true);
|
|
189424
|
+
const configs = await prepareConfigs(config2.configs, void 0, true);
|
|
189425
|
+
const usedSecrets = findUsedSecrets(config2.services, true);
|
|
189426
|
+
const usedConfigs = findUsedConfigs(config2.services, true);
|
|
189427
|
+
const missingSecrets = findMissingSecrets(config2.secrets, secrets, usedSecrets);
|
|
189428
|
+
const missingConfigs = findMissingConfigs(config2.configs, configs, usedConfigs);
|
|
189429
|
+
if (missingSecrets.length > 0 || missingConfigs.length > 0) {
|
|
189430
|
+
if (isInteractive()) {
|
|
189431
|
+
if (missingSecrets.length > 0) {
|
|
189432
|
+
setState((s) => ({
|
|
189433
|
+
...s,
|
|
189434
|
+
status: "awaiting-secrets",
|
|
189435
|
+
missingSecrets,
|
|
189436
|
+
currentSecretIndex: 0,
|
|
189437
|
+
missingConfigs: missingConfigs.length > 0 ? missingConfigs : void 0
|
|
189438
|
+
}));
|
|
189439
|
+
return;
|
|
189440
|
+
} else {
|
|
189441
|
+
setState((s) => ({
|
|
189442
|
+
...s,
|
|
189443
|
+
status: "awaiting-configs",
|
|
189444
|
+
missingConfigs,
|
|
189445
|
+
currentConfigIndex: 0
|
|
189446
|
+
}));
|
|
189447
|
+
return;
|
|
189448
|
+
}
|
|
189449
|
+
} else {
|
|
189450
|
+
const errorParts = [];
|
|
189451
|
+
if (missingSecrets.length > 0) {
|
|
189452
|
+
errorParts.push(`Missing secrets: ${missingSecrets.join(", ")}
|
|
189453
|
+
Add them to specific.secrets`);
|
|
189454
|
+
}
|
|
189455
|
+
if (missingConfigs.length > 0) {
|
|
189456
|
+
errorParts.push(`Missing configs: ${missingConfigs.join(", ")}
|
|
189457
|
+
Add them to specific.config`);
|
|
189458
|
+
}
|
|
189459
|
+
setState((s) => ({
|
|
189460
|
+
...s,
|
|
189461
|
+
status: "error",
|
|
189462
|
+
error: errorParts.join("\n\n")
|
|
189463
|
+
}));
|
|
189464
|
+
return;
|
|
189465
|
+
}
|
|
189466
|
+
}
|
|
189052
189467
|
const validationErrors = validateEndpointReferences(config2);
|
|
189053
189468
|
if (validationErrors.length > 0) {
|
|
189054
189469
|
for (const error of validationErrors) {
|
|
@@ -189334,33 +189749,57 @@ function DevUI({ instanceKey }) {
|
|
|
189334
189749
|
}, [reloadTrigger, readyToStart, instanceKey]);
|
|
189335
189750
|
if (state.status === "installing-ca") {
|
|
189336
189751
|
if (state.caInstallPhase === "installing") {
|
|
189337
|
-
return /* @__PURE__ */
|
|
189752
|
+
return /* @__PURE__ */ React6.createElement(Box6, { flexDirection: "column" }, /* @__PURE__ */ React6.createElement(Text6, { bold: true, color: "cyan" }, "TLS Certificate Setup"), /* @__PURE__ */ React6.createElement(Text6, null, " "), /* @__PURE__ */ React6.createElement(Text6, null, "Installing a local certificate authority (CA) to enable HTTPS"), /* @__PURE__ */ React6.createElement(Text6, null, "for local development. The CA is limited to Specific projects."), /* @__PURE__ */ React6.createElement(Text6, null, " "), /* @__PURE__ */ React6.createElement(Text6, null, "Your password is required to add the CA to your system's trust store."), /* @__PURE__ */ React6.createElement(Text6, null, " "));
|
|
189338
189753
|
}
|
|
189339
189754
|
if (state.caInstallPhase === "error") {
|
|
189340
|
-
return /* @__PURE__ */
|
|
189755
|
+
return /* @__PURE__ */ React6.createElement(Box6, { flexDirection: "column" }, /* @__PURE__ */ React6.createElement(Text6, { color: "red" }, "Failed to install CA: ", state.caError));
|
|
189341
189756
|
}
|
|
189342
189757
|
}
|
|
189343
189758
|
if (state.status === "loading") {
|
|
189344
|
-
return /* @__PURE__ */
|
|
189759
|
+
return /* @__PURE__ */ React6.createElement(Box6, null, /* @__PURE__ */ React6.createElement(Text6, { color: "blue" }, /* @__PURE__ */ React6.createElement(Spinner4, { type: "dots" })));
|
|
189760
|
+
}
|
|
189761
|
+
if (state.status === "awaiting-secrets" && state.missingSecrets && state.currentSecretIndex !== void 0) {
|
|
189762
|
+
const currentSecret = state.missingSecrets[state.currentSecretIndex];
|
|
189763
|
+
return /* @__PURE__ */ React6.createElement(Box6, { flexDirection: "column" }, /* @__PURE__ */ React6.createElement(Text6, null, /* @__PURE__ */ React6.createElement(Text6, { bold: true, color: "cyan" }, "Specific dev server")), /* @__PURE__ */ React6.createElement(Text6, null, " "), /* @__PURE__ */ React6.createElement(Text6, null, "Missing secrets (", state.currentSecretIndex + 1, "/", state.missingSecrets.length, "):"), /* @__PURE__ */ React6.createElement(
|
|
189764
|
+
SecretInput,
|
|
189765
|
+
{
|
|
189766
|
+
key: currentSecret,
|
|
189767
|
+
secretName: currentSecret,
|
|
189768
|
+
onSubmit: handleSecretSubmit,
|
|
189769
|
+
onCancel: handleInputCancel
|
|
189770
|
+
}
|
|
189771
|
+
));
|
|
189772
|
+
}
|
|
189773
|
+
if (state.status === "awaiting-configs" && state.missingConfigs && state.currentConfigIndex !== void 0) {
|
|
189774
|
+
const currentConfig = state.missingConfigs[state.currentConfigIndex];
|
|
189775
|
+
return /* @__PURE__ */ React6.createElement(Box6, { flexDirection: "column" }, /* @__PURE__ */ React6.createElement(Text6, null, /* @__PURE__ */ React6.createElement(Text6, { bold: true, color: "cyan" }, "Specific dev server")), /* @__PURE__ */ React6.createElement(Text6, null, " "), /* @__PURE__ */ React6.createElement(Text6, null, "Missing configs (", state.currentConfigIndex + 1, "/", state.missingConfigs.length, "):"), /* @__PURE__ */ React6.createElement(
|
|
189776
|
+
ConfigInput,
|
|
189777
|
+
{
|
|
189778
|
+
key: currentConfig,
|
|
189779
|
+
configName: currentConfig,
|
|
189780
|
+
onSubmit: handleConfigSubmit,
|
|
189781
|
+
onCancel: handleInputCancel
|
|
189782
|
+
}
|
|
189783
|
+
));
|
|
189345
189784
|
}
|
|
189346
189785
|
if (state.status === "waiting") {
|
|
189347
|
-
return /* @__PURE__ */
|
|
189786
|
+
return /* @__PURE__ */ React6.createElement(Box6, { flexDirection: "column" }, /* @__PURE__ */ React6.createElement(Text6, null, /* @__PURE__ */ React6.createElement(Text6, { color: "yellow" }, /* @__PURE__ */ React6.createElement(Spinner4, { type: "dots" })), /* @__PURE__ */ React6.createElement(Text6, null, " No specific.hcl in project yet. Go build something with your coding agent!")));
|
|
189348
189787
|
}
|
|
189349
189788
|
if (state.status === "error") {
|
|
189350
|
-
return /* @__PURE__ */
|
|
189789
|
+
return /* @__PURE__ */ React6.createElement(Box6, { flexDirection: "column" }, /* @__PURE__ */ React6.createElement(Text6, { color: "red" }, "Error: ", state.error));
|
|
189351
189790
|
}
|
|
189352
189791
|
if (state.status === "stopping") {
|
|
189353
|
-
return /* @__PURE__ */
|
|
189792
|
+
return /* @__PURE__ */ React6.createElement(Box6, null, /* @__PURE__ */ React6.createElement(Text6, { color: "yellow" }, /* @__PURE__ */ React6.createElement(Spinner4, { type: "dots" })), /* @__PURE__ */ React6.createElement(Text6, null, " Shutting down..."));
|
|
189354
189793
|
}
|
|
189355
189794
|
if (state.status === "reloading") {
|
|
189356
|
-
return /* @__PURE__ */
|
|
189795
|
+
return /* @__PURE__ */ React6.createElement(Box6, { flexDirection: "column" }, /* @__PURE__ */ React6.createElement(Text6, null, /* @__PURE__ */ React6.createElement(Text6, { bold: true, color: "cyan" }, "Specific dev server")), /* @__PURE__ */ React6.createElement(Text6, null, " "), /* @__PURE__ */ React6.createElement(Box6, null, /* @__PURE__ */ React6.createElement(Text6, { color: "yellow" }, /* @__PURE__ */ React6.createElement(Spinner4, { type: "dots" })), /* @__PURE__ */ React6.createElement(Text6, null, " Reloading (specific.hcl changed)...")));
|
|
189357
189796
|
}
|
|
189358
189797
|
const { config, resources, services, proxy, output } = state;
|
|
189359
189798
|
if (!config) {
|
|
189360
|
-
return /* @__PURE__ */
|
|
189799
|
+
return /* @__PURE__ */ React6.createElement(Box6, null, /* @__PURE__ */ React6.createElement(Text6, { color: "blue" }, /* @__PURE__ */ React6.createElement(Spinner4, { type: "dots" })));
|
|
189361
189800
|
}
|
|
189362
189801
|
if (state.status === "starting") {
|
|
189363
|
-
return /* @__PURE__ */
|
|
189802
|
+
return /* @__PURE__ */ React6.createElement(Box6, { flexDirection: "column" }, /* @__PURE__ */ React6.createElement(Text6, null, /* @__PURE__ */ React6.createElement(Text6, { bold: true, color: "cyan" }, "Specific dev server"), /* @__PURE__ */ React6.createElement(Text6, { dimColor: true }, " (Ctrl+C to stop)")), /* @__PURE__ */ React6.createElement(Text6, null, " "), (config.postgres.length > 0 || config.redis.length > 0 || config.storage.length > 0) && /* @__PURE__ */ React6.createElement(React6.Fragment, null, /* @__PURE__ */ React6.createElement(Text6, { bold: true }, "Resources:"), config.postgres.map((pg) => {
|
|
189364
189803
|
const instance = resources.get(pg.name);
|
|
189365
189804
|
const resStatus = state.resourceStatus.get(pg.name);
|
|
189366
189805
|
const isReady = !!instance;
|
|
@@ -189375,7 +189814,7 @@ function DevUI({ instanceKey }) {
|
|
|
189375
189814
|
} else if (resStatus?.status === "starting") {
|
|
189376
189815
|
statusText = " starting...";
|
|
189377
189816
|
}
|
|
189378
|
-
return /* @__PURE__ */
|
|
189817
|
+
return /* @__PURE__ */ React6.createElement(Text6, { key: pg.name }, /* @__PURE__ */ React6.createElement(Text6, { color: isReady ? "green" : "gray" }, " \u25CF "), /* @__PURE__ */ React6.createElement(Text6, null, pg.name, " (postgres)"), instance && /* @__PURE__ */ React6.createElement(Text6, null, " \u2192 localhost:", instance.port), !isReady && statusText && /* @__PURE__ */ React6.createElement(Text6, { dimColor: true }, statusText));
|
|
189379
189818
|
}), config.redis.map((redis) => {
|
|
189380
189819
|
const instance = resources.get(redis.name);
|
|
189381
189820
|
const resStatus = state.resourceStatus.get(redis.name);
|
|
@@ -189391,35 +189830,35 @@ function DevUI({ instanceKey }) {
|
|
|
189391
189830
|
} else if (resStatus?.status === "starting") {
|
|
189392
189831
|
statusText = " starting...";
|
|
189393
189832
|
}
|
|
189394
|
-
return /* @__PURE__ */
|
|
189833
|
+
return /* @__PURE__ */ React6.createElement(Text6, { key: redis.name }, /* @__PURE__ */ React6.createElement(Text6, { color: isReady ? "green" : "gray" }, " \u25CF "), /* @__PURE__ */ React6.createElement(Text6, null, redis.name, " (redis)"), instance && /* @__PURE__ */ React6.createElement(Text6, null, " \u2192 localhost:", instance.port), !isReady && statusText && /* @__PURE__ */ React6.createElement(Text6, { dimColor: true }, statusText));
|
|
189395
189834
|
}), config.storage.map((storage) => {
|
|
189396
189835
|
const instance = resources.get(storage.name);
|
|
189397
189836
|
const resStatus = state.resourceStatus.get(storage.name);
|
|
189398
189837
|
const isReady = !!instance;
|
|
189399
189838
|
const statusText = resStatus?.status === "starting" ? " starting..." : "";
|
|
189400
|
-
return /* @__PURE__ */
|
|
189401
|
-
}), /* @__PURE__ */
|
|
189839
|
+
return /* @__PURE__ */ React6.createElement(Text6, { key: storage.name }, /* @__PURE__ */ React6.createElement(Text6, { color: isReady ? "green" : "gray" }, " \u25CF "), /* @__PURE__ */ React6.createElement(Text6, null, storage.name, " (storage)"), instance && /* @__PURE__ */ React6.createElement(Text6, null, " \u2192 localhost:", instance.port), !isReady && statusText && /* @__PURE__ */ React6.createElement(Text6, { dimColor: true }, statusText));
|
|
189840
|
+
}), /* @__PURE__ */ React6.createElement(Text6, null, " ")), config.services.length > 0 && /* @__PURE__ */ React6.createElement(React6.Fragment, null, /* @__PURE__ */ React6.createElement(Text6, { bold: true }, "Services:"), config.services.map((svc) => {
|
|
189402
189841
|
const running = services.find((s) => s.name === svc.name);
|
|
189403
189842
|
const isReady = !!running;
|
|
189404
189843
|
const defaultPort = running?.ports.get("default");
|
|
189405
189844
|
const portInfo = defaultPort ? ` \u2192 localhost:${defaultPort}` : "";
|
|
189406
|
-
return /* @__PURE__ */
|
|
189407
|
-
}), /* @__PURE__ */
|
|
189845
|
+
return /* @__PURE__ */ React6.createElement(Text6, { key: svc.name }, /* @__PURE__ */ React6.createElement(Text6, { color: isReady ? "green" : "gray" }, " \u25CF "), /* @__PURE__ */ React6.createElement(Text6, null, svc.name, portInfo));
|
|
189846
|
+
}), /* @__PURE__ */ React6.createElement(Text6, null, " ")), /* @__PURE__ */ React6.createElement(Box6, null, /* @__PURE__ */ React6.createElement(Text6, { color: "blue" }, /* @__PURE__ */ React6.createElement(Spinner4, { type: "dots" })), /* @__PURE__ */ React6.createElement(Text6, null, " Starting...")));
|
|
189408
189847
|
}
|
|
189409
189848
|
const staticItems = [
|
|
189410
189849
|
{
|
|
189411
189850
|
key: "title",
|
|
189412
|
-
content: /* @__PURE__ */
|
|
189851
|
+
content: /* @__PURE__ */ React6.createElement(Text6, null, /* @__PURE__ */ React6.createElement(Text6, { bold: true, color: "cyan" }, "Specific dev server"), instanceKey !== "default" && /* @__PURE__ */ React6.createElement(Text6, { color: "yellow" }, " [", instanceKey, "]"), /* @__PURE__ */ React6.createElement(Text6, { dimColor: true }, " (Ctrl+C to stop)"))
|
|
189413
189852
|
},
|
|
189414
|
-
{ key: "space1", content: /* @__PURE__ */
|
|
189853
|
+
{ key: "space1", content: /* @__PURE__ */ React6.createElement(Text6, null, " ") },
|
|
189415
189854
|
// Show admin UI URL
|
|
189416
189855
|
{
|
|
189417
189856
|
key: "admin",
|
|
189418
|
-
content: /* @__PURE__ */
|
|
189857
|
+
content: /* @__PURE__ */ React6.createElement(Text6, null, /* @__PURE__ */ React6.createElement(Text6, { bold: true }, "Admin:"), /* @__PURE__ */ React6.createElement(Text6, null, " "), /* @__PURE__ */ React6.createElement(Text6, { bold: true }, "https://", instanceKey === "default" ? "" : `${instanceKey}.`, "local.spcf.app"))
|
|
189419
189858
|
},
|
|
189420
|
-
{ key: "admin-space", content: /* @__PURE__ */
|
|
189859
|
+
{ key: "admin-space", content: /* @__PURE__ */ React6.createElement(Text6, null, " ") },
|
|
189421
189860
|
...services.length > 0 ? [
|
|
189422
|
-
{ key: "svc-header", content: /* @__PURE__ */
|
|
189861
|
+
{ key: "svc-header", content: /* @__PURE__ */ React6.createElement(Text6, { bold: true }, "Services:") },
|
|
189423
189862
|
...services.flatMap((svc) => {
|
|
189424
189863
|
const serviceConfig = config.services.find((s) => s.name === svc.name);
|
|
189425
189864
|
const endpoints = serviceConfig?.endpoints || [];
|
|
@@ -189427,7 +189866,7 @@ function DevUI({ instanceKey }) {
|
|
|
189427
189866
|
const defaultPort = svc.ports.get("default");
|
|
189428
189867
|
return [{
|
|
189429
189868
|
key: `svc-${svc.name}`,
|
|
189430
|
-
content: /* @__PURE__ */
|
|
189869
|
+
content: /* @__PURE__ */ React6.createElement(Text6, null, /* @__PURE__ */ React6.createElement(Text6, { color: "green" }, " \u25CF "), /* @__PURE__ */ React6.createElement(Text6, null, svc.name), defaultPort && /* @__PURE__ */ React6.createElement(Text6, { dimColor: true }, " (localhost:", defaultPort, ")"))
|
|
189431
189870
|
}];
|
|
189432
189871
|
}
|
|
189433
189872
|
return endpoints.map((endpoint) => {
|
|
@@ -189436,61 +189875,61 @@ function DevUI({ instanceKey }) {
|
|
|
189436
189875
|
const proxyName = endpoint.name === "default" ? svc.name : `${svc.name}-${endpoint.name}`;
|
|
189437
189876
|
return {
|
|
189438
189877
|
key: `svc-${svc.name}-${endpoint.name}`,
|
|
189439
|
-
content: /* @__PURE__ */
|
|
189878
|
+
content: /* @__PURE__ */ React6.createElement(Text6, null, /* @__PURE__ */ React6.createElement(Text6, { color: "green" }, " \u25CF "), /* @__PURE__ */ React6.createElement(Text6, null, displayName), port ? endpoint.public ? /* @__PURE__ */ React6.createElement(React6.Fragment, null, /* @__PURE__ */ React6.createElement(Text6, null, " \u2192 "), /* @__PURE__ */ React6.createElement(Text6, { bold: true }, "https://", proxyName, instanceKey === "default" ? "" : `.${instanceKey}`, ".local.spcf.app"), /* @__PURE__ */ React6.createElement(Text6, { dimColor: true }, " (localhost:", port, ")")) : /* @__PURE__ */ React6.createElement(Text6, { dimColor: true }, " (localhost:", port, ")") : null)
|
|
189440
189879
|
};
|
|
189441
189880
|
});
|
|
189442
189881
|
}),
|
|
189443
|
-
{ key: "space2", content: /* @__PURE__ */
|
|
189882
|
+
{ key: "space2", content: /* @__PURE__ */ React6.createElement(Text6, null, " ") }
|
|
189444
189883
|
] : [],
|
|
189445
189884
|
...config.postgres.length > 0 ? [
|
|
189446
|
-
{ key: "pg-header", content: /* @__PURE__ */
|
|
189885
|
+
{ key: "pg-header", content: /* @__PURE__ */ React6.createElement(Text6, { bold: true }, "Postgres:") },
|
|
189447
189886
|
...config.postgres.map((pg) => {
|
|
189448
189887
|
const instance = resources.get(pg.name);
|
|
189449
189888
|
return {
|
|
189450
189889
|
key: `pg-${pg.name}`,
|
|
189451
|
-
content: /* @__PURE__ */
|
|
189890
|
+
content: /* @__PURE__ */ React6.createElement(Text6, null, /* @__PURE__ */ React6.createElement(Text6, { color: "green" }, " \u25CF "), /* @__PURE__ */ React6.createElement(Text6, null, pg.name), instance && /* @__PURE__ */ React6.createElement(Text6, null, " \u2192 ", instance.url))
|
|
189452
189891
|
};
|
|
189453
189892
|
}),
|
|
189454
|
-
{ key: "pg-space", content: /* @__PURE__ */
|
|
189893
|
+
{ key: "pg-space", content: /* @__PURE__ */ React6.createElement(Text6, null, " ") }
|
|
189455
189894
|
] : [],
|
|
189456
189895
|
...config.redis.length > 0 ? [
|
|
189457
|
-
{ key: "redis-header", content: /* @__PURE__ */
|
|
189896
|
+
{ key: "redis-header", content: /* @__PURE__ */ React6.createElement(Text6, { bold: true }, "Redis:") },
|
|
189458
189897
|
...config.redis.map((redis) => {
|
|
189459
189898
|
const instance = resources.get(redis.name);
|
|
189460
189899
|
return {
|
|
189461
189900
|
key: `redis-${redis.name}`,
|
|
189462
|
-
content: /* @__PURE__ */
|
|
189901
|
+
content: /* @__PURE__ */ React6.createElement(Text6, null, /* @__PURE__ */ React6.createElement(Text6, { color: "green" }, " \u25CF "), /* @__PURE__ */ React6.createElement(Text6, null, redis.name), instance && /* @__PURE__ */ React6.createElement(Text6, null, " \u2192 localhost:", instance.port))
|
|
189463
189902
|
};
|
|
189464
189903
|
}),
|
|
189465
|
-
{ key: "redis-space", content: /* @__PURE__ */
|
|
189904
|
+
{ key: "redis-space", content: /* @__PURE__ */ React6.createElement(Text6, null, " ") }
|
|
189466
189905
|
] : [],
|
|
189467
189906
|
...config.storage.length > 0 ? [
|
|
189468
|
-
{ key: "storage-header", content: /* @__PURE__ */
|
|
189907
|
+
{ key: "storage-header", content: /* @__PURE__ */ React6.createElement(Text6, { bold: true }, "Storage:") },
|
|
189469
189908
|
...config.storage.map((storage) => {
|
|
189470
189909
|
const instance = resources.get(storage.name);
|
|
189471
189910
|
return {
|
|
189472
189911
|
key: `storage-${storage.name}`,
|
|
189473
|
-
content: /* @__PURE__ */
|
|
189912
|
+
content: /* @__PURE__ */ React6.createElement(Text6, null, /* @__PURE__ */ React6.createElement(Text6, { color: "green" }, " \u25CF "), /* @__PURE__ */ React6.createElement(Text6, null, storage.name), instance && /* @__PURE__ */ React6.createElement(Text6, null, " \u2192 localhost:", instance.port))
|
|
189474
189913
|
};
|
|
189475
189914
|
}),
|
|
189476
|
-
{ key: "storage-space", content: /* @__PURE__ */
|
|
189915
|
+
{ key: "storage-space", content: /* @__PURE__ */ React6.createElement(Text6, null, " ") }
|
|
189477
189916
|
] : [],
|
|
189478
|
-
{ key: "separator", content: /* @__PURE__ */
|
|
189917
|
+
{ key: "separator", content: /* @__PURE__ */ React6.createElement(Text6, { dimColor: true }, "\u2500".repeat(50)) },
|
|
189479
189918
|
...state.parseError ? [
|
|
189480
189919
|
{
|
|
189481
189920
|
key: "parse-error",
|
|
189482
|
-
content: /* @__PURE__ */
|
|
189921
|
+
content: /* @__PURE__ */ React6.createElement(Text6, { color: "red" }, "Warning: ", state.parseError)
|
|
189483
189922
|
}
|
|
189484
189923
|
] : [],
|
|
189485
189924
|
...output.map((line, i) => ({
|
|
189486
189925
|
key: `log-${i}`,
|
|
189487
|
-
content: /* @__PURE__ */
|
|
189926
|
+
content: /* @__PURE__ */ React6.createElement(Text6, null, /* @__PURE__ */ React6.createElement(Text6, { color: line.color }, "[", line.service, "]"), " ", line.text)
|
|
189488
189927
|
}))
|
|
189489
189928
|
];
|
|
189490
|
-
return /* @__PURE__ */
|
|
189929
|
+
return /* @__PURE__ */ React6.createElement(Box6, { flexDirection: "column" }, /* @__PURE__ */ React6.createElement(Static, { items: staticItems }, (item) => /* @__PURE__ */ React6.createElement(Box6, { key: item.key }, item.content)));
|
|
189491
189930
|
}
|
|
189492
189931
|
function devCommand(instanceKey) {
|
|
189493
|
-
render4(/* @__PURE__ */
|
|
189932
|
+
render4(/* @__PURE__ */ React6.createElement(DevUI, { instanceKey }));
|
|
189494
189933
|
}
|
|
189495
189934
|
|
|
189496
189935
|
// src/lib/dev/git-worktree.ts
|
|
@@ -189533,8 +189972,9 @@ function getDefaultKey() {
|
|
|
189533
189972
|
}
|
|
189534
189973
|
|
|
189535
189974
|
// src/commands/deploy.tsx
|
|
189536
|
-
|
|
189537
|
-
import
|
|
189975
|
+
init_open();
|
|
189976
|
+
import React7, { useState as useState6, useEffect as useEffect4, useCallback } from "react";
|
|
189977
|
+
import { render as render5, Text as Text7, Box as Box7, useApp as useApp3, useInput as useInput5 } from "ink";
|
|
189538
189978
|
import Spinner5 from "ink-spinner";
|
|
189539
189979
|
import * as fs21 from "fs";
|
|
189540
189980
|
import * as path19 from "path";
|
|
@@ -189857,57 +190297,23 @@ function PhaseIndicator({
|
|
|
189857
190297
|
const currentIndex = phases.indexOf(currentPhase);
|
|
189858
190298
|
if (currentPhase === "error") {
|
|
189859
190299
|
if (phaseIndex < currentIndex) {
|
|
189860
|
-
return /* @__PURE__ */
|
|
190300
|
+
return /* @__PURE__ */ React7.createElement(Text7, null, /* @__PURE__ */ React7.createElement(Text7, { color: "green" }, " ", "\u2713"), " ", label);
|
|
189861
190301
|
}
|
|
189862
190302
|
if (phaseIndex === currentIndex) {
|
|
189863
|
-
return /* @__PURE__ */
|
|
190303
|
+
return /* @__PURE__ */ React7.createElement(Text7, null, /* @__PURE__ */ React7.createElement(Text7, { color: "red" }, " ", "\u2717"), " ", label);
|
|
189864
190304
|
}
|
|
189865
|
-
return /* @__PURE__ */
|
|
190305
|
+
return /* @__PURE__ */ React7.createElement(Text7, null, /* @__PURE__ */ React7.createElement(Text7, { dimColor: true }, " ", "\u25CB"), " ", /* @__PURE__ */ React7.createElement(Text7, { dimColor: true }, label));
|
|
189866
190306
|
}
|
|
189867
190307
|
if (phaseIndex < currentIndex) {
|
|
189868
|
-
return /* @__PURE__ */
|
|
190308
|
+
return /* @__PURE__ */ React7.createElement(Text7, null, /* @__PURE__ */ React7.createElement(Text7, { color: "green" }, " ", "\u2713"), " ", label);
|
|
189869
190309
|
}
|
|
189870
190310
|
if (phaseIndex === currentIndex) {
|
|
189871
190311
|
if (showSpinner) {
|
|
189872
|
-
return /* @__PURE__ */
|
|
190312
|
+
return /* @__PURE__ */ React7.createElement(Text7, null, " ", /* @__PURE__ */ React7.createElement(Text7, { color: "blue" }, /* @__PURE__ */ React7.createElement(Spinner5, { type: "dots" })), " ", label);
|
|
189873
190313
|
}
|
|
189874
|
-
return /* @__PURE__ */
|
|
190314
|
+
return /* @__PURE__ */ React7.createElement(Text7, null, /* @__PURE__ */ React7.createElement(Text7, { color: "yellow" }, " ", "\u25CF"), " ", label);
|
|
189875
190315
|
}
|
|
189876
|
-
return /* @__PURE__ */
|
|
189877
|
-
}
|
|
189878
|
-
function SecretInput({ secretName, onSubmit, onCancel }) {
|
|
189879
|
-
const [value, setValue] = useState5("");
|
|
189880
|
-
useInput3((input, key) => {
|
|
189881
|
-
if (key.return) {
|
|
189882
|
-
if (value.trim() !== "") {
|
|
189883
|
-
onSubmit(value);
|
|
189884
|
-
}
|
|
189885
|
-
} else if (key.escape) {
|
|
189886
|
-
onCancel();
|
|
189887
|
-
} else if (key.backspace || key.delete) {
|
|
189888
|
-
setValue((prev) => prev.slice(0, -1));
|
|
189889
|
-
} else if (!key.ctrl && !key.meta && input) {
|
|
189890
|
-
setValue((prev) => prev + input);
|
|
189891
|
-
}
|
|
189892
|
-
});
|
|
189893
|
-
return /* @__PURE__ */ React5.createElement(Box5, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React5.createElement(Text5, null, "Enter value for ", /* @__PURE__ */ React5.createElement(Text5, { color: "cyan" }, secretName), ":"), /* @__PURE__ */ React5.createElement(Box5, null, /* @__PURE__ */ React5.createElement(Text5, { color: "cyan" }, "> "), /* @__PURE__ */ React5.createElement(Text5, null, value.length > 0 ? "*".repeat(value.length) : ""), /* @__PURE__ */ React5.createElement(Text5, { color: "gray" }, "|")), /* @__PURE__ */ React5.createElement(Text5, { dimColor: true }, "(Press Enter to save, Esc to cancel deployment)"));
|
|
189894
|
-
}
|
|
189895
|
-
function ConfigInput({ configName, onSubmit, onCancel }) {
|
|
189896
|
-
const [value, setValue] = useState5("");
|
|
189897
|
-
useInput3((input, key) => {
|
|
189898
|
-
if (key.return) {
|
|
189899
|
-
if (value.trim() !== "") {
|
|
189900
|
-
onSubmit(value);
|
|
189901
|
-
}
|
|
189902
|
-
} else if (key.escape) {
|
|
189903
|
-
onCancel();
|
|
189904
|
-
} else if (key.backspace || key.delete) {
|
|
189905
|
-
setValue((prev) => prev.slice(0, -1));
|
|
189906
|
-
} else if (!key.ctrl && !key.meta && input) {
|
|
189907
|
-
setValue((prev) => prev + input);
|
|
189908
|
-
}
|
|
189909
|
-
});
|
|
189910
|
-
return /* @__PURE__ */ React5.createElement(Box5, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React5.createElement(Text5, null, "Enter value for config ", /* @__PURE__ */ React5.createElement(Text5, { color: "cyan" }, configName), ":"), /* @__PURE__ */ React5.createElement(Box5, null, /* @__PURE__ */ React5.createElement(Text5, { color: "cyan" }, "> "), /* @__PURE__ */ React5.createElement(Text5, null, value), /* @__PURE__ */ React5.createElement(Text5, { color: "gray" }, "|")), /* @__PURE__ */ React5.createElement(Text5, { dimColor: true }, "(Press Enter to save, Esc to cancel deployment)"));
|
|
190316
|
+
return /* @__PURE__ */ React7.createElement(Text7, null, /* @__PURE__ */ React7.createElement(Text7, { dimColor: true }, " ", "\u25CB"), " ", /* @__PURE__ */ React7.createElement(Text7, { dimColor: true }, label));
|
|
189911
190317
|
}
|
|
189912
190318
|
function ProjectSelector({
|
|
189913
190319
|
projects,
|
|
@@ -189916,7 +190322,7 @@ function ProjectSelector({
|
|
|
189916
190322
|
onUp,
|
|
189917
190323
|
onDown
|
|
189918
190324
|
}) {
|
|
189919
|
-
|
|
190325
|
+
useInput5((input, key) => {
|
|
189920
190326
|
if (key.return) {
|
|
189921
190327
|
if (selectedIndex === 0) {
|
|
189922
190328
|
onSelect("new");
|
|
@@ -189933,11 +190339,11 @@ function ProjectSelector({
|
|
|
189933
190339
|
{ id: "new", name: "Create new project", isNew: true },
|
|
189934
190340
|
...projects.map((p) => ({ ...p, isNew: false }))
|
|
189935
190341
|
];
|
|
189936
|
-
return /* @__PURE__ */
|
|
190342
|
+
return /* @__PURE__ */ React7.createElement(Box7, { flexDirection: "column", gap: 1 }, /* @__PURE__ */ React7.createElement(Text7, { bold: true }, "Select a project to deploy:"), /* @__PURE__ */ React7.createElement(Box7, { flexDirection: "column" }, items.map((item, index) => /* @__PURE__ */ React7.createElement(Text7, { key: item.id }, index === selectedIndex ? /* @__PURE__ */ React7.createElement(Text7, { color: "cyan" }, "> ") : /* @__PURE__ */ React7.createElement(Text7, null, " "), item.isNew ? /* @__PURE__ */ React7.createElement(Text7, { color: "green" }, item.name) : /* @__PURE__ */ React7.createElement(Text7, null, item.name, " ", /* @__PURE__ */ React7.createElement(Text7, { dimColor: true }, "(", item.id, ")"))))), /* @__PURE__ */ React7.createElement(Text7, { dimColor: true }, "Use arrow keys to navigate, Enter to select"));
|
|
189937
190343
|
}
|
|
189938
190344
|
function NameInput({ onSubmit, onCancel }) {
|
|
189939
|
-
const [value, setValue] =
|
|
189940
|
-
|
|
190345
|
+
const [value, setValue] = useState6("");
|
|
190346
|
+
useInput5((input, key) => {
|
|
189941
190347
|
if (key.return) {
|
|
189942
190348
|
if (value.trim() !== "") {
|
|
189943
190349
|
onSubmit(value.trim());
|
|
@@ -189950,13 +190356,13 @@ function NameInput({ onSubmit, onCancel }) {
|
|
|
189950
190356
|
setValue((prev) => prev + input);
|
|
189951
190357
|
}
|
|
189952
190358
|
});
|
|
189953
|
-
return /* @__PURE__ */
|
|
190359
|
+
return /* @__PURE__ */ React7.createElement(Box7, { flexDirection: "column", gap: 1 }, /* @__PURE__ */ React7.createElement(Text7, { bold: true }, "Create new project"), /* @__PURE__ */ React7.createElement(Text7, null, "Enter project name:"), /* @__PURE__ */ React7.createElement(Box7, null, /* @__PURE__ */ React7.createElement(Text7, { color: "cyan" }, "> "), /* @__PURE__ */ React7.createElement(Text7, null, value), /* @__PURE__ */ React7.createElement(Text7, { color: "gray" }, "|")), /* @__PURE__ */ React7.createElement(Text7, { dimColor: true }, "Press Enter to create, Esc to go back"));
|
|
189954
190360
|
}
|
|
189955
190361
|
function DeployUI({ environment, config, skipBuildTest }) {
|
|
189956
|
-
const { exit } =
|
|
189957
|
-
const [state, setState] =
|
|
189958
|
-
const clientRef =
|
|
189959
|
-
|
|
190362
|
+
const { exit } = useApp3();
|
|
190363
|
+
const [state, setState] = useState6({ phase: "checking-auth" });
|
|
190364
|
+
const clientRef = React7.useRef(null);
|
|
190365
|
+
useEffect4(() => {
|
|
189960
190366
|
if (state.phase !== "checking-auth") return;
|
|
189961
190367
|
const projectDir = process.cwd();
|
|
189962
190368
|
if (hasProjectId(projectDir)) {
|
|
@@ -189977,7 +190383,7 @@ function DeployUI({ environment, config, skipBuildTest }) {
|
|
|
189977
190383
|
}
|
|
189978
190384
|
setState({ phase: "logging-in" });
|
|
189979
190385
|
}, [state.phase]);
|
|
189980
|
-
|
|
190386
|
+
useEffect4(() => {
|
|
189981
190387
|
if (state.phase !== "logging-in") return;
|
|
189982
190388
|
let cancelled = false;
|
|
189983
190389
|
async function startLogin() {
|
|
@@ -190042,7 +190448,7 @@ function DeployUI({ environment, config, skipBuildTest }) {
|
|
|
190042
190448
|
cancelled = true;
|
|
190043
190449
|
};
|
|
190044
190450
|
}, [state.phase]);
|
|
190045
|
-
|
|
190451
|
+
useEffect4(() => {
|
|
190046
190452
|
if (state.phase !== "loading-projects") return;
|
|
190047
190453
|
let cancelled = false;
|
|
190048
190454
|
async function loadProjects() {
|
|
@@ -190089,7 +190495,7 @@ function DeployUI({ environment, config, skipBuildTest }) {
|
|
|
190089
190495
|
const handleNameCancel = useCallback(() => {
|
|
190090
190496
|
setState((s) => ({ ...s, phase: "selecting-project" }));
|
|
190091
190497
|
}, []);
|
|
190092
|
-
|
|
190498
|
+
useEffect4(() => {
|
|
190093
190499
|
if (state.phase !== "creating-project" || !state.newProjectName) return;
|
|
190094
190500
|
let cancelled = false;
|
|
190095
190501
|
async function createProject() {
|
|
@@ -190174,7 +190580,7 @@ function DeployUI({ environment, config, skipBuildTest }) {
|
|
|
190174
190580
|
error: "Deployment cancelled - configs not provided"
|
|
190175
190581
|
}));
|
|
190176
190582
|
}, []);
|
|
190177
|
-
|
|
190583
|
+
useEffect4(() => {
|
|
190178
190584
|
const {
|
|
190179
190585
|
phase: phase2,
|
|
190180
190586
|
deployment: deployment2,
|
|
@@ -190216,7 +190622,7 @@ function DeployUI({ environment, config, skipBuildTest }) {
|
|
|
190216
190622
|
}
|
|
190217
190623
|
})();
|
|
190218
190624
|
}, [state]);
|
|
190219
|
-
|
|
190625
|
+
useEffect4(() => {
|
|
190220
190626
|
const {
|
|
190221
190627
|
phase: phase2,
|
|
190222
190628
|
deployment: deployment2,
|
|
@@ -190258,7 +190664,7 @@ function DeployUI({ environment, config, skipBuildTest }) {
|
|
|
190258
190664
|
}
|
|
190259
190665
|
})();
|
|
190260
190666
|
}, [state]);
|
|
190261
|
-
|
|
190667
|
+
useEffect4(() => {
|
|
190262
190668
|
if (state.phase !== "testing-builds" || !state.projectId) return;
|
|
190263
190669
|
let cancelled = false;
|
|
190264
190670
|
let pollInterval;
|
|
@@ -190448,7 +190854,7 @@ ${errorMsg}`
|
|
|
190448
190854
|
if (pollInterval) clearInterval(pollInterval);
|
|
190449
190855
|
};
|
|
190450
190856
|
}, [state.projectId, environment, config.builds, skipBuildTest]);
|
|
190451
|
-
|
|
190857
|
+
useEffect4(() => {
|
|
190452
190858
|
let pollInterval;
|
|
190453
190859
|
if ((state.phase === "building" || state.phase === "deploying") && state.deployment && state.missingSecrets === void 0 && state.secretValues === void 0 && state.missingConfigs === void 0 && state.configValues === void 0) {
|
|
190454
190860
|
const client2 = clientRef.current;
|
|
@@ -190471,6 +190877,22 @@ ${errorMsg}`
|
|
|
190471
190877
|
if (pollInterval) clearInterval(pollInterval);
|
|
190472
190878
|
return;
|
|
190473
190879
|
}
|
|
190880
|
+
if (status.state === "awaiting_configs") {
|
|
190881
|
+
if (pollInterval) clearInterval(pollInterval);
|
|
190882
|
+
pollInterval = void 0;
|
|
190883
|
+
const missingConfigs2 = status.missingConfigs || [];
|
|
190884
|
+
writeLog("deploy", `Awaiting configs: ${missingConfigs2.join(", ")}`);
|
|
190885
|
+
setState((s) => ({
|
|
190886
|
+
...s,
|
|
190887
|
+
phase: "awaiting-configs",
|
|
190888
|
+
deployment: status,
|
|
190889
|
+
missingConfigs: missingConfigs2,
|
|
190890
|
+
configValues: {},
|
|
190891
|
+
currentConfigIndex: 0,
|
|
190892
|
+
currentConfigInput: ""
|
|
190893
|
+
}));
|
|
190894
|
+
return;
|
|
190895
|
+
}
|
|
190474
190896
|
if (status.state === "deploying") {
|
|
190475
190897
|
setState((s) => ({ ...s, phase: "deploying", deployment: status }));
|
|
190476
190898
|
} else if (status.state === "building") {
|
|
@@ -190486,12 +190908,12 @@ ${errorMsg}`
|
|
|
190486
190908
|
};
|
|
190487
190909
|
}
|
|
190488
190910
|
}, [state.phase, state.missingSecrets, state.secretValues, state.missingConfigs, state.configValues]);
|
|
190489
|
-
|
|
190911
|
+
useEffect4(() => {
|
|
190490
190912
|
if (state.phase === "testing-builds") {
|
|
190491
190913
|
trackEvent("deploy_started", { environment });
|
|
190492
190914
|
}
|
|
190493
190915
|
}, [state.phase, environment]);
|
|
190494
|
-
|
|
190916
|
+
useEffect4(() => {
|
|
190495
190917
|
if (state.phase === "success") {
|
|
190496
190918
|
trackEvent("deploy_succeeded", { environment });
|
|
190497
190919
|
closeDebugLog();
|
|
@@ -190520,16 +190942,16 @@ ${errorMsg}`
|
|
|
190520
190942
|
verificationUri
|
|
190521
190943
|
} = state;
|
|
190522
190944
|
if (phase === "checking-auth") {
|
|
190523
|
-
return /* @__PURE__ */
|
|
190945
|
+
return /* @__PURE__ */ React7.createElement(Box7, null, /* @__PURE__ */ React7.createElement(Text7, { color: "blue" }, /* @__PURE__ */ React7.createElement(Spinner5, { type: "dots" })), /* @__PURE__ */ React7.createElement(Text7, null, " Checking authentication..."));
|
|
190524
190946
|
}
|
|
190525
190947
|
if (phase === "logging-in") {
|
|
190526
|
-
return /* @__PURE__ */
|
|
190948
|
+
return /* @__PURE__ */ React7.createElement(Box7, { flexDirection: "column", gap: 1 }, /* @__PURE__ */ React7.createElement(Text7, { bold: true }, "Log in to Specific"), userCode ? /* @__PURE__ */ React7.createElement(React7.Fragment, null, /* @__PURE__ */ React7.createElement(Text7, null, "Your authentication code:", " ", /* @__PURE__ */ React7.createElement(Text7, { color: "cyan", bold: true }, userCode)), /* @__PURE__ */ React7.createElement(Box7, null, /* @__PURE__ */ React7.createElement(Text7, { color: "blue" }, /* @__PURE__ */ React7.createElement(Spinner5, { type: "dots" })), /* @__PURE__ */ React7.createElement(Text7, null, " Waiting for authentication in browser...")), /* @__PURE__ */ React7.createElement(Text7, { dimColor: true }, "If the browser didn't open, visit: ", verificationUri)) : /* @__PURE__ */ React7.createElement(Box7, null, /* @__PURE__ */ React7.createElement(Text7, { color: "blue" }, /* @__PURE__ */ React7.createElement(Spinner5, { type: "dots" })), /* @__PURE__ */ React7.createElement(Text7, null, " Initiating login...")));
|
|
190527
190949
|
}
|
|
190528
190950
|
if (phase === "loading-projects") {
|
|
190529
|
-
return /* @__PURE__ */
|
|
190951
|
+
return /* @__PURE__ */ React7.createElement(Box7, null, /* @__PURE__ */ React7.createElement(Text7, { color: "blue" }, /* @__PURE__ */ React7.createElement(Spinner5, { type: "dots" })), /* @__PURE__ */ React7.createElement(Text7, null, " Loading projects..."));
|
|
190530
190952
|
}
|
|
190531
190953
|
if (phase === "selecting-project" && projects && selectedIndex !== void 0) {
|
|
190532
|
-
return /* @__PURE__ */
|
|
190954
|
+
return /* @__PURE__ */ React7.createElement(
|
|
190533
190955
|
ProjectSelector,
|
|
190534
190956
|
{
|
|
190535
190957
|
projects,
|
|
@@ -190550,57 +190972,57 @@ ${errorMsg}`
|
|
|
190550
190972
|
);
|
|
190551
190973
|
}
|
|
190552
190974
|
if (phase === "entering-name") {
|
|
190553
|
-
return /* @__PURE__ */
|
|
190975
|
+
return /* @__PURE__ */ React7.createElement(NameInput, { onSubmit: handleNameSubmit, onCancel: handleNameCancel });
|
|
190554
190976
|
}
|
|
190555
190977
|
if (phase === "creating-project") {
|
|
190556
|
-
return /* @__PURE__ */
|
|
190978
|
+
return /* @__PURE__ */ React7.createElement(Box7, null, /* @__PURE__ */ React7.createElement(Text7, { color: "blue" }, /* @__PURE__ */ React7.createElement(Spinner5, { type: "dots" })), /* @__PURE__ */ React7.createElement(Text7, null, " Creating project..."));
|
|
190557
190979
|
}
|
|
190558
190980
|
const currentSecret = missingSecrets && currentSecretIndex !== void 0 ? missingSecrets[currentSecretIndex] : void 0;
|
|
190559
190981
|
const currentConfig = missingConfigs && currentConfigIndex !== void 0 ? missingConfigs[currentConfigIndex] : void 0;
|
|
190560
190982
|
const displayPhase = phase === "awaiting-secrets" || phase === "awaiting-configs" ? "building" : phase;
|
|
190561
|
-
return /* @__PURE__ */
|
|
190983
|
+
return /* @__PURE__ */ React7.createElement(Box7, { flexDirection: "column", gap: 1 }, /* @__PURE__ */ React7.createElement(Text7, null, /* @__PURE__ */ React7.createElement(Text7, { bold: true, color: "cyan" }, "Deploying to ", environment), deployment && /* @__PURE__ */ React7.createElement(Text7, { dimColor: true }, " (", deployment.id, ")")), /* @__PURE__ */ React7.createElement(Box7, { flexDirection: "column" }, /* @__PURE__ */ React7.createElement(
|
|
190562
190984
|
PhaseIndicator,
|
|
190563
190985
|
{
|
|
190564
190986
|
phase: "testing-builds",
|
|
190565
190987
|
currentPhase: displayPhase,
|
|
190566
190988
|
label: "Testing builds locally"
|
|
190567
190989
|
}
|
|
190568
|
-
), /* @__PURE__ */
|
|
190990
|
+
), /* @__PURE__ */ React7.createElement(
|
|
190569
190991
|
PhaseIndicator,
|
|
190570
190992
|
{
|
|
190571
190993
|
phase: "creating-tarball",
|
|
190572
190994
|
currentPhase: displayPhase,
|
|
190573
190995
|
label: `Creating archive${tarballSize ? ` (${formatBytes(tarballSize)})` : ""}`
|
|
190574
190996
|
}
|
|
190575
|
-
), /* @__PURE__ */
|
|
190997
|
+
), /* @__PURE__ */ React7.createElement(
|
|
190576
190998
|
PhaseIndicator,
|
|
190577
190999
|
{
|
|
190578
191000
|
phase: "creating-deployment",
|
|
190579
191001
|
currentPhase: displayPhase,
|
|
190580
191002
|
label: "Creating deployment"
|
|
190581
191003
|
}
|
|
190582
|
-
), /* @__PURE__ */
|
|
191004
|
+
), /* @__PURE__ */ React7.createElement(
|
|
190583
191005
|
PhaseIndicator,
|
|
190584
191006
|
{
|
|
190585
191007
|
phase: "uploading",
|
|
190586
191008
|
currentPhase: displayPhase,
|
|
190587
191009
|
label: "Uploading"
|
|
190588
191010
|
}
|
|
190589
|
-
), /* @__PURE__ */
|
|
191011
|
+
), /* @__PURE__ */ React7.createElement(
|
|
190590
191012
|
PhaseIndicator,
|
|
190591
191013
|
{
|
|
190592
191014
|
phase: "building",
|
|
190593
191015
|
currentPhase: displayPhase,
|
|
190594
191016
|
label: "Building"
|
|
190595
191017
|
}
|
|
190596
|
-
), /* @__PURE__ */
|
|
191018
|
+
), /* @__PURE__ */ React7.createElement(
|
|
190597
191019
|
PhaseIndicator,
|
|
190598
191020
|
{
|
|
190599
191021
|
phase: "deploying",
|
|
190600
191022
|
currentPhase: displayPhase,
|
|
190601
191023
|
label: "Deploying"
|
|
190602
191024
|
}
|
|
190603
|
-
)), phase === "awaiting-secrets" && currentSecret && /* @__PURE__ */
|
|
191025
|
+
)), phase === "awaiting-secrets" && currentSecret && /* @__PURE__ */ React7.createElement(
|
|
190604
191026
|
SecretInput,
|
|
190605
191027
|
{
|
|
190606
191028
|
key: currentSecret,
|
|
@@ -190608,7 +191030,7 @@ ${errorMsg}`
|
|
|
190608
191030
|
onSubmit: handleSecretSubmit,
|
|
190609
191031
|
onCancel: handleSecretCancel
|
|
190610
191032
|
}
|
|
190611
|
-
), phase === "awaiting-configs" && currentConfig && /* @__PURE__ */
|
|
191033
|
+
), phase === "awaiting-configs" && currentConfig && /* @__PURE__ */ React7.createElement(
|
|
190612
191034
|
ConfigInput,
|
|
190613
191035
|
{
|
|
190614
191036
|
key: currentConfig,
|
|
@@ -190616,7 +191038,7 @@ ${errorMsg}`
|
|
|
190616
191038
|
onSubmit: handleConfigSubmit,
|
|
190617
191039
|
onCancel: handleConfigCancel
|
|
190618
191040
|
}
|
|
190619
|
-
), phase === "error" && /* @__PURE__ */
|
|
191041
|
+
), phase === "error" && /* @__PURE__ */ React7.createElement(Box7, { marginTop: 1 }, /* @__PURE__ */ React7.createElement(Text7, { color: "red" }, "Error: ", error)), phase === "success" && /* @__PURE__ */ React7.createElement(Box7, { marginTop: 1, flexDirection: "column" }, /* @__PURE__ */ React7.createElement(Text7, { color: "green" }, "Deployment successful!"), deployment?.publicUrls && Object.keys(deployment.publicUrls).length > 0 && /* @__PURE__ */ React7.createElement(Box7, { marginTop: 1, flexDirection: "column" }, /* @__PURE__ */ React7.createElement(Text7, { bold: true }, "Public URLs:"), Object.entries(deployment.publicUrls).map(([name, url]) => /* @__PURE__ */ React7.createElement(Text7, { key: name }, " ", name, ": ", /* @__PURE__ */ React7.createElement(Text7, { color: "cyan" }, url))))));
|
|
190620
191042
|
}
|
|
190621
191043
|
async function deployCommand(environment, options2) {
|
|
190622
191044
|
const configPath = path19.join(process.cwd(), "specific.hcl");
|
|
@@ -190637,7 +191059,7 @@ async function deployCommand(environment, options2) {
|
|
|
190637
191059
|
const env2 = environment || "prod";
|
|
190638
191060
|
const skipBuildTest = options2?.skipBuildTest ?? false;
|
|
190639
191061
|
render5(
|
|
190640
|
-
/* @__PURE__ */
|
|
191062
|
+
/* @__PURE__ */ React7.createElement(
|
|
190641
191063
|
DeployUI,
|
|
190642
191064
|
{
|
|
190643
191065
|
environment: env2,
|
|
@@ -190877,14 +191299,14 @@ async function psqlCommand(databaseName, instanceKey = "default") {
|
|
|
190877
191299
|
}
|
|
190878
191300
|
|
|
190879
191301
|
// src/commands/clean.tsx
|
|
190880
|
-
import
|
|
190881
|
-
import { render as render6, Text as
|
|
191302
|
+
import React8, { useState as useState7, useEffect as useEffect5 } from "react";
|
|
191303
|
+
import { render as render6, Text as Text8, Box as Box8 } from "ink";
|
|
190882
191304
|
import Spinner6 from "ink-spinner";
|
|
190883
191305
|
import * as fs23 from "fs";
|
|
190884
191306
|
import * as path21 from "path";
|
|
190885
191307
|
function CleanUI({ instanceKey }) {
|
|
190886
|
-
const [state, setState] =
|
|
190887
|
-
|
|
191308
|
+
const [state, setState] = useState7({ status: "checking" });
|
|
191309
|
+
useEffect5(() => {
|
|
190888
191310
|
async function clean() {
|
|
190889
191311
|
const projectRoot = process.cwd();
|
|
190890
191312
|
const specificDir = path21.join(projectRoot, ".specific");
|
|
@@ -190960,85 +191382,52 @@ function CleanUI({ instanceKey }) {
|
|
|
190960
191382
|
clean();
|
|
190961
191383
|
}, [instanceKey]);
|
|
190962
191384
|
if (state.status === "checking") {
|
|
190963
|
-
return /* @__PURE__ */
|
|
191385
|
+
return /* @__PURE__ */ React8.createElement(Box8, null, /* @__PURE__ */ React8.createElement(Text8, { color: "blue" }, /* @__PURE__ */ React8.createElement(Spinner6, { type: "dots" })), /* @__PURE__ */ React8.createElement(Text8, null, " Checking for running instances..."));
|
|
190964
191386
|
}
|
|
190965
191387
|
if (state.status === "cleaning") {
|
|
190966
|
-
return /* @__PURE__ */
|
|
191388
|
+
return /* @__PURE__ */ React8.createElement(Box8, null, /* @__PURE__ */ React8.createElement(Text8, { color: "blue" }, /* @__PURE__ */ React8.createElement(Spinner6, { type: "dots" })), /* @__PURE__ */ React8.createElement(Text8, null, " Removing .specific directory..."));
|
|
190967
191389
|
}
|
|
190968
191390
|
if (state.status === "error") {
|
|
190969
|
-
return /* @__PURE__ */
|
|
191391
|
+
return /* @__PURE__ */ React8.createElement(Text8, { color: "red" }, "Error: ", state.error);
|
|
190970
191392
|
}
|
|
190971
191393
|
if (state.status === "nothing") {
|
|
190972
191394
|
const target2 = instanceKey ? `key "${instanceKey}"` : ".specific directory";
|
|
190973
|
-
return /* @__PURE__ */
|
|
191395
|
+
return /* @__PURE__ */ React8.createElement(Text8, { color: "yellow" }, "Nothing to clean (", target2, " does not exist)");
|
|
190974
191396
|
}
|
|
190975
191397
|
const target = instanceKey ? `key "${instanceKey}"` : ".specific directory";
|
|
190976
|
-
return /* @__PURE__ */
|
|
191398
|
+
return /* @__PURE__ */ React8.createElement(Text8, { color: "green" }, "Cleaned ", target);
|
|
190977
191399
|
}
|
|
190978
191400
|
function cleanCommand(instanceKey) {
|
|
190979
191401
|
if (instanceKey) {
|
|
190980
|
-
render6(/* @__PURE__ */
|
|
191402
|
+
render6(/* @__PURE__ */ React8.createElement(CleanUI, { instanceKey }));
|
|
190981
191403
|
} else {
|
|
190982
|
-
render6(/* @__PURE__ */
|
|
191404
|
+
render6(/* @__PURE__ */ React8.createElement(CleanUI, null));
|
|
190983
191405
|
}
|
|
190984
191406
|
}
|
|
190985
191407
|
|
|
190986
191408
|
// src/commands/secrets.tsx
|
|
190987
|
-
import
|
|
190988
|
-
import { render as render7, Text as
|
|
190989
|
-
import * as fs24 from "fs";
|
|
190990
|
-
var HEADER_COMMENT = "# Do not commit this file - it contains secrets\n";
|
|
191409
|
+
import React9, { useState as useState8, useEffect as useEffect6 } from "react";
|
|
191410
|
+
import { render as render7, Text as Text9, Box as Box9, useInput as useInput6, useApp as useApp4 } from "ink";
|
|
190991
191411
|
function SetSecretUI({ secretName }) {
|
|
190992
|
-
const { exit } =
|
|
190993
|
-
const [value, setValue] =
|
|
190994
|
-
const [done, setDone] =
|
|
190995
|
-
const [
|
|
190996
|
-
|
|
190997
|
-
|
|
191412
|
+
const { exit } = useApp4();
|
|
191413
|
+
const [value, setValue] = useState8("");
|
|
191414
|
+
const [done, setDone] = useState8(false);
|
|
191415
|
+
const [saving, setSaving] = useState8(false);
|
|
191416
|
+
const [error, setError] = useState8(null);
|
|
191417
|
+
useInput6((input, key) => {
|
|
191418
|
+
if (done || saving) return;
|
|
190998
191419
|
if (key.return) {
|
|
190999
191420
|
if (value.trim() === "") {
|
|
191000
191421
|
setError("Secret value cannot be empty");
|
|
191001
191422
|
return;
|
|
191002
191423
|
}
|
|
191003
|
-
|
|
191004
|
-
|
|
191005
|
-
const hclLine = `${secretName} = "${escapedValue}"`;
|
|
191006
|
-
let content = "";
|
|
191007
|
-
let hasHeader = false;
|
|
191008
|
-
if (fs24.existsSync(SECRETS_FILE)) {
|
|
191009
|
-
content = fs24.readFileSync(SECRETS_FILE, "utf-8");
|
|
191010
|
-
hasHeader = content.startsWith("#");
|
|
191011
|
-
const lines = content.split("\n");
|
|
191012
|
-
const newLines = [];
|
|
191013
|
-
let found = false;
|
|
191014
|
-
const pattern = new RegExp(`^${secretName}\\s*=\\s*"`);
|
|
191015
|
-
for (const line of lines) {
|
|
191016
|
-
if (pattern.test(line.trim())) {
|
|
191017
|
-
newLines.push(hclLine);
|
|
191018
|
-
found = true;
|
|
191019
|
-
} else {
|
|
191020
|
-
newLines.push(line);
|
|
191021
|
-
}
|
|
191022
|
-
}
|
|
191023
|
-
if (found) {
|
|
191024
|
-
fs24.writeFileSync(SECRETS_FILE, newLines.join("\n"));
|
|
191025
|
-
setDone(true);
|
|
191026
|
-
return;
|
|
191027
|
-
}
|
|
191028
|
-
}
|
|
191029
|
-
let newContent = "";
|
|
191030
|
-
if (!hasHeader && !content) {
|
|
191031
|
-
newContent = HEADER_COMMENT + "\n";
|
|
191032
|
-
} else if (content) {
|
|
191033
|
-
newContent = content.endsWith("\n") ? content : content + "\n";
|
|
191034
|
-
}
|
|
191035
|
-
newContent += `${hclLine}
|
|
191036
|
-
`;
|
|
191037
|
-
fs24.writeFileSync(SECRETS_FILE, newContent);
|
|
191424
|
+
setSaving(true);
|
|
191425
|
+
saveSecret(secretName, value).then(() => {
|
|
191038
191426
|
setDone(true);
|
|
191039
|
-
}
|
|
191427
|
+
}).catch((err) => {
|
|
191040
191428
|
setError(err instanceof Error ? err.message : String(err));
|
|
191041
|
-
|
|
191429
|
+
setSaving(false);
|
|
191430
|
+
});
|
|
191042
191431
|
} else if (key.backspace || key.delete) {
|
|
191043
191432
|
setValue((prev) => prev.slice(0, -1));
|
|
191044
191433
|
} else if (key.escape) {
|
|
@@ -191047,19 +191436,19 @@ function SetSecretUI({ secretName }) {
|
|
|
191047
191436
|
setValue((prev) => prev + input);
|
|
191048
191437
|
}
|
|
191049
191438
|
});
|
|
191050
|
-
|
|
191439
|
+
useEffect6(() => {
|
|
191051
191440
|
if (done) {
|
|
191052
191441
|
const timer = setTimeout(() => exit(), 50);
|
|
191053
191442
|
return () => clearTimeout(timer);
|
|
191054
191443
|
}
|
|
191055
191444
|
}, [done, exit]);
|
|
191056
191445
|
if (error) {
|
|
191057
|
-
return /* @__PURE__ */
|
|
191446
|
+
return /* @__PURE__ */ React9.createElement(Text9, { color: "red" }, "Error: ", error);
|
|
191058
191447
|
}
|
|
191059
191448
|
if (done) {
|
|
191060
|
-
return /* @__PURE__ */
|
|
191449
|
+
return /* @__PURE__ */ React9.createElement(Box9, { flexDirection: "column" }, /* @__PURE__ */ React9.createElement(Text9, { color: "green" }, "Secret '", secretName, "' saved to ", SECRETS_FILE));
|
|
191061
191450
|
}
|
|
191062
|
-
return /* @__PURE__ */
|
|
191451
|
+
return /* @__PURE__ */ React9.createElement(Box9, { flexDirection: "column" }, /* @__PURE__ */ React9.createElement(Text9, null, "Enter value for secret '", secretName, "':"), /* @__PURE__ */ React9.createElement(Box9, null, /* @__PURE__ */ React9.createElement(Text9, { color: "cyan" }, "> "), /* @__PURE__ */ React9.createElement(Text9, null, value.length > 0 ? "*".repeat(value.length) : ""), /* @__PURE__ */ React9.createElement(Text9, { color: "gray" }, "|")), /* @__PURE__ */ React9.createElement(Text9, { dimColor: true }, "(Press Enter to save, Esc to cancel)"));
|
|
191063
191452
|
}
|
|
191064
191453
|
async function secretsSetCommand(secretName) {
|
|
191065
191454
|
if (!secretName) {
|
|
@@ -191067,7 +191456,7 @@ async function secretsSetCommand(secretName) {
|
|
|
191067
191456
|
console.error("Usage: specific secrets set <name>");
|
|
191068
191457
|
process.exit(1);
|
|
191069
191458
|
}
|
|
191070
|
-
render7(/* @__PURE__ */
|
|
191459
|
+
render7(/* @__PURE__ */ React9.createElement(SetSecretUI, { secretName }));
|
|
191071
191460
|
}
|
|
191072
191461
|
async function secretsCommand(action, secretName) {
|
|
191073
191462
|
if (!action) {
|
|
@@ -191092,16 +191481,16 @@ async function secretsCommand(action, secretName) {
|
|
|
191092
191481
|
}
|
|
191093
191482
|
|
|
191094
191483
|
// src/commands/config.tsx
|
|
191095
|
-
import
|
|
191096
|
-
import { render as render8, Text as
|
|
191097
|
-
import * as
|
|
191484
|
+
import React10, { useState as useState9, useEffect as useEffect7 } from "react";
|
|
191485
|
+
import { render as render8, Text as Text10, Box as Box10, useInput as useInput7, useApp as useApp5 } from "ink";
|
|
191486
|
+
import * as fs24 from "fs";
|
|
191098
191487
|
var HEADER_COMMENT2 = "# Configuration values for this project\n# These values override defaults defined in specific.hcl\n";
|
|
191099
191488
|
function SetConfigUI({ configName, initialValue }) {
|
|
191100
|
-
const { exit } =
|
|
191101
|
-
const [value, setValue] =
|
|
191102
|
-
const [done, setDone] =
|
|
191103
|
-
const [error, setError] =
|
|
191104
|
-
|
|
191489
|
+
const { exit } = useApp5();
|
|
191490
|
+
const [value, setValue] = useState9(initialValue ?? "");
|
|
191491
|
+
const [done, setDone] = useState9(false);
|
|
191492
|
+
const [error, setError] = useState9(null);
|
|
191493
|
+
useInput7((input, key) => {
|
|
191105
191494
|
if (done) return;
|
|
191106
191495
|
if (key.return) {
|
|
191107
191496
|
if (value.trim() === "") {
|
|
@@ -191113,8 +191502,8 @@ function SetConfigUI({ configName, initialValue }) {
|
|
|
191113
191502
|
const hclLine = `${configName} = "${escapedValue}"`;
|
|
191114
191503
|
let content = "";
|
|
191115
191504
|
let hasHeader = false;
|
|
191116
|
-
if (
|
|
191117
|
-
content =
|
|
191505
|
+
if (fs24.existsSync(CONFIG_FILE)) {
|
|
191506
|
+
content = fs24.readFileSync(CONFIG_FILE, "utf-8");
|
|
191118
191507
|
hasHeader = content.startsWith("#");
|
|
191119
191508
|
const lines = content.split("\n");
|
|
191120
191509
|
const newLines = [];
|
|
@@ -191129,7 +191518,7 @@ function SetConfigUI({ configName, initialValue }) {
|
|
|
191129
191518
|
}
|
|
191130
191519
|
}
|
|
191131
191520
|
if (found) {
|
|
191132
|
-
|
|
191521
|
+
fs24.writeFileSync(CONFIG_FILE, newLines.join("\n"));
|
|
191133
191522
|
setDone(true);
|
|
191134
191523
|
return;
|
|
191135
191524
|
}
|
|
@@ -191142,7 +191531,7 @@ function SetConfigUI({ configName, initialValue }) {
|
|
|
191142
191531
|
}
|
|
191143
191532
|
newContent += `${hclLine}
|
|
191144
191533
|
`;
|
|
191145
|
-
|
|
191534
|
+
fs24.writeFileSync(CONFIG_FILE, newContent);
|
|
191146
191535
|
setDone(true);
|
|
191147
191536
|
} catch (err) {
|
|
191148
191537
|
setError(err instanceof Error ? err.message : String(err));
|
|
@@ -191155,19 +191544,19 @@ function SetConfigUI({ configName, initialValue }) {
|
|
|
191155
191544
|
setValue((prev) => prev + input);
|
|
191156
191545
|
}
|
|
191157
191546
|
});
|
|
191158
|
-
|
|
191547
|
+
useEffect7(() => {
|
|
191159
191548
|
if (done) {
|
|
191160
191549
|
const timer = setTimeout(() => exit(), 50);
|
|
191161
191550
|
return () => clearTimeout(timer);
|
|
191162
191551
|
}
|
|
191163
191552
|
}, [done, exit]);
|
|
191164
191553
|
if (error) {
|
|
191165
|
-
return /* @__PURE__ */
|
|
191554
|
+
return /* @__PURE__ */ React10.createElement(Text10, { color: "red" }, "Error: ", error);
|
|
191166
191555
|
}
|
|
191167
191556
|
if (done) {
|
|
191168
|
-
return /* @__PURE__ */
|
|
191557
|
+
return /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "column" }, /* @__PURE__ */ React10.createElement(Text10, { color: "green" }, "Config '", configName, "' saved to ", CONFIG_FILE));
|
|
191169
191558
|
}
|
|
191170
|
-
return /* @__PURE__ */
|
|
191559
|
+
return /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "column" }, /* @__PURE__ */ React10.createElement(Text10, null, "Enter value for config '", configName, "':"), /* @__PURE__ */ React10.createElement(Box10, null, /* @__PURE__ */ React10.createElement(Text10, { color: "cyan" }, "> "), /* @__PURE__ */ React10.createElement(Text10, null, value), /* @__PURE__ */ React10.createElement(Text10, { color: "gray" }, "|")), /* @__PURE__ */ React10.createElement(Text10, { dimColor: true }, "(Press Enter to save, Esc to cancel)"));
|
|
191171
191560
|
}
|
|
191172
191561
|
async function configSetCommand(configName, configValue) {
|
|
191173
191562
|
if (!configName) {
|
|
@@ -191181,8 +191570,8 @@ async function configSetCommand(configName, configValue) {
|
|
|
191181
191570
|
const hclLine = `${configName} = "${escapedValue}"`;
|
|
191182
191571
|
let content = "";
|
|
191183
191572
|
let hasHeader = false;
|
|
191184
|
-
if (
|
|
191185
|
-
content =
|
|
191573
|
+
if (fs24.existsSync(CONFIG_FILE)) {
|
|
191574
|
+
content = fs24.readFileSync(CONFIG_FILE, "utf-8");
|
|
191186
191575
|
hasHeader = content.startsWith("#");
|
|
191187
191576
|
const lines = content.split("\n");
|
|
191188
191577
|
const newLines = [];
|
|
@@ -191197,7 +191586,7 @@ async function configSetCommand(configName, configValue) {
|
|
|
191197
191586
|
}
|
|
191198
191587
|
}
|
|
191199
191588
|
if (found) {
|
|
191200
|
-
|
|
191589
|
+
fs24.writeFileSync(CONFIG_FILE, newLines.join("\n"));
|
|
191201
191590
|
console.log(`Config '${configName}' saved to ${CONFIG_FILE}`);
|
|
191202
191591
|
return;
|
|
191203
191592
|
}
|
|
@@ -191210,7 +191599,7 @@ async function configSetCommand(configName, configValue) {
|
|
|
191210
191599
|
}
|
|
191211
191600
|
newContent += `${hclLine}
|
|
191212
191601
|
`;
|
|
191213
|
-
|
|
191602
|
+
fs24.writeFileSync(CONFIG_FILE, newContent);
|
|
191214
191603
|
console.log(`Config '${configName}' saved to ${CONFIG_FILE}`);
|
|
191215
191604
|
} catch (err) {
|
|
191216
191605
|
console.error("Error:", err instanceof Error ? err.message : String(err));
|
|
@@ -191218,7 +191607,7 @@ async function configSetCommand(configName, configValue) {
|
|
|
191218
191607
|
}
|
|
191219
191608
|
return;
|
|
191220
191609
|
}
|
|
191221
|
-
render8(/* @__PURE__ */
|
|
191610
|
+
render8(/* @__PURE__ */ React10.createElement(SetConfigUI, { configName }));
|
|
191222
191611
|
}
|
|
191223
191612
|
async function configCommand(action, configName, configValue) {
|
|
191224
191613
|
if (!action) {
|
|
@@ -191243,62 +191632,26 @@ async function configCommand(action, configName, configValue) {
|
|
|
191243
191632
|
}
|
|
191244
191633
|
|
|
191245
191634
|
// src/commands/login.tsx
|
|
191246
|
-
|
|
191247
|
-
|
|
191248
|
-
|
|
191249
|
-
|
|
191250
|
-
const { exit } = useApp7();
|
|
191251
|
-
useEffect9(() => {
|
|
191252
|
-
const timer = setTimeout(() => exit(), 100);
|
|
191253
|
-
return () => clearTimeout(timer);
|
|
191254
|
-
}, [exit]);
|
|
191255
|
-
return /* @__PURE__ */ React9.createElement(Box9, { flexDirection: "column" }, /* @__PURE__ */ React9.createElement(Text9, { color: "green" }, "Already logged in."), /* @__PURE__ */ React9.createElement(Text9, { dimColor: true }, "Credentials saved to ~/.specific/credentials.json"));
|
|
191256
|
-
}
|
|
191257
|
-
function CheckingUI() {
|
|
191258
|
-
return /* @__PURE__ */ React9.createElement(Box9, null, /* @__PURE__ */ React9.createElement(Text9, { color: "blue" }, /* @__PURE__ */ React9.createElement(Spinner7, { type: "dots" })), /* @__PURE__ */ React9.createElement(Text9, null, " Checking login status..."));
|
|
191259
|
-
}
|
|
191260
|
-
function LoginUI() {
|
|
191261
|
-
const { exit } = useApp7();
|
|
191262
|
-
const [checking, setChecking] = useState9(true);
|
|
191263
|
-
const [alreadyLoggedIn, setAlreadyLoggedIn] = useState9(false);
|
|
191264
|
-
useEffect9(() => {
|
|
191265
|
-
if (isLoggedIn()) {
|
|
191266
|
-
setAlreadyLoggedIn(true);
|
|
191267
|
-
}
|
|
191268
|
-
setChecking(false);
|
|
191269
|
-
}, []);
|
|
191270
|
-
useEffect9(() => {
|
|
191271
|
-
if (checking || alreadyLoggedIn) return;
|
|
191272
|
-
async function doLogin() {
|
|
191273
|
-
const result = await performLogin();
|
|
191274
|
-
if (!result.success) {
|
|
191275
|
-
process.exitCode = 1;
|
|
191276
|
-
}
|
|
191277
|
-
exit();
|
|
191278
|
-
}
|
|
191279
|
-
doLogin();
|
|
191280
|
-
}, [checking, alreadyLoggedIn, exit]);
|
|
191281
|
-
if (checking) {
|
|
191282
|
-
return /* @__PURE__ */ React9.createElement(CheckingUI, null);
|
|
191635
|
+
async function loginCommand() {
|
|
191636
|
+
if (isLoggedIn()) {
|
|
191637
|
+
console.log("Already logged in.");
|
|
191638
|
+
return;
|
|
191283
191639
|
}
|
|
191284
|
-
|
|
191285
|
-
|
|
191640
|
+
const result = await performLogin();
|
|
191641
|
+
if (!result.success) {
|
|
191642
|
+
process.exitCode = 1;
|
|
191286
191643
|
}
|
|
191287
|
-
return null;
|
|
191288
|
-
}
|
|
191289
|
-
function loginCommand() {
|
|
191290
|
-
render9(/* @__PURE__ */ React9.createElement(LoginUI, null));
|
|
191291
191644
|
}
|
|
191292
191645
|
|
|
191293
191646
|
// src/commands/logout.tsx
|
|
191294
|
-
import
|
|
191295
|
-
import { render as
|
|
191647
|
+
import React11, { useState as useState10, useEffect as useEffect8 } from "react";
|
|
191648
|
+
import { render as render9, Text as Text11, useApp as useApp6 } from "ink";
|
|
191296
191649
|
function LogoutUI() {
|
|
191297
|
-
const { exit } =
|
|
191650
|
+
const { exit } = useApp6();
|
|
191298
191651
|
const [state, setState] = useState10({
|
|
191299
191652
|
phase: "checking"
|
|
191300
191653
|
});
|
|
191301
|
-
|
|
191654
|
+
useEffect8(() => {
|
|
191302
191655
|
if (state.phase !== "checking") return;
|
|
191303
191656
|
if (!isLoggedIn()) {
|
|
191304
191657
|
setState({ phase: "not-logged-in" });
|
|
@@ -191307,29 +191660,29 @@ function LogoutUI() {
|
|
|
191307
191660
|
clearUserCredentials();
|
|
191308
191661
|
setState({ phase: "done" });
|
|
191309
191662
|
}, [state.phase]);
|
|
191310
|
-
|
|
191663
|
+
useEffect8(() => {
|
|
191311
191664
|
if (state.phase === "done" || state.phase === "not-logged-in") {
|
|
191312
191665
|
const timer = setTimeout(() => exit(), 100);
|
|
191313
191666
|
return () => clearTimeout(timer);
|
|
191314
191667
|
}
|
|
191315
191668
|
}, [state.phase, exit]);
|
|
191316
191669
|
if (state.phase === "not-logged-in") {
|
|
191317
|
-
return /* @__PURE__ */
|
|
191670
|
+
return /* @__PURE__ */ React11.createElement(Text11, { dimColor: true }, "Not logged in.");
|
|
191318
191671
|
}
|
|
191319
191672
|
if (state.phase === "done") {
|
|
191320
|
-
return /* @__PURE__ */
|
|
191673
|
+
return /* @__PURE__ */ React11.createElement(Text11, { color: "green" }, "Logged out successfully.");
|
|
191321
191674
|
}
|
|
191322
|
-
return /* @__PURE__ */
|
|
191675
|
+
return /* @__PURE__ */ React11.createElement(Text11, null, "Logging out...");
|
|
191323
191676
|
}
|
|
191324
191677
|
function logoutCommand() {
|
|
191325
|
-
|
|
191678
|
+
render9(/* @__PURE__ */ React11.createElement(LogoutUI, null));
|
|
191326
191679
|
}
|
|
191327
191680
|
|
|
191328
191681
|
// src/cli.tsx
|
|
191329
191682
|
var program = new Command();
|
|
191330
191683
|
var env = "production";
|
|
191331
191684
|
var envLabel = env !== "production" ? `[${env.toUpperCase()}] ` : "";
|
|
191332
|
-
program.name("specific").description(`${envLabel}Infrastructure-as-code for coding agents`).version("0.1.
|
|
191685
|
+
program.name("specific").description(`${envLabel}Infrastructure-as-code for coding agents`).version("0.1.43").enablePositionalOptions();
|
|
191333
191686
|
program.command("init").description("Initialize project for use with a coding agent").action(initCommand);
|
|
191334
191687
|
program.command("docs [topic]").description("Fetch LLM-optimized documentation").action(docsCommand);
|
|
191335
191688
|
program.command("check").description("Validate specific.hcl configuration").action(checkCommand);
|