digital-tools 2.1.3 → 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 (294) hide show
  1. package/CHANGELOG.md +9 -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 +21 -11
  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 +31 -14
  132. package/src/client.ts +136 -0
  133. package/src/define.ts +30 -24
  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 -4
  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
@@ -0,0 +1,554 @@
1
+ /**
2
+ * Common test helpers and mock utilities for provider tests
3
+ *
4
+ * Provides reusable mock patterns and test utilities for provider implementations.
5
+ */
6
+
7
+ import { vi, type MockInstance } from 'vitest'
8
+
9
+ // =============================================================================
10
+ // Mock Fetch Response Types
11
+ // =============================================================================
12
+
13
+ export interface MockFetchResponse {
14
+ ok: boolean
15
+ status?: number
16
+ statusText?: string
17
+ json: () => Promise<unknown>
18
+ text?: () => Promise<string>
19
+ arrayBuffer?: () => Promise<ArrayBuffer>
20
+ }
21
+
22
+ // =============================================================================
23
+ // Mock Fetch Utilities
24
+ // =============================================================================
25
+
26
+ /**
27
+ * Create a mock fetch function that can be configured per test
28
+ */
29
+ export function createMockFetch() {
30
+ return vi.fn<[RequestInfo | URL, RequestInit?], Promise<Response>>()
31
+ }
32
+
33
+ /**
34
+ * Create a successful JSON response
35
+ */
36
+ export function mockJsonResponse<T>(data: T, status = 200): MockFetchResponse {
37
+ return {
38
+ ok: status >= 200 && status < 300,
39
+ status,
40
+ statusText: status === 200 ? 'OK' : 'Error',
41
+ json: async () => data,
42
+ text: async () => JSON.stringify(data),
43
+ arrayBuffer: async () => new TextEncoder().encode(JSON.stringify(data)).buffer,
44
+ }
45
+ }
46
+
47
+ /**
48
+ * Create an error response
49
+ */
50
+ export function mockErrorResponse(
51
+ error: { message?: string; error?: string; code?: string },
52
+ status = 400
53
+ ): MockFetchResponse {
54
+ return {
55
+ ok: false,
56
+ status,
57
+ statusText: 'Bad Request',
58
+ json: async () => error,
59
+ text: async () => JSON.stringify(error),
60
+ }
61
+ }
62
+
63
+ /**
64
+ * Create a network error (simulates fetch rejection)
65
+ */
66
+ export function mockNetworkError(message = 'Network error'): Error {
67
+ return new Error(message)
68
+ }
69
+
70
+ /**
71
+ * Setup mock fetch on global
72
+ */
73
+ export function setupMockFetch(): MockInstance<
74
+ [RequestInfo | URL, RequestInit?],
75
+ Promise<Response>
76
+ > {
77
+ const mockFetch = vi.fn<[RequestInfo | URL, RequestInit?], Promise<Response>>()
78
+ global.fetch = mockFetch as unknown as typeof fetch
79
+ return mockFetch
80
+ }
81
+
82
+ /**
83
+ * Reset mock fetch between tests
84
+ */
85
+ export function resetMockFetch(mockFetch: MockInstance) {
86
+ mockFetch.mockReset()
87
+ }
88
+
89
+ // =============================================================================
90
+ // Request Assertion Helpers
91
+ // =============================================================================
92
+
93
+ /**
94
+ * Get the last call's request info from mock fetch
95
+ */
96
+ export function getLastFetchCall(mockFetch: MockInstance) {
97
+ const calls = mockFetch.mock.calls
98
+ if (calls.length === 0) {
99
+ throw new Error('No fetch calls recorded')
100
+ }
101
+ const [url, options] = calls[calls.length - 1]
102
+ return { url: String(url), options }
103
+ }
104
+
105
+ /**
106
+ * Get a specific call's request info by index
107
+ */
108
+ export function getFetchCall(mockFetch: MockInstance, index: number) {
109
+ const calls = mockFetch.mock.calls
110
+ if (index >= calls.length) {
111
+ throw new Error(`Fetch call at index ${index} not found. Only ${calls.length} calls recorded.`)
112
+ }
113
+ const [url, options] = calls[index]
114
+ return { url: String(url), options }
115
+ }
116
+
117
+ /**
118
+ * Assert that fetch was called with specific URL pattern
119
+ */
120
+ export function assertFetchCalledWithUrl(mockFetch: MockInstance, urlPattern: string | RegExp) {
121
+ const { url } = getLastFetchCall(mockFetch)
122
+ if (typeof urlPattern === 'string') {
123
+ if (!url.includes(urlPattern)) {
124
+ throw new Error(`Expected URL to contain "${urlPattern}", got "${url}"`)
125
+ }
126
+ } else {
127
+ if (!urlPattern.test(url)) {
128
+ throw new Error(`Expected URL to match ${urlPattern}, got "${url}"`)
129
+ }
130
+ }
131
+ }
132
+
133
+ /**
134
+ * Assert that fetch was called with specific method
135
+ */
136
+ export function assertFetchCalledWithMethod(mockFetch: MockInstance, method: string) {
137
+ const { options } = getLastFetchCall(mockFetch)
138
+ const actualMethod = options?.method || 'GET'
139
+ if (actualMethod.toUpperCase() !== method.toUpperCase()) {
140
+ throw new Error(`Expected method "${method}", got "${actualMethod}"`)
141
+ }
142
+ }
143
+
144
+ /**
145
+ * Assert that fetch was called with specific header
146
+ */
147
+ export function assertFetchCalledWithHeader(
148
+ mockFetch: MockInstance,
149
+ headerName: string,
150
+ expectedValue: string
151
+ ) {
152
+ const { options } = getLastFetchCall(mockFetch)
153
+ const headers = options?.headers as Record<string, string> | undefined
154
+ if (!headers) {
155
+ throw new Error('No headers in fetch call')
156
+ }
157
+ const actualValue = headers[headerName]
158
+ if (actualValue !== expectedValue) {
159
+ throw new Error(
160
+ `Expected header "${headerName}" to be "${expectedValue}", got "${actualValue}"`
161
+ )
162
+ }
163
+ }
164
+
165
+ /**
166
+ * Assert that fetch was called with Authorization header
167
+ */
168
+ export function assertFetchCalledWithAuth(
169
+ mockFetch: MockInstance,
170
+ authType: 'Bearer' | 'Basic',
171
+ token: string
172
+ ) {
173
+ const expectedAuth = `${authType} ${token}`
174
+ assertFetchCalledWithHeader(mockFetch, 'Authorization', expectedAuth)
175
+ }
176
+
177
+ /**
178
+ * Parse JSON body from fetch call
179
+ */
180
+ export function parseFetchJsonBody(mockFetch: MockInstance): unknown {
181
+ const { options } = getLastFetchCall(mockFetch)
182
+ if (!options?.body) {
183
+ return undefined
184
+ }
185
+ if (typeof options.body === 'string') {
186
+ return JSON.parse(options.body)
187
+ }
188
+ throw new Error('Body is not a JSON string')
189
+ }
190
+
191
+ /**
192
+ * Parse form-urlencoded body from fetch call
193
+ */
194
+ export function parseFetchFormBody(mockFetch: MockInstance): Record<string, string> {
195
+ const { options } = getLastFetchCall(mockFetch)
196
+ if (!options?.body) {
197
+ return {}
198
+ }
199
+ if (typeof options.body === 'string') {
200
+ const params = new URLSearchParams(options.body)
201
+ const result: Record<string, string> = {}
202
+ params.forEach((value, key) => {
203
+ result[key] = value
204
+ })
205
+ return result
206
+ }
207
+ throw new Error('Body is not a URL-encoded string')
208
+ }
209
+
210
+ // =============================================================================
211
+ // Common Mock Response Generators
212
+ // =============================================================================
213
+
214
+ /**
215
+ * Create HubSpot-style API responses
216
+ */
217
+ export const hubspotMocks = {
218
+ contact(id: string, overrides?: Record<string, unknown>) {
219
+ return {
220
+ id,
221
+ properties: {
222
+ firstname: 'John',
223
+ lastname: 'Doe',
224
+ email: 'john@example.com',
225
+ phone: '+1234567890',
226
+ company: 'Acme Inc',
227
+ jobtitle: 'Developer',
228
+ createdate: '2024-01-01T00:00:00Z',
229
+ lastmodifieddate: '2024-01-15T00:00:00Z',
230
+ ...overrides,
231
+ },
232
+ createdAt: '2024-01-01T00:00:00Z',
233
+ updatedAt: '2024-01-15T00:00:00Z',
234
+ }
235
+ },
236
+ deal(id: string, overrides?: Record<string, unknown>) {
237
+ return {
238
+ id,
239
+ properties: {
240
+ dealname: 'New Deal',
241
+ amount: '10000',
242
+ dealstage: 'negotiation',
243
+ hs_deal_stage_probability: '0.5',
244
+ createdate: '2024-01-01T00:00:00Z',
245
+ hs_lastmodifieddate: '2024-01-15T00:00:00Z',
246
+ ...overrides,
247
+ },
248
+ createdAt: '2024-01-01T00:00:00Z',
249
+ updatedAt: '2024-01-15T00:00:00Z',
250
+ }
251
+ },
252
+ engagement(id: string, type = 'note', overrides?: Record<string, unknown>) {
253
+ return {
254
+ id,
255
+ properties: {
256
+ hs_engagement_type: type,
257
+ hs_engagement_subject: 'Test Subject',
258
+ hs_note_body: 'Test note body',
259
+ hs_createdate: '2024-01-01T00:00:00Z',
260
+ ...overrides,
261
+ },
262
+ createdAt: '2024-01-01T00:00:00Z',
263
+ }
264
+ },
265
+ listResponse<T>(items: T[], hasMore = false, after?: string) {
266
+ return {
267
+ results: items,
268
+ total: items.length,
269
+ paging: hasMore ? { next: { after } } : undefined,
270
+ }
271
+ },
272
+ error(message: string, status = 'error') {
273
+ return { message, status }
274
+ },
275
+ }
276
+
277
+ /**
278
+ * Create Stripe-style API responses
279
+ */
280
+ export const stripeMocks = {
281
+ customer(id: string, overrides?: Record<string, unknown>) {
282
+ return {
283
+ id,
284
+ name: 'John Doe',
285
+ email: 'john@example.com',
286
+ phone: '+1234567890',
287
+ balance: 0,
288
+ created: Math.floor(Date.now() / 1000),
289
+ ...overrides,
290
+ }
291
+ },
292
+ invoice(id: string, overrides?: Record<string, unknown>) {
293
+ return {
294
+ id,
295
+ number: 'INV-001',
296
+ customer: 'cus_123',
297
+ status: 'draft',
298
+ currency: 'usd',
299
+ subtotal: 10000,
300
+ tax: 0,
301
+ total: 10000,
302
+ amount_due: 10000,
303
+ amount_paid: 0,
304
+ due_date: Math.floor(Date.now() / 1000) + 86400 * 30,
305
+ created: Math.floor(Date.now() / 1000),
306
+ ...overrides,
307
+ }
308
+ },
309
+ paymentIntent(id: string, overrides?: Record<string, unknown>) {
310
+ return {
311
+ id,
312
+ amount: 10000,
313
+ currency: 'usd',
314
+ status: 'succeeded',
315
+ customer: 'cus_123',
316
+ payment_method: 'pm_123',
317
+ created: Math.floor(Date.now() / 1000),
318
+ ...overrides,
319
+ }
320
+ },
321
+ refund(id: string, paymentIntentId: string, overrides?: Record<string, unknown>) {
322
+ return {
323
+ id,
324
+ payment_intent: paymentIntentId,
325
+ amount: 5000,
326
+ status: 'succeeded',
327
+ created: Math.floor(Date.now() / 1000),
328
+ ...overrides,
329
+ }
330
+ },
331
+ listResponse<T>(items: T[], hasMore = false) {
332
+ return {
333
+ data: items,
334
+ has_more: hasMore,
335
+ }
336
+ },
337
+ error(message: string, type = 'invalid_request_error', code?: string) {
338
+ return {
339
+ error: { message, type, code },
340
+ }
341
+ },
342
+ }
343
+
344
+ /**
345
+ * Create Google Sheets-style API responses
346
+ */
347
+ export const googleSheetsMocks = {
348
+ spreadsheet(id: string, name: string, sheets?: { id: number; title: string }[]) {
349
+ return {
350
+ spreadsheetId: id,
351
+ properties: { title: name },
352
+ sheets: (sheets || [{ id: 0, title: 'Sheet1' }]).map((s, i) => ({
353
+ properties: {
354
+ sheetId: s.id,
355
+ title: s.title,
356
+ index: i,
357
+ gridProperties: { rowCount: 1000, columnCount: 26 },
358
+ },
359
+ })),
360
+ spreadsheetUrl: `https://docs.google.com/spreadsheets/d/${id}`,
361
+ }
362
+ },
363
+ sheetWithData(sheetId: number, title: string, data: unknown[][]) {
364
+ return {
365
+ properties: {
366
+ sheetId,
367
+ title,
368
+ index: 0,
369
+ gridProperties: { rowCount: data.length, columnCount: data[0]?.length || 0 },
370
+ },
371
+ data: [
372
+ {
373
+ rowData: data.map((row) => ({
374
+ values: row.map((cell) => ({
375
+ effectiveValue:
376
+ typeof cell === 'number'
377
+ ? { numberValue: cell }
378
+ : typeof cell === 'boolean'
379
+ ? { boolValue: cell }
380
+ : cell === null
381
+ ? {}
382
+ : { stringValue: String(cell) },
383
+ })),
384
+ })),
385
+ },
386
+ ],
387
+ }
388
+ },
389
+ valueRange(range: string, values: unknown[][]) {
390
+ return { range, values }
391
+ },
392
+ updateResponse(range: string, rows: number, cols: number, cells: number) {
393
+ return {
394
+ spreadsheetId: 'test-id',
395
+ updatedRange: range,
396
+ updatedRows: rows,
397
+ updatedColumns: cols,
398
+ updatedCells: cells,
399
+ }
400
+ },
401
+ batchUpdateResponse(replies: unknown[]) {
402
+ return { replies }
403
+ },
404
+ driveFile(id: string, name: string) {
405
+ return {
406
+ id,
407
+ name,
408
+ createdTime: '2024-01-01T00:00:00Z',
409
+ modifiedTime: '2024-01-15T00:00:00Z',
410
+ }
411
+ },
412
+ driveListResponse(files: unknown[], nextPageToken?: string) {
413
+ return { files, nextPageToken }
414
+ },
415
+ error(message: string, code = 400) {
416
+ return { error: { message, code } }
417
+ },
418
+ }
419
+
420
+ /**
421
+ * Create Slack-style API responses
422
+ */
423
+ export const slackMocks = {
424
+ message(ts: string, channel: string, text: string, overrides?: Record<string, unknown>) {
425
+ return {
426
+ ts,
427
+ channel,
428
+ user: 'U123',
429
+ text,
430
+ ...overrides,
431
+ }
432
+ },
433
+ channel(id: string, name: string, overrides?: Record<string, unknown>) {
434
+ return {
435
+ id,
436
+ name,
437
+ topic: { value: 'Test topic' },
438
+ purpose: { value: 'Test purpose' },
439
+ is_private: false,
440
+ is_archived: false,
441
+ num_members: 10,
442
+ created: Math.floor(Date.now() / 1000),
443
+ ...overrides,
444
+ }
445
+ },
446
+ user(id: string, name: string, overrides?: Record<string, unknown>) {
447
+ return {
448
+ id,
449
+ name,
450
+ real_name: `Real ${name}`,
451
+ profile: {
452
+ display_name: name,
453
+ email: `${name}@example.com`,
454
+ image_192: 'https://example.com/avatar.png',
455
+ title: 'Developer',
456
+ },
457
+ is_admin: false,
458
+ is_owner: false,
459
+ is_bot: false,
460
+ deleted: false,
461
+ tz: 'America/New_York',
462
+ ...overrides,
463
+ }
464
+ },
465
+ team(id: string, name: string, domain: string) {
466
+ return {
467
+ id,
468
+ name,
469
+ domain,
470
+ icon: { image_132: 'https://example.com/icon.png' },
471
+ }
472
+ },
473
+ okResponse(data: Record<string, unknown> = {}) {
474
+ return { ok: true, ...data }
475
+ },
476
+ errorResponse(error: string) {
477
+ return { ok: false, error }
478
+ },
479
+ postMessageResponse(ts: string, channel: string) {
480
+ return { ok: true, ts, channel }
481
+ },
482
+ conversationsHistoryResponse(messages: unknown[], hasMore = false, nextCursor?: string) {
483
+ return {
484
+ ok: true,
485
+ messages,
486
+ has_more: hasMore,
487
+ response_metadata: nextCursor ? { next_cursor: nextCursor } : {},
488
+ }
489
+ },
490
+ conversationsListResponse(channels: unknown[], nextCursor?: string) {
491
+ return {
492
+ ok: true,
493
+ channels,
494
+ response_metadata: nextCursor ? { next_cursor: nextCursor } : {},
495
+ }
496
+ },
497
+ usersListResponse(members: unknown[], nextCursor?: string) {
498
+ return {
499
+ ok: true,
500
+ members,
501
+ response_metadata: nextCursor ? { next_cursor: nextCursor } : {},
502
+ }
503
+ },
504
+ }
505
+
506
+ // =============================================================================
507
+ // Test Data Factories
508
+ // =============================================================================
509
+
510
+ /**
511
+ * Generate test contact data
512
+ */
513
+ export function createTestContact(
514
+ overrides?: Partial<{
515
+ firstName: string
516
+ lastName: string
517
+ email: string
518
+ phone: string
519
+ company: string
520
+ title: string
521
+ }>
522
+ ) {
523
+ return {
524
+ firstName: 'Test',
525
+ lastName: 'User',
526
+ email: 'test@example.com',
527
+ phone: '+1234567890',
528
+ company: 'Test Company',
529
+ title: 'Developer',
530
+ ...overrides,
531
+ }
532
+ }
533
+
534
+ /**
535
+ * Generate test invoice line items
536
+ */
537
+ export function createTestLineItems(count = 2) {
538
+ return Array.from({ length: count }, (_, i) => ({
539
+ description: `Item ${i + 1}`,
540
+ quantity: i + 1,
541
+ unitPrice: (i + 1) * 100,
542
+ }))
543
+ }
544
+
545
+ /**
546
+ * Generate test spreadsheet data
547
+ */
548
+ export function createTestSpreadsheetData(rows = 3, cols = 3): (string | number | null)[][] {
549
+ return Array.from({ length: rows }, (_, row) =>
550
+ Array.from({ length: cols }, (_, col) =>
551
+ row === 0 ? `Header${col + 1}` : `Value${row}-${col + 1}`
552
+ )
553
+ )
554
+ }