@pipedream/zendesk 0.3.5 → 0.5.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 CHANGED
@@ -1,8 +1,11 @@
1
1
  # Overview
2
2
 
3
- Using the Zendesk API, you can build custom apps and integrations to automate processes and help your teams build better customer relationships.
3
+ Using the Zendesk API, you can build custom apps and integrations to automate
4
+ processes and help your teams build better customer relationships.
4
5
 
5
- The API provides a range of methods to interact with your customer help desk, customer data, and customer communication tools. This enables you to create custom customer experiences that are tailored to your business needs.
6
+ The API provides a range of methods to interact with your customer help desk,
7
+ customer data, and customer communication tools. This enables you to create
8
+ custom customer experiences that are tailored to your business needs.
6
9
 
7
10
  Some examples of what you can build using the Zendesk API include:
8
11
 
@@ -0,0 +1,78 @@
1
+ import app from "../../zendesk.app.mjs";
2
+
3
+ export default {
4
+ key: "zendesk-create-ticket",
5
+ name: "Create Ticket",
6
+ description: "Creates a ticket. [See the docs](https://developer.zendesk.com/api-reference/ticketing/tickets/tickets/#create-ticket).",
7
+ type: "action",
8
+ version: "0.1.0",
9
+ props: {
10
+ app,
11
+ ticketCommentBody: {
12
+ propDefinition: [
13
+ app,
14
+ "ticketCommentBody",
15
+ ],
16
+ },
17
+ ticketPriority: {
18
+ propDefinition: [
19
+ app,
20
+ "ticketPriority",
21
+ ],
22
+ },
23
+ ticketSubject: {
24
+ propDefinition: [
25
+ app,
26
+ "ticketSubject",
27
+ ],
28
+ },
29
+ ticketStatus: {
30
+ propDefinition: [
31
+ app,
32
+ "ticketStatus",
33
+ ],
34
+ },
35
+ customSubdomain: {
36
+ propDefinition: [
37
+ app,
38
+ "customSubdomain",
39
+ ],
40
+ },
41
+ },
42
+ methods: {
43
+ createTicket(args = {}) {
44
+ return this.app.create({
45
+ path: "/tickets",
46
+ ...args,
47
+ });
48
+ },
49
+ },
50
+ async run({ $: step }) {
51
+ const {
52
+ ticketCommentBody,
53
+ ticketPriority,
54
+ ticketSubject,
55
+ ticketStatus,
56
+ customSubdomain,
57
+ } = this;
58
+
59
+ const response = await this.createTicket({
60
+ step,
61
+ customSubdomain,
62
+ data: {
63
+ ticket: {
64
+ comment: {
65
+ body: ticketCommentBody,
66
+ },
67
+ priority: ticketPriority,
68
+ subject: ticketSubject,
69
+ status: ticketStatus,
70
+ },
71
+ },
72
+ });
73
+
74
+ step.export("$summary", `Successfully created ticket with ID ${response.ticket.id}`);
75
+
76
+ return response;
77
+ },
78
+ };
@@ -0,0 +1,50 @@
1
+ import app from "../../zendesk.app.mjs";
2
+
3
+ export default {
4
+ key: "zendesk-delete-ticket",
5
+ name: "Delete Ticket",
6
+ description: "Deletes a ticket. [See the docs](https://developer.zendesk.com/api-reference/ticketing/tickets/tickets/#delete-ticket).",
7
+ type: "action",
8
+ version: "0.1.0",
9
+ props: {
10
+ app,
11
+ ticketId: {
12
+ propDefinition: [
13
+ app,
14
+ "ticketId",
15
+ ],
16
+ },
17
+ customSubdomain: {
18
+ propDefinition: [
19
+ app,
20
+ "customSubdomain",
21
+ ],
22
+ },
23
+ },
24
+ methods: {
25
+ deleteTicket({
26
+ ticketId, ...args
27
+ } = {}) {
28
+ return this.app.delete({
29
+ path: `/tickets/${ticketId}`,
30
+ ...args,
31
+ });
32
+ },
33
+ },
34
+ async run({ $: step }) {
35
+ const {
36
+ ticketId,
37
+ customSubdomain,
38
+ } = this;
39
+
40
+ await this.deleteTicket({
41
+ step,
42
+ ticketId,
43
+ customSubdomain,
44
+ });
45
+
46
+ step.export("$summary", "Successfully deleted ticket");
47
+
48
+ return true;
49
+ },
50
+ };
@@ -0,0 +1,88 @@
1
+ import app from "../../zendesk.app.mjs";
2
+
3
+ export default {
4
+ key: "zendesk-update-ticket",
5
+ name: "Update Ticket",
6
+ description: "Updates a ticket. [See the docs](https://developer.zendesk.com/api-reference/ticketing/tickets/tickets/#update-ticket).",
7
+ type: "action",
8
+ version: "0.1.0",
9
+ props: {
10
+ app,
11
+ ticketId: {
12
+ propDefinition: [
13
+ app,
14
+ "ticketId",
15
+ ],
16
+ },
17
+ ticketCommentBody: {
18
+ propDefinition: [
19
+ app,
20
+ "ticketCommentBody",
21
+ ],
22
+ },
23
+ ticketPriority: {
24
+ propDefinition: [
25
+ app,
26
+ "ticketPriority",
27
+ ],
28
+ },
29
+ ticketSubject: {
30
+ propDefinition: [
31
+ app,
32
+ "ticketSubject",
33
+ ],
34
+ },
35
+ ticketStatus: {
36
+ propDefinition: [
37
+ app,
38
+ "ticketStatus",
39
+ ],
40
+ },
41
+ customSubdomain: {
42
+ propDefinition: [
43
+ app,
44
+ "customSubdomain",
45
+ ],
46
+ },
47
+ },
48
+ methods: {
49
+ updateTicket({
50
+ ticketId, ...args
51
+ } = {}) {
52
+ return this.app.update({
53
+ path: `/tickets/${ticketId}`,
54
+ ...args,
55
+ });
56
+ },
57
+ },
58
+ async run({ $: step }) {
59
+ const {
60
+ ticketId,
61
+ ticketCommentBody,
62
+ ticketPriority,
63
+ ticketSubject,
64
+ ticketStatus,
65
+ customSubdomain,
66
+ } = this;
67
+
68
+ const response = await this.updateTicket({
69
+ step,
70
+ ticketId,
71
+ customSubdomain,
72
+ data: {
73
+ ticket: {
74
+ comment: {
75
+ body: ticketCommentBody,
76
+ },
77
+ priority: ticketPriority,
78
+ subject: ticketSubject,
79
+ status: ticketStatus,
80
+ },
81
+ },
82
+ });
83
+
84
+ step.export("$summary", `Successfully updated ticket with ID ${response.ticket.id}`);
85
+
86
+ return response;
87
+ },
88
+ };
@@ -6,11 +6,30 @@ const TRIGGER_ID = "triggerId";
6
6
  const PAGE_SIZE_PARAM = "page[size]";
