@rws-framework/client
Version:
This package provides the core client-side framework for Realtime Web Suit (RWS), enabling modular, asynchronous web components, state management, and integration with backend services. It is located in `.dev/client`.
127 lines (95 loc) • 4.59 kB
text/typescript
import RWSContainer from './_container';
import TheRWSService from '../services/_service';
import ConfigService from '../services/ConfigService';
import { loadRWSRichWindow } from '../types/RWSWindow';
import RWSViewComponent, { IWithCompose } from './_component';
import { InterfaceSymbol } from './_container';
import { RWSInject } from './_decorators/RWSInject';
import { ElementStyles, Observable, ViewTemplate } from '@microsoft/fast-element';
import { handleExternalChange } from './_attrs/_external_handler';
interface RWSDecoratorOptions {
template?: string,
styles?: string,
fastElementOptions?: {
shadowOptions?: ShadowRootInit
},
ignorePackaging?: boolean,
debugPackaging?: boolean
oreoMode?: boolean
}
//const _PARAMTYPES_METADATA_KEY = 'design:paramtypes';
type HtmlBinderType = (context: RWSViewComponent) => ViewTemplate;
function RWSView<Component extends RWSViewComponent>(name: string, data?: RWSDecoratorOptions | null, override?: { styles?: ElementStyles, template?: ViewTemplate, options?: any }): (type: any, args?: any) => void {
return (theComponent: IWithCompose<Component>, args?: any) => {
theComponent.definition = { name, template: null }
if(override){
if(override.styles){
theComponent.definition.styles = override.styles;
}
if(override.template){
theComponent.definition.template = override.template;
}
if(override.options){
(theComponent.definition as any).options = override.options;
}
}
};
}
function RWSIgnore(params: { mergeToApp?: boolean } | null = null): () => void {
return () => { };
}
function getParentConstructor(instance: any): any {
const proto = Object.getPrototypeOf(instance.constructor.prototype);
if (proto && proto.constructor) {
return proto.constructor;
}
return null;
}
const applyConstructor = (component: RWSViewComponent, x: boolean = false): void => {
const mainConstructor: any = component.constructor;
const parent = getParentConstructor(component);
if (parent.name !== 'RWSViewComponent' ) {
return;
}
const existingInjectedDependencies = (mainConstructor as IWithCompose<RWSViewComponent>)._toInject;
const regServices = loadRWSRichWindow().RWS._registered;
const depsToInject: string[] = (mainConstructor as IWithCompose<RWSViewComponent>)._depKeys[mainConstructor.name] || [];
const depsInInjector: string[] = Object.keys(existingInjectedDependencies);
const toInject: string[] = [...depsToInject]
type KeyType = {[key: string]: TheRWSService | string };
const _target = (component as any);
function inject(services: KeyType){
for (const prop in services) {
const service = (typeof services[prop] === 'string' ? existingInjectedDependencies[prop] : services[prop]) as TheRWSService;
_target[prop] = service;
}
}
inject(toInject.reduce((acc: KeyType, cur) => {
acc[cur] = cur;
return acc;
}, {}));
const defaultDeps: [string, TheRWSService][] = Object.keys(existingInjectedDependencies)
.filter((depKey: string) => existingInjectedDependencies[depKey].isDefault()).map((depKey => [depKey, existingInjectedDependencies[depKey]]));
inject(defaultDeps.reduce((acc: KeyType, cur: [string, TheRWSService]) => {
acc[cur[0]] = cur[1];
return acc;
}, {}));
inject({
config: RWSContainer().get(ConfigService)
})
if(Object.keys(RWSViewComponent._externalAttrs).includes((_target.constructor as IWithCompose<any>).name)){
for(const exAttrKey in RWSViewComponent._externalAttrs[(_target.constructor as IWithCompose<any>).name]){
const exAttr = RWSViewComponent._externalAttrs[(_target.constructor as IWithCompose<any>).name][exAttrKey];
const notifier = Observable.getNotifier(_target);
notifier.subscribe({
handleChange(source, key) {
if (key === exAttr && !_target.__exAttrLoaded.includes(exAttr)) {
handleExternalChange(source, key);
_target.__exAttrLoaded.push(key);
}
}
}, exAttr);
}
}
};
export { RWSView, RWSDecoratorOptions, RWSIgnore, RWSInject, applyConstructor };