@specific.dev/cli 0.1.61 → 0.1.63
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.!KGRlZmF1bHQp.__PAGE__.txt +2 -2
- package/dist/admin/__next.!KGRlZmF1bHQp.txt +5 -5
- package/dist/admin/__next._full.txt +8 -8
- package/dist/admin/__next._head.txt +1 -1
- package/dist/admin/__next._index.txt +3 -3
- package/dist/admin/__next._tree.txt +1 -1
- package/dist/admin/_next/static/chunks/{59b95f8f36877231.js → 369cccd775763aa2.js} +2 -2
- package/dist/admin/_next/static/chunks/497f00630c8a5681.js +1 -0
- package/dist/admin/_next/static/chunks/{422a5aac8222197b.js → c7954d71061f1f9b.js} +2 -2
- package/dist/admin/_next/static/chunks/e3baf0c708c5b9ae.js +1 -0
- package/dist/admin/_not-found/__next._full.txt +3 -3
- package/dist/admin/_not-found/__next._head.txt +1 -1
- package/dist/admin/_not-found/__next._index.txt +3 -3
- 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 +1 -1
- package/dist/admin/_not-found/index.html +1 -1
- package/dist/admin/_not-found/index.txt +3 -3
- package/dist/admin/databases/__next.!KGRlZmF1bHQp.databases.__PAGE__.txt +2 -2
- package/dist/admin/databases/__next.!KGRlZmF1bHQp.databases.txt +1 -1
- package/dist/admin/databases/__next.!KGRlZmF1bHQp.txt +5 -5
- package/dist/admin/databases/__next._full.txt +8 -8
- package/dist/admin/databases/__next._head.txt +1 -1
- package/dist/admin/databases/__next._index.txt +3 -3
- package/dist/admin/databases/__next._tree.txt +1 -1
- package/dist/admin/databases/index.html +1 -1
- package/dist/admin/databases/index.txt +8 -8
- package/dist/admin/fullscreen/__next._full.txt +4 -4
- package/dist/admin/fullscreen/__next._head.txt +1 -1
- package/dist/admin/fullscreen/__next._index.txt +3 -3
- package/dist/admin/fullscreen/__next._tree.txt +1 -1
- package/dist/admin/fullscreen/__next.fullscreen.__PAGE__.txt +2 -2
- package/dist/admin/fullscreen/__next.fullscreen.txt +1 -1
- package/dist/admin/fullscreen/databases/__next._full.txt +4 -4
- package/dist/admin/fullscreen/databases/__next._head.txt +1 -1
- package/dist/admin/fullscreen/databases/__next._index.txt +3 -3
- package/dist/admin/fullscreen/databases/__next._tree.txt +1 -1
- package/dist/admin/fullscreen/databases/__next.fullscreen.databases.__PAGE__.txt +2 -2
- package/dist/admin/fullscreen/databases/__next.fullscreen.databases.txt +1 -1
- package/dist/admin/fullscreen/databases/__next.fullscreen.txt +1 -1
- package/dist/admin/fullscreen/databases/index.html +1 -1
- package/dist/admin/fullscreen/databases/index.txt +4 -4
- package/dist/admin/fullscreen/index.html +1 -1
- package/dist/admin/fullscreen/index.txt +4 -4
- package/dist/admin/index.html +1 -1
- package/dist/admin/index.txt +8 -8
- package/dist/admin/workflows/__next.!KGRlZmF1bHQp.txt +8 -0
- package/dist/admin/workflows/__next.!KGRlZmF1bHQp.workflows.__PAGE__.txt +9 -0
- package/dist/admin/workflows/__next.!KGRlZmF1bHQp.workflows.txt +4 -0
- package/dist/admin/workflows/__next._full.txt +27 -0
- package/dist/admin/workflows/__next._head.txt +6 -0
- package/dist/admin/workflows/__next._index.txt +7 -0
- package/dist/admin/workflows/__next._tree.txt +5 -0
- package/dist/admin/workflows/index.html +1 -0
- package/dist/admin/workflows/index.txt +27 -0
- package/dist/cli.js +1837 -727
- package/dist/docs/builds.md +59 -13
- package/dist/docs/index.md +4 -0
- package/dist/docs/integrations/temporal.md +4 -0
- package/dist/docs/temporal.md +98 -0
- package/dist/docs/volumes.md +63 -0
- package/dist/postinstall.js +1 -1
- package/package.json +5 -2
- package/dist/admin/_next/static/chunks/144304e5f91b7ae5.js +0 -1
- /package/dist/admin/_next/static/{ko53a3ptYl472sHJWxbir → 3gQ1McserxEZ29fmlvSRS}/_buildManifest.js +0 -0
- /package/dist/admin/_next/static/{ko53a3ptYl472sHJWxbir → 3gQ1McserxEZ29fmlvSRS}/_clientMiddlewareManifest.json +0 -0
- /package/dist/admin/_next/static/{ko53a3ptYl472sHJWxbir → 3gQ1McserxEZ29fmlvSRS}/_ssgManifest.js +0 -0
package/dist/cli.js
CHANGED
|
@@ -39,10 +39,10 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
39
39
|
));
|
|
40
40
|
|
|
41
41
|
// node_modules/.pnpm/is-docker@3.0.0/node_modules/is-docker/index.js
|
|
42
|
-
import
|
|
42
|
+
import fs5 from "node:fs";
|
|
43
43
|
function hasDockerEnv() {
|
|
44
44
|
try {
|
|
45
|
-
|
|
45
|
+
fs5.statSync("/.dockerenv");
|
|
46
46
|
return true;
|
|
47
47
|
} catch {
|
|
48
48
|
return false;
|
|
@@ -50,7 +50,7 @@ function hasDockerEnv() {
|
|
|
50
50
|
}
|
|
51
51
|
function hasDockerCGroup() {
|
|
52
52
|
try {
|
|
53
|
-
return
|
|
53
|
+
return fs5.readFileSync("/proc/self/cgroup", "utf8").includes("docker");
|
|
54
54
|
} catch {
|
|
55
55
|
return false;
|
|
56
56
|
}
|
|
@@ -68,7 +68,7 @@ var init_is_docker = __esm({
|
|
|
68
68
|
});
|
|
69
69
|
|
|
70
70
|
// node_modules/.pnpm/is-inside-container@1.0.0/node_modules/is-inside-container/index.js
|
|
71
|
-
import
|
|
71
|
+
import fs6 from "node:fs";
|
|
72
72
|
function isInsideContainer() {
|
|
73
73
|
if (cachedResult === void 0) {
|
|
74
74
|
cachedResult = hasContainerEnv() || isDocker();
|
|
@@ -81,7 +81,7 @@ var init_is_inside_container = __esm({
|
|
|
81
81
|
init_is_docker();
|
|
82
82
|
hasContainerEnv = () => {
|
|
83
83
|
try {
|
|
84
|
-
|
|
84
|
+
fs6.statSync("/run/.containerenv");
|
|
85
85
|
return true;
|
|
86
86
|
} catch {
|
|
87
87
|
return false;
|
|
@@ -92,8 +92,8 @@ var init_is_inside_container = __esm({
|
|
|
92
92
|
|
|
93
93
|
// node_modules/.pnpm/is-wsl@3.1.0/node_modules/is-wsl/index.js
|
|
94
94
|
import process2 from "node:process";
|
|
95
|
-
import
|
|
96
|
-
import
|
|
95
|
+
import os4 from "node:os";
|
|
96
|
+
import fs7 from "node:fs";
|
|
97
97
|
var isWsl, is_wsl_default;
|
|
98
98
|
var init_is_wsl = __esm({
|
|
99
99
|
"node_modules/.pnpm/is-wsl@3.1.0/node_modules/is-wsl/index.js"() {
|
|
@@ -102,14 +102,14 @@ var init_is_wsl = __esm({
|
|
|
102
102
|
if (process2.platform !== "linux") {
|
|
103
103
|
return false;
|
|
104
104
|
}
|
|
105
|
-
if (
|
|
105
|
+
if (os4.release().toLowerCase().includes("microsoft")) {
|
|
106
106
|
if (isInsideContainer()) {
|
|
107
107
|
return false;
|
|
108
108
|
}
|
|
109
109
|
return true;
|
|
110
110
|
}
|
|
111
111
|
try {
|
|
112
|
-
return
|
|
112
|
+
return fs7.readFileSync("/proc/version", "utf8").toLowerCase().includes("microsoft") ? !isInsideContainer() : false;
|
|
113
113
|
} catch {
|
|
114
114
|
return false;
|
|
115
115
|
}
|
|
@@ -179,7 +179,7 @@ var init_utilities = __esm({
|
|
|
179
179
|
// node_modules/.pnpm/wsl-utils@0.3.1/node_modules/wsl-utils/index.js
|
|
180
180
|
import { promisify as promisify2 } from "node:util";
|
|
181
181
|
import childProcess2 from "node:child_process";
|
|
182
|
-
import
|
|
182
|
+
import fs8, { constants as fsConstants } from "node:fs/promises";
|
|
183
183
|
var execFile2, wslDrivesMountPoint, powerShellPathFromWsl, powerShellPath2, canAccessPowerShellPromise, canAccessPowerShell, wslDefaultBrowser, convertWslPathToWindows;
|
|
184
184
|
var init_wsl_utils = __esm({
|
|
185
185
|
"node_modules/.pnpm/wsl-utils@0.3.1/node_modules/wsl-utils/index.js"() {
|
|
@@ -198,14 +198,14 @@ var init_wsl_utils = __esm({
|
|
|
198
198
|
const configFilePath = "/etc/wsl.conf";
|
|
199
199
|
let isConfigFileExists = false;
|
|
200
200
|
try {
|
|
201
|
-
await
|
|
201
|
+
await fs8.access(configFilePath, fsConstants.F_OK);
|
|
202
202
|
isConfigFileExists = true;
|
|
203
203
|
} catch {
|
|
204
204
|
}
|
|
205
205
|
if (!isConfigFileExists) {
|
|
206
206
|
return defaultMountPoint;
|
|
207
207
|
}
|
|
208
|
-
const configContent = await
|
|
208
|
+
const configContent = await fs8.readFile(configFilePath, { encoding: "utf8" });
|
|
209
209
|
const parsedMountPoint = parseMountPointFromConfig(configContent);
|
|
210
210
|
if (parsedMountPoint === void 0) {
|
|
211
211
|
return defaultMountPoint;
|
|
@@ -224,7 +224,7 @@ var init_wsl_utils = __esm({
|
|
|
224
224
|
canAccessPowerShellPromise ??= (async () => {
|
|
225
225
|
try {
|
|
226
226
|
const psPath = await powerShellPath2();
|
|
227
|
-
await
|
|
227
|
+
await fs8.access(psPath, fsConstants.X_OK);
|
|
228
228
|
return true;
|
|
229
229
|
} catch {
|
|
230
230
|
return false;
|
|
@@ -238,15 +238,15 @@ var init_wsl_utils = __esm({
|
|
|
238
238
|
const { stdout } = await executePowerShell(command, { powerShellPath: psPath });
|
|
239
239
|
return stdout.trim();
|
|
240
240
|
};
|
|
241
|
-
convertWslPathToWindows = async (
|
|
242
|
-
if (/^[a-z]+:\/\//i.test(
|
|
243
|
-
return
|
|
241
|
+
convertWslPathToWindows = async (path28) => {
|
|
242
|
+
if (/^[a-z]+:\/\//i.test(path28)) {
|
|
243
|
+
return path28;
|
|
244
244
|
}
|
|
245
245
|
try {
|
|
246
|
-
const { stdout } = await execFile2("wslpath", ["-aw",
|
|
246
|
+
const { stdout } = await execFile2("wslpath", ["-aw", path28], { encoding: "utf8" });
|
|
247
247
|
return stdout.trim();
|
|
248
248
|
} catch {
|
|
249
|
-
return
|
|
249
|
+
return path28;
|
|
250
250
|
}
|
|
251
251
|
};
|
|
252
252
|
}
|
|
@@ -432,10 +432,10 @@ __export(open_exports, {
|
|
|
432
432
|
openApp: () => openApp
|
|
433
433
|
});
|
|
434
434
|
import process8 from "node:process";
|
|
435
|
-
import
|
|
435
|
+
import path5 from "node:path";
|
|
436
436
|
import { fileURLToPath } from "node:url";
|
|
437
437
|
import childProcess3 from "node:child_process";
|
|
438
|
-
import
|
|
438
|
+
import fs9, { constants as fsConstants2 } from "node:fs/promises";
|
|
439
439
|
function detectArchBinary(binary) {
|
|
440
440
|
if (typeof binary === "string" || Array.isArray(binary)) {
|
|
441
441
|
return binary;
|
|
@@ -446,16 +446,16 @@ function detectArchBinary(binary) {
|
|
|
446
446
|
}
|
|
447
447
|
return archBinary;
|
|
448
448
|
}
|
|
449
|
-
function detectPlatformBinary({ [
|
|
449
|
+
function detectPlatformBinary({ [platform3]: platformBinary }, { wsl } = {}) {
|
|
450
450
|
if (wsl && is_wsl_default) {
|
|
451
451
|
return detectArchBinary(wsl);
|
|
452
452
|
}
|
|
453
453
|
if (!platformBinary) {
|
|
454
|
-
throw new Error(`${
|
|
454
|
+
throw new Error(`${platform3} is not supported`);
|
|
455
455
|
}
|
|
456
456
|
return detectArchBinary(platformBinary);
|
|
457
457
|
}
|
|
458
|
-
var fallbackAttemptSymbol, __dirname, localXdgOpenPath,
|
|
458
|
+
var fallbackAttemptSymbol, __dirname, localXdgOpenPath, platform3, arch, tryEachApp, baseOpen, open, openApp, apps, open_default;
|
|
459
459
|
var init_open = __esm({
|
|
460
460
|
"node_modules/.pnpm/open@11.0.0/node_modules/open/index.js"() {
|
|
461
461
|
init_wsl_utils();
|
|
@@ -465,9 +465,9 @@ var init_open = __esm({
|
|
|
465
465
|
init_is_inside_container();
|
|
466
466
|
init_is_in_ssh();
|
|
467
467
|
fallbackAttemptSymbol = Symbol("fallbackAttempt");
|
|
468
|
-
__dirname = import.meta.url ?
|
|
469
|
-
localXdgOpenPath =
|
|
470
|
-
({ platform:
|
|
468
|
+
__dirname = import.meta.url ? path5.dirname(fileURLToPath(import.meta.url)) : "";
|
|
469
|
+
localXdgOpenPath = path5.join(__dirname, "xdg-open");
|
|
470
|
+
({ platform: platform3, arch } = process8);
|
|
471
471
|
tryEachApp = async (apps2, opener) => {
|
|
472
472
|
if (apps2.length === 0) {
|
|
473
473
|
return;
|
|
@@ -564,7 +564,7 @@ var init_open = __esm({
|
|
|
564
564
|
if (is_wsl_default && !isInsideContainer() && !is_in_ssh_default && !app) {
|
|
565
565
|
shouldUseWindowsInWsl = await canAccessPowerShell();
|
|
566
566
|
}
|
|
567
|
-
if (
|
|
567
|
+
if (platform3 === "darwin") {
|
|
568
568
|
command = "open";
|
|
569
569
|
if (options2.wait) {
|
|
570
570
|
cliArguments.push("--wait-apps");
|
|
@@ -578,7 +578,7 @@ var init_open = __esm({
|
|
|
578
578
|
if (app) {
|
|
579
579
|
cliArguments.push("-a", app);
|
|
580
580
|
}
|
|
581
|
-
} else if (
|
|
581
|
+
} else if (platform3 === "win32" || shouldUseWindowsInWsl) {
|
|
582
582
|
command = await powerShellPath2();
|
|
583
583
|
cliArguments.push(...executePowerShell.argumentsPrefix);
|
|
584
584
|
if (!is_wsl_default) {
|
|
@@ -614,11 +614,11 @@ var init_open = __esm({
|
|
|
614
614
|
const isBundled = !__dirname || __dirname === "/";
|
|
615
615
|
let exeLocalXdgOpen = false;
|
|
616
616
|
try {
|
|
617
|
-
await
|
|
617
|
+
await fs9.access(localXdgOpenPath, fsConstants2.X_OK);
|
|
618
618
|
exeLocalXdgOpen = true;
|
|
619
619
|
} catch {
|
|
620
620
|
}
|
|
621
|
-
const useSystemXdgOpen = process8.versions.electron ?? (
|
|
621
|
+
const useSystemXdgOpen = process8.versions.electron ?? (platform3 === "android" || isBundled || !exeLocalXdgOpen);
|
|
622
622
|
command = useSystemXdgOpen ? "xdg-open" : localXdgOpenPath;
|
|
623
623
|
}
|
|
624
624
|
if (appArguments.length > 0) {
|
|
@@ -629,7 +629,7 @@ var init_open = __esm({
|
|
|
629
629
|
childProcessOptions.detached = true;
|
|
630
630
|
}
|
|
631
631
|
}
|
|
632
|
-
if (
|
|
632
|
+
if (platform3 === "darwin" && appArguments.length > 0) {
|
|
633
633
|
cliArguments.push("--args", ...appArguments);
|
|
634
634
|
}
|
|
635
635
|
if (options2.target) {
|
|
@@ -754,8 +754,8 @@ var require_dist = __commonJS({
|
|
|
754
754
|
var $global, $module, $NaN = NaN;
|
|
755
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");
|
|
756
756
|
if ("undefined" != typeof module && ($module = module), !$global.fs && $global.require) try {
|
|
757
|
-
var
|
|
758
|
-
"object" == typeof
|
|
757
|
+
var fs30 = $global.require("fs");
|
|
758
|
+
"object" == typeof fs30 && null !== fs30 && 0 !== Object.keys(fs30).length && ($global.fs = fs30);
|
|
759
759
|
} catch (e) {
|
|
760
760
|
}
|
|
761
761
|
if (!$global.fs) {
|
|
@@ -182942,6 +182942,487 @@ var require_dist = __commonJS({
|
|
|
182942
182942
|
}
|
|
182943
182943
|
});
|
|
182944
182944
|
|
|
182945
|
+
// node_modules/.pnpm/picocolors@1.1.1/node_modules/picocolors/picocolors.js
|
|
182946
|
+
var require_picocolors = __commonJS({
|
|
182947
|
+
"node_modules/.pnpm/picocolors@1.1.1/node_modules/picocolors/picocolors.js"(exports, module) {
|
|
182948
|
+
var p = process || {};
|
|
182949
|
+
var argv = p.argv || [];
|
|
182950
|
+
var env2 = p.env || {};
|
|
182951
|
+
var isColorSupported = !(!!env2.NO_COLOR || argv.includes("--no-color")) && (!!env2.FORCE_COLOR || argv.includes("--color") || p.platform === "win32" || (p.stdout || {}).isTTY && env2.TERM !== "dumb" || !!env2.CI);
|
|
182952
|
+
var formatter = (open3, close, replace = open3) => (input) => {
|
|
182953
|
+
let string = "" + input, index = string.indexOf(close, open3.length);
|
|
182954
|
+
return ~index ? open3 + replaceClose(string, close, replace, index) + close : open3 + string + close;
|
|
182955
|
+
};
|
|
182956
|
+
var replaceClose = (string, close, replace, index) => {
|
|
182957
|
+
let result = "", cursor = 0;
|
|
182958
|
+
do {
|
|
182959
|
+
result += string.substring(cursor, index) + replace;
|
|
182960
|
+
cursor = index + close.length;
|
|
182961
|
+
index = string.indexOf(close, cursor);
|
|
182962
|
+
} while (~index);
|
|
182963
|
+
return result + string.substring(cursor);
|
|
182964
|
+
};
|
|
182965
|
+
var createColors = (enabled = isColorSupported) => {
|
|
182966
|
+
let f = enabled ? formatter : () => String;
|
|
182967
|
+
return {
|
|
182968
|
+
isColorSupported: enabled,
|
|
182969
|
+
reset: f("\x1B[0m", "\x1B[0m"),
|
|
182970
|
+
bold: f("\x1B[1m", "\x1B[22m", "\x1B[22m\x1B[1m"),
|
|
182971
|
+
dim: f("\x1B[2m", "\x1B[22m", "\x1B[22m\x1B[2m"),
|
|
182972
|
+
italic: f("\x1B[3m", "\x1B[23m"),
|
|
182973
|
+
underline: f("\x1B[4m", "\x1B[24m"),
|
|
182974
|
+
inverse: f("\x1B[7m", "\x1B[27m"),
|
|
182975
|
+
hidden: f("\x1B[8m", "\x1B[28m"),
|
|
182976
|
+
strikethrough: f("\x1B[9m", "\x1B[29m"),
|
|
182977
|
+
black: f("\x1B[30m", "\x1B[39m"),
|
|
182978
|
+
red: f("\x1B[31m", "\x1B[39m"),
|
|
182979
|
+
green: f("\x1B[32m", "\x1B[39m"),
|
|
182980
|
+
yellow: f("\x1B[33m", "\x1B[39m"),
|
|
182981
|
+
blue: f("\x1B[34m", "\x1B[39m"),
|
|
182982
|
+
magenta: f("\x1B[35m", "\x1B[39m"),
|
|
182983
|
+
cyan: f("\x1B[36m", "\x1B[39m"),
|
|
182984
|
+
white: f("\x1B[37m", "\x1B[39m"),
|
|
182985
|
+
gray: f("\x1B[90m", "\x1B[39m"),
|
|
182986
|
+
bgBlack: f("\x1B[40m", "\x1B[49m"),
|
|
182987
|
+
bgRed: f("\x1B[41m", "\x1B[49m"),
|
|
182988
|
+
bgGreen: f("\x1B[42m", "\x1B[49m"),
|
|
182989
|
+
bgYellow: f("\x1B[43m", "\x1B[49m"),
|
|
182990
|
+
bgBlue: f("\x1B[44m", "\x1B[49m"),
|
|
182991
|
+
bgMagenta: f("\x1B[45m", "\x1B[49m"),
|
|
182992
|
+
bgCyan: f("\x1B[46m", "\x1B[49m"),
|
|
182993
|
+
bgWhite: f("\x1B[47m", "\x1B[49m"),
|
|
182994
|
+
blackBright: f("\x1B[90m", "\x1B[39m"),
|
|
182995
|
+
redBright: f("\x1B[91m", "\x1B[39m"),
|
|
182996
|
+
greenBright: f("\x1B[92m", "\x1B[39m"),
|
|
182997
|
+
yellowBright: f("\x1B[93m", "\x1B[39m"),
|
|
182998
|
+
blueBright: f("\x1B[94m", "\x1B[39m"),
|
|
182999
|
+
magentaBright: f("\x1B[95m", "\x1B[39m"),
|
|
183000
|
+
cyanBright: f("\x1B[96m", "\x1B[39m"),
|
|
183001
|
+
whiteBright: f("\x1B[97m", "\x1B[39m"),
|
|
183002
|
+
bgBlackBright: f("\x1B[100m", "\x1B[49m"),
|
|
183003
|
+
bgRedBright: f("\x1B[101m", "\x1B[49m"),
|
|
183004
|
+
bgGreenBright: f("\x1B[102m", "\x1B[49m"),
|
|
183005
|
+
bgYellowBright: f("\x1B[103m", "\x1B[49m"),
|
|
183006
|
+
bgBlueBright: f("\x1B[104m", "\x1B[49m"),
|
|
183007
|
+
bgMagentaBright: f("\x1B[105m", "\x1B[49m"),
|
|
183008
|
+
bgCyanBright: f("\x1B[106m", "\x1B[49m"),
|
|
183009
|
+
bgWhiteBright: f("\x1B[107m", "\x1B[49m")
|
|
183010
|
+
};
|
|
183011
|
+
};
|
|
183012
|
+
module.exports = createColors();
|
|
183013
|
+
module.exports.createColors = createColors;
|
|
183014
|
+
}
|
|
183015
|
+
});
|
|
183016
|
+
|
|
183017
|
+
// node_modules/.pnpm/js-tokens@4.0.0/node_modules/js-tokens/index.js
|
|
183018
|
+
var require_js_tokens = __commonJS({
|
|
183019
|
+
"node_modules/.pnpm/js-tokens@4.0.0/node_modules/js-tokens/index.js"(exports) {
|
|
183020
|
+
Object.defineProperty(exports, "__esModule", {
|
|
183021
|
+
value: true
|
|
183022
|
+
});
|
|
183023
|
+
exports.default = /((['"])(?:(?!\2|\\).|\\(?:\r\n|[\s\S]))*(\2)?|`(?:[^`\\$]|\\[\s\S]|\$(?!\{)|\$\{(?:[^{}]|\{[^}]*\}?)*\}?)*(`)?)|(\/\/.*)|(\/\*(?:[^*]|\*(?!\/))*(\*\/)?)|(\/(?!\*)(?:\[(?:(?![\]\\]).|\\.)*\]|(?![\/\]\\]).|\\.)+\/(?:(?!\s*(?:\b|[\u0080-\uFFFF$\\'"~({]|[+\-!](?!=)|\.?\d))|[gmiyus]{1,6}\b(?![\u0080-\uFFFF$\\]|\s*(?:[+\-*%&|^<>!=?({]|\/(?![\/*])))))|(0[xX][\da-fA-F]+|0[oO][0-7]+|0[bB][01]+|(?:\d*\.\d+|\d+\.?)(?:[eE][+-]?\d+)?)|((?!\d)(?:(?!\s)[$\w\u0080-\uFFFF]|\\u[\da-fA-F]{4}|\\u\{[\da-fA-F]+\})+)|(--|\+\+|&&|\|\||=>|\.{3}|(?:[+\-\/%&|^]|\*{1,2}|<{1,2}|>{1,3}|!=?|={1,2})=?|[?~.,:;[\](){}])|(\s+)|(^$|[\s\S])/g;
|
|
183024
|
+
exports.matchToToken = function(match) {
|
|
183025
|
+
var token = { type: "invalid", value: match[0], closed: void 0 };
|
|
183026
|
+
if (match[1]) token.type = "string", token.closed = !!(match[3] || match[4]);
|
|
183027
|
+
else if (match[5]) token.type = "comment";
|
|
183028
|
+
else if (match[6]) token.type = "comment", token.closed = !!match[7];
|
|
183029
|
+
else if (match[8]) token.type = "regex";
|
|
183030
|
+
else if (match[9]) token.type = "number";
|
|
183031
|
+
else if (match[10]) token.type = "name";
|
|
183032
|
+
else if (match[11]) token.type = "punctuator";
|
|
183033
|
+
else if (match[12]) token.type = "whitespace";
|
|
183034
|
+
return token;
|
|
183035
|
+
};
|
|
183036
|
+
}
|
|
183037
|
+
});
|
|
183038
|
+
|
|
183039
|
+
// node_modules/.pnpm/@babel+helper-validator-identifier@7.28.5/node_modules/@babel/helper-validator-identifier/lib/identifier.js
|
|
183040
|
+
var require_identifier = __commonJS({
|
|
183041
|
+
"node_modules/.pnpm/@babel+helper-validator-identifier@7.28.5/node_modules/@babel/helper-validator-identifier/lib/identifier.js"(exports) {
|
|
183042
|
+
"use strict";
|
|
183043
|
+
Object.defineProperty(exports, "__esModule", {
|
|
183044
|
+
value: true
|
|
183045
|
+
});
|
|
183046
|
+
exports.isIdentifierChar = isIdentifierChar;
|
|
183047
|
+
exports.isIdentifierName = isIdentifierName;
|
|
183048
|
+
exports.isIdentifierStart = isIdentifierStart;
|
|
183049
|
+
var nonASCIIidentifierStartChars = "\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u052F\u0531-\u0556\u0559\u0560-\u0588\u05D0-\u05EA\u05EF-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u0860-\u086A\u0870-\u0887\u0889-\u088F\u08A0-\u08C9\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u09FC\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0AF9\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D\u0C58-\u0C5A\u0C5C\u0C5D\u0C60\u0C61\u0C80\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDC-\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D04-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D54-\u0D56\u0D5F-\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81\u0E82\u0E84\u0E86-\u0E8A\u0E8C-\u0EA3\u0EA5\u0EA7-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F5\u13F8-\u13FD\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u1711\u171F-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u1820-\u1878\u1880-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u1A00-\u1A16\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4C\u1B83-\u1BA0\u1BAE\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1C80-\u1C8A\u1C90-\u1CBA\u1CBD-\u1CBF\u1CE9-\u1CEC\u1CEE-\u1CF3\u1CF5\u1CF6\u1CFA\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2118-\u211D\u2124\u2126\u2128\u212A-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303C\u3041-\u3096\u309B-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312F\u3131-\u318E\u31A0-\u31BF\u31F0-\u31FF\u3400-\u4DBF\u4E00-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA66E\uA67F-\uA69D\uA6A0-\uA6EF\uA717-\uA71F\uA722-\uA788\uA78B-\uA7DC\uA7F1-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA8FD\uA8FE\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uA9E0-\uA9E4\uA9E6-\uA9EF\uA9FA-\uA9FE\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB69\uAB70-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC";
|
|
183050
|
+
var nonASCIIidentifierChars = "\xB7\u0300-\u036F\u0387\u0483-\u0487\u0591-\u05BD\u05BF\u05C1\u05C2\u05C4\u05C5\u05C7\u0610-\u061A\u064B-\u0669\u0670\u06D6-\u06DC\u06DF-\u06E4\u06E7\u06E8\u06EA-\u06ED\u06F0-\u06F9\u0711\u0730-\u074A\u07A6-\u07B0\u07C0-\u07C9\u07EB-\u07F3\u07FD\u0816-\u0819\u081B-\u0823\u0825-\u0827\u0829-\u082D\u0859-\u085B\u0897-\u089F\u08CA-\u08E1\u08E3-\u0903\u093A-\u093C\u093E-\u094F\u0951-\u0957\u0962\u0963\u0966-\u096F\u0981-\u0983\u09BC\u09BE-\u09C4\u09C7\u09C8\u09CB-\u09CD\u09D7\u09E2\u09E3\u09E6-\u09EF\u09FE\u0A01-\u0A03\u0A3C\u0A3E-\u0A42\u0A47\u0A48\u0A4B-\u0A4D\u0A51\u0A66-\u0A71\u0A75\u0A81-\u0A83\u0ABC\u0ABE-\u0AC5\u0AC7-\u0AC9\u0ACB-\u0ACD\u0AE2\u0AE3\u0AE6-\u0AEF\u0AFA-\u0AFF\u0B01-\u0B03\u0B3C\u0B3E-\u0B44\u0B47\u0B48\u0B4B-\u0B4D\u0B55-\u0B57\u0B62\u0B63\u0B66-\u0B6F\u0B82\u0BBE-\u0BC2\u0BC6-\u0BC8\u0BCA-\u0BCD\u0BD7\u0BE6-\u0BEF\u0C00-\u0C04\u0C3C\u0C3E-\u0C44\u0C46-\u0C48\u0C4A-\u0C4D\u0C55\u0C56\u0C62\u0C63\u0C66-\u0C6F\u0C81-\u0C83\u0CBC\u0CBE-\u0CC4\u0CC6-\u0CC8\u0CCA-\u0CCD\u0CD5\u0CD6\u0CE2\u0CE3\u0CE6-\u0CEF\u0CF3\u0D00-\u0D03\u0D3B\u0D3C\u0D3E-\u0D44\u0D46-\u0D48\u0D4A-\u0D4D\u0D57\u0D62\u0D63\u0D66-\u0D6F\u0D81-\u0D83\u0DCA\u0DCF-\u0DD4\u0DD6\u0DD8-\u0DDF\u0DE6-\u0DEF\u0DF2\u0DF3\u0E31\u0E34-\u0E3A\u0E47-\u0E4E\u0E50-\u0E59\u0EB1\u0EB4-\u0EBC\u0EC8-\u0ECE\u0ED0-\u0ED9\u0F18\u0F19\u0F20-\u0F29\u0F35\u0F37\u0F39\u0F3E\u0F3F\u0F71-\u0F84\u0F86\u0F87\u0F8D-\u0F97\u0F99-\u0FBC\u0FC6\u102B-\u103E\u1040-\u1049\u1056-\u1059\u105E-\u1060\u1062-\u1064\u1067-\u106D\u1071-\u1074\u1082-\u108D\u108F-\u109D\u135D-\u135F\u1369-\u1371\u1712-\u1715\u1732-\u1734\u1752\u1753\u1772\u1773\u17B4-\u17D3\u17DD\u17E0-\u17E9\u180B-\u180D\u180F-\u1819\u18A9\u1920-\u192B\u1930-\u193B\u1946-\u194F\u19D0-\u19DA\u1A17-\u1A1B\u1A55-\u1A5E\u1A60-\u1A7C\u1A7F-\u1A89\u1A90-\u1A99\u1AB0-\u1ABD\u1ABF-\u1ADD\u1AE0-\u1AEB\u1B00-\u1B04\u1B34-\u1B44\u1B50-\u1B59\u1B6B-\u1B73\u1B80-\u1B82\u1BA1-\u1BAD\u1BB0-\u1BB9\u1BE6-\u1BF3\u1C24-\u1C37\u1C40-\u1C49\u1C50-\u1C59\u1CD0-\u1CD2\u1CD4-\u1CE8\u1CED\u1CF4\u1CF7-\u1CF9\u1DC0-\u1DFF\u200C\u200D\u203F\u2040\u2054\u20D0-\u20DC\u20E1\u20E5-\u20F0\u2CEF-\u2CF1\u2D7F\u2DE0-\u2DFF\u302A-\u302F\u3099\u309A\u30FB\uA620-\uA629\uA66F\uA674-\uA67D\uA69E\uA69F\uA6F0\uA6F1\uA802\uA806\uA80B\uA823-\uA827\uA82C\uA880\uA881\uA8B4-\uA8C5\uA8D0-\uA8D9\uA8E0-\uA8F1\uA8FF-\uA909\uA926-\uA92D\uA947-\uA953\uA980-\uA983\uA9B3-\uA9C0\uA9D0-\uA9D9\uA9E5\uA9F0-\uA9F9\uAA29-\uAA36\uAA43\uAA4C\uAA4D\uAA50-\uAA59\uAA7B-\uAA7D\uAAB0\uAAB2-\uAAB4\uAAB7\uAAB8\uAABE\uAABF\uAAC1\uAAEB-\uAAEF\uAAF5\uAAF6\uABE3-\uABEA\uABEC\uABED\uABF0-\uABF9\uFB1E\uFE00-\uFE0F\uFE20-\uFE2F\uFE33\uFE34\uFE4D-\uFE4F\uFF10-\uFF19\uFF3F\uFF65";
|
|
183051
|
+
var nonASCIIidentifierStart = new RegExp("[" + nonASCIIidentifierStartChars + "]");
|
|
183052
|
+
var nonASCIIidentifier = new RegExp("[" + nonASCIIidentifierStartChars + nonASCIIidentifierChars + "]");
|
|
183053
|
+
nonASCIIidentifierStartChars = nonASCIIidentifierChars = null;
|
|
183054
|
+
var astralIdentifierStartCodes = [0, 11, 2, 25, 2, 18, 2, 1, 2, 14, 3, 13, 35, 122, 70, 52, 268, 28, 4, 48, 48, 31, 14, 29, 6, 37, 11, 29, 3, 35, 5, 7, 2, 4, 43, 157, 19, 35, 5, 35, 5, 39, 9, 51, 13, 10, 2, 14, 2, 6, 2, 1, 2, 10, 2, 14, 2, 6, 2, 1, 4, 51, 13, 310, 10, 21, 11, 7, 25, 5, 2, 41, 2, 8, 70, 5, 3, 0, 2, 43, 2, 1, 4, 0, 3, 22, 11, 22, 10, 30, 66, 18, 2, 1, 11, 21, 11, 25, 7, 25, 39, 55, 7, 1, 65, 0, 16, 3, 2, 2, 2, 28, 43, 28, 4, 28, 36, 7, 2, 27, 28, 53, 11, 21, 11, 18, 14, 17, 111, 72, 56, 50, 14, 50, 14, 35, 39, 27, 10, 22, 251, 41, 7, 1, 17, 5, 57, 28, 11, 0, 9, 21, 43, 17, 47, 20, 28, 22, 13, 52, 58, 1, 3, 0, 14, 44, 33, 24, 27, 35, 30, 0, 3, 0, 9, 34, 4, 0, 13, 47, 15, 3, 22, 0, 2, 0, 36, 17, 2, 24, 20, 1, 64, 6, 2, 0, 2, 3, 2, 14, 2, 9, 8, 46, 39, 7, 3, 1, 3, 21, 2, 6, 2, 1, 2, 4, 4, 0, 19, 0, 13, 4, 31, 9, 2, 0, 3, 0, 2, 37, 2, 0, 26, 0, 2, 0, 45, 52, 19, 3, 21, 2, 31, 47, 21, 1, 2, 0, 185, 46, 42, 3, 37, 47, 21, 0, 60, 42, 14, 0, 72, 26, 38, 6, 186, 43, 117, 63, 32, 7, 3, 0, 3, 7, 2, 1, 2, 23, 16, 0, 2, 0, 95, 7, 3, 38, 17, 0, 2, 0, 29, 0, 11, 39, 8, 0, 22, 0, 12, 45, 20, 0, 19, 72, 200, 32, 32, 8, 2, 36, 18, 0, 50, 29, 113, 6, 2, 1, 2, 37, 22, 0, 26, 5, 2, 1, 2, 31, 15, 0, 24, 43, 261, 18, 16, 0, 2, 12, 2, 33, 125, 0, 80, 921, 103, 110, 18, 195, 2637, 96, 16, 1071, 18, 5, 26, 3994, 6, 582, 6842, 29, 1763, 568, 8, 30, 18, 78, 18, 29, 19, 47, 17, 3, 32, 20, 6, 18, 433, 44, 212, 63, 33, 24, 3, 24, 45, 74, 6, 0, 67, 12, 65, 1, 2, 0, 15, 4, 10, 7381, 42, 31, 98, 114, 8702, 3, 2, 6, 2, 1, 2, 290, 16, 0, 30, 2, 3, 0, 15, 3, 9, 395, 2309, 106, 6, 12, 4, 8, 8, 9, 5991, 84, 2, 70, 2, 1, 3, 0, 3, 1, 3, 3, 2, 11, 2, 0, 2, 6, 2, 64, 2, 3, 3, 7, 2, 6, 2, 27, 2, 3, 2, 4, 2, 0, 4, 6, 2, 339, 3, 24, 2, 24, 2, 30, 2, 24, 2, 30, 2, 24, 2, 30, 2, 24, 2, 30, 2, 24, 2, 7, 1845, 30, 7, 5, 262, 61, 147, 44, 11, 6, 17, 0, 322, 29, 19, 43, 485, 27, 229, 29, 3, 0, 208, 30, 2, 2, 2, 1, 2, 6, 3, 4, 10, 1, 225, 6, 2, 3, 2, 1, 2, 14, 2, 196, 60, 67, 8, 0, 1205, 3, 2, 26, 2, 1, 2, 0, 3, 0, 2, 9, 2, 3, 2, 0, 2, 0, 7, 0, 5, 0, 2, 0, 2, 0, 2, 2, 2, 1, 2, 0, 3, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 1, 2, 0, 3, 3, 2, 6, 2, 3, 2, 3, 2, 0, 2, 9, 2, 16, 6, 2, 2, 4, 2, 16, 4421, 42719, 33, 4381, 3, 5773, 3, 7472, 16, 621, 2467, 541, 1507, 4938, 6, 8489];
|
|
183055
|
+
var astralIdentifierCodes = [509, 0, 227, 0, 150, 4, 294, 9, 1368, 2, 2, 1, 6, 3, 41, 2, 5, 0, 166, 1, 574, 3, 9, 9, 7, 9, 32, 4, 318, 1, 78, 5, 71, 10, 50, 3, 123, 2, 54, 14, 32, 10, 3, 1, 11, 3, 46, 10, 8, 0, 46, 9, 7, 2, 37, 13, 2, 9, 6, 1, 45, 0, 13, 2, 49, 13, 9, 3, 2, 11, 83, 11, 7, 0, 3, 0, 158, 11, 6, 9, 7, 3, 56, 1, 2, 6, 3, 1, 3, 2, 10, 0, 11, 1, 3, 6, 4, 4, 68, 8, 2, 0, 3, 0, 2, 3, 2, 4, 2, 0, 15, 1, 83, 17, 10, 9, 5, 0, 82, 19, 13, 9, 214, 6, 3, 8, 28, 1, 83, 16, 16, 9, 82, 12, 9, 9, 7, 19, 58, 14, 5, 9, 243, 14, 166, 9, 71, 5, 2, 1, 3, 3, 2, 0, 2, 1, 13, 9, 120, 6, 3, 6, 4, 0, 29, 9, 41, 6, 2, 3, 9, 0, 10, 10, 47, 15, 199, 7, 137, 9, 54, 7, 2, 7, 17, 9, 57, 21, 2, 13, 123, 5, 4, 0, 2, 1, 2, 6, 2, 0, 9, 9, 49, 4, 2, 1, 2, 4, 9, 9, 55, 9, 266, 3, 10, 1, 2, 0, 49, 6, 4, 4, 14, 10, 5350, 0, 7, 14, 11465, 27, 2343, 9, 87, 9, 39, 4, 60, 6, 26, 9, 535, 9, 470, 0, 2, 54, 8, 3, 82, 0, 12, 1, 19628, 1, 4178, 9, 519, 45, 3, 22, 543, 4, 4, 5, 9, 7, 3, 6, 31, 3, 149, 2, 1418, 49, 513, 54, 5, 49, 9, 0, 15, 0, 23, 4, 2, 14, 1361, 6, 2, 16, 3, 6, 2, 1, 2, 4, 101, 0, 161, 6, 10, 9, 357, 0, 62, 13, 499, 13, 245, 1, 2, 9, 233, 0, 3, 0, 8, 1, 6, 0, 475, 6, 110, 6, 6, 9, 4759, 9, 787719, 239];
|
|
183056
|
+
function isInAstralSet(code, set) {
|
|
183057
|
+
let pos = 65536;
|
|
183058
|
+
for (let i = 0, length = set.length; i < length; i += 2) {
|
|
183059
|
+
pos += set[i];
|
|
183060
|
+
if (pos > code) return false;
|
|
183061
|
+
pos += set[i + 1];
|
|
183062
|
+
if (pos >= code) return true;
|
|
183063
|
+
}
|
|
183064
|
+
return false;
|
|
183065
|
+
}
|
|
183066
|
+
function isIdentifierStart(code) {
|
|
183067
|
+
if (code < 65) return code === 36;
|
|
183068
|
+
if (code <= 90) return true;
|
|
183069
|
+
if (code < 97) return code === 95;
|
|
183070
|
+
if (code <= 122) return true;
|
|
183071
|
+
if (code <= 65535) {
|
|
183072
|
+
return code >= 170 && nonASCIIidentifierStart.test(String.fromCharCode(code));
|
|
183073
|
+
}
|
|
183074
|
+
return isInAstralSet(code, astralIdentifierStartCodes);
|
|
183075
|
+
}
|
|
183076
|
+
function isIdentifierChar(code) {
|
|
183077
|
+
if (code < 48) return code === 36;
|
|
183078
|
+
if (code < 58) return true;
|
|
183079
|
+
if (code < 65) return false;
|
|
183080
|
+
if (code <= 90) return true;
|
|
183081
|
+
if (code < 97) return code === 95;
|
|
183082
|
+
if (code <= 122) return true;
|
|
183083
|
+
if (code <= 65535) {
|
|
183084
|
+
return code >= 170 && nonASCIIidentifier.test(String.fromCharCode(code));
|
|
183085
|
+
}
|
|
183086
|
+
return isInAstralSet(code, astralIdentifierStartCodes) || isInAstralSet(code, astralIdentifierCodes);
|
|
183087
|
+
}
|
|
183088
|
+
function isIdentifierName(name) {
|
|
183089
|
+
let isFirst = true;
|
|
183090
|
+
for (let i = 0; i < name.length; i++) {
|
|
183091
|
+
let cp = name.charCodeAt(i);
|
|
183092
|
+
if ((cp & 64512) === 55296 && i + 1 < name.length) {
|
|
183093
|
+
const trail = name.charCodeAt(++i);
|
|
183094
|
+
if ((trail & 64512) === 56320) {
|
|
183095
|
+
cp = 65536 + ((cp & 1023) << 10) + (trail & 1023);
|
|
183096
|
+
}
|
|
183097
|
+
}
|
|
183098
|
+
if (isFirst) {
|
|
183099
|
+
isFirst = false;
|
|
183100
|
+
if (!isIdentifierStart(cp)) {
|
|
183101
|
+
return false;
|
|
183102
|
+
}
|
|
183103
|
+
} else if (!isIdentifierChar(cp)) {
|
|
183104
|
+
return false;
|
|
183105
|
+
}
|
|
183106
|
+
}
|
|
183107
|
+
return !isFirst;
|
|
183108
|
+
}
|
|
183109
|
+
}
|
|
183110
|
+
});
|
|
183111
|
+
|
|
183112
|
+
// node_modules/.pnpm/@babel+helper-validator-identifier@7.28.5/node_modules/@babel/helper-validator-identifier/lib/keyword.js
|
|
183113
|
+
var require_keyword = __commonJS({
|
|
183114
|
+
"node_modules/.pnpm/@babel+helper-validator-identifier@7.28.5/node_modules/@babel/helper-validator-identifier/lib/keyword.js"(exports) {
|
|
183115
|
+
"use strict";
|
|
183116
|
+
Object.defineProperty(exports, "__esModule", {
|
|
183117
|
+
value: true
|
|
183118
|
+
});
|
|
183119
|
+
exports.isKeyword = isKeyword;
|
|
183120
|
+
exports.isReservedWord = isReservedWord;
|
|
183121
|
+
exports.isStrictBindOnlyReservedWord = isStrictBindOnlyReservedWord;
|
|
183122
|
+
exports.isStrictBindReservedWord = isStrictBindReservedWord;
|
|
183123
|
+
exports.isStrictReservedWord = isStrictReservedWord;
|
|
183124
|
+
var reservedWords = {
|
|
183125
|
+
keyword: ["break", "case", "catch", "continue", "debugger", "default", "do", "else", "finally", "for", "function", "if", "return", "switch", "throw", "try", "var", "const", "while", "with", "new", "this", "super", "class", "extends", "export", "import", "null", "true", "false", "in", "instanceof", "typeof", "void", "delete"],
|
|
183126
|
+
strict: ["implements", "interface", "let", "package", "private", "protected", "public", "static", "yield"],
|
|
183127
|
+
strictBind: ["eval", "arguments"]
|
|
183128
|
+
};
|
|
183129
|
+
var keywords = new Set(reservedWords.keyword);
|
|
183130
|
+
var reservedWordsStrictSet = new Set(reservedWords.strict);
|
|
183131
|
+
var reservedWordsStrictBindSet = new Set(reservedWords.strictBind);
|
|
183132
|
+
function isReservedWord(word, inModule) {
|
|
183133
|
+
return inModule && word === "await" || word === "enum";
|
|
183134
|
+
}
|
|
183135
|
+
function isStrictReservedWord(word, inModule) {
|
|
183136
|
+
return isReservedWord(word, inModule) || reservedWordsStrictSet.has(word);
|
|
183137
|
+
}
|
|
183138
|
+
function isStrictBindOnlyReservedWord(word) {
|
|
183139
|
+
return reservedWordsStrictBindSet.has(word);
|
|
183140
|
+
}
|
|
183141
|
+
function isStrictBindReservedWord(word, inModule) {
|
|
183142
|
+
return isStrictReservedWord(word, inModule) || isStrictBindOnlyReservedWord(word);
|
|
183143
|
+
}
|
|
183144
|
+
function isKeyword(word) {
|
|
183145
|
+
return keywords.has(word);
|
|
183146
|
+
}
|
|
183147
|
+
}
|
|
183148
|
+
});
|
|
183149
|
+
|
|
183150
|
+
// node_modules/.pnpm/@babel+helper-validator-identifier@7.28.5/node_modules/@babel/helper-validator-identifier/lib/index.js
|
|
183151
|
+
var require_lib = __commonJS({
|
|
183152
|
+
"node_modules/.pnpm/@babel+helper-validator-identifier@7.28.5/node_modules/@babel/helper-validator-identifier/lib/index.js"(exports) {
|
|
183153
|
+
"use strict";
|
|
183154
|
+
Object.defineProperty(exports, "__esModule", {
|
|
183155
|
+
value: true
|
|
183156
|
+
});
|
|
183157
|
+
Object.defineProperty(exports, "isIdentifierChar", {
|
|
183158
|
+
enumerable: true,
|
|
183159
|
+
get: function() {
|
|
183160
|
+
return _identifier.isIdentifierChar;
|
|
183161
|
+
}
|
|
183162
|
+
});
|
|
183163
|
+
Object.defineProperty(exports, "isIdentifierName", {
|
|
183164
|
+
enumerable: true,
|
|
183165
|
+
get: function() {
|
|
183166
|
+
return _identifier.isIdentifierName;
|
|
183167
|
+
}
|
|
183168
|
+
});
|
|
183169
|
+
Object.defineProperty(exports, "isIdentifierStart", {
|
|
183170
|
+
enumerable: true,
|
|
183171
|
+
get: function() {
|
|
183172
|
+
return _identifier.isIdentifierStart;
|
|
183173
|
+
}
|
|
183174
|
+
});
|
|
183175
|
+
Object.defineProperty(exports, "isKeyword", {
|
|
183176
|
+
enumerable: true,
|
|
183177
|
+
get: function() {
|
|
183178
|
+
return _keyword.isKeyword;
|
|
183179
|
+
}
|
|
183180
|
+
});
|
|
183181
|
+
Object.defineProperty(exports, "isReservedWord", {
|
|
183182
|
+
enumerable: true,
|
|
183183
|
+
get: function() {
|
|
183184
|
+
return _keyword.isReservedWord;
|
|
183185
|
+
}
|
|
183186
|
+
});
|
|
183187
|
+
Object.defineProperty(exports, "isStrictBindOnlyReservedWord", {
|
|
183188
|
+
enumerable: true,
|
|
183189
|
+
get: function() {
|
|
183190
|
+
return _keyword.isStrictBindOnlyReservedWord;
|
|
183191
|
+
}
|
|
183192
|
+
});
|
|
183193
|
+
Object.defineProperty(exports, "isStrictBindReservedWord", {
|
|
183194
|
+
enumerable: true,
|
|
183195
|
+
get: function() {
|
|
183196
|
+
return _keyword.isStrictBindReservedWord;
|
|
183197
|
+
}
|
|
183198
|
+
});
|
|
183199
|
+
Object.defineProperty(exports, "isStrictReservedWord", {
|
|
183200
|
+
enumerable: true,
|
|
183201
|
+
get: function() {
|
|
183202
|
+
return _keyword.isStrictReservedWord;
|
|
183203
|
+
}
|
|
183204
|
+
});
|
|
183205
|
+
var _identifier = require_identifier();
|
|
183206
|
+
var _keyword = require_keyword();
|
|
183207
|
+
}
|
|
183208
|
+
});
|
|
183209
|
+
|
|
183210
|
+
// node_modules/.pnpm/@babel+code-frame@7.29.0/node_modules/@babel/code-frame/lib/index.js
|
|
183211
|
+
var require_lib2 = __commonJS({
|
|
183212
|
+
"node_modules/.pnpm/@babel+code-frame@7.29.0/node_modules/@babel/code-frame/lib/index.js"(exports) {
|
|
183213
|
+
"use strict";
|
|
183214
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
183215
|
+
var picocolors = require_picocolors();
|
|
183216
|
+
var jsTokens = require_js_tokens();
|
|
183217
|
+
var helperValidatorIdentifier = require_lib();
|
|
183218
|
+
function isColorSupported() {
|
|
183219
|
+
return typeof process === "object" && (process.env.FORCE_COLOR === "0" || process.env.FORCE_COLOR === "false") ? false : picocolors.isColorSupported;
|
|
183220
|
+
}
|
|
183221
|
+
var compose = (f, g) => (v) => f(g(v));
|
|
183222
|
+
function buildDefs(colors) {
|
|
183223
|
+
return {
|
|
183224
|
+
keyword: colors.cyan,
|
|
183225
|
+
capitalized: colors.yellow,
|
|
183226
|
+
jsxIdentifier: colors.yellow,
|
|
183227
|
+
punctuator: colors.yellow,
|
|
183228
|
+
number: colors.magenta,
|
|
183229
|
+
string: colors.green,
|
|
183230
|
+
regex: colors.magenta,
|
|
183231
|
+
comment: colors.gray,
|
|
183232
|
+
invalid: compose(compose(colors.white, colors.bgRed), colors.bold),
|
|
183233
|
+
gutter: colors.gray,
|
|
183234
|
+
marker: compose(colors.red, colors.bold),
|
|
183235
|
+
message: compose(colors.red, colors.bold),
|
|
183236
|
+
reset: colors.reset
|
|
183237
|
+
};
|
|
183238
|
+
}
|
|
183239
|
+
var defsOn = buildDefs(picocolors.createColors(true));
|
|
183240
|
+
var defsOff = buildDefs(picocolors.createColors(false));
|
|
183241
|
+
function getDefs(enabled) {
|
|
183242
|
+
return enabled ? defsOn : defsOff;
|
|
183243
|
+
}
|
|
183244
|
+
var sometimesKeywords = /* @__PURE__ */ new Set(["as", "async", "from", "get", "of", "set"]);
|
|
183245
|
+
var NEWLINE$1 = /\r\n|[\n\r\u2028\u2029]/;
|
|
183246
|
+
var BRACKET = /^[()[\]{}]$/;
|
|
183247
|
+
var tokenize;
|
|
183248
|
+
var JSX_TAG = /^[a-z][\w-]*$/i;
|
|
183249
|
+
var getTokenType = function(token, offset, text) {
|
|
183250
|
+
if (token.type === "name") {
|
|
183251
|
+
const tokenValue = token.value;
|
|
183252
|
+
if (helperValidatorIdentifier.isKeyword(tokenValue) || helperValidatorIdentifier.isStrictReservedWord(tokenValue, true) || sometimesKeywords.has(tokenValue)) {
|
|
183253
|
+
return "keyword";
|
|
183254
|
+
}
|
|
183255
|
+
if (JSX_TAG.test(tokenValue) && (text[offset - 1] === "<" || text.slice(offset - 2, offset) === "</")) {
|
|
183256
|
+
return "jsxIdentifier";
|
|
183257
|
+
}
|
|
183258
|
+
const firstChar = String.fromCodePoint(tokenValue.codePointAt(0));
|
|
183259
|
+
if (firstChar !== firstChar.toLowerCase()) {
|
|
183260
|
+
return "capitalized";
|
|
183261
|
+
}
|
|
183262
|
+
}
|
|
183263
|
+
if (token.type === "punctuator" && BRACKET.test(token.value)) {
|
|
183264
|
+
return "bracket";
|
|
183265
|
+
}
|
|
183266
|
+
if (token.type === "invalid" && (token.value === "@" || token.value === "#")) {
|
|
183267
|
+
return "punctuator";
|
|
183268
|
+
}
|
|
183269
|
+
return token.type;
|
|
183270
|
+
};
|
|
183271
|
+
tokenize = function* (text) {
|
|
183272
|
+
let match;
|
|
183273
|
+
while (match = jsTokens.default.exec(text)) {
|
|
183274
|
+
const token = jsTokens.matchToToken(match);
|
|
183275
|
+
yield {
|
|
183276
|
+
type: getTokenType(token, match.index, text),
|
|
183277
|
+
value: token.value
|
|
183278
|
+
};
|
|
183279
|
+
}
|
|
183280
|
+
};
|
|
183281
|
+
function highlight(text) {
|
|
183282
|
+
if (text === "") return "";
|
|
183283
|
+
const defs = getDefs(true);
|
|
183284
|
+
let highlighted = "";
|
|
183285
|
+
for (const {
|
|
183286
|
+
type,
|
|
183287
|
+
value
|
|
183288
|
+
} of tokenize(text)) {
|
|
183289
|
+
if (type in defs) {
|
|
183290
|
+
highlighted += value.split(NEWLINE$1).map((str) => defs[type](str)).join("\n");
|
|
183291
|
+
} else {
|
|
183292
|
+
highlighted += value;
|
|
183293
|
+
}
|
|
183294
|
+
}
|
|
183295
|
+
return highlighted;
|
|
183296
|
+
}
|
|
183297
|
+
var deprecationWarningShown = false;
|
|
183298
|
+
var NEWLINE = /\r\n|[\n\r\u2028\u2029]/;
|
|
183299
|
+
function getMarkerLines(loc, source, opts, startLineBaseZero) {
|
|
183300
|
+
const startLoc = Object.assign({
|
|
183301
|
+
column: 0,
|
|
183302
|
+
line: -1
|
|
183303
|
+
}, loc.start);
|
|
183304
|
+
const endLoc = Object.assign({}, startLoc, loc.end);
|
|
183305
|
+
const {
|
|
183306
|
+
linesAbove = 2,
|
|
183307
|
+
linesBelow = 3
|
|
183308
|
+
} = opts || {};
|
|
183309
|
+
const startLine = startLoc.line - startLineBaseZero;
|
|
183310
|
+
const startColumn = startLoc.column;
|
|
183311
|
+
const endLine = endLoc.line - startLineBaseZero;
|
|
183312
|
+
const endColumn = endLoc.column;
|
|
183313
|
+
let start = Math.max(startLine - (linesAbove + 1), 0);
|
|
183314
|
+
let end = Math.min(source.length, endLine + linesBelow);
|
|
183315
|
+
if (startLine === -1) {
|
|
183316
|
+
start = 0;
|
|
183317
|
+
}
|
|
183318
|
+
if (endLine === -1) {
|
|
183319
|
+
end = source.length;
|
|
183320
|
+
}
|
|
183321
|
+
const lineDiff = endLine - startLine;
|
|
183322
|
+
const markerLines = {};
|
|
183323
|
+
if (lineDiff) {
|
|
183324
|
+
for (let i = 0; i <= lineDiff; i++) {
|
|
183325
|
+
const lineNumber = i + startLine;
|
|
183326
|
+
if (!startColumn) {
|
|
183327
|
+
markerLines[lineNumber] = true;
|
|
183328
|
+
} else if (i === 0) {
|
|
183329
|
+
const sourceLength = source[lineNumber - 1].length;
|
|
183330
|
+
markerLines[lineNumber] = [startColumn, sourceLength - startColumn + 1];
|
|
183331
|
+
} else if (i === lineDiff) {
|
|
183332
|
+
markerLines[lineNumber] = [0, endColumn];
|
|
183333
|
+
} else {
|
|
183334
|
+
const sourceLength = source[lineNumber - i].length;
|
|
183335
|
+
markerLines[lineNumber] = [0, sourceLength];
|
|
183336
|
+
}
|
|
183337
|
+
}
|
|
183338
|
+
} else {
|
|
183339
|
+
if (startColumn === endColumn) {
|
|
183340
|
+
if (startColumn) {
|
|
183341
|
+
markerLines[startLine] = [startColumn, 0];
|
|
183342
|
+
} else {
|
|
183343
|
+
markerLines[startLine] = true;
|
|
183344
|
+
}
|
|
183345
|
+
} else {
|
|
183346
|
+
markerLines[startLine] = [startColumn, endColumn - startColumn];
|
|
183347
|
+
}
|
|
183348
|
+
}
|
|
183349
|
+
return {
|
|
183350
|
+
start,
|
|
183351
|
+
end,
|
|
183352
|
+
markerLines
|
|
183353
|
+
};
|
|
183354
|
+
}
|
|
183355
|
+
function codeFrameColumns2(rawLines, loc, opts = {}) {
|
|
183356
|
+
const shouldHighlight = opts.forceColor || isColorSupported() && opts.highlightCode;
|
|
183357
|
+
const startLineBaseZero = (opts.startLine || 1) - 1;
|
|
183358
|
+
const defs = getDefs(shouldHighlight);
|
|
183359
|
+
const lines = rawLines.split(NEWLINE);
|
|
183360
|
+
const {
|
|
183361
|
+
start,
|
|
183362
|
+
end,
|
|
183363
|
+
markerLines
|
|
183364
|
+
} = getMarkerLines(loc, lines, opts, startLineBaseZero);
|
|
183365
|
+
const hasColumns = loc.start && typeof loc.start.column === "number";
|
|
183366
|
+
const numberMaxWidth = String(end + startLineBaseZero).length;
|
|
183367
|
+
const highlightedLines = shouldHighlight ? highlight(rawLines) : rawLines;
|
|
183368
|
+
let frame = highlightedLines.split(NEWLINE, end).slice(start, end).map((line, index2) => {
|
|
183369
|
+
const number = start + 1 + index2;
|
|
183370
|
+
const paddedNumber = ` ${number + startLineBaseZero}`.slice(-numberMaxWidth);
|
|
183371
|
+
const gutter = ` ${paddedNumber} |`;
|
|
183372
|
+
const hasMarker = markerLines[number];
|
|
183373
|
+
const lastMarkerLine = !markerLines[number + 1];
|
|
183374
|
+
if (hasMarker) {
|
|
183375
|
+
let markerLine = "";
|
|
183376
|
+
if (Array.isArray(hasMarker)) {
|
|
183377
|
+
const markerSpacing = line.slice(0, Math.max(hasMarker[0] - 1, 0)).replace(/[^\t]/g, " ");
|
|
183378
|
+
const numberOfMarkers = hasMarker[1] || 1;
|
|
183379
|
+
markerLine = ["\n ", defs.gutter(gutter.replace(/\d/g, " ")), " ", markerSpacing, defs.marker("^").repeat(numberOfMarkers)].join("");
|
|
183380
|
+
if (lastMarkerLine && opts.message) {
|
|
183381
|
+
markerLine += " " + defs.message(opts.message);
|
|
183382
|
+
}
|
|
183383
|
+
}
|
|
183384
|
+
return [defs.marker(">"), defs.gutter(gutter), line.length > 0 ? ` ${line}` : "", markerLine].join("");
|
|
183385
|
+
} else {
|
|
183386
|
+
return ` ${defs.gutter(gutter)}${line.length > 0 ? ` ${line}` : ""}`;
|
|
183387
|
+
}
|
|
183388
|
+
}).join("\n");
|
|
183389
|
+
if (opts.message && !hasColumns) {
|
|
183390
|
+
frame = `${" ".repeat(numberMaxWidth + 1)}${opts.message}
|
|
183391
|
+
${frame}`;
|
|
183392
|
+
}
|
|
183393
|
+
if (shouldHighlight) {
|
|
183394
|
+
return defs.reset(frame);
|
|
183395
|
+
} else {
|
|
183396
|
+
return frame;
|
|
183397
|
+
}
|
|
183398
|
+
}
|
|
183399
|
+
function index(rawLines, lineNumber, colNumber, opts = {}) {
|
|
183400
|
+
if (!deprecationWarningShown) {
|
|
183401
|
+
deprecationWarningShown = true;
|
|
183402
|
+
const message = "Passing lineNumber and colNumber is deprecated to @babel/code-frame. Please use `codeFrameColumns`.";
|
|
183403
|
+
if (process.emitWarning) {
|
|
183404
|
+
process.emitWarning(message, "DeprecationWarning");
|
|
183405
|
+
} else {
|
|
183406
|
+
const deprecationError = new Error(message);
|
|
183407
|
+
deprecationError.name = "DeprecationWarning";
|
|
183408
|
+
console.warn(new Error(message));
|
|
183409
|
+
}
|
|
183410
|
+
}
|
|
183411
|
+
colNumber = Math.max(colNumber, 0);
|
|
183412
|
+
const location = {
|
|
183413
|
+
start: {
|
|
183414
|
+
column: colNumber,
|
|
183415
|
+
line: lineNumber
|
|
183416
|
+
}
|
|
183417
|
+
};
|
|
183418
|
+
return codeFrameColumns2(rawLines, location, opts);
|
|
183419
|
+
}
|
|
183420
|
+
exports.codeFrameColumns = codeFrameColumns2;
|
|
183421
|
+
exports.default = index;
|
|
183422
|
+
exports.highlight = highlight;
|
|
183423
|
+
}
|
|
183424
|
+
});
|
|
183425
|
+
|
|
182945
183426
|
// src/cli.tsx
|
|
182946
183427
|
import { Command } from "commander";
|
|
182947
183428
|
|
|
@@ -182949,8 +183430,11 @@ import { Command } from "commander";
|
|
|
182949
183430
|
import React2, { useState, useEffect } from "react";
|
|
182950
183431
|
import { render as render2, Text as Text2, Box as Box2, useInput, useApp } from "ink";
|
|
182951
183432
|
import "ink-spinner";
|
|
182952
|
-
import * as
|
|
182953
|
-
import * as
|
|
183433
|
+
import * as fs11 from "fs";
|
|
183434
|
+
import * as path7 from "path";
|
|
183435
|
+
|
|
183436
|
+
// src/lib/dev/system-setup.ts
|
|
183437
|
+
import { execSync as execSync2 } from "child_process";
|
|
182954
183438
|
|
|
182955
183439
|
// src/lib/dev/local-ca.ts
|
|
182956
183440
|
import * as fs from "fs";
|
|
@@ -182965,6 +183449,38 @@ function caFilesExist() {
|
|
|
182965
183449
|
const caDir = getCADir();
|
|
182966
183450
|
return fs.existsSync(path.join(caDir, "ca.key")) && fs.existsSync(path.join(caDir, "ca.crt"));
|
|
182967
183451
|
}
|
|
183452
|
+
function caInstalledInTrustStore() {
|
|
183453
|
+
if (!caFilesExist()) {
|
|
183454
|
+
return false;
|
|
183455
|
+
}
|
|
183456
|
+
const platform5 = os.platform();
|
|
183457
|
+
const certPath = path.join(getCADir(), "ca.crt");
|
|
183458
|
+
const diskCert = fs.readFileSync(certPath, "utf-8").replace(/\r\n/g, "\n").trim();
|
|
183459
|
+
try {
|
|
183460
|
+
if (platform5 === "darwin") {
|
|
183461
|
+
const keychainCert = execSync(
|
|
183462
|
+
'security find-certificate -c "Specific Local Development CA" -p /Library/Keychains/System.keychain',
|
|
183463
|
+
{ encoding: "utf-8" }
|
|
183464
|
+
).replace(/\r\n/g, "\n").trim();
|
|
183465
|
+
return keychainCert === diskCert;
|
|
183466
|
+
} else if (platform5 === "linux") {
|
|
183467
|
+
const trustPaths = [
|
|
183468
|
+
"/usr/local/share/ca-certificates/specific-local-ca.crt",
|
|
183469
|
+
"/etc/pki/ca-trust/source/anchors/specific-local-ca.crt"
|
|
183470
|
+
];
|
|
183471
|
+
for (const trustPath of trustPaths) {
|
|
183472
|
+
if (fs.existsSync(trustPath)) {
|
|
183473
|
+
const trustedCert = fs.readFileSync(trustPath, "utf-8").replace(/\r\n/g, "\n").trim();
|
|
183474
|
+
return trustedCert === diskCert;
|
|
183475
|
+
}
|
|
183476
|
+
}
|
|
183477
|
+
return false;
|
|
183478
|
+
}
|
|
183479
|
+
} catch {
|
|
183480
|
+
return false;
|
|
183481
|
+
}
|
|
183482
|
+
return false;
|
|
183483
|
+
}
|
|
182968
183484
|
function createNameConstraintsExtension(permittedDNSNames) {
|
|
182969
183485
|
const nameConstraintsOID = "2.5.29.30";
|
|
182970
183486
|
const permittedSubtrees = permittedDNSNames.map((dnsName) => {
|
|
@@ -183054,32 +183570,30 @@ function removeCA() {
|
|
|
183054
183570
|
fs.unlinkSync(certPath);
|
|
183055
183571
|
}
|
|
183056
183572
|
}
|
|
183057
|
-
function
|
|
183058
|
-
const
|
|
183059
|
-
if (
|
|
183060
|
-
|
|
183061
|
-
|
|
183062
|
-
|
|
183063
|
-
|
|
183064
|
-
|
|
183573
|
+
function getCAInstallCommands(certPath) {
|
|
183574
|
+
const platform5 = os.platform();
|
|
183575
|
+
if (platform5 === "darwin") {
|
|
183576
|
+
return [
|
|
183577
|
+
// Remove any existing cert with the same CN first — add-trusted-cert
|
|
183578
|
+
// silently does nothing if a cert with the same subject already exists.
|
|
183579
|
+
'security delete-certificate -c "Specific Local Development CA" /Library/Keychains/System.keychain 2>/dev/null || true',
|
|
183580
|
+
`security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain "${certPath}"`
|
|
183581
|
+
];
|
|
183582
|
+
} else if (platform5 === "linux") {
|
|
183065
183583
|
if (fs.existsSync("/usr/local/share/ca-certificates")) {
|
|
183066
|
-
|
|
183067
|
-
`
|
|
183068
|
-
|
|
183069
|
-
|
|
183070
|
-
execSync("sudo update-ca-certificates", { stdio: "inherit" });
|
|
183584
|
+
return [
|
|
183585
|
+
`cp "${certPath}" /usr/local/share/ca-certificates/specific-local-ca.crt`,
|
|
183586
|
+
"update-ca-certificates"
|
|
183587
|
+
];
|
|
183071
183588
|
} else if (fs.existsSync("/etc/pki/ca-trust/source/anchors")) {
|
|
183072
|
-
|
|
183073
|
-
`
|
|
183074
|
-
|
|
183075
|
-
|
|
183076
|
-
execSync("sudo update-ca-trust extract", { stdio: "inherit" });
|
|
183077
|
-
} else {
|
|
183078
|
-
throw new Error("Could not detect Linux certificate trust mechanism");
|
|
183589
|
+
return [
|
|
183590
|
+
`cp "${certPath}" /etc/pki/ca-trust/source/anchors/specific-local-ca.crt`,
|
|
183591
|
+
"update-ca-trust extract"
|
|
183592
|
+
];
|
|
183079
183593
|
}
|
|
183080
|
-
|
|
183081
|
-
throw new Error(`Unsupported platform: ${platform4}`);
|
|
183594
|
+
throw new Error("Could not detect Linux certificate trust mechanism");
|
|
183082
183595
|
}
|
|
183596
|
+
throw new Error(`Unsupported platform: ${platform5}`);
|
|
183083
183597
|
}
|
|
183084
183598
|
function generateCertificate(domain, keys = []) {
|
|
183085
183599
|
const caDir = getCADir();
|
|
@@ -183118,139 +183632,52 @@ function generateCertificate(domain, keys = []) {
|
|
|
183118
183632
|
};
|
|
183119
183633
|
}
|
|
183120
183634
|
|
|
183121
|
-
// src/lib/
|
|
183122
|
-
import { PostHog } from "posthog-node";
|
|
183123
|
-
import * as os5 from "os";
|
|
183124
|
-
import * as crypto from "crypto";
|
|
183125
|
-
|
|
183126
|
-
// src/lib/project/config.ts
|
|
183635
|
+
// src/lib/dev/resolver-config.ts
|
|
183127
183636
|
import * as fs2 from "fs";
|
|
183128
|
-
import * as
|
|
183129
|
-
var
|
|
183130
|
-
var
|
|
183131
|
-
|
|
183132
|
-
|
|
183133
|
-
|
|
183134
|
-
|
|
183135
|
-
|
|
183136
|
-
|
|
183137
|
-
Run: specific deploy`
|
|
183138
|
-
);
|
|
183139
|
-
this.name = "ProjectNotLinkedError";
|
|
183140
|
-
}
|
|
183141
|
-
};
|
|
183142
|
-
function readProjectId(projectDir = process.cwd()) {
|
|
183143
|
-
const projectIdPath = path2.join(projectDir, PROJECT_ID_FILE);
|
|
183144
|
-
if (!fs2.existsSync(projectIdPath)) {
|
|
183145
|
-
throw new ProjectNotLinkedError();
|
|
183146
|
-
}
|
|
183147
|
-
const projectId = fs2.readFileSync(projectIdPath, "utf-8").trim();
|
|
183148
|
-
if (!projectId) {
|
|
183149
|
-
throw new Error(`${PROJECT_ID_FILE} is empty`);
|
|
183150
|
-
}
|
|
183151
|
-
return projectId;
|
|
183152
|
-
}
|
|
183153
|
-
function hasProjectId(projectDir = process.cwd()) {
|
|
183154
|
-
const projectIdPath = path2.join(projectDir, PROJECT_ID_FILE);
|
|
183155
|
-
return fs2.existsSync(projectIdPath);
|
|
183156
|
-
}
|
|
183157
|
-
function writeProjectId(projectId, projectDir = process.cwd()) {
|
|
183158
|
-
const specificDir = path2.join(projectDir, ".specific");
|
|
183159
|
-
if (!fs2.existsSync(specificDir)) {
|
|
183160
|
-
fs2.mkdirSync(specificDir, { recursive: true });
|
|
183161
|
-
}
|
|
183162
|
-
fs2.writeFileSync(path2.join(specificDir, "project_id"), projectId + "\n");
|
|
183163
|
-
}
|
|
183164
|
-
|
|
183165
|
-
// src/lib/auth/credentials.ts
|
|
183166
|
-
import * as fs9 from "fs";
|
|
183167
|
-
import * as path5 from "path";
|
|
183168
|
-
import * as os4 from "os";
|
|
183169
|
-
|
|
183170
|
-
// src/lib/auth/errors.ts
|
|
183171
|
-
var RefreshTokenExpiredError = class extends Error {
|
|
183172
|
-
constructor(originalError) {
|
|
183173
|
-
super("Session expired due to inactivity. Please log in again.");
|
|
183174
|
-
this.originalError = originalError;
|
|
183175
|
-
this.name = "RefreshTokenExpiredError";
|
|
183176
|
-
}
|
|
183177
|
-
};
|
|
183178
|
-
|
|
183179
|
-
// src/lib/auth/workos.ts
|
|
183180
|
-
var WORKOS_CLIENT_ID = "client_01K4HSP8CE0R73V7Z67WE9CC86";
|
|
183181
|
-
async function initiateDeviceAuthorization() {
|
|
183182
|
-
const response = await fetch(
|
|
183183
|
-
"https://api.workos.com/user_management/authorize/device",
|
|
183184
|
-
{
|
|
183185
|
-
method: "POST",
|
|
183186
|
-
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
183187
|
-
body: new URLSearchParams({ client_id: WORKOS_CLIENT_ID })
|
|
183188
|
-
}
|
|
183189
|
-
);
|
|
183190
|
-
if (!response.ok) {
|
|
183191
|
-
const error = await response.text();
|
|
183192
|
-
throw new Error(`Failed to initiate device authorization: ${error}`);
|
|
183637
|
+
import * as os2 from "os";
|
|
183638
|
+
var RESOLVER_FILE_MACOS = "/etc/resolver/local.spcf.app";
|
|
183639
|
+
var RESOLVER_FILE_LINUX = "/etc/systemd/resolved.conf.d/specific-local.conf";
|
|
183640
|
+
function resolverConfigExists() {
|
|
183641
|
+
const platform5 = os2.platform();
|
|
183642
|
+
if (platform5 === "darwin") {
|
|
183643
|
+
return fs2.existsSync(RESOLVER_FILE_MACOS);
|
|
183644
|
+
} else if (platform5 === "linux") {
|
|
183645
|
+
return fs2.existsSync(RESOLVER_FILE_LINUX);
|
|
183193
183646
|
}
|
|
183194
|
-
return
|
|
183195
|
-
}
|
|
183196
|
-
async function pollForToken(deviceCode) {
|
|
183197
|
-
const response = await fetch(
|
|
183198
|
-
"https://api.workos.com/user_management/authenticate",
|
|
183199
|
-
{
|
|
183200
|
-
method: "POST",
|
|
183201
|
-
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
183202
|
-
body: new URLSearchParams({
|
|
183203
|
-
client_id: WORKOS_CLIENT_ID,
|
|
183204
|
-
grant_type: "urn:ietf:params:oauth:grant-type:device_code",
|
|
183205
|
-
device_code: deviceCode
|
|
183206
|
-
})
|
|
183207
|
-
}
|
|
183208
|
-
);
|
|
183209
|
-
const data = await response.json();
|
|
183210
|
-
return data;
|
|
183647
|
+
return false;
|
|
183211
183648
|
}
|
|
183212
|
-
|
|
183213
|
-
const
|
|
183214
|
-
|
|
183215
|
-
|
|
183216
|
-
|
|
183217
|
-
|
|
183218
|
-
|
|
183219
|
-
|
|
183220
|
-
|
|
183221
|
-
|
|
183222
|
-
|
|
183223
|
-
|
|
183224
|
-
|
|
183225
|
-
|
|
183226
|
-
const errorText = await response.text();
|
|
183227
|
-
try {
|
|
183228
|
-
const errorJson = JSON.parse(errorText);
|
|
183229
|
-
if (errorJson.error === "invalid_grant") {
|
|
183230
|
-
throw new RefreshTokenExpiredError(errorJson.error_description);
|
|
183231
|
-
}
|
|
183232
|
-
} catch (e) {
|
|
183233
|
-
if (e instanceof RefreshTokenExpiredError) throw e;
|
|
183649
|
+
function getResolverInstallCommands(port) {
|
|
183650
|
+
const platform5 = os2.platform();
|
|
183651
|
+
if (platform5 === "darwin") {
|
|
183652
|
+
return [
|
|
183653
|
+
"mkdir -p /etc/resolver",
|
|
183654
|
+
`printf "nameserver 127.0.0.1\\nport ${port}\\n" > ${RESOLVER_FILE_MACOS}`
|
|
183655
|
+
];
|
|
183656
|
+
} else if (platform5 === "linux") {
|
|
183657
|
+
if (fs2.existsSync("/etc/systemd/resolved.conf.d") || fs2.existsSync("/etc/systemd")) {
|
|
183658
|
+
return [
|
|
183659
|
+
"mkdir -p /etc/systemd/resolved.conf.d",
|
|
183660
|
+
`printf "[Resolve]\\nDNS=127.0.0.1:${port}\\nDomains=~local.spcf.app\\n" > ${RESOLVER_FILE_LINUX}`,
|
|
183661
|
+
"systemctl restart systemd-resolved"
|
|
183662
|
+
];
|
|
183234
183663
|
}
|
|
183235
|
-
|
|
183664
|
+
return [];
|
|
183236
183665
|
}
|
|
183237
|
-
return
|
|
183666
|
+
return [];
|
|
183238
183667
|
}
|
|
183239
183668
|
|
|
183240
|
-
// src/lib/
|
|
183241
|
-
import
|
|
183242
|
-
import { render, Box, Text } from "ink";
|
|
183243
|
-
import Spinner from "ink-spinner";
|
|
183669
|
+
// src/lib/dev/dns-server.ts
|
|
183670
|
+
import DNS from "dns2";
|
|
183244
183671
|
|
|
183245
183672
|
// src/lib/dev/debug-logger.ts
|
|
183246
183673
|
import * as fs3 from "fs";
|
|
183247
|
-
import * as
|
|
183248
|
-
import * as
|
|
183674
|
+
import * as os3 from "os";
|
|
183675
|
+
import * as path2 from "path";
|
|
183249
183676
|
var DEBUG_LOG_PATH = ".specific/debug.log";
|
|
183250
183677
|
var logStream = null;
|
|
183251
183678
|
function writeLog(source, message) {
|
|
183252
|
-
const logPath =
|
|
183253
|
-
fs3.mkdirSync(
|
|
183679
|
+
const logPath = path2.join(os3.homedir(), DEBUG_LOG_PATH);
|
|
183680
|
+
fs3.mkdirSync(path2.dirname(logPath), { recursive: true });
|
|
183254
183681
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
183255
183682
|
const line = message.endsWith("\n") ? message : message + "\n";
|
|
183256
183683
|
fs3.appendFileSync(logPath, `[${timestamp}] [${source}] ${line}`);
|
|
@@ -183284,6 +183711,201 @@ function closeDebugLog() {
|
|
|
183284
183711
|
}
|
|
183285
183712
|
}
|
|
183286
183713
|
|
|
183714
|
+
// src/lib/dev/dns-server.ts
|
|
183715
|
+
var DNS_PORT = 15353;
|
|
183716
|
+
async function startDnsServer(port = DNS_PORT) {
|
|
183717
|
+
const server = DNS.createServer({
|
|
183718
|
+
udp: true,
|
|
183719
|
+
handle: (request, send) => {
|
|
183720
|
+
const response = DNS.Packet.createResponseFromRequest(request);
|
|
183721
|
+
for (const question of request.questions) {
|
|
183722
|
+
if (question.type === DNS.Packet.TYPE.A) {
|
|
183723
|
+
response.answers.push({
|
|
183724
|
+
name: question.name,
|
|
183725
|
+
type: DNS.Packet.TYPE.A,
|
|
183726
|
+
class: DNS.Packet.CLASS.IN,
|
|
183727
|
+
ttl: 300,
|
|
183728
|
+
address: "127.0.0.1"
|
|
183729
|
+
});
|
|
183730
|
+
}
|
|
183731
|
+
}
|
|
183732
|
+
send(response);
|
|
183733
|
+
}
|
|
183734
|
+
});
|
|
183735
|
+
await server.listen({
|
|
183736
|
+
udp: { port, address: "127.0.0.1" }
|
|
183737
|
+
});
|
|
183738
|
+
writeLog("dns", `DNS server started on 127.0.0.1:${port}`);
|
|
183739
|
+
return {
|
|
183740
|
+
port,
|
|
183741
|
+
async stop() {
|
|
183742
|
+
await server.close();
|
|
183743
|
+
writeLog("dns", "DNS server stopped");
|
|
183744
|
+
}
|
|
183745
|
+
};
|
|
183746
|
+
}
|
|
183747
|
+
|
|
183748
|
+
// src/lib/dev/system-setup.ts
|
|
183749
|
+
import * as path3 from "path";
|
|
183750
|
+
function systemSetupNeeded() {
|
|
183751
|
+
return !caInstalledInTrustStore() || !resolverConfigExists();
|
|
183752
|
+
}
|
|
183753
|
+
function performSystemSetup() {
|
|
183754
|
+
const needsGenerate = !caFilesExist();
|
|
183755
|
+
const needsInstallCA = !caInstalledInTrustStore();
|
|
183756
|
+
const needsResolver = !resolverConfigExists();
|
|
183757
|
+
if (!needsInstallCA && !needsResolver) {
|
|
183758
|
+
return;
|
|
183759
|
+
}
|
|
183760
|
+
if (needsGenerate) {
|
|
183761
|
+
const { key, cert } = generateRootCA();
|
|
183762
|
+
saveCA(key, cert);
|
|
183763
|
+
}
|
|
183764
|
+
const certPath = path3.join(getCADir(), "ca.crt");
|
|
183765
|
+
const commands = [];
|
|
183766
|
+
if (needsInstallCA) {
|
|
183767
|
+
commands.push(...getCAInstallCommands(certPath));
|
|
183768
|
+
}
|
|
183769
|
+
if (needsResolver) {
|
|
183770
|
+
commands.push(...getResolverInstallCommands(DNS_PORT));
|
|
183771
|
+
}
|
|
183772
|
+
if (commands.length === 0) {
|
|
183773
|
+
return;
|
|
183774
|
+
}
|
|
183775
|
+
try {
|
|
183776
|
+
execSync2(`sudo sh -c '${commands.join(" && ")}'`, { stdio: "inherit" });
|
|
183777
|
+
} catch (err) {
|
|
183778
|
+
if (needsGenerate) {
|
|
183779
|
+
removeCA();
|
|
183780
|
+
}
|
|
183781
|
+
throw err;
|
|
183782
|
+
}
|
|
183783
|
+
}
|
|
183784
|
+
|
|
183785
|
+
// src/lib/analytics/index.ts
|
|
183786
|
+
import { PostHog } from "posthog-node";
|
|
183787
|
+
import * as os6 from "os";
|
|
183788
|
+
import * as crypto from "crypto";
|
|
183789
|
+
|
|
183790
|
+
// src/lib/project/config.ts
|
|
183791
|
+
import * as fs4 from "fs";
|
|
183792
|
+
import * as path4 from "path";
|
|
183793
|
+
var PROJECT_ID_FILE = ".specific/project_id";
|
|
183794
|
+
var ProjectNotLinkedError = class extends Error {
|
|
183795
|
+
constructor() {
|
|
183796
|
+
super(
|
|
183797
|
+
`Project not linked to Specific.
|
|
183798
|
+
|
|
183799
|
+
The file ${PROJECT_ID_FILE} does not exist.
|
|
183800
|
+
|
|
183801
|
+
Run: specific deploy`
|
|
183802
|
+
);
|
|
183803
|
+
this.name = "ProjectNotLinkedError";
|
|
183804
|
+
}
|
|
183805
|
+
};
|
|
183806
|
+
function readProjectId(projectDir = process.cwd()) {
|
|
183807
|
+
const projectIdPath = path4.join(projectDir, PROJECT_ID_FILE);
|
|
183808
|
+
if (!fs4.existsSync(projectIdPath)) {
|
|
183809
|
+
throw new ProjectNotLinkedError();
|
|
183810
|
+
}
|
|
183811
|
+
const projectId = fs4.readFileSync(projectIdPath, "utf-8").trim();
|
|
183812
|
+
if (!projectId) {
|
|
183813
|
+
throw new Error(`${PROJECT_ID_FILE} is empty`);
|
|
183814
|
+
}
|
|
183815
|
+
return projectId;
|
|
183816
|
+
}
|
|
183817
|
+
function hasProjectId(projectDir = process.cwd()) {
|
|
183818
|
+
const projectIdPath = path4.join(projectDir, PROJECT_ID_FILE);
|
|
183819
|
+
return fs4.existsSync(projectIdPath);
|
|
183820
|
+
}
|
|
183821
|
+
function writeProjectId(projectId, projectDir = process.cwd()) {
|
|
183822
|
+
const specificDir = path4.join(projectDir, ".specific");
|
|
183823
|
+
if (!fs4.existsSync(specificDir)) {
|
|
183824
|
+
fs4.mkdirSync(specificDir, { recursive: true });
|
|
183825
|
+
}
|
|
183826
|
+
fs4.writeFileSync(path4.join(specificDir, "project_id"), projectId + "\n");
|
|
183827
|
+
}
|
|
183828
|
+
|
|
183829
|
+
// src/lib/auth/credentials.ts
|
|
183830
|
+
import * as fs10 from "fs";
|
|
183831
|
+
import * as path6 from "path";
|
|
183832
|
+
import * as os5 from "os";
|
|
183833
|
+
|
|
183834
|
+
// src/lib/auth/errors.ts
|
|
183835
|
+
var RefreshTokenExpiredError = class extends Error {
|
|
183836
|
+
constructor(originalError) {
|
|
183837
|
+
super("Session expired due to inactivity. Please log in again.");
|
|
183838
|
+
this.originalError = originalError;
|
|
183839
|
+
this.name = "RefreshTokenExpiredError";
|
|
183840
|
+
}
|
|
183841
|
+
};
|
|
183842
|
+
|
|
183843
|
+
// src/lib/auth/workos.ts
|
|
183844
|
+
var WORKOS_CLIENT_ID = "client_01K4HSP8CE0R73V7Z67WE9CC86";
|
|
183845
|
+
async function initiateDeviceAuthorization() {
|
|
183846
|
+
const response = await fetch(
|
|
183847
|
+
"https://api.workos.com/user_management/authorize/device",
|
|
183848
|
+
{
|
|
183849
|
+
method: "POST",
|
|
183850
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
183851
|
+
body: new URLSearchParams({ client_id: WORKOS_CLIENT_ID })
|
|
183852
|
+
}
|
|
183853
|
+
);
|
|
183854
|
+
if (!response.ok) {
|
|
183855
|
+
const error = await response.text();
|
|
183856
|
+
throw new Error(`Failed to initiate device authorization: ${error}`);
|
|
183857
|
+
}
|
|
183858
|
+
return response.json();
|
|
183859
|
+
}
|
|
183860
|
+
async function pollForToken(deviceCode) {
|
|
183861
|
+
const response = await fetch(
|
|
183862
|
+
"https://api.workos.com/user_management/authenticate",
|
|
183863
|
+
{
|
|
183864
|
+
method: "POST",
|
|
183865
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
183866
|
+
body: new URLSearchParams({
|
|
183867
|
+
client_id: WORKOS_CLIENT_ID,
|
|
183868
|
+
grant_type: "urn:ietf:params:oauth:grant-type:device_code",
|
|
183869
|
+
device_code: deviceCode
|
|
183870
|
+
})
|
|
183871
|
+
}
|
|
183872
|
+
);
|
|
183873
|
+
const data = await response.json();
|
|
183874
|
+
return data;
|
|
183875
|
+
}
|
|
183876
|
+
async function refreshAccessToken(refreshToken) {
|
|
183877
|
+
const response = await fetch(
|
|
183878
|
+
"https://api.workos.com/user_management/authenticate",
|
|
183879
|
+
{
|
|
183880
|
+
method: "POST",
|
|
183881
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
183882
|
+
body: new URLSearchParams({
|
|
183883
|
+
client_id: WORKOS_CLIENT_ID,
|
|
183884
|
+
grant_type: "refresh_token",
|
|
183885
|
+
refresh_token: refreshToken
|
|
183886
|
+
})
|
|
183887
|
+
}
|
|
183888
|
+
);
|
|
183889
|
+
if (!response.ok) {
|
|
183890
|
+
const errorText = await response.text();
|
|
183891
|
+
try {
|
|
183892
|
+
const errorJson = JSON.parse(errorText);
|
|
183893
|
+
if (errorJson.error === "invalid_grant") {
|
|
183894
|
+
throw new RefreshTokenExpiredError(errorJson.error_description);
|
|
183895
|
+
}
|
|
183896
|
+
} catch (e) {
|
|
183897
|
+
if (e instanceof RefreshTokenExpiredError) throw e;
|
|
183898
|
+
}
|
|
183899
|
+
throw new Error(`Failed to refresh token: ${errorText}`);
|
|
183900
|
+
}
|
|
183901
|
+
return response.json();
|
|
183902
|
+
}
|
|
183903
|
+
|
|
183904
|
+
// src/lib/auth/login.tsx
|
|
183905
|
+
import React from "react";
|
|
183906
|
+
import { render, Box, Text } from "ink";
|
|
183907
|
+
import Spinner from "ink-spinner";
|
|
183908
|
+
|
|
183287
183909
|
// src/lib/api/client.ts
|
|
183288
183910
|
var ApiClient = class {
|
|
183289
183911
|
baseUrl;
|
|
@@ -183756,18 +184378,18 @@ function performLogin(options2 = {}) {
|
|
|
183756
184378
|
|
|
183757
184379
|
// src/lib/auth/credentials.ts
|
|
183758
184380
|
function getUserCredentialsDir() {
|
|
183759
|
-
return
|
|
184381
|
+
return path6.join(os5.homedir(), ".specific");
|
|
183760
184382
|
}
|
|
183761
184383
|
function getCredentialsPath() {
|
|
183762
|
-
return
|
|
184384
|
+
return path6.join(getUserCredentialsDir(), "credentials.json");
|
|
183763
184385
|
}
|
|
183764
184386
|
function readUserCredentials() {
|
|
183765
184387
|
const credentialsPath = getCredentialsPath();
|
|
183766
|
-
if (!
|
|
184388
|
+
if (!fs10.existsSync(credentialsPath)) {
|
|
183767
184389
|
return null;
|
|
183768
184390
|
}
|
|
183769
184391
|
try {
|
|
183770
|
-
const content =
|
|
184392
|
+
const content = fs10.readFileSync(credentialsPath, "utf-8");
|
|
183771
184393
|
return JSON.parse(content);
|
|
183772
184394
|
} catch {
|
|
183773
184395
|
return null;
|
|
@@ -183775,18 +184397,18 @@ function readUserCredentials() {
|
|
|
183775
184397
|
}
|
|
183776
184398
|
function writeUserCredentials(credentials) {
|
|
183777
184399
|
const dir = getUserCredentialsDir();
|
|
183778
|
-
if (!
|
|
183779
|
-
|
|
184400
|
+
if (!fs10.existsSync(dir)) {
|
|
184401
|
+
fs10.mkdirSync(dir, { recursive: true, mode: 448 });
|
|
183780
184402
|
}
|
|
183781
184403
|
const credentialsPath = getCredentialsPath();
|
|
183782
|
-
|
|
184404
|
+
fs10.writeFileSync(credentialsPath, JSON.stringify(credentials, null, 2), {
|
|
183783
184405
|
mode: 384
|
|
183784
184406
|
});
|
|
183785
184407
|
}
|
|
183786
184408
|
function clearUserCredentials() {
|
|
183787
184409
|
const credentialsPath = getCredentialsPath();
|
|
183788
|
-
if (
|
|
183789
|
-
|
|
184410
|
+
if (fs10.existsSync(credentialsPath)) {
|
|
184411
|
+
fs10.unlinkSync(credentialsPath);
|
|
183790
184412
|
}
|
|
183791
184413
|
}
|
|
183792
184414
|
function isLoggedIn() {
|
|
@@ -183840,7 +184462,7 @@ function isEnabled() {
|
|
|
183840
184462
|
}
|
|
183841
184463
|
function getAnonymousId() {
|
|
183842
184464
|
if (anonymousId) return anonymousId;
|
|
183843
|
-
const machineId = `${
|
|
184465
|
+
const machineId = `${os6.hostname()}-${os6.userInfo().username}`;
|
|
183844
184466
|
anonymousId = crypto.createHash("sha256").update(machineId).digest("hex").slice(0, 16);
|
|
183845
184467
|
return anonymousId;
|
|
183846
184468
|
}
|
|
@@ -183873,7 +184495,7 @@ function trackEvent(event, properties) {
|
|
|
183873
184495
|
event,
|
|
183874
184496
|
properties: {
|
|
183875
184497
|
...properties,
|
|
183876
|
-
cli_version: "0.1.
|
|
184498
|
+
cli_version: "0.1.63",
|
|
183877
184499
|
platform: process.platform,
|
|
183878
184500
|
node_version: process.version,
|
|
183879
184501
|
project_id: getProjectId(),
|
|
@@ -183910,67 +184532,67 @@ var options = [
|
|
|
183910
184532
|
{ id: "other", label: "Other / Manual" }
|
|
183911
184533
|
];
|
|
183912
184534
|
function isGitProject() {
|
|
183913
|
-
const gitPath =
|
|
183914
|
-
return
|
|
184535
|
+
const gitPath = path7.join(process.cwd(), ".git");
|
|
184536
|
+
return fs11.existsSync(gitPath);
|
|
183915
184537
|
}
|
|
183916
184538
|
function detectExistingAgents() {
|
|
183917
184539
|
const detected = {};
|
|
183918
|
-
const cursorDir =
|
|
183919
|
-
if (
|
|
184540
|
+
const cursorDir = path7.join(process.cwd(), ".cursor");
|
|
184541
|
+
if (fs11.existsSync(cursorDir)) {
|
|
183920
184542
|
detected["cursor"] = true;
|
|
183921
184543
|
}
|
|
183922
|
-
const claudeDir =
|
|
183923
|
-
const claudeMd =
|
|
183924
|
-
if (
|
|
184544
|
+
const claudeDir = path7.join(process.cwd(), ".claude");
|
|
184545
|
+
const claudeMd = path7.join(process.cwd(), "CLAUDE.md");
|
|
184546
|
+
if (fs11.existsSync(claudeDir) || fs11.existsSync(claudeMd)) {
|
|
183925
184547
|
detected["claude"] = true;
|
|
183926
184548
|
}
|
|
183927
|
-
const agentsMd =
|
|
183928
|
-
if (
|
|
184549
|
+
const agentsMd = path7.join(process.cwd(), "AGENTS.md");
|
|
184550
|
+
if (fs11.existsSync(agentsMd)) {
|
|
183929
184551
|
detected["codex"] = true;
|
|
183930
184552
|
}
|
|
183931
184553
|
return detected;
|
|
183932
184554
|
}
|
|
183933
184555
|
function appendOrCreateFile(filePath, content) {
|
|
183934
|
-
if (
|
|
183935
|
-
const existing =
|
|
184556
|
+
if (fs11.existsSync(filePath)) {
|
|
184557
|
+
const existing = fs11.readFileSync(filePath, "utf-8");
|
|
183936
184558
|
if (existing.includes("specific docs") || existing.includes("specific check")) {
|
|
183937
184559
|
return "unchanged";
|
|
183938
184560
|
}
|
|
183939
184561
|
const separator = existing.endsWith("\n") ? "\n" : "\n\n";
|
|
183940
|
-
|
|
184562
|
+
fs11.writeFileSync(filePath, existing + separator + content + "\n");
|
|
183941
184563
|
return "modified";
|
|
183942
184564
|
} else {
|
|
183943
|
-
|
|
184565
|
+
fs11.writeFileSync(filePath, content + "\n");
|
|
183944
184566
|
return "created";
|
|
183945
184567
|
}
|
|
183946
184568
|
}
|
|
183947
184569
|
function addToGitignore() {
|
|
183948
|
-
const gitignorePath =
|
|
184570
|
+
const gitignorePath = path7.join(process.cwd(), ".gitignore");
|
|
183949
184571
|
const entries = [".specific", "specific.local"];
|
|
183950
|
-
if (
|
|
183951
|
-
const existing =
|
|
184572
|
+
if (fs11.existsSync(gitignorePath)) {
|
|
184573
|
+
const existing = fs11.readFileSync(gitignorePath, "utf-8");
|
|
183952
184574
|
const lines = existing.split("\n").map((l) => l.trim());
|
|
183953
184575
|
const missingEntries = entries.filter((entry) => !lines.includes(entry));
|
|
183954
184576
|
if (missingEntries.length === 0) {
|
|
183955
184577
|
return "unchanged";
|
|
183956
184578
|
}
|
|
183957
184579
|
const separator = existing.endsWith("\n") ? "" : "\n";
|
|
183958
|
-
|
|
184580
|
+
fs11.writeFileSync(
|
|
183959
184581
|
gitignorePath,
|
|
183960
184582
|
existing + separator + missingEntries.join("\n") + "\n"
|
|
183961
184583
|
);
|
|
183962
184584
|
return "modified";
|
|
183963
184585
|
} else {
|
|
183964
|
-
|
|
184586
|
+
fs11.writeFileSync(gitignorePath, entries.join("\n") + "\n");
|
|
183965
184587
|
return "created";
|
|
183966
184588
|
}
|
|
183967
184589
|
}
|
|
183968
184590
|
function configureClaudeCodePermissions() {
|
|
183969
|
-
const claudeDir =
|
|
183970
|
-
const settingsPath =
|
|
184591
|
+
const claudeDir = path7.join(process.cwd(), ".claude");
|
|
184592
|
+
const settingsPath = path7.join(claudeDir, "settings.local.json");
|
|
183971
184593
|
const permissions = ["Bash(specific docs:*)", "Bash(specific check:*)"];
|
|
183972
|
-
if (
|
|
183973
|
-
const existing = JSON.parse(
|
|
184594
|
+
if (fs11.existsSync(settingsPath)) {
|
|
184595
|
+
const existing = JSON.parse(fs11.readFileSync(settingsPath, "utf-8"));
|
|
183974
184596
|
const allowList = existing?.permissions?.allow || [];
|
|
183975
184597
|
const missingPermissions = permissions.filter(
|
|
183976
184598
|
(p) => !allowList.includes(p)
|
|
@@ -183985,39 +184607,39 @@ function configureClaudeCodePermissions() {
|
|
|
183985
184607
|
existing.permissions.allow = [];
|
|
183986
184608
|
}
|
|
183987
184609
|
existing.permissions.allow.push(...missingPermissions);
|
|
183988
|
-
|
|
184610
|
+
fs11.writeFileSync(settingsPath, JSON.stringify(existing, null, 2) + "\n");
|
|
183989
184611
|
return "modified";
|
|
183990
184612
|
}
|
|
183991
|
-
if (!
|
|
183992
|
-
|
|
184613
|
+
if (!fs11.existsSync(claudeDir)) {
|
|
184614
|
+
fs11.mkdirSync(claudeDir);
|
|
183993
184615
|
}
|
|
183994
184616
|
const settings = {
|
|
183995
184617
|
permissions: {
|
|
183996
184618
|
allow: permissions
|
|
183997
184619
|
}
|
|
183998
184620
|
};
|
|
183999
|
-
|
|
184621
|
+
fs11.writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + "\n");
|
|
184000
184622
|
return "created";
|
|
184001
184623
|
}
|
|
184002
184624
|
function createCursorRule() {
|
|
184003
|
-
const cursorDir =
|
|
184004
|
-
const rulesDir =
|
|
184005
|
-
const mdcPath =
|
|
184006
|
-
if (
|
|
184007
|
-
const existing =
|
|
184625
|
+
const cursorDir = path7.join(process.cwd(), ".cursor");
|
|
184626
|
+
const rulesDir = path7.join(cursorDir, "rules");
|
|
184627
|
+
const mdcPath = path7.join(rulesDir, "specific.mdc");
|
|
184628
|
+
if (fs11.existsSync(mdcPath)) {
|
|
184629
|
+
const existing = fs11.readFileSync(mdcPath, "utf-8");
|
|
184008
184630
|
if (existing.includes("specific docs") || existing.includes("specific check")) {
|
|
184009
184631
|
return "unchanged";
|
|
184010
184632
|
}
|
|
184011
|
-
|
|
184633
|
+
fs11.writeFileSync(mdcPath, CURSOR_MDC_CONTENT);
|
|
184012
184634
|
return "modified";
|
|
184013
184635
|
}
|
|
184014
|
-
if (!
|
|
184015
|
-
|
|
184636
|
+
if (!fs11.existsSync(cursorDir)) {
|
|
184637
|
+
fs11.mkdirSync(cursorDir);
|
|
184016
184638
|
}
|
|
184017
|
-
if (!
|
|
184018
|
-
|
|
184639
|
+
if (!fs11.existsSync(rulesDir)) {
|
|
184640
|
+
fs11.mkdirSync(rulesDir);
|
|
184019
184641
|
}
|
|
184020
|
-
|
|
184642
|
+
fs11.writeFileSync(mdcPath, CURSOR_MDC_CONTENT);
|
|
184021
184643
|
return "created";
|
|
184022
184644
|
}
|
|
184023
184645
|
function configureAgents(checked) {
|
|
@@ -184033,7 +184655,7 @@ function configureAgents(checked) {
|
|
|
184033
184655
|
agents.filesModified.push(".cursor/rules/specific.mdc");
|
|
184034
184656
|
}
|
|
184035
184657
|
if (checked["claude"]) {
|
|
184036
|
-
const claudeMdPath =
|
|
184658
|
+
const claudeMdPath = path7.join(process.cwd(), "CLAUDE.md");
|
|
184037
184659
|
const status = appendOrCreateFile(claudeMdPath, SPECIFIC_INSTRUCTIONS);
|
|
184038
184660
|
if (status === "created") agents.filesCreated.push("CLAUDE.md");
|
|
184039
184661
|
else if (status === "modified") agents.filesModified.push("CLAUDE.md");
|
|
@@ -184044,7 +184666,7 @@ function configureAgents(checked) {
|
|
|
184044
184666
|
agents.filesModified.push(".claude/settings.local.json");
|
|
184045
184667
|
}
|
|
184046
184668
|
if (checked["codex"]) {
|
|
184047
|
-
const agentsMdPath =
|
|
184669
|
+
const agentsMdPath = path7.join(process.cwd(), "AGENTS.md");
|
|
184048
184670
|
const status = appendOrCreateFile(agentsMdPath, SPECIFIC_INSTRUCTIONS);
|
|
184049
184671
|
if (status === "created") agents.filesCreated.push("AGENTS.md");
|
|
184050
184672
|
else if (status === "modified") agents.filesModified.push("AGENTS.md");
|
|
@@ -184070,16 +184692,16 @@ function InitUI() {
|
|
|
184070
184692
|
};
|
|
184071
184693
|
});
|
|
184072
184694
|
const [phase, setPhase] = useState(
|
|
184073
|
-
() =>
|
|
184695
|
+
() => !systemSetupNeeded() ? "agents" : "installing-ca"
|
|
184074
184696
|
);
|
|
184075
|
-
const [caInstallPhase, setCaInstallPhase] = useState(() =>
|
|
184697
|
+
const [caInstallPhase, setCaInstallPhase] = useState(() => !systemSetupNeeded() ? "done" : "installing");
|
|
184076
184698
|
const [focusedIndex, setFocusedIndex] = useState(initialState.focusedIndex);
|
|
184077
184699
|
const [checked, setChecked] = useState(
|
|
184078
184700
|
initialState.detected
|
|
184079
184701
|
);
|
|
184080
184702
|
const [result, setResult] = useState(null);
|
|
184081
184703
|
const [tlsResult, setTlsResult] = useState(
|
|
184082
|
-
|
|
184704
|
+
!systemSetupNeeded() ? { status: "success" } : null
|
|
184083
184705
|
);
|
|
184084
184706
|
useEffect(() => {
|
|
184085
184707
|
if (phase === "installing-ca" && caInstallPhase === "installing") {
|
|
@@ -184088,14 +184710,11 @@ function InitUI() {
|
|
|
184088
184710
|
}, [phase, caInstallPhase]);
|
|
184089
184711
|
async function installCA() {
|
|
184090
184712
|
try {
|
|
184091
|
-
|
|
184092
|
-
const certPath = saveCA(key, cert);
|
|
184093
|
-
installCAToTrustStore(certPath);
|
|
184713
|
+
performSystemSetup();
|
|
184094
184714
|
setTlsResult({ status: "success" });
|
|
184095
184715
|
setCaInstallPhase("done");
|
|
184096
184716
|
setPhase("agents");
|
|
184097
184717
|
} catch (err) {
|
|
184098
|
-
removeCA();
|
|
184099
184718
|
setTlsResult({
|
|
184100
184719
|
status: "error",
|
|
184101
184720
|
error: err instanceof Error ? err.message : String(err)
|
|
@@ -184136,16 +184755,16 @@ function InitUI() {
|
|
|
184136
184755
|
}, [phase, exit]);
|
|
184137
184756
|
if (phase === "installing-ca") {
|
|
184138
184757
|
if (caInstallPhase === "installing") {
|
|
184139
|
-
return /* @__PURE__ */ React2.createElement(Box2, { flexDirection: "column" }, /* @__PURE__ */ React2.createElement(Text2, { bold: true, color: "cyan" }, "
|
|
184758
|
+
return /* @__PURE__ */ React2.createElement(Box2, { flexDirection: "column" }, /* @__PURE__ */ React2.createElement(Text2, { bold: true, color: "cyan" }, "Local Development Setup"), /* @__PURE__ */ React2.createElement(Text2, null, " "), /* @__PURE__ */ React2.createElement(Text2, null, "Setting up TLS certificates and DNS resolution for local"), /* @__PURE__ */ React2.createElement(Text2, null, "development. This is a one-time setup for Specific projects."), /* @__PURE__ */ React2.createElement(Text2, null, " "), /* @__PURE__ */ React2.createElement(Text2, null, "Your password is required to configure your system."), /* @__PURE__ */ React2.createElement(Text2, null, " "));
|
|
184140
184759
|
}
|
|
184141
184760
|
}
|
|
184142
184761
|
if (phase === "done") {
|
|
184143
184762
|
const selectedAgents = Object.entries(checked).filter(([, v]) => v).length;
|
|
184144
184763
|
const agentChanges = result && (result.agents.filesCreated.length > 0 || result.agents.filesModified.length > 0);
|
|
184145
184764
|
const gitChanges = result?.git && (result.git.filesCreated.length > 0 || result.git.filesModified.length > 0);
|
|
184146
|
-
return /* @__PURE__ */ React2.createElement(Box2, { flexDirection: "column" }, tlsResult === null && /* @__PURE__ */ React2.createElement(Text2, null, /* @__PURE__ */ React2.createElement(Text2, { dimColor: true }, "\u25CF"), "
|
|
184765
|
+
return /* @__PURE__ */ React2.createElement(Box2, { flexDirection: "column" }, tlsResult === null && /* @__PURE__ */ React2.createElement(Text2, null, /* @__PURE__ */ React2.createElement(Text2, { dimColor: true }, "\u25CF"), " Setting up TLS and DNS..."), tlsResult?.status === "success" && /* @__PURE__ */ React2.createElement(Text2, null, /* @__PURE__ */ React2.createElement(Text2, { color: "green" }, "\u2713"), " TLS and DNS configured"), tlsResult?.status === "error" && /* @__PURE__ */ React2.createElement(React2.Fragment, null, /* @__PURE__ */ React2.createElement(Text2, null, /* @__PURE__ */ React2.createElement(Text2, { color: "red" }, "\u2717"), " Failed to set up TLS and DNS"), /* @__PURE__ */ React2.createElement(Text2, { dimColor: true }, " ", tlsResult.error)), result && /* @__PURE__ */ React2.createElement(React2.Fragment, null, /* @__PURE__ */ React2.createElement(Text2, null, /* @__PURE__ */ React2.createElement(Text2, { color: "green" }, "\u2713"), " Coding agents configured"), result.agents.filesCreated.length > 0 && /* @__PURE__ */ React2.createElement(Text2, { dimColor: true }, " ", "Created: ", result.agents.filesCreated.join(", ")), result.agents.filesModified.length > 0 && /* @__PURE__ */ React2.createElement(Text2, { dimColor: true }, " ", "Modified: ", result.agents.filesModified.join(", ")), !agentChanges && selectedAgents > 0 && /* @__PURE__ */ React2.createElement(Text2, { dimColor: true }, " ", "No changes needed (files already configured)"), selectedAgents === 0 && /* @__PURE__ */ React2.createElement(Text2, { dimColor: true }, " No agents selected")), result?.git && /* @__PURE__ */ React2.createElement(React2.Fragment, null, /* @__PURE__ */ React2.createElement(Text2, null, /* @__PURE__ */ React2.createElement(Text2, { color: "green" }, "\u2713"), " Git configured"), result.git.filesCreated.length > 0 && /* @__PURE__ */ React2.createElement(Text2, { dimColor: true }, " ", "Created: ", result.git.filesCreated.join(", ")), result.git.filesModified.length > 0 && /* @__PURE__ */ React2.createElement(Text2, { dimColor: true }, " ", "Modified: ", result.git.filesModified.join(", ")), !gitChanges && /* @__PURE__ */ React2.createElement(Text2, { dimColor: true }, " ", "No changes needed (.gitignore already configured)")), result?.showManualInstructions && /* @__PURE__ */ React2.createElement(React2.Fragment, null, /* @__PURE__ */ React2.createElement(Text2, null, " "), /* @__PURE__ */ React2.createElement(Text2, null, /* @__PURE__ */ React2.createElement(Text2, { color: "green" }, "\u2713"), " Manual configuration selected"), /* @__PURE__ */ React2.createElement(Text2, null, " "), /* @__PURE__ */ React2.createElement(Text2, null, " Add this to your agent's system prompt:"), /* @__PURE__ */ React2.createElement(Text2, { dimColor: true }, "\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"), /* @__PURE__ */ React2.createElement(Text2, null, SPECIFIC_INSTRUCTIONS), /* @__PURE__ */ React2.createElement(Text2, { dimColor: true }, "\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"), /* @__PURE__ */ React2.createElement(Text2, null, " "), /* @__PURE__ */ React2.createElement(Text2, null, " ", "We also recommend allowing your agent to run `specific docs *`"), /* @__PURE__ */ React2.createElement(Text2, null, " and `specific check *` without confirmation.")));
|
|
184147
184766
|
}
|
|
184148
|
-
const tlsLine = tlsResult?.status === "success" ? /* @__PURE__ */ React2.createElement(Text2, null, /* @__PURE__ */ React2.createElement(Text2, { color: "green" }, "\u2713"), " TLS
|
|
184767
|
+
const tlsLine = tlsResult?.status === "success" ? /* @__PURE__ */ React2.createElement(Text2, null, /* @__PURE__ */ React2.createElement(Text2, { color: "green" }, "\u2713"), " TLS and DNS configured") : tlsResult?.status === "error" ? /* @__PURE__ */ React2.createElement(Text2, null, /* @__PURE__ */ React2.createElement(Text2, { color: "red" }, "\u2717"), " TLS and DNS setup failed", " ", /* @__PURE__ */ React2.createElement(Text2, { dimColor: true }, "(", tlsResult.error, ")")) : null;
|
|
184149
184768
|
return /* @__PURE__ */ React2.createElement(Box2, { flexDirection: "column" }, tlsLine, /* @__PURE__ */ React2.createElement(Text2, null, /* @__PURE__ */ React2.createElement(Text2, { dimColor: true }, "\u25CF"), " Configure coding agents", " ", /* @__PURE__ */ React2.createElement(Text2, { dimColor: true }, "(space to select)")), /* @__PURE__ */ React2.createElement(Text2, null, " "), options.map((option, index) => {
|
|
184150
184769
|
const isFocused = focusedIndex === index;
|
|
184151
184770
|
const isChecked = checked[option.id];
|
|
@@ -184216,9 +184835,9 @@ Valid agents: ${VALID_AGENT_IDS.join(", ")}`
|
|
|
184216
184835
|
console.log(" No changes needed (.gitignore already configured)");
|
|
184217
184836
|
}
|
|
184218
184837
|
}
|
|
184219
|
-
if (
|
|
184838
|
+
if (systemSetupNeeded()) {
|
|
184220
184839
|
console.log(
|
|
184221
|
-
"\u26A0 TLS
|
|
184840
|
+
"\u26A0 TLS and DNS not configured (run `specific init` in a terminal to set up)"
|
|
184222
184841
|
);
|
|
184223
184842
|
}
|
|
184224
184843
|
if (result.showManualInstructions) {
|
|
@@ -184235,8 +184854,8 @@ Valid agents: ${VALID_AGENT_IDS.join(", ")}`
|
|
|
184235
184854
|
}
|
|
184236
184855
|
|
|
184237
184856
|
// src/commands/docs.tsx
|
|
184238
|
-
import { readFileSync as readFileSync6, existsSync as
|
|
184239
|
-
import { join as
|
|
184857
|
+
import { readFileSync as readFileSync6, existsSync as existsSync7 } from "fs";
|
|
184858
|
+
import { join as join8, dirname as dirname2 } from "path";
|
|
184240
184859
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
184241
184860
|
|
|
184242
184861
|
// src/lib/beta/registry.ts
|
|
@@ -184244,16 +184863,20 @@ var BETA_REGISTRY = [
|
|
|
184244
184863
|
{
|
|
184245
184864
|
name: "reshape",
|
|
184246
184865
|
description: "Zero-downtime database schema migrations using Reshape"
|
|
184866
|
+
},
|
|
184867
|
+
{
|
|
184868
|
+
name: "temporal",
|
|
184869
|
+
description: "Managed Temporal workflow engine for durable workflows and background tasks"
|
|
184247
184870
|
}
|
|
184248
184871
|
];
|
|
184249
184872
|
|
|
184250
184873
|
// src/lib/beta/storage.ts
|
|
184251
|
-
import { readFileSync as readFileSync5, writeFileSync as writeFileSync5, existsSync as
|
|
184252
|
-
import { join as
|
|
184874
|
+
import { readFileSync as readFileSync5, writeFileSync as writeFileSync5, existsSync as existsSync6, mkdirSync as mkdirSync6 } from "fs";
|
|
184875
|
+
import { join as join7 } from "path";
|
|
184253
184876
|
var BETAS_FILE = ".specific/betas.json";
|
|
184254
184877
|
function loadEnabledBetas(projectDir = process.cwd()) {
|
|
184255
|
-
const filePath =
|
|
184256
|
-
if (!
|
|
184878
|
+
const filePath = join7(projectDir, BETAS_FILE);
|
|
184879
|
+
if (!existsSync6(filePath)) {
|
|
184257
184880
|
return [];
|
|
184258
184881
|
}
|
|
184259
184882
|
try {
|
|
@@ -184276,25 +184899,25 @@ function disableBeta(name, projectDir = process.cwd()) {
|
|
|
184276
184899
|
saveBetas(enabled, projectDir);
|
|
184277
184900
|
}
|
|
184278
184901
|
function saveBetas(enabled, projectDir) {
|
|
184279
|
-
const specificDir =
|
|
184280
|
-
if (!
|
|
184902
|
+
const specificDir = join7(projectDir, ".specific");
|
|
184903
|
+
if (!existsSync6(specificDir)) {
|
|
184281
184904
|
mkdirSync6(specificDir, { recursive: true });
|
|
184282
184905
|
}
|
|
184283
184906
|
const data = { enabled };
|
|
184284
184907
|
writeFileSync5(
|
|
184285
|
-
|
|
184908
|
+
join7(projectDir, BETAS_FILE),
|
|
184286
184909
|
JSON.stringify(data, null, 2) + "\n"
|
|
184287
184910
|
);
|
|
184288
184911
|
}
|
|
184289
184912
|
|
|
184290
184913
|
// src/commands/docs.tsx
|
|
184291
184914
|
var __dirname2 = dirname2(fileURLToPath2(import.meta.url));
|
|
184292
|
-
var docsDir =
|
|
184293
|
-
function docsCommand(
|
|
184294
|
-
const docPath = resolveDocPath(
|
|
184915
|
+
var docsDir = join8(__dirname2, "docs");
|
|
184916
|
+
function docsCommand(path28) {
|
|
184917
|
+
const docPath = resolveDocPath(path28);
|
|
184295
184918
|
if (!docPath) {
|
|
184296
184919
|
console.error(
|
|
184297
|
-
`Documentation not found: ${
|
|
184920
|
+
`Documentation not found: ${path28 || "index"}
|
|
184298
184921
|
|
|
184299
184922
|
Run 'specific docs' to see available topics.`
|
|
184300
184923
|
);
|
|
@@ -184313,17 +184936,17 @@ function filterBetaTags(content, enabledBetas) {
|
|
|
184313
184936
|
}
|
|
184314
184937
|
);
|
|
184315
184938
|
}
|
|
184316
|
-
function resolveDocPath(
|
|
184317
|
-
if (!
|
|
184318
|
-
const indexPath2 =
|
|
184319
|
-
return
|
|
184939
|
+
function resolveDocPath(path28) {
|
|
184940
|
+
if (!path28) {
|
|
184941
|
+
const indexPath2 = join8(docsDir, "index.md");
|
|
184942
|
+
return existsSync7(indexPath2) ? indexPath2 : null;
|
|
184320
184943
|
}
|
|
184321
|
-
const directPath =
|
|
184322
|
-
if (
|
|
184944
|
+
const directPath = join8(docsDir, `${path28}.md`);
|
|
184945
|
+
if (existsSync7(directPath)) {
|
|
184323
184946
|
return directPath;
|
|
184324
184947
|
}
|
|
184325
|
-
const indexPath =
|
|
184326
|
-
if (
|
|
184948
|
+
const indexPath = join8(docsDir, path28, "index.md");
|
|
184949
|
+
if (existsSync7(indexPath)) {
|
|
184327
184950
|
return indexPath;
|
|
184328
184951
|
}
|
|
184329
184952
|
return null;
|
|
@@ -184333,8 +184956,8 @@ function resolveDocPath(path26) {
|
|
|
184333
184956
|
import React3, { useState as useState2, useEffect as useEffect2 } from "react";
|
|
184334
184957
|
import { render as render3, Text as Text3, Box as Box3 } from "ink";
|
|
184335
184958
|
import Spinner3 from "ink-spinner";
|
|
184336
|
-
import * as
|
|
184337
|
-
import * as
|
|
184959
|
+
import * as fs13 from "fs";
|
|
184960
|
+
import * as path9 from "path";
|
|
184338
184961
|
import { execFile as execFile7 } from "child_process";
|
|
184339
184962
|
|
|
184340
184963
|
// node_modules/.pnpm/@specific+config@file+..+config/node_modules/@specific/config/dist/parser.js
|
|
@@ -184437,6 +185060,28 @@ function parseReferenceString(str) {
|
|
|
184437
185060
|
};
|
|
184438
185061
|
}
|
|
184439
185062
|
}
|
|
185063
|
+
const temporalMatch = str.match(/^temporal\.(\w+)\.(\w+)$/);
|
|
185064
|
+
if (temporalMatch && temporalMatch[1] && temporalMatch[2]) {
|
|
185065
|
+
const attr = temporalMatch[2];
|
|
185066
|
+
if (["url", "namespace", "api_key"].includes(attr)) {
|
|
185067
|
+
return {
|
|
185068
|
+
type: "temporal",
|
|
185069
|
+
name: temporalMatch[1],
|
|
185070
|
+
attribute: attr
|
|
185071
|
+
};
|
|
185072
|
+
}
|
|
185073
|
+
}
|
|
185074
|
+
const volumeMatch = str.match(/^volume\.(\w+)\.(\w+)$/);
|
|
185075
|
+
if (volumeMatch && volumeMatch[1] && volumeMatch[2]) {
|
|
185076
|
+
const attr = volumeMatch[2];
|
|
185077
|
+
if (["path"].includes(attr)) {
|
|
185078
|
+
return {
|
|
185079
|
+
type: "volume",
|
|
185080
|
+
volumeName: volumeMatch[1],
|
|
185081
|
+
attribute: attr
|
|
185082
|
+
};
|
|
185083
|
+
}
|
|
185084
|
+
}
|
|
184440
185085
|
const configMatch = str.match(/^config\.(\w+)$/);
|
|
184441
185086
|
if (configMatch && configMatch[1]) {
|
|
184442
185087
|
return { type: "config", name: configMatch[1] };
|
|
@@ -184547,16 +185192,31 @@ function parseBuilds(buildData) {
|
|
|
184547
185192
|
}
|
|
184548
185193
|
const fieldObj = fields;
|
|
184549
185194
|
const base = fieldObj.base;
|
|
184550
|
-
|
|
184551
|
-
|
|
185195
|
+
const dockerfile = fieldObj.dockerfile;
|
|
185196
|
+
if (base && dockerfile) {
|
|
185197
|
+
throw new Error(`Build "${name}" cannot have both "base" and "dockerfile". Use one or the other.`);
|
|
185198
|
+
}
|
|
185199
|
+
if (!base && !dockerfile) {
|
|
185200
|
+
throw new Error(`Build "${name}" must have either "base" (supported: ${VALID_BASES.join(", ")}) or "dockerfile" (path to a custom Dockerfile).`);
|
|
184552
185201
|
}
|
|
184553
|
-
if (
|
|
184554
|
-
|
|
185202
|
+
if (base) {
|
|
185203
|
+
if (typeof base !== "string" || !VALID_BASES.includes(base)) {
|
|
185204
|
+
throw new Error(`Build "${name}" has invalid base "${base}". Supported values: ${VALID_BASES.join(", ")}`);
|
|
185205
|
+
}
|
|
185206
|
+
}
|
|
185207
|
+
if (dockerfile) {
|
|
185208
|
+
if (typeof dockerfile !== "string" || dockerfile.trim() === "") {
|
|
185209
|
+
throw new Error(`Build "${name}" has invalid "dockerfile" value. Must be a non-empty path string.`);
|
|
185210
|
+
}
|
|
185211
|
+
if (fieldObj.command) {
|
|
185212
|
+
throw new Error(`Build "${name}" cannot have both "dockerfile" and "command". When using a custom Dockerfile, the build steps are defined in the Dockerfile itself.`);
|
|
185213
|
+
}
|
|
184555
185214
|
}
|
|
184556
185215
|
const dev = parseDevBlock(fieldObj.dev);
|
|
184557
185216
|
const build = {
|
|
184558
185217
|
name,
|
|
184559
|
-
base
|
|
185218
|
+
...base ? { base } : {},
|
|
185219
|
+
...dockerfile ? { dockerfile: String(dockerfile) } : {}
|
|
184560
185220
|
};
|
|
184561
185221
|
if (fieldObj.command) {
|
|
184562
185222
|
build.command = String(fieldObj.command);
|
|
@@ -184645,6 +185305,22 @@ function parseEndpoints(fieldObj) {
|
|
|
184645
185305
|
}
|
|
184646
185306
|
return endpoints;
|
|
184647
185307
|
}
|
|
185308
|
+
function parseVolumes(fieldObj) {
|
|
185309
|
+
const volumes = [];
|
|
185310
|
+
const volumeData = fieldObj.volume;
|
|
185311
|
+
if (!volumeData) {
|
|
185312
|
+
return volumes;
|
|
185313
|
+
}
|
|
185314
|
+
if (typeof volumeData !== "object") {
|
|
185315
|
+
return volumes;
|
|
185316
|
+
}
|
|
185317
|
+
if (!Array.isArray(volumeData)) {
|
|
185318
|
+
for (const [name] of Object.entries(volumeData)) {
|
|
185319
|
+
volumes.push({ name });
|
|
185320
|
+
}
|
|
185321
|
+
}
|
|
185322
|
+
return volumes;
|
|
185323
|
+
}
|
|
184648
185324
|
function parseServices(serviceData) {
|
|
184649
185325
|
if (!serviceData || typeof serviceData !== "object" || Array.isArray(serviceData)) {
|
|
184650
185326
|
return [];
|
|
@@ -184668,6 +185344,10 @@ function parseServices(serviceData) {
|
|
|
184668
185344
|
service.root = String(fieldObj.root);
|
|
184669
185345
|
}
|
|
184670
185346
|
const endpoints = parseEndpoints(fieldObj);
|
|
185347
|
+
const volumes = parseVolumes(fieldObj);
|
|
185348
|
+
if (volumes.length > 0) {
|
|
185349
|
+
service.volumes = volumes;
|
|
185350
|
+
}
|
|
184671
185351
|
if (fieldObj.expose !== void 0) {
|
|
184672
185352
|
service.expose = {};
|
|
184673
185353
|
if (endpoints.length === 0) {
|
|
@@ -184761,6 +185441,16 @@ function parseStorage(data) {
|
|
|
184761
185441
|
}
|
|
184762
185442
|
return result;
|
|
184763
185443
|
}
|
|
185444
|
+
function parseTemporal(data) {
|
|
185445
|
+
if (!data || typeof data !== "object" || Array.isArray(data)) {
|
|
185446
|
+
return [];
|
|
185447
|
+
}
|
|
185448
|
+
const result = [];
|
|
185449
|
+
for (const [name] of Object.entries(data)) {
|
|
185450
|
+
result.push({ name });
|
|
185451
|
+
}
|
|
185452
|
+
return result;
|
|
185453
|
+
}
|
|
184764
185454
|
function parseConfigDevBlock(dev) {
|
|
184765
185455
|
if (!dev) {
|
|
184766
185456
|
return void 0;
|
|
@@ -184872,6 +185562,7 @@ async function parseConfig(hcl) {
|
|
|
184872
185562
|
postgres: parsePostgres(json.postgres),
|
|
184873
185563
|
redis: parseRedis(json.redis),
|
|
184874
185564
|
storage: parseStorage(json.storage),
|
|
185565
|
+
temporal: parseTemporal(json.temporal),
|
|
184875
185566
|
configs: parseConfigs(json.config),
|
|
184876
185567
|
secrets: parseSecrets(json.secret),
|
|
184877
185568
|
environments: parseEnvironments(json.environment)
|
|
@@ -184970,12 +185661,101 @@ function validateEndpointReferences(config) {
|
|
|
184970
185661
|
});
|
|
184971
185662
|
}
|
|
184972
185663
|
}
|
|
185664
|
+
if (ref.type === "volume") {
|
|
185665
|
+
const volumeRef = ref;
|
|
185666
|
+
const volumeExists = service.volumes?.some((v) => v.name === volumeRef.volumeName);
|
|
185667
|
+
if (!volumeExists) {
|
|
185668
|
+
errors.push({
|
|
185669
|
+
service: service.name,
|
|
185670
|
+
message: `Service "${service.name}" references volume "${volumeRef.volumeName}" in env var "${key}", but that volume is not defined on this service.`
|
|
185671
|
+
});
|
|
185672
|
+
}
|
|
185673
|
+
}
|
|
184973
185674
|
}
|
|
184974
185675
|
}
|
|
184975
185676
|
}
|
|
184976
185677
|
return errors;
|
|
184977
185678
|
}
|
|
184978
185679
|
|
|
185680
|
+
// node_modules/.pnpm/@specific+config@file+..+config/node_modules/@specific/config/dist/errors.js
|
|
185681
|
+
function parseHclErrors(rawError) {
|
|
185682
|
+
const raw = rawError.trim();
|
|
185683
|
+
if (!raw.startsWith("parse config: [")) {
|
|
185684
|
+
return [];
|
|
185685
|
+
}
|
|
185686
|
+
const inner = raw.slice("parse config: [".length, -1);
|
|
185687
|
+
const errors = [];
|
|
185688
|
+
const locationPattern = /:(\d+),(\d+)-(?:(\d+),)?(\d+):\s*/g;
|
|
185689
|
+
const locations = [];
|
|
185690
|
+
let match;
|
|
185691
|
+
while ((match = locationPattern.exec(inner)) !== null) {
|
|
185692
|
+
const line = parseInt(match[1], 10);
|
|
185693
|
+
const colStart = parseInt(match[2], 10);
|
|
185694
|
+
const endLine = match[3] ? parseInt(match[3], 10) : line;
|
|
185695
|
+
const colEnd = parseInt(match[4], 10);
|
|
185696
|
+
locations.push({
|
|
185697
|
+
index: match.index,
|
|
185698
|
+
line,
|
|
185699
|
+
colStart,
|
|
185700
|
+
endLine,
|
|
185701
|
+
colEnd,
|
|
185702
|
+
matchEnd: match.index + match[0].length
|
|
185703
|
+
});
|
|
185704
|
+
}
|
|
185705
|
+
for (let i = 0; i < locations.length; i++) {
|
|
185706
|
+
const loc = locations[i];
|
|
185707
|
+
const nextStart = locations[i + 1]?.index ?? inner.length;
|
|
185708
|
+
const messageText = inner.slice(loc.matchEnd, nextStart).trim();
|
|
185709
|
+
const semicolonIdx = messageText.indexOf(";");
|
|
185710
|
+
let title;
|
|
185711
|
+
let description;
|
|
185712
|
+
if (semicolonIdx !== -1) {
|
|
185713
|
+
title = messageText.slice(0, semicolonIdx).trim();
|
|
185714
|
+
description = messageText.slice(semicolonIdx + 1).trim();
|
|
185715
|
+
} else {
|
|
185716
|
+
title = messageText;
|
|
185717
|
+
description = "";
|
|
185718
|
+
}
|
|
185719
|
+
errors.push({
|
|
185720
|
+
line: loc.line,
|
|
185721
|
+
colStart: loc.colStart,
|
|
185722
|
+
endLine: loc.endLine,
|
|
185723
|
+
colEnd: loc.colEnd,
|
|
185724
|
+
title,
|
|
185725
|
+
description
|
|
185726
|
+
});
|
|
185727
|
+
}
|
|
185728
|
+
return errors;
|
|
185729
|
+
}
|
|
185730
|
+
|
|
185731
|
+
// src/lib/format-config-error.ts
|
|
185732
|
+
var import_code_frame = __toESM(require_lib2(), 1);
|
|
185733
|
+
function formatConfigError(err, fileContents, filePath) {
|
|
185734
|
+
const raw = err instanceof Error ? err.message : String(err);
|
|
185735
|
+
const errors = parseHclErrors(raw);
|
|
185736
|
+
if (errors.length === 0) {
|
|
185737
|
+
return `Error: Invalid configuration: ${raw}`;
|
|
185738
|
+
}
|
|
185739
|
+
const name = filePath ?? "specific.hcl";
|
|
185740
|
+
const header = errors.length === 1 ? `Error in ${name}:` : `${errors.length} errors in ${name}:`;
|
|
185741
|
+
const blocks = errors.map((e) => {
|
|
185742
|
+
const frame = (0, import_code_frame.codeFrameColumns)(
|
|
185743
|
+
fileContents,
|
|
185744
|
+
{
|
|
185745
|
+
start: { line: e.line, column: e.colStart },
|
|
185746
|
+
end: { line: e.endLine, column: e.colEnd }
|
|
185747
|
+
},
|
|
185748
|
+
{ highlightCode: false, message: e.description }
|
|
185749
|
+
);
|
|
185750
|
+
return ` ${e.title}
|
|
185751
|
+
|
|
185752
|
+
${frame}`;
|
|
185753
|
+
});
|
|
185754
|
+
return `${header}
|
|
185755
|
+
|
|
185756
|
+
${blocks.join("\n\n")}`;
|
|
185757
|
+
}
|
|
185758
|
+
|
|
184979
185759
|
// src/lib/bin/types.ts
|
|
184980
185760
|
var BinaryNotFoundError = class extends Error {
|
|
184981
185761
|
constructor(binaryName, version, platformInfo) {
|
|
@@ -185011,32 +185791,32 @@ var ExtractionError = class extends Error {
|
|
|
185011
185791
|
};
|
|
185012
185792
|
|
|
185013
185793
|
// src/lib/bin/manager.ts
|
|
185014
|
-
import * as
|
|
185015
|
-
import * as
|
|
185016
|
-
import * as
|
|
185794
|
+
import * as fs12 from "fs";
|
|
185795
|
+
import * as path8 from "path";
|
|
185796
|
+
import * as os7 from "os";
|
|
185017
185797
|
import { createReadStream } from "fs";
|
|
185018
185798
|
import { createTarExtractor, extractTo } from "tar-vern";
|
|
185019
185799
|
function getLibraryEnv(binary) {
|
|
185020
185800
|
if (!binary.libraryPath) {
|
|
185021
185801
|
return {};
|
|
185022
185802
|
}
|
|
185023
|
-
const
|
|
185024
|
-
if (
|
|
185803
|
+
const platform5 = os7.platform();
|
|
185804
|
+
if (platform5 === "darwin") {
|
|
185025
185805
|
return { DYLD_LIBRARY_PATH: binary.libraryPath };
|
|
185026
|
-
} else if (
|
|
185806
|
+
} else if (platform5 === "linux") {
|
|
185027
185807
|
return { LD_LIBRARY_PATH: binary.libraryPath };
|
|
185028
185808
|
}
|
|
185029
185809
|
return {};
|
|
185030
185810
|
}
|
|
185031
185811
|
function getBinBaseDir() {
|
|
185032
|
-
return
|
|
185812
|
+
return path8.join(os7.homedir(), ".specific", "bin");
|
|
185033
185813
|
}
|
|
185034
185814
|
function getPlatformInfo() {
|
|
185035
|
-
const
|
|
185036
|
-
const arch3 =
|
|
185037
|
-
if (
|
|
185815
|
+
const platform5 = os7.platform();
|
|
185816
|
+
const arch3 = os7.arch();
|
|
185817
|
+
if (platform5 !== "darwin" && platform5 !== "linux") {
|
|
185038
185818
|
throw new Error(
|
|
185039
|
-
`Unsupported platform: ${
|
|
185819
|
+
`Unsupported platform: ${platform5}. Only macOS and Linux are supported.`
|
|
185040
185820
|
);
|
|
185041
185821
|
}
|
|
185042
185822
|
const archStr = arch3;
|
|
@@ -185050,10 +185830,10 @@ function getPlatformInfo() {
|
|
|
185050
185830
|
`Unsupported architecture: ${arch3}. Only x64 and arm64 are supported.`
|
|
185051
185831
|
);
|
|
185052
185832
|
}
|
|
185053
|
-
return { platform:
|
|
185833
|
+
return { platform: platform5, arch: mappedArch };
|
|
185054
185834
|
}
|
|
185055
185835
|
function getBinaryDir(definition, version, platformInfo) {
|
|
185056
|
-
return
|
|
185836
|
+
return path8.join(
|
|
185057
185837
|
getBinBaseDir(),
|
|
185058
185838
|
definition.name,
|
|
185059
185839
|
version,
|
|
@@ -185063,8 +185843,8 @@ function getBinaryDir(definition, version, platformInfo) {
|
|
|
185063
185843
|
function isBinaryInstalled(definition, version, platformInfo) {
|
|
185064
185844
|
const binDir = getBinaryDir(definition, version, platformInfo);
|
|
185065
185845
|
for (const execPath of definition.executables) {
|
|
185066
|
-
const fullPath =
|
|
185067
|
-
if (!
|
|
185846
|
+
const fullPath = path8.join(binDir, execPath);
|
|
185847
|
+
if (!fs12.existsSync(fullPath)) {
|
|
185068
185848
|
return false;
|
|
185069
185849
|
}
|
|
185070
185850
|
}
|
|
@@ -185092,12 +185872,12 @@ async function downloadFile(url, destPath, onProgress) {
|
|
|
185092
185872
|
10
|
|
185093
185873
|
);
|
|
185094
185874
|
let bytesDownloaded = 0;
|
|
185095
|
-
const parentDir =
|
|
185096
|
-
if (!
|
|
185097
|
-
|
|
185875
|
+
const parentDir = path8.dirname(destPath);
|
|
185876
|
+
if (!fs12.existsSync(parentDir)) {
|
|
185877
|
+
fs12.mkdirSync(parentDir, { recursive: true });
|
|
185098
185878
|
}
|
|
185099
185879
|
const partPath = destPath + ".part";
|
|
185100
|
-
const fileStream =
|
|
185880
|
+
const fileStream = fs12.createWriteStream(partPath);
|
|
185101
185881
|
try {
|
|
185102
185882
|
const reader = response.body.getReader();
|
|
185103
185883
|
while (true) {
|
|
@@ -185120,12 +185900,12 @@ async function downloadFile(url, destPath, onProgress) {
|
|
|
185120
185900
|
else resolve10();
|
|
185121
185901
|
});
|
|
185122
185902
|
});
|
|
185123
|
-
|
|
185903
|
+
fs12.renameSync(partPath, destPath);
|
|
185124
185904
|
} catch (error) {
|
|
185125
185905
|
try {
|
|
185126
185906
|
fileStream.close();
|
|
185127
|
-
if (
|
|
185128
|
-
|
|
185907
|
+
if (fs12.existsSync(partPath)) {
|
|
185908
|
+
fs12.unlinkSync(partPath);
|
|
185129
185909
|
}
|
|
185130
185910
|
} catch {
|
|
185131
185911
|
}
|
|
@@ -185134,8 +185914,8 @@ async function downloadFile(url, destPath, onProgress) {
|
|
|
185134
185914
|
}
|
|
185135
185915
|
async function extractTarball(archivePath, destDir, definition, onProgress) {
|
|
185136
185916
|
onProgress?.({ phase: "extracting" });
|
|
185137
|
-
if (!
|
|
185138
|
-
|
|
185917
|
+
if (!fs12.existsSync(destDir)) {
|
|
185918
|
+
fs12.mkdirSync(destDir, { recursive: true });
|
|
185139
185919
|
}
|
|
185140
185920
|
try {
|
|
185141
185921
|
const fileStream = createReadStream(archivePath);
|
|
@@ -185143,9 +185923,9 @@ async function extractTarball(archivePath, destDir, definition, onProgress) {
|
|
|
185143
185923
|
await extractTo(entries, destDir);
|
|
185144
185924
|
onProgress?.({ phase: "finalizing" });
|
|
185145
185925
|
for (const execPath of definition.executables) {
|
|
185146
|
-
const fullPath =
|
|
185147
|
-
if (
|
|
185148
|
-
|
|
185926
|
+
const fullPath = path8.join(destDir, execPath);
|
|
185927
|
+
if (fs12.existsSync(fullPath)) {
|
|
185928
|
+
fs12.chmodSync(fullPath, 493);
|
|
185149
185929
|
}
|
|
185150
185930
|
}
|
|
185151
185931
|
} catch (error) {
|
|
@@ -185169,24 +185949,24 @@ async function ensureBinary(definition, version, onProgress) {
|
|
|
185169
185949
|
`Binary type definitions must have exactly one executable, got ${definition.executables.length}`
|
|
185170
185950
|
);
|
|
185171
185951
|
}
|
|
185172
|
-
if (!
|
|
185173
|
-
|
|
185952
|
+
if (!fs12.existsSync(binDir)) {
|
|
185953
|
+
fs12.mkdirSync(binDir, { recursive: true });
|
|
185174
185954
|
}
|
|
185175
|
-
const execPath =
|
|
185955
|
+
const execPath = path8.join(binDir, definition.executables[0]);
|
|
185176
185956
|
await downloadFile(url, execPath, onProgress);
|
|
185177
|
-
|
|
185957
|
+
fs12.chmodSync(execPath, 493);
|
|
185178
185958
|
onProgress?.({ phase: "finalizing" });
|
|
185179
185959
|
} else {
|
|
185180
|
-
const downloadDir =
|
|
185960
|
+
const downloadDir = path8.join(getBinBaseDir(), "downloads");
|
|
185181
185961
|
const archiveName = `${definition.name}-${resolvedVersion}-${platformInfo.platform}-${platformInfo.arch}.tar.gz`;
|
|
185182
|
-
const archivePath =
|
|
185962
|
+
const archivePath = path8.join(downloadDir, archiveName);
|
|
185183
185963
|
try {
|
|
185184
185964
|
await downloadFile(url, archivePath, onProgress);
|
|
185185
185965
|
await extractTarball(archivePath, binDir, definition, onProgress);
|
|
185186
185966
|
} finally {
|
|
185187
185967
|
try {
|
|
185188
|
-
if (
|
|
185189
|
-
|
|
185968
|
+
if (fs12.existsSync(archivePath)) {
|
|
185969
|
+
fs12.unlinkSync(archivePath);
|
|
185190
185970
|
}
|
|
185191
185971
|
} catch {
|
|
185192
185972
|
}
|
|
@@ -185195,10 +185975,10 @@ async function ensureBinary(definition, version, onProgress) {
|
|
|
185195
185975
|
}
|
|
185196
185976
|
const executables = {};
|
|
185197
185977
|
for (const execPath of definition.executables) {
|
|
185198
|
-
const name =
|
|
185199
|
-
executables[name] =
|
|
185978
|
+
const name = path8.basename(execPath);
|
|
185979
|
+
executables[name] = path8.join(binDir, execPath);
|
|
185200
185980
|
}
|
|
185201
|
-
const libraryPath = definition.libraryDir ?
|
|
185981
|
+
const libraryPath = definition.libraryDir ? path8.join(binDir, definition.libraryDir) : void 0;
|
|
185202
185982
|
return {
|
|
185203
185983
|
rootDir: binDir,
|
|
185204
185984
|
version: resolvedVersion,
|
|
@@ -185319,6 +186099,25 @@ var reshapeBinary = {
|
|
|
185319
186099
|
executables: ["reshape"]
|
|
185320
186100
|
};
|
|
185321
186101
|
|
|
186102
|
+
// src/lib/bin/definitions/temporal.ts
|
|
186103
|
+
var temporalBinary = {
|
|
186104
|
+
name: "temporal",
|
|
186105
|
+
versions: ["1.3.0"],
|
|
186106
|
+
urlTemplate: "https://temporal.download/cli/archive/v{version}?platform={platform}&arch={arch}",
|
|
186107
|
+
platformMapping: {
|
|
186108
|
+
darwin: {
|
|
186109
|
+
arm64: { platform: "darwin", arch: "arm64" },
|
|
186110
|
+
x64: { platform: "darwin", arch: "amd64" }
|
|
186111
|
+
},
|
|
186112
|
+
linux: {
|
|
186113
|
+
arm64: { platform: "linux", arch: "arm64" },
|
|
186114
|
+
x64: { platform: "linux", arch: "amd64" }
|
|
186115
|
+
}
|
|
186116
|
+
},
|
|
186117
|
+
stripComponents: 0,
|
|
186118
|
+
executables: ["temporal"]
|
|
186119
|
+
};
|
|
186120
|
+
|
|
185322
186121
|
// src/commands/check.tsx
|
|
185323
186122
|
async function runReshapeCheck(migrationsDir) {
|
|
185324
186123
|
try {
|
|
@@ -185342,25 +186141,37 @@ function CheckUI() {
|
|
|
185342
186141
|
const [state, setState] = useState2({ status: "loading" });
|
|
185343
186142
|
useEffect2(() => {
|
|
185344
186143
|
async function load() {
|
|
185345
|
-
const configPath =
|
|
185346
|
-
if (!
|
|
186144
|
+
const configPath = path9.join(process.cwd(), "specific.hcl");
|
|
186145
|
+
if (!fs13.existsSync(configPath)) {
|
|
185347
186146
|
setState({
|
|
185348
186147
|
status: "error",
|
|
185349
186148
|
error: "No specific.hcl found in current directory"
|
|
185350
186149
|
});
|
|
185351
186150
|
return;
|
|
185352
186151
|
}
|
|
186152
|
+
const hcl = fs13.readFileSync(configPath, "utf-8");
|
|
185353
186153
|
try {
|
|
185354
|
-
const hcl = fs12.readFileSync(configPath, "utf-8");
|
|
185355
186154
|
const config2 = await parseConfig(hcl);
|
|
186155
|
+
for (const build of config2.builds) {
|
|
186156
|
+
if (build.dockerfile) {
|
|
186157
|
+
const dockerfilePath = path9.resolve(process.cwd(), build.dockerfile);
|
|
186158
|
+
if (!fs13.existsSync(dockerfilePath)) {
|
|
186159
|
+
setState({
|
|
186160
|
+
status: "error",
|
|
186161
|
+
error: `Build "${build.name}": Dockerfile not found at "${build.dockerfile}" (resolved to ${dockerfilePath})`
|
|
186162
|
+
});
|
|
186163
|
+
return;
|
|
186164
|
+
}
|
|
186165
|
+
}
|
|
186166
|
+
}
|
|
185356
186167
|
const reshapeChecks2 = [];
|
|
185357
186168
|
for (const pg of config2.postgres) {
|
|
185358
186169
|
if (pg.reshape?.enabled) {
|
|
185359
|
-
const migrationsDir =
|
|
186170
|
+
const migrationsDir = path9.resolve(
|
|
185360
186171
|
process.cwd(),
|
|
185361
186172
|
pg.reshape.migrations_dir ?? "migrations"
|
|
185362
186173
|
);
|
|
185363
|
-
if (!
|
|
186174
|
+
if (!fs13.existsSync(migrationsDir)) {
|
|
185364
186175
|
reshapeChecks2.push({
|
|
185365
186176
|
databaseName: pg.name,
|
|
185366
186177
|
migrationsDir: pg.reshape.migrations_dir ?? "migrations",
|
|
@@ -185384,7 +186195,7 @@ function CheckUI() {
|
|
|
185384
186195
|
} catch (err) {
|
|
185385
186196
|
setState({
|
|
185386
186197
|
status: "error",
|
|
185387
|
-
error: err
|
|
186198
|
+
error: formatConfigError(err, hcl, configPath)
|
|
185388
186199
|
});
|
|
185389
186200
|
}
|
|
185390
186201
|
}
|
|
@@ -185394,7 +186205,7 @@ function CheckUI() {
|
|
|
185394
186205
|
return /* @__PURE__ */ React3.createElement(Box3, null, /* @__PURE__ */ React3.createElement(Text3, { color: "blue" }, /* @__PURE__ */ React3.createElement(Spinner3, { type: "dots" })), /* @__PURE__ */ React3.createElement(Text3, null, " Checking configuration..."));
|
|
185395
186206
|
}
|
|
185396
186207
|
if (state.status === "error") {
|
|
185397
|
-
return /* @__PURE__ */ React3.createElement(Box3, { flexDirection: "column" }, /* @__PURE__ */ React3.createElement(Text3, { color: "red" },
|
|
186208
|
+
return /* @__PURE__ */ React3.createElement(Box3, { flexDirection: "column" }, /* @__PURE__ */ React3.createElement(Text3, { color: "red" }, state.error));
|
|
185398
186209
|
}
|
|
185399
186210
|
const { config } = state;
|
|
185400
186211
|
if (!config) {
|
|
@@ -185403,7 +186214,7 @@ function CheckUI() {
|
|
|
185403
186214
|
const reshapeChecks = state.reshapeChecks ?? [];
|
|
185404
186215
|
const reshapeErrors = reshapeChecks.filter((r) => !r.success);
|
|
185405
186216
|
const hasReshapeErrors = reshapeErrors.length > 0;
|
|
185406
|
-
return /* @__PURE__ */ React3.createElement(Box3, { flexDirection: "column", gap: 1 }, /* @__PURE__ */ React3.createElement(Text3, { color: hasReshapeErrors ? "yellow" : "green" }, hasReshapeErrors ? "Configuration is valid but reshape migrations have errors" : "Configuration is valid"), config.builds.length > 0 && /* @__PURE__ */ React3.createElement(Box3, { flexDirection: "column" }, /* @__PURE__ */ React3.createElement(Text3, { bold: true }, "Builds (", config.builds.length, "):"), config.builds.map((b) => /* @__PURE__ */ React3.createElement(Text3, { key: b.name }, " ", "- ", b.name))), config.services.length > 0 && /* @__PURE__ */ React3.createElement(Box3, { flexDirection: "column" }, /* @__PURE__ */ React3.createElement(Text3, { bold: true }, "Services (", config.services.length, "):"), config.services.map((s) => /* @__PURE__ */ React3.createElement(Text3, { key: s.name }, " ", "- ", s.name))), config.postgres.length > 0 && /* @__PURE__ */ React3.createElement(Box3, { flexDirection: "column" }, /* @__PURE__ */ React3.createElement(Text3, { bold: true }, "Postgres (", config.postgres.length, "):"), config.postgres.map((p) => /* @__PURE__ */ React3.createElement(Text3, { key: p.name }, " ", "- ", p.name, p.reshape?.enabled ? " (reshape enabled)" : ""))), reshapeChecks.length > 0 && /* @__PURE__ */ React3.createElement(Box3, { flexDirection: "column" }, /* @__PURE__ */ React3.createElement(Text3, { bold: true }, "Reshape Migrations:"), reshapeChecks.map((r) => /* @__PURE__ */ React3.createElement(Box3, { key: r.databaseName, flexDirection: "column" }, /* @__PURE__ */ React3.createElement(Text3, null, " ", /* @__PURE__ */ React3.createElement(Text3, { color: r.success ? "green" : "red" }, r.success ? "pass" : "fail"), " ", r.databaseName, " (", r.migrationsDir, ")"), r.error && /* @__PURE__ */ React3.createElement(Text3, { color: "red" }, " ", r.error)))), config.redis.length > 0 && /* @__PURE__ */ React3.createElement(Box3, { flexDirection: "column" }, /* @__PURE__ */ React3.createElement(Text3, { bold: true }, "Redis (", config.redis.length, "):"), config.redis.map((r) => /* @__PURE__ */ React3.createElement(Text3, { key: r.name }, " ", "- ", r.name))), config.storage.length > 0 && /* @__PURE__ */ React3.createElement(Box3, { flexDirection: "column" }, /* @__PURE__ */ React3.createElement(Text3, { bold: true }, "Storage (", config.storage.length, "):"), config.storage.map((s) => /* @__PURE__ */ React3.createElement(Text3, { key: s.name }, " ", "- ", s.name))), config.configs.length > 0 && /* @__PURE__ */ React3.createElement(Box3, { flexDirection: "column" }, /* @__PURE__ */ React3.createElement(Text3, { bold: true }, "Config (", config.configs.length, "):"), config.configs.map((c) => /* @__PURE__ */ React3.createElement(Text3, { key: c.name }, " ", "- ", c.name, c.default ? ` (default: ${c.default})` : ""))), config.environments.length > 0 && /* @__PURE__ */ React3.createElement(Box3, { flexDirection: "column" }, /* @__PURE__ */ React3.createElement(Text3, { bold: true }, "Environments (", config.environments.length, "):"), config.environments.map((e) => /* @__PURE__ */ React3.createElement(Text3, { key: e.name }, " ", "- ", e.name))));
|
|
186217
|
+
return /* @__PURE__ */ React3.createElement(Box3, { flexDirection: "column", gap: 1 }, /* @__PURE__ */ React3.createElement(Text3, { color: hasReshapeErrors ? "yellow" : "green" }, hasReshapeErrors ? "Configuration is valid but reshape migrations have errors" : "Configuration is valid"), config.builds.length > 0 && /* @__PURE__ */ React3.createElement(Box3, { flexDirection: "column" }, /* @__PURE__ */ React3.createElement(Text3, { bold: true }, "Builds (", config.builds.length, "):"), config.builds.map((b) => /* @__PURE__ */ React3.createElement(Text3, { key: b.name }, " ", "- ", b.name, b.base ? ` (${b.base})` : "", b.dockerfile ? ` (dockerfile: ${b.dockerfile})` : ""))), config.services.length > 0 && /* @__PURE__ */ React3.createElement(Box3, { flexDirection: "column" }, /* @__PURE__ */ React3.createElement(Text3, { bold: true }, "Services (", config.services.length, "):"), config.services.map((s) => /* @__PURE__ */ React3.createElement(Text3, { key: s.name }, " ", "- ", s.name))), config.postgres.length > 0 && /* @__PURE__ */ React3.createElement(Box3, { flexDirection: "column" }, /* @__PURE__ */ React3.createElement(Text3, { bold: true }, "Postgres (", config.postgres.length, "):"), config.postgres.map((p) => /* @__PURE__ */ React3.createElement(Text3, { key: p.name }, " ", "- ", p.name, p.reshape?.enabled ? " (reshape enabled)" : ""))), reshapeChecks.length > 0 && /* @__PURE__ */ React3.createElement(Box3, { flexDirection: "column" }, /* @__PURE__ */ React3.createElement(Text3, { bold: true }, "Reshape Migrations:"), reshapeChecks.map((r) => /* @__PURE__ */ React3.createElement(Box3, { key: r.databaseName, flexDirection: "column" }, /* @__PURE__ */ React3.createElement(Text3, null, " ", /* @__PURE__ */ React3.createElement(Text3, { color: r.success ? "green" : "red" }, r.success ? "pass" : "fail"), " ", r.databaseName, " (", r.migrationsDir, ")"), r.error && /* @__PURE__ */ React3.createElement(Text3, { color: "red" }, " ", r.error)))), config.redis.length > 0 && /* @__PURE__ */ React3.createElement(Box3, { flexDirection: "column" }, /* @__PURE__ */ React3.createElement(Text3, { bold: true }, "Redis (", config.redis.length, "):"), config.redis.map((r) => /* @__PURE__ */ React3.createElement(Text3, { key: r.name }, " ", "- ", r.name))), config.storage.length > 0 && /* @__PURE__ */ React3.createElement(Box3, { flexDirection: "column" }, /* @__PURE__ */ React3.createElement(Text3, { bold: true }, "Storage (", config.storage.length, "):"), config.storage.map((s) => /* @__PURE__ */ React3.createElement(Text3, { key: s.name }, " ", "- ", s.name))), config.configs.length > 0 && /* @__PURE__ */ React3.createElement(Box3, { flexDirection: "column" }, /* @__PURE__ */ React3.createElement(Text3, { bold: true }, "Config (", config.configs.length, "):"), config.configs.map((c) => /* @__PURE__ */ React3.createElement(Text3, { key: c.name }, " ", "- ", c.name, c.default ? ` (default: ${c.default})` : ""))), config.environments.length > 0 && /* @__PURE__ */ React3.createElement(Box3, { flexDirection: "column" }, /* @__PURE__ */ React3.createElement(Text3, { bold: true }, "Environments (", config.environments.length, "):"), config.environments.map((e) => /* @__PURE__ */ React3.createElement(Text3, { key: e.name }, " ", "- ", e.name))));
|
|
185407
186218
|
}
|
|
185408
186219
|
function checkCommand() {
|
|
185409
186220
|
render3(/* @__PURE__ */ React3.createElement(CheckUI, null));
|
|
@@ -185413,8 +186224,8 @@ function checkCommand() {
|
|
|
185413
186224
|
import React6, { useState as useState5, useEffect as useEffect3, useRef } from "react";
|
|
185414
186225
|
import { render as render4, Text as Text6, Box as Box6, useApp as useApp2, Static } from "ink";
|
|
185415
186226
|
import Spinner4 from "ink-spinner";
|
|
185416
|
-
import * as
|
|
185417
|
-
import * as
|
|
186227
|
+
import * as fs23 from "fs";
|
|
186228
|
+
import * as path20 from "path";
|
|
185418
186229
|
|
|
185419
186230
|
// node_modules/.pnpm/chokidar@5.0.0/node_modules/chokidar/index.js
|
|
185420
186231
|
import { EventEmitter } from "node:events";
|
|
@@ -185506,7 +186317,7 @@ var ReaddirpStream = class extends Readable {
|
|
|
185506
186317
|
this._directoryFilter = normalizeFilter(opts.directoryFilter);
|
|
185507
186318
|
const statMethod = opts.lstat ? lstat : stat;
|
|
185508
186319
|
if (wantBigintFsStats) {
|
|
185509
|
-
this._stat = (
|
|
186320
|
+
this._stat = (path28) => statMethod(path28, { bigint: true });
|
|
185510
186321
|
} else {
|
|
185511
186322
|
this._stat = statMethod;
|
|
185512
186323
|
}
|
|
@@ -185531,8 +186342,8 @@ var ReaddirpStream = class extends Readable {
|
|
|
185531
186342
|
const par = this.parent;
|
|
185532
186343
|
const fil = par && par.files;
|
|
185533
186344
|
if (fil && fil.length > 0) {
|
|
185534
|
-
const { path:
|
|
185535
|
-
const slice = fil.splice(0, batch).map((dirent) => this._formatEntry(dirent,
|
|
186345
|
+
const { path: path28, depth } = par;
|
|
186346
|
+
const slice = fil.splice(0, batch).map((dirent) => this._formatEntry(dirent, path28));
|
|
185536
186347
|
const awaited = await Promise.all(slice);
|
|
185537
186348
|
for (const entry of awaited) {
|
|
185538
186349
|
if (!entry)
|
|
@@ -185572,20 +186383,20 @@ var ReaddirpStream = class extends Readable {
|
|
|
185572
186383
|
this.reading = false;
|
|
185573
186384
|
}
|
|
185574
186385
|
}
|
|
185575
|
-
async _exploreDir(
|
|
186386
|
+
async _exploreDir(path28, depth) {
|
|
185576
186387
|
let files;
|
|
185577
186388
|
try {
|
|
185578
|
-
files = await readdir(
|
|
186389
|
+
files = await readdir(path28, this._rdOptions);
|
|
185579
186390
|
} catch (error) {
|
|
185580
186391
|
this._onError(error);
|
|
185581
186392
|
}
|
|
185582
|
-
return { files, depth, path:
|
|
186393
|
+
return { files, depth, path: path28 };
|
|
185583
186394
|
}
|
|
185584
|
-
async _formatEntry(dirent,
|
|
186395
|
+
async _formatEntry(dirent, path28) {
|
|
185585
186396
|
let entry;
|
|
185586
186397
|
const basename6 = this._isDirent ? dirent.name : dirent;
|
|
185587
186398
|
try {
|
|
185588
|
-
const fullPath = presolve(pjoin(
|
|
186399
|
+
const fullPath = presolve(pjoin(path28, basename6));
|
|
185589
186400
|
entry = { path: prelative(this._root, fullPath), fullPath, basename: basename6 };
|
|
185590
186401
|
entry[this._statsProp] = this._isDirent ? dirent : await this._stat(fullPath);
|
|
185591
186402
|
} catch (err) {
|
|
@@ -185985,16 +186796,16 @@ var delFromSet = (main, prop, item) => {
|
|
|
185985
186796
|
};
|
|
185986
186797
|
var isEmptySet = (val) => val instanceof Set ? val.size === 0 : !val;
|
|
185987
186798
|
var FsWatchInstances = /* @__PURE__ */ new Map();
|
|
185988
|
-
function createFsWatchInstance(
|
|
186799
|
+
function createFsWatchInstance(path28, options2, listener, errHandler, emitRaw) {
|
|
185989
186800
|
const handleEvent = (rawEvent, evPath) => {
|
|
185990
|
-
listener(
|
|
185991
|
-
emitRaw(rawEvent, evPath, { watchedPath:
|
|
185992
|
-
if (evPath &&
|
|
185993
|
-
fsWatchBroadcast(sp.resolve(
|
|
186801
|
+
listener(path28);
|
|
186802
|
+
emitRaw(rawEvent, evPath, { watchedPath: path28 });
|
|
186803
|
+
if (evPath && path28 !== evPath) {
|
|
186804
|
+
fsWatchBroadcast(sp.resolve(path28, evPath), KEY_LISTENERS, sp.join(path28, evPath));
|
|
185994
186805
|
}
|
|
185995
186806
|
};
|
|
185996
186807
|
try {
|
|
185997
|
-
return fs_watch(
|
|
186808
|
+
return fs_watch(path28, {
|
|
185998
186809
|
persistent: options2.persistent
|
|
185999
186810
|
}, handleEvent);
|
|
186000
186811
|
} catch (error) {
|
|
@@ -186010,12 +186821,12 @@ var fsWatchBroadcast = (fullPath, listenerType, val1, val2, val3) => {
|
|
|
186010
186821
|
listener(val1, val2, val3);
|
|
186011
186822
|
});
|
|
186012
186823
|
};
|
|
186013
|
-
var setFsWatchListener = (
|
|
186824
|
+
var setFsWatchListener = (path28, fullPath, options2, handlers) => {
|
|
186014
186825
|
const { listener, errHandler, rawEmitter } = handlers;
|
|
186015
186826
|
let cont = FsWatchInstances.get(fullPath);
|
|
186016
186827
|
let watcher;
|
|
186017
186828
|
if (!options2.persistent) {
|
|
186018
|
-
watcher = createFsWatchInstance(
|
|
186829
|
+
watcher = createFsWatchInstance(path28, options2, listener, errHandler, rawEmitter);
|
|
186019
186830
|
if (!watcher)
|
|
186020
186831
|
return;
|
|
186021
186832
|
return watcher.close.bind(watcher);
|
|
@@ -186026,7 +186837,7 @@ var setFsWatchListener = (path26, fullPath, options2, handlers) => {
|
|
|
186026
186837
|
addAndConvert(cont, KEY_RAW, rawEmitter);
|
|
186027
186838
|
} else {
|
|
186028
186839
|
watcher = createFsWatchInstance(
|
|
186029
|
-
|
|
186840
|
+
path28,
|
|
186030
186841
|
options2,
|
|
186031
186842
|
fsWatchBroadcast.bind(null, fullPath, KEY_LISTENERS),
|
|
186032
186843
|
errHandler,
|
|
@@ -186041,7 +186852,7 @@ var setFsWatchListener = (path26, fullPath, options2, handlers) => {
|
|
|
186041
186852
|
cont.watcherUnusable = true;
|
|
186042
186853
|
if (isWindows && error.code === "EPERM") {
|
|
186043
186854
|
try {
|
|
186044
|
-
const fd = await open2(
|
|
186855
|
+
const fd = await open2(path28, "r");
|
|
186045
186856
|
await fd.close();
|
|
186046
186857
|
broadcastErr(error);
|
|
186047
186858
|
} catch (err) {
|
|
@@ -186072,7 +186883,7 @@ var setFsWatchListener = (path26, fullPath, options2, handlers) => {
|
|
|
186072
186883
|
};
|
|
186073
186884
|
};
|
|
186074
186885
|
var FsWatchFileInstances = /* @__PURE__ */ new Map();
|
|
186075
|
-
var setFsWatchFileListener = (
|
|
186886
|
+
var setFsWatchFileListener = (path28, fullPath, options2, handlers) => {
|
|
186076
186887
|
const { listener, rawEmitter } = handlers;
|
|
186077
186888
|
let cont = FsWatchFileInstances.get(fullPath);
|
|
186078
186889
|
const copts = cont && cont.options;
|
|
@@ -186094,7 +186905,7 @@ var setFsWatchFileListener = (path26, fullPath, options2, handlers) => {
|
|
|
186094
186905
|
});
|
|
186095
186906
|
const currmtime = curr.mtimeMs;
|
|
186096
186907
|
if (curr.size !== prev.size || currmtime > prev.mtimeMs || currmtime === 0) {
|
|
186097
|
-
foreach(cont.listeners, (listener2) => listener2(
|
|
186908
|
+
foreach(cont.listeners, (listener2) => listener2(path28, curr));
|
|
186098
186909
|
}
|
|
186099
186910
|
})
|
|
186100
186911
|
};
|
|
@@ -186124,13 +186935,13 @@ var NodeFsHandler = class {
|
|
|
186124
186935
|
* @param listener on fs change
|
|
186125
186936
|
* @returns closer for the watcher instance
|
|
186126
186937
|
*/
|
|
186127
|
-
_watchWithNodeFs(
|
|
186938
|
+
_watchWithNodeFs(path28, listener) {
|
|
186128
186939
|
const opts = this.fsw.options;
|
|
186129
|
-
const directory = sp.dirname(
|
|
186130
|
-
const basename6 = sp.basename(
|
|
186940
|
+
const directory = sp.dirname(path28);
|
|
186941
|
+
const basename6 = sp.basename(path28);
|
|
186131
186942
|
const parent = this.fsw._getWatchedDir(directory);
|
|
186132
186943
|
parent.add(basename6);
|
|
186133
|
-
const absolutePath = sp.resolve(
|
|
186944
|
+
const absolutePath = sp.resolve(path28);
|
|
186134
186945
|
const options2 = {
|
|
186135
186946
|
persistent: opts.persistent
|
|
186136
186947
|
};
|
|
@@ -186140,12 +186951,12 @@ var NodeFsHandler = class {
|
|
|
186140
186951
|
if (opts.usePolling) {
|
|
186141
186952
|
const enableBin = opts.interval !== opts.binaryInterval;
|
|
186142
186953
|
options2.interval = enableBin && isBinaryPath(basename6) ? opts.binaryInterval : opts.interval;
|
|
186143
|
-
closer = setFsWatchFileListener(
|
|
186954
|
+
closer = setFsWatchFileListener(path28, absolutePath, options2, {
|
|
186144
186955
|
listener,
|
|
186145
186956
|
rawEmitter: this.fsw._emitRaw
|
|
186146
186957
|
});
|
|
186147
186958
|
} else {
|
|
186148
|
-
closer = setFsWatchListener(
|
|
186959
|
+
closer = setFsWatchListener(path28, absolutePath, options2, {
|
|
186149
186960
|
listener,
|
|
186150
186961
|
errHandler: this._boundHandleError,
|
|
186151
186962
|
rawEmitter: this.fsw._emitRaw
|
|
@@ -186161,13 +186972,13 @@ var NodeFsHandler = class {
|
|
|
186161
186972
|
if (this.fsw.closed) {
|
|
186162
186973
|
return;
|
|
186163
186974
|
}
|
|
186164
|
-
const
|
|
186975
|
+
const dirname9 = sp.dirname(file);
|
|
186165
186976
|
const basename6 = sp.basename(file);
|
|
186166
|
-
const parent = this.fsw._getWatchedDir(
|
|
186977
|
+
const parent = this.fsw._getWatchedDir(dirname9);
|
|
186167
186978
|
let prevStats = stats;
|
|
186168
186979
|
if (parent.has(basename6))
|
|
186169
186980
|
return;
|
|
186170
|
-
const listener = async (
|
|
186981
|
+
const listener = async (path28, newStats) => {
|
|
186171
186982
|
if (!this.fsw._throttle(THROTTLE_MODE_WATCH, file, 5))
|
|
186172
186983
|
return;
|
|
186173
186984
|
if (!newStats || newStats.mtimeMs === 0) {
|
|
@@ -186181,16 +186992,16 @@ var NodeFsHandler = class {
|
|
|
186181
186992
|
this.fsw._emit(EV.CHANGE, file, newStats2);
|
|
186182
186993
|
}
|
|
186183
186994
|
if ((isMacos || isLinux || isFreeBSD) && prevStats.ino !== newStats2.ino) {
|
|
186184
|
-
this.fsw._closeFile(
|
|
186995
|
+
this.fsw._closeFile(path28);
|
|
186185
186996
|
prevStats = newStats2;
|
|
186186
186997
|
const closer2 = this._watchWithNodeFs(file, listener);
|
|
186187
186998
|
if (closer2)
|
|
186188
|
-
this.fsw._addPathCloser(
|
|
186999
|
+
this.fsw._addPathCloser(path28, closer2);
|
|
186189
187000
|
} else {
|
|
186190
187001
|
prevStats = newStats2;
|
|
186191
187002
|
}
|
|
186192
187003
|
} catch (error) {
|
|
186193
|
-
this.fsw._remove(
|
|
187004
|
+
this.fsw._remove(dirname9, basename6);
|
|
186194
187005
|
}
|
|
186195
187006
|
} else if (parent.has(basename6)) {
|
|
186196
187007
|
const at = newStats.atimeMs;
|
|
@@ -186217,7 +187028,7 @@ var NodeFsHandler = class {
|
|
|
186217
187028
|
* @param item basename of this item
|
|
186218
187029
|
* @returns true if no more processing is needed for this entry.
|
|
186219
187030
|
*/
|
|
186220
|
-
async _handleSymlink(entry, directory,
|
|
187031
|
+
async _handleSymlink(entry, directory, path28, item) {
|
|
186221
187032
|
if (this.fsw.closed) {
|
|
186222
187033
|
return;
|
|
186223
187034
|
}
|
|
@@ -186227,7 +187038,7 @@ var NodeFsHandler = class {
|
|
|
186227
187038
|
this.fsw._incrReadyCount();
|
|
186228
187039
|
let linkPath;
|
|
186229
187040
|
try {
|
|
186230
|
-
linkPath = await fsrealpath(
|
|
187041
|
+
linkPath = await fsrealpath(path28);
|
|
186231
187042
|
} catch (e) {
|
|
186232
187043
|
this.fsw._emitReady();
|
|
186233
187044
|
return true;
|
|
@@ -186237,12 +187048,12 @@ var NodeFsHandler = class {
|
|
|
186237
187048
|
if (dir.has(item)) {
|
|
186238
187049
|
if (this.fsw._symlinkPaths.get(full) !== linkPath) {
|
|
186239
187050
|
this.fsw._symlinkPaths.set(full, linkPath);
|
|
186240
|
-
this.fsw._emit(EV.CHANGE,
|
|
187051
|
+
this.fsw._emit(EV.CHANGE, path28, entry.stats);
|
|
186241
187052
|
}
|
|
186242
187053
|
} else {
|
|
186243
187054
|
dir.add(item);
|
|
186244
187055
|
this.fsw._symlinkPaths.set(full, linkPath);
|
|
186245
|
-
this.fsw._emit(EV.ADD,
|
|
187056
|
+
this.fsw._emit(EV.ADD, path28, entry.stats);
|
|
186246
187057
|
}
|
|
186247
187058
|
this.fsw._emitReady();
|
|
186248
187059
|
return true;
|
|
@@ -186272,9 +187083,9 @@ var NodeFsHandler = class {
|
|
|
186272
187083
|
return;
|
|
186273
187084
|
}
|
|
186274
187085
|
const item = entry.path;
|
|
186275
|
-
let
|
|
187086
|
+
let path28 = sp.join(directory, item);
|
|
186276
187087
|
current.add(item);
|
|
186277
|
-
if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory,
|
|
187088
|
+
if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory, path28, item)) {
|
|
186278
187089
|
return;
|
|
186279
187090
|
}
|
|
186280
187091
|
if (this.fsw.closed) {
|
|
@@ -186283,8 +187094,8 @@ var NodeFsHandler = class {
|
|
|
186283
187094
|
}
|
|
186284
187095
|
if (item === target || !target && !previous.has(item)) {
|
|
186285
187096
|
this.fsw._incrReadyCount();
|
|
186286
|
-
|
|
186287
|
-
this._addToNodeFs(
|
|
187097
|
+
path28 = sp.join(dir, sp.relative(dir, path28));
|
|
187098
|
+
this._addToNodeFs(path28, initialAdd, wh, depth + 1);
|
|
186288
187099
|
}
|
|
186289
187100
|
}).on(EV.ERROR, this._boundHandleError);
|
|
186290
187101
|
return new Promise((resolve10, reject) => {
|
|
@@ -186353,13 +187164,13 @@ var NodeFsHandler = class {
|
|
|
186353
187164
|
* @param depth Child path actually targeted for watch
|
|
186354
187165
|
* @param target Child path actually targeted for watch
|
|
186355
187166
|
*/
|
|
186356
|
-
async _addToNodeFs(
|
|
187167
|
+
async _addToNodeFs(path28, initialAdd, priorWh, depth, target) {
|
|
186357
187168
|
const ready = this.fsw._emitReady;
|
|
186358
|
-
if (this.fsw._isIgnored(
|
|
187169
|
+
if (this.fsw._isIgnored(path28) || this.fsw.closed) {
|
|
186359
187170
|
ready();
|
|
186360
187171
|
return false;
|
|
186361
187172
|
}
|
|
186362
|
-
const wh = this.fsw._getWatchHelpers(
|
|
187173
|
+
const wh = this.fsw._getWatchHelpers(path28);
|
|
186363
187174
|
if (priorWh) {
|
|
186364
187175
|
wh.filterPath = (entry) => priorWh.filterPath(entry);
|
|
186365
187176
|
wh.filterDir = (entry) => priorWh.filterDir(entry);
|
|
@@ -186375,8 +187186,8 @@ var NodeFsHandler = class {
|
|
|
186375
187186
|
const follow = this.fsw.options.followSymlinks;
|
|
186376
187187
|
let closer;
|
|
186377
187188
|
if (stats.isDirectory()) {
|
|
186378
|
-
const absPath = sp.resolve(
|
|
186379
|
-
const targetPath = follow ? await fsrealpath(
|
|
187189
|
+
const absPath = sp.resolve(path28);
|
|
187190
|
+
const targetPath = follow ? await fsrealpath(path28) : path28;
|
|
186380
187191
|
if (this.fsw.closed)
|
|
186381
187192
|
return;
|
|
186382
187193
|
closer = await this._handleDir(wh.watchPath, stats, initialAdd, depth, target, wh, targetPath);
|
|
@@ -186386,29 +187197,29 @@ var NodeFsHandler = class {
|
|
|
186386
187197
|
this.fsw._symlinkPaths.set(absPath, targetPath);
|
|
186387
187198
|
}
|
|
186388
187199
|
} else if (stats.isSymbolicLink()) {
|
|
186389
|
-
const targetPath = follow ? await fsrealpath(
|
|
187200
|
+
const targetPath = follow ? await fsrealpath(path28) : path28;
|
|
186390
187201
|
if (this.fsw.closed)
|
|
186391
187202
|
return;
|
|
186392
187203
|
const parent = sp.dirname(wh.watchPath);
|
|
186393
187204
|
this.fsw._getWatchedDir(parent).add(wh.watchPath);
|
|
186394
187205
|
this.fsw._emit(EV.ADD, wh.watchPath, stats);
|
|
186395
|
-
closer = await this._handleDir(parent, stats, initialAdd, depth,
|
|
187206
|
+
closer = await this._handleDir(parent, stats, initialAdd, depth, path28, wh, targetPath);
|
|
186396
187207
|
if (this.fsw.closed)
|
|
186397
187208
|
return;
|
|
186398
187209
|
if (targetPath !== void 0) {
|
|
186399
|
-
this.fsw._symlinkPaths.set(sp.resolve(
|
|
187210
|
+
this.fsw._symlinkPaths.set(sp.resolve(path28), targetPath);
|
|
186400
187211
|
}
|
|
186401
187212
|
} else {
|
|
186402
187213
|
closer = this._handleFile(wh.watchPath, stats, initialAdd);
|
|
186403
187214
|
}
|
|
186404
187215
|
ready();
|
|
186405
187216
|
if (closer)
|
|
186406
|
-
this.fsw._addPathCloser(
|
|
187217
|
+
this.fsw._addPathCloser(path28, closer);
|
|
186407
187218
|
return false;
|
|
186408
187219
|
} catch (error) {
|
|
186409
187220
|
if (this.fsw._handleError(error)) {
|
|
186410
187221
|
ready();
|
|
186411
|
-
return
|
|
187222
|
+
return path28;
|
|
186412
187223
|
}
|
|
186413
187224
|
}
|
|
186414
187225
|
}
|
|
@@ -186451,24 +187262,24 @@ function createPattern(matcher) {
|
|
|
186451
187262
|
}
|
|
186452
187263
|
return () => false;
|
|
186453
187264
|
}
|
|
186454
|
-
function normalizePath(
|
|
186455
|
-
if (typeof
|
|
187265
|
+
function normalizePath(path28) {
|
|
187266
|
+
if (typeof path28 !== "string")
|
|
186456
187267
|
throw new Error("string expected");
|
|
186457
|
-
|
|
186458
|
-
|
|
187268
|
+
path28 = sp2.normalize(path28);
|
|
187269
|
+
path28 = path28.replace(/\\/g, "/");
|
|
186459
187270
|
let prepend = false;
|
|
186460
|
-
if (
|
|
187271
|
+
if (path28.startsWith("//"))
|
|
186461
187272
|
prepend = true;
|
|
186462
|
-
|
|
187273
|
+
path28 = path28.replace(DOUBLE_SLASH_RE, "/");
|
|
186463
187274
|
if (prepend)
|
|
186464
|
-
|
|
186465
|
-
return
|
|
187275
|
+
path28 = "/" + path28;
|
|
187276
|
+
return path28;
|
|
186466
187277
|
}
|
|
186467
187278
|
function matchPatterns(patterns, testString, stats) {
|
|
186468
|
-
const
|
|
187279
|
+
const path28 = normalizePath(testString);
|
|
186469
187280
|
for (let index = 0; index < patterns.length; index++) {
|
|
186470
187281
|
const pattern = patterns[index];
|
|
186471
|
-
if (pattern(
|
|
187282
|
+
if (pattern(path28, stats)) {
|
|
186472
187283
|
return true;
|
|
186473
187284
|
}
|
|
186474
187285
|
}
|
|
@@ -186506,19 +187317,19 @@ var toUnix = (string) => {
|
|
|
186506
187317
|
}
|
|
186507
187318
|
return str;
|
|
186508
187319
|
};
|
|
186509
|
-
var normalizePathToUnix = (
|
|
186510
|
-
var normalizeIgnored = (cwd = "") => (
|
|
186511
|
-
if (typeof
|
|
186512
|
-
return normalizePathToUnix(sp2.isAbsolute(
|
|
187320
|
+
var normalizePathToUnix = (path28) => toUnix(sp2.normalize(toUnix(path28)));
|
|
187321
|
+
var normalizeIgnored = (cwd = "") => (path28) => {
|
|
187322
|
+
if (typeof path28 === "string") {
|
|
187323
|
+
return normalizePathToUnix(sp2.isAbsolute(path28) ? path28 : sp2.join(cwd, path28));
|
|
186513
187324
|
} else {
|
|
186514
|
-
return
|
|
187325
|
+
return path28;
|
|
186515
187326
|
}
|
|
186516
187327
|
};
|
|
186517
|
-
var getAbsolutePath = (
|
|
186518
|
-
if (sp2.isAbsolute(
|
|
186519
|
-
return
|
|
187328
|
+
var getAbsolutePath = (path28, cwd) => {
|
|
187329
|
+
if (sp2.isAbsolute(path28)) {
|
|
187330
|
+
return path28;
|
|
186520
187331
|
}
|
|
186521
|
-
return sp2.join(cwd,
|
|
187332
|
+
return sp2.join(cwd, path28);
|
|
186522
187333
|
};
|
|
186523
187334
|
var EMPTY_SET = Object.freeze(/* @__PURE__ */ new Set());
|
|
186524
187335
|
var DirEntry = class {
|
|
@@ -186583,10 +187394,10 @@ var WatchHelper = class {
|
|
|
186583
187394
|
dirParts;
|
|
186584
187395
|
followSymlinks;
|
|
186585
187396
|
statMethod;
|
|
186586
|
-
constructor(
|
|
187397
|
+
constructor(path28, follow, fsw) {
|
|
186587
187398
|
this.fsw = fsw;
|
|
186588
|
-
const watchPath =
|
|
186589
|
-
this.path =
|
|
187399
|
+
const watchPath = path28;
|
|
187400
|
+
this.path = path28 = path28.replace(REPLACER_RE, "");
|
|
186590
187401
|
this.watchPath = watchPath;
|
|
186591
187402
|
this.fullWatchPath = sp2.resolve(watchPath);
|
|
186592
187403
|
this.dirParts = [];
|
|
@@ -186726,20 +187537,20 @@ var FSWatcher = class extends EventEmitter {
|
|
|
186726
187537
|
this._closePromise = void 0;
|
|
186727
187538
|
let paths = unifyPaths(paths_);
|
|
186728
187539
|
if (cwd) {
|
|
186729
|
-
paths = paths.map((
|
|
186730
|
-
const absPath = getAbsolutePath(
|
|
187540
|
+
paths = paths.map((path28) => {
|
|
187541
|
+
const absPath = getAbsolutePath(path28, cwd);
|
|
186731
187542
|
return absPath;
|
|
186732
187543
|
});
|
|
186733
187544
|
}
|
|
186734
|
-
paths.forEach((
|
|
186735
|
-
this._removeIgnoredPath(
|
|
187545
|
+
paths.forEach((path28) => {
|
|
187546
|
+
this._removeIgnoredPath(path28);
|
|
186736
187547
|
});
|
|
186737
187548
|
this._userIgnored = void 0;
|
|
186738
187549
|
if (!this._readyCount)
|
|
186739
187550
|
this._readyCount = 0;
|
|
186740
187551
|
this._readyCount += paths.length;
|
|
186741
|
-
Promise.all(paths.map(async (
|
|
186742
|
-
const res = await this._nodeFsHandler._addToNodeFs(
|
|
187552
|
+
Promise.all(paths.map(async (path28) => {
|
|
187553
|
+
const res = await this._nodeFsHandler._addToNodeFs(path28, !_internal, void 0, 0, _origAdd);
|
|
186743
187554
|
if (res)
|
|
186744
187555
|
this._emitReady();
|
|
186745
187556
|
return res;
|
|
@@ -186761,17 +187572,17 @@ var FSWatcher = class extends EventEmitter {
|
|
|
186761
187572
|
return this;
|
|
186762
187573
|
const paths = unifyPaths(paths_);
|
|
186763
187574
|
const { cwd } = this.options;
|
|
186764
|
-
paths.forEach((
|
|
186765
|
-
if (!sp2.isAbsolute(
|
|
187575
|
+
paths.forEach((path28) => {
|
|
187576
|
+
if (!sp2.isAbsolute(path28) && !this._closers.has(path28)) {
|
|
186766
187577
|
if (cwd)
|
|
186767
|
-
|
|
186768
|
-
|
|
187578
|
+
path28 = sp2.join(cwd, path28);
|
|
187579
|
+
path28 = sp2.resolve(path28);
|
|
186769
187580
|
}
|
|
186770
|
-
this._closePath(
|
|
186771
|
-
this._addIgnoredPath(
|
|
186772
|
-
if (this._watched.has(
|
|
187581
|
+
this._closePath(path28);
|
|
187582
|
+
this._addIgnoredPath(path28);
|
|
187583
|
+
if (this._watched.has(path28)) {
|
|
186773
187584
|
this._addIgnoredPath({
|
|
186774
|
-
path:
|
|
187585
|
+
path: path28,
|
|
186775
187586
|
recursive: true
|
|
186776
187587
|
});
|
|
186777
187588
|
}
|
|
@@ -186835,38 +187646,38 @@ var FSWatcher = class extends EventEmitter {
|
|
|
186835
187646
|
* @param stats arguments to be passed with event
|
|
186836
187647
|
* @returns the error if defined, otherwise the value of the FSWatcher instance's `closed` flag
|
|
186837
187648
|
*/
|
|
186838
|
-
async _emit(event,
|
|
187649
|
+
async _emit(event, path28, stats) {
|
|
186839
187650
|
if (this.closed)
|
|
186840
187651
|
return;
|
|
186841
187652
|
const opts = this.options;
|
|
186842
187653
|
if (isWindows)
|
|
186843
|
-
|
|
187654
|
+
path28 = sp2.normalize(path28);
|
|
186844
187655
|
if (opts.cwd)
|
|
186845
|
-
|
|
186846
|
-
const args = [
|
|
187656
|
+
path28 = sp2.relative(opts.cwd, path28);
|
|
187657
|
+
const args = [path28];
|
|
186847
187658
|
if (stats != null)
|
|
186848
187659
|
args.push(stats);
|
|
186849
187660
|
const awf = opts.awaitWriteFinish;
|
|
186850
187661
|
let pw;
|
|
186851
|
-
if (awf && (pw = this._pendingWrites.get(
|
|
187662
|
+
if (awf && (pw = this._pendingWrites.get(path28))) {
|
|
186852
187663
|
pw.lastChange = /* @__PURE__ */ new Date();
|
|
186853
187664
|
return this;
|
|
186854
187665
|
}
|
|
186855
187666
|
if (opts.atomic) {
|
|
186856
187667
|
if (event === EVENTS.UNLINK) {
|
|
186857
|
-
this._pendingUnlinks.set(
|
|
187668
|
+
this._pendingUnlinks.set(path28, [event, ...args]);
|
|
186858
187669
|
setTimeout(() => {
|
|
186859
|
-
this._pendingUnlinks.forEach((entry,
|
|
187670
|
+
this._pendingUnlinks.forEach((entry, path29) => {
|
|
186860
187671
|
this.emit(...entry);
|
|
186861
187672
|
this.emit(EVENTS.ALL, ...entry);
|
|
186862
|
-
this._pendingUnlinks.delete(
|
|
187673
|
+
this._pendingUnlinks.delete(path29);
|
|
186863
187674
|
});
|
|
186864
187675
|
}, typeof opts.atomic === "number" ? opts.atomic : 100);
|
|
186865
187676
|
return this;
|
|
186866
187677
|
}
|
|
186867
|
-
if (event === EVENTS.ADD && this._pendingUnlinks.has(
|
|
187678
|
+
if (event === EVENTS.ADD && this._pendingUnlinks.has(path28)) {
|
|
186868
187679
|
event = EVENTS.CHANGE;
|
|
186869
|
-
this._pendingUnlinks.delete(
|
|
187680
|
+
this._pendingUnlinks.delete(path28);
|
|
186870
187681
|
}
|
|
186871
187682
|
}
|
|
186872
187683
|
if (awf && (event === EVENTS.ADD || event === EVENTS.CHANGE) && this._readyEmitted) {
|
|
@@ -186884,16 +187695,16 @@ var FSWatcher = class extends EventEmitter {
|
|
|
186884
187695
|
this.emitWithAll(event, args);
|
|
186885
187696
|
}
|
|
186886
187697
|
};
|
|
186887
|
-
this._awaitWriteFinish(
|
|
187698
|
+
this._awaitWriteFinish(path28, awf.stabilityThreshold, event, awfEmit);
|
|
186888
187699
|
return this;
|
|
186889
187700
|
}
|
|
186890
187701
|
if (event === EVENTS.CHANGE) {
|
|
186891
|
-
const isThrottled = !this._throttle(EVENTS.CHANGE,
|
|
187702
|
+
const isThrottled = !this._throttle(EVENTS.CHANGE, path28, 50);
|
|
186892
187703
|
if (isThrottled)
|
|
186893
187704
|
return this;
|
|
186894
187705
|
}
|
|
186895
187706
|
if (opts.alwaysStat && stats === void 0 && (event === EVENTS.ADD || event === EVENTS.ADD_DIR || event === EVENTS.CHANGE)) {
|
|
186896
|
-
const fullPath = opts.cwd ? sp2.join(opts.cwd,
|
|
187707
|
+
const fullPath = opts.cwd ? sp2.join(opts.cwd, path28) : path28;
|
|
186897
187708
|
let stats2;
|
|
186898
187709
|
try {
|
|
186899
187710
|
stats2 = await stat3(fullPath);
|
|
@@ -186924,23 +187735,23 @@ var FSWatcher = class extends EventEmitter {
|
|
|
186924
187735
|
* @param timeout duration of time to suppress duplicate actions
|
|
186925
187736
|
* @returns tracking object or false if action should be suppressed
|
|
186926
187737
|
*/
|
|
186927
|
-
_throttle(actionType,
|
|
187738
|
+
_throttle(actionType, path28, timeout) {
|
|
186928
187739
|
if (!this._throttled.has(actionType)) {
|
|
186929
187740
|
this._throttled.set(actionType, /* @__PURE__ */ new Map());
|
|
186930
187741
|
}
|
|
186931
187742
|
const action = this._throttled.get(actionType);
|
|
186932
187743
|
if (!action)
|
|
186933
187744
|
throw new Error("invalid throttle");
|
|
186934
|
-
const actionPath = action.get(
|
|
187745
|
+
const actionPath = action.get(path28);
|
|
186935
187746
|
if (actionPath) {
|
|
186936
187747
|
actionPath.count++;
|
|
186937
187748
|
return false;
|
|
186938
187749
|
}
|
|
186939
187750
|
let timeoutObject;
|
|
186940
187751
|
const clear = () => {
|
|
186941
|
-
const item = action.get(
|
|
187752
|
+
const item = action.get(path28);
|
|
186942
187753
|
const count = item ? item.count : 0;
|
|
186943
|
-
action.delete(
|
|
187754
|
+
action.delete(path28);
|
|
186944
187755
|
clearTimeout(timeoutObject);
|
|
186945
187756
|
if (item)
|
|
186946
187757
|
clearTimeout(item.timeoutObject);
|
|
@@ -186948,7 +187759,7 @@ var FSWatcher = class extends EventEmitter {
|
|
|
186948
187759
|
};
|
|
186949
187760
|
timeoutObject = setTimeout(clear, timeout);
|
|
186950
187761
|
const thr = { timeoutObject, clear, count: 0 };
|
|
186951
|
-
action.set(
|
|
187762
|
+
action.set(path28, thr);
|
|
186952
187763
|
return thr;
|
|
186953
187764
|
}
|
|
186954
187765
|
_incrReadyCount() {
|
|
@@ -186962,44 +187773,44 @@ var FSWatcher = class extends EventEmitter {
|
|
|
186962
187773
|
* @param event
|
|
186963
187774
|
* @param awfEmit Callback to be called when ready for event to be emitted.
|
|
186964
187775
|
*/
|
|
186965
|
-
_awaitWriteFinish(
|
|
187776
|
+
_awaitWriteFinish(path28, threshold, event, awfEmit) {
|
|
186966
187777
|
const awf = this.options.awaitWriteFinish;
|
|
186967
187778
|
if (typeof awf !== "object")
|
|
186968
187779
|
return;
|
|
186969
187780
|
const pollInterval = awf.pollInterval;
|
|
186970
187781
|
let timeoutHandler;
|
|
186971
|
-
let fullPath =
|
|
186972
|
-
if (this.options.cwd && !sp2.isAbsolute(
|
|
186973
|
-
fullPath = sp2.join(this.options.cwd,
|
|
187782
|
+
let fullPath = path28;
|
|
187783
|
+
if (this.options.cwd && !sp2.isAbsolute(path28)) {
|
|
187784
|
+
fullPath = sp2.join(this.options.cwd, path28);
|
|
186974
187785
|
}
|
|
186975
187786
|
const now = /* @__PURE__ */ new Date();
|
|
186976
187787
|
const writes = this._pendingWrites;
|
|
186977
187788
|
function awaitWriteFinishFn(prevStat) {
|
|
186978
187789
|
statcb(fullPath, (err, curStat) => {
|
|
186979
|
-
if (err || !writes.has(
|
|
187790
|
+
if (err || !writes.has(path28)) {
|
|
186980
187791
|
if (err && err.code !== "ENOENT")
|
|
186981
187792
|
awfEmit(err);
|
|
186982
187793
|
return;
|
|
186983
187794
|
}
|
|
186984
187795
|
const now2 = Number(/* @__PURE__ */ new Date());
|
|
186985
187796
|
if (prevStat && curStat.size !== prevStat.size) {
|
|
186986
|
-
writes.get(
|
|
187797
|
+
writes.get(path28).lastChange = now2;
|
|
186987
187798
|
}
|
|
186988
|
-
const pw = writes.get(
|
|
187799
|
+
const pw = writes.get(path28);
|
|
186989
187800
|
const df = now2 - pw.lastChange;
|
|
186990
187801
|
if (df >= threshold) {
|
|
186991
|
-
writes.delete(
|
|
187802
|
+
writes.delete(path28);
|
|
186992
187803
|
awfEmit(void 0, curStat);
|
|
186993
187804
|
} else {
|
|
186994
187805
|
timeoutHandler = setTimeout(awaitWriteFinishFn, pollInterval, curStat);
|
|
186995
187806
|
}
|
|
186996
187807
|
});
|
|
186997
187808
|
}
|
|
186998
|
-
if (!writes.has(
|
|
186999
|
-
writes.set(
|
|
187809
|
+
if (!writes.has(path28)) {
|
|
187810
|
+
writes.set(path28, {
|
|
187000
187811
|
lastChange: now,
|
|
187001
187812
|
cancelWait: () => {
|
|
187002
|
-
writes.delete(
|
|
187813
|
+
writes.delete(path28);
|
|
187003
187814
|
clearTimeout(timeoutHandler);
|
|
187004
187815
|
return event;
|
|
187005
187816
|
}
|
|
@@ -187010,8 +187821,8 @@ var FSWatcher = class extends EventEmitter {
|
|
|
187010
187821
|
/**
|
|
187011
187822
|
* Determines whether user has asked to ignore this path.
|
|
187012
187823
|
*/
|
|
187013
|
-
_isIgnored(
|
|
187014
|
-
if (this.options.atomic && DOT_RE.test(
|
|
187824
|
+
_isIgnored(path28, stats) {
|
|
187825
|
+
if (this.options.atomic && DOT_RE.test(path28))
|
|
187015
187826
|
return true;
|
|
187016
187827
|
if (!this._userIgnored) {
|
|
187017
187828
|
const { cwd } = this.options;
|
|
@@ -187021,17 +187832,17 @@ var FSWatcher = class extends EventEmitter {
|
|
|
187021
187832
|
const list = [...ignoredPaths.map(normalizeIgnored(cwd)), ...ignored];
|
|
187022
187833
|
this._userIgnored = anymatch(list, void 0);
|
|
187023
187834
|
}
|
|
187024
|
-
return this._userIgnored(
|
|
187835
|
+
return this._userIgnored(path28, stats);
|
|
187025
187836
|
}
|
|
187026
|
-
_isntIgnored(
|
|
187027
|
-
return !this._isIgnored(
|
|
187837
|
+
_isntIgnored(path28, stat4) {
|
|
187838
|
+
return !this._isIgnored(path28, stat4);
|
|
187028
187839
|
}
|
|
187029
187840
|
/**
|
|
187030
187841
|
* Provides a set of common helpers and properties relating to symlink handling.
|
|
187031
187842
|
* @param path file or directory pattern being watched
|
|
187032
187843
|
*/
|
|
187033
|
-
_getWatchHelpers(
|
|
187034
|
-
return new WatchHelper(
|
|
187844
|
+
_getWatchHelpers(path28) {
|
|
187845
|
+
return new WatchHelper(path28, this.options.followSymlinks, this);
|
|
187035
187846
|
}
|
|
187036
187847
|
// Directory helpers
|
|
187037
187848
|
// -----------------
|
|
@@ -187063,63 +187874,63 @@ var FSWatcher = class extends EventEmitter {
|
|
|
187063
187874
|
* @param item base path of item/directory
|
|
187064
187875
|
*/
|
|
187065
187876
|
_remove(directory, item, isDirectory) {
|
|
187066
|
-
const
|
|
187067
|
-
const fullPath = sp2.resolve(
|
|
187068
|
-
isDirectory = isDirectory != null ? isDirectory : this._watched.has(
|
|
187069
|
-
if (!this._throttle("remove",
|
|
187877
|
+
const path28 = sp2.join(directory, item);
|
|
187878
|
+
const fullPath = sp2.resolve(path28);
|
|
187879
|
+
isDirectory = isDirectory != null ? isDirectory : this._watched.has(path28) || this._watched.has(fullPath);
|
|
187880
|
+
if (!this._throttle("remove", path28, 100))
|
|
187070
187881
|
return;
|
|
187071
187882
|
if (!isDirectory && this._watched.size === 1) {
|
|
187072
187883
|
this.add(directory, item, true);
|
|
187073
187884
|
}
|
|
187074
|
-
const wp = this._getWatchedDir(
|
|
187885
|
+
const wp = this._getWatchedDir(path28);
|
|
187075
187886
|
const nestedDirectoryChildren = wp.getChildren();
|
|
187076
|
-
nestedDirectoryChildren.forEach((nested) => this._remove(
|
|
187887
|
+
nestedDirectoryChildren.forEach((nested) => this._remove(path28, nested));
|
|
187077
187888
|
const parent = this._getWatchedDir(directory);
|
|
187078
187889
|
const wasTracked = parent.has(item);
|
|
187079
187890
|
parent.remove(item);
|
|
187080
187891
|
if (this._symlinkPaths.has(fullPath)) {
|
|
187081
187892
|
this._symlinkPaths.delete(fullPath);
|
|
187082
187893
|
}
|
|
187083
|
-
let relPath =
|
|
187894
|
+
let relPath = path28;
|
|
187084
187895
|
if (this.options.cwd)
|
|
187085
|
-
relPath = sp2.relative(this.options.cwd,
|
|
187896
|
+
relPath = sp2.relative(this.options.cwd, path28);
|
|
187086
187897
|
if (this.options.awaitWriteFinish && this._pendingWrites.has(relPath)) {
|
|
187087
187898
|
const event = this._pendingWrites.get(relPath).cancelWait();
|
|
187088
187899
|
if (event === EVENTS.ADD)
|
|
187089
187900
|
return;
|
|
187090
187901
|
}
|
|
187091
|
-
this._watched.delete(
|
|
187902
|
+
this._watched.delete(path28);
|
|
187092
187903
|
this._watched.delete(fullPath);
|
|
187093
187904
|
const eventName = isDirectory ? EVENTS.UNLINK_DIR : EVENTS.UNLINK;
|
|
187094
|
-
if (wasTracked && !this._isIgnored(
|
|
187095
|
-
this._emit(eventName,
|
|
187096
|
-
this._closePath(
|
|
187905
|
+
if (wasTracked && !this._isIgnored(path28))
|
|
187906
|
+
this._emit(eventName, path28);
|
|
187907
|
+
this._closePath(path28);
|
|
187097
187908
|
}
|
|
187098
187909
|
/**
|
|
187099
187910
|
* Closes all watchers for a path
|
|
187100
187911
|
*/
|
|
187101
|
-
_closePath(
|
|
187102
|
-
this._closeFile(
|
|
187103
|
-
const dir = sp2.dirname(
|
|
187104
|
-
this._getWatchedDir(dir).remove(sp2.basename(
|
|
187912
|
+
_closePath(path28) {
|
|
187913
|
+
this._closeFile(path28);
|
|
187914
|
+
const dir = sp2.dirname(path28);
|
|
187915
|
+
this._getWatchedDir(dir).remove(sp2.basename(path28));
|
|
187105
187916
|
}
|
|
187106
187917
|
/**
|
|
187107
187918
|
* Closes only file-specific watchers
|
|
187108
187919
|
*/
|
|
187109
|
-
_closeFile(
|
|
187110
|
-
const closers = this._closers.get(
|
|
187920
|
+
_closeFile(path28) {
|
|
187921
|
+
const closers = this._closers.get(path28);
|
|
187111
187922
|
if (!closers)
|
|
187112
187923
|
return;
|
|
187113
187924
|
closers.forEach((closer) => closer());
|
|
187114
|
-
this._closers.delete(
|
|
187925
|
+
this._closers.delete(path28);
|
|
187115
187926
|
}
|
|
187116
|
-
_addPathCloser(
|
|
187927
|
+
_addPathCloser(path28, closer) {
|
|
187117
187928
|
if (!closer)
|
|
187118
187929
|
return;
|
|
187119
|
-
let list = this._closers.get(
|
|
187930
|
+
let list = this._closers.get(path28);
|
|
187120
187931
|
if (!list) {
|
|
187121
187932
|
list = [];
|
|
187122
|
-
this._closers.set(
|
|
187933
|
+
this._closers.set(path28, list);
|
|
187123
187934
|
}
|
|
187124
187935
|
list.push(closer);
|
|
187125
187936
|
}
|
|
@@ -187168,8 +187979,8 @@ var PortAllocator = class {
|
|
|
187168
187979
|
};
|
|
187169
187980
|
|
|
187170
187981
|
// src/lib/dev/stable-port-allocator.ts
|
|
187171
|
-
import * as
|
|
187172
|
-
import * as
|
|
187982
|
+
import * as fs14 from "fs";
|
|
187983
|
+
import * as path10 from "path";
|
|
187173
187984
|
var PORT_RANGE_START2 = 4e4;
|
|
187174
187985
|
var PORT_RANGE_END2 = 49999;
|
|
187175
187986
|
var StablePortAllocator = class {
|
|
@@ -187178,16 +187989,16 @@ var StablePortAllocator = class {
|
|
|
187178
187989
|
savedPorts = {};
|
|
187179
187990
|
usedPorts = /* @__PURE__ */ new Set();
|
|
187180
187991
|
constructor(projectRoot, key = "default") {
|
|
187181
|
-
this.portsDir =
|
|
187182
|
-
this.portsFilePath =
|
|
187992
|
+
this.portsDir = path10.join(projectRoot, ".specific", "keys", key);
|
|
187993
|
+
this.portsFilePath = path10.join(this.portsDir, "ports.json");
|
|
187183
187994
|
this.loadPorts();
|
|
187184
187995
|
}
|
|
187185
187996
|
loadPorts() {
|
|
187186
|
-
if (!
|
|
187997
|
+
if (!fs14.existsSync(this.portsFilePath)) {
|
|
187187
187998
|
return;
|
|
187188
187999
|
}
|
|
187189
188000
|
try {
|
|
187190
|
-
const content =
|
|
188001
|
+
const content = fs14.readFileSync(this.portsFilePath, "utf-8");
|
|
187191
188002
|
const data = JSON.parse(content);
|
|
187192
188003
|
if (data.version === 1 && data.ports) {
|
|
187193
188004
|
this.savedPorts = data.ports;
|
|
@@ -187200,14 +188011,14 @@ var StablePortAllocator = class {
|
|
|
187200
188011
|
}
|
|
187201
188012
|
}
|
|
187202
188013
|
savePorts() {
|
|
187203
|
-
if (!
|
|
187204
|
-
|
|
188014
|
+
if (!fs14.existsSync(this.portsDir)) {
|
|
188015
|
+
fs14.mkdirSync(this.portsDir, { recursive: true });
|
|
187205
188016
|
}
|
|
187206
188017
|
const data = {
|
|
187207
188018
|
version: 1,
|
|
187208
188019
|
ports: this.savedPorts
|
|
187209
188020
|
};
|
|
187210
|
-
|
|
188021
|
+
fs14.writeFileSync(this.portsFilePath, JSON.stringify(data, null, 2));
|
|
187211
188022
|
}
|
|
187212
188023
|
allocateRandom() {
|
|
187213
188024
|
const rangeSize = PORT_RANGE_END2 - PORT_RANGE_START2 + 1;
|
|
@@ -187234,21 +188045,21 @@ var StablePortAllocator = class {
|
|
|
187234
188045
|
};
|
|
187235
188046
|
|
|
187236
188047
|
// src/lib/dev/database-manager.ts
|
|
187237
|
-
import * as
|
|
187238
|
-
import * as
|
|
188048
|
+
import * as fs15 from "fs";
|
|
188049
|
+
import * as path11 from "path";
|
|
187239
188050
|
import * as net from "net";
|
|
187240
188051
|
import { spawn } from "child_process";
|
|
187241
188052
|
async function startPostgres(pg, port, dataDir, onProgress) {
|
|
187242
188053
|
const binary = await ensureBinary(postgresBinary, void 0, onProgress);
|
|
187243
|
-
const dbDataPath =
|
|
188054
|
+
const dbDataPath = path11.join(process.cwd(), dataDir, pg.name);
|
|
187244
188055
|
const host = "127.0.0.1";
|
|
187245
188056
|
const user = "postgres";
|
|
187246
188057
|
const password = "postgres";
|
|
187247
188058
|
const libraryEnv = getLibraryEnv(binary);
|
|
187248
188059
|
const env2 = { ...process.env, ...libraryEnv };
|
|
187249
|
-
const dataExists =
|
|
188060
|
+
const dataExists = fs15.existsSync(dbDataPath);
|
|
187250
188061
|
if (!dataExists) {
|
|
187251
|
-
|
|
188062
|
+
fs15.mkdirSync(dbDataPath, { recursive: true });
|
|
187252
188063
|
await runCommand(
|
|
187253
188064
|
binary.executables["initdb"],
|
|
187254
188065
|
["-D", dbDataPath, "-U", user, "--auth=trust", "--no-locale", "-E", "UTF8"],
|
|
@@ -187324,9 +188135,9 @@ async function startRedis(redis, port, onProgress) {
|
|
|
187324
188135
|
}
|
|
187325
188136
|
async function startStorage(storage, port, dataDir) {
|
|
187326
188137
|
const S3rver = (await import("s3rver")).default;
|
|
187327
|
-
const storageDataPath =
|
|
187328
|
-
if (!
|
|
187329
|
-
|
|
188138
|
+
const storageDataPath = path11.join(process.cwd(), dataDir, storage.name);
|
|
188139
|
+
if (!fs15.existsSync(storageDataPath)) {
|
|
188140
|
+
fs15.mkdirSync(storageDataPath, { recursive: true });
|
|
187330
188141
|
}
|
|
187331
188142
|
const host = "127.0.0.1";
|
|
187332
188143
|
const accessKey = "S3RVER";
|
|
@@ -187460,7 +188271,7 @@ import { spawn as spawn2 } from "child_process";
|
|
|
187460
188271
|
// src/lib/local/parser.ts
|
|
187461
188272
|
var import_hcl2_json_parser2 = __toESM(require_dist(), 1);
|
|
187462
188273
|
import { readFile, writeFile } from "fs/promises";
|
|
187463
|
-
import { existsSync as
|
|
188274
|
+
import { existsSync as existsSync12 } from "fs";
|
|
187464
188275
|
var { parseToObject: parseToObject2 } = import_hcl2_json_parser2.default;
|
|
187465
188276
|
var LOCAL_FILE = "specific.local";
|
|
187466
188277
|
var HEADER_COMMENT = `# Local secrets and configuration
|
|
@@ -187501,7 +188312,7 @@ async function parseLocalFile(content) {
|
|
|
187501
188312
|
return { secrets, configs };
|
|
187502
188313
|
}
|
|
187503
188314
|
async function loadLocal() {
|
|
187504
|
-
if (!
|
|
188315
|
+
if (!existsSync12(LOCAL_FILE)) {
|
|
187505
188316
|
return { secrets: /* @__PURE__ */ new Map(), configs: /* @__PURE__ */ new Map() };
|
|
187506
188317
|
}
|
|
187507
188318
|
const content = await readFile(LOCAL_FILE, "utf-8");
|
|
@@ -187541,7 +188352,7 @@ ${newLine}
|
|
|
187541
188352
|
}
|
|
187542
188353
|
async function saveLocalSecret(name, value) {
|
|
187543
188354
|
let content = "";
|
|
187544
|
-
if (
|
|
188355
|
+
if (existsSync12(LOCAL_FILE)) {
|
|
187545
188356
|
content = await readFile(LOCAL_FILE, "utf-8");
|
|
187546
188357
|
} else {
|
|
187547
188358
|
content = HEADER_COMMENT;
|
|
@@ -187551,7 +188362,7 @@ async function saveLocalSecret(name, value) {
|
|
|
187551
188362
|
}
|
|
187552
188363
|
async function saveLocalConfig(name, value) {
|
|
187553
188364
|
let content = "";
|
|
187554
|
-
if (
|
|
188365
|
+
if (existsSync12(LOCAL_FILE)) {
|
|
187555
188366
|
content = await readFile(LOCAL_FILE, "utf-8");
|
|
187556
188367
|
} else {
|
|
187557
188368
|
content = HEADER_COMMENT;
|
|
@@ -187600,7 +188411,7 @@ config {
|
|
|
187600
188411
|
this.name = "MissingConfigError";
|
|
187601
188412
|
}
|
|
187602
188413
|
};
|
|
187603
|
-
function resolveEnvValue(value, resources, secrets, configs, servicePort, serviceEndpoints, currentServicePorts, publicUrls) {
|
|
188414
|
+
function resolveEnvValue(value, resources, secrets, configs, servicePort, serviceEndpoints, currentServicePorts, publicUrls, volumePaths) {
|
|
187604
188415
|
if (typeof value === "string") {
|
|
187605
188416
|
return value;
|
|
187606
188417
|
}
|
|
@@ -187615,7 +188426,8 @@ function resolveEnvValue(value, resources, secrets, configs, servicePort, servic
|
|
|
187615
188426
|
servicePort,
|
|
187616
188427
|
serviceEndpoints,
|
|
187617
188428
|
currentServicePorts,
|
|
187618
|
-
publicUrls
|
|
188429
|
+
publicUrls,
|
|
188430
|
+
volumePaths
|
|
187619
188431
|
);
|
|
187620
188432
|
}).join("");
|
|
187621
188433
|
}
|
|
@@ -187762,6 +188574,22 @@ function resolveEnvValue(value, resources, secrets, configs, servicePort, servic
|
|
|
187762
188574
|
throw new Error(`Unknown storage attribute: ${String(value.attribute)}`);
|
|
187763
188575
|
}
|
|
187764
188576
|
}
|
|
188577
|
+
case "temporal": {
|
|
188578
|
+
const temporal = resources.get(value.name);
|
|
188579
|
+
if (!temporal || temporal.type !== "temporal") {
|
|
188580
|
+
throw new Error(`Temporal "${value.name}" not found`);
|
|
188581
|
+
}
|
|
188582
|
+
switch (value.attribute) {
|
|
188583
|
+
case "url":
|
|
188584
|
+
return temporal.url;
|
|
188585
|
+
case "namespace":
|
|
188586
|
+
return value.name;
|
|
188587
|
+
case "api_key":
|
|
188588
|
+
return "";
|
|
188589
|
+
default:
|
|
188590
|
+
throw new Error(`Unknown temporal attribute: ${String(value.attribute)}`);
|
|
188591
|
+
}
|
|
188592
|
+
}
|
|
187765
188593
|
case "config": {
|
|
187766
188594
|
const configValue = configs.get(value.name);
|
|
187767
188595
|
if (configValue === void 0) {
|
|
@@ -187776,13 +188604,24 @@ function resolveEnvValue(value, resources, secrets, configs, servicePort, servic
|
|
|
187776
188604
|
}
|
|
187777
188605
|
return secretValue;
|
|
187778
188606
|
}
|
|
188607
|
+
case "volume": {
|
|
188608
|
+
const volumeRef = value;
|
|
188609
|
+
if (!volumePaths) {
|
|
188610
|
+
throw new Error("Volume reference used but no volume paths provided");
|
|
188611
|
+
}
|
|
188612
|
+
const volumePath = volumePaths.get(volumeRef.volumeName);
|
|
188613
|
+
if (volumePath === void 0) {
|
|
188614
|
+
throw new Error(`Volume "${volumeRef.volumeName}" not found`);
|
|
188615
|
+
}
|
|
188616
|
+
return volumePath;
|
|
188617
|
+
}
|
|
187779
188618
|
case "build":
|
|
187780
188619
|
throw new Error(`Build references cannot be used as env values`);
|
|
187781
188620
|
default:
|
|
187782
188621
|
throw new Error(`Unknown reference type`);
|
|
187783
188622
|
}
|
|
187784
188623
|
}
|
|
187785
|
-
function resolveEnv(env2, resources, secrets, configs, servicePort, serviceEndpoints, currentServicePorts, publicUrls) {
|
|
188624
|
+
function resolveEnv(env2, resources, secrets, configs, servicePort, serviceEndpoints, currentServicePorts, publicUrls, volumePaths) {
|
|
187786
188625
|
if (!env2) {
|
|
187787
188626
|
return {};
|
|
187788
188627
|
}
|
|
@@ -187796,7 +188635,8 @@ function resolveEnv(env2, resources, secrets, configs, servicePort, serviceEndpo
|
|
|
187796
188635
|
servicePort,
|
|
187797
188636
|
serviceEndpoints,
|
|
187798
188637
|
currentServicePorts,
|
|
187799
|
-
publicUrls
|
|
188638
|
+
publicUrls,
|
|
188639
|
+
volumePaths
|
|
187800
188640
|
);
|
|
187801
188641
|
}
|
|
187802
188642
|
return resolved;
|
|
@@ -187811,12 +188651,12 @@ function resolveEnvForExec(env2, resources, secrets, configs) {
|
|
|
187811
188651
|
resolved[key] = value;
|
|
187812
188652
|
continue;
|
|
187813
188653
|
}
|
|
187814
|
-
if (value.type === "port" || value.type === "endpoint" || value.type === "service") {
|
|
188654
|
+
if (value.type === "port" || value.type === "endpoint" || value.type === "service" || value.type === "volume") {
|
|
187815
188655
|
continue;
|
|
187816
188656
|
}
|
|
187817
188657
|
if (value.type === "interpolated") {
|
|
187818
188658
|
const hasSkippableRef = value.parts.some(
|
|
187819
|
-
(part) => part.type === "ref" && (part.ref.type === "port" || part.ref.type === "endpoint" || part.ref.type === "service")
|
|
188659
|
+
(part) => part.type === "ref" && (part.ref.type === "port" || part.ref.type === "endpoint" || part.ref.type === "service" || part.ref.type === "volume")
|
|
187820
188660
|
);
|
|
187821
188661
|
if (hasSkippableRef) {
|
|
187822
188662
|
continue;
|
|
@@ -187830,7 +188670,7 @@ function resolveEnvForExec(env2, resources, secrets, configs) {
|
|
|
187830
188670
|
}
|
|
187831
188671
|
|
|
187832
188672
|
// src/lib/dev/service-runner.ts
|
|
187833
|
-
function startService(service, resources, secrets, configs, endpointPorts, serviceEndpoints, onLog, publicUrls, cwd) {
|
|
188673
|
+
function startService(service, resources, secrets, configs, endpointPorts, serviceEndpoints, onLog, publicUrls, cwd, volumePaths) {
|
|
187834
188674
|
const command = service.dev?.command ?? service.command;
|
|
187835
188675
|
if (!command) {
|
|
187836
188676
|
throw new Error(`Service "${service.name}" has no command`);
|
|
@@ -187848,7 +188688,8 @@ function startService(service, resources, secrets, configs, endpointPorts, servi
|
|
|
187848
188688
|
defaultPort,
|
|
187849
188689
|
serviceEndpoints,
|
|
187850
188690
|
endpointPorts,
|
|
187851
|
-
publicUrls
|
|
188691
|
+
publicUrls,
|
|
188692
|
+
volumePaths
|
|
187852
188693
|
);
|
|
187853
188694
|
const child = spawn2(command, {
|
|
187854
188695
|
shell: true,
|
|
@@ -187915,8 +188756,8 @@ function startService(service, resources, secrets, configs, endpointPorts, servi
|
|
|
187915
188756
|
}
|
|
187916
188757
|
|
|
187917
188758
|
// src/lib/dev/instance-state.ts
|
|
187918
|
-
import * as
|
|
187919
|
-
import * as
|
|
188759
|
+
import * as fs16 from "fs";
|
|
188760
|
+
import * as path12 from "path";
|
|
187920
188761
|
var InstanceStateManager = class {
|
|
187921
188762
|
stateDir;
|
|
187922
188763
|
statePath;
|
|
@@ -187925,16 +188766,16 @@ var InstanceStateManager = class {
|
|
|
187925
188766
|
key;
|
|
187926
188767
|
constructor(projectRoot, key = "default") {
|
|
187927
188768
|
this.key = key;
|
|
187928
|
-
this.stateDir =
|
|
187929
|
-
this.statePath =
|
|
187930
|
-
this.lockPath =
|
|
188769
|
+
this.stateDir = path12.join(projectRoot, ".specific", "keys", key);
|
|
188770
|
+
this.statePath = path12.join(this.stateDir, "state.json");
|
|
188771
|
+
this.lockPath = path12.join(this.stateDir, "state.lock");
|
|
187931
188772
|
}
|
|
187932
188773
|
getKey() {
|
|
187933
188774
|
return this.key;
|
|
187934
188775
|
}
|
|
187935
188776
|
ensureStateDir() {
|
|
187936
|
-
if (!
|
|
187937
|
-
|
|
188777
|
+
if (!fs16.existsSync(this.stateDir)) {
|
|
188778
|
+
fs16.mkdirSync(this.stateDir, { recursive: true });
|
|
187938
188779
|
}
|
|
187939
188780
|
}
|
|
187940
188781
|
isProcessRunning(pid) {
|
|
@@ -187951,15 +188792,15 @@ var InstanceStateManager = class {
|
|
|
187951
188792
|
const startTime = Date.now();
|
|
187952
188793
|
while (Date.now() - startTime < timeoutMs) {
|
|
187953
188794
|
try {
|
|
187954
|
-
const fd =
|
|
188795
|
+
const fd = fs16.openSync(
|
|
187955
188796
|
this.lockPath,
|
|
187956
|
-
|
|
188797
|
+
fs16.constants.O_CREAT | fs16.constants.O_EXCL | fs16.constants.O_WRONLY
|
|
187957
188798
|
);
|
|
187958
|
-
|
|
187959
|
-
|
|
188799
|
+
fs16.writeSync(fd, String(process.pid));
|
|
188800
|
+
fs16.closeSync(fd);
|
|
187960
188801
|
return () => {
|
|
187961
188802
|
try {
|
|
187962
|
-
|
|
188803
|
+
fs16.unlinkSync(this.lockPath);
|
|
187963
188804
|
} catch {
|
|
187964
188805
|
}
|
|
187965
188806
|
};
|
|
@@ -187968,16 +188809,16 @@ var InstanceStateManager = class {
|
|
|
187968
188809
|
if (err.code === "EEXIST") {
|
|
187969
188810
|
try {
|
|
187970
188811
|
const lockPid = parseInt(
|
|
187971
|
-
|
|
188812
|
+
fs16.readFileSync(this.lockPath, "utf-8").trim(),
|
|
187972
188813
|
10
|
|
187973
188814
|
);
|
|
187974
188815
|
if (!this.isProcessRunning(lockPid)) {
|
|
187975
|
-
|
|
188816
|
+
fs16.unlinkSync(this.lockPath);
|
|
187976
188817
|
continue;
|
|
187977
188818
|
}
|
|
187978
188819
|
} catch {
|
|
187979
188820
|
try {
|
|
187980
|
-
|
|
188821
|
+
fs16.unlinkSync(this.lockPath);
|
|
187981
188822
|
} catch {
|
|
187982
188823
|
}
|
|
187983
188824
|
continue;
|
|
@@ -187991,12 +188832,12 @@ var InstanceStateManager = class {
|
|
|
187991
188832
|
throw new Error("Failed to acquire state lock (timeout)");
|
|
187992
188833
|
}
|
|
187993
188834
|
async getExistingInstances() {
|
|
187994
|
-
if (!
|
|
188835
|
+
if (!fs16.existsSync(this.statePath)) {
|
|
187995
188836
|
return null;
|
|
187996
188837
|
}
|
|
187997
188838
|
const releaseLock = await this.acquireLock();
|
|
187998
188839
|
try {
|
|
187999
|
-
const content =
|
|
188840
|
+
const content = fs16.readFileSync(this.statePath, "utf-8");
|
|
188000
188841
|
const state = JSON.parse(content);
|
|
188001
188842
|
if (!this.isProcessRunning(state.owner.pid)) {
|
|
188002
188843
|
return null;
|
|
@@ -188009,21 +188850,21 @@ var InstanceStateManager = class {
|
|
|
188009
188850
|
}
|
|
188010
188851
|
}
|
|
188011
188852
|
async cleanStaleState() {
|
|
188012
|
-
if (!
|
|
188853
|
+
if (!fs16.existsSync(this.statePath)) {
|
|
188013
188854
|
return false;
|
|
188014
188855
|
}
|
|
188015
188856
|
const releaseLock = await this.acquireLock();
|
|
188016
188857
|
try {
|
|
188017
|
-
const content =
|
|
188858
|
+
const content = fs16.readFileSync(this.statePath, "utf-8");
|
|
188018
188859
|
const state = JSON.parse(content);
|
|
188019
188860
|
if (!this.isProcessRunning(state.owner.pid)) {
|
|
188020
|
-
|
|
188861
|
+
fs16.unlinkSync(this.statePath);
|
|
188021
188862
|
return true;
|
|
188022
188863
|
}
|
|
188023
188864
|
return false;
|
|
188024
188865
|
} catch {
|
|
188025
188866
|
try {
|
|
188026
|
-
|
|
188867
|
+
fs16.unlinkSync(this.statePath);
|
|
188027
188868
|
return true;
|
|
188028
188869
|
} catch {
|
|
188029
188870
|
}
|
|
@@ -188035,8 +188876,8 @@ var InstanceStateManager = class {
|
|
|
188035
188876
|
async claimOwnership(command) {
|
|
188036
188877
|
const releaseLock = await this.acquireLock();
|
|
188037
188878
|
try {
|
|
188038
|
-
if (
|
|
188039
|
-
const content =
|
|
188879
|
+
if (fs16.existsSync(this.statePath)) {
|
|
188880
|
+
const content = fs16.readFileSync(this.statePath, "utf-8");
|
|
188040
188881
|
const state2 = JSON.parse(content);
|
|
188041
188882
|
if (this.isProcessRunning(state2.owner.pid)) {
|
|
188042
188883
|
throw new Error(`Instances already owned by PID ${state2.owner.pid}`);
|
|
@@ -188105,8 +188946,8 @@ var InstanceStateManager = class {
|
|
|
188105
188946
|
}
|
|
188106
188947
|
const releaseLock = await this.acquireLock();
|
|
188107
188948
|
try {
|
|
188108
|
-
if (
|
|
188109
|
-
|
|
188949
|
+
if (fs16.existsSync(this.statePath)) {
|
|
188950
|
+
fs16.unlinkSync(this.statePath);
|
|
188110
188951
|
}
|
|
188111
188952
|
this.ownsInstances = false;
|
|
188112
188953
|
} finally {
|
|
@@ -188114,31 +188955,32 @@ var InstanceStateManager = class {
|
|
|
188114
188955
|
}
|
|
188115
188956
|
}
|
|
188116
188957
|
readState() {
|
|
188117
|
-
const content =
|
|
188958
|
+
const content = fs16.readFileSync(this.statePath, "utf-8");
|
|
188118
188959
|
return JSON.parse(content);
|
|
188119
188960
|
}
|
|
188120
188961
|
writeStateAtomic(state) {
|
|
188121
188962
|
this.ensureStateDir();
|
|
188122
188963
|
const tmpPath = this.statePath + ".tmp";
|
|
188123
|
-
|
|
188124
|
-
|
|
188964
|
+
fs16.writeFileSync(tmpPath, JSON.stringify(state, null, 2));
|
|
188965
|
+
fs16.renameSync(tmpPath, this.statePath);
|
|
188125
188966
|
}
|
|
188126
188967
|
};
|
|
188127
188968
|
|
|
188128
188969
|
// src/lib/dev/http-proxy.ts
|
|
188129
188970
|
import * as http from "http";
|
|
188130
188971
|
import * as https from "https";
|
|
188131
|
-
import * as
|
|
188132
|
-
import * as
|
|
188972
|
+
import * as fs17 from "fs";
|
|
188973
|
+
import * as path13 from "path";
|
|
188133
188974
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
188134
188975
|
import httpProxy from "http-proxy";
|
|
188135
|
-
var __dirname3 =
|
|
188136
|
-
var adminDir =
|
|
188976
|
+
var __dirname3 = path13.dirname(fileURLToPath3(import.meta.url));
|
|
188977
|
+
var adminDir = path13.join(__dirname3, "admin");
|
|
188137
188978
|
var HTTP_PORT = 80;
|
|
188138
188979
|
var HTTPS_PORT = 443;
|
|
188139
188980
|
var DOMAIN_SUFFIX = ".local.spcf.app";
|
|
188140
188981
|
var ADMIN_DOMAIN = "local.spcf.app";
|
|
188141
188982
|
var DRIZZLE_GATEWAY_PREFIX = "__drizzle_gateway";
|
|
188983
|
+
var TEMPORAL_UI_PREFIX = "__temporal";
|
|
188142
188984
|
var MIME_TYPES = {
|
|
188143
188985
|
".html": "text/html",
|
|
188144
188986
|
".css": "text/css",
|
|
@@ -188157,6 +188999,7 @@ async function startHttpProxy(services, certificate, getState, instanceKey = "de
|
|
|
188157
188999
|
const serviceMap = /* @__PURE__ */ new Map();
|
|
188158
189000
|
const adminPortMap = /* @__PURE__ */ new Map();
|
|
188159
189001
|
const drizzleGatewayPortMap = /* @__PURE__ */ new Map();
|
|
189002
|
+
const temporalUiPortMap = /* @__PURE__ */ new Map();
|
|
188160
189003
|
const buildMapKey = (serviceName, key) => {
|
|
188161
189004
|
return key === "default" ? serviceName : `${serviceName}.${key}`;
|
|
188162
189005
|
};
|
|
@@ -188167,6 +189010,7 @@ async function startHttpProxy(services, certificate, getState, instanceKey = "de
|
|
|
188167
189010
|
serviceMap.clear();
|
|
188168
189011
|
adminPortMap.clear();
|
|
188169
189012
|
drizzleGatewayPortMap.clear();
|
|
189013
|
+
temporalUiPortMap.clear();
|
|
188170
189014
|
for (const svc of registryServices) {
|
|
188171
189015
|
serviceMap.set(buildMapKey(svc.serviceName, svc.key), svc.port);
|
|
188172
189016
|
}
|
|
@@ -188175,6 +189019,9 @@ async function startHttpProxy(services, certificate, getState, instanceKey = "de
|
|
|
188175
189019
|
if (registration.drizzleGatewayPort !== void 0) {
|
|
188176
189020
|
drizzleGatewayPortMap.set(key, registration.drizzleGatewayPort);
|
|
188177
189021
|
}
|
|
189022
|
+
if (registration.temporalUiPort !== void 0) {
|
|
189023
|
+
temporalUiPortMap.set(key, registration.temporalUiPort);
|
|
189024
|
+
}
|
|
188178
189025
|
}
|
|
188179
189026
|
writeLog("proxy", `Updated service map: ${serviceMap.size} services, ${adminPortMap.size} admin instances, ${drizzleGatewayPortMap.size} drizzle gateways`);
|
|
188180
189027
|
};
|
|
@@ -188188,9 +189035,32 @@ async function startHttpProxy(services, certificate, getState, instanceKey = "de
|
|
|
188188
189035
|
res.end(`<h1>Bad Gateway</h1><p>Service unavailable: ${err.message}</p>`);
|
|
188189
189036
|
}
|
|
188190
189037
|
});
|
|
189038
|
+
proxy.on("proxyRes", (proxyRes, req) => {
|
|
189039
|
+
const host = req.headers?.host || "";
|
|
189040
|
+
if (extractTemporalUiKey(host) !== null || extractDrizzleGatewayKey(host) !== null) {
|
|
189041
|
+
delete proxyRes.headers["x-frame-options"];
|
|
189042
|
+
const csp = proxyRes.headers["content-security-policy"];
|
|
189043
|
+
if (typeof csp === "string" && csp.includes("frame-ancestors")) {
|
|
189044
|
+
proxyRes.headers["content-security-policy"] = csp.split(";").filter((d) => !d.trim().startsWith("frame-ancestors")).join(";");
|
|
189045
|
+
}
|
|
189046
|
+
}
|
|
189047
|
+
});
|
|
188191
189048
|
const handleRequest = (req, res) => {
|
|
188192
189049
|
const host = req.headers.host || "";
|
|
188193
189050
|
const hostname2 = host.split(":")[0];
|
|
189051
|
+
const temporalKey = extractTemporalUiKey(host);
|
|
189052
|
+
if (temporalKey !== null) {
|
|
189053
|
+
const temporalPort = temporalUiPortMap.get(temporalKey);
|
|
189054
|
+
if (temporalPort) {
|
|
189055
|
+
proxy.web(req, res, {
|
|
189056
|
+
target: `http://127.0.0.1:${temporalPort}`
|
|
189057
|
+
});
|
|
189058
|
+
return;
|
|
189059
|
+
}
|
|
189060
|
+
res.writeHead(503, { "Content-Type": "text/html" });
|
|
189061
|
+
res.end("<h1>Workflow Engine</h1><p>No workflow engine running for this instance.</p>");
|
|
189062
|
+
return;
|
|
189063
|
+
}
|
|
188194
189064
|
const drizzleKey = extractDrizzleGatewayKey(host);
|
|
188195
189065
|
if (drizzleKey !== null) {
|
|
188196
189066
|
const drizzlePort = drizzleGatewayPortMap.get(drizzleKey);
|
|
@@ -188235,6 +189105,26 @@ async function startHttpProxy(services, certificate, getState, instanceKey = "de
|
|
|
188235
189105
|
};
|
|
188236
189106
|
const handleUpgrade = (req, socket, head) => {
|
|
188237
189107
|
const host = req.headers.host || "";
|
|
189108
|
+
const temporalKey = extractTemporalUiKey(host);
|
|
189109
|
+
if (temporalKey !== null) {
|
|
189110
|
+
const temporalPort = temporalUiPortMap.get(temporalKey);
|
|
189111
|
+
if (temporalPort) {
|
|
189112
|
+
proxy.ws(req, socket, head, { target: `http://127.0.0.1:${temporalPort}` });
|
|
189113
|
+
return;
|
|
189114
|
+
}
|
|
189115
|
+
socket.end("HTTP/1.1 404 Not Found\r\n\r\n");
|
|
189116
|
+
return;
|
|
189117
|
+
}
|
|
189118
|
+
const drizzleKey = extractDrizzleGatewayKey(host);
|
|
189119
|
+
if (drizzleKey !== null) {
|
|
189120
|
+
const drizzlePort = drizzleGatewayPortMap.get(drizzleKey);
|
|
189121
|
+
if (drizzlePort) {
|
|
189122
|
+
proxy.ws(req, socket, head, { target: `http://127.0.0.1:${drizzlePort}` });
|
|
189123
|
+
return;
|
|
189124
|
+
}
|
|
189125
|
+
socket.end("HTTP/1.1 404 Not Found\r\n\r\n");
|
|
189126
|
+
return;
|
|
189127
|
+
}
|
|
188238
189128
|
const adminKey = extractAdminKey(host);
|
|
188239
189129
|
if (adminKey !== null) {
|
|
188240
189130
|
if (adminPortMap.has(adminKey)) {
|
|
@@ -188370,6 +189260,23 @@ function extractDrizzleGatewayKey(host) {
|
|
|
188370
189260
|
}
|
|
188371
189261
|
return null;
|
|
188372
189262
|
}
|
|
189263
|
+
function extractTemporalUiKey(host) {
|
|
189264
|
+
const hostname2 = host.split(":")[0];
|
|
189265
|
+
if (!hostname2 || !hostname2.endsWith(DOMAIN_SUFFIX)) {
|
|
189266
|
+
return null;
|
|
189267
|
+
}
|
|
189268
|
+
const prefix = hostname2.slice(0, -DOMAIN_SUFFIX.length);
|
|
189269
|
+
if (!prefix) {
|
|
189270
|
+
return null;
|
|
189271
|
+
}
|
|
189272
|
+
const parts = prefix.split(".");
|
|
189273
|
+
if (parts.length === 1 && parts[0] === TEMPORAL_UI_PREFIX) {
|
|
189274
|
+
return "default";
|
|
189275
|
+
} else if (parts.length === 2 && parts[0] === TEMPORAL_UI_PREFIX && parts[1]) {
|
|
189276
|
+
return parts[1];
|
|
189277
|
+
}
|
|
189278
|
+
return null;
|
|
189279
|
+
}
|
|
188373
189280
|
function extractAdminKey(host) {
|
|
188374
189281
|
const hostname2 = host.split(":")[0];
|
|
188375
189282
|
if (!hostname2) {
|
|
@@ -188419,18 +189326,18 @@ function serveStaticFile(res, pathname) {
|
|
|
188419
189326
|
filePath = filePath + "index.html";
|
|
188420
189327
|
}
|
|
188421
189328
|
const relativePath = filePath.startsWith("/") ? filePath.slice(1) : filePath;
|
|
188422
|
-
const fullPath =
|
|
188423
|
-
const resolvedPath =
|
|
188424
|
-
const resolvedAdminDir =
|
|
189329
|
+
const fullPath = path13.join(adminDir, relativePath);
|
|
189330
|
+
const resolvedPath = path13.resolve(fullPath);
|
|
189331
|
+
const resolvedAdminDir = path13.resolve(adminDir);
|
|
188425
189332
|
if (!resolvedPath.startsWith(resolvedAdminDir)) {
|
|
188426
189333
|
res.writeHead(403, { "Content-Type": "text/html" });
|
|
188427
189334
|
res.end("<h1>Forbidden</h1>");
|
|
188428
189335
|
return;
|
|
188429
189336
|
}
|
|
188430
|
-
if (
|
|
188431
|
-
if (
|
|
188432
|
-
const indexPath2 =
|
|
188433
|
-
if (
|
|
189337
|
+
if (fs17.existsSync(resolvedPath)) {
|
|
189338
|
+
if (fs17.statSync(resolvedPath).isDirectory()) {
|
|
189339
|
+
const indexPath2 = path13.join(resolvedPath, "index.html");
|
|
189340
|
+
if (fs17.existsSync(indexPath2)) {
|
|
188434
189341
|
return serveFile(res, indexPath2);
|
|
188435
189342
|
}
|
|
188436
189343
|
} else {
|
|
@@ -188438,28 +189345,28 @@ function serveStaticFile(res, pathname) {
|
|
|
188438
189345
|
}
|
|
188439
189346
|
}
|
|
188440
189347
|
const htmlPath = resolvedPath + ".html";
|
|
188441
|
-
if (
|
|
189348
|
+
if (fs17.existsSync(htmlPath)) {
|
|
188442
189349
|
return serveFile(res, htmlPath);
|
|
188443
189350
|
}
|
|
188444
|
-
const indexPath =
|
|
188445
|
-
if (
|
|
189351
|
+
const indexPath = path13.join(resolvedPath, "index.html");
|
|
189352
|
+
if (fs17.existsSync(indexPath)) {
|
|
188446
189353
|
return serveFile(res, indexPath);
|
|
188447
189354
|
}
|
|
188448
|
-
const notFoundPath =
|
|
188449
|
-
if (
|
|
189355
|
+
const notFoundPath = path13.join(adminDir, "404.html");
|
|
189356
|
+
if (fs17.existsSync(notFoundPath)) {
|
|
188450
189357
|
return serveFileContent(res, notFoundPath, "text/html", 404);
|
|
188451
189358
|
}
|
|
188452
189359
|
res.writeHead(404, { "Content-Type": "text/html" });
|
|
188453
189360
|
res.end("<h1>Not Found</h1>");
|
|
188454
189361
|
}
|
|
188455
189362
|
function serveFile(res, filePath) {
|
|
188456
|
-
const ext =
|
|
189363
|
+
const ext = path13.extname(filePath).toLowerCase();
|
|
188457
189364
|
const contentType = MIME_TYPES[ext] || "application/octet-stream";
|
|
188458
189365
|
serveFileContent(res, filePath, contentType, 200);
|
|
188459
189366
|
}
|
|
188460
189367
|
function serveFileContent(res, filePath, contentType, statusCode = 200) {
|
|
188461
189368
|
try {
|
|
188462
|
-
const content =
|
|
189369
|
+
const content = fs17.readFileSync(filePath);
|
|
188463
189370
|
res.writeHead(statusCode, { "Content-Type": contentType });
|
|
188464
189371
|
res.end(content);
|
|
188465
189372
|
} catch (err) {
|
|
@@ -188519,8 +189426,8 @@ import { spawn as spawn3 } from "child_process";
|
|
|
188519
189426
|
|
|
188520
189427
|
// src/lib/secrets/parser.ts
|
|
188521
189428
|
import { readFile as readFile2, writeFile as writeFile2, mkdir } from "fs/promises";
|
|
188522
|
-
import { existsSync as
|
|
188523
|
-
import * as
|
|
189429
|
+
import { existsSync as existsSync15 } from "fs";
|
|
189430
|
+
import * as path14 from "path";
|
|
188524
189431
|
import * as crypto2 from "crypto";
|
|
188525
189432
|
var GENERATED_SECRETS_FILE = ".specific/generated-secrets.json";
|
|
188526
189433
|
async function loadSecrets() {
|
|
@@ -188537,7 +189444,7 @@ function generateRandomString(length = 64) {
|
|
|
188537
189444
|
return result;
|
|
188538
189445
|
}
|
|
188539
189446
|
async function loadGeneratedSecrets() {
|
|
188540
|
-
if (!
|
|
189447
|
+
if (!existsSync15(GENERATED_SECRETS_FILE)) {
|
|
188541
189448
|
return /* @__PURE__ */ new Map();
|
|
188542
189449
|
}
|
|
188543
189450
|
const content = await readFile2(GENERATED_SECRETS_FILE, "utf-8");
|
|
@@ -188546,13 +189453,13 @@ async function loadGeneratedSecrets() {
|
|
|
188546
189453
|
}
|
|
188547
189454
|
async function saveGeneratedSecret(name, value) {
|
|
188548
189455
|
let secrets = {};
|
|
188549
|
-
if (
|
|
189456
|
+
if (existsSync15(GENERATED_SECRETS_FILE)) {
|
|
188550
189457
|
const content = await readFile2(GENERATED_SECRETS_FILE, "utf-8");
|
|
188551
189458
|
secrets = JSON.parse(content);
|
|
188552
189459
|
}
|
|
188553
189460
|
secrets[name] = value;
|
|
188554
|
-
const dir =
|
|
188555
|
-
if (!
|
|
189461
|
+
const dir = path14.dirname(GENERATED_SECRETS_FILE);
|
|
189462
|
+
if (!existsSync15(dir)) {
|
|
188556
189463
|
await mkdir(dir, { recursive: true });
|
|
188557
189464
|
}
|
|
188558
189465
|
await writeFile2(GENERATED_SECRETS_FILE, JSON.stringify(secrets, null, 2) + "\n");
|
|
@@ -188706,8 +189613,8 @@ function sleep3(ms) {
|
|
|
188706
189613
|
|
|
188707
189614
|
// src/lib/dev/drizzle-gateway-manager.ts
|
|
188708
189615
|
import * as net3 from "net";
|
|
188709
|
-
import * as
|
|
188710
|
-
import * as
|
|
189616
|
+
import * as fs18 from "fs";
|
|
189617
|
+
import * as path15 from "path";
|
|
188711
189618
|
import { spawn as spawn4 } from "child_process";
|
|
188712
189619
|
import { randomUUID } from "crypto";
|
|
188713
189620
|
function generateStoreJson(postgresInstances) {
|
|
@@ -188739,13 +189646,13 @@ async function startDrizzleGateway(postgresInstances, port, configDir, options2)
|
|
|
188739
189646
|
options2?.onProgress
|
|
188740
189647
|
);
|
|
188741
189648
|
const host = "127.0.0.1";
|
|
188742
|
-
const drizzleConfigDir =
|
|
188743
|
-
if (!
|
|
188744
|
-
|
|
189649
|
+
const drizzleConfigDir = path15.join(configDir, "drizzle-gateway");
|
|
189650
|
+
if (!fs18.existsSync(drizzleConfigDir)) {
|
|
189651
|
+
fs18.mkdirSync(drizzleConfigDir, { recursive: true });
|
|
188745
189652
|
}
|
|
188746
189653
|
const storeJson = generateStoreJson(postgresInstances);
|
|
188747
|
-
const storeJsonPath =
|
|
188748
|
-
|
|
189654
|
+
const storeJsonPath = path15.join(drizzleConfigDir, "store.json");
|
|
189655
|
+
fs18.writeFileSync(storeJsonPath, JSON.stringify(storeJson, null, 2));
|
|
188749
189656
|
writeLog("drizzle-gateway", `Starting Drizzle Gateway`);
|
|
188750
189657
|
writeLog("drizzle-gateway", `STORE_PATH: ${drizzleConfigDir}`);
|
|
188751
189658
|
writeLog("drizzle-gateway", `PORT: ${port}`);
|
|
@@ -188847,16 +189754,16 @@ function detectSyncDatabases(config) {
|
|
|
188847
189754
|
}
|
|
188848
189755
|
|
|
188849
189756
|
// src/lib/dev/reshape-watcher.ts
|
|
188850
|
-
import * as
|
|
188851
|
-
import * as
|
|
189757
|
+
import * as fs19 from "fs";
|
|
189758
|
+
import * as path16 from "path";
|
|
188852
189759
|
import { spawnSync } from "child_process";
|
|
188853
189760
|
function getMigrationFiles(dir, log) {
|
|
188854
189761
|
log(`Scanning migrations directory: ${dir}`);
|
|
188855
|
-
if (!
|
|
189762
|
+
if (!fs19.existsSync(dir)) {
|
|
188856
189763
|
log(`Migrations directory does not exist: ${dir}`);
|
|
188857
189764
|
return [];
|
|
188858
189765
|
}
|
|
188859
|
-
const files =
|
|
189766
|
+
const files = fs19.readdirSync(dir);
|
|
188860
189767
|
log(`Found ${files.length} files in directory`);
|
|
188861
189768
|
const tomlFiles = files.filter((f) => f.endsWith(".toml")).sort((a, b) => a.localeCompare(b));
|
|
188862
189769
|
log(`Found ${tomlFiles.length} .toml migration files: ${tomlFiles.join(", ") || "(none)"}`);
|
|
@@ -188906,7 +189813,7 @@ function runReshape(args, databaseUrl, migrationsDir, reshapeBinaryPath, log) {
|
|
|
188906
189813
|
}
|
|
188907
189814
|
function makeReadOnly(filePath, log) {
|
|
188908
189815
|
try {
|
|
188909
|
-
|
|
189816
|
+
fs19.chmodSync(filePath, 292);
|
|
188910
189817
|
log(`Set file permissions to read-only (444): ${filePath}`);
|
|
188911
189818
|
} catch (err) {
|
|
188912
189819
|
const message = err instanceof Error ? err.message : String(err);
|
|
@@ -188967,7 +189874,7 @@ function createReshapeWatcher(options2) {
|
|
|
188967
189874
|
log(`Successfully completed ${currentMigrationFiles.length - 1} migration(s)`);
|
|
188968
189875
|
log(`Making completed migration files read-only...`);
|
|
188969
189876
|
for (let i = 0; i < currentMigrationFiles.length - 1; i++) {
|
|
188970
|
-
const filePath =
|
|
189877
|
+
const filePath = path16.join(migrationsDir, currentMigrationFiles[i]);
|
|
188971
189878
|
makeReadOnly(filePath, log);
|
|
188972
189879
|
}
|
|
188973
189880
|
log(`Starting latest migration "${lastMigrationName}" (will not be completed, allowing iteration)`);
|
|
@@ -188992,9 +189899,9 @@ function createReshapeWatcher(options2) {
|
|
|
188992
189899
|
};
|
|
188993
189900
|
const startWatching = () => {
|
|
188994
189901
|
log(`Starting file watcher for migrations directory...`);
|
|
188995
|
-
if (!
|
|
189902
|
+
if (!fs19.existsSync(migrationsDir)) {
|
|
188996
189903
|
log(`Migrations directory does not exist, creating: ${migrationsDir}`);
|
|
188997
|
-
|
|
189904
|
+
fs19.mkdirSync(migrationsDir, { recursive: true });
|
|
188998
189905
|
}
|
|
188999
189906
|
log(`Watching directory: ${migrationsDir}`);
|
|
189000
189907
|
watcher = chokidar_default.watch(migrationsDir, {
|
|
@@ -189007,7 +189914,7 @@ function createReshapeWatcher(options2) {
|
|
|
189007
189914
|
}
|
|
189008
189915
|
});
|
|
189009
189916
|
watcher.on("change", (filePath) => {
|
|
189010
|
-
const filename =
|
|
189917
|
+
const filename = path16.basename(filePath);
|
|
189011
189918
|
if (!filename.endsWith(".toml")) return;
|
|
189012
189919
|
log(`File change detected: ${filename}`);
|
|
189013
189920
|
log(` Full path: ${filePath}`);
|
|
@@ -189038,7 +189945,7 @@ function createReshapeWatcher(options2) {
|
|
|
189038
189945
|
}
|
|
189039
189946
|
});
|
|
189040
189947
|
watcher.on("add", (filePath) => {
|
|
189041
|
-
const filename =
|
|
189948
|
+
const filename = path16.basename(filePath);
|
|
189042
189949
|
if (!filename.endsWith(".toml")) return;
|
|
189043
189950
|
log(`New file detected: ${filename}`);
|
|
189044
189951
|
log(` Full path: ${filePath}`);
|
|
@@ -189062,7 +189969,7 @@ function createReshapeWatcher(options2) {
|
|
|
189062
189969
|
return;
|
|
189063
189970
|
}
|
|
189064
189971
|
log(`Previous migration completed successfully`);
|
|
189065
|
-
const completedPath =
|
|
189972
|
+
const completedPath = path16.join(migrationsDir, startedMigration);
|
|
189066
189973
|
makeReadOnly(completedPath, log);
|
|
189067
189974
|
} else {
|
|
189068
189975
|
log(`No previous migration was started`);
|
|
@@ -189087,7 +189994,7 @@ function createReshapeWatcher(options2) {
|
|
|
189087
189994
|
onSearchPathChanged(newSearchPath);
|
|
189088
189995
|
});
|
|
189089
189996
|
watcher.on("unlink", (filePath) => {
|
|
189090
|
-
const filename =
|
|
189997
|
+
const filename = path16.basename(filePath);
|
|
189091
189998
|
if (!filename.endsWith(".toml")) return;
|
|
189092
189999
|
log(`File deleted: ${filename}`);
|
|
189093
190000
|
log(` Full path: ${filePath}`);
|
|
@@ -189128,9 +190035,110 @@ function createReshapeWatcher(options2) {
|
|
|
189128
190035
|
};
|
|
189129
190036
|
}
|
|
189130
190037
|
|
|
190038
|
+
// src/lib/dev/temporal-manager.ts
|
|
190039
|
+
import * as fs20 from "fs";
|
|
190040
|
+
import * as path17 from "path";
|
|
190041
|
+
import * as net4 from "net";
|
|
190042
|
+
import { spawn as spawn5 } from "child_process";
|
|
190043
|
+
async function startTemporalDevServer(temporals, grpcPort, uiPort, dataDir, onProgress) {
|
|
190044
|
+
const binary = await ensureBinary(temporalBinary, void 0, onProgress);
|
|
190045
|
+
const dbPath = path17.join(process.cwd(), dataDir, "temporal.db");
|
|
190046
|
+
const dbDir = path17.dirname(dbPath);
|
|
190047
|
+
if (!fs20.existsSync(dbDir)) {
|
|
190048
|
+
fs20.mkdirSync(dbDir, { recursive: true });
|
|
190049
|
+
}
|
|
190050
|
+
const host = "127.0.0.1";
|
|
190051
|
+
const namespaceArgs = temporals.flatMap((t) => ["--namespace", t.name]);
|
|
190052
|
+
const proc = spawn5(
|
|
190053
|
+
binary.executables["temporal"],
|
|
190054
|
+
[
|
|
190055
|
+
"server",
|
|
190056
|
+
"start-dev",
|
|
190057
|
+
"--port",
|
|
190058
|
+
String(grpcPort),
|
|
190059
|
+
"--ui-port",
|
|
190060
|
+
String(uiPort),
|
|
190061
|
+
"--db-filename",
|
|
190062
|
+
dbPath,
|
|
190063
|
+
...namespaceArgs,
|
|
190064
|
+
"--log-format",
|
|
190065
|
+
"pretty"
|
|
190066
|
+
],
|
|
190067
|
+
{
|
|
190068
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
190069
|
+
}
|
|
190070
|
+
);
|
|
190071
|
+
pipeProcess("temporal", proc);
|
|
190072
|
+
await waitForTcpPort4(host, grpcPort);
|
|
190073
|
+
const stopServer = () => stopProcess4(proc);
|
|
190074
|
+
const instances = temporals.map((temporal, i) => ({
|
|
190075
|
+
name: temporal.name,
|
|
190076
|
+
type: "temporal",
|
|
190077
|
+
port: grpcPort,
|
|
190078
|
+
host,
|
|
190079
|
+
user: "",
|
|
190080
|
+
password: "",
|
|
190081
|
+
dbName: temporal.name,
|
|
190082
|
+
url: `${host}:${grpcPort}`,
|
|
190083
|
+
uiPort,
|
|
190084
|
+
// Only the first instance owns the server lifecycle
|
|
190085
|
+
stop: i === 0 ? stopServer : async () => {
|
|
190086
|
+
}
|
|
190087
|
+
}));
|
|
190088
|
+
return instances;
|
|
190089
|
+
}
|
|
190090
|
+
async function waitForTcpPort4(host, port, timeoutMs = 3e4) {
|
|
190091
|
+
const startTime = Date.now();
|
|
190092
|
+
while (Date.now() - startTime < timeoutMs) {
|
|
190093
|
+
const isOpen = await checkTcpPort4(host, port);
|
|
190094
|
+
if (isOpen) {
|
|
190095
|
+
return;
|
|
190096
|
+
}
|
|
190097
|
+
await new Promise((resolve10) => setTimeout(resolve10, 100));
|
|
190098
|
+
}
|
|
190099
|
+
throw new Error(`Temporal port ${port} did not become available within timeout`);
|
|
190100
|
+
}
|
|
190101
|
+
function checkTcpPort4(host, port) {
|
|
190102
|
+
return new Promise((resolve10) => {
|
|
190103
|
+
const socket = new net4.Socket();
|
|
190104
|
+
socket.setTimeout(1e3);
|
|
190105
|
+
socket.on("connect", () => {
|
|
190106
|
+
socket.destroy();
|
|
190107
|
+
resolve10(true);
|
|
190108
|
+
});
|
|
190109
|
+
socket.on("timeout", () => {
|
|
190110
|
+
socket.destroy();
|
|
190111
|
+
resolve10(false);
|
|
190112
|
+
});
|
|
190113
|
+
socket.on("error", () => {
|
|
190114
|
+
socket.destroy();
|
|
190115
|
+
resolve10(false);
|
|
190116
|
+
});
|
|
190117
|
+
socket.connect(port, host);
|
|
190118
|
+
});
|
|
190119
|
+
}
|
|
190120
|
+
async function stopProcess4(proc) {
|
|
190121
|
+
return new Promise((resolve10) => {
|
|
190122
|
+
if (proc.killed || proc.exitCode !== null) {
|
|
190123
|
+
resolve10();
|
|
190124
|
+
return;
|
|
190125
|
+
}
|
|
190126
|
+
proc.once("exit", () => {
|
|
190127
|
+
clearTimeout(forceKillTimeout);
|
|
190128
|
+
resolve10();
|
|
190129
|
+
});
|
|
190130
|
+
proc.kill("SIGTERM");
|
|
190131
|
+
const forceKillTimeout = setTimeout(() => {
|
|
190132
|
+
if (!proc.killed && proc.exitCode === null) {
|
|
190133
|
+
proc.kill("SIGKILL");
|
|
190134
|
+
}
|
|
190135
|
+
}, 2e3);
|
|
190136
|
+
});
|
|
190137
|
+
}
|
|
190138
|
+
|
|
189131
190139
|
// src/lib/dev/resource-starter.ts
|
|
189132
190140
|
function findRequiredResources(service) {
|
|
189133
|
-
const required = { postgres: [], redis: [], storage: [] };
|
|
190141
|
+
const required = { postgres: [], redis: [], storage: [], temporal: [] };
|
|
189134
190142
|
if (service.env) {
|
|
189135
190143
|
for (const value of Object.values(service.env)) {
|
|
189136
190144
|
if (typeof value !== "object" || value === null) continue;
|
|
@@ -189142,6 +190150,8 @@ function findRequiredResources(service) {
|
|
|
189142
190150
|
required.redis.push(ref.name);
|
|
189143
190151
|
} else if (ref.type === "storage" && !required.storage.includes(ref.name)) {
|
|
189144
190152
|
required.storage.push(ref.name);
|
|
190153
|
+
} else if (ref.type === "temporal" && !required.temporal.includes(ref.name)) {
|
|
190154
|
+
required.temporal.push(ref.name);
|
|
189145
190155
|
}
|
|
189146
190156
|
}
|
|
189147
190157
|
}
|
|
@@ -189168,14 +190178,17 @@ async function startResources(options2) {
|
|
|
189168
190178
|
let postgresConfigs;
|
|
189169
190179
|
let redisConfigs;
|
|
189170
190180
|
let storageConfigs;
|
|
190181
|
+
let temporalConfigs;
|
|
189171
190182
|
if (selection.mode === "all") {
|
|
189172
190183
|
postgresConfigs = config.postgres;
|
|
189173
190184
|
redisConfigs = config.redis;
|
|
189174
190185
|
storageConfigs = config.storage;
|
|
190186
|
+
temporalConfigs = config.temporal;
|
|
189175
190187
|
} else {
|
|
189176
190188
|
postgresConfigs = config.postgres.filter((p) => selection.postgres.includes(p.name));
|
|
189177
190189
|
redisConfigs = config.redis.filter((r) => selection.redis.includes(r.name));
|
|
189178
190190
|
storageConfigs = config.storage.filter((s) => selection.storage.includes(s.name));
|
|
190191
|
+
temporalConfigs = config.temporal.filter((t) => selection.temporal.includes(t.name));
|
|
189179
190192
|
}
|
|
189180
190193
|
for (const pg of postgresConfigs) {
|
|
189181
190194
|
if (signal?.cancelled) {
|
|
@@ -189261,6 +190274,25 @@ async function startResources(options2) {
|
|
|
189261
190274
|
if (instance.secretKey) dbState.secretKey = instance.secretKey;
|
|
189262
190275
|
await stateManager.registerDatabase(storage.name, dbState);
|
|
189263
190276
|
}
|
|
190277
|
+
if (temporalConfigs.length > 0) {
|
|
190278
|
+
if (signal?.cancelled) {
|
|
190279
|
+
return { resources, electric, startedResources, startedElectric, cancelled: true };
|
|
190280
|
+
}
|
|
190281
|
+
const grpcPort = portAllocator.allocate("temporal-grpc");
|
|
190282
|
+
const uiPort = portAllocator.allocate("temporal-ui");
|
|
190283
|
+
const names = temporalConfigs.map((t) => t.name).join(", ");
|
|
190284
|
+
log(`Starting temporal dev server on port ${grpcPort} (UI: ${uiPort}) with namespaces: ${names}`);
|
|
190285
|
+
callbacks.onResourceStarting?.(temporalConfigs[0].name, "temporal");
|
|
190286
|
+
const instances = await startTemporalDevServer(temporalConfigs, grpcPort, uiPort, dataDir, (progress) => {
|
|
190287
|
+
callbacks.onResourceProgress?.(temporalConfigs[0].name, progress);
|
|
190288
|
+
});
|
|
190289
|
+
for (const instance of instances) {
|
|
190290
|
+
resources.set(instance.name, instance);
|
|
190291
|
+
startedResources.push(instance);
|
|
190292
|
+
callbacks.onResourceReady?.(instance.name, instance);
|
|
190293
|
+
log(`Temporal namespace "${instance.name}" ready`);
|
|
190294
|
+
}
|
|
190295
|
+
}
|
|
189264
190296
|
if (shouldStartElectric) {
|
|
189265
190297
|
const syncDatabases = detectSyncDatabases(config);
|
|
189266
190298
|
for (const pgName of syncDatabases) {
|
|
@@ -189311,24 +190343,24 @@ function watchConfigFile(configPath, debounceMs, onChange) {
|
|
|
189311
190343
|
}
|
|
189312
190344
|
|
|
189313
190345
|
// src/lib/dev/subdomain-generator.ts
|
|
189314
|
-
import * as
|
|
189315
|
-
import * as
|
|
190346
|
+
import * as fs21 from "fs";
|
|
190347
|
+
import * as path18 from "path";
|
|
189316
190348
|
import { generateSlug } from "random-word-slugs";
|
|
189317
190349
|
var StableSubdomainAllocator = class {
|
|
189318
190350
|
tunnelsDir;
|
|
189319
190351
|
tunnelsFilePath;
|
|
189320
190352
|
baseSlug = null;
|
|
189321
190353
|
constructor(projectRoot, key = "default") {
|
|
189322
|
-
this.tunnelsDir =
|
|
189323
|
-
this.tunnelsFilePath =
|
|
190354
|
+
this.tunnelsDir = path18.join(projectRoot, ".specific", "keys", key);
|
|
190355
|
+
this.tunnelsFilePath = path18.join(this.tunnelsDir, "tunnels.json");
|
|
189324
190356
|
this.loadTunnels();
|
|
189325
190357
|
}
|
|
189326
190358
|
loadTunnels() {
|
|
189327
|
-
if (!
|
|
190359
|
+
if (!fs21.existsSync(this.tunnelsFilePath)) {
|
|
189328
190360
|
return;
|
|
189329
190361
|
}
|
|
189330
190362
|
try {
|
|
189331
|
-
const content =
|
|
190363
|
+
const content = fs21.readFileSync(this.tunnelsFilePath, "utf-8");
|
|
189332
190364
|
const data = JSON.parse(content);
|
|
189333
190365
|
if (data.version === 1 && data.baseSlug) {
|
|
189334
190366
|
this.baseSlug = data.baseSlug;
|
|
@@ -189338,14 +190370,14 @@ var StableSubdomainAllocator = class {
|
|
|
189338
190370
|
}
|
|
189339
190371
|
}
|
|
189340
190372
|
saveTunnels() {
|
|
189341
|
-
if (!
|
|
189342
|
-
|
|
190373
|
+
if (!fs21.existsSync(this.tunnelsDir)) {
|
|
190374
|
+
fs21.mkdirSync(this.tunnelsDir, { recursive: true });
|
|
189343
190375
|
}
|
|
189344
190376
|
const data = {
|
|
189345
190377
|
version: 1,
|
|
189346
190378
|
baseSlug: this.baseSlug
|
|
189347
190379
|
};
|
|
189348
|
-
|
|
190380
|
+
fs21.writeFileSync(this.tunnelsFilePath, JSON.stringify(data, null, 2));
|
|
189349
190381
|
}
|
|
189350
190382
|
generateBaseSlug() {
|
|
189351
190383
|
return generateSlug(2, {
|
|
@@ -189382,7 +190414,7 @@ var StableSubdomainAllocator = class {
|
|
|
189382
190414
|
|
|
189383
190415
|
// node_modules/.pnpm/@specific+tunnel-client@file+..+tunnel+client/node_modules/@specific/tunnel-client/dist/index.js
|
|
189384
190416
|
import { EventEmitter as EventEmitter2 } from "node:events";
|
|
189385
|
-
import * as
|
|
190417
|
+
import * as net5 from "node:net";
|
|
189386
190418
|
var DEFAULT_HOST = "https://tunnel.spcf.app";
|
|
189387
190419
|
var RECONNECT_DELAYS = [1e3, 2e3, 4e3, 8e3, 15e3];
|
|
189388
190420
|
async function register(baseUrl, subdomain) {
|
|
@@ -189424,7 +190456,7 @@ var TunnelClientImpl = class extends EventEmitter2 {
|
|
|
189424
190456
|
}
|
|
189425
190457
|
}
|
|
189426
190458
|
addPoolConnection() {
|
|
189427
|
-
const remote =
|
|
190459
|
+
const remote = net5.connect({ host: this.tunnelHost, port: this.info.port });
|
|
189428
190460
|
remote.setKeepAlive(true, 3e4);
|
|
189429
190461
|
this.pool.add(remote);
|
|
189430
190462
|
remote.once("data", (firstChunk) => {
|
|
@@ -189439,7 +190471,7 @@ var TunnelClientImpl = class extends EventEmitter2 {
|
|
|
189439
190471
|
remote.on("close", () => this.onIdleClose(remote, errored));
|
|
189440
190472
|
}
|
|
189441
190473
|
pipeToLocal(remote, firstChunk) {
|
|
189442
|
-
const local =
|
|
190474
|
+
const local = net5.connect({ host: "127.0.0.1", port: this.localPort }, () => {
|
|
189443
190475
|
local.write(firstChunk);
|
|
189444
190476
|
remote.pipe(local);
|
|
189445
190477
|
local.pipe(remote);
|
|
@@ -189501,10 +190533,10 @@ async function startTunnel(serviceName, endpointName, port, subdomain, callbacks
|
|
|
189501
190533
|
}
|
|
189502
190534
|
|
|
189503
190535
|
// src/lib/dev/proxy-registry.ts
|
|
189504
|
-
import * as
|
|
189505
|
-
import * as
|
|
189506
|
-
import * as
|
|
189507
|
-
import * as
|
|
190536
|
+
import * as fs22 from "fs";
|
|
190537
|
+
import * as path19 from "path";
|
|
190538
|
+
import * as os8 from "os";
|
|
190539
|
+
import * as net6 from "net";
|
|
189508
190540
|
var ProxyRegistryManager = class {
|
|
189509
190541
|
proxyDir;
|
|
189510
190542
|
ownerPath;
|
|
@@ -189513,14 +190545,14 @@ var ProxyRegistryManager = class {
|
|
|
189513
190545
|
isOwner = false;
|
|
189514
190546
|
registryWatcher = null;
|
|
189515
190547
|
constructor() {
|
|
189516
|
-
this.proxyDir =
|
|
189517
|
-
this.ownerPath =
|
|
189518
|
-
this.registryPath =
|
|
189519
|
-
this.lockPath =
|
|
190548
|
+
this.proxyDir = path19.join(os8.homedir(), ".specific", "proxy");
|
|
190549
|
+
this.ownerPath = path19.join(this.proxyDir, "owner.json");
|
|
190550
|
+
this.registryPath = path19.join(this.proxyDir, "registry.json");
|
|
190551
|
+
this.lockPath = path19.join(this.proxyDir, "registry.lock");
|
|
189520
190552
|
}
|
|
189521
190553
|
ensureProxyDir() {
|
|
189522
|
-
if (!
|
|
189523
|
-
|
|
190554
|
+
if (!fs22.existsSync(this.proxyDir)) {
|
|
190555
|
+
fs22.mkdirSync(this.proxyDir, { recursive: true });
|
|
189524
190556
|
}
|
|
189525
190557
|
}
|
|
189526
190558
|
isProcessRunning(pid) {
|
|
@@ -189538,7 +190570,7 @@ var ProxyRegistryManager = class {
|
|
|
189538
190570
|
*/
|
|
189539
190571
|
isProxyListening(port, timeoutMs = 1e3) {
|
|
189540
190572
|
return new Promise((resolve10) => {
|
|
189541
|
-
const socket = new
|
|
190573
|
+
const socket = new net6.Socket();
|
|
189542
190574
|
let resolved = false;
|
|
189543
190575
|
const cleanup = () => {
|
|
189544
190576
|
if (!resolved) {
|
|
@@ -189577,15 +190609,15 @@ var ProxyRegistryManager = class {
|
|
|
189577
190609
|
const startTime = Date.now();
|
|
189578
190610
|
while (Date.now() - startTime < timeoutMs) {
|
|
189579
190611
|
try {
|
|
189580
|
-
const fd =
|
|
190612
|
+
const fd = fs22.openSync(
|
|
189581
190613
|
this.lockPath,
|
|
189582
|
-
|
|
190614
|
+
fs22.constants.O_CREAT | fs22.constants.O_EXCL | fs22.constants.O_WRONLY
|
|
189583
190615
|
);
|
|
189584
|
-
|
|
189585
|
-
|
|
190616
|
+
fs22.writeSync(fd, String(process.pid));
|
|
190617
|
+
fs22.closeSync(fd);
|
|
189586
190618
|
return () => {
|
|
189587
190619
|
try {
|
|
189588
|
-
|
|
190620
|
+
fs22.unlinkSync(this.lockPath);
|
|
189589
190621
|
} catch {
|
|
189590
190622
|
}
|
|
189591
190623
|
};
|
|
@@ -189594,16 +190626,16 @@ var ProxyRegistryManager = class {
|
|
|
189594
190626
|
if (err.code === "EEXIST") {
|
|
189595
190627
|
try {
|
|
189596
190628
|
const lockPid = parseInt(
|
|
189597
|
-
|
|
190629
|
+
fs22.readFileSync(this.lockPath, "utf-8").trim(),
|
|
189598
190630
|
10
|
|
189599
190631
|
);
|
|
189600
190632
|
if (!this.isProcessRunning(lockPid)) {
|
|
189601
|
-
|
|
190633
|
+
fs22.unlinkSync(this.lockPath);
|
|
189602
190634
|
continue;
|
|
189603
190635
|
}
|
|
189604
190636
|
} catch {
|
|
189605
190637
|
try {
|
|
189606
|
-
|
|
190638
|
+
fs22.unlinkSync(this.lockPath);
|
|
189607
190639
|
} catch {
|
|
189608
190640
|
}
|
|
189609
190641
|
continue;
|
|
@@ -189623,8 +190655,8 @@ var ProxyRegistryManager = class {
|
|
|
189623
190655
|
async claimProxyOwnership(key) {
|
|
189624
190656
|
const releaseLock = await this.acquireLock();
|
|
189625
190657
|
try {
|
|
189626
|
-
if (
|
|
189627
|
-
const content =
|
|
190658
|
+
if (fs22.existsSync(this.ownerPath)) {
|
|
190659
|
+
const content = fs22.readFileSync(this.ownerPath, "utf-8");
|
|
189628
190660
|
const ownerFile2 = JSON.parse(content);
|
|
189629
190661
|
if (await this.isProxyOwnerHealthy(ownerFile2.owner.pid)) {
|
|
189630
190662
|
return false;
|
|
@@ -189654,11 +190686,11 @@ var ProxyRegistryManager = class {
|
|
|
189654
190686
|
}
|
|
189655
190687
|
const releaseLock = await this.acquireLock();
|
|
189656
190688
|
try {
|
|
189657
|
-
if (
|
|
189658
|
-
const content =
|
|
190689
|
+
if (fs22.existsSync(this.ownerPath)) {
|
|
190690
|
+
const content = fs22.readFileSync(this.ownerPath, "utf-8");
|
|
189659
190691
|
const ownerFile = JSON.parse(content);
|
|
189660
190692
|
if (ownerFile.owner.pid === process.pid) {
|
|
189661
|
-
|
|
190693
|
+
fs22.unlinkSync(this.ownerPath);
|
|
189662
190694
|
}
|
|
189663
190695
|
}
|
|
189664
190696
|
this.isOwner = false;
|
|
@@ -189670,12 +190702,12 @@ var ProxyRegistryManager = class {
|
|
|
189670
190702
|
* Get the current proxy owner.
|
|
189671
190703
|
*/
|
|
189672
190704
|
async getProxyOwner() {
|
|
189673
|
-
if (!
|
|
190705
|
+
if (!fs22.existsSync(this.ownerPath)) {
|
|
189674
190706
|
return null;
|
|
189675
190707
|
}
|
|
189676
190708
|
const releaseLock = await this.acquireLock();
|
|
189677
190709
|
try {
|
|
189678
|
-
const content =
|
|
190710
|
+
const content = fs22.readFileSync(this.ownerPath, "utf-8");
|
|
189679
190711
|
const ownerFile = JSON.parse(content);
|
|
189680
190712
|
if (!await this.isProxyOwnerHealthy(ownerFile.owner.pid)) {
|
|
189681
190713
|
return null;
|
|
@@ -189696,7 +190728,7 @@ var ProxyRegistryManager = class {
|
|
|
189696
190728
|
/**
|
|
189697
190729
|
* Register services for a key.
|
|
189698
190730
|
*/
|
|
189699
|
-
async registerServices(key, adminPort, services, drizzleGatewayPort) {
|
|
190731
|
+
async registerServices(key, adminPort, services, drizzleGatewayPort, temporalUiPort) {
|
|
189700
190732
|
const releaseLock = await this.acquireLock();
|
|
189701
190733
|
try {
|
|
189702
190734
|
const registry = this.readRegistry();
|
|
@@ -189707,6 +190739,9 @@ var ProxyRegistryManager = class {
|
|
|
189707
190739
|
if (drizzleGatewayPort !== void 0) {
|
|
189708
190740
|
registration.drizzleGatewayPort = drizzleGatewayPort;
|
|
189709
190741
|
}
|
|
190742
|
+
if (temporalUiPort !== void 0) {
|
|
190743
|
+
registration.temporalUiPort = temporalUiPort;
|
|
190744
|
+
}
|
|
189710
190745
|
registry.keys[key] = registration;
|
|
189711
190746
|
registry.lastUpdated = (/* @__PURE__ */ new Date()).toISOString();
|
|
189712
190747
|
this.writeFileAtomic(this.registryPath, registry);
|
|
@@ -189769,7 +190804,7 @@ var ProxyRegistryManager = class {
|
|
|
189769
190804
|
*/
|
|
189770
190805
|
watchRegistry(onChange) {
|
|
189771
190806
|
this.ensureProxyDir();
|
|
189772
|
-
if (!
|
|
190807
|
+
if (!fs22.existsSync(this.registryPath)) {
|
|
189773
190808
|
const emptyRegistry = {
|
|
189774
190809
|
version: 1,
|
|
189775
190810
|
keys: {},
|
|
@@ -189812,13 +190847,13 @@ var ProxyRegistryManager = class {
|
|
|
189812
190847
|
async attemptElection(key) {
|
|
189813
190848
|
const releaseLock = await this.acquireLock();
|
|
189814
190849
|
try {
|
|
189815
|
-
if (
|
|
189816
|
-
const content =
|
|
190850
|
+
if (fs22.existsSync(this.ownerPath)) {
|
|
190851
|
+
const content = fs22.readFileSync(this.ownerPath, "utf-8");
|
|
189817
190852
|
const ownerFile2 = JSON.parse(content);
|
|
189818
190853
|
if (await this.isProxyOwnerHealthy(ownerFile2.owner.pid)) {
|
|
189819
190854
|
return false;
|
|
189820
190855
|
}
|
|
189821
|
-
|
|
190856
|
+
fs22.unlinkSync(this.ownerPath);
|
|
189822
190857
|
}
|
|
189823
190858
|
const ownerFile = {
|
|
189824
190859
|
version: 1,
|
|
@@ -189836,7 +190871,7 @@ var ProxyRegistryManager = class {
|
|
|
189836
190871
|
}
|
|
189837
190872
|
}
|
|
189838
190873
|
readRegistry() {
|
|
189839
|
-
if (!
|
|
190874
|
+
if (!fs22.existsSync(this.registryPath)) {
|
|
189840
190875
|
return {
|
|
189841
190876
|
version: 1,
|
|
189842
190877
|
keys: {},
|
|
@@ -189844,7 +190879,7 @@ var ProxyRegistryManager = class {
|
|
|
189844
190879
|
};
|
|
189845
190880
|
}
|
|
189846
190881
|
try {
|
|
189847
|
-
const content =
|
|
190882
|
+
const content = fs22.readFileSync(this.registryPath, "utf-8");
|
|
189848
190883
|
return JSON.parse(content);
|
|
189849
190884
|
} catch {
|
|
189850
190885
|
return {
|
|
@@ -189857,8 +190892,8 @@ var ProxyRegistryManager = class {
|
|
|
189857
190892
|
writeFileAtomic(filePath, data) {
|
|
189858
190893
|
this.ensureProxyDir();
|
|
189859
190894
|
const tmpPath = filePath + ".tmp";
|
|
189860
|
-
|
|
189861
|
-
|
|
190895
|
+
fs22.writeFileSync(tmpPath, JSON.stringify(data, null, 2));
|
|
190896
|
+
fs22.renameSync(tmpPath, filePath);
|
|
189862
190897
|
}
|
|
189863
190898
|
};
|
|
189864
190899
|
|
|
@@ -189962,10 +190997,10 @@ var COLORS = ["cyan", "yellow", "green", "magenta", "blue"];
|
|
|
189962
190997
|
function DevUI({ instanceKey, tunnelEnabled }) {
|
|
189963
190998
|
const { exit } = useApp2();
|
|
189964
190999
|
const [state, setState] = useState5(() => {
|
|
189965
|
-
const
|
|
191000
|
+
const setupDone = tunnelEnabled || !systemSetupNeeded();
|
|
189966
191001
|
return {
|
|
189967
|
-
status:
|
|
189968
|
-
...
|
|
191002
|
+
status: setupDone ? "loading" : "installing-ca",
|
|
191003
|
+
...setupDone ? {} : { caInstallPhase: "installing" },
|
|
189969
191004
|
resources: /* @__PURE__ */ new Map(),
|
|
189970
191005
|
resourceStatus: /* @__PURE__ */ new Map(),
|
|
189971
191006
|
services: [],
|
|
@@ -189978,18 +191013,15 @@ function DevUI({ instanceKey, tunnelEnabled }) {
|
|
|
189978
191013
|
});
|
|
189979
191014
|
useEffect3(() => {
|
|
189980
191015
|
if (state.status === "installing-ca" && state.caInstallPhase === "installing") {
|
|
189981
|
-
|
|
191016
|
+
installSystemConfig();
|
|
189982
191017
|
}
|
|
189983
191018
|
}, [state.status, state.caInstallPhase]);
|
|
189984
|
-
async function
|
|
191019
|
+
async function installSystemConfig() {
|
|
189985
191020
|
try {
|
|
189986
|
-
|
|
189987
|
-
const certPath = saveCA(key, cert);
|
|
189988
|
-
installCAToTrustStore(certPath);
|
|
191021
|
+
performSystemSetup();
|
|
189989
191022
|
setState((s) => ({ ...s, status: "loading", caInstallPhase: "done" }));
|
|
189990
191023
|
setReadyToStart(true);
|
|
189991
191024
|
} catch (err) {
|
|
189992
|
-
removeCA();
|
|
189993
191025
|
setState((s) => ({
|
|
189994
191026
|
...s,
|
|
189995
191027
|
caInstallPhase: "error",
|
|
@@ -190007,13 +191039,14 @@ function DevUI({ instanceKey, tunnelEnabled }) {
|
|
|
190007
191039
|
const registryWatcherCleanupRef = useRef(null);
|
|
190008
191040
|
const electionIntervalRef = useRef(null);
|
|
190009
191041
|
const tunnelsRef = useRef([]);
|
|
191042
|
+
const dnsServerRef = useRef(null);
|
|
190010
191043
|
const proxyRef = useRef(null);
|
|
190011
191044
|
const adminServerRef = useRef(null);
|
|
190012
191045
|
const servicesRef = useRef([]);
|
|
190013
191046
|
const resourcesRef = useRef(/* @__PURE__ */ new Map());
|
|
190014
191047
|
const restartServicesRef = useRef(null);
|
|
190015
191048
|
const [reloadTrigger, setReloadTrigger] = useState5(0);
|
|
190016
|
-
const [readyToStart, setReadyToStart] = useState5(() => tunnelEnabled ||
|
|
191049
|
+
const [readyToStart, setReadyToStart] = useState5(() => tunnelEnabled || !systemSetupNeeded());
|
|
190017
191050
|
const shutdown2 = async () => {
|
|
190018
191051
|
if (shuttingDown.current) return;
|
|
190019
191052
|
shuttingDown.current = true;
|
|
@@ -190032,6 +191065,8 @@ function DevUI({ instanceKey, tunnelEnabled }) {
|
|
|
190032
191065
|
await Promise.all([
|
|
190033
191066
|
// Stop proxy
|
|
190034
191067
|
proxyRef.current?.stop(),
|
|
191068
|
+
// Stop DNS server
|
|
191069
|
+
dnsServerRef.current?.stop(),
|
|
190035
191070
|
// Stop admin server
|
|
190036
191071
|
adminServerRef.current?.stop(),
|
|
190037
191072
|
// Stop all services
|
|
@@ -190075,6 +191110,8 @@ function DevUI({ instanceKey, tunnelEnabled }) {
|
|
|
190075
191110
|
await Promise.all([
|
|
190076
191111
|
// Stop proxy
|
|
190077
191112
|
proxyRef.current?.stop(),
|
|
191113
|
+
// Stop DNS server
|
|
191114
|
+
dnsServerRef.current?.stop(),
|
|
190078
191115
|
// Stop admin server
|
|
190079
191116
|
adminServerRef.current?.stop(),
|
|
190080
191117
|
// Stop all services
|
|
@@ -190095,6 +191132,7 @@ function DevUI({ instanceKey, tunnelEnabled }) {
|
|
|
190095
191132
|
restartServicesRef.current = null;
|
|
190096
191133
|
drizzleGatewayRef.current = null;
|
|
190097
191134
|
proxyRef.current = null;
|
|
191135
|
+
dnsServerRef.current = null;
|
|
190098
191136
|
adminServerRef.current = null;
|
|
190099
191137
|
servicesRef.current = [];
|
|
190100
191138
|
resourcesRef.current = /* @__PURE__ */ new Map();
|
|
@@ -190126,6 +191164,7 @@ function DevUI({ instanceKey, tunnelEnabled }) {
|
|
|
190126
191164
|
writeLog("system", "Force shutting down");
|
|
190127
191165
|
const allProcesses = [
|
|
190128
191166
|
proxyRef.current,
|
|
191167
|
+
dnsServerRef.current,
|
|
190129
191168
|
...servicesRef.current,
|
|
190130
191169
|
...electricInstancesRef.current,
|
|
190131
191170
|
drizzleGatewayRef.current,
|
|
@@ -190167,16 +191206,16 @@ function DevUI({ instanceKey, tunnelEnabled }) {
|
|
|
190167
191206
|
}, [state.status]);
|
|
190168
191207
|
useEffect3(() => {
|
|
190169
191208
|
if (state.status !== "running") return;
|
|
190170
|
-
const configPath =
|
|
191209
|
+
const configPath = path20.join(process.cwd(), "specific.hcl");
|
|
190171
191210
|
const watcher = watchConfigFile(configPath, 1e3, () => {
|
|
190172
191211
|
try {
|
|
190173
|
-
const hcl =
|
|
191212
|
+
const hcl = fs23.readFileSync(configPath, "utf-8");
|
|
190174
191213
|
parseConfig(hcl).then(() => {
|
|
190175
191214
|
triggerReload();
|
|
190176
191215
|
}).catch((err) => {
|
|
190177
191216
|
setState((s) => ({
|
|
190178
191217
|
...s,
|
|
190179
|
-
parseError:
|
|
191218
|
+
parseError: formatConfigError(err, hcl, configPath)
|
|
190180
191219
|
}));
|
|
190181
191220
|
});
|
|
190182
191221
|
} catch (err) {
|
|
@@ -190295,8 +191334,8 @@ function DevUI({ instanceKey, tunnelEnabled }) {
|
|
|
190295
191334
|
}));
|
|
190296
191335
|
return;
|
|
190297
191336
|
}
|
|
190298
|
-
const configPath =
|
|
190299
|
-
if (!
|
|
191337
|
+
const configPath = path20.join(process.cwd(), "specific.hcl");
|
|
191338
|
+
if (!fs23.existsSync(configPath)) {
|
|
190300
191339
|
writeLog("system", "Waiting for specific.hcl to appear");
|
|
190301
191340
|
setState((s) => ({
|
|
190302
191341
|
...s,
|
|
@@ -190314,14 +191353,14 @@ function DevUI({ instanceKey, tunnelEnabled }) {
|
|
|
190314
191353
|
return;
|
|
190315
191354
|
}
|
|
190316
191355
|
let config2;
|
|
191356
|
+
const hcl = fs23.readFileSync(configPath, "utf-8");
|
|
190317
191357
|
try {
|
|
190318
|
-
const hcl = fs21.readFileSync(configPath, "utf-8");
|
|
190319
191358
|
config2 = await parseConfig(hcl);
|
|
190320
191359
|
} catch (err) {
|
|
190321
191360
|
setState((s) => ({
|
|
190322
191361
|
...s,
|
|
190323
191362
|
status: "error",
|
|
190324
|
-
error: err
|
|
191363
|
+
error: formatConfigError(err, hcl, configPath)
|
|
190325
191364
|
}));
|
|
190326
191365
|
return;
|
|
190327
191366
|
}
|
|
@@ -190340,6 +191379,10 @@ function DevUI({ instanceKey, tunnelEnabled }) {
|
|
|
190340
191379
|
colorMap.set(`res:${storage.name}`, COLORS[colorIndex % COLORS.length]);
|
|
190341
191380
|
colorIndex++;
|
|
190342
191381
|
}
|
|
191382
|
+
for (const temporal of config2.temporal) {
|
|
191383
|
+
colorMap.set(`res:${temporal.name}`, COLORS[colorIndex % COLORS.length]);
|
|
191384
|
+
colorIndex++;
|
|
191385
|
+
}
|
|
190343
191386
|
for (const service of config2.services) {
|
|
190344
191387
|
colorMap.set(
|
|
190345
191388
|
`svc:${service.name}`,
|
|
@@ -190421,7 +191464,7 @@ function DevUI({ instanceKey, tunnelEnabled }) {
|
|
|
190421
191464
|
const drizzleGateway = await startDrizzleGateway(
|
|
190422
191465
|
postgresResources,
|
|
190423
191466
|
drizzlePort,
|
|
190424
|
-
|
|
191467
|
+
path20.join(process.cwd(), ".specific", "keys", instanceKey)
|
|
190425
191468
|
);
|
|
190426
191469
|
startedDrizzleGateway = drizzleGateway;
|
|
190427
191470
|
drizzleGatewayRef.current = drizzleGateway;
|
|
@@ -190441,7 +191484,7 @@ function DevUI({ instanceKey, tunnelEnabled }) {
|
|
|
190441
191484
|
if (pg.reshape?.enabled) {
|
|
190442
191485
|
const resource = resources2.get(pg.name);
|
|
190443
191486
|
if (!resource) continue;
|
|
190444
|
-
const migrationsDir =
|
|
191487
|
+
const migrationsDir = path20.resolve(
|
|
190445
191488
|
process.cwd(),
|
|
190446
191489
|
pg.reshape.migrations_dir ?? "migrations"
|
|
190447
191490
|
);
|
|
@@ -190609,10 +191652,10 @@ Add them to the config block in specific.local`);
|
|
|
190609
191652
|
}
|
|
190610
191653
|
const services2 = [];
|
|
190611
191654
|
function resolveServiceCwd(service) {
|
|
190612
|
-
if (service.root) return
|
|
191655
|
+
if (service.root) return path20.resolve(process.cwd(), service.root);
|
|
190613
191656
|
if (service.build) {
|
|
190614
191657
|
const build = config2.builds.find((b) => b.name === service.build.name);
|
|
190615
|
-
if (build?.root) return
|
|
191658
|
+
if (build?.root) return path20.resolve(process.cwd(), build.root);
|
|
190616
191659
|
}
|
|
190617
191660
|
return process.cwd();
|
|
190618
191661
|
}
|
|
@@ -190631,6 +191674,14 @@ Add them to the config block in specific.local`);
|
|
|
190631
191674
|
"system",
|
|
190632
191675
|
`Starting service "${service.name}"${portsList ? ` on port${endpointPorts.size > 1 ? "s" : ""} ${portsList}` : ""}`
|
|
190633
191676
|
);
|
|
191677
|
+
const volumePaths = /* @__PURE__ */ new Map();
|
|
191678
|
+
if (service.volumes) {
|
|
191679
|
+
for (const vol of service.volumes) {
|
|
191680
|
+
const volumeDir = path20.resolve(`.specific/keys/${instanceKey}/data/volumes/${service.name}/${vol.name}`);
|
|
191681
|
+
fs23.mkdirSync(volumeDir, { recursive: true });
|
|
191682
|
+
volumePaths.set(vol.name, volumeDir);
|
|
191683
|
+
}
|
|
191684
|
+
}
|
|
190634
191685
|
const running = startService(
|
|
190635
191686
|
service,
|
|
190636
191687
|
resources2,
|
|
@@ -190640,7 +191691,8 @@ Add them to the config block in specific.local`);
|
|
|
190640
191691
|
serviceEndpoints,
|
|
190641
191692
|
(line) => addLog(line, colorMap),
|
|
190642
191693
|
publicUrls,
|
|
190643
|
-
resolveServiceCwd(service)
|
|
191694
|
+
resolveServiceCwd(service),
|
|
191695
|
+
volumePaths
|
|
190644
191696
|
);
|
|
190645
191697
|
services2.push(running);
|
|
190646
191698
|
startedServices.push(running);
|
|
@@ -190678,6 +191730,14 @@ Add them to the config block in specific.local`);
|
|
|
190678
191730
|
if (!service.command && !service.dev?.command) continue;
|
|
190679
191731
|
try {
|
|
190680
191732
|
const endpointPorts = serviceEndpointPorts.get(service.name) || /* @__PURE__ */ new Map();
|
|
191733
|
+
const volumePaths = /* @__PURE__ */ new Map();
|
|
191734
|
+
if (service.volumes) {
|
|
191735
|
+
for (const vol of service.volumes) {
|
|
191736
|
+
const volumeDir = path20.resolve(`.specific/keys/${instanceKey}/data/volumes/${service.name}/${vol.name}`);
|
|
191737
|
+
fs23.mkdirSync(volumeDir, { recursive: true });
|
|
191738
|
+
volumePaths.set(vol.name, volumeDir);
|
|
191739
|
+
}
|
|
191740
|
+
}
|
|
190681
191741
|
const running = startService(
|
|
190682
191742
|
service,
|
|
190683
191743
|
resources2,
|
|
@@ -190687,7 +191747,8 @@ Add them to the config block in specific.local`);
|
|
|
190687
191747
|
serviceEndpoints,
|
|
190688
191748
|
(line) => addLog(line, colorMap),
|
|
190689
191749
|
void 0,
|
|
190690
|
-
resolveServiceCwd(service)
|
|
191750
|
+
resolveServiceCwd(service),
|
|
191751
|
+
volumePaths
|
|
190691
191752
|
);
|
|
190692
191753
|
newServices.push(running);
|
|
190693
191754
|
} catch (err) {
|
|
@@ -190774,6 +191835,7 @@ Add them to the config block in specific.local`);
|
|
|
190774
191835
|
runningServicePorts.set(s.name, s.ports.get("default"));
|
|
190775
191836
|
}
|
|
190776
191837
|
const projectId = hasProjectId() ? readProjectId() : void 0;
|
|
191838
|
+
const hasTemporal = config2.temporal.length > 0;
|
|
190777
191839
|
const getState = () => ({
|
|
190778
191840
|
status: "running",
|
|
190779
191841
|
services: config2.services.filter((svc) => runningServicePorts.has(svc.name) || svc.serve).map((svc) => ({
|
|
@@ -190789,22 +191851,28 @@ Add them to the config block in specific.local`);
|
|
|
190789
191851
|
host: r.host,
|
|
190790
191852
|
syncEnabled: r.type === "postgres" && syncDatabases.has(name)
|
|
190791
191853
|
})),
|
|
190792
|
-
projectId
|
|
191854
|
+
projectId,
|
|
191855
|
+
hasTemporal
|
|
190793
191856
|
});
|
|
190794
191857
|
const adminServer = await startAdminServer(getState);
|
|
190795
191858
|
adminServerRef.current = adminServer;
|
|
190796
191859
|
writeLog("system", `Admin API server started on port ${adminServer.port}`);
|
|
191860
|
+
const temporalInstance = [...resources2.values()].find((r) => r.type === "temporal");
|
|
191861
|
+
const temporalUiPort = temporalInstance?.uiPort;
|
|
190797
191862
|
await proxyRegistry.registerServices(
|
|
190798
191863
|
instanceKey,
|
|
190799
191864
|
adminServer.port,
|
|
190800
191865
|
serviceInfos,
|
|
190801
|
-
startedDrizzleGateway?.port
|
|
191866
|
+
startedDrizzleGateway?.port,
|
|
191867
|
+
temporalUiPort
|
|
190802
191868
|
);
|
|
190803
191869
|
writeLog("system", `Registered ${serviceInfos.length} services with proxy registry`);
|
|
190804
191870
|
const becameProxyOwner = await proxyRegistry.claimProxyOwnership(instanceKey);
|
|
190805
191871
|
if (becameProxyOwner) {
|
|
190806
|
-
writeLog("system", "Claimed proxy ownership, starting HTTP proxy");
|
|
191872
|
+
writeLog("system", "Claimed proxy ownership, starting HTTP proxy and DNS server");
|
|
190807
191873
|
try {
|
|
191874
|
+
const dnsServer = await startDnsServer();
|
|
191875
|
+
dnsServerRef.current = dnsServer;
|
|
190808
191876
|
const currentServices = await proxyRegistry.getAllServices();
|
|
190809
191877
|
const registeredKeys = [...new Set(currentServices.map((s) => s.key))];
|
|
190810
191878
|
const certificate = generateCertificate("local.spcf.app", registeredKeys);
|
|
@@ -190869,12 +191937,14 @@ Add them to the config block in specific.local`);
|
|
|
190869
191937
|
writeLog("system", "Proxy owner died, attempting election");
|
|
190870
191938
|
const won = await proxyRegistry.attemptElection(instanceKey);
|
|
190871
191939
|
if (won) {
|
|
190872
|
-
writeLog("system", "Won election, starting HTTP proxy");
|
|
191940
|
+
writeLog("system", "Won election, starting HTTP proxy and DNS server");
|
|
190873
191941
|
if (electionIntervalRef.current) {
|
|
190874
191942
|
clearInterval(electionIntervalRef.current);
|
|
190875
191943
|
electionIntervalRef.current = null;
|
|
190876
191944
|
}
|
|
190877
191945
|
try {
|
|
191946
|
+
const dnsServer = await startDnsServer();
|
|
191947
|
+
dnsServerRef.current = dnsServer;
|
|
190878
191948
|
const electionServices = await proxyRegistry.getAllServices();
|
|
190879
191949
|
const electionKeyRegistrations = await proxyRegistry.getAllKeyRegistrations();
|
|
190880
191950
|
const electionKeyNames = Object.keys(electionKeyRegistrations);
|
|
@@ -190920,6 +191990,8 @@ Add them to the config block in specific.local`);
|
|
|
190920
191990
|
startedProxy.stop().catch(() => {
|
|
190921
191991
|
});
|
|
190922
191992
|
}
|
|
191993
|
+
dnsServerRef.current?.stop().catch(() => {
|
|
191994
|
+
});
|
|
190923
191995
|
for (const service of startedServices) {
|
|
190924
191996
|
service.stop().catch(() => {
|
|
190925
191997
|
});
|
|
@@ -190952,10 +192024,10 @@ Add them to the config block in specific.local`);
|
|
|
190952
192024
|
}, [reloadTrigger, readyToStart, instanceKey]);
|
|
190953
192025
|
if (state.status === "installing-ca") {
|
|
190954
192026
|
if (state.caInstallPhase === "installing") {
|
|
190955
|
-
return /* @__PURE__ */ React6.createElement(Box6, { flexDirection: "column" }, /* @__PURE__ */ React6.createElement(Text6, { bold: true, color: "cyan" }, "
|
|
192027
|
+
return /* @__PURE__ */ React6.createElement(Box6, { flexDirection: "column" }, /* @__PURE__ */ React6.createElement(Text6, { bold: true, color: "cyan" }, "Local Development Setup"), /* @__PURE__ */ React6.createElement(Text6, null, " "), /* @__PURE__ */ React6.createElement(Text6, null, "Setting up TLS certificates and DNS resolution for local"), /* @__PURE__ */ React6.createElement(Text6, null, "development. This is a one-time setup for Specific projects."), /* @__PURE__ */ React6.createElement(Text6, null, " "), /* @__PURE__ */ React6.createElement(Text6, null, "Your password is required to configure your system."), /* @__PURE__ */ React6.createElement(Text6, null, " "));
|
|
190956
192028
|
}
|
|
190957
192029
|
if (state.caInstallPhase === "error") {
|
|
190958
|
-
return /* @__PURE__ */ React6.createElement(Box6, { flexDirection: "column" }, /* @__PURE__ */ React6.createElement(Text6, { color: "red" }, "
|
|
192030
|
+
return /* @__PURE__ */ React6.createElement(Box6, { flexDirection: "column" }, /* @__PURE__ */ React6.createElement(Text6, { color: "red" }, "Setup failed: ", state.caError));
|
|
190959
192031
|
}
|
|
190960
192032
|
}
|
|
190961
192033
|
if (state.status === "loading") {
|
|
@@ -190989,7 +192061,7 @@ Add them to the config block in specific.local`);
|
|
|
190989
192061
|
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!")));
|
|
190990
192062
|
}
|
|
190991
192063
|
if (state.status === "error") {
|
|
190992
|
-
return /* @__PURE__ */ React6.createElement(Box6, { flexDirection: "column" }, /* @__PURE__ */ React6.createElement(Text6, { color: "red" },
|
|
192064
|
+
return /* @__PURE__ */ React6.createElement(Box6, { flexDirection: "column" }, /* @__PURE__ */ React6.createElement(Text6, { color: "red" }, state.error));
|
|
190993
192065
|
}
|
|
190994
192066
|
if (state.status === "stopping") {
|
|
190995
192067
|
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..."));
|
|
@@ -191002,7 +192074,7 @@ Add them to the config block in specific.local`);
|
|
|
191002
192074
|
return /* @__PURE__ */ React6.createElement(Box6, null, /* @__PURE__ */ React6.createElement(Text6, { color: "blue" }, /* @__PURE__ */ React6.createElement(Spinner4, { type: "dots" })));
|
|
191003
192075
|
}
|
|
191004
192076
|
if (state.status === "starting") {
|
|
191005
|
-
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) => {
|
|
192077
|
+
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 || config.temporal.length > 0) && /* @__PURE__ */ React6.createElement(React6.Fragment, null, /* @__PURE__ */ React6.createElement(Text6, { bold: true }, "Resources:"), config.postgres.map((pg) => {
|
|
191006
192078
|
const instance = resources.get(pg.name);
|
|
191007
192079
|
const resStatus = state.resourceStatus.get(pg.name);
|
|
191008
192080
|
const isReady = !!instance;
|
|
@@ -191040,6 +192112,22 @@ Add them to the config block in specific.local`);
|
|
|
191040
192112
|
const isReady = !!instance;
|
|
191041
192113
|
const statusText = resStatus?.status === "starting" ? " starting..." : "";
|
|
191042
192114
|
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));
|
|
192115
|
+
}), config.temporal.map((temporal) => {
|
|
192116
|
+
const instance = resources.get(temporal.name);
|
|
192117
|
+
const resStatus = state.resourceStatus.get(temporal.name);
|
|
192118
|
+
const isReady = !!instance;
|
|
192119
|
+
let statusText = "";
|
|
192120
|
+
if (resStatus?.status === "downloading") {
|
|
192121
|
+
const progress = resStatus.downloadProgress;
|
|
192122
|
+
if (progress?.percent !== void 0) {
|
|
192123
|
+
statusText = ` downloading ${progress.percent}%`;
|
|
192124
|
+
} else {
|
|
192125
|
+
statusText = " downloading...";
|
|
192126
|
+
}
|
|
192127
|
+
} else if (resStatus?.status === "starting") {
|
|
192128
|
+
statusText = " starting...";
|
|
192129
|
+
}
|
|
192130
|
+
return /* @__PURE__ */ React6.createElement(Text6, { key: temporal.name }, /* @__PURE__ */ React6.createElement(Text6, { color: isReady ? "green" : "gray" }, " \u25CF "), /* @__PURE__ */ React6.createElement(Text6, null, temporal.name, " (temporal)"), instance && /* @__PURE__ */ React6.createElement(Text6, null, " \u2192 localhost:", instance.port), !isReady && statusText && /* @__PURE__ */ React6.createElement(Text6, { dimColor: true }, statusText));
|
|
191043
192131
|
}), /* @__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) => {
|
|
191044
192132
|
const running = services.find((s) => s.name === svc.name);
|
|
191045
192133
|
const isReady = !!running;
|
|
@@ -191136,11 +192224,22 @@ Add them to the config block in specific.local`);
|
|
|
191136
192224
|
}),
|
|
191137
192225
|
{ key: "storage-space", content: /* @__PURE__ */ React6.createElement(Text6, null, " ") }
|
|
191138
192226
|
] : [],
|
|
192227
|
+
...config.temporal.length > 0 ? [
|
|
192228
|
+
{ key: "temporal-header", content: /* @__PURE__ */ React6.createElement(Text6, { bold: true }, "Temporal:") },
|
|
192229
|
+
...config.temporal.map((temporal) => {
|
|
192230
|
+
const instance = resources.get(temporal.name);
|
|
192231
|
+
return {
|
|
192232
|
+
key: `temporal-${temporal.name}`,
|
|
192233
|
+
content: /* @__PURE__ */ React6.createElement(Text6, null, /* @__PURE__ */ React6.createElement(Text6, { color: "green" }, " \u25CF "), /* @__PURE__ */ React6.createElement(Text6, null, temporal.name), instance && /* @__PURE__ */ React6.createElement(Text6, null, " \u2192 localhost:", instance.port))
|
|
192234
|
+
};
|
|
192235
|
+
}),
|
|
192236
|
+
{ key: "temporal-space", content: /* @__PURE__ */ React6.createElement(Text6, null, " ") }
|
|
192237
|
+
] : [],
|
|
191139
192238
|
{ key: "separator", content: /* @__PURE__ */ React6.createElement(Text6, { dimColor: true }, "\u2500".repeat(50)) },
|
|
191140
192239
|
...state.parseError ? [
|
|
191141
192240
|
{
|
|
191142
192241
|
key: "parse-error",
|
|
191143
|
-
content: /* @__PURE__ */ React6.createElement(Text6, { color: "red" },
|
|
192242
|
+
content: /* @__PURE__ */ React6.createElement(Text6, { color: "red" }, state.parseError)
|
|
191144
192243
|
}
|
|
191145
192244
|
] : [],
|
|
191146
192245
|
...output.map((line, i) => ({
|
|
@@ -191155,20 +192254,20 @@ function devCommand(instanceKey, tunnelEnabled = false) {
|
|
|
191155
192254
|
}
|
|
191156
192255
|
|
|
191157
192256
|
// src/lib/dev/git-worktree.ts
|
|
191158
|
-
import { execSync as
|
|
191159
|
-
import * as
|
|
192257
|
+
import { execSync as execSync3 } from "child_process";
|
|
192258
|
+
import * as path21 from "path";
|
|
191160
192259
|
function isInWorktree() {
|
|
191161
192260
|
try {
|
|
191162
|
-
const commonDir =
|
|
192261
|
+
const commonDir = execSync3("git rev-parse --git-common-dir", {
|
|
191163
192262
|
encoding: "utf-8",
|
|
191164
192263
|
stdio: ["pipe", "pipe", "pipe"]
|
|
191165
192264
|
}).trim();
|
|
191166
|
-
const gitDir =
|
|
192265
|
+
const gitDir = execSync3("git rev-parse --git-dir", {
|
|
191167
192266
|
encoding: "utf-8",
|
|
191168
192267
|
stdio: ["pipe", "pipe", "pipe"]
|
|
191169
192268
|
}).trim();
|
|
191170
|
-
const resolvedCommonDir =
|
|
191171
|
-
const resolvedGitDir =
|
|
192269
|
+
const resolvedCommonDir = path21.resolve(commonDir);
|
|
192270
|
+
const resolvedGitDir = path21.resolve(gitDir);
|
|
191172
192271
|
return resolvedCommonDir !== resolvedGitDir;
|
|
191173
192272
|
} catch {
|
|
191174
192273
|
return false;
|
|
@@ -191179,11 +192278,11 @@ function getWorktreeName() {
|
|
|
191179
192278
|
return null;
|
|
191180
192279
|
}
|
|
191181
192280
|
try {
|
|
191182
|
-
const gitDir =
|
|
192281
|
+
const gitDir = execSync3("git rev-parse --git-dir", {
|
|
191183
192282
|
encoding: "utf-8",
|
|
191184
192283
|
stdio: ["pipe", "pipe", "pipe"]
|
|
191185
192284
|
}).trim();
|
|
191186
|
-
return
|
|
192285
|
+
return path21.basename(gitDir);
|
|
191187
192286
|
} catch {
|
|
191188
192287
|
return null;
|
|
191189
192288
|
}
|
|
@@ -191198,36 +192297,37 @@ init_open();
|
|
|
191198
192297
|
import React7, { useState as useState6, useEffect as useEffect4, useCallback } from "react";
|
|
191199
192298
|
import { render as render5, Text as Text7, Box as Box7, useApp as useApp3, useInput as useInput5 } from "ink";
|
|
191200
192299
|
import Spinner5 from "ink-spinner";
|
|
191201
|
-
import * as
|
|
191202
|
-
import * as
|
|
192300
|
+
import * as fs25 from "fs";
|
|
192301
|
+
import * as path23 from "path";
|
|
191203
192302
|
|
|
191204
192303
|
// src/lib/deploy/build-tester.ts
|
|
191205
|
-
import { spawn as
|
|
191206
|
-
import { existsSync as
|
|
191207
|
-
import { join as
|
|
192304
|
+
import { spawn as spawn6 } from "child_process";
|
|
192305
|
+
import { existsSync as existsSync22 } from "fs";
|
|
192306
|
+
import { join as join23, resolve as resolve7 } from "path";
|
|
191208
192307
|
function getDependencyInstallCommand(build, projectDir) {
|
|
192308
|
+
if (!build.base) return null;
|
|
191209
192309
|
switch (build.base) {
|
|
191210
192310
|
case "node":
|
|
191211
|
-
if (
|
|
192311
|
+
if (existsSync22(join23(projectDir, "pnpm-lock.yaml"))) {
|
|
191212
192312
|
return "pnpm install --frozen-lockfile";
|
|
191213
|
-
} else if (
|
|
192313
|
+
} else if (existsSync22(join23(projectDir, "yarn.lock"))) {
|
|
191214
192314
|
return "yarn install --frozen-lockfile";
|
|
191215
|
-
} else if (
|
|
192315
|
+
} else if (existsSync22(join23(projectDir, "package-lock.json"))) {
|
|
191216
192316
|
return "npm ci";
|
|
191217
|
-
} else if (
|
|
192317
|
+
} else if (existsSync22(join23(projectDir, "package.json"))) {
|
|
191218
192318
|
return "npm install";
|
|
191219
192319
|
}
|
|
191220
192320
|
return null;
|
|
191221
192321
|
case "python":
|
|
191222
|
-
if (
|
|
192322
|
+
if (existsSync22(join23(projectDir, "poetry.lock"))) {
|
|
191223
192323
|
return "poetry install --no-interaction";
|
|
191224
|
-
} else if (
|
|
192324
|
+
} else if (existsSync22(join23(projectDir, "Pipfile.lock"))) {
|
|
191225
192325
|
return "pipenv install --deploy";
|
|
191226
|
-
} else if (
|
|
192326
|
+
} else if (existsSync22(join23(projectDir, "Pipfile"))) {
|
|
191227
192327
|
return "pipenv install";
|
|
191228
|
-
} else if (
|
|
192328
|
+
} else if (existsSync22(join23(projectDir, "pyproject.toml"))) {
|
|
191229
192329
|
return "pip install .";
|
|
191230
|
-
} else if (
|
|
192330
|
+
} else if (existsSync22(join23(projectDir, "requirements.txt"))) {
|
|
191231
192331
|
return "pip install -r requirements.txt";
|
|
191232
192332
|
}
|
|
191233
192333
|
return null;
|
|
@@ -191245,7 +192345,7 @@ function runCommand2(command, projectDir, buildName) {
|
|
|
191245
192345
|
const stdout = [];
|
|
191246
192346
|
const stderr = [];
|
|
191247
192347
|
writeLog("build-test", `[${buildName}] Running: ${command}`);
|
|
191248
|
-
const child =
|
|
192348
|
+
const child = spawn6(command, {
|
|
191249
192349
|
shell: true,
|
|
191250
192350
|
cwd: projectDir,
|
|
191251
192351
|
env: { ...process.env },
|
|
@@ -191293,6 +192393,15 @@ function runCommand2(command, projectDir, buildName) {
|
|
|
191293
192393
|
}
|
|
191294
192394
|
async function testBuild(build, projectDir) {
|
|
191295
192395
|
const startTime = Date.now();
|
|
192396
|
+
if (build.dockerfile) {
|
|
192397
|
+
writeLog("build-test", `Skipping test for build "${build.name}" (custom Dockerfile)`);
|
|
192398
|
+
return {
|
|
192399
|
+
buildName: build.name,
|
|
192400
|
+
success: true,
|
|
192401
|
+
output: "Skipped: custom Dockerfile build",
|
|
192402
|
+
durationMs: Date.now() - startTime
|
|
192403
|
+
};
|
|
192404
|
+
}
|
|
191296
192405
|
const outputs = [];
|
|
191297
192406
|
const workDir = build.root ? resolve7(projectDir, build.root) : projectDir;
|
|
191298
192407
|
writeLog("build-test", `Starting test for build "${build.name}" (base: ${build.base}, workDir: ${workDir})`);
|
|
@@ -191372,13 +192481,13 @@ async function testAllBuilds(builds, projectDir) {
|
|
|
191372
192481
|
}
|
|
191373
192482
|
|
|
191374
192483
|
// src/lib/tarball/create.ts
|
|
191375
|
-
import { execSync as
|
|
191376
|
-
import * as
|
|
191377
|
-
import * as
|
|
192484
|
+
import { execSync as execSync4 } from "child_process";
|
|
192485
|
+
import * as fs24 from "fs";
|
|
192486
|
+
import * as path22 from "path";
|
|
191378
192487
|
import { createTarPacker, createEntryItemGenerator } from "tar-vern";
|
|
191379
192488
|
function isInsideGitRepository(dir) {
|
|
191380
192489
|
try {
|
|
191381
|
-
const result =
|
|
192490
|
+
const result = execSync4("git rev-parse --is-inside-work-tree", {
|
|
191382
192491
|
cwd: dir,
|
|
191383
192492
|
encoding: "utf-8",
|
|
191384
192493
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -191390,7 +192499,7 @@ function isInsideGitRepository(dir) {
|
|
|
191390
192499
|
}
|
|
191391
192500
|
async function createGitArchive(projectDir) {
|
|
191392
192501
|
writeLog("tarball", "Creating tarball using git ls-files");
|
|
191393
|
-
const filesOutput =
|
|
192502
|
+
const filesOutput = execSync4(
|
|
191394
192503
|
"git ls-files --cached --others --exclude-standard",
|
|
191395
192504
|
{
|
|
191396
192505
|
cwd: projectDir,
|
|
@@ -191431,10 +192540,10 @@ var EXCLUDED_DIRS = [
|
|
|
191431
192540
|
];
|
|
191432
192541
|
async function collectPaths(baseDir, currentDir, exclude) {
|
|
191433
192542
|
const results = [];
|
|
191434
|
-
const entries = await
|
|
192543
|
+
const entries = await fs24.promises.readdir(currentDir, { withFileTypes: true });
|
|
191435
192544
|
for (const entry of entries) {
|
|
191436
|
-
const fullPath =
|
|
191437
|
-
const relativePath =
|
|
192545
|
+
const fullPath = path22.join(currentDir, entry.name);
|
|
192546
|
+
const relativePath = path22.relative(baseDir, fullPath);
|
|
191438
192547
|
if (entry.isDirectory()) {
|
|
191439
192548
|
if (!exclude.includes(entry.name)) {
|
|
191440
192549
|
results.push(relativePath);
|
|
@@ -191449,8 +192558,8 @@ async function collectPaths(baseDir, currentDir, exclude) {
|
|
|
191449
192558
|
}
|
|
191450
192559
|
async function createTarArchive(projectDir) {
|
|
191451
192560
|
writeLog("tarball", "Creating tarball using tar-vern (non-git project)");
|
|
191452
|
-
const configPath =
|
|
191453
|
-
if (!
|
|
192561
|
+
const configPath = path22.join(projectDir, "specific.hcl");
|
|
192562
|
+
if (!fs24.existsSync(configPath)) {
|
|
191454
192563
|
throw new Error("specific.hcl not found in project directory");
|
|
191455
192564
|
}
|
|
191456
192565
|
const relativePaths = await collectPaths(projectDir, projectDir, EXCLUDED_DIRS);
|
|
@@ -191467,8 +192576,8 @@ async function createTarArchive(projectDir) {
|
|
|
191467
192576
|
}
|
|
191468
192577
|
function findWidestContext(projectDir, contexts) {
|
|
191469
192578
|
if (contexts.length === 0) return ".";
|
|
191470
|
-
const absolute = contexts.map((c) =>
|
|
191471
|
-
const segments = absolute.map((p) => p.split(
|
|
192579
|
+
const absolute = contexts.map((c) => path22.resolve(projectDir, c));
|
|
192580
|
+
const segments = absolute.map((p) => p.split(path22.sep).filter(Boolean));
|
|
191472
192581
|
const firstSegments = segments[0];
|
|
191473
192582
|
if (!firstSegments) return ".";
|
|
191474
192583
|
const minLen = Math.min(...segments.map((s) => s.length));
|
|
@@ -191482,12 +192591,12 @@ function findWidestContext(projectDir, contexts) {
|
|
|
191482
192591
|
}
|
|
191483
192592
|
}
|
|
191484
192593
|
const ancestorSegments = firstSegments.slice(0, commonLength);
|
|
191485
|
-
const ancestor =
|
|
191486
|
-
return
|
|
192594
|
+
const ancestor = path22.sep + ancestorSegments.join(path22.sep);
|
|
192595
|
+
return path22.relative(projectDir, ancestor) || ".";
|
|
191487
192596
|
}
|
|
191488
192597
|
async function createProjectTarball(projectDir, context = ".") {
|
|
191489
|
-
const contextDir =
|
|
191490
|
-
const appPath =
|
|
192598
|
+
const contextDir = path22.resolve(projectDir, context);
|
|
192599
|
+
const appPath = path22.relative(contextDir, projectDir) || ".";
|
|
191491
192600
|
writeLog("tarball", `Context: ${contextDir}, appPath: ${appPath}`);
|
|
191492
192601
|
let tarball;
|
|
191493
192602
|
if (isInsideGitRepository(contextDir)) {
|
|
@@ -192374,19 +193483,17 @@ ${errorMsg}`
|
|
|
192374
193483
|
), 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))))));
|
|
192375
193484
|
}
|
|
192376
193485
|
async function deployCommand(environment, options2) {
|
|
192377
|
-
const configPath =
|
|
192378
|
-
if (!
|
|
193486
|
+
const configPath = path23.join(process.cwd(), "specific.hcl");
|
|
193487
|
+
if (!fs25.existsSync(configPath)) {
|
|
192379
193488
|
console.error("Error: No specific.hcl found in current directory");
|
|
192380
193489
|
process.exit(1);
|
|
192381
193490
|
}
|
|
192382
193491
|
let config;
|
|
193492
|
+
const hcl = fs25.readFileSync(configPath, "utf-8");
|
|
192383
193493
|
try {
|
|
192384
|
-
const hcl = fs23.readFileSync(configPath, "utf-8");
|
|
192385
193494
|
config = await parseConfig(hcl);
|
|
192386
193495
|
} catch (err) {
|
|
192387
|
-
console.error(
|
|
192388
|
-
`Error: Invalid configuration: ${err instanceof Error ? err.message : String(err)}`
|
|
192389
|
-
);
|
|
193496
|
+
console.error(formatConfigError(err, hcl, configPath));
|
|
192390
193497
|
process.exit(1);
|
|
192391
193498
|
}
|
|
192392
193499
|
const env2 = environment || "prod";
|
|
@@ -192404,9 +193511,9 @@ async function deployCommand(environment, options2) {
|
|
|
192404
193511
|
}
|
|
192405
193512
|
|
|
192406
193513
|
// src/commands/exec.tsx
|
|
192407
|
-
import { spawn as
|
|
192408
|
-
import * as
|
|
192409
|
-
import * as
|
|
193514
|
+
import { spawn as spawn7 } from "child_process";
|
|
193515
|
+
import * as fs26 from "fs";
|
|
193516
|
+
import * as path24 from "path";
|
|
192410
193517
|
async function execCommand(serviceName, command, instanceKey = "default") {
|
|
192411
193518
|
if (command.length === 0) {
|
|
192412
193519
|
console.error(
|
|
@@ -192434,17 +193541,17 @@ async function execCommand(serviceName, command, instanceKey = "default") {
|
|
|
192434
193541
|
}
|
|
192435
193542
|
}
|
|
192436
193543
|
};
|
|
192437
|
-
const configPath =
|
|
192438
|
-
if (!
|
|
193544
|
+
const configPath = path24.join(process.cwd(), "specific.hcl");
|
|
193545
|
+
if (!fs26.existsSync(configPath)) {
|
|
192439
193546
|
console.error("Error: No specific.hcl found in current directory");
|
|
192440
193547
|
process.exit(1);
|
|
192441
193548
|
}
|
|
192442
193549
|
let config;
|
|
193550
|
+
const hcl = fs26.readFileSync(configPath, "utf-8");
|
|
192443
193551
|
try {
|
|
192444
|
-
const hcl = fs24.readFileSync(configPath, "utf-8");
|
|
192445
193552
|
config = await parseConfig(hcl);
|
|
192446
193553
|
} catch (err) {
|
|
192447
|
-
console.error(
|
|
193554
|
+
console.error(formatConfigError(err, hcl, configPath));
|
|
192448
193555
|
process.exit(1);
|
|
192449
193556
|
}
|
|
192450
193557
|
const service = config.services.find((s) => s.name === serviceName);
|
|
@@ -192512,7 +193619,8 @@ async function execCommand(serviceName, command, instanceKey = "default") {
|
|
|
192512
193619
|
mode: "required",
|
|
192513
193620
|
postgres: required.postgres,
|
|
192514
193621
|
redis: required.redis,
|
|
192515
|
-
storage: required.storage
|
|
193622
|
+
storage: required.storage,
|
|
193623
|
+
temporal: required.temporal
|
|
192516
193624
|
},
|
|
192517
193625
|
stateManager,
|
|
192518
193626
|
dataDir: `.specific/keys/${instanceKey}/data`,
|
|
@@ -192557,14 +193665,14 @@ async function execCommand(serviceName, command, instanceKey = "default") {
|
|
|
192557
193665
|
process.on("SIGTERM", () => handleSignal("SIGTERM"));
|
|
192558
193666
|
let effectiveCwd = process.cwd();
|
|
192559
193667
|
if (service.root) {
|
|
192560
|
-
effectiveCwd =
|
|
193668
|
+
effectiveCwd = path24.resolve(process.cwd(), service.root);
|
|
192561
193669
|
} else if (service.build) {
|
|
192562
193670
|
const build = config.builds.find((b) => b.name === service.build.name);
|
|
192563
193671
|
if (build?.root) {
|
|
192564
|
-
effectiveCwd =
|
|
193672
|
+
effectiveCwd = path24.resolve(process.cwd(), build.root);
|
|
192565
193673
|
}
|
|
192566
193674
|
}
|
|
192567
|
-
child =
|
|
193675
|
+
child = spawn7(command[0], command.slice(1), {
|
|
192568
193676
|
cwd: effectiveCwd,
|
|
192569
193677
|
env: {
|
|
192570
193678
|
...process.env,
|
|
@@ -192588,9 +193696,9 @@ async function execCommand(serviceName, command, instanceKey = "default") {
|
|
|
192588
193696
|
}
|
|
192589
193697
|
|
|
192590
193698
|
// src/commands/psql.tsx
|
|
192591
|
-
import { spawn as
|
|
192592
|
-
import * as
|
|
192593
|
-
import * as
|
|
193699
|
+
import { spawn as spawn8 } from "child_process";
|
|
193700
|
+
import * as fs27 from "fs";
|
|
193701
|
+
import * as path25 from "path";
|
|
192594
193702
|
async function psqlCommand(databaseName, instanceKey = "default", extraArgs = []) {
|
|
192595
193703
|
let startedResources = [];
|
|
192596
193704
|
let ownsInstances = false;
|
|
@@ -192607,17 +193715,17 @@ async function psqlCommand(databaseName, instanceKey = "default", extraArgs = []
|
|
|
192607
193715
|
}
|
|
192608
193716
|
}
|
|
192609
193717
|
};
|
|
192610
|
-
const configPath =
|
|
192611
|
-
if (!
|
|
193718
|
+
const configPath = path25.join(process.cwd(), "specific.hcl");
|
|
193719
|
+
if (!fs27.existsSync(configPath)) {
|
|
192612
193720
|
console.error("Error: No specific.hcl found in current directory");
|
|
192613
193721
|
process.exit(1);
|
|
192614
193722
|
}
|
|
192615
193723
|
let config;
|
|
193724
|
+
const hcl = fs27.readFileSync(configPath, "utf-8");
|
|
192616
193725
|
try {
|
|
192617
|
-
const hcl = fs25.readFileSync(configPath, "utf-8");
|
|
192618
193726
|
config = await parseConfig(hcl);
|
|
192619
193727
|
} catch (err) {
|
|
192620
|
-
console.error(
|
|
193728
|
+
console.error(formatConfigError(err, hcl, configPath));
|
|
192621
193729
|
process.exit(1);
|
|
192622
193730
|
}
|
|
192623
193731
|
const availableDatabases = config.postgres.map((p) => p.name);
|
|
@@ -192666,7 +193774,8 @@ async function psqlCommand(databaseName, instanceKey = "default", extraArgs = []
|
|
|
192666
193774
|
mode: "required",
|
|
192667
193775
|
postgres: [targetDb],
|
|
192668
193776
|
redis: [],
|
|
192669
|
-
storage: []
|
|
193777
|
+
storage: [],
|
|
193778
|
+
temporal: []
|
|
192670
193779
|
},
|
|
192671
193780
|
stateManager,
|
|
192672
193781
|
dataDir: `.specific/keys/${instanceKey}/data`,
|
|
@@ -192710,7 +193819,7 @@ async function psqlCommand(databaseName, instanceKey = "default", extraArgs = []
|
|
|
192710
193819
|
};
|
|
192711
193820
|
process.on("SIGINT", () => handleSignal("SIGINT"));
|
|
192712
193821
|
process.on("SIGTERM", () => handleSignal("SIGTERM"));
|
|
192713
|
-
child =
|
|
193822
|
+
child = spawn8(psqlPath, ["-h", dbState.host, "-p", String(dbState.port), "-U", dbState.user, "-d", dbState.dbName, ...extraArgs], {
|
|
192714
193823
|
cwd: process.cwd(),
|
|
192715
193824
|
env: {
|
|
192716
193825
|
...process.env,
|
|
@@ -192735,9 +193844,9 @@ async function psqlCommand(databaseName, instanceKey = "default", extraArgs = []
|
|
|
192735
193844
|
}
|
|
192736
193845
|
|
|
192737
193846
|
// src/commands/reshape.tsx
|
|
192738
|
-
import { spawn as
|
|
192739
|
-
import * as
|
|
192740
|
-
import * as
|
|
193847
|
+
import { spawn as spawn9 } from "child_process";
|
|
193848
|
+
import * as fs28 from "fs";
|
|
193849
|
+
import * as path26 from "path";
|
|
192741
193850
|
var VALID_ACTIONS = ["start", "complete", "status", "abort", "check"];
|
|
192742
193851
|
var MIGRATION_SUBCOMMANDS = ["start", "complete", "abort"];
|
|
192743
193852
|
var OFFLINE_ACTIONS = ["check"];
|
|
@@ -192749,13 +193858,13 @@ async function reshapeCommand(action, databaseName, instanceKey = "default") {
|
|
|
192749
193858
|
process.exit(1);
|
|
192750
193859
|
}
|
|
192751
193860
|
const isOfflineAction = OFFLINE_ACTIONS.includes(action);
|
|
192752
|
-
const configPath =
|
|
193861
|
+
const configPath = path26.join(process.cwd(), "specific.hcl");
|
|
192753
193862
|
let config;
|
|
192754
193863
|
let migrationsDir = "migrations";
|
|
192755
193864
|
let targetDb;
|
|
192756
193865
|
try {
|
|
192757
|
-
if (
|
|
192758
|
-
const configContent =
|
|
193866
|
+
if (fs28.existsSync(configPath)) {
|
|
193867
|
+
const configContent = fs28.readFileSync(configPath, "utf-8");
|
|
192759
193868
|
config = await parseConfig(configContent);
|
|
192760
193869
|
if (databaseName) {
|
|
192761
193870
|
const postgresConfig = config.postgres.find((p) => p.name === databaseName);
|
|
@@ -192859,7 +193968,8 @@ async function reshapeCommand(action, databaseName, instanceKey = "default") {
|
|
|
192859
193968
|
mode: "required",
|
|
192860
193969
|
postgres: [targetDb],
|
|
192861
193970
|
redis: [],
|
|
192862
|
-
storage: []
|
|
193971
|
+
storage: [],
|
|
193972
|
+
temporal: []
|
|
192863
193973
|
},
|
|
192864
193974
|
stateManager,
|
|
192865
193975
|
dataDir: `.specific/keys/${instanceKey}/data`,
|
|
@@ -192888,9 +193998,9 @@ async function reshapeCommand(action, databaseName, instanceKey = "default") {
|
|
|
192888
193998
|
}
|
|
192889
193999
|
const isMigrationSubcommand = MIGRATION_SUBCOMMANDS.includes(action);
|
|
192890
194000
|
const reshapeArgs = isMigrationSubcommand ? ["migration", action] : [action];
|
|
192891
|
-
const fullMigrationsPath =
|
|
194001
|
+
const fullMigrationsPath = path26.join(process.cwd(), migrationsDir);
|
|
192892
194002
|
if (action === "check" || action === "start") {
|
|
192893
|
-
if (
|
|
194003
|
+
if (fs28.existsSync(fullMigrationsPath)) {
|
|
192894
194004
|
reshapeArgs.push("--dirs", fullMigrationsPath);
|
|
192895
194005
|
} else if (action === "check") {
|
|
192896
194006
|
console.error(`Error: Migrations directory not found: ${fullMigrationsPath}`);
|
|
@@ -192912,7 +194022,7 @@ async function reshapeCommand(action, databaseName, instanceKey = "default") {
|
|
|
192912
194022
|
};
|
|
192913
194023
|
process.on("SIGINT", () => handleSignal("SIGINT"));
|
|
192914
194024
|
process.on("SIGTERM", () => handleSignal("SIGTERM"));
|
|
192915
|
-
child =
|
|
194025
|
+
child = spawn9(reshapePath, reshapeArgs, {
|
|
192916
194026
|
cwd: process.cwd(),
|
|
192917
194027
|
env: {
|
|
192918
194028
|
...process.env,
|
|
@@ -192940,21 +194050,21 @@ async function reshapeCommand(action, databaseName, instanceKey = "default") {
|
|
|
192940
194050
|
import React8, { useState as useState7, useEffect as useEffect5 } from "react";
|
|
192941
194051
|
import { render as render6, Text as Text8, Box as Box8 } from "ink";
|
|
192942
194052
|
import Spinner6 from "ink-spinner";
|
|
192943
|
-
import * as
|
|
192944
|
-
import * as
|
|
194053
|
+
import * as fs29 from "fs";
|
|
194054
|
+
import * as path27 from "path";
|
|
192945
194055
|
function CleanUI({ instanceKey }) {
|
|
192946
194056
|
const [state, setState] = useState7({ status: "checking" });
|
|
192947
194057
|
useEffect5(() => {
|
|
192948
194058
|
async function clean() {
|
|
192949
194059
|
const projectRoot = process.cwd();
|
|
192950
|
-
const specificDir =
|
|
192951
|
-
if (!
|
|
194060
|
+
const specificDir = path27.join(projectRoot, ".specific");
|
|
194061
|
+
if (!fs29.existsSync(specificDir)) {
|
|
192952
194062
|
setState({ status: "nothing" });
|
|
192953
194063
|
return;
|
|
192954
194064
|
}
|
|
192955
194065
|
if (instanceKey) {
|
|
192956
|
-
const keyDir =
|
|
192957
|
-
if (!
|
|
194066
|
+
const keyDir = path27.join(specificDir, "keys", instanceKey);
|
|
194067
|
+
if (!fs29.existsSync(keyDir)) {
|
|
192958
194068
|
setState({ status: "nothing" });
|
|
192959
194069
|
return;
|
|
192960
194070
|
}
|
|
@@ -192970,7 +194080,7 @@ function CleanUI({ instanceKey }) {
|
|
|
192970
194080
|
await stateManager.cleanStaleState();
|
|
192971
194081
|
setState({ status: "cleaning" });
|
|
192972
194082
|
try {
|
|
192973
|
-
|
|
194083
|
+
fs29.rmSync(keyDir, { recursive: true, force: true });
|
|
192974
194084
|
setState({ status: "success" });
|
|
192975
194085
|
} catch (err) {
|
|
192976
194086
|
setState({
|
|
@@ -192979,13 +194089,13 @@ function CleanUI({ instanceKey }) {
|
|
|
192979
194089
|
});
|
|
192980
194090
|
}
|
|
192981
194091
|
} else {
|
|
192982
|
-
const keysDir =
|
|
192983
|
-
if (!
|
|
194092
|
+
const keysDir = path27.join(specificDir, "keys");
|
|
194093
|
+
if (!fs29.existsSync(keysDir)) {
|
|
192984
194094
|
setState({ status: "nothing" });
|
|
192985
194095
|
return;
|
|
192986
194096
|
}
|
|
192987
|
-
const keys =
|
|
192988
|
-
(f) =>
|
|
194097
|
+
const keys = fs29.readdirSync(keysDir).filter(
|
|
194098
|
+
(f) => fs29.statSync(path27.join(keysDir, f)).isDirectory()
|
|
192989
194099
|
);
|
|
192990
194100
|
for (const key of keys) {
|
|
192991
194101
|
const stateManager2 = new InstanceStateManager(projectRoot, key);
|
|
@@ -193009,7 +194119,7 @@ function CleanUI({ instanceKey }) {
|
|
|
193009
194119
|
}
|
|
193010
194120
|
setState({ status: "cleaning" });
|
|
193011
194121
|
try {
|
|
193012
|
-
|
|
194122
|
+
fs29.rmSync(keysDir, { recursive: true, force: true });
|
|
193013
194123
|
setState({ status: "success" });
|
|
193014
194124
|
} catch (err) {
|
|
193015
194125
|
setState({
|
|
@@ -193172,7 +194282,7 @@ function betaCommand() {
|
|
|
193172
194282
|
var program = new Command();
|
|
193173
194283
|
var env = "production";
|
|
193174
194284
|
var envLabel = env !== "production" ? `[${env.toUpperCase()}] ` : "";
|
|
193175
|
-
program.name("specific").description(`${envLabel}Infrastructure-as-code for coding agents`).version("0.1.
|
|
194285
|
+
program.name("specific").description(`${envLabel}Infrastructure-as-code for coding agents`).version("0.1.63").enablePositionalOptions();
|
|
193176
194286
|
program.command("init").description("Initialize project for use with a coding agent").option("--agent <name...>", "Agents to configure (cursor, claude, codex, other)").action((options2) => initCommand(options2));
|
|
193177
194287
|
program.command("docs [topic]").description("Fetch LLM-optimized documentation").action(docsCommand);
|
|
193178
194288
|
program.command("check").description("Validate specific.hcl configuration").action(checkCommand);
|