@frogbotai/piece-slack 0.29.0 → 0.30.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.
Files changed (42) hide show
  1. package/README.md +3 -2
  2. package/dist/actions.d.ts +2 -2
  3. package/dist/actions.d.ts.map +1 -1
  4. package/dist/actions.js +285 -193
  5. package/dist/actions.js.map +1 -1
  6. package/dist/client.js +47 -35
  7. package/dist/client.js.map +1 -1
  8. package/dist/config.js +17 -5
  9. package/dist/config.js.map +1 -1
  10. package/dist/define.js +1 -0
  11. package/dist/define.js.map +1 -1
  12. package/dist/files.d.ts.map +1 -1
  13. package/dist/files.js +25 -15
  14. package/dist/files.js.map +1 -1
  15. package/dist/index.d.ts +1 -1
  16. package/dist/index.js +45 -39
  17. package/dist/index.js.map +1 -1
  18. package/dist/options.js +36 -21
  19. package/dist/options.js.map +1 -1
  20. package/dist/questions/blocks.js +148 -74
  21. package/dist/questions/blocks.js.map +1 -1
  22. package/dist/questions/index.js +2 -1
  23. package/dist/questions/index.js.map +1 -1
  24. package/dist/questions/notify.js +19 -13
  25. package/dist/questions/notify.js.map +1 -1
  26. package/dist/questions/parse.js +110 -59
  27. package/dist/questions/parse.js.map +1 -1
  28. package/dist/questions/render.js +16 -7
  29. package/dist/questions/render.js.map +1 -1
  30. package/dist/questions/settled.js +9 -3
  31. package/dist/questions/settled.js.map +1 -1
  32. package/dist/questions/slackThread.js +12 -6
  33. package/dist/questions/slackThread.js.map +1 -1
  34. package/dist/questions/state.js +18 -5
  35. package/dist/questions/state.js.map +1 -1
  36. package/dist/questions/updated.js +32 -24
  37. package/dist/questions/updated.js.map +1 -1
  38. package/dist/triggers.js +150 -126
  39. package/dist/triggers.js.map +1 -1
  40. package/dist/webhook.js +28 -43
  41. package/dist/webhook.js.map +1 -1
  42. package/package.json +4 -4
package/dist/actions.js CHANGED
@@ -1,29 +1,33 @@
1
+ import { filesCollectionSlug } from 'frogbot/pieces';
1
2
  import { z } from 'zod';
2
- import { slackApiResult, slackResponse, slackValue, slackValues, } from './client.js';
3
+ import { slackApiResult, slackResponse, slackValue, slackValues } from './client.js';
3
4
  import { defineAction } from './define.js';
4
5
  import { loadSlackFile, slackFile } from './files.js';
5
6
  import { channelOptions, userOptions } from './options.js';
6
- const channel = z.string().min(1).meta({ label: 'Channel' });
7
- const user = z.string().min(1).meta({ label: 'User' });
7
+ const channel = z.string().min(1).meta({
8
+ label: 'Channel'
9
+ });
10
+ const user = z.string().min(1).meta({
11
+ label: 'User'
12
+ });
8
13
  const timestamp = z.string().regex(/^(?:.*\/p\d{16}|\d+\.\d{6})$/, 'Invalid Slack timestamp.');
9
14
  const blocks = z.array(slackValue).default([]);
10
15
  const messageResult = slackResponse.extend({
11
16
  channel: z.string().optional(),
12
- ts: z.string().optional(),
17
+ ts: z.string().optional()
13
18
  });
14
19
  function normalizeTimestamp(value) {
15
20
  const link = value.match(/\/p(\d+)(\d{6})$/);
16
21
  return link ? `${link[1]}.${link[2]}` : value;
17
22
  }
