node-autotask 0.26.0 → 0.27.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 (49) hide show
  1. package/CHANGELOG.md +47 -0
  2. package/MCP_TOOL_CATALOG.json +921 -30
  3. package/MCP_TOOL_MANIFEST.md +69 -16
  4. package/N8N_MCP_MANIFEST.json +39 -8
  5. package/N8N_MCP_MANIFEST.md +9 -8
  6. package/README.md +11 -9
  7. package/capabilities.json +13316 -7733
  8. package/capabilities.schema.json +125 -0
  9. package/dist/capabilities.cjs +2 -2
  10. package/dist/capabilities.js +1 -1
  11. package/dist/{chunk-SSUECUVN.js → chunk-42ZUISDH.js} +947 -128
  12. package/dist/{chunk-WM6E5O55.cjs → chunk-5CC7LGNM.cjs} +13315 -7732
  13. package/dist/{chunk-SG4LIVMG.cjs → chunk-5GGCSRT4.cjs} +848 -439
  14. package/dist/{chunk-QXWIQ67O.js → chunk-F7FVOXPQ.js} +13315 -7732
  15. package/dist/{chunk-7DOSJS6S.js → chunk-GURC52J7.js} +23 -2
  16. package/dist/{chunk-5OGJTS2E.cjs → chunk-UHTZLUDE.cjs} +157 -136
  17. package/dist/{chunk-VVQ6NJYZ.js → chunk-ZGTFVZL5.js} +433 -24
  18. package/dist/{chunk-HQGE4WAV.cjs → chunk-ZJ4ONAQF.cjs} +1054 -235
  19. package/dist/{index-CKYr0unq.d.cts → index-BIWy9m-a.d.ts} +379 -49
  20. package/dist/{index-C8QH3BkP.d.ts → index-D4XYtn4s.d.cts} +379 -49
  21. package/dist/{index-1zBdJIEy.d.cts → index-DQ9NgraW.d.cts} +281 -1
  22. package/dist/{index-1zBdJIEy.d.ts → index-DQ9NgraW.d.ts} +281 -1
  23. package/dist/index.cjs +44 -24
  24. package/dist/index.d.cts +11 -5
  25. package/dist/index.d.ts +11 -5
  26. package/dist/index.js +26 -6
  27. package/dist/operations/index.cjs +147 -120
  28. package/dist/operations/index.d.cts +136 -7
  29. package/dist/operations/index.d.ts +136 -7
  30. package/dist/operations/index.js +33 -6
  31. package/dist/pool.cjs +42 -9
  32. package/dist/pool.d.cts +14 -3
  33. package/dist/pool.d.ts +14 -3
  34. package/dist/pool.js +38 -5
  35. package/dist/resources/index.cjs +19 -5
  36. package/dist/resources/index.d.cts +2 -2
  37. package/dist/resources/index.d.ts +2 -2
  38. package/dist/resources/index.js +18 -4
  39. package/dist/types/index.cjs +1 -1
  40. package/dist/types/index.d.cts +1 -1
  41. package/dist/types/index.d.ts +1 -1
  42. package/dist/types/index.js +1 -1
  43. package/docs/API.md +207 -9
  44. package/examples/mcp/schemas.ts +16 -7
  45. package/package.json +1 -1
  46. /package/dist/{chunk-S643FDOR.cjs → chunk-IXF7AKOJ.cjs} +0 -0
  47. /package/dist/{chunk-2TWKEB2L.js → chunk-RMG55JTF.js} +0 -0
  48. /package/dist/{chunk-W3K5BEVY.cjs → chunk-SDYRQFGL.cjs} +0 -0
  49. /package/dist/{chunk-EBCHCNPK.js → chunk-WLTLB2ND.js} +0 -0
@@ -38,10 +38,10 @@ import {
38
38
  unwrapItem,
39
39
  unwrapItems,
40
40
  unwrapOperation
41
- } from "./chunk-SSUECUVN.js";
41
+ } from "./chunk-42ZUISDH.js";
42
42
  import {
43
43
  CAPABILITIES
44
- } from "./chunk-QXWIQ67O.js";
44
+ } from "./chunk-F7FVOXPQ.js";
45
45
 
46
46
  // src/resources/appointments.ts
47
47
  var AppointmentsResource = class extends BaseResource {
@@ -172,6 +172,42 @@ var BillingCodesResource = class extends BaseResource {
172
172
  }
173
173
  };
174
174
 
