Skip to content

Commit 20d842d

Browse files
authored
Merge pull request #102 from zendesk/victor.piolin/search-for-custom-object-record
feat(custom-object-service): Add search records method for Custom object service
2 parents 726324f + 0c408da commit 20d842d

4 files changed

Lines changed: 130 additions & 26 deletions

File tree

__tests__/services/custom-objects.spec.ts

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -326,5 +326,66 @@ describe("CustomObjectService", () => {
326326
});
327327
expect(requestMock).toHaveBeenCalledTimes(1);
328328
});
329+
330+
it("should call Zendesk API with search query", async () => {
331+
requestMock.mockResolvedValueOnce({
332+
custom_object_records: [customObjectRecord],
333+
meta: {
334+
has_more: false
335+
}
336+
});
337+
338+
await service.searchRecords("foo", "search_query");
339+
340+
expect(requestMock).toHaveBeenNthCalledWith(1, {
341+
url: `/api/v2/custom_objects/foo/records/search`,
342+
type: "GET",
343+
contentType: "application/json",
344+
data: {
345+
query: "search_query"
346+
}
347+
});
348+
expect(requestMock).toHaveBeenCalledTimes(1);
349+
});
350+
351+
it("should keep sort threw all pages ", async () => {
352+
requestMock
353+
.mockResolvedValueOnce({
354+
custom_object_records: [customObjectRecord],
355+
meta: {
356+
has_more: true,
357+
after_cursor: "1"
358+
}
359+
})
360+
.mockResolvedValueOnce({
361+
custom_object_records: [customObjectRecord],
362+
meta: {
363+
has_more: false
364+
}
365+
});
366+
367+
await service.retrieveAllCustomObjectRecords("foo", { sort: ListCutomObjectRecordsSortingOptions.ID });
368+
369+
expect(requestMock).toHaveBeenNthCalledWith(1, {
370+
url: `/api/v2/custom_objects/foo/records`,
371+
type: "GET",
372+
contentType: "application/json",
373+
data: {
374+
sort: "id"
375+
}
376+
});
377+
expect(requestMock).toHaveBeenNthCalledWith(2, {
378+
url: `/api/v2/custom_objects/foo/records`,
379+
type: "GET",
380+
contentType: "application/json",
381+
data: {
382+
page: {
383+
after: "1"
384+
},
385+
sort: "id"
386+
}
387+
});
388+
expect(requestMock).toHaveBeenCalledTimes(2);
389+
});
329390
});
330391
});

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@zendesk/zaf-toolbox",
3-
"version": "0.2.9",
3+
"version": "0.2.10",
44
"description": "A toolbox for ZAF application built with 🩷 by Zendesk Labs",
55
"main": "lib/src/index.js",
66
"types": "lib/src/index.d.ts",

src/models/custom-objects.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,10 @@ export interface IListCustomObjectRecordsFilter {
141141
sort?: ListCutomObjectRecordsSortingOptions;
142142
}
143143

144+
export interface ISearchCustomObjectRecordsFilter extends IListCustomObjectRecordsFilter {
145+
query: string;
146+
}
147+
144148
export interface ICreateCustomObjectRecordBody<T extends ICustomObjectRecordField> {
145149
custom_object_fields: T;
146150
name: string;

src/services/custom-object-service.ts

Lines changed: 64 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ import {
1111
IListCustomObjectRecordsResponse,
1212
ICustomObjectRecord,
1313
ListCutomObjectRecordsSortingOptions,
14-
ICustomObjectRecordField
14+
ICustomObjectRecordField,
15+
ISearchCustomObjectRecordsFilter
1516
} from "@models/index";
1617
import { Client } from "@zendesk/sell-zaf-app-toolbox";
1718

@@ -140,30 +141,9 @@ export class CustomObjectService {
140141
key: string,
141142
sortOptions?: { sort: ListCutomObjectRecordsSortingOptions }
142143
): Promise<ICustomObjectRecord<T>[]> {
143-
let hasMore = true;
144-
let data: IListCustomObjectRecordsFilter = {};
145-
let objects: ICustomObjectRecord<T>[] = [];
146-
147-
do {
148-
const response = await this.client.request<any, IListCustomObjectRecordsResponse<T>>({
149-
url: `/api/v2/custom_objects/${key}/records`,
150-
type: "GET",
151-
contentType: CONTENT_TYPE,
152-
data
153-
});
154-
155-
objects = [...objects, ...response.custom_object_records];
156-
157-
hasMore = response.meta.has_more;
158-
data = {
159-
page: {
160-
after: response.meta.after_cursor
161-
},
162-
...sortOptions
163-
};
164-
} while (hasMore);
165-
166-
return objects;
144+
return this.fetchAllPaginatedRecords<T>(`/api/v2/custom_objects/${key}/records`, {
145+
sort: sortOptions?.sort
146+
} as IListCustomObjectRecordsFilter);
167147
}
168148

169149
/**
@@ -237,4 +217,63 @@ export class CustomObjectService {
237217
contentType: CONTENT_TYPE
238218
});
239219
}
220+
221+
/**
222+
* Get custom object records by search
223+
* The query parameter is used to search text-based fields for records that match specific query terms. The query can be multiple words or numbers. Every record that matches the beginning of any word or number in the query string is returned.
224+
* Fuzzy search is supported for the following text-based field types: : Text fields, Multi Line Text fields, and RegExp fields.
225+
*
226+
* @param key - The custom object key
227+
* @param query - The search query
228+
* @see https://developer.zendesk.com/api-reference/custom-data/custom-objects/custom_object_records/#search-custom-object-records
229+
*/
230+
public async searchRecords<T extends ICustomObjectRecordField>(key: string, query: string) {
231+
return this.fetchAllPaginatedRecords<T>(`/api/v2/custom_objects/${key}/records/search`, {
232+
query
233+
} as ISearchCustomObjectRecordsFilter);
234+
}
235+
236+
/**
237+
* Generic method to fetch all records using pagination
238+
*
239+
* @param url - The API endpoint URL
240+
* @param initialData - Initial request data
241+
* @param getNextPageData - Function to build the next page request data
242+
* @returns Array of all fetched records
243+
*/
244+
private async fetchAllPaginatedRecords<T extends ICustomObjectRecordField>(
245+
url: string,
246+
initialData: IListCustomObjectRecordsFilter
247+
): Promise<ICustomObjectRecord<T>[]> {
248+
let hasMore = true;
249+
let data = initialData;
250+
let objects: ICustomObjectRecord<T>[] = [];
251+
252+
do {
253+
const response = await this.client.request<any, IListCustomObjectRecordsResponse<T>>({
254+
url,
255+
type: "GET",
256+
contentType: CONTENT_TYPE,
257+
data
258+
});
259+
260+
objects = [...objects, ...response.custom_object_records];
261+
262+
hasMore = response.meta.has_more;
263+
if (hasMore) {
264+
data = {
265+
page: {
266+
after: response.meta.after_cursor
267+
},
268+
...(initialData.sort
269+
? {
270+
sort: initialData.sort
271+
}
272+
: undefined)
273+
} as IListCustomObjectRecordsFilter;
274+
}
275+
} while (hasMore);
276+
277+
return objects;
278+
}
240279
}

0 commit comments

Comments
 (0)