@ikatec/digisac-api-sdk 4.9.0 → 4.10.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 (283) hide show
  1. package/README.md +36 -12
  2. package/dist/apis/absence/AbsenceApi.cjs +12 -0
  3. package/dist/apis/absence/AbsenceApi.cjs.map +1 -1
  4. package/dist/apis/absence/AbsenceApi.d.ts +9 -0
  5. package/dist/apis/absence/AbsenceApi.d.ts.map +1 -1
  6. package/dist/apis/absence/AbsenceApi.mjs +12 -0
  7. package/dist/apis/absence/AbsenceApi.mjs.map +1 -1
  8. package/dist/apis/acceptanceTerms/AcceptanceTermsApi.cjs +8 -0
  9. package/dist/apis/acceptanceTerms/AcceptanceTermsApi.cjs.map +1 -1
  10. package/dist/apis/acceptanceTerms/AcceptanceTermsApi.d.ts +8 -1
  11. package/dist/apis/acceptanceTerms/AcceptanceTermsApi.d.ts.map +1 -1
  12. package/dist/apis/acceptanceTerms/AcceptanceTermsApi.mjs +8 -0
  13. package/dist/apis/acceptanceTerms/AcceptanceTermsApi.mjs.map +1 -1
  14. package/dist/apis/accounts/AccountsApi.cjs +5 -0
  15. package/dist/apis/accounts/AccountsApi.cjs.map +1 -1
  16. package/dist/apis/accounts/AccountsApi.d.ts +5 -0
  17. package/dist/apis/accounts/AccountsApi.d.ts.map +1 -1
  18. package/dist/apis/accounts/AccountsApi.mjs +5 -0
  19. package/dist/apis/accounts/AccountsApi.mjs.map +1 -1
  20. package/dist/apis/accounts/types.d.ts +2 -0
  21. package/dist/apis/accounts/types.d.ts.map +1 -1
  22. package/dist/apis/activityLog/ActivityLogApi.cjs +12 -0
  23. package/dist/apis/activityLog/ActivityLogApi.cjs.map +1 -1
  24. package/dist/apis/activityLog/ActivityLogApi.d.ts +8 -0
  25. package/dist/apis/activityLog/ActivityLogApi.d.ts.map +1 -1
  26. package/dist/apis/activityLog/ActivityLogApi.mjs +12 -0
  27. package/dist/apis/activityLog/ActivityLogApi.mjs.map +1 -1
  28. package/dist/apis/categories/CategoriesApi.cjs +7 -0
  29. package/dist/apis/categories/CategoriesApi.cjs.map +1 -1
  30. package/dist/apis/categories/CategoriesApi.d.ts +7 -1
  31. package/dist/apis/categories/CategoriesApi.d.ts.map +1 -1
  32. package/dist/apis/categories/CategoriesApi.mjs +7 -0
  33. package/dist/apis/categories/CategoriesApi.mjs.map +1 -1
  34. package/dist/apis/clientFeedback/ClientFeedbackApi.cjs +5 -1
  35. package/dist/apis/clientFeedback/ClientFeedbackApi.cjs.map +1 -1
  36. package/dist/apis/clientFeedback/ClientFeedbackApi.d.ts +5 -1
  37. package/dist/apis/clientFeedback/ClientFeedbackApi.d.ts.map +1 -1
  38. package/dist/apis/clientFeedback/ClientFeedbackApi.mjs +5 -1
  39. package/dist/apis/clientFeedback/ClientFeedbackApi.mjs.map +1 -1
  40. package/dist/apis/contactBlockLists/ContactBlockListsApi.cjs +8 -0
  41. package/dist/apis/contactBlockLists/ContactBlockListsApi.cjs.map +1 -1
  42. package/dist/apis/contactBlockLists/ContactBlockListsApi.d.ts +8 -1
  43. package/dist/apis/contactBlockLists/ContactBlockListsApi.d.ts.map +1 -1
  44. package/dist/apis/contactBlockLists/ContactBlockListsApi.mjs +8 -0
  45. package/dist/apis/contactBlockLists/ContactBlockListsApi.mjs.map +1 -1
  46. package/dist/apis/contactBlockListsControls/ContactBlockListsControlsApi.cjs +7 -0
  47. package/dist/apis/contactBlockListsControls/ContactBlockListsControlsApi.cjs.map +1 -1
  48. package/dist/apis/contactBlockListsControls/ContactBlockListsControlsApi.d.ts +7 -1
  49. package/dist/apis/contactBlockListsControls/ContactBlockListsControlsApi.d.ts.map +1 -1
  50. package/dist/apis/contactBlockListsControls/ContactBlockListsControlsApi.mjs +7 -0
  51. package/dist/apis/contactBlockListsControls/ContactBlockListsControlsApi.mjs.map +1 -1
  52. package/dist/apis/contacts/ContactsApi.cjs +16 -3
  53. package/dist/apis/contacts/ContactsApi.cjs.map +1 -1
  54. package/dist/apis/contacts/ContactsApi.d.ts +16 -5
  55. package/dist/apis/contacts/ContactsApi.d.ts.map +1 -1
  56. package/dist/apis/contacts/ContactsApi.mjs +16 -3
  57. package/dist/apis/contacts/ContactsApi.mjs.map +1 -1
  58. package/dist/apis/contacts/types.d.ts +6 -1
  59. package/dist/apis/contacts/types.d.ts.map +1 -1
  60. package/dist/apis/creditMovements/CreditMovementsApi.cjs +17 -0
  61. package/dist/apis/creditMovements/CreditMovementsApi.cjs.map +1 -1
  62. package/dist/apis/creditMovements/CreditMovementsApi.d.ts +11 -0
  63. package/dist/apis/creditMovements/CreditMovementsApi.d.ts.map +1 -1
  64. package/dist/apis/creditMovements/CreditMovementsApi.mjs +17 -0
  65. package/dist/apis/creditMovements/CreditMovementsApi.mjs.map +1 -1
  66. package/dist/apis/customFields/CustomFieldsApi.cjs +7 -0
  67. package/dist/apis/customFields/CustomFieldsApi.cjs.map +1 -1
  68. package/dist/apis/customFields/CustomFieldsApi.d.ts +7 -1
  69. package/dist/apis/customFields/CustomFieldsApi.d.ts.map +1 -1
  70. package/dist/apis/customFields/CustomFieldsApi.mjs +7 -0
  71. package/dist/apis/customFields/CustomFieldsApi.mjs.map +1 -1
  72. package/dist/apis/departments/DepartmentsApi.cjs +21 -0
  73. package/dist/apis/departments/DepartmentsApi.cjs.map +1 -1
  74. package/dist/apis/departments/DepartmentsApi.d.ts +20 -2
  75. package/dist/apis/departments/DepartmentsApi.d.ts.map +1 -1
  76. package/dist/apis/departments/DepartmentsApi.mjs +21 -0
  77. package/dist/apis/departments/DepartmentsApi.mjs.map +1 -1
  78. package/dist/apis/departments/types.d.ts +5 -0
  79. package/dist/apis/departments/types.d.ts.map +1 -1
  80. package/dist/apis/distribution/DistributionApi.cjs +7 -0
  81. package/dist/apis/distribution/DistributionApi.cjs.map +1 -1
  82. package/dist/apis/distribution/DistributionApi.d.ts +7 -1
  83. package/dist/apis/distribution/DistributionApi.d.ts.map +1 -1
  84. package/dist/apis/distribution/DistributionApi.mjs +7 -0
  85. package/dist/apis/distribution/DistributionApi.mjs.map +1 -1
  86. package/dist/apis/files/FilesApi.cjs +49 -0
  87. package/dist/apis/files/FilesApi.cjs.map +1 -1
  88. package/dist/apis/files/FilesApi.d.ts +45 -2
  89. package/dist/apis/files/FilesApi.d.ts.map +1 -1
  90. package/dist/apis/files/FilesApi.mjs +49 -0
  91. package/dist/apis/files/FilesApi.mjs.map +1 -1
  92. package/dist/apis/files/types.d.ts +45 -7
  93. package/dist/apis/files/types.d.ts.map +1 -1
  94. package/dist/apis/holiday/HolidayApi.cjs +7 -0
  95. package/dist/apis/holiday/HolidayApi.cjs.map +1 -1
  96. package/dist/apis/holiday/HolidayApi.d.ts +7 -1
  97. package/dist/apis/holiday/HolidayApi.d.ts.map +1 -1
  98. package/dist/apis/holiday/HolidayApi.mjs +7 -0
  99. package/dist/apis/holiday/HolidayApi.mjs.map +1 -1
  100. package/dist/apis/integrations/IntegrationsApi.cjs +7 -0
  101. package/dist/apis/integrations/IntegrationsApi.cjs.map +1 -1
  102. package/dist/apis/integrations/IntegrationsApi.d.ts +7 -1
  103. package/dist/apis/integrations/IntegrationsApi.d.ts.map +1 -1
  104. package/dist/apis/integrations/IntegrationsApi.mjs +7 -0
  105. package/dist/apis/integrations/IntegrationsApi.mjs.map +1 -1
  106. package/dist/apis/interactiveMessages/InteractiveMessagesApi.cjs +7 -0
  107. package/dist/apis/interactiveMessages/InteractiveMessagesApi.cjs.map +1 -1
  108. package/dist/apis/interactiveMessages/InteractiveMessagesApi.d.ts +7 -1
  109. package/dist/apis/interactiveMessages/InteractiveMessagesApi.d.ts.map +1 -1
  110. package/dist/apis/interactiveMessages/InteractiveMessagesApi.mjs +7 -0
  111. package/dist/apis/interactiveMessages/InteractiveMessagesApi.mjs.map +1 -1
  112. package/dist/apis/kanbanBoards/KanbanBoardsApi.cjs +7 -0
  113. package/dist/apis/kanbanBoards/KanbanBoardsApi.cjs.map +1 -1
  114. package/dist/apis/kanbanBoards/KanbanBoardsApi.d.ts +7 -1
  115. package/dist/apis/kanbanBoards/KanbanBoardsApi.d.ts.map +1 -1
  116. package/dist/apis/kanbanBoards/KanbanBoardsApi.mjs +7 -0
  117. package/dist/apis/kanbanBoards/KanbanBoardsApi.mjs.map +1 -1
  118. package/dist/apis/kanbanCards/KanbanCardsApi.cjs +7 -0
  119. package/dist/apis/kanbanCards/KanbanCardsApi.cjs.map +1 -1
  120. package/dist/apis/kanbanCards/KanbanCardsApi.d.ts +7 -1
  121. package/dist/apis/kanbanCards/KanbanCardsApi.d.ts.map +1 -1
  122. package/dist/apis/kanbanCards/KanbanCardsApi.mjs +7 -0
  123. package/dist/apis/kanbanCards/KanbanCardsApi.mjs.map +1 -1
  124. package/dist/apis/knowledgeBase/KnowledgeBaseApi.cjs +8 -0
  125. package/dist/apis/knowledgeBase/KnowledgeBaseApi.cjs.map +1 -1
  126. package/dist/apis/knowledgeBase/KnowledgeBaseApi.d.ts +8 -1
  127. package/dist/apis/knowledgeBase/KnowledgeBaseApi.d.ts.map +1 -1
  128. package/dist/apis/knowledgeBase/KnowledgeBaseApi.mjs +8 -0
  129. package/dist/apis/knowledgeBase/KnowledgeBaseApi.mjs.map +1 -1
  130. package/dist/apis/knowledgeBaseItem/KnowledgeBaseItemApi.cjs +8 -0
  131. package/dist/apis/knowledgeBaseItem/KnowledgeBaseItemApi.cjs.map +1 -1
  132. package/dist/apis/knowledgeBaseItem/KnowledgeBaseItemApi.d.ts +8 -1
  133. package/dist/apis/knowledgeBaseItem/KnowledgeBaseItemApi.d.ts.map +1 -1
  134. package/dist/apis/knowledgeBaseItem/KnowledgeBaseItemApi.mjs +8 -0
  135. package/dist/apis/knowledgeBaseItem/KnowledgeBaseItemApi.mjs.map +1 -1
  136. package/dist/apis/messages/MessagesApi.cjs +23 -3
  137. package/dist/apis/messages/MessagesApi.cjs.map +1 -1
  138. package/dist/apis/messages/MessagesApi.d.ts +19 -3
  139. package/dist/apis/messages/MessagesApi.d.ts.map +1 -1
  140. package/dist/apis/messages/MessagesApi.mjs +23 -3
  141. package/dist/apis/messages/MessagesApi.mjs.map +1 -1
  142. package/dist/apis/messages/types.d.ts +3 -0
  143. package/dist/apis/messages/types.d.ts.map +1 -1
  144. package/dist/apis/notifications/NotificationsApi.cjs +7 -0
  145. package/dist/apis/notifications/NotificationsApi.cjs.map +1 -1
  146. package/dist/apis/notifications/NotificationsApi.d.ts +7 -1
  147. package/dist/apis/notifications/NotificationsApi.d.ts.map +1 -1
  148. package/dist/apis/notifications/NotificationsApi.mjs +7 -0
  149. package/dist/apis/notifications/NotificationsApi.mjs.map +1 -1
  150. package/dist/apis/organizations/OrganizationsApi.cjs +7 -0
  151. package/dist/apis/organizations/OrganizationsApi.cjs.map +1 -1
  152. package/dist/apis/organizations/OrganizationsApi.d.ts +7 -1
  153. package/dist/apis/organizations/OrganizationsApi.d.ts.map +1 -1
  154. package/dist/apis/organizations/OrganizationsApi.mjs +7 -0
  155. package/dist/apis/organizations/OrganizationsApi.mjs.map +1 -1
  156. package/dist/apis/people/PeopleApi.cjs +7 -0
  157. package/dist/apis/people/PeopleApi.cjs.map +1 -1
  158. package/dist/apis/people/PeopleApi.d.ts +7 -1
  159. package/dist/apis/people/PeopleApi.d.ts.map +1 -1
  160. package/dist/apis/people/PeopleApi.mjs +7 -0
  161. package/dist/apis/people/PeopleApi.mjs.map +1 -1
  162. package/dist/apis/planAiHistory/PlanAiHistoryApi.cjs +16 -0
  163. package/dist/apis/planAiHistory/PlanAiHistoryApi.cjs.map +1 -1
  164. package/dist/apis/planAiHistory/PlanAiHistoryApi.d.ts +10 -0
  165. package/dist/apis/planAiHistory/PlanAiHistoryApi.d.ts.map +1 -1
  166. package/dist/apis/planAiHistory/PlanAiHistoryApi.mjs +16 -0
  167. package/dist/apis/planAiHistory/PlanAiHistoryApi.mjs.map +1 -1
  168. package/dist/apis/roles/RolesApi.cjs +7 -0
  169. package/dist/apis/roles/RolesApi.cjs.map +1 -1
  170. package/dist/apis/roles/RolesApi.d.ts +6 -1
  171. package/dist/apis/roles/RolesApi.d.ts.map +1 -1
  172. package/dist/apis/roles/RolesApi.mjs +7 -0
  173. package/dist/apis/roles/RolesApi.mjs.map +1 -1
  174. package/dist/apis/services/ServicesApi.cjs +68 -0
  175. package/dist/apis/services/ServicesApi.cjs.map +1 -1
  176. package/dist/apis/services/ServicesApi.d.ts +53 -1
  177. package/dist/apis/services/ServicesApi.d.ts.map +1 -1
  178. package/dist/apis/services/ServicesApi.mjs +68 -0
  179. package/dist/apis/services/ServicesApi.mjs.map +1 -1
  180. package/dist/apis/services/types.d.ts +15 -0
  181. package/dist/apis/services/types.d.ts.map +1 -1
  182. package/dist/apis/stickers/StickersApi.cjs +20 -0
  183. package/dist/apis/stickers/StickersApi.cjs.map +1 -1
  184. package/dist/apis/stickers/StickersApi.d.ts +15 -0
  185. package/dist/apis/stickers/StickersApi.d.ts.map +1 -1
  186. package/dist/apis/stickers/StickersApi.mjs +20 -0
  187. package/dist/apis/stickers/StickersApi.mjs.map +1 -1
  188. package/dist/apis/tags/TagsApi.cjs +7 -0
  189. package/dist/apis/tags/TagsApi.cjs.map +1 -1
  190. package/dist/apis/tags/TagsApi.d.ts +7 -1
  191. package/dist/apis/tags/TagsApi.d.ts.map +1 -1
  192. package/dist/apis/tags/TagsApi.mjs +7 -0
  193. package/dist/apis/tags/TagsApi.mjs.map +1 -1
  194. package/dist/apis/timetable/TimetableApi.cjs +7 -0
  195. package/dist/apis/timetable/TimetableApi.cjs.map +1 -1
  196. package/dist/apis/timetable/TimetableApi.d.ts +7 -1
  197. package/dist/apis/timetable/TimetableApi.d.ts.map +1 -1
  198. package/dist/apis/timetable/TimetableApi.mjs +7 -0
  199. package/dist/apis/timetable/TimetableApi.mjs.map +1 -1
  200. package/dist/apis/users/UsersApi.cjs +8 -0
  201. package/dist/apis/users/UsersApi.cjs.map +1 -1
  202. package/dist/apis/users/UsersApi.d.ts +8 -1
  203. package/dist/apis/users/UsersApi.d.ts.map +1 -1
  204. package/dist/apis/users/UsersApi.mjs +8 -0
  205. package/dist/apis/users/UsersApi.mjs.map +1 -1
  206. package/dist/apis/users/types.d.ts +15 -0
  207. package/dist/apis/users/types.d.ts.map +1 -1
  208. package/dist/apis/webhooks/WebhooksApi.cjs +7 -0
  209. package/dist/apis/webhooks/WebhooksApi.cjs.map +1 -1
  210. package/dist/apis/webhooks/WebhooksApi.d.ts +7 -1
  211. package/dist/apis/webhooks/WebhooksApi.d.ts.map +1 -1
  212. package/dist/apis/webhooks/WebhooksApi.mjs +7 -0
  213. package/dist/apis/webhooks/WebhooksApi.mjs.map +1 -1
  214. package/dist/core/ApiClient.d.ts +14 -0
  215. package/dist/core/ApiClient.d.ts.map +1 -1
  216. package/dist/core/ArchivableCrudApi.cjs.map +1 -1
  217. package/dist/core/ArchivableCrudApi.d.ts +1 -1
  218. package/dist/core/ArchivableCrudApi.d.ts.map +1 -1
  219. package/dist/core/ArchivableCrudApi.mjs.map +1 -1
  220. package/dist/core/BaseApiClient.cjs +24 -3
  221. package/dist/core/BaseApiClient.cjs.map +1 -1
  222. package/dist/core/BaseApiClient.d.ts +14 -0
  223. package/dist/core/BaseApiClient.d.ts.map +1 -1
  224. package/dist/core/BaseApiClient.mjs +24 -3
  225. package/dist/core/BaseApiClient.mjs.map +1 -1
  226. package/dist/core/requestExternal.cjs +33 -0
  227. package/dist/core/requestExternal.cjs.map +1 -0
  228. package/dist/core/requestExternal.d.ts +9 -0
  229. package/dist/core/requestExternal.d.ts.map +1 -0
  230. package/dist/core/requestExternal.mjs +32 -0
  231. package/dist/core/requestExternal.mjs.map +1 -0
  232. package/package.json +1 -1
  233. package/src/apis/absence/AbsenceApi.ts +19 -0
  234. package/src/apis/acceptanceTerms/AcceptanceTermsApi.ts +13 -1
  235. package/src/apis/accounts/AccountsApi.ts +5 -0
  236. package/src/apis/accounts/types.ts +2 -0
  237. package/src/apis/activityLog/ActivityLogApi.ts +18 -0
  238. package/src/apis/categories/CategoriesApi.ts +12 -1
  239. package/src/apis/clientFeedback/ClientFeedbackApi.ts +5 -1
  240. package/src/apis/contactBlockLists/ContactBlockListsApi.ts +13 -1
  241. package/src/apis/contactBlockListsControls/ContactBlockListsControlsApi.ts +12 -1
  242. package/src/apis/contacts/ContactsApi.test.ts +20 -4
  243. package/src/apis/contacts/ContactsApi.ts +24 -5
  244. package/src/apis/contacts/types.ts +7 -1
  245. package/src/apis/creditMovements/CreditMovementsApi.ts +27 -0
  246. package/src/apis/customFields/CustomFieldsApi.ts +12 -1
  247. package/src/apis/departments/DepartmentsApi.test.ts +88 -0
  248. package/src/apis/departments/DepartmentsApi.ts +41 -2
  249. package/src/apis/departments/types.ts +6 -0
  250. package/src/apis/distribution/DistributionApi.ts +12 -1
  251. package/src/apis/files/FilesApi.test.ts +122 -0
  252. package/src/apis/files/FilesApi.ts +107 -2
  253. package/src/apis/files/types.ts +48 -7
  254. package/src/apis/holiday/HolidayApi.ts +16 -1
  255. package/src/apis/integrations/IntegrationsApi.ts +12 -1
  256. package/src/apis/interactiveMessages/InteractiveMessagesApi.ts +12 -1
  257. package/src/apis/kanbanBoards/KanbanBoardsApi.ts +12 -1
  258. package/src/apis/kanbanCards/KanbanCardsApi.ts +12 -1
  259. package/src/apis/knowledgeBase/KnowledgeBaseApi.ts +13 -1
  260. package/src/apis/knowledgeBaseItem/KnowledgeBaseItemApi.ts +13 -1
  261. package/src/apis/messages/MessagesApi.test.ts +13 -7
  262. package/src/apis/messages/MessagesApi.ts +29 -3
  263. package/src/apis/messages/types.ts +3 -0
  264. package/src/apis/notifications/NotificationsApi.ts +12 -1
  265. package/src/apis/organizations/OrganizationsApi.ts +12 -1
  266. package/src/apis/payloads.test-d.ts +114 -0
  267. package/src/apis/people/PeopleApi.ts +16 -1
  268. package/src/apis/planAiHistory/PlanAiHistoryApi.ts +26 -0
  269. package/src/apis/roles/RolesApi.ts +10 -1
  270. package/src/apis/services/ServicesApi.test.ts +45 -0
  271. package/src/apis/services/ServicesApi.ts +91 -1
  272. package/src/apis/services/types.ts +16 -0
  273. package/src/apis/stickers/StickersApi.ts +32 -0
  274. package/src/apis/tags/TagsApi.ts +16 -1
  275. package/src/apis/timetable/TimetableApi.ts +12 -1
  276. package/src/apis/users/UsersApi.ts +17 -1
  277. package/src/apis/users/types.ts +11 -0
  278. package/src/apis/webhooks/WebhooksApi.ts +16 -1
  279. package/src/core/ApiClient.ts +24 -0
  280. package/src/core/ArchivableCrudApi.ts +2 -1
  281. package/src/core/BaseApiClient.test.ts +98 -0
  282. package/src/core/BaseApiClient.ts +49 -4
  283. package/src/core/requestExternal.ts +43 -0
