@37signals/basecamp 0.2.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 (356) hide show
  1. package/README.md +600 -0
  2. package/dist/auth-strategy.d.ts +36 -0
  3. package/dist/auth-strategy.d.ts.map +1 -0
  4. package/dist/auth-strategy.js +33 -0
  5. package/dist/auth-strategy.js.map +1 -0
  6. package/dist/client.d.ts +224 -0
  7. package/dist/client.d.ts.map +1 -0
  8. package/dist/client.js +715 -0
  9. package/dist/client.js.map +1 -0
  10. package/dist/errors.d.ts +137 -0
  11. package/dist/errors.d.ts.map +1 -0
  12. package/dist/errors.js +269 -0
  13. package/dist/errors.js.map +1 -0
  14. package/dist/generated/metadata.json +2281 -0
  15. package/dist/generated/openapi-stripped.json +21268 -0
  16. package/dist/generated/path-mapping.d.ts +8 -0
  17. package/dist/generated/path-mapping.d.ts.map +1 -0
  18. package/dist/generated/path-mapping.js +192 -0
  19. package/dist/generated/path-mapping.js.map +1 -0
  20. package/dist/generated/path-mapping.ts +199 -0
  21. package/dist/generated/schema.d.ts +14883 -0
  22. package/dist/generated/services/attachments.d.ts +27 -0
  23. package/dist/generated/services/attachments.d.ts.map +1 -0
  24. package/dist/generated/services/attachments.js +49 -0
  25. package/dist/generated/services/attachments.js.map +1 -0
  26. package/dist/generated/services/attachments.ts +59 -0
  27. package/dist/generated/services/boosts.d.ts +114 -0
  28. package/dist/generated/services/boosts.d.ts.map +1 -0
  29. package/dist/generated/services/boosts.js +179 -0
  30. package/dist/generated/services/boosts.js.map +1 -0
  31. package/dist/generated/services/boosts.ts +250 -0
  32. package/dist/generated/services/campfires.d.ts +202 -0
  33. package/dist/generated/services/campfires.d.ts.map +1 -0
  34. package/dist/generated/services/campfires.js +309 -0
  35. package/dist/generated/services/campfires.js.map +1 -0
  36. package/dist/generated/services/campfires.ts +433 -0
  37. package/dist/generated/services/card-columns.d.ts +163 -0
  38. package/dist/generated/services/card-columns.d.ts.map +1 -0
  39. package/dist/generated/services/card-columns.js +264 -0
  40. package/dist/generated/services/card-columns.js.map +1 -0
  41. package/dist/generated/services/card-columns.ts +360 -0
  42. package/dist/generated/services/card-steps.d.ts +105 -0
  43. package/dist/generated/services/card-steps.d.ts.map +1 -0
  44. package/dist/generated/services/card-steps.js +148 -0
  45. package/dist/generated/services/card-steps.js.map +1 -0
  46. package/dist/generated/services/card-steps.ts +221 -0
  47. package/dist/generated/services/card-tables.d.ts +27 -0
  48. package/dist/generated/services/card-tables.d.ts.map +1 -0
  49. package/dist/generated/services/card-tables.js +40 -0
  50. package/dist/generated/services/card-tables.js.map +1 -0
  51. package/dist/generated/services/card-tables.ts +55 -0
  52. package/dist/generated/services/cards.d.ts +118 -0
  53. package/dist/generated/services/cards.d.ts.map +1 -0
  54. package/dist/generated/services/cards.js +166 -0
  55. package/dist/generated/services/cards.js.map +1 -0
  56. package/dist/generated/services/cards.ts +247 -0
  57. package/dist/generated/services/checkins.d.ts +278 -0
  58. package/dist/generated/services/checkins.d.ts.map +1 -0
  59. package/dist/generated/services/checkins.js +420 -0
  60. package/dist/generated/services/checkins.js.map +1 -0
  61. package/dist/generated/services/checkins.ts +600 -0
  62. package/dist/generated/services/client-approvals.d.ts +45 -0
  63. package/dist/generated/services/client-approvals.d.ts.map +1 -0
  64. package/dist/generated/services/client-approvals.js +58 -0
  65. package/dist/generated/services/client-approvals.js.map +1 -0
  66. package/dist/generated/services/client-approvals.ts +89 -0
  67. package/dist/generated/services/client-correspondences.d.ts +45 -0
  68. package/dist/generated/services/client-correspondences.d.ts.map +1 -0
  69. package/dist/generated/services/client-correspondences.js +58 -0
  70. package/dist/generated/services/client-correspondences.js.map +1 -0
  71. package/dist/generated/services/client-correspondences.ts +89 -0
  72. package/dist/generated/services/client-replies.d.ts +47 -0
  73. package/dist/generated/services/client-replies.d.ts.map +1 -0
  74. package/dist/generated/services/client-replies.js +65 -0
  75. package/dist/generated/services/client-replies.js.map +1 -0
  76. package/dist/generated/services/client-replies.ts +95 -0
  77. package/dist/generated/services/client-visibility.d.ts +35 -0
  78. package/dist/generated/services/client-visibility.d.ts.map +1 -0
  79. package/dist/generated/services/client-visibility.js +44 -0
  80. package/dist/generated/services/client-visibility.js.map +1 -0
  81. package/dist/generated/services/client-visibility.ts +68 -0
  82. package/dist/generated/services/comments.d.ts +86 -0
  83. package/dist/generated/services/comments.d.ts.map +1 -0
  84. package/dist/generated/services/comments.js +129 -0
  85. package/dist/generated/services/comments.js.map +1 -0
  86. package/dist/generated/services/comments.ts +185 -0
  87. package/dist/generated/services/documents.d.ts +92 -0
  88. package/dist/generated/services/documents.d.ts.map +1 -0
  89. package/dist/generated/services/documents.js +129 -0
  90. package/dist/generated/services/documents.js.map +1 -0
  91. package/dist/generated/services/documents.ts +191 -0
  92. package/dist/generated/services/events.d.ts +34 -0
  93. package/dist/generated/services/events.d.ts.map +1 -0
  94. package/dist/generated/services/events.js +39 -0
  95. package/dist/generated/services/events.js.map +1 -0
  96. package/dist/generated/services/events.ts +64 -0
  97. package/dist/generated/services/forwards.d.ts +112 -0
  98. package/dist/generated/services/forwards.d.ts.map +1 -0
  99. package/dist/generated/services/forwards.js +172 -0
  100. package/dist/generated/services/forwards.js.map +1 -0
  101. package/dist/generated/services/forwards.ts +241 -0
  102. package/dist/generated/services/index.d.ts +39 -0
  103. package/dist/generated/services/index.d.ts.map +1 -0
  104. package/dist/generated/services/index.js +39 -0
  105. package/dist/generated/services/index.js.map +1 -0
  106. package/dist/generated/services/index.ts +38 -0
  107. package/dist/generated/services/lineup.d.ts +67 -0
  108. package/dist/generated/services/lineup.d.ts.map +1 -0
  109. package/dist/generated/services/lineup.js +99 -0
  110. package/dist/generated/services/lineup.js.map +1 -0
  111. package/dist/generated/services/lineup.ts +143 -0
  112. package/dist/generated/services/message-boards.d.ts +27 -0
  113. package/dist/generated/services/message-boards.d.ts.map +1 -0
  114. package/dist/generated/services/message-boards.js +40 -0
  115. package/dist/generated/services/message-boards.js.map +1 -0
  116. package/dist/generated/services/message-boards.ts +55 -0
  117. package/dist/generated/services/message-types.d.ts +100 -0
  118. package/dist/generated/services/message-types.d.ts.map +1 -0
  119. package/dist/generated/services/message-types.js +144 -0
  120. package/dist/generated/services/message-types.js.map +1 -0
  121. package/dist/generated/services/message-types.ts +210 -0
  122. package/dist/generated/services/messages.d.ts +122 -0
  123. package/dist/generated/services/messages.d.ts.map +1 -0
  124. package/dist/generated/services/messages.js +180 -0
  125. package/dist/generated/services/messages.js.map +1 -0
  126. package/dist/generated/services/messages.ts +258 -0
  127. package/dist/generated/services/people.d.ts +122 -0
  128. package/dist/generated/services/people.d.ts.map +1 -0
  129. package/dist/generated/services/people.js +167 -0
  130. package/dist/generated/services/people.js.map +1 -0
  131. package/dist/generated/services/people.ts +252 -0
  132. package/dist/generated/services/projects.d.ts +109 -0
  133. package/dist/generated/services/projects.d.ts.map +1 -0
  134. package/dist/generated/services/projects.js +153 -0
  135. package/dist/generated/services/projects.js.map +1 -0
  136. package/dist/generated/services/projects.ts +224 -0
  137. package/dist/generated/services/recordings.d.ts +93 -0
  138. package/dist/generated/services/recordings.d.ts.map +1 -0
  139. package/dist/generated/services/recordings.js +138 -0
  140. package/dist/generated/services/recordings.js.map +1 -0
  141. package/dist/generated/services/recordings.ts +191 -0
  142. package/dist/generated/services/reports.d.ts +90 -0
  143. package/dist/generated/services/reports.d.ts.map +1 -0
  144. package/dist/generated/services/reports.js +124 -0
  145. package/dist/generated/services/reports.js.map +1 -0
  146. package/dist/generated/services/reports.ts +187 -0
  147. package/dist/generated/services/schedules.d.ts +162 -0
  148. package/dist/generated/services/schedules.d.ts.map +1 -0
  149. package/dist/generated/services/schedules.js +228 -0
  150. package/dist/generated/services/schedules.js.map +1 -0
  151. package/dist/generated/services/schedules.ts +335 -0
  152. package/dist/generated/services/search.d.ts +45 -0
  153. package/dist/generated/services/search.d.ts.map +1 -0
  154. package/dist/generated/services/search.js +56 -0
  155. package/dist/generated/services/search.js.map +1 -0
  156. package/dist/generated/services/search.ts +89 -0
  157. package/dist/generated/services/subscriptions.d.ts +73 -0
  158. package/dist/generated/services/subscriptions.d.ts.map +1 -0
  159. package/dist/generated/services/subscriptions.js +119 -0
  160. package/dist/generated/services/subscriptions.js.map +1 -0
  161. package/dist/generated/services/subscriptions.ts +160 -0
  162. package/dist/generated/services/templates.d.ts +140 -0
  163. package/dist/generated/services/templates.d.ts.map +1 -0
  164. package/dist/generated/services/templates.js +207 -0
  165. package/dist/generated/services/templates.js.map +1 -0
  166. package/dist/generated/services/templates.ts +294 -0
  167. package/dist/generated/services/timeline.d.ts +31 -0
  168. package/dist/generated/services/timeline.d.ts.map +1 -0
  169. package/dist/generated/services/timeline.js +39 -0
  170. package/dist/generated/services/timeline.js.map +1 -0
  171. package/dist/generated/services/timeline.ts +62 -0
  172. package/dist/generated/services/timesheets.d.ts +145 -0
  173. package/dist/generated/services/timesheets.d.ts.map +1 -0
  174. package/dist/generated/services/timesheets.js +186 -0
  175. package/dist/generated/services/timesheets.js.map +1 -0
  176. package/dist/generated/services/timesheets.ts +289 -0
  177. package/dist/generated/services/todolist-groups.d.ts +74 -0
  178. package/dist/generated/services/todolist-groups.d.ts.map +1 -0
  179. package/dist/generated/services/todolist-groups.js +100 -0
  180. package/dist/generated/services/todolist-groups.js.map +1 -0
  181. package/dist/generated/services/todolist-groups.ts +151 -0
  182. package/dist/generated/services/todolists.d.ts +95 -0
  183. package/dist/generated/services/todolists.d.ts.map +1 -0
  184. package/dist/generated/services/todolists.js +130 -0
  185. package/dist/generated/services/todolists.js.map +1 -0
  186. package/dist/generated/services/todolists.ts +192 -0
  187. package/dist/generated/services/todos.d.ts +175 -0
  188. package/dist/generated/services/todos.d.ts.map +1 -0
  189. package/dist/generated/services/todos.js +255 -0
  190. package/dist/generated/services/todos.js.map +1 -0
  191. package/dist/generated/services/todos.ts +369 -0
  192. package/dist/generated/services/todosets.d.ts +27 -0
  193. package/dist/generated/services/todosets.d.ts.map +1 -0
  194. package/dist/generated/services/todosets.js +40 -0
  195. package/dist/generated/services/todosets.js.map +1 -0
  196. package/dist/generated/services/todosets.ts +55 -0
  197. package/dist/generated/services/tools.d.ts +122 -0
  198. package/dist/generated/services/tools.d.ts.map +1 -0
  199. package/dist/generated/services/tools.js +197 -0
  200. package/dist/generated/services/tools.js.map +1 -0
  201. package/dist/generated/services/tools.ts +267 -0
  202. package/dist/generated/services/uploads.d.ts +109 -0
  203. package/dist/generated/services/uploads.d.ts.map +1 -0
  204. package/dist/generated/services/uploads.js +153 -0
  205. package/dist/generated/services/uploads.js.map +1 -0
  206. package/dist/generated/services/uploads.ts +227 -0
  207. package/dist/generated/services/vaults.d.ts +86 -0
  208. package/dist/generated/services/vaults.d.ts.map +1 -0
  209. package/dist/generated/services/vaults.js +126 -0
  210. package/dist/generated/services/vaults.js.map +1 -0
  211. package/dist/generated/services/vaults.ts +182 -0
  212. package/dist/generated/services/webhooks.d.ts +106 -0
  213. package/dist/generated/services/webhooks.d.ts.map +1 -0
  214. package/dist/generated/services/webhooks.js +157 -0
  215. package/dist/generated/services/webhooks.js.map +1 -0
  216. package/dist/generated/services/webhooks.ts +226 -0
  217. package/dist/hooks/otel.d.ts +136 -0
  218. package/dist/hooks/otel.d.ts.map +1 -0
  219. package/dist/hooks/otel.js +240 -0
  220. package/dist/hooks/otel.js.map +1 -0
  221. package/dist/hooks.d.ts +171 -0
  222. package/dist/hooks.d.ts.map +1 -0
  223. package/dist/hooks.js +196 -0
  224. package/dist/hooks.js.map +1 -0
  225. package/dist/index.d.ts +90 -0
  226. package/dist/index.d.ts.map +1 -0
  227. package/dist/index.js +122 -0
  228. package/dist/index.js.map +1 -0
  229. package/dist/oauth/authorize.d.ts +48 -0
  230. package/dist/oauth/authorize.d.ts.map +1 -0
  231. package/dist/oauth/authorize.js +56 -0
  232. package/dist/oauth/authorize.js.map +1 -0
  233. package/dist/oauth/callback-server.d.ts +56 -0
  234. package/dist/oauth/callback-server.d.ts.map +1 -0
  235. package/dist/oauth/callback-server.js +150 -0
  236. package/dist/oauth/callback-server.js.map +1 -0
  237. package/dist/oauth/discovery.d.ts +54 -0
  238. package/dist/oauth/discovery.d.ts.map +1 -0
  239. package/dist/oauth/discovery.js +116 -0
  240. package/dist/oauth/discovery.js.map +1 -0
  241. package/dist/oauth/exchange.d.ts +96 -0
  242. package/dist/oauth/exchange.d.ts.map +1 -0
  243. package/dist/oauth/exchange.js +324 -0
  244. package/dist/oauth/exchange.js.map +1 -0
  245. package/dist/oauth/identity.d.ts +30 -0
  246. package/dist/oauth/identity.d.ts.map +1 -0
  247. package/dist/oauth/identity.js +82 -0
  248. package/dist/oauth/identity.js.map +1 -0
  249. package/dist/oauth/index.d.ts +50 -0
  250. package/dist/oauth/index.d.ts.map +1 -0
  251. package/dist/oauth/index.js +58 -0
  252. package/dist/oauth/index.js.map +1 -0
  253. package/dist/oauth/interactive-login.d.ts +62 -0
  254. package/dist/oauth/interactive-login.d.ts.map +1 -0
  255. package/dist/oauth/interactive-login.js +106 -0
  256. package/dist/oauth/interactive-login.js.map +1 -0
  257. package/dist/oauth/pkce.d.ts +68 -0
  258. package/dist/oauth/pkce.d.ts.map +1 -0
  259. package/dist/oauth/pkce.js +80 -0
  260. package/dist/oauth/pkce.js.map +1 -0
  261. package/dist/oauth/token-manager.d.ts +92 -0
  262. package/dist/oauth/token-manager.d.ts.map +1 -0
  263. package/dist/oauth/token-manager.js +126 -0
  264. package/dist/oauth/token-manager.js.map +1 -0
  265. package/dist/oauth/token-store.d.ts +45 -0
  266. package/dist/oauth/token-store.d.ts.map +1 -0
  267. package/dist/oauth/token-store.js +105 -0
  268. package/dist/oauth/token-store.js.map +1 -0
  269. package/dist/oauth/types.d.ts +98 -0
  270. package/dist/oauth/types.d.ts.map +1 -0
  271. package/dist/oauth/types.js +8 -0
  272. package/dist/oauth/types.js.map +1 -0
  273. package/dist/pagination-utils.d.ts +27 -0
  274. package/dist/pagination-utils.d.ts.map +1 -0
  275. package/dist/pagination-utils.js +54 -0
  276. package/dist/pagination-utils.js.map +1 -0
  277. package/dist/pagination.d.ts +56 -0
  278. package/dist/pagination.d.ts.map +1 -0
  279. package/dist/pagination.js +57 -0
  280. package/dist/pagination.js.map +1 -0
  281. package/dist/security.d.ts +68 -0
  282. package/dist/security.d.ts.map +1 -0
  283. package/dist/security.js +107 -0
  284. package/dist/security.js.map +1 -0
  285. package/dist/services/authorization.d.ts +124 -0
  286. package/dist/services/authorization.d.ts.map +1 -0
  287. package/dist/services/authorization.js +117 -0
  288. package/dist/services/authorization.js.map +1 -0
  289. package/dist/services/base.d.ts +102 -0
  290. package/dist/services/base.d.ts.map +1 -0
  291. package/dist/services/base.js +230 -0
  292. package/dist/services/base.js.map +1 -0
  293. package/dist/webhooks/adapters/node-http.d.ts +14 -0
  294. package/dist/webhooks/adapters/node-http.d.ts.map +1 -0
  295. package/dist/webhooks/adapters/node-http.js +60 -0
  296. package/dist/webhooks/adapters/node-http.js.map +1 -0
  297. package/dist/webhooks/events.d.ts +52 -0
  298. package/dist/webhooks/events.d.ts.map +1 -0
  299. package/dist/webhooks/events.js +52 -0
  300. package/dist/webhooks/events.js.map +1 -0
  301. package/dist/webhooks/handler.d.ts +62 -0
  302. package/dist/webhooks/handler.d.ts.map +1 -0
  303. package/dist/webhooks/handler.js +226 -0
  304. package/dist/webhooks/handler.js.map +1 -0
  305. package/dist/webhooks/index.d.ts +5 -0
  306. package/dist/webhooks/index.d.ts.map +1 -0
  307. package/dist/webhooks/index.js +5 -0
  308. package/dist/webhooks/index.js.map +1 -0
  309. package/dist/webhooks/verify.d.ts +11 -0
  310. package/dist/webhooks/verify.d.ts.map +1 -0
  311. package/dist/webhooks/verify.js +25 -0
  312. package/dist/webhooks/verify.js.map +1 -0
  313. package/package.json +70 -0
  314. package/src/generated/metadata.json +2281 -0
  315. package/src/generated/openapi-stripped.json +21268 -0
  316. package/src/generated/path-mapping.ts +199 -0
  317. package/src/generated/schema.d.ts +14883 -0
  318. package/src/generated/services/attachments.ts +59 -0
  319. package/src/generated/services/boosts.ts +250 -0
  320. package/src/generated/services/campfires.ts +433 -0
  321. package/src/generated/services/card-columns.ts +360 -0
  322. package/src/generated/services/card-steps.ts +221 -0
  323. package/src/generated/services/card-tables.ts +55 -0
  324. package/src/generated/services/cards.ts +247 -0
  325. package/src/generated/services/checkins.ts +600 -0
  326. package/src/generated/services/client-approvals.ts +89 -0
  327. package/src/generated/services/client-correspondences.ts +89 -0
  328. package/src/generated/services/client-replies.ts +95 -0
  329. package/src/generated/services/client-visibility.ts +68 -0
  330. package/src/generated/services/comments.ts +185 -0
  331. package/src/generated/services/documents.ts +191 -0
  332. package/src/generated/services/events.ts +64 -0
  333. package/src/generated/services/forwards.ts +241 -0
  334. package/src/generated/services/index.ts +38 -0
  335. package/src/generated/services/lineup.ts +143 -0
  336. package/src/generated/services/message-boards.ts +55 -0
  337. package/src/generated/services/message-types.ts +210 -0
  338. package/src/generated/services/messages.ts +258 -0
  339. package/src/generated/services/people.ts +252 -0
  340. package/src/generated/services/projects.ts +224 -0
  341. package/src/generated/services/recordings.ts +191 -0
  342. package/src/generated/services/reports.ts +187 -0
  343. package/src/generated/services/schedules.ts +335 -0
  344. package/src/generated/services/search.ts +89 -0
  345. package/src/generated/services/subscriptions.ts +160 -0
  346. package/src/generated/services/templates.ts +294 -0
  347. package/src/generated/services/timeline.ts +62 -0
  348. package/src/generated/services/timesheets.ts +289 -0
  349. package/src/generated/services/todolist-groups.ts +151 -0
  350. package/src/generated/services/todolists.ts +192 -0
  351. package/src/generated/services/todos.ts +369 -0
  352. package/src/generated/services/todosets.ts +55 -0
  353. package/src/generated/services/tools.ts +267 -0
  354. package/src/generated/services/uploads.ts +227 -0
  355. package/src/generated/services/vaults.ts +182 -0
  356. package/src/generated/services/webhooks.ts +226 -0
