@vxil/cli 0.12.0 → 0.13.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/config.d.ts +15 -0
- package/dist/config.js +21 -0
- package/dist/vxil.js +62 -17
- package/package.json +4 -4
package/dist/config.d.ts
CHANGED
|
@@ -40,7 +40,22 @@ export interface FieldDef {
|
|
|
40
40
|
* `orgs` role alphabet). The gate
|
|
41
41
|
* never affects WRITES. Carried by BOTH push paths and alterable in place. */
|
|
42
42
|
readRoles?: string[];
|
|
43
|
+
/** EQUALITY INDEX for an UNSLOTTED field (cms.md §3 "Indexed equality"):
|
|
44
|
+
* `=` / `$eq` / `$in` filters on it are index-served instead of a bounded
|
|
45
|
+
* scan — results are identical either way. At most 4 per collection (the
|
|
46
|
+
* equality-key budget, separate from the 8 index slots); not together with
|
|
47
|
+
* `indexSlot` (a slot already indexes equality) and not on a computed field
|
|
48
|
+
* (both checked here at define time and again by the server). Carried by
|
|
49
|
+
* BOTH push paths and alterable in place; on a collection over 2,000 live
|
|
50
|
+
* items `vxil push` also runs the re-index that arms it. */
|
|
51
|
+
indexed?: boolean;
|
|
43
52
|
}
|
|
53
|
+
/** The per-collection budget of `indexed: true` fields (cms/0158: e1…e4). */
|
|
54
|
+
export declare const CMS_INDEXED_FIELD_BUDGET = 4;
|
|
55
|
+
/** Define-time checks of a collection's `indexed` fields — the same refusals
|
|
56
|
+
* the server makes (422), so a config fails at `defineConfig` / `collection()`
|
|
57
|
+
* instead of mid-push. Throws on the first violation. */
|
|
58
|
+
export declare function assertIndexedFields(name: string, def: CollectionDef): void;
|
|
44
59
|
/** One config-declared per-record ACTION button (cms.md §17): exactly ONE
|
|
45
60
|
* human-initiated step — pressing it invokes the deployed tenant function `fn`
|
|
46
61
|
* with `{ collection, item_id, action, actor, item }` and returns its result.
|
package/dist/config.js
CHANGED
|
@@ -1,4 +1,21 @@
|
|
|
1
1
|
// ../config/src/index.ts
|
|
2
|
+
var CMS_INDEXED_FIELD_BUDGET = 4;
|
|
3
|
+
function assertIndexedFields(name, def) {
|
|
4
|
+
let n = 0;
|
|
5
|
+
for (const [fname, f] of Object.entries(def.fields ?? {})) {
|
|
6
|
+
if (f.indexed !== true) continue;
|
|
7
|
+
n += 1;
|
|
8
|
+
if (f.indexSlot) {
|
|
9
|
+
throw new Error(`vxil.config: cms.${name}.${fname} sets both indexed and indexSlot '${f.indexSlot}' \u2014 a slot already indexes equality; use one`);
|
|
10
|
+
}
|
|
11
|
+
if (f.computed) {
|
|
12
|
+
throw new Error(`vxil.config: cms.${name}.${fname} is computed \u2014 a computed field cannot be indexed (bind it to an indexSlot instead)`);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
if (n > CMS_INDEXED_FIELD_BUDGET) {
|
|
16
|
+
throw new Error(`vxil.config: cms.${name} has ${n} indexed fields \u2014 at most ${CMS_INDEXED_FIELD_BUDGET} per collection`);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
2
19
|
var RELEASED_API_VERSIONS = ["v1"];
|
|
3
20
|
function defineConfig(c) {
|
|
4
21
|
if (c.apiVersion !== void 0 && !RELEASED_API_VERSIONS.includes(c.apiVersion)) {
|
|
@@ -6,16 +23,20 @@ function defineConfig(c) {
|
|
|
6
23
|
`vxil.config: apiVersion '${String(c.apiVersion)}' is not a released API major (released: ${RELEASED_API_VERSIONS.map((v) => `'${v}'`).join(", ")}). A new major ships as a new path with its own deprecation window \u2014 see https://vxil.com/docs/guide/12-going-to-production.`
|
|
7
24
|
);
|
|
8
25
|
}
|
|
26
|
+
for (const [name, def] of Object.entries(c.cms?.collections ?? {})) assertIndexedFields(name, def);
|
|
9
27
|
return c;
|
|
10
28
|
}
|
|
11
29
|
function field(type, opts = {}) {
|
|
12
30
|
return { type, ...opts };
|
|
13
31
|
}
|
|
14
32
|
function collection(def) {
|
|
33
|
+
assertIndexedFields(def.singular ?? "collection", def);
|
|
15
34
|
return def;
|
|
16
35
|
}
|
|
17
36
|
export {
|
|
37
|
+
CMS_INDEXED_FIELD_BUDGET,
|
|
18
38
|
RELEASED_API_VERSIONS,
|
|
39
|
+
assertIndexedFields,
|
|
19
40
|
collection,
|
|
20
41
|
defineConfig,
|
|
21
42
|
field
|
package/dist/vxil.js
CHANGED
|
@@ -4461,9 +4461,9 @@ function lowerAllTriggerBindings(def, name) {
|
|
|
4461
4461
|
return bindings;
|
|
4462
4462
|
}
|
|
4463
4463
|
var CONFIG_FILENAMES = ["vxil.config.ts", "vxil.config.mjs", "vxil.config.js"];
|
|
4464
|
-
var VXIL_CONFIG_PKG_VERSION = "0.
|
|
4465
|
-
var VXIL_SDK_PKG_VERSION = "0.
|
|
4466
|
-
var VXIL_CLI_PKG_VERSION = "0.
|
|
4464
|
+
var VXIL_CONFIG_PKG_VERSION = "0.8.0";
|
|
4465
|
+
var VXIL_SDK_PKG_VERSION = "0.13.0";
|
|
4466
|
+
var VXIL_CLI_PKG_VERSION = "0.13.0";
|
|
4467
4467
|
function ensureScaffoldPackageJson(cwd, opts = {}) {
|
|
4468
4468
|
const file = resolve(cwd, "package.json");
|
|
4469
4469
|
const wanted = {
|
|
@@ -8150,6 +8150,14 @@ function formatLogLines(lines) {
|
|
|
8150
8150
|
}
|
|
8151
8151
|
|
|
8152
8152
|
// src/cms.ts
|
|
8153
|
+
function indexReadyOf(rf) {
|
|
8154
|
+
return rf.index_ready === true;
|
|
8155
|
+
}
|
|
8156
|
+
var EQ_INDEX_INLINE_MAX_ROWS = 2e3;
|
|
8157
|
+
function indexArmNote(rows) {
|
|
8158
|
+
if (rows === null) return "arms inline or through the re-index push runs (live row count unavailable)";
|
|
8159
|
+
return rows <= EQ_INDEX_INLINE_MAX_ROWS ? `arms inline (${rows} rows)` : `needs reindex (${rows} rows; push runs it)`;
|
|
8160
|
+
}
|
|
8153
8161
|
function normalizeActions(raw) {
|
|
8154
8162
|
if (!Array.isArray(raw)) return [];
|
|
8155
8163
|
return raw.filter((a) => !!a && typeof a === "object").map((a) => ({ key: String(a.key), label: String(a.label), fn: String(a.fn) }));
|
|
@@ -8169,7 +8177,10 @@ var FIELD_ATTRS = [
|
|
|
8169
8177
|
// (the server stores NULL for "ungated" and normalizes `[]` to NULL), so an
|
|
8170
8178
|
// omitted attribute diffs clean; CLEARING it WIDENS access and therefore rides
|
|
8171
8179
|
// the same --allow-destructive gate as clearing unique/on_delete/owner_field.
|
|
8172
|
-
{ config: "readRoles", wire: "read_roles", remote: "read_roles", blank: null, alter: "tighten-only" }
|
|
8180
|
+
{ config: "readRoles", wire: "read_roles", remote: "read_roles", blank: null, alter: "tighten-only" },
|
|
8181
|
+
// PERF-26b: the equality index of an unslotted field (≤4 per collection).
|
|
8182
|
+
// Present-key on the server; arming on > 2,000 live rows runs the re-index.
|
|
8183
|
+
{ config: "indexed", wire: "indexed", remote: "indexed", blank: false, alter: "index" }
|
|
8173
8184
|
];
|
|
8174
8185
|
function fieldToInput(name, def) {
|
|
8175
8186
|
const out = { field: name, type: def.type };
|
|
@@ -8192,7 +8203,7 @@ function remoteFieldToConfig(rf) {
|
|
|
8192
8203
|
function fieldAttrDelta(def, rf) {
|
|
8193
8204
|
const d = def;
|
|
8194
8205
|
const r = rf;
|
|
8195
|
-
const out = { flags: [], clearing: [], inPlace: [], reindex: [], retarget: [], drift: [] };
|
|
8206
|
+
const out = { flags: [], clearing: [], inPlace: [], reindex: [], retarget: [], index: [], drift: [] };
|
|
8196
8207
|
for (const a of FIELD_ATTRS) {
|
|
8197
8208
|
const wantBlank = stableStringify(a.blank);
|
|
8198
8209
|
const want = stableStringify(d[a.config] ?? a.blank);
|
|
@@ -8209,6 +8220,7 @@ function fieldAttrDelta(def, rf) {
|
|
|
8209
8220
|
}
|
|
8210
8221
|
if (a.alter === "reindex") out.reindex.push(line);
|
|
8211
8222
|
else if (a.alter === "destructive") out.retarget.push(line);
|
|
8223
|
+
else if (a.alter === "index") out.index.push(line);
|
|
8212
8224
|
else out.inPlace.push(line);
|
|
8213
8225
|
}
|
|
8214
8226
|
return out;
|
|
@@ -8254,6 +8266,7 @@ async function reindexCollection({ api, collection, field, onProgress }) {
|
|
|
8254
8266
|
let updated = 0;
|
|
8255
8267
|
let pages = 0;
|
|
8256
8268
|
let skipped = 0;
|
|
8269
|
+
let indexCertify;
|
|
8257
8270
|
const page = async () => {
|
|
8258
8271
|
const res = await api("POST", `/v1/cms/collections/${encodeURIComponent(collection)}/reindex`, {
|
|
8259
8272
|
...field ? { field } : {},
|
|
@@ -8267,6 +8280,7 @@ async function reindexCollection({ api, collection, field, onProgress }) {
|
|
|
8267
8280
|
scanned += d.scanned ?? 0;
|
|
8268
8281
|
updated += d.updated ?? 0;
|
|
8269
8282
|
pages++;
|
|
8283
|
+
if (d.index_certify) indexCertify = d.index_certify;
|
|
8270
8284
|
return d;
|
|
8271
8285
|
};
|
|
8272
8286
|
for (; ; ) {
|
|
@@ -8283,7 +8297,7 @@ async function reindexCollection({ api, collection, field, onProgress }) {
|
|
|
8283
8297
|
}
|
|
8284
8298
|
cursor = d.next_cursor;
|
|
8285
8299
|
}
|
|
8286
|
-
return { scanned, updated, pages, skipped };
|
|
8300
|
+
return { scanned, updated, pages, skipped, ...indexCertify ? { indexCertify } : {} };
|
|
8287
8301
|
}
|
|
8288
8302
|
async function planCmsSchema({ api, collections, apply, allowDestructive = false, onProgress }) {
|
|
8289
8303
|
const read = await readRemote2(api);
|
|
@@ -8312,11 +8326,17 @@ async function planCmsSchema({ api, collections, apply, allowDestructive = false
|
|
|
8312
8326
|
const collChanges = [];
|
|
8313
8327
|
const post = [];
|
|
8314
8328
|
const slotMoved = [];
|
|
8329
|
+
const indexArming = [];
|
|
8330
|
+
const indexVacating = [];
|
|
8331
|
+
let rowsMemo;
|
|
8332
|
+
const rows = () => rowsMemo ??= liveRowCount(api, name);
|
|
8315
8333
|
const remoteByName = new Map(rc.fields.map((f) => [f.field, f]));
|
|
8316
8334
|
for (const [fn, fd] of declaredFields) {
|
|
8317
8335
|
const existing = remoteByName.get(fn);
|
|
8318
8336
|
if (!existing) {
|
|
8319
|
-
|
|
8337
|
+
const arm = fd.indexed === true ? `; indexed: ${indexArmNote(await rows())}` : "";
|
|
8338
|
+
if (fd.indexed === true) indexArming.push(fn);
|
|
8339
|
+
collChanges.push({ collection: name, kind: "add-field", field: fn, detail: `${name}.${fn} (${fd.type})${arm}` });
|
|
8320
8340
|
} else if (existing.type !== fd.type) {
|
|
8321
8341
|
if (allowDestructive && (fd.indexSlot ?? null) !== (existing.index_slot ?? null)) {
|
|
8322
8342
|
if (existing.index_slot) {
|
|
@@ -8339,10 +8359,14 @@ async function planCmsSchema({ api, collections, apply, allowDestructive = false
|
|
|
8339
8359
|
detail: `${name}.${fn} type ${existing.type} \u2192 ${fd.type} (destructive alter)`
|
|
8340
8360
|
});
|
|
8341
8361
|
} else {
|
|
8342
|
-
const { flags, clearing, inPlace, reindex, retarget, drift } = fieldAttrDelta(fd, existing);
|
|
8362
|
+
const { flags, clearing, inPlace, reindex, retarget, index, drift } = fieldAttrDelta(fd, existing);
|
|
8363
|
+
const armsIndex = fd.indexed === true && (index.length > 0 || !indexReadyOf(existing));
|
|
8364
|
+
const indexNote = armsIndex ? ` \u2014 ${fn} indexed: ${indexArmNote(await rows())}` : "";
|
|
8365
|
+
if (armsIndex) indexArming.push(fn);
|
|
8366
|
+
if (index.length > 0 && fd.indexed !== true && existing.indexed === true) indexVacating.push(fn);
|
|
8343
8367
|
const destructiveAttrs = [...clearing, ...reindex, ...retarget];
|
|
8344
8368
|
if (destructiveAttrs.length) {
|
|
8345
|
-
const all = [...destructiveAttrs, ...flags, ...inPlace];
|
|
8369
|
+
const all = [...destructiveAttrs, ...flags, ...inPlace, ...index];
|
|
8346
8370
|
if (allowDestructive) {
|
|
8347
8371
|
if (reindex.length && existing.index_slot) {
|
|
8348
8372
|
pre.push({
|
|
@@ -8359,7 +8383,7 @@ async function planCmsSchema({ api, collections, apply, allowDestructive = false
|
|
|
8359
8383
|
kind: "destructive",
|
|
8360
8384
|
op: "alter-field",
|
|
8361
8385
|
field: fn,
|
|
8362
|
-
detail: `${name}.${fn} ${all.join(", ")}` + (clearing.length ? " \u2014 clearing a live invariant (unique claims / on_delete cascade / read_roles gate)" : "") + (reindex.length ? " \u2014 an index_slot move: stored rows keep the OLD projection until the re-index runs" : "") + (retarget.length ? " \u2014 a relation retarget: every stored id now names a different collection" : "") + " (full-config reconciliation)"
|
|
8386
|
+
detail: `${name}.${fn} ${all.join(", ")}` + (clearing.length ? " \u2014 clearing a live invariant (unique claims / on_delete cascade / read_roles gate)" : "") + (reindex.length ? " \u2014 an index_slot move: stored rows keep the OLD projection until the re-index runs" : "") + (retarget.length ? " \u2014 a relation retarget: every stored id now names a different collection" : "") + indexNote + " (full-config reconciliation)"
|
|
8363
8387
|
});
|
|
8364
8388
|
if (reindex.length) slotMoved.push(fn);
|
|
8365
8389
|
} else {
|
|
@@ -8370,12 +8394,12 @@ async function planCmsSchema({ api, collections, apply, allowDestructive = false
|
|
|
8370
8394
|
detail: `${name}.${fn} ${all.join(", ")}: this is DESTRUCTIVE-SHAPED \u2014 ` + (clearing.length ? "it CLEARS a live invariant (clearing unique DROPS the uniqueness claims \u2014 duplicates then accepted, unrecoverable; clearing on_delete stops cascades; clearing read_roles WIDENS the field to every end-user); " : "") + (reindex.length ? "an index_slot move leaves stored rows on the OLD projection until a re-index, so queries on the field return the WRONG rows; " : "") + (retarget.length ? "a relation retarget repoints every stored id at another collection; " : "") + "it is NOT applied (nor is any co-declared in-place change on this field). Re-run with --allow-destructive to apply."
|
|
8371
8395
|
});
|
|
8372
8396
|
}
|
|
8373
|
-
} else if (flags.length || inPlace.length) {
|
|
8397
|
+
} else if (flags.length || inPlace.length || index.length) {
|
|
8374
8398
|
collChanges.push({
|
|
8375
8399
|
collection: name,
|
|
8376
8400
|
kind: "alter-flags",
|
|
8377
8401
|
field: fn,
|
|
8378
|
-
detail: `${name}.${fn} ${[...flags, ...inPlace].join(", ")} (non-destructive in-place alter)`
|
|
8402
|
+
detail: `${name}.${fn} ${[...flags, ...inPlace, ...index].join(", ")} (non-destructive in-place alter)${indexNote}`
|
|
8379
8403
|
});
|
|
8380
8404
|
}
|
|
8381
8405
|
if (drift.length) {
|
|
@@ -8439,12 +8463,25 @@ async function planCmsSchema({ api, collections, apply, allowDestructive = false
|
|
|
8439
8463
|
});
|
|
8440
8464
|
}
|
|
8441
8465
|
}
|
|
8442
|
-
|
|
8443
|
-
|
|
8466
|
+
let armReindex = false;
|
|
8467
|
+
let vacateReindex = false;
|
|
8468
|
+
if (indexArming.length > 0 || indexVacating.length > 0) {
|
|
8469
|
+
const n = await rows();
|
|
8470
|
+
const large = n === null || n > EQ_INDEX_INLINE_MAX_ROWS;
|
|
8471
|
+
armReindex = large && indexArming.length > 0;
|
|
8472
|
+
vacateReindex = large && indexVacating.length > 0;
|
|
8473
|
+
}
|
|
8474
|
+
if (slotMoved.length || armReindex || vacateReindex) {
|
|
8475
|
+
const n = await rows();
|
|
8476
|
+
const why = [
|
|
8477
|
+
...slotMoved.length ? [`the index_slot move on ${slotMoved.join(", ")}`] : [],
|
|
8478
|
+
...armReindex ? [`arming the equality index on ${indexArming.join(", ")}`] : [],
|
|
8479
|
+
...vacateReindex ? [`clearing the equality index of ${indexVacating.join(", ")}`] : []
|
|
8480
|
+
];
|
|
8444
8481
|
post.push({
|
|
8445
8482
|
collection: name,
|
|
8446
8483
|
kind: "reindex",
|
|
8447
|
-
detail: `${name} re-index ${n === null ? "live rows" : `${n} live rows`} after
|
|
8484
|
+
detail: `${name} re-index ${n === null ? "live rows" : `${n} live rows`} after ${why.join(" and ")}`
|
|
8448
8485
|
});
|
|
8449
8486
|
}
|
|
8450
8487
|
changes.push(...pre, ...collChanges, ...post);
|
|
@@ -8534,6 +8571,8 @@ async function planCmsSchema({ api, collections, apply, allowDestructive = false
|
|
|
8534
8571
|
if (done.skipped > 0) {
|
|
8535
8572
|
onProgress?.(` \u26A0 ${done.skipped} row(s) of ${c.collection} were written while the re-index ran and were NOT re-projected \u2014 re-run \`vxil cms reindex ` + c.collection + "` when writes are quiet");
|
|
8536
8573
|
}
|
|
8574
|
+
const certifyWarning = indexCertifyWarning(c.collection, done.indexCertify);
|
|
8575
|
+
if (certifyWarning) onProgress?.(certifyWarning);
|
|
8537
8576
|
applied++;
|
|
8538
8577
|
} else if (c.kind === "destructive") {
|
|
8539
8578
|
applied += await applyDestructive(api, collections, c);
|
|
@@ -8608,6 +8647,10 @@ function formatCollectionDrop(collection, plan, declaredLocally) {
|
|
|
8608
8647
|
}
|
|
8609
8648
|
return lines.join("\n");
|
|
8610
8649
|
}
|
|
8650
|
+
function indexCertifyWarning(collection, certify) {
|
|
8651
|
+
if (certify !== "timeout" && certify !== "pending") return null;
|
|
8652
|
+
return ` \u26A0 the index on ${collection} is NOT armed yet (` + (certify === "timeout" ? "its certification ran out of time" : "rows changed during the pass") + ") \u2014 filters stay correct but unaccelerated; re-run `vxil cms reindex " + collection + "`";
|
|
8653
|
+
}
|
|
8611
8654
|
|
|
8612
8655
|
// src/apiCmd.ts
|
|
8613
8656
|
var API_METHODS = ["GET", "POST", "PUT", "PATCH", "DELETE"];
|
|
@@ -11733,7 +11776,7 @@ var TOOLS = [
|
|
|
11733
11776
|
{
|
|
11734
11777
|
name: "cms_list_collections",
|
|
11735
11778
|
feature: "cms",
|
|
11736
|
-
description: "List the tenant's content model: collections with their typed field definitions (the schema items are validated against). Each field row carries its attributes \u2014 required, validation, index_slot, relation_to, computed/compute, is_unique, on_delete,
|
|
11779
|
+
description: "List the tenant's content model: collections with their typed field definitions (the schema items are validated against). Each field row carries its attributes \u2014 required, validation, index_slot, relation_to, computed/compute, is_unique, on_delete, read_roles (the end-user org roles allowed to READ that field; null = ungated), and on an equality-indexed field indexed: true + index_ready (equality filters on it are index-served once ready; until then, and on unindexed unslotted fields, they are a bounded scan \u2014 same results). A field with read_roles is omitted from end-user reads without a matching role and is never served on the public lane, so a missing key in an item's data may be a read gate rather than an unset value.",
|
|
11737
11780
|
inputSchema: { type: "object", properties: {} },
|
|
11738
11781
|
method: "GET",
|
|
11739
11782
|
path: "/v1/cms/collections"
|
|
@@ -11757,7 +11800,7 @@ var TOOLS = [
|
|
|
11757
11800
|
{
|
|
11758
11801
|
name: "cms_query_items",
|
|
11759
11802
|
feature: "cms",
|
|
11760
|
-
description: 'Query content items with the bounded DSL. filter is a JSON object (\u22648 terms): {"price":{"$gte":10},"status":"published"}; ops $eq $ne $gt $gte $lt $lte $in $contains $startsWith (substring/prefix, LIKE-escaped) $arrayContains/$anyOf (array fields: all-of / any-of). sort: "-field" (slot-indexed fields + created_at/updated_at/published_at). Paging: pass the returned next_cursor back as cursor WITH THE SAME filter and sort (works for the default order and for any slot/timestamp sort; not for a dotted join sort). $expand inlines relation/file fields. count=true returns {count} instead of a page (filter only \u2014 no sort/limit/cursor/$expand).',
|
|
11803
|
+
description: 'Query content items with the bounded DSL. filter is a JSON object (\u22648 terms): {"price":{"$gte":10},"status":"published"}; ops $eq $ne $gt $gte $lt $lte $in $contains $startsWith (substring/prefix, LIKE-escaped) $arrayContains/$anyOf (array fields: all-of / any-of). Equality ($eq / bare value / $in) is index-served on slot-indexed and `indexed` fields; on other fields it is a bounded scan (same results). sort: "-field" (slot-indexed fields + created_at/updated_at/published_at). Paging: pass the returned next_cursor back as cursor WITH THE SAME filter and sort (works for the default order and for any slot/timestamp sort; not for a dotted join sort). $expand inlines relation/file fields. count=true returns {count} instead of a page (filter only \u2014 no sort/limit/cursor/$expand).',
|
|
11761
11804
|
inputSchema: {
|
|
11762
11805
|
type: "object",
|
|
11763
11806
|
properties: {
|
|
@@ -22529,6 +22572,8 @@ export default defineConfig(${JSON.stringify({ features: featBlocks, cms: { coll
|
|
|
22529
22572
|
if (done.skipped > 0) {
|
|
22530
22573
|
console.log(` \u26A0 ${done.skipped} row(s) were written while the re-index ran and were NOT re-projected \u2014 re-run \`vxil cms reindex ${collection}\` when writes are quiet`);
|
|
22531
22574
|
}
|
|
22575
|
+
const certifyWarning = indexCertifyWarning(collection, done.indexCertify);
|
|
22576
|
+
if (certifyWarning) console.log(certifyWarning);
|
|
22532
22577
|
} else {
|
|
22533
22578
|
fail("usage: vxil cms status|pull|reindex <collection> [--field <field>]|drop <collection> [--yes]|bulk-rm <collection> --filter '<json>' [--dry-run] [--yes]");
|
|
22534
22579
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vxil/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.13.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",
|
|
@@ -46,10 +46,10 @@
|
|
|
46
46
|
},
|
|
47
47
|
"devDependencies": {
|
|
48
48
|
"miniflare": "^4.20260611.0",
|
|
49
|
-
"@vxil/config": "0.
|
|
49
|
+
"@vxil/config": "0.8.0",
|
|
50
50
|
"@vxil/runtime": "0.0.1",
|
|
51
|
-
"@vxil/
|
|
52
|
-
"@vxil/
|
|
51
|
+
"@vxil/feature-configs": "0.7.0",
|
|
52
|
+
"@vxil/types": "0.0.1"
|
|
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",
|