node-autotask 0.32.0 → 0.34.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.
Files changed (40) hide show
  1. package/CHANGELOG.md +47 -0
  2. package/MCP_TOOL_CATALOG.json +27 -8
  3. package/MCP_TOOL_MANIFEST.md +14 -13
  4. package/N8N_MCP_MANIFEST.json +38 -12
  5. package/N8N_MCP_MANIFEST.md +10 -9
  6. package/README.md +1 -1
  7. package/capabilities.json +4228 -2547
  8. package/capabilities.schema.json +32 -0
  9. package/dist/capabilities.cjs +2 -2
  10. package/dist/capabilities.d.cts +13 -1
  11. package/dist/capabilities.d.ts +13 -1
  12. package/dist/capabilities.js +1 -1
  13. package/dist/{chunk-M2EGFPGF.js → chunk-4MUBUSTL.js} +4227 -2546
  14. package/dist/{chunk-FVHPN7ZR.js → chunk-6ADFCU3I.js} +636 -429
  15. package/dist/{chunk-FTF2FEQ6.cjs → chunk-DKJP73FX.cjs} +1176 -969
  16. package/dist/{chunk-R6HLJCI2.js → chunk-EZKM4HQ6.js} +1038 -573
  17. package/dist/{chunk-DCTHO7CQ.cjs → chunk-FOOHJBPP.cjs} +4227 -2546
  18. package/dist/{chunk-IKPFR6K2.cjs → chunk-GDQ4QM7Q.cjs} +1085 -620
  19. package/dist/{chunk-QCB4LYKD.cjs → chunk-P6YN2POI.cjs} +143 -143
  20. package/dist/{chunk-T6EDJRLT.js → chunk-RDFL5QYE.js} +2 -2
  21. package/dist/{index-Cw4aNNMo.d.ts → index-ByMU8IC2.d.ts} +584 -198
  22. package/dist/{index-OkbCWcef.d.cts → index-Dx4-zpDo.d.cts} +584 -198
  23. package/dist/index.cjs +22 -22
  24. package/dist/index.d.cts +2 -2
  25. package/dist/index.d.ts +2 -2
  26. package/dist/index.js +4 -4
  27. package/dist/operations/index.cjs +165 -137
  28. package/dist/operations/index.d.cts +39 -25
  29. package/dist/operations/index.d.ts +39 -25
  30. package/dist/operations/index.js +48 -20
  31. package/dist/pool.cjs +9 -9
  32. package/dist/pool.d.cts +1 -1
  33. package/dist/pool.d.ts +1 -1
  34. package/dist/pool.js +4 -4
  35. package/dist/resources/index.cjs +4 -4
  36. package/dist/resources/index.d.cts +1 -1
  37. package/dist/resources/index.d.ts +1 -1
  38. package/dist/resources/index.js +3 -3
  39. package/docs/API.md +161 -36
  40. package/package.json +2 -1
@@ -25,6 +25,7 @@ import {
25
25
  createNamePlan,
26
26
  cursorToPath,
27
27
  decodeFileData,
28
+ effectiveRequiredFields,
28
29
  formatUnknownNameList,
29
30
  formatVendorDetail,
30
31
  isAutotaskError,
@@ -40,10 +41,10 @@ import {
40
41
  unwrapItems,
41
42
  unwrapOperation,
42
43
  vendorId
43
- } from "./chunk-R6HLJCI2.js";
44
+ } from "./chunk-EZKM4HQ6.js";
44
45
  import {
45
46
  CAPABILITIES
46
- } from "./chunk-M2EGFPGF.js";
47
+ } from "./chunk-4MUBUSTL.js";
47
48
 
48
49
  // src/resources/appointments.ts
