Integrating remoteObservable
This commit is contained in:
parent
3430a33cc2
commit
5612ef0460
@ -4,14 +4,15 @@ const _registeredDispatcherParams_ = Symbol('_registeredDispatcherParams_');
|
||||
|
||||
// Interfaces for the Class
|
||||
export interface IExportToDispatcherParameters {
|
||||
uri?: string,
|
||||
}
|
||||
|
||||
export interface IExportMethodToDispatcherParameters {
|
||||
url?: string,
|
||||
uri?: string,
|
||||
}
|
||||
|
||||
export interface IExportPropertyToDispatcherParameters {
|
||||
url?: string,
|
||||
uri?: string,
|
||||
readonly?: boolean
|
||||
}
|
||||
|
||||
@ -59,7 +60,7 @@ export function exportsElementsToDispatcher(options: IExportToDispatcherParamete
|
||||
* Decorator, used to export the Method.
|
||||
* @param options
|
||||
*/
|
||||
export function exportMethodToDispatcher(options: IExportMethodToDispatcherParameters = {}) {
|
||||
export function exportMethodToDispatcher(options: IExportMethodToDispatcherParameters) {
|
||||
return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
|
||||
target[_registeredDispatcherMethods_] = target[_registeredDispatcherMethods_] || new Map<string, IExportMethodToDispatcherParameters>();
|
||||
// Here we just add some information that class decorator will use
|
||||
@ -71,7 +72,7 @@ export function exportMethodToDispatcher(options: IExportMethodToDispatcherParam
|
||||
* Decorator, will create a POST and GET api for the Parameter.
|
||||
* @param options
|
||||
*/
|
||||
export function exportPropertyToDispatcher(options: IExportPropertyToDispatcherParameters = {}) {
|
||||
export function exportPropertyToDispatcher(options: IExportPropertyToDispatcherParameters) {
|
||||
return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
|
||||
target[_registeredDispatcherParams_] = target[_registeredDispatcherParams_] || new Map<string, IExportPropertyToDispatcherParameters>();
|
||||
// Here we just add some information that class decorator will use
|
||||
|
@ -81,7 +81,7 @@ export interface IAnalyzeResult {
|
||||
}
|
||||
}
|
||||
|
||||
export type PropertyInformation = ModifierInformation & TypeInformation & { name: string; declaration: PropertyDeclaration; };
|
||||
export type PropertyInformation = DecoratorInformation & ModifierInformation & TypeInformation & { name: string; declaration: PropertyDeclaration; };
|
||||
|
||||
/**
|
||||
* Helperfunction, used to extract a Mapping of imported Files. This allows the user to rename the interfaces
|
||||
|
@ -19,18 +19,47 @@ export async function generateClientTemplate(options: {
|
||||
logger?: Logger
|
||||
}) {
|
||||
|
||||
// Create the Output dir (if it doenst exists)
|
||||
await createPath(options.outputDir);
|
||||
|
||||
if (options.logger) {
|
||||
options.logger.info('Templates will be stored in ' + options.outputDir);
|
||||
}
|
||||
|
||||
// Firstly copy the nopeDispatcher
|
||||
await copyFile(
|
||||
join(__dirname, '..', '..', '..', 'lib', 'dispatcher', 'nopeDispatcher.ts'),
|
||||
join(options.outputDir, 'nopeDispatcher.ts')
|
||||
);
|
||||
const filesToCopy: {
|
||||
src: string[],
|
||||
name: string,
|
||||
path: string[]
|
||||
}[] = [
|
||||
{
|
||||
name: 'nopeDispatcher.ts',
|
||||
path: ['dispatcher'],
|
||||
src: ['lib', 'dispatcher']
|
||||
},
|
||||
{
|
||||
name: 'nopeObservable.ts',
|
||||
path: ['observables'],
|
||||
src: ['lib', 'observables']
|
||||
},
|
||||
{
|
||||
name: 'nopeRemoteObservable.ts',
|
||||
path: ['observables'],
|
||||
src: ['lib', 'observables']
|
||||
}
|
||||
];
|
||||
|
||||
for (const file of filesToCopy) {
|
||||
// Create the Output dir (if it doenst exists)
|
||||
await createPath(join(options.outputDir, ...file.path));
|
||||
|
||||
// Copy the File.
|
||||
await copyFile(
|
||||
join(__dirname, '..', '..', '..', ...file.src, file.name),
|
||||
join(options.outputDir, ...file.path, file.name)
|
||||
);
|
||||
|
||||
if (options.logger) {
|
||||
options.logger.info('Copied -> ' + file.name);
|
||||
}
|
||||
}
|
||||
|
||||
// Function to Determine new project files.
|
||||
const project = new Project({
|
||||
@ -60,7 +89,27 @@ export async function generateClientTemplate(options: {
|
||||
content: string,
|
||||
}[] = result.map(item => {
|
||||
|
||||
item.className = item.className + 'ClientInterface'
|
||||
// Extract the Class uri
|
||||
const classUri = item.classDecorator.decoratorSettings.exportsElementsToDispatcher ? item.classDecorator.decoratorSettings.exportsElementsToDispatcher.uri || item.className : item.className;
|
||||
|
||||
item.className = item.className + 'ClientInterface';
|
||||
item.methods = item.methods.map(m => {
|
||||
|
||||
const methodUri = m.decoratorSettings.exportMethodToDispatcher ? m.decoratorSettings.exportMethodToDispatcher.uri || m.name : m.name;
|
||||
|
||||
(m as any).uri = classUri + '_' + methodUri;
|
||||
|
||||
return m;
|
||||
});
|
||||
|
||||
item.properties = item.properties.map(p => {
|
||||
|
||||
const methodUri = p.decoratorSettings.exportPropertyToDispatcher ? p.decoratorSettings.exportPropertyToDispatcher.uri || p.name : p.name;
|
||||
|
||||
(p as any).uri = classUri + '_' + methodUri;
|
||||
|
||||
return p;
|
||||
});
|
||||
|
||||
return {
|
||||
name: item.className + '.ts',
|
||||
@ -79,7 +128,7 @@ export async function generateClientTemplate(options: {
|
||||
);
|
||||
|
||||
if (options.logger) {
|
||||
options.logger.info('Generated -> ' + fileName);
|
||||
options.logger.info('Generated -> ' + join('clients', fileName));
|
||||
}
|
||||
|
||||
// Function to Determine new project files.
|
||||
|
@ -1,10 +1,13 @@
|
||||
import { BehaviorSubject, CompletionObserver, ErrorObserver, NextObserver, Subscription } from 'rxjs';
|
||||
import { BehaviorSubject, CompletionObserver, ErrorObserver, NextObserver, Observable, Subscription } from 'rxjs';
|
||||
|
||||
export interface nopeObserver {
|
||||
active: boolean;
|
||||
}
|
||||
|
||||
export declare type NopePartialObserver<T> = NextObserver<T> & nopeObserver | ErrorObserver<T> & nopeObserver | CompletionObserver<T> & nopeObserver;
|
||||
export type pipe<T, K> = (scope: { [index: string]: any }, observable: Observable<T>) => Observable<K>
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* RsJX based Observable.
|
||||
@ -119,4 +122,28 @@ export class nopeObservable<T> extends BehaviorSubject<T> {
|
||||
|
||||
return super.subscribe(_observerOrNext, _error, _complete);
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to enhance the Subscription
|
||||
* @param next Method, that will be called on next.
|
||||
* @param options
|
||||
*/
|
||||
public enhancedSubscribe<K>(next: (data: K) => void, options: {
|
||||
scope?: { [index: string]: any },
|
||||
pipe?: pipe<T, K>
|
||||
} = {}) {
|
||||
|
||||
let observable: Observable<K> = this as any as Observable<K>;
|
||||
if (options.pipe) {
|
||||
observable = options.pipe(options.scope, this);
|
||||
}
|
||||
|
||||
const subscription = observable.subscribe({
|
||||
next
|
||||
});
|
||||
|
||||
const unsubscribe = () => { subscription.unsubscribe(); }
|
||||
|
||||
return unsubscribe;
|
||||
}
|
||||
}
|
70
lib/observables/nopeRemoteObservable.ts
Normal file
70
lib/observables/nopeRemoteObservable.ts
Normal file
@ -0,0 +1,70 @@
|
||||
import { nopeDispatcher } from "../dispatcher/nopeDispatcher";
|
||||
import { pipe } from "./nopeObservable";
|
||||
|
||||
|
||||
export class nopeRemoteObservable<T> {
|
||||
protected _currentLocalValue: T;
|
||||
protected _pathes: {
|
||||
get: string,
|
||||
set: string,
|
||||
subscribe: string,
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for the Current Value.
|
||||
*/
|
||||
public get currentLocalValue(): T {
|
||||
return this._currentLocalValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter for the Current value.
|
||||
*/
|
||||
public set currentLocalValue(value: T) {
|
||||
this.setRemoteValue(value).catch(e => {
|
||||
// Catch the Error an rethrow it.
|
||||
throw e;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a Remote Dispatcher.
|
||||
* @param _dispatcher
|
||||
* @param options
|
||||
*/
|
||||
constructor(
|
||||
protected _dispatcher: nopeDispatcher,
|
||||
public options: {
|
||||
path: string,
|
||||
}
|
||||
) {
|
||||
|
||||
}
|
||||
|
||||
public get currentRemoteValue() {
|
||||
return this.getRemoteValue()
|
||||
}
|
||||
|
||||
public async getRemoteValue() {
|
||||
return await this._dispatcher.performCall<T>(this._pathes.get, [])
|
||||
}
|
||||
|
||||
public async setRemoteValue(value: T) {
|
||||
// Update the Local Value as Well
|
||||
this._currentLocalValue = value;
|
||||
// Perform an Update.
|
||||
return await this._dispatcher.performCall<T>(this._pathes.set, [value]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to Subscribe a NopeObservable on a Remote.
|
||||
* @param next the callback, which will be called on new Data.
|
||||
* @param options
|
||||
*/
|
||||
public async subscribe<K>(next: (data: K) => void, options: {
|
||||
scope?: { [index: string]: any },
|
||||
pipe?: pipe<T, K>
|
||||
} = {}) {
|
||||
return await this._dispatcher.performCall<() => void>(this._pathes.subscribe, [next, options]);
|
||||
}
|
||||
}
|
@ -1,7 +1,8 @@
|
||||
// Automatic Genearted File for Backendclass: "{{className}}"
|
||||
// To update run `npm run build:backend`
|
||||
|
||||
import { nopeDispatcher } from "../nopeDispatcher"
|
||||
import { nopeDispatcher } from "../dispatcher/nopeDispatcher"
|
||||
import { nopeRemoteObservable } from "../observables/nopeRemoteObservable"
|
||||
|
||||
{{!--
|
||||
/**
|
||||
@ -28,8 +29,17 @@ export interface IAnalyzeResult {
|
||||
{{/if}}
|
||||
|
||||
export class {{className}} {
|
||||
constructor(protected _dispatcher: nopeDispatcher){
|
||||
|
||||
{{#each properties}}
|
||||
public {{name}}: nopeRemoteObservable<{{{simplifiedSubType}}}>
|
||||
{{/each}}
|
||||
|
||||
constructor(protected _dispatcher: nopeDispatcher){
|
||||
{{#each properties}}
|
||||
this.{{name}} = new nopeRemoteObservable(_dispatcher,{
|
||||
path: '{{uri}}'
|
||||
})
|
||||
{{/each}}
|
||||
}
|
||||
{{!--
|
||||
declaration: MethodDeclaration;
|
||||
@ -47,7 +57,7 @@ export class {{className}} {
|
||||
{{{authorDescription}}}
|
||||
public async {{name}}{{{head}}}{
|
||||
// Perform the Method
|
||||
return await this._dispatcher.performCall<{{{returnType.simplifiedSubType}}}>('{{../classDecorator.decoratorSettings.exportsElementsToDispatcher.uri}}/{{decoratorSettings.exportMethodToDispatcher.url}}', [{{#each params}}{{name}}{{#unless @last}}, {{/unless}}{{/each}}])
|
||||
return await this._dispatcher.performCall<{{{returnType.simplifiedSubType}}}>('{{uri}}', [{{#each params}}{{name}}{{#unless @last}}, {{/unless}}{{/each}}])
|
||||
}
|
||||
{{/each}}
|
||||
}
|
@ -9,17 +9,13 @@ export interface IF00 {
|
||||
hello: 'world'
|
||||
}
|
||||
|
||||
@exportsElementsToOpenAPI({
|
||||
uri: 'test'
|
||||
})
|
||||
@exportsElementsToDispatcher({
|
||||
uri: 'test'
|
||||
})
|
||||
@exportsElementsToOpenAPI({})
|
||||
@exportsElementsToDispatcher({})
|
||||
export class CLWithInterface {
|
||||
@exportPropertyToDispatcher
|
||||
@exportPropertyToDispatcher({})
|
||||
exportedAttributeSimple = new nopeObservable<boolean>(false);
|
||||
|
||||
@exportPropertyToDispatcher
|
||||
@exportPropertyToDispatcher({})
|
||||
exportedAttributeComplex = new nopeObservable<{
|
||||
element01: IF00,
|
||||
num: number
|
||||
@ -31,9 +27,7 @@ export class CLWithInterface {
|
||||
});
|
||||
|
||||
@exportMethodToOpenAPI({})
|
||||
@exportMethodToDispatcher({
|
||||
url: 'exportedFunction'
|
||||
})
|
||||
@exportMethodToDispatcher({})
|
||||
async exportedFunctionShouldBeHosted(/* COMMENT */ a: IF00, b?: IF01) {
|
||||
return a + b
|
||||
}
|
||||
@ -45,9 +39,7 @@ export class CLWithInterface {
|
||||
* @param b Parameter b
|
||||
*/
|
||||
@exportMethodToOpenAPI({})
|
||||
@exportMethodToDispatcher({
|
||||
url: 'exportedFunction'
|
||||
})
|
||||
@exportMethodToDispatcher({})
|
||||
async exportedFunctionShouldNotBeHosted(/* COMMENT */ a: number, b: IF00, operator: (a: number, b: IF01) => Promise<{
|
||||
test: IF02,
|
||||
x: string
|
||||
@ -64,9 +56,7 @@ export class CLWithInterface {
|
||||
* @param a Parameter a
|
||||
* @param b Parameter b
|
||||
*/
|
||||
@exportMethodToDispatcher({
|
||||
url: 'exportedStringFunction'
|
||||
})
|
||||
@exportMethodToDispatcher({})
|
||||
async exportedStringFunction(a: string, b: string) {
|
||||
// Comment etc.
|
||||
return "";
|
||||
|
@ -17,7 +17,8 @@
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"jsx": "preserve",
|
||||
"downlevelIteration": true
|
||||
"downlevelIteration": true,
|
||||
"experimentalDecorators": true
|
||||
},
|
||||
"include": [
|
||||
"next-env.d.ts",
|
||||
|
@ -19,8 +19,7 @@
|
||||
"removeComments": true,
|
||||
"rootDir": "./",
|
||||
"stripInternal": true,
|
||||
"downlevelIteration": true,
|
||||
"noEmit": true
|
||||
"downlevelIteration": true
|
||||
},
|
||||
"include": [
|
||||
"next-env.d.ts",
|
||||
|
Loading…
Reference in New Issue
Block a user