175
+ // src/resources/billing_item_approval_levels.ts
176
+ var BillingItemApprovalLevelsResource = class extends BaseResource {
177
+ constructor(http, pageSize) {
178
+ super(http, {
179
+ key: "billing_item_approval_levels",
180
+ resourcePath: "/V1.0/BillingItemApprovalLevels",
181
+ deletable: false,
182
+ udfCapable: false
183
+ }, pageSize);
184
+ }
185
+ /** Query BillingItemApprovalLevel records with the G3 filter surface (server-side JSON filter). */
186
+ query(params) {
187
+ return this.queryItems(params);
188
+ }
189
+ /** Get every BillingItemApprovalLevel record (the MCP-preferred read; 1000-page guarded). */
190
+ async queryAll(params) {
191
+ return this.queryAllItems(params);
192
+ }
193
+ /** Count matching records (queryCount envelope unwrapped to a plain number). */
194
+ async count(params) {
195
+ return this.countGlobal(params);
196
+ }
197
+ /** Get one record by id (item envelope; item: null → NotFoundError). */
198
+ async get(id) {
199
+ return this.getGlobal(id);
200
+ }
201
+ /** Create a record (OperationResultModel → { id}). `dryRun: true` returns the
202
+ * pinned envelope (section 19.3) and never issues the create. A 2xx that is not the
203
+ * specced envelope runs the plan-pinned marker recovery (issue #13 — one bounded read;
204
+ * `recoverIdFromMarker: false` restores the pre-recovery behaviour). */
205
+ async create(data, opts = {}) {
206
+ if (opts.dryRun === true) return this.runCreateDryRun(data);
207
+ return this.createGlobal(data, opts);
208
+ }
209
+ };
210
+
175
211
  // src/resources/special/dateWindow.ts
176
212
  var DAY_MS = 864e5;
177
213
  var DEFAULT_LIMIT = 500;
@@ -5184,7 +5220,7 @@ function appendWiresNote(wires, note) {
5184
5220
  wires.note = (wires.note ? wires.note + " | " : "") + note;
5185
5221
  }
5186
5222
  function makeFetchCtx(rawHttp, v, contractId, budget) {
5187
- const OP6 = PROFITABILITY_OP;
5223
+ const OP7 = PROFITABILITY_OP;
5188
5224
  const id = parseIdentifier(contractId, "contractId");
5189
5225
  const idNum = typeof id === "number" ? id : Number(id);
5190
5226
  const wires = { issued: 0, requests: 0, budget };
@@ -5196,19 +5232,19 @@ function makeFetchCtx(rawHttp, v, contractId, budget) {
5196
5232
  } };
5197
5233
  const readPart = (path, conditions, fields) => {
5198
5234
  wires.issued += 1;
5199
- return degradable(() => boundedPart(http, path, conditions, v.limit, OP6, fields));
5235
+ return degradable(() => boundedPart(http, path, conditions, v.limit, OP7, fields));
5200
5236
  };
5201
5237
  const truncatedMonths = {};
5202
5238
  const windowedPart = async (name, key, path, cond, fields, dateField) => {
5203
5239
  const first = await readPart(path, cond, fields);
5204
5240
  if (first.absent !== void 0 || !first.hasMore) return { part: stampPart(key, first, cond), rows: first.items };
5205
- const wp = await degradable(() => expandByMonth(http, path, cond, v.limit, OP6, fields, dateField, v.dateFrom, v.dateTo, wires));
5241
+ const wp = await degradable(() => expandByMonth(http, path, cond, v.limit, OP7, fields, dateField, v.dateFrom, v.dateTo, wires));
5206
5242
  if (!("truncatedMonths" in wp)) return { part: stampPart(key, wp, cond), rows: [] };
5207
5243
  const { truncatedMonths: tm, ...part } = wp;
5208
5244
  truncatedMonths[name] = tm;
5209
5245
  return { part, rows: wp.items };
5210
5246
  };
5211
- return { v, OP: OP6, id, idNum, rawHttp, http, wires, windowOn, readPart, windowedPart, truncatedMonths };
5247
+ return { v, OP: OP7, id, idNum, rawHttp, http, wires, windowOn, readPart, windowedPart, truncatedMonths };
5212
5248
  }
5213
5249
 
5214
5250
  // src/resources/special/contracts/profitability.stages.ts
@@ -7131,6 +7167,34 @@ var InvoicesResource = class extends BaseResource {
7131
7167
  }
7132
7168
  };
7133
7169
 
7170
+ // src/resources/invoice_templates.ts
7171
+ var InvoiceTemplatesResource = class extends BaseResource {
7172
+ constructor(http, pageSize) {
7173
+ super(http, {
7174
+ key: "invoice_templates",
7175
+ resourcePath: "/V1.0/InvoiceTemplates",
7176
+ deletable: false,
7177
+ udfCapable: false
7178
+ }, pageSize);
7179
+ }
7180
+ /** Query InvoiceTemplate records with the G3 filter surface (server-side JSON filter). */
7181
+ query(params) {
7182
+ return this.queryItems(params);
7183
+ }
7184
+ /** Get every InvoiceTemplate record (the MCP-preferred read; 1000-page guarded). */
7185
+ async queryAll(params) {
7186
+ return this.queryAllItems(params);
7187
+ }
7188
+ /** Count matching records (queryCount envelope unwrapped to a plain number). */
7189
+ async count(params) {
7190
+ return this.countGlobal(params);
7191
+ }
7192
+ /** Get one record by id (item envelope; item: null → NotFoundError). */
7193
+ async get(id) {
7194
+ return this.getGlobal(id);
7195
+ }
7196
+ };
7197
+
7134
7198
  // src/resources/modules.ts
7135
7199
  var ModulesResource = class {
7136
7200
  http;
@@ -7369,6 +7433,159 @@ var OpportunityCategoriesResource = class extends BaseResource {
7369
7433
  }
7370
7434
  };
