digital-tools 2.1.1 → 2.3.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 (293) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/README.md +2 -0
  3. package/dist/client.d.ts +109 -0
  4. package/dist/client.d.ts.map +1 -0
  5. package/dist/client.js +69 -0
  6. package/dist/client.js.map +1 -0
  7. package/dist/define.d.ts +2 -2
  8. package/dist/define.d.ts.map +1 -1
  9. package/dist/define.js +22 -20
  10. package/dist/define.js.map +1 -1
  11. package/dist/function-ref.d.ts +229 -0
  12. package/dist/function-ref.d.ts.map +1 -0
  13. package/dist/function-ref.js +28 -0
  14. package/dist/function-ref.js.map +1 -0
  15. package/dist/function-sugar.d.ts +57 -0
  16. package/dist/function-sugar.d.ts.map +1 -0
  17. package/dist/function-sugar.js +79 -0
  18. package/dist/function-sugar.js.map +1 -0
  19. package/dist/index.d.ts +10 -3
  20. package/dist/index.d.ts.map +1 -1
  21. package/dist/index.js +24 -4
  22. package/dist/index.js.map +1 -1
  23. package/dist/providers/analytics/mixpanel.d.ts.map +1 -1
  24. package/dist/providers/analytics/mixpanel.js +21 -18
  25. package/dist/providers/analytics/mixpanel.js.map +1 -1
  26. package/dist/providers/calendar/cal-com.d.ts.map +1 -1
  27. package/dist/providers/calendar/cal-com.js +10 -10
  28. package/dist/providers/calendar/cal-com.js.map +1 -1
  29. package/dist/providers/calendar/google-calendar.d.ts.map +1 -1
  30. package/dist/providers/calendar/google-calendar.js +4 -4
  31. package/dist/providers/calendar/google-calendar.js.map +1 -1
  32. package/dist/providers/crm/hubspot.d.ts.map +1 -1
  33. package/dist/providers/crm/hubspot.js +107 -85
  34. package/dist/providers/crm/hubspot.js.map +1 -1
  35. package/dist/providers/development/github.d.ts.map +1 -1
  36. package/dist/providers/development/github.js +40 -43
  37. package/dist/providers/development/github.js.map +1 -1
  38. package/dist/providers/ecommerce/shopify.d.ts.map +1 -1
  39. package/dist/providers/ecommerce/shopify.js +79 -62
  40. package/dist/providers/ecommerce/shopify.js.map +1 -1
  41. package/dist/providers/email/resend.d.ts.map +1 -1
  42. package/dist/providers/email/resend.js +20 -16
  43. package/dist/providers/email/resend.js.map +1 -1
  44. package/dist/providers/email/sendgrid.d.ts.map +1 -1
  45. package/dist/providers/email/sendgrid.js +12 -9
  46. package/dist/providers/email/sendgrid.js.map +1 -1
  47. package/dist/providers/finance/stripe.d.ts.map +1 -1
  48. package/dist/providers/finance/stripe.js +44 -42
  49. package/dist/providers/finance/stripe.js.map +1 -1
  50. package/dist/providers/forms/typeform.d.ts.map +1 -1
  51. package/dist/providers/forms/typeform.js +68 -58
  52. package/dist/providers/forms/typeform.js.map +1 -1
  53. package/dist/providers/knowledge/notion.d.ts.map +1 -1
  54. package/dist/providers/knowledge/notion.js +75 -41
  55. package/dist/providers/knowledge/notion.js.map +1 -1
  56. package/dist/providers/marketing/mailchimp.d.ts.map +1 -1
  57. package/dist/providers/marketing/mailchimp.js +74 -61
  58. package/dist/providers/marketing/mailchimp.js.map +1 -1
  59. package/dist/providers/media/cloudinary.d.ts.map +1 -1
  60. package/dist/providers/media/cloudinary.js +30 -28
  61. package/dist/providers/media/cloudinary.js.map +1 -1
  62. package/dist/providers/messaging/slack.d.ts.map +1 -1
  63. package/dist/providers/messaging/slack.js +75 -58
  64. package/dist/providers/messaging/slack.js.map +1 -1
  65. package/dist/providers/messaging/twilio-sms.d.ts.map +1 -1
  66. package/dist/providers/messaging/twilio-sms.js +33 -15
  67. package/dist/providers/messaging/twilio-sms.js.map +1 -1
  68. package/dist/providers/project-management/linear.d.ts.map +1 -1
  69. package/dist/providers/project-management/linear.js +31 -27
  70. package/dist/providers/project-management/linear.js.map +1 -1
  71. package/dist/providers/spreadsheet/google-sheets.d.ts.map +1 -1
  72. package/dist/providers/spreadsheet/google-sheets.js +21 -18
  73. package/dist/providers/spreadsheet/google-sheets.js.map +1 -1
  74. package/dist/providers/spreadsheet/xlsx.d.ts.map +1 -1
  75. package/dist/providers/spreadsheet/xlsx.js +4 -4
  76. package/dist/providers/spreadsheet/xlsx.js.map +1 -1
  77. package/dist/providers/storage/index.js +1 -0
  78. package/dist/providers/storage/index.js.map +1 -1
  79. package/dist/providers/storage/s3.d.ts.map +1 -1
  80. package/dist/providers/storage/s3.js +36 -27
  81. package/dist/providers/storage/s3.js.map +1 -1
  82. package/dist/providers/support/zendesk.d.ts.map +1 -1
  83. package/dist/providers/support/zendesk.js +24 -25
  84. package/dist/providers/support/zendesk.js.map +1 -1
  85. package/dist/providers/tasks/todoist.d.ts.map +1 -1
  86. package/dist/providers/tasks/todoist.js +18 -18
  87. package/dist/providers/tasks/todoist.js.map +1 -1
  88. package/dist/providers/video-conferencing/google-meet.d.ts.map +1 -1
  89. package/dist/providers/video-conferencing/google-meet.js +11 -11
  90. package/dist/providers/video-conferencing/google-meet.js.map +1 -1
  91. package/dist/providers/video-conferencing/jitsi.js +14 -14
  92. package/dist/providers/video-conferencing/jitsi.js.map +1 -1
  93. package/dist/providers/video-conferencing/teams.d.ts.map +1 -1
  94. package/dist/providers/video-conferencing/teams.js +9 -7
  95. package/dist/providers/video-conferencing/teams.js.map +1 -1
  96. package/dist/providers/video-conferencing/zoom.d.ts.map +1 -1
  97. package/dist/providers/video-conferencing/zoom.js +26 -24
  98. package/dist/providers/video-conferencing/zoom.js.map +1 -1
  99. package/dist/tools/data.d.ts.map +1 -1
  100. package/dist/tools/data.js +5 -12
  101. package/dist/tools/data.js.map +1 -1
  102. package/dist/tools/index.d.ts +1 -0
  103. package/dist/tools/index.d.ts.map +1 -1
  104. package/dist/tools/index.js +1 -0
  105. package/dist/tools/index.js.map +1 -1
  106. package/dist/tools/system.d.ts +289 -0
  107. package/dist/tools/system.d.ts.map +1 -0
  108. package/dist/tools/system.js +752 -0
  109. package/dist/tools/system.js.map +1 -0
  110. package/dist/tools/web.d.ts.map +1 -1
  111. package/dist/tools/web.js +22 -10
  112. package/dist/tools/web.js.map +1 -1
  113. package/dist/track-record.d.ts +101 -0
  114. package/dist/track-record.d.ts.map +1 -0
  115. package/dist/track-record.js +17 -0
  116. package/dist/track-record.js.map +1 -0
  117. package/dist/types.d.ts +210 -9
  118. package/dist/types.d.ts.map +1 -1
  119. package/dist/verb-registration.d.ts +122 -0
  120. package/dist/verb-registration.d.ts.map +1 -0
  121. package/dist/verb-registration.js +176 -0
  122. package/dist/verb-registration.js.map +1 -0
  123. package/dist/worker.d.ts +93 -0
  124. package/dist/worker.d.ts.map +1 -0
  125. package/dist/worker.js +315 -0
  126. package/dist/worker.js.map +1 -0
  127. package/dist/wrap.d.ts +89 -0
  128. package/dist/wrap.d.ts.map +1 -0
  129. package/dist/wrap.js +225 -0
  130. package/dist/wrap.js.map +1 -0
  131. package/package.json +21 -4
  132. package/src/client.ts +136 -0
  133. package/src/define.ts +31 -37
  134. package/src/function-ref.ts +264 -0
  135. package/src/function-sugar.ts +134 -0
  136. package/src/index.ts +132 -10
  137. package/src/providers/analytics/mixpanel.ts +19 -18
  138. package/src/providers/calendar/cal-com.ts +29 -18
  139. package/src/providers/calendar/google-calendar.ts +20 -14
  140. package/src/providers/crm/hubspot.ts +225 -99
  141. package/src/providers/development/github.ts +206 -135
  142. package/src/providers/ecommerce/shopify.ts +250 -89
  143. package/src/providers/email/resend.ts +101 -28
  144. package/src/providers/email/sendgrid.ts +12 -9
  145. package/src/providers/finance/stripe.ts +128 -49
  146. package/src/providers/forms/typeform.ts +74 -58
  147. package/src/providers/knowledge/notion.ts +340 -88
  148. package/src/providers/marketing/mailchimp.ts +86 -70
  149. package/src/providers/media/cloudinary.ts +99 -41
  150. package/src/providers/messaging/slack.ts +283 -85
  151. package/src/providers/messaging/twilio-sms.ts +35 -15
  152. package/src/providers/project-management/linear.ts +143 -55
  153. package/src/providers/spreadsheet/google-sheets.ts +222 -56
  154. package/src/providers/spreadsheet/xlsx.ts +47 -16
  155. package/src/providers/storage/s3.ts +119 -47
  156. package/src/providers/support/zendesk.ts +196 -46
  157. package/src/providers/tasks/todoist.ts +20 -26
  158. package/src/providers/video-conferencing/google-meet.ts +17 -20
  159. package/src/providers/video-conferencing/jitsi.ts +14 -14
  160. package/src/providers/video-conferencing/teams.ts +14 -13
  161. package/src/providers/video-conferencing/zoom.ts +54 -49
  162. package/src/tools/data.ts +6 -16
  163. package/src/tools/index.ts +1 -0
  164. package/src/tools/system.ts +887 -0
  165. package/src/tools/web.ts +22 -10
  166. package/src/track-record.ts +106 -0
  167. package/src/types.ts +241 -13
  168. package/src/verb-registration.ts +197 -0
  169. package/src/worker.ts +370 -0
  170. package/src/wrap.ts +260 -0
  171. package/test/client.test.ts +146 -0
  172. package/test/communication-tools-extended.test.ts +734 -0
  173. package/test/data-tools-extended.test.ts +743 -0
  174. package/test/define-extended.test.ts +819 -0
  175. package/test/define.test.ts +150 -41
  176. package/test/entities.test.ts +623 -0
  177. package/test/extended-entities.test.ts +1228 -0
  178. package/test/provider-implementations.test.ts +725 -0
  179. package/test/provider-registry-extended.test.ts +583 -0
  180. package/test/providers/google-sheets.test.ts +851 -0
  181. package/test/providers/helpers.ts +554 -0
  182. package/test/providers/hubspot.test.ts +576 -0
  183. package/test/providers/slack.test.ts +932 -0
  184. package/test/providers/stripe.test.ts +701 -0
  185. package/test/providers.test.ts +578 -0
  186. package/test/system-tools-extended.test.ts +632 -0
  187. package/test/system.test.ts +673 -0
  188. package/test/tools.test.ts +15 -11
  189. package/test/types.test.ts +402 -0
  190. package/test/verb-registration.test.ts +395 -0
  191. package/test/web-tools.test.ts +553 -0
  192. package/test/worker-extended.test.ts +699 -0
  193. package/test/worker.test.ts +576 -0
  194. package/test/wrap.test.ts +366 -0
  195. package/tsconfig.json +3 -13
  196. package/vitest.config.ts +37 -0
  197. package/wrangler.jsonc +9 -0
  198. package/.turbo/turbo-build.log +0 -5
  199. package/dist/providers/voice/vapi.d.ts +0 -27
  200. package/dist/providers/voice/vapi.d.ts.map +0 -1
  201. package/dist/providers/voice/vapi.js +0 -440
  202. package/dist/providers/voice/vapi.js.map +0 -1
  203. package/src/define.js +0 -267
  204. package/src/entities/advertising.js +0 -999
  205. package/src/entities/ai.js +0 -756
  206. package/src/entities/analytics.js +0 -1588
  207. package/src/entities/automation.js +0 -601
  208. package/src/entities/communication.js +0 -1150
  209. package/src/entities/crm.js +0 -1386
  210. package/src/entities/design.js +0 -546
  211. package/src/entities/development.js +0 -2212
  212. package/src/entities/document.js +0 -874
  213. package/src/entities/ecommerce.js +0 -1429
  214. package/src/entities/experiment.js +0 -1039
  215. package/src/entities/finance.js +0 -3478
  216. package/src/entities/forms.js +0 -1892
  217. package/src/entities/hr.js +0 -661
  218. package/src/entities/identity.js +0 -997
  219. package/src/entities/index.js +0 -282
  220. package/src/entities/infrastructure.js +0 -1153
  221. package/src/entities/knowledge.js +0 -1438
  222. package/src/entities/marketing.js +0 -1610
  223. package/src/entities/media.js +0 -1634
  224. package/src/entities/notification.js +0 -1199
  225. package/src/entities/presentation.js +0 -1274
  226. package/src/entities/productivity.js +0 -1317
  227. package/src/entities/project-management.js +0 -1136
  228. package/src/entities/recruiting.js +0 -736
  229. package/src/entities/shipping.js +0 -509
  230. package/src/entities/signature.js +0 -1102
  231. package/src/entities/site.js +0 -222
  232. package/src/entities/spreadsheet.js +0 -1341
  233. package/src/entities/storage.js +0 -1198
  234. package/src/entities/support.js +0 -1166
  235. package/src/entities/video-conferencing.js +0 -1750
  236. package/src/entities/video.js +0 -950
  237. package/src/entities.js +0 -1663
  238. package/src/index.js +0 -74
  239. package/src/providers/analytics/index.js +0 -17
  240. package/src/providers/analytics/mixpanel.js +0 -255
  241. package/src/providers/calendar/cal-com.js +0 -303
  242. package/src/providers/calendar/google-calendar.js +0 -335
  243. package/src/providers/calendar/index.js +0 -20
  244. package/src/providers/crm/hubspot.js +0 -566
  245. package/src/providers/crm/index.js +0 -17
  246. package/src/providers/development/github.js +0 -472
  247. package/src/providers/development/index.js +0 -17
  248. package/src/providers/ecommerce/index.js +0 -17
  249. package/src/providers/ecommerce/shopify.js +0 -378
  250. package/src/providers/email/index.js +0 -20
  251. package/src/providers/email/resend.js +0 -258
  252. package/src/providers/email/sendgrid.js +0 -161
  253. package/src/providers/finance/index.js +0 -17
  254. package/src/providers/finance/stripe.js +0 -549
  255. package/src/providers/forms/index.js +0 -17
  256. package/src/providers/forms/typeform.js +0 -500
  257. package/src/providers/index.js +0 -123
  258. package/src/providers/knowledge/index.js +0 -17
  259. package/src/providers/knowledge/notion.js +0 -389
  260. package/src/providers/marketing/index.js +0 -17
  261. package/src/providers/marketing/mailchimp.js +0 -443
  262. package/src/providers/media/cloudinary.js +0 -318
  263. package/src/providers/media/index.js +0 -17
  264. package/src/providers/messaging/index.js +0 -20
  265. package/src/providers/messaging/slack.js +0 -393
  266. package/src/providers/messaging/twilio-sms.js +0 -249
  267. package/src/providers/project-management/index.js +0 -17
  268. package/src/providers/project-management/linear.js +0 -575
  269. package/src/providers/registry.js +0 -86
  270. package/src/providers/spreadsheet/google-sheets.js +0 -375
  271. package/src/providers/spreadsheet/index.js +0 -20
  272. package/src/providers/spreadsheet/xlsx.js +0 -423
  273. package/src/providers/storage/index.js +0 -24
  274. package/src/providers/storage/s3.js +0 -419
  275. package/src/providers/support/index.js +0 -17
  276. package/src/providers/support/zendesk.js +0 -373
  277. package/src/providers/tasks/index.js +0 -17
  278. package/src/providers/tasks/todoist.js +0 -286
  279. package/src/providers/types.js +0 -9
  280. package/src/providers/video-conferencing/google-meet.js +0 -286
  281. package/src/providers/video-conferencing/index.js +0 -31
  282. package/src/providers/video-conferencing/jitsi.js +0 -254
  283. package/src/providers/video-conferencing/teams.js +0 -270
  284. package/src/providers/video-conferencing/zoom.js +0 -332
  285. package/src/registry.js +0 -128
  286. package/src/tools/communication.js +0 -184
  287. package/src/tools/data.js +0 -205
  288. package/src/tools/index.js +0 -11
  289. package/src/tools/web.js +0 -137
  290. package/src/types.js +0 -10
  291. package/test/define.test.js +0 -306
  292. package/test/registry.test.js +0 -357
  293. package/test/tools.test.js +0 -363
