node-autotask 0.39.1 → 0.39.2
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 +13 -0
- package/dist/{chunk-LB34VFQY.cjs → chunk-5QS3VT34.cjs} +34 -17
- package/dist/{chunk-LDTJNLX7.js → chunk-GSGP2B4I.js} +1 -1
- package/dist/{chunk-GIVYTQ6R.cjs → chunk-HSBIVZGJ.cjs} +283 -283
- package/dist/{chunk-CQXB7KAO.js → chunk-I7IM342A.js} +2 -2
- package/dist/{chunk-73QNAEAF.cjs → chunk-N2JOGUGI.cjs} +143 -143
- package/dist/{chunk-LN3HQQBR.js → chunk-UNOQESFU.js} +27 -10
- package/dist/{index-C-Oqef4y.d.cts → index-BsyWsYWi.d.cts} +13 -2
- package/dist/{index-C-Oqef4y.d.ts → index-BsyWsYWi.d.ts} +13 -2
- package/dist/index.cjs +21 -21
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- 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 +14 -5
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,19 @@ 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
|
+
## [0.39.2] - 2026-10-30
|
|
9
|
+
|
|
10
|
+
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.
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
- **#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.
|
|
14
|
+
- **#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.
|
|
15
|
+
- **#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).
|
|
16
|
+
|
|
17
|
+
### Changed
|
|
18
|
+
- **#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.
|
|
19
|
+
- **#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".
|
|
20
|
+
|
|
8
21
|
## [0.39.1] - Unreleased
|
|
9
22
|
|
|
10
23
|
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.
|
|
@@ -20557,7 +20557,7 @@ function createNamePlan(labelFields = [], labelResource) {
|
|
|
20557
20557
|
...lineOfBusinessContractId !== void 0 ? { lineOfBusinessContractId } : {}
|
|
20558
20558
|
}),
|
|
20559
20559
|
addResource: (value) => {
|
|
20560
|
-
if (!isVendorId(value)) return;
|
|
20560
|
+
if (!isVendorId(value) || Number(value) === 0) return;
|
|
20561
20561
|
const k = String(value);
|
|
20562
20562
|
if (!resSeen.has(k)) {
|
|
20563
20563
|
resSeen.add(k);
|
|
@@ -20565,7 +20565,7 @@ function createNamePlan(labelFields = [], labelResource) {
|
|
|
20565
20565
|
}
|
|
20566
20566
|
},
|
|
20567
20567
|
addFk: (table, value) => {
|
|
20568
|
-
if (!isVendorId(value)) return;
|
|
20568
|
+
if (!isVendorId(value) || Number(value) === 0) return;
|
|
20569
20569
|
const k = `${table}:${String(value)}`;
|
|
20570
20570
|
if (!fkSeen.has(k)) {
|
|
20571
20571
|
fkSeen.add(k);
|
|
@@ -20787,23 +20787,30 @@ async function resolveCompositeNames(http, plan, opts = {}) {
|
|
|
20787
20787
|
const picklists = {};
|
|
20788
20788
|
if (plan.labelFields.length > 0) {
|
|
20789
20789
|
let usable = true;
|
|
20790
|
+
let failure;
|
|
20790
20791
|
try {
|
|
20791
20792
|
const labelResource = _nullishCoalesce(plan.labelResource, () => ( "tickets"));
|
|
20792
20793
|
const catalog = await fieldCatalog(client, { resources: [labelResource], labels: true, fields: [...plan.labelFields] });
|
|
20793
20794
|
const row = catalog.rows.find((r) => r.resource === labelResource);
|
|
20794
20795
|
if (row === void 0 || row.error !== null || row.fields === void 0) {
|
|
20795
20796
|
usable = false;
|
|
20797
|
+
failure = _nullishCoalesce(_optionalChain([row, 'optionalAccess', _197 => _197.error]), () => ( { code: "INVALID_RESPONSE", message: `fieldCatalog: no ${labelResource} row` }));
|
|
20796
20798
|
} else {
|
|
20797
20799
|
for (const f of plan.labelFields) {
|
|
20798
20800
|
const frow = row.fields.find((x) => x.name === f);
|
|
20799
|
-
picklists[f] = _optionalChain([frow, 'optionalAccess',
|
|
20801
|
+
picklists[f] = _optionalChain([frow, 'optionalAccess', _198 => _198.picklistValues]);
|
|
20800
20802
|
}
|
|
20801
20803
|
}
|
|
20802
20804
|
} catch (err) {
|
|
20803
|
-
if (isAutotaskError(err) && err.code !== "ABORTED")
|
|
20804
|
-
|
|
20805
|
+
if (isAutotaskError(err) && err.code !== "ABORTED") {
|
|
20806
|
+
usable = false;
|
|
20807
|
+
failure = { code: err.code, message: err.message };
|
|
20808
|
+
} else throw err;
|
|
20809
|
+
}
|
|
20810
|
+
if (!usable) {
|
|
20811
|
+
section.catalogError = failure;
|
|
20812
|
+
for (const f of plan.labelFields) section.reasons[f] = PICKLIST_CATALOG_UNAVAILABLE_NOTE;
|
|
20805
20813
|
}
|
|
20806
|
-
if (!usable) for (const f of plan.labelFields) section.reasons[f] = FIELD_CATALOG_HONESTY_NOTE;
|
|
20807
20814
|
}
|
|
20808
20815
|
let lineOfBusiness2 = null;
|
|
20809
20816
|
const lobId = _nullishCoalesce(plan.lineOfBusinessId, () => ( contractLobPointer));
|
|
@@ -20830,13 +20837,13 @@ async function resolveCompositeNames(http, plan, opts = {}) {
|
|
|
20830
20837
|
return {
|
|
20831
20838
|
section,
|
|
20832
20839
|
lineOfBusiness: lineOfBusiness2,
|
|
20833
|
-
resourceName: (id) => _nullishCoalesce(_optionalChain([section, 'access',
|
|
20834
|
-
recordName: (table, id) => _nullishCoalesce(_optionalChain([section, 'access',
|
|
20840
|
+
resourceName: (id) => _nullishCoalesce(_optionalChain([section, 'access', _199 => _199.rows, 'access', _200 => _200[`resource:${id}`], 'optionalAccess', _201 => _201.name]), () => ( null)),
|
|
20841
|
+
recordName: (table, id) => _nullishCoalesce(_optionalChain([section, 'access', _202 => _202.rows, 'access', _203 => _203[`${table}:${id}`], 'optionalAccess', _204 => _204.name]), () => ( null)),
|
|
20835
20842
|
labelFor: (field, value) => {
|
|
20836
20843
|
if (value === null || value === void 0) return null;
|
|
20837
20844
|
const values = picklists[field];
|
|
20838
20845
|
if (values === void 0) {
|
|
20839
|
-
section.reasons[field] = FIELD_CATALOG_HONESTY_NOTE;
|
|
20846
|
+
section.reasons[field] = section.catalogError !== void 0 ? PICKLIST_CATALOG_UNAVAILABLE_NOTE : FIELD_CATALOG_HONESTY_NOTE;
|
|
20840
20847
|
return null;
|
|
20841
20848
|
}
|
|
20842
20849
|
const hit = values.find((v) => String(v.value) === String(value));
|
|
@@ -20884,11 +20891,11 @@ async function labelRows(client, resourceKey, rows) {
|
|
|
20884
20891
|
const row = catalog.rows.find((r) => r.resource === resourceKey);
|
|
20885
20892
|
const known = _nullishCoalesce(lastPicklists.get(client), () => ( /* @__PURE__ */ new Map()));
|
|
20886
20893
|
lastPicklists.set(client, known);
|
|
20887
|
-
if (_optionalChain([row, 'optionalAccess',
|
|
20894
|
+
if (_optionalChain([row, 'optionalAccess', _205 => _205.fields]) === void 0) {
|
|
20888
20895
|
const last = known.get(resourceKey);
|
|
20889
20896
|
unavailable = (_nullishCoalesce(last, () => ( []))).filter((f) => candidates.includes(f));
|
|
20890
20897
|
if (last === void 0 || unavailable.length > 0) {
|
|
20891
|
-
catalogError = _nullishCoalesce(_optionalChain([row, 'optionalAccess',
|
|
20898
|
+
catalogError = _nullishCoalesce(_optionalChain([row, 'optionalAccess', _206 => _206.error]), () => ( { code: "INVALID_RESPONSE", message: `fieldCatalog: no ${resourceKey} row` }));
|
|
20892
20899
|
}
|
|
20893
20900
|
} else {
|
|
20894
20901
|
const all = row.fields.filter((f) => f.isPickList).map((f) => f.name);
|
|
@@ -20911,6 +20918,11 @@ async function labelRows(client, resourceKey, rows) {
|
|
|
20911
20918
|
}
|
|
20912
20919
|
const plan = builder.plan();
|
|
20913
20920
|
const names = plan.resourceIds.length === 0 && plan.recordFks.length === 0 && picklistFields.length === 0 ? void 0 : await resolveCompositeNames(client.http, plan);
|
|
20921
|
+
const secondReadFailed = _optionalChain([names, 'optionalAccess', _207 => _207.section, 'access', _208 => _208.catalogError]);
|
|
20922
|
+
if (secondReadFailed !== void 0) {
|
|
20923
|
+
catalogError ??= secondReadFailed;
|
|
20924
|
+
unavailable = [.../* @__PURE__ */ new Set([...unavailable, ...picklistFields])];
|
|
20925
|
+
}
|
|
20914
20926
|
const out = rows.map((row) => {
|
|
20915
20927
|
const r = { ...row };
|
|
20916
20928
|
for (const [field, value] of Object.entries(row)) {
|
|
@@ -20926,8 +20938,8 @@ async function labelRows(client, resourceKey, rows) {
|
|
|
20926
20938
|
return r;
|
|
20927
20939
|
});
|
|
20928
20940
|
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',
|
|
20941
|
+
const unresolved = Object.keys(_nullishCoalesce(_optionalChain([names, 'optionalAccess', _209 => _209.section, 'access', _210 => _210.reasons]), () => ( {})));
|
|
20942
|
+
const reasons = { ..._optionalChain([names, 'optionalAccess', _211 => _211.section, 'access', _212 => _212.reasons]) };
|
|
20931
20943
|
for (const f of unavailable) reasons[f] = PICKLIST_CATALOG_UNAVAILABLE_NOTE;
|
|
20932
20944
|
if (capped === 0 && unresolved.length === 0 && catalogError === void 0) return { rows: out };
|
|
20933
20945
|
const parts = [];
|
|
@@ -20956,22 +20968,27 @@ async function labelFetchResults(client, result) {
|
|
|
20956
20968
|
});
|
|
20957
20969
|
const results = [...result.results];
|
|
20958
20970
|
const summaries = [];
|
|
20971
|
+
const reasons = {};
|
|
20972
|
+
const catalogErrors = {};
|
|
20959
20973
|
for (const [resource, indices] of byResource) {
|
|
20960
20974
|
const labelled = await labelRows(client, resource, indices.map((i) => results[i].value));
|
|
20961
20975
|
indices.forEach((idx, j) => {
|
|
20962
20976
|
results[idx] = { ...results[idx], value: labelled.rows[j] };
|
|
20963
20977
|
});
|
|
20964
|
-
if (labelled.names !== void 0)
|
|
20978
|
+
if (labelled.names !== void 0) {
|
|
20979
|
+
summaries.push(labelled.names);
|
|
20980
|
+
for (const [field, why] of Object.entries(_nullishCoalesce(labelled.names.reasons, () => ( {})))) reasons[`${resource}.${field}`] = why;
|
|
20981
|
+
if (labelled.names.catalogError !== void 0) catalogErrors[resource] = labelled.names.catalogError;
|
|
20982
|
+
}
|
|
20965
20983
|
}
|
|
20966
20984
|
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]);
|
|
20985
|
+
const catalogError = Object.values(catalogErrors)[0];
|
|
20969
20986
|
const names = {
|
|
20970
20987
|
truncated: summaries.some((s) => s.truncated),
|
|
20971
20988
|
capped: summaries.reduce((n, s) => n + s.capped, 0),
|
|
20972
20989
|
note: summaries.map((s) => s.note).join("; "),
|
|
20973
20990
|
...Object.keys(reasons).length > 0 ? { reasons } : {},
|
|
20974
|
-
...catalogError !== void 0 ? { catalogError } : {}
|
|
20991
|
+
...catalogError !== void 0 ? { catalogError, catalogErrors } : {}
|
|
20975
20992
|
};
|
|
20976
20993
|
return { ...result, results, names };
|
|
20977
20994
|
}
|