node-autotask 0.21.0 → 0.23.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/ARCHITECTURE.md +44 -21
- package/CHANGELOG.md +31 -0
- package/MCP_TOOL_CATALOG.json +69 -10
- package/MCP_TOOL_MANIFEST.md +20 -17
- package/MCP_TOOL_OVERRIDES.json +6 -6
- package/N8N_MCP_MANIFEST.json +20 -4
- package/N8N_MCP_MANIFEST.md +6 -5
- package/README.md +9 -9
- package/capabilities.json +2898 -7412
- package/capabilities.schema.json +0 -12
- package/dist/capabilities.cjs +2 -2
- package/dist/capabilities.d.cts +0 -2
- package/dist/capabilities.d.ts +0 -2
- package/dist/capabilities.js +1 -1
- package/dist/{chunk-KD6LOSAK.js → chunk-B5SNZ3TZ.js} +3473 -3084
- package/dist/{chunk-QWAWNQEZ.cjs → chunk-D5TVBI4U.cjs} +3021 -2632
- package/dist/{chunk-CBUY3MKB.cjs → chunk-JUO3URUI.cjs} +2897 -7411
- package/dist/{chunk-HEW4WJLC.cjs → chunk-N27NUB4R.cjs} +2466 -1745
- package/dist/{chunk-DM67SXCO.js → chunk-OGNUI3UR.js} +2897 -7411
- package/dist/{chunk-GBVUXAUA.js → chunk-PVUUOM5G.js} +2092 -1371
- package/dist/{chunk-PMPFQDVM.cjs → chunk-TTQB537V.cjs} +135 -135
- package/dist/{chunk-JRSU6PKP.js → chunk-VYFO2N5F.js} +2 -2
- package/dist/{index-BXtKN1M5.d.cts → index-BVtycq-6.d.cts} +1 -1
- package/dist/{index-BXtKN1M5.d.ts → index-BVtycq-6.d.ts} +1 -1
- package/dist/{index-DSnuyiTr.d.ts → index-DBoX-Dnk.d.ts} +430 -957
- package/dist/{index-ByWYfNog.d.cts → index-NC-x-bYl.d.cts} +430 -957
- package/dist/index.cjs +91 -62
- package/dist/index.d.cts +360 -5
- package/dist/index.d.ts +360 -5
- package/dist/index.js +74 -45
- package/dist/operations/index.cjs +462 -462
- package/dist/operations/index.d.cts +78 -84
- package/dist/operations/index.d.ts +78 -84
- package/dist/operations/index.js +382 -382
- package/dist/pool.cjs +8 -8
- package/dist/pool.d.cts +2 -2
- package/dist/pool.d.ts +2 -2
- package/dist/pool.js +4 -4
- package/dist/resources/index.cjs +4 -4
- package/dist/resources/index.d.cts +2 -2
- package/dist/resources/index.d.ts +2 -2
- package/dist/resources/index.js +3 -3
- package/dist/types/index.d.cts +1 -1
- package/dist/types/index.d.ts +1 -1
- package/docs/API.md +133 -41
- package/docs/N8N-ADAPTER.md +3 -3
- package/examples/mcp/errors.ts +135 -0
- package/examples/mcp/manifest.ts +168 -0
- package/examples/mcp/register.ts +66 -0
- package/examples/mcp/schemas.ts +203 -0
- package/examples/mcp/tools-meta.ts +120 -0
- package/examples/mcp/tools-mode.ts +177 -0
- package/examples/mcp/tools-read.ts +264 -0
- package/examples/mcp/types.ts +34 -0
- package/examples/mcp-register.ts +9 -1074
- package/package.json +1 -1
|
@@ -37,44 +37,63 @@
|
|
|
37
37
|
|
|
38
38
|
|
|
39
39
|
|
|
40
|
-
var _chunkQWAWNQEZcjs = require('../chunk-QWAWNQEZ.cjs');
|
|
41
40
|
|
|
42
41
|
|
|
43
|
-
|
|
42
|
+
|
|
43
|
+
var _chunkD5TVBI4Ucjs = require('../chunk-D5TVBI4U.cjs');
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
var _chunkJUO3URUIcjs = require('../chunk-JUO3URUI.cjs');
|
|
44
47
|
|
|
45
48
|
// src/operations/searchAcrossResources.ts
|
|
46
49
|
var DEFAULT_LIMIT = 25;
|
|
47
50
|
function resourceFor(client, key) {
|
|
48
|
-
return client[
|
|
51
|
+
return client[_chunkD5TVBI4Ucjs.camelKey.call(void 0, key)];
|
|
49
52
|
}
|
|
50
53
|
async function searchAcrossResources(client, query, opts = {}) {
|
|
51
54
|
const text = query.trim();
|
|
52
55
|
if (text === "") {
|
|
53
|
-
throw new (0,
|
|
56
|
+
throw new (0, _chunkD5TVBI4Ucjs.AutotaskConfigError)("searchAcrossResources: query must be a non-empty string");
|
|
54
57
|
}
|
|
55
|
-
const keys = _nullishCoalesce(opts.resources, () => (
|
|
58
|
+
const keys = _nullishCoalesce(opts.resources, () => ( _chunkD5TVBI4Ucjs.WORKFLOW_RESOURCES));
|
|
56
59
|
if (keys.length === 0) {
|
|
57
|
-
throw new (0,
|
|
60
|
+
throw new (0, _chunkD5TVBI4Ucjs.AutotaskConfigError)("searchAcrossResources: no resources requested");
|
|
61
|
+
}
|
|
62
|
+
const limit = _chunkD5TVBI4Ucjs.clampPageSize.call(void 0, _nullishCoalesce(opts.limit, () => ( DEFAULT_LIMIT)));
|
|
63
|
+
const totalLimit = opts.totalLimit;
|
|
64
|
+
if (totalLimit !== void 0 && !(Number.isInteger(totalLimit) && totalLimit >= 1)) {
|
|
65
|
+
throw new (0, _chunkD5TVBI4Ucjs.AutotaskConfigError)("searchAcrossResources: totalLimit must be a positive integer");
|
|
58
66
|
}
|
|
59
|
-
const limit = _chunkQWAWNQEZcjs.clampPageSize.call(void 0, _nullishCoalesce(opts.limit, () => ( DEFAULT_LIMIT)));
|
|
60
67
|
const results = [];
|
|
61
68
|
const skipped = [];
|
|
69
|
+
const notSearched = [];
|
|
70
|
+
let remaining = _nullishCoalesce(totalLimit, () => ( Infinity));
|
|
71
|
+
let hitQuota = false;
|
|
62
72
|
for (const key of keys) {
|
|
63
73
|
const holder = resourceFor(client, key);
|
|
64
74
|
if (holder === void 0 || typeof holder.search !== "function") {
|
|
65
75
|
skipped.push(key);
|
|
66
76
|
continue;
|
|
67
77
|
}
|
|
68
|
-
|
|
78
|
+
if (remaining <= 0) {
|
|
79
|
+
notSearched.push(key);
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
const ask = Math.min(limit, remaining);
|
|
83
|
+
const matches = await holder.search(text, { limit: ask });
|
|
69
84
|
const rows = Array.isArray(matches) ? matches.filter((m) => typeof m === "object" && m !== null).map((m) => m) : [];
|
|
85
|
+
if (totalLimit !== void 0) rows.length = Math.min(rows.length, ask);
|
|
70
86
|
results.push({ resource: key, matches: rows });
|
|
87
|
+
remaining -= rows.length;
|
|
88
|
+
if (rows.length === ask) hitQuota = true;
|
|
71
89
|
}
|
|
72
|
-
return { query: text, results, skipped };
|
|
90
|
+
if (totalLimit === void 0) return { query: text, results, skipped };
|
|
91
|
+
return { query: text, results, skipped, notSearched, truncated: notSearched.length > 0 || hitQuota };
|
|
73
92
|
}
|
|
74
93
|
|
|
75
94
|
// src/operations/resolveAny.ts
|
|
76
95
|
function resourceFor2(client, key) {
|
|
77
|
-
return client[
|
|
96
|
+
return client[_chunkD5TVBI4Ucjs.camelKey.call(void 0, key)];
|
|
78
97
|
}
|
|
79
98
|
var FAULT_CATEGORIES = /* @__PURE__ */ new Set(["auth", "rate_limit", "server", "network", "timeout", "policy"]);
|
|
80
99
|
function missCost(identifier) {
|
|
@@ -83,13 +102,13 @@ function missCost(identifier) {
|
|
|
83
102
|
}
|
|
84
103
|
async function resolveAny(client, identifier, opts = {}) {
|
|
85
104
|
if (typeof identifier === "number") {
|
|
86
|
-
|
|
105
|
+
_chunkD5TVBI4Ucjs.parseIdentifier.call(void 0, identifier, "identifier");
|
|
87
106
|
} else if (identifier.trim() === "") {
|
|
88
|
-
throw new (0,
|
|
107
|
+
throw new (0, _chunkD5TVBI4Ucjs.AutotaskConfigError)("resolveAny: identifier must be non-empty");
|
|
89
108
|
}
|
|
90
|
-
const keys = _nullishCoalesce(opts.resources, () => (
|
|
109
|
+
const keys = _nullishCoalesce(opts.resources, () => ( _chunkD5TVBI4Ucjs.WORKFLOW_RESOURCES));
|
|
91
110
|
if (keys.length === 0) {
|
|
92
|
-
throw new (0,
|
|
111
|
+
throw new (0, _chunkD5TVBI4Ucjs.AutotaskConfigError)("resolveAny: no resources requested");
|
|
93
112
|
}
|
|
94
113
|
const results = [];
|
|
95
114
|
for (const key of keys) {
|
|
@@ -119,9 +138,9 @@ async function resolveAny(client, identifier, opts = {}) {
|
|
|
119
138
|
} catch (err) {
|
|
120
139
|
let code;
|
|
121
140
|
let candidates = [];
|
|
122
|
-
if (err instanceof
|
|
141
|
+
if (err instanceof _chunkD5TVBI4Ucjs.AutotaskConfigError) {
|
|
123
142
|
code = "CONFIG_ERROR";
|
|
124
|
-
} else if (
|
|
143
|
+
} else if (_chunkD5TVBI4Ucjs.isAutotaskError.call(void 0, err)) {
|
|
125
144
|
if (FAULT_CATEGORIES.has(err.category)) throw err;
|
|
126
145
|
code = err.code;
|
|
127
146
|
if (code === "RESOLUTION_AMBIGUOUS" && err.resourceIds !== void 0) {
|
|
@@ -148,7 +167,7 @@ async function resolveAny(client, identifier, opts = {}) {
|
|
|
148
167
|
// src/operations/aggregate.ts
|
|
149
168
|
var AGGREGATE_TOP_MAX = 100;
|
|
150
169
|
var AGGREGATE_DEFAULT_TOP = 25;
|
|
151
|
-
var AGGREGATE_DEFAULT_LIMIT =
|
|
170
|
+
var AGGREGATE_DEFAULT_LIMIT = _chunkD5TVBI4Ucjs.BOUNDED_QUERY_MAX_LIMIT;
|
|
152
171
|
var AGGREGATE_DATE_BUCKETS = ["month", "week", "year"];
|
|
153
172
|
var DATE_ONLY_RE = /^(\d{4})-(\d{2})-(\d{2})$/;
|
|
154
173
|
var DATETIME_RE = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(\.\d{1,9})?(Z|[+-]\d{2}:?\d{2})?$/;
|
|
@@ -205,7 +224,7 @@ function dateBucketLabel(value, bucket) {
|
|
|
205
224
|
}
|
|
206
225
|
var QUERY_RESOURCE_KEYS = (() => {
|
|
207
226
|
const s = /* @__PURE__ */ new Set();
|
|
208
|
-
for (const rec of
|
|
227
|
+
for (const rec of _chunkJUO3URUIcjs.CAPABILITIES) if (rec.operation === "query") s.add(rec.resource);
|
|
209
228
|
return s;
|
|
210
229
|
})();
|
|
211
230
|
var AGGREGATE_OPT_KEYS = ["groupBy", "sum", "top", "limit"];
|
|
@@ -213,41 +232,43 @@ var OP_RE = /^([a-z0-9_]+)\.query$/;
|
|
|
213
232
|
function num(v) {
|
|
214
233
|
return typeof v === "number" && Number.isFinite(v) ? v : 0;
|
|
215
234
|
}
|
|
216
|
-
function
|
|
217
|
-
const problems = [];
|
|
218
|
-
let resourceKey;
|
|
235
|
+
function parseOperationKey(operation, problems) {
|
|
219
236
|
if (typeof operation !== "string" || !OP_RE.test(operation)) {
|
|
220
237
|
problems.push(
|
|
221
238
|
`operation must be exactly "<planResourceKey>.query" (the resource's bounded query op \u2014 e.g. "billing_items.query"); a special op, a ".count" row, or any other verb is not an aggregate surface \u2014 see autotask_catalog for the exact plan keys`
|
|
222
239
|
);
|
|
223
|
-
|
|
224
|
-
const key = OP_RE.exec(operation)[1];
|
|
225
|
-
resourceKey = key;
|
|
226
|
-
if (!QUERY_RESOURCE_KEYS.has(key)) {
|
|
227
|
-
problems.push(
|
|
228
|
-
`operation "${operation}": "${key}" has no query row in the capability registry (116 query surfaces) \u2014 see autotask_catalog for the exact plan keys`
|
|
229
|
-
);
|
|
230
|
-
}
|
|
240
|
+
return void 0;
|
|
231
241
|
}
|
|
232
|
-
|
|
242
|
+
const key = OP_RE.exec(operation)[1];
|
|
243
|
+
if (!QUERY_RESOURCE_KEYS.has(key)) {
|
|
244
|
+
problems.push(
|
|
245
|
+
`operation "${operation}": "${key}" has no query row in the capability registry (116 query surfaces) \u2014 see autotask_catalog for the exact plan keys`
|
|
246
|
+
);
|
|
247
|
+
}
|
|
248
|
+
return key;
|
|
249
|
+
}
|
|
250
|
+
function parseFilterConditions(filter, problems) {
|
|
233
251
|
if (filter === void 0 || filter === null) {
|
|
234
|
-
|
|
235
|
-
} else {
|
|
236
|
-
const conds = Array.isArray(filter) ? filter : filter.filter;
|
|
237
|
-
if (!Array.isArray(conds)) {
|
|
238
|
-
problems.push("filter must be the query-bag filter (a conditions array, or { filter: [...] })");
|
|
239
|
-
} else if (conds.length === 0) {
|
|
240
|
-
conditions = [];
|
|
241
|
-
} else {
|
|
242
|
-
try {
|
|
243
|
-
conditions = _chunkQWAWNQEZcjs.buildFilter.call(void 0, conds).filter;
|
|
244
|
-
} catch (err) {
|
|
245
|
-
problems.push(err instanceof _chunkQWAWNQEZcjs.AutotaskConfigError ? err.message : `filter must be the query-bag filter (13 operators; caps 500 OR-conditions / 1 UDF / 8000 chars); ${String(err)}`);
|
|
246
|
-
}
|
|
247
|
-
}
|
|
252
|
+
return [];
|
|
248
253
|
}
|
|
254
|
+
const conds = Array.isArray(filter) ? filter : filter.filter;
|
|
255
|
+
if (!Array.isArray(conds)) {
|
|
256
|
+
problems.push("filter must be the query-bag filter (a conditions array, or { filter: [...] })");
|
|
257
|
+
return [];
|
|
258
|
+
}
|
|
259
|
+
if (conds.length === 0) {
|
|
260
|
+
return [];
|
|
261
|
+
}
|
|
262
|
+
try {
|
|
263
|
+
return _chunkD5TVBI4Ucjs.buildFilter.call(void 0, conds).filter;
|
|
264
|
+
} catch (err) {
|
|
265
|
+
problems.push(err instanceof _chunkD5TVBI4Ucjs.AutotaskConfigError ? err.message : `filter must be the query-bag filter (13 operators; caps 500 OR-conditions / 1 UDF / 8000 chars); ${String(err)}`);
|
|
266
|
+
return [];
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
function checkOptsBag(opts, problems) {
|
|
249
270
|
if (opts !== void 0 && (typeof opts !== "object" || opts === null || Array.isArray(opts))) {
|
|
250
|
-
throw new (0,
|
|
271
|
+
throw new (0, _chunkD5TVBI4Ucjs.AutotaskConfigError)(
|
|
251
272
|
`aggregate: opts must be the options object (got ${Array.isArray(opts) ? "an array" : typeof opts})`,
|
|
252
273
|
{ operation: "operations.aggregate" }
|
|
253
274
|
);
|
|
@@ -257,58 +278,63 @@ function validateAggregate(operation, filter, opts) {
|
|
|
257
278
|
problems.push(`unknown opts key "${key}" \u2014 the bag is closed: ${AGGREGATE_OPT_KEYS.join(", ")}`);
|
|
258
279
|
}
|
|
259
280
|
}
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
281
|
+
}
|
|
282
|
+
function checkSumFields(name, fields, oracles, problems) {
|
|
283
|
+
if (fields === void 0) return [];
|
|
284
|
+
if (!Array.isArray(fields) || fields.length === 0 || fields.some((f) => typeof f !== "string" || f.trim() === "")) {
|
|
285
|
+
problems.push(`${name} must be a non-empty array of exact vendor field names (discover them via operations.fieldCatalog)`);
|
|
286
|
+
return [];
|
|
287
|
+
}
|
|
288
|
+
const out = [];
|
|
289
|
+
for (const f of fields) {
|
|
290
|
+
if (oracles.fieldSets === void 0 || !oracles.fieldSets.includes(f)) {
|
|
291
|
+
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)`);
|
|
292
|
+
} else {
|
|
293
|
+
out.push(f);
|
|
267
294
|
}
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
295
|
+
}
|
|
296
|
+
return out;
|
|
297
|
+
}
|
|
298
|
+
function parseGroupSpec(f, oracles, problems) {
|
|
299
|
+
const { resourceKey, fieldSets, dateSets } = oracles;
|
|
300
|
+
const at = f.indexOf("@");
|
|
301
|
+
if (at === -1) {
|
|
302
|
+
if (fieldSets === void 0 || !fieldSets.includes(f)) {
|
|
303
|
+
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)`);
|
|
304
|
+
return void 0;
|
|
275
305
|
}
|
|
276
|
-
return
|
|
277
|
-
}
|
|
306
|
+
return { name: f, base: f };
|
|
307
|
+
}
|
|
308
|
+
const base = f.slice(0, at);
|
|
309
|
+
const suffix = f.slice(at + 1);
|
|
310
|
+
if (!AGGREGATE_DATE_BUCKETS.includes(suffix)) {
|
|
311
|
+
problems.push(`groupBy: "${f}": unknown bucket suffix "${suffix}" \u2014 the closed set is month | week | year (the suffix applies to date-typed fields only)`);
|
|
312
|
+
return void 0;
|
|
313
|
+
}
|
|
314
|
+
if (fieldSets === void 0 || !fieldSets.includes(base)) {
|
|
315
|
+
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)`);
|
|
316
|
+
return void 0;
|
|
317
|
+
}
|
|
318
|
+
if (dateSets === void 0 || !dateSets.includes(base)) {
|
|
319
|
+
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)`);
|
|
320
|
+
return void 0;
|
|
321
|
+
}
|
|
322
|
+
return { name: f, base, bucket: suffix };
|
|
323
|
+
}
|
|
324
|
+
function parseGroupBy(opts, oracles, problems) {
|
|
278
325
|
const groupBy = [];
|
|
279
|
-
if (opts.groupBy
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
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)`);
|
|
288
|
-
} else {
|
|
289
|
-
groupBy.push({ name: f, base: f });
|
|
290
|
-
}
|
|
291
|
-
continue;
|
|
292
|
-
}
|
|
293
|
-
const base = f.slice(0, at);
|
|
294
|
-
const suffix = f.slice(at + 1);
|
|
295
|
-
if (!AGGREGATE_DATE_BUCKETS.includes(suffix)) {
|
|
296
|
-
problems.push(`groupBy: "${f}": unknown bucket suffix "${suffix}" \u2014 the closed set is month | week | year (the suffix applies to date-typed fields only)`);
|
|
297
|
-
continue;
|
|
298
|
-
}
|
|
299
|
-
if (fieldSets === void 0 || !fieldSets.includes(base)) {
|
|
300
|
-
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)`);
|
|
301
|
-
continue;
|
|
302
|
-
}
|
|
303
|
-
if (dateSets === void 0 || !dateSets.includes(base)) {
|
|
304
|
-
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)`);
|
|
305
|
-
continue;
|
|
306
|
-
}
|
|
307
|
-
groupBy.push({ name: f, base, bucket: suffix });
|
|
308
|
-
}
|
|
309
|
-
}
|
|
326
|
+
if (opts.groupBy === void 0) return groupBy;
|
|
327
|
+
if (!Array.isArray(opts.groupBy) || opts.groupBy.length === 0 || opts.groupBy.some((f) => typeof f !== "string" || f.trim() === "")) {
|
|
328
|
+
problems.push("groupBy must be a non-empty array of exact vendor field names (a date-typed field may carry the closed bucket suffix @month | @week | @year \u2014 discover them via operations.fieldCatalog)");
|
|
329
|
+
return groupBy;
|
|
330
|
+
}
|
|
331
|
+
for (const f of opts.groupBy) {
|
|
332
|
+
const spec = parseGroupSpec(f, oracles, problems);
|
|
333
|
+
if (spec !== void 0) groupBy.push(spec);
|
|
310
334
|
}
|
|
311
|
-
|
|
335
|
+
return groupBy;
|
|
336
|
+
}
|
|
337
|
+
function parseTopAndLimit(opts, problems) {
|
|
312
338
|
let top = AGGREGATE_DEFAULT_TOP;
|
|
313
339
|
if (opts.top !== void 0) {
|
|
314
340
|
if (!Number.isInteger(opts.top)) {
|
|
@@ -322,11 +348,26 @@ function validateAggregate(operation, filter, opts) {
|
|
|
322
348
|
if (!Number.isInteger(opts.limit)) {
|
|
323
349
|
problems.push(`limit must be an integer (got ${String(opts.limit)})`);
|
|
324
350
|
} else {
|
|
325
|
-
limit = Math.min(Math.max(opts.limit, 1),
|
|
351
|
+
limit = Math.min(Math.max(opts.limit, 1), _chunkD5TVBI4Ucjs.BOUNDED_QUERY_MAX_LIMIT);
|
|
326
352
|
}
|
|
327
353
|
}
|
|
354
|
+
return { top, limit };
|
|
355
|
+
}
|
|
356
|
+
function validateAggregate(operation, filter, opts) {
|
|
357
|
+
const problems = [];
|
|
358
|
+
const resourceKey = parseOperationKey(operation, problems);
|
|
359
|
+
const conditions = parseFilterConditions(filter, problems);
|
|
360
|
+
checkOptsBag(opts, problems);
|
|
361
|
+
const oracles = {
|
|
362
|
+
resourceKey,
|
|
363
|
+
fieldSets: resourceKey !== void 0 ? _chunkD5TVBI4Ucjs.MODEL_FIELD_SETS[resourceKey] : void 0,
|
|
364
|
+
dateSets: resourceKey !== void 0 ? _chunkD5TVBI4Ucjs.MODEL_DATE_FIELDS[resourceKey] : void 0
|
|
365
|
+
};
|
|
366
|
+
const groupBy = parseGroupBy(opts, oracles, problems);
|
|
367
|
+
const sum = checkSumFields("sum", opts.sum, oracles, problems);
|
|
368
|
+
const { top, limit } = parseTopAndLimit(opts, problems);
|
|
328
369
|
if (problems.length > 0) {
|
|
329
|
-
throw new (0,
|
|
370
|
+
throw new (0, _chunkD5TVBI4Ucjs.AutotaskConfigError)(
|
|
330
371
|
`aggregate: ${problems.length} problem(s) found pre-request (zero wire was issued)
|
|
331
372
|
- ` + problems.join("\n- "),
|
|
332
373
|
{ operation: "operations.aggregate" }
|
|
@@ -334,27 +375,9 @@ function validateAggregate(operation, filter, opts) {
|
|
|
334
375
|
}
|
|
335
376
|
return { resourceKey, conditions, groupBy, sum, top, limit };
|
|
336
377
|
}
|
|
337
|
-
|
|
338
|
-
const v = validateAggregate(operation, filter, opts);
|
|
339
|
-
const holder = client[_chunkQWAWNQEZcjs.camelKey.call(void 0, v.resourceKey)];
|
|
340
|
-
if (holder === void 0) {
|
|
341
|
-
throw new (0, _chunkQWAWNQEZcjs.AutotaskConfigError)(`aggregate: the client exposes no accessor for resource "${v.resourceKey}"`, {
|
|
342
|
-
operation: "operations.aggregate",
|
|
343
|
-
suggestedAction: "Rebuild the client from the SDK build that ships this registry (the resource set is pinned by the plan)."
|
|
344
|
-
});
|
|
345
|
-
}
|
|
346
|
-
const wireFilter = v.conditions.length === 0 ? void 0 : v.conditions;
|
|
347
|
-
if (v.groupBy.length === 0 && v.sum.length === 0) {
|
|
348
|
-
const raw = await holder.count({ filter: wireFilter });
|
|
349
|
-
const sentinel = typeof raw === "object" && raw !== null && "count" in raw ? raw : { count: raw };
|
|
350
|
-
const result2 = { mode: "count", count: sentinel.count, blind: sentinel.blindSurface !== void 0 };
|
|
351
|
-
if (sentinel.blindSurface !== void 0) result2.blindSurface = sentinel.blindSurface;
|
|
352
|
-
if (sentinel.emptyReason !== void 0) result2.emptyReason = sentinel.emptyReason;
|
|
353
|
-
return result2;
|
|
354
|
-
}
|
|
355
|
-
const res = await holder.queryBounded({ filter: wireFilter, limit: v.limit });
|
|
378
|
+
function foldGroups(items, v) {
|
|
356
379
|
const groups = /* @__PURE__ */ new Map();
|
|
357
|
-
for (const item of
|
|
380
|
+
for (const item of items) {
|
|
358
381
|
const key = {};
|
|
359
382
|
const values = [];
|
|
360
383
|
for (const spec of v.groupBy) {
|
|
@@ -374,7 +397,28 @@ async function aggregate(client, operation, filter, opts = {}) {
|
|
|
374
397
|
for (const f of v.sum) g.sums[f] = (_nullishCoalesce(g.sums[f], () => ( 0))) + num(item[f]);
|
|
375
398
|
}
|
|
376
399
|
}
|
|
377
|
-
|
|
400
|
+
return [...groups.values()].sort((a, b) => b.count - a.count || (a.keyOrder < b.keyOrder ? -1 : a.keyOrder > b.keyOrder ? 1 : 0));
|
|
401
|
+
}
|
|
402
|
+
async function aggregate(client, operation, filter, opts = {}) {
|
|
403
|
+
const v = validateAggregate(operation, filter, opts);
|
|
404
|
+
const holder = client[_chunkD5TVBI4Ucjs.camelKey.call(void 0, v.resourceKey)];
|
|
405
|
+
if (holder === void 0) {
|
|
406
|
+
throw new (0, _chunkD5TVBI4Ucjs.AutotaskConfigError)(`aggregate: the client exposes no accessor for resource "${v.resourceKey}"`, {
|
|
407
|
+
operation: "operations.aggregate",
|
|
408
|
+
suggestedAction: "Rebuild the client from the SDK build that ships this registry (the resource set is pinned by the plan)."
|
|
409
|
+
});
|
|
410
|
+
}
|
|
411
|
+
const wireFilter = v.conditions.length === 0 ? void 0 : v.conditions;
|
|
412
|
+
if (v.groupBy.length === 0 && v.sum.length === 0) {
|
|
413
|
+
const raw = await holder.count({ filter: wireFilter });
|
|
414
|
+
const sentinel = typeof raw === "object" && raw !== null && "count" in raw ? raw : { count: raw };
|
|
415
|
+
const result2 = { mode: "count", count: sentinel.count, blind: sentinel.blindSurface !== void 0 };
|
|
416
|
+
if (sentinel.blindSurface !== void 0) result2.blindSurface = sentinel.blindSurface;
|
|
417
|
+
if (sentinel.emptyReason !== void 0) result2.emptyReason = sentinel.emptyReason;
|
|
418
|
+
return result2;
|
|
419
|
+
}
|
|
420
|
+
const res = await holder.queryBounded({ filter: wireFilter, limit: v.limit });
|
|
421
|
+
const sorted = foldGroups(res.items, v);
|
|
378
422
|
const top = sorted.slice(0, v.top);
|
|
379
423
|
const result = {
|
|
380
424
|
mode: v.groupBy.length > 0 ? "group" : "sum",
|
|
@@ -393,20 +437,20 @@ async function aggregate(client, operation, filter, opts = {}) {
|
|
|
393
437
|
async function relationshipMap(client, resourceKey) {
|
|
394
438
|
void client;
|
|
395
439
|
if (typeof resourceKey !== "string" || resourceKey.trim() === "") {
|
|
396
|
-
throw new (0,
|
|
440
|
+
throw new (0, _chunkD5TVBI4Ucjs.AutotaskConfigError)(
|
|
397
441
|
`relationshipMap: resourceKey must be a non-empty plan resource key string (e.g. 'tickets'; got ${typeof resourceKey === "string" ? "a blank string" : typeof resourceKey})`,
|
|
398
442
|
{ suggestedAction: "Pass the exact plan resource key (snake_case) from autotask_catalog \u2014 e.g. tickets, companies, configuration_items, ticket_notes." }
|
|
399
443
|
);
|
|
400
444
|
}
|
|
401
445
|
const key = resourceKey.trim();
|
|
402
|
-
const entry =
|
|
446
|
+
const entry = _chunkD5TVBI4Ucjs.RELATIONSHIP_MAP[key];
|
|
403
447
|
if (entry === void 0) {
|
|
404
|
-
throw new (0,
|
|
405
|
-
`relationshipMap: unknown resource "${key}" \u2014 the plan has ${Object.keys(
|
|
448
|
+
throw new (0, _chunkD5TVBI4Ucjs.AutotaskError)(
|
|
449
|
+
`relationshipMap: unknown resource "${key}" \u2014 the plan has ${Object.keys(_chunkD5TVBI4Ucjs.RELATIONSHIP_MAP).length} resources`,
|
|
406
450
|
{
|
|
407
451
|
code: "RESOURCE_UNKNOWN",
|
|
408
452
|
category: "validation",
|
|
409
|
-
suggestedAction: `Pass the exact plan resource key (snake_case) from autotask_catalog (e.g. tickets, companies, configuration_items). Zone facts served are ${
|
|
453
|
+
suggestedAction: `Pass the exact plan resource key (snake_case) from autotask_catalog (e.g. tickets, companies, configuration_items). Zone facts served are ${_chunkD5TVBI4Ucjs.RELATIONSHIP_ZONE.label} (${_chunkD5TVBI4Ucjs.RELATIONSHIP_ZONE.zone})-verified.`
|
|
410
454
|
}
|
|
411
455
|
);
|
|
412
456
|
}
|
|
@@ -423,24 +467,24 @@ var BLIND_SURFACE_KINDS = [
|
|
|
423
467
|
async function blindSurfaces(client, opts) {
|
|
424
468
|
void client;
|
|
425
469
|
if (opts !== void 0 && (typeof opts !== "object" || opts === null || Array.isArray(opts))) {
|
|
426
|
-
throw new (0,
|
|
470
|
+
throw new (0, _chunkD5TVBI4Ucjs.AutotaskConfigError)("blindSurfaces: opts must be an object { resource?: string, kind?: BlindSurfaceKind }");
|
|
427
471
|
}
|
|
428
|
-
const inv =
|
|
472
|
+
const inv = _chunkD5TVBI4Ucjs.BLIND_SURFACE_INVENTORY;
|
|
429
473
|
if (inv === null) {
|
|
430
|
-
throw new (0,
|
|
474
|
+
throw new (0, _chunkD5TVBI4Ucjs.AutotaskConfigError)("blindSurfaces: the reachability inventory is absent from the generated artifact \u2014 re-run the build");
|
|
431
475
|
}
|
|
432
476
|
let surfaces = inv.surfaces;
|
|
433
477
|
if (_optionalChain([opts, 'optionalAccess', _ => _.resource]) !== void 0) {
|
|
434
478
|
const key = typeof opts.resource === "string" ? opts.resource.trim() : "";
|
|
435
479
|
if (key === "") {
|
|
436
|
-
throw new (0,
|
|
480
|
+
throw new (0, _chunkD5TVBI4Ucjs.AutotaskConfigError)(
|
|
437
481
|
"blindSurfaces: opts.resource must be a non-empty plan resource key string (e.g. 'tickets')",
|
|
438
482
|
{ suggestedAction: "Pass the exact plan resource key (snake_case) from autotask_catalog \u2014 e.g. tickets, companies, configuration_items." }
|
|
439
483
|
);
|
|
440
484
|
}
|
|
441
485
|
if (!inv.surfaces.some((row) => row.resource === key)) {
|
|
442
|
-
throw new (0,
|
|
443
|
-
`blindSurfaces: unknown resource "${key}" \u2014 the plan has ${Object.keys(
|
|
486
|
+
throw new (0, _chunkD5TVBI4Ucjs.AutotaskError)(
|
|
487
|
+
`blindSurfaces: unknown resource "${key}" \u2014 the plan has ${Object.keys(_chunkD5TVBI4Ucjs.RELATIONSHIP_MAP).length} resources`,
|
|
444
488
|
{
|
|
445
489
|
code: "RESOURCE_UNKNOWN",
|
|
446
490
|
category: "validation",
|
|
@@ -452,7 +496,7 @@ async function blindSurfaces(client, opts) {
|
|
|
452
496
|
}
|
|
453
497
|
if (_optionalChain([opts, 'optionalAccess', _2 => _2.kind]) !== void 0) {
|
|
454
498
|
if (!BLIND_SURFACE_KINDS.includes(opts.kind)) {
|
|
455
|
-
throw new (0,
|
|
499
|
+
throw new (0, _chunkD5TVBI4Ucjs.AutotaskConfigError)(
|
|
456
500
|
`blindSurfaces: unknown kind "${String(opts.kind)}" \u2014 the valid classes are: ${BLIND_SURFACE_KINDS.join(", ")}`,
|
|
457
501
|
{ suggestedAction: `Filter with one of: ${BLIND_SURFACE_KINDS.join(", ")} (or omit kind for the full 116-surface inventory).` }
|
|
458
502
|
);
|
|
@@ -465,51 +509,51 @@ async function blindSurfaces(client, opts) {
|
|
|
465
509
|
// src/operations/probeReachability.ts
|
|
466
510
|
async function probeReachability(client, opts) {
|
|
467
511
|
if (opts !== void 0 && (typeof opts !== "object" || opts === null || Array.isArray(opts))) {
|
|
468
|
-
throw new (0,
|
|
512
|
+
throw new (0, _chunkD5TVBI4Ucjs.AutotaskConfigError)("probeReachability: opts must be an object { resources?: string[], limit?: 1|2, maxWireCalls?: number, confirmProbe?: true }");
|
|
469
513
|
}
|
|
470
|
-
const defs =
|
|
514
|
+
const defs = _chunkD5TVBI4Ucjs.REACHABILITY_PROBE_DEFAULTS;
|
|
471
515
|
if (_optionalChain([opts, 'optionalAccess', _3 => _3.confirmProbe]) !== true) {
|
|
472
|
-
throw new (0,
|
|
516
|
+
throw new (0, _chunkD5TVBI4Ucjs.AutotaskConfigError)(
|
|
473
517
|
"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",
|
|
474
518
|
{ suggestedAction: `Re-call with { confirmProbe: true } (plus resources/limit/maxWireCalls as needed). For the ZERO-wire pinned inventory use operations.blindSurfaces.` }
|
|
475
519
|
);
|
|
476
520
|
}
|
|
477
521
|
const limit = _nullishCoalesce(_optionalChain([opts, 'optionalAccess', _4 => _4.limit]), () => ( defs.limitDefault));
|
|
478
522
|
if (!Number.isInteger(limit) || limit < 1 || limit > defs.limitMax) {
|
|
479
|
-
throw new (0,
|
|
523
|
+
throw new (0, _chunkD5TVBI4Ucjs.AutotaskConfigError)(
|
|
480
524
|
`probeReachability: limit must be an integer 1..${defs.limitMax} (got ${String(limit)}) \u2014 the rows-per-surface bound for the discovery read`
|
|
481
525
|
);
|
|
482
526
|
}
|
|
483
527
|
const cap = _nullishCoalesce(_optionalChain([opts, 'optionalAccess', _5 => _5.maxWireCalls]), () => ( defs.defaultCap));
|
|
484
528
|
if (!Number.isInteger(cap) || cap < 1) {
|
|
485
|
-
throw new (0,
|
|
529
|
+
throw new (0, _chunkD5TVBI4Ucjs.AutotaskConfigError)(`probeReachability: maxWireCalls must be a positive integer (got ${String(cap)})`);
|
|
486
530
|
}
|
|
487
531
|
if (cap > defs.hardCap) {
|
|
488
|
-
throw new (0,
|
|
532
|
+
throw new (0, _chunkD5TVBI4Ucjs.AutotaskConfigError)(
|
|
489
533
|
`probeReachability: maxWireCalls ${cap} exceeds the hard wire cap of ${defs.hardCap} \u2014 the sweep is refused above it (never capped silently)`,
|
|
490
534
|
{ suggestedAction: `Pass maxWireCalls \u2264 ${defs.hardCap} and a resources set no larger than the cap (the refused set is never truncated).` }
|
|
491
535
|
);
|
|
492
536
|
}
|
|
493
|
-
const inv =
|
|
537
|
+
const inv = _chunkD5TVBI4Ucjs.BLIND_SURFACE_INVENTORY;
|
|
494
538
|
if (inv === null) {
|
|
495
|
-
throw new (0,
|
|
539
|
+
throw new (0, _chunkD5TVBI4Ucjs.AutotaskConfigError)("probeReachability: the reachability inventory is absent from the generated artifact \u2014 re-run the build");
|
|
496
540
|
}
|
|
497
541
|
let targets;
|
|
498
542
|
if (_optionalChain([opts, 'optionalAccess', _6 => _6.resources]) === void 0) {
|
|
499
543
|
targets = [...defs.defaultTargets];
|
|
500
544
|
} else {
|
|
501
545
|
if (!Array.isArray(opts.resources) || opts.resources.length === 0) {
|
|
502
|
-
throw new (0,
|
|
546
|
+
throw new (0, _chunkD5TVBI4Ucjs.AutotaskConfigError)("probeReachability: opts.resources must be a non-empty string[] of plan resource keys (or omit it for the default non-data-full set)");
|
|
503
547
|
}
|
|
504
548
|
const seen = /* @__PURE__ */ new Set();
|
|
505
549
|
for (const r of opts.resources) {
|
|
506
550
|
if (typeof r !== "string" || r.trim() === "") {
|
|
507
|
-
throw new (0,
|
|
551
|
+
throw new (0, _chunkD5TVBI4Ucjs.AutotaskConfigError)(`probeReachability: opts.resources must contain non-empty plan resource key strings (got ${typeof r === "string" && r.trim() === "" ? "a blank string" : typeof r})`);
|
|
508
552
|
}
|
|
509
553
|
const key = r.trim();
|
|
510
554
|
if (!inv.surfaces.some((row) => row.resource === key)) {
|
|
511
555
|
const surfaceCount = new Set(inv.surfaces.map((s) => s.resource)).size;
|
|
512
|
-
throw new (0,
|
|
556
|
+
throw new (0, _chunkD5TVBI4Ucjs.AutotaskError)(
|
|
513
557
|
`probeReachability: unknown resource "${key}" \u2014 the inventory has ${surfaceCount} surfaces`,
|
|
514
558
|
{
|
|
515
559
|
code: "RESOURCE_UNKNOWN",
|
|
@@ -523,7 +567,7 @@ async function probeReachability(client, opts) {
|
|
|
523
567
|
targets = [...seen];
|
|
524
568
|
}
|
|
525
569
|
if (targets.length > cap) {
|
|
526
|
-
throw new (0,
|
|
570
|
+
throw new (0, _chunkD5TVBI4Ucjs.AutotaskConfigError)(
|
|
527
571
|
`probeReachability: ${targets.length} requested surface(s) exceed the wire cap of ${cap} \u2014 the sweep is refused above its cap (never truncated)`,
|
|
528
572
|
{ suggestedAction: `Raise maxWireCalls (\u2264 ${defs.hardCap}) to cover the set, or pass a smaller resources list.` }
|
|
529
573
|
);
|
|
@@ -533,7 +577,7 @@ async function probeReachability(client, opts) {
|
|
|
533
577
|
for (const resource of targets.sort()) {
|
|
534
578
|
const row = byResource.get(resource);
|
|
535
579
|
if (row === void 0) continue;
|
|
536
|
-
const holder = client[
|
|
580
|
+
const holder = client[_chunkD5TVBI4Ucjs.camelKey.call(void 0, resource)];
|
|
537
581
|
const probeFn = _optionalChain([holder, 'optionalAccess', _7 => _7.queryBounded]);
|
|
538
582
|
if (typeof probeFn !== "function") {
|
|
539
583
|
results.push({
|
|
@@ -552,7 +596,7 @@ async function probeReachability(client, opts) {
|
|
|
552
596
|
probe: { ok: true, wire: 1, error: null }
|
|
553
597
|
});
|
|
554
598
|
} catch (err) {
|
|
555
|
-
const code =
|
|
599
|
+
const code = _chunkD5TVBI4Ucjs.isAutotaskError.call(void 0, err) ? err.code : "NETWORK_ERROR";
|
|
556
600
|
const message = err instanceof Error ? err.message : String(err);
|
|
557
601
|
results.push({
|
|
558
602
|
...row,
|
|
@@ -580,24 +624,24 @@ var CREATE_BLOCKER_KINDS = [
|
|
|
580
624
|
async function createGuidance(client, opts) {
|
|
581
625
|
void client;
|
|
582
626
|
if (opts !== void 0 && (typeof opts !== "object" || opts === null || Array.isArray(opts))) {
|
|
583
|
-
throw new (0,
|
|
627
|
+
throw new (0, _chunkD5TVBI4Ucjs.AutotaskConfigError)(
|
|
584
628
|
"createGuidance: opts must be an object { resources?: string[], kind?: CreateBlockerKind }"
|
|
585
629
|
);
|
|
586
630
|
}
|
|
587
|
-
let rows =
|
|
631
|
+
let rows = _chunkD5TVBI4Ucjs.CREATE_GUIDANCE.rows;
|
|
588
632
|
if (_optionalChain([opts, 'optionalAccess', _9 => _9.resources]) !== void 0) {
|
|
589
633
|
if (!Array.isArray(opts.resources) || opts.resources.length === 0) {
|
|
590
|
-
throw new (0,
|
|
634
|
+
throw new (0, _chunkD5TVBI4Ucjs.AutotaskConfigError)("createGuidance: opts.resources must be a non-empty string[] of plan resource keys");
|
|
591
635
|
}
|
|
592
636
|
const wanted = /* @__PURE__ */ new Set();
|
|
593
637
|
for (const r of opts.resources) {
|
|
594
638
|
if (typeof r !== "string" || r.trim() === "") {
|
|
595
|
-
throw new (0,
|
|
639
|
+
throw new (0, _chunkD5TVBI4Ucjs.AutotaskConfigError)("createGuidance: opts.resources must contain non-empty plan resource key strings");
|
|
596
640
|
}
|
|
597
641
|
const key = r.trim();
|
|
598
|
-
if (!
|
|
599
|
-
throw new (0,
|
|
600
|
-
`createGuidance: unknown resource "${key}" \u2014 the catalog has ${
|
|
642
|
+
if (!_chunkD5TVBI4Ucjs.CREATE_GUIDANCE.rows.some((row) => row.resource === key)) {
|
|
643
|
+
throw new (0, _chunkD5TVBI4Ucjs.AutotaskError)(
|
|
644
|
+
`createGuidance: unknown resource "${key}" \u2014 the catalog has ${_chunkD5TVBI4Ucjs.CREATE_GUIDANCE.rows.length} create entities`,
|
|
601
645
|
{
|
|
602
646
|
code: "RESOURCE_UNKNOWN",
|
|
603
647
|
category: "validation",
|
|
@@ -611,18 +655,18 @@ async function createGuidance(client, opts) {
|
|
|
611
655
|
}
|
|
612
656
|
if (_optionalChain([opts, 'optionalAccess', _10 => _10.kind]) !== void 0) {
|
|
613
657
|
if (!CREATE_BLOCKER_KINDS.includes(opts.kind)) {
|
|
614
|
-
throw new (0,
|
|
658
|
+
throw new (0, _chunkD5TVBI4Ucjs.AutotaskConfigError)(
|
|
615
659
|
`createGuidance: unknown kind "${String(opts.kind)}" \u2014 the valid kinds are: ${CREATE_BLOCKER_KINDS.join(", ")}`
|
|
616
660
|
);
|
|
617
661
|
}
|
|
618
662
|
rows = rows.filter((row) => _optionalChain([row, 'access', _11 => _11.blocker, 'optionalAccess', _12 => _12.kind]) === opts.kind);
|
|
619
663
|
}
|
|
620
664
|
return {
|
|
621
|
-
zone:
|
|
622
|
-
label:
|
|
623
|
-
verifiedAt:
|
|
665
|
+
zone: _chunkD5TVBI4Ucjs.CREATE_GUIDANCE.zone,
|
|
666
|
+
label: _chunkD5TVBI4Ucjs.CREATE_GUIDANCE.label,
|
|
667
|
+
verifiedAt: _chunkD5TVBI4Ucjs.CREATE_GUIDANCE.verifiedAt,
|
|
624
668
|
rows,
|
|
625
|
-
counts:
|
|
669
|
+
counts: _chunkD5TVBI4Ucjs.CREATE_GUIDANCE.counts
|
|
626
670
|
};
|
|
627
671
|
}
|
|
628
672
|
|
|
@@ -631,7 +675,7 @@ var RECOVERY_CONFIRM = "operations.recovery";
|
|
|
631
675
|
var RECOVERY_DEFAULT_LIMIT = 25;
|
|
632
676
|
var RECOVERY_MAX_LIMIT = 100;
|
|
633
677
|
function configError(message, operation, suggestedAction) {
|
|
634
|
-
throw new (0,
|
|
678
|
+
throw new (0, _chunkD5TVBI4Ucjs.AutotaskConfigError)(message, { operation, suggestedAction });
|
|
635
679
|
}
|
|
636
680
|
function parseMatchId(record) {
|
|
637
681
|
const raw = record.id;
|
|
@@ -646,9 +690,8 @@ function parseMatchId(record) {
|
|
|
646
690
|
}
|
|
647
691
|
return { id: null, unsafe: true };
|
|
648
692
|
}
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
if (!_chunkQWAWNQEZcjs.isRecord.call(void 0, input)) {
|
|
693
|
+
function validateRecoveryInput(input, operation) {
|
|
694
|
+
if (!_chunkD5TVBI4Ucjs.isRecord.call(void 0, input)) {
|
|
652
695
|
configError(
|
|
653
696
|
`recovery: input must be an object { resource, marker, ... } (got ${typeof input})`,
|
|
654
697
|
operation,
|
|
@@ -679,10 +722,13 @@ async function recovery(client, input, opts = {}) {
|
|
|
679
722
|
"Pass action: 'delete' for the destructive path (dry-run-first; the apply requires the confirm string)."
|
|
680
723
|
);
|
|
681
724
|
}
|
|
682
|
-
|
|
725
|
+
return { resource, marker, action };
|
|
726
|
+
}
|
|
727
|
+
function resolveRecoveryTarget(client, resource, operation) {
|
|
728
|
+
const entry = _chunkD5TVBI4Ucjs.RELATIONSHIP_MAP[resource];
|
|
683
729
|
if (entry === void 0) {
|
|
684
|
-
throw new (0,
|
|
685
|
-
`recovery: unknown resource "${resource}" \u2014 the plan has ${Object.keys(
|
|
730
|
+
throw new (0, _chunkD5TVBI4Ucjs.AutotaskError)(
|
|
731
|
+
`recovery: unknown resource "${resource}" \u2014 the plan has ${Object.keys(_chunkD5TVBI4Ucjs.RELATIONSHIP_MAP).length} resources`,
|
|
686
732
|
{
|
|
687
733
|
code: "RESOURCE_UNKNOWN",
|
|
688
734
|
category: "validation",
|
|
@@ -691,7 +737,7 @@ async function recovery(client, input, opts = {}) {
|
|
|
691
737
|
}
|
|
692
738
|
);
|
|
693
739
|
}
|
|
694
|
-
const holder = client[
|
|
740
|
+
const holder = client[_chunkD5TVBI4Ucjs.camelKey.call(void 0, resource)];
|
|
695
741
|
if (!holder || typeof holder.queryBounded !== "function") {
|
|
696
742
|
configError(
|
|
697
743
|
`recovery: ${resource} exposes no bounded query surface \u2014 the marker search cannot run`,
|
|
@@ -699,7 +745,10 @@ async function recovery(client, input, opts = {}) {
|
|
|
699
745
|
"Use a resource with a query surface, or address the record by id directly (get/fetchMany)."
|
|
700
746
|
);
|
|
701
747
|
}
|
|
702
|
-
|
|
748
|
+
return { entry, holder };
|
|
749
|
+
}
|
|
750
|
+
function resolveMarkerField(input, resource, operation) {
|
|
751
|
+
const field = input.field !== void 0 ? String(input.field) : _chunkD5TVBI4Ucjs.MARKER_FIELDS[resource];
|
|
703
752
|
if (typeof field !== "string" || field.trim() === "") {
|
|
704
753
|
configError(
|
|
705
754
|
`recovery: ${resource} has no plan markerField and no input.field was passed \u2014 the marker search needs a name-like field to filter on`,
|
|
@@ -707,56 +756,127 @@ async function recovery(client, input, opts = {}) {
|
|
|
707
756
|
"Pass input.field \u2014 a name-like vendor field the marker was stamped into (see the resource model in autotask_describe / autotask_catalog)."
|
|
708
757
|
);
|
|
709
758
|
}
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
if (entry.parent === null || entry.parent.field === null) {
|
|
721
|
-
configError(
|
|
722
|
-
`recovery: ${resource} is not a parent-scoped child resource \u2014 input.parentId does not apply`,
|
|
723
|
-
operation,
|
|
724
|
-
`Drop input.parentId (the search runs unscoped), or pass the child resource that IS scoped under ${resource}.`
|
|
725
|
-
);
|
|
726
|
-
}
|
|
759
|
+
return field;
|
|
760
|
+
}
|
|
761
|
+
function resolveParentId(input, entry, resource, operation) {
|
|
762
|
+
if (input.parentId === void 0) return void 0;
|
|
763
|
+
if (!Number.isInteger(input.parentId) || input.parentId < 0) {
|
|
764
|
+
configError(
|
|
765
|
+
`recovery: input.parentId must be a non-negative integer (got ${String(input.parentId)})`,
|
|
766
|
+
operation,
|
|
767
|
+
"Pass the parent record id (e.g. the ticket id for a ticket note)."
|
|
768
|
+
);
|
|
727
769
|
}
|
|
770
|
+
if (entry.parent === null || entry.parent.field === null) {
|
|
771
|
+
configError(
|
|
772
|
+
`recovery: ${resource} is not a parent-scoped child resource \u2014 input.parentId does not apply`,
|
|
773
|
+
operation,
|
|
774
|
+
`Drop input.parentId (the search runs unscoped), or pass the child resource that IS scoped under ${resource}.`
|
|
775
|
+
);
|
|
776
|
+
}
|
|
777
|
+
return input.parentId;
|
|
778
|
+
}
|
|
779
|
+
function resolveExtraFilter(input, operation) {
|
|
728
780
|
const extra = [];
|
|
729
|
-
if (input.filter
|
|
730
|
-
|
|
781
|
+
if (input.filter === void 0) return extra;
|
|
782
|
+
if (!Array.isArray(input.filter)) {
|
|
783
|
+
configError(
|
|
784
|
+
`recovery: input.filter must be an array of leaf filter conditions (got ${typeof input.filter})`,
|
|
785
|
+
operation,
|
|
786
|
+
"Pass e.g. [{ field: 'status', op: 'eq', value: 'open' }] \u2014 leaf conditions only."
|
|
787
|
+
);
|
|
788
|
+
}
|
|
789
|
+
for (const c of input.filter) {
|
|
790
|
+
if (!_chunkD5TVBI4Ucjs.isRecord.call(void 0, c) || typeof c.op !== "string" || c.op === "and" || c.op === "or") {
|
|
731
791
|
configError(
|
|
732
|
-
|
|
792
|
+
"recovery: input.filter accepts only plain leaf conditions ({ field, op, value }) \u2014 no grouping",
|
|
733
793
|
operation,
|
|
734
|
-
"Pass
|
|
794
|
+
"Pass flat leaf conditions; grouping operators are not supported here."
|
|
735
795
|
);
|
|
736
796
|
}
|
|
737
|
-
|
|
738
|
-
if (!_chunkQWAWNQEZcjs.isRecord.call(void 0, c) || typeof c.op !== "string" || c.op === "and" || c.op === "or") {
|
|
739
|
-
configError(
|
|
740
|
-
"recovery: input.filter accepts only plain leaf conditions ({ field, op, value }) \u2014 no grouping",
|
|
741
|
-
operation,
|
|
742
|
-
"Pass flat leaf conditions; grouping operators are not supported here."
|
|
743
|
-
);
|
|
744
|
-
}
|
|
745
|
-
extra.push(c);
|
|
746
|
-
}
|
|
797
|
+
extra.push(c);
|
|
747
798
|
}
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
799
|
+
return extra;
|
|
800
|
+
}
|
|
801
|
+
function resolveLimit(input, operation) {
|
|
802
|
+
if (input.limit === void 0) return RECOVERY_DEFAULT_LIMIT;
|
|
803
|
+
if (!Number.isInteger(input.limit) || input.limit < 1 || input.limit > RECOVERY_MAX_LIMIT) {
|
|
804
|
+
configError(
|
|
805
|
+
`recovery: input.limit must be an integer 1..${RECOVERY_MAX_LIMIT} (got ${String(input.limit)})`,
|
|
806
|
+
operation,
|
|
807
|
+
`Raise the marker precision instead of the cap, or pass limit up to ${RECOVERY_MAX_LIMIT}.`
|
|
808
|
+
);
|
|
809
|
+
}
|
|
810
|
+
return input.limit;
|
|
811
|
+
}
|
|
812
|
+
async function applyRecoveryDeletes(holder, matches, parentId, resource, operation) {
|
|
813
|
+
const deleteMethod = holder.delete;
|
|
814
|
+
if (deleteMethod === void 0) {
|
|
815
|
+
throw new (0, _chunkD5TVBI4Ucjs.DeleteBoundaryError)(
|
|
816
|
+
`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`,
|
|
817
|
+
{
|
|
753
818
|
operation,
|
|
754
|
-
|
|
755
|
-
|
|
819
|
+
suggestedAction: "Report the registry drift (plan says deletable, client exposes no delete) \u2014 or clean up via the Autotask UI.",
|
|
820
|
+
details: { resource }
|
|
821
|
+
}
|
|
822
|
+
);
|
|
823
|
+
}
|
|
824
|
+
const deleted = [];
|
|
825
|
+
for (const match of matches) {
|
|
826
|
+
const id = match.id;
|
|
827
|
+
let verify = "error";
|
|
828
|
+
let code;
|
|
829
|
+
try {
|
|
830
|
+
if (parentId !== void 0) {
|
|
831
|
+
await deleteMethod.call(holder, parentId, id, { dryRun: false });
|
|
832
|
+
} else {
|
|
833
|
+
await deleteMethod.call(holder, id, { dryRun: false });
|
|
834
|
+
}
|
|
835
|
+
try {
|
|
836
|
+
if (parentId !== void 0) {
|
|
837
|
+
await holder.get.call(holder, parentId, id);
|
|
838
|
+
verify = "still-present";
|
|
839
|
+
} else {
|
|
840
|
+
await holder.get.call(holder, id);
|
|
841
|
+
verify = "still-present";
|
|
842
|
+
}
|
|
843
|
+
} catch (err) {
|
|
844
|
+
if (err instanceof _chunkD5TVBI4Ucjs.NotFoundError) verify = "not-found";
|
|
845
|
+
else {
|
|
846
|
+
verify = "error";
|
|
847
|
+
code = _chunkD5TVBI4Ucjs.isAutotaskError.call(void 0, err) ? err.code : "SERVER_ERROR";
|
|
848
|
+
}
|
|
849
|
+
}
|
|
850
|
+
} catch (err) {
|
|
851
|
+
code = _chunkD5TVBI4Ucjs.isAutotaskError.call(void 0, err) ? err.code : "SERVER_ERROR";
|
|
756
852
|
}
|
|
757
|
-
|
|
853
|
+
deleted.push({ id, verified: verify === "not-found", code });
|
|
758
854
|
}
|
|
759
|
-
|
|
855
|
+
return deleted;
|
|
856
|
+
}
|
|
857
|
+
function collectMatches(items, field) {
|
|
858
|
+
const matches = [];
|
|
859
|
+
const unsafeIds = [];
|
|
860
|
+
items.forEach((record, idx) => {
|
|
861
|
+
const parsed = parseMatchId(record);
|
|
862
|
+
if (parsed.unsafe) unsafeIds.push(idx);
|
|
863
|
+
const value = record[field];
|
|
864
|
+
matches.push({
|
|
865
|
+
id: parsed.id,
|
|
866
|
+
value: typeof value === "string" || typeof value === "number" || typeof value === "boolean" ? value : null
|
|
867
|
+
});
|
|
868
|
+
});
|
|
869
|
+
return { matches, unsafeIds };
|
|
870
|
+
}
|
|
871
|
+
async function recovery(client, input, opts = {}) {
|
|
872
|
+
const operation = RECOVERY_CONFIRM;
|
|
873
|
+
const { resource, marker, action } = validateRecoveryInput(input, operation);
|
|
874
|
+
const { entry, holder } = resolveRecoveryTarget(client, resource, operation);
|
|
875
|
+
const field = resolveMarkerField(input, resource, operation);
|
|
876
|
+
const parentId = resolveParentId(input, entry, resource, operation);
|
|
877
|
+
const extra = resolveExtraFilter(input, operation);
|
|
878
|
+
const limit = resolveLimit(input, operation);
|
|
879
|
+
const boundaryNote = _chunkD5TVBI4Ucjs.DELETE_BOUNDARY_NOTES[resource];
|
|
760
880
|
const boundary = {
|
|
761
881
|
available: boundaryNote === void 0,
|
|
762
882
|
reason: _nullishCoalesce(boundaryNote, () => ( null)),
|
|
@@ -768,7 +888,7 @@ async function recovery(client, input, opts = {}) {
|
|
|
768
888
|
};
|
|
769
889
|
const isDelete = action === "delete";
|
|
770
890
|
if (isDelete && boundaryNote !== void 0) {
|
|
771
|
-
throw new (0,
|
|
891
|
+
throw new (0, _chunkD5TVBI4Ucjs.DeleteBoundaryError)(
|
|
772
892
|
`recovery: the vendor defines no DELETE for ${resource} \u2014 the delete cannot be issued through the API (zero wire was issued)`,
|
|
773
893
|
{
|
|
774
894
|
operation,
|
|
@@ -780,7 +900,7 @@ async function recovery(client, input, opts = {}) {
|
|
|
780
900
|
const dryRun = _optionalChain([opts, 'optionalAccess', _13 => _13.dryRun]) !== false;
|
|
781
901
|
const confirm = _nullishCoalesce(_optionalChain([opts, 'optionalAccess', _14 => _14.confirm]), () => ( input.confirm));
|
|
782
902
|
if (isDelete && !dryRun && confirm !== RECOVERY_CONFIRM) {
|
|
783
|
-
throw new (0,
|
|
903
|
+
throw new (0, _chunkD5TVBI4Ucjs.ConfirmationRequiredError)(
|
|
784
904
|
`recovery: action 'delete' apply is destructive and requires its confirmation flag: pass confirm: "${RECOVERY_CONFIRM}"`,
|
|
785
905
|
{
|
|
786
906
|
operation: RECOVERY_CONFIRM,
|
|
@@ -796,7 +916,7 @@ async function recovery(client, input, opts = {}) {
|
|
|
796
916
|
const query = await holder.queryBounded({ filter: conditions, limit });
|
|
797
917
|
if (query.hasMore) {
|
|
798
918
|
const wire = isDelete ? "DELETE wire" : "mutating wire";
|
|
799
|
-
throw new (0,
|
|
919
|
+
throw new (0, _chunkD5TVBI4Ucjs.RecoveryTruncatedError)(
|
|
800
920
|
`recovery: the marker search on ${resource} TRIPPED its match cap (${limit}) \u2014 more matches exist than were returned (zero ${wire} was issued)`,
|
|
801
921
|
{
|
|
802
922
|
operation,
|
|
@@ -805,17 +925,7 @@ async function recovery(client, input, opts = {}) {
|
|
|
805
925
|
}
|
|
806
926
|
);
|
|
807
927
|
}
|
|
808
|
-
const matches =
|
|
809
|
-
const unsafeIds = [];
|
|
810
|
-
query.items.forEach((record, idx) => {
|
|
811
|
-
const parsed = parseMatchId(record);
|
|
812
|
-
if (parsed.unsafe) unsafeIds.push(idx);
|
|
813
|
-
const value = record[field];
|
|
814
|
-
matches.push({
|
|
815
|
-
id: parsed.id,
|
|
816
|
-
value: typeof value === "string" || typeof value === "number" || typeof value === "boolean" ? value : null
|
|
817
|
-
});
|
|
818
|
-
});
|
|
928
|
+
const { matches, unsafeIds } = collectMatches(query.items, field);
|
|
819
929
|
const unsafeId = unsafeIds.length > 0;
|
|
820
930
|
const base = {
|
|
821
931
|
resource,
|
|
@@ -835,7 +945,7 @@ async function recovery(client, input, opts = {}) {
|
|
|
835
945
|
return { ...base, simulated: true, dryRun: true };
|
|
836
946
|
}
|
|
837
947
|
if (unsafeId) {
|
|
838
|
-
throw new (0,
|
|
948
|
+
throw new (0, _chunkD5TVBI4Ucjs.MarkerUnsafeIdError)(
|
|
839
949
|
`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)`,
|
|
840
950
|
{
|
|
841
951
|
operation,
|
|
@@ -844,59 +954,16 @@ async function recovery(client, input, opts = {}) {
|
|
|
844
954
|
}
|
|
845
955
|
);
|
|
846
956
|
}
|
|
847
|
-
const
|
|
848
|
-
if (deleteMethod === void 0) {
|
|
849
|
-
throw new (0, _chunkQWAWNQEZcjs.DeleteBoundaryError)(
|
|
850
|
-
`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`,
|
|
851
|
-
{
|
|
852
|
-
operation,
|
|
853
|
-
suggestedAction: "Report the registry drift (plan says deletable, client exposes no delete) \u2014 or clean up via the Autotask UI.",
|
|
854
|
-
details: { resource }
|
|
855
|
-
}
|
|
856
|
-
);
|
|
857
|
-
}
|
|
858
|
-
const deleted = [];
|
|
859
|
-
for (const match of matches) {
|
|
860
|
-
const id = match.id;
|
|
861
|
-
let verify = "error";
|
|
862
|
-
let code;
|
|
863
|
-
try {
|
|
864
|
-
if (parentId !== void 0) {
|
|
865
|
-
await deleteMethod.call(holder, parentId, id, { dryRun: false });
|
|
866
|
-
} else {
|
|
867
|
-
await deleteMethod.call(holder, id, { dryRun: false });
|
|
868
|
-
}
|
|
869
|
-
try {
|
|
870
|
-
if (parentId !== void 0) {
|
|
871
|
-
await holder.get.call(holder, parentId, id);
|
|
872
|
-
verify = "still-present";
|
|
873
|
-
} else {
|
|
874
|
-
await holder.get.call(holder, id);
|
|
875
|
-
verify = "still-present";
|
|
876
|
-
}
|
|
877
|
-
} catch (err) {
|
|
878
|
-
if (err instanceof _chunkQWAWNQEZcjs.NotFoundError) verify = "not-found";
|
|
879
|
-
else {
|
|
880
|
-
verify = "error";
|
|
881
|
-
code = _chunkQWAWNQEZcjs.isAutotaskError.call(void 0, err) ? err.code : "SERVER_ERROR";
|
|
882
|
-
}
|
|
883
|
-
}
|
|
884
|
-
} catch (err) {
|
|
885
|
-
code = _chunkQWAWNQEZcjs.isAutotaskError.call(void 0, err) ? err.code : "SERVER_ERROR";
|
|
886
|
-
}
|
|
887
|
-
deleted.push({ id, verified: verify === "not-found", code });
|
|
888
|
-
}
|
|
957
|
+
const deleted = await applyRecoveryDeletes(holder, matches, parentId, resource, operation);
|
|
889
958
|
return { ...base, deleted, dryRun: false };
|
|
890
959
|
}
|
|
891
960
|
|
|
892
|
-
// src/operations/invoke.ts
|
|
893
|
-
var RECORDS = _chunkCBUY3MKBcjs.CAPABILITIES;
|
|
894
|
-
var byId = new Map(RECORDS.map((r) => [r.id, r]));
|
|
961
|
+
// src/operations/invoke/modes.ts
|
|
895
962
|
function needsConfirmation(record) {
|
|
896
963
|
return record.effect === "destructive" || (_nullishCoalesce(record.flags, () => ( []))).includes("requiresApproval");
|
|
897
964
|
}
|
|
898
965
|
function refuse(message, operation, suggestedAction) {
|
|
899
|
-
throw new (0,
|
|
966
|
+
throw new (0, _chunkD5TVBI4Ucjs.ConfirmationRequiredError)(message, { operation, suggestedAction });
|
|
900
967
|
}
|
|
901
968
|
var MODE_BY_EFFECT = {
|
|
902
969
|
read: "read",
|
|
@@ -924,6 +991,8 @@ function crossModeRefusal(operation, effect, mode) {
|
|
|
924
991
|
const target = actual === "read" ? `Route it through the read mode (${MODE_SDK[actual]} / ${MODE_TOOL[actual]}).` : actual === "write" ? `Route it through the write mode (${MODE_SDK[actual]} / ${MODE_TOOL[actual]} \u2014 dry-run first).` : `Deletes have their own tool (${MODE_TOOL[actual]}) and require confirm: "${operation}".`;
|
|
925
992
|
return `invoke: "${operation}" is ${subject} (effect=${effect}) \u2014 refused on the ${mode} path (${MODE_TOOL[mode]} routes effect=${MODE_EFFECT[mode]} operations only). ${target}`;
|
|
926
993
|
}
|
|
994
|
+
|
|
995
|
+
// src/operations/invoke/validate.ts
|
|
927
996
|
function isSafeNonNegativeInteger(value) {
|
|
928
997
|
return typeof value === "number" && Number.isSafeInteger(value) && value >= 0;
|
|
929
998
|
}
|
|
@@ -940,7 +1009,7 @@ function looseTypeOk(type, value) {
|
|
|
940
1009
|
case "string[]":
|
|
941
1010
|
return Array.isArray(value) && value.every((v) => typeof v === "string");
|
|
942
1011
|
case "object":
|
|
943
|
-
return
|
|
1012
|
+
return _chunkD5TVBI4Ucjs.isRecord.call(void 0, value);
|
|
944
1013
|
default:
|
|
945
1014
|
return true;
|
|
946
1015
|
}
|
|
@@ -957,8 +1026,11 @@ function validateDispatchArgs(record, argsIn) {
|
|
|
957
1026
|
const schema = _nullishCoalesce(record.inputSchema, () => ( {}));
|
|
958
1027
|
const names = Object.keys(schema);
|
|
959
1028
|
if (args.length > names.length) {
|
|
960
|
-
|
|
961
|
-
|
|
1029
|
+
const bagName = names.find((n) => schema[n].properties);
|
|
1030
|
+
const surplus = args[names.length];
|
|
1031
|
+
const bagHint = bagName && surplus !== null && typeof surplus === "object" && !Array.isArray(surplus) ? ` \u2014 options go inside the single ${bagName} object` : "";
|
|
1032
|
+
throw new (0, _chunkD5TVBI4Ucjs.AutotaskConfigError)(
|
|
1033
|
+
`invoke: "${operation}" declares ${names.length} positional arg(s) (${declaredArgList(record)}) but ${args.length} were passed \u2014 extra args are refused${bagHint}`,
|
|
962
1034
|
{
|
|
963
1035
|
operation,
|
|
964
1036
|
suggestedAction: `Pass exactly the declared args in order (${declaredArgList(record)}); dryRun/confirm/lastModifiedDate travel through the invoke options, never the args.`
|
|
@@ -967,7 +1039,7 @@ function validateDispatchArgs(record, argsIn) {
|
|
|
967
1039
|
}
|
|
968
1040
|
const required = names.filter((n) => schema[n].required);
|
|
969
1041
|
if (args.length < required.length) {
|
|
970
|
-
throw new (0,
|
|
1042
|
+
throw new (0, _chunkD5TVBI4Ucjs.AutotaskConfigError)(
|
|
971
1043
|
`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)}`,
|
|
972
1044
|
{ operation }
|
|
973
1045
|
);
|
|
@@ -978,13 +1050,15 @@ function validateDispatchArgs(record, argsIn) {
|
|
|
978
1050
|
const name = names[i];
|
|
979
1051
|
const spec = schema[name];
|
|
980
1052
|
if (!looseTypeOk(spec.type, value)) {
|
|
981
|
-
throw new (0,
|
|
1053
|
+
throw new (0, _chunkD5TVBI4Ucjs.AutotaskConfigError)(
|
|
982
1054
|
`invoke: "${operation}" arg ${i + 1} is declared ${name}: ${spec.type} \u2014 the value has the wrong type (pass a ${spec.type} value)`,
|
|
983
1055
|
{ operation }
|
|
984
1056
|
);
|
|
985
1057
|
}
|
|
986
1058
|
}
|
|
987
1059
|
}
|
|
1060
|
+
|
|
1061
|
+
// src/operations/invoke/inputSets.ts
|
|
988
1062
|
var PARAMS_BAG_KEYS = {
|
|
989
1063
|
query: ["filter", "limit", "includeFields", "via", "latest", "noteChars", "fieldsPreset", "fieldCheck"],
|
|
990
1064
|
// No registry row DECLARES `queryAll` today (a plan decision: the raw walk is
|
|
@@ -1038,11 +1112,11 @@ function validateParamsBag(record, args) {
|
|
|
1038
1112
|
const valid = PARAMS_BAG_KEYS[record.operation];
|
|
1039
1113
|
if (valid === void 0) return;
|
|
1040
1114
|
const bag = _optionalChain([args, 'optionalAccess', _15 => _15[0]]);
|
|
1041
|
-
if (bag === void 0 || bag === null || !
|
|
1115
|
+
if (bag === void 0 || bag === null || !_chunkD5TVBI4Ucjs.isRecord.call(void 0, bag)) return;
|
|
1042
1116
|
const unknown = Object.keys(bag).filter((k) => !valid.includes(k));
|
|
1043
1117
|
if (unknown.length === 0) return;
|
|
1044
1118
|
const suggestions = unknown.map((k) => [k, suggestForKey(k, valid)]).filter((pair) => pair[1] !== null).map(([k, s]) => `"${k}" \u2192 "${s}"`);
|
|
1045
|
-
throw new (0,
|
|
1119
|
+
throw new (0, _chunkD5TVBI4Ucjs.AutotaskConfigError)(
|
|
1046
1120
|
`invoke: "${record.id}" params bag has unknown key(s) ${unknown.map((k) => `"${k}"`).join(", ")} \u2014 the bag is closed (valid keys: ${valid.join(", ")})`,
|
|
1047
1121
|
{
|
|
1048
1122
|
operation: record.id,
|
|
@@ -1050,123 +1124,13 @@ function validateParamsBag(record, args) {
|
|
|
1050
1124
|
}
|
|
1051
1125
|
);
|
|
1052
1126
|
}
|
|
1053
|
-
async function liveFieldNames(holder) {
|
|
1054
|
-
const reader = holder.getFieldInfo;
|
|
1055
|
-
if (typeof reader !== "function") return null;
|
|
1056
|
-
try {
|
|
1057
|
-
const rows = await reader.call(holder);
|
|
1058
|
-
if (!Array.isArray(rows)) return null;
|
|
1059
|
-
const names = [];
|
|
1060
|
-
for (const row of rows) {
|
|
1061
|
-
if (typeof row.name === "string") names.push(row.name);
|
|
1062
|
-
}
|
|
1063
|
-
return names.length > 0 ? names : null;
|
|
1064
|
-
} catch (err) {
|
|
1065
|
-
if (!_chunkQWAWNQEZcjs.isAutotaskError.call(void 0, err) || err.code === "ABORTED") throw err;
|
|
1066
|
-
return null;
|
|
1067
|
-
}
|
|
1068
|
-
}
|
|
1069
|
-
var UNKNOWN_NAME_LIST_CAP = 20;
|
|
1070
|
-
var UNKNOWN_NAME_DISPLAY_CHARS = 80;
|
|
1071
|
-
function formatUnknownNameList(names) {
|
|
1072
|
-
const listed = names.slice(0, UNKNOWN_NAME_LIST_CAP).map((n) => `"${n.length > UNKNOWN_NAME_DISPLAY_CHARS ? `${n.slice(0, UNKNOWN_NAME_DISPLAY_CHARS)}\u2026` : n}"`).join(", ");
|
|
1073
|
-
const more = names.length > UNKNOWN_NAME_LIST_CAP ? ` (and ${names.length - UNKNOWN_NAME_LIST_CAP} more)` : "";
|
|
1074
|
-
return `${listed}${more}`;
|
|
1075
|
-
}
|
|
1076
|
-
function collectFilterFieldNames(conditions) {
|
|
1077
|
-
const out = [];
|
|
1078
|
-
const walk = (conds) => {
|
|
1079
|
-
for (const cond of conds) {
|
|
1080
|
-
if (!_chunkQWAWNQEZcjs.isRecord.call(void 0, cond)) continue;
|
|
1081
|
-
if (cond.op === "and" || cond.op === "or") {
|
|
1082
|
-
if (Array.isArray(cond.items)) walk(cond.items);
|
|
1083
|
-
continue;
|
|
1084
|
-
}
|
|
1085
|
-
if (cond.udf === true) continue;
|
|
1086
|
-
if (typeof cond.field === "string" && cond.field.length > 0) out.push(cond.field);
|
|
1087
|
-
}
|
|
1088
|
-
};
|
|
1089
|
-
walk(conditions);
|
|
1090
|
-
return out;
|
|
1091
|
-
}
|
|
1092
|
-
async function validateQueryFieldNames(record, holder, args) {
|
|
1093
|
-
const bag = args[0];
|
|
1094
|
-
if (!_chunkQWAWNQEZcjs.isRecord.call(void 0, bag)) return;
|
|
1095
|
-
const fieldCheck = bag["fieldCheck"];
|
|
1096
|
-
if (fieldCheck !== void 0 && typeof fieldCheck !== "boolean") {
|
|
1097
|
-
throw new (0, _chunkQWAWNQEZcjs.AutotaskConfigError)(
|
|
1098
|
-
`invoke: "${record.id}" params bag fieldCheck must be a boolean (got ${typeof fieldCheck}) \u2014 the request was not issued`,
|
|
1099
|
-
{ operation: record.id, suggestedAction: "Pass fieldCheck: true (default) or fieldCheck: false (disable the field-name checks \u2014 includeFields AND filter condition names)." }
|
|
1100
|
-
);
|
|
1101
|
-
}
|
|
1102
|
-
const includeFields = bag["includeFields"];
|
|
1103
|
-
let includeNames;
|
|
1104
|
-
if (includeFields !== void 0) {
|
|
1105
|
-
let shapeOk = Array.isArray(includeFields);
|
|
1106
|
-
const names = [];
|
|
1107
|
-
if (shapeOk) {
|
|
1108
|
-
for (const entry of includeFields) {
|
|
1109
|
-
if (typeof entry !== "string" || entry.length === 0) {
|
|
1110
|
-
shapeOk = false;
|
|
1111
|
-
break;
|
|
1112
|
-
}
|
|
1113
|
-
names.push(entry);
|
|
1114
|
-
}
|
|
1115
|
-
}
|
|
1116
|
-
if (!shapeOk) {
|
|
1117
|
-
throw new (0, _chunkQWAWNQEZcjs.AutotaskConfigError)(
|
|
1118
|
-
`invoke: "${record.id}" params bag includeFields must be an array of non-empty field-name strings \u2014 the request was not issued`,
|
|
1119
|
-
{
|
|
1120
|
-
operation: record.id,
|
|
1121
|
-
suggestedAction: 'Pass includeFields as an array of exact vendor field names, e.g. ["id", "title"]; the live set is in operations.fieldCatalog.'
|
|
1122
|
-
}
|
|
1123
|
-
);
|
|
1124
|
-
}
|
|
1125
|
-
includeNames = names;
|
|
1126
|
-
}
|
|
1127
|
-
let filterNames;
|
|
1128
|
-
if (bag["filter"] !== void 0) {
|
|
1129
|
-
const conditions = _chunkQWAWNQEZcjs.normalizedConditions.call(void 0, bag["filter"]);
|
|
1130
|
-
filterNames = collectFilterFieldNames(_nullishCoalesce(conditions, () => ( [])));
|
|
1131
|
-
}
|
|
1132
|
-
if (fieldCheck === false) return;
|
|
1133
|
-
const hasInclude = includeNames !== void 0 && includeNames.length > 0;
|
|
1134
|
-
const hasFilter = filterNames !== void 0 && filterNames.length > 0;
|
|
1135
|
-
if (!hasInclude && !hasFilter) return;
|
|
1136
|
-
const live = await liveFieldNames(holder);
|
|
1137
|
-
let known;
|
|
1138
|
-
let liveOnlyExempt = [];
|
|
1139
|
-
if (live !== null) {
|
|
1140
|
-
known = live;
|
|
1141
|
-
} else {
|
|
1142
|
-
const vendored = _chunkQWAWNQEZcjs.MODEL_FIELD_SETS[record.resource];
|
|
1143
|
-
liveOnlyExempt = Array.isArray(_optionalChain([record, 'access', _16 => _16.metadata, 'optionalAccess', _17 => _17.liveOnlyFields])) ? record.metadata.liveOnlyFields : [];
|
|
1144
|
-
known = vendored === void 0 ? void 0 : [...vendored, ...liveOnlyExempt];
|
|
1145
|
-
}
|
|
1146
|
-
if (known === void 0) return;
|
|
1147
|
-
const authority = live !== null ? "the tenant's live entity field metadata" : liveOnlyExempt.length > 0 ? "the vendored spec (src/field-sets.ts) + the plan-pinned live-only fields (exempt from the vendored refusal)" : "the vendored spec (src/field-sets.ts)";
|
|
1148
|
-
const unknownInclude = hasInclude ? includeNames.filter((name) => !known.includes(name)) : [];
|
|
1149
|
-
const unknownFilter = hasFilter ? [...new Set(filterNames.filter((name) => !known.includes(name)))] : [];
|
|
1150
|
-
if (unknownInclude.length === 0 && unknownFilter.length === 0) return;
|
|
1151
|
-
const parts = [];
|
|
1152
|
-
if (unknownInclude.length > 0) parts.push(`includeFields has unknown field name(s) ${formatUnknownNameList(unknownInclude)}`);
|
|
1153
|
-
if (unknownFilter.length > 0) parts.push(`filter condition(s) carry unknown field name(s) ${formatUnknownNameList(unknownFilter)}`);
|
|
1154
|
-
const wireClause = record.operation === "count" ? "the count request was not issued" : "the query POST was not issued";
|
|
1155
|
-
throw new (0, _chunkQWAWNQEZcjs.AutotaskConfigError)(
|
|
1156
|
-
`invoke: "${record.id}" ${parts.join("; ")} against ${authority} \u2014 ${wireClause}`,
|
|
1157
|
-
{
|
|
1158
|
-
operation: record.id,
|
|
1159
|
-
suggestedAction: `Use exact vendor field names (operations.fieldCatalog lists the live set for the entity); pass fieldCheck: false to disable this name check. The authority here was ${authority}.`
|
|
1160
|
-
}
|
|
1161
|
-
);
|
|
1162
|
-
}
|
|
1163
1127
|
var INVOKE_OPTION_KEYS = ["dryRun", "confirm", "lastModifiedDate", "maxRetries", "mode"];
|
|
1164
1128
|
function validateInvokeOptions(opts, operation) {
|
|
1165
1129
|
if (opts === void 0 || opts === null) return;
|
|
1166
1130
|
const unknown = Object.keys(opts).filter((k) => !INVOKE_OPTION_KEYS.includes(k));
|
|
1167
1131
|
if (unknown.length === 0) return;
|
|
1168
1132
|
const suggestions = unknown.map((k) => [k, suggestForKey(k, ["dryRun", "confirm", "lastModifiedDate", "maxRetries"])]).filter((pair) => pair[1] !== null).map(([k, s]) => `"${k}" \u2192 "${s}"`);
|
|
1169
|
-
throw new (0,
|
|
1133
|
+
throw new (0, _chunkD5TVBI4Ucjs.AutotaskConfigError)(
|
|
1170
1134
|
`invoke: "${operation}" has unknown option key(s) ${unknown.map((k) => `"${k}"`).join(", ")} \u2014 the options set is closed (valid: dryRun, confirm, lastModifiedDate, maxRetries; "mode" is internal to the mode wrappers)`,
|
|
1171
1135
|
{
|
|
1172
1136
|
operation,
|
|
@@ -1179,7 +1143,7 @@ function unknownKeysRefusal(raw, validKeys, subject, operation) {
|
|
|
1179
1143
|
const unknown = Object.keys(raw).filter((k) => !validKeys.includes(k));
|
|
1180
1144
|
if (unknown.length === 0) return null;
|
|
1181
1145
|
const suggestions = unknown.map((k) => [k, suggestForKey(k, [...validKeys])]).filter((pair) => pair[1] !== null).map(([k, s]) => `"${k}" \u2192 "${s}"`);
|
|
1182
|
-
return new (0,
|
|
1146
|
+
return new (0, _chunkD5TVBI4Ucjs.AutotaskConfigError)(
|
|
1183
1147
|
`unknown ${subject} ${unknown.map((k) => `"${k}"`).join(", ")} \u2014 the ${subject} set is closed (valid keys: ${validKeys.join(", ")})`,
|
|
1184
1148
|
{
|
|
1185
1149
|
...operation !== void 0 ? { operation } : {},
|
|
@@ -1187,29 +1151,48 @@ function unknownKeysRefusal(raw, validKeys, subject, operation) {
|
|
|
1187
1151
|
}
|
|
1188
1152
|
);
|
|
1189
1153
|
}
|
|
1190
|
-
|
|
1191
|
-
|
|
1154
|
+
|
|
1155
|
+
// src/operations/invoke/registry.ts
|
|
1156
|
+
var RECORDS = _chunkJUO3URUIcjs.CAPABILITIES;
|
|
1157
|
+
var byId = new Map(RECORDS.map((r) => [r.id, r]));
|
|
1158
|
+
|
|
1159
|
+
// src/operations/invoke/dispatch.ts
|
|
1160
|
+
var INVOKE_MAX_INLINE_BYTES = 1024 * 1024;
|
|
1161
|
+
function bufferResult(buf) {
|
|
1162
|
+
if (buf.byteLength <= INVOKE_MAX_INLINE_BYTES) {
|
|
1163
|
+
return { encoding: "base64", byteLength: buf.byteLength, truncated: false, data: buf.toString("base64") };
|
|
1164
|
+
}
|
|
1165
|
+
return {
|
|
1166
|
+
encoding: "base64",
|
|
1167
|
+
byteLength: buf.byteLength,
|
|
1168
|
+
truncated: true,
|
|
1169
|
+
note: `Body exceeds the ${INVOKE_MAX_INLINE_BYTES}-byte inline limit and was not returned; call the resource's download method directly.`
|
|
1170
|
+
};
|
|
1171
|
+
}
|
|
1172
|
+
function resolveRecord(operation) {
|
|
1192
1173
|
const record = byId.get(operation);
|
|
1193
1174
|
if (record === void 0) {
|
|
1194
|
-
throw new (0,
|
|
1175
|
+
throw new (0, _chunkD5TVBI4Ucjs.AutotaskConfigError)(
|
|
1195
1176
|
`invoke: unknown operation "${operation}" \u2014 it is not in the capability registry`,
|
|
1196
1177
|
{ operation, suggestedAction: "List the registry (the ./capabilities subpath) for the exact operation key." }
|
|
1197
1178
|
);
|
|
1198
1179
|
}
|
|
1180
|
+
return record;
|
|
1181
|
+
}
|
|
1182
|
+
function governPreRequest(record, operation, opts) {
|
|
1199
1183
|
validateInvokeOptions(opts, operation);
|
|
1200
1184
|
const mode = opts.mode;
|
|
1201
1185
|
if (mode !== void 0 && MODE_BY_EFFECT[record.effect] !== mode) {
|
|
1202
|
-
throw new (0,
|
|
1186
|
+
throw new (0, _chunkD5TVBI4Ucjs.AutotaskConfigError)(crossModeRefusal(operation, record.effect, mode), { operation });
|
|
1203
1187
|
}
|
|
1204
1188
|
if (opts.dryRun !== void 0 && typeof opts.dryRun !== "boolean") {
|
|
1205
|
-
throw new (0,
|
|
1189
|
+
throw new (0, _chunkD5TVBI4Ucjs.AutotaskConfigError)(
|
|
1206
1190
|
`invoke: dryRun must be a boolean (got ${typeof opts.dryRun}) \u2014 "${operation}" was not issued`,
|
|
1207
1191
|
{ operation, suggestedAction: "Pass dryRun: true (simulate) or dryRun: false (apply) as a real boolean." }
|
|
1208
1192
|
);
|
|
1209
1193
|
}
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
throw new (0, _chunkQWAWNQEZcjs.AutotaskConfigError)(
|
|
1194
|
+
if (record.effect === "read" && opts.dryRun === true) {
|
|
1195
|
+
throw new (0, _chunkD5TVBI4Ucjs.AutotaskConfigError)(
|
|
1213
1196
|
`invoke: "${operation}" is a read \u2014 dryRun is not applicable (reads issue their request as-is)`,
|
|
1214
1197
|
{ operation }
|
|
1215
1198
|
);
|
|
@@ -1221,69 +1204,71 @@ async function invokeMode(client, operation, argsIn = [], opts = {}) {
|
|
|
1221
1204
|
"Pass confirm equal to the operation key to acknowledge the deliberate act."
|
|
1222
1205
|
);
|
|
1223
1206
|
}
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1207
|
+
}
|
|
1208
|
+
function operationsHolder(client) {
|
|
1209
|
+
return {
|
|
1210
|
+
resolveAny: (identifier, opts) => resolveAny(client, identifier, opts),
|
|
1211
|
+
searchAcrossResources: (query, opts) => searchAcrossResources(client, query, opts),
|
|
1212
|
+
fetchMany: (items, opts) => _chunkD5TVBI4Ucjs.fetchMany.call(void 0, client, items, opts),
|
|
1213
|
+
// Issue #62: the generic aggregate + the cheap count — the
|
|
1214
|
+
// groupBy/sum-absent mode is ONE vendor /query/count (the S12-C blind
|
|
1215
|
+
// sentinel rides through); the group/sum modes walk the named
|
|
1216
|
+
// <resource>.query op via the house bounded walk and fold client-side
|
|
1217
|
+
// (truncation honesty: hasMore/totalScanned — no silent partial sums).
|
|
1218
|
+
aggregate: (operation, filter, opts) => aggregate(client, operation, filter, opts),
|
|
1219
|
+
// Issue #59 PR-B: the bulk fetch by ids — query-first chunked `id in`
|
|
1220
|
+
// reads + the per-id `get` fallback (blind-surface-safe; per-item
|
|
1221
|
+
// typed outcomes reuse the fetchMany shapes).
|
|
1222
|
+
fetchByIds: (items, opts) => _chunkD5TVBI4Ucjs.fetchByIds.call(void 0, client, items, opts),
|
|
1223
|
+
// Issue #65: opt-in resource name expansion — per-id resources.get
|
|
1224
|
+
// reads ONLY (never an id-in query — the resources table can be blind
|
|
1225
|
+
// to count/query while per-id reads work); blind-marked rows for ids
|
|
1226
|
+
// the API user cannot resolve; the name cache (default-on).
|
|
1227
|
+
expandResourceNames: (ids, opts) => _chunkD5TVBI4Ucjs.expandResourceNames.call(void 0, client, ids, opts),
|
|
1228
|
+
relationshipMap: (resourceKey) => relationshipMap(client, resourceKey),
|
|
1229
|
+
// Issue #11: the served blind-surface inventory (zero wire) + the
|
|
1230
|
+
// bounded caller-opted reachability sweep (read-only, confirmProbe-
|
|
1231
|
+
// required — the op's own pre-request gates keep it deliberate).
|
|
1232
|
+
blindSurfaces: (opts) => blindSurfaces(client, opts),
|
|
1233
|
+
probeReachability: (opts) => probeReachability(client, opts),
|
|
1234
|
+
// Issue #12: the served zone-fact create-guidance catalog (zero wire).
|
|
1235
|
+
createGuidance: (opts) => createGuidance(client, opts),
|
|
1236
|
+
// Issue #202: ExecuteCommand deep links — pure, zero wire.
|
|
1237
|
+
uiLink: (input) => _chunkD5TVBI4Ucjs.uiLink.call(void 0, client, input),
|
|
1238
|
+
// Issue #31: the opt-in live field-metadata channel — N bounded
|
|
1239
|
+
// entityInformation GETs (the op's own cap refuses over-cap fan-outs
|
|
1240
|
+
// pre-request; per-resource failures are recorded on the row and
|
|
1241
|
+
// never abort the call).
|
|
1242
|
+
fieldCatalog: (opts) => _chunkD5TVBI4Ucjs.fieldCatalog.call(void 0, client, opts),
|
|
1243
|
+
// Issue #9: the one-call recovery/cleanup op — effect write in the
|
|
1244
|
+
// registry (the governor's dry-run-first applies to it); the op's own
|
|
1245
|
+
// confirm gate makes the destructive action deliberate (the governor
|
|
1246
|
+
// forwards the caller's confirm through the trailing bag below).
|
|
1247
|
+
recovery: (input, opts) => recovery(client, input, opts)
|
|
1248
|
+
};
|
|
1249
|
+
}
|
|
1250
|
+
function resolveHolder(client, record, operation) {
|
|
1251
|
+
const clientBag = client;
|
|
1252
|
+
let holder = clientBag[_chunkD5TVBI4Ucjs.camelKey.call(void 0, record.resource)];
|
|
1229
1253
|
if (typeof holder === "function") {
|
|
1230
|
-
holder = _nullishCoalesce(
|
|
1254
|
+
holder = _nullishCoalesce(clientBag[`${_chunkD5TVBI4Ucjs.camelKey.call(void 0, record.resource)}Resource`], () => ( holder));
|
|
1231
1255
|
}
|
|
1232
1256
|
if (holder === void 0 && record.resource === "operations") {
|
|
1233
|
-
holder =
|
|
1234
|
-
resolveAny: (identifier, opts2) => resolveAny(client, identifier, opts2),
|
|
1235
|
-
searchAcrossResources: (query, opts2) => searchAcrossResources(client, query, opts2),
|
|
1236
|
-
fetchMany: (items, opts2) => _chunkQWAWNQEZcjs.fetchMany.call(void 0, client, items, opts2),
|
|
1237
|
-
// Issue #62: the generic aggregate + the cheap count — the
|
|
1238
|
-
// groupBy/sum-absent mode is ONE vendor /query/count (the S12-C blind
|
|
1239
|
-
// sentinel rides through); the group/sum modes walk the named
|
|
1240
|
-
// <resource>.query op via the house bounded walk and fold client-side
|
|
1241
|
-
// (truncation honesty: hasMore/totalScanned — no silent partial sums).
|
|
1242
|
-
aggregate: (operation2, filter, opts2) => aggregate(client, operation2, filter, opts2),
|
|
1243
|
-
// Issue #59 PR-B: the bulk fetch by ids — query-first chunked `id in`
|
|
1244
|
-
// reads + the per-id `get` fallback (blind-surface-safe; per-item
|
|
1245
|
-
// typed outcomes reuse the fetchMany shapes).
|
|
1246
|
-
fetchByIds: (items, opts2) => _chunkQWAWNQEZcjs.fetchByIds.call(void 0, client, items, opts2),
|
|
1247
|
-
// Issue #65: opt-in resource name expansion — per-id resources.get
|
|
1248
|
-
// reads ONLY (never an id-in query — the resources table can be blind
|
|
1249
|
-
// to count/query while per-id reads work); blind-marked rows for ids
|
|
1250
|
-
// the API user cannot resolve; the name cache (default-on).
|
|
1251
|
-
expandResourceNames: (ids, opts2) => _chunkQWAWNQEZcjs.expandResourceNames.call(void 0, client, ids, opts2),
|
|
1252
|
-
relationshipMap: (resourceKey) => relationshipMap(client, resourceKey),
|
|
1253
|
-
// Issue #11: the served blind-surface inventory (zero wire) + the
|
|
1254
|
-
// bounded caller-opted reachability sweep (read-only, confirmProbe-
|
|
1255
|
-
// required — the op's own pre-request gates keep it deliberate).
|
|
1256
|
-
blindSurfaces: (opts2) => blindSurfaces(client, opts2),
|
|
1257
|
-
probeReachability: (opts2) => probeReachability(client, opts2),
|
|
1258
|
-
// Issue #12: the served zone-fact create-guidance catalog (zero wire).
|
|
1259
|
-
createGuidance: (opts2) => createGuidance(client, opts2),
|
|
1260
|
-
// Issue #31: the opt-in live field-metadata channel — N bounded
|
|
1261
|
-
// entityInformation GETs (the op's own cap refuses over-cap fan-outs
|
|
1262
|
-
// pre-request; per-resource failures are recorded on the row and
|
|
1263
|
-
// never abort the call).
|
|
1264
|
-
fieldCatalog: (opts2) => _chunkQWAWNQEZcjs.fieldCatalog.call(void 0, client, opts2),
|
|
1265
|
-
// Issue #9: the one-call recovery/cleanup op — effect write in the
|
|
1266
|
-
// registry (the governor's dry-run-first applies to it); the op's own
|
|
1267
|
-
// confirm gate makes the destructive action deliberate (the governor
|
|
1268
|
-
// forwards the caller's confirm through the trailing bag below).
|
|
1269
|
-
recovery: (input, opts2) => recovery(client, input, opts2)
|
|
1270
|
-
};
|
|
1257
|
+
holder = operationsHolder(client);
|
|
1271
1258
|
}
|
|
1272
1259
|
if (holder === void 0) {
|
|
1273
|
-
throw new (0,
|
|
1260
|
+
throw new (0, _chunkD5TVBI4Ucjs.AutotaskConfigError)(
|
|
1274
1261
|
`invoke: the client exposes no accessor for resource "${record.resource}"`,
|
|
1275
1262
|
{ operation }
|
|
1276
1263
|
);
|
|
1277
1264
|
}
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
);
|
|
1286
|
-
}
|
|
1265
|
+
return holder;
|
|
1266
|
+
}
|
|
1267
|
+
var BAG_RIDING_ARGS = {
|
|
1268
|
+
createIfNotExists: ["dedupFields"],
|
|
1269
|
+
moveConfigurationItem: ["destinationCompanyId"]
|
|
1270
|
+
};
|
|
1271
|
+
function buildMutationOpts(opts, isWrite) {
|
|
1287
1272
|
const dryRun = isWrite ? opts.dryRun !== false : false;
|
|
1288
1273
|
const mutationOpts = { dryRun };
|
|
1289
1274
|
if (isWrite && opts.lastModifiedDate !== void 0) {
|
|
@@ -1295,10 +1280,9 @@ async function invokeMode(client, operation, argsIn = [], opts = {}) {
|
|
|
1295
1280
|
if (isWrite && opts.confirm !== void 0) {
|
|
1296
1281
|
mutationOpts.confirm = opts.confirm;
|
|
1297
1282
|
}
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
};
|
|
1283
|
+
return mutationOpts;
|
|
1284
|
+
}
|
|
1285
|
+
function buildCallArgs(record, args, mutationOpts, isWrite) {
|
|
1302
1286
|
const declaredNames = Object.keys(_nullishCoalesce(record.inputSchema, () => ( {})));
|
|
1303
1287
|
const bagRiding = new Set(_nullishCoalesce(BAG_RIDING_ARGS[record.operation], () => ( [])));
|
|
1304
1288
|
let positional = args;
|
|
@@ -1315,21 +1299,34 @@ async function invokeMode(client, operation, argsIn = [], opts = {}) {
|
|
|
1315
1299
|
while (callArgs.length < declaredPositional.length) callArgs.push(void 0);
|
|
1316
1300
|
callArgs.push(mutationOpts);
|
|
1317
1301
|
}
|
|
1318
|
-
|
|
1319
|
-
return Buffer.isBuffer(result) ? bufferResult(result) : result;
|
|
1302
|
+
return callArgs;
|
|
1320
1303
|
}
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1304
|
+
async function invokeMode(client, operation, argsIn = [], opts = {}) {
|
|
1305
|
+
const args = _nullishCoalesce(argsIn, () => ( []));
|
|
1306
|
+
const record = resolveRecord(operation);
|
|
1307
|
+
governPreRequest(record, operation, opts);
|
|
1308
|
+
validateDispatchArgs(record, args);
|
|
1309
|
+
validateParamsBag(record, args);
|
|
1310
|
+
const boundedQuery = record.kind === "primitive" && record.operation === "query";
|
|
1311
|
+
const countedQuery = record.kind === "primitive" && record.operation === "count";
|
|
1312
|
+
const holder = resolveHolder(client, record, operation);
|
|
1313
|
+
if (boundedQuery || countedQuery) await _chunkD5TVBI4Ucjs.validateQueryFieldNames.call(void 0, record, holder, args);
|
|
1314
|
+
const methodName = boundedQuery ? "queryBounded" : record.operation;
|
|
1315
|
+
const method = holder[methodName];
|
|
1316
|
+
if (typeof method !== "function") {
|
|
1317
|
+
throw new (0, _chunkD5TVBI4Ucjs.AutotaskConfigError)(
|
|
1318
|
+
`invoke: "${record.resource}.${methodName}" is not a callable method on the client`,
|
|
1319
|
+
{ operation }
|
|
1320
|
+
);
|
|
1325
1321
|
}
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
};
|
|
1322
|
+
const isWrite = record.effect !== "read";
|
|
1323
|
+
const mutationOpts = buildMutationOpts(opts, isWrite);
|
|
1324
|
+
const callArgs = buildCallArgs(record, args, mutationOpts, isWrite);
|
|
1325
|
+
const result = await method.apply(holder, callArgs);
|
|
1326
|
+
return Buffer.isBuffer(result) ? bufferResult(result) : result;
|
|
1332
1327
|
}
|
|
1328
|
+
|
|
1329
|
+
// src/operations/invoke/wrappers.ts
|
|
1333
1330
|
async function invoke(client, operation, args = [], opts = {}) {
|
|
1334
1331
|
return invokeMode(client, operation, args, { ...opts, mode: void 0 });
|
|
1335
1332
|
}
|
|
@@ -1386,4 +1383,7 @@ async function invokeDelete(client, operation, args = [], opts = {}) {
|
|
|
1386
1383
|
|
|
1387
1384
|
|
|
1388
1385
|
|
|
1389
|
-
|
|
1386
|
+
|
|
1387
|
+
|
|
1388
|
+
|
|
1389
|
+
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.EXPAND_RESOURCE_NAMES_MAX_IDS = _chunkD5TVBI4Ucjs.EXPAND_RESOURCE_NAMES_MAX_IDS; exports.FETCH_BY_IDS_CHUNK_SIZE = _chunkD5TVBI4Ucjs.FETCH_BY_IDS_CHUNK_SIZE; exports.FETCH_BY_IDS_MAX_ITEMS = _chunkD5TVBI4Ucjs.FETCH_BY_IDS_MAX_ITEMS; exports.FETCH_MANY_MAX_ITEMS = _chunkD5TVBI4Ucjs.FETCH_MANY_MAX_ITEMS; exports.FIELD_CACHE_KINDS = _chunkD5TVBI4Ucjs.FIELD_CACHE_KINDS; exports.FIELD_CATALOG_HONESTY_NOTE = _chunkD5TVBI4Ucjs.FIELD_CATALOG_HONESTY_NOTE; exports.INVOKE_OPTION_KEYS = INVOKE_OPTION_KEYS; exports.MAX_FIELD_CATALOG_WIRE = _chunkD5TVBI4Ucjs.MAX_FIELD_CATALOG_WIRE; exports.PARAMS_BAG_KEYS = PARAMS_BAG_KEYS; exports.PICKLIST_VALUE_NOT_SERVED_NOTE = _chunkD5TVBI4Ucjs.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 = _chunkD5TVBI4Ucjs.UI_LINK_ENTITIES; exports.WORKFLOW_RESOURCES = _chunkD5TVBI4Ucjs.WORKFLOW_RESOURCES; exports.aggregate = aggregate; exports.blindSurfaces = blindSurfaces; exports.buildUiLink = _chunkD5TVBI4Ucjs.buildUiLink; exports.createGuidance = createGuidance; exports.dateBucketLabel = dateBucketLabel; exports.expandResourceNames = _chunkD5TVBI4Ucjs.expandResourceNames; exports.fetchByIds = _chunkD5TVBI4Ucjs.fetchByIds; exports.fetchMany = _chunkD5TVBI4Ucjs.fetchMany; exports.fieldCatalog = _chunkD5TVBI4Ucjs.fieldCatalog; exports.invoke = invoke; exports.invokeDelete = invokeDelete; exports.invokeRead = invokeRead; exports.invokeWrite = invokeWrite; exports.needsConfirmation = needsConfirmation; exports.probeReachability = probeReachability; exports.recovery = recovery; exports.relationshipMap = relationshipMap; exports.resolveAny = resolveAny; exports.searchAcrossResources = searchAcrossResources; exports.uiLink = _chunkD5TVBI4Ucjs.uiLink; exports.unknownKeysRefusal = unknownKeysRefusal; exports.validateDispatchArgs = validateDispatchArgs; exports.validateFetchManyItems = _chunkD5TVBI4Ucjs.validateFetchManyItems; exports.validateInvokeOptions = validateInvokeOptions; exports.validateParamsBag = validateParamsBag;
|