7371
7435
 
7436
+ // src/resources/organizational_level1s.ts
7437
+ var OrganizationalLevel1sResource = class extends BaseResource {
7438
+ constructor(http, pageSize) {
7439
+ super(http, {
7440
+ key: "organizational_level1s",
7441
+ resourcePath: "/V1.0/OrganizationalLevel1s",
7442
+ deletable: false,
7443
+ udfCapable: false,
7444
+ collectionUpdate: true
7445
+ // D1: the spec's item path is GET-only — confirmed updates PUT the collection (id in the body)
7446
+ }, pageSize);
7447
+ }
7448
+ /** Query OrganizationalLevel1 records with the G3 filter surface (server-side JSON filter). */
7449
+ query(params) {
7450
+ return this.queryItems(params);
7451
+ }
7452
+ /** Get every OrganizationalLevel1 record (the MCP-preferred read; 1000-page guarded). */
7453
+ async queryAll(params) {
7454
+ return this.queryAllItems(params);
7455
+ }
7456
+ /** Count matching records (queryCount envelope unwrapped to a plain number). */
7457
+ async count(params) {
7458
+ return this.countGlobal(params);
7459
+ }
7460
+ /** Get one record by id (item envelope; item: null → NotFoundError). */
7461
+ async get(id) {
7462
+ return this.getGlobal(id);
7463
+ }
7464
+ /** Create a record (OperationResultModel → { id}). `dryRun: true` returns the
7465
+ * pinned envelope (section 19.3) and never issues the create. A 2xx that is not the
7466
+ * specced envelope runs the plan-pinned marker recovery (issue #13 — one bounded read;
7467
+ * `recoverIdFromMarker: false` restores the pre-recovery behaviour). */
7468
+ async create(data, opts = {}) {
7469
+ if (opts.dryRun === true) return this.runCreateDryRun(data);
7470
+ return this.createGlobal(data, opts);
7471
+ }
7472
+ /** Update a record (PUT on the COLLECTION — the vendored spec's item path is GET-only; the vendor
7473
+ * keys the record by the id in the body). The vendor validates the FULL model on this route (V2), so a
7474
+ * partial body is merged into the CURRENT record first: one fresh GET (which also serves the
7475
+ * stale-object guard's read) then the collection PUT of the merged model — an explicit null in the
7476
+ * caller body sends null; an omitted field keeps the current value. `raw: true` in the opts bag sends
7477
+ * the body as-is (full model or intentional partial — the compatibility escape hatch; no merge read).
7478
+ * `dryRun: true` returns the pinned envelope whose `data` is the merged body (the exact confirmed
7479
+ * wire) with the best-effort diff, from that same single read; a caller-supplied lastModifiedDate that
7480
+ * mismatches the vendor's current value throws STALE_OBJECT before the mutation. */
7481
+ async update(id, data, opts = {}) {
7482
+ if (opts.dryRun === true) return this.runUpdateDryRun(id, data, opts);
7483
+ return this.updateGlobal(id, data, opts);
7484
+ }
7485
+ };
7486
+
7487
+ // src/resources/organizational_level2s.ts
7488
+ var OrganizationalLevel2sResource = class extends BaseResource {
7489
+ constructor(http, pageSize) {
7490
+ super(http, {
7491
+ key: "organizational_level2s",
7492
+ resourcePath: "/V1.0/OrganizationalLevel2s",
7493
+ deletable: false,
7494
+ udfCapable: false,
7495
+ collectionUpdate: true
7496
+ // D1: the spec's item path is GET-only — confirmed updates PUT the collection (id in the body)
7497
+ }, pageSize);
7498
+ }
7499
+ /** Query OrganizationalLevel2 records with the G3 filter surface (server-side JSON filter). */
7500
+ query(params) {
7501
+ return this.queryItems(params);
7502
+ }
7503
+ /** Get every OrganizationalLevel2 record (the MCP-preferred read; 1000-page guarded). */
7504
+ async queryAll(params) {
7505
+ return this.queryAllItems(params);
7506
+ }
7507
+ /** Count matching records (queryCount envelope unwrapped to a plain number). */
7508
+ async count(params) {
7509
+ return this.countGlobal(params);
7510
+ }
7511
+ /** Get one record by id (item envelope; item: null → NotFoundError). */
7512
+ async get(id) {
7513
+ return this.getGlobal(id);
7514
+ }
7515
+ /** Create a record (OperationResultModel → { id}). `dryRun: true` returns the
7516
+ * pinned envelope (section 19.3) and never issues the create. A 2xx that is not the
7517
+ * specced envelope runs the plan-pinned marker recovery (issue #13 — one bounded read;
7518
+ * `recoverIdFromMarker: false` restores the pre-recovery behaviour). */
7519
+ async create(data, opts = {}) {
7520
+ if (opts.dryRun === true) return this.runCreateDryRun(data);
7521
+ return this.createGlobal(data, opts);
7522
+ }
7523
+ /** Update a record (PUT on the COLLECTION — the vendored spec's item path is GET-only; the vendor
7524
+ * keys the record by the id in the body). The vendor validates the FULL model on this route (V2), so a
7525
+ * partial body is merged into the CURRENT record first: one fresh GET (which also serves the
7526
+ * stale-object guard's read) then the collection PUT of the merged model — an explicit null in the
7527
+ * caller body sends null; an omitted field keeps the current value. `raw: true` in the opts bag sends
7528
+ * the body as-is (full model or intentional partial — the compatibility escape hatch; no merge read).
7529
+ * `dryRun: true` returns the pinned envelope whose `data` is the merged body (the exact confirmed
7530
+ * wire) with the best-effort diff, from that same single read; a caller-supplied lastModifiedDate that
7531
+ * mismatches the vendor's current value throws STALE_OBJECT before the mutation. */
7532
+ async update(id, data, opts = {}) {
7533
+ if (opts.dryRun === true) return this.runUpdateDryRun(id, data, opts);
7534
+ return this.updateGlobal(id, data, opts);
7535
+ }
7536
+ };
7537
+
7538
+ // src/resources/organizational_level_associations.ts
7539
+ var OrganizationalLevelAssociationsResource = class extends BaseResource {
7540
+ constructor(http, pageSize) {
7541
+ super(http, {
7542
+ key: "organizational_level_associations",
7543
+ resourcePath: "/V1.0/OrganizationalLevelAssociations",
7544
+ deletable: false,
7545
+ udfCapable: false,
7546
+ collectionUpdate: true
7547
+ // D1: the spec's item path is GET-only — confirmed updates PUT the collection (id in the body)
7548
+ }, pageSize);
7549
+ }
7550
+ /** Query OrganizationalLevelAssociation records with the G3 filter surface (server-side JSON filter). */
7551
+ query(params) {
7552
+ return this.queryItems(params);
7553
+ }
7554
+ /** Get every OrganizationalLevelAssociation record (the MCP-preferred read; 1000-page guarded). */
7555
+ async queryAll(params) {
7556
+ return this.queryAllItems(params);
7557
+ }
7558
+ /** Count matching records (queryCount envelope unwrapped to a plain number). */
7559
+ async count(params) {
7560
+ return this.countGlobal(params);
7561
+ }
7562
+ /** Get one record by id (item envelope; item: null → NotFoundError). */
7563
+ async get(id) {
7564
+ return this.getGlobal(id);
7565
+ }
7566
+ /** Create a record (OperationResultModel → { id}). `dryRun: true` returns the
7567
+ * pinned envelope (section 19.3) and never issues the create. A 2xx that is not the
7568
+ * specced envelope runs the plan-pinned marker recovery (issue #13 — one bounded read;
7569
+ * `recoverIdFromMarker: false` restores the pre-recovery behaviour). */
7570
+ async create(data, opts = {}) {
7571
+ if (opts.dryRun === true) return this.runCreateDryRun(data);
7572
+ return this.createGlobal(data, opts);
7573
+ }
7574
+ /** Update a record (PUT on the COLLECTION — the vendored spec's item path is GET-only; the vendor
7575
+ * keys the record by the id in the body). The vendor validates the FULL model on this route (V2), so a
7576
+ * partial body is merged into the CURRENT record first: one fresh GET (which also serves the
7577
+ * stale-object guard's read) then the collection PUT of the merged model — an explicit null in the
7578
+ * caller body sends null; an omitted field keeps the current value. `raw: true` in the opts bag sends
7579
+ * the body as-is (full model or intentional partial — the compatibility escape hatch; no merge read).
7580
+ * `dryRun: true` returns the pinned envelope whose `data` is the merged body (the exact confirmed
7581
+ * wire) with the best-effort diff, from that same single read; a caller-supplied lastModifiedDate that
7582
+ * mismatches the vendor's current value throws STALE_OBJECT before the mutation. */
7583
+ async update(id, data, opts = {}) {
7584
+ if (opts.dryRun === true) return this.runUpdateDryRun(id, data, opts);
7585
+ return this.updateGlobal(id, data, opts);
7586
+ }
7587
+ };
7588
+
7372
7589
  // src/resources/phases.ts
