@pipedream/harvest 0.0.6 → 1.0.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/README.md +7 -12
- package/actions/create-invoice/create-invoice.mjs +116 -0
- package/actions/create-project/create-project.mjs +138 -0
- package/actions/create-task-assignment/create-task-assignment.mjs +77 -0
- package/actions/create-timesheet-entry/create-timesheet-entry.mjs +39 -38
- package/actions/create-user/create-user.mjs +109 -0
- package/actions/create-user-assignment/create-user-assignment.mjs +85 -0
- package/actions/delete-invoice/delete-invoice.mjs +38 -0
- package/actions/delete-project/delete-project.mjs +38 -0
- package/actions/delete-task-assignment/delete-task-assignment.mjs +45 -0
- package/actions/delete-time-entry/delete-time-entry.mjs +38 -0
- package/actions/delete-user/delete-user.mjs +39 -0
- package/actions/delete-user-assignment/delete-user-assignment.mjs +45 -0
- package/actions/get-invoice/get-invoice.mjs +39 -0
- package/actions/get-me/get-me.mjs +32 -0
- package/actions/get-project/get-project.mjs +39 -0
- package/actions/get-projects/get-projects.mjs +20 -12
- package/actions/get-task-assignment/get-task-assignment.mjs +46 -0
- package/actions/get-time-entry/get-time-entry.mjs +39 -0
- package/actions/get-time-report/get-time-report.mjs +80 -0
- package/actions/get-user/get-user.mjs +40 -0
- package/actions/get-user-assignment/get-user-assignment.mjs +46 -0
- package/actions/list-account-id-options/list-account-id-options.mjs +33 -0
- package/actions/list-clients/list-clients.mjs +57 -0
- package/actions/list-invoices/list-invoices.mjs +86 -0
- package/actions/list-task-assignments/list-task-assignments.mjs +66 -0
- package/actions/list-tasks/list-tasks.mjs +57 -0
- package/actions/list-time-entries/list-time-entries.mjs +150 -0
- package/actions/list-user-assignments/list-user-assignments.mjs +74 -0
- package/actions/list-users/list-users.mjs +57 -0
- package/actions/start-timer/start-timer.mjs +9 -6
- package/actions/stop-timer/stop-timer.mjs +9 -6
- package/actions/update-invoice/update-invoice.mjs +114 -0
- package/actions/update-project/update-project.mjs +140 -0
- package/actions/update-task-assignment/update-task-assignment.mjs +77 -0
- package/actions/update-time-entry/update-time-entry.mjs +92 -0
- package/actions/update-user/update-user.mjs +106 -0
- package/actions/update-user-assignment/update-user-assignment.mjs +84 -0
- package/common/constants.mjs +51 -1
- package/common/utils.mjs +50 -1
- package/harvest.app.mjs +683 -110
- package/package.json +3 -3
- package/sources/new-invoice-entry/new-invoice-entry.mjs +1 -1
- package/sources/new-timesheet-entry/new-timesheet-entry.mjs +1 -1
package/harvest.app.mjs
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import constants from "./common/constants.mjs";
|
|
2
|
-
import {
|
|
3
|
-
axios, ConfigurationError,
|
|
4
|
-
} from "@pipedream/platform";
|
|
2
|
+
import { axios } from "@pipedream/platform";
|
|
5
3
|
import retry from "async-retry";
|
|
6
4
|
|
|
7
5
|
export default {
|
|
@@ -11,116 +9,279 @@ export default {
|
|
|
11
9
|
projectId: {
|
|
12
10
|
type: "string",
|
|
13
11
|
label: "Project ID",
|
|
14
|
-
description: "
|
|
15
|
-
useQuery: true,
|
|
16
|
-
async options({
|
|
17
|
-
page, accountId,
|
|
18
|
-
}) {
|
|
19
|
-
const response = await this.listProjects({
|
|
20
|
-
perPage: constants.PAGE_SIZE,
|
|
21
|
-
page: page + 1,
|
|
22
|
-
accountId,
|
|
23
|
-
});
|
|
24
|
-
return response.projects.map((project) => ({
|
|
25
|
-
label: project.name,
|
|
26
|
-
value: project.id,
|
|
27
|
-
}));
|
|
28
|
-
},
|
|
12
|
+
description: "Free-form project ID, e.g. `14308069`. Run **Get Projects** first to find valid IDs.",
|
|
29
13
|
},
|
|
30
14
|
taskId: {
|
|
31
15
|
type: "string",
|
|
32
16
|
label: "Task ID",
|
|
33
|
-
description: "
|
|
34
|
-
useQuery: true,
|
|
35
|
-
async options({
|
|
36
|
-
page, accountId,
|
|
37
|
-
}) {
|
|
38
|
-
const response = await this.listTasks({
|
|
39
|
-
perPage: constants.PAGE_SIZE,
|
|
40
|
-
page: page + 1,
|
|
41
|
-
accountId,
|
|
42
|
-
});
|
|
43
|
-
return response.tasks.map((task) => ({
|
|
44
|
-
label: task.name,
|
|
45
|
-
value: task.id,
|
|
46
|
-
}));
|
|
47
|
-
},
|
|
17
|
+
description: "Free-form task ID, e.g. `1467097`. Run **List Tasks** first to find valid IDs.",
|
|
48
18
|
},
|
|
49
19
|
userId: {
|
|
50
20
|
type: "string",
|
|
51
21
|
label: "User ID",
|
|
52
|
-
description: "
|
|
53
|
-
|
|
54
|
-
optional: true,
|
|
55
|
-
async options({
|
|
56
|
-
page, accountId,
|
|
57
|
-
}) {
|
|
58
|
-
const response = await this.listUsers({
|
|
59
|
-
perPage: constants.PAGE_SIZE,
|
|
60
|
-
page: page + 1,
|
|
61
|
-
accountId,
|
|
62
|
-
});
|
|
63
|
-
return response.users.map((user) => ({
|
|
64
|
-
label: `${user.first_name} ${user.last_name}`,
|
|
65
|
-
value: user.id,
|
|
66
|
-
}));
|
|
67
|
-
},
|
|
22
|
+
description: "Free-form user ID, e.g. `1782959`. Run **List Users** first to find valid IDs.",
|
|
23
|
+
optional: true,
|
|
68
24
|
},
|
|
69
25
|
clientId: {
|
|
70
26
|
type: "string",
|
|
71
27
|
label: "Client ID",
|
|
72
|
-
description: "
|
|
73
|
-
|
|
74
|
-
optional: true,
|
|
75
|
-
async options({
|
|
76
|
-
page, accountId,
|
|
77
|
-
}) {
|
|
78
|
-
const response = await this.listClients({
|
|
79
|
-
perPage: constants.PAGE_SIZE,
|
|
80
|
-
page: page + 1,
|
|
81
|
-
accountId,
|
|
82
|
-
});
|
|
83
|
-
return response.clients.map((client) => ({
|
|
84
|
-
label: client.name,
|
|
85
|
-
value: client.id,
|
|
86
|
-
}));
|
|
87
|
-
},
|
|
28
|
+
description: "Free-form client ID, e.g. `5735776`. Run **List Clients** first to find valid IDs.",
|
|
29
|
+
optional: true,
|
|
88
30
|
},
|
|
89
31
|
timeEntryId: {
|
|
90
32
|
type: "string",
|
|
91
|
-
label: "Time
|
|
92
|
-
description: "
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
}));
|
|
109
|
-
},
|
|
33
|
+
label: "Time Entry ID",
|
|
34
|
+
description: "Free-form time entry ID, e.g. `636708723`. Run **List Time Entries** first to find valid IDs.",
|
|
35
|
+
},
|
|
36
|
+
invoiceId: {
|
|
37
|
+
type: "string",
|
|
38
|
+
label: "Invoice ID",
|
|
39
|
+
description: "Free-form invoice ID, e.g. `13150403`. Run **List Invoices** first to find valid IDs.",
|
|
40
|
+
},
|
|
41
|
+
taskAssignmentId: {
|
|
42
|
+
type: "string",
|
|
43
|
+
label: "Task Assignment ID",
|
|
44
|
+
description: "Free-form task assignment ID, e.g. `162728`. Run **List Task Assignments** first to find valid IDs.",
|
|
45
|
+
},
|
|
46
|
+
userAssignmentId: {
|
|
47
|
+
type: "string",
|
|
48
|
+
label: "User Assignment ID",
|
|
49
|
+
description: "Free-form user assignment ID, e.g. `195420`. Run **List User Assignments** first to find valid IDs.",
|
|
110
50
|
},
|
|
111
51
|
accountId: {
|
|
112
52
|
type: "string",
|
|
113
53
|
label: "Account ID",
|
|
114
|
-
description: "
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
54
|
+
description: "Your Harvest account ID, e.g. `1234567`. Run **List Account ID Options** to find it.",
|
|
55
|
+
},
|
|
56
|
+
isActive: {
|
|
57
|
+
type: "boolean",
|
|
58
|
+
label: "Is Active",
|
|
59
|
+
description: "Whether the record is active.",
|
|
60
|
+
optional: true,
|
|
61
|
+
},
|
|
62
|
+
updatedSince: {
|
|
63
|
+
type: "string",
|
|
64
|
+
label: "Updated Since",
|
|
65
|
+
description: "Only return records updated since this UTC datetime, e.g. `2019-06-25T15:30:00Z`.",
|
|
66
|
+
optional: true,
|
|
67
|
+
},
|
|
68
|
+
accessRoles: {
|
|
69
|
+
type: "string[]",
|
|
70
|
+
label: "Access Roles",
|
|
71
|
+
description: "Access roles for the user. One of `member`, `manager`, `administrator`; or one of `project_creator`, `billable_rates_manager`, `managed_projects_invoice_drafter`, `managed_projects_invoice_manager`, `client_and_task_manager`, `time_and_expenses_manager`, `estimates_manager` — these additional roles can only be combined with `manager`.",
|
|
72
|
+
optional: true,
|
|
73
|
+
options: constants.ACCESS_ROLE_OPTIONS,
|
|
74
|
+
},
|
|
75
|
+
// Project
|
|
76
|
+
projectName: {
|
|
77
|
+
type: "string",
|
|
78
|
+
label: "Project Name",
|
|
79
|
+
description: "The name of the project. Run **Get Project** or **Get Projects** to see names on existing projects.",
|
|
80
|
+
optional: true,
|
|
81
|
+
},
|
|
82
|
+
isBillable: {
|
|
83
|
+
type: "boolean",
|
|
84
|
+
label: "Is Billable",
|
|
85
|
+
description: "Whether the project is billable.",
|
|
86
|
+
optional: true,
|
|
87
|
+
},
|
|
88
|
+
billBy: {
|
|
89
|
+
type: "string",
|
|
90
|
+
label: "Bill By",
|
|
91
|
+
description: "Method by which the project is invoiced. One of: `Project`, `Tasks`, `People`, `none`.",
|
|
92
|
+
optional: true,
|
|
93
|
+
options: constants.BILL_BY_OPTIONS,
|
|
94
|
+
},
|
|
95
|
+
budgetBy: {
|
|
96
|
+
type: "string",
|
|
97
|
+
label: "Budget By",
|
|
98
|
+
description: "Method by which the project is budgeted. `project`, `task`, and `person` budget in hours (set Budget); `project_cost` and `task_fees` budget in money (set Cost Budget); `none` sets no budget.",
|
|
99
|
+
optional: true,
|
|
100
|
+
options: constants.BUDGET_BY_OPTIONS,
|
|
101
|
+
},
|
|
102
|
+
code: {
|
|
103
|
+
type: "string",
|
|
104
|
+
label: "Code",
|
|
105
|
+
description: "The code associated with the project, e.g. `PRJ-100`. Run **Get Project** or **Get Projects** to see codes on existing projects.",
|
|
106
|
+
optional: true,
|
|
107
|
+
},
|
|
108
|
+
isFixedFee: {
|
|
109
|
+
type: "boolean",
|
|
110
|
+
label: "Is Fixed Fee",
|
|
111
|
+
description: "Whether the project is a fixed-fee project.",
|
|
112
|
+
optional: true,
|
|
113
|
+
},
|
|
114
|
+
projectHourlyRate: {
|
|
115
|
+
type: "string",
|
|
116
|
+
label: "Hourly Rate",
|
|
117
|
+
description: "Rate for projects billed by Project Hourly Rate, decimal, e.g. `150` or `150.00`. Run **Get Project** to see the current rate.",
|
|
118
|
+
optional: true,
|
|
119
|
+
},
|
|
120
|
+
projectBudget: {
|
|
121
|
+
type: "string",
|
|
122
|
+
label: "Budget",
|
|
123
|
+
description: "The budget in **hours**, decimal, e.g. `120` or `120.5`. Only applies when Budget By is `project`, `task`, or `person`. Run **Get Project** to see the current budget.",
|
|
124
|
+
optional: true,
|
|
125
|
+
},
|
|
126
|
+
costBudget: {
|
|
127
|
+
type: "string",
|
|
128
|
+
label: "Cost Budget",
|
|
129
|
+
description: "The budget in **money**, decimal, e.g. `10000` or `10000.00`. Only applies when Budget By is `project_cost` or `task_fees`. Run **Get Project** to see the current cost budget.",
|
|
130
|
+
optional: true,
|
|
131
|
+
},
|
|
132
|
+
projectNotes: {
|
|
133
|
+
type: "string",
|
|
134
|
+
label: "Notes",
|
|
135
|
+
description: "Notes about the project. Run **Get Project** to see any existing notes.",
|
|
136
|
+
optional: true,
|
|
137
|
+
},
|
|
138
|
+
startsOn: {
|
|
139
|
+
type: "string",
|
|
140
|
+
label: "Starts On",
|
|
141
|
+
description: "Start date, format `YYYY-MM-DD`, e.g. `2026-09-01`. Run **Get Project** to see the current start date.",
|
|
142
|
+
optional: true,
|
|
143
|
+
},
|
|
144
|
+
endsOn: {
|
|
145
|
+
type: "string",
|
|
146
|
+
label: "Ends On",
|
|
147
|
+
description: "End date, format `YYYY-MM-DD`, e.g. `2026-12-31`. Run **Get Project** to see the current end date.",
|
|
148
|
+
optional: true,
|
|
149
|
+
},
|
|
150
|
+
// Invoice
|
|
151
|
+
subject: {
|
|
152
|
+
type: "string",
|
|
153
|
+
label: "Subject",
|
|
154
|
+
description: "The invoice subject. Run **Get Invoice** to see the current subject.",
|
|
155
|
+
optional: true,
|
|
156
|
+
},
|
|
157
|
+
invoiceNumber: {
|
|
158
|
+
type: "string",
|
|
159
|
+
label: "Number",
|
|
160
|
+
description: "The invoice number, e.g. `1000`. Run **Get Invoice** to see the current number.",
|
|
161
|
+
optional: true,
|
|
162
|
+
},
|
|
163
|
+
purchaseOrder: {
|
|
164
|
+
type: "string",
|
|
165
|
+
label: "Purchase Order",
|
|
166
|
+
description: "The purchase order number, e.g. `PO-1234`. Run **Get Invoice** to see the current value.",
|
|
167
|
+
optional: true,
|
|
168
|
+
},
|
|
169
|
+
tax: {
|
|
170
|
+
type: "string",
|
|
171
|
+
label: "Tax",
|
|
172
|
+
description: "First tax rate percentage, decimal, e.g. `5.5` for 5.5%. Run **Get Invoice** to see the current rate.",
|
|
173
|
+
optional: true,
|
|
174
|
+
},
|
|
175
|
+
discount: {
|
|
176
|
+
type: "string",
|
|
177
|
+
label: "Discount",
|
|
178
|
+
description: "Discount percentage, decimal, e.g. `10` for 10%. Run **Get Invoice** to see the current discount.",
|
|
179
|
+
optional: true,
|
|
180
|
+
},
|
|
181
|
+
invoiceNotes: {
|
|
182
|
+
type: "string",
|
|
183
|
+
label: "Notes",
|
|
184
|
+
description: "Notes about the invoice. Run **Get Invoice** to see any existing notes.",
|
|
185
|
+
optional: true,
|
|
186
|
+
},
|
|
187
|
+
issueDate: {
|
|
188
|
+
type: "string",
|
|
189
|
+
label: "Issue Date",
|
|
190
|
+
description: "Issue date, `YYYY-MM-DD`, e.g. `2026-09-01`. Run **Get Invoice** to see the current issue date.",
|
|
191
|
+
optional: true,
|
|
192
|
+
},
|
|
193
|
+
dueDate: {
|
|
194
|
+
type: "string",
|
|
195
|
+
label: "Due Date",
|
|
196
|
+
description: "Due date, `YYYY-MM-DD`, e.g. `2026-09-30`. Run **Get Invoice** to see the current due date.",
|
|
197
|
+
optional: true,
|
|
198
|
+
},
|
|
199
|
+
// User
|
|
200
|
+
firstName: {
|
|
201
|
+
type: "string",
|
|
202
|
+
label: "First Name",
|
|
203
|
+
description: "The user's first name. Run **Get User** to see the current value.",
|
|
204
|
+
optional: true,
|
|
205
|
+
},
|
|
206
|
+
lastName: {
|
|
207
|
+
type: "string",
|
|
208
|
+
label: "Last Name",
|
|
209
|
+
description: "The user's last name. Run **Get User** to see the current value.",
|
|
210
|
+
optional: true,
|
|
211
|
+
},
|
|
212
|
+
email: {
|
|
213
|
+
type: "string",
|
|
214
|
+
label: "Email",
|
|
215
|
+
description: "The user's email address, e.g. `jane@example.com`. Run **Get User** to see the current value.",
|
|
216
|
+
optional: true,
|
|
217
|
+
},
|
|
218
|
+
timezone: {
|
|
219
|
+
type: "string",
|
|
220
|
+
label: "Timezone",
|
|
221
|
+
description: "The user's IANA timezone name, e.g. `America/Chicago`. Run **Get User** to see the current value.",
|
|
222
|
+
optional: true,
|
|
223
|
+
},
|
|
224
|
+
isContractor: {
|
|
225
|
+
type: "boolean",
|
|
226
|
+
label: "Is Contractor",
|
|
227
|
+
description: "Whether the user is a contractor.",
|
|
228
|
+
optional: true,
|
|
229
|
+
},
|
|
230
|
+
weeklyCapacity: {
|
|
231
|
+
type: "integer",
|
|
232
|
+
label: "Weekly Capacity",
|
|
233
|
+
description: "Expected weekly working capacity in seconds, e.g. `144000` for a 40-hour week. Run **Get User** to see the current value.",
|
|
234
|
+
optional: true,
|
|
235
|
+
},
|
|
236
|
+
defaultHourlyRate: {
|
|
237
|
+
type: "string",
|
|
238
|
+
label: "Default Hourly Rate",
|
|
239
|
+
description: "Default hourly rate, decimal, e.g. `150` or `150.00`. Run **Get User** to see the current rate.",
|
|
240
|
+
optional: true,
|
|
241
|
+
},
|
|
242
|
+
// Task assignment
|
|
243
|
+
billable: {
|
|
244
|
+
type: "boolean",
|
|
245
|
+
label: "Billable",
|
|
246
|
+
description: "Whether the task assignment is billable.",
|
|
247
|
+
optional: true,
|
|
248
|
+
},
|
|
249
|
+
taskAssignmentHourlyRate: {
|
|
250
|
+
type: "string",
|
|
251
|
+
label: "Hourly Rate",
|
|
252
|
+
description: "Rate used when the project's bill_by is Tasks, decimal, e.g. `150` or `150.00`. Run **Get Task Assignment** to see the current rate.",
|
|
253
|
+
optional: true,
|
|
254
|
+
},
|
|
255
|
+
taskAssignmentBudget: {
|
|
256
|
+
type: "string",
|
|
257
|
+
label: "Budget",
|
|
258
|
+
description: "Budget used when the project's budget_by is task or task_fees, decimal, e.g. `5000` or `5000.00`. Run **Get Task Assignment** to see the current budget.",
|
|
259
|
+
optional: true,
|
|
260
|
+
},
|
|
261
|
+
// User assignment
|
|
262
|
+
isProjectManager: {
|
|
263
|
+
type: "boolean",
|
|
264
|
+
label: "Is Project Manager",
|
|
265
|
+
description: "Whether the user is a project manager.",
|
|
266
|
+
optional: true,
|
|
267
|
+
},
|
|
268
|
+
useDefaultRates: {
|
|
269
|
+
type: "boolean",
|
|
270
|
+
label: "Use Default Rates",
|
|
271
|
+
description: "Whether to use the user's default rate.",
|
|
272
|
+
optional: true,
|
|
273
|
+
},
|
|
274
|
+
userAssignmentHourlyRate: {
|
|
275
|
+
type: "string",
|
|
276
|
+
label: "Hourly Rate",
|
|
277
|
+
description: "Custom hourly rate, decimal, e.g. `150` or `150.00`. Run **Get User Assignment** to see the current rate.",
|
|
278
|
+
optional: true,
|
|
279
|
+
},
|
|
280
|
+
userAssignmentBudget: {
|
|
281
|
+
type: "string",
|
|
282
|
+
label: "Budget",
|
|
283
|
+
description: "Budget used when budget_by is person, decimal, e.g. `5000` or `5000.00`. Run **Get User Assignment** to see the current budget.",
|
|
284
|
+
optional: true,
|
|
124
285
|
},
|
|
125
286
|
},
|
|
126
287
|
methods: {
|
|
@@ -175,7 +336,7 @@ export default {
|
|
|
175
336
|
});
|
|
176
337
|
},
|
|
177
338
|
_isRetriableStatusCode(statusCode) {
|
|
178
|
-
constants.
|
|
339
|
+
return constants.RETRIABLE_STATUS_CODES.includes(statusCode);
|
|
179
340
|
},
|
|
180
341
|
async _withRetries(apiCall) {
|
|
181
342
|
const retryOpts = {
|
|
@@ -188,27 +349,27 @@ export default {
|
|
|
188
349
|
|
|
189
350
|
return data;
|
|
190
351
|
} catch (err) {
|
|
191
|
-
const
|
|
352
|
+
const status = err?.response?.status ?? err?.status ?? 500;
|
|
192
353
|
if (!this._isRetriableStatusCode(status)) {
|
|
193
|
-
bail(
|
|
194
|
-
|
|
195
|
-
${JSON.stringify(err.response)}
|
|
196
|
-
`);
|
|
354
|
+
bail(err);
|
|
355
|
+
return;
|
|
197
356
|
}
|
|
198
|
-
throw
|
|
357
|
+
throw err;
|
|
199
358
|
}
|
|
200
359
|
}, retryOpts);
|
|
201
360
|
},
|
|
202
361
|
async *listTimeEntriesPaginated({
|
|
203
|
-
page, updatedSince,
|
|
362
|
+
page, $, accountId, updatedSince, ...params
|
|
204
363
|
}) {
|
|
205
364
|
do {
|
|
206
365
|
const response = await this._withRetries(
|
|
207
366
|
() => this.listTimeEntries({
|
|
208
367
|
per_page: constants.PAGE_SIZE,
|
|
209
368
|
page,
|
|
210
|
-
|
|
369
|
+
$,
|
|
211
370
|
accountId,
|
|
371
|
+
updated_since: updatedSince,
|
|
372
|
+
...params,
|
|
212
373
|
}),
|
|
213
374
|
);
|
|
214
375
|
|
|
@@ -225,15 +386,17 @@ export default {
|
|
|
225
386
|
} while (true);
|
|
226
387
|
},
|
|
227
388
|
async *listInvoicesPaginated({
|
|
228
|
-
page, updatedSince,
|
|
389
|
+
page, $, accountId, updatedSince, ...params
|
|
229
390
|
}) {
|
|
230
391
|
do {
|
|
231
392
|
const response = await this._withRetries(
|
|
232
393
|
() => this.listInvoices({
|
|
233
394
|
per_page: constants.PAGE_SIZE,
|
|
234
395
|
page,
|
|
235
|
-
|
|
396
|
+
$,
|
|
236
397
|
accountId,
|
|
398
|
+
updated_since: updatedSince,
|
|
399
|
+
...params,
|
|
237
400
|
}),
|
|
238
401
|
);
|
|
239
402
|
|
|
@@ -274,6 +437,139 @@ export default {
|
|
|
274
437
|
page += 1;
|
|
275
438
|
} while (true);
|
|
276
439
|
},
|
|
440
|
+
async *listClientsPaginated({
|
|
441
|
+
page, $, accountId, isActive, updatedSince,
|
|
442
|
+
}) {
|
|
443
|
+
do {
|
|
444
|
+
const response = await this._withRetries(
|
|
445
|
+
() => this.listClients({
|
|
446
|
+
perPage: constants.PAGE_SIZE,
|
|
447
|
+
page,
|
|
448
|
+
$,
|
|
449
|
+
accountId,
|
|
450
|
+
isActive,
|
|
451
|
+
updatedSince,
|
|
452
|
+
}),
|
|
453
|
+
);
|
|
454
|
+
|
|
455
|
+
if (response.clients.length === 0) {
|
|
456
|
+
return;
|
|
457
|
+
}
|
|
458
|
+
for (const client of response.clients) {
|
|
459
|
+
yield client;
|
|
460
|
+
}
|
|
461
|
+
if (!response.next_page) {
|
|
462
|
+
return;
|
|
463
|
+
}
|
|
464
|
+
page += 1;
|
|
465
|
+
} while (true);
|
|
466
|
+
},
|
|
467
|
+
async *listTasksPaginated({
|
|
468
|
+
page, $, accountId, isActive, updatedSince,
|
|
469
|
+
}) {
|
|
470
|
+
do {
|
|
471
|
+
const response = await this._withRetries(
|
|
472
|
+
() => this.listTasks({
|
|
473
|
+
perPage: constants.PAGE_SIZE,
|
|
474
|
+
page,
|
|
475
|
+
$,
|
|
476
|
+
accountId,
|
|
477
|
+
isActive,
|
|
478
|
+
updatedSince,
|
|
479
|
+
}),
|
|
480
|
+
);
|
|
481
|
+
|
|
482
|
+
if (response.tasks.length === 0) {
|
|
483
|
+
return;
|
|
484
|
+
}
|
|
485
|
+
for (const task of response.tasks) {
|
|
486
|
+
yield task;
|
|
487
|
+
}
|
|
488
|
+
if (!response.next_page) {
|
|
489
|
+
return;
|
|
490
|
+
}
|
|
491
|
+
page += 1;
|
|
492
|
+
} while (true);
|
|
493
|
+
},
|
|
494
|
+
async *listUsersPaginated({
|
|
495
|
+
page, $, accountId, isActive, updatedSince,
|
|
496
|
+
}) {
|
|
497
|
+
do {
|
|
498
|
+
const response = await this._withRetries(
|
|
499
|
+
() => this.listUsers({
|
|
500
|
+
perPage: constants.PAGE_SIZE,
|
|
501
|
+
page,
|
|
502
|
+
$,
|
|
503
|
+
accountId,
|
|
504
|
+
isActive,
|
|
505
|
+
updatedSince,
|
|
506
|
+
}),
|
|
507
|
+
);
|
|
508
|
+
|
|
509
|
+
if (response.users.length === 0) {
|
|
510
|
+
return;
|
|
511
|
+
}
|
|
512
|
+
for (const user of response.users) {
|
|
513
|
+
yield user;
|
|
514
|
+
}
|
|
515
|
+
if (!response.next_page) {
|
|
516
|
+
return;
|
|
517
|
+
}
|
|
518
|
+
page += 1;
|
|
519
|
+
} while (true);
|
|
520
|
+
},
|
|
521
|
+
async *listTaskAssignmentsPaginated({
|
|
522
|
+
page, $, accountId, ...params
|
|
523
|
+
}) {
|
|
524
|
+
do {
|
|
525
|
+
const response = await this._withRetries(
|
|
526
|
+
() => this.listTaskAssignments({
|
|
527
|
+
per_page: constants.PAGE_SIZE,
|
|
528
|
+
page,
|
|
529
|
+
$,
|
|
530
|
+
accountId,
|
|
531
|
+
...params,
|
|
532
|
+
}),
|
|
533
|
+
);
|
|
534
|
+
|
|
535
|
+
if (response.task_assignments.length === 0) {
|
|
536
|
+
return;
|
|
537
|
+
}
|
|
538
|
+
for (const assignment of response.task_assignments) {
|
|
539
|
+
yield assignment;
|
|
540
|
+
}
|
|
541
|
+
if (!response.next_page) {
|
|
542
|
+
return;
|
|
543
|
+
}
|
|
544
|
+
page += 1;
|
|
545
|
+
} while (true);
|
|
546
|
+
},
|
|
547
|
+
async *listUserAssignmentsPaginated({
|
|
548
|
+
page, $, accountId, ...params
|
|
549
|
+
}) {
|
|
550
|
+
do {
|
|
551
|
+
const response = await this._withRetries(
|
|
552
|
+
() => this.listUserAssignments({
|
|
553
|
+
per_page: constants.PAGE_SIZE,
|
|
554
|
+
page,
|
|
555
|
+
$,
|
|
556
|
+
accountId,
|
|
557
|
+
...params,
|
|
558
|
+
}),
|
|
559
|
+
);
|
|
560
|
+
|
|
561
|
+
if (response.user_assignments.length === 0) {
|
|
562
|
+
return;
|
|
563
|
+
}
|
|
564
|
+
for (const assignment of response.user_assignments) {
|
|
565
|
+
yield assignment;
|
|
566
|
+
}
|
|
567
|
+
if (!response.next_page) {
|
|
568
|
+
return;
|
|
569
|
+
}
|
|
570
|
+
page += 1;
|
|
571
|
+
} while (true);
|
|
572
|
+
},
|
|
277
573
|
async getProject({
|
|
278
574
|
$, projectId, accountId,
|
|
279
575
|
}) {
|
|
@@ -297,7 +593,7 @@ export default {
|
|
|
297
593
|
});
|
|
298
594
|
},
|
|
299
595
|
async listTasks({
|
|
300
|
-
$, perPage, page, accountId,
|
|
596
|
+
$, perPage, page, accountId, isActive, updatedSince,
|
|
301
597
|
}) {
|
|
302
598
|
return this._makeRequest({
|
|
303
599
|
$,
|
|
@@ -305,12 +601,14 @@ export default {
|
|
|
305
601
|
params: {
|
|
306
602
|
per_page: perPage,
|
|
307
603
|
page,
|
|
604
|
+
is_active: isActive,
|
|
605
|
+
updated_since: updatedSince,
|
|
308
606
|
},
|
|
309
607
|
accountId,
|
|
310
608
|
});
|
|
311
609
|
},
|
|
312
610
|
async listUsers({
|
|
313
|
-
$, perPage, page, accountId,
|
|
611
|
+
$, perPage, page, accountId, isActive, updatedSince,
|
|
314
612
|
}) {
|
|
315
613
|
return this._makeRequest({
|
|
316
614
|
$,
|
|
@@ -318,12 +616,14 @@ export default {
|
|
|
318
616
|
params: {
|
|
319
617
|
per_page: perPage,
|
|
320
618
|
page,
|
|
619
|
+
is_active: isActive,
|
|
620
|
+
updated_since: updatedSince,
|
|
321
621
|
},
|
|
322
622
|
accountId,
|
|
323
623
|
});
|
|
324
624
|
},
|
|
325
625
|
async listClients({
|
|
326
|
-
$, perPage, page, accountId,
|
|
626
|
+
$, perPage, page, accountId, isActive, updatedSince,
|
|
327
627
|
}) {
|
|
328
628
|
return this._makeRequest({
|
|
329
629
|
$,
|
|
@@ -331,17 +631,19 @@ export default {
|
|
|
331
631
|
params: {
|
|
332
632
|
per_page: perPage,
|
|
333
633
|
page,
|
|
634
|
+
is_active: isActive,
|
|
635
|
+
updated_since: updatedSince,
|
|
334
636
|
},
|
|
335
637
|
accountId,
|
|
336
638
|
});
|
|
337
639
|
},
|
|
338
640
|
async createTimeEntry({
|
|
339
|
-
$,
|
|
641
|
+
$, data, accountId,
|
|
340
642
|
}) {
|
|
341
643
|
return this._makeRequest({
|
|
342
644
|
$,
|
|
343
645
|
path: "/time_entries",
|
|
344
|
-
|
|
646
|
+
data,
|
|
345
647
|
method: "post",
|
|
346
648
|
accountId,
|
|
347
649
|
});
|
|
@@ -387,5 +689,276 @@ export default {
|
|
|
387
689
|
params,
|
|
388
690
|
});
|
|
389
691
|
},
|
|
692
|
+
async getTimeEntry({
|
|
693
|
+
$, id, accountId,
|
|
694
|
+
}) {
|
|
695
|
+
return this._makeRequest({
|
|
696
|
+
$,
|
|
697
|
+
path: `/time_entries/${id}`,
|
|
698
|
+
accountId,
|
|
699
|
+
});
|
|
700
|
+
},
|
|
701
|
+
async updateTimeEntry({
|
|
702
|
+
$, id, data, accountId,
|
|
703
|
+
}) {
|
|
704
|
+
return this._makeRequest({
|
|
705
|
+
$,
|
|
706
|
+
path: `/time_entries/${id}`,
|
|
707
|
+
method: "patch",
|
|
708
|
+
data,
|
|
709
|
+
accountId,
|
|
710
|
+
});
|
|
711
|
+
},
|
|
712
|
+
async deleteTimeEntry({
|
|
713
|
+
$, id, accountId,
|
|
714
|
+
}) {
|
|
715
|
+
return this._makeRequest({
|
|
716
|
+
$,
|
|
717
|
+
path: `/time_entries/${id}`,
|
|
718
|
+
method: "delete",
|
|
719
|
+
accountId,
|
|
720
|
+
});
|
|
721
|
+
},
|
|
722
|
+
async createProject({
|
|
723
|
+
$, data, accountId,
|
|
724
|
+
}) {
|
|
725
|
+
return this._makeRequest({
|
|
726
|
+
$,
|
|
727
|
+
path: "/projects",
|
|
728
|
+
method: "post",
|
|
729
|
+
data,
|
|
730
|
+
accountId,
|
|
731
|
+
});
|
|
732
|
+
},
|
|
733
|
+
async updateProject({
|
|
734
|
+
$, projectId, data, accountId,
|
|
735
|
+
}) {
|
|
736
|
+
return this._makeRequest({
|
|
737
|
+
$,
|
|
738
|
+
path: `/projects/${projectId}`,
|
|
739
|
+
method: "patch",
|
|
740
|
+
data,
|
|
741
|
+
accountId,
|
|
742
|
+
});
|
|
743
|
+
},
|
|
744
|
+
async deleteProject({
|
|
745
|
+
$, projectId, accountId,
|
|
746
|
+
}) {
|
|
747
|
+
return this._makeRequest({
|
|
748
|
+
$,
|
|
749
|
+
path: `/projects/${projectId}`,
|
|
750
|
+
method: "delete",
|
|
751
|
+
accountId,
|
|
752
|
+
});
|
|
753
|
+
},
|
|
754
|
+
async listTaskAssignments({
|
|
755
|
+
$, projectId, accountId, ...params
|
|
756
|
+
}) {
|
|
757
|
+
const path = projectId
|
|
758
|
+
? `/projects/${projectId}/task_assignments`
|
|
759
|
+
: "/task_assignments";
|
|
760
|
+
return this._makeRequest({
|
|
761
|
+
$,
|
|
762
|
+
path,
|
|
763
|
+
params,
|
|
764
|
+
accountId,
|
|
765
|
+
});
|
|
766
|
+
},
|
|
767
|
+
async getTaskAssignment({
|
|
768
|
+
$, projectId, taskAssignmentId, accountId,
|
|
769
|
+
}) {
|
|
770
|
+
return this._makeRequest({
|
|
771
|
+
$,
|
|
772
|
+
path: `/projects/${projectId}/task_assignments/${taskAssignmentId}`,
|
|
773
|
+
accountId,
|
|
774
|
+
});
|
|
775
|
+
},
|
|
776
|
+
async createTaskAssignment({
|
|
777
|
+
$, projectId, data, accountId,
|
|
778
|
+
}) {
|
|
779
|
+
return this._makeRequest({
|
|
780
|
+
$,
|
|
781
|
+
path: `/projects/${projectId}/task_assignments`,
|
|
782
|
+
method: "post",
|
|
783
|
+
data,
|
|
784
|
+
accountId,
|
|
785
|
+
});
|
|
786
|
+
},
|
|
787
|
+
async updateTaskAssignment({
|
|
788
|
+
$, projectId, taskAssignmentId, data, accountId,
|
|
789
|
+
}) {
|
|
790
|
+
return this._makeRequest({
|
|
791
|
+
$,
|
|
792
|
+
path: `/projects/${projectId}/task_assignments/${taskAssignmentId}`,
|
|
793
|
+
method: "patch",
|
|
794
|
+
data,
|
|
795
|
+
accountId,
|
|
796
|
+
});
|
|
797
|
+
},
|
|
798
|
+
async deleteTaskAssignment({
|
|
799
|
+
$, projectId, taskAssignmentId, accountId,
|
|
800
|
+
}) {
|
|
801
|
+
return this._makeRequest({
|
|
802
|
+
$,
|
|
803
|
+
path: `/projects/${projectId}/task_assignments/${taskAssignmentId}`,
|
|
804
|
+
method: "delete",
|
|
805
|
+
accountId,
|
|
806
|
+
});
|
|
807
|
+
},
|
|
808
|
+
async listUserAssignments({
|
|
809
|
+
$, projectId, accountId, ...params
|
|
810
|
+
}) {
|
|
811
|
+
const path = projectId
|
|
812
|
+
? `/projects/${projectId}/user_assignments`
|
|
813
|
+
: "/user_assignments";
|
|
814
|
+
return this._makeRequest({
|
|
815
|
+
$,
|
|
816
|
+
path,
|
|
817
|
+
params,
|
|
818
|
+
accountId,
|
|
819
|
+
});
|
|
820
|
+
},
|
|
821
|
+
async getUserAssignment({
|
|
822
|
+
$, projectId, userAssignmentId, accountId,
|
|
823
|
+
}) {
|
|
824
|
+
return this._makeRequest({
|
|
825
|
+
$,
|
|
826
|
+
path: `/projects/${projectId}/user_assignments/${userAssignmentId}`,
|
|
827
|
+
accountId,
|
|
828
|
+
});
|
|
829
|
+
},
|
|
830
|
+
async createUserAssignment({
|
|
831
|
+
$, projectId, data, accountId,
|
|
832
|
+
}) {
|
|
833
|
+
return this._makeRequest({
|
|
834
|
+
$,
|
|
835
|
+
path: `/projects/${projectId}/user_assignments`,
|
|
836
|
+
method: "post",
|
|
837
|
+
data,
|
|
838
|
+
accountId,
|
|
839
|
+
});
|
|
840
|
+
},
|
|
841
|
+
async updateUserAssignment({
|
|
842
|
+
$, projectId, userAssignmentId, data, accountId,
|
|
843
|
+
}) {
|
|
844
|
+
return this._makeRequest({
|
|
845
|
+
$,
|
|
846
|
+
path: `/projects/${projectId}/user_assignments/${userAssignmentId}`,
|
|
847
|
+
method: "patch",
|
|
848
|
+
data,
|
|
849
|
+
accountId,
|
|
850
|
+
});
|
|
851
|
+
},
|
|
852
|
+
async deleteUserAssignment({
|
|
853
|
+
$, projectId, userAssignmentId, accountId,
|
|
854
|
+
}) {
|
|
855
|
+
return this._makeRequest({
|
|
856
|
+
$,
|
|
857
|
+
path: `/projects/${projectId}/user_assignments/${userAssignmentId}`,
|
|
858
|
+
method: "delete",
|
|
859
|
+
accountId,
|
|
860
|
+
});
|
|
861
|
+
},
|
|
862
|
+
async getTimeReport({
|
|
863
|
+
$, reportBy, accountId, ...params
|
|
864
|
+
}) {
|
|
865
|
+
return this._makeRequest({
|
|
866
|
+
$,
|
|
867
|
+
path: `/reports/time/${reportBy}`,
|
|
868
|
+
params,
|
|
869
|
+
accountId,
|
|
870
|
+
});
|
|
871
|
+
},
|
|
872
|
+
async getUser({
|
|
873
|
+
$, userId, accountId,
|
|
874
|
+
}) {
|
|
875
|
+
return this._makeRequest({
|
|
876
|
+
$,
|
|
877
|
+
path: `/users/${userId}`,
|
|
878
|
+
accountId,
|
|
879
|
+
});
|
|
880
|
+
},
|
|
881
|
+
async getMe({
|
|
882
|
+
$, accountId,
|
|
883
|
+
}) {
|
|
884
|
+
return this._makeRequest({
|
|
885
|
+
$,
|
|
886
|
+
path: "/users/me",
|
|
887
|
+
accountId,
|
|
888
|
+
});
|
|
889
|
+
},
|
|
890
|
+
async createUser({
|
|
891
|
+
$, data, accountId,
|
|
892
|
+
}) {
|
|
893
|
+
return this._makeRequest({
|
|
894
|
+
$,
|
|
895
|
+
path: "/users",
|
|
896
|
+
method: "post",
|
|
897
|
+
data,
|
|
898
|
+
accountId,
|
|
899
|
+
});
|
|
900
|
+
},
|
|
901
|
+
async updateUser({
|
|
902
|
+
$, userId, data, accountId,
|
|
903
|
+
}) {
|
|
904
|
+
return this._makeRequest({
|
|
905
|
+
$,
|
|
906
|
+
path: `/users/${userId}`,
|
|
907
|
+
method: "patch",
|
|
908
|
+
data,
|
|
909
|
+
accountId,
|
|
910
|
+
});
|
|
911
|
+
},
|
|
912
|
+
async deleteUser({
|
|
913
|
+
$, userId, accountId,
|
|
914
|
+
}) {
|
|
915
|
+
return this._makeRequest({
|
|
916
|
+
$,
|
|
917
|
+
path: `/users/${userId}`,
|
|
918
|
+
method: "delete",
|
|
919
|
+
accountId,
|
|
920
|
+
});
|
|
921
|
+
},
|
|
922
|
+
async getInvoice({
|
|
923
|
+
$, invoiceId, accountId,
|
|
924
|
+
}) {
|
|
925
|
+
return this._makeRequest({
|
|
926
|
+
$,
|
|
927
|
+
path: `/invoices/${invoiceId}`,
|
|
928
|
+
accountId,
|
|
929
|
+
});
|
|
930
|
+
},
|
|
931
|
+
async createInvoice({
|
|
932
|
+
$, data, accountId,
|
|
933
|
+
}) {
|
|
934
|
+
return this._makeRequest({
|
|
935
|
+
$,
|
|
936
|
+
path: "/invoices",
|
|
937
|
+
method: "post",
|
|
938
|
+
data,
|
|
939
|
+
accountId,
|
|
940
|
+
});
|
|
941
|
+
},
|
|
942
|
+
async updateInvoice({
|
|
943
|
+
$, invoiceId, data, accountId,
|
|
944
|
+
}) {
|
|
945
|
+
return this._makeRequest({
|
|
946
|
+
$,
|
|
947
|
+
path: `/invoices/${invoiceId}`,
|
|
948
|
+
method: "patch",
|
|
949
|
+
data,
|
|
950
|
+
accountId,
|
|
951
|
+
});
|
|
952
|
+
},
|
|
953
|
+
async deleteInvoice({
|
|
954
|
+
$, invoiceId, accountId,
|
|
955
|
+
}) {
|
|
956
|
+
return this._makeRequest({
|
|
957
|
+
$,
|
|
958
|
+
path: `/invoices/${invoiceId}`,
|
|
959
|
+
method: "delete",
|
|
960
|
+
accountId,
|
|
961
|
+
});
|
|
962
|
+
},
|
|
390
963
|
},
|
|
391
964
|
};
|