@ikatec/digisac-api-sdk 4.14.0 → 4.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/README.md +7 -2
  2. package/dist/apis/authHistory/AuthHistoryApi.cjs +9 -2
  3. package/dist/apis/authHistory/AuthHistoryApi.cjs.map +1 -1
  4. package/dist/apis/authHistory/AuthHistoryApi.d.ts +7 -2
  5. package/dist/apis/authHistory/AuthHistoryApi.d.ts.map +1 -1
  6. package/dist/apis/authHistory/AuthHistoryApi.mjs +9 -2
  7. package/dist/apis/authHistory/AuthHistoryApi.mjs.map +1 -1
  8. package/dist/apis/authHistory/types.d.ts +6 -1
  9. package/dist/apis/authHistory/types.d.ts.map +1 -1
  10. package/dist/apis/contacts/ContactsApi.cjs +10 -0
  11. package/dist/apis/contacts/ContactsApi.cjs.map +1 -1
  12. package/dist/apis/contacts/ContactsApi.d.ts +10 -2
  13. package/dist/apis/contacts/ContactsApi.d.ts.map +1 -1
  14. package/dist/apis/contacts/ContactsApi.mjs +10 -0
  15. package/dist/apis/contacts/ContactsApi.mjs.map +1 -1
  16. package/dist/apis/contacts/types.d.ts +76 -2
  17. package/dist/apis/contacts/types.d.ts.map +1 -1
  18. package/dist/apis/files/FilesApi.cjs +13 -1
  19. package/dist/apis/files/FilesApi.cjs.map +1 -1
  20. package/dist/apis/files/FilesApi.d.ts +12 -2
  21. package/dist/apis/files/FilesApi.d.ts.map +1 -1
  22. package/dist/apis/files/FilesApi.mjs +13 -1
  23. package/dist/apis/files/FilesApi.mjs.map +1 -1
  24. package/dist/apis/files/types.d.ts +19 -1
  25. package/dist/apis/files/types.d.ts.map +1 -1
  26. package/dist/core/BaseReadApi.cjs +2 -2
  27. package/dist/core/BaseReadApi.cjs.map +1 -1
  28. package/dist/core/BaseReadApi.d.ts +2 -2
  29. package/dist/core/BaseReadApi.mjs +2 -2
  30. package/dist/core/BaseReadApi.mjs.map +1 -1
  31. package/package.json +1 -1
  32. package/src/apis/authHistory/AuthHistoryApi.test.ts +16 -0
  33. package/src/apis/authHistory/AuthHistoryApi.ts +10 -2
  34. package/src/apis/authHistory/types.ts +6 -1
  35. package/src/apis/contacts/ContactsApi.test.ts +13 -0
  36. package/src/apis/contacts/ContactsApi.ts +23 -1
  37. package/src/apis/contacts/types.ts +83 -1
  38. package/src/apis/files/FilesApi.test.ts +21 -0
  39. package/src/apis/files/FilesApi.ts +19 -1
  40. package/src/apis/files/types.ts +20 -1
  41. package/src/apis/payloads.test-d.ts +39 -1
  42. package/src/core/BaseReadApi.ts +2 -2
