UNPKG

contensis-delivery-api

Version:

Client for retrieving content using the read-only Contensis Delivery API

204 lines (164 loc) 6.89 kB
import { Config, ContensisClient, IContentTypeOperations, IEntryOperations, IProjectOperations, ITaxonomyOperations, INodeOperations } from '../models'; import { EntryOperations } from '../entries/entry-operations'; import { ContentTypeOperations } from '../content-types/content-type-operations'; import { ProjectOperations } from '../projects/project-operations'; import { TaxonomyOperations } from '../taxonomy/taxonomy-operations'; import { ClientConfig } from './client-config'; import { NodeOperations } from '../nodes/node-operations'; import { ClientParams, HttpClient, IHttpClient, ContensisAuthenticationError, ContensisApplicationError, ContensisClassicGrant, ClientCredentialsGrant, ContensisClassicRefreshTokenGrant } from 'contensis-core-api'; import * as Scopes from './scopes'; import fetch from 'cross-fetch'; const browserGlobal = typeof window !== 'undefined' ? window : typeof self !== 'undefined' ? self : null; const defaultFetch = browserGlobal ? browserGlobal.fetch.bind(browserGlobal) as typeof browserGlobal.fetch : fetch; const ContensisClassicTokenKey = 'x-contensis-classic-token'; export class Client implements ContensisClient { static defaultClientConfig: ClientConfig = null; clientConfig: ClientConfig = null; fetchFn: (input: RequestInfo, init?: RequestInit) => Promise<Response>; entries: IEntryOperations; contentTypes: IContentTypeOperations; nodes: INodeOperations; project: IProjectOperations; taxonomy: ITaxonomyOperations; bearerToken: string; bearerTokenExpiryDate: Date; refreshToken?: string; refreshTokenExpiryDate?: Date; private httpClient: IHttpClient; // @ts-ignore private contensisClassicToken: string; static create(config: Config = null): Client { return new Client(config); } static configure(config: Config) { Client.defaultClientConfig = new ClientConfig(config, Client.defaultClientConfig); } constructor(config: Config = null) { this.clientConfig = new ClientConfig(config, Client.defaultClientConfig); this.fetchFn = !this.clientConfig.fetchFn ? defaultFetch : this.clientConfig.fetchFn; this.httpClient = new HttpClient(this, this.fetchFn); this.entries = new EntryOperations(this.httpClient, this); this.project = new ProjectOperations(this.httpClient, this); this.contentTypes = new ContentTypeOperations(this.httpClient, this); this.nodes = new NodeOperations(this.httpClient, this); this.taxonomy = new TaxonomyOperations(this.httpClient, this); } public getParams(): ClientParams { return this.clientConfig.toParams(); } public getHeaders(contentType: string = 'application/json'): { [key: string]: string } { let headers = { Accept: 'application/json' }; if (!!contentType) { headers['Content-Type'] = contentType; } if (!this.clientConfig.accessToken) { headers['Authorization'] = `Bearer ${this.bearerToken}`; } return headers; } public isBearerTokenExpired(): boolean { if (!!this.bearerToken && !!this.bearerTokenExpiryDate) { const approxCurrentDate = new Date((new Date()).getTime() + 60 * 1000); if (approxCurrentDate < this.bearerTokenExpiryDate) { return false; } } return true; } public isRefreshTokenExpired(): boolean { if (!!this.refreshToken && !!this.refreshTokenExpiryDate) { const approxCurrentDate = new Date((new Date()).getTime() + 60 * 1000); if (approxCurrentDate < this.refreshTokenExpiryDate) { return false; } } return true; } public ensureIsAuthorized(): Promise<string> { if (!!this.clientConfig.accessToken) { return Promise.resolve(''); } if (!this.isBearerTokenExpired()) { return Promise.resolve(this.bearerToken); } return this.authenticate() .then(() => this.bearerToken) .catch((error: Error) => { if (error instanceof ContensisAuthenticationError) { throw error; } throw new ContensisApplicationError(error.message); }); } private authenticate(): Promise<void> { const AuthPayload = this.getAuthenticatePayload(); const AuthData = Object.keys(AuthPayload) .map(key => { return encodeURIComponent(key) + '=' + encodeURIComponent(AuthPayload[key]); }) .join('&'); let rootUrl = !!this.clientConfig.rootUrl ? this.clientConfig.rootUrl : ''; return this.fetchFn(`${rootUrl}/authenticate/connect/token`, { method: 'POST', // mode: 'cors', // cache: 'no-cache', // credentials: 'same-origin', headers: { 'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8', }, body: AuthData, }) .then(async response => { let responseData = await response.json(); return { response, responseData }; }) .then(responseAndData => { let { response, responseData } = responseAndData; if (!response.ok) { throw new ContensisAuthenticationError(!!responseData.error ? responseData.error : JSON.stringify(responseData)); } this.bearerToken = responseData.access_token; const expiresInSeconds = responseData.expires_in; const currentDate = new Date(); this.bearerTokenExpiryDate = new Date(currentDate.getTime() + expiresInSeconds * 1000); if (!!responseData.refresh_token) { this.refreshToken = responseData.refresh_token; this.refreshTokenExpiryDate = new Date(currentDate.getTime() + 15 * 24 * 3600 * 1000); // 15 days } else { this.refreshToken = null; this.refreshTokenExpiryDate = null; } if (!!response.headers && response.headers.has(ContensisClassicTokenKey)) { this.contensisClassicToken = response.headers.get(ContensisClassicTokenKey); } else { this.contensisClassicToken = null; } }); } private getAuthenticatePayload() { let payload = { scope: this.clientConfig.clientType === 'client_credentials' ? Scopes.getResourcesScopes() : Scopes.getAllScopes(), }; if (this.clientConfig.clientType !== 'none') { payload['grant_type'] = this.clientConfig.clientType; } if (this.clientConfig.clientType === 'client_credentials') { let clientDetails = this.clientConfig.clientDetails as ClientCredentialsGrant; payload['client_id'] = clientDetails.clientId; payload['client_secret'] = clientDetails.clientSecret; } else if (this.clientConfig.clientType === 'contensis_classic') { let clientDetails = this.clientConfig.clientDetails as ContensisClassicGrant; payload['username'] = clientDetails.username; payload['password'] = clientDetails.password; } else if (this.clientConfig.clientType === 'contensis_classic_refresh_token') { let clientDetails = this.clientConfig.clientDetails as ContensisClassicRefreshTokenGrant; payload['refresh_token'] = clientDetails.refreshToken; } return payload; } }