@@ -0,0 +1,117 @@
1
+ /**
2
+ * Authorization service for Basecamp SDK.
3
+ *
4
+ * Provides functionality to fetch authorization information including
5
+ * the authenticated user's identity and list of accessible accounts.
6
+ */
7
+ import { BaseService } from "./base.js";
8
+ const DEFAULT_AUTHORIZATION_ENDPOINT = "https://launchpad.37signals.com/authorization.json";
9
+ /**
10
+ * Service for authorization-related operations.
11
+ *
12
+ * This service communicates with the Launchpad authorization endpoint
13
+ * rather than the standard Basecamp API.
14
+ *
15
+ * @example
16
+ * ```ts
17
+ * import { createBasecampClient } from "@37signals/basecamp";
18
+ *
19
+ * const client = createBasecampClient({
20
+ * accountId: "12345",
21
+ * accessToken: "your-token",
22
+ * });
23
+ *
24
+ * // Get all accounts
25
+ * const info = await client.authorization.getInfo();
26
+ * console.log(`Logged in as ${info.identity.firstName}`);
27
+ *
28
+ * // Filter to only Basecamp 3 accounts
29
+ * const bc3Info = await client.authorization.getInfo({ filterProduct: "bc3" });
30
+ * for (const account of bc3Info.accounts) {
31
+ * console.log(account.name);
32
+ * }
33
+ * ```
34
+ */
35
+ export class AuthorizationService extends BaseService {
36
+ authStrategy;
37
+ userAgent;
38
+ constructor(client, hooks, authStrategy, userAgent) {
39
+ super(client, hooks);
40
+ this.authStrategy = authStrategy;
41
+ this.userAgent = userAgent;
42
+ }
43
+ /**
44
+ * Fetches authorization information for the current access token.
45
+ *
46
+ * Returns the authenticated user's identity and list of accounts
47
+ * they have access to.
48
+ *
49
+ * @param options - Optional configuration
50
+ * @returns Authorization information including identity and accounts
51
+ *
52
+ * @example
53
+ * ```ts
54
+ * const info = await authService.getInfo();
55
+ *
56
+ * console.log(`User: ${info.identity.firstName} ${info.identity.lastName}`);
57
+ * console.log(`Email: ${info.identity.emailAddress}`);
58
+ * console.log(`Token expires: ${info.expiresAt}`);
59
+ *
60
+ * for (const account of info.accounts) {
61
+ * console.log(`${account.name} (${account.product})`);
62
+ * }
63
+ * ```
64
+ */
65
+ async getInfo(options = {}) {
66
+ const endpoint = options.endpoint ?? DEFAULT_AUTHORIZATION_ENDPOINT;
67
+ return this.request({
68
+ service: "Authorization",
69
+ operation: "GetInfo",
70
+ resourceType: "authorization",
71
+ isMutation: false,
72
+ }, async () => {
73
+ // Build headers with auth strategy
74
+ const headers = new Headers({
75
+ "User-Agent": this.userAgent,
76
+ Accept: "application/json",
77
+ });
78
+ await this.authStrategy.authenticate(headers);
79
+ // Make direct fetch request to Launchpad endpoint
80
+ const response = await fetch(endpoint, {
81
+ method: "GET",
82
+ headers,
83
+ });
84
+ if (!response.ok) {
85
+ return { data: undefined, error: undefined, response };
86
+ }
87
+ const raw = (await response.json());
88
+ // Transform to our clean types
89
+ let accounts = raw.accounts.map((a) => ({
90
+ id: a.id,
91
+ name: a.name,
92
+ product: a.product,
93
+ href: a.href,
94
+ appHref: a.app_href,
95
+ hidden: a.hidden,
96
+ expired: a.expired,
97
+ featured: a.featured,
98
+ }));
99
+ // Filter by product if requested
100
+ if (options.filterProduct) {
101
+ accounts = accounts.filter((a) => a.product === options.filterProduct);
102
+ }
103
+ const data = {
104
+ expiresAt: new Date(raw.expires_at),
105
+ identity: {
106
+ id: raw.identity.id,
107
+ firstName: raw.identity.first_name,
108
+ lastName: raw.identity.last_name,
109
+ emailAddress: raw.identity.email_address,
110
+ },
111
+ accounts,
112
+ };
113
+ return { data, error: undefined, response };
114
+ });
115
+ }
116
+ }
117
+ //# sourceMappingURL=authorization.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"authorization.js","sourceRoot":"","sources":["../../src/services/authorization.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,102 @@
1
+ /**
2
+ * Base service class for Basecamp API services.
3
+ *
4
+ * Provides shared functionality for all service classes including:
5
+ * - Error handling with typed BasecampError
6
+ * - Hooks integration for observability
7
+ * - Request/response processing
8
+ * - Automatic pagination via Link headers
9
+ *
10
+ * @example
11
+ * ```ts
12
+ * export class TodosService extends BaseService {
13
+ * async list(projectId: number, todolistId: number): Promise<ListResult<Todo>> {
14
+ * return this.requestPaginated(
15
+ * { service: "Todos", operation: "List", resourceType: "todo", isMutation: false, projectId },
16
+ * () => this.client.GET("/buckets/{projectId}/todolists/{todolistId}/todos.json", {
17
+ * params: { path: { projectId, todolistId } },
18
+ * })
19
+ * );
20
+ * }
21
+ * }
22
+ * ```
23
+ */
24
+ import type { BasecampHooks, OperationInfo } from "../hooks.js";
25
+ import { BasecampError } from "../errors.js";
26
+ import { ListResult, type PaginationOptions } from "../pagination.js";
27
+ import type { paths } from "../generated/schema.js";
28
+ import type createClient from "openapi-fetch";
29
+ /**
30
+ * Raw client type from openapi-fetch.
31
+ */
32
+ export type RawClient = ReturnType<typeof createClient<paths>>;
33
+ /**
34
+ * Response type from openapi-fetch methods.
35
+ */
36
+ export interface FetchResponse<T> {
37
+ data?: T;
38
+ error?: unknown;
39
+ response: Response;
40
+ }
41
+ /**
42
+ * Abstract base class for all Basecamp API services.
43
+ *
44
+ * Services extend this class to inherit common functionality
45
+ * for making API requests, handling errors, and integrating
46
+ * with the hooks system.
47
+ */
48
+ export declare abstract class BaseService {
49
+ /** The underlying openapi-fetch client */
50
+ protected readonly client: RawClient;
51
+ /** Optional hooks for observability */
52
+ protected readonly hooks?: BasecampHooks;
53
+ /**
54
+ * Authenticated fetch for pagination follow-up requests.
55
+ *
56
+ * Note: Subsequent pages use this raw fetch rather than the openapi-fetch
57
+ * middleware stack (retry, cache, hooks). This is intentional — Link header
58
+ * URLs are absolute and don't map to openapi-fetch path patterns. The
59
+ * createBasecampClient() factory provides an authenticated fetchPage closure
60
+ * with Bearer token and User-Agent. When services are instantiated directly
61
+ * (without the factory), the fallback is unauthenticated — page 1 will
62
+ * succeed via the authenticated raw client, but page 2+ may 401.
63
+ */
64
+ protected readonly fetchPage: (url: string) => Promise<Response>;
65
+ constructor(client: RawClient, hooks?: BasecampHooks, fetchPage?: (url: string) => Promise<Response>);
66
+ /**
67
+ * Executes an API request with error handling and hooks integration.
68
+ *
69
+ * @param info - Operation metadata for hooks
70
+ * @param fn - The function that performs the actual API call
71
+ * @returns The response data
72
+ * @throws BasecampError on API errors
73
+ */
74
+ protected request<T>(info: OperationInfo, fn: () => Promise<FetchResponse<T>>): Promise<T>;
75
+ /**
76
+ * Executes a paginated API request, automatically following Link headers.
77
+ *
78
+ * Returns a ListResult<T> which extends Array<T> — fully backwards-compatible
79
+ * with array operations, plus `.meta.totalCount` for total item count.
80
+ *
81
+ * @param info - Operation metadata for hooks
82
+ * @param fn - The function that performs the initial API call
83
+ * @param paginationOpts - Optional pagination control (maxItems)
84
+ * @returns A ListResult containing all items across pages
85
+ * @throws BasecampError on API errors or cross-origin Link headers
86
+ */
87
+ protected requestPaginated<T>(info: OperationInfo, fn: () => Promise<FetchResponse<T[]>>, paginationOpts?: PaginationOptions): Promise<ListResult<T>>;
88
+ /**
89
+ * Follows Link header pagination, accumulating items across pages.
90
+ * Returns items and whether results were truncated (by maxItems or page cap).
91
+ */
92
+ private followPagination;
93
+ /**
94
+ * Converts an HTTP error response to a typed BasecampError.
95
+ *
96
+ * @param response - The HTTP response
97
+ * @param error - Optional error object from openapi-fetch
98
+ * @returns A BasecampError with appropriate code and metadata
99
+ */
100
+ protected handleError(response: Response, error?: unknown): Promise<BasecampError>;
101
+ }
102
+ //# sourceMappingURL=base.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../src/services/base.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAmB,MAAM,aAAa,CAAC;AACjF,OAAO,EAAE,aAAa,EAAqB,MAAM,cAAc,CAAC;AAChE,OAAO,EAAE,UAAU,EAAmB,KAAK,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAEvF,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,wBAAwB,CAAC;AACpD,OAAO,KAAK,YAAY,MAAM,eAAe,CAAC;AAE9C;;GAEG;AACH,MAAM,MAAM,SAAS,GAAG,UAAU,CAAC,OAAO,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC;AAE/D;;GAEG;AACH,MAAM,WAAW,aAAa,CAAC,CAAC;IAC9B,IAAI,CAAC,EAAE,CAAC,CAAC;IACT,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,QAAQ,EAAE,QAAQ,CAAC;CACpB;AAKD;;;;;;GAMG;AACH,8BAAsB,WAAW;IAC/B,0CAA0C;IAC1C,SAAS,CAAC,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC;IAErC,uCAAuC;IACvC,SAAS,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,aAAa,CAAC;IAEzC;;;;;;;;;;OAUG;IACH,SAAS,CAAC,QAAQ,CAAC,SAAS,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;gBAG/D,MAAM,EAAE,SAAS,EACjB,KAAK,CAAC,EAAE,aAAa,EACrB,SAAS,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,QAAQ,CAAC;IAOhD;;;;;;;OAOG;cACa,OAAO,CAAC,CAAC,EACvB,IAAI,EAAE,aAAa,EACnB,EAAE,EAAE,MAAM,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,GAClC,OAAO,CAAC,CAAC,CAAC;IAgDb;;;;;;;;;;;OAWG;cACa,gBAAgB,CAAC,CAAC,EAChC,IAAI,EAAE,aAAa,EACnB,EAAE,EAAE,MAAM,OAAO,CAAC,aAAa,CAAC,CAAC,EAAE,CAAC,CAAC,EACrC,cAAc,CAAC,EAAE,iBAAiB,GACjC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;IAkEzB;;;OAGG;YACW,gBAAgB;IA4C9B;;;;;;OAMG;cACa,WAAW,CAAC,QAAQ,EAAE,QAAQ,EAAE,KAAK,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,aAAa,CAAC;CAYzF"}
@@ -0,0 +1,230 @@
1
+ /**
2
+ * Base service class for Basecamp API services.
3
+ *
4
+ * Provides shared functionality for all service classes including:
5
+ * - Error handling with typed BasecampError
6
+ * - Hooks integration for observability
7
+ * - Request/response processing
8
+ * - Automatic pagination via Link headers
9
+ *
10
+ * @example
11
+ * ```ts
12
+ * export class TodosService extends BaseService {
13
+ * async list(projectId: number, todolistId: number): Promise<ListResult<Todo>> {
14
+ * return this.requestPaginated(
15
+ * { service: "Todos", operation: "List", resourceType: "todo", isMutation: false, projectId },
16
+ * () => this.client.GET("/buckets/{projectId}/todolists/{todolistId}/todos.json", {
17
+ * params: { path: { projectId, todolistId } },
18
+ * })
19
+ * );
20
+ * }
21
+ * }
22
+ * ```
23
+ */
24
+ import { BasecampError, errorFromResponse } from "../errors.js";
25
+ import { ListResult, parseTotalCount } from "../pagination.js";
26
+ import { parseNextLink, resolveURL, isSameOrigin } from "../pagination-utils.js";
27
+ /** Maximum pages to follow as a safety cap against infinite loops. */
28
+ const MAX_PAGES = 10_000;
29
+ /**
30
+ * Abstract base class for all Basecamp API services.
31
+ *
32
+ * Services extend this class to inherit common functionality
33
+ * for making API requests, handling errors, and integrating
34
+ * with the hooks system.
35
+ */
36
+ export class BaseService {
37
+ /** The underlying openapi-fetch client */
38
+ client;
39
+ /** Optional hooks for observability */
40
+ hooks;
41
+ /**
42
+ * Authenticated fetch for pagination follow-up requests.
43
+ *
44
+ * Note: Subsequent pages use this raw fetch rather than the openapi-fetch
45
+ * middleware stack (retry, cache, hooks). This is intentional — Link header
46
+ * URLs are absolute and don't map to openapi-fetch path patterns. The
47
+ * createBasecampClient() factory provides an authenticated fetchPage closure
48
+ * with Bearer token and User-Agent. When services are instantiated directly
49
+ * (without the factory), the fallback is unauthenticated — page 1 will
50
+ * succeed via the authenticated raw client, but page 2+ may 401.
51
+ */
52
+ fetchPage;
53
+ constructor(client, hooks, fetchPage) {
54
+ this.client = client;
55
+ this.hooks = hooks;
56
+ this.fetchPage = fetchPage ?? ((url) => fetch(url, { headers: { Accept: "application/json" } }));
57
+ }
58
+ /**
59
+ * Executes an API request with error handling and hooks integration.
60
+ *
61
+ * @param info - Operation metadata for hooks
62
+ * @param fn - The function that performs the actual API call
63
+ * @returns The response data
64
+ * @throws BasecampError on API errors
65
+ */
66
+ async request(info, fn) {
67
+ const start = performance.now();
68
+ let result = { durationMs: 0 };
69
+ // Notify hooks of operation start (wrapped to prevent hook failures from breaking operations)
70
+ try {
71
+ this.hooks?.onOperationStart?.(info);
72
+ }
73
+ catch {
74
+ // Hooks should not interrupt operations
75
+ }
76
+ try {
77
+ const { data, error, response } = await fn();
78
+ result.durationMs = Math.round(performance.now() - start);
79
+ // Check for errors
80
+ if (!response.ok || error) {
81
+ const basecampError = await this.handleError(response, error);
82
+ result.error = basecampError;
83
+ throw basecampError;
84
+ }
85
+ // For void responses (204, etc.), return undefined as T
86
+ if (response.status === 204 || data === undefined) {
87
+ return undefined;
88
+ }
89
+ return data;
90
+ }
91
+ catch (err) {
92
+ result.durationMs = Math.round(performance.now() - start);
93
+ if (err instanceof BasecampError) {
94
+ result.error = err;
95
+ }
96
+ else if (err instanceof Error) {
97
+ result.error = err;
98
+ }
99
+ throw err;
100
+ }
101
+ finally {
102
+ // Always notify hooks of operation end (wrapped to prevent hook failures from breaking operations)
103
+ try {
104
+ this.hooks?.onOperationEnd?.(info, result);
105
+ }
106
+ catch {
107
+ // Hooks should not interrupt operations
108
+ }
109
+ }
110
+ }
111
+ /**
112
+ * Executes a paginated API request, automatically following Link headers.
113
+ *
114
+ * Returns a ListResult<T> which extends Array<T> — fully backwards-compatible
115
+ * with array operations, plus `.meta.totalCount` for total item count.
116
+ *
117
+ * @param info - Operation metadata for hooks
118
+ * @param fn - The function that performs the initial API call
119
+ * @param paginationOpts - Optional pagination control (maxItems)
120
+ * @returns A ListResult containing all items across pages
121
+ * @throws BasecampError on API errors or cross-origin Link headers
122
+ */
123
+ async requestPaginated(info, fn, paginationOpts) {
124
+ const start = performance.now();
125
+ let result = { durationMs: 0 };
126
+ // Notify hooks of operation start
127
+ try {
128
+ this.hooks?.onOperationStart?.(info);
129
+ }
130
+ catch {
131
+ // Hooks should not interrupt operations
132
+ }
133
+ try {
134
+ const { data, error, response } = await fn();
135
+ result.durationMs = Math.round(performance.now() - start);
136
+ // Check for errors
137
+ if (!response.ok || error) {
138
+ const basecampError = await this.handleError(response, error);
139
+ result.error = basecampError;
140
+ throw basecampError;
141
+ }
142
+ const firstPageItems = data ?? [];
143
+ const totalCount = parseTotalCount(response);
144
+ const maxItems = paginationOpts?.maxItems;
145
+ // If maxItems is set and first page satisfies it, return early
146
+ if (maxItems && maxItems > 0 && firstPageItems.length >= maxItems) {
147
+ // Only mark truncated if there are actually more items beyond maxItems
148
+ // (either more items on this page than maxItems, or a Link header for more pages)
149
+ const hasMore = firstPageItems.length > maxItems
150
+ || parseNextLink(response.headers.get("Link")) !== null;
151
+ result.durationMs = Math.round(performance.now() - start);
152
+ return new ListResult(firstPageItems.slice(0, maxItems), { totalCount, truncated: hasMore });
153
+ }
154
+ // Follow pagination
155
+ const { items: allItems, truncated } = await this.followPagination(response, firstPageItems, maxItems);
156
+ // Update duration to reflect total time across all pages
157
+ result.durationMs = Math.round(performance.now() - start);
158
+ return new ListResult(allItems, { totalCount, truncated });
159
+ }
160
+ catch (err) {
161
+ result.durationMs = Math.round(performance.now() - start);
162
+ if (err instanceof BasecampError) {
163
+ result.error = err;
164
+ }
165
+ else if (err instanceof Error) {
166
+ result.error = err;
167
+ }
168
+ throw err;
169
+ }
170
+ finally {
171
+ try {
172
+ this.hooks?.onOperationEnd?.(info, result);
173
+ }
174
+ catch {
175
+ // Hooks should not interrupt operations
176
+ }
177
+ }
178
+ }
179
+ /**
180
+ * Follows Link header pagination, accumulating items across pages.
181
+ * Returns items and whether results were truncated (by maxItems or page cap).
182
+ */
183
+ async followPagination(initialResponse, firstPageItems, maxItems) {
184
+ const allItems = [...firstPageItems];
185
+ let response = initialResponse;
186
+ const initialUrl = initialResponse.url;
187
+ for (let page = 1; page < MAX_PAGES; page++) {
188
+ const rawNextUrl = parseNextLink(response.headers.get("Link"));
189
+ if (!rawNextUrl)
190
+ break;
191
+ const nextUrl = resolveURL(response.url, rawNextUrl);
192
+ // Validate same-origin to prevent SSRF / token leakage
193
+ if (!isSameOrigin(nextUrl, initialUrl)) {
194
+ throw new BasecampError("api_error", `Pagination Link header points to different origin: ${nextUrl}`);
195
+ }
196
+ response = await this.fetchPage(nextUrl);
197
+ if (!response.ok) {
198
+ throw await errorFromResponse(response, response.headers.get("X-Request-Id") ?? undefined);
199
+ }
200
+ const pageItems = (await response.json());
201
+ allItems.push(...pageItems);
202
+ // Check maxItems cap
203
+ if (maxItems && maxItems > 0 && allItems.length >= maxItems) {
204
+ return { items: allItems.slice(0, maxItems), truncated: true };
205
+ }
206
+ }
207
+ // If we exited the loop because page >= MAX_PAGES and there's still a next link,
208
+ // the results are truncated by the safety cap
209
+ const hasMore = parseNextLink(response.headers.get("Link")) !== null;
210
+ return { items: allItems, truncated: hasMore };
211
+ }
212
+ /**
213
+ * Converts an HTTP error response to a typed BasecampError.
214
+ *
215
+ * @param response - The HTTP response
216
+ * @param error - Optional error object from openapi-fetch
217
+ * @returns A BasecampError with appropriate code and metadata
218
+ */
219
+ async handleError(response, error) {
220
+ // If already a BasecampError, just return it
221
+ if (error instanceof BasecampError) {
222
+ return error;
223
+ }
224
+ // Extract request ID from response headers if available
225
+ const requestId = response.headers.get("X-Request-Id") ?? undefined;
226
+ // Use the errorFromResponse helper to create the appropriate error
227
+ return errorFromResponse(response, requestId);
228
+ }
229
+ }
230
+ //# sourceMappingURL=base.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base.js","sourceRoot":"","sources":["../../src/services/base.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import type { RequestListener } from "node:http";
2
+ import { WebhookReceiver } from "../handler.js";
3
+ export interface NodeHandlerOptions {
4
+ /** URL path to handle (default: "/webhooks/basecamp"). Requests to other paths get 404. */
5
+ path?: string;
6
+ /** Maximum request body size in bytes (default: 1MB). Requests exceeding this get 413. */
7
+ maxBodyBytes?: number;
8
+ }
9
+ /**
10
+ * Create a Node.js HTTP request listener that dispatches to a WebhookReceiver.
11
+ * Returns 200 on success, 401 on bad signature, 405 on non-POST, 404 on wrong path.
12
+ */
13
+ export declare function createNodeHandler(receiver: WebhookReceiver, options?: NodeHandlerOptions): RequestListener;
14
+ //# sourceMappingURL=node-http.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"node-http.d.ts","sourceRoot":"","sources":["../../../src/webhooks/adapters/node-http.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAmC,eAAe,EAAE,MAAM,WAAW,CAAC;AAClF,OAAO,EAAE,eAAe,EAA4B,MAAM,eAAe,CAAC;AAE1E,MAAM,WAAW,kBAAkB;IACjC,2FAA2F;IAC3F,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,0FAA0F;IAC1F,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,eAAe,EACzB,OAAO,CAAC,EAAE,kBAAkB,GAC3B,eAAe,CAyDjB"}
@@ -0,0 +1,60 @@
1
+ import { WebhookVerificationError } from "../handler.js";
2
+ /**
3
+ * Create a Node.js HTTP request listener that dispatches to a WebhookReceiver.
4
+ * Returns 200 on success, 401 on bad signature, 405 on non-POST, 404 on wrong path.
5
+ */
6
+ export function createNodeHandler(receiver, options) {
7
+ const targetPath = options?.path ?? "/webhooks/basecamp";
8
+ const maxBodyBytes = options?.maxBodyBytes ?? 1_048_576; // 1MB
9
+ return (req, res) => {
10
+ // Parse URL path (handles both origin-form and absolute-form request targets)
11
+ const { pathname } = new URL(req.url ?? "/", "http://localhost");
12
+ if (pathname !== targetPath) {
13
+ res.writeHead(404);
14
+ res.end("Not Found");
15
+ return;
16
+ }
17
+ if (req.method !== "POST") {
18
+ res.writeHead(405);
19
+ res.end("Method Not Allowed");
20
+ return;
21
+ }
22
+ const chunks = [];
23
+ let totalBytes = 0;
24
+ req.on("data", (chunk) => {
25
+ totalBytes += chunk.length;
26
+ if (totalBytes <= maxBodyBytes) {
27
+ chunks.push(chunk);
28
+ }
29
+ });
30
+ req.on("end", () => {
31
+ if (totalBytes > maxBodyBytes) {
32
+ res.writeHead(413);
33
+ res.end("Payload Too Large");
34
+ return;
35
+ }
36
+ const body = Buffer.concat(chunks);
37
+ const headers = (name) => {
38
+ const val = req.headers[name.toLowerCase()];
39
+ return Array.isArray(val) ? val[0] : val;
40
+ };
41
+ receiver
42
+ .handleRequest(body, headers)
43
+ .then(() => {
44
+ res.writeHead(200);
45
+ res.end("OK");
46
+ })
47
+ .catch((err) => {
48
+ if (err instanceof WebhookVerificationError) {
49
+ res.writeHead(401);
50
+ res.end("Unauthorized");
51
+ }
52
+ else {
53
+ res.writeHead(500);
54
+ res.end("Internal Server Error");
55
+ }
56
+ });
57
+ });
58
+ };
59
+ }
60
+ //# sourceMappingURL=node-http.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"node-http.js","sourceRoot":"","sources":["../../../src/webhooks/adapters/node-http.ts"],"names":[],"mappings":"AACA,OAAO,EAAmB,wBAAwB,EAAE,MAAM,eAAe,CAAC;AAS1E;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAC/B,QAAyB,EACzB,OAA4B;IAE5B,MAAM,UAAU,GAAG,OAAO,EAAE,IAAI,IAAI,oBAAoB,CAAC;IACzD,MAAM,YAAY,GAAG,OAAO,EAAE,YAAY,IAAI,SAAS,CAAC,CAAC,MAAM;IAE/D,OAAO,CAAC,GAAoB,EAAE,GAAmB,EAAE,EAAE;QACnD,8EAA8E;QAC9E,MAAM,EAAE,QAAQ,EAAE,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,GAAG,IAAI,GAAG,EAAE,kBAAkB,CAAC,CAAC;QAEjE,IAAI,QAAQ,KAAK,UAAU,EAAE,CAAC;YAC5B,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;YACnB,GAAG,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;YACrB,OAAO;QACT,CAAC;QAED,IAAI,GAAG,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;YAC1B,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;YACnB,GAAG,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC;YAC9B,OAAO;QACT,CAAC;QAED,MAAM,MAAM,GAAa,EAAE,CAAC;QAC5B,IAAI,UAAU,GAAG,CAAC,CAAC;QACnB,GAAG,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAa,EAAE,EAAE;YAC/B,UAAU,IAAI,KAAK,CAAC,MAAM,CAAC;YAC3B,IAAI,UAAU,IAAI,YAAY,EAAE,CAAC;gBAC/B,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACrB,CAAC;QACH,CAAC,CAAC,CAAC;QACH,GAAG,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE;YACjB,IAAI,UAAU,GAAG,YAAY,EAAE,CAAC;gBAC9B,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;gBACnB,GAAG,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC;gBAC7B,OAAO;YACT,CAAC;YACD,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;YACnC,MAAM,OAAO,GAAG,CAAC,IAAY,EAAE,EAAE;gBAC/B,MAAM,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC;gBAC5C,OAAO,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;YAC3C,CAAC,CAAC;YAEF,QAAQ;iBACL,aAAa,CAAC,IAAI,EAAE,OAAO,CAAC;iBAC5B,IAAI,CAAC,GAAG,EAAE;gBACT,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;gBACnB,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YAChB,CAAC,CAAC;iBACD,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE;gBACtB,IAAI,GAAG,YAAY,wBAAwB,EAAE,CAAC;oBAC5C,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;oBACnB,GAAG,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;gBAC1B,CAAC;qBAAM,CAAC;oBACN,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;oBACnB,GAAG,CAAC,GAAG,CAAC,uBAAuB,CAAC,CAAC;gBACnC,CAAC;YACH,CAAC,CAAC,CAAC;QACP,CAAC,CAAC,CAAC;IACL,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,52 @@
1
+ import type { components } from "../generated/schema.js";
2
+ export type WebhookEvent = components["schemas"]["WebhookEvent"];
3
+ export type WebhookDelivery = components["schemas"]["WebhookDelivery"];
4
+ export type WebhookDeliveryRequest = components["schemas"]["WebhookDeliveryRequest"];
5
+ export type WebhookDeliveryResponse = components["schemas"]["WebhookDeliveryResponse"];
6
+ export type WebhookCopy = components["schemas"]["WebhookCopy"];
7
+ /**
8
+ * Parse "todo_created" → { type: "todo", action: "created" }.
9
+ * For compound types like "question_answer_created" → { type: "question_answer", action: "created" }.
10
+ * The action is always the last underscore-separated segment.
11
+ */
12
+ export declare function parseEventKind(kind: string): {
13
+ type: string;
14
+ action: string;
15
+ };
16
+ /** Known webhook event kind strings (convenience constants, not exhaustive). */
17
+ export declare const WebhookEventKind: {
18
+ readonly TodoCreated: "todo_created";
19
+ readonly TodoCompleted: "todo_completed";
20
+ readonly TodoUncompleted: "todo_uncompleted";
21
+ readonly TodoChanged: "todo_changed";
22
+ readonly TodolistCreated: "todolist_created";
23
+ readonly TodolistChanged: "todolist_changed";
24
+ readonly MessageCreated: "message_created";
25
+ readonly MessageChanged: "message_changed";
26
+ readonly CommentCreated: "comment_created";
27
+ readonly CommentChanged: "comment_changed";
28
+ readonly DocumentCreated: "document_created";
29
+ readonly DocumentChanged: "document_changed";
30
+ readonly UploadCreated: "upload_created";
31
+ readonly UploadChanged: "upload_changed";
32
+ readonly QuestionAnswerCreated: "question_answer_created";
33
+ readonly QuestionAnswerChanged: "question_answer_changed";
34
+ readonly ScheduleEntryCreated: "schedule_entry_created";
35
+ readonly ScheduleEntryChanged: "schedule_entry_changed";
36
+ readonly CloudFileCreated: "cloud_file_created";
37
+ readonly VaultCreated: "vault_created";
38
+ readonly InboxForwardCreated: "inbox_forward_created";
39
+ readonly ForwardReplyCreated: "forward_reply_created";
40
+ readonly ClientReplyCreated: "client_reply_created";
41
+ readonly ClientApprovalCreated: "client_approval_created";
42
+ readonly ClientApprovalChanged: "client_approval_changed";
43
+ readonly TodoCopied: "todo_copied";
44
+ readonly MessageCopied: "message_copied";
45
+ readonly TodoArchived: "todo_archived";
46
+ readonly TodoUnarchived: "todo_unarchived";
47
+ readonly TodoTrashed: "todo_trashed";
48
+ readonly MessageArchived: "message_archived";
49
+ readonly MessageUnarchived: "message_unarchived";
50
+ readonly MessageTrashed: "message_trashed";
51
+ };
52
+ //# sourceMappingURL=events.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../../src/webhooks/events.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAGzD,MAAM,MAAM,YAAY,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC,cAAc,CAAC,CAAC;AACjE,MAAM,MAAM,eAAe,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC,iBAAiB,CAAC,CAAC;AACvE,MAAM,MAAM,sBAAsB,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC,wBAAwB,CAAC,CAAC;AACrF,MAAM,MAAM,uBAAuB,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC,yBAAyB,CAAC,CAAC;AACvF,MAAM,MAAM,WAAW,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC,aAAa,CAAC,CAAC;AAE/D;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAS7E;AAED,gFAAgF;AAChF,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAkCnB,CAAC"}