49
50
  var AppointmentsResource = class extends BaseResource {
@@ -69,9 +70,9 @@ var AppointmentsResource = class extends BaseResource {
69
70
  async count(params) {
70
71
  return this.countGlobal(params);
71
72
  }
72
- /** Get one record by id (item envelope; item: null → NotFoundError). */
73
- async get(id) {
74
- return this.getGlobal(id);
73
+ /** Get one record by id (item envelope; item: null → NotFoundError). `fresh: true` bypasses the read-cache lookup and refreshes the entry (issue #250). */
74
+ async get(id, opts = {}) {
75
+ return this.getGlobal(id, opts?.fresh === true);
75
76
  }
76
77
  /** Create a record (OperationResultModel → { id}). `dryRun: true` returns the
77
78
  * pinned envelope (section 19.3) and never issues the create. A 2xx that is not the
@@ -153,9 +154,9 @@ var BillingCodesResource = class extends BaseResource {
153
154
  async count(params) {
154
155
  return this.countGlobal(params);
155
156
  }
156
- /** Get one record by id (item envelope; item: null → NotFoundError). */
157
- async get(id) {
158
- return this.getGlobal(id);
157
+ /** Get one record by id (item envelope; item: null → NotFoundError). `fresh: true` bypasses the read-cache lookup and refreshes the entry (issue #250). */
158
+ async get(id, opts = {}) {
159
+ return this.getGlobal(id, opts?.fresh === true);
159
160
  }
160
161
  /** Resolve a BillingCode from a numeric id (or, where the vendor indexes a primary text field,
161
162
  * from an exact match on name). A numeric id miss throws NOT_FOUND; a complete
@@ -196,9 +197,9 @@ var BillingItemApprovalLevelsResource = class extends BaseResource {
196
197
  async count(params) {
197
198
  return this.countGlobal(params);
198
199
  }
199
- /** Get one record by id (item envelope; item: null → NotFoundError). */
200
- async get(id) {
201
- return this.getGlobal(id);
200
+ /** Get one record by id (item envelope; item: null → NotFoundError). `fresh: true` bypasses the read-cache lookup and refreshes the entry (issue #250). */
201
+ async get(id, opts = {}) {
202
+ return this.getGlobal(id, opts?.fresh === true);
202
203
  }
203
204
  /** Create a record (OperationResultModel → { id}). `dryRun: true` returns the
204
205
  * pinned envelope (section 19.3) and never issues the create. A 2xx that is not the
@@ -273,11 +274,11 @@ function tzOffsetMs(tz, ms) {
273
274
  }
274
275
  function localDayStartMs(y, m, d, tz) {
275
276
  if (tz === void 0) return Date.UTC(y, m - 1, d);
276
- const candidate = Date.UTC(y, m - 1, d);
277
- const offset = tzOffsetMs(tz, candidate);
278
- let start = candidate - offset;
277
+ const candidate2 = Date.UTC(y, m - 1, d);
278
+ const offset = tzOffsetMs(tz, candidate2);
279
+ let start = candidate2 - offset;
279
280
  if (tzOffsetMs(tz, start) !== offset) {
280
- start = candidate - tzOffsetMs(tz, start);
281
+ start = candidate2 - tzOffsetMs(tz, start);
281
282
  }
282
283
  const p = wallParts(tz, start);
283
284
  if (p.d !== d) start += 864e5 - ((p.h * 60 + p.mi) * 60 + p.s) * 1e3;
@@ -561,9 +562,9 @@ var BillingItemsResource = class extends BaseResource {
561
562
  async count(params) {
562
563
  return this.countGlobal(params);
563
564
  }
564
- /** Get one record by id (item envelope; item: null → NotFoundError). */
565
- async get(id) {
566
- return this.getGlobal(id);
565
+ /** Get one record by id (item envelope; item: null → NotFoundError). `fresh: true` bypasses the read-cache lookup and refreshes the entry (issue #250). */
566
+ async get(id, opts = {}) {
567
+ return this.getGlobal(id, opts?.fresh === true);
567
568
  }
568
569
  /** Update a record (PUT on the COLLECTION — the vendored spec's item path is GET-only; the vendor
569
570
  * keys the record by the id in the body). The vendor validates the FULL model on this route (V2), so a
@@ -661,9 +662,9 @@ var ChangeRequestLinksResource = class extends BaseResource {
661
662
  async count(params) {
662
663
  return this.countGlobal(params);
663
664
  }
664
- /** Get one record by id (item envelope; item: null → NotFoundError). */
665
- async get(id) {
666
- return this.getGlobal(id);
665
+ /** Get one record by id (item envelope; item: null → NotFoundError). `fresh: true` bypasses the read-cache lookup and refreshes the entry (issue #250). */
666
+ async get(id, opts = {}) {
667
+ return this.getGlobal(id, opts?.fresh === true);
667
668
  }
668
669
  /** Create a record (OperationResultModel → { id}). `dryRun: true` returns the
669
670
  * pinned envelope (section 19.3) and never issues the create. A 2xx that is not the
@@ -718,9 +719,9 @@ var ChecklistLibrariesResource = class extends BaseResource {
718
719
  async count(params) {
719
720
  return this.countGlobal(params);
720
721
  }
721
- /** Get one record by id (item envelope; item: null → NotFoundError). */
722
- async get(id) {
723
- return this.getGlobal(id);
722
+ /** Get one record by id (item envelope; item: null → NotFoundError). `fresh: true` bypasses the read-cache lookup and refreshes the entry (issue #250). */
723
+ async get(id, opts = {}) {
724
+ return this.getGlobal(id, opts?.fresh === true);
724
725
  }
725
726
  /** Create a record (OperationResultModel → { id}). `dryRun: true` returns the
726
727
  * pinned envelope (section 19.3) and never issues the create. A 2xx that is not the
@@ -793,8 +794,8 @@ var ChecklistLibraryChecklistItemsResource = class extends BaseResource {
793
794
  return this.countGlobal(params);
794
795
  }
795
796
  /** Get one record by parent + id (/V1.0/ChecklistLibraries/{parentId}/ChecklistItems/{id} — vendor item envelope; item: null → NotFoundError). */
796
- async get(parentId, id) {
797
- return this.getScopedRaw(parentId, id);
797
+ async get(parentId, id, opts = {}) {
798
+ return this.getScopedRaw(parentId, id, opts?.fresh === true);
798
799
  }
799
800
  /** Create a record under the parent (OperationResultModel → { id}). `dryRun: true` returns the
800
801
  * pinned envelope (section 19.3) and never issues the create. A 2xx that is not the
@@ -856,9 +857,9 @@ var ClassificationIconsResource = class extends BaseResource {
856
857
  async count(params) {
857
858
  return this.countGlobal(params);
858
859
  }
859
- /** Get one record by id (item envelope; item: null → NotFoundError). */
860
- async get(id) {
861
- return this.getGlobal(id);
860
+ /** Get one record by id (item envelope; item: null → NotFoundError). `fresh: true` bypasses the read-cache lookup and refreshes the entry (issue #250). */
861
+ async get(id, opts = {}) {
862
+ return this.getGlobal(id, opts?.fresh === true);
862
863
  }
863
864
  /** Resolve a ClassificationIcon from a numeric id (or, where the vendor indexes a primary text field,
864
865
  * from an exact match on name). A numeric id miss throws NOT_FOUND; a complete
@@ -1327,8 +1328,14 @@ async function readFields(http, fresh) {
1327
1328
  cache?.set(key, "fields", fields);
1328
1329
  return fields;
1329
1330
  }
1330
- function assumed(excludeStatusIds) {
1331
- const closedIds = excludeStatusIds === void 0 ? [ASSUMED_CLOSED_STATUS_ID] : [...excludeStatusIds];
1331
+ function assumed(allowAssumed, operation) {
1332
+ if (!allowAssumed) {
1333
+ throw new AutotaskError(
1334
+ `${operation}: the tenant Tickets status picklist could not be resolved to a closed set and allowAssumed is false, so the assumed id ${ASSUMED_CLOSED_STATUS_ID} is refused (fix: expose the Tickets field catalog to this API user, or pass excludeStatusIds)`,
1335
+ { code: "STATUS_SEMANTICS_UNRESOLVED", category: "validation", operation }
1336
+ );
1337
+ }
1338
+ const closedIds = [ASSUMED_CLOSED_STATUS_ID];
1332
1339
  return {
1333
1340
  picklist: [],
1334
1341
  closedIds,
@@ -1337,7 +1344,11 @@ function assumed(excludeStatusIds) {
1337
1344
  note: `closed = status ${closedIds.join(", ")} \u2014 ASSUMED, not read from the tenant: the Tickets status picklist could not be resolved, so the historical id ${ASSUMED_CLOSED_STATUS_ID} stands in (fix: expose the Tickets field catalog to this API user, or pass excludeStatusIds)`
1338
1345
  };
1339
1346
  }
1340
- async function resolveTicketStatusSemantics(http, opts = {}) {
1347
+ async function resolveTicketStatusSemantics(http, opts = {}, operation = OP) {
1348
+ if (opts.allowAssumed !== void 0 && typeof opts.allowAssumed !== "boolean") {
1349
+ throw new AutotaskConfigError(`${operation}: allowAssumed must be a boolean (got ${JSON.stringify(opts.allowAssumed)})`, { operation });
1350
+ }
1351
+ const allowAssumed = opts.allowAssumed !== false;
1341
1352
  if (opts.excludeStatusIds !== void 0) {
1342
1353
  const closedIds2 = [...new Set(opts.excludeStatusIds.map((id) => Number(id)))];
1343
1354
  if (closedIds2.length === 0 || closedIds2.some((id) => !Number.isSafeInteger(id) || id < 1)) {
@@ -1350,11 +1361,11 @@ async function resolveTicketStatusSemantics(http, opts = {}) {
1350
1361
  fields = await readFields(http, opts.fresh === true);
1351
1362
  } catch (e) {
1352
1363
  if (e instanceof AutotaskError && e.code === "ABORTED") throw e;
1353
- return assumed();
1364
+ return assumed(allowAssumed, operation);
1354
1365
  }
1355
1366
  const picklist = picklistOf(fields);
1356
1367
  const closedIds = picklist.filter((v) => CLOSED_STATUS_LABELS.includes(v.label.trim().toLowerCase())).map((v) => v.id);
1357
- if (closedIds.length === 0) return assumed();
1368
+ if (closedIds.length === 0) return assumed(allowAssumed, operation);
1358
1369
  const labels = picklist.filter((v) => closedIds.includes(v.id)).map((v) => `${v.id} ${v.label}`).join(", ");
1359
1370
  return {
1360
1371
  picklist,
@@ -1439,8 +1450,8 @@ async function scopedCompanyQuery(http, path, companyID, limit, includeFields) {
1439
1450
  });
1440
1451
  return project(unwrapItems(res).items, includeFields);
1441
1452
  }
1442
- async function readOpenTickets(http, companyID, ticketLimit, includeFields) {
1443
- const semantics = await resolveTicketStatusSemantics(http);
1453
+ async function readOpenTickets(http, companyID, ticketLimit, includeFields, status = {}) {
1454
+ const semantics = await resolveTicketStatusSemantics(http, status, "companies.fullProfile");
1444
1455
  const openLeaf = openStatusFilter(semantics.closedIds);
1445
1456
  const openRows = await (async () => {
1446
1457
  const res = await http.request({
@@ -1540,7 +1551,10 @@ async function fullProfile(resource, id, opts = {}, http) {
1540
1551
  const contacts = await scopedCompanyQuery(http, "/V1.0/Contacts/query", companyID, contactLimit, proj.contacts);
1541
1552
  const notes = await scopedCompanyQuery(http, "/V1.0/CompanyNotes/query", companyID, noteLimit, proj.notes);
1542
1553
  const projects = await scopedCompanyQuery(http, "/V1.0/Projects/query", companyID, projectLimit, proj.projects);
1543
- const openTickets = await readOpenTickets(http, companyID, ticketLimit, proj.openTickets);
1554
+ const openTickets = await readOpenTickets(http, companyID, ticketLimit, proj.openTickets, {
1555
+ ...opts.excludeStatusIds === void 0 ? {} : { excludeStatusIds: opts.excludeStatusIds },
1556
+ ...opts.allowAssumed === void 0 ? {} : { allowAssumed: opts.allowAssumed }
1557
+ });
1544
1558
  const result = {
1545
1559
  company,
1546
1560
  locations: { items: locations, capped: locations.length >= locLimit },
@@ -1561,6 +1575,151 @@ async function fullProfile(resource, id, opts = {}, http) {
1561
1575
  return result;
1562
1576
  }
1563
1577
 
1578
+ // src/resources/special/companies/prepareCrmWrite.ts
1579
+ var FREEMAIL = /* @__PURE__ */ new Set(["gmail.com", "googlemail.com", "outlook.com", "hotmail.com", "live.com", "yahoo.com", "yahoo.com.au", "icloud.com", "bigpond.com", "optusnet.com.au", "me.com", "proton.me", "protonmail.com"]);
1580
+ var LIMIT = 10;
1581
+ var OP2 = "companies.prepareCrmWrite";
1582
+ async function readRows(http, path, filter) {
1583
+ const res = await http.request({ method: "POST", idempotent: true, path, body: { MaxRecords: LIMIT * 5, filter }, operation: OP2 });
1584
+ return unwrapItems(res).items;
1585
+ }
1586
+ var str = (v) => typeof v === "string" && v !== "" ? v : null;
1587
+ var bool = (v) => typeof v === "boolean" ? v : null;
1588
+ var norm = (s) => s.toLowerCase().replace(/[^a-z0-9]+/g, " ").replace(/\b(pty|ltd|limited|inc|llc)\b/g, "").replace(/\s+/g, " ").trim();
1589
+ function domainOf(input) {
1590
+ if (!input) return null;
1591
+ const host = input.trim().toLowerCase().replace(/^[a-z]+:\/\//, "").replace(/^.*@/, "").replace(/^www\./, "").split(/[/?#:]/)[0] ?? "";
1592
+ return host.includes(".") && !FREEMAIL.has(host) ? host : null;
1593
+ }
1594
+ function candidate(r) {
1595
+ return { id: r.id, companyName: str(r.companyName), webAddress: str(r.webAddress), phone: str(r.phone), isActive: bool(r.isActive) };
1596
+ }
1597
+ function has(v) {
1598
+ return v !== void 0 && v !== null && v !== "";
1599
+ }
1600
+ async function prepareCrmWrite(resource, input, http) {
1601
+ const intents = ["create_company", "add_contact", "update_contact", "update_company"];
1602
+ if (!input || !intents.includes(input.intent)) throw new AutotaskConfigError(`prepareCrmWrite: intent must be one of ${intents.join(", ")}`);
1603
+ const co = input.company ?? {};
1604
+ const ct = input.contact ?? {};
1605
+ const caveats = [
1606
+ "Companies, resources and countries are blind surfaces on some tenants: a miss is not proof a record is absent, and owner / country candidates are lookups, not lists.",
1607
+ "Company name matching is `contains` (exact names ranked first); there is no semantic search in the SDK."
1608
+ ];
1609
+ const needsInput = [];
1610
+ let candidates = [];
1611
+ let matchedBy = null;
1612
+ let searched = false;
1613
+ if (has(co.id)) {
1614
+ searched = true;
1615
+ const rows = await readRows(http, "/V1.0/Companies/query", [{ field: "id", op: "eq", value: co.id }]);
1616
+ candidates = rows.map(candidate);
1617
+ matchedBy = candidates.length ? "id" : null;
1618
+ }
1619
+ const domain = domainOf(co.domain) ?? domainOf(co.website) ?? domainOf(ct.emailAddress);
1620
+ if (candidates.length === 0 && domain) {
1621
+ searched = true;
1622
+ candidates = (await resource.searchByDomain(domain, { limit: LIMIT })).map((c) => candidate(c));
1623
+ matchedBy = candidates.length ? "domain" : null;
1624
+ }
1625
+ if (candidates.length === 0 && has(co.companyName)) {
1626
+ searched = true;
1627
+ const rows = (await resource.searchByIdentity({ companyName: co.companyName }, { limit: LIMIT })).map((c) => candidate(c));
1628
+ const want = norm(co.companyName);
1629
+ const exact = rows.filter((r) => r.companyName !== null && norm(r.companyName) === want);
1630
+ candidates = exact.length ? exact : rows;
1631
+ matchedBy = candidates.length ? exact.length ? "name_exact" : "name_contains" : null;
1632
+ }
1633
+ const status = !searched ? "not_searched" : candidates.length === 0 ? "none" : candidates.length === 1 ? "matched" : "ambiguous";
1634
+ const companyID = status === "matched" ? candidates[0].id : null;
1635
+ const company = { status, matchedBy, candidates };
1636
+ if (status === "ambiguous") {
1637
+ needsInput.push({ field: "company", why: `${candidates.length} companies match; choose one`, source: "policy", lookup: { candidates: candidates.map((c) => ({ id: c.id, companyName: c.companyName })) }, research: "ask" });
1638
+ }
1639
+ if (status === "none" && input.intent !== "create_company") {
1640
+ needsInput.push({ field: "company", why: "no company matched; give a company id, name or domain, or use intent create_company (a miss is not proof of absence)", source: "policy", research: "ask" });
1641
+ }
1642
+ if (status === "not_searched" && input.intent !== "create_company") {
1643
+ needsInput.push({ field: "company", why: "give a company id, name, domain/website or a contact email to search by", source: "policy", research: "ask" });
1644
+ }
1645
+ let locations = null;
1646
+ if (companyID !== null) {
1647
+ const rows = await readRows(http, "/V1.0/CompanyLocations/query", [{ field: "companyID", op: "eq", value: companyID }]);
1648
+ const items = rows.map((r) => ({ id: r.id, name: str(r.name), isPrimary: bool(r.isPrimary), isActive: bool(r.isActive), city: str(r.city), state: str(r.state), postalCode: str(r.postalCode) }));
1649
+ const active = items.filter((l) => l.isActive !== false);
1650
+ const m = active.filter((l) => has(ct.city) && l.city?.toLowerCase() === String(ct.city).toLowerCase() || has(ct.postalCode) && l.postalCode === String(ct.postalCode));
1651
+ const pick = has(ct.companyLocationID) ? { rule: "matched", locationID: ct.companyLocationID } : active.length === 1 ? { rule: "single", locationID: active[0].id } : active.length > 1 && m.length === 1 ? { rule: "matched", locationID: m[0].id } : active.length > 1 ? { rule: "ask", locationID: null } : { rule: "none", locationID: null };
1652
+ locations = { items, pick };
1653
+ if (input.intent === "add_contact" && pick.locationID === null) {
1654
+ needsInput.push({
1655
+ field: "companyLocationID",
1656
+ why: active.length > 1 ? "the company has several active locations; do not guess" : "the company has no active location; create or reactivate one first",
1657
+ source: "policy",
1658
+ lookup: { candidates: active.map((l) => ({ id: l.id, name: l.name, isPrimary: l.isPrimary })) },
1659
+ research: "ask"
1660
+ });
1661
+ }
1662
+ }
1663
+ let contacts = null;
1664
+ if (input.intent !== "create_company" && (has(ct.emailAddress) || has(ct.firstName) && has(ct.lastName) || has(ct.id))) {
1665
+ const pickFields = (r) => ({ id: r.id, firstName: r.firstName, lastName: r.lastName, emailAddress: r.emailAddress, companyID: r.companyID, companyLocationID: r.companyLocationID, isActive: r.isActive });
1666
+ let rows = [];
1667
+ let by = null;
1668
+ if (has(ct.id)) rows = await readRows(http, "/V1.0/Contacts/query", [{ field: "id", op: "eq", value: ct.id }]);
1669
+ else if (has(ct.emailAddress)) {
1670
+ rows = await readRows(http, "/V1.0/Contacts/query", [{ field: "emailAddress", op: "eq", value: ct.emailAddress }]);
1671
+ by = rows.length ? "email" : null;
1672
+ }
1673
+ if (rows.length === 0 && has(ct.firstName) && has(ct.lastName)) {
1674
+ const f = [{ field: "firstName", op: "eq", value: ct.firstName }, { field: "lastName", op: "eq", value: ct.lastName }];
1675
+ if (companyID !== null) f.push({ field: "companyID", op: "eq", value: companyID });
1676
+ rows = await readRows(http, "/V1.0/Contacts/query", f);
1677
+ by = rows.length ? "name" : null;
1678
+ }
1679
+ contacts = { duplicates: rows.slice(0, LIMIT).map(pickFields), matchedBy: by };
1680
+ if (input.intent === "update_contact" && rows.length === 0) {
1681
+ needsInput.push({ field: "contact", why: "no contact matched; give a contact id or email", source: "policy", research: "ask" });
1682
+ }
1683
+ }
1684
+ if (input.intent === "create_company" && status !== "matched") {
1685
+ const eff = effectiveRequiredFields(null, RELATIONSHIP_MAP.companies?.zoneFacts);
1686
+ const research = (f) => ["companyType", "ownerResourceID", "countryID"].includes(f) ? "lookup" : "web_if_available_else_ask";
1687
+ const lookups = {
1688
+ companyType: { via: "operations.fieldCatalog", resource: "companies", field: "companyType", labels: true, note: "map the user wording to one returned label; never hardcode ids" },
1689
+ ownerResourceID: { via: "resources.get / the staff resolver", note: "owners cannot be enumerated on a blind surface: take a known resource id and confirm it with resources.get" },
1690
+ countryID: { via: "countries.query", note: "resolve the country name to an id; never guess" }
1691
+ };
1692
+ const wanted = [
1693
+ ...eff.fields.filter((f) => f !== "isActive").map((f) => [f, "live-proven"]),
1694
+ ...["address1", "city", "state", "postalCode", "countryID"].map((f) => [f, "policy"])
1695
+ ];
1696
+ for (const [f, source] of wanted) {
1697
+ if (has(co[f]) || needsInput.some((n) => n.field === f)) continue;
1698
+ needsInput.push({ field: f, why: source === "policy" ? `CRM policy: a new company needs ${f} (the vendor auto-creates a "Primary Address" location from it)` : `the vendor requires ${f} to create a company`, source, ...lookups[f] ? { lookup: lookups[f] } : {}, research: research(f) });
1699
+ }
1700
+ }
1701
+ if (input.intent === "add_contact") {
1702
+ for (const f of ["firstName", "lastName"]) if (!has(ct[f])) needsInput.push({ field: f, why: `the vendor requires contact ${f}`, source: "live-proven", research: "ask" });
1703
+ if (!has(ct.emailAddress) && !has(ct.phone) && !has(ct.mobilePhone)) needsInput.push({ field: "emailAddress", why: "CRM policy: a contact needs an email or a phone number", source: "policy", research: "ask" });
1704
+ }
1705
+ let next = null;
1706
+ const isInactive = (d) => d.isActive === false || d.isActive === 0;
1707
+ const dups = contacts?.duplicates ?? [];
1708
+ const sameCompany = companyID === null ? dups : dups.filter((d) => d.companyID === companyID);
1709
+ const elsewhere = companyID === null ? [] : dups.filter((d) => d.companyID !== companyID && !isInactive(d));
1710
+ if (input.intent === "add_contact" && sameCompany.length === 0 && elsewhere.length > 0) {
1711
+ needsInput.push({ field: "contact", why: `a contact with this ${contacts?.matchedBy ?? "identity"} is active at another company: update it, move it with contacts.moveToCompany, or confirm a second record`, source: "policy", lookup: { duplicates: elsewhere }, research: "ask" });
1712
+ }
1713
+ if (needsInput.length === 0) {
1714
+ const dup = sameCompany[0];
1715
+ if (input.intent === "create_company") next = status === "matched" ? { operation: "companies.update", note: "the company already exists: update it instead of creating" } : { operation: "companies.create", note: 'then re-run with intent add_contact: the vendor auto-creates a "Primary Address" location (rename it with company_locations.update; locations cannot be deleted via the API)' };
1716
+ else if (input.intent === "add_contact") next = dup ? { operation: "contacts.update", note: `a contact already matches by ${contacts?.matchedBy ?? "id"} (id ${String(dup.id)}): update it, or move it with contacts.moveToCompany if it belongs to another company` } : { operation: "contacts.create", note: `set companyID ${String(companyID)} and companyLocationID ${String(locations?.pick.locationID)}` };
1717
+ else if (input.intent === "update_contact") next = { operation: "contacts.update", note: "send only the changed fields" };
1718
+ else next = { operation: "companies.update", note: "send only the changed fields" };
1719
+ }
1720
+ return { intent: input.intent, company, locations, contacts, needsInput, next, caveats };
1721
+ }
1722
+
1564
1723
  // src/resources/special/companies/unbilledWorkTypes.ts
1565
1724
  var UNBILLED_WORK_NOTE_CHARS_DEFAULT = 400;
1566
1725
  var UNBILLED_WORK_JOIN_SET_CAP = 300;
@@ -1671,7 +1830,7 @@ function validateUnbilledWorkOptions(companyId, opts) {
1671
1830
  }
1672
1831
 
1673
1832
  // src/resources/special/companies/unbilledWork.ts
1674
- var OP2 = "companies.unbilledWork";
1833
+ var OP3 = "companies.unbilledWork";
1675
1834
  function capJoinSet(ids2, cap) {
1676
1835
  const sorted = [...new Set(ids2)].sort((a, b) => a - b);
1677
1836
  if (sorted.length <= cap) return { ids: sorted, truncated: false };
@@ -1708,14 +1867,14 @@ async function readCompanyAndParent(resource, id, includeParent) {
1708
1867
  }
1709
1868
  async function readJoinSets(http, companyIds, v) {
1710
1869
  const ticketsCond = [{ field: "companyID", op: "in", value: companyIds }];
1711
- const ticketsRaw = await boundedPart(http, "/V1.0/Tickets/query", ticketsCond, v.limit, OP2);
1870
+ const ticketsRaw = await boundedPart(http, "/V1.0/Tickets/query", ticketsCond, v.limit, OP3);
1712
1871
  const projectsCond = [{ field: "companyID", op: "in", value: companyIds }];
1713
- const projectsRaw = await boundedPart(http, "/V1.0/Projects/query", projectsCond, v.limit, OP2);
1872
+ const projectsRaw = await boundedPart(http, "/V1.0/Projects/query", projectsCond, v.limit, OP3);
1714
1873
  const projectIds = projectsRaw.items.map((p) => num(p.id)).filter((n) => n > 0);
1715
1874
  let taskIds = [];
1716
1875
  let tasksHasMore = false;
1717
1876
  if (projectIds.length > 0) {
1718
- const tasksRaw = await boundedPart(http, "/V1.0/Tasks/query", [{ field: "projectID", op: "in", value: projectIds }], v.limit, OP2);
1877
+ const tasksRaw = await boundedPart(http, "/V1.0/Tasks/query", [{ field: "projectID", op: "in", value: projectIds }], v.limit, OP3);
1719
1878
  taskIds = tasksRaw.items.map((t) => num(t.id)).filter((n) => n > 0);
1720
1879
  tasksHasMore = tasksRaw.hasMore;
1721
1880
  }
@@ -1739,7 +1898,7 @@ async function readBillingPart(http, v, companyIds) {
1739
1898
  }
1740
1899
  const billingFields = resolveFieldsPreset("billing_join", "billing_items");
1741
1900
  const billingIncludeFields = [...billingFields, "id", ...v.includeNotes ? ["description"] : []];
1742
- const billingRaw = await boundedPart(http, "/V1.0/BillingItems/query", billingConditions, v.limit, OP2, billingIncludeFields);
1901
+ const billingRaw = await boundedPart(http, "/V1.0/BillingItems/query", billingConditions, v.limit, OP3, billingIncludeFields);
1743
1902
  let billingItems = billingRaw.items;
1744
1903
  let billingNoteCharsTruncated = 0;
1745
1904
  if (v.includeNotes) {
@@ -1783,7 +1942,7 @@ async function readTimePart(http, v, join) {
1783
1942
  if (v.dateFrom !== void 0) timeConditions.push({ field: "dateWorked", op: "gte", value: v.dateFrom });
1784
1943
  if (v.dateTo !== void 0) timeConditions.push({ field: "dateWorked", op: "lte", value: v.dateTo });
1785
1944
  const timeFields = ["taskID", "ticketID", "hoursWorked", "dateWorked", "id", ...v.includeNotes ? ["summaryNotes"] : []];
1786
- const raw = await boundedPart(http, "/V1.0/TimeEntries/query", timeConditions, v.limit, OP2, timeFields);
1945
+ const raw = await boundedPart(http, "/V1.0/TimeEntries/query", timeConditions, v.limit, OP3, timeFields);
1787
1946
  entries = raw.items;
1788
1947
  let cappedItems = entries;
1789
1948
  let noteCharsTruncated = 0;
@@ -1927,9 +2086,9 @@ var CompaniesResource = class extends BaseResource {
1927
2086
  async count(params) {
1928
2087
  return this.countGlobal(params);
1929
2088
  }
1930
- /** Get one record by id (item envelope; item: null → NotFoundError). */
1931
- async get(id) {
1932
- return this.getGlobal(id);
2089
+ /** Get one record by id (item envelope; item: null → NotFoundError). `fresh: true` bypasses the read-cache lookup and refreshes the entry (issue #250). */
2090
+ async get(id, opts = {}) {
2091
+ return this.getGlobal(id, opts?.fresh === true);
1933
2092
  }
1934
2093
  /** Create a record (OperationResultModel → { id}). `dryRun: true` returns the
1935
2094
  * pinned envelope (section 19.3) and never issues the create. A 2xx that is not the
@@ -2007,6 +2166,10 @@ var CompaniesResource = class extends BaseResource {
2007
2166
  unbilledWork(id, opts) {
2008
2167
  return unbilledWork(this, id, opts, this.http);
2009
2168
  }
2169
+ /** Node-parity special op (hand-written in src/resources/special/companies.ts). */
2170
+ prepareCrmWrite(input) {
2171
+ return prepareCrmWrite(this, input, this.http);
2172
+ }
2010
2173
  };
2011
2174
 
2012
2175
  // src/resources/company_alerts.ts
@@ -2035,8 +2198,8 @@ var CompanyAlertsResource = class extends BaseResource {
2035
2198
  return this.countGlobal(params);
2036
2199
  }
2037
2200
  /** Get one record by parent + id (/V1.0/Companies/{parentId}/Alerts/{id} — vendor item envelope; item: null → NotFoundError). */
2038
- async get(parentId, id) {
2039
- return this.getScopedRaw(parentId, id);
2201
+ async get(parentId, id, opts = {}) {
2202
+ return this.getScopedRaw(parentId, id, opts?.fresh === true);
2040
2203
  }
2041
2204
  /** Create a record under the parent (OperationResultModel → { id}). `dryRun: true` returns the
2042
2205
  * pinned envelope (section 19.3) and never issues the create. A 2xx that is not the
@@ -2102,8 +2265,8 @@ var CompanyLocationsResource = class extends BaseResource {
2102
2265
  return this.countGlobal(params);
2103
2266
  }
2104
2267
  /** Get one record by parent + id (/V1.0/Companies/{parentId}/Locations/{id} — vendor item envelope; item: null → NotFoundError). */
2105
- async get(parentId, id) {
2106
- return this.getScopedRaw(parentId, id);
2268
+ async get(parentId, id, opts = {}) {
2269
+ return this.getScopedRaw(parentId, id, opts?.fresh === true);
2107
2270
  }
2108
2271
  /** Create a record under the parent (OperationResultModel → { id}). `dryRun: true` returns the
2109
2272
  * pinned envelope (section 19.3) and never issues the create. A 2xx that is not the
@@ -2174,8 +2337,8 @@ var CompanyNotesResource = class extends BaseResource {
2174
2337
  return this.countGlobal(params);
2175
2338
  }
2176
2339
  /** Get one record by parent + id (/V1.0/Companies/{parentId}/Notes/{id} — vendor item envelope; item: null → NotFoundError). */
2177
- async get(parentId, id) {
2178
- return this.getScopedRaw(parentId, id);
2340
+ async get(parentId, id, opts = {}) {
2341
+ return this.getScopedRaw(parentId, id, opts?.fresh === true);
2179
2342
  }
2180
2343
  /** Create a record under the parent (OperationResultModel → { id}). `dryRun: true` returns the
2181
2344
  * pinned envelope (section 19.3) and never issues the create. A 2xx that is not the
@@ -2237,8 +2400,8 @@ var CompanySiteConfigurationsResource = class extends BaseResource {
2237
2400
  return this.countGlobal(params);
2238
2401
  }
2239
2402
  /** Get one record by parent + id (/V1.0/Companies/{parentId}/SiteConfigurations/{id} — vendor item envelope; item: null → NotFoundError). */
2240
- async get(parentId, id) {
2241
- return this.getScopedRaw(parentId, id);
2403
+ async get(parentId, id, opts = {}) {
2404
+ return this.getScopedRaw(parentId, id, opts?.fresh === true);
2242
2405
  }
2243
2406
  /** Update a record under the parent (PATCH on the collection — swagger documents put+patch there;
2244
2407
  * the vendor keys the record by the id in the body; OperationResultModel → { id}). `dryRun: true` returns
@@ -2289,9 +2452,9 @@ var CompanyWebhooksResource = class extends BaseResource {
2289
2452
  async count(params) {
2290
2453
  return this.countGlobal(params);
2291
2454
  }
2292
- /** Get one record by id (item envelope; item: null → NotFoundError). */
2293
- async get(id) {
2294
- return this.getGlobal(id);
2455
+ /** Get one record by id (item envelope; item: null → NotFoundError). `fresh: true` bypasses the read-cache lookup and refreshes the entry (issue #250). */
2456
+ async get(id, opts = {}) {
2457
+ return this.getGlobal(id, opts?.fresh === true);
2295
2458
  }
2296
2459
  /** Create a record (OperationResultModel → { id}). `dryRun: true` returns the
2297
2460
  * pinned envelope (section 19.3) and never issues the create. A 2xx that is not the
@@ -2364,8 +2527,8 @@ var ConfigurationItemBillingProductAssociationsResource = class extends BaseReso
2364
2527
  return this.countGlobal(params);
2365
2528
  }
2366
2529
  /** Get one record by parent + id (/V1.0/ConfigurationItems/{parentId}/BillingProductAssociations/{id} — vendor item envelope; item: null → NotFoundError). */
2367
- async get(parentId, id) {
2368
- return this.getScopedRaw(parentId, id);
2530
+ async get(parentId, id, opts = {}) {
2531
+ return this.getScopedRaw(parentId, id, opts?.fresh === true);
2369
2532
  }
2370
2533
  /** Create a record under the parent (OperationResultModel → { id}). `dryRun: true` returns the
2371
2534
  * pinned envelope (section 19.3) and never issues the create. A 2xx that is not the
@@ -2429,9 +2592,9 @@ var ConfigurationItemCategoriesResource = class extends BaseResource {
2429
2592
  async count(params) {
2430
2593
  return this.countGlobal(params);
2431
2594
  }
2432
- /** Get one record by id (item envelope; item: null → NotFoundError). */
2433
- async get(id) {
2434
- return this.getGlobal(id);
2595
+ /** Get one record by id (item envelope; item: null → NotFoundError). `fresh: true` bypasses the read-cache lookup and refreshes the entry (issue #250). */
2596
+ async get(id, opts = {}) {
2597
+ return this.getGlobal(id, opts?.fresh === true);
2435
2598
  }
2436
2599
  /** Create a record (OperationResultModel → { id}). `dryRun: true` returns the
2437
2600
  * pinned envelope (section 19.3) and never issues the create. A 2xx that is not the
@@ -2497,8 +2660,8 @@ var ConfigurationItemCategoryUdfAssociationsResource = class extends BaseResourc
2497
2660
  return this.countGlobal(params);
2498
2661
  }
2499
2662
  /** Get one record by parent + id (/V1.0/ConfigurationItemCategories/{parentId}/UdfAssociations/{id} — vendor item envelope; item: null → NotFoundError). */
2500
- async get(parentId, id) {
2501
- return this.getScopedRaw(parentId, id);
2663
+ async get(parentId, id, opts = {}) {
2664
+ return this.getScopedRaw(parentId, id, opts?.fresh === true);
2502
2665
  }
2503
2666
  /** Create a record under the parent (OperationResultModel → { id}). `dryRun: true` returns the
2504
2667
  * pinned envelope (section 19.3) and never issues the create. A 2xx that is not the
@@ -2563,8 +2726,8 @@ var ConfigurationItemDnsRecordsResource = class extends BaseResource {
2563
2726
  return this.countGlobal(params);
2564
2727
  }
2565
2728
  /** Get one record by parent + id (/V1.0/ConfigurationItems/{parentId}/DnsRecords/{id} — vendor item envelope; item: null → NotFoundError). */
2566
- async get(parentId, id) {
2567
- return this.getScopedRaw(parentId, id);
2729
+ async get(parentId, id, opts = {}) {
2730
+ return this.getScopedRaw(parentId, id, opts?.fresh === true);
2568
2731
  }
2569
2732
  /** Delete a record under the parent (OperationResultModel → { id}). `dryRun: true` returns the pinned
2570
2733
  * envelope and never issues the delete. */
@@ -2612,8 +2775,8 @@ var ConfigurationItemNotesResource = class extends BaseResource {
2612
2775
  return this.countGlobal(params);
2613
2776
  }
2614
2777
  /** Get one record by parent + id (/V1.0/ConfigurationItems/{parentId}/Notes/{id} — vendor item envelope; item: null → NotFoundError). */
2615
- async get(parentId, id) {
2616
- return this.getScopedRaw(parentId, id);
2778
+ async get(parentId, id, opts = {}) {
2779
+ return this.getScopedRaw(parentId, id, opts?.fresh === true);
2617
2780
  }
2618
2781
  /** Create a record under the parent (OperationResultModel → { id}). `dryRun: true` returns the
2619
2782
  * pinned envelope (section 19.3) and never issues the create. A 2xx that is not the
@@ -2671,8 +2834,8 @@ var ConfigurationItemRelatedItemsResource = class extends BaseResource {
2671
2834
  return this.countGlobal(params);
2672
2835
  }
2673
2836
  /** Get one record by parent + id (/V1.0/ConfigurationItems/{parentId}/RelatedItems/{id} — vendor item envelope; item: null → NotFoundError). */
2674
- async get(parentId, id) {
2675
- return this.getScopedRaw(parentId, id);
2837
+ async get(parentId, id, opts = {}) {
2838
+ return this.getScopedRaw(parentId, id, opts?.fresh === true);
2676
2839
  }
2677
2840
  /** Create a record under the parent (OperationResultModel → { id}). `dryRun: true` returns the
2678
2841
  * pinned envelope (section 19.3) and never issues the create. A 2xx that is not the
@@ -2890,9 +3053,9 @@ var ConfigurationItemsResource = class extends BaseResource {
2890
3053
  async count(params) {
2891
3054
  return this.countGlobal(params);
2892
3055
  }
2893
- /** Get one record by id (item envelope; item: null → NotFoundError). */
2894
- async get(id) {
2895
- return this.getGlobal(id);
3056
+ /** Get one record by id (item envelope; item: null → NotFoundError). `fresh: true` bypasses the read-cache lookup and refreshes the entry (issue #250). */
3057
+ async get(id, opts = {}) {
3058
+ return this.getGlobal(id, opts?.fresh === true);
2896
3059
  }
2897
3060
  /** Create a record (OperationResultModel → { id}). `dryRun: true` returns the
2898
3061
  * pinned envelope (section 19.3) and never issues the create. A 2xx that is not the
@@ -2981,8 +3144,8 @@ var ConfigurationItemSslSubjectAlternativeNamesResource = class extends BaseReso
2981
3144
  return this.countGlobal(params);
2982
3145
  }
2983
3146
  /** Get one record by parent + id (/V1.0/ConfigurationItems/{parentId}/SslSubjectAlternativeNames/{id} — vendor item envelope; item: null → NotFoundError). */
2984
- async get(parentId, id) {
2985
- return this.getScopedRaw(parentId, id);
3147
+ async get(parentId, id, opts = {}) {
3148
+ return this.getScopedRaw(parentId, id, opts?.fresh === true);
2986
3149
  }
2987
3150
  /** Update a record under the parent (PATCH on the collection — swagger documents put+patch there;
2988
3151
  * the vendor keys the record by the id in the body; OperationResultModel → { id}). `dryRun: true` returns
@@ -3042,9 +3205,9 @@ var ConfigurationItemTypesResource = class extends BaseResource {
3042
3205
  async count(params) {
3043
3206
  return this.countGlobal(params);
3044
3207
  }
3045
- /** Get one record by id (item envelope; item: null → NotFoundError). */
3046
- async get(id) {
3047
- return this.getGlobal(id);
3208
+ /** Get one record by id (item envelope; item: null → NotFoundError). `fresh: true` bypasses the read-cache lookup and refreshes the entry (issue #250). */
3209
+ async get(id, opts = {}) {
3210
+ return this.getGlobal(id, opts?.fresh === true);
3048
3211
  }
3049
3212
  /** Create a record (OperationResultModel → { id}). `dryRun: true` returns the
3050
3213
  * pinned envelope (section 19.3) and never issues the create. A 2xx that is not the
@@ -3118,9 +3281,9 @@ var ConfigurationItemWebhooksResource = class extends BaseResource {
3118
3281
  async count(params) {
3119
3282
  return this.countGlobal(params);
3120
3283
  }
3121
- /** Get one record by id (item envelope; item: null → NotFoundError). */
3122
- async get(id) {
3123
- return this.getGlobal(id);
3284
+ /** Get one record by id (item envelope; item: null → NotFoundError). `fresh: true` bypasses the read-cache lookup and refreshes the entry (issue #250). */
3285
+ async get(id, opts = {}) {
3286
+ return this.getGlobal(id, opts?.fresh === true);
3124
3287
  }
3125
3288
  /** Create a record (OperationResultModel → { id}). `dryRun: true` returns the
3126
3289
  * pinned envelope (section 19.3) and never issues the create. A 2xx that is not the
@@ -3189,9 +3352,9 @@ var ContactGroupContactsResource = class extends BaseResource {
3189
3352
  async count(params) {
3190
3353
  return this.countGlobal(params);
3191
3354
  }
3192
- /** Get one record by id (item envelope; item: null → NotFoundError). */
3193
- async get(id) {
3194
- return this.getGlobal(id);
3355
+ /** Get one record by id (item envelope; item: null → NotFoundError). `fresh: true` bypasses the read-cache lookup and refreshes the entry (issue #250). */
3356
+ async get(id, opts = {}) {
3357
+ return this.getGlobal(id, opts?.fresh === true);
3195
3358
  }
3196
3359
  /** Create a record (OperationResultModel → { id}). `dryRun: true` returns the
3197
3360
  * pinned envelope (section 19.3) and never issues the create. A 2xx that is not the
@@ -3246,9 +3409,9 @@ var ContactGroupsResource = class extends BaseResource {
3246
3409
  async count(params) {
3247
3410
  return this.countGlobal(params);
3248
3411
  }
3249
- /** Get one record by id (item envelope; item: null → NotFoundError). */
3250
- async get(id) {
3251
- return this.getGlobal(id);
3412
+ /** Get one record by id (item envelope; item: null → NotFoundError). `fresh: true` bypasses the read-cache lookup and refreshes the entry (issue #250). */
3413
+ async get(id, opts = {}) {
3414
+ return this.getGlobal(id, opts?.fresh === true);
3252
3415
  }
3253
3416
  /** Create a record (OperationResultModel → { id}). `dryRun: true` returns the
3254
3417
  * pinned envelope (section 19.3) and never issues the create. A 2xx that is not the
@@ -3571,8 +3734,8 @@ var ContactsResource = class extends BaseResource {
3571
3734
  return this.countGlobal(params);
3572
3735
  }
3573
3736
  /** Get one record by parent + id (/V1.0/Companies/{parentId}/Contacts/{id} — vendor item envelope; item: null → NotFoundError). */
3574
- async get(parentId, id) {
3575
- return this.getScopedRaw(parentId, id);
3737
+ async get(parentId, id, opts = {}) {
3738
+ return this.getScopedRaw(parentId, id, opts?.fresh === true);
3576
3739
  }
3577
3740
  /** Create a record under the parent (OperationResultModel → { id}). `dryRun: true` returns the
3578
3741
  * pinned envelope (section 19.3) and never issues the create. A 2xx that is not the
@@ -3662,9 +3825,9 @@ var ContactWebhooksResource = class extends BaseResource {
3662
3825
  async count(params) {
3663
3826
  return this.countGlobal(params);
3664
3827
  }
3665
- /** Get one record by id (item envelope; item: null → NotFoundError). */
3666
- async get(id) {
3667
- return this.getGlobal(id);
3828
+ /** Get one record by id (item envelope; item: null → NotFoundError). `fresh: true` bypasses the read-cache lookup and refreshes the entry (issue #250). */
3829
+ async get(id, opts = {}) {
3830
+ return this.getGlobal(id, opts?.fresh === true);
3668
3831
  }
3669
3832
  /** Create a record (OperationResultModel → { id}). `dryRun: true` returns the
3670
3833
  * pinned envelope (section 19.3) and never issues the create. A 2xx that is not the
@@ -3737,8 +3900,8 @@ var ContractBillingRulesResource = class extends BaseResource {
3737
3900
  return this.countGlobal(params);
3738
3901
  }
3739
3902
  /** Get one record by parent + id (/V1.0/Contracts/{parentId}/BillingRules/{id} — vendor item envelope; item: null → NotFoundError). */
3740
- async get(parentId, id) {
3741
- return this.getScopedRaw(parentId, id);
3903
+ async get(parentId, id, opts = {}) {
3904
+ return this.getScopedRaw(parentId, id, opts?.fresh === true);
3742
3905
  }
3743
3906
  /** Create a record under the parent (OperationResultModel → { id}). `dryRun: true` returns the
3744
3907
  * pinned envelope (section 19.3) and never issues the create. A 2xx that is not the
@@ -3803,8 +3966,8 @@ var ContractBlockHourFactorsResource = class extends BaseResource {
3803
3966
  return this.countGlobal(params);
3804
3967
  }
3805
3968
  /** Get one record by parent + id (/V1.0/Contracts/{parentId}/BlockHourFactors/{id} — vendor item envelope; item: null → NotFoundError). */
3806
- async get(parentId, id) {
3807
- return this.getScopedRaw(parentId, id);
3969
+ async get(parentId, id, opts = {}) {
3970
+ return this.getScopedRaw(parentId, id, opts?.fresh === true);
3808
3971
  }
3809
3972
  /** Create a record under the parent (OperationResultModel → { id}). `dryRun: true` returns the
3810
3973
  * pinned envelope (section 19.3) and never issues the create. A 2xx that is not the
@@ -3862,8 +4025,8 @@ var ContractBlocksResource = class extends BaseResource {
3862
4025
  return this.countGlobal(params);
3863
4026
  }
3864
4027
  /** Get one record by parent + id (/V1.0/Contracts/{parentId}/Blocks/{id} — vendor item envelope; item: null → NotFoundError). */
3865
- async get(parentId, id) {
3866
- return this.getScopedRaw(parentId, id);
4028
+ async get(parentId, id, opts = {}) {
4029
+ return this.getScopedRaw(parentId, id, opts?.fresh === true);
3867
4030
  }
3868
4031
  /** Create a record under the parent (OperationResultModel → { id}). `dryRun: true` returns the
3869
4032
  * pinned envelope (section 19.3) and never issues the create. A 2xx that is not the
@@ -3922,8 +4085,8 @@ var ContractChargesResource = class extends BaseResource {
3922
4085
  return this.countGlobal(params);
3923
4086
  }
3924
4087
  /** Get one record by parent + id (/V1.0/Contracts/{parentId}/Charges/{id} — vendor item envelope; item: null → NotFoundError). */
3925
- async get(parentId, id) {
3926
- return this.getScopedRaw(parentId, id);
4088
+ async get(parentId, id, opts = {}) {
4089
+ return this.getScopedRaw(parentId, id, opts?.fresh === true);
3927
4090
  }
3928
4091
  /** Create a record under the parent (OperationResultModel → { id}). `dryRun: true` returns the
3929
4092
  * pinned envelope (section 19.3) and never issues the create. A 2xx that is not the
@@ -3992,8 +4155,8 @@ var ContractExclusionBillingCodesResource = class extends BaseResource {
3992
4155
  return this.countGlobal(params);
3993
4156
  }
3994
4157
  /** Get one record by parent + id (/V1.0/Contracts/{parentId}/ExclusionBillingCodes/{id} — vendor item envelope; item: null → NotFoundError). */
3995
- async get(parentId, id) {
3996
- return this.getScopedRaw(parentId, id);
4158
+ async get(parentId, id, opts = {}) {
4159
+ return this.getScopedRaw(parentId, id, opts?.fresh === true);
3997
4160
  }
3998
4161
  /** Create a record under the parent (OperationResultModel → { id}). `dryRun: true` returns the
3999
4162
  * pinned envelope (section 19.3) and never issues the create. A 2xx that is not the
@@ -4049,8 +4212,8 @@ var ContractExclusionRolesResource = class extends BaseResource {
4049
4212
  return this.countGlobal(params);
4050
4213
  }
4051
4214
  /** Get one record by parent + id (/V1.0/Contracts/{parentId}/ExclusionRoles/{id} — vendor item envelope; item: null → NotFoundError). */
4052
- async get(parentId, id) {
4053
- return this.getScopedRaw(parentId, id);
4215
+ async get(parentId, id, opts = {}) {
4216
+ return this.getScopedRaw(parentId, id, opts?.fresh === true);
4054
4217
  }
4055
4218
  /** Create a record under the parent (OperationResultModel → { id}). `dryRun: true` returns the
4056
4219
  * pinned envelope (section 19.3) and never issues the create. A 2xx that is not the
@@ -4106,8 +4269,8 @@ var ContractExclusionSetExcludedRolesResource = class extends BaseResource {
4106
4269
  return this.countGlobal(params);
4107
4270
  }
4108
4271
  /** Get one record by parent + id (/V1.0/ContractExclusionSets/{parentId}/ExcludedRoles/{id} — vendor item envelope; item: null → NotFoundError). */
4109
- async get(parentId, id) {
4110
- return this.getScopedRaw(parentId, id);
4272
+ async get(parentId, id, opts = {}) {
4273
+ return this.getScopedRaw(parentId, id, opts?.fresh === true);
4111
4274
  }
4112
4275
  /** Create a record under the parent (OperationResultModel → { id}). `dryRun: true` returns the
4113
4276
  * pinned envelope (section 19.3) and never issues the create. A 2xx that is not the
@@ -4163,8 +4326,8 @@ var ContractExclusionSetExcludedWorkTypesResource = class extends BaseResource {
4163
4326
  return this.countGlobal(params);
4164
4327
  }
4165
4328
  /** Get one record by parent + id (/V1.0/ContractExclusionSets/{parentId}/ExcludedWorkTypes/{id} — vendor item envelope; item: null → NotFoundError). */
4166
- async get(parentId, id) {
4167
- return this.getScopedRaw(parentId, id);
4329
+ async get(parentId, id, opts = {}) {
4330
+ return this.getScopedRaw(parentId, id, opts?.fresh === true);
4168
4331
  }
4169
4332
  /** Create a record under the parent (OperationResultModel → { id}). `dryRun: true` returns the
4170
4333
  * pinned envelope (section 19.3) and never issues the create. A 2xx that is not the
@@ -4219,9 +4382,9 @@ var ContractExclusionSetsResource = class extends BaseResource {
4219
4382
  async count(params) {
4220
4383
  return this.countGlobal(params);
4221
4384
  }
4222
- /** Get one record by id (item envelope; item: null → NotFoundError). */
4223
- async get(id) {
4224
- return this.getGlobal(id);
4385
+ /** Get one record by id (item envelope; item: null → NotFoundError). `fresh: true` bypasses the read-cache lookup and refreshes the entry (issue #250). */
4386
+ async get(id, opts = {}) {
4387
+ return this.getGlobal(id, opts?.fresh === true);
4225
4388
  }
4226
4389
  /** Create a record (OperationResultModel → { id}). `dryRun: true` returns the
4227
4390
  * pinned envelope (section 19.3) and never issues the create. A 2xx that is not the
@@ -4294,8 +4457,8 @@ var ContractMilestonesResource = class extends BaseResource {
4294
4457
  return this.countGlobal(params);
4295
4458
  }
4296
4459
  /** Get one record by parent + id (/V1.0/Contracts/{parentId}/Milestones/{id} — vendor item envelope; item: null → NotFoundError). */
4297
- async get(parentId, id) {
4298
- return this.getScopedRaw(parentId, id);
4460
+ async get(parentId, id, opts = {}) {
4461
+ return this.getScopedRaw(parentId, id, opts?.fresh === true);
4299
4462
  }
4300
4463
  /** Create a record under the parent (OperationResultModel → { id}). `dryRun: true` returns the
4301
4464
  * pinned envelope (section 19.3) and never issues the create. A 2xx that is not the
@@ -4353,8 +4516,8 @@ var ContractNotesResource = class extends BaseResource {
4353
4516
  return this.countGlobal(params);
4354
4517
  }
4355
4518
  /** Get one record by parent + id (/V1.0/Contracts/{parentId}/Notes/{id} — vendor item envelope; item: null → NotFoundError). */
4356
- async get(parentId, id) {
4357
- return this.getScopedRaw(parentId, id);
4519
+ async get(parentId, id, opts = {}) {
4520
+ return this.getScopedRaw(parentId, id, opts?.fresh === true);
4358
4521
  }
4359
4522
  /** Create a record under the parent (OperationResultModel → { id}). `dryRun: true` returns the
4360
4523
  * pinned envelope (section 19.3) and never issues the create. A 2xx that is not the
@@ -4412,8 +4575,8 @@ var ContractRatesResource = class extends BaseResource {
4412
4575
  return this.countGlobal(params);
4413
4576
  }
4414
4577
  /** Get one record by parent + id (/V1.0/Contracts/{parentId}/Rates/{id} — vendor item envelope; item: null → NotFoundError). */
4415
- async get(parentId, id) {
4416
- return this.getScopedRaw(parentId, id);
4578
+ async get(parentId, id, opts = {}) {
4579
+ return this.getScopedRaw(parentId, id, opts?.fresh === true);
4417
4580
  }
4418
4581
  /** Create a record under the parent (OperationResultModel → { id}). `dryRun: true` returns the
4419
4582
  * pinned envelope (section 19.3) and never issues the create. A 2xx that is not the
@@ -4471,8 +4634,8 @@ var ContractRetainersResource = class extends BaseResource {
4471
4634
  return this.countGlobal(params);
4472
4635
  }
4473
4636
  /** Get one record by parent + id (/V1.0/Contracts/{parentId}/Retainers/{id} — vendor item envelope; item: null → NotFoundError). */
4474
- async get(parentId, id) {
4475
- return this.getScopedRaw(parentId, id);
4637
+ async get(parentId, id, opts = {}) {
4638
+ return this.getScopedRaw(parentId, id, opts?.fresh === true);
4476
4639
  }
4477
4640
  /** Create a record under the parent (OperationResultModel → { id}). `dryRun: true` returns the
4478
4641
  * pinned envelope (section 19.3) and never issues the create. A 2xx that is not the
@@ -4530,8 +4693,8 @@ var ContractRoleCostsResource = class extends BaseResource {
4530
4693
  return this.countGlobal(params);
4531
4694
  }
4532
4695
  /** Get one record by parent + id (/V1.0/Contracts/{parentId}/RoleCosts/{id} — vendor item envelope; item: null → NotFoundError). */
4533
- async get(parentId, id) {
4534
- return this.getScopedRaw(parentId, id);
4696
+ async get(parentId, id, opts = {}) {
4697
+ return this.getScopedRaw(parentId, id, opts?.fresh === true);
4535
4698
  }
4536
4699
  /** Create a record under the parent (OperationResultModel → { id}). `dryRun: true` returns the
4537
4700
  * pinned envelope (section 19.3) and never issues the create. A 2xx that is not the
@@ -4657,8 +4820,8 @@ var ContractServiceBundlesResource = class extends BaseResource {
4657
4820
  return this.countGlobal(params);
4658
4821
  }
4659
4822
  /** Get one record by parent + id (/V1.0/Contracts/{parentId}/ServiceBundles/{id} — vendor item envelope; item: null → NotFoundError). */
4660
- async get(parentId, id) {
4661
- return this.getScopedRaw(parentId, id);
4823
+ async get(parentId, id, opts = {}) {
4824
+ return this.getScopedRaw(parentId, id, opts?.fresh === true);
4662
4825
  }
4663
4826
  /** Create a record under the parent (OperationResultModel → { id}). `dryRun: true` returns the
4664
4827
  * pinned envelope (section 19.3) and never issues the create. A 2xx that is not the
@@ -4716,8 +4879,8 @@ var ContractServiceBundleUnitsResource = class extends BaseResource {
4716
4879
  return this.countGlobal(params);
4717
4880
  }
4718
4881
  /** Get one record by parent + id (/V1.0/Contracts/{parentId}/ServiceBundleUnits/{id} — vendor item envelope; item: null → NotFoundError). */
4719
- async get(parentId, id) {
4720
- return this.getScopedRaw(parentId, id);
4882
+ async get(parentId, id, opts = {}) {
4883
+ return this.getScopedRaw(parentId, id, opts?.fresh === true);
4721
4884
  }
4722
4885
  /** Resolve a ContractServiceBundleUnit from a numeric id (or, where the vendor indexes a primary text field,
4723
4886
  * from a numeric id — this resource has no primary text field). A numeric id miss throws NOT_FOUND;
@@ -4758,8 +4921,8 @@ var ContractServicesResource = class extends BaseResource {
4758
4921
  return this.countGlobal(params);
4759
4922
  }
4760
4923
  /** Get one record by parent + id (/V1.0/Contracts/{parentId}/Services/{id} — vendor item envelope; item: null → NotFoundError). */
4761
- async get(parentId, id) {
4762
- return this.getScopedRaw(parentId, id);
4924
+ async get(parentId, id, opts = {}) {
4925
+ return this.getScopedRaw(parentId, id, opts?.fresh === true);
4763
4926
  }
4764
4927
  /** Create a record under the parent (OperationResultModel → { id}). `dryRun: true` returns the
4765
4928
  * pinned envelope (section 19.3) and never issues the create. A 2xx that is not the
@@ -4817,8 +4980,8 @@ var ContractServiceUnitsResource = class extends BaseResource {
4817
4980
  return this.countGlobal(params);
4818
4981
  }
4819
4982
  /** Get one record by parent + id (/V1.0/Contracts/{parentId}/ServiceUnits/{id} — vendor item envelope; item: null → NotFoundError). */
4820
- async get(parentId, id) {
4821
- return this.getScopedRaw(parentId, id);
4983
+ async get(parentId, id, opts = {}) {
4984
+ return this.getScopedRaw(parentId, id, opts?.fresh === true);
4822
4985
  }
4823
4986
  /** Resolve a ContractServiceUnit from a numeric id (or, where the vendor indexes a primary text field,
4824
4987
  * from a numeric id — this resource has no primary text field). A numeric id miss throws NOT_FOUND;
@@ -4834,11 +4997,11 @@ var ContractServiceUnitsResource = class extends BaseResource {
4834
4997
  };
4835
4998
 
4836
4999
  // src/resources/special/contracts/lineOfBusiness.ts
4837
- var OP3 = "contracts.lineOfBusiness";
5000
+ var OP4 = "contracts.lineOfBusiness";
4838
5001
  function positiveId(value, name) {
4839
5002
  const n = typeof value === "string" && /^[0-9]+$/.test(value.trim()) ? Number(value) : value;
4840
5003
  if (typeof n !== "number" || !Number.isSafeInteger(n) || n < 1) {
4841
- throw new AutotaskConfigError(OP3 + ": " + name + " must be a positive integer id (got " + String(value) + ")", { operation: OP3 });
5004
+ throw new AutotaskConfigError(OP4 + ": " + name + " must be a positive integer id (got " + String(value) + ")", { operation: OP4 });
4842
5005
  }
4843
5006
  return n;
4844
5007
  }
@@ -4864,7 +5027,7 @@ async function lineOfBusiness(resource, contractIdIn, http, associationIdIn) {
4864
5027
  markers: { association: "missing", organizationalLevel2: "missing", organizationalLevel1: "missing" }
4865
5028
  };
4866
5029
  }
4867
- const chain = await resolveLineOfBusinessChain(http, associationId, { budget: 3, operation: OP3, onError: "propagate" });
5030
+ const chain = await resolveLineOfBusinessChain(http, associationId, { budget: 3, operation: OP4, onError: "propagate" });
4868
5031
  const { association, organizationalLevel2, organizationalLevel1, markers } = chain.lineOfBusiness;
4869
5032
  return { contractId, associationSource, association, organizationalLevel2, organizationalLevel1, markers };
4870
5033
  }
@@ -5338,7 +5501,7 @@ function appendWiresNote(wires, note) {
5338
5501
  wires.note = (wires.note ? wires.note + " | " : "") + note;
5339
5502
  }
5340
5503
  function makeFetchCtx(rawHttp, v, contractId, budget) {
5341
- const OP11 = PROFITABILITY_OP;
5504
+ const OP12 = PROFITABILITY_OP;
5342
5505
  const id = parseIdentifier(contractId, "contractId");
5343
5506
  const idNum = typeof id === "number" ? id : Number(id);
5344
5507
  const wires = { issued: 0, requests: 0, budget };
@@ -5350,19 +5513,19 @@ function makeFetchCtx(rawHttp, v, contractId, budget) {
5350
5513
  } };
5351
5514
  const readPart = (path, conditions, fields) => {
5352
5515
  wires.issued += 1;
5353
- return degradable(() => boundedPart(http, path, conditions, v.limit, OP11, fields));
5516
+ return degradable(() => boundedPart(http, path, conditions, v.limit, OP12, fields));
5354
5517
  };
5355
5518
  const truncatedMonths = {};
5356
5519
  const windowedPart = async (name, key, path, cond, fields, dateField) => {
5357
5520
  const first = await readPart(path, cond, fields);
5358
5521
  if (first.absent !== void 0 || !first.hasMore) return { part: stampPart(key, first, cond), rows: first.items };
5359
- const wp = await degradable(() => expandByMonth(http, path, cond, v.limit, OP11, fields, dateField, v.dateFrom, v.dateTo, wires));
5522
+ const wp = await degradable(() => expandByMonth(http, path, cond, v.limit, OP12, fields, dateField, v.dateFrom, v.dateTo, wires));
5360
5523
  if (!("truncatedMonths" in wp)) return { part: stampPart(key, wp, cond), rows: [] };
5361
5524
  const { truncatedMonths: tm, ...part } = wp;
5362
5525
  truncatedMonths[name] = tm;
5363
5526
  return { part, rows: wp.items };
5364
5527
  };
5365
- return { v, OP: OP11, id, idNum, rawHttp, http, wires, windowOn, readPart, windowedPart, truncatedMonths };
5528
+ return { v, OP: OP12, id, idNum, rawHttp, http, wires, windowOn, readPart, windowedPart, truncatedMonths };
5366
5529
  }
5367
5530
 
5368
5531
  // src/resources/special/contracts/profitability.stages.ts
@@ -6324,9 +6487,9 @@ var ContractsResource = class extends BaseResource {
6324
6487
  async count(params) {
6325
6488
  return this.countGlobal(params);
6326
6489
  }
6327
- /** Get one record by id (item envelope; item: null → NotFoundError). */
6328
- async get(id) {
6329
- return this.getGlobal(id);
6490
+ /** Get one record by id (item envelope; item: null → NotFoundError). `fresh: true` bypasses the read-cache lookup and refreshes the entry (issue #250). */
6491
+ async get(id, opts = {}) {
6492
+ return this.getGlobal(id, opts?.fresh === true);
6330
6493
  }
6331
6494
  /** Create a record (OperationResultModel → { id}). `dryRun: true` returns the
6332
6495
  * pinned envelope (section 19.3) and never issues the create. A 2xx that is not the
@@ -6400,8 +6563,8 @@ var ContractTicketPurchasesResource = class extends BaseResource {
6400
6563
  return this.countGlobal(params);
6401
6564
  }
6402
6565
  /** Get one record by parent + id (/V1.0/Contracts/{parentId}/TicketPurchases/{id} — vendor item envelope; item: null → NotFoundError). */
6403
- async get(parentId, id) {
6404
- return this.getScopedRaw(parentId, id);
6566
+ async get(parentId, id, opts = {}) {
6567
+ return this.getScopedRaw(parentId, id, opts?.fresh === true);
6405
6568
  }
6406
6569
  /** Create a record under the parent (OperationResultModel → { id}). `dryRun: true` returns the
6407
6570
  * pinned envelope (section 19.3) and never issues the create. A 2xx that is not the
@@ -6458,9 +6621,9 @@ var CountriesResource = class extends BaseResource {
6458
6621
  async count(params) {
6459
6622
  return this.countGlobal(params);
6460
6623
  }
6461
- /** Get one record by id (item envelope; item: null → NotFoundError). */
6462
- async get(id) {
6463
- return this.getGlobal(id);
6624
+ /** Get one record by id (item envelope; item: null → NotFoundError). `fresh: true` bypasses the read-cache lookup and refreshes the entry (issue #250). */
6625
+ async get(id, opts = {}) {
6626
+ return this.getGlobal(id, opts?.fresh === true);
6464
6627
  }
6465
6628
  /** Update a record (PUT on the COLLECTION — the vendored spec's item path is GET-only; the vendor
6466
6629
  * keys the record by the id in the body). The vendor validates the FULL model on this route (V2), so a
@@ -6515,9 +6678,9 @@ var CurrenciesResource = class extends BaseResource {
6515
6678
  async count(params) {
6516
6679
  return this.countGlobal(params);
6517
6680
  }
6518
- /** Get one record by id (item envelope; item: null → NotFoundError). */
6519
- async get(id) {
6520
- return this.getGlobal(id);
6681
+ /** Get one record by id (item envelope; item: null → NotFoundError). `fresh: true` bypasses the read-cache lookup and refreshes the entry (issue #250). */
6682
+ async get(id, opts = {}) {
6683
+ return this.getGlobal(id, opts?.fresh === true);
6521
6684
  }
6522
6685
  /** Resolve a Currency from a numeric id (or, where the vendor indexes a primary text field,
6523
6686
  * from an exact match on name). A numeric id miss throws NOT_FOUND; a complete
@@ -6561,9 +6724,9 @@ var DepartmentsResource = class extends BaseResource {
6561
6724
  async count(params) {
6562
6725
  return this.countGlobal(params);
6563
6726
  }
6564
- /** Get one record by id (item envelope; item: null → NotFoundError). */
6565
- async get(id) {
6566
- return this.getGlobal(id);
6727
+ /** Get one record by id (item envelope; item: null → NotFoundError). `fresh: true` bypasses the read-cache lookup and refreshes the entry (issue #250). */
6728
+ async get(id, opts = {}) {
6729
+ return this.getGlobal(id, opts?.fresh === true);
6567
6730
  }
6568
6731
  /** Create a record (OperationResultModel → { id}). `dryRun: true` returns the
6569
6732
  * pinned envelope (section 19.3) and never issues the create. A 2xx that is not the
@@ -6628,9 +6791,9 @@ var DomainRegistrarsResource = class extends BaseResource {
6628
6791
  async count(params) {
6629
6792
  return this.countGlobal(params);
6630
6793
  }
6631
- /** Get one record by id (item envelope; item: null → NotFoundError). */
6632
- async get(id) {
6633
- return this.getGlobal(id);
6794
+ /** Get one record by id (item envelope; item: null → NotFoundError). `fresh: true` bypasses the read-cache lookup and refreshes the entry (issue #250). */
6795
+ async get(id, opts = {}) {
6796
+ return this.getGlobal(id, opts?.fresh === true);
6634
6797
  }
6635
6798
  /** Create a record (OperationResultModel → { id}). `dryRun: true` returns the
6636
6799
  * pinned envelope (section 19.3) and never issues the create. A 2xx that is not the
@@ -6713,8 +6876,8 @@ var ExpenseItemAttachmentsResource = class extends BaseResource {
6713
6876
  return this.countGlobal(params);
6714
6877
  }
6715
6878
  /** Get one record by parent + id (/V1.0/ExpenseItems/{parentId}/Attachments/{id} — vendor answers the model directly). */
6716
- async get(parentId, id) {
6717
- return this.getScopedModel(parentId, id);
6879
+ async get(parentId, id, opts = {}) {
6880
+ return this.getScopedModel(parentId, id, opts?.fresh === true);
6718
6881
  }
6719
6882
  /** Create a record under the parent (OperationResultModel → { id}). `dryRun: true` returns the
6720
6883
  * pinned envelope (section 19.3) and never issues the create. A 2xx that is not the
@@ -6773,9 +6936,9 @@ var ExpenseItemsResource = class extends BaseResource {
6773
6936
  async count(params) {
6774
6937
  return this.countGlobal(params);
6775
6938
  }
6776
- /** Get one record by id (item envelope; item: null → NotFoundError). */
6777
- async get(id) {
6778
- return this.getGlobal(id);
6939
+ /** Get one record by id (item envelope; item: null → NotFoundError). `fresh: true` bypasses the read-cache lookup and refreshes the entry (issue #250). */
6940
+ async get(id, opts = {}) {
6941
+ return this.getGlobal(id, opts?.fresh === true);
6779
6942
  }
6780
6943
  /** Create a record under the parent (OperationResultModel → { id}). `dryRun: true` returns the
6781
6944
  * pinned envelope (section 19.3) and never issues the create. A 2xx that is not the
@@ -6832,9 +6995,9 @@ var ExpenseReportsResource = class extends BaseResource {
6832
6995
  async count(params) {
6833
6996
  return this.countGlobal(params);
6834
6997
  }
6835
- /** Get one record by id (item envelope; item: null → NotFoundError). */
6836
- async get(id) {
6837
- return this.getGlobal(id);
6998
+ /** Get one record by id (item envelope; item: null → NotFoundError). `fresh: true` bypasses the read-cache lookup and refreshes the entry (issue #250). */
6999
+ async get(id, opts = {}) {
7000
+ return this.getGlobal(id, opts?.fresh === true);
6838
7001
  }
6839
7002
  /** Create a record (OperationResultModel → { id}). `dryRun: true` returns the
6840
7003
  * pinned envelope (section 19.3) and never issues the create. A 2xx that is not the
@@ -6898,9 +7061,9 @@ var HolidaySetsResource = class extends BaseResource {
6898
7061
  async count(params) {
6899
7062
  return this.countGlobal(params);
6900
7063
  }
6901
- /** Get one record by id (item envelope; item: null → NotFoundError). */
6902
- async get(id) {
6903
- return this.getGlobal(id);
7064
+ /** Get one record by id (item envelope; item: null → NotFoundError). `fresh: true` bypasses the read-cache lookup and refreshes the entry (issue #250). */
7065
+ async get(id, opts = {}) {
7066
+ return this.getGlobal(id, opts?.fresh === true);
6904
7067
  }
6905
7068
  /** Create a record (OperationResultModel → { id}). `dryRun: true` returns the
6906
7069
  * pinned envelope (section 19.3) and never issues the create. A 2xx that is not the
@@ -6969,8 +7132,8 @@ var HolidaysResource = class extends BaseResource {
6969
7132
  return this.countGlobal(params);
6970
7133
  }
6971
7134
  /** Get one record by parent + id (/V1.0/HolidaySets/{parentId}/Holidays/{id} — vendor item envelope; item: null → NotFoundError). */
6972
- async get(parentId, id) {
6973
- return this.getScopedRaw(parentId, id);
7135
+ async get(parentId, id, opts = {}) {
7136
+ return this.getScopedRaw(parentId, id, opts?.fresh === true);
6974
7137
  }
6975
7138
  /** Create a record under the parent (OperationResultModel → { id}). `dryRun: true` returns the
6976
7139
  * pinned envelope (section 19.3) and never issues the create. A 2xx that is not the
@@ -7063,9 +7226,9 @@ var InventoryProductsResource = class extends BaseResource {
7063
7226
  async count(params) {
7064
7227
  return this.countGlobal(params);
7065
7228
  }
7066
- /** Get one record by id (item envelope; item: null → NotFoundError). */
7067
- async get(id) {
7068
- return this.getGlobal(id);
7229
+ /** Get one record by id (item envelope; item: null → NotFoundError). `fresh: true` bypasses the read-cache lookup and refreshes the entry (issue #250). */
7230
+ async get(id, opts = {}) {
7231
+ return this.getGlobal(id, opts?.fresh === true);
7069
7232
  }
7070
7233
  /** Create a record (OperationResultModel → { id}). `dryRun: true` returns the
7071
7234
  * pinned envelope (section 19.3) and never issues the create. A 2xx that is not the
@@ -7199,9 +7362,9 @@ var InvoicesResource = class extends BaseResource {
7199
7362
  async count(params) {
7200
7363
  return this.countGlobal(params);
7201
7364
  }
7202
- /** Get one record by id (item envelope; item: null → NotFoundError). */
7203
- async get(id) {
7204
- return this.getGlobal(id);
7365
+ /** Get one record by id (item envelope; item: null → NotFoundError). `fresh: true` bypasses the read-cache lookup and refreshes the entry (issue #250). */
7366
+ async get(id, opts = {}) {
7367
+ return this.getGlobal(id, opts?.fresh === true);
7205
7368
  }
7206
7369
  /** Update a record (PUT on the COLLECTION — the vendored spec's item path is GET-only; the vendor
7207
7370
  * keys the record by the id in the body). The vendor validates the FULL model on this route (V2), so a
@@ -7311,9 +7474,9 @@ var InvoiceTemplatesResource = class extends BaseResource {
7311
7474
  async count(params) {
7312
7475
  return this.countGlobal(params);
7313
7476
  }
7314
- /** Get one record by id (item envelope; item: null → NotFoundError). */
7315
- async get(id) {
7316
- return this.getGlobal(id);
7477
+ /** Get one record by id (item envelope; item: null → NotFoundError). `fresh: true` bypasses the read-cache lookup and refreshes the entry (issue #250). */
7478
+ async get(id, opts = {}) {
7479
+ return this.getGlobal(id, opts?.fresh === true);
7317
7480
  }
7318
7481
  };
7319
7482
 
@@ -7355,9 +7518,9 @@ var NotificationHistoryResource = class extends BaseResource {
7355
7518
  async count(params) {
7356
7519
  return this.countGlobal(params);
7357
7520
  }
7358
- /** Get one record by id (item envelope; item: null → NotFoundError). */
7359
- async get(id) {
7360
- return this.getGlobal(id);
7521
+ /** Get one record by id (item envelope; item: null → NotFoundError). `fresh: true` bypasses the read-cache lookup and refreshes the entry (issue #250). */
7522
+ async get(id, opts = {}) {
7523
+ return this.getGlobal(id, opts?.fresh === true);
7361
7524
  }
7362
7525
  /** Resolve a NotificationHistory from a numeric id (or, where the vendor indexes a primary text field,
7363
7526
  * from a numeric id — this resource has no primary text field). A numeric id miss throws NOT_FOUND;
@@ -7396,9 +7559,9 @@ var OpportunitiesResource = class extends BaseResource {
7396
7559
  async count(params) {
7397
7560
  return this.countGlobal(params);
7398
7561
  }
7399
- /** Get one record by id (item envelope; item: null → NotFoundError). */
7400
- async get(id) {
7401
- return this.getGlobal(id);
7562
+ /** Get one record by id (item envelope; item: null → NotFoundError). `fresh: true` bypasses the read-cache lookup and refreshes the entry (issue #250). */
7563
+ async get(id, opts = {}) {
7564
+ return this.getGlobal(id, opts?.fresh === true);
7402
7565
  }
7403
7566
  /** Create a record (OperationResultModel → { id}). `dryRun: true` returns the
7404
7567
  * pinned envelope (section 19.3) and never issues the create. A 2xx that is not the
@@ -7461,8 +7624,8 @@ var OpportunityAttachmentsResource = class extends BaseResource {
7461
7624
  return this.countGlobal(params);
7462
7625
  }
7463
7626
  /** Get one record by parent + id (/V1.0/Opportunities/{parentId}/Attachments/{id} — vendor answers the model directly). */
7464
- async get(parentId, id) {
7465
- return this.getScopedModel(parentId, id);
7627
+ async get(parentId, id, opts = {}) {
7628
+ return this.getScopedModel(parentId, id, opts?.fresh === true);
7466
7629
  }
7467
7630
  /** Create a record under the parent (OperationResultModel → { id}). `dryRun: true` returns the
7468
7631
  * pinned envelope (section 19.3) and never issues the create. A 2xx that is not the
@@ -7521,9 +7684,9 @@ var OpportunityCategoriesResource = class extends BaseResource {
7521
7684
  async count(params) {
7522
7685
  return this.countGlobal(params);
7523
7686
  }
7524
- /** Get one record by id (item envelope; item: null → NotFoundError). */
7525
- async get(id) {
7526
- return this.getGlobal(id);
7687
+ /** Get one record by id (item envelope; item: null → NotFoundError). `fresh: true` bypasses the read-cache lookup and refreshes the entry (issue #250). */
7688
+ async get(id, opts = {}) {
7689
+ return this.getGlobal(id, opts?.fresh === true);
7527
7690
  }
7528
7691
  /** Update a record (PUT on the COLLECTION — the vendored spec's item path is GET-only; the vendor
7529
7692
  * keys the record by the id in the body). The vendor validates the FULL model on this route (V2), so a
@@ -7579,9 +7742,9 @@ var OrganizationalLevel1sResource = class extends BaseResource {
7579
7742
  async count(params) {
7580
7743
  return this.countGlobal(params);
7581
7744
  }
7582
- /** Get one record by id (item envelope; item: null → NotFoundError). */
7583
- async get(id) {
7584
- return this.getGlobal(id);
7745
+ /** Get one record by id (item envelope; item: null → NotFoundError). `fresh: true` bypasses the read-cache lookup and refreshes the entry (issue #250). */
7746
+ async get(id, opts = {}) {
7747
+ return this.getGlobal(id, opts?.fresh === true);
7585
7748
  }
7586
7749
  /** Create a record (OperationResultModel → { id}). `dryRun: true` returns the
7587
7750
  * pinned envelope (section 19.3) and never issues the create. A 2xx that is not the
@@ -7630,9 +7793,9 @@ var OrganizationalLevel2sResource = class extends BaseResource {
7630
7793
  async count(params) {
7631
7794
  return this.countGlobal(params);
7632
7795
  }
7633
- /** Get one record by id (item envelope; item: null → NotFoundError). */
7634
- async get(id) {
7635
- return this.getGlobal(id);
7796
+ /** Get one record by id (item envelope; item: null → NotFoundError). `fresh: true` bypasses the read-cache lookup and refreshes the entry (issue #250). */
7797
+ async get(id, opts = {}) {
7798
+ return this.getGlobal(id, opts?.fresh === true);
7636
7799
  }
7637
7800
  /** Create a record (OperationResultModel → { id}). `dryRun: true` returns the
7638
7801
  * pinned envelope (section 19.3) and never issues the create. A 2xx that is not the
@@ -7681,9 +7844,9 @@ var OrganizationalLevelAssociationsResource = class extends BaseResource {
7681
7844
  async count(params) {
7682
7845
  return this.countGlobal(params);
7683
7846
  }
7684
- /** Get one record by id (item envelope; item: null → NotFoundError). */
7685
- async get(id) {
7686
- return this.getGlobal(id);
7847
+ /** Get one record by id (item envelope; item: null → NotFoundError). `fresh: true` bypasses the read-cache lookup and refreshes the entry (issue #250). */
7848
+ async get(id, opts = {}) {
7849
+ return this.getGlobal(id, opts?.fresh === true);
7687
7850
  }
7688
7851
  /** Create a record (OperationResultModel → { id}). `dryRun: true` returns the
7689
7852
  * pinned envelope (section 19.3) and never issues the create. A 2xx that is not the
@@ -7734,8 +7897,8 @@ var PhasesResource = class extends BaseResource {
7734
7897
  return this.countGlobal(params);
7735
7898
  }
7736
7899
  /** Get one record by parent + id (/V1.0/Projects/{parentId}/Phases/{id} — vendor item envelope; item: null → NotFoundError). */
7737
- async get(parentId, id) {
7738
- return this.getScopedRaw(parentId, id);
7900
+ async get(parentId, id, opts = {}) {
7901
+ return this.getScopedRaw(parentId, id, opts?.fresh === true);
7739
7902
  }
7740
7903
  /** Create a record under the parent (OperationResultModel → { id}). `dryRun: true` returns the
7741
7904
  * pinned envelope (section 19.3) and never issues the create. A 2xx that is not the
@@ -7792,9 +7955,9 @@ var ProductsResource = class extends BaseResource {
7792
7955
  async count(params) {
7793
7956
  return this.countGlobal(params);
7794
7957
  }
7795
- /** Get one record by id (item envelope; item: null → NotFoundError). */
7796
- async get(id) {
7797
- return this.getGlobal(id);
7958
+ /** Get one record by id (item envelope; item: null → NotFoundError). `fresh: true` bypasses the read-cache lookup and refreshes the entry (issue #250). */
7959
+ async get(id, opts = {}) {
7960
+ return this.getGlobal(id, opts?.fresh === true);
7798
7961
  }
7799
7962
  /** Create a record (OperationResultModel → { id}). `dryRun: true` returns the
7800
7963
  * pinned envelope (section 19.3) and never issues the create. A 2xx that is not the
@@ -7860,8 +8023,8 @@ var ProductVendorsResource = class extends BaseResource {
7860
8023
  return this.countGlobal(params);
7861
8024
  }
7862
8025
  /** Get one record by parent + id (/V1.0/Products/{parentId}/Vendors/{id} — vendor item envelope; item: null → NotFoundError). */
7863
- async get(parentId, id) {
7864
- return this.getScopedRaw(parentId, id);
8026
+ async get(parentId, id, opts = {}) {
8027
+ return this.getScopedRaw(parentId, id, opts?.fresh === true);
7865
8028
  }
7866
8029
  /** Create a record under the parent (OperationResultModel → { id}). `dryRun: true` returns the
7867
8030
  * pinned envelope (section 19.3) and never issues the create. A 2xx that is not the
@@ -7920,8 +8083,8 @@ var ProjectChargesResource = class extends BaseResource {
7920
8083
  return this.countGlobal(params);
7921
8084
  }
7922
8085
  /** Get one record by parent + id (/V1.0/Projects/{parentId}/Charges/{id} — vendor item envelope; item: null → NotFoundError). */
7923
- async get(parentId, id) {
7924
- return this.getScopedRaw(parentId, id);
8086
+ async get(parentId, id, opts = {}) {
8087
+ return this.getScopedRaw(parentId, id, opts?.fresh === true);
7925
8088
  }
7926
8089
  /** Create a record under the parent (OperationResultModel → { id}). `dryRun: true` returns the
7927
8090
  * pinned envelope (section 19.3) and never issues the create. A 2xx that is not the
@@ -7990,8 +8153,8 @@ var ProjectNotesResource = class extends BaseResource {
7990
8153
  return this.countGlobal(params);
7991
8154
  }
7992
8155
  /** Get one record by parent + id (/V1.0/Projects/{parentId}/Notes/{id} — vendor item envelope; item: null → NotFoundError). */
7993
- async get(parentId, id) {
7994
- return this.getScopedRaw(parentId, id);
8156
+ async get(parentId, id, opts = {}) {
8157
+ return this.getScopedRaw(parentId, id, opts?.fresh === true);
7995
8158
  }
7996
8159
  /** Create a record under the parent (OperationResultModel → { id}). `dryRun: true` returns the
7997
8160
  * pinned envelope (section 19.3) and never issues the create. A 2xx that is not the
@@ -8048,9 +8211,9 @@ var ProjectsResource = class extends BaseResource {
8048
8211
  async count(params) {
8049
8212
  return this.countGlobal(params);
8050
8213
  }
8051
- /** Get one record by id (item envelope; item: null → NotFoundError). */
8052
- async get(id) {
8053
- return this.getGlobal(id);
8214
+ /** Get one record by id (item envelope; item: null → NotFoundError). `fresh: true` bypasses the read-cache lookup and refreshes the entry (issue #250). */
8215
+ async get(id, opts = {}) {
8216
+ return this.getGlobal(id, opts?.fresh === true);
8054
8217
  }
8055
8218
  /** Create a record (OperationResultModel → { id}). `dryRun: true` returns the
8056
8219
  * pinned envelope (section 19.3) and never issues the create. A 2xx that is not the
@@ -8139,9 +8302,9 @@ var PurchaseApprovalsResource = class extends BaseResource {
8139
8302
  async count(params) {
8140
8303
  return this.countGlobal(params);
8141
8304
  }
8142
- /** Get one record by id (item envelope; item: null → NotFoundError). */
8143
- async get(id) {
8144
- return this.getGlobal(id);
8305
+ /** Get one record by id (item envelope; item: null → NotFoundError). `fresh: true` bypasses the read-cache lookup and refreshes the entry (issue #250). */
8306
+ async get(id, opts = {}) {
8307
+ return this.getGlobal(id, opts?.fresh === true);
8145
8308
  }
8146
8309
  /** Update a record (PUT on the COLLECTION — the vendored spec's item path is GET-only; the vendor
8147
8310
  * keys the record by the id in the body). The vendor validates the FULL model on this route (V2), so a
@@ -8195,8 +8358,8 @@ var PurchaseOrderItemReceivingResource = class extends BaseResource {
8195
8358
  return this.countGlobal(params);
8196
8359
  }
8197
8360
  /** Get one record by parent + id (/V1.0/PurchaseOrderItems/{parentId}/Receiving/{id} — vendor item envelope; item: null → NotFoundError). */
8198
- async get(parentId, id) {
8199
- return this.getScopedRaw(parentId, id);
8361
+ async get(parentId, id, opts = {}) {
8362
+ return this.getScopedRaw(parentId, id, opts?.fresh === true);
8200
8363
  }
8201
8364
  /** Create a record under the parent (OperationResultModel → { id}). `dryRun: true` returns the
8202
8365
  * pinned envelope (section 19.3) and never issues the create. A 2xx that is not the
@@ -8245,8 +8408,8 @@ var PurchaseOrderItemsResource = class extends BaseResource {
8245
8408
  return this.countGlobal(params);
8246
8409
  }
8247
8410
  /** Get one record by parent + id (/V1.0/PurchaseOrders/{parentId}/Items/{id} — vendor item envelope; item: null → NotFoundError). */
8248
- async get(parentId, id) {
8249
- return this.getScopedRaw(parentId, id);
8411
+ async get(parentId, id, opts = {}) {
8412
+ return this.getScopedRaw(parentId, id, opts?.fresh === true);
8250
8413
  }
8251
8414
  /** Create a record under the parent (OperationResultModel → { id}). `dryRun: true` returns the
8252
8415
  * pinned envelope (section 19.3) and never issues the create. A 2xx that is not the
@@ -8302,9 +8465,9 @@ var PurchaseOrdersResource = class extends BaseResource {
8302
8465
  async count(params) {
8303
8466
  return this.countGlobal(params);
8304
8467
  }
8305
- /** Get one record by id (item envelope; item: null → NotFoundError). */
8306
- async get(id) {
8307
- return this.getGlobal(id);
8468
+ /** Get one record by id (item envelope; item: null → NotFoundError). `fresh: true` bypasses the read-cache lookup and refreshes the entry (issue #250). */
8469
+ async get(id, opts = {}) {
8470
+ return this.getGlobal(id, opts?.fresh === true);
8308
8471
  }
8309
8472
  /** Create a record (OperationResultModel → { id}). `dryRun: true` returns the
8310
8473
  * pinned envelope (section 19.3) and never issues the create. A 2xx that is not the
@@ -8367,8 +8530,8 @@ var QuoteItemsResource = class extends BaseResource {
8367
8530
  return this.countGlobal(params);
8368
8531
  }
8369
8532
  /** Get one record by parent + id (/V1.0/Quotes/{parentId}/Items/{id} — vendor item envelope; item: null → NotFoundError). */
8370
- async get(parentId, id) {
8371
- return this.getScopedRaw(parentId, id);
8533
+ async get(parentId, id, opts = {}) {
8534
+ return this.getScopedRaw(parentId, id, opts?.fresh === true);
8372
8535
  }
8373
8536
  /** Create a record under the parent (OperationResultModel → { id}). `dryRun: true` returns the
8374
8537
  * pinned envelope (section 19.3) and never issues the create. A 2xx that is not the
@@ -8438,9 +8601,9 @@ var QuoteLocationsResource = class extends BaseResource {
8438
8601
  async count(params) {
8439
8602
  return this.countGlobal(params);
8440
8603
  }
8441
- /** Get one record by id (item envelope; item: null → NotFoundError). */
8442
- async get(id) {
8443
- return this.getGlobal(id);
8604
+ /** Get one record by id (item envelope; item: null → NotFoundError). `fresh: true` bypasses the read-cache lookup and refreshes the entry (issue #250). */
8605
+ async get(id, opts = {}) {
8606
+ return this.getGlobal(id, opts?.fresh === true);
8444
8607
  }
8445
8608
  /** Create a record (OperationResultModel → { id}). `dryRun: true` returns the
8446
8609
  * pinned envelope (section 19.3) and never issues the create. A 2xx that is not the
@@ -8501,9 +8664,9 @@ var QuotesResource = class extends BaseResource {
8501
8664
  async count(params) {
8502
8665
  return this.countGlobal(params);
8503
8666
  }
8504
- /** Get one record by id (item envelope; item: null → NotFoundError). */
8505
- async get(id) {
8506
- return this.getGlobal(id);
8667
+ /** Get one record by id (item envelope; item: null → NotFoundError). `fresh: true` bypasses the read-cache lookup and refreshes the entry (issue #250). */
8668
+ async get(id, opts = {}) {
8669
+ return this.getGlobal(id, opts?.fresh === true);
8507
8670
  }
8508
8671
  /** Create a record (OperationResultModel → { id}). `dryRun: true` returns the
8509
8672
  * pinned envelope (section 19.3) and never issues the create. A 2xx that is not the
@@ -8566,9 +8729,9 @@ var QuoteTemplatesResource = class extends BaseResource {
8566
8729
  async count(params) {
8567
8730
  return this.countGlobal(params);
8568
8731
  }
8569
- /** Get one record by id (item envelope; item: null → NotFoundError). */
8570
- async get(id) {
8571
- return this.getGlobal(id);
8732
+ /** Get one record by id (item envelope; item: null → NotFoundError). `fresh: true` bypasses the read-cache lookup and refreshes the entry (issue #250). */
8733
+ async get(id, opts = {}) {
8734
+ return this.getGlobal(id, opts?.fresh === true);
8572
8735
  }
8573
8736
  /** Resolve a QuoteTemplate from a numeric id (or, where the vendor indexes a primary text field,
8574
8737
  * from an exact match on name). A numeric id miss throws NOT_FOUND; a complete
@@ -8613,8 +8776,8 @@ var ResourceRoleQueuesResource = class extends BaseResource {
8613
8776
  return this.countGlobal(params);
8614
8777
  }
8615
8778
  /** Get one record by parent + id (/V1.0/Resources/{parentId}/RoleQueues/{id} — vendor item envelope; item: null → NotFoundError). */
8616
- async get(parentId, id) {
8617
- return this.getScopedRaw(parentId, id);
8779
+ async get(parentId, id, opts = {}) {
8780
+ return this.getScopedRaw(parentId, id, opts?.fresh === true);
8618
8781
  }
8619
8782
  /** Create a record under the parent (OperationResultModel → { id}). `dryRun: true` returns the
8620
8783
  * pinned envelope (section 19.3) and never issues the create. A 2xx that is not the
@@ -8672,8 +8835,8 @@ var ResourceRolesResource = class extends BaseResource {
8672
8835
  return this.countGlobal(params);
8673
8836
  }
8674
8837
  /** Get one record by parent + id (/V1.0/Resources/{parentId}/Roles/{id} — vendor item envelope; item: null → NotFoundError). */
8675
- async get(parentId, id) {
8676
- return this.getScopedRaw(parentId, id);
8838
+ async get(parentId, id, opts = {}) {
8839
+ return this.getScopedRaw(parentId, id, opts?.fresh === true);
8677
8840
  }
8678
8841
  /** Resolve a ResourceRole from a numeric id (or, where the vendor indexes a primary text field,
8679
8842
  * from a numeric id — this resource has no primary text field). A numeric id miss throws NOT_FOUND;
@@ -8714,8 +8877,8 @@ var ResourceSkillsResource = class extends BaseResource {
8714
8877
  return this.countGlobal(params);
8715
8878
  }
8716
8879
  /** Get one record by parent + id (/V1.0/Resources/{parentId}/Skills/{id} — vendor item envelope; item: null → NotFoundError). */
8717
- async get(parentId, id) {
8718
- return this.getScopedRaw(parentId, id);
8880
+ async get(parentId, id, opts = {}) {
8881
+ return this.getScopedRaw(parentId, id, opts?.fresh === true);
8719
8882
  }
8720
8883
  /** Update a record under the parent (PATCH on the collection — swagger documents put+patch there;
8721
8884
  * the vendor keys the record by the id in the body; OperationResultModel → { id}). `dryRun: true` returns
@@ -8873,12 +9036,9 @@ var ResourcesResource = class extends BaseResource {
8873
9036
  async count(params) {
8874
9037
  return this.countGlobal(params);
8875
9038
  }
8876
- /** Get one record by id (item envelope; item: null → NotFoundError).
8877
- * `fresh: true` in the opts bag bypasses AND refreshes the ReadCache entry for this id
8878
- * (the per-id authority read of operations.expandResourceNames with fresh: true — issue #77);
8879
- * a plain get is the bit-for-bit cached read. */
9039
+ /** Get one record by id (item envelope; item: null → NotFoundError). `fresh: true` bypasses the read-cache lookup and refreshes the entry (issue #250). */
8880
9040
  async get(id, opts = {}) {
8881
- return this.getGlobal(id, opts.fresh === true);
9041
+ return this.getGlobal(id, opts?.fresh === true);
8882
9042
  }
8883
9043
  /** Update a record (PUT on the COLLECTION — the vendored spec's item path is GET-only; the vendor
8884
9044
  * keys the record by the id in the body). The vendor validates the FULL model on this route (V2), so a
@@ -9002,8 +9162,8 @@ var ResourceTimeOffApproversResource = class extends BaseResource {
9002
9162
  return this.countGlobal(params);
9003
9163
  }
9004
9164
  /** Get one record by parent + id (/V1.0/Resources/{parentId}/TimeOffApprovers/{id} — vendor item envelope; item: null → NotFoundError). */
9005
- async get(parentId, id) {
9006
- return this.getScopedRaw(parentId, id);
9165
+ async get(parentId, id, opts = {}) {
9166
+ return this.getScopedRaw(parentId, id, opts?.fresh === true);
9007
9167
  }
9008
9168
  /** Resolve a ResourceTimeOffApprover from a numeric id (or, where the vendor indexes a primary text field,
9009
9169
  * from a numeric id — this resource has no primary text field). A numeric id miss throws NOT_FOUND;
@@ -9055,8 +9215,8 @@ var ResourceTimeOffBalancesResource = class extends BaseResource {
9055
9215
  }, pageSize);
9056
9216
  }
9057
9217
  /** Get one record by parent + id (/V1.0/Resources/{parentId}/TimeOffBalances/{id} — vendor item envelope; item: null → NotFoundError). */
9058
- async get(parentId, id) {
9059
- return this.getScopedRaw(parentId, id);
9218
+ async get(parentId, id, opts = {}) {
9219
+ return this.getScopedRaw(parentId, id, opts?.fresh === true);
9060
9220
  }
9061
9221
  /** Resolve a ResourceTimeOffBalance from a numeric id (or, where the vendor indexes a primary text field,
9062
9222
  * from a numeric id — this resource has no primary text field). A numeric id miss throws NOT_FOUND;
@@ -9104,9 +9264,9 @@ var RolesResource = class extends BaseResource {
9104
9264
  async count(params) {
9105
9265
  return this.countGlobal(params);
9106
9266
  }
9107
- /** Get one record by id (item envelope; item: null → NotFoundError). */
9108
- async get(id) {
9109
- return this.getGlobal(id);
9267
+ /** Get one record by id (item envelope; item: null → NotFoundError). `fresh: true` bypasses the read-cache lookup and refreshes the entry (issue #250). */
9268
+ async get(id, opts = {}) {
9269
+ return this.getGlobal(id, opts?.fresh === true);
9110
9270
  }
9111
9271
  /** Create a record (OperationResultModel → { id}). `dryRun: true` returns the
9112
9272
  * pinned envelope (section 19.3) and never issues the create. A 2xx that is not the
@@ -9170,9 +9330,9 @@ var SalesOrdersResource = class extends BaseResource {
9170
9330
  async count(params) {
9171
9331
  return this.countGlobal(params);
9172
9332
  }
9173
- /** Get one record by id (item envelope; item: null → NotFoundError). */
9174
- async get(id) {
9175
- return this.getGlobal(id);
9333
+ /** Get one record by id (item envelope; item: null → NotFoundError). `fresh: true` bypasses the read-cache lookup and refreshes the entry (issue #250). */
9334
+ async get(id, opts = {}) {
9335
+ return this.getGlobal(id, opts?.fresh === true);
9176
9336
  }
9177
9337
  /** Update a record (PUT on the COLLECTION — the vendored spec's item path is GET-only; the vendor
9178
9338
  * keys the record by the id in the body). The vendor validates the FULL model on this route (V2), so a
@@ -9213,9 +9373,9 @@ var ServiceCallsResource = class extends BaseResource {
9213
9373
  async count(params) {
9214
9374
  return this.countGlobal(params);
9215
9375
  }
9216
- /** Get one record by id (item envelope; item: null → NotFoundError). */
9217
- async get(id) {
9218
- return this.getGlobal(id);
9376
+ /** Get one record by id (item envelope; item: null → NotFoundError). `fresh: true` bypasses the read-cache lookup and refreshes the entry (issue #250). */
9377
+ async get(id, opts = {}) {
9378
+ return this.getGlobal(id, opts?.fresh === true);
9219
9379
  }
9220
9380
  /** Create a record (OperationResultModel → { id}). `dryRun: true` returns the
9221
9381
  * pinned envelope (section 19.3) and never issues the create. A 2xx that is not the
@@ -9284,8 +9444,8 @@ var ServiceCallTaskResourcesResource = class extends BaseResource {
9284
9444
  return this.countGlobal(params);
9285
9445
  }
9286
9446
  /** Get one record by parent + id (/V1.0/ServiceCallTasks/{parentId}/Resources/{id} — vendor item envelope; item: null → NotFoundError). */
9287
- async get(parentId, id) {
9288
- return this.getScopedRaw(parentId, id);
9447
+ async get(parentId, id, opts = {}) {
9448
+ return this.getScopedRaw(parentId, id, opts?.fresh === true);
9289
9449
  }
9290
9450
  /** Create a record under the parent (OperationResultModel → { id}). `dryRun: true` returns the
9291
9451
  * pinned envelope (section 19.3) and never issues the create. A 2xx that is not the
@@ -9341,8 +9501,8 @@ var ServiceCallTasksResource = class extends BaseResource {
9341
9501
  return this.countGlobal(params);
9342
9502
  }
9343
9503
  /** Get one record by parent + id (/V1.0/ServiceCalls/{parentId}/Tasks/{id} — vendor item envelope; item: null → NotFoundError). */
9344
- async get(parentId, id) {
9345
- return this.getScopedRaw(parentId, id);
9504
+ async get(parentId, id, opts = {}) {
9505
+ return this.getScopedRaw(parentId, id, opts?.fresh === true);
9346
9506
  }
9347
9507
  /** Create a record under the parent (OperationResultModel → { id}). `dryRun: true` returns the
9348
9508
  * pinned envelope (section 19.3) and never issues the create. A 2xx that is not the
@@ -9398,8 +9558,8 @@ var ServiceCallTicketResourcesResource = class extends BaseResource {
9398
9558
  return this.countGlobal(params);
9399
9559
  }
9400
9560
  /** Get one record by parent + id (/V1.0/ServiceCallTickets/{parentId}/Resources/{id} — vendor item envelope; item: null → NotFoundError). */
9401
- async get(parentId, id) {
9402
- return this.getScopedRaw(parentId, id);
9561
+ async get(parentId, id, opts = {}) {
9562
+ return this.getScopedRaw(parentId, id, opts?.fresh === true);
9403
9563
  }
9404
9564
  /** Create a record under the parent (OperationResultModel → { id}). `dryRun: true` returns the
9405
9565
  * pinned envelope (section 19.3) and never issues the create. A 2xx that is not the
@@ -9455,8 +9615,8 @@ var ServiceCallTicketsResource = class extends BaseResource {
9455
9615
  return this.countGlobal(params);
9456
9616
  }
9457
9617
  /** Get one record by parent + id (/V1.0/ServiceCalls/{parentId}/Tickets/{id} — vendor item envelope; item: null → NotFoundError). */
9458
- async get(parentId, id) {
9459
- return this.getScopedRaw(parentId, id);
9618
+ async get(parentId, id, opts = {}) {
9619
+ return this.getScopedRaw(parentId, id, opts?.fresh === true);
9460
9620
  }
9461
9621
  /** Create a record under the parent (OperationResultModel → { id}). `dryRun: true` returns the
9462
9622
  * pinned envelope (section 19.3) and never issues the create. A 2xx that is not the
@@ -9508,9 +9668,9 @@ var ServiceLevelAgreementResultsResource = class extends BaseResource {
9508
9668
  async count(params) {
9509
9669
  return this.countGlobal(params);
9510
9670
  }
9511
- /** Get one record by id (item envelope; item: null → NotFoundError). */
9512
- async get(id) {
9513
- return this.getGlobal(id);
9671
+ /** Get one record by id (item envelope; item: null → NotFoundError). `fresh: true` bypasses the read-cache lookup and refreshes the entry (issue #250). */
9672
+ async get(id, opts = {}) {
9673
+ return this.getGlobal(id, opts?.fresh === true);
9514
9674
  }
9515
9675
  /** Resolve a ServiceLevelAgreementResults from a numeric id (or, where the vendor indexes a primary text field,
9516
9676
  * from a numeric id — this resource has no primary text field). A numeric id miss throws NOT_FOUND;
@@ -9551,9 +9711,9 @@ var ServicesResource = class extends BaseResource {
9551
9711
  async count(params) {
9552
9712
  return this.countGlobal(params);
9553
9713
  }
9554
- /** Get one record by id (item envelope; item: null → NotFoundError). */
9555
- async get(id) {
9556
- return this.getGlobal(id);
9714
+ /** Get one record by id (item envelope; item: null → NotFoundError). `fresh: true` bypasses the read-cache lookup and refreshes the entry (issue #250). */
9715
+ async get(id, opts = {}) {
9716
+ return this.getGlobal(id, opts?.fresh === true);
9557
9717
  }
9558
9718
  /** Create a record (OperationResultModel → { id}). `dryRun: true` returns the
9559
9719
  * pinned envelope (section 19.3) and never issues the create. A 2xx that is not the
@@ -9616,9 +9776,9 @@ var SkillsResource = class extends BaseResource {
9616
9776
  async count(params) {
9617
9777
  return this.countGlobal(params);
9618
9778
  }
9619
- /** Get one record by id (item envelope; item: null → NotFoundError). */
9620
- async get(id) {
9621
- return this.getGlobal(id);
9779
+ /** Get one record by id (item envelope; item: null → NotFoundError). `fresh: true` bypasses the read-cache lookup and refreshes the entry (issue #250). */
9780
+ async get(id, opts = {}) {
9781
+ return this.getGlobal(id, opts?.fresh === true);
9622
9782
  }
9623
9783
  /** Resolve a Skill from a numeric id (or, where the vendor indexes a primary text field,
9624
9784
  * from an exact match on name). A numeric id miss throws NOT_FOUND; a complete
@@ -9659,9 +9819,9 @@ var SubscriptionPeriodsResource = class extends BaseResource {
9659
9819
  async count(params) {
9660
9820
  return this.countGlobal(params);
9661
9821
  }
9662
- /** Get one record by id (item envelope; item: null → NotFoundError). */
9663
- async get(id) {
9664
- return this.getGlobal(id);
9822
+ /** Get one record by id (item envelope; item: null → NotFoundError). `fresh: true` bypasses the read-cache lookup and refreshes the entry (issue #250). */
9823
+ async get(id, opts = {}) {
9824
+ return this.getGlobal(id, opts?.fresh === true);
9665
9825
  }
9666
9826
  /** Resolve a SubscriptionPeriod from a numeric id (or, where the vendor indexes a primary text field,
9667
9827
  * from a numeric id — this resource has no primary text field). A numeric id miss throws NOT_FOUND;
@@ -9700,9 +9860,9 @@ var SubscriptionsResource = class extends BaseResource {
9700
9860
  async count(params) {
9701
9861
  return this.countGlobal(params);
9702
9862
  }
9703
- /** Get one record by id (item envelope; item: null → NotFoundError). */
9704
- async get(id) {
9705
- return this.getGlobal(id);
9863
+ /** Get one record by id (item envelope; item: null → NotFoundError). `fresh: true` bypasses the read-cache lookup and refreshes the entry (issue #250). */
9864
+ async get(id, opts = {}) {
9865
+ return this.getGlobal(id, opts?.fresh === true);
9706
9866
  }
9707
9867
  /** Create a record (OperationResultModel → { id}). `dryRun: true` returns the
9708
9868
  * pinned envelope (section 19.3) and never issues the create. A 2xx that is not the
@@ -9767,9 +9927,9 @@ var SurveyResultsResource = class extends BaseResource {
9767
9927
  async count(params) {
9768
9928
  return this.countGlobal(params);
9769
9929
  }
9770
- /** Get one record by id (item envelope; item: null → NotFoundError). */
9771
- async get(id) {
9772
- return this.getGlobal(id);
9930
+ /** Get one record by id (item envelope; item: null → NotFoundError). `fresh: true` bypasses the read-cache lookup and refreshes the entry (issue #250). */
9931
+ async get(id, opts = {}) {
9932
+ return this.getGlobal(id, opts?.fresh === true);
9773
9933
  }
9774
9934
  /** Resolve a SurveyResults from a numeric id (or, where the vendor indexes a primary text field,
9775
9935
  * from a numeric id — this resource has no primary text field). A numeric id miss throws NOT_FOUND;
@@ -9807,9 +9967,9 @@ var SurveysResource = class extends BaseResource {
9807
9967
  async count(params) {
9808
9968
  return this.countGlobal(params);
9809
9969
  }
9810
- /** Get one record by id (item envelope; item: null → NotFoundError). */
9811
- async get(id) {
9812
- return this.getGlobal(id);
9970
+ /** Get one record by id (item envelope; item: null → NotFoundError). `fresh: true` bypasses the read-cache lookup and refreshes the entry (issue #250). */
9971
+ async get(id, opts = {}) {
9972
+ return this.getGlobal(id, opts?.fresh === true);
9813
9973
  }
9814
9974
  /** Resolve a Survey from a numeric id (or, where the vendor indexes a primary text field,
9815
9975
  * from an exact match on name). A numeric id miss throws NOT_FOUND; a complete
@@ -9854,8 +10014,8 @@ var TagAliasesResource = class extends BaseResource {
9854
10014
  return this.countGlobal(params);
9855
10015
  }
9856
10016
  /** Get one record by parent + id (/V1.0/Tags/{parentId}/Aliases/{id} — vendor item envelope; item: null → NotFoundError). */
9857
- async get(parentId, id) {
9858
- return this.getScopedRaw(parentId, id);
10017
+ async get(parentId, id, opts = {}) {
10018
+ return this.getScopedRaw(parentId, id, opts?.fresh === true);
9859
10019
  }
9860
10020
  /** Create a record under the parent (OperationResultModel → { id}). `dryRun: true` returns the
9861
10021
  * pinned envelope (section 19.3) and never issues the create. A 2xx that is not the
@@ -9909,9 +10069,9 @@ var TagGroupsResource = class extends BaseResource {
9909
10069
  async count(params) {
9910
10070
  return this.countGlobal(params);
9911
10071
  }
9912
- /** Get one record by id (item envelope; item: null → NotFoundError). */
9913
- async get(id) {
9914
- return this.getGlobal(id);
10072
+ /** Get one record by id (item envelope; item: null → NotFoundError). `fresh: true` bypasses the read-cache lookup and refreshes the entry (issue #250). */
10073
+ async get(id, opts = {}) {
10074
+ return this.getGlobal(id, opts?.fresh === true);
9915
10075
  }
9916
10076
  /** Create a record (OperationResultModel → { id}). `dryRun: true` returns the
9917
10077
  * pinned envelope (section 19.3) and never issues the create. A 2xx that is not the
@@ -9978,9 +10138,9 @@ var TagsResource = class extends BaseResource {
9978
10138
  async count(params) {
9979
10139
  return this.countGlobal(params);
9980
10140
  }
9981
- /** Get one record by id (item envelope; item: null → NotFoundError). */
9982
- async get(id) {
9983
- return this.getGlobal(id);
10141
+ /** Get one record by id (item envelope; item: null → NotFoundError). `fresh: true` bypasses the read-cache lookup and refreshes the entry (issue #250). */
10142
+ async get(id, opts = {}) {
10143
+ return this.getGlobal(id, opts?.fresh === true);
9984
10144
  }
9985
10145
  /** Create a record (OperationResultModel → { id}). `dryRun: true` returns the
9986
10146
  * pinned envelope (section 19.3) and never issues the create. A 2xx that is not the
@@ -10049,8 +10209,8 @@ var TaskSecondaryResourcesResource = class extends BaseResource {
10049
10209
  return this.countGlobal(params);
10050
10210
  }
10051
10211
  /** Get one record by parent + id (/V1.0/Tasks/{parentId}/SecondaryResources/{id} — vendor item envelope; item: null → NotFoundError). */
10052
- async get(parentId, id) {
10053
- return this.getScopedRaw(parentId, id);
10212
+ async get(parentId, id, opts = {}) {
10213
+ return this.getScopedRaw(parentId, id, opts?.fresh === true);
10054
10214
  }
10055
10215
  /** Create a record under the parent (OperationResultModel → { id}). `dryRun: true` returns the
10056
10216
  * pinned envelope (section 19.3) and never issues the create. A 2xx that is not the
@@ -10107,8 +10267,8 @@ var TasksResource = class extends BaseResource {
10107
10267
  return this.countGlobal(params);
10108
10268
  }
10109
10269
  /** Get one record by parent + id (/V1.0/Projects/{parentId}/Tasks/{id} — vendor item envelope; item: null → NotFoundError). */
10110
- async get(parentId, id) {
10111
- return this.getScopedRaw(parentId, id);
10270
+ async get(parentId, id, opts = {}) {
10271
+ return this.getScopedRaw(parentId, id, opts?.fresh === true);
10112
10272
  }
10113
10273
  /** Create a record under the parent (OperationResultModel → { id}). `dryRun: true` returns the
10114
10274
  * pinned envelope (section 19.3) and never issues the create. A 2xx that is not the
@@ -10168,9 +10328,9 @@ var TaxRegionsResource = class extends BaseResource {
10168
10328
  async count(params) {
10169
10329
  return this.countGlobal(params);
10170
10330
  }
10171
- /** Get one record by id (item envelope; item: null → NotFoundError). */
10172
- async get(id) {
10173
- return this.getGlobal(id);
10331
+ /** Get one record by id (item envelope; item: null → NotFoundError). `fresh: true` bypasses the read-cache lookup and refreshes the entry (issue #250). */
10332
+ async get(id, opts = {}) {
10333
+ return this.getGlobal(id, opts?.fresh === true);
10174
10334
  }
10175
10335
  /** Create a record (OperationResultModel → { id}). `dryRun: true` returns the
10176
10336
  * pinned envelope (section 19.3) and never issues the create. A 2xx that is not the
@@ -10245,8 +10405,8 @@ var TicketAdditionalConfigurationItemsResource = class extends BaseResource {
10245
10405
  return this.countGlobal(params);
10246
10406
  }
10247
10407
  /** Get one record by parent + id (/V1.0/Tickets/{parentId}/AdditionalConfigurationItems/{id} — vendor item envelope; item: null → NotFoundError). */
10248
- async get(parentId, id) {
10249
- return this.getScopedRaw(parentId, id);
10408
+ async get(parentId, id, opts = {}) {
10409
+ return this.getScopedRaw(parentId, id, opts?.fresh === true);
10250
10410
  }
10251
10411
  /** Create a record under the parent (OperationResultModel → { id}). `dryRun: true` returns the
10252
10412
  * pinned envelope (section 19.3) and never issues the create. A 2xx that is not the
@@ -10302,8 +10462,8 @@ var TicketAdditionalContactsResource = class extends BaseResource {
10302
10462
  return this.countGlobal(params);
10303
10463
  }
10304
10464
  /** Get one record by parent + id (/V1.0/Tickets/{parentId}/AdditionalContacts/{id} — vendor item envelope; item: null → NotFoundError). */
10305
- async get(parentId, id) {
10306
- return this.getScopedRaw(parentId, id);
10465
+ async get(parentId, id, opts = {}) {
10466
+ return this.getScopedRaw(parentId, id, opts?.fresh === true);
10307
10467
  }
10308
10468
  /** Create a record under the parent (OperationResultModel → { id}). `dryRun: true` returns the
10309
10469
  * pinned envelope (section 19.3) and never issues the create. A 2xx that is not the
@@ -10360,8 +10520,8 @@ var TicketAttachmentsResource = class extends BaseResource {
10360
10520
  return this.countGlobal(params);
10361
10521
  }
10362
10522
  /** Get one record by parent + id (/V1.0/Tickets/{parentId}/Attachments/{id} — vendor answers the model directly). */
10363
- async get(parentId, id) {
10364
- return this.getScopedModel(parentId, id);
10523
+ async get(parentId, id, opts = {}) {
10524
+ return this.getScopedModel(parentId, id, opts?.fresh === true);
10365
10525
  }
10366
10526
  /** Create a record under the parent (OperationResultModel → { id}). `dryRun: true` returns the
10367
10527
  * pinned envelope (section 19.3) and never issues the create. A 2xx that is not the
@@ -10420,9 +10580,9 @@ var TicketCategoriesResource = class extends BaseResource {
10420
10580
  async count(params) {
10421
10581
  return this.countGlobal(params);
10422
10582
  }
10423
- /** Get one record by id (item envelope; item: null → NotFoundError). */
10424
- async get(id) {
10425
- return this.getGlobal(id);
10583
+ /** Get one record by id (item envelope; item: null → NotFoundError). `fresh: true` bypasses the read-cache lookup and refreshes the entry (issue #250). */
10584
+ async get(id, opts = {}) {
10585
+ return this.getGlobal(id, opts?.fresh === true);
10426
10586
  }
10427
10587
  /** Update a record (PUT on the COLLECTION — the vendored spec's item path is GET-only; the vendor
10428
10588
  * keys the record by the id in the body). The vendor validates the FULL model on this route (V2), so a
@@ -10480,8 +10640,8 @@ var TicketCategoryFieldDefaultsResource = class extends BaseResource {
10480
10640
  return this.countGlobal(params);
10481
10641
  }
10482
10642
  /** Get one record by parent + id (/V1.0/TicketCategories/{parentId}/FieldDefaults/{id} — vendor item envelope; item: null → NotFoundError). */
10483
- async get(parentId, id) {
10484
- return this.getScopedRaw(parentId, id);
10643
+ async get(parentId, id, opts = {}) {
10644
+ return this.getScopedRaw(parentId, id, opts?.fresh === true);
10485
10645
  }
10486
10646
  /** Resolve a TicketCategoryFieldDefault from a numeric id (or, where the vendor indexes a primary text field,
10487
10647
  * from a numeric id — this resource has no primary text field). A numeric id miss throws NOT_FOUND;
@@ -10522,8 +10682,8 @@ var TicketChangeRequestApprovalsResource = class extends BaseResource {
10522
10682
  return this.countGlobal(params);
10523
10683
  }
10524
10684
  /** Get one record by parent + id (/V1.0/Tickets/{parentId}/ChangeRequestApprovals/{id} — vendor item envelope; item: null → NotFoundError). */
10525
- async get(parentId, id) {
10526
- return this.getScopedRaw(parentId, id);
10685
+ async get(parentId, id, opts = {}) {
10686
+ return this.getScopedRaw(parentId, id, opts?.fresh === true);
10527
10687
  }
10528
10688
  /** Create a record under the parent (OperationResultModel → { id}). `dryRun: true` returns the
10529
10689
  * pinned envelope (section 19.3) and never issues the create. A 2xx that is not the
@@ -10734,22 +10894,22 @@ function uiLinkFor(http, entity, id) {
10734
10894
  }
10735
10895
 
10736
10896
  // src/resources/special/ticket_charges.ts
10737
- var OP4 = "ticket_charges.moveToTicket";
10897
+ var OP5 = "ticket_charges.moveToTicket";
10738
10898
  var COPY = ["name", "description", "chargeType", "billingCodeID", "productID", "unitQuantity", "unitCost", "unitPrice", "datePurchased", "isBillableToCompany", "notes", "purchaseOrderNumber", "internalPurchaseOrderNumber"];
10739
10899
  var CONTRACT_SCOPED = ["contractServiceID", "contractServiceBundleID"];
10740
10900
  async function readCharge(http, id, retries) {
10741
- const rows = await queryRows(http, "TicketCharges", [{ field: "id", op: "eq", value: id }], OP4, retries);
10901
+ const rows = await queryRows(http, "TicketCharges", [{ field: "id", op: "eq", value: id }], OP5, retries);
10742
10902
  return rows[0] ?? null;
10743
10903
  }
10744
10904
  async function checkSource({ http, source, sourceId, sourceTicketId, toTicketId }) {
10745
10905
  if (source.isBilled === true) {
10746
- throw refuse("MOVE_BLOCKED_BILLED", `${OP4}: ticket charge ${sourceId} is billed \u2014 move it in the Autotask UI`, { sourceId, toTicketId }, OP4, {
10906
+ throw refuse("MOVE_BLOCKED_BILLED", `${OP5}: ticket charge ${sourceId} is billed \u2014 move it in the Autotask UI`, { sourceId, toTicketId }, OP5, {
10747
10907
  manualAction: { action: "delete_source", uiLink: uiLinkFor(http, "tickets", sourceTicketId), reason: "billed charges are not moved by the API (the ticket link opens its charges)" }
10748
10908
  });
10749
10909
  }
10750
10910
  }
10751
10911
  var SPEC = {
10752
- operation: OP4,
10912
+ operation: OP5,
10753
10913
  entity: "ticket_charge",
10754
10914
  readSource: readCharge,
10755
10915
  sourceTicketId: (s) => typeof s.ticketID === "number" ? s.ticketID : null,
@@ -10811,8 +10971,8 @@ var TicketChargesResource = class extends BaseResource {
10811
10971
  return this.countGlobal(params);
10812
10972
  }
10813
10973
  /** Get one record by parent + id (/V1.0/Tickets/{parentId}/Charges/{id} — vendor item envelope; item: null → NotFoundError). */
10814
- async get(parentId, id) {
10815
- return this.getScopedRaw(parentId, id);
10974
+ async get(parentId, id, opts = {}) {
10975
+ return this.getScopedRaw(parentId, id, opts?.fresh === true);
10816
10976
  }
10817
10977
  /** Create a record under the parent (OperationResultModel → { id}). `dryRun: true` returns the
10818
10978
  * pinned envelope (section 19.3) and never issues the create. A 2xx that is not the
@@ -10885,8 +11045,8 @@ var TicketChecklistItemsResource = class extends BaseResource {
10885
11045
  return this.countGlobal(params);
10886
11046
  }
10887
11047
  /** Get one record by parent + id (/V1.0/Tickets/{parentId}/ChecklistItems/{id} — vendor item envelope; item: null → NotFoundError). */
10888
- async get(parentId, id) {
10889
- return this.getScopedRaw(parentId, id);
11048
+ async get(parentId, id, opts = {}) {
11049
+ return this.getScopedRaw(parentId, id, opts?.fresh === true);
10890
11050
  }
10891
11051
  /** Create a record under the parent (OperationResultModel → { id}). `dryRun: true` returns the
10892
11052
  * pinned envelope (section 19.3) and never issues the create. A 2xx that is not the
@@ -11007,9 +11167,9 @@ var TicketHistoryResource = class extends BaseResource {
11007
11167
  async count(params) {
11008
11168
  return this.countGlobal(params);
11009
11169
  }
11010
- /** Get one record by id (item envelope; item: null → NotFoundError). */
11011
- async get(id) {
11012
- return this.getGlobal(id);
11170
+ /** Get one record by id (item envelope; item: null → NotFoundError). `fresh: true` bypasses the read-cache lookup and refreshes the entry (issue #250). */
11171
+ async get(id, opts = {}) {
11172
+ return this.getGlobal(id, opts?.fresh === true);
11013
11173
  }
11014
11174
  /** Resolve a TicketHistory from a numeric id (or, where the vendor indexes a primary text field,
11015
11175
  * from a numeric id — this resource has no primary text field). A numeric id miss throws NOT_FOUND;
@@ -11051,8 +11211,8 @@ var TicketNoteAttachmentsResource = class extends BaseResource {
11051
11211
  return this.countGlobal(params);
11052
11212
  }
11053
11213
  /** Get one record by parent + id (/V1.0/TicketNotes/{parentId}/Attachments/{id} — vendor answers the model directly). */
11054
- async get(parentId, id) {
11055
- return this.getScopedModel(parentId, id);
11214
+ async get(parentId, id, opts = {}) {
11215
+ return this.getScopedModel(parentId, id, opts?.fresh === true);
11056
11216
  }
11057
11217
  /** Create a record under the parent (OperationResultModel → { id}). `dryRun: true` returns the
11058
11218
  * pinned envelope (section 19.3) and never issues the create. A 2xx that is not the
@@ -11112,8 +11272,8 @@ var TicketNotesResource = class extends BaseResource {
11112
11272
  return this.countGlobal(params);
11113
11273
  }
11114
11274
  /** Get one record by parent + id (/V1.0/Tickets/{parentId}/Notes/{id} — vendor item envelope; item: null → NotFoundError). */
11115
- async get(parentId, id) {
11116
- return this.getScopedRaw(parentId, id);
11275
+ async get(parentId, id, opts = {}) {
11276
+ return this.getScopedRaw(parentId, id, opts?.fresh === true);
11117
11277
  }
11118
11278
  /** Create a record under the parent (OperationResultModel → { id}). `dryRun: true` returns the
11119
11279
  * pinned envelope (section 19.3) and never issues the create. A 2xx that is not the
@@ -11172,9 +11332,9 @@ var TicketNoteWebhooksResource = class extends BaseResource {
11172
11332
  async count(params) {
11173
11333
  return this.countGlobal(params);
11174
11334
  }
11175
- /** Get one record by id (item envelope; item: null → NotFoundError). */
11176
- async get(id) {
11177
- return this.getGlobal(id);
11335
+ /** Get one record by id (item envelope; item: null → NotFoundError). `fresh: true` bypasses the read-cache lookup and refreshes the entry (issue #250). */
11336
+ async get(id, opts = {}) {
11337
+ return this.getGlobal(id, opts?.fresh === true);
11178
11338
  }
11179
11339
  /** Create a record (OperationResultModel → { id}). `dryRun: true` returns the
11180
11340
  * pinned envelope (section 19.3) and never issues the create. A 2xx that is not the
@@ -11247,8 +11407,8 @@ var TicketSecondaryResourcesResource = class extends BaseResource {
11247
11407
  return this.countGlobal(params);
11248
11408
  }
11249
11409
  /** Get one record by parent + id (/V1.0/Tickets/{parentId}/SecondaryResources/{id} — vendor item envelope; item: null → NotFoundError). */
11250
- async get(parentId, id) {
11251
- return this.getScopedRaw(parentId, id);
11410
+ async get(parentId, id, opts = {}) {
11411
+ return this.getScopedRaw(parentId, id, opts?.fresh === true);
11252
11412
  }
11253
11413
  /** Create a record under the parent (OperationResultModel → { id}). `dryRun: true` returns the
11254
11414
  * pinned envelope (section 19.3) and never issues the create. A 2xx that is not the
@@ -11418,12 +11578,12 @@ async function slaHealthCheck(_resource, id, opts = {}, http) {
11418
11578
  "tickets.slaHealthCheck"
11419
11579
  );
11420
11580
  const slas = rows.map((row) => {
11421
- const bool = (v) => typeof v === "boolean" ? v : null;
11581
+ const bool2 = (v) => typeof v === "boolean" ? v : null;
11422
11582
  const num2 = (v) => typeof v === "number" ? v : null;
11423
11583
  const milestones = [
11424
- { name: "firstResponse", met: bool(row.isFirstResponseMet), elapsedHours: num2(row.firstResponseElapsedHours) },
11425
- { name: "resolution", met: bool(row.isResolutionMet), elapsedHours: num2(row.resolutionElapsedHours) },
11426
- { name: "resolutionPlan", met: bool(row.isResolutionPlanMet), elapsedHours: num2(row.resolutionPlanElapsedHours) }
11584
+ { name: "firstResponse", met: bool2(row.isFirstResponseMet), elapsedHours: num2(row.firstResponseElapsedHours) },
11585
+ { name: "resolution", met: bool2(row.isResolutionMet), elapsedHours: num2(row.resolutionElapsedHours) },
11586
+ { name: "resolutionPlan", met: bool2(row.isResolutionPlanMet), elapsedHours: num2(row.resolutionPlanElapsedHours) }
11427
11587
  ];
11428
11588
  return { id: Number(row.id), name: row.serviceLevelAgreementName ?? null, milestones };
11429
11589
  });
@@ -11441,11 +11601,11 @@ async function summary(_resource, id, opts = {}, http) {
11441
11601
  const now = opts.now ?? /* @__PURE__ */ new Date();
11442
11602
  const ageDays = typeof ticket.createDate === "string" && ticket.createDate !== "" ? Math.max(0, Math.floor((now.getTime() - Date.parse(ticket.createDate)) / MS)) : null;
11443
11603
  const pick = (v) => typeof v === "number" ? v : null;
11444
- const str = (v) => typeof v === "string" && v !== "" ? v : null;
11604
+ const str2 = (v) => typeof v === "string" && v !== "" ? v : null;
11445
11605
  return {
11446
11606
  ticketId,
11447
- ticketNumber: str(ticket.ticketNumber),
11448
- title: str(ticket.title),
11607
+ ticketNumber: str2(ticket.ticketNumber),
11608
+ title: str2(ticket.title),
11449
11609
  description: desc.value,
11450
11610
  descriptionLength: desc.length,
11451
11611
  descriptionTruncated: desc.truncated,
@@ -11455,8 +11615,8 @@ async function summary(_resource, id, opts = {}, http) {
11455
11615
  contactID: pick(ticket.contactID),
11456
11616
  assignedResourceID: pick(ticket.assignedResourceID),
11457
11617
  projectID: pick(ticket.projectID),
11458
- createDate: str(ticket.createDate),
11459
- dueDateTime: str(ticket.dueDateTime),
11618
+ createDate: str2(ticket.createDate),
11619
+ dueDateTime: str2(ticket.dueDateTime),
11460
11620
  ageDays
11461
11621
  };
11462
11622
  }
@@ -12203,16 +12363,17 @@ async function fullContext(resource, id, opts = {}, http) {
12203
12363
  }
12204
12364
 
12205
12365
  // src/resources/special/tickets/forResource.ts
12206
- var OP5 = "tickets.forResource";
12366
+ var OP6 = "tickets.forResource";
12207
12367
  var TICKET_CHUNK = 100;
12208
12368
  var LIMIT_DEFAULT = 100;
12209
12369
  var LIMIT_MAX = 500;
12210
12370
  var LINK_READ_CAP = 500;
12371
+ var COUNT_LINK_PAGES = 20;
12211
12372
  var TICKET_FIELDS2 = ["id", "ticketNumber", "title", "status", "assignedResourceID", "companyID"];
12212
12373
  function positiveId2(value, name) {
12213
12374
  const n = typeof value === "string" && /^\d+$/.test(value.trim()) ? Number(value) : value;
12214
12375
  if (typeof n !== "number" || !Number.isSafeInteger(n) || n < 1) {
12215
- throw new AutotaskConfigError(`${OP5}: ${name} must be a positive integer id (got ${String(value)})`, { operation: OP5 });
12376
+ throw new AutotaskConfigError(`${OP6}: ${name} must be a positive integer id (got ${String(value)})`, { operation: OP6 });
12216
12377
  }
12217
12378
  return n;
12218
12379
  }
@@ -12222,53 +12383,93 @@ async function ticketPage(http, filter, maxRecords, fields) {
12222
12383
  idempotent: true,
12223
12384
  path: "/V1.0/Tickets/query",
12224
12385
  body: { MaxRecords: maxRecords, filter, IncludeFields: fields },
12225
- operation: OP5
12386
+ operation: OP6
12226
12387
  });
12227
- const page = unwrapItems(res, OP5);
12388
+ const page = unwrapItems(res, OP6);
12228
12389
  return { rows: page.items, more: page.pageDetails.nextPageUrl !== null };
12229
12390
  }
12391
+ async function readLinkIds(http, resourceID, maxPages = 1) {
12392
+ const ids2 = /* @__PURE__ */ new Set();
12393
+ let cursor = null;
12394
+ for (let pages = 0; pages < maxPages; pages++) {
12395
+ const res = await http.request({
12396
+ method: "POST",
12397
+ idempotent: true,
12398
+ path: cursor === null ? "/V1.0/TicketSecondaryResources/query" : cursorToPath(http.baseUrl, cursor),
12399
+ body: { MaxRecords: LINK_READ_CAP, filter: [{ field: "resourceID", op: "eq", value: resourceID }], IncludeFields: ["ticketID"] },
12400
+ operation: OP6
12401
+ });
12402
+ const page = unwrapItems(res, OP6);
12403
+ for (const row of page.items) if (typeof row.ticketID === "number") ids2.add(row.ticketID);
12404
+ cursor = page.pageDetails.nextPageUrl;
12405
+ if (cursor === null || page.items.length === 0) return { ids: [...ids2], capped: false };
12406
+ }
12407
+ return { ids: [...ids2], capped: true };
12408
+ }
12230
12409
  async function forResource(_resource, resourceIDIn, http, opts = {}) {
12231
- if (opts === null || typeof opts !== "object") throw new AutotaskConfigError(`${OP5}: opts must be an object`, { operation: OP5 });
12410
+ if (opts === null || typeof opts !== "object") throw new AutotaskConfigError(`${OP6}: opts must be an object`, { operation: OP6 });
12232
12411
  const resourceID = positiveId2(resourceIDIn, "resourceID");
12233
12412
  const scope = opts.scope ?? "both";
12234
12413
  if (scope !== "primary" && scope !== "secondary" && scope !== "both") {
12235
- throw new AutotaskConfigError(`${OP5}: scope must be 'primary', 'secondary' or 'both' (got ${JSON.stringify(opts.scope)})`, { operation: OP5 });
12414
+ throw new AutotaskConfigError(`${OP6}: scope must be 'primary', 'secondary' or 'both' (got ${JSON.stringify(opts.scope)})`, { operation: OP6 });
12236
12415
  }
12237
12416
  if (opts.openOnly !== void 0 && typeof opts.openOnly !== "boolean") {
12238
- throw new AutotaskConfigError(`${OP5}: openOnly must be a boolean`, { operation: OP5 });
12417
+ throw new AutotaskConfigError(`${OP6}: openOnly must be a boolean`, { operation: OP6 });
12239
12418
  }
12240
12419
  const limit = opts.limit === void 0 ? LIMIT_DEFAULT : opts.limit;
12241
- if (!Number.isInteger(limit) || limit < 1 || limit > LIMIT_MAX) {
12242
- throw new AutotaskConfigError(`${OP5}: limit must be an integer 1-${LIMIT_MAX} (got ${String(opts.limit)})`, { operation: OP5 });
12420
+ if (opts.countOnly !== true && (!Number.isInteger(limit) || limit < 1 || limit > LIMIT_MAX)) {
12421
+ throw new AutotaskConfigError(`${OP6}: limit must be an integer 1-${LIMIT_MAX} (got ${String(opts.limit)})`, { operation: OP6 });
12243
12422
  }
12244
12423
  const includeFields = opts.includeFields ?? [];
12245
12424
  if (!Array.isArray(includeFields) || includeFields.some((f) => typeof f !== "string" || f.length === 0)) {
12246
- throw new AutotaskConfigError(`${OP5}: includeFields must be a list of field names`, { operation: OP5 });
12425
+ throw new AutotaskConfigError(`${OP6}: includeFields must be a list of field names`, { operation: OP6 });
12247
12426
  }
12248
12427
  const openOnly = opts.openOnly === true;
12249
12428
  const fields = [.../* @__PURE__ */ new Set([...TICKET_FIELDS2, ...includeFields])];
12250
- const closed = await resolveTicketStatusSemantics(http, opts.excludeStatusIds === void 0 ? {} : { excludeStatusIds: opts.excludeStatusIds });
12429
+ if (opts.countOnly !== void 0 && typeof opts.countOnly !== "boolean") {
12430
+ throw new AutotaskConfigError(`${OP6}: countOnly must be a boolean`, { operation: OP6 });
12431
+ }
12432
+ const closed = await resolveTicketStatusSemantics(
12433
+ http,
12434
+ { ...opts.excludeStatusIds === void 0 ? {} : { excludeStatusIds: opts.excludeStatusIds }, ...opts.allowAssumed === void 0 ? {} : { allowAssumed: opts.allowAssumed } },
12435
+ OP6
12436
+ );
12251
12437
  const closedStatus = { closedIds: closed.closedIds, source: closed.source, note: closed.note };
12252
- const openLeaf = openOnly ? [openStatusFilter(closed.closedIds)] : [];
12438
+ const openLeaf = openOnly || opts.countOnly === true ? [openStatusFilter(closed.closedIds)] : [];
12439
+ if (opts.countOnly === true) {
12440
+ const primaryCount = scope === "secondary" ? 0 : await _resource.count({ filter: [{ field: "assignedResourceID", op: "eq", value: resourceID }, ...openLeaf] });
12441
+ let secondaryCount = 0;
12442
+ let bothCount = 0;
12443
+ let linkCapped = false;
12444
+ if (scope !== "primary") {
12445
+ const links = await readLinkIds(http, resourceID, COUNT_LINK_PAGES);
12446
+ linkCapped = links.capped;
12447
+ for (let c = 0; c < links.ids.length; c += TICKET_CHUNK) {
12448
+ const chunk = links.ids.slice(c, c + TICKET_CHUNK);
12449
+ const page = await ticketPage(http, [{ field: "id", op: "in", value: chunk }, ...openLeaf], chunk.length, ["id", "status", "assignedResourceID"]);
12450
+ const seen = /* @__PURE__ */ new Set();
12451
+ for (const t of page.rows) {
12452
+ if (typeof t.id !== "number" || seen.has(t.id) || isClosedStatus(t.status, closed.closedIds)) continue;
12453
+ seen.add(t.id);
12454
+ if (scope === "both" && t.assignedResourceID === resourceID) bothCount++;
12455
+ }
12456
+ secondaryCount += seen.size;
12457
+ }
12458
+ }
12459
+ return { resourceID, scope, primary: primaryCount, secondary: secondaryCount, both: bothCount, open: primaryCount + secondaryCount - bothCount, capped: linkCapped, closedStatus };
12460
+ }
12253
12461
  const linkIds = [];
12254
12462
  let capped = false;
12255
12463
  if (scope !== "primary") {
12256
- const res = await http.request({
12257
- method: "POST",
12258
- idempotent: true,
12259
- path: "/V1.0/TicketSecondaryResources/query",
12260
- body: { MaxRecords: LINK_READ_CAP, filter: [{ field: "resourceID", op: "eq", value: resourceID }], IncludeFields: ["ticketID"] },
12261
- operation: OP5
12262
- });
12263
- const page = unwrapItems(res, OP5);
12264
- for (const row of page.items) if (typeof row.ticketID === "number" && !linkIds.includes(row.ticketID)) linkIds.push(row.ticketID);
12265
- if (page.items.length >= LINK_READ_CAP || page.pageDetails.nextPageUrl !== null) capped = true;
12464
+ const links = await readLinkIds(http, resourceID);
12465
+ linkIds.push(...links.ids);
12466
+ capped = links.capped;
12266
12467
  }
12267
12468
  const primary = /* @__PURE__ */ new Map();
12268
12469
  if (scope !== "secondary") {
12269
- const page = await ticketPage(http, [{ field: "assignedResourceID", op: "eq", value: resourceID }, ...openLeaf], limit, fields);
12270
- if (page.more || page.rows.length >= limit) capped = true;
12271
- for (const t of page.rows) if (typeof t.id === "number") primary.set(t.id, t);
12470
+ const page = await ticketPage(http, [{ field: "assignedResourceID", op: "eq", value: resourceID }, ...openLeaf], Math.min(limit + 1, LIMIT_MAX), fields);
12471
+ if (page.more || page.rows.length > limit) capped = true;
12472
+ for (const t of page.rows.slice(0, limit)) if (typeof t.id === "number") primary.set(t.id, t);
12272
12473
  }
12273
12474
  const secondary = /* @__PURE__ */ new Map();
12274
12475
  const unresolvedIds = [];
@@ -12281,7 +12482,14 @@ async function forResource(_resource, resourceIDIn, http, opts = {}) {
12281
12482
  secondary.set(t.id, t);
12282
12483
  seen.add(t.id);
12283
12484
  }
12284
- for (const id of chunk) if (!seen.has(id)) unresolvedIds.push(id);
12485
+ const missing = chunk.filter((id) => !seen.has(id));
12486
+ if (missing.length > 0 && openOnly) {
12487
+ const found = await ticketPage(http, [{ field: "id", op: "in", value: missing }], missing.length, ["id"]);
12488
+ const closedHere = new Set(found.rows.map((t) => t.id));
12489
+ for (const id of missing) if (!closedHere.has(id)) unresolvedIds.push(id);
12490
+ } else {
12491
+ unresolvedIds.push(...missing);
12492
+ }
12285
12493
  }
12286
12494
  const merged = /* @__PURE__ */ new Map();
12287
12495
  for (const [id, t] of primary) merged.set(id, t);
@@ -12313,11 +12521,11 @@ async function forResource(_resource, resourceIDIn, http, opts = {}) {
12313
12521
  }
12314
12522
 
12315
12523
  // src/resources/special/tickets/lineOfBusiness.ts
12316
- var OP6 = "tickets.lineOfBusiness";
12524
+ var OP7 = "tickets.lineOfBusiness";
12317
12525
  function positiveId3(value, name) {
12318
12526
  const n = typeof value === "string" && /^[0-9]+$/.test(value.trim()) ? Number(value) : value;
12319
12527
  if (typeof n !== "number" || !Number.isSafeInteger(n) || n < 1) {
12320
- throw new AutotaskConfigError(OP6 + ": " + name + " must be a positive integer id (got " + String(value) + ")", { operation: OP6 });
12528
+ throw new AutotaskConfigError(OP7 + ": " + name + " must be a positive integer id (got " + String(value) + ")", { operation: OP7 });
12321
12529
  }
12322
12530
  return n;
12323
12531
  }
@@ -12340,7 +12548,7 @@ async function lineOfBusiness2(resource, ticketIdIn, http, associationIdIn) {
12340
12548
  if (contractRef !== void 0) {
12341
12549
  const client = http.client;
12342
12550
  if (client === void 0) {
12343
- throw new AutotaskConfigError(OP6 + ": the transport is not wired to an AutotaskClient (the composite must run through the client)", { operation: OP6 });
12551
+ throw new AutotaskConfigError(OP7 + ": the transport is not wired to an AutotaskClient (the composite must run through the client)", { operation: OP7 });
12344
12552
  }
12345
12553
  try {
12346
12554
  const contract = await client.contracts.get(contractRef);
@@ -12371,7 +12579,7 @@ async function lineOfBusiness2(resource, ticketIdIn, http, associationIdIn) {
12371
12579
  markers: { association: contractUnread ? "unresolved" : "missing", organizationalLevel2: "missing", organizationalLevel1: "missing" }
12372
12580
  };
12373
12581
  }
12374
- const chain = await resolveLineOfBusinessChain(http, associationId, { budget: 3, operation: OP6, onError: "propagate" });
12582
+ const chain = await resolveLineOfBusinessChain(http, associationId, { budget: 3, operation: OP7, onError: "propagate" });
12375
12583
  const { association, organizationalLevel2, organizationalLevel1, markers } = chain.lineOfBusiness;
12376
12584
  return { ticketId, associationSource, contractId, association, organizationalLevel2, organizationalLevel1, markers };
12377
12585
  }
@@ -12406,9 +12614,9 @@ var TicketsResource = class extends BaseResource {
12406
12614
  async count(params) {
12407
12615
  return this.countGlobal(params);
12408
12616
  }
12409
- /** Get one record by id (item envelope; item: null → NotFoundError). */
12410
- async get(id) {
12411
- return this.getGlobal(id);
12617
+ /** Get one record by id (item envelope; item: null → NotFoundError). `fresh: true` bypasses the read-cache lookup and refreshes the entry (issue #250). */
12618
+ async get(id, opts = {}) {
12619
+ return this.getGlobal(id, opts?.fresh === true);
12412
12620
  }
12413
12621
  /** Create a record (OperationResultModel → { id}). `dryRun: true` returns the
12414
12622
  * pinned envelope (section 19.3) and never issues the create. A 2xx that is not the
@@ -12490,7 +12698,6 @@ var TicketsResource = class extends BaseResource {
12490
12698
  statusSemantics(opts) {
12491
12699
  return statusSemantics(this, opts, this.http);
12492
12700
  }
12493
- /** Node-parity special op (hand-written in src/resources/special/tickets.ts). */
12494
12701
  forResource(resourceID, opts) {
12495
12702
  return forResource(this, resourceID, this.http, opts);
12496
12703
  }
@@ -12527,9 +12734,9 @@ var TicketWebhooksResource = class extends BaseResource {
12527
12734
  async count(params) {
12528
12735
  return this.countGlobal(params);
12529
12736
  }
12530
- /** Get one record by id (item envelope; item: null → NotFoundError). */
12531
- async get(id) {
12532
- return this.getGlobal(id);
12737
+ /** Get one record by id (item envelope; item: null → NotFoundError). `fresh: true` bypasses the read-cache lookup and refreshes the entry (issue #250). */
12738
+ async get(id, opts = {}) {
12739
+ return this.getGlobal(id, opts?.fresh === true);
12533
12740
  }
12534
12741
  /** Create a record (OperationResultModel → { id}). `dryRun: true` returns the
12535
12742
  * pinned envelope (section 19.3) and never issues the create. A 2xx that is not the
@@ -12662,12 +12869,12 @@ async function postedStateQuery(_resource, mode, http, opts) {
12662
12869
  return { items, hasMore: read.hasMore || incomplete, window, approvedCount, unapprovedCount: items.length - approvedCount };
12663
12870
  }
12664
12871
  async function postedWithin(_resource, from, to, http, opts, opLabel = "time_entries.postedWithin") {
12665
- const OP11 = opLabel;
12666
- if (opts?.tz !== void 0) validateZone(opts.tz, OP11);
12667
- const fromB = customRangeDay(from, "from", void 0, OP11);
12668
- const toB = customRangeDay(to, "to", void 0, OP11);
12872
+ const OP12 = opLabel;
12873
+ if (opts?.tz !== void 0) validateZone(opts.tz, OP12);
12874
+ const fromB = customRangeDay(from, "from", void 0, OP12);
12875
+ const toB = customRangeDay(to, "to", void 0, OP12);
12669
12876
  if (fromB.ms > toB.ms) {
12670
- throw new AutotaskConfigError(`${OP11}: from (${iso2(fromB.ms)}) must not be after to (${iso2(toB.ms)})`, { operation: OP11 });
12877
+ throw new AutotaskConfigError(`${OP12}: from (${iso2(fromB.ms)}) must not be after to (${iso2(toB.ms)})`, { operation: OP12 });
12671
12878
  }
12672
12879
  const windowToMs = toB.ms + DAY_MS2 - 1;
12673
12880
  const filter = [
@@ -12676,8 +12883,8 @@ async function postedWithin(_resource, from, to, http, opts, opLabel = "time_ent
12676
12883
  ];
12677
12884
  if (opts?.ticketID !== void 0) filter.push({ field: "ticketID", op: "eq", value: opts.ticketID });
12678
12885
  if (opts?.resourceID !== void 0) filter.push({ field: "resourceID", op: "eq", value: opts.resourceID });
12679
- const { items, hasMore } = await queryTimeEntries(_resource, filter, clampWindowLimit(opts?.limit), OP11, http);
12680
- const { states, incomplete } = await postedStateOf(http, items, OP11);
12886
+ const { items, hasMore } = await queryTimeEntries(_resource, filter, clampWindowLimit(opts?.limit), OP12, http);
12887
+ const { states, incomplete } = await postedStateOf(http, items, OP12);
12681
12888
  let postedCount = 0;
12682
12889
  let unpostedCount = 0;
12683
12890
  for (const state of states.values()) {
@@ -12887,7 +13094,7 @@ async function resolveCode(http, family, familyLabel2, pinnedId, departments, op
12887
13094
  }
12888
13095
 
12889
13096
  // src/resources/special/time_entries/createForResource.ts
12890
- var OP7 = "time_entries.createForResource";
13097
+ var OP8 = "time_entries.createForResource";
12891
13098
  var PARAM_KEYS = /* @__PURE__ */ new Set([
12892
13099
  "internallAllocationCodeID",
12893
13100
  "ticketID",
@@ -12923,30 +13130,30 @@ function validateCreateParams(params) {
12923
13130
  if (pinCount > 1) {
12924
13131
  throw new AutotaskConfigError(
12925
13132
  "createForResource: exactly one linkage pin is honoured (internallAllocationCodeID | ticketID | taskID) \u2014 the vendor gate requires exactly one; pass one pin (or none for the default internal linkage)",
12926
- { operation: OP7 }
13133
+ { operation: OP8 }
12927
13134
  );
12928
13135
  }
12929
13136
  if (pins.role !== void 0 && pins.code !== void 0) {
12930
13137
  throw new AutotaskConfigError(
12931
13138
  "createForResource: a pinned roleID is only meaningful with the task/ticket linkage (internallAllocationCodeID pins the internal linkage and owns the code) \u2014 drop one",
12932
- { operation: OP7 }
13139
+ { operation: OP8 }
12933
13140
  );
12934
13141
  }
12935
13142
  if (params.hoursWorked !== void 0 && (typeof params.hoursWorked !== "number" || !Number.isFinite(params.hoursWorked) || params.hoursWorked <= 0)) {
12936
13143
  throw new AutotaskConfigError(
12937
13144
  `createForResource: hoursWorked must be a positive finite number (got ${String(params.hoursWorked)})`,
12938
- { operation: OP7 }
13145
+ { operation: OP8 }
12939
13146
  );
12940
13147
  }
12941
13148
  return pins;
12942
13149
  }
12943
13150
  async function assertResourceActive(http, rid) {
12944
- const rec = await fetchItem2(http, `/V1.0/Resources/${rid}`, OP7);
13151
+ const rec = await fetchItem2(http, `/V1.0/Resources/${rid}`, OP8);
12945
13152
  if (rec === null) {
12946
13153
  throw new ResourceInvalidError(`Resource ${rid} was not found \u2014 a time entry cannot attach to a missing resource`, {
12947
13154
  resourceIds: [rid],
12948
13155
  details: { idRefs: [{ entity: "resource", id: rid }] },
12949
- operation: OP7,
13156
+ operation: OP8,
12950
13157
  category: "not_found",
12951
13158
  suggestedAction: "Resolve the resource id (resources.get / resources.search) and retry."
12952
13159
  });
@@ -12955,7 +13162,7 @@ async function assertResourceActive(http, rid) {
12955
13162
  throw new ResourceInvalidError(`Resource ${rid} is not active (isActive !== true) \u2014 the vendor would reject a time entry for an inactive resource`, {
12956
13163
  resourceIds: [rid],
12957
13164
  details: { idRefs: [{ entity: "resource", id: rid }] },
12958
- operation: OP7,
13165
+ operation: OP8,
12959
13166
  suggestedAction: "Activate the resource or pick an active one."
12960
13167
  });
12961
13168
  }
@@ -12965,11 +13172,11 @@ async function resolveAllocationCode(http, rid, linkage, pins, departments) {
12965
13172
  const pinnedForCode = pins.code !== void 0 ? pins.code : pins.role;
12966
13173
  let code = null;
12967
13174
  const familiesTried = [];
12968
- code = await resolveCode(http, familyOf(linkage), familyLabel(familyOf(linkage)), pinnedForCode, departments, OP7);
13175
+ code = await resolveCode(http, familyOf(linkage), familyLabel(familyOf(linkage)), pinnedForCode, departments, OP8);
12969
13176
  familiesTried.push({ family: familyOf(linkage), label: familyLabel(familyOf(linkage)), filters: [{ field: "useType", op: "eq", value: familyOf(linkage) }, { field: "isActive", op: "eq", value: true }] });
12970
13177
  if (code === null && linkage === "task" && pins.role === void 0) {
12971
13178
  usedLinkage = "internal";
12972
- code = await resolveCode(http, USE_TYPE_INTERNAL, familyLabel(USE_TYPE_INTERNAL), void 0, departments, OP7);
13179
+ code = await resolveCode(http, USE_TYPE_INTERNAL, familyLabel(USE_TYPE_INTERNAL), void 0, departments, OP8);
12973
13180
  familiesTried.push({ family: USE_TYPE_INTERNAL, label: familyLabel(USE_TYPE_INTERNAL), filters: [{ field: "useType", op: "eq", value: USE_TYPE_INTERNAL }, { field: "isActive", op: "eq", value: true }] });
12974
13181
  }
12975
13182
  if (code === null) {
@@ -12979,7 +13186,7 @@ async function resolveAllocationCode(http, rid, linkage, pins, departments) {
12979
13186
  families: familiesTried,
12980
13187
  resourceDepartments: [...departments].sort((a, b) => a - b)
12981
13188
  },
12982
- { operation: OP7 }
13189
+ { operation: OP8 }
12983
13190
  );
12984
13191
  }
12985
13192
  const resolvedCode = codeInfo(code);
@@ -13018,7 +13225,7 @@ function createDryRun2(http, rid, body, linkage, usedLinkage, resolvedCode) {
13018
13225
  }
13019
13226
  return buildDryRunResult(
13020
13227
  {
13021
- operation: OP7,
13228
+ operation: OP8,
13022
13229
  method: "POST",
13023
13230
  path: "/V1.0/TimeEntries",
13024
13231
  ids: [rid],
@@ -13060,7 +13267,7 @@ async function createWithAttempts(resource, http, opts, body, defaults, pins, us
13060
13267
  const gate3 = ROLE_REJECTION_PATTERN.test(text);
13061
13268
  if (usedLinkage !== "internal" && gate3) {
13062
13269
  if (!taskRoleFetched && usedLinkage === "task" && pins.task !== void 0) {
13063
- const task = await fetchItem2(http, `/V1.0/Tasks/${pins.task}`, OP7);
13270
+ const task = await fetchItem2(http, `/V1.0/Tasks/${pins.task}`, OP8);
13064
13271
  taskRoleFetched = true;
13065
13272
  if (task !== null) pushLadder(task.assignedResourceRoleID);
13066
13273
  }
@@ -13086,7 +13293,7 @@ async function createForResource(resource, resourceID, params, opts = {}, http)
13086
13293
  const pins = validateCreateParams(params);
13087
13294
  await assertResourceActive(http, rid);
13088
13295
  const linkage = pins.code !== void 0 ? "internal" : pins.ticket !== void 0 ? "ticket" : pins.task !== void 0 ? "task" : "internal";
13089
- const roleRows = await resourceRoleRows(http, rid, OP7);
13296
+ const roleRows = await resourceRoleRows(http, rid, OP8);
13090
13297
  const departments = roleRows.departments;
13091
13298
  const { usedLinkage, resolvedCode } = await resolveAllocationCode(http, rid, linkage, pins, departments);
13092
13299
  const defaults = windowDefaults(params);
@@ -13109,12 +13316,12 @@ function discoveryField(err, body, defaults) {
13109
13316
  }
13110
13317
 
13111
13318
  // src/resources/special/time_entries/move.ts
13112
- var OP8 = "time_entries.moveToTicket";
13319
+ var OP9 = "time_entries.moveToTicket";
13113
13320
  var COPY2 = ["resourceID", "roleID", "billingCodeID", "dateWorked", "startDateTime", "endDateTime", "hoursWorked", "offsetHours", "summaryNotes", "internalNotes", "isNonBillable", "showOnInvoice"];
13114
13321
  var CONTRACT_SCOPED2 = ["contractID", "contractServiceID", "contractServiceBundleID"];
13115
13322
  async function readTimeEntry(http, id, retries) {
13116
13323
  try {
13117
- const res = await http.request({ method: "GET", path: `/V1.0/TimeEntries/${id}`, operation: OP8, maxRetries: retries });
13324
+ const res = await http.request({ method: "GET", path: `/V1.0/TimeEntries/${id}`, operation: OP9, maxRetries: retries });
13118
13325
  return res?.item ?? null;
13119
13326
  } catch (e) {
13120
13327
  if (isAutotaskError(e) && (e.httpStatus === 404 || e.code === "NOT_FOUND")) return null;
@@ -13124,27 +13331,27 @@ async function readTimeEntry(http, id, retries) {
13124
13331
  async function checkSource2({ http, source, sourceId, toTicketId, retries }) {
13125
13332
  const ids2 = { sourceId, toTicketId };
13126
13333
  if (source.taskID !== null && source.taskID !== void 0) {
13127
- throw refuse("MOVE_SOURCE_UNSUPPORTED", `${OP8}: time entry ${sourceId} is on a task \u2014 only ticket time entries are moved`, ids2, OP8);
13334
+ throw refuse("MOVE_SOURCE_UNSUPPORTED", `${OP9}: time entry ${sourceId} is on a task \u2014 only ticket time entries are moved`, ids2, OP9);
13128
13335
  }
13129
13336
  if (source.billingApprovalDateTime || source.billingApprovalResourceID || source.billingApprovalLevelMostRecent) {
13130
- throw refuse("MOVE_BLOCKED_APPROVED", `${OP8}: time entry ${sourceId} has billing approval set \u2014 move it in the Autotask UI`, ids2, OP8, { manualAction: { action: "delete_source", uiLink: uiLinkFor(http, "time_entries", sourceId), reason: "approved entries are not moved by the API" } });
13337
+ throw refuse("MOVE_BLOCKED_APPROVED", `${OP9}: time entry ${sourceId} has billing approval set \u2014 move it in the Autotask UI`, ids2, OP9, { manualAction: { action: "delete_source", uiLink: uiLinkFor(http, "time_entries", sourceId), reason: "approved entries are not moved by the API" } });
13131
13338
  }
13132
13339
  let billing;
13133
13340
  try {
13134
- billing = await queryRows(http, "BillingItems", [{ field: "timeEntryID", op: "eq", value: sourceId }], OP8, retries);
13341
+ billing = await queryRows(http, "BillingItems", [{ field: "timeEntryID", op: "eq", value: sourceId }], OP9, retries);
13135
13342
  } catch {
13136
- throw refuse("MOVE_BLOCKED_BILLED", `${OP8}: the billing items of time entry ${sourceId} could not be read \u2014 refused (fails closed)`, ids2, OP8, { manualAction: { action: "delete_source", uiLink: uiLinkFor(http, "time_entries", sourceId), reason: "billing state unreadable" } });
13343
+ throw refuse("MOVE_BLOCKED_BILLED", `${OP9}: the billing items of time entry ${sourceId} could not be read \u2014 refused (fails closed)`, ids2, OP9, { manualAction: { action: "delete_source", uiLink: uiLinkFor(http, "time_entries", sourceId), reason: "billing state unreadable" } });
13137
13344
  }
13138
13345
  if (billing.some((b) => b.invoiceID || b.postedDate)) {
13139
- throw refuse("MOVE_BLOCKED_BILLED", `${OP8}: time entry ${sourceId} is billed or posted \u2014 move it in the Autotask UI`, ids2, OP8, { manualAction: { action: "delete_source", uiLink: uiLinkFor(http, "time_entries", sourceId), reason: "billed entries are not moved by the API" } });
13346
+ throw refuse("MOVE_BLOCKED_BILLED", `${OP9}: time entry ${sourceId} is billed or posted \u2014 move it in the Autotask UI`, ids2, OP9, { manualAction: { action: "delete_source", uiLink: uiLinkFor(http, "time_entries", sourceId), reason: "billed entries are not moved by the API" } });
13140
13347
  }
13141
- const attachments = await queryRows(http, "TimeEntryAttachments", [{ field: "timeEntryID", op: "eq", value: sourceId }], OP8, retries);
13348
+ const attachments = await queryRows(http, "TimeEntryAttachments", [{ field: "timeEntryID", op: "eq", value: sourceId }], OP9, retries);
13142
13349
  if (attachments.length > 0) {
13143
- throw refuse("MOVE_BLOCKED_ATTACHMENTS", `${OP8}: time entry ${sourceId} has attachments, which a delete would destroy \u2014 move it in the Autotask UI`, ids2, OP8, { manualAction: { action: "delete_source", uiLink: uiLinkFor(http, "time_entries", sourceId), reason: "entries with attachments are not moved by the API" } });
13350
+ throw refuse("MOVE_BLOCKED_ATTACHMENTS", `${OP9}: time entry ${sourceId} has attachments, which a delete would destroy \u2014 move it in the Autotask UI`, ids2, OP9, { manualAction: { action: "delete_source", uiLink: uiLinkFor(http, "time_entries", sourceId), reason: "entries with attachments are not moved by the API" } });
13144
13351
  }
13145
13352
  }
13146
13353
  var SPEC2 = {
13147
- operation: OP8,
13354
+ operation: OP9,
13148
13355
  entity: "time_entry",
13149
13356
  readSource: readTimeEntry,
13150
13357
  sourceTicketId: (s) => typeof s.ticketID === "number" ? s.ticketID : null,
@@ -13179,7 +13386,7 @@ function moveToTicket2(_resource, sourceId, toTicketId, opts, http) {
13179
13386
  }
13180
13387
 
13181
13388
  // src/resources/special/time_entries/approve.ts
13182
- var OP9 = "time_entries.approve";
13389
+ var OP10 = "time_entries.approve";
13183
13390
  var APPROVAL_LEVELS_PATH = "/V1.0/BillingItemApprovalLevels";
13184
13391
  function toIso(value) {
13185
13392
  if (value instanceof Date) {
@@ -13217,7 +13424,7 @@ async function approve(resource, id, opts = {}, http) {
13217
13424
  if (opts.dryRun === true) {
13218
13425
  return buildDryRunResult(
13219
13426
  {
13220
- operation: OP9,
13427
+ operation: OP10,
13221
13428
  method: "POST",
13222
13429
  path: APPROVAL_LEVELS_PATH,
13223
13430
  ids: [numericId],
@@ -13240,10 +13447,10 @@ async function approve(resource, id, opts = {}, http) {
13240
13447
  method: "POST",
13241
13448
  path: APPROVAL_LEVELS_PATH,
13242
13449
  body,
13243
- operation: OP9,
13450
+ operation: OP10,
13244
13451
  maxRetries: opts.maxRetries
13245
13452
  });
13246
- const levelId = toNumber(parseIdentifier(unwrapOperation(created, OP9).id, "billingItemApprovalLevelID"));
13453
+ const levelId = toNumber(parseIdentifier(unwrapOperation(created, OP10).id, "billingItemApprovalLevelID"));
13247
13454
  await resource.update(
13248
13455
  numericId,
13249
13456
  { billingApprovalDateTime: approvalDateTime, billingApprovalResourceID: approvalResourceID },
@@ -13266,28 +13473,28 @@ async function approve(resource, id, opts = {}, http) {
13266
13473
  }
13267
13474
 
13268
13475
  // src/resources/special/time_entries/recentTickets.ts
13269
- var OP10 = "time_entries.recentTickets";
13476
+ var OP11 = "time_entries.recentTickets";
13270
13477
  var DAY_MS3 = 864e5;
13271
13478
  var TICKET_CHUNK2 = 100;
13272
13479
  var TICKET_FIELDS3 = ["id", "ticketNumber", "title", "status", "assignedResourceID", "companyID"];
13273
13480
  function positiveId4(value, name) {
13274
13481
  const n = typeof value === "string" && /^\d+$/.test(value.trim()) ? Number(value) : value;
13275
13482
  if (typeof n !== "number" || !Number.isSafeInteger(n) || n < 1) {
13276
- throw new AutotaskConfigError(`${OP10}: ${name} must be a positive integer id (got ${String(value)})`, { operation: OP10 });
13483
+ throw new AutotaskConfigError(`${OP11}: ${name} must be a positive integer id (got ${String(value)})`, { operation: OP11 });
13277
13484
  }
13278
13485
  return n;
13279
13486
  }
13280
13487
  async function recentTickets(_resource, from, to, http, opts) {
13281
13488
  if (opts === void 0 || opts === null || typeof opts !== "object") {
13282
- throw new AutotaskConfigError(`${OP10}: opts { resourceID, companyID?, tz?, limit? } is required`, { operation: OP10 });
13489
+ throw new AutotaskConfigError(`${OP11}: opts { resourceID, companyID?, tz?, limit? } is required`, { operation: OP11 });
13283
13490
  }
13284
13491
  const resourceID = positiveId4(opts.resourceID, "resourceID");
13285
13492
  const companyID = opts.companyID === void 0 ? void 0 : positiveId4(opts.companyID, "companyID");
13286
- if (opts.tz !== void 0) validateZone(opts.tz, OP10);
13287
- const fromB = customRangeDay(from, "from", void 0, OP10);
13288
- const toB = customRangeDay(to, "to", void 0, OP10);
13493
+ if (opts.tz !== void 0) validateZone(opts.tz, OP11);
13494
+ const fromB = customRangeDay(from, "from", void 0, OP11);
13495
+ const toB = customRangeDay(to, "to", void 0, OP11);
13289
13496
  if (fromB.ms > toB.ms) {
13290
- throw new AutotaskConfigError(`${OP10}: from (${isoUtc(fromB.ms)}) must not be after to (${isoUtc(toB.ms)})`, { operation: OP10 });
13497
+ throw new AutotaskConfigError(`${OP11}: from (${isoUtc(fromB.ms)}) must not be after to (${isoUtc(toB.ms)})`, { operation: OP11 });
13291
13498
  }
13292
13499
  const windowToMs = toB.ms + DAY_MS3 - 1;
13293
13500
  const { items: entries, hasMore } = await queryTimeEntries(
@@ -13298,7 +13505,7 @@ async function recentTickets(_resource, from, to, http, opts) {
13298
13505
  { field: "resourceID", op: "eq", value: resourceID }
13299
13506
  ],
13300
13507
  clampWindowLimit(opts.limit),
13301
- OP10,
13508
+ OP11,
13302
13509
  http
13303
13510
  );
13304
13511
  const groups = /* @__PURE__ */ new Map();
@@ -13324,9 +13531,9 @@ async function recentTickets(_resource, from, to, http, opts) {
13324
13531
  idempotent: true,
13325
13532
  path: "/V1.0/Tickets/query",
13326
13533
  body: { MaxRecords: TICKET_CHUNK2, filter, IncludeFields: TICKET_FIELDS3 },
13327
- operation: OP10
13534
+ operation: OP11
13328
13535
  });
13329
- for (const t of unwrapItems(res, OP10).items) if (typeof t.id === "number") tickets.set(t.id, t);
13536
+ for (const t of unwrapItems(res, OP11).items) if (typeof t.id === "number") tickets.set(t.id, t);
13330
13537
  }
13331
13538
  const items = [];
13332
13539
  const unresolvedTicketIDs = [];
@@ -13386,9 +13593,9 @@ var TimeEntriesResource = class extends BaseResource {
13386
13593
  async count(params) {
13387
13594
  return this.countGlobal(params);
13388
13595
  }
13389
- /** Get one record by id (item envelope; item: null → NotFoundError). */
13390
- async get(id) {
13391
- return this.getGlobal(id);
13596
+ /** Get one record by id (item envelope; item: null → NotFoundError). `fresh: true` bypasses the read-cache lookup and refreshes the entry (issue #250). */
13597
+ async get(id, opts = {}) {
13598
+ return this.getGlobal(id, opts?.fresh === true);
13392
13599
  }
13393
13600
  /** Create a record (OperationResultModel → { id}). `dryRun: true` returns the
13394
13601
  * pinned envelope (section 19.3) and never issues the create. A 2xx that is not the
@@ -13538,8 +13745,8 @@ var TimeEntryAttachmentsResource = class extends BaseResource {
13538
13745
  return this.countGlobal(params);
13539
13746
  }
13540
13747
  /** Get one record by parent + id (/V1.0/TimeEntries/{parentId}/Attachments/{id} — vendor answers the model directly). */
13541
- async get(parentId, id) {
13542
- return this.getScopedModel(parentId, id);
13748
+ async get(parentId, id, opts = {}) {
13749
+ return this.getScopedModel(parentId, id, opts?.fresh === true);
13543
13750
  }
13544
13751
  /** Create a record under the parent (OperationResultModel → { id}). `dryRun: true` returns the
13545
13752
  * pinned envelope (section 19.3) and never issues the create. A 2xx that is not the
@@ -13645,9 +13852,9 @@ var TimeOffRequestsResource = class extends BaseResource {
13645
13852
  async count(params) {
13646
13853
  return this.countGlobal(params);
13647
13854
  }
13648
- /** Get one record by id (item envelope; item: null → NotFoundError). */
13649
- async get(id) {
13650
- return this.getGlobal(id);
13855
+ /** Get one record by id (item envelope; item: null → NotFoundError). `fresh: true` bypasses the read-cache lookup and refreshes the entry (issue #250). */
13856
+ async get(id, opts = {}) {
13857
+ return this.getGlobal(id, opts?.fresh === true);
13651
13858
  }
13652
13859
  /** Resolve a TimeOffRequest from a numeric id (or, where the vendor indexes a primary text field,
13653
13860
  * from a numeric id — this resource has no primary text field). A numeric id miss throws NOT_FOUND;