@keystrokehq/zendesk 0.0.1
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 +188 -0
- package/dist/_official/index.d.mts +2 -0
- package/dist/_official/index.mjs +3 -0
- package/dist/_runtime/index.d.mts +1531 -0
- package/dist/_runtime/index.mjs +39 -0
- package/dist/chunk-DQk6qfdC.mjs +18 -0
- package/dist/client.d.mts +41 -0
- package/dist/client.mjs +137 -0
- package/dist/custom/connection.d.mts +2 -0
- package/dist/custom/connection.mjs +3 -0
- package/dist/custom/jobs.d.mts +8 -0
- package/dist/custom/jobs.mjs +8 -0
- package/dist/custom/organizations.d.mts +8 -0
- package/dist/custom/organizations.mjs +17 -0
- package/dist/custom/search.d.mts +8 -0
- package/dist/custom/search.mjs +11 -0
- package/dist/custom/tickets.d.mts +8 -0
- package/dist/custom/tickets.mjs +18 -0
- package/dist/custom/triggers.d.mts +2 -0
- package/dist/custom/triggers.mjs +3 -0
- package/dist/custom/users.d.mts +8 -0
- package/dist/custom/users.mjs +18 -0
- package/dist/custom.d.mts +7 -0
- package/dist/custom.mjs +8 -0
- package/dist/errors-BPAyL8gM.mjs +38 -0
- package/dist/events.d.mts +47 -0
- package/dist/events.mjs +58 -0
- package/dist/factory-BOeuadDj.mjs +9 -0
- package/dist/index.d.mts +1 -0
- package/dist/index.mjs +1 -0
- package/dist/integration-BGHdDCMn.mjs +83 -0
- package/dist/integration-BYDT8ccc.d.mts +98 -0
- package/dist/jobs-9tdPkCE1.d.mts +43 -0
- package/dist/jobs-BjDRvbsd.mjs +36 -0
- package/dist/messaging.d.mts +1 -0
- package/dist/messaging.mjs +1 -0
- package/dist/organizations-BHCFYHgM.mjs +277 -0
- package/dist/organizations-Ct_354Ea.d.mts +355 -0
- package/dist/platform/connection.d.mts +2 -0
- package/dist/platform/connection.mjs +3 -0
- package/dist/platform/jobs.d.mts +8 -0
- package/dist/platform/jobs.mjs +8 -0
- package/dist/platform/organizations.d.mts +8 -0
- package/dist/platform/organizations.mjs +17 -0
- package/dist/platform/search.d.mts +8 -0
- package/dist/platform/search.mjs +11 -0
- package/dist/platform/tickets.d.mts +8 -0
- package/dist/platform/tickets.mjs +18 -0
- package/dist/platform/triggers.d.mts +2 -0
- package/dist/platform/triggers.mjs +3 -0
- package/dist/platform/users.d.mts +8 -0
- package/dist/platform/users.mjs +18 -0
- package/dist/platform.d.mts +7 -0
- package/dist/platform.mjs +8 -0
- package/dist/schemas.d.mts +287 -0
- package/dist/schemas.mjs +101 -0
- package/dist/search-BpPJ9ccR.mjs +85 -0
- package/dist/search-CpISWBay.d.mts +83 -0
- package/dist/shared-BmxcJmfq.mjs +12 -0
- package/dist/tickets-BnTr_JO7.mjs +387 -0
- package/dist/tickets-DWxLBQOd.d.mts +633 -0
- package/dist/triggers-BIrYDGYF.d.mts +37 -0
- package/dist/triggers-ELU-gyey.mjs +107 -0
- package/dist/users-4ecCBdGw.d.mts +423 -0
- package/dist/users-BDj0GBC8.mjs +323 -0
- package/dist/verification.d.mts +9 -0
- package/dist/verification.mjs +41 -0
- package/package.json +172 -0
|
@@ -0,0 +1,323 @@
|
|
|
1
|
+
import { zendeskBulkJobResponseSchema, zendeskUserEnvelopeSchema, zendeskUserListResponseSchema, zendeskUserSchema } from "./schemas.mjs";
|
|
2
|
+
import { n as zendeskPlatformOperation, t as zendeskCustomOperation } from "./factory-BOeuadDj.mjs";
|
|
3
|
+
import { n as createPlatformZendeskClient, t as createCustomZendeskClient } from "./shared-BmxcJmfq.mjs";
|
|
4
|
+
import { z } from "zod";
|
|
5
|
+
|
|
6
|
+
//#region src/users.ts
|
|
7
|
+
const listUsersInputSchema = z.object({
|
|
8
|
+
page: z.number().int().positive().optional(),
|
|
9
|
+
perPage: z.number().int().positive().max(100).optional(),
|
|
10
|
+
role: z.string().optional()
|
|
11
|
+
});
|
|
12
|
+
const getUserInputSchema = z.object({ id: z.number().int().positive() });
|
|
13
|
+
const searchUsersInputSchema = z.object({ query: z.string().min(1) });
|
|
14
|
+
const userCreateInputSchema = z.object({
|
|
15
|
+
name: z.string().min(1),
|
|
16
|
+
email: z.email(),
|
|
17
|
+
organizationId: z.number().int().positive().optional(),
|
|
18
|
+
externalId: z.string().optional(),
|
|
19
|
+
details: z.string().optional(),
|
|
20
|
+
notes: z.string().optional(),
|
|
21
|
+
role: z.string().optional()
|
|
22
|
+
});
|
|
23
|
+
const userUpdateInputSchema = z.object({
|
|
24
|
+
id: z.number().int().positive(),
|
|
25
|
+
name: z.string().min(1).optional(),
|
|
26
|
+
email: z.email().optional(),
|
|
27
|
+
organizationId: z.number().int().positive().optional(),
|
|
28
|
+
externalId: z.string().optional(),
|
|
29
|
+
details: z.string().optional(),
|
|
30
|
+
notes: z.string().optional(),
|
|
31
|
+
role: z.string().optional(),
|
|
32
|
+
verified: z.boolean().optional()
|
|
33
|
+
});
|
|
34
|
+
const createManyUsersInputSchema = z.object({ users: z.array(userCreateInputSchema).min(1).max(100) });
|
|
35
|
+
const updateManyUsersInputSchema = z.object({ users: z.array(userUpdateInputSchema).min(1).max(100) });
|
|
36
|
+
const deleteUserInputSchema = z.object({ id: z.number().int().positive() });
|
|
37
|
+
function mapUserInput(input) {
|
|
38
|
+
return {
|
|
39
|
+
...input.name ? { name: input.name } : {},
|
|
40
|
+
...input.email ? { email: input.email } : {},
|
|
41
|
+
...input.organizationId ? { organization_id: input.organizationId } : {},
|
|
42
|
+
...input.externalId ? { external_id: input.externalId } : {},
|
|
43
|
+
...input.details ? { details: input.details } : {},
|
|
44
|
+
...input.notes ? { notes: input.notes } : {},
|
|
45
|
+
...input.role ? { role: input.role } : {},
|
|
46
|
+
..."verified" in input && input.verified !== void 0 ? { verified: input.verified } : {}
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
const platformListUsers = zendeskPlatformOperation({
|
|
50
|
+
id: "list_users",
|
|
51
|
+
name: "List Zendesk Users",
|
|
52
|
+
description: "List users from Zendesk Support",
|
|
53
|
+
input: listUsersInputSchema,
|
|
54
|
+
output: zendeskUserListResponseSchema,
|
|
55
|
+
run: async (input, credentials) => {
|
|
56
|
+
return createPlatformZendeskClient(credentials).get({
|
|
57
|
+
path: "/users.json",
|
|
58
|
+
query: {
|
|
59
|
+
page: input.page,
|
|
60
|
+
per_page: input.perPage,
|
|
61
|
+
role: input.role
|
|
62
|
+
},
|
|
63
|
+
schema: zendeskUserListResponseSchema
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
const customListUsers = zendeskCustomOperation({
|
|
68
|
+
id: "list_users",
|
|
69
|
+
name: "List Zendesk Users",
|
|
70
|
+
description: "List users from Zendesk Support",
|
|
71
|
+
input: listUsersInputSchema,
|
|
72
|
+
output: zendeskUserListResponseSchema,
|
|
73
|
+
run: async (input, credentials) => {
|
|
74
|
+
return createCustomZendeskClient(credentials).get({
|
|
75
|
+
path: "/users.json",
|
|
76
|
+
query: {
|
|
77
|
+
page: input.page,
|
|
78
|
+
per_page: input.perPage,
|
|
79
|
+
role: input.role
|
|
80
|
+
},
|
|
81
|
+
schema: zendeskUserListResponseSchema
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
const platformGetUser = zendeskPlatformOperation({
|
|
86
|
+
id: "get_user",
|
|
87
|
+
name: "Get Zendesk User",
|
|
88
|
+
description: "Get a single Zendesk user by ID",
|
|
89
|
+
input: getUserInputSchema,
|
|
90
|
+
output: zendeskUserSchema,
|
|
91
|
+
run: async (input, credentials) => {
|
|
92
|
+
return (await createPlatformZendeskClient(credentials).get({
|
|
93
|
+
path: `/users/${input.id}.json`,
|
|
94
|
+
schema: zendeskUserEnvelopeSchema
|
|
95
|
+
})).user;
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
const customGetUser = zendeskCustomOperation({
|
|
99
|
+
id: "get_user",
|
|
100
|
+
name: "Get Zendesk User",
|
|
101
|
+
description: "Get a single Zendesk user by ID",
|
|
102
|
+
input: getUserInputSchema,
|
|
103
|
+
output: zendeskUserSchema,
|
|
104
|
+
run: async (input, credentials) => {
|
|
105
|
+
return (await createCustomZendeskClient(credentials).get({
|
|
106
|
+
path: `/users/${input.id}.json`,
|
|
107
|
+
schema: zendeskUserEnvelopeSchema
|
|
108
|
+
})).user;
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
const platformGetCurrentUser = zendeskPlatformOperation({
|
|
112
|
+
id: "get_current_user",
|
|
113
|
+
name: "Get Current Zendesk User",
|
|
114
|
+
description: "Get the currently authenticated Zendesk user",
|
|
115
|
+
input: z.object({}),
|
|
116
|
+
output: zendeskUserSchema,
|
|
117
|
+
run: async (_input, credentials) => {
|
|
118
|
+
return (await createPlatformZendeskClient(credentials).get({
|
|
119
|
+
path: "/users/me.json",
|
|
120
|
+
schema: zendeskUserEnvelopeSchema
|
|
121
|
+
})).user;
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
const customGetCurrentUser = zendeskCustomOperation({
|
|
125
|
+
id: "get_current_user",
|
|
126
|
+
name: "Get Current Zendesk User",
|
|
127
|
+
description: "Get the currently authenticated Zendesk user",
|
|
128
|
+
input: z.object({}),
|
|
129
|
+
output: zendeskUserSchema,
|
|
130
|
+
run: async (_input, credentials) => {
|
|
131
|
+
return (await createCustomZendeskClient(credentials).get({
|
|
132
|
+
path: "/users/me.json",
|
|
133
|
+
schema: zendeskUserEnvelopeSchema
|
|
134
|
+
})).user;
|
|
135
|
+
}
|
|
136
|
+
});
|
|
137
|
+
const platformSearchUsers = zendeskPlatformOperation({
|
|
138
|
+
id: "search_users",
|
|
139
|
+
name: "Search Zendesk Users",
|
|
140
|
+
description: "Search Zendesk users with a free-text query",
|
|
141
|
+
input: searchUsersInputSchema,
|
|
142
|
+
output: zendeskUserListResponseSchema,
|
|
143
|
+
run: async (input, credentials) => {
|
|
144
|
+
return createPlatformZendeskClient(credentials).get({
|
|
145
|
+
path: "/users/search.json",
|
|
146
|
+
query: { query: input.query },
|
|
147
|
+
schema: zendeskUserListResponseSchema
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
|
+
const customSearchUsers = zendeskCustomOperation({
|
|
152
|
+
id: "search_users",
|
|
153
|
+
name: "Search Zendesk Users",
|
|
154
|
+
description: "Search Zendesk users with a free-text query",
|
|
155
|
+
input: searchUsersInputSchema,
|
|
156
|
+
output: zendeskUserListResponseSchema,
|
|
157
|
+
run: async (input, credentials) => {
|
|
158
|
+
return createCustomZendeskClient(credentials).get({
|
|
159
|
+
path: "/users/search.json",
|
|
160
|
+
query: { query: input.query },
|
|
161
|
+
schema: zendeskUserListResponseSchema
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
});
|
|
165
|
+
const platformCreateUser = zendeskPlatformOperation({
|
|
166
|
+
id: "create_user",
|
|
167
|
+
name: "Create Zendesk User",
|
|
168
|
+
description: "Create a new Zendesk user",
|
|
169
|
+
input: userCreateInputSchema,
|
|
170
|
+
output: zendeskUserSchema,
|
|
171
|
+
needsApproval: true,
|
|
172
|
+
run: async (input, credentials) => {
|
|
173
|
+
return (await createPlatformZendeskClient(credentials).post({
|
|
174
|
+
path: "/users.json",
|
|
175
|
+
body: { user: mapUserInput(input) },
|
|
176
|
+
schema: zendeskUserEnvelopeSchema
|
|
177
|
+
})).user;
|
|
178
|
+
}
|
|
179
|
+
});
|
|
180
|
+
const customCreateUser = zendeskCustomOperation({
|
|
181
|
+
id: "create_user",
|
|
182
|
+
name: "Create Zendesk User",
|
|
183
|
+
description: "Create a new Zendesk user",
|
|
184
|
+
input: userCreateInputSchema,
|
|
185
|
+
output: zendeskUserSchema,
|
|
186
|
+
needsApproval: true,
|
|
187
|
+
run: async (input, credentials) => {
|
|
188
|
+
return (await createCustomZendeskClient(credentials).post({
|
|
189
|
+
path: "/users.json",
|
|
190
|
+
body: { user: mapUserInput(input) },
|
|
191
|
+
schema: zendeskUserEnvelopeSchema
|
|
192
|
+
})).user;
|
|
193
|
+
}
|
|
194
|
+
});
|
|
195
|
+
const platformUpdateUser = zendeskPlatformOperation({
|
|
196
|
+
id: "update_user",
|
|
197
|
+
name: "Update Zendesk User",
|
|
198
|
+
description: "Update an existing Zendesk user",
|
|
199
|
+
input: userUpdateInputSchema,
|
|
200
|
+
output: zendeskUserSchema,
|
|
201
|
+
needsApproval: true,
|
|
202
|
+
run: async (input, credentials) => {
|
|
203
|
+
return (await createPlatformZendeskClient(credentials).put({
|
|
204
|
+
path: `/users/${input.id}.json`,
|
|
205
|
+
body: { user: mapUserInput(input) },
|
|
206
|
+
schema: zendeskUserEnvelopeSchema
|
|
207
|
+
})).user;
|
|
208
|
+
}
|
|
209
|
+
});
|
|
210
|
+
const customUpdateUser = zendeskCustomOperation({
|
|
211
|
+
id: "update_user",
|
|
212
|
+
name: "Update Zendesk User",
|
|
213
|
+
description: "Update an existing Zendesk user",
|
|
214
|
+
input: userUpdateInputSchema,
|
|
215
|
+
output: zendeskUserSchema,
|
|
216
|
+
needsApproval: true,
|
|
217
|
+
run: async (input, credentials) => {
|
|
218
|
+
return (await createCustomZendeskClient(credentials).put({
|
|
219
|
+
path: `/users/${input.id}.json`,
|
|
220
|
+
body: { user: mapUserInput(input) },
|
|
221
|
+
schema: zendeskUserEnvelopeSchema
|
|
222
|
+
})).user;
|
|
223
|
+
}
|
|
224
|
+
});
|
|
225
|
+
const platformDeleteUser = zendeskPlatformOperation({
|
|
226
|
+
id: "delete_user",
|
|
227
|
+
name: "Delete Zendesk User",
|
|
228
|
+
description: "Delete a Zendesk user",
|
|
229
|
+
input: deleteUserInputSchema,
|
|
230
|
+
output: z.object({ success: z.boolean() }),
|
|
231
|
+
needsApproval: true,
|
|
232
|
+
run: async (input, credentials) => {
|
|
233
|
+
await createPlatformZendeskClient(credentials).delete({
|
|
234
|
+
path: `/users/${input.id}.json`,
|
|
235
|
+
schema: z.object({})
|
|
236
|
+
});
|
|
237
|
+
return { success: true };
|
|
238
|
+
}
|
|
239
|
+
});
|
|
240
|
+
const customDeleteUser = zendeskCustomOperation({
|
|
241
|
+
id: "delete_user",
|
|
242
|
+
name: "Delete Zendesk User",
|
|
243
|
+
description: "Delete a Zendesk user",
|
|
244
|
+
input: deleteUserInputSchema,
|
|
245
|
+
output: z.object({ success: z.boolean() }),
|
|
246
|
+
needsApproval: true,
|
|
247
|
+
run: async (input, credentials) => {
|
|
248
|
+
await createCustomZendeskClient(credentials).delete({
|
|
249
|
+
path: `/users/${input.id}.json`,
|
|
250
|
+
schema: z.object({})
|
|
251
|
+
});
|
|
252
|
+
return { success: true };
|
|
253
|
+
}
|
|
254
|
+
});
|
|
255
|
+
const platformCreateManyUsers = zendeskPlatformOperation({
|
|
256
|
+
id: "create_many_users",
|
|
257
|
+
name: "Create Many Zendesk Users",
|
|
258
|
+
description: "Create multiple Zendesk users asynchronously",
|
|
259
|
+
input: createManyUsersInputSchema,
|
|
260
|
+
output: zendeskBulkJobResponseSchema,
|
|
261
|
+
needsApproval: true,
|
|
262
|
+
run: async (input, credentials) => {
|
|
263
|
+
return createPlatformZendeskClient(credentials).post({
|
|
264
|
+
path: "/users/create_many.json",
|
|
265
|
+
body: { users: input.users.map(mapUserInput) },
|
|
266
|
+
schema: zendeskBulkJobResponseSchema
|
|
267
|
+
});
|
|
268
|
+
}
|
|
269
|
+
});
|
|
270
|
+
const customCreateManyUsers = zendeskCustomOperation({
|
|
271
|
+
id: "create_many_users",
|
|
272
|
+
name: "Create Many Zendesk Users",
|
|
273
|
+
description: "Create multiple Zendesk users asynchronously",
|
|
274
|
+
input: createManyUsersInputSchema,
|
|
275
|
+
output: zendeskBulkJobResponseSchema,
|
|
276
|
+
needsApproval: true,
|
|
277
|
+
run: async (input, credentials) => {
|
|
278
|
+
return createCustomZendeskClient(credentials).post({
|
|
279
|
+
path: "/users/create_many.json",
|
|
280
|
+
body: { users: input.users.map(mapUserInput) },
|
|
281
|
+
schema: zendeskBulkJobResponseSchema
|
|
282
|
+
});
|
|
283
|
+
}
|
|
284
|
+
});
|
|
285
|
+
const platformUpdateManyUsers = zendeskPlatformOperation({
|
|
286
|
+
id: "update_many_users",
|
|
287
|
+
name: "Update Many Zendesk Users",
|
|
288
|
+
description: "Update multiple Zendesk users asynchronously",
|
|
289
|
+
input: updateManyUsersInputSchema,
|
|
290
|
+
output: zendeskBulkJobResponseSchema,
|
|
291
|
+
needsApproval: true,
|
|
292
|
+
run: async (input, credentials) => {
|
|
293
|
+
return createPlatformZendeskClient(credentials).put({
|
|
294
|
+
path: "/users/update_many.json",
|
|
295
|
+
body: { users: input.users.map((user) => ({
|
|
296
|
+
id: user.id,
|
|
297
|
+
...mapUserInput(user)
|
|
298
|
+
})) },
|
|
299
|
+
schema: zendeskBulkJobResponseSchema
|
|
300
|
+
});
|
|
301
|
+
}
|
|
302
|
+
});
|
|
303
|
+
const customUpdateManyUsers = zendeskCustomOperation({
|
|
304
|
+
id: "update_many_users",
|
|
305
|
+
name: "Update Many Zendesk Users",
|
|
306
|
+
description: "Update multiple Zendesk users asynchronously",
|
|
307
|
+
input: updateManyUsersInputSchema,
|
|
308
|
+
output: zendeskBulkJobResponseSchema,
|
|
309
|
+
needsApproval: true,
|
|
310
|
+
run: async (input, credentials) => {
|
|
311
|
+
return createCustomZendeskClient(credentials).put({
|
|
312
|
+
path: "/users/update_many.json",
|
|
313
|
+
body: { users: input.users.map((user) => ({
|
|
314
|
+
id: user.id,
|
|
315
|
+
...mapUserInput(user)
|
|
316
|
+
})) },
|
|
317
|
+
schema: zendeskBulkJobResponseSchema
|
|
318
|
+
});
|
|
319
|
+
}
|
|
320
|
+
});
|
|
321
|
+
|
|
322
|
+
//#endregion
|
|
323
|
+
export { platformUpdateManyUsers as _, customGetUser as a, customUpdateManyUsers as c, platformCreateUser as d, platformDeleteUser as f, platformSearchUsers as g, platformListUsers as h, customGetCurrentUser as i, customUpdateUser as l, platformGetUser as m, customCreateUser as n, customListUsers as o, platformGetCurrentUser as p, customDeleteUser as r, customSearchUsers as s, customCreateManyUsers as t, platformCreateManyUsers as u, platformUpdateUser as v };
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { WebhookRequest } from "@keystrokehq/core";
|
|
2
|
+
|
|
3
|
+
//#region src/verification.d.ts
|
|
4
|
+
declare const DEFAULT_TIMESTAMP_TOLERANCE_SECONDS = 300;
|
|
5
|
+
declare function extractZendeskWebhookInvocationId(request: WebhookRequest): string | undefined;
|
|
6
|
+
declare function calculateZendeskWebhookSignature(request: Pick<WebhookRequest, 'headers' | 'rawBody'>, secret: string): string;
|
|
7
|
+
declare function verifyZendeskWebhookSignature(request: WebhookRequest, secret: string, maxAgeSeconds?: number): void;
|
|
8
|
+
//#endregion
|
|
9
|
+
export { DEFAULT_TIMESTAMP_TOLERANCE_SECONDS, calculateZendeskWebhookSignature, extractZendeskWebhookInvocationId, verifyZendeskWebhookSignature };
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import crypto from "node:crypto";
|
|
2
|
+
|
|
3
|
+
//#region src/verification.ts
|
|
4
|
+
const DEFAULT_TIMESTAMP_TOLERANCE_SECONDS = 300;
|
|
5
|
+
function parseZendeskWebhookTimestampMs(timestamp) {
|
|
6
|
+
const iso = Date.parse(timestamp);
|
|
7
|
+
if (Number.isFinite(iso)) return iso;
|
|
8
|
+
const numeric = Number(timestamp);
|
|
9
|
+
if (!Number.isFinite(numeric)) return;
|
|
10
|
+
return numeric < 0xe8d4a51000 ? numeric * 1e3 : numeric;
|
|
11
|
+
}
|
|
12
|
+
function getHeader(headers, name) {
|
|
13
|
+
const lowerName = name.toLowerCase();
|
|
14
|
+
for (const [headerName, value] of Object.entries(headers)) if (headerName.toLowerCase() === lowerName && value) return value;
|
|
15
|
+
}
|
|
16
|
+
function extractZendeskWebhookInvocationId(request) {
|
|
17
|
+
return getHeader(request.headers, "x-zendesk-webhook-invocation-id");
|
|
18
|
+
}
|
|
19
|
+
function calculateZendeskWebhookSignature(request, secret) {
|
|
20
|
+
const timestamp = getHeader(request.headers, "x-zendesk-webhook-signature-timestamp");
|
|
21
|
+
if (!timestamp) throw new Error("Zendesk webhook signature timestamp header is missing.");
|
|
22
|
+
return crypto.createHmac("sha256", secret).update(`${timestamp}${request.rawBody}`).digest("base64");
|
|
23
|
+
}
|
|
24
|
+
function verifyZendeskWebhookSignature(request, secret, maxAgeSeconds = DEFAULT_TIMESTAMP_TOLERANCE_SECONDS) {
|
|
25
|
+
const signature = getHeader(request.headers, "x-zendesk-webhook-signature");
|
|
26
|
+
const timestamp = getHeader(request.headers, "x-zendesk-webhook-signature-timestamp");
|
|
27
|
+
if (!signature) throw new Error("Zendesk webhook signature header is missing.");
|
|
28
|
+
if (!timestamp) throw new Error("Zendesk webhook signature timestamp header is missing.");
|
|
29
|
+
const timestampMs = parseZendeskWebhookTimestampMs(timestamp);
|
|
30
|
+
if (timestampMs !== void 0) {
|
|
31
|
+
if (Math.abs(Date.now() - timestampMs) > maxAgeSeconds * 1e3) throw new Error("Zendesk webhook timestamp is outside the accepted tolerance window.");
|
|
32
|
+
}
|
|
33
|
+
const expectedSignature = calculateZendeskWebhookSignature(request, secret);
|
|
34
|
+
const actualBuffer = Buffer.from(signature);
|
|
35
|
+
const expectedBuffer = Buffer.from(expectedSignature);
|
|
36
|
+
if (actualBuffer.length !== expectedBuffer.length) throw new Error("Zendesk webhook signature is invalid.");
|
|
37
|
+
if (!crypto.timingSafeEqual(actualBuffer, expectedBuffer)) throw new Error("Zendesk webhook signature is invalid.");
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
//#endregion
|
|
41
|
+
export { DEFAULT_TIMESTAMP_TOLERANCE_SECONDS, calculateZendeskWebhookSignature, extractZendeskWebhookInvocationId, verifyZendeskWebhookSignature };
|
package/package.json
ADDED
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@keystrokehq/zendesk",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"private": false,
|
|
5
|
+
"sideEffects": false,
|
|
6
|
+
"type": "module",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"import": "./dist/index.mjs",
|
|
10
|
+
"default": "./dist/index.mjs",
|
|
11
|
+
"types": "./dist/index.d.mts"
|
|
12
|
+
},
|
|
13
|
+
"./client": {
|
|
14
|
+
"import": "./dist/client.mjs",
|
|
15
|
+
"default": "./dist/client.mjs",
|
|
16
|
+
"types": "./dist/client.d.mts"
|
|
17
|
+
},
|
|
18
|
+
"./schemas": {
|
|
19
|
+
"import": "./dist/schemas.mjs",
|
|
20
|
+
"default": "./dist/schemas.mjs",
|
|
21
|
+
"types": "./dist/schemas.d.mts"
|
|
22
|
+
},
|
|
23
|
+
"./_official": {
|
|
24
|
+
"import": "./dist/_official/index.mjs",
|
|
25
|
+
"default": "./dist/_official/index.mjs",
|
|
26
|
+
"types": "./dist/_official/index.d.mts"
|
|
27
|
+
},
|
|
28
|
+
"./events": {
|
|
29
|
+
"import": "./dist/events.mjs",
|
|
30
|
+
"default": "./dist/events.mjs",
|
|
31
|
+
"types": "./dist/events.d.mts"
|
|
32
|
+
},
|
|
33
|
+
"./messaging": {
|
|
34
|
+
"import": "./dist/messaging.mjs",
|
|
35
|
+
"default": "./dist/messaging.mjs",
|
|
36
|
+
"types": "./dist/messaging.d.mts"
|
|
37
|
+
},
|
|
38
|
+
"./verification": {
|
|
39
|
+
"import": "./dist/verification.mjs",
|
|
40
|
+
"default": "./dist/verification.mjs",
|
|
41
|
+
"types": "./dist/verification.d.mts"
|
|
42
|
+
},
|
|
43
|
+
"./platform": {
|
|
44
|
+
"import": "./dist/platform.mjs",
|
|
45
|
+
"default": "./dist/platform.mjs",
|
|
46
|
+
"types": "./dist/platform.d.mts"
|
|
47
|
+
},
|
|
48
|
+
"./platform/connection": {
|
|
49
|
+
"import": "./dist/platform/connection.mjs",
|
|
50
|
+
"default": "./dist/platform/connection.mjs",
|
|
51
|
+
"types": "./dist/platform/connection.d.mts"
|
|
52
|
+
},
|
|
53
|
+
"./platform/tickets": {
|
|
54
|
+
"import": "./dist/platform/tickets.mjs",
|
|
55
|
+
"default": "./dist/platform/tickets.mjs",
|
|
56
|
+
"types": "./dist/platform/tickets.d.mts"
|
|
57
|
+
},
|
|
58
|
+
"./platform/users": {
|
|
59
|
+
"import": "./dist/platform/users.mjs",
|
|
60
|
+
"default": "./dist/platform/users.mjs",
|
|
61
|
+
"types": "./dist/platform/users.d.mts"
|
|
62
|
+
},
|
|
63
|
+
"./platform/organizations": {
|
|
64
|
+
"import": "./dist/platform/organizations.mjs",
|
|
65
|
+
"default": "./dist/platform/organizations.mjs",
|
|
66
|
+
"types": "./dist/platform/organizations.d.mts"
|
|
67
|
+
},
|
|
68
|
+
"./platform/search": {
|
|
69
|
+
"import": "./dist/platform/search.mjs",
|
|
70
|
+
"default": "./dist/platform/search.mjs",
|
|
71
|
+
"types": "./dist/platform/search.d.mts"
|
|
72
|
+
},
|
|
73
|
+
"./platform/jobs": {
|
|
74
|
+
"import": "./dist/platform/jobs.mjs",
|
|
75
|
+
"default": "./dist/platform/jobs.mjs",
|
|
76
|
+
"types": "./dist/platform/jobs.d.mts"
|
|
77
|
+
},
|
|
78
|
+
"./platform/triggers": {
|
|
79
|
+
"import": "./dist/platform/triggers.mjs",
|
|
80
|
+
"default": "./dist/platform/triggers.mjs",
|
|
81
|
+
"types": "./dist/platform/triggers.d.mts"
|
|
82
|
+
},
|
|
83
|
+
"./custom": {
|
|
84
|
+
"import": "./dist/custom.mjs",
|
|
85
|
+
"default": "./dist/custom.mjs",
|
|
86
|
+
"types": "./dist/custom.d.mts"
|
|
87
|
+
},
|
|
88
|
+
"./custom/connection": {
|
|
89
|
+
"import": "./dist/custom/connection.mjs",
|
|
90
|
+
"default": "./dist/custom/connection.mjs",
|
|
91
|
+
"types": "./dist/custom/connection.d.mts"
|
|
92
|
+
},
|
|
93
|
+
"./custom/tickets": {
|
|
94
|
+
"import": "./dist/custom/tickets.mjs",
|
|
95
|
+
"default": "./dist/custom/tickets.mjs",
|
|
96
|
+
"types": "./dist/custom/tickets.d.mts"
|
|
97
|
+
},
|
|
98
|
+
"./custom/users": {
|
|
99
|
+
"import": "./dist/custom/users.mjs",
|
|
100
|
+
"default": "./dist/custom/users.mjs",
|
|
101
|
+
"types": "./dist/custom/users.d.mts"
|
|
102
|
+
},
|
|
103
|
+
"./custom/organizations": {
|
|
104
|
+
"import": "./dist/custom/organizations.mjs",
|
|
105
|
+
"default": "./dist/custom/organizations.mjs",
|
|
106
|
+
"types": "./dist/custom/organizations.d.mts"
|
|
107
|
+
},
|
|
108
|
+
"./custom/search": {
|
|
109
|
+
"import": "./dist/custom/search.mjs",
|
|
110
|
+
"default": "./dist/custom/search.mjs",
|
|
111
|
+
"types": "./dist/custom/search.d.mts"
|
|
112
|
+
},
|
|
113
|
+
"./custom/jobs": {
|
|
114
|
+
"import": "./dist/custom/jobs.mjs",
|
|
115
|
+
"default": "./dist/custom/jobs.mjs",
|
|
116
|
+
"types": "./dist/custom/jobs.d.mts"
|
|
117
|
+
},
|
|
118
|
+
"./custom/triggers": {
|
|
119
|
+
"import": "./dist/custom/triggers.mjs",
|
|
120
|
+
"default": "./dist/custom/triggers.mjs",
|
|
121
|
+
"types": "./dist/custom/triggers.d.mts"
|
|
122
|
+
},
|
|
123
|
+
"./_runtime": {
|
|
124
|
+
"import": "./dist/_runtime/index.mjs",
|
|
125
|
+
"default": "./dist/_runtime/index.mjs",
|
|
126
|
+
"types": "./dist/_runtime/index.d.mts"
|
|
127
|
+
}
|
|
128
|
+
},
|
|
129
|
+
"files": [
|
|
130
|
+
"dist",
|
|
131
|
+
"README.md",
|
|
132
|
+
"LICENSE"
|
|
133
|
+
],
|
|
134
|
+
"scripts": {
|
|
135
|
+
"typecheck": "tsgo --build",
|
|
136
|
+
"build": "tsdown",
|
|
137
|
+
"lint": "biome check .",
|
|
138
|
+
"test:unit": "vitest run --passWithNoTests --project unit",
|
|
139
|
+
"test:int": "vitest run --passWithNoTests --project int",
|
|
140
|
+
"prepublishOnly": "pnpm build && pnpm test:unit",
|
|
141
|
+
"lint:fix": "biome check --write ."
|
|
142
|
+
},
|
|
143
|
+
"dependencies": {
|
|
144
|
+
"@keystrokehq/integration-authoring": "^0.0.1",
|
|
145
|
+
"@keystrokehq/core": "^0.0.5",
|
|
146
|
+
"zod": "^4.3.6"
|
|
147
|
+
},
|
|
148
|
+
"devDependencies": {
|
|
149
|
+
"@types/node": "catalog:",
|
|
150
|
+
"@keystrokehq/test-utils": "workspace:*",
|
|
151
|
+
"@keystrokehq/typescript-config": "workspace:*",
|
|
152
|
+
"tsdown": "catalog:",
|
|
153
|
+
"typescript": "catalog:",
|
|
154
|
+
"vitest": "catalog:"
|
|
155
|
+
},
|
|
156
|
+
"keywords": [
|
|
157
|
+
"zendesk",
|
|
158
|
+
"keystroke",
|
|
159
|
+
"integration",
|
|
160
|
+
"support"
|
|
161
|
+
],
|
|
162
|
+
"repository": {
|
|
163
|
+
"type": "git",
|
|
164
|
+
"url": "https://github.com/keystrokehq/integrations",
|
|
165
|
+
"directory": "integrations/zendesk"
|
|
166
|
+
},
|
|
167
|
+
"license": "MIT",
|
|
168
|
+
"publishConfig": {
|
|
169
|
+
"access": "public",
|
|
170
|
+
"registry": "https://registry.npmjs.org/"
|
|
171
|
+
}
|
|
172
|
+
}
|