node-autotask 0.37.1 → 0.38.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/CHANGELOG.md +17 -0
- package/MCP_TOOL_CATALOG.json +127 -44
- package/MCP_TOOL_MANIFEST.md +8 -8
- package/N8N_MCP_MANIFEST.json +4 -4
- package/N8N_MCP_MANIFEST.md +5 -5
- package/README.md +3 -0
- package/capabilities.json +2454 -1698
- package/dist/capabilities.cjs +2 -2
- package/dist/capabilities.js +1 -1
- package/dist/{chunk-7IADHNBZ.js → chunk-4QHGCYEI.js} +2255 -1946
- package/dist/chunk-5VHSLJMR.js +71 -0
- package/dist/{chunk-HBYKTXN3.cjs → chunk-73JMTV4O.cjs} +2453 -1697
- package/dist/{chunk-PFFW4DIK.cjs → chunk-7FNKFNIJ.cjs} +285 -285
- package/dist/{chunk-25VGFT5M.cjs → chunk-DCTUBUIZ.cjs} +143 -143
- package/dist/{chunk-7WI7FBPB.js → chunk-IY3WCPCK.js} +2 -2
- package/dist/{chunk-TBFXRNNE.cjs → chunk-IY5QZZVF.cjs} +2389 -2080
- package/dist/{chunk-PFJAMFUL.js → chunk-KPYXO7F5.js} +2 -2
- package/dist/chunk-MJTKK3QG.cjs +71 -0
- package/dist/{chunk-KQ6HMBB4.js → chunk-U3K6IDKB.js} +2453 -1697
- package/dist/{index-CqepIQfp.d.cts → index-BFbUB5YD.d.cts} +28 -8
- package/dist/{index-m-7fOwFl.d.cts → index-BQVStxwi.d.cts} +15 -1
- package/dist/{index-m-7fOwFl.d.ts → index-BQVStxwi.d.ts} +15 -1
- package/dist/{index-BDqw377y.d.ts → index-Q-4HQEEb.d.ts} +28 -8
- package/dist/index.cjs +27 -22
- package/dist/index.d.cts +26 -5
- package/dist/index.d.ts +26 -5
- package/dist/index.js +9 -4
- package/dist/operations/index.cjs +247 -227
- package/dist/operations/index.d.cts +16 -4
- package/dist/operations/index.d.ts +16 -4
- package/dist/operations/index.js +58 -38
- package/dist/pool.cjs +10 -9
- package/dist/pool.d.cts +2 -2
- package/dist/pool.d.ts +2 -2
- package/dist/pool.js +5 -4
- package/dist/resources/index.cjs +5 -4
- package/dist/resources/index.d.cts +2 -2
- package/dist/resources/index.d.ts +2 -2
- package/dist/resources/index.js +4 -3
- package/dist/types/index.d.cts +1 -1
- package/dist/types/index.d.ts +1 -1
- package/dist/untrusted.cjs +24 -70
- package/dist/untrusted.js +12 -58
- package/docs/API.md +101 -0
- package/examples/mcp/manifest.ts +5 -0
- package/examples/mcp/rank.ts +62 -0
- package/examples/mcp/tools-meta.ts +6 -1
- package/package.json +1 -1
|
@@ -64,29 +64,33 @@
|
|
|
64
64
|
|
|
65
65
|
|
|
66
66
|
|
|
67
|
-
var _chunkTBFXRNNEcjs = require('../chunk-TBFXRNNE.cjs');
|
|
68
67
|
|
|
69
68
|
|
|
70
|
-
|
|
69
|
+
|
|
70
|
+
var _chunkIY5QZZVFcjs = require('../chunk-IY5QZZVF.cjs');
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
var _chunk73JMTV4Ocjs = require('../chunk-73JMTV4O.cjs');
|
|
74
|
+
require('../chunk-MJTKK3QG.cjs');
|
|
71
75
|
|
|
72
76
|
// src/operations/searchAcrossResources.ts
|
|
73
77
|
var DEFAULT_LIMIT = 25;
|
|
74
78
|
function resourceFor(client, key) {
|
|
75
|
-
return client[
|
|
79
|
+
return client[_chunkIY5QZZVFcjs.camelKey.call(void 0, key)];
|
|
76
80
|
}
|
|
77
81
|
async function searchAcrossResources(client, query, opts = {}) {
|
|
78
82
|
const text = query.trim();
|
|
79
83
|
if (text === "") {
|
|
80
|
-
throw new (0,
|
|
84
|
+
throw new (0, _chunkIY5QZZVFcjs.AutotaskConfigError)("searchAcrossResources: query must be a non-empty string");
|
|
81
85
|
}
|
|
82
|
-
const keys = _nullishCoalesce(opts.resources, () => (
|
|
86
|
+
const keys = _nullishCoalesce(opts.resources, () => ( _chunkIY5QZZVFcjs.WORKFLOW_RESOURCES));
|
|
83
87
|
if (keys.length === 0) {
|
|
84
|
-
throw new (0,
|
|
88
|
+
throw new (0, _chunkIY5QZZVFcjs.AutotaskConfigError)("searchAcrossResources: no resources requested");
|
|
85
89
|
}
|
|
86
|
-
const limit =
|
|
90
|
+
const limit = _chunkIY5QZZVFcjs.clampPageSize.call(void 0, _nullishCoalesce(opts.limit, () => ( DEFAULT_LIMIT)));
|
|
87
91
|
const totalLimit = opts.totalLimit;
|
|
88
92
|
if (totalLimit !== void 0 && !(Number.isInteger(totalLimit) && totalLimit >= 1)) {
|
|
89
|
-
throw new (0,
|
|
93
|
+
throw new (0, _chunkIY5QZZVFcjs.AutotaskConfigError)("searchAcrossResources: totalLimit must be a positive integer");
|
|
90
94
|
}
|
|
91
95
|
const results = [];
|
|
92
96
|
const skipped = [];
|
|
@@ -117,7 +121,7 @@ async function searchAcrossResources(client, query, opts = {}) {
|
|
|
117
121
|
|
|
118
122
|
// src/operations/resolveAny.ts
|
|
119
123
|
function resourceFor2(client, key) {
|
|
120
|
-
return client[
|
|
124
|
+
return client[_chunkIY5QZZVFcjs.camelKey.call(void 0, key)];
|
|
121
125
|
}
|
|
122
126
|
var FAULT_CATEGORIES = /* @__PURE__ */ new Set(["auth", "rate_limit", "server", "network", "timeout", "policy"]);
|
|
123
127
|
function missCost(identifier) {
|
|
@@ -126,13 +130,13 @@ function missCost(identifier) {
|
|
|
126
130
|
}
|
|
127
131
|
async function resolveAny(client, identifier, opts = {}) {
|
|
128
132
|
if (typeof identifier === "number") {
|
|
129
|
-
|
|
133
|
+
_chunkIY5QZZVFcjs.parseIdentifier.call(void 0, identifier, "identifier");
|
|
130
134
|
} else if (identifier.trim() === "") {
|
|
131
|
-
throw new (0,
|
|
135
|
+
throw new (0, _chunkIY5QZZVFcjs.AutotaskConfigError)("resolveAny: identifier must be non-empty");
|
|
132
136
|
}
|
|
133
|
-
const keys = _nullishCoalesce(opts.resources, () => (
|
|
137
|
+
const keys = _nullishCoalesce(opts.resources, () => ( _chunkIY5QZZVFcjs.WORKFLOW_RESOURCES));
|
|
134
138
|
if (keys.length === 0) {
|
|
135
|
-
throw new (0,
|
|
139
|
+
throw new (0, _chunkIY5QZZVFcjs.AutotaskConfigError)("resolveAny: no resources requested");
|
|
136
140
|
}
|
|
137
141
|
const results = [];
|
|
138
142
|
for (const key of keys) {
|
|
@@ -162,9 +166,9 @@ async function resolveAny(client, identifier, opts = {}) {
|
|
|
162
166
|
} catch (err) {
|
|
163
167
|
let code;
|
|
164
168
|
let candidates = [];
|
|
165
|
-
if (err instanceof
|
|
169
|
+
if (err instanceof _chunkIY5QZZVFcjs.AutotaskConfigError) {
|
|
166
170
|
code = "CONFIG_ERROR";
|
|
167
|
-
} else if (
|
|
171
|
+
} else if (_chunkIY5QZZVFcjs.isAutotaskError.call(void 0, err)) {
|
|
168
172
|
if (FAULT_CATEGORIES.has(err.category)) throw err;
|
|
169
173
|
code = err.code;
|
|
170
174
|
if (code === "RESOLUTION_AMBIGUOUS" && err.resourceIds !== void 0) {
|
|
@@ -191,7 +195,7 @@ async function resolveAny(client, identifier, opts = {}) {
|
|
|
191
195
|
// src/operations/aggregate.ts
|
|
192
196
|
var AGGREGATE_TOP_MAX = 100;
|
|
193
197
|
var AGGREGATE_DEFAULT_TOP = 25;
|
|
194
|
-
var AGGREGATE_DEFAULT_LIMIT =
|
|
198
|
+
var AGGREGATE_DEFAULT_LIMIT = _chunkIY5QZZVFcjs.BOUNDED_QUERY_MAX_LIMIT;
|
|
195
199
|
var AGGREGATE_DATE_BUCKETS = ["month", "week", "year"];
|
|
196
200
|
var DATE_ONLY_RE = /^(\d{4})-(\d{2})-(\d{2})$/;
|
|
197
201
|
var DATETIME_RE = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(\.\d{1,9})?(Z|[+-]\d{2}:?\d{2})?$/;
|
|
@@ -248,10 +252,10 @@ function dateBucketLabel(value, bucket) {
|
|
|
248
252
|
}
|
|
249
253
|
var QUERY_RESOURCE_KEYS = (() => {
|
|
250
254
|
const s = /* @__PURE__ */ new Set();
|
|
251
|
-
for (const rec of
|
|
255
|
+
for (const rec of _chunk73JMTV4Ocjs.CAPABILITIES) if (rec.operation === "query") s.add(rec.resource);
|
|
252
256
|
return s;
|
|
253
257
|
})();
|
|
254
|
-
var AGGREGATE_OPT_KEYS = ["groupBy", "sum", "top", "limit"];
|
|
258
|
+
var AGGREGATE_OPT_KEYS = ["groupBy", "sum", "top", "limit", "names"];
|
|
255
259
|
var OP_RE = /^([a-z0-9_]+)\.query$/;
|
|
256
260
|
function num2(v) {
|
|
257
261
|
return typeof v === "number" && Number.isFinite(v) ? v : 0;
|
|
@@ -284,15 +288,15 @@ function parseFilterConditions(filter, problems) {
|
|
|
284
288
|
return [];
|
|
285
289
|
}
|
|
286
290
|
try {
|
|
287
|
-
return
|
|
291
|
+
return _chunkIY5QZZVFcjs.buildFilter.call(void 0, conds).filter;
|
|
288
292
|
} catch (err) {
|
|
289
|
-
problems.push(err instanceof
|
|
293
|
+
problems.push(err instanceof _chunkIY5QZZVFcjs.AutotaskConfigError ? err.message : `filter must be the query-bag filter (13 operators; caps 500 OR-conditions / 1 UDF / 8000 chars); ${String(err)}`);
|
|
290
294
|
return [];
|
|
291
295
|
}
|
|
292
296
|
}
|
|
293
297
|
function checkOptsBag(opts, problems) {
|
|
294
298
|
if (opts !== void 0 && (typeof opts !== "object" || opts === null || Array.isArray(opts))) {
|
|
295
|
-
throw new (0,
|
|
299
|
+
throw new (0, _chunkIY5QZZVFcjs.AutotaskConfigError)(
|
|
296
300
|
`aggregate: opts must be the options object (got ${Array.isArray(opts) ? "an array" : typeof opts})`,
|
|
297
301
|
{ operation: "operations.aggregate" }
|
|
298
302
|
);
|
|
@@ -302,50 +306,34 @@ function checkOptsBag(opts, problems) {
|
|
|
302
306
|
problems.push(`unknown opts key "${key}" \u2014 the bag is closed: ${AGGREGATE_OPT_KEYS.join(", ")}`);
|
|
303
307
|
}
|
|
304
308
|
}
|
|
309
|
+
if (_optionalChain([opts, 'optionalAccess', _2 => _2.names]) !== void 0 && typeof opts.names !== "boolean") problems.push(`names must be a boolean (got ${typeof opts.names})`);
|
|
305
310
|
}
|
|
306
|
-
function checkSumFields(name, fields,
|
|
311
|
+
function checkSumFields(name, fields, problems) {
|
|
307
312
|
if (fields === void 0) return [];
|
|
308
313
|
if (!Array.isArray(fields) || fields.length === 0 || fields.some((f) => typeof f !== "string" || f.trim() === "")) {
|
|
309
314
|
problems.push(`${name} must be a non-empty array of exact vendor field names (discover them via operations.fieldCatalog)`);
|
|
310
315
|
return [];
|
|
311
316
|
}
|
|
312
|
-
|
|
313
|
-
for (const f of fields) {
|
|
314
|
-
if (oracles.fieldSets === void 0 || !oracles.fieldSets.includes(f)) {
|
|
315
|
-
problems.push(`${name}: "${f}" is not a field of ${oracles.resourceKey} \u2014 a hallucinated field is a shape error, not a silent fold-miss (exact vendor field names via operations.fieldCatalog)`);
|
|
316
|
-
} else {
|
|
317
|
-
out.push(f);
|
|
318
|
-
}
|
|
319
|
-
}
|
|
320
|
-
return out;
|
|
317
|
+
return fields;
|
|
321
318
|
}
|
|
322
|
-
function parseGroupSpec(f, oracles, problems) {
|
|
323
|
-
const { resourceKey,
|
|
319
|
+
function parseGroupSpec(f, oracles, known, problems) {
|
|
320
|
+
const { resourceKey, dateSets } = oracles;
|
|
324
321
|
const at = f.indexOf("@");
|
|
325
|
-
if (at === -1) {
|
|
326
|
-
if (fieldSets === void 0 || !fieldSets.includes(f)) {
|
|
327
|
-
problems.push(`groupBy: "${f}" is not a field of ${resourceKey} \u2014 a hallucinated field is a shape error, not a silent fold-miss (exact vendor field names via operations.fieldCatalog)`);
|
|
328
|
-
return void 0;
|
|
329
|
-
}
|
|
330
|
-
return { name: f, base: f };
|
|
331
|
-
}
|
|
322
|
+
if (at === -1) return { name: f, base: f };
|
|
332
323
|
const base = f.slice(0, at);
|
|
333
324
|
const suffix = f.slice(at + 1);
|
|
334
325
|
if (!AGGREGATE_DATE_BUCKETS.includes(suffix)) {
|
|
335
326
|
problems.push(`groupBy: "${f}": unknown bucket suffix "${suffix}" \u2014 the closed set is month | week | year (the suffix applies to date-typed fields only)`);
|
|
336
327
|
return void 0;
|
|
337
328
|
}
|
|
338
|
-
if (
|
|
339
|
-
problems.push(`groupBy: "${f}": "${base}" is not a field of ${resourceKey} \u2014 a hallucinated field is a shape error, not a silent fold-miss (exact vendor field names via operations.fieldCatalog)`);
|
|
340
|
-
return void 0;
|
|
341
|
-
}
|
|
329
|
+
if (known !== void 0 && !known.includes(base)) return void 0;
|
|
342
330
|
if (dateSets === void 0 || !dateSets.includes(base)) {
|
|
343
331
|
problems.push(`groupBy: "${f}": "${base}" is not a date field of ${resourceKey} (the @month/@week/@year bucket suffix applies to date-typed fields of the resource's vendored model \u2014 exact vendor field names via operations.fieldCatalog)`);
|
|
344
332
|
return void 0;
|
|
345
333
|
}
|
|
346
334
|
return { name: f, base, bucket: suffix };
|
|
347
335
|
}
|
|
348
|
-
function parseGroupBy(opts, oracles, problems) {
|
|
336
|
+
function parseGroupBy(opts, oracles, known, problems) {
|
|
349
337
|
const groupBy = [];
|
|
350
338
|
if (opts.groupBy === void 0) return groupBy;
|
|
351
339
|
if (!Array.isArray(opts.groupBy) || opts.groupBy.length === 0 || opts.groupBy.some((f) => typeof f !== "string" || f.trim() === "")) {
|
|
@@ -353,7 +341,7 @@ function parseGroupBy(opts, oracles, problems) {
|
|
|
353
341
|
return groupBy;
|
|
354
342
|
}
|
|
355
343
|
for (const f of opts.groupBy) {
|
|
356
|
-
const spec = parseGroupSpec(f, oracles, problems);
|
|
344
|
+
const spec = parseGroupSpec(f, oracles, known, problems);
|
|
357
345
|
if (spec !== void 0) groupBy.push(spec);
|
|
358
346
|
}
|
|
359
347
|
return groupBy;
|
|
@@ -372,26 +360,49 @@ function parseTopAndLimit(opts, problems) {
|
|
|
372
360
|
if (!Number.isInteger(opts.limit)) {
|
|
373
361
|
problems.push(`limit must be an integer (got ${String(opts.limit)})`);
|
|
374
362
|
} else {
|
|
375
|
-
limit = Math.min(Math.max(opts.limit, 1),
|
|
363
|
+
limit = Math.min(Math.max(opts.limit, 1), _chunkIY5QZZVFcjs.BOUNDED_QUERY_MAX_LIMIT);
|
|
376
364
|
}
|
|
377
365
|
}
|
|
378
366
|
return { top, limit };
|
|
379
367
|
}
|
|
380
|
-
function
|
|
368
|
+
async function checkFieldNames(resourceKey, conditions, opts, problems) {
|
|
369
|
+
const record = resourceKey === void 0 ? void 0 : _chunk73JMTV4Ocjs.CAPABILITIES.find((r) => r.resource === resourceKey && r.operation === "query");
|
|
370
|
+
if (record === void 0) return void 0;
|
|
371
|
+
const strings = (v) => Array.isArray(v) ? v.filter((f) => typeof f === "string" && f.trim() !== "") : [];
|
|
372
|
+
const groupBy = strings(opts.groupBy);
|
|
373
|
+
const found = await _chunkIY5QZZVFcjs.findUnknownFieldNames.call(void 0, record, void 0, {
|
|
374
|
+
filter: _chunkIY5QZZVFcjs.collectFilterFieldNames.call(void 0, conditions),
|
|
375
|
+
groupBy: groupBy.map((f) => f.split("@")[0]),
|
|
376
|
+
sum: strings(opts.sum)
|
|
377
|
+
});
|
|
378
|
+
if (found === void 0) return void 0;
|
|
379
|
+
const refuse2 = (key, entry, base) => {
|
|
380
|
+
const named = entry === base ? `"${base}"` : `"${entry}": "${base}"`;
|
|
381
|
+
problems.push(`${key}: ${named} is not a field of ${resourceKey} \u2014 a hallucinated field is a shape error, not a silent fold-miss (exact vendor field names via operations.fieldCatalog; checked against ${found.authority})`);
|
|
382
|
+
};
|
|
383
|
+
for (const f of found.unknown["filter"]) refuse2("filter", f, f);
|
|
384
|
+
for (const f of groupBy) {
|
|
385
|
+
const base = f.split("@")[0];
|
|
386
|
+
if (found.unknown["groupBy"].includes(base)) refuse2("groupBy", f, base);
|
|
387
|
+
}
|
|
388
|
+
for (const f of found.unknown["sum"]) refuse2("sum", f, f);
|
|
389
|
+
return found.known;
|
|
390
|
+
}
|
|
391
|
+
async function validateAggregate(operation, filter, opts) {
|
|
381
392
|
const problems = [];
|
|
382
393
|
const resourceKey = parseOperationKey(operation, problems);
|
|
383
394
|
const conditions = parseFilterConditions(filter, problems);
|
|
384
395
|
checkOptsBag(opts, problems);
|
|
385
396
|
const oracles = {
|
|
386
397
|
resourceKey,
|
|
387
|
-
|
|
388
|
-
dateSets: resourceKey !== void 0 ? _chunkTBFXRNNEcjs.MODEL_DATE_FIELDS[resourceKey] : void 0
|
|
398
|
+
dateSets: resourceKey !== void 0 ? _chunkIY5QZZVFcjs.MODEL_DATE_FIELDS[resourceKey] : void 0
|
|
389
399
|
};
|
|
390
|
-
const
|
|
391
|
-
const
|
|
400
|
+
const known = await checkFieldNames(resourceKey, conditions, opts, problems);
|
|
401
|
+
const groupBy = parseGroupBy(opts, oracles, known, problems);
|
|
402
|
+
const sum = checkSumFields("sum", opts.sum, problems);
|
|
392
403
|
const { top, limit } = parseTopAndLimit(opts, problems);
|
|
393
404
|
if (problems.length > 0) {
|
|
394
|
-
throw new (0,
|
|
405
|
+
throw new (0, _chunkIY5QZZVFcjs.AutotaskConfigError)(
|
|
395
406
|
`aggregate: ${problems.length} problem(s) found pre-request (zero wire was issued)
|
|
396
407
|
- ` + problems.join("\n- "),
|
|
397
408
|
{ operation: "operations.aggregate" }
|
|
@@ -424,10 +435,10 @@ function foldGroups(items, v) {
|
|
|
424
435
|
return [...groups.values()].sort((a, b) => b.count - a.count || (a.keyOrder < b.keyOrder ? -1 : a.keyOrder > b.keyOrder ? 1 : 0));
|
|
425
436
|
}
|
|
426
437
|
async function aggregate(client, operation, filter, opts = {}) {
|
|
427
|
-
const v = validateAggregate(operation, filter, opts);
|
|
428
|
-
const holder = client[
|
|
438
|
+
const v = await validateAggregate(operation, filter, opts);
|
|
439
|
+
const holder = client[_chunkIY5QZZVFcjs.camelKey.call(void 0, v.resourceKey)];
|
|
429
440
|
if (holder === void 0) {
|
|
430
|
-
throw new (0,
|
|
441
|
+
throw new (0, _chunkIY5QZZVFcjs.AutotaskConfigError)(`aggregate: the client exposes no accessor for resource "${v.resourceKey}"`, {
|
|
431
442
|
operation: "operations.aggregate",
|
|
432
443
|
suggestedAction: "Rebuild the client from the SDK build that ships this registry (the resource set is pinned by the plan)."
|
|
433
444
|
});
|
|
@@ -444,9 +455,10 @@ async function aggregate(client, operation, filter, opts = {}) {
|
|
|
444
455
|
const res = await holder.queryBounded({ filter: wireFilter, limit: v.limit });
|
|
445
456
|
const sorted = foldGroups(res.items, v);
|
|
446
457
|
const top = sorted.slice(0, v.top);
|
|
458
|
+
const labelled = opts.names === false || v.groupBy.length === 0 ? void 0 : await _chunkIY5QZZVFcjs.labelRows.call(void 0, client, v.resourceKey, top.map((g) => g.key));
|
|
447
459
|
const result = {
|
|
448
460
|
mode: v.groupBy.length > 0 ? "group" : "sum",
|
|
449
|
-
groups: top.map((g) => ({ key: g.key, count: g.count, ...g.sums !== void 0 ? { sums: g.sums } : {} })),
|
|
461
|
+
groups: top.map((g, i) => ({ key: _nullishCoalesce(_optionalChain([labelled, 'optionalAccess', _3 => _3.rows, 'access', _4 => _4[i]]), () => ( g.key)), count: g.count, ...g.sums !== void 0 ? { sums: g.sums } : {} })),
|
|
450
462
|
totalGroups: sorted.length,
|
|
451
463
|
groupsTruncated: sorted.length > top.length,
|
|
452
464
|
totalScanned: res.fetched,
|
|
@@ -454,6 +466,8 @@ async function aggregate(client, operation, filter, opts = {}) {
|
|
|
454
466
|
};
|
|
455
467
|
if (res.blindSurface !== void 0) result.blindSurface = res.blindSurface;
|
|
456
468
|
if (res.emptyReason !== void 0) result.emptyReason = res.emptyReason;
|
|
469
|
+
if (res.relationNote !== void 0) result.relationNote = res.relationNote;
|
|
470
|
+
if (_optionalChain([labelled, 'optionalAccess', _5 => _5.names]) !== void 0) result.names = labelled.names;
|
|
457
471
|
return result;
|
|
458
472
|
}
|
|
459
473
|
|
|
@@ -472,12 +486,12 @@ var DEFAULT_CONTRACT_TYPE_RE = /^\s*(recurring|fixed)\b/i;
|
|
|
472
486
|
var CONTRACTS_PATH = "/V1.0/Contracts";
|
|
473
487
|
var COMPANIES_PATH = "/V1.0/Companies";
|
|
474
488
|
var BILLING_ITEMS_PATH = "/V1.0/BillingItems";
|
|
475
|
-
var LINE_TYPE_FIELDS = ["billingItemType", "timeEntryID", "expenseItemID", ...
|
|
476
|
-
var isLabour = (line) =>
|
|
489
|
+
var LINE_TYPE_FIELDS = ["billingItemType", "timeEntryID", "expenseItemID", ..._chunkIY5QZZVFcjs.CHARGE_LINE_FKS, ..._chunkIY5QZZVFcjs.SERVICE_LINE_FKS];
|
|
490
|
+
var isLabour = (line) => _chunkIY5QZZVFcjs.billingLineType.call(void 0, line) === "labour";
|
|
477
491
|
function picklistKey(c, dim, path, field, raw, missing) {
|
|
478
|
-
const id =
|
|
492
|
+
const id = _chunkIY5QZZVFcjs.num.call(void 0, raw);
|
|
479
493
|
if (id === 0) return { id: null, label: missing };
|
|
480
|
-
const label = _optionalChain([c, 'access',
|
|
494
|
+
const label = _optionalChain([c, 'access', _6 => _6.labels, 'access', _7 => _7[path], 'optionalAccess', _8 => _8.get, 'call', _9 => _9(field), 'optionalAccess', _10 => _10.get, 'call', _11 => _11(id)]);
|
|
481
495
|
if (label === void 0) {
|
|
482
496
|
c.unlabelled.add(`${dim}: ${field} value ${id} has no label on the live ${path} picklist (id-only)`);
|
|
483
497
|
return { id };
|
|
@@ -488,7 +502,7 @@ var DIMENSIONS = {
|
|
|
488
502
|
vertical: {
|
|
489
503
|
joins: { companies: ["marketSegmentID"] },
|
|
490
504
|
picklist: COMPANIES_PATH,
|
|
491
|
-
key: (c) => picklistKey(c, "vertical", COMPANIES_PATH, "marketSegmentID", _optionalChain([c, 'access',
|
|
505
|
+
key: (c) => picklistKey(c, "vertical", COMPANIES_PATH, "marketSegmentID", _optionalChain([c, 'access', _12 => _12.company, 'optionalAccess', _13 => _13["marketSegmentID"]]), "unassigned")
|
|
492
506
|
},
|
|
493
507
|
contractType: {
|
|
494
508
|
key: (c) => picklistKey(c, "contractType", CONTRACTS_PATH, "contractType", c.contract["contractType"], "none")
|
|
@@ -498,7 +512,7 @@ var DIMENSIONS = {
|
|
|
498
512
|
},
|
|
499
513
|
company: {
|
|
500
514
|
joins: { companies: ["companyName"] },
|
|
501
|
-
key: (c) => ({ id:
|
|
515
|
+
key: (c) => ({ id: _chunkIY5QZZVFcjs.num.call(void 0, c.line["companyID"]), name: String(_nullishCoalesce(_optionalChain([c, 'access', _14 => _14.company, 'optionalAccess', _15 => _15["companyName"]]), () => ( ""))) })
|
|
502
516
|
},
|
|
503
517
|
month: {
|
|
504
518
|
key: (c) => ({ id: c.invoice.month })
|
|
@@ -506,11 +520,11 @@ var DIMENSIONS = {
|
|
|
506
520
|
billingItemKind: {
|
|
507
521
|
lineFields: LINE_TYPE_FIELDS,
|
|
508
522
|
picklist: BILLING_ITEMS_PATH,
|
|
509
|
-
key: (c) =>
|
|
523
|
+
key: (c) => _chunkIY5QZZVFcjs.num.call(void 0, c.line["billingItemType"]) === 0 ? { id: _chunkIY5QZZVFcjs.billingLineType.call(void 0, c.line), label: _chunkIY5QZZVFcjs.billingLineType.call(void 0, c.line) } : picklistKey(c, "billingItemKind", BILLING_ITEMS_PATH, "billingItemType", c.line["billingItemType"], "other")
|
|
510
524
|
},
|
|
511
525
|
contract: {
|
|
512
526
|
joins: { contracts: ["contractName"] },
|
|
513
|
-
key: (c) => ({ id:
|
|
527
|
+
key: (c) => ({ id: _chunkIY5QZZVFcjs.num.call(void 0, c.line["contractID"]), name: String(_nullishCoalesce(c.contract["contractName"], () => ( ""))) })
|
|
514
528
|
},
|
|
515
529
|
// Per line (no contract-pointer fallback): association → level2 (the Line of Business, `name`) + level1 (the division).
|
|
516
530
|
lineOfBusiness: {
|
|
@@ -518,11 +532,11 @@ var DIMENSIONS = {
|
|
|
518
532
|
joins: { organizationalLevelAssociations: [], organizationalLevel1s: [], organizationalLevel2s: [] },
|
|
519
533
|
unresolved: "unresolvedAssociations",
|
|
520
534
|
key: (c) => {
|
|
521
|
-
const id =
|
|
535
|
+
const id = _chunkIY5QZZVFcjs.num.call(void 0, c.line["organizationalLevelAssociationID"]);
|
|
522
536
|
if (id === 0) return { id: null, label: "no LOB assigned" };
|
|
523
537
|
const a = c.joined.organizationalLevelAssociations.get(id);
|
|
524
|
-
const l1 = c.joined.organizationalLevel1s.get(
|
|
525
|
-
const l2 = c.joined.organizationalLevel2s.get(
|
|
538
|
+
const l1 = c.joined.organizationalLevel1s.get(_chunkIY5QZZVFcjs.num.call(void 0, _optionalChain([a, 'optionalAccess', _16 => _16["organizationalLevel1ID"]])));
|
|
539
|
+
const l2 = c.joined.organizationalLevel2s.get(_chunkIY5QZZVFcjs.num.call(void 0, _optionalChain([a, 'optionalAccess', _17 => _17["organizationalLevel2ID"]])));
|
|
526
540
|
if (l1 === void 0 || l2 === void 0) return "unresolvedAssociations";
|
|
527
541
|
return { id, name: String(_nullishCoalesce(l2["name"], () => ( ""))), division: String(_nullishCoalesce(l1["name"], () => ( ""))) };
|
|
528
542
|
}
|
|
@@ -533,9 +547,9 @@ var DIMENSIONS = {
|
|
|
533
547
|
joins: { timeEntries: [], resources: [] },
|
|
534
548
|
unresolved: "unresolvedTimeEntries",
|
|
535
549
|
key: (c) => {
|
|
536
|
-
const te =
|
|
550
|
+
const te = _chunkIY5QZZVFcjs.num.call(void 0, c.line["timeEntryID"]);
|
|
537
551
|
if (!isLabour(c.line) || te === 0) return { id: null, label: "n/a" };
|
|
538
|
-
const id =
|
|
552
|
+
const id = _chunkIY5QZZVFcjs.num.call(void 0, _optionalChain([c, 'access', _18 => _18.joined, 'access', _19 => _19.timeEntries, 'access', _20 => _20.get, 'call', _21 => _21(te), 'optionalAccess', _22 => _22["resourceID"]]));
|
|
539
553
|
const r = c.joined.resources.get(id);
|
|
540
554
|
if (r === void 0) return "unresolvedTimeEntries";
|
|
541
555
|
return { id, name: `${String(_nullishCoalesce(r["firstName"], () => ( "")))} ${String(_nullishCoalesce(r["lastName"], () => ( "")))}`.trim() };
|
|
@@ -546,58 +560,58 @@ var DIMENSIONS = {
|
|
|
546
560
|
joins: { billingCodes: [] },
|
|
547
561
|
unresolved: "unresolvedBillingCodes",
|
|
548
562
|
key: (c) => {
|
|
549
|
-
const id =
|
|
563
|
+
const id = _chunkIY5QZZVFcjs.num.call(void 0, c.line["billingCodeID"]);
|
|
550
564
|
if (id === 0) return { id: null, label: "none" };
|
|
551
565
|
const b = c.joined.billingCodes.get(id);
|
|
552
566
|
return b === void 0 ? "unresolvedBillingCodes" : { id, name: String(_nullishCoalesce(b["name"], () => ( ""))) };
|
|
553
567
|
}
|
|
554
568
|
}
|
|
555
569
|
};
|
|
556
|
-
var fk = (rows, field) => [...rows].map((r) =>
|
|
570
|
+
var fk = (rows, field) => [...rows].map((r) => _chunkIY5QZZVFcjs.num.call(void 0, r[field]));
|
|
557
571
|
var ONE_CHUNK = (idChunks) => Math.min(1, idChunks);
|
|
558
572
|
var JOINS = {
|
|
559
573
|
contracts: {
|
|
560
|
-
make: (http) => new (0,
|
|
574
|
+
make: (http) => new (0, _chunkIY5QZZVFcjs.ContractsResource)(http, PAGE),
|
|
561
575
|
fields: ["id", "contractType", "contractCategory"],
|
|
562
576
|
ids: (lines) => fk(lines, "contractID")
|
|
563
577
|
},
|
|
564
578
|
companies: {
|
|
565
|
-
make: (http) => new (0,
|
|
579
|
+
make: (http) => new (0, _chunkIY5QZZVFcjs.CompaniesResource)(http, PAGE),
|
|
566
580
|
fields: ["id"],
|
|
567
581
|
ids: (lines) => fk(lines, "companyID")
|
|
568
582
|
},
|
|
569
583
|
organizationalLevelAssociations: {
|
|
570
|
-
make: (http) => new (0,
|
|
584
|
+
make: (http) => new (0, _chunkIY5QZZVFcjs.OrganizationalLevelAssociationsResource)(http, PAGE),
|
|
571
585
|
fields: ["id", "organizationalLevel1ID", "organizationalLevel2ID"],
|
|
572
586
|
ids: (lines) => fk(lines, "organizationalLevelAssociationID")
|
|
573
587
|
},
|
|
574
588
|
organizationalLevel1s: {
|
|
575
|
-
make: (http) => new (0,
|
|
589
|
+
make: (http) => new (0, _chunkIY5QZZVFcjs.OrganizationalLevel1sResource)(http, PAGE),
|
|
576
590
|
fields: ["id", "name"],
|
|
577
591
|
ids: (_, j) => fk(j["organizationalLevelAssociations"].values(), "organizationalLevel1ID"),
|
|
578
592
|
chunks: ONE_CHUNK
|
|
579
593
|
},
|
|
580
594
|
organizationalLevel2s: {
|
|
581
|
-
make: (http) => new (0,
|
|
595
|
+
make: (http) => new (0, _chunkIY5QZZVFcjs.OrganizationalLevel2sResource)(http, PAGE),
|
|
582
596
|
fields: ["id", "name"],
|
|
583
597
|
ids: (_, j) => fk(j["organizationalLevelAssociations"].values(), "organizationalLevel2ID"),
|
|
584
598
|
chunks: ONE_CHUNK
|
|
585
599
|
},
|
|
586
600
|
timeEntries: {
|
|
587
|
-
make: (http) => new (0,
|
|
601
|
+
make: (http) => new (0, _chunkIY5QZZVFcjs.TimeEntriesResource)(http, PAGE),
|
|
588
602
|
fields: ["id", "resourceID"],
|
|
589
603
|
ids: (lines) => fk(lines.filter(isLabour), "timeEntryID"),
|
|
590
604
|
// One time entry per labour line: the line count is the upper bound (labour share unknown pre-walk).
|
|
591
605
|
chunks: (_, lines) => pages(lines)
|
|
592
606
|
},
|
|
593
607
|
resources: {
|
|
594
|
-
make: (http, client) => new (0,
|
|
608
|
+
make: (http, client) => new (0, _chunkIY5QZZVFcjs.ResourcesResource)(http, client.config, PAGE),
|
|
595
609
|
fields: ["id", "firstName", "lastName"],
|
|
596
610
|
ids: (_, j) => fk(j["timeEntries"].values(), "resourceID"),
|
|
597
611
|
chunks: ONE_CHUNK
|
|
598
612
|
},
|
|
599
613
|
billingCodes: {
|
|
600
|
-
make: (http) => new (0,
|
|
614
|
+
make: (http) => new (0, _chunkIY5QZZVFcjs.BillingCodesResource)(http, PAGE),
|
|
601
615
|
fields: ["id", "name"],
|
|
602
616
|
ids: (lines) => fk(lines, "billingCodeID")
|
|
603
617
|
}
|
|
@@ -632,7 +646,7 @@ function checkInt(name, v, def, max, problems) {
|
|
|
632
646
|
}
|
|
633
647
|
function validate(opts) {
|
|
634
648
|
if (typeof opts !== "object" || opts === null || Array.isArray(opts)) {
|
|
635
|
-
throw new (0,
|
|
649
|
+
throw new (0, _chunkIY5QZZVFcjs.AutotaskConfigError)("revenueRollup: opts must be the options object { <scope>, dateFrom, dateTo, ... } (zero wire was issued)", { operation: OP });
|
|
636
650
|
}
|
|
637
651
|
const o = opts;
|
|
638
652
|
const problems = [];
|
|
@@ -649,12 +663,12 @@ function validate(opts) {
|
|
|
649
663
|
if (scopeKind === "tenantWide" && o.tenantWide !== true) problems.push("tenantWide must be exactly true");
|
|
650
664
|
}
|
|
651
665
|
const { dateFrom, dateTo } = o;
|
|
652
|
-
if (!
|
|
666
|
+
if (!_chunkIY5QZZVFcjs.isDateYMD.call(void 0, dateFrom) || !_chunkIY5QZZVFcjs.isDateYMD.call(void 0, dateTo)) {
|
|
653
667
|
problems.push("dateFrom and dateTo are both required as YYYY-MM-DD (the window is inclusive, whole UTC days)");
|
|
654
668
|
} else if (dateFrom > dateTo) {
|
|
655
669
|
problems.push(`dateFrom ${dateFrom} is after dateTo ${dateTo}`);
|
|
656
|
-
} else if (
|
|
657
|
-
problems.push(`the window spans ${
|
|
670
|
+
} else if (_chunkIY5QZZVFcjs.monthsInWindow.call(void 0, dateFrom, dateTo) > _chunkIY5QZZVFcjs.PROFITABILITY_MAX_WINDOW_MONTHS) {
|
|
671
|
+
problems.push(`the window spans ${_chunkIY5QZZVFcjs.monthsInWindow.call(void 0, dateFrom, dateTo)} months; the cap is ${_chunkIY5QZZVFcjs.PROFITABILITY_MAX_WINDOW_MONTHS}`);
|
|
658
672
|
}
|
|
659
673
|
let groupBy = [...DEFAULT_GROUP_BY];
|
|
660
674
|
if (o.groupBy !== void 0) {
|
|
@@ -681,7 +695,7 @@ function validate(opts) {
|
|
|
681
695
|
};
|
|
682
696
|
if (o.includeNonChargeable !== void 0 && typeof o.includeNonChargeable !== "boolean") problems.push("includeNonChargeable must be a boolean");
|
|
683
697
|
if (problems.length > 0) {
|
|
684
|
-
throw new (0,
|
|
698
|
+
throw new (0, _chunkIY5QZZVFcjs.AutotaskConfigError)(`revenueRollup: ${problems.length} problem(s) found pre-request (zero wire was issued)
|
|
685
699
|
- ${problems.join("\n- ")}`, { operation: OP });
|
|
686
700
|
}
|
|
687
701
|
return v;
|
|
@@ -699,7 +713,7 @@ function resolveSelector(name, sel, values) {
|
|
|
699
713
|
}
|
|
700
714
|
function unmatched(name, what, values) {
|
|
701
715
|
const live = [...values].map(([id, l]) => `${id} ${l}`).join("; ") || "(the picklist serves no values)";
|
|
702
|
-
return new (0,
|
|
716
|
+
return new (0, _chunkIY5QZZVFcjs.AutotaskConfigError)(`revenueRollup: ${name}: ${what}. Live values (id label): ${live}`, {
|
|
703
717
|
operation: OP,
|
|
704
718
|
suggestedAction: `Pass ${name} as ids or exact labels from the live list.`
|
|
705
719
|
});
|
|
@@ -710,21 +724,21 @@ var chunk = (a) => {
|
|
|
710
724
|
for (let i = 0; i < a.length; i += PAGE) out.push(a.slice(i, i + PAGE));
|
|
711
725
|
return out;
|
|
712
726
|
};
|
|
713
|
-
var byId = (rows) => [...new Map(rows.map((r) => [
|
|
714
|
-
var cents = (v) => Math.round(
|
|
715
|
-
var revC = (line) => cents(
|
|
716
|
-
var extC = (line) => cents(
|
|
727
|
+
var byId = (rows) => [...new Map(rows.map((r) => [_chunkIY5QZZVFcjs.num.call(void 0, r["id"]), r])).values()];
|
|
728
|
+
var cents = (v) => Math.round(_chunkIY5QZZVFcjs.num.call(void 0, v) * 100);
|
|
729
|
+
var revC = (line) => cents(_chunkIY5QZZVFcjs.internalAmount.call(void 0, line, "internalCurrencyTotalAmount", "totalAmount"));
|
|
730
|
+
var extC = (line) => cents(_chunkIY5QZZVFcjs.internalAmount.call(void 0, line, "internalCurrencyExtendedPrice", "extendedPrice"));
|
|
717
731
|
var INTERNAL_FIELDS = ["internalCurrencyTotalAmount", "internalCurrencyExtendedPrice"];
|
|
718
732
|
var lacksInternal = (line) => INTERNAL_FIELDS.some((k) => !Number.isFinite(line[k]));
|
|
719
733
|
var money = (c) => c / 100;
|
|
720
734
|
var pages = (n) => Math.ceil(n / PAGE);
|
|
721
735
|
async function collect(res, filter, includeFields) {
|
|
722
736
|
const out = [];
|
|
723
|
-
for await (const r of res.query({ filter, includeFields, maxRecords: PAGE })) out.push(r);
|
|
737
|
+
for await (const r of res.query({ filter, includeFields, maxRecords: PAGE, names: false })) out.push(r);
|
|
724
738
|
return out;
|
|
725
739
|
}
|
|
726
740
|
function blindCount() {
|
|
727
|
-
return new (0,
|
|
741
|
+
return new (0, _chunkIY5QZZVFcjs.AutotaskError)("revenueRollup: a gate count came back blind (unknown, not zero); the roll-up cannot be sized", {
|
|
728
742
|
code: "INVALID_RESPONSE",
|
|
729
743
|
category: "server",
|
|
730
744
|
operation: OP,
|
|
@@ -734,7 +748,7 @@ function blindCount() {
|
|
|
734
748
|
}
|
|
735
749
|
function countMismatch(what, streamed, counted, rows) {
|
|
736
750
|
const rowNote = rows !== void 0 && rows !== streamed ? ` (${rows} rows)` : "";
|
|
737
|
-
return new (0,
|
|
751
|
+
return new (0, _chunkIY5QZZVFcjs.AutotaskError)(`revenueRollup: the ${what} stream returned ${streamed} distinct ids${rowNote} but the gate count was ${counted} (the data changed mid-walk or a page dropped rows); the fold was discarded`, {
|
|
738
752
|
code: "INVALID_RESPONSE",
|
|
739
753
|
category: "server",
|
|
740
754
|
operation: OP,
|
|
@@ -743,7 +757,7 @@ function countMismatch(what, streamed, counted, rows) {
|
|
|
743
757
|
});
|
|
744
758
|
}
|
|
745
759
|
function budgetError(message, details, suggestedAction) {
|
|
746
|
-
return new (0,
|
|
760
|
+
return new (0, _chunkIY5QZZVFcjs.AutotaskError)(message, { code: "BUDGET_EXCEEDED", category: "policy", operation: OP, details, suggestedAction });
|
|
747
761
|
}
|
|
748
762
|
function lastMonthsFrom(dateTo, months) {
|
|
749
763
|
return new Date(Date.UTC(Number(dateTo.slice(0, 4)), Number(dateTo.slice(5, 7)) - months, 1)).toISOString().slice(0, 10);
|
|
@@ -776,7 +790,7 @@ async function revenueRollup(client, opts) {
|
|
|
776
790
|
const groupDims = v.groupBy.map((d) => DIMENSIONS[d]);
|
|
777
791
|
const paths = [.../* @__PURE__ */ new Set([CONTRACTS_PATH, ...groupDims.flatMap((d) => d.picklist ? [d.picklist] : [])])];
|
|
778
792
|
const labels = {};
|
|
779
|
-
for (const p of paths) labels[p] = await
|
|
793
|
+
for (const p of paths) labels[p] = await _chunkIY5QZZVFcjs.readPicklists.call(void 0, http, p, OP);
|
|
780
794
|
const contractLabels = labels[CONTRACTS_PATH];
|
|
781
795
|
const typeValues = _nullishCoalesce(contractLabels.get("contractType"), () => ( /* @__PURE__ */ new Map()));
|
|
782
796
|
const inTypes = v.contractTypes ? resolveSelector("contractTypes", v.contractTypes, typeValues) : new Map([...typeValues].filter(([, l]) => DEFAULT_CONTRACT_TYPE_RE.test(l)));
|
|
@@ -785,23 +799,23 @@ async function revenueRollup(client, opts) {
|
|
|
785
799
|
let scopeIds = v.scopeIds;
|
|
786
800
|
if (v.scopeKind === "ownerResourceID") {
|
|
787
801
|
const owned = /* @__PURE__ */ new Set();
|
|
788
|
-
for await (const c of new (0,
|
|
789
|
-
const id =
|
|
802
|
+
for await (const c of new (0, _chunkIY5QZZVFcjs.CompaniesResource)(http, PAGE).query({ filter: [{ field: "ownerResourceID", op: "eq", value: v.ownerResourceID }], includeFields: ["id"], maxRecords: PAGE, names: false })) {
|
|
803
|
+
const id = _chunkIY5QZZVFcjs.num.call(void 0, c.id);
|
|
790
804
|
if (id > 0) owned.add(id);
|
|
791
805
|
if (owned.size > SCOPE_IDS_MAX) break;
|
|
792
806
|
}
|
|
793
807
|
scopeIds = [...owned].sort((a, b) => a - b);
|
|
794
808
|
if (scopeIds.length === 0 || scopeIds.length > SCOPE_IDS_MAX) {
|
|
795
|
-
throw new (0,
|
|
809
|
+
throw new (0, _chunkIY5QZZVFcjs.AutotaskConfigError)(
|
|
796
810
|
`revenueRollup: ownerResourceID ${v.ownerResourceID} resolves to ${scopeIds.length > SCOPE_IDS_MAX ? `more than ${SCOPE_IDS_MAX}` : 0} companies (companies.query; 1..${SCOPE_IDS_MAX} supported)`,
|
|
797
811
|
{ operation: OP, suggestedAction: "Pass companyIDs explicitly, or tenantWide: true." }
|
|
798
812
|
);
|
|
799
813
|
}
|
|
800
814
|
}
|
|
801
815
|
const scopeCond = scopeIds === void 0 ? [] : [{ field: v.scopeKind === "contractIDs" ? "contractID" : "companyID", op: "in", value: scopeIds }];
|
|
802
|
-
const invoices = new (0,
|
|
803
|
-
const billingItems = new (0,
|
|
804
|
-
const windowOn = (field) => [{ field, op: "gte", value: v.dateFrom }, { field, op: "lt", value:
|
|
816
|
+
const invoices = new (0, _chunkIY5QZZVFcjs.InvoicesResource)(http, PAGE);
|
|
817
|
+
const billingItems = new (0, _chunkIY5QZZVFcjs.BillingItemsResource)(http, PAGE);
|
|
818
|
+
const windowOn = (field) => [{ field, op: "gte", value: v.dateFrom }, { field, op: "lt", value: _chunkIY5QZZVFcjs.dayAfter.call(void 0, v.dateTo) }];
|
|
805
819
|
const invoiceFilter = (voided2) => [...windowOn("invoiceDateTime"), { field: "isVoided", op: "eq", value: voided2 }];
|
|
806
820
|
const withVoided = v.scopeKind !== "contractIDs";
|
|
807
821
|
const voidedFilter = [...invoiceFilter(true), ...scopeIds !== void 0 && withVoided ? [{ field: "companyID", op: "in", value: scopeIds }] : []];
|
|
@@ -810,7 +824,7 @@ async function revenueRollup(client, opts) {
|
|
|
810
824
|
const uninvoicedFilter = [{ field: "invoiceID", op: "notExist" }, ...windowOn("itemDate"), ...scopeCond];
|
|
811
825
|
const nUninvoiced = v.nonChargeable ? await billingItems.count({ filter: uninvoicedFilter }) : 0;
|
|
812
826
|
if (typeof nInvoices !== "number" || typeof nLines !== "number" || typeof nUninvoiced !== "number") throw blindCount();
|
|
813
|
-
const joinsNeeded = Object.keys(JOINS).filter((j) => j === "contracts" || groupDims.some((d) => _optionalChain([d, 'access',
|
|
827
|
+
const joinsNeeded = Object.keys(JOINS).filter((j) => j === "contracts" || groupDims.some((d) => _optionalChain([d, 'access', _23 => _23.joins, 'optionalAccess', _24 => _24[j]])));
|
|
814
828
|
const chunks = pages(nInvoices);
|
|
815
829
|
const linePages = chunks + Math.max(0, pages(nLines) - 1) + chunks;
|
|
816
830
|
const uninvoicedPages = v.nonChargeable ? Math.max(1, pages(nUninvoiced)) : 0;
|
|
@@ -825,7 +839,7 @@ async function revenueRollup(client, opts) {
|
|
|
825
839
|
const invoiceRows = await collect(invoices, invoiceFilter(false), ["id", "invoiceTotal", "invoiceDateTime", "companyID"]);
|
|
826
840
|
const invoiceById = /* @__PURE__ */ new Map();
|
|
827
841
|
for (const r of invoiceRows) {
|
|
828
|
-
invoiceById.set(
|
|
842
|
+
invoiceById.set(_chunkIY5QZZVFcjs.num.call(void 0, r["id"]), { total: cents(r["invoiceTotal"]), month: String(_nullishCoalesce(r["invoiceDateTime"], () => ( ""))).slice(0, 7), companyID: _chunkIY5QZZVFcjs.num.call(void 0, r["companyID"]) });
|
|
829
843
|
}
|
|
830
844
|
if (invoiceById.size !== nInvoices) throw countMismatch("invoice", invoiceById.size, nInvoices, invoiceRows.length);
|
|
831
845
|
const voided = withVoided ? byId(await collect(invoices, voidedFilter, ["id", "invoiceTotal"])) : void 0;
|
|
@@ -839,13 +853,13 @@ async function revenueRollup(client, opts) {
|
|
|
839
853
|
if (rows.length !== n) throw countMismatch("line", rows.length, n);
|
|
840
854
|
return rows;
|
|
841
855
|
}, chunk(ids), { concurrency: CONCURRENCY })).flat();
|
|
842
|
-
const orphan = lines.find((l) => !invoiceById.has(
|
|
856
|
+
const orphan = lines.find((l) => !invoiceById.has(_chunkIY5QZZVFcjs.num.call(void 0, l["invoiceID"])));
|
|
843
857
|
if (orphan !== void 0) {
|
|
844
|
-
throw new (0,
|
|
858
|
+
throw new (0, _chunkIY5QZZVFcjs.AutotaskError)(`revenueRollup: billing line ${_chunkIY5QZZVFcjs.num.call(void 0, orphan["id"])} belongs to invoice ${_chunkIY5QZZVFcjs.num.call(void 0, orphan["invoiceID"])}, which is not among the ${invoiceById.size} streamed invoices; the fold was discarded`, {
|
|
845
859
|
code: "INVALID_RESPONSE",
|
|
846
860
|
category: "server",
|
|
847
861
|
operation: OP,
|
|
848
|
-
details: { reason: "orphan_line", lineID:
|
|
862
|
+
details: { reason: "orphan_line", lineID: _chunkIY5QZZVFcjs.num.call(void 0, orphan["id"]), invoiceID: _chunkIY5QZZVFcjs.num.call(void 0, orphan["invoiceID"]) },
|
|
849
863
|
suggestedAction: "Retry the call."
|
|
850
864
|
});
|
|
851
865
|
}
|
|
@@ -856,15 +870,15 @@ async function revenueRollup(client, opts) {
|
|
|
856
870
|
for (const j of joinsNeeded) {
|
|
857
871
|
const spec = JOINS[j];
|
|
858
872
|
const res = spec.make(http, client);
|
|
859
|
-
const fields = [.../* @__PURE__ */ new Set([...spec.fields, ...groupDims.flatMap((d) => _nullishCoalesce(_optionalChain([d, 'access',
|
|
873
|
+
const fields = [.../* @__PURE__ */ new Set([...spec.fields, ...groupDims.flatMap((d) => _nullishCoalesce(_optionalChain([d, 'access', _25 => _25.joins, 'optionalAccess', _26 => _26[j]]), () => ( [])))])];
|
|
860
874
|
const want = [...new Set(spec.ids(all, joined))].filter((id) => id > 0).sort((a, b) => a - b);
|
|
861
875
|
const rows = await client.batch((c) => collect(res, [{ field: "id", op: "in", value: c }], fields), chunk(want), { concurrency: CONCURRENCY });
|
|
862
|
-
for (const r of rows.flat()) joined[j].set(
|
|
876
|
+
for (const r of rows.flat()) joined[j].set(_chunkIY5QZZVFcjs.num.call(void 0, r["id"]), r);
|
|
863
877
|
}
|
|
864
878
|
return fold(v, { invoiceById, voided, lines, uninvoiced, joined, labels, inTypes, inCategories, scopeIds, calls, estimate });
|
|
865
879
|
}
|
|
866
880
|
function refusal(v, estimate, fixed, scopeIds, joinCount) {
|
|
867
|
-
const months =
|
|
881
|
+
const months = _chunkIY5QZZVFcjs.monthsInWindow.call(void 0, v.dateFrom, v.dateTo);
|
|
868
882
|
const variable = estimate - fixed;
|
|
869
883
|
const fitMonths = Math.floor((v.budget - fixed) * months / variable);
|
|
870
884
|
const suggestions = [];
|
|
@@ -937,13 +951,13 @@ function fold(v, f) {
|
|
|
937
951
|
const contractLabels = f.labels[CONTRACTS_PATH];
|
|
938
952
|
const bucketLabel = (field, fallback) => (t) => {
|
|
939
953
|
const values = contractLabels.get(field);
|
|
940
|
-
const l = _optionalChain([values, 'optionalAccess',
|
|
954
|
+
const l = _optionalChain([values, 'optionalAccess', _27 => _27.get, 'call', _28 => _28(t)]);
|
|
941
955
|
if (l === void 0) return `${fallback} ${t}`;
|
|
942
956
|
return [...values.values()].filter((x) => x === l).length > 1 ? `${l} (${t})` : l;
|
|
943
957
|
};
|
|
944
958
|
const typeLabel = bucketLabel("contractType", "type");
|
|
945
959
|
const catLabel = bucketLabel("contractCategory", "category");
|
|
946
|
-
const needCompany = v.groupBy.some((d) => _optionalChain([DIMENSIONS, 'access',
|
|
960
|
+
const needCompany = v.groupBy.some((d) => _optionalChain([DIMENSIONS, 'access', _29 => _29[d], 'access', _30 => _30.joins, 'optionalAccess', _31 => _31.companies]));
|
|
947
961
|
const byLob = v.groupBy.includes("lineOfBusiness");
|
|
948
962
|
const unlabelled = /* @__PURE__ */ new Set();
|
|
949
963
|
const uncontracted = amt();
|
|
@@ -960,15 +974,15 @@ function fold(v, f) {
|
|
|
960
974
|
const zeroTotal = amt();
|
|
961
975
|
const zeroIds = /* @__PURE__ */ new Set();
|
|
962
976
|
const locate = (line, invoice) => {
|
|
963
|
-
const contractID =
|
|
977
|
+
const contractID = _chunkIY5QZZVFcjs.num.call(void 0, line["contractID"]);
|
|
964
978
|
if (contractID === 0) return { bucket: uncontracted, unresolved: false };
|
|
965
979
|
const contract = f.joined.contracts.get(contractID);
|
|
966
980
|
if (contract === void 0) return { bucket: unresolvedContracts, unresolved: true };
|
|
967
|
-
const type =
|
|
981
|
+
const type = _chunkIY5QZZVFcjs.num.call(void 0, contract["contractType"]);
|
|
968
982
|
if (!f.inTypes.has(type)) return { bucket: slot(otherTypes, typeLabel(type)), unresolved: false };
|
|
969
|
-
const cat =
|
|
983
|
+
const cat = _chunkIY5QZZVFcjs.num.call(void 0, contract["contractCategory"]);
|
|
970
984
|
if (f.inCategories !== void 0 && !f.inCategories.has(cat)) return { bucket: slot(otherCats, cat === 0 ? "uncategorised" : catLabel(cat)), unresolved: false };
|
|
971
|
-
const company = f.joined.companies.get(
|
|
985
|
+
const company = f.joined.companies.get(_chunkIY5QZZVFcjs.num.call(void 0, line["companyID"]));
|
|
972
986
|
if (needCompany && company === void 0) return { bucket: unresolvedCompanies, unresolved: true };
|
|
973
987
|
const ctx = { line, invoice, contract, company, joined: f.joined, labels: f.labels, unlabelled };
|
|
974
988
|
const keys = {};
|
|
@@ -988,7 +1002,7 @@ function fold(v, f) {
|
|
|
988
1002
|
return { cell };
|
|
989
1003
|
};
|
|
990
1004
|
for (const line of f.lines) {
|
|
991
|
-
const invoiceID =
|
|
1005
|
+
const invoiceID = _chunkIY5QZZVFcjs.num.call(void 0, line["invoiceID"]);
|
|
992
1006
|
const invoice = f.invoiceById.get(invoiceID);
|
|
993
1007
|
lineTotals.set(invoiceID, (_nullishCoalesce(lineTotals.get(invoiceID), () => ( 0))) + cents(line["totalAmount"]));
|
|
994
1008
|
const c = revC(line);
|
|
@@ -1009,9 +1023,9 @@ function fold(v, f) {
|
|
|
1009
1023
|
cell.creditLines += 1;
|
|
1010
1024
|
}
|
|
1011
1025
|
cell.included += extC(line) - c;
|
|
1012
|
-
cell.contracts.add(
|
|
1026
|
+
cell.contracts.add(_chunkIY5QZZVFcjs.num.call(void 0, line["contractID"]));
|
|
1013
1027
|
cell.items += 1;
|
|
1014
|
-
allContracts.add(
|
|
1028
|
+
allContracts.add(_chunkIY5QZZVFcjs.num.call(void 0, line["contractID"]));
|
|
1015
1029
|
if (byLob && cell.keys.lineOfBusiness.id === null) add(noPointer, c);
|
|
1016
1030
|
const k = v.nonChargeable ? ncClass(line) : void 0;
|
|
1017
1031
|
if (k) ncAdd(cell.nc, k, line);
|
|
@@ -1019,7 +1033,7 @@ function fold(v, f) {
|
|
|
1019
1033
|
for (const line of f.uninvoiced) {
|
|
1020
1034
|
const k = ncClass(line);
|
|
1021
1035
|
if (!k) continue;
|
|
1022
|
-
const at = locate(line, { total: 0, month: String(_nullishCoalesce(line["itemDate"], () => ( ""))).slice(0, 7), companyID:
|
|
1036
|
+
const at = locate(line, { total: 0, month: String(_nullishCoalesce(line["itemDate"], () => ( ""))).slice(0, 7), companyID: _chunkIY5QZZVFcjs.num.call(void 0, line["companyID"]) });
|
|
1023
1037
|
if ("cell" in at) ncAdd(at.cell.nc, k, line);
|
|
1024
1038
|
else if (at.unresolved) add(unresolvedNc, extC(line));
|
|
1025
1039
|
}
|
|
@@ -1129,20 +1143,20 @@ function slot(m, k) {
|
|
|
1129
1143
|
async function relationshipMap(client, resourceKey) {
|
|
1130
1144
|
void client;
|
|
1131
1145
|
if (typeof resourceKey !== "string" || resourceKey.trim() === "") {
|
|
1132
|
-
throw new (0,
|
|
1146
|
+
throw new (0, _chunkIY5QZZVFcjs.AutotaskConfigError)(
|
|
1133
1147
|
`relationshipMap: resourceKey must be a non-empty plan resource key string (e.g. 'tickets'; got ${typeof resourceKey === "string" ? "a blank string" : typeof resourceKey})`,
|
|
1134
1148
|
{ suggestedAction: "Pass the exact plan resource key (snake_case) from autotask_catalog \u2014 e.g. tickets, companies, configuration_items, ticket_notes." }
|
|
1135
1149
|
);
|
|
1136
1150
|
}
|
|
1137
1151
|
const key = resourceKey.trim();
|
|
1138
|
-
const entry =
|
|
1152
|
+
const entry = _chunkIY5QZZVFcjs.RELATIONSHIP_MAP[key];
|
|
1139
1153
|
if (entry === void 0) {
|
|
1140
|
-
throw new (0,
|
|
1141
|
-
`relationshipMap: unknown resource "${key}" \u2014 the plan has ${Object.keys(
|
|
1154
|
+
throw new (0, _chunkIY5QZZVFcjs.AutotaskError)(
|
|
1155
|
+
`relationshipMap: unknown resource "${key}" \u2014 the plan has ${Object.keys(_chunkIY5QZZVFcjs.RELATIONSHIP_MAP).length} resources`,
|
|
1142
1156
|
{
|
|
1143
1157
|
code: "RESOURCE_UNKNOWN",
|
|
1144
1158
|
category: "validation",
|
|
1145
|
-
suggestedAction: `Pass the exact plan resource key (snake_case) from autotask_catalog (e.g. tickets, companies, configuration_items). Zone facts served are ${
|
|
1159
|
+
suggestedAction: `Pass the exact plan resource key (snake_case) from autotask_catalog (e.g. tickets, companies, configuration_items). Zone facts served are ${_chunkIY5QZZVFcjs.RELATIONSHIP_ZONE.label} (${_chunkIY5QZZVFcjs.RELATIONSHIP_ZONE.zone})-verified.`
|
|
1146
1160
|
}
|
|
1147
1161
|
);
|
|
1148
1162
|
}
|
|
@@ -1159,24 +1173,24 @@ var BLIND_SURFACE_KINDS = [
|
|
|
1159
1173
|
async function blindSurfaces(client, opts) {
|
|
1160
1174
|
void client;
|
|
1161
1175
|
if (opts !== void 0 && (typeof opts !== "object" || opts === null || Array.isArray(opts))) {
|
|
1162
|
-
throw new (0,
|
|
1176
|
+
throw new (0, _chunkIY5QZZVFcjs.AutotaskConfigError)("blindSurfaces: opts must be an object { resource?: string, kind?: BlindSurfaceKind }");
|
|
1163
1177
|
}
|
|
1164
|
-
const inv =
|
|
1178
|
+
const inv = _chunkIY5QZZVFcjs.BLIND_SURFACE_INVENTORY;
|
|
1165
1179
|
if (inv === null) {
|
|
1166
|
-
throw new (0,
|
|
1180
|
+
throw new (0, _chunkIY5QZZVFcjs.AutotaskConfigError)("blindSurfaces: the reachability inventory is absent from the generated artifact \u2014 re-run the build");
|
|
1167
1181
|
}
|
|
1168
1182
|
let surfaces = inv.surfaces;
|
|
1169
|
-
if (_optionalChain([opts, 'optionalAccess',
|
|
1183
|
+
if (_optionalChain([opts, 'optionalAccess', _32 => _32.resource]) !== void 0) {
|
|
1170
1184
|
const key = typeof opts.resource === "string" ? opts.resource.trim() : "";
|
|
1171
1185
|
if (key === "") {
|
|
1172
|
-
throw new (0,
|
|
1186
|
+
throw new (0, _chunkIY5QZZVFcjs.AutotaskConfigError)(
|
|
1173
1187
|
"blindSurfaces: opts.resource must be a non-empty plan resource key string (e.g. 'tickets')",
|
|
1174
1188
|
{ suggestedAction: "Pass the exact plan resource key (snake_case) from autotask_catalog \u2014 e.g. tickets, companies, configuration_items." }
|
|
1175
1189
|
);
|
|
1176
1190
|
}
|
|
1177
1191
|
if (!inv.surfaces.some((row) => row.resource === key)) {
|
|
1178
|
-
throw new (0,
|
|
1179
|
-
`blindSurfaces: unknown resource "${key}" \u2014 the plan has ${Object.keys(
|
|
1192
|
+
throw new (0, _chunkIY5QZZVFcjs.AutotaskError)(
|
|
1193
|
+
`blindSurfaces: unknown resource "${key}" \u2014 the plan has ${Object.keys(_chunkIY5QZZVFcjs.RELATIONSHIP_MAP).length} resources`,
|
|
1180
1194
|
{
|
|
1181
1195
|
code: "RESOURCE_UNKNOWN",
|
|
1182
1196
|
category: "validation",
|
|
@@ -1186,9 +1200,9 @@ async function blindSurfaces(client, opts) {
|
|
|
1186
1200
|
}
|
|
1187
1201
|
surfaces = surfaces.filter((row) => row.resource === key);
|
|
1188
1202
|
}
|
|
1189
|
-
if (_optionalChain([opts, 'optionalAccess',
|
|
1203
|
+
if (_optionalChain([opts, 'optionalAccess', _33 => _33.kind]) !== void 0) {
|
|
1190
1204
|
if (!BLIND_SURFACE_KINDS.includes(opts.kind)) {
|
|
1191
|
-
throw new (0,
|
|
1205
|
+
throw new (0, _chunkIY5QZZVFcjs.AutotaskConfigError)(
|
|
1192
1206
|
`blindSurfaces: unknown kind "${String(opts.kind)}" \u2014 the valid classes are: ${BLIND_SURFACE_KINDS.join(", ")}`,
|
|
1193
1207
|
{ suggestedAction: `Filter with one of: ${BLIND_SURFACE_KINDS.join(", ")} (or omit kind for the full 116-surface inventory).` }
|
|
1194
1208
|
);
|
|
@@ -1201,51 +1215,51 @@ async function blindSurfaces(client, opts) {
|
|
|
1201
1215
|
// src/operations/probeReachability.ts
|
|
1202
1216
|
async function probeReachability(client, opts) {
|
|
1203
1217
|
if (opts !== void 0 && (typeof opts !== "object" || opts === null || Array.isArray(opts))) {
|
|
1204
|
-
throw new (0,
|
|
1218
|
+
throw new (0, _chunkIY5QZZVFcjs.AutotaskConfigError)("probeReachability: opts must be an object { resources?: string[], limit?: 1|2, maxWireCalls?: number, confirmProbe?: true }");
|
|
1205
1219
|
}
|
|
1206
|
-
const defs =
|
|
1207
|
-
if (_optionalChain([opts, 'optionalAccess',
|
|
1208
|
-
throw new (0,
|
|
1220
|
+
const defs = _chunkIY5QZZVFcjs.REACHABILITY_PROBE_DEFAULTS;
|
|
1221
|
+
if (_optionalChain([opts, 'optionalAccess', _34 => _34.confirmProbe]) !== true) {
|
|
1222
|
+
throw new (0, _chunkIY5QZZVFcjs.AutotaskConfigError)(
|
|
1209
1223
|
"probeReachability: confirmProbe: true is required \u2014 the op deliberately fans out read wire across the tenant (one bounded query per surface); pass confirmProbe: true to run it",
|
|
1210
1224
|
{ suggestedAction: `Re-call with { confirmProbe: true } (plus resources/limit/maxWireCalls as needed). For the ZERO-wire pinned inventory use operations.blindSurfaces.` }
|
|
1211
1225
|
);
|
|
1212
1226
|
}
|
|
1213
|
-
const limit = _nullishCoalesce(_optionalChain([opts, 'optionalAccess',
|
|
1227
|
+
const limit = _nullishCoalesce(_optionalChain([opts, 'optionalAccess', _35 => _35.limit]), () => ( defs.limitDefault));
|
|
1214
1228
|
if (!Number.isInteger(limit) || limit < 1 || limit > defs.limitMax) {
|
|
1215
|
-
throw new (0,
|
|
1229
|
+
throw new (0, _chunkIY5QZZVFcjs.AutotaskConfigError)(
|
|
1216
1230
|
`probeReachability: limit must be an integer 1..${defs.limitMax} (got ${String(limit)}) \u2014 the rows-per-surface bound for the discovery read`
|
|
1217
1231
|
);
|
|
1218
1232
|
}
|
|
1219
|
-
const cap = _nullishCoalesce(_optionalChain([opts, 'optionalAccess',
|
|
1233
|
+
const cap = _nullishCoalesce(_optionalChain([opts, 'optionalAccess', _36 => _36.maxWireCalls]), () => ( defs.defaultCap));
|
|
1220
1234
|
if (!Number.isInteger(cap) || cap < 1) {
|
|
1221
|
-
throw new (0,
|
|
1235
|
+
throw new (0, _chunkIY5QZZVFcjs.AutotaskConfigError)(`probeReachability: maxWireCalls must be a positive integer (got ${String(cap)})`);
|
|
1222
1236
|
}
|
|
1223
1237
|
if (cap > defs.hardCap) {
|
|
1224
|
-
throw new (0,
|
|
1238
|
+
throw new (0, _chunkIY5QZZVFcjs.AutotaskConfigError)(
|
|
1225
1239
|
`probeReachability: maxWireCalls ${cap} exceeds the hard wire cap of ${defs.hardCap} \u2014 the sweep is refused above it (never capped silently)`,
|
|
1226
1240
|
{ suggestedAction: `Pass maxWireCalls \u2264 ${defs.hardCap} and a resources set no larger than the cap (the refused set is never truncated).` }
|
|
1227
1241
|
);
|
|
1228
1242
|
}
|
|
1229
|
-
const inv =
|
|
1243
|
+
const inv = _chunkIY5QZZVFcjs.BLIND_SURFACE_INVENTORY;
|
|
1230
1244
|
if (inv === null) {
|
|
1231
|
-
throw new (0,
|
|
1245
|
+
throw new (0, _chunkIY5QZZVFcjs.AutotaskConfigError)("probeReachability: the reachability inventory is absent from the generated artifact \u2014 re-run the build");
|
|
1232
1246
|
}
|
|
1233
1247
|
let targets;
|
|
1234
|
-
if (_optionalChain([opts, 'optionalAccess',
|
|
1248
|
+
if (_optionalChain([opts, 'optionalAccess', _37 => _37.resources]) === void 0) {
|
|
1235
1249
|
targets = [...defs.defaultTargets];
|
|
1236
1250
|
} else {
|
|
1237
1251
|
if (!Array.isArray(opts.resources) || opts.resources.length === 0) {
|
|
1238
|
-
throw new (0,
|
|
1252
|
+
throw new (0, _chunkIY5QZZVFcjs.AutotaskConfigError)("probeReachability: opts.resources must be a non-empty string[] of plan resource keys (or omit it for the default non-data-full set)");
|
|
1239
1253
|
}
|
|
1240
1254
|
const seen = /* @__PURE__ */ new Set();
|
|
1241
1255
|
for (const r of opts.resources) {
|
|
1242
1256
|
if (typeof r !== "string" || r.trim() === "") {
|
|
1243
|
-
throw new (0,
|
|
1257
|
+
throw new (0, _chunkIY5QZZVFcjs.AutotaskConfigError)(`probeReachability: opts.resources must contain non-empty plan resource key strings (got ${typeof r === "string" && r.trim() === "" ? "a blank string" : typeof r})`);
|
|
1244
1258
|
}
|
|
1245
1259
|
const key = r.trim();
|
|
1246
1260
|
if (!inv.surfaces.some((row) => row.resource === key)) {
|
|
1247
1261
|
const surfaceCount = new Set(inv.surfaces.map((s) => s.resource)).size;
|
|
1248
|
-
throw new (0,
|
|
1262
|
+
throw new (0, _chunkIY5QZZVFcjs.AutotaskError)(
|
|
1249
1263
|
`probeReachability: unknown resource "${key}" \u2014 the inventory has ${surfaceCount} surfaces`,
|
|
1250
1264
|
{
|
|
1251
1265
|
code: "RESOURCE_UNKNOWN",
|
|
@@ -1259,7 +1273,7 @@ async function probeReachability(client, opts) {
|
|
|
1259
1273
|
targets = [...seen];
|
|
1260
1274
|
}
|
|
1261
1275
|
if (targets.length > cap) {
|
|
1262
|
-
throw new (0,
|
|
1276
|
+
throw new (0, _chunkIY5QZZVFcjs.AutotaskConfigError)(
|
|
1263
1277
|
`probeReachability: ${targets.length} requested surface(s) exceed the wire cap of ${cap} \u2014 the sweep is refused above its cap (never truncated)`,
|
|
1264
1278
|
{ suggestedAction: `Raise maxWireCalls (\u2264 ${defs.hardCap}) to cover the set, or pass a smaller resources list.` }
|
|
1265
1279
|
);
|
|
@@ -1269,8 +1283,8 @@ async function probeReachability(client, opts) {
|
|
|
1269
1283
|
for (const resource of targets.sort()) {
|
|
1270
1284
|
const row = byResource.get(resource);
|
|
1271
1285
|
if (row === void 0) continue;
|
|
1272
|
-
const holder = client[
|
|
1273
|
-
const probeFn = _optionalChain([holder, 'optionalAccess',
|
|
1286
|
+
const holder = client[_chunkIY5QZZVFcjs.camelKey.call(void 0, resource)];
|
|
1287
|
+
const probeFn = _optionalChain([holder, 'optionalAccess', _38 => _38.queryBounded]);
|
|
1274
1288
|
if (typeof probeFn !== "function") {
|
|
1275
1289
|
results.push({
|
|
1276
1290
|
...row,
|
|
@@ -1281,14 +1295,14 @@ async function probeReachability(client, opts) {
|
|
|
1281
1295
|
}
|
|
1282
1296
|
try {
|
|
1283
1297
|
const res = await probeFn.call(holder, { limit });
|
|
1284
|
-
const items = Array.isArray(_optionalChain([res, 'optionalAccess',
|
|
1298
|
+
const items = Array.isArray(_optionalChain([res, 'optionalAccess', _39 => _39.items])) ? res.items : [];
|
|
1285
1299
|
results.push({
|
|
1286
1300
|
...row,
|
|
1287
1301
|
unfilteredRows: items.length,
|
|
1288
1302
|
probe: { ok: true, wire: 1, error: null }
|
|
1289
1303
|
});
|
|
1290
1304
|
} catch (err) {
|
|
1291
|
-
const code =
|
|
1305
|
+
const code = _chunkIY5QZZVFcjs.isAutotaskError.call(void 0, err) ? err.code : "NETWORK_ERROR";
|
|
1292
1306
|
const message = err instanceof Error ? err.message : String(err);
|
|
1293
1307
|
results.push({
|
|
1294
1308
|
...row,
|
|
@@ -1316,30 +1330,30 @@ var CREATE_BLOCKER_KINDS = [
|
|
|
1316
1330
|
async function createGuidance(client, opts) {
|
|
1317
1331
|
void client;
|
|
1318
1332
|
if (opts !== void 0 && (typeof opts !== "object" || opts === null || Array.isArray(opts))) {
|
|
1319
|
-
throw new (0,
|
|
1333
|
+
throw new (0, _chunkIY5QZZVFcjs.AutotaskConfigError)(
|
|
1320
1334
|
"createGuidance: opts must be an object { resources?: string[], kind?: CreateBlockerKind }"
|
|
1321
1335
|
);
|
|
1322
1336
|
}
|
|
1323
|
-
let servedRows =
|
|
1337
|
+
let servedRows = _chunkIY5QZZVFcjs.CREATE_GUIDANCE.rows.map((row) => ({
|
|
1324
1338
|
...row,
|
|
1325
1339
|
// Issue #219 N4: one precedence rule, stated on every row (live-proven >
|
|
1326
1340
|
// zone > spec). The spec set is not available here (it is a LIVE read) —
|
|
1327
1341
|
// the helper is handed the plan's two shapes and names the source.
|
|
1328
|
-
requiredFields:
|
|
1342
|
+
requiredFields: _chunkIY5QZZVFcjs.effectiveRequiredFields.call(void 0, void 0, _nullishCoalesce(_optionalChain([_chunkIY5QZZVFcjs.RELATIONSHIP_MAP, 'access', _40 => _40[row.resource], 'optionalAccess', _41 => _41.zoneFacts]), () => ( null)))
|
|
1329
1343
|
}));
|
|
1330
|
-
if (_optionalChain([opts, 'optionalAccess',
|
|
1344
|
+
if (_optionalChain([opts, 'optionalAccess', _42 => _42.resources]) !== void 0) {
|
|
1331
1345
|
if (!Array.isArray(opts.resources) || opts.resources.length === 0) {
|
|
1332
|
-
throw new (0,
|
|
1346
|
+
throw new (0, _chunkIY5QZZVFcjs.AutotaskConfigError)("createGuidance: opts.resources must be a non-empty string[] of plan resource keys");
|
|
1333
1347
|
}
|
|
1334
1348
|
const wanted = /* @__PURE__ */ new Set();
|
|
1335
1349
|
for (const r of opts.resources) {
|
|
1336
1350
|
if (typeof r !== "string" || r.trim() === "") {
|
|
1337
|
-
throw new (0,
|
|
1351
|
+
throw new (0, _chunkIY5QZZVFcjs.AutotaskConfigError)("createGuidance: opts.resources must contain non-empty plan resource key strings");
|
|
1338
1352
|
}
|
|
1339
1353
|
const key = r.trim();
|
|
1340
|
-
if (!
|
|
1341
|
-
throw new (0,
|
|
1342
|
-
`createGuidance: unknown resource "${key}" \u2014 the catalog has ${
|
|
1354
|
+
if (!_chunkIY5QZZVFcjs.CREATE_GUIDANCE.rows.some((row) => row.resource === key)) {
|
|
1355
|
+
throw new (0, _chunkIY5QZZVFcjs.AutotaskError)(
|
|
1356
|
+
`createGuidance: unknown resource "${key}" \u2014 the catalog has ${_chunkIY5QZZVFcjs.CREATE_GUIDANCE.rows.length} create entities`,
|
|
1343
1357
|
{
|
|
1344
1358
|
code: "RESOURCE_UNKNOWN",
|
|
1345
1359
|
category: "validation",
|
|
@@ -1351,20 +1365,20 @@ async function createGuidance(client, opts) {
|
|
|
1351
1365
|
}
|
|
1352
1366
|
servedRows = servedRows.filter((row) => wanted.has(row.resource));
|
|
1353
1367
|
}
|
|
1354
|
-
if (_optionalChain([opts, 'optionalAccess',
|
|
1368
|
+
if (_optionalChain([opts, 'optionalAccess', _43 => _43.kind]) !== void 0) {
|
|
1355
1369
|
if (!CREATE_BLOCKER_KINDS.includes(opts.kind)) {
|
|
1356
|
-
throw new (0,
|
|
1370
|
+
throw new (0, _chunkIY5QZZVFcjs.AutotaskConfigError)(
|
|
1357
1371
|
`createGuidance: unknown kind "${String(opts.kind)}" \u2014 the valid kinds are: ${CREATE_BLOCKER_KINDS.join(", ")}`
|
|
1358
1372
|
);
|
|
1359
1373
|
}
|
|
1360
|
-
servedRows = servedRows.filter((row) => _optionalChain([row, 'access',
|
|
1374
|
+
servedRows = servedRows.filter((row) => _optionalChain([row, 'access', _44 => _44.blocker, 'optionalAccess', _45 => _45.kind]) === opts.kind);
|
|
1361
1375
|
}
|
|
1362
1376
|
return {
|
|
1363
|
-
zone:
|
|
1364
|
-
label:
|
|
1365
|
-
verifiedAt:
|
|
1377
|
+
zone: _chunkIY5QZZVFcjs.CREATE_GUIDANCE.zone,
|
|
1378
|
+
label: _chunkIY5QZZVFcjs.CREATE_GUIDANCE.label,
|
|
1379
|
+
verifiedAt: _chunkIY5QZZVFcjs.CREATE_GUIDANCE.verifiedAt,
|
|
1366
1380
|
rows: servedRows,
|
|
1367
|
-
counts:
|
|
1381
|
+
counts: _chunkIY5QZZVFcjs.CREATE_GUIDANCE.counts
|
|
1368
1382
|
};
|
|
1369
1383
|
}
|
|
1370
1384
|
|
|
@@ -1373,7 +1387,7 @@ var RECOVERY_CONFIRM = "operations.recovery";
|
|
|
1373
1387
|
var RECOVERY_DEFAULT_LIMIT = 25;
|
|
1374
1388
|
var RECOVERY_MAX_LIMIT = 100;
|
|
1375
1389
|
function configError(message, operation, suggestedAction) {
|
|
1376
|
-
throw new (0,
|
|
1390
|
+
throw new (0, _chunkIY5QZZVFcjs.AutotaskConfigError)(message, { operation, suggestedAction });
|
|
1377
1391
|
}
|
|
1378
1392
|
function parseMatchId(record) {
|
|
1379
1393
|
const raw = record.id;
|
|
@@ -1389,7 +1403,7 @@ function parseMatchId(record) {
|
|
|
1389
1403
|
return { id: null, unsafe: true };
|
|
1390
1404
|
}
|
|
1391
1405
|
function validateRecoveryInput(input, operation) {
|
|
1392
|
-
if (!
|
|
1406
|
+
if (!_chunkIY5QZZVFcjs.isRecord.call(void 0, input)) {
|
|
1393
1407
|
configError(
|
|
1394
1408
|
`recovery: input must be an object { resource, marker, ... } (got ${typeof input})`,
|
|
1395
1409
|
operation,
|
|
@@ -1423,10 +1437,10 @@ function validateRecoveryInput(input, operation) {
|
|
|
1423
1437
|
return { resource, marker, action };
|
|
1424
1438
|
}
|
|
1425
1439
|
function resolveRecoveryTarget(client, resource, operation) {
|
|
1426
|
-
const entry =
|
|
1440
|
+
const entry = _chunkIY5QZZVFcjs.RELATIONSHIP_MAP[resource];
|
|
1427
1441
|
if (entry === void 0) {
|
|
1428
|
-
throw new (0,
|
|
1429
|
-
`recovery: unknown resource "${resource}" \u2014 the plan has ${Object.keys(
|
|
1442
|
+
throw new (0, _chunkIY5QZZVFcjs.AutotaskError)(
|
|
1443
|
+
`recovery: unknown resource "${resource}" \u2014 the plan has ${Object.keys(_chunkIY5QZZVFcjs.RELATIONSHIP_MAP).length} resources`,
|
|
1430
1444
|
{
|
|
1431
1445
|
code: "RESOURCE_UNKNOWN",
|
|
1432
1446
|
category: "validation",
|
|
@@ -1435,7 +1449,7 @@ function resolveRecoveryTarget(client, resource, operation) {
|
|
|
1435
1449
|
}
|
|
1436
1450
|
);
|
|
1437
1451
|
}
|
|
1438
|
-
const holder = client[
|
|
1452
|
+
const holder = client[_chunkIY5QZZVFcjs.camelKey.call(void 0, resource)];
|
|
1439
1453
|
if (!holder || typeof holder.queryBounded !== "function") {
|
|
1440
1454
|
configError(
|
|
1441
1455
|
`recovery: ${resource} exposes no bounded query surface \u2014 the marker search cannot run`,
|
|
@@ -1446,7 +1460,7 @@ function resolveRecoveryTarget(client, resource, operation) {
|
|
|
1446
1460
|
return { entry, holder };
|
|
1447
1461
|
}
|
|
1448
1462
|
function resolveMarkerField(input, resource, operation) {
|
|
1449
|
-
const field = input.field !== void 0 ? String(input.field) :
|
|
1463
|
+
const field = input.field !== void 0 ? String(input.field) : _chunkIY5QZZVFcjs.MARKER_FIELDS[resource];
|
|
1450
1464
|
if (typeof field !== "string" || field.trim() === "") {
|
|
1451
1465
|
configError(
|
|
1452
1466
|
`recovery: ${resource} has no plan markerField and no input.field was passed \u2014 the marker search needs a name-like field to filter on`,
|
|
@@ -1485,7 +1499,7 @@ function resolveExtraFilter(input, operation) {
|
|
|
1485
1499
|
);
|
|
1486
1500
|
}
|
|
1487
1501
|
for (const c of input.filter) {
|
|
1488
|
-
if (!
|
|
1502
|
+
if (!_chunkIY5QZZVFcjs.isRecord.call(void 0, c) || typeof c.op !== "string" || c.op === "and" || c.op === "or") {
|
|
1489
1503
|
configError(
|
|
1490
1504
|
"recovery: input.filter accepts only plain leaf conditions ({ field, op, value }) \u2014 no grouping",
|
|
1491
1505
|
operation,
|
|
@@ -1510,7 +1524,7 @@ function resolveLimit(input, operation) {
|
|
|
1510
1524
|
async function applyRecoveryDeletes(holder, matches, parentId, resource, operation) {
|
|
1511
1525
|
const deleteMethod = holder.delete;
|
|
1512
1526
|
if (deleteMethod === void 0) {
|
|
1513
|
-
throw new (0,
|
|
1527
|
+
throw new (0, _chunkIY5QZZVFcjs.DeleteBoundaryError)(
|
|
1514
1528
|
`recovery: ${resource} has no delete method on the client \u2014 the boundary is marked available in the plan but the typed delete surface is missing`,
|
|
1515
1529
|
{
|
|
1516
1530
|
operation,
|
|
@@ -1539,14 +1553,14 @@ async function applyRecoveryDeletes(holder, matches, parentId, resource, operati
|
|
|
1539
1553
|
verify = "still-present";
|
|
1540
1554
|
}
|
|
1541
1555
|
} catch (err) {
|
|
1542
|
-
if (err instanceof
|
|
1556
|
+
if (err instanceof _chunkIY5QZZVFcjs.NotFoundError) verify = "not-found";
|
|
1543
1557
|
else {
|
|
1544
1558
|
verify = "error";
|
|
1545
|
-
code =
|
|
1559
|
+
code = _chunkIY5QZZVFcjs.isAutotaskError.call(void 0, err) ? err.code : "SERVER_ERROR";
|
|
1546
1560
|
}
|
|
1547
1561
|
}
|
|
1548
1562
|
} catch (err) {
|
|
1549
|
-
code =
|
|
1563
|
+
code = _chunkIY5QZZVFcjs.isAutotaskError.call(void 0, err) ? err.code : "SERVER_ERROR";
|
|
1550
1564
|
}
|
|
1551
1565
|
deleted.push({ id, verified: verify === "not-found", code });
|
|
1552
1566
|
}
|
|
@@ -1574,7 +1588,7 @@ async function recovery(client, input, opts = {}) {
|
|
|
1574
1588
|
const parentId = resolveParentId(input, entry, resource, operation);
|
|
1575
1589
|
const extra = resolveExtraFilter(input, operation);
|
|
1576
1590
|
const limit = resolveLimit(input, operation);
|
|
1577
|
-
const boundaryNote =
|
|
1591
|
+
const boundaryNote = _chunkIY5QZZVFcjs.DELETE_BOUNDARY_NOTES[resource];
|
|
1578
1592
|
const boundary = {
|
|
1579
1593
|
available: boundaryNote === void 0,
|
|
1580
1594
|
reason: _nullishCoalesce(boundaryNote, () => ( null)),
|
|
@@ -1586,7 +1600,7 @@ async function recovery(client, input, opts = {}) {
|
|
|
1586
1600
|
};
|
|
1587
1601
|
const isDelete = action === "delete";
|
|
1588
1602
|
if (isDelete && boundaryNote !== void 0) {
|
|
1589
|
-
throw new (0,
|
|
1603
|
+
throw new (0, _chunkIY5QZZVFcjs.DeleteBoundaryError)(
|
|
1590
1604
|
`recovery: the vendor defines no DELETE for ${resource} \u2014 the delete cannot be issued through the API (zero wire was issued)`,
|
|
1591
1605
|
{
|
|
1592
1606
|
operation,
|
|
@@ -1595,10 +1609,10 @@ async function recovery(client, input, opts = {}) {
|
|
|
1595
1609
|
}
|
|
1596
1610
|
);
|
|
1597
1611
|
}
|
|
1598
|
-
const dryRun = _optionalChain([opts, 'optionalAccess',
|
|
1599
|
-
const confirm = _nullishCoalesce(_optionalChain([opts, 'optionalAccess',
|
|
1612
|
+
const dryRun = _optionalChain([opts, 'optionalAccess', _46 => _46.dryRun]) !== false;
|
|
1613
|
+
const confirm = _nullishCoalesce(_optionalChain([opts, 'optionalAccess', _47 => _47.confirm]), () => ( input.confirm));
|
|
1600
1614
|
if (isDelete && !dryRun && confirm !== RECOVERY_CONFIRM) {
|
|
1601
|
-
throw new (0,
|
|
1615
|
+
throw new (0, _chunkIY5QZZVFcjs.ConfirmationRequiredError)(
|
|
1602
1616
|
`recovery: action 'delete' apply is destructive and requires its confirmation flag: pass confirm: "${RECOVERY_CONFIRM}"`,
|
|
1603
1617
|
{
|
|
1604
1618
|
operation: RECOVERY_CONFIRM,
|
|
@@ -1614,7 +1628,7 @@ async function recovery(client, input, opts = {}) {
|
|
|
1614
1628
|
const query = await holder.queryBounded({ filter: conditions, limit });
|
|
1615
1629
|
if (query.hasMore) {
|
|
1616
1630
|
const wire = isDelete ? "DELETE wire" : "mutating wire";
|
|
1617
|
-
throw new (0,
|
|
1631
|
+
throw new (0, _chunkIY5QZZVFcjs.RecoveryTruncatedError)(
|
|
1618
1632
|
`recovery: the marker search on ${resource} TRIPPED its match cap (${limit}) \u2014 more matches exist than were returned (zero ${wire} was issued)`,
|
|
1619
1633
|
{
|
|
1620
1634
|
operation,
|
|
@@ -1643,7 +1657,7 @@ async function recovery(client, input, opts = {}) {
|
|
|
1643
1657
|
return { ...base, simulated: true, dryRun: true };
|
|
1644
1658
|
}
|
|
1645
1659
|
if (unsafeId) {
|
|
1646
|
-
throw new (0,
|
|
1660
|
+
throw new (0, _chunkIY5QZZVFcjs.MarkerUnsafeIdError)(
|
|
1647
1661
|
`recovery: ${unsafeIds.length} of ${matches.length} match(es) on ${resource} have ids beyond Number.MAX_SAFE_INTEGER \u2014 they CANNOT be addressed through the SDK's typed delete surface (zero DELETE wire was issued)`,
|
|
1648
1662
|
{
|
|
1649
1663
|
operation,
|
|
@@ -1661,7 +1675,7 @@ function needsConfirmation(record) {
|
|
|
1661
1675
|
return record.effect === "destructive" || (_nullishCoalesce(record.flags, () => ( []))).includes("requiresApproval");
|
|
1662
1676
|
}
|
|
1663
1677
|
function refuse(message, operation, suggestedAction) {
|
|
1664
|
-
throw new (0,
|
|
1678
|
+
throw new (0, _chunkIY5QZZVFcjs.ConfirmationRequiredError)(message, { operation, suggestedAction });
|
|
1665
1679
|
}
|
|
1666
1680
|
var MODE_BY_EFFECT = {
|
|
1667
1681
|
read: "read",
|
|
@@ -1707,7 +1721,7 @@ function looseTypeOk(type, value) {
|
|
|
1707
1721
|
case "string[]":
|
|
1708
1722
|
return Array.isArray(value) && value.every((v) => typeof v === "string");
|
|
1709
1723
|
case "object":
|
|
1710
|
-
return
|
|
1724
|
+
return _chunkIY5QZZVFcjs.isRecord.call(void 0, value);
|
|
1711
1725
|
default:
|
|
1712
1726
|
return true;
|
|
1713
1727
|
}
|
|
@@ -1721,12 +1735,12 @@ function declaredArgList(record) {
|
|
|
1721
1735
|
function resolveDispatchArgs(record, argsIn) {
|
|
1722
1736
|
const operation = record.id;
|
|
1723
1737
|
const bad = (message) => {
|
|
1724
|
-
throw new (0,
|
|
1738
|
+
throw new (0, _chunkIY5QZZVFcjs.AutotaskConfigError)(`invoke: "${operation}" ${message}`, { operation });
|
|
1725
1739
|
};
|
|
1726
1740
|
if (argsIn === void 0 || argsIn === null) return [];
|
|
1727
1741
|
if (Array.isArray(argsIn)) return argsIn;
|
|
1728
1742
|
const byName = argsIn;
|
|
1729
|
-
if (!
|
|
1743
|
+
if (!_chunkIY5QZZVFcjs.isRecord.call(void 0, byName) || ![Object.prototype, null].includes(Object.getPrototypeOf(byName))) {
|
|
1730
1744
|
return bad(`args must be a positional array or a plain object of named inputs (declared: ${declaredArgList(record)})`);
|
|
1731
1745
|
}
|
|
1732
1746
|
const schema = _nullishCoalesce(record.inputSchema, () => ( {}));
|
|
@@ -1747,7 +1761,7 @@ function validateDispatchArgs(record, argsIn) {
|
|
|
1747
1761
|
const bagName = names.find((n) => schema[n].properties);
|
|
1748
1762
|
const surplus = args[names.length];
|
|
1749
1763
|
const bagHint = bagName && surplus !== null && typeof surplus === "object" && !Array.isArray(surplus) ? ` \u2014 options go inside the single ${bagName} object` : "";
|
|
1750
|
-
throw new (0,
|
|
1764
|
+
throw new (0, _chunkIY5QZZVFcjs.AutotaskConfigError)(
|
|
1751
1765
|
`invoke: "${operation}" declares ${names.length} positional arg(s) (${declaredArgList(record)}) but ${args.length} were passed \u2014 extra args are refused${bagHint}`,
|
|
1752
1766
|
{
|
|
1753
1767
|
operation,
|
|
@@ -1757,7 +1771,7 @@ function validateDispatchArgs(record, argsIn) {
|
|
|
1757
1771
|
}
|
|
1758
1772
|
const required = names.filter((n) => schema[n].required);
|
|
1759
1773
|
if (args.length < required.length) {
|
|
1760
|
-
throw new (0,
|
|
1774
|
+
throw new (0, _chunkIY5QZZVFcjs.AutotaskConfigError)(
|
|
1761
1775
|
`invoke: "${operation}" requires ${required.length} positional arg(s) (${required.map((n) => `${n}: ${schema[n].type}`).join(", ")}) but only ${args.length} were passed \u2014 declared args: ${declaredArgList(record)}`,
|
|
1762
1776
|
{ operation }
|
|
1763
1777
|
);
|
|
@@ -1768,7 +1782,7 @@ function validateDispatchArgs(record, argsIn) {
|
|
|
1768
1782
|
const name = names[i];
|
|
1769
1783
|
const spec = schema[name];
|
|
1770
1784
|
if (!looseTypeOk(spec.type, value)) {
|
|
1771
|
-
throw new (0,
|
|
1785
|
+
throw new (0, _chunkIY5QZZVFcjs.AutotaskConfigError)(
|
|
1772
1786
|
`invoke: "${operation}" arg ${i + 1} is declared ${name}: ${spec.type} \u2014 the value has the wrong type (pass a ${spec.type} value)`,
|
|
1773
1787
|
{ operation }
|
|
1774
1788
|
);
|
|
@@ -1776,17 +1790,17 @@ function validateDispatchArgs(record, argsIn) {
|
|
|
1776
1790
|
}
|
|
1777
1791
|
}
|
|
1778
1792
|
function foldFlattenedOpts(record, toolArgs) {
|
|
1779
|
-
if (!
|
|
1780
|
-
throw new (0,
|
|
1793
|
+
if (!_chunkIY5QZZVFcjs.isRecord.call(void 0, toolArgs)) {
|
|
1794
|
+
throw new (0, _chunkIY5QZZVFcjs.AutotaskConfigError)(`invoke: "${record.id}" tool args must be a plain object of named inputs`, { operation: record.id });
|
|
1781
1795
|
}
|
|
1782
|
-
const bagKeys = (_nullishCoalesce(_optionalChain([record, 'access',
|
|
1796
|
+
const bagKeys = (_nullishCoalesce(_optionalChain([record, 'access', _48 => _48.inputSchema, 'optionalAccess', _49 => _49.opts, 'optionalAccess', _50 => _50.properties]), () => ( []))).map((p) => p.name);
|
|
1783
1797
|
const flat = Object.keys(toolArgs).filter((k) => bagKeys.includes(k) && toolArgs[k] !== void 0 && toolArgs[k] !== null);
|
|
1784
1798
|
const folded = { ...toolArgs };
|
|
1785
1799
|
for (const k of bagKeys) delete folded[k];
|
|
1786
1800
|
if (folded.opts === null) delete folded.opts;
|
|
1787
1801
|
if (flat.length === 0) return folded;
|
|
1788
1802
|
if (folded.opts !== void 0) {
|
|
1789
|
-
throw new (0,
|
|
1803
|
+
throw new (0, _chunkIY5QZZVFcjs.AutotaskConfigError)(
|
|
1790
1804
|
`invoke: "${record.id}" was given both opts and flattened option(s) ${flat.map((k) => `"${k}"`).join(", ")} \u2014 pass one form`,
|
|
1791
1805
|
{ operation: record.id }
|
|
1792
1806
|
);
|
|
@@ -1796,7 +1810,7 @@ function foldFlattenedOpts(record, toolArgs) {
|
|
|
1796
1810
|
|
|
1797
1811
|
// src/operations/invoke/inputSets.ts
|
|
1798
1812
|
var PARAMS_BAG_KEYS = {
|
|
1799
|
-
query: ["filter", "limit", "includeFields", "via", "latest", "noteChars", "fieldsPreset", "fieldCheck"],
|
|
1813
|
+
query: ["filter", "limit", "includeFields", "via", "latest", "noteChars", "fieldsPreset", "fieldCheck", "names"],
|
|
1800
1814
|
// No registry row DECLARES `queryAll` today (a plan decision: the raw walk is
|
|
1801
1815
|
// called directly), so this entry never fires. It is KEPT so that a future
|
|
1802
1816
|
// `queryAll` row — which `invoke` WOULD dispatch via holder[operation] —
|
|
@@ -1847,12 +1861,12 @@ function validateParamsBag(record, args) {
|
|
|
1847
1861
|
if (record.inputSchemaStrict !== true) return;
|
|
1848
1862
|
const valid = PARAMS_BAG_KEYS[record.operation];
|
|
1849
1863
|
if (valid === void 0) return;
|
|
1850
|
-
const bag = _optionalChain([args, 'optionalAccess',
|
|
1851
|
-
if (bag === void 0 || bag === null || !
|
|
1864
|
+
const bag = _optionalChain([args, 'optionalAccess', _51 => _51[0]]);
|
|
1865
|
+
if (bag === void 0 || bag === null || !_chunkIY5QZZVFcjs.isRecord.call(void 0, bag)) return;
|
|
1852
1866
|
const unknown = Object.keys(bag).filter((k) => !valid.includes(k));
|
|
1853
1867
|
if (unknown.length === 0) return;
|
|
1854
1868
|
const suggestions = unknown.map((k) => [k, suggestForKey(k, valid)]).filter((pair) => pair[1] !== null).map(([k, s]) => `"${k}" \u2192 "${s}"`);
|
|
1855
|
-
throw new (0,
|
|
1869
|
+
throw new (0, _chunkIY5QZZVFcjs.AutotaskConfigError)(
|
|
1856
1870
|
`invoke: "${record.id}" params bag has unknown key(s) ${unknown.map((k) => `"${k}"`).join(", ")} \u2014 the bag is closed (valid keys: ${valid.join(", ")})`,
|
|
1857
1871
|
{
|
|
1858
1872
|
operation: record.id,
|
|
@@ -1863,17 +1877,17 @@ function validateParamsBag(record, args) {
|
|
|
1863
1877
|
function validateGetBag(record, args) {
|
|
1864
1878
|
if (record.kind !== "primitive" || record.operation !== "get") return;
|
|
1865
1879
|
const at = Object.keys(_nullishCoalesce(record.inputSchema, () => ( {}))).indexOf("opts");
|
|
1866
|
-
const bag = at < 0 ? void 0 : _optionalChain([args, 'optionalAccess',
|
|
1867
|
-
if (bag === void 0 || bag === null || !
|
|
1880
|
+
const bag = at < 0 ? void 0 : _optionalChain([args, 'optionalAccess', _52 => _52[at]]);
|
|
1881
|
+
if (bag === void 0 || bag === null || !_chunkIY5QZZVFcjs.isRecord.call(void 0, bag)) return;
|
|
1868
1882
|
const unknown = Object.keys(bag).filter((k) => k !== "fresh");
|
|
1869
1883
|
if (unknown.length > 0) {
|
|
1870
|
-
throw new (0,
|
|
1884
|
+
throw new (0, _chunkIY5QZZVFcjs.AutotaskConfigError)(
|
|
1871
1885
|
`invoke: "${record.id}" opts bag has unknown key(s) ${unknown.map((k) => `"${k}"`).join(", ")} \u2014 the bag is closed (valid keys: fresh)`,
|
|
1872
1886
|
{ operation: record.id, suggestedAction: "Pass only { fresh?: boolean }." }
|
|
1873
1887
|
);
|
|
1874
1888
|
}
|
|
1875
1889
|
if (bag.fresh !== void 0 && typeof bag.fresh !== "boolean") {
|
|
1876
|
-
throw new (0,
|
|
1890
|
+
throw new (0, _chunkIY5QZZVFcjs.AutotaskConfigError)(
|
|
1877
1891
|
`invoke: fresh must be a boolean (got ${typeof bag.fresh}) \u2014 "${record.id}" was not issued`,
|
|
1878
1892
|
{ operation: record.id, suggestedAction: "Pass fresh: true (bypass the read cache) or omit it." }
|
|
1879
1893
|
);
|
|
@@ -1885,7 +1899,7 @@ function validateInvokeOptions(opts, operation) {
|
|
|
1885
1899
|
const unknown = Object.keys(opts).filter((k) => !INVOKE_OPTION_KEYS.includes(k));
|
|
1886
1900
|
if (unknown.length === 0) return;
|
|
1887
1901
|
const suggestions = unknown.map((k) => [k, suggestForKey(k, ["dryRun", "confirm", "lastModifiedDate", "maxRetries", "fresh"])]).filter((pair) => pair[1] !== null).map(([k, s]) => `"${k}" \u2192 "${s}"`);
|
|
1888
|
-
throw new (0,
|
|
1902
|
+
throw new (0, _chunkIY5QZZVFcjs.AutotaskConfigError)(
|
|
1889
1903
|
`invoke: "${operation}" has unknown option key(s) ${unknown.map((k) => `"${k}"`).join(", ")} \u2014 the options set is closed (valid: dryRun, confirm, lastModifiedDate, maxRetries, fresh; "mode" is internal to the mode wrappers)`,
|
|
1890
1904
|
{
|
|
1891
1905
|
operation,
|
|
@@ -1898,7 +1912,7 @@ function unknownKeysRefusal(raw, validKeys, subject, operation) {
|
|
|
1898
1912
|
const unknown = Object.keys(raw).filter((k) => !validKeys.includes(k));
|
|
1899
1913
|
if (unknown.length === 0) return null;
|
|
1900
1914
|
const suggestions = unknown.map((k) => [k, suggestForKey(k, [...validKeys])]).filter((pair) => pair[1] !== null).map(([k, s]) => `"${k}" \u2192 "${s}"`);
|
|
1901
|
-
return new (0,
|
|
1915
|
+
return new (0, _chunkIY5QZZVFcjs.AutotaskConfigError)(
|
|
1902
1916
|
`unknown ${subject} ${unknown.map((k) => `"${k}"`).join(", ")} \u2014 the ${subject} set is closed (valid keys: ${validKeys.join(", ")})`,
|
|
1903
1917
|
{
|
|
1904
1918
|
...operation !== void 0 ? { operation } : {},
|
|
@@ -1908,7 +1922,7 @@ function unknownKeysRefusal(raw, validKeys, subject, operation) {
|
|
|
1908
1922
|
}
|
|
1909
1923
|
|
|
1910
1924
|
// src/operations/invoke/registry.ts
|
|
1911
|
-
var RECORDS =
|
|
1925
|
+
var RECORDS = _chunk73JMTV4Ocjs.CAPABILITIES;
|
|
1912
1926
|
var byId2 = new Map(RECORDS.map((r) => [r.id, r]));
|
|
1913
1927
|
|
|
1914
1928
|
// src/operations/invoke/dispatch.ts
|
|
@@ -1927,7 +1941,7 @@ function bufferResult(buf) {
|
|
|
1927
1941
|
function resolveRecord(operation) {
|
|
1928
1942
|
const record = byId2.get(operation);
|
|
1929
1943
|
if (record === void 0) {
|
|
1930
|
-
throw new (0,
|
|
1944
|
+
throw new (0, _chunkIY5QZZVFcjs.AutotaskConfigError)(
|
|
1931
1945
|
`invoke: unknown operation "${operation}" \u2014 it is not in the capability registry`,
|
|
1932
1946
|
{ operation, suggestedAction: "List the registry (the ./capabilities subpath) for the exact operation key." }
|
|
1933
1947
|
);
|
|
@@ -1938,30 +1952,30 @@ function governPreRequest(record, operation, opts) {
|
|
|
1938
1952
|
validateInvokeOptions(opts, operation);
|
|
1939
1953
|
const mode = opts.mode;
|
|
1940
1954
|
if (mode !== void 0 && MODE_BY_EFFECT[record.effect] !== mode) {
|
|
1941
|
-
throw new (0,
|
|
1955
|
+
throw new (0, _chunkIY5QZZVFcjs.AutotaskConfigError)(crossModeRefusal(operation, record.effect, mode), { operation });
|
|
1942
1956
|
}
|
|
1943
1957
|
if (opts.dryRun !== void 0 && typeof opts.dryRun !== "boolean") {
|
|
1944
|
-
throw new (0,
|
|
1958
|
+
throw new (0, _chunkIY5QZZVFcjs.AutotaskConfigError)(
|
|
1945
1959
|
`invoke: dryRun must be a boolean (got ${typeof opts.dryRun}) \u2014 "${operation}" was not issued`,
|
|
1946
1960
|
{ operation, suggestedAction: "Pass dryRun: true (simulate) or dryRun: false (apply) as a real boolean." }
|
|
1947
1961
|
);
|
|
1948
1962
|
}
|
|
1949
1963
|
if (opts.fresh !== void 0) {
|
|
1950
1964
|
if (typeof opts.fresh !== "boolean") {
|
|
1951
|
-
throw new (0,
|
|
1965
|
+
throw new (0, _chunkIY5QZZVFcjs.AutotaskConfigError)(
|
|
1952
1966
|
`invoke: fresh must be a boolean (got ${typeof opts.fresh}) \u2014 "${operation}" was not issued`,
|
|
1953
1967
|
{ operation, suggestedAction: "Pass fresh: true (bypass the read cache) or omit it." }
|
|
1954
1968
|
);
|
|
1955
1969
|
}
|
|
1956
1970
|
if (record.effect !== "read" || record.kind !== "primitive" || record.operation !== "get" || !("opts" in (_nullishCoalesce(record.inputSchema, () => ( {}))))) {
|
|
1957
|
-
throw new (0,
|
|
1971
|
+
throw new (0, _chunkIY5QZZVFcjs.AutotaskConfigError)(
|
|
1958
1972
|
`invoke: fresh applies only to a single-record "<resource>.get" read \u2014 "${operation}" was not issued`,
|
|
1959
1973
|
{ operation, suggestedAction: "Drop the fresh option (only <resource>.get consults the read cache per call)." }
|
|
1960
1974
|
);
|
|
1961
1975
|
}
|
|
1962
1976
|
}
|
|
1963
1977
|
if (record.effect === "read" && opts.dryRun === true) {
|
|
1964
|
-
throw new (0,
|
|
1978
|
+
throw new (0, _chunkIY5QZZVFcjs.AutotaskConfigError)(
|
|
1965
1979
|
`invoke: "${operation}" is a read \u2014 dryRun is not applicable (reads issue their request as-is)`,
|
|
1966
1980
|
{ operation }
|
|
1967
1981
|
);
|
|
@@ -1978,7 +1992,7 @@ function operationsHolder(client) {
|
|
|
1978
1992
|
return {
|
|
1979
1993
|
resolveAny: (identifier, opts) => resolveAny(client, identifier, opts),
|
|
1980
1994
|
searchAcrossResources: (query, opts) => searchAcrossResources(client, query, opts),
|
|
1981
|
-
fetchMany: (items, opts) =>
|
|
1995
|
+
fetchMany: (items, opts) => _chunkIY5QZZVFcjs.fetchMany.call(void 0, client, items, opts),
|
|
1982
1996
|
// Issue #62: the generic aggregate + the cheap count — the
|
|
1983
1997
|
// groupBy/sum-absent mode is ONE vendor /query/count (the S12-C blind
|
|
1984
1998
|
// sentinel rides through); the group/sum modes walk the named
|
|
@@ -1990,12 +2004,12 @@ function operationsHolder(client) {
|
|
|
1990
2004
|
// Issue #59 PR-B: the bulk fetch by ids — query-first chunked `id in`
|
|
1991
2005
|
// reads + the per-id `get` fallback (blind-surface-safe; per-item
|
|
1992
2006
|
// typed outcomes reuse the fetchMany shapes).
|
|
1993
|
-
fetchByIds: (items, opts) =>
|
|
2007
|
+
fetchByIds: (items, opts) => _chunkIY5QZZVFcjs.fetchByIds.call(void 0, client, items, opts),
|
|
1994
2008
|
// Issue #65: opt-in resource name expansion — per-id resources.get
|
|
1995
2009
|
// reads ONLY (never an id-in query — the resources table can be blind
|
|
1996
2010
|
// to count/query while per-id reads work); blind-marked rows for ids
|
|
1997
2011
|
// the API user cannot resolve; the name cache (default-on).
|
|
1998
|
-
expandResourceNames: (ids, opts) =>
|
|
2012
|
+
expandResourceNames: (ids, opts) => _chunkIY5QZZVFcjs.expandResourceNames.call(void 0, client, ids, opts),
|
|
1999
2013
|
relationshipMap: (resourceKey) => relationshipMap(client, resourceKey),
|
|
2000
2014
|
// Issue #11: the served blind-surface inventory (zero wire) + the
|
|
2001
2015
|
// bounded caller-opted reachability sweep (read-only, confirmProbe-
|
|
@@ -2005,12 +2019,12 @@ function operationsHolder(client) {
|
|
|
2005
2019
|
// Issue #12: the served zone-fact create-guidance catalog (zero wire).
|
|
2006
2020
|
createGuidance: (opts) => createGuidance(client, opts),
|
|
2007
2021
|
// Issue #202: ExecuteCommand deep links — pure, zero wire.
|
|
2008
|
-
uiLink: (input) =>
|
|
2022
|
+
uiLink: (input) => _chunkIY5QZZVFcjs.uiLink.call(void 0, client, input),
|
|
2009
2023
|
// Issue #31: the opt-in live field-metadata channel — N bounded
|
|
2010
2024
|
// entityInformation GETs (the op's own cap refuses over-cap fan-outs
|
|
2011
2025
|
// pre-request; per-resource failures are recorded on the row and
|
|
2012
2026
|
// never abort the call).
|
|
2013
|
-
fieldCatalog: (opts) =>
|
|
2027
|
+
fieldCatalog: (opts) => _chunkIY5QZZVFcjs.fieldCatalog.call(void 0, client, opts),
|
|
2014
2028
|
// Issue #9: the one-call recovery/cleanup op — effect write in the
|
|
2015
2029
|
// registry (the governor's dry-run-first applies to it); the op's own
|
|
2016
2030
|
// confirm gate makes the destructive action deliberate (the governor
|
|
@@ -2020,15 +2034,15 @@ function operationsHolder(client) {
|
|
|
2020
2034
|
}
|
|
2021
2035
|
function resolveHolder(client, record, operation) {
|
|
2022
2036
|
const clientBag = client;
|
|
2023
|
-
let holder = clientBag[
|
|
2037
|
+
let holder = clientBag[_chunkIY5QZZVFcjs.camelKey.call(void 0, record.resource)];
|
|
2024
2038
|
if (typeof holder === "function") {
|
|
2025
|
-
holder = _nullishCoalesce(clientBag[`${
|
|
2039
|
+
holder = _nullishCoalesce(clientBag[`${_chunkIY5QZZVFcjs.camelKey.call(void 0, record.resource)}Resource`], () => ( holder));
|
|
2026
2040
|
}
|
|
2027
2041
|
if (holder === void 0 && record.resource === "operations") {
|
|
2028
2042
|
holder = operationsHolder(client);
|
|
2029
2043
|
}
|
|
2030
2044
|
if (holder === void 0) {
|
|
2031
|
-
throw new (0,
|
|
2045
|
+
throw new (0, _chunkIY5QZZVFcjs.AutotaskConfigError)(
|
|
2032
2046
|
`invoke: the client exposes no accessor for resource "${record.resource}"`,
|
|
2033
2047
|
{ operation }
|
|
2034
2048
|
);
|
|
@@ -2088,11 +2102,12 @@ async function invokeMode(client, operation, argsIn = [], opts = {}) {
|
|
|
2088
2102
|
const boundedQuery = record.kind === "primitive" && record.operation === "query";
|
|
2089
2103
|
const countedQuery = record.kind === "primitive" && record.operation === "count";
|
|
2090
2104
|
const holder = resolveHolder(client, record, operation);
|
|
2091
|
-
if (boundedQuery || countedQuery) await
|
|
2105
|
+
if (boundedQuery || countedQuery) await _chunkIY5QZZVFcjs.validateQueryFieldNames.call(void 0, record, holder, args);
|
|
2106
|
+
const labelQuery = boundedQuery && _chunkIY5QZZVFcjs.readNamesOpt.call(void 0, _optionalChain([args, 'access', _53 => _53[0], 'optionalAccess', _54 => _54["names"]]), `invoke: "${record.id}" params bag`);
|
|
2092
2107
|
const methodName = boundedQuery ? "queryBounded" : record.operation;
|
|
2093
2108
|
const method = holder[methodName];
|
|
2094
2109
|
if (typeof method !== "function") {
|
|
2095
|
-
throw new (0,
|
|
2110
|
+
throw new (0, _chunkIY5QZZVFcjs.AutotaskConfigError)(
|
|
2096
2111
|
`invoke: "${record.resource}.${methodName}" is not a callable method on the client`,
|
|
2097
2112
|
{ operation }
|
|
2098
2113
|
);
|
|
@@ -2102,6 +2117,11 @@ async function invokeMode(client, operation, argsIn = [], opts = {}) {
|
|
|
2102
2117
|
const callArgs = buildCallArgs(record, args, mutationOpts, isWrite);
|
|
2103
2118
|
if (opts.fresh === true) appendFresh(record, callArgs);
|
|
2104
2119
|
const result = await method.apply(holder, callArgs);
|
|
2120
|
+
if (labelQuery && Array.isArray(_optionalChain([result, 'optionalAccess', _55 => _55.items]))) {
|
|
2121
|
+
const bounded = result;
|
|
2122
|
+
const labelled = await _chunkIY5QZZVFcjs.labelRows.call(void 0, client, record.resource, bounded.items);
|
|
2123
|
+
return { ...bounded, items: labelled.rows, ...labelled.names !== void 0 ? { names: labelled.names } : {} };
|
|
2124
|
+
}
|
|
2105
2125
|
return Buffer.isBuffer(result) ? bufferResult(result) : result;
|
|
2106
2126
|
}
|
|
2107
2127
|
|
|
@@ -2171,4 +2191,4 @@ async function invokeDelete(client, operation, args = [], opts = {}) {
|
|
|
2171
2191
|
|
|
2172
2192
|
|
|
2173
2193
|
|
|
2174
|
-
exports.AGGREGATE_DATE_BUCKETS = AGGREGATE_DATE_BUCKETS; exports.AGGREGATE_DEFAULT_LIMIT = AGGREGATE_DEFAULT_LIMIT; exports.AGGREGATE_DEFAULT_TOP = AGGREGATE_DEFAULT_TOP; exports.AGGREGATE_TOP_MAX = AGGREGATE_TOP_MAX; exports.BLIND_SURFACE_KINDS = BLIND_SURFACE_KINDS; exports.CREATE_BLOCKER_KINDS = CREATE_BLOCKER_KINDS; exports.ENTITY_TYPE_TO_RESOURCE =
|
|
2194
|
+
exports.AGGREGATE_DATE_BUCKETS = AGGREGATE_DATE_BUCKETS; exports.AGGREGATE_DEFAULT_LIMIT = AGGREGATE_DEFAULT_LIMIT; exports.AGGREGATE_DEFAULT_TOP = AGGREGATE_DEFAULT_TOP; exports.AGGREGATE_TOP_MAX = AGGREGATE_TOP_MAX; exports.BLIND_SURFACE_KINDS = BLIND_SURFACE_KINDS; exports.CREATE_BLOCKER_KINDS = CREATE_BLOCKER_KINDS; exports.ENTITY_TYPE_TO_RESOURCE = _chunkIY5QZZVFcjs.ENTITY_TYPE_TO_RESOURCE; exports.EXPAND_RESOURCE_NAMES_MAX_IDS = _chunkIY5QZZVFcjs.EXPAND_RESOURCE_NAMES_MAX_IDS; exports.FETCH_BY_IDS_CHUNK_SIZE = _chunkIY5QZZVFcjs.FETCH_BY_IDS_CHUNK_SIZE; exports.FETCH_BY_IDS_MAX_ITEMS = _chunkIY5QZZVFcjs.FETCH_BY_IDS_MAX_ITEMS; exports.FETCH_MANY_MAX_ITEMS = _chunkIY5QZZVFcjs.FETCH_MANY_MAX_ITEMS; exports.FIELD_CACHE_KINDS = _chunkIY5QZZVFcjs.FIELD_CACHE_KINDS; exports.FIELD_CATALOG_HONESTY_NOTE = _chunkIY5QZZVFcjs.FIELD_CATALOG_HONESTY_NOTE; exports.INVOKE_OPTION_KEYS = INVOKE_OPTION_KEYS; exports.MAX_FIELD_CATALOG_WIRE = _chunkIY5QZZVFcjs.MAX_FIELD_CATALOG_WIRE; exports.PARAMS_BAG_KEYS = PARAMS_BAG_KEYS; exports.PICKLIST_VALUE_NOT_SERVED_NOTE = _chunkIY5QZZVFcjs.PICKLIST_VALUE_NOT_SERVED_NOTE; exports.RECOVERY_CONFIRM = RECOVERY_CONFIRM; exports.RECOVERY_DEFAULT_LIMIT = RECOVERY_DEFAULT_LIMIT; exports.RECOVERY_MAX_LIMIT = RECOVERY_MAX_LIMIT; exports.UI_LINK_ENTITIES = _chunkIY5QZZVFcjs.UI_LINK_ENTITIES; exports.WORKFLOW_RESOURCES = _chunkIY5QZZVFcjs.WORKFLOW_RESOURCES; exports.aggregate = aggregate; exports.blindSurfaces = blindSurfaces; exports.buildUiLink = _chunkIY5QZZVFcjs.buildUiLink; exports.createGuidance = createGuidance; exports.dateBucketLabel = dateBucketLabel; exports.effectiveRequiredFields = _chunkIY5QZZVFcjs.effectiveRequiredFields; exports.expandResourceNames = _chunkIY5QZZVFcjs.expandResourceNames; exports.fetchByIds = _chunkIY5QZZVFcjs.fetchByIds; exports.fetchMany = _chunkIY5QZZVFcjs.fetchMany; exports.fieldCatalog = _chunkIY5QZZVFcjs.fieldCatalog; exports.foldFlattenedOpts = foldFlattenedOpts; exports.invoke = invoke; exports.invokeDelete = invokeDelete; exports.invokeRead = invokeRead; exports.invokeWrite = invokeWrite; exports.isEnumerableResource = _chunkIY5QZZVFcjs.isEnumerableResource; exports.needsConfirmation = needsConfirmation; exports.probeReachability = probeReachability; exports.recovery = recovery; exports.relationshipMap = relationshipMap; exports.resolveAny = resolveAny; exports.resourceForEntityType = _chunkIY5QZZVFcjs.resourceForEntityType; exports.revenueRollup = revenueRollup; exports.searchAcrossResources = searchAcrossResources; exports.uiLink = _chunkIY5QZZVFcjs.uiLink; exports.unknownKeysRefusal = unknownKeysRefusal; exports.validateDispatchArgs = validateDispatchArgs; exports.validateFetchManyItems = _chunkIY5QZZVFcjs.validateFetchManyItems; exports.validateInvokeOptions = validateInvokeOptions; exports.validateParamsBag = validateParamsBag;
|