@ikatec/digisac-api-sdk 4.12.0 → 4.13.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/dist/apis/absence/AbsenceApi.cjs +46 -2
- package/dist/apis/absence/AbsenceApi.cjs.map +1 -1
- package/dist/apis/absence/AbsenceApi.d.ts +38 -4
- package/dist/apis/absence/AbsenceApi.d.ts.map +1 -1
- package/dist/apis/absence/AbsenceApi.mjs +46 -2
- package/dist/apis/absence/AbsenceApi.mjs.map +1 -1
- package/dist/apis/absence/types.d.ts +51 -2
- package/dist/apis/absence/types.d.ts.map +1 -1
- package/dist/apis/activityLog/ActivityLogApi.cjs +10 -1
- package/dist/apis/activityLog/ActivityLogApi.cjs.map +1 -1
- package/dist/apis/activityLog/ActivityLogApi.d.ts +10 -3
- package/dist/apis/activityLog/ActivityLogApi.d.ts.map +1 -1
- package/dist/apis/activityLog/ActivityLogApi.mjs +10 -1
- package/dist/apis/activityLog/ActivityLogApi.mjs.map +1 -1
- package/dist/apis/activityLog/types.d.ts +48 -8
- package/dist/apis/activityLog/types.d.ts.map +1 -1
- package/dist/apis/creditMovements/CreditMovementsApi.cjs +31 -2
- package/dist/apis/creditMovements/CreditMovementsApi.cjs.map +1 -1
- package/dist/apis/creditMovements/CreditMovementsApi.d.ts +21 -3
- package/dist/apis/creditMovements/CreditMovementsApi.d.ts.map +1 -1
- package/dist/apis/creditMovements/CreditMovementsApi.mjs +31 -2
- package/dist/apis/creditMovements/CreditMovementsApi.mjs.map +1 -1
- package/dist/apis/creditMovements/types.d.ts +73 -2
- package/dist/apis/creditMovements/types.d.ts.map +1 -1
- package/dist/apis/knowledgeBase/KnowledgeBaseApi.cjs +27 -0
- package/dist/apis/knowledgeBase/KnowledgeBaseApi.cjs.map +1 -1
- package/dist/apis/knowledgeBase/KnowledgeBaseApi.d.ts +22 -1
- package/dist/apis/knowledgeBase/KnowledgeBaseApi.d.ts.map +1 -1
- package/dist/apis/knowledgeBase/KnowledgeBaseApi.mjs +27 -0
- package/dist/apis/knowledgeBase/KnowledgeBaseApi.mjs.map +1 -1
- package/dist/apis/knowledgeBase/types.d.ts +56 -2
- package/dist/apis/knowledgeBase/types.d.ts.map +1 -1
- package/dist/apis/knowledgeBaseItem/KnowledgeBaseItemApi.cjs +26 -0
- package/dist/apis/knowledgeBaseItem/KnowledgeBaseItemApi.cjs.map +1 -1
- package/dist/apis/knowledgeBaseItem/KnowledgeBaseItemApi.d.ts +24 -0
- package/dist/apis/knowledgeBaseItem/KnowledgeBaseItemApi.d.ts.map +1 -1
- package/dist/apis/knowledgeBaseItem/KnowledgeBaseItemApi.mjs +26 -0
- package/dist/apis/knowledgeBaseItem/KnowledgeBaseItemApi.mjs.map +1 -1
- package/dist/apis/knowledgeBaseItem/types.d.ts +23 -6
- package/dist/apis/knowledgeBaseItem/types.d.ts.map +1 -1
- package/dist/apis/notifications/NotificationsApi.cjs +50 -2
- package/dist/apis/notifications/NotificationsApi.cjs.map +1 -1
- package/dist/apis/notifications/NotificationsApi.d.ts +41 -3
- package/dist/apis/notifications/NotificationsApi.d.ts.map +1 -1
- package/dist/apis/notifications/NotificationsApi.mjs +50 -2
- package/dist/apis/notifications/NotificationsApi.mjs.map +1 -1
- package/dist/apis/notifications/types.d.ts +54 -8
- package/dist/apis/notifications/types.d.ts.map +1 -1
- package/dist/apis/serviceAccessManagement/ServiceAccessManagementApi.cjs.map +1 -1
- package/dist/apis/serviceAccessManagement/ServiceAccessManagementApi.d.ts +4 -1
- package/dist/apis/serviceAccessManagement/ServiceAccessManagementApi.d.ts.map +1 -1
- package/dist/apis/serviceAccessManagement/ServiceAccessManagementApi.mjs.map +1 -1
- package/dist/apis/serviceAccessManagement/types.d.ts +3 -0
- package/dist/apis/serviceAccessManagement/types.d.ts.map +1 -1
- package/dist/apis/stickerUsers/StickerUsersApi.cjs.map +1 -1
- package/dist/apis/stickerUsers/StickerUsersApi.d.ts +3 -1
- package/dist/apis/stickerUsers/StickerUsersApi.d.ts.map +1 -1
- package/dist/apis/stickerUsers/StickerUsersApi.mjs.map +1 -1
- package/dist/apis/stickerUsers/types.d.ts +4 -0
- package/dist/apis/stickerUsers/types.d.ts.map +1 -1
- package/dist/apis/stickers/StickersApi.cjs +27 -3
- package/dist/apis/stickers/StickersApi.cjs.map +1 -1
- package/dist/apis/stickers/StickersApi.d.ts +24 -4
- package/dist/apis/stickers/StickersApi.d.ts.map +1 -1
- package/dist/apis/stickers/StickersApi.mjs +27 -3
- package/dist/apis/stickers/StickersApi.mjs.map +1 -1
- package/dist/apis/stickers/types.d.ts +28 -4
- package/dist/apis/stickers/types.d.ts.map +1 -1
- package/dist/apis/whatsappBusinessTemplates/WhatsappBusinessTemplatesApi.cjs +1 -2
- package/dist/apis/whatsappBusinessTemplates/WhatsappBusinessTemplatesApi.cjs.map +1 -1
- package/dist/apis/whatsappBusinessTemplates/WhatsappBusinessTemplatesApi.d.ts +1 -2
- package/dist/apis/whatsappBusinessTemplates/WhatsappBusinessTemplatesApi.d.ts.map +1 -1
- package/dist/apis/whatsappBusinessTemplates/WhatsappBusinessTemplatesApi.mjs +1 -2
- package/dist/apis/whatsappBusinessTemplates/WhatsappBusinessTemplatesApi.mjs.map +1 -1
- package/package.json +1 -1
- package/src/apis/absence/AbsenceApi.test.ts +65 -0
- package/src/apis/absence/AbsenceApi.ts +77 -4
- package/src/apis/absence/types.ts +53 -2
- package/src/apis/activityLog/ActivityLogApi.test.ts +44 -0
- package/src/apis/activityLog/ActivityLogApi.ts +22 -3
- package/src/apis/activityLog/types.ts +47 -8
- package/src/apis/creditMovements/CreditMovementsApi.test.ts +88 -0
- package/src/apis/creditMovements/CreditMovementsApi.ts +73 -2
- package/src/apis/creditMovements/types.ts +74 -2
- package/src/apis/knowledgeBase/KnowledgeBaseApi.test.ts +54 -0
- package/src/apis/knowledgeBase/KnowledgeBaseApi.ts +61 -1
- package/src/apis/knowledgeBase/types.ts +62 -2
- package/src/apis/knowledgeBaseItem/KnowledgeBaseItemApi.test.ts +57 -0
- package/src/apis/knowledgeBaseItem/KnowledgeBaseItemApi.ts +45 -0
- package/src/apis/knowledgeBaseItem/types.ts +23 -6
- package/src/apis/me/MeApi.test.ts +1 -1
- package/src/apis/notifications/NotificationsApi.test.ts +74 -0
- package/src/apis/notifications/NotificationsApi.ts +88 -3
- package/src/apis/notifications/types.ts +65 -7
- package/src/apis/payloads.test-d.ts +46 -0
- package/src/apis/serviceAccessManagement/ServiceAccessManagementApi.ts +4 -1
- package/src/apis/serviceAccessManagement/types.ts +3 -0
- package/src/apis/stickerUsers/StickerUsersApi.ts +3 -1
- package/src/apis/stickerUsers/types.ts +4 -0
- package/src/apis/stickers/StickersApi.test.ts +58 -0
- package/src/apis/stickers/StickersApi.ts +46 -4
- package/src/apis/stickers/types.ts +29 -4
- package/src/apis/whatsappBusinessTemplates/WhatsappBusinessTemplatesApi.ts +1 -2
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
|
2
|
+
import { NotificationsApi } from './NotificationsApi'
|
|
3
|
+
import type { ApiClient } from '../../core/ApiClient'
|
|
4
|
+
|
|
5
|
+
// ── Mock client factory ──────────────────────────────────────────────
|
|
6
|
+
|
|
7
|
+
function createMockClient(): ApiClient {
|
|
8
|
+
return {
|
|
9
|
+
setAccessToken: vi.fn().mockReturnThis(),
|
|
10
|
+
request: vi.fn(),
|
|
11
|
+
requestRaw: vi.fn(),
|
|
12
|
+
get: vi.fn(),
|
|
13
|
+
post: vi.fn(),
|
|
14
|
+
put: vi.fn(),
|
|
15
|
+
patch: vi.fn(),
|
|
16
|
+
delete: vi.fn(),
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// ── Tests ────────────────────────────────────────────────────────────
|
|
21
|
+
|
|
22
|
+
describe('NotificationsApi', () => {
|
|
23
|
+
let client: ReturnType<typeof createMockClient>
|
|
24
|
+
let api: NotificationsApi
|
|
25
|
+
|
|
26
|
+
beforeEach(() => {
|
|
27
|
+
client = createMockClient()
|
|
28
|
+
api = new NotificationsApi(client)
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
it('count posts to /notifications/count and resolves the counts as text', async () => {
|
|
32
|
+
const counts = { count: { total: '3', read: '1', unread: '2' } }
|
|
33
|
+
vi.mocked(client.post).mockResolvedValue(counts)
|
|
34
|
+
await expect(api.count()).resolves.toEqual(counts)
|
|
35
|
+
expect(client.post).toHaveBeenCalledWith('/notifications/count', undefined, undefined)
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
it('read puts to /notifications/:id/read', async () => {
|
|
39
|
+
await api.read('n-1')
|
|
40
|
+
expect(client.put).toHaveBeenCalledWith('/notifications/n-1/read', undefined, undefined)
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
it('unread puts to /notifications/:id/unread', async () => {
|
|
44
|
+
await api.unread('n-1')
|
|
45
|
+
expect(client.put).toHaveBeenCalledWith('/notifications/n-1/unread', undefined, undefined)
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
it('readMany posts the ids as the body', async () => {
|
|
49
|
+
await api.readMany(['n-1', 'n-2'])
|
|
50
|
+
expect(client.post).toHaveBeenCalledWith('/notifications/read-many', ['n-1', 'n-2'], undefined)
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
it('readAll calls client.get with /notifications/read-all', async () => {
|
|
54
|
+
vi.mocked(client.get).mockResolvedValue({ total: 2, read: 2, unread: 0 })
|
|
55
|
+
await expect(api.readAll()).resolves.toEqual({ total: 2, read: 2, unread: 0 })
|
|
56
|
+
expect(client.get).toHaveBeenCalledWith('/notifications/read-all', undefined)
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
it('resetBadgeCount posts to /notifications/reset-badge-count', async () => {
|
|
60
|
+
vi.mocked(client.post).mockResolvedValue({ success: true })
|
|
61
|
+
await expect(api.resetBadgeCount()).resolves.toEqual({ success: true })
|
|
62
|
+
expect(client.post).toHaveBeenCalledWith(
|
|
63
|
+
'/notifications/reset-badge-count',
|
|
64
|
+
undefined,
|
|
65
|
+
undefined,
|
|
66
|
+
)
|
|
67
|
+
})
|
|
68
|
+
|
|
69
|
+
it('sendAll posts the announcement to /notifications/send-all', async () => {
|
|
70
|
+
const body = { text: 'Aviso', to: 'admin' as const }
|
|
71
|
+
await api.sendAll(body)
|
|
72
|
+
expect(client.post).toHaveBeenCalledWith('/notifications/send-all', body, undefined)
|
|
73
|
+
})
|
|
74
|
+
})
|
|
@@ -1,8 +1,19 @@
|
|
|
1
1
|
import type { ApiClient } from '../../core/ApiClient'
|
|
2
2
|
import type { ListQuery } from '../../core/types'
|
|
3
3
|
import { BaseCrudApi } from '../../core/BaseCrudApi'
|
|
4
|
-
import type {
|
|
4
|
+
import type {
|
|
5
|
+
Notification,
|
|
6
|
+
CreateNotificationPayload,
|
|
7
|
+
UpdateNotificationPayload,
|
|
8
|
+
NotificationCountsResponse,
|
|
9
|
+
NotificationReadAllResponse,
|
|
10
|
+
SendAllNotificationsPayload,
|
|
11
|
+
} from './types'
|
|
5
12
|
|
|
13
|
+
/**
|
|
14
|
+
* Notifications of the current user (all of the account with `notification.view.all`). Some types open a modal in the web app as soon as they arrive (`announcement`, `credits-90`,
|
|
15
|
+
* `credits-100`, `smart-summary`, `warn-service-reconnect`).
|
|
16
|
+
*/
|
|
6
17
|
export class NotificationsApi extends BaseCrudApi<
|
|
7
18
|
Notification,
|
|
8
19
|
CreateNotificationPayload,
|
|
@@ -15,10 +26,84 @@ export class NotificationsApi extends BaseCrudApi<
|
|
|
15
26
|
}
|
|
16
27
|
|
|
17
28
|
/**
|
|
18
|
-
* Deletes a notification. Resolves the text `'OK'`; an unknown id answers 500.
|
|
19
|
-
* no permission.
|
|
29
|
+
* Deletes a notification. Resolves the text `'OK'`; an unknown id answers 500.
|
|
20
30
|
*/
|
|
21
31
|
override deleteById(id: string, headers?: Record<string, string>): Promise<'OK'> {
|
|
22
32
|
return super.deleteById(id, headers)
|
|
23
33
|
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Counts the notifications the user sees: `{ count: { total, read, unread } }`, as TEXT.
|
|
37
|
+
*/
|
|
38
|
+
count(headers?: Record<string, string>): Promise<NotificationCountsResponse> {
|
|
39
|
+
return this.client.post<NotificationCountsResponse>(
|
|
40
|
+
`${this.basePath}/count`,
|
|
41
|
+
undefined,
|
|
42
|
+
headers,
|
|
43
|
+
)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Marks a notification as read for the current user and resolves the new counts. An unknown id answers
|
|
48
|
+
* 400 `Notification not found.`.
|
|
49
|
+
*/
|
|
50
|
+
read(id: string, headers?: Record<string, string>): Promise<NotificationCountsResponse> {
|
|
51
|
+
return this.client.put<NotificationCountsResponse>(
|
|
52
|
+
`${this.basePath}/${id}/read`,
|
|
53
|
+
undefined,
|
|
54
|
+
headers,
|
|
55
|
+
)
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Marks a notification as unread for the current user and resolves the new counts. An unknown id
|
|
60
|
+
* answers 400 `Notification not found.`.
|
|
61
|
+
*/
|
|
62
|
+
unread(id: string, headers?: Record<string, string>): Promise<NotificationCountsResponse> {
|
|
63
|
+
return this.client.put<NotificationCountsResponse>(
|
|
64
|
+
`${this.basePath}/${id}/unread`,
|
|
65
|
+
undefined,
|
|
66
|
+
headers,
|
|
67
|
+
)
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Marks the notifications of `ids` as read. Resolves with no body; a body that is not an array answers
|
|
72
|
+
* 500 `Body must be an array of notification IDs`.
|
|
73
|
+
*/
|
|
74
|
+
readMany(ids: string[], headers?: Record<string, string>): Promise<void> {
|
|
75
|
+
return this.client.post<void, string[]>(`${this.basePath}/read-many`, ids, headers)
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Marks every notification the user sees as read (a GET that writes: it recreates the read receipts of
|
|
80
|
+
* the user) and resolves the counts, as numbers.
|
|
81
|
+
*/
|
|
82
|
+
readAll(headers?: Record<string, string>): Promise<NotificationReadAllResponse> {
|
|
83
|
+
return this.client.get<NotificationReadAllResponse>(`${this.basePath}/read-all`, headers)
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/** Clears the push badge counter of the current user. Resolves `{ success: true }`. */
|
|
87
|
+
resetBadgeCount(headers?: Record<string, string>): Promise<{ success: true }> {
|
|
88
|
+
return this.client.post<{ success: true }>(
|
|
89
|
+
`${this.basePath}/reset-badge-count`,
|
|
90
|
+
undefined,
|
|
91
|
+
headers,
|
|
92
|
+
)
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* SENDS an announcement (`type: 'announcement'`, which opens a modal in the web app) to every user of
|
|
97
|
+
* the account, or only to the admins with `to: 'admin'`. Resolves `{ message: 'Notificações enviadas' }` before the notifications are created.
|
|
98
|
+
*/
|
|
99
|
+
sendAll(
|
|
100
|
+
body: SendAllNotificationsPayload,
|
|
101
|
+
headers?: Record<string, string>,
|
|
102
|
+
): Promise<{ message: string }> {
|
|
103
|
+
return this.client.post<{ message: string }, SendAllNotificationsPayload>(
|
|
104
|
+
`${this.basePath}/send-all`,
|
|
105
|
+
body,
|
|
106
|
+
headers,
|
|
107
|
+
)
|
|
108
|
+
}
|
|
24
109
|
}
|
|
@@ -13,46 +13,104 @@ export type NotificationType =
|
|
|
13
13
|
| 'undefined'
|
|
14
14
|
| 'waba-health-warning'
|
|
15
15
|
| 'waba-health-block'
|
|
16
|
+
| 'kanban-board-initialized'
|
|
17
|
+
| 'users-bulk-archive-blocked'
|
|
18
|
+
| 'user-import'
|
|
19
|
+
| 'credits-90'
|
|
20
|
+
| 'credits-100'
|
|
21
|
+
| 'smart-summary'
|
|
22
|
+
| 'warn-service-reconnect'
|
|
16
23
|
|
|
17
|
-
/**
|
|
24
|
+
/** Extra data of the notification; the pipeline notifications carry the pipeline ids. */
|
|
18
25
|
export type NotificationConfig = {
|
|
19
|
-
pipelineId
|
|
20
|
-
pipelineAutomationId
|
|
26
|
+
pipelineId?: string
|
|
27
|
+
pipelineAutomationId?: string
|
|
28
|
+
[key: string]: unknown
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/** The read receipt of a notification for the current user. */
|
|
32
|
+
export type NotificationRead = {
|
|
33
|
+
id: string
|
|
34
|
+
notificationId: string
|
|
35
|
+
userId: string
|
|
36
|
+
readAt: string | null
|
|
37
|
+
createdAt: string
|
|
38
|
+
updatedAt: string
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Counts of the notifications the user sees (all of the account with `notification.view.all`).
|
|
43
|
+
* They come as TEXT: the backend answers the `COUNT` of the database as is (e.g. `"43"`).
|
|
44
|
+
*/
|
|
45
|
+
export type NotificationCounts = {
|
|
46
|
+
total: string
|
|
47
|
+
read: string
|
|
48
|
+
unread: string
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/** What `read`, `unread` and `count` answer. */
|
|
52
|
+
export type NotificationCountsResponse = {
|
|
53
|
+
count: NotificationCounts
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/** What `readAll` answers: the counts after marking everything as read, as numbers. */
|
|
57
|
+
export type NotificationReadAllResponse = {
|
|
58
|
+
total: number
|
|
59
|
+
read: number
|
|
60
|
+
unread: number
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/** The body of `sendAll`: `to: 'admin'` sends only to the admins; any other value sends to every user. */
|
|
64
|
+
export type SendAllNotificationsPayload = {
|
|
65
|
+
/** Up to 255 characters. */
|
|
66
|
+
text: string
|
|
67
|
+
to: 'admin' | 'all' | (string & {})
|
|
68
|
+
image?: string
|
|
21
69
|
}
|
|
22
70
|
|
|
23
71
|
export type Notification = {
|
|
24
72
|
id: string
|
|
25
73
|
text: string
|
|
26
74
|
type: NotificationType | null
|
|
27
|
-
read
|
|
75
|
+
/** `null` on the announcements of `sendAll` until they are read. */
|
|
76
|
+
read: boolean | null
|
|
28
77
|
image: string | null
|
|
29
78
|
label: string | null
|
|
30
79
|
config: NotificationConfig | null
|
|
31
80
|
attachedType: string | null
|
|
81
|
+
attachedId: string | null
|
|
82
|
+
notificationReadId: string | null
|
|
32
83
|
contactId: string | null
|
|
33
84
|
userId: string
|
|
34
85
|
accountId: string
|
|
35
86
|
scheduleId: string | null
|
|
36
87
|
createdAt: string
|
|
37
88
|
updatedAt: string
|
|
38
|
-
|
|
89
|
+
/** @deprecated Not answered: the transformer of the backend does not send it. */
|
|
90
|
+
deletedAt?: string | null
|
|
39
91
|
// relationships
|
|
40
92
|
user?: User
|
|
41
93
|
schedule?: Schedule | null
|
|
94
|
+
/** @deprecated Not served: the model has no such association, so it never comes. */
|
|
42
95
|
contact?: Contact | null
|
|
96
|
+
notificationRead?: NotificationRead | null
|
|
43
97
|
}
|
|
44
98
|
|
|
45
|
-
|
|
99
|
+
/** The backend serves `user`, `schedule` and `notificationRead` (`contact` is never answered). */
|
|
100
|
+
export type NotificationRelationships = 'user' | 'schedule' | 'contact' | 'notificationRead'
|
|
46
101
|
|
|
47
102
|
export type CreateNotificationPayload = {
|
|
103
|
+
/** Up to 255 characters. */
|
|
48
104
|
text: string
|
|
49
|
-
|
|
105
|
+
/** Ignored: the backend creates the notification for the current user. */
|
|
106
|
+
userId?: string
|
|
50
107
|
type?: NotificationType
|
|
51
108
|
label?: string
|
|
52
109
|
config?: NotificationConfig
|
|
53
110
|
attachedType?: string
|
|
54
111
|
contactId?: string
|
|
55
112
|
scheduleId?: string
|
|
113
|
+
image?: string
|
|
56
114
|
}
|
|
57
115
|
|
|
58
116
|
export type UpdateNotificationPayload = {
|
|
@@ -71,6 +71,14 @@ import { KnowledgeBaseApi } from './knowledgeBase/KnowledgeBaseApi'
|
|
|
71
71
|
import { KnowledgeBaseItemApi } from './knowledgeBaseItem/KnowledgeBaseItemApi'
|
|
72
72
|
import { MessagesApi } from './messages/MessagesApi'
|
|
73
73
|
import { NotificationsApi } from './notifications/NotificationsApi'
|
|
74
|
+
import type { NotificationCountsResponse } from './notifications/types'
|
|
75
|
+
import { AbsenceApi } from './absence/AbsenceApi'
|
|
76
|
+
import type { AbsenceReportItem, UnlockAbsenceResponse } from './absence/types'
|
|
77
|
+
import { ActivityLogApi } from './activityLog/ActivityLogApi'
|
|
78
|
+
import { CreditMovementsApi } from './creditMovements/CreditMovementsApi'
|
|
79
|
+
import type { CreditBalances, CreditTotalServices } from './creditMovements/types'
|
|
80
|
+
import { StickersApi } from './stickers/StickersApi'
|
|
81
|
+
import type { Sticker } from './stickers/types'
|
|
74
82
|
import { OrganizationsApi } from './organizations/OrganizationsApi'
|
|
75
83
|
import { PeopleApi } from './people/PeopleApi'
|
|
76
84
|
import { ServicesApi } from './services/ServicesApi'
|
|
@@ -703,3 +711,41 @@ expectAssignable<ApiClient>({
|
|
|
703
711
|
patch: async <T>() => undefined as T,
|
|
704
712
|
delete: async <T>() => undefined as T,
|
|
705
713
|
})
|
|
714
|
+
|
|
715
|
+
// ── QARC-1010: notifications, absence, log, knowledge base, credits, stickers ─────
|
|
716
|
+
|
|
717
|
+
expectType<Promise<NotificationCountsResponse>>(new NotificationsApi(client).count())
|
|
718
|
+
expectType<Promise<string>>(new NotificationsApi(client).count().then(({ count }) => count.total))
|
|
719
|
+
expectError(new NotificationsApi(client).sendAll({ to: 'admin' }))
|
|
720
|
+
expectType<Promise<void>>(new NotificationsApi(client).readMany(['n-1']))
|
|
721
|
+
expectType<Promise<Paginated<AbsenceReportItem>>>(
|
|
722
|
+
new AbsenceApi(client).report({ filters: { reason: 'x' }, order: 'ASC' }),
|
|
723
|
+
)
|
|
724
|
+
expectType<Promise<UnlockAbsenceResponse>>(new AbsenceApi(client).unlock({}))
|
|
725
|
+
expectError(new AbsenceApi(client).report({ sort: 'name' }))
|
|
726
|
+
expectType<Promise<string>>(
|
|
727
|
+
new ActivityLogApi(client).exportCsv({ filters: { from: 'a', to: 'b' } }),
|
|
728
|
+
)
|
|
729
|
+
expectAssignable<Parameters<ActivityLogApi['create']>[0]>({
|
|
730
|
+
resourceType: 'contact',
|
|
731
|
+
event: 'update',
|
|
732
|
+
})
|
|
733
|
+
expectType<Promise<true>>(new KnowledgeBaseItemApi(client).deleteMany(['i-1']))
|
|
734
|
+
expectError(
|
|
735
|
+
new KnowledgeBaseApi(client).saveWithItems({ name: 'qa', items: [{ name: 'x', type: 'pdf' }] }),
|
|
736
|
+
)
|
|
737
|
+
expectType<Promise<CreditBalances>>(new CreditMovementsApi(client).balances())
|
|
738
|
+
expectType<Promise<number>>(new CreditMovementsApi(client).balance('sms-wavy'))
|
|
739
|
+
expectType<Promise<CreditTotalServices | undefined>>(
|
|
740
|
+
new CreditMovementsApi(client).totalServices({
|
|
741
|
+
filters: { from: 'a', to: 'b', serviceType: 'summary' },
|
|
742
|
+
page: 1,
|
|
743
|
+
}),
|
|
744
|
+
)
|
|
745
|
+
expectType<Promise<ArrayBuffer>>(
|
|
746
|
+
new CreditMovementsApi(client).exportXlsx({ from: 'a', to: 'b', where: { $and: [] } }),
|
|
747
|
+
)
|
|
748
|
+
expectType<Promise<Sticker>>(new StickersApi(client).create({ base64: 'iVBOR', name: 'qa' }))
|
|
749
|
+
expectError(new StickersApi(client).create({ type: 'created' }))
|
|
750
|
+
expectType<Promise<'OK' | false>>(new StickersApi(client).remove('s-1'))
|
|
751
|
+
expectAssignable<Parameters<StickersApi['getMany']>[0]>({ include: ['file'] })
|
|
@@ -6,7 +6,10 @@ export class ServiceAccessManagementApi
|
|
|
6
6
|
extends BaseApi
|
|
7
7
|
implements HasGetMany<ServiceAccessManagement>
|
|
8
8
|
{
|
|
9
|
-
/**
|
|
9
|
+
/**
|
|
10
|
+
* The connections denied to each user (one row per user × connection, written by
|
|
11
|
+
* `POST /services/:id/access-management`), raw. Filter by the `serviceId` or `userId` you want.
|
|
12
|
+
*/
|
|
10
13
|
getMany(
|
|
11
14
|
query: ListQuery<ServiceAccessManagement> & { paginate: false },
|
|
12
15
|
headers?: Record<string, string>,
|
|
@@ -6,8 +6,11 @@ export type ServiceAccessManagement = {
|
|
|
6
6
|
serviceId: string
|
|
7
7
|
createdAt: string
|
|
8
8
|
// relationships
|
|
9
|
+
/** @deprecated Not served: the backend drops every include of this route. */
|
|
9
10
|
user?: User
|
|
11
|
+
/** @deprecated Not served: the backend drops every include of this route. */
|
|
10
12
|
service?: Service
|
|
11
13
|
}
|
|
12
14
|
|
|
15
|
+
/** None is served: the backend drops every include of this route. */
|
|
13
16
|
export type ServiceAccessManagementRelationships = 'user' | 'service'
|
|
@@ -4,7 +4,9 @@ import type { StickerUser } from './types'
|
|
|
4
4
|
|
|
5
5
|
export class StickerUsersApi extends BaseApi implements HasGetMany<StickerUser> {
|
|
6
6
|
/**
|
|
7
|
-
*
|
|
7
|
+
* The stickers the current user sent recently (`lastSendAt`), paginated; only the `file` include is
|
|
8
|
+
* served. A row is written when the user sends a message of type `sticker` (in the background, after the
|
|
9
|
+
* send).
|
|
8
10
|
* @permissions stickers.send
|
|
9
11
|
*/
|
|
10
12
|
getMany(
|
|
@@ -10,9 +10,13 @@ export type StickerUser = {
|
|
|
10
10
|
createdAt: string
|
|
11
11
|
updatedAt: string
|
|
12
12
|
// relationships
|
|
13
|
+
/** @deprecated Not served: the backend only serves the `file` include. */
|
|
13
14
|
sticker?: Sticker
|
|
15
|
+
/** @deprecated Not served: the backend only serves the `file` include. */
|
|
14
16
|
user?: User
|
|
17
|
+
/** The image of the sticker. */
|
|
15
18
|
file?: File
|
|
16
19
|
}
|
|
17
20
|
|
|
21
|
+
/** The backend serves only `file` (`sticker` and `user` are dropped). */
|
|
18
22
|
export type StickerUserRelationships = 'sticker' | 'user' | 'file'
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
|
2
|
+
import { StickersApi } from './StickersApi'
|
|
3
|
+
import type { ApiClient } from '../../core/ApiClient'
|
|
4
|
+
|
|
5
|
+
// ── Mock client factory ──────────────────────────────────────────────
|
|
6
|
+
|
|
7
|
+
function createMockClient(): ApiClient {
|
|
8
|
+
return {
|
|
9
|
+
setAccessToken: vi.fn().mockReturnThis(),
|
|
10
|
+
request: vi.fn(),
|
|
11
|
+
requestRaw: vi.fn(),
|
|
12
|
+
get: vi.fn(),
|
|
13
|
+
post: vi.fn(),
|
|
14
|
+
put: vi.fn(),
|
|
15
|
+
patch: vi.fn(),
|
|
16
|
+
delete: vi.fn(),
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// ── Tests ────────────────────────────────────────────────────────────
|
|
21
|
+
|
|
22
|
+
describe('StickersApi', () => {
|
|
23
|
+
let client: ReturnType<typeof createMockClient>
|
|
24
|
+
let api: StickersApi
|
|
25
|
+
|
|
26
|
+
beforeEach(() => {
|
|
27
|
+
client = createMockClient()
|
|
28
|
+
api = new StickersApi(client)
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
it('create posts the image to /stickers', async () => {
|
|
32
|
+
await api.create({ base64: 'iVBOR', name: 'qa' })
|
|
33
|
+
expect(client.post).toHaveBeenCalledWith(
|
|
34
|
+
'/stickers',
|
|
35
|
+
{ base64: 'iVBOR', name: 'qa' },
|
|
36
|
+
undefined,
|
|
37
|
+
)
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
it('exist serializes the message and the checksum', async () => {
|
|
41
|
+
vi.mocked(client.get).mockResolvedValue({})
|
|
42
|
+
await expect(api.exist({ messageId: 'm-1', fileChecksum: 'abc' })).resolves.toEqual({})
|
|
43
|
+
const url = vi.mocked(client.get).mock.calls[0]?.[0] as string
|
|
44
|
+
expect(url).toMatch(/^\/stickers\/exist\?/)
|
|
45
|
+
expect(decodeURIComponent(url)).toContain('"fileChecksum":"abc"')
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
it('add posts the message to /stickers/add', async () => {
|
|
49
|
+
await api.add('m-1')
|
|
50
|
+
expect(client.post).toHaveBeenCalledWith('/stickers/add', { messageId: 'm-1' }, undefined)
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
it('remove deletes /stickers/remove/:stickerId', async () => {
|
|
54
|
+
vi.mocked(client.delete).mockResolvedValue('OK')
|
|
55
|
+
await expect(api.remove('s-1')).resolves.toBe('OK')
|
|
56
|
+
expect(client.delete).toHaveBeenCalledWith('/stickers/remove/s-1', undefined)
|
|
57
|
+
})
|
|
58
|
+
})
|
|
@@ -1,12 +1,18 @@
|
|
|
1
1
|
import type { ApiClient } from '../../core/ApiClient'
|
|
2
2
|
import { BaseCrudApi } from '../../core/BaseCrudApi'
|
|
3
3
|
import type { GetByIdQuery } from '../../core/types'
|
|
4
|
-
import type {
|
|
4
|
+
import type {
|
|
5
|
+
Sticker,
|
|
6
|
+
CreateStickerPayload,
|
|
7
|
+
UpdateStickerPayload,
|
|
8
|
+
StickerExistQuery,
|
|
9
|
+
} from './types'
|
|
5
10
|
|
|
6
11
|
/**
|
|
7
|
-
* Stickers of the account. The backend serves `GET /stickers
|
|
8
|
-
* `GET /stickers/exist`, `POST /stickers/add` and `DELETE /stickers/remove/:stickerId
|
|
9
|
-
* no read by id, update nor `DELETE /stickers/:id`.
|
|
12
|
+
* Stickers of the account: every user of the account sees them. The backend serves `GET /stickers`,
|
|
13
|
+
* `POST /stickers`, `GET /stickers/exist`, `POST /stickers/add` and `DELETE /stickers/remove/:stickerId`;
|
|
14
|
+
* there is no read by id, update nor `DELETE /stickers/:id`. The list accepts only the `file` include.
|
|
15
|
+
* @permissions stickers.send (list) · stickers.management (create, exist, add, remove)
|
|
10
16
|
*/
|
|
11
17
|
export class StickersApi extends BaseCrudApi<Sticker, CreateStickerPayload, UpdateStickerPayload> {
|
|
12
18
|
constructor(client: ApiClient) {
|
|
@@ -38,4 +44,40 @@ export class StickersApi extends BaseCrudApi<Sticker, CreateStickerPayload, Upda
|
|
|
38
44
|
override deleteById(id: string, headers?: Record<string, string>): Promise<Sticker> {
|
|
39
45
|
return super.deleteById(id, headers)
|
|
40
46
|
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Finds the sticker of the account that came from the message, or from the file of `fileChecksum` or
|
|
50
|
+
* `filehash`. Resolves `{ stickerId }`, or `{}` when there is none; without `messageId` it answers 500
|
|
51
|
+
* `Invalid message ID`.
|
|
52
|
+
*/
|
|
53
|
+
exist(
|
|
54
|
+
query: StickerExistQuery,
|
|
55
|
+
headers?: Record<string, string>,
|
|
56
|
+
): Promise<{ stickerId?: string }> {
|
|
57
|
+
return this.client.get<{ stickerId?: string }>(
|
|
58
|
+
`${this.basePath}/exist${this.toQueryString(query)}`,
|
|
59
|
+
headers,
|
|
60
|
+
)
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Turns the file of a message of the account into a sticker (`type: 'added'`). Idempotent: a sticker that
|
|
65
|
+
* already came from the message (or its file) is answered as is, and a removed one is restored. A message
|
|
66
|
+
* without file answers 500 `Message or file not found`.
|
|
67
|
+
*/
|
|
68
|
+
add(messageId: string, headers?: Record<string, string>): Promise<Sticker> {
|
|
69
|
+
return this.client.post<Sticker, { messageId: string }>(
|
|
70
|
+
`${this.basePath}/add`,
|
|
71
|
+
{ messageId },
|
|
72
|
+
headers,
|
|
73
|
+
)
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Removes a sticker of the account (soft delete; its file stays in the storage) and clears it from the
|
|
78
|
+
* recent stickers of every user. Resolves the text `'OK'`, or `false` when there is no such sticker.
|
|
79
|
+
*/
|
|
80
|
+
remove(stickerId: string, headers?: Record<string, string>): Promise<'OK' | false> {
|
|
81
|
+
return this.client.delete<'OK' | false>(`${this.basePath}/remove/${stickerId}`, headers)
|
|
82
|
+
}
|
|
41
83
|
}
|
|
@@ -1,8 +1,11 @@
|
|
|
1
|
+
import type { File } from '../files/types'
|
|
1
2
|
import type { User } from '../users/types'
|
|
2
3
|
|
|
4
|
+
/** A sticker of the account (every user of the account sees it). */
|
|
3
5
|
export type Sticker = {
|
|
4
6
|
id: string
|
|
5
|
-
|
|
7
|
+
/** `'created'` (uploaded with `create`) or `'added'` (taken from a message with `add`). */
|
|
8
|
+
type: 'created' | 'added' | (string & {})
|
|
6
9
|
originFileChecksum: string | null
|
|
7
10
|
originFilehash: string | null
|
|
8
11
|
originMessageId: string | null
|
|
@@ -10,20 +13,42 @@ export type Sticker = {
|
|
|
10
13
|
accountId: string
|
|
11
14
|
createdAt: string
|
|
12
15
|
updatedAt: string
|
|
13
|
-
deletedAt
|
|
16
|
+
deletedAt?: string | null
|
|
14
17
|
// relationships
|
|
18
|
+
/** @deprecated Not served: the backend only serves the `file` include. */
|
|
15
19
|
user?: User
|
|
20
|
+
/** The image (webp) of the sticker. */
|
|
21
|
+
file?: File
|
|
16
22
|
}
|
|
17
23
|
|
|
18
|
-
|
|
24
|
+
/** The backend serves only `file` (`user` is dropped). */
|
|
25
|
+
export type StickerRelationships = 'user' | 'file'
|
|
19
26
|
|
|
27
|
+
/**
|
|
28
|
+
* Uploads an image as a sticker: the backend converts it to a 512x512 webp (413 when it ends up too large:
|
|
29
|
+
* 100KB static, 500KB animated). `base64` without the `data:...;base64,` prefix.
|
|
30
|
+
*/
|
|
20
31
|
export type CreateStickerPayload = {
|
|
21
|
-
|
|
32
|
+
base64: string
|
|
33
|
+
/** The name of the file (`<name>.webp`). */
|
|
34
|
+
name: string
|
|
35
|
+
/** @deprecated Ignored by the backend: a created sticker is always `'created'`. */
|
|
36
|
+
type?: string
|
|
37
|
+
/** @deprecated Ignored by the backend: use `add` to take a sticker from a message. */
|
|
22
38
|
originMessageId?: string
|
|
39
|
+
/** @deprecated Ignored by the backend. */
|
|
23
40
|
originFileChecksum?: string
|
|
41
|
+
/** @deprecated Ignored by the backend. */
|
|
24
42
|
originFilehash?: string
|
|
25
43
|
}
|
|
26
44
|
|
|
27
45
|
export type UpdateStickerPayload = {
|
|
28
46
|
type?: string
|
|
29
47
|
}
|
|
48
|
+
|
|
49
|
+
/** Query of `exist`: finds a sticker of the account by the message or by the file it came from. */
|
|
50
|
+
export type StickerExistQuery = {
|
|
51
|
+
messageId: string
|
|
52
|
+
fileChecksum?: string
|
|
53
|
+
filehash?: string
|
|
54
|
+
}
|
|
@@ -81,8 +81,7 @@ export class WhatsappBusinessTemplatesApi extends BaseCrudApi<
|
|
|
81
81
|
}
|
|
82
82
|
|
|
83
83
|
/**
|
|
84
|
-
* Reads the template balance from 360Dialog
|
|
85
|
-
* not only in the account, and calls 360Dialog when it finds one.
|
|
84
|
+
* Reads the template balance from 360Dialog (an external call, when there is a 360Dialog connection).
|
|
86
85
|
* @permissions hsm.view
|
|
87
86
|
*/
|
|
88
87
|
resume(headers?: Record<string, string>): Promise<Record<string, unknown>[]> {
|