@specific.dev/cli 0.1.75 → 0.1.77
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 +1 -1
- package/dist/admin/__next.!KGRlZmF1bHQp.txt +1 -1
- package/dist/admin/__next._full.txt +1 -1
- package/dist/admin/__next._head.txt +1 -1
- package/dist/admin/__next._index.txt +1 -1
- package/dist/admin/__next._tree.txt +1 -1
- package/dist/admin/_not-found/__next._full.txt +1 -1
- package/dist/admin/_not-found/__next._head.txt +1 -1
- package/dist/admin/_not-found/__next._index.txt +1 -1
- 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 +1 -1
- package/dist/admin/databases/__next.!KGRlZmF1bHQp.databases.__PAGE__.txt +1 -1
- package/dist/admin/databases/__next.!KGRlZmF1bHQp.databases.txt +1 -1
- package/dist/admin/databases/__next.!KGRlZmF1bHQp.txt +1 -1
- package/dist/admin/databases/__next._full.txt +1 -1
- package/dist/admin/databases/__next._head.txt +1 -1
- package/dist/admin/databases/__next._index.txt +1 -1
- package/dist/admin/databases/__next._tree.txt +1 -1
- package/dist/admin/databases/index.html +1 -1
- package/dist/admin/databases/index.txt +1 -1
- package/dist/admin/fullscreen/__next._full.txt +1 -1
- package/dist/admin/fullscreen/__next._head.txt +1 -1
- package/dist/admin/fullscreen/__next._index.txt +1 -1
- package/dist/admin/fullscreen/__next._tree.txt +1 -1
- package/dist/admin/fullscreen/__next.fullscreen.__PAGE__.txt +1 -1
- package/dist/admin/fullscreen/__next.fullscreen.txt +1 -1
- package/dist/admin/fullscreen/databases/__next._full.txt +1 -1
- package/dist/admin/fullscreen/databases/__next._head.txt +1 -1
- package/dist/admin/fullscreen/databases/__next._index.txt +1 -1
- package/dist/admin/fullscreen/databases/__next._tree.txt +1 -1
- package/dist/admin/fullscreen/databases/__next.fullscreen.databases.__PAGE__.txt +1 -1
- 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 +1 -1
- package/dist/admin/fullscreen/index.html +1 -1
- package/dist/admin/fullscreen/index.txt +1 -1
- package/dist/admin/index.html +1 -1
- package/dist/admin/index.txt +1 -1
- package/dist/admin/mail/__next.!KGRlZmF1bHQp.mail.__PAGE__.txt +1 -1
- package/dist/admin/mail/__next.!KGRlZmF1bHQp.mail.txt +1 -1
- package/dist/admin/mail/__next.!KGRlZmF1bHQp.txt +1 -1
- package/dist/admin/mail/__next._full.txt +1 -1
- package/dist/admin/mail/__next._head.txt +1 -1
- package/dist/admin/mail/__next._index.txt +1 -1
- package/dist/admin/mail/__next._tree.txt +1 -1
- package/dist/admin/mail/index.html +1 -1
- package/dist/admin/mail/index.txt +1 -1
- package/dist/admin/workflows/__next.!KGRlZmF1bHQp.txt +1 -1
- package/dist/admin/workflows/__next.!KGRlZmF1bHQp.workflows.__PAGE__.txt +1 -1
- package/dist/admin/workflows/__next.!KGRlZmF1bHQp.workflows.txt +1 -1
- package/dist/admin/workflows/__next._full.txt +1 -1
- package/dist/admin/workflows/__next._head.txt +1 -1
- package/dist/admin/workflows/__next._index.txt +1 -1
- package/dist/admin/workflows/__next._tree.txt +1 -1
- package/dist/admin/workflows/index.html +1 -1
- package/dist/admin/workflows/index.txt +1 -1
- package/dist/cli.js +260 -291
- package/dist/postinstall.js +1 -1
- package/package.json +1 -1
- /package/dist/admin/_next/static/{ntsk0waJiBFcaeQ8sbm0K → P2MjAcNNtToSRrG27euV4}/_buildManifest.js +0 -0
- /package/dist/admin/_next/static/{ntsk0waJiBFcaeQ8sbm0K → P2MjAcNNtToSRrG27euV4}/_clientMiddlewareManifest.json +0 -0
- /package/dist/admin/_next/static/{ntsk0waJiBFcaeQ8sbm0K → P2MjAcNNtToSRrG27euV4}/_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;
|
|
@@ -435,7 +435,7 @@ import process8 from "node:process";
|
|
|
435
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();
|
|
@@ -467,7 +467,7 @@ var init_open = __esm({
|
|
|
467
467
|
fallbackAttemptSymbol = Symbol("fallbackAttempt");
|
|
468
468
|
__dirname = import.meta.url ? path5.dirname(fileURLToPath(import.meta.url)) : "";
|
|
469
469
|
localXdgOpenPath = path5.join(__dirname, "xdg-open");
|
|
470
|
-
({ platform:
|
|
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 fs32 = $global.require("fs");
|
|
758
|
+
"object" == typeof fs32 && null !== fs32 && 0 !== Object.keys(fs32).length && ($global.fs = fs32);
|
|
759
759
|
} catch (e) {
|
|
760
760
|
}
|
|
761
761
|
if (!$global.fs) {
|
|
@@ -183430,13 +183430,11 @@ import { Command } from "commander";
|
|
|
183430
183430
|
import React2, { useState, useEffect } from "react";
|
|
183431
183431
|
import { render as render2, Text as Text2, Box as Box2, useInput, useApp } from "ink";
|
|
183432
183432
|
import "ink-spinner";
|
|
183433
|
-
import * as
|
|
183433
|
+
import * as fs11 from "fs";
|
|
183434
183434
|
import * as path7 from "path";
|
|
183435
183435
|
|
|
183436
183436
|
// src/lib/dev/system-setup.ts
|
|
183437
183437
|
import { execSync as execSync2 } from "child_process";
|
|
183438
|
-
import * as fs4 from "fs";
|
|
183439
|
-
import * as os4 from "os";
|
|
183440
183438
|
import * as path3 from "path";
|
|
183441
183439
|
|
|
183442
183440
|
// src/lib/dev/local-ca.ts
|
|
@@ -183472,17 +183470,17 @@ function caInstalledInTrustStore() {
|
|
|
183472
183470
|
if (!caFilesExist()) {
|
|
183473
183471
|
return false;
|
|
183474
183472
|
}
|
|
183475
|
-
const
|
|
183473
|
+
const platform5 = os.platform();
|
|
183476
183474
|
const certPath = path.join(getCADir(), "ca.crt");
|
|
183477
183475
|
const diskCert = fs.readFileSync(certPath, "utf-8").replace(/\r\n/g, "\n").trim();
|
|
183478
183476
|
try {
|
|
183479
|
-
if (
|
|
183477
|
+
if (platform5 === "darwin") {
|
|
183480
183478
|
const keychainCert = execSync(
|
|
183481
183479
|
'security find-certificate -c "Specific Local Development CA" -p /Library/Keychains/System.keychain',
|
|
183482
183480
|
{ encoding: "utf-8" }
|
|
183483
183481
|
).replace(/\r\n/g, "\n").trim();
|
|
183484
183482
|
return keychainCert === diskCert;
|
|
183485
|
-
} else if (
|
|
183483
|
+
} else if (platform5 === "linux") {
|
|
183486
183484
|
const trustPaths = [
|
|
183487
183485
|
"/usr/local/share/ca-certificates/specific-local-ca.crt",
|
|
183488
183486
|
// Debian/Ubuntu
|
|
@@ -183594,15 +183592,15 @@ function removeCA() {
|
|
|
183594
183592
|
}
|
|
183595
183593
|
}
|
|
183596
183594
|
function getCAInstallCommands(certPath) {
|
|
183597
|
-
const
|
|
183598
|
-
if (
|
|
183595
|
+
const platform5 = os.platform();
|
|
183596
|
+
if (platform5 === "darwin") {
|
|
183599
183597
|
return [
|
|
183600
183598
|
// Remove any existing cert with the same CN first — add-trusted-cert
|
|
183601
183599
|
// silently does nothing if a cert with the same subject already exists.
|
|
183602
183600
|
'security delete-certificate -c "Specific Local Development CA" /Library/Keychains/System.keychain 2>/dev/null || true',
|
|
183603
183601
|
`security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain "${certPath}"`
|
|
183604
183602
|
];
|
|
183605
|
-
} else if (
|
|
183603
|
+
} else if (platform5 === "linux") {
|
|
183606
183604
|
if (fs.existsSync("/usr/local/share/ca-certificates")) {
|
|
183607
183605
|
return [
|
|
183608
183606
|
`cp "${certPath}" /usr/local/share/ca-certificates/specific-local-ca.crt`,
|
|
@@ -183621,7 +183619,7 @@ function getCAInstallCommands(certPath) {
|
|
|
183621
183619
|
}
|
|
183622
183620
|
throw new Error("Could not detect Linux certificate trust mechanism");
|
|
183623
183621
|
}
|
|
183624
|
-
throw new Error(`Unsupported platform: ${
|
|
183622
|
+
throw new Error(`Unsupported platform: ${platform5}`);
|
|
183625
183623
|
}
|
|
183626
183624
|
function generateCertificate(domain, keys = []) {
|
|
183627
183625
|
const caDir = getCADir();
|
|
@@ -183667,23 +183665,23 @@ var RESOLVER_FILE_MACOS = "/etc/resolver/spcf.localhost";
|
|
|
183667
183665
|
var OLD_RESOLVER_FILE_MACOS = "/etc/resolver/local.spcf.app";
|
|
183668
183666
|
var RESOLVER_FILE_LINUX = "/etc/systemd/resolved.conf.d/specific-local.conf";
|
|
183669
183667
|
function resolverConfigExists() {
|
|
183670
|
-
const
|
|
183671
|
-
if (
|
|
183668
|
+
const platform5 = os2.platform();
|
|
183669
|
+
if (platform5 === "darwin") {
|
|
183672
183670
|
return fs2.existsSync(RESOLVER_FILE_MACOS);
|
|
183673
|
-
} else if (
|
|
183671
|
+
} else if (platform5 === "linux") {
|
|
183674
183672
|
return fs2.existsSync(RESOLVER_FILE_LINUX);
|
|
183675
183673
|
}
|
|
183676
183674
|
return false;
|
|
183677
183675
|
}
|
|
183678
183676
|
function getResolverInstallCommands(port) {
|
|
183679
|
-
const
|
|
183680
|
-
if (
|
|
183677
|
+
const platform5 = os2.platform();
|
|
183678
|
+
if (platform5 === "darwin") {
|
|
183681
183679
|
return [
|
|
183682
183680
|
"mkdir -p /etc/resolver",
|
|
183683
183681
|
`rm -f ${OLD_RESOLVER_FILE_MACOS}`,
|
|
183684
183682
|
`printf "nameserver 127.0.0.1\\nport ${port}\\n" > ${RESOLVER_FILE_MACOS}`
|
|
183685
183683
|
];
|
|
183686
|
-
} else if (
|
|
183684
|
+
} else if (platform5 === "linux") {
|
|
183687
183685
|
if (fs2.existsSync("/etc/systemd/resolved.conf.d") || fs2.existsSync("/etc/systemd")) {
|
|
183688
183686
|
return [
|
|
183689
183687
|
"mkdir -p /etc/systemd/resolved.conf.d",
|
|
@@ -183802,7 +183800,7 @@ function performSystemSetup() {
|
|
|
183802
183800
|
return;
|
|
183803
183801
|
}
|
|
183804
183802
|
try {
|
|
183805
|
-
|
|
183803
|
+
execSync2(`sudo sh -c '${commands.join(" && ")}'`, { stdio: "inherit" });
|
|
183806
183804
|
} catch (err) {
|
|
183807
183805
|
if (needsGenerate) {
|
|
183808
183806
|
removeCA();
|
|
@@ -183810,43 +183808,14 @@ function performSystemSetup() {
|
|
|
183810
183808
|
throw err;
|
|
183811
183809
|
}
|
|
183812
183810
|
}
|
|
183813
|
-
function execPrivileged(commands) {
|
|
183814
|
-
if (commands.length === 0) return;
|
|
183815
|
-
if (os4.platform() === "darwin") {
|
|
183816
|
-
const scriptPath = path3.join(os4.tmpdir(), "specific-setup.sh");
|
|
183817
|
-
const appPath = path3.join(os4.tmpdir(), "Specific.app");
|
|
183818
|
-
try {
|
|
183819
|
-
fs4.writeFileSync(
|
|
183820
|
-
scriptPath,
|
|
183821
|
-
"#!/bin/sh\nset -e\n" + commands.join("\n") + "\n",
|
|
183822
|
-
{ mode: 448 }
|
|
183823
|
-
);
|
|
183824
|
-
execSync2(
|
|
183825
|
-
`osacompile -o '${appPath}' -e 'do shell script "sh ${scriptPath}" with administrator privileges'`
|
|
183826
|
-
);
|
|
183827
|
-
execSync2(`'${appPath}/Contents/MacOS/applet'`, { stdio: "pipe" });
|
|
183828
|
-
} finally {
|
|
183829
|
-
try {
|
|
183830
|
-
fs4.unlinkSync(scriptPath);
|
|
183831
|
-
} catch {
|
|
183832
|
-
}
|
|
183833
|
-
try {
|
|
183834
|
-
fs4.rmSync(appPath, { recursive: true });
|
|
183835
|
-
} catch {
|
|
183836
|
-
}
|
|
183837
|
-
}
|
|
183838
|
-
} else {
|
|
183839
|
-
execSync2(`sudo sh -c '${commands.join(" && ")}'`, { stdio: "inherit" });
|
|
183840
|
-
}
|
|
183841
|
-
}
|
|
183842
183811
|
|
|
183843
183812
|
// src/lib/analytics/index.ts
|
|
183844
183813
|
import { PostHog } from "posthog-node";
|
|
183845
|
-
import * as
|
|
183814
|
+
import * as os6 from "os";
|
|
183846
183815
|
import * as crypto from "crypto";
|
|
183847
183816
|
|
|
183848
183817
|
// src/lib/project/config.ts
|
|
183849
|
-
import * as
|
|
183818
|
+
import * as fs4 from "fs";
|
|
183850
183819
|
import * as path4 from "path";
|
|
183851
183820
|
var PROJECT_ID_FILE = ".specific/project_id";
|
|
183852
183821
|
var ProjectNotLinkedError = class extends Error {
|
|
@@ -183863,10 +183832,10 @@ Run: specific deploy`
|
|
|
183863
183832
|
};
|
|
183864
183833
|
function readProjectId(projectDir = process.cwd()) {
|
|
183865
183834
|
const projectIdPath = path4.join(projectDir, PROJECT_ID_FILE);
|
|
183866
|
-
if (!
|
|
183835
|
+
if (!fs4.existsSync(projectIdPath)) {
|
|
183867
183836
|
throw new ProjectNotLinkedError();
|
|
183868
183837
|
}
|
|
183869
|
-
const projectId =
|
|
183838
|
+
const projectId = fs4.readFileSync(projectIdPath, "utf-8").trim();
|
|
183870
183839
|
if (!projectId) {
|
|
183871
183840
|
throw new Error(`${PROJECT_ID_FILE} is empty`);
|
|
183872
183841
|
}
|
|
@@ -183874,20 +183843,20 @@ function readProjectId(projectDir = process.cwd()) {
|
|
|
183874
183843
|
}
|
|
183875
183844
|
function hasProjectId(projectDir = process.cwd()) {
|
|
183876
183845
|
const projectIdPath = path4.join(projectDir, PROJECT_ID_FILE);
|
|
183877
|
-
return
|
|
183846
|
+
return fs4.existsSync(projectIdPath);
|
|
183878
183847
|
}
|
|
183879
183848
|
function writeProjectId(projectId, projectDir = process.cwd()) {
|
|
183880
183849
|
const specificDir = path4.join(projectDir, ".specific");
|
|
183881
|
-
if (!
|
|
183882
|
-
|
|
183850
|
+
if (!fs4.existsSync(specificDir)) {
|
|
183851
|
+
fs4.mkdirSync(specificDir, { recursive: true });
|
|
183883
183852
|
}
|
|
183884
|
-
|
|
183853
|
+
fs4.writeFileSync(path4.join(specificDir, "project_id"), projectId + "\n");
|
|
183885
183854
|
}
|
|
183886
183855
|
|
|
183887
183856
|
// src/lib/auth/credentials.ts
|
|
183888
|
-
import * as
|
|
183857
|
+
import * as fs10 from "fs";
|
|
183889
183858
|
import * as path6 from "path";
|
|
183890
|
-
import * as
|
|
183859
|
+
import * as os5 from "os";
|
|
183891
183860
|
|
|
183892
183861
|
// src/lib/auth/errors.ts
|
|
183893
183862
|
var RefreshTokenExpiredError = class extends Error {
|
|
@@ -184468,18 +184437,18 @@ var ApiClient = class {
|
|
|
184468
184437
|
|
|
184469
184438
|
// src/lib/auth/credentials.ts
|
|
184470
184439
|
function getUserCredentialsDir() {
|
|
184471
|
-
return path6.join(
|
|
184440
|
+
return path6.join(os5.homedir(), ".specific");
|
|
184472
184441
|
}
|
|
184473
184442
|
function getCredentialsPath() {
|
|
184474
184443
|
return path6.join(getUserCredentialsDir(), "credentials.json");
|
|
184475
184444
|
}
|
|
184476
184445
|
function readUserCredentials() {
|
|
184477
184446
|
const credentialsPath = getCredentialsPath();
|
|
184478
|
-
if (!
|
|
184447
|
+
if (!fs10.existsSync(credentialsPath)) {
|
|
184479
184448
|
return null;
|
|
184480
184449
|
}
|
|
184481
184450
|
try {
|
|
184482
|
-
const content =
|
|
184451
|
+
const content = fs10.readFileSync(credentialsPath, "utf-8");
|
|
184483
184452
|
return JSON.parse(content);
|
|
184484
184453
|
} catch {
|
|
184485
184454
|
return null;
|
|
@@ -184487,18 +184456,18 @@ function readUserCredentials() {
|
|
|
184487
184456
|
}
|
|
184488
184457
|
function writeUserCredentials(credentials) {
|
|
184489
184458
|
const dir = getUserCredentialsDir();
|
|
184490
|
-
if (!
|
|
184491
|
-
|
|
184459
|
+
if (!fs10.existsSync(dir)) {
|
|
184460
|
+
fs10.mkdirSync(dir, { recursive: true, mode: 448 });
|
|
184492
184461
|
}
|
|
184493
184462
|
const credentialsPath = getCredentialsPath();
|
|
184494
|
-
|
|
184463
|
+
fs10.writeFileSync(credentialsPath, JSON.stringify(credentials, null, 2), {
|
|
184495
184464
|
mode: 384
|
|
184496
184465
|
});
|
|
184497
184466
|
}
|
|
184498
184467
|
function clearUserCredentials() {
|
|
184499
184468
|
const credentialsPath = getCredentialsPath();
|
|
184500
|
-
if (
|
|
184501
|
-
|
|
184469
|
+
if (fs10.existsSync(credentialsPath)) {
|
|
184470
|
+
fs10.unlinkSync(credentialsPath);
|
|
184502
184471
|
}
|
|
184503
184472
|
}
|
|
184504
184473
|
function isLoggedIn() {
|
|
@@ -184577,7 +184546,7 @@ function isEnabled() {
|
|
|
184577
184546
|
}
|
|
184578
184547
|
function getAnonymousId() {
|
|
184579
184548
|
if (anonymousId) return anonymousId;
|
|
184580
|
-
const machineId = `${
|
|
184549
|
+
const machineId = `${os6.hostname()}-${os6.userInfo().username}`;
|
|
184581
184550
|
anonymousId = crypto.createHash("sha256").update(machineId).digest("hex").slice(0, 16);
|
|
184582
184551
|
return anonymousId;
|
|
184583
184552
|
}
|
|
@@ -184624,7 +184593,7 @@ function trackEvent(event, properties) {
|
|
|
184624
184593
|
event,
|
|
184625
184594
|
properties: {
|
|
184626
184595
|
...properties,
|
|
184627
|
-
cli_version: "0.1.
|
|
184596
|
+
cli_version: "0.1.77",
|
|
184628
184597
|
platform: process.platform,
|
|
184629
184598
|
node_version: process.version,
|
|
184630
184599
|
project_id: getProjectId()
|
|
@@ -184661,57 +184630,57 @@ var options = [
|
|
|
184661
184630
|
];
|
|
184662
184631
|
function isGitProject() {
|
|
184663
184632
|
const gitPath = path7.join(process.cwd(), ".git");
|
|
184664
|
-
return
|
|
184633
|
+
return fs11.existsSync(gitPath);
|
|
184665
184634
|
}
|
|
184666
184635
|
function detectExistingAgents() {
|
|
184667
184636
|
const detected = {};
|
|
184668
184637
|
const cursorDir = path7.join(process.cwd(), ".cursor");
|
|
184669
|
-
if (
|
|
184638
|
+
if (fs11.existsSync(cursorDir)) {
|
|
184670
184639
|
detected["cursor"] = true;
|
|
184671
184640
|
}
|
|
184672
184641
|
const claudeDir = path7.join(process.cwd(), ".claude");
|
|
184673
184642
|
const claudeMd = path7.join(process.cwd(), "CLAUDE.md");
|
|
184674
|
-
if (
|
|
184643
|
+
if (fs11.existsSync(claudeDir) || fs11.existsSync(claudeMd)) {
|
|
184675
184644
|
detected["claude"] = true;
|
|
184676
184645
|
}
|
|
184677
184646
|
const agentsMd = path7.join(process.cwd(), "AGENTS.md");
|
|
184678
|
-
if (
|
|
184647
|
+
if (fs11.existsSync(agentsMd)) {
|
|
184679
184648
|
detected["codex"] = true;
|
|
184680
184649
|
}
|
|
184681
184650
|
return detected;
|
|
184682
184651
|
}
|
|
184683
184652
|
function appendOrCreateFile(filePath, content) {
|
|
184684
|
-
if (
|
|
184685
|
-
const existing =
|
|
184653
|
+
if (fs11.existsSync(filePath)) {
|
|
184654
|
+
const existing = fs11.readFileSync(filePath, "utf-8");
|
|
184686
184655
|
if (existing.includes("specific docs") || existing.includes("specific check")) {
|
|
184687
184656
|
return "unchanged";
|
|
184688
184657
|
}
|
|
184689
184658
|
const separator = existing.endsWith("\n") ? "\n" : "\n\n";
|
|
184690
|
-
|
|
184659
|
+
fs11.writeFileSync(filePath, existing + separator + content + "\n");
|
|
184691
184660
|
return "modified";
|
|
184692
184661
|
} else {
|
|
184693
|
-
|
|
184662
|
+
fs11.writeFileSync(filePath, content + "\n");
|
|
184694
184663
|
return "created";
|
|
184695
184664
|
}
|
|
184696
184665
|
}
|
|
184697
184666
|
function addToGitignore() {
|
|
184698
184667
|
const gitignorePath = path7.join(process.cwd(), ".gitignore");
|
|
184699
184668
|
const entries = [".specific", "specific.local"];
|
|
184700
|
-
if (
|
|
184701
|
-
const existing =
|
|
184669
|
+
if (fs11.existsSync(gitignorePath)) {
|
|
184670
|
+
const existing = fs11.readFileSync(gitignorePath, "utf-8");
|
|
184702
184671
|
const lines = existing.split("\n").map((l) => l.trim());
|
|
184703
184672
|
const missingEntries = entries.filter((entry) => !lines.includes(entry));
|
|
184704
184673
|
if (missingEntries.length === 0) {
|
|
184705
184674
|
return "unchanged";
|
|
184706
184675
|
}
|
|
184707
184676
|
const separator = existing.endsWith("\n") ? "" : "\n";
|
|
184708
|
-
|
|
184677
|
+
fs11.writeFileSync(
|
|
184709
184678
|
gitignorePath,
|
|
184710
184679
|
existing + separator + missingEntries.join("\n") + "\n"
|
|
184711
184680
|
);
|
|
184712
184681
|
return "modified";
|
|
184713
184682
|
} else {
|
|
184714
|
-
|
|
184683
|
+
fs11.writeFileSync(gitignorePath, entries.join("\n") + "\n");
|
|
184715
184684
|
return "created";
|
|
184716
184685
|
}
|
|
184717
184686
|
}
|
|
@@ -184719,8 +184688,8 @@ function configureClaudeCodePermissions() {
|
|
|
184719
184688
|
const claudeDir = path7.join(process.cwd(), ".claude");
|
|
184720
184689
|
const settingsPath = path7.join(claudeDir, "settings.local.json");
|
|
184721
184690
|
const permissions = ["Bash(specific docs:*)", "Bash(specific check:*)"];
|
|
184722
|
-
if (
|
|
184723
|
-
const existing = JSON.parse(
|
|
184691
|
+
if (fs11.existsSync(settingsPath)) {
|
|
184692
|
+
const existing = JSON.parse(fs11.readFileSync(settingsPath, "utf-8"));
|
|
184724
184693
|
const allowList = existing?.permissions?.allow || [];
|
|
184725
184694
|
const missingPermissions = permissions.filter(
|
|
184726
184695
|
(p) => !allowList.includes(p)
|
|
@@ -184735,39 +184704,39 @@ function configureClaudeCodePermissions() {
|
|
|
184735
184704
|
existing.permissions.allow = [];
|
|
184736
184705
|
}
|
|
184737
184706
|
existing.permissions.allow.push(...missingPermissions);
|
|
184738
|
-
|
|
184707
|
+
fs11.writeFileSync(settingsPath, JSON.stringify(existing, null, 2) + "\n");
|
|
184739
184708
|
return "modified";
|
|
184740
184709
|
}
|
|
184741
|
-
if (!
|
|
184742
|
-
|
|
184710
|
+
if (!fs11.existsSync(claudeDir)) {
|
|
184711
|
+
fs11.mkdirSync(claudeDir);
|
|
184743
184712
|
}
|
|
184744
184713
|
const settings = {
|
|
184745
184714
|
permissions: {
|
|
184746
184715
|
allow: permissions
|
|
184747
184716
|
}
|
|
184748
184717
|
};
|
|
184749
|
-
|
|
184718
|
+
fs11.writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + "\n");
|
|
184750
184719
|
return "created";
|
|
184751
184720
|
}
|
|
184752
184721
|
function createCursorRule() {
|
|
184753
184722
|
const cursorDir = path7.join(process.cwd(), ".cursor");
|
|
184754
184723
|
const rulesDir = path7.join(cursorDir, "rules");
|
|
184755
184724
|
const mdcPath = path7.join(rulesDir, "specific.mdc");
|
|
184756
|
-
if (
|
|
184757
|
-
const existing =
|
|
184725
|
+
if (fs11.existsSync(mdcPath)) {
|
|
184726
|
+
const existing = fs11.readFileSync(mdcPath, "utf-8");
|
|
184758
184727
|
if (existing.includes("specific docs") || existing.includes("specific check")) {
|
|
184759
184728
|
return "unchanged";
|
|
184760
184729
|
}
|
|
184761
|
-
|
|
184730
|
+
fs11.writeFileSync(mdcPath, CURSOR_MDC_CONTENT);
|
|
184762
184731
|
return "modified";
|
|
184763
184732
|
}
|
|
184764
|
-
if (!
|
|
184765
|
-
|
|
184733
|
+
if (!fs11.existsSync(cursorDir)) {
|
|
184734
|
+
fs11.mkdirSync(cursorDir);
|
|
184766
184735
|
}
|
|
184767
|
-
if (!
|
|
184768
|
-
|
|
184736
|
+
if (!fs11.existsSync(rulesDir)) {
|
|
184737
|
+
fs11.mkdirSync(rulesDir);
|
|
184769
184738
|
}
|
|
184770
|
-
|
|
184739
|
+
fs11.writeFileSync(mdcPath, CURSOR_MDC_CONTENT);
|
|
184771
184740
|
return "created";
|
|
184772
184741
|
}
|
|
184773
184742
|
function configureAgents(checked) {
|
|
@@ -185010,7 +184979,7 @@ var BETA_REGISTRY = [
|
|
|
185010
184979
|
];
|
|
185011
184980
|
|
|
185012
184981
|
// src/lib/beta/storage.ts
|
|
185013
|
-
import { readFileSync as readFileSync5, writeFileSync as
|
|
184982
|
+
import { readFileSync as readFileSync5, writeFileSync as writeFileSync5, existsSync as existsSync6, mkdirSync as mkdirSync6 } from "fs";
|
|
185014
184983
|
import { join as join7 } from "path";
|
|
185015
184984
|
var BETAS_FILE = ".specific/betas.json";
|
|
185016
184985
|
function loadEnabledBetas(projectDir = process.cwd()) {
|
|
@@ -185043,7 +185012,7 @@ function saveBetas(enabled, projectDir) {
|
|
|
185043
185012
|
mkdirSync6(specificDir, { recursive: true });
|
|
185044
185013
|
}
|
|
185045
185014
|
const data = { enabled };
|
|
185046
|
-
|
|
185015
|
+
writeFileSync5(
|
|
185047
185016
|
join7(projectDir, BETAS_FILE),
|
|
185048
185017
|
JSON.stringify(data, null, 2) + "\n"
|
|
185049
185018
|
);
|
|
@@ -185110,7 +185079,7 @@ function resolveFilesystemDoc(path30) {
|
|
|
185110
185079
|
import React3, { useState as useState2, useEffect as useEffect2 } from "react";
|
|
185111
185080
|
import { render as render3, Text as Text3, Box as Box3 } from "ink";
|
|
185112
185081
|
import Spinner3 from "ink-spinner";
|
|
185113
|
-
import * as
|
|
185082
|
+
import * as fs13 from "fs";
|
|
185114
185083
|
import * as path9 from "path";
|
|
185115
185084
|
import { execFile as execFile7 } from "child_process";
|
|
185116
185085
|
|
|
@@ -185982,32 +185951,32 @@ var ExtractionError = class extends Error {
|
|
|
185982
185951
|
};
|
|
185983
185952
|
|
|
185984
185953
|
// src/lib/bin/manager.ts
|
|
185985
|
-
import * as
|
|
185954
|
+
import * as fs12 from "fs";
|
|
185986
185955
|
import * as path8 from "path";
|
|
185987
|
-
import * as
|
|
185956
|
+
import * as os7 from "os";
|
|
185988
185957
|
import { createReadStream } from "fs";
|
|
185989
185958
|
import { createTarExtractor, extractTo } from "tar-vern";
|
|
185990
185959
|
function getLibraryEnv(binary) {
|
|
185991
185960
|
if (!binary.libraryPath) {
|
|
185992
185961
|
return {};
|
|
185993
185962
|
}
|
|
185994
|
-
const
|
|
185995
|
-
if (
|
|
185963
|
+
const platform5 = os7.platform();
|
|
185964
|
+
if (platform5 === "darwin") {
|
|
185996
185965
|
return { DYLD_LIBRARY_PATH: binary.libraryPath };
|
|
185997
|
-
} else if (
|
|
185966
|
+
} else if (platform5 === "linux") {
|
|
185998
185967
|
return { LD_LIBRARY_PATH: binary.libraryPath };
|
|
185999
185968
|
}
|
|
186000
185969
|
return {};
|
|
186001
185970
|
}
|
|
186002
185971
|
function getBinBaseDir() {
|
|
186003
|
-
return path8.join(
|
|
185972
|
+
return path8.join(os7.homedir(), ".specific", "bin");
|
|
186004
185973
|
}
|
|
186005
185974
|
function getPlatformInfo() {
|
|
186006
|
-
const
|
|
186007
|
-
const arch3 =
|
|
186008
|
-
if (
|
|
185975
|
+
const platform5 = os7.platform();
|
|
185976
|
+
const arch3 = os7.arch();
|
|
185977
|
+
if (platform5 !== "darwin" && platform5 !== "linux") {
|
|
186009
185978
|
throw new Error(
|
|
186010
|
-
`Unsupported platform: ${
|
|
185979
|
+
`Unsupported platform: ${platform5}. Only macOS and Linux are supported.`
|
|
186011
185980
|
);
|
|
186012
185981
|
}
|
|
186013
185982
|
const archStr = arch3;
|
|
@@ -186021,7 +185990,7 @@ function getPlatformInfo() {
|
|
|
186021
185990
|
`Unsupported architecture: ${arch3}. Only x64 and arm64 are supported.`
|
|
186022
185991
|
);
|
|
186023
185992
|
}
|
|
186024
|
-
return { platform:
|
|
185993
|
+
return { platform: platform5, arch: mappedArch };
|
|
186025
185994
|
}
|
|
186026
185995
|
function getBinaryDir(definition, version, platformInfo) {
|
|
186027
185996
|
return path8.join(
|
|
@@ -186035,7 +186004,7 @@ function isBinaryInstalled(definition, version, platformInfo) {
|
|
|
186035
186004
|
const binDir = getBinaryDir(definition, version, platformInfo);
|
|
186036
186005
|
for (const execPath of definition.executables) {
|
|
186037
186006
|
const fullPath = path8.join(binDir, execPath);
|
|
186038
|
-
if (!
|
|
186007
|
+
if (!fs12.existsSync(fullPath)) {
|
|
186039
186008
|
return false;
|
|
186040
186009
|
}
|
|
186041
186010
|
}
|
|
@@ -186064,11 +186033,11 @@ async function downloadFile(url, destPath, onProgress) {
|
|
|
186064
186033
|
);
|
|
186065
186034
|
let bytesDownloaded = 0;
|
|
186066
186035
|
const parentDir = path8.dirname(destPath);
|
|
186067
|
-
if (!
|
|
186068
|
-
|
|
186036
|
+
if (!fs12.existsSync(parentDir)) {
|
|
186037
|
+
fs12.mkdirSync(parentDir, { recursive: true });
|
|
186069
186038
|
}
|
|
186070
186039
|
const partPath = destPath + ".part";
|
|
186071
|
-
const fileStream =
|
|
186040
|
+
const fileStream = fs12.createWriteStream(partPath);
|
|
186072
186041
|
try {
|
|
186073
186042
|
const reader = response.body.getReader();
|
|
186074
186043
|
while (true) {
|
|
@@ -186091,12 +186060,12 @@ async function downloadFile(url, destPath, onProgress) {
|
|
|
186091
186060
|
else resolve9();
|
|
186092
186061
|
});
|
|
186093
186062
|
});
|
|
186094
|
-
|
|
186063
|
+
fs12.renameSync(partPath, destPath);
|
|
186095
186064
|
} catch (error) {
|
|
186096
186065
|
try {
|
|
186097
186066
|
fileStream.close();
|
|
186098
|
-
if (
|
|
186099
|
-
|
|
186067
|
+
if (fs12.existsSync(partPath)) {
|
|
186068
|
+
fs12.unlinkSync(partPath);
|
|
186100
186069
|
}
|
|
186101
186070
|
} catch {
|
|
186102
186071
|
}
|
|
@@ -186105,8 +186074,8 @@ async function downloadFile(url, destPath, onProgress) {
|
|
|
186105
186074
|
}
|
|
186106
186075
|
async function extractTarball(archivePath, destDir, definition, onProgress) {
|
|
186107
186076
|
onProgress?.({ phase: "extracting" });
|
|
186108
|
-
if (!
|
|
186109
|
-
|
|
186077
|
+
if (!fs12.existsSync(destDir)) {
|
|
186078
|
+
fs12.mkdirSync(destDir, { recursive: true });
|
|
186110
186079
|
}
|
|
186111
186080
|
try {
|
|
186112
186081
|
const fileStream = createReadStream(archivePath);
|
|
@@ -186115,8 +186084,8 @@ async function extractTarball(archivePath, destDir, definition, onProgress) {
|
|
|
186115
186084
|
onProgress?.({ phase: "finalizing" });
|
|
186116
186085
|
for (const execPath of definition.executables) {
|
|
186117
186086
|
const fullPath = path8.join(destDir, execPath);
|
|
186118
|
-
if (
|
|
186119
|
-
|
|
186087
|
+
if (fs12.existsSync(fullPath)) {
|
|
186088
|
+
fs12.chmodSync(fullPath, 493);
|
|
186120
186089
|
}
|
|
186121
186090
|
}
|
|
186122
186091
|
} catch (error) {
|
|
@@ -186140,12 +186109,12 @@ async function ensureBinary(definition, version, onProgress) {
|
|
|
186140
186109
|
`Binary type definitions must have exactly one executable, got ${definition.executables.length}`
|
|
186141
186110
|
);
|
|
186142
186111
|
}
|
|
186143
|
-
if (!
|
|
186144
|
-
|
|
186112
|
+
if (!fs12.existsSync(binDir)) {
|
|
186113
|
+
fs12.mkdirSync(binDir, { recursive: true });
|
|
186145
186114
|
}
|
|
186146
186115
|
const execPath = path8.join(binDir, definition.executables[0]);
|
|
186147
186116
|
await downloadFile(url, execPath, onProgress);
|
|
186148
|
-
|
|
186117
|
+
fs12.chmodSync(execPath, 493);
|
|
186149
186118
|
onProgress?.({ phase: "finalizing" });
|
|
186150
186119
|
} else {
|
|
186151
186120
|
const downloadDir = path8.join(getBinBaseDir(), "downloads");
|
|
@@ -186156,8 +186125,8 @@ async function ensureBinary(definition, version, onProgress) {
|
|
|
186156
186125
|
await extractTarball(archivePath, binDir, definition, onProgress);
|
|
186157
186126
|
} finally {
|
|
186158
186127
|
try {
|
|
186159
|
-
if (
|
|
186160
|
-
|
|
186128
|
+
if (fs12.existsSync(archivePath)) {
|
|
186129
|
+
fs12.unlinkSync(archivePath);
|
|
186161
186130
|
}
|
|
186162
186131
|
} catch {
|
|
186163
186132
|
}
|
|
@@ -186333,20 +186302,20 @@ function CheckUI() {
|
|
|
186333
186302
|
useEffect2(() => {
|
|
186334
186303
|
async function load() {
|
|
186335
186304
|
const configPath = path9.join(process.cwd(), "specific.hcl");
|
|
186336
|
-
if (!
|
|
186305
|
+
if (!fs13.existsSync(configPath)) {
|
|
186337
186306
|
setState({
|
|
186338
186307
|
status: "error",
|
|
186339
186308
|
error: "No specific.hcl found in current directory"
|
|
186340
186309
|
});
|
|
186341
186310
|
return;
|
|
186342
186311
|
}
|
|
186343
|
-
const hcl =
|
|
186312
|
+
const hcl = fs13.readFileSync(configPath, "utf-8");
|
|
186344
186313
|
try {
|
|
186345
186314
|
const config2 = await parseConfig(hcl);
|
|
186346
186315
|
for (const build of config2.builds) {
|
|
186347
186316
|
if (build.dockerfile) {
|
|
186348
186317
|
const dockerfilePath = path9.resolve(process.cwd(), build.dockerfile);
|
|
186349
|
-
if (!
|
|
186318
|
+
if (!fs13.existsSync(dockerfilePath)) {
|
|
186350
186319
|
setState({
|
|
186351
186320
|
status: "error",
|
|
186352
186321
|
error: `Build "${build.name}": Dockerfile not found at "${build.dockerfile}" (resolved to ${dockerfilePath})`
|
|
@@ -186362,7 +186331,7 @@ function CheckUI() {
|
|
|
186362
186331
|
process.cwd(),
|
|
186363
186332
|
pg.reshape.migrations_dir ?? "migrations"
|
|
186364
186333
|
);
|
|
186365
|
-
if (!
|
|
186334
|
+
if (!fs13.existsSync(migrationsDir)) {
|
|
186366
186335
|
reshapeChecks2.push({
|
|
186367
186336
|
databaseName: pg.name,
|
|
186368
186337
|
migrationsDir: pg.reshape.migrations_dir ?? "migrations",
|
|
@@ -186415,7 +186384,7 @@ function checkCommand() {
|
|
|
186415
186384
|
import React6, { useState as useState5, useEffect as useEffect3, useRef } from "react";
|
|
186416
186385
|
import { render as render4, Text as Text6, Box as Box6, useApp as useApp2, Static, useInput as useInput4 } from "ink";
|
|
186417
186386
|
import Spinner4 from "ink-spinner";
|
|
186418
|
-
import * as
|
|
186387
|
+
import * as fs23 from "fs";
|
|
186419
186388
|
import * as path20 from "path";
|
|
186420
186389
|
|
|
186421
186390
|
// node_modules/.pnpm/chokidar@5.0.0/node_modules/chokidar/index.js
|
|
@@ -188170,7 +188139,7 @@ var PortAllocator = class {
|
|
|
188170
188139
|
};
|
|
188171
188140
|
|
|
188172
188141
|
// src/lib/dev/stable-port-allocator.ts
|
|
188173
|
-
import * as
|
|
188142
|
+
import * as fs14 from "fs";
|
|
188174
188143
|
import * as path10 from "path";
|
|
188175
188144
|
var PORT_RANGE_START2 = 4e4;
|
|
188176
188145
|
var PORT_RANGE_END2 = 49999;
|
|
@@ -188185,11 +188154,11 @@ var StablePortAllocator = class {
|
|
|
188185
188154
|
this.loadPorts();
|
|
188186
188155
|
}
|
|
188187
188156
|
loadPorts() {
|
|
188188
|
-
if (!
|
|
188157
|
+
if (!fs14.existsSync(this.portsFilePath)) {
|
|
188189
188158
|
return;
|
|
188190
188159
|
}
|
|
188191
188160
|
try {
|
|
188192
|
-
const content =
|
|
188161
|
+
const content = fs14.readFileSync(this.portsFilePath, "utf-8");
|
|
188193
188162
|
const data = JSON.parse(content);
|
|
188194
188163
|
if (data.version === 1 && data.ports) {
|
|
188195
188164
|
this.savedPorts = data.ports;
|
|
@@ -188202,14 +188171,14 @@ var StablePortAllocator = class {
|
|
|
188202
188171
|
}
|
|
188203
188172
|
}
|
|
188204
188173
|
savePorts() {
|
|
188205
|
-
if (!
|
|
188206
|
-
|
|
188174
|
+
if (!fs14.existsSync(this.portsDir)) {
|
|
188175
|
+
fs14.mkdirSync(this.portsDir, { recursive: true });
|
|
188207
188176
|
}
|
|
188208
188177
|
const data = {
|
|
188209
188178
|
version: 1,
|
|
188210
188179
|
ports: this.savedPorts
|
|
188211
188180
|
};
|
|
188212
|
-
|
|
188181
|
+
fs14.writeFileSync(this.portsFilePath, JSON.stringify(data, null, 2));
|
|
188213
188182
|
}
|
|
188214
188183
|
allocateRandom() {
|
|
188215
188184
|
const rangeSize = PORT_RANGE_END2 - PORT_RANGE_START2 + 1;
|
|
@@ -188236,7 +188205,7 @@ var StablePortAllocator = class {
|
|
|
188236
188205
|
};
|
|
188237
188206
|
|
|
188238
188207
|
// src/lib/dev/database-manager.ts
|
|
188239
|
-
import * as
|
|
188208
|
+
import * as fs15 from "fs";
|
|
188240
188209
|
import * as path11 from "path";
|
|
188241
188210
|
import * as net from "net";
|
|
188242
188211
|
import { spawn } from "child_process";
|
|
@@ -188248,9 +188217,9 @@ async function startPostgres(pg, port, dataDir, onProgress) {
|
|
|
188248
188217
|
const password = "postgres";
|
|
188249
188218
|
const libraryEnv = getLibraryEnv(binary);
|
|
188250
188219
|
const env2 = { ...process.env, ...libraryEnv };
|
|
188251
|
-
const dataExists =
|
|
188220
|
+
const dataExists = fs15.existsSync(dbDataPath);
|
|
188252
188221
|
if (!dataExists) {
|
|
188253
|
-
|
|
188222
|
+
fs15.mkdirSync(dbDataPath, { recursive: true });
|
|
188254
188223
|
await runCommand(
|
|
188255
188224
|
binary.executables["initdb"],
|
|
188256
188225
|
["-D", dbDataPath, "-U", user, "--auth=trust", "--no-locale", "-E", "UTF8"],
|
|
@@ -188327,8 +188296,8 @@ async function startRedis(redis, port, onProgress) {
|
|
|
188327
188296
|
async function startStorage(storage, port, dataDir) {
|
|
188328
188297
|
const S3rver = (await import("s3rver")).default;
|
|
188329
188298
|
const storageDataPath = path11.join(process.cwd(), dataDir, storage.name);
|
|
188330
|
-
if (!
|
|
188331
|
-
|
|
188299
|
+
if (!fs15.existsSync(storageDataPath)) {
|
|
188300
|
+
fs15.mkdirSync(storageDataPath, { recursive: true });
|
|
188332
188301
|
}
|
|
188333
188302
|
const host = "127.0.0.1";
|
|
188334
188303
|
const accessKey = "S3RVER";
|
|
@@ -188971,7 +188940,7 @@ function startService(service, resources, secrets, configs, endpointPorts, servi
|
|
|
188971
188940
|
}
|
|
188972
188941
|
|
|
188973
188942
|
// src/lib/dev/instance-state.ts
|
|
188974
|
-
import * as
|
|
188943
|
+
import * as fs16 from "fs";
|
|
188975
188944
|
import * as path12 from "path";
|
|
188976
188945
|
var InstanceStateManager = class {
|
|
188977
188946
|
stateDir;
|
|
@@ -188989,8 +188958,8 @@ var InstanceStateManager = class {
|
|
|
188989
188958
|
return this.key;
|
|
188990
188959
|
}
|
|
188991
188960
|
ensureStateDir() {
|
|
188992
|
-
if (!
|
|
188993
|
-
|
|
188961
|
+
if (!fs16.existsSync(this.stateDir)) {
|
|
188962
|
+
fs16.mkdirSync(this.stateDir, { recursive: true });
|
|
188994
188963
|
}
|
|
188995
188964
|
}
|
|
188996
188965
|
isProcessRunning(pid) {
|
|
@@ -189007,15 +188976,15 @@ var InstanceStateManager = class {
|
|
|
189007
188976
|
const startTime = Date.now();
|
|
189008
188977
|
while (Date.now() - startTime < timeoutMs) {
|
|
189009
188978
|
try {
|
|
189010
|
-
const fd =
|
|
188979
|
+
const fd = fs16.openSync(
|
|
189011
188980
|
this.lockPath,
|
|
189012
|
-
|
|
188981
|
+
fs16.constants.O_CREAT | fs16.constants.O_EXCL | fs16.constants.O_WRONLY
|
|
189013
188982
|
);
|
|
189014
|
-
|
|
189015
|
-
|
|
188983
|
+
fs16.writeSync(fd, String(process.pid));
|
|
188984
|
+
fs16.closeSync(fd);
|
|
189016
188985
|
return () => {
|
|
189017
188986
|
try {
|
|
189018
|
-
|
|
188987
|
+
fs16.unlinkSync(this.lockPath);
|
|
189019
188988
|
} catch {
|
|
189020
188989
|
}
|
|
189021
188990
|
};
|
|
@@ -189024,16 +188993,16 @@ var InstanceStateManager = class {
|
|
|
189024
188993
|
if (err.code === "EEXIST") {
|
|
189025
188994
|
try {
|
|
189026
188995
|
const lockPid = parseInt(
|
|
189027
|
-
|
|
188996
|
+
fs16.readFileSync(this.lockPath, "utf-8").trim(),
|
|
189028
188997
|
10
|
|
189029
188998
|
);
|
|
189030
188999
|
if (!this.isProcessRunning(lockPid)) {
|
|
189031
|
-
|
|
189000
|
+
fs16.unlinkSync(this.lockPath);
|
|
189032
189001
|
continue;
|
|
189033
189002
|
}
|
|
189034
189003
|
} catch {
|
|
189035
189004
|
try {
|
|
189036
|
-
|
|
189005
|
+
fs16.unlinkSync(this.lockPath);
|
|
189037
189006
|
} catch {
|
|
189038
189007
|
}
|
|
189039
189008
|
continue;
|
|
@@ -189047,12 +189016,12 @@ var InstanceStateManager = class {
|
|
|
189047
189016
|
throw new Error("Failed to acquire state lock (timeout)");
|
|
189048
189017
|
}
|
|
189049
189018
|
async getExistingInstances() {
|
|
189050
|
-
if (!
|
|
189019
|
+
if (!fs16.existsSync(this.statePath)) {
|
|
189051
189020
|
return null;
|
|
189052
189021
|
}
|
|
189053
189022
|
const releaseLock = await this.acquireLock();
|
|
189054
189023
|
try {
|
|
189055
|
-
const content =
|
|
189024
|
+
const content = fs16.readFileSync(this.statePath, "utf-8");
|
|
189056
189025
|
const state = JSON.parse(content);
|
|
189057
189026
|
if (!this.isProcessRunning(state.owner.pid)) {
|
|
189058
189027
|
return null;
|
|
@@ -189065,21 +189034,21 @@ var InstanceStateManager = class {
|
|
|
189065
189034
|
}
|
|
189066
189035
|
}
|
|
189067
189036
|
async cleanStaleState() {
|
|
189068
|
-
if (!
|
|
189037
|
+
if (!fs16.existsSync(this.statePath)) {
|
|
189069
189038
|
return false;
|
|
189070
189039
|
}
|
|
189071
189040
|
const releaseLock = await this.acquireLock();
|
|
189072
189041
|
try {
|
|
189073
|
-
const content =
|
|
189042
|
+
const content = fs16.readFileSync(this.statePath, "utf-8");
|
|
189074
189043
|
const state = JSON.parse(content);
|
|
189075
189044
|
if (!this.isProcessRunning(state.owner.pid)) {
|
|
189076
|
-
|
|
189045
|
+
fs16.unlinkSync(this.statePath);
|
|
189077
189046
|
return true;
|
|
189078
189047
|
}
|
|
189079
189048
|
return false;
|
|
189080
189049
|
} catch {
|
|
189081
189050
|
try {
|
|
189082
|
-
|
|
189051
|
+
fs16.unlinkSync(this.statePath);
|
|
189083
189052
|
return true;
|
|
189084
189053
|
} catch {
|
|
189085
189054
|
}
|
|
@@ -189091,8 +189060,8 @@ var InstanceStateManager = class {
|
|
|
189091
189060
|
async claimOwnership(command) {
|
|
189092
189061
|
const releaseLock = await this.acquireLock();
|
|
189093
189062
|
try {
|
|
189094
|
-
if (
|
|
189095
|
-
const content =
|
|
189063
|
+
if (fs16.existsSync(this.statePath)) {
|
|
189064
|
+
const content = fs16.readFileSync(this.statePath, "utf-8");
|
|
189096
189065
|
const state2 = JSON.parse(content);
|
|
189097
189066
|
if (this.isProcessRunning(state2.owner.pid)) {
|
|
189098
189067
|
throw new Error(`Instances already owned by PID ${state2.owner.pid}`);
|
|
@@ -189161,8 +189130,8 @@ var InstanceStateManager = class {
|
|
|
189161
189130
|
}
|
|
189162
189131
|
const releaseLock = await this.acquireLock();
|
|
189163
189132
|
try {
|
|
189164
|
-
if (
|
|
189165
|
-
|
|
189133
|
+
if (fs16.existsSync(this.statePath)) {
|
|
189134
|
+
fs16.unlinkSync(this.statePath);
|
|
189166
189135
|
}
|
|
189167
189136
|
this.ownsInstances = false;
|
|
189168
189137
|
} finally {
|
|
@@ -189170,21 +189139,21 @@ var InstanceStateManager = class {
|
|
|
189170
189139
|
}
|
|
189171
189140
|
}
|
|
189172
189141
|
readState() {
|
|
189173
|
-
const content =
|
|
189142
|
+
const content = fs16.readFileSync(this.statePath, "utf-8");
|
|
189174
189143
|
return JSON.parse(content);
|
|
189175
189144
|
}
|
|
189176
189145
|
writeStateAtomic(state) {
|
|
189177
189146
|
this.ensureStateDir();
|
|
189178
189147
|
const tmpPath = this.statePath + ".tmp";
|
|
189179
|
-
|
|
189180
|
-
|
|
189148
|
+
fs16.writeFileSync(tmpPath, JSON.stringify(state, null, 2));
|
|
189149
|
+
fs16.renameSync(tmpPath, this.statePath);
|
|
189181
189150
|
}
|
|
189182
189151
|
};
|
|
189183
189152
|
|
|
189184
189153
|
// src/lib/dev/http-proxy.ts
|
|
189185
189154
|
import * as http from "http";
|
|
189186
189155
|
import * as https from "https";
|
|
189187
|
-
import * as
|
|
189156
|
+
import * as fs17 from "fs";
|
|
189188
189157
|
import * as path13 from "path";
|
|
189189
189158
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
189190
189159
|
import httpProxy from "http-proxy";
|
|
@@ -189592,10 +189561,10 @@ function serveFilesystemFile(res, pathname) {
|
|
|
189592
189561
|
res.end("<h1>Forbidden</h1>");
|
|
189593
189562
|
return;
|
|
189594
189563
|
}
|
|
189595
|
-
if (
|
|
189596
|
-
if (
|
|
189564
|
+
if (fs17.existsSync(resolvedPath)) {
|
|
189565
|
+
if (fs17.statSync(resolvedPath).isDirectory()) {
|
|
189597
189566
|
const indexPath2 = path13.join(resolvedPath, "index.html");
|
|
189598
|
-
if (
|
|
189567
|
+
if (fs17.existsSync(indexPath2)) {
|
|
189599
189568
|
return serveFile(res, indexPath2);
|
|
189600
189569
|
}
|
|
189601
189570
|
} else {
|
|
@@ -189603,15 +189572,15 @@ function serveFilesystemFile(res, pathname) {
|
|
|
189603
189572
|
}
|
|
189604
189573
|
}
|
|
189605
189574
|
const htmlPath = resolvedPath + ".html";
|
|
189606
|
-
if (
|
|
189575
|
+
if (fs17.existsSync(htmlPath)) {
|
|
189607
189576
|
return serveFile(res, htmlPath);
|
|
189608
189577
|
}
|
|
189609
189578
|
const indexPath = path13.join(resolvedPath, "index.html");
|
|
189610
|
-
if (
|
|
189579
|
+
if (fs17.existsSync(indexPath)) {
|
|
189611
189580
|
return serveFile(res, indexPath);
|
|
189612
189581
|
}
|
|
189613
189582
|
const notFoundPath = path13.join(adminDir, "404.html");
|
|
189614
|
-
if (
|
|
189583
|
+
if (fs17.existsSync(notFoundPath)) {
|
|
189615
189584
|
return serveFileContent(res, notFoundPath, "text/html", 404);
|
|
189616
189585
|
}
|
|
189617
189586
|
res.writeHead(404, { "Content-Type": "text/html" });
|
|
@@ -189624,7 +189593,7 @@ function serveFile(res, filePath) {
|
|
|
189624
189593
|
}
|
|
189625
189594
|
function serveFileContent(res, filePath, contentType, statusCode = 200) {
|
|
189626
189595
|
try {
|
|
189627
|
-
const content =
|
|
189596
|
+
const content = fs17.readFileSync(filePath);
|
|
189628
189597
|
res.writeHead(statusCode, { "Content-Type": contentType });
|
|
189629
189598
|
res.end(content);
|
|
189630
189599
|
} catch (err) {
|
|
@@ -189999,7 +189968,7 @@ async function startMailServer(mail, smtpPort, apiPort) {
|
|
|
189999
189968
|
|
|
190000
189969
|
// src/lib/dev/drizzle-gateway-manager.ts
|
|
190001
189970
|
import * as net3 from "net";
|
|
190002
|
-
import * as
|
|
189971
|
+
import * as fs18 from "fs";
|
|
190003
189972
|
import * as path15 from "path";
|
|
190004
189973
|
import { spawn as spawn4 } from "child_process";
|
|
190005
189974
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
@@ -190033,12 +190002,12 @@ async function startDrizzleGateway(postgresInstances, port, configDir, options2)
|
|
|
190033
190002
|
);
|
|
190034
190003
|
const host = "127.0.0.1";
|
|
190035
190004
|
const drizzleConfigDir = path15.join(configDir, "drizzle-gateway");
|
|
190036
|
-
if (!
|
|
190037
|
-
|
|
190005
|
+
if (!fs18.existsSync(drizzleConfigDir)) {
|
|
190006
|
+
fs18.mkdirSync(drizzleConfigDir, { recursive: true });
|
|
190038
190007
|
}
|
|
190039
190008
|
const storeJson = generateStoreJson(postgresInstances);
|
|
190040
190009
|
const storeJsonPath = path15.join(drizzleConfigDir, "store.json");
|
|
190041
|
-
|
|
190010
|
+
fs18.writeFileSync(storeJsonPath, JSON.stringify(storeJson, null, 2));
|
|
190042
190011
|
writeLog("drizzle-gateway", `Starting Drizzle Gateway`);
|
|
190043
190012
|
writeLog("drizzle-gateway", `STORE_PATH: ${drizzleConfigDir}`);
|
|
190044
190013
|
writeLog("drizzle-gateway", `PORT: ${port}`);
|
|
@@ -190140,16 +190109,16 @@ function detectSyncDatabases(config) {
|
|
|
190140
190109
|
}
|
|
190141
190110
|
|
|
190142
190111
|
// src/lib/dev/reshape-watcher.ts
|
|
190143
|
-
import * as
|
|
190112
|
+
import * as fs19 from "fs";
|
|
190144
190113
|
import * as path16 from "path";
|
|
190145
190114
|
import { spawnSync } from "child_process";
|
|
190146
190115
|
function getMigrationFiles(dir, log) {
|
|
190147
190116
|
log(`Scanning migrations directory: ${dir}`);
|
|
190148
|
-
if (!
|
|
190117
|
+
if (!fs19.existsSync(dir)) {
|
|
190149
190118
|
log(`Migrations directory does not exist: ${dir}`);
|
|
190150
190119
|
return [];
|
|
190151
190120
|
}
|
|
190152
|
-
const files =
|
|
190121
|
+
const files = fs19.readdirSync(dir);
|
|
190153
190122
|
log(`Found ${files.length} files in directory`);
|
|
190154
190123
|
const tomlFiles = files.filter((f) => f.endsWith(".toml")).sort((a, b) => a.localeCompare(b));
|
|
190155
190124
|
log(`Found ${tomlFiles.length} .toml migration files: ${tomlFiles.join(", ") || "(none)"}`);
|
|
@@ -190199,7 +190168,7 @@ function runReshape(args, databaseUrl, migrationsDir, reshapeBinaryPath, log) {
|
|
|
190199
190168
|
}
|
|
190200
190169
|
function makeReadOnly(filePath, log) {
|
|
190201
190170
|
try {
|
|
190202
|
-
|
|
190171
|
+
fs19.chmodSync(filePath, 292);
|
|
190203
190172
|
log(`Set file permissions to read-only (444): ${filePath}`);
|
|
190204
190173
|
} catch (err) {
|
|
190205
190174
|
const message = err instanceof Error ? err.message : String(err);
|
|
@@ -190285,9 +190254,9 @@ function createReshapeWatcher(options2) {
|
|
|
190285
190254
|
};
|
|
190286
190255
|
const startWatching = () => {
|
|
190287
190256
|
log(`Starting file watcher for migrations directory...`);
|
|
190288
|
-
if (!
|
|
190257
|
+
if (!fs19.existsSync(migrationsDir)) {
|
|
190289
190258
|
log(`Migrations directory does not exist, creating: ${migrationsDir}`);
|
|
190290
|
-
|
|
190259
|
+
fs19.mkdirSync(migrationsDir, { recursive: true });
|
|
190291
190260
|
}
|
|
190292
190261
|
log(`Watching directory: ${migrationsDir}`);
|
|
190293
190262
|
watcher = chokidar_default.watch(migrationsDir, {
|
|
@@ -190422,7 +190391,7 @@ function createReshapeWatcher(options2) {
|
|
|
190422
190391
|
}
|
|
190423
190392
|
|
|
190424
190393
|
// src/lib/dev/temporal-manager.ts
|
|
190425
|
-
import * as
|
|
190394
|
+
import * as fs20 from "fs";
|
|
190426
190395
|
import * as path17 from "path";
|
|
190427
190396
|
import * as net4 from "net";
|
|
190428
190397
|
import { spawn as spawn5 } from "child_process";
|
|
@@ -190430,8 +190399,8 @@ async function startTemporalDevServer(temporals, grpcPort, uiPort, dataDir, onPr
|
|
|
190430
190399
|
const binary = await ensureBinary(temporalBinary, void 0, onProgress);
|
|
190431
190400
|
const dbPath = path17.join(process.cwd(), dataDir, "temporal.db");
|
|
190432
190401
|
const dbDir = path17.dirname(dbPath);
|
|
190433
|
-
if (!
|
|
190434
|
-
|
|
190402
|
+
if (!fs20.existsSync(dbDir)) {
|
|
190403
|
+
fs20.mkdirSync(dbDir, { recursive: true });
|
|
190435
190404
|
}
|
|
190436
190405
|
const host = "127.0.0.1";
|
|
190437
190406
|
const namespaceArgs = temporals.flatMap((t) => ["--namespace", t.name]);
|
|
@@ -190760,7 +190729,7 @@ function watchConfigFile(configPath, debounceMs, onChange) {
|
|
|
190760
190729
|
}
|
|
190761
190730
|
|
|
190762
190731
|
// src/lib/dev/subdomain-generator.ts
|
|
190763
|
-
import * as
|
|
190732
|
+
import * as fs21 from "fs";
|
|
190764
190733
|
import * as path18 from "path";
|
|
190765
190734
|
import { generateSlug } from "random-word-slugs";
|
|
190766
190735
|
var StableSubdomainAllocator = class {
|
|
@@ -190773,11 +190742,11 @@ var StableSubdomainAllocator = class {
|
|
|
190773
190742
|
this.loadTunnels();
|
|
190774
190743
|
}
|
|
190775
190744
|
loadTunnels() {
|
|
190776
|
-
if (!
|
|
190745
|
+
if (!fs21.existsSync(this.tunnelsFilePath)) {
|
|
190777
190746
|
return;
|
|
190778
190747
|
}
|
|
190779
190748
|
try {
|
|
190780
|
-
const content =
|
|
190749
|
+
const content = fs21.readFileSync(this.tunnelsFilePath, "utf-8");
|
|
190781
190750
|
const data = JSON.parse(content);
|
|
190782
190751
|
if (data.version === 1 && data.baseSlug) {
|
|
190783
190752
|
this.baseSlug = data.baseSlug;
|
|
@@ -190787,14 +190756,14 @@ var StableSubdomainAllocator = class {
|
|
|
190787
190756
|
}
|
|
190788
190757
|
}
|
|
190789
190758
|
saveTunnels() {
|
|
190790
|
-
if (!
|
|
190791
|
-
|
|
190759
|
+
if (!fs21.existsSync(this.tunnelsDir)) {
|
|
190760
|
+
fs21.mkdirSync(this.tunnelsDir, { recursive: true });
|
|
190792
190761
|
}
|
|
190793
190762
|
const data = {
|
|
190794
190763
|
version: 1,
|
|
190795
190764
|
baseSlug: this.baseSlug
|
|
190796
190765
|
};
|
|
190797
|
-
|
|
190766
|
+
fs21.writeFileSync(this.tunnelsFilePath, JSON.stringify(data, null, 2));
|
|
190798
190767
|
}
|
|
190799
190768
|
generateBaseSlug() {
|
|
190800
190769
|
return generateSlug(2, {
|
|
@@ -190950,9 +190919,9 @@ async function startTunnel(serviceName, endpointName, port, subdomain, callbacks
|
|
|
190950
190919
|
}
|
|
190951
190920
|
|
|
190952
190921
|
// src/lib/dev/proxy-registry.ts
|
|
190953
|
-
import * as
|
|
190922
|
+
import * as fs22 from "fs";
|
|
190954
190923
|
import * as path19 from "path";
|
|
190955
|
-
import * as
|
|
190924
|
+
import * as os8 from "os";
|
|
190956
190925
|
import * as net6 from "net";
|
|
190957
190926
|
var ProxyRegistryManager = class {
|
|
190958
190927
|
proxyDir;
|
|
@@ -190962,14 +190931,14 @@ var ProxyRegistryManager = class {
|
|
|
190962
190931
|
isOwner = false;
|
|
190963
190932
|
registryWatcher = null;
|
|
190964
190933
|
constructor() {
|
|
190965
|
-
this.proxyDir = path19.join(
|
|
190934
|
+
this.proxyDir = path19.join(os8.homedir(), ".specific", "proxy");
|
|
190966
190935
|
this.ownerPath = path19.join(this.proxyDir, "owner.json");
|
|
190967
190936
|
this.registryPath = path19.join(this.proxyDir, "registry.json");
|
|
190968
190937
|
this.lockPath = path19.join(this.proxyDir, "registry.lock");
|
|
190969
190938
|
}
|
|
190970
190939
|
ensureProxyDir() {
|
|
190971
|
-
if (!
|
|
190972
|
-
|
|
190940
|
+
if (!fs22.existsSync(this.proxyDir)) {
|
|
190941
|
+
fs22.mkdirSync(this.proxyDir, { recursive: true });
|
|
190973
190942
|
}
|
|
190974
190943
|
}
|
|
190975
190944
|
isProcessRunning(pid) {
|
|
@@ -191026,15 +190995,15 @@ var ProxyRegistryManager = class {
|
|
|
191026
190995
|
const startTime = Date.now();
|
|
191027
190996
|
while (Date.now() - startTime < timeoutMs) {
|
|
191028
190997
|
try {
|
|
191029
|
-
const fd =
|
|
190998
|
+
const fd = fs22.openSync(
|
|
191030
190999
|
this.lockPath,
|
|
191031
|
-
|
|
191000
|
+
fs22.constants.O_CREAT | fs22.constants.O_EXCL | fs22.constants.O_WRONLY
|
|
191032
191001
|
);
|
|
191033
|
-
|
|
191034
|
-
|
|
191002
|
+
fs22.writeSync(fd, String(process.pid));
|
|
191003
|
+
fs22.closeSync(fd);
|
|
191035
191004
|
return () => {
|
|
191036
191005
|
try {
|
|
191037
|
-
|
|
191006
|
+
fs22.unlinkSync(this.lockPath);
|
|
191038
191007
|
} catch {
|
|
191039
191008
|
}
|
|
191040
191009
|
};
|
|
@@ -191043,16 +191012,16 @@ var ProxyRegistryManager = class {
|
|
|
191043
191012
|
if (err.code === "EEXIST") {
|
|
191044
191013
|
try {
|
|
191045
191014
|
const lockPid = parseInt(
|
|
191046
|
-
|
|
191015
|
+
fs22.readFileSync(this.lockPath, "utf-8").trim(),
|
|
191047
191016
|
10
|
|
191048
191017
|
);
|
|
191049
191018
|
if (!this.isProcessRunning(lockPid)) {
|
|
191050
|
-
|
|
191019
|
+
fs22.unlinkSync(this.lockPath);
|
|
191051
191020
|
continue;
|
|
191052
191021
|
}
|
|
191053
191022
|
} catch {
|
|
191054
191023
|
try {
|
|
191055
|
-
|
|
191024
|
+
fs22.unlinkSync(this.lockPath);
|
|
191056
191025
|
} catch {
|
|
191057
191026
|
}
|
|
191058
191027
|
continue;
|
|
@@ -191072,8 +191041,8 @@ var ProxyRegistryManager = class {
|
|
|
191072
191041
|
async claimProxyOwnership(key) {
|
|
191073
191042
|
const releaseLock = await this.acquireLock();
|
|
191074
191043
|
try {
|
|
191075
|
-
if (
|
|
191076
|
-
const content =
|
|
191044
|
+
if (fs22.existsSync(this.ownerPath)) {
|
|
191045
|
+
const content = fs22.readFileSync(this.ownerPath, "utf-8");
|
|
191077
191046
|
const ownerFile2 = JSON.parse(content);
|
|
191078
191047
|
if (await this.isProxyOwnerHealthy(ownerFile2.owner.pid)) {
|
|
191079
191048
|
return false;
|
|
@@ -191103,11 +191072,11 @@ var ProxyRegistryManager = class {
|
|
|
191103
191072
|
}
|
|
191104
191073
|
const releaseLock = await this.acquireLock();
|
|
191105
191074
|
try {
|
|
191106
|
-
if (
|
|
191107
|
-
const content =
|
|
191075
|
+
if (fs22.existsSync(this.ownerPath)) {
|
|
191076
|
+
const content = fs22.readFileSync(this.ownerPath, "utf-8");
|
|
191108
191077
|
const ownerFile = JSON.parse(content);
|
|
191109
191078
|
if (ownerFile.owner.pid === process.pid) {
|
|
191110
|
-
|
|
191079
|
+
fs22.unlinkSync(this.ownerPath);
|
|
191111
191080
|
}
|
|
191112
191081
|
}
|
|
191113
191082
|
this.isOwner = false;
|
|
@@ -191119,12 +191088,12 @@ var ProxyRegistryManager = class {
|
|
|
191119
191088
|
* Get the current proxy owner.
|
|
191120
191089
|
*/
|
|
191121
191090
|
async getProxyOwner() {
|
|
191122
|
-
if (!
|
|
191091
|
+
if (!fs22.existsSync(this.ownerPath)) {
|
|
191123
191092
|
return null;
|
|
191124
191093
|
}
|
|
191125
191094
|
const releaseLock = await this.acquireLock();
|
|
191126
191095
|
try {
|
|
191127
|
-
const content =
|
|
191096
|
+
const content = fs22.readFileSync(this.ownerPath, "utf-8");
|
|
191128
191097
|
const ownerFile = JSON.parse(content);
|
|
191129
191098
|
if (!await this.isProxyOwnerHealthy(ownerFile.owner.pid)) {
|
|
191130
191099
|
return null;
|
|
@@ -191221,7 +191190,7 @@ var ProxyRegistryManager = class {
|
|
|
191221
191190
|
*/
|
|
191222
191191
|
watchRegistry(onChange) {
|
|
191223
191192
|
this.ensureProxyDir();
|
|
191224
|
-
if (!
|
|
191193
|
+
if (!fs22.existsSync(this.registryPath)) {
|
|
191225
191194
|
const emptyRegistry = {
|
|
191226
191195
|
version: 1,
|
|
191227
191196
|
keys: {},
|
|
@@ -191264,13 +191233,13 @@ var ProxyRegistryManager = class {
|
|
|
191264
191233
|
async attemptElection(key) {
|
|
191265
191234
|
const releaseLock = await this.acquireLock();
|
|
191266
191235
|
try {
|
|
191267
|
-
if (
|
|
191268
|
-
const content =
|
|
191236
|
+
if (fs22.existsSync(this.ownerPath)) {
|
|
191237
|
+
const content = fs22.readFileSync(this.ownerPath, "utf-8");
|
|
191269
191238
|
const ownerFile2 = JSON.parse(content);
|
|
191270
191239
|
if (await this.isProxyOwnerHealthy(ownerFile2.owner.pid)) {
|
|
191271
191240
|
return false;
|
|
191272
191241
|
}
|
|
191273
|
-
|
|
191242
|
+
fs22.unlinkSync(this.ownerPath);
|
|
191274
191243
|
}
|
|
191275
191244
|
const ownerFile = {
|
|
191276
191245
|
version: 1,
|
|
@@ -191288,7 +191257,7 @@ var ProxyRegistryManager = class {
|
|
|
191288
191257
|
}
|
|
191289
191258
|
}
|
|
191290
191259
|
readRegistry() {
|
|
191291
|
-
if (!
|
|
191260
|
+
if (!fs22.existsSync(this.registryPath)) {
|
|
191292
191261
|
return {
|
|
191293
191262
|
version: 1,
|
|
191294
191263
|
keys: {},
|
|
@@ -191296,7 +191265,7 @@ var ProxyRegistryManager = class {
|
|
|
191296
191265
|
};
|
|
191297
191266
|
}
|
|
191298
191267
|
try {
|
|
191299
|
-
const content =
|
|
191268
|
+
const content = fs22.readFileSync(this.registryPath, "utf-8");
|
|
191300
191269
|
return JSON.parse(content);
|
|
191301
191270
|
} catch {
|
|
191302
191271
|
return {
|
|
@@ -191309,8 +191278,8 @@ var ProxyRegistryManager = class {
|
|
|
191309
191278
|
writeFileAtomic(filePath, data) {
|
|
191310
191279
|
this.ensureProxyDir();
|
|
191311
191280
|
const tmpPath = filePath + ".tmp";
|
|
191312
|
-
|
|
191313
|
-
|
|
191281
|
+
fs22.writeFileSync(tmpPath, JSON.stringify(data, null, 2));
|
|
191282
|
+
fs22.renameSync(tmpPath, filePath);
|
|
191314
191283
|
}
|
|
191315
191284
|
};
|
|
191316
191285
|
|
|
@@ -191436,10 +191405,10 @@ function DevUI({ instanceKey, tunnelEnabled }) {
|
|
|
191436
191405
|
}
|
|
191437
191406
|
}, [state.status, state.caInstallPhase]);
|
|
191438
191407
|
useInput4((_input, key) => {
|
|
191439
|
-
if (
|
|
191408
|
+
if (key.return) {
|
|
191440
191409
|
setState((s) => ({ ...s, caInstallPhase: "installing" }));
|
|
191441
191410
|
}
|
|
191442
|
-
});
|
|
191411
|
+
}, { isActive: state.status === "installing-ca" && state.caInstallPhase === "prompt" });
|
|
191443
191412
|
async function installSystemConfig() {
|
|
191444
191413
|
try {
|
|
191445
191414
|
performSystemSetup();
|
|
@@ -191633,7 +191602,7 @@ function DevUI({ instanceKey, tunnelEnabled }) {
|
|
|
191633
191602
|
const configPath = path20.join(process.cwd(), "specific.hcl");
|
|
191634
191603
|
const watcher = watchConfigFile(configPath, 1e3, () => {
|
|
191635
191604
|
try {
|
|
191636
|
-
const hcl =
|
|
191605
|
+
const hcl = fs23.readFileSync(configPath, "utf-8");
|
|
191637
191606
|
parseConfig(hcl).then(() => {
|
|
191638
191607
|
triggerReload();
|
|
191639
191608
|
}).catch((err) => {
|
|
@@ -191759,7 +191728,7 @@ function DevUI({ instanceKey, tunnelEnabled }) {
|
|
|
191759
191728
|
return;
|
|
191760
191729
|
}
|
|
191761
191730
|
const configPath = path20.join(process.cwd(), "specific.hcl");
|
|
191762
|
-
if (!
|
|
191731
|
+
if (!fs23.existsSync(configPath)) {
|
|
191763
191732
|
writeLog("system", "Waiting for specific.hcl to appear");
|
|
191764
191733
|
setState((s) => ({
|
|
191765
191734
|
...s,
|
|
@@ -191777,7 +191746,7 @@ function DevUI({ instanceKey, tunnelEnabled }) {
|
|
|
191777
191746
|
return;
|
|
191778
191747
|
}
|
|
191779
191748
|
let config2;
|
|
191780
|
-
const hcl =
|
|
191749
|
+
const hcl = fs23.readFileSync(configPath, "utf-8");
|
|
191781
191750
|
try {
|
|
191782
191751
|
config2 = await parseConfig(hcl);
|
|
191783
191752
|
} catch (err) {
|
|
@@ -192104,7 +192073,7 @@ Add them to the config block in specific.local`);
|
|
|
192104
192073
|
if (service.volumes) {
|
|
192105
192074
|
for (const vol of service.volumes) {
|
|
192106
192075
|
const volumeDir = path20.resolve(`.specific/keys/${instanceKey}/data/volumes/${service.name}/${vol.name}`);
|
|
192107
|
-
|
|
192076
|
+
fs23.mkdirSync(volumeDir, { recursive: true });
|
|
192108
192077
|
volumePaths.set(vol.name, volumeDir);
|
|
192109
192078
|
}
|
|
192110
192079
|
}
|
|
@@ -192160,7 +192129,7 @@ Add them to the config block in specific.local`);
|
|
|
192160
192129
|
if (service.volumes) {
|
|
192161
192130
|
for (const vol of service.volumes) {
|
|
192162
192131
|
const volumeDir = path20.resolve(`.specific/keys/${instanceKey}/data/volumes/${service.name}/${vol.name}`);
|
|
192163
|
-
|
|
192132
|
+
fs23.mkdirSync(volumeDir, { recursive: true });
|
|
192164
192133
|
volumePaths.set(vol.name, volumeDir);
|
|
192165
192134
|
}
|
|
192166
192135
|
}
|
|
@@ -192731,12 +192700,12 @@ init_open();
|
|
|
192731
192700
|
import React7, { useState as useState6, useEffect as useEffect4, useCallback } from "react";
|
|
192732
192701
|
import { render as render5, Text as Text7, Box as Box7, useApp as useApp3, useInput as useInput5 } from "ink";
|
|
192733
192702
|
import Spinner5 from "ink-spinner";
|
|
192734
|
-
import * as
|
|
192703
|
+
import * as fs25 from "fs";
|
|
192735
192704
|
import * as path23 from "path";
|
|
192736
192705
|
|
|
192737
192706
|
// src/lib/tarball/create.ts
|
|
192738
192707
|
import { execSync as execSync4 } from "child_process";
|
|
192739
|
-
import * as
|
|
192708
|
+
import * as fs24 from "fs";
|
|
192740
192709
|
import * as path22 from "path";
|
|
192741
192710
|
import { createTarPacker, createEntryItemGenerator } from "tar-vern";
|
|
192742
192711
|
function isInsideGitRepository(dir) {
|
|
@@ -192794,7 +192763,7 @@ var EXCLUDED_DIRS = [
|
|
|
192794
192763
|
];
|
|
192795
192764
|
async function collectPaths(baseDir, currentDir, exclude) {
|
|
192796
192765
|
const results = [];
|
|
192797
|
-
const entries = await
|
|
192766
|
+
const entries = await fs24.promises.readdir(currentDir, { withFileTypes: true });
|
|
192798
192767
|
for (const entry of entries) {
|
|
192799
192768
|
const fullPath = path22.join(currentDir, entry.name);
|
|
192800
192769
|
const relativePath = path22.relative(baseDir, fullPath);
|
|
@@ -192813,7 +192782,7 @@ async function collectPaths(baseDir, currentDir, exclude) {
|
|
|
192813
192782
|
async function createTarArchive(projectDir) {
|
|
192814
192783
|
writeLog("tarball", "Creating tarball using tar-vern (non-git project)");
|
|
192815
192784
|
const configPath = path22.join(projectDir, "specific.hcl");
|
|
192816
|
-
if (!
|
|
192785
|
+
if (!fs24.existsSync(configPath)) {
|
|
192817
192786
|
throw new Error("specific.hcl not found in project directory");
|
|
192818
192787
|
}
|
|
192819
192788
|
const relativePaths = await collectPaths(projectDir, projectDir, EXCLUDED_DIRS);
|
|
@@ -193735,12 +193704,12 @@ function DeployUI({ environment, config }) {
|
|
|
193735
193704
|
}
|
|
193736
193705
|
async function deployCommand(environment) {
|
|
193737
193706
|
const configPath = path23.join(process.cwd(), "specific.hcl");
|
|
193738
|
-
if (!
|
|
193707
|
+
if (!fs25.existsSync(configPath)) {
|
|
193739
193708
|
console.error("Error: No specific.hcl found in current directory");
|
|
193740
193709
|
process.exit(1);
|
|
193741
193710
|
}
|
|
193742
193711
|
let config;
|
|
193743
|
-
const hcl =
|
|
193712
|
+
const hcl = fs25.readFileSync(configPath, "utf-8");
|
|
193744
193713
|
try {
|
|
193745
193714
|
config = await parseConfig(hcl);
|
|
193746
193715
|
} catch (err) {
|
|
@@ -193761,7 +193730,7 @@ async function deployCommand(environment) {
|
|
|
193761
193730
|
|
|
193762
193731
|
// src/commands/exec.tsx
|
|
193763
193732
|
import { spawn as spawn6 } from "child_process";
|
|
193764
|
-
import * as
|
|
193733
|
+
import * as fs26 from "fs";
|
|
193765
193734
|
import * as path24 from "path";
|
|
193766
193735
|
async function execCommand(serviceName, command, instanceKey = "default") {
|
|
193767
193736
|
if (command.length === 0) {
|
|
@@ -193791,12 +193760,12 @@ async function execCommand(serviceName, command, instanceKey = "default") {
|
|
|
193791
193760
|
}
|
|
193792
193761
|
};
|
|
193793
193762
|
const configPath = path24.join(process.cwd(), "specific.hcl");
|
|
193794
|
-
if (!
|
|
193763
|
+
if (!fs26.existsSync(configPath)) {
|
|
193795
193764
|
console.error("Error: No specific.hcl found in current directory");
|
|
193796
193765
|
process.exit(1);
|
|
193797
193766
|
}
|
|
193798
193767
|
let config;
|
|
193799
|
-
const hcl =
|
|
193768
|
+
const hcl = fs26.readFileSync(configPath, "utf-8");
|
|
193800
193769
|
try {
|
|
193801
193770
|
config = await parseConfig(hcl);
|
|
193802
193771
|
} catch (err) {
|
|
@@ -193946,7 +193915,7 @@ async function execCommand(serviceName, command, instanceKey = "default") {
|
|
|
193946
193915
|
|
|
193947
193916
|
// src/commands/psql.tsx
|
|
193948
193917
|
import { spawn as spawn7 } from "child_process";
|
|
193949
|
-
import * as
|
|
193918
|
+
import * as fs27 from "fs";
|
|
193950
193919
|
import * as path25 from "path";
|
|
193951
193920
|
async function psqlCommand(databaseName, instanceKey = "default", extraArgs = []) {
|
|
193952
193921
|
let startedResources = [];
|
|
@@ -193965,12 +193934,12 @@ async function psqlCommand(databaseName, instanceKey = "default", extraArgs = []
|
|
|
193965
193934
|
}
|
|
193966
193935
|
};
|
|
193967
193936
|
const configPath = path25.join(process.cwd(), "specific.hcl");
|
|
193968
|
-
if (!
|
|
193937
|
+
if (!fs27.existsSync(configPath)) {
|
|
193969
193938
|
console.error("Error: No specific.hcl found in current directory");
|
|
193970
193939
|
process.exit(1);
|
|
193971
193940
|
}
|
|
193972
193941
|
let config;
|
|
193973
|
-
const hcl =
|
|
193942
|
+
const hcl = fs27.readFileSync(configPath, "utf-8");
|
|
193974
193943
|
try {
|
|
193975
193944
|
config = await parseConfig(hcl);
|
|
193976
193945
|
} catch (err) {
|
|
@@ -194094,7 +194063,7 @@ async function psqlCommand(databaseName, instanceKey = "default", extraArgs = []
|
|
|
194094
194063
|
|
|
194095
194064
|
// src/commands/reshape.tsx
|
|
194096
194065
|
import { spawn as spawn8 } from "child_process";
|
|
194097
|
-
import * as
|
|
194066
|
+
import * as fs28 from "fs";
|
|
194098
194067
|
import * as path26 from "path";
|
|
194099
194068
|
var VALID_ACTIONS = ["start", "complete", "status", "abort", "check"];
|
|
194100
194069
|
var MIGRATION_SUBCOMMANDS = ["start", "complete", "abort"];
|
|
@@ -194112,8 +194081,8 @@ async function reshapeCommand(action, databaseName, instanceKey = "default") {
|
|
|
194112
194081
|
let migrationsDir = "migrations";
|
|
194113
194082
|
let targetDb;
|
|
194114
194083
|
try {
|
|
194115
|
-
if (
|
|
194116
|
-
const configContent =
|
|
194084
|
+
if (fs28.existsSync(configPath)) {
|
|
194085
|
+
const configContent = fs28.readFileSync(configPath, "utf-8");
|
|
194117
194086
|
config = await parseConfig(configContent);
|
|
194118
194087
|
if (databaseName) {
|
|
194119
194088
|
const postgresConfig = config.postgres.find((p) => p.name === databaseName);
|
|
@@ -194249,7 +194218,7 @@ async function reshapeCommand(action, databaseName, instanceKey = "default") {
|
|
|
194249
194218
|
const reshapeArgs = isMigrationSubcommand ? ["migration", action] : [action];
|
|
194250
194219
|
const fullMigrationsPath = path26.join(process.cwd(), migrationsDir);
|
|
194251
194220
|
if (action === "check" || action === "start") {
|
|
194252
|
-
if (
|
|
194221
|
+
if (fs28.existsSync(fullMigrationsPath)) {
|
|
194253
194222
|
reshapeArgs.push("--dirs", fullMigrationsPath);
|
|
194254
194223
|
} else if (action === "check") {
|
|
194255
194224
|
console.error(`Error: Migrations directory not found: ${fullMigrationsPath}`);
|
|
@@ -194299,7 +194268,7 @@ async function reshapeCommand(action, databaseName, instanceKey = "default") {
|
|
|
194299
194268
|
import React8, { useState as useState7, useEffect as useEffect5 } from "react";
|
|
194300
194269
|
import { render as render6, Text as Text8, Box as Box8 } from "ink";
|
|
194301
194270
|
import Spinner6 from "ink-spinner";
|
|
194302
|
-
import * as
|
|
194271
|
+
import * as fs29 from "fs";
|
|
194303
194272
|
import * as path27 from "path";
|
|
194304
194273
|
function CleanUI({ instanceKey }) {
|
|
194305
194274
|
const [state, setState] = useState7({ status: "checking" });
|
|
@@ -194307,13 +194276,13 @@ function CleanUI({ instanceKey }) {
|
|
|
194307
194276
|
async function clean() {
|
|
194308
194277
|
const projectRoot = process.cwd();
|
|
194309
194278
|
const specificDir = path27.join(projectRoot, ".specific");
|
|
194310
|
-
if (!
|
|
194279
|
+
if (!fs29.existsSync(specificDir)) {
|
|
194311
194280
|
setState({ status: "nothing" });
|
|
194312
194281
|
return;
|
|
194313
194282
|
}
|
|
194314
194283
|
if (instanceKey) {
|
|
194315
194284
|
const keyDir = path27.join(specificDir, "keys", instanceKey);
|
|
194316
|
-
if (!
|
|
194285
|
+
if (!fs29.existsSync(keyDir)) {
|
|
194317
194286
|
setState({ status: "nothing" });
|
|
194318
194287
|
return;
|
|
194319
194288
|
}
|
|
@@ -194329,7 +194298,7 @@ function CleanUI({ instanceKey }) {
|
|
|
194329
194298
|
await stateManager.cleanStaleState();
|
|
194330
194299
|
setState({ status: "cleaning" });
|
|
194331
194300
|
try {
|
|
194332
|
-
|
|
194301
|
+
fs29.rmSync(keyDir, { recursive: true, force: true });
|
|
194333
194302
|
setState({ status: "success" });
|
|
194334
194303
|
} catch (err) {
|
|
194335
194304
|
setState({
|
|
@@ -194339,12 +194308,12 @@ function CleanUI({ instanceKey }) {
|
|
|
194339
194308
|
}
|
|
194340
194309
|
} else {
|
|
194341
194310
|
const keysDir = path27.join(specificDir, "keys");
|
|
194342
|
-
if (!
|
|
194311
|
+
if (!fs29.existsSync(keysDir)) {
|
|
194343
194312
|
setState({ status: "nothing" });
|
|
194344
194313
|
return;
|
|
194345
194314
|
}
|
|
194346
|
-
const keys =
|
|
194347
|
-
(f) =>
|
|
194315
|
+
const keys = fs29.readdirSync(keysDir).filter(
|
|
194316
|
+
(f) => fs29.statSync(path27.join(keysDir, f)).isDirectory()
|
|
194348
194317
|
);
|
|
194349
194318
|
for (const key of keys) {
|
|
194350
194319
|
const stateManager2 = new InstanceStateManager(projectRoot, key);
|
|
@@ -194368,7 +194337,7 @@ function CleanUI({ instanceKey }) {
|
|
|
194368
194337
|
}
|
|
194369
194338
|
setState({ status: "cleaning" });
|
|
194370
194339
|
try {
|
|
194371
|
-
|
|
194340
|
+
fs29.rmSync(keysDir, { recursive: true, force: true });
|
|
194372
194341
|
setState({ status: "success" });
|
|
194373
194342
|
} catch (err) {
|
|
194374
194343
|
setState({
|
|
@@ -194533,7 +194502,7 @@ import { render as render9, Text as Text11, Box as Box10, useApp as useApp6 } fr
|
|
|
194533
194502
|
import Spinner7 from "ink-spinner";
|
|
194534
194503
|
|
|
194535
194504
|
// src/lib/update.ts
|
|
194536
|
-
import * as
|
|
194505
|
+
import * as fs30 from "fs";
|
|
194537
194506
|
import * as path28 from "path";
|
|
194538
194507
|
var BINARIES_BASE_URL = "https://binaries.specific.dev/cli";
|
|
194539
194508
|
function compareVersions(a, b) {
|
|
@@ -194548,7 +194517,7 @@ function compareVersions(a, b) {
|
|
|
194548
194517
|
return 0;
|
|
194549
194518
|
}
|
|
194550
194519
|
async function checkForUpdate() {
|
|
194551
|
-
const currentVersion = "0.1.
|
|
194520
|
+
const currentVersion = "0.1.77";
|
|
194552
194521
|
const response = await fetch(`${BINARIES_BASE_URL}/latest?t=${Date.now()}`);
|
|
194553
194522
|
if (!response.ok) {
|
|
194554
194523
|
throw new Error(`Failed to check for updates: HTTP ${response.status}`);
|
|
@@ -194564,7 +194533,7 @@ function isBinaryWritable() {
|
|
|
194564
194533
|
const binaryPath = getCurrentBinaryPath();
|
|
194565
194534
|
const dir = path28.dirname(binaryPath);
|
|
194566
194535
|
try {
|
|
194567
|
-
|
|
194536
|
+
fs30.accessSync(dir, fs30.constants.W_OK);
|
|
194568
194537
|
return true;
|
|
194569
194538
|
} catch {
|
|
194570
194539
|
return false;
|
|
@@ -194575,21 +194544,21 @@ async function performUpdate(version, onProgress) {
|
|
|
194575
194544
|
const binaryDir = path28.dirname(binaryPath);
|
|
194576
194545
|
const tempPath = path28.join(binaryDir, `.specific-update-${process.pid}`);
|
|
194577
194546
|
try {
|
|
194578
|
-
const { platform:
|
|
194579
|
-
const url = `${BINARIES_BASE_URL}/${version}/specific-${
|
|
194547
|
+
const { platform: platform5, arch: arch3 } = getPlatformInfo();
|
|
194548
|
+
const url = `${BINARIES_BASE_URL}/${version}/specific-${platform5}-${arch3}`;
|
|
194580
194549
|
await downloadFile(url, tempPath, onProgress);
|
|
194581
|
-
const stat4 =
|
|
194550
|
+
const stat4 = fs30.statSync(tempPath);
|
|
194582
194551
|
if (stat4.size === 0) {
|
|
194583
194552
|
throw new Error("Downloaded binary is empty");
|
|
194584
194553
|
}
|
|
194585
|
-
|
|
194554
|
+
fs30.chmodSync(tempPath, 493);
|
|
194586
194555
|
onProgress?.({ phase: "finalizing" });
|
|
194587
|
-
|
|
194588
|
-
|
|
194556
|
+
fs30.unlinkSync(binaryPath);
|
|
194557
|
+
fs30.renameSync(tempPath, binaryPath);
|
|
194589
194558
|
} catch (error) {
|
|
194590
194559
|
try {
|
|
194591
|
-
if (
|
|
194592
|
-
|
|
194560
|
+
if (fs30.existsSync(tempPath)) {
|
|
194561
|
+
fs30.unlinkSync(tempPath);
|
|
194593
194562
|
}
|
|
194594
194563
|
} catch {
|
|
194595
194564
|
}
|
|
@@ -194599,21 +194568,21 @@ async function performUpdate(version, onProgress) {
|
|
|
194599
194568
|
|
|
194600
194569
|
// src/lib/background-update.ts
|
|
194601
194570
|
import { spawn as spawn9 } from "child_process";
|
|
194602
|
-
import * as
|
|
194571
|
+
import * as fs31 from "fs";
|
|
194603
194572
|
import * as path29 from "path";
|
|
194604
|
-
import * as
|
|
194605
|
-
var SPECIFIC_DIR = path29.join(
|
|
194573
|
+
import * as os9 from "os";
|
|
194574
|
+
var SPECIFIC_DIR = path29.join(os9.homedir(), ".specific");
|
|
194606
194575
|
var RATE_LIMIT_FILE = path29.join(SPECIFIC_DIR, "last-update-check");
|
|
194607
194576
|
var LOCK_FILE = path29.join(SPECIFIC_DIR, "update.lock");
|
|
194608
194577
|
var RATE_LIMIT_MS = 60 * 60 * 1e3;
|
|
194609
194578
|
var STALE_LOCK_MS = 10 * 60 * 1e3;
|
|
194610
194579
|
function writeCheckTimestamp() {
|
|
194611
|
-
|
|
194612
|
-
|
|
194580
|
+
fs31.mkdirSync(SPECIFIC_DIR, { recursive: true });
|
|
194581
|
+
fs31.writeFileSync(RATE_LIMIT_FILE, String(Date.now()), "utf-8");
|
|
194613
194582
|
}
|
|
194614
194583
|
function isRateLimited() {
|
|
194615
194584
|
try {
|
|
194616
|
-
const content =
|
|
194585
|
+
const content = fs31.readFileSync(RATE_LIMIT_FILE, "utf-8").trim();
|
|
194617
194586
|
const lastCheck = parseInt(content, 10);
|
|
194618
194587
|
if (isNaN(lastCheck)) return false;
|
|
194619
194588
|
return Date.now() - lastCheck < RATE_LIMIT_MS;
|
|
@@ -194747,7 +194716,7 @@ function updateCommand() {
|
|
|
194747
194716
|
var program = new Command();
|
|
194748
194717
|
var env = "production";
|
|
194749
194718
|
var envLabel = env !== "production" ? `[${env.toUpperCase()}] ` : "";
|
|
194750
|
-
program.name("specific").description(`${envLabel}Infrastructure-as-code for coding agents`).version("0.1.
|
|
194719
|
+
program.name("specific").description(`${envLabel}Infrastructure-as-code for coding agents`).version("0.1.77").enablePositionalOptions();
|
|
194751
194720
|
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));
|
|
194752
194721
|
program.command("docs [topic]").description("Fetch LLM-optimized documentation").action(docsCommand);
|
|
194753
194722
|
program.command("check").description("Validate specific.hcl configuration").action(checkCommand);
|