Skip to content

Commit

Permalink
feat: add fields -parameter
Browse files Browse the repository at this point in the history
  • Loading branch information
Strobotti committed Jun 9, 2023
1 parent 4fd800a commit faff396
Show file tree
Hide file tree
Showing 2 changed files with 88 additions and 25 deletions.
46 changes: 45 additions & 1 deletion src/__tests__/JsonApiFetch.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {
ItemDeserializer,
RelationshipDeserializer,
} from 'jsonapi-ts-deserializer';
import { Fetch, getJsonApiFetch, JsonApiFetch, JsonApiResponse } from '../index';
import { buildRequestUrl, Fetch, getJsonApiFetch, JsonApiFetch, JsonApiResponse } from '../index';

const jsonapiOrgExampleData = {
links: {
Expand Down Expand Up @@ -487,3 +487,47 @@ describe('JsonApiFetch', () => {
});
});
});

describe('buildRequestUrl', () => {
it('builds a request url with no query parameters', () => {
expect(buildRequestUrl('http://example.com', {}, [])).toEqual('http://example.com');
});

it('builds a request url with a single query parameter', () => {
expect(buildRequestUrl('http://example.com', { filters: { foo: 'bar' } }, [])).toEqual(
'http://example.com?filter[foo]=bar',
);
});

it('builds a request url with multiple query parameters', () => {
expect(buildRequestUrl('http://example.com', { filters: { foo: 'bar', baz: 'qux' } }, [])).toEqual(
'http://example.com?filter[foo]=bar&filter[baz]=qux',
);
});

it('builds a request url with a single include', () => {
expect(buildRequestUrl('http://example.com', {}, ['foo'])).toEqual('http://example.com?include=foo');
});

it('builds a request url with multiple includes', () => {
expect(buildRequestUrl('http://example.com', {}, ['foo', 'bar'])).toEqual('http://example.com?include=foo%2Cbar');
});

it('builds a request url with a single include and a single query parameter', () => {
expect(buildRequestUrl('http://example.com', { filters: { foo: 'bar' } }, ['baz'])).toEqual(
'http://example.com?filter[foo]=bar&include=baz',
);
});

it('builds a request url with sorting and pagination', () => {
expect(buildRequestUrl('http://example.com', { sort: ['name', '-email'], page: 1, limit: 10 }, [])).toEqual(
'http://example.com?page[number]=1&page[size]=10&sort=name%2C-email',
);
});

it('builds a request url with fields parameters set', () => {
expect(buildRequestUrl('http://example.com', { fields: { articles: ['title', 'body'] } }, [])).toEqual(
'http://example.com?fields[articles]=title%2Cbody',
);
});
});
67 changes: 43 additions & 24 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ export type GetParams = {
filters?: {
[key: string]: any;
};
fields?: {
[key: string]: string[];
};
};

export type JsonApiResponse<T> = {
Expand All @@ -55,6 +58,45 @@ export type EntitySerializer<T> = {
serialize: (entity: T) => JsonApiItem;
};

export const buildRequestUrl = (route: string, params: GetParams, includes: string[]): string => {
const paramsArray: string[] = [];

if (params.filters !== undefined) {
const filters = params.filters;

Object.keys(filters).forEach((key: string) => {
const val = filters[key] as string;
paramsArray.push(`filter[${key}]=${val}`);
});
}
if (params.fields !== undefined) {
const fields = params.fields;

Object.keys(fields).forEach((key: string) => {
const val = encodeURIComponent(fields[key].join(','));
paramsArray.push(`fields[${key}]=${val}`);
});
}
if (params.page !== undefined && params.page !== null) {
paramsArray.push(`page[number]=${params.page}`);
}
if (params.limit) {
paramsArray.push(`page[size]=${params.limit}`);
}
if (params.sort !== undefined) {
paramsArray.push(`sort=` + encodeURIComponent(params.sort.join(',')));
}
if (includes.length > 0) {
paramsArray.push(`include=` + encodeURIComponent(includes.join(',')));
}

if (paramsArray.length === 0) {
return route;
}

return route + '?' + paramsArray.join('&');
};

/**
* Instantiate a generic service for interacting with a JSON:API endpoint
*
Expand Down Expand Up @@ -83,30 +125,7 @@ export const getJsonApiFetch = <T>(

return {
find: (params: GetParams, includes: string[]): Promise<JsonApiResponse<T>> => {
const paramsArray: string[] = [];

if (params.filters !== undefined) {
const filters = params.filters;

Object.keys(filters).forEach((key: string) => {
const val = filters[key] as string;
paramsArray.push(`filter[${key}]=${val}`);
});
}
if (params.page !== undefined && params.page !== null) {
paramsArray.push(`page[number]=${params.page}`);
}
if (params.limit) {
paramsArray.push(`page[size]=${params.limit}`);
}
if (params.sort !== undefined) {
paramsArray.push(`sort=` + encodeURIComponent(params.sort.join(',')));
}
if (includes.length > 0) {
paramsArray.push(`include=` + encodeURIComponent(includes.join(',')));
}

const url = route + '?' + paramsArray.join('&');
const url = buildRequestUrl(route, params, includes);

return fetch
.get(url)
Expand Down

0 comments on commit faff396

Please sign in to comment.