@@ -1 +1 @@
1
- {"version":3,"file":"FilesApi.d.ts","sourceRoot":"","sources":["../../../src/apis/files/FilesApi.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAA;AACrD,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAA;AAEpD,OAAO,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;AAC1E,OAAO,KAAK,EACV,IAAI,EACJ,iBAAiB,EACjB,iBAAiB,EACjB,qBAAqB,EACrB,oBAAoB,EACpB,gBAAgB,EACjB,MAAM,SAAS,CAAA;AAEhB;;;;;GAKG;AACH,qBAAa,QAAS,SAAQ,WAAW,CACvC,IAAI,EACJ,iBAAiB,EACjB,iBAAiB,EACjB,SAAS,CAAC,IAAI,CAAC,EACf,gBAAgB,CACjB;gBACa,MAAM,EAAE,SAAS;IAI7B,wFAAwF;IAC/E,OAAO,CACd,KAAK,EAAE,SAAS,CAAC,IAAI,CAAC,GAAG;QAAE,QAAQ,EAAE,KAAK,CAAA;KAAE,EAC5C,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC/B,OAAO,CAAC,IAAI,EAAE,CAAC;IAClB,wFAAwF;IAC/E,OAAO,CACd,KAAK,CAAC,EAAE,SAAS,CAAC,IAAI,CAAC,GAAG;QAAE,QAAQ,CAAC,EAAE,IAAI,CAAA;KAAE,EAC7C,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC/B,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;IAC3B,wFAAwF;IAC/E,OAAO,CACd,KAAK,CAAC,EAAE,SAAS,CAAC,IAAI,CAAC,EACvB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC/B,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,IAAI,EAAE,CAAC;IAQpC,wFAAwF;IAC/E,MAAM,CAAC,KAAK,CAAC,EAAE,SAAS,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;IAIhG,4FAA4F;IACnF,OAAO,CACd,EAAE,EAAE,MAAM,EACV,KAAK,CAAC,EAAE,YAAY,CAAC,IAAI,CAAC,EAC1B,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC/B,OAAO,CAAC,IAAI,CAAC;IAIhB,4FAA4F;IACnF,UAAU,CACjB,EAAE,EAAE,MAAM,EACV,IAAI,EAAE,iBAAiB,EACvB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC/B,OAAO,CAAC,IAAI,CAAC;IAIhB;;;OAGG;IACM,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAI5F;;;;;OAKG;IACH,cAAc,CACZ,IAAI,EAAE,qBAAqB,EAC3B,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC/B,OAAO,CAAC,oBAAoB,CAAC;IAQhC;;;;;;OAMG;IACG,MAAM,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAMtF"}
1
+ {"version":3,"file":"FilesApi.d.ts","sourceRoot":"","sources":["../../../src/apis/files/FilesApi.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAA;AACrD,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAA;AAEpD,OAAO,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;AAC1E,OAAO,KAAK,EACV,IAAI,EACJ,iBAAiB,EACjB,iBAAiB,EACjB,qBAAqB,EACrB,oBAAoB,EACpB,gBAAgB,EAChB,oBAAoB,EACrB,MAAM,SAAS,CAAA;AAEhB;;;;;GAKG;AACH,qBAAa,QAAS,SAAQ,WAAW,CACvC,IAAI,EACJ,iBAAiB,EACjB,iBAAiB,EACjB,SAAS,CAAC,IAAI,CAAC,EACf,gBAAgB,CACjB;gBACa,MAAM,EAAE,SAAS;IAI7B,wFAAwF;IAC/E,OAAO,CACd,KAAK,EAAE,SAAS,CAAC,IAAI,CAAC,GAAG;QAAE,QAAQ,EAAE,KAAK,CAAA;KAAE,EAC5C,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC/B,OAAO,CAAC,IAAI,EAAE,CAAC;IAClB,wFAAwF;IAC/E,OAAO,CACd,KAAK,CAAC,EAAE,SAAS,CAAC,IAAI,CAAC,GAAG;QAAE,QAAQ,CAAC,EAAE,IAAI,CAAA;KAAE,EAC7C,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC/B,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;IAC3B,wFAAwF;IAC/E,OAAO,CACd,KAAK,CAAC,EAAE,SAAS,CAAC,IAAI,CAAC,EACvB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC/B,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,IAAI,EAAE,CAAC;IAQpC,wFAAwF;IAC/E,MAAM,CAAC,KAAK,CAAC,EAAE,SAAS,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;IAIhG,4FAA4F;IACnF,OAAO,CACd,EAAE,EAAE,MAAM,EACV,KAAK,CAAC,EAAE,YAAY,CAAC,IAAI,CAAC,EAC1B,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC/B,OAAO,CAAC,IAAI,CAAC;IAIhB,4FAA4F;IACnF,UAAU,CACjB,EAAE,EAAE,MAAM,EACV,IAAI,EAAE,iBAAiB,EACvB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC/B,OAAO,CAAC,IAAI,CAAC;IAIhB;;;OAGG;IACM,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAI5F;;;;;;OAMG;IACH,cAAc,CACZ,IAAI,EAAE,qBAAqB,EAC3B,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC/B,OAAO,CAAC,oBAAoB,CAAC;IAQhC;;;;;;;OAOG;IACH,aAAa,CAAC,IAAI,EAAE,oBAAoB,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC;IAQ5F;;;;;;OAMG;IACG,MAAM,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAMtF"}
@@ -38,12 +38,24 @@ var FilesApi = class extends BaseCrudApi {
38
38
  * Creates the record of a file and returns the signed URL to upload its content: send the
39
39
  * content with {@link upload}. An audio that must be converted (a voice message for the
40
40
  * connection) is sent in `base64` instead, and then no `urlToUpload` is returned. `name` and
41
- * `mimetype` are required (500 without them; an audio without `name` is named `recording`).
41
+ * `mimetype` are required (500 without them; an audio without `name` is named `recording`). With
42
+ * `serviceId`, an extension the account blocks for the type of the connection answers 403.
42
43
  */
43
44
  createToUpload(body, headers) {
44
45
  return this.client.post(`${this.basePath}/create-to-upload`, body, headers);
45
46
  }
46
47
  /**
48
+ * Copies the content of a file. With `urlToUpload` (the signed URL of a record created by
49
+ * {@link createToUpload} with the same `mimetype` as the file copied), the content is sent to that
50
+ * record and the answer is the `fileId` given; without it, a new record (`attachedType`
51
+ * `'message.file'`) is created with the copied content and its id is the answer, and with
52
+ * `serviceId` an extension the account blocks for the type of the connection answers 403. An
53
+ * unknown `fileId` answers 500.
54
+ */
55
+ duplicateFile(body, headers) {
56
+ return this.client.post(`${this.basePath}/duplicate-file`, body, headers);
57
+ }
58
+ /**
47
59
  * Uploads the content of a file to the `urlToUpload` returned by {@link createToUpload}. The URL
48
60
  * is signed by the storage, so the request goes straight to it, without the API token (the
49
61
  * storage refuses an `Authorization` header). `mimetype` must be the one sent to
@@ -1 +1 @@
1
- {"version":3,"file":"FilesApi.mjs","names":[],"sources":["../../../src/apis/files/FilesApi.ts"],"sourcesContent":["import type { ApiClient } from '../../core/ApiClient'\nimport { BaseCrudApi } from '../../core/BaseCrudApi'\nimport { requestExternal } from '../../core/requestExternal'\nimport type { GetByIdQuery, ListQuery, Paginated } from '../../core/types'\nimport type {\n File,\n CreateFilePayload,\n UpdateFilePayload,\n CreateToUploadPayload,\n CreateToUploadResult,\n DeleteFileResult,\n} from './types'\n\n/**\n * Files of the account. The backend serves `POST /files` (the record only, no content),\n * `POST /files/create-to-upload` (record + signed URL to upload the content), `POST\n * /files/duplicate-file`, `DELETE /files/:id` and the signed download `GET\n * /files/:accountId/:filename`; there is no list, read by id nor update.\n */\nexport class FilesApi extends BaseCrudApi<\n File,\n CreateFilePayload,\n UpdateFilePayload,\n ListQuery<File>,\n DeleteFileResult\n> {\n constructor(client: ApiClient) {\n super(client, '/files')\n }\n\n /** @deprecated Not served: the backend has no GET /files, so this route answers 404. */\n override getMany(\n query: ListQuery<File> & { paginate: false },\n headers?: Record<string, string>,\n ): Promise<File[]>\n /** @deprecated Not served: the backend has no GET /files, so this route answers 404. */\n override getMany(\n query?: ListQuery<File> & { paginate?: true },\n headers?: Record<string, string>,\n ): Promise<Paginated<File>>\n /** @deprecated Not served: the backend has no GET /files, so this route answers 404. */\n override getMany(\n query?: ListQuery<File>,\n headers?: Record<string, string>,\n ): Promise<Paginated<File> | File[]>\n override getMany(\n query?: ListQuery<File>,\n headers?: Record<string, string>,\n ): Promise<Paginated<File> | File[]> {\n return super.getMany(query, headers)\n }\n\n /** @deprecated Not served: the backend has no GET /files, so this route answers 404. */\n override getOne(query?: ListQuery<File>, headers?: Record<string, string>): Promise<File | null> {\n return super.getOne(query, headers)\n }\n\n /** @deprecated Not served: the backend has no GET /files/:id, so this route answers 404. */\n override getById(\n id: string,\n query?: GetByIdQuery<File>,\n headers?: Record<string, string>,\n ): Promise<File> {\n return super.getById(id, query, headers)\n }\n\n /** @deprecated Not served: the backend has no PUT /files/:id, so this route answers 404. */\n override updateById(\n id: string,\n body: UpdateFilePayload,\n headers?: Record<string, string>,\n ): Promise<File> {\n return super.updateById(id, body, headers)\n }\n\n /**\n * Deletes a file. Resolves `{ success: true }`, also for an unknown id; a file of another\n * account answers 403.\n */\n override deleteById(id: string, headers?: Record<string, string>): Promise<DeleteFileResult> {\n return super.deleteById(id, headers)\n }\n\n /**\n * Creates the record of a file and returns the signed URL to upload its content: send the\n * content with {@link upload}. An audio that must be converted (a voice message for the\n * connection) is sent in `base64` instead, and then no `urlToUpload` is returned. `name` and\n * `mimetype` are required (500 without them; an audio without `name` is named `recording`).\n */\n createToUpload(\n body: CreateToUploadPayload,\n headers?: Record<string, string>,\n ): Promise<CreateToUploadResult> {\n return this.client.post<CreateToUploadResult, CreateToUploadPayload>(\n `${this.basePath}/create-to-upload`,\n body,\n headers,\n )\n }\n\n /**\n * Uploads the content of a file to the `urlToUpload` returned by {@link createToUpload}. The URL\n * is signed by the storage, so the request goes straight to it, without the API token (the\n * storage refuses an `Authorization` header). `mimetype` must be the one sent to\n * `createToUpload`. Sent through `client.requestExternal` (the global `fetch` for a client\n * without it). A non-2xx answer of the storage throws `ApiError`.\n */\n async upload(urlToUpload: string, content: BodyInit, mimetype: string): Promise<void> {\n const headers = { 'Content-Type': mimetype }\n await (this.client.requestExternal\n ? this.client.requestExternal('PUT', urlToUpload, content, headers)\n : requestExternal('PUT', urlToUpload, content, headers))\n }\n}\n"],"mappings":";;;;;;;;;;AAmBA,IAAa,WAAb,cAA8B,YAM5B;CACA,YAAY,QAAmB;AAC7B,QAAM,QAAQ,SAAS;;CAkBzB,AAAS,QACP,OACA,SACmC;AACnC,SAAO,MAAM,QAAQ,OAAO,QAAQ;;;CAItC,AAAS,OAAO,OAAyB,SAAwD;AAC/F,SAAO,MAAM,OAAO,OAAO,QAAQ;;;CAIrC,AAAS,QACP,IACA,OACA,SACe;AACf,SAAO,MAAM,QAAQ,IAAI,OAAO,QAAQ;;;CAI1C,AAAS,WACP,IACA,MACA,SACe;AACf,SAAO,MAAM,WAAW,IAAI,MAAM,QAAQ;;;;;;CAO5C,AAAS,WAAW,IAAY,SAA6D;AAC3F,SAAO,MAAM,WAAW,IAAI,QAAQ;;;;;;;;CAStC,eACE,MACA,SAC+B;AAC/B,SAAO,KAAK,OAAO,KACjB,GAAG,KAAK,SAAS,oBACjB,MACA,QACD;;;;;;;;;CAUH,MAAM,OAAO,aAAqB,SAAmB,UAAiC;EACpF,MAAM,UAAU,EAAE,gBAAgB,UAAU;AAC5C,SAAO,KAAK,OAAO,kBACf,KAAK,OAAO,gBAAgB,OAAO,aAAa,SAAS,QAAQ,GACjE,gBAAgB,OAAO,aAAa,SAAS,QAAQ"}
1
+ {"version":3,"file":"FilesApi.mjs","names":[],"sources":["../../../src/apis/files/FilesApi.ts"],"sourcesContent":["import type { ApiClient } from '../../core/ApiClient'\nimport { BaseCrudApi } from '../../core/BaseCrudApi'\nimport { requestExternal } from '../../core/requestExternal'\nimport type { GetByIdQuery, ListQuery, Paginated } from '../../core/types'\nimport type {\n File,\n CreateFilePayload,\n UpdateFilePayload,\n CreateToUploadPayload,\n CreateToUploadResult,\n DeleteFileResult,\n DuplicateFilePayload,\n} from './types'\n\n/**\n * Files of the account. The backend serves `POST /files` (the record only, no content),\n * `POST /files/create-to-upload` (record + signed URL to upload the content), `POST\n * /files/duplicate-file`, `DELETE /files/:id` and the signed download `GET\n * /files/:accountId/:filename`; there is no list, read by id nor update.\n */\nexport class FilesApi extends BaseCrudApi<\n File,\n CreateFilePayload,\n UpdateFilePayload,\n ListQuery<File>,\n DeleteFileResult\n> {\n constructor(client: ApiClient) {\n super(client, '/files')\n }\n\n /** @deprecated Not served: the backend has no GET /files, so this route answers 404. */\n override getMany(\n query: ListQuery<File> & { paginate: false },\n headers?: Record<string, string>,\n ): Promise<File[]>\n /** @deprecated Not served: the backend has no GET /files, so this route answers 404. */\n override getMany(\n query?: ListQuery<File> & { paginate?: true },\n headers?: Record<string, string>,\n ): Promise<Paginated<File>>\n /** @deprecated Not served: the backend has no GET /files, so this route answers 404. */\n override getMany(\n query?: ListQuery<File>,\n headers?: Record<string, string>,\n ): Promise<Paginated<File> | File[]>\n override getMany(\n query?: ListQuery<File>,\n headers?: Record<string, string>,\n ): Promise<Paginated<File> | File[]> {\n return super.getMany(query, headers)\n }\n\n /** @deprecated Not served: the backend has no GET /files, so this route answers 404. */\n override getOne(query?: ListQuery<File>, headers?: Record<string, string>): Promise<File | null> {\n return super.getOne(query, headers)\n }\n\n /** @deprecated Not served: the backend has no GET /files/:id, so this route answers 404. */\n override getById(\n id: string,\n query?: GetByIdQuery<File>,\n headers?: Record<string, string>,\n ): Promise<File> {\n return super.getById(id, query, headers)\n }\n\n /** @deprecated Not served: the backend has no PUT /files/:id, so this route answers 404. */\n override updateById(\n id: string,\n body: UpdateFilePayload,\n headers?: Record<string, string>,\n ): Promise<File> {\n return super.updateById(id, body, headers)\n }\n\n /**\n * Deletes a file. Resolves `{ success: true }`, also for an unknown id; a file of another\n * account answers 403.\n */\n override deleteById(id: string, headers?: Record<string, string>): Promise<DeleteFileResult> {\n return super.deleteById(id, headers)\n }\n\n /**\n * Creates the record of a file and returns the signed URL to upload its content: send the\n * content with {@link upload}. An audio that must be converted (a voice message for the\n * connection) is sent in `base64` instead, and then no `urlToUpload` is returned. `name` and\n * `mimetype` are required (500 without them; an audio without `name` is named `recording`). With\n * `serviceId`, an extension the account blocks for the type of the connection answers 403.\n */\n createToUpload(\n body: CreateToUploadPayload,\n headers?: Record<string, string>,\n ): Promise<CreateToUploadResult> {\n return this.client.post<CreateToUploadResult, CreateToUploadPayload>(\n `${this.basePath}/create-to-upload`,\n body,\n headers,\n )\n }\n\n /**\n * Copies the content of a file. With `urlToUpload` (the signed URL of a record created by\n * {@link createToUpload} with the same `mimetype` as the file copied), the content is sent to that\n * record and the answer is the `fileId` given; without it, a new record (`attachedType`\n * `'message.file'`) is created with the copied content and its id is the answer, and with\n * `serviceId` an extension the account blocks for the type of the connection answers 403. An\n * unknown `fileId` answers 500.\n */\n duplicateFile(body: DuplicateFilePayload, headers?: Record<string, string>): Promise<string> {\n return this.client.post<string, DuplicateFilePayload>(\n `${this.basePath}/duplicate-file`,\n body,\n headers,\n )\n }\n\n /**\n * Uploads the content of a file to the `urlToUpload` returned by {@link createToUpload}. The URL\n * is signed by the storage, so the request goes straight to it, without the API token (the\n * storage refuses an `Authorization` header). `mimetype` must be the one sent to\n * `createToUpload`. Sent through `client.requestExternal` (the global `fetch` for a client\n * without it). A non-2xx answer of the storage throws `ApiError`.\n */\n async upload(urlToUpload: string, content: BodyInit, mimetype: string): Promise<void> {\n const headers = { 'Content-Type': mimetype }\n await (this.client.requestExternal\n ? this.client.requestExternal('PUT', urlToUpload, content, headers)\n : requestExternal('PUT', urlToUpload, content, headers))\n }\n}\n"],"mappings":";;;;;;;;;;AAoBA,IAAa,WAAb,cAA8B,YAM5B;CACA,YAAY,QAAmB;AAC7B,QAAM,QAAQ,SAAS;;CAkBzB,AAAS,QACP,OACA,SACmC;AACnC,SAAO,MAAM,QAAQ,OAAO,QAAQ;;;CAItC,AAAS,OAAO,OAAyB,SAAwD;AAC/F,SAAO,MAAM,OAAO,OAAO,QAAQ;;;CAIrC,AAAS,QACP,IACA,OACA,SACe;AACf,SAAO,MAAM,QAAQ,IAAI,OAAO,QAAQ;;;CAI1C,AAAS,WACP,IACA,MACA,SACe;AACf,SAAO,MAAM,WAAW,IAAI,MAAM,QAAQ;;;;;;CAO5C,AAAS,WAAW,IAAY,SAA6D;AAC3F,SAAO,MAAM,WAAW,IAAI,QAAQ;;;;;;;;;CAUtC,eACE,MACA,SAC+B;AAC/B,SAAO,KAAK,OAAO,KACjB,GAAG,KAAK,SAAS,oBACjB,MACA,QACD;;;;;;;;;;CAWH,cAAc,MAA4B,SAAmD;AAC3F,SAAO,KAAK,OAAO,KACjB,GAAG,KAAK,SAAS,kBACjB,MACA,QACD;;;;;;;;;CAUH,MAAM,OAAO,aAAqB,SAAmB,UAAiC;EACpF,MAAM,UAAU,EAAE,gBAAgB,UAAU;AAC5C,SAAO,KAAK,OAAO,kBACf,KAAK,OAAO,gBAAgB,OAAO,aAAa,SAAS,QAAQ,GACjE,gBAAgB,OAAO,aAAa,SAAS,QAAQ"}
@@ -60,7 +60,10 @@ export type CreateToUploadPayload = {
60
60
  mimetype: string;
61
61
  /** What the file is attached to, e.g. `'message.file'` (default), `'campaign.file'`, `'quickreply.file'`. */
62
62
  attachedType?: string;
63
- /** Connection that will send the file (used to decide the audio conversion). */
63
+ /**
64
+ * Connection that will send the file: used to decide the audio conversion and to apply the
65
+ * extensions the account blocks for its type (403).
66
+ */
64
67
  serviceId?: string;
65
68
  /** Audio sent as a voice message (default `true`). */
66
69
  isPtt?: boolean;
@@ -77,6 +80,21 @@ export type CreateToUploadResult = {
77
80
  name: string;
78
81
  mimetype: string;
79
82
  };
83
+ /** Body of `FilesApi.duplicateFile`. */
84
+ export type DuplicateFilePayload = {
85
+ /** The file whose content is copied. */
86
+ fileId: string;
87
+ /**
88
+ * Signed URL of a record created by `FilesApi.createToUpload`, with the same `mimetype` as the file
89
+ * copied, to receive the content. Without it, a new record is created with the copied content.
90
+ */
91
+ urlToUpload?: string;
92
+ /**
93
+ * Connection that will send the new record (used only without `urlToUpload`): the extensions the
94
+ * account blocks for its type apply.
95
+ */
96
+ serviceId?: string;
97
+ };
80
98
  /** Result of `FilesApi.deleteById`. */
81
99
  export type DeleteFileResult = {
82
100
  success: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/apis/files/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/apis/files/types.ts"],"names":[],"mappings":"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"}
@@ -4,8 +4,8 @@ const require_core_BaseApi = require('./BaseApi.cjs');
4
4
  //#region src/core/BaseReadApi.ts
5
5
  /**
6
6
  * Generic read-only resource: `getMany`, `getOne` and `getById` under `basePath`. Base of
7
- * `BaseCrudApi`, and of the resources the backend only serves for reading (e.g. permissions,
8
- * auth history).
7
+ * `BaseCrudApi`, and of the resources the backend serves for reading, plus their own actions (e.g.
8
+ * permissions, auth history).
9
9
  */
10
10
  var BaseReadApi = class extends require_core_BaseApi.BaseApi {
11
11
  basePath;
@@ -1 +1 @@
1
- {"version":3,"file":"BaseReadApi.cjs","names":["BaseApi"],"sources":["../../src/core/BaseReadApi.ts"],"sourcesContent":["import type { ApiClient } from './ApiClient'\nimport { BaseApi } from './BaseApi'\nimport type { GetByIdQuery, HasGetById, HasGetMany, ListQuery, Paginated } from './types'\n\n/**\n * Generic read-only resource: `getMany`, `getOne` and `getById` under `basePath`. Base of\n * `BaseCrudApi`, and of the resources the backend only serves for reading (e.g. permissions,\n * auth history).\n */\nexport class BaseReadApi<TResponse, TQuery extends ListQuery<TResponse> = ListQuery<TResponse>>\n extends BaseApi\n implements HasGetMany<TResponse, TQuery>, HasGetById<TResponse>\n{\n public readonly basePath: string\n\n constructor(client: ApiClient, basePath: string) {\n super(client)\n this.basePath = basePath.replace(/\\/$/, '')\n }\n\n getMany(\n query: TQuery & { paginate: false },\n headers?: Record<string, string>,\n ): Promise<TResponse[]>\n getMany(\n query?: TQuery & { paginate?: true },\n headers?: Record<string, string>,\n ): Promise<Paginated<TResponse>>\n getMany(\n query?: TQuery,\n headers?: Record<string, string>,\n ): Promise<Paginated<TResponse> | TResponse[]>\n getMany(\n query?: TQuery,\n headers?: Record<string, string>,\n ): Promise<Paginated<TResponse> | TResponse[]> {\n const queryString = this.toQueryString(query)\n return this.client.get<Paginated<TResponse> | TResponse[]>(\n `${this.basePath}${queryString}`,\n headers,\n )\n }\n\n /**\n * Returns the first resource matching the query, or `null` when none match.\n * Convenience over `getMany` with `limit: 1`.\n * @permissions $resourceName.view\n */\n async getOne(query?: TQuery, headers?: Record<string, string>): Promise<TResponse | null> {\n const results = await this.getMany(\n { ...query, limit: 1, paginate: false } as TQuery & { paginate: false },\n headers,\n )\n // An empty response body resolves to `undefined`.\n return results?.[0] ?? null\n }\n\n /**\n * Returns a single resource by ID. When it does not exist most routes answer 200 with an empty\n * body, which resolves to `undefined`.\n * @permissions $resourceName.view\n */\n getById(\n id: string,\n query?: GetByIdQuery<TResponse>,\n headers?: Record<string, string>,\n ): Promise<TResponse> {\n return this.client.get<TResponse>(`${this.basePath}/${id}${this.toQueryString(query)}`, headers)\n }\n}\n"],"mappings":";;;;;;;;;AASA,IAAa,cAAb,cACUA,6BAEV;CACE,AAAgB;CAEhB,YAAY,QAAmB,UAAkB;AAC/C,QAAM,OAAO;AACb,OAAK,WAAW,SAAS,QAAQ,OAAO,GAAG;;CAe7C,QACE,OACA,SAC6C;EAC7C,MAAM,cAAc,KAAK,cAAc,MAAM;AAC7C,SAAO,KAAK,OAAO,IACjB,GAAG,KAAK,WAAW,eACnB,QACD;;;;;;;CAQH,MAAM,OAAO,OAAgB,SAA6D;AAMxF,UALgB,MAAM,KAAK,QACzB;GAAE,GAAG;GAAO,OAAO;GAAG,UAAU;GAAO,EACvC,QACD,IAEgB,MAAM;;;;;;;CAQzB,QACE,IACA,OACA,SACoB;AACpB,SAAO,KAAK,OAAO,IAAe,GAAG,KAAK,SAAS,GAAG,KAAK,KAAK,cAAc,MAAM,IAAI,QAAQ"}
1
+ {"version":3,"file":"BaseReadApi.cjs","names":["BaseApi"],"sources":["../../src/core/BaseReadApi.ts"],"sourcesContent":["import type { ApiClient } from './ApiClient'\nimport { BaseApi } from './BaseApi'\nimport type { GetByIdQuery, HasGetById, HasGetMany, ListQuery, Paginated } from './types'\n\n/**\n * Generic read-only resource: `getMany`, `getOne` and `getById` under `basePath`. Base of\n * `BaseCrudApi`, and of the resources the backend serves for reading, plus their own actions (e.g.\n * permissions, auth history).\n */\nexport class BaseReadApi<TResponse, TQuery extends ListQuery<TResponse> = ListQuery<TResponse>>\n extends BaseApi\n implements HasGetMany<TResponse, TQuery>, HasGetById<TResponse>\n{\n public readonly basePath: string\n\n constructor(client: ApiClient, basePath: string) {\n super(client)\n this.basePath = basePath.replace(/\\/$/, '')\n }\n\n getMany(\n query: TQuery & { paginate: false },\n headers?: Record<string, string>,\n ): Promise<TResponse[]>\n getMany(\n query?: TQuery & { paginate?: true },\n headers?: Record<string, string>,\n ): Promise<Paginated<TResponse>>\n getMany(\n query?: TQuery,\n headers?: Record<string, string>,\n ): Promise<Paginated<TResponse> | TResponse[]>\n getMany(\n query?: TQuery,\n headers?: Record<string, string>,\n ): Promise<Paginated<TResponse> | TResponse[]> {\n const queryString = this.toQueryString(query)\n return this.client.get<Paginated<TResponse> | TResponse[]>(\n `${this.basePath}${queryString}`,\n headers,\n )\n }\n\n /**\n * Returns the first resource matching the query, or `null` when none match.\n * Convenience over `getMany` with `limit: 1`.\n * @permissions $resourceName.view\n */\n async getOne(query?: TQuery, headers?: Record<string, string>): Promise<TResponse | null> {\n const results = await this.getMany(\n { ...query, limit: 1, paginate: false } as TQuery & { paginate: false },\n headers,\n )\n // An empty response body resolves to `undefined`.\n return results?.[0] ?? null\n }\n\n /**\n * Returns a single resource by ID. When it does not exist most routes answer 200 with an empty\n * body, which resolves to `undefined`.\n * @permissions $resourceName.view\n */\n getById(\n id: string,\n query?: GetByIdQuery<TResponse>,\n headers?: Record<string, string>,\n ): Promise<TResponse> {\n return this.client.get<TResponse>(`${this.basePath}/${id}${this.toQueryString(query)}`, headers)\n }\n}\n"],"mappings":";;;;;;;;;AASA,IAAa,cAAb,cACUA,6BAEV;CACE,AAAgB;CAEhB,YAAY,QAAmB,UAAkB;AAC/C,QAAM,OAAO;AACb,OAAK,WAAW,SAAS,QAAQ,OAAO,GAAG;;CAe7C,QACE,OACA,SAC6C;EAC7C,MAAM,cAAc,KAAK,cAAc,MAAM;AAC7C,SAAO,KAAK,OAAO,IACjB,GAAG,KAAK,WAAW,eACnB,QACD;;;;;;;CAQH,MAAM,OAAO,OAAgB,SAA6D;AAMxF,UALgB,MAAM,KAAK,QACzB;GAAE,GAAG;GAAO,OAAO;GAAG,UAAU;GAAO,EACvC,QACD,IAEgB,MAAM;;;;;;;CAQzB,QACE,IACA,OACA,SACoB;AACpB,SAAO,KAAK,OAAO,IAAe,GAAG,KAAK,SAAS,GAAG,KAAK,KAAK,cAAc,MAAM,IAAI,QAAQ"}
@@ -3,8 +3,8 @@ import { BaseApi } from './BaseApi';
3
3
  import type { GetByIdQuery, HasGetById, HasGetMany, ListQuery, Paginated } from './types';
4
4
  /**
5
5
  * Generic read-only resource: `getMany`, `getOne` and `getById` under `basePath`. Base of
6
- * `BaseCrudApi`, and of the resources the backend only serves for reading (e.g. permissions,
7
- * auth history).
6
+ * `BaseCrudApi`, and of the resources the backend serves for reading, plus their own actions (e.g.
7
+ * permissions, auth history).
8
8
  */
9
9
  export declare class BaseReadApi<TResponse, TQuery extends ListQuery<TResponse> = ListQuery<TResponse>> extends BaseApi implements HasGetMany<TResponse, TQuery>, HasGetById<TResponse> {
10
10
  readonly basePath: string;
@@ -3,8 +3,8 @@ import { BaseApi } from "./BaseApi.mjs";
3
3
  //#region src/core/BaseReadApi.ts
4
4
  /**
5
5
  * Generic read-only resource: `getMany`, `getOne` and `getById` under `basePath`. Base of
6
- * `BaseCrudApi`, and of the resources the backend only serves for reading (e.g. permissions,
7
- * auth history).
6
+ * `BaseCrudApi`, and of the resources the backend serves for reading, plus their own actions (e.g.
7
+ * permissions, auth history).
8
8
  */
9
9
  var BaseReadApi = class extends BaseApi {
10
10
  basePath;
@@ -1 +1 @@
1
- {"version":3,"file":"BaseReadApi.mjs","names":[],"sources":["../../src/core/BaseReadApi.ts"],"sourcesContent":["import type { ApiClient } from './ApiClient'\nimport { BaseApi } from './BaseApi'\nimport type { GetByIdQuery, HasGetById, HasGetMany, ListQuery, Paginated } from './types'\n\n/**\n * Generic read-only resource: `getMany`, `getOne` and `getById` under `basePath`. Base of\n * `BaseCrudApi`, and of the resources the backend only serves for reading (e.g. permissions,\n * auth history).\n */\nexport class BaseReadApi<TResponse, TQuery extends ListQuery<TResponse> = ListQuery<TResponse>>\n extends BaseApi\n implements HasGetMany<TResponse, TQuery>, HasGetById<TResponse>\n{\n public readonly basePath: string\n\n constructor(client: ApiClient, basePath: string) {\n super(client)\n this.basePath = basePath.replace(/\\/$/, '')\n }\n\n getMany(\n query: TQuery & { paginate: false },\n headers?: Record<string, string>,\n ): Promise<TResponse[]>\n getMany(\n query?: TQuery & { paginate?: true },\n headers?: Record<string, string>,\n ): Promise<Paginated<TResponse>>\n getMany(\n query?: TQuery,\n headers?: Record<string, string>,\n ): Promise<Paginated<TResponse> | TResponse[]>\n getMany(\n query?: TQuery,\n headers?: Record<string, string>,\n ): Promise<Paginated<TResponse> | TResponse[]> {\n const queryString = this.toQueryString(query)\n return this.client.get<Paginated<TResponse> | TResponse[]>(\n `${this.basePath}${queryString}`,\n headers,\n )\n }\n\n /**\n * Returns the first resource matching the query, or `null` when none match.\n * Convenience over `getMany` with `limit: 1`.\n * @permissions $resourceName.view\n */\n async getOne(query?: TQuery, headers?: Record<string, string>): Promise<TResponse | null> {\n const results = await this.getMany(\n { ...query, limit: 1, paginate: false } as TQuery & { paginate: false },\n headers,\n )\n // An empty response body resolves to `undefined`.\n return results?.[0] ?? null\n }\n\n /**\n * Returns a single resource by ID. When it does not exist most routes answer 200 with an empty\n * body, which resolves to `undefined`.\n * @permissions $resourceName.view\n */\n getById(\n id: string,\n query?: GetByIdQuery<TResponse>,\n headers?: Record<string, string>,\n ): Promise<TResponse> {\n return this.client.get<TResponse>(`${this.basePath}/${id}${this.toQueryString(query)}`, headers)\n }\n}\n"],"mappings":";;;;;;;;AASA,IAAa,cAAb,cACU,QAEV;CACE,AAAgB;CAEhB,YAAY,QAAmB,UAAkB;AAC/C,QAAM,OAAO;AACb,OAAK,WAAW,SAAS,QAAQ,OAAO,GAAG;;CAe7C,QACE,OACA,SAC6C;EAC7C,MAAM,cAAc,KAAK,cAAc,MAAM;AAC7C,SAAO,KAAK,OAAO,IACjB,GAAG,KAAK,WAAW,eACnB,QACD;;;;;;;CAQH,MAAM,OAAO,OAAgB,SAA6D;AAMxF,UALgB,MAAM,KAAK,QACzB;GAAE,GAAG;GAAO,OAAO;GAAG,UAAU;GAAO,EACvC,QACD,IAEgB,MAAM;;;;;;;CAQzB,QACE,IACA,OACA,SACoB;AACpB,SAAO,KAAK,OAAO,IAAe,GAAG,KAAK,SAAS,GAAG,KAAK,KAAK,cAAc,MAAM,IAAI,QAAQ"}
1
+ {"version":3,"file":"BaseReadApi.mjs","names":[],"sources":["../../src/core/BaseReadApi.ts"],"sourcesContent":["import type { ApiClient } from './ApiClient'\nimport { BaseApi } from './BaseApi'\nimport type { GetByIdQuery, HasGetById, HasGetMany, ListQuery, Paginated } from './types'\n\n/**\n * Generic read-only resource: `getMany`, `getOne` and `getById` under `basePath`. Base of\n * `BaseCrudApi`, and of the resources the backend serves for reading, plus their own actions (e.g.\n * permissions, auth history).\n */\nexport class BaseReadApi<TResponse, TQuery extends ListQuery<TResponse> = ListQuery<TResponse>>\n extends BaseApi\n implements HasGetMany<TResponse, TQuery>, HasGetById<TResponse>\n{\n public readonly basePath: string\n\n constructor(client: ApiClient, basePath: string) {\n super(client)\n this.basePath = basePath.replace(/\\/$/, '')\n }\n\n getMany(\n query: TQuery & { paginate: false },\n headers?: Record<string, string>,\n ): Promise<TResponse[]>\n getMany(\n query?: TQuery & { paginate?: true },\n headers?: Record<string, string>,\n ): Promise<Paginated<TResponse>>\n getMany(\n query?: TQuery,\n headers?: Record<string, string>,\n ): Promise<Paginated<TResponse> | TResponse[]>\n getMany(\n query?: TQuery,\n headers?: Record<string, string>,\n ): Promise<Paginated<TResponse> | TResponse[]> {\n const queryString = this.toQueryString(query)\n return this.client.get<Paginated<TResponse> | TResponse[]>(\n `${this.basePath}${queryString}`,\n headers,\n )\n }\n\n /**\n * Returns the first resource matching the query, or `null` when none match.\n * Convenience over `getMany` with `limit: 1`.\n * @permissions $resourceName.view\n */\n async getOne(query?: TQuery, headers?: Record<string, string>): Promise<TResponse | null> {\n const results = await this.getMany(\n { ...query, limit: 1, paginate: false } as TQuery & { paginate: false },\n headers,\n )\n // An empty response body resolves to `undefined`.\n return results?.[0] ?? null\n }\n\n /**\n * Returns a single resource by ID. When it does not exist most routes answer 200 with an empty\n * body, which resolves to `undefined`.\n * @permissions $resourceName.view\n */\n getById(\n id: string,\n query?: GetByIdQuery<TResponse>,\n headers?: Record<string, string>,\n ): Promise<TResponse> {\n return this.client.get<TResponse>(`${this.basePath}/${id}${this.toQueryString(query)}`, headers)\n }\n}\n"],"mappings":";;;;;;;;AASA,IAAa,cAAb,cACU,QAEV;CACE,AAAgB;CAEhB,YAAY,QAAmB,UAAkB;AAC/C,QAAM,OAAO;AACb,OAAK,WAAW,SAAS,QAAQ,OAAO,GAAG;;CAe7C,QACE,OACA,SAC6C;EAC7C,MAAM,cAAc,KAAK,cAAc,MAAM;AAC7C,SAAO,KAAK,OAAO,IACjB,GAAG,KAAK,WAAW,eACnB,QACD;;;;;;;CAQH,MAAM,OAAO,OAAgB,SAA6D;AAMxF,UALgB,MAAM,KAAK,QACzB;GAAE,GAAG;GAAO,OAAO;GAAG,UAAU;GAAO,EACvC,QACD,IAEgB,MAAM;;;;;;;CAQzB,QACE,IACA,OACA,SACoB;AACpB,SAAO,KAAK,OAAO,IAAe,GAAG,KAAK,SAAS,GAAG,KAAK,KAAK,cAAc,MAAM,IAAI,QAAQ"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ikatec/digisac-api-sdk",
3
- "version": "4.14.0",
3
+ "version": "4.15.0",
4
4
  "type": "module",
5
5
  "main": "./dist/index.cjs",
6
6
  "module": "./dist/index.mjs",
@@ -115,4 +115,20 @@ describe('AuthHistoryApi', () => {
115
115
  await expect(api.getById('missing')).rejects.toThrow('Not found')
116
116
  })
117
117
  })
118
+
119
+ describe('registerLogout', () => {
120
+ it('calls client.post with /auth-history and an empty body', async () => {
121
+ vi.mocked(client.post).mockResolvedValue(undefined)
122
+ const result = await api.registerLogout()
123
+ expect(client.post).toHaveBeenCalledWith('/auth-history', {}, undefined)
124
+ expect(result).toBeUndefined()
125
+ })
126
+
127
+ it('forwards custom headers', async () => {
128
+ vi.mocked(client.post).mockResolvedValue(undefined)
129
+ const headers = { 'X-Req': 'r-1' }
130
+ await api.registerLogout(headers)
131
+ expect(client.post).toHaveBeenCalledWith('/auth-history', {}, headers)
132
+ })
133
+ })
118
134
  })
@@ -3,8 +3,8 @@ import { BaseReadApi } from '../../core/BaseReadApi'
3
3
  import type { AuthHistory } from './types'
4
4
 
5
5
  /**
6
- * Authentication events (auth, password_change, logout), read-only (guarded by
7
- * `authHistory.view`). Non-admin users can only see and access their own records.
6
+ * Authentication events (auth, password_change, logout, 2fa_disabled), read with
7
+ * `authHistory.view`. Non-admin users can only see and access their own records.
8
8
  *
9
9
  * Since 4.2 `getById` has the base signature `(id, query?, headers?)`: a call written as
10
10
  * `getById(id, headers)` with the headers in a variable still compiles, but the headers are sent
@@ -14,4 +14,12 @@ export class AuthHistoryApi extends BaseReadApi<AuthHistory> {
14
14
  constructor(client: ApiClient) {
15
15
  super(client, '/auth-history')
16
16
  }
17
+
18
+ /**
19
+ * Records the `logout` event of the current session, as the web app does before revoking its
20
+ * token (revoke the token apart: this call does not). Resolves with no body.
21
+ */
22
+ registerLogout(headers?: Record<string, string>): Promise<void> {
23
+ return this.client.post<void, Record<string, never>>(this.basePath, {}, headers)
24
+ }
17
25
  }
@@ -1,7 +1,12 @@
1
1
  import type { Account } from '../accounts/types'
2
2
  import type { User } from '../users/types'
3
3
 
4
- export type AuthHistoryEvent = 'auth' | 'password_change' | 'logout'
4
+ /**
5
+ * `auth`: a login (after the second factor, when active); `password_change`: by the user, by an
6
+ * admin or by the password reset; `logout`: recorded by `AuthHistoryApi.registerLogout`;
7
+ * `2fa_disabled`: the second factor turned off, by the user or by an admin.
8
+ */
9
+ export type AuthHistoryEvent = 'auth' | 'password_change' | 'logout' | '2fa_disabled'
5
10
 
6
11
  export type AuthHistory = {
7
12
  id: string
@@ -138,6 +138,19 @@ describe('ContactsApi', () => {
138
138
  await api.getById('cnt-1', undefined, headers)
139
139
  expect(client.get).toHaveBeenCalledWith('/contacts/cnt-1', headers)
140
140
  })
141
+
142
+ it('sends formatCustomFields and the include of the custom fields in the query', async () => {
143
+ vi.mocked(client.get).mockResolvedValue(contact)
144
+ const query = {
145
+ include: [{ model: 'customFieldValues' as const, include: ['customField' as const] }],
146
+ formatCustomFields: true,
147
+ }
148
+ await api.getById('cnt-1', query)
149
+ expect(client.get).toHaveBeenCalledWith(
150
+ `/contacts/cnt-1?query=${encodeURIComponent(JSON.stringify(query))}`,
151
+ undefined,
152
+ )
153
+ })
141
154
  })
142
155
 
143
156
  // ── create ───────────────────────────────────────────────────────
@@ -7,6 +7,8 @@ import type {
7
7
  BulkTransferTicketsPayload,
8
8
  BulkTransferTicketsResult,
9
9
  Contact,
10
+ ContactGetByIdQuery,
11
+ ContactListQuery,
10
12
  ContactMediaPage,
11
13
  ContactMediaQuery,
12
14
  ContactsSelection,
@@ -24,11 +26,31 @@ import type {
24
26
  SummarizeTicketResult,
25
27
  } from './types'
26
28
 
27
- export class ContactsApi extends BaseCrudApi<Contact, CreateContactPayload, UpdateContactPayload> {
29
+ export class ContactsApi extends BaseCrudApi<
30
+ Contact,
31
+ CreateContactPayload,
32
+ UpdateContactPayload,
33
+ ContactListQuery
34
+ > {
28
35
  constructor(client: ApiClient) {
29
36
  super(client, '/contacts')
30
37
  }
31
38
 
39
+ /**
40
+ * Returns a contact by ID. When it does not exist the route answers 200 with an empty body, which
41
+ * resolves to `undefined`. With `formatCustomFields: true` (and the include
42
+ * `{ model: 'customFieldValues', include: ['customField'] }`), the custom fields come keyed by name
43
+ * in `customFields`.
44
+ * @permissions contacts.view
45
+ */
46
+ override getById(
47
+ id: string,
48
+ query?: ContactGetByIdQuery,
49
+ headers?: Record<string, string>,
50
+ ): Promise<Contact> {
51
+ return super.getById(id, query, headers)
52
+ }
53
+
32
54
  /**
33
55
  * Downloads the CSV template (`;`-separated header line, in the language of the user) for
34
56
  * importing contacts, with columns based on the service type. Answered with no Content-Type.
@@ -1,10 +1,11 @@
1
+ import type { CustomField, CustomFieldType } from '../customFields/types'
1
2
  import type { Department } from '../departments/types'
2
3
  import type { Person } from '../people/types'
3
4
  import type { Service } from '../services/types'
4
5
  import type { Tag } from '../tags/types'
5
6
  import type { Ticket } from '../tickets/types'
6
7
  import type { User } from '../users/types'
7
- import type { IncludeItem, ListQuery, WhereClause } from '../../core/types'
8
+ import type { GetByIdQuery, IncludeItem, ListQuery, WhereClause } from '../../core/types'
8
9
 
9
10
  export type ContactStatus = 'online' | 'offline' | 'absent'
10
11
  export type ContactOrigin = 'api' | 'app' | 'campaign' | 'driver' | 'import' | 'web'
@@ -95,6 +96,56 @@ export type ContactDataBlock = {
95
96
  description: string
96
97
  }
97
98
 
99
+ /**
100
+ * A value of a custom field of the contact, as `include: ['customFieldValues']` answers it (the
101
+ * stored row).
102
+ */
103
+ export type CustomFieldValue = {
104
+ id: string
105
+ customFieldId: string
106
+ /** The contact. */
107
+ relatedId: string
108
+ relatedType: string | null
109
+ /**
110
+ * The value as stored: text, or JSON text for the composite types (`date-range`, `hour-range`,
111
+ * `numeric`, `monetary`, `phone`, `postal-code`).
112
+ */
113
+ value: string
114
+ createdAt: string
115
+ updatedAt: string
116
+ deletedAt: string | null
117
+ // relationships
118
+ customField?: CustomField
119
+ }
120
+
121
+ /**
122
+ * A custom field of the contact as `formatCustomFields: true` answers it, keyed by the name of the
123
+ * field in `Contact.customFields`.
124
+ */
125
+ export type FormattedCustomField = {
126
+ name: string
127
+ /** The value, parsed from JSON for the composite types. */
128
+ value: unknown
129
+ /** Id of the value. */
130
+ id: string
131
+ type: CustomFieldType
132
+ /** Id of the field. */
133
+ fieldId: string
134
+ /** When the field was created. */
135
+ createdAt: string
136
+ }
137
+
138
+ /** A custom field value sent in the create or update of a contact. */
139
+ export type ContactCustomFieldInput = {
140
+ /**
141
+ * Id of the custom field (`CustomField.id`, `FormattedCustomField.fieldId` or
142
+ * `CustomFieldValue.customFieldId`), not the id of the value.
143
+ */
144
+ id: string
145
+ /** Text, or an object for the composite types (stored as JSON). */
146
+ value: unknown
147
+ }
148
+
98
149
  export type Contact = {
99
150
  id: string
100
151
  idFromService: string | null
@@ -139,6 +190,13 @@ export type Contact = {
139
190
  person?: Person | null
140
191
  tags?: Tag[]
141
192
  currentTicket?: Ticket | null
193
+ /** With `include: ['customFieldValues']`, unless `formatCustomFields` is set. */
194
+ customFieldValues?: CustomFieldValue[]
195
+ /**
196
+ * With `formatCustomFields: true` and the include
197
+ * `{ model: 'customFieldValues', include: ['customField'] }`: the values keyed by the field name.
198
+ */
199
+ customFields?: Record<string, FormattedCustomField>
142
200
  }
143
201
 
144
202
  export type ContactRelationships =
@@ -148,6 +206,23 @@ export type ContactRelationships =
148
206
  | 'person'
149
207
  | 'tags'
150
208
  | 'currentTicket'
209
+ | 'customFieldValues'
210
+ | 'customFields'
211
+
212
+ type FormatCustomFieldsOption = {
213
+ /**
214
+ * Answers `customFields` keyed by the field name instead of the raw `customFieldValues` (with the
215
+ * include `{ model: 'customFieldValues', include: ['customField'] }`; without the nested
216
+ * `customField`, `customFields` comes empty).
217
+ */
218
+ formatCustomFields?: boolean
219
+ }
220
+
221
+ /** Query of `ContactsApi.getById`. */
222
+ export type ContactGetByIdQuery = GetByIdQuery<Contact> & FormatCustomFieldsOption
223
+
224
+ /** Query of `ContactsApi.getMany` and `getOne`. */
225
+ export type ContactListQuery = ListQuery<Contact> & FormatCustomFieldsOption
151
226
 
152
227
  export type CreateContactPayload = {
153
228
  name?: string
@@ -160,6 +235,8 @@ export type CreateContactPayload = {
160
235
  data?: ContactData
161
236
  note?: string
162
237
  origin?: ContactOrigin
238
+ /** Values of the custom fields of the account. An id that is not a custom field answers 400. */
239
+ customFields?: ContactCustomFieldInput[]
163
240
  }
164
241
 
165
242
  export type UpdateContactPayload = {
@@ -174,6 +251,11 @@ export type UpdateContactPayload = {
174
251
  block?: boolean
175
252
  /** Tag IDs to associate with the contact. */
176
253
  tagIds?: string[]
254
+ /**
255
+ * Values of the custom fields of the account: a value of the same field is updated. An id that is
256
+ * not a custom field is skipped.
257
+ */
258
+ customFields?: ContactCustomFieldInput[]
177
259
  }
178
260
 
179
261
  /** Result of `ContactsApi.summarizeTicket`. */
@@ -97,6 +97,27 @@ describe('FilesApi', () => {
97
97
  })
98
98
  })
99
99
 
100
+ describe('duplicateFile', () => {
101
+ it('calls client.post with /files/duplicate-file and resolves the id of the copy', async () => {
102
+ vi.mocked(client.post).mockResolvedValue('file-2')
103
+ const result = await api.duplicateFile({ fileId: 'file-1' })
104
+ expect(client.post).toHaveBeenCalledWith(
105
+ '/files/duplicate-file',
106
+ { fileId: 'file-1' },
107
+ undefined,
108
+ )
109
+ expect(result).toBe('file-2')
110
+ })
111
+
112
+ it('sends urlToUpload and serviceId in the body and forwards custom headers', async () => {
113
+ vi.mocked(client.post).mockResolvedValue('file-1')
114
+ const headers = { 'X-Req': 'r-1' }
115
+ const body = { fileId: 'file-1', urlToUpload: URL_TO_UPLOAD, serviceId: 'svc-1' }
116
+ await api.duplicateFile(body, headers)
117
+ expect(client.post).toHaveBeenCalledWith('/files/duplicate-file', body, headers)
118
+ })
119
+ })
120
+
100
121
  describe('deleteById', () => {
101
122
  it('calls client.delete with /files/:id and resolves { success }', async () => {
102
123
  vi.mocked(client.delete).mockResolvedValue({ success: true })
@@ -9,6 +9,7 @@ import type {
9
9
  CreateToUploadPayload,
10
10
  CreateToUploadResult,
11
11
  DeleteFileResult,
12
+ DuplicateFilePayload,
12
13
  } from './types'
13
14
 
14
15
  /**
@@ -85,7 +86,8 @@ export class FilesApi extends BaseCrudApi<
85
86
  * Creates the record of a file and returns the signed URL to upload its content: send the
86
87
  * content with {@link upload}. An audio that must be converted (a voice message for the
87
88
  * connection) is sent in `base64` instead, and then no `urlToUpload` is returned. `name` and
88
- * `mimetype` are required (500 without them; an audio without `name` is named `recording`).
89
+ * `mimetype` are required (500 without them; an audio without `name` is named `recording`). With
90
+ * `serviceId`, an extension the account blocks for the type of the connection answers 403.
89
91
  */
90
92
  createToUpload(
91
93
  body: CreateToUploadPayload,
@@ -98,6 +100,22 @@ export class FilesApi extends BaseCrudApi<
98
100
  )
99
101
  }
100
102
 
103
+ /**
104
+ * Copies the content of a file. With `urlToUpload` (the signed URL of a record created by
105
+ * {@link createToUpload} with the same `mimetype` as the file copied), the content is sent to that
106
+ * record and the answer is the `fileId` given; without it, a new record (`attachedType`
107
+ * `'message.file'`) is created with the copied content and its id is the answer, and with
108
+ * `serviceId` an extension the account blocks for the type of the connection answers 403. An
109
+ * unknown `fileId` answers 500.
110
+ */
111
+ duplicateFile(body: DuplicateFilePayload, headers?: Record<string, string>): Promise<string> {
112
+ return this.client.post<string, DuplicateFilePayload>(
113
+ `${this.basePath}/duplicate-file`,
114
+ body,
115
+ headers,
116
+ )
117
+ }
118
+
101
119
  /**
102
120
  * Uploads the content of a file to the `urlToUpload` returned by {@link createToUpload}. The URL
103
121
  * is signed by the storage, so the request goes straight to it, without the API token (the
@@ -74,7 +74,10 @@ export type CreateToUploadPayload = {
74
74
  mimetype: string
75
75
  /** What the file is attached to, e.g. `'message.file'` (default), `'campaign.file'`, `'quickreply.file'`. */
76
76
  attachedType?: string
77
- /** Connection that will send the file (used to decide the audio conversion). */
77
+ /**
78
+ * Connection that will send the file: used to decide the audio conversion and to apply the
79
+ * extensions the account blocks for its type (403).
80
+ */
78
81
  serviceId?: string
79
82
  /** Audio sent as a voice message (default `true`). */
80
83
  isPtt?: boolean
@@ -93,6 +96,22 @@ export type CreateToUploadResult = {
93
96
  mimetype: string
94
97
  }
95
98
 
99
+ /** Body of `FilesApi.duplicateFile`. */
100
+ export type DuplicateFilePayload = {
101
+ /** The file whose content is copied. */
102
+ fileId: string
103
+ /**
104
+ * Signed URL of a record created by `FilesApi.createToUpload`, with the same `mimetype` as the file
105
+ * copied, to receive the content. Without it, a new record is created with the copied content.
106
+ */
107
+ urlToUpload?: string
108
+ /**
109
+ * Connection that will send the new record (used only without `urlToUpload`): the extensions the
110
+ * account blocks for its type apply.
111
+ */
112
+ serviceId?: string
113
+ }
114
+
96
115
  /** Result of `FilesApi.deleteById`. */
97
116
  export type DeleteFileResult = {
98
117
  success: boolean
@@ -54,7 +54,14 @@ import { AcceptanceTermsApi } from './acceptanceTerms/AcceptanceTermsApi'
54
54
  import { CategoriesApi } from './categories/CategoriesApi'
55
55
  import { ContactBlockListsApi } from './contactBlockLists/ContactBlockListsApi'
56
56
  import { ContactBlockListsControlsApi } from './contactBlockListsControls/ContactBlockListsControlsApi'
57
- import type { SummarizeTicketResult } from './contacts/types'
57
+ import type {
58
+ Contact,
59
+ CustomFieldValue,
60
+ FormattedCustomField,
61
+ SummarizeTicketResult,
62
+ } from './contacts/types'
63
+ import { AuthHistoryApi } from './authHistory/AuthHistoryApi'
64
+ import type { AuthHistoryEvent } from './authHistory/types'
58
65
  import { CustomFieldsApi } from './customFields/CustomFieldsApi'
59
66
  import { DepartmentsApi } from './departments/DepartmentsApi'
60
67
  import type { Department } from './departments/types'
@@ -769,3 +776,34 @@ expectAssignable<Awaited<ReturnType<ServicesApi['accessManagement']>>>({
769
776
  })
770
777
  expectNotAssignable<Awaited<ReturnType<ServicesApi['accessManagement']>>>({ message: 'denied' })
771
778
  expectError(new ServicesApi(client).accessManagement('s-1', { userIds: ['u-1'] }))
779
+
780
+ // ── QARC-1015 (4.15.0): custom fields of the contact, file copy, logout event ─────
781
+
782
+ expectAssignable<Parameters<ContactsApi['create']>[0]>({
783
+ serviceId: 's-1',
784
+ customFields: [
785
+ { id: 'f-1', value: 'text' },
786
+ { id: 'f-2', value: { value: '10,50', identifier: 'BRL', min: '', max: '' } },
787
+ ],
788
+ })
789
+ expectAssignable<Parameters<ContactsApi['updateById']>[1]>({
790
+ customFields: [{ id: 'f-1', value: 'new' }],
791
+ })
792
+ expectError(
793
+ new ContactsApi(client).create({ serviceId: 's-1', customFields: [{ value: 'no id' }] }),
794
+ )
795
+ expectAssignable<Parameters<ContactsApi['getById']>[1]>({
796
+ include: [{ model: 'customFieldValues', include: ['customField'] }],
797
+ formatCustomFields: true,
798
+ })
799
+ declare const contactWithFields: Contact
800
+ expectType<CustomFieldValue[] | undefined>(contactWithFields.customFieldValues)
801
+ expectType<Record<string, FormattedCustomField> | undefined>(contactWithFields.customFields)
802
+ expectAssignable<Parameters<ContactsApi['getMany']>[0]>({
803
+ include: [{ model: 'customFieldValues', include: ['customField'] }],
804
+ formatCustomFields: true,
805
+ })
806
+ expectType<Promise<string>>(new FilesApi(client).duplicateFile({ fileId: 'file-1' }))
807
+ expectError(new FilesApi(client).duplicateFile({ urlToUpload: 'https://storage' }))
808
+ expectType<Promise<void>>(new AuthHistoryApi(client).registerLogout())
809
+ expectAssignable<AuthHistoryEvent>('2fa_disabled')
@@ -4,8 +4,8 @@ import type { GetByIdQuery, HasGetById, HasGetMany, ListQuery, Paginated } from
4
4
 
5
5
  /**
6
6
  * Generic read-only resource: `getMany`, `getOne` and `getById` under `basePath`. Base of
7
- * `BaseCrudApi`, and of the resources the backend only serves for reading (e.g. permissions,
8
- * auth history).
7
+ * `BaseCrudApi`, and of the resources the backend serves for reading, plus their own actions (e.g.
8
+ * permissions, auth history).
9
9
  */
10
10
  export class BaseReadApi<TResponse, TQuery extends ListQuery<TResponse> = ListQuery<TResponse>>
11
11
  extends BaseApi