@@ -498,4 +498,102 @@ describe('BaseApiClient', () => {
498
498
  errorClass: 'AccessDenied',
499
499
  })
500
500
  })
501
+
502
+ // ── requestRaw ───────────────────────────────────────────────────
503
+
504
+ describe('requestRaw', () => {
505
+ it('resolves the raw Response of a 2xx answer, with the headers and body untouched', async () => {
506
+ const spy = mockFetch({
507
+ ok: true,
508
+ status: 200,
509
+ statusText: 'OK',
510
+ headers: { 'Content-Type': 'application/pdf', 'Content-Disposition': 'attachment' },
511
+ body: '%PDF-1.4',
512
+ })
513
+ client.setAccessToken('token-1')
514
+ const response = await client.requestRaw('GET', '/terms/t-1/export-pdf')
515
+ expect(spy).toHaveBeenCalledWith(
516
+ 'https://api.example.com/terms/t-1/export-pdf',
517
+ expect.objectContaining({
518
+ method: 'GET',
519
+ headers: expect.objectContaining({ Authorization: 'Bearer token-1' }),
520
+ }),
521
+ )
522
+ expect(response.status).toBe(200)
523
+ expect(response.headers.get('Content-Type')).toBe('application/pdf')
524
+ expect(await response.text()).toBe('%PDF-1.4')
525
+ })
526
+
527
+ it('sends the JSON body and the custom headers', async () => {
528
+ const spy = mockFetch({ ok: true, status: 200, statusText: 'OK', body: 'a;b' })
529
+ await client.requestRaw('POST', '/export', { where: { id: '1' } }, { 'X-Custom': 'v' })
530
+ expect(spy).toHaveBeenCalledWith(
531
+ 'https://api.example.com/export',
532
+ expect.objectContaining({
533
+ method: 'POST',
534
+ body: JSON.stringify({ where: { id: '1' } }),
535
+ headers: expect.objectContaining({ 'X-Custom': 'v' }),
536
+ }),
537
+ )
538
+ })
539
+
540
+ it('throws the ApiError subclass of a non-2xx answer', async () => {
541
+ mockFetch({
542
+ ok: false,
543
+ status: 404,
544
+ statusText: 'Not Found',
545
+ headers: { 'Content-Type': 'application/json' },
546
+ body: JSON.stringify({ error: 'NotFoundHttpError', message: 'Route not found.' }),
547
+ })
548
+ await expect(client.requestRaw('GET', '/missing')).rejects.toBeInstanceOf(NotFoundError)
549
+ })
550
+
551
+ it('throws ApiConnectionError when the request fails', async () => {
552
+ vi.spyOn(globalThis, 'fetch').mockRejectedValue(new TypeError('fetch failed'))
553
+ await expect(client.requestRaw('GET', '/down')).rejects.toBeInstanceOf(ApiConnectionError)
554
+ })
555
+ })
556
+
557
+ // ── requestExternal ──────────────────────────────────────────────
558
+
559
+ describe('requestExternal', () => {
560
+ const SIGNED_URL = 'https://storage.example.com/acc-1/file-1.csv?X-Amz-Signature=secret'
561
+
562
+ it('sends the body as is to the absolute URL, without the token nor the JSON Content-Type', async () => {
563
+ const spy = vi
564
+ .spyOn(globalThis, 'fetch')
565
+ .mockResolvedValue(new Response(null, { status: 200 }))
566
+ client.setAccessToken('token-1')
567
+ const response = await client.requestExternal('PUT', SIGNED_URL, 'a;b', {
568
+ 'Content-Type': 'text/csv',
569
+ })
570
+ expect(spy).toHaveBeenCalledWith(SIGNED_URL, {
571
+ method: 'PUT',
572
+ headers: { 'Content-Type': 'text/csv' },
573
+ body: 'a;b',
574
+ })
575
+ expect(response.status).toBe(200)
576
+ })
577
+
578
+ it('throws the ApiError subclass of a non-2xx answer, with the body as text', async () => {
579
+ vi.spyOn(globalThis, 'fetch').mockResolvedValue(
580
+ new Response('<Error><Code>AccessDenied</Code></Error>', {
581
+ status: 403,
582
+ statusText: 'Forbidden',
583
+ }),
584
+ )
585
+ const captured = await client.requestExternal('PUT', SIGNED_URL).catch((e) => e)
586
+ expect(captured).toBeInstanceOf(PermissionDeniedError)
587
+ expect((captured as ApiError).body).toBe('<Error><Code>AccessDenied</Code></Error>')
588
+ })
589
+
590
+ it('throws ApiConnectionError without the query string (the signature) in the message', async () => {
591
+ vi.spyOn(globalThis, 'fetch').mockRejectedValue(new TypeError('fetch failed'))
592
+ const captured = await client.requestExternal('PUT', SIGNED_URL).catch((e) => e)
593
+ expect(captured).toBeInstanceOf(ApiConnectionError)
594
+ expect((captured as ApiConnectionError).message).toBe(
595
+ 'Request to PUT https://storage.example.com/acc-1/file-1.csv failed: fetch failed',
596
+ )
597
+ })
598
+ })
501
599
  })