@@ -0,0 +1,578 @@
1
+ /**
2
+ * Tests for Provider Registry and Provider Definitions
3
+ *
4
+ * Covers provider registration, discovery, and instantiation.
5
+ */
6
+
7
+ import { describe, it, expect, beforeEach } from 'vitest'
8
+ import {
9
+ // Provider registry
10
+ providerRegistry,
11
+ createProviderRegistry,
12
+ registerProvider,
13
+ getProvider,
14
+ listProviders,
15
+ defineProvider,
16
+
17
+ // Provider info exports
18
+ sendgridInfo,
19
+ resendInfo,
20
+ slackInfo,
21
+ twilioSmsInfo,
22
+ xlsxInfo,
23
+ googleSheetsInfo,
24
+ cloudinaryInfo,
25
+ todoistInfo,
26
+ stripeInfo,
27
+ zendeskInfo,
28
+ linearInfo,
29
+ notionInfo,
30
+ hubspotInfo,
31
+ shopifyInfo,
32
+ githubInfo,
33
+ typeformInfo,
34
+ mixpanelInfo,
35
+ zoomInfo,
36
+ googleMeetInfo,
37
+ teamsInfo,
38
+ jitsiInfo,
39
+ googleCalendarInfo,
40
+ s3Info,
41
+
42
+ // Registration helpers
43
+ registerAllProviders,
44
+ registerEmailProviders,
45
+ registerMessagingProviders,
46
+ registerSpreadsheetProviders,
47
+
48
+ // Provider collections
49
+ allProviders,
50
+ } from '../src/providers/index.js'
51
+
52
+ import type {
53
+ BaseProvider,
54
+ ProviderCategory,
55
+ ProviderConfig,
56
+ ProviderInfo,
57
+ ProviderHealth,
58
+ EmailProvider,
59
+ MessagingProvider,
60
+ SpreadsheetProvider,
61
+ } from '../src/providers/types.js'
62
+
63
+ describe('Provider Registry', () => {
64
+ describe('createProviderRegistry', () => {
65
+ it('creates an isolated registry', () => {
66
+ const registry = createProviderRegistry()
67
+
68
+ expect(registry.list()).toHaveLength(0)
69
+ })
70
+
71
+ it('registries are independent', () => {
72
+ const registry1 = createProviderRegistry()
73
+ const registry2 = createProviderRegistry()
74
+
75
+ const mockInfo: ProviderInfo = {
76
+ id: 'test.provider',
77
+ name: 'Test Provider',
78
+ description: 'Test',
79
+ category: 'email',
80
+ requiredConfig: [],
81
+ }
82
+
83
+ registry1.register(mockInfo, async () => createMockProvider(mockInfo))
84
+
85
+ expect(registry1.has('test.provider')).toBe(true)
86
+ expect(registry2.has('test.provider')).toBe(false)
87
+ })
88
+ })
89
+
90
+ describe('register', () => {
91
+ it('registers a provider', () => {
92
+ const registry = createProviderRegistry()
93
+
94
+ const mockInfo: ProviderInfo = {
95
+ id: 'mock.email',
96
+ name: 'Mock Email',
97
+ description: 'A mock email provider',
98
+ category: 'email',
99
+ requiredConfig: ['apiKey'],
100
+ }
101
+
102
+ registry.register(mockInfo, async (config) => createMockProvider(mockInfo))
103
+
104
+ expect(registry.has('mock.email')).toBe(true)
105
+ })
106
+
107
+ it('throws on duplicate registration', () => {
108
+ const registry = createProviderRegistry()
109
+
110
+ const mockInfo: ProviderInfo = {
111
+ id: 'duplicate.provider',
112
+ name: 'Duplicate',
113
+ description: 'Test',
114
+ category: 'email',
115
+ requiredConfig: [],
116
+ }
117
+
118
+ registry.register(mockInfo, async () => createMockProvider(mockInfo))
119
+
120
+ expect(() => {
121
+ registry.register(mockInfo, async () => createMockProvider(mockInfo))
122
+ }).toThrow("Provider 'duplicate.provider' is already registered")
123
+ })
124
+ })
125
+
126
+ describe('get', () => {
127
+ it('returns registered provider', () => {
128
+ const registry = createProviderRegistry()
129
+
130
+ const mockInfo: ProviderInfo = {
131
+ id: 'get.test',
132
+ name: 'Get Test',
133
+ description: 'Test',
134
+ category: 'messaging',
135
+ requiredConfig: [],
136
+ }
137
+
138
+ registry.register(mockInfo, async () => createMockProvider(mockInfo))
139
+
140
+ const result = registry.get('get.test')
141
+
142
+ expect(result).toBeDefined()
143
+ expect(result?.info.id).toBe('get.test')
144
+ expect(result?.info.category).toBe('messaging')
145
+ })
146
+
147
+ it('returns undefined for non-existent provider', () => {
148
+ const registry = createProviderRegistry()
149
+
150
+ expect(registry.get('non.existent')).toBeUndefined()
151
+ })
152
+ })
153
+
154
+ describe('list', () => {
155
+ it('returns all providers', () => {
156
+ const registry = createProviderRegistry()
157
+
158
+ registry.register(
159
+ { id: 'list.a', name: 'A', description: 'A', category: 'email', requiredConfig: [] },
160
+ async (config) => createMockProvider({ id: 'list.a', name: 'A', description: 'A', category: 'email', requiredConfig: [] })
161
+ )
162
+ registry.register(
163
+ { id: 'list.b', name: 'B', description: 'B', category: 'messaging', requiredConfig: [] },
164
+ async (config) => createMockProvider({ id: 'list.b', name: 'B', description: 'B', category: 'messaging', requiredConfig: [] })
165
+ )
166
+
167
+ const all = registry.list()
168
+
169
+ expect(all).toHaveLength(2)
170
+ })
171
+
172
+ it('filters by category', () => {
173
+ const registry = createProviderRegistry()
174
+
175
+ registry.register(
176
+ { id: 'cat.email', name: 'Email', description: 'Email', category: 'email', requiredConfig: [] },
177
+ async () => createMockProvider({ id: 'cat.email', name: 'Email', description: 'Email', category: 'email', requiredConfig: [] })
178
+ )
179
+ registry.register(
180
+ { id: 'cat.sms', name: 'SMS', description: 'SMS', category: 'messaging', requiredConfig: [] },
181
+ async () => createMockProvider({ id: 'cat.sms', name: 'SMS', description: 'SMS', category: 'messaging', requiredConfig: [] })
182
+ )
183
+ registry.register(
184
+ { id: 'cat.email2', name: 'Email2', description: 'Email2', category: 'email', requiredConfig: [] },
185
+ async () => createMockProvider({ id: 'cat.email2', name: 'Email2', description: 'Email2', category: 'email', requiredConfig: [] })
186
+ )
187
+
188
+ const emailProviders = registry.list('email')
189
+
190
+ expect(emailProviders).toHaveLength(2)
191
+ expect(emailProviders.every((p) => p.info.category === 'email')).toBe(true)
192
+ })
193
+ })
194
+
195
+ describe('create', () => {
196
+ it('creates provider instance', async () => {
197
+ const registry = createProviderRegistry()
198
+
199
+ const mockInfo: ProviderInfo = {
200
+ id: 'create.test',
201
+ name: 'Create Test',
202
+ description: 'Test',
203
+ category: 'email',
204
+ requiredConfig: [],
205
+ }
206
+
207
+ registry.register(mockInfo, async (config) => createMockProvider(mockInfo))
208
+
209
+ const provider = await registry.create('create.test', {})
210
+
211
+ expect(provider.info.id).toBe('create.test')
212
+ })
213
+
214
+ it('throws for non-existent provider', async () => {
215
+ const registry = createProviderRegistry()
216
+
217
+ await expect(registry.create('non.existent', {})).rejects.toThrow(
218
+ "Provider 'non.existent' not found"
219
+ )
220
+ })
221
+
222
+ it('validates required config', async () => {
223
+ const registry = createProviderRegistry()
224
+
225
+ const mockInfo: ProviderInfo = {
226
+ id: 'config.test',
227
+ name: 'Config Test',
228
+ description: 'Test',
229
+ category: 'email',
230
+ requiredConfig: ['apiKey', 'apiSecret'],
231
+ }
232
+
233
+ registry.register(mockInfo, async (config) => createMockProvider(mockInfo))
234
+
235
+ await expect(registry.create('config.test', { apiKey: 'key' })).rejects.toThrow(
236
+ "missing required config: apiSecret"
237
+ )
238
+ })
239
+
240
+ it('passes config to factory', async () => {
241
+ const registry = createProviderRegistry()
242
+ let receivedConfig: ProviderConfig | undefined
243
+
244
+ const mockInfo: ProviderInfo = {
245
+ id: 'factory.test',
246
+ name: 'Factory Test',
247
+ description: 'Test',
248
+ category: 'email',
249
+ requiredConfig: ['apiKey'],
250
+ }
251
+
252
+ registry.register(mockInfo, async (config) => {
253
+ receivedConfig = config
254
+ return createMockProvider(mockInfo)
255
+ })
256
+
257
+ await registry.create('factory.test', { apiKey: 'test-key' })
258
+
259
+ expect(receivedConfig?.apiKey).toBe('test-key')
260
+ })
261
+ })
262
+
263
+ describe('has', () => {
264
+ it('returns true for registered provider', () => {
265
+ const registry = createProviderRegistry()
266
+
267
+ registry.register(
268
+ { id: 'has.test', name: 'Has', description: 'Has', category: 'email', requiredConfig: [] },
269
+ async () => createMockProvider({ id: 'has.test', name: 'Has', description: 'Has', category: 'email', requiredConfig: [] })
270
+ )
271
+
272
+ expect(registry.has('has.test')).toBe(true)
273
+ })
274
+
275
+ it('returns false for non-existent provider', () => {
276
+ const registry = createProviderRegistry()
277
+
278
+ expect(registry.has('non.existent')).toBe(false)
279
+ })
280
+ })
281
+ })
282
+
283
+ describe('defineProvider', () => {
284
+ it('creates provider definition', () => {
285
+ const mockInfo: ProviderInfo = {
286
+ id: 'define.test',
287
+ name: 'Define Test',
288
+ description: 'Test',
289
+ category: 'email',
290
+ requiredConfig: [],
291
+ }
292
+
293
+ const definition = defineProvider(mockInfo, async () => createMockProvider(mockInfo))
294
+
295
+ expect(definition.info).toBe(mockInfo)
296
+ expect(typeof definition.factory).toBe('function')
297
+ expect(typeof definition.register).toBe('function')
298
+ })
299
+ })
300
+
301
+ describe('Provider Info Exports', () => {
302
+ describe('Email Providers', () => {
303
+ it('sendgrid info is valid', () => {
304
+ expect(sendgridInfo.id).toBe('email.sendgrid')
305
+ expect(sendgridInfo.name).toBe('SendGrid')
306
+ expect(sendgridInfo.category).toBe('email')
307
+ expect(sendgridInfo.requiredConfig).toContain('apiKey')
308
+ })
309
+
310
+ it('resend info is valid', () => {
311
+ expect(resendInfo.id).toBe('email.resend')
312
+ expect(resendInfo.name).toBe('Resend')
313
+ expect(resendInfo.category).toBe('email')
314
+ expect(resendInfo.requiredConfig).toContain('apiKey')
315
+ })
316
+ })
317
+
318
+ describe('Messaging Providers', () => {
319
+ it('slack info is valid', () => {
320
+ expect(slackInfo.id).toBe('messaging.slack')
321
+ expect(slackInfo.name).toBe('Slack')
322
+ expect(slackInfo.category).toBe('messaging')
323
+ expect(slackInfo.requiredConfig).toContain('accessToken')
324
+ })
325
+
326
+ it('twilio sms info is valid', () => {
327
+ expect(twilioSmsInfo.id).toBe('messaging.twilio-sms')
328
+ expect(twilioSmsInfo.name).toBe('Twilio SMS')
329
+ expect(twilioSmsInfo.category).toBe('messaging')
330
+ expect(twilioSmsInfo.requiredConfig).toContain('accountSid')
331
+ expect(twilioSmsInfo.requiredConfig).toContain('authToken')
332
+ })
333
+ })
334
+
335
+ describe('Spreadsheet Providers', () => {
336
+ it('xlsx info is valid', () => {
337
+ expect(xlsxInfo.id).toBe('spreadsheet.xlsx')
338
+ expect(xlsxInfo.name).toBe('XLSX (SheetJS)')
339
+ expect(xlsxInfo.category).toBe('spreadsheet')
340
+ expect(xlsxInfo.requiredConfig).toHaveLength(0) // No required config for local xlsx
341
+ })
342
+
343
+ it('google sheets info is valid', () => {
344
+ expect(googleSheetsInfo.id).toBe('spreadsheet.google-sheets')
345
+ expect(googleSheetsInfo.name).toBe('Google Sheets')
346
+ expect(googleSheetsInfo.category).toBe('spreadsheet')
347
+ })
348
+ })
349
+
350
+ describe('Media Providers', () => {
351
+ it('cloudinary info is valid', () => {
352
+ expect(cloudinaryInfo.id).toBe('media.cloudinary')
353
+ expect(cloudinaryInfo.name).toBe('Cloudinary')
354
+ expect(cloudinaryInfo.category).toBe('media')
355
+ expect(cloudinaryInfo.requiredConfig).toContain('cloudName')
356
+ expect(cloudinaryInfo.requiredConfig).toContain('apiKey')
357
+ expect(cloudinaryInfo.requiredConfig).toContain('apiSecret')
358
+ })
359
+ })
360
+
361
+ describe('Task Providers', () => {
362
+ it('todoist info is valid', () => {
363
+ expect(todoistInfo.id).toBe('tasks.todoist')
364
+ expect(todoistInfo.name).toBe('Todoist')
365
+ expect(todoistInfo.category).toBe('tasks')
366
+ expect(todoistInfo.requiredConfig).toContain('apiKey')
367
+ })
368
+ })
369
+
370
+ describe('Finance Providers', () => {
371
+ it('stripe info is valid', () => {
372
+ expect(stripeInfo.id).toBe('finance.stripe')
373
+ expect(stripeInfo.name).toBe('Stripe')
374
+ expect(stripeInfo.category).toBe('finance')
375
+ expect(stripeInfo.requiredConfig).toContain('apiKey')
376
+ })
377
+ })
378
+
379
+ describe('Support Providers', () => {
380
+ it('zendesk info is valid', () => {
381
+ expect(zendeskInfo.id).toBe('support.zendesk')
382
+ expect(zendeskInfo.name).toBe('Zendesk')
383
+ expect(zendeskInfo.category).toBe('support')
384
+ expect(zendeskInfo.requiredConfig).toContain('subdomain')
385
+ })
386
+ })
387
+
388
+ describe('Project Management Providers', () => {
389
+ it('linear info is valid', () => {
390
+ expect(linearInfo.id).toBe('project-management.linear')
391
+ expect(linearInfo.name).toBe('Linear')
392
+ expect(linearInfo.category).toBe('project-management')
393
+ expect(linearInfo.requiredConfig).toContain('apiKey')
394
+ })
395
+ })
396
+
397
+ describe('Knowledge Providers', () => {
398
+ it('notion info is valid', () => {
399
+ expect(notionInfo.id).toBe('knowledge.notion')
400
+ expect(notionInfo.name).toBe('Notion')
401
+ expect(notionInfo.category).toBe('knowledge')
402
+ expect(notionInfo.requiredConfig).toContain('integrationToken')
403
+ })
404
+ })
405
+
406
+ describe('CRM Providers', () => {
407
+ it('hubspot info is valid', () => {
408
+ expect(hubspotInfo.id).toBe('crm.hubspot')
409
+ expect(hubspotInfo.name).toBe('HubSpot')
410
+ expect(hubspotInfo.category).toBe('crm')
411
+ expect(hubspotInfo.requiredConfig).toContain('accessToken')
412
+ })
413
+ })
414
+
415
+ describe('E-commerce Providers', () => {
416
+ it('shopify info is valid', () => {
417
+ expect(shopifyInfo.id).toBe('ecommerce.shopify')
418
+ expect(shopifyInfo.name).toBe('Shopify')
419
+ expect(shopifyInfo.category).toBe('ecommerce')
420
+ expect(shopifyInfo.requiredConfig).toContain('shopDomain')
421
+ expect(shopifyInfo.requiredConfig).toContain('accessToken')
422
+ })
423
+ })
424
+
425
+ describe('Development Providers', () => {
426
+ it('github info is valid', () => {
427
+ expect(githubInfo.id).toBe('development.github')
428
+ expect(githubInfo.name).toBe('GitHub')
429
+ expect(githubInfo.category).toBe('development')
430
+ expect(githubInfo.requiredConfig).toContain('accessToken')
431
+ })
432
+ })
433
+
434
+ describe('Forms Providers', () => {
435
+ it('typeform info is valid', () => {
436
+ expect(typeformInfo.id).toBe('forms.typeform')
437
+ expect(typeformInfo.name).toBe('Typeform')
438
+ expect(typeformInfo.category).toBe('forms')
439
+ expect(typeformInfo.requiredConfig).toContain('accessToken')
440
+ })
441
+ })
442
+
443
+ describe('Analytics Providers', () => {
444
+ it('mixpanel info is valid', () => {
445
+ expect(mixpanelInfo.id).toBe('analytics.mixpanel')
446
+ expect(mixpanelInfo.name).toBe('Mixpanel')
447
+ expect(mixpanelInfo.category).toBe('analytics')
448
+ expect(mixpanelInfo.requiredConfig).toContain('projectToken')
449
+ })
450
+ })
451
+
452
+ describe('Video Conferencing Providers', () => {
453
+ it('zoom info is valid', () => {
454
+ expect(zoomInfo.id).toBe('video-conferencing.zoom')
455
+ expect(zoomInfo.name).toBe('Zoom')
456
+ expect(zoomInfo.category).toBe('video-conferencing')
457
+ })
458
+
459
+ it('google meet info is valid', () => {
460
+ expect(googleMeetInfo.id).toBe('meeting.google-meet')
461
+ expect(googleMeetInfo.name).toBe('Google Meet')
462
+ expect(googleMeetInfo.category).toBe('video-conferencing')
463
+ })
464
+
465
+ it('teams info is valid', () => {
466
+ expect(teamsInfo.id).toBe('meeting.teams')
467
+ expect(teamsInfo.name).toBe('Microsoft Teams')
468
+ expect(teamsInfo.category).toBe('video-conferencing')
469
+ })
470
+
471
+ it('jitsi info is valid', () => {
472
+ expect(jitsiInfo.id).toBe('meeting.jitsi')
473
+ expect(jitsiInfo.name).toBe('Jitsi Meet')
474
+ expect(jitsiInfo.category).toBe('video-conferencing')
475
+ })
476
+ })
477
+
478
+ describe('Calendar Providers', () => {
479
+ it('google calendar info is valid', () => {
480
+ expect(googleCalendarInfo.id).toBe('calendar.google-calendar')
481
+ expect(googleCalendarInfo.name).toBe('Google Calendar')
482
+ expect(googleCalendarInfo.category).toBe('calendar')
483
+ })
484
+ })
485
+
486
+ describe('Storage Providers', () => {
487
+ it('s3 info is valid', () => {
488
+ expect(s3Info.id).toBe('storage.s3')
489
+ expect(s3Info.name).toBe('AWS S3')
490
+ expect(s3Info.category).toBe('storage')
491
+ expect(s3Info.requiredConfig).toContain('accessKeyId')
492
+ expect(s3Info.requiredConfig).toContain('secretAccessKey')
493
+ expect(s3Info.requiredConfig).toContain('bucket')
494
+ expect(s3Info.requiredConfig).toContain('region')
495
+ })
496
+ })
497
+ })
498
+
499
+ describe('All Providers Collection', () => {
500
+ it('organizes providers by category', () => {
501
+ expect(allProviders.email).toContain('email.sendgrid')
502
+ expect(allProviders.email).toContain('email.resend')
503
+
504
+ expect(allProviders.messaging).toContain('messaging.slack')
505
+ expect(allProviders.messaging).toContain('messaging.twilio-sms')
506
+
507
+ expect(allProviders.spreadsheet).toContain('spreadsheet.xlsx')
508
+ expect(allProviders.spreadsheet).toContain('spreadsheet.google-sheets')
509
+
510
+ expect(allProviders.task).toContain('task.todoist')
511
+
512
+ expect(allProviders.project).toContain('project.linear')
513
+
514
+ expect(allProviders.code).toContain('code.github')
515
+
516
+ expect(allProviders.sales).toContain('sales.hubspot')
517
+
518
+ expect(allProviders.finance).toContain('finance.stripe')
519
+
520
+ expect(allProviders.support).toContain('support.zendesk')
521
+
522
+ expect(allProviders.commerce).toContain('commerce.shopify')
523
+
524
+ expect(allProviders.knowledge).toContain('knowledge.notion')
525
+
526
+ expect(allProviders.media).toContain('media.cloudinary')
527
+
528
+ expect(allProviders.form).toContain('form.typeform')
529
+
530
+ expect(allProviders.analytics).toContain('analytics.mixpanel')
531
+
532
+ expect(allProviders.meeting).toContain('meeting.zoom')
533
+ expect(allProviders.meeting).toContain('meeting.google-meet')
534
+ expect(allProviders.meeting).toContain('meeting.teams')
535
+ expect(allProviders.meeting).toContain('meeting.jitsi')
536
+
537
+ expect(allProviders.storage).toContain('storage.s3')
538
+ })
539
+
540
+ it('has category keys for all provider types', () => {
541
+ const categories = Object.keys(allProviders)
542
+
543
+ expect(categories).toContain('email')
544
+ expect(categories).toContain('messaging')
545
+ expect(categories).toContain('calendar')
546
+ expect(categories).toContain('task')
547
+ expect(categories).toContain('project')
548
+ expect(categories).toContain('code')
549
+ expect(categories).toContain('sales')
550
+ expect(categories).toContain('finance')
551
+ expect(categories).toContain('support')
552
+ expect(categories).toContain('commerce')
553
+ expect(categories).toContain('knowledge')
554
+ expect(categories).toContain('media')
555
+ expect(categories).toContain('form')
556
+ expect(categories).toContain('analytics')
557
+ expect(categories).toContain('document')
558
+ expect(categories).toContain('spreadsheet')
559
+ expect(categories).toContain('presentation')
560
+ expect(categories).toContain('meeting')
561
+ expect(categories).toContain('storage')
562
+ expect(categories).toContain('signature')
563
+ })
564
+ })
565
+
566
+ // Helper function to create mock providers for testing
567
+ function createMockProvider(info: ProviderInfo): BaseProvider {
568
+ return {
569
+ info,
570
+ initialize: async (config: ProviderConfig) => {},
571
+ healthCheck: async (): Promise<ProviderHealth> => ({
572
+ healthy: true,
573
+ latencyMs: 10,
574
+ checkedAt: new Date(),
575
+ }),
576
+ dispose: async () => {},
577
+ }
578
+ }