baqend
Version:
Baqend JavaScript SDK
175 lines (151 loc) • 5.9 kB
text/typescript
import * as message from '../message';
import { StatusCode } from '../connector';
import type { EntityManagerFactory } from '../EntityManagerFactory';
import type { Metamodel, ManagedType } from '../metamodel';
import { Validator } from './Validator';
/**
* Representation of a Code which runs on Baqend.
*/
export class Code {
metamodel: Metamodel;
entityManagerFactory: EntityManagerFactory;
/**
* @param metamodel
* @param entityManagerFactory
*/
constructor(metamodel: Metamodel, entityManagerFactory: EntityManagerFactory) {
this.metamodel = metamodel;
this.entityManagerFactory = entityManagerFactory;
}
/**
* Converts the given function to a string
* @param fn The JavaScript function to serialize
* @return The serialized function
*/
functionToString(fn: Function): string {
if (!fn) {
return '';
}
let str = fn.toString();
str = str.substring(str.indexOf('{') + 1, str.lastIndexOf('}'));
if (str.charAt(0) === '\n') {
str = str.substring(1);
}
if (str.charAt(str.length - 1) === '\n') {
str = str.substring(0, str.length - 1);
}
return str;
}
/**
* Converts the given string to a module wrapper function
* @param signature The expected parameters of the function
* @param code The JavaScript function to deserialize
* @return The deserialized function
*/
stringToFunction(signature: string[], code: string): Function {
// eslint-disable-next-line @typescript-eslint/no-implied-eval
return new Function(signature as any /* typings are incorrect here */, code); // eslint-disable-line no-new-func
}
/**
* Loads a list of all available modules without handlers
*
* @return
*/
loadModules(): Promise<string[]> {
const msg = new message.GetAllModules();
return this.entityManagerFactory.send(msg)
.then((response) => response.entity);
}
/**
* Loads Baqend code which will be identified by the given bucket and code type
*
* @param type The entity type for the handler or the Name of the
* Baqend code
* @param codeType The type of the code
* @param asFunction set it to <code>true</code>, to parse the code as a function and return it
* instead of a string
* @return The code as parsed function
*/
loadCode(type: ManagedType<any> | string, codeType: string, asFunction: true): Promise<Function>;
/**
* Loads Baqend code which will be identified by the given bucket and code type
*
* @param type The entity type for the handler or the Name of the
* Baqend code
* @param codeType The type of the code
* @param asFunction set it to <code>true</code>, to parse the code as a function and return it
* instead of a string
* @return The code as string
*/
loadCode(type: ManagedType<any> | string, codeType: string, asFunction?: false): Promise<string>;
loadCode(type: ManagedType<any> | string, codeType: string, asFunction = false): Promise<Function | string | null> {
const bucket = typeof type === 'string' ? type : type.name;
const msg = new message.GetBaqendCode(bucket, codeType)
.responseType('text');
return this.entityManagerFactory.send(msg)
.then((response) => this.parseCode(bucket, codeType, asFunction, response.entity), (e) => {
if (e.status === StatusCode.OBJECT_NOT_FOUND) {
return null;
}
throw e;
});
}
/**
* Saves Baqend code which will be identified by the given bucket and code type
*
* @param type The entity type for the handler or the Name of the
* Baqend code
* @param codeType The type of the code
* @param fn Baqend code as a string
* @return The stored code as a string
*/
saveCode(type: ManagedType<any> | string, codeType: string, fn: string): Promise<string>;
/**
* Saves Baqend code which will be identified by the given bucket and code type
*
* @param type The entity type for the handler or the Name of the
* Baqend code
* @param codeType The type of the code
* @param fn Baqend code as a function
* @return The stored code as a parsed function
*/
saveCode(type: ManagedType<any> | string, codeType: string, fn: Function): Promise<Function>;
saveCode(type: ManagedType<any> | string, codeType: string, fn: Function | string): Promise<Function | string> {
const bucket = typeof type === 'string' ? type : type.name;
const msg = new message.SetBaqendCode(bucket, codeType)
.entity(fn instanceof Function ? this.functionToString(fn) : fn, 'text')
.responseType('text');
return this.entityManagerFactory.send(msg)
.then((response) => this.parseCode(bucket, codeType, fn instanceof Function, response.entity)!);
}
/**
* Deletes Baqend code identified by the given bucket and code type
*
* @param type The entity type for the handler or the Name of the
* Baqend code
* @param codeType The type of the code
* @return succeed if the code was deleted
*/
deleteCode(type: ManagedType<any> | string, codeType: string): Promise<any> {
const bucket = typeof type === 'string' ? type : type.name;
const msg = new message.DeleteBaqendCode(bucket, codeType);
return this.entityManagerFactory.send(msg)
.then(() => this.parseCode(bucket, codeType, false, null));
}
/**
* @param bucket
* @param codeType
* @param [asFunction=false]
* @param code
* @return
* @private
*/
parseCode(bucket: string, codeType: string, asFunction: boolean, code: string | null): string | null | Function {
if (codeType === 'validate') {
const type = this.metamodel.entity(bucket)!;
type.validationCode = code === null ? null : Validator.compile(type, code);
return asFunction ? type.validationCode : code;
}
return code && asFunction ? this.stringToFunction(['module', 'exports'], code) : code;
}
}