node-autotask 0.39.1 → 0.39.3
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 +28 -0
- package/README.md +1 -1
- package/dist/{chunk-CQXB7KAO.js → chunk-5JAS6CAN.js} +2 -2
- package/dist/{chunk-LB34VFQY.cjs → chunk-BPRDYT5L.cjs} +47 -25
- package/dist/{chunk-GIVYTQ6R.cjs → chunk-F4YDKUGY.cjs} +283 -283
- package/dist/{chunk-LN3HQQBR.js → chunk-GSMFRPYB.js} +40 -18
- package/dist/{chunk-LDTJNLX7.js → chunk-K6RZDRWX.js} +1 -1
- package/dist/{chunk-73QNAEAF.cjs → chunk-MBI24PEF.cjs} +143 -143
- package/dist/{index-C-Oqef4y.d.cts → index-DkZVRMeW.d.cts} +18 -5
- package/dist/{index-C-Oqef4y.d.ts → index-DkZVRMeW.d.ts} +18 -5
- package/dist/index.cjs +21 -21
- package/dist/index.d.cts +4 -4
- package/dist/index.d.ts +4 -4
- package/dist/index.js +3 -3
- package/dist/operations/index.cjs +173 -173
- package/dist/operations/index.d.cts +2 -2
- package/dist/operations/index.d.ts +2 -2
- package/dist/operations/index.js +1 -1
- package/dist/pool.cjs +8 -8
- package/dist/pool.d.cts +1 -1
- package/dist/pool.d.ts +1 -1
- package/dist/pool.js +3 -3
- package/dist/resources/index.cjs +3 -3
- package/dist/resources/index.d.cts +1 -1
- package/dist/resources/index.d.ts +1 -1
- package/dist/resources/index.js +2 -2
- package/dist/types/index.d.cts +1 -1
- package/dist/types/index.d.ts +1 -1
- package/docs/API.md +16 -7
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,34 @@ All notable changes to this project are documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [Unreleased]
|
|
9
|
+
|
|
10
|
+
## [0.39.3] - 2026-10-30
|
|
11
|
+
|
|
12
|
+
Patch: standalone fixes (#263, #264, #265, #266, #306 part a). No capability-plan change.
|
|
13
|
+
|
|
14
|
+
### Fixed
|
|
15
|
+
- **#264:** `credentialShapeProblem` now reports an interior line feed (`'line feed'`), matching its "interior CR/LF always reported" doc; previously an LF-laden credential reached fetch and surfaced as an opaque `NETWORK_ERROR`.
|
|
16
|
+
- **#265:** `createIfNotExists` treats a dedup match with an all-digit string id (above 2^53) as existing, and the create dry-run `parent-exists` check accepts a string-id parent; both go through `parseIdentifier`.
|
|
17
|
+
- **#263:** a mutation sent with `idempotent: true` (for example `client.http.request`) now voids cached reads like any other write. `idempotent` governs retry only; the internal `/query`, `/query/count` and `/query/next` read POSTs still skip invalidation.
|
|
18
|
+
- **#306 (a):** the picklist-unavailable note now names the resource (`... unavailable for tickets.status (see reasons)`), matching the `<resource>.<field>` `reasons` keys; the `resolveCompositeNames` catch branch is covered by a test.
|
|
19
|
+
|
|
20
|
+
### Changed
|
|
21
|
+
- **#266 / #306 (a):** docs only. Pagination module headers now state that same-origin cursors are used and cross-origin cursors are refused with `ResponseRejectedError` (issue #54); the API.md note on id 0 is reworded as a node rule, not a vendor claim.
|
|
22
|
+
|
|
23
|
+
## [0.39.2] - 2026-10-30
|
|
24
|
+
|
|
25
|
+
Patch: follow-ups to the 0.39.0 / 0.39.1 label work (#302, #303, #304). The plan hash is unchanged (`9bb87de7...`); no capability-plan change, so the MCP server needs no re-pin.
|
|
26
|
+
|
|
27
|
+
### Fixed
|
|
28
|
+
- **#302: `fetchMany` / `fetchByIds` names merge.** `names.reasons` is keyed `<resource>.<field>` (`tickets.status`, `contracts.status`), so two resources sharing a field name no longer overwrite each other's reason. **Consumer-visible:** this applies to every `fetchMany` / `fetchByIds` result, including one whose items all name a single resource, so a reader of `names.reasons.status` now reads `names.reasons['tickets.status']`. Every failing resource's catalog error is kept in the new `names.catalogErrors` (keyed by resource); `names.catalogError` stays and is the first of them. The single-resource operations (`<resource>.query`, `aggregate`) are unchanged: `reasons` is still keyed by field.
|
|
29
|
+
- **#303: composite name paths no longer read a foreign-key id of 0.** The full-context composites (`tickets.fullContext`, `companies.fullProfile`, ...) planned a read for `contractID: 0` and the like; 0 is the vendor's "no reference", so the sibling is `null` with no read, as on the row path.
|
|
30
|
+
- **#304: a failed field-catalog read is no longer reported as "retrying will not help".** On the composite path (and on the row path when the second, field-filtered catalog read fails after the first succeeded) the picklist labels are `null` with `PICKLIST_CATALOG_UNAVAILABLE_NOTE` and the section / `names` carries `catalogError`. The "retrying will not help" honesty note (`FIELD_CATALOG_HONESTY_NOTE`) is now served only for a picklist the vendor does not serve. The pinned composite reasons moved accordingly (new optional `catalogError` on the composite `names` section).
|
|
31
|
+
|
|
32
|
+
### Changed
|
|
33
|
+
- **#303: 0.39.0 -> 0.39.1 behaviour note.** A value of 0 on a picklist whose values the vendor does not serve now gets a reason row (the honesty note); 0.39.0 gave none. A 0 on a picklist that IS served but does not define 0 still gets no reason row: the SDK treats a 0 absent from the picklist as "none". A defined 0 that the vendor hides from the API user therefore reads as `null` with no reason; the SDK cannot tell the two apart.
|
|
34
|
+
- **#303: `docs/API.md` §11.27 response-size figure** now uses the live measurement (31 siblings per row, 341,178 B -> 477,325 B, +40%) instead of "~50%, 19 siblings".
|
|
35
|
+
|
|
8
36
|
## [0.39.1] - Unreleased
|
|
9
37
|
|
|
10
38
|
Patch: label follow-ups from QA of #283. The plan hash is unchanged (`9bb87de7...`); only registry text in `capabilities.json` moved, so the MCP server needs no plan re-pin.
|
package/README.md
CHANGED
|
@@ -120,7 +120,7 @@ code `INVALID_CREDENTIAL_SHAPE`) **before any request is built**. The three cano
|
|
|
120
120
|
`AUTOTASK_API_INTEGRATION_CODE` and `AUTOTASK_USER` are read as fall-backs, canonical first.
|
|
121
121
|
|
|
122
122
|
**What the SDK refuses at construction.** `apiIntegrationCode`, `userName`, `secret` and
|
|
123
|
-
`impersonationResourceId` reject a value with a surrounding quote pair or an interior CR (and refuse
|
|
123
|
+
`impersonationResourceId` reject a value with a surrounding quote pair or an interior CR or LF (and refuse
|
|
124
124
|
whitespace-only blank values exactly as before); padding-only whitespace is still trimmed as it
|
|
125
125
|
always was. The same gate runs at the wire boundary, so a value that reaches the transport by any
|
|
126
126
|
other route is refused before the request is sent. Errors are value-free: they name the field and
|
|
@@ -125,7 +125,7 @@ import {
|
|
|
125
125
|
VersionInformationResource,
|
|
126
126
|
VersionResource,
|
|
127
127
|
ZoneInformationResource
|
|
128
|
-
} from "./chunk-
|
|
128
|
+
} from "./chunk-K6RZDRWX.js";
|
|
129
129
|
import {
|
|
130
130
|
AutotaskConfigError,
|
|
131
131
|
BillingCodesResource,
|
|
@@ -141,7 +141,7 @@ import {
|
|
|
141
141
|
TimeEntriesResource,
|
|
142
142
|
resolveConfig,
|
|
143
143
|
runWithSignal
|
|
144
|
-
} from "./chunk-
|
|
144
|
+
} from "./chunk-GSMFRPYB.js";
|
|
145
145
|
|
|
146
146
|
// src/client.ts
|
|
147
147
|
var AutotaskClient = class {
|
|
@@ -1095,6 +1095,7 @@ function credentialShapeProblem(value, options = {}) {
|
|
|
1095
1095
|
return "single- or double-quote surrounding the value";
|
|
1096
1096
|
}
|
|
1097
1097
|
if (value.includes("\r")) return "carriage return";
|
|
1098
|
+
if (value.includes("\n")) return "line feed";
|
|
1098
1099
|
return void 0;
|
|
1099
1100
|
}
|
|
1100
1101
|
var CREDENTIAL_ENV_LOAD_ACTION = "value appears shell-quoted or line-break contaminated \u2014 check how your env file was loaded (single-quoted values must be shell-sourced, not parsed by a quote-preserving loader)";
|
|
@@ -17469,7 +17470,7 @@ var HttpClient = class {
|
|
|
17469
17470
|
}
|
|
17470
17471
|
/** A real write (even a failed one — it may have partly applied) voids cached reads. */
|
|
17471
17472
|
invalidateAfterWrite(opts) {
|
|
17472
|
-
if (opts.method === "GET" || opts.idempotent === true) return;
|
|
17473
|
+
if (opts.method === "GET" || opts.idempotent === true && /\/query(\/|\?|$)/.test(opts.path)) return;
|
|
17473
17474
|
_optionalChain([this, 'access', _120 => _120.readCache, 'optionalAccess', _121 => _121.clear, 'call', _122 => _122()]);
|
|
17474
17475
|
this.latestCountCache.clear();
|
|
17475
17476
|
const nameOp = typeof opts.operation === "string" ? opts.operation : void 0;
|
|
@@ -20281,9 +20282,9 @@ var MutationBase = class extends MetaBase {
|
|
|
20281
20282
|
const first = matches[0];
|
|
20282
20283
|
if (first !== void 0) {
|
|
20283
20284
|
const firstId = first.id;
|
|
20284
|
-
if (
|
|
20285
|
+
if (isIdentifierCandidate(firstId)) {
|
|
20285
20286
|
existing = first;
|
|
20286
|
-
existingId = firstId;
|
|
20287
|
+
existingId = parseIdentifier(firstId, "id");
|
|
20287
20288
|
}
|
|
20288
20289
|
}
|
|
20289
20290
|
}
|
|
@@ -20382,9 +20383,13 @@ var MutationBase = class extends MetaBase {
|
|
|
20382
20383
|
);
|
|
20383
20384
|
}
|
|
20384
20385
|
let parent = null;
|
|
20385
|
-
if (
|
|
20386
|
+
if (isIdentifierCandidate(parentId)) {
|
|
20386
20387
|
try {
|
|
20387
|
-
parent = await this.fetchRecordRaw(
|
|
20388
|
+
parent = await this.fetchRecordRaw(
|
|
20389
|
+
parentPath,
|
|
20390
|
+
parseIdentifier(parentId, "parentId"),
|
|
20391
|
+
true
|
|
20392
|
+
);
|
|
20388
20393
|
} catch (err) {
|
|
20389
20394
|
if (!(err instanceof NotFoundError)) throw err;
|
|
20390
20395
|
}
|
|
@@ -20557,7 +20562,7 @@ function createNamePlan(labelFields = [], labelResource) {
|
|
|
20557
20562
|
...lineOfBusinessContractId !== void 0 ? { lineOfBusinessContractId } : {}
|
|
20558
20563
|
}),
|
|
20559
20564
|
addResource: (value) => {
|
|
20560
|
-
if (!isVendorId(value)) return;
|
|
20565
|
+
if (!isVendorId(value) || Number(value) === 0) return;
|
|
20561
20566
|
const k = String(value);
|
|
20562
20567
|
if (!resSeen.has(k)) {
|
|
20563
20568
|
resSeen.add(k);
|
|
@@ -20565,7 +20570,7 @@ function createNamePlan(labelFields = [], labelResource) {
|
|
|
20565
20570
|
}
|
|
20566
20571
|
},
|
|
20567
20572
|
addFk: (table, value) => {
|
|
20568
|
-
if (!isVendorId(value)) return;
|
|
20573
|
+
if (!isVendorId(value) || Number(value) === 0) return;
|
|
20569
20574
|
const k = `${table}:${String(value)}`;
|
|
20570
20575
|
if (!fkSeen.has(k)) {
|
|
20571
20576
|
fkSeen.add(k);
|
|
@@ -20787,23 +20792,30 @@ async function resolveCompositeNames(http, plan, opts = {}) {
|
|
|
20787
20792
|
const picklists = {};
|
|
20788
20793
|
if (plan.labelFields.length > 0) {
|
|
20789
20794
|
let usable = true;
|
|
20795
|
+
let failure;
|
|
20790
20796
|
try {
|
|
20791
20797
|
const labelResource = _nullishCoalesce(plan.labelResource, () => ( "tickets"));
|
|
20792
20798
|
const catalog = await fieldCatalog(client, { resources: [labelResource], labels: true, fields: [...plan.labelFields] });
|
|
20793
20799
|
const row = catalog.rows.find((r) => r.resource === labelResource);
|
|
20794
20800
|
if (row === void 0 || row.error !== null || row.fields === void 0) {
|
|
20795
20801
|
usable = false;
|
|
20802
|
+
failure = _nullishCoalesce(_optionalChain([row, 'optionalAccess', _197 => _197.error]), () => ( { code: "INVALID_RESPONSE", message: `fieldCatalog: no ${labelResource} row` }));
|
|
20796
20803
|
} else {
|
|
20797
20804
|
for (const f of plan.labelFields) {
|
|
20798
20805
|
const frow = row.fields.find((x) => x.name === f);
|
|
20799
|
-
picklists[f] = _optionalChain([frow, 'optionalAccess',
|
|
20806
|
+
picklists[f] = _optionalChain([frow, 'optionalAccess', _198 => _198.picklistValues]);
|
|
20800
20807
|
}
|
|
20801
20808
|
}
|
|
20802
20809
|
} catch (err) {
|
|
20803
|
-
if (isAutotaskError(err) && err.code !== "ABORTED")
|
|
20804
|
-
|
|
20810
|
+
if (isAutotaskError(err) && err.code !== "ABORTED") {
|
|
20811
|
+
usable = false;
|
|
20812
|
+
failure = { code: err.code, message: err.message };
|
|
20813
|
+
} else throw err;
|
|
20814
|
+
}
|
|
20815
|
+
if (!usable) {
|
|
20816
|
+
section.catalogError = failure;
|
|
20817
|
+
for (const f of plan.labelFields) section.reasons[f] = PICKLIST_CATALOG_UNAVAILABLE_NOTE;
|
|
20805
20818
|
}
|
|
20806
|
-
if (!usable) for (const f of plan.labelFields) section.reasons[f] = FIELD_CATALOG_HONESTY_NOTE;
|
|
20807
20819
|
}
|
|
20808
20820
|
let lineOfBusiness2 = null;
|
|
20809
20821
|
const lobId = _nullishCoalesce(plan.lineOfBusinessId, () => ( contractLobPointer));
|
|
@@ -20830,13 +20842,13 @@ async function resolveCompositeNames(http, plan, opts = {}) {
|
|
|
20830
20842
|
return {
|
|
20831
20843
|
section,
|
|
20832
20844
|
lineOfBusiness: lineOfBusiness2,
|
|
20833
|
-
resourceName: (id) => _nullishCoalesce(_optionalChain([section, 'access',
|
|
20834
|
-
recordName: (table, id) => _nullishCoalesce(_optionalChain([section, 'access',
|
|
20845
|
+
resourceName: (id) => _nullishCoalesce(_optionalChain([section, 'access', _199 => _199.rows, 'access', _200 => _200[`resource:${id}`], 'optionalAccess', _201 => _201.name]), () => ( null)),
|
|
20846
|
+
recordName: (table, id) => _nullishCoalesce(_optionalChain([section, 'access', _202 => _202.rows, 'access', _203 => _203[`${table}:${id}`], 'optionalAccess', _204 => _204.name]), () => ( null)),
|
|
20835
20847
|
labelFor: (field, value) => {
|
|
20836
20848
|
if (value === null || value === void 0) return null;
|
|
20837
20849
|
const values = picklists[field];
|
|
20838
20850
|
if (values === void 0) {
|
|
20839
|
-
section.reasons[field] = FIELD_CATALOG_HONESTY_NOTE;
|
|
20851
|
+
section.reasons[field] = section.catalogError !== void 0 ? PICKLIST_CATALOG_UNAVAILABLE_NOTE : FIELD_CATALOG_HONESTY_NOTE;
|
|
20840
20852
|
return null;
|
|
20841
20853
|
}
|
|
20842
20854
|
const hit = values.find((v) => String(v.value) === String(value));
|
|
@@ -20870,7 +20882,7 @@ function readNamesOpt(value, where) {
|
|
|
20870
20882
|
}
|
|
20871
20883
|
return value;
|
|
20872
20884
|
}
|
|
20873
|
-
async function labelRows(client, resourceKey, rows) {
|
|
20885
|
+
async function labelRows(client, resourceKey, rows, resourceKeyedReasons = false) {
|
|
20874
20886
|
const keys = /* @__PURE__ */ new Set();
|
|
20875
20887
|
for (const row of rows) for (const k of Object.keys(row)) keys.add(k);
|
|
20876
20888
|
if (keys.size === 0) return { rows: [...rows] };
|
|
@@ -20884,11 +20896,11 @@ async function labelRows(client, resourceKey, rows) {
|
|
|
20884
20896
|
const row = catalog.rows.find((r) => r.resource === resourceKey);
|
|
20885
20897
|
const known = _nullishCoalesce(lastPicklists.get(client), () => ( /* @__PURE__ */ new Map()));
|
|
20886
20898
|
lastPicklists.set(client, known);
|
|
20887
|
-
if (_optionalChain([row, 'optionalAccess',
|
|
20899
|
+
if (_optionalChain([row, 'optionalAccess', _205 => _205.fields]) === void 0) {
|
|
20888
20900
|
const last = known.get(resourceKey);
|
|
20889
20901
|
unavailable = (_nullishCoalesce(last, () => ( []))).filter((f) => candidates.includes(f));
|
|
20890
20902
|
if (last === void 0 || unavailable.length > 0) {
|
|
20891
|
-
catalogError = _nullishCoalesce(_optionalChain([row, 'optionalAccess',
|
|
20903
|
+
catalogError = _nullishCoalesce(_optionalChain([row, 'optionalAccess', _206 => _206.error]), () => ( { code: "INVALID_RESPONSE", message: `fieldCatalog: no ${resourceKey} row` }));
|
|
20892
20904
|
}
|
|
20893
20905
|
} else {
|
|
20894
20906
|
const all = row.fields.filter((f) => f.isPickList).map((f) => f.name);
|
|
@@ -20911,6 +20923,11 @@ async function labelRows(client, resourceKey, rows) {
|
|
|
20911
20923
|
}
|
|
20912
20924
|
const plan = builder.plan();
|
|
20913
20925
|
const names = plan.resourceIds.length === 0 && plan.recordFks.length === 0 && picklistFields.length === 0 ? void 0 : await resolveCompositeNames(client.http, plan);
|
|
20926
|
+
const secondReadFailed = _optionalChain([names, 'optionalAccess', _207 => _207.section, 'access', _208 => _208.catalogError]);
|
|
20927
|
+
if (secondReadFailed !== void 0) {
|
|
20928
|
+
catalogError ??= secondReadFailed;
|
|
20929
|
+
unavailable = [.../* @__PURE__ */ new Set([...unavailable, ...picklistFields])];
|
|
20930
|
+
}
|
|
20914
20931
|
const out = rows.map((row) => {
|
|
20915
20932
|
const r = { ...row };
|
|
20916
20933
|
for (const [field, value] of Object.entries(row)) {
|
|
@@ -20926,13 +20943,13 @@ async function labelRows(client, resourceKey, rows) {
|
|
|
20926
20943
|
return r;
|
|
20927
20944
|
});
|
|
20928
20945
|
const capped = names === void 0 ? 0 : Object.values(names.section.rows).filter((row) => row.capped).length;
|
|
20929
|
-
const unresolved = Object.keys(_nullishCoalesce(_optionalChain([names, 'optionalAccess',
|
|
20930
|
-
const reasons = { ..._optionalChain([names, 'optionalAccess',
|
|
20946
|
+
const unresolved = Object.keys(_nullishCoalesce(_optionalChain([names, 'optionalAccess', _209 => _209.section, 'access', _210 => _210.reasons]), () => ( {})));
|
|
20947
|
+
const reasons = { ..._optionalChain([names, 'optionalAccess', _211 => _211.section, 'access', _212 => _212.reasons]) };
|
|
20931
20948
|
for (const f of unavailable) reasons[f] = PICKLIST_CATALOG_UNAVAILABLE_NOTE;
|
|
20932
20949
|
if (capped === 0 && unresolved.length === 0 && catalogError === void 0) return { rows: out };
|
|
20933
20950
|
const parts = [];
|
|
20934
20951
|
if (capped > 0) parts.push(`${capped} id(s) left unlabelled (their *Name is null): the per-call cap of ${DEFAULT_MAX_NAME_READS} uncached name reads was hit \u2014 names already read are cached, so repeating or narrowing the call labels more`);
|
|
20935
|
-
if (unresolved.length > 0) parts.push(`picklist label(s) unavailable for ${unresolved.join(", ")} (see reasons)`);
|
|
20952
|
+
if (unresolved.length > 0) parts.push(`picklist label(s) unavailable for ${unresolved.map((f) => resourceKeyedReasons ? `${resourceKey}.${f}` : f).join(", ")} (see reasons)`);
|
|
20936
20953
|
if (catalogError !== void 0) {
|
|
20937
20954
|
parts.push(
|
|
20938
20955
|
`the ${resourceKey} field catalog read failed (${catalogError.code}), so picklist labels are unavailable for this call, not absent: ` + (unavailable.length > 0 ? `the *Label is null for ${unavailable.join(", ")}` : "no *Label sibling was added (the picklist fields are unknown until a catalog read succeeds)") + " \u2014 retry the call to label them"
|
|
@@ -20956,22 +20973,27 @@ async function labelFetchResults(client, result) {
|
|
|
20956
20973
|
});
|
|
20957
20974
|
const results = [...result.results];
|
|
20958
20975
|
const summaries = [];
|
|
20976
|
+
const reasons = {};
|
|
20977
|
+
const catalogErrors = {};
|
|
20959
20978
|
for (const [resource, indices] of byResource) {
|
|
20960
|
-
const labelled = await labelRows(client, resource, indices.map((i) => results[i].value));
|
|
20979
|
+
const labelled = await labelRows(client, resource, indices.map((i) => results[i].value), true);
|
|
20961
20980
|
indices.forEach((idx, j) => {
|
|
20962
20981
|
results[idx] = { ...results[idx], value: labelled.rows[j] };
|
|
20963
20982
|
});
|
|
20964
|
-
if (labelled.names !== void 0)
|
|
20983
|
+
if (labelled.names !== void 0) {
|
|
20984
|
+
summaries.push(labelled.names);
|
|
20985
|
+
for (const [field, why] of Object.entries(_nullishCoalesce(labelled.names.reasons, () => ( {})))) reasons[`${resource}.${field}`] = why;
|
|
20986
|
+
if (labelled.names.catalogError !== void 0) catalogErrors[resource] = labelled.names.catalogError;
|
|
20987
|
+
}
|
|
20965
20988
|
}
|
|
20966
20989
|
if (summaries.length === 0) return { ...result, results };
|
|
20967
|
-
const
|
|
20968
|
-
const catalogError = _optionalChain([summaries, 'access', _210 => _210.find, 'call', _211 => _211((s) => s.catalogError !== void 0), 'optionalAccess', _212 => _212.catalogError]);
|
|
20990
|
+
const catalogError = Object.values(catalogErrors)[0];
|
|
20969
20991
|
const names = {
|
|
20970
20992
|
truncated: summaries.some((s) => s.truncated),
|
|
20971
20993
|
capped: summaries.reduce((n, s) => n + s.capped, 0),
|
|
20972
20994
|
note: summaries.map((s) => s.note).join("; "),
|
|
20973
20995
|
...Object.keys(reasons).length > 0 ? { reasons } : {},
|
|
20974
|
-
...catalogError !== void 0 ? { catalogError } : {}
|
|
20996
|
+
...catalogError !== void 0 ? { catalogError, catalogErrors } : {}
|
|
20975
20997
|
};
|
|
20976
20998
|
return { ...result, results, names };
|
|
20977
20999
|
}
|