diff --git a/packages/server-client/__tests__/__dataSets__/delete.ts b/packages/server-client/__tests__/__dataSets__/delete.ts index 30d5e638..dde3947c 100644 --- a/packages/server-client/__tests__/__dataSets__/delete.ts +++ b/packages/server-client/__tests__/__dataSets__/delete.ts @@ -23,4 +23,28 @@ export default [ statusText: 'OK', }, }, + { + label: 'make delete request with content-type header but no body', + request: ['/my/path', 'DELETE'], + response: [ + 204, + null, + undefined, + { + headers: { + 'Content-Type': 'application/json', + } + } + ], + clientMethod: 'sendDeleteRequest', + parameters: [`${BASE_URL}/my/path`], + expected: { + config: expect.anything(), + data: null, + headers: expect.anything(), + request: expect.anything(), + status: 204, + statusText: 'No Content', + }, + }, ]; diff --git a/packages/server-client/lib/client.ts b/packages/server-client/lib/client.ts index 9789f47e..75410c92 100644 --- a/packages/server-client/lib/client.ts +++ b/packages/server-client/lib/client.ts @@ -443,26 +443,39 @@ export class Client { } log('Request succeeded'); - + const contentLength = parseInt(response.headers.get('content-length') || '0'); const [contentType] = (response.headers.get('content-type') || '').split( ';', ); - log(`Response content type: ${contentType}`); - switch (contentType) { - case ContentType.FORM_URLENCODED: - log('Decoding form data'); - decoded = response.body - ? new URLSearchParams(await response.text()) - : ''; - break; - case ContentType.JSON: - log('Decoding JSON'); - decoded = await response.json(); - break; - default: - log('Decoding text'); - decoded = await response.text(); + log(`Response content type: ${contentType}`); + try { + const body = await response.text(); + + switch (contentType) { + case ContentType.FORM_URLENCODED: + log('Decoding form data'); + decoded = response.body + ? new URLSearchParams(body) + : ''; + break; + case ContentType.JSON: + log('Decoding JSON'); + decoded = JSON.parse(body); + break; + default: + log('Decoding text'); + decoded = body; + } + } catch (error) { + log('Failed to decode body', error); + if (contentLength > 0) { + throw new VetchError( + 'Failed to decode response body', + request, + response, + ); + } } log('Decoded body', decoded); diff --git a/packages/verify2/__tests__/__dataSets__/cancel.ts b/packages/verify2/__tests__/__dataSets__/cancel.ts index 71554617..302d5f56 100644 --- a/packages/verify2/__tests__/__dataSets__/cancel.ts +++ b/packages/verify2/__tests__/__dataSets__/cancel.ts @@ -1,8 +1,28 @@ +import { + SDKTestCase, + keyAuth, + validateBearerAuth, +} from '../../../../testHelpers'; +import { + Verify2, +} from '../../lib/'; + export default [ { label: 'cancel request', - request: ['/v2/verify/091e717f-8715-41a0-a3f0-cc04912deaa1', 'DELETE'], - response: [204], + baseUrl: 'https://api.nexmo.com', + reqHeaders: { + authorization: validateBearerAuth, + }, + client: new Verify2(keyAuth), + generator: false, + error: false, + requests: [ + ['/v2/verify/091e717f-8715-41a0-a3f0-cc04912deaa1', 'DELETE'], + ], + responses: [ + [204], + ], method: 'post', clientMethod: 'cancel', parameters: ['091e717f-8715-41a0-a3f0-cc04912deaa1'], @@ -10,19 +30,29 @@ export default [ }, { label: 'error when request not found', - request: ['/v2/verify/091e717f-8715-41a0-a3f0-cc04912deaa1', 'DELETE'], - response: [ - 404, - { - title: 'Not Found', - type: 'https://developer.vonage.com/api-errors#not-found', - detail: 'Request was not found or it has been verified already.', - instance: 'bf0ca0bf927b3b52e3cb03217e1a1ddf', - }, + baseUrl: 'https://api.nexmo.com', + reqHeaders: { + authorization: validateBearerAuth, + }, + client: new Verify2(keyAuth), + generator: false, + error: false, + requests: [ + ['/v2/verify/091e717f-8715-41a0-a3f0-cc04912deaa1', 'DELETE'], + ], + responses: [ + [ + 404, + { + title: 'Not Found', + type: 'https://developer.vonage.com/api-errors#not-found', + detail: 'Request was not found or it has been verified already.', + instance: 'bf0ca0bf927b3b52e3cb03217e1a1ddf', + }, + ], ], - method: 'delete', clientMethod: 'cancel', parameters: ['091e717f-8715-41a0-a3f0-cc04912deaa1'], expected: false, }, -]; +] as SDKTestCase[]; diff --git a/packages/verify2/__tests__/__dataSets__/check.ts b/packages/verify2/__tests__/__dataSets__/check.ts index db8ffcfc..eff0601c 100644 --- a/packages/verify2/__tests__/__dataSets__/check.ts +++ b/packages/verify2/__tests__/__dataSets__/check.ts @@ -1,49 +1,74 @@ import { CheckCodeRequest, CheckRequestResponse } from '../../lib/types'; +import { + SDKTestCase, + keyAuth, + validateBearerAuth, +} from '../../../../testHelpers'; +import { Verify2 } from '../../lib'; export default [ { label: 'check code', - request: [ - '/v2/verify/091e717f-8715-41a0-a3f0-cc04912deaa1', - 'POST', - { - code: '123456', - } as CheckCodeRequest, + baseUrl: 'https://api.nexmo.com', + reqHeaders: { + authorization: validateBearerAuth, + }, + client: new Verify2(keyAuth), + generator: false, + error: false, + requests: [ + [ + '/v2/verify/091e717f-8715-41a0-a3f0-cc04912deaa1', + 'POST', + { + code: '123456', + } as CheckCodeRequest, + ], ], - response: [ - 200, - { - request_id: '091e717f-8715-41a0-a3f0-cc04912deaa1', - status: 'complete', - } as CheckRequestResponse, + responses: [ + [ + 200, + { + request_id: '091e717f-8715-41a0-a3f0-cc04912deaa1', + status: 'complete', + } as CheckRequestResponse, + ], ], - method: 'post', clientMethod: 'checkCode', parameters: ['091e717f-8715-41a0-a3f0-cc04912deaa1', '123456'], expected: 'complete', }, { label: 'error when request not found', - request: [ - '/v2/verify/091e717f-8715-41a0-a3f0-cc04912deaa1', - 'POST', - { - code: '123456', - } as CheckCodeRequest, + baseUrl: 'https://api.nexmo.com', + reqHeaders: { + authorization: validateBearerAuth, + }, + client: new Verify2(keyAuth), + generator: false, + error: 'Request failed with status code 404', + requests: [ + [ + '/v2/verify/091e717f-8715-41a0-a3f0-cc04912deaa1', + 'POST', + { + code: '123456', + } as CheckCodeRequest, + ], ], - response: [ - 404, - { - title: 'Not Found', - type: 'https://developer.vonage.com/api-errors#not-found', - detail: 'Request was not found or it has been verified already.', - instance: 'bf0ca0bf927b3b52e3cb03217e1a1ddf', - }, + responses: [ + [ + 404, + { + title: 'Not Found', + type: 'https://developer.vonage.com/api-errors#not-found', + detail: 'Request was not found or it has been verified already.', + instance: 'bf0ca0bf927b3b52e3cb03217e1a1ddf', + }, + ], ], - method: 'post', clientMethod: 'checkCode', parameters: ['091e717f-8715-41a0-a3f0-cc04912deaa1', '123456'], expected: true, - error: 'Request failed with status code 404', }, -]; +] as SDKTestCase[]; diff --git a/packages/verify2/__tests__/__dataSets__/index.ts b/packages/verify2/__tests__/__dataSets__/index.ts index 44901e4d..019c31f7 100644 --- a/packages/verify2/__tests__/__dataSets__/index.ts +++ b/packages/verify2/__tests__/__dataSets__/index.ts @@ -1,18 +1,28 @@ import requestTests from './verify'; import checkTests from './check'; import cancelTests from './cancel'; +import templateTests from './templates'; +import fragmentTests from './templateFragments'; export default [ { - label: 'Request tests', + name: 'Request tests', tests: requestTests, }, { - label: 'Check tests', + name: 'Check tests', tests: checkTests, }, { - label: 'Cancel tests', + name: 'Cancel tests', tests: cancelTests, }, + { + name: 'Templates tests', + tests: templateTests, + }, + { + name: 'Template Fragment tests', + tests: fragmentTests, + } ]; diff --git a/packages/verify2/__tests__/__dataSets__/templateFragments.ts b/packages/verify2/__tests__/__dataSets__/templateFragments.ts new file mode 100644 index 00000000..fd6a6745 --- /dev/null +++ b/packages/verify2/__tests__/__dataSets__/templateFragments.ts @@ -0,0 +1,662 @@ +import { + SDKTestCase, + keyAuth, + validateBearerAuth, +} from '../../../../testHelpers'; +import { + Verify2, + ListAllTemplateFragmentsResponse, + TemplateFragmentResponse, + TemplateFragmentPage, + TemplateFragment, +} from '../../lib/'; + +export default [ + { + label: 'fetch a page of templates', + baseUrl: 'https://api.nexmo.com', + reqHeaders: { + authorization: validateBearerAuth, + }, + requests: [ + [ + '/v2/verify/templates/22f571c1-f41a-4db2-bba7-f23a069200c1/template_fragments', + 'GET', + ], + ], + responses: [ + [ + 200, + { + total_items: 25, + page: 1, + page_size: 10, + total_pages: 3, + _embedded: { + template_fragments: [ + { + template_fragment_id: 'c70f446e-997a-4313-a081-60a02a31dc19', + channel: 'sms', + locale: 'en-us', + text: 'Your verification code is ${code} for ${brand}. It is valid for ${time-limit} ${time-limit-unit}.', + date_created: '2023-01-01T10:00:00.000Z', + date_updated: '2023-02-01T12:00:00.000Z', + _links: { + self: { + href: 'https://api.nexmo.com/v2/templates/22f571c1-f41a-4db2-bba7-f23a069200c1/template_fragments/c70f446e-997a-4313-a081-60a02a31dc19', + }, + template: { + href: 'https://api.nexmo.com/v2/templates/22f571c1-f41a-4db2-bba7-f23a069200c1', + }, + }, + } as TemplateFragmentResponse, + { + template_fragment_id: '9a2c62fb-c917-42df-be7a-ab1dc88b00d0', + channel: 'voice', + locale: 'fr-fr', + text: 'Votre code de vérification est ${code} pour ${brand}. Il est valide pour ${time-limit} ${time-limit-unit}.', + date_created: '2023-03-15T09:30:00.000Z', + date_updated: '2023-04-10T10:45:00.000Z', + _links: { + self: { + href: 'https://api.nexmo.com/v2/templates/22f571c1-f41a-4db2-bba7-f23a069200c1/template_fragments/9a2c62fb-c917-42df-be7a-ab1dc88b00d0', + }, + template: { + href: 'https://api.nexmo.com/v2/templates/22f571c1-f41a-4db2-bba7-f23a069200c1', + }, + }, + } as TemplateFragmentResponse, + ], + }, + _links: { + self: { + href: '/v2/verify/templates', + }, + next: { + href: '/v2/verify/templates?page=2', + }, + }, + } as ListAllTemplateFragmentsResponse, + ], + ], + client: new Verify2(keyAuth), + clientMethod: 'getTemplateFragmentPage' as keyof Verify2, + parameters: [ + { + templateId: '22f571c1-f41a-4db2-bba7-f23a069200c1', + } + ], + generator: false, + error: false, + expected: { + totalItems: 25, + page: 1, + pageSize: 10, + totalPages: 3, + fragments: [ + { + templateFragmentId: 'c70f446e-997a-4313-a081-60a02a31dc19', + channel: 'sms', + locale: 'en-us', + text: 'Your verification code is ${code} for ${brand}. It is valid for ${time-limit} ${time-limit-unit}.', + dateCreated: '2023-01-01T10:00:00.000Z', + dateUpdated: '2023-02-01T12:00:00.000Z', + links: { + self: { + href: 'https://api.nexmo.com/v2/templates/22f571c1-f41a-4db2-bba7-f23a069200c1/template_fragments/c70f446e-997a-4313-a081-60a02a31dc19', + }, + template: { + href: 'https://api.nexmo.com/v2/templates/22f571c1-f41a-4db2-bba7-f23a069200c1', + }, + }, + } as TemplateFragment, + { + templateFragmentId: '9a2c62fb-c917-42df-be7a-ab1dc88b00d0', + channel: 'voice', + locale: 'fr-fr', + text: 'Votre code de vérification est ${code} pour ${brand}. Il est valide pour ${time-limit} ${time-limit-unit}.', + dateCreated: '2023-03-15T09:30:00.000Z', + dateUpdated: '2023-04-10T10:45:00.000Z', + links: { + self: { + href: 'https://api.nexmo.com/v2/templates/22f571c1-f41a-4db2-bba7-f23a069200c1/template_fragments/9a2c62fb-c917-42df-be7a-ab1dc88b00d0', + }, + template: { + href: 'https://api.nexmo.com/v2/templates/22f571c1-f41a-4db2-bba7-f23a069200c1', + }, + }, + } as TemplateFragment, + ], + links: { + self: { + href: '/v2/verify/templates', + }, + next: { + href: '/v2/verify/templates?page=2', + }, + }, + } as TemplateFragmentPage, + }, + { + label: 'fetch a page of templates with pagination parameters', + baseUrl: 'https://api.nexmo.com', + reqHeaders: { + authorization: validateBearerAuth, + }, + requests: [ + [ + '/v2/verify/templates/22f571c1-f41a-4db2-bba7-f23a069200c1/template_fragments?page=1&page_size=10', + 'GET', + ], + ], + responses: [ + [ + 200, + { + total_items: 25, + page: 1, + page_size: 10, + total_pages: 3, + _embedded: { + template_fragments: [ + { + template_fragment_id: 'c70f446e-997a-4313-a081-60a02a31dc19', + channel: 'sms', + locale: 'en-us', + text: 'Your verification code is ${code} for ${brand}. It is valid for ${time-limit} ${time-limit-unit}.', + date_created: '2023-01-01T10:00:00.000Z', + date_updated: '2023-02-01T12:00:00.000Z', + _links: { + self: { + href: 'https://api.nexmo.com/v2/templates/22f571c1-f41a-4db2-bba7-f23a069200c1/template_fragments/c70f446e-997a-4313-a081-60a02a31dc19', + }, + template: { + href: 'https://api.nexmo.com/v2/templates/22f571c1-f41a-4db2-bba7-f23a069200c1', + }, + }, + } as TemplateFragmentResponse, + { + template_fragment_id: '9a2c62fb-c917-42df-be7a-ab1dc88b00d0', + channel: 'voice', + locale: 'fr-fr', + text: 'Votre code de vérification est ${code} pour ${brand}. Il est valide pour ${time-limit} ${time-limit-unit}.', + date_created: '2023-03-15T09:30:00.000Z', + date_updated: '2023-04-10T10:45:00.000Z', + _links: { + self: { + href: 'https://api.nexmo.com/v2/templates/22f571c1-f41a-4db2-bba7-f23a069200c1/template_fragments/9a2c62fb-c917-42df-be7a-ab1dc88b00d0', + }, + template: { + href: 'https://api.nexmo.com/v2/templates/22f571c1-f41a-4db2-bba7-f23a069200c1', + }, + }, + } as TemplateFragmentResponse, + ], + }, + _links: { + self: { + href: '/v2/verify/templates', + }, + next: { + href: '/v2/verify/templates?page=2', + }, + }, + } as ListAllTemplateFragmentsResponse, + ], + ], + client: new Verify2(keyAuth), + clientMethod: 'getTemplateFragmentPage' as keyof Verify2, + parameters: [ + { + templateId: '22f571c1-f41a-4db2-bba7-f23a069200c1', + page: 1, + pageSize: 10, + } + ], + generator: false, + error: false, + expected: { + totalItems: 25, + page: 1, + pageSize: 10, + totalPages: 3, + fragments: [ + { + templateFragmentId: 'c70f446e-997a-4313-a081-60a02a31dc19', + channel: 'sms', + locale: 'en-us', + text: 'Your verification code is ${code} for ${brand}. It is valid for ${time-limit} ${time-limit-unit}.', + dateCreated: '2023-01-01T10:00:00.000Z', + dateUpdated: '2023-02-01T12:00:00.000Z', + links: { + self: { + href: 'https://api.nexmo.com/v2/templates/22f571c1-f41a-4db2-bba7-f23a069200c1/template_fragments/c70f446e-997a-4313-a081-60a02a31dc19', + }, + template: { + href: 'https://api.nexmo.com/v2/templates/22f571c1-f41a-4db2-bba7-f23a069200c1', + }, + }, + } as TemplateFragment, + { + templateFragmentId: '9a2c62fb-c917-42df-be7a-ab1dc88b00d0', + channel: 'voice', + locale: 'fr-fr', + text: 'Votre code de vérification est ${code} pour ${brand}. Il est valide pour ${time-limit} ${time-limit-unit}.', + dateCreated: '2023-03-15T09:30:00.000Z', + dateUpdated: '2023-04-10T10:45:00.000Z', + links: { + self: { + href: 'https://api.nexmo.com/v2/templates/22f571c1-f41a-4db2-bba7-f23a069200c1/template_fragments/9a2c62fb-c917-42df-be7a-ab1dc88b00d0', + }, + template: { + href: 'https://api.nexmo.com/v2/templates/22f571c1-f41a-4db2-bba7-f23a069200c1', + }, + }, + } as TemplateFragment, + ], + links: { + self: { + href: '/v2/verify/templates', + }, + next: { + href: '/v2/verify/templates?page=2', + }, + }, + } as TemplateFragmentPage, + }, + { + label: 'list all template fragments', + baseUrl: 'https://api.nexmo.com', + reqHeaders: { + authorization: validateBearerAuth, + }, + requests: [ + [ + '/v2/verify/templates/22f571c1-f41a-4db2-bba7-f23a069200c1/template_fragments?page=1', + 'GET', + ], + [ + '/v2/verify/templates/22f571c1-f41a-4db2-bba7-f23a069200c1/template_fragments?page=2', + 'GET', + ], + ], + responses: [ + [ + 200, + { + total_items: 25, + page: 1, + page_size: 10, + total_pages: 3, + _embedded: { + template_fragments: [ + { + template_fragment_id: 'c70f446e-997a-4313-a081-60a02a31dc19', + channel: 'sms', + locale: 'en-us', + text: 'Your verification code is ${code} for ${brand}. It is valid for ${time-limit} ${time-limit-unit}.', + date_created: '2023-01-01T10:00:00.000Z', + date_updated: '2023-02-01T12:00:00.000Z', + _links: { + self: { + href: 'https://api.nexmo.com/v2/templates/22f571c1-f41a-4db2-bba7-f23a069200c1/template_fragments/c70f446e-997a-4313-a081-60a02a31dc19', + }, + template: { + href: 'https://api.nexmo.com/v2/templates/22f571c1-f41a-4db2-bba7-f23a069200c1', + }, + }, + } as TemplateFragmentResponse, + ], + }, + _links: { + self: { + href: '/v2/verify/templates', + }, + next: { + href: '/v2/verify/templates?page=2', + }, + }, + } as ListAllTemplateFragmentsResponse, + ], + [ + 200, + { + total_items: 25, + page: 1, + page_size: 10, + total_pages: 3, + _embedded: { + template_fragments: [ + { + template_fragment_id: '9a2c62fb-c917-42df-be7a-ab1dc88b00d0', + channel: 'voice', + locale: 'fr-fr', + text: 'Votre code de vérification est ${code} pour ${brand}. Il est valide pour ${time-limit} ${time-limit-unit}.', + date_created: '2023-03-15T09:30:00.000Z', + date_updated: '2023-04-10T10:45:00.000Z', + _links: { + self: { + href: 'https://api.nexmo.com/v2/templates/22f571c1-f41a-4db2-bba7-f23a069200c1/template_fragments/9a2c62fb-c917-42df-be7a-ab1dc88b00d0', + }, + template: { + href: 'https://api.nexmo.com/v2/templates/22f571c1-f41a-4db2-bba7-f23a069200c1', + }, + }, + } as TemplateFragmentResponse, + ], + }, + _links: { + self: { + href: '/v2/verify/templates', + }, + prev:{ + href: '/v2/verify/templates?page=1', + }, + }, + } as ListAllTemplateFragmentsResponse, + ], + ], + client: new Verify2(keyAuth), + clientMethod: 'listAllTemplateFragments' as keyof Verify2, + parameters: [ + { + templateId: '22f571c1-f41a-4db2-bba7-f23a069200c1', + } + ], + generator: true, + error: false, + expected: [ + { + templateFragmentId: 'c70f446e-997a-4313-a081-60a02a31dc19', + channel: 'sms', + locale: 'en-us', + text: 'Your verification code is ${code} for ${brand}. It is valid for ${time-limit} ${time-limit-unit}.', + dateCreated: '2023-01-01T10:00:00.000Z', + dateUpdated: '2023-02-01T12:00:00.000Z', + links: { + self: { + href: 'https://api.nexmo.com/v2/templates/22f571c1-f41a-4db2-bba7-f23a069200c1/template_fragments/c70f446e-997a-4313-a081-60a02a31dc19', + }, + template: { + href: 'https://api.nexmo.com/v2/templates/22f571c1-f41a-4db2-bba7-f23a069200c1', + }, + }, + } as TemplateFragment, + { + templateFragmentId: '9a2c62fb-c917-42df-be7a-ab1dc88b00d0', + channel: 'voice', + locale: 'fr-fr', + text: 'Votre code de vérification est ${code} pour ${brand}. Il est valide pour ${time-limit} ${time-limit-unit}.', + dateCreated: '2023-03-15T09:30:00.000Z', + dateUpdated: '2023-04-10T10:45:00.000Z', + links: { + self: { + href: 'https://api.nexmo.com/v2/templates/22f571c1-f41a-4db2-bba7-f23a069200c1/template_fragments/9a2c62fb-c917-42df-be7a-ab1dc88b00d0', + }, + template: { + href: 'https://api.nexmo.com/v2/templates/22f571c1-f41a-4db2-bba7-f23a069200c1', + }, + }, + } as TemplateFragment, + ], + }, + { + label: 'fetch a template fragment', + baseUrl: 'https://api.nexmo.com', + reqHeaders: { + authorization: validateBearerAuth, + }, + requests: [ + [ + '/v2/verify/templates/22f571c1-f41a-4db2-bba7-f23a069200c1/template_fragments/c70f446e-997a-4313-a081-60a02a31dc19', + 'GET', + ], + ], + responses: [ + [ + 200, + { + template_fragment_id: 'c70f446e-997a-4313-a081-60a02a31dc19', + channel: 'sms', + locale: 'en-us', + text: 'Your verification code is ${code} for ${brand}. It is valid for ${time-limit} ${time-limit-unit}.', + date_created: '2023-01-01T10:00:00.000Z', + date_updated: '2023-02-01T12:00:00.000Z', + _links: { + self: { + href: 'https://api.nexmo.com/v2/templates/22f571c1-f41a-4db2-bba7-f23a069200c1/template_fragments/c70f446e-997a-4313-a081-60a02a31dc19', + }, + template: { + href: 'https://api.nexmo.com/v2/templates/22f571c1-f41a-4db2-bba7-f23a069200c1', + }, + }, + } as TemplateFragmentResponse, + ], + ], + client: new Verify2(keyAuth), + clientMethod: 'getTemplateFragment' as keyof Verify2, + parameters: [ + '22f571c1-f41a-4db2-bba7-f23a069200c1', + 'c70f446e-997a-4313-a081-60a02a31dc19', + ], + generator: false, + error: false, + expected: { + templateFragmentId: 'c70f446e-997a-4313-a081-60a02a31dc19', + channel: 'sms', + locale: 'en-us', + text: 'Your verification code is ${code} for ${brand}. It is valid for ${time-limit} ${time-limit-unit}.', + dateCreated: '2023-01-01T10:00:00.000Z', + dateUpdated: '2023-02-01T12:00:00.000Z', + links: { + self: { + href: 'https://api.nexmo.com/v2/templates/22f571c1-f41a-4db2-bba7-f23a069200c1/template_fragments/c70f446e-997a-4313-a081-60a02a31dc19', + }, + template: { + href: 'https://api.nexmo.com/v2/templates/22f571c1-f41a-4db2-bba7-f23a069200c1', + }, + }, + } as TemplateFragment, + }, + { + label: 'delete a template fragment', + baseUrl: 'https://api.nexmo.com', + reqHeaders: { + authorization: validateBearerAuth, + }, + requests: [ + [ + '/v2/verify/templates/22f571c1-f41a-4db2-bba7-f23a069200c1/template_fragments/c70f446e-997a-4313-a081-60a02a31dc19', + 'DELETE', + ], + ], + responses: [ + [ + 204, + ], + ], + client: new Verify2(keyAuth), + clientMethod: 'deleteTemplateFragment' as keyof Verify2, + parameters: [ + '22f571c1-f41a-4db2-bba7-f23a069200c1', + 'c70f446e-997a-4313-a081-60a02a31dc19', + ], + generator: false, + error: false, + expected: true + }, + { + label: 'create a template fragment', + baseUrl: 'https://api.nexmo.com', + reqHeaders: { + authorization: validateBearerAuth, + }, + requests: [ + [ + '/v2/verify/templates/22f571c1-f41a-4db2-bba7-f23a069200c1/template_fragments', + 'POST', + { + channel: 'sms', + locale: 'en-us', + text: 'The verification code is ${code} for ${brand}. It is valid for ${time-limit} ${time-limit-unit}.', + } + ], + ], + responses: [ + [ + 200, + { + template_fragment_id: 'c70f446e-997a-4313-a081-60a02a31dc19', + channel: 'sms', + locale: 'en-us', + text: 'The verification code is ${code} for ${brand}. It is valid for ${time-limit} ${time-limit-unit}.', + date_created: '2023-01-01T10:00:00.000Z', + date_updated: '2023-02-01T12:00:00.000Z', + _links: { + self: { + href: 'https://api.nexmo.com/v2/templates/22f571c1-f41a-4db2-bba7-f23a069200c1/template_fragments/c70f446e-997a-4313-a081-60a02a31dc19', + }, + template: { + href: 'https://api.nexmo.com/v2/templates/22f571c1-f41a-4db2-bba7-f23a069200c1', + }, + }, + } as TemplateFragmentResponse, + ], + ], + client: new Verify2(keyAuth), + clientMethod: 'createTemplateFragment' as keyof Verify2, + parameters: [ + '22f571c1-f41a-4db2-bba7-f23a069200c1', + { + channel: 'sms', + locale: 'en-us', + text: 'The verification code is ${code} for ${brand}. It is valid for ${time-limit} ${time-limit-unit}.', + } + ], + generator: false, + error: false, + expected: { + templateFragmentId: 'c70f446e-997a-4313-a081-60a02a31dc19', + channel: 'sms', + locale: 'en-us', + text: 'The verification code is ${code} for ${brand}. It is valid for ${time-limit} ${time-limit-unit}.', + dateCreated: '2023-01-01T10:00:00.000Z', + dateUpdated: '2023-02-01T12:00:00.000Z', + links: { + self: { + href: 'https://api.nexmo.com/v2/templates/22f571c1-f41a-4db2-bba7-f23a069200c1/template_fragments/c70f446e-997a-4313-a081-60a02a31dc19', + }, + template: { + href: 'https://api.nexmo.com/v2/templates/22f571c1-f41a-4db2-bba7-f23a069200c1', + }, + }, + } as TemplateFragment, + }, + { + label: 'update a template fragment', + baseUrl: 'https://api.nexmo.com', + reqHeaders: { + authorization: validateBearerAuth, + }, + requests: [ + [ + '/v2/verify/templates/22f571c1-f41a-4db2-bba7-f23a069200c1/template_fragments/c70f446e-997a-4313-a081-60a02a31dc19', + 'PATCH', + ], + ], + responses: [ + [ + 200, + { + template_fragment_id: 'c70f446e-997a-4313-a081-60a02a31dc19', + channel: 'sms', + locale: 'en-us', + text: 'The verification code is ${code} for ${brand}. It is valid for ${time-limit} ${time-limit-unit}.', + date_created: '2023-01-01T10:00:00.000Z', + date_updated: '2023-02-01T12:00:00.000Z', + _links: { + self: { + href: 'https://api.nexmo.com/v2/templates/22f571c1-f41a-4db2-bba7-f23a069200c1/template_fragments/c70f446e-997a-4313-a081-60a02a31dc19', + }, + template: { + href: 'https://api.nexmo.com/v2/templates/22f571c1-f41a-4db2-bba7-f23a069200c1', + }, + }, + } as TemplateFragmentResponse, + ], + ], + client: new Verify2(keyAuth), + clientMethod: 'updateTemplateFragment' as keyof Verify2, + parameters: [ + '22f571c1-f41a-4db2-bba7-f23a069200c1', + { + templateFragmentId: 'c70f446e-997a-4313-a081-60a02a31dc19', + channel: 'sms', + locale: 'en-us', + text: 'The verification code is ${code} for ${brand}. It is valid for ${time-limit} ${time-limit-unit}.', + dateCreated: '2023-01-01T10:00:00.000Z', + dateUpdated: '2023-02-01T12:00:00.000Z', + links: { + self: { + href: 'https://api.nexmo.com/v2/templates/22f571c1-f41a-4db2-bba7-f23a069200c1/template_fragments/c70f446e-997a-4313-a081-60a02a31dc19', + }, + template: { + href: 'https://api.nexmo.com/v2/templates/22f571c1-f41a-4db2-bba7-f23a069200c1', + }, + }, + } + ], + generator: false, + error: false, + expected: { + templateFragmentId: 'c70f446e-997a-4313-a081-60a02a31dc19', + channel: 'sms', + locale: 'en-us', + text: 'The verification code is ${code} for ${brand}. It is valid for ${time-limit} ${time-limit-unit}.', + dateCreated: '2023-01-01T10:00:00.000Z', + dateUpdated: '2023-02-01T12:00:00.000Z', + links: { + self: { + href: 'https://api.nexmo.com/v2/templates/22f571c1-f41a-4db2-bba7-f23a069200c1/template_fragments/c70f446e-997a-4313-a081-60a02a31dc19', + }, + template: { + href: 'https://api.nexmo.com/v2/templates/22f571c1-f41a-4db2-bba7-f23a069200c1', + }, + }, + } as TemplateFragment, + }, + { + label: 'error when missing template fragment id', + baseUrl: 'https://api.nexmo.com', + reqHeaders: { + authorization: validateBearerAuth, + }, + requests: [ + ], + responses: [ + ], + client: new Verify2(keyAuth), + clientMethod: 'updateTemplateFragment' as keyof Verify2, + parameters: [ + '22f571c1-f41a-4db2-bba7-f23a069200c1', + { + channel: 'sms', + locale: 'en-us', + text: 'The verification code is ${code} for ${brand}. It is valid for ${time-limit} ${time-limit-unit}.', + dateCreated: '2023-01-01T10:00:00.000Z', + dateUpdated: '2023-02-01T12:00:00.000Z', + links: { + self: { + href: 'https://api.nexmo.com/v2/templates/22f571c1-f41a-4db2-bba7-f23a069200c1/template_fragments/c70f446e-997a-4313-a081-60a02a31dc19', + }, + template: { + href: 'https://api.nexmo.com/v2/templates/22f571c1-f41a-4db2-bba7-f23a069200c1', + }, + }, + } + ], + generator: false, + error: 'Template Fragment ID is required for updating a template fragment', + expected: null, + } +] as SDKTestCase[]; diff --git a/packages/verify2/__tests__/__dataSets__/templates.ts b/packages/verify2/__tests__/__dataSets__/templates.ts new file mode 100644 index 00000000..03d2e0f9 --- /dev/null +++ b/packages/verify2/__tests__/__dataSets__/templates.ts @@ -0,0 +1,517 @@ +import { + SDKTestCase, + keyAuth, + validateBearerAuth, +} from '../../../../testHelpers'; +import { + Verify2, + Template, + ListAllTemplatesResponse, + TemplateResponse, + TemplatePage, +} from '../../lib/'; + +export default [ + { + label: 'fetch a page of templates', + baseUrl: 'https://api.nexmo.com', + reqHeaders: { + authorization: validateBearerAuth, + }, + requests: [ + [ + '/v2/verify/templates', + 'GET', + ], + ], + responses: [ + [ + 200, + { + total_items: 25, + page: 1, + page_size: 10, + total_pages: 3, + _embedded: { + templates: [ + { + template_id: 'a1b2c3d4', + name: 'My Template', + is_default: true, + _links: { + self: { + href: '/v2/verify/templates/a1b2c3d4', + }, + }, + } as TemplateResponse, + { + template_id: 'e5f6g7h8', + name: 'Another Template', + is_default: false, + _links: { + self: { + href: '/v2/verify/templates/e5f6g7h8', + }, + }, + } as TemplateResponse, + ], + }, + _links: { + self: { + href: '/v2/verify/templates', + }, + next: { + href: '/v2/verify/templates?page=2', + }, + }, + } as ListAllTemplatesResponse, + ], + ], + client: new Verify2(keyAuth), + clientMethod: 'getTemplatePage' as keyof Verify2, + parameters: [], + generator: false, + error: false, + expected: { + totalItems: 25, + page: 1, + pageSize: 10, + totalPages: 3, + templates: [ + { + templateId: 'a1b2c3d4', + name: 'My Template', + isDefault: true, + links: { + self: { + href: '/v2/verify/templates/a1b2c3d4', + }, + }, + } as Template, + { + templateId: 'e5f6g7h8', + name: 'Another Template', + isDefault: false, + links: { + self: { + href: '/v2/verify/templates/e5f6g7h8', + }, + }, + } as Template, + ], + links: { + self: { + href: '/v2/verify/templates', + }, + next: { + href: '/v2/verify/templates?page=2', + }, + }, + } as TemplatePage, + }, + { + label: 'fetch a page of templates with pagination parameters', + baseUrl: 'https://api.nexmo.com', + reqHeaders: { + authorization: validateBearerAuth, + }, + client: new Verify2(keyAuth), + generator: false, + error: false, + requests: [ + [ + '/v2/verify/templates?page=2&page_size=10', + 'GET', + ], + ], + responses: [ + [ + 200, + { + total_items: 25, + page: 1, + page_size: 10, + total_pages: 3, + _embedded: { + templates: [ + { + template_id: 'a1b2c3d4', + name: 'My Template', + is_default: true, + _links: { + self: { + href: '/v2/verify/templates/a1b2c3d4', + }, + }, + } as TemplateResponse, + { + template_id: 'e5f6g7h8', + name: 'Another Template', + is_default: false, + _links: { + self: { + href: '/v2/verify/templates/e5f6g7h8', + }, + }, + } as TemplateResponse, + ], + }, + _links: { + self: { + href: '/v2/verify/templates', + }, + next: { + href: '/v2/verify/templates?page=2', + }, + }, + } as ListAllTemplatesResponse, + ], + ], + clientMethod: 'getTemplatePage', + parameters: [ + { + page: 2, + pageSize: 10, + } + ], + expected: { + totalItems: 25, + page: 1, + pageSize: 10, + totalPages: 3, + templates: [ + { + templateId: 'a1b2c3d4', + name: 'My Template', + isDefault: true, + links: { + self: { + href: '/v2/verify/templates/a1b2c3d4', + }, + }, + } as Template, + { + templateId: 'e5f6g7h8', + name: 'Another Template', + isDefault: false, + links: { + self: { + href: '/v2/verify/templates/e5f6g7h8', + }, + }, + } as Template, + ], + links: { + self: { + href: '/v2/verify/templates', + }, + next: { + href: '/v2/verify/templates?page=2', + }, + }, + } as TemplatePage, + }, + { + label: 'list all templates', + baseUrl: 'https://api.nexmo.com', + reqHeaders: { + authorization: validateBearerAuth, + }, + client: new Verify2(keyAuth), + generator: true, + error: false, + requests: [ + [ + '/v2/verify/templates?page=1', + 'GET', + ], + [ + '/v2/verify/templates?page=2', + 'GET', + ], + ], + responses: [ + [ + 200, + { + total_items: 25, + page: 1, + page_size: 10, + total_pages: 3, + _embedded: { + templates: [ + { + template_id: 'a1b2c3d4', + name: 'My Template', + is_default: true, + _links: { + self: { + href: '/v2/verify/templates/a1b2c3d4', + }, + }, + } as TemplateResponse, + ], + }, + _links: { + self: { + href: '/v2/verify/templates', + }, + next: { + href: '/v2/verify/templates?page=2', + }, + }, + } as ListAllTemplatesResponse, + ], + [ + 200, + { + total_items: 25, + page: 1, + page_size: 10, + total_pages: 3, + _embedded: { + templates: [ + { + template_id: 'e5f6g7h8', + name: 'Another Template', + is_default: false, + _links: { + self: { + href: '/v2/verify/templates/e5f6g7h8', + }, + }, + } as TemplateResponse, + ], + }, + _links: { + self: { + href: '/v2/verify/templates', + }, + }, + } as ListAllTemplatesResponse, + ], + ], + clientMethod: 'listAllTemplates', + parameters: [], + expected: [ + { + templateId: 'a1b2c3d4', + name: 'My Template', + isDefault: true, + links: { + self: { + href: '/v2/verify/templates/a1b2c3d4', + }, + }, + }, + { + templateId: 'e5f6g7h8', + name: 'Another Template', + isDefault: false, + links: { + self: { + href: '/v2/verify/templates/e5f6g7h8', + }, + }, + } + ], + }, + { + label: 'fetch a template', + baseUrl: 'https://api.nexmo.com', + reqHeaders: { + authorization: validateBearerAuth, + }, + client: new Verify2(keyAuth), + generator: false, + error: false, + requests: [ + [ + '/v2/verify/templates/a1b2c3d4', + 'GET', + ], + ], + responses: [ + [ + 200, + { + template_id: 'a1b2c3d4', + name: 'My Template', + is_default: true, + _links: { + self: { + href: '/v2/verify/templates/a1b2c3d4', + }, + }, + } as TemplateResponse, + ], + ], + clientMethod: 'getTemplate' as keyof Verify2, + parameters: [ + 'a1b2c3d4', + ], + expected: { + templateId: 'a1b2c3d4', + name: 'My Template', + isDefault: true, + links: { + self: { + href: '/v2/verify/templates/a1b2c3d4', + }, + }, + }, + }, + { + label: 'delete a template', + baseUrl: 'https://api.nexmo.com', + reqHeaders: { + authorization: validateBearerAuth, + }, + client: new Verify2(keyAuth), + generator: false, + error: false, + requests: [ + [ + '/v2/verify/templates/a1b2c3d4', + 'DELETE', + ], + ], + responses: [ + [ + 204, + ], + ], + clientMethod: 'deleteTemplate' as keyof Verify2, + parameters: [ + 'a1b2c3d4', + ], + expected: true, + }, + { + label: 'create a template', + baseUrl: 'https://api.nexmo.com', + reqHeaders: { + authorization: validateBearerAuth, + }, + client: new Verify2(keyAuth), + generator: false, + error: false, + requests: [ + [ + '/v2/verify/templates', + 'POST', + { + name: 'My Template', + } + ], + ], + responses: [ + [ + 200, + { + templateId: 'a1b2c3d4', + name: 'My Template', + isDefault: false, + links: { + self: { + href: '/v2/verify/templates/a1b2c3d4', + }, + }, + + } + ], + ], + clientMethod: 'createTemplate' as keyof Verify2, + parameters: [ + { + name: 'My Template', + } + ], + expected: { + templateId: 'a1b2c3d4', + name: 'My Template', + isDefault: false, + links: { + self: { + href: '/v2/verify/templates/a1b2c3d4', + }, + } + }, + }, + { + label: 'update a template', + baseUrl: 'https://api.nexmo.com', + reqHeaders: { + authorization: validateBearerAuth, + }, + client: new Verify2(keyAuth), + generator: false, + error: false, + requests: [ + [ + '/v2/verify/templates/a1b2c3d4', + 'PATCH', + { + name: 'My Updated Template', + is_default: false, + } + ], + ], + responses: [ + [ + 200, + { + templateId: 'a1b2c3d4', + name: 'My Updated Template', + isDefault: false, + links: { + self: { + href: '/v2/verify/templates/a1b2c3d4', + }, + }, + + } + ], + ], + clientMethod: 'updateTemplate' as keyof Verify2, + parameters: [ + { + templateId: 'a1b2c3d4', + name: 'My Updated Template', + isDefault: false, + } + ], + expected: { + templateId: 'a1b2c3d4', + name: 'My Updated Template', + isDefault: false, + links: { + self: { + href: '/v2/verify/templates/a1b2c3d4', + }, + } + }, + }, + { + label: 'error when missing template id', + baseUrl: 'https://api.nexmo.com', + reqHeaders: { + authorization: validateBearerAuth, + }, + client: new Verify2(keyAuth), + generator: false, + error: 'Template ID is required for updating a template', + requests: [ + ], + responses: [ + ], + clientMethod: 'updateTemplate' as keyof Verify2, + parameters: [ + { + name: 'My Updated Template', + isDefault: false, + } + ], + expected: null, + }, +] as SDKTestCase[]; diff --git a/packages/verify2/__tests__/__dataSets__/verify.ts b/packages/verify2/__tests__/__dataSets__/verify.ts index 8b8cfd5a..f46ee389 100644 --- a/packages/verify2/__tests__/__dataSets__/verify.ts +++ b/packages/verify2/__tests__/__dataSets__/verify.ts @@ -1,4 +1,10 @@ import { + SDKTestCase, + keyAuth, + validateBearerAuth, +} from '../../../../testHelpers'; +import { + Verify2, VerificationRequest, SMSWorkflow, VerificationRequestParams, @@ -16,26 +22,36 @@ import { export default [ { label: 'start request using SMS', - request: [ - '/v2/verify', - 'POST', - { - brand: 'Vonage', - workflow: [ - { - channel: Channels.SMS, - to: '14152739164', - }, - ], - } as VerificationRequest, - ], - response: [ - 202, - { - request_id: 'cef1c266-d144-485e-8915-bd2d51b06776', - } as VerificationResponse, + baseUrl: 'https://api.nexmo.com', + reqHeaders: { + authorization: validateBearerAuth, + }, + client: new Verify2(keyAuth), + generator: false, + error: false, + requests: [ + [ + '/v2/verify', + 'POST', + { + brand: 'Vonage', + workflow: [ + { + channel: Channels.SMS, + to: '14152739164', + }, + ], + } as VerificationRequest, + ], + ], + responses: [ + [ + 202, + { + request_id: 'cef1c266-d144-485e-8915-bd2d51b06776', + } as VerificationResponse, + ], ], - method: 'post', clientMethod: 'newRequest', parameters: [ { @@ -54,26 +70,36 @@ export default [ }, { label: 'start request using WhatsApp', - request: [ - '/v2/verify', - 'POST', - { - brand: 'Vonage', - workflow: [ - { - channel: Channels.WHATSAPP, - to: '14152739164', - }, - ], - } as VerificationRequest, - ], - response: [ - 202, - { - request_id: 'cef1c266-d144-485e-8915-bd2d51b06776', - } as VerificationResponse, + baseUrl: 'https://api.nexmo.com', + reqHeaders: { + authorization: validateBearerAuth, + }, + client: new Verify2(keyAuth), + generator: false, + error: false, + requests: [ + [ + '/v2/verify', + 'POST', + { + brand: 'Vonage', + workflow: [ + { + channel: Channels.WHATSAPP, + to: '14152739164', + }, + ], + } as VerificationRequest, + ], + ], + responses: [ + [ + 202, + { + request_id: 'cef1c266-d144-485e-8915-bd2d51b06776', + } as VerificationResponse, + ], ], - method: 'post', clientMethod: 'newRequest', parameters: [ { @@ -92,26 +118,36 @@ export default [ }, { label: 'start request using WhatsApp interactive', - request: [ - '/v2/verify', - 'POST', - { - brand: 'Vonage', - workflow: [ - { - channel: Channels.WHATSAPP_INTERACTIVE, - to: '14152739164', - }, - ], - } as VerificationRequest, - ], - response: [ - 202, - { - request_id: 'cef1c266-d144-485e-8915-bd2d51b06776', - } as VerificationResponse, + baseUrl: 'https://api.nexmo.com', + reqHeaders: { + authorization: validateBearerAuth, + }, + client: new Verify2(keyAuth), + generator: false, + error: false, + requests: [ + [ + '/v2/verify', + 'POST', + { + brand: 'Vonage', + workflow: [ + { + channel: Channels.WHATSAPP_INTERACTIVE, + to: '14152739164', + }, + ], + } as VerificationRequest, + ], + ], + responses: [ + [ + 202, + { + request_id: 'cef1c266-d144-485e-8915-bd2d51b06776', + } as VerificationResponse, + ], ], - method: 'post', clientMethod: 'newRequest', parameters: [ { @@ -130,26 +166,36 @@ export default [ }, { label: 'start request using Voice', - request: [ - '/v2/verify', - 'POST', - { - brand: 'Vonage', - workflow: [ - { - channel: Channels.VOICE, - to: '14152739164', - }, - ], - } as VerificationRequest, - ], - response: [ - 202, - { - request_id: 'cef1c266-d144-485e-8915-bd2d51b06776', - } as VerificationResponse, + baseUrl: 'https://api.nexmo.com', + reqHeaders: { + authorization: validateBearerAuth, + }, + client: new Verify2(keyAuth), + generator: false, + error: false, + requests: [ + [ + '/v2/verify', + 'POST', + { + brand: 'Vonage', + workflow: [ + { + channel: Channels.VOICE, + to: '14152739164', + }, + ], + } as VerificationRequest, + ], + ], + responses: [ + [ + 202, + { + request_id: 'cef1c266-d144-485e-8915-bd2d51b06776', + } as VerificationResponse, + ], ], - method: 'post', clientMethod: 'newRequest', parameters: [ { @@ -168,26 +214,36 @@ export default [ }, { label: 'start request using Email', - request: [ - '/v2/verify', - 'POST', - { - brand: 'Vonage', - workflow: [ - { - channel: Channels.EMAIL, - to: 'alice@company.com', - }, - ], - } as VerificationRequest, - ], - response: [ - 202, - { - request_id: 'cef1c266-d144-485e-8915-bd2d51b06776', - } as VerificationResponse, + baseUrl: 'https://api.nexmo.com', + reqHeaders: { + authorization: validateBearerAuth, + }, + client: new Verify2(keyAuth), + generator: false, + error: false, + requests: [ + [ + '/v2/verify', + 'POST', + { + brand: 'Vonage', + workflow: [ + { + channel: Channels.EMAIL, + to: 'alice@company.com', + }, + ], + } as VerificationRequest, + ], + ], + responses: [ + [ + 202, + { + request_id: 'cef1c266-d144-485e-8915-bd2d51b06776', + } as VerificationResponse, + ], ], - method: 'post', clientMethod: 'newRequest', parameters: [ { @@ -206,26 +262,36 @@ export default [ }, { label: 'start request using silent auth', - request: [ - '/v2/verify', - 'POST', - { - brand: 'Vonage', - workflow: [ - { - channel: SilentAuthChannel.SILENT_AUTH, - to: '14152739164', - }, - ], - } as VerificationRequest, - ], - response: [ - 202, - { - request_id: 'cef1c266-d144-485e-8915-bd2d51b06776', - } as VerificationResponse, + baseUrl: 'https://api.nexmo.com', + reqHeaders: { + authorization: validateBearerAuth, + }, + client: new Verify2(keyAuth), + generator: false, + error: false, + requests: [ + [ + '/v2/verify', + 'POST', + { + brand: 'Vonage', + workflow: [ + { + channel: SilentAuthChannel.SILENT_AUTH, + to: '14152739164', + }, + ], + } as VerificationRequest, + ], + ], + responses: [ + [ + 202, + { + request_id: 'cef1c266-d144-485e-8915-bd2d51b06776', + } as VerificationResponse, + ], ], - method: 'post', clientMethod: 'newRequest', parameters: [ { @@ -244,34 +310,45 @@ export default [ }, { label: 'start request using SMS with all options', - request: [ - '/v2/verify', - 'POST', - { - brand: 'Vonage', - workflow: [ - { - channel: Channels.SMS, - to: '14152739164', - app_hash: 'C0FFEE', - entity_id: '1101407360000017170', - content_id: '1107158078772563946', - }, - ], - locale: VerifyLocale.EN_GB, - channel_timeout: 300, - client_ref: 'my-ref', - code_length: 4, - code: '4242', - } as VerificationRequest, - ], - response: [ - 202, - { - request_id: 'cef1c266-d144-485e-8915-bd2d51b06776', - } as VerificationResponse, + baseUrl: 'https://api.nexmo.com', + reqHeaders: { + authorization: validateBearerAuth, + }, + client: new Verify2(keyAuth), + generator: false, + error: false, + requests: [ + [ + '/v2/verify', + 'POST', + { + brand: 'Vonage', + workflow: [ + { + channel: Channels.SMS, + to: '14152739164', + app_hash: 'C0FFEE', + entity_id: '1101407360000017170', + content_id: '1107158078772563946', + }, + ], + locale: VerifyLocale.EN_GB, + channel_timeout: 300, + client_ref: 'my-ref', + code_length: 4, + code: '4242', + template_id: 'ce1b1f8b-0b9e-4f3b-9b2b-6b1d7e0c0c7f', + } as VerificationRequest, + ], + ], + responses: [ + [ + 202, + { + request_id: 'cef1c266-d144-485e-8915-bd2d51b06776', + } as VerificationResponse, + ], ], - method: 'post', clientMethod: 'newRequest', parameters: [ { @@ -290,6 +367,7 @@ export default [ clientRef: 'my-ref', codeLength: 4, code: '4242', + templateId: 'ce1b1f8b-0b9e-4f3b-9b2b-6b1d7e0c0c7f', } as VerificationRequestParams, ], expected: { @@ -298,31 +376,41 @@ export default [ }, { label: 'start request using WhatsApp with all options', - request: [ - '/v2/verify', - 'POST', - { - brand: 'Vonage', - workflow: [ - { - channel: Channels.WHATSAPP, - to: '14152739164', - }, - ], - locale: VerifyLocale.EN_GB, - channel_timeout: 300, - client_ref: 'my-ref', - code_length: 4, - code: '4242', - } as VerificationRequest, - ], - response: [ - 202, - { - request_id: 'cef1c266-d144-485e-8915-bd2d51b06776', - } as VerificationResponse, + baseUrl: 'https://api.nexmo.com', + reqHeaders: { + authorization: validateBearerAuth, + }, + client: new Verify2(keyAuth), + generator: false, + error: false, + requests: [ + [ + '/v2/verify', + 'POST', + { + brand: 'Vonage', + workflow: [ + { + channel: Channels.WHATSAPP, + to: '14152739164', + }, + ], + locale: VerifyLocale.EN_GB, + channel_timeout: 300, + client_ref: 'my-ref', + code_length: 4, + code: '4242', + } as VerificationRequest, + ], + ], + responses: [ + [ + 202, + { + request_id: 'cef1c266-d144-485e-8915-bd2d51b06776', + } as VerificationResponse, + ], ], - method: 'post', clientMethod: 'newRequest', parameters: [ { @@ -346,31 +434,41 @@ export default [ }, { label: 'start request using WhatsApp interactive with all options ', - request: [ - '/v2/verify', - 'POST', - { - brand: 'Vonage', - workflow: [ - { - channel: Channels.WHATSAPP_INTERACTIVE, - to: '14152739164', - }, - ], - locale: VerifyLocale.EN_GB, - channel_timeout: 300, - client_ref: 'my-ref', - code_length: 4, - code: '4242', - } as VerificationRequest, - ], - response: [ - 202, - { - request_id: 'cef1c266-d144-485e-8915-bd2d51b06776', - } as VerificationResponse, + baseUrl: 'https://api.nexmo.com', + reqHeaders: { + authorization: validateBearerAuth, + }, + client: new Verify2(keyAuth), + generator: false, + error: false, + requests: [ + [ + '/v2/verify', + 'POST', + { + brand: 'Vonage', + workflow: [ + { + channel: Channels.WHATSAPP_INTERACTIVE, + to: '14152739164', + }, + ], + locale: VerifyLocale.EN_GB, + channel_timeout: 300, + client_ref: 'my-ref', + code_length: 4, + code: '4242', + } as VerificationRequest, + ], + ], + responses: [ + [ + 202, + { + request_id: 'cef1c266-d144-485e-8915-bd2d51b06776', + } as VerificationResponse, + ], ], - method: 'post', clientMethod: 'newRequest', parameters: [ { @@ -394,31 +492,42 @@ export default [ }, { label: 'start request using Voice with all options ', - request: [ - '/v2/verify', - 'POST', - { - brand: 'Vonage', - workflow: [ - { - channel: Channels.VOICE, - to: '14152739164', - }, - ], - locale: VerifyLocale.EN_GB, - channel_timeout: 300, - client_ref: 'my-ref', - code_length: 4, - code: '4242', - } as VerificationRequest, - ], - response: [ - 202, - { - request_id: 'cef1c266-d144-485e-8915-bd2d51b06776', - } as VerificationResponse, + baseUrl: 'https://api.nexmo.com', + reqHeaders: { + authorization: validateBearerAuth, + }, + client: new Verify2(keyAuth), + generator: false, + error: false, + requests: [ + [ + '/v2/verify', + 'POST', + { + brand: 'Vonage', + workflow: [ + { + channel: Channels.VOICE, + to: '14152739164', + }, + ], + locale: VerifyLocale.EN_GB, + channel_timeout: 300, + client_ref: 'my-ref', + code_length: 4, + code: '4242', + template_id: 'ce1b1f8b-0b9e-4f3b-9b2b-6b1d7e0c0c7f', + } as VerificationRequest, + ], + ], + responses: [ + [ + 202, + { + request_id: 'cef1c266-d144-485e-8915-bd2d51b06776', + } as VerificationResponse, + ], ], - method: 'post', clientMethod: 'newRequest', parameters: [ { @@ -434,6 +543,7 @@ export default [ clientRef: 'my-ref', codeLength: 4, code: '4242', + templateId: 'ce1b1f8b-0b9e-4f3b-9b2b-6b1d7e0c0c7f', } as VerificationRequestParams, ], expected: { @@ -442,31 +552,41 @@ export default [ }, { label: 'start request using Email with all options ', - request: [ - '/v2/verify', - 'POST', - { - brand: 'Vonage', - workflow: [ - { - channel: Channels.EMAIL, - to: 'alice@company.com', - }, - ], - locale: VerifyLocale.EN_GB, - channel_timeout: 300, - client_ref: 'my-ref', - code_length: 4, - code: '4242', - } as VerificationRequest, - ], - response: [ - 202, - { - request_id: 'cef1c266-d144-485e-8915-bd2d51b06776', - } as VerificationResponse, + baseUrl: 'https://api.nexmo.com', + reqHeaders: { + authorization: validateBearerAuth, + }, + client: new Verify2(keyAuth), + generator: false, + error: false, + requests: [ + [ + '/v2/verify', + 'POST', + { + brand: 'Vonage', + workflow: [ + { + channel: Channels.EMAIL, + to: 'alice@company.com', + }, + ], + locale: VerifyLocale.EN_GB, + channel_timeout: 300, + client_ref: 'my-ref', + code_length: 4, + code: '4242', + } as VerificationRequest, + ], + ], + responses: [ + [ + 202, + { + request_id: 'cef1c266-d144-485e-8915-bd2d51b06776', + } as VerificationResponse, + ], ], - method: 'post', clientMethod: 'newRequest', parameters: [ { @@ -490,33 +610,43 @@ export default [ }, { label: 'start request using silent auth with all options', - request: [ - '/v2/verify', - 'POST', - { - brand: 'Vonage', - workflow: [ - { - channel: SilentAuthChannel.SILENT_AUTH, - to: '14152739164', - redirect_url: 'https://example.com/redirect', - }, - ], - locale: VerifyLocale.EN_GB, - channel_timeout: 300, - client_ref: 'my-ref', - code_length: 4, - code: '4242', - } as VerificationRequest, - ], - response: [ - 202, - { - request_id: 'cef1c266-d144-485e-8915-bd2d51b06776', - check_url: 'https://example.com/check', - } as VerificationResponse, + baseUrl: 'https://api.nexmo.com', + reqHeaders: { + authorization: validateBearerAuth, + }, + client: new Verify2(keyAuth), + generator: false, + error: false, + requests: [ + [ + '/v2/verify', + 'POST', + { + brand: 'Vonage', + workflow: [ + { + channel: SilentAuthChannel.SILENT_AUTH, + to: '14152739164', + redirect_url: 'https://example.com/redirect', + }, + ], + locale: VerifyLocale.EN_GB, + channel_timeout: 300, + client_ref: 'my-ref', + code_length: 4, + code: '4242', + } as VerificationRequest, + ], + ], + responses: [ + [ + 202, + { + request_id: 'cef1c266-d144-485e-8915-bd2d51b06776', + check_url: 'https://example.com/check', + } as VerificationResponse, + ], ], - method: 'post', clientMethod: 'newRequest', parameters: [ { @@ -542,30 +672,40 @@ export default [ }, { label: 'start request using multiple workflows', - request: [ - '/v2/verify', - 'POST', - { - brand: 'Vonage', - workflow: [ - { - channel: Channels.SMS, - to: '14152739164', - }, - { - channel: Channels.WHATSAPP, - to: '14152739164', - } as WhatsAppWorkflow, - ], - } as VerificationRequest, - ], - response: [ - 202, - { - request_id: 'cef1c266-d144-485e-8915-bd2d51b06776', - } as VerificationResponse, + baseUrl: 'https://api.nexmo.com', + reqHeaders: { + authorization: validateBearerAuth, + }, + client: new Verify2(keyAuth), + generator: false, + error: false, + requests: [ + [ + '/v2/verify', + 'POST', + { + brand: 'Vonage', + workflow: [ + { + channel: Channels.SMS, + to: '14152739164', + }, + { + channel: Channels.WHATSAPP, + to: '14152739164', + } as WhatsAppWorkflow, + ], + } as VerificationRequest, + ], + ], + responses: [ + [ + 202, + { + request_id: 'cef1c266-d144-485e-8915-bd2d51b06776', + } as VerificationResponse, + ], ], - method: 'post', clientMethod: 'newRequest', parameters: [ { @@ -588,27 +728,37 @@ export default [ }, { label: 'start request with fruad_check to true', - request: [ - '/v2/verify', - 'POST', - { - brand: 'Vonage', - fraud_check: true, - workflow: [ - { - channel: Channels.SMS, - to: '14152739164', - }, - ], - } as VerificationRequest, - ], - response: [ - 202, - { - request_id: 'cef1c266-d144-485e-8915-bd2d51b06776', - } as VerificationResponse, + baseUrl: 'https://api.nexmo.com', + reqHeaders: { + authorization: validateBearerAuth, + }, + client: new Verify2(keyAuth), + generator: false, + error: false, + requests: [ + [ + '/v2/verify', + 'POST', + { + brand: 'Vonage', + fraud_check: true, + workflow: [ + { + channel: Channels.SMS, + to: '14152739164', + }, + ], + } as VerificationRequest, + ], + ], + responses: [ + [ + 202, + { + request_id: 'cef1c266-d144-485e-8915-bd2d51b06776', + } as VerificationResponse, + ], ], - method: 'post', clientMethod: 'newRequest', parameters: [ { @@ -628,27 +778,37 @@ export default [ }, { label: 'start request with fruad_check to false', - request: [ - '/v2/verify', - 'POST', - { - brand: 'Vonage', - fraud_check: false, - workflow: [ - { - channel: Channels.SMS, - to: '14152739164', - }, - ], - } as VerificationRequest, - ], - response: [ - 202, - { - request_id: 'cef1c266-d144-485e-8915-bd2d51b06776', - } as VerificationResponse, + baseUrl: 'https://api.nexmo.com', + reqHeaders: { + authorization: validateBearerAuth, + }, + client: new Verify2(keyAuth), + generator: false, + error: false, + requests: [ + [ + '/v2/verify', + 'POST', + { + brand: 'Vonage', + fraud_check: false, + workflow: [ + { + channel: Channels.SMS, + to: '14152739164', + }, + ], + } as VerificationRequest, + ], + ], + responses: [ + [ + 202, + { + request_id: 'cef1c266-d144-485e-8915-bd2d51b06776', + } as VerificationResponse, + ], ], - method: 'post', clientMethod: 'newRequest', parameters: [ { @@ -668,30 +828,39 @@ export default [ }, { label: 'error when request returns conflict', - request: [ - '/v2/verify', - 'POST', - { - brand: 'Vonage', - workflow: [ - { - channel: Channels.SMS, - to: '14152739164', - }, - ], - } as VerificationRequest, + baseUrl: 'https://api.nexmo.com', + reqHeaders: { + authorization: validateBearerAuth, + }, + client: new Verify2(keyAuth), + generator: false, + requests: [ + [ + '/v2/verify', + 'POST', + { + brand: 'Vonage', + workflow: [ + { + channel: Channels.SMS, + to: '14152739164', + }, + ], + } as VerificationRequest, + ], + ], + responses: [ + [ + 422, + { + title: 'Conflict', + type: 'https://www.developer.vonage.com/api-errors/verify#conflict', + detail: 'Concurrent verifications to the same number are not allowed.', + instance: '738f9313-418a-4259-9b0d-6670f06fa82d', + request_id: '575a2054-aaaf-4405-994e-290be7b9a91f', + }, + ], ], - response: [ - 422, - { - title: 'Conflict', - type: 'https://www.developer.vonage.com/api-errors/verify#conflict', - detail: 'Concurrent verifications to the same number are not allowed.', - instance: '738f9313-418a-4259-9b0d-6670f06fa82d', - request_id: '575a2054-aaaf-4405-994e-290be7b9a91f', - }, - ], - method: 'post', clientMethod: 'newRequest', parameters: [ { @@ -706,4 +875,4 @@ export default [ ], error: 'Request failed with status code 422', }, -]; +] as SDKTestCase[]; diff --git a/packages/verify2/__tests__/verify2.test.ts b/packages/verify2/__tests__/verify2.test.ts index 56417c42..eec8bb43 100644 --- a/packages/verify2/__tests__/verify2.test.ts +++ b/packages/verify2/__tests__/verify2.test.ts @@ -1,39 +1,6 @@ -import { Verify2 } from '../lib'; import testDataSets from './__dataSets__'; import { VonageTest, - SDKTestCase, - TestResponse, - TestRequest, - TestTuple, - keyAuth, - validateBearerAuth, } from '../../../testHelpers'; -const applicationsTest = testDataSets.map((dataSet): TestTuple => { - const { label, tests } = dataSet; - - return { - name: label, - tests: tests.map((test): SDKTestCase => { - return { - label: test.label, - baseUrl: 'https://api.nexmo.com', - reqHeaders: { - authorization: validateBearerAuth, - }, - requests: [test.request] as TestRequest[], - responses: [test.response] as TestResponse[], - client: new Verify2(keyAuth), - clientMethod: test.clientMethod as keyof Verify2, - parameters: test.parameters, - generator: false, - error: 'error' in test ? String(test.error) : false, - expected: test.expected, - }; - }), - }; -}); - -VonageTest(applicationsTest); - +VonageTest(testDataSets); diff --git a/packages/verify2/lib/types/index.ts b/packages/verify2/lib/types/index.ts index a8c3f31a..115dece0 100644 --- a/packages/verify2/lib/types/index.ts +++ b/packages/verify2/lib/types/index.ts @@ -1,16 +1,12 @@ -export * from './checkCodeRequest'; -export * from './checkRequestResponse'; -export * from './emailWorkflow'; -export * from './eventCallback'; +export * from './params'; export * from './request'; +export * from './requests'; +export * from './responses'; +export * from './workflows'; +export * from './eventCallback'; export * from './requestStatusCallback'; -export * from './requestStatusCallbackWorkflow'; export * from './silentAuthCallback'; -export * from './silentAuthWorkflow'; -export * from './smsWorkflow'; -export * from './verifcationRequest'; -export * from './verifcationRequestParams'; -export * from './verificationResponse'; -export * from './voiceWorkflow'; -export * from './whatsAppInteractiveWorkflow'; -export * from './whatsAppWorkflow'; +export * from './template'; +export * from './templateFragment'; +export * from './templatePage'; +export * from './templateFragmentPage'; diff --git a/packages/verify2/lib/types/params/index.ts b/packages/verify2/lib/types/params/index.ts new file mode 100644 index 00000000..3be3a71b --- /dev/null +++ b/packages/verify2/lib/types/params/index.ts @@ -0,0 +1,3 @@ +export * from './listAllTemplateFragmentsParams'; +export * from './listAllTemplateParams'; +export * from './verifcationRequestParams'; diff --git a/packages/verify2/lib/types/params/listAllTemplateFragmentsParams.ts b/packages/verify2/lib/types/params/listAllTemplateFragmentsParams.ts new file mode 100644 index 00000000..e220b7da --- /dev/null +++ b/packages/verify2/lib/types/params/listAllTemplateFragmentsParams.ts @@ -0,0 +1,12 @@ +import { ListAllTemplatesParams } from './listAllTemplateParams'; + +/** + * Query parameters for listing all template fragments, including pagination. + */ +export type ListAllTemplateFragmentsParams = { + /** + * The template ID to retrieve fragments for. + * @example "22f571c1-f41a-4db2-bba7-f23a069200c1" + */ + templateId: string; + } & ListAllTemplatesParams; diff --git a/packages/verify2/lib/types/params/listAllTemplateParams.ts b/packages/verify2/lib/types/params/listAllTemplateParams.ts new file mode 100644 index 00000000..d0381d7d --- /dev/null +++ b/packages/verify2/lib/types/params/listAllTemplateParams.ts @@ -0,0 +1,16 @@ +/** + * Query parameters for listing all templates in the Verify API. + */ +export interface ListAllTemplatesParams { + /** + * The number of templates to return per page. + * @example 10 + */ + pageSize?: number; + + /** + * The page number to retrieve. + * @example 2 + */ + page?: number; +} diff --git a/packages/verify2/lib/types/verifcationRequestParams.ts b/packages/verify2/lib/types/params/verifcationRequestParams.ts similarity index 77% rename from packages/verify2/lib/types/verifcationRequestParams.ts rename to packages/verify2/lib/types/params/verifcationRequestParams.ts index c8291fea..9ce79f86 100644 --- a/packages/verify2/lib/types/verifcationRequestParams.ts +++ b/packages/verify2/lib/types/params/verifcationRequestParams.ts @@ -1,10 +1,12 @@ -import { VerifyLocale } from '../enums'; -import { EmailWorkflow } from './emailWorkflow'; -import { SMSWorkflow } from './smsWorkflow'; -import { SilentAuthWorkflow } from './silentAuthWorkflow'; -import { VoiceWorkflow } from './voiceWorkflow'; -import { WhatsAppInteractiveWorkflow } from './whatsAppInteractiveWorkflow'; -import { WhatsAppWorkflow } from './whatsAppWorkflow'; +import { VerifyLocale } from '../../enums'; +import { + EmailWorkflow, + SMSWorkflow, + SilentAuthWorkflow , + VoiceWorkflow, + WhatsAppInteractiveWorkflow , + WhatsAppWorkflow, +} from '../workflows'; /** * Represents parameters for creating a verification request for sending @@ -61,4 +63,12 @@ export type VerificationRequestParams = { * verification request. */ fraudCheck?: boolean; + + /** + * A custom template ID to use for the verification request. + * + * @remarks + * Only voice and sms workflows support custom templates. + */ + templateId?: string; }; diff --git a/packages/verify2/lib/types/requestStatusCallback.ts b/packages/verify2/lib/types/requestStatusCallback.ts index 94be68b5..cf320825 100644 --- a/packages/verify2/lib/types/requestStatusCallback.ts +++ b/packages/verify2/lib/types/requestStatusCallback.ts @@ -1,5 +1,5 @@ import { RequestStatus } from '../enums'; -import { RequestStatusCallbackWorkflow } from './requestStatusCallbackWorkflow'; +import { RequestStatusCallbackWorkflow } from './workflows/requestStatusCallbackWorkflow'; /** * Represents a callback received for the status update of a diff --git a/packages/verify2/lib/types/checkCodeRequest.ts b/packages/verify2/lib/types/requests/checkCodeRequest.ts similarity index 100% rename from packages/verify2/lib/types/checkCodeRequest.ts rename to packages/verify2/lib/types/requests/checkCodeRequest.ts diff --git a/packages/verify2/lib/types/requests/createTemplateFragmentRequest.ts b/packages/verify2/lib/types/requests/createTemplateFragmentRequest.ts new file mode 100644 index 00000000..13dc8878 --- /dev/null +++ b/packages/verify2/lib/types/requests/createTemplateFragmentRequest.ts @@ -0,0 +1,22 @@ +/** + * Represents the request body for creating a template fragment. + */ +export type CreateTemplateFragmentRequest = { + /** + * The communication channel for the fragment (e.g., sms, voice, email). + * @example "sms" + */ + channel: 'sms' | 'voice'; + + /** + * Locale in IETF BCP 47 format. + * @example "en-us" + */ + locale: string; + + /** + * Text content of the template fragment. + * @example "Text content of the template. May contain 4 reserved variables: `${code}`, `${brand}`, `${time-limit}` and `${time-limit-unit}`" + */ + text: string; +}; diff --git a/packages/verify2/lib/types/requests/index.ts b/packages/verify2/lib/types/requests/index.ts new file mode 100644 index 00000000..081262c1 --- /dev/null +++ b/packages/verify2/lib/types/requests/index.ts @@ -0,0 +1,3 @@ +export * from './checkCodeRequest'; +export * from './createTemplateFragmentRequest'; +export * from './verifcationRequest'; diff --git a/packages/verify2/lib/types/verifcationRequest.ts b/packages/verify2/lib/types/requests/verifcationRequest.ts similarity index 80% rename from packages/verify2/lib/types/verifcationRequest.ts rename to packages/verify2/lib/types/requests/verifcationRequest.ts index 57459ebd..057b8179 100644 --- a/packages/verify2/lib/types/verifcationRequest.ts +++ b/packages/verify2/lib/types/requests/verifcationRequest.ts @@ -1,10 +1,12 @@ -import { VerifyLocale } from '../enums'; -import { EmailWorkflow } from './emailWorkflow'; -import { SMSWorkflow } from './smsWorkflow'; -import { SilentAuthWorkflow } from './silentAuthWorkflow'; -import { VoiceWorkflow } from './voiceWorkflow'; -import { WhatsAppInteractiveWorkflow } from './whatsAppInteractiveWorkflow'; -import { WhatsAppWorkflow } from './whatsAppWorkflow'; +import { VerifyLocale } from '../../enums'; +import { + EmailWorkflow, + SMSWorkflow, + SilentAuthWorkflow, + VoiceWorkflow, + WhatsAppInteractiveWorkflow, + WhatsAppWorkflow +} from '../workflows'; export type SMSWorkflowRequest = { app_hash?: string; diff --git a/packages/verify2/lib/types/checkRequestResponse.ts b/packages/verify2/lib/types/responses/checkRequestResponse.ts similarity index 100% rename from packages/verify2/lib/types/checkRequestResponse.ts rename to packages/verify2/lib/types/responses/checkRequestResponse.ts diff --git a/packages/verify2/lib/types/responses/index.ts b/packages/verify2/lib/types/responses/index.ts new file mode 100644 index 00000000..55e86c5f --- /dev/null +++ b/packages/verify2/lib/types/responses/index.ts @@ -0,0 +1,6 @@ +export * from './checkRequestResponse'; +export * from './listAllTemplatesResponse'; +export * from './listAllTemplateFragmentsResponse'; +export * from './templateFragmentResponse'; +export * from './templateResponse'; +export * from './verificationResponse'; diff --git a/packages/verify2/lib/types/responses/listAllTemplateFragmentsResponse.ts b/packages/verify2/lib/types/responses/listAllTemplateFragmentsResponse.ts new file mode 100644 index 00000000..4ce0ee24 --- /dev/null +++ b/packages/verify2/lib/types/responses/listAllTemplateFragmentsResponse.ts @@ -0,0 +1,43 @@ +import { APILinks } from '@vonage/server-client'; +import { TemplateFragmentResponse } from './templateFragmentResponse'; + +/** + * The response when listing all template fragments, including pagination. + */ +export type ListAllTemplateFragmentsResponse = { + /** + * The number of fragments returned in the current page. + * @example 10 + */ + page_size: number; + + /** + * The current page number. + * @example 2 + */ + page: number; + + /** + * Total number of pages available. + * @example 5 + */ + total_pages: number; + + /** + * Total number of template fragments available. + * @example 25 + */ + total_items: number; + + /** + * The list of template fragments. + */ + _embedded: { + template_fragments: TemplateFragmentResponse[]; + }; + + /** + * Pagination links in HAL format. + */ + _links: APILinks['_links']; +}; diff --git a/packages/verify2/lib/types/responses/listAllTemplatesResponse.ts b/packages/verify2/lib/types/responses/listAllTemplatesResponse.ts new file mode 100644 index 00000000..789a5968 --- /dev/null +++ b/packages/verify2/lib/types/responses/listAllTemplatesResponse.ts @@ -0,0 +1,49 @@ +import { TemplateResponse } from './templateResponse'; +import { Template } from '../template'; +import { APILinks } from '@vonage/server-client'; + +/** + * The response when listing all templates, including pagination. + */ +export type ListAllTemplatesResponse = { + /** + * The number of templates returned in the current page. + * @example 1 + */ + page_size: number; + + /** + * The current page number. + * @example 2 + */ + page: number; + + /** + * Total number of pages available. + * @example 10 + */ + total_pages: number; + + /** + * Total number of templates available. + * @example 25 + */ + total_items: number; + + /** + * The list of templates. + */ + _embedded: { + templates: TemplateResponse[]; + }; + + /** + * Pagination links in HAL format. + */ + _links: APILinks['_links']; + + /** + * The list of templates transformed into the SDK format. + */ + templates: Template[]; +}; diff --git a/packages/verify2/lib/types/responses/templateFragmentResponse.ts b/packages/verify2/lib/types/responses/templateFragmentResponse.ts new file mode 100644 index 00000000..b0cdb9d8 --- /dev/null +++ b/packages/verify2/lib/types/responses/templateFragmentResponse.ts @@ -0,0 +1,57 @@ +import { APILink } from '@vonage/server-client'; + +/** + * Represents the response when retrieving a template fragment. + */ +export type TemplateFragmentResponse = { + /** + * Unique identifier for the template fragment. + * @example "c70f446e-997a-4313-a081-60a02a31dc19" + */ + template_fragment_id: string; + + /** + * The communication channel for the fragment (e.g., sms, voice, email). + * @example "sms" + */ + channel: 'sms' | 'voice'; + + /** + * Locale in IETF BCP 47 format. + * @example "en-us" + */ + locale: string; + + /** + * Text content of the template fragment. + * @example "Text content of the template. May contain 4 reserved variables: `${code}`, `${brand}`, `${time-limit}` and `${time-limit-unit}`" + */ + text: string; + + /** + * The date when the template fragment was last updated, in ISO 8601 format. + * @example "2023-08-30T15:20:15.17865735Z" + */ + date_updated: string; + + /** + * The date when the template fragment was created, in ISO 8601 format. + * @example "2021-08-30T20:12:15.17865735Z" + */ + date_created: string; + + /** + * HAL format links related to the template fragment. + */ + _links: { + /** + * A link to the template fragment itself. + */ + self: APILink; + + /** + * A link to the parent template this fragment belongs to. + */ + template: APILink; + }; +}; diff --git a/packages/verify2/lib/types/responses/templateResponse.ts b/packages/verify2/lib/types/responses/templateResponse.ts new file mode 100644 index 00000000..284fe249 --- /dev/null +++ b/packages/verify2/lib/types/responses/templateResponse.ts @@ -0,0 +1,40 @@ +import { APILink } from '@vonage/server-client'; + +/** + * Represents a single template in the Verify API response. + */ +export type TemplateResponse = { + /** + * Unique identifier for the template. + * @example "8f35a1a7-eb2f-4552-8fdf-fffdaee41bc9" + */ + template_id: string; + + /** + * The name of the template. + * @example "my-template" + */ + name: string; + + /** + * Indicates whether this is the default template. + * @example true + */ + is_default: boolean; + + /** + * HAL format links related to the template. + */ + _links: { + /** + * A link to the template itself. + */ + self: APILink; + + /** + * A link to the template fragments associated with this template. + */ + fragments: APILink; + }; +} + diff --git a/packages/verify2/lib/types/verificationResponse.ts b/packages/verify2/lib/types/responses/verificationResponse.ts similarity index 100% rename from packages/verify2/lib/types/verificationResponse.ts rename to packages/verify2/lib/types/responses/verificationResponse.ts diff --git a/packages/verify2/lib/types/template.ts b/packages/verify2/lib/types/template.ts new file mode 100644 index 00000000..00fc2fbe --- /dev/null +++ b/packages/verify2/lib/types/template.ts @@ -0,0 +1,22 @@ +/** + * Represents a value object for a template, converted to camelCase, without _links. + */ +export type Template = { + /** + * Unique identifier for the template. + * @example "8f35a1a7-eb2f-4552-8fdf-fffdaee41bc9" + */ + templateId: string; + + /** + * The name of the template. + * @example "my-template" + */ + name: string; + + /** + * Indicates whether this is the default template. + * @example true + */ + isDefault: boolean; +}; diff --git a/packages/verify2/lib/types/templateFragment.ts b/packages/verify2/lib/types/templateFragment.ts new file mode 100644 index 00000000..d5a2fce7 --- /dev/null +++ b/packages/verify2/lib/types/templateFragment.ts @@ -0,0 +1,40 @@ +/** + * Represents a template fragment + */ +export type TemplateFragment = { + /** + * Unique identifier for the template fragment. + * @example "c70f446e-997a-4313-a081-60a02a31dc19" + */ + templateFragmentId: string; + + /** + * The communication channel for the fragment (e.g., sms, voice). + * @example "sms" + */ + channel: 'sms' | 'voice'; + + /** + * Locale in IETF BCP 47 format. + * @example "en-us" + */ + locale: string; + + /** + * Text content of the template fragment. + * @example "Text content of the template. May contain 4 reserved variables: `${code}`, `${brand}`, `${time-limit}` and `${time-limit-unit}`" + */ + text: string; + + /** + * The date when the template fragment was last updated, in ISO 8601 format. + * @example "2023-08-30T15:20:15.17865735Z" + */ + dateUpdated: string; + + /** + * The date when the template fragment was created, in ISO 8601 format. + * @example "2021-08-30T20:12:15.17865735Z" + */ + dateCreated: string; +}; diff --git a/packages/verify2/lib/types/templateFragmentPage.ts b/packages/verify2/lib/types/templateFragmentPage.ts new file mode 100644 index 00000000..d3bf38b0 --- /dev/null +++ b/packages/verify2/lib/types/templateFragmentPage.ts @@ -0,0 +1,41 @@ +import { APILink } from '@vonage/server-client'; +import { TemplateFragment } from './templateFragment'; + +/** + * Value object for a page of template fragments, with camelCase properties. + */ +export type TemplateFragmentPage = { + /** + * The number of fragments returned in the current page. + * @example 10 + */ + pageSize: number; + + /** + * The current page number. + * @example 2 + */ + page: number; + + /** + * Total number of pages available. + * @example 5 + */ + totalPages: number; + + /** + * Total number of template fragments available. + * @example 25 + */ + totalItems: number; + + /** + * The list of template fragments. + */ + fragments: TemplateFragment[]; + + /** + * The set of links for the current page. + */ + links?: Record; +}; diff --git a/packages/verify2/lib/types/templatePage.ts b/packages/verify2/lib/types/templatePage.ts new file mode 100644 index 00000000..2cf01744 --- /dev/null +++ b/packages/verify2/lib/types/templatePage.ts @@ -0,0 +1,41 @@ +import { APILink } from '@vonage/server-client'; +import { Template } from './template'; + +/** + * Value object for a page of templates with camelCase properties. + */ +export type TemplatePage = { + /** + * The number of templates returned in the current page. + * @example 10 + */ + pageSize: number; + + /** + * The current page number. + * @example 2 + */ + page: number; + + /** + * Total number of pages available. + * @example 5 + */ + totalPages: number; + + /** + * Total number of template available. + * @example 25 + */ + totalItems: number; + + /** + * The list of templates. + */ + templates: Template[]; + + /** + * The set of links for the current page. + */ + links?: Record; +}; diff --git a/packages/verify2/lib/types/emailWorkflow.ts b/packages/verify2/lib/types/workflows/emailWorkflow.ts similarity index 91% rename from packages/verify2/lib/types/emailWorkflow.ts rename to packages/verify2/lib/types/workflows/emailWorkflow.ts index a10023c1..98aa26e7 100644 --- a/packages/verify2/lib/types/emailWorkflow.ts +++ b/packages/verify2/lib/types/workflows/emailWorkflow.ts @@ -1,4 +1,4 @@ -import { Channels } from '../enums'; +import { Channels } from '../../enums'; /** * Represents a workflow for sending a verification code via email. diff --git a/packages/verify2/lib/types/workflows/index.ts b/packages/verify2/lib/types/workflows/index.ts new file mode 100644 index 00000000..4b17f219 --- /dev/null +++ b/packages/verify2/lib/types/workflows/index.ts @@ -0,0 +1,7 @@ +export * from './emailWorkflow'; +export * from './requestStatusCallbackWorkflow'; +export * from './silentAuthWorkflow'; +export * from './smsWorkflow'; +export * from './voiceWorkflow'; +export * from './whatsAppInteractiveWorkflow'; +export * from './whatsAppWorkflow'; diff --git a/packages/verify2/lib/types/requestStatusCallbackWorkflow.ts b/packages/verify2/lib/types/workflows/requestStatusCallbackWorkflow.ts similarity index 88% rename from packages/verify2/lib/types/requestStatusCallbackWorkflow.ts rename to packages/verify2/lib/types/workflows/requestStatusCallbackWorkflow.ts index 7195e660..25a43e51 100644 --- a/packages/verify2/lib/types/requestStatusCallbackWorkflow.ts +++ b/packages/verify2/lib/types/workflows/requestStatusCallbackWorkflow.ts @@ -1,4 +1,4 @@ -import { Channels, RequestWorkflowStatus } from '../enums'; +import { Channels, RequestWorkflowStatus } from '../../enums'; /** * Represents a workflow step within a verification request's status callback. diff --git a/packages/verify2/lib/types/silentAuthWorkflow.ts b/packages/verify2/lib/types/workflows/silentAuthWorkflow.ts similarity index 88% rename from packages/verify2/lib/types/silentAuthWorkflow.ts rename to packages/verify2/lib/types/workflows/silentAuthWorkflow.ts index 953cc672..f3d13bb0 100644 --- a/packages/verify2/lib/types/silentAuthWorkflow.ts +++ b/packages/verify2/lib/types/workflows/silentAuthWorkflow.ts @@ -1,4 +1,4 @@ -import { SilentAuthChannel } from '../enums'; +import { SilentAuthChannel } from '../../enums'; /** * Represents a workflow for Silent Authentication. diff --git a/packages/verify2/lib/types/smsWorkflow.ts b/packages/verify2/lib/types/workflows/smsWorkflow.ts similarity index 96% rename from packages/verify2/lib/types/smsWorkflow.ts rename to packages/verify2/lib/types/workflows/smsWorkflow.ts index e5c3c2b3..ddb6b454 100644 --- a/packages/verify2/lib/types/smsWorkflow.ts +++ b/packages/verify2/lib/types/workflows/smsWorkflow.ts @@ -1,4 +1,4 @@ -import { Channels } from '../enums'; +import { Channels } from '../../enums'; /** * Represents a workflow for sending a verification code via SMS. diff --git a/packages/verify2/lib/types/voiceWorkflow.ts b/packages/verify2/lib/types/workflows/voiceWorkflow.ts similarity index 89% rename from packages/verify2/lib/types/voiceWorkflow.ts rename to packages/verify2/lib/types/workflows/voiceWorkflow.ts index 31024af6..edd809a6 100644 --- a/packages/verify2/lib/types/voiceWorkflow.ts +++ b/packages/verify2/lib/types/workflows/voiceWorkflow.ts @@ -1,4 +1,4 @@ -import { Channels } from '../enums'; +import { Channels } from '../../enums'; /** * Represents a workflow for sending a verification code via voice call. diff --git a/packages/verify2/lib/types/whatsAppInteractiveWorkflow.ts b/packages/verify2/lib/types/workflows/whatsAppInteractiveWorkflow.ts similarity index 90% rename from packages/verify2/lib/types/whatsAppInteractiveWorkflow.ts rename to packages/verify2/lib/types/workflows/whatsAppInteractiveWorkflow.ts index 40fc707a..d6cd70d2 100644 --- a/packages/verify2/lib/types/whatsAppInteractiveWorkflow.ts +++ b/packages/verify2/lib/types/workflows/whatsAppInteractiveWorkflow.ts @@ -1,4 +1,4 @@ -import { Channels } from '../enums'; +import { Channels } from '../../enums'; /** * Represents a workflow for sending a verification code via interactive diff --git a/packages/verify2/lib/types/whatsAppWorkflow.ts b/packages/verify2/lib/types/workflows/whatsAppWorkflow.ts similarity index 92% rename from packages/verify2/lib/types/whatsAppWorkflow.ts rename to packages/verify2/lib/types/workflows/whatsAppWorkflow.ts index 0d2f7bfe..5e57bd39 100644 --- a/packages/verify2/lib/types/whatsAppWorkflow.ts +++ b/packages/verify2/lib/types/workflows/whatsAppWorkflow.ts @@ -1,4 +1,4 @@ -import { Channels } from '../enums'; +import { Channels } from '../../enums'; /** * Represents a workflow for sending a verification code via WhatsApp. diff --git a/packages/verify2/lib/verify2.ts b/packages/verify2/lib/verify2.ts index 4d61603a..f42fcdd2 100644 --- a/packages/verify2/lib/verify2.ts +++ b/packages/verify2/lib/verify2.ts @@ -1,9 +1,19 @@ import { AuthenticationType, Client } from '@vonage/server-client'; import { + CheckRequestResponse, + ListAllTemplateFragmentsParams, + ListAllTemplateFragmentsResponse, + ListAllTemplatesParams, + ListAllTemplatesResponse, Request, + Template, + TemplateFragmentPage, + TemplateFragmentResponse, + TemplateFragment, + TemplatePage, + TemplateResponse, VerificationRequestParams, VerificationResponse, - CheckRequestResponse, } from './types'; /** @@ -22,7 +32,7 @@ export class Verify2 extends Client { * verification request. * @return {Request} A `Request` object containing the request ID. */ - public async newRequest(params: VerificationRequestParams): Promise { + async newRequest(params: VerificationRequestParams): Promise { const resp = await this.sendPostRequest( `${this.config.apiHost}/v2/verify`, Client.transformers.snakeCaseObjectKeys(params, true), @@ -40,7 +50,7 @@ export class Verify2 extends Client { * @param {string} code - The verification code to check. * @return {string} The status of the verification code check. */ - public async checkCode(requestId: string, code: string): Promise { + async checkCode(requestId: string, code: string): Promise { const resp = await this.sendPostRequest( `${this.config.apiHost}/v2/verify/${requestId}`, { @@ -56,7 +66,7 @@ export class Verify2 extends Client { * @param {string} requestId - The ID of the verification request to cancel. * @return {boolean} `true` if the cancellation was successful. */ - public async cancel(requestId: string): Promise { + async cancel(requestId: string): Promise { try { await this.sendDeleteRequest( `${this.config.apiHost}/v2/verify/${requestId}`, @@ -68,4 +78,401 @@ export class Verify2 extends Client { return false; } } + + /** + * Generator function to list all templates across multiple pages. + * + * @remarks + * This will continue calling the API to retrieve all templates until there are no more pages left. + * The function yields each template in camelCase format. + * + * @param {ListAllTemplatesParams} [params={}] - Optional filter parameters, including pagination. + * @yields {Template} - Yields each template object in camelCase format. + * + * @example + * List all templates using pagination: + * ```ts + * for await (const template of templateClient.listAllTemplates({ pageSize: 5 })) { + * console.log(template.name); + * } + * ``` + * + * @example + * List all templates without pagination: + * ```ts + * for await (const template of templateClient.listAllTemplates()) { + * console.log(template.name); + * } + * ``` + */ + async *listAllTemplates( + params: ListAllTemplatesParams = {}, + ): AsyncGenerator { + let next = null; + params.page = params?.page || 1; + do { + const resp = await this.getTemplatePage(params); + + yield* resp.templates || []; + next = resp.links?.next; + params.page++; + } while (next); + } + + /** + * Retrieves a single page of templates based on the provided pagination parameters. + * + * @param {ListAllTemplatesParams} params - The filter parameters for pagination (e.g., page number, page size). + * @return {Promise} - A promise resolving to a page of templates. + * + * @example + * Get a single page of templates: + * + * ```ts + * const templatePage = await templateClient.getTemplatePage({ + * page: 1, + * pageSize: 10 + * }); + * + * templatePage.templates.forEach(template => { + * console.log(template.name); + * }); + * ``` + */ + async getTemplatePage( + params: ListAllTemplatesParams = {}, + ): Promise { + const resp = await this.sendGetRequest( + `${this.config.apiHost}/v2/verify/templates`, + { + ...(params.page ? {page: params.page} : {}), + ...(params.pageSize? {page_size: params.pageSize} : {}), + } + ); + + const templates: Template[] = (resp.data._embedded?.templates || []).map( + (template: TemplateResponse) => Client.transformers.camelCaseObjectKeys(template) as Template + ); + + return { + pageSize: resp.data.page_size, + page: resp.data.page, + totalPages: resp.data.total_pages, + totalItems: resp.data.total_items, + templates: templates, + links: resp.data._links, + }; + } + + /** + * Creates a new template with the provided details. + * + * @param {Template} template - The template details to be created. + * @return {Promise