@specific.dev/cli 0.1.114 → 0.1.116
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 +266 -231
- package/package.json +1 -1
- /package/dist/admin/_next/static/{bgRGrZnID0BykUNK10yK_ → t-VQmQIYeEfVRQc8YYQbq}/_buildManifest.js +0 -0
- /package/dist/admin/_next/static/{bgRGrZnID0BykUNK10yK_ → t-VQmQIYeEfVRQc8YYQbq}/_clientMiddlewareManifest.json +0 -0
- /package/dist/admin/_next/static/{bgRGrZnID0BykUNK10yK_ → t-VQmQIYeEfVRQc8YYQbq}/_ssgManifest.js +0 -0
package/dist/cli.js
CHANGED
|
@@ -367514,8 +367514,14 @@ var ApiClient = class {
|
|
|
367514
367514
|
Authorization: `Bearer ${token}`
|
|
367515
367515
|
};
|
|
367516
367516
|
}
|
|
367517
|
-
async createDeployment(projectId, environment) {
|
|
367518
|
-
const requestBody = {
|
|
367517
|
+
async createDeployment(projectId, environment, options2) {
|
|
367518
|
+
const requestBody = {
|
|
367519
|
+
projectId,
|
|
367520
|
+
environment,
|
|
367521
|
+
...options2?.triggeredBy && { triggeredBy: options2.triggeredBy },
|
|
367522
|
+
...options2?.gitCommitSha && { gitCommitSha: options2.gitCommitSha },
|
|
367523
|
+
...options2?.gitBranch && { gitBranch: options2.gitBranch }
|
|
367524
|
+
};
|
|
367519
367525
|
writeLog("api", `POST ${this.baseUrl}/deployments`);
|
|
367520
367526
|
writeLog("api", `Request body: ${JSON.stringify(requestBody)}`);
|
|
367521
367527
|
const response = await fetch(`${this.baseUrl}/deployments`, {
|
|
@@ -367862,9 +367868,9 @@ var SpecificClient = class {
|
|
|
367862
367868
|
return await this.client.getMe();
|
|
367863
367869
|
}
|
|
367864
367870
|
// --- Deployments ---
|
|
367865
|
-
async createDeployment(projectId, environment) {
|
|
367871
|
+
async createDeployment(projectId, environment, options2) {
|
|
367866
367872
|
return toDeployment(
|
|
367867
|
-
await this.client.createDeployment(projectId, environment)
|
|
367873
|
+
await this.client.createDeployment(projectId, environment, options2)
|
|
367868
367874
|
);
|
|
367869
367875
|
}
|
|
367870
367876
|
async uploadTarball(deploymentId, tarball, appPath) {
|
|
@@ -369210,6 +369216,22 @@ var temporalBinary = {
|
|
|
369210
369216
|
stripComponents: 0,
|
|
369211
369217
|
executables: ["temporal"]
|
|
369212
369218
|
};
|
|
369219
|
+
function killProcess(proc) {
|
|
369220
|
+
return new Promise((resolve52) => {
|
|
369221
|
+
if (proc.killed || proc.exitCode !== null) {
|
|
369222
|
+
resolve52();
|
|
369223
|
+
return;
|
|
369224
|
+
}
|
|
369225
|
+
proc.once("exit", () => resolve52());
|
|
369226
|
+
proc.kill("SIGKILL");
|
|
369227
|
+
});
|
|
369228
|
+
}
|
|
369229
|
+
function killProcessGroup(pid) {
|
|
369230
|
+
try {
|
|
369231
|
+
process.kill(-pid, "SIGKILL");
|
|
369232
|
+
} catch {
|
|
369233
|
+
}
|
|
369234
|
+
}
|
|
369213
369235
|
async function startPostgres(pg, port, dataDir, onProgress) {
|
|
369214
369236
|
const binary = await ensureBinary(postgresBinary, void 0, onProgress);
|
|
369215
369237
|
const dbDataPath = path5.join(process.cwd(), dataDir, pg.name);
|
|
@@ -369276,8 +369298,9 @@ async function startPostgres(pg, port, dataDir, onProgress) {
|
|
|
369276
369298
|
password,
|
|
369277
369299
|
dbName: pg.name,
|
|
369278
369300
|
url: `postgres://${user}:${password}@${host}:${port}/${pg.name}`,
|
|
369301
|
+
pid: postgres.pid,
|
|
369279
369302
|
async stop() {
|
|
369280
|
-
return
|
|
369303
|
+
return killProcess(postgres);
|
|
369281
369304
|
}
|
|
369282
369305
|
};
|
|
369283
369306
|
}
|
|
@@ -369302,8 +369325,9 @@ async function startRedis(redis, port, onProgress) {
|
|
|
369302
369325
|
password: "",
|
|
369303
369326
|
dbName: redis.name,
|
|
369304
369327
|
url: `redis://${host}:${port}`,
|
|
369328
|
+
pid: redisProc.pid,
|
|
369305
369329
|
async stop() {
|
|
369306
|
-
return
|
|
369330
|
+
return killProcess(redisProc);
|
|
369307
369331
|
}
|
|
369308
369332
|
};
|
|
369309
369333
|
}
|
|
@@ -369340,6 +369364,7 @@ async function startStorage(storage, port, dataDir) {
|
|
|
369340
369364
|
secretKey,
|
|
369341
369365
|
bucket: storage.name,
|
|
369342
369366
|
async stop() {
|
|
369367
|
+
server.httpServer?.closeAllConnections?.();
|
|
369343
369368
|
await server.close();
|
|
369344
369369
|
}
|
|
369345
369370
|
};
|
|
@@ -369417,24 +369442,6 @@ function checkTcpPort(host, port) {
|
|
|
369417
369442
|
socket.connect(port, host);
|
|
369418
369443
|
});
|
|
369419
369444
|
}
|
|
369420
|
-
async function stopProcess(proc) {
|
|
369421
|
-
return new Promise((resolve52) => {
|
|
369422
|
-
if (proc.killed || proc.exitCode !== null) {
|
|
369423
|
-
resolve52();
|
|
369424
|
-
return;
|
|
369425
|
-
}
|
|
369426
|
-
proc.once("exit", () => {
|
|
369427
|
-
clearTimeout(forceKillTimeout);
|
|
369428
|
-
resolve52();
|
|
369429
|
-
});
|
|
369430
|
-
proc.kill("SIGTERM");
|
|
369431
|
-
const forceKillTimeout = setTimeout(() => {
|
|
369432
|
-
if (!proc.killed && proc.exitCode === null) {
|
|
369433
|
-
proc.kill("SIGKILL");
|
|
369434
|
-
}
|
|
369435
|
-
}, 2e3);
|
|
369436
|
-
});
|
|
369437
|
-
}
|
|
369438
369445
|
function sleep(ms) {
|
|
369439
369446
|
return new Promise((resolve52) => setTimeout(resolve52, ms));
|
|
369440
369447
|
}
|
|
@@ -369458,7 +369465,7 @@ async function parseLocalFile(content) {
|
|
|
369458
369465
|
if (block && typeof block === "object") {
|
|
369459
369466
|
for (const [key, value] of Object.entries(block)) {
|
|
369460
369467
|
if (typeof value === "string") {
|
|
369461
|
-
secrets.set(key, value);
|
|
369468
|
+
secrets.set(key, value.trimEnd());
|
|
369462
369469
|
}
|
|
369463
369470
|
}
|
|
369464
369471
|
}
|
|
@@ -369470,7 +369477,7 @@ async function parseLocalFile(content) {
|
|
|
369470
369477
|
if (block && typeof block === "object") {
|
|
369471
369478
|
for (const [key, value] of Object.entries(block)) {
|
|
369472
369479
|
if (typeof value === "string") {
|
|
369473
|
-
configs.set(key, value);
|
|
369480
|
+
configs.set(key, value.trimEnd());
|
|
369474
369481
|
}
|
|
369475
369482
|
}
|
|
369476
369483
|
}
|
|
@@ -369485,57 +369492,42 @@ async function loadLocal() {
|
|
|
369485
369492
|
const content = await readFile(LOCAL_FILE, "utf-8");
|
|
369486
369493
|
return await parseLocalFile(content);
|
|
369487
369494
|
}
|
|
369488
|
-
function
|
|
369489
|
-
|
|
369495
|
+
function formatHclValue(value) {
|
|
369496
|
+
if (value.includes("\n")) {
|
|
369497
|
+
return `<<-EOT
|
|
369498
|
+
${value}
|
|
369499
|
+
EOT`;
|
|
369500
|
+
}
|
|
369501
|
+
const escaped = value.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
|
|
369502
|
+
return `"${escaped}"`;
|
|
369490
369503
|
}
|
|
369491
|
-
function
|
|
369492
|
-
const
|
|
369493
|
-
const
|
|
369494
|
-
|
|
369495
|
-
|
|
369496
|
-
|
|
369497
|
-
|
|
369498
|
-
const keyRegex = new RegExp(`^(\\s*)${key}\\s*=\\s*"[^"]*"\\s*$`, "m");
|
|
369499
|
-
const keyMatch = blockContent.match(keyRegex);
|
|
369500
|
-
if (keyMatch) {
|
|
369501
|
-
const updatedBlockContent = blockContent.replace(keyRegex, newLine);
|
|
369502
|
-
return content.replace(blockRegex, `$1${updatedBlockContent}$3`);
|
|
369503
|
-
} else {
|
|
369504
|
-
const trimmedContent = blockContent.trimEnd();
|
|
369505
|
-
const newBlockContent = trimmedContent ? `${trimmedContent}
|
|
369506
|
-
${newLine}
|
|
369507
|
-
` : `
|
|
369508
|
-
${newLine}
|
|
369509
|
-
`;
|
|
369510
|
-
return content.replace(blockRegex, `$1${newBlockContent}$3`);
|
|
369511
|
-
}
|
|
369512
|
-
} else {
|
|
369513
|
-
const newBlock = `${blockName} {
|
|
369514
|
-
${newLine}
|
|
369504
|
+
function serializeBlock(blockName, entries) {
|
|
369505
|
+
const lines = [`${blockName} {`];
|
|
369506
|
+
for (const [key, value] of entries) {
|
|
369507
|
+
lines.push(` ${key} = ${formatHclValue(value)}`);
|
|
369508
|
+
}
|
|
369509
|
+
lines.push("}");
|
|
369510
|
+
return lines.join("\n");
|
|
369515
369511
|
}
|
|
369516
|
-
|
|
369517
|
-
|
|
369512
|
+
function serializeLocalFile(secrets, configs) {
|
|
369513
|
+
const blocks = [];
|
|
369514
|
+
if (secrets.size > 0) {
|
|
369515
|
+
blocks.push(serializeBlock("secrets", secrets));
|
|
369516
|
+
}
|
|
369517
|
+
if (configs.size > 0) {
|
|
369518
|
+
blocks.push(serializeBlock("config", configs));
|
|
369518
369519
|
}
|
|
369520
|
+
return HEADER_COMMENT + blocks.join("\n\n") + "\n";
|
|
369519
369521
|
}
|
|
369520
369522
|
async function saveLocalSecret(name, value) {
|
|
369521
|
-
|
|
369522
|
-
|
|
369523
|
-
|
|
369524
|
-
} else {
|
|
369525
|
-
content = HEADER_COMMENT;
|
|
369526
|
-
}
|
|
369527
|
-
content = updateBlockValue(content, "secrets", name, value);
|
|
369528
|
-
await writeFile(LOCAL_FILE, content);
|
|
369523
|
+
const { secrets, configs } = existsSync5(LOCAL_FILE) ? await parseLocalFile(await readFile(LOCAL_FILE, "utf-8")) : { secrets: /* @__PURE__ */ new Map(), configs: /* @__PURE__ */ new Map() };
|
|
369524
|
+
secrets.set(name, value);
|
|
369525
|
+
await writeFile(LOCAL_FILE, serializeLocalFile(secrets, configs));
|
|
369529
369526
|
}
|
|
369530
369527
|
async function saveLocalConfig(name, value) {
|
|
369531
|
-
|
|
369532
|
-
|
|
369533
|
-
|
|
369534
|
-
} else {
|
|
369535
|
-
content = HEADER_COMMENT;
|
|
369536
|
-
}
|
|
369537
|
-
content = updateBlockValue(content, "config", name, value);
|
|
369538
|
-
await writeFile(LOCAL_FILE, content);
|
|
369528
|
+
const { secrets, configs } = existsSync5(LOCAL_FILE) ? await parseLocalFile(await readFile(LOCAL_FILE, "utf-8")) : { secrets: /* @__PURE__ */ new Map(), configs: /* @__PURE__ */ new Map() };
|
|
369529
|
+
configs.set(name, value);
|
|
369530
|
+
await writeFile(LOCAL_FILE, serializeLocalFile(secrets, configs));
|
|
369539
369531
|
}
|
|
369540
369532
|
function appendSearchPathToUrl(baseUrl, searchPath) {
|
|
369541
369533
|
const url = new URL(baseUrl);
|
|
@@ -369922,29 +369914,13 @@ function startService(service, resources, secrets, configs, endpointPorts, servi
|
|
|
369922
369914
|
resolve52();
|
|
369923
369915
|
return;
|
|
369924
369916
|
}
|
|
369925
|
-
child.once("exit", () =>
|
|
369926
|
-
clearTimeout(forceKillTimeout);
|
|
369927
|
-
resolve52();
|
|
369928
|
-
});
|
|
369917
|
+
child.once("exit", () => resolve52());
|
|
369929
369918
|
const pid = child.pid;
|
|
369930
369919
|
if (pid) {
|
|
369931
|
-
|
|
369932
|
-
process.kill(-pid, "SIGTERM");
|
|
369933
|
-
} catch {
|
|
369934
|
-
}
|
|
369920
|
+
killProcessGroup(pid);
|
|
369935
369921
|
} else {
|
|
369936
|
-
child.kill("
|
|
369922
|
+
child.kill("SIGKILL");
|
|
369937
369923
|
}
|
|
369938
|
-
const forceKillTimeout = setTimeout(() => {
|
|
369939
|
-
if (pid) {
|
|
369940
|
-
try {
|
|
369941
|
-
process.kill(-pid, "SIGKILL");
|
|
369942
|
-
} catch {
|
|
369943
|
-
}
|
|
369944
|
-
} else if (!child.killed) {
|
|
369945
|
-
child.kill("SIGKILL");
|
|
369946
|
-
}
|
|
369947
|
-
}, 2e3);
|
|
369948
369924
|
});
|
|
369949
369925
|
}
|
|
369950
369926
|
};
|
|
@@ -370389,6 +370365,7 @@ async function startAdminServer(getState, listenPort = 0) {
|
|
|
370389
370365
|
port,
|
|
370390
370366
|
stop: () => new Promise((res, rej) => {
|
|
370391
370367
|
server.close((err) => err ? rej(err) : res());
|
|
370368
|
+
server.closeAllConnections();
|
|
370392
370369
|
})
|
|
370393
370370
|
});
|
|
370394
370371
|
});
|
|
@@ -370539,7 +370516,7 @@ async function startElectric(postgres, port, dataDir, options2) {
|
|
|
370539
370516
|
url: `http://${host}:${port}`,
|
|
370540
370517
|
secret,
|
|
370541
370518
|
async stop() {
|
|
370542
|
-
return
|
|
370519
|
+
return killProcess(electric);
|
|
370543
370520
|
}
|
|
370544
370521
|
};
|
|
370545
370522
|
}
|
|
@@ -370573,24 +370550,6 @@ function checkTcpPort2(host, port) {
|
|
|
370573
370550
|
socket.connect(port, host);
|
|
370574
370551
|
});
|
|
370575
370552
|
}
|
|
370576
|
-
async function stopProcess2(proc) {
|
|
370577
|
-
return new Promise((resolve52) => {
|
|
370578
|
-
if (proc.killed || proc.exitCode !== null) {
|
|
370579
|
-
resolve52();
|
|
370580
|
-
return;
|
|
370581
|
-
}
|
|
370582
|
-
proc.once("exit", () => {
|
|
370583
|
-
clearTimeout(forceKillTimeout);
|
|
370584
|
-
resolve52();
|
|
370585
|
-
});
|
|
370586
|
-
proc.kill("SIGTERM");
|
|
370587
|
-
const forceKillTimeout = setTimeout(() => {
|
|
370588
|
-
if (!proc.killed && proc.exitCode === null) {
|
|
370589
|
-
proc.kill("SIGKILL");
|
|
370590
|
-
}
|
|
370591
|
-
}, 2e3);
|
|
370592
|
-
});
|
|
370593
|
-
}
|
|
370594
370553
|
function sleep2(ms) {
|
|
370595
370554
|
return new Promise((resolve52) => setTimeout(resolve52, ms));
|
|
370596
370555
|
}
|
|
@@ -370692,12 +370651,11 @@ async function startMailServer(mail, smtpPort, apiPort) {
|
|
|
370692
370651
|
httpServer.on("error", reject);
|
|
370693
370652
|
});
|
|
370694
370653
|
const stop = async () => {
|
|
370695
|
-
|
|
370696
|
-
|
|
370697
|
-
|
|
370698
|
-
|
|
370699
|
-
|
|
370700
|
-
});
|
|
370654
|
+
httpServer.closeAllConnections();
|
|
370655
|
+
await Promise.all([
|
|
370656
|
+
new Promise((resolve52) => smtpServer.close(() => resolve52())),
|
|
370657
|
+
new Promise((resolve52) => httpServer.close(() => resolve52()))
|
|
370658
|
+
]);
|
|
370701
370659
|
};
|
|
370702
370660
|
const resource = {
|
|
370703
370661
|
name: mail.name,
|
|
@@ -370774,8 +370732,9 @@ async function startDrizzleGateway(postgresInstances, port, configDir, options2)
|
|
|
370774
370732
|
return {
|
|
370775
370733
|
port,
|
|
370776
370734
|
url: `http://${host}:${port}`,
|
|
370735
|
+
pid: drizzleGateway.pid,
|
|
370777
370736
|
async stop() {
|
|
370778
|
-
return
|
|
370737
|
+
return killProcess(drizzleGateway);
|
|
370779
370738
|
}
|
|
370780
370739
|
};
|
|
370781
370740
|
}
|
|
@@ -370811,24 +370770,6 @@ function checkTcpPort3(host, port) {
|
|
|
370811
370770
|
socket.connect(port, host);
|
|
370812
370771
|
});
|
|
370813
370772
|
}
|
|
370814
|
-
async function stopProcess3(proc) {
|
|
370815
|
-
return new Promise((resolve52) => {
|
|
370816
|
-
if (proc.killed || proc.exitCode !== null) {
|
|
370817
|
-
resolve52();
|
|
370818
|
-
return;
|
|
370819
|
-
}
|
|
370820
|
-
proc.once("exit", () => {
|
|
370821
|
-
clearTimeout(forceKillTimeout);
|
|
370822
|
-
resolve52();
|
|
370823
|
-
});
|
|
370824
|
-
proc.kill("SIGTERM");
|
|
370825
|
-
const forceKillTimeout = setTimeout(() => {
|
|
370826
|
-
if (!proc.killed && proc.exitCode === null) {
|
|
370827
|
-
proc.kill("SIGKILL");
|
|
370828
|
-
}
|
|
370829
|
-
}, 2e3);
|
|
370830
|
-
});
|
|
370831
|
-
}
|
|
370832
370773
|
function sleep3(ms) {
|
|
370833
370774
|
return new Promise((resolve52) => setTimeout(resolve52, ms));
|
|
370834
370775
|
}
|
|
@@ -371169,7 +371110,7 @@ async function startTemporalDevServer(temporals, grpcPort, uiPort, dataDir, onPr
|
|
|
371169
371110
|
);
|
|
371170
371111
|
pipeProcess("temporal", proc);
|
|
371171
371112
|
await waitForTcpPort4(host, grpcPort);
|
|
371172
|
-
const stopServer = () =>
|
|
371113
|
+
const stopServer = () => killProcess(proc);
|
|
371173
371114
|
const instances = temporals.map((temporal, i) => ({
|
|
371174
371115
|
name: temporal.name,
|
|
371175
371116
|
type: "temporal",
|
|
@@ -371180,6 +371121,7 @@ async function startTemporalDevServer(temporals, grpcPort, uiPort, dataDir, onPr
|
|
|
371180
371121
|
dbName: temporal.name,
|
|
371181
371122
|
url: `${host}:${grpcPort}`,
|
|
371182
371123
|
uiPort,
|
|
371124
|
+
pid: i === 0 ? proc.pid : void 0,
|
|
371183
371125
|
// Only the first instance owns the server lifecycle
|
|
371184
371126
|
stop: i === 0 ? stopServer : async () => {
|
|
371185
371127
|
}
|
|
@@ -371216,24 +371158,6 @@ function checkTcpPort4(host, port) {
|
|
|
371216
371158
|
socket.connect(port, host);
|
|
371217
371159
|
});
|
|
371218
371160
|
}
|
|
371219
|
-
async function stopProcess4(proc) {
|
|
371220
|
-
return new Promise((resolve52) => {
|
|
371221
|
-
if (proc.killed || proc.exitCode !== null) {
|
|
371222
|
-
resolve52();
|
|
371223
|
-
return;
|
|
371224
|
-
}
|
|
371225
|
-
proc.once("exit", () => {
|
|
371226
|
-
clearTimeout(forceKillTimeout);
|
|
371227
|
-
resolve52();
|
|
371228
|
-
});
|
|
371229
|
-
proc.kill("SIGTERM");
|
|
371230
|
-
const forceKillTimeout = setTimeout(() => {
|
|
371231
|
-
if (!proc.killed && proc.exitCode === null) {
|
|
371232
|
-
proc.kill("SIGKILL");
|
|
371233
|
-
}
|
|
371234
|
-
}, 2e3);
|
|
371235
|
-
});
|
|
371236
|
-
}
|
|
371237
371161
|
function findRequiredResources(service) {
|
|
371238
371162
|
const required = { postgres: [], redis: [], storage: [], temporal: [], mail: [] };
|
|
371239
371163
|
if (service.env) {
|
|
@@ -371909,28 +371833,35 @@ var DevEnvironment = class extends TypedEventEmitter {
|
|
|
371909
371833
|
* Fire-and-forget stop all processes without waiting.
|
|
371910
371834
|
*/
|
|
371911
371835
|
forceStop() {
|
|
371912
|
-
|
|
371913
|
-
|
|
371914
|
-
const
|
|
371915
|
-
|
|
371916
|
-
|
|
371917
|
-
|
|
371918
|
-
|
|
371919
|
-
|
|
371920
|
-
|
|
371921
|
-
for (const proc of allProcesses) {
|
|
371836
|
+
this.systemLog("Force shutting down");
|
|
371837
|
+
for (const service of this.services) {
|
|
371838
|
+
const pid = service.process.pid;
|
|
371839
|
+
if (pid) {
|
|
371840
|
+
killProcessGroup(pid);
|
|
371841
|
+
}
|
|
371842
|
+
}
|
|
371843
|
+
for (const electric of this.electricInstances) {
|
|
371844
|
+
if (electric.pid) {
|
|
371922
371845
|
try {
|
|
371923
|
-
|
|
371924
|
-
|
|
371846
|
+
process.kill(electric.pid, "SIGKILL");
|
|
371847
|
+
} catch {
|
|
371848
|
+
}
|
|
371849
|
+
}
|
|
371850
|
+
}
|
|
371851
|
+
if (this.drizzleGateway?.pid) {
|
|
371852
|
+
try {
|
|
371853
|
+
process.kill(this.drizzleGateway.pid, "SIGKILL");
|
|
371854
|
+
} catch {
|
|
371855
|
+
}
|
|
371856
|
+
}
|
|
371857
|
+
for (const resource of this.resources.values()) {
|
|
371858
|
+
if (resource.pid) {
|
|
371859
|
+
try {
|
|
371860
|
+
process.kill(resource.pid, "SIGKILL");
|
|
371925
371861
|
} catch {
|
|
371926
371862
|
}
|
|
371927
371863
|
}
|
|
371928
|
-
return;
|
|
371929
371864
|
}
|
|
371930
|
-
this.shuttingDown = true;
|
|
371931
|
-
this.cancelled = true;
|
|
371932
|
-
this.shutdownInternal().catch(() => {
|
|
371933
|
-
});
|
|
371934
371865
|
}
|
|
371935
371866
|
/**
|
|
371936
371867
|
* Reload the dev environment (stop everything except release instance ownership completely, then restart).
|
|
@@ -372044,13 +371975,11 @@ var DevEnvironment = class extends TypedEventEmitter {
|
|
|
372044
371975
|
...this.reshapeWatchers.map((watcher) => watcher.close()),
|
|
372045
371976
|
this.drizzleGateway?.stop(),
|
|
372046
371977
|
...[...this.resources.values()].map((resource) => resource.stop()),
|
|
372047
|
-
...this.tunnels.map((tunnel) => tunnel.stop())
|
|
371978
|
+
...this.tunnels.map((tunnel) => tunnel.stop()),
|
|
371979
|
+
this.stateManager?.releaseOwnership()
|
|
372048
371980
|
]);
|
|
372049
371981
|
this.reshapeWatchers = [];
|
|
372050
371982
|
this.restartServices = null;
|
|
372051
|
-
if (this.stateManager) {
|
|
372052
|
-
await this.stateManager.releaseOwnership();
|
|
372053
|
-
}
|
|
372054
371983
|
this.removeExitHandler();
|
|
372055
371984
|
this.systemLog("Shutdown complete");
|
|
372056
371985
|
closeDebugLog();
|
|
@@ -372070,6 +371999,15 @@ var DevEnvironment = class extends TypedEventEmitter {
|
|
|
372070
371999
|
registerExitHandler() {
|
|
372071
372000
|
this.removeExitHandler();
|
|
372072
372001
|
this.exitHandler = () => {
|
|
372002
|
+
for (const service of this.services) {
|
|
372003
|
+
const pid = service.process.pid;
|
|
372004
|
+
if (pid) {
|
|
372005
|
+
try {
|
|
372006
|
+
process.kill(-pid, "SIGKILL");
|
|
372007
|
+
} catch {
|
|
372008
|
+
}
|
|
372009
|
+
}
|
|
372010
|
+
}
|
|
372073
372011
|
for (const electric of this.electricInstances) {
|
|
372074
372012
|
if (electric.pid) {
|
|
372075
372013
|
try {
|
|
@@ -372078,11 +372016,16 @@ var DevEnvironment = class extends TypedEventEmitter {
|
|
|
372078
372016
|
}
|
|
372079
372017
|
}
|
|
372080
372018
|
}
|
|
372081
|
-
|
|
372082
|
-
|
|
372083
|
-
|
|
372019
|
+
if (this.drizzleGateway?.pid) {
|
|
372020
|
+
try {
|
|
372021
|
+
process.kill(this.drizzleGateway.pid, "SIGKILL");
|
|
372022
|
+
} catch {
|
|
372023
|
+
}
|
|
372024
|
+
}
|
|
372025
|
+
for (const resource of this.resources.values()) {
|
|
372026
|
+
if (resource.pid) {
|
|
372084
372027
|
try {
|
|
372085
|
-
process.kill(
|
|
372028
|
+
process.kill(resource.pid, "SIGKILL");
|
|
372086
372029
|
} catch {
|
|
372087
372030
|
}
|
|
372088
372031
|
}
|
|
@@ -373287,7 +373230,7 @@ function trackEvent(event, properties) {
|
|
|
373287
373230
|
event,
|
|
373288
373231
|
properties: {
|
|
373289
373232
|
...properties,
|
|
373290
|
-
cli_version: "0.1.
|
|
373233
|
+
cli_version: "0.1.116",
|
|
373291
373234
|
platform: process.platform,
|
|
373292
373235
|
node_version: process.version,
|
|
373293
373236
|
project_id: getProjectId()
|
|
@@ -373296,7 +373239,7 @@ function trackEvent(event, properties) {
|
|
|
373296
373239
|
}
|
|
373297
373240
|
async function shutdown() {
|
|
373298
373241
|
if (client) {
|
|
373299
|
-
await client.shutdown();
|
|
373242
|
+
await client.shutdown(1e3);
|
|
373300
373243
|
client = null;
|
|
373301
373244
|
}
|
|
373302
373245
|
}
|
|
@@ -374520,53 +374463,113 @@ function checkCommand() {
|
|
|
374520
374463
|
}
|
|
374521
374464
|
|
|
374522
374465
|
// src/commands/dev.tsx
|
|
374523
|
-
import React6, { useState as useState5, useEffect as
|
|
374466
|
+
import React6, { useState as useState5, useEffect as useEffect5, useRef as useRef3 } from "react";
|
|
374524
374467
|
import { render as render4, Text as Text6, Box as Box6, useApp as useApp2, Static } from "ink";
|
|
374525
374468
|
import Spinner3 from "ink-spinner";
|
|
374526
374469
|
import { Readable as Readable2 } from "stream";
|
|
374527
374470
|
|
|
374528
374471
|
// src/lib/ui/SecretInput.tsx
|
|
374529
|
-
import React4, { useState as useState3 } from "react";
|
|
374472
|
+
import React4, { useState as useState3, useRef, useCallback, useEffect as useEffect3 } from "react";
|
|
374530
374473
|
import { Box as Box4, Text as Text4, useInput as useInput2 } from "ink";
|
|
374474
|
+
var PASTE_DETECT_DELAY_MS = 100;
|
|
374531
374475
|
function SecretInput({ secretName, onSubmit, onCancel }) {
|
|
374532
374476
|
const [value, setValue] = useState3("");
|
|
374477
|
+
const valueRef = useRef("");
|
|
374478
|
+
const submitTimer = useRef(null);
|
|
374479
|
+
useEffect3(() => {
|
|
374480
|
+
valueRef.current = value;
|
|
374481
|
+
}, [value]);
|
|
374482
|
+
const scheduleSubmit = useCallback(() => {
|
|
374483
|
+
if (submitTimer.current) {
|
|
374484
|
+
clearTimeout(submitTimer.current);
|
|
374485
|
+
}
|
|
374486
|
+
submitTimer.current = setTimeout(() => {
|
|
374487
|
+
submitTimer.current = null;
|
|
374488
|
+
if (valueRef.current.trim() !== "") {
|
|
374489
|
+
onSubmit(valueRef.current);
|
|
374490
|
+
}
|
|
374491
|
+
}, PASTE_DETECT_DELAY_MS);
|
|
374492
|
+
}, [onSubmit]);
|
|
374493
|
+
const cancelSubmit = useCallback(() => {
|
|
374494
|
+
if (submitTimer.current) {
|
|
374495
|
+
clearTimeout(submitTimer.current);
|
|
374496
|
+
submitTimer.current = null;
|
|
374497
|
+
setValue((prev) => prev + "\n");
|
|
374498
|
+
}
|
|
374499
|
+
}, []);
|
|
374500
|
+
useEffect3(() => {
|
|
374501
|
+
return () => {
|
|
374502
|
+
if (submitTimer.current) clearTimeout(submitTimer.current);
|
|
374503
|
+
};
|
|
374504
|
+
}, []);
|
|
374533
374505
|
useInput2((input, key) => {
|
|
374534
374506
|
if (key.return) {
|
|
374535
|
-
|
|
374536
|
-
onSubmit(value);
|
|
374537
|
-
}
|
|
374507
|
+
scheduleSubmit();
|
|
374538
374508
|
} else if (key.escape) {
|
|
374539
374509
|
onCancel();
|
|
374540
374510
|
} else if (key.backspace || key.delete) {
|
|
374511
|
+
cancelSubmit();
|
|
374541
374512
|
setValue((prev) => prev.slice(0, -1));
|
|
374542
374513
|
} else if (!key.ctrl && !key.meta && input) {
|
|
374514
|
+
cancelSubmit();
|
|
374543
374515
|
setValue((prev) => prev + input);
|
|
374544
374516
|
}
|
|
374545
374517
|
});
|
|
374546
|
-
|
|
374518
|
+
const lineCount = value.split("\n").length;
|
|
374519
|
+
return /* @__PURE__ */ React4.createElement(Box4, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React4.createElement(Text4, null, "Enter value for secret ", /* @__PURE__ */ React4.createElement(Text4, { color: "cyan" }, secretName), ":"), /* @__PURE__ */ React4.createElement(Box4, null, /* @__PURE__ */ React4.createElement(Text4, { color: "cyan" }, "> "), /* @__PURE__ */ React4.createElement(Text4, null, value.length > 0 ? lineCount > 1 ? `[${lineCount} lines, ${value.length} chars]` : "*".repeat(value.length) : ""), /* @__PURE__ */ React4.createElement(Text4, { color: "gray" }, "|")), /* @__PURE__ */ React4.createElement(Text4, { dimColor: true }, "(Press Enter to save, Esc to cancel)"));
|
|
374547
374520
|
}
|
|
374548
374521
|
|
|
374549
374522
|
// src/lib/ui/ConfigInput.tsx
|
|
374550
|
-
import React5, { useState as useState4 } from "react";
|
|
374523
|
+
import React5, { useState as useState4, useRef as useRef2, useCallback as useCallback2, useEffect as useEffect4 } from "react";
|
|
374551
374524
|
import { Box as Box5, Text as Text5, useInput as useInput3 } from "ink";
|
|
374525
|
+
var PASTE_DETECT_DELAY_MS2 = 100;
|
|
374552
374526
|
function ConfigInput({ configName, defaultValue, onSubmit, onCancel }) {
|
|
374553
374527
|
const [value, setValue] = useState4("");
|
|
374554
|
-
|
|
374555
|
-
|
|
374556
|
-
|
|
374557
|
-
|
|
374528
|
+
const valueRef = useRef2("");
|
|
374529
|
+
const submitTimer = useRef2(null);
|
|
374530
|
+
useEffect4(() => {
|
|
374531
|
+
valueRef.current = value;
|
|
374532
|
+
}, [value]);
|
|
374533
|
+
const scheduleSubmit = useCallback2(() => {
|
|
374534
|
+
if (submitTimer.current) {
|
|
374535
|
+
clearTimeout(submitTimer.current);
|
|
374536
|
+
}
|
|
374537
|
+
submitTimer.current = setTimeout(() => {
|
|
374538
|
+
submitTimer.current = null;
|
|
374539
|
+
if (valueRef.current.trim() !== "") {
|
|
374540
|
+
onSubmit(valueRef.current);
|
|
374558
374541
|
} else if (defaultValue !== void 0) {
|
|
374559
374542
|
onSubmit(defaultValue);
|
|
374560
374543
|
}
|
|
374544
|
+
}, PASTE_DETECT_DELAY_MS2);
|
|
374545
|
+
}, [onSubmit, defaultValue]);
|
|
374546
|
+
const cancelSubmit = useCallback2(() => {
|
|
374547
|
+
if (submitTimer.current) {
|
|
374548
|
+
clearTimeout(submitTimer.current);
|
|
374549
|
+
submitTimer.current = null;
|
|
374550
|
+
setValue((prev) => prev + "\n");
|
|
374551
|
+
}
|
|
374552
|
+
}, []);
|
|
374553
|
+
useEffect4(() => {
|
|
374554
|
+
return () => {
|
|
374555
|
+
if (submitTimer.current) clearTimeout(submitTimer.current);
|
|
374556
|
+
};
|
|
374557
|
+
}, []);
|
|
374558
|
+
useInput3((input, key) => {
|
|
374559
|
+
if (key.return) {
|
|
374560
|
+
scheduleSubmit();
|
|
374561
374561
|
} else if (key.escape) {
|
|
374562
374562
|
onCancel();
|
|
374563
374563
|
} else if (key.backspace || key.delete) {
|
|
374564
|
+
cancelSubmit();
|
|
374564
374565
|
setValue((prev) => prev.slice(0, -1));
|
|
374565
374566
|
} else if (!key.ctrl && !key.meta && input) {
|
|
374567
|
+
cancelSubmit();
|
|
374566
374568
|
setValue((prev) => prev + input);
|
|
374567
374569
|
}
|
|
374568
374570
|
});
|
|
374569
|
-
|
|
374571
|
+
const lineCount = value.split("\n").length;
|
|
374572
|
+
return /* @__PURE__ */ React5.createElement(Box5, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React5.createElement(Text5, null, "Enter value for config ", /* @__PURE__ */ React5.createElement(Text5, { color: "cyan" }, configName), defaultValue !== void 0 && /* @__PURE__ */ React5.createElement(Text5, { dimColor: true }, " (default: ", defaultValue, ")"), ":"), /* @__PURE__ */ React5.createElement(Box5, null, /* @__PURE__ */ React5.createElement(Text5, { color: "cyan" }, "> "), /* @__PURE__ */ React5.createElement(Text5, null, lineCount > 1 ? `[${lineCount} lines]` : value), /* @__PURE__ */ React5.createElement(Text5, { color: "gray" }, "|")), /* @__PURE__ */ React5.createElement(Text5, { dimColor: true }, defaultValue !== void 0 ? "(Press Enter to accept default, type to override, Esc to cancel)" : "(Press Enter to save, Esc to cancel)"));
|
|
374570
374573
|
}
|
|
374571
374574
|
|
|
374572
374575
|
// src/commands/dev.tsx
|
|
@@ -374583,8 +374586,8 @@ function DevUI({ instanceKey, tunnelEnabled }) {
|
|
|
374583
374586
|
tunnelUrls: /* @__PURE__ */ new Map(),
|
|
374584
374587
|
tunnelStatus: /* @__PURE__ */ new Map()
|
|
374585
374588
|
});
|
|
374586
|
-
const devEnvRef =
|
|
374587
|
-
const startTimeRef =
|
|
374589
|
+
const devEnvRef = useRef3(null);
|
|
374590
|
+
const startTimeRef = useRef3(null);
|
|
374588
374591
|
const buildColorMap = (config2) => {
|
|
374589
374592
|
const colorMap = /* @__PURE__ */ new Map();
|
|
374590
374593
|
let colorIndex = 0;
|
|
@@ -374610,7 +374613,7 @@ function DevUI({ instanceKey, tunnelEnabled }) {
|
|
|
374610
374613
|
}
|
|
374611
374614
|
return colorMap;
|
|
374612
374615
|
};
|
|
374613
|
-
|
|
374616
|
+
useEffect5(() => {
|
|
374614
374617
|
const devEnv = new DevEnvironment({
|
|
374615
374618
|
projectDir: process.cwd(),
|
|
374616
374619
|
instanceKey,
|
|
@@ -374747,7 +374750,7 @@ function DevUI({ instanceKey, tunnelEnabled }) {
|
|
|
374747
374750
|
devEnvRef.current = null;
|
|
374748
374751
|
};
|
|
374749
374752
|
}, [instanceKey, tunnelEnabled]);
|
|
374750
|
-
|
|
374753
|
+
useEffect5(() => {
|
|
374751
374754
|
const handleSignal = () => {
|
|
374752
374755
|
const devEnv = devEnvRef.current;
|
|
374753
374756
|
if (!devEnv) return;
|
|
@@ -374778,7 +374781,7 @@ function DevUI({ instanceKey, tunnelEnabled }) {
|
|
|
374778
374781
|
process.off("unhandledRejection", handleCrash);
|
|
374779
374782
|
};
|
|
374780
374783
|
}, []);
|
|
374781
|
-
|
|
374784
|
+
useEffect5(() => {
|
|
374782
374785
|
if (state.status === "running" && !startTimeRef.current) {
|
|
374783
374786
|
startTimeRef.current = Date.now();
|
|
374784
374787
|
trackEvent("dev_started");
|
|
@@ -375074,11 +375077,29 @@ function devCommand(instanceKey, tunnelEnabled = false) {
|
|
|
375074
375077
|
|
|
375075
375078
|
// src/commands/deploy.tsx
|
|
375076
375079
|
init_open();
|
|
375077
|
-
import React7, { useState as useState6, useEffect as
|
|
375080
|
+
import React7, { useState as useState6, useEffect as useEffect6, useCallback as useCallback3 } from "react";
|
|
375078
375081
|
import { render as render5, Text as Text7, Box as Box7, useApp as useApp3, useInput as useInput4 } from "ink";
|
|
375079
375082
|
import Spinner4 from "ink-spinner";
|
|
375080
375083
|
import * as fs22 from "fs";
|
|
375081
375084
|
import * as path20 from "path";
|
|
375085
|
+
import { execFileSync as execFileSync2 } from "child_process";
|
|
375086
|
+
function getGitInfo(cwd) {
|
|
375087
|
+
try {
|
|
375088
|
+
const commitSha = execFileSync2("git", ["rev-parse", "HEAD"], {
|
|
375089
|
+
cwd,
|
|
375090
|
+
encoding: "utf-8",
|
|
375091
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
375092
|
+
}).trim();
|
|
375093
|
+
const branch = execFileSync2(
|
|
375094
|
+
"git",
|
|
375095
|
+
["rev-parse", "--abbrev-ref", "HEAD"],
|
|
375096
|
+
{ cwd, encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }
|
|
375097
|
+
).trim();
|
|
375098
|
+
return { commitSha, branch };
|
|
375099
|
+
} catch {
|
|
375100
|
+
return null;
|
|
375101
|
+
}
|
|
375102
|
+
}
|
|
375082
375103
|
function formatBytes(bytes) {
|
|
375083
375104
|
if (bytes < 1024) return `${bytes} B`;
|
|
375084
375105
|
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
|
|
@@ -375224,7 +375245,7 @@ function DeployUI({ environment, config }) {
|
|
|
375224
375245
|
const { exit } = useApp3();
|
|
375225
375246
|
const [state, setState] = useState6({ phase: "checking-auth" });
|
|
375226
375247
|
const clientRef = React7.useRef(null);
|
|
375227
|
-
|
|
375248
|
+
useEffect6(() => {
|
|
375228
375249
|
if (state.phase !== "checking-auth") return;
|
|
375229
375250
|
const projectDir = process.cwd();
|
|
375230
375251
|
if (hasProjectId(projectDir)) {
|
|
@@ -375245,7 +375266,7 @@ function DeployUI({ environment, config }) {
|
|
|
375245
375266
|
}
|
|
375246
375267
|
setState({ phase: "logging-in" });
|
|
375247
375268
|
}, [state.phase]);
|
|
375248
|
-
|
|
375269
|
+
useEffect6(() => {
|
|
375249
375270
|
if (state.phase !== "logging-in") return;
|
|
375250
375271
|
let cancelled = false;
|
|
375251
375272
|
async function startLogin() {
|
|
@@ -375306,7 +375327,7 @@ function DeployUI({ environment, config }) {
|
|
|
375306
375327
|
cancelled = true;
|
|
375307
375328
|
};
|
|
375308
375329
|
}, [state.phase]);
|
|
375309
|
-
|
|
375330
|
+
useEffect6(() => {
|
|
375310
375331
|
if (state.phase !== "loading-projects") return;
|
|
375311
375332
|
let cancelled = false;
|
|
375312
375333
|
async function loadProjects() {
|
|
@@ -375339,7 +375360,7 @@ function DeployUI({ environment, config }) {
|
|
|
375339
375360
|
cancelled = true;
|
|
375340
375361
|
};
|
|
375341
375362
|
}, [state.phase]);
|
|
375342
|
-
const handleProjectSelect =
|
|
375363
|
+
const handleProjectSelect = useCallback3(
|
|
375343
375364
|
(project) => {
|
|
375344
375365
|
if ("type" in project && project.type === "new") {
|
|
375345
375366
|
setState((s) => ({ ...s, phase: "entering-name", selectedOrganizationId: project.orgId }));
|
|
@@ -375354,13 +375375,13 @@ function DeployUI({ environment, config }) {
|
|
|
375354
375375
|
},
|
|
375355
375376
|
[]
|
|
375356
375377
|
);
|
|
375357
|
-
const handleNameSubmit =
|
|
375378
|
+
const handleNameSubmit = useCallback3((name) => {
|
|
375358
375379
|
setState((s) => ({ ...s, phase: "creating-project", newProjectName: name }));
|
|
375359
375380
|
}, []);
|
|
375360
|
-
const handleNameCancel =
|
|
375381
|
+
const handleNameCancel = useCallback3(() => {
|
|
375361
375382
|
setState((s) => ({ ...s, phase: "selecting-project" }));
|
|
375362
375383
|
}, []);
|
|
375363
|
-
|
|
375384
|
+
useEffect6(() => {
|
|
375364
375385
|
if (state.phase !== "creating-project" || !state.newProjectName) return;
|
|
375365
375386
|
let cancelled = false;
|
|
375366
375387
|
async function createProject() {
|
|
@@ -375387,7 +375408,7 @@ function DeployUI({ environment, config }) {
|
|
|
375387
375408
|
cancelled = true;
|
|
375388
375409
|
};
|
|
375389
375410
|
}, [state.phase, state.newProjectName]);
|
|
375390
|
-
const handleSecretSubmit =
|
|
375411
|
+
const handleSecretSubmit = useCallback3((value) => {
|
|
375391
375412
|
setState((s) => {
|
|
375392
375413
|
if (!s.missingSecrets || s.currentSecretIndex === void 0) return s;
|
|
375393
375414
|
const currentSecret2 = s.missingSecrets[s.currentSecretIndex];
|
|
@@ -375410,14 +375431,14 @@ function DeployUI({ environment, config }) {
|
|
|
375410
375431
|
};
|
|
375411
375432
|
});
|
|
375412
375433
|
}, []);
|
|
375413
|
-
const handleSecretCancel =
|
|
375434
|
+
const handleSecretCancel = useCallback3(() => {
|
|
375414
375435
|
setState((s) => ({
|
|
375415
375436
|
...s,
|
|
375416
375437
|
phase: "error",
|
|
375417
375438
|
error: "Deployment cancelled - secrets not provided"
|
|
375418
375439
|
}));
|
|
375419
375440
|
}, []);
|
|
375420
|
-
const handleConfigSubmit =
|
|
375441
|
+
const handleConfigSubmit = useCallback3((value) => {
|
|
375421
375442
|
setState((s) => {
|
|
375422
375443
|
if (!s.missingConfigs || s.currentConfigIndex === void 0) return s;
|
|
375423
375444
|
const currentConfig2 = s.missingConfigs[s.currentConfigIndex];
|
|
@@ -375440,14 +375461,14 @@ function DeployUI({ environment, config }) {
|
|
|
375440
375461
|
};
|
|
375441
375462
|
});
|
|
375442
375463
|
}, []);
|
|
375443
|
-
const handleConfigCancel =
|
|
375464
|
+
const handleConfigCancel = useCallback3(() => {
|
|
375444
375465
|
setState((s) => ({
|
|
375445
375466
|
...s,
|
|
375446
375467
|
phase: "error",
|
|
375447
375468
|
error: "Deployment cancelled - configs not provided"
|
|
375448
375469
|
}));
|
|
375449
375470
|
}, []);
|
|
375450
|
-
|
|
375471
|
+
useEffect6(() => {
|
|
375451
375472
|
const {
|
|
375452
375473
|
phase: phase2,
|
|
375453
375474
|
deployment: deployment2,
|
|
@@ -375489,7 +375510,7 @@ function DeployUI({ environment, config }) {
|
|
|
375489
375510
|
}
|
|
375490
375511
|
})();
|
|
375491
375512
|
}, [state]);
|
|
375492
|
-
|
|
375513
|
+
useEffect6(() => {
|
|
375493
375514
|
const {
|
|
375494
375515
|
phase: phase2,
|
|
375495
375516
|
deployment: deployment2,
|
|
@@ -375531,7 +375552,7 @@ function DeployUI({ environment, config }) {
|
|
|
375531
375552
|
}
|
|
375532
375553
|
})();
|
|
375533
375554
|
}, [state]);
|
|
375534
|
-
|
|
375555
|
+
useEffect6(() => {
|
|
375535
375556
|
if (state.phase !== "creating-tarball" || !state.projectId) return;
|
|
375536
375557
|
let cancelled = false;
|
|
375537
375558
|
async function runDeploy() {
|
|
@@ -375567,7 +375588,14 @@ function DeployUI({ environment, config }) {
|
|
|
375567
375588
|
let deployment2;
|
|
375568
375589
|
try {
|
|
375569
375590
|
writeLog("deploy", `Creating deployment for project ${state.projectId}`);
|
|
375570
|
-
|
|
375591
|
+
const gitInfo = getGitInfo(projectDir);
|
|
375592
|
+
deployment2 = await client2.createDeployment(state.projectId, environment, {
|
|
375593
|
+
triggeredBy: "cli",
|
|
375594
|
+
...gitInfo && {
|
|
375595
|
+
gitCommitSha: gitInfo.commitSha,
|
|
375596
|
+
gitBranch: gitInfo.branch
|
|
375597
|
+
}
|
|
375598
|
+
});
|
|
375571
375599
|
writeLog("deploy", `Deployment created: ${deployment2.id}`);
|
|
375572
375600
|
} catch (err) {
|
|
375573
375601
|
const errorMsg = `Failed to create deployment: ${err instanceof Error ? err.message : String(err)}`;
|
|
@@ -375604,7 +375632,7 @@ function DeployUI({ environment, config }) {
|
|
|
375604
375632
|
cancelled = true;
|
|
375605
375633
|
};
|
|
375606
375634
|
}, [state.projectId, environment, config.builds]);
|
|
375607
|
-
|
|
375635
|
+
useEffect6(() => {
|
|
375608
375636
|
if (state.phase !== "pending" || !state.deployment) return;
|
|
375609
375637
|
let pollInterval;
|
|
375610
375638
|
let cancelled = false;
|
|
@@ -375713,7 +375741,7 @@ function DeployUI({ environment, config }) {
|
|
|
375713
375741
|
if (pollInterval) clearInterval(pollInterval);
|
|
375714
375742
|
};
|
|
375715
375743
|
}, [state.phase, state.deployment?.id]);
|
|
375716
|
-
|
|
375744
|
+
useEffect6(() => {
|
|
375717
375745
|
if (state.phase !== "starting" || !state.deployment) return;
|
|
375718
375746
|
let cancelled = false;
|
|
375719
375747
|
const client2 = clientRef.current;
|
|
@@ -375743,7 +375771,7 @@ function DeployUI({ environment, config }) {
|
|
|
375743
375771
|
cancelled = true;
|
|
375744
375772
|
};
|
|
375745
375773
|
}, [state.phase, state.deployment?.id]);
|
|
375746
|
-
|
|
375774
|
+
useEffect6(() => {
|
|
375747
375775
|
if (state.phase !== "queued" && state.phase !== "deploying" || !state.deployment) return;
|
|
375748
375776
|
let pollInterval;
|
|
375749
375777
|
let cancelled = false;
|
|
@@ -375796,12 +375824,12 @@ function DeployUI({ environment, config }) {
|
|
|
375796
375824
|
if (pollInterval) clearInterval(pollInterval);
|
|
375797
375825
|
};
|
|
375798
375826
|
}, [state.phase, state.deployment?.id]);
|
|
375799
|
-
|
|
375827
|
+
useEffect6(() => {
|
|
375800
375828
|
if (state.phase === "creating-tarball") {
|
|
375801
375829
|
trackEvent("deploy_started", { environment });
|
|
375802
375830
|
}
|
|
375803
375831
|
}, [state.phase, environment]);
|
|
375804
|
-
|
|
375832
|
+
useEffect6(() => {
|
|
375805
375833
|
if (state.phase === "success") {
|
|
375806
375834
|
trackEvent("deploy_succeeded", { environment });
|
|
375807
375835
|
closeDebugLog();
|
|
@@ -376008,7 +376036,14 @@ async function runDeployPipeline(options2) {
|
|
|
376008
376036
|
console.log("Creating deployment...");
|
|
376009
376037
|
let deployment;
|
|
376010
376038
|
try {
|
|
376011
|
-
|
|
376039
|
+
const gitInfo = getGitInfo(projectDir);
|
|
376040
|
+
deployment = await client2.createDeployment(projectId, "prod", {
|
|
376041
|
+
triggeredBy: "cli",
|
|
376042
|
+
...gitInfo && {
|
|
376043
|
+
gitCommitSha: gitInfo.commitSha,
|
|
376044
|
+
gitBranch: gitInfo.branch
|
|
376045
|
+
}
|
|
376046
|
+
});
|
|
376012
376047
|
} catch (err) {
|
|
376013
376048
|
console.error(`Error: Failed to create deployment: ${err instanceof Error ? err.message : String(err)}`);
|
|
376014
376049
|
process.exit(1);
|
|
@@ -376753,14 +376788,14 @@ async function reshapeCommand(action, databaseName, instanceKey = "default") {
|
|
|
376753
376788
|
}
|
|
376754
376789
|
|
|
376755
376790
|
// src/commands/clean.tsx
|
|
376756
|
-
import React8, { useState as useState7, useEffect as
|
|
376791
|
+
import React8, { useState as useState7, useEffect as useEffect7 } from "react";
|
|
376757
376792
|
import { render as render6, Text as Text8, Box as Box8 } from "ink";
|
|
376758
376793
|
import Spinner5 from "ink-spinner";
|
|
376759
376794
|
import * as fs26 from "fs";
|
|
376760
376795
|
import * as path24 from "path";
|
|
376761
376796
|
function CleanUI({ instanceKey }) {
|
|
376762
376797
|
const [state, setState] = useState7({ status: "checking" });
|
|
376763
|
-
|
|
376798
|
+
useEffect7(() => {
|
|
376764
376799
|
async function clean() {
|
|
376765
376800
|
const projectRoot = process.cwd();
|
|
376766
376801
|
const specificDir = path24.join(projectRoot, ".specific");
|
|
@@ -376888,14 +376923,14 @@ async function loginCommand(options2 = {}) {
|
|
|
376888
376923
|
}
|
|
376889
376924
|
|
|
376890
376925
|
// src/commands/logout.tsx
|
|
376891
|
-
import React9, { useState as useState8, useEffect as
|
|
376926
|
+
import React9, { useState as useState8, useEffect as useEffect8 } from "react";
|
|
376892
376927
|
import { render as render7, Text as Text9, useApp as useApp4 } from "ink";
|
|
376893
376928
|
function LogoutUI() {
|
|
376894
376929
|
const { exit } = useApp4();
|
|
376895
376930
|
const [state, setState] = useState8({
|
|
376896
376931
|
phase: "checking"
|
|
376897
376932
|
});
|
|
376898
|
-
|
|
376933
|
+
useEffect8(() => {
|
|
376899
376934
|
if (state.phase !== "checking") return;
|
|
376900
376935
|
if (!isLoggedIn()) {
|
|
376901
376936
|
setState({ phase: "not-logged-in" });
|
|
@@ -376904,7 +376939,7 @@ function LogoutUI() {
|
|
|
376904
376939
|
clearUserCredentials();
|
|
376905
376940
|
setState({ phase: "done" });
|
|
376906
376941
|
}, [state.phase]);
|
|
376907
|
-
|
|
376942
|
+
useEffect8(() => {
|
|
376908
376943
|
if (state.phase === "done" || state.phase === "not-logged-in") {
|
|
376909
376944
|
const timer = setTimeout(() => exit(), 100);
|
|
376910
376945
|
return () => clearTimeout(timer);
|
|
@@ -376923,7 +376958,7 @@ function logoutCommand() {
|
|
|
376923
376958
|
}
|
|
376924
376959
|
|
|
376925
376960
|
// src/commands/beta.tsx
|
|
376926
|
-
import React10, { useState as useState9, useEffect as
|
|
376961
|
+
import React10, { useState as useState9, useEffect as useEffect9 } from "react";
|
|
376927
376962
|
import { render as render8, Text as Text10, Box as Box9, useInput as useInput5, useApp as useApp5 } from "ink";
|
|
376928
376963
|
function BetaToggleUI() {
|
|
376929
376964
|
const { exit } = useApp5();
|
|
@@ -376961,7 +376996,7 @@ function BetaToggleUI() {
|
|
|
376961
376996
|
setSaved(true);
|
|
376962
376997
|
}
|
|
376963
376998
|
});
|
|
376964
|
-
|
|
376999
|
+
useEffect9(() => {
|
|
376965
377000
|
if (saved) {
|
|
376966
377001
|
const timer = setTimeout(() => exit(), 100);
|
|
376967
377002
|
return () => clearTimeout(timer);
|
|
@@ -376999,7 +377034,7 @@ function betaCommand() {
|
|
|
376999
377034
|
}
|
|
377000
377035
|
|
|
377001
377036
|
// src/commands/update.tsx
|
|
377002
|
-
import React11, { useState as useState10, useEffect as
|
|
377037
|
+
import React11, { useState as useState10, useEffect as useEffect10 } from "react";
|
|
377003
377038
|
import { render as render9, Text as Text11, Box as Box10, useApp as useApp6 } from "ink";
|
|
377004
377039
|
import Spinner6 from "ink-spinner";
|
|
377005
377040
|
|
|
@@ -377019,7 +377054,7 @@ function compareVersions(a, b) {
|
|
|
377019
377054
|
return 0;
|
|
377020
377055
|
}
|
|
377021
377056
|
async function checkForUpdate() {
|
|
377022
|
-
const currentVersion = "0.1.
|
|
377057
|
+
const currentVersion = "0.1.116";
|
|
377023
377058
|
const response = await fetch(`${BINARIES_BASE_URL}/latest?t=${Date.now()}`);
|
|
377024
377059
|
if (!response.ok) {
|
|
377025
377060
|
throw new Error(`Failed to check for updates: HTTP ${response.status}`);
|
|
@@ -377115,7 +377150,7 @@ function maybeStartBackgroundUpdate() {
|
|
|
377115
377150
|
function UpdateUI() {
|
|
377116
377151
|
const { exit } = useApp6();
|
|
377117
377152
|
const [state, setState] = useState10({ phase: "checking" });
|
|
377118
|
-
|
|
377153
|
+
useEffect10(() => {
|
|
377119
377154
|
if (state.phase !== "checking") return;
|
|
377120
377155
|
let cancelled = false;
|
|
377121
377156
|
async function check() {
|
|
@@ -377144,7 +377179,7 @@ function UpdateUI() {
|
|
|
377144
377179
|
cancelled = true;
|
|
377145
377180
|
};
|
|
377146
377181
|
}, [state.phase]);
|
|
377147
|
-
|
|
377182
|
+
useEffect10(() => {
|
|
377148
377183
|
if (state.phase !== "downloading" || !state.checkResult) return;
|
|
377149
377184
|
let cancelled = false;
|
|
377150
377185
|
async function download() {
|
|
@@ -377176,7 +377211,7 @@ function UpdateUI() {
|
|
|
377176
377211
|
cancelled = true;
|
|
377177
377212
|
};
|
|
377178
377213
|
}, [state.phase, state.checkResult]);
|
|
377179
|
-
|
|
377214
|
+
useEffect10(() => {
|
|
377180
377215
|
if (state.phase === "up-to-date" || state.phase === "success" || state.phase === "error" || state.phase === "permission-error") {
|
|
377181
377216
|
const timer = setTimeout(() => exit(), 100);
|
|
377182
377217
|
return () => clearTimeout(timer);
|
|
@@ -377287,7 +377322,7 @@ async function projectListCommand() {
|
|
|
377287
377322
|
var program = new Command();
|
|
377288
377323
|
var env = "production";
|
|
377289
377324
|
var envLabel = env !== "production" ? `[${env.toUpperCase()}] ` : "";
|
|
377290
|
-
program.name("specific").description(`${envLabel}Infrastructure-as-code for coding agents`).version("0.1.
|
|
377325
|
+
program.name("specific").description(`${envLabel}Infrastructure-as-code for coding agents`).version("0.1.116").enablePositionalOptions();
|
|
377291
377326
|
program.command("init").description("Initialize project for use with a coding agent").option("--agent <name...>", "Agents to configure (cursor, claude, codex, other)").addHelpText("after", `
|
|
377292
377327
|
Examples:
|
|
377293
377328
|
$ specific init
|