@vxil/cli 0.11.1 → 0.12.0
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/vxil.js +193 -38
- package/package.json +3 -3
package/dist/vxil.js
CHANGED
|
@@ -4462,8 +4462,8 @@ function lowerAllTriggerBindings(def, name) {
|
|
|
4462
4462
|
}
|
|
4463
4463
|
var CONFIG_FILENAMES = ["vxil.config.ts", "vxil.config.mjs", "vxil.config.js"];
|
|
4464
4464
|
var VXIL_CONFIG_PKG_VERSION = "0.7.0";
|
|
4465
|
-
var VXIL_SDK_PKG_VERSION = "0.
|
|
4466
|
-
var VXIL_CLI_PKG_VERSION = "0.
|
|
4465
|
+
var VXIL_SDK_PKG_VERSION = "0.12.0";
|
|
4466
|
+
var VXIL_CLI_PKG_VERSION = "0.12.0";
|
|
4467
4467
|
function ensureScaffoldPackageJson(cwd, opts = {}) {
|
|
4468
4468
|
const file = resolve(cwd, "package.json");
|
|
4469
4469
|
const wanted = {
|
|
@@ -4748,6 +4748,7 @@ async function serverApply({ api, bundle, resume, allowDestructive, onPlan }) {
|
|
|
4748
4748
|
`apply execute (resume with: vxil push --server --resume ${plan.apply_id})`
|
|
4749
4749
|
);
|
|
4750
4750
|
}
|
|
4751
|
+
var PUSH_READ_CONCURRENCY = 5;
|
|
4751
4752
|
async function planOrPush({ api, features, apply, allowDestructive }) {
|
|
4752
4753
|
const results = [];
|
|
4753
4754
|
const destructiveQs = allowDestructive ? "&allow_destructive=true" : "";
|
|
@@ -4755,8 +4756,20 @@ async function planOrPush({ api, features, apply, allowDestructive }) {
|
|
|
4755
4756
|
const v = r.body.data?.api_state;
|
|
4756
4757
|
return v && typeof v === "object" && typeof v.ok === "boolean" ? v : void 0;
|
|
4757
4758
|
};
|
|
4758
|
-
|
|
4759
|
-
|
|
4759
|
+
const entries = Object.entries(features);
|
|
4760
|
+
const reads = await mapPool(entries, PUSH_READ_CONCURRENCY, async ([feature, manifest]) => {
|
|
4761
|
+
try {
|
|
4762
|
+
const dry = await api("PUT", `/v1/config/${feature}?dry_run=true${destructiveQs}`, manifest);
|
|
4763
|
+
if (dry.status !== 200) return { dry };
|
|
4764
|
+
return { dry, cur: await api("GET", `/v1/config/${feature}`) };
|
|
4765
|
+
} catch (err) {
|
|
4766
|
+
return { err };
|
|
4767
|
+
}
|
|
4768
|
+
});
|
|
4769
|
+
for (const [i, [feature, manifest]] of entries.entries()) {
|
|
4770
|
+
const read = reads[i];
|
|
4771
|
+
if ("err" in read) throw read.err;
|
|
4772
|
+
const dry = read.dry;
|
|
4760
4773
|
if (dry.status !== 200) {
|
|
4761
4774
|
const e = dry.body.error ?? {};
|
|
4762
4775
|
throw new Error(
|
|
@@ -4765,7 +4778,7 @@ async function planOrPush({ api, features, apply, allowDestructive }) {
|
|
|
4765
4778
|
}
|
|
4766
4779
|
const effective = dry.body.data?.manifest;
|
|
4767
4780
|
const apiStatePlan = apiStateOf(dry);
|
|
4768
|
-
const cur =
|
|
4781
|
+
const cur = read.cur;
|
|
4769
4782
|
const unavailable = readUnavailable(`GET /v1/config/${feature}`, cur);
|
|
4770
4783
|
if (unavailable) {
|
|
4771
4784
|
if (apply) {
|
|
@@ -7706,6 +7719,58 @@ function hookReconcileOf(data2) {
|
|
|
7706
7719
|
function hookReconcileRemedy(fnName) {
|
|
7707
7720
|
return fnName ? `re-run the reconcile with \`vxil functions deploy ${fnName} --force\` or \`vxil push --server\` (a plain re-push sends no deploy for an unchanged function, so it would not retry it)` : "re-run the reconcile with `vxil push --server` (a plain re-push sends no deploy, so it would not retry it)";
|
|
7708
7721
|
}
|
|
7722
|
+
var WIRING_WARNING = /trigger subscription|cron schedule/i;
|
|
7723
|
+
function triggerWiringOf(data2) {
|
|
7724
|
+
if (!data2) return null;
|
|
7725
|
+
const counts = (v) => {
|
|
7726
|
+
if (!v || typeof v !== "object" || Array.isArray(v)) return void 0;
|
|
7727
|
+
const o = v;
|
|
7728
|
+
const n = (x) => typeof x === "number" && Number.isFinite(x) ? x : 0;
|
|
7729
|
+
const opt = (x) => typeof x === "number" && Number.isFinite(x) ? x : void 0;
|
|
7730
|
+
const updated = opt(o.updated);
|
|
7731
|
+
const unchanged = opt(o.unchanged);
|
|
7732
|
+
return {
|
|
7733
|
+
created: n(o.created),
|
|
7734
|
+
...updated !== void 0 ? { updated } : {},
|
|
7735
|
+
...unchanged !== void 0 ? { unchanged } : {},
|
|
7736
|
+
deleted: n(o.deleted),
|
|
7737
|
+
failed: n(o.failed)
|
|
7738
|
+
};
|
|
7739
|
+
};
|
|
7740
|
+
const cms = counts(data2.cms_hook_subscriptions);
|
|
7741
|
+
const webhook = counts(data2.webhook_subscriptions);
|
|
7742
|
+
const cron = counts(data2.cron_schedules);
|
|
7743
|
+
const total = counts(data2.hook_reconcile);
|
|
7744
|
+
if (!total && !cms && !webhook && !cron) return null;
|
|
7745
|
+
const warnings = Array.isArray(data2.warnings) ? data2.warnings.filter((w) => typeof w === "string" && WIRING_WARNING.test(w)) : [];
|
|
7746
|
+
return {
|
|
7747
|
+
total: total ?? { created: 0, deleted: 0, failed: (cms?.failed ?? 0) + (webhook?.failed ?? 0) + (cron?.failed ?? 0) },
|
|
7748
|
+
...cms ? { cms_hook_subscriptions: cms } : {},
|
|
7749
|
+
...webhook ? { webhook_subscriptions: webhook } : {},
|
|
7750
|
+
...cron ? { cron_schedules: cron } : {},
|
|
7751
|
+
warnings
|
|
7752
|
+
};
|
|
7753
|
+
}
|
|
7754
|
+
function formatTriggerWiring(r) {
|
|
7755
|
+
const line = (c) => [
|
|
7756
|
+
`${c.created} created`,
|
|
7757
|
+
...c.updated !== void 0 ? [`${c.updated} updated`] : [],
|
|
7758
|
+
...c.unchanged !== void 0 ? [`${c.unchanged} unchanged`] : [],
|
|
7759
|
+
`${c.deleted} removed`,
|
|
7760
|
+
`${c.failed} failed`
|
|
7761
|
+
].join(" \xB7 ");
|
|
7762
|
+
const lanes = [
|
|
7763
|
+
["hook subscriptions (cms/auth)", r.cms_hook_subscriptions],
|
|
7764
|
+
["webhook-trigger subscriptions", r.webhook_subscriptions],
|
|
7765
|
+
["cron schedules", r.cron_schedules]
|
|
7766
|
+
];
|
|
7767
|
+
const out = [r.total.failed > 0 ? `trigger wiring (reconciled by the server) \u2014 ${r.total.failed} FAILED:` : "trigger wiring (reconciled by the server):"];
|
|
7768
|
+
const shown = lanes.filter(([, c]) => c);
|
|
7769
|
+
if (shown.length) for (const [label, c] of shown) out.push(` ${label.padEnd(30)} ${line(c)}`);
|
|
7770
|
+
else out.push(` ${"all triggers".padEnd(30)} ${line(r.total)}`);
|
|
7771
|
+
for (const w of r.warnings) out.push(` ! ${w}`);
|
|
7772
|
+
return out;
|
|
7773
|
+
}
|
|
7709
7774
|
function sourceSha12(source, runtime) {
|
|
7710
7775
|
const suffix = runtime ? functionsRuntimeHashSuffix(runtime) : "";
|
|
7711
7776
|
return createHash("sha256").update(source + suffix, "utf8").digest("hex").slice(0, 12);
|
|
@@ -12302,7 +12367,7 @@ var TOOLS = [
|
|
|
12302
12367
|
{
|
|
12303
12368
|
name: "search_query",
|
|
12304
12369
|
feature: "vector-search",
|
|
12305
|
-
description: "Retrieve the top-k most relevant chunks from a vector-search collection. mode 'hybrid' (default) fuses semantic + keyword via RRF; 'vector' is pure semantic; 'keyword' is lexical. filter is a JSON object of equality constraints over chunk metadata. Returns
|
|
12370
|
+
description: "Retrieve the top-k most relevant chunks from a vector-search collection. mode 'hybrid' (default) fuses semantic + keyword via RRF; 'vector' is pure semantic; 'keyword' is lexical. filter is a JSON object of equality constraints over chunk metadata. Returns ranked results with document/chunk attribution: score is the fused rank value (orders the hits, not a similarity); similarity is the cosine similarity to the query (-1..1, null in keyword mode) \u2014 threshold on similarity.",
|
|
12306
12371
|
inputSchema: {
|
|
12307
12372
|
type: "object",
|
|
12308
12373
|
properties: {
|
|
@@ -12496,7 +12561,7 @@ var TOOLS = [
|
|
|
12496
12561
|
filter: { type: "object", additionalProperties: true, description: "Metadata equality filter applied to retrieval." },
|
|
12497
12562
|
rerank: { type: "boolean", description: "Forward rerank:true to vector-search's BYO rerank pass (inert until configured there)." },
|
|
12498
12563
|
boosts: { type: "object", additionalProperties: true, description: "Per-metadata-field boost specs: { field: { kind:'recency', halfLifeDays?, weight? } | { kind:'value', weights:{\u2026} } }." },
|
|
12499
|
-
min_score: { type: "number", description: "Drop hits below this EFFECTIVE (post-boost) score." }
|
|
12564
|
+
min_score: { type: "number", description: "Drop hits below this EFFECTIVE (post-boost) score. score is a rank value (about 0.016-0.033 at the top), so a floor above ~0.033 drops every hit; judge relevance by each hit's similarity instead." }
|
|
12500
12565
|
},
|
|
12501
12566
|
required: ["query"]
|
|
12502
12567
|
},
|
|
@@ -13933,7 +13998,7 @@ var VERB_USAGE = {
|
|
|
13933
13998
|
mcp: "usage: vxil mcp install [--client cursor|claude|vscode] [--project] [--print] [--key <api_key>] [--scopes a,b] [--name <server>]",
|
|
13934
13999
|
plan: "usage: vxil plan [--dev|--target <name>] [--explain] [--skip-functions] \u2014 what `vxil push` would change: cms schema, feature config, declared API state, functions (a deployed function the config no longer declares shows as `-`); writes nothing",
|
|
13935
14000
|
diff: "usage: vxil diff [--against <target>|--exit-code] [--explain] [--ignore <k,\u2026>] [--strict-secrets] [--strict-api-state] [--api-state] [--json] \u2014 the CI gate: exit 0 no drift \xB7 1 drift \xB7 2 error",
|
|
13936
|
-
push: "usage: vxil push [--dev|--target <name>|--prod] [--allow-destructive] [--strict] [--server [--resume <apply_id>]] [--no-gen] [--skip-functions] [--yes] \u2014 apply the config; --allow-destructive also deletes deployed functions and stored AI templates the config no longer declares; --strict exits 1 when anything declared was refused, deferred or left unwired",
|
|
14001
|
+
push: "usage: vxil push [--dev|--target <name>|--prod] [--allow-destructive] [--strict] [--server [--resume <apply_id>]] [--no-gen] [--skip-functions] [--yes] \u2014 apply the config; --allow-destructive also deletes deployed functions and stored AI templates the config no longer declares; --strict exits 1 when anything declared was refused, deferred or left unwired; --server prints the trigger wiring the server reconciled (--json: one result document on stdout)",
|
|
13937
14002
|
gen: "usage: vxil gen [--check] [--offline] [--out <f>] [--no-mcp] [--mcp-out <f>] \u2014 generate vxil.types.ts (+ vxil.mcp.json); --offline keeps an existing API_VERSIONS block; --check compares instead of writing",
|
|
13938
14003
|
types: "usage: vxil types \u2014 alias of `vxil gen` (run `vxil gen --help`)",
|
|
13939
14004
|
doctor: "usage: vxil doctor [--dev|--target <name>] \u2014 preflight: the binding's tenant vs the key's tenant, secrets referenced-vs-stored, per-function hashes, keys (read-only)",
|
|
@@ -14022,6 +14087,32 @@ function pushExitCode(p, strict) {
|
|
|
14022
14087
|
if (p.strict.length) lines.push(`${p.strict.length} warning(s) \u2014 \`vxil push --strict\` turns them into exit 1 for CI`);
|
|
14023
14088
|
return { code: 0, lines };
|
|
14024
14089
|
}
|
|
14090
|
+
function serverApplyJson(input) {
|
|
14091
|
+
const { view, triggerWiring, problems, exitCode, error } = input;
|
|
14092
|
+
return {
|
|
14093
|
+
ok: exitCode === 0,
|
|
14094
|
+
exit_code: exitCode,
|
|
14095
|
+
apply_id: view.apply_id,
|
|
14096
|
+
status: view.status,
|
|
14097
|
+
steps: view.steps,
|
|
14098
|
+
...view.failed_step ? { failed_step: view.failed_step } : {},
|
|
14099
|
+
trigger_wiring: triggerWiring ?? null,
|
|
14100
|
+
problems: { hard: problems.hard, strict: problems.strict },
|
|
14101
|
+
...error ? { error } : {}
|
|
14102
|
+
};
|
|
14103
|
+
}
|
|
14104
|
+
function serverApplyErrorJson(input) {
|
|
14105
|
+
return {
|
|
14106
|
+
ok: false,
|
|
14107
|
+
exit_code: input.exitCode,
|
|
14108
|
+
apply_id: null,
|
|
14109
|
+
status: null,
|
|
14110
|
+
steps: [],
|
|
14111
|
+
trigger_wiring: null,
|
|
14112
|
+
problems: { hard: [], strict: [] },
|
|
14113
|
+
error: input.error
|
|
14114
|
+
};
|
|
14115
|
+
}
|
|
14025
14116
|
|
|
14026
14117
|
// src/paymentsCmd.ts
|
|
14027
14118
|
var SIMULATE_SCENARIOS = [
|
|
@@ -19669,12 +19760,19 @@ function hasFlag(name) {
|
|
|
19669
19760
|
return rest.includes(`--${name}`);
|
|
19670
19761
|
}
|
|
19671
19762
|
var jsonOut = rest.includes("--json");
|
|
19763
|
+
var jsonFailDoc = null;
|
|
19672
19764
|
function ttlFlag(fallback) {
|
|
19673
19765
|
const parsed = parseTtlFlag(flag("ttl"), fallback);
|
|
19674
19766
|
if ("error" in parsed) fail(parsed.error);
|
|
19675
19767
|
return parsed.hours;
|
|
19676
19768
|
}
|
|
19677
19769
|
function fail(msg, code = 1) {
|
|
19770
|
+
if (jsonFailDoc) {
|
|
19771
|
+
const doc = jsonFailDoc;
|
|
19772
|
+
jsonFailDoc = null;
|
|
19773
|
+
process.stdout.write(`${doc(msg, code)}
|
|
19774
|
+
`);
|
|
19775
|
+
}
|
|
19678
19776
|
console.error(`vxil: ${msg}`);
|
|
19679
19777
|
process.exit(code);
|
|
19680
19778
|
}
|
|
@@ -20566,22 +20664,79 @@ async function backendListsFunctions(api) {
|
|
|
20566
20664
|
}
|
|
20567
20665
|
}
|
|
20568
20666
|
async function runServerApply(sel) {
|
|
20667
|
+
armServerApplyJsonFail();
|
|
20569
20668
|
const { api, target } = requireApi(sel, { write: "push --server" });
|
|
20669
|
+
const say = (s) => {
|
|
20670
|
+
if (jsonOut) console.error(s);
|
|
20671
|
+
else console.log(s);
|
|
20672
|
+
};
|
|
20673
|
+
const strict = hasFlag("strict");
|
|
20674
|
+
const finish = async (done2, problems2, code, error) => {
|
|
20675
|
+
jsonFailDoc = null;
|
|
20676
|
+
if (jsonOut) {
|
|
20677
|
+
const doc = JSON.stringify(serverApplyJson({
|
|
20678
|
+
view: done2,
|
|
20679
|
+
triggerWiring: triggerWiringOf(done2),
|
|
20680
|
+
problems: problems2,
|
|
20681
|
+
exitCode: code,
|
|
20682
|
+
...error ? { error } : {}
|
|
20683
|
+
}));
|
|
20684
|
+
await new Promise((r) => {
|
|
20685
|
+
process.stdout.write(`${doc}
|
|
20686
|
+
`, () => r());
|
|
20687
|
+
});
|
|
20688
|
+
}
|
|
20689
|
+
if (error) fail(error, code);
|
|
20690
|
+
process.exit(code);
|
|
20691
|
+
};
|
|
20692
|
+
const armWith = (done2, problems2) => {
|
|
20693
|
+
if (!jsonOut) return;
|
|
20694
|
+
jsonFailDoc = (error, exitCode) => JSON.stringify(serverApplyJson({
|
|
20695
|
+
view: done2,
|
|
20696
|
+
triggerWiring: triggerWiringOf(done2),
|
|
20697
|
+
problems: problems2,
|
|
20698
|
+
exitCode,
|
|
20699
|
+
error
|
|
20700
|
+
}));
|
|
20701
|
+
};
|
|
20702
|
+
const report = (done2, wiring) => {
|
|
20703
|
+
say(formatApplySteps(done2.steps));
|
|
20704
|
+
say(`
|
|
20705
|
+
apply ${done2.apply_id}: ${done2.status}`);
|
|
20706
|
+
if (!wiring) return;
|
|
20707
|
+
const w = triggerWiringOf(done2);
|
|
20708
|
+
if (w) say(`
|
|
20709
|
+
${formatTriggerWiring(w).join("\n")}`);
|
|
20710
|
+
};
|
|
20711
|
+
const gen = async () => {
|
|
20712
|
+
if (hasFlag("no-gen")) return;
|
|
20713
|
+
if (!jsonOut) {
|
|
20714
|
+
await runGen(sel);
|
|
20715
|
+
return;
|
|
20716
|
+
}
|
|
20717
|
+
const log = console.log;
|
|
20718
|
+
console.log = (...a) => {
|
|
20719
|
+
console.error(...a);
|
|
20720
|
+
};
|
|
20721
|
+
try {
|
|
20722
|
+
await runGen(sel);
|
|
20723
|
+
} finally {
|
|
20724
|
+
console.log = log;
|
|
20725
|
+
}
|
|
20726
|
+
};
|
|
20570
20727
|
const resume = flag("resume");
|
|
20571
20728
|
if (resume) {
|
|
20572
20729
|
const done2 = await serverApply({ api, resume });
|
|
20573
|
-
|
|
20574
|
-
console.log(`
|
|
20575
|
-
apply ${done2.apply_id}: ${done2.status}`);
|
|
20576
|
-
if (done2.status === "running") console.log(`resume with: vxil push --server --resume ${done2.apply_id}`);
|
|
20577
|
-
if (done2.status !== "succeeded" && done2.status !== "running") process.exit(1);
|
|
20578
|
-
if (done2.status === "succeeded" && !hasFlag("no-gen")) await runGen(sel);
|
|
20730
|
+
report(done2, true);
|
|
20579
20731
|
const resumed = { hard: [], strict: [] };
|
|
20732
|
+
armWith(done2, resumed);
|
|
20733
|
+
if (done2.status === "running") say(`resume with: vxil push --server --resume ${done2.apply_id}`);
|
|
20734
|
+
if (done2.status !== "succeeded" && done2.status !== "running") return finish(done2, resumed, 1);
|
|
20735
|
+
if (done2.status === "succeeded") await gen();
|
|
20580
20736
|
applyHookProblems(done2, resumed);
|
|
20581
|
-
const exitResumed = pushExitCode(resumed,
|
|
20737
|
+
const exitResumed = pushExitCode(resumed, strict);
|
|
20582
20738
|
for (const line of exitResumed.lines) console.error(`vxil: ${line}`);
|
|
20583
|
-
|
|
20584
|
-
return;
|
|
20739
|
+
return finish(done2, resumed, exitResumed.code);
|
|
20585
20740
|
}
|
|
20586
20741
|
const loaded = await loadVxilConfig();
|
|
20587
20742
|
const cwd = process.cwd();
|
|
@@ -20589,7 +20744,7 @@ apply ${done2.apply_id}: ${done2.status}`);
|
|
|
20589
20744
|
const cfg = hasFlag("skip-functions") ? rest2 : loaded;
|
|
20590
20745
|
const fnNames = Object.keys(cfg.functions ?? {});
|
|
20591
20746
|
if (hasFlag("skip-functions") && declaredFns && Object.keys(declaredFns).length) {
|
|
20592
|
-
|
|
20747
|
+
say(`functions: skipped (--skip-functions) \u2014 ${Object.keys(declaredFns).length} declared function(s) not deployed`);
|
|
20593
20748
|
}
|
|
20594
20749
|
if (fnNames.length) {
|
|
20595
20750
|
const ent = await probeFunctionsEntitlement(api, fnNames[0]);
|
|
@@ -20614,33 +20769,30 @@ apply ${done2.apply_id}: ${done2.status}`);
|
|
|
20614
20769
|
bundle,
|
|
20615
20770
|
allowDestructive: hasFlag("allow-destructive"),
|
|
20616
20771
|
onPlan: (plan) => {
|
|
20617
|
-
|
|
20618
|
-
|
|
20619
|
-
for (const w of plan.warnings ?? [])
|
|
20620
|
-
|
|
20772
|
+
say(`plan (apply ${plan.apply_id}):`);
|
|
20773
|
+
say(formatApplySteps(plan.steps));
|
|
20774
|
+
for (const w of plan.warnings ?? []) say(` ! ${w}`);
|
|
20775
|
+
say("\napplying server-side\u2026");
|
|
20621
20776
|
}
|
|
20622
20777
|
});
|
|
20623
|
-
console.log(formatApplySteps(done.steps));
|
|
20624
|
-
console.log(`
|
|
20625
|
-
apply ${done.apply_id}: ${done.status}`);
|
|
20626
20778
|
if (done.status === "running") {
|
|
20627
20779
|
const errored = done.steps.filter((st) => st.status === "pending" && st.error);
|
|
20628
20780
|
const onlyDeferredApiState = errored.length > 0 && errored.every((st) => st.kind === "api-state" && (st.error ?? "").startsWith("deferred:"));
|
|
20629
20781
|
if (onlyDeferredApiState) {
|
|
20630
|
-
|
|
20782
|
+
report(done, false);
|
|
20783
|
+
say(" \u2026 declared API state deferred (the feature config is still propagating) \u2014 waiting 30 s, then resuming the same apply");
|
|
20631
20784
|
await new Promise((r) => setTimeout(r, 3e4));
|
|
20632
20785
|
done = await serverApply({ api, resume: done.apply_id });
|
|
20633
|
-
console.log(formatApplySteps(done.steps));
|
|
20634
|
-
console.log(`
|
|
20635
|
-
apply ${done.apply_id}: ${done.status}`);
|
|
20636
20786
|
}
|
|
20637
20787
|
}
|
|
20788
|
+
report(done, true);
|
|
20789
|
+
const problems = { hard: [], strict: [] };
|
|
20790
|
+
armWith(done, problems);
|
|
20638
20791
|
if (done.status === "running") {
|
|
20639
|
-
|
|
20792
|
+
return finish(done, problems, 1, `a transient step failure interrupted the apply \u2014 resume with: vxil push --server --resume ${done.apply_id}`);
|
|
20640
20793
|
}
|
|
20641
20794
|
const standing = done.steps.filter((st) => st.kind === "api-state" && st.status === "failed");
|
|
20642
20795
|
const onlyApiStateFailed = done.steps.every((st) => st.status !== "failed" || st.kind === "api-state");
|
|
20643
|
-
const problems = { hard: [], strict: [] };
|
|
20644
20796
|
if (done.status === "partial" && standing.length && onlyApiStateFailed && done.failed_step?.kind === "api-state" && done.steps.every((st) => st.status !== "rolled_back")) {
|
|
20645
20797
|
for (const st of standing) {
|
|
20646
20798
|
console.error(`vxil: warning \u2014 ${st.target} not converged: ${st.error ?? ""} (the config stands; fix the cause and re-push)`);
|
|
@@ -20648,7 +20800,7 @@ apply ${done.apply_id}: ${done.status}`);
|
|
|
20648
20800
|
}
|
|
20649
20801
|
} else if (done.status !== "succeeded") {
|
|
20650
20802
|
const f = done.failed_step;
|
|
20651
|
-
|
|
20803
|
+
return finish(done, problems, 1, `apply ${done.status}${f ? ` \u2014 step ${f.seq} (${f.kind} ${f.target}): ${f.error}` : ""} (config/functions were rolled back to their pre-apply versions; cms schema additions were kept)`);
|
|
20652
20804
|
}
|
|
20653
20805
|
applyHookProblems(done, problems);
|
|
20654
20806
|
if (!hasFlag("skip-functions") && (fnNames.length || cfg.features.functions || await backendListsFunctions(api))) {
|
|
@@ -20662,24 +20814,26 @@ apply ${done.apply_id}: ${done.status}`);
|
|
|
20662
20814
|
for (const name of deployed.filter((n) => !fnNames.includes(n)).sort()) {
|
|
20663
20815
|
if (hasFlag("allow-destructive")) {
|
|
20664
20816
|
const del = await deleteRemoteFunction(api, name);
|
|
20665
|
-
|
|
20817
|
+
say(` - ${name} [deployed, not in vxil.config] \u2014 ${del.gone ? "already gone" : "deleted (--allow-destructive)"}`);
|
|
20666
20818
|
if (del.hook && del.hook.failed > 0) problems.hard.push(`trigger wiring: ${del.hook.failed} subscription(s) failed to reconcile after deleting ${name} \u2014 ${hookReconcileRemedy(fnNames[0])}`);
|
|
20667
20819
|
} else {
|
|
20668
|
-
|
|
20820
|
+
say(` - ${name} [deployed, not in vxil.config] \u2014 kept; \`vxil push --server --allow-destructive\` deletes it`);
|
|
20669
20821
|
problems.strict.push(`deployed but not declared (kept): ${name}`);
|
|
20670
20822
|
}
|
|
20671
20823
|
}
|
|
20672
20824
|
}
|
|
20673
20825
|
}
|
|
20674
|
-
|
|
20675
|
-
const exitWith = pushExitCode(problems,
|
|
20826
|
+
await gen();
|
|
20827
|
+
const exitWith = pushExitCode(problems, strict);
|
|
20676
20828
|
for (const line of exitWith.lines) console.error(`vxil: ${line}`);
|
|
20677
|
-
|
|
20829
|
+
return finish(done, problems, exitWith.code);
|
|
20830
|
+
}
|
|
20831
|
+
function armServerApplyJsonFail() {
|
|
20832
|
+
if (jsonOut) jsonFailDoc = (error, exitCode) => JSON.stringify(serverApplyErrorJson({ error, exitCode }));
|
|
20678
20833
|
}
|
|
20679
20834
|
function applyHookProblems(done, problems) {
|
|
20680
20835
|
const hook = hookReconcileOf(done);
|
|
20681
20836
|
if (!hook || hook.failed === 0) return;
|
|
20682
|
-
console.error(` ! trigger wiring: ${hook.warning ?? `${hook.failed} trigger subscription(s) could not be written`}`);
|
|
20683
20837
|
problems.hard.push(`trigger wiring: ${hook.failed} subscription(s) failed to reconcile \u2014 a function may be wired to nothing; re-run \`vxil push --server\` (every executed apply re-runs the reconcile)`);
|
|
20684
20838
|
}
|
|
20685
20839
|
async function runSeed(sel, opts = {}) {
|
|
@@ -21877,6 +22031,7 @@ ${formatSummary(state)}`);
|
|
|
21877
22031
|
break;
|
|
21878
22032
|
}
|
|
21879
22033
|
case "push": {
|
|
22034
|
+
if (hasFlag("server") || flag("resume") !== void 0) armServerApplyJsonFail();
|
|
21880
22035
|
if (hasFlag("prod") && (hasFlag("dev") || flag("target") !== void 0)) fail("--prod cannot be combined with --dev / --target \u2014 pick one target");
|
|
21881
22036
|
const sel = selector();
|
|
21882
22037
|
const pushTarget = resolveTargetOrFail(sel);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vxil/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.12.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "The vxil CLI — init, quickstart, push, gen, secrets, keys, migrate, doctor, diff, functions, payments; installs the `vxil` command (npm i -g @vxil/cli).",
|
|
6
6
|
"license": "MIT",
|
|
@@ -47,9 +47,9 @@
|
|
|
47
47
|
"devDependencies": {
|
|
48
48
|
"miniflare": "^4.20260611.0",
|
|
49
49
|
"@vxil/config": "0.7.0",
|
|
50
|
-
"@vxil/feature-configs": "0.7.0",
|
|
51
50
|
"@vxil/runtime": "0.0.1",
|
|
52
|
-
"@vxil/types": "0.0.1"
|
|
51
|
+
"@vxil/types": "0.0.1",
|
|
52
|
+
"@vxil/feature-configs": "0.7.0"
|
|
53
53
|
},
|
|
54
54
|
"scripts": {
|
|
55
55
|
"build": "pnpm --filter @vxil/feature-configs run build && pnpm --filter @vxil/config run build && esbuild bin/vxil.ts --bundle --platform=node --format=esm --target=node24 --outfile=dist/vxil.js --banner:js='#!/usr/bin/env node' --external:esbuild --external:miniflare && esbuild src/config-entry.ts --bundle --platform=node --format=esm --target=node24 --outfile=dist/config.js && pnpm exec tsx scripts/build-config-dts.ts",
|