@pipedream/harvest 0.0.4 → 0.0.6
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/LICENSE +41 -7
- package/README.md +16 -0
- package/actions/create-timesheet-entry/create-timesheet-entry.mjs +19 -3
- package/actions/get-projects/get-projects.mjs +64 -0
- package/actions/start-timer/start-timer.mjs +10 -2
- package/actions/stop-timer/stop-timer.mjs +10 -2
- package/harvest.app.mjs +104 -20
- package/package.json +1 -2
- package/sources/new-invoice-entry/new-invoice-entry.mjs +8 -1
- package/sources/new-timesheet-entry/new-timesheet-entry.mjs +8 -1
package/LICENSE
CHANGED
|
@@ -1,7 +1,41 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
1
|
+
Pipedream Source Available License Version 1.0
|
|
2
|
+
|
|
3
|
+
This Pipedream Source Available License Agreement Version 1.0 (this “Agreement”) sets forth the terms on which Pipedream, Inc., a Delaware corporation (“Pipedream”) makes available certain software (the “Software”). By installing, downloading, accessing, using or distributing the Software, you agree to the terms of this Agreement. If you do not agree to such terms, you must not use the Software. If you are receiving the Software on behalf of a legal entity, you represent and warrant that you have the actual authority to agree to the terms and conditions of this Agreement on behalf of such entity. “Licensee” means you, an individual, or the entity on whose behalf you are receiving the Software.
|
|
4
|
+
|
|
5
|
+
LICENSE GRANT AND CONDITIONS.
|
|
6
|
+
|
|
7
|
+
1.1 License. Subject to the terms and conditions of this Agreement, Pipedream hereby grants to Licensee a non-exclusive, royalty-free, worldwide, non-transferable, non-sublicenseable license during the term of this Agreement to use, prepare modifications and derivative works, distribute (including without limitation in source code or object code form) and reproduce copies of the Software (the “License”). Licensee is not granted the right to, and Licensee shall not, exercise the License for an Excluded Purpose. For purposes of this Agreement, “Excluded Purpose” means any commercial use of the software including, but not limited to, making available any software-as-a-service, platform-as-a-service, infrastructure-as-a-service or other online service that competes with the Software or any other Pipedream products or services.
|
|
8
|
+
|
|
9
|
+
1.2 Conditions. In consideration of the License, Licensee’s distribution of the Software is subject to the following conditions:
|
|
10
|
+
|
|
11
|
+
a. Licensee must cause any Software modified by Licensee to carry prominent notices stating that Licensee modified the Software.
|
|
12
|
+
|
|
13
|
+
b. On each Software copy, Licensee shall reproduce and not remove or alter all Pipedream or third party copyright or other proprietary notices contained in the Software, and Licensee must provide this with each copy: “This software is made available by Pipedream, Inc., under the terms of the Pipedream Source Available License, Version 1.0 located at https://github.com/PipedreamHQ/pipedream/blob/master/LICENSE. By installing, downloading, accessing, using or distributing the Software, you agree to the terms of such License Agreement.”
|
|
14
|
+
|
|
15
|
+
1.3 Modifications. Licensee may add its own copyright notices to modifications made by Licensee and may provide additional or different license terms and conditions for use, reproduction, or distribution of Licensee’s modifications. While redistributing the Software or modifications thereof, Licensee may choose to offer, for a fee or free of charge, support, warranty, indemnity, or other obligations. Licensee, and not Pipedream, will be responsible for any such obligations.
|
|
16
|
+
|
|
17
|
+
1.4 No Sublicensing. The License does not include the right to sublicense the Software; provided, however, that any recipient to which Licensee provides the Software may exercise the License so long as such recipient agrees to the terms and conditions of this Agreement.
|
|
18
|
+
|
|
19
|
+
TERM AND TERMINATION.
|
|
20
|
+
|
|
21
|
+
This Agreement will continue unless and until earlier terminated as set forth herein. If Licensee breaches any of its conditions or obligations under this Agreement, this Agreement will terminate automatically and the License will terminate automatically and permanently.
|
|
22
|
+
|
|
23
|
+
INTELLECTUAL PROPERTY.
|
|
24
|
+
|
|
25
|
+
As between the parties, Pipedream retains all right, title, and interest in the Software, and all intellectual property rights therein. Pipedream hereby reserves all rights not expressly granted to Licensee in this Agreement. Pipedream reserves all rights in its trademarks and service marks, and no licenses thereto are granted by this Agreement.
|
|
26
|
+
|
|
27
|
+
DISCLAIMER.
|
|
28
|
+
|
|
29
|
+
PIPEDREAM HEREBY DISCLAIMS ANY AND ALL WARRANTIES AND CONDITIONS, EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, AND SPECIFICALLY DISCLAIMS ANY WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, WITH RESPECT TO THE SOFTWARE.
|
|
30
|
+
|
|
31
|
+
LIMITATION OF LIABILITY.
|
|
32
|
+
|
|
33
|
+
PIPEDREAM WILL NOT BE LIABLE FOR ANY DAMAGES OF ANY KIND, INCLUDING BUT NOT LIMITED TO, LOST PROFITS OR ANY CONSEQUENTIAL, SPECIAL, INCIDENTAL, INDIRECT, OR DIRECT DAMAGES, HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, ARISING OUT OF THIS AGREEMENT. THE FOREGOING SHALL APPLY TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW.
|
|
34
|
+
|
|
35
|
+
GENERAL.
|
|
36
|
+
|
|
37
|
+
6.1 Governing Law. This Agreement will be governed by and interpreted in accordance with the laws of the state of California, without reference to its conflict of laws principles. If Licensee is located outside of the United States, any dispute, controversy or claim arising out of or relating to this Agreement will be referred to and finally determined by arbitration in accordance with the JAMS International Arbitration Rules. The tribunal will consist of one arbitrator. Judgment upon the award rendered by the arbitrator may be entered in any court having jurisdiction thereof. All disputes including arbitrations shall take place in Santa Clara County, California. The language to be used in any such proceedings shall be English.
|
|
38
|
+
|
|
39
|
+
6.2. Assignment. Licensee is not authorized to assign its rights under this Agreement to any third party. Pipedream may freely assign its rights under this Agreement to any third party.
|
|
40
|
+
|
|
41
|
+
6.3. Other. This Agreement is the entire agreement between the parties regarding the subject matter hereof. No amendment or modification of this Agreement will be valid or binding upon the parties unless made in writing and signed by the duly authorized representatives of both parties. In the event that any provision, including without limitation any condition, of this Agreement is held to be unenforceable, this Agreement and all licenses and rights granted hereunder will immediately terminate. Waiver by Pipedream of a breach of any provision of this Agreement or the failure by Pipedream to exercise any right hereunder will not be construed as a waiver of any subsequent breach of that right or as a waiver of any other right.
|
package/README.md
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# Overview
|
|
2
|
+
|
|
3
|
+
The Harvest API allows developers to programmatically access data and objects
|
|
4
|
+
in Harvest, a web-based time tracking application. With the API, developers can
|
|
5
|
+
create applications that submit and retrieve time tracking data, as well as
|
|
6
|
+
automate various aspects of the Harvest user experience.
|
|
7
|
+
|
|
8
|
+
Some examples of what you can build using the Harvest API include:
|
|
9
|
+
|
|
10
|
+
- A time tracking application that automatically submits time tracking data to
|
|
11
|
+
Harvest on behalf of the user
|
|
12
|
+
- A reporting application that retrieves time tracking data from Harvest and
|
|
13
|
+
presents it in various charts and graphs
|
|
14
|
+
- An integration with a third-party project management application that pulls
|
|
15
|
+
in time tracking data from Harvest to provide a more complete picture of
|
|
16
|
+
project progress
|
|
@@ -10,20 +10,32 @@ export default {
|
|
|
10
10
|
description: `Creates a new time entry object.
|
|
11
11
|
[Create a time entry via duration documentation](https://help.getharvest.com/api-v2/timesheets-api/timesheets/time-entries/#create-a-time-entry-via-duration),
|
|
12
12
|
[Create a time entry via start and end time documentation](https://help.getharvest.com/api-v2/timesheets-api/timesheets/time-entries/#create-a-time-entry-via-start-and-end-time)`,
|
|
13
|
-
version: "0.0.
|
|
13
|
+
version: "0.0.2",
|
|
14
14
|
type: "action",
|
|
15
15
|
props: {
|
|
16
16
|
harvest,
|
|
17
|
+
accountId: {
|
|
18
|
+
propDefinition: [
|
|
19
|
+
harvest,
|
|
20
|
+
"accountId",
|
|
21
|
+
],
|
|
22
|
+
},
|
|
17
23
|
projectId: {
|
|
18
24
|
propDefinition: [
|
|
19
25
|
harvest,
|
|
20
26
|
"projectId",
|
|
27
|
+
(c) => ({
|
|
28
|
+
accountId: c.accountId,
|
|
29
|
+
}),
|
|
21
30
|
],
|
|
22
31
|
},
|
|
23
32
|
taskId: {
|
|
24
33
|
propDefinition: [
|
|
25
34
|
harvest,
|
|
26
35
|
"taskId",
|
|
36
|
+
(c) => ({
|
|
37
|
+
accountId: c.accountId,
|
|
38
|
+
}),
|
|
27
39
|
],
|
|
28
40
|
},
|
|
29
41
|
spentDate: {
|
|
@@ -35,6 +47,9 @@ export default {
|
|
|
35
47
|
propDefinition: [
|
|
36
48
|
harvest,
|
|
37
49
|
"userId",
|
|
50
|
+
(c) => ({
|
|
51
|
+
accountId: c.accountId,
|
|
52
|
+
}),
|
|
38
53
|
],
|
|
39
54
|
},
|
|
40
55
|
specifyStartEndTime: {
|
|
@@ -80,12 +95,13 @@ export default {
|
|
|
80
95
|
task_id: this.taskId,
|
|
81
96
|
user_id: this.userId,
|
|
82
97
|
spent_date: this.spentDate,
|
|
83
|
-
started_time: this.startedTime
|
|
84
|
-
ended_time: this.endedTime
|
|
98
|
+
started_time: this.startedTime?.replace(/\s/g, ""),
|
|
99
|
+
ended_time: this.endedTime?.replace(/\s/g, ""),
|
|
85
100
|
});
|
|
86
101
|
const response = await this.harvest.createTimeEntry({
|
|
87
102
|
$,
|
|
88
103
|
params,
|
|
104
|
+
accountId: this.accountId,
|
|
89
105
|
});
|
|
90
106
|
response && $.export("$summary", "Successfully created time entry");
|
|
91
107
|
return response;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import harvest from "../../harvest.app.mjs";
|
|
2
|
+
import { ConfigurationError } from "@pipedream/platform";
|
|
3
|
+
|
|
4
|
+
export default {
|
|
5
|
+
key: "harvest-get-projects",
|
|
6
|
+
name: "Get Projects",
|
|
7
|
+
description: "Retrieve data for a project or projects. [See docs here](https://help.getharvest.com/api-v2/projects-api/projects/projects/#list-all-projects)",
|
|
8
|
+
version: "0.0.1",
|
|
9
|
+
type: "action",
|
|
10
|
+
props: {
|
|
11
|
+
harvest,
|
|
12
|
+
accountId: {
|
|
13
|
+
propDefinition: [
|
|
14
|
+
harvest,
|
|
15
|
+
"accountId",
|
|
16
|
+
],
|
|
17
|
+
},
|
|
18
|
+
projectIds: {
|
|
19
|
+
propDefinition: [
|
|
20
|
+
harvest,
|
|
21
|
+
"projectId",
|
|
22
|
+
(c) => ({
|
|
23
|
+
accountId: c.accountId,
|
|
24
|
+
}),
|
|
25
|
+
],
|
|
26
|
+
type: "string[]",
|
|
27
|
+
description: "Array of project IDs",
|
|
28
|
+
optional: true,
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
async run({ $ }) {
|
|
32
|
+
const {
|
|
33
|
+
accountId, projectIds,
|
|
34
|
+
} = this;
|
|
35
|
+
|
|
36
|
+
if (projectIds && !Array.isArray(projectIds)) {
|
|
37
|
+
throw new ConfigurationError("Project IDs must be an array");
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const results = [];
|
|
41
|
+
|
|
42
|
+
if (projectIds) {
|
|
43
|
+
for (const projectId of projectIds) {
|
|
44
|
+
const project = await this.harvest.getProject({
|
|
45
|
+
$,
|
|
46
|
+
projectId,
|
|
47
|
+
accountId,
|
|
48
|
+
});
|
|
49
|
+
results.push(project);
|
|
50
|
+
}
|
|
51
|
+
} else {
|
|
52
|
+
const projects = await this.harvest.listProjectsPaginated({
|
|
53
|
+
page: 1,
|
|
54
|
+
accountId,
|
|
55
|
+
});
|
|
56
|
+
for await (const project of projects) {
|
|
57
|
+
results.push(project);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
results && $.export("$summary", `Successfully retrieved ${results?.length} project(s).`);
|
|
62
|
+
return results;
|
|
63
|
+
},
|
|
64
|
+
};
|
|
@@ -4,16 +4,23 @@ export default {
|
|
|
4
4
|
key: "harvest-start-timer",
|
|
5
5
|
name: "Start Time Entry",
|
|
6
6
|
description: "Restart a stopped timer entry. [See docs here](https://help.getharvest.com/api-v2/timesheets-api/timesheets/time-entries/#restart-a-stopped-time-entry)",
|
|
7
|
-
version: "0.0.
|
|
7
|
+
version: "0.0.2",
|
|
8
8
|
type: "action",
|
|
9
9
|
props: {
|
|
10
10
|
harvest,
|
|
11
|
+
accountId: {
|
|
12
|
+
propDefinition: [
|
|
13
|
+
harvest,
|
|
14
|
+
"accountId",
|
|
15
|
+
],
|
|
16
|
+
},
|
|
11
17
|
timeEntryId: {
|
|
12
18
|
propDefinition: [
|
|
13
19
|
harvest,
|
|
14
20
|
"timeEntryId",
|
|
15
|
-
() => ({
|
|
21
|
+
(c) => ({
|
|
16
22
|
isRunning: false,
|
|
23
|
+
accountId: c.accountId,
|
|
17
24
|
}),
|
|
18
25
|
],
|
|
19
26
|
},
|
|
@@ -22,6 +29,7 @@ export default {
|
|
|
22
29
|
const response = await this.harvest.restartTimeEntry({
|
|
23
30
|
$,
|
|
24
31
|
id: this.timeEntryId,
|
|
32
|
+
accountId: this.accountId,
|
|
25
33
|
});
|
|
26
34
|
response && $.export("$summary", "Successfully started the time entry");
|
|
27
35
|
return response;
|
|
@@ -4,16 +4,23 @@ export default {
|
|
|
4
4
|
key: "harvest-stop-timer",
|
|
5
5
|
name: "Stop Time Entry",
|
|
6
6
|
description: "Stop a timer entry. [See docs here](https://help.getharvest.com/api-v2/timesheets-api/timesheets/time-entries/#stop-a-running-time-entry)",
|
|
7
|
-
version: "0.0.
|
|
7
|
+
version: "0.0.3",
|
|
8
8
|
type: "action",
|
|
9
9
|
props: {
|
|
10
10
|
harvest,
|
|
11
|
+
accountId: {
|
|
12
|
+
propDefinition: [
|
|
13
|
+
harvest,
|
|
14
|
+
"accountId",
|
|
15
|
+
],
|
|
16
|
+
},
|
|
11
17
|
timeEntryId: {
|
|
12
18
|
propDefinition: [
|
|
13
19
|
harvest,
|
|
14
20
|
"timeEntryId",
|
|
15
|
-
() => ({
|
|
21
|
+
(c) => ({
|
|
16
22
|
isRunning: true,
|
|
23
|
+
accountId: c.accountId,
|
|
17
24
|
}),
|
|
18
25
|
],
|
|
19
26
|
},
|
|
@@ -22,6 +29,7 @@ export default {
|
|
|
22
29
|
const response = await this.harvest.stopTimeEntry({
|
|
23
30
|
$,
|
|
24
31
|
id: this.timeEntryId,
|
|
32
|
+
accountId: this.accountId,
|
|
25
33
|
});
|
|
26
34
|
response && $.export("$summary", "Successfully ended the time entry");
|
|
27
35
|
return response;
|
package/harvest.app.mjs
CHANGED
|
@@ -13,10 +13,13 @@ export default {
|
|
|
13
13
|
label: "Project ID",
|
|
14
14
|
description: "The ID of the project to associate with the time entry",
|
|
15
15
|
useQuery: true,
|
|
16
|
-
async options({
|
|
16
|
+
async options({
|
|
17
|
+
page, accountId,
|
|
18
|
+
}) {
|
|
17
19
|
const response = await this.listProjects({
|
|
18
20
|
perPage: constants.PAGE_SIZE,
|
|
19
21
|
page: page + 1,
|
|
22
|
+
accountId,
|
|
20
23
|
});
|
|
21
24
|
return response.projects.map((project) => ({
|
|
22
25
|
label: project.name,
|
|
@@ -29,10 +32,13 @@ export default {
|
|
|
29
32
|
label: "Task ID",
|
|
30
33
|
description: "The ID of the task to associate with the time entry",
|
|
31
34
|
useQuery: true,
|
|
32
|
-
async options({
|
|
35
|
+
async options({
|
|
36
|
+
page, accountId,
|
|
37
|
+
}) {
|
|
33
38
|
const response = await this.listTasks({
|
|
34
39
|
perPage: constants.PAGE_SIZE,
|
|
35
40
|
page: page + 1,
|
|
41
|
+
accountId,
|
|
36
42
|
});
|
|
37
43
|
return response.tasks.map((task) => ({
|
|
38
44
|
label: task.name,
|
|
@@ -46,10 +52,13 @@ export default {
|
|
|
46
52
|
description: "The ID of the user to associate with the time entry",
|
|
47
53
|
useQuery: true,
|
|
48
54
|
optional: true,
|
|
49
|
-
async options({
|
|
55
|
+
async options({
|
|
56
|
+
page, accountId,
|
|
57
|
+
}) {
|
|
50
58
|
const response = await this.listUsers({
|
|
51
59
|
perPage: constants.PAGE_SIZE,
|
|
52
60
|
page: page + 1,
|
|
61
|
+
accountId,
|
|
53
62
|
});
|
|
54
63
|
return response.users.map((user) => ({
|
|
55
64
|
label: `${user.first_name} ${user.last_name}`,
|
|
@@ -63,10 +72,13 @@ export default {
|
|
|
63
72
|
description: "The ID of the client to associate with time entries",
|
|
64
73
|
useQuery: true,
|
|
65
74
|
optional: true,
|
|
66
|
-
async options({
|
|
75
|
+
async options({
|
|
76
|
+
page, accountId,
|
|
77
|
+
}) {
|
|
67
78
|
const response = await this.listClients({
|
|
68
79
|
perPage: constants.PAGE_SIZE,
|
|
69
80
|
page: page + 1,
|
|
81
|
+
accountId,
|
|
70
82
|
});
|
|
71
83
|
return response.clients.map((client) => ({
|
|
72
84
|
label: client.name,
|
|
@@ -80,12 +92,13 @@ export default {
|
|
|
80
92
|
description: "The ID of the time entry.",
|
|
81
93
|
useQuery: true,
|
|
82
94
|
async options({
|
|
83
|
-
page, isRunning,
|
|
95
|
+
page, isRunning, accountId,
|
|
84
96
|
}) {
|
|
85
97
|
const response = await this.listTimeEntries({
|
|
86
98
|
perPage: constants.PAGE_SIZE,
|
|
87
99
|
page: page + 1,
|
|
88
100
|
is_running: isRunning,
|
|
101
|
+
accountId,
|
|
89
102
|
});
|
|
90
103
|
return response.time_entries.map((entry) => ({
|
|
91
104
|
label: `Project: ${entry.project.name}, Task: ${entry.task.name}, Spend date: ${entry.spent_date} ${entry.started_time || ""} ${entry.ended_time
|
|
@@ -95,6 +108,20 @@ export default {
|
|
|
95
108
|
}));
|
|
96
109
|
},
|
|
97
110
|
},
|
|
111
|
+
accountId: {
|
|
112
|
+
type: "string",
|
|
113
|
+
label: "Account ID",
|
|
114
|
+
description: "The ID of your account",
|
|
115
|
+
async options() {
|
|
116
|
+
const { accounts } = await this.listAccounts({});
|
|
117
|
+
return accounts.map(({
|
|
118
|
+
id, name,
|
|
119
|
+
}) => ({
|
|
120
|
+
label: name,
|
|
121
|
+
value: id,
|
|
122
|
+
}));
|
|
123
|
+
},
|
|
124
|
+
},
|
|
98
125
|
},
|
|
99
126
|
methods: {
|
|
100
127
|
setLastDateChecked(db, value) {
|
|
@@ -103,11 +130,16 @@ export default {
|
|
|
103
130
|
getLastDateChecked(db) {
|
|
104
131
|
return db && db.get(constants.DB_LAST_DATE_CHECK);
|
|
105
132
|
},
|
|
106
|
-
|
|
133
|
+
_getAuthorizationHeader() {
|
|
107
134
|
return {
|
|
108
|
-
"Content-Type": "application/json",
|
|
109
135
|
"Authorization": `Bearer ${this.$auth.oauth_access_token}`,
|
|
110
|
-
|
|
136
|
+
};
|
|
137
|
+
},
|
|
138
|
+
_getHeaders(accountId) {
|
|
139
|
+
return {
|
|
140
|
+
"Content-Type": "application/json",
|
|
141
|
+
"Harvest-Account-Id": accountId,
|
|
142
|
+
...this._getAuthorizationHeader(),
|
|
111
143
|
};
|
|
112
144
|
},
|
|
113
145
|
_getUrl(path) {
|
|
@@ -125,16 +157,23 @@ export default {
|
|
|
125
157
|
path,
|
|
126
158
|
params,
|
|
127
159
|
data,
|
|
160
|
+
accountId,
|
|
128
161
|
} = args;
|
|
129
162
|
const config = {
|
|
130
163
|
method,
|
|
131
164
|
url: this._getUrl(path),
|
|
132
|
-
headers: this._getHeaders(),
|
|
165
|
+
headers: this._getHeaders(accountId),
|
|
133
166
|
params,
|
|
134
167
|
data,
|
|
135
168
|
};
|
|
136
169
|
return axios($ ?? this, config);
|
|
137
170
|
},
|
|
171
|
+
async listAccounts({ $ = this }) {
|
|
172
|
+
return axios($, {
|
|
173
|
+
url: "https://id.getharvest.com/api/v2/accounts",
|
|
174
|
+
headers: this._getAuthorizationHeader(),
|
|
175
|
+
});
|
|
176
|
+
},
|
|
138
177
|
_isRetriableStatusCode(statusCode) {
|
|
139
178
|
constants.retriableStatusCodes.includes(statusCode);
|
|
140
179
|
},
|
|
@@ -161,7 +200,7 @@ export default {
|
|
|
161
200
|
}, retryOpts);
|
|
162
201
|
},
|
|
163
202
|
async *listTimeEntriesPaginated({
|
|
164
|
-
page, updatedSince,
|
|
203
|
+
page, updatedSince, accountId,
|
|
165
204
|
}) {
|
|
166
205
|
do {
|
|
167
206
|
const response = await this._withRetries(
|
|
@@ -169,6 +208,7 @@ export default {
|
|
|
169
208
|
per_page: constants.PAGE_SIZE,
|
|
170
209
|
page,
|
|
171
210
|
updated_since: updatedSince,
|
|
211
|
+
accountId,
|
|
172
212
|
}),
|
|
173
213
|
);
|
|
174
214
|
|
|
@@ -185,7 +225,7 @@ export default {
|
|
|
185
225
|
} while (true);
|
|
186
226
|
},
|
|
187
227
|
async *listInvoicesPaginated({
|
|
188
|
-
page, updatedSince,
|
|
228
|
+
page, updatedSince, accountId,
|
|
189
229
|
}) {
|
|
190
230
|
do {
|
|
191
231
|
const response = await this._withRetries(
|
|
@@ -193,6 +233,7 @@ export default {
|
|
|
193
233
|
per_page: constants.PAGE_SIZE,
|
|
194
234
|
page,
|
|
195
235
|
updated_since: updatedSince,
|
|
236
|
+
accountId,
|
|
196
237
|
}),
|
|
197
238
|
);
|
|
198
239
|
|
|
@@ -208,8 +249,42 @@ export default {
|
|
|
208
249
|
page += 1;
|
|
209
250
|
} while (true);
|
|
210
251
|
},
|
|
252
|
+
async *listProjectsPaginated({
|
|
253
|
+
page, $, accountId,
|
|
254
|
+
}) {
|
|
255
|
+
do {
|
|
256
|
+
const response = await this._withRetries(
|
|
257
|
+
() => this.listProjects({
|
|
258
|
+
accountId,
|
|
259
|
+
per_page: constants.PAGE_SIZE,
|
|
260
|
+
page,
|
|
261
|
+
$,
|
|
262
|
+
}),
|
|
263
|
+
);
|
|
264
|
+
|
|
265
|
+
if (response.projects.length === 0) {
|
|
266
|
+
return;
|
|
267
|
+
}
|
|
268
|
+
for (const project of response.projects) {
|
|
269
|
+
yield project;
|
|
270
|
+
}
|
|
271
|
+
if (!response.next_page) {
|
|
272
|
+
return;
|
|
273
|
+
}
|
|
274
|
+
page += 1;
|
|
275
|
+
} while (true);
|
|
276
|
+
},
|
|
277
|
+
async getProject({
|
|
278
|
+
$, projectId, accountId,
|
|
279
|
+
}) {
|
|
280
|
+
return this._makeRequest({
|
|
281
|
+
$,
|
|
282
|
+
path: `/projects/${projectId}`,
|
|
283
|
+
accountId,
|
|
284
|
+
});
|
|
285
|
+
},
|
|
211
286
|
async listProjects({
|
|
212
|
-
$, perPage, page,
|
|
287
|
+
$, perPage, page, accountId,
|
|
213
288
|
}) {
|
|
214
289
|
return this._makeRequest({
|
|
215
290
|
$,
|
|
@@ -218,10 +293,11 @@ export default {
|
|
|
218
293
|
per_page: perPage,
|
|
219
294
|
page,
|
|
220
295
|
},
|
|
296
|
+
accountId,
|
|
221
297
|
});
|
|
222
298
|
},
|
|
223
299
|
async listTasks({
|
|
224
|
-
$, perPage, page,
|
|
300
|
+
$, perPage, page, accountId,
|
|
225
301
|
}) {
|
|
226
302
|
return this._makeRequest({
|
|
227
303
|
$,
|
|
@@ -230,10 +306,11 @@ export default {
|
|
|
230
306
|
per_page: perPage,
|
|
231
307
|
page,
|
|
232
308
|
},
|
|
309
|
+
accountId,
|
|
233
310
|
});
|
|
234
311
|
},
|
|
235
312
|
async listUsers({
|
|
236
|
-
$, perPage, page,
|
|
313
|
+
$, perPage, page, accountId,
|
|
237
314
|
}) {
|
|
238
315
|
return this._makeRequest({
|
|
239
316
|
$,
|
|
@@ -242,10 +319,11 @@ export default {
|
|
|
242
319
|
per_page: perPage,
|
|
243
320
|
page,
|
|
244
321
|
},
|
|
322
|
+
accountId,
|
|
245
323
|
});
|
|
246
324
|
},
|
|
247
325
|
async listClients({
|
|
248
|
-
$, perPage, page,
|
|
326
|
+
$, perPage, page, accountId,
|
|
249
327
|
}) {
|
|
250
328
|
return this._makeRequest({
|
|
251
329
|
$,
|
|
@@ -254,52 +332,58 @@ export default {
|
|
|
254
332
|
per_page: perPage,
|
|
255
333
|
page,
|
|
256
334
|
},
|
|
335
|
+
accountId,
|
|
257
336
|
});
|
|
258
337
|
},
|
|
259
338
|
async createTimeEntry({
|
|
260
|
-
$, params,
|
|
339
|
+
$, params, accountId,
|
|
261
340
|
}) {
|
|
262
341
|
return this._makeRequest({
|
|
263
342
|
$,
|
|
264
343
|
path: "/time_entries",
|
|
265
344
|
params,
|
|
266
345
|
method: "post",
|
|
346
|
+
accountId,
|
|
267
347
|
});
|
|
268
348
|
},
|
|
269
349
|
async listTimeEntries({
|
|
270
|
-
$, ...params
|
|
350
|
+
$, accountId, ...params
|
|
271
351
|
}) {
|
|
272
352
|
|
|
273
353
|
return this._makeRequest({
|
|
274
354
|
$,
|
|
275
355
|
path: "/time_entries",
|
|
356
|
+
accountId,
|
|
276
357
|
params,
|
|
277
358
|
});
|
|
278
359
|
},
|
|
279
360
|
async restartTimeEntry({
|
|
280
|
-
$, id,
|
|
361
|
+
$, id, accountId,
|
|
281
362
|
}) {
|
|
282
363
|
return this._makeRequest({
|
|
283
364
|
$,
|
|
284
365
|
path: `/time_entries/${id}/restart`,
|
|
285
366
|
method: "patch",
|
|
367
|
+
accountId,
|
|
286
368
|
});
|
|
287
369
|
},
|
|
288
370
|
async stopTimeEntry({
|
|
289
|
-
$, id,
|
|
371
|
+
$, id, accountId,
|
|
290
372
|
}) {
|
|
291
373
|
return this._makeRequest({
|
|
292
374
|
$,
|
|
293
375
|
path: `/time_entries/${id}/stop`,
|
|
294
376
|
method: "patch",
|
|
377
|
+
accountId,
|
|
295
378
|
});
|
|
296
379
|
},
|
|
297
380
|
async listInvoices({
|
|
298
|
-
$, ...params
|
|
381
|
+
$, accountId, ...params
|
|
299
382
|
}) {
|
|
300
383
|
return this._makeRequest({
|
|
301
384
|
$,
|
|
302
385
|
path: "/invoices",
|
|
386
|
+
accountId,
|
|
303
387
|
params,
|
|
304
388
|
});
|
|
305
389
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pipedream/harvest",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.6",
|
|
4
4
|
"description": "Pipedream Harvest Components",
|
|
5
5
|
"main": "harvest.app.mjs",
|
|
6
6
|
"keywords": [
|
|
@@ -9,7 +9,6 @@
|
|
|
9
9
|
],
|
|
10
10
|
"homepage": "https://pipedream.com/apps/harvest",
|
|
11
11
|
"author": "Pipedream <support@pipedream.com> (https://pipedream.com/)",
|
|
12
|
-
"license": "MIT",
|
|
13
12
|
"publishConfig": {
|
|
14
13
|
"access": "public"
|
|
15
14
|
},
|
|
@@ -5,7 +5,7 @@ export default {
|
|
|
5
5
|
key: "harvest-new-invoice-entry",
|
|
6
6
|
name: "New Invoice Entry",
|
|
7
7
|
description: "Emit new notifications when a new invoice is created",
|
|
8
|
-
version: "0.0.
|
|
8
|
+
version: "0.0.4",
|
|
9
9
|
type: "source",
|
|
10
10
|
props: {
|
|
11
11
|
harvest,
|
|
@@ -18,6 +18,12 @@ export default {
|
|
|
18
18
|
},
|
|
19
19
|
},
|
|
20
20
|
db: "$.service.db",
|
|
21
|
+
accountId: {
|
|
22
|
+
propDefinition: [
|
|
23
|
+
harvest,
|
|
24
|
+
"accountId",
|
|
25
|
+
],
|
|
26
|
+
},
|
|
21
27
|
},
|
|
22
28
|
dedupe: "unique",
|
|
23
29
|
async run() {
|
|
@@ -30,6 +36,7 @@ export default {
|
|
|
30
36
|
const invoices = await this.harvest.listInvoicesPaginated({
|
|
31
37
|
page: 1,
|
|
32
38
|
updatedSince: lastDateChecked,
|
|
39
|
+
accountId: this.accountId,
|
|
33
40
|
});
|
|
34
41
|
for await (const invoice of invoices) {
|
|
35
42
|
data.push(invoice);
|
|
@@ -5,7 +5,7 @@ export default {
|
|
|
5
5
|
key: "harvest-new-timesheet-entry",
|
|
6
6
|
name: "New Timesheet Entry",
|
|
7
7
|
description: "Emit new notifications when a new timesheet entry is created",
|
|
8
|
-
version: "0.0.
|
|
8
|
+
version: "0.0.4",
|
|
9
9
|
type: "source",
|
|
10
10
|
props: {
|
|
11
11
|
harvest,
|
|
@@ -18,6 +18,12 @@ export default {
|
|
|
18
18
|
},
|
|
19
19
|
},
|
|
20
20
|
db: "$.service.db",
|
|
21
|
+
accountId: {
|
|
22
|
+
propDefinition: [
|
|
23
|
+
harvest,
|
|
24
|
+
"accountId",
|
|
25
|
+
],
|
|
26
|
+
},
|
|
21
27
|
},
|
|
22
28
|
dedupe: "unique",
|
|
23
29
|
async run() {
|
|
@@ -30,6 +36,7 @@ export default {
|
|
|
30
36
|
const entries = await this.harvest.listTimeEntriesPaginated({
|
|
31
37
|
page: 1,
|
|
32
38
|
updatedSince: lastDateChecked,
|
|
39
|
+
accountId: this.accountId,
|
|
33
40
|
});
|
|
34
41
|
for await (const entry of entries) {
|
|
35
42
|
data.push(entry);
|