@pipedream/jobnimbus 0.0.2 → 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/LICENSE CHANGED
@@ -1,7 +1,41 @@
1
- Copyright 2020 Pipedream, Inc.
2
-
3
- Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4
-
5
- The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6
-
7
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
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,12 @@
1
+ # Overview
2
+
3
+ Jobnimbus API can be used to create custom applications for managing job
4
+ information.
5
+
6
+ Some examples of what you can build using the Jobnimbus API include:
7
+
8
+ - A custom job board
9
+ - A job search engine
10
+ - A job management system
11
+ - A CRM for job-related information
12
+ - A job-related data analytics platform
@@ -0,0 +1,209 @@
1
+ import app from "../../jobnimbus.app.mjs";
2
+ import utils from "../../common/utils.mjs";
3
+
4
+ export default {
5
+ props: {
6
+ app,
7
+ firstName: {
8
+ type: "string",
9
+ label: "First Name",
10
+ description: "The first name of the person this contact record is associated with.",
11
+ optional: true,
12
+ },
13
+ lastName: {
14
+ type: "string",
15
+ label: "Last Name",
16
+ description: "The last name of the person this contact record is associated with.",
17
+ optional: true,
18
+ },
19
+ displayName: {
20
+ type: "string",
21
+ label: "Display Name",
22
+ description: "The company name that this contact record is associated with.",
23
+ optional: true,
24
+ },
25
+ company: {
26
+ type: "string",
27
+ label: "Company Name",
28
+ description: "Display name used mainly for QB syncing.",
29
+ optional: true,
30
+ },
31
+ number: {
32
+ type: "string",
33
+ label: "Number",
34
+ description: "The customer defined template generated number assigned to this record, based off of the record id.",
35
+ optional: true,
36
+ },
37
+ isActive: {
38
+ type: "boolean",
39
+ label: "Is Active",
40
+ description: "Whether this record is active(true) or deleted(false).",
41
+ optional: true,
42
+ },
43
+ isArchived: {
44
+ type: "boolean",
45
+ label: "Is Archived",
46
+ description: "Whether this record has been archived (true) or not (false).",
47
+ optional: true,
48
+ },
49
+ tags: {
50
+ type: "string[]",
51
+ label: "Tags",
52
+ description: "List of string tags",
53
+ optional: true,
54
+ },
55
+ description: {
56
+ type: "string",
57
+ label: "Description",
58
+ description: "The description of this record.",
59
+ optional: true,
60
+ },
61
+ address1: {
62
+ type: "string",
63
+ label: "Address Line 1",
64
+ description: "The line 1 portion of the physical address.",
65
+ optional: true,
66
+ },
67
+ address2: {
68
+ type: "string",
69
+ label: "Address Line 2",
70
+ description: "The line 2 portion of the physical address.",
71
+ optional: true,
72
+ },
73
+ city: {
74
+ type: "string",
75
+ label: "City",
76
+ description: "The city portion of the physical address.",
77
+ optional: true,
78
+ },
79
+ state: {
80
+ type: "string",
81
+ label: "State",
82
+ description: "The state text portion of the physical address.",
83
+ optional: true,
84
+ },
85
+ zip: {
86
+ type: "string",
87
+ label: "Zip",
88
+ description: "The postal code portion of the physical address.",
89
+ optional: true,
90
+ },
91
+ country: {
92
+ type: "string",
93
+ label: "Country",
94
+ description: "The country portion of the physical address.",
95
+ optional: true,
96
+ },
97
+ geoLat: {
98
+ type: "string",
99
+ label: "Geo Latitude",
100
+ description: "The latitude of geo coordinates of the address associated with this record.",
101
+ optional: true,
102
+ },
103
+ geoLong: {
104
+ type: "string",
105
+ label: "Geo Longitude",
106
+ description: "The longitude of geo coordinates of the address associated with this record.",
107
+ optional: true,
108
+ },
109
+ estimatedTime: {
110
+ type: "integer",
111
+ label: "Estimated Time",
112
+ description: "The number of minutes this record is estimated to take to complete.",
113
+ optional: true,
114
+ },
115
+ isLead: {
116
+ type: "boolean",
117
+ label: "Is Lead",
118
+ description: "Whether this record is a lead or not.",
119
+ optional: true,
120
+ },
121
+ isClosed: {
122
+ type: "boolean",
123
+ label: "Is Closed",
124
+ description: "Whether this record is closed or not.",
125
+ optional: true,
126
+ },
127
+ isSubcontractor: {
128
+ type: "boolean",
129
+ label: "Is Subcontractor",
130
+ description: "Whether this contact is a subcontractor or not for User.",
131
+ optional: true,
132
+ },
133
+ email: {
134
+ propDefinition: [
135
+ app,
136
+ "email",
137
+ ],
138
+ optional: true,
139
+ },
140
+ homePhone: {
141
+ type: "string",
142
+ label: "Home Phone",
143
+ description: "The home phone number associated with this contact.",
144
+ optional: true,
145
+ },
146
+ mobilePhone: {
147
+ type: "string",
148
+ label: "Mobile Phone",
149
+ description: "The mobile phone number associated with this contact.",
150
+ optional: true,
151
+ },
152
+ workPhone: {
153
+ type: "string",
154
+ label: "Work Phone",
155
+ description: "The work phone number associated with this contact.",
156
+ optional: true,
157
+ },
158
+ faxNumber: {
159
+ type: "string",
160
+ label: "Fax Number",
161
+ description: "The fax number associated with this contact.",
162
+ optional: true,
163
+ },
164
+ website: {
165
+ type: "string",
166
+ label: "Website",
167
+ description: "Website",
168
+ optional: true,
169
+ },
170
+ additionalFields: {
171
+ type: "object",
172
+ label: "Additional Fields",
173
+ description: "Additional fields that can be added according to API docs and custom fields.",
174
+ optional: true,
175
+ },
176
+ },
177
+ methods: {
178
+ prepareData() {
179
+ const pairs = {
180
+ firstName: "first_name",
181
+ lastName: "last_name",
182
+ displayName: "display_name",
183
+ isActive: "is_active",
184
+ isArchived: "is_archived",
185
+ address1: "address_line1",
186
+ address2: "address_line2",
187
+ state: "state_text",
188
+ country: "country_name",
189
+ estimatedTime: "estimated_time",
190
+ isLead: "is_lead",
191
+ isClosed: "is_closed",
192
+ isSubcontractor: "is_sub_contractor",
193
+ homePhone: "home_phone",
194
+ mobilePhone: "mobile_phone",
195
+ workPhone: "work_phone",
196
+ faxNumber: "fax_number",
197
+ };
198
+ const data = {
199
+ ...utils.extractProps(this, pairs),
200
+ geo: {
201
+ lat: parseFloat(this.geoLat),
202
+ lon: parseFloat(this.geoLong),
203
+ },
204
+ ...this.additionalFields,
205
+ };
206
+ return data;
207
+ },
208
+ },
209
+ };
@@ -0,0 +1,69 @@
1
+ import app from "../../jobnimbus.app.mjs";
2
+ import utils from "../../common/utils.mjs";
3
+ import { attachmentTypes } from "../../common/constants.mjs";
4
+ import { ConfigurationError } from "@pipedream/platform";
5
+ import fs from "fs";
6
+
7
+ export default {
8
+ key: "jobnimbus-create-attachment",
9
+ version: "0.0.1",
10
+ type: "action",
11
+ name: "Create Attachment",
12
+ description: "Creates an attachment. [See the documentation](https://documenter.getpostman.com/view/3919598/S11PpG4x#5f3f485b-91f9-4ed9-912c-99a07987ac6c)",
13
+ props: {
14
+ app,
15
+ filePath: {
16
+ type: "string",
17
+ label: "File Path",
18
+ description: "The file to upload, please provide a valid file from `/tmp`. To upload a file to `/tmp` folder, please follow the doc [here](https://pipedream.com/docs/code/nodejs/working-with-files/#writing-a-file-to-tmp)",
19
+ },
20
+ type: {
21
+ type: "string",
22
+ label: "Type",
23
+ description: "The record type.",
24
+ options: attachmentTypes,
25
+ },
26
+ customerIdFromContacts: { //There is no endpoint that can be customers fetched from.
27
+ propDefinition: [
28
+ app,
29
+ "customerIdFromContacts",
30
+ ],
31
+ optional: true,
32
+ },
33
+ filename: {
34
+ type: "string",
35
+ label: "File Name",
36
+ description: "Name of the file to be uploaded.",
37
+ optional: true,
38
+ },
39
+ description: {
40
+ type: "string",
41
+ label: "Description",
42
+ description: "The description of the file.",
43
+ optional: true,
44
+ },
45
+ },
46
+ async run ({ $ }) {
47
+ const filePath = utils.isValidFile(this.filePath);
48
+ if (!filePath) {
49
+ throw new ConfigurationError("`File Path` must be a valid file path!");
50
+ }
51
+ const fileData = fs.readFileSync(filePath, {
52
+ flag: "r",
53
+ encoding: "base64",
54
+ });
55
+ const data = {
56
+ ...utils.extractProps(this, {
57
+ customerIdFromContacts: "customer",
58
+ }),
59
+ data: fileData,
60
+ };
61
+ delete data["filePath"];
62
+ const resp = await this.app.createAttachment({
63
+ $,
64
+ data,
65
+ });
66
+ $.export("$summary", `Successfully created attachment with ID ${resp.jnid}`);
67
+ return resp;
68
+ },
69
+ };
@@ -0,0 +1,40 @@
1
+ /* eslint-disable pipedream/props-label */
2
+ /* eslint-disable pipedream/props-description */
3
+ import base from "../common/contact-base.mjs";
4
+
5
+ export default {
6
+ key: "jobnimbus-create-contact",
7
+ version: "0.0.1",
8
+ type: "action",
9
+ name: "Create Contact",
10
+ description: "Creates a contact. [See the documentation](https://documenter.getpostman.com/view/3919598/S11PpG4x#7ec1541f-7241-4840-9322-0ed83c01d48e)",
11
+ ...base,
12
+ props: {
13
+ ...base.props,
14
+ firstName: {
15
+ ...base.props.firstName,
16
+ optional: false,
17
+ },
18
+ lastName: {
19
+ ...base.props.lastName,
20
+ optional: false,
21
+ },
22
+ displayName: {
23
+ ...base.props.displayName,
24
+ optional: false,
25
+ },
26
+ company: {
27
+ ...base.props.company,
28
+ optional: false,
29
+ },
30
+ },
31
+ async run ({ $ }) {
32
+ const data = this.prepareData();
33
+ const resp = await this.app.createContact({
34
+ $,
35
+ data,
36
+ });
37
+ $.export("$summary", `Successfully created contact with ID ${resp.jnid}`);
38
+ return resp;
39
+ },
40
+ };
@@ -0,0 +1,36 @@
1
+ import app from "../../jobnimbus.app.mjs";
2
+
3
+ export default {
4
+ key: "jobnimbus-find-contact-by-email",
5
+ version: "0.0.1",
6
+ type: "action",
7
+ name: "Find Contact By Email",
8
+ description: "Finds contact by email. [See the documentation](https://documenter.getpostman.com/view/3919598/S11PpG4x#46dff3eb-80ae-46b1-a399-eb80ab2a09bc)",
9
+ props: {
10
+ app,
11
+ email: {
12
+ propDefinition: [
13
+ app,
14
+ "email",
15
+ ],
16
+ },
17
+ },
18
+ async run ({ $ }) {
19
+ const resp = await this.app.getContacts({
20
+ $,
21
+ params: {
22
+ filter: {
23
+ must: [
24
+ {
25
+ term: {
26
+ email: this.email,
27
+ },
28
+ },
29
+ ],
30
+ },
31
+ },
32
+ });
33
+ $.export("$summary", "Contact has been retrieved successfully.");
34
+ return resp;
35
+ },
36
+ };
@@ -0,0 +1,26 @@
1
+ import app from "../../jobnimbus.app.mjs";
2
+
3
+ export default {
4
+ key: "jobnimbus-find-contact-by-id",
5
+ version: "0.0.1",
6
+ type: "action",
7
+ name: "Find Contact By ID",
8
+ description: "Finds contact by ID. [See the documentation](https://documenter.getpostman.com/view/3919598/S11PpG4x#02875033-b94e-4ed9-83cc-d157fba8e5d5)",
9
+ props: {
10
+ app,
11
+ contactId: {
12
+ propDefinition: [
13
+ app,
14
+ "contactId",
15
+ ],
16
+ },
17
+ },
18
+ async run ({ $ }) {
19
+ const resp = await this.app.getContact({
20
+ $,
21
+ contactId: this.contactId,
22
+ });
23
+ $.export("$summary", "Contact has been retrieved successfully.");
24
+ return resp;
25
+ },
26
+ };
@@ -0,0 +1,30 @@
1
+ import base from "../common/contact-base.mjs";
2
+
3
+ export default {
4
+ key: "jobnimbus-update-contact",
5
+ version: "0.0.1",
6
+ type: "action",
7
+ name: "Update Contact",
8
+ description: "Updates a contact. [See the documentation](https://documenter.getpostman.com/view/3919598/S11PpG4x#6c94f9a6-2bac-4189-9b2e-5d856f0fe310)",
9
+ ...base,
10
+ props: {
11
+ app: base.props.app,
12
+ contactId: {
13
+ propDefinition: [
14
+ base.props.app,
15
+ "contactId",
16
+ ],
17
+ },
18
+ ...base.props,
19
+ },
20
+ async run ({ $ }) {
21
+ const data = this.prepareData();
22
+ const resp = await this.app.updateContact({
23
+ $,
24
+ contactId: this.contactId,
25
+ data,
26
+ });
27
+ $.export("$summary", "Contact has been updated successfully.");
28
+ return resp;
29
+ },
30
+ };
@@ -0,0 +1,38 @@
1
+ const attachmentTypes = [
2
+ {
3
+ label: "Document",
4
+ value: "1",
5
+ },
6
+ {
7
+ label: "Photo",
8
+ value: "2",
9
+ },
10
+ {
11
+ label: "Email Attachment",
12
+ value: "3",
13
+ },
14
+ {
15
+ label: "naturalForms",
16
+ value: "4",
17
+ },
18
+ {
19
+ label: "Invoice",
20
+ value: "5",
21
+ },
22
+ {
23
+ label: "Eagleview",
24
+ value: "6",
25
+ },
26
+ {
27
+ label: "Accurence",
28
+ value: "7",
29
+ },
30
+ {
31
+ label: "Credit Memo",
32
+ value: "8",
33
+ },
34
+ ];
35
+
36
+ export {
37
+ attachmentTypes,
38
+ };
@@ -0,0 +1,75 @@
1
+ import fs from "fs";
2
+
3
+ const PAGE_SIZE = 25;
4
+
5
+ export default {
6
+ isValidFile(filePath) {
7
+ const filePathWithTmp = `/tmp/${filePath}`;
8
+ if (fs.existsSync(filePathWithTmp)) {
9
+ return filePathWithTmp;
10
+ }
11
+ if (fs.existsSync(filePath)) {
12
+ return filePath;
13
+ }
14
+ return false;
15
+ },
16
+ extractProps(that, pairs) {
17
+ const {
18
+ // eslint-disable-next-line no-unused-vars
19
+ app,
20
+ ...props
21
+ } = that;
22
+ return Object.keys(props)
23
+ .reduce((acc, key) => {
24
+ const keyMapped = pairs[key];
25
+ const value = props[key];
26
+ const newKey = keyMapped ?? key;
27
+ return {
28
+ ...acc,
29
+ [newKey]: value,
30
+ };
31
+ }, {});
32
+ },
33
+ async asyncPropHandler({
34
+ resourceFn, page, mapper, params, resourceKey = "results",
35
+ } = {}) {
36
+ const { [resourceKey]: items } =
37
+ await resourceFn({
38
+ params: {
39
+ ...params,
40
+ ...(typeof page != "undefined" && {
41
+ from: page * PAGE_SIZE,
42
+ size: PAGE_SIZE,
43
+ }),
44
+ },
45
+ });
46
+ return items.map(mapper);
47
+ },
48
+ async *getResourcesStream({
49
+ resourceFn, resourceFnArgs, resourceKey,
50
+ }) {
51
+ let page = 0;
52
+ while (true) {
53
+ const { [resourceKey]: nextResources } =
54
+ await resourceFn({
55
+ ...resourceFnArgs,
56
+ params: {
57
+ ...resourceFnArgs?.params,
58
+ from: page++ * PAGE_SIZE,
59
+ size: PAGE_SIZE,
60
+ },
61
+ });
62
+ if (!nextResources?.length) {
63
+ console.log("No more resources");
64
+ return;
65
+ }
66
+ for (const resource of nextResources) {
67
+ yield resource;
68
+ }
69
+ if (nextResources?.length < PAGE_SIZE) {
70
+ console.log("Number of resources less than page size");
71
+ return;
72
+ }
73
+ }
74
+ },
75
+ };
@@ -0,0 +1,131 @@
1
+ import { axios } from "@pipedream/platform";
2
+ import utils from "./common/utils.mjs";
3
+
4
+ export default {
5
+ type: "app",
6
+ app: "jobnimbus",
7
+ propDefinitions: {
8
+ contactId: {
9
+ type: "string",
10
+ label: "Contact ID",
11
+ description: "JNID of the contact.",
12
+ async options({ page }) {
13
+ return utils.asyncPropHandler({
14
+ resourceFn: this.getContacts,
15
+ page,
16
+ params: {
17
+ fields: "jnid,display_name",
18
+ },
19
+ mapper: ({
20
+ display_name: label,
21
+ jnid: value,
22
+ }) => ({
23
+ label,
24
+ value,
25
+ }),
26
+ });
27
+ },
28
+ },
29
+ customerIdFromContacts: {
30
+ type: "string",
31
+ label: "Customer ID",
32
+ description: "JNID of the customer. These options are fetched from contacts. There can be missing customers or duplicates. If missing, please provide the ID manually.",
33
+ async options({ page }) {
34
+ return utils.asyncPropHandler({
35
+ resourceFn: this.getContacts,
36
+ page,
37
+ params: {
38
+ fields: "customer,company",
39
+ },
40
+ mapper: ({
41
+ company: label,
42
+ customer: value,
43
+ }) => ({
44
+ label,
45
+ value,
46
+ }),
47
+ });
48
+ },
49
+ },
50
+ email: {
51
+ type: "string",
52
+ label: "Email",
53
+ description: "The email address associated with the contact.",
54
+ },
55
+ },
56
+ methods: {
57
+ _getUrl(path) {
58
+ return `https://app.jobnimbus.com/api1${path}`;
59
+ },
60
+ _getHeaders(headers = {}) {
61
+ return {
62
+ "Authorization": `Bearer ${this.$auth.api_key}`,
63
+ "Content-Type": "application/json",
64
+ "Accept": "application/json",
65
+ "User-Agent": "@PipedreamHQ/pipedream v0.1",
66
+ ...headers,
67
+ };
68
+ },
69
+ _makeRequest({
70
+ $ = this, path, headers, ...args
71
+ } = {}) {
72
+ const config = {
73
+ url: this._getUrl(path),
74
+ headers: this._getHeaders(headers),
75
+ ...args,
76
+ };
77
+ return axios($, config);
78
+ },
79
+ getContact({
80
+ contactId, ...args
81
+ } = {}) {
82
+ return this._makeRequest({
83
+ path: `/contacts/${contactId}`,
84
+ ...args,
85
+ });
86
+ },
87
+ getJob({
88
+ jobId, ...args
89
+ } = {}) {
90
+ return this._makeRequest({
91
+ path: `/jobs/${jobId}`,
92
+ ...args,
93
+ });
94
+ },
95
+ getContacts(args = {}) {
96
+ return this._makeRequest({
97
+ path: "/contacts",
98
+ ...args,
99
+ });
100
+ },
101
+ getActivities(args = {}) {
102
+ return this._makeRequest({
103
+ path: "/activities",
104
+ ...args,
105
+ });
106
+ },
107
+ createContact(args = {}) {
108
+ return this._makeRequest({
109
+ path: "/contacts",
110
+ method: "POST",
111
+ ...args,
112
+ });
113
+ },
114
+ updateContact({
115
+ contactId, ...args
116
+ } = {}) {
117
+ return this._makeRequest({
118
+ path: `/contacts/${contactId}`,
119
+ method: "PUT",
120
+ ...args,
121
+ });
122
+ },
123
+ createAttachment(args = {}) {
124
+ return this._makeRequest({
125
+ path: "/files",
126
+ method: "POST",
127
+ ...args,
128
+ });
129
+ },
130
+ },
131
+ };
package/package.json CHANGED
@@ -1,18 +1,17 @@
1
1
  {
2
2
  "name": "@pipedream/jobnimbus",
3
- "version": "0.0.2",
3
+ "version": "0.1.0",
4
4
  "description": "Pipedream Jobnimbus Components",
5
- "main": "dist/app/jobnimbus.app.mjs",
5
+ "main": "jobnimbus.app.mjs",
6
6
  "keywords": [
7
7
  "pipedream",
8
8
  "jobnimbus"
9
9
  ],
10
- "files": [
11
- "dist"
12
- ],
13
10
  "homepage": "https://pipedream.com/apps/jobnimbus",
14
11
  "author": "Pipedream <support@pipedream.com> (https://pipedream.com/)",
15
- "license": "MIT",
12
+ "dependencies": {
13
+ "@pipedream/platform": "^1.5.1"
14
+ },
16
15
  "publishConfig": {
17
16
  "access": "public"
18
17
  }
@@ -0,0 +1,11 @@
1
+ import common from "../common/activity-based.mjs";
2
+
3
+ export default {
4
+ ...common,
5
+ key: "jobnimbus-activity-created",
6
+ name: "New Activity Created Event",
7
+ description: "Emit new events when a new activity created. [See the docs](https://documenter.getpostman.com/view/3919598/S11PpG4x#62c713fe-5d46-4fd6-9953-db49255fd5e0)",
8
+ version: "0.0.1",
9
+ type: "source",
10
+ dedupe: "unique",
11
+ };
@@ -0,0 +1,38 @@
1
+ import common from "./common.mjs";
2
+
3
+ export default {
4
+ ...common,
5
+ methods: {
6
+ ...common.methods,
7
+ getResourceFnConfig() {
8
+ return {
9
+ resourceFn: this.app.getActivities,
10
+ resourceFnArgs: {
11
+ boardId: this.boardId,
12
+ params: {
13
+ must: [
14
+ {
15
+ range: {
16
+ date_created: {
17
+ gte: this.getLastComparable(),
18
+ },
19
+ },
20
+ },
21
+ ],
22
+ },
23
+ },
24
+ resourceKey: "activity",
25
+ };
26
+ },
27
+ getComparable(item) {
28
+ return item.date_created;
29
+ },
30
+ getMeta(item) {
31
+ return {
32
+ id: item.date_created,
33
+ summary: item.note,
34
+ ts: item.date_created * 1000,
35
+ };
36
+ },
37
+ },
38
+ };
@@ -0,0 +1,57 @@
1
+ import app from "../../jobnimbus.app.mjs";
2
+ import utils from "../../common/utils.mjs";
3
+ import { DEFAULT_POLLING_SOURCE_TIMER_INTERVAL } from "@pipedream/platform";
4
+
5
+ export default {
6
+ props: {
7
+ app,
8
+ timer: {
9
+ type: "$.interface.timer",
10
+ default: {
11
+ intervalSeconds: DEFAULT_POLLING_SOURCE_TIMER_INTERVAL,
12
+ },
13
+ },
14
+ db: "$.service.db",
15
+ },
16
+ methods: {
17
+ setLastComparable(lastComparable) {
18
+ this.db.set("lastComparable", lastComparable);
19
+ },
20
+ getLastComparable() {
21
+ return this.db.get("lastComparable") || 0;
22
+ },
23
+ getResourceFnConfig() {
24
+ throw new Error("getResourceFnConfig() is not implemented!");
25
+ },
26
+ getItem(item) {
27
+ return item;
28
+ },
29
+ getMeta() {
30
+ throw new Error("getMeta() is not implemented!");
31
+ },
32
+ getComparable() {
33
+ throw new Error("getComparable() is not implemented!");
34
+ },
35
+ compareFn() {
36
+ return true;
37
+ },
38
+ },
39
+ async run() {
40
+ let lastComparable = this.getLastComparable();
41
+ const resourcesStream = utils.getResourcesStream(this.getResourceFnConfig());
42
+ for await (const resource of resourcesStream) {
43
+ const comparable = this.getComparable(resource);
44
+ if (lastComparable < comparable && this.compareFn(resource)) {
45
+ const item = await this.getItem(resource);
46
+ this.$emit(
47
+ item,
48
+ this.getMeta(item),
49
+ );
50
+ }
51
+ if (lastComparable < comparable) {
52
+ lastComparable = comparable;
53
+ }
54
+ }
55
+ this.setLastComparable(lastComparable);
56
+ },
57
+ };
@@ -0,0 +1,29 @@
1
+ import common from "../common/activity-based.mjs";
2
+
3
+ export default {
4
+ ...common,
5
+ key: "jobnimbus-contact-created",
6
+ name: "New Contact Created Event",
7
+ description: "Emit new events when a new contact is created. [See the docs](https://documenter.getpostman.com/view/3919598/S11PpG4x#62c713fe-5d46-4fd6-9953-db49255fd5e0)",
8
+ version: "0.0.1",
9
+ type: "source",
10
+ dedupe: "unique",
11
+ methods: {
12
+ ...common.methods,
13
+ compareFn(item) {
14
+ return item?.record_type_name == "Contact Created";
15
+ },
16
+ getItem(item) {
17
+ return this.app.getContact({
18
+ contactId: item.primary.id,
19
+ });
20
+ },
21
+ getMeta(item) {
22
+ return {
23
+ id: item.date_created,
24
+ summary: `New contact has been created - ID: ${item.jnid}`,
25
+ ts: item.date_created * 1000,
26
+ };
27
+ },
28
+ },
29
+ };
@@ -0,0 +1,24 @@
1
+ import common from "../common/activity-based.mjs";
2
+
3
+ export default {
4
+ ...common,
5
+ key: "jobnimbus-contact-deleted",
6
+ name: "New Contact Deleted Event",
7
+ description: "Emit new events when a contact is deleted. [See the docs](https://documenter.getpostman.com/view/3919598/S11PpG4x#62c713fe-5d46-4fd6-9953-db49255fd5e0)",
8
+ version: "0.0.1",
9
+ type: "source",
10
+ dedupe: "unique",
11
+ methods: {
12
+ ...common.methods,
13
+ compareFn(item) {
14
+ return item?.record_type_name == "Contact Deleted";
15
+ },
16
+ getMeta(item) {
17
+ return {
18
+ id: item.date_created,
19
+ summary: `Contact has been deleted - ID: ${item.primary.id}`,
20
+ ts: item.date_created * 1000,
21
+ };
22
+ },
23
+ },
24
+ };
@@ -0,0 +1,29 @@
1
+ import common from "../common/activity-based.mjs";
2
+
3
+ export default {
4
+ ...common,
5
+ key: "jobnimbus-contact-updated",
6
+ name: "New Contact Updated Event",
7
+ description: "Emit new events when a contact is updated. [See the docs](https://documenter.getpostman.com/view/3919598/S11PpG4x#62c713fe-5d46-4fd6-9953-db49255fd5e0)",
8
+ version: "0.0.1",
9
+ type: "source",
10
+ dedupe: "unique",
11
+ methods: {
12
+ ...common.methods,
13
+ compareFn(item) {
14
+ return item?.record_type_name == "Contact Modified";
15
+ },
16
+ async getItem(item) {
17
+ return this.app.getContact({
18
+ contactId: item.primary.id,
19
+ });
20
+ },
21
+ getMeta(item) {
22
+ return {
23
+ id: item.date_updated,
24
+ summary: `Contact has been updated - ID: ${item.jnid}`,
25
+ ts: item.date_updated * 1000,
26
+ };
27
+ },
28
+ },
29
+ };
@@ -0,0 +1,29 @@
1
+ import common from "../common/activity-based.mjs";
2
+
3
+ export default {
4
+ ...common,
5
+ key: "jobnimbus-job-created",
6
+ name: "New Job Created Event",
7
+ description: "Emit new events when a new job is created. [See the docs](https://documenter.getpostman.com/view/3919598/S11PpG4x#62c713fe-5d46-4fd6-9953-db49255fd5e0)",
8
+ version: "0.0.1",
9
+ type: "source",
10
+ dedupe: "unique",
11
+ methods: {
12
+ ...common.methods,
13
+ compareFn(item) {
14
+ return item?.record_type_name == "Job Created";
15
+ },
16
+ async getItem(item) {
17
+ return this.app.getJob({
18
+ jobId: item.primary.id,
19
+ });
20
+ },
21
+ getMeta(item) {
22
+ return {
23
+ id: item.date_created,
24
+ summary: `New job has been created - ID: ${item.jnid}`,
25
+ ts: item.date_created * 1000,
26
+ };
27
+ },
28
+ },
29
+ };
@@ -0,0 +1,24 @@
1
+ import common from "../common/activity-based.mjs";
2
+
3
+ export default {
4
+ ...common,
5
+ key: "jobnimbus-job-deleted",
6
+ name: "New Job Deleted Event",
7
+ description: "Emit new events when a job is deleted. [See the docs](https://documenter.getpostman.com/view/3919598/S11PpG4x#62c713fe-5d46-4fd6-9953-db49255fd5e0)",
8
+ version: "0.0.1",
9
+ type: "source",
10
+ dedupe: "unique",
11
+ methods: {
12
+ ...common.methods,
13
+ compareFn(item) {
14
+ return item?.record_type_name == "Job Deleted";
15
+ },
16
+ getMeta(item) {
17
+ return {
18
+ id: item.date_created,
19
+ summary: `Job has been deleted - ID: ${item.primary.id}`,
20
+ ts: item.date_created * 1000,
21
+ };
22
+ },
23
+ },
24
+ };
@@ -0,0 +1,29 @@
1
+ import common from "../common/activity-based.mjs";
2
+
3
+ export default {
4
+ ...common,
5
+ key: "jobnimbus-job-updated",
6
+ name: "New Job Updated Event",
7
+ description: "Emit new events when a job is updated. [See the docs](https://documenter.getpostman.com/view/3919598/S11PpG4x#62c713fe-5d46-4fd6-9953-db49255fd5e0)",
8
+ version: "0.0.1",
9
+ type: "source",
10
+ dedupe: "unique",
11
+ methods: {
12
+ ...common.methods,
13
+ compareFn(item) {
14
+ return item?.record_type_name == "Job Modified";
15
+ },
16
+ async getItem(item) {
17
+ return this.app.getJob({
18
+ jobId: item.primary.id,
19
+ });
20
+ },
21
+ getMeta(item) {
22
+ return {
23
+ id: item.date_updated,
24
+ summary: `Job has been updated - ID: ${item.jnid}`,
25
+ ts: item.date_updated * 1000,
26
+ };
27
+ },
28
+ },
29
+ };