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,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
+ }