@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.
- package/README.md +36 -12
- package/dist/apis/absence/AbsenceApi.cjs +12 -0
- package/dist/apis/absence/AbsenceApi.cjs.map +1 -1
- package/dist/apis/absence/AbsenceApi.d.ts +9 -0
- package/dist/apis/absence/AbsenceApi.d.ts.map +1 -1
- package/dist/apis/absence/AbsenceApi.mjs +12 -0
- package/dist/apis/absence/AbsenceApi.mjs.map +1 -1
- package/dist/apis/acceptanceTerms/AcceptanceTermsApi.cjs +8 -0
- package/dist/apis/acceptanceTerms/AcceptanceTermsApi.cjs.map +1 -1
- package/dist/apis/acceptanceTerms/AcceptanceTermsApi.d.ts +8 -1
- package/dist/apis/acceptanceTerms/AcceptanceTermsApi.d.ts.map +1 -1
- package/dist/apis/acceptanceTerms/AcceptanceTermsApi.mjs +8 -0
- package/dist/apis/acceptanceTerms/AcceptanceTermsApi.mjs.map +1 -1
- package/dist/apis/accounts/AccountsApi.cjs +5 -0
- package/dist/apis/accounts/AccountsApi.cjs.map +1 -1
- package/dist/apis/accounts/AccountsApi.d.ts +5 -0
- package/dist/apis/accounts/AccountsApi.d.ts.map +1 -1
- package/dist/apis/accounts/AccountsApi.mjs +5 -0
- package/dist/apis/accounts/AccountsApi.mjs.map +1 -1
- package/dist/apis/accounts/types.d.ts +2 -0
- package/dist/apis/accounts/types.d.ts.map +1 -1
- package/dist/apis/activityLog/ActivityLogApi.cjs +12 -0
- package/dist/apis/activityLog/ActivityLogApi.cjs.map +1 -1
- package/dist/apis/activityLog/ActivityLogApi.d.ts +8 -0
- package/dist/apis/activityLog/ActivityLogApi.d.ts.map +1 -1
- package/dist/apis/activityLog/ActivityLogApi.mjs +12 -0
- package/dist/apis/activityLog/ActivityLogApi.mjs.map +1 -1
- package/dist/apis/categories/CategoriesApi.cjs +7 -0
- package/dist/apis/categories/CategoriesApi.cjs.map +1 -1
- package/dist/apis/categories/CategoriesApi.d.ts +7 -1
- package/dist/apis/categories/CategoriesApi.d.ts.map +1 -1
- package/dist/apis/categories/CategoriesApi.mjs +7 -0
- package/dist/apis/categories/CategoriesApi.mjs.map +1 -1
- package/dist/apis/clientFeedback/ClientFeedbackApi.cjs +5 -1
- package/dist/apis/clientFeedback/ClientFeedbackApi.cjs.map +1 -1
- package/dist/apis/clientFeedback/ClientFeedbackApi.d.ts +5 -1
- package/dist/apis/clientFeedback/ClientFeedbackApi.d.ts.map +1 -1
- package/dist/apis/clientFeedback/ClientFeedbackApi.mjs +5 -1
- package/dist/apis/clientFeedback/ClientFeedbackApi.mjs.map +1 -1
- package/dist/apis/contactBlockLists/ContactBlockListsApi.cjs +8 -0
- package/dist/apis/contactBlockLists/ContactBlockListsApi.cjs.map +1 -1
- package/dist/apis/contactBlockLists/ContactBlockListsApi.d.ts +8 -1
- package/dist/apis/contactBlockLists/ContactBlockListsApi.d.ts.map +1 -1
- package/dist/apis/contactBlockLists/ContactBlockListsApi.mjs +8 -0
- package/dist/apis/contactBlockLists/ContactBlockListsApi.mjs.map +1 -1
- package/dist/apis/contactBlockListsControls/ContactBlockListsControlsApi.cjs +7 -0
- package/dist/apis/contactBlockListsControls/ContactBlockListsControlsApi.cjs.map +1 -1
- package/dist/apis/contactBlockListsControls/ContactBlockListsControlsApi.d.ts +7 -1
- package/dist/apis/contactBlockListsControls/ContactBlockListsControlsApi.d.ts.map +1 -1
- package/dist/apis/contactBlockListsControls/ContactBlockListsControlsApi.mjs +7 -0
- package/dist/apis/contactBlockListsControls/ContactBlockListsControlsApi.mjs.map +1 -1
- package/dist/apis/contacts/ContactsApi.cjs +16 -3
- package/dist/apis/contacts/ContactsApi.cjs.map +1 -1
- package/dist/apis/contacts/ContactsApi.d.ts +16 -5
- package/dist/apis/contacts/ContactsApi.d.ts.map +1 -1
- package/dist/apis/contacts/ContactsApi.mjs +16 -3
- package/dist/apis/contacts/ContactsApi.mjs.map +1 -1
- package/dist/apis/contacts/types.d.ts +6 -1
- package/dist/apis/contacts/types.d.ts.map +1 -1
- package/dist/apis/creditMovements/CreditMovementsApi.cjs +17 -0
- package/dist/apis/creditMovements/CreditMovementsApi.cjs.map +1 -1
- package/dist/apis/creditMovements/CreditMovementsApi.d.ts +11 -0
- package/dist/apis/creditMovements/CreditMovementsApi.d.ts.map +1 -1
- package/dist/apis/creditMovements/CreditMovementsApi.mjs +17 -0
- package/dist/apis/creditMovements/CreditMovementsApi.mjs.map +1 -1
- package/dist/apis/customFields/CustomFieldsApi.cjs +7 -0
- package/dist/apis/customFields/CustomFieldsApi.cjs.map +1 -1
- package/dist/apis/customFields/CustomFieldsApi.d.ts +7 -1
- package/dist/apis/customFields/CustomFieldsApi.d.ts.map +1 -1
- package/dist/apis/customFields/CustomFieldsApi.mjs +7 -0
- package/dist/apis/customFields/CustomFieldsApi.mjs.map +1 -1
- package/dist/apis/departments/DepartmentsApi.cjs +21 -0
- package/dist/apis/departments/DepartmentsApi.cjs.map +1 -1
- package/dist/apis/departments/DepartmentsApi.d.ts +20 -2
- package/dist/apis/departments/DepartmentsApi.d.ts.map +1 -1
- package/dist/apis/departments/DepartmentsApi.mjs +21 -0
- package/dist/apis/departments/DepartmentsApi.mjs.map +1 -1
- package/dist/apis/departments/types.d.ts +5 -0
- package/dist/apis/departments/types.d.ts.map +1 -1
- package/dist/apis/distribution/DistributionApi.cjs +7 -0
- package/dist/apis/distribution/DistributionApi.cjs.map +1 -1
- package/dist/apis/distribution/DistributionApi.d.ts +7 -1
- package/dist/apis/distribution/DistributionApi.d.ts.map +1 -1
- package/dist/apis/distribution/DistributionApi.mjs +7 -0
- package/dist/apis/distribution/DistributionApi.mjs.map +1 -1
- package/dist/apis/files/FilesApi.cjs +49 -0
- package/dist/apis/files/FilesApi.cjs.map +1 -1
- package/dist/apis/files/FilesApi.d.ts +45 -2
- package/dist/apis/files/FilesApi.d.ts.map +1 -1
- package/dist/apis/files/FilesApi.mjs +49 -0
- package/dist/apis/files/FilesApi.mjs.map +1 -1
- package/dist/apis/files/types.d.ts +45 -7
- package/dist/apis/files/types.d.ts.map +1 -1
- package/dist/apis/holiday/HolidayApi.cjs +7 -0
- package/dist/apis/holiday/HolidayApi.cjs.map +1 -1
- package/dist/apis/holiday/HolidayApi.d.ts +7 -1
- package/dist/apis/holiday/HolidayApi.d.ts.map +1 -1
- package/dist/apis/holiday/HolidayApi.mjs +7 -0
- package/dist/apis/holiday/HolidayApi.mjs.map +1 -1
- package/dist/apis/integrations/IntegrationsApi.cjs +7 -0
- package/dist/apis/integrations/IntegrationsApi.cjs.map +1 -1
- package/dist/apis/integrations/IntegrationsApi.d.ts +7 -1
- package/dist/apis/integrations/IntegrationsApi.d.ts.map +1 -1
- package/dist/apis/integrations/IntegrationsApi.mjs +7 -0
- package/dist/apis/integrations/IntegrationsApi.mjs.map +1 -1
- package/dist/apis/interactiveMessages/InteractiveMessagesApi.cjs +7 -0
- package/dist/apis/interactiveMessages/InteractiveMessagesApi.cjs.map +1 -1
- package/dist/apis/interactiveMessages/InteractiveMessagesApi.d.ts +7 -1
- package/dist/apis/interactiveMessages/InteractiveMessagesApi.d.ts.map +1 -1
- package/dist/apis/interactiveMessages/InteractiveMessagesApi.mjs +7 -0
- package/dist/apis/interactiveMessages/InteractiveMessagesApi.mjs.map +1 -1
- package/dist/apis/kanbanBoards/KanbanBoardsApi.cjs +7 -0
- package/dist/apis/kanbanBoards/KanbanBoardsApi.cjs.map +1 -1
- package/dist/apis/kanbanBoards/KanbanBoardsApi.d.ts +7 -1
- package/dist/apis/kanbanBoards/KanbanBoardsApi.d.ts.map +1 -1
- package/dist/apis/kanbanBoards/KanbanBoardsApi.mjs +7 -0
- package/dist/apis/kanbanBoards/KanbanBoardsApi.mjs.map +1 -1
- package/dist/apis/kanbanCards/KanbanCardsApi.cjs +7 -0
- package/dist/apis/kanbanCards/KanbanCardsApi.cjs.map +1 -1
- package/dist/apis/kanbanCards/KanbanCardsApi.d.ts +7 -1
- package/dist/apis/kanbanCards/KanbanCardsApi.d.ts.map +1 -1
- package/dist/apis/kanbanCards/KanbanCardsApi.mjs +7 -0
- package/dist/apis/kanbanCards/KanbanCardsApi.mjs.map +1 -1
- package/dist/apis/knowledgeBase/KnowledgeBaseApi.cjs +8 -0
- package/dist/apis/knowledgeBase/KnowledgeBaseApi.cjs.map +1 -1
- package/dist/apis/knowledgeBase/KnowledgeBaseApi.d.ts +8 -1
- package/dist/apis/knowledgeBase/KnowledgeBaseApi.d.ts.map +1 -1
- package/dist/apis/knowledgeBase/KnowledgeBaseApi.mjs +8 -0
- package/dist/apis/knowledgeBase/KnowledgeBaseApi.mjs.map +1 -1
- package/dist/apis/knowledgeBaseItem/KnowledgeBaseItemApi.cjs +8 -0
- package/dist/apis/knowledgeBaseItem/KnowledgeBaseItemApi.cjs.map +1 -1
- package/dist/apis/knowledgeBaseItem/KnowledgeBaseItemApi.d.ts +8 -1
- package/dist/apis/knowledgeBaseItem/KnowledgeBaseItemApi.d.ts.map +1 -1
- package/dist/apis/knowledgeBaseItem/KnowledgeBaseItemApi.mjs +8 -0
- package/dist/apis/knowledgeBaseItem/KnowledgeBaseItemApi.mjs.map +1 -1
- package/dist/apis/messages/MessagesApi.cjs +23 -3
- package/dist/apis/messages/MessagesApi.cjs.map +1 -1
- package/dist/apis/messages/MessagesApi.d.ts +19 -3
- package/dist/apis/messages/MessagesApi.d.ts.map +1 -1
- package/dist/apis/messages/MessagesApi.mjs +23 -3
- package/dist/apis/messages/MessagesApi.mjs.map +1 -1
- package/dist/apis/messages/types.d.ts +3 -0
- package/dist/apis/messages/types.d.ts.map +1 -1
- package/dist/apis/notifications/NotificationsApi.cjs +7 -0
- package/dist/apis/notifications/NotificationsApi.cjs.map +1 -1
- package/dist/apis/notifications/NotificationsApi.d.ts +7 -1
- package/dist/apis/notifications/NotificationsApi.d.ts.map +1 -1
- package/dist/apis/notifications/NotificationsApi.mjs +7 -0
- package/dist/apis/notifications/NotificationsApi.mjs.map +1 -1
- package/dist/apis/organizations/OrganizationsApi.cjs +7 -0
- package/dist/apis/organizations/OrganizationsApi.cjs.map +1 -1
- package/dist/apis/organizations/OrganizationsApi.d.ts +7 -1
- package/dist/apis/organizations/OrganizationsApi.d.ts.map +1 -1
- package/dist/apis/organizations/OrganizationsApi.mjs +7 -0
- package/dist/apis/organizations/OrganizationsApi.mjs.map +1 -1
- package/dist/apis/people/PeopleApi.cjs +7 -0
- package/dist/apis/people/PeopleApi.cjs.map +1 -1
- package/dist/apis/people/PeopleApi.d.ts +7 -1
- package/dist/apis/people/PeopleApi.d.ts.map +1 -1
- package/dist/apis/people/PeopleApi.mjs +7 -0
- package/dist/apis/people/PeopleApi.mjs.map +1 -1
- package/dist/apis/planAiHistory/PlanAiHistoryApi.cjs +16 -0
- package/dist/apis/planAiHistory/PlanAiHistoryApi.cjs.map +1 -1
- package/dist/apis/planAiHistory/PlanAiHistoryApi.d.ts +10 -0
- package/dist/apis/planAiHistory/PlanAiHistoryApi.d.ts.map +1 -1
- package/dist/apis/planAiHistory/PlanAiHistoryApi.mjs +16 -0
- package/dist/apis/planAiHistory/PlanAiHistoryApi.mjs.map +1 -1
- package/dist/apis/roles/RolesApi.cjs +7 -0
- package/dist/apis/roles/RolesApi.cjs.map +1 -1
- package/dist/apis/roles/RolesApi.d.ts +6 -1
- package/dist/apis/roles/RolesApi.d.ts.map +1 -1
- package/dist/apis/roles/RolesApi.mjs +7 -0
- package/dist/apis/roles/RolesApi.mjs.map +1 -1
- package/dist/apis/services/ServicesApi.cjs +68 -0
- package/dist/apis/services/ServicesApi.cjs.map +1 -1
- package/dist/apis/services/ServicesApi.d.ts +53 -1
- package/dist/apis/services/ServicesApi.d.ts.map +1 -1
- package/dist/apis/services/ServicesApi.mjs +68 -0
- package/dist/apis/services/ServicesApi.mjs.map +1 -1
- package/dist/apis/services/types.d.ts +15 -0
- package/dist/apis/services/types.d.ts.map +1 -1
- package/dist/apis/stickers/StickersApi.cjs +20 -0
- package/dist/apis/stickers/StickersApi.cjs.map +1 -1
- package/dist/apis/stickers/StickersApi.d.ts +15 -0
- package/dist/apis/stickers/StickersApi.d.ts.map +1 -1
- package/dist/apis/stickers/StickersApi.mjs +20 -0
- package/dist/apis/stickers/StickersApi.mjs.map +1 -1
- package/dist/apis/tags/TagsApi.cjs +7 -0
- package/dist/apis/tags/TagsApi.cjs.map +1 -1
- package/dist/apis/tags/TagsApi.d.ts +7 -1
- package/dist/apis/tags/TagsApi.d.ts.map +1 -1
- package/dist/apis/tags/TagsApi.mjs +7 -0
- package/dist/apis/tags/TagsApi.mjs.map +1 -1
- package/dist/apis/timetable/TimetableApi.cjs +7 -0
- package/dist/apis/timetable/TimetableApi.cjs.map +1 -1
- package/dist/apis/timetable/TimetableApi.d.ts +7 -1
- package/dist/apis/timetable/TimetableApi.d.ts.map +1 -1
- package/dist/apis/timetable/TimetableApi.mjs +7 -0
- package/dist/apis/timetable/TimetableApi.mjs.map +1 -1
- package/dist/apis/users/UsersApi.cjs +8 -0
- package/dist/apis/users/UsersApi.cjs.map +1 -1
- package/dist/apis/users/UsersApi.d.ts +8 -1
- package/dist/apis/users/UsersApi.d.ts.map +1 -1
- package/dist/apis/users/UsersApi.mjs +8 -0
- package/dist/apis/users/UsersApi.mjs.map +1 -1
- package/dist/apis/users/types.d.ts +15 -0
- package/dist/apis/users/types.d.ts.map +1 -1
- package/dist/apis/webhooks/WebhooksApi.cjs +7 -0
- package/dist/apis/webhooks/WebhooksApi.cjs.map +1 -1
- package/dist/apis/webhooks/WebhooksApi.d.ts +7 -1
- package/dist/apis/webhooks/WebhooksApi.d.ts.map +1 -1
- package/dist/apis/webhooks/WebhooksApi.mjs +7 -0
- package/dist/apis/webhooks/WebhooksApi.mjs.map +1 -1
- package/dist/core/ApiClient.d.ts +14 -0
- package/dist/core/ApiClient.d.ts.map +1 -1
- package/dist/core/ArchivableCrudApi.cjs.map +1 -1
- package/dist/core/ArchivableCrudApi.d.ts +1 -1
- package/dist/core/ArchivableCrudApi.d.ts.map +1 -1
- package/dist/core/ArchivableCrudApi.mjs.map +1 -1
- package/dist/core/BaseApiClient.cjs +24 -3
- package/dist/core/BaseApiClient.cjs.map +1 -1
- package/dist/core/BaseApiClient.d.ts +14 -0
- package/dist/core/BaseApiClient.d.ts.map +1 -1
- package/dist/core/BaseApiClient.mjs +24 -3
- package/dist/core/BaseApiClient.mjs.map +1 -1
- package/dist/core/requestExternal.cjs +33 -0
- package/dist/core/requestExternal.cjs.map +1 -0
- package/dist/core/requestExternal.d.ts +9 -0
- package/dist/core/requestExternal.d.ts.map +1 -0
- package/dist/core/requestExternal.mjs +32 -0
- package/dist/core/requestExternal.mjs.map +1 -0
- package/package.json +1 -1
- package/src/apis/absence/AbsenceApi.ts +19 -0
- package/src/apis/acceptanceTerms/AcceptanceTermsApi.ts +13 -1
- package/src/apis/accounts/AccountsApi.ts +5 -0
- package/src/apis/accounts/types.ts +2 -0
- package/src/apis/activityLog/ActivityLogApi.ts +18 -0
- package/src/apis/categories/CategoriesApi.ts +12 -1
- package/src/apis/clientFeedback/ClientFeedbackApi.ts +5 -1
- package/src/apis/contactBlockLists/ContactBlockListsApi.ts +13 -1
- package/src/apis/contactBlockListsControls/ContactBlockListsControlsApi.ts +12 -1
- package/src/apis/contacts/ContactsApi.test.ts +20 -4
- package/src/apis/contacts/ContactsApi.ts +24 -5
- package/src/apis/contacts/types.ts +7 -1
- package/src/apis/creditMovements/CreditMovementsApi.ts +27 -0
- package/src/apis/customFields/CustomFieldsApi.ts +12 -1
- package/src/apis/departments/DepartmentsApi.test.ts +88 -0
- package/src/apis/departments/DepartmentsApi.ts +41 -2
- package/src/apis/departments/types.ts +6 -0
- package/src/apis/distribution/DistributionApi.ts +12 -1
- package/src/apis/files/FilesApi.test.ts +122 -0
- package/src/apis/files/FilesApi.ts +107 -2
- package/src/apis/files/types.ts +48 -7
- package/src/apis/holiday/HolidayApi.ts +16 -1
- package/src/apis/integrations/IntegrationsApi.ts +12 -1
- package/src/apis/interactiveMessages/InteractiveMessagesApi.ts +12 -1
- package/src/apis/kanbanBoards/KanbanBoardsApi.ts +12 -1
- package/src/apis/kanbanCards/KanbanCardsApi.ts +12 -1
- package/src/apis/knowledgeBase/KnowledgeBaseApi.ts +13 -1
- package/src/apis/knowledgeBaseItem/KnowledgeBaseItemApi.ts +13 -1
- package/src/apis/messages/MessagesApi.test.ts +13 -7
- package/src/apis/messages/MessagesApi.ts +29 -3
- package/src/apis/messages/types.ts +3 -0
- package/src/apis/notifications/NotificationsApi.ts +12 -1
- package/src/apis/organizations/OrganizationsApi.ts +12 -1
- package/src/apis/payloads.test-d.ts +114 -0
- package/src/apis/people/PeopleApi.ts +16 -1
- package/src/apis/planAiHistory/PlanAiHistoryApi.ts +26 -0
- package/src/apis/roles/RolesApi.ts +10 -1
- package/src/apis/services/ServicesApi.test.ts +45 -0
- package/src/apis/services/ServicesApi.ts +91 -1
- package/src/apis/services/types.ts +16 -0
- package/src/apis/stickers/StickersApi.ts +32 -0
- package/src/apis/tags/TagsApi.ts +16 -1
- package/src/apis/timetable/TimetableApi.ts +12 -1
- package/src/apis/users/UsersApi.ts +17 -1
- package/src/apis/users/types.ts +11 -0
- package/src/apis/webhooks/WebhooksApi.ts +16 -1
- package/src/core/ApiClient.ts +24 -0
- package/src/core/ArchivableCrudApi.ts +2 -1
- package/src/core/BaseApiClient.test.ts +98 -0
- package/src/core/BaseApiClient.ts +49 -4
- 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
|
-
|
|
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
|
+
}
|