@datarails-ai/dr-cli 1.6.113 → 1.6.115
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.115",
|
|
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-11T19:13:34.414Z";
|
|
73
73
|
function formatBuildTime(iso) {
|
|
74
74
|
if (iso === "") return "";
|
|
75
75
|
const d = new Date(iso);
|
|
@@ -3863,7 +3863,10 @@ var PROD_GATE_TIER_B = /* @__PURE__ */ new Set([
|
|
|
3863
3863
|
// org export cleanup (dr organizations export delete). Removes the export's
|
|
3864
3864
|
// server-side record + blob folder — migration ARTIFACTS only; no org data
|
|
3865
3865
|
// is touched, and the state is recoverable by re-running the export.
|
|
3866
|
-
"org-export|delete"
|
|
3866
|
+
"org-export|delete",
|
|
3867
|
+
// connectors poll item skip (dr connectors poll skip). The item is never landed,
|
|
3868
|
+
// but `dr connectors poll retry` queues it again, so the token alone is enough.
|
|
3869
|
+
"connector-poll-item|skip"
|
|
3867
3870
|
]);
|
|
3868
3871
|
var PROD_GATE_TIER_A = /* @__PURE__ */ new Set([
|
|
3869
3872
|
// workflow / mec — soft-delete + cascade deletes. `archive` also covers the
|
|
@@ -3998,7 +4001,15 @@ var PROD_GATE_TIER_A = /* @__PURE__ */ new Set([
|
|
|
3998
4001
|
// imported-org delete (dr organizations import delete-orgs) — PERMANENTLY
|
|
3999
4002
|
// deletes whole organizations via the org-delete chord. The single most
|
|
4000
4003
|
// destructive verb in the CLI; the word gate stays on prod unconditionally.
|
|
4001
|
-
"org-import|delete-orgs"
|
|
4004
|
+
"org-import|delete-orgs",
|
|
4005
|
+
// connectors polled ingestion (dr connectors poll seed / set / resume --source land).
|
|
4006
|
+
// A seed marks items landed so they never land; `set` is gated (as `set-land-or-seed`)
|
|
4007
|
+
// only when it lands a wider window or seeds / lands on a change-policy switch;
|
|
4008
|
+
// `resume --source land` lands everything a changed source holds. Versions landed in
|
|
4009
|
+
// a customer filebox, or files hidden from it, cannot be taken back from the CLI.
|
|
4010
|
+
"connector-poll|seed",
|
|
4011
|
+
"connector-poll|set-land-or-seed",
|
|
4012
|
+
"connector-poll|resume-land"
|
|
4002
4013
|
]);
|
|
4003
4014
|
function classifyTier(action) {
|
|
4004
4015
|
const key = `${action.resource}|${action.verb}`;
|
|
@@ -19023,6 +19034,14 @@ async function setVersionAutoSave(client, versionId, autoSave, reqOptions) {
|
|
|
19023
19034
|
reqOptions
|
|
19024
19035
|
);
|
|
19025
19036
|
}
|
|
19037
|
+
async function setVersionNameLabel(client, versionId, label, reqOptions) {
|
|
19038
|
+
return client.do(
|
|
19039
|
+
"PUT",
|
|
19040
|
+
`/api/documents/versions/${versionId}/name`,
|
|
19041
|
+
JSON.stringify({ label }),
|
|
19042
|
+
reqOptions
|
|
19043
|
+
);
|
|
19044
|
+
}
|
|
19026
19045
|
async function setVersionIncludeFile(client, versionId, includeFile, reqOptions) {
|
|
19027
19046
|
return client.do(
|
|
19028
19047
|
"PUT",
|
|
@@ -35947,7 +35966,10 @@ async function runFileboxVersions(cfg) {
|
|
|
35947
35966
|
writeJSONIndented(cfg.out, selected);
|
|
35948
35967
|
return;
|
|
35949
35968
|
}
|
|
35950
|
-
|
|
35969
|
+
const forTable = selected.map(
|
|
35970
|
+
(v) => typeof v.label === "string" ? { ...v, label: decodeHtmlEntitiesDeep(v.label) } : v
|
|
35971
|
+
);
|
|
35972
|
+
renderFileboxVersionsTable(cfg.out, forTable, includeArchived, wantIncluded);
|
|
35951
35973
|
}
|
|
35952
35974
|
async function runFileboxTags(cfg) {
|
|
35953
35975
|
const tags = await listTags(cfg.client, { signal: cfg.signal });
|
|
@@ -36214,6 +36236,9 @@ async function runFileboxUploadVersion(cfg) {
|
|
|
36214
36236
|
"--date and --scenario must be used together (planning fileboxes set both at once)"
|
|
36215
36237
|
);
|
|
36216
36238
|
}
|
|
36239
|
+
if (cfg.label !== void 0) {
|
|
36240
|
+
validateVersionLabel(cfg.label);
|
|
36241
|
+
}
|
|
36217
36242
|
let blob;
|
|
36218
36243
|
try {
|
|
36219
36244
|
blob = await fileToBlob(cfg.filePath);
|
|
@@ -36314,6 +36339,26 @@ async function runFileboxUploadVersion(cfg) {
|
|
|
36314
36339
|
throw new Error(confirmation.failure);
|
|
36315
36340
|
}
|
|
36316
36341
|
}
|
|
36342
|
+
let appliedLabel = null;
|
|
36343
|
+
let labelFailed = false;
|
|
36344
|
+
let labelFailure;
|
|
36345
|
+
if (cfg.label !== void 0) {
|
|
36346
|
+
if (id <= 0) {
|
|
36347
|
+
throw new Error(
|
|
36348
|
+
`uploaded, but could not read the new version id from the response to label it \u2014 set the label with \`dr filebox set-version-label\`. Server response: ${JSON.stringify(result)}`
|
|
36349
|
+
);
|
|
36350
|
+
}
|
|
36351
|
+
try {
|
|
36352
|
+
appliedLabel = await writeVersionLabel(cfg.client, id, cfg.label, cfg.signal);
|
|
36353
|
+
} catch (err) {
|
|
36354
|
+
labelFailed = true;
|
|
36355
|
+
labelFailure = err;
|
|
36356
|
+
}
|
|
36357
|
+
}
|
|
36358
|
+
const labelJSON = cfg.label === void 0 ? {} : labelFailed ? {
|
|
36359
|
+
label_error: labelFailure instanceof Error ? labelFailure.message : String(labelFailure)
|
|
36360
|
+
} : { label: appliedLabel };
|
|
36361
|
+
const errStream = cfg.err ?? process.stderr;
|
|
36317
36362
|
if (cfg.asJson) {
|
|
36318
36363
|
if (prepared !== void 0) {
|
|
36319
36364
|
writeJSONIndented(cfg.out, {
|
|
@@ -36324,11 +36369,15 @@ async function runFileboxUploadVersion(cfg) {
|
|
|
36324
36369
|
cycle_tag_id: prepared.cycleTagId,
|
|
36325
36370
|
date: prepared.cycleDate,
|
|
36326
36371
|
scenario: cfg.scenario,
|
|
36372
|
+
...labelJSON,
|
|
36327
36373
|
...cycleTagVerdictJSON(confirmation)
|
|
36328
36374
|
});
|
|
36329
|
-
|
|
36375
|
+
} else if (cfg.label !== void 0) {
|
|
36376
|
+
cfg.out.write(JSON.stringify({ ...asRecord2(result), ...labelJSON }) + "\n");
|
|
36377
|
+
} else {
|
|
36378
|
+
cfg.out.write(JSON.stringify(result) + "\n");
|
|
36330
36379
|
}
|
|
36331
|
-
|
|
36380
|
+
if (labelFailed) throw uploadLabelFailure(id, labelFailure, errStream);
|
|
36332
36381
|
return;
|
|
36333
36382
|
}
|
|
36334
36383
|
if (renamed !== null) {
|
|
@@ -36355,6 +36404,26 @@ ${JSON.stringify(result)}
|
|
|
36355
36404
|
`
|
|
36356
36405
|
);
|
|
36357
36406
|
}
|
|
36407
|
+
if (labelFailed) throw uploadLabelFailure(id, labelFailure, errStream);
|
|
36408
|
+
if (cfg.label !== void 0) {
|
|
36409
|
+
cfg.out.write(`Set label on version ${id}: ${JSON.stringify(appliedLabel)}.
|
|
36410
|
+
`);
|
|
36411
|
+
}
|
|
36412
|
+
}
|
|
36413
|
+
function uploadLabelFailure(versionId, err, errStream) {
|
|
36414
|
+
const retry = `retry with \`dr filebox set-version-label ${versionId} --label <text>\``;
|
|
36415
|
+
if (isTypedError(err)) {
|
|
36416
|
+
errStream.write(`uploaded version ${versionId}, but setting its label failed \u2014 ${retry}
|
|
36417
|
+
`);
|
|
36418
|
+
return err;
|
|
36419
|
+
}
|
|
36420
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
36421
|
+
return new Error(
|
|
36422
|
+
`uploaded version ${versionId}, but setting its label failed: ${msg} \u2014 ${retry}`,
|
|
36423
|
+
{
|
|
36424
|
+
cause: err
|
|
36425
|
+
}
|
|
36426
|
+
);
|
|
36358
36427
|
}
|
|
36359
36428
|
async function runFileboxUpdate(cfg) {
|
|
36360
36429
|
if (cfg.id <= 0) {
|
|
@@ -36903,6 +36972,12 @@ async function resolveVersionByNumber(client, docId, target, signal) {
|
|
|
36903
36972
|
}
|
|
36904
36973
|
if (target.number === void 0) {
|
|
36905
36974
|
const latest = pool.reduce((a, b) => b.version > a.version ? b : a);
|
|
36975
|
+
const tied = pool.filter((v) => v.version === latest.version);
|
|
36976
|
+
if (target.refuseTiedLatest === true && tied.length > 1) {
|
|
36977
|
+
throw new Error(
|
|
36978
|
+
`ambiguous latest: ${tied.length} ${setLabel} versions of filebox ${docId} share version number ${latest.version} (ids ${tied.map((v) => v.id).join(", ")}); pass the global version id instead`
|
|
36979
|
+
);
|
|
36980
|
+
}
|
|
36906
36981
|
return { id: latest.id, version: latest.version };
|
|
36907
36982
|
}
|
|
36908
36983
|
const matches = pool.filter((v) => v.version === target.number);
|
|
@@ -36970,6 +37045,116 @@ async function runFileboxSetVersionDateTag(cfg) {
|
|
|
36970
37045
|
const body = await res.text();
|
|
36971
37046
|
throw new Error(`set version date-tag refused (HTTP ${res.status}): ${body.trim()}`);
|
|
36972
37047
|
}
|
|
37048
|
+
var VERSION_LABEL_MAX = 256;
|
|
37049
|
+
var RESERVED_VERSION_LABEL = "auto-calculated";
|
|
37050
|
+
var CONTROL_CHARS = /[\u0000-\u001f\u007f-\u009f]/g;
|
|
37051
|
+
function validateVersionLabel(label) {
|
|
37052
|
+
if (label.trim() === "") {
|
|
37053
|
+
throw new Error("--label must not be empty \u2014 use --clear to remove a label");
|
|
37054
|
+
}
|
|
37055
|
+
if (new RegExp(CONTROL_CHARS.source).test(label)) {
|
|
37056
|
+
throw new Error("--label must not contain control characters (newlines, tabs and the like)");
|
|
37057
|
+
}
|
|
37058
|
+
if (label.trim().toLowerCase() === RESERVED_VERSION_LABEL) {
|
|
37059
|
+
throw new Error(
|
|
37060
|
+
`--label "${RESERVED_VERSION_LABEL}" is reserved: the server uses it to mark versions it generated itself, which scanning can skip and archiving can move to cold storage`
|
|
37061
|
+
);
|
|
37062
|
+
}
|
|
37063
|
+
const length = [...label].length;
|
|
37064
|
+
if (length > VERSION_LABEL_MAX) {
|
|
37065
|
+
throw new Error(`--label must be at most ${VERSION_LABEL_MAX} characters (got ${length})`);
|
|
37066
|
+
}
|
|
37067
|
+
return label;
|
|
37068
|
+
}
|
|
37069
|
+
function renderVersionLabelCell(label) {
|
|
37070
|
+
if (label === null || label === void 0) return "";
|
|
37071
|
+
return label.replace(CONTROL_CHARS, (c) => {
|
|
37072
|
+
if (c === "\n") return "\\n";
|
|
37073
|
+
if (c === "\r") return "\\r";
|
|
37074
|
+
if (c === " ") return "\\t";
|
|
37075
|
+
return `\\u${c.charCodeAt(0).toString(16).padStart(4, "0")}`;
|
|
37076
|
+
});
|
|
37077
|
+
}
|
|
37078
|
+
function parseVersionLabelFlags(label, clear) {
|
|
37079
|
+
if (label !== void 0 && clear) {
|
|
37080
|
+
throw new Error("pass either --label <text> or --clear, not both");
|
|
37081
|
+
}
|
|
37082
|
+
if (clear) return null;
|
|
37083
|
+
if (label === void 0) {
|
|
37084
|
+
throw new Error("one of --label <text> or --clear is required");
|
|
37085
|
+
}
|
|
37086
|
+
return validateVersionLabel(label);
|
|
37087
|
+
}
|
|
37088
|
+
function isTypedError(err) {
|
|
37089
|
+
return !(err instanceof Error) || err.constructor !== Error || "code" in err;
|
|
37090
|
+
}
|
|
37091
|
+
async function writeVersionLabel(client, versionId, label, signal) {
|
|
37092
|
+
const res = await setVersionNameLabel(client, versionId, label, { signal });
|
|
37093
|
+
if (res.status < 200 || res.status >= 300) {
|
|
37094
|
+
const body = (await res.text()).trim();
|
|
37095
|
+
const detail = body === "" && res.status === 405 ? "no permission \u2014 changing a version's label needs change rights on the filebox, or to be the user who uploaded the version" : body;
|
|
37096
|
+
throw new Error(
|
|
37097
|
+
`${label === null ? "clear" : "set"} version label refused (HTTP ${res.status}): ${detail}`
|
|
37098
|
+
);
|
|
37099
|
+
}
|
|
37100
|
+
let readBack;
|
|
37101
|
+
try {
|
|
37102
|
+
readBack = await getVersion(client, versionId, { signal });
|
|
37103
|
+
} catch (err) {
|
|
37104
|
+
if (isTypedError(err)) throw err;
|
|
37105
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
37106
|
+
throw new Error(`label written to version ${versionId}, but reading it back failed: ${msg}`, {
|
|
37107
|
+
cause: err
|
|
37108
|
+
});
|
|
37109
|
+
}
|
|
37110
|
+
const stored = readBack.label === null || readBack.label === void 0 ? null : decodeHtmlEntitiesDeep(readBack.label);
|
|
37111
|
+
const expected = label === null ? null : label.trim();
|
|
37112
|
+
const matches = expected === null ? stored === null || stored === "" : stored === expected;
|
|
37113
|
+
if (!matches) {
|
|
37114
|
+
throw new Error(
|
|
37115
|
+
`the server accepted the label for version ${versionId} but reports ${JSON.stringify(stored)} on read-back, not ${JSON.stringify(expected)}`
|
|
37116
|
+
);
|
|
37117
|
+
}
|
|
37118
|
+
return expected === null ? null : stored;
|
|
37119
|
+
}
|
|
37120
|
+
async function runFileboxSetVersionLabel(cfg) {
|
|
37121
|
+
if (cfg.versionId <= 0) {
|
|
37122
|
+
throw new Error("version id must be positive");
|
|
37123
|
+
}
|
|
37124
|
+
let current;
|
|
37125
|
+
try {
|
|
37126
|
+
current = decodeHtmlEntitiesDeep(
|
|
37127
|
+
await getVersion(cfg.client, cfg.versionId, { signal: cfg.signal })
|
|
37128
|
+
);
|
|
37129
|
+
} catch (err) {
|
|
37130
|
+
if (isTypedError(err)) throw err;
|
|
37131
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
37132
|
+
if (/HTTP 404\b/.test(msg)) {
|
|
37133
|
+
throw new Error(
|
|
37134
|
+
`version ${cfg.versionId} not found \u2014 label not changed (find the id with \`dr filebox versions <doc_id>\`)`,
|
|
37135
|
+
{ cause: err }
|
|
37136
|
+
);
|
|
37137
|
+
}
|
|
37138
|
+
throw new Error(`load version ${cfg.versionId}: ${msg} \u2014 label not changed`, { cause: err });
|
|
37139
|
+
}
|
|
37140
|
+
const stored = await writeVersionLabel(cfg.client, cfg.versionId, cfg.label, cfg.signal);
|
|
37141
|
+
if (cfg.asJson) {
|
|
37142
|
+
writeJSONIndented(cfg.out, {
|
|
37143
|
+
version_id: cfg.versionId,
|
|
37144
|
+
doc_id: current.document,
|
|
37145
|
+
version: current.version,
|
|
37146
|
+
label: stored,
|
|
37147
|
+
previous_label: current.label ?? null
|
|
37148
|
+
});
|
|
37149
|
+
return;
|
|
37150
|
+
}
|
|
37151
|
+
const target = versionLabel(cfg.versionId, current.version);
|
|
37152
|
+
cfg.out.write(
|
|
37153
|
+
stored === null ? `Cleared label on ${target}.
|
|
37154
|
+
` : `Set label on ${target}: ${JSON.stringify(stored)}.
|
|
37155
|
+
`
|
|
37156
|
+
);
|
|
37157
|
+
}
|
|
36973
37158
|
var WORKFLOW_STATUSES = [
|
|
36974
37159
|
"Not Started",
|
|
36975
37160
|
"In Progress",
|
|
@@ -38248,7 +38433,7 @@ function renderFileboxVersionsTable(out, versions, showArchived = false, showInc
|
|
|
38248
38433
|
out.write("(no versions)\n");
|
|
38249
38434
|
return;
|
|
38250
38435
|
}
|
|
38251
|
-
const header = ["VERSION_ID", "VERSION", "NAME", "STATUS", "DOC_ID", "CREATED"];
|
|
38436
|
+
const header = ["VERSION_ID", "VERSION", "NAME", "LABEL", "STATUS", "DOC_ID", "CREATED"];
|
|
38252
38437
|
if (showArchived) header.push("ARCHIVED");
|
|
38253
38438
|
if (showIncluded) header.push("INCLUDED");
|
|
38254
38439
|
const rows = [{ cells: header }];
|
|
@@ -38257,6 +38442,7 @@ function renderFileboxVersionsTable(out, versions, showArchived = false, showInc
|
|
|
38257
38442
|
String(v.id),
|
|
38258
38443
|
String(v.version),
|
|
38259
38444
|
v.name,
|
|
38445
|
+
renderVersionLabelCell(v.label),
|
|
38260
38446
|
v.status,
|
|
38261
38447
|
String(v.document),
|
|
38262
38448
|
renderCreateTime(v.create_time)
|
|
@@ -38527,6 +38713,9 @@ function registerFileboxCommand(root) {
|
|
|
38527
38713
|
"--scenario <name>",
|
|
38528
38714
|
"Forecast/budget filebox: scenario/cycle name (must already exist). Use with --date."
|
|
38529
38715
|
).option("--date-tag-name <name>", "Date tag to use when the filebox has more than one DATE tag").option(
|
|
38716
|
+
"--label <text>",
|
|
38717
|
+
"Label the new version right after the upload (same as `set-version-label --label`)"
|
|
38718
|
+
).option(
|
|
38530
38719
|
"--no-reconcile",
|
|
38531
38720
|
`Upload under the file's literal name without correcting its extension to the byte content. Use only when you intend a wrong-but-deliberate name; the server may then reject it with HTTP 400 "Invalid file signature".`
|
|
38532
38721
|
).option("--json", "Output raw JSON instead of a summary", false).action(
|
|
@@ -38543,6 +38732,7 @@ function registerFileboxCommand(root) {
|
|
|
38543
38732
|
...opts.date !== void 0 ? { dateInput: opts.date } : {},
|
|
38544
38733
|
...opts.scenario !== void 0 ? { scenario: opts.scenario } : {},
|
|
38545
38734
|
...opts.dateTagName !== void 0 ? { dateTagName: opts.dateTagName } : {},
|
|
38735
|
+
...opts.label !== void 0 ? { label: opts.label } : {},
|
|
38546
38736
|
reconcile: opts.reconcile !== false,
|
|
38547
38737
|
asJson: opts.json === true,
|
|
38548
38738
|
signal: setup.signal,
|
|
@@ -38881,6 +39071,46 @@ function registerFileboxCommand(root) {
|
|
|
38881
39071
|
);
|
|
38882
39072
|
addServerFlag(setVersionDateTagCmd);
|
|
38883
39073
|
addAccountFlag(setVersionDateTagCmd);
|
|
39074
|
+
const setVersionLabelCmd = fb.command("set-version-label").description(
|
|
39075
|
+
"Set or clear a filebox version's label (date and dimension tags are left unchanged). Address it by global version id, or by --doc with --version-number/--latest-active."
|
|
39076
|
+
).argument(
|
|
39077
|
+
"[version_id]",
|
|
39078
|
+
"document version id (global). Omit to address by --doc + --version-number/--latest-active."
|
|
39079
|
+
).option("--label <text>", "the new label (at most 256 characters)").option("--clear", "remove the label", false).option("--doc <doc_id>", "filebox id \u2014 resolve the version within this filebox").option("--version-number <n>", "per-filebox version number to label (requires --doc)").option("--latest-active", "label the latest active version of --doc (requires --doc)", false).option(
|
|
39080
|
+
"--json",
|
|
39081
|
+
"Output a JSON record (version_id, doc_id, version, label, previous_label)",
|
|
39082
|
+
false
|
|
39083
|
+
).action(
|
|
39084
|
+
async (idStr, opts) => {
|
|
39085
|
+
const label = parseVersionLabelFlags(opts.label, opts.clear === true);
|
|
39086
|
+
const addressing = parseVersionAddressing(
|
|
39087
|
+
idStr,
|
|
39088
|
+
{ doc: opts.doc, versionNumber: opts.versionNumber, latest: opts.latestActive },
|
|
39089
|
+
"--latest-active"
|
|
39090
|
+
);
|
|
39091
|
+
const setup = await setupCall(opts.server, opts.account);
|
|
39092
|
+
try {
|
|
39093
|
+
const versionId = addressing.mode === "direct" ? addressing.versionId : (await resolveVersionByNumber(
|
|
39094
|
+
setup.client,
|
|
39095
|
+
addressing.docId,
|
|
39096
|
+
{ number: addressing.number, from: "active", refuseTiedLatest: true },
|
|
39097
|
+
setup.signal
|
|
39098
|
+
)).id;
|
|
39099
|
+
await runFileboxSetVersionLabel({
|
|
39100
|
+
client: setup.client,
|
|
39101
|
+
versionId,
|
|
39102
|
+
label,
|
|
39103
|
+
asJson: opts.json === true,
|
|
39104
|
+
signal: setup.signal,
|
|
39105
|
+
out: process.stdout
|
|
39106
|
+
});
|
|
39107
|
+
} finally {
|
|
39108
|
+
setup.cleanup();
|
|
39109
|
+
}
|
|
39110
|
+
}
|
|
39111
|
+
);
|
|
39112
|
+
addServerFlag(setVersionLabelCmd);
|
|
39113
|
+
addAccountFlag(setVersionLabelCmd);
|
|
38884
39114
|
const setVersionWorkflowCmd = fb.command("set-version-workflow").description(
|
|
38885
39115
|
"Set the WORKFLOW tag value on a single document version (Approve / Reject / move to In Progress / etc.)"
|
|
38886
39116
|
).argument("<version_id>", "document version id (positive integer)").requiredOption(
|
|
@@ -40928,6 +41158,82 @@ async function cancelSync(client, fileboxUuid, target = {}, reqOptions) {
|
|
|
40928
41158
|
}
|
|
40929
41159
|
return out;
|
|
40930
41160
|
}
|
|
41161
|
+
async function getPoll(client, queryId, reqOptions) {
|
|
41162
|
+
const path12 = `/connector-queries/${queryId}/poll`;
|
|
41163
|
+
let out;
|
|
41164
|
+
try {
|
|
41165
|
+
out = await client.getJSON(path12, reqOptions);
|
|
41166
|
+
} catch (err) {
|
|
41167
|
+
throw toControlPlaneError("GET", path12, err);
|
|
41168
|
+
}
|
|
41169
|
+
if (out === null) {
|
|
41170
|
+
throw new Error(`GET ${path12}: empty response from control-plane poll get`);
|
|
41171
|
+
}
|
|
41172
|
+
return out;
|
|
41173
|
+
}
|
|
41174
|
+
async function putPoll(client, queryId, fields, reqOptions) {
|
|
41175
|
+
const path12 = `/connector-queries/${queryId}/poll`;
|
|
41176
|
+
let out;
|
|
41177
|
+
try {
|
|
41178
|
+
out = await client.putJSON(path12, fields, reqOptions);
|
|
41179
|
+
} catch (err) {
|
|
41180
|
+
throw toControlPlaneError("PUT", path12, err);
|
|
41181
|
+
}
|
|
41182
|
+
if (out === null) {
|
|
41183
|
+
throw new Error(`PUT ${path12}: empty response from control-plane poll set`);
|
|
41184
|
+
}
|
|
41185
|
+
return out;
|
|
41186
|
+
}
|
|
41187
|
+
async function postPollJSON(client, path12, body, what, reqOptions) {
|
|
41188
|
+
let out;
|
|
41189
|
+
try {
|
|
41190
|
+
out = await client.postJSON(path12, body, reqOptions);
|
|
41191
|
+
} catch (err) {
|
|
41192
|
+
throw toControlPlaneError("POST", path12, err);
|
|
41193
|
+
}
|
|
41194
|
+
if (out === null) {
|
|
41195
|
+
throw new Error(`POST ${path12}: empty response from control-plane ${what}`);
|
|
41196
|
+
}
|
|
41197
|
+
return out;
|
|
41198
|
+
}
|
|
41199
|
+
async function runPoll(client, queryId, reqOptions) {
|
|
41200
|
+
const path12 = `/connector-queries/${queryId}/poll/run`;
|
|
41201
|
+
return postPollJSON(client, path12, {}, "poll run", reqOptions);
|
|
41202
|
+
}
|
|
41203
|
+
async function seedPoll(client, queryId, body, reqOptions) {
|
|
41204
|
+
const path12 = `/connector-queries/${queryId}/poll/seed`;
|
|
41205
|
+
return postPollJSON(client, path12, body, "poll seed", reqOptions);
|
|
41206
|
+
}
|
|
41207
|
+
async function resumePoll(client, queryId, body, reqOptions) {
|
|
41208
|
+
const path12 = `/connector-queries/${queryId}/poll/resume`;
|
|
41209
|
+
return postPollJSON(client, path12, body, "poll resume", reqOptions);
|
|
41210
|
+
}
|
|
41211
|
+
async function listPollItems(client, queryId, query = {}, reqOptions) {
|
|
41212
|
+
const params = new URLSearchParams();
|
|
41213
|
+
if (query.state !== void 0) params.set("state", query.state);
|
|
41214
|
+
if (query.limit !== void 0) params.set("limit", String(query.limit));
|
|
41215
|
+
if (query.after !== void 0) params.set("after", String(query.after));
|
|
41216
|
+
const suffix = params.toString() === "" ? "" : `?${params.toString()}`;
|
|
41217
|
+
const path12 = `/connector-queries/${queryId}/poll/items${suffix}`;
|
|
41218
|
+
let out;
|
|
41219
|
+
try {
|
|
41220
|
+
out = await client.getJSON(path12, reqOptions);
|
|
41221
|
+
} catch (err) {
|
|
41222
|
+
throw toControlPlaneError("GET", path12, err);
|
|
41223
|
+
}
|
|
41224
|
+
if (out === null) {
|
|
41225
|
+
throw new Error(`GET ${path12}: empty response from control-plane poll items`);
|
|
41226
|
+
}
|
|
41227
|
+
return out;
|
|
41228
|
+
}
|
|
41229
|
+
async function retryPollItem(client, queryId, itemId, reqOptions) {
|
|
41230
|
+
const path12 = `/connector-queries/${queryId}/poll/items/${itemId}/retry`;
|
|
41231
|
+
return postPollJSON(client, path12, {}, "poll item retry", reqOptions);
|
|
41232
|
+
}
|
|
41233
|
+
async function skipPollItem(client, queryId, itemId, reqOptions) {
|
|
41234
|
+
const path12 = `/connector-queries/${queryId}/poll/items/${itemId}/skip`;
|
|
41235
|
+
return postPollJSON(client, path12, {}, "poll item skip", reqOptions);
|
|
41236
|
+
}
|
|
40931
41237
|
function toControlPlaneError(method, path12, err) {
|
|
40932
41238
|
const msg = err instanceof Error ? err.message : String(err);
|
|
40933
41239
|
const m = /HTTP (\d{3})(?::\s*([\s\S]*))?$/.exec(msg);
|
|
@@ -41157,6 +41463,962 @@ function registerDevFetch(connectors) {
|
|
|
41157
41463
|
);
|
|
41158
41464
|
}
|
|
41159
41465
|
|
|
41466
|
+
// src/commands/connectorsPoll.ts
|
|
41467
|
+
import * as readline2 from "readline";
|
|
41468
|
+
import { createHash as createHash10 } from "crypto";
|
|
41469
|
+
|
|
41470
|
+
// src/types/connectors.ts
|
|
41471
|
+
var POLL_ITEM_STATES = [
|
|
41472
|
+
"seen",
|
|
41473
|
+
"new",
|
|
41474
|
+
"dispatched",
|
|
41475
|
+
"running",
|
|
41476
|
+
"retry_wait",
|
|
41477
|
+
"landed",
|
|
41478
|
+
"failed",
|
|
41479
|
+
"skipped",
|
|
41480
|
+
"seeded",
|
|
41481
|
+
"superseded"
|
|
41482
|
+
];
|
|
41483
|
+
|
|
41484
|
+
// src/commands/connectorsPoll.ts
|
|
41485
|
+
var DURATION_UNIT_SECONDS = { s: 1, m: 60, h: 3600, d: 86400 };
|
|
41486
|
+
var DURATION_BOUNDS = {
|
|
41487
|
+
"--interval": [300, 7 * 86400],
|
|
41488
|
+
"--settle": [0, 86400]
|
|
41489
|
+
};
|
|
41490
|
+
var LOOKBACK_MAX_DAYS = 3650;
|
|
41491
|
+
function parseDurationSeconds(raw, flag) {
|
|
41492
|
+
const m = /^(\d+)([smhd])?$/.exec(raw.trim());
|
|
41493
|
+
const seconds = m === null ? NaN : Number(m[1]) * (DURATION_UNIT_SECONDS[m[2] ?? "s"] ?? 1);
|
|
41494
|
+
const [min, max] = DURATION_BOUNDS[flag] ?? [0, Number.MAX_SAFE_INTEGER];
|
|
41495
|
+
if (m === null) {
|
|
41496
|
+
throw new Error(`invalid ${flag} "${raw}": expected a duration like 90s, 5m or 1h`);
|
|
41497
|
+
}
|
|
41498
|
+
if (!Number.isSafeInteger(seconds) || seconds < min || seconds > max) {
|
|
41499
|
+
throw new Error(
|
|
41500
|
+
`invalid ${flag} "${raw}": must be between ${formatSeconds(min)} and ${formatSeconds(max)}`
|
|
41501
|
+
);
|
|
41502
|
+
}
|
|
41503
|
+
return seconds;
|
|
41504
|
+
}
|
|
41505
|
+
function parseLookbackDays(raw) {
|
|
41506
|
+
const m = /^(\d+)d?$/.exec(raw.trim());
|
|
41507
|
+
const days = m === null ? 0 : Number(m[1]);
|
|
41508
|
+
if (days < 1 || days > LOOKBACK_MAX_DAYS) {
|
|
41509
|
+
throw new Error(
|
|
41510
|
+
`invalid --lookback "${raw}": must be between 1 and ${LOOKBACK_MAX_DAYS} days, e.g. 180d`
|
|
41511
|
+
);
|
|
41512
|
+
}
|
|
41513
|
+
return days;
|
|
41514
|
+
}
|
|
41515
|
+
var DATE_ONLY_RE = /^(\d{4})-(\d{2})-(\d{2})$/;
|
|
41516
|
+
var DATE_TIME_RE = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2})(?::(\d{2})(?:\.\d+)?)?(?:Z|[+-](\d{2}):(\d{2}))$/;
|
|
41517
|
+
function inRange(value, max, min = 0) {
|
|
41518
|
+
const n = Number(value ?? "0");
|
|
41519
|
+
return n >= min && n <= max;
|
|
41520
|
+
}
|
|
41521
|
+
function isCalendarDay(y, m, d) {
|
|
41522
|
+
if (!inRange(m, 12, 1)) return false;
|
|
41523
|
+
const daysInMonth3 = new Date(Date.UTC(Number(y), Number(m), 0)).getUTCDate();
|
|
41524
|
+
return inRange(d, daysInMonth3, 1);
|
|
41525
|
+
}
|
|
41526
|
+
function parseTimestampFlag(raw, flag) {
|
|
41527
|
+
const invalid = new Error(
|
|
41528
|
+
`invalid ${flag} "${raw}": expected YYYY-MM-DD or a timestamp with a zone (e.g. 2026-10-08T17:30:00+03:00)`
|
|
41529
|
+
);
|
|
41530
|
+
const value = raw.trim();
|
|
41531
|
+
const dateOnly = DATE_ONLY_RE.exec(value);
|
|
41532
|
+
if (dateOnly !== null) {
|
|
41533
|
+
if (!isCalendarDay(dateOnly[1], dateOnly[2], dateOnly[3])) throw invalid;
|
|
41534
|
+
return (/* @__PURE__ */ new Date(`${value}T00:00:00Z`)).toISOString();
|
|
41535
|
+
}
|
|
41536
|
+
const dt = DATE_TIME_RE.exec(value);
|
|
41537
|
+
const valid = dt !== null && isCalendarDay(dt[1], dt[2], dt[3]) && inRange(dt[4], 23) && inRange(dt[5], 59) && inRange(dt[6], 59) && inRange(dt[7], 23) && inRange(dt[8], 59);
|
|
41538
|
+
const ms = valid ? Date.parse(value) : NaN;
|
|
41539
|
+
if (Number.isNaN(ms)) throw invalid;
|
|
41540
|
+
return new Date(ms).toISOString();
|
|
41541
|
+
}
|
|
41542
|
+
function parseSameName(raw) {
|
|
41543
|
+
if (raw === "new-version") return "new_version";
|
|
41544
|
+
if (raw === "ignore") return "ignore";
|
|
41545
|
+
throw new Error(`--same-name must be new-version or ignore (got "${raw}")`);
|
|
41546
|
+
}
|
|
41547
|
+
function parseChoice(raw, flag, choices) {
|
|
41548
|
+
const match = choices.find((c) => c === raw);
|
|
41549
|
+
if (match === void 0) {
|
|
41550
|
+
throw new Error(`${flag} must be ${choices.join(" or ")} (got "${raw}")`);
|
|
41551
|
+
}
|
|
41552
|
+
return match;
|
|
41553
|
+
}
|
|
41554
|
+
var WIDEN_CHOICES = ["seed", "land"];
|
|
41555
|
+
var POLICY_CHOICES = ["rekey", "seed", "land"];
|
|
41556
|
+
function parseSettings(opts) {
|
|
41557
|
+
const fields = {};
|
|
41558
|
+
if (opts.interval !== void 0) {
|
|
41559
|
+
fields.interval_seconds = parseDurationSeconds(opts.interval, "--interval");
|
|
41560
|
+
}
|
|
41561
|
+
if (opts.since !== void 0) fields.since = parseTimestampFlag(opts.since, "--since");
|
|
41562
|
+
if (opts.lookback !== void 0) fields.lookback_days = parseLookbackDays(opts.lookback);
|
|
41563
|
+
if (opts.settle !== void 0) {
|
|
41564
|
+
fields.settle_seconds = parseDurationSeconds(opts.settle, "--settle");
|
|
41565
|
+
}
|
|
41566
|
+
if (opts.sameName !== void 0) fields.change_policy = parseSameName(opts.sameName);
|
|
41567
|
+
return fields;
|
|
41568
|
+
}
|
|
41569
|
+
function settingsArgs(opts) {
|
|
41570
|
+
const pairs = [
|
|
41571
|
+
["--interval", opts.interval],
|
|
41572
|
+
["--since", opts.since],
|
|
41573
|
+
["--lookback", opts.lookback],
|
|
41574
|
+
["--settle", opts.settle],
|
|
41575
|
+
["--same-name", opts.sameName]
|
|
41576
|
+
];
|
|
41577
|
+
return pairs.filter((p) => p[1] !== void 0).map(([flag, value]) => ` ${flag} ${value.trim()}`).join("");
|
|
41578
|
+
}
|
|
41579
|
+
async function resolvePollBinding(client, filebox, signal) {
|
|
41580
|
+
const wanted = filebox.trim();
|
|
41581
|
+
const byId = /^\d+$/.test(wanted);
|
|
41582
|
+
const rows = await listQueries(client, { signal });
|
|
41583
|
+
const matches = rows.filter(
|
|
41584
|
+
(q) => byId ? q.filebox_id === Number(wanted) : q.filebox_uuid.toLowerCase() === wanted.toLowerCase()
|
|
41585
|
+
);
|
|
41586
|
+
const [first] = matches;
|
|
41587
|
+
if (first === void 0) {
|
|
41588
|
+
throw new Error(
|
|
41589
|
+
`no connector binding for filebox ${wanted} in this org (see dr connectors query list)`
|
|
41590
|
+
);
|
|
41591
|
+
}
|
|
41592
|
+
if (matches.length > 1) {
|
|
41593
|
+
const ids = matches.map((q) => `#${q.query_id}`).join(", ");
|
|
41594
|
+
throw new Error(`filebox ${wanted} has several connector bindings (${ids})`);
|
|
41595
|
+
}
|
|
41596
|
+
return first;
|
|
41597
|
+
}
|
|
41598
|
+
function isNotPolled(err) {
|
|
41599
|
+
return err instanceof ControlPlaneError && err.status === 404 && err.body.includes("not polled");
|
|
41600
|
+
}
|
|
41601
|
+
function isPollThrottled(err) {
|
|
41602
|
+
return err instanceof ControlPlaneError && err.status === 409 && (err.body.includes("discover is in flight") || err.body.includes("polled less than"));
|
|
41603
|
+
}
|
|
41604
|
+
async function explainNotPolled(filebox, call) {
|
|
41605
|
+
try {
|
|
41606
|
+
return await call;
|
|
41607
|
+
} catch (err) {
|
|
41608
|
+
if (isNotPolled(err)) {
|
|
41609
|
+
throw new Error(
|
|
41610
|
+
`filebox ${filebox} is not set to polled ingestion; run dr connectors poll enable ${filebox}`,
|
|
41611
|
+
{ cause: err }
|
|
41612
|
+
);
|
|
41613
|
+
}
|
|
41614
|
+
throw err;
|
|
41615
|
+
}
|
|
41616
|
+
}
|
|
41617
|
+
async function readFileboxDateTag(monolith, fileboxId, signal) {
|
|
41618
|
+
const details = await getDetails(monolith, fileboxId, { signal });
|
|
41619
|
+
const dateTags = (details.tags_config ?? []).filter((t) => t.type === "DATE");
|
|
41620
|
+
const [only] = dateTags;
|
|
41621
|
+
if (only === void 0) return {};
|
|
41622
|
+
if (dateTags.length > 1) {
|
|
41623
|
+
const names = dateTags.map((t) => t.name).join(", ");
|
|
41624
|
+
throw new Error(
|
|
41625
|
+
`filebox ${fileboxId} has several DATE tags (${names}); a polled filebox needs exactly one`
|
|
41626
|
+
);
|
|
41627
|
+
}
|
|
41628
|
+
return { id: only.id, name: only.name };
|
|
41629
|
+
}
|
|
41630
|
+
function formatSeconds(sec) {
|
|
41631
|
+
if (sec > 0 && sec % 86400 === 0) return `${sec / 86400}d`;
|
|
41632
|
+
if (sec > 0 && sec % 3600 === 0) return `${sec / 3600}h`;
|
|
41633
|
+
if (sec > 0 && sec % 60 === 0) return `${sec / 60}m`;
|
|
41634
|
+
return `${sec}s`;
|
|
41635
|
+
}
|
|
41636
|
+
function oneLine3(s) {
|
|
41637
|
+
return s.replace(/\s+/g, " ").trim();
|
|
41638
|
+
}
|
|
41639
|
+
function sameNameLabel(policy) {
|
|
41640
|
+
return policy === "new_version" ? "new-version" : String(policy);
|
|
41641
|
+
}
|
|
41642
|
+
function formatDateTag(tag) {
|
|
41643
|
+
if (tag?.id === void 0) return "none (undated filebox)";
|
|
41644
|
+
return `${tag.name ?? "?"} (id ${tag.id})`;
|
|
41645
|
+
}
|
|
41646
|
+
function bindingTarget(binding) {
|
|
41647
|
+
return `filebox ${binding.filebox_uuid} (query #${binding.query_id})`;
|
|
41648
|
+
}
|
|
41649
|
+
function renderPoll(out, headline, binding, p) {
|
|
41650
|
+
const row = (label, value) => {
|
|
41651
|
+
out.write(` ${`${label}:`.padEnd(15)}${value}
|
|
41652
|
+
`);
|
|
41653
|
+
};
|
|
41654
|
+
const status2 = `${p.enabled ? "enabled" : "disabled"}${p.paused_reason === null ? "" : `, paused: ${oneLine3(p.paused_reason)}`}`;
|
|
41655
|
+
const counts = Object.entries(p.counts).sort(([a], [b]) => a.localeCompare(b)).map(([state, n]) => `${state}=${n}`).join(" ");
|
|
41656
|
+
out.write(`${headline} for ${bindingTarget(binding)}
|
|
41657
|
+
`);
|
|
41658
|
+
row("Status", status2);
|
|
41659
|
+
row("Interval", formatSeconds(p.interval_seconds));
|
|
41660
|
+
row("Date tag", formatDateTag(p.date_tag));
|
|
41661
|
+
row("Since", p.since ?? "-");
|
|
41662
|
+
row("Lookback", `${p.lookback_days}d`);
|
|
41663
|
+
row("Settle", formatSeconds(p.settle_seconds));
|
|
41664
|
+
row("Same name", sameNameLabel(p.change_policy));
|
|
41665
|
+
row("Max attempts", String(p.max_attempts));
|
|
41666
|
+
row("Last poll", `${p.last_poll_at ?? "-"} ${oneLine3(p.last_poll_status ?? "")}`.trimEnd());
|
|
41667
|
+
row("Next poll", p.next_poll_at);
|
|
41668
|
+
row("Failures", String(p.consecutive_failures));
|
|
41669
|
+
row("Discover", p.discover_in_flight ? `in flight since ${p.discover_sent_at ?? "?"}` : "-");
|
|
41670
|
+
row("Last digest", p.last_digest ?? "-");
|
|
41671
|
+
row("Pending seed", p.poll_run_seed_until ?? "-");
|
|
41672
|
+
row(
|
|
41673
|
+
"Pending rekey",
|
|
41674
|
+
p.poll_run_rekey_to === null ? "-" : `to ${sameNameLabel(p.poll_run_rekey_to)}`
|
|
41675
|
+
);
|
|
41676
|
+
row("Items", counts === "" ? "(none)" : counts);
|
|
41677
|
+
}
|
|
41678
|
+
function writeTable26(out, rows) {
|
|
41679
|
+
const widths = [];
|
|
41680
|
+
for (const r of rows) {
|
|
41681
|
+
r.forEach((cell, i) => {
|
|
41682
|
+
widths[i] = Math.max(widths[i] ?? 0, cell.length);
|
|
41683
|
+
});
|
|
41684
|
+
}
|
|
41685
|
+
for (const r of rows) {
|
|
41686
|
+
const cells = r.map(
|
|
41687
|
+
(cell, i) => i === r.length - 1 ? cell : cell.padEnd((widths[i] ?? 0) + 2)
|
|
41688
|
+
);
|
|
41689
|
+
out.write(`${cells.join("").trimEnd()}
|
|
41690
|
+
`);
|
|
41691
|
+
}
|
|
41692
|
+
}
|
|
41693
|
+
function renderItemTable(out, items) {
|
|
41694
|
+
const rows = [["ID", "LABEL", "DATE", "STATE", "ATTEMPTS", "VERSION", "ERROR"]];
|
|
41695
|
+
for (const it of items) {
|
|
41696
|
+
const error = it.last_error ?? (it.skip_reason === null ? null : `skipped: ${it.skip_reason}`);
|
|
41697
|
+
rows.push([
|
|
41698
|
+
String(it.id),
|
|
41699
|
+
oneLine3(it.label),
|
|
41700
|
+
it.item_date ?? "-",
|
|
41701
|
+
it.state,
|
|
41702
|
+
String(it.attempts),
|
|
41703
|
+
it.version_id === null ? "-" : String(it.version_id),
|
|
41704
|
+
error === null ? "-" : truncate3(oneLine3(error), 80)
|
|
41705
|
+
]);
|
|
41706
|
+
}
|
|
41707
|
+
writeTable26(out, rows);
|
|
41708
|
+
}
|
|
41709
|
+
async function runPollEnable(cfg) {
|
|
41710
|
+
const binding = await resolvePollBinding(cfg.client, cfg.filebox, cfg.signal);
|
|
41711
|
+
let existing;
|
|
41712
|
+
try {
|
|
41713
|
+
existing = await getPoll(cfg.client, binding.query_id, { signal: cfg.signal });
|
|
41714
|
+
} catch (err) {
|
|
41715
|
+
if (!isNotPolled(err)) throw err;
|
|
41716
|
+
existing = null;
|
|
41717
|
+
}
|
|
41718
|
+
const s = cfg.settings;
|
|
41719
|
+
if (existing !== null && (s.since !== void 0 || s.lookback_days !== void 0 || s.change_policy !== void 0)) {
|
|
41720
|
+
throw new Error(
|
|
41721
|
+
`filebox ${cfg.filebox} is already polled; change --since, --lookback or --same-name with dr connectors poll set ${cfg.filebox}, which asks what to do with a wider window or a policy switch`
|
|
41722
|
+
);
|
|
41723
|
+
}
|
|
41724
|
+
if (binding.filebox_id <= 0) {
|
|
41725
|
+
throw new Error(
|
|
41726
|
+
`connector-query #${binding.query_id} has no filebox id recorded, so its date tag cannot be read; record it with dr connectors query repoint ${binding.query_id} --filebox-id <id>`
|
|
41727
|
+
);
|
|
41728
|
+
}
|
|
41729
|
+
const dateTag = await readFileboxDateTag(cfg.monolith, binding.filebox_id, cfg.signal);
|
|
41730
|
+
const stored = await putPoll(
|
|
41731
|
+
cfg.client,
|
|
41732
|
+
binding.query_id,
|
|
41733
|
+
{ enabled: true, date_tag: dateTag, ...s },
|
|
41734
|
+
{ signal: cfg.signal }
|
|
41735
|
+
);
|
|
41736
|
+
if (cfg.asJson) {
|
|
41737
|
+
writeJSONIndented(cfg.out, stored);
|
|
41738
|
+
return;
|
|
41739
|
+
}
|
|
41740
|
+
renderPoll(cfg.out, "Polling enabled", binding, stored);
|
|
41741
|
+
}
|
|
41742
|
+
function windowStart(since, lookbackDays, now) {
|
|
41743
|
+
const start = now - lookbackDays * 864e5;
|
|
41744
|
+
return since === null ? start : Math.max(start, Date.parse(since));
|
|
41745
|
+
}
|
|
41746
|
+
function widening(current, changes, now) {
|
|
41747
|
+
if (changes.since === void 0 && changes.lookback_days === void 0) return null;
|
|
41748
|
+
const from = windowStart(current.since, current.lookback_days, now);
|
|
41749
|
+
const to = windowStart(
|
|
41750
|
+
changes.since ?? current.since,
|
|
41751
|
+
changes.lookback_days ?? current.lookback_days,
|
|
41752
|
+
now
|
|
41753
|
+
);
|
|
41754
|
+
if (to >= from) return null;
|
|
41755
|
+
return { from: new Date(from).toISOString(), to: new Date(to).toISOString() };
|
|
41756
|
+
}
|
|
41757
|
+
async function ask(cfg, message, choices, defaultChoice) {
|
|
41758
|
+
const answer = await cfg.prompt(message, choices, defaultChoice);
|
|
41759
|
+
if (answer === null) throw new Error("poll set cancelled; nothing was changed");
|
|
41760
|
+
return parseChoice(answer, "the answer", choices);
|
|
41761
|
+
}
|
|
41762
|
+
var WIDEN_HELP = "seed = mark the newly exposed items as already landed, land = land them all";
|
|
41763
|
+
var POLICY_HELP = "rekey = re-key the ledger from a fresh listing (nothing lands again), seed = mark everything in the window as landed, land = land everything in the window";
|
|
41764
|
+
async function runPollSet(cfg) {
|
|
41765
|
+
if (Object.keys(cfg.changes).length === 0) {
|
|
41766
|
+
throw new Error(
|
|
41767
|
+
"poll set: pass at least one of --interval, --since, --lookback, --settle, --same-name"
|
|
41768
|
+
);
|
|
41769
|
+
}
|
|
41770
|
+
const binding = await resolvePollBinding(cfg.client, cfg.filebox, cfg.signal);
|
|
41771
|
+
const current = await explainNotPolled(
|
|
41772
|
+
cfg.filebox,
|
|
41773
|
+
getPoll(cfg.client, binding.query_id, { signal: cfg.signal })
|
|
41774
|
+
);
|
|
41775
|
+
const body = { ...cfg.changes };
|
|
41776
|
+
const detail = [`target: ${bindingTarget(binding)}`];
|
|
41777
|
+
const wider = widening(current, cfg.changes, cfg.now ?? Date.now());
|
|
41778
|
+
if (wider !== null) {
|
|
41779
|
+
const what = `the polling window widens (start ${wider.from} -> ${wider.to})`;
|
|
41780
|
+
if (cfg.widen === void 0 && !cfg.interactive) {
|
|
41781
|
+
throw new Error(`${what}; pass --widen seed or --widen land (${WIDEN_HELP})`);
|
|
41782
|
+
}
|
|
41783
|
+
body.widen = cfg.widen ?? await ask(cfg, `${what}. ${WIDEN_HELP}.`, WIDEN_CHOICES);
|
|
41784
|
+
detail.push(`window: start ${wider.from} -> ${wider.to}, widen ${body.widen}`);
|
|
41785
|
+
} else if (cfg.widen !== void 0) {
|
|
41786
|
+
body.widen = cfg.widen;
|
|
41787
|
+
}
|
|
41788
|
+
const newPolicy = cfg.changes.change_policy;
|
|
41789
|
+
const policySwitch = newPolicy !== void 0 && newPolicy !== current.change_policy;
|
|
41790
|
+
if (policySwitch) {
|
|
41791
|
+
const change = `${sameNameLabel(current.change_policy)} -> ${sameNameLabel(newPolicy)}`;
|
|
41792
|
+
const what = `--same-name changes ${change}`;
|
|
41793
|
+
if (cfg.onPolicyChange === void 0 && !cfg.interactive) {
|
|
41794
|
+
throw new Error(`${what}; pass --on-policy-change rekey, seed or land (${POLICY_HELP})`);
|
|
41795
|
+
}
|
|
41796
|
+
body.on_policy_change = cfg.onPolicyChange ?? await ask(cfg, `${what}. ${POLICY_HELP}.`, POLICY_CHOICES, "rekey");
|
|
41797
|
+
detail.push(`same name: ${change}, on policy change ${body.on_policy_change}`);
|
|
41798
|
+
} else if (cfg.onPolicyChange !== void 0) {
|
|
41799
|
+
body.on_policy_change = cfg.onPolicyChange;
|
|
41800
|
+
}
|
|
41801
|
+
const put = async () => {
|
|
41802
|
+
const stored = await putPoll(cfg.client, binding.query_id, body, {
|
|
41803
|
+
signal: cfg.signal
|
|
41804
|
+
});
|
|
41805
|
+
if (cfg.asJson) {
|
|
41806
|
+
writeJSONIndented(cfg.out, stored);
|
|
41807
|
+
return;
|
|
41808
|
+
}
|
|
41809
|
+
renderPoll(cfg.out, "Polling settings updated", binding, stored);
|
|
41810
|
+
};
|
|
41811
|
+
const landsOrHides = wider !== null && body.widen === "land" || policySwitch && (body.on_policy_change === "seed" || body.on_policy_change === "land");
|
|
41812
|
+
if (!landsOrHides) {
|
|
41813
|
+
await put();
|
|
41814
|
+
return;
|
|
41815
|
+
}
|
|
41816
|
+
const flags = `${body.widen === void 0 ? "" : ` --widen ${body.widen}`}${body.on_policy_change === void 0 ? "" : ` --on-policy-change ${body.on_policy_change}`}`;
|
|
41817
|
+
cfg.deadline?.pause();
|
|
41818
|
+
await twoStepConfirm({
|
|
41819
|
+
out: cfg.out,
|
|
41820
|
+
action: pollConfirmAction(cfg.filebox, "set-land-or-seed", cfg.scope, { ...body }),
|
|
41821
|
+
token: cfg.token,
|
|
41822
|
+
server: cfg.scope.serverKey,
|
|
41823
|
+
confirmCmd: `dr connectors poll set ${cfg.filebox}${cfg.settingsArgs}${flags}${cfg.targetArgs}`,
|
|
41824
|
+
describe: async () => detail,
|
|
41825
|
+
execute: async () => {
|
|
41826
|
+
cfg.deadline?.resume();
|
|
41827
|
+
await put();
|
|
41828
|
+
}
|
|
41829
|
+
});
|
|
41830
|
+
}
|
|
41831
|
+
function confirmDigest(scope, payload) {
|
|
41832
|
+
const canonical = JSON.stringify({
|
|
41833
|
+
server: scope.serverKey,
|
|
41834
|
+
account: scope.account ?? "",
|
|
41835
|
+
controlPlane: scope.controlPlane,
|
|
41836
|
+
payload: Object.fromEntries(Object.entries(payload).sort(([a], [b]) => a.localeCompare(b)))
|
|
41837
|
+
});
|
|
41838
|
+
return createHash10("sha256").update(canonical).digest("hex").slice(0, 12);
|
|
41839
|
+
}
|
|
41840
|
+
function pollConfirmAction(filebox, verb, scope, payload = {}) {
|
|
41841
|
+
return {
|
|
41842
|
+
resource: "connector-poll",
|
|
41843
|
+
id: `${filebox.trim()}#${confirmDigest(scope, payload)}`,
|
|
41844
|
+
verb
|
|
41845
|
+
};
|
|
41846
|
+
}
|
|
41847
|
+
function pollItemConfirmAction(filebox, item, scope) {
|
|
41848
|
+
return {
|
|
41849
|
+
resource: "connector-poll-item",
|
|
41850
|
+
id: `${filebox.trim()}/${item}#${confirmDigest(scope, {})}`,
|
|
41851
|
+
verb: "skip"
|
|
41852
|
+
};
|
|
41853
|
+
}
|
|
41854
|
+
async function runPollDisable(cfg) {
|
|
41855
|
+
const binding = await resolvePollBinding(cfg.client, cfg.filebox, cfg.signal);
|
|
41856
|
+
await explainNotPolled(
|
|
41857
|
+
cfg.filebox,
|
|
41858
|
+
getPoll(cfg.client, binding.query_id, { signal: cfg.signal })
|
|
41859
|
+
);
|
|
41860
|
+
const stored = await putPoll(
|
|
41861
|
+
cfg.client,
|
|
41862
|
+
binding.query_id,
|
|
41863
|
+
{ enabled: false },
|
|
41864
|
+
{ signal: cfg.signal }
|
|
41865
|
+
);
|
|
41866
|
+
if (cfg.asJson) {
|
|
41867
|
+
writeJSONIndented(cfg.out, stored);
|
|
41868
|
+
return;
|
|
41869
|
+
}
|
|
41870
|
+
renderPoll(cfg.out, "Polling disabled", binding, stored);
|
|
41871
|
+
}
|
|
41872
|
+
async function runPollGet(cfg) {
|
|
41873
|
+
const binding = await resolvePollBinding(cfg.client, cfg.filebox, cfg.signal);
|
|
41874
|
+
const p = await explainNotPolled(
|
|
41875
|
+
cfg.filebox,
|
|
41876
|
+
getPoll(cfg.client, binding.query_id, { signal: cfg.signal })
|
|
41877
|
+
);
|
|
41878
|
+
if (cfg.asJson) {
|
|
41879
|
+
writeJSONIndented(cfg.out, p);
|
|
41880
|
+
return;
|
|
41881
|
+
}
|
|
41882
|
+
renderPoll(cfg.out, "Polling", binding, p);
|
|
41883
|
+
}
|
|
41884
|
+
async function runPollRun(cfg) {
|
|
41885
|
+
const binding = await resolvePollBinding(cfg.client, cfg.filebox, cfg.signal);
|
|
41886
|
+
let p;
|
|
41887
|
+
try {
|
|
41888
|
+
p = await explainNotPolled(
|
|
41889
|
+
cfg.filebox,
|
|
41890
|
+
runPoll(cfg.client, binding.query_id, { signal: cfg.signal })
|
|
41891
|
+
);
|
|
41892
|
+
} catch (err) {
|
|
41893
|
+
if (isPollThrottled(err)) {
|
|
41894
|
+
throw new Error(
|
|
41895
|
+
`a poll of filebox ${cfg.filebox} is running or ran less than a minute ago; try again shortly`,
|
|
41896
|
+
{ cause: err }
|
|
41897
|
+
);
|
|
41898
|
+
}
|
|
41899
|
+
throw err;
|
|
41900
|
+
}
|
|
41901
|
+
if (cfg.asJson) {
|
|
41902
|
+
writeJSONIndented(cfg.out, p);
|
|
41903
|
+
return;
|
|
41904
|
+
}
|
|
41905
|
+
renderPoll(cfg.out, "Poll requested", binding, p);
|
|
41906
|
+
}
|
|
41907
|
+
async function runPollResume(cfg) {
|
|
41908
|
+
const binding = await resolvePollBinding(cfg.client, cfg.filebox, cfg.signal);
|
|
41909
|
+
const resume = async () => {
|
|
41910
|
+
const p = await explainNotPolled(
|
|
41911
|
+
cfg.filebox,
|
|
41912
|
+
resumePoll(
|
|
41913
|
+
cfg.client,
|
|
41914
|
+
binding.query_id,
|
|
41915
|
+
cfg.source === void 0 ? {} : { source: cfg.source },
|
|
41916
|
+
{ signal: cfg.signal }
|
|
41917
|
+
)
|
|
41918
|
+
);
|
|
41919
|
+
if (cfg.asJson) {
|
|
41920
|
+
writeJSONIndented(cfg.out, p);
|
|
41921
|
+
return;
|
|
41922
|
+
}
|
|
41923
|
+
renderPoll(cfg.out, "Polling resumed", binding, p);
|
|
41924
|
+
};
|
|
41925
|
+
if (cfg.source !== "land") {
|
|
41926
|
+
await resume();
|
|
41927
|
+
return;
|
|
41928
|
+
}
|
|
41929
|
+
cfg.deadline?.pause();
|
|
41930
|
+
await twoStepConfirm({
|
|
41931
|
+
out: cfg.out,
|
|
41932
|
+
action: pollConfirmAction(cfg.filebox, "resume-land", cfg.scope),
|
|
41933
|
+
token: cfg.token,
|
|
41934
|
+
server: cfg.scope.serverKey,
|
|
41935
|
+
confirmCmd: `dr connectors poll resume ${cfg.filebox} --source land${cfg.targetArgs}`,
|
|
41936
|
+
describe: async () => [
|
|
41937
|
+
`target: ${bindingTarget(binding)}`,
|
|
41938
|
+
"source: land every item the changed source holds now"
|
|
41939
|
+
],
|
|
41940
|
+
execute: async () => {
|
|
41941
|
+
cfg.deadline?.resume();
|
|
41942
|
+
await resume();
|
|
41943
|
+
}
|
|
41944
|
+
});
|
|
41945
|
+
}
|
|
41946
|
+
async function countSeedable(cfg, binding) {
|
|
41947
|
+
const untilMs = Date.parse(cfg.until);
|
|
41948
|
+
let count = 0;
|
|
41949
|
+
for (const state of ["seen", "new"]) {
|
|
41950
|
+
let after = null;
|
|
41951
|
+
do {
|
|
41952
|
+
cfg.deadline?.resume();
|
|
41953
|
+
const page = await explainNotPolled(
|
|
41954
|
+
cfg.filebox,
|
|
41955
|
+
listPollItems(
|
|
41956
|
+
cfg.client,
|
|
41957
|
+
binding.query_id,
|
|
41958
|
+
{ state, ...after === null ? {} : { after } },
|
|
41959
|
+
{ signal: cfg.signal }
|
|
41960
|
+
)
|
|
41961
|
+
);
|
|
41962
|
+
count += page.items.filter(
|
|
41963
|
+
(it) => it.source_modified_at !== null && Date.parse(it.source_modified_at) <= untilMs
|
|
41964
|
+
).length;
|
|
41965
|
+
after = page.next_after;
|
|
41966
|
+
} while (after !== null);
|
|
41967
|
+
}
|
|
41968
|
+
return count;
|
|
41969
|
+
}
|
|
41970
|
+
async function runPollSeed(cfg) {
|
|
41971
|
+
const binding = await resolvePollBinding(cfg.client, cfg.filebox, cfg.signal);
|
|
41972
|
+
if (cfg.dryRun) {
|
|
41973
|
+
const wouldSeed = await countSeedable(cfg, binding);
|
|
41974
|
+
if (cfg.asJson) {
|
|
41975
|
+
writeJSONIndented(cfg.out, { dry_run: true, until: cfg.until, would_seed: wouldSeed });
|
|
41976
|
+
return;
|
|
41977
|
+
}
|
|
41978
|
+
cfg.out.write(`Seed dry run for ${bindingTarget(binding)}: nothing was changed.
|
|
41979
|
+
`);
|
|
41980
|
+
cfg.out.write(
|
|
41981
|
+
`${wouldSeed} already-discovered items would be seeded (items not yet discovered are not counted).
|
|
41982
|
+
`
|
|
41983
|
+
);
|
|
41984
|
+
return;
|
|
41985
|
+
}
|
|
41986
|
+
cfg.deadline?.pause();
|
|
41987
|
+
await twoStepConfirm({
|
|
41988
|
+
out: cfg.out,
|
|
41989
|
+
action: pollConfirmAction(cfg.filebox, "seed", cfg.scope, { until: cfg.until }),
|
|
41990
|
+
token: cfg.token,
|
|
41991
|
+
server: cfg.scope.serverKey,
|
|
41992
|
+
confirmCmd: `dr connectors poll seed ${cfg.filebox} --until ${cfg.untilArg}${cfg.targetArgs}`,
|
|
41993
|
+
describe: async () => [
|
|
41994
|
+
`target: ${bindingTarget(binding)}`,
|
|
41995
|
+
`until: ${cfg.until}`,
|
|
41996
|
+
"effect: items modified at or before it are marked landed and never land"
|
|
41997
|
+
],
|
|
41998
|
+
execute: async () => {
|
|
41999
|
+
cfg.deadline?.resume();
|
|
42000
|
+
const p = await explainNotPolled(
|
|
42001
|
+
cfg.filebox,
|
|
42002
|
+
seedPoll(
|
|
42003
|
+
cfg.client,
|
|
42004
|
+
binding.query_id,
|
|
42005
|
+
{ until: cfg.until },
|
|
42006
|
+
{
|
|
42007
|
+
signal: cfg.signal
|
|
42008
|
+
}
|
|
42009
|
+
)
|
|
42010
|
+
);
|
|
42011
|
+
if (cfg.asJson) {
|
|
42012
|
+
writeJSONIndented(cfg.out, p);
|
|
42013
|
+
return;
|
|
42014
|
+
}
|
|
42015
|
+
renderPoll(cfg.out, "Seed requested", binding, p);
|
|
42016
|
+
}
|
|
42017
|
+
});
|
|
42018
|
+
}
|
|
42019
|
+
async function runPollItems(cfg) {
|
|
42020
|
+
const binding = await resolvePollBinding(cfg.client, cfg.filebox, cfg.signal);
|
|
42021
|
+
const page = await explainNotPolled(
|
|
42022
|
+
cfg.filebox,
|
|
42023
|
+
listPollItems(
|
|
42024
|
+
cfg.client,
|
|
42025
|
+
binding.query_id,
|
|
42026
|
+
{
|
|
42027
|
+
...cfg.state !== void 0 ? { state: cfg.state } : {},
|
|
42028
|
+
...cfg.limit !== void 0 ? { limit: cfg.limit } : {},
|
|
42029
|
+
...cfg.after !== void 0 ? { after: cfg.after } : {}
|
|
42030
|
+
},
|
|
42031
|
+
{ signal: cfg.signal }
|
|
42032
|
+
)
|
|
42033
|
+
);
|
|
42034
|
+
if (cfg.asJson) {
|
|
42035
|
+
writeJSONIndented(cfg.out, page);
|
|
42036
|
+
return;
|
|
42037
|
+
}
|
|
42038
|
+
if (page.items.length === 0) {
|
|
42039
|
+
cfg.out.write(`No items${cfg.state === void 0 ? "" : ` in state ${cfg.state}`}.
|
|
42040
|
+
`);
|
|
42041
|
+
return;
|
|
42042
|
+
}
|
|
42043
|
+
renderItemTable(cfg.out, page.items);
|
|
42044
|
+
if (page.next_after !== null) {
|
|
42045
|
+
const state = cfg.state === void 0 ? "" : ` --state ${cfg.state}`;
|
|
42046
|
+
const limit = cfg.limit === void 0 ? "" : ` --limit ${cfg.limit}`;
|
|
42047
|
+
cfg.out.write(
|
|
42048
|
+
`
|
|
42049
|
+
More: dr connectors poll items ${cfg.filebox}${state}${limit} --after ${page.next_after}
|
|
42050
|
+
`
|
|
42051
|
+
);
|
|
42052
|
+
}
|
|
42053
|
+
}
|
|
42054
|
+
function renderItemResult(cfg, binding, headline, item) {
|
|
42055
|
+
if (cfg.asJson) {
|
|
42056
|
+
writeJSONIndented(cfg.out, item);
|
|
42057
|
+
return;
|
|
42058
|
+
}
|
|
42059
|
+
cfg.out.write(`${headline} (${bindingTarget(binding)})
|
|
42060
|
+
`);
|
|
42061
|
+
renderItemTable(cfg.out, [item]);
|
|
42062
|
+
}
|
|
42063
|
+
async function runPollRetry(cfg) {
|
|
42064
|
+
const binding = await resolvePollBinding(cfg.client, cfg.filebox, cfg.signal);
|
|
42065
|
+
const item = await explainNotPolled(
|
|
42066
|
+
cfg.filebox,
|
|
42067
|
+
retryPollItem(cfg.client, binding.query_id, cfg.itemId, { signal: cfg.signal })
|
|
42068
|
+
);
|
|
42069
|
+
renderItemResult(cfg, binding, `Item ${cfg.itemId} queued for retry`, item);
|
|
42070
|
+
}
|
|
42071
|
+
async function runPollSkip(cfg) {
|
|
42072
|
+
const binding = await resolvePollBinding(cfg.client, cfg.filebox, cfg.signal);
|
|
42073
|
+
cfg.deadline?.pause();
|
|
42074
|
+
await twoStepConfirm({
|
|
42075
|
+
out: cfg.out,
|
|
42076
|
+
action: pollItemConfirmAction(cfg.filebox, cfg.itemId, cfg.scope),
|
|
42077
|
+
token: cfg.token,
|
|
42078
|
+
server: cfg.scope.serverKey,
|
|
42079
|
+
confirmCmd: `dr connectors poll skip ${cfg.filebox} ${cfg.itemId}${cfg.targetArgs}`,
|
|
42080
|
+
describe: async () => [
|
|
42081
|
+
`item: ${cfg.itemId} of ${bindingTarget(binding)}`,
|
|
42082
|
+
"effect: the item is never landed (dr connectors poll retry queues it again)"
|
|
42083
|
+
],
|
|
42084
|
+
execute: async () => {
|
|
42085
|
+
cfg.deadline?.resume();
|
|
42086
|
+
const item = await explainNotPolled(
|
|
42087
|
+
cfg.filebox,
|
|
42088
|
+
skipPollItem(cfg.client, binding.query_id, cfg.itemId, {
|
|
42089
|
+
signal: cfg.signal
|
|
42090
|
+
})
|
|
42091
|
+
);
|
|
42092
|
+
renderItemResult(cfg, binding, `Item ${cfg.itemId} skipped`, item);
|
|
42093
|
+
}
|
|
42094
|
+
});
|
|
42095
|
+
}
|
|
42096
|
+
async function withMonolith(opts, action) {
|
|
42097
|
+
const monolithHost = resolve(resolveServer(opts.server)).host;
|
|
42098
|
+
const setup = await setupCall(opts.server, opts.account, {
|
|
42099
|
+
host: monolithHost,
|
|
42100
|
+
authHost: monolithHost
|
|
42101
|
+
});
|
|
42102
|
+
try {
|
|
42103
|
+
await action(setup.client);
|
|
42104
|
+
} finally {
|
|
42105
|
+
setup.cleanup();
|
|
42106
|
+
}
|
|
42107
|
+
}
|
|
42108
|
+
function scopeOf(opts) {
|
|
42109
|
+
const serverKey = resolveServer(opts.server);
|
|
42110
|
+
return {
|
|
42111
|
+
serverKey,
|
|
42112
|
+
account: normaliseAccount(opts.account),
|
|
42113
|
+
controlPlane: resolveConnectorsUrl(serverKey, opts.connectorsUrl)
|
|
42114
|
+
};
|
|
42115
|
+
}
|
|
42116
|
+
function targetArgsOf(opts) {
|
|
42117
|
+
const url = (opts.connectorsUrl ?? "").trim();
|
|
42118
|
+
return ` --server ${resolveServer(opts.server)}${url === "" ? "" : ` --connectors-url ${url}`}`;
|
|
42119
|
+
}
|
|
42120
|
+
function addCommonFlags(cmd, jsonHelp) {
|
|
42121
|
+
cmd.option("--json", jsonHelp, false);
|
|
42122
|
+
addServerFlag(cmd);
|
|
42123
|
+
addAccountFlag(cmd);
|
|
42124
|
+
addConnectorsUrlFlag(cmd);
|
|
42125
|
+
}
|
|
42126
|
+
function addConfirmTokenFlag(cmd) {
|
|
42127
|
+
return cmd.option("--confirm-token <token>", "Token from a prior plan run \u2014 required to proceed");
|
|
42128
|
+
}
|
|
42129
|
+
function addSettingsFlags(cmd) {
|
|
42130
|
+
return cmd.option("--interval <duration>", "how often to poll, 5m to 7d (default: per source)").option("--since <date>", "never pick up items modified before this date or timestamp").option("--lookback <days>", "window every poll lists, 1d to 3650d (default: per source)").option("--settle <duration>", "how long an item must stay unchanged before landing, 0s to 1d").option(
|
|
42131
|
+
"--same-name <policy>",
|
|
42132
|
+
"a changed file under the same name: new-version (lands again) or ignore"
|
|
42133
|
+
);
|
|
42134
|
+
}
|
|
42135
|
+
function ttyChoicePrompt(message, choices, defaultChoice, io = { input: process.stdin, output: process.stderr }) {
|
|
42136
|
+
return new Promise((resolvePrompt) => {
|
|
42137
|
+
const rl = readline2.createInterface({
|
|
42138
|
+
input: io.input,
|
|
42139
|
+
output: io.output,
|
|
42140
|
+
...io.terminal !== void 0 ? { terminal: io.terminal } : {}
|
|
42141
|
+
});
|
|
42142
|
+
let settled = false;
|
|
42143
|
+
const settle = (value) => {
|
|
42144
|
+
if (settled) return;
|
|
42145
|
+
settled = true;
|
|
42146
|
+
rl.close();
|
|
42147
|
+
resolvePrompt(value);
|
|
42148
|
+
};
|
|
42149
|
+
rl.on("SIGINT", () => settle(null));
|
|
42150
|
+
rl.on("close", () => settle(null));
|
|
42151
|
+
io.output.write(`${message}
|
|
42152
|
+
`);
|
|
42153
|
+
const question = defaultChoice === void 0 ? `[${choices.join("/")}]: ` : `[${choices.join("/")}] (Enter = ${defaultChoice}): `;
|
|
42154
|
+
const askOnce = () => {
|
|
42155
|
+
rl.question(question, (answer) => {
|
|
42156
|
+
const picked = answer.trim().toLowerCase();
|
|
42157
|
+
if (picked === "" && defaultChoice !== void 0) {
|
|
42158
|
+
settle(defaultChoice);
|
|
42159
|
+
} else if (choices.includes(picked)) {
|
|
42160
|
+
settle(picked);
|
|
42161
|
+
} else {
|
|
42162
|
+
io.output.write(`Answer one of: ${choices.join(", ")}
|
|
42163
|
+
`);
|
|
42164
|
+
askOnce();
|
|
42165
|
+
}
|
|
42166
|
+
});
|
|
42167
|
+
};
|
|
42168
|
+
askOnce();
|
|
42169
|
+
});
|
|
42170
|
+
}
|
|
42171
|
+
function registerConnectorsPoll(connectors) {
|
|
42172
|
+
const poll2 = connectors.command("poll").description("Polled file ingestion: the control-plane lands each new file as one version");
|
|
42173
|
+
const enableCmd = addSettingsFlags(
|
|
42174
|
+
poll2.command("enable").description("Poll a filebox's binding (dated with the filebox's DATE tag)").argument("<filebox>", "filebox id or uuid")
|
|
42175
|
+
).action(async (filebox, opts) => {
|
|
42176
|
+
const settings = parseSettings(opts);
|
|
42177
|
+
await withConnectorsSetup(opts, async ({ client, signal }) => {
|
|
42178
|
+
await withMonolith(opts, async (monolith) => {
|
|
42179
|
+
await runPollEnable({
|
|
42180
|
+
client,
|
|
42181
|
+
monolith,
|
|
42182
|
+
filebox,
|
|
42183
|
+
settings,
|
|
42184
|
+
asJson: opts.json === true,
|
|
42185
|
+
signal,
|
|
42186
|
+
out: process.stdout
|
|
42187
|
+
});
|
|
42188
|
+
});
|
|
42189
|
+
});
|
|
42190
|
+
});
|
|
42191
|
+
addCommonFlags(enableCmd, "Output the stored binding as JSON");
|
|
42192
|
+
const setCmd = addConfirmTokenFlag(
|
|
42193
|
+
addSettingsFlags(
|
|
42194
|
+
poll2.command("set").description("Change polling settings (only the given flags change)").argument("<filebox>", "filebox id or uuid")
|
|
42195
|
+
).option(
|
|
42196
|
+
"--widen <seed|land>",
|
|
42197
|
+
"a wider window: seed (mark exposed items landed) or land them"
|
|
42198
|
+
).option("--on-policy-change <rekey|seed|land>", "a --same-name switch: rekey, seed or land")
|
|
42199
|
+
).action(
|
|
42200
|
+
async (filebox, opts) => {
|
|
42201
|
+
const changes = parseSettings(opts);
|
|
42202
|
+
const widen = opts.widen === void 0 ? void 0 : parseChoice(opts.widen, "--widen", WIDEN_CHOICES);
|
|
42203
|
+
const onPolicyChange = opts.onPolicyChange === void 0 ? void 0 : parseChoice(opts.onPolicyChange, "--on-policy-change", POLICY_CHOICES);
|
|
42204
|
+
await preflightConfirmToken(
|
|
42205
|
+
pollConfirmAction(filebox, "set-land-or-seed", scopeOf(opts), {
|
|
42206
|
+
...changes,
|
|
42207
|
+
...widen !== void 0 ? { widen } : {},
|
|
42208
|
+
...onPolicyChange !== void 0 ? { on_policy_change: onPolicyChange } : {}
|
|
42209
|
+
}),
|
|
42210
|
+
opts.confirmToken
|
|
42211
|
+
);
|
|
42212
|
+
await withConnectorsSetup(opts, async (setup) => {
|
|
42213
|
+
const deadline = {
|
|
42214
|
+
pause: () => setup.pauseTimeout(),
|
|
42215
|
+
resume: () => setup.extendTimeout(DEFAULT_CALL_TIMEOUT_MS)
|
|
42216
|
+
};
|
|
42217
|
+
await runPollSet({
|
|
42218
|
+
client: setup.client,
|
|
42219
|
+
filebox,
|
|
42220
|
+
changes,
|
|
42221
|
+
settingsArgs: settingsArgs(opts),
|
|
42222
|
+
...widen !== void 0 ? { widen } : {},
|
|
42223
|
+
...onPolicyChange !== void 0 ? { onPolicyChange } : {},
|
|
42224
|
+
interactive: process.stdin.isTTY === true && process.stderr.isTTY === true,
|
|
42225
|
+
prompt: async (message, choices, defaultChoice) => {
|
|
42226
|
+
deadline.pause();
|
|
42227
|
+
try {
|
|
42228
|
+
return await ttyChoicePrompt(message, choices, defaultChoice);
|
|
42229
|
+
} finally {
|
|
42230
|
+
deadline.resume();
|
|
42231
|
+
}
|
|
42232
|
+
},
|
|
42233
|
+
deadline,
|
|
42234
|
+
...opts.confirmToken !== void 0 ? { token: opts.confirmToken } : {},
|
|
42235
|
+
scope: scopeOf(opts),
|
|
42236
|
+
targetArgs: targetArgsOf(opts),
|
|
42237
|
+
asJson: opts.json === true,
|
|
42238
|
+
signal: setup.signal,
|
|
42239
|
+
out: process.stdout
|
|
42240
|
+
});
|
|
42241
|
+
});
|
|
42242
|
+
}
|
|
42243
|
+
);
|
|
42244
|
+
addCommonFlags(setCmd, "Output the stored binding as JSON");
|
|
42245
|
+
const disableCmd = poll2.command("disable").description("Stop polling (an item already in flight still finishes)").argument("<filebox>", "filebox id or uuid").action(async (filebox, opts) => {
|
|
42246
|
+
await withConnectorsSetup(opts, async ({ client, signal }) => {
|
|
42247
|
+
await runPollDisable({
|
|
42248
|
+
client,
|
|
42249
|
+
filebox,
|
|
42250
|
+
asJson: opts.json === true,
|
|
42251
|
+
signal,
|
|
42252
|
+
out: process.stdout
|
|
42253
|
+
});
|
|
42254
|
+
});
|
|
42255
|
+
});
|
|
42256
|
+
addCommonFlags(disableCmd, "Output the stored binding as JSON");
|
|
42257
|
+
const getCmd = poll2.command("get").description("Show polling settings, last poll, pending seed / rekey and item counts").argument("<filebox>", "filebox id or uuid").action(async (filebox, opts) => {
|
|
42258
|
+
await withConnectorsSetup(opts, async ({ client, signal }) => {
|
|
42259
|
+
await runPollGet({
|
|
42260
|
+
client,
|
|
42261
|
+
filebox,
|
|
42262
|
+
asJson: opts.json === true,
|
|
42263
|
+
signal,
|
|
42264
|
+
out: process.stdout
|
|
42265
|
+
});
|
|
42266
|
+
});
|
|
42267
|
+
});
|
|
42268
|
+
addCommonFlags(getCmd, "Output the raw binding as JSON");
|
|
42269
|
+
const runCmd = poll2.command("run").description("Poll now").argument("<filebox>", "filebox id or uuid").action(async (filebox, opts) => {
|
|
42270
|
+
await withConnectorsSetup(opts, async ({ client, signal }) => {
|
|
42271
|
+
await runPollRun({
|
|
42272
|
+
client,
|
|
42273
|
+
filebox,
|
|
42274
|
+
asJson: opts.json === true,
|
|
42275
|
+
signal,
|
|
42276
|
+
out: process.stdout
|
|
42277
|
+
});
|
|
42278
|
+
});
|
|
42279
|
+
});
|
|
42280
|
+
addCommonFlags(runCmd, "Output the binding as JSON");
|
|
42281
|
+
const resumeCmd = addConfirmTokenFlag(
|
|
42282
|
+
poll2.command("resume").description("Resume a paused binding (after fixing credentials, or a source change)").argument("<filebox>", "filebox id or uuid").option(
|
|
42283
|
+
"--source <seed|land>",
|
|
42284
|
+
"after a source change: seed (mark present items landed) or land them"
|
|
42285
|
+
)
|
|
42286
|
+
).action(async (filebox, opts) => {
|
|
42287
|
+
const source = opts.source === void 0 ? void 0 : parseChoice(opts.source, "--source", WIDEN_CHOICES);
|
|
42288
|
+
if (source === "land") {
|
|
42289
|
+
await preflightConfirmToken(
|
|
42290
|
+
pollConfirmAction(filebox, "resume-land", scopeOf(opts)),
|
|
42291
|
+
opts.confirmToken
|
|
42292
|
+
);
|
|
42293
|
+
}
|
|
42294
|
+
await withConnectorsSetup(opts, async (setup) => {
|
|
42295
|
+
await runPollResume({
|
|
42296
|
+
client: setup.client,
|
|
42297
|
+
filebox,
|
|
42298
|
+
...source !== void 0 ? { source } : {},
|
|
42299
|
+
deadline: {
|
|
42300
|
+
pause: () => setup.pauseTimeout(),
|
|
42301
|
+
resume: () => setup.extendTimeout(DEFAULT_CALL_TIMEOUT_MS)
|
|
42302
|
+
},
|
|
42303
|
+
...opts.confirmToken !== void 0 ? { token: opts.confirmToken } : {},
|
|
42304
|
+
scope: scopeOf(opts),
|
|
42305
|
+
targetArgs: targetArgsOf(opts),
|
|
42306
|
+
asJson: opts.json === true,
|
|
42307
|
+
signal: setup.signal,
|
|
42308
|
+
out: process.stdout
|
|
42309
|
+
});
|
|
42310
|
+
});
|
|
42311
|
+
});
|
|
42312
|
+
addCommonFlags(resumeCmd, "Output the binding as JSON");
|
|
42313
|
+
const itemsCmd = poll2.command("items").description("List the item ledger: label, date, state, attempts, version, error").argument("<filebox>", "filebox id or uuid").option("--state <state>", `only items in this state (${POLL_ITEM_STATES.join("|")})`).option("--limit <n>", "page size (default and maximum: the control-plane page size, 100)").option("--after <id>", "start after this item id (the next-page cursor)").action(
|
|
42314
|
+
async (filebox, opts) => {
|
|
42315
|
+
const state = opts.state === void 0 ? void 0 : POLL_ITEM_STATES.find((s) => s === opts.state);
|
|
42316
|
+
if (opts.state !== void 0 && state === void 0) {
|
|
42317
|
+
throw new Error(
|
|
42318
|
+
`invalid --state "${opts.state}": expected one of ${POLL_ITEM_STATES.join(", ")}`
|
|
42319
|
+
);
|
|
42320
|
+
}
|
|
42321
|
+
const limit = opts.limit === void 0 ? void 0 : parsePositiveIntArg2(opts.limit, "--limit");
|
|
42322
|
+
const after = opts.after === void 0 ? void 0 : parsePositiveIntArg2(opts.after, "--after");
|
|
42323
|
+
await withConnectorsSetup(opts, async ({ client, signal }) => {
|
|
42324
|
+
await runPollItems({
|
|
42325
|
+
client,
|
|
42326
|
+
filebox,
|
|
42327
|
+
...state !== void 0 ? { state } : {},
|
|
42328
|
+
...limit !== void 0 ? { limit } : {},
|
|
42329
|
+
...after !== void 0 ? { after } : {},
|
|
42330
|
+
asJson: opts.json === true,
|
|
42331
|
+
signal,
|
|
42332
|
+
out: process.stdout
|
|
42333
|
+
});
|
|
42334
|
+
});
|
|
42335
|
+
}
|
|
42336
|
+
);
|
|
42337
|
+
addCommonFlags(itemsCmd, "Output the raw page as JSON");
|
|
42338
|
+
const retryCmd = poll2.command("retry").description("Queue a failed, waiting or skipped item again").argument("<filebox>", "filebox id or uuid").argument("<item>", "item id (from poll items)").action(async (filebox, item, opts) => {
|
|
42339
|
+
const itemId = parsePositiveIntArg2(item, "item id");
|
|
42340
|
+
await withConnectorsSetup(opts, async ({ client, signal }) => {
|
|
42341
|
+
await runPollRetry({
|
|
42342
|
+
client,
|
|
42343
|
+
filebox,
|
|
42344
|
+
itemId,
|
|
42345
|
+
asJson: opts.json === true,
|
|
42346
|
+
signal,
|
|
42347
|
+
out: process.stdout
|
|
42348
|
+
});
|
|
42349
|
+
});
|
|
42350
|
+
});
|
|
42351
|
+
addCommonFlags(retryCmd, "Output the item as JSON");
|
|
42352
|
+
const skipCmd = addConfirmTokenFlag(
|
|
42353
|
+
poll2.command("skip").description("Skip an item so it is never landed (two-step confirmation)").argument("<filebox>", "filebox id or uuid").argument("<item>", "item id (from poll items)")
|
|
42354
|
+
).action(async (filebox, item, opts) => {
|
|
42355
|
+
const itemId = parsePositiveIntArg2(item, "item id");
|
|
42356
|
+
await preflightConfirmToken(
|
|
42357
|
+
pollItemConfirmAction(filebox, itemId, scopeOf(opts)),
|
|
42358
|
+
opts.confirmToken
|
|
42359
|
+
);
|
|
42360
|
+
await withConnectorsSetup(opts, async (setup) => {
|
|
42361
|
+
await runPollSkip({
|
|
42362
|
+
client: setup.client,
|
|
42363
|
+
filebox,
|
|
42364
|
+
itemId,
|
|
42365
|
+
deadline: {
|
|
42366
|
+
pause: () => setup.pauseTimeout(),
|
|
42367
|
+
resume: () => setup.extendTimeout(DEFAULT_CALL_TIMEOUT_MS)
|
|
42368
|
+
},
|
|
42369
|
+
...opts.confirmToken !== void 0 ? { token: opts.confirmToken } : {},
|
|
42370
|
+
scope: scopeOf(opts),
|
|
42371
|
+
targetArgs: targetArgsOf(opts),
|
|
42372
|
+
asJson: opts.json === true,
|
|
42373
|
+
signal: setup.signal,
|
|
42374
|
+
out: process.stdout
|
|
42375
|
+
});
|
|
42376
|
+
});
|
|
42377
|
+
});
|
|
42378
|
+
addCommonFlags(skipCmd, "Output the item as JSON");
|
|
42379
|
+
const seedCmd = addConfirmTokenFlag(
|
|
42380
|
+
poll2.command("seed").description("Mark items modified at or before --until as already landed (cut-over)").argument("<filebox>", "filebox id or uuid").requiredOption(
|
|
42381
|
+
"--until <timestamp>",
|
|
42382
|
+
"date or timestamp with a zone, e.g. 2026-10-08T17:30:00Z"
|
|
42383
|
+
).option(
|
|
42384
|
+
"--dry-run",
|
|
42385
|
+
"count the already-discovered items it would mark, without changing anything",
|
|
42386
|
+
false
|
|
42387
|
+
)
|
|
42388
|
+
).action(
|
|
42389
|
+
async (filebox, opts) => {
|
|
42390
|
+
const until = parseTimestampFlag(opts.until, "--until");
|
|
42391
|
+
const dryRun = opts.dryRun === true;
|
|
42392
|
+
if (!dryRun) {
|
|
42393
|
+
await preflightConfirmToken(
|
|
42394
|
+
pollConfirmAction(filebox, "seed", scopeOf(opts), { until }),
|
|
42395
|
+
opts.confirmToken
|
|
42396
|
+
);
|
|
42397
|
+
}
|
|
42398
|
+
await withConnectorsSetup(opts, async (setup) => {
|
|
42399
|
+
await runPollSeed({
|
|
42400
|
+
client: setup.client,
|
|
42401
|
+
filebox,
|
|
42402
|
+
until,
|
|
42403
|
+
untilArg: opts.until.trim(),
|
|
42404
|
+
dryRun,
|
|
42405
|
+
deadline: {
|
|
42406
|
+
pause: () => setup.pauseTimeout(),
|
|
42407
|
+
resume: () => setup.extendTimeout(DEFAULT_CALL_TIMEOUT_MS)
|
|
42408
|
+
},
|
|
42409
|
+
...opts.confirmToken !== void 0 ? { token: opts.confirmToken } : {},
|
|
42410
|
+
scope: scopeOf(opts),
|
|
42411
|
+
targetArgs: targetArgsOf(opts),
|
|
42412
|
+
asJson: opts.json === true,
|
|
42413
|
+
signal: setup.signal,
|
|
42414
|
+
out: process.stdout
|
|
42415
|
+
});
|
|
42416
|
+
});
|
|
42417
|
+
}
|
|
42418
|
+
);
|
|
42419
|
+
addCommonFlags(seedCmd, "Output the binding (or the dry-run count) as JSON");
|
|
42420
|
+
}
|
|
42421
|
+
|
|
41160
42422
|
// src/commands/connectors.ts
|
|
41161
42423
|
var CONTROL_PLANE_HOST = (subDomain) => `https://${subDomain}-connectors-control-plane.datarails.io`;
|
|
41162
42424
|
function resolveConnectorsUrl(serverKey, connectorsUrlFlag) {
|
|
@@ -41202,7 +42464,12 @@ async function withConnectorsSetup(opts, action) {
|
|
|
41202
42464
|
authHost: resolve(serverKey).host
|
|
41203
42465
|
});
|
|
41204
42466
|
try {
|
|
41205
|
-
await action({
|
|
42467
|
+
await action({
|
|
42468
|
+
client: setup.client,
|
|
42469
|
+
signal: setup.signal,
|
|
42470
|
+
pauseTimeout: setup.pauseTimeout,
|
|
42471
|
+
extendTimeout: setup.extendTimeout
|
|
42472
|
+
});
|
|
41206
42473
|
} catch (err) {
|
|
41207
42474
|
throw augmentTlsCertError(err);
|
|
41208
42475
|
} finally {
|
|
@@ -41808,6 +43075,7 @@ ${TLS_VPN_HELP}`);
|
|
|
41808
43075
|
addAccountFlag(activeGetCmd);
|
|
41809
43076
|
addConnectorsUrlFlag(activeGetCmd);
|
|
41810
43077
|
registerDevFetch(connectors);
|
|
43078
|
+
registerConnectorsPoll(connectors);
|
|
41811
43079
|
}
|
|
41812
43080
|
|
|
41813
43081
|
// src/types/dashboards.ts
|
|
@@ -43088,7 +44356,7 @@ async function buildFiltersForCfg(resolver, cfg) {
|
|
|
43088
44356
|
dateFlags: cfg.dateFlags
|
|
43089
44357
|
});
|
|
43090
44358
|
}
|
|
43091
|
-
function
|
|
44359
|
+
function writeTable27(out, rows) {
|
|
43092
44360
|
if (rows.length === 0) return;
|
|
43093
44361
|
const widths = [];
|
|
43094
44362
|
for (const r of rows) {
|
|
@@ -43122,7 +44390,7 @@ function renderWidgetsTable(out, widgets) {
|
|
|
43122
44390
|
]
|
|
43123
44391
|
});
|
|
43124
44392
|
}
|
|
43125
|
-
|
|
44393
|
+
writeTable27(out, rows);
|
|
43126
44394
|
}
|
|
43127
44395
|
function registerWidgetsCommand(root) {
|
|
43128
44396
|
const widgets = root.command("widgets").alias("widget").description("Operations on Datarails dashboard widgets");
|
|
@@ -43554,7 +44822,7 @@ function registerWidgetsCommand(root) {
|
|
|
43554
44822
|
}
|
|
43555
44823
|
|
|
43556
44824
|
// src/commands/reconciliation.ts
|
|
43557
|
-
import { createHash as
|
|
44825
|
+
import { createHash as createHash11 } from "crypto";
|
|
43558
44826
|
import { promises as fs18 } from "fs";
|
|
43559
44827
|
|
|
43560
44828
|
// src/api/reconciliation.ts
|
|
@@ -44298,7 +45566,7 @@ function dash(v) {
|
|
|
44298
45566
|
if (typeof v === "string" && v === "") return "-";
|
|
44299
45567
|
return String(v);
|
|
44300
45568
|
}
|
|
44301
|
-
function
|
|
45569
|
+
function writeTable28(out, rows) {
|
|
44302
45570
|
if (rows.length === 0) return;
|
|
44303
45571
|
const widths = [];
|
|
44304
45572
|
for (const r of rows) {
|
|
@@ -44336,7 +45604,7 @@ function renderEvidenceList(out, items) {
|
|
|
44336
45604
|
dash(e.note ?? null)
|
|
44337
45605
|
]);
|
|
44338
45606
|
}
|
|
44339
|
-
|
|
45607
|
+
writeTable28(out, rows);
|
|
44340
45608
|
const word = items.length === 1 ? "evidence" : "evidences";
|
|
44341
45609
|
out.write(`
|
|
44342
45610
|
(${items.length} ${word})
|
|
@@ -44355,7 +45623,7 @@ function renderEvidenceSingle(out, e) {
|
|
|
44355
45623
|
dash(e.file_url ?? null)
|
|
44356
45624
|
]
|
|
44357
45625
|
];
|
|
44358
|
-
|
|
45626
|
+
writeTable28(out, rows);
|
|
44359
45627
|
}
|
|
44360
45628
|
function renderSupportingItemsList(out, items) {
|
|
44361
45629
|
if (items.length === 0) {
|
|
@@ -44372,7 +45640,7 @@ function renderSupportingItemsList(out, items) {
|
|
|
44372
45640
|
dash(e.url)
|
|
44373
45641
|
]);
|
|
44374
45642
|
}
|
|
44375
|
-
|
|
45643
|
+
writeTable28(out, rows);
|
|
44376
45644
|
const word = items.length === 1 ? "supporting item" : "supporting items";
|
|
44377
45645
|
out.write(`
|
|
44378
45646
|
(${items.length} ${word})
|
|
@@ -44749,7 +46017,7 @@ function dash2(v) {
|
|
|
44749
46017
|
if (typeof v === "string" && v === "") return "-";
|
|
44750
46018
|
return String(v);
|
|
44751
46019
|
}
|
|
44752
|
-
function
|
|
46020
|
+
function writeTable29(out, rows) {
|
|
44753
46021
|
if (rows.length === 0) return;
|
|
44754
46022
|
const widths = [];
|
|
44755
46023
|
for (const r of rows) {
|
|
@@ -44790,7 +46058,7 @@ function renderConnectionList(out, items) {
|
|
|
44790
46058
|
String(c.sync_progress_percentage)
|
|
44791
46059
|
]);
|
|
44792
46060
|
}
|
|
44793
|
-
|
|
46061
|
+
writeTable29(out, rows);
|
|
44794
46062
|
out.write(`
|
|
44795
46063
|
(${items.length} connection${plural(items.length)})
|
|
44796
46064
|
`);
|
|
@@ -44818,7 +46086,7 @@ function renderConnectionSingle(out, c) {
|
|
|
44818
46086
|
String(c.initial_sync_total_files)
|
|
44819
46087
|
]
|
|
44820
46088
|
];
|
|
44821
|
-
|
|
46089
|
+
writeTable29(out, rows);
|
|
44822
46090
|
}
|
|
44823
46091
|
function renderSyncProgress(out, resp) {
|
|
44824
46092
|
out.write(`Status: ${dash2(resp.status)}
|
|
@@ -45181,7 +46449,7 @@ function chunkByJsonBytes(rows, maxBytes) {
|
|
|
45181
46449
|
return chunks;
|
|
45182
46450
|
}
|
|
45183
46451
|
function settingsActionId(settings) {
|
|
45184
|
-
return
|
|
46452
|
+
return createHash11("sha256").update(JSON.stringify(settings)).digest("hex").slice(0, 12);
|
|
45185
46453
|
}
|
|
45186
46454
|
async function runReconciliationAccountsUpdateSettings(cfg) {
|
|
45187
46455
|
const action = {
|
|
@@ -45268,7 +46536,7 @@ function dash4(v) {
|
|
|
45268
46536
|
if (typeof v === "string" && v === "") return "-";
|
|
45269
46537
|
return String(v);
|
|
45270
46538
|
}
|
|
45271
|
-
function
|
|
46539
|
+
function writeTable30(out, rows) {
|
|
45272
46540
|
if (rows.length === 0) return;
|
|
45273
46541
|
const widths = [];
|
|
45274
46542
|
for (const r of rows) {
|
|
@@ -45308,7 +46576,7 @@ function renderAccountsList(out, items) {
|
|
|
45308
46576
|
dash4(a.frequency)
|
|
45309
46577
|
]);
|
|
45310
46578
|
}
|
|
45311
|
-
|
|
46579
|
+
writeTable30(out, rows);
|
|
45312
46580
|
out.write(`
|
|
45313
46581
|
(${items.length} account${plural(items.length)})
|
|
45314
46582
|
`);
|
|
@@ -45337,7 +46605,7 @@ function renderEntityCurrencies(out, resp) {
|
|
|
45337
46605
|
for (const e of resp.entities) {
|
|
45338
46606
|
rows.push([dash4(e.name), dash4(e.currency)]);
|
|
45339
46607
|
}
|
|
45340
|
-
|
|
46608
|
+
writeTable30(out, rows);
|
|
45341
46609
|
}
|
|
45342
46610
|
function renderAccountsInfo(out, items) {
|
|
45343
46611
|
if (items.length === 0) {
|
|
@@ -45348,7 +46616,7 @@ function renderAccountsInfo(out, items) {
|
|
|
45348
46616
|
for (const a of items) {
|
|
45349
46617
|
rows.push([dash4(a.id), dash4(a.name), dash4(a.account_group ?? null), dash4(a.entity ?? null)]);
|
|
45350
46618
|
}
|
|
45351
|
-
|
|
46619
|
+
writeTable30(out, rows);
|
|
45352
46620
|
out.write(`
|
|
45353
46621
|
(${items.length} account${plural(items.length)})
|
|
45354
46622
|
`);
|
|
@@ -45399,7 +46667,7 @@ function renderAccountsSettings(out, items) {
|
|
|
45399
46667
|
String(a.threshold_to)
|
|
45400
46668
|
]);
|
|
45401
46669
|
}
|
|
45402
|
-
|
|
46670
|
+
writeTable30(out, rows);
|
|
45403
46671
|
out.write(`
|
|
45404
46672
|
(${items.length} account${plural(items.length)})
|
|
45405
46673
|
`);
|
|
@@ -45559,7 +46827,7 @@ async function runReconciliationAccountsSetAssignee(cfg) {
|
|
|
45559
46827
|
var ASSIGNEE_BATCH_CHUNK_SIZE = 100;
|
|
45560
46828
|
function assigneeBatchActionId(date, rows) {
|
|
45561
46829
|
const canonical = rows.map((r) => [r.accountId, r.type, r.userId, r.userName, r.userEmail]);
|
|
45562
|
-
return
|
|
46830
|
+
return createHash11("sha256").update(JSON.stringify([date, canonical])).digest("hex").slice(0, 12);
|
|
45563
46831
|
}
|
|
45564
46832
|
async function runReconciliationAccountsSetAssigneeBatch(cfg) {
|
|
45565
46833
|
const action = {
|
|
@@ -45713,7 +46981,7 @@ verify the date matches the accounts' reporting period (try \`dr reconciliation
|
|
|
45713
46981
|
}
|
|
45714
46982
|
function clearBatchActionId(date, rows) {
|
|
45715
46983
|
const canonical = rows.map((r) => [r.accountId, r.type]);
|
|
45716
|
-
return
|
|
46984
|
+
return createHash11("sha256").update(JSON.stringify(["clear", date, canonical])).digest("hex").slice(0, 12);
|
|
45717
46985
|
}
|
|
45718
46986
|
async function runReconciliationAccountsClearAssigneeBatch(cfg) {
|
|
45719
46987
|
const action = {
|
|
@@ -47603,7 +48871,7 @@ function renderForError(v) {
|
|
|
47603
48871
|
}
|
|
47604
48872
|
|
|
47605
48873
|
// src/commands/mecWorkflow.ts
|
|
47606
|
-
import { createHash as
|
|
48874
|
+
import { createHash as createHash12 } from "crypto";
|
|
47607
48875
|
|
|
47608
48876
|
// src/api/workflow.ts
|
|
47609
48877
|
function buildQueryString(params) {
|
|
@@ -49095,7 +50363,7 @@ function dash5(s) {
|
|
|
49095
50363
|
if (s === "") return "-";
|
|
49096
50364
|
return s;
|
|
49097
50365
|
}
|
|
49098
|
-
function
|
|
50366
|
+
function writeTable31(out, rows) {
|
|
49099
50367
|
if (rows.length === 0) return;
|
|
49100
50368
|
const widths = [];
|
|
49101
50369
|
for (const r of rows) {
|
|
@@ -49217,7 +50485,7 @@ function renderMecWorkflowList(out, rows) {
|
|
|
49217
50485
|
dash5(r.update_time)
|
|
49218
50486
|
]);
|
|
49219
50487
|
}
|
|
49220
|
-
|
|
50488
|
+
writeTable31(out, tableRows);
|
|
49221
50489
|
out.write(`
|
|
49222
50490
|
(${rows.length} MEC workflow${plural(rows.length)})
|
|
49223
50491
|
`);
|
|
@@ -49245,7 +50513,7 @@ function renderMecWorkflowDetail(out, t) {
|
|
|
49245
50513
|
["updated:", dash5(t.update_time)],
|
|
49246
50514
|
["process_start_time:", dash5(t.process_start_time)]
|
|
49247
50515
|
];
|
|
49248
|
-
|
|
50516
|
+
writeTable31(out, rows);
|
|
49249
50517
|
out.write("\n");
|
|
49250
50518
|
const perms = t.permissions ?? [];
|
|
49251
50519
|
out.write("permissions: ");
|
|
@@ -49260,7 +50528,7 @@ function renderMecWorkflowDetail(out, t) {
|
|
|
49260
50528
|
for (const tag of tags) {
|
|
49261
50529
|
tagRows.push([` ${tag.id}`, dash5(tag.name), dash5(tag.label), String(tag.value)]);
|
|
49262
50530
|
}
|
|
49263
|
-
|
|
50531
|
+
writeTable31(out, tagRows);
|
|
49264
50532
|
}
|
|
49265
50533
|
out.write("\nprocess_instances:\n");
|
|
49266
50534
|
const instances = t.process_instances ?? [];
|
|
@@ -49277,7 +50545,7 @@ function renderMecWorkflowDetail(out, t) {
|
|
|
49277
50545
|
dash5(pi.create_time)
|
|
49278
50546
|
]);
|
|
49279
50547
|
}
|
|
49280
|
-
|
|
50548
|
+
writeTable31(out, piRows);
|
|
49281
50549
|
}
|
|
49282
50550
|
}
|
|
49283
50551
|
async function runMecProcessList(cfg) {
|
|
@@ -49311,7 +50579,7 @@ function renderMecProcessList(out, rows) {
|
|
|
49311
50579
|
dash5(r.create_time)
|
|
49312
50580
|
]);
|
|
49313
50581
|
}
|
|
49314
|
-
|
|
50582
|
+
writeTable31(out, tableRows);
|
|
49315
50583
|
out.write(`
|
|
49316
50584
|
(${rows.length} MEC process${rows.length === 1 ? "" : "es"})
|
|
49317
50585
|
`);
|
|
@@ -49337,7 +50605,7 @@ function renderMecProcessDetail(out, p) {
|
|
|
49337
50605
|
["active:", p.is_active === true ? "yes" : p.is_active === false ? "no" : "-"],
|
|
49338
50606
|
["created:", dash5(p.create_time)]
|
|
49339
50607
|
];
|
|
49340
|
-
|
|
50608
|
+
writeTable31(out, rows);
|
|
49341
50609
|
out.write("\nsteps:\n");
|
|
49342
50610
|
const steps = p.steps ?? [];
|
|
49343
50611
|
if (steps.length === 0) {
|
|
@@ -49355,7 +50623,7 @@ function renderMecProcessDetail(out, p) {
|
|
|
49355
50623
|
dash5(s.due_date)
|
|
49356
50624
|
]);
|
|
49357
50625
|
}
|
|
49358
|
-
|
|
50626
|
+
writeTable31(out, stepRows);
|
|
49359
50627
|
}
|
|
49360
50628
|
async function runMecStepGet(cfg) {
|
|
49361
50629
|
await requireMec(cfg.client, { signal: cfg.signal });
|
|
@@ -49384,7 +50652,7 @@ function renderMecStepDetail(out, s) {
|
|
|
49384
50652
|
["starting_date:", dash5(s.starting_date)],
|
|
49385
50653
|
["due_date:", dash5(s.due_date)]
|
|
49386
50654
|
];
|
|
49387
|
-
|
|
50655
|
+
writeTable31(out, rows);
|
|
49388
50656
|
out.write("\ntasks:\n");
|
|
49389
50657
|
const tasks = allStepTasks(s);
|
|
49390
50658
|
if (tasks.length === 0) {
|
|
@@ -49409,7 +50677,7 @@ function renderMecTaskTable(out, tasks, indent) {
|
|
|
49409
50677
|
reconciliationTagsSummary(t.reconciliation_tags)
|
|
49410
50678
|
]);
|
|
49411
50679
|
}
|
|
49412
|
-
|
|
50680
|
+
writeTable31(out, tableRows);
|
|
49413
50681
|
}
|
|
49414
50682
|
async function runMecTaskList(cfg) {
|
|
49415
50683
|
await requireMec(cfg.client, { signal: cfg.signal });
|
|
@@ -49475,7 +50743,7 @@ function renderMecTaskDetail(out, t) {
|
|
|
49475
50743
|
rows.push(["description:", dash5(nf.description)]);
|
|
49476
50744
|
rows.push(["display_reviewer:", nf.display_reviewer ? "yes" : "no"]);
|
|
49477
50745
|
}
|
|
49478
|
-
|
|
50746
|
+
writeTable31(out, rows);
|
|
49479
50747
|
}
|
|
49480
50748
|
async function runMecMemberList(cfg) {
|
|
49481
50749
|
await requireMec(cfg.client, { signal: cfg.signal });
|
|
@@ -49497,7 +50765,7 @@ function renderMecMemberList(out, rows) {
|
|
|
49497
50765
|
for (const r of rows) {
|
|
49498
50766
|
tableRows.push([dash5(r.id), dash5(r.email), memberRoleName(r.role), memberRoleId(r.role)]);
|
|
49499
50767
|
}
|
|
49500
|
-
|
|
50768
|
+
writeTable31(out, tableRows);
|
|
49501
50769
|
out.write(`
|
|
49502
50770
|
(${rows.length} member${plural(rows.length)})
|
|
49503
50771
|
`);
|
|
@@ -49533,7 +50801,7 @@ async function runMecMemberCheck(cfg) {
|
|
|
49533
50801
|
for (const d of docs) {
|
|
49534
50802
|
tableRows.push([String(d.id), dash5(d.name)]);
|
|
49535
50803
|
}
|
|
49536
|
-
|
|
50804
|
+
writeTable31(cfg.out, tableRows);
|
|
49537
50805
|
cfg.out.write(`
|
|
49538
50806
|
(${docs.length} doc${plural(docs.length)})
|
|
49539
50807
|
`);
|
|
@@ -49562,7 +50830,7 @@ function renderMecGroupList(out, rows) {
|
|
|
49562
50830
|
dash5(typeof r.role === "string" ? r.role : r.role)
|
|
49563
50831
|
]);
|
|
49564
50832
|
}
|
|
49565
|
-
|
|
50833
|
+
writeTable31(out, tableRows);
|
|
49566
50834
|
out.write(`
|
|
49567
50835
|
(${rows.length} group${plural(rows.length)})
|
|
49568
50836
|
`);
|
|
@@ -49585,7 +50853,7 @@ function renderMecPeriods(out, rows) {
|
|
|
49585
50853
|
for (const r of rows) {
|
|
49586
50854
|
tableRows.push([String(r), unixSecondsToYmd(r)]);
|
|
49587
50855
|
}
|
|
49588
|
-
|
|
50856
|
+
writeTable31(out, tableRows);
|
|
49589
50857
|
out.write(`
|
|
49590
50858
|
(${rows.length} period${plural(rows.length)})
|
|
49591
50859
|
`);
|
|
@@ -49654,7 +50922,7 @@ async function runMecAccountsTaskStatuses(cfg) {
|
|
|
49654
50922
|
renderMecAccountsTasksOrStatuses(cfg.out, resp, "statuses");
|
|
49655
50923
|
}
|
|
49656
50924
|
function shortHash4(input) {
|
|
49657
|
-
return
|
|
50925
|
+
return createHash12("sha256").update(input).digest("hex").slice(0, 12);
|
|
49658
50926
|
}
|
|
49659
50927
|
async function runMecWorkflowCreate(cfg) {
|
|
49660
50928
|
const action = {
|
|
@@ -51907,7 +53175,7 @@ async function runMecCloseDatesSet(cfg) {
|
|
|
51907
53175
|
cfg.out.write(`Updated ${monthCount} ${monthWord} across ${yearCount} ${yearWord}.
|
|
51908
53176
|
`);
|
|
51909
53177
|
}
|
|
51910
|
-
function
|
|
53178
|
+
function writeTable32(out, rows) {
|
|
51911
53179
|
if (rows.length === 0) return;
|
|
51912
53180
|
const widths = [];
|
|
51913
53181
|
for (const r of rows) {
|
|
@@ -51960,7 +53228,7 @@ function renderCloseDatesTable(out, map) {
|
|
|
51960
53228
|
tableRows.push([String(r.year), String(r.month), String(r.rawValue), "-"]);
|
|
51961
53229
|
}
|
|
51962
53230
|
}
|
|
51963
|
-
|
|
53231
|
+
writeTable32(out, tableRows);
|
|
51964
53232
|
const word = rows.length === 1 ? "month" : "months";
|
|
51965
53233
|
out.write(`
|
|
51966
53234
|
(${rows.length} ${word})
|
|
@@ -52038,14 +53306,14 @@ function wireMec(program) {
|
|
|
52038
53306
|
}
|
|
52039
53307
|
|
|
52040
53308
|
// src/commands/workflow.ts
|
|
52041
|
-
import { createHash as
|
|
53309
|
+
import { createHash as createHash13 } from "crypto";
|
|
52042
53310
|
function dash6(s) {
|
|
52043
53311
|
if (s === null || s === void 0) return "-";
|
|
52044
53312
|
if (typeof s === "number") return String(s);
|
|
52045
53313
|
if (s === "") return "-";
|
|
52046
53314
|
return s;
|
|
52047
53315
|
}
|
|
52048
|
-
function
|
|
53316
|
+
function writeTable33(out, rows) {
|
|
52049
53317
|
if (rows.length === 0) return;
|
|
52050
53318
|
const widths = [];
|
|
52051
53319
|
for (const r of rows) {
|
|
@@ -52146,7 +53414,7 @@ function renderWorkflowList(out, rows) {
|
|
|
52146
53414
|
dash6(r.update_time)
|
|
52147
53415
|
]);
|
|
52148
53416
|
}
|
|
52149
|
-
|
|
53417
|
+
writeTable33(out, tableRows);
|
|
52150
53418
|
out.write(`
|
|
52151
53419
|
(${rows.length} workflow${plural(rows.length)})
|
|
52152
53420
|
`);
|
|
@@ -52176,7 +53444,7 @@ function renderWorkflowDetail(out, t) {
|
|
|
52176
53444
|
["updated:", dash6(t.update_time)],
|
|
52177
53445
|
["process_start_time:", dash6(t.process_start_time)]
|
|
52178
53446
|
];
|
|
52179
|
-
|
|
53447
|
+
writeTable33(out, rows);
|
|
52180
53448
|
out.write("\n");
|
|
52181
53449
|
const perms = t.permissions ?? [];
|
|
52182
53450
|
out.write("permissions: ");
|
|
@@ -52191,7 +53459,7 @@ function renderWorkflowDetail(out, t) {
|
|
|
52191
53459
|
for (const tag of tags) {
|
|
52192
53460
|
tagRows.push([` ${tag.id}`, dash6(tag.name), dash6(tag.label), String(tag.value)]);
|
|
52193
53461
|
}
|
|
52194
|
-
|
|
53462
|
+
writeTable33(out, tagRows);
|
|
52195
53463
|
}
|
|
52196
53464
|
out.write("\nprocess_instances:\n");
|
|
52197
53465
|
const instances = t.process_instances ?? [];
|
|
@@ -52207,7 +53475,7 @@ function renderWorkflowDetail(out, t) {
|
|
|
52207
53475
|
dash6(pi.create_time)
|
|
52208
53476
|
]);
|
|
52209
53477
|
}
|
|
52210
|
-
|
|
53478
|
+
writeTable33(out, piRows);
|
|
52211
53479
|
}
|
|
52212
53480
|
}
|
|
52213
53481
|
async function runProcessList(cfg) {
|
|
@@ -52240,7 +53508,7 @@ function renderProcessList(out, rows) {
|
|
|
52240
53508
|
dash6(r.create_time)
|
|
52241
53509
|
]);
|
|
52242
53510
|
}
|
|
52243
|
-
|
|
53511
|
+
writeTable33(out, tableRows);
|
|
52244
53512
|
out.write(`
|
|
52245
53513
|
(${rows.length} process${rows.length === 1 ? "" : "es"})
|
|
52246
53514
|
`);
|
|
@@ -52268,7 +53536,7 @@ function renderProcessDetail(out, p) {
|
|
|
52268
53536
|
["active:", p.is_active === true ? "yes" : p.is_active === false ? "no" : "-"],
|
|
52269
53537
|
["created:", dash6(p.create_time)]
|
|
52270
53538
|
];
|
|
52271
|
-
|
|
53539
|
+
writeTable33(out, rows);
|
|
52272
53540
|
out.write("\nsteps:\n");
|
|
52273
53541
|
const steps = p.steps ?? [];
|
|
52274
53542
|
if (steps.length === 0) {
|
|
@@ -52286,7 +53554,7 @@ function renderProcessDetail(out, p) {
|
|
|
52286
53554
|
dash6(s.due_date)
|
|
52287
53555
|
]);
|
|
52288
53556
|
}
|
|
52289
|
-
|
|
53557
|
+
writeTable33(out, stepRows);
|
|
52290
53558
|
}
|
|
52291
53559
|
async function runStepGet(cfg) {
|
|
52292
53560
|
await requireWorkflowV2(cfg.client, { signal: cfg.signal });
|
|
@@ -52317,7 +53585,7 @@ function renderStepDetail(out, s) {
|
|
|
52317
53585
|
["starting_date:", dash6(s.starting_date)],
|
|
52318
53586
|
["due_date:", dash6(s.due_date)]
|
|
52319
53587
|
];
|
|
52320
|
-
|
|
53588
|
+
writeTable33(out, rows);
|
|
52321
53589
|
out.write("\ntasks:\n");
|
|
52322
53590
|
const tasks = allStepTasks2(s);
|
|
52323
53591
|
if (tasks.length === 0) {
|
|
@@ -52341,7 +53609,7 @@ function renderTaskTable(out, tasks, indent) {
|
|
|
52341
53609
|
dash6(t.task_status)
|
|
52342
53610
|
]);
|
|
52343
53611
|
}
|
|
52344
|
-
|
|
53612
|
+
writeTable33(out, tableRows);
|
|
52345
53613
|
}
|
|
52346
53614
|
async function runTaskList(cfg) {
|
|
52347
53615
|
await requireWorkflowV2(cfg.client, { signal: cfg.signal });
|
|
@@ -52408,7 +53676,7 @@ function renderTaskDetail(out, t) {
|
|
|
52408
53676
|
rows.push(["description:", dash6(nf.description)]);
|
|
52409
53677
|
rows.push(["display_reviewer:", nf.display_reviewer ? "yes" : "no"]);
|
|
52410
53678
|
}
|
|
52411
|
-
|
|
53679
|
+
writeTable33(out, rows);
|
|
52412
53680
|
}
|
|
52413
53681
|
async function runMemberList(cfg) {
|
|
52414
53682
|
await requireWorkflowV2(cfg.client, { signal: cfg.signal });
|
|
@@ -52432,7 +53700,7 @@ function renderMemberList(out, rows) {
|
|
|
52432
53700
|
for (const r of rows) {
|
|
52433
53701
|
tableRows.push([dash6(r.id), dash6(r.email), memberRoleName2(r.role), memberRoleId2(r.role)]);
|
|
52434
53702
|
}
|
|
52435
|
-
|
|
53703
|
+
writeTable33(out, tableRows);
|
|
52436
53704
|
out.write(`
|
|
52437
53705
|
(${rows.length} member${plural(rows.length)})
|
|
52438
53706
|
`);
|
|
@@ -52470,7 +53738,7 @@ async function runMemberCheck(cfg) {
|
|
|
52470
53738
|
for (const d of docs) {
|
|
52471
53739
|
tableRows.push([String(d.id), dash6(d.name)]);
|
|
52472
53740
|
}
|
|
52473
|
-
|
|
53741
|
+
writeTable33(cfg.out, tableRows);
|
|
52474
53742
|
cfg.out.write(`
|
|
52475
53743
|
(${docs.length} doc${plural(docs.length)})
|
|
52476
53744
|
`);
|
|
@@ -52501,13 +53769,13 @@ function renderGroupList(out, rows) {
|
|
|
52501
53769
|
dash6(typeof r.role === "string" ? r.role : r.role)
|
|
52502
53770
|
]);
|
|
52503
53771
|
}
|
|
52504
|
-
|
|
53772
|
+
writeTable33(out, tableRows);
|
|
52505
53773
|
out.write(`
|
|
52506
53774
|
(${rows.length} group${plural(rows.length)})
|
|
52507
53775
|
`);
|
|
52508
53776
|
}
|
|
52509
53777
|
function shortHash5(input) {
|
|
52510
|
-
return
|
|
53778
|
+
return createHash13("sha256").update(input).digest("hex").slice(0, 12);
|
|
52511
53779
|
}
|
|
52512
53780
|
async function runWorkflowCreate(cfg) {
|
|
52513
53781
|
const action = {
|
|
@@ -54666,7 +55934,7 @@ function wireWorkflow(root) {
|
|
|
54666
55934
|
}
|
|
54667
55935
|
|
|
54668
55936
|
// src/commands/cash.ts
|
|
54669
|
-
import { createHash as
|
|
55937
|
+
import { createHash as createHash14 } from "crypto";
|
|
54670
55938
|
import { promises as fs25 } from "fs";
|
|
54671
55939
|
|
|
54672
55940
|
// src/api/cash.ts
|
|
@@ -55346,7 +56614,7 @@ function truncate7(s, max) {
|
|
|
55346
56614
|
function dash7(s) {
|
|
55347
56615
|
return s === null || s === void 0 || s === "" ? "-" : s;
|
|
55348
56616
|
}
|
|
55349
|
-
function
|
|
56617
|
+
function writeTable34(out, rows) {
|
|
55350
56618
|
if (rows.length === 0) return;
|
|
55351
56619
|
const widths = [];
|
|
55352
56620
|
for (const r of rows) {
|
|
@@ -55401,7 +56669,7 @@ async function runCashCurrenciesList(cfg) {
|
|
|
55401
56669
|
}
|
|
55402
56670
|
const tableRows = [["CODE", "FULL_NAME"]];
|
|
55403
56671
|
for (const r of rows) tableRows.push([r.code, r.full_name]);
|
|
55404
|
-
|
|
56672
|
+
writeTable34(cfg.out, tableRows);
|
|
55405
56673
|
cfg.out.write(`
|
|
55406
56674
|
(${rows.length} currenc${rows.length === 1 ? "y" : "ies"})
|
|
55407
56675
|
`);
|
|
@@ -55470,7 +56738,7 @@ function renderOrgCurrencies(out, rows) {
|
|
|
55470
56738
|
r.is_system_default ? "yes" : ""
|
|
55471
56739
|
]);
|
|
55472
56740
|
}
|
|
55473
|
-
|
|
56741
|
+
writeTable34(out, tableRows);
|
|
55474
56742
|
out.write(`
|
|
55475
56743
|
(${rows.length} currenc${rows.length === 1 ? "y" : "ies"})
|
|
55476
56744
|
`);
|
|
@@ -55506,7 +56774,7 @@ function renderTransactions(out, resp) {
|
|
|
55506
56774
|
})
|
|
55507
56775
|
);
|
|
55508
56776
|
}
|
|
55509
|
-
|
|
56777
|
+
writeTable34(out, tableRows);
|
|
55510
56778
|
const shown = resp.results.length;
|
|
55511
56779
|
const pageHint = resp.next !== null ? ` \u2014 next page: ${resp.next}` : "";
|
|
55512
56780
|
out.write(`
|
|
@@ -55757,7 +57025,7 @@ async function runCashRulesDeleteAll(cfg) {
|
|
|
55757
57025
|
return;
|
|
55758
57026
|
}
|
|
55759
57027
|
const ids = targets.map((r) => r.id).sort((a, b) => a - b);
|
|
55760
|
-
const sha =
|
|
57028
|
+
const sha = createHash14("sha256").update(ids.join(",")).digest("hex").slice(0, 12);
|
|
55761
57029
|
const action = {
|
|
55762
57030
|
resource: "cash-rules-batch",
|
|
55763
57031
|
id: `${templateId}:${sha}`,
|
|
@@ -56131,7 +57399,7 @@ function renderRulesTable2(out, rules) {
|
|
|
56131
57399
|
truncate3(dash7(r.description), 40)
|
|
56132
57400
|
]);
|
|
56133
57401
|
}
|
|
56134
|
-
|
|
57402
|
+
writeTable34(out, rows);
|
|
56135
57403
|
out.write(`
|
|
56136
57404
|
(${rules.length} rule${plural(rules.length)})
|
|
56137
57405
|
`);
|
|
@@ -56935,7 +58203,7 @@ function renderManageCompanies(out, resp) {
|
|
|
56935
58203
|
out.write("Groups:\n");
|
|
56936
58204
|
const rows = [["NAME", "DOCUMENTS"]];
|
|
56937
58205
|
for (const g of resp.groups) rows.push([dash8(g.name), formatDocs(g.documents)]);
|
|
56938
|
-
|
|
58206
|
+
writeTable35(out, rows);
|
|
56939
58207
|
out.write("\n");
|
|
56940
58208
|
}
|
|
56941
58209
|
if (resp.companies.length > 0) {
|
|
@@ -56950,7 +58218,7 @@ function renderManageCompanies(out, resp) {
|
|
|
56950
58218
|
dashOrNull(e.group)
|
|
56951
58219
|
]);
|
|
56952
58220
|
}
|
|
56953
|
-
|
|
58221
|
+
writeTable35(out, rows);
|
|
56954
58222
|
out.write(`
|
|
56955
58223
|
(${resp.companies.length} entit${resp.companies.length === 1 ? "y" : "ies"})
|
|
56956
58224
|
`);
|
|
@@ -56967,7 +58235,7 @@ function dashOrNull(s) {
|
|
|
56967
58235
|
if (typeof s !== "string" || s === "") return "-";
|
|
56968
58236
|
return s;
|
|
56969
58237
|
}
|
|
56970
|
-
function
|
|
58238
|
+
function writeTable35(out, rows) {
|
|
56971
58239
|
if (rows.length === 0) return;
|
|
56972
58240
|
const widths = [];
|
|
56973
58241
|
for (const r of rows) {
|
|
@@ -57653,7 +58921,7 @@ async function runCalcmodelsDelete(cfg) {
|
|
|
57653
58921
|
}
|
|
57654
58922
|
});
|
|
57655
58923
|
}
|
|
57656
|
-
function
|
|
58924
|
+
function writeTable36(out, rows) {
|
|
57657
58925
|
if (rows.length === 0) return;
|
|
57658
58926
|
const widths = [];
|
|
57659
58927
|
for (const r of rows) {
|
|
@@ -57709,7 +58977,7 @@ function renderCalcmodelTable(out, models) {
|
|
|
57709
58977
|
]
|
|
57710
58978
|
});
|
|
57711
58979
|
}
|
|
57712
|
-
|
|
58980
|
+
writeTable36(out, rows);
|
|
57713
58981
|
}
|
|
57714
58982
|
function parseCalcmodelIdArg(idStr) {
|
|
57715
58983
|
const n = Number(idStr);
|
|
@@ -58069,7 +59337,7 @@ async function runCalcValsDelete(cfg) {
|
|
|
58069
59337
|
}
|
|
58070
59338
|
});
|
|
58071
59339
|
}
|
|
58072
|
-
function
|
|
59340
|
+
function writeTable37(out, rows) {
|
|
58073
59341
|
if (rows.length === 0) return;
|
|
58074
59342
|
const widths = [];
|
|
58075
59343
|
for (const r of rows) {
|
|
@@ -58107,7 +59375,7 @@ function renderCalcValTable(out, vals) {
|
|
|
58107
59375
|
]
|
|
58108
59376
|
});
|
|
58109
59377
|
}
|
|
58110
|
-
|
|
59378
|
+
writeTable37(out, rows);
|
|
58111
59379
|
}
|
|
58112
59380
|
function parseCalcValIdArg(idStr) {
|
|
58113
59381
|
const n = Number(idStr);
|
|
@@ -58408,7 +59676,7 @@ async function runCyclesList(cfg) {
|
|
|
58408
59676
|
]
|
|
58409
59677
|
});
|
|
58410
59678
|
}
|
|
58411
|
-
|
|
59679
|
+
writeTable38(cfg.out, tableRows);
|
|
58412
59680
|
}
|
|
58413
59681
|
async function runCyclesGet(cfg) {
|
|
58414
59682
|
const allScenarios = await listScenarios(cfg.client, {}, { signal: cfg.signal });
|
|
@@ -58451,7 +59719,7 @@ async function runCyclesGet(cfg) {
|
|
|
58451
59719
|
]
|
|
58452
59720
|
});
|
|
58453
59721
|
}
|
|
58454
|
-
|
|
59722
|
+
writeTable38(cfg.out, rows);
|
|
58455
59723
|
}
|
|
58456
59724
|
cfg.out.write("\nRelated documents:\n");
|
|
58457
59725
|
if (docIds.length === 0) {
|
|
@@ -58488,7 +59756,7 @@ async function runCyclesDocuments(cfg) {
|
|
|
58488
59756
|
}
|
|
58489
59757
|
rows.push({ cells: [String(id), name] });
|
|
58490
59758
|
}
|
|
58491
|
-
|
|
59759
|
+
writeTable38(cfg.out, rows);
|
|
58492
59760
|
}
|
|
58493
59761
|
async function runScenariosList(cfg) {
|
|
58494
59762
|
const scenarios = await listScenarios(
|
|
@@ -58525,7 +59793,7 @@ async function runScenariosList(cfg) {
|
|
|
58525
59793
|
]
|
|
58526
59794
|
});
|
|
58527
59795
|
}
|
|
58528
|
-
|
|
59796
|
+
writeTable38(cfg.out, rows);
|
|
58529
59797
|
}
|
|
58530
59798
|
async function runScenariosVersions(cfg) {
|
|
58531
59799
|
const found = await findScenarioById(cfg.client, cfg.scenarioId, cfg.signal);
|
|
@@ -58561,7 +59829,7 @@ async function runScenariosVersions(cfg) {
|
|
|
58561
59829
|
]
|
|
58562
59830
|
});
|
|
58563
59831
|
}
|
|
58564
|
-
|
|
59832
|
+
writeTable38(cfg.out, rows);
|
|
58565
59833
|
}
|
|
58566
59834
|
async function runScenariosGet(cfg) {
|
|
58567
59835
|
const found = await findScenarioById(cfg.client, cfg.scenarioId, cfg.signal);
|
|
@@ -58635,7 +59903,7 @@ async function runScenariosGet(cfg) {
|
|
|
58635
59903
|
]
|
|
58636
59904
|
});
|
|
58637
59905
|
}
|
|
58638
|
-
|
|
59906
|
+
writeTable38(cfg.out, rows);
|
|
58639
59907
|
cfg.out.write("\n");
|
|
58640
59908
|
}
|
|
58641
59909
|
}
|
|
@@ -59196,7 +60464,7 @@ async function runScenariosBulkEdit(cfg) {
|
|
|
59196
60464
|
}
|
|
59197
60465
|
});
|
|
59198
60466
|
}
|
|
59199
|
-
function
|
|
60467
|
+
function writeTable38(out, rows) {
|
|
59200
60468
|
if (rows.length === 0) return;
|
|
59201
60469
|
const widths = [];
|
|
59202
60470
|
for (const r of rows) {
|
|
@@ -61640,7 +62908,7 @@ function printVendorRows(out, items) {
|
|
|
61640
62908
|
}
|
|
61641
62909
|
rows.push({ cells });
|
|
61642
62910
|
}
|
|
61643
|
-
|
|
62911
|
+
writeTable39(out, rows);
|
|
61644
62912
|
}
|
|
61645
62913
|
var LISTING_FETCH = {
|
|
61646
62914
|
all: listVendors,
|
|
@@ -61720,7 +62988,7 @@ async function runVendorCategories(cfg) {
|
|
|
61720
62988
|
}
|
|
61721
62989
|
const rows = [{ cells: ["VALUE", "DISPLAY NAME"] }];
|
|
61722
62990
|
for (const c of items) rows.push({ cells: [c.value, c.display_name] });
|
|
61723
|
-
|
|
62991
|
+
writeTable39(cfg.out, rows);
|
|
61724
62992
|
cfg.out.write(`
|
|
61725
62993
|
${items.length} categor${items.length === 1 ? "y" : "ies"}.
|
|
61726
62994
|
`);
|
|
@@ -61745,7 +63013,7 @@ async function runVendorOwners(cfg) {
|
|
|
61745
63013
|
}
|
|
61746
63014
|
const rows = [{ cells: ["VENDOR ID", "OWNER ID"] }];
|
|
61747
63015
|
for (const o of ids) rows.push({ cells: [owners.id, String(o.owner_id)] });
|
|
61748
|
-
|
|
63016
|
+
writeTable39(cfg.out, rows);
|
|
61749
63017
|
cfg.out.write(`
|
|
61750
63018
|
${ids.length} owner(s).
|
|
61751
63019
|
`);
|
|
@@ -62147,7 +63415,7 @@ function printAlertRows(out, items) {
|
|
|
62147
63415
|
]
|
|
62148
63416
|
});
|
|
62149
63417
|
}
|
|
62150
|
-
|
|
63418
|
+
writeTable39(out, rows);
|
|
62151
63419
|
}
|
|
62152
63420
|
async function runAlertsList(cfg) {
|
|
62153
63421
|
if (cfg.params.status === void 0) {
|
|
@@ -62242,7 +63510,7 @@ async function runAlertsDismiss(cfg) {
|
|
|
62242
63510
|
});
|
|
62243
63511
|
}
|
|
62244
63512
|
}
|
|
62245
|
-
|
|
63513
|
+
writeTable39(cfg.out, rows);
|
|
62246
63514
|
cfg.out.write(
|
|
62247
63515
|
`
|
|
62248
63516
|
dismiss: ${cfg.alertIds.length - failed.length} ok, ${failed.length} failed.
|
|
@@ -62287,7 +63555,7 @@ async function runAlertSettingsGet(cfg) {
|
|
|
62287
63555
|
rows.push({
|
|
62288
63556
|
cells: ["user_ids", (s.user_ids ?? []).join(", ") || "(none)"]
|
|
62289
63557
|
});
|
|
62290
|
-
|
|
63558
|
+
writeTable39(cfg.out, rows);
|
|
62291
63559
|
}
|
|
62292
63560
|
async function runAlertSettingsUpdate(cfg) {
|
|
62293
63561
|
if (Object.keys(cfg.changes).length === 0) {
|
|
@@ -62372,7 +63640,7 @@ async function runContractCategories(cfg) {
|
|
|
62372
63640
|
}
|
|
62373
63641
|
const rows = [{ cells: ["VALUE", "DISPLAY NAME"] }];
|
|
62374
63642
|
for (const c of items) rows.push({ cells: [c.value, c.display_name] });
|
|
62375
|
-
|
|
63643
|
+
writeTable39(cfg.out, rows);
|
|
62376
63644
|
cfg.out.write(`
|
|
62377
63645
|
${items.length} categor${items.length === 1 ? "y" : "ies"}.
|
|
62378
63646
|
`);
|
|
@@ -62401,7 +63669,7 @@ async function runContractHistory(cfg) {
|
|
|
62401
63669
|
]
|
|
62402
63670
|
});
|
|
62403
63671
|
}
|
|
62404
|
-
|
|
63672
|
+
writeTable39(cfg.out, rows);
|
|
62405
63673
|
cfg.out.write(`
|
|
62406
63674
|
${items.length} change(s).
|
|
62407
63675
|
`);
|
|
@@ -62611,7 +63879,7 @@ var MIME_MAGIC = {
|
|
|
62611
63879
|
function magicMatches(buf, mime) {
|
|
62612
63880
|
return matchesAny(buf, MIME_MAGIC[mime] ?? []);
|
|
62613
63881
|
}
|
|
62614
|
-
function
|
|
63882
|
+
function writeTable39(out, rows) {
|
|
62615
63883
|
if (rows.length === 0) return;
|
|
62616
63884
|
const header = rows[0];
|
|
62617
63885
|
const cols = header.cells.length;
|
|
@@ -62705,7 +63973,7 @@ async function runBillingFrequenciesList(cfg) {
|
|
|
62705
63973
|
for (const bf of items) {
|
|
62706
63974
|
rows.push({ cells: [bf.name, String(bf.period_months), bf.id] });
|
|
62707
63975
|
}
|
|
62708
|
-
|
|
63976
|
+
writeTable39(cfg.out, rows);
|
|
62709
63977
|
}
|
|
62710
63978
|
async function runExtractFromFiles(cfg) {
|
|
62711
63979
|
if (cfg.files.length === 0) {
|
|
@@ -62937,7 +64205,7 @@ function printFileRows(out, items) {
|
|
|
62937
64205
|
]
|
|
62938
64206
|
});
|
|
62939
64207
|
}
|
|
62940
|
-
|
|
64208
|
+
writeTable39(out, rows);
|
|
62941
64209
|
}
|
|
62942
64210
|
async function runFilesUpload(cfg) {
|
|
62943
64211
|
if (cfg.files.length === 0) {
|
|
@@ -62978,7 +64246,7 @@ async function runFilesUpload(cfg) {
|
|
|
62978
64246
|
if (cfg.asJson) {
|
|
62979
64247
|
writeJSONIndented(cfg.out, { uploaded, failed: failures });
|
|
62980
64248
|
} else {
|
|
62981
|
-
|
|
64249
|
+
writeTable39(cfg.out, rows);
|
|
62982
64250
|
cfg.out.write(`
|
|
62983
64251
|
${uploaded.length} uploaded, ${failedPaths.length} failed.
|
|
62984
64252
|
`);
|
|
@@ -63111,7 +64379,7 @@ per-file results (${outcomes.length - failed.length} ok, ${failed.length} failed
|
|
|
63111
64379
|
for (const o of outcomes) {
|
|
63112
64380
|
rows.push({ cells: [o.path, o.ok ? "ok" : "FAILED", o.detail] });
|
|
63113
64381
|
}
|
|
63114
|
-
|
|
64382
|
+
writeTable39(err, rows);
|
|
63115
64383
|
if (abortedMidRun) {
|
|
63116
64384
|
err.write(
|
|
63117
64385
|
`
|
|
@@ -63250,7 +64518,7 @@ batch ${i + 1}/${batches.length} failed: ${msg}
|
|
|
63250
64518
|
]
|
|
63251
64519
|
});
|
|
63252
64520
|
}
|
|
63253
|
-
|
|
64521
|
+
writeTable39(cfg.out, rows);
|
|
63254
64522
|
}
|
|
63255
64523
|
});
|
|
63256
64524
|
}
|
|
@@ -63302,7 +64570,7 @@ async function runContractUpdate(cfg) {
|
|
|
63302
64570
|
String(updated.status)
|
|
63303
64571
|
]
|
|
63304
64572
|
});
|
|
63305
|
-
|
|
64573
|
+
writeTable39(cfg.out, rows);
|
|
63306
64574
|
}
|
|
63307
64575
|
var DESCRIBE_PREVIEW_ROWS3 = 5;
|
|
63308
64576
|
var ISO_DATE_RE = /^\d{4}-\d{2}-\d{2}$/;
|
|
@@ -63492,7 +64760,7 @@ function printContractRows(out, items) {
|
|
|
63492
64760
|
]
|
|
63493
64761
|
});
|
|
63494
64762
|
}
|
|
63495
|
-
|
|
64763
|
+
writeTable39(out, rows);
|
|
63496
64764
|
}
|
|
63497
64765
|
async function runContractsGet(cfg) {
|
|
63498
64766
|
const contract = await getContract(
|
|
@@ -63516,7 +64784,7 @@ function reportIdOutcomes(out, outcomes, verb) {
|
|
|
63516
64784
|
for (const o of outcomes) {
|
|
63517
64785
|
rows.push({ cells: [o.id, o.ok ? "ok" : "FAILED", o.detail] });
|
|
63518
64786
|
}
|
|
63519
|
-
|
|
64787
|
+
writeTable39(out, rows);
|
|
63520
64788
|
const failed = outcomes.filter((o) => !o.ok);
|
|
63521
64789
|
const okCount = outcomes.length - failed.length;
|
|
63522
64790
|
out.write(`
|
|
@@ -64268,7 +65536,7 @@ async function runRhConfigVersionTemplates(cfg) {
|
|
|
64268
65536
|
}
|
|
64269
65537
|
renderTemplateTable2(cfg.out, filteredData);
|
|
64270
65538
|
}
|
|
64271
|
-
function
|
|
65539
|
+
function writeTable40(out, rows) {
|
|
64272
65540
|
if (rows.length === 0) return;
|
|
64273
65541
|
const widths = [];
|
|
64274
65542
|
for (const r of rows) {
|
|
@@ -64317,7 +65585,7 @@ function renderConfigInfo(out, info) {
|
|
|
64317
65585
|
for (const t of info.tables) {
|
|
64318
65586
|
rows.push({ cells: [t] });
|
|
64319
65587
|
}
|
|
64320
|
-
|
|
65588
|
+
writeTable40(out, rows);
|
|
64321
65589
|
const n = info.tables.length;
|
|
64322
65590
|
out.write(`
|
|
64323
65591
|
(${n} table${n === 1 ? "" : "s"})
|
|
@@ -64340,7 +65608,7 @@ function renderTemplateTable2(out, templates) {
|
|
|
64340
65608
|
]
|
|
64341
65609
|
});
|
|
64342
65610
|
}
|
|
64343
|
-
|
|
65611
|
+
writeTable40(out, rows);
|
|
64344
65612
|
}
|
|
64345
65613
|
function parsePositiveIdArg(label, raw) {
|
|
64346
65614
|
const n = Number(raw);
|
|
@@ -64496,7 +65764,7 @@ async function runProductContentList(cfg) {
|
|
|
64496
65764
|
}
|
|
64497
65765
|
const rows = [["ID", "NAME", "TYPE"]];
|
|
64498
65766
|
for (const pc of resp) rows.push([String(pc.id), pc.name, pc.type]);
|
|
64499
|
-
|
|
65767
|
+
writeTable41(cfg.out, rows);
|
|
64500
65768
|
cfg.out.write(`
|
|
64501
65769
|
(${resp.length} row${plural(resp.length)})
|
|
64502
65770
|
`);
|
|
@@ -64584,7 +65852,7 @@ function countItems(body) {
|
|
|
64584
65852
|
for (const g of body) items += g.items.length;
|
|
64585
65853
|
return { items, groups: body.length };
|
|
64586
65854
|
}
|
|
64587
|
-
function
|
|
65855
|
+
function writeTable41(out, rows) {
|
|
64588
65856
|
if (rows.length === 0) return;
|
|
64589
65857
|
const widths = [];
|
|
64590
65858
|
for (const r of rows) {
|
|
@@ -64888,7 +66156,7 @@ function writeWarnings(out, warnings) {
|
|
|
64888
66156
|
for (const w of warnings) out.write(`warning: ${w}
|
|
64889
66157
|
`);
|
|
64890
66158
|
}
|
|
64891
|
-
function
|
|
66159
|
+
function writeTable42(out, rows) {
|
|
64892
66160
|
if (rows.length === 0) return;
|
|
64893
66161
|
const widths = [];
|
|
64894
66162
|
for (const r of rows) {
|
|
@@ -64923,7 +66191,7 @@ async function runTeamsList(cfg) {
|
|
|
64923
66191
|
for (const t of resp.teams) {
|
|
64924
66192
|
rows.push([String(t.team_id), t.name ?? "", t.support_email ?? "(none set)"]);
|
|
64925
66193
|
}
|
|
64926
|
-
|
|
66194
|
+
writeTable42(cfg.out, rows);
|
|
64927
66195
|
cfg.out.write(`
|
|
64928
66196
|
(${resp.teams.length} team${plural(resp.teams.length)})
|
|
64929
66197
|
`);
|
|
@@ -65346,7 +66614,7 @@ function renderSendgridStatus(out, resp, asJson) {
|
|
|
65346
66614
|
r.valid === true ? "yes" : r.valid === false ? "NO" : "-"
|
|
65347
66615
|
]);
|
|
65348
66616
|
}
|
|
65349
|
-
|
|
66617
|
+
writeTable42(out, rows);
|
|
65350
66618
|
for (const r of resp.records) {
|
|
65351
66619
|
if (r.valid === false && r.reason !== void 0 && r.reason !== null && r.reason !== "") {
|
|
65352
66620
|
out.write(` ${r.name}: ${r.reason}
|
|
@@ -66126,7 +67394,7 @@ function writeCloneReport(out, report) {
|
|
|
66126
67394
|
String(t.members_added.length) + (t.members_unmapped.length > 0 ? ` (${t.members_unmapped.length} unmapped)` : "")
|
|
66127
67395
|
]);
|
|
66128
67396
|
}
|
|
66129
|
-
|
|
67397
|
+
writeTable42(out, rows);
|
|
66130
67398
|
const tables = report.import_result.tables;
|
|
66131
67399
|
const counts = Object.entries(tables).filter(([, c]) => c.imported + c.skipped + c.updated > 0).map(([name, c]) => `${name}: ${c.imported} imported, ${c.skipped} skipped`);
|
|
66132
67400
|
out.write(`
|
|
@@ -66581,7 +67849,7 @@ function parsePaletteFile(raw) {
|
|
|
66581
67849
|
}
|
|
66582
67850
|
return payload;
|
|
66583
67851
|
}
|
|
66584
|
-
function
|
|
67852
|
+
function writeTable43(out, rows) {
|
|
66585
67853
|
if (rows.length === 0) return;
|
|
66586
67854
|
const widths = [];
|
|
66587
67855
|
for (const r of rows) {
|
|
@@ -66621,7 +67889,7 @@ function renderPalettesTable(out, palettes) {
|
|
|
66621
67889
|
]
|
|
66622
67890
|
});
|
|
66623
67891
|
}
|
|
66624
|
-
|
|
67892
|
+
writeTable43(out, rows);
|
|
66625
67893
|
}
|
|
66626
67894
|
function renderColorsPreview(colors) {
|
|
66627
67895
|
if (colors.length === 0) return "(none)";
|