Skip to content

Commit

Permalink
feat: Adds 'excludeArchivedItems' client configuration & fixes elemen…
Browse files Browse the repository at this point in the history
…t endpoint mapping due to API change
  • Loading branch information
Enngage authored Aug 21, 2023
2 parents 724fe4f + 598844d commit 19f3fff
Show file tree
Hide file tree
Showing 15 changed files with 77 additions and 114 deletions.
5 changes: 5 additions & 0 deletions lib/config/delivery-configs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,4 +95,9 @@ export interface IDeliveryClientConfig {
* Codename of rendition preset to be applied by default to the base asset URL path.
*/
defaultRenditionPreset?: string;

/**
* Can be used to exclude archived items from all queries by default. Only applicable when preview API is used
*/
excludeArchivedItems?: boolean;
}
6 changes: 5 additions & 1 deletion lib/contracts/contracts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,11 @@ export namespace Contracts {
}

export interface IViewContentTypeElementContract {
element: IContentTypeElementContract;
codename?: string;
type: string;
name: string;
taxonomy_group?: string;
options?: IElementOptionContract[];
}

export interface IElementContract {
Expand Down
2 changes: 1 addition & 1 deletion lib/mappers/generic-element.mapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export class GenericElementMapper {
throw Error(`Invalid response for mapping element`);
}

const element = response.element;
const element = response;

return {
codename: element.codename,
Expand Down
3 changes: 1 addition & 2 deletions lib/mappers/type.mapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ export class TypeMapper {
const elementCodename = elementName;

// extra properties for certain element types
const taxonomyGroup: string | undefined = typeElement.taxonomy_group;
const options: Contracts.IElementOptionContract[] = [];

// some elements can contain options
Expand All @@ -62,7 +61,7 @@ export class TypeMapper {

elements.push({
codename: elementCodename,
taxonomyGroup: taxonomyGroup,
taxonomyGroup: typeElement.taxonomy_group,
options: options,
name: typeElement.name,
type: typeElement.type
Expand Down
15 changes: 7 additions & 8 deletions lib/models/responses.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { IDeliveryNetworkResponse } from './common/base-responses';
import { IKontentListAllResponse, IKontentListResponse, IKontentResponse } from './common/common-models';
import { IPagination } from './common/pagination.class';
import { IContentType } from './content-type-models';
import { IGenericElement } from './element-models';
import { IGenericElementOption } from './element-models';
import { IContentItem, IContentItemsContainer } from './item-models';
import { ILanguage } from './language-models';
import { IContentItemDelta } from './sync-models';
Expand All @@ -24,14 +24,13 @@ export namespace Responses {
type: IContentType;
}


export interface IViewContentTypeElementResponse extends IKontentResponse {
/**
* Response containing content type element
*
* @constructor
* @param {IGenericElement} element - Content type element
*/
element: IGenericElement;
codename?: string,
type: string,
name: string;
taxonomyGroup?: string
options: IGenericElementOption[];
}

export interface IListItemsFeedResponse<TContentItem extends IContentItem = IContentItem>
Expand Down
13 changes: 10 additions & 3 deletions lib/query/common/base-query.class.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import { IHeader, IQueryParameter } from '@kontent-ai/core-sdk';

import { IDeliveryClientConfig } from '../../config';
import { IDeliveryNetworkResponse, IKontentResponse, IQueryConfig, Parameters} from '../../models';
import { Filters, IDeliveryNetworkResponse, IKontentResponse, IQueryConfig, Parameters } from '../../models';
import { QueryService } from '../../services';


export abstract class BaseQuery<TResponse extends IKontentResponse, TQueryConfig extends IQueryConfig, TContract> {
protected parameters: IQueryParameter[] = [];
protected customUrl?: string;
Expand Down Expand Up @@ -119,11 +118,19 @@ export abstract class BaseQuery<TResponse extends IKontentResponse, TQueryConfig
protected processDefaultLanguageParameter(): void {
// add default language if none is specified && default language is specified globally
if (this.config.defaultLanguage) {
const languageParameter = this.getParameters().find((m) => m.getParam().match(`language=[a-zA-Z_][a-zA-Z0-9_]{0,59}$`));
const languageParameter = this.getParameters().find((m) =>
m.getParam()?.toLowerCase().includes('language='.toLowerCase())
);
if (!languageParameter) {
// language parameter was not specified in query, use globally defined language
this.parameters.push(new Parameters.LanguageParameter(this.config.defaultLanguage));
}
}
}

protected processExcludeArchivedItemsParameter(): void {
if (this.config.excludeArchivedItems) {
this.parameters.push(new Filters.NotEqualsFilter('system.workflow_step', 'archived'));
}
}
}
5 changes: 4 additions & 1 deletion lib/query/item/multiple-items-query.class.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,9 +100,12 @@ export class MultipleItemsQuery<TContentItem extends IContentItem = IContentItem
getUrl(): string {
const action = '/items';

// add default language is necessry
// handle default language
this.processDefaultLanguageParameter();

// handle archived items
this.processExcludeArchivedItemsParameter();

return super.resolveUrlInternal(action);
}

Expand Down
3 changes: 3 additions & 0 deletions lib/query/item/single-item-query.class.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,9 @@ export class SingleItemQuery<TContentItem extends IContentItem = IContentItem> e
// add default language is necessry
this.processDefaultLanguageParameter();

//process client level archived item exclusion
this.processExcludeArchivedItemsParameter();

return super.resolveUrlInternal(action);
}

Expand Down
3 changes: 3 additions & 0 deletions lib/query/items-feed/items-feed-query.class.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,9 @@ export class ItemsFeedQuery<TContentItem extends IContentItem = IContentItem> ex
// add default language is necessary
this.processDefaultLanguageParameter();

//process client level archived item exclusion
this.processExcludeArchivedItemsParameter();

return super.resolveUrlInternal(action);
}

Expand Down
6 changes: 2 additions & 4 deletions lib/services/mapping.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ export class MappingService implements IMappingService {
listTaxonomiesResponse(data: Contracts.IListTaxonomyGroupsContract): Responses.IListTaxonomiesResponse {
return {
items: this.taxonomyMapper.mapTaxonomies(data.taxonomies),
pagination: this.mapPagination(data.pagination)
pagination: this.mapPagination(data.pagination),
};
}

Expand All @@ -158,9 +158,7 @@ export class MappingService implements IMappingService {
viewContentTypeElementResponse(
data: Contracts.IViewContentTypeElementContract
): Responses.IViewContentTypeElementResponse {
return {
element: this.genericElementMapper.mapElement(data)
};
return this.genericElementMapper.mapElement(data);
}

initializeContentSync(data: Contracts.IInitializeSyncContract): Responses.IInitializeSyncResponse {
Expand Down
1 change: 1 addition & 0 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ Following is a list of configuration options for DeliveryClient (`IDeliveryClien
| propertyNameResolver? | PropertyNameResolver | Used to map properties. Choose one of the following default resolvers: `snakeCasePropertyNameResolver`, `pascalCasePropertyNameResolver` & `camelCasePropertyNameResolver` or create your own PropertyNameResolver function |
| assetsDomain? | string | Custom domain for assets. Changes url of assets in both asset & rich text elements |
| defaultRenditionPreset? | string | Codename of rendition preset to be applied by default to the base asset URL path when present. When set, the SDK will provide the URL of customized images by default. Right now the only supported preset codename is `default`. |
| excludeArchivedItems? | boolean | Can be used to exclude archived items from all queries by default. Only applicable when preview API is used. |

### Create typed models

Expand Down
112 changes: 27 additions & 85 deletions test/browser/isolated-tests/url/item-url-parameters.spec.ts
Original file line number Diff line number Diff line change
@@ -1,28 +1,19 @@
import { Context, setup } from '../../setup';

describe('Item url parameters', () => {

const context = new Context({defaultLanguage: 'default'});
const context = new Context({ defaultLanguage: 'default', excludeArchivedItems: true });
setup(context);

it(`includeTotalCount parameter should be set to true when used`, () => {
const url = new URL(
context.deliveryClient.items()
.includeTotalCountParameter()
.getUrl()
);
const url = new URL(context.deliveryClient.items().includeTotalCountParameter().getUrl())

const param = url.searchParams.get('includeTotalCount');

expect(param).toEqual('true');
});

it(`depth param should be set`, () => {
const url = new URL(
context.deliveryClient.items()
.depthParameter(1)
.getUrl()
);
const url = new URL(context.deliveryClient.items().depthParameter(1).getUrl());

const param = url.searchParams.get('depth');

Expand All @@ -34,35 +25,23 @@ describe('Item url parameters', () => {
});

it(`multiple elements param should be set`, () => {
const url = new URL(
context.deliveryClient.items()
.elementsParameter(['elem1', 'elem2'])
.getUrl()
);
const url = new URL(context.deliveryClient.items().elementsParameter(['elem1', 'elem2']).getUrl());

const param = url.searchParams.get('elements');

expect(param).toEqual('elem1,elem2');
});

it(`single elements param should be set`, () => {
const url = new URL(
context.deliveryClient.items()
.elementsParameter(['elem1'])
.getUrl()
);
const url = new URL(context.deliveryClient.items().elementsParameter(['elem1']).getUrl());

const param = url.searchParams.get('elements');

expect(param).toEqual('elem1');
});

it(`limit parameter should be set`, () => {
const url = new URL(
context.deliveryClient.items()
.limitParameter(1)
.getUrl()
);
const url = new URL(context.deliveryClient.items().limitParameter(1).getUrl());

const param = url.searchParams.get('limit');

Expand All @@ -74,59 +53,39 @@ describe('Item url parameters', () => {
});

it(`order (desc) parameter should be set`, () => {
const url = new URL(
context.deliveryClient.items()
.orderParameter('elem1', 'desc')
.getUrl()
);
const url = new URL(context.deliveryClient.items().orderParameter('elem1', 'desc').getUrl());

const param = url.searchParams.get('order');

expect(param).toEqual('elem1[desc]');
});

it(`order (asc) parameter should be set`, () => {
const url = new URL(
context.deliveryClient.items()
.orderParameter('elem1', 'asc')
.getUrl()
);
const url = new URL(context.deliveryClient.items().orderParameter('elem1', 'asc').getUrl());

const param = url.searchParams.get('order');

expect(param).toEqual('elem1[asc]');
});

it(`orderByDescending should be set`, () => {
const url = new URL(
context.deliveryClient.items()
.orderByDescending('elem1')
.getUrl()
);
const url = new URL(context.deliveryClient.items().orderByDescending('elem1').getUrl());

const param = url.searchParams.get('order');

expect(param).toEqual('elem1[desc]');
});

it(`orderByAscending should be set`, () => {
const url = new URL(
context.deliveryClient.items()
.orderByAscending('elem1')
.getUrl()
);
const url = new URL(context.deliveryClient.items().orderByAscending('elem1').getUrl());

const param = url.searchParams.get('order');

expect(param).toEqual('elem1[asc]');
});

it(`skip parameter should be set`, () => {
const url = new URL(
context.deliveryClient.items()
.skipParameter(1)
.getUrl()
);
const url = new URL(context.deliveryClient.items().skipParameter(1).getUrl());

const param = url.searchParams.get('skip');

Expand All @@ -138,64 +97,47 @@ describe('Item url parameters', () => {
});

it(`language parameter should be set`, () => {
const url = new URL(
context.deliveryClient.items()
.languageParameter('en')
.getUrl()
);
const url = new URL(context.deliveryClient.items().languageParameter('en').getUrl());

const param = url.searchParams.get('language');

expect(param).toEqual('en');
});

it('exclude archived items should apply workflow filter', () => {
const url = new URL(context.deliveryClient.items().getUrl());
const param = url.searchParams.get('system.workflow_step[neq]');
expect(param).toEqual('archived');
});

// trim checks

it(`elementsParameter should trim its element codenames`, () => {
const url = new URL(
context.deliveryClient.items()
.elementsParameter([' elem1', 'elem2', ' elem3'])
.getUrl()
);
const url = new URL(context.deliveryClient.items().elementsParameter([' elem1', 'elem2', ' elem3']).getUrl());

const param = url.searchParams.get('elements');

expect(param).toEqual('elem1,elem2,elem3');
});

it(`orderParameter should trim its element`, () => {
const url = new URL(
context.deliveryClient.items()
.orderParameter(' elem1 ', 'asc')
.getUrl()
);
const url = new URL(context.deliveryClient.items().orderParameter(' elem1 ', 'asc').getUrl());

const param = url.searchParams.get('order');

expect(param).toEqual('elem1[asc]');
});

it('defaultLanguage should set language parameter', ()=> {
const url = new URL(
context.deliveryClient.items()
.getUrl()
);
const param = url.searchParams.get('language')
expect(param).toEqual('default')
it('defaultLanguage should set language parameter', () => {
const url = new URL(context.deliveryClient.items().getUrl());
const param = url.searchParams.get('language');
expect(param).toEqual('default');
});

it(`languageParameter should overwrite default language`, () => {
const url = new URL(
context.deliveryClient.items()
.languageParameter('es_ES')
.getUrl()
);

const param = url.searchParams.get('language')
expect(param).toEqual('es_ES')
const url = new URL(context.deliveryClient.items().languageParameter('es_ES').getUrl());

const param = url.searchParams.get('language');
expect(param).toEqual('es_ES');
});


});

Loading

0 comments on commit 19f3fff

Please sign in to comment.