@senticor/hive 1.47.0 → 1.48.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/hive.cjs +469 -112
- package/package.json +1 -1
package/hive.cjs
CHANGED
|
@@ -3303,8 +3303,8 @@ var require_utils = __commonJS({
|
|
|
3303
3303
|
}
|
|
3304
3304
|
return ind;
|
|
3305
3305
|
}
|
|
3306
|
-
function removeDotSegments(
|
|
3307
|
-
let input =
|
|
3306
|
+
function removeDotSegments(path10) {
|
|
3307
|
+
let input = path10;
|
|
3308
3308
|
const output2 = [];
|
|
3309
3309
|
let nextSlash = -1;
|
|
3310
3310
|
let len = 0;
|
|
@@ -3714,8 +3714,8 @@ var require_schemes = __commonJS({
|
|
|
3714
3714
|
}
|
|
3715
3715
|
if (wsComponent.resourceName) {
|
|
3716
3716
|
const queryIndex = wsComponent.resourceName.indexOf("?");
|
|
3717
|
-
const
|
|
3718
|
-
wsComponent.path =
|
|
3717
|
+
const path10 = queryIndex === -1 ? wsComponent.resourceName : wsComponent.resourceName.slice(0, queryIndex);
|
|
3718
|
+
wsComponent.path = path10 && path10 !== "/" ? path10 : void 0;
|
|
3719
3719
|
wsComponent.query = queryIndex === -1 ? void 0 : wsComponent.resourceName.slice(queryIndex + 1);
|
|
3720
3720
|
wsComponent.resourceName = void 0;
|
|
3721
3721
|
}
|
|
@@ -8531,13 +8531,9 @@ var HiveClient = class {
|
|
|
8531
8531
|
this.tenant = opts.tenant === null ? null : opts.tenant || process.env.HIVE_TENANT || process.env.HIVE_TENANT_ID || "default";
|
|
8532
8532
|
this.verbose = !!opts.verbose;
|
|
8533
8533
|
}
|
|
8534
|
-
/**
|
|
8535
|
-
async
|
|
8536
|
-
const
|
|
8537
|
-
const mod = url2.protocol === "https:" ? import_node_https2.default : import_node_http2.default;
|
|
8538
|
-
const headers = {
|
|
8539
|
-
accept: "application/json"
|
|
8540
|
-
};
|
|
8534
|
+
/** Tenant + auth headers every request to the Hive API carries. */
|
|
8535
|
+
async _baseHeaders(accept) {
|
|
8536
|
+
const headers = { accept };
|
|
8541
8537
|
if (this.tenant) headers["x-hive-tenant"] = this.tenant;
|
|
8542
8538
|
try {
|
|
8543
8539
|
const token = process.env.HIVE_TOKEN || process.env.HIVE_TEST_TOKEN || process.env.HIVE_BEARER_TOKEN || await getValidToken();
|
|
@@ -8545,6 +8541,13 @@ var HiveClient = class {
|
|
|
8545
8541
|
} catch (e) {
|
|
8546
8542
|
if (this.verbose) console.error("Warning: Could not fetch auth token", e.message);
|
|
8547
8543
|
}
|
|
8544
|
+
return headers;
|
|
8545
|
+
}
|
|
8546
|
+
/** Low-level request helper (no external deps, uses Node built-ins) */
|
|
8547
|
+
async _request(method, path10, body) {
|
|
8548
|
+
const url2 = new import_node_url2.URL(path10, this.baseUrl);
|
|
8549
|
+
const mod = url2.protocol === "https:" ? import_node_https2.default : import_node_http2.default;
|
|
8550
|
+
const headers = await this._baseHeaders("application/json");
|
|
8548
8551
|
let payload = null;
|
|
8549
8552
|
if (body !== void 0 && body !== null) {
|
|
8550
8553
|
payload = typeof body === "string" ? body : JSON.stringify(body);
|
|
@@ -8572,7 +8575,7 @@ var HiveClient = class {
|
|
|
8572
8575
|
`);
|
|
8573
8576
|
}
|
|
8574
8577
|
if (!isHttpOk(res.statusCode)) {
|
|
8575
|
-
recordRemoteFailure({ method, path:
|
|
8578
|
+
recordRemoteFailure({ method, path: path10, status: res.statusCode, body: data });
|
|
8576
8579
|
}
|
|
8577
8580
|
resolve3({ status: res.statusCode, data });
|
|
8578
8581
|
});
|
|
@@ -8582,20 +8585,42 @@ var HiveClient = class {
|
|
|
8582
8585
|
req2.end();
|
|
8583
8586
|
});
|
|
8584
8587
|
}
|
|
8585
|
-
|
|
8586
|
-
|
|
8588
|
+
/**
|
|
8589
|
+
* Streaming request: resolves once the response headers arrive and hands back
|
|
8590
|
+
* the body unread, for responses too large or too binary for `_request`
|
|
8591
|
+
* (a mission export, a document's bytes). Sends the same tenant and auth
|
|
8592
|
+
* headers. The caller reads or discards `body` and reports failures itself.
|
|
8593
|
+
*/
|
|
8594
|
+
async getRaw(path10) {
|
|
8595
|
+
const url2 = new import_node_url2.URL(path10, this.baseUrl);
|
|
8596
|
+
const mod = url2.protocol === "https:" ? import_node_https2.default : import_node_http2.default;
|
|
8597
|
+
const headers = await this._baseHeaders("*/*");
|
|
8598
|
+
if (this.verbose) process.stderr.write(`\u2192 GET ${url2.href} (stream)
|
|
8599
|
+
`);
|
|
8600
|
+
return new Promise((resolve3, reject) => {
|
|
8601
|
+
const req2 = mod.request(url2, { method: "GET", headers }, (res) => {
|
|
8602
|
+
if (this.verbose) process.stderr.write(`\u2190 ${res.statusCode} (stream)
|
|
8603
|
+
`);
|
|
8604
|
+
resolve3({ status: res.statusCode, headers: res.headers, body: res });
|
|
8605
|
+
});
|
|
8606
|
+
req2.on("error", reject);
|
|
8607
|
+
req2.end();
|
|
8608
|
+
});
|
|
8609
|
+
}
|
|
8610
|
+
get(path10) {
|
|
8611
|
+
return this._request("GET", path10);
|
|
8587
8612
|
}
|
|
8588
|
-
post(
|
|
8589
|
-
return this._request("POST",
|
|
8613
|
+
post(path10, body) {
|
|
8614
|
+
return this._request("POST", path10, body || {});
|
|
8590
8615
|
}
|
|
8591
|
-
put(
|
|
8592
|
-
return this._request("PUT",
|
|
8616
|
+
put(path10, body) {
|
|
8617
|
+
return this._request("PUT", path10, body || {});
|
|
8593
8618
|
}
|
|
8594
|
-
patch(
|
|
8595
|
-
return this._request("PATCH",
|
|
8619
|
+
patch(path10, body) {
|
|
8620
|
+
return this._request("PATCH", path10, body || {});
|
|
8596
8621
|
}
|
|
8597
|
-
del(
|
|
8598
|
-
return this._request("DELETE",
|
|
8622
|
+
del(path10) {
|
|
8623
|
+
return this._request("DELETE", path10);
|
|
8599
8624
|
}
|
|
8600
8625
|
};
|
|
8601
8626
|
|
|
@@ -8831,7 +8856,7 @@ function fieldText(value) {
|
|
|
8831
8856
|
function schemaErrorFields(data) {
|
|
8832
8857
|
const errors = data?.schemaErrors;
|
|
8833
8858
|
if (!Array.isArray(errors)) return [];
|
|
8834
|
-
const paths = errors.map((entry) => String(entry?.instancePath ?? "").trim()).filter(Boolean).map((
|
|
8859
|
+
const paths = errors.map((entry) => String(entry?.instancePath ?? "").trim()).filter(Boolean).map((path10) => path10.replace(/^\//, ""));
|
|
8835
8860
|
return [...new Set(paths)];
|
|
8836
8861
|
}
|
|
8837
8862
|
function remoteFailureRemediation(data) {
|
|
@@ -9177,11 +9202,11 @@ function parseBoolish(value) {
|
|
|
9177
9202
|
}
|
|
9178
9203
|
function readTlsKeysFromEnvFile(file2) {
|
|
9179
9204
|
const out = {};
|
|
9180
|
-
const
|
|
9181
|
-
if (!
|
|
9205
|
+
const path10 = cleanString(file2);
|
|
9206
|
+
if (!path10) return out;
|
|
9182
9207
|
let text;
|
|
9183
9208
|
try {
|
|
9184
|
-
text = import_node_fs3.default.readFileSync(
|
|
9209
|
+
text = import_node_fs3.default.readFileSync(path10, "utf-8");
|
|
9185
9210
|
} catch {
|
|
9186
9211
|
return out;
|
|
9187
9212
|
}
|
|
@@ -9449,8 +9474,8 @@ function resolvePrincipal(args) {
|
|
|
9449
9474
|
}
|
|
9450
9475
|
return email3 ? { principalEmail: email3.toLowerCase() } : { principalSub: sub };
|
|
9451
9476
|
}
|
|
9452
|
-
function dryRunResult(method,
|
|
9453
|
-
return body === void 0 ? { dryRun: true, method, path:
|
|
9477
|
+
function dryRunResult(method, path10, body) {
|
|
9478
|
+
return body === void 0 ? { dryRun: true, method, path: path10 } : { dryRun: true, method, path: path10, body };
|
|
9454
9479
|
}
|
|
9455
9480
|
function runScript(script) {
|
|
9456
9481
|
try {
|
|
@@ -9495,22 +9520,22 @@ var artifactName = injectedString(
|
|
|
9495
9520
|
true ? "hive-cli" : void 0
|
|
9496
9521
|
) || String(process.env.HIVE_CLI_ARTIFACT_NAME || "hive-cli").trim() || "hive-cli";
|
|
9497
9522
|
var packageVersion = injectedString(
|
|
9498
|
-
true ? "1.
|
|
9523
|
+
true ? "1.48.0" : void 0
|
|
9499
9524
|
) || String(process.env.HIVE_CLI_PACKAGE_VERSION || "").trim() || readPackageVersion();
|
|
9500
9525
|
var releaseVersion = injectedString(
|
|
9501
|
-
true ? "1.
|
|
9526
|
+
true ? "1.48.0" : void 0
|
|
9502
9527
|
) || String(process.env.HIVE_CLI_RELEASE_VERSION || "").trim() || packageVersion || "dev";
|
|
9503
9528
|
var releaseChannel = injectedString(
|
|
9504
9529
|
true ? "final" : void 0
|
|
9505
9530
|
) || String(process.env.HIVE_CLI_RELEASE_CHANNEL || "").trim() || (releaseVersion.includes("-rc.") ? "rc" : releaseVersion === "dev" ? "dev" : "final");
|
|
9506
9531
|
var buildCommit = injectedString(
|
|
9507
|
-
true ? "
|
|
9532
|
+
true ? "3faa9b71ef73e2fbcf86dce4bdd838ca7fb1fe85" : void 0
|
|
9508
9533
|
) || String(process.env.HIVE_CLI_BUILD_COMMIT || "").trim() || "unknown";
|
|
9509
9534
|
var buildTimestamp = injectedString(
|
|
9510
|
-
true ? "2026-09-
|
|
9535
|
+
true ? "2026-09-30T15:02:20Z" : void 0
|
|
9511
9536
|
) || String(process.env.HIVE_CLI_BUILD_TIMESTAMP || "").trim() || "unknown";
|
|
9512
9537
|
var ociRef = injectedString(
|
|
9513
|
-
true ? "registry.onstackit.cloud/senticor/hive-cli:1.
|
|
9538
|
+
true ? "registry.onstackit.cloud/senticor/hive-cli:1.48.0" : void 0
|
|
9514
9539
|
) || String(process.env.HIVE_CLI_OCI_REF || "").trim() || `registry.onstackit.cloud/senticor/${artifactName}:${releaseVersion}`;
|
|
9515
9540
|
var RELEASE_INFO = Object.freeze({
|
|
9516
9541
|
packageVersion,
|
|
@@ -11530,10 +11555,10 @@ function mergeDefs(...defs) {
|
|
|
11530
11555
|
function cloneDef(schema) {
|
|
11531
11556
|
return mergeDefs(schema._zod.def);
|
|
11532
11557
|
}
|
|
11533
|
-
function getElementAtPath(obj,
|
|
11534
|
-
if (!
|
|
11558
|
+
function getElementAtPath(obj, path10) {
|
|
11559
|
+
if (!path10)
|
|
11535
11560
|
return obj;
|
|
11536
|
-
return
|
|
11561
|
+
return path10.reduce((acc, key) => acc?.[key], obj);
|
|
11537
11562
|
}
|
|
11538
11563
|
function promiseAllObject(promisesObj) {
|
|
11539
11564
|
const keys = Object.keys(promisesObj);
|
|
@@ -11942,11 +11967,11 @@ function explicitlyAborted(x, startIndex = 0) {
|
|
|
11942
11967
|
}
|
|
11943
11968
|
return false;
|
|
11944
11969
|
}
|
|
11945
|
-
function prefixIssues(
|
|
11970
|
+
function prefixIssues(path10, issues) {
|
|
11946
11971
|
return issues.map((iss) => {
|
|
11947
11972
|
var _a3;
|
|
11948
11973
|
(_a3 = iss).path ?? (_a3.path = []);
|
|
11949
|
-
iss.path.unshift(
|
|
11974
|
+
iss.path.unshift(path10);
|
|
11950
11975
|
return iss;
|
|
11951
11976
|
});
|
|
11952
11977
|
}
|
|
@@ -12093,16 +12118,16 @@ function flattenError(error51, mapper = (issue2) => issue2.message) {
|
|
|
12093
12118
|
}
|
|
12094
12119
|
function formatError(error51, mapper = (issue2) => issue2.message) {
|
|
12095
12120
|
const fieldErrors = { _errors: [] };
|
|
12096
|
-
const processError = (error52,
|
|
12121
|
+
const processError = (error52, path10 = []) => {
|
|
12097
12122
|
for (const issue2 of error52.issues) {
|
|
12098
12123
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
12099
|
-
issue2.errors.map((issues) => processError({ issues }, [...
|
|
12124
|
+
issue2.errors.map((issues) => processError({ issues }, [...path10, ...issue2.path]));
|
|
12100
12125
|
} else if (issue2.code === "invalid_key") {
|
|
12101
|
-
processError({ issues: issue2.issues }, [...
|
|
12126
|
+
processError({ issues: issue2.issues }, [...path10, ...issue2.path]);
|
|
12102
12127
|
} else if (issue2.code === "invalid_element") {
|
|
12103
|
-
processError({ issues: issue2.issues }, [...
|
|
12128
|
+
processError({ issues: issue2.issues }, [...path10, ...issue2.path]);
|
|
12104
12129
|
} else {
|
|
12105
|
-
const fullpath = [...
|
|
12130
|
+
const fullpath = [...path10, ...issue2.path];
|
|
12106
12131
|
if (fullpath.length === 0) {
|
|
12107
12132
|
fieldErrors._errors.push(mapper(issue2));
|
|
12108
12133
|
} else {
|
|
@@ -12129,17 +12154,17 @@ function formatError(error51, mapper = (issue2) => issue2.message) {
|
|
|
12129
12154
|
}
|
|
12130
12155
|
function treeifyError(error51, mapper = (issue2) => issue2.message) {
|
|
12131
12156
|
const result = { errors: [] };
|
|
12132
|
-
const processError = (error52,
|
|
12157
|
+
const processError = (error52, path10 = []) => {
|
|
12133
12158
|
var _a3, _b;
|
|
12134
12159
|
for (const issue2 of error52.issues) {
|
|
12135
12160
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
12136
|
-
issue2.errors.map((issues) => processError({ issues }, [...
|
|
12161
|
+
issue2.errors.map((issues) => processError({ issues }, [...path10, ...issue2.path]));
|
|
12137
12162
|
} else if (issue2.code === "invalid_key") {
|
|
12138
|
-
processError({ issues: issue2.issues }, [...
|
|
12163
|
+
processError({ issues: issue2.issues }, [...path10, ...issue2.path]);
|
|
12139
12164
|
} else if (issue2.code === "invalid_element") {
|
|
12140
|
-
processError({ issues: issue2.issues }, [...
|
|
12165
|
+
processError({ issues: issue2.issues }, [...path10, ...issue2.path]);
|
|
12141
12166
|
} else {
|
|
12142
|
-
const fullpath = [...
|
|
12167
|
+
const fullpath = [...path10, ...issue2.path];
|
|
12143
12168
|
if (fullpath.length === 0) {
|
|
12144
12169
|
result.errors.push(mapper(issue2));
|
|
12145
12170
|
continue;
|
|
@@ -12171,8 +12196,8 @@ function treeifyError(error51, mapper = (issue2) => issue2.message) {
|
|
|
12171
12196
|
}
|
|
12172
12197
|
function toDotPath(_path) {
|
|
12173
12198
|
const segs = [];
|
|
12174
|
-
const
|
|
12175
|
-
for (const seg of
|
|
12199
|
+
const path10 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
|
|
12200
|
+
for (const seg of path10) {
|
|
12176
12201
|
if (typeof seg === "number")
|
|
12177
12202
|
segs.push(`[${seg}]`);
|
|
12178
12203
|
else if (typeof seg === "symbol")
|
|
@@ -23964,8 +23989,8 @@ function hex2(_params) {
|
|
|
23964
23989
|
return _stringFormat(ZodCustomStringFormat, "hex", regexes_exports.hex, _params);
|
|
23965
23990
|
}
|
|
23966
23991
|
function hash(alg, params) {
|
|
23967
|
-
const
|
|
23968
|
-
const format = `${alg}_${
|
|
23992
|
+
const enc3 = params?.enc ?? "hex";
|
|
23993
|
+
const format = `${alg}_${enc3}`;
|
|
23969
23994
|
const regex = regexes_exports[format];
|
|
23970
23995
|
if (!regex)
|
|
23971
23996
|
throw new Error(`Unrecognized hash format: ${format}`);
|
|
@@ -24945,13 +24970,13 @@ function resolveRef(ref, ctx2) {
|
|
|
24945
24970
|
if (!ref.startsWith("#")) {
|
|
24946
24971
|
throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
|
|
24947
24972
|
}
|
|
24948
|
-
const
|
|
24949
|
-
if (
|
|
24973
|
+
const path10 = ref.slice(1).split("/").filter(Boolean);
|
|
24974
|
+
if (path10.length === 0) {
|
|
24950
24975
|
return ctx2.rootSchema;
|
|
24951
24976
|
}
|
|
24952
24977
|
const defsKey = ctx2.version === "draft-2020-12" ? "$defs" : "definitions";
|
|
24953
|
-
if (
|
|
24954
|
-
const key =
|
|
24978
|
+
if (path10[0] === defsKey) {
|
|
24979
|
+
const key = path10[1];
|
|
24955
24980
|
if (!key || !ctx2.defs[key]) {
|
|
24956
24981
|
throw new Error(`Reference not found: ${ref}`);
|
|
24957
24982
|
}
|
|
@@ -25514,8 +25539,8 @@ function loadConfig(raw) {
|
|
|
25514
25539
|
const result = BootstrapConfigSchema.safeParse(raw);
|
|
25515
25540
|
if (!result.success) {
|
|
25516
25541
|
const lines = result.error.issues.map((issue2) => {
|
|
25517
|
-
const
|
|
25518
|
-
return ` \u2022 ${
|
|
25542
|
+
const path10 = issue2.path.length ? issue2.path.join(".") : "(root)";
|
|
25543
|
+
return ` \u2022 ${path10}: ${issue2.message}`;
|
|
25519
25544
|
});
|
|
25520
25545
|
throw new Error(`Invalid customer config:
|
|
25521
25546
|
${lines.join("\n")}`);
|
|
@@ -25601,7 +25626,7 @@ function createHttpClient(baseUrl, token, fetchImpl = fetch) {
|
|
|
25601
25626
|
const base = baseUrl.replace(/\/$/, "");
|
|
25602
25627
|
return {
|
|
25603
25628
|
baseUrl: base,
|
|
25604
|
-
async request(method,
|
|
25629
|
+
async request(method, path10, opts = {}) {
|
|
25605
25630
|
const headers = {
|
|
25606
25631
|
Authorization: `Bearer ${token}`,
|
|
25607
25632
|
Accept: "application/json"
|
|
@@ -25612,7 +25637,7 @@ function createHttpClient(baseUrl, token, fetchImpl = fetch) {
|
|
|
25612
25637
|
headers["Content-Type"] = "application/json";
|
|
25613
25638
|
body = JSON.stringify(opts.body);
|
|
25614
25639
|
}
|
|
25615
|
-
const res = await fetchImpl(`${base}${
|
|
25640
|
+
const res = await fetchImpl(`${base}${path10}`, { method, headers, body });
|
|
25616
25641
|
const text = await res.text().catch(() => "");
|
|
25617
25642
|
let json2 = null;
|
|
25618
25643
|
if (text) {
|
|
@@ -25633,21 +25658,21 @@ init_cjs_shims();
|
|
|
25633
25658
|
// src/admin/state.mts
|
|
25634
25659
|
init_cjs_shims();
|
|
25635
25660
|
var import_node_fs7 = require("fs");
|
|
25636
|
-
function readState(
|
|
25637
|
-
if (!(0, import_node_fs7.existsSync)(
|
|
25661
|
+
function readState(path10) {
|
|
25662
|
+
if (!(0, import_node_fs7.existsSync)(path10)) return {};
|
|
25638
25663
|
try {
|
|
25639
|
-
const parsed = JSON.parse((0, import_node_fs7.readFileSync)(
|
|
25664
|
+
const parsed = JSON.parse((0, import_node_fs7.readFileSync)(path10, "utf-8"));
|
|
25640
25665
|
return parsed && typeof parsed === "object" ? parsed : {};
|
|
25641
25666
|
} catch {
|
|
25642
25667
|
return {};
|
|
25643
25668
|
}
|
|
25644
25669
|
}
|
|
25645
|
-
function writeState(
|
|
25646
|
-
(0, import_node_fs7.writeFileSync)(
|
|
25670
|
+
function writeState(path10, state) {
|
|
25671
|
+
(0, import_node_fs7.writeFileSync)(path10, `${JSON.stringify(state, null, 2)}
|
|
25647
25672
|
`, "utf-8");
|
|
25648
25673
|
}
|
|
25649
|
-
function mergeState(
|
|
25650
|
-
const current = readState(
|
|
25674
|
+
function mergeState(path10, patch2, now) {
|
|
25675
|
+
const current = readState(path10);
|
|
25651
25676
|
const completed = /* @__PURE__ */ new Set([
|
|
25652
25677
|
...current.completedSteps ?? [],
|
|
25653
25678
|
...patch2.completedSteps ?? []
|
|
@@ -25658,7 +25683,7 @@ function mergeState(path9, patch2, now) {
|
|
|
25658
25683
|
completedSteps: [...completed],
|
|
25659
25684
|
...now ? { updatedAt: now } : {}
|
|
25660
25685
|
};
|
|
25661
|
-
writeState(
|
|
25686
|
+
writeState(path10, merged);
|
|
25662
25687
|
return merged;
|
|
25663
25688
|
}
|
|
25664
25689
|
|
|
@@ -25760,8 +25785,8 @@ async function ensureMission(client, mission2, opts) {
|
|
|
25760
25785
|
}
|
|
25761
25786
|
const body = { userIntent: mission2.userIntent };
|
|
25762
25787
|
if (mission2.instantiationConfig) body.instantiationConfig = mission2.instantiationConfig;
|
|
25763
|
-
const
|
|
25764
|
-
const res = await client.request("POST",
|
|
25788
|
+
const path10 = `/api/mission-templates/${encodeURIComponent(mission2.templateId)}/instantiate`;
|
|
25789
|
+
const res = await client.request("POST", path10, { body, tenant: opts.tenant });
|
|
25765
25790
|
if (!res.ok) {
|
|
25766
25791
|
throw new Error(
|
|
25767
25792
|
`Instantiate '${mission2.templateId}' failed (HTTP ${res.status}): ${res.text}`
|
|
@@ -26125,10 +26150,10 @@ function defaultStatePath(configDir, override, cwd = process.cwd()) {
|
|
|
26125
26150
|
}
|
|
26126
26151
|
|
|
26127
26152
|
// src/admin/admin.mts
|
|
26128
|
-
function loadEnvFile(
|
|
26153
|
+
function loadEnvFile(path10) {
|
|
26129
26154
|
let text;
|
|
26130
26155
|
try {
|
|
26131
|
-
text = (0, import_node_fs9.readFileSync)(
|
|
26156
|
+
text = (0, import_node_fs9.readFileSync)(path10, "utf-8");
|
|
26132
26157
|
} catch {
|
|
26133
26158
|
return;
|
|
26134
26159
|
}
|
|
@@ -27281,7 +27306,7 @@ var completion = defineCommand({
|
|
|
27281
27306
|
|
|
27282
27307
|
// src/commands/core.ts
|
|
27283
27308
|
init_cjs_shims();
|
|
27284
|
-
var
|
|
27309
|
+
var import_node_fs12 = require("fs");
|
|
27285
27310
|
|
|
27286
27311
|
// ../hive-api-contracts/src/cases-import.ts
|
|
27287
27312
|
init_cjs_shims();
|
|
@@ -27392,9 +27417,282 @@ function parseCasesImportInput(body) {
|
|
|
27392
27417
|
};
|
|
27393
27418
|
}
|
|
27394
27419
|
|
|
27420
|
+
// src/lib/mission-transfer.ts
|
|
27421
|
+
init_cjs_shims();
|
|
27422
|
+
var import_node_crypto5 = require("crypto");
|
|
27423
|
+
var import_node_fs11 = require("fs");
|
|
27424
|
+
var import_node_path11 = __toESM(require("path"), 1);
|
|
27425
|
+
var import_promises = require("stream/promises");
|
|
27426
|
+
var EXPORT_FILE = "export.jsonl";
|
|
27427
|
+
var OBJECTS_DIR = "objects";
|
|
27428
|
+
var EXPORT_FORMAT = "hive.mission.export.v1";
|
|
27429
|
+
var BATCH_MAX_ROWS = 200;
|
|
27430
|
+
var BATCH_MAX_BYTES = 4 * 1024 * 1024;
|
|
27431
|
+
var enc2 = encodeURIComponent;
|
|
27432
|
+
function asRow(value) {
|
|
27433
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
27434
|
+
}
|
|
27435
|
+
function sha256(buf) {
|
|
27436
|
+
return (0, import_node_crypto5.createHash)("sha256").update(buf).digest("hex");
|
|
27437
|
+
}
|
|
27438
|
+
async function readAll(stream) {
|
|
27439
|
+
const chunks = [];
|
|
27440
|
+
for await (const chunk of stream) chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
|
|
27441
|
+
return Buffer.concat(chunks);
|
|
27442
|
+
}
|
|
27443
|
+
function parseBody(buf) {
|
|
27444
|
+
const text = buf.toString("utf8");
|
|
27445
|
+
try {
|
|
27446
|
+
return JSON.parse(text);
|
|
27447
|
+
} catch {
|
|
27448
|
+
return { _raw: text };
|
|
27449
|
+
}
|
|
27450
|
+
}
|
|
27451
|
+
function objectFileName(docId) {
|
|
27452
|
+
return enc2(docId);
|
|
27453
|
+
}
|
|
27454
|
+
function parseExport(text) {
|
|
27455
|
+
const lines = text.split("\n").filter((l) => l.trim() !== "");
|
|
27456
|
+
const parsed = lines.map((line, i) => {
|
|
27457
|
+
try {
|
|
27458
|
+
return JSON.parse(line);
|
|
27459
|
+
} catch {
|
|
27460
|
+
throw commandError("EXPORT_UNREADABLE", 1, `export line ${i + 1} is not JSON`);
|
|
27461
|
+
}
|
|
27462
|
+
});
|
|
27463
|
+
const header = parsed[0];
|
|
27464
|
+
if (!header || header.kind !== "header" || header.format !== EXPORT_FORMAT) {
|
|
27465
|
+
throw commandError("EXPORT_UNREADABLE", 1, `not a ${EXPORT_FORMAT} export (first line must be its header)`);
|
|
27466
|
+
}
|
|
27467
|
+
const source = asRow(header.source);
|
|
27468
|
+
if (!source || typeof source.tenantId !== "string" || typeof source.missionId !== "string") {
|
|
27469
|
+
throw commandError("EXPORT_UNREADABLE", 1, "the export header names no source tenant and mission");
|
|
27470
|
+
}
|
|
27471
|
+
const summary = parsed[parsed.length - 1];
|
|
27472
|
+
if (!summary || summary.kind !== "summary") {
|
|
27473
|
+
throw commandError("EXPORT_INCOMPLETE", 1, "the export has no closing summary line: the stream was cut short");
|
|
27474
|
+
}
|
|
27475
|
+
const out = {
|
|
27476
|
+
header,
|
|
27477
|
+
source: { tenantId: source.tenantId, missionId: source.missionId },
|
|
27478
|
+
cases: [],
|
|
27479
|
+
documents: [],
|
|
27480
|
+
records: [],
|
|
27481
|
+
members: [],
|
|
27482
|
+
summary
|
|
27483
|
+
};
|
|
27484
|
+
for (const line of parsed.slice(1, -1)) {
|
|
27485
|
+
if (line.kind === "case" && asRow(line.case)) out.cases.push(line.case);
|
|
27486
|
+
else if (line.kind === "document" && asRow(line.document)) out.documents.push({ document: line.document, content: asRow(line.content) });
|
|
27487
|
+
else if (line.kind === "record" && asRow(line.record)) out.records.push(line.record);
|
|
27488
|
+
else if (line.kind === "member" && asRow(line.member)) out.members.push(line.member);
|
|
27489
|
+
}
|
|
27490
|
+
const counts = asRow(summary.counts) || {};
|
|
27491
|
+
const expected = [
|
|
27492
|
+
["cases", out.cases.length],
|
|
27493
|
+
["documents", out.documents.length],
|
|
27494
|
+
["records", out.records.length],
|
|
27495
|
+
["members", out.members.length]
|
|
27496
|
+
];
|
|
27497
|
+
for (const [kind, actual] of expected) {
|
|
27498
|
+
if (Number(counts[kind]) !== actual) {
|
|
27499
|
+
throw commandError("EXPORT_INCOMPLETE", 1, `the export summary counts ${String(counts[kind])} ${kind} but the stream holds ${actual}`);
|
|
27500
|
+
}
|
|
27501
|
+
}
|
|
27502
|
+
return out;
|
|
27503
|
+
}
|
|
27504
|
+
async function downloadDocument(client, content, fetchImpl) {
|
|
27505
|
+
const minted = await client.get(String(content.url));
|
|
27506
|
+
if (isHttpOk(minted.status)) {
|
|
27507
|
+
const url2 = asRow(minted.data)?.url;
|
|
27508
|
+
if (typeof url2 !== "string" || !url2) throw commandError("DOCUMENT_URL_MISSING", 1, `${String(content.url)} answered without a url`);
|
|
27509
|
+
const res = await fetchImpl(url2);
|
|
27510
|
+
if (!res.ok) throw commandError("DOCUMENT_DOWNLOAD_FAILED", 1, `direct download failed (HTTP ${res.status}) for ${String(content.url)}`);
|
|
27511
|
+
return { bytes: Buffer.from(await res.arrayBuffer()), via: "direct" };
|
|
27512
|
+
}
|
|
27513
|
+
if (minted.status !== 501) throw remoteFailureError(minted.status, minted.data, "document url");
|
|
27514
|
+
remoteFailureHandled();
|
|
27515
|
+
const raw = await client.getRaw(String(content.content));
|
|
27516
|
+
const body = await readAll(raw.body);
|
|
27517
|
+
if (!isHttpOk(raw.status)) throw remoteFailureError(raw.status, parseBody(body), "document content");
|
|
27518
|
+
return { bytes: body, via: "api" };
|
|
27519
|
+
}
|
|
27520
|
+
async function exportMission(client, opts) {
|
|
27521
|
+
const log = opts.log || (() => void 0);
|
|
27522
|
+
const fetchImpl = opts.fetchImpl || globalThis.fetch;
|
|
27523
|
+
const exportPath = import_node_path11.default.join(opts.outDir, EXPORT_FILE);
|
|
27524
|
+
if ((0, import_node_fs11.existsSync)(exportPath)) {
|
|
27525
|
+
throw commandError("EXPORT_EXISTS", 2, `${exportPath} already exists; choose an empty --out directory`);
|
|
27526
|
+
}
|
|
27527
|
+
(0, import_node_fs11.mkdirSync)(import_node_path11.default.join(opts.outDir, OBJECTS_DIR), { recursive: true, mode: 448 });
|
|
27528
|
+
const res = await client.getRaw(`/api/admin/missions/${enc2(opts.missionId)}/export`);
|
|
27529
|
+
if (!isHttpOk(res.status)) throw remoteFailureError(res.status, parseBody(await readAll(res.body)), "mission export");
|
|
27530
|
+
const partial2 = `${exportPath}.partial`;
|
|
27531
|
+
await (0, import_promises.pipeline)(res.body, (0, import_node_fs11.createWriteStream)(partial2, { mode: 384 }));
|
|
27532
|
+
const exported = parseExport((0, import_node_fs11.readFileSync)(partial2, "utf8"));
|
|
27533
|
+
(0, import_node_fs11.renameSync)(partial2, exportPath);
|
|
27534
|
+
log(`export: ${exported.records.length} records, ${exported.documents.length} documents, ${exported.cases.length} cases`);
|
|
27535
|
+
let direct = 0;
|
|
27536
|
+
let viaApi = 0;
|
|
27537
|
+
let reused = 0;
|
|
27538
|
+
for (const { document: document3, content } of exported.documents) {
|
|
27539
|
+
if (!content) continue;
|
|
27540
|
+
const docId = String(document3.docId);
|
|
27541
|
+
const file2 = import_node_path11.default.join(opts.outDir, OBJECTS_DIR, objectFileName(docId));
|
|
27542
|
+
const expected = typeof content.sha256 === "string" ? content.sha256.toLowerCase() : null;
|
|
27543
|
+
if (expected && (0, import_node_fs11.existsSync)(file2) && sha256((0, import_node_fs11.readFileSync)(file2)) === expected) {
|
|
27544
|
+
reused += 1;
|
|
27545
|
+
continue;
|
|
27546
|
+
}
|
|
27547
|
+
const { bytes, via } = await downloadDocument(client, content, fetchImpl);
|
|
27548
|
+
if (expected && sha256(bytes) !== expected) {
|
|
27549
|
+
throw commandError("DOCUMENT_HASH_MISMATCH", 1, `${docId}: downloaded bytes do not match the exported sha256`);
|
|
27550
|
+
}
|
|
27551
|
+
(0, import_node_fs11.writeFileSync)(file2, bytes, { mode: 384 });
|
|
27552
|
+
if (via === "direct") direct += 1;
|
|
27553
|
+
else viaApi += 1;
|
|
27554
|
+
}
|
|
27555
|
+
return {
|
|
27556
|
+
ok: true,
|
|
27557
|
+
source: exported.source,
|
|
27558
|
+
outDir: opts.outDir,
|
|
27559
|
+
counts: exported.summary.counts,
|
|
27560
|
+
documentsWithoutContent: exported.summary.documentsWithoutContent,
|
|
27561
|
+
downloads: { direct, viaApi, reused }
|
|
27562
|
+
};
|
|
27563
|
+
}
|
|
27564
|
+
function emptyTotals() {
|
|
27565
|
+
return { create: [], replace: [], unchanged: [] };
|
|
27566
|
+
}
|
|
27567
|
+
function batches(rows, maxRows = BATCH_MAX_ROWS, maxBytes = BATCH_MAX_BYTES) {
|
|
27568
|
+
const out = [];
|
|
27569
|
+
let current = [];
|
|
27570
|
+
let size = 0;
|
|
27571
|
+
for (const row of rows) {
|
|
27572
|
+
const bytes = Buffer.byteLength(JSON.stringify(row));
|
|
27573
|
+
if (current.length > 0 && (current.length >= maxRows || size + bytes > maxBytes)) {
|
|
27574
|
+
out.push(current);
|
|
27575
|
+
current = [];
|
|
27576
|
+
size = 0;
|
|
27577
|
+
}
|
|
27578
|
+
current.push(row);
|
|
27579
|
+
size += bytes;
|
|
27580
|
+
}
|
|
27581
|
+
if (current.length > 0) out.push(current);
|
|
27582
|
+
return out;
|
|
27583
|
+
}
|
|
27584
|
+
async function runImportPass(client, exported, opts, dryRun) {
|
|
27585
|
+
const base = `/api/admin/missions/${enc2(opts.missionId)}/import`;
|
|
27586
|
+
const principalMap = opts.principalMap || {};
|
|
27587
|
+
const documents = emptyTotals();
|
|
27588
|
+
const failures = [];
|
|
27589
|
+
const withoutContent = [];
|
|
27590
|
+
for (const { document: document3, content } of exported.documents) {
|
|
27591
|
+
const docId = String(document3.docId);
|
|
27592
|
+
if (!content) {
|
|
27593
|
+
withoutContent.push(docId);
|
|
27594
|
+
continue;
|
|
27595
|
+
}
|
|
27596
|
+
const file2 = import_node_path11.default.join(opts.fromDir, OBJECTS_DIR, objectFileName(docId));
|
|
27597
|
+
if (!(0, import_node_fs11.existsSync)(file2)) throw commandError("DOCUMENT_BYTES_MISSING", 1, `${file2} is missing; re-run the export into this directory to fetch it`);
|
|
27598
|
+
const res = await client.post(`${base}/documents`, {
|
|
27599
|
+
source: exported.source,
|
|
27600
|
+
document: document3,
|
|
27601
|
+
bytesBase64: (0, import_node_fs11.readFileSync)(file2).toString("base64"),
|
|
27602
|
+
principalMap,
|
|
27603
|
+
dryRun,
|
|
27604
|
+
...opts.changeId ? { changeId: opts.changeId } : {}
|
|
27605
|
+
});
|
|
27606
|
+
if (!isHttpOk(res.status)) {
|
|
27607
|
+
remoteFailureHandled();
|
|
27608
|
+
failures.push({ kind: "document", id: docId, status: res.status, error: asRow(res.data)?.error ?? res.data });
|
|
27609
|
+
continue;
|
|
27610
|
+
}
|
|
27611
|
+
const action = String(asRow(res.data)?.action || "");
|
|
27612
|
+
if (action === "create" || action === "replace" || action === "unchanged") documents[action].push(docId);
|
|
27613
|
+
}
|
|
27614
|
+
const records = emptyTotals();
|
|
27615
|
+
const cases = emptyTotals();
|
|
27616
|
+
const collisions = [];
|
|
27617
|
+
const invalid = [];
|
|
27618
|
+
const unresolvedDocumentRefs = [];
|
|
27619
|
+
const unmapped = /* @__PURE__ */ new Set();
|
|
27620
|
+
const sourcePrincipals = exported.members.map((m) => String(m.userId || "")).filter(Boolean);
|
|
27621
|
+
const calls = [
|
|
27622
|
+
...batches(exported.cases).map((rows) => ({ cases: rows })),
|
|
27623
|
+
...batches(exported.records).map((rows) => ({ records: rows }))
|
|
27624
|
+
];
|
|
27625
|
+
for (const rows of calls) {
|
|
27626
|
+
const res = await client.post(base, {
|
|
27627
|
+
source: exported.source,
|
|
27628
|
+
...rows,
|
|
27629
|
+
principalMap,
|
|
27630
|
+
sourcePrincipals,
|
|
27631
|
+
dryRun,
|
|
27632
|
+
...opts.changeId ? { changeId: opts.changeId } : {}
|
|
27633
|
+
});
|
|
27634
|
+
const body = asRow(res.data) || {};
|
|
27635
|
+
if (!isHttpOk(res.status)) remoteFailureHandled();
|
|
27636
|
+
if (!isHttpOk(res.status) && res.status !== 400 && res.status !== 409) {
|
|
27637
|
+
throw remoteFailureError(res.status, res.data, "mission import");
|
|
27638
|
+
}
|
|
27639
|
+
for (const [key, totals] of [["records", records], ["cases", cases]]) {
|
|
27640
|
+
const part = asRow(body[key]) || {};
|
|
27641
|
+
for (const action of ["create", "replace", "unchanged"]) {
|
|
27642
|
+
const ids = part[action];
|
|
27643
|
+
if (Array.isArray(ids)) totals[action].push(...ids.map(String));
|
|
27644
|
+
}
|
|
27645
|
+
}
|
|
27646
|
+
for (const [list, key] of [[collisions, "collisions"], [invalid, "invalid"], [unresolvedDocumentRefs, "unresolvedDocumentRefs"]]) {
|
|
27647
|
+
const items = body[key];
|
|
27648
|
+
if (Array.isArray(items)) list.push(...items);
|
|
27649
|
+
}
|
|
27650
|
+
const unmappedHere = body.unmappedPrincipals;
|
|
27651
|
+
if (Array.isArray(unmappedHere)) unmappedHere.forEach((p) => unmapped.add(String(p)));
|
|
27652
|
+
}
|
|
27653
|
+
return {
|
|
27654
|
+
ok: failures.length === 0 && collisions.length === 0 && invalid.length === 0,
|
|
27655
|
+
dryRun,
|
|
27656
|
+
source: exported.source,
|
|
27657
|
+
target: { missionId: opts.missionId },
|
|
27658
|
+
documents: { ...documents, withoutContent, failures },
|
|
27659
|
+
records,
|
|
27660
|
+
cases,
|
|
27661
|
+
collisions,
|
|
27662
|
+
invalid,
|
|
27663
|
+
unresolvedDocumentRefs,
|
|
27664
|
+
unmappedPrincipals: [...unmapped].sort()
|
|
27665
|
+
};
|
|
27666
|
+
}
|
|
27667
|
+
async function importMission(client, opts) {
|
|
27668
|
+
const exportPath = import_node_path11.default.join(opts.fromDir, EXPORT_FILE);
|
|
27669
|
+
if (!(0, import_node_fs11.existsSync)(exportPath)) throw commandError("EXPORT_NOT_FOUND", 2, `${exportPath} not found`);
|
|
27670
|
+
const exported = parseExport((0, import_node_fs11.readFileSync)(exportPath, "utf8"));
|
|
27671
|
+
if (!opts.dryRun && !opts.changeId) throw commandError("CHANGE_ID_REQUIRED", 2, "--change-id is required unless --dry-run");
|
|
27672
|
+
const plan = await runImportPass(client, exported, opts, true);
|
|
27673
|
+
if (opts.dryRun) return plan;
|
|
27674
|
+
if (!plan.ok) {
|
|
27675
|
+
throw commandError("IMPORT_BLOCKED", 1, `the dry-run found problems; nothing was written: ${JSON.stringify({
|
|
27676
|
+
documentFailures: asRow(plan.documents)?.failures,
|
|
27677
|
+
collisions: plan.collisions,
|
|
27678
|
+
invalid: plan.invalid
|
|
27679
|
+
})}`);
|
|
27680
|
+
}
|
|
27681
|
+
opts.log?.("import: dry-run clean, writing");
|
|
27682
|
+
const written = await runImportPass(client, exported, opts, false);
|
|
27683
|
+
if (!written.ok) {
|
|
27684
|
+
throw commandError("IMPORT_INCOMPLETE", 1, `the import stopped part-way; re-run it once resolved: ${JSON.stringify({
|
|
27685
|
+
documentFailures: asRow(written.documents)?.failures,
|
|
27686
|
+
collisions: written.collisions,
|
|
27687
|
+
invalid: written.invalid
|
|
27688
|
+
})}`);
|
|
27689
|
+
}
|
|
27690
|
+
return written;
|
|
27691
|
+
}
|
|
27692
|
+
|
|
27395
27693
|
// src/commands/core.ts
|
|
27396
|
-
function readItemsFile(
|
|
27397
|
-
const trimmed2 = (0,
|
|
27694
|
+
function readItemsFile(path10) {
|
|
27695
|
+
const trimmed2 = (0, import_node_fs12.readFileSync)(path10, "utf-8").trim();
|
|
27398
27696
|
if (trimmed2.startsWith("[")) {
|
|
27399
27697
|
const arr = JSON.parse(trimmed2);
|
|
27400
27698
|
if (!Array.isArray(arr)) throw new Error("--file JSON must be an array of row objects");
|
|
@@ -27874,6 +28172,26 @@ var missionArgs = withArgs({
|
|
|
27874
28172
|
dryRun: { type: "boolean", description: "Print the request that would be sent; perform no write" },
|
|
27875
28173
|
pin: { type: "boolean", description: "Pin created/reused mission as CLI context" }
|
|
27876
28174
|
});
|
|
28175
|
+
var missionTransferArgs = withArgs({
|
|
28176
|
+
out: { type: "string", description: "mission export: directory to write export.jsonl and objects/ into (must not hold an export yet)" },
|
|
28177
|
+
from: { type: "string", description: "mission import: directory written by `hive mission export`" },
|
|
28178
|
+
changeId: { type: "string", description: "mission import: change or ticket id, recorded in the audit event (required unless --dry-run)" },
|
|
28179
|
+
principalMap: { type: "string", description: "mission import: JSON file mapping source principal ids to target principal ids" },
|
|
28180
|
+
dryRun: { type: "boolean", description: "mission import: report what would change; write nothing" }
|
|
28181
|
+
});
|
|
28182
|
+
function explicitMissionId(args, action) {
|
|
28183
|
+
const missionId = String(args.missionId || args.id || "").trim();
|
|
28184
|
+
if (!missionId) throw commandError("MISSION_REQUIRED", 2, `${action} needs --mission-id <id> (a pinned mission is not used here)`);
|
|
28185
|
+
return missionId;
|
|
28186
|
+
}
|
|
28187
|
+
function readPrincipalMap(file2) {
|
|
28188
|
+
if (!file2) return {};
|
|
28189
|
+
const raw = readJsonFile(String(file2));
|
|
28190
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw) || !Object.values(raw).every((v) => typeof v === "string" && v !== "")) {
|
|
28191
|
+
throw commandError("INVALID_PRINCIPAL_MAP", 2, "--principal-map must be a JSON object of source id \u2192 target id strings");
|
|
28192
|
+
}
|
|
28193
|
+
return raw;
|
|
28194
|
+
}
|
|
27877
28195
|
var mission = defineCommand({
|
|
27878
28196
|
meta: { name: "mission", description: "Missions, their cases, bundles and members" },
|
|
27879
28197
|
args: missionArgs,
|
|
@@ -27914,6 +28232,45 @@ var mission = defineCommand({
|
|
|
27914
28232
|
return runMissionSummary(args);
|
|
27915
28233
|
}
|
|
27916
28234
|
}),
|
|
28235
|
+
export: defineCommand({
|
|
28236
|
+
meta: {
|
|
28237
|
+
name: "export",
|
|
28238
|
+
description: "Export a mission (records, cases, documents with their bytes, member ids) into a directory (--mission-id, --out; admin)"
|
|
28239
|
+
},
|
|
28240
|
+
args: missionTransferArgs,
|
|
28241
|
+
async run({ args }) {
|
|
28242
|
+
const { client, fmt } = ctx(args);
|
|
28243
|
+
const missionId = explicitMissionId(args, "mission export");
|
|
28244
|
+
const outDir = String(args.out || "").trim();
|
|
28245
|
+
if (!outDir) throw commandError("OUT_REQUIRED", 2, "mission export needs --out <directory>");
|
|
28246
|
+
const result = await exportMission(client, { missionId, outDir, log: (l) => process.stderr.write(`${l}
|
|
28247
|
+
`) });
|
|
28248
|
+
return output(result, fmt);
|
|
28249
|
+
}
|
|
28250
|
+
}),
|
|
28251
|
+
import: defineCommand({
|
|
28252
|
+
meta: {
|
|
28253
|
+
name: "import",
|
|
28254
|
+
description: "Import a `hive mission export` directory into an existing mission of this tenant, without re-evaluation (--mission-id, --from, --change-id; admin)"
|
|
28255
|
+
},
|
|
28256
|
+
args: missionTransferArgs,
|
|
28257
|
+
async run({ args }) {
|
|
28258
|
+
const { client, fmt } = ctx(args);
|
|
28259
|
+
const missionId = explicitMissionId(args, "mission import");
|
|
28260
|
+
const fromDir = String(args.from || "").trim();
|
|
28261
|
+
if (!fromDir) throw commandError("FROM_REQUIRED", 2, "mission import needs --from <directory>");
|
|
28262
|
+
const result = await importMission(client, {
|
|
28263
|
+
missionId,
|
|
28264
|
+
fromDir,
|
|
28265
|
+
changeId: args.changeId ? String(args.changeId) : void 0,
|
|
28266
|
+
principalMap: readPrincipalMap(args.principalMap),
|
|
28267
|
+
dryRun: args.dryRun === true,
|
|
28268
|
+
log: (l) => process.stderr.write(`${l}
|
|
28269
|
+
`)
|
|
28270
|
+
});
|
|
28271
|
+
return output(result, fmt);
|
|
28272
|
+
}
|
|
28273
|
+
}),
|
|
27917
28274
|
use: defineCommand({
|
|
27918
28275
|
meta: { name: "use", description: "Pin a mission id for later commands (--id)" },
|
|
27919
28276
|
args: missionArgs,
|
|
@@ -28094,9 +28451,9 @@ var mission = defineCommand({
|
|
|
28094
28451
|
const missionId = requireMissionContext(args, "mission member grant");
|
|
28095
28452
|
const principal = resolvePrincipal(args);
|
|
28096
28453
|
const body = { ...principal, role: validateMissionGrantRole(args.role) };
|
|
28097
|
-
const
|
|
28098
|
-
if (args.dryRun) return output(dryRunResult("POST",
|
|
28099
|
-
const res = await client.post(
|
|
28454
|
+
const path10 = `/api/missions/${enc(missionId)}/members`;
|
|
28455
|
+
if (args.dryRun) return output(dryRunResult("POST", path10, body), fmt);
|
|
28456
|
+
const res = await client.post(path10, body);
|
|
28100
28457
|
assertMissionMembershipOk(res.status, res.data, "grant mission member");
|
|
28101
28458
|
const data = recordOf3(res.data);
|
|
28102
28459
|
const created = data.created === true;
|
|
@@ -28122,9 +28479,9 @@ var mission = defineCommand({
|
|
|
28122
28479
|
throw commandError("EMAIL_INVALID", 2, `--email '${raw}' is not an email. admit is by email; use \`mission members grant --principal-sub\` for an OIDC sub.`);
|
|
28123
28480
|
}
|
|
28124
28481
|
const body = { principalEmail: raw, role: validateMissionGrantRole(args.role) };
|
|
28125
|
-
const
|
|
28126
|
-
if (args.dryRun) return output(dryRunResult("POST",
|
|
28127
|
-
const res = await client.post(
|
|
28482
|
+
const path10 = `/api/missions/${enc(missionId)}/members`;
|
|
28483
|
+
if (args.dryRun) return output(dryRunResult("POST", path10, body), fmt);
|
|
28484
|
+
const res = await client.post(path10, body);
|
|
28128
28485
|
assertMissionMembershipOk(res.status, res.data, "admit mission member");
|
|
28129
28486
|
const data = recordOf3(res.data);
|
|
28130
28487
|
const created = data.created === true;
|
|
@@ -28176,9 +28533,9 @@ var mission = defineCommand({
|
|
|
28176
28533
|
printContextNotice(args, { mission: true });
|
|
28177
28534
|
const missionId = requireMissionContext(args, "mission member revoke");
|
|
28178
28535
|
const userId = reqAny(args, "userId", "id", "principalSub");
|
|
28179
|
-
const
|
|
28180
|
-
if (args.dryRun) return output(dryRunResult("DELETE",
|
|
28181
|
-
const res = await client.del(
|
|
28536
|
+
const path10 = `/api/missions/${enc(missionId)}/members/${enc(userId)}`;
|
|
28537
|
+
if (args.dryRun) return output(dryRunResult("DELETE", path10), fmt);
|
|
28538
|
+
const res = await client.del(path10);
|
|
28182
28539
|
if (res.status === 404 && recordOf3(res.data).error === "member_not_found") {
|
|
28183
28540
|
remoteFailureHandled();
|
|
28184
28541
|
return output({ revoked: false, notFound: true, userId }, fmt);
|
|
@@ -28227,10 +28584,10 @@ var mission = defineCommand({
|
|
|
28227
28584
|
"Changing tenantWideRead to true broadens mission visibility to the whole tenant. Re-run with --yes."
|
|
28228
28585
|
);
|
|
28229
28586
|
}
|
|
28230
|
-
const
|
|
28587
|
+
const path10 = `/api/missions/${enc(missionId)}/access-policy`;
|
|
28231
28588
|
const body = { tenantWideRead };
|
|
28232
|
-
if (args.dryRun) return output(dryRunResult("PATCH",
|
|
28233
|
-
const res = await client.patch(
|
|
28589
|
+
if (args.dryRun) return output(dryRunResult("PATCH", path10, body), fmt);
|
|
28590
|
+
const res = await client.patch(path10, body);
|
|
28234
28591
|
assertRemoteOk(res.status, res.data, "set mission access policy");
|
|
28235
28592
|
return output({ updated: true, missionId, policy: recordOf3(res.data).policy ?? { tenantWideRead } }, fmt);
|
|
28236
28593
|
}
|
|
@@ -28519,16 +28876,16 @@ var upgrade = defineCommand({
|
|
|
28519
28876
|
|
|
28520
28877
|
// src/commands/data.ts
|
|
28521
28878
|
init_cjs_shims();
|
|
28522
|
-
var
|
|
28523
|
-
var
|
|
28879
|
+
var import_node_fs14 = __toESM(require("fs"), 1);
|
|
28880
|
+
var import_node_path13 = __toESM(require("path"), 1);
|
|
28524
28881
|
var ajvModule2 = __toESM(require_ajv(), 1);
|
|
28525
28882
|
var ajvFormatsModule2 = __toESM(require_dist(), 1);
|
|
28526
28883
|
|
|
28527
28884
|
// src/lib/application-package.ts
|
|
28528
28885
|
init_cjs_shims();
|
|
28529
|
-
var
|
|
28530
|
-
var
|
|
28531
|
-
var
|
|
28886
|
+
var import_node_crypto6 = require("crypto");
|
|
28887
|
+
var import_node_fs13 = require("fs");
|
|
28888
|
+
var import_node_path12 = require("path");
|
|
28532
28889
|
var ajvModule = __toESM(require_ajv(), 1);
|
|
28533
28890
|
var ajvFormatsModule = __toESM(require_dist(), 1);
|
|
28534
28891
|
|
|
@@ -28646,7 +29003,7 @@ var envelopeAjv = new AjvCtor({ allErrors: true, strict: false });
|
|
|
28646
29003
|
addFormats(envelopeAjv);
|
|
28647
29004
|
var validateStarterEnvelope = envelopeAjv.compile(DEFAULT_ENVELOPE_SCHEMA);
|
|
28648
29005
|
function sha256Hex(bytes) {
|
|
28649
|
-
return (0,
|
|
29006
|
+
return (0, import_node_crypto6.createHash)("sha256").update(bytes).digest("hex");
|
|
28650
29007
|
}
|
|
28651
29008
|
function formatBytes(n) {
|
|
28652
29009
|
if (n >= 1024 * 1024) return `${(n / (1024 * 1024)).toFixed(1)} MiB`;
|
|
@@ -28654,7 +29011,7 @@ function formatBytes(n) {
|
|
|
28654
29011
|
return `${n} B`;
|
|
28655
29012
|
}
|
|
28656
29013
|
function loadApplicationPackage(inputPath, opts = {}) {
|
|
28657
|
-
const st = (0,
|
|
29014
|
+
const st = (0, import_node_fs13.statSync)(inputPath);
|
|
28658
29015
|
const envelope = st.isDirectory() ? buildEnvelopeFromDirectory(inputPath) : readEnvelopeJson(inputPath);
|
|
28659
29016
|
const validation = validateApplicationEnvelope(envelope, {
|
|
28660
29017
|
inputPath,
|
|
@@ -28664,7 +29021,7 @@ function loadApplicationPackage(inputPath, opts = {}) {
|
|
|
28664
29021
|
return { envelope, summary: validation.summary, validation };
|
|
28665
29022
|
}
|
|
28666
29023
|
function readEnvelopeJson(inputPath) {
|
|
28667
|
-
const parsed = JSON.parse((0,
|
|
29024
|
+
const parsed = JSON.parse((0, import_node_fs13.readFileSync)(inputPath, "utf8"));
|
|
28668
29025
|
const envelope = parsed?.envelope && typeof parsed.envelope === "object" ? parsed.envelope : parsed;
|
|
28669
29026
|
if (!envelope || typeof envelope !== "object" || Array.isArray(envelope)) {
|
|
28670
29027
|
throw new Error(`${inputPath}: expected a JobApplication envelope object or { "envelope": ... } wrapper`);
|
|
@@ -28673,10 +29030,10 @@ function readEnvelopeJson(inputPath) {
|
|
|
28673
29030
|
}
|
|
28674
29031
|
function buildEnvelopeFromDirectory(folder) {
|
|
28675
29032
|
const entries = [];
|
|
28676
|
-
for (const name of (0,
|
|
29033
|
+
for (const name of (0, import_node_fs13.readdirSync)(folder).sort((a, b) => a.localeCompare(b))) {
|
|
28677
29034
|
if (name.startsWith(".")) continue;
|
|
28678
|
-
const full = (0,
|
|
28679
|
-
if (!(0,
|
|
29035
|
+
const full = (0, import_node_path12.join)(folder, name);
|
|
29036
|
+
if (!(0, import_node_fs13.statSync)(full).isFile()) continue;
|
|
28680
29037
|
const match = name.match(APP_FILE_RE);
|
|
28681
29038
|
const wireMatch = match ? null : name.match(WIRE_FILE_RE);
|
|
28682
29039
|
if (!match && !wireMatch) continue;
|
|
@@ -28685,7 +29042,7 @@ function buildEnvelopeFromDirectory(folder) {
|
|
|
28685
29042
|
const ext = (match ? match[3] : wireMatch[2]).toLowerCase();
|
|
28686
29043
|
let role = "pdf";
|
|
28687
29044
|
if (ext === "xml") {
|
|
28688
|
-
const xml = (0,
|
|
29045
|
+
const xml = (0, import_node_fs13.readFileSync)(full, "utf8");
|
|
28689
29046
|
if (/<Document[\s>]/i.test(xml)) role = "manifest";
|
|
28690
29047
|
else if (FORM_XML_RE.test(xml)) role = "form";
|
|
28691
29048
|
else continue;
|
|
@@ -28708,8 +29065,8 @@ function buildEnvelopeFromDirectory(folder) {
|
|
|
28708
29065
|
group.sort((a, b) => roleOrder[a.role] - roleOrder[b.role] || partNo(a.partName) - partNo(b.partName));
|
|
28709
29066
|
const applicationId = group[0].applicationId;
|
|
28710
29067
|
const form = group.find((entry) => entry.role === "form");
|
|
28711
|
-
const createdAt = form ? extractElement((0,
|
|
28712
|
-
const files = group.map((entry) => inlineFile(entry.filename, (0,
|
|
29068
|
+
const createdAt = form ? extractElement((0, import_node_fs13.readFileSync)(form.path, "utf8"), "sendtimestamp") : null;
|
|
29069
|
+
const files = group.map((entry) => inlineFile(entry.filename, (0, import_node_fs13.readFileSync)(entry.path), entry.ext));
|
|
28713
29070
|
return {
|
|
28714
29071
|
schema_version: "1.0",
|
|
28715
29072
|
application_id: applicationId,
|
|
@@ -28815,13 +29172,13 @@ function appendStarterSchemaErrors(envelope, errors) {
|
|
|
28815
29172
|
}
|
|
28816
29173
|
}
|
|
28817
29174
|
function formatSchemaError(error51) {
|
|
28818
|
-
const
|
|
29175
|
+
const path10 = error51.instancePath || "/";
|
|
28819
29176
|
if (error51.keyword === "additionalProperties") {
|
|
28820
29177
|
const params = recordOf4(error51.params);
|
|
28821
29178
|
const prop = String(params.additionalProperty || "");
|
|
28822
|
-
return `schema ${
|
|
29179
|
+
return `schema ${path10}: additional property '${prop}' is not allowed`;
|
|
28823
29180
|
}
|
|
28824
|
-
return `schema ${
|
|
29181
|
+
return `schema ${path10}: ${error51.message || error51.keyword}`;
|
|
28825
29182
|
}
|
|
28826
29183
|
function recordOf4(value) {
|
|
28827
29184
|
return value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
@@ -28905,7 +29262,7 @@ function extractManifestParts(xml) {
|
|
|
28905
29262
|
return parts;
|
|
28906
29263
|
}
|
|
28907
29264
|
function producerPartName(filename) {
|
|
28908
|
-
const match = (0,
|
|
29265
|
+
const match = (0, import_node_path12.basename)(filename).match(APP_FILE_RE);
|
|
28909
29266
|
return match?.[2] || null;
|
|
28910
29267
|
}
|
|
28911
29268
|
function textOf(xml, tag) {
|
|
@@ -28922,7 +29279,7 @@ function summarizeEnvelope(envelope, opts) {
|
|
|
28922
29279
|
return {
|
|
28923
29280
|
compatibility: APPLICATION_PACKAGE_COMPATIBILITY,
|
|
28924
29281
|
source: opts.source,
|
|
28925
|
-
inputPath: opts.inputPath ? statMaybe(opts.inputPath)?.isDirectory() ? opts.inputPath : (0,
|
|
29282
|
+
inputPath: opts.inputPath ? statMaybe(opts.inputPath)?.isDirectory() ? opts.inputPath : (0, import_node_path12.basename)(opts.inputPath) : "",
|
|
28926
29283
|
schemaVersion: envelope.schema_version ? String(envelope.schema_version) : null,
|
|
28927
29284
|
packageFormatVersion: envelope.package_format_version ? String(envelope.package_format_version) : null,
|
|
28928
29285
|
applicationId: envelope.application_id ? String(envelope.application_id) : null,
|
|
@@ -28945,7 +29302,7 @@ function summarizeEnvelope(envelope, opts) {
|
|
|
28945
29302
|
}
|
|
28946
29303
|
function statMaybe(inputPath) {
|
|
28947
29304
|
try {
|
|
28948
|
-
return (0,
|
|
29305
|
+
return (0, import_node_fs13.statSync)(inputPath);
|
|
28949
29306
|
} catch {
|
|
28950
29307
|
return null;
|
|
28951
29308
|
}
|
|
@@ -29026,7 +29383,7 @@ function localValidationOutput(validation) {
|
|
|
29026
29383
|
}
|
|
29027
29384
|
function contentTypeFor(filePath, override) {
|
|
29028
29385
|
if (typeof override === "string" && override.trim()) return override.trim();
|
|
29029
|
-
const ext =
|
|
29386
|
+
const ext = import_node_path13.default.extname(filePath).toLowerCase();
|
|
29030
29387
|
if (ext === ".pdf") return "application/pdf";
|
|
29031
29388
|
if (ext === ".xml") return "application/xml";
|
|
29032
29389
|
if (ext === ".json") return "application/json";
|
|
@@ -29046,8 +29403,8 @@ var ingest = defineCommand({
|
|
|
29046
29403
|
const body = { missionId: args.missionId, caseId: args.caseId };
|
|
29047
29404
|
if (args.url) body.url = args.url;
|
|
29048
29405
|
if (args.file) {
|
|
29049
|
-
body.filename =
|
|
29050
|
-
body.contentBase64 =
|
|
29406
|
+
body.filename = import_node_path13.default.basename(args.file);
|
|
29407
|
+
body.contentBase64 = import_node_fs14.default.readFileSync(args.file).toString("base64");
|
|
29051
29408
|
}
|
|
29052
29409
|
return output((await client.post("/api/ingest", body)).data, fmt);
|
|
29053
29410
|
}
|
|
@@ -29635,10 +29992,10 @@ var document2 = defineCommand({
|
|
|
29635
29992
|
const missionId = requireMissionContext(args, "document upload");
|
|
29636
29993
|
req(args, "file");
|
|
29637
29994
|
const filePath = String(args.file);
|
|
29638
|
-
const bytes =
|
|
29995
|
+
const bytes = import_node_fs14.default.readFileSync(filePath);
|
|
29639
29996
|
if (!bytes.length) throw commandError("EMPTY_FILE", 1, `${filePath} is empty`);
|
|
29640
29997
|
const body = {
|
|
29641
|
-
filename: args.filename ||
|
|
29998
|
+
filename: args.filename || import_node_path13.default.basename(filePath),
|
|
29642
29999
|
contentType: contentTypeFor(filePath, args.contentType),
|
|
29643
30000
|
bytesBase64: bytes.toString("base64")
|
|
29644
30001
|
};
|