@@ -1,6 +1,7 @@
1
1
  import type { ApiClient, HttpMethod } from './ApiClient'
2
2
  import { ApiConnectionError, ApiError } from './errors'
3
3
  import { DEFAULT_QUERY_FORMAT, type QueryFormat } from './queryString'
4
+ import { requestExternal } from './requestExternal'
4
5
 
5
6
  export interface BaseApiClientOptions {
6
7
  /** How list/get queries are serialized in the URL. Defaults to `'json'`. */
@@ -29,6 +30,53 @@ export class BaseApiClient implements ApiClient {
29
30
  body?: TBody,
30
31
  headers?: Record<string, string>,
31
32
  ): Promise<TResponse> {
33
+ return this.handleResponse<TResponse>(await this.send(method, endpoint, body, headers))
34
+ }
35
+
36
+ /**
37
+ * Sends the request and resolves the raw `Response` of a 2xx answer (headers and body
38
+ * untouched, so a binary body can be read with `arrayBuffer()`). Non-2xx throws the
39
+ * `ApiError` subclass, as {@link request} does.
40
+ */
41
+ async requestRaw<TBody = unknown>(
42
+ method: HttpMethod,
43
+ endpoint: string,
44
+ body?: TBody,
45
+ headers?: Record<string, string>,
46
+ ): Promise<Response> {
47
+ const response = await this.send(method, endpoint, body, headers)
48
+ if (!response.ok) {
49
+ throw ApiError.fromResponse(
50
+ response.status,
51
+ response.statusText,
52
+ response.headers,
53
+ await this.readErrorBody(response),
54
+ )
55
+ }
56
+ return response
57
+ }
58
+
59
+ /**
60
+ * Sends a request to an absolute URL outside the API, without the base URL, the access token
61
+ * and the JSON serialization. Resolves the raw `Response` of a 2xx answer; non-2xx throws the
62
+ * `ApiError` subclass. Override it to intercept those requests as well.
63
+ */
64
+ requestExternal(
65
+ method: HttpMethod,
66
+ url: string,
67
+ body?: BodyInit,
68
+ headers?: Record<string, string>,
69
+ ): Promise<Response> {
70
+ return requestExternal(method, url, body, headers)
71
+ }
72
+
73
+ /** Builds and sends the request; a network failure is thrown as `ApiConnectionError`. */
74
+ protected async send<TBody = unknown>(
75
+ method: HttpMethod,
76
+ endpoint: string,
77
+ body?: TBody,
78
+ headers?: Record<string, string>,
79
+ ): Promise<Response> {
32
80
  const url = `${this.baseUrl}/${endpoint.replace(/^\//, '')}`
33
81
  const init: RequestInit = {
34
82
  method,
@@ -40,17 +88,14 @@ export class BaseApiClient implements ApiClient {
40
88
  ...(body !== undefined && { body: JSON.stringify(body) }),
41
89
  }
42
90
 
43
- let response: Response
44
91
  try {
45
- response = await fetch(url, init)
92
+ return await fetch(url, init)
46
93
  } catch (error) {
47
94
  const reason = error instanceof Error ? error.message : String(error)
48
95
  throw new ApiConnectionError(`Request to ${method} ${url} failed: ${reason}`, {
49
96
  cause: error,
50
97
  })
51
98
  }
52
-
53
- return this.handleResponse<TResponse>(response)
54
99
  }
55
100
 
56
101
  protected async handleResponse<TResponse>(response: Response): Promise<TResponse> {
@@ -0,0 +1,43 @@
1
+ import type { HttpMethod } from './ApiClient'
2
+ import { ApiConnectionError, ApiError } from './errors'
3
+
4
+ /** The URL without its query string, which may carry a signature that must not reach the logs. */
5
+ function withoutQuery(url: string): string {
6
+ return url.replace(/[?#].*$/s, '')
7
+ }
8
+
9
+ /**
10
+ * Sends a request to an absolute URL outside the API (e.g. a signed storage URL): no base URL, no
11
+ * `Authorization` header and no JSON serialization, `body` goes as is. Resolves the raw `Response`
12
+ * of a 2xx answer; non-2xx throws the `ApiError` subclass with the body as text, and a network
13
+ * failure throws `ApiConnectionError`.
14
+ */
15
+ export async function requestExternal(
16
+ method: HttpMethod,
17
+ url: string,
18
+ body?: BodyInit,
19
+ headers?: Record<string, string>,
20
+ ): Promise<Response> {
21
+ let response: Response
22
+ try {
23
+ response = await fetch(url, {
24
+ method,
25
+ ...(headers && { headers }),
26
+ ...(body !== undefined && { body }),
27
+ })
28
+ } catch (error) {
29
+ const reason = error instanceof Error ? error.message : String(error)
30
+ throw new ApiConnectionError(`Request to ${method} ${withoutQuery(url)} failed: ${reason}`, {
31
+ cause: error,
32
+ })
33
+ }
34
+ if (!response.ok) {
35
+ throw ApiError.fromResponse(
36
+ response.status,
37
+ response.statusText,
38
+ response.headers,
39
+ (await response.text().catch(() => undefined)) || undefined,
40
+ )
41
+ }
42
+ return response
43
+ }