@avleon/core 0.0.45 → 0.0.46
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.
- package/License +21 -21
- package/README.md +667 -681
- package/dist/application.test.js +15 -0
- package/dist/controller.test.js +0 -14
- package/dist/core/application.d.ts +74 -0
- package/dist/core/application.js +424 -0
- package/dist/core/router.d.ts +44 -0
- package/dist/core/router.js +520 -0
- package/dist/core/testing.d.ts +21 -0
- package/dist/core/testing.js +104 -0
- package/dist/core/types.d.ts +67 -0
- package/dist/core/types.js +2 -0
- package/dist/event-dispatcher.d.ts +0 -1
- package/dist/event-dispatcher.js +4 -7
- package/dist/file-storage.test.js +15 -2
- package/dist/helpers.d.ts +9 -42
- package/dist/helpers.js +19 -411
- package/dist/index.d.ts +17 -15
- package/dist/index.js +18 -22
- package/dist/interfaces/avleon-application.d.ts +74 -26
- package/dist/interfaces/avleon-application.js +1 -0
- package/dist/middleware.d.ts +11 -4
- package/dist/middleware.js +9 -0
- package/dist/multipart.d.ts +2 -2
- package/dist/openapi.d.ts +70 -3
- package/dist/openapi.js +32 -0
- package/dist/params.js +1 -1
- package/dist/params.test.js +8 -8
- package/dist/route-methods.js +16 -5
- package/dist/swagger-schema.d.ts +11 -17
- package/dist/swagger-schema.js +84 -82
- package/dist/swagger-schema.test.js +32 -12
- package/dist/utils/common-utils.d.ts +17 -0
- package/dist/utils/common-utils.js +108 -0
- package/dist/utils/di-utils.d.ts +1 -0
- package/dist/utils/di-utils.js +22 -0
- package/dist/utils/hash.d.ts +0 -2
- package/dist/utils/hash.js +1 -5
- package/dist/utils/object-utils.d.ts +11 -0
- package/dist/utils/object-utils.js +198 -0
- package/dist/utils/validation-utils.d.ts +13 -0
- package/dist/utils/validation-utils.js +119 -0
- package/dist/validation.js +1 -4
- package/dist/websocket.d.ts +3 -0
- package/dist/websocket.js +2 -1
- package/package.json +53 -40
- package/dist/application.d.ts +0 -47
- package/dist/application.js +0 -50
- package/dist/icore.d.ts +0 -226
- package/dist/icore.js +0 -968
- package/dist/icore.test.js +0 -14
- package/dist/testing.d.ts +0 -55
- package/dist/testing.js +0 -196
- /package/dist/{icore.test.d.ts → application.test.d.ts} +0 -0
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @copyright 2024
|
|
3
|
+
* @author Tareq Hossain
|
|
4
|
+
* @email xtrinsic96@gmail.com
|
|
5
|
+
* @url https://github.com/xtareq
|
|
6
|
+
*/
|
|
7
|
+
import { FastifyRequest, FastifyReply } from "fastify";
|
|
8
|
+
import { MultipartFile } from "../multipart";
|
|
9
|
+
import { OpenApiUiOptions } from "../openapi";
|
|
10
|
+
import { IAvleonApplication, AvleonApplicationOptions, CorsOptions, GlobalOptions, AutoControllerOptions, TestApplication, TestResponse } from "../interfaces/avleon-application";
|
|
11
|
+
export { IAvleonApplication, AvleonApplicationOptions, CorsOptions, GlobalOptions, AutoControllerOptions, TestApplication, TestResponse };
|
|
12
|
+
export interface IRequest extends Omit<FastifyRequest, "files" | "formData" | "file" | "saveRequestFiles"> {
|
|
13
|
+
params: any;
|
|
14
|
+
query: any;
|
|
15
|
+
body: any;
|
|
16
|
+
headers: any;
|
|
17
|
+
user?: any;
|
|
18
|
+
formData?: any;
|
|
19
|
+
file?: MultipartFile;
|
|
20
|
+
files?: MultipartFile[];
|
|
21
|
+
saveRequestFiles?: (options?: any) => Promise<MultipartFile[]>;
|
|
22
|
+
_argsCache?: Map<string, any[]>;
|
|
23
|
+
}
|
|
24
|
+
export interface IResponse extends FastifyReply {
|
|
25
|
+
}
|
|
26
|
+
export interface ParamMetaOptions {
|
|
27
|
+
index: number;
|
|
28
|
+
key: string;
|
|
29
|
+
name: string;
|
|
30
|
+
required: boolean;
|
|
31
|
+
validate: boolean;
|
|
32
|
+
dataType: any;
|
|
33
|
+
validatorClass: boolean;
|
|
34
|
+
schema?: any;
|
|
35
|
+
type: "route:param" | "route:query" | "route:body" | "route:header" | "route:user" | "route:file" | "route:files";
|
|
36
|
+
}
|
|
37
|
+
export interface ParamMetaFilesOptions {
|
|
38
|
+
index: number;
|
|
39
|
+
type: "route:files";
|
|
40
|
+
files: MultipartFile[];
|
|
41
|
+
fieldName: string;
|
|
42
|
+
}
|
|
43
|
+
export interface MethodParamMeta {
|
|
44
|
+
request: any[];
|
|
45
|
+
params: ParamMetaOptions[];
|
|
46
|
+
query: ParamMetaOptions[];
|
|
47
|
+
body: ParamMetaOptions[];
|
|
48
|
+
headers: ParamMetaOptions[];
|
|
49
|
+
currentUser: ParamMetaOptions[];
|
|
50
|
+
swagger?: OpenApiUiOptions;
|
|
51
|
+
file?: any[];
|
|
52
|
+
files?: ParamMetaFilesOptions[];
|
|
53
|
+
}
|
|
54
|
+
export interface IRoute {
|
|
55
|
+
url: string;
|
|
56
|
+
method: string;
|
|
57
|
+
controller: string;
|
|
58
|
+
}
|
|
59
|
+
export type FuncRoute = {
|
|
60
|
+
handler: Function;
|
|
61
|
+
middlewares: any[];
|
|
62
|
+
schema: any;
|
|
63
|
+
};
|
|
64
|
+
export type StaticFileOptions = {
|
|
65
|
+
path?: string;
|
|
66
|
+
prefix?: string;
|
|
67
|
+
};
|
|
@@ -11,7 +11,6 @@ export type DispatchOptions = {
|
|
|
11
11
|
retry?: number;
|
|
12
12
|
retryDelay?: number;
|
|
13
13
|
};
|
|
14
|
-
export declare function sleep(ms: number): Promise<unknown>;
|
|
15
14
|
export declare class EventDispatcher {
|
|
16
15
|
private readonly _context;
|
|
17
16
|
constructor(_context: SocketContextService);
|
package/dist/event-dispatcher.js
CHANGED
|
@@ -10,11 +10,11 @@ var __metadata = (this && this.__metadata) || function (k, v) {
|
|
|
10
10
|
};
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
12
|
exports.EventDispatcher = exports.SocketContextService = void 0;
|
|
13
|
-
exports.sleep = sleep;
|
|
14
13
|
exports.Dispatch = Dispatch;
|
|
15
14
|
const typedi_1 = require("typedi");
|
|
16
|
-
const
|
|
15
|
+
const websocket_1 = require("./websocket");
|
|
17
16
|
const node_async_hooks_1 = require("node:async_hooks");
|
|
17
|
+
const helpers_1 = require("./helpers");
|
|
18
18
|
let SocketContextService = class SocketContextService {
|
|
19
19
|
constructor() {
|
|
20
20
|
this.storage = new node_async_hooks_1.AsyncLocalStorage();
|
|
@@ -31,9 +31,6 @@ exports.SocketContextService = SocketContextService;
|
|
|
31
31
|
exports.SocketContextService = SocketContextService = __decorate([
|
|
32
32
|
(0, typedi_1.Service)()
|
|
33
33
|
], SocketContextService);
|
|
34
|
-
function sleep(ms) {
|
|
35
|
-
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
36
|
-
}
|
|
37
34
|
let EventDispatcher = class EventDispatcher {
|
|
38
35
|
constructor(_context) {
|
|
39
36
|
this._context = _context;
|
|
@@ -50,7 +47,7 @@ let EventDispatcher = class EventDispatcher {
|
|
|
50
47
|
catch (err) {
|
|
51
48
|
if (attempt === retryCount)
|
|
52
49
|
throw err;
|
|
53
|
-
await sleep(delay * (attempt + 1));
|
|
50
|
+
await (0, helpers_1.sleep)(delay * (attempt + 1));
|
|
54
51
|
}
|
|
55
52
|
}
|
|
56
53
|
}
|
|
@@ -59,7 +56,7 @@ let EventDispatcher = class EventDispatcher {
|
|
|
59
56
|
const transports = (_a = options.transports) !== null && _a !== void 0 ? _a : ["socket"];
|
|
60
57
|
for (const transport of transports) {
|
|
61
58
|
if (transport === "socket") {
|
|
62
|
-
const io = typedi_1.Container.get(
|
|
59
|
+
const io = typedi_1.Container.get(websocket_1.SocketIoServer);
|
|
63
60
|
const context = typedi_1.Container.get(SocketContextService);
|
|
64
61
|
const socket = context.getSocket();
|
|
65
62
|
if (options.broadcast && socket) {
|
|
@@ -31,7 +31,10 @@ describe("FileStorage", () => {
|
|
|
31
31
|
});
|
|
32
32
|
describe("save", () => {
|
|
33
33
|
it("should save a file successfully", async () => {
|
|
34
|
-
await expect(fileStorage.save(testFile)).resolves.toEqual(
|
|
34
|
+
await expect(fileStorage.save(testFile)).resolves.toEqual({
|
|
35
|
+
uploadPath: "/uploads/test.txt",
|
|
36
|
+
staticPath: "/static/test.txt",
|
|
37
|
+
});
|
|
35
38
|
});
|
|
36
39
|
it("should throw SystemUseError if file exists and overwrite is false", async () => {
|
|
37
40
|
mockFs.existsSync.mockReturnValue(true);
|
|
@@ -61,7 +64,16 @@ describe("FileStorage", () => {
|
|
|
61
64
|
{ ...testFile, filename: "a.txt" },
|
|
62
65
|
{ ...testFile, filename: "b.txt" },
|
|
63
66
|
];
|
|
64
|
-
await expect(fileStorage.saveAll(files)).resolves.toEqual(
|
|
67
|
+
await expect(fileStorage.saveAll(files)).resolves.toEqual([
|
|
68
|
+
{
|
|
69
|
+
uploadPath: "/uploads/a.txt",
|
|
70
|
+
staticPath: "/static/a.txt",
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
uploadPath: "/uploads/b.txt",
|
|
74
|
+
staticPath: "/static/b.txt",
|
|
75
|
+
},
|
|
76
|
+
]);
|
|
65
77
|
});
|
|
66
78
|
it("should throw SystemUseError on error", async () => {
|
|
67
79
|
promises_1.pipeline.mockImplementationOnce(() => {
|
|
@@ -96,6 +108,7 @@ describe("FileStorage", () => {
|
|
|
96
108
|
expect(mockFs.mkdirSync).toHaveBeenCalled();
|
|
97
109
|
});
|
|
98
110
|
it("should not create directory if exists", async () => {
|
|
111
|
+
mockFs.mkdirSync.mockClear();
|
|
99
112
|
mockFs.existsSync.mockReturnValue(true);
|
|
100
113
|
await fileStorage["ensureDirectoryExists"]("public/test.txt");
|
|
101
114
|
expect(mockFs.mkdirSync).not.toHaveBeenCalled();
|
package/dist/helpers.d.ts
CHANGED
|
@@ -1,44 +1,11 @@
|
|
|
1
|
-
export declare const uuid: `${string}-${string}-${string}-${string}-${string}`;
|
|
2
|
-
export declare function inject<T>(cls: new (...args: any[]) => T): T;
|
|
3
|
-
export type Constructor<T = any> = new (...args: any[]) => T;
|
|
4
|
-
export declare function isConstructor(func: any): boolean;
|
|
5
|
-
export declare function formatUrl(path: string): string;
|
|
6
|
-
export declare function parsedPath(ipath: string): string;
|
|
7
|
-
export declare const isClassValidator: (target: Constructor) => boolean;
|
|
8
|
-
export interface MatchLocation {
|
|
9
|
-
line: number;
|
|
10
|
-
column: number;
|
|
11
|
-
}
|
|
12
|
-
export declare const getLineNumber: (filePath: string, rpath: string | RegExp) => MatchLocation[] | null;
|
|
13
|
-
export declare function normalizePath(base?: string, subPath?: string): string;
|
|
14
|
-
export declare function extrctParamFromUrl(url: string): {
|
|
15
|
-
key: string;
|
|
16
|
-
required: boolean;
|
|
17
|
-
}[];
|
|
18
|
-
export declare function findDuplicates(arr: string[]): string[];
|
|
19
|
-
export declare function getDataType(expectedType: any): any;
|
|
20
|
-
export declare function isValidType(value: any, expectedType: any): boolean;
|
|
21
|
-
export declare function isValidJsonString(value: string): object | boolean;
|
|
22
|
-
export declare function jsonToJs(value: string): any;
|
|
23
|
-
export declare function jsonToInstance(value: string, instance: Constructor): any;
|
|
24
|
-
export declare function transformObjectByInstanceToObject(instance: Constructor, value: object): Record<string, any>;
|
|
25
|
-
export declare const isClassValidatorClass: (target: Constructor) => boolean;
|
|
26
|
-
export declare function validateObjectByInstance(target: Constructor, value?: object, options?: "object" | "array"): Promise<any>;
|
|
27
|
-
type ValidationError = {
|
|
28
|
-
count: number;
|
|
29
|
-
errors: any;
|
|
30
|
-
};
|
|
31
|
-
export declare function validateRequestBody(target: Constructor, value: object, options?: "object" | "array"): ValidationError;
|
|
32
|
-
export declare function pick<T extends object>(obj: T, paths: string[]): Partial<T>;
|
|
33
|
-
export declare function exclude<T extends object>(obj: T | T[], paths: string[]): Partial<T> | Partial<T>[];
|
|
34
|
-
export declare function autoCast(value: any, typeHint?: any, schema?: any): any;
|
|
35
1
|
/**
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
* - filter[tags][]=a&filter[tags][]=b
|
|
41
|
-
* - filter=name&filter=sorna
|
|
2
|
+
* @copyright 2024
|
|
3
|
+
* @author Tareq Hossain
|
|
4
|
+
* @email xtrinsic96@gmail.com
|
|
5
|
+
* @url https://github.com/xtareq
|
|
42
6
|
*/
|
|
43
|
-
export
|
|
44
|
-
export
|
|
7
|
+
export * from "./utils/common-utils";
|
|
8
|
+
export * from "./utils/object-utils";
|
|
9
|
+
export * from "./utils/validation-utils";
|
|
10
|
+
export * from "./utils/di-utils";
|
|
11
|
+
export * from "./validation";
|
package/dist/helpers.js
CHANGED
|
@@ -1,419 +1,27 @@
|
|
|
1
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.isClassValidatorClass = exports.getLineNumber = exports.isClassValidator = exports.uuid = void 0;
|
|
7
|
-
exports.inject = inject;
|
|
8
|
-
exports.isConstructor = isConstructor;
|
|
9
|
-
exports.formatUrl = formatUrl;
|
|
10
|
-
exports.parsedPath = parsedPath;
|
|
11
|
-
exports.normalizePath = normalizePath;
|
|
12
|
-
exports.extrctParamFromUrl = extrctParamFromUrl;
|
|
13
|
-
exports.findDuplicates = findDuplicates;
|
|
14
|
-
exports.getDataType = getDataType;
|
|
15
|
-
exports.isValidType = isValidType;
|
|
16
|
-
exports.isValidJsonString = isValidJsonString;
|
|
17
|
-
exports.jsonToJs = jsonToJs;
|
|
18
|
-
exports.jsonToInstance = jsonToInstance;
|
|
19
|
-
exports.transformObjectByInstanceToObject = transformObjectByInstanceToObject;
|
|
20
|
-
exports.validateObjectByInstance = validateObjectByInstance;
|
|
21
|
-
exports.validateRequestBody = validateRequestBody;
|
|
22
|
-
exports.pick = pick;
|
|
23
|
-
exports.exclude = exclude;
|
|
24
|
-
exports.autoCast = autoCast;
|
|
25
|
-
exports.normalizeQueryDeep = normalizeQueryDeep;
|
|
26
2
|
/**
|
|
27
3
|
* @copyright 2024
|
|
28
4
|
* @author Tareq Hossain
|
|
29
5
|
* @email xtrinsic96@gmail.com
|
|
30
6
|
* @url https://github.com/xtareq
|
|
31
7
|
*/
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
throw new system_exception_1.SystemUseError("Not a project class. Maybe you wanna register it first.");
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
function isConstructor(func) {
|
|
49
|
-
if (typeof func !== "function") {
|
|
50
|
-
return false;
|
|
51
|
-
}
|
|
52
|
-
if (func === Function.prototype.bind || func instanceof RegExp) {
|
|
53
|
-
return false;
|
|
54
|
-
}
|
|
55
|
-
if (func.prototype && typeof func.prototype === "object") {
|
|
56
|
-
return true;
|
|
57
|
-
}
|
|
58
|
-
try {
|
|
59
|
-
const instance = new func();
|
|
60
|
-
return typeof instance === "object";
|
|
61
|
-
}
|
|
62
|
-
catch (e) {
|
|
63
|
-
return false;
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
function formatUrl(path) {
|
|
67
|
-
if (typeof path !== "string") {
|
|
68
|
-
throw new Error("The path must be a string");
|
|
69
|
-
}
|
|
70
|
-
path = path.trim();
|
|
71
|
-
if (!path.startsWith("/")) {
|
|
72
|
-
path = "/" + path;
|
|
73
|
-
}
|
|
74
|
-
path = path.replace(/\/\/+/g, "/");
|
|
75
|
-
if (path.endsWith("/")) {
|
|
76
|
-
path = path.slice(0, -1);
|
|
77
|
-
}
|
|
78
|
-
return path;
|
|
79
|
-
}
|
|
80
|
-
function parsedPath(ipath) {
|
|
81
|
-
return !ipath.startsWith("/") ? "/" + ipath : ipath;
|
|
82
|
-
}
|
|
83
|
-
const isClassValidator = (target) => {
|
|
84
|
-
try {
|
|
85
|
-
const clsval = require("class-validator");
|
|
86
|
-
const result = (0, class_validator_1.getMetadataStorage)().getTargetValidationMetadatas(target, "", false, false);
|
|
87
|
-
return result.length > 0;
|
|
88
|
-
}
|
|
89
|
-
catch (err) {
|
|
90
|
-
console.log(err);
|
|
91
|
-
return false;
|
|
92
|
-
}
|
|
93
|
-
};
|
|
94
|
-
exports.isClassValidator = isClassValidator;
|
|
95
|
-
const getLineNumber = (filePath, rpath) => {
|
|
96
|
-
var _a;
|
|
97
|
-
let numbers = [];
|
|
98
|
-
try {
|
|
99
|
-
const fileContent = fs_1.default.readFileSync(filePath, "utf8");
|
|
100
|
-
const lines = fileContent.split("\n");
|
|
101
|
-
for (let i = 0; i < lines.length; i++) {
|
|
102
|
-
const match = lines[i].match(rpath);
|
|
103
|
-
if (match) {
|
|
104
|
-
console.log(match);
|
|
105
|
-
numbers.push({
|
|
106
|
-
line: i + 1,
|
|
107
|
-
column: (_a = match.index) !== null && _a !== void 0 ? _a : 0,
|
|
108
|
-
});
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
return numbers;
|
|
112
|
-
}
|
|
113
|
-
catch (error) {
|
|
114
|
-
return numbers;
|
|
115
|
-
}
|
|
8
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
9
|
+
if (k2 === undefined) k2 = k;
|
|
10
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
11
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
12
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
13
|
+
}
|
|
14
|
+
Object.defineProperty(o, k2, desc);
|
|
15
|
+
}) : (function(o, m, k, k2) {
|
|
16
|
+
if (k2 === undefined) k2 = k;
|
|
17
|
+
o[k2] = m[k];
|
|
18
|
+
}));
|
|
19
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
20
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
116
21
|
};
|
|
117
|
-
exports
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
.split("/")
|
|
124
|
-
.filter((x) => x.startsWith(":") || x.startsWith("?:"));
|
|
125
|
-
return splitPart.map((f) => ({
|
|
126
|
-
key: f.replace(/(\?|:)/g, ""),
|
|
127
|
-
required: !f.startsWith("?:"),
|
|
128
|
-
}));
|
|
129
|
-
}
|
|
130
|
-
function findDuplicates(arr) {
|
|
131
|
-
const seen = new Set();
|
|
132
|
-
const duplicates = new Set();
|
|
133
|
-
for (const str of arr) {
|
|
134
|
-
if (seen.has(str)) {
|
|
135
|
-
duplicates.add(str);
|
|
136
|
-
}
|
|
137
|
-
else {
|
|
138
|
-
seen.add(str);
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
return Array.from(duplicates);
|
|
142
|
-
}
|
|
143
|
-
function getDataType(expectedType) {
|
|
144
|
-
switch (expectedType.name) {
|
|
145
|
-
case "Object":
|
|
146
|
-
if (Array.isArray(expectedType)) {
|
|
147
|
-
return "array";
|
|
148
|
-
}
|
|
149
|
-
return "object";
|
|
150
|
-
case "String":
|
|
151
|
-
return "string";
|
|
152
|
-
case "Number":
|
|
153
|
-
return "number";
|
|
154
|
-
case "Boolean":
|
|
155
|
-
return "boolean";
|
|
156
|
-
default:
|
|
157
|
-
return expectedType;
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
function isValidType(value, expectedType) {
|
|
161
|
-
if (value === undefined || value === null)
|
|
162
|
-
return true;
|
|
163
|
-
switch (expectedType.name) {
|
|
164
|
-
case "String":
|
|
165
|
-
return typeof value === "string";
|
|
166
|
-
case "Number":
|
|
167
|
-
return typeof value === "number" || !isNaN(Number(value));
|
|
168
|
-
case "Boolean":
|
|
169
|
-
return typeof value === "boolean";
|
|
170
|
-
default:
|
|
171
|
-
return value instanceof expectedType;
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
function isValidJsonString(value) {
|
|
175
|
-
try {
|
|
176
|
-
return JSON.parse(value);
|
|
177
|
-
}
|
|
178
|
-
catch (err) {
|
|
179
|
-
return false;
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
function jsonToJs(value) {
|
|
183
|
-
try {
|
|
184
|
-
return JSON.parse(value);
|
|
185
|
-
}
|
|
186
|
-
catch (err) {
|
|
187
|
-
return false;
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
function jsonToInstance(value, instance) {
|
|
191
|
-
try {
|
|
192
|
-
const parsedValue = JSON.parse(value);
|
|
193
|
-
return (0, class_transformer_1.plainToInstance)(instance, parsedValue);
|
|
194
|
-
}
|
|
195
|
-
catch (err) {
|
|
196
|
-
return false;
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
function transformObjectByInstanceToObject(instance, value) {
|
|
200
|
-
return (0, class_transformer_1.instanceToPlain)((0, class_transformer_1.plainToInstance)(instance, value), {
|
|
201
|
-
excludeExtraneousValues: true,
|
|
202
|
-
exposeUnsetFields: true,
|
|
203
|
-
});
|
|
204
|
-
}
|
|
205
|
-
const isClassValidatorClass = (target) => {
|
|
206
|
-
try {
|
|
207
|
-
const clsval = require("class-validator");
|
|
208
|
-
const result = clsval
|
|
209
|
-
.getMetadataStorage()
|
|
210
|
-
.getTargetValidationMetadatas(target, undefined, false, false);
|
|
211
|
-
return result.length > 0;
|
|
212
|
-
}
|
|
213
|
-
catch (err) {
|
|
214
|
-
return false;
|
|
215
|
-
}
|
|
216
|
-
};
|
|
217
|
-
exports.isClassValidatorClass = isClassValidatorClass;
|
|
218
|
-
async function validateObjectByInstance(target, value = {}, options = "array") {
|
|
219
|
-
try {
|
|
220
|
-
const { validateOrReject } = require("class-validator");
|
|
221
|
-
const { plainToInstance } = require("class-transformer");
|
|
222
|
-
await validateOrReject(plainToInstance(target, value));
|
|
223
|
-
}
|
|
224
|
-
catch (error) {
|
|
225
|
-
if (typeof error == "object" && Array.isArray(error)) {
|
|
226
|
-
const errors = options == "object"
|
|
227
|
-
? error.reduce((acc, x) => {
|
|
228
|
-
//acc[x.property] = Object.values(x.constraints);
|
|
229
|
-
acc[x.property] = x.constraints;
|
|
230
|
-
return acc;
|
|
231
|
-
}, {})
|
|
232
|
-
: error.map((x) => ({
|
|
233
|
-
path: x.property,
|
|
234
|
-
constraints: x.constraints,
|
|
235
|
-
}));
|
|
236
|
-
return errors;
|
|
237
|
-
}
|
|
238
|
-
else {
|
|
239
|
-
throw new exceptions_1.InternalErrorException("Can't validate object");
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
function validateRequestBody(target, value, options = "array") {
|
|
244
|
-
if (!(0, exports.isClassValidatorClass)(target))
|
|
245
|
-
return { count: 0, errors: {} };
|
|
246
|
-
const error = (0, class_validator_1.validateSync)((0, class_transformer_1.plainToInstance)(target, value ? value : {}));
|
|
247
|
-
const errors = options == "object"
|
|
248
|
-
? error.reduce((acc, x) => {
|
|
249
|
-
//acc[x.property] = Object.values(x.constraints);
|
|
250
|
-
acc[x.property] = x.constraints;
|
|
251
|
-
return acc;
|
|
252
|
-
}, {})
|
|
253
|
-
: error.map((x) => ({ path: x.property, constraints: x.constraints }));
|
|
254
|
-
return { count: error.length, errors };
|
|
255
|
-
}
|
|
256
|
-
function pick(obj, paths) {
|
|
257
|
-
const result = {};
|
|
258
|
-
for (const path of paths) {
|
|
259
|
-
const keys = path.split(".");
|
|
260
|
-
let source = obj;
|
|
261
|
-
let target = result;
|
|
262
|
-
for (let i = 0; i < keys.length; i++) {
|
|
263
|
-
const key = keys[i];
|
|
264
|
-
if (!(key in source))
|
|
265
|
-
break;
|
|
266
|
-
if (i === keys.length - 1) {
|
|
267
|
-
target[key] = source[key];
|
|
268
|
-
}
|
|
269
|
-
else {
|
|
270
|
-
source = source[key];
|
|
271
|
-
target[key] = target[key] || {};
|
|
272
|
-
target = target[key];
|
|
273
|
-
}
|
|
274
|
-
}
|
|
275
|
-
}
|
|
276
|
-
return result;
|
|
277
|
-
}
|
|
278
|
-
function exclude(obj, paths) {
|
|
279
|
-
if (Array.isArray(obj)) {
|
|
280
|
-
return obj.map((item) => exclude(item, paths));
|
|
281
|
-
}
|
|
282
|
-
const clone = structuredClone(obj); // Or use lodash.cloneDeep
|
|
283
|
-
for (const path of paths) {
|
|
284
|
-
const keys = path.split(".");
|
|
285
|
-
let target = clone;
|
|
286
|
-
for (let i = 0; i < keys.length - 1; i++) {
|
|
287
|
-
if (!(keys[i] in target))
|
|
288
|
-
break;
|
|
289
|
-
target = target[keys[i]];
|
|
290
|
-
}
|
|
291
|
-
target === null || target === void 0 ? true : delete target[keys[keys.length - 1]];
|
|
292
|
-
}
|
|
293
|
-
return clone;
|
|
294
|
-
}
|
|
295
|
-
function autoCast(value, typeHint, schema) {
|
|
296
|
-
var _a, _b;
|
|
297
|
-
if (value === null || value === undefined)
|
|
298
|
-
return value;
|
|
299
|
-
if (Array.isArray(value)) {
|
|
300
|
-
const elementType = Array.isArray(typeHint) ? typeHint[0] : undefined;
|
|
301
|
-
return value.map((v) => autoCast(v, elementType));
|
|
302
|
-
}
|
|
303
|
-
if (typeof value === "object" && !(value instanceof Date)) {
|
|
304
|
-
const result = {};
|
|
305
|
-
for (const [key, val] of Object.entries(value)) {
|
|
306
|
-
let fieldType = undefined;
|
|
307
|
-
if ((_b = (_a = schema === null || schema === void 0 ? void 0 : schema.properties) === null || _a === void 0 ? void 0 : _a[key]) === null || _b === void 0 ? void 0 : _b.type) {
|
|
308
|
-
const t = schema.properties[key].type;
|
|
309
|
-
fieldType =
|
|
310
|
-
t === "integer" || t === "number"
|
|
311
|
-
? Number
|
|
312
|
-
: t === "boolean"
|
|
313
|
-
? Boolean
|
|
314
|
-
: t === "array"
|
|
315
|
-
? Array
|
|
316
|
-
: t === "object"
|
|
317
|
-
? Object
|
|
318
|
-
: String;
|
|
319
|
-
}
|
|
320
|
-
result[key] = autoCast(val, fieldType);
|
|
321
|
-
}
|
|
322
|
-
return result;
|
|
323
|
-
}
|
|
324
|
-
if (typeof value !== "string")
|
|
325
|
-
return value;
|
|
326
|
-
const trimmed = value.trim();
|
|
327
|
-
if (typeHint === Boolean || trimmed.toLowerCase() === "true")
|
|
328
|
-
return true;
|
|
329
|
-
if (trimmed.toLowerCase() === "false")
|
|
330
|
-
return false;
|
|
331
|
-
if (typeHint === Number || (!isNaN(Number(trimmed)) && trimmed !== "")) {
|
|
332
|
-
const n = Number(trimmed);
|
|
333
|
-
if (!isNaN(n))
|
|
334
|
-
return n;
|
|
335
|
-
}
|
|
336
|
-
if ((trimmed.startsWith("{") && trimmed.endsWith("}")) ||
|
|
337
|
-
(trimmed.startsWith("[") && trimmed.endsWith("]"))) {
|
|
338
|
-
try {
|
|
339
|
-
const parsed = JSON.parse(trimmed);
|
|
340
|
-
return autoCast(parsed, typeHint, schema);
|
|
341
|
-
}
|
|
342
|
-
catch (_c) {
|
|
343
|
-
return trimmed;
|
|
344
|
-
}
|
|
345
|
-
}
|
|
346
|
-
if (typeHint === Date ||
|
|
347
|
-
/^\d{4}-\d{2}-\d{2}([Tt]\d{2}:\d{2})?/.test(trimmed)) {
|
|
348
|
-
const d = new Date(trimmed);
|
|
349
|
-
if (!isNaN(d.getTime()))
|
|
350
|
-
return d;
|
|
351
|
-
}
|
|
352
|
-
return trimmed;
|
|
353
|
-
}
|
|
354
|
-
/**
|
|
355
|
-
* Deeply normalizes query strings into nested JS objects.
|
|
356
|
-
* Supports:
|
|
357
|
-
* - filter[name]=john
|
|
358
|
-
* - filter[user][age]=25
|
|
359
|
-
* - filter[tags][]=a&filter[tags][]=b
|
|
360
|
-
* - filter=name&filter=sorna
|
|
361
|
-
*/
|
|
362
|
-
function normalizeQueryDeep(query) {
|
|
363
|
-
const result = {};
|
|
364
|
-
const setDeep = (obj, path, value) => {
|
|
365
|
-
let current = obj;
|
|
366
|
-
for (let i = 0; i < path.length; i++) {
|
|
367
|
-
const key = path[i];
|
|
368
|
-
const nextKey = path[i + 1];
|
|
369
|
-
if (i === path.length - 1) {
|
|
370
|
-
if (key === "") {
|
|
371
|
-
if (!Array.isArray(current))
|
|
372
|
-
current = [];
|
|
373
|
-
current.push(value);
|
|
374
|
-
}
|
|
375
|
-
else if (Array.isArray(current[key])) {
|
|
376
|
-
current[key].push(value);
|
|
377
|
-
}
|
|
378
|
-
else if (current[key] !== undefined) {
|
|
379
|
-
current[key] = [current[key], value];
|
|
380
|
-
}
|
|
381
|
-
else {
|
|
382
|
-
current[key] = value;
|
|
383
|
-
}
|
|
384
|
-
}
|
|
385
|
-
else {
|
|
386
|
-
if (!current[key]) {
|
|
387
|
-
current[key] = nextKey === "" || /^\d+$/.test(nextKey) ? [] : {};
|
|
388
|
-
}
|
|
389
|
-
current = current[key];
|
|
390
|
-
}
|
|
391
|
-
}
|
|
392
|
-
};
|
|
393
|
-
for (const [rawKey, rawValue] of Object.entries(query)) {
|
|
394
|
-
const path = [];
|
|
395
|
-
const regex = /([^\[\]]+)|(\[\])/g;
|
|
396
|
-
let match;
|
|
397
|
-
while ((match = regex.exec(rawKey)) !== null) {
|
|
398
|
-
if (match[1])
|
|
399
|
-
path.push(match[1]);
|
|
400
|
-
else if (match[2])
|
|
401
|
-
path.push("");
|
|
402
|
-
}
|
|
403
|
-
if (path.length === 0) {
|
|
404
|
-
if (result[rawKey]) {
|
|
405
|
-
if (Array.isArray(result[rawKey]))
|
|
406
|
-
result[rawKey].push(rawValue);
|
|
407
|
-
else
|
|
408
|
-
result[rawKey] = [result[rawKey], rawValue];
|
|
409
|
-
}
|
|
410
|
-
else {
|
|
411
|
-
result[rawKey] = rawValue;
|
|
412
|
-
}
|
|
413
|
-
}
|
|
414
|
-
else {
|
|
415
|
-
setDeep(result, path, rawValue);
|
|
416
|
-
}
|
|
417
|
-
}
|
|
418
|
-
return result;
|
|
419
|
-
}
|
|
22
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
23
|
+
__exportStar(require("./utils/common-utils"), exports);
|
|
24
|
+
__exportStar(require("./utils/object-utils"), exports);
|
|
25
|
+
__exportStar(require("./utils/validation-utils"), exports);
|
|
26
|
+
__exportStar(require("./utils/di-utils"), exports);
|
|
27
|
+
__exportStar(require("./validation"), exports);
|