diff --git a/__tests__/services/zendesk-api-service.spec.ts b/__tests__/services/zendesk-api-service.spec.ts index 9f106a7..ccf51b4 100644 --- a/__tests__/services/zendesk-api-service.spec.ts +++ b/__tests__/services/zendesk-api-service.spec.ts @@ -594,4 +594,107 @@ describe("ZendeskService", () => { expect(result).toEqual(zisIntegration); }); }); + + describe("jobSpecs", () => { + const jobSpec = { + description: "Test Job", + event_source: "source", + event_type: "type", + flow_name: "flow", + installed: true, + integration: "integration", + name: "jobName", + uuid: "uuid" + }; + + it("should fetchs jobs and call Zendesk API multiple times if has more is true", async () => { + requestMock + .mockResolvedValueOnce({ + job_specs: [jobSpec], + meta: { + has_more: true, + after: "1" + } + }) + .mockResolvedValueOnce({ + job_specs: [jobSpec], + meta: { + has_more: false + } + }); + + const data = await service.fetchZisJobSpecs("integrationName"); + + expect(requestMock).toHaveBeenNthCalledWith(1, { + url: "/api/services/zis/registry/integrationName/job_specs", + type: "GET", + data: { + page: { + size: "100" + } + } + }); + expect(requestMock).toHaveBeenNthCalledWith(2, { + url: "/api/services/zis/registry/integrationName/job_specs", + type: "GET", + data: { + page: { + after: "1", + size: "100" + } + } + }); + expect(requestMock).toHaveBeenCalledTimes(2); + expect(data).toHaveLength(2); + }); + + it("should fetchs jobs with correct data", async () => { + requestMock.mockResolvedValueOnce({ + job_specs: [jobSpec], + meta: { + has_more: false + } + }); + + const data = await service.fetchZisJobSpecs("integrationName", { + page: { + size: "5" + } + }); + + expect(requestMock).toHaveBeenNthCalledWith(1, { + url: "/api/services/zis/registry/integrationName/job_specs", + type: "GET", + data: { + page: { + size: "5" + } + } + }); + expect(requestMock).toHaveBeenCalledTimes(1); + expect(data).toHaveLength(1); + }); + + it("should create a job spec with correct data", async () => { + await service.createZisJobSpec("job_name_test"); + + expect(requestMock).toHaveBeenNthCalledWith(1, { + url: "/api/services/zis/registry/job_specs/install?job_spec_name=job_name_test", + type: "POST", + contentType: "application/json" + }); + expect(requestMock).toHaveBeenCalledTimes(1); + }); + + it("should delete a job spec with correct data", async () => { + await service.deleteZisJobSpec("job_name_test"); + + expect(requestMock).toHaveBeenNthCalledWith(1, { + url: "/api/services/zis/registry/job_specs/install?job_spec_name=job_name_test", + type: "DELETE", + contentType: "application/json" + }); + expect(requestMock).toHaveBeenCalledTimes(1); + }); + }); }); diff --git a/package.json b/package.json index b97ba40..8f0119f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@zendesk/zaf-toolbox", - "version": "0.6.0", + "version": "0.7.0", "description": "A toolbox for ZAF application built with 🩷 by Zendesk Labs", "main": "lib/src/index.js", "types": "lib/src/index.d.ts", diff --git a/src/models/custom-objects.ts b/src/models/custom-objects.ts index 986ef17..086e4b0 100644 --- a/src/models/custom-objects.ts +++ b/src/models/custom-objects.ts @@ -110,7 +110,7 @@ export enum ListCutomObjectRecordsSortingOptions { MINUS_UPDATED_AT = "-updated_at" } -export interface IListCustomObjectRecordsFilter { +export interface IListFilter { filter?: { /** * Comma separated list of external ids of records @@ -141,7 +141,7 @@ export interface IListCustomObjectRecordsFilter { sort?: ListCutomObjectRecordsSortingOptions; } -export interface ISearchCustomObjectRecordsFilter extends IListCustomObjectRecordsFilter { +export interface ISearchCustomObjectRecordsFilter extends IListFilter { query: string; } diff --git a/src/models/zendesk-integration-services.ts b/src/models/zendesk-integration-services.ts index 2282295..f2a973e 100644 --- a/src/models/zendesk-integration-services.ts +++ b/src/models/zendesk-integration-services.ts @@ -14,3 +14,22 @@ export interface IZisIntegration { export interface IZisIntegrationResponse { integrations: IZisIntegration[]; } + +export interface IZisJobspec { + description: string; + event_source: string; + event_type: string; + flow_name: string; + installed: boolean; + integration: string; + name: string; + uuid: string; +} +export interface IZisJobspecsResponse { + job_specs: IZisJobspec[]; + meta: { + after: string; + before: string; + has_more: boolean; + }; +} diff --git a/src/services/custom-object-service.ts b/src/services/custom-object-service.ts index 207f66f..ce308e5 100644 --- a/src/services/custom-object-service.ts +++ b/src/services/custom-object-service.ts @@ -7,7 +7,7 @@ import { IGetCustomObjectRecordsResponse, IListCustomObjectsResponse, ICreateCustomObjectRecordBody, - IListCustomObjectRecordsFilter, + IListFilter, IListCustomObjectRecordsResponse, ICustomObjectRecord, ListCutomObjectRecordsSortingOptions, @@ -124,7 +124,7 @@ export class CustomObjectService { */ public async listCustomObjectRecords( key: string, - data?: IListCustomObjectRecordsFilter + data?: IListFilter ): Promise[]> { const { custom_object_records } = await this.client.request>({ url: `/api/v2/custom_objects/${key}/records`, @@ -145,7 +145,7 @@ export class CustomObjectService { ): Promise[]> { return this.fetchAllPaginatedRecords(`/api/v2/custom_objects/${key}/records`, { sort: sortOptions?.sort - } as IListCustomObjectRecordsFilter); + } as IListFilter); } /** @@ -263,7 +263,7 @@ export class CustomObjectService { */ private async fetchAllPaginatedRecords( url: string, - initialData: IListCustomObjectRecordsFilter + initialData: IListFilter ): Promise[]> { let hasMore = true; let data = initialData; @@ -290,7 +290,7 @@ export class CustomObjectService { sort: initialData.sort } : undefined) - } as IListCustomObjectRecordsFilter; + } as IListFilter; } } while (hasMore); diff --git a/src/services/zendesk-api-service.ts b/src/services/zendesk-api-service.ts index f9ad6ef..3dfc877 100644 --- a/src/services/zendesk-api-service.ts +++ b/src/services/zendesk-api-service.ts @@ -25,9 +25,15 @@ import { IZendeskResponse, Line, IMessage, - IMessagesResults + IMessagesResults, + IListFilter } from "@models/index"; -import { IZisIntegration, IZisIntegrationResponse } from "@models/zendesk-integration-services"; +import { + IZisIntegration, + IZisIntegrationResponse, + IZisJobspec, + IZisJobspecsResponse +} from "@models/zendesk-integration-services"; import { convertContentMessageToHtml } from "@utils/convert-content-message-to-html"; import { getFromClient } from "@utils/get-from-client"; import { Client } from "@zendesk/sell-zaf-app-toolbox"; @@ -325,4 +331,71 @@ export class ZendeskApiService { }) }); } + + /** + * Fetch Zis job specs from an integration + * + * @param {string} integrationName Name of the Zis integration + * @returns {Promise} List of Zis job specs + */ + public async fetchZisJobSpecs(integrationName: string, filterTheList?: IListFilter): Promise { + let hasMore = true; + const numberOfJobSpecs = "100"; // Maximum number of job specs per page + let jobspecs: IZisJobspec[] = []; + let data: IListFilter = filterTheList ?? { + page: { + size: numberOfJobSpecs + } + }; + + do { + const response = await this.client.request({ + url: `/api/services/zis/registry/${integrationName}/job_specs`, + type: "GET", + data + }); + + jobspecs = [...jobspecs, ...response.job_specs]; + + hasMore = response.meta.has_more; + if (hasMore) { + data = { + page: { + after: response.meta.after, + size: numberOfJobSpecs + } + }; + } + } while (hasMore); + + return jobspecs; + } + + /** + * Install a Zis job spec for an integration + * + * @param {string} jobSpecName Name of the Zis job spec to install + * @returns {Promise} Resolves when the job spec is installed + */ + public async createZisJobSpec(jobSpecName: string): Promise { + return await this.client.request({ + url: `/api/services/zis/registry/job_specs/install?job_spec_name=${encodeURIComponent(jobSpecName)}`, + contentType: "application/json", + type: "POST" + }); + } + + /** + * Delete a Zis job spec for an integration + * + * @param {string} jobSpecName Name of the Zis job spec to delete + * @returns {Promise} Resolves when the job spec is deleted + */ + public async deleteZisJobSpec(jobSpecName: string): Promise { + return await this.client.request({ + url: `/api/services/zis/registry/job_specs/install?job_spec_name=${encodeURIComponent(jobSpecName)}`, + contentType: "application/json", + type: "DELETE" + }); + } }