@ikatec/digisac-api-sdk 4.2.0 → 4.4.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/contacts/ContactsApi.cjs +70 -0
- package/dist/apis/contacts/ContactsApi.cjs.map +1 -1
- package/dist/apis/contacts/ContactsApi.d.ts +51 -1
- package/dist/apis/contacts/ContactsApi.d.ts.map +1 -1
- package/dist/apis/contacts/ContactsApi.mjs +70 -0
- package/dist/apis/contacts/ContactsApi.mjs.map +1 -1
- package/dist/apis/contacts/types.d.ts +141 -1
- package/dist/apis/contacts/types.d.ts.map +1 -1
- package/dist/apis/dashboard/DashboardApi.cjs +36 -1
- package/dist/apis/dashboard/DashboardApi.cjs.map +1 -1
- package/dist/apis/dashboard/DashboardApi.d.ts +55 -2
- package/dist/apis/dashboard/DashboardApi.d.ts.map +1 -1
- package/dist/apis/dashboard/DashboardApi.mjs +36 -1
- package/dist/apis/dashboard/DashboardApi.mjs.map +1 -1
- package/dist/apis/dashboard/types.d.ts +71 -0
- package/dist/apis/dashboard/types.d.ts.map +1 -1
- package/dist/apis/services/ServicesApi.cjs +8 -0
- package/dist/apis/services/ServicesApi.cjs.map +1 -1
- package/dist/apis/services/ServicesApi.d.ts +7 -1
- package/dist/apis/services/ServicesApi.d.ts.map +1 -1
- package/dist/apis/services/ServicesApi.mjs +8 -0
- package/dist/apis/services/ServicesApi.mjs.map +1 -1
- package/dist/apis/services/types.d.ts +7 -0
- package/dist/apis/services/types.d.ts.map +1 -1
- package/dist/apis/tags/TagsApi.cjs +23 -0
- package/dist/apis/tags/TagsApi.cjs.map +1 -1
- package/dist/apis/tags/TagsApi.d.ts +19 -1
- package/dist/apis/tags/TagsApi.d.ts.map +1 -1
- package/dist/apis/tags/TagsApi.mjs +23 -0
- package/dist/apis/tags/TagsApi.mjs.map +1 -1
- package/dist/apis/tags/types.d.ts +8 -0
- package/dist/apis/tags/types.d.ts.map +1 -1
- package/dist/apis/users/UsersApi.cjs +77 -0
- package/dist/apis/users/UsersApi.cjs.map +1 -1
- package/dist/apis/users/UsersApi.d.ts +59 -1
- package/dist/apis/users/UsersApi.d.ts.map +1 -1
- package/dist/apis/users/UsersApi.mjs +77 -0
- package/dist/apis/users/UsersApi.mjs.map +1 -1
- package/dist/apis/users/types.d.ts +102 -0
- package/dist/apis/users/types.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/apis/acceptanceTerms/AcceptanceTermsApi.test.ts +1 -1
- package/src/apis/authHistory/AuthHistoryApi.test.ts +1 -1
- package/src/apis/campaigns/CampaignsApi.test.ts +1 -1
- package/src/apis/contacts/ContactsApi.test.ts +182 -5
- package/src/apis/contacts/ContactsApi.ts +128 -0
- package/src/apis/contacts/types.ts +154 -1
- package/src/apis/dashboard/DashboardApi.test-d.ts +49 -0
- package/src/apis/dashboard/DashboardApi.test.ts +197 -9
- package/src/apis/dashboard/DashboardApi.ts +130 -2
- package/src/apis/dashboard/types.ts +78 -0
- package/src/apis/messages/MessagesApi.test.ts +3 -3
- package/src/apis/payloads.test-d.ts +26 -0
- package/src/apis/queryFormat.test.ts +91 -3
- package/src/apis/serviceAccessManagement/ServiceAccessManagementApi.test.ts +2 -2
- package/src/apis/services/ServicesApi.test.ts +49 -0
- package/src/apis/services/ServicesApi.ts +10 -1
- package/src/apis/services/types.ts +9 -0
- package/src/apis/stickerUsers/StickerUsersApi.test.ts +1 -1
- package/src/apis/tags/TagsApi.test.ts +79 -0
- package/src/apis/tags/TagsApi.ts +57 -1
- package/src/apis/tags/types.ts +9 -0
- package/src/apis/terms/TermsApi.test.ts +1 -1
- package/src/apis/users/UsersApi.test.ts +228 -0
- package/src/apis/users/UsersApi.ts +152 -1
- package/src/apis/users/types.ts +121 -0
|
@@ -5,6 +5,83 @@ var UsersApi = class extends ArchivableCrudApi {
|
|
|
5
5
|
constructor(client) {
|
|
6
6
|
super(client, "/users");
|
|
7
7
|
}
|
|
8
|
+
/**
|
|
9
|
+
* Archives or restores a user through the dedicated route used by the UI, which also
|
|
10
|
+
* sets the user offline and ends its sessions. The route enforces the business rules that
|
|
11
|
+
* {@link archive}/{@link unarchive} (a plain `PUT { archivedAt }`) skip:
|
|
12
|
+
* - archiving refuses (403) a user referenced by a bot or with open tickets;
|
|
13
|
+
* - restoring refuses (402) when the plan has no free user slot.
|
|
14
|
+
* @permissions users.view OR users.archive
|
|
15
|
+
*/
|
|
16
|
+
archiveWithValidation(id, body, headers) {
|
|
17
|
+
return this.client.post(`${this.basePath}/${id}/archive`, body, headers);
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Previews a bulk archive/unarchive without changing anything.
|
|
21
|
+
* @permissions users.archive
|
|
22
|
+
*/
|
|
23
|
+
previewBulkStatus(body, headers) {
|
|
24
|
+
return this.client.post(`${this.basePath}/bulk-status/preview`, body, headers);
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Archives or unarchives up to 100 users at once.
|
|
28
|
+
* @permissions users.archive
|
|
29
|
+
*/
|
|
30
|
+
bulkStatus(body, headers) {
|
|
31
|
+
return this.client.post(`${this.basePath}/bulk-status`, body, headers);
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Exports the users of the account as CSV. Resolves to the CSV text.
|
|
35
|
+
* @permissions users.export
|
|
36
|
+
*/
|
|
37
|
+
exportCsv(body, headers) {
|
|
38
|
+
return this.client.post(`${this.basePath}/export`, body, headers);
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Validates a CSV file previously uploaded through `FilesApi` before importing it.
|
|
42
|
+
* @permissions users.create
|
|
43
|
+
*/
|
|
44
|
+
validateImport(body, headers) {
|
|
45
|
+
return this.client.post(`${this.basePath}/import/validate`, body, headers);
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Starts the import of a CSV file previously uploaded through `FilesApi`. The import runs
|
|
49
|
+
* in the background (the route answers `202 Accepted`).
|
|
50
|
+
* @permissions users.create
|
|
51
|
+
*/
|
|
52
|
+
startImport(body, headers) {
|
|
53
|
+
return this.client.post(`${this.basePath}/import`, body, headers);
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Turns off the two-factor authentication (OTP) of a user.
|
|
57
|
+
* @permissions users.update AND myAccount.update
|
|
58
|
+
*/
|
|
59
|
+
disableOtpAuth(id, headers) {
|
|
60
|
+
return this.client.post(`${this.basePath}/${id}/disable-otp-auth`, void 0, headers);
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Clears the login throttling of a user blocked by too many failed attempts.
|
|
64
|
+
* @permissions users.update
|
|
65
|
+
*/
|
|
66
|
+
enableAccess(id, headers) {
|
|
67
|
+
return this.client.post(`${this.basePath}/${id}/enable-access`, void 0, headers);
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Returns the contacts pinned by the logged user.
|
|
71
|
+
* @permissions contacts.pin
|
|
72
|
+
*/
|
|
73
|
+
getPinnedContacts(headers) {
|
|
74
|
+
return this.client.get(`${this.basePath}/pin`, headers);
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Pins the contact for the logged user, or unpins it when already pinned. A user can pin
|
|
78
|
+
* up to 3 contacts. Resolves to the created link rows when pinning, or to the number of
|
|
79
|
+
* removed links when unpinning.
|
|
80
|
+
* @permissions contacts.pin
|
|
81
|
+
*/
|
|
82
|
+
togglePinContact(body, headers) {
|
|
83
|
+
return this.client.patch(`${this.basePath}/pin`, body, headers);
|
|
84
|
+
}
|
|
8
85
|
};
|
|
9
86
|
|
|
10
87
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"UsersApi.mjs","names":[],"sources":["../../../src/apis/users/UsersApi.ts"],"sourcesContent":["import type { ApiClient } from '../../core/ApiClient'\nimport { ArchivableCrudApi } from '../../core/ArchivableCrudApi'\nimport type {
|
|
1
|
+
{"version":3,"file":"UsersApi.mjs","names":[],"sources":["../../../src/apis/users/UsersApi.ts"],"sourcesContent":["import type { ApiClient } from '../../core/ApiClient'\nimport { ArchivableCrudApi } from '../../core/ArchivableCrudApi'\nimport type { Contact } from '../contacts/types'\nimport type {\n ArchiveUserPayload,\n BulkUsersStatusPayload,\n BulkUsersStatusPreview,\n BulkUsersStatusResult,\n CreateUserPayload,\n EnableUserAccessResult,\n ExportUsersPayload,\n ImportUsersPayload,\n ImportUsersResult,\n TogglePinContactPayload,\n TogglePinContactResult,\n UpdateUserPayload,\n User,\n ValidateUserImportPayload,\n ValidateUserImportResult,\n} from './types'\n\nexport class UsersApi extends ArchivableCrudApi<User, CreateUserPayload, UpdateUserPayload> {\n constructor(client: ApiClient) {\n super(client, '/users')\n }\n\n /**\n * Archives or restores a user through the dedicated route used by the UI, which also\n * sets the user offline and ends its sessions. The route enforces the business rules that\n * {@link archive}/{@link unarchive} (a plain `PUT { archivedAt }`) skip:\n * - archiving refuses (403) a user referenced by a bot or with open tickets;\n * - restoring refuses (402) when the plan has no free user slot.\n * @permissions users.view OR users.archive\n */\n archiveWithValidation(\n id: string,\n body: ArchiveUserPayload,\n headers?: Record<string, string>,\n ): Promise<User> {\n return this.client.post<User, ArchiveUserPayload>(\n `${this.basePath}/${id}/archive`,\n body,\n headers,\n )\n }\n\n /**\n * Previews a bulk archive/unarchive without changing anything.\n * @permissions users.archive\n */\n previewBulkStatus(\n body: BulkUsersStatusPayload,\n headers?: Record<string, string>,\n ): Promise<BulkUsersStatusPreview> {\n return this.client.post<BulkUsersStatusPreview, BulkUsersStatusPayload>(\n `${this.basePath}/bulk-status/preview`,\n body,\n headers,\n )\n }\n\n /**\n * Archives or unarchives up to 100 users at once.\n * @permissions users.archive\n */\n bulkStatus(\n body: BulkUsersStatusPayload,\n headers?: Record<string, string>,\n ): Promise<BulkUsersStatusResult> {\n return this.client.post<BulkUsersStatusResult, BulkUsersStatusPayload>(\n `${this.basePath}/bulk-status`,\n body,\n headers,\n )\n }\n\n /**\n * Exports the users of the account as CSV. Resolves to the CSV text.\n * @permissions users.export\n */\n exportCsv(body: ExportUsersPayload, headers?: Record<string, string>): Promise<string> {\n return this.client.post<string, ExportUsersPayload>(`${this.basePath}/export`, body, headers)\n }\n\n /**\n * Validates a CSV file previously uploaded through `FilesApi` before importing it.\n * @permissions users.create\n */\n validateImport(\n body: ValidateUserImportPayload,\n headers?: Record<string, string>,\n ): Promise<ValidateUserImportResult> {\n return this.client.post<ValidateUserImportResult, ValidateUserImportPayload>(\n `${this.basePath}/import/validate`,\n body,\n headers,\n )\n }\n\n /**\n * Starts the import of a CSV file previously uploaded through `FilesApi`. The import runs\n * in the background (the route answers `202 Accepted`).\n * @permissions users.create\n */\n startImport(\n body: ImportUsersPayload,\n headers?: Record<string, string>,\n ): Promise<ImportUsersResult> {\n return this.client.post<ImportUsersResult, ImportUsersPayload>(\n `${this.basePath}/import`,\n body,\n headers,\n )\n }\n\n /**\n * Turns off the two-factor authentication (OTP) of a user.\n * @permissions users.update AND myAccount.update\n */\n disableOtpAuth(id: string, headers?: Record<string, string>): Promise<User> {\n return this.client.post<User>(`${this.basePath}/${id}/disable-otp-auth`, undefined, headers)\n }\n\n /**\n * Clears the login throttling of a user blocked by too many failed attempts.\n * @permissions users.update\n */\n enableAccess(id: string, headers?: Record<string, string>): Promise<EnableUserAccessResult> {\n return this.client.post<EnableUserAccessResult>(\n `${this.basePath}/${id}/enable-access`,\n undefined,\n headers,\n )\n }\n\n /**\n * Returns the contacts pinned by the logged user.\n * @permissions contacts.pin\n */\n getPinnedContacts(headers?: Record<string, string>): Promise<Contact[]> {\n return this.client.get<Contact[]>(`${this.basePath}/pin`, headers)\n }\n\n /**\n * Pins the contact for the logged user, or unpins it when already pinned. A user can pin\n * up to 3 contacts. Resolves to the created link rows when pinning, or to the number of\n * removed links when unpinning.\n * @permissions contacts.pin\n */\n togglePinContact(\n body: TogglePinContactPayload,\n headers?: Record<string, string>,\n ): Promise<TogglePinContactResult> {\n return this.client.patch<TogglePinContactResult, TogglePinContactPayload>(\n `${this.basePath}/pin`,\n body,\n headers,\n )\n }\n}\n"],"mappings":";;;AAqBA,IAAa,WAAb,cAA8B,kBAA8D;CAC1F,YAAY,QAAmB;AAC7B,QAAM,QAAQ,SAAS;;;;;;;;;;CAWzB,sBACE,IACA,MACA,SACe;AACf,SAAO,KAAK,OAAO,KACjB,GAAG,KAAK,SAAS,GAAG,GAAG,WACvB,MACA,QACD;;;;;;CAOH,kBACE,MACA,SACiC;AACjC,SAAO,KAAK,OAAO,KACjB,GAAG,KAAK,SAAS,uBACjB,MACA,QACD;;;;;;CAOH,WACE,MACA,SACgC;AAChC,SAAO,KAAK,OAAO,KACjB,GAAG,KAAK,SAAS,eACjB,MACA,QACD;;;;;;CAOH,UAAU,MAA0B,SAAmD;AACrF,SAAO,KAAK,OAAO,KAAiC,GAAG,KAAK,SAAS,UAAU,MAAM,QAAQ;;;;;;CAO/F,eACE,MACA,SACmC;AACnC,SAAO,KAAK,OAAO,KACjB,GAAG,KAAK,SAAS,mBACjB,MACA,QACD;;;;;;;CAQH,YACE,MACA,SAC4B;AAC5B,SAAO,KAAK,OAAO,KACjB,GAAG,KAAK,SAAS,UACjB,MACA,QACD;;;;;;CAOH,eAAe,IAAY,SAAiD;AAC1E,SAAO,KAAK,OAAO,KAAW,GAAG,KAAK,SAAS,GAAG,GAAG,oBAAoB,QAAW,QAAQ;;;;;;CAO9F,aAAa,IAAY,SAAmE;AAC1F,SAAO,KAAK,OAAO,KACjB,GAAG,KAAK,SAAS,GAAG,GAAG,iBACvB,QACA,QACD;;;;;;CAOH,kBAAkB,SAAsD;AACtE,SAAO,KAAK,OAAO,IAAe,GAAG,KAAK,SAAS,OAAO,QAAQ;;;;;;;;CASpE,iBACE,MACA,SACiC;AACjC,SAAO,KAAK,OAAO,MACjB,GAAG,KAAK,SAAS,OACjB,MACA,QACD"}
|
|
@@ -62,4 +62,106 @@ export type UpdateUserPayload = {
|
|
|
62
62
|
language?: string;
|
|
63
63
|
archivedAt?: string | null;
|
|
64
64
|
};
|
|
65
|
+
/** Body for `POST /users/:id/archive`. */
|
|
66
|
+
export type ArchiveUserPayload = {
|
|
67
|
+
/** `true` archives the user; `false` restores it. */
|
|
68
|
+
archive: boolean;
|
|
69
|
+
};
|
|
70
|
+
/** Body for `POST /users/bulk-status` and `POST /users/bulk-status/preview` (1 to 100 IDs). */
|
|
71
|
+
export type BulkUsersStatusPayload = {
|
|
72
|
+
ids: string[];
|
|
73
|
+
archive: boolean;
|
|
74
|
+
};
|
|
75
|
+
export type BulkUsersStatusScenario = 'emptySelection' | 'noneEligible' | 'allEligible' | 'partiallyBlocked' | 'onlySelfBlocked' | 'planLimitExceeded';
|
|
76
|
+
/** Read-only preview of a bulk status change: nothing is written. */
|
|
77
|
+
export type BulkUsersStatusPreview = {
|
|
78
|
+
scenario: BulkUsersStatusScenario;
|
|
79
|
+
totalSelected: number;
|
|
80
|
+
/** Users already in the target status. */
|
|
81
|
+
noop: number;
|
|
82
|
+
eligible: number;
|
|
83
|
+
/** Users that cannot change (e.g. referenced by a bot, or the acting user). */
|
|
84
|
+
blocked: number;
|
|
85
|
+
blockedSelf: boolean;
|
|
86
|
+
/** Free plan slots when unarchiving; `null` when archiving. */
|
|
87
|
+
planSlotsAvailable: number | null;
|
|
88
|
+
};
|
|
89
|
+
export type BulkUsersStatusResult = {
|
|
90
|
+
changed: number;
|
|
91
|
+
noop: number;
|
|
92
|
+
blocked: number;
|
|
93
|
+
failed: number;
|
|
94
|
+
changedIds: string[];
|
|
95
|
+
/** IDs of the batch that no longer exist in the account. */
|
|
96
|
+
missingIds: string[];
|
|
97
|
+
};
|
|
98
|
+
/** Body for `POST /users/export`. */
|
|
99
|
+
export type ExportUsersPayload = {
|
|
100
|
+
filter: 'all' | 'active' | 'archived';
|
|
101
|
+
};
|
|
102
|
+
/** A file previously uploaded through `FilesApi`. */
|
|
103
|
+
export type UserImportFile = {
|
|
104
|
+
id: string;
|
|
105
|
+
name: string;
|
|
106
|
+
mimetype: string;
|
|
107
|
+
url?: string;
|
|
108
|
+
urlToUpload?: string;
|
|
109
|
+
};
|
|
110
|
+
/** Body for `POST /users/import/validate`. */
|
|
111
|
+
export type ValidateUserImportPayload = {
|
|
112
|
+
file: UserImportFile;
|
|
113
|
+
};
|
|
114
|
+
export type UserImportRowsSummary = {
|
|
115
|
+
total: number;
|
|
116
|
+
valid: number;
|
|
117
|
+
invalid: number;
|
|
118
|
+
hasInvalid: boolean;
|
|
119
|
+
};
|
|
120
|
+
export type ValidateUserImportResult = {
|
|
121
|
+
licenses: {
|
|
122
|
+
requestedRows: number;
|
|
123
|
+
available: number;
|
|
124
|
+
exceeded: boolean;
|
|
125
|
+
};
|
|
126
|
+
columns: {
|
|
127
|
+
required: {
|
|
128
|
+
name: string;
|
|
129
|
+
found: boolean;
|
|
130
|
+
}[];
|
|
131
|
+
missingRequired: string[];
|
|
132
|
+
optionalFound: string[];
|
|
133
|
+
};
|
|
134
|
+
rows: UserImportRowsSummary;
|
|
135
|
+
/** Same rows validated with the optional columns applied. */
|
|
136
|
+
rowsWithOptionalColumns: UserImportRowsSummary;
|
|
137
|
+
};
|
|
138
|
+
/** Body for `POST /users/import`. */
|
|
139
|
+
export type ImportUsersPayload = {
|
|
140
|
+
file: UserImportFile;
|
|
141
|
+
useOptionalColumns?: boolean;
|
|
142
|
+
};
|
|
143
|
+
/** The import runs in the background (the route answers `202 Accepted`). */
|
|
144
|
+
export type ImportUsersResult = {
|
|
145
|
+
importId: string;
|
|
146
|
+
};
|
|
147
|
+
export type EnableUserAccessResult = {
|
|
148
|
+
success: boolean;
|
|
149
|
+
message: string;
|
|
150
|
+
};
|
|
151
|
+
/** Body for `PATCH /users/pin`: toggles the pin of a contact for the logged user (max. 3). */
|
|
152
|
+
export type TogglePinContactPayload = {
|
|
153
|
+
contactId: string;
|
|
154
|
+
};
|
|
155
|
+
/** Link row returned by `PATCH /users/pin` when the contact gets pinned. */
|
|
156
|
+
export type UserPinnedContactLink = {
|
|
157
|
+
userId: string;
|
|
158
|
+
contactId: string;
|
|
159
|
+
createdAt: string;
|
|
160
|
+
updatedAt: string;
|
|
161
|
+
};
|
|
162
|
+
/**
|
|
163
|
+
* Result of `PATCH /users/pin`: the created link rows when the contact gets pinned, or the
|
|
164
|
+
* number of removed links when it gets unpinned.
|
|
165
|
+
*/
|
|
166
|
+
export type TogglePinContactResult = UserPinnedContactLink[] | number;
|
|
65
167
|
//# sourceMappingURL=types.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/apis/users/types.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/apis/users/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAA;AACtD,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAA;AAC1C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAA;AAEnD,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,SAAS,GAAG,MAAM,CAAA;AAEtD,MAAM,MAAM,eAAe,GAAG;IAC5B,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,cAAc,CAAC,EAAE,OAAO,CAAA;CACzB,CAAA;AAED,MAAM,MAAM,IAAI,GAAG;IACjB,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;IACb,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB,YAAY,EAAE,OAAO,CAAA;IACrB,YAAY,EAAE,OAAO,CAAA;IACrB,MAAM,EAAE,OAAO,CAAA;IACf,QAAQ,EAAE,MAAM,CAAA;IAChB,YAAY,EAAE,OAAO,CAAA;IACrB,MAAM,EAAE,UAAU,CAAA;IAClB,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAAA;IAC5C,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,oBAAoB,EAAE,OAAO,CAAA;IAC7B,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAA;IAChC,aAAa,EAAE,OAAO,GAAG,IAAI,CAAA;IAC7B,WAAW,EAAE,eAAe,CAAA;IAC5B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB,SAAS,EAAE,MAAM,CAAA;IACjB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IAExB,SAAS,CAAC,EAAE,SAAS,GAAG,IAAI,CAAA;IAC5B,KAAK,CAAC,EAAE,IAAI,EAAE,CAAA;IACd,WAAW,CAAC,EAAE,UAAU,EAAE,CAAA;CAC3B,CAAA;AAED,MAAM,MAAM,iBAAiB,GAAG,WAAW,GAAG,OAAO,GAAG,aAAa,CAAA;AAErE,MAAM,MAAM,iBAAiB,GAAG;IAC9B,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,MAAM,CAAA;IAChB,oBAAoB,EAAE,MAAM,CAAA;IAC5B,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAA;IAChB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAA;IACtB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAA;IACnB,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB,CAAA;AAED,MAAM,MAAM,iBAAiB,GAAG;IAC9B,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACtB,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAA;IAChB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAA;IACtB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAA;IACnB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B,WAAW,CAAC,EAAE,eAAe,CAAA;IAC7B,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAC3B,CAAA;AAED,0CAA0C;AAC1C,MAAM,MAAM,kBAAkB,GAAG;IAC/B,qDAAqD;IACrD,OAAO,EAAE,OAAO,CAAA;CACjB,CAAA;AAED,+FAA+F;AAC/F,MAAM,MAAM,sBAAsB,GAAG;IACnC,GAAG,EAAE,MAAM,EAAE,CAAA;IACb,OAAO,EAAE,OAAO,CAAA;CACjB,CAAA;AAED,MAAM,MAAM,uBAAuB,GAC/B,gBAAgB,GAChB,cAAc,GACd,aAAa,GACb,kBAAkB,GAClB,iBAAiB,GACjB,mBAAmB,CAAA;AAEvB,qEAAqE;AACrE,MAAM,MAAM,sBAAsB,GAAG;IACnC,QAAQ,EAAE,uBAAuB,CAAA;IACjC,aAAa,EAAE,MAAM,CAAA;IACrB,0CAA0C;IAC1C,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,MAAM,CAAA;IAChB,+EAA+E;IAC/E,OAAO,EAAE,MAAM,CAAA;IACf,WAAW,EAAE,OAAO,CAAA;IACpB,+DAA+D;IAC/D,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAA;CAClC,CAAA;AAED,MAAM,MAAM,qBAAqB,GAAG;IAClC,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,MAAM,CAAA;IACd,UAAU,EAAE,MAAM,EAAE,CAAA;IACpB,4DAA4D;IAC5D,UAAU,EAAE,MAAM,EAAE,CAAA;CACrB,CAAA;AAED,qCAAqC;AACrC,MAAM,MAAM,kBAAkB,GAAG;IAC/B,MAAM,EAAE,KAAK,GAAG,QAAQ,GAAG,UAAU,CAAA;CACtC,CAAA;AAED,qDAAqD;AACrD,MAAM,MAAM,cAAc,GAAG;IAC3B,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,MAAM,CAAA;IAChB,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB,CAAA;AAED,8CAA8C;AAC9C,MAAM,MAAM,yBAAyB,GAAG;IACtC,IAAI,EAAE,cAAc,CAAA;CACrB,CAAA;AAED,MAAM,MAAM,qBAAqB,GAAG;IAClC,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;IACb,OAAO,EAAE,MAAM,CAAA;IACf,UAAU,EAAE,OAAO,CAAA;CACpB,CAAA;AAED,MAAM,MAAM,wBAAwB,GAAG;IACrC,QAAQ,EAAE;QACR,aAAa,EAAE,MAAM,CAAA;QACrB,SAAS,EAAE,MAAM,CAAA;QACjB,QAAQ,EAAE,OAAO,CAAA;KAClB,CAAA;IACD,OAAO,EAAE;QACP,QAAQ,EAAE;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,OAAO,CAAA;SAAE,EAAE,CAAA;QAC5C,eAAe,EAAE,MAAM,EAAE,CAAA;QACzB,aAAa,EAAE,MAAM,EAAE,CAAA;KACxB,CAAA;IACD,IAAI,EAAE,qBAAqB,CAAA;IAC3B,6DAA6D;IAC7D,uBAAuB,EAAE,qBAAqB,CAAA;CAC/C,CAAA;AAED,qCAAqC;AACrC,MAAM,MAAM,kBAAkB,GAAG;IAC/B,IAAI,EAAE,cAAc,CAAA;IACpB,kBAAkB,CAAC,EAAE,OAAO,CAAA;CAC7B,CAAA;AAED,4EAA4E;AAC5E,MAAM,MAAM,iBAAiB,GAAG;IAC9B,QAAQ,EAAE,MAAM,CAAA;CACjB,CAAA;AAED,MAAM,MAAM,sBAAsB,GAAG;IACnC,OAAO,EAAE,OAAO,CAAA;IAChB,OAAO,EAAE,MAAM,CAAA;CAChB,CAAA;AAED,8FAA8F;AAC9F,MAAM,MAAM,uBAAuB,GAAG;IACpC,SAAS,EAAE,MAAM,CAAA;CAClB,CAAA;AAED,4EAA4E;AAC5E,MAAM,MAAM,qBAAqB,GAAG;IAClC,MAAM,EAAE,MAAM,CAAA;IACd,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE,MAAM,CAAA;CAClB,CAAA;AAED;;;GAGG;AACH,MAAM,MAAM,sBAAsB,GAAG,qBAAqB,EAAE,GAAG,MAAM,CAAA"}
|
package/package.json
CHANGED
|
@@ -87,7 +87,7 @@ describe('AcceptanceTermsApi', () => {
|
|
|
87
87
|
it('includes the file relationship', async () => {
|
|
88
88
|
vi.mocked(client.get).mockResolvedValue({ ...term, file: null })
|
|
89
89
|
const result = await api.getById('at-1', { include: ['file'] })
|
|
90
|
-
const url = vi.mocked(client.get).mock.calls[0][0] as string
|
|
90
|
+
const url = vi.mocked(client.get).mock.calls[0]?.[0] as string
|
|
91
91
|
expect(url).toContain('/acceptance-terms/at-1?')
|
|
92
92
|
expect(url).toContain('include')
|
|
93
93
|
expect(result.file).toBeNull()
|
|
@@ -66,7 +66,7 @@ describe('AuthHistoryApi', () => {
|
|
|
66
66
|
it('serializes query parameters', async () => {
|
|
67
67
|
vi.mocked(client.get).mockResolvedValue(paginated)
|
|
68
68
|
await api.getMany({ page: 2, perPage: 5 })
|
|
69
|
-
const url = vi.mocked(client.get).mock.calls[0][0] as string
|
|
69
|
+
const url = vi.mocked(client.get).mock.calls[0]?.[0] as string
|
|
70
70
|
expect(url).toContain('/auth-history?')
|
|
71
71
|
expect(decodeURIComponent(url)).toContain('"page":2')
|
|
72
72
|
})
|
|
@@ -94,7 +94,7 @@ describe('CampaignsApi', () => {
|
|
|
94
94
|
it('serializes query parameters', async () => {
|
|
95
95
|
vi.mocked(client.get).mockResolvedValue(paginated)
|
|
96
96
|
await api.getMany({ page: 2, perPage: 5 })
|
|
97
|
-
const url = vi.mocked(client.get).mock.calls[0][0] as string
|
|
97
|
+
const url = vi.mocked(client.get).mock.calls[0]?.[0] as string
|
|
98
98
|
expect(url).toContain('/campaigns?')
|
|
99
99
|
expect(decodeURIComponent(url)).toContain('"page":2')
|
|
100
100
|
})
|
|
@@ -2,12 +2,20 @@ import { beforeEach, describe, expect, it, vi } from 'vitest'
|
|
|
2
2
|
import { ContactsApi } from './ContactsApi'
|
|
3
3
|
import type { ApiClient } from '../../core/ApiClient'
|
|
4
4
|
import type {
|
|
5
|
+
BlockContactPayload,
|
|
6
|
+
BulkTransferTicketsPayload,
|
|
7
|
+
BulkTransferTicketsResult,
|
|
5
8
|
Contact,
|
|
9
|
+
ContactMediaPage,
|
|
10
|
+
ContactsSelection,
|
|
6
11
|
CreateContactPayload,
|
|
12
|
+
CreateManyContactsItem,
|
|
13
|
+
ExportCsvPayload,
|
|
7
14
|
ExportTemplatePayload,
|
|
8
15
|
CountContactsQuery,
|
|
9
16
|
ExistsContactsParams,
|
|
10
17
|
CountMediaResult,
|
|
18
|
+
ImportContactsPayload,
|
|
11
19
|
} from './types'
|
|
12
20
|
import type { Paginated } from '../../core/types'
|
|
13
21
|
|
|
@@ -101,7 +109,7 @@ describe('ContactsApi', () => {
|
|
|
101
109
|
it('serializes query parameters', async () => {
|
|
102
110
|
vi.mocked(client.get).mockResolvedValue(paginated)
|
|
103
111
|
await api.getMany({ page: 2, perPage: 5 })
|
|
104
|
-
const url = vi.mocked(client.get).mock.calls[0][0] as string
|
|
112
|
+
const url = vi.mocked(client.get).mock.calls[0]?.[0] as string
|
|
105
113
|
expect(url).toContain('/contacts?')
|
|
106
114
|
expect(decodeURIComponent(url)).toContain('"page":2')
|
|
107
115
|
})
|
|
@@ -225,7 +233,7 @@ describe('ContactsApi', () => {
|
|
|
225
233
|
vi.mocked(client.get).mockResolvedValue({ count: 10 })
|
|
226
234
|
const query: CountContactsQuery = { where: { name: 'Alice' } }
|
|
227
235
|
await api.count(query)
|
|
228
|
-
const url = vi.mocked(client.get).mock.calls[0][0] as string
|
|
236
|
+
const url = vi.mocked(client.get).mock.calls[0]?.[0] as string
|
|
229
237
|
expect(url).toContain('/contacts/count?')
|
|
230
238
|
expect(url).toContain('where')
|
|
231
239
|
})
|
|
@@ -270,7 +278,7 @@ describe('ContactsApi', () => {
|
|
|
270
278
|
it('serializes query parameters', async () => {
|
|
271
279
|
vi.mocked(client.get).mockResolvedValue(paginated)
|
|
272
280
|
await api.forward({ page: 1, perPage: 10 })
|
|
273
|
-
const url = vi.mocked(client.get).mock.calls[0][0] as string
|
|
281
|
+
const url = vi.mocked(client.get).mock.calls[0]?.[0] as string
|
|
274
282
|
expect(url).toContain('/contacts/forward?')
|
|
275
283
|
})
|
|
276
284
|
|
|
@@ -289,7 +297,7 @@ describe('ContactsApi', () => {
|
|
|
289
297
|
vi.mocked(client.get).mockResolvedValue({ '1234567890': true })
|
|
290
298
|
const params: ExistsContactsParams = { serviceId: 'svc-1', numbers: ['1234567890'] }
|
|
291
299
|
const result = await api.exists(params)
|
|
292
|
-
const url = vi.mocked(client.get).mock.calls[0][0] as string
|
|
300
|
+
const url = vi.mocked(client.get).mock.calls[0]?.[0] as string
|
|
293
301
|
expect(url).toContain('/contacts/exists?')
|
|
294
302
|
expect(url).toContain('serviceId=svc-1')
|
|
295
303
|
expect(result).toEqual({ '1234567890': true })
|
|
@@ -299,7 +307,7 @@ describe('ContactsApi', () => {
|
|
|
299
307
|
vi.mocked(client.get).mockResolvedValue({})
|
|
300
308
|
const headers = { 'X-Custom': 'h' }
|
|
301
309
|
await api.exists({ serviceId: 'svc-1', numbers: [] }, headers)
|
|
302
|
-
expect(vi.mocked(client.get).mock.calls[0][1]).toEqual(headers)
|
|
310
|
+
expect(vi.mocked(client.get).mock.calls[0]?.[1]).toEqual(headers)
|
|
303
311
|
})
|
|
304
312
|
})
|
|
305
313
|
|
|
@@ -365,6 +373,175 @@ describe('ContactsApi', () => {
|
|
|
365
373
|
})
|
|
366
374
|
})
|
|
367
375
|
|
|
376
|
+
// ── createMany ───────────────────────────────────────────────────
|
|
377
|
+
|
|
378
|
+
describe('createMany', () => {
|
|
379
|
+
const items: CreateManyContactsItem[] = [
|
|
380
|
+
{ serviceId: 'svc-1', name: 'Alice', number: '5511999990001' },
|
|
381
|
+
{ serviceId: 'svc-1', name: 'Bob', number: '5511999990002', tagIds: ['t1'] },
|
|
382
|
+
]
|
|
383
|
+
|
|
384
|
+
it('calls client.post with /contacts/many and the array body', async () => {
|
|
385
|
+
vi.mocked(client.post).mockResolvedValue([contact])
|
|
386
|
+
const result = await api.createMany(items)
|
|
387
|
+
expect(client.post).toHaveBeenCalledWith('/contacts/many', items, undefined)
|
|
388
|
+
expect(result).toEqual([contact])
|
|
389
|
+
})
|
|
390
|
+
|
|
391
|
+
it('serializes the query and forwards custom headers', async () => {
|
|
392
|
+
const headers = { 'X-Custom': 'value' }
|
|
393
|
+
await api.createMany(items, { include: ['tags'] }, headers)
|
|
394
|
+
const [url, body, sentHeaders] = vi.mocked(client.post).mock.calls[0] ?? []
|
|
395
|
+
expect(decodeURIComponent(url as string)).toBe('/contacts/many?query={"include":["tags"]}')
|
|
396
|
+
expect(body).toBe(items)
|
|
397
|
+
expect(sentHeaders).toBe(headers)
|
|
398
|
+
})
|
|
399
|
+
})
|
|
400
|
+
|
|
401
|
+
// ── deleteMany ───────────────────────────────────────────────────
|
|
402
|
+
|
|
403
|
+
describe('deleteMany', () => {
|
|
404
|
+
it('calls client.request with DELETE /contacts/many and the selection', async () => {
|
|
405
|
+
vi.mocked(client.request).mockResolvedValue(true)
|
|
406
|
+
const body: ContactsSelection = { where: { id: { $in: ['c1', 'c2'] } } }
|
|
407
|
+
const result = await api.deleteMany(body)
|
|
408
|
+
expect(client.request).toHaveBeenCalledWith('DELETE', '/contacts/many', body, undefined)
|
|
409
|
+
expect(result).toBe(true)
|
|
410
|
+
})
|
|
411
|
+
|
|
412
|
+
it('forwards custom headers', async () => {
|
|
413
|
+
const headers = { 'X-Custom': 'value' }
|
|
414
|
+
await api.deleteMany({ where: { id: 'c1' } }, headers)
|
|
415
|
+
expect(client.request).toHaveBeenCalledWith(
|
|
416
|
+
'DELETE',
|
|
417
|
+
'/contacts/many',
|
|
418
|
+
{ where: { id: 'c1' } },
|
|
419
|
+
headers,
|
|
420
|
+
)
|
|
421
|
+
})
|
|
422
|
+
})
|
|
423
|
+
|
|
424
|
+
// ── exportCsv ────────────────────────────────────────────────────
|
|
425
|
+
|
|
426
|
+
describe('exportCsv', () => {
|
|
427
|
+
it('calls client.post with /contacts/export/csv and resolves to the CSV text', async () => {
|
|
428
|
+
const csv = 'Nome,DDI,Número\nAlice,55,11999990001\n'
|
|
429
|
+
vi.mocked(client.post).mockResolvedValue(csv)
|
|
430
|
+
const body: ExportCsvPayload = {
|
|
431
|
+
serviceType: 'whatsapp',
|
|
432
|
+
type: 'comma',
|
|
433
|
+
where: { id: 'cnt-1' },
|
|
434
|
+
}
|
|
435
|
+
const result = await api.exportCsv(body)
|
|
436
|
+
expect(client.post).toHaveBeenCalledWith('/contacts/export/csv', body, undefined)
|
|
437
|
+
expect(result).toBe(csv)
|
|
438
|
+
})
|
|
439
|
+
})
|
|
440
|
+
|
|
441
|
+
// ── importCsv ────────────────────────────────────────────────────
|
|
442
|
+
|
|
443
|
+
describe('importCsv', () => {
|
|
444
|
+
it('calls client.post with /contacts/import-contacts and body', async () => {
|
|
445
|
+
const body: ImportContactsPayload = {
|
|
446
|
+
service: { id: 'svc-1', accountId: 'acc-1', type: 'whatsapp' },
|
|
447
|
+
file: { id: 'f1', name: 'contacts.csv', mimetype: 'text/csv', urlToUpload: 'https://s3' },
|
|
448
|
+
csvHeaderLine: ['Nome', 'DDI', 'Número'],
|
|
449
|
+
type: 'comma',
|
|
450
|
+
tagsIds: ['t1'],
|
|
451
|
+
}
|
|
452
|
+
vi.mocked(client.post).mockResolvedValue('OK')
|
|
453
|
+
const headers = { 'X-Custom': 'value' }
|
|
454
|
+
const result = await api.importCsv(body, headers)
|
|
455
|
+
expect(client.post).toHaveBeenCalledWith('/contacts/import-contacts', body, headers)
|
|
456
|
+
expect(result).toBe('OK')
|
|
457
|
+
})
|
|
458
|
+
})
|
|
459
|
+
|
|
460
|
+
// ── sync ─────────────────────────────────────────────────────────
|
|
461
|
+
|
|
462
|
+
describe('sync', () => {
|
|
463
|
+
it('calls client.post with /contacts/:id/sync and an empty body by default', async () => {
|
|
464
|
+
vi.mocked(client.post).mockResolvedValue('OK')
|
|
465
|
+
const result = await api.sync('c1')
|
|
466
|
+
expect(client.post).toHaveBeenCalledWith('/contacts/c1/sync', {}, undefined)
|
|
467
|
+
expect(result).toBe('OK')
|
|
468
|
+
})
|
|
469
|
+
|
|
470
|
+
it('sends forceSync and forwards custom headers', async () => {
|
|
471
|
+
const headers = { 'X-Custom': 'value' }
|
|
472
|
+
await api.sync('c1', { forceSync: true }, headers)
|
|
473
|
+
expect(client.post).toHaveBeenCalledWith('/contacts/c1/sync', { forceSync: true }, headers)
|
|
474
|
+
})
|
|
475
|
+
})
|
|
476
|
+
|
|
477
|
+
// ── block ────────────────────────────────────────────────────────
|
|
478
|
+
|
|
479
|
+
describe('block', () => {
|
|
480
|
+
it('calls client.post with /contacts/:id/block and body', async () => {
|
|
481
|
+
vi.mocked(client.post).mockResolvedValue({ ...contact, block: true })
|
|
482
|
+
const body: BlockContactPayload = { block: true, description: 'spam' }
|
|
483
|
+
const result = await api.block('c1', body)
|
|
484
|
+
expect(client.post).toHaveBeenCalledWith('/contacts/c1/block', body, undefined)
|
|
485
|
+
expect(result.block).toBe(true)
|
|
486
|
+
})
|
|
487
|
+
})
|
|
488
|
+
|
|
489
|
+
// ── markRead ─────────────────────────────────────────────────────
|
|
490
|
+
|
|
491
|
+
describe('markRead', () => {
|
|
492
|
+
it('calls client.post with /contacts/:id/mark-read and no body', async () => {
|
|
493
|
+
vi.mocked(client.post).mockResolvedValue('OK')
|
|
494
|
+
const headers = { 'X-Custom': 'value' }
|
|
495
|
+
const result = await api.markRead('c1', headers)
|
|
496
|
+
expect(client.post).toHaveBeenCalledWith('/contacts/c1/mark-read', undefined, headers)
|
|
497
|
+
expect(result).toBe('OK')
|
|
498
|
+
})
|
|
499
|
+
})
|
|
500
|
+
|
|
501
|
+
// ── getMedia ─────────────────────────────────────────────────────
|
|
502
|
+
|
|
503
|
+
describe('getMedia', () => {
|
|
504
|
+
const page: ContactMediaPage = { data: [], limit: 50, hasNextPage: false, nextCursor: null }
|
|
505
|
+
|
|
506
|
+
it('calls client.get with /contacts/:id/media when no query is provided', async () => {
|
|
507
|
+
vi.mocked(client.get).mockResolvedValue(page)
|
|
508
|
+
const result = await api.getMedia('c1')
|
|
509
|
+
expect(client.get).toHaveBeenCalledWith('/contacts/c1/media', undefined)
|
|
510
|
+
expect(result).toEqual(page)
|
|
511
|
+
})
|
|
512
|
+
|
|
513
|
+
it('serializes the type, cursor and perPage', async () => {
|
|
514
|
+
await api.getMedia('c1', {
|
|
515
|
+
where: { type: 'document', cursor: '2026-01-01T00:00:00Z' },
|
|
516
|
+
perPage: 10,
|
|
517
|
+
})
|
|
518
|
+
const url = decodeURIComponent(vi.mocked(client.get).mock.calls[0]?.[0] as string)
|
|
519
|
+
expect(url).toBe(
|
|
520
|
+
'/contacts/c1/media?query={"where":{"type":"document","cursor":"2026-01-01T00:00:00Z"},"perPage":10}',
|
|
521
|
+
)
|
|
522
|
+
})
|
|
523
|
+
})
|
|
524
|
+
|
|
525
|
+
// ── bulkTransferTickets ──────────────────────────────────────────
|
|
526
|
+
|
|
527
|
+
describe('bulkTransferTickets', () => {
|
|
528
|
+
it('calls client.post with /contacts/ticket/bulk-transfer and body', async () => {
|
|
529
|
+
const response: BulkTransferTicketsResult = {
|
|
530
|
+
message: 'Transferência realizada com sucesso',
|
|
531
|
+
ticketsSelectedId: ['t1'],
|
|
532
|
+
}
|
|
533
|
+
vi.mocked(client.post).mockResolvedValue(response)
|
|
534
|
+
const body: BulkTransferTicketsPayload = {
|
|
535
|
+
departmentId: 'd1',
|
|
536
|
+
userId: null,
|
|
537
|
+
ticketsSelectedId: ['t1'],
|
|
538
|
+
}
|
|
539
|
+
const result = await api.bulkTransferTickets(body)
|
|
540
|
+
expect(client.post).toHaveBeenCalledWith('/contacts/ticket/bulk-transfer', body, undefined)
|
|
541
|
+
expect(result).toEqual(response)
|
|
542
|
+
})
|
|
543
|
+
})
|
|
544
|
+
|
|
368
545
|
// ── Error propagation ────────────────────────────────────────────
|
|
369
546
|
|
|
370
547
|
describe('error propagation', () => {
|
|
@@ -3,12 +3,22 @@ import type { ApiClient } from '../../core/ApiClient'
|
|
|
3
3
|
import { BaseCrudApi } from '../../core/BaseCrudApi'
|
|
4
4
|
import type { ListQuery, Paginated } from '../../core/types'
|
|
5
5
|
import type {
|
|
6
|
+
BlockContactPayload,
|
|
7
|
+
BulkTransferTicketsPayload,
|
|
8
|
+
BulkTransferTicketsResult,
|
|
6
9
|
Contact,
|
|
10
|
+
ContactMediaPage,
|
|
11
|
+
ContactMediaQuery,
|
|
12
|
+
ContactsSelection,
|
|
7
13
|
CountContactsQuery,
|
|
8
14
|
CountMediaResult,
|
|
9
15
|
CreateContactPayload,
|
|
16
|
+
CreateManyContactsItem,
|
|
10
17
|
ExistsContactsParams,
|
|
18
|
+
ExportCsvPayload,
|
|
11
19
|
ExportTemplatePayload,
|
|
20
|
+
ImportContactsPayload,
|
|
21
|
+
SyncContactPayload,
|
|
12
22
|
TransferTicketPayload,
|
|
13
23
|
UpdateContactPayload,
|
|
14
24
|
} from './types'
|
|
@@ -120,4 +130,122 @@ export class ContactsApi extends BaseCrudApi<Contact, CreateContactPayload, Upda
|
|
|
120
130
|
headers,
|
|
121
131
|
)
|
|
122
132
|
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Creates or updates several contacts in one call. Existing contacts (same service and
|
|
136
|
+
* number or e-mail) are updated; the others are created. Returns the resulting contacts.
|
|
137
|
+
* @permissions contacts.view OR contacts.update OR contacts.create
|
|
138
|
+
*/
|
|
139
|
+
createMany(
|
|
140
|
+
body: CreateManyContactsItem[],
|
|
141
|
+
query?: ListQuery<Contact>,
|
|
142
|
+
headers?: Record<string, string>,
|
|
143
|
+
): Promise<Contact[]> {
|
|
144
|
+
const queryString = this.toQueryString(query)
|
|
145
|
+
return this.client.post<Contact[], CreateManyContactsItem[]>(
|
|
146
|
+
`${this.basePath}/many${queryString}`,
|
|
147
|
+
body,
|
|
148
|
+
headers,
|
|
149
|
+
)
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Deletes every contact of the account that matches the selection.
|
|
154
|
+
* @permissions contacts.view OR contacts.destroy
|
|
155
|
+
*/
|
|
156
|
+
deleteMany(body: ContactsSelection, headers?: Record<string, string>): Promise<boolean> {
|
|
157
|
+
return this.client.request<boolean, ContactsSelection>(
|
|
158
|
+
'DELETE',
|
|
159
|
+
`${this.basePath}/many`,
|
|
160
|
+
body,
|
|
161
|
+
headers,
|
|
162
|
+
)
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Exports the contacts that match the filter as CSV. Resolves to the CSV text.
|
|
167
|
+
* @permissions contacts.view AND contacts.export
|
|
168
|
+
*/
|
|
169
|
+
exportCsv(body: ExportCsvPayload, headers?: Record<string, string>): Promise<string> {
|
|
170
|
+
return this.client.post<string, ExportCsvPayload>(`${this.basePath}/export/csv`, body, headers)
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Starts the import of a CSV file previously uploaded through `FilesApi`. The import runs
|
|
175
|
+
* in the background; the header line is validated against the service type template.
|
|
176
|
+
* Resolves to `'OK'`.
|
|
177
|
+
* @permissions contacts.view OR contacts.update OR contacts.create
|
|
178
|
+
*/
|
|
179
|
+
importCsv(body: ImportContactsPayload, headers?: Record<string, string>): Promise<string> {
|
|
180
|
+
return this.client.post<string, ImportContactsPayload>(
|
|
181
|
+
`${this.basePath}/import-contacts`,
|
|
182
|
+
body,
|
|
183
|
+
headers,
|
|
184
|
+
)
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* Marks the contact as read and, when needed, syncs it with the messaging service.
|
|
189
|
+
* Resolves to `'OK'`.
|
|
190
|
+
* @permissions contacts.view OR contacts.update
|
|
191
|
+
*/
|
|
192
|
+
sync(id: string, body?: SyncContactPayload, headers?: Record<string, string>): Promise<string> {
|
|
193
|
+
return this.client.post<string, SyncContactPayload>(
|
|
194
|
+
`${this.basePath}/${id}/sync`,
|
|
195
|
+
body ?? {},
|
|
196
|
+
headers,
|
|
197
|
+
)
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* Blocks or unblocks a contact. Blocking closes the contact's open ticket. Requires the
|
|
202
|
+
* block list to be active on the account.
|
|
203
|
+
* @permissions contacts.block
|
|
204
|
+
*/
|
|
205
|
+
block(id: string, body: BlockContactPayload, headers?: Record<string, string>): Promise<Contact> {
|
|
206
|
+
return this.client.post<Contact, BlockContactPayload>(
|
|
207
|
+
`${this.basePath}/${id}/block`,
|
|
208
|
+
body,
|
|
209
|
+
headers,
|
|
210
|
+
)
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Resets the contact's unread counter. Resolves to `'OK'`.
|
|
215
|
+
* @permissions contacts.view OR contacts.update
|
|
216
|
+
*/
|
|
217
|
+
markRead(id: string, headers?: Record<string, string>): Promise<string> {
|
|
218
|
+
return this.client.post<string>(`${this.basePath}/${id}/mark-read`, undefined, headers)
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* Returns the files and links exchanged with a contact, cursor-paginated.
|
|
223
|
+
* @permissions contacts.view
|
|
224
|
+
*/
|
|
225
|
+
getMedia(
|
|
226
|
+
contactId: string,
|
|
227
|
+
query?: ContactMediaQuery,
|
|
228
|
+
headers?: Record<string, string>,
|
|
229
|
+
): Promise<ContactMediaPage> {
|
|
230
|
+
const queryString = this.toQueryString(query)
|
|
231
|
+
return this.client.get<ContactMediaPage>(
|
|
232
|
+
`${this.basePath}/${contactId}/media${queryString}`,
|
|
233
|
+
headers,
|
|
234
|
+
)
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
/**
|
|
238
|
+
* Transfers several tickets at once to a department and/or user.
|
|
239
|
+
* @permissions tickets.transfer.all.bulk
|
|
240
|
+
*/
|
|
241
|
+
bulkTransferTickets(
|
|
242
|
+
body: BulkTransferTicketsPayload,
|
|
243
|
+
headers?: Record<string, string>,
|
|
244
|
+
): Promise<BulkTransferTicketsResult> {
|
|
245
|
+
return this.client.post<BulkTransferTicketsResult, BulkTransferTicketsPayload>(
|
|
246
|
+
`${this.basePath}/ticket/bulk-transfer`,
|
|
247
|
+
body,
|
|
248
|
+
headers,
|
|
249
|
+
)
|
|
250
|
+
}
|
|
123
251
|
}
|