@specific.dev/cli 0.1.125 → 0.1.126
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 +81 -15
- package/package.json +1 -1
- /package/dist/admin/_next/static/{r3veCvOuDWyK-S0rsl-XQ → xkQQHpz09QHzHXw5WkFYT}/_buildManifest.js +0 -0
- /package/dist/admin/_next/static/{r3veCvOuDWyK-S0rsl-XQ → xkQQHpz09QHzHXw5WkFYT}/_clientMiddlewareManifest.json +0 -0
- /package/dist/admin/_next/static/{r3veCvOuDWyK-S0rsl-XQ → xkQQHpz09QHzHXw5WkFYT}/_ssgManifest.js +0 -0
package/dist/cli.js
CHANGED
|
@@ -369882,31 +369882,59 @@ function resolveEnv(env2, resources, secrets, configs, servicePort, serviceEndpo
|
|
|
369882
369882
|
}
|
|
369883
369883
|
return resolved;
|
|
369884
369884
|
}
|
|
369885
|
-
function resolveEnvForExec(env2, resources, secrets, configs) {
|
|
369885
|
+
function resolveEnvForExec(env2, resources, secrets, configs, runningContext) {
|
|
369886
369886
|
if (!env2) {
|
|
369887
369887
|
return { env: {}, missingSecrets: [], missingConfigs: [] };
|
|
369888
369888
|
}
|
|
369889
369889
|
const resolved = {};
|
|
369890
369890
|
const missingSecrets = [];
|
|
369891
369891
|
const missingConfigs = [];
|
|
369892
|
+
const canResolveRef = (ref) => {
|
|
369893
|
+
if (!runningContext) return false;
|
|
369894
|
+
switch (ref.type) {
|
|
369895
|
+
case "port":
|
|
369896
|
+
return runningContext.servicePort !== void 0;
|
|
369897
|
+
case "endpoint":
|
|
369898
|
+
return runningContext.currentServicePorts !== void 0;
|
|
369899
|
+
case "service": {
|
|
369900
|
+
if (!runningContext.serviceEndpoints) return false;
|
|
369901
|
+
if (ref.attribute === "public_url" && !runningContext.publicUrls) return false;
|
|
369902
|
+
return true;
|
|
369903
|
+
}
|
|
369904
|
+
case "volume":
|
|
369905
|
+
return false;
|
|
369906
|
+
default:
|
|
369907
|
+
return true;
|
|
369908
|
+
}
|
|
369909
|
+
};
|
|
369910
|
+
const isSkippableType = (type) => type === "port" || type === "endpoint" || type === "service" || type === "volume";
|
|
369892
369911
|
for (const [key, value] of Object.entries(env2)) {
|
|
369893
369912
|
if (typeof value === "string") {
|
|
369894
369913
|
resolved[key] = value;
|
|
369895
369914
|
continue;
|
|
369896
369915
|
}
|
|
369897
|
-
if (value.type
|
|
369916
|
+
if (isSkippableType(value.type) && !canResolveRef(value)) {
|
|
369898
369917
|
continue;
|
|
369899
369918
|
}
|
|
369900
369919
|
if (value.type === "interpolated") {
|
|
369901
|
-
const
|
|
369902
|
-
(part) => part.type === "ref" && (part.ref.type
|
|
369920
|
+
const hasUnresolvableRef = value.parts.some(
|
|
369921
|
+
(part) => part.type === "ref" && isSkippableType(part.ref.type) && !canResolveRef(part.ref)
|
|
369903
369922
|
);
|
|
369904
|
-
if (
|
|
369923
|
+
if (hasUnresolvableRef) {
|
|
369905
369924
|
continue;
|
|
369906
369925
|
}
|
|
369907
369926
|
}
|
|
369908
369927
|
try {
|
|
369909
|
-
resolved[key] = resolveEnvValue(
|
|
369928
|
+
resolved[key] = resolveEnvValue(
|
|
369929
|
+
value,
|
|
369930
|
+
resources,
|
|
369931
|
+
secrets,
|
|
369932
|
+
configs,
|
|
369933
|
+
runningContext?.servicePort,
|
|
369934
|
+
runningContext?.serviceEndpoints,
|
|
369935
|
+
runningContext?.currentServicePorts,
|
|
369936
|
+
runningContext?.publicUrls
|
|
369937
|
+
);
|
|
369910
369938
|
} catch (err) {
|
|
369911
369939
|
if (err instanceof MissingSecretError) {
|
|
369912
369940
|
missingSecrets.push({ name: err.secretName, envVar: key });
|
|
@@ -370200,6 +370228,19 @@ var InstanceStateManager = class {
|
|
|
370200
370228
|
releaseLock();
|
|
370201
370229
|
}
|
|
370202
370230
|
}
|
|
370231
|
+
async setPublicUrls(publicUrls) {
|
|
370232
|
+
if (!this.ownsInstances) {
|
|
370233
|
+
throw new Error("Cannot set public URLs: not the owner");
|
|
370234
|
+
}
|
|
370235
|
+
const releaseLock = await this.acquireLock();
|
|
370236
|
+
try {
|
|
370237
|
+
const state = this.readState();
|
|
370238
|
+
state.publicUrls = publicUrls;
|
|
370239
|
+
this.writeStateAtomic(state);
|
|
370240
|
+
} finally {
|
|
370241
|
+
releaseLock();
|
|
370242
|
+
}
|
|
370243
|
+
}
|
|
370203
370244
|
async releaseOwnership() {
|
|
370204
370245
|
if (!this.ownsInstances) {
|
|
370205
370246
|
return;
|
|
@@ -372524,6 +372565,7 @@ Add them to the config block in specific.local`
|
|
|
372524
372565
|
publicUrls.set(svc.name, `localhost:${svc.port}`);
|
|
372525
372566
|
}
|
|
372526
372567
|
}
|
|
372568
|
+
await stateManager.setPublicUrls(Object.fromEntries(publicUrls));
|
|
372527
372569
|
const runningServices = [];
|
|
372528
372570
|
const resolveServiceCwd = (service) => {
|
|
372529
372571
|
if (service.root)
|
|
@@ -373341,7 +373383,7 @@ function trackEvent(event, properties) {
|
|
|
373341
373383
|
event,
|
|
373342
373384
|
properties: {
|
|
373343
373385
|
...properties,
|
|
373344
|
-
cli_version: "0.1.
|
|
373386
|
+
cli_version: "0.1.126",
|
|
373345
373387
|
platform: process.platform,
|
|
373346
373388
|
node_version: process.version,
|
|
373347
373389
|
project_id: getProjectId()
|
|
@@ -376585,7 +376627,7 @@ function startSpinner(text) {
|
|
|
376585
376627
|
}
|
|
376586
376628
|
};
|
|
376587
376629
|
}
|
|
376588
|
-
async function execCommand(serviceName, command, instanceKey = "default") {
|
|
376630
|
+
async function execCommand(serviceName, command, instanceKey = "default", options2 = {}) {
|
|
376589
376631
|
if (command.length === 0) {
|
|
376590
376632
|
console.error(
|
|
376591
376633
|
"Error: No command provided. Usage: specific exec <service> -- <command>"
|
|
@@ -376723,11 +376765,32 @@ async function execCommand(serviceName, command, instanceKey = "default") {
|
|
|
376723
376765
|
}
|
|
376724
376766
|
}
|
|
376725
376767
|
}
|
|
376768
|
+
let runningContext;
|
|
376769
|
+
if (existingInstances) {
|
|
376770
|
+
const serviceEndpoints = /* @__PURE__ */ new Map();
|
|
376771
|
+
for (const [name, svcState] of Object.entries(existingInstances.services)) {
|
|
376772
|
+
if (svcState.port !== void 0) {
|
|
376773
|
+
serviceEndpoints.set(name, [
|
|
376774
|
+
{ serviceName: name, endpointName: "default", port: svcState.port }
|
|
376775
|
+
]);
|
|
376776
|
+
}
|
|
376777
|
+
}
|
|
376778
|
+
const selfPort = existingInstances.services[serviceName]?.port;
|
|
376779
|
+
runningContext = { serviceEndpoints };
|
|
376780
|
+
if (selfPort !== void 0) {
|
|
376781
|
+
runningContext.servicePort = selfPort;
|
|
376782
|
+
runningContext.currentServicePorts = /* @__PURE__ */ new Map([["default", selfPort]]);
|
|
376783
|
+
}
|
|
376784
|
+
if (existingInstances.publicUrls) {
|
|
376785
|
+
runningContext.publicUrls = new Map(Object.entries(existingInstances.publicUrls));
|
|
376786
|
+
}
|
|
376787
|
+
}
|
|
376788
|
+
const effectiveEnv = runningContext && service.dev?.env ? { ...service.env, ...service.dev.env } : service.env;
|
|
376726
376789
|
let resolvedEnv;
|
|
376727
376790
|
try {
|
|
376728
376791
|
const secrets = await prepareSecrets(config.secrets);
|
|
376729
376792
|
const configs = await prepareConfigs(config.configs);
|
|
376730
|
-
const result = resolveEnvForExec(
|
|
376793
|
+
const result = resolveEnvForExec(effectiveEnv, resources, secrets, configs, runningContext);
|
|
376731
376794
|
resolvedEnv = result.env;
|
|
376732
376795
|
if (result.missingSecrets.length > 0 || result.missingConfigs.length > 0) {
|
|
376733
376796
|
if (result.missingSecrets.length > 0) {
|
|
@@ -376762,7 +376825,9 @@ async function execCommand(serviceName, command, instanceKey = "default") {
|
|
|
376762
376825
|
process.on("SIGINT", () => handleSignal("SIGINT"));
|
|
376763
376826
|
process.on("SIGTERM", () => handleSignal("SIGTERM"));
|
|
376764
376827
|
let effectiveCwd = process.cwd();
|
|
376765
|
-
if (
|
|
376828
|
+
if (options2.cwd) {
|
|
376829
|
+
effectiveCwd = path21.resolve(process.cwd(), options2.cwd);
|
|
376830
|
+
} else if (service.root) {
|
|
376766
376831
|
effectiveCwd = path21.resolve(process.cwd(), service.root);
|
|
376767
376832
|
} else if (service.build) {
|
|
376768
376833
|
const build = config.builds.find((b) => b.name === service.build.name);
|
|
@@ -377422,7 +377487,7 @@ function compareVersions(a, b) {
|
|
|
377422
377487
|
return 0;
|
|
377423
377488
|
}
|
|
377424
377489
|
async function checkForUpdate() {
|
|
377425
|
-
const currentVersion = "0.1.
|
|
377490
|
+
const currentVersion = "0.1.126";
|
|
377426
377491
|
const response = await fetch(`${BINARIES_BASE_URL}/latest?t=${Date.now()}`);
|
|
377427
377492
|
if (!response.ok) {
|
|
377428
377493
|
throw new Error(`Failed to check for updates: HTTP ${response.status}`);
|
|
@@ -377692,7 +377757,7 @@ async function projectListCommand() {
|
|
|
377692
377757
|
var program = new Command();
|
|
377693
377758
|
var env = "production";
|
|
377694
377759
|
var envLabel = env !== "production" ? `[${env.toUpperCase()}] ` : "";
|
|
377695
|
-
program.name("specific").description(`${envLabel}Infrastructure-as-code for coding agents`).version("0.1.
|
|
377760
|
+
program.name("specific").description(`${envLabel}Infrastructure-as-code for coding agents`).version("0.1.126").enablePositionalOptions();
|
|
377696
377761
|
program.command("init").description("Initialize project for use with a coding agent").option("--agent <name...>", "Agents to configure (cursor, claude, codex, other)").addHelpText("after", `
|
|
377697
377762
|
Examples:
|
|
377698
377763
|
$ specific init
|
|
@@ -377722,13 +377787,14 @@ Examples:
|
|
|
377722
377787
|
$ specific deploy --secret db_url=postgres://... --config domain=app.com`).action((options2) => {
|
|
377723
377788
|
deployCommand(options2);
|
|
377724
377789
|
});
|
|
377725
|
-
program.command("exec <service> [args...]").description("Run a one-off command with service environment").option("-k, --key <key>", "Dev environment namespace (auto-detected from git worktree if not specified)").passThroughOptions().addHelpText("after", `
|
|
377790
|
+
program.command("exec <service> [args...]").description("Run a one-off command with service environment").option("-k, --key <key>", "Dev environment namespace (auto-detected from git worktree if not specified)").option("--cwd <path>", "Override working directory (defaults to service.root or build.root)").passThroughOptions().addHelpText("after", `
|
|
377726
377791
|
Examples:
|
|
377727
377792
|
$ specific exec api -- npm run migrate
|
|
377728
|
-
$ specific exec worker -- python manage.py shell
|
|
377793
|
+
$ specific exec worker -- python manage.py shell
|
|
377794
|
+
$ specific exec --cwd . api -- npx expo start`).action(async (service, args, options2) => {
|
|
377729
377795
|
const filteredArgs = args[0] === "--" ? args.slice(1) : args;
|
|
377730
377796
|
const key = options2.key ?? getDefaultKey();
|
|
377731
|
-
await execCommand(service, filteredArgs, key);
|
|
377797
|
+
await execCommand(service, filteredArgs, key, options2.cwd !== void 0 ? { cwd: options2.cwd } : {});
|
|
377732
377798
|
});
|
|
377733
377799
|
program.command("psql [database] [args...]").description("Connect to a Postgres database").option("-k, --key <key>", "Dev environment namespace (auto-detected from git worktree if not specified)").passThroughOptions().addHelpText("after", `
|
|
377734
377800
|
Examples:
|
package/package.json
CHANGED
/package/dist/admin/_next/static/{r3veCvOuDWyK-S0rsl-XQ → xkQQHpz09QHzHXw5WkFYT}/_buildManifest.js
RENAMED
|
File without changes
|
|
File without changes
|
/package/dist/admin/_next/static/{r3veCvOuDWyK-S0rsl-XQ → xkQQHpz09QHzHXw5WkFYT}/_ssgManifest.js
RENAMED
|
File without changes
|