@pipedream/zendesk 0.8.0 → 0.8.2

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.
@@ -5,7 +5,7 @@ export default {
5
5
  name: "Add Ticket Tags",
6
6
  description: "Add tags to a ticket (appends to existing tags). [See the documentation](https://developer.zendesk.com/api-reference/ticketing/ticket-management/tags/#add-tags).",
7
7
  type: "action",
8
- version: "0.0.2",
8
+ version: "0.0.3",
9
9
  props: {
10
10
  app,
11
11
  ticketId: {
@@ -5,7 +5,7 @@ export default {
5
5
  name: "Create Ticket",
6
6
  description: "Creates a ticket. [See the documentation](https://developer.zendesk.com/api-reference/ticketing/tickets/tickets/#create-ticket).",
7
7
  type: "action",
8
- version: "0.1.6",
8
+ version: "0.1.7",
9
9
  props: {
10
10
  app,
11
11
  ticketCommentBody: {
@@ -5,7 +5,7 @@ export default {
5
5
  name: "Delete Ticket",
6
6
  description: "Deletes a ticket. [See the documentation](https://developer.zendesk.com/api-reference/ticketing/tickets/tickets/#delete-ticket).",
7
7
  type: "action",
8
- version: "0.1.6",
8
+ version: "0.1.7",
9
9
  props: {
10
10
  app,
11
11
  ticketId: {
@@ -5,7 +5,7 @@ export default {
5
5
  name: "Get Ticket Info",
6
6
  description: "Retrieves information about a specific ticket. [See the documentation](https://developer.zendesk.com/api-reference/ticketing/tickets/tickets/#show-ticket).",
7
7
  type: "action",
8
- version: "0.0.4",
8
+ version: "0.0.5",
9
9
  props: {
10
10
  app,
11
11
  ticketId: {
@@ -4,7 +4,7 @@ export default {
4
4
  key: "zendesk-get-user-info",
5
5
  name: "Get User Info",
6
6
  description: "Retrieves information about a specific user. [See the documentation](https://developer.zendesk.com/api-reference/ticketing/users/users/#show-user).",
7
- version: "0.0.1",
7
+ version: "0.0.2",
8
8
  type: "action",
9
9
  props: {
10
10
  zendesk,
@@ -4,7 +4,7 @@ export default {
4
4
  key: "zendesk-list-locales",
5
5
  name: "List Locales",
6
6
  description: "Retrieves all locales. [See the documentation](https://developer.zendesk.com/api-reference/ticketing/account-configuration/locales/).",
7
- version: "0.0.1",
7
+ version: "0.0.2",
8
8
  type: "action",
9
9
  props: {
10
10
  zendesk,
@@ -4,7 +4,7 @@ export default {
4
4
  key: "zendesk-list-macros",
5
5
  name: "List Macros",
6
6
  description: "Retrieves all macros. [See the documentation](https://developer.zendesk.com/api-reference/ticketing/business-rules/macros/#list-macros).",
7
- version: "0.0.1",
7
+ version: "0.0.2",
8
8
  type: "action",
9
9
  props: {
10
10
  zendesk,
@@ -4,7 +4,7 @@ export default {
4
4
  key: "zendesk-list-ticket-comments",
5
5
  name: "List Ticket Comments",
6
6
  description: "Retrieves all comments for a specific ticket. [See the documentation](https://developer.zendesk.com/api-reference/ticketing/tickets/ticket_comments/#list-comments).",
7
- version: "0.0.1",
7
+ version: "0.0.2",
8
8
  type: "action",
9
9
  props: {
10
10
  zendesk,
@@ -5,7 +5,7 @@ export default {
5
5
  name: "List Tickets",
6
6
  description: "Retrieves a list of tickets. [See the documentation](https://developer.zendesk.com/api-reference/ticketing/tickets/tickets/#list-tickets).",
7
7
  type: "action",
8
- version: "0.0.4",
8
+ version: "0.0.5",
9
9
  props: {
10
10
  app,
11
11
  sortBy: {
@@ -5,7 +5,7 @@ export default {
5
5
  name: "Remove Ticket Tags",
6
6
  description: "Remove specific tags from a ticket. [See the documentation](https://developer.zendesk.com/api-reference/ticketing/ticket-management/tags/#remove-tags).",
7
7
  type: "action",
8
- version: "0.0.2",
8
+ version: "0.0.3",
9
9
  props: {
10
10
  app,
11
11
  ticketId: {
@@ -5,7 +5,7 @@ export default {
5
5
  name: "Search Tickets",
6
6
  description: "Searches for tickets using Zendesk's search API. [See the documentation](https://developer.zendesk.com/api-reference/ticketing/ticket-management/search/#search-tickets).",
7
7
  type: "action",
8
- version: "0.0.4",
8
+ version: "0.0.6",
9
9
  props: {
10
10
  app,
11
11
  query: {
@@ -37,6 +37,13 @@ export default {
37
37
  "customSubdomain",
38
38
  ],
39
39
  },
40
+ page: {
41
+ type: "integer",
42
+ label: "Page",
43
+ description: "The page number to retrieve. Default is 1.",
44
+ default: 1,
45
+ optional: true,
46
+ },
40
47
  },
41
48
  async run({ $: step }) {
42
49
  const {
@@ -47,28 +54,20 @@ export default {
47
54
  customSubdomain,
48
55
  } = this;
49
56
 
50
- const results = this.app.paginate({
51
- fn: this.app.searchTickets,
52
- args: {
53
- step,
54
- customSubdomain,
55
- params: {
56
- query,
57
- sort_by: sortBy,
58
- sort_order: sortOrder,
59
- },
57
+ const results = await this.app.searchTickets({
58
+ step,
59
+ customSubdomain,
60
+ params: {
61
+ query,
62
+ sort_by: sortBy,
63
+ sort_order: sortOrder,
64
+ per_page: limit,
65
+ page: this.page,
60
66
  },
61
- resourceKey: "results",
62
- max: limit,
63
67
  });
64
68
 
65
- const tickets = [];
66
- for await (const ticket of results) {
67
- tickets.push(ticket);
68
- }
69
-
70
- step.export("$summary", `Successfully found ${tickets.length} tickets matching the search query`);
69
+ step.export("$summary", "Successfully retrieved tickets matching the search query");
71
70
 
72
- return tickets;
71
+ return results;
73
72
  },
74
73
  };
@@ -5,7 +5,7 @@ export default {
5
5
  name: "Set Ticket Tags",
6
6
  description: "Set tags on a ticket (replaces all existing tags). [See the documentation](https://developer.zendesk.com/api-reference/ticketing/ticket-management/tags/#set-tags).",
7
7
  type: "action",
8
- version: "0.0.2",
8
+ version: "0.0.3",
9
9
  props: {
10
10
  app,
11
11
  ticketId: {
@@ -3,9 +3,9 @@ import app from "../../zendesk.app.mjs";
3
3
  export default {
4
4
  key: "zendesk-update-ticket",
5
5
  name: "Update Ticket",
6
- description: "Updates a ticket and optionally manages tags. [See the documentation](https://developer.zendesk.com/api-reference/ticketing/tickets/tickets/#update-ticket).",
6
+ description: "Updates a ticket. [See the documentation](https://developer.zendesk.com/api-reference/ticketing/tickets/tickets/#update-ticket).",
7
7
  type: "action",
8
- version: "0.1.6",
8
+ version: "0.2.0",
9
9
  props: {
10
10
  app,
11
11
  ticketId: {
@@ -56,6 +56,12 @@ export default {
56
56
  "customSubdomain",
57
57
  ],
58
58
  },
59
+ attachments: {
60
+ propDefinition: [
61
+ app,
62
+ "attachments",
63
+ ],
64
+ },
59
65
  ticketTags: {
60
66
  propDefinition: [
61
67
  app,
@@ -104,6 +110,7 @@ export default {
104
110
  ticketStatus,
105
111
  ticketCommentPublic,
106
112
  customSubdomain,
113
+ attachments,
107
114
  ticketTags,
108
115
  tagAction,
109
116
  } = this;
@@ -118,6 +125,24 @@ export default {
118
125
 
119
126
  ticketComment.public = ticketCommentPublic;
120
127
 
128
+ // Upload attachments if provided
129
+ if (attachments && attachments.length > 0) {
130
+ try {
131
+ const uploadTokens = await this.app.uploadFiles({
132
+ attachments,
133
+ customSubdomain,
134
+ step,
135
+ });
136
+
137
+ if (uploadTokens.length > 0) {
138
+ ticketComment.uploads = uploadTokens;
139
+ }
140
+ } catch (error) {
141
+ step.export("$summary", `Failed to upload attachments: ${error.message}`);
142
+ throw error;
143
+ }
144
+ }
145
+
121
146
  const response = await this.updateTicket({
122
147
  step,
123
148
  ticketId,
@@ -132,6 +157,13 @@ export default {
132
157
  },
133
158
  });
134
159
 
160
+ const attachmentCount = ticketComment.uploads?.length || 0;
161
+ const summary = attachmentCount > 0
162
+ ? `Successfully updated ticket with ID ${response.ticket.id} with ${attachmentCount} attachment(s)`
163
+ : `Successfully updated ticket with ID ${response.ticket.id}`;
164
+
165
+ step.export("$summary", summary);
166
+
135
167
  // Handle tag operations if tags are provided
136
168
  if (ticketTags && ticketTags.length > 0) {
137
169
  let tagResponse;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pipedream/zendesk",
3
- "version": "0.8.0",
3
+ "version": "0.8.2",
4
4
  "description": "Pipedream Zendesk Components",
5
5
  "main": "zendesk.app.mjs",
6
6
  "keywords": [
@@ -14,7 +14,8 @@
14
14
  "access": "public"
15
15
  },
16
16
  "dependencies": {
17
- "@pipedream/platform": "^3.0.3",
18
- "crypto": "^1.0.1"
17
+ "@pipedream/platform": "^3.1.0",
18
+ "crypto": "^1.0.1",
19
+ "path": "^0.12.7"
19
20
  }
20
21
  }
@@ -6,7 +6,7 @@ export default {
6
6
  name: "Locale Updated",
7
7
  type: "source",
8
8
  description: "Emit new event when a locale has been updated",
9
- version: "0.0.1",
9
+ version: "0.0.2",
10
10
  dedupe: "unique",
11
11
  async run() {
12
12
  const lastTs = this._getLastTs();
@@ -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.2.6",
9
+ version: "0.2.7",
10
10
  dedupe: "unique",
11
11
  methods: {
12
12
  ...common.methods,
@@ -7,7 +7,7 @@ export default {
7
7
  key: "zendesk-new-ticket-comment-added",
8
8
  type: "source",
9
9
  description: "Emit new event when a ticket comment has been added",
10
- version: "0.0.1",
10
+ version: "0.0.2",
11
11
  dedupe: "unique",
12
12
  props: {
13
13
  app,
@@ -5,7 +5,7 @@ export default {
5
5
  key: "zendesk-ticket-added-to-view",
6
6
  name: "New Ticket Added to View (Instant)",
7
7
  description: "Emit new event when a ticket is added to the specified view",
8
- version: "0.0.6",
8
+ version: "0.0.7",
9
9
  type: "source",
10
10
  dedupe: "unique",
11
11
  props: {
@@ -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.2.6",
9
+ version: "0.2.7",
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.2.6",
9
+ version: "0.2.7",
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.2.6",
9
+ version: "0.2.7",
10
10
  dedupe: "unique",
11
11
  methods: {
12
12
  ...common.methods,
@@ -6,7 +6,7 @@ export default {
6
6
  key: "zendesk-ticket-updated",
7
7
  type: "source",
8
8
  description: "Emit new event when a ticket has been updated",
9
- version: "0.2.6",
9
+ version: "0.2.7",
10
10
  dedupe: "unique",
11
11
  methods: {
12
12
  ...common.methods,
package/zendesk.app.mjs CHANGED
@@ -1,5 +1,7 @@
1
1
  import { axios } from "@pipedream/platform";
2
2
  import constants from "./common/constants.mjs";
3
+ import { getFileStreamAndMetadata } from "@pipedream/platform";
4
+ import path from "path";
3
5
 
4
6
  export default {
5
7
  type: "app",
@@ -260,6 +262,12 @@ export default {
260
262
  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`",
261
263
  optional: true,
262
264
  },
265
+ attachments: {
266
+ type: "string[]",
267
+ label: "Attachments",
268
+ description: "File paths or URLs to attach to the ticket. Multiple files can be attached.",
269
+ optional: true,
270
+ },
263
271
  ticketTags: {
264
272
  type: "string[]",
265
273
  label: "Tags",
@@ -369,6 +377,94 @@ export default {
369
377
  ...args,
370
378
  });
371
379
  },
380
+ streamToBuffer(stream) {
381
+ return new Promise((resolve, reject) => {
382
+ const chunks = [];
383
+ stream.on("data", (chunk) => chunks.push(chunk));
384
+ stream.on("end", () => resolve(Buffer.concat(chunks)));
385
+ stream.on("error", reject);
386
+ });
387
+ },
388
+ /**
389
+ * Upload a single file (local path or http(s) URL) to Zendesk Uploads API.
390
+ * @param {Object} params
391
+ * @param {string} params.filePath - Local filesystem path or http(s) URL.
392
+ * @param {string} [params.filename] - Optional filename override for the upload.
393
+ * @param {string} [params.customSubdomain]
394
+ * @param {*} [params.step]
395
+ */
396
+ async uploadFile({
397
+ filePath, filename, customSubdomain, step,
398
+ }) {
399
+ if (!filePath || typeof filePath !== "string") {
400
+ throw new Error("uploadFile: 'filePath' (string) is required");
401
+ }
402
+
403
+ const {
404
+ stream, metadata,
405
+ } = await getFileStreamAndMetadata(filePath);
406
+ const fileBinary = await this.streamToBuffer(stream);
407
+
408
+ if (!filename) {
409
+ filename = path.basename(filePath);
410
+ }
411
+
412
+ return this.makeRequest({
413
+ step,
414
+ method: "post",
415
+ path: `/uploads?filename=${encodeURIComponent(filename)}`,
416
+ customSubdomain,
417
+ headers: {
418
+ "Content-Type": metadata.contentType,
419
+ "Content-Length": metadata.size,
420
+ "Accept": "application/json",
421
+ },
422
+ data: Buffer.from(fileBinary, "binary"),
423
+ });
424
+ },
425
+ async uploadFiles({
426
+ attachments, customSubdomain, step,
427
+ } = {}) {
428
+ if (!attachments || !attachments.length) {
429
+ return [];
430
+ }
431
+ const files = attachments
432
+ .map((a) => (typeof a === "string"
433
+ ? a.trim()
434
+ : a))
435
+ .filter(Boolean);
436
+
437
+ const settled = await Promise.allSettled(
438
+ files.map((attachment) =>
439
+ this.uploadFile({
440
+ filePath: attachment,
441
+ customSubdomain,
442
+ step,
443
+ })),
444
+ );
445
+
446
+ const tokens = [];
447
+ const errors = [];
448
+ settled.forEach((res, i) => {
449
+ const attachment = files[i];
450
+ if (res.status === "fulfilled") {
451
+ const token = res.value?.upload?.token;
452
+ if (!token) {
453
+ errors.push(`Upload API returned no token for ${attachment}`);
454
+ } else {
455
+ tokens.push(token);
456
+ }
457
+ } else {
458
+ const reason = res.reason?.message || String(res.reason || "Unknown error");
459
+ errors.push(`${attachment}: ${reason}`);
460
+ }
461
+ });
462
+
463
+ if (errors.length) {
464
+ throw new Error(`Failed to upload ${errors.length}/${files.length} attachment(s): ${errors.join("; ")}`);
465
+ }
466
+ return tokens;
467
+ },
372
468
  listTicketComments({
373
469
  ticketId, ...args
374
470
  } = {}) {