7
7
  const PAGE_AFTER_PARAM = "page[after]";
8
8
  const SORT_BY_POSITION_ASC = "position";
9
+ const SORT_BY_UPDATED_AT_DESC = "-updated_at";
9
10
  const X_ZENDESK_WEBHOOK_SIGNATURE_HEADER = "x-zendesk-webhook-signature";
10
11
  const X_ZENDESK_WEBHOOK_SIGNATURE_TIMESTAMP_HEADER = "x-zendesk-webhook-signature-timestamp";
11
12
  const SIGNING_SECRET = "signingSecret";
12
13
  const SIGNING_SECRET_ALGORITHM = "sha256";
13
14
  const BASE_64 = "base64";
15
+ const DEFAULT_LIMIT = 20;
16
+ const DEFAULT_TIMEOUT = 10000;
17
+
18
+ const TICKET_PRIORITY_OPTIONS = {
19
+ URGENT: "urgent",
20
+ HIGH: "high",
21
+ NORMAL: "normal",
22
+ LOW: "low",
23
+ };
24
+
25
+ const TICKET_STATUS_OPTIONS = {
26
+ NEW: "new",
27
+ OPEN: "open",
28
+ PENDING: "pending",
29
+ HOLD: "hold",
30
+ SOLVED: "solved",
31
+ CLOSED: "closed",
32
+ };
14
33
 
