@shuffl/api-contracts 0.4.0 → 0.5.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/dist/base.d.ts +5 -3
- package/dist/base.js +8 -4
- package/dist/index.d.ts +8919 -4904
- package/dist/index.js +22 -3
- package/dist/management-operations.d.ts +1 -1
- package/dist/management-operations.js +500 -82
- package/dist/management.generated.d.ts +5947 -2124
- package/dist/management.generated.js +4618 -762
- package/dist/permissions.d.ts +181 -59
- package/dist/permissions.js +23 -18
- package/dist/schemas.d.ts +7 -0
- package/dist/schemas.js +20 -3
- package/dist/webhooks.d.ts +373 -0
- package/dist/webhooks.js +429 -0
- package/openapi.json +98520 -55741
- package/package.json +9 -1
package/dist/schemas.js
CHANGED
|
@@ -156,7 +156,8 @@ export const matchSchema = z
|
|
|
156
156
|
maxGroupSize: z.number().int().min(2).max(8),
|
|
157
157
|
strategy: strategySchema,
|
|
158
158
|
unitIds: z.array(z.string().trim().min(1).max(200)).max(20).optional(),
|
|
159
|
-
|
|
159
|
+
// #745: communities mix like teams people choose themselves.
|
|
160
|
+
unitKind: z.enum(['department', 'team', 'community']).optional(),
|
|
160
161
|
})
|
|
161
162
|
.refine((x) => !currentStrategies.includes(x.strategy) || x.iterations <= 50, 'Purpose matching supports at most 50 search attempts')
|
|
162
163
|
.refine((x) => x.maxGroupSize >= x.groupSize, 'Maximum group size must be at least the target size')
|
|
@@ -168,7 +169,7 @@ export const matchSchema = z
|
|
|
168
169
|
.refine((x) => !x.unitIds || new Set(x.unitIds).size === x.unitIds.length, 'Choose each team or department only once')
|
|
169
170
|
.refine((x) => x.strategy === 'cross-unit' || x.strategy === 'within-unit'
|
|
170
171
|
? !!x.unitKind
|
|
171
|
-
: x.unitKind === undefined, 'Choose teams or
|
|
172
|
+
: x.unitKind === undefined, 'Choose teams, departments or communities only when mixing across or within them')
|
|
172
173
|
.refine((x) => !currentStrategies.includes(x.strategy) ||
|
|
173
174
|
x.maxGroupSize <= x.groupSize + 1, 'Allow at most one extra person per group')
|
|
174
175
|
.refine((x) => !x.keepApart || currentStrategies.includes(x.strategy), 'Keeping coworkers apart needs a current matching purpose')
|
|
@@ -176,6 +177,17 @@ export const matchSchema = z
|
|
|
176
177
|
export const programInput = z.object({
|
|
177
178
|
channelId: z.string().regex(/^[CG][A-Z0-9]+$/),
|
|
178
179
|
channelName: z.string().trim().min(1).max(100),
|
|
180
|
+
// #745: one to 20 communities whose members take part instead, by those
|
|
181
|
+
// who show the community on their profile. Empty or omitted means the
|
|
182
|
+
// channel or the group; a program uses one of the three.
|
|
183
|
+
communityIds: z
|
|
184
|
+
.array(z.string().trim().min(1).max(128))
|
|
185
|
+
.max(20)
|
|
186
|
+
.optional()
|
|
187
|
+
.describe('Communities whose members take part, instead of the Slack channel or a group. Only people who show the community on their profile are enrolled.'),
|
|
188
|
+
// #1832: the group whose members take part; null or omitted means everyone
|
|
189
|
+
// in the Slack channel. Introductions are posted in the channel either way.
|
|
190
|
+
groupId: z.string().trim().min(1).max(128).nullish(),
|
|
179
191
|
includeBios: z.boolean(),
|
|
180
192
|
// Omission preserves an existing program's choice; new programs default on.
|
|
181
193
|
includeSchedulingLink: z.boolean().optional(),
|
|
@@ -201,6 +213,8 @@ export const profileSchema = z.object({
|
|
|
201
213
|
export const programPatch = z.strictObject({
|
|
202
214
|
channelId: programInput.shape.channelId.optional(),
|
|
203
215
|
channelName: programInput.shape.channelName.optional(),
|
|
216
|
+
communityIds: z.array(z.string().trim().min(1).max(128)).max(20).optional(),
|
|
217
|
+
groupId: z.string().trim().min(1).max(128).nullable().optional(),
|
|
204
218
|
includeBios: z.boolean().optional(),
|
|
205
219
|
includeSchedulingLink: z.boolean().optional(),
|
|
206
220
|
intro: programInput.shape.intro.optional(),
|
|
@@ -218,7 +232,10 @@ export const programPatch = z.strictObject({
|
|
|
218
232
|
maxGroupSize: z.number().int().min(2).max(8).optional(),
|
|
219
233
|
strategy: strategySchema.optional(),
|
|
220
234
|
unitIds: z.array(z.string().trim().min(1).max(200)).max(20).optional(),
|
|
221
|
-
unitKind: z
|
|
235
|
+
unitKind: z
|
|
236
|
+
.enum(['department', 'team', 'community'])
|
|
237
|
+
.nullable()
|
|
238
|
+
.optional(),
|
|
222
239
|
})
|
|
223
240
|
.optional(),
|
|
224
241
|
name: programInput.shape.name.optional(),
|
|
@@ -0,0 +1,373 @@
|
|
|
1
|
+
export declare const webhookApiVersion = "2026-10-17";
|
|
2
|
+
export declare const webhookEventGroups: {
|
|
3
|
+
readonly connections: {
|
|
4
|
+
readonly description: 'Connections programs, rounds and who takes part';
|
|
5
|
+
readonly label: 'Connections';
|
|
6
|
+
readonly scope: 'programs:read';
|
|
7
|
+
};
|
|
8
|
+
readonly hr: {
|
|
9
|
+
readonly description: 'Who answers HR requests';
|
|
10
|
+
readonly label: 'HR team';
|
|
11
|
+
readonly scope: 'hr:read';
|
|
12
|
+
};
|
|
13
|
+
readonly knowledge: {
|
|
14
|
+
readonly description: 'Proposals, drafts, published pages and connected sources';
|
|
15
|
+
readonly label: 'Knowledge';
|
|
16
|
+
readonly scope: 'knowledge:read';
|
|
17
|
+
};
|
|
18
|
+
readonly people: {
|
|
19
|
+
readonly description: 'People, roles, access, identities and departments';
|
|
20
|
+
readonly label: 'People';
|
|
21
|
+
readonly scope: 'users:read';
|
|
22
|
+
};
|
|
23
|
+
readonly playbook: {
|
|
24
|
+
readonly description: 'Playbook enrollments, steps, buddies and check-ins';
|
|
25
|
+
readonly label: 'Playbooks';
|
|
26
|
+
readonly scope: 'playbooks:read';
|
|
27
|
+
};
|
|
28
|
+
readonly webhooks: {
|
|
29
|
+
readonly description: 'Test events and endpoints Shuffl turned off';
|
|
30
|
+
readonly label: 'Webhooks';
|
|
31
|
+
readonly scope: 'webhooks:read';
|
|
32
|
+
};
|
|
33
|
+
readonly workspace: {
|
|
34
|
+
readonly description: 'The workspace itself and its Slack connection';
|
|
35
|
+
readonly label: 'Workspace';
|
|
36
|
+
readonly scope: 'team:read';
|
|
37
|
+
};
|
|
38
|
+
};
|
|
39
|
+
export type WebhookEventGroup = keyof typeof webhookEventGroups;
|
|
40
|
+
export declare const webhookEventGroupIds: WebhookEventGroup[];
|
|
41
|
+
export declare const webhookEventCatalog: {
|
|
42
|
+
readonly 'hr.responder.granted': {
|
|
43
|
+
readonly description: 'Someone joined the HR team that answers requests';
|
|
44
|
+
readonly fields: readonly ["person_id", "revision"];
|
|
45
|
+
readonly group: 'hr';
|
|
46
|
+
};
|
|
47
|
+
readonly 'hr.responder.revoked': {
|
|
48
|
+
readonly description: 'Someone left the HR team';
|
|
49
|
+
readonly fields: readonly ["person_id", "revision"];
|
|
50
|
+
readonly group: 'hr';
|
|
51
|
+
};
|
|
52
|
+
readonly 'hr.team.renamed': {
|
|
53
|
+
readonly description: 'The HR team’s name changed';
|
|
54
|
+
readonly fields: readonly ["revision"];
|
|
55
|
+
readonly group: 'hr';
|
|
56
|
+
};
|
|
57
|
+
readonly 'knowledge.document.archived': {
|
|
58
|
+
readonly description: 'A page was archived';
|
|
59
|
+
readonly fields: readonly ["document_id"];
|
|
60
|
+
readonly group: 'knowledge';
|
|
61
|
+
};
|
|
62
|
+
readonly 'knowledge.document.audience_changed': {
|
|
63
|
+
readonly description: 'Who can read a published page changed';
|
|
64
|
+
readonly fields: readonly ["document_id", "version_id", "audience", "previous_audience"];
|
|
65
|
+
readonly group: 'knowledge';
|
|
66
|
+
};
|
|
67
|
+
readonly 'knowledge.document.published': {
|
|
68
|
+
readonly description: 'A page was published';
|
|
69
|
+
readonly fields: readonly ["document_id", "version_id", "audience"];
|
|
70
|
+
readonly group: 'knowledge';
|
|
71
|
+
};
|
|
72
|
+
readonly 'knowledge.document.restored': {
|
|
73
|
+
readonly description: 'An archived page was restored';
|
|
74
|
+
readonly fields: readonly ["document_id"];
|
|
75
|
+
readonly group: 'knowledge';
|
|
76
|
+
};
|
|
77
|
+
readonly 'knowledge.document.withdrawn': {
|
|
78
|
+
readonly description: 'A published page was withdrawn';
|
|
79
|
+
readonly fields: readonly ["document_id"];
|
|
80
|
+
readonly group: 'knowledge';
|
|
81
|
+
};
|
|
82
|
+
readonly 'knowledge.draft.saved': {
|
|
83
|
+
readonly description: 'A draft of a page was saved';
|
|
84
|
+
readonly fields: readonly ["document_id", "version_id"];
|
|
85
|
+
readonly group: 'knowledge';
|
|
86
|
+
};
|
|
87
|
+
readonly 'knowledge.proposal.created': {
|
|
88
|
+
readonly description: 'Mello proposed new or changed Knowledge for review';
|
|
89
|
+
readonly fields: readonly ["proposal_id", "revision"];
|
|
90
|
+
readonly group: 'knowledge';
|
|
91
|
+
};
|
|
92
|
+
readonly 'knowledge.proposal.published': {
|
|
93
|
+
readonly description: 'A verifier approved a proposal, as written or edited';
|
|
94
|
+
readonly fields: readonly ["proposal_id", "revision", "document_id", "edited"];
|
|
95
|
+
readonly group: 'knowledge';
|
|
96
|
+
};
|
|
97
|
+
readonly 'knowledge.proposal.rejected': {
|
|
98
|
+
readonly description: 'A verifier turned a proposal down';
|
|
99
|
+
readonly fields: readonly ["proposal_id", "revision"];
|
|
100
|
+
readonly group: 'knowledge';
|
|
101
|
+
};
|
|
102
|
+
readonly 'knowledge.section.removed': {
|
|
103
|
+
readonly description: 'A section was removed from a handbook page';
|
|
104
|
+
readonly fields: readonly ["document_id"];
|
|
105
|
+
readonly group: 'knowledge';
|
|
106
|
+
};
|
|
107
|
+
readonly 'knowledge.source.access_lost': {
|
|
108
|
+
readonly description: 'Shuffl can no longer read a connected document';
|
|
109
|
+
readonly fields: readonly ["document_id"];
|
|
110
|
+
readonly group: 'knowledge';
|
|
111
|
+
};
|
|
112
|
+
readonly 'knowledge.source.connected': {
|
|
113
|
+
readonly description: 'A Knowledge source such as Google Drive was connected';
|
|
114
|
+
readonly fields: readonly ["connection_id"];
|
|
115
|
+
readonly group: 'knowledge';
|
|
116
|
+
};
|
|
117
|
+
readonly 'knowledge.source.disconnected': {
|
|
118
|
+
readonly description: 'A Knowledge source was disconnected';
|
|
119
|
+
readonly fields: readonly ["connection_id"];
|
|
120
|
+
readonly group: 'knowledge';
|
|
121
|
+
};
|
|
122
|
+
readonly 'knowledge.verifier.granted': {
|
|
123
|
+
readonly description: 'Someone can now verify Knowledge';
|
|
124
|
+
readonly fields: readonly ["person_id", "revision"];
|
|
125
|
+
readonly group: 'knowledge';
|
|
126
|
+
};
|
|
127
|
+
readonly 'knowledge.verifier.revoked': {
|
|
128
|
+
readonly description: 'Someone can no longer verify Knowledge';
|
|
129
|
+
readonly fields: readonly ["person_id", "revision"];
|
|
130
|
+
readonly group: 'knowledge';
|
|
131
|
+
};
|
|
132
|
+
readonly 'participant.opted_in': {
|
|
133
|
+
readonly description: 'A person joined a Connections program';
|
|
134
|
+
readonly fields: readonly ["person_id", "program_id", "revision"];
|
|
135
|
+
readonly group: 'connections';
|
|
136
|
+
};
|
|
137
|
+
readonly 'participant.opted_out': {
|
|
138
|
+
readonly description: 'A person left a Connections program';
|
|
139
|
+
readonly fields: readonly ["person_id", "program_id", "revision"];
|
|
140
|
+
readonly group: 'connections';
|
|
141
|
+
};
|
|
142
|
+
readonly 'participant.profile_updated': {
|
|
143
|
+
readonly description: 'A person updated their profile';
|
|
144
|
+
readonly fields: readonly ["person_id"];
|
|
145
|
+
readonly group: 'connections';
|
|
146
|
+
};
|
|
147
|
+
readonly 'person.access_changed': {
|
|
148
|
+
readonly description: 'A person’s app access or employment changed';
|
|
149
|
+
readonly fields: readonly ["person_id", "status", "previous_status", "employment", "previous_employment", "revision"];
|
|
150
|
+
readonly group: 'people';
|
|
151
|
+
};
|
|
152
|
+
readonly 'person.access_suspended': {
|
|
153
|
+
readonly description: 'A person’s access was suspended';
|
|
154
|
+
readonly fields: readonly ["person_id"];
|
|
155
|
+
readonly group: 'people';
|
|
156
|
+
};
|
|
157
|
+
readonly 'person.created': {
|
|
158
|
+
readonly description: 'A person was added to the directory';
|
|
159
|
+
readonly fields: readonly ["person_id", "revision"];
|
|
160
|
+
readonly group: 'people';
|
|
161
|
+
};
|
|
162
|
+
readonly 'person.identity_linked': {
|
|
163
|
+
readonly description: 'A Slack or single sign-on identity was linked to a person';
|
|
164
|
+
readonly fields: readonly ["person_id", "identity_id", "provider"];
|
|
165
|
+
readonly group: 'people';
|
|
166
|
+
};
|
|
167
|
+
readonly 'person.identity_revoked': {
|
|
168
|
+
readonly description: 'A linked identity was removed from a person';
|
|
169
|
+
readonly fields: readonly ["person_id", "identity_id", "provider"];
|
|
170
|
+
readonly group: 'people';
|
|
171
|
+
};
|
|
172
|
+
readonly 'person.manager_changed': {
|
|
173
|
+
readonly description: 'A person’s manager changed';
|
|
174
|
+
readonly fields: readonly ["person_id"];
|
|
175
|
+
readonly group: 'people';
|
|
176
|
+
};
|
|
177
|
+
readonly 'person.role_changed': {
|
|
178
|
+
readonly description: 'A person’s workspace role changed';
|
|
179
|
+
readonly fields: readonly ["person_id", "role", "previous_role"];
|
|
180
|
+
readonly group: 'people';
|
|
181
|
+
};
|
|
182
|
+
readonly 'person.updated': {
|
|
183
|
+
readonly description: 'A person’s directory record changed';
|
|
184
|
+
readonly fields: readonly ["person_id", "revision"];
|
|
185
|
+
readonly group: 'people';
|
|
186
|
+
};
|
|
187
|
+
readonly 'playbooks.approved': {
|
|
188
|
+
readonly description: 'HR approved a person’s playbook steps';
|
|
189
|
+
readonly fields: readonly ["enrollment_id"];
|
|
190
|
+
readonly group: 'playbook';
|
|
191
|
+
};
|
|
192
|
+
readonly 'playbooks.buddy.accepted': {
|
|
193
|
+
readonly description: 'A buddy said yes';
|
|
194
|
+
readonly fields: readonly ["enrollment_id"];
|
|
195
|
+
readonly group: 'playbook';
|
|
196
|
+
};
|
|
197
|
+
readonly 'playbooks.buddy.assigned': {
|
|
198
|
+
readonly description: 'A buddy was asked to help a new hire';
|
|
199
|
+
readonly fields: readonly ["enrollment_id", "buddy_person_id"];
|
|
200
|
+
readonly group: 'playbook';
|
|
201
|
+
};
|
|
202
|
+
readonly 'playbooks.buddy.declined': {
|
|
203
|
+
readonly description: 'A buddy said no';
|
|
204
|
+
readonly fields: readonly ["enrollment_id"];
|
|
205
|
+
readonly group: 'playbook';
|
|
206
|
+
};
|
|
207
|
+
readonly 'playbooks.check_in.answered': {
|
|
208
|
+
readonly description: 'A new hire answered a check-in: all_good, or need_help when they asked HR for help';
|
|
209
|
+
readonly fields: readonly ["step_id", "enrollment_id", "answer"];
|
|
210
|
+
readonly group: 'playbook';
|
|
211
|
+
};
|
|
212
|
+
readonly 'playbooks.enrolled': {
|
|
213
|
+
readonly description: 'A person started a playbook';
|
|
214
|
+
readonly fields: readonly ["enrollment_id", "person_id", "program_id", "with_buddy"];
|
|
215
|
+
readonly group: 'playbook';
|
|
216
|
+
};
|
|
217
|
+
readonly 'playbooks.enrollment_removed': {
|
|
218
|
+
readonly description: 'A person was taken off a playbook';
|
|
219
|
+
readonly fields: readonly ["enrollment_id", "reason"];
|
|
220
|
+
readonly group: 'playbook';
|
|
221
|
+
};
|
|
222
|
+
readonly 'playbooks.schedule_changed': {
|
|
223
|
+
readonly description: 'A person’s playbook schedule changed';
|
|
224
|
+
readonly fields: readonly ["enrollment_id"];
|
|
225
|
+
readonly group: 'playbook';
|
|
226
|
+
};
|
|
227
|
+
readonly 'playbooks.step.failed': {
|
|
228
|
+
readonly description: 'A playbook step could not be delivered';
|
|
229
|
+
readonly fields: readonly ["step_id", "reason"];
|
|
230
|
+
readonly group: 'playbook';
|
|
231
|
+
};
|
|
232
|
+
readonly 'playbooks.step.needs_review': {
|
|
233
|
+
readonly description: 'A playbook step waits for HR before it sends';
|
|
234
|
+
readonly fields: readonly ["step_id"];
|
|
235
|
+
readonly group: 'playbook';
|
|
236
|
+
};
|
|
237
|
+
readonly 'playbooks.step.sent': {
|
|
238
|
+
readonly description: 'A playbook step reached its person';
|
|
239
|
+
readonly fields: readonly ["step_id"];
|
|
240
|
+
readonly group: 'playbook';
|
|
241
|
+
};
|
|
242
|
+
readonly 'program.archived': {
|
|
243
|
+
readonly description: 'A program was archived';
|
|
244
|
+
readonly fields: readonly ["program_id"];
|
|
245
|
+
readonly group: 'connections';
|
|
246
|
+
};
|
|
247
|
+
readonly 'program.created': {
|
|
248
|
+
readonly description: 'A Connections program or playbook was created';
|
|
249
|
+
readonly fields: readonly ["program_id", "kind"];
|
|
250
|
+
readonly group: 'connections';
|
|
251
|
+
};
|
|
252
|
+
readonly 'program.paused': {
|
|
253
|
+
readonly description: 'A program was paused';
|
|
254
|
+
readonly fields: readonly ["program_id"];
|
|
255
|
+
readonly group: 'connections';
|
|
256
|
+
};
|
|
257
|
+
readonly 'program.resumed': {
|
|
258
|
+
readonly description: 'A program was switched on';
|
|
259
|
+
readonly fields: readonly ["program_id"];
|
|
260
|
+
readonly group: 'connections';
|
|
261
|
+
};
|
|
262
|
+
readonly 'program.updated': {
|
|
263
|
+
readonly description: 'A program’s settings changed';
|
|
264
|
+
readonly fields: readonly ["program_id", "kind"];
|
|
265
|
+
readonly group: 'connections';
|
|
266
|
+
};
|
|
267
|
+
readonly 'round.planned': {
|
|
268
|
+
readonly description: 'Shuffl planned a round of introductions';
|
|
269
|
+
readonly fields: readonly ["round_id", "groups", "unmatched"];
|
|
270
|
+
readonly group: 'connections';
|
|
271
|
+
};
|
|
272
|
+
readonly 'round.requested': {
|
|
273
|
+
readonly description: 'Someone asked for a round of introductions';
|
|
274
|
+
readonly fields: readonly ["round_id", "retry"];
|
|
275
|
+
readonly group: 'connections';
|
|
276
|
+
};
|
|
277
|
+
readonly 'slack.connected': {
|
|
278
|
+
readonly description: 'Slack was connected';
|
|
279
|
+
readonly fields: readonly [];
|
|
280
|
+
readonly group: 'workspace';
|
|
281
|
+
};
|
|
282
|
+
readonly 'slack.connection_expired': {
|
|
283
|
+
readonly description: 'Slack stopped accepting Shuffl’s connection';
|
|
284
|
+
readonly fields: readonly ["reason"];
|
|
285
|
+
readonly group: 'workspace';
|
|
286
|
+
};
|
|
287
|
+
readonly 'slack.uninstalled': {
|
|
288
|
+
readonly description: 'Shuffl was removed from Slack';
|
|
289
|
+
readonly fields: readonly ["reason"];
|
|
290
|
+
readonly group: 'workspace';
|
|
291
|
+
};
|
|
292
|
+
readonly 'webhook.endpoint.disabled': {
|
|
293
|
+
readonly description: 'Shuffl turned an endpoint off after it kept failing';
|
|
294
|
+
readonly fields: readonly ["endpoint_id", "reason"];
|
|
295
|
+
readonly group: 'webhooks';
|
|
296
|
+
};
|
|
297
|
+
readonly 'webhook.test': {
|
|
298
|
+
readonly description: 'A test event someone sent from Settings or the API';
|
|
299
|
+
readonly fields: readonly ["endpoint_id"];
|
|
300
|
+
readonly group: 'webhooks';
|
|
301
|
+
};
|
|
302
|
+
readonly 'workspace.deletion_requested': {
|
|
303
|
+
readonly description: 'An owner asked to delete the workspace';
|
|
304
|
+
readonly fields: readonly ["delete_after"];
|
|
305
|
+
readonly group: 'workspace';
|
|
306
|
+
};
|
|
307
|
+
readonly 'workspace.exported': {
|
|
308
|
+
readonly description: 'Someone exported the workspace’s data';
|
|
309
|
+
readonly fields: readonly [];
|
|
310
|
+
readonly group: 'workspace';
|
|
311
|
+
};
|
|
312
|
+
readonly 'workspace.renamed': {
|
|
313
|
+
readonly description: 'The workspace was renamed';
|
|
314
|
+
readonly fields: readonly [];
|
|
315
|
+
readonly group: 'workspace';
|
|
316
|
+
};
|
|
317
|
+
readonly 'workspace.restored': {
|
|
318
|
+
readonly description: 'The workspace was restored';
|
|
319
|
+
readonly fields: readonly ["deletion_canceled"];
|
|
320
|
+
readonly group: 'workspace';
|
|
321
|
+
};
|
|
322
|
+
readonly 'workspace.slack_join_access_changed': {
|
|
323
|
+
readonly description: 'Who can join from Slack changed';
|
|
324
|
+
readonly fields: readonly [];
|
|
325
|
+
readonly group: 'workspace';
|
|
326
|
+
};
|
|
327
|
+
};
|
|
328
|
+
export type WebhookEventType = keyof typeof webhookEventCatalog;
|
|
329
|
+
export declare const webhookEventTypes: WebhookEventType[];
|
|
330
|
+
export declare const isWebhookEventType: (value: string) => value is WebhookEventType;
|
|
331
|
+
/** Keys no payload may ever carry. A test walks the catalog against it. */
|
|
332
|
+
export declare const webhookNeverSendFields: readonly ['answer_text', 'body', 'comment', 'bio', 'email', 'feedback', 'message', 'name', 'note', 'previous_name', 'question', 'slack_team_id', 'slack_user_id', 'subject', 'text', 'title', 'token', 'secret'];
|
|
333
|
+
type Fields<T extends WebhookEventType> = (typeof webhookEventCatalog)[T]['fields'][number];
|
|
334
|
+
export type WebhookEventData<T extends WebhookEventType = WebhookEventType> = {
|
|
335
|
+
[K in Fields<T>]?: string | number | boolean | null;
|
|
336
|
+
};
|
|
337
|
+
export type WebhookActor = {
|
|
338
|
+
type: 'user' | 'system';
|
|
339
|
+
id: string | null;
|
|
340
|
+
};
|
|
341
|
+
export type WebhookEvent<T extends WebhookEventType = WebhookEventType> = {
|
|
342
|
+
[K in T]: {
|
|
343
|
+
id: string;
|
|
344
|
+
type: K;
|
|
345
|
+
api_version: string;
|
|
346
|
+
created_at: string;
|
|
347
|
+
workspace_id: string;
|
|
348
|
+
actor: WebhookActor;
|
|
349
|
+
data: WebhookEventData<K>;
|
|
350
|
+
};
|
|
351
|
+
}[T];
|
|
352
|
+
export declare const webhookSecretPrefix = "whsec_";
|
|
353
|
+
export declare const webhookToleranceSeconds = 300;
|
|
354
|
+
/** The `v1,<signature>` value for one secret: base64 HMAC-SHA256 of
|
|
355
|
+
* `id.timestamp.body`, as Standard Webhooks specifies. */
|
|
356
|
+
export declare function signWebhook(secret: string, id: string, timestamp: number, body: string): Promise<string>;
|
|
357
|
+
export declare class WebhookVerificationError extends Error {
|
|
358
|
+
name: string;
|
|
359
|
+
}
|
|
360
|
+
type HeaderSource = Headers | Record<string, string | string[] | undefined | null>;
|
|
361
|
+
/** Checks a delivery's Standard Webhooks headers against the endpoint's
|
|
362
|
+
* signing secret (or several while one is rolled) and returns the parsed
|
|
363
|
+
* event. Pass the raw request body, before any JSON parsing. Throws
|
|
364
|
+
* WebhookVerificationError for a missing header, a timestamp more than
|
|
365
|
+
* five minutes away or a signature that matches no secret. */
|
|
366
|
+
export declare function verifyWebhook<T extends WebhookEventType = WebhookEventType>(input: {
|
|
367
|
+
body: string;
|
|
368
|
+
headers: HeaderSource;
|
|
369
|
+
secret: string | readonly string[];
|
|
370
|
+
toleranceSeconds?: number;
|
|
371
|
+
now?: Date;
|
|
372
|
+
}): Promise<WebhookEvent<T>>;
|
|
373
|
+
export {};
|