@tsed/formio
Version:
Formio package for Ts.ED framework
137 lines (107 loc) • 3.81 kB
text/typescript
import {AnyToPromise, AnyToPromiseStatus} from "@tsed/core";
import {Inject, InjectorService, Provider} from "@tsed/di";
import {FormioActionInfo} from "@tsed/formio-types";
import {PlatformContext, setResponseHeaders} from "@tsed/platform-http";
import {PlatformParams} from "@tsed/platform-params";
import {PlatformResponseFilter} from "@tsed/platform-response-filter";
import {EndpointMetadata} from "@tsed/schema";
import {Alter} from "../decorators/alter.js";
import {AlterHook} from "../domain/AlterHook.js";
import {SetActionItemMessage} from "../domain/FormioAction.js";
import {FormioActions} from "../domain/FormioActionsIndex.js";
import {FormioService} from "../services/FormioService.js";
("actions")
export class AlterActions implements AlterHook {
()
protected injector: InjectorService;
()
protected formio: FormioService;
()
protected params: PlatformParams;
()
protected responseFilter: PlatformResponseFilter;
transform(actions: FormioActions): FormioActions {
const {Action} = this.formio;
return this.getActions().reduce((actions, provider) => {
const instance = this.injector.invoke<any>(provider.token);
const options = provider.store.get<FormioActionInfo>("formio:action");
const resolveHandler = this.createHandler(provider, "resolve");
return {
...actions,
[options.name]: class extends Action {
static access = options.access;
static async info(req: any, res: any, next: Function) {
let opts = {...options};
if (instance.info) {
opts = await instance.info(opts, req, res);
}
next(null, opts);
}
static async settingsForm(req: any, res: any, next: Function) {
next(null, await instance.settingsForm(req, res));
}
resolve(handler: string, method: string, req: any, res: any, next: Function, setActionItemMessage: SetActionItemMessage): void {
resolveHandler(this, handler, method, req, res, next, setActionItemMessage);
}
}
};
}, actions);
}
protected getActions() {
return this.injector.getProviders("formio:action");
}
protected createHandler(provider: Provider, propertyKey: string | symbol) {
const compiledHandler = this.params.compileHandler({
token: provider.token,
propertyKey
});
return async (
action: any,
handler: string,
method: string,
req: any,
res: any,
next: any,
setActionItemMessage: SetActionItemMessage
) => {
const {$ctx} = req;
if ($ctx) {
$ctx.set("ACTION_CTX", {handler, method, setActionItemMessage, action});
$ctx.endpoint = EndpointMetadata.get(provider.useClass, "resolve");
try {
if (await this.onRequest(compiledHandler, $ctx)) {
next();
}
} catch (er) {
next(er);
}
}
};
}
private async onRequest(handler: any, $ctx: PlatformContext) {
const resolver = new AnyToPromise();
const {state, data, status, headers} = await resolver.call(() => handler({$ctx}));
if (state === AnyToPromiseStatus.RESOLVED) {
if (status) {
$ctx.response.status(status);
}
if (headers) {
$ctx.response.setHeaders(headers);
}
if (data !== undefined) {
$ctx.data = data;
return this.flush($ctx.data, $ctx);
}
return true;
}
}
private async flush(data: any, $ctx: PlatformContext) {
const {response} = $ctx;
if (!$ctx.isDone()) {
setResponseHeaders($ctx);
data = await this.responseFilter.transform(data, $ctx as any);
response.body(data);
}
return response;
}
}