@specific.dev/cli 0.1.106 → 0.1.108
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 +194 -82
- package/package.json +5 -2
- /package/dist/admin/_next/static/{P3VZVUKKu1Qjrf-CPDzDC → -uB2tvCTW06hUMOZfRURZ}/_buildManifest.js +0 -0
- /package/dist/admin/_next/static/{P3VZVUKKu1Qjrf-CPDzDC → -uB2tvCTW06hUMOZfRURZ}/_clientMiddlewareManifest.json +0 -0
- /package/dist/admin/_next/static/{P3VZVUKKu1Qjrf-CPDzDC → -uB2tvCTW06hUMOZfRURZ}/_ssgManifest.js +0 -0
package/dist/cli.js
CHANGED
|
@@ -602,12 +602,12 @@ var init_is_wsl = __esm({
|
|
|
602
602
|
// node_modules/.pnpm/powershell-utils@0.1.0/node_modules/powershell-utils/index.js
|
|
603
603
|
import process3 from "node:process";
|
|
604
604
|
import { Buffer as Buffer2 } from "node:buffer";
|
|
605
|
-
import { promisify } from "node:util";
|
|
605
|
+
import { promisify as promisify2 } from "node:util";
|
|
606
606
|
import childProcess from "node:child_process";
|
|
607
|
-
var
|
|
607
|
+
var execFile2, powerShellPath, executePowerShell;
|
|
608
608
|
var init_powershell_utils = __esm({
|
|
609
609
|
"node_modules/.pnpm/powershell-utils@0.1.0/node_modules/powershell-utils/index.js"() {
|
|
610
|
-
|
|
610
|
+
execFile2 = promisify2(childProcess.execFile);
|
|
611
611
|
powerShellPath = () => `${process3.env.SYSTEMROOT || process3.env.windir || String.raw`C:\Windows`}\\System32\\WindowsPowerShell\\v1.0\\powershell.exe`;
|
|
612
612
|
executePowerShell = async (command, options2 = {}) => {
|
|
613
613
|
const {
|
|
@@ -615,7 +615,7 @@ var init_powershell_utils = __esm({
|
|
|
615
615
|
...execFileOptions
|
|
616
616
|
} = options2;
|
|
617
617
|
const encodedCommand = executePowerShell.encodeCommand(command);
|
|
618
|
-
return
|
|
618
|
+
return execFile2(
|
|
619
619
|
psPath ?? powerShellPath(),
|
|
620
620
|
[
|
|
621
621
|
...executePowerShell.argumentsPrefix,
|
|
@@ -658,17 +658,17 @@ var init_utilities = __esm({
|
|
|
658
658
|
});
|
|
659
659
|
|
|
660
660
|
// node_modules/.pnpm/wsl-utils@0.3.1/node_modules/wsl-utils/index.js
|
|
661
|
-
import { promisify as
|
|
661
|
+
import { promisify as promisify3 } from "node:util";
|
|
662
662
|
import childProcess2 from "node:child_process";
|
|
663
663
|
import fs17, { constants as fsConstants } from "node:fs/promises";
|
|
664
|
-
var
|
|
664
|
+
var execFile3, wslDrivesMountPoint, powerShellPathFromWsl, powerShellPath2, canAccessPowerShellPromise, canAccessPowerShell, wslDefaultBrowser, convertWslPathToWindows;
|
|
665
665
|
var init_wsl_utils = __esm({
|
|
666
666
|
"node_modules/.pnpm/wsl-utils@0.3.1/node_modules/wsl-utils/index.js"() {
|
|
667
667
|
init_is_wsl();
|
|
668
668
|
init_powershell_utils();
|
|
669
669
|
init_utilities();
|
|
670
670
|
init_is_wsl();
|
|
671
|
-
|
|
671
|
+
execFile3 = promisify3(childProcess2.execFile);
|
|
672
672
|
wslDrivesMountPoint = /* @__PURE__ */ (() => {
|
|
673
673
|
const defaultMountPoint = "/mnt/";
|
|
674
674
|
let mountPoint;
|
|
@@ -724,7 +724,7 @@ var init_wsl_utils = __esm({
|
|
|
724
724
|
return path27;
|
|
725
725
|
}
|
|
726
726
|
try {
|
|
727
|
-
const { stdout } = await
|
|
727
|
+
const { stdout } = await execFile3("wslpath", ["-aw", path27], { encoding: "utf8" });
|
|
728
728
|
return stdout.trim();
|
|
729
729
|
} catch {
|
|
730
730
|
return path27;
|
|
@@ -756,14 +756,14 @@ var init_define_lazy_prop = __esm({
|
|
|
756
756
|
});
|
|
757
757
|
|
|
758
758
|
// node_modules/.pnpm/default-browser-id@5.0.1/node_modules/default-browser-id/index.js
|
|
759
|
-
import { promisify as
|
|
759
|
+
import { promisify as promisify4 } from "node:util";
|
|
760
760
|
import process4 from "node:process";
|
|
761
|
-
import { execFile as
|
|
761
|
+
import { execFile as execFile4 } from "node:child_process";
|
|
762
762
|
async function defaultBrowserId() {
|
|
763
763
|
if (process4.platform !== "darwin") {
|
|
764
764
|
throw new Error("macOS only");
|
|
765
765
|
}
|
|
766
|
-
const { stdout } = await
|
|
766
|
+
const { stdout } = await execFileAsync2("defaults", ["read", "com.apple.LaunchServices/com.apple.launchservices.secure", "LSHandlers"]);
|
|
767
767
|
const match = /LSHandlerRoleAll = "(?!-)(?<id>[^"]+?)";\s+?LSHandlerURLScheme = (?:http|https);/.exec(stdout);
|
|
768
768
|
const browserId = match?.groups.id ?? "com.apple.Safari";
|
|
769
769
|
if (browserId === "com.apple.safari") {
|
|
@@ -771,17 +771,17 @@ async function defaultBrowserId() {
|
|
|
771
771
|
}
|
|
772
772
|
return browserId;
|
|
773
773
|
}
|
|
774
|
-
var
|
|
774
|
+
var execFileAsync2;
|
|
775
775
|
var init_default_browser_id = __esm({
|
|
776
776
|
"node_modules/.pnpm/default-browser-id@5.0.1/node_modules/default-browser-id/index.js"() {
|
|
777
|
-
|
|
777
|
+
execFileAsync2 = promisify4(execFile4);
|
|
778
778
|
}
|
|
779
779
|
});
|
|
780
780
|
|
|
781
781
|
// node_modules/.pnpm/run-applescript@7.1.0/node_modules/run-applescript/index.js
|
|
782
782
|
import process5 from "node:process";
|
|
783
|
-
import { promisify as
|
|
784
|
-
import { execFile as
|
|
783
|
+
import { promisify as promisify5 } from "node:util";
|
|
784
|
+
import { execFile as execFile5, execFileSync } from "node:child_process";
|
|
785
785
|
async function runAppleScript(script, { humanReadableOutput = true, signal } = {}) {
|
|
786
786
|
if (process5.platform !== "darwin") {
|
|
787
787
|
throw new Error("macOS only");
|
|
@@ -791,13 +791,13 @@ async function runAppleScript(script, { humanReadableOutput = true, signal } = {
|
|
|
791
791
|
if (signal) {
|
|
792
792
|
execOptions.signal = signal;
|
|
793
793
|
}
|
|
794
|
-
const { stdout } = await
|
|
794
|
+
const { stdout } = await execFileAsync3("osascript", ["-e", script, outputArguments], execOptions);
|
|
795
795
|
return stdout.trim();
|
|
796
796
|
}
|
|
797
|
-
var
|
|
797
|
+
var execFileAsync3;
|
|
798
798
|
var init_run_applescript = __esm({
|
|
799
799
|
"node_modules/.pnpm/run-applescript@7.1.0/node_modules/run-applescript/index.js"() {
|
|
800
|
-
|
|
800
|
+
execFileAsync3 = promisify5(execFile5);
|
|
801
801
|
}
|
|
802
802
|
});
|
|
803
803
|
|
|
@@ -813,9 +813,9 @@ var init_bundle_name = __esm({
|
|
|
813
813
|
});
|
|
814
814
|
|
|
815
815
|
// node_modules/.pnpm/default-browser@5.4.0/node_modules/default-browser/windows.js
|
|
816
|
-
import { promisify as
|
|
817
|
-
import { execFile as
|
|
818
|
-
async function defaultBrowser(_execFileAsync =
|
|
816
|
+
import { promisify as promisify6 } from "node:util";
|
|
817
|
+
import { execFile as execFile6 } from "node:child_process";
|
|
818
|
+
async function defaultBrowser(_execFileAsync = execFileAsync4) {
|
|
819
819
|
const { stdout } = await _execFileAsync("reg", [
|
|
820
820
|
"QUERY",
|
|
821
821
|
" HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\Shell\\Associations\\UrlAssociations\\http\\UserChoice",
|
|
@@ -833,10 +833,10 @@ async function defaultBrowser(_execFileAsync = execFileAsync3) {
|
|
|
833
833
|
}
|
|
834
834
|
return browser;
|
|
835
835
|
}
|
|
836
|
-
var
|
|
836
|
+
var execFileAsync4, windowsBrowserProgIds, _windowsBrowserProgIdMap, UnknownBrowserError;
|
|
837
837
|
var init_windows = __esm({
|
|
838
838
|
"node_modules/.pnpm/default-browser@5.4.0/node_modules/default-browser/windows.js"() {
|
|
839
|
-
|
|
839
|
+
execFileAsync4 = promisify6(execFile6);
|
|
840
840
|
windowsBrowserProgIds = {
|
|
841
841
|
MSEdgeHTM: { name: "Edge", id: "com.microsoft.edge" },
|
|
842
842
|
// The missing `L` is correct.
|
|
@@ -863,9 +863,9 @@ var init_windows = __esm({
|
|
|
863
863
|
});
|
|
864
864
|
|
|
865
865
|
// node_modules/.pnpm/default-browser@5.4.0/node_modules/default-browser/index.js
|
|
866
|
-
import { promisify as
|
|
866
|
+
import { promisify as promisify7 } from "node:util";
|
|
867
867
|
import process6 from "node:process";
|
|
868
|
-
import { execFile as
|
|
868
|
+
import { execFile as execFile7 } from "node:child_process";
|
|
869
869
|
async function defaultBrowser2() {
|
|
870
870
|
if (process6.platform === "darwin") {
|
|
871
871
|
const id = await defaultBrowserId();
|
|
@@ -873,7 +873,7 @@ async function defaultBrowser2() {
|
|
|
873
873
|
return { name, id };
|
|
874
874
|
}
|
|
875
875
|
if (process6.platform === "linux") {
|
|
876
|
-
const { stdout } = await
|
|
876
|
+
const { stdout } = await execFileAsync5("xdg-mime", ["query", "default", "x-scheme-handler/http"]);
|
|
877
877
|
const id = stdout.trim();
|
|
878
878
|
const name = titleize(id.replace(/.desktop$/, "").replace("-", " "));
|
|
879
879
|
return { name, id };
|
|
@@ -883,14 +883,14 @@ async function defaultBrowser2() {
|
|
|
883
883
|
}
|
|
884
884
|
throw new Error("Only macOS, Linux, and Windows are supported");
|
|
885
885
|
}
|
|
886
|
-
var
|
|
886
|
+
var execFileAsync5, titleize;
|
|
887
887
|
var init_default_browser = __esm({
|
|
888
888
|
"node_modules/.pnpm/default-browser@5.4.0/node_modules/default-browser/index.js"() {
|
|
889
889
|
init_default_browser_id();
|
|
890
890
|
init_bundle_name();
|
|
891
891
|
init_windows();
|
|
892
892
|
init_windows();
|
|
893
|
-
|
|
893
|
+
execFileAsync5 = promisify7(execFile7);
|
|
894
894
|
titleize = (string) => string.toLowerCase().replaceAll(/(?:^|\s|-)\S/g, (x) => x.toUpperCase());
|
|
895
895
|
}
|
|
896
896
|
});
|
|
@@ -185191,6 +185191,8 @@ import { readFile, writeFile } from "fs/promises";
|
|
|
185191
185191
|
import { existsSync as existsSync5 } from "fs";
|
|
185192
185192
|
import * as fs6 from "fs";
|
|
185193
185193
|
import * as path6 from "path";
|
|
185194
|
+
import { execFile } from "child_process";
|
|
185195
|
+
import { promisify } from "util";
|
|
185194
185196
|
import * as http from "http";
|
|
185195
185197
|
import * as fs7 from "fs";
|
|
185196
185198
|
import * as path7 from "path";
|
|
@@ -369936,6 +369938,7 @@ function startService(service, resources, secrets, configs, endpointPorts, servi
|
|
|
369936
369938
|
}
|
|
369937
369939
|
};
|
|
369938
369940
|
}
|
|
369941
|
+
var execFileAsync = promisify(execFile);
|
|
369939
369942
|
var InstanceStateManager = class {
|
|
369940
369943
|
stateDir;
|
|
369941
369944
|
statePath;
|
|
@@ -370036,6 +370039,7 @@ var InstanceStateManager = class {
|
|
|
370036
370039
|
const content = fs6.readFileSync(this.statePath, "utf-8");
|
|
370037
370040
|
const state = JSON.parse(content);
|
|
370038
370041
|
if (!this.isProcessRunning(state.owner.pid)) {
|
|
370042
|
+
await this.killOrphanedProcesses(state);
|
|
370039
370043
|
fs6.unlinkSync(this.statePath);
|
|
370040
370044
|
return true;
|
|
370041
370045
|
}
|
|
@@ -370051,6 +370055,35 @@ var InstanceStateManager = class {
|
|
|
370051
370055
|
releaseLock();
|
|
370052
370056
|
}
|
|
370053
370057
|
}
|
|
370058
|
+
/**
|
|
370059
|
+
* Kill orphaned child processes left behind by a dead owner.
|
|
370060
|
+
* Best-effort: failures are silently ignored.
|
|
370061
|
+
*/
|
|
370062
|
+
async killOrphanedProcesses(state) {
|
|
370063
|
+
for (const service of Object.values(state.services)) {
|
|
370064
|
+
if (service.pid && this.isProcessRunning(service.pid)) {
|
|
370065
|
+
try {
|
|
370066
|
+
process.kill(-service.pid, "SIGKILL");
|
|
370067
|
+
} catch {
|
|
370068
|
+
}
|
|
370069
|
+
}
|
|
370070
|
+
}
|
|
370071
|
+
for (const db of Object.values(state.databases)) {
|
|
370072
|
+
if (db.syncUrl) {
|
|
370073
|
+
try {
|
|
370074
|
+
const url = new URL(db.syncUrl);
|
|
370075
|
+
const port = parseInt(url.port, 10);
|
|
370076
|
+
if (!isNaN(port)) {
|
|
370077
|
+
const pid = await findPidOnPort(port);
|
|
370078
|
+
if (pid !== void 0) {
|
|
370079
|
+
process.kill(pid, "SIGKILL");
|
|
370080
|
+
}
|
|
370081
|
+
}
|
|
370082
|
+
} catch {
|
|
370083
|
+
}
|
|
370084
|
+
}
|
|
370085
|
+
}
|
|
370086
|
+
}
|
|
370054
370087
|
async claimOwnership(command) {
|
|
370055
370088
|
const releaseLock = await this.acquireLock();
|
|
370056
370089
|
try {
|
|
@@ -370143,6 +370176,19 @@ var InstanceStateManager = class {
|
|
|
370143
370176
|
fs6.renameSync(tmpPath, this.statePath);
|
|
370144
370177
|
}
|
|
370145
370178
|
};
|
|
370179
|
+
async function findPidOnPort(port) {
|
|
370180
|
+
try {
|
|
370181
|
+
const { stdout } = await execFileAsync(
|
|
370182
|
+
"lsof",
|
|
370183
|
+
["-i", `:${port}`, "-t", "-sTCP:LISTEN"],
|
|
370184
|
+
{ timeout: 5e3 }
|
|
370185
|
+
);
|
|
370186
|
+
const pid = parseInt(stdout.trim().split("\n")[0], 10);
|
|
370187
|
+
return isNaN(pid) ? void 0 : pid;
|
|
370188
|
+
} catch {
|
|
370189
|
+
return void 0;
|
|
370190
|
+
}
|
|
370191
|
+
}
|
|
370146
370192
|
var __dirname = path7.dirname(fileURLToPath(import.meta.url));
|
|
370147
370193
|
var adminDir = path7.join(__dirname, "admin");
|
|
370148
370194
|
var _embeddedAdmin = null;
|
|
@@ -370399,6 +370445,22 @@ async function startElectric(postgres, port, dataDir, options2) {
|
|
|
370399
370445
|
);
|
|
370400
370446
|
const secret = generateRandomString(32);
|
|
370401
370447
|
const host = "127.0.0.1";
|
|
370448
|
+
if (await checkTcpPort2(host, port)) {
|
|
370449
|
+
let freed = false;
|
|
370450
|
+
for (let i = 0; i < 30; i++) {
|
|
370451
|
+
await sleep2(100);
|
|
370452
|
+
if (!await checkTcpPort2(host, port)) {
|
|
370453
|
+
freed = true;
|
|
370454
|
+
break;
|
|
370455
|
+
}
|
|
370456
|
+
}
|
|
370457
|
+
if (!freed) {
|
|
370458
|
+
throw new Error(
|
|
370459
|
+
`Electric port ${port} is already in use. This may be an orphaned process from a previous session \u2014 find it with \`lsof -i :${port}\` and kill it, then retry.`
|
|
370460
|
+
);
|
|
370461
|
+
}
|
|
370462
|
+
writeLog("electric", `Port ${port} was occupied but is now free`);
|
|
370463
|
+
}
|
|
370402
370464
|
const storageDir = path9.join(process.cwd(), dataDir, `electric-${postgres.name}`);
|
|
370403
370465
|
fs8.rmSync(storageDir, { recursive: true, force: true });
|
|
370404
370466
|
writeLog("electric", `Starting Electric for database "${postgres.name}"`);
|
|
@@ -370423,6 +370485,7 @@ async function startElectric(postgres, port, dataDir, options2) {
|
|
|
370423
370485
|
await waitForTcpPort2(host, port);
|
|
370424
370486
|
return {
|
|
370425
370487
|
databaseName: postgres.name,
|
|
370488
|
+
pid: electric.pid,
|
|
370426
370489
|
port,
|
|
370427
370490
|
url: `http://${host}:${port}`,
|
|
370428
370491
|
secret,
|
|
@@ -370793,6 +370856,29 @@ function runReshape(args, databaseUrl, migrationsDir, reshapeBinaryPath, log) {
|
|
|
370793
370856
|
return { success: false, output: message };
|
|
370794
370857
|
}
|
|
370795
370858
|
}
|
|
370859
|
+
function getReshapeStatus(databaseUrl, reshapeBinaryPath, log) {
|
|
370860
|
+
const args = ["status", "--format", "json", "--url", databaseUrl];
|
|
370861
|
+
log(`Executing: reshape ${args.join(" ")}`);
|
|
370862
|
+
try {
|
|
370863
|
+
const result = spawnSync(reshapeBinaryPath, args, {
|
|
370864
|
+
encoding: "utf-8",
|
|
370865
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
370866
|
+
});
|
|
370867
|
+
const stdout = result.stdout || "";
|
|
370868
|
+
const stderr = result.stderr || "";
|
|
370869
|
+
if (result.status !== 0) {
|
|
370870
|
+
log(`Reshape status command failed with exit code ${result.status}`);
|
|
370871
|
+
if (stderr.trim()) log(` stderr: ${stderr.trim()}`);
|
|
370872
|
+
return null;
|
|
370873
|
+
}
|
|
370874
|
+
log(`Reshape status: ${stdout.trim()}`);
|
|
370875
|
+
return JSON.parse(stdout);
|
|
370876
|
+
} catch (err) {
|
|
370877
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
370878
|
+
log(`Failed to get Reshape status: ${message}`);
|
|
370879
|
+
return null;
|
|
370880
|
+
}
|
|
370881
|
+
}
|
|
370796
370882
|
function makeReadOnly(filePath, log) {
|
|
370797
370883
|
try {
|
|
370798
370884
|
fs10.chmodSync(filePath, 292);
|
|
@@ -370818,64 +370904,50 @@ function createReshapeWatcher(options2) {
|
|
|
370818
370904
|
return null;
|
|
370819
370905
|
}
|
|
370820
370906
|
log(`Processing ${currentMigrationFiles.length} migration file(s)`);
|
|
370821
|
-
|
|
370822
|
-
|
|
370823
|
-
|
|
370824
|
-
|
|
370825
|
-
log(`
|
|
370826
|
-
|
|
370827
|
-
|
|
370828
|
-
|
|
370829
|
-
onError(new Error(`Failed to start migration: ${result.output}`));
|
|
370830
|
-
return null;
|
|
370831
|
-
}
|
|
370832
|
-
startedMigration = migrationFile;
|
|
370833
|
-
log(`Migration "${migrationName}" started successfully`);
|
|
370834
|
-
log(` Started migration file: ${startedMigration}`);
|
|
370835
|
-
} else {
|
|
370907
|
+
const lastMigration = currentMigrationFiles[currentMigrationFiles.length - 1];
|
|
370908
|
+
const lastMigrationName = getMigrationName(lastMigration);
|
|
370909
|
+
const status = getReshapeStatus(databaseUrl, reshapeBinaryPath, log);
|
|
370910
|
+
if (status?.status === "in_progress") {
|
|
370911
|
+
log(`Found in-progress migration(s), aborting before re-initialization...`);
|
|
370912
|
+
runReshape(["abort"], databaseUrl, migrationsDir, reshapeBinaryPath, log);
|
|
370913
|
+
}
|
|
370914
|
+
if (currentMigrationFiles.length > 1) {
|
|
370836
370915
|
const secondToLast = currentMigrationFiles[currentMigrationFiles.length - 2];
|
|
370837
370916
|
const secondToLastName = getMigrationName(secondToLast);
|
|
370838
|
-
|
|
370839
|
-
|
|
370840
|
-
|
|
370841
|
-
|
|
370842
|
-
|
|
370843
|
-
|
|
370844
|
-
|
|
370845
|
-
|
|
370846
|
-
|
|
370847
|
-
|
|
370848
|
-
|
|
370849
|
-
|
|
370850
|
-
|
|
370851
|
-
|
|
370852
|
-
log(`
|
|
370853
|
-
|
|
370854
|
-
|
|
370917
|
+
if (status?.latest_completed_migration !== secondToLastName) {
|
|
370918
|
+
log(`Completing all migrations up to and including "${secondToLastName}"...`);
|
|
370919
|
+
const completeResult = runReshape(
|
|
370920
|
+
["start", "--complete", "--migration", secondToLastName],
|
|
370921
|
+
databaseUrl,
|
|
370922
|
+
migrationsDir,
|
|
370923
|
+
reshapeBinaryPath,
|
|
370924
|
+
log
|
|
370925
|
+
);
|
|
370926
|
+
if (!completeResult.success) {
|
|
370927
|
+
log(`ERROR: Failed to complete migrations up to "${secondToLastName}"`);
|
|
370928
|
+
onError(new Error(`Failed to complete migrations: ${completeResult.output}`));
|
|
370929
|
+
return null;
|
|
370930
|
+
}
|
|
370931
|
+
log(`Successfully completed ${currentMigrationFiles.length - 1} migration(s)`);
|
|
370932
|
+
} else {
|
|
370933
|
+
log(`Migrations up to "${secondToLastName}" already completed, skipping`);
|
|
370855
370934
|
}
|
|
370856
|
-
log(`Successfully completed ${currentMigrationFiles.length - 1} migration(s)`);
|
|
370857
|
-
log(`Making completed migration files read-only...`);
|
|
370858
370935
|
for (let i = 0; i < currentMigrationFiles.length - 1; i++) {
|
|
370859
370936
|
const filePath = path11.join(migrationsDir, currentMigrationFiles[i]);
|
|
370860
370937
|
makeReadOnly(filePath, log);
|
|
370861
370938
|
}
|
|
370862
|
-
log(`Starting latest migration "${lastMigrationName}" (will not be completed, allowing iteration)`);
|
|
370863
|
-
const startResult = runReshape(["start"], databaseUrl, migrationsDir, reshapeBinaryPath, log);
|
|
370864
|
-
if (!startResult.success) {
|
|
370865
|
-
log(`ERROR: Failed to start migration "${lastMigrationName}"`);
|
|
370866
|
-
onError(new Error(`Failed to start last migration: ${startResult.output}`));
|
|
370867
|
-
return null;
|
|
370868
|
-
}
|
|
370869
|
-
startedMigration = lastMigration;
|
|
370870
|
-
log(`Migration "${lastMigrationName}" started successfully`);
|
|
370871
|
-
log(` Started migration file: ${startedMigration}`);
|
|
370872
370939
|
}
|
|
370873
|
-
|
|
370874
|
-
|
|
370875
|
-
|
|
370876
|
-
|
|
370877
|
-
|
|
370940
|
+
log(`Starting latest migration "${lastMigrationName}" (will not be completed, allowing iteration)`);
|
|
370941
|
+
const startResult = runReshape(["start"], databaseUrl, migrationsDir, reshapeBinaryPath, log);
|
|
370942
|
+
if (!startResult.success) {
|
|
370943
|
+
log(`ERROR: Failed to start migration "${lastMigrationName}"`);
|
|
370944
|
+
onError(new Error(`Failed to start migration: ${startResult.output}`));
|
|
370945
|
+
return null;
|
|
370878
370946
|
}
|
|
370947
|
+
startedMigration = lastMigration;
|
|
370948
|
+
log(`Migration "${lastMigrationName}" started successfully`);
|
|
370949
|
+
const searchPath = getSchemaName(startedMigration);
|
|
370950
|
+
log(`Search path (schema name): ${searchPath}`);
|
|
370879
370951
|
log(`Reshape initialization complete`);
|
|
370880
370952
|
return searchPath;
|
|
370881
370953
|
};
|
|
@@ -371711,6 +371783,9 @@ var DevEnvironment = class extends TypedEventEmitter {
|
|
|
371711
371783
|
collectedSecrets = {};
|
|
371712
371784
|
collectedConfigs = {};
|
|
371713
371785
|
inputResolve = null;
|
|
371786
|
+
// Last-resort exit handler to kill child processes when the process exits
|
|
371787
|
+
// unexpectedly (e.g. SIGKILL from an agent). Runs synchronously.
|
|
371788
|
+
exitHandler = null;
|
|
371714
371789
|
constructor(options2) {
|
|
371715
371790
|
super();
|
|
371716
371791
|
this.projectDir = options2?.projectDir ?? process.cwd();
|
|
@@ -371913,6 +371988,7 @@ var DevEnvironment = class extends TypedEventEmitter {
|
|
|
371913
371988
|
if (this.stateManager) {
|
|
371914
371989
|
await this.stateManager.releaseOwnership();
|
|
371915
371990
|
}
|
|
371991
|
+
this.removeExitHandler();
|
|
371916
371992
|
this.systemLog("Shutdown complete");
|
|
371917
371993
|
closeDebugLog();
|
|
371918
371994
|
this.setStatus("idle");
|
|
@@ -371922,6 +371998,41 @@ var DevEnvironment = class extends TypedEventEmitter {
|
|
|
371922
371998
|
this.startResolve = null;
|
|
371923
371999
|
}
|
|
371924
372000
|
}
|
|
372001
|
+
// ── Private: exit handler ─────────────────────────────────────────────────
|
|
372002
|
+
/**
|
|
372003
|
+
* Register a synchronous process 'exit' handler that kills all known child
|
|
372004
|
+
* PIDs. This is a last resort for when the process exits without going
|
|
372005
|
+
* through shutdownInternal (e.g. parent sends SIGKILL).
|
|
372006
|
+
*/
|
|
372007
|
+
registerExitHandler() {
|
|
372008
|
+
this.removeExitHandler();
|
|
372009
|
+
this.exitHandler = () => {
|
|
372010
|
+
for (const electric of this.electricInstances) {
|
|
372011
|
+
if (electric.pid) {
|
|
372012
|
+
try {
|
|
372013
|
+
process.kill(electric.pid, "SIGKILL");
|
|
372014
|
+
} catch {
|
|
372015
|
+
}
|
|
372016
|
+
}
|
|
372017
|
+
}
|
|
372018
|
+
for (const service of this.services) {
|
|
372019
|
+
const pid = service.process.pid;
|
|
372020
|
+
if (pid) {
|
|
372021
|
+
try {
|
|
372022
|
+
process.kill(-pid, "SIGKILL");
|
|
372023
|
+
} catch {
|
|
372024
|
+
}
|
|
372025
|
+
}
|
|
372026
|
+
}
|
|
372027
|
+
};
|
|
372028
|
+
process.on("exit", this.exitHandler);
|
|
372029
|
+
}
|
|
372030
|
+
removeExitHandler() {
|
|
372031
|
+
if (this.exitHandler) {
|
|
372032
|
+
process.removeListener("exit", this.exitHandler);
|
|
372033
|
+
this.exitHandler = null;
|
|
372034
|
+
}
|
|
372035
|
+
}
|
|
371925
372036
|
// ── Private: config file watcher ───────────────────────────────────────────
|
|
371926
372037
|
startConfigWatcher() {
|
|
371927
372038
|
const configPath = path14.join(this.projectDir, "specific.hcl");
|
|
@@ -372099,6 +372210,7 @@ var DevEnvironment = class extends TypedEventEmitter {
|
|
|
372099
372210
|
if (result.cancelled) return;
|
|
372100
372211
|
resources = result.resources;
|
|
372101
372212
|
this.mailServers = result.mail;
|
|
372213
|
+
this.registerExitHandler();
|
|
372102
372214
|
} catch (err) {
|
|
372103
372215
|
const errorMsg = `Failed to start resources: ${err instanceof Error ? err.message : String(err)}`;
|
|
372104
372216
|
writeLog("system:error", errorMsg);
|
|
@@ -373075,7 +373187,7 @@ function trackEvent(event, properties) {
|
|
|
373075
373187
|
event,
|
|
373076
373188
|
properties: {
|
|
373077
373189
|
...properties,
|
|
373078
|
-
cli_version: "0.1.
|
|
373190
|
+
cli_version: "0.1.108",
|
|
373079
373191
|
platform: process.platform,
|
|
373080
373192
|
node_version: process.version,
|
|
373081
373193
|
project_id: getProjectId()
|
|
@@ -373512,7 +373624,7 @@ import { render as render3, Text as Text3, Box as Box3 } from "ink";
|
|
|
373512
373624
|
import Spinner2 from "ink-spinner";
|
|
373513
373625
|
import * as fs21 from "fs";
|
|
373514
373626
|
import * as path19 from "path";
|
|
373515
|
-
import { execFile as
|
|
373627
|
+
import { execFile as execFile8 } from "child_process";
|
|
373516
373628
|
|
|
373517
373629
|
// node_modules/.pnpm/@specific+config@file+..+config/node_modules/@specific/config/dist/parser.js
|
|
373518
373630
|
var import_hcl2_json_parser3 = __toESM(require_dist2(), 1);
|
|
@@ -374166,7 +374278,7 @@ async function runReshapeCheck(migrationsDir) {
|
|
|
374166
374278
|
const binary = await ensureBinary(reshapeBinary);
|
|
374167
374279
|
const reshapePath = binary.executables["reshape"];
|
|
374168
374280
|
return new Promise((resolve9) => {
|
|
374169
|
-
|
|
374281
|
+
execFile8(reshapePath, ["check", "--dirs", migrationsDir], (err, _stdout, stderr) => {
|
|
374170
374282
|
if (err) {
|
|
374171
374283
|
const errorMsg = stderr.trim() || err.message;
|
|
374172
374284
|
resolve9({ success: false, error: errorMsg });
|
|
@@ -376754,7 +376866,7 @@ function compareVersions(a, b) {
|
|
|
376754
376866
|
return 0;
|
|
376755
376867
|
}
|
|
376756
376868
|
async function checkForUpdate() {
|
|
376757
|
-
const currentVersion = "0.1.
|
|
376869
|
+
const currentVersion = "0.1.108";
|
|
376758
376870
|
const response = await fetch(`${BINARIES_BASE_URL}/latest?t=${Date.now()}`);
|
|
376759
376871
|
if (!response.ok) {
|
|
376760
376872
|
throw new Error(`Failed to check for updates: HTTP ${response.status}`);
|
|
@@ -377022,7 +377134,7 @@ async function projectListCommand() {
|
|
|
377022
377134
|
var program = new Command();
|
|
377023
377135
|
var env = "production";
|
|
377024
377136
|
var envLabel = env !== "production" ? `[${env.toUpperCase()}] ` : "";
|
|
377025
|
-
program.name("specific").description(`${envLabel}Infrastructure-as-code for coding agents`).version("0.1.
|
|
377137
|
+
program.name("specific").description(`${envLabel}Infrastructure-as-code for coding agents`).version("0.1.108").enablePositionalOptions();
|
|
377026
377138
|
program.command("init").description("Initialize project for use with a coding agent").option("--agent <name...>", "Agents to configure (cursor, claude, codex, other)").addHelpText("after", `
|
|
377027
377139
|
Examples:
|
|
377028
377140
|
$ specific init
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@specific.dev/cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.108",
|
|
4
4
|
"description": "CLI for Specific infrastructure-as-code",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/cli.js",
|
|
@@ -17,7 +17,10 @@
|
|
|
17
17
|
"link:dev": "npm run build:dev && npm link",
|
|
18
18
|
"link:staging": "npm run build:staging && npm link",
|
|
19
19
|
"link:prod": "npm run build && npm link",
|
|
20
|
-
"build:binary": "npx tsx scripts/build-binary.ts"
|
|
20
|
+
"build:binary": "npx tsx scripts/build-binary.ts",
|
|
21
|
+
"link:binary:dev": "NODE_ENV=development npm run build:binary && codesign -s - dist/specific && cp dist/specific ~/.local/bin/specific",
|
|
22
|
+
"link:binary:staging": "NODE_ENV=staging npm run build:binary && codesign -s - dist/specific && cp dist/specific ~/.local/bin/specific",
|
|
23
|
+
"link:binary:prod": "npm run build:binary && codesign -s - dist/specific && cp dist/specific ~/.local/bin/specific"
|
|
21
24
|
},
|
|
22
25
|
"keywords": [
|
|
23
26
|
"infrastructure",
|
/package/dist/admin/_next/static/{P3VZVUKKu1Qjrf-CPDzDC → -uB2tvCTW06hUMOZfRURZ}/_buildManifest.js
RENAMED
|
File without changes
|
|
File without changes
|
/package/dist/admin/_next/static/{P3VZVUKKu1Qjrf-CPDzDC → -uB2tvCTW06hUMOZfRURZ}/_ssgManifest.js
RENAMED
|
File without changes
|