18
- async function upload({ client, file, channelId, title, initialComment, threadTimestamp, token = 'bot', signal, }) {
19
- const created = await client.request('files.getUploadURLExternal', { filename: file.name, length: file.data.size }, token);
23
+ async function upload({ client, file, channelId, title, initialComment, threadTimestamp, token = 'bot', signal }) {
24
+ const created = await client.request('files.getUploadURLExternal', {
25
+ filename: file.name,
26
+ length: file.data.size
27
+ }, token);
20
28
  const uploadUrl = typeof created.upload_url === 'string' ? new URL(created.upload_url) : undefined;
21
29
  const fileId = typeof created.file_id === 'string' ? created.file_id : undefined;
22
- if (!uploadUrl ||
23
- !fileId ||
24
- uploadUrl.protocol !== 'https:' ||
25
- uploadUrl.username ||
26
- uploadUrl.password) {
30
+ if (!uploadUrl || !fileId || uploadUrl.protocol !== 'https:' || uploadUrl.username || uploadUrl.password) {
27
31
  throw new Error('Slack returned an invalid file upload target.');
28
32
  }
29
33
  if (uploadUrl.hostname !== 'files.slack.com' && !uploadUrl.hostname.endsWith('.slack.com')) {
@@ -33,15 +37,19 @@ async function upload({ client, file, channelId, title, initialComment, threadTi
33
37
  method: 'POST',
34
38
  body: file.data,
35
39
  redirect: 'error',
36
- signal,
40
+ signal
37
41
  });
38
- if (!response.ok)
39
- throw new Error(`Slack file upload failed (${response.status}).`);
42
+ if (!response.ok) throw new Error(`Slack file upload failed (${response.status}).`);
40
43
  return client.request('files.completeUploadExternal', {
41
- files: [{ id: fileId, title }],
44
+ files: [
45
+ {
46
+ id: fileId,
47
+ title
48
+ }
49
+ ],
42
50
  channel_id: channelId,
43
51
  initial_comment: initialComment,
44
- thread_ts: threadTimestamp,
52
+ thread_ts: threadTimestamp
45
53
  }, token);
46
54
  }
47
55
  const messageFields = {
@@ -50,17 +58,22 @@ const messageFields = {
50
58
  profilePicture: z.url().optional(),
51
59
  iconEmoji: z.string().optional(),
52
60
  blocks,
53
- unfurlLinks: z.boolean().default(true),
61
+ unfurlLinks: z.boolean().default(true)
54
62
  };
55
- const sendDirectMessageInput = z.object({ userId: user, ...messageFields });
63
+ const sendDirectMessageInput = z.object({
64
+ userId: user,
65
+ ...messageFields
66
+ });
56
67
  export const sendDirectMessage = defineAction({
57
68
  slug: 'sendDirectMessage',
58
69
  description: 'Send a direct message to a Slack user.',
59
70
  input: sendDirectMessageInput,
60
71
  output: messageResult,
61
72
  idempotent: false,
62
- options: { userId: userOptions },
63
- async run({ client, input }) {
73
+ options: {
74
+ userId: userOptions
75
+ },
76
+ async run ({ client, input }) {
64
77
  return client.request('chat.postMessage', {
65
78
  channel: input.userId,
66
79
  text: input.text,
@@ -68,12 +81,11 @@ export const sendDirectMessage = defineAction({
68
81
  icon_url: input.profilePicture,
69
82
  icon_emoji: input.iconEmoji,
70
83
  blocks: input.blocks,
71
- unfurl_links: input.unfurlLinks,
84
+ unfurl_links: input.unfurlLinks
72
85
  });
73
- },
86
+ }
74
87
  });
75
- const sendChannelInput = z
76
- .object({
88
+ const sendChannelInput = z.object({
77
89
  channel,
78
90
  text: z.string().optional(),
79
91
  sendAsBot: z.boolean().default(true),
@@ -84,10 +96,9 @@ const sendChannelInput = z
84
96
  file: slackFile.optional(),
85
97
  replyBroadcast: z.boolean().default(false),
86
98
  unfurlLinks: z.boolean().default(true),
87
- blocks,
88
- })
89
- .refine(({ text, blocks: value }) => Boolean(text) || value.length > 0, {
90
- message: 'A message or Block Kit blocks are required.',
99
+ blocks
100
+ }).refine(({ text, blocks: value })=>Boolean(text) || value.length > 0, {
101
+ message: 'A message or Block Kit blocks are required.'
91
102
  });
92
103
  export const sendChannelMessage = defineAction({
93
104
  slug: 'sendChannelMessage',
@@ -95,8 +106,10 @@ export const sendChannelMessage = defineAction({
95
106
  input: sendChannelInput,
96
107
  output: slackResponse,
97
108
  idempotent: false,
98
- options: { channel: channelOptions },
99
- async run({ client, input, req }) {
109
+ options: {
110
+ channel: channelOptions
111
+ },
112
+ async run ({ client, input, req }) {
100
113
  const token = input.sendAsBot ? 'bot' : 'user';
101
114
  if (input.file) {
102
115
  const file = await loadSlackFile(req, input.file);
@@ -105,11 +118,9 @@ export const sendChannelMessage = defineAction({
105
118
  file,
106
119
  channelId: input.channel,
107
120
  initialComment: input.text,
108
- threadTimestamp: input.threadTimestamp
109
- ? normalizeTimestamp(input.threadTimestamp)
110
- : undefined,
121
+ threadTimestamp: input.threadTimestamp ? normalizeTimestamp(input.threadTimestamp) : undefined,
111
122
  token,
112
- signal: req.signal,
123
+ signal: req.signal
113
124
  });
114
125
  }
115
126
  return client.request('chat.postMessage', {
@@ -121,15 +132,15 @@ export const sendChannelMessage = defineAction({
121
132
  icon_emoji: input.iconEmoji,
122
133
  reply_broadcast: input.replyBroadcast,
123
134
  unfurl_links: input.unfurlLinks,
124
- blocks: input.blocks,
135
+ blocks: input.blocks
125
136
  }, token);
126
- },
137
+ }
127
138
  });
128
139
  const addReactionInput = z.object({
129
140
  channel,
130
141
  timestamp,
131
142
  reaction: z.string().min(1),
132
- reactAsUser: z.boolean().default(false),
143
+ reactAsUser: z.boolean().default(false)
133
144
  });
134
145
  export const addReaction = defineAction({
135
146
  slug: 'addReaction',
@@ -137,20 +148,22 @@ export const addReaction = defineAction({
137
148
  input: addReactionInput,
138
149
  output: slackResponse,
139
150
  idempotent: true,
140
- options: { channel: channelOptions },
141
- async run({ client, input }) {
151
+ options: {
152
+ channel: channelOptions
153
+ },
154
+ async run ({ client, input }) {
142
155
  return client.request('reactions.add', {
143
156
  channel: input.channel,
144
157
  timestamp: normalizeTimestamp(input.timestamp),
145
- name: input.reaction,
158
+ name: input.reaction
146
159
  }, input.reactAsUser ? 'user' : 'bot');
147
- },
160
+ }
148
161
  });
149
162
  const uploadFileInput = z.object({
150
163
  file: slackFile,
151
164
  title: z.string().optional(),
152
165
  filename: z.string().optional(),
153
- channel: channel.optional(),
166
+ channel: channel.optional()
154
167
  });
155
168
  export const uploadFile = defineAction({
156
169
  slug: 'uploadFile',
@@ -158,65 +171,68 @@ export const uploadFile = defineAction({
158
171
  input: uploadFileInput,
159
172
  output: slackResponse,
160
173
  idempotent: false,
161
- options: { channel: channelOptions },
162
- async run({ client, input, req }) {
174
+ options: {
175
+ channel: channelOptions
176
+ },
177
+ async run ({ client, input, req }) {
163
178
  const loaded = await loadSlackFile(req, {
164
179
  ...input.file,
165
- name: input.filename ?? input.file.name,
180
+ name: input.filename ?? input.file.name
166
181
  });
167
182
  return upload({
168
183
  client,
169
184
  file: loaded,
170
185
  channelId: input.channel,
171
186
  title: input.title,
172
- signal: req.signal,
187
+ signal: req.signal
173
188
  });
174
- },
189
+ }
190
+ });
191
+ const getFileInput = z.object({
192
+ fileId: z.string().min(1)
175
193
  });
176
- const getFileInput = z.object({ fileId: z.string().min(1) });
177
194
  export const getFile = defineAction({
178
195
  slug: 'getFile',
179
196
  description: 'Get Slack file metadata and safely download its contents.',
180
197
  input: getFileInput,
181
198
  output: slackValue,
182
199
  idempotent: true,
183
- async run({ client, input, req }) {
184
- const response = await client.request('files.info', { file: input.fileId });
200
+ async run ({ client, input, req }) {
201
+ const response = await client.request('files.info', {
202
+ file: input.fileId
203
+ });
185
204
  const file = response.file;
186
- if (!file ||
187
- typeof file !== 'object' ||
188
- !('url_private_download' in file) ||
189
- typeof file.url_private_download !== 'string') {
205
+ if (!file || typeof file !== 'object' || !('url_private_download' in file) || typeof file.url_private_download !== 'string') {
190
206
  throw new Error('Slack file has no download URL.');
191
207
  }
192
208
  const url = new URL(file.url_private_download);
193
- if (url.protocol !== 'https:' ||
194
- url.hostname !== 'files.slack.com' ||
195
- url.username ||
196
- url.password) {
209
+ if (url.protocol !== 'https:' || url.hostname !== 'files.slack.com' || url.username || url.password) {
197
210
  throw new Error('Slack file download URL is untrusted.');
198
211
  }
199
212
  const downloaded = await fetch(url, {
200
- headers: { authorization: `Bearer ${client.token()}` },
213
+ headers: {
214
+ authorization: `Bearer ${client.token()}`
215
+ },
201
216
  redirect: 'error',
202
- signal: req.signal,
217
+ signal: req.signal
203
218
  });
204
- if (!downloaded.ok)
205
- throw new Error(`Slack file download failed (${downloaded.status}).`);
219
+ if (!downloaded.ok) throw new Error(`Slack file download failed (${downloaded.status}).`);
206
220
  const data = Buffer.from(await downloaded.arrayBuffer());
207
221
  const name = 'name' in file && typeof file.name === 'string' ? file.name : `slack-${input.fileId}`;
208
222
  const mimeType = downloaded.headers.get('content-type')?.split(';')[0] || 'application/octet-stream';
209
- const collection = req.frogbot.config.files?.slug;
210
- if (!collection) {
211
- throw new Error('[frogbot] Slack file downloads require the files collection.');
212
- }
223
+ const collection = filesCollectionSlug(req, 'Slack');
213
224
  req.signal?.throwIfAborted();
214
225
  const saved = await req.frogbot.create({
215
226
  collection,
216
227
  data: {},
217
- file: { data, name, mimetype: mimeType, size: data.length },
228
+ file: {
229
+ data,
230
+ name,
231
+ mimetype: mimeType,
232
+ size: data.length
233
+ },
218
234
  req,
219
- overrideAccess: false,
235
+ overrideAccess: false
220
236
  });
221
237
  return {
222
238
  ...file,
@@ -225,96 +241,104 @@ export const getFile = defineAction({
225
241
  name,
226
242
  mimeType,
227
243
  size: data.length,
228
- url: typeof saved.url === 'string' ? saved.url : undefined,
229
- },
244
+ url: typeof saved.url === 'string' ? saved.url : undefined
245
+ }
230
246
  };
231
- },
247
+ }
248
+ });
249
+ const searchMessagesInput = z.object({
250
+ query: z.string().min(1)
232
251
  });
233
- const searchMessagesInput = z.object({ query: z.string().min(1) });
234
252
  export const searchMessages = defineAction({
235
253
  slug: 'searchMessages',
236
254
  description: 'Search all Slack messages matching a query.',
237
255
  input: searchMessagesInput,
238
256
  output: slackValues,
239
257
  idempotent: true,
240
- async run({ client, input }) {
258
+ async run ({ client, input }) {
241
259
  const matches = [];
242
260
  let cursor = '*';
243
261
  do {
244
- const response = await client.request('search.messages', { query: input.query, count: 100, cursor }, 'user');
262
+ const response = await client.request('search.messages', {
263
+ query: input.query,
264
+ count: 100,
265
+ cursor
266
+ }, 'user');
245
267
  const messages = response.messages;
246
- if (!messages || typeof messages !== 'object')
247
- break;
268
+ if (!messages || typeof messages !== 'object') break;
248
269
  if ('matches' in messages && Array.isArray(messages.matches)) {
249
- for (const match of messages.matches) {
270
+ for (const match of messages.matches){
250
271
  if (match && typeof match === 'object' && !Array.isArray(match)) {
251
272
  matches.push(Object.fromEntries(Object.entries(match)));
252
273
  }
253
274
  }
254
275
  }
255
276
  const pagination = 'pagination' in messages ? messages.pagination : undefined;
256
- cursor =
257
- pagination && typeof pagination === 'object' && 'next_cursor' in pagination
258
- ? String(pagination.next_cursor || '') || undefined
259
- : undefined;
260
- } while (cursor);
277
+ cursor = pagination && typeof pagination === 'object' && 'next_cursor' in pagination ? String(pagination.next_cursor || '') || undefined : undefined;
278
+ }while (cursor)
261
279
  return matches;
262
- },
280
+ }
281
+ });
282
+ const emailInput = z.object({
283
+ email: z.email()
263
284
  });
264
- const emailInput = z.object({ email: z.email() });
265
285
  export const findUserByEmail = defineAction({
266
286
  slug: 'findUserByEmail',
267
287
  description: 'Find a Slack user by exact email address.',
268
288
  input: emailInput,
269
289
  output: slackResponse,
270
290
  idempotent: true,
271
- async run({ client, input }) {
291
+ async run ({ client, input }) {
272
292
  return client.request('users.lookupByEmail', input);
273
- },
293
+ }
294
+ });
295
+ const handleInput = z.object({
296
+ handle: z.string().min(1)
274
297
  });
275
- const handleInput = z.object({ handle: z.string().min(1) });
276
298
  export const findUserByHandle = defineAction({
277
299
  slug: 'findUserByHandle',
278
300
  description: 'Find a Slack user by display-name handle.',
279
301
  input: handleInput,
280
302
  output: slackValue,
281
303
  idempotent: true,
282
- async run({ client, input }) {
304
+ async run ({ client, input }) {
283
305
  const handle = input.handle.replace(/^@/, '');
284
306
  const members = await client.paginate({
285
307
  path: 'users.list',
286
308
  item: 'members',
287
- body: { limit: 1000 },
309
+ body: {
310
+ limit: 1000
311
+ }
288
312
  });
289
- const found = members.find((member) => {
290
- if (!member || typeof member !== 'object' || !('profile' in member))
291
- return false;
313
+ const found = members.find((member)=>{
314
+ if (!member || typeof member !== 'object' || !('profile' in member)) return false;
292
315
  const profile = member.profile;
293
- return (profile &&
294
- typeof profile === 'object' &&
295
- 'display_name' in profile &&
296
- profile.display_name === handle);
316
+ return profile && typeof profile === 'object' && 'display_name' in profile && profile.display_name === handle;
297
317
  });
298
318
  if (!found || typeof found !== 'object') {
299
319
  throw new Error(`Could not find user with handle @${handle}`);
300
320
  }
301
321
  return found;
302
- },
322
+ }
323
+ });
324
+ const findUserByIdInput = z.object({
325
+ id: z.string().min(1)
303
326
  });
304
- const findUserByIdInput = z.object({ id: z.string().min(1) });
305
327
  export const findUserById = defineAction({
306
328
  slug: 'findUserById',
307
329
  description: 'Find a Slack user profile by ID.',
308
330
  input: findUserByIdInput,
309
331
  output: slackResponse,
310
332
  idempotent: true,
311
- async run({ client, input }) {
312
- return client.request('users.profile.get', { user: input.id });
313
- },
333
+ async run ({ client, input }) {
334
+ return client.request('users.profile.get', {
335
+ user: input.id
336
+ });
337
+ }
314
338
  });
315
339
  const listUsersInput = z.object({
316
340
  includeBots: z.boolean().default(false),
317
- includeDisabled: z.boolean().default(false),
341
+ includeDisabled: z.boolean().default(false)
318
342
  });
319
343
  export const listUsers = defineAction({
320
344
  slug: 'listUsers',
@@ -322,60 +346,79 @@ export const listUsers = defineAction({
322
346
  input: listUsersInput,
323
347
  output: slackValues,
324
348
  idempotent: true,
325
- async run({ client, input }) {
349
+ async run ({ client, input }) {
326
350
  const members = await client.paginate({
327
351
  path: 'users.list',
328
352
  item: 'members',
329
- body: { limit: 1000 },
353
+ body: {
354
+ limit: 1000
355
+ }
330
356
  });
331
- return members.filter((member) => {
332
- if (!member || typeof member !== 'object')
333
- return false;
334
- if (!input.includeBots && 'is_bot' in member && member.is_bot === true)
335
- return false;
336
- if (!input.includeDisabled && 'deleted' in member && member.deleted === true)
337
- return false;
357
+ return members.filter((member)=>{
358
+ if (!member || typeof member !== 'object') return false;
359
+ if (!input.includeBots && 'is_bot' in member && member.is_bot === true) return false;
360
+ if (!input.includeDisabled && 'deleted' in member && member.deleted === true) return false;
338
361
  return true;
339
362
  });
340
- },
363
+ }
364
+ });
365
+ const updateMessageInput = z.object({
366
+ channel,
367
+ timestamp,
368
+ text: z.string().min(1),
369
+ blocks
341
370
  });
342
- const updateMessageInput = z.object({ channel, timestamp, text: z.string().min(1), blocks });
343
371
  export const updateMessage = defineAction({
344
372
  slug: 'updateMessage',
345
373
  description: 'Update an existing Slack message.',
346
374
  input: updateMessageInput,
347
375
  output: slackResponse,
348
376
  idempotent: true,
349
- options: { channel: channelOptions },
350
- async run({ client, input }) {
377
+ options: {
378
+ channel: channelOptions
379
+ },
380
+ async run ({ client, input }) {
351
381
  return client.request('chat.update', {
352
382
  channel: input.channel,
353
383
  ts: normalizeTimestamp(input.timestamp),
354
384
  text: input.text,
355
- blocks: input.blocks,
385
+ blocks: input.blocks
356
386
  });
357
- },
387
+ }
388
+ });
389
+ const deleteMessageInput = z.object({
390
+ channel,
391
+ timestamp
358
392
  });
359
- const deleteMessageInput = z.object({ channel, timestamp });
360
393
  export const deleteMessage = defineAction({
361
394
  slug: 'deleteMessage',
362
395
  description: 'Delete a Slack message after confirming it exists.',
363
396
  input: deleteMessageInput,
364
397
  output: slackResponse,
365
398
  idempotent: false,
366
- options: { channel: channelOptions },
367
- async run({ client, input }) {
399
+ options: {
400
+ channel: channelOptions
401
+ },
402
+ async run ({ client, input }) {
368
403
  const ts = normalizeTimestamp(input.timestamp);
369
- const history = await client.request('conversations.history', { channel: input.channel, oldest: ts, limit: 1, inclusive: true }, 'user');
404
+ const history = await client.request('conversations.history', {
405
+ channel: input.channel,
406
+ oldest: ts,
407
+ limit: 1,
408
+ inclusive: true
409
+ }, 'user');
370
410
  if (!Array.isArray(history.messages) || history.messages.length === 0) {
371
411
  throw new Error('No message found for the provided timestamp.');
372
412
  }
373
- return client.request('chat.delete', { channel: input.channel, ts }, 'user');
374
- },
413
+ return client.request('chat.delete', {
414
+ channel: input.channel,
415
+ ts
416
+ }, 'user');
417
+ }
375
418
  });
376
419
  const createChannelInput = z.object({
377
420
  channelName: z.string().min(1),
378
- isPrivate: z.boolean().default(false),
421
+ isPrivate: z.boolean().default(false)
379
422
  });
380
423
  export const createChannel = defineAction({
381
424
  slug: 'createChannel',
@@ -383,18 +426,18 @@ export const createChannel = defineAction({
383
426
  input: createChannelInput,
384
427
  output: slackResponse,
385
428
  idempotent: false,
386
- async run({ client, input }) {
429
+ async run ({ client, input }) {
387
430
  return client.request('conversations.create', {
388
431
  name: input.channelName,
389
- is_private: input.isPrivate,
432
+ is_private: input.isPrivate
390
433
  });
391
- },
434
+ }
392
435
  });
393
436
  const updateProfileInput = z.object({
394
437
  firstName: z.string().optional(),
395
438
  lastName: z.string().optional(),
396
439
  email: z.email().optional(),
397
- userId: z.string().optional(),
440
+ userId: z.string().optional()
398
441
  });
399
442
  export const updateProfile = defineAction({
400
443
  slug: 'updateProfile',
@@ -402,19 +445,23 @@ export const updateProfile = defineAction({
402
445
  input: updateProfileInput,
403
446
  output: slackResponse,
404
447
  idempotent: true,
405
- async run({ client, input }) {
448
+ async run ({ client, input }) {
406
449
  return client.request('users.profile.set', {
407
- profile: { first_name: input.firstName, last_name: input.lastName, email: input.email },
408
- user: input.userId,
450
+ profile: {
451
+ first_name: input.firstName,
452
+ last_name: input.lastName,
453
+ email: input.email
454
+ },
455
+ user: input.userId
409
456
  }, 'user');
410
- },
457
+ }
411
458
  });
412
459
  const getChannelHistoryInput = z.object({
413
460
  channel,
414
461
  oldest: z.number().optional(),
415
462
  latest: z.number().optional(),
416
463
  inclusive: z.boolean().default(false),
417
- includeAllMetadata: z.boolean().default(false),
464
+ includeAllMetadata: z.boolean().default(false)
418
465
  });
419
466
  export const getChannelHistory = defineAction({
420
467
  slug: 'getChannelHistory',
@@ -422,8 +469,10 @@ export const getChannelHistory = defineAction({
422
469
  input: getChannelHistoryInput,
423
470
  output: slackValues,
424
471
  idempotent: true,
425
- options: { channel: channelOptions },
426
- async run({ client, input }) {
472
+ options: {
473
+ channel: channelOptions
474
+ },
475
+ async run ({ client, input }) {
427
476
  return client.paginate({
428
477
  path: 'conversations.history',
429
478
  item: 'messages',
@@ -433,15 +482,15 @@ export const getChannelHistory = defineAction({
433
482
  latest: input.latest,
434
483
  inclusive: input.inclusive,
435
484
  include_all_metadata: input.includeAllMetadata,
436
- limit: 200,
437
- },
485
+ limit: 200
486
+ }
438
487
  });
439
- },
488
+ }
440
489
  });
441
490
  const setUserStatusInput = z.object({
442
491
  text: z.string().max(100),
443
492
  emoji: z.string().optional(),
444
- expiration: z.number().int().optional(),
493
+ expiration: z.number().int().optional()
445
494
  });
446
495
  export const setUserStatus = defineAction({
447
496
  slug: 'setUserStatus',
@@ -449,88 +498,118 @@ export const setUserStatus = defineAction({
449
498
  input: setUserStatusInput,
450
499
  output: slackResponse,
451
500
  idempotent: true,
452
- async run({ client, input }) {
501
+ async run ({ client, input }) {
453
502
  return client.request('users.profile.set', {
454
503
  profile: {
455
504
  status_text: input.text,
456
505
  status_emoji: input.emoji,
457
- status_expiration: input.expiration,
458
- },
506
+ status_expiration: input.expiration
507
+ }
459
508
  }, 'user');
460
- },
509
+ }
510
+ });
511
+ const markdownToSlackInput = z.object({
512
+ markdown: z.string()
513
+ });
514
+ const markdownToSlackOutput = z.object({
515
+ text: z.string()
461
516
  });
462
- const markdownToSlackInput = z.object({ markdown: z.string() });
463
- const markdownToSlackOutput = z.object({ text: z.string() });
464
517
  export const markdownToSlack = defineAction({
465
518
  slug: 'markdownToSlack',
466
519
  description: 'Convert Markdown text to Slack mrkdwn.',
467
520
  input: markdownToSlackInput,
468
521
  output: markdownToSlackOutput,
469
522
  idempotent: true,
470
- async run({ input }) {
471
- const text = input.markdown
472
- .replace(/\[([^\]]+)]\((https?:\/\/[^)]+)\)/g, '<$2|$1>')
473
- .replace(/\*\*([^*]+)\*\*/g, '*$1*')
474
- .replace(/^[-+] /gm, '• ');
475
- return { text };
476
- },
523
+ async run ({ input }) {
524
+ const text = input.markdown.replace(/\[([^\]]+)]\((https?:\/\/[^)]+)\)/g, '<$2|$1>').replace(/\*\*([^*]+)\*\*/g, '*$1*').replace(/^[-+] /gm, '• ');
525
+ return {
526
+ text
527
+ };
528
+ }
529
+ });
530
+ const listThreadMessagesInput = z.object({
531
+ channel,
532
+ threadTimestamp: timestamp
477
533
  });
478
- const listThreadMessagesInput = z.object({ channel, threadTimestamp: timestamp });
479
534
  export const listThreadMessages = defineAction({
480
535
  slug: 'listThreadMessages',
481
536
  description: 'Retrieve all messages in a Slack thread.',
482
537
  input: listThreadMessagesInput,
483
538
  output: slackValues,
484
539
  idempotent: true,
485
- options: { channel: channelOptions },
486
- async run({ client, input }) {
540
+ options: {
541
+ channel: channelOptions
542
+ },
543
+ async run ({ client, input }) {
487
544
  return client.paginate({
488
545
  path: 'conversations.replies',
489
546
  item: 'messages',
490
- body: { channel: input.channel, ts: normalizeTimestamp(input.threadTimestamp) },
547
+ body: {
548
+ channel: input.channel,
549
+ ts: normalizeTimestamp(input.threadTimestamp)
550
+ }
491
551
  });
492
- },
552
+ }
553
+ });
554
+ const setChannelTopicInput = z.object({
555
+ channel,
556
+ topic: z.string()
493
557
  });
494
- const setChannelTopicInput = z.object({ channel, topic: z.string() });
495
558
  export const setChannelTopic = defineAction({
496
559
  slug: 'setChannelTopic',
497
560
  description: 'Set a Slack channel topic.',
498
561
  input: setChannelTopicInput,
499
562
  output: slackResponse,
500
563
  idempotent: true,
501
- options: { channel: channelOptions },
502
- async run({ client, input }) {
503
- return client.request('conversations.setTopic', input);
564
+ options: {
565
+ channel: channelOptions
504
566
  },
567
+ async run ({ client, input }) {
568
+ return client.request('conversations.setTopic', input);
569
+ }
570
+ });
571
+ const getMessageInput = z.object({
572
+ channel,
573
+ timestamp
505
574
  });
506
- const getMessageInput = z.object({ channel, timestamp });
507
575
  export const getMessage = defineAction({
508
576
  slug: 'getMessage',
509
577
  description: 'Get a Slack message by channel and timestamp.',
510
578
  input: getMessageInput,
511
579
  output: slackResponse,
512
580
  idempotent: true,
513
- options: { channel: channelOptions },
514
- async run({ client, input }) {
581
+ options: {
582
+ channel: channelOptions
583
+ },
584
+ async run ({ client, input }) {
515
585
  return client.request('conversations.history', {
516
586
  channel: input.channel,
517
587
  oldest: normalizeTimestamp(input.timestamp),
518
588
  limit: 1,
519
- inclusive: true,
589
+ inclusive: true
520
590
  });
521
- },
591
+ }
592
+ });
593
+ const inviteUserToChannelInput = z.object({
594
+ channel,
595
+ userId: user
522
596
  });
523
- const inviteUserToChannelInput = z.object({ channel, userId: user });
524
597
  export const inviteUserToChannel = defineAction({
525
598
  slug: 'inviteUserToChannel',
526
599
  description: 'Invite an existing user to a Slack channel.',
527
600
  input: inviteUserToChannelInput,
528
601
  output: slackResponse,
529
602
  idempotent: false,
530
- options: { channel: channelOptions, userId: userOptions },
531
- async run({ client, input }) {
532
- return client.request('conversations.invite', { channel: input.channel, users: input.userId });
603
+ options: {
604
+ channel: channelOptions,
605
+ userId: userOptions
533
606
  },
607
+ async run ({ client, input }) {
608
+ return client.request('conversations.invite', {
609
+ channel: input.channel,
610
+ users: input.userId
611
+ });
612
+ }
534
613
  });
535
614
  export const getUserGroupByHandle = defineAction({
536
615
  slug: 'getUserGroupByHandle',
@@ -538,18 +617,15 @@ export const getUserGroupByHandle = defineAction({
538
617
  input: handleInput,
539
618
  output: slackValue,
540
619
  idempotent: true,
541
- async run({ client, input }) {
620
+ async run ({ client, input }) {
542
621
  return findUserGroup(client, input.handle);
543
- },
622
+ }
544
623
  });
545
624
  async function findUserGroup(client, value) {
546
625
  const handle = value.replace(/^@/, '').toLowerCase();
547
626
  const response = await client.request('usergroups.list');
548
627
  const groups = Array.isArray(response.usergroups) ? response.usergroups : [];
549
- const found = groups.find((group) => group &&
550
- typeof group === 'object' &&
551
- 'handle' in group &&
552
- String(group.handle).toLowerCase() === handle);
628
+ const found = groups.find((group)=>group && typeof group === 'object' && 'handle' in group && String(group.handle).toLowerCase() === handle);
553
629
  if (!found || typeof found !== 'object') {
554
630
  throw new Error(`User group with handle '@${handle}' not found.`);
555
631
  }
@@ -557,7 +633,7 @@ async function findUserGroup(client, value) {
557
633
  }
558
634
  const updateUserGroupMembersInput = handleInput.extend({
559
635
  userIds: z.array(z.string()).optional(),
560
- appendUsers: z.boolean().default(true),
636
+ appendUsers: z.boolean().default(true)
561
637
  });
562
638
  export const updateUserGroupMembers = defineAction({
563
639
  slug: 'updateUserGroupMembers',
@@ -565,23 +641,39 @@ export const updateUserGroupMembers = defineAction({
565
641
  input: updateUserGroupMembersInput,
566
642
  output: slackResponse,
567
643
  idempotent: false,
568
- async run({ client, input }) {
644
+ async run ({ client, input }) {
569
645
  const group = await findUserGroup(client, input.handle);
570
646
  const id = 'id' in group ? String(group.id) : '';
571
- const existing = input.appendUsers && 'users' in group && Array.isArray(group.users)
572
- ? group.users.map(String)
573
- : [];
574
- const users = [...new Set([...existing, ...(input.userIds ?? []).filter(Boolean)])].join(', ');
575
- return client.request('usergroups.users.update', { usergroup: id, users }, 'user');
576
- },
647
+ const existing = input.appendUsers && 'users' in group && Array.isArray(group.users) ? group.users.map(String) : [];
648
+ const users = [
649
+ ...new Set([
650
+ ...existing,
651
+ ...(input.userIds ?? []).filter(Boolean)
652
+ ])
653
+ ].join(', ');
654
+ return client.request('usergroups.users.update', {
655
+ usergroup: id,
656
+ users
657
+ }, 'user');
658
+ }
577
659
  });
578
660
  const customApiInput = z.object({
579
- method: z.enum(['GET', 'POST', 'PUT', 'PATCH', 'DELETE']),
661
+ method: z.enum([
662
+ 'GET',
663
+ 'POST',
664
+ 'PUT',
665
+ 'PATCH',
666
+ 'DELETE'
667
+ ]),
580
668
  path: z.string().regex(/^[a-zA-Z][a-zA-Z0-9._-]*$/),
581
669
  headers: z.record(z.string(), z.string()).default({}),
582
- queryParams: z.record(z.string(), z.union([z.string(), z.number(), z.boolean()])).default({}),
670
+ queryParams: z.record(z.string(), z.union([
671
+ z.string(),
672
+ z.number(),
673
+ z.boolean()
674
+ ])).default({}),
583
675
  body: z.record(z.string(), z.unknown()).optional(),
584
- useUserToken: z.boolean().default(false),
676
+ useUserToken: z.boolean().default(false)
585
677
  });
586
678
  export const customApiCall = defineAction({
587
679
  slug: 'customApiCall',
@@ -589,10 +681,9 @@ export const customApiCall = defineAction({
589
681
  input: customApiInput,
590
682
  output: slackApiResult,
591
683
  idempotent: false,
592
- async run({ client, input }) {
684
+ async run ({ client, input }) {
593
685
  const query = new URLSearchParams();
594
- for (const [key, value] of Object.entries(input.queryParams))
595
- query.set(key, String(value));
686
+ for (const [key, value] of Object.entries(input.queryParams))query.set(key, String(value));
596
687
  const suffix = query.size ? `?${query}` : '';
597
688
  const headers = new Headers(input.headers);
598
689
  headers.delete('authorization');
@@ -606,9 +697,9 @@ export const customApiCall = defineAction({
606
697
  method: input.method,
607
698
  headers,
608
699
  body: input.body === undefined ? undefined : JSON.stringify(input.body),
609
- token: input.useUserToken ? 'user' : 'bot',
700
+ token: input.useUserToken ? 'user' : 'bot'
610
701
  });
611
- },
702
+ }
612
703
  });
613
704
  export const slackActions = [
614
705
  addReaction,
@@ -634,6 +725,7 @@ export const slackActions = [
634
725
  inviteUserToChannel,
635
726
  getUserGroupByHandle,
636
727
  updateUserGroupMembers,
637
- customApiCall,
728
+ customApiCall
638
729
  ];
730
+
639
731
  //# sourceMappingURL=actions.js.map