@specific.dev/cli 0.1.50 → 0.1.52
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/admin/404/index.html +1 -1
- package/dist/admin/404.html +1 -1
- package/dist/admin/__next.__PAGE__.txt +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._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/__next.databases.__PAGE__.txt +1 -1
- package/dist/admin/databases/__next.databases.txt +1 -1
- package/dist/admin/databases/index.html +1 -1
- package/dist/admin/databases/index.txt +1 -1
- package/dist/admin/index.html +1 -1
- package/dist/admin/index.txt +1 -1
- package/dist/cli.js +226 -114
- package/dist/docs/builds.md +42 -0
- package/dist/docs/services.md +53 -0
- package/dist/postinstall.js +1 -1
- package/package.json +2 -2
- /package/dist/admin/_next/static/{o2Qo92jA0gWbtB1ZWKQFF → 0CmgQNPZi3W-iwSoebP4u}/_buildManifest.js +0 -0
- /package/dist/admin/_next/static/{o2Qo92jA0gWbtB1ZWKQFF → 0CmgQNPZi3W-iwSoebP4u}/_clientMiddlewareManifest.json +0 -0
- /package/dist/admin/_next/static/{o2Qo92jA0gWbtB1ZWKQFF → 0CmgQNPZi3W-iwSoebP4u}/_ssgManifest.js +0 -0
package/dist/cli.js
CHANGED
|
@@ -637,19 +637,19 @@ var init_open = __esm({
|
|
|
637
637
|
}
|
|
638
638
|
const subprocess = childProcess3.spawn(command, cliArguments, childProcessOptions);
|
|
639
639
|
if (options2.wait) {
|
|
640
|
-
return new Promise((
|
|
640
|
+
return new Promise((resolve10, reject) => {
|
|
641
641
|
subprocess.once("error", reject);
|
|
642
642
|
subprocess.once("close", (exitCode) => {
|
|
643
643
|
if (!options2.allowNonzeroExitCode && exitCode !== 0) {
|
|
644
644
|
reject(new Error(`Exited with code ${exitCode}`));
|
|
645
645
|
return;
|
|
646
646
|
}
|
|
647
|
-
|
|
647
|
+
resolve10(subprocess);
|
|
648
648
|
});
|
|
649
649
|
});
|
|
650
650
|
}
|
|
651
651
|
if (isFallbackAttempt) {
|
|
652
|
-
return new Promise((
|
|
652
|
+
return new Promise((resolve10, reject) => {
|
|
653
653
|
subprocess.once("error", reject);
|
|
654
654
|
subprocess.once("spawn", () => {
|
|
655
655
|
subprocess.once("close", (exitCode) => {
|
|
@@ -659,17 +659,17 @@ var init_open = __esm({
|
|
|
659
659
|
return;
|
|
660
660
|
}
|
|
661
661
|
subprocess.unref();
|
|
662
|
-
|
|
662
|
+
resolve10(subprocess);
|
|
663
663
|
});
|
|
664
664
|
});
|
|
665
665
|
});
|
|
666
666
|
}
|
|
667
667
|
subprocess.unref();
|
|
668
|
-
return new Promise((
|
|
668
|
+
return new Promise((resolve10, reject) => {
|
|
669
669
|
subprocess.once("error", reject);
|
|
670
670
|
subprocess.once("spawn", () => {
|
|
671
671
|
subprocess.off("error", reject);
|
|
672
|
-
|
|
672
|
+
resolve10(subprocess);
|
|
673
673
|
});
|
|
674
674
|
});
|
|
675
675
|
};
|
|
@@ -183682,7 +183682,7 @@ async function pollUntilToken(deviceAuth, isCancelled) {
|
|
|
183682
183682
|
return null;
|
|
183683
183683
|
}
|
|
183684
183684
|
function sleep(ms) {
|
|
183685
|
-
return new Promise((
|
|
183685
|
+
return new Promise((resolve10) => setTimeout(resolve10, ms));
|
|
183686
183686
|
}
|
|
183687
183687
|
|
|
183688
183688
|
// src/lib/auth/login.tsx
|
|
@@ -183699,7 +183699,7 @@ function LoginUI({
|
|
|
183699
183699
|
return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column", gap: 1 }, isReauthentication && /* @__PURE__ */ React.createElement(Text, { color: "yellow" }, "Session expired. Please log in again."), /* @__PURE__ */ React.createElement(Text, { bold: true }, "Log in to Specific"), state.phase === "waiting-for-browser" ? /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(Box, { flexDirection: "column" }, /* @__PURE__ */ React.createElement(Text, null, "Your authentication code:", " ", /* @__PURE__ */ React.createElement(Text, { color: "cyan", bold: true }, state.userCode))), /* @__PURE__ */ React.createElement(Box, null, /* @__PURE__ */ React.createElement(Text, { color: "blue" }, /* @__PURE__ */ React.createElement(Spinner, { type: "dots" })), /* @__PURE__ */ React.createElement(Text, null, " Waiting for authentication in browser...")), /* @__PURE__ */ React.createElement(Text, { dimColor: true }, "If the browser didn't open, visit: ", state.verificationUri)) : /* @__PURE__ */ React.createElement(Box, null, /* @__PURE__ */ React.createElement(Text, { color: "blue" }, /* @__PURE__ */ React.createElement(Spinner, { type: "dots" })), /* @__PURE__ */ React.createElement(Text, null, " Initiating login...")));
|
|
183700
183700
|
}
|
|
183701
183701
|
function performLogin(options2 = {}) {
|
|
183702
|
-
return new Promise((
|
|
183702
|
+
return new Promise((resolve10) => {
|
|
183703
183703
|
let currentState = { phase: "initiating" };
|
|
183704
183704
|
let flowHandle;
|
|
183705
183705
|
const instance = render(
|
|
@@ -183739,14 +183739,14 @@ function performLogin(options2 = {}) {
|
|
|
183739
183739
|
process.off("SIGINT", handleExit);
|
|
183740
183740
|
process.off("SIGTERM", handleExit);
|
|
183741
183741
|
instance.unmount();
|
|
183742
|
-
|
|
183742
|
+
resolve10({ success: true, userEmail: newState.email });
|
|
183743
183743
|
}, 100);
|
|
183744
183744
|
} else if (newState.phase === "error") {
|
|
183745
183745
|
setTimeout(() => {
|
|
183746
183746
|
process.off("SIGINT", handleExit);
|
|
183747
183747
|
process.off("SIGTERM", handleExit);
|
|
183748
183748
|
instance.unmount();
|
|
183749
|
-
|
|
183749
|
+
resolve10({ success: false, error: new Error(newState.message) });
|
|
183750
183750
|
}, 100);
|
|
183751
183751
|
}
|
|
183752
183752
|
}
|
|
@@ -183873,7 +183873,7 @@ function trackEvent(event, properties) {
|
|
|
183873
183873
|
event,
|
|
183874
183874
|
properties: {
|
|
183875
183875
|
...properties,
|
|
183876
|
-
cli_version: "0.1.
|
|
183876
|
+
cli_version: "0.1.52",
|
|
183877
183877
|
platform: process.platform,
|
|
183878
183878
|
node_version: process.version,
|
|
183879
183879
|
project_id: getProjectId(),
|
|
@@ -184348,8 +184348,43 @@ function parseReference(value) {
|
|
|
184348
184348
|
if (match && match[1]) {
|
|
184349
184349
|
return parseReferenceString(match[1]);
|
|
184350
184350
|
}
|
|
184351
|
+
if (value.includes("${")) {
|
|
184352
|
+
return parseInterpolatedString(value);
|
|
184353
|
+
}
|
|
184351
184354
|
return value;
|
|
184352
184355
|
}
|
|
184356
|
+
function parseInterpolatedString(value) {
|
|
184357
|
+
const parts = [];
|
|
184358
|
+
const regex = /\$\{([^}]+)\}/g;
|
|
184359
|
+
let lastIndex = 0;
|
|
184360
|
+
let match;
|
|
184361
|
+
while ((match = regex.exec(value)) !== null) {
|
|
184362
|
+
if (match.index > lastIndex) {
|
|
184363
|
+
parts.push({ type: "literal", value: value.slice(lastIndex, match.index) });
|
|
184364
|
+
}
|
|
184365
|
+
const refStr = match[1];
|
|
184366
|
+
const parsed = parseReferenceString(refStr);
|
|
184367
|
+
if (typeof parsed === "string") {
|
|
184368
|
+
parts.push({ type: "literal", value: match[0] });
|
|
184369
|
+
} else {
|
|
184370
|
+
if (parsed.type === "secret") {
|
|
184371
|
+
throw new Error(`Secret references cannot be used inside interpolated strings. Use \${secret.${parsed.name}} as a standalone env var value instead.`);
|
|
184372
|
+
}
|
|
184373
|
+
if (parsed.type === "config") {
|
|
184374
|
+
throw new Error(`Config references cannot be used inside interpolated strings. Use \${config.${parsed.name}} as a standalone env var value instead.`);
|
|
184375
|
+
}
|
|
184376
|
+
if (parsed.type === "build") {
|
|
184377
|
+
throw new Error(`Build references cannot be used inside interpolated strings.`);
|
|
184378
|
+
}
|
|
184379
|
+
parts.push({ type: "ref", ref: parsed });
|
|
184380
|
+
}
|
|
184381
|
+
lastIndex = match.index + match[0].length;
|
|
184382
|
+
}
|
|
184383
|
+
if (lastIndex < value.length) {
|
|
184384
|
+
parts.push({ type: "literal", value: value.slice(lastIndex) });
|
|
184385
|
+
}
|
|
184386
|
+
return { type: "interpolated", parts };
|
|
184387
|
+
}
|
|
184353
184388
|
function parseReferenceString(str) {
|
|
184354
184389
|
if (str === "port") {
|
|
184355
184390
|
return { type: "port" };
|
|
@@ -184529,6 +184564,9 @@ function parseBuilds(buildData) {
|
|
|
184529
184564
|
if (fieldObj.context) {
|
|
184530
184565
|
build.context = String(fieldObj.context);
|
|
184531
184566
|
}
|
|
184567
|
+
if (fieldObj.root) {
|
|
184568
|
+
build.root = String(fieldObj.root);
|
|
184569
|
+
}
|
|
184532
184570
|
if (dev) {
|
|
184533
184571
|
build.dev = dev;
|
|
184534
184572
|
}
|
|
@@ -184539,6 +184577,16 @@ function parseBuilds(buildData) {
|
|
|
184539
184577
|
continue;
|
|
184540
184578
|
if (value.type === "service" && value.attribute === "public_url")
|
|
184541
184579
|
continue;
|
|
184580
|
+
if (value.type === "interpolated") {
|
|
184581
|
+
for (const part of value.parts) {
|
|
184582
|
+
if (part.type === "ref") {
|
|
184583
|
+
if (part.ref.type !== "service" || part.ref.attribute !== "public_url") {
|
|
184584
|
+
throw new Error(`Build "${name}" env var "${key}" uses an unsupported reference type in interpolated string. Build env vars only support string literals and \${service.<name>.public_url} references.`);
|
|
184585
|
+
}
|
|
184586
|
+
}
|
|
184587
|
+
}
|
|
184588
|
+
continue;
|
|
184589
|
+
}
|
|
184542
184590
|
throw new Error(`Build "${name}" env var "${key}" uses an unsupported reference type. Build env vars only support string literals and \${service.<name>.public_url} references.`);
|
|
184543
184591
|
}
|
|
184544
184592
|
build.env = env2;
|
|
@@ -184616,6 +184664,9 @@ function parseServices(serviceData) {
|
|
|
184616
184664
|
if (fieldObj.command) {
|
|
184617
184665
|
service.command = String(fieldObj.command);
|
|
184618
184666
|
}
|
|
184667
|
+
if (fieldObj.root) {
|
|
184668
|
+
service.root = String(fieldObj.root);
|
|
184669
|
+
}
|
|
184619
184670
|
const endpoints = parseEndpoints(fieldObj);
|
|
184620
184671
|
if (fieldObj.expose !== void 0) {
|
|
184621
184672
|
service.expose = {};
|
|
@@ -184826,12 +184877,21 @@ async function parseConfig(hcl) {
|
|
|
184826
184877
|
environments: parseEnvironments(json.environment)
|
|
184827
184878
|
};
|
|
184828
184879
|
}
|
|
184880
|
+
function envValueReferences(value) {
|
|
184881
|
+
if (typeof value === "string")
|
|
184882
|
+
return [];
|
|
184883
|
+
if (value.type === "interpolated") {
|
|
184884
|
+
return value.parts.filter((p) => p.type === "ref").map((p) => p.ref);
|
|
184885
|
+
}
|
|
184886
|
+
return [value];
|
|
184887
|
+
}
|
|
184829
184888
|
function hasPortReference(env2) {
|
|
184830
184889
|
if (!env2)
|
|
184831
184890
|
return false;
|
|
184832
184891
|
for (const value of Object.values(env2)) {
|
|
184833
|
-
|
|
184834
|
-
|
|
184892
|
+
for (const ref of envValueReferences(value)) {
|
|
184893
|
+
if (ref.type === "port")
|
|
184894
|
+
return true;
|
|
184835
184895
|
}
|
|
184836
184896
|
}
|
|
184837
184897
|
return false;
|
|
@@ -184843,20 +184903,19 @@ function validateEndpointReferences(config) {
|
|
|
184843
184903
|
serviceEndpointsMap.set(service.name, service.endpoints);
|
|
184844
184904
|
}
|
|
184845
184905
|
for (const service of config.services) {
|
|
184846
|
-
if (service.
|
|
184847
|
-
|
|
184848
|
-
|
|
184906
|
+
if (!service.env)
|
|
184907
|
+
continue;
|
|
184908
|
+
for (const [key, value] of Object.entries(service.env)) {
|
|
184909
|
+
const refs = envValueReferences(value);
|
|
184910
|
+
for (const ref of refs) {
|
|
184911
|
+
if (service.endpoints.length > 1 && ref.type === "port") {
|
|
184849
184912
|
errors.push({
|
|
184850
184913
|
service: service.name,
|
|
184851
184914
|
message: `Service "${service.name}" has multiple endpoints but uses \${port} for env var "${key}". Use \${endpoint.<name>.port} instead.`
|
|
184852
184915
|
});
|
|
184853
184916
|
}
|
|
184854
|
-
|
|
184855
|
-
|
|
184856
|
-
if (service.env) {
|
|
184857
|
-
for (const [key, value] of Object.entries(service.env)) {
|
|
184858
|
-
if (typeof value === "object" && value.type === "service") {
|
|
184859
|
-
const serviceRef = value;
|
|
184917
|
+
if (ref.type === "service") {
|
|
184918
|
+
const serviceRef = ref;
|
|
184860
184919
|
const targetEndpoints = serviceEndpointsMap.get(serviceRef.serviceName);
|
|
184861
184920
|
if (!targetEndpoints) {
|
|
184862
184921
|
errors.push({
|
|
@@ -184901,8 +184960,8 @@ function validateEndpointReferences(config) {
|
|
|
184901
184960
|
}
|
|
184902
184961
|
}
|
|
184903
184962
|
}
|
|
184904
|
-
if (
|
|
184905
|
-
const endpointRef =
|
|
184963
|
+
if (ref.type === "endpoint") {
|
|
184964
|
+
const endpointRef = ref;
|
|
184906
184965
|
const endpointExists = service.endpoints.some((e) => e.name === endpointRef.endpointName);
|
|
184907
184966
|
if (!endpointExists) {
|
|
184908
184967
|
errors.push({
|
|
@@ -185055,10 +185114,10 @@ async function downloadFile(url, destPath, onProgress) {
|
|
|
185055
185114
|
});
|
|
185056
185115
|
}
|
|
185057
185116
|
}
|
|
185058
|
-
await new Promise((
|
|
185117
|
+
await new Promise((resolve10, reject) => {
|
|
185059
185118
|
fileStream.end((err) => {
|
|
185060
185119
|
if (err) reject(err);
|
|
185061
|
-
else
|
|
185120
|
+
else resolve10();
|
|
185062
185121
|
});
|
|
185063
185122
|
});
|
|
185064
185123
|
fs11.renameSync(partPath, destPath);
|
|
@@ -185241,7 +185300,7 @@ var drizzleGatewayBinary = {
|
|
|
185241
185300
|
// src/lib/bin/definitions/reshape.ts
|
|
185242
185301
|
var reshapeBinary = {
|
|
185243
185302
|
name: "reshape",
|
|
185244
|
-
versions: ["0.9.
|
|
185303
|
+
versions: ["0.9.1"],
|
|
185245
185304
|
// GitHub release assets
|
|
185246
185305
|
urlTemplate: "https://github.com/fabianlindfors/reshape/releases/download/v{version}/reshape-{arch}",
|
|
185247
185306
|
platformMapping: {
|
|
@@ -185265,13 +185324,13 @@ async function runReshapeCheck(migrationsDir) {
|
|
|
185265
185324
|
try {
|
|
185266
185325
|
const binary = await ensureBinary(reshapeBinary);
|
|
185267
185326
|
const reshapePath = binary.executables["reshape"];
|
|
185268
|
-
return new Promise((
|
|
185327
|
+
return new Promise((resolve10) => {
|
|
185269
185328
|
execFile7(reshapePath, ["check", "--dirs", migrationsDir], (err, _stdout, stderr) => {
|
|
185270
185329
|
if (err) {
|
|
185271
185330
|
const errorMsg = stderr.trim() || err.message;
|
|
185272
|
-
|
|
185331
|
+
resolve10({ success: false, error: errorMsg });
|
|
185273
185332
|
} else {
|
|
185274
|
-
|
|
185333
|
+
resolve10({ success: true });
|
|
185275
185334
|
}
|
|
185276
185335
|
});
|
|
185277
185336
|
});
|
|
@@ -186228,7 +186287,7 @@ var NodeFsHandler = class {
|
|
|
186228
186287
|
this._addToNodeFs(path26, initialAdd, wh, depth + 1);
|
|
186229
186288
|
}
|
|
186230
186289
|
}).on(EV.ERROR, this._boundHandleError);
|
|
186231
|
-
return new Promise((
|
|
186290
|
+
return new Promise((resolve10, reject) => {
|
|
186232
186291
|
if (!stream)
|
|
186233
186292
|
return reject();
|
|
186234
186293
|
stream.once(STR_END, () => {
|
|
@@ -186237,7 +186296,7 @@ var NodeFsHandler = class {
|
|
|
186237
186296
|
return;
|
|
186238
186297
|
}
|
|
186239
186298
|
const wasThrottled = throttler ? throttler.clear() : false;
|
|
186240
|
-
|
|
186299
|
+
resolve10(void 0);
|
|
186241
186300
|
previous.getChildren().filter((item) => {
|
|
186242
186301
|
return item !== directory && !current.has(item);
|
|
186243
186302
|
}).forEach((item) => {
|
|
@@ -187301,7 +187360,7 @@ async function startStorage(storage, port, dataDir) {
|
|
|
187301
187360
|
};
|
|
187302
187361
|
}
|
|
187303
187362
|
async function runCommand(command, args, env2) {
|
|
187304
|
-
return new Promise((
|
|
187363
|
+
return new Promise((resolve10, reject) => {
|
|
187305
187364
|
const proc = spawn(command, args, {
|
|
187306
187365
|
stdio: ["ignore", "pipe", "pipe"],
|
|
187307
187366
|
env: env2
|
|
@@ -187312,7 +187371,7 @@ async function runCommand(command, args, env2) {
|
|
|
187312
187371
|
});
|
|
187313
187372
|
proc.on("close", (code) => {
|
|
187314
187373
|
if (code === 0) {
|
|
187315
|
-
|
|
187374
|
+
resolve10();
|
|
187316
187375
|
} else {
|
|
187317
187376
|
reject(new Error(`Command failed with code ${code}: ${stderr}`));
|
|
187318
187377
|
}
|
|
@@ -187321,7 +187380,7 @@ async function runCommand(command, args, env2) {
|
|
|
187321
187380
|
});
|
|
187322
187381
|
}
|
|
187323
187382
|
async function createPostgresDatabase(postgresPath, dataDir, dbName, env2) {
|
|
187324
|
-
return new Promise((
|
|
187383
|
+
return new Promise((resolve10, reject) => {
|
|
187325
187384
|
const proc = spawn(
|
|
187326
187385
|
postgresPath,
|
|
187327
187386
|
["--single", "-D", dataDir, "postgres"],
|
|
@@ -187335,7 +187394,7 @@ async function createPostgresDatabase(postgresPath, dataDir, dbName, env2) {
|
|
|
187335
187394
|
stderr += data.toString();
|
|
187336
187395
|
});
|
|
187337
187396
|
proc.on("close", (code) => {
|
|
187338
|
-
|
|
187397
|
+
resolve10();
|
|
187339
187398
|
});
|
|
187340
187399
|
proc.on("error", reject);
|
|
187341
187400
|
proc.stdin?.write(`CREATE DATABASE "${dbName}";
|
|
@@ -187355,33 +187414,33 @@ async function waitForTcpPort(host, port, timeoutMs = 3e4) {
|
|
|
187355
187414
|
throw new Error(`Port ${port} did not become available within timeout`);
|
|
187356
187415
|
}
|
|
187357
187416
|
function checkTcpPort(host, port) {
|
|
187358
|
-
return new Promise((
|
|
187417
|
+
return new Promise((resolve10) => {
|
|
187359
187418
|
const socket = new net.Socket();
|
|
187360
187419
|
socket.setTimeout(1e3);
|
|
187361
187420
|
socket.on("connect", () => {
|
|
187362
187421
|
socket.destroy();
|
|
187363
|
-
|
|
187422
|
+
resolve10(true);
|
|
187364
187423
|
});
|
|
187365
187424
|
socket.on("timeout", () => {
|
|
187366
187425
|
socket.destroy();
|
|
187367
|
-
|
|
187426
|
+
resolve10(false);
|
|
187368
187427
|
});
|
|
187369
187428
|
socket.on("error", () => {
|
|
187370
187429
|
socket.destroy();
|
|
187371
|
-
|
|
187430
|
+
resolve10(false);
|
|
187372
187431
|
});
|
|
187373
187432
|
socket.connect(port, host);
|
|
187374
187433
|
});
|
|
187375
187434
|
}
|
|
187376
187435
|
async function stopProcess(proc) {
|
|
187377
|
-
return new Promise((
|
|
187436
|
+
return new Promise((resolve10) => {
|
|
187378
187437
|
if (proc.killed || proc.exitCode !== null) {
|
|
187379
|
-
|
|
187438
|
+
resolve10();
|
|
187380
187439
|
return;
|
|
187381
187440
|
}
|
|
187382
187441
|
proc.once("exit", () => {
|
|
187383
187442
|
clearTimeout(forceKillTimeout);
|
|
187384
|
-
|
|
187443
|
+
resolve10();
|
|
187385
187444
|
});
|
|
187386
187445
|
proc.kill("SIGTERM");
|
|
187387
187446
|
const forceKillTimeout = setTimeout(() => {
|
|
@@ -187392,7 +187451,7 @@ async function stopProcess(proc) {
|
|
|
187392
187451
|
});
|
|
187393
187452
|
}
|
|
187394
187453
|
function sleep2(ms) {
|
|
187395
|
-
return new Promise((
|
|
187454
|
+
return new Promise((resolve10) => setTimeout(resolve10, ms));
|
|
187396
187455
|
}
|
|
187397
187456
|
|
|
187398
187457
|
// src/lib/dev/service-runner.ts
|
|
@@ -187545,6 +187604,21 @@ function resolveEnvValue(value, resources, secrets, configs, servicePort, servic
|
|
|
187545
187604
|
if (typeof value === "string") {
|
|
187546
187605
|
return value;
|
|
187547
187606
|
}
|
|
187607
|
+
if (value.type === "interpolated") {
|
|
187608
|
+
return value.parts.map((part) => {
|
|
187609
|
+
if (part.type === "literal") return part.value;
|
|
187610
|
+
return resolveEnvValue(
|
|
187611
|
+
part.ref,
|
|
187612
|
+
resources,
|
|
187613
|
+
secrets,
|
|
187614
|
+
configs,
|
|
187615
|
+
servicePort,
|
|
187616
|
+
serviceEndpoints,
|
|
187617
|
+
currentServicePorts,
|
|
187618
|
+
publicUrls
|
|
187619
|
+
);
|
|
187620
|
+
}).join("");
|
|
187621
|
+
}
|
|
187548
187622
|
switch (value.type) {
|
|
187549
187623
|
case "port":
|
|
187550
187624
|
if (servicePort === void 0) {
|
|
@@ -187740,13 +187814,23 @@ function resolveEnvForExec(env2, resources, secrets, configs) {
|
|
|
187740
187814
|
if (value.type === "port" || value.type === "endpoint" || value.type === "service") {
|
|
187741
187815
|
continue;
|
|
187742
187816
|
}
|
|
187817
|
+
if (value.type === "interpolated") {
|
|
187818
|
+
const hasSkippableRef = value.parts.some(
|
|
187819
|
+
(part) => part.type === "ref" && (part.ref.type === "port" || part.ref.type === "endpoint" || part.ref.type === "service")
|
|
187820
|
+
);
|
|
187821
|
+
if (hasSkippableRef) {
|
|
187822
|
+
continue;
|
|
187823
|
+
}
|
|
187824
|
+
resolved[key] = resolveEnvValue(value, resources, secrets, configs);
|
|
187825
|
+
continue;
|
|
187826
|
+
}
|
|
187743
187827
|
resolved[key] = resolveEnvValue(value, resources, secrets, configs);
|
|
187744
187828
|
}
|
|
187745
187829
|
return resolved;
|
|
187746
187830
|
}
|
|
187747
187831
|
|
|
187748
187832
|
// src/lib/dev/service-runner.ts
|
|
187749
|
-
function startService(service, resources, secrets, configs, endpointPorts, serviceEndpoints, onLog, publicUrls) {
|
|
187833
|
+
function startService(service, resources, secrets, configs, endpointPorts, serviceEndpoints, onLog, publicUrls, cwd) {
|
|
187750
187834
|
const command = service.dev?.command ?? service.command;
|
|
187751
187835
|
if (!command) {
|
|
187752
187836
|
throw new Error(`Service "${service.name}" has no command`);
|
|
@@ -187768,7 +187852,7 @@ function startService(service, resources, secrets, configs, endpointPorts, servi
|
|
|
187768
187852
|
);
|
|
187769
187853
|
const child = spawn2(command, {
|
|
187770
187854
|
shell: true,
|
|
187771
|
-
cwd: process.cwd(),
|
|
187855
|
+
cwd: cwd || process.cwd(),
|
|
187772
187856
|
env: {
|
|
187773
187857
|
...process.env,
|
|
187774
187858
|
...resolvedEnv
|
|
@@ -187796,14 +187880,14 @@ function startService(service, resources, secrets, configs, endpointPorts, servi
|
|
|
187796
187880
|
ports: endpointPorts,
|
|
187797
187881
|
process: child,
|
|
187798
187882
|
async stop() {
|
|
187799
|
-
return new Promise((
|
|
187883
|
+
return new Promise((resolve10) => {
|
|
187800
187884
|
if (child.killed || child.exitCode !== null) {
|
|
187801
|
-
|
|
187885
|
+
resolve10();
|
|
187802
187886
|
return;
|
|
187803
187887
|
}
|
|
187804
187888
|
child.once("exit", () => {
|
|
187805
187889
|
clearTimeout(forceKillTimeout);
|
|
187806
|
-
|
|
187890
|
+
resolve10();
|
|
187807
187891
|
});
|
|
187808
187892
|
child.kill("SIGTERM");
|
|
187809
187893
|
const forceKillTimeout = setTimeout(() => {
|
|
@@ -187884,7 +187968,7 @@ var InstanceStateManager = class {
|
|
|
187884
187968
|
}
|
|
187885
187969
|
continue;
|
|
187886
187970
|
}
|
|
187887
|
-
await new Promise((
|
|
187971
|
+
await new Promise((resolve10) => setTimeout(resolve10, 100));
|
|
187888
187972
|
} else {
|
|
187889
187973
|
throw e;
|
|
187890
187974
|
}
|
|
@@ -188167,7 +188251,7 @@ async function startHttpProxy(services, certificate, getState, instanceKey = "de
|
|
|
188167
188251
|
handleRequest
|
|
188168
188252
|
);
|
|
188169
188253
|
httpsServer.on("upgrade", handleUpgrade);
|
|
188170
|
-
return new Promise((
|
|
188254
|
+
return new Promise((resolve10, reject) => {
|
|
188171
188255
|
let httpStarted = false;
|
|
188172
188256
|
let httpsStarted = false;
|
|
188173
188257
|
let failed = false;
|
|
@@ -188178,7 +188262,7 @@ async function startHttpProxy(services, certificate, getState, instanceKey = "de
|
|
|
188178
188262
|
"proxy",
|
|
188179
188263
|
`HTTP/HTTPS proxy started on ports ${HTTP_PORT}/${HTTPS_PORT}`
|
|
188180
188264
|
);
|
|
188181
|
-
|
|
188265
|
+
resolve10({
|
|
188182
188266
|
httpPort: HTTP_PORT,
|
|
188183
188267
|
httpsPort: HTTPS_PORT,
|
|
188184
188268
|
updateServices,
|
|
@@ -188190,13 +188274,13 @@ async function startHttpProxy(services, certificate, getState, instanceKey = "de
|
|
|
188190
188274
|
writeLog("proxy", "Certificate updated");
|
|
188191
188275
|
},
|
|
188192
188276
|
async stop() {
|
|
188193
|
-
return new Promise((
|
|
188277
|
+
return new Promise((resolve11) => {
|
|
188194
188278
|
let closed = 0;
|
|
188195
188279
|
const onClose = () => {
|
|
188196
188280
|
closed++;
|
|
188197
188281
|
if (closed === 2) {
|
|
188198
188282
|
clearTimeout(forceCloseTimeout);
|
|
188199
|
-
|
|
188283
|
+
resolve11();
|
|
188200
188284
|
}
|
|
188201
188285
|
};
|
|
188202
188286
|
httpServer.close(onClose);
|
|
@@ -188204,7 +188288,7 @@ async function startHttpProxy(services, certificate, getState, instanceKey = "de
|
|
|
188204
188288
|
const forceCloseTimeout = setTimeout(() => {
|
|
188205
188289
|
httpServer.closeAllConnections?.();
|
|
188206
188290
|
httpsServer.closeAllConnections?.();
|
|
188207
|
-
|
|
188291
|
+
resolve11();
|
|
188208
188292
|
}, 2e3);
|
|
188209
188293
|
});
|
|
188210
188294
|
}
|
|
@@ -188367,7 +188451,7 @@ function serveFileContent(res, filePath, contentType, statusCode = 200) {
|
|
|
188367
188451
|
}
|
|
188368
188452
|
}
|
|
188369
188453
|
async function startAdminServer(getState) {
|
|
188370
|
-
return new Promise((
|
|
188454
|
+
return new Promise((resolve10, reject) => {
|
|
188371
188455
|
const server = http.createServer((req, res) => {
|
|
188372
188456
|
const url = new URL(req.url || "/", "http://localhost");
|
|
188373
188457
|
res.setHeader("Access-Control-Allow-Origin", "*");
|
|
@@ -188399,7 +188483,7 @@ async function startAdminServer(getState) {
|
|
|
188399
188483
|
}
|
|
188400
188484
|
const port = addr.port;
|
|
188401
188485
|
writeLog("admin", `Admin API server started on port ${port}`);
|
|
188402
|
-
|
|
188486
|
+
resolve10({
|
|
188403
188487
|
port,
|
|
188404
188488
|
stop: () => new Promise((res, rej) => {
|
|
188405
188489
|
server.close((err) => err ? rej(err) : res());
|
|
@@ -188560,33 +188644,33 @@ async function waitForTcpPort2(host, port, timeoutMs = 3e4) {
|
|
|
188560
188644
|
throw new Error(`Electric port ${port} did not become available within timeout`);
|
|
188561
188645
|
}
|
|
188562
188646
|
function checkTcpPort2(host, port) {
|
|
188563
|
-
return new Promise((
|
|
188647
|
+
return new Promise((resolve10) => {
|
|
188564
188648
|
const socket = new net2.Socket();
|
|
188565
188649
|
socket.setTimeout(1e3);
|
|
188566
188650
|
socket.on("connect", () => {
|
|
188567
188651
|
socket.destroy();
|
|
188568
|
-
|
|
188652
|
+
resolve10(true);
|
|
188569
188653
|
});
|
|
188570
188654
|
socket.on("timeout", () => {
|
|
188571
188655
|
socket.destroy();
|
|
188572
|
-
|
|
188656
|
+
resolve10(false);
|
|
188573
188657
|
});
|
|
188574
188658
|
socket.on("error", () => {
|
|
188575
188659
|
socket.destroy();
|
|
188576
|
-
|
|
188660
|
+
resolve10(false);
|
|
188577
188661
|
});
|
|
188578
188662
|
socket.connect(port, host);
|
|
188579
188663
|
});
|
|
188580
188664
|
}
|
|
188581
188665
|
async function stopProcess2(proc) {
|
|
188582
|
-
return new Promise((
|
|
188666
|
+
return new Promise((resolve10) => {
|
|
188583
188667
|
if (proc.killed || proc.exitCode !== null) {
|
|
188584
|
-
|
|
188668
|
+
resolve10();
|
|
188585
188669
|
return;
|
|
188586
188670
|
}
|
|
188587
188671
|
proc.once("exit", () => {
|
|
188588
188672
|
clearTimeout(forceKillTimeout);
|
|
188589
|
-
|
|
188673
|
+
resolve10();
|
|
188590
188674
|
});
|
|
188591
188675
|
proc.kill("SIGTERM");
|
|
188592
188676
|
const forceKillTimeout = setTimeout(() => {
|
|
@@ -188597,7 +188681,7 @@ async function stopProcess2(proc) {
|
|
|
188597
188681
|
});
|
|
188598
188682
|
}
|
|
188599
188683
|
function sleep3(ms) {
|
|
188600
|
-
return new Promise((
|
|
188684
|
+
return new Promise((resolve10) => setTimeout(resolve10, ms));
|
|
188601
188685
|
}
|
|
188602
188686
|
|
|
188603
188687
|
// src/lib/dev/drizzle-gateway-manager.ts
|
|
@@ -188681,33 +188765,33 @@ async function waitForTcpPort3(host, port, timeoutMs = 3e4) {
|
|
|
188681
188765
|
);
|
|
188682
188766
|
}
|
|
188683
188767
|
function checkTcpPort3(host, port) {
|
|
188684
|
-
return new Promise((
|
|
188768
|
+
return new Promise((resolve10) => {
|
|
188685
188769
|
const socket = new net3.Socket();
|
|
188686
188770
|
socket.setTimeout(1e3);
|
|
188687
188771
|
socket.on("connect", () => {
|
|
188688
188772
|
socket.destroy();
|
|
188689
|
-
|
|
188773
|
+
resolve10(true);
|
|
188690
188774
|
});
|
|
188691
188775
|
socket.on("timeout", () => {
|
|
188692
188776
|
socket.destroy();
|
|
188693
|
-
|
|
188777
|
+
resolve10(false);
|
|
188694
188778
|
});
|
|
188695
188779
|
socket.on("error", () => {
|
|
188696
188780
|
socket.destroy();
|
|
188697
|
-
|
|
188781
|
+
resolve10(false);
|
|
188698
188782
|
});
|
|
188699
188783
|
socket.connect(port, host);
|
|
188700
188784
|
});
|
|
188701
188785
|
}
|
|
188702
188786
|
async function stopProcess3(proc) {
|
|
188703
|
-
return new Promise((
|
|
188787
|
+
return new Promise((resolve10) => {
|
|
188704
188788
|
if (proc.killed || proc.exitCode !== null) {
|
|
188705
|
-
|
|
188789
|
+
resolve10();
|
|
188706
188790
|
return;
|
|
188707
188791
|
}
|
|
188708
188792
|
proc.once("exit", () => {
|
|
188709
188793
|
clearTimeout(forceKillTimeout);
|
|
188710
|
-
|
|
188794
|
+
resolve10();
|
|
188711
188795
|
});
|
|
188712
188796
|
proc.kill("SIGTERM");
|
|
188713
188797
|
const forceKillTimeout = setTimeout(() => {
|
|
@@ -188718,7 +188802,7 @@ async function stopProcess3(proc) {
|
|
|
188718
188802
|
});
|
|
188719
188803
|
}
|
|
188720
188804
|
function sleep4(ms) {
|
|
188721
|
-
return new Promise((
|
|
188805
|
+
return new Promise((resolve10) => setTimeout(resolve10, ms));
|
|
188722
188806
|
}
|
|
188723
188807
|
|
|
188724
188808
|
// src/lib/dev/sync-detector.ts
|
|
@@ -188727,10 +188811,14 @@ function detectSyncDatabases(config) {
|
|
|
188727
188811
|
for (const service of config.services) {
|
|
188728
188812
|
if (!service.env) continue;
|
|
188729
188813
|
for (const value of Object.values(service.env)) {
|
|
188730
|
-
if (typeof value
|
|
188731
|
-
|
|
188732
|
-
|
|
188733
|
-
|
|
188814
|
+
if (typeof value !== "object") continue;
|
|
188815
|
+
const refs = value.type === "interpolated" ? value.parts.filter((p) => p.type === "ref").map((p) => p.ref) : [value];
|
|
188816
|
+
for (const ref of refs) {
|
|
188817
|
+
if (ref.type === "postgres") {
|
|
188818
|
+
const attr = ref.attribute;
|
|
188819
|
+
if (attr === "sync.url" || attr === "sync.secret") {
|
|
188820
|
+
needsSync.add(ref.name);
|
|
188821
|
+
}
|
|
188734
188822
|
}
|
|
188735
188823
|
}
|
|
188736
188824
|
}
|
|
@@ -189025,8 +189113,9 @@ function findRequiredResources(service) {
|
|
|
189025
189113
|
const required = { postgres: [], redis: [], storage: [] };
|
|
189026
189114
|
if (service.env) {
|
|
189027
189115
|
for (const value of Object.values(service.env)) {
|
|
189028
|
-
if (typeof value
|
|
189029
|
-
|
|
189116
|
+
if (typeof value !== "object" || value === null) continue;
|
|
189117
|
+
const refs = value.type === "interpolated" ? value.parts.filter((p) => p.type === "ref").map((p) => p.ref) : [value];
|
|
189118
|
+
for (const ref of refs) {
|
|
189030
189119
|
if (ref.type === "postgres" && !required.postgres.includes(ref.name)) {
|
|
189031
189120
|
required.postgres.push(ref.name);
|
|
189032
189121
|
} else if (ref.type === "redis" && !required.redis.includes(ref.name)) {
|
|
@@ -189335,7 +189424,7 @@ var ProxyRegistryManager = class {
|
|
|
189335
189424
|
* This catches cases where the owner process is alive but the proxy has crashed.
|
|
189336
189425
|
*/
|
|
189337
189426
|
isProxyListening(port, timeoutMs = 1e3) {
|
|
189338
|
-
return new Promise((
|
|
189427
|
+
return new Promise((resolve10) => {
|
|
189339
189428
|
const socket = new net4.Socket();
|
|
189340
189429
|
let resolved = false;
|
|
189341
189430
|
const cleanup = () => {
|
|
@@ -189347,15 +189436,15 @@ var ProxyRegistryManager = class {
|
|
|
189347
189436
|
socket.setTimeout(timeoutMs);
|
|
189348
189437
|
socket.on("connect", () => {
|
|
189349
189438
|
cleanup();
|
|
189350
|
-
|
|
189439
|
+
resolve10(true);
|
|
189351
189440
|
});
|
|
189352
189441
|
socket.on("timeout", () => {
|
|
189353
189442
|
cleanup();
|
|
189354
|
-
|
|
189443
|
+
resolve10(false);
|
|
189355
189444
|
});
|
|
189356
189445
|
socket.on("error", () => {
|
|
189357
189446
|
cleanup();
|
|
189358
|
-
|
|
189447
|
+
resolve10(false);
|
|
189359
189448
|
});
|
|
189360
189449
|
socket.connect(port, "127.0.0.1");
|
|
189361
189450
|
});
|
|
@@ -189406,7 +189495,7 @@ var ProxyRegistryManager = class {
|
|
|
189406
189495
|
}
|
|
189407
189496
|
continue;
|
|
189408
189497
|
}
|
|
189409
|
-
await new Promise((
|
|
189498
|
+
await new Promise((resolve10) => setTimeout(resolve10, 100));
|
|
189410
189499
|
} else {
|
|
189411
189500
|
throw e;
|
|
189412
189501
|
}
|
|
@@ -189890,7 +189979,7 @@ function DevUI({ instanceKey, tunnelEnabled }) {
|
|
|
189890
189979
|
...tunnelsRef.current.map((tunnel) => tunnel.stop())
|
|
189891
189980
|
]);
|
|
189892
189981
|
if (tunnelsRef.current.length > 0) {
|
|
189893
|
-
await new Promise((
|
|
189982
|
+
await new Promise((resolve10) => setTimeout(resolve10, 1500));
|
|
189894
189983
|
}
|
|
189895
189984
|
electricInstancesRef.current = [];
|
|
189896
189985
|
reshapeWatchersRef.current = [];
|
|
@@ -190400,6 +190489,14 @@ Add them to the config block in specific.local`);
|
|
|
190400
190489
|
}
|
|
190401
190490
|
}
|
|
190402
190491
|
const services2 = [];
|
|
190492
|
+
function resolveServiceCwd(service) {
|
|
190493
|
+
if (service.root) return path18.resolve(process.cwd(), service.root);
|
|
190494
|
+
if (service.build) {
|
|
190495
|
+
const build = config2.builds.find((b) => b.name === service.build.name);
|
|
190496
|
+
if (build?.root) return path18.resolve(process.cwd(), build.root);
|
|
190497
|
+
}
|
|
190498
|
+
return process.cwd();
|
|
190499
|
+
}
|
|
190403
190500
|
for (const service of config2.services) {
|
|
190404
190501
|
if (cancelled) break;
|
|
190405
190502
|
if (service.serve) {
|
|
@@ -190423,7 +190520,8 @@ Add them to the config block in specific.local`);
|
|
|
190423
190520
|
endpointPorts,
|
|
190424
190521
|
serviceEndpoints,
|
|
190425
190522
|
(line) => addLog(line, colorMap),
|
|
190426
|
-
publicUrls
|
|
190523
|
+
publicUrls,
|
|
190524
|
+
resolveServiceCwd(service)
|
|
190427
190525
|
);
|
|
190428
190526
|
services2.push(running);
|
|
190429
190527
|
startedServices.push(running);
|
|
@@ -190468,7 +190566,9 @@ Add them to the config block in specific.local`);
|
|
|
190468
190566
|
configs,
|
|
190469
190567
|
endpointPorts,
|
|
190470
190568
|
serviceEndpoints,
|
|
190471
|
-
(line) => addLog(line, colorMap)
|
|
190569
|
+
(line) => addLog(line, colorMap),
|
|
190570
|
+
void 0,
|
|
190571
|
+
resolveServiceCwd(service)
|
|
190472
190572
|
);
|
|
190473
190573
|
newServices.push(running);
|
|
190474
190574
|
} catch (err) {
|
|
@@ -190978,7 +191078,7 @@ import * as path21 from "path";
|
|
|
190978
191078
|
// src/lib/deploy/build-tester.ts
|
|
190979
191079
|
import { spawn as spawn5 } from "child_process";
|
|
190980
191080
|
import { existsSync as existsSync20 } from "fs";
|
|
190981
|
-
import { join as join21 } from "path";
|
|
191081
|
+
import { join as join21, resolve as resolve7 } from "path";
|
|
190982
191082
|
function getDependencyInstallCommand(build, projectDir) {
|
|
190983
191083
|
switch (build.base) {
|
|
190984
191084
|
case "node":
|
|
@@ -190988,9 +191088,10 @@ function getDependencyInstallCommand(build, projectDir) {
|
|
|
190988
191088
|
return "yarn install --frozen-lockfile";
|
|
190989
191089
|
} else if (existsSync20(join21(projectDir, "package-lock.json"))) {
|
|
190990
191090
|
return "npm ci";
|
|
190991
|
-
} else {
|
|
191091
|
+
} else if (existsSync20(join21(projectDir, "package.json"))) {
|
|
190992
191092
|
return "npm install";
|
|
190993
191093
|
}
|
|
191094
|
+
return null;
|
|
190994
191095
|
case "python":
|
|
190995
191096
|
if (existsSync20(join21(projectDir, "poetry.lock"))) {
|
|
190996
191097
|
return "poetry install --no-interaction";
|
|
@@ -191014,7 +191115,7 @@ function getDependencyInstallCommand(build, projectDir) {
|
|
|
191014
191115
|
}
|
|
191015
191116
|
}
|
|
191016
191117
|
function runCommand2(command, projectDir, buildName) {
|
|
191017
|
-
return new Promise((
|
|
191118
|
+
return new Promise((resolve10) => {
|
|
191018
191119
|
const stdout = [];
|
|
191019
191120
|
const stderr = [];
|
|
191020
191121
|
writeLog("build-test", `[${buildName}] Running: ${command}`);
|
|
@@ -191044,7 +191145,7 @@ function runCommand2(command, projectDir, buildName) {
|
|
|
191044
191145
|
});
|
|
191045
191146
|
child.on("error", (err) => {
|
|
191046
191147
|
writeLog("build-test:error", `[${buildName}] Failed to start: ${err.message}`);
|
|
191047
|
-
|
|
191148
|
+
resolve10({
|
|
191048
191149
|
success: false,
|
|
191049
191150
|
output: `Failed to start command: ${err.message}`
|
|
191050
191151
|
});
|
|
@@ -191053,10 +191154,10 @@ function runCommand2(command, projectDir, buildName) {
|
|
|
191053
191154
|
const output = [...stdout, ...stderr].join("");
|
|
191054
191155
|
if (code === 0) {
|
|
191055
191156
|
writeLog("build-test", `[${buildName}] Command succeeded (exit code 0)`);
|
|
191056
|
-
|
|
191157
|
+
resolve10({ success: true, output });
|
|
191057
191158
|
} else {
|
|
191058
191159
|
writeLog("build-test:error", `[${buildName}] Command failed with exit code ${code}`);
|
|
191059
|
-
|
|
191160
|
+
resolve10({
|
|
191060
191161
|
success: false,
|
|
191061
191162
|
output: output || `Exit code: ${code}`
|
|
191062
191163
|
});
|
|
@@ -191067,7 +191168,7 @@ function runCommand2(command, projectDir, buildName) {
|
|
|
191067
191168
|
async function testBuild(build, projectDir) {
|
|
191068
191169
|
const startTime = Date.now();
|
|
191069
191170
|
const outputs = [];
|
|
191070
|
-
const workDir = projectDir;
|
|
191171
|
+
const workDir = build.root ? resolve7(projectDir, build.root) : projectDir;
|
|
191071
191172
|
writeLog("build-test", `Starting test for build "${build.name}" (base: ${build.base}, workDir: ${workDir})`);
|
|
191072
191173
|
const depsCommand = getDependencyInstallCommand(build, workDir);
|
|
191073
191174
|
if (depsCommand) {
|
|
@@ -192328,8 +192429,17 @@ async function execCommand(serviceName, command, instanceKey = "default") {
|
|
|
192328
192429
|
};
|
|
192329
192430
|
process.on("SIGINT", () => handleSignal("SIGINT"));
|
|
192330
192431
|
process.on("SIGTERM", () => handleSignal("SIGTERM"));
|
|
192432
|
+
let effectiveCwd = process.cwd();
|
|
192433
|
+
if (service.root) {
|
|
192434
|
+
effectiveCwd = path22.resolve(process.cwd(), service.root);
|
|
192435
|
+
} else if (service.build) {
|
|
192436
|
+
const build = config.builds.find((b) => b.name === service.build.name);
|
|
192437
|
+
if (build?.root) {
|
|
192438
|
+
effectiveCwd = path22.resolve(process.cwd(), build.root);
|
|
192439
|
+
}
|
|
192440
|
+
}
|
|
192331
192441
|
child = spawn6(command[0], command.slice(1), {
|
|
192332
|
-
cwd:
|
|
192442
|
+
cwd: effectiveCwd,
|
|
192333
192443
|
env: {
|
|
192334
192444
|
...process.env,
|
|
192335
192445
|
...resolvedEnv
|
|
@@ -192744,20 +192854,22 @@ function CleanUI({ instanceKey }) {
|
|
|
192744
192854
|
}
|
|
192745
192855
|
} else {
|
|
192746
192856
|
const keysDir = path25.join(specificDir, "keys");
|
|
192747
|
-
if (fs27.existsSync(keysDir)) {
|
|
192748
|
-
|
|
192749
|
-
|
|
192750
|
-
|
|
192751
|
-
|
|
192752
|
-
|
|
192753
|
-
|
|
192754
|
-
|
|
192755
|
-
|
|
192756
|
-
|
|
192757
|
-
|
|
192758
|
-
|
|
192759
|
-
|
|
192760
|
-
|
|
192857
|
+
if (!fs27.existsSync(keysDir)) {
|
|
192858
|
+
setState({ status: "nothing" });
|
|
192859
|
+
return;
|
|
192860
|
+
}
|
|
192861
|
+
const keys = fs27.readdirSync(keysDir).filter(
|
|
192862
|
+
(f) => fs27.statSync(path25.join(keysDir, f)).isDirectory()
|
|
192863
|
+
);
|
|
192864
|
+
for (const key of keys) {
|
|
192865
|
+
const stateManager2 = new InstanceStateManager(projectRoot, key);
|
|
192866
|
+
const existingInstances2 = await stateManager2.getExistingInstances();
|
|
192867
|
+
if (existingInstances2) {
|
|
192868
|
+
setState({
|
|
192869
|
+
status: "error",
|
|
192870
|
+
error: `Cannot clean while 'specific dev' is running for key "${key}" (PID ${existingInstances2.owner.pid}). Please stop it first.`
|
|
192871
|
+
});
|
|
192872
|
+
return;
|
|
192761
192873
|
}
|
|
192762
192874
|
}
|
|
192763
192875
|
const stateManager = new InstanceStateManager(projectRoot);
|
|
@@ -192771,7 +192883,7 @@ function CleanUI({ instanceKey }) {
|
|
|
192771
192883
|
}
|
|
192772
192884
|
setState({ status: "cleaning" });
|
|
192773
192885
|
try {
|
|
192774
|
-
fs27.rmSync(
|
|
192886
|
+
fs27.rmSync(keysDir, { recursive: true, force: true });
|
|
192775
192887
|
setState({ status: "success" });
|
|
192776
192888
|
} catch (err) {
|
|
192777
192889
|
setState({
|
|
@@ -192787,16 +192899,16 @@ function CleanUI({ instanceKey }) {
|
|
|
192787
192899
|
return /* @__PURE__ */ React8.createElement(Box8, null, /* @__PURE__ */ React8.createElement(Text8, { color: "blue" }, /* @__PURE__ */ React8.createElement(Spinner6, { type: "dots" })), /* @__PURE__ */ React8.createElement(Text8, null, " Checking for running instances..."));
|
|
192788
192900
|
}
|
|
192789
192901
|
if (state.status === "cleaning") {
|
|
192790
|
-
return /* @__PURE__ */ React8.createElement(Box8, null, /* @__PURE__ */ React8.createElement(Text8, { color: "blue" }, /* @__PURE__ */ React8.createElement(Spinner6, { type: "dots" })), /* @__PURE__ */ React8.createElement(Text8, null, "
|
|
192902
|
+
return /* @__PURE__ */ React8.createElement(Box8, null, /* @__PURE__ */ React8.createElement(Text8, { color: "blue" }, /* @__PURE__ */ React8.createElement(Spinner6, { type: "dots" })), /* @__PURE__ */ React8.createElement(Text8, null, " Cleaning app data..."));
|
|
192791
192903
|
}
|
|
192792
192904
|
if (state.status === "error") {
|
|
192793
192905
|
return /* @__PURE__ */ React8.createElement(Text8, { color: "red" }, "Error: ", state.error);
|
|
192794
192906
|
}
|
|
192795
192907
|
if (state.status === "nothing") {
|
|
192796
|
-
const target2 = instanceKey ? `key "${instanceKey}"` : "
|
|
192908
|
+
const target2 = instanceKey ? `key "${instanceKey}"` : "app data";
|
|
192797
192909
|
return /* @__PURE__ */ React8.createElement(Text8, { color: "yellow" }, "Nothing to clean (", target2, " does not exist)");
|
|
192798
192910
|
}
|
|
192799
|
-
const target = instanceKey ? `key "${instanceKey}"` : "
|
|
192911
|
+
const target = instanceKey ? `key "${instanceKey}"` : "app data";
|
|
192800
192912
|
return /* @__PURE__ */ React8.createElement(Text8, { color: "green" }, "Cleaned ", target);
|
|
192801
192913
|
}
|
|
192802
192914
|
function cleanCommand(instanceKey) {
|
|
@@ -192934,7 +193046,7 @@ function betaCommand() {
|
|
|
192934
193046
|
var program = new Command();
|
|
192935
193047
|
var env = "production";
|
|
192936
193048
|
var envLabel = env !== "production" ? `[${env.toUpperCase()}] ` : "";
|
|
192937
|
-
program.name("specific").description(`${envLabel}Infrastructure-as-code for coding agents`).version("0.1.
|
|
193049
|
+
program.name("specific").description(`${envLabel}Infrastructure-as-code for coding agents`).version("0.1.52").enablePositionalOptions();
|
|
192938
193050
|
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));
|
|
192939
193051
|
program.command("docs [topic]").description("Fetch LLM-optimized documentation").action(docsCommand);
|
|
192940
193052
|
program.command("check").description("Validate specific.hcl configuration").action(checkCommand);
|