first-npm-package-nicule
Version:
This isi first npm package
87 lines (69 loc) • 3.67 kB
text/typescript
import { HrefFormatterProvider } from 'first-npm-package-nicule/core';
import { ReflectiveInjector, Type } from '@angular/core';
import { makePropDecorator } from '../../google-decorator-factories';
import { BindDecorator } from '../bind.decorator';
// import { HypermediaStore } from 'hypermedia/core/services/hypermedia.store';
import { TOKEN_PROVIDER } from '../../token-provider';
import { PARENT_ENTITY } from '../../parent-entity';
import { HypermediaStore } from '../../../core/services/hypermedia.store';
type TokenProviderType = { useClass: Type<any> } | { useFactory: any, deps?: Array<any> } | { useExisting: Type<any> };
interface LinkedEntityOptions<T> {
as?: Type<T>;
authorize?: boolean;
tokenProvider?: TokenProviderType;
}
export interface BindLinkedEntityDecorator {
<T>(classList: Array<string>, options?: LinkedEntityOptions<T>): any;
new <T>(classList: Array<string>, options?: LinkedEntityOptions<T>): any;
}
function guid(): string {
function s4(): string {
return Math.floor((Math.random() + 1) * 0x10000)
.toString(16)
.substring(1);
}
return `${s4()}${s4()}-${s4()}-${s4()}-${s4()}-${s4()}${s4()}${s4()}`;
}
export const LinkedEntity: BindLinkedEntityDecorator = makePropDecorator('BindLinkedEntity',
<T>(classList: Array<string>, options: LinkedEntityOptions<T> = {}) => {
return ({
binding: {
priority: 1,
bind: (({ entities = [] }, fieldName, injector, parent) => {
let tokenOverride;
if (entities.length === 0) {
return undefined;
}
const { href } = entities.find(({ class: classes }) => classList.every(clazz => classes.includes(clazz))) || {} as any;
if (!href) {
return undefined;
}
if (!/^(http|https):\/\//.test(href)) {
return undefined;
}
if (options && options.tokenProvider) {
injector = ReflectiveInjector.resolveAndCreate([{ provide: PARENT_ENTITY, useValue: parent }, { provide: TOKEN_PROVIDER, ...options.tokenProvider }], injector);
const tokenProvider = injector.get(TOKEN_PROVIDER);
tokenOverride = tokenProvider.getToken();
}
const formatterProvider = injector.get(HrefFormatterProvider);
const formatter = formatterProvider.getHrefFormatterForHref(href);
const scope = (formatter === undefined) ? 'external' : formatter.getScope();
const path = (formatter === undefined) ? href : formatter.makePathFromHref(href);
const { authorize, as } = options;
const selector = injector
.get(HypermediaStore)
.select(`${path}?noCache=${guid()}`, scope, authorize, tokenOverride);
selector
.intercept(0, ({ class: classes }) => {
console.log("linked-entity-decorator: intercepted 0 response exception");
// prevents from redirecting to disconnected error page
});
if (!as) {
return selector;
}
return selector.as(as);
})
} as BindDecorator
}) as any;
});