digital-tools 2.1.3 → 2.4.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 (294) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/CHANGELOG.md +19 -0
  3. package/README.md +2 -0
  4. package/dist/client.d.ts +109 -0
  5. package/dist/client.d.ts.map +1 -0
  6. package/dist/client.js +69 -0
  7. package/dist/client.js.map +1 -0
  8. package/dist/define.d.ts +2 -2
  9. package/dist/define.d.ts.map +1 -1
  10. package/dist/define.js +21 -11
  11. package/dist/define.js.map +1 -1
  12. package/dist/function-ref.d.ts +229 -0
  13. package/dist/function-ref.d.ts.map +1 -0
  14. package/dist/function-ref.js +28 -0
  15. package/dist/function-ref.js.map +1 -0
  16. package/dist/function-sugar.d.ts +57 -0
  17. package/dist/function-sugar.d.ts.map +1 -0
  18. package/dist/function-sugar.js +79 -0
  19. package/dist/function-sugar.js.map +1 -0
  20. package/dist/index.d.ts +10 -3
  21. package/dist/index.d.ts.map +1 -1
  22. package/dist/index.js +24 -4
  23. package/dist/index.js.map +1 -1
  24. package/dist/providers/analytics/mixpanel.d.ts.map +1 -1
  25. package/dist/providers/analytics/mixpanel.js +21 -18
  26. package/dist/providers/analytics/mixpanel.js.map +1 -1
  27. package/dist/providers/calendar/cal-com.d.ts.map +1 -1
  28. package/dist/providers/calendar/cal-com.js +10 -10
  29. package/dist/providers/calendar/cal-com.js.map +1 -1
  30. package/dist/providers/calendar/google-calendar.d.ts.map +1 -1
  31. package/dist/providers/calendar/google-calendar.js +4 -4
  32. package/dist/providers/calendar/google-calendar.js.map +1 -1
  33. package/dist/providers/crm/hubspot.d.ts.map +1 -1
  34. package/dist/providers/crm/hubspot.js +107 -85
  35. package/dist/providers/crm/hubspot.js.map +1 -1
  36. package/dist/providers/development/github.d.ts.map +1 -1
  37. package/dist/providers/development/github.js +40 -43
  38. package/dist/providers/development/github.js.map +1 -1
  39. package/dist/providers/ecommerce/shopify.d.ts.map +1 -1
  40. package/dist/providers/ecommerce/shopify.js +79 -62
  41. package/dist/providers/ecommerce/shopify.js.map +1 -1
  42. package/dist/providers/email/resend.d.ts.map +1 -1
  43. package/dist/providers/email/resend.js +20 -16
  44. package/dist/providers/email/resend.js.map +1 -1
  45. package/dist/providers/email/sendgrid.d.ts.map +1 -1
  46. package/dist/providers/email/sendgrid.js +12 -9
  47. package/dist/providers/email/sendgrid.js.map +1 -1
  48. package/dist/providers/finance/stripe.d.ts.map +1 -1
  49. package/dist/providers/finance/stripe.js +44 -42
  50. package/dist/providers/finance/stripe.js.map +1 -1
  51. package/dist/providers/forms/typeform.d.ts.map +1 -1
  52. package/dist/providers/forms/typeform.js +68 -58
  53. package/dist/providers/forms/typeform.js.map +1 -1
  54. package/dist/providers/knowledge/notion.d.ts.map +1 -1
  55. package/dist/providers/knowledge/notion.js +75 -41
  56. package/dist/providers/knowledge/notion.js.map +1 -1
  57. package/dist/providers/marketing/mailchimp.d.ts.map +1 -1
  58. package/dist/providers/marketing/mailchimp.js +74 -61
  59. package/dist/providers/marketing/mailchimp.js.map +1 -1
  60. package/dist/providers/media/cloudinary.d.ts.map +1 -1
  61. package/dist/providers/media/cloudinary.js +30 -28
  62. package/dist/providers/media/cloudinary.js.map +1 -1
  63. package/dist/providers/messaging/slack.d.ts.map +1 -1
  64. package/dist/providers/messaging/slack.js +75 -58
  65. package/dist/providers/messaging/slack.js.map +1 -1
  66. package/dist/providers/messaging/twilio-sms.d.ts.map +1 -1
  67. package/dist/providers/messaging/twilio-sms.js +33 -15
  68. package/dist/providers/messaging/twilio-sms.js.map +1 -1
  69. package/dist/providers/project-management/linear.d.ts.map +1 -1
  70. package/dist/providers/project-management/linear.js +31 -27
  71. package/dist/providers/project-management/linear.js.map +1 -1
  72. package/dist/providers/spreadsheet/google-sheets.d.ts.map +1 -1
  73. package/dist/providers/spreadsheet/google-sheets.js +21 -18
  74. package/dist/providers/spreadsheet/google-sheets.js.map +1 -1
  75. package/dist/providers/spreadsheet/xlsx.d.ts.map +1 -1
  76. package/dist/providers/spreadsheet/xlsx.js +4 -4
  77. package/dist/providers/spreadsheet/xlsx.js.map +1 -1
  78. package/dist/providers/storage/index.js +1 -0
  79. package/dist/providers/storage/index.js.map +1 -1
  80. package/dist/providers/storage/s3.d.ts.map +1 -1
  81. package/dist/providers/storage/s3.js +36 -27
  82. package/dist/providers/storage/s3.js.map +1 -1
  83. package/dist/providers/support/zendesk.d.ts.map +1 -1
  84. package/dist/providers/support/zendesk.js +24 -25
  85. package/dist/providers/support/zendesk.js.map +1 -1
  86. package/dist/providers/tasks/todoist.d.ts.map +1 -1
  87. package/dist/providers/tasks/todoist.js +18 -18
  88. package/dist/providers/tasks/todoist.js.map +1 -1
  89. package/dist/providers/video-conferencing/google-meet.d.ts.map +1 -1
  90. package/dist/providers/video-conferencing/google-meet.js +11 -11
  91. package/dist/providers/video-conferencing/google-meet.js.map +1 -1
  92. package/dist/providers/video-conferencing/jitsi.js +14 -14
  93. package/dist/providers/video-conferencing/jitsi.js.map +1 -1
  94. package/dist/providers/video-conferencing/teams.d.ts.map +1 -1
  95. package/dist/providers/video-conferencing/teams.js +9 -7
  96. package/dist/providers/video-conferencing/teams.js.map +1 -1
  97. package/dist/providers/video-conferencing/zoom.d.ts.map +1 -1
  98. package/dist/providers/video-conferencing/zoom.js +26 -24
  99. package/dist/providers/video-conferencing/zoom.js.map +1 -1
  100. package/dist/tools/data.d.ts.map +1 -1
  101. package/dist/tools/data.js +5 -12
  102. package/dist/tools/data.js.map +1 -1
  103. package/dist/tools/index.d.ts +1 -0
  104. package/dist/tools/index.d.ts.map +1 -1
  105. package/dist/tools/index.js +1 -0
  106. package/dist/tools/index.js.map +1 -1
  107. package/dist/tools/system.d.ts +289 -0
  108. package/dist/tools/system.d.ts.map +1 -0
  109. package/dist/tools/system.js +752 -0
  110. package/dist/tools/system.js.map +1 -0
  111. package/dist/tools/web.d.ts.map +1 -1
  112. package/dist/tools/web.js +22 -10
  113. package/dist/tools/web.js.map +1 -1
  114. package/dist/track-record.d.ts +101 -0
  115. package/dist/track-record.d.ts.map +1 -0
  116. package/dist/track-record.js +17 -0
  117. package/dist/track-record.js.map +1 -0
  118. package/dist/types.d.ts +210 -9
  119. package/dist/types.d.ts.map +1 -1
  120. package/dist/verb-registration.d.ts +122 -0
  121. package/dist/verb-registration.d.ts.map +1 -0
  122. package/dist/verb-registration.js +176 -0
  123. package/dist/verb-registration.js.map +1 -0
  124. package/dist/worker.d.ts +93 -0
  125. package/dist/worker.d.ts.map +1 -0
  126. package/dist/worker.js +315 -0
  127. package/dist/worker.js.map +1 -0
  128. package/dist/wrap.d.ts +89 -0
  129. package/dist/wrap.d.ts.map +1 -0
  130. package/dist/wrap.js +225 -0
  131. package/dist/wrap.js.map +1 -0
  132. package/package.json +31 -14
  133. package/src/client.ts +136 -0
  134. package/src/define.ts +30 -24
  135. package/src/function-ref.ts +264 -0
  136. package/src/function-sugar.ts +134 -0
  137. package/src/index.ts +132 -10
  138. package/src/providers/analytics/mixpanel.ts +19 -18
  139. package/src/providers/calendar/cal-com.ts +29 -18
  140. package/src/providers/calendar/google-calendar.ts +20 -14
  141. package/src/providers/crm/hubspot.ts +225 -99
  142. package/src/providers/development/github.ts +206 -135
  143. package/src/providers/ecommerce/shopify.ts +250 -89
  144. package/src/providers/email/resend.ts +101 -28
  145. package/src/providers/email/sendgrid.ts +12 -9
  146. package/src/providers/finance/stripe.ts +128 -49
  147. package/src/providers/forms/typeform.ts +74 -58
  148. package/src/providers/knowledge/notion.ts +340 -88
  149. package/src/providers/marketing/mailchimp.ts +86 -70
  150. package/src/providers/media/cloudinary.ts +99 -41
  151. package/src/providers/messaging/slack.ts +283 -85
  152. package/src/providers/messaging/twilio-sms.ts +35 -15
  153. package/src/providers/project-management/linear.ts +143 -55
  154. package/src/providers/spreadsheet/google-sheets.ts +222 -56
  155. package/src/providers/spreadsheet/xlsx.ts +47 -16
  156. package/src/providers/storage/s3.ts +119 -47
  157. package/src/providers/support/zendesk.ts +196 -46
  158. package/src/providers/tasks/todoist.ts +20 -26
  159. package/src/providers/video-conferencing/google-meet.ts +17 -20
  160. package/src/providers/video-conferencing/jitsi.ts +14 -14
  161. package/src/providers/video-conferencing/teams.ts +14 -13
  162. package/src/providers/video-conferencing/zoom.ts +54 -49
  163. package/src/tools/data.ts +6 -16
  164. package/src/tools/index.ts +1 -0
  165. package/src/tools/system.ts +887 -0
  166. package/src/tools/web.ts +22 -10
  167. package/src/track-record.ts +106 -0
  168. package/src/types.ts +241 -13
  169. package/src/verb-registration.ts +197 -0
  170. package/src/worker.ts +370 -0
  171. package/src/wrap.ts +260 -0
  172. package/test/client.test.ts +146 -0
  173. package/test/communication-tools-extended.test.ts +734 -0
  174. package/test/data-tools-extended.test.ts +743 -0
  175. package/test/define-extended.test.ts +819 -0
  176. package/test/define.test.ts +150 -41
  177. package/test/entities.test.ts +623 -0
  178. package/test/extended-entities.test.ts +1228 -0
  179. package/test/provider-implementations.test.ts +725 -0
  180. package/test/provider-registry-extended.test.ts +583 -0
  181. package/test/providers/google-sheets.test.ts +851 -0
  182. package/test/providers/helpers.ts +554 -0
  183. package/test/providers/hubspot.test.ts +576 -0
  184. package/test/providers/slack.test.ts +932 -0
  185. package/test/providers/stripe.test.ts +701 -0
  186. package/test/providers.test.ts +578 -0
  187. package/test/system-tools-extended.test.ts +632 -0
  188. package/test/system.test.ts +673 -0
  189. package/test/tools.test.ts +15 -11
  190. package/test/types.test.ts +402 -0
  191. package/test/verb-registration.test.ts +395 -0
  192. package/test/web-tools.test.ts +553 -0
  193. package/test/worker-extended.test.ts +699 -0
  194. package/test/worker.test.ts +576 -0
  195. package/test/wrap.test.ts +366 -0
  196. package/tsconfig.json +3 -13
  197. package/vitest.config.ts +37 -0
  198. package/wrangler.jsonc +9 -0
  199. package/LICENSE +0 -21
  200. package/dist/providers/voice/vapi.d.ts +0 -27
  201. package/dist/providers/voice/vapi.d.ts.map +0 -1
  202. package/dist/providers/voice/vapi.js +0 -440
  203. package/dist/providers/voice/vapi.js.map +0 -1
  204. package/src/define.js +0 -259
  205. package/src/entities/advertising.js +0 -999
  206. package/src/entities/ai.js +0 -756
  207. package/src/entities/analytics.js +0 -1588
  208. package/src/entities/automation.js +0 -601
  209. package/src/entities/communication.js +0 -1150
  210. package/src/entities/crm.js +0 -1386
  211. package/src/entities/design.js +0 -546
  212. package/src/entities/development.js +0 -2212
  213. package/src/entities/document.js +0 -874
  214. package/src/entities/ecommerce.js +0 -1429
  215. package/src/entities/experiment.js +0 -1039
  216. package/src/entities/finance.js +0 -3478
  217. package/src/entities/forms.js +0 -1892
  218. package/src/entities/hr.js +0 -661
  219. package/src/entities/identity.js +0 -997
  220. package/src/entities/index.js +0 -282
  221. package/src/entities/infrastructure.js +0 -1153
  222. package/src/entities/knowledge.js +0 -1438
  223. package/src/entities/marketing.js +0 -1610
  224. package/src/entities/media.js +0 -1634
  225. package/src/entities/notification.js +0 -1199
  226. package/src/entities/presentation.js +0 -1274
  227. package/src/entities/productivity.js +0 -1317
  228. package/src/entities/project-management.js +0 -1136
  229. package/src/entities/recruiting.js +0 -736
  230. package/src/entities/shipping.js +0 -509
  231. package/src/entities/signature.js +0 -1102
  232. package/src/entities/site.js +0 -222
  233. package/src/entities/spreadsheet.js +0 -1341
  234. package/src/entities/storage.js +0 -1198
  235. package/src/entities/support.js +0 -1166
  236. package/src/entities/video-conferencing.js +0 -1750
  237. package/src/entities/video.js +0 -950
  238. package/src/entities.js +0 -1663
  239. package/src/index.js +0 -74
  240. package/src/providers/analytics/index.js +0 -17
  241. package/src/providers/analytics/mixpanel.js +0 -255
  242. package/src/providers/calendar/cal-com.js +0 -303
  243. package/src/providers/calendar/google-calendar.js +0 -335
  244. package/src/providers/calendar/index.js +0 -20
  245. package/src/providers/crm/hubspot.js +0 -566
  246. package/src/providers/crm/index.js +0 -17
  247. package/src/providers/development/github.js +0 -472
  248. package/src/providers/development/index.js +0 -17
  249. package/src/providers/ecommerce/index.js +0 -17
  250. package/src/providers/ecommerce/shopify.js +0 -378
  251. package/src/providers/email/index.js +0 -20
  252. package/src/providers/email/resend.js +0 -258
  253. package/src/providers/email/sendgrid.js +0 -161
  254. package/src/providers/finance/index.js +0 -17
  255. package/src/providers/finance/stripe.js +0 -549
  256. package/src/providers/forms/index.js +0 -17
  257. package/src/providers/forms/typeform.js +0 -500
  258. package/src/providers/index.js +0 -123
  259. package/src/providers/knowledge/index.js +0 -17
  260. package/src/providers/knowledge/notion.js +0 -389
  261. package/src/providers/marketing/index.js +0 -17
  262. package/src/providers/marketing/mailchimp.js +0 -443
  263. package/src/providers/media/cloudinary.js +0 -318
  264. package/src/providers/media/index.js +0 -17
  265. package/src/providers/messaging/index.js +0 -20
  266. package/src/providers/messaging/slack.js +0 -393
  267. package/src/providers/messaging/twilio-sms.js +0 -249
  268. package/src/providers/project-management/index.js +0 -17
  269. package/src/providers/project-management/linear.js +0 -575
  270. package/src/providers/registry.js +0 -86
  271. package/src/providers/spreadsheet/google-sheets.js +0 -375
  272. package/src/providers/spreadsheet/index.js +0 -20
  273. package/src/providers/spreadsheet/xlsx.js +0 -423
  274. package/src/providers/storage/index.js +0 -24
  275. package/src/providers/storage/s3.js +0 -419
  276. package/src/providers/support/index.js +0 -17
  277. package/src/providers/support/zendesk.js +0 -373
  278. package/src/providers/tasks/index.js +0 -17
  279. package/src/providers/tasks/todoist.js +0 -286
  280. package/src/providers/types.js +0 -9
  281. package/src/providers/video-conferencing/google-meet.js +0 -286
  282. package/src/providers/video-conferencing/index.js +0 -31
  283. package/src/providers/video-conferencing/jitsi.js +0 -254
  284. package/src/providers/video-conferencing/teams.js +0 -270
  285. package/src/providers/video-conferencing/zoom.js +0 -332
  286. package/src/registry.js +0 -128
  287. package/src/tools/communication.js +0 -184
  288. package/src/tools/data.js +0 -205
  289. package/src/tools/index.js +0 -11
  290. package/src/tools/web.js +0 -137
  291. package/src/types.js +0 -10
  292. package/test/define.test.js +0 -306
  293. package/test/registry.test.js +0 -357
  294. package/test/tools.test.js +0 -363
