badmfck-api-server 3.0.7 → 3.0.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -34,6 +34,10 @@ export interface APIServiceOptions {
34
34
  interceptor?: IBaseEndpoint;
35
35
  postproducer?: (req: HTTPRequestVO | undefined | null, res: Response, data: TransferPacketVO<any>, requestTime: number, endpoint?: string, log?: APIServiceNetworkLogItem | null) => Promise<TransferPacketVO>;
36
36
  preproducer?: (req: HTTPRequestVO | undefined | null) => any;
37
+ access: {
38
+ monitor?: IMonitorUser[];
39
+ documentation?: IMonitorUser[];
40
+ };
37
41
  monitor?: IMonitorUser[];
38
42
  appVersion?: string;
39
43
  fileTempDir: string;
@@ -49,6 +53,7 @@ export declare const REQ_HTTP_SERVER: Req<void, {
49
53
  }>;
50
54
  export declare const REQ_INTERNAL_CALL: Req<HTTPRequestVO, IError | any>;
51
55
  export declare const REQ_MONITOR_USERS: Req<void, IMonitorUser[]>;
56
+ export declare const REQ_DOC_USERS: Req<void, IMonitorUser[]>;
52
57
  export declare function Initializer(services: IBaseService[]): Promise<void>;
53
58
  export declare class APIService extends BaseService {
54
59
  private static nextLogID;
@@ -26,7 +26,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
26
26
  return (mod && mod.__esModule) ? mod : { "default": mod };
27
27
  };
28
28
  Object.defineProperty(exports, "__esModule", { value: true });
29
- exports.APIService = exports.Initializer = exports.REQ_MONITOR_USERS = exports.REQ_INTERNAL_CALL = exports.REQ_HTTP_SERVER = exports.REQ_HTTP_REQUESTS_COUNT = exports.REQ_HTTP_LOG = exports.REQ_CREATE_NET_LOG = exports.getDefaultOptions = void 0;
29
+ exports.APIService = exports.Initializer = exports.REQ_DOC_USERS = exports.REQ_MONITOR_USERS = exports.REQ_INTERNAL_CALL = exports.REQ_HTTP_SERVER = exports.REQ_HTTP_REQUESTS_COUNT = exports.REQ_HTTP_LOG = exports.REQ_CREATE_NET_LOG = exports.getDefaultOptions = void 0;
30
30
  const express_1 = __importDefault(require("express"));
31
31
  const BaseService_1 = require("./BaseService");
32
32
  const cors_1 = __importDefault(require("cors"));
@@ -47,9 +47,15 @@ const StatService_1 = require("./StatService");
47
47
  const ExternalServiceEndpoint_1 = require("./external/ExternalServiceEndpoint");
48
48
  const MonitorService_1 = require("./MonitorService");
49
49
  const MysqlAdapter_1 = require("./db/MysqlAdapter");
50
+ const DocumentService_1 = require("./DocumentService");
51
+ const Documentation_1 = require("./documentation/Documentation");
50
52
  function getDefaultOptions() {
51
53
  return {
52
54
  port: 8091,
55
+ access: {
56
+ monitor: [],
57
+ documentation: [],
58
+ },
53
59
  baseEndPoint: '/api/',
54
60
  corsHostWhiteList: [
55
61
  'http://localhost:3000',
@@ -74,6 +80,7 @@ exports.REQ_HTTP_REQUESTS_COUNT = new badmfck_signal_1.Req(undefined, "REQ_HTTP_
74
80
  exports.REQ_HTTP_SERVER = new badmfck_signal_1.Req(undefined, "REQ_HTTP_SERVER");
75
81
  exports.REQ_INTERNAL_CALL = new badmfck_signal_1.Req(undefined, "REQ_INTERNAL_CALL");
76
82
  exports.REQ_MONITOR_USERS = new badmfck_signal_1.Req(undefined, "REQ_MONITOR_USERS");
83
+ exports.REQ_DOC_USERS = new badmfck_signal_1.Req(undefined, "REQ_MONITOR_USERS");
77
84
  const activeServices = [];
78
85
  async function Initializer(services) {
79
86
  services.push(new StatService_1.StatService());
@@ -89,7 +96,7 @@ async function Initializer(services) {
89
96
  exports.Initializer = Initializer;
90
97
  class APIService extends BaseService_1.BaseService {
91
98
  static nextLogID = 0;
92
- version = "3.0.7";
99
+ version = "3.0.9";
93
100
  options;
94
101
  monitor = null;
95
102
  monitorIndexFile;
@@ -106,11 +113,13 @@ class APIService extends BaseService_1.BaseService {
106
113
  if (!this.options.corsHostWhiteList.find(val => val === self))
107
114
  this.options.corsHostWhiteList.push();
108
115
  if (this.options.monitor && this.options.monitor.length > 0) {
109
- exports.REQ_MONITOR_USERS.listener = async () => this.options.monitor ?? [];
116
+ exports.REQ_MONITOR_USERS.listener = async () => this.options.access.monitor ?? this.options.monitor ?? [];
117
+ exports.REQ_DOC_USERS.listener = async () => this.options.access.documentation ?? [];
110
118
  this.monitor = new MonitorService_1.MonitorService();
111
119
  this.monitor.init();
112
120
  this.options.endpoints.push(new Monitor_1.Monitor());
113
121
  }
122
+ this.options.endpoints.push(new Documentation_1.Documentation());
114
123
  this.options.endpoints.push(new ExternalServiceEndpoint_1.ExternalServiceEndpoint());
115
124
  this.options.endpoints.push(new Liveness_1.Liveness(this.started), new Readiness_1.Readiness(this.started));
116
125
  exports.REQ_HTTP_REQUESTS_COUNT.listener = async () => this.requestsCount;
@@ -369,6 +378,7 @@ class APIService extends BaseService_1.BaseService {
369
378
  server.listen(this.options.port, () => {
370
379
  (0, LogService_1.logCrit)('${APIService.js}', 'API Service started at: ' + this.options.port + ", with base endpoint:" + this.options.baseEndPoint + ", ver.: " + this.version);
371
380
  });
381
+ new DocumentService_1.DocumentGenerator(this.options.endpoints);
372
382
  }
373
383
  async sendResponse(ref, res, data, requestTime, endpoint, log, req) {
374
384
  if (data.blockResponse) {
@@ -8,28 +8,38 @@ export interface IBaseEndpoint {
8
8
  }
9
9
  declare const httpMethods: string[];
10
10
  type HTTPMethod = typeof httpMethods[number];
11
- type IHandler = Record<HTTPMethod, ((req: HTTPRequestVO) => Promise<TransferPacketVO<any>>) | {
11
+ export type IHandler = Record<HTTPMethod, ((req: HTTPRequestVO) => Promise<TransferPacketVO<any>>) | {
12
12
  controller: (req: HTTPRequestVO) => Promise<TransferPacketVO<any>>;
13
13
  ignoreInterceptor?: boolean;
14
14
  allowInterceptorError?: boolean;
15
15
  validationModel?: any;
16
16
  asStream?: boolean;
17
+ ignoreInDocumentation?: boolean;
18
+ ignoreHttpLogging?: boolean;
19
+ description?: string;
20
+ title?: string;
17
21
  }>;
18
22
  export interface IEndpointHandler {
19
23
  endpoint: string;
20
24
  handler?: ((req: HTTPRequestVO) => Promise<TransferPacketVO<any>>) | IHandler;
21
25
  ignoreInterceptor?: boolean;
26
+ ignoreInDocumentation?: boolean;
27
+ ignoreHttpLogging?: boolean;
22
28
  independed?: boolean;
23
29
  allowInterceptorError?: boolean;
24
30
  asStream?: boolean;
31
+ description?: string;
32
+ title?: string;
25
33
  validationModel?: any;
26
34
  }
27
35
  export declare class BaseEndpoint implements IBaseEndpoint {
28
36
  private inializedEndpointNames;
37
+ description: string;
29
38
  endpoints?: IEndpointHandler[];
30
39
  ignoreHttpLogging: boolean;
40
+ ignoreInDocumentation: boolean;
31
41
  private static entrypoint;
32
- private endpoint;
42
+ endpoint: string;
33
43
  static setEntryPoint: (ep: string) => void;
34
44
  static getEntryPoint: () => string;
35
45
  constructor(endpoint: string);
@@ -11,8 +11,10 @@ const stream_1 = require("stream");
11
11
  const httpMethods = ["GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS", "HEAD", "TRACE", "CONNECT"];
12
12
  class BaseEndpoint {
13
13
  inializedEndpointNames = [];
14
+ description = "no description";
14
15
  endpoints;
15
16
  ignoreHttpLogging = false;
17
+ ignoreInDocumentation = false;
16
18
  static entrypoint = "/";
17
19
  endpoint = "";
18
20
  static setEntryPoint = (ep) => {
@@ -1,42 +1,9 @@
1
- declare type DocumentGeneratorConfig = {
2
- sourcePath: string;
3
- apiEndpoint: string;
4
- savePath: string;
5
- savePathFileName: string;
6
- };
7
- declare type DocumentGeneratorDocumentation = {
8
- [baseEndpointName: string]: {
9
- [endPointName: string]: DocumentGeneratorDocumentationEndpoint;
10
- };
11
- };
12
- declare type DocumentGeneratorDocumentationEndpoint = {
13
- handler: string;
14
- fullPath: string;
15
- ignoreInterceptor?: string;
16
- description?: string;
17
- parameters: DocumentGeneratorDocumentationEndpointParameter[];
18
- returns?: Omit<DocumentGeneratorDocumentationEndpointParameter, "optional">;
19
- example?: string[];
20
- throws?: Omit<DocumentGeneratorDocumentationEndpointParameter, "optional">[];
21
- };
22
- declare type DocumentGeneratorDocumentationEndpointParameter = {
23
- name: string;
24
- type: string;
25
- description: string;
26
- optional?: boolean;
27
- };
1
+ import { Req } from "badmfck-signal";
2
+ import { BaseEndpoint } from "./BaseEndpoint";
3
+ export declare const REQ_DOC: Req<void, Record<string, any>[]>;
28
4
  export declare class DocumentGenerator {
29
- private documentation;
30
- private config;
31
- constructor(config: DocumentGeneratorConfig);
32
- private getFiles;
33
- private getFileContent;
5
+ endpoints: BaseEndpoint[];
6
+ documentation: Record<string, any>[];
7
+ constructor(endpoints: BaseEndpoint[]);
34
8
  private generateDocumentation;
35
- private getCommentsByEndpoint;
36
- private parseEndPointComments;
37
- private tagToEndpoint;
38
- private tagModifications;
39
- private saveDocumentation;
40
- getDocumentation(): DocumentGeneratorDocumentation;
41
9
  }
42
- export {};
@@ -1,182 +1,58 @@
1
1
  "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || function (mod) {
19
- if (mod && mod.__esModule) return mod;
20
- var result = {};
21
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
- __setModuleDefault(result, mod);
23
- return result;
24
- };
25
2
  Object.defineProperty(exports, "__esModule", { value: true });
26
- exports.DocumentGenerator = void 0;
27
- const fs = __importStar(require("fs"));
28
- const path = __importStar(require("path"));
29
- const comment_parser_1 = require("comment-parser");
3
+ exports.DocumentGenerator = exports.REQ_DOC = void 0;
4
+ const badmfck_signal_1 = require("badmfck-signal");
5
+ const Validator_1 = require("./helper/Validator");
6
+ exports.REQ_DOC = new badmfck_signal_1.Req(undefined, "REQ_DOC");
30
7
  class DocumentGenerator {
31
- documentation = {};
32
- config;
33
- constructor(config) {
34
- this.config = config;
8
+ endpoints = [];
9
+ documentation = [];
10
+ constructor(endpoints) {
11
+ this.endpoints = endpoints;
35
12
  this.generateDocumentation();
36
- }
37
- getFiles() {
38
- return fs.readdirSync(this.config.sourcePath);
39
- }
40
- getFileContent(file) {
41
- return fs.readFileSync(path.resolve(this.config.sourcePath, file), "utf-8");
13
+ exports.REQ_DOC.listener = async () => this.documentation;
42
14
  }
43
15
  generateDocumentation = () => {
44
- for (const file of this.getFiles()) {
45
- const fileContent = this.getFileContent(file);
46
- const baseEndpoint = fileContent.match(/super\(['"](.*?)['"]\)/);
47
- if (!baseEndpoint) {
48
- console.error(`No base endpoint found in ${file}`);
16
+ for (let i of this.endpoints) {
17
+ if (i.ignoreInDocumentation || i.ignoreHttpLogging)
49
18
  continue;
50
- }
51
- const nodeEndpoint = this.config.apiEndpoint + "/" + baseEndpoint[1];
52
- const regex = /{\s*endpoint:\s*"(.*?)",\s*handler:\s*this\.(.*?)(?:,\s*ignoreInterceptor:\s*(true|false))?\s*}/g;
53
- const endpoints = fileContent.matchAll(regex);
54
- for (const match of endpoints) {
55
- const endpointName = match[1];
56
- const handler = match[2];
57
- const ignoreInterceptor = match[3];
58
- if (!this.documentation.hasOwnProperty(nodeEndpoint)) {
59
- this.documentation[nodeEndpoint] = {};
19
+ const branch = {
20
+ name: i.endpoint,
21
+ description: i.description,
22
+ endpoints: []
23
+ };
24
+ for (let j of i.endpoints || []) {
25
+ if (j.ignoreInDocumentation || j.ignoreHttpLogging)
26
+ continue;
27
+ const endpoint = {};
28
+ endpoint.name = j.endpoint;
29
+ endpoint.methods = {};
30
+ if (typeof j.handler === "function") {
31
+ const method = j.validationModel ? "POST" : "GET";
32
+ endpoint.methods[method] = {
33
+ title: j.title || "",
34
+ description: j.description,
35
+ parameters: Validator_1.Validator.documentStructure(j.validationModel),
36
+ authorized: !j.ignoreInterceptor
37
+ };
60
38
  }
61
- const endpoint = {
62
- handler,
63
- ignoreInterceptor,
64
- fullPath: nodeEndpoint + "/" + endpointName,
65
- description: "",
66
- parameters: [],
67
- };
68
- this.documentation[nodeEndpoint][endpointName] = this.parseEndPointComments(this.getCommentsByEndpoint(fileContent, handler), endpoint);
69
- }
70
- }
71
- this.saveDocumentation();
72
- console.log("Documentation generated and saved successfully");
73
- };
74
- getCommentsByEndpoint(fileContent, handler) {
75
- let comments = "";
76
- const regex = new RegExp(`(async )*${handler}(\\s*)\\(`, "g");
77
- const match = fileContent.match(regex);
78
- if (match) {
79
- const indexHandler = fileContent.indexOf(`${match[0]}`);
80
- if (indexHandler != -1) {
81
- const indexCommentStart = fileContent.lastIndexOf("/**", indexHandler);
82
- if (indexCommentStart != -1) {
83
- const indexCommentEnd = fileContent.indexOf("*/", indexCommentStart);
84
- if (indexCommentEnd != -1) {
85
- const commentsSubstring = fileContent.substring(indexCommentStart, indexCommentEnd + 2);
86
- if (commentsSubstring) {
87
- const regexToCheckCommentWithMethod = new RegExp(`${commentsSubstring.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}([\\s]*?)(async )*${handler}(\\s*)\\(`, "g");
88
- const matchToCheckCommentWithMethod = fileContent.match(regexToCheckCommentWithMethod);
89
- if (matchToCheckCommentWithMethod) {
90
- comments = commentsSubstring;
91
- }
92
- }
39
+ else if (typeof j.handler === "object") {
40
+ for (let method in j.handler) {
41
+ const handler = j.handler;
42
+ if (handler.ignoreInDocumentation || handler.ignoreHttpLogging)
43
+ continue;
44
+ endpoint.methods[method] = {
45
+ title: handler.title || j.title || "",
46
+ description: handler.description || j.description,
47
+ parameters: Validator_1.Validator.documentStructure(handler.validationModel),
48
+ authorized: !handler.ignoreInterceptor
49
+ };
93
50
  }
94
51
  }
52
+ branch.endpoints.push(endpoint);
95
53
  }
54
+ this.documentation.push(branch);
96
55
  }
97
- return comments;
98
- }
99
- parseEndPointComments(comments, endpoint) {
100
- if (comments) {
101
- const parsed = (0, comment_parser_1.parse)(comments, { spacing: "preserve" });
102
- if (parsed[0]) {
103
- const firstParsed = parsed[0];
104
- endpoint.description = this.tagModifications(firstParsed.description);
105
- firstParsed.tags.forEach((tag) => {
106
- endpoint = this.tagToEndpoint(tag, endpoint);
107
- });
108
- }
109
- }
110
- return endpoint;
111
- }
112
- tagToEndpoint(tag, endpoint) {
113
- switch (tag.tag) {
114
- case "param":
115
- endpoint.parameters.push({
116
- name: this.tagModifications(tag.name, "name"),
117
- type: tag.type,
118
- description: this.tagModifications(tag.description),
119
- optional: tag.optional,
120
- });
121
- break;
122
- case "description":
123
- endpoint.description = this.tagModifications(tag.description);
124
- break;
125
- case "example":
126
- if (!endpoint.example) {
127
- endpoint.example = [];
128
- }
129
- endpoint.example.push(this.tagModifications(tag.description));
130
- break;
131
- case "returns":
132
- endpoint.returns = {
133
- name: this.tagModifications(tag.name, "name"),
134
- type: tag.type,
135
- description: this.tagModifications(tag.description),
136
- };
137
- break;
138
- case "throws":
139
- if (!endpoint.throws) {
140
- endpoint.throws = [];
141
- }
142
- endpoint.throws.push({
143
- name: this.tagModifications(tag.name, "name"),
144
- type: tag.type,
145
- description: this.tagModifications(tag.description),
146
- });
147
- break;
148
- }
149
- return endpoint;
150
- }
151
- tagModifications(text, field = "description") {
152
- switch (field) {
153
- case "description":
154
- text = text
155
- .trim()
156
- .replace(/^(\-.)/, "")
157
- .trim();
158
- break;
159
- case "name":
160
- if (text === "-") {
161
- text = "";
162
- }
163
- break;
164
- }
165
- return text;
166
- }
167
- saveDocumentation() {
168
- const formatForSave = this.documentation;
169
- const filePath = this.config.savePath + this.config.savePathFileName;
170
- fs.writeFileSync(filePath, JSON.stringify(formatForSave, null, 2));
171
- }
172
- getDocumentation() {
173
- return this.documentation;
174
- }
56
+ };
175
57
  }
176
58
  exports.DocumentGenerator = DocumentGenerator;
177
- new DocumentGenerator({
178
- sourcePath: "./src/api",
179
- apiEndpoint: "api/v1",
180
- savePath: "./bin/",
181
- savePathFileName: "doc.json",
182
- });
@@ -0,0 +1,13 @@
1
+ /// <reference types="node" />
2
+ /// <reference types="node" />
3
+ import { BaseEndpoint } from "../BaseEndpoint";
4
+ import { HTTPRequestVO, TransferPacketVO } from "../structures/Interfaces";
5
+ export declare class Documentation extends BaseEndpoint {
6
+ indexHtmlFile: Buffer | null;
7
+ constructor();
8
+ json(req: HTTPRequestVO): Promise<{
9
+ data: Record<string, any>[];
10
+ }>;
11
+ html(req: HTTPRequestVO): Promise<TransferPacketVO<any>>;
12
+ checkAuthorization(req: HTTPRequestVO): Promise<void>;
13
+ }
@@ -0,0 +1,65 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.Documentation = void 0;
7
+ const APIService_1 = require("../APIService");
8
+ const BaseEndpoint_1 = require("../BaseEndpoint");
9
+ const DocumentService_1 = require("../DocumentService");
10
+ const DefaultErrors_1 = __importDefault(require("../structures/DefaultErrors"));
11
+ const crypto_1 = __importDefault(require("crypto"));
12
+ const fs_1 = __importDefault(require("fs"));
13
+ const path_1 = __importDefault(require("path"));
14
+ class Documentation extends BaseEndpoint_1.BaseEndpoint {
15
+ indexHtmlFile = null;
16
+ constructor() {
17
+ super("doc");
18
+ this.registerEndpoints([{
19
+ ignoreInDocumentation: true,
20
+ endpoint: "json",
21
+ handler: this.json,
22
+ ignoreInterceptor: true
23
+ },
24
+ {
25
+ ignoreInDocumentation: true,
26
+ endpoint: "html",
27
+ handler: this.html,
28
+ ignoreInterceptor: true
29
+ }]);
30
+ }
31
+ async json(req) {
32
+ this.checkAuthorization(req);
33
+ const doc = await DocumentService_1.REQ_DOC.request();
34
+ return { data: doc };
35
+ }
36
+ async html(req) {
37
+ if (!this.indexHtmlFile)
38
+ this.indexHtmlFile = fs_1.default.readFileSync(path_1.default.resolve(__dirname, "index.html"));
39
+ return {
40
+ rawResponse: true,
41
+ data: this.indexHtmlFile,
42
+ headers: {
43
+ "Content-Type": "text/html",
44
+ "Content-Length": this.indexHtmlFile.byteLength.toString()
45
+ }
46
+ };
47
+ }
48
+ async checkAuthorization(req) {
49
+ const users = await APIService_1.REQ_DOC_USERS.request();
50
+ if (!users || users.length == 0)
51
+ throw { ...DefaultErrors_1.default.UNAUTHORIZED, details: "No users found for documentation access" };
52
+ let header = req.headers['authorization'];
53
+ if (!header)
54
+ throw { ...DefaultErrors_1.default.UNAUTHORIZED, details: "No authorization header found" };
55
+ header = header.split(" ").pop() ?? "";
56
+ for (let i of users) {
57
+ const hash = crypto_1.default.createHash("sha256").update(i.login + ":" + i.password).digest("hex");
58
+ if (hash === header) {
59
+ return;
60
+ }
61
+ }
62
+ throw { ...DefaultErrors_1.default.UNAUTHORIZED, details: "Invalid user" };
63
+ }
64
+ }
65
+ exports.Documentation = Documentation;
@@ -7,6 +7,7 @@ const ExternalService_1 = require("./ExternalService");
7
7
  class ExternalServiceEndpoint extends BaseEndpoint_1.BaseEndpoint {
8
8
  constructor() {
9
9
  super("external");
10
+ this.ignoreInDocumentation = true;
10
11
  this.registerEndpoints([
11
12
  { endpoint: "call/:id", handler: this.handler, ignoreInterceptor: true }
12
13
  ]);
@@ -21,6 +21,7 @@ export declare enum ValidationReport {
21
21
  }
22
22
  export declare class Validator {
23
23
  static validateObject(fields: string[], object: any): boolean;
24
+ static documentStructure(structure: any): Record<string, any> | undefined;
24
25
  static validateStructure(structure: any, object: any, level?: number): Promise<string[] | undefined>;
25
26
  static filterStructure(structure: any, object: any): void;
26
27
  static convertToType<T>(value: any, type: "string" | "number" | "boolean" | "date"): T | null;
@@ -24,6 +24,32 @@ class Validator {
24
24
  }
25
25
  return true;
26
26
  }
27
+ static documentStructure(structure) {
28
+ const params = {};
29
+ if (!structure || typeof structure !== "object")
30
+ return;
31
+ for (let i in structure) {
32
+ if (i.startsWith("$__"))
33
+ continue;
34
+ let type = typeof structure[i];
35
+ let description = structure[i]['$__' + i] || "";
36
+ let childs = undefined;
37
+ let optional = structure[i]['$__optional_' + i] || "";
38
+ if (optional === undefined)
39
+ optional = structure[i] === null || structure[i] === undefined;
40
+ if (typeof structure[i] === "object")
41
+ childs = this.documentStructure(structure[i]);
42
+ if (structure[i] === "@")
43
+ type = "email";
44
+ params[i] = {
45
+ type: type,
46
+ description: description,
47
+ optional: optional,
48
+ childs: childs
49
+ };
50
+ }
51
+ return params;
52
+ }
27
53
  static async validateStructure(structure, object, level = 0) {
28
54
  if (!structure)
29
55
  return;
@@ -47,12 +73,23 @@ class Validator {
47
73
  let errors = [];
48
74
  let foundKeys = [];
49
75
  for (let i in structure) {
76
+ if (i.startsWith("$__")) {
77
+ foundKeys.push(i);
78
+ continue;
79
+ }
50
80
  if (structure[i] === null) {
51
81
  foundKeys.push(i);
52
82
  continue;
53
83
  }
54
- if (!(i in object))
55
- errors.push("no field '" + i + "'");
84
+ let optional = structure[i]['$__optional_' + i] || false;
85
+ if (!(i in object)) {
86
+ if (!optional)
87
+ errors.push("no field '" + i + "'");
88
+ else {
89
+ foundKeys.push(i);
90
+ continue;
91
+ }
92
+ }
56
93
  if (typeof structure[i] === "number" && typeof object[i] === "string") {
57
94
  let num = parseInt(object[i]);
58
95
  if (object[i].includes(","))
@@ -13,6 +13,7 @@ interface IStatObject {
13
13
  export declare const S_MONITOR_REGISTRATE_ACTION: Signal<IUserAction>;
14
14
  export declare class Monitor extends BaseEndpoint {
15
15
  ignoreHttpLogging: boolean;
16
+ ignoreInDocumentation: boolean;
16
17
  users: Map<string, IStatObject>;
17
18
  constructor();
18
19
  controllers(req: HTTPRequestVO): Promise<TransferPacketVO>;
@@ -15,6 +15,7 @@ const MonitorService_1 = require("../MonitorService");
15
15
  exports.S_MONITOR_REGISTRATE_ACTION = new badmfck_signal_1.Signal();
16
16
  class Monitor extends BaseEndpoint_1.BaseEndpoint {
17
17
  ignoreHttpLogging = true;
18
+ ignoreInDocumentation = true;
18
19
  users = new Map();
19
20
  constructor() {
20
21
  super("--sys-monitor");
@@ -7,6 +7,7 @@ class Liveness extends BaseEndpoint_1.BaseEndpoint {
7
7
  started;
8
8
  constructor(stated) {
9
9
  super("liveness");
10
+ this.ignoreInDocumentation = true;
10
11
  this.started = stated;
11
12
  this.registerEndpoints([{ endpoint: "", handler: this.checkLiveness, ignoreInterceptor: true }]);
12
13
  }
@@ -8,6 +8,7 @@ class Readiness extends BaseEndpoint_1.BaseEndpoint {
8
8
  constructor(stated) {
9
9
  super("readiness");
10
10
  this.started = stated;
11
+ this.ignoreInDocumentation = true;
11
12
  this.registerEndpoints([{ endpoint: "", handler: this.checkReadiness, ignoreInterceptor: true }]);
12
13
  }
13
14
  async checkReadiness(req) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "badmfck-api-server",
3
- "version": "3.0.7",
3
+ "version": "3.0.9",
4
4
  "description": "Simple API http server based on express",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",