15
34
  export default {
16
35
  SUBDOMAIN_PLACEHOLDER,
@@ -21,9 +40,14 @@ export default {
21
40
  PAGE_SIZE_PARAM,
22
41
  PAGE_AFTER_PARAM,
23
42
  SORT_BY_POSITION_ASC,
43
+ SORT_BY_UPDATED_AT_DESC,
24
44
  X_ZENDESK_WEBHOOK_SIGNATURE_HEADER,
25
45
  X_ZENDESK_WEBHOOK_SIGNATURE_TIMESTAMP_HEADER,
26
46
  SIGNING_SECRET,
27
47
  SIGNING_SECRET_ALGORITHM,
28
48
  BASE_64,
49
+ DEFAULT_LIMIT,
50
+ DEFAULT_TIMEOUT,
51
+ TICKET_PRIORITY_OPTIONS,
52
+ TICKET_STATUS_OPTIONS,
29
53
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pipedream/zendesk",
3
- "version": "0.3.5",
3
+ "version": "0.5.0",
4
4
  "description": "Pipedream Zendesk Components",
5
5
  "main": "zendesk.app.mjs",
6
6
  "keywords": [
@@ -1,4 +1,4 @@
1
- import common from "./base.mjs";
1
+ import common from "./webhook.mjs";
2
2
 
3
3
  export default {
4
4
  ...common,
@@ -1,38 +1,50 @@
1
1
  import crypto from "crypto";
2
- import zendesk from "../../zendesk.app.mjs";
2
+ import app from "../../zendesk.app.mjs";
3
3
  import constants from "../../common/constants.mjs";
4
4
 
5
5
  export default {
6
6
  props: {
7
- zendesk,
7
+ app,
8
8
  db: "$.service.db",
9
9
  http: "$.interface.http",
10
10
  categoryId: {
11
11
  propDefinition: [
12
- zendesk,
12
+ app,
13
13
  "categoryId",
14
14
  ],
15
15
  },
16
+ customSubdomain: {
17
+ propDefinition: [
18
+ app,
19
+ "customSubdomain",
20
+ ],
21
+ },
16
22
  },
17
23
  hooks: {
18
24
  async activate() {
19
- const { categoryId } = this;
25
+ const {
26
+ categoryId,
27
+ customSubdomain,
28
+ } = this;
20
29
 
21
- const { webhook } = await this.zendesk.createWebhook({
30
+ const { webhook } = await this.createWebhook({
31
+ customSubdomain,
22
32
  data: this.setupWebhookData(),
23
33
  });
24
34
 
25
35
  const { id: webhookId } = webhook;
26
36
  this.setWebhookId(webhookId);
27
37
 
28
- const { signing_secret: signingSecret } = await this.zendesk.showWebhookSigningSecret({
38
+ const { signing_secret: signingSecret } = await this.showWebhookSigningSecret({
39
+ customSubdomain,
29
40
  webhookId,
30
41
  });
31
42
 
32
43
  const { secret } = signingSecret;
33
44
  this.setSigningSecret(secret);
34
45
 
35
- const { trigger } = await this.zendesk.createTrigger({
46
+ const { trigger } = await this.createTrigger({
47
+ customSubdomain,
36
48
  data: this.setupTriggerData({
37
49
  webhookId,
38
50
  categoryId,
@@ -43,17 +55,56 @@ export default {
43
55
  this.setTriggerId(String(triggerId));
44
56
  },
45
57
  async deactivate() {
58
+ const { customSubdomain } = this;
46
59
  await Promise.all([
47
- this.zendesk.deleteTrigger({
60
+ this.deleteTrigger({
61
+ customSubdomain,
48
62
  triggerId: this.getTriggerId(),
49
63
  }),
50
- this.zendesk.deleteWebhook({
64
+ this.deleteWebhook({
65
+ customSubdomain,
51
66
  webhookId: this.getWebhookId(),
52
67
  }),
53
68
  ]);
54
69
  },
55
70
  },
56
71
  methods: {
72
+ createWebhook(args = {}) {
73
+ return this.app.create({
74
+ path: "/webhooks",
75
+ ...args,
76
+ });
77
+ },
78
+ deleteWebhook({
79
+ webhookId, ...args
80
+ } = {}) {
81
+ return this.app.delete({
82
+ path: `/webhooks/${webhookId}`,
83
+ ...args,
84
+ });
85
+ },
86
+ createTrigger(args = {}) {
87
+ return this.app.create({
88
+ path: "/triggers",
89
+ ...args,
90
+ });
91
+ },
92
+ deleteTrigger({
93
+ triggerId, ...args
94
+ } = {}) {
95
+ return this.app.delete({
96
+ path: `/triggers/${triggerId}`,
97
+ ...args,
98
+ });
99
+ },
100
+ showWebhookSigningSecret({
101
+ webhookId, ...args
102
+ } = {}) {
103
+ return this.app.makeRequest({
104
+ path: `/webhooks/${webhookId}/signing_secret`,
105
+ ...args,
106
+ });
107
+ },
57
108
  setWebhookId(webhookId) {
58
109
  this.db.set(constants.WEBHOOK_ID, webhookId);
59
110
  },
@@ -6,7 +6,7 @@ export default {
6
6
  key: "zendesk-new-ticket",
7
7
  type: "source",
8
8
  description: "Emit new event when a ticket is created",
9
- version: "0.0.2",
9
+ version: "0.2.0",
10
10
  dedupe: "unique",
11
11
  methods: {
12
12
  ...common.methods,
@@ -6,7 +6,7 @@ export default {
6
6
  key: "zendesk-ticket-closed",
7
7
  type: "source",
8
8
  description: "Emit new event when a ticket has changed to closed status",
9
- version: "0.0.2",
9
+ version: "0.2.0",
10
10
  dedupe: "unique",
11
11
  methods: {
12
12
  ...common.methods,
@@ -6,7 +6,7 @@ export default {
6
6
  key: "zendesk-ticket-pended",
7
7
  type: "source",
8
8
  description: "Emit new event when a ticket has changed to pending status",
9
- version: "0.0.2",
9
+ version: "0.2.0",
10
10
  dedupe: "unique",
11
11
  methods: {
12
12
  ...common.methods,
@@ -6,7 +6,7 @@ export default {
6
6
  key: "zendesk-ticket-solved",
7
7
  type: "source",
8
8
  description: "Emit new event when a ticket has changed to solved status",
9
- version: "0.0.2",
9
+ version: "0.2.0",
10
10
  dedupe: "unique",
11
11
  methods: {
12
12
  ...common.methods,
@@ -0,0 +1,30 @@
1
+ import common from "../common/ticket.mjs";
2
+
3
+ export default {
4
+ ...common,
5
+ name: "Ticket Updated (Instant)",
6
+ key: "zendesk-ticket-updated",
7
+ type: "source",
8
+ description: "Emit new event when a ticket has been updated",
9
+ version: "0.2.0",
10
+ dedupe: "unique",
11
+ methods: {
12
+ ...common.methods,
13
+ getWebhookName() {
14
+ return "Ticket Updated Webhook";
15
+ },
16
+ getTriggerTitle() {
17
+ return "Ticket Updated Trigger";
18
+ },
19
+ getTriggerConditions() {
20
+ return {
21
+ all: [
22
+ {
23
+ field: "update_type",
24
+ value: "Change",
25
+ },
26
+ ],
27
+ };
28
+ },
29
+ },
30
+ };
package/zendesk.app.mjs CHANGED
@@ -18,7 +18,7 @@ export default {
18
18
  } =
19
19
  await this.listTriggerCategories({
20
20
  params: {
21
- [constants.PAGE_SIZE_PARAM]: 20,
21
+ [constants.PAGE_SIZE_PARAM]: constants.DEFAULT_LIMIT,
22
22
  sort: constants.SORT_BY_POSITION_ASC,
23
23
  [constants.PAGE_AFTER_PARAM]: afterCursor,
24
24
  },
@@ -37,102 +37,128 @@ export default {
37
37
  };
38
38
  },
39
39
  },
40
+ ticketId: {
41
+ type: "string",
42
+ label: "Ticket ID",
43
+ description: "The ID of the ticket.",
44
+ async options({ prevContext }) {
45
+ const { afterCursor } = prevContext;
46
+
47
+ const {
48
+ tickets,
49
+ meta,
50
+ } =
51
+ await this.listTickets({
52
+ params: {
53
+ [constants.PAGE_SIZE_PARAM]: constants.DEFAULT_LIMIT,
54
+ sort: constants.SORT_BY_UPDATED_AT_DESC,
55
+ [constants.PAGE_AFTER_PARAM]: afterCursor,
56
+ },
57
+ });
58
+
59
+ return {
60
+ context: {
61
+ afterCursor: meta.after_cursor,
62
+ },
63
+ options: tickets.map(({
64
+ id, subject,
65
+ }) => ({
66
+ label: subject || `Ticket #${id}`,
67
+ value: id,
68
+ })),
69
+ };
70
+ },
71
+ },
72
+ ticketCommentBody: {
73
+ type: "string",
74
+ label: "Comment body",
75
+ description: "The body of the comment.",
76
+ },
77
+ ticketPriority: {
78
+ type: "string",
79
+ label: "Ticket Priority",
80
+ description: "The priority of the ticket.",
81
+ optional: true,
82
+ options: Object.values(constants.TICKET_PRIORITY_OPTIONS),
83
+ },
84
+ ticketSubject: {
85
+ type: "string",
86
+ label: "Ticket Subject",
87
+ description: "The subject of the ticket.",
88
+ optional: true,
89
+ },
90
+ ticketStatus: {
91
+ type: "string",
92
+ label: "Ticket Status",
93
+ description: "The status of the ticket.",
94
+ optional: true,
95
+ options: Object.values(constants.TICKET_STATUS_OPTIONS),
96
+ },
97
+ customSubdomain: {
98
+ type: "string",
99
+ label: "Custom Subdomain",
100
+ description: "For Enterprise Zendesk accounts: optionally specify the subdomain to use. This will override the subdomain that was provided when connecting your Zendesk account to Pipedream. For example, if you Zendesk URL is https://examplehelp.zendesk.com, your subdomain is `examplehelp`",
101
+ optional: true,
102
+ },
40
103
  },
41
104
  methods: {
42
- getApiUrl({
43
- path, subdomain,
44
- }) {
105
+ getUrl(path, customSubdomain) {
45
106
  const {
46
107
  SUBDOMAIN_PLACEHOLDER,
47
108
  BASE_URL,
48
109
  VERSION_PATH,
49
110
  } = constants;
50
- return `${BASE_URL.replace(SUBDOMAIN_PLACEHOLDER, subdomain)}${VERSION_PATH}${path}`;
111
+ const baseUrl = BASE_URL.replace(
112
+ SUBDOMAIN_PLACEHOLDER,
113
+ customSubdomain?.trim() || this.$auth.subdomain,
114
+ );
115
+ return `${baseUrl}${VERSION_PATH}${path}`;
51
116
  },
52
- async makeRequest(customConfig) {
53
- const {
54
- $,
55
- url,
56
- path,
57
- ...configProps
58
- } = customConfig;
59
-
60
- const {
61
- oauth_access_token: oauthAccessToken,
62
- subdomain,
63
- } = this.$auth;
64
-
65
- const headers = {
66
- ...configProps?.headers,
67
- authorization: `Bearer ${oauthAccessToken}`,
117
+ getHeaders(headers) {
118
+ return {
119
+ authorization: `Bearer ${this.$auth.oauth_access_token}`,
120
+ ...headers,
68
121
  };
69
-
122
+ },
123
+ makeRequest({
124
+ step = this, url, path, headers, customSubdomain, ...args
125
+ }) {
70
126
  const config = {
71
- ...configProps,
72
- headers,
73
- url: url ?? this.getApiUrl({
74
- subdomain,
75
- path,
76
- }),
77
- timeout: 10000,
127
+ headers: this.getHeaders(headers),
128
+ url: url ?? this.getUrl(path, customSubdomain),
129
+ timeout: constants.DEFAULT_TIMEOUT,
130
+ ...args,
78
131
  };
79
-
80
- return axios($ ?? this, config);
132
+ return axios(step, config);
81
133
  },
82
- async createTrigger({
83
- $, data,
84
- }) {
134
+ create(args = {}) {
85
135
  return this.makeRequest({
86
- $,
87
136
  method: "post",
88
- path: "/triggers",
89
- data,
137
+ ...args,
90
138
  });
91
139
  },
92
- async deleteTrigger({
93
- $, triggerId,
94
- }) {
140
+ update(args = {}) {
95
141
  return this.makeRequest({
96
- $,
97
- method: "delete",
98
- path: `/triggers/${triggerId}`,
99
- });
100
- },
101
- async listTriggerCategories({
102
- $, url, params,
103
- }) {
104
- return this.makeRequest({
105
- $,
106
- url,
107
- path: "/trigger_categories",
108
- params,
142
+ method: "put",
143
+ ...args,
109
144
  });
110
145
  },
111
- async createWebhook({
112
- $, data,
113
- }) {
146
+ delete(args = {}) {
114
147
  return this.makeRequest({
115
- $,
116
- method: "post",
117
- path: "/webhooks",
118
- data,
148
+ method: "delete",
149
+ ...args,
119
150
  });
120
151
  },
121
- async deleteWebhook({
122
- $, webhookId,
123
- }) {
152
+ listTriggerCategories(args = {}) {
124
153
  return this.makeRequest({
125
- $,
126
- method: "delete",
127
- path: `/webhooks/${webhookId}`,
154
+ path: "/trigger_categories",
155
+ ...args,
128
156
  });
129
157
  },
130
- async showWebhookSigningSecret({
131
- $, webhookId,
132
- }) {
158
+ listTickets(args = {}) {
133
159
  return this.makeRequest({
134
- $,
135
- path: `/webhooks/${webhookId}/signing_secret`,
160
+ path: "/tickets",
161
+ ...args,
136
162
  });
137
163
  },
138
164
  },