@@ -56,13 +56,18 @@ export function createTwilioSmsProvider(config: ProviderConfig): SmsProvider {
56
56
  ): Promise<any> {
57
57
  const url = `${TWILIO_API_URL}/Accounts/${accountSid}${path}`
58
58
 
59
+ const headers: Record<string, string> = {
60
+ Authorization: getAuthHeader(),
61
+ }
62
+ if (body) {
63
+ headers['Content-Type'] = 'application/x-www-form-urlencoded'
64
+ }
65
+
66
+ const bodyStr = body?.toString()
59
67
  const response = await fetch(url, {
60
68
  method,
61
- headers: {
62
- Authorization: getAuthHeader(),
63
- ...(body && { 'Content-Type': 'application/x-www-form-urlencoded' }),
64
- },
65
- body: body?.toString(),
69
+ headers,
70
+ ...(bodyStr !== undefined && { body: bodyStr }),
66
71
  })
67
72
 
68
73
  return response.json()
@@ -72,10 +77,10 @@ export function createTwilioSmsProvider(config: ProviderConfig): SmsProvider {
72
77
  info: twilioSmsInfo,
73
78
 
74
79
  async initialize(cfg: ProviderConfig): Promise<void> {
75
- accountSid = cfg.accountSid as string
76
- authToken = cfg.authToken as string
77
- defaultFrom = cfg.defaultFrom as string | undefined
78
- messagingServiceSid = cfg.messagingServiceSid as string | undefined
80
+ accountSid = cfg['accountSid'] as string
81
+ authToken = cfg['authToken'] as string
82
+ defaultFrom = cfg['defaultFrom'] as string | undefined
83
+ messagingServiceSid = cfg['messagingServiceSid'] as string | undefined
79
84
 
80
85
  if (!accountSid || !authToken) {
81
86
  throw new Error('Twilio account SID and auth token are required')
@@ -112,7 +117,10 @@ export function createTwilioSmsProvider(config: ProviderConfig): SmsProvider {
112
117
  if (!from && !messagingServiceSid) {
113
118
  return {
114
119
  success: false,
115
- error: { code: 'MISSING_FROM', message: 'From number or messaging service SID is required' },
120
+ error: {
121
+ code: 'MISSING_FROM',
122
+ message: 'From number or messaging service SID is required',
123
+ },
116
124
  }
117
125
  }
118
126
 
@@ -164,7 +172,10 @@ export function createTwilioSmsProvider(config: ProviderConfig): SmsProvider {
164
172
  if (!from && !messagingServiceSid) {
165
173
  return {
166
174
  success: false,
167
- error: { code: 'MISSING_FROM', message: 'From number or messaging service SID is required' },
175
+ error: {
176
+ code: 'MISSING_FROM',
177
+ message: 'From number or messaging service SID is required',
178
+ },
168
179
  }
169
180
  }
170
181
 
@@ -240,10 +251,16 @@ export function createTwilioSmsProvider(config: ProviderConfig): SmsProvider {
240
251
  params.append('From', options.from)
241
252
  }
242
253
  if (options?.since) {
243
- params.append('DateSent>', options.since.toISOString().split('T')[0])
254
+ const sincePart = options.since.toISOString().split('T')[0]
255
+ if (sincePart) {
256
+ params.append('DateSent>', sincePart)
257
+ }
244
258
  }
245
259
  if (options?.until) {
246
- params.append('DateSent<', options.until.toISOString().split('T')[0])
260
+ const untilPart = options.until.toISOString().split('T')[0]
261
+ if (untilPart) {
262
+ params.append('DateSent<', untilPart)
263
+ }
247
264
  }
248
265
 
249
266
  const queryString = params.toString()
@@ -281,6 +298,9 @@ function mapTwilioStatus(status: string): SmsStatus['status'] {
281
298
  }
282
299
 
283
300
  function mapTwilioMessage(msg: any): SmsData {
301
+ const sentAt = msg.date_sent ? new Date(msg.date_sent) : undefined
302
+ const deliveredAt = msg.status === 'delivered' ? new Date(msg.date_updated) : undefined
303
+
284
304
  return {
285
305
  id: msg.sid,
286
306
  to: msg.to,
@@ -288,8 +308,8 @@ function mapTwilioMessage(msg: any): SmsData {
288
308
  body: msg.body,
289
309
  status: msg.status,
290
310
  direction: msg.direction === 'inbound' ? 'inbound' : 'outbound',
291
- sentAt: msg.date_sent ? new Date(msg.date_sent) : undefined,
292
- deliveredAt: msg.status === 'delivered' ? new Date(msg.date_updated) : undefined,
311
+ ...(sentAt !== undefined && { sentAt }),
312
+ ...(deliveredAt !== undefined && { deliveredAt }),
293
313
  }
294
314
  }
295
315
 
@@ -23,6 +23,93 @@ import { defineProvider } from '../registry.js'
23
23
 
24
24
  const LINEAR_API_URL = 'https://api.linear.app/graphql'
25
25
 
26
+ // =============================================================================
27
+ // Linear API Response Types
28
+ // =============================================================================
29
+
30
+ /** Linear GraphQL response wrapper */
31
+ interface LinearGraphQLResponse<T> {
32
+ data?: T
33
+ errors?: Array<{ message: string }>
34
+ }
35
+
36
+ /** Linear project from API */
37
+ interface LinearProject {
38
+ id: string
39
+ key: string
40
+ name: string
41
+ description?: string
42
+ lead?: { id: string }
43
+ url: string
44
+ }
45
+
46
+ /** Linear issue state from API */
47
+ interface LinearIssueState {
48
+ name: string
49
+ }
50
+
51
+ /** Linear label from API */
52
+ interface LinearLabel {
53
+ name: string
54
+ }
55
+
56
+ /** Linear user reference from API */
57
+ interface LinearUserRef {
58
+ id: string
59
+ }
60
+
61
+ /** Linear issue from API */
62
+ interface LinearIssue {
63
+ id: string
64
+ identifier: string
65
+ title: string
66
+ description?: string
67
+ state: LinearIssueState
68
+ priority: number
69
+ priorityLabel: string
70
+ labels: { nodes: LinearLabel[] }
71
+ assignee?: LinearUserRef
72
+ creator?: LinearUserRef
73
+ createdAt: string
74
+ updatedAt: string
75
+ url: string
76
+ }
77
+
78
+ /** Linear comment from API */
79
+ interface LinearComment {
80
+ id: string
81
+ body: string
82
+ user: LinearUserRef
83
+ createdAt: string
84
+ }
85
+
86
+ /** Linear page info from API */
87
+ interface LinearPageInfo {
88
+ hasNextPage: boolean
89
+ endCursor: string
90
+ }
91
+
92
+ /** Linear issue filter for GraphQL */
93
+ interface LinearIssueFilter {
94
+ project?: { id: { eq: string } }
95
+ state?: { name: { in: string[] } }
96
+ assignee?: { id: { eq: string } }
97
+ labels?: { name: { in: string[] } }
98
+ }
99
+
100
+ /** Linear issue create input */
101
+ interface LinearIssueCreateInput {
102
+ projectId: string
103
+ title: string
104
+ description?: string
105
+ type?: string
106
+ priority?: number
107
+ assigneeId?: string
108
+ parentId?: string
109
+ estimate?: number
110
+ labelIds?: string[]
111
+ }
112
+
26
113
  /**
27
114
  * Linear provider info
28
115
  */
@@ -40,10 +127,10 @@ export const linearInfo: ProviderInfo = {
40
127
  /**
41
128
  * GraphQL query helper
42
129
  */
43
- async function graphqlRequest<T = any>(
130
+ async function graphqlRequest<T>(
44
131
  apiKey: string,
45
132
  query: string,
46
- variables?: Record<string, any>
133
+ variables?: Record<string, unknown>
47
134
  ): Promise<T> {
48
135
  const response = await fetch(LINEAR_API_URL, {
49
136
  method: 'POST',
@@ -54,7 +141,7 @@ async function graphqlRequest<T = any>(
54
141
  body: JSON.stringify({ query, variables }),
55
142
  })
56
143
 
57
- const result = (await response.json()) as any
144
+ const result = (await response.json()) as LinearGraphQLResponse<T>
58
145
 
59
146
  if (result.errors) {
60
147
  throw new Error(result.errors[0]?.message || 'GraphQL query failed')
@@ -83,10 +170,7 @@ export function createLinearProvider(config: ProviderConfig): ProjectManagementP
83
170
  async healthCheck(): Promise<ProviderHealth> {
84
171
  const start = Date.now()
85
172
  try {
86
- await graphqlRequest(
87
- apiKey,
88
- `query { viewer { id name } }`
89
- )
173
+ await graphqlRequest(apiKey, `query { viewer { id name } }`)
90
174
 
91
175
  return {
92
176
  healthy: true,
@@ -135,19 +219,19 @@ export function createLinearProvider(config: ProviderConfig): ProjectManagementP
135
219
 
136
220
  const data = await graphqlRequest<{
137
221
  projects: {
138
- nodes: any[]
139
- pageInfo: { hasNextPage: boolean; endCursor: string }
222
+ nodes: LinearProject[]
223
+ pageInfo: LinearPageInfo
140
224
  }
141
225
  }>(apiKey, query, { first, after })
142
226
 
143
227
  return {
144
- items: data.projects.nodes.map((p: any) => ({
228
+ items: data.projects.nodes.map((p) => ({
145
229
  id: p.id,
146
230
  key: p.key,
147
231
  name: p.name,
148
- description: p.description,
149
- lead: p.lead?.id,
150
232
  url: p.url,
233
+ ...(p.description !== undefined && { description: p.description }),
234
+ ...(p.lead?.id !== undefined && { lead: p.lead.id }),
151
235
  })),
152
236
  hasMore: data.projects.pageInfo.hasNextPage,
153
237
  nextCursor: data.projects.pageInfo.endCursor,
@@ -171,7 +255,9 @@ export function createLinearProvider(config: ProviderConfig): ProjectManagementP
171
255
  `
172
256
 
173
257
  try {
174
- const data = await graphqlRequest<{ project: any }>(apiKey, query, { id: projectId })
258
+ const data = await graphqlRequest<{ project: LinearProject | null }>(apiKey, query, {
259
+ id: projectId,
260
+ })
175
261
 
176
262
  if (!data.project) {
177
263
  return null
@@ -181,9 +267,9 @@ export function createLinearProvider(config: ProviderConfig): ProjectManagementP
181
267
  id: data.project.id,
182
268
  key: data.project.key,
183
269
  name: data.project.name,
184
- description: data.project.description,
185
- lead: data.project.lead?.id,
186
270
  url: data.project.url,
271
+ ...(data.project.description !== undefined && { description: data.project.description }),
272
+ ...(data.project.lead?.id !== undefined && { lead: data.project.lead.id }),
187
273
  }
188
274
  } catch {
189
275
  return null
@@ -224,15 +310,15 @@ export function createLinearProvider(config: ProviderConfig): ProjectManagementP
224
310
  }
225
311
  `
226
312
 
227
- const input: any = {
313
+ const input: LinearIssueCreateInput = {
228
314
  projectId,
229
315
  title: issue.title,
230
- description: issue.description,
231
- ...(issue.type && { type: issue.type }),
232
- ...(issue.priority && { priority: parsePriority(issue.priority) }),
233
- ...(issue.assigneeId && { assigneeId: issue.assigneeId }),
234
- ...(issue.parentId && { parentId: issue.parentId }),
235
- ...(issue.estimate && { estimate: issue.estimate }),
316
+ ...(issue.description !== undefined && { description: issue.description }),
317
+ ...(issue.type !== undefined && { type: issue.type }),
318
+ ...(issue.priority !== undefined && { priority: parsePriority(issue.priority) }),
319
+ ...(issue.assigneeId !== undefined && { assigneeId: issue.assigneeId }),
320
+ ...(issue.parentId !== undefined && { parentId: issue.parentId }),
321
+ ...(issue.estimate !== undefined && { estimate: issue.estimate }),
236
322
  }
237
323
 
238
324
  if (issue.labels?.length) {
@@ -240,7 +326,7 @@ export function createLinearProvider(config: ProviderConfig): ProjectManagementP
240
326
  }
241
327
 
242
328
  const data = await graphqlRequest<{
243
- issueCreate: { success: boolean; issue: any }
329
+ issueCreate: { success: boolean; issue: LinearIssue }
244
330
  }>(apiKey, query, { input })
245
331
 
246
332
  if (!data.issueCreate.success) {
@@ -253,16 +339,16 @@ export function createLinearProvider(config: ProviderConfig): ProjectManagementP
253
339
  id: created.id,
254
340
  key: created.identifier,
255
341
  title: created.title,
256
- description: created.description,
257
342
  type: issue.type || 'Issue',
258
343
  status: created.state.name,
259
344
  priority: created.priorityLabel,
260
- labels: created.labels.nodes.map((l: any) => l.name),
261
- assigneeId: created.assignee?.id,
262
- reporterId: created.creator?.id,
345
+ labels: created.labels.nodes.map((l) => l.name),
263
346
  createdAt: new Date(created.createdAt),
264
347
  updatedAt: new Date(created.updatedAt),
265
348
  url: created.url,
349
+ ...(created.description !== undefined && { description: created.description }),
350
+ ...(created.assignee?.id !== undefined && { assigneeId: created.assignee.id }),
351
+ ...(created.creator?.id !== undefined && { reporterId: created.creator.id }),
266
352
  }
267
353
  },
268
354
 
@@ -298,7 +384,9 @@ export function createLinearProvider(config: ProviderConfig): ProjectManagementP
298
384
  `
299
385
 
300
386
  try {
301
- const data = await graphqlRequest<{ issue: any }>(apiKey, query, { id: issueId })
387
+ const data = await graphqlRequest<{ issue: LinearIssue | null }>(apiKey, query, {
388
+ id: issueId,
389
+ })
302
390
 
303
391
  if (!data.issue) {
304
392
  return null
@@ -310,16 +398,16 @@ export function createLinearProvider(config: ProviderConfig): ProjectManagementP
310
398
  id: issue.id,
311
399
  key: issue.identifier,
312
400
  title: issue.title,
313
- description: issue.description,
314
401
  type: 'Issue',
315
402
  status: issue.state.name,
316
403
  priority: issue.priorityLabel,
317
- labels: issue.labels.nodes.map((l: any) => l.name),
318
- assigneeId: issue.assignee?.id,
319
- reporterId: issue.creator?.id,
404
+ labels: issue.labels.nodes.map((l) => l.name),
320
405
  createdAt: new Date(issue.createdAt),
321
406
  updatedAt: new Date(issue.updatedAt),
322
407
  url: issue.url,
408
+ ...(issue.description !== undefined && { description: issue.description }),
409
+ ...(issue.assignee?.id !== undefined && { assigneeId: issue.assignee.id }),
410
+ ...(issue.creator?.id !== undefined && { reporterId: issue.creator.id }),
323
411
  }
324
412
  } catch {
325
413
  return null
@@ -360,7 +448,7 @@ export function createLinearProvider(config: ProviderConfig): ProjectManagementP
360
448
  }
361
449
  `
362
450
 
363
- const input: any = {}
451
+ const input: Partial<LinearIssueCreateInput> = {}
364
452
 
365
453
  if (updates.title) input.title = updates.title
366
454
  if (updates.description !== undefined) input.description = updates.description
@@ -369,7 +457,7 @@ export function createLinearProvider(config: ProviderConfig): ProjectManagementP
369
457
  if (updates.estimate !== undefined) input.estimate = updates.estimate
370
458
 
371
459
  const data = await graphqlRequest<{
372
- issueUpdate: { success: boolean; issue: any }
460
+ issueUpdate: { success: boolean; issue: LinearIssue }
373
461
  }>(apiKey, query, { id: issueId, input })
374
462
 
375
463
  if (!data.issueUpdate.success) {
@@ -382,16 +470,16 @@ export function createLinearProvider(config: ProviderConfig): ProjectManagementP
382
470
  id: updated.id,
383
471
  key: updated.identifier,
384
472
  title: updated.title,
385
- description: updated.description,
386
473
  type: 'Issue',
387
474
  status: updated.state.name,
388
475
  priority: updated.priorityLabel,
389
- labels: updated.labels.nodes.map((l: any) => l.name),
390
- assigneeId: updated.assignee?.id,
391
- reporterId: updated.creator?.id,
476
+ labels: updated.labels.nodes.map((l) => l.name),
392
477
  createdAt: new Date(updated.createdAt),
393
478
  updatedAt: new Date(updated.updatedAt),
394
479
  url: updated.url,
480
+ ...(updated.description !== undefined && { description: updated.description }),
481
+ ...(updated.assignee?.id !== undefined && { assigneeId: updated.assignee.id }),
482
+ ...(updated.creator?.id !== undefined && { reporterId: updated.creator.id }),
395
483
  }
396
484
  },
397
485
 
@@ -423,7 +511,7 @@ export function createLinearProvider(config: ProviderConfig): ProjectManagementP
423
511
  const after = options?.cursor
424
512
 
425
513
  // Build filter
426
- const filter: any = { project: { id: { eq: projectId } } }
514
+ const filter: LinearIssueFilter = { project: { id: { eq: projectId } } }
427
515
 
428
516
  if (options?.status?.length) {
429
517
  filter.state = { name: { in: options.status } }
@@ -475,26 +563,26 @@ export function createLinearProvider(config: ProviderConfig): ProjectManagementP
475
563
 
476
564
  const data = await graphqlRequest<{
477
565
  issues: {
478
- nodes: any[]
479
- pageInfo: { hasNextPage: boolean; endCursor: string }
566
+ nodes: LinearIssue[]
567
+ pageInfo: LinearPageInfo
480
568
  }
481
569
  }>(apiKey, query, { first, after, filter })
482
570
 
483
571
  return {
484
- items: data.issues.nodes.map((issue: any) => ({
572
+ items: data.issues.nodes.map((issue) => ({
485
573
  id: issue.id,
486
574
  key: issue.identifier,
487
575
  title: issue.title,
488
- description: issue.description,
489
576
  type: 'Issue',
490
577
  status: issue.state.name,
491
578
  priority: issue.priorityLabel,
492
- labels: issue.labels.nodes.map((l: any) => l.name),
493
- assigneeId: issue.assignee?.id,
494
- reporterId: issue.creator?.id,
579
+ labels: issue.labels.nodes.map((l) => l.name),
495
580
  createdAt: new Date(issue.createdAt),
496
581
  updatedAt: new Date(issue.updatedAt),
497
582
  url: issue.url,
583
+ ...(issue.description !== undefined && { description: issue.description }),
584
+ ...(issue.assignee?.id !== undefined && { assigneeId: issue.assignee.id }),
585
+ ...(issue.creator?.id !== undefined && { reporterId: issue.creator.id }),
498
586
  })),
499
587
  hasMore: data.issues.pageInfo.hasNextPage,
500
588
  nextCursor: data.issues.pageInfo.endCursor,
@@ -545,7 +633,7 @@ export function createLinearProvider(config: ProviderConfig): ProjectManagementP
545
633
  `
546
634
 
547
635
  // Build filter
548
- const filter: any = {}
636
+ const filter: LinearIssueFilter = {}
549
637
 
550
638
  if (options?.status?.length) {
551
639
  filter.state = { name: { in: options.status } }
@@ -561,26 +649,26 @@ export function createLinearProvider(config: ProviderConfig): ProjectManagementP
561
649
 
562
650
  const data = await graphqlRequest<{
563
651
  issueSearch: {
564
- nodes: any[]
565
- pageInfo: { hasNextPage: boolean; endCursor: string }
652
+ nodes: LinearIssue[]
653
+ pageInfo: LinearPageInfo
566
654
  }
567
655
  }>(apiKey, graphqlQuery, { first, after, query, filter })
568
656
 
569
657
  return {
570
- items: data.issueSearch.nodes.map((issue: any) => ({
658
+ items: data.issueSearch.nodes.map((issue) => ({
571
659
  id: issue.id,
572
660
  key: issue.identifier,
573
661
  title: issue.title,
574
- description: issue.description,
575
662
  type: 'Issue',
576
663
  status: issue.state.name,
577
664
  priority: issue.priorityLabel,
578
- labels: issue.labels.nodes.map((l: any) => l.name),
579
- assigneeId: issue.assignee?.id,
580
- reporterId: issue.creator?.id,
665
+ labels: issue.labels.nodes.map((l) => l.name),
581
666
  createdAt: new Date(issue.createdAt),
582
667
  updatedAt: new Date(issue.updatedAt),
583
668
  url: issue.url,
669
+ ...(issue.description !== undefined && { description: issue.description }),
670
+ ...(issue.assignee?.id !== undefined && { assigneeId: issue.assignee.id }),
671
+ ...(issue.creator?.id !== undefined && { reporterId: issue.creator.id }),
584
672
  })),
585
673
  hasMore: data.issueSearch.pageInfo.hasNextPage,
586
674
  nextCursor: data.issueSearch.pageInfo.endCursor,
@@ -605,7 +693,7 @@ export function createLinearProvider(config: ProviderConfig): ProjectManagementP
605
693
  `
606
694
 
607
695
  const data = await graphqlRequest<{
608
- commentCreate: { success: boolean; comment: any }
696
+ commentCreate: { success: boolean; comment: LinearComment }
609
697
  }>(apiKey, query, {
610
698
  input: {
611
699
  issueId,