@datarails-ai/dr-cli 1.6.119 → 1.6.120
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/cli.js
CHANGED
|
@@ -8,7 +8,7 @@ import { fileURLToPath as fileURLToPath3 } from "url";
|
|
|
8
8
|
// package.json
|
|
9
9
|
var package_default = {
|
|
10
10
|
name: "@datarails-ai/dr-cli",
|
|
11
|
-
version: "1.6.
|
|
11
|
+
version: "1.6.120",
|
|
12
12
|
description: "Datarails CLI",
|
|
13
13
|
type: "module",
|
|
14
14
|
engines: {
|
|
@@ -69,7 +69,7 @@ var package_default = {
|
|
|
69
69
|
};
|
|
70
70
|
|
|
71
71
|
// src/buildInfo.ts
|
|
72
|
-
var BUILD_TIME = "2026-10-
|
|
72
|
+
var BUILD_TIME = "2026-10-12T10:19:56.130Z";
|
|
73
73
|
function formatBuildTime(iso) {
|
|
74
74
|
if (iso === "") return "";
|
|
75
75
|
const d = new Date(iso);
|
|
@@ -3798,6 +3798,11 @@ var PROD_GATE_TIER_B = /* @__PURE__ */ new Set([
|
|
|
3798
3798
|
// no interactive word gate. If a rescan ever gains a destructive side effect,
|
|
3799
3799
|
// this key moves to Tier A.
|
|
3800
3800
|
"table|rescan",
|
|
3801
|
+
// dr filebox rescan-version (DR-54137): the same reasoning at the scale of one
|
|
3802
|
+
// version — the UI's per-version Rescan. It re-extracts that version with the
|
|
3803
|
+
// tables' current datamappers and replaces its rows; it never deletes rows it
|
|
3804
|
+
// does not re-load, and it is re-runnable. Token-only.
|
|
3805
|
+
"filebox-version|rescan",
|
|
3801
3806
|
// spend-control (dr spend-control contracts bulk-create). `archive` and its
|
|
3802
3807
|
// inverse `restore` are a single PATCH of `is_archived` — each undoes the
|
|
3803
3808
|
// other exactly, so token-only. The hard `delete` verb is Tier A.
|
|
@@ -19116,6 +19121,24 @@ async function updateAutoCalculateSettings(client, docId, body, reqOptions) {
|
|
|
19116
19121
|
async function downloadVersion(client, versionId, reqOptions) {
|
|
19117
19122
|
return client.do("GET", `/api/documents/versions/${versionId}/file`, void 0, reqOptions);
|
|
19118
19123
|
}
|
|
19124
|
+
async function listBucketTemplates(client, bucketId, reqOptions) {
|
|
19125
|
+
const out = await client.getJSON(
|
|
19126
|
+
`/api/buckets/${bucketId}/templates`,
|
|
19127
|
+
reqOptions
|
|
19128
|
+
);
|
|
19129
|
+
return Array.isArray(out) ? out : [];
|
|
19130
|
+
}
|
|
19131
|
+
async function listDocumentTables(client, docId, reqOptions) {
|
|
19132
|
+
const out = await client.getJSON(
|
|
19133
|
+
`/api/documents/${docId}/bucket`,
|
|
19134
|
+
reqOptions
|
|
19135
|
+
);
|
|
19136
|
+
const list28 = out?.templates;
|
|
19137
|
+
return Array.isArray(list28) ? list28 : [];
|
|
19138
|
+
}
|
|
19139
|
+
async function rescanBucketVersions(client, bucketId, body, reqOptions) {
|
|
19140
|
+
await client.postJSON(`/api/buckets/${bucketId}/rescan_versions`, body, reqOptions);
|
|
19141
|
+
}
|
|
19119
19142
|
|
|
19120
19143
|
// src/commands/_lutMappings.ts
|
|
19121
19144
|
var ROW_FIELDS = ["create", "update", "delete"];
|
|
@@ -35341,6 +35364,232 @@ function registerFileboxAdminCommands(fb, setupCall2, addServerFlag2, addAccount
|
|
|
35341
35364
|
addAccountFlag2(vrSetCmd);
|
|
35342
35365
|
}
|
|
35343
35366
|
|
|
35367
|
+
// src/commands/_typedError.ts
|
|
35368
|
+
function isTypedError(err) {
|
|
35369
|
+
return !(err instanceof Error) || err.constructor !== Error || "code" in err;
|
|
35370
|
+
}
|
|
35371
|
+
function withErrorContext(context, err) {
|
|
35372
|
+
if (isTypedError(err)) return err;
|
|
35373
|
+
const e = err;
|
|
35374
|
+
return new Error(`${context}: ${e.message}`, { cause: e });
|
|
35375
|
+
}
|
|
35376
|
+
|
|
35377
|
+
// src/commands/filebox_rescanVersion.ts
|
|
35378
|
+
function sortedUnique(ids) {
|
|
35379
|
+
return [...new Set(ids)].sort((a, b) => a - b);
|
|
35380
|
+
}
|
|
35381
|
+
function rescanVersionAction(versionId, tableIds) {
|
|
35382
|
+
return {
|
|
35383
|
+
resource: "filebox-version",
|
|
35384
|
+
id: `${versionId}:tables=${sortedUnique(tableIds).join(",")}`,
|
|
35385
|
+
verb: "rescan"
|
|
35386
|
+
};
|
|
35387
|
+
}
|
|
35388
|
+
function buildRescanVersionConfirmCmd(versionId, tableIds, serverFlag, asJson) {
|
|
35389
|
+
const tableFlags = sortedUnique(tableIds).map((t) => ` --table ${t}`).join("");
|
|
35390
|
+
const jsonFlag = asJson ? " --json" : "";
|
|
35391
|
+
return `dr filebox rescan-version ${versionId}${tableFlags} --server ${serverFlag}${jsonFlag}`;
|
|
35392
|
+
}
|
|
35393
|
+
function describeVersionTags(tags) {
|
|
35394
|
+
if (!Array.isArray(tags) || tags.length === 0) return "(none)";
|
|
35395
|
+
const parts = [];
|
|
35396
|
+
for (const t of tags) {
|
|
35397
|
+
if (t === null || typeof t !== "object") continue;
|
|
35398
|
+
const r = t;
|
|
35399
|
+
const name = typeof r["name"] === "string" && r["name"] !== "" ? r["name"] : `tag ${String(r["id"])}`;
|
|
35400
|
+
const label = r["label"];
|
|
35401
|
+
const value = typeof label === "string" && label !== "" ? label : r["value"] === void 0 || r["value"] === null ? "?" : String(r["value"]);
|
|
35402
|
+
parts.push(`${name}: ${value}`);
|
|
35403
|
+
}
|
|
35404
|
+
return parts.length === 0 ? "(none)" : parts.join(", ");
|
|
35405
|
+
}
|
|
35406
|
+
async function step(context, p) {
|
|
35407
|
+
try {
|
|
35408
|
+
return await p;
|
|
35409
|
+
} catch (err) {
|
|
35410
|
+
throw withErrorContext(context, err);
|
|
35411
|
+
}
|
|
35412
|
+
}
|
|
35413
|
+
async function resolveRescan2(cfg) {
|
|
35414
|
+
const opts = { signal: cfg.signal };
|
|
35415
|
+
const version = await step(
|
|
35416
|
+
`load version ${cfg.versionId}`,
|
|
35417
|
+
getVersion(cfg.client, cfg.versionId, opts)
|
|
35418
|
+
);
|
|
35419
|
+
if (version.auto_save === true) {
|
|
35420
|
+
throw new Error(
|
|
35421
|
+
`version ${cfg.versionId} is archived; the server only rescans non-archived versions (restore it first with \`dr filebox restore-version ${cfg.versionId}\`)`
|
|
35422
|
+
);
|
|
35423
|
+
}
|
|
35424
|
+
if (version.include_file === false) {
|
|
35425
|
+
throw new Error(
|
|
35426
|
+
`version ${cfg.versionId} is excluded from the database; a rescan would extract nothing (include it with \`dr filebox set-version-include ${cfg.versionId} --include on\`, which itself queues the extraction)`
|
|
35427
|
+
);
|
|
35428
|
+
}
|
|
35429
|
+
const doc = await step(
|
|
35430
|
+
`load filebox ${version.document} of version ${cfg.versionId}`,
|
|
35431
|
+
getDetails(cfg.client, version.document, opts)
|
|
35432
|
+
);
|
|
35433
|
+
const bucketId = typeof doc.bucket === "number" && doc.bucket > 0 ? doc.bucket : void 0;
|
|
35434
|
+
if (bucketId === void 0) {
|
|
35435
|
+
throw new Error(
|
|
35436
|
+
`filebox ${version.document} has no bucket; the per-version rescan endpoint is bucket-scoped and cannot address this version`
|
|
35437
|
+
);
|
|
35438
|
+
}
|
|
35439
|
+
const [bucketTables, docTables] = await Promise.all([
|
|
35440
|
+
step(
|
|
35441
|
+
`list tables of filebox ${version.document}`,
|
|
35442
|
+
listBucketTemplates(cfg.client, bucketId, opts)
|
|
35443
|
+
),
|
|
35444
|
+
step(
|
|
35445
|
+
`list tables filebox ${version.document} is mapped into`,
|
|
35446
|
+
listDocumentTables(cfg.client, version.document, opts)
|
|
35447
|
+
)
|
|
35448
|
+
]);
|
|
35449
|
+
const mappedIds = new Set(docTables.map((t) => t.id));
|
|
35450
|
+
const eligible = bucketTables.filter((t) => mappedIds.has(t.id));
|
|
35451
|
+
let tables;
|
|
35452
|
+
if (cfg.tableIds.length === 0) {
|
|
35453
|
+
tables = eligible;
|
|
35454
|
+
} else {
|
|
35455
|
+
const byId = new Map(eligible.map((t) => [t.id, t]));
|
|
35456
|
+
const unknown = sortedUnique(cfg.tableIds).filter((id) => !byId.has(id));
|
|
35457
|
+
if (unknown.length > 0) {
|
|
35458
|
+
throw new Error(
|
|
35459
|
+
`--table ${unknown.join(", ")}: not an active table that filebox ${version.document} is mapped into, so the server would skip it` + (eligible.length > 0 ? ` (eligible tables: ${eligible.map((t) => t.id).join(", ")})` : "")
|
|
35460
|
+
);
|
|
35461
|
+
}
|
|
35462
|
+
tables = sortedUnique(cfg.tableIds).map((id) => byId.get(id));
|
|
35463
|
+
}
|
|
35464
|
+
if (tables.length === 0) {
|
|
35465
|
+
throw new Error(
|
|
35466
|
+
`filebox ${version.document} is not mapped into any active table; there is nothing to re-extract version ${cfg.versionId} into`
|
|
35467
|
+
);
|
|
35468
|
+
}
|
|
35469
|
+
return { version, doc, bucketId, tables };
|
|
35470
|
+
}
|
|
35471
|
+
function tableLabel(t) {
|
|
35472
|
+
return t.name !== "" ? `${t.name} (${t.id})` : String(t.id);
|
|
35473
|
+
}
|
|
35474
|
+
async function runFileboxRescanVersion(cfg) {
|
|
35475
|
+
if (cfg.versionId <= 0) {
|
|
35476
|
+
throw new Error("version id must be positive");
|
|
35477
|
+
}
|
|
35478
|
+
for (const id of cfg.tableIds) {
|
|
35479
|
+
if (!Number.isInteger(id) || id <= 0) {
|
|
35480
|
+
throw new Error(`invalid --table value: "${id}"`);
|
|
35481
|
+
}
|
|
35482
|
+
}
|
|
35483
|
+
if (cfg.tableIds.length > 0) {
|
|
35484
|
+
await preflightConfirmToken(rescanVersionAction(cfg.versionId, cfg.tableIds), cfg.token);
|
|
35485
|
+
}
|
|
35486
|
+
const r = await resolveRescan2(cfg);
|
|
35487
|
+
const tableIds = r.tables.map((t) => t.id);
|
|
35488
|
+
const action = rescanVersionAction(cfg.versionId, tableIds);
|
|
35489
|
+
await preflightConfirmToken(action, cfg.token);
|
|
35490
|
+
const docLabel = r.doc.name !== "" ? `${r.doc.name} (${r.doc.id})` : String(r.doc.id);
|
|
35491
|
+
await twoStepConfirm({
|
|
35492
|
+
out: cfg.out,
|
|
35493
|
+
action,
|
|
35494
|
+
token: cfg.token,
|
|
35495
|
+
server: cfg.serverFlag,
|
|
35496
|
+
confirmCmd: buildRescanVersionConfirmCmd(
|
|
35497
|
+
cfg.versionId,
|
|
35498
|
+
cfg.tableIds,
|
|
35499
|
+
cfg.serverFlag,
|
|
35500
|
+
cfg.asJson
|
|
35501
|
+
),
|
|
35502
|
+
describe: async () => [
|
|
35503
|
+
`version: ${cfg.versionId} (v${r.version.version}, ${r.version.name})`,
|
|
35504
|
+
`filebox: ${docLabel}, bucket ${r.bucketId}`,
|
|
35505
|
+
`tags: ${describeVersionTags(r.version.tags)} (unchanged)`,
|
|
35506
|
+
`tables: ${r.tables.map(tableLabel).join(", ")}`,
|
|
35507
|
+
"effect: re-extracts THIS version only, in place, with the tables\u2019 current datamappers; its existing rows in each table are replaced, not duplicated",
|
|
35508
|
+
"scope: other versions of the filebox or collection process are not touched; the token is bound to these tables"
|
|
35509
|
+
],
|
|
35510
|
+
execute: async () => {
|
|
35511
|
+
await step(
|
|
35512
|
+
`rescan version ${cfg.versionId}`,
|
|
35513
|
+
rescanBucketVersions(
|
|
35514
|
+
cfg.client,
|
|
35515
|
+
r.bucketId,
|
|
35516
|
+
{ versions: [cfg.versionId], templates: tableIds },
|
|
35517
|
+
{ signal: cfg.signal }
|
|
35518
|
+
)
|
|
35519
|
+
);
|
|
35520
|
+
if (cfg.asJson) {
|
|
35521
|
+
writeJSONIndented(cfg.out, {
|
|
35522
|
+
version_id: cfg.versionId,
|
|
35523
|
+
version: r.version.version,
|
|
35524
|
+
doc_id: r.doc.id,
|
|
35525
|
+
bucket_id: r.bucketId,
|
|
35526
|
+
tables: r.tables.map((t) => ({ id: t.id, name: t.name })),
|
|
35527
|
+
queued: true
|
|
35528
|
+
});
|
|
35529
|
+
return;
|
|
35530
|
+
}
|
|
35531
|
+
cfg.out.write(
|
|
35532
|
+
`Rescan queued for version ${cfg.versionId} (v${r.version.version}) into ${r.tables.length} table(s). Poll with: dr scans status ${tableIds[0]} --server ${cfg.serverFlag}
|
|
35533
|
+
`
|
|
35534
|
+
);
|
|
35535
|
+
}
|
|
35536
|
+
});
|
|
35537
|
+
}
|
|
35538
|
+
function parseVersionIdArg(arg) {
|
|
35539
|
+
const n = Number(arg);
|
|
35540
|
+
if (!Number.isInteger(n) || String(n) !== arg || n <= 0) {
|
|
35541
|
+
throw new Error(`invalid version id: "${arg}"`);
|
|
35542
|
+
}
|
|
35543
|
+
return n;
|
|
35544
|
+
}
|
|
35545
|
+
function collectTableId(value, previous) {
|
|
35546
|
+
const n = Number(value);
|
|
35547
|
+
if (!Number.isInteger(n) || String(n) !== value || n <= 0) {
|
|
35548
|
+
throw new Error(`invalid --table value: "${value}"`);
|
|
35549
|
+
}
|
|
35550
|
+
return previous.concat([n]);
|
|
35551
|
+
}
|
|
35552
|
+
function registerFileboxRescanVersionCommand(fb) {
|
|
35553
|
+
const cmd = fb.command("rescan-version").description(
|
|
35554
|
+
'Re-extract ONE filebox version in place, without changing its tags \u2014 the UI version "three dots > Rescan". Only this version is re-extracted (not the rest of its filebox or collection process), with the tables\u2019 current datamappers; its rows in each table are replaced, not duplicated. Two-step confirmation: run once to see the version, filebox, tags and tables and get a token, then re-run with --confirm-token.'
|
|
35555
|
+
).argument("<version_id>", "document version id (global)").option(
|
|
35556
|
+
"--table <table_id>",
|
|
35557
|
+
"Re-extract into this table only (repeatable). Default: every active table the filebox is mapped into.",
|
|
35558
|
+
collectTableId,
|
|
35559
|
+
[]
|
|
35560
|
+
).option(
|
|
35561
|
+
"--confirm-token <token>",
|
|
35562
|
+
"Token from a prior plan run \u2014 required to actually trigger the rescan",
|
|
35563
|
+
""
|
|
35564
|
+
).option("--json", "Output the queued rescan as JSON instead of prose", false).action(
|
|
35565
|
+
async (idStr, opts) => {
|
|
35566
|
+
const versionId = parseVersionIdArg(idStr);
|
|
35567
|
+
const tableIds = opts.table ?? [];
|
|
35568
|
+
if (tableIds.length > 0) {
|
|
35569
|
+
await preflightConfirmToken(rescanVersionAction(versionId, tableIds), opts.confirmToken);
|
|
35570
|
+
}
|
|
35571
|
+
const serverKey = resolveServer(opts.server);
|
|
35572
|
+
const setup = await setupCall(opts.server, opts.account);
|
|
35573
|
+
try {
|
|
35574
|
+
await runFileboxRescanVersion({
|
|
35575
|
+
client: setup.client,
|
|
35576
|
+
versionId,
|
|
35577
|
+
tableIds,
|
|
35578
|
+
token: opts.confirmToken,
|
|
35579
|
+
serverFlag: serverKey,
|
|
35580
|
+
asJson: opts.json === true,
|
|
35581
|
+
signal: setup.signal,
|
|
35582
|
+
out: process.stdout
|
|
35583
|
+
});
|
|
35584
|
+
} finally {
|
|
35585
|
+
setup.cleanup();
|
|
35586
|
+
}
|
|
35587
|
+
}
|
|
35588
|
+
);
|
|
35589
|
+
addServerFlag(cmd);
|
|
35590
|
+
addAccountFlag(cmd);
|
|
35591
|
+
}
|
|
35592
|
+
|
|
35344
35593
|
// src/api/forecast.ts
|
|
35345
35594
|
var SCENARIO_PARAM = "Forecast";
|
|
35346
35595
|
async function listScenarios(client, filter = {}, options) {
|
|
@@ -36979,7 +37228,7 @@ function parseVersionAddressing(positional, opts, latestFlag) {
|
|
|
36979
37228
|
);
|
|
36980
37229
|
}
|
|
36981
37230
|
if (hasPositional) {
|
|
36982
|
-
return { mode: "direct", versionId:
|
|
37231
|
+
return { mode: "direct", versionId: parseVersionIdArg2(positional) };
|
|
36983
37232
|
}
|
|
36984
37233
|
if (hasNumber && hasLatest) {
|
|
36985
37234
|
throw new Error(`pass either --version-number <n> or ${latestFlag}, not both`);
|
|
@@ -37159,9 +37408,6 @@ function parseVersionLabelFlags(label, clear) {
|
|
|
37159
37408
|
}
|
|
37160
37409
|
return validateVersionLabel(label);
|
|
37161
37410
|
}
|
|
37162
|
-
function isTypedError(err) {
|
|
37163
|
-
return !(err instanceof Error) || err.constructor !== Error || "code" in err;
|
|
37164
|
-
}
|
|
37165
37411
|
async function writeVersionLabel(client, versionId, label, signal) {
|
|
37166
37412
|
const res = await setVersionNameLabel(client, versionId, label, { signal });
|
|
37167
37413
|
if (res.status < 200 || res.status >= 300) {
|
|
@@ -38583,7 +38829,7 @@ function parseFileboxIdArg(arg) {
|
|
|
38583
38829
|
}
|
|
38584
38830
|
return n;
|
|
38585
38831
|
}
|
|
38586
|
-
function
|
|
38832
|
+
function parseVersionIdArg2(arg) {
|
|
38587
38833
|
const n = Number(arg);
|
|
38588
38834
|
if (!Number.isInteger(n) || String(n) !== arg) {
|
|
38589
38835
|
throw new Error(`invalid version id: "${arg}"`);
|
|
@@ -38684,7 +38930,7 @@ function registerFileboxCommand(root) {
|
|
|
38684
38930
|
addServerFlag(tagsCmd);
|
|
38685
38931
|
addAccountFlag(tagsCmd);
|
|
38686
38932
|
const sheetsCmd = fb.command("sheets").description("List sheets in a filebox version (names, indices, row/col counts)").argument("<version_id>", "version id (positive integer)").option("--json", "Output raw JSON instead of a table", false).action(async (vidStr, opts) => {
|
|
38687
|
-
const versionId =
|
|
38933
|
+
const versionId = parseVersionIdArg2(vidStr);
|
|
38688
38934
|
const setup = await setupCall(opts.server, opts.account);
|
|
38689
38935
|
try {
|
|
38690
38936
|
await runFileboxSheets({
|
|
@@ -38702,7 +38948,7 @@ function registerFileboxCommand(root) {
|
|
|
38702
38948
|
addAccountFlag(sheetsCmd);
|
|
38703
38949
|
const previewCmd = fb.command("preview").description("Preview raw cell data of a filebox version (row 1 is headers)").argument("<version_id>", "version id (positive integer)").option("--sheet <name>", "Sheet name. Defaults to first sheet from /desc.", "").option("--sheet-ind <n>", "Sheet index (0-based). Defaults to 0.", "0").option("--start <n>", "First row to read (1-based)", "1").option("--rows <n>", "Number of rows to return (start..start+rows-1)", "100").option("--data-only", "Return evaluated values only; omit raw formulas", false).option("--json", "Output raw JSON instead of a table", false).action(
|
|
38704
38950
|
async (vidStr, opts) => {
|
|
38705
|
-
const versionId =
|
|
38951
|
+
const versionId = parseVersionIdArg2(vidStr);
|
|
38706
38952
|
const sheetInd = parsePositiveIntFlag2(opts.sheetInd, "--sheet-ind", 0);
|
|
38707
38953
|
const start = parsePositiveIntFlag2(opts.start, "--start", 1);
|
|
38708
38954
|
const rows = parsePositiveIntFlag2(opts.rows, "--rows", 100);
|
|
@@ -39490,6 +39736,7 @@ function registerFileboxCommand(root) {
|
|
|
39490
39736
|
addServerFlag(dqSyncCmd);
|
|
39491
39737
|
addAccountFlag(dqSyncCmd);
|
|
39492
39738
|
registerFileboxAdminCommands(fb, setupCall, addServerFlag, addAccountFlag);
|
|
39739
|
+
registerFileboxRescanVersionCommand(fb);
|
|
39493
39740
|
}
|
|
39494
39741
|
|
|
39495
39742
|
// src/commands/integrations.ts
|
|
@@ -50743,14 +50990,14 @@ function renderMecProcessDetail(out, p) {
|
|
|
50743
50990
|
}
|
|
50744
50991
|
async function runMecStepGet(cfg) {
|
|
50745
50992
|
await requireMec(cfg.client, { signal: cfg.signal });
|
|
50746
|
-
const
|
|
50993
|
+
const step2 = await withMec(
|
|
50747
50994
|
() => getStep(cfg.client, cfg.processId, cfg.stepId, { signal: cfg.signal })
|
|
50748
50995
|
);
|
|
50749
50996
|
if (cfg.asJson) {
|
|
50750
|
-
writeJSONIndented(cfg.out,
|
|
50997
|
+
writeJSONIndented(cfg.out, step2);
|
|
50751
50998
|
return;
|
|
50752
50999
|
}
|
|
50753
|
-
renderMecStepDetail(cfg.out,
|
|
51000
|
+
renderMecStepDetail(cfg.out, step2);
|
|
50754
51001
|
}
|
|
50755
51002
|
function renderMecStepDetail(out, s) {
|
|
50756
51003
|
const rows = [
|
|
@@ -50797,10 +51044,10 @@ function renderMecTaskTable(out, tasks, indent) {
|
|
|
50797
51044
|
}
|
|
50798
51045
|
async function runMecTaskList(cfg) {
|
|
50799
51046
|
await requireMec(cfg.client, { signal: cfg.signal });
|
|
50800
|
-
const
|
|
51047
|
+
const step2 = await withMec(
|
|
50801
51048
|
() => getStep(cfg.client, cfg.processId, cfg.stepId, { signal: cfg.signal })
|
|
50802
51049
|
);
|
|
50803
|
-
const tasks = allStepTasks(
|
|
51050
|
+
const tasks = allStepTasks(step2);
|
|
50804
51051
|
if (cfg.asJson) {
|
|
50805
51052
|
writeJSONIndented(cfg.out, tasks);
|
|
50806
51053
|
return;
|
|
@@ -50816,10 +51063,10 @@ async function runMecTaskList(cfg) {
|
|
|
50816
51063
|
}
|
|
50817
51064
|
async function runMecTaskGet(cfg) {
|
|
50818
51065
|
await requireMec(cfg.client, { signal: cfg.signal });
|
|
50819
|
-
const
|
|
51066
|
+
const step2 = await withMec(
|
|
50820
51067
|
() => getStep(cfg.client, cfg.processId, cfg.stepId, { signal: cfg.signal })
|
|
50821
51068
|
);
|
|
50822
|
-
const tasks = allStepTasks(
|
|
51069
|
+
const tasks = allStepTasks(step2);
|
|
50823
51070
|
const match = tasks.find((t) => t.id === cfg.taskId);
|
|
50824
51071
|
if (match === void 0) {
|
|
50825
51072
|
throw new Error(
|
|
@@ -51194,11 +51441,11 @@ async function collectMecActivationCascade(client, template, signal) {
|
|
|
51194
51441
|
return lines;
|
|
51195
51442
|
}
|
|
51196
51443
|
const steps = process2.steps ?? [];
|
|
51197
|
-
for (const
|
|
51198
|
-
if (
|
|
51199
|
-
const tasks = allStepTasks(
|
|
51444
|
+
for (const step2 of steps) {
|
|
51445
|
+
if (step2.notify_automatically !== true) continue;
|
|
51446
|
+
const tasks = allStepTasks(step2);
|
|
51200
51447
|
if (tasks.length === 0) continue;
|
|
51201
|
-
lines.push(` step "${
|
|
51448
|
+
lines.push(` step "${step2.name}":`);
|
|
51202
51449
|
for (const t of tasks) {
|
|
51203
51450
|
lines.push(` \u2192 ${userLabel(t.assignee)} (task: ${taskDisplayName(t)})`);
|
|
51204
51451
|
}
|
|
@@ -51695,9 +51942,9 @@ async function runMecTaskDelete(cfg) {
|
|
|
51695
51942
|
};
|
|
51696
51943
|
await preflightConfirmToken(action, cfg.token);
|
|
51697
51944
|
await requireMec(cfg.client, { signal: cfg.signal });
|
|
51698
|
-
let
|
|
51945
|
+
let step2;
|
|
51699
51946
|
try {
|
|
51700
|
-
|
|
51947
|
+
step2 = await withMec(
|
|
51701
51948
|
() => getStep(cfg.client, cfg.processId, cfg.stepId, {
|
|
51702
51949
|
signal: cfg.signal
|
|
51703
51950
|
})
|
|
@@ -51713,11 +51960,11 @@ async function runMecTaskDelete(cfg) {
|
|
|
51713
51960
|
describe: async () => {
|
|
51714
51961
|
const lines = [
|
|
51715
51962
|
`process: ${cfg.processId}`,
|
|
51716
|
-
`step: ${cfg.stepId}${
|
|
51963
|
+
`step: ${cfg.stepId}${step2 !== void 0 ? ` ("${step2.name}")` : ""}`,
|
|
51717
51964
|
`tasks to delete: ${cfg.ids.length}`
|
|
51718
51965
|
];
|
|
51719
51966
|
const tasksById = new Map(
|
|
51720
|
-
(
|
|
51967
|
+
(step2 === void 0 ? [] : allStepTasks(step2)).map((t) => [t.id, t])
|
|
51721
51968
|
);
|
|
51722
51969
|
for (const { id } of cfg.ids) {
|
|
51723
51970
|
const found = tasksById.get(id);
|
|
@@ -52322,8 +52569,8 @@ function wireMecWorkflow(mecCmd) {
|
|
|
52322
52569
|
});
|
|
52323
52570
|
addServerFlag(procGetCmd);
|
|
52324
52571
|
addAccountFlag(procGetCmd);
|
|
52325
|
-
const
|
|
52326
|
-
const stepGetCmd =
|
|
52572
|
+
const step2 = workflow.command("step").description("MEC workflow steps");
|
|
52573
|
+
const stepGetCmd = step2.command("get").description("Show a step with embedded tasks").argument("<process-id>", "numeric process instance id").argument("<step-id>", "numeric step id").option("--json", "Output raw JSON", false).action(
|
|
52327
52574
|
async (processIdRaw, stepIdRaw, opts) => {
|
|
52328
52575
|
const processId = parsePositiveIntId(processIdRaw, "process id");
|
|
52329
52576
|
const stepId = parsePositiveIntId(stepIdRaw, "step id");
|
|
@@ -52705,7 +52952,7 @@ function wireMecWorkflow(mecCmd) {
|
|
|
52705
52952
|
});
|
|
52706
52953
|
addServerFlag(procDeleteCmd);
|
|
52707
52954
|
addAccountFlag(procDeleteCmd);
|
|
52708
|
-
const stepCreateCmd =
|
|
52955
|
+
const stepCreateCmd = step2.command("create").description("Create a new step on a MEC process instance").argument("<process-id>", "numeric process instance id").requiredOption("--file <path>", "JSON file matching the step-create shape").option("--json", "Output the created step as JSON", false).option("--confirm-token <token>", "Token from a prior plan step").action(
|
|
52709
52956
|
async (pidRaw, opts) => {
|
|
52710
52957
|
const processId = parsePositiveIntId(pidRaw, "process id");
|
|
52711
52958
|
const payload = await readStepCreatePayload(opts.file ?? "");
|
|
@@ -52729,7 +52976,7 @@ function wireMecWorkflow(mecCmd) {
|
|
|
52729
52976
|
);
|
|
52730
52977
|
addServerFlag(stepCreateCmd);
|
|
52731
52978
|
addAccountFlag(stepCreateCmd);
|
|
52732
|
-
const stepUpdateCmd =
|
|
52979
|
+
const stepUpdateCmd = step2.command("update").description("Edit a MEC step").argument("<process-id>", "numeric process instance id").argument("<step-id>", "numeric step id").requiredOption("--file <path>", "JSON file with partial step shape").option("--json", "Output the updated step as JSON", false).option("--confirm-token <token>", "Token from a prior plan step").action(
|
|
52733
52980
|
async (pidRaw, sidRaw, opts) => {
|
|
52734
52981
|
const processId = parsePositiveIntId(pidRaw, "process id");
|
|
52735
52982
|
const stepId = parsePositiveIntId(sidRaw, "step id");
|
|
@@ -52755,7 +53002,7 @@ function wireMecWorkflow(mecCmd) {
|
|
|
52755
53002
|
);
|
|
52756
53003
|
addServerFlag(stepUpdateCmd);
|
|
52757
53004
|
addAccountFlag(stepUpdateCmd);
|
|
52758
|
-
const stepDeleteCmd =
|
|
53005
|
+
const stepDeleteCmd = step2.command("delete").description("Delete a MEC step (cascades to all its tasks)").argument("<process-id>", "numeric process instance id").argument("<step-id>", "numeric step id").option("--confirm-token <token>", "Token from a prior plan step").action(
|
|
52759
53006
|
async (pidRaw, sidRaw, opts) => {
|
|
52760
53007
|
const processId = parsePositiveIntId(pidRaw, "process id");
|
|
52761
53008
|
const stepId = parsePositiveIntId(sidRaw, "step id");
|
|
@@ -52777,7 +53024,7 @@ function wireMecWorkflow(mecCmd) {
|
|
|
52777
53024
|
);
|
|
52778
53025
|
addServerFlag(stepDeleteCmd);
|
|
52779
53026
|
addAccountFlag(stepDeleteCmd);
|
|
52780
|
-
const stepReorderCmd =
|
|
53027
|
+
const stepReorderCmd = step2.command("reorder").description("Reorder steps on a MEC template").argument("<template-id>", "numeric template id").option("--file <path>", "JSON array of {id, index, y_index}").option("--order <pairs>", 'Shorthand: "id:n,id2:n2,..." (mutually exclusive with --file)').option("--confirm-token <token>", "Token from a prior plan step").action(
|
|
52781
53028
|
async (tidRaw, opts) => {
|
|
52782
53029
|
const templateId = parsePositiveIntId(tidRaw, "template id");
|
|
52783
53030
|
if ((opts.file === void 0 || opts.file === "") && (opts.order === void 0 || opts.order === "")) {
|
|
@@ -53674,16 +53921,16 @@ function renderProcessDetail(out, p) {
|
|
|
53674
53921
|
}
|
|
53675
53922
|
async function runStepGet(cfg) {
|
|
53676
53923
|
await requireWorkflowV2(cfg.client, { signal: cfg.signal });
|
|
53677
|
-
const
|
|
53924
|
+
const step2 = decodeShape(
|
|
53678
53925
|
await withWorkflowV2(
|
|
53679
53926
|
() => getStep(cfg.client, cfg.processId, cfg.stepId, { signal: cfg.signal })
|
|
53680
53927
|
)
|
|
53681
53928
|
);
|
|
53682
53929
|
if (cfg.asJson) {
|
|
53683
|
-
writeJSONIndented(cfg.out,
|
|
53930
|
+
writeJSONIndented(cfg.out, step2);
|
|
53684
53931
|
return;
|
|
53685
53932
|
}
|
|
53686
|
-
renderStepDetail(cfg.out,
|
|
53933
|
+
renderStepDetail(cfg.out, step2);
|
|
53687
53934
|
}
|
|
53688
53935
|
function renderStepDetail(out, s) {
|
|
53689
53936
|
const rows = [
|
|
@@ -53729,12 +53976,12 @@ function renderTaskTable(out, tasks, indent) {
|
|
|
53729
53976
|
}
|
|
53730
53977
|
async function runTaskList(cfg) {
|
|
53731
53978
|
await requireWorkflowV2(cfg.client, { signal: cfg.signal });
|
|
53732
|
-
const
|
|
53979
|
+
const step2 = decodeShape(
|
|
53733
53980
|
await withWorkflowV2(
|
|
53734
53981
|
() => getStep(cfg.client, cfg.processId, cfg.stepId, { signal: cfg.signal })
|
|
53735
53982
|
)
|
|
53736
53983
|
);
|
|
53737
|
-
const tasks = allStepTasks2(
|
|
53984
|
+
const tasks = allStepTasks2(step2);
|
|
53738
53985
|
if (cfg.asJson) {
|
|
53739
53986
|
writeJSONIndented(cfg.out, tasks);
|
|
53740
53987
|
return;
|
|
@@ -53750,12 +53997,12 @@ async function runTaskList(cfg) {
|
|
|
53750
53997
|
}
|
|
53751
53998
|
async function runTaskGet(cfg) {
|
|
53752
53999
|
await requireWorkflowV2(cfg.client, { signal: cfg.signal });
|
|
53753
|
-
const
|
|
54000
|
+
const step2 = decodeShape(
|
|
53754
54001
|
await withWorkflowV2(
|
|
53755
54002
|
() => getStep(cfg.client, cfg.processId, cfg.stepId, { signal: cfg.signal })
|
|
53756
54003
|
)
|
|
53757
54004
|
);
|
|
53758
|
-
const tasks = allStepTasks2(
|
|
54005
|
+
const tasks = allStepTasks2(step2);
|
|
53759
54006
|
const match = tasks.find((t) => t.id === cfg.taskId);
|
|
53760
54007
|
if (match === void 0) {
|
|
53761
54008
|
throw new Error(
|
|
@@ -54045,11 +54292,11 @@ async function collectActivationCascade(client, template, signal) {
|
|
|
54045
54292
|
return lines;
|
|
54046
54293
|
}
|
|
54047
54294
|
const steps = process2.steps ?? [];
|
|
54048
|
-
for (const
|
|
54049
|
-
if (
|
|
54050
|
-
const tasks = allStepTasks2(
|
|
54295
|
+
for (const step2 of steps) {
|
|
54296
|
+
if (step2.notify_automatically !== true) continue;
|
|
54297
|
+
const tasks = allStepTasks2(step2);
|
|
54051
54298
|
if (tasks.length === 0) continue;
|
|
54052
|
-
lines.push(` step "${
|
|
54299
|
+
lines.push(` step "${step2.name}":`);
|
|
54053
54300
|
for (const t of tasks) {
|
|
54054
54301
|
const assignee = userLabel2(t.assignee);
|
|
54055
54302
|
const taskName = taskDisplayName2(t);
|
|
@@ -54543,9 +54790,9 @@ async function runTaskDelete(cfg) {
|
|
|
54543
54790
|
};
|
|
54544
54791
|
await preflightConfirmToken(action, cfg.token);
|
|
54545
54792
|
await requireWorkflowV2(cfg.client, { signal: cfg.signal });
|
|
54546
|
-
let
|
|
54793
|
+
let step2;
|
|
54547
54794
|
try {
|
|
54548
|
-
|
|
54795
|
+
step2 = decodeShape(
|
|
54549
54796
|
await withWorkflowV2(
|
|
54550
54797
|
() => getStep(cfg.client, cfg.processId, cfg.stepId, { signal: cfg.signal })
|
|
54551
54798
|
)
|
|
@@ -54561,11 +54808,11 @@ async function runTaskDelete(cfg) {
|
|
|
54561
54808
|
describe: async () => {
|
|
54562
54809
|
const lines = [
|
|
54563
54810
|
`process: ${cfg.processId}`,
|
|
54564
|
-
`step: ${cfg.stepId}${
|
|
54811
|
+
`step: ${cfg.stepId}${step2 !== void 0 ? ` ("${step2.name}")` : ""}`,
|
|
54565
54812
|
`tasks to delete: ${cfg.ids.length}`
|
|
54566
54813
|
];
|
|
54567
54814
|
const tasksById = new Map(
|
|
54568
|
-
(
|
|
54815
|
+
(step2 === void 0 ? [] : allStepTasks2(step2)).map((t) => [t.id, t])
|
|
54569
54816
|
);
|
|
54570
54817
|
for (const { id } of cfg.ids) {
|
|
54571
54818
|
const found = tasksById.get(id);
|
|
@@ -55191,8 +55438,8 @@ function wireWorkflow(root) {
|
|
|
55191
55438
|
});
|
|
55192
55439
|
addServerFlag(processGetCmd);
|
|
55193
55440
|
addAccountFlag(processGetCmd);
|
|
55194
|
-
const
|
|
55195
|
-
const stepGetCmd =
|
|
55441
|
+
const step2 = workflow.command("step").description("Workflow steps");
|
|
55442
|
+
const stepGetCmd = step2.command("get").description("Show a step with embedded tasks (`GET /processes/v2/<pid>/step/<sid>`)").argument("<process-id>", "numeric process instance id").argument("<step-id>", "numeric step id").option("--json", "Output raw JSON", false).action(
|
|
55196
55443
|
async (processIdRaw, stepIdRaw, opts) => {
|
|
55197
55444
|
const processId = parsePositiveIntId2(processIdRaw, "process id");
|
|
55198
55445
|
const stepId = parsePositiveIntId2(stepIdRaw, "step id");
|
|
@@ -55495,7 +55742,7 @@ function wireWorkflow(root) {
|
|
|
55495
55742
|
});
|
|
55496
55743
|
addServerFlag(processDeleteCmd);
|
|
55497
55744
|
addAccountFlag(processDeleteCmd);
|
|
55498
|
-
const stepCreateCmd =
|
|
55745
|
+
const stepCreateCmd = step2.command("create").description("Create a new step on a process instance").argument("<process-id>", "numeric process instance id").requiredOption("--file <path>", "JSON file matching the step-create shape").option("--json", "Output the created step as JSON", false).option("--confirm-token <token>", "Token from a prior plan step").action(
|
|
55499
55746
|
async (pidRaw, opts) => {
|
|
55500
55747
|
const processId = parsePositiveIntId2(pidRaw, "process id");
|
|
55501
55748
|
const payload = await readStepCreatePayload(opts.file ?? "");
|
|
@@ -55519,7 +55766,7 @@ function wireWorkflow(root) {
|
|
|
55519
55766
|
);
|
|
55520
55767
|
addServerFlag(stepCreateCmd);
|
|
55521
55768
|
addAccountFlag(stepCreateCmd);
|
|
55522
|
-
const stepUpdateCmd =
|
|
55769
|
+
const stepUpdateCmd = step2.command("update").description("Edit a step").argument("<process-id>", "numeric process instance id").argument("<step-id>", "numeric step id").requiredOption("--file <path>", "JSON file with partial step shape").option("--json", "Output the updated step as JSON", false).option("--confirm-token <token>", "Token from a prior plan step").action(
|
|
55523
55770
|
async (pidRaw, sidRaw, opts) => {
|
|
55524
55771
|
const processId = parsePositiveIntId2(pidRaw, "process id");
|
|
55525
55772
|
const stepId = parsePositiveIntId2(sidRaw, "step id");
|
|
@@ -55545,7 +55792,7 @@ function wireWorkflow(root) {
|
|
|
55545
55792
|
);
|
|
55546
55793
|
addServerFlag(stepUpdateCmd);
|
|
55547
55794
|
addAccountFlag(stepUpdateCmd);
|
|
55548
|
-
const stepDeleteCmd =
|
|
55795
|
+
const stepDeleteCmd = step2.command("delete").description("Delete a step (cascades to all its tasks)").argument("<process-id>", "numeric process instance id").argument("<step-id>", "numeric step id").option("--confirm-token <token>", "Token from a prior plan step").action(
|
|
55549
55796
|
async (pidRaw, sidRaw, opts) => {
|
|
55550
55797
|
const processId = parsePositiveIntId2(pidRaw, "process id");
|
|
55551
55798
|
const stepId = parsePositiveIntId2(sidRaw, "step id");
|
|
@@ -55567,7 +55814,7 @@ function wireWorkflow(root) {
|
|
|
55567
55814
|
);
|
|
55568
55815
|
addServerFlag(stepDeleteCmd);
|
|
55569
55816
|
addAccountFlag(stepDeleteCmd);
|
|
55570
|
-
const stepReorderCmd =
|
|
55817
|
+
const stepReorderCmd = step2.command("reorder").description("Reorder steps on a template").argument("<template-id>", "numeric template id").option("--file <path>", "JSON array of {id, index, y_index}").option("--order <pairs>", 'Shorthand: "id:n,id2:n2,..." (mutually exclusive with --file)').option("--confirm-token <token>", "Token from a prior plan step").action(
|
|
55571
55818
|
async (tidRaw, opts) => {
|
|
55572
55819
|
const templateId = parsePositiveIntId2(tidRaw, "template id");
|
|
55573
55820
|
if ((opts.file === void 0 || opts.file === "") && (opts.order === void 0 || opts.order === "")) {
|
|
@@ -66253,15 +66500,15 @@ var MAX_ATTACHMENT_FILENAME_LENGTH = 500;
|
|
|
66253
66500
|
function writeManualSteps(out, steps) {
|
|
66254
66501
|
if (steps.length === 0) return;
|
|
66255
66502
|
out.write("\nManual steps:\n");
|
|
66256
|
-
for (const
|
|
66257
|
-
const mark =
|
|
66258
|
-
out.write(` [${mark}] ${
|
|
66503
|
+
for (const step2 of steps) {
|
|
66504
|
+
const mark = step2.done ? "x" : " ";
|
|
66505
|
+
out.write(` [${mark}] ${step2.n}. (${step2.done_by}) ${step2.title}
|
|
66259
66506
|
`);
|
|
66260
|
-
if (
|
|
66261
|
-
out.write(` ${
|
|
66507
|
+
if (step2.detail !== void 0 && step2.detail !== null && step2.detail !== "") {
|
|
66508
|
+
out.write(` ${step2.detail}
|
|
66262
66509
|
`);
|
|
66263
66510
|
}
|
|
66264
|
-
for (const rec of
|
|
66511
|
+
for (const rec of step2.records ?? []) {
|
|
66265
66512
|
const type = (rec.type ?? "cname").toUpperCase();
|
|
66266
66513
|
out.write(` ${type} ${rec.host ?? "?"} -> ${rec.value ?? "?"}
|
|
66267
66514
|
`);
|
|
@@ -66471,9 +66718,9 @@ function renderSmtpResponse(out, resp, asJson) {
|
|
|
66471
66718
|
writeJSONIndented(out, resp);
|
|
66472
66719
|
return;
|
|
66473
66720
|
}
|
|
66474
|
-
for (const
|
|
66475
|
-
const detail =
|
|
66476
|
-
out.write(`${
|
|
66721
|
+
for (const step2 of resp.steps) {
|
|
66722
|
+
const detail = step2.detail === void 0 || step2.detail === null || step2.detail === "" ? "" : ` - ${step2.detail}`;
|
|
66723
|
+
out.write(`${step2.status.padEnd(8, " ")}${step2.step}${detail}
|
|
66477
66724
|
`);
|
|
66478
66725
|
}
|
|
66479
66726
|
const scope = resp.team_id === null ? "org-wide" : `team ${resp.team_id}`;
|
package/dist/scopes-map.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 1,
|
|
3
|
-
"cliVersion": "1.6.
|
|
3
|
+
"cliVersion": "1.6.120",
|
|
4
4
|
"_contract": "Resolve a command path through `aliases` (canonical prefix + alias segment -> canonical path) before any lookup. A path listed in `pendingCommands`, or whose first segment is a key of `pending`, is UNDECIDED, not unrestricted: fail closed or skip it, and never read a path's absence from `commands` as 'no requirement'. An entry carrying `denied` is UNAVAILABLE to any AGENT-SCOPED credential — one whose `scopes` claim carries at least one `resource:action` entry; a claim that is absent, empty, capability-only or wholly unparseable is UNRESTRICTED, and this mark does not apply to it — whatever else that entry says: it is not a ceiling and it is not always-available, its `denied.reason` says why and `denied.until` names the ticket that lifts it, and the absence of `requires` on it must NEVER be read as 'no requirement'. Only an entry in `commands` with an empty `requires` means always-available.",
|
|
5
5
|
"commands": {
|
|
6
6
|
"login": {
|
|
@@ -2315,6 +2315,14 @@
|
|
|
2315
2315
|
}
|
|
2316
2316
|
]
|
|
2317
2317
|
},
|
|
2318
|
+
"filebox rescan-version": {
|
|
2319
|
+
"requires": [
|
|
2320
|
+
{
|
|
2321
|
+
"resource": "fileboxes",
|
|
2322
|
+
"action": "write"
|
|
2323
|
+
}
|
|
2324
|
+
]
|
|
2325
|
+
},
|
|
2318
2326
|
"widgets list": {
|
|
2319
2327
|
"requires": [
|
|
2320
2328
|
{
|
|
@@ -285,7 +285,8 @@ area's gotchas.
|
|
|
285
285
|
|
|
286
286
|
**Fileboxes & documents** → [reference/filebox-documents.md](reference/filebox-documents.md)
|
|
287
287
|
- `filebox list|get|versions|tags|sheets|preview|create|upload|upload-version|update|download` (alias `fileboxes`)
|
|
288
|
-
- `filebox archive|archive-version|restore-version|set-version-include|set-version-date-tag|set-version-label|set-version-workflow|set-version-file-status|set-version-cycle`
|
|
288
|
+
- `filebox archive|archive-version|restore-version|set-version-include|set-version-date-tag|set-version-label|set-version-workflow|set-version-file-status|set-version-cycle|rescan-version`
|
|
289
|
+
- _re-extract one version in place (UI version "Rescan"): `rescan-version <vid>` (two-step confirm; only that version, current datamappers, tags unchanged, rows replaced not doubled) — the way to redo a live version that is not the newest_
|
|
289
290
|
- _archived versions (opt-in; defaults unchanged): `versions --archived|--all` to discover them; `archive-version`/`restore-version` also take `--doc` + `--version-number <n>` or `--latest-archived`/`--latest-active`_
|
|
290
291
|
- _include in database: `versions --included` lists the versions whose `include_file` flag is on (intent, not delivered rows); `set-version-include <vid> --include on|off` writes the flag (two-step confirm both ways — off deletes the version's table rows, on queues an ETL scan). `--doc <id> --all-except-latest` is the bulk cleanup; it never targets the latest, and warns in the plan if the latest is itself excluded_
|
|
291
292
|
- `filebox share|shares|set-option|set-tag-config|set-parent|lock|unlock|lock-date-tag|unlock-date-tag|locked-date-tags`
|
|
@@ -561,7 +562,9 @@ status` again. This is a **full historical** rescan (every calc field × every
|
|
|
561
562
|
version). To only pick up a datamapper change on the live template, prefer
|
|
562
563
|
`datamappers update <id> --payload-file <p> --rescan latest` (latest version of
|
|
563
564
|
the mapper's bound documents only) — far cheaper and lower-blast. It publishes a
|
|
564
|
-
new mapper version, so the mapper gets a **new id**, which dr prints.
|
|
565
|
+
new mapper version, so the mapper gets a **new id**, which dr prints. To redo
|
|
566
|
+
**one version** (e.g. a live version that is not the newest), use `filebox
|
|
567
|
+
rescan-version <vid>` — the UI's per-version Rescan, no new mapper id.
|
|
565
568
|
|
|
566
569
|
**Build a `create` body from plain-English intent** (calc models, datamappers,
|
|
567
570
|
metrics): you resolve names → integer IDs yourself against the tenant
|
|
@@ -114,6 +114,42 @@ set-version-include` (below).
|
|
|
114
114
|
damage, then `filebox set-version-include --doc <doc> --all-except-latest
|
|
115
115
|
--include off`.
|
|
116
116
|
|
|
117
|
+
### Re-extract one version (rescan-version)
|
|
118
|
+
|
|
119
|
+
- `filebox rescan-version <vid> [--table <table_id> …] [--json]` — re-extract
|
|
120
|
+
**one** version into its tables **in place**, without changing its tags: the
|
|
121
|
+
UI's version row "three dots > Rescan". It sends the same request the UI does
|
|
122
|
+
(`POST /api/buckets/<bucket>/rescan_versions` with that one version id and the
|
|
123
|
+
filebox's tables), so the server does all the work:
|
|
124
|
+
- **Which versions:** only the one you name. The server does not widen it to
|
|
125
|
+
the other versions of the filebox or of a collection process; to redo
|
|
126
|
+
several, run it once per version. It runs with the tables' **current**
|
|
127
|
+
datamappers — no datamapper is published, no mapper gets a new id, no tag
|
|
128
|
+
changes.
|
|
129
|
+
- **Rows are replaced, not doubled:** the load deletes that version's existing
|
|
130
|
+
rows in each table before writing the new ones.
|
|
131
|
+
- **Tables:** by default every active table this filebox is mapped into —
|
|
132
|
+
the tables the server will actually re-extract into (the UI offers every
|
|
133
|
+
table of the bucket, and the server silently drops the ones this filebox
|
|
134
|
+
does not feed). `--table` (repeatable) narrows it; an id this filebox does
|
|
135
|
+
not feed is refused rather than sent and skipped.
|
|
136
|
+
- This is the way to re-extract a live version that is **not the newest** in
|
|
137
|
+
its filebox — `datamappers update|bind --rescan latest` only reach the
|
|
138
|
+
newest, and `rescan table` redoes the whole table.
|
|
139
|
+
- **Two-step confirm** (Tier B, like `rescan table`: token only): the first
|
|
140
|
+
run prints the version, its filebox and bucket, its tags, the tables, and a
|
|
141
|
+
token; re-run with `--confirm-token`. The token is bound to the version and
|
|
142
|
+
to the exact table set the plan showed: if a table starts or stops being fed
|
|
143
|
+
in between, the token no longer matches — re-run the plan. Then poll `scans
|
|
144
|
+
status <table_id>`.
|
|
145
|
+
- Refused up front, with the remedy: an **archived** version
|
|
146
|
+
(`restore-version` first) and a version **excluded from the database**
|
|
147
|
+
(`set-version-include <vid> --include on`, which queues the extraction
|
|
148
|
+
itself). The server answers `"ok"` even when it filtered everything out, so
|
|
149
|
+
the success line means "queued", not "rows written" — check `scans status`.
|
|
150
|
+
- Needs read access to the filebox; a scoped credential needs
|
|
151
|
+
`fileboxes:write`.
|
|
152
|
+
|
|
117
153
|
### Version tagging
|
|
118
154
|
|
|
119
155
|
- `filebox set-version-date-tag <vid> --doc <id> --month|--quarter|--day|--year|--week …
|
|
@@ -27,7 +27,8 @@ delete`, `devices command-delete`, `validate onboarding session delete`,
|
|
|
27
27
|
`cash hidden-rules upsert|delete`, `forecast` lock/unlock/default/delete/clone
|
|
28
28
|
verbs, `workflow`/`mec workflow` create/update/activate/delete and friends,
|
|
29
29
|
`collection-processes` create/mutate verbs, and the non-`delete` mutations
|
|
30
|
-
`templates set-field-type`, `rescan table`, `
|
|
30
|
+
`templates set-field-type`, `rescan table`, `filebox rescan-version`,
|
|
31
|
+
`features orgs add|remove`,
|
|
31
32
|
`dashboards push`, `filebox push`, and `reconciliation accounts
|
|
32
33
|
set-assignee|clear-assignee|set-due-date|sign|update-settings`. When
|
|
33
34
|
in doubt, run the command without a token and read the plan output.
|
|
@@ -82,7 +83,9 @@ stop it, so check the destination afterwards.
|
|
|
82
83
|
Everything else gated is Tier B (all `create`/`update`/`reorder`/`set-*`/`lock`/
|
|
83
84
|
`unlock` verbs, `templates set-field-type`, `rescan table` (a full historical
|
|
84
85
|
rescan — expensive/high-blast but reversible, so token-only; the plan step shows
|
|
85
|
-
the document + version counts), `
|
|
86
|
+
the document + version counts), `filebox rescan-version` (the same, for one
|
|
87
|
+
version: re-extracts it in place and replaces its rows, never deletes; the plan
|
|
88
|
+
shows the version, filebox, tags and tables), `metrics re-aggregate`, `metrics migrate` (the
|
|
86
89
|
org-wide V1→V2 backfill — deletes nothing, but **overwrites**
|
|
87
90
|
`category`/`time_aggregation` with the name-derived mapping, hand-set values
|
|
88
91
|
included; per-metric before→after is in the response `details[]`. A
|