@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,324 @@
1
+ /**
2
+ * OAuth 2.0 token exchange and refresh for Basecamp SDK.
3
+ *
4
+ * Handles authorization code exchange and token refresh operations.
5
+ * Supports both standard OAuth 2.0 and Basecamp's Launchpad legacy format.
6
+ */
7
+ import { BasecampError } from "../errors.js";
8
+ import { isLocalhost } from "../security.js";
9
+ /**
10
+ * Exchanges an authorization code for access and refresh tokens.
11
+ *
12
+ * Supports both standard OAuth 2.0 and Basecamp's Launchpad legacy format.
13
+ * Use `useLegacyFormat: true` for Launchpad compatibility.
14
+ *
15
+ * @param request - Exchange request parameters
16
+ * @param options - Optional configuration
17
+ * @returns The token response
18
+ * @throws BasecampError on validation, network, or authentication errors
19
+ *
20
+ * @example
21
+ * ```ts
22
+ * // Standard OAuth 2.0
23
+ * const token = await exchangeCode({
24
+ * tokenEndpoint: config.tokenEndpoint,
25
+ * code: "auth_code_from_callback",
26
+ * redirectUri: "https://myapp.com/callback",
27
+ * clientId: "my_client_id",
28
+ * clientSecret: "my_client_secret",
29
+ * });
30
+ *
31
+ * // Launchpad legacy format
32
+ * const token = await exchangeCode({
33
+ * tokenEndpoint: "https://launchpad.37signals.com/authorization/token",
34
+ * code: "auth_code",
35
+ * redirectUri: "https://myapp.com/callback",
36
+ * clientId: "my_client_id",
37
+ * clientSecret: "my_client_secret",
38
+ * useLegacyFormat: true,
39
+ * });
40
+ * ```
41
+ */
42
+ export async function exchangeCode(request, options = {}) {
43
+ // Validate required fields
44
+ if (!request.tokenEndpoint) {
45
+ throw new BasecampError("validation", "Token endpoint is required");
46
+ }
47
+ if (!request.code) {
48
+ throw new BasecampError("validation", "Authorization code is required");
49
+ }
50
+ if (!request.redirectUri) {
51
+ throw new BasecampError("validation", "Redirect URI is required");
52
+ }
53
+ if (!request.clientId) {
54
+ throw new BasecampError("validation", "Client ID is required");
55
+ }
56
+ // Build request body
57
+ const body = new URLSearchParams();
58
+ if (request.useLegacyFormat) {
59
+ // Launchpad uses non-standard "type" parameter
60
+ body.set("type", "web_server");
61
+ }
62
+ else {
63
+ // Standard OAuth 2.0
64
+ body.set("grant_type", "authorization_code");
65
+ }
66
+ body.set("code", request.code);
67
+ body.set("redirect_uri", request.redirectUri);
68
+ body.set("client_id", request.clientId);
69
+ if (request.clientSecret) {
70
+ body.set("client_secret", request.clientSecret);
71
+ }
72
+ if (request.codeVerifier) {
73
+ body.set("code_verifier", request.codeVerifier);
74
+ }
75
+ return doTokenRequest(request.tokenEndpoint, body, options);
76
+ }
77
+ /**
78
+ * Refreshes an access token using a refresh token.
79
+ *
80
+ * Supports both standard OAuth 2.0 and Basecamp's Launchpad legacy format.
81
+ * Use `useLegacyFormat: true` for Launchpad compatibility.
82
+ *
83
+ * @param request - Refresh request parameters
84
+ * @param options - Optional configuration
85
+ * @returns The new token response
86
+ * @throws BasecampError on validation, network, or authentication errors
87
+ *
88
+ * @example
89
+ * ```ts
90
+ * // Standard OAuth 2.0
91
+ * const newToken = await refreshToken({
92
+ * tokenEndpoint: config.tokenEndpoint,
93
+ * refreshToken: oldToken.refreshToken,
94
+ * clientId: "my_client_id",
95
+ * clientSecret: "my_client_secret",
96
+ * });
97
+ *
98
+ * // Launchpad legacy format
99
+ * const newToken = await refreshToken({
100
+ * tokenEndpoint: "https://launchpad.37signals.com/authorization/token",
101
+ * refreshToken: oldToken.refreshToken,
102
+ * useLegacyFormat: true,
103
+ * });
104
+ * ```
105
+ */
106
+ export async function refreshToken(request, options = {}) {
107
+ // Validate required fields
108
+ if (!request.tokenEndpoint) {
109
+ throw new BasecampError("validation", "Token endpoint is required");
110
+ }
111
+ if (!request.refreshToken) {
112
+ throw new BasecampError("validation", "Refresh token is required");
113
+ }
114
+ // Build request body
115
+ const body = new URLSearchParams();
116
+ if (request.useLegacyFormat) {
117
+ // Launchpad uses non-standard "type" parameter
118
+ body.set("type", "refresh");
119
+ }
120
+ else {
121
+ // Standard OAuth 2.0
122
+ body.set("grant_type", "refresh_token");
123
+ }
124
+ body.set("refresh_token", request.refreshToken);
125
+ if (request.clientId) {
126
+ body.set("client_id", request.clientId);
127
+ }
128
+ if (request.clientSecret) {
129
+ body.set("client_secret", request.clientSecret);
130
+ }
131
+ return doTokenRequest(request.tokenEndpoint, body, options);
132
+ }
133
+ /**
134
+ * Validates that a URL uses the HTTPS scheme (allows localhost for testing).
135
+ */
136
+ function requireHTTPS(url, label) {
137
+ try {
138
+ const parsed = new URL(url);
139
+ if (parsed.protocol !== "https:" && !isLocalhost(parsed.hostname)) {
140
+ throw new BasecampError("validation", `${label} must use HTTPS: ${url}`);
141
+ }
142
+ }
143
+ catch (err) {
144
+ if (err instanceof BasecampError)
145
+ throw err;
146
+ throw new BasecampError("validation", `Invalid ${label}: ${url}`);
147
+ }
148
+ }
149
+ /**
150
+ * Parses Content-Length header, returning null for missing/invalid values.
151
+ * Treats non-numeric or negative values as invalid (fail closed).
152
+ */
153
+ function parseContentLength(header) {
154
+ if (!header)
155
+ return null;
156
+ const parsed = parseInt(header, 10);
157
+ // NaN, negative, or non-integer values are invalid
158
+ if (!Number.isInteger(parsed) || parsed < 0)
159
+ return null;
160
+ // Reject if the header contains non-digit characters (e.g., "123abc")
161
+ if (!/^\d+$/.test(header.trim()))
162
+ return null;
163
+ return parsed;
164
+ }
165
+ /**
166
+ * Reads a response body with streaming byte limit.
167
+ * Uses true byte counting even when Content-Length is absent or inaccurate.
168
+ */
169
+ async function readResponseWithByteLimit(response, maxBytes, httpStatus) {
170
+ // Parse Content-Length, treating invalid values as missing (fail closed)
171
+ const contentLengthBytes = parseContentLength(response.headers.get("Content-Length"));
172
+ // Fast path: reject if Content-Length exceeds limit
173
+ if (contentLengthBytes !== null && contentLengthBytes > maxBytes) {
174
+ throw new BasecampError("api_error", `Token response too large (Content-Length: ${contentLengthBytes} bytes, max ${maxBytes})`, { httpStatus });
175
+ }
176
+ // If no body or body isn't streamable, require valid Content-Length
177
+ if (!response.body) {
178
+ // If Content-Length is missing or invalid, we cannot protect against DoS - fail closed.
179
+ // If it was valid and within limits, we can safely read.
180
+ if (contentLengthBytes === null) {
181
+ throw new BasecampError("api_error", "Cannot safely read token response: no valid Content-Length header and streaming unavailable", { httpStatus });
182
+ }
183
+ // Content-Length was valid and within limits, safe to read
184
+ return response.text();
185
+ }
186
+ // Stream with byte counting
187
+ const reader = response.body.getReader();
188
+ const chunks = [];
189
+ let totalBytes = 0;
190
+ try {
191
+ while (true) {
192
+ const { done, value } = await reader.read();
193
+ if (done)
194
+ break;
195
+ totalBytes += value.length;
196
+ if (totalBytes > maxBytes) {
197
+ reader.cancel();
198
+ throw new BasecampError("api_error", `Token response too large (${totalBytes}+ bytes, max ${maxBytes})`, { httpStatus });
199
+ }
200
+ chunks.push(value);
201
+ }
202
+ }
203
+ finally {
204
+ reader.releaseLock();
205
+ }
206
+ // Concatenate and decode
207
+ const combined = new Uint8Array(totalBytes);
208
+ let offset = 0;
209
+ for (const chunk of chunks) {
210
+ combined.set(chunk, offset);
211
+ offset += chunk.length;
212
+ }
213
+ return new TextDecoder().decode(combined);
214
+ }
215
+ /**
216
+ * Performs the actual HTTP token request.
217
+ */
218
+ async function doTokenRequest(tokenEndpoint, body, options) {
219
+ requireHTTPS(tokenEndpoint, "token endpoint");
220
+ const { fetch: customFetch = globalThis.fetch, timeoutMs = 30000 } = options;
221
+ // Create abort controller for timeout
222
+ const controller = new AbortController();
223
+ const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
224
+ try {
225
+ const response = await customFetch(tokenEndpoint, {
226
+ method: "POST",
227
+ headers: {
228
+ "Content-Type": "application/x-www-form-urlencoded",
229
+ Accept: "application/json",
230
+ },
231
+ body: body.toString(),
232
+ signal: controller.signal,
233
+ });
234
+ const MAX_TOKEN_RESPONSE_BYTES = 1 * 1024 * 1024; // 1 MB
235
+ // Use streaming reader with true byte-level limit enforcement.
236
+ // This handles cases where Content-Length is absent or inaccurate.
237
+ const responseText = await readResponseWithByteLimit(response, MAX_TOKEN_RESPONSE_BYTES, response.status);
238
+ let data;
239
+ try {
240
+ data = JSON.parse(responseText);
241
+ }
242
+ catch {
243
+ // Truncate response text to avoid leaking sensitive data in error messages
244
+ const truncated = responseText.length > 500 ? responseText.slice(0, 497) + "..." : responseText;
245
+ throw new BasecampError("api_error", `Failed to parse token response: ${truncated}`, { httpStatus: response.status });
246
+ }
247
+ // Check for error response
248
+ if (!response.ok) {
249
+ const errorData = data;
250
+ const rawMessage = errorData.error_description || errorData.error || "Token request failed";
251
+ const message = rawMessage.length > 500 ? rawMessage.slice(0, 497) + "..." : rawMessage;
252
+ if (response.status === 401 || errorData.error === "invalid_grant") {
253
+ throw new BasecampError("auth", message, {
254
+ httpStatus: response.status,
255
+ hint: "The authorization code or refresh token may be invalid or expired",
256
+ });
257
+ }
258
+ throw new BasecampError("api_error", message, {
259
+ httpStatus: response.status,
260
+ });
261
+ }
262
+ // Parse successful response
263
+ const tokenData = data;
264
+ if (!tokenData.access_token) {
265
+ throw new BasecampError("api_error", "Token response missing access_token");
266
+ }
267
+ return {
268
+ accessToken: tokenData.access_token,
269
+ refreshToken: tokenData.refresh_token,
270
+ tokenType: tokenData.token_type || "Bearer",
271
+ expiresIn: tokenData.expires_in,
272
+ expiresAt: tokenData.expires_in
273
+ ? new Date(Date.now() + tokenData.expires_in * 1000)
274
+ : undefined,
275
+ scope: tokenData.scope,
276
+ };
277
+ }
278
+ catch (err) {
279
+ if (err instanceof BasecampError) {
280
+ throw err;
281
+ }
282
+ if (err instanceof Error) {
283
+ if (err.name === "AbortError") {
284
+ throw new BasecampError("network", "Token request timed out", {
285
+ cause: err,
286
+ retryable: true,
287
+ });
288
+ }
289
+ throw new BasecampError("network", `Token request failed: ${err.message}`, {
290
+ cause: err,
291
+ retryable: true,
292
+ });
293
+ }
294
+ throw new BasecampError("network", "Token request failed with unknown error", {
295
+ retryable: true,
296
+ });
297
+ }
298
+ finally {
299
+ clearTimeout(timeoutId);
300
+ }
301
+ }
302
+ /**
303
+ * Checks if a token is expired or about to expire.
304
+ *
305
+ * @param token - The token to check
306
+ * @param bufferSeconds - Buffer time before actual expiration (default: 60)
307
+ * @returns true if the token is expired or will expire within the buffer time
308
+ *
309
+ * @example
310
+ * ```ts
311
+ * if (isTokenExpired(token)) {
312
+ * token = await refreshToken({ ... });
313
+ * }
314
+ * ```
315
+ */
316
+ export function isTokenExpired(token, bufferSeconds = 60) {
317
+ if (!token.expiresAt) {
318
+ // No expiration info - assume not expired
319
+ return false;
320
+ }
321
+ const bufferMs = bufferSeconds * 1000;
322
+ return Date.now() + bufferMs >= token.expiresAt.getTime();
323
+ }
324
+ //# sourceMappingURL=exchange.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exchange.js","sourceRoot":"","sources":["../../src/oauth/exchange.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * OAuth identity discovery for Basecamp SDK.
3
+ *
4
+ * Fetches authorization information (identity and accounts) from
5
+ * the Launchpad endpoint without requiring a full client instance.
6
+ */
7
+ import type { TokenProvider } from "../client.js";
8
+ import type { AuthorizationInfo } from "../services/authorization.js";
9
+ /**
10
+ * Fetches authorization information using an access token.
11
+ *
12
+ * Calls the Launchpad authorization endpoint to retrieve the
13
+ * authenticated user's identity and list of accessible accounts.
14
+ * Does not require a full Basecamp client instance.
15
+ *
16
+ * @param accessToken - A token string or async function returning one
17
+ * @returns Authorization information including identity and accounts
18
+ * @throws BasecampError on network or auth errors
19
+ *
20
+ * @example
21
+ * ```ts
22
+ * const info = await discoverIdentity("my_access_token");
23
+ * console.log(info.identity.firstName, info.identity.lastName);
24
+ * for (const account of info.accounts) {
25
+ * console.log(`${account.name} (${account.product})`);
26
+ * }
27
+ * ```
28
+ */
29
+ export declare function discoverIdentity(accessToken: TokenProvider): Promise<AuthorizationInfo>;
30
+ //# sourceMappingURL=identity.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"identity.d.ts","sourceRoot":"","sources":["../../src/oauth/identity.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AA2BtE;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAsB,gBAAgB,CAAC,WAAW,EAAE,aAAa,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAsD7F"}
@@ -0,0 +1,82 @@
1
+ /**
2
+ * OAuth identity discovery for Basecamp SDK.
3
+ *
4
+ * Fetches authorization information (identity and accounts) from
5
+ * the Launchpad endpoint without requiring a full client instance.
6
+ */
7
+ import { BasecampError } from "../errors.js";
8
+ const AUTHORIZATION_ENDPOINT = "https://launchpad.37signals.com/authorization.json";
9
+ /**
10
+ * Fetches authorization information using an access token.
11
+ *
12
+ * Calls the Launchpad authorization endpoint to retrieve the
13
+ * authenticated user's identity and list of accessible accounts.
14
+ * Does not require a full Basecamp client instance.
15
+ *
16
+ * @param accessToken - A token string or async function returning one
17
+ * @returns Authorization information including identity and accounts
18
+ * @throws BasecampError on network or auth errors
19
+ *
20
+ * @example
21
+ * ```ts
22
+ * const info = await discoverIdentity("my_access_token");
23
+ * console.log(info.identity.firstName, info.identity.lastName);
24
+ * for (const account of info.accounts) {
25
+ * console.log(`${account.name} (${account.product})`);
26
+ * }
27
+ * ```
28
+ */
29
+ export async function discoverIdentity(accessToken) {
30
+ const token = typeof accessToken === "function" ? await accessToken() : accessToken;
31
+ let response;
32
+ try {
33
+ response = await fetch(AUTHORIZATION_ENDPOINT, {
34
+ method: "GET",
35
+ headers: {
36
+ Authorization: `Bearer ${token}`,
37
+ Accept: "application/json",
38
+ },
39
+ });
40
+ }
41
+ catch (err) {
42
+ throw new BasecampError("network", `Identity discovery failed: ${err instanceof Error ? err.message : String(err)}`);
43
+ }
44
+ if (!response.ok) {
45
+ if (response.status === 401) {
46
+ throw new BasecampError("auth", "Invalid or expired access token", {
47
+ httpStatus: 401,
48
+ hint: "The access token may need to be refreshed",
49
+ });
50
+ }
51
+ throw new BasecampError("api_error", `Authorization endpoint returned ${response.status}`, {
52
+ httpStatus: response.status,
53
+ });
54
+ }
55
+ let raw;
56
+ try {
57
+ raw = (await response.json());
58
+ }
59
+ catch {
60
+ throw new BasecampError("api_error", "Identity discovery returned invalid JSON");
61
+ }
62
+ return {
63
+ expiresAt: new Date(raw.expires_at),
64
+ identity: {
65
+ id: raw.identity.id,
66
+ firstName: raw.identity.first_name,
67
+ lastName: raw.identity.last_name,
68
+ emailAddress: raw.identity.email_address,
69
+ },
70
+ accounts: raw.accounts.map((a) => ({
71
+ id: a.id,
72
+ name: a.name,
73
+ product: a.product,
74
+ href: a.href,
75
+ appHref: a.app_href ?? "",
76
+ hidden: a.hidden,
77
+ expired: a.expired,
78
+ featured: a.featured,
79
+ })),
80
+ };
81
+ }
82
+ //# sourceMappingURL=identity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"identity.js","sourceRoot":"","sources":["../../src/oauth/identity.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AA2B7C,MAAM,sBAAsB,GAAG,oDAAoD,CAAC;AAEpF;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,WAA0B;IAC/D,MAAM,KAAK,GAAG,OAAO,WAAW,KAAK,UAAU,CAAC,CAAC,CAAC,MAAM,WAAW,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC;IAEpF,IAAI,QAAkB,CAAC;IACvB,IAAI,CAAC;QACH,QAAQ,GAAG,MAAM,KAAK,CAAC,sBAAsB,EAAE;YAC7C,MAAM,EAAE,KAAK;YACb,OAAO,EAAE;gBACP,aAAa,EAAE,UAAU,KAAK,EAAE;gBAChC,MAAM,EAAE,kBAAkB;aAC3B;SACF,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,IAAI,aAAa,CAAC,SAAS,EAAE,8BAA8B,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IACvH,CAAC;IAED,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;YAC5B,MAAM,IAAI,aAAa,CAAC,MAAM,EAAE,iCAAiC,EAAE;gBACjE,UAAU,EAAE,GAAG;gBACf,IAAI,EAAE,2CAA2C;aAClD,CAAC,CAAC;QACL,CAAC;QACD,MAAM,IAAI,aAAa,CAAC,WAAW,EAAE,mCAAmC,QAAQ,CAAC,MAAM,EAAE,EAAE;YACzF,UAAU,EAAE,QAAQ,CAAC,MAAM;SAC5B,CAAC,CAAC;IACL,CAAC;IAED,IAAI,GAA6B,CAAC;IAClC,IAAI,CAAC;QACH,GAAG,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAA6B,CAAC;IAC5D,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,aAAa,CAAC,WAAW,EAAE,0CAA0C,CAAC,CAAC;IACnF,CAAC;IAED,OAAO;QACL,SAAS,EAAE,IAAI,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC;QACnC,QAAQ,EAAE;YACR,EAAE,EAAE,GAAG,CAAC,QAAQ,CAAC,EAAE;YACnB,SAAS,EAAE,GAAG,CAAC,QAAQ,CAAC,UAAU;YAClC,QAAQ,EAAE,GAAG,CAAC,QAAQ,CAAC,SAAS;YAChC,YAAY,EAAE,GAAG,CAAC,QAAQ,CAAC,aAAa;SACzC;QACD,QAAQ,EAAE,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACjC,EAAE,EAAE,CAAC,CAAC,EAAE;YACR,IAAI,EAAE,CAAC,CAAC,IAAI;YACZ,OAAO,EAAE,CAAC,CAAC,OAAO;YAClB,IAAI,EAAE,CAAC,CAAC,IAAI;YACZ,OAAO,EAAE,CAAC,CAAC,QAAQ,IAAI,EAAE;YACzB,MAAM,EAAE,CAAC,CAAC,MAAM;YAChB,OAAO,EAAE,CAAC,CAAC,OAAO;YAClB,QAAQ,EAAE,CAAC,CAAC,QAAQ;SACrB,CAAC,CAAC;KACJ,CAAC;AACJ,CAAC"}
@@ -0,0 +1,50 @@
1
+ /**
2
+ * OAuth 2.0 module for Basecamp SDK.
3
+ *
4
+ * Provides OAuth discovery, token exchange, and token refresh functionality.
5
+ * Supports both standard OAuth 2.0 and Basecamp's Launchpad legacy format.
6
+ *
7
+ * @example
8
+ * ```ts
9
+ * import { discover, exchangeCode, refreshToken, isTokenExpired } from "@basecamp/sdk/oauth";
10
+ *
11
+ * // 1. Discover OAuth configuration
12
+ * const config = await discover("https://launchpad.37signals.com");
13
+ *
14
+ * // 2. Exchange authorization code for tokens
15
+ * const token = await exchangeCode({
16
+ * tokenEndpoint: config.tokenEndpoint,
17
+ * code: "auth_code_from_callback",
18
+ * redirectUri: "https://myapp.com/callback",
19
+ * clientId: process.env.BASECAMP_CLIENT_ID!,
20
+ * clientSecret: process.env.BASECAMP_CLIENT_SECRET!,
21
+ * useLegacyFormat: true, // Required for Launchpad
22
+ * });
23
+ *
24
+ * // 3. Use the token
25
+ * const client = createBasecampClient({
26
+ * accountId: "12345",
27
+ * accessToken: token.accessToken,
28
+ * });
29
+ *
30
+ * // 4. Refresh when needed
31
+ * if (isTokenExpired(token)) {
32
+ * const newToken = await refreshToken({
33
+ * tokenEndpoint: config.tokenEndpoint,
34
+ * refreshToken: token.refreshToken!,
35
+ * useLegacyFormat: true,
36
+ * });
37
+ * }
38
+ * ```
39
+ */
40
+ export type { OAuthConfig, OAuthToken, ExchangeRequest, RefreshRequest, RawTokenResponse, OAuthErrorResponse, } from "./types.js";
41
+ export { discover, discoverLaunchpad, LAUNCHPAD_BASE_URL, type DiscoverOptions, } from "./discovery.js";
42
+ export { exchangeCode, refreshToken, isTokenExpired, type TokenOptions, } from "./exchange.js";
43
+ export { generatePKCE, generateState, type PKCE, } from "./pkce.js";
44
+ export { buildAuthorizationUrl, type AuthorizeParams, } from "./authorize.js";
45
+ export { FileTokenStore, type TokenStore, } from "./token-store.js";
46
+ export { TokenManager, type TokenManagerOptions, } from "./token-manager.js";
47
+ export { startCallbackServer, type CallbackResult, type CallbackServerOptions, } from "./callback-server.js";
48
+ export { performInteractiveLogin, type InteractiveLoginOptions, } from "./interactive-login.js";
49
+ export { discoverIdentity, } from "./identity.js";
50
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/oauth/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AAGH,YAAY,EACV,WAAW,EACX,UAAU,EACV,eAAe,EACf,cAAc,EACd,gBAAgB,EAChB,kBAAkB,GACnB,MAAM,YAAY,CAAC;AAGpB,OAAO,EACL,QAAQ,EACR,iBAAiB,EACjB,kBAAkB,EAClB,KAAK,eAAe,GACrB,MAAM,gBAAgB,CAAC;AAGxB,OAAO,EACL,YAAY,EACZ,YAAY,EACZ,cAAc,EACd,KAAK,YAAY,GAClB,MAAM,eAAe,CAAC;AAGvB,OAAO,EACL,YAAY,EACZ,aAAa,EACb,KAAK,IAAI,GACV,MAAM,WAAW,CAAC;AAGnB,OAAO,EACL,qBAAqB,EACrB,KAAK,eAAe,GACrB,MAAM,gBAAgB,CAAC;AAGxB,OAAO,EACL,cAAc,EACd,KAAK,UAAU,GAChB,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EACL,YAAY,EACZ,KAAK,mBAAmB,GACzB,MAAM,oBAAoB,CAAC;AAG5B,OAAO,EACL,mBAAmB,EACnB,KAAK,cAAc,EACnB,KAAK,qBAAqB,GAC3B,MAAM,sBAAsB,CAAC;AAG9B,OAAO,EACL,uBAAuB,EACvB,KAAK,uBAAuB,GAC7B,MAAM,wBAAwB,CAAC;AAGhC,OAAO,EACL,gBAAgB,GACjB,MAAM,eAAe,CAAC"}
@@ -0,0 +1,58 @@
1
+ /**
2
+ * OAuth 2.0 module for Basecamp SDK.
3
+ *
4
+ * Provides OAuth discovery, token exchange, and token refresh functionality.
5
+ * Supports both standard OAuth 2.0 and Basecamp's Launchpad legacy format.
6
+ *
7
+ * @example
8
+ * ```ts
9
+ * import { discover, exchangeCode, refreshToken, isTokenExpired } from "@basecamp/sdk/oauth";
10
+ *
11
+ * // 1. Discover OAuth configuration
12
+ * const config = await discover("https://launchpad.37signals.com");
13
+ *
14
+ * // 2. Exchange authorization code for tokens
15
+ * const token = await exchangeCode({
16
+ * tokenEndpoint: config.tokenEndpoint,
17
+ * code: "auth_code_from_callback",
18
+ * redirectUri: "https://myapp.com/callback",
19
+ * clientId: process.env.BASECAMP_CLIENT_ID!,
20
+ * clientSecret: process.env.BASECAMP_CLIENT_SECRET!,
21
+ * useLegacyFormat: true, // Required for Launchpad
22
+ * });
23
+ *
24
+ * // 3. Use the token
25
+ * const client = createBasecampClient({
26
+ * accountId: "12345",
27
+ * accessToken: token.accessToken,
28
+ * });
29
+ *
30
+ * // 4. Refresh when needed
31
+ * if (isTokenExpired(token)) {
32
+ * const newToken = await refreshToken({
33
+ * tokenEndpoint: config.tokenEndpoint,
34
+ * refreshToken: token.refreshToken!,
35
+ * useLegacyFormat: true,
36
+ * });
37
+ * }
38
+ * ```
39
+ */
40
+ // Discovery
41
+ export { discover, discoverLaunchpad, LAUNCHPAD_BASE_URL, } from "./discovery.js";
42
+ // Token exchange
43
+ export { exchangeCode, refreshToken, isTokenExpired, } from "./exchange.js";
44
+ // PKCE utilities
45
+ export { generatePKCE, generateState, } from "./pkce.js";
46
+ // Authorization URL
47
+ export { buildAuthorizationUrl, } from "./authorize.js";
48
+ // Token store
49
+ export { FileTokenStore, } from "./token-store.js";
50
+ // Token manager
51
+ export { TokenManager, } from "./token-manager.js";
52
+ // Callback server
53
+ export { startCallbackServer, } from "./callback-server.js";
54
+ // Interactive login
55
+ export { performInteractiveLogin, } from "./interactive-login.js";
56
+ // Identity
57
+ export { discoverIdentity, } from "./identity.js";
58
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/oauth/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AAYH,YAAY;AACZ,OAAO,EACL,QAAQ,EACR,iBAAiB,EACjB,kBAAkB,GAEnB,MAAM,gBAAgB,CAAC;AAExB,iBAAiB;AACjB,OAAO,EACL,YAAY,EACZ,YAAY,EACZ,cAAc,GAEf,MAAM,eAAe,CAAC;AAEvB,iBAAiB;AACjB,OAAO,EACL,YAAY,EACZ,aAAa,GAEd,MAAM,WAAW,CAAC;AAEnB,oBAAoB;AACpB,OAAO,EACL,qBAAqB,GAEtB,MAAM,gBAAgB,CAAC;AAExB,cAAc;AACd,OAAO,EACL,cAAc,GAEf,MAAM,kBAAkB,CAAC;AAE1B,gBAAgB;AAChB,OAAO,EACL,YAAY,GAEb,MAAM,oBAAoB,CAAC;AAE5B,kBAAkB;AAClB,OAAO,EACL,mBAAmB,GAGpB,MAAM,sBAAsB,CAAC;AAE9B,oBAAoB;AACpB,OAAO,EACL,uBAAuB,GAExB,MAAM,wBAAwB,CAAC;AAEhC,WAAW;AACX,OAAO,EACL,gBAAgB,GACjB,MAAM,eAAe,CAAC"}
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Interactive OAuth login flow for CLI and desktop applications.
3
+ *
4
+ * Orchestrates the full OAuth 2.0 authorization code flow:
5
+ * discovery, PKCE, local callback server, browser launch, code exchange.
6
+ */
7
+ import type { TokenStore } from "./token-store.js";
8
+ import type { OAuthToken } from "./types.js";
9
+ /**
10
+ * Options for the interactive login flow.
11
+ */
12
+ export interface InteractiveLoginOptions {
13
+ /** The client identifier */
14
+ clientId: string;
15
+ /** The client secret (optional for public clients) */
16
+ clientSecret?: string;
17
+ /** Token store for persisting the resulting token */
18
+ store: TokenStore;
19
+ /** OAuth server base URL (defaults to Launchpad) */
20
+ baseUrl?: string;
21
+ /** Use Launchpad's non-standard token format (default: true) */
22
+ useLegacyFormat?: boolean;
23
+ /** Port for the local callback server (optional) */
24
+ callbackPort?: number;
25
+ /** Function to open the authorization URL in a browser */
26
+ openBrowser: (url: string) => Promise<void>;
27
+ /** Fallback for when browser launch fails — prompt user to visit URL manually */
28
+ promptForManualVisit?: (authUrl: string) => Promise<void>;
29
+ /** Status callback for progress messages */
30
+ onStatus?: (message: string) => void;
31
+ }
32
+ /**
33
+ * Performs the full interactive OAuth login flow.
34
+ *
35
+ * Steps:
36
+ * 1. Discover OAuth endpoints
37
+ * 2. Generate PKCE and state parameters
38
+ * 3. Start local callback server
39
+ * 4. Build authorization URL and open browser
40
+ * 5. Wait for callback with authorization code
41
+ * 6. Exchange code for tokens
42
+ * 7. Save token to store
43
+ *
44
+ * @param options - Login flow configuration
45
+ * @returns The resulting OAuth token
46
+ * @throws BasecampError on any flow failure
47
+ *
48
+ * @example
49
+ * ```ts
50
+ * import open from "open"; // or use child_process
51
+ *
52
+ * const token = await performInteractiveLogin({
53
+ * clientId: process.env.BASECAMP_CLIENT_ID!,
54
+ * clientSecret: process.env.BASECAMP_CLIENT_SECRET!,
55
+ * store: new FileTokenStore("~/.config/basecamp/tokens.json"),
56
+ * openBrowser: (url) => open(url),
57
+ * onStatus: (msg) => console.log(msg),
58
+ * });
59
+ * ```
60
+ */
61
+ export declare function performInteractiveLogin(options: InteractiveLoginOptions): Promise<OAuthToken>;
62
+ //# sourceMappingURL=interactive-login.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"interactive-login.d.ts","sourceRoot":"","sources":["../../src/oauth/interactive-login.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAOH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAG7C;;GAEG;AACH,MAAM,WAAW,uBAAuB;IACtC,4BAA4B;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,sDAAsD;IACtD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,qDAAqD;IACrD,KAAK,EAAE,UAAU,CAAC;IAClB,oDAAoD;IACpD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,gEAAgE;IAChE,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,oDAAoD;IACpD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,0DAA0D;IAC1D,WAAW,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5C,iFAAiF;IACjF,oBAAoB,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1D,4CAA4C;IAC5C,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CACtC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAsB,uBAAuB,CAC3C,OAAO,EAAE,uBAAuB,GAC/B,OAAO,CAAC,UAAU,CAAC,CAgFrB"}