codeweaver 1.1.0 → 2.0.0
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/.vscode/settings.json +3 -0
- package/README.md +54 -61
- package/package.json +8 -6
- package/src/config.ts +23 -15
- package/src/constants.ts +6 -0
- package/src/main.ts +82 -0
- package/src/routers/orders/dto/order.dto.ts +1 -0
- package/src/routers/orders/{index.ts → index.router.ts} +3 -7
- package/src/routers/orders/order.controller.ts +41 -54
- package/src/routers/products/dto/product.dto.ts +1 -0
- package/src/routers/products/{index.ts → index.router.ts} +3 -10
- package/src/routers/products/product.controller.ts +45 -65
- package/src/routers/users/dto/user.dto.ts +3 -1
- package/src/routers/users/{index.ts → index.router.ts} +1 -4
- package/src/routers/users/user.controller.ts +33 -41
- package/src/swagger-options.ts +54 -0
- package/src/utilities/assign.ts +81 -0
- package/src/utilities/error-handling.ts +120 -0
- package/src/utilities/types.ts +23 -0
- package/tsconfig.json +1 -4
- package/tsconfig.paths.json +8 -10
- package/src/app.ts +0 -113
- package/src/packages/ts-zod-decorators/index.ts +0 -3
- package/src/packages/ts-zod-decorators/validate.decorator.ts +0 -20
- package/src/packages/ts-zod-decorators/validator.class.ts +0 -72
- package/src/packages/ts-zod-decorators/zod-input.decorator.ts +0 -12
- package/src/packages/ts-zod-decorators/zod-output.decorator.ts +0 -11
- package/src/types.ts +0 -16
- package/src/utilities.ts +0 -47
- /package/src/routers/{index.ts → index.router.ts} +0 -0
package/tsconfig.json
CHANGED
|
@@ -9,11 +9,8 @@
|
|
|
9
9
|
"forceConsistentCasingInFileNames": true,
|
|
10
10
|
"experimentalDecorators": true,
|
|
11
11
|
"emitDecoratorMetadata": true,
|
|
12
|
-
"baseUrl": ".",
|
|
13
12
|
"paths": {
|
|
14
|
-
"
|
|
15
|
-
"@r/*": ["src/routers/*"],
|
|
16
|
-
"@/*": ["src/*"]
|
|
13
|
+
"@/*": ["./src/*"]
|
|
17
14
|
}
|
|
18
15
|
},
|
|
19
16
|
"include": ["**/*.ts", "**/*.js"],
|
package/tsconfig.paths.json
CHANGED
package/src/app.ts
DELETED
|
@@ -1,113 +0,0 @@
|
|
|
1
|
-
import express, {
|
|
2
|
-
ErrorRequestHandler,
|
|
3
|
-
NextFunction,
|
|
4
|
-
Request,
|
|
5
|
-
Response,
|
|
6
|
-
} from "express";
|
|
7
|
-
import fs from "fs";
|
|
8
|
-
import path from "path";
|
|
9
|
-
import config from "./config";
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Recursively loads Express routers from directory
|
|
13
|
-
* @param {string} routerPath - Directory path to scan
|
|
14
|
-
* @param {string} [basePath=""] - Base route path
|
|
15
|
-
*/
|
|
16
|
-
function loadRouters(routerPath: string, basePath: string = "") {
|
|
17
|
-
fs.readdirSync(routerPath).forEach((file) => {
|
|
18
|
-
// Check if the filename should be excluded based on certain criteria
|
|
19
|
-
if (
|
|
20
|
-
// Exclude files that start with an underscore (_)
|
|
21
|
-
file.startsWith("_") ||
|
|
22
|
-
// Exclude files that start with an at symbol (@)
|
|
23
|
-
file.startsWith("@") ||
|
|
24
|
-
// Exclude JavaScript controller files
|
|
25
|
-
file.endsWith(".controller.js") ||
|
|
26
|
-
// Exclude TypeScript controller files
|
|
27
|
-
file.endsWith(".controller.ts") ||
|
|
28
|
-
// Exclude JavaScript service files
|
|
29
|
-
file.endsWith(".service.js") ||
|
|
30
|
-
// Exclude TypeScript service files
|
|
31
|
-
file.endsWith(".service.ts") ||
|
|
32
|
-
// Exclude JavaScript middleware files
|
|
33
|
-
file.endsWith(".middleware.js") ||
|
|
34
|
-
// Exclude TypeScript middleware files
|
|
35
|
-
file.endsWith(".middleware.ts") ||
|
|
36
|
-
// Exclude JavaScript error middleware files
|
|
37
|
-
file.endsWith(".error.js") ||
|
|
38
|
-
// Exclude TypeScript error middleware files
|
|
39
|
-
file.endsWith(".error.ts") ||
|
|
40
|
-
// Exclude JavaScript service files
|
|
41
|
-
file.endsWith(".decorator.js") ||
|
|
42
|
-
// Exclude TypeScript service files
|
|
43
|
-
file.endsWith(".decorator.ts") ||
|
|
44
|
-
// Exclude JavaScript DTO files
|
|
45
|
-
file.endsWith(".dto.js") ||
|
|
46
|
-
// Exclude TypeScript DTO files
|
|
47
|
-
file.endsWith(".dto.ts") ||
|
|
48
|
-
// Exclude JavaScript test specification files
|
|
49
|
-
file.endsWith(".spec.js") ||
|
|
50
|
-
// Exclude TypeScript test specification files
|
|
51
|
-
file.endsWith(".spec.ts") ||
|
|
52
|
-
// Exclude JavaScript test specification files
|
|
53
|
-
file.endsWith(".class.js") ||
|
|
54
|
-
// Exclude TypeScript test specification files
|
|
55
|
-
file.endsWith(".class.ts")
|
|
56
|
-
)
|
|
57
|
-
// If any of the above conditions are true, exit the function early
|
|
58
|
-
return;
|
|
59
|
-
|
|
60
|
-
const fullPath = path.join(routerPath, file);
|
|
61
|
-
|
|
62
|
-
// Construct a route path by combining the base path with the filename
|
|
63
|
-
const routePath = path
|
|
64
|
-
// Join the base path and the filename, removing the file extension (.js or .ts)
|
|
65
|
-
.join(basePath, file.replace(/(\.js|\.ts)/g, ""))
|
|
66
|
-
// Replace all backslashes with forward slashes for consistent file path formatting
|
|
67
|
-
.replaceAll("\\", "/")
|
|
68
|
-
// Remove the trailing '/index' if it exists, to clean up the route
|
|
69
|
-
.replace(/\/?index$/g, "");
|
|
70
|
-
|
|
71
|
-
if (fs.lstatSync(fullPath).isDirectory()) {
|
|
72
|
-
// If the file is a directory, call the function again
|
|
73
|
-
loadRouters(fullPath, routePath);
|
|
74
|
-
} else if (file.endsWith(".ts") || file.endsWith(".js")) {
|
|
75
|
-
// Import the router module and mount it to the app
|
|
76
|
-
const router = require(fullPath);
|
|
77
|
-
app.use("/" + routePath, router);
|
|
78
|
-
console.log(`Mounted ${file} at ${"/" + routePath}`);
|
|
79
|
-
}
|
|
80
|
-
});
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
const app = express();
|
|
84
|
-
app.use(express.json());
|
|
85
|
-
app.use(express.urlencoded({ extended: true }));
|
|
86
|
-
|
|
87
|
-
//app.use(cors());
|
|
88
|
-
|
|
89
|
-
// Automatically import all routers from the /src/routers directory
|
|
90
|
-
const routersPath = path.join(__dirname, "/routers");
|
|
91
|
-
loadRouters(routersPath);
|
|
92
|
-
|
|
93
|
-
// Swagger setup
|
|
94
|
-
if (config.devMode) {
|
|
95
|
-
const swaggerJsDoc = require("swagger-jsdoc");
|
|
96
|
-
const swaggerUi = require("swagger-ui-express");
|
|
97
|
-
const swaggerDocs = swaggerJsDoc(config.swaggerOptions);
|
|
98
|
-
app.use("/api-docs", swaggerUi.serve, swaggerUi.setup(swaggerDocs));
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
// General error handler
|
|
102
|
-
app.use((err: unknown, req: Request, res: Response, next: NextFunction) => {
|
|
103
|
-
res.status(500).json(err);
|
|
104
|
-
});
|
|
105
|
-
|
|
106
|
-
// Start the server
|
|
107
|
-
app.listen(config.port, () => {
|
|
108
|
-
console.log(`Server is running on http://localhost:${config.port}`);
|
|
109
|
-
if (config.devMode)
|
|
110
|
-
console.log(
|
|
111
|
-
`Swagger UI is available at http://localhost:${config.port}/api-docs`
|
|
112
|
-
);
|
|
113
|
-
});
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
/* eslint-disable @typescript-eslint/ban-types */
|
|
2
|
-
import ZodValidator from './validator.class';
|
|
3
|
-
|
|
4
|
-
export const Validate: MethodDecorator = (
|
|
5
|
-
target: Object,
|
|
6
|
-
propertyKey: string | symbol,
|
|
7
|
-
descriptor: PropertyDescriptor,
|
|
8
|
-
) => {
|
|
9
|
-
const originalMethod = descriptor.value;
|
|
10
|
-
descriptor.value = async function (...args: unknown[]) {
|
|
11
|
-
ZodValidator.validateInput(target, propertyKey as string, args);
|
|
12
|
-
const result = originalMethod.apply(this, args);
|
|
13
|
-
let resultValue = result;
|
|
14
|
-
if (result instanceof Promise) {
|
|
15
|
-
resultValue = await result;
|
|
16
|
-
ZodValidator.validateOutput(target, propertyKey as string, resultValue);
|
|
17
|
-
}
|
|
18
|
-
return resultValue;
|
|
19
|
-
};
|
|
20
|
-
};
|
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
/* eslint-disable @typescript-eslint/ban-types */
|
|
2
|
-
import * as z from "zod";
|
|
3
|
-
|
|
4
|
-
type Target = Object;
|
|
5
|
-
type MethodName = string;
|
|
6
|
-
type Metadata = {
|
|
7
|
-
paramsIndex: number[];
|
|
8
|
-
inputSchema?: z.ZodObject<any, any>;
|
|
9
|
-
outputSchema?: z.ZodObject<any, any>;
|
|
10
|
-
};
|
|
11
|
-
|
|
12
|
-
export default class ZodValidator {
|
|
13
|
-
private static methodValidatorMap: Map<Target, Map<MethodName, Metadata>> =
|
|
14
|
-
new Map();
|
|
15
|
-
|
|
16
|
-
static registerInputParameterValidationSchema(
|
|
17
|
-
target: Object,
|
|
18
|
-
methodName: MethodName,
|
|
19
|
-
paramIndex: number,
|
|
20
|
-
schema: z.ZodObject<any, any>
|
|
21
|
-
) {
|
|
22
|
-
let paramMap = this.methodValidatorMap.get(target)!;
|
|
23
|
-
if (!paramMap) {
|
|
24
|
-
paramMap = new Map();
|
|
25
|
-
this.methodValidatorMap.set(target, paramMap);
|
|
26
|
-
}
|
|
27
|
-
let metadata = paramMap.get(methodName)!;
|
|
28
|
-
if (!metadata) {
|
|
29
|
-
metadata = { paramsIndex: [], inputSchema: schema };
|
|
30
|
-
paramMap.set(methodName, metadata);
|
|
31
|
-
}
|
|
32
|
-
metadata.paramsIndex.push(paramIndex);
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
static registerMethodValidationOutputSchema(
|
|
36
|
-
target: Object,
|
|
37
|
-
methodName: MethodName,
|
|
38
|
-
schema: z.ZodObject<any, any>
|
|
39
|
-
) {
|
|
40
|
-
let paramMap = this.methodValidatorMap.get(target)!;
|
|
41
|
-
if (!paramMap) {
|
|
42
|
-
paramMap = new Map();
|
|
43
|
-
this.methodValidatorMap.set(target, paramMap);
|
|
44
|
-
}
|
|
45
|
-
let metadata = paramMap.get(methodName)!;
|
|
46
|
-
if (!metadata) {
|
|
47
|
-
metadata = { paramsIndex: [], outputSchema: schema };
|
|
48
|
-
paramMap.set(methodName, metadata);
|
|
49
|
-
}
|
|
50
|
-
metadata.outputSchema = schema;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
static validateInput(
|
|
54
|
-
target: Object,
|
|
55
|
-
methodName: string,
|
|
56
|
-
paramValues: unknown[]
|
|
57
|
-
) {
|
|
58
|
-
const methodMetadataMap = this.methodValidatorMap.get(target)!;
|
|
59
|
-
const metadata = methodMetadataMap.get(methodName)!;
|
|
60
|
-
for (const [index, input] of paramValues.entries()) {
|
|
61
|
-
if (metadata.paramsIndex.indexOf(index) != -1) {
|
|
62
|
-
metadata.inputSchema?.parse(input);
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
static validateOutput(target: Object, methodName: string, output: unknown) {
|
|
68
|
-
const methodMetadataMap = this.methodValidatorMap.get(target)!;
|
|
69
|
-
const metadata = methodMetadataMap.get(methodName)!;
|
|
70
|
-
metadata.outputSchema?.parse(output);
|
|
71
|
-
}
|
|
72
|
-
}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { ZodObject } from "zod";
|
|
2
|
-
import ZodValidator from "./validator.class";
|
|
3
|
-
|
|
4
|
-
export const ZodInput =
|
|
5
|
-
<T extends ZodObject<any, any>>(schema: T): ParameterDecorator =>
|
|
6
|
-
(target, propertyKey, parameterIndex) =>
|
|
7
|
-
ZodValidator.registerInputParameterValidationSchema(
|
|
8
|
-
target,
|
|
9
|
-
propertyKey as string,
|
|
10
|
-
parameterIndex,
|
|
11
|
-
schema
|
|
12
|
-
);
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { ZodObject } from "zod";
|
|
2
|
-
import ZodValidator from "./validator.class";
|
|
3
|
-
|
|
4
|
-
export const ZodOutput =
|
|
5
|
-
<T extends ZodObject<any, any>>(schema: T): MethodDecorator =>
|
|
6
|
-
(target, propertyKey) =>
|
|
7
|
-
ZodValidator.registerMethodValidationOutputSchema(
|
|
8
|
-
target,
|
|
9
|
-
propertyKey as string,
|
|
10
|
-
schema
|
|
11
|
-
);
|
package/src/types.ts
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Represents a standardized error response structure for API endpoints
|
|
3
|
-
* @interface
|
|
4
|
-
* @property {number} status - HTTP status code
|
|
5
|
-
* @property {string} [name] - Error name/type
|
|
6
|
-
* @property {string} message - Human-readable error message
|
|
7
|
-
* @property {string} [stack] - Error stack trace (development only)
|
|
8
|
-
* @property {string} [details] - Additional error details
|
|
9
|
-
*/
|
|
10
|
-
export interface ResponseError {
|
|
11
|
-
status: number;
|
|
12
|
-
name?: string;
|
|
13
|
-
message: string;
|
|
14
|
-
stack?: string;
|
|
15
|
-
details?: string;
|
|
16
|
-
}
|
package/src/utilities.ts
DELETED
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
import { Response } from "express";
|
|
2
|
-
import { ResponseError } from "./types";
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Sends a standardized error response
|
|
6
|
-
* @param {Response} res - Express response object
|
|
7
|
-
* @param {ResponseError} error - Error details object
|
|
8
|
-
*/
|
|
9
|
-
export function sendError(res: Response, error: ResponseError): void {
|
|
10
|
-
res.status(error.status).json(error);
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Parses and validates ID parameter from string to number
|
|
15
|
-
* @param {string} input - Input string to parse
|
|
16
|
-
* @returns {number|ResponseError} Parsed number or error object
|
|
17
|
-
*/
|
|
18
|
-
export function tryParseId(input: string): number | ResponseError {
|
|
19
|
-
try {
|
|
20
|
-
return parseInt(input) satisfies number;
|
|
21
|
-
} catch {
|
|
22
|
-
return {
|
|
23
|
-
status: 400,
|
|
24
|
-
message: "wrong input",
|
|
25
|
-
details: "The id parameter must be an integer number.",
|
|
26
|
-
} satisfies ResponseError;
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* Checks if the provided object is a ResponseError.
|
|
32
|
-
*
|
|
33
|
-
* A ResponseError is an object that contains at least the properties:
|
|
34
|
-
* - message: string
|
|
35
|
-
* - status: number
|
|
36
|
-
*
|
|
37
|
-
* @param obj - The object to check.
|
|
38
|
-
* @returns true if the object is a ResponseError, false otherwise.
|
|
39
|
-
*/
|
|
40
|
-
export function isResponseError(obj: unknown): boolean {
|
|
41
|
-
return (
|
|
42
|
-
obj != null &&
|
|
43
|
-
typeof obj === "object" &&
|
|
44
|
-
"message" in obj &&
|
|
45
|
-
"status" in obj
|
|
46
|
-
);
|
|
47
|
-
}
|
|
File without changes
|