@deepkit/framework
Version:
446 lines • 20.7 kB
JavaScript
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
const __ΩPick = ['T', 'K', 'Pick', 'l+e#!e"!fRb!b"Pde""N#!w#y'];
function __assignType(fn, args) {
fn.__type = args;
return fn;
}
/*
* Deepkit Framework
* Copyright (C) 2021 Deepkit UG, Marc J. Schmidt
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the MIT License.
*
* You should have received a copy of the MIT License along with this program.
*/
import { Config, Database, DebugControllerInterface, DebugRequest, decodeFrameData, decodeFrames, deserializeFrameData, Event, Filesystem, ModuleApi, ModuleImportedService, ModuleService, Route, RpcAction, RpcActionParameter, Workflow, } from '@deepkit/framework-debug-api';
import { rpc, rpcClass } from '@deepkit/rpc';
import { HttpRouter, parseRouteControllerAction } from '@deepkit/http';
import { changeClass, getClassName, isClass } from '@deepkit/core';
import { EventDispatcher, isEventListenerContainerEntryService } from '@deepkit/event';
import { DatabaseRegistry } from '@deepkit/orm';
import { existsSync, readFileSync, statSync, truncateSync } from 'fs';
import { join } from 'path';
import { FrameworkConfig } from '../module.config.js';
import { FileStopwatchStore } from './stopwatch/store.js';
import { Subject } from 'rxjs';
import { unlink } from 'fs/promises';
import { getScope, resolveToken } from '@deepkit/injector';
import { AppModule, ServiceContainer } from '@deepkit/app';
import { RpcControllers } from '../rpc.js';
import { isType, ReflectionClass, serializeType, stringifyType } from '@deepkit/type';
import { FilesystemRegistry } from '../filesystem.js';
import { FrameCategory, FrameType } from '@deepkit/stopwatch';
let DebugController = class DebugController {
constructor(serviceContainer, eventDispatcher, router, config, rpcControllers, databaseRegistry, filesystemRegistry, stopwatchStore) {
this.serviceContainer = serviceContainer;
this.eventDispatcher = eventDispatcher;
this.router = router;
this.config = config;
this.rpcControllers = rpcControllers;
this.databaseRegistry = databaseRegistry;
this.filesystemRegistry = filesystemRegistry;
this.stopwatchStore = stopwatchStore;
this.reservedTokenIds = (Map.Ω = [['Token', '"w!'], ['\'']], new Map());
this.idToTokenMap = (Map.Ω = [['\''], ['Token', '"w!']], new Map());
}
async subscribeStopwatchFramesData() {
if (!this.stopwatchStore || !this.stopwatchStore.frameDataChannel)
throw new Error('not enabled');
const subject = (Subject.Ω = [['W']], new Subject());
const close = await this.stopwatchStore.frameDataChannel.subscribe(__assignType((v) => {
subject.next(v);
}, ['v', '', 'P"2!"/"']));
subject.subscribe().add(() => {
close();
});
return subject;
}
async subscribeStopwatchFrames() {
if (!this.stopwatchStore || !this.stopwatchStore.frameChannel)
throw new Error('not enabled');
const subject = (Subject.Ω = [['W']], new Subject());
const close = await this.stopwatchStore.frameChannel.subscribe(__assignType((v) => {
subject.next(v);
}, ['v', '', 'P"2!"/"']));
subject.subscribe().add(() => {
close();
});
return subject;
}
resetProfilerFrames() {
const path = join(this.config.varPath, this.config.debugStorePath);
unlink(join(path, 'frames.bin')).catch();
unlink(join(path, 'frames-data.bin')).catch();
}
getProfilerFrames() {
const framesPath = join(this.config.varPath, this.config.debugStorePath, 'frames.bin');
const frameDataPath = join(this.config.varPath, this.config.debugStorePath, 'frames-data.bin');
const analyticsPath = join(this.config.varPath, this.config.debugStorePath, 'analytics.bin');
for (const file of [framesPath, frameDataPath, analyticsPath]) {
try {
const stat = statSync(file);
if (stat.size > 1000000) {
//make sure that file is not too big
truncateSync(file);
}
}
catch { }
}
return [
existsSync(framesPath) ? readFileSync(framesPath) : new Uint8Array(),
existsSync(frameDataPath) ? readFileSync(frameDataPath) : new Uint8Array(),
existsSync(frameDataPath) ? readFileSync(frameDataPath) : new Uint8Array(),
];
}
getFrames() {
const framesPath = join(this.config.varPath, this.config.debugStorePath, 'frames.bin');
return readFileSync(framesPath);
}
getFramesData() {
const frameDataPath = join(this.config.varPath, this.config.debugStorePath, 'frames-data.bin');
return readFileSync(frameDataPath);
}
httpRequests() {
const requests = {};
decodeFrames(this.getFrames(), __assignType((frame) => {
if (frame.type === FrameType.start) {
if (frame.category !== FrameCategory.http)
return;
requests[frame.cid] = new DebugRequest(frame.cid, frame.timestamp, '', '', '');
}
else if (frame.type === FrameType.end) {
const r = requests[frame.cid];
if (!r)
return;
r.ended = frame.timestamp;
}
}, ['frame', '', 'P"2!"/"']));
decodeFrameData(this.getFramesData(), __assignType((frame) => {
const r = requests[frame.cid];
if (!r)
return;
const data = deserializeFrameData(frame);
if (data.clientIp)
r.clientIp = data.clientIp;
if (data.method)
r.method = data.method;
if (data.url)
r.url = data.url;
if (data.responseStatus)
r.statusCode = data.responseStatus;
}, ['frame', '', 'P"2!"/"']));
return Object.values(requests);
}
databases() {
if (!this.databaseRegistry)
return [];
const databases = [];
for (const db of this.databaseRegistry.getDatabases()) {
const entities = [];
for (const classSchema of db.entityRegistry.all()) {
entities.push({ name: classSchema.name, className: classSchema.getClassName() });
}
databases.push({ name: db.name, entities, adapter: db.adapter.getName() });
}
return databases;
}
filesystems() {
const filesystems = [];
for (const fs of this.filesystemRegistry.getFilesystems()) {
filesystems.push({ name: getClassName(fs), adapter: getClassName(fs.adapter), options: {} });
}
return filesystems;
}
events() {
const events = [];
for (const token of this.eventDispatcher.getTokens()) {
const listeners = this.eventDispatcher.getListeners(token);
for (const listener of listeners) {
if (isEventListenerContainerEntryService(listener)) {
events.push({
event: token.id,
controller: getClassName(listener.classType),
methodName: listener.methodName,
priority: listener.order,
});
}
}
}
return events;
}
routes() {
const routes = [];
for (const route of this.router.getRoutes()) {
const routeD = {
path: route.getFullPath(),
httpMethods: route.httpMethods,
parameters: [],
groups: route.groups,
category: route.category,
controller: route.action.type === 'controller' ? getClassName(route.action.controller) + '.' + route.action.methodName : route.action.fn.name,
description: route.description,
};
const parsedRoute = parseRouteControllerAction(route);
const queryParameters = [];
for (const parameter of parsedRoute.getParameters()) {
if (parameter.body || parameter.bodyValidation) {
routeD.bodyType = stringifyType(parameter.getType());
}
else if (parameter.query) {
routeD.parameters.push({
name: parameter.getName(),
type: 'query',
stringType: stringifyType(parameter.parameter.parameter),
});
queryParameters.push(`${parameter.getName()}=TODO`);
// queryParameters.push(`${parameter.getName()}=${stringifyType(parameter.parameter.type)}`);
}
else if (parameter.isPartOfPath()) {
routeD.parameters.push({
name: parameter.getName(),
type: 'url',
stringType: stringifyType(parameter.parameter.parameter),
});
}
else {
//its a dependency injection token
}
}
if (queryParameters.length) {
routeD.path += '?' + queryParameters.join('&');
}
routes.push(routeD);
}
return routes;
}
configuration() {
const appConfig = [];
if (this.serviceContainer.appModule.configDefinition) {
const schema = ReflectionClass.from(this.serviceContainer.appModule.configDefinition);
for (const [name, value] of Object.entries(this.serviceContainer.appModule.getConfig())) {
const property = schema.getProperty(name);
appConfig.push({
name: name,
value: value,
defaultValue: property.getDefaultValue(),
description: property.getDescription(),
type: stringifyType(property.property),
});
}
}
const modulesConfig = [];
for (const module of this.serviceContainer.appModule.getImports()) {
if (!module.configDefinition)
continue;
const schema = ReflectionClass.from(module.configDefinition);
for (const [name, value] of Object.entries(module.getConfig())) {
const property = schema.getProperty(name);
modulesConfig.push({
name: module.getName() + '.' + name,
value: value,
defaultValue: property.getDefaultValue(),
description: property.getDescription(),
type: stringifyType(property.property),
});
}
}
return changeClass({
appConfig, modulesConfig,
}, Config);
}
actions() {
const result = [];
for (const { controller } of this.rpcControllers.controllers.values()) {
const rpcConfig = rpcClass._fetch(controller);
if (!rpcConfig)
continue;
for (const action of rpcConfig.actions.values()) {
const parameters = [];
for (const parameter of ReflectionClass.from(controller).getMethodParameters(action.name || '')) {
parameters.push(new RpcActionParameter(parameter.name, stringifyType(parameter.parameter)));
}
result.push({
path: rpcConfig.getPath(),
controller: getClassName(controller),
methodName: action.name || '',
parameters: parameters,
});
}
}
return result;
}
getWorkflow(name) {
const w = this.serviceContainer.workflowRegistry.get(name);
return changeClass({
places: Object.keys(w.places),
transitions: w.transitions,
}, Workflow);
}
// @rpc.action()
// httpRequests(): Promise<Collection<DebugRequest>> {
// return this.liveDatabase.query(DebugRequest).find();
// }
modules() {
const injectorContext = this.serviceContainer.getInjectorContext();
const getTokenId = __assignType((token) => {
const found = this.reservedTokenIds.get(token);
if (found === undefined) {
const id = this.reservedTokenIds.size;
this.idToTokenMap.set(id, token);
this.reservedTokenIds.set(token, id);
return id;
}
return found;
}, ['Token', 'token', '', 'P"w!2"\'/#']);
function getTokenLabel(token) {
if (isClass(token))
return getClassName(token);
if (isType(token))
return stringifyType(token);
return String(token);
}
getTokenLabel.__type = ['Token', 'token', 'getTokenLabel', 'P"w!2"&/#'];
function extract(module) {
const moduleApi = new ModuleApi(module.name, module.id, getClassName(module));
moduleApi.config = module.getConfig();
if (module.configDefinition) {
moduleApi.configSchemas = serializeType(ReflectionClass.from(module.configDefinition).type);
}
for (const provider of module.getProviders()) {
const token = resolveToken(provider);
const service = new ModuleService(getTokenId(token), getTokenLabel(token));
service.scope = getScope(provider);
service.instantiations = injectorContext.instantiationCount(token, module, service.scope);
if (isClass(token) && module.controllers.includes(token)) {
service.type = 'controller';
}
else if (isClass(token) && module.listeners.includes(token)) {
service.type = 'listener';
}
moduleApi.services.push(service);
service.exported = module.isExported(token);
service.forRoot = module.root;
}
const builtPreparedProviders = module.getBuiltPreparedProviders();
if (builtPreparedProviders) {
for (const preparedProvider of builtPreparedProviders) {
const token = preparedProvider.token;
//We want to know which token has been imported by whom
if (preparedProvider.modules[0] !== module) {
//was imported from originally preparedProvider.modules[0]
moduleApi.importedServices.push(new ModuleImportedService(getTokenId(token), getTokenLabel(token), getClassName(preparedProvider.modules[0])));
}
else if (preparedProvider.modules.length > 1) {
//was imported and overwritten by this module
moduleApi.importedServices.push(new ModuleImportedService(getTokenId(token), getTokenLabel(token), getClassName(preparedProvider.modules[1])));
}
}
}
for (const m of module.getImports()) {
moduleApi.imports.push(extract(m));
}
return moduleApi;
}
extract.__type = [() => AppModule, 'module', () => ModuleApi, 'extract', 'PP"7!2"P7#/$'];
return extract(this.serviceContainer.appModule);
}
};
DebugController.__type = ['reservedTokenIds', function () { return (Map.Ω = [['Token', '"w!'], ['\'']], new Map()); }, 'idToTokenMap', function () { return (Map.Ω = [['\''], ['Token', '"w!']], new Map()); }, () => ServiceContainer, 'serviceContainer', () => EventDispatcher, 'eventDispatcher', () => HttpRouter, 'router', () => __ΩPick, () => FrameworkConfig, "varPath", "debugStorePath", 'config', () => RpcControllers, 'rpcControllers', () => DatabaseRegistry, 'databaseRegistry', () => FilesystemRegistry, 'filesystemRegistry', () => FileStopwatchStore, 'stopwatchStore', 'constructor', () => Subject, 'subscribeStopwatchFramesData', () => Subject, 'subscribeStopwatchFrames', 'resetProfilerFrames', 'getProfilerFrames', 'getFrames', 'getFramesData', () => DebugRequest, 'httpRequests', () => Database, 'databases', () => Filesystem, 'filesystems', () => Event, 'events', () => Route, 'routes', () => Config, 'configuration', () => RpcAction, 'actions', 'name', () => Workflow, 'getWorkflow', () => ModuleApi, 'modules', 'DebugController', '!3!<>"!3#<>$PP7%2&<P7\'2(<P7)2*<P7,P.-..Jo+#2/<P7021<P7223<P7425<P76278<"08PPW79`0:PPW7;`0<P$0=PPWWWG0>P"0?<P"0@<PP7AF0BPP7CF0DPP7EF0FPP7GF0HPP7IF0JPP7K0LPP7MF0NP&2OP7P0QPP7R0S5!x"wT'];
__decorate([
rpc.action(),
__metadata("design:type", Function),
__metadata("design:paramtypes", []),
__metadata("design:returntype", Promise)
], DebugController.prototype, "subscribeStopwatchFramesData", null);
__decorate([
rpc.action(),
__metadata("design:type", Function),
__metadata("design:paramtypes", []),
__metadata("design:returntype", Promise)
], DebugController.prototype, "subscribeStopwatchFrames", null);
__decorate([
rpc.action(),
__metadata("design:type", Function),
__metadata("design:paramtypes", []),
__metadata("design:returntype", void 0)
], DebugController.prototype, "resetProfilerFrames", null);
__decorate([
rpc.action(),
__metadata("design:type", Function),
__metadata("design:paramtypes", []),
__metadata("design:returntype", Array)
], DebugController.prototype, "getProfilerFrames", null);
__decorate([
rpc.action(),
__metadata("design:type", Function),
__metadata("design:paramtypes", []),
__metadata("design:returntype", Array)
], DebugController.prototype, "httpRequests", null);
__decorate([
rpc.action(),
__metadata("design:type", Function),
__metadata("design:paramtypes", []),
__metadata("design:returntype", Array)
], DebugController.prototype, "databases", null);
__decorate([
rpc.action(),
__metadata("design:type", Function),
__metadata("design:paramtypes", []),
__metadata("design:returntype", Array)
], DebugController.prototype, "filesystems", null);
__decorate([
rpc.action(),
__metadata("design:type", Function),
__metadata("design:paramtypes", []),
__metadata("design:returntype", Array)
], DebugController.prototype, "events", null);
__decorate([
rpc.action(),
__metadata("design:type", Function),
__metadata("design:paramtypes", []),
__metadata("design:returntype", Array)
], DebugController.prototype, "routes", null);
__decorate([
rpc.action(),
__metadata("design:type", Function),
__metadata("design:paramtypes", []),
__metadata("design:returntype", Config)
], DebugController.prototype, "configuration", null);
__decorate([
rpc.action(),
__metadata("design:type", Function),
__metadata("design:paramtypes", []),
__metadata("design:returntype", Array)
], DebugController.prototype, "actions", null);
__decorate([
rpc.action(),
__metadata("design:type", Function),
__metadata("design:paramtypes", [String]),
__metadata("design:returntype", Workflow)
], DebugController.prototype, "getWorkflow", null);
__decorate([
rpc.action(),
__metadata("design:type", Function),
__metadata("design:paramtypes", []),
__metadata("design:returntype", ModuleApi)
], DebugController.prototype, "modules", null);
DebugController = __decorate([
rpc.controller(DebugControllerInterface),
__metadata("design:paramtypes", [ServiceContainer,
EventDispatcher,
HttpRouter, Object, RpcControllers,
DatabaseRegistry,
FilesystemRegistry,
FileStopwatchStore])
], DebugController);
export { DebugController };
//# sourceMappingURL=debug.controller.js.map