@procyon-creative/harvest-sdk 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs ADDED
@@ -0,0 +1,762 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ ClientsResource: () => ClientsResource,
24
+ CompanyResource: () => CompanyResource,
25
+ ContactsResource: () => ContactsResource,
26
+ EstimateItemCategoriesResource: () => EstimateItemCategoriesResource,
27
+ EstimateMessagesResource: () => EstimateMessagesResource,
28
+ EstimatesResource: () => EstimatesResource,
29
+ ExpenseCategoriesResource: () => ExpenseCategoriesResource,
30
+ ExpenseReports: () => ExpenseReports,
31
+ ExpensesResource: () => ExpensesResource,
32
+ Harvest: () => Harvest,
33
+ HarvestApiError: () => HarvestApiError,
34
+ HarvestClient: () => HarvestClient,
35
+ HarvestNotFoundError: () => HarvestNotFoundError,
36
+ HarvestRateLimitError: () => HarvestRateLimitError,
37
+ HarvestUnprocessableError: () => HarvestUnprocessableError,
38
+ InvoiceItemCategoriesResource: () => InvoiceItemCategoriesResource,
39
+ InvoiceMessagesResource: () => InvoiceMessagesResource,
40
+ InvoicesResource: () => InvoicesResource,
41
+ Paginator: () => Paginator,
42
+ ProjectTaskAssignmentsResource: () => ProjectTaskAssignmentsResource,
43
+ ProjectUserAssignmentsResource: () => ProjectUserAssignmentsResource,
44
+ ProjectsResource: () => ProjectsResource,
45
+ ReportsResource: () => ReportsResource,
46
+ RolesResource: () => RolesResource,
47
+ TaskAssignmentsResource: () => TaskAssignmentsResource,
48
+ TasksResource: () => TasksResource,
49
+ TimeEntriesResource: () => TimeEntriesResource,
50
+ TimeReports: () => TimeReports,
51
+ UserAssignmentsResource: () => UserAssignmentsResource,
52
+ UserBillableRatesResource: () => UserBillableRatesResource,
53
+ UserCostRatesResource: () => UserCostRatesResource,
54
+ UserProjectAssignmentsResource: () => UserProjectAssignmentsResource,
55
+ UserTeammatesResource: () => UserTeammatesResource,
56
+ UsersResource: () => UsersResource
57
+ });
58
+ module.exports = __toCommonJS(index_exports);
59
+
60
+ // src/params.ts
61
+ function serializeParams(params) {
62
+ const parts = [];
63
+ function encode(prefix, value) {
64
+ if (value === null || value === void 0) return;
65
+ if (Array.isArray(value)) {
66
+ value.forEach((item, i) => {
67
+ encode(`${prefix}[${i}]`, item);
68
+ });
69
+ } else if (typeof value === "object" && !(value instanceof Date)) {
70
+ for (const [k, v] of Object.entries(value)) {
71
+ encode(`${prefix}[${k}]`, v);
72
+ }
73
+ } else {
74
+ parts.push(
75
+ `${encodeURIComponent(prefix)}=${encodeURIComponent(String(value))}`
76
+ );
77
+ }
78
+ }
79
+ for (const [key, value] of Object.entries(params)) {
80
+ if (value === null || value === void 0) continue;
81
+ if (Array.isArray(value)) {
82
+ value.forEach((item, i) => {
83
+ if (typeof item === "object" && item !== null) {
84
+ encode(`${key}[${i}]`, item);
85
+ } else {
86
+ parts.push(
87
+ `${encodeURIComponent(key)}=${encodeURIComponent(String(item))}`
88
+ );
89
+ }
90
+ });
91
+ } else if (typeof value === "object" && !(value instanceof Date)) {
92
+ encode(key, value);
93
+ } else {
94
+ parts.push(
95
+ `${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`
96
+ );
97
+ }
98
+ }
99
+ return parts.join("&");
100
+ }
101
+ function buildQueryString(params) {
102
+ if (!params) return "";
103
+ const parts = [];
104
+ for (const [key, value] of Object.entries(params)) {
105
+ if (value === null || value === void 0) continue;
106
+ if (typeof value === "boolean") {
107
+ parts.push(`${encodeURIComponent(key)}=${value}`);
108
+ } else {
109
+ parts.push(
110
+ `${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`
111
+ );
112
+ }
113
+ }
114
+ return parts.length ? `?${parts.join("&")}` : "";
115
+ }
116
+
117
+ // src/errors.ts
118
+ var HarvestApiError = class extends Error {
119
+ constructor(status, statusText, body) {
120
+ super(`Harvest API error ${status}: ${statusText}`);
121
+ this.status = status;
122
+ this.statusText = statusText;
123
+ this.body = body;
124
+ this.name = "HarvestApiError";
125
+ }
126
+ };
127
+ var HarvestRateLimitError = class extends HarvestApiError {
128
+ retryAfter;
129
+ constructor(retryAfter, body) {
130
+ super(429, "Too Many Requests", body);
131
+ this.name = "HarvestRateLimitError";
132
+ this.retryAfter = retryAfter;
133
+ }
134
+ };
135
+ var HarvestNotFoundError = class extends HarvestApiError {
136
+ constructor(body) {
137
+ super(404, "Not Found", body);
138
+ this.name = "HarvestNotFoundError";
139
+ }
140
+ };
141
+ var HarvestUnprocessableError = class extends HarvestApiError {
142
+ constructor(body) {
143
+ super(422, "Unprocessable Entity", body);
144
+ this.name = "HarvestUnprocessableError";
145
+ }
146
+ };
147
+
148
+ // src/client.ts
149
+ var HarvestClient = class {
150
+ baseUrl;
151
+ headers;
152
+ constructor(config) {
153
+ this.baseUrl = config.baseUrl ?? "https://api.harvestapp.com/v2";
154
+ this.headers = {
155
+ "Harvest-Account-Id": config.accountId,
156
+ Authorization: `Bearer ${config.accessToken}`,
157
+ "User-Agent": config.userAgent ?? "harvest-sdk-typescript"
158
+ };
159
+ }
160
+ async get(path, params) {
161
+ const qs = buildQueryString(params);
162
+ const url = `${this.baseUrl}${path}${qs}`;
163
+ return this.request(url, { method: "GET" });
164
+ }
165
+ async post(path, body) {
166
+ const url = `${this.baseUrl}${path}`;
167
+ const init = { method: "POST" };
168
+ if (body && Object.keys(body).length > 0) {
169
+ init.headers = {
170
+ "Content-Type": "application/x-www-form-urlencoded"
171
+ };
172
+ init.body = serializeParams(body);
173
+ }
174
+ return this.request(url, init);
175
+ }
176
+ async patch(path, body) {
177
+ const url = `${this.baseUrl}${path}`;
178
+ const init = { method: "PATCH" };
179
+ if (body && Object.keys(body).length > 0) {
180
+ init.headers = {
181
+ "Content-Type": "application/x-www-form-urlencoded"
182
+ };
183
+ init.body = serializeParams(body);
184
+ }
185
+ return this.request(url, init);
186
+ }
187
+ async delete(path) {
188
+ const url = `${this.baseUrl}${path}`;
189
+ await this.request(url, { method: "DELETE" });
190
+ }
191
+ async request(url, init) {
192
+ const response = await fetch(url, {
193
+ ...init,
194
+ headers: {
195
+ ...this.headers,
196
+ ...init.headers ?? {}
197
+ }
198
+ });
199
+ if (response.status === 204) return void 0;
200
+ if (!response.ok) {
201
+ const body = await response.json().catch(() => null);
202
+ if (response.status === 429) {
203
+ const retryAfter = Number(response.headers.get("Retry-After")) || 15;
204
+ throw new HarvestRateLimitError(retryAfter, body);
205
+ }
206
+ if (response.status === 404) {
207
+ throw new HarvestNotFoundError(body);
208
+ }
209
+ if (response.status === 422) {
210
+ throw new HarvestUnprocessableError(body);
211
+ }
212
+ throw new HarvestApiError(response.status, response.statusText, body);
213
+ }
214
+ return response.json();
215
+ }
216
+ };
217
+
218
+ // src/paginator.ts
219
+ var Paginator = class {
220
+ client;
221
+ path;
222
+ dataKey;
223
+ params;
224
+ constructor(client, path, dataKey, params = {}) {
225
+ this.client = client;
226
+ this.path = path;
227
+ this.dataKey = dataKey;
228
+ this.params = params;
229
+ }
230
+ async *[Symbol.asyncIterator]() {
231
+ let page = 1;
232
+ let totalPages = 1;
233
+ do {
234
+ const response = await this.client.get(
235
+ this.path,
236
+ { ...this.params, page, per_page: this.params.per_page ?? 100 }
237
+ );
238
+ const items = response[this.dataKey];
239
+ if (!items || items.length === 0) return;
240
+ for (const item of items) {
241
+ yield item;
242
+ }
243
+ const totalPagesValue = response.total_pages;
244
+ totalPages = typeof totalPagesValue === "number" ? totalPagesValue : 1;
245
+ page++;
246
+ } while (page <= totalPages);
247
+ }
248
+ async toArray() {
249
+ const results = [];
250
+ for await (const item of this) {
251
+ results.push(item);
252
+ }
253
+ return results;
254
+ }
255
+ };
256
+
257
+ // src/resources/base.ts
258
+ var BaseResource = class {
259
+ constructor(client) {
260
+ this.client = client;
261
+ }
262
+ };
263
+ var CrudResource = class extends BaseResource {
264
+ async list(params) {
265
+ const response = await this.client.get(
266
+ this.path,
267
+ params
268
+ );
269
+ return response[this.dataKey] ?? [];
270
+ }
271
+ listAll(params) {
272
+ return new Paginator(this.client, this.path, this.dataKey, params);
273
+ }
274
+ async get(id) {
275
+ return this.client.get(`${this.path}/${id}`);
276
+ }
277
+ async create(data) {
278
+ return this.client.post(this.path, data);
279
+ }
280
+ async update(id, data) {
281
+ return this.client.patch(`${this.path}/${id}`, data);
282
+ }
283
+ async delete(id) {
284
+ return this.client.delete(`${this.path}/${id}`);
285
+ }
286
+ };
287
+
288
+ // src/resources/clients.ts
289
+ var ClientsResource = class extends CrudResource {
290
+ path = "/clients";
291
+ dataKey = "clients";
292
+ };
293
+
294
+ // src/resources/company.ts
295
+ var CompanyResource = class extends BaseResource {
296
+ async get() {
297
+ return this.client.get("/company");
298
+ }
299
+ };
300
+
301
+ // src/resources/contacts.ts
302
+ var ContactsResource = class extends CrudResource {
303
+ path = "/contacts";
304
+ dataKey = "contacts";
305
+ };
306
+
307
+ // src/resources/estimateItemCategories.ts
308
+ var EstimateItemCategoriesResource = class extends CrudResource {
309
+ path = "/estimate_item_categories";
310
+ dataKey = "estimate_item_categories";
311
+ };
312
+
313
+ // src/resources/estimates.ts
314
+ var EstimatesResource = class extends CrudResource {
315
+ path = "/estimates";
316
+ dataKey = "estimates";
317
+ /** Access messages for an estimate. */
318
+ messages(estimateId) {
319
+ return new EstimateMessagesResource(this.client, estimateId);
320
+ }
321
+ };
322
+ var EstimateMessagesResource = class {
323
+ constructor(client, estimateId) {
324
+ this.client = client;
325
+ this.estimateId = estimateId;
326
+ }
327
+ get path() {
328
+ return `/estimates/${this.estimateId}/messages`;
329
+ }
330
+ async list(params) {
331
+ const response = await this.client.get(this.path, params);
332
+ return response.estimate_messages ?? [];
333
+ }
334
+ listAll(params) {
335
+ return new Paginator(this.client, this.path, "estimate_messages", params);
336
+ }
337
+ async create(data) {
338
+ return this.client.post(this.path, data);
339
+ }
340
+ async delete(id) {
341
+ return this.client.delete(`${this.path}/${id}`);
342
+ }
343
+ };
344
+
345
+ // src/resources/expenseCategories.ts
346
+ var ExpenseCategoriesResource = class extends CrudResource {
347
+ path = "/expense_categories";
348
+ dataKey = "expense_categories";
349
+ };
350
+
351
+ // src/resources/expenses.ts
352
+ var ExpensesResource = class extends CrudResource {
353
+ path = "/expenses";
354
+ dataKey = "expenses";
355
+ };
356
+
357
+ // src/resources/invoiceItemCategories.ts
358
+ var InvoiceItemCategoriesResource = class extends CrudResource {
359
+ path = "/invoice_item_categories";
360
+ dataKey = "invoice_item_categories";
361
+ };
362
+
363
+ // src/resources/invoices.ts
364
+ var InvoicesResource = class extends CrudResource {
365
+ path = "/invoices";
366
+ dataKey = "invoices";
367
+ /** Access messages (send, list, delete) for an invoice. */
368
+ messages(invoiceId) {
369
+ return new InvoiceMessagesResource(this.client, invoiceId);
370
+ }
371
+ };
372
+ var InvoiceMessagesResource = class {
373
+ constructor(client, invoiceId) {
374
+ this.client = client;
375
+ this.invoiceId = invoiceId;
376
+ }
377
+ get path() {
378
+ return `/invoices/${this.invoiceId}/messages`;
379
+ }
380
+ async list(params) {
381
+ const response = await this.client.get(this.path, params);
382
+ return response.invoice_messages ?? [];
383
+ }
384
+ listAll(params) {
385
+ return new Paginator(this.client, this.path, "invoice_messages", params);
386
+ }
387
+ async create(data) {
388
+ return this.client.post(this.path, data);
389
+ }
390
+ async delete(id) {
391
+ return this.client.delete(`${this.path}/${id}`);
392
+ }
393
+ };
394
+
395
+ // src/resources/userAssignments.ts
396
+ var UserAssignmentsResource = class extends BaseResource {
397
+ async list(params) {
398
+ const response = await this.client.get(
399
+ "/user_assignments",
400
+ params
401
+ );
402
+ return response.user_assignments ?? [];
403
+ }
404
+ listAll(params) {
405
+ return new Paginator(this.client, "/user_assignments", "user_assignments", params);
406
+ }
407
+ };
408
+ var ProjectUserAssignmentsResource = class {
409
+ constructor(client, projectId) {
410
+ this.client = client;
411
+ this.projectId = projectId;
412
+ }
413
+ get path() {
414
+ return `/projects/${this.projectId}/user_assignments`;
415
+ }
416
+ async list(params) {
417
+ const response = await this.client.get(this.path, params);
418
+ return response.user_assignments ?? [];
419
+ }
420
+ listAll(params) {
421
+ return new Paginator(this.client, this.path, "user_assignments", params);
422
+ }
423
+ async get(id) {
424
+ return this.client.get(`${this.path}/${id}`);
425
+ }
426
+ async create(data) {
427
+ return this.client.post(this.path, data);
428
+ }
429
+ async update(id, data) {
430
+ return this.client.patch(`${this.path}/${id}`, data);
431
+ }
432
+ async delete(id) {
433
+ return this.client.delete(`${this.path}/${id}`);
434
+ }
435
+ };
436
+
437
+ // src/resources/taskAssignments.ts
438
+ var TaskAssignmentsResource = class extends BaseResource {
439
+ async list(params) {
440
+ const response = await this.client.get(
441
+ "/task_assignments",
442
+ params
443
+ );
444
+ return response.task_assignments ?? [];
445
+ }
446
+ listAll(params) {
447
+ return new Paginator(this.client, "/task_assignments", "task_assignments", params);
448
+ }
449
+ };
450
+ var ProjectTaskAssignmentsResource = class {
451
+ constructor(client, projectId) {
452
+ this.client = client;
453
+ this.projectId = projectId;
454
+ }
455
+ get path() {
456
+ return `/projects/${this.projectId}/task_assignments`;
457
+ }
458
+ async list(params) {
459
+ const response = await this.client.get(this.path, params);
460
+ return response.task_assignments ?? [];
461
+ }
462
+ listAll(params) {
463
+ return new Paginator(this.client, this.path, "task_assignments", params);
464
+ }
465
+ async get(id) {
466
+ return this.client.get(`${this.path}/${id}`);
467
+ }
468
+ async create(data) {
469
+ return this.client.post(this.path, data);
470
+ }
471
+ async update(id, data) {
472
+ return this.client.patch(`${this.path}/${id}`, data);
473
+ }
474
+ async delete(id) {
475
+ return this.client.delete(`${this.path}/${id}`);
476
+ }
477
+ };
478
+
479
+ // src/resources/projects.ts
480
+ var ProjectsResource = class extends CrudResource {
481
+ path = "/projects";
482
+ dataKey = "projects";
483
+ /** Access user assignments nested under a project. */
484
+ userAssignments(projectId) {
485
+ return new ProjectUserAssignmentsResource(this.client, projectId);
486
+ }
487
+ /** Access task assignments nested under a project. */
488
+ taskAssignments(projectId) {
489
+ return new ProjectTaskAssignmentsResource(this.client, projectId);
490
+ }
491
+ };
492
+
493
+ // src/resources/reports.ts
494
+ var TimeReports = class {
495
+ constructor(client) {
496
+ this.client = client;
497
+ }
498
+ async byClients(params) {
499
+ return this.client.get("/reports/time/clients", params);
500
+ }
501
+ async byProjects(params) {
502
+ return this.client.get("/reports/time/projects", params);
503
+ }
504
+ async byTasks(params) {
505
+ return this.client.get("/reports/time/tasks", params);
506
+ }
507
+ async byTeam(params) {
508
+ return this.client.get("/reports/time/team", params);
509
+ }
510
+ };
511
+ var ExpenseReports = class {
512
+ constructor(client) {
513
+ this.client = client;
514
+ }
515
+ async byClients(params) {
516
+ return this.client.get("/reports/expenses/clients", params);
517
+ }
518
+ async byProjects(params) {
519
+ return this.client.get("/reports/expenses/projects", params);
520
+ }
521
+ async byCategories(params) {
522
+ return this.client.get("/reports/expenses/categories", params);
523
+ }
524
+ async byTeam(params) {
525
+ return this.client.get("/reports/expenses/team", params);
526
+ }
527
+ };
528
+ var ReportsResource = class {
529
+ constructor(client) {
530
+ this.client = client;
531
+ this.time = new TimeReports(client);
532
+ this.expenses = new ExpenseReports(client);
533
+ }
534
+ time;
535
+ expenses;
536
+ async uninvoiced(params) {
537
+ return this.client.get("/reports/uninvoiced", params);
538
+ }
539
+ async projectBudget(params) {
540
+ return this.client.get("/reports/project_budget", params);
541
+ }
542
+ };
543
+
544
+ // src/resources/roles.ts
545
+ var RolesResource = class extends CrudResource {
546
+ path = "/roles";
547
+ dataKey = "roles";
548
+ };
549
+
550
+ // src/resources/tasks.ts
551
+ var TasksResource = class extends CrudResource {
552
+ path = "/tasks";
553
+ dataKey = "tasks";
554
+ };
555
+
556
+ // src/resources/timeEntries.ts
557
+ var TimeEntriesResource = class extends CrudResource {
558
+ path = "/time_entries";
559
+ dataKey = "time_entries";
560
+ /** Stop a running time entry timer. */
561
+ async stop(id) {
562
+ return this.client.patch(`/time_entries/${id}/stop`);
563
+ }
564
+ /** Restart a stopped time entry timer. */
565
+ async restart(id) {
566
+ return this.client.patch(`/time_entries/${id}/restart`);
567
+ }
568
+ /** Delete external reference for a time entry. */
569
+ async deleteExternalReference(id) {
570
+ return this.client.delete(`/time_entries/${id}/external_reference`);
571
+ }
572
+ };
573
+
574
+ // src/resources/users.ts
575
+ var UsersResource = class extends CrudResource {
576
+ path = "/users";
577
+ dataKey = "users";
578
+ /** Retrieve the currently authenticated user. */
579
+ async me() {
580
+ return this.client.get("/users/me");
581
+ }
582
+ /** List project assignments for the current user. */
583
+ async myProjectAssignments(params) {
584
+ const response = await this.client.get(
585
+ "/users/me/project_assignments",
586
+ params
587
+ );
588
+ return response.project_assignments ?? [];
589
+ }
590
+ /** Access billable rates for a user. */
591
+ billableRates(userId) {
592
+ return new UserBillableRatesResource(this.client, userId);
593
+ }
594
+ /** Access cost rates for a user. */
595
+ costRates(userId) {
596
+ return new UserCostRatesResource(this.client, userId);
597
+ }
598
+ /** Access teammates for a user. */
599
+ teammates(userId) {
600
+ return new UserTeammatesResource(this.client, userId);
601
+ }
602
+ /** List project assignments for a specific user. */
603
+ projectAssignments(userId) {
604
+ return new UserProjectAssignmentsResource(this.client, userId);
605
+ }
606
+ };
607
+ var UserBillableRatesResource = class {
608
+ constructor(client, userId) {
609
+ this.client = client;
610
+ this.userId = userId;
611
+ }
612
+ get path() {
613
+ return `/users/${this.userId}/billable_rates`;
614
+ }
615
+ async list(params) {
616
+ const response = await this.client.get(this.path, params);
617
+ return response.billable_rates ?? [];
618
+ }
619
+ listAll(params) {
620
+ return new Paginator(this.client, this.path, "billable_rates", params);
621
+ }
622
+ async get(id) {
623
+ return this.client.get(`${this.path}/${id}`);
624
+ }
625
+ async create(data) {
626
+ return this.client.post(this.path, data);
627
+ }
628
+ };
629
+ var UserCostRatesResource = class {
630
+ constructor(client, userId) {
631
+ this.client = client;
632
+ this.userId = userId;
633
+ }
634
+ get path() {
635
+ return `/users/${this.userId}/cost_rates`;
636
+ }
637
+ async list(params) {
638
+ const response = await this.client.get(this.path, params);
639
+ return response.cost_rates ?? [];
640
+ }
641
+ listAll(params) {
642
+ return new Paginator(this.client, this.path, "cost_rates", params);
643
+ }
644
+ async get(id) {
645
+ return this.client.get(`${this.path}/${id}`);
646
+ }
647
+ async create(data) {
648
+ return this.client.post(this.path, data);
649
+ }
650
+ };
651
+ var UserTeammatesResource = class {
652
+ constructor(client, userId) {
653
+ this.client = client;
654
+ this.userId = userId;
655
+ }
656
+ get path() {
657
+ return `/users/${this.userId}/teammates`;
658
+ }
659
+ async list(params) {
660
+ const response = await this.client.get(this.path, params);
661
+ return response.teammates ?? [];
662
+ }
663
+ /** Update (replace) teammates for a user. */
664
+ async update(data) {
665
+ const response = await this.client.patch(this.path, data);
666
+ return response.teammates ?? [];
667
+ }
668
+ };
669
+ var UserProjectAssignmentsResource = class {
670
+ constructor(client, userId) {
671
+ this.client = client;
672
+ this.userId = userId;
673
+ }
674
+ get path() {
675
+ return `/users/${this.userId}/project_assignments`;
676
+ }
677
+ async list(params) {
678
+ const response = await this.client.get(this.path, params);
679
+ return response.project_assignments ?? [];
680
+ }
681
+ listAll(params) {
682
+ return new Paginator(this.client, this.path, "project_assignments", params);
683
+ }
684
+ };
685
+
686
+ // src/index.ts
687
+ var Harvest = class {
688
+ clients;
689
+ company;
690
+ contacts;
691
+ estimateItemCategories;
692
+ estimates;
693
+ expenseCategories;
694
+ expenses;
695
+ invoiceItemCategories;
696
+ invoices;
697
+ projects;
698
+ reports;
699
+ roles;
700
+ taskAssignments;
701
+ tasks;
702
+ timeEntries;
703
+ userAssignments;
704
+ users;
705
+ constructor(config) {
706
+ const client = new HarvestClient(config);
707
+ this.clients = new ClientsResource(client);
708
+ this.company = new CompanyResource(client);
709
+ this.contacts = new ContactsResource(client);
710
+ this.estimateItemCategories = new EstimateItemCategoriesResource(client);
711
+ this.estimates = new EstimatesResource(client);
712
+ this.expenseCategories = new ExpenseCategoriesResource(client);
713
+ this.expenses = new ExpensesResource(client);
714
+ this.invoiceItemCategories = new InvoiceItemCategoriesResource(client);
715
+ this.invoices = new InvoicesResource(client);
716
+ this.projects = new ProjectsResource(client);
717
+ this.reports = new ReportsResource(client);
718
+ this.roles = new RolesResource(client);
719
+ this.taskAssignments = new TaskAssignmentsResource(client);
720
+ this.tasks = new TasksResource(client);
721
+ this.timeEntries = new TimeEntriesResource(client);
722
+ this.userAssignments = new UserAssignmentsResource(client);
723
+ this.users = new UsersResource(client);
724
+ }
725
+ };
726
+ // Annotate the CommonJS export names for ESM import in node:
727
+ 0 && (module.exports = {
728
+ ClientsResource,
729
+ CompanyResource,
730
+ ContactsResource,
731
+ EstimateItemCategoriesResource,
732
+ EstimateMessagesResource,
733
+ EstimatesResource,
734
+ ExpenseCategoriesResource,
735
+ ExpenseReports,
736
+ ExpensesResource,
737
+ Harvest,
738
+ HarvestApiError,
739
+ HarvestClient,
740
+ HarvestNotFoundError,
741
+ HarvestRateLimitError,
742
+ HarvestUnprocessableError,
743
+ InvoiceItemCategoriesResource,
744
+ InvoiceMessagesResource,
745
+ InvoicesResource,
746
+ Paginator,
747
+ ProjectTaskAssignmentsResource,
748
+ ProjectUserAssignmentsResource,
749
+ ProjectsResource,
750
+ ReportsResource,
751
+ RolesResource,
752
+ TaskAssignmentsResource,
753
+ TasksResource,
754
+ TimeEntriesResource,
755
+ TimeReports,
756
+ UserAssignmentsResource,
757
+ UserBillableRatesResource,
758
+ UserCostRatesResource,
759
+ UserProjectAssignmentsResource,
760
+ UserTeammatesResource,
761
+ UsersResource
762
+ });