@datarails-ai/dr-cli 1.6.73 → 1.6.75
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/README.md +12 -11
- package/dist/cli.js +930 -313
- package/dist/scopes-map.json +25 -1
- package/dist/skills/dr-cli/SKILL.md +6 -5
- package/dist/skills/dr-cli/reference/datamappers.md +6 -0
- package/dist/skills/dr-cli/reference/multi-product.md +1 -1
- package/dist/skills/dr-cli/reference/safety.md +3 -2
- package/dist/skills/dr-cli/reference/templates.md +1 -1
- package/dist/skills/dr-error-enrichment/SKILL.md +1 -1
- package/dist/skills/dr-error-enrichment/reference/groundcover.md +3 -2
- package/dist/skills/dr-error-enrichment/reference/safety-backup.md +2 -2
- package/dist/skills/dr-error-enrichment-improve/SKILL.md +1 -1
- package/dist/skills/dr-filebox-api-setup/SKILL.md +3 -3
- package/dist/skills/dr-switch-user/SKILL.md +3 -3
- package/dist/skills/fx-conversion-matrix/SKILL.md +1 -1
- package/dist/skills/mec-table-validation/SKILL.md +2 -2
- package/package.json +3 -2
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.75",
|
|
12
12
|
description: "Datarails CLI",
|
|
13
13
|
type: "module",
|
|
14
14
|
engines: {
|
|
@@ -38,10 +38,11 @@ var package_default = {
|
|
|
38
38
|
postinstall: "node scripts/postinstall.mjs"
|
|
39
39
|
},
|
|
40
40
|
dependencies: {
|
|
41
|
-
"@datarails-ai/dr-appspace-cli": "0.9.
|
|
41
|
+
"@datarails-ai/dr-appspace-cli": "0.9.7",
|
|
42
42
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
43
43
|
"@napi-rs/keyring": "^1.3.0",
|
|
44
44
|
commander: "^12.1.0",
|
|
45
|
+
"fast-xml-parser": "^5.11.2",
|
|
45
46
|
jszip: "^3.10.1",
|
|
46
47
|
"node-html-parser": "^6.1.13",
|
|
47
48
|
open: "^10.1.0",
|
|
@@ -66,7 +67,7 @@ var package_default = {
|
|
|
66
67
|
};
|
|
67
68
|
|
|
68
69
|
// src/buildInfo.ts
|
|
69
|
-
var BUILD_TIME = "2026-09-
|
|
70
|
+
var BUILD_TIME = "2026-09-30T12:50:28.608Z";
|
|
70
71
|
function formatBuildTime(iso) {
|
|
71
72
|
if (iso === "") return "";
|
|
72
73
|
const d = new Date(iso);
|
|
@@ -411,6 +412,7 @@ var ordered = [
|
|
|
411
412
|
{ key: "UK", host: "https://ukapp.datarails.com", subDomain: "uk" },
|
|
412
413
|
{ key: "CA", host: "https://caapp.datarails.com", subDomain: "canada" },
|
|
413
414
|
{ key: "EU", host: "https://euapp.datarails.com", subDomain: "eu" },
|
|
415
|
+
{ key: "STUDIO", host: "https://studio.datarails.com", subDomain: "studio" },
|
|
414
416
|
{ key: "DEV", host: "https://dev.datarails.com", subDomain: "dev" },
|
|
415
417
|
{ key: "DEV-1", host: "https://dev-1.datarails.com", subDomain: "dev-1" },
|
|
416
418
|
{ key: "TEST", host: "https://testapp.datarails.com", subDomain: "test" },
|
|
@@ -436,7 +438,7 @@ function list() {
|
|
|
436
438
|
function keys() {
|
|
437
439
|
return ordered.map((s) => s.key);
|
|
438
440
|
}
|
|
439
|
-
var PROD_KEYS = /* @__PURE__ */ new Set(["US", "US2", "UK", "CA", "EU", "DEMO"]);
|
|
441
|
+
var PROD_KEYS = /* @__PURE__ */ new Set(["US", "US2", "UK", "CA", "EU", "STUDIO", "DEMO"]);
|
|
440
442
|
function isProdServer(input) {
|
|
441
443
|
let server;
|
|
442
444
|
try {
|
|
@@ -577,11 +579,11 @@ var ScopeDeniedError = class extends Error {
|
|
|
577
579
|
return `${this.method} ${this.path}: this identity's credential scope does not allow it${needs}; run 'dr whoami' to see the scopes this identity carries`;
|
|
578
580
|
}
|
|
579
581
|
};
|
|
580
|
-
function parseScopeDenial(status2,
|
|
582
|
+
function parseScopeDenial(status2, text2) {
|
|
581
583
|
if (status2 !== 403) return void 0;
|
|
582
584
|
let body;
|
|
583
585
|
try {
|
|
584
|
-
body = JSON.parse(
|
|
586
|
+
body = JSON.parse(text2);
|
|
585
587
|
} catch {
|
|
586
588
|
return void 0;
|
|
587
589
|
}
|
|
@@ -698,10 +700,10 @@ function decodeJwtExpiration(token) {
|
|
|
698
700
|
}
|
|
699
701
|
return at;
|
|
700
702
|
}
|
|
701
|
-
function parseTokenBody(
|
|
703
|
+
function parseTokenBody(text2, label) {
|
|
702
704
|
let raw;
|
|
703
705
|
try {
|
|
704
|
-
raw = JSON.parse(
|
|
706
|
+
raw = JSON.parse(text2);
|
|
705
707
|
} catch (err) {
|
|
706
708
|
throw new Error(`jwt ${label} parse: ${msgOf3(err)}`);
|
|
707
709
|
}
|
|
@@ -727,11 +729,11 @@ async function mintJwt(host, sessionId, csrfToken, options) {
|
|
|
727
729
|
body: "{}",
|
|
728
730
|
signal: options?.signal
|
|
729
731
|
});
|
|
730
|
-
const
|
|
732
|
+
const text2 = await res.text();
|
|
731
733
|
if (!res.ok) {
|
|
732
|
-
throw new Error(`jwt mint: HTTP ${res.status}: ${truncate(
|
|
734
|
+
throw new Error(`jwt mint: HTTP ${res.status}: ${truncate(text2, TRUNCATE)}`);
|
|
733
735
|
}
|
|
734
|
-
const out = parseTokenBody(
|
|
736
|
+
const out = parseTokenBody(text2, "mint");
|
|
735
737
|
if (out.access === "") {
|
|
736
738
|
throw new Error("jwt mint: empty access token");
|
|
737
739
|
}
|
|
@@ -754,11 +756,11 @@ async function refreshJwt(host, refreshToken, options) {
|
|
|
754
756
|
body: JSON.stringify({ refresh: refreshToken }),
|
|
755
757
|
signal: options?.signal
|
|
756
758
|
});
|
|
757
|
-
const
|
|
759
|
+
const text2 = await res.text();
|
|
758
760
|
if (!res.ok) {
|
|
759
|
-
throw new Error(`jwt refresh: HTTP ${res.status}: ${truncate(
|
|
761
|
+
throw new Error(`jwt refresh: HTTP ${res.status}: ${truncate(text2, TRUNCATE)}`);
|
|
760
762
|
}
|
|
761
|
-
const out = parseTokenBody(
|
|
763
|
+
const out = parseTokenBody(text2, "refresh");
|
|
762
764
|
if (out.access === "") {
|
|
763
765
|
throw new Error("jwt refresh: empty access token");
|
|
764
766
|
}
|
|
@@ -778,11 +780,11 @@ async function refreshExternalJwt(host, refreshToken, options) {
|
|
|
778
780
|
body: JSON.stringify({ refresh: refreshToken }),
|
|
779
781
|
signal: options?.signal
|
|
780
782
|
});
|
|
781
|
-
const
|
|
783
|
+
const text2 = await res.text();
|
|
782
784
|
if (!res.ok) {
|
|
783
|
-
throw new Error(`jwt external refresh: HTTP ${res.status}: ${truncate(
|
|
785
|
+
throw new Error(`jwt external refresh: HTTP ${res.status}: ${truncate(text2, TRUNCATE)}`);
|
|
784
786
|
}
|
|
785
|
-
const out = parseTokenBody(
|
|
787
|
+
const out = parseTokenBody(text2, "refresh");
|
|
786
788
|
if (out.access === "") {
|
|
787
789
|
throw new Error("jwt external refresh: empty access token");
|
|
788
790
|
}
|
|
@@ -810,11 +812,11 @@ async function exchangeApiKey(host, apiKey, options) {
|
|
|
810
812
|
headers: { Authorization: `Bearer ${key}`, Accept: "application/json" },
|
|
811
813
|
signal: options?.signal
|
|
812
814
|
});
|
|
813
|
-
const
|
|
815
|
+
const text2 = await res.text();
|
|
814
816
|
if (!res.ok) {
|
|
815
817
|
let code;
|
|
816
818
|
try {
|
|
817
|
-
const value = JSON.parse(
|
|
819
|
+
const value = JSON.parse(text2)["error"];
|
|
818
820
|
if (value === "invalid_key" || value === "exchange_unavailable") code = value;
|
|
819
821
|
} catch {
|
|
820
822
|
}
|
|
@@ -822,7 +824,7 @@ async function exchangeApiKey(host, apiKey, options) {
|
|
|
822
824
|
}
|
|
823
825
|
let raw;
|
|
824
826
|
try {
|
|
825
|
-
raw = JSON.parse(
|
|
827
|
+
raw = JSON.parse(text2);
|
|
826
828
|
} catch {
|
|
827
829
|
throw new Error("api-key exchange parse: the response is not JSON");
|
|
828
830
|
}
|
|
@@ -871,21 +873,21 @@ async function loginAs(host, operatorAccessToken, userId, options) {
|
|
|
871
873
|
body: JSON.stringify(body),
|
|
872
874
|
signal: options?.signal
|
|
873
875
|
});
|
|
874
|
-
const
|
|
876
|
+
const text2 = await res.text();
|
|
875
877
|
if (!res.ok) {
|
|
876
878
|
let code;
|
|
877
879
|
let detail;
|
|
878
880
|
try {
|
|
879
|
-
const parsed2 = JSON.parse(
|
|
881
|
+
const parsed2 = JSON.parse(text2);
|
|
880
882
|
if (typeof parsed2["code"] === "string") code = parsed2["code"];
|
|
881
883
|
if (typeof parsed2["detail"] === "string") detail = parsed2["detail"];
|
|
882
884
|
} catch {
|
|
883
885
|
}
|
|
884
|
-
throw new LoginAsError(res.status, { code, detail, body: truncate(
|
|
886
|
+
throw new LoginAsError(res.status, { code, detail, body: truncate(text2, TRUNCATE) });
|
|
885
887
|
}
|
|
886
888
|
let raw;
|
|
887
889
|
try {
|
|
888
|
-
raw = JSON.parse(
|
|
890
|
+
raw = JSON.parse(text2);
|
|
889
891
|
} catch (err) {
|
|
890
892
|
throw new Error(`jwt loginas parse: ${msgOf3(err)}`);
|
|
891
893
|
}
|
|
@@ -2245,17 +2247,17 @@ var AuthorizedClient = class _AuthorizedClient {
|
|
|
2245
2247
|
body: fd,
|
|
2246
2248
|
signal: options?.signal
|
|
2247
2249
|
});
|
|
2248
|
-
const
|
|
2249
|
-
_AuthorizedClient.throwIfScopeDeniedBody("POST", path11, res.status,
|
|
2250
|
+
const text2 = await res.text();
|
|
2251
|
+
_AuthorizedClient.throwIfScopeDeniedBody("POST", path11, res.status, text2);
|
|
2250
2252
|
if (res.status === 401 || res.status === 403) {
|
|
2251
2253
|
throw new SessionExpiredError(`POST ${path11} (HTTP ${res.status})`);
|
|
2252
2254
|
}
|
|
2253
2255
|
if (res.status < 200 || res.status >= 300) {
|
|
2254
|
-
throw new Error(`POST ${path11}: HTTP ${res.status}: ${truncate2(
|
|
2256
|
+
throw new Error(`POST ${path11}: HTTP ${res.status}: ${truncate2(text2, 200)}`);
|
|
2255
2257
|
}
|
|
2256
|
-
if (
|
|
2258
|
+
if (text2 === "" || text2 === '""') return null;
|
|
2257
2259
|
try {
|
|
2258
|
-
return JSON.parse(
|
|
2260
|
+
return JSON.parse(text2);
|
|
2259
2261
|
} catch (err) {
|
|
2260
2262
|
const msg = err instanceof Error ? err.message : String(err);
|
|
2261
2263
|
throw new Error(`POST ${path11}: decode: ${msg}`);
|
|
@@ -2296,17 +2298,17 @@ var AuthorizedClient = class _AuthorizedClient {
|
|
|
2296
2298
|
body: fd,
|
|
2297
2299
|
signal: options?.signal
|
|
2298
2300
|
});
|
|
2299
|
-
const
|
|
2300
|
-
_AuthorizedClient.throwIfScopeDeniedBody("POST", path11, res.status,
|
|
2301
|
+
const text2 = await res.text();
|
|
2302
|
+
_AuthorizedClient.throwIfScopeDeniedBody("POST", path11, res.status, text2);
|
|
2301
2303
|
if (res.status === 401 || res.status === 403) {
|
|
2302
2304
|
throw new SessionExpiredError(`POST ${path11} (HTTP ${res.status})`);
|
|
2303
2305
|
}
|
|
2304
2306
|
if (res.status < 200 || res.status >= 300) {
|
|
2305
|
-
throw new Error(`POST ${path11}: HTTP ${res.status}: ${truncate2(
|
|
2307
|
+
throw new Error(`POST ${path11}: HTTP ${res.status}: ${truncate2(text2, 200)}`);
|
|
2306
2308
|
}
|
|
2307
|
-
if (
|
|
2309
|
+
if (text2 === "" || text2 === '""') return null;
|
|
2308
2310
|
try {
|
|
2309
|
-
return JSON.parse(
|
|
2311
|
+
return JSON.parse(text2);
|
|
2310
2312
|
} catch (err) {
|
|
2311
2313
|
const msg = err instanceof Error ? err.message : String(err);
|
|
2312
2314
|
throw new Error(`POST ${path11}: decode: ${msg}`);
|
|
@@ -2355,17 +2357,17 @@ var AuthorizedClient = class _AuthorizedClient {
|
|
|
2355
2357
|
body: fd,
|
|
2356
2358
|
signal: options?.signal
|
|
2357
2359
|
});
|
|
2358
|
-
const
|
|
2359
|
-
_AuthorizedClient.throwIfScopeDeniedBody("POST", path11, res.status,
|
|
2360
|
+
const text2 = await res.text();
|
|
2361
|
+
_AuthorizedClient.throwIfScopeDeniedBody("POST", path11, res.status, text2);
|
|
2360
2362
|
if (res.status === 401 || res.status === 403) {
|
|
2361
2363
|
throw new SessionExpiredError(`POST ${path11} (HTTP ${res.status})`);
|
|
2362
2364
|
}
|
|
2363
2365
|
if (res.status < 200 || res.status >= 300) {
|
|
2364
|
-
throw new Error(`POST ${path11}: HTTP ${res.status}: ${truncate2(
|
|
2366
|
+
throw new Error(`POST ${path11}: HTTP ${res.status}: ${truncate2(text2, 200)}`);
|
|
2365
2367
|
}
|
|
2366
|
-
if (
|
|
2368
|
+
if (text2 === "" || text2 === '""') return null;
|
|
2367
2369
|
try {
|
|
2368
|
-
return JSON.parse(
|
|
2370
|
+
return JSON.parse(text2);
|
|
2369
2371
|
} catch (err) {
|
|
2370
2372
|
const msg = err instanceof Error ? err.message : String(err);
|
|
2371
2373
|
throw new Error(`POST ${path11}: decode: ${msg}`);
|
|
@@ -2426,12 +2428,12 @@ var AuthorizedClient = class _AuthorizedClient {
|
|
|
2426
2428
|
}
|
|
2427
2429
|
}
|
|
2428
2430
|
if (this.isAuthRejected(res)) {
|
|
2429
|
-
const
|
|
2430
|
-
_AuthorizedClient.throwIfScopeDeniedBody(method, path11, res.status,
|
|
2431
|
+
const text3 = await res.text();
|
|
2432
|
+
_AuthorizedClient.throwIfScopeDeniedBody(method, path11, res.status, text3);
|
|
2431
2433
|
if (refreshed || triedSessionOnly) {
|
|
2432
2434
|
const attempted = refreshed ? "session-only retry and JWT refresh" : "session-only retry";
|
|
2433
2435
|
throw new Error(
|
|
2434
|
-
`${method} ${path11}: HTTP ${res.status} after ${attempted} (authenticated, but endpoint rejected \u2014 check permissions, tenant/org context, or body): ${truncate2(
|
|
2436
|
+
`${method} ${path11}: HTTP ${res.status} after ${attempted} (authenticated, but endpoint rejected \u2014 check permissions, tenant/org context, or body): ${truncate2(text3, 200)}`
|
|
2435
2437
|
);
|
|
2436
2438
|
}
|
|
2437
2439
|
if (refreshErr !== void 0) {
|
|
@@ -2440,17 +2442,17 @@ var AuthorizedClient = class _AuthorizedClient {
|
|
|
2440
2442
|
}
|
|
2441
2443
|
throw new SessionExpiredError(`${method} ${path11} (HTTP ${res.status})`);
|
|
2442
2444
|
}
|
|
2443
|
-
const
|
|
2445
|
+
const text2 = await res.text();
|
|
2444
2446
|
if (res.status < 200 || res.status >= 300) {
|
|
2445
|
-
throw new Error(`${method} ${path11}: HTTP ${res.status}: ${truncate2(
|
|
2447
|
+
throw new Error(`${method} ${path11}: HTTP ${res.status}: ${truncate2(text2, 200)}`);
|
|
2446
2448
|
}
|
|
2447
2449
|
try {
|
|
2448
2450
|
await this._store.touch(this._serverKey, this._email);
|
|
2449
2451
|
} catch {
|
|
2450
2452
|
}
|
|
2451
|
-
if (
|
|
2453
|
+
if (text2 === "" || text2 === '""') return null;
|
|
2452
2454
|
try {
|
|
2453
|
-
return JSON.parse(
|
|
2455
|
+
return JSON.parse(text2);
|
|
2454
2456
|
} catch (err) {
|
|
2455
2457
|
const msg = err instanceof Error ? err.message : String(err);
|
|
2456
2458
|
throw new Error(`${method} ${path11}: decode: ${msg}`);
|
|
@@ -2522,18 +2524,18 @@ var AuthorizedClient = class _AuthorizedClient {
|
|
|
2522
2524
|
*/
|
|
2523
2525
|
static async throwIfScopeDenied(method, path11, res) {
|
|
2524
2526
|
if (res.status !== 403) return;
|
|
2525
|
-
let
|
|
2527
|
+
let text2;
|
|
2526
2528
|
try {
|
|
2527
|
-
|
|
2529
|
+
text2 = await res.clone().text();
|
|
2528
2530
|
} catch {
|
|
2529
2531
|
return;
|
|
2530
2532
|
}
|
|
2531
|
-
_AuthorizedClient.throwIfScopeDeniedBody(method, path11, res.status,
|
|
2533
|
+
_AuthorizedClient.throwIfScopeDeniedBody(method, path11, res.status, text2);
|
|
2532
2534
|
}
|
|
2533
2535
|
/** {@link AuthorizedClient.throwIfScopeDenied} for a body already in hand — the multipart
|
|
2534
2536
|
* methods and `requestJson`'s final branch have read theirs and must not read it twice. */
|
|
2535
|
-
static throwIfScopeDeniedBody(method, path11, status2,
|
|
2536
|
-
const denial = parseScopeDenial(status2,
|
|
2537
|
+
static throwIfScopeDeniedBody(method, path11, status2, text2) {
|
|
2538
|
+
const denial = parseScopeDenial(status2, text2);
|
|
2537
2539
|
if (denial !== void 0) throw new ScopeDeniedError(method, path11, denial.code);
|
|
2538
2540
|
}
|
|
2539
2541
|
/** True iff `res` is the auth-rejection signal (401 or 403). */
|
|
@@ -3424,9 +3426,9 @@ async function commandExists(cmd) {
|
|
|
3424
3426
|
const probe = process.platform === "win32" ? "where" : "which";
|
|
3425
3427
|
return new Promise((resolve3) => {
|
|
3426
3428
|
try {
|
|
3427
|
-
const
|
|
3428
|
-
|
|
3429
|
-
|
|
3429
|
+
const child2 = spawn(probe, [cmd], { stdio: "ignore" });
|
|
3430
|
+
child2.on("error", () => resolve3(false));
|
|
3431
|
+
child2.on("close", (code) => resolve3(code === 0));
|
|
3430
3432
|
} catch {
|
|
3431
3433
|
resolve3(false);
|
|
3432
3434
|
}
|
|
@@ -3446,20 +3448,20 @@ async function realEnv() {
|
|
|
3446
3448
|
}
|
|
3447
3449
|
function spawnCapture(cmd, args) {
|
|
3448
3450
|
return new Promise((resolve3, reject) => {
|
|
3449
|
-
const
|
|
3451
|
+
const child2 = spawn(cmd, args, {
|
|
3450
3452
|
stdio: ["ignore", "pipe", "pipe"],
|
|
3451
3453
|
windowsHide: false
|
|
3452
3454
|
});
|
|
3453
3455
|
let stdout = "";
|
|
3454
3456
|
let stderr = "";
|
|
3455
|
-
|
|
3457
|
+
child2.stdout.on("data", (c) => {
|
|
3456
3458
|
stdout += c.toString("utf8");
|
|
3457
3459
|
});
|
|
3458
|
-
|
|
3460
|
+
child2.stderr.on("data", (c) => {
|
|
3459
3461
|
stderr += c.toString("utf8");
|
|
3460
3462
|
});
|
|
3461
|
-
|
|
3462
|
-
|
|
3463
|
+
child2.on("error", reject);
|
|
3464
|
+
child2.on("close", (code) => resolve3({ code: code ?? 0, stdout, stderr }));
|
|
3463
3465
|
});
|
|
3464
3466
|
}
|
|
3465
3467
|
function ttyPrompt(spec, io = { input: process.stdin, output: process.stderr }) {
|
|
@@ -4362,6 +4364,7 @@ async function setupCall(serverFlag, accountFlag, options = {}) {
|
|
|
4362
4364
|
let deadline = Date.now() + timeoutMs;
|
|
4363
4365
|
let timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
4364
4366
|
let cleared = false;
|
|
4367
|
+
let paused = false;
|
|
4365
4368
|
let client;
|
|
4366
4369
|
try {
|
|
4367
4370
|
client = await AuthorizedClient.create(store, key, email, {
|
|
@@ -4388,11 +4391,17 @@ async function setupCall(serverFlag, accountFlag, options = {}) {
|
|
|
4388
4391
|
if (cleared || controller.signal.aborted) return;
|
|
4389
4392
|
if (!Number.isFinite(ms) || ms <= 0) return;
|
|
4390
4393
|
const next = Date.now() + ms;
|
|
4391
|
-
if (next <= deadline) return;
|
|
4394
|
+
if (!paused && next <= deadline) return;
|
|
4395
|
+
paused = false;
|
|
4392
4396
|
clearTimeout(timer);
|
|
4393
4397
|
deadline = next;
|
|
4394
4398
|
timer = setTimeout(() => controller.abort(), ms);
|
|
4395
4399
|
},
|
|
4400
|
+
pauseTimeout: () => {
|
|
4401
|
+
if (cleared || controller.signal.aborted) return;
|
|
4402
|
+
paused = true;
|
|
4403
|
+
clearTimeout(timer);
|
|
4404
|
+
},
|
|
4396
4405
|
cleanup: () => {
|
|
4397
4406
|
if (cleared) return;
|
|
4398
4407
|
cleared = true;
|
|
@@ -4589,10 +4598,10 @@ function parsePendingCommands(v, pending) {
|
|
|
4589
4598
|
}
|
|
4590
4599
|
return out;
|
|
4591
4600
|
}
|
|
4592
|
-
function parseScopesMap(
|
|
4601
|
+
function parseScopesMap(text2) {
|
|
4593
4602
|
let raw;
|
|
4594
4603
|
try {
|
|
4595
|
-
raw = JSON.parse(
|
|
4604
|
+
raw = JSON.parse(text2);
|
|
4596
4605
|
} catch {
|
|
4597
4606
|
return void 0;
|
|
4598
4607
|
}
|
|
@@ -4626,13 +4635,13 @@ function parseScopesMap(text) {
|
|
|
4626
4635
|
return map;
|
|
4627
4636
|
}
|
|
4628
4637
|
function loadScopesMap(here = path3.dirname(fileURLToPath(import.meta.url))) {
|
|
4629
|
-
let
|
|
4638
|
+
let text2;
|
|
4630
4639
|
try {
|
|
4631
|
-
|
|
4640
|
+
text2 = readFileSync(path3.join(here, "scopes-map.json"), "utf8");
|
|
4632
4641
|
} catch {
|
|
4633
4642
|
return void 0;
|
|
4634
4643
|
}
|
|
4635
|
-
return parseScopesMap(
|
|
4644
|
+
return parseScopesMap(text2);
|
|
4636
4645
|
}
|
|
4637
4646
|
function scopesMapKey(cmd) {
|
|
4638
4647
|
const names = [];
|
|
@@ -4652,10 +4661,10 @@ function commandPathOf(argv, root) {
|
|
|
4652
4661
|
if (takesValue(token, cmd)) i += 1;
|
|
4653
4662
|
continue;
|
|
4654
4663
|
}
|
|
4655
|
-
const
|
|
4656
|
-
if (
|
|
4657
|
-
names.push(
|
|
4658
|
-
cmd =
|
|
4664
|
+
const child2 = childNamed(cmd, token);
|
|
4665
|
+
if (child2 === void 0) break;
|
|
4666
|
+
names.push(child2.name());
|
|
4667
|
+
cmd = child2;
|
|
4659
4668
|
}
|
|
4660
4669
|
return names.join(" ");
|
|
4661
4670
|
}
|
|
@@ -4672,11 +4681,11 @@ function takesValue(flag, cmd) {
|
|
|
4672
4681
|
return declaredWithValueBelow(flag, cmd);
|
|
4673
4682
|
}
|
|
4674
4683
|
function declaredWithValueBelow(flag, cmd) {
|
|
4675
|
-
for (const
|
|
4676
|
-
for (const opt of
|
|
4684
|
+
for (const child2 of cmd.commands) {
|
|
4685
|
+
for (const opt of child2.options) {
|
|
4677
4686
|
if ((opt.short === flag || opt.long === flag) && (opt.required || opt.optional)) return true;
|
|
4678
4687
|
}
|
|
4679
|
-
if (declaredWithValueBelow(flag,
|
|
4688
|
+
if (declaredWithValueBelow(flag, child2)) return true;
|
|
4680
4689
|
}
|
|
4681
4690
|
return false;
|
|
4682
4691
|
}
|
|
@@ -5011,14 +5020,14 @@ async function requestDeviceCode(host, options) {
|
|
|
5011
5020
|
body: body.toString(),
|
|
5012
5021
|
signal: options?.signal
|
|
5013
5022
|
});
|
|
5014
|
-
const
|
|
5023
|
+
const text2 = await res.text();
|
|
5015
5024
|
if (!res.ok) {
|
|
5016
5025
|
const hint = flow === "v2" && res.status === 429 ? " (too many logins from this address: wait a minute and run `dr login` again)" : "";
|
|
5017
|
-
throw new Error(`device/code failed: ${res.status} ${
|
|
5026
|
+
throw new Error(`device/code failed: ${res.status} ${text2.trim()}${hint}`);
|
|
5018
5027
|
}
|
|
5019
5028
|
let raw;
|
|
5020
5029
|
try {
|
|
5021
|
-
raw = JSON.parse(
|
|
5030
|
+
raw = JSON.parse(text2);
|
|
5022
5031
|
} catch (err) {
|
|
5023
5032
|
const msg = err instanceof Error ? err.message : String(err);
|
|
5024
5033
|
throw new Error(`device/code parse: ${msg}`);
|
|
@@ -5049,10 +5058,10 @@ var defaultSleep = (ms, signal) => new Promise((resolve3, reject) => {
|
|
|
5049
5058
|
{ once: true }
|
|
5050
5059
|
);
|
|
5051
5060
|
});
|
|
5052
|
-
function parseObject(
|
|
5061
|
+
function parseObject(text2) {
|
|
5053
5062
|
let raw;
|
|
5054
5063
|
try {
|
|
5055
|
-
raw = JSON.parse(
|
|
5064
|
+
raw = JSON.parse(text2);
|
|
5056
5065
|
} catch (err) {
|
|
5057
5066
|
const msg = err instanceof Error ? err.message : String(err);
|
|
5058
5067
|
throw new Error(`token parse: ${msg}`);
|
|
@@ -5062,8 +5071,8 @@ function parseObject(text) {
|
|
|
5062
5071
|
}
|
|
5063
5072
|
return raw;
|
|
5064
5073
|
}
|
|
5065
|
-
function parseTokenResponse(
|
|
5066
|
-
const obj = parseObject(
|
|
5074
|
+
function parseTokenResponse(text2) {
|
|
5075
|
+
const obj = parseObject(text2);
|
|
5067
5076
|
const tok = {
|
|
5068
5077
|
sessionId: typeof obj.session_id === "string" ? obj.session_id : "",
|
|
5069
5078
|
csrfToken: typeof obj.csrf_token === "string" ? obj.csrf_token : ""
|
|
@@ -5073,10 +5082,10 @@ function parseTokenResponse(text) {
|
|
|
5073
5082
|
}
|
|
5074
5083
|
return tok;
|
|
5075
5084
|
}
|
|
5076
|
-
function tryParseErrorCode(
|
|
5085
|
+
function tryParseErrorCode(text2) {
|
|
5077
5086
|
let raw;
|
|
5078
5087
|
try {
|
|
5079
|
-
raw = JSON.parse(
|
|
5088
|
+
raw = JSON.parse(text2);
|
|
5080
5089
|
} catch {
|
|
5081
5090
|
return "";
|
|
5082
5091
|
}
|
|
@@ -5085,8 +5094,8 @@ function tryParseErrorCode(text) {
|
|
|
5085
5094
|
return typeof errVal === "string" ? errVal : "";
|
|
5086
5095
|
}
|
|
5087
5096
|
async function pollForToken(host, deviceCode, options = {}) {
|
|
5088
|
-
return poll(host, PATHS.legacy.token, deviceCode, options, (
|
|
5089
|
-
const tok = parseTokenResponse(
|
|
5097
|
+
return poll(host, PATHS.legacy.token, deviceCode, options, (text2) => {
|
|
5098
|
+
const tok = parseTokenResponse(text2);
|
|
5090
5099
|
if (!tok.sessionId || !tok.csrfToken) {
|
|
5091
5100
|
throw new Error("token response missing session_id or csrf_token");
|
|
5092
5101
|
}
|
|
@@ -5094,8 +5103,8 @@ async function pollForToken(host, deviceCode, options = {}) {
|
|
|
5094
5103
|
});
|
|
5095
5104
|
}
|
|
5096
5105
|
async function pollForV2Token(host, deviceCode, options = {}) {
|
|
5097
|
-
return poll(host, PATHS.v2.token, deviceCode, options, (
|
|
5098
|
-
const obj = parseObject(
|
|
5106
|
+
return poll(host, PATHS.v2.token, deviceCode, options, (text2) => {
|
|
5107
|
+
const obj = parseObject(text2);
|
|
5099
5108
|
const access = typeof obj.access === "string" ? obj.access : "";
|
|
5100
5109
|
const refresh = typeof obj.refresh === "string" ? obj.refresh : "";
|
|
5101
5110
|
if (access === "" || refresh === "") {
|
|
@@ -5108,7 +5117,7 @@ async function poll(host, path11, deviceCode, options, onSuccess) {
|
|
|
5108
5117
|
const interval = options.interval ?? 2e3;
|
|
5109
5118
|
const maxWait = options.maxWait ?? 6e5;
|
|
5110
5119
|
const now = options.now ?? Date.now;
|
|
5111
|
-
const
|
|
5120
|
+
const sleep4 = options.sleep ?? defaultSleep;
|
|
5112
5121
|
const signal = options.signal;
|
|
5113
5122
|
const base = host.replace(/\/+$/, "");
|
|
5114
5123
|
const deadline = now() + maxWait;
|
|
@@ -5130,19 +5139,19 @@ async function poll(host, path11, deviceCode, options, onSuccess) {
|
|
|
5130
5139
|
body: body.toString(),
|
|
5131
5140
|
signal
|
|
5132
5141
|
});
|
|
5133
|
-
const
|
|
5142
|
+
const text2 = await res.text();
|
|
5134
5143
|
if (res.ok) {
|
|
5135
|
-
return onSuccess(
|
|
5144
|
+
return onSuccess(text2);
|
|
5136
5145
|
}
|
|
5137
|
-
const errCode = tryParseErrorCode(
|
|
5146
|
+
const errCode = tryParseErrorCode(text2);
|
|
5138
5147
|
if (errCode === "authorization_pending" || errCode === "slow_down") {
|
|
5139
|
-
await
|
|
5148
|
+
await sleep4(interval, signal);
|
|
5140
5149
|
continue;
|
|
5141
5150
|
}
|
|
5142
5151
|
if (errCode) {
|
|
5143
5152
|
throw new Error(`token error: ${errCode}`);
|
|
5144
5153
|
}
|
|
5145
|
-
throw new Error(`token HTTP ${res.status}: ${
|
|
5154
|
+
throw new Error(`token HTTP ${res.status}: ${text2.trim()}`);
|
|
5146
5155
|
}
|
|
5147
5156
|
}
|
|
5148
5157
|
|
|
@@ -5642,11 +5651,11 @@ var UserExistsError = class extends Error {
|
|
|
5642
5651
|
async function create(client, payload, options) {
|
|
5643
5652
|
const path11 = "/api/it/users";
|
|
5644
5653
|
const res = await client.do("POST", path11, JSON.stringify(payload), options);
|
|
5645
|
-
const
|
|
5654
|
+
const text2 = await res.text();
|
|
5646
5655
|
if (res.status >= 200 && res.status < 300) {
|
|
5647
5656
|
let parsed2;
|
|
5648
5657
|
try {
|
|
5649
|
-
parsed2 = JSON.parse(
|
|
5658
|
+
parsed2 = JSON.parse(text2);
|
|
5650
5659
|
} catch (err) {
|
|
5651
5660
|
const msg = err instanceof Error ? err.message : String(err);
|
|
5652
5661
|
throw new Error(`POST ${path11}: decode: ${msg}`);
|
|
@@ -5664,7 +5673,7 @@ async function create(client, payload, options) {
|
|
|
5664
5673
|
if (res.status === 400) {
|
|
5665
5674
|
let details;
|
|
5666
5675
|
try {
|
|
5667
|
-
const body = JSON.parse(
|
|
5676
|
+
const body = JSON.parse(text2);
|
|
5668
5677
|
if (typeof body.details === "string") details = body.details;
|
|
5669
5678
|
} catch {
|
|
5670
5679
|
}
|
|
@@ -5672,23 +5681,23 @@ async function create(client, payload, options) {
|
|
|
5672
5681
|
throw new UserExistsError(payload.email);
|
|
5673
5682
|
}
|
|
5674
5683
|
}
|
|
5675
|
-
throw new Error(`POST ${path11}: HTTP ${res.status}: ${truncate4(
|
|
5684
|
+
throw new Error(`POST ${path11}: HTTP ${res.status}: ${truncate4(text2, 200)}`);
|
|
5676
5685
|
}
|
|
5677
5686
|
async function registerIdentity(client, id, options) {
|
|
5678
5687
|
const path11 = `/api/it/users/${id}/register_identity`;
|
|
5679
5688
|
const res = await client.do("PUT", path11, void 0, options);
|
|
5680
|
-
const
|
|
5689
|
+
const text2 = await res.text();
|
|
5681
5690
|
if (res.status >= 200 && res.status < 300) {
|
|
5682
5691
|
let body;
|
|
5683
5692
|
try {
|
|
5684
|
-
body = JSON.parse(
|
|
5693
|
+
body = JSON.parse(text2);
|
|
5685
5694
|
} catch (err) {
|
|
5686
5695
|
const msg = err instanceof Error ? err.message : String(err);
|
|
5687
5696
|
throw new Error(`PUT ${path11}: decode: ${msg}`);
|
|
5688
5697
|
}
|
|
5689
5698
|
if (typeof body.sent !== "boolean") {
|
|
5690
5699
|
throw new Error(
|
|
5691
|
-
`PUT ${path11}: expected a boolean "sent" in the 2xx body, got ${truncate4(
|
|
5700
|
+
`PUT ${path11}: expected a boolean "sent" in the 2xx body, got ${truncate4(text2, 200)}`
|
|
5692
5701
|
);
|
|
5693
5702
|
}
|
|
5694
5703
|
return body.sent ? { status: "registered" } : { status: "already_exists" };
|
|
@@ -5696,42 +5705,42 @@ async function registerIdentity(client, id, options) {
|
|
|
5696
5705
|
if (res.status === 502) {
|
|
5697
5706
|
let reason;
|
|
5698
5707
|
try {
|
|
5699
|
-
const body = JSON.parse(
|
|
5708
|
+
const body = JSON.parse(text2);
|
|
5700
5709
|
if (typeof body.reason === "string") reason = body.reason;
|
|
5701
5710
|
} catch {
|
|
5702
5711
|
}
|
|
5703
5712
|
return { status: "failed", ...reason !== void 0 ? { reason } : {} };
|
|
5704
5713
|
}
|
|
5705
|
-
throw new Error(`PUT ${path11}: HTTP ${res.status}: ${truncate4(
|
|
5714
|
+
throw new Error(`PUT ${path11}: HTTP ${res.status}: ${truncate4(text2, 200)}`);
|
|
5706
5715
|
}
|
|
5707
5716
|
async function assignPermissionGroups(client, id, groupIds, options) {
|
|
5708
5717
|
const path11 = `/api/it/users/${id}/permission_groups`;
|
|
5709
5718
|
const body = JSON.stringify({ permission_groups: groupIds });
|
|
5710
5719
|
const res = await client.do("POST", path11, body, options);
|
|
5711
|
-
const
|
|
5720
|
+
const text2 = await res.text();
|
|
5712
5721
|
if (res.status >= 200 && res.status < 300) {
|
|
5713
5722
|
return;
|
|
5714
5723
|
}
|
|
5715
|
-
throw new Error(`POST ${path11}: HTTP ${res.status}: ${truncate4(
|
|
5724
|
+
throw new Error(`POST ${path11}: HTTP ${res.status}: ${truncate4(text2, 200)}`);
|
|
5716
5725
|
}
|
|
5717
5726
|
async function updateUserRole(client, id, role, options) {
|
|
5718
5727
|
const path11 = `/api/it/users/${id}/permissions`;
|
|
5719
5728
|
const body = JSON.stringify({ role });
|
|
5720
5729
|
const res = await client.do("PUT", path11, body, options);
|
|
5721
|
-
const
|
|
5730
|
+
const text2 = await res.text();
|
|
5722
5731
|
if (res.status >= 200 && res.status < 300) {
|
|
5723
5732
|
return;
|
|
5724
5733
|
}
|
|
5725
|
-
throw new Error(`PUT ${path11}: HTTP ${res.status}: ${truncate4(
|
|
5734
|
+
throw new Error(`PUT ${path11}: HTTP ${res.status}: ${truncate4(text2, 200)}`);
|
|
5726
5735
|
}
|
|
5727
5736
|
async function removePermissionGroup(client, id, groupId, options) {
|
|
5728
5737
|
const path11 = `/api/it/users/${id}/permission_groups/${groupId}`;
|
|
5729
5738
|
const res = await client.do("DELETE", path11, void 0, options);
|
|
5730
|
-
const
|
|
5739
|
+
const text2 = await res.text();
|
|
5731
5740
|
if (res.status >= 200 && res.status < 300) {
|
|
5732
5741
|
return;
|
|
5733
5742
|
}
|
|
5734
|
-
throw new Error(`DELETE ${path11}: HTTP ${res.status}: ${truncate4(
|
|
5743
|
+
throw new Error(`DELETE ${path11}: HTTP ${res.status}: ${truncate4(text2, 200)}`);
|
|
5735
5744
|
}
|
|
5736
5745
|
var PasswordValidationError = class extends Error {
|
|
5737
5746
|
errors;
|
|
@@ -5751,11 +5760,11 @@ async function setPassword(client, id, password, options) {
|
|
|
5751
5760
|
await res.text();
|
|
5752
5761
|
return;
|
|
5753
5762
|
}
|
|
5754
|
-
const
|
|
5763
|
+
const text2 = await res.text();
|
|
5755
5764
|
if (res.status === 400) {
|
|
5756
5765
|
let parsed2;
|
|
5757
5766
|
try {
|
|
5758
|
-
parsed2 = JSON.parse(
|
|
5767
|
+
parsed2 = JSON.parse(text2);
|
|
5759
5768
|
} catch {
|
|
5760
5769
|
}
|
|
5761
5770
|
if (typeof parsed2 === "object" && parsed2 !== null && "password" in parsed2 && Array.isArray(parsed2.password)) {
|
|
@@ -5764,7 +5773,7 @@ async function setPassword(client, id, password, options) {
|
|
|
5764
5773
|
throw new PasswordValidationError(messages);
|
|
5765
5774
|
}
|
|
5766
5775
|
}
|
|
5767
|
-
throw new Error(`PUT ${path11}: HTTP ${res.status}: ${truncate4(
|
|
5776
|
+
throw new Error(`PUT ${path11}: HTTP ${res.status}: ${truncate4(text2, 200)}`);
|
|
5768
5777
|
}
|
|
5769
5778
|
var EmailInUseError = class extends Error {
|
|
5770
5779
|
email;
|
|
@@ -5782,14 +5791,14 @@ async function updateUserEmail(client, id, newEmail, options) {
|
|
|
5782
5791
|
excel_online_email: current.profile?.excel_online_email ?? null
|
|
5783
5792
|
});
|
|
5784
5793
|
const res = await client.do("PUT", path11, body, options);
|
|
5785
|
-
const
|
|
5794
|
+
const text2 = await res.text();
|
|
5786
5795
|
if (res.status >= 200 && res.status < 300) {
|
|
5787
5796
|
return { id, email: newEmail, previousEmail: current.email };
|
|
5788
5797
|
}
|
|
5789
|
-
if (res.status === 400 && /already in use/i.test(
|
|
5798
|
+
if (res.status === 400 && /already in use/i.test(text2)) {
|
|
5790
5799
|
throw new EmailInUseError(newEmail);
|
|
5791
5800
|
}
|
|
5792
|
-
throw new Error(`PUT ${path11}: HTTP ${res.status}: ${truncate4(
|
|
5801
|
+
throw new Error(`PUT ${path11}: HTTP ${res.status}: ${truncate4(text2, 200)}`);
|
|
5793
5802
|
}
|
|
5794
5803
|
var StoredEmailInvalidError = class extends Error {
|
|
5795
5804
|
id;
|
|
@@ -5813,7 +5822,7 @@ async function setEmailNotifications(client, id, enabled, options) {
|
|
|
5813
5822
|
excel_online_email: current.profile?.excel_online_email ?? null
|
|
5814
5823
|
});
|
|
5815
5824
|
const res = await client.do("PUT", path11, body, options);
|
|
5816
|
-
const
|
|
5825
|
+
const text2 = await res.text();
|
|
5817
5826
|
if (res.status >= 200 && res.status < 300) {
|
|
5818
5827
|
return {
|
|
5819
5828
|
id,
|
|
@@ -5822,10 +5831,10 @@ async function setEmailNotifications(client, id, enabled, options) {
|
|
|
5822
5831
|
blocked: current.profile?.is_blocked === true
|
|
5823
5832
|
};
|
|
5824
5833
|
}
|
|
5825
|
-
if (res.status === 400 && /valid email address/i.test(
|
|
5834
|
+
if (res.status === 400 && /valid email address/i.test(text2)) {
|
|
5826
5835
|
throw new StoredEmailInvalidError(id, current.email);
|
|
5827
5836
|
}
|
|
5828
|
-
throw new Error(`PUT ${path11}: HTTP ${res.status}: ${truncate4(
|
|
5837
|
+
throw new Error(`PUT ${path11}: HTTP ${res.status}: ${truncate4(text2, 200)}`);
|
|
5829
5838
|
}
|
|
5830
5839
|
async function getCanLoginAs(client, params = {}, options) {
|
|
5831
5840
|
const qs = new URLSearchParams();
|
|
@@ -7063,66 +7072,66 @@ async function listPermissionGroups(client, options) {
|
|
|
7063
7072
|
async function createPermissionGroup(client, payload, options) {
|
|
7064
7073
|
const path11 = "/api/it/permission_groups";
|
|
7065
7074
|
const res = await client.do("POST", path11, JSON.stringify(payload), options);
|
|
7066
|
-
const
|
|
7075
|
+
const text2 = await res.text();
|
|
7067
7076
|
if (res.status < 200 || res.status >= 300) {
|
|
7068
|
-
throw new Error(`POST ${path11}: HTTP ${res.status}: ${truncate4(
|
|
7077
|
+
throw new Error(`POST ${path11}: HTTP ${res.status}: ${truncate4(text2, 200)}`);
|
|
7069
7078
|
}
|
|
7070
|
-
return parsePermissionGroup("POST", path11,
|
|
7079
|
+
return parsePermissionGroup("POST", path11, text2);
|
|
7071
7080
|
}
|
|
7072
|
-
function parsePermissionGroup(method, path11,
|
|
7081
|
+
function parsePermissionGroup(method, path11, text2) {
|
|
7073
7082
|
try {
|
|
7074
|
-
return JSON.parse(
|
|
7083
|
+
return JSON.parse(text2);
|
|
7075
7084
|
} catch (err) {
|
|
7076
7085
|
const msg = err instanceof Error ? err.message : String(err);
|
|
7077
|
-
throw new Error(`${method} ${path11}: decode: ${msg} (body: ${truncate4(
|
|
7086
|
+
throw new Error(`${method} ${path11}: decode: ${msg} (body: ${truncate4(text2, 200)})`);
|
|
7078
7087
|
}
|
|
7079
7088
|
}
|
|
7080
7089
|
async function getPermissionGroup(client, id, options) {
|
|
7081
7090
|
const path11 = `/api/it/permission_groups/${id}`;
|
|
7082
7091
|
const res = await client.do("GET", path11, void 0, options);
|
|
7083
|
-
const
|
|
7092
|
+
const text2 = await res.text();
|
|
7084
7093
|
if (res.status < 200 || res.status >= 300) {
|
|
7085
|
-
throw new Error(`GET ${path11}: HTTP ${res.status}: ${truncate4(
|
|
7094
|
+
throw new Error(`GET ${path11}: HTTP ${res.status}: ${truncate4(text2, 200)}`);
|
|
7086
7095
|
}
|
|
7087
|
-
return parsePermissionGroup("GET", path11,
|
|
7096
|
+
return parsePermissionGroup("GET", path11, text2);
|
|
7088
7097
|
}
|
|
7089
7098
|
async function updatePermissionGroup(client, id, name, options) {
|
|
7090
7099
|
const path11 = `/api/it/permission_groups/${id}`;
|
|
7091
7100
|
const res = await client.do("PUT", path11, JSON.stringify({ name }), options);
|
|
7092
|
-
const
|
|
7101
|
+
const text2 = await res.text();
|
|
7093
7102
|
if (res.status < 200 || res.status >= 300) {
|
|
7094
|
-
throw new Error(`PUT ${path11}: HTTP ${res.status}: ${truncate4(
|
|
7103
|
+
throw new Error(`PUT ${path11}: HTTP ${res.status}: ${truncate4(text2, 200)}`);
|
|
7095
7104
|
}
|
|
7096
|
-
return parsePermissionGroup("PUT", path11,
|
|
7105
|
+
return parsePermissionGroup("PUT", path11, text2);
|
|
7097
7106
|
}
|
|
7098
7107
|
async function deletePermissionGroup(client, id, options) {
|
|
7099
7108
|
const path11 = `/api/it/permission_groups/${id}`;
|
|
7100
7109
|
const res = await client.do("DELETE", path11, void 0, options);
|
|
7101
7110
|
if (res.status < 200 || res.status >= 300) {
|
|
7102
|
-
const
|
|
7103
|
-
throw new Error(`DELETE ${path11}: HTTP ${res.status}: ${truncate4(
|
|
7111
|
+
const text2 = await res.text();
|
|
7112
|
+
throw new Error(`DELETE ${path11}: HTTP ${res.status}: ${truncate4(text2, 200)}`);
|
|
7104
7113
|
}
|
|
7105
7114
|
}
|
|
7106
|
-
function decodeJsonBody(method, path11,
|
|
7115
|
+
function decodeJsonBody(method, path11, text2) {
|
|
7107
7116
|
try {
|
|
7108
|
-
return JSON.parse(
|
|
7117
|
+
return JSON.parse(text2);
|
|
7109
7118
|
} catch (err) {
|
|
7110
7119
|
const msg = err instanceof Error ? err.message : String(err);
|
|
7111
|
-
throw new Error(`${method} ${path11}: decode: ${msg} (body: ${truncate4(
|
|
7120
|
+
throw new Error(`${method} ${path11}: decode: ${msg} (body: ${truncate4(text2, 200)})`);
|
|
7112
7121
|
}
|
|
7113
7122
|
}
|
|
7114
|
-
function redactPasswordsInBodyText(
|
|
7115
|
-
return
|
|
7123
|
+
function redactPasswordsInBodyText(text2) {
|
|
7124
|
+
return text2.replace(/"password"\s*:\s*"(?:[^"\\]|\\.)*"/g, '"password":"[redacted]"');
|
|
7116
7125
|
}
|
|
7117
7126
|
async function orgMigrationRequest(client, method, path11, payload, options) {
|
|
7118
7127
|
const res = await client.do(method, path11, JSON.stringify(payload), options);
|
|
7119
|
-
const
|
|
7128
|
+
const text2 = await res.text();
|
|
7120
7129
|
if (res.status < 200 || res.status >= 300) {
|
|
7121
7130
|
throw new Error(
|
|
7122
|
-
`${method} ${path11}: HTTP ${res.status}: ${truncate4(redactPasswordsInBodyText(
|
|
7131
|
+
`${method} ${path11}: HTTP ${res.status}: ${truncate4(redactPasswordsInBodyText(text2), 600)}`
|
|
7123
7132
|
);
|
|
7124
7133
|
}
|
|
7125
|
-
return decodeJsonBody(method, path11,
|
|
7134
|
+
return decodeJsonBody(method, path11, text2);
|
|
7126
7135
|
}
|
|
7127
7136
|
async function exportCreate(client, payload, options) {
|
|
7128
7137
|
return orgMigrationRequest(
|
|
@@ -7165,8 +7174,8 @@ async function importDeleteOrgs(client, payload, options) {
|
|
|
7165
7174
|
import { promises as fs4 } from "fs";
|
|
7166
7175
|
|
|
7167
7176
|
// src/commands/_csv.ts
|
|
7168
|
-
function parseCsvRows(
|
|
7169
|
-
const normalized =
|
|
7177
|
+
function parseCsvRows(text2) {
|
|
7178
|
+
const normalized = text2.replace(/\r\n/g, "\n").replace(/\n$/, "");
|
|
7170
7179
|
if (normalized === "") return [];
|
|
7171
7180
|
const rows = [];
|
|
7172
7181
|
let row = [];
|
|
@@ -7216,6 +7225,9 @@ function parseCsvRows(text) {
|
|
|
7216
7225
|
rows.push(row);
|
|
7217
7226
|
return rows;
|
|
7218
7227
|
}
|
|
7228
|
+
function formatCsvRow(cells) {
|
|
7229
|
+
return cells.map((c) => /[",\r\n]/.test(c) ? `"${c.replace(/"/g, '""')}"` : c).join(",");
|
|
7230
|
+
}
|
|
7219
7231
|
|
|
7220
7232
|
// src/commands/_userCsv.ts
|
|
7221
7233
|
var EXPECTED_HEADER = [
|
|
@@ -7245,8 +7257,8 @@ async function readUsersCsv(path11) {
|
|
|
7245
7257
|
}
|
|
7246
7258
|
return parseUsersCsvText(raw);
|
|
7247
7259
|
}
|
|
7248
|
-
function parseUsersCsvText(
|
|
7249
|
-
const withoutBom =
|
|
7260
|
+
function parseUsersCsvText(text2) {
|
|
7261
|
+
const withoutBom = text2.charCodeAt(0) === 65279 ? text2.slice(1) : text2;
|
|
7250
7262
|
const rows = parseCsvRows(withoutBom);
|
|
7251
7263
|
if (rows.length === 0) {
|
|
7252
7264
|
throw new Error("--file: CSV is empty");
|
|
@@ -7420,11 +7432,11 @@ async function getRoles(client, segment, options) {
|
|
|
7420
7432
|
async function grantRoleToUsers(client, appSegment, payload, options) {
|
|
7421
7433
|
const path11 = `/api/${appSegment}/users/grant_permissions_bulk`;
|
|
7422
7434
|
const res = await client.do("POST", path11, JSON.stringify(payload), options);
|
|
7423
|
-
const
|
|
7435
|
+
const text2 = await res.text();
|
|
7424
7436
|
if (res.status >= 200 && res.status < 300) {
|
|
7425
7437
|
return;
|
|
7426
7438
|
}
|
|
7427
|
-
throw new Error(`POST ${path11}: HTTP ${res.status}: ${truncate4(
|
|
7439
|
+
throw new Error(`POST ${path11}: HTTP ${res.status}: ${truncate4(text2, 200)}`);
|
|
7428
7440
|
}
|
|
7429
7441
|
async function getUserTableRoles(client, userId, options) {
|
|
7430
7442
|
const out = await client.getJSON(
|
|
@@ -7444,11 +7456,11 @@ async function setUserPermissionFilters(client, userId, newFilters, options) {
|
|
|
7444
7456
|
const path11 = `/api/it/users/${userId}/permission_filters`;
|
|
7445
7457
|
const body = JSON.stringify({ new_filters: newFilters });
|
|
7446
7458
|
const res = await client.do("POST", path11, body, options);
|
|
7447
|
-
const
|
|
7459
|
+
const text2 = await res.text();
|
|
7448
7460
|
if (res.status >= 200 && res.status < 300) {
|
|
7449
7461
|
return;
|
|
7450
7462
|
}
|
|
7451
|
-
throw new Error(`POST ${path11}: HTTP ${res.status}: ${truncate4(
|
|
7463
|
+
throw new Error(`POST ${path11}: HTTP ${res.status}: ${truncate4(text2, 200)}`);
|
|
7452
7464
|
}
|
|
7453
7465
|
async function getTableRoles(client, options) {
|
|
7454
7466
|
return getRoles(client, "table", options);
|
|
@@ -8155,8 +8167,8 @@ async function readPermissionsCsv(path11) {
|
|
|
8155
8167
|
}
|
|
8156
8168
|
return parsePermissionsCsvText(raw);
|
|
8157
8169
|
}
|
|
8158
|
-
function parsePermissionsCsvText(
|
|
8159
|
-
const withoutBom =
|
|
8170
|
+
function parsePermissionsCsvText(text2) {
|
|
8171
|
+
const withoutBom = text2.charCodeAt(0) === 65279 ? text2.slice(1) : text2;
|
|
8160
8172
|
const rows = parseCsvRows(withoutBom);
|
|
8161
8173
|
if (rows.length === 0) {
|
|
8162
8174
|
throw new Error("--file: CSV is empty");
|
|
@@ -8589,8 +8601,8 @@ async function readEmailRenameCsv(path11) {
|
|
|
8589
8601
|
}
|
|
8590
8602
|
return parseEmailRenameCsvText(raw);
|
|
8591
8603
|
}
|
|
8592
|
-
function parseEmailRenameCsvText(
|
|
8593
|
-
const withoutBom =
|
|
8604
|
+
function parseEmailRenameCsvText(text2) {
|
|
8605
|
+
const withoutBom = text2.charCodeAt(0) === 65279 ? text2.slice(1) : text2;
|
|
8594
8606
|
const rows = parseCsvRows(withoutBom);
|
|
8595
8607
|
if (rows.length === 0) {
|
|
8596
8608
|
throw new Error("--file: CSV is empty");
|
|
@@ -10223,8 +10235,8 @@ async function readGroupsCsv(path11) {
|
|
|
10223
10235
|
}
|
|
10224
10236
|
return parseGroupsCsvText(raw);
|
|
10225
10237
|
}
|
|
10226
|
-
function parseGroupsCsvText(
|
|
10227
|
-
const withoutBom =
|
|
10238
|
+
function parseGroupsCsvText(text2) {
|
|
10239
|
+
const withoutBom = text2.charCodeAt(0) === 65279 ? text2.slice(1) : text2;
|
|
10228
10240
|
const rows = parseCsvRows(withoutBom);
|
|
10229
10241
|
if (rows.length === 0) {
|
|
10230
10242
|
throw new Error("--file: CSV is empty");
|
|
@@ -11889,8 +11901,8 @@ function envelopeErr(success, error) {
|
|
|
11889
11901
|
}
|
|
11890
11902
|
throw new Error("finance-os returned success=false with no error message");
|
|
11891
11903
|
}
|
|
11892
|
-
function describeFinanceOsFailure(
|
|
11893
|
-
const trimmed =
|
|
11904
|
+
function describeFinanceOsFailure(text2) {
|
|
11905
|
+
const trimmed = text2.trim();
|
|
11894
11906
|
let parsed2;
|
|
11895
11907
|
try {
|
|
11896
11908
|
parsed2 = JSON.parse(trimmed);
|
|
@@ -11954,9 +11966,9 @@ var AGGREGATE_POLL_TIMEOUT_MS = 6e4;
|
|
|
11954
11966
|
async function startTask(client, label, path11, body, options) {
|
|
11955
11967
|
const res = await client.do("POST", path11, JSON.stringify(body), options);
|
|
11956
11968
|
if (res.status !== 202) {
|
|
11957
|
-
const
|
|
11969
|
+
const text2 = await res.text();
|
|
11958
11970
|
throw new Error(
|
|
11959
|
-
`${label} POST: expected 202, got ${res.status}: ${describeFinanceOsFailure(
|
|
11971
|
+
`${label} POST: expected 202, got ${res.status}: ${describeFinanceOsFailure(text2)}`
|
|
11960
11972
|
);
|
|
11961
11973
|
}
|
|
11962
11974
|
const location = res.headers.get("Location") ?? "";
|
|
@@ -12000,10 +12012,10 @@ async function getTaskOnce(client, label, pollPath, options) {
|
|
|
12000
12012
|
throw new Error(`poll ${label}: ${msg}`);
|
|
12001
12013
|
}
|
|
12002
12014
|
if (res.status === 200) {
|
|
12003
|
-
const
|
|
12015
|
+
const text3 = await res.text();
|
|
12004
12016
|
let parsed2;
|
|
12005
12017
|
try {
|
|
12006
|
-
parsed2 =
|
|
12018
|
+
parsed2 = text3 === "" ? null : JSON.parse(text3);
|
|
12007
12019
|
} catch (err) {
|
|
12008
12020
|
const msg = err instanceof Error ? err.message : String(err);
|
|
12009
12021
|
throw new Error(`poll ${label}: ${msg}`);
|
|
@@ -12014,9 +12026,9 @@ async function getTaskOnce(client, label, pollPath, options) {
|
|
|
12014
12026
|
await res.text();
|
|
12015
12027
|
return { env: null, status: res.status };
|
|
12016
12028
|
}
|
|
12017
|
-
const
|
|
12029
|
+
const text2 = await res.text();
|
|
12018
12030
|
throw new Error(
|
|
12019
|
-
`poll ${label}: unexpected status ${res.status}: ${describeFinanceOsFailure(
|
|
12031
|
+
`poll ${label}: unexpected status ${res.status}: ${describeFinanceOsFailure(text2)}`
|
|
12020
12032
|
);
|
|
12021
12033
|
}
|
|
12022
12034
|
var defaultSleep2 = (ms, signal) => new Promise((resolve3, reject) => {
|
|
@@ -12037,7 +12049,7 @@ var defaultSleep2 = (ms, signal) => new Promise((resolve3, reject) => {
|
|
|
12037
12049
|
async function pollTask(client, label, path11, options = {}) {
|
|
12038
12050
|
const interval = options.pollIntervalMs ?? AGGREGATE_POLL_INTERVAL_MS;
|
|
12039
12051
|
const timeout = options.timeoutMs ?? AGGREGATE_POLL_TIMEOUT_MS;
|
|
12040
|
-
const
|
|
12052
|
+
const sleep4 = options.sleep ?? defaultSleep2;
|
|
12041
12053
|
const now = options.now ?? Date.now;
|
|
12042
12054
|
const inner = new AbortController();
|
|
12043
12055
|
const onOuterAbort = () => inner.abort(options.signal?.reason);
|
|
@@ -12079,7 +12091,7 @@ async function pollTask(client, label, path11, options = {}) {
|
|
|
12079
12091
|
return result.env;
|
|
12080
12092
|
}
|
|
12081
12093
|
try {
|
|
12082
|
-
await
|
|
12094
|
+
await sleep4(interval, inner.signal);
|
|
12083
12095
|
} catch {
|
|
12084
12096
|
const reason = inner.signal.reason instanceof Error ? inner.signal.reason.message : String(inner.signal.reason ?? "aborted");
|
|
12085
12097
|
throw new Error(`${label} polling timed out: ${reason}`);
|
|
@@ -14280,7 +14292,7 @@ function renderFolderTree(out, tree) {
|
|
|
14280
14292
|
node.parent_id !== null ? String(node.parent_id) : "(root)"
|
|
14281
14293
|
]
|
|
14282
14294
|
});
|
|
14283
|
-
for (const
|
|
14295
|
+
for (const child2 of node.children ?? []) walk(child2, depth + 1);
|
|
14284
14296
|
};
|
|
14285
14297
|
for (const root of tree) walk(root, 0);
|
|
14286
14298
|
writeTable9(out, rows);
|
|
@@ -15775,6 +15787,503 @@ function collectArray3(value, previous) {
|
|
|
15775
15787
|
return previous.concat([value]);
|
|
15776
15788
|
}
|
|
15777
15789
|
|
|
15790
|
+
// src/commands/odata.ts
|
|
15791
|
+
import { once } from "events";
|
|
15792
|
+
|
|
15793
|
+
// src/api/odata.ts
|
|
15794
|
+
import { XMLParser } from "fast-xml-parser";
|
|
15795
|
+
var ODATA_VARIANTS = ["latest", "cleared", "full", "full-cleared"];
|
|
15796
|
+
var VARIANT_BY_SUFFIX = /* @__PURE__ */ new Map([
|
|
15797
|
+
["", "latest"],
|
|
15798
|
+
[" (Cleared)", "cleared"],
|
|
15799
|
+
[" (Full)", "full"],
|
|
15800
|
+
[" (Full)(Cleared)", "full-cleared"]
|
|
15801
|
+
]);
|
|
15802
|
+
var TAG = "%";
|
|
15803
|
+
var TEXT = "#text";
|
|
15804
|
+
var ATTR = "@_";
|
|
15805
|
+
var parser = new XMLParser({
|
|
15806
|
+
ignoreAttributes: false,
|
|
15807
|
+
attributeNamePrefix: ATTR,
|
|
15808
|
+
textNodeName: TEXT,
|
|
15809
|
+
removeNSPrefix: true,
|
|
15810
|
+
parseTagValue: false,
|
|
15811
|
+
parseAttributeValue: false,
|
|
15812
|
+
trimValues: false,
|
|
15813
|
+
htmlEntities: true,
|
|
15814
|
+
transformTagName: (name) => name.startsWith(TAG) ? name : `${TAG}${name}`,
|
|
15815
|
+
isArray: (_name, _jpath, _isLeaf, isAttribute) => isAttribute !== true
|
|
15816
|
+
});
|
|
15817
|
+
function isNode(v) {
|
|
15818
|
+
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
15819
|
+
}
|
|
15820
|
+
function children(node, tag) {
|
|
15821
|
+
if (!isNode(node)) return [];
|
|
15822
|
+
const v = node[`${TAG}${tag}`];
|
|
15823
|
+
return Array.isArray(v) ? v : [];
|
|
15824
|
+
}
|
|
15825
|
+
function child(node, tag) {
|
|
15826
|
+
return children(node, tag)[0];
|
|
15827
|
+
}
|
|
15828
|
+
function attr(node, name) {
|
|
15829
|
+
if (!isNode(node)) return void 0;
|
|
15830
|
+
const v = node[`${ATTR}${name}`];
|
|
15831
|
+
return typeof v === "string" ? v : void 0;
|
|
15832
|
+
}
|
|
15833
|
+
function text(node) {
|
|
15834
|
+
if (typeof node === "string") return node;
|
|
15835
|
+
if (isNode(node) && typeof node[TEXT] === "string") return node[TEXT];
|
|
15836
|
+
return "";
|
|
15837
|
+
}
|
|
15838
|
+
function parseXml(xml, what) {
|
|
15839
|
+
let doc;
|
|
15840
|
+
try {
|
|
15841
|
+
doc = parser.parse(xml);
|
|
15842
|
+
} catch (err) {
|
|
15843
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
15844
|
+
throw new Error(`not ${what}: ${msg}`);
|
|
15845
|
+
}
|
|
15846
|
+
if (!isNode(doc)) throw new Error(`not ${what}`);
|
|
15847
|
+
return doc;
|
|
15848
|
+
}
|
|
15849
|
+
function parseServiceDocument(xml) {
|
|
15850
|
+
const doc = parseXml(xml, "an OData service document");
|
|
15851
|
+
const service = child(doc, "service");
|
|
15852
|
+
if (service === void 0) {
|
|
15853
|
+
throw new Error("not an OData service document (no <service> root)");
|
|
15854
|
+
}
|
|
15855
|
+
const out = [];
|
|
15856
|
+
for (const ws of children(service, "workspace")) {
|
|
15857
|
+
for (const c of children(ws, "collection")) {
|
|
15858
|
+
const key = attr(c, "href");
|
|
15859
|
+
if (key === void 0) continue;
|
|
15860
|
+
out.push({ key, title: text(child(c, "title")), updated: text(child(c, "updated")) });
|
|
15861
|
+
}
|
|
15862
|
+
}
|
|
15863
|
+
return out;
|
|
15864
|
+
}
|
|
15865
|
+
function parseMetadata(xml) {
|
|
15866
|
+
const doc = parseXml(xml, "an OData $metadata document");
|
|
15867
|
+
const edmx = child(doc, "Edmx");
|
|
15868
|
+
if (edmx === void 0) {
|
|
15869
|
+
throw new Error("not an OData $metadata document (no <edmx:Edmx> root)");
|
|
15870
|
+
}
|
|
15871
|
+
const out = [];
|
|
15872
|
+
for (const ds of children(edmx, "DataServices")) {
|
|
15873
|
+
for (const schema of children(ds, "Schema")) {
|
|
15874
|
+
for (const et of children(schema, "EntityType")) {
|
|
15875
|
+
const name = attr(et, "Name");
|
|
15876
|
+
if (name === void 0) continue;
|
|
15877
|
+
const columns = [];
|
|
15878
|
+
for (const p of children(et, "Property")) {
|
|
15879
|
+
const pname = attr(p, "Name");
|
|
15880
|
+
if (pname === void 0) continue;
|
|
15881
|
+
columns.push({ name: pname, type: attr(p, "Type") ?? "" });
|
|
15882
|
+
}
|
|
15883
|
+
out.push({ name, columns });
|
|
15884
|
+
}
|
|
15885
|
+
}
|
|
15886
|
+
}
|
|
15887
|
+
return out;
|
|
15888
|
+
}
|
|
15889
|
+
function parseFeed(xml) {
|
|
15890
|
+
const tooLarge = /^\s*\[\{'error': 'too_large_data'(?:, 'rows_count': (\d+))?(?:, 'cols_count': (\d+))?/.exec(
|
|
15891
|
+
xml
|
|
15892
|
+
);
|
|
15893
|
+
if (tooLarge !== null) {
|
|
15894
|
+
const dims = tooLarge[1] !== void 0 && tooLarge[2] !== void 0 ? ` (${tooLarge[1]} rows \xD7 ${tooLarge[2]} columns)` : "";
|
|
15895
|
+
throw new Error(
|
|
15896
|
+
`the server refused the page as too large${dims}: lower --page-size or narrow --select`
|
|
15897
|
+
);
|
|
15898
|
+
}
|
|
15899
|
+
if (!/<\/(?:[\w.-]+:)?feed>\s*$/.test(xml)) {
|
|
15900
|
+
throw new Error("not an OData Atom feed: the body ends before </feed> (truncated response)");
|
|
15901
|
+
}
|
|
15902
|
+
const doc = parseXml(xml, "an OData Atom feed");
|
|
15903
|
+
const feed = child(doc, "feed");
|
|
15904
|
+
if (feed === void 0) {
|
|
15905
|
+
throw new Error("not an OData Atom feed (no <feed> root)");
|
|
15906
|
+
}
|
|
15907
|
+
const out = [];
|
|
15908
|
+
for (const e of children(feed, "entry")) {
|
|
15909
|
+
const row = /* @__PURE__ */ new Map();
|
|
15910
|
+
const props = child(child(e, "content"), "properties");
|
|
15911
|
+
if (isNode(props)) {
|
|
15912
|
+
for (const [k, v] of Object.entries(props)) {
|
|
15913
|
+
if (!k.startsWith(TAG) || !Array.isArray(v)) continue;
|
|
15914
|
+
const value = v[0];
|
|
15915
|
+
row.set(k.slice(TAG.length), attr(value, "null") === "true" ? null : text(value));
|
|
15916
|
+
}
|
|
15917
|
+
}
|
|
15918
|
+
out.push(row);
|
|
15919
|
+
}
|
|
15920
|
+
return out;
|
|
15921
|
+
}
|
|
15922
|
+
function parseODataTitle(title) {
|
|
15923
|
+
const m = /^(.*)_(\d+)( \(Full\)\(Cleared\)| \(Cleared\)| \(Full\))?$/s.exec(title);
|
|
15924
|
+
if (m === null) return null;
|
|
15925
|
+
const variant = VARIANT_BY_SUFFIX.get(m[3] ?? "");
|
|
15926
|
+
if (variant === void 0) return null;
|
|
15927
|
+
return { baseTitle: m[1] ?? "", tableId: Number(m[2]), variant };
|
|
15928
|
+
}
|
|
15929
|
+
function findByTableId(items, titleOf, tableId, variant) {
|
|
15930
|
+
const hits = items.filter((it) => {
|
|
15931
|
+
const p = parseODataTitle(titleOf(it));
|
|
15932
|
+
return p !== null && p.tableId === tableId && p.variant === variant;
|
|
15933
|
+
});
|
|
15934
|
+
if (hits.length > 1) {
|
|
15935
|
+
const titles = hits.map((h) => `"${titleOf(h)}"`).join(", ");
|
|
15936
|
+
throw new Error(`table ${tableId} (${variant}) is ambiguous over OData: ${titles}`);
|
|
15937
|
+
}
|
|
15938
|
+
return hits[0];
|
|
15939
|
+
}
|
|
15940
|
+
function tablePagePath(key, q) {
|
|
15941
|
+
let path11 = `/OData.svc/${key}?$top=${q.top}&$skip=${q.skip}`;
|
|
15942
|
+
if (q.select !== void 0 && q.select.length > 0) {
|
|
15943
|
+
path11 += `&$select=${encodeURIComponent(q.select.join(","))}`;
|
|
15944
|
+
}
|
|
15945
|
+
if (q.filter !== void 0 && q.filter !== "") {
|
|
15946
|
+
path11 += `&$filter=${encodeURIComponent(q.filter)}`;
|
|
15947
|
+
}
|
|
15948
|
+
return path11;
|
|
15949
|
+
}
|
|
15950
|
+
async function getXml(client, path11, accept, options) {
|
|
15951
|
+
const res = await client.do("GET", path11, void 0, {
|
|
15952
|
+
...options,
|
|
15953
|
+
headers: { ...options?.headers, Accept: accept }
|
|
15954
|
+
});
|
|
15955
|
+
const body = await res.text();
|
|
15956
|
+
if (res.status < 200 || res.status >= 300) {
|
|
15957
|
+
throw new Error(`GET ${path11}: HTTP ${res.status}: ${truncate4(body, 200)}`);
|
|
15958
|
+
}
|
|
15959
|
+
return body;
|
|
15960
|
+
}
|
|
15961
|
+
async function getServiceDocument(client, options) {
|
|
15962
|
+
return parseServiceDocument(await getXml(client, "/OData.svc", "application/xml", options));
|
|
15963
|
+
}
|
|
15964
|
+
async function getMetadata(client, options) {
|
|
15965
|
+
return parseMetadata(await getXml(client, "/OData.svc/$metadata", "application/xml", options));
|
|
15966
|
+
}
|
|
15967
|
+
async function getTablePage(client, key, q, options) {
|
|
15968
|
+
return parseFeed(await getXml(client, tablePagePath(key, q), "application/atom+xml", options));
|
|
15969
|
+
}
|
|
15970
|
+
|
|
15971
|
+
// src/commands/odata.ts
|
|
15972
|
+
var ODATA_DEFAULT_PAGE_SIZE = 3e4;
|
|
15973
|
+
var ODATA_REQUEST_TIMEOUT_MS = 12e4;
|
|
15974
|
+
function notVisible(tableId, variant, where) {
|
|
15975
|
+
return new Error(
|
|
15976
|
+
`table ${tableId} (${variant}) is not visible to this user over OData (not in ${where})`
|
|
15977
|
+
);
|
|
15978
|
+
}
|
|
15979
|
+
async function runODataTables(cfg) {
|
|
15980
|
+
const collections = await getServiceDocument(cfg.client, { signal: cfg.signal });
|
|
15981
|
+
const byId = /* @__PURE__ */ new Map();
|
|
15982
|
+
for (const c of collections) {
|
|
15983
|
+
const parts = parseODataTitle(c.title);
|
|
15984
|
+
if (parts === null) continue;
|
|
15985
|
+
let info = byId.get(parts.tableId);
|
|
15986
|
+
if (info === void 0) {
|
|
15987
|
+
info = { id: parts.tableId, title: parts.baseTitle, variants: [] };
|
|
15988
|
+
byId.set(parts.tableId, info);
|
|
15989
|
+
}
|
|
15990
|
+
info.variants.push({ variant: parts.variant, title: c.title, key: c.key, updated: c.updated });
|
|
15991
|
+
}
|
|
15992
|
+
const order = ODATA_VARIANTS;
|
|
15993
|
+
const tables = [...byId.values()].sort((a, b) => a.id - b.id);
|
|
15994
|
+
for (const t of tables) {
|
|
15995
|
+
t.variants.sort((a, b) => order.indexOf(a.variant) - order.indexOf(b.variant));
|
|
15996
|
+
}
|
|
15997
|
+
if (cfg.asJson) {
|
|
15998
|
+
writeJSONIndented(cfg.out, tables);
|
|
15999
|
+
return;
|
|
16000
|
+
}
|
|
16001
|
+
if (tables.length === 0) {
|
|
16002
|
+
cfg.out.write("(no tables visible over OData)\n");
|
|
16003
|
+
return;
|
|
16004
|
+
}
|
|
16005
|
+
const rows = [["ID", "TITLE", "VARIANTS", "UPDATED"]];
|
|
16006
|
+
for (const t of tables) {
|
|
16007
|
+
const updated = (t.variants.find((v) => v.variant === "latest") ?? t.variants[0])?.updated;
|
|
16008
|
+
rows.push([String(t.id), t.title, t.variants.map((v) => v.variant).join(","), updated ?? ""]);
|
|
16009
|
+
}
|
|
16010
|
+
for (const line of formatTable(rows, columnWidths(rows))) cfg.out.write(`${line}
|
|
16011
|
+
`);
|
|
16012
|
+
}
|
|
16013
|
+
async function runODataMetadata(cfg) {
|
|
16014
|
+
const types = await getMetadata(cfg.client, { signal: cfg.signal });
|
|
16015
|
+
const entity = findByTableId(types, (t) => t.name, cfg.tableId, cfg.variant);
|
|
16016
|
+
if (entity === void 0) throw notVisible(cfg.tableId, cfg.variant, "$metadata");
|
|
16017
|
+
if (cfg.asJson) {
|
|
16018
|
+
writeJSONIndented(cfg.out, entity);
|
|
16019
|
+
return;
|
|
16020
|
+
}
|
|
16021
|
+
cfg.out.write(`${entity.name}
|
|
16022
|
+
`);
|
|
16023
|
+
if (entity.columns.length === 0) {
|
|
16024
|
+
cfg.out.write("(no columns)\n");
|
|
16025
|
+
return;
|
|
16026
|
+
}
|
|
16027
|
+
cfg.out.write("\n");
|
|
16028
|
+
const rows = [["COLUMN", "TYPE"], ...entity.columns.map((c) => [c.name, c.type])];
|
|
16029
|
+
for (const line of formatTable(rows, columnWidths(rows))) cfg.out.write(`${line}
|
|
16030
|
+
`);
|
|
16031
|
+
}
|
|
16032
|
+
async function runODataData(cfg) {
|
|
16033
|
+
const req = { signal: cfg.signal };
|
|
16034
|
+
const budget = () => cfg.extendTimeout?.(cfg.requestTimeoutMs ?? ODATA_REQUEST_TIMEOUT_MS);
|
|
16035
|
+
let key = cfg.key;
|
|
16036
|
+
if (key === void 0) {
|
|
16037
|
+
budget();
|
|
16038
|
+
const collections = await getServiceDocument(cfg.client, req);
|
|
16039
|
+
const hit = findByTableId(collections, (c) => c.title, cfg.tableId, cfg.variant);
|
|
16040
|
+
if (hit === void 0) throw notVisible(cfg.tableId, cfg.variant, "the service document");
|
|
16041
|
+
key = hit.key;
|
|
16042
|
+
}
|
|
16043
|
+
budget();
|
|
16044
|
+
const types = await getMetadata(cfg.client, req);
|
|
16045
|
+
const entity = findByTableId(types, (t) => t.name, cfg.tableId, cfg.variant);
|
|
16046
|
+
if (entity === void 0) throw notVisible(cfg.tableId, cfg.variant, "$metadata");
|
|
16047
|
+
const columns = selectColumns(entity.columns, cfg.select, cfg.tableId, cfg.variant);
|
|
16048
|
+
const names = columns.map((c) => c.name);
|
|
16049
|
+
const pause = () => cfg.pauseTimeout?.();
|
|
16050
|
+
const sink = createSink(cfg.format, names, cfg.out, cfg.signal, pause, budget);
|
|
16051
|
+
await sink.start();
|
|
16052
|
+
let skip = 0;
|
|
16053
|
+
let remaining = cfg.limit;
|
|
16054
|
+
for (; ; ) {
|
|
16055
|
+
const top = remaining === null ? cfg.pageSize : Math.min(cfg.pageSize, remaining);
|
|
16056
|
+
budget();
|
|
16057
|
+
const entries = await getTablePage(
|
|
16058
|
+
cfg.client,
|
|
16059
|
+
key,
|
|
16060
|
+
{ top, skip, select: cfg.select === void 0 ? void 0 : names, filter: cfg.filter },
|
|
16061
|
+
req
|
|
16062
|
+
);
|
|
16063
|
+
const page = entries.slice(0, top);
|
|
16064
|
+
await sink.page(page.map((e) => names.map((n) => e.get(n) ?? null)));
|
|
16065
|
+
skip += page.length;
|
|
16066
|
+
if (remaining !== null) remaining -= page.length;
|
|
16067
|
+
if (page.length < top || remaining === 0) break;
|
|
16068
|
+
}
|
|
16069
|
+
await sink.end();
|
|
16070
|
+
}
|
|
16071
|
+
function selectColumns(all, select, tableId, variant) {
|
|
16072
|
+
if (select === void 0) return [...all];
|
|
16073
|
+
const known = new Set(all.map((c) => c.name));
|
|
16074
|
+
for (const s of select) {
|
|
16075
|
+
if (!known.has(s)) {
|
|
16076
|
+
throw new Error(
|
|
16077
|
+
`--select: unknown column "${s}" for table ${tableId} (${variant}); names are the OData-sanitized ones from \`dr odata metadata ${tableId}\``
|
|
16078
|
+
);
|
|
16079
|
+
}
|
|
16080
|
+
}
|
|
16081
|
+
const wanted = new Set(select);
|
|
16082
|
+
return all.filter((c) => wanted.has(c.name));
|
|
16083
|
+
}
|
|
16084
|
+
async function emitTo(out, s, signal, pause, rearm) {
|
|
16085
|
+
if (!out.write(s)) {
|
|
16086
|
+
pause();
|
|
16087
|
+
await once(out, "drain", { signal });
|
|
16088
|
+
rearm();
|
|
16089
|
+
}
|
|
16090
|
+
}
|
|
16091
|
+
function createSink(format, names, out, signal, pause = () => {
|
|
16092
|
+
}, rearm = () => {
|
|
16093
|
+
}) {
|
|
16094
|
+
const emit = (s) => emitTo(out, s, signal, pause, rearm);
|
|
16095
|
+
if (format === "csv") {
|
|
16096
|
+
return {
|
|
16097
|
+
start: () => emit(`${formatCsvRow(names)}
|
|
16098
|
+
`),
|
|
16099
|
+
page: async (rows) => {
|
|
16100
|
+
for (const r of rows) await emit(`${formatCsvRow(r.map((c) => c ?? ""))}
|
|
16101
|
+
`);
|
|
16102
|
+
},
|
|
16103
|
+
end: async () => {
|
|
16104
|
+
}
|
|
16105
|
+
};
|
|
16106
|
+
}
|
|
16107
|
+
if (format === "json") {
|
|
16108
|
+
let count = 0;
|
|
16109
|
+
return {
|
|
16110
|
+
start: () => emit("["),
|
|
16111
|
+
page: async (rows) => {
|
|
16112
|
+
for (const r of rows) {
|
|
16113
|
+
const obj = Object.fromEntries(names.map((n, i) => [n, r[i] ?? null]));
|
|
16114
|
+
await emit(`${count === 0 ? "\n" : ",\n"}${JSON.stringify(obj)}`);
|
|
16115
|
+
count++;
|
|
16116
|
+
}
|
|
16117
|
+
},
|
|
16118
|
+
end: () => emit(count === 0 ? "]\n" : "\n]\n")
|
|
16119
|
+
};
|
|
16120
|
+
}
|
|
16121
|
+
let widths = null;
|
|
16122
|
+
return {
|
|
16123
|
+
start: async () => {
|
|
16124
|
+
},
|
|
16125
|
+
page: async (rows) => {
|
|
16126
|
+
const cells = rows.map((r) => r.map((c) => c ?? ""));
|
|
16127
|
+
if (widths === null) {
|
|
16128
|
+
if (cells.length === 0) return;
|
|
16129
|
+
widths = columnWidths([names, ...cells]);
|
|
16130
|
+
await emit(`${formatTable([names], widths)[0]}
|
|
16131
|
+
`);
|
|
16132
|
+
}
|
|
16133
|
+
for (const line of formatTable(cells, widths)) await emit(`${line}
|
|
16134
|
+
`);
|
|
16135
|
+
},
|
|
16136
|
+
end: async () => {
|
|
16137
|
+
if (widths === null) await emit("(no rows)\n");
|
|
16138
|
+
}
|
|
16139
|
+
};
|
|
16140
|
+
}
|
|
16141
|
+
function columnWidths(rows) {
|
|
16142
|
+
const widths = [];
|
|
16143
|
+
for (const r of rows) {
|
|
16144
|
+
r.forEach((cell, i) => {
|
|
16145
|
+
if ((widths[i] ?? 0) < cell.length) widths[i] = cell.length;
|
|
16146
|
+
});
|
|
16147
|
+
}
|
|
16148
|
+
return widths;
|
|
16149
|
+
}
|
|
16150
|
+
function formatTable(rows, widths) {
|
|
16151
|
+
return rows.map(
|
|
16152
|
+
(r) => r.map((cell, i) => i === r.length - 1 ? cell : cell.padEnd((widths[i] ?? 0) + 2)).join("")
|
|
16153
|
+
);
|
|
16154
|
+
}
|
|
16155
|
+
function parseVariant(raw) {
|
|
16156
|
+
if (raw === void 0) return "latest";
|
|
16157
|
+
const hit = ODATA_VARIANTS.find((v) => v === raw);
|
|
16158
|
+
if (hit === void 0) {
|
|
16159
|
+
throw new Error(
|
|
16160
|
+
`invalid --variant "${raw}" (expected one of: ${ODATA_VARIANTS.join(", ")})`
|
|
16161
|
+
);
|
|
16162
|
+
}
|
|
16163
|
+
return hit;
|
|
16164
|
+
}
|
|
16165
|
+
var KEY_PATTERN = /^[A-Za-z0-9+/_-]+={0,2}$/;
|
|
16166
|
+
function resolveDataOptions(tableIdStr, f) {
|
|
16167
|
+
const tableId = parsePositiveIntArg(tableIdStr, "<table-id>");
|
|
16168
|
+
const variant = parseVariant(f.variant);
|
|
16169
|
+
if (f.top !== void 0 && f.all === true) {
|
|
16170
|
+
throw new Error("--top and --all cannot be combined");
|
|
16171
|
+
}
|
|
16172
|
+
if (f.csv === true && f.json === true) {
|
|
16173
|
+
throw new Error("--csv and --json cannot be combined");
|
|
16174
|
+
}
|
|
16175
|
+
const pageSize = f.pageSize === void 0 ? ODATA_DEFAULT_PAGE_SIZE : parsePositiveIntArg(f.pageSize, "--page-size");
|
|
16176
|
+
let limit = pageSize;
|
|
16177
|
+
if (f.all === true) limit = null;
|
|
16178
|
+
else if (f.top !== void 0) limit = parsePositiveIntArg(f.top, "--top");
|
|
16179
|
+
if (f.key !== void 0 && !KEY_PATTERN.test(f.key)) {
|
|
16180
|
+
throw new Error(
|
|
16181
|
+
`invalid --key "${f.key}" (expected a base64 key, see \`dr odata tables --json\`)`
|
|
16182
|
+
);
|
|
16183
|
+
}
|
|
16184
|
+
let select;
|
|
16185
|
+
if (f.select !== void 0) {
|
|
16186
|
+
select = f.select.split(",").map((s) => s.trim()).filter((s) => s !== "");
|
|
16187
|
+
if (select.length === 0) throw new Error("--select must name at least one column");
|
|
16188
|
+
}
|
|
16189
|
+
if (f.filter !== void 0 && f.filter === "") {
|
|
16190
|
+
throw new Error("--filter must not be empty");
|
|
16191
|
+
}
|
|
16192
|
+
const requestTimeoutMs = parsePositiveSecondsFlag(
|
|
16193
|
+
f.timeout,
|
|
16194
|
+
"--timeout",
|
|
16195
|
+
ODATA_REQUEST_TIMEOUT_MS
|
|
16196
|
+
);
|
|
16197
|
+
if (requestTimeoutMs > BATCH_TIMEOUT_MAX_SECONDS * 1e3) {
|
|
16198
|
+
throw new Error(`--timeout must be at most ${BATCH_TIMEOUT_MAX_SECONDS} seconds`);
|
|
16199
|
+
}
|
|
16200
|
+
return {
|
|
16201
|
+
tableId,
|
|
16202
|
+
variant,
|
|
16203
|
+
key: f.key,
|
|
16204
|
+
limit,
|
|
16205
|
+
pageSize,
|
|
16206
|
+
select,
|
|
16207
|
+
filter: f.filter,
|
|
16208
|
+
format: f.csv === true ? "csv" : f.json === true ? "json" : "table",
|
|
16209
|
+
requestTimeoutMs
|
|
16210
|
+
};
|
|
16211
|
+
}
|
|
16212
|
+
var VARIANT_HELP = "latest (default), cleared, full (all versions) or full-cleared \u2014 the four collections OData clients see";
|
|
16213
|
+
function registerODataCommand(root) {
|
|
16214
|
+
const od = root.command("odata").description(
|
|
16215
|
+
"Read tables over OData V1 exactly as Excel / Power BI / SQLConnector receive them (read-only)"
|
|
16216
|
+
);
|
|
16217
|
+
const tablesCmd = od.command("tables").description("List the tables this user can read over OData, with their variants").option("--json", "Output JSON, including each variant key", false).action(async (opts) => {
|
|
16218
|
+
const setup = await setupCall(opts.server, opts.account);
|
|
16219
|
+
try {
|
|
16220
|
+
await runODataTables({
|
|
16221
|
+
client: setup.client,
|
|
16222
|
+
asJson: opts.json === true,
|
|
16223
|
+
signal: setup.signal,
|
|
16224
|
+
out: process.stdout
|
|
16225
|
+
});
|
|
16226
|
+
} finally {
|
|
16227
|
+
setup.cleanup();
|
|
16228
|
+
}
|
|
16229
|
+
});
|
|
16230
|
+
addServerFlag(tablesCmd);
|
|
16231
|
+
addAccountFlag(tablesCmd);
|
|
16232
|
+
const metadataCmd = od.command("metadata").description("Columns and EDM types of a table, in $metadata order").argument("<table-id>", "table (template) id").option("--variant <variant>", VARIANT_HELP).option("--json", "Output JSON", false).action(async (idStr, opts) => {
|
|
16233
|
+
const tableId = parsePositiveIntArg(idStr, "<table-id>");
|
|
16234
|
+
const variant = parseVariant(opts.variant);
|
|
16235
|
+
const setup = await setupCall(opts.server, opts.account);
|
|
16236
|
+
try {
|
|
16237
|
+
await runODataMetadata({
|
|
16238
|
+
client: setup.client,
|
|
16239
|
+
tableId,
|
|
16240
|
+
variant,
|
|
16241
|
+
asJson: opts.json === true,
|
|
16242
|
+
signal: setup.signal,
|
|
16243
|
+
out: process.stdout
|
|
16244
|
+
});
|
|
16245
|
+
} finally {
|
|
16246
|
+
setup.cleanup();
|
|
16247
|
+
}
|
|
16248
|
+
});
|
|
16249
|
+
addServerFlag(metadataCmd);
|
|
16250
|
+
addAccountFlag(metadataCmd);
|
|
16251
|
+
const dataCmd = od.command("data").description(
|
|
16252
|
+
"Read table rows over OData. Without --top/--all: one page of --page-size rows. --top N: at most N rows. --all: page until the table is exhausted. Rows stream as each page arrives."
|
|
16253
|
+
).argument("<table-id>", "table (template) id").option("--variant <variant>", VARIANT_HELP).option(
|
|
16254
|
+
"--key <base64>",
|
|
16255
|
+
"Use this OData key verbatim instead of the one the service document lists"
|
|
16256
|
+
).option("--top <n>", "Return at most N rows").option("--all", "Page until the table is exhausted", false).option("--page-size <n>", `Rows per request ($top) (default ${ODATA_DEFAULT_PAGE_SIZE})`).option("--select <columns>", "Comma-separated OData column names (see `dr odata metadata`)").option("--filter <expr>", "OData $filter expression, passed through to the server").option("--csv", "Output CSV", false).option("--json", "Output a JSON array, streamed", false).option(
|
|
16257
|
+
"--timeout <seconds>",
|
|
16258
|
+
`Budget for each request in seconds (default ${ODATA_REQUEST_TIMEOUT_MS / 1e3})`
|
|
16259
|
+
).action(async (idStr, opts) => {
|
|
16260
|
+
const r = resolveDataOptions(idStr, opts);
|
|
16261
|
+
const setup = await setupCall(opts.server, opts.account, { timeoutMs: r.requestTimeoutMs });
|
|
16262
|
+
try {
|
|
16263
|
+
await runODataData({
|
|
16264
|
+
client: setup.client,
|
|
16265
|
+
tableId: r.tableId,
|
|
16266
|
+
variant: r.variant,
|
|
16267
|
+
key: r.key,
|
|
16268
|
+
limit: r.limit,
|
|
16269
|
+
pageSize: r.pageSize,
|
|
16270
|
+
select: r.select,
|
|
16271
|
+
filter: r.filter,
|
|
16272
|
+
format: r.format,
|
|
16273
|
+
signal: setup.signal,
|
|
16274
|
+
out: process.stdout,
|
|
16275
|
+
extendTimeout: setup.extendTimeout,
|
|
16276
|
+
pauseTimeout: setup.pauseTimeout,
|
|
16277
|
+
requestTimeoutMs: r.requestTimeoutMs
|
|
16278
|
+
});
|
|
16279
|
+
} finally {
|
|
16280
|
+
setup.cleanup();
|
|
16281
|
+
}
|
|
16282
|
+
});
|
|
16283
|
+
addServerFlag(dataCmd);
|
|
16284
|
+
addAccountFlag(dataCmd);
|
|
16285
|
+
}
|
|
16286
|
+
|
|
15778
16287
|
// src/api/storyboards.ts
|
|
15779
16288
|
async function list13(client, options) {
|
|
15780
16289
|
const out = await client.getJSON("/api/storytelling/", options);
|
|
@@ -16373,7 +16882,7 @@ var LUT_SAVE_POLL_TIMEOUT_MS = 3e5;
|
|
|
16373
16882
|
async function saveMappings(client, documentId, body, options = {}) {
|
|
16374
16883
|
const interval = options.pollIntervalMs ?? LUT_SAVE_POLL_INTERVAL_MS;
|
|
16375
16884
|
const timeout = options.timeoutMs ?? LUT_SAVE_POLL_TIMEOUT_MS;
|
|
16376
|
-
const
|
|
16885
|
+
const sleep4 = options.sleep ?? defaultPollSleep;
|
|
16377
16886
|
const now = options.now ?? Date.now;
|
|
16378
16887
|
const deadline = now() + timeout;
|
|
16379
16888
|
const path11 = `/api/documents/${documentId}/web_update_lut`;
|
|
@@ -16395,7 +16904,7 @@ async function saveMappings(client, documentId, body, options = {}) {
|
|
|
16395
16904
|
`lut save-mappings: the server is still writing after ${Math.round(timeout / 1e3)}s (task ${cacheKey}). The write is still running server-side \u2014 re-run the same command to rejoin it, or raise --timeout.`
|
|
16396
16905
|
);
|
|
16397
16906
|
}
|
|
16398
|
-
await
|
|
16907
|
+
await sleep4(interval, options.signal);
|
|
16399
16908
|
const tick = await postOnce(client, pollPath, payload, options.signal);
|
|
16400
16909
|
if (tick.status === 200) {
|
|
16401
16910
|
return toResult(tick.text);
|
|
@@ -16404,22 +16913,22 @@ async function saveMappings(client, documentId, body, options = {}) {
|
|
|
16404
16913
|
}
|
|
16405
16914
|
async function postOnce(client, path11, payload, signal) {
|
|
16406
16915
|
const res = await client.do("POST", path11, payload, { signal });
|
|
16407
|
-
const
|
|
16916
|
+
const text2 = await res.text();
|
|
16408
16917
|
if (res.status === 200 || res.status === 409) {
|
|
16409
|
-
return { status: res.status, text };
|
|
16918
|
+
return { status: res.status, text: text2 };
|
|
16410
16919
|
}
|
|
16411
|
-
throw new Error(`POST ${path11}: HTTP ${res.status}: ${truncateBody(
|
|
16920
|
+
throw new Error(`POST ${path11}: HTTP ${res.status}: ${truncateBody(text2)}`);
|
|
16412
16921
|
}
|
|
16413
|
-
function extractCacheKey(
|
|
16922
|
+
function extractCacheKey(text2) {
|
|
16414
16923
|
try {
|
|
16415
|
-
const parsed2 = JSON.parse(
|
|
16924
|
+
const parsed2 = JSON.parse(text2);
|
|
16416
16925
|
return typeof parsed2.cache_key === "string" ? parsed2.cache_key : "";
|
|
16417
16926
|
} catch {
|
|
16418
16927
|
return "";
|
|
16419
16928
|
}
|
|
16420
16929
|
}
|
|
16421
|
-
function toResult(
|
|
16422
|
-
let message =
|
|
16930
|
+
function toResult(text2) {
|
|
16931
|
+
let message = text2.trim();
|
|
16423
16932
|
try {
|
|
16424
16933
|
const parsed2 = JSON.parse(message);
|
|
16425
16934
|
if (typeof parsed2 === "string") message = parsed2;
|
|
@@ -16454,8 +16963,8 @@ async function getLutFile(client, documentId, options) {
|
|
|
16454
16963
|
const path11 = `/api/documents/${documentId}/lut-file`;
|
|
16455
16964
|
const res = await client.do("GET", path11, void 0, options);
|
|
16456
16965
|
if (res.status < 200 || res.status >= 300) {
|
|
16457
|
-
const
|
|
16458
|
-
const truncated =
|
|
16966
|
+
const text2 = await res.text();
|
|
16967
|
+
const truncated = text2.length > 200 ? `${text2.slice(0, 200)}\u2026` : text2;
|
|
16459
16968
|
throw new Error(`GET ${path11}: HTTP ${res.status}: ${truncated}`);
|
|
16460
16969
|
}
|
|
16461
16970
|
const ab = await res.arrayBuffer();
|
|
@@ -16493,8 +17002,8 @@ async function downloadDebugZip(client, docVersionId, type, reqOptions) {
|
|
|
16493
17002
|
const path11 = `/api/documents/download_debug_zip_file/${docVersionId}?type=${type}`;
|
|
16494
17003
|
const res = await client.do("GET", path11, void 0, reqOptions);
|
|
16495
17004
|
if (res.status < 200 || res.status >= 300) {
|
|
16496
|
-
const
|
|
16497
|
-
const truncated =
|
|
17005
|
+
const text2 = await res.text();
|
|
17006
|
+
const truncated = text2.length > 200 ? `${text2.slice(0, 200)}\u2026` : text2;
|
|
16498
17007
|
throw new Error(`GET ${path11}: HTTP ${res.status}: ${truncated}`);
|
|
16499
17008
|
}
|
|
16500
17009
|
const ab = await res.arrayBuffer();
|
|
@@ -16620,19 +17129,19 @@ async function getDocumentJobStatusOnce(client, basePath, requestId, reqOptions)
|
|
|
16620
17129
|
await res.text();
|
|
16621
17130
|
return { kind: "notFound" };
|
|
16622
17131
|
}
|
|
16623
|
-
const
|
|
16624
|
-
throw new Error(`document-job status: unexpected HTTP ${res.status}: ${
|
|
17132
|
+
const text2 = await res.text();
|
|
17133
|
+
throw new Error(`document-job status: unexpected HTTP ${res.status}: ${text2.trim()}`);
|
|
16625
17134
|
}
|
|
16626
17135
|
async function readAutoCalcError(res) {
|
|
16627
|
-
const
|
|
17136
|
+
const text2 = await res.text();
|
|
16628
17137
|
try {
|
|
16629
|
-
const parsed2 = JSON.parse(
|
|
17138
|
+
const parsed2 = JSON.parse(text2);
|
|
16630
17139
|
if (typeof parsed2.error === "string" && parsed2.error !== "") {
|
|
16631
17140
|
return parsed2.error;
|
|
16632
17141
|
}
|
|
16633
17142
|
} catch {
|
|
16634
17143
|
}
|
|
16635
|
-
return
|
|
17144
|
+
return text2.trim();
|
|
16636
17145
|
}
|
|
16637
17146
|
var defaultSleep3 = (ms, signal) => new Promise((resolve3, reject) => {
|
|
16638
17147
|
if (signal?.aborted) {
|
|
@@ -16693,7 +17202,7 @@ async function exportDocument(client, id, destinationOrgIds, override, reqOption
|
|
|
16693
17202
|
async function pollDocumentJob(client, basePath, label, requestId, options = {}) {
|
|
16694
17203
|
const interval = options.pollIntervalMs ?? AUTO_CALC_POLL_INTERVAL_MS;
|
|
16695
17204
|
const timeout = options.timeoutMs ?? AUTO_CALC_POLL_TIMEOUT_MS;
|
|
16696
|
-
const
|
|
17205
|
+
const sleep4 = options.sleep ?? defaultSleep3;
|
|
16697
17206
|
const now = options.now ?? Date.now;
|
|
16698
17207
|
const deadline = now() + timeout;
|
|
16699
17208
|
for (; ; ) {
|
|
@@ -16721,7 +17230,7 @@ async function pollDocumentJob(client, basePath, label, requestId, options = {})
|
|
|
16721
17230
|
`${label} polling timed out after ${timeout}ms (request ${requestId} still processing)`
|
|
16722
17231
|
);
|
|
16723
17232
|
}
|
|
16724
|
-
await
|
|
17233
|
+
await sleep4(interval, options.signal);
|
|
16725
17234
|
}
|
|
16726
17235
|
}
|
|
16727
17236
|
|
|
@@ -16873,13 +17382,13 @@ async function getAutoCalculateSettings(client, docId, reqOptions) {
|
|
|
16873
17382
|
await res.text().catch(() => "");
|
|
16874
17383
|
return null;
|
|
16875
17384
|
}
|
|
16876
|
-
const
|
|
17385
|
+
const text2 = await res.text();
|
|
16877
17386
|
if (res.status < 200 || res.status >= 300) {
|
|
16878
|
-
throw new Error(`GET ${path11}: HTTP ${res.status}: ${
|
|
17387
|
+
throw new Error(`GET ${path11}: HTTP ${res.status}: ${text2.slice(0, 200)}`);
|
|
16879
17388
|
}
|
|
16880
|
-
if (
|
|
17389
|
+
if (text2 === "" || text2 === '""') return null;
|
|
16881
17390
|
try {
|
|
16882
|
-
return JSON.parse(
|
|
17391
|
+
return JSON.parse(text2);
|
|
16883
17392
|
} catch (err) {
|
|
16884
17393
|
const msg = err instanceof Error ? err.message : String(err);
|
|
16885
17394
|
throw new Error(`GET ${path11}: decode: ${msg}`);
|
|
@@ -19946,7 +20455,7 @@ async function waitForReAggregation(cfg) {
|
|
|
19946
20455
|
let interval = cfg.pollIntervalMs ?? REAGG_POLL_INTERVAL_MS;
|
|
19947
20456
|
const maxInterval = cfg.maxPollIntervalMs ?? REAGG_POLL_MAX_INTERVAL_MS;
|
|
19948
20457
|
const timeout = cfg.timeoutMs ?? REAGG_POLL_TIMEOUT_MS;
|
|
19949
|
-
const
|
|
20458
|
+
const sleep4 = cfg.sleep ?? defaultSleep4;
|
|
19950
20459
|
const now = cfg.now ?? Date.now;
|
|
19951
20460
|
const accepted = [...cfg.accepted];
|
|
19952
20461
|
const observedProcessing = /* @__PURE__ */ new Set();
|
|
@@ -19981,7 +20490,7 @@ async function waitForReAggregation(cfg) {
|
|
|
19981
20490
|
break;
|
|
19982
20491
|
}
|
|
19983
20492
|
try {
|
|
19984
|
-
await
|
|
20493
|
+
await sleep4(interval, cfg.signal);
|
|
19985
20494
|
} catch {
|
|
19986
20495
|
aborted = true;
|
|
19987
20496
|
break;
|
|
@@ -20970,15 +21479,15 @@ function parseSuppressionDimension(d, source, i) {
|
|
|
20970
21479
|
return { name, mappings };
|
|
20971
21480
|
}
|
|
20972
21481
|
async function loadSuppression(path11) {
|
|
20973
|
-
let
|
|
21482
|
+
let text2;
|
|
20974
21483
|
try {
|
|
20975
|
-
|
|
21484
|
+
text2 = await readFile2(path11, "utf8");
|
|
20976
21485
|
} catch (err) {
|
|
20977
21486
|
throw new Error(`--suppression: cannot read ${path11} (${errText(err)})`);
|
|
20978
21487
|
}
|
|
20979
21488
|
let parsed2;
|
|
20980
21489
|
try {
|
|
20981
|
-
parsed2 = JSON.parse(
|
|
21490
|
+
parsed2 = JSON.parse(text2);
|
|
20982
21491
|
} catch (err) {
|
|
20983
21492
|
throw new Error(`--suppression: ${path11} is not valid JSON (${errText(err)})`);
|
|
20984
21493
|
}
|
|
@@ -22588,7 +23097,7 @@ async function waitForSuggestionRun(r, cfg, runId) {
|
|
|
22588
23097
|
let interval = cfg.pollIntervalMs ?? SUGGESTIONS_POLL_INTERVAL_MS;
|
|
22589
23098
|
const maxInterval = cfg.maxPollIntervalMs ?? SUGGESTIONS_POLL_MAX_INTERVAL_MS;
|
|
22590
23099
|
const timeout = cfg.timeoutMs ?? SUGGESTIONS_POLL_TIMEOUT_MS;
|
|
22591
|
-
const
|
|
23100
|
+
const sleep4 = cfg.sleep ?? defaultSleep5;
|
|
22592
23101
|
const now = cfg.now ?? Date.now;
|
|
22593
23102
|
const errOut = cfg.errOut ?? process.stderr;
|
|
22594
23103
|
const start = now();
|
|
@@ -22618,7 +23127,7 @@ async function waitForSuggestionRun(r, cfg, runId) {
|
|
|
22618
23127
|
break;
|
|
22619
23128
|
}
|
|
22620
23129
|
try {
|
|
22621
|
-
await
|
|
23130
|
+
await sleep4(interval, cfg.signal);
|
|
22622
23131
|
} catch {
|
|
22623
23132
|
aborted = true;
|
|
22624
23133
|
break;
|
|
@@ -24778,18 +25287,18 @@ async function getTemplateFields(client, templateId, options) {
|
|
|
24778
25287
|
}
|
|
24779
25288
|
async function putDataOnce(client, path11, body, options) {
|
|
24780
25289
|
const res = await client.do("PUT", path11, body, options);
|
|
24781
|
-
const
|
|
25290
|
+
const text2 = await res.text();
|
|
24782
25291
|
if (res.status === 401 || res.status === 403) {
|
|
24783
|
-
throw new Error(`PUT ${path11}: HTTP ${res.status}: ${truncate5(
|
|
25292
|
+
throw new Error(`PUT ${path11}: HTTP ${res.status}: ${truncate5(text2, 200)}`);
|
|
24784
25293
|
}
|
|
24785
25294
|
if (res.status !== 200 && res.status !== 409 && (res.status < 200 || res.status >= 300)) {
|
|
24786
|
-
throw new Error(`PUT ${path11}: HTTP ${res.status}: ${truncate5(
|
|
25295
|
+
throw new Error(`PUT ${path11}: HTTP ${res.status}: ${truncate5(text2, 200)}`);
|
|
24787
25296
|
}
|
|
24788
|
-
if (
|
|
25297
|
+
if (text2 === "" || text2 === '""') {
|
|
24789
25298
|
return { status: res.status, parsed: null };
|
|
24790
25299
|
}
|
|
24791
25300
|
try {
|
|
24792
|
-
return { status: res.status, parsed: JSON.parse(
|
|
25301
|
+
return { status: res.status, parsed: JSON.parse(text2) };
|
|
24793
25302
|
} catch (err) {
|
|
24794
25303
|
const msg = err instanceof Error ? err.message : String(err);
|
|
24795
25304
|
throw new Error(`PUT ${path11}: decode: ${msg}`);
|
|
@@ -24813,7 +25322,7 @@ var defaultSleep6 = (ms, signal) => new Promise((resolve3, reject) => {
|
|
|
24813
25322
|
});
|
|
24814
25323
|
async function putDataWithPolling(client, dashboardId, id, payload, options = {}) {
|
|
24815
25324
|
const interval = options.pollIntervalMs ?? WIDGET_DATA_POLL_INTERVAL_MS;
|
|
24816
|
-
const
|
|
25325
|
+
const sleep4 = options.sleep ?? defaultSleep6;
|
|
24817
25326
|
const path11 = `/api/dashboards/${dashboardId}/widgets/${id}/data`;
|
|
24818
25327
|
const body = JSON.stringify(payload);
|
|
24819
25328
|
const first = await putDataOnce(client, path11, body, options);
|
|
@@ -24830,7 +25339,7 @@ async function putDataWithPolling(client, dashboardId, id, payload, options = {}
|
|
|
24830
25339
|
const pollPath = `${path11}?cache_key=${encodeURIComponent(cacheKey)}`;
|
|
24831
25340
|
for (; ; ) {
|
|
24832
25341
|
try {
|
|
24833
|
-
await
|
|
25342
|
+
await sleep4(interval, options.signal);
|
|
24834
25343
|
} catch (err) {
|
|
24835
25344
|
const reason = err instanceof Error ? err.message : String(err);
|
|
24836
25345
|
throw new Error(`widget data polling timed out: ${reason}`);
|
|
@@ -26696,8 +27205,8 @@ async function exportCsv(client, options) {
|
|
|
26696
27205
|
const path11 = `${BASE}export-csv/`;
|
|
26697
27206
|
const res = await client.do("GET", path11, void 0, options);
|
|
26698
27207
|
if (res.status < 200 || res.status >= 300) {
|
|
26699
|
-
const
|
|
26700
|
-
const truncated =
|
|
27208
|
+
const text2 = await res.text();
|
|
27209
|
+
const truncated = text2.length > 200 ? `${text2.slice(0, 200)}\u2026` : text2;
|
|
26701
27210
|
throw new Error(`GET ${path11}: HTTP ${res.status}: ${truncated}`);
|
|
26702
27211
|
}
|
|
26703
27212
|
return res.text();
|
|
@@ -28485,13 +28994,13 @@ ${MARKER_END}`;
|
|
|
28485
28994
|
}
|
|
28486
28995
|
function renderInlineBlock(skills, managedBy, installRoot) {
|
|
28487
28996
|
const sections = skills.map((s) => {
|
|
28488
|
-
const
|
|
28489
|
-
const trailingNl =
|
|
28997
|
+
const text2 = Buffer.from(routerBytes(s)).toString("utf8");
|
|
28998
|
+
const trailingNl = text2.endsWith("\n") ? "" : "\n";
|
|
28490
28999
|
const refs = s.files.filter((f) => f.relPath !== ROUTER_FILE).map((f) => f.relPath);
|
|
28491
29000
|
const pointer = refs.length === 0 ? "" : `<!-- dr-cli skill ${s.name}: ${refs.length} reference file(s) installed under ${installRoot}/${s.name}/ (${refs.join(", ")}) \u2014 read on demand -->
|
|
28492
29001
|
`;
|
|
28493
29002
|
return `<!-- dr-cli skill: ${s.name} -->
|
|
28494
|
-
${
|
|
29003
|
+
${text2}${trailingNl}${pointer}`;
|
|
28495
29004
|
});
|
|
28496
29005
|
return `${MARKER_BEGIN}
|
|
28497
29006
|
<!-- dr-cli \u2014 Datarails CLI skills (auto-managed by ${managedBy}) -->
|
|
@@ -28591,6 +29100,9 @@ function registerSkillCommand(root) {
|
|
|
28591
29100
|
});
|
|
28592
29101
|
}
|
|
28593
29102
|
|
|
29103
|
+
// src/commands/datamappers.ts
|
|
29104
|
+
import { setTimeout as sleep3 } from "timers/promises";
|
|
29105
|
+
|
|
28594
29106
|
// src/api/datamappers.ts
|
|
28595
29107
|
async function list20(client, tableId, options) {
|
|
28596
29108
|
const out = await client.getJSON(`/api/templates/${tableId}/mappers`, options);
|
|
@@ -28608,6 +29120,14 @@ async function get14(client, tableId, id, options) {
|
|
|
28608
29120
|
}
|
|
28609
29121
|
return out;
|
|
28610
29122
|
}
|
|
29123
|
+
async function getDetails2(client, id, options) {
|
|
29124
|
+
const path11 = `/api/templates/mappers/${id}`;
|
|
29125
|
+
const out = await client.getJSON(path11, options);
|
|
29126
|
+
if (out === null) {
|
|
29127
|
+
throw new Error(`GET ${path11}: empty response from datamapper details`);
|
|
29128
|
+
}
|
|
29129
|
+
return out;
|
|
29130
|
+
}
|
|
28611
29131
|
async function create12(client, tableId, body, options) {
|
|
28612
29132
|
const path11 = `/api/templates/${tableId}/mappers`;
|
|
28613
29133
|
const out = await client.postJSON(path11, body, options);
|
|
@@ -29356,13 +29876,15 @@ async function runDatamappersUpdate(cfg) {
|
|
|
29356
29876
|
body = decodedBody;
|
|
29357
29877
|
}
|
|
29358
29878
|
validateCalcFields(extractCalcFields(body));
|
|
29879
|
+
const err = cfg.err ?? process.stderr;
|
|
29880
|
+
const scanBaseline = rescanValue === "latest" && cfg.verifyScanDispatch !== void 0 ? await captureScanBaseline(cfg.client, cfg.id, cfg.signal, err) : void 0;
|
|
29359
29881
|
let updated;
|
|
29360
29882
|
try {
|
|
29361
29883
|
updated = await update8(cfg.client, cfg.id, body, {
|
|
29362
29884
|
signal: cfg.signal
|
|
29363
29885
|
});
|
|
29364
|
-
} catch (
|
|
29365
|
-
const msg =
|
|
29886
|
+
} catch (err2) {
|
|
29887
|
+
const msg = err2 instanceof Error ? err2.message : String(err2);
|
|
29366
29888
|
if (/HTTP 500/.test(msg)) {
|
|
29367
29889
|
const hint = "hint: the server logs an `ETLError: Custom Columns: The creation of '<field>' field has failed due to incorrect formula syntax.` line for this case but the response body is a bare 500 HTML page. Common causes the client-side guard cannot detect: (1) a [field] reference in a calc formula that does not resolve to any header `map_to`, calc-field `name`, or system field (`[FileBox_ID]`, `[System_Year]`, `[Posting Date]`, \u2026), (2) an unsupported function name (try copying the function spelling from another working calc field via `dr datamappers get`), (3) a string literal that's a plain-English placeholder (e.g. `\"Customer or Client name\"`) which parses but the ETL refuses. Iterate on calc-field formulas one at a time. If every formula looks correct and PUT still 500s, fall back to the workaround: `dr datamappers create from-file <table> --file <new.json>` then `dr datamappers delete <old_id> --table <table>` (note: this orphans references \u2014 LUTs/dashboards/functions pointing at the old mapper id break).";
|
|
29368
29890
|
const responseBody = extractResponseBodyFromError(msg);
|
|
@@ -29388,13 +29910,106 @@ Full request + response captured to: ${logPath}
|
|
|
29388
29910
|
|
|
29389
29911
|
${hint}${logSuffix}`);
|
|
29390
29912
|
}
|
|
29391
|
-
throw
|
|
29913
|
+
throw err2;
|
|
29392
29914
|
}
|
|
29393
29915
|
if (cfg.asJson) {
|
|
29394
29916
|
writeJSONIndented(cfg.out, updated);
|
|
29395
|
-
|
|
29917
|
+
} else {
|
|
29918
|
+
renderMappersTable(cfg.out, [updated]);
|
|
29396
29919
|
}
|
|
29397
|
-
|
|
29920
|
+
if (scanBaseline !== void 0) {
|
|
29921
|
+
const opts = cfg.verifyScanDispatch ?? {};
|
|
29922
|
+
const started2 = await waitForNewScan(cfg.client, scanBaseline, cfg.signal, opts);
|
|
29923
|
+
if (!started2) {
|
|
29924
|
+
const docIds = await mappedDocumentIds(
|
|
29925
|
+
cfg.client,
|
|
29926
|
+
scanBaseline.templateId,
|
|
29927
|
+
cfg.id,
|
|
29928
|
+
cfg.signal
|
|
29929
|
+
);
|
|
29930
|
+
err.write(
|
|
29931
|
+
formatNoScanWarning({
|
|
29932
|
+
mapperId: cfg.id,
|
|
29933
|
+
templateId: scanBaseline.templateId,
|
|
29934
|
+
timeoutMs: opts.timeoutMs ?? DEFAULT_SCAN_DISPATCH_TIMEOUT_MS,
|
|
29935
|
+
docIds
|
|
29936
|
+
})
|
|
29937
|
+
);
|
|
29938
|
+
}
|
|
29939
|
+
}
|
|
29940
|
+
}
|
|
29941
|
+
var DEFAULT_SCAN_DISPATCH_TIMEOUT_MS = 3e4;
|
|
29942
|
+
var DEFAULT_SCAN_DISPATCH_POLL_MS = 2e3;
|
|
29943
|
+
function scanFingerprint(report) {
|
|
29944
|
+
let maxScanId = 0;
|
|
29945
|
+
for (const doc of report.documents ?? []) {
|
|
29946
|
+
for (const v of doc.versions ?? []) {
|
|
29947
|
+
if (typeof v.scan_id === "number" && v.scan_id > maxScanId) maxScanId = v.scan_id;
|
|
29948
|
+
}
|
|
29949
|
+
}
|
|
29950
|
+
return `${report.scans_status?.last_updated ?? ""}|${maxScanId}`;
|
|
29951
|
+
}
|
|
29952
|
+
async function captureScanBaseline(client, mapperId, signal, err) {
|
|
29953
|
+
try {
|
|
29954
|
+
const details = await getDetails2(client, mapperId, { signal });
|
|
29955
|
+
const templateId = details.template.id;
|
|
29956
|
+
const report = await getStatus(client, templateId, { signal });
|
|
29957
|
+
return { templateId, fingerprint: scanFingerprint(report) };
|
|
29958
|
+
} catch (e) {
|
|
29959
|
+
if (signal.aborted) throw e;
|
|
29960
|
+
err.write(
|
|
29961
|
+
"note: could not read the scan status before the update, so dr cannot confirm a rescan starts. Check with `dr scans status <template_id>` afterwards.\n"
|
|
29962
|
+
);
|
|
29963
|
+
return void 0;
|
|
29964
|
+
}
|
|
29965
|
+
}
|
|
29966
|
+
async function waitForNewScan(client, baseline, signal, opts) {
|
|
29967
|
+
const timeoutMs = opts.timeoutMs ?? DEFAULT_SCAN_DISPATCH_TIMEOUT_MS;
|
|
29968
|
+
const pollIntervalMs = opts.pollIntervalMs ?? DEFAULT_SCAN_DISPATCH_POLL_MS;
|
|
29969
|
+
const deadline = Date.now() + timeoutMs;
|
|
29970
|
+
for (; ; ) {
|
|
29971
|
+
try {
|
|
29972
|
+
const report = await getStatus(client, baseline.templateId, { signal });
|
|
29973
|
+
if (scanFingerprint(report) !== baseline.fingerprint) return true;
|
|
29974
|
+
} catch (e) {
|
|
29975
|
+
if (signal.aborted) throw e;
|
|
29976
|
+
}
|
|
29977
|
+
const remaining = deadline - Date.now();
|
|
29978
|
+
if (remaining <= 0) return false;
|
|
29979
|
+
await sleep3(Math.min(pollIntervalMs, remaining), void 0, { signal });
|
|
29980
|
+
}
|
|
29981
|
+
}
|
|
29982
|
+
async function mappedDocumentIds(client, templateId, mapperId, signal) {
|
|
29983
|
+
try {
|
|
29984
|
+
const mapper = await get14(client, templateId, mapperId, { signal });
|
|
29985
|
+
return Array.isArray(mapper.mapped_documents_ids) ? mapper.mapped_documents_ids : void 0;
|
|
29986
|
+
} catch (e) {
|
|
29987
|
+
if (signal.aborted) throw e;
|
|
29988
|
+
return void 0;
|
|
29989
|
+
}
|
|
29990
|
+
}
|
|
29991
|
+
function formatNoScanWarning(p) {
|
|
29992
|
+
const secs = Math.round(p.timeoutMs / 1e3);
|
|
29993
|
+
const lines = [
|
|
29994
|
+
`warning: mapper ${p.mapperId} was saved, but no new scan showed up on template ${p.templateId} within ${secs}s.`,
|
|
29995
|
+
' Either the scan is still queued, or this server predates the DR-54200 fix and ignored rescan="latest", so existing data still has the old config.',
|
|
29996
|
+
` Check first: dr scans status ${p.templateId}`
|
|
29997
|
+
];
|
|
29998
|
+
if (p.docIds !== void 0 && p.docIds.length === 0) {
|
|
29999
|
+
lines.push(" The mapper has no bound documents, so there is nothing to scan.");
|
|
30000
|
+
} else {
|
|
30001
|
+
const docFlags = p.docIds !== void 0 ? p.docIds.map((d) => `--doc ${d}`).join(" ") : "--doc <doc_id> [--doc <doc_id> ...]";
|
|
30002
|
+
lines.push(
|
|
30003
|
+
" If no new scan appears there, re-bind the mapper to its current documents with a rescan:"
|
|
30004
|
+
);
|
|
30005
|
+
if (p.docIds === void 0) {
|
|
30006
|
+
lines.push(
|
|
30007
|
+
` dr datamappers get ${p.mapperId} --table ${p.templateId} --json # read mapped_documents_ids`
|
|
30008
|
+
);
|
|
30009
|
+
}
|
|
30010
|
+
lines.push(` dr datamappers bind ${p.mapperId} ${docFlags} --rescan latest`);
|
|
30011
|
+
}
|
|
30012
|
+
return lines.join("\n") + "\n";
|
|
29398
30013
|
}
|
|
29399
30014
|
async function buildConveniencePayload(client, tableId, name, versionId, sheet, flags, signal) {
|
|
29400
30015
|
const fieldTypes = parseFieldOverrides(flags.fieldOverrides);
|
|
@@ -29709,7 +30324,7 @@ function renderMappersTable(out, mappers) {
|
|
|
29709
30324
|
}
|
|
29710
30325
|
];
|
|
29711
30326
|
for (const m of mappers) {
|
|
29712
|
-
const ordinal = m.ordinal
|
|
30327
|
+
const ordinal = m.ordinal == null ? "-" : String(m.ordinal);
|
|
29713
30328
|
rows.push({
|
|
29714
30329
|
cells: [
|
|
29715
30330
|
String(m.id),
|
|
@@ -30007,7 +30622,7 @@ function registerDatamappersCommand(root) {
|
|
|
30007
30622
|
addServerFlag(fromFileCmd);
|
|
30008
30623
|
addAccountFlag(fromFileCmd);
|
|
30009
30624
|
const updateCmd = dm.command("update").description(
|
|
30010
|
-
|
|
30625
|
+
"Update a datamapper in place (payload-file only \u2014 server accepts config+sheet_name+rescan). `--rescan latest` (the default) re-extracts the LATEST version of each document bound to the mapper. Servers without the DR-54200 fix save the config and start no scan, so after the update dr watches the template for a new scan and, when none shows up, prints how to check `dr scans status` and the `dr datamappers bind` fallback. For a full historical rescan (every calculated field re-executed against every document version ever uploaded), use `dr rescan table <template_id>` instead \u2014 that is far more expensive and higher-blast."
|
|
30011
30626
|
).argument("<mapper_id>", "mapper id (positive integer)").option("--payload-file <path>", "Path to a JSON file with the PUT body (required)", "").option(
|
|
30012
30627
|
"--field <NAME:TYPE>",
|
|
30013
30628
|
'Set a column type via fields_to_change (Text|Float|Date|Integer). Repeatable. Mirrors the UI "Publish and scan" so a calc column referencing a LUT-injected column materialises instead of 500ing on inferred types. Note: the server blocks a type change (HTTP 400) when the template has more than one mapper.',
|
|
@@ -30030,7 +30645,8 @@ function registerDatamappersCommand(root) {
|
|
|
30030
30645
|
serverFlag: opts.server ?? "",
|
|
30031
30646
|
asJson: opts.json === true,
|
|
30032
30647
|
signal: setup.signal,
|
|
30033
|
-
out: process.stdout
|
|
30648
|
+
out: process.stdout,
|
|
30649
|
+
verifyScanDispatch: {}
|
|
30034
30650
|
});
|
|
30035
30651
|
} finally {
|
|
30036
30652
|
setup.cleanup();
|
|
@@ -30554,14 +31170,14 @@ async function runSplitCreate(cfg) {
|
|
|
30554
31170
|
writeJSONIndented(cfg.out, result);
|
|
30555
31171
|
return;
|
|
30556
31172
|
}
|
|
30557
|
-
const
|
|
31173
|
+
const children2 = Array.isArray(result.split_documents) ? result.split_documents : [];
|
|
30558
31174
|
const parentName = result.document !== null && typeof result.document?.name === "string" ? result.document.name : "-";
|
|
30559
31175
|
cfg.out.write(
|
|
30560
|
-
`Split created (id=${result.id}): ${
|
|
31176
|
+
`Split created (id=${result.id}): ${children2.length} child file(s) under parent ${JSON.stringify(parentName)}.
|
|
30561
31177
|
`
|
|
30562
31178
|
);
|
|
30563
|
-
for (const
|
|
30564
|
-
const name = typeof
|
|
31179
|
+
for (const child2 of children2) {
|
|
31180
|
+
const name = typeof child2.name === "string" ? child2.name : "(unnamed)";
|
|
30565
31181
|
cfg.out.write(` - ${name}
|
|
30566
31182
|
`);
|
|
30567
31183
|
}
|
|
@@ -30642,11 +31258,11 @@ function renderSplitsTable(out, splits) {
|
|
|
30642
31258
|
const rows = [["ID", "PARENT", "CHILDREN", "INPUT_METHOD", "DATA_MODE"]];
|
|
30643
31259
|
for (const s of splits) {
|
|
30644
31260
|
const parent = s.document !== null && typeof s.document?.name === "string" ? s.document.name : "-";
|
|
30645
|
-
const
|
|
31261
|
+
const children2 = Array.isArray(s.split_documents) ? String(s.split_documents.length) : "0";
|
|
30646
31262
|
rows.push([
|
|
30647
31263
|
String(s.id),
|
|
30648
31264
|
parent,
|
|
30649
|
-
|
|
31265
|
+
children2,
|
|
30650
31266
|
s.input_method ?? "-",
|
|
30651
31267
|
s.export_as_values === true ? "fixed" : "live"
|
|
30652
31268
|
]);
|
|
@@ -31719,21 +32335,21 @@ async function queryCheckStatus(client, queryIds, reqOptions) {
|
|
|
31719
32335
|
}
|
|
31720
32336
|
async function getErrorExplanation(client, path11, reqOptions) {
|
|
31721
32337
|
const res = await client.do("GET", path11, void 0, reqOptions);
|
|
31722
|
-
const
|
|
32338
|
+
const text2 = await res.text();
|
|
31723
32339
|
if (res.status === 200) {
|
|
31724
32340
|
let parsed2;
|
|
31725
32341
|
try {
|
|
31726
|
-
parsed2 = JSON.parse(
|
|
32342
|
+
parsed2 = JSON.parse(text2);
|
|
31727
32343
|
} catch (err) {
|
|
31728
32344
|
const msg = err instanceof Error ? err.message : String(err);
|
|
31729
32345
|
throw new Error(`decode error-explanation: ${msg}`);
|
|
31730
32346
|
}
|
|
31731
|
-
return { status: 200, body: parsed2, rawText:
|
|
32347
|
+
return { status: 200, body: parsed2, rawText: text2 };
|
|
31732
32348
|
}
|
|
31733
32349
|
if (res.status === 404) {
|
|
31734
|
-
return { status: 404, body: null, rawText:
|
|
32350
|
+
return { status: 404, body: null, rawText: text2 };
|
|
31735
32351
|
}
|
|
31736
|
-
throw new Error(`error explanation: unexpected status ${res.status}: ${
|
|
32352
|
+
throw new Error(`error explanation: unexpected status ${res.status}: ${text2.trim()}`);
|
|
31737
32353
|
}
|
|
31738
32354
|
async function resync(client, id, reqOptions) {
|
|
31739
32355
|
const out = await client.postJSON(
|
|
@@ -31751,8 +32367,8 @@ async function testConnection(client, rawBody, reqOptions) {
|
|
|
31751
32367
|
rawBody,
|
|
31752
32368
|
reqOptions
|
|
31753
32369
|
);
|
|
31754
|
-
const
|
|
31755
|
-
return { status: res.status, rawText:
|
|
32370
|
+
const text2 = await res.text();
|
|
32371
|
+
return { status: res.status, rawText: text2 };
|
|
31756
32372
|
}
|
|
31757
32373
|
async function create15(client, body, reqOptions) {
|
|
31758
32374
|
const path11 = "/api/v3/data_integrations/";
|
|
@@ -31772,8 +32388,8 @@ async function update9(client, id, body, reqOptions) {
|
|
|
31772
32388
|
}
|
|
31773
32389
|
async function deleteById13(client, id, reqOptions) {
|
|
31774
32390
|
const res = await client.do("DELETE", `/api/v3/data_integrations/${id}/`, void 0, reqOptions);
|
|
31775
|
-
const
|
|
31776
|
-
return { status: res.status, rawText:
|
|
32391
|
+
const text2 = await res.text();
|
|
32392
|
+
return { status: res.status, rawText: text2 };
|
|
31777
32393
|
}
|
|
31778
32394
|
async function revoke(client, id, reqOptions) {
|
|
31779
32395
|
const res = await client.do(
|
|
@@ -31852,14 +32468,14 @@ async function itUpdate(client, id, body, reqOptions) {
|
|
|
31852
32468
|
}
|
|
31853
32469
|
async function itDelete(client, id, reqOptions) {
|
|
31854
32470
|
const res = await client.do("DELETE", `/api/it/integrations/${id}`, void 0, reqOptions);
|
|
31855
|
-
const
|
|
31856
|
-
return { status: res.status, rawText:
|
|
32471
|
+
const text2 = await res.text();
|
|
32472
|
+
return { status: res.status, rawText: text2 };
|
|
31857
32473
|
}
|
|
31858
32474
|
async function itResync(client, id, reqOptions) {
|
|
31859
32475
|
const res = await client.do("GET", `/api/it/integrations/${id}/resync`, void 0, reqOptions);
|
|
31860
|
-
const
|
|
32476
|
+
const text2 = await res.text();
|
|
31861
32477
|
if (res.status < 200 || res.status >= 300) {
|
|
31862
|
-
throw new Error(`resync: HTTP ${res.status}: ${
|
|
32478
|
+
throw new Error(`resync: HTTP ${res.status}: ${text2.trim()}`);
|
|
31863
32479
|
}
|
|
31864
32480
|
}
|
|
31865
32481
|
|
|
@@ -32196,7 +32812,7 @@ async function runIntegrationsSync(cfg) {
|
|
|
32196
32812
|
throw new Error("integration id must be positive");
|
|
32197
32813
|
}
|
|
32198
32814
|
const interval = cfg.pollIntervalMs ?? INTEGRATIONS_SYNC_POLL_INTERVAL_MS;
|
|
32199
|
-
const
|
|
32815
|
+
const sleep4 = cfg.sleep ?? defaultSleep7;
|
|
32200
32816
|
const resp = await resync(cfg.client, cfg.id, {
|
|
32201
32817
|
signal: cfg.signal
|
|
32202
32818
|
});
|
|
@@ -32245,7 +32861,7 @@ async function runIntegrationsSync(cfg) {
|
|
|
32245
32861
|
return;
|
|
32246
32862
|
}
|
|
32247
32863
|
try {
|
|
32248
|
-
await
|
|
32864
|
+
await sleep4(interval, inner.signal);
|
|
32249
32865
|
} catch {
|
|
32250
32866
|
cfg.out.write(
|
|
32251
32867
|
`Timed out waiting for sync to finish \u2014 last status was ${orDash(lastStatus)}
|
|
@@ -37019,7 +37635,7 @@ async function runFileboxSetVersionFileStatus(cfg) {
|
|
|
37019
37635
|
throw new Error("version id must be positive");
|
|
37020
37636
|
}
|
|
37021
37637
|
const err = cfg.err ?? process.stderr;
|
|
37022
|
-
const
|
|
37638
|
+
const sleep4 = cfg.sleep ?? defaultCycleTagSleep;
|
|
37023
37639
|
const settleMs = cfg.tagSettleDelayMs ?? CYCLE_TAG_SETTLE_DELAY_MS;
|
|
37024
37640
|
const details = await getDetails(cfg.client, cfg.docId, { signal: cfg.signal });
|
|
37025
37641
|
const tag = (details.tags_config ?? []).find(isFileStatusTag);
|
|
@@ -37112,7 +37728,7 @@ async function runFileboxSetVersionFileStatus(cfg) {
|
|
|
37112
37728
|
}
|
|
37113
37729
|
};
|
|
37114
37730
|
const readBack = async () => {
|
|
37115
|
-
await
|
|
37731
|
+
await sleep4(settleMs, cfg.signal);
|
|
37116
37732
|
return readVersionForConfirm(cfg.client, cfg.versionId, cfg.docId, cfg.signal);
|
|
37117
37733
|
};
|
|
37118
37734
|
await write();
|
|
@@ -40846,8 +41462,8 @@ async function getEvidenceFile(client, params, options) {
|
|
|
40846
41462
|
const path11 = params.accountId !== void 0 && params.accountId !== "" ? `/api/reconciliation/processes/${params.processId}/account/${params.accountId}/evidences/${params.evidenceId}/file` : `/api/reconciliation/processes/${params.processId}/evidences/${params.evidenceId}/file`;
|
|
40847
41463
|
const res = await client.do("GET", path11, void 0, options);
|
|
40848
41464
|
if (res.status < 200 || res.status >= 300) {
|
|
40849
|
-
const
|
|
40850
|
-
const truncated =
|
|
41465
|
+
const text2 = await res.text();
|
|
41466
|
+
const truncated = text2.length > 200 ? `${text2.slice(0, 200)}\u2026` : text2;
|
|
40851
41467
|
throw new Error(`GET ${path11}: HTTP ${res.status}: ${truncated}`);
|
|
40852
41468
|
}
|
|
40853
41469
|
const ab = await res.arrayBuffer();
|
|
@@ -40905,19 +41521,19 @@ async function deleteFileboxConnection(client, connectionId, options) {
|
|
|
40905
41521
|
async function getFileboxSyncProgress(client, params, options) {
|
|
40906
41522
|
const path11 = `/api/reconciliation/filebox/connections/${params.connectionId}/sync/progress`;
|
|
40907
41523
|
const res = await client.do("GET", path11, void 0, options);
|
|
40908
|
-
const
|
|
41524
|
+
const text2 = await res.text();
|
|
40909
41525
|
if (res.status === 200 || res.status === 409) {
|
|
40910
|
-
if (
|
|
41526
|
+
if (text2 === "" || text2 === '""') {
|
|
40911
41527
|
return { status: "", remaining_files: 0, message: "" };
|
|
40912
41528
|
}
|
|
40913
41529
|
try {
|
|
40914
|
-
return JSON.parse(
|
|
41530
|
+
return JSON.parse(text2);
|
|
40915
41531
|
} catch (err) {
|
|
40916
41532
|
const msg = err instanceof Error ? err.message : String(err);
|
|
40917
41533
|
throw new Error(`GET ${path11}: decode: ${msg}`);
|
|
40918
41534
|
}
|
|
40919
41535
|
}
|
|
40920
|
-
const truncated =
|
|
41536
|
+
const truncated = text2.length > 200 ? `${text2.slice(0, 200)}\u2026` : text2;
|
|
40921
41537
|
throw new Error(`GET ${path11}: HTTP ${res.status}: ${truncated}`);
|
|
40922
41538
|
}
|
|
40923
41539
|
async function getFileboxUnlinkedCount(client, params, options) {
|
|
@@ -41074,8 +41690,8 @@ async function readAssigneeCsv(path11) {
|
|
|
41074
41690
|
}
|
|
41075
41691
|
return parseAssigneeCsvText(raw);
|
|
41076
41692
|
}
|
|
41077
|
-
function parseAssigneeCsvText(
|
|
41078
|
-
const withoutBom =
|
|
41693
|
+
function parseAssigneeCsvText(text2) {
|
|
41694
|
+
const withoutBom = text2.charCodeAt(0) === 65279 ? text2.slice(1) : text2;
|
|
41079
41695
|
const rows = parseCsvRows(withoutBom);
|
|
41080
41696
|
if (rows.length === 0) {
|
|
41081
41697
|
throw new Error("--file: CSV is empty");
|
|
@@ -44451,8 +45067,8 @@ async function deleteWithBody(client, path11, body, options) {
|
|
|
44451
45067
|
const encoded = JSON.stringify(body);
|
|
44452
45068
|
const res = await client.do("DELETE", path11, encoded, options);
|
|
44453
45069
|
if (res.status < 200 || res.status >= 300) {
|
|
44454
|
-
const
|
|
44455
|
-
const truncated =
|
|
45070
|
+
const text2 = await res.text();
|
|
45071
|
+
const truncated = text2.length > 200 ? `${text2.slice(0, 200)}\u2026` : text2;
|
|
44456
45072
|
throw new Error(`DELETE ${path11}: HTTP ${res.status}: ${truncated}`);
|
|
44457
45073
|
}
|
|
44458
45074
|
await res.text();
|
|
@@ -44900,16 +45516,16 @@ async function runProbe(client, options) {
|
|
|
44900
45516
|
return;
|
|
44901
45517
|
}
|
|
44902
45518
|
if (res.status === 403 || res.status === 404) {
|
|
44903
|
-
const
|
|
44904
|
-
const lower =
|
|
45519
|
+
const text3 = await res.text();
|
|
45520
|
+
const lower = text3.toLowerCase();
|
|
44905
45521
|
if (V2_NOT_ENABLED_MARKERS.some((marker) => lower.includes(marker))) {
|
|
44906
45522
|
throw new WorkflowV2NotEnabledError();
|
|
44907
45523
|
}
|
|
44908
|
-
const truncated2 =
|
|
45524
|
+
const truncated2 = text3.length > 200 ? `${text3.slice(0, 200)}\u2026` : text3;
|
|
44909
45525
|
throw new Error(`GET ${WORKFLOW_V2_PROBE_PATH}: HTTP ${res.status}: ${truncated2}`);
|
|
44910
45526
|
}
|
|
44911
|
-
const
|
|
44912
|
-
const truncated =
|
|
45527
|
+
const text2 = await res.text();
|
|
45528
|
+
const truncated = text2.length > 200 ? `${text2.slice(0, 200)}\u2026` : text2;
|
|
44913
45529
|
throw new Error(`GET ${WORKFLOW_V2_PROBE_PATH}: HTTP ${res.status}: ${truncated}`);
|
|
44914
45530
|
}
|
|
44915
45531
|
var MEC_NOT_ENABLED_MARKERS = [
|
|
@@ -44982,16 +45598,16 @@ async function runMecProbe(client, options) {
|
|
|
44982
45598
|
return;
|
|
44983
45599
|
}
|
|
44984
45600
|
if (res.status === 403 || res.status === 404) {
|
|
44985
|
-
const
|
|
44986
|
-
const lower =
|
|
45601
|
+
const text3 = await res.text();
|
|
45602
|
+
const lower = text3.toLowerCase();
|
|
44987
45603
|
if (MEC_NOT_ENABLED_MARKERS.some((marker) => lower.includes(marker))) {
|
|
44988
45604
|
throw new MecNotEnabledError();
|
|
44989
45605
|
}
|
|
44990
|
-
const truncated2 =
|
|
45606
|
+
const truncated2 = text3.length > 200 ? `${text3.slice(0, 200)}\u2026` : text3;
|
|
44991
45607
|
throw new Error(`GET ${MEC_PROBE_PATH}: HTTP ${res.status}: ${truncated2}`);
|
|
44992
45608
|
}
|
|
44993
|
-
const
|
|
44994
|
-
const truncated =
|
|
45609
|
+
const text2 = await res.text();
|
|
45610
|
+
const truncated = text2.length > 200 ? `${text2.slice(0, 200)}\u2026` : text2;
|
|
44995
45611
|
throw new Error(`GET ${MEC_PROBE_PATH}: HTTP ${res.status}: ${truncated}`);
|
|
44996
45612
|
}
|
|
44997
45613
|
var SHARE_DATA_FLAG = "--yes-share-data";
|
|
@@ -51539,8 +52155,8 @@ async function putTransactions(client, params, payload, options) {
|
|
|
51539
52155
|
async function rescanTemplateRules(client, params, options) {
|
|
51540
52156
|
const path11 = `/api/templates/${params.templateId}/rules/rescan`;
|
|
51541
52157
|
const res = await client.do("POST", path11, void 0, options);
|
|
51542
|
-
const
|
|
51543
|
-
let body =
|
|
52158
|
+
const text2 = await res.text();
|
|
52159
|
+
let body = text2;
|
|
51544
52160
|
if (body.startsWith('"') && body.endsWith('"') && body.length >= 2) {
|
|
51545
52161
|
try {
|
|
51546
52162
|
body = JSON.parse(body);
|
|
@@ -51616,8 +52232,8 @@ async function exportRulesCsv(client, params, options) {
|
|
|
51616
52232
|
const path11 = `/api/templates/${params.templateId}/rules/export_to_csv${qs}`;
|
|
51617
52233
|
const res = await client.do("POST", path11, void 0, options);
|
|
51618
52234
|
if (res.status < 200 || res.status >= 300) {
|
|
51619
|
-
const
|
|
51620
|
-
const truncated =
|
|
52235
|
+
const text2 = await res.text();
|
|
52236
|
+
const truncated = text2.length > 200 ? `${text2.slice(0, 200)}\u2026` : text2;
|
|
51621
52237
|
throw new Error(`POST ${path11}: HTTP ${res.status}: ${truncated}`);
|
|
51622
52238
|
}
|
|
51623
52239
|
const csv = await res.text();
|
|
@@ -51643,8 +52259,8 @@ async function deleteHiddenRules(client, params, customerTransactionIds, options
|
|
|
51643
52259
|
const body = JSON.stringify(customerTransactionIds);
|
|
51644
52260
|
const res = await client.do("DELETE", path11, body, options);
|
|
51645
52261
|
if (res.status < 200 || res.status >= 300) {
|
|
51646
|
-
const
|
|
51647
|
-
const truncated =
|
|
52262
|
+
const text2 = await res.text();
|
|
52263
|
+
const truncated = text2.length > 200 ? `${text2.slice(0, 200)}\u2026` : text2;
|
|
51648
52264
|
throw new Error(`DELETE ${path11}: HTTP ${res.status}: ${truncated}`);
|
|
51649
52265
|
}
|
|
51650
52266
|
await res.text();
|
|
@@ -51652,8 +52268,8 @@ async function deleteHiddenRules(client, params, customerTransactionIds, options
|
|
|
51652
52268
|
async function triggerAiRules(client, options) {
|
|
51653
52269
|
const path11 = `/api/templates/ai-rules`;
|
|
51654
52270
|
const res = await client.do("POST", path11, void 0, options);
|
|
51655
|
-
const
|
|
51656
|
-
let body =
|
|
52271
|
+
const text2 = await res.text();
|
|
52272
|
+
let body = text2;
|
|
51657
52273
|
if (body.startsWith('"') && body.endsWith('"') && body.length >= 2) {
|
|
51658
52274
|
try {
|
|
51659
52275
|
body = JSON.parse(body);
|
|
@@ -51963,8 +52579,8 @@ async function readCsvImportPayload(path11) {
|
|
|
51963
52579
|
}
|
|
51964
52580
|
return parseCsvImportText(raw);
|
|
51965
52581
|
}
|
|
51966
|
-
function parseCsvImportText(
|
|
51967
|
-
const rows = parseCsvRows(
|
|
52582
|
+
function parseCsvImportText(text2) {
|
|
52583
|
+
const rows = parseCsvRows(text2);
|
|
51968
52584
|
if (rows.length === 0) {
|
|
51969
52585
|
throw new Error("--file: CSV is empty");
|
|
51970
52586
|
}
|
|
@@ -52069,24 +52685,24 @@ function parseClause(clause, lineNo, clauseIdx) {
|
|
|
52069
52685
|
args: values[0]
|
|
52070
52686
|
};
|
|
52071
52687
|
}
|
|
52072
|
-
function parseQuotedValueList(
|
|
52688
|
+
function parseQuotedValueList(text2, lineNo, clauseIdx) {
|
|
52073
52689
|
const out = [];
|
|
52074
52690
|
let i = 0;
|
|
52075
|
-
while (i <
|
|
52076
|
-
while (i <
|
|
52077
|
-
if (i >=
|
|
52078
|
-
if (
|
|
52691
|
+
while (i < text2.length) {
|
|
52692
|
+
while (i < text2.length && (text2[i] === " " || text2[i] === ",")) i++;
|
|
52693
|
+
if (i >= text2.length) break;
|
|
52694
|
+
if (text2[i] !== "'") {
|
|
52079
52695
|
throw new Error(
|
|
52080
|
-
`--file: line ${lineNo} clause ${clauseIdx + 1}: expected single-quoted value at offset ${i} in "${truncate7(
|
|
52696
|
+
`--file: line ${lineNo} clause ${clauseIdx + 1}: expected single-quoted value at offset ${i} in "${truncate7(text2, 80)}"`
|
|
52081
52697
|
);
|
|
52082
52698
|
}
|
|
52083
52699
|
i++;
|
|
52084
52700
|
let v = "";
|
|
52085
52701
|
let closed = false;
|
|
52086
|
-
while (i <
|
|
52087
|
-
const ch =
|
|
52702
|
+
while (i < text2.length) {
|
|
52703
|
+
const ch = text2[i];
|
|
52088
52704
|
if (ch === "'") {
|
|
52089
|
-
if (i + 1 <
|
|
52705
|
+
if (i + 1 < text2.length && text2[i + 1] === "'") {
|
|
52090
52706
|
v += "'";
|
|
52091
52707
|
i += 2;
|
|
52092
52708
|
continue;
|
|
@@ -52100,27 +52716,27 @@ function parseQuotedValueList(text, lineNo, clauseIdx) {
|
|
|
52100
52716
|
}
|
|
52101
52717
|
if (!closed) {
|
|
52102
52718
|
throw new Error(
|
|
52103
|
-
`--file: line ${lineNo} clause ${clauseIdx + 1}: unterminated single-quoted value in "${truncate7(
|
|
52719
|
+
`--file: line ${lineNo} clause ${clauseIdx + 1}: unterminated single-quoted value in "${truncate7(text2, 80)}"`
|
|
52104
52720
|
);
|
|
52105
52721
|
}
|
|
52106
52722
|
out.push(v);
|
|
52107
52723
|
}
|
|
52108
52724
|
if (out.length === 0) {
|
|
52109
52725
|
throw new Error(
|
|
52110
|
-
`--file: line ${lineNo} clause ${clauseIdx + 1}: no quoted values found in "${truncate7(
|
|
52726
|
+
`--file: line ${lineNo} clause ${clauseIdx + 1}: no quoted values found in "${truncate7(text2, 80)}"`
|
|
52111
52727
|
);
|
|
52112
52728
|
}
|
|
52113
52729
|
return out;
|
|
52114
52730
|
}
|
|
52115
|
-
function splitOutsideQuotes(
|
|
52731
|
+
function splitOutsideQuotes(text2, sep) {
|
|
52116
52732
|
const out = [];
|
|
52117
52733
|
let buf = "";
|
|
52118
52734
|
let i = 0;
|
|
52119
52735
|
let inQuote = false;
|
|
52120
|
-
while (i <
|
|
52121
|
-
const ch =
|
|
52736
|
+
while (i < text2.length) {
|
|
52737
|
+
const ch = text2[i];
|
|
52122
52738
|
if (ch === "'") {
|
|
52123
|
-
if (inQuote && i + 1 <
|
|
52739
|
+
if (inQuote && i + 1 < text2.length && text2[i + 1] === "'") {
|
|
52124
52740
|
buf += "''";
|
|
52125
52741
|
i += 2;
|
|
52126
52742
|
continue;
|
|
@@ -52130,7 +52746,7 @@ function splitOutsideQuotes(text, sep) {
|
|
|
52130
52746
|
i++;
|
|
52131
52747
|
continue;
|
|
52132
52748
|
}
|
|
52133
|
-
if (!inQuote &&
|
|
52749
|
+
if (!inQuote && text2.startsWith(sep, i)) {
|
|
52134
52750
|
out.push(buf);
|
|
52135
52751
|
buf = "";
|
|
52136
52752
|
i += sep.length;
|
|
@@ -53633,35 +54249,35 @@ var REGISTRY = "https://datarails.jfrog.io/artifactory/api/npm/dr-cli-virtual";
|
|
|
53633
54249
|
var PACKAGE = "@datarails-ai/dr-cli";
|
|
53634
54250
|
function spawnInherit(command, args) {
|
|
53635
54251
|
return new Promise((resolve3) => {
|
|
53636
|
-
const
|
|
54252
|
+
const child2 = spawn2(command, args, {
|
|
53637
54253
|
stdio: "inherit",
|
|
53638
54254
|
// Windows resolves `npm` as `npm.cmd`; `shell: true` lets cmd.exe do
|
|
53639
54255
|
// the resolution without us having to special-case the suffix.
|
|
53640
54256
|
shell: true
|
|
53641
54257
|
});
|
|
53642
|
-
|
|
54258
|
+
child2.on("close", (code) => {
|
|
53643
54259
|
resolve3(code ?? 1);
|
|
53644
54260
|
});
|
|
53645
|
-
|
|
54261
|
+
child2.on("error", () => {
|
|
53646
54262
|
resolve3(1);
|
|
53647
54263
|
});
|
|
53648
54264
|
});
|
|
53649
54265
|
}
|
|
53650
54266
|
function captureVersion() {
|
|
53651
54267
|
return new Promise((resolve3) => {
|
|
53652
|
-
const
|
|
54268
|
+
const child2 = spawn2("dr", ["--version"], { shell: true });
|
|
53653
54269
|
let out = "";
|
|
53654
|
-
|
|
54270
|
+
child2.stdout.on("data", (chunk) => {
|
|
53655
54271
|
out += chunk.toString();
|
|
53656
54272
|
});
|
|
53657
|
-
|
|
54273
|
+
child2.on("close", (code) => {
|
|
53658
54274
|
if (code !== 0) {
|
|
53659
54275
|
resolve3(null);
|
|
53660
54276
|
return;
|
|
53661
54277
|
}
|
|
53662
54278
|
resolve3(out.trim());
|
|
53663
54279
|
});
|
|
53664
|
-
|
|
54280
|
+
child2.on("error", () => resolve3(null));
|
|
53665
54281
|
});
|
|
53666
54282
|
}
|
|
53667
54283
|
async function runUpdate() {
|
|
@@ -53733,8 +54349,8 @@ async function deleteEntity(client, body, options) {
|
|
|
53733
54349
|
const path11 = "/bo/pre_kickoff/qbo_manage_companies/v2";
|
|
53734
54350
|
const res = await client.do("DELETE", path11, JSON.stringify(body), options);
|
|
53735
54351
|
if (res.status < 200 || res.status >= 300) {
|
|
53736
|
-
const
|
|
53737
|
-
const truncated =
|
|
54352
|
+
const text2 = await res.text();
|
|
54353
|
+
const truncated = text2.length > 200 ? `${text2.slice(0, 200)}\u2026` : text2;
|
|
53738
54354
|
throw new Error(`DELETE ${path11}: HTTP ${res.status}: ${truncated}`);
|
|
53739
54355
|
}
|
|
53740
54356
|
}
|
|
@@ -57864,7 +58480,7 @@ async function defaultSleep8(ms, signal) {
|
|
|
57864
58480
|
async function pollExtractionStatus(client, contractFileIds, options = {}) {
|
|
57865
58481
|
const interval = options.pollIntervalMs ?? EXTRACT_POLL_INTERVAL_MS;
|
|
57866
58482
|
const timeout = options.timeoutMs ?? EXTRACT_POLL_TIMEOUT_MS;
|
|
57867
|
-
const
|
|
58483
|
+
const sleep4 = options.sleep ?? defaultSleep8;
|
|
57868
58484
|
const now = options.now ?? Date.now;
|
|
57869
58485
|
const resolved = /* @__PURE__ */ new Map();
|
|
57870
58486
|
if (contractFileIds.length === 0) return { resolved, pending: [] };
|
|
@@ -57914,7 +58530,7 @@ async function pollExtractionStatus(client, contractFileIds, options = {}) {
|
|
|
57914
58530
|
options.onTick?.(resolved.size, contractFileIds.length);
|
|
57915
58531
|
if (resolved.size >= contractFileIds.length) break;
|
|
57916
58532
|
if (now() > deadline || inner.signal.aborted) break;
|
|
57917
|
-
await
|
|
58533
|
+
await sleep4(interval, inner.signal);
|
|
57918
58534
|
}
|
|
57919
58535
|
} finally {
|
|
57920
58536
|
clearTimeout(deadlineTimer);
|
|
@@ -59712,11 +60328,11 @@ async function extractSync(cfg, parts) {
|
|
|
59712
60328
|
async function emitExtractionDraft(cfg, allResults, sourceFiles, outcomes, abortedMidRun) {
|
|
59713
60329
|
const failed = outcomes.filter((o) => !o.ok);
|
|
59714
60330
|
if (cfg.asRawJson) {
|
|
59715
|
-
const
|
|
60331
|
+
const text3 = JSON.stringify(allResults, null, 2);
|
|
59716
60332
|
if (cfg.outputPath !== void 0) {
|
|
59717
|
-
await fsPromises3.writeFile(cfg.outputPath,
|
|
60333
|
+
await fsPromises3.writeFile(cfg.outputPath, text3 + "\n", "utf8");
|
|
59718
60334
|
} else {
|
|
59719
|
-
cfg.out.write(
|
|
60335
|
+
cfg.out.write(text3 + "\n");
|
|
59720
60336
|
}
|
|
59721
60337
|
reportFileOutcomes(cfg.err, outcomes, abortedMidRun);
|
|
59722
60338
|
throwIfAnyFileFailed(failed, outcomes.length);
|
|
@@ -59728,13 +60344,13 @@ async function emitExtractionDraft(cfg, allResults, sourceFiles, outcomes, abort
|
|
|
59728
60344
|
tenantServer: cfg.serverKey,
|
|
59729
60345
|
defaults: cfg.defaults
|
|
59730
60346
|
});
|
|
59731
|
-
const
|
|
60347
|
+
const text2 = JSON.stringify(draft, null, 2);
|
|
59732
60348
|
if (cfg.outputPath !== void 0) {
|
|
59733
|
-
await fsPromises3.writeFile(cfg.outputPath,
|
|
60349
|
+
await fsPromises3.writeFile(cfg.outputPath, text2 + "\n", "utf8");
|
|
59734
60350
|
cfg.err.write(`wrote ${cfg.outputPath}
|
|
59735
60351
|
`);
|
|
59736
60352
|
} else {
|
|
59737
|
-
cfg.out.write(
|
|
60353
|
+
cfg.out.write(text2 + "\n");
|
|
59738
60354
|
}
|
|
59739
60355
|
const review = draft._meta?.review_required ?? [];
|
|
59740
60356
|
const failures = draft._meta?.ai_failures ?? [];
|
|
@@ -60223,14 +60839,14 @@ async function collectResourceIds(args, fromPath, labels = {}) {
|
|
|
60223
60839
|
raw.push(...a.split(",").map((s) => s.trim()));
|
|
60224
60840
|
}
|
|
60225
60841
|
if (fromPath !== void 0 && fromPath !== "") {
|
|
60226
|
-
let
|
|
60842
|
+
let text2;
|
|
60227
60843
|
try {
|
|
60228
|
-
|
|
60844
|
+
text2 = await fsPromises3.readFile(fromPath, "utf8");
|
|
60229
60845
|
} catch (err) {
|
|
60230
60846
|
const m = err instanceof Error ? err.message : String(err);
|
|
60231
60847
|
throw new Error(`read --from: ${m}`);
|
|
60232
60848
|
}
|
|
60233
|
-
for (const line of
|
|
60849
|
+
for (const line of text2.split(/\r?\n/)) {
|
|
60234
60850
|
const stripped = line.split("#")[0] ?? "";
|
|
60235
60851
|
raw.push(...stripped.split(",").map((s) => s.trim()));
|
|
60236
60852
|
}
|
|
@@ -63816,27 +64432,27 @@ function groupAnswer(group, below) {
|
|
|
63816
64432
|
function filterBelow(node, scopes, map, armed) {
|
|
63817
64433
|
const here = { count: 0, answer: void 0, required: [], denials: [] };
|
|
63818
64434
|
let allAnswered = node.commands.length > 0;
|
|
63819
|
-
for (const
|
|
63820
|
-
if (
|
|
63821
|
-
const below = filterBelow(
|
|
64435
|
+
for (const child2 of node.commands) {
|
|
64436
|
+
if (child2.commands.length > 0) {
|
|
64437
|
+
const below = filterBelow(child2, scopes, map, armed);
|
|
63822
64438
|
here.count += below.count;
|
|
63823
64439
|
if (below.answer === void 0) {
|
|
63824
64440
|
allAnswered = false;
|
|
63825
64441
|
continue;
|
|
63826
64442
|
}
|
|
63827
|
-
interceptGroup(
|
|
63828
|
-
hide(
|
|
64443
|
+
interceptGroup(child2, below.answer);
|
|
64444
|
+
hide(child2);
|
|
63829
64445
|
addRequired(here, below.required);
|
|
63830
64446
|
addDenials(here, below.denials);
|
|
63831
64447
|
continue;
|
|
63832
64448
|
}
|
|
63833
|
-
const answer = leafAnswer(
|
|
64449
|
+
const answer = leafAnswer(child2, scopes, map);
|
|
63834
64450
|
if (answer === void 0) {
|
|
63835
64451
|
allAnswered = false;
|
|
63836
64452
|
continue;
|
|
63837
64453
|
}
|
|
63838
|
-
intercept(
|
|
63839
|
-
hide(
|
|
64454
|
+
intercept(child2, answer.err, armed);
|
|
64455
|
+
hide(child2);
|
|
63840
64456
|
here.count += 1;
|
|
63841
64457
|
addRequired(here, answer.required);
|
|
63842
64458
|
if (answer.denial !== void 0) addDenials(here, [answer.denial]);
|
|
@@ -63959,7 +64575,7 @@ function registersServerFlag(cmd) {
|
|
|
63959
64575
|
}
|
|
63960
64576
|
function isServerBound(cmd) {
|
|
63961
64577
|
if (cmd.commands.length === 0) return registersServerFlag(cmd);
|
|
63962
|
-
return cmd.commands.every((
|
|
64578
|
+
return cmd.commands.every((child2) => isServerBound(child2));
|
|
63963
64579
|
}
|
|
63964
64580
|
function isOpenWithoutServer(cmd) {
|
|
63965
64581
|
return SERVER_OPTIONAL_COMMANDS.has(cmd.name()) || !isServerBound(cmd);
|
|
@@ -64264,6 +64880,7 @@ function buildRootCommand() {
|
|
|
64264
64880
|
registerDynamicRangesCommand(root);
|
|
64265
64881
|
registerFunctionsCommand(root);
|
|
64266
64882
|
registerSemanticTablesCommand(root);
|
|
64883
|
+
registerODataCommand(root);
|
|
64267
64884
|
registerStoryboardsCommand(root);
|
|
64268
64885
|
registerExTablesCommand(root);
|
|
64269
64886
|
registerLutCommand(root);
|
|
@@ -64416,8 +65033,8 @@ function redactUnknownOption(match, prefix, token) {
|
|
|
64416
65033
|
if (!looksLikeFlag(name)) return `${prefix}<redacted>'`;
|
|
64417
65034
|
return eq === -1 ? match : `${prefix}${name}=<redacted>'`;
|
|
64418
65035
|
}
|
|
64419
|
-
function redactCommanderValues(
|
|
64420
|
-
return
|
|
65036
|
+
function redactCommanderValues(text2) {
|
|
65037
|
+
return text2.replace(UNKNOWN_OPTION_PATTERN, redactUnknownOption).replace(UNKNOWN_COMMAND_PATTERN, "$1<redacted>'").replace(INVALID_OPTION_ARGUMENT_PATTERN, "$1<redacted>$2").replace(INVALID_ENV_VALUE_PATTERN, "$1<redacted>$2").replace(INVALID_COMMAND_ARGUMENT_PATTERN, "$1<redacted>$2");
|
|
64421
65038
|
}
|
|
64422
65039
|
async function main() {
|
|
64423
65040
|
let root;
|