contensis-delivery-api
Version:
Client for retrieving content using the read-only Contensis Delivery API
179 lines (159 loc) • 6.36 kB
text/typescript
import { Entry } from '../models';
interface ResolvedEntry {
entries: Entry[];
value: any;
}
function isUnresolvedEntry(value: any): boolean {
if (value && value.sys && value.sys.id) {
let keys = Object.keys(value);
return (keys.length === 1);
}
return false;
}
function isUnresolvedImage(value: any): boolean {
if (value && value.asset) {
let keys = Object.keys(value);
return (keys.length <= 2) && isUnresolvedEntry(value.asset);
}
return false;
}
function isComposer(value: any): boolean {
if (Array.isArray(value) && (value.length > 0)) {
return isComposerItem(value[0]);
}
return false;
}
function isComposerItem(value: any): boolean {
if (value && value.type && value.value) {
let keys = Object.keys(value);
return (keys.length === 2);
}
return false;
}
export class EntryResolver {
constructor(private entry: Entry, private paths: string[], private getEntry: (id: string, language: string) => Promise<Entry>) {
}
resolve(): Promise<Entry> {
let paths: string[] = this.paths || Object.keys(this.entry);
let promises: Promise<ResolvedEntry>[] = paths.map(path => {
let parts = path.split('.');
let field = parts.shift();
let promise: Promise<ResolvedEntry> = null;
let value = this.entry[field];
if (value) {
promise = this.resolveField(value);
if (!promise && isComposer(value)) {
let composerType = (parts.length > 0) ? parts.shift() : null;
promise = this.resolveComposerField(value, composerType);
}
}
promise = !promise
? Promise.resolve(null)
: promise.then(resolvedValue => {
this.entry[field] = resolvedValue.value;
return resolvedValue;
});
return promise.then(v => {
return this.next(v, parts.join('.'));
});
});
return Promise.all(promises).then(values => {
return this.entry;
});
}
next(resolvedEntry: ResolvedEntry, path: string): Promise<any> {
if (!path || !resolvedEntry || !resolvedEntry.entries || (resolvedEntry.entries.length <= 0)) {
return Promise.resolve(resolvedEntry);
}
let promises = resolvedEntry.entries.map(entry => {
let resolver = new EntryResolver(entry, [path], (id: string, language: string) => this.getEntry(id, language));
return resolver.resolve();
});
return Promise.all(promises);
}
private resolveField(value: any): Promise<ResolvedEntry> {
if (isUnresolvedEntry(value)) {
return this.resolveEntry(value);
}
if (isUnresolvedImage(value)) {
return this.resolveImage(value);
}
if (Array.isArray(value)) {
let isResolving = false;
let promises = value.map(item => {
if (isUnresolvedEntry(item)) {
isResolving = true;
return this.resolveEntry(item);
}
if (isUnresolvedImage(item)) {
isResolving = true;
return this.resolveImage(item);
}
return Promise.resolve({ entries: [], value: item });
});
if (isResolving) {
return Promise.all(promises).then((resolvedEntries) => {
let list = [];
let entries = [];
for (let e of resolvedEntries) {
list.push(e.value);
entries = entries.concat(e.entries);
}
return { entries, value: list };
});
}
}
return null;
}
private resolveComposerField(value: any, type: string): Promise<ResolvedEntry> {
if (Array.isArray(value)) {
let isResolving = false;
let promises: Promise<ResolvedEntry>[] = value.map(item => {
if (isComposerItem(item)) {
if (!type || (type === item.type)) {
let itemPromise = this.resolveField(item.value);
if (itemPromise) {
isResolving = true;
return itemPromise.then((v) => {
item.value = v;
return item;
});
}
}
}
return Promise.resolve({ entries: [], value: item });
});
if (isResolving) {
return Promise.all(promises).then((resolvedEntries) => {
let list = [];
let entries = [];
for (let e of resolvedEntries) {
list.push(e.value);
entries = entries.concat(e.entries);
}
return { entries, value: list };
});
}
}
return null;
}
private async resolveEntry(value: any): Promise<ResolvedEntry> {
if (value && value.sys && value.sys.id) {
let language = value.sys.language || this.entry.sys.language;
let entry = await this.getEntry(value.sys.id, language);
return { entries: [entry], value: entry };
}
return Promise.resolve({ entries: [], value });
}
private resolveImage(value: any): Promise<ResolvedEntry> {
if (value && value.asset && value.asset.sys && value.asset.sys.id) {
let language = value.asset.sys.language || this.entry.sys.language;
return this.getEntry(value.asset.sys.id, language)
.then((image) => {
value.asset = image;
return { entries: [image], value };
});
}
return Promise.resolve({ entries: [], value });
}
}