7373
7590
  var PhasesResource = class extends BaseResource {
7374
7591
  constructor(http, pageSize) {
@@ -8807,6 +9024,49 @@ var RolesResource = class extends BaseResource {
8807
9024
  }
8808
9025
  };
8809
9026
 
9027
+ // src/resources/sales_orders.ts
9028
+ var SalesOrdersResource = class extends BaseResource {
9029
+ constructor(http, pageSize) {
9030
+ super(http, {
9031
+ key: "sales_orders",
9032
+ resourcePath: "/V1.0/SalesOrders",
9033
+ deletable: false,
9034
+ udfCapable: true,
9035
+ collectionUpdate: true
9036
+ // D1: the spec's item path is GET-only — confirmed updates PUT the collection (id in the body)
9037
+ }, pageSize);
9038
+ }
9039
+ /** Query SalesOrder records with the G3 filter surface (server-side JSON filter). */
9040
+ query(params) {
9041
+ return this.queryItems(params);
9042
+ }
9043
+ /** Get every SalesOrder record (the MCP-preferred read; 1000-page guarded). */
9044
+ async queryAll(params) {
9045
+ return this.queryAllItems(params);
9046
+ }
9047
+ /** Count matching records (queryCount envelope unwrapped to a plain number). */
9048
+ async count(params) {
9049
+ return this.countGlobal(params);
9050
+ }
9051
+ /** Get one record by id (item envelope; item: null → NotFoundError). */
9052
+ async get(id) {
9053
+ return this.getGlobal(id);
9054
+ }
9055
+ /** Update a record (PUT on the COLLECTION — the vendored spec's item path is GET-only; the vendor
9056
+ * keys the record by the id in the body). The vendor validates the FULL model on this route (V2), so a
9057
+ * partial body is merged into the CURRENT record first: one fresh GET (which also serves the
9058
+ * stale-object guard's read) then the collection PUT of the merged model — an explicit null in the
9059
+ * caller body sends null; an omitted field keeps the current value. `raw: true` in the opts bag sends
9060
+ * the body as-is (full model or intentional partial — the compatibility escape hatch; no merge read).
9061
+ * `dryRun: true` returns the pinned envelope whose `data` is the merged body (the exact confirmed
9062
+ * wire) with the best-effort diff, from that same single read; a caller-supplied lastModifiedDate that
9063
+ * mismatches the vendor's current value throws STALE_OBJECT before the mutation. */
9064
+ async update(id, data, opts = {}) {
9065
+ if (opts.dryRun === true) return this.runUpdateDryRun(id, data, opts);
9066
+ return this.updateGlobal(id, data, opts);
9067
+ }
9068
+ };
9069
+
8810
9070
  // src/resources/service_calls.ts
8811
9071
  var ServiceCallsResource = class extends BaseResource {
8812
9072
  constructor(http, pageSize) {
@@ -9762,6 +10022,57 @@ var TasksResource = class extends BaseResource {
9762
10022
  }
9763
10023
  };
9764
10024
 
10025
+ // src/resources/tax_regions.ts
10026
+ var TaxRegionsResource = class extends BaseResource {
10027
+ constructor(http, pageSize) {
10028
+ super(http, {
10029
+ key: "tax_regions",
10030
+ resourcePath: "/V1.0/TaxRegions",
10031
+ deletable: false,
10032
+ udfCapable: false,
10033
+ collectionUpdate: true
10034
+ // D1: the spec's item path is GET-only — confirmed updates PUT the collection (id in the body)
10035
+ }, pageSize);
10036
+ }
10037
+ /** Query TaxRegion records with the G3 filter surface (server-side JSON filter). */
10038
+ query(params) {
10039
+ return this.queryItems(params);
10040
+ }
10041
+ /** Get every TaxRegion record (the MCP-preferred read; 1000-page guarded). */
10042
+ async queryAll(params) {
10043
+ return this.queryAllItems(params);
10044
+ }
10045
+ /** Count matching records (queryCount envelope unwrapped to a plain number). */
10046
+ async count(params) {
10047
+ return this.countGlobal(params);
10048
+ }
10049
+ /** Get one record by id (item envelope; item: null → NotFoundError). */
10050
+ async get(id) {
10051
+ return this.getGlobal(id);
10052
+ }
10053
+ /** Create a record (OperationResultModel → { id}). `dryRun: true` returns the
10054
+ * pinned envelope (section 19.3) and never issues the create. A 2xx that is not the
10055
+ * specced envelope runs the plan-pinned marker recovery (issue #13 — one bounded read;
10056
+ * `recoverIdFromMarker: false` restores the pre-recovery behaviour). */
10057
+ async create(data, opts = {}) {
10058
+ if (opts.dryRun === true) return this.runCreateDryRun(data);
10059
+ return this.createGlobal(data, opts);
10060
+ }
10061
+ /** Update a record (PUT on the COLLECTION — the vendored spec's item path is GET-only; the vendor
10062
+ * keys the record by the id in the body). The vendor validates the FULL model on this route (V2), so a
10063
+ * partial body is merged into the CURRENT record first: one fresh GET (which also serves the
10064
+ * stale-object guard's read) then the collection PUT of the merged model — an explicit null in the
10065
+ * caller body sends null; an omitted field keeps the current value. `raw: true` in the opts bag sends
10066
+ * the body as-is (full model or intentional partial — the compatibility escape hatch; no merge read).
10067
+ * `dryRun: true` returns the pinned envelope whose `data` is the merged body (the exact confirmed
10068
+ * wire) with the best-effort diff, from that same single read; a caller-supplied lastModifiedDate that
10069
+ * mismatches the vendor's current value throws STALE_OBJECT before the mutation. */
10070
+ async update(id, data, opts = {}) {
10071
+ if (opts.dryRun === true) return this.runUpdateDryRun(id, data, opts);
10072
+ return this.updateGlobal(id, data, opts);
10073
+ }
10074
+ };
10075
+
9765
10076
  // src/resources/threshold_information.ts
9766
10077
  var ThresholdInformationResource = class {
9767
10078
  http;
@@ -11983,12 +12294,12 @@ async function postedDateStatusQuery(_resource, mode, http, opts) {
11983
12294
  return items;
11984
12295
  }
11985
12296
  async function postedWithin(_resource, from, to, http, opts, opLabel = "time_entries.postedWithin") {
11986
- const OP6 = opLabel;
11987
- if (opts?.tz !== void 0) validateZone(opts.tz, OP6);
11988
- const fromB = customRangeDay(from, "from", void 0, OP6);
11989
- const toB = customRangeDay(to, "to", void 0, OP6);
12297
+ const OP7 = opLabel;
12298
+ if (opts?.tz !== void 0) validateZone(opts.tz, OP7);
12299
+ const fromB = customRangeDay(from, "from", void 0, OP7);
12300
+ const toB = customRangeDay(to, "to", void 0, OP7);
11990
12301
  if (fromB.ms > toB.ms) {
11991
- throw new AutotaskConfigError(`${OP6}: from (${iso2(fromB.ms)}) must not be after to (${iso2(toB.ms)})`, { operation: OP6 });
12302
+ throw new AutotaskConfigError(`${OP7}: from (${iso2(fromB.ms)}) must not be after to (${iso2(toB.ms)})`, { operation: OP7 });
11992
12303
  }
11993
12304
  const windowToMs = toB.ms + DAY_MS2 - 1;
11994
12305
  const filter = [
@@ -11999,7 +12310,7 @@ async function postedWithin(_resource, from, to, http, opts, opLabel = "time_ent
11999
12310
  else if (opts?.posted === false) filter.push({ field: "postedDate", op: "notExist" });
12000
12311
  if (opts?.ticketID !== void 0) filter.push({ field: "ticketID", op: "eq", value: opts.ticketID });
12001
12312
  if (opts?.resourceID !== void 0) filter.push({ field: "resourceID", op: "eq", value: opts.resourceID });
12002
- const { items, hasMore } = await queryTimeEntries(_resource, filter, clampWindowLimit(opts?.limit), OP6, http);
12313
+ const { items, hasMore } = await queryTimeEntries(_resource, filter, clampWindowLimit(opts?.limit), OP7, http);
12003
12314
  let postedCount = 0;
12004
12315
  for (const item of items) {
12005
12316
  const postedDate = item.postedDate;
@@ -12500,29 +12811,116 @@ function moveToTicket2(_resource, sourceId, toTicketId, opts, http) {
12500
12811
  return runMove(http, SPEC2, sourceId, toTicketId, opts);
12501
12812
  }
12502
12813
 
12814
+ // src/resources/special/time_entries/approve.ts
12815
+ var OP5 = "time_entries.approve";
12816
+ var APPROVAL_LEVELS_PATH = "/V1.0/BillingItemApprovalLevels";
12817
+ function toIso(value) {
12818
+ if (value instanceof Date) {
12819
+ if (Number.isNaN(value.getTime())) throw new AutotaskConfigError("time_entries.approve: approvalDateTime is an invalid Date");
12820
+ return value.toISOString();
12821
+ }
12822
+ const parsed = new Date(value);
12823
+ if (Number.isNaN(parsed.getTime())) throw new AutotaskConfigError(`time_entries.approve: approvalDateTime "${value}" is not a parseable date`);
12824
+ return parsed.toISOString();
12825
+ }
12826
+ function toNumber(value) {
12827
+ return typeof value === "number" ? value : Number(value);
12828
+ }
12829
+ function sameInstant(a, b) {
12830
+ if (typeof a !== "string" || a === "") return false;
12831
+ const left = new Date(a).getTime();
12832
+ const right = new Date(b).getTime();
12833
+ return !Number.isNaN(left) && left === right;
12834
+ }
12835
+ async function approve(resource, id, opts = {}, http) {
12836
+ const numericId = toNumber(parseIdentifier(id, "id"));
12837
+ if (opts.approvalLevel !== void 0 && (!Number.isInteger(opts.approvalLevel) || opts.approvalLevel < 1)) {
12838
+ throw new AutotaskConfigError(`time_entries.approve: approvalLevel must be a positive integer (got ${String(opts.approvalLevel)})`);
12839
+ }
12840
+ const approvalLevel = opts.approvalLevel ?? 1;
12841
+ const approvalDateTime = toIso(opts.approvalDateTime ?? /* @__PURE__ */ new Date());
12842
+ const entry = await resource.get(numericId);
12843
+ const approvalResourceID = opts.approvalResourceID === void 0 ? entry.resourceID : toNumber(parseIdentifier(opts.approvalResourceID, "approvalResourceID"));
12844
+ if (approvalResourceID === void 0) {
12845
+ throw new AutotaskConfigError(
12846
+ `time_entries.approve: time entry ${numericId} carries no resourceID and the caller supplied no approvalResourceID \u2014 the vendor requires an approving resource`
12847
+ );
12848
+ }
12849
+ const body = { timeEntryID: numericId, approvalLevel, approvalResourceID, approvalDateTime };
12850
+ if (opts.dryRun === true) {
12851
+ return buildDryRunResult(
12852
+ {
12853
+ operation: OP5,
12854
+ method: "POST",
12855
+ path: APPROVAL_LEVELS_PATH,
12856
+ ids: [numericId],
12857
+ checks: [
12858
+ { name: "input-validation", ok: true },
12859
+ { name: "time-entry-exists", ok: true }
12860
+ ],
12861
+ impact: { affected: 1, scope: "single-record", reversible: false },
12862
+ warnings: [
12863
+ "two calls: POST the BillingItemApprovalLevels record, then PUT the time entry (billingApprovalDateTime + billingApprovalResourceID) \u2014 the vendor sets BillingApprovalLevelMostRecent from the create but not these two fields",
12864
+ "approval is not posting: the API exposes no post action on BillingItems, so the entry stays unposted until a vendor workflow posts it",
12865
+ `approvalResourceID ${approvalResourceID} is not existence-checked by the dry run`
12866
+ ],
12867
+ data: body
12868
+ },
12869
+ { redactPersonalData: http.redactPersonalData }
12870
+ );
12871
+ }
12872
+ const created = await http.request({
12873
+ method: "POST",
12874
+ path: APPROVAL_LEVELS_PATH,
12875
+ body,
12876
+ operation: OP5,
12877
+ maxRetries: opts.maxRetries
12878
+ });
12879
+ const levelId = toNumber(parseIdentifier(unwrapOperation(created, OP5).id, "billingItemApprovalLevelID"));
12880
+ await resource.update(
12881
+ numericId,
12882
+ { billingApprovalDateTime: approvalDateTime, billingApprovalResourceID: approvalResourceID },
12883
+ { maxRetries: opts.maxRetries, lastModifiedDate: opts.lastModifiedDate ?? entry.lastModifiedDateTime }
12884
+ );
12885
+ const fresh = await resource.get(numericId);
12886
+ const persisted = sameInstant(fresh.billingApprovalDateTime, approvalDateTime) && fresh.billingApprovalResourceID === approvalResourceID;
12887
+ return {
12888
+ timeEntryID: numericId,
12889
+ billingItemApprovalLevelID: levelId,
12890
+ approvalLevel,
12891
+ approvalResourceID,
12892
+ approvalDateTime,
12893
+ billingApprovalLevelMostRecent: fresh.billingApprovalLevelMostRecent ?? null,
12894
+ billingApprovalDateTime: fresh.billingApprovalDateTime ?? null,
12895
+ billingApprovalResourceID: fresh.billingApprovalResourceID ?? null,
12896
+ status: persisted ? "approved" : "approval_fields_not_persisted",
12897
+ persisted
12898
+ };
12899
+ }
12900
+
12503
12901
  // src/resources/special/time_entries/recentTickets.ts
12504
- var OP5 = "time_entries.recentTickets";
12902
+ var OP6 = "time_entries.recentTickets";
12505
12903
  var DAY_MS3 = 864e5;
12506
12904
  var TICKET_CHUNK = 100;
12507
12905
  var TICKET_FIELDS2 = ["id", "ticketNumber", "title", "status", "assignedResourceID", "companyID"];
12508
12906
  function positiveId(value, name) {
12509
12907
  const n = typeof value === "string" && /^\d+$/.test(value.trim()) ? Number(value) : value;
12510
12908
  if (typeof n !== "number" || !Number.isSafeInteger(n) || n < 1) {
12511
- throw new AutotaskConfigError(`${OP5}: ${name} must be a positive integer id (got ${String(value)})`, { operation: OP5 });
12909
+ throw new AutotaskConfigError(`${OP6}: ${name} must be a positive integer id (got ${String(value)})`, { operation: OP6 });
12512
12910
  }
12513
12911
  return n;
12514
12912
  }
12515
12913
  async function recentTickets(_resource, from, to, http, opts) {
12516
12914
  if (opts === void 0 || opts === null || typeof opts !== "object") {
12517
- throw new AutotaskConfigError(`${OP5}: opts { resourceID, companyID?, tz?, limit? } is required`, { operation: OP5 });
12915
+ throw new AutotaskConfigError(`${OP6}: opts { resourceID, companyID?, tz?, limit? } is required`, { operation: OP6 });
12518
12916
  }
12519
12917
  const resourceID = positiveId(opts.resourceID, "resourceID");
12520
12918
  const companyID = opts.companyID === void 0 ? void 0 : positiveId(opts.companyID, "companyID");
12521
- if (opts.tz !== void 0) validateZone(opts.tz, OP5);
12522
- const fromB = customRangeDay(from, "from", void 0, OP5);
12523
- const toB = customRangeDay(to, "to", void 0, OP5);
12919
+ if (opts.tz !== void 0) validateZone(opts.tz, OP6);
12920
+ const fromB = customRangeDay(from, "from", void 0, OP6);
12921
+ const toB = customRangeDay(to, "to", void 0, OP6);
12524
12922
  if (fromB.ms > toB.ms) {
12525
- throw new AutotaskConfigError(`${OP5}: from (${isoUtc(fromB.ms)}) must not be after to (${isoUtc(toB.ms)})`, { operation: OP5 });
12923
+ throw new AutotaskConfigError(`${OP6}: from (${isoUtc(fromB.ms)}) must not be after to (${isoUtc(toB.ms)})`, { operation: OP6 });
12526
12924
  }
12527
12925
  const windowToMs = toB.ms + DAY_MS3 - 1;
12528
12926
  const { items: entries, hasMore } = await queryTimeEntries(
@@ -12533,7 +12931,7 @@ async function recentTickets(_resource, from, to, http, opts) {
12533
12931
  { field: "resourceID", op: "eq", value: resourceID }
12534
12932
  ],
12535
12933
  clampWindowLimit(opts.limit),
12536
- OP5,
12934
+ OP6,
12537
12935
  http
12538
12936
  );
12539
12937
  const groups = /* @__PURE__ */ new Map();
@@ -12559,9 +12957,9 @@ async function recentTickets(_resource, from, to, http, opts) {
12559
12957
  idempotent: true,
12560
12958
  path: "/V1.0/Tickets/query",
12561
12959
  body: { MaxRecords: TICKET_CHUNK, filter, IncludeFields: TICKET_FIELDS2 },
12562
- operation: OP5
12960
+ operation: OP6
12563
12961
  });
12564
- for (const t of unwrapItems(res, OP5).items) if (typeof t.id === "number") tickets.set(t.id, t);
12962
+ for (const t of unwrapItems(res, OP6).items) if (typeof t.id === "number") tickets.set(t.id, t);
12565
12963
  }
12566
12964
  const items = [];
12567
12965
  const unresolvedTicketIDs = [];
@@ -12665,6 +13063,10 @@ var TimeEntriesResource = class extends BaseResource {
12665
13063
  return this.resolveBase(identifier);
12666
13064
  }
12667
13065
  /** Node-parity special op (hand-written in src/resources/special/time_entries.ts). */
13066
+ approve(id, opts = {}) {
13067
+ return approve(this, id, opts, this.http);
13068
+ }
13069
+ /** Node-parity special op (hand-written in src/resources/special/time_entries.ts). */
12668
13070
  createForResource(resourceID, params, opts = {}) {
12669
13071
  return createForResource(this, resourceID, params, opts, this.http);
12670
13072
  }
@@ -12805,7 +13207,7 @@ var TimeEntryAttachmentsResource = class extends BaseResource {
12805
13207
  };
12806
13208
 
12807
13209
  // src/resources/special/time_off_requests.ts
12808
- async function approve(_resource, id, opts = {}, http) {
13210
+ async function approve2(_resource, id, opts = {}, http) {
12809
13211
  const numericId = parseIdentifier(id, "id");
12810
13212
  if (opts.dryRun === true) {
12811
13213
  return buildDryRunResult({
@@ -12893,7 +13295,7 @@ var TimeOffRequestsResource = class extends BaseResource {
12893
13295
  }
12894
13296
  /** Node-parity special op (hand-written in src/resources/special/time_off_requests.ts). */
12895
13297
  approve(id, opts = {}) {
12896
- return approve(this, id, opts, this.http);
13298
+ return approve2(this, id, opts, this.http);
12897
13299
  }
12898
13300
  /** Node-parity special op (hand-written in src/resources/special/time_off_requests.ts). */
12899
13301
  reject(id, reason, opts = {}) {
@@ -12965,6 +13367,7 @@ export {
12965
13367
  AppointmentsResource,
12966
13368
  AuthenticateResource,
12967
13369
  BillingCodesResource,
13370
+ BillingItemApprovalLevelsResource,
12968
13371
  BillingItemsResource,
12969
13372
  ChangeRequestLinksResource,
12970
13373
  ChecklistLibrariesResource,
@@ -13024,11 +13427,15 @@ export {
13024
13427
  HolidaysResource,
13025
13428
  InventoryProductsResource,
13026
13429
  InvoicesResource,
13430
+ InvoiceTemplatesResource,
13027
13431
  ModulesResource,
13028
13432
  NotificationHistoryResource,
13029
13433
  OpportunitiesResource,
13030
13434
  OpportunityAttachmentsResource,
13031
13435
  OpportunityCategoriesResource,
13436
+ OrganizationalLevel1sResource,
13437
+ OrganizationalLevel2sResource,
13438
+ OrganizationalLevelAssociationsResource,
13032
13439
  PhasesResource,
13033
13440
  ProductsResource,
13034
13441
  ProductVendorsResource,
@@ -13051,6 +13458,7 @@ export {
13051
13458
  ResourceTimeOffApproversResource,
13052
13459
  ResourceTimeOffBalancesResource,
13053
13460
  RolesResource,
13461
+ SalesOrdersResource,
13054
13462
  ServiceCallsResource,
13055
13463
  ServiceCallTaskResourcesResource,
13056
13464
  ServiceCallTasksResource,
@@ -13068,6 +13476,7 @@ export {
13068
13476
  TagsResource,
13069
13477
  TaskSecondaryResourcesResource,
13070
13478
  TasksResource,
13479
+ TaxRegionsResource,
13071
13480
  ThresholdInformationResource,
13072
13481
  TicketAdditionalConfigurationItemsResource,
13073
13482
  TicketAdditionalContactsResource,