codeweaver 2.0.0 → 2.1.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/README.md +84 -144
- package/package.json +6 -3
- package/src/app.ts +3 -0
- package/src/config.ts +11 -50
- package/src/constants.ts +1 -0
- package/src/db.ts +183 -0
- package/src/entities/order.entity.ts +68 -0
- package/src/entities/product.entity.ts +75 -0
- package/src/entities/user.entity.ts +38 -0
- package/src/main.ts +10 -7
- package/src/routers/orders/dto/order.dto.ts +54 -30
- package/src/routers/orders/index.router.ts +10 -6
- package/src/routers/orders/order.controller.ts +88 -77
- package/src/routers/products/dto/product.dto.ts +86 -31
- package/src/routers/products/index.router.ts +11 -5
- package/src/routers/products/product.controller.ts +112 -117
- package/src/routers/users/dto/user.dto.ts +13 -19
- package/src/routers/users/index.router.ts +5 -3
- package/src/routers/users/user.controller.ts +74 -97
- package/src/swagger-options.ts +7 -22
- package/src/utilities/assign.ts +44 -59
- package/src/utilities/cache/memory-cache.ts +74 -0
- package/src/utilities/cache/redis-cache.ts +111 -0
- package/src/utilities/conversion.ts +158 -0
- package/src/utilities/error-handling.ts +62 -26
- package/src/utilities/router.ts +0 -0
- package/src/utilities/types.ts +0 -23
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import { z, ZodRawShape } from "zod";
|
|
2
|
+
import { ResponseError } from "./error-handling";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Helper: normalize and validate a numeric string for integer parsing.
|
|
6
|
+
* This ensures we reject non-integer strings, empty input, or inputs with extra chars.
|
|
7
|
+
*/
|
|
8
|
+
function parseIntegerStrict(input: string): number {
|
|
9
|
+
// Trim whitespace
|
|
10
|
+
const s = input.trim();
|
|
11
|
+
|
|
12
|
+
// Empty or just sign is invalid
|
|
13
|
+
if (s.length === 0 || s === "+" || s === "-") {
|
|
14
|
+
throw new Error("Invalid integer");
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// Use a regex to ensure the entire string is an optional sign followed by digits
|
|
18
|
+
if (!/^[+-]?\d+$/.test(s)) {
|
|
19
|
+
throw new Error("Invalid integer");
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// Safe parse
|
|
23
|
+
const n = Number(s);
|
|
24
|
+
if (!Number.isSafeInteger(n)) {
|
|
25
|
+
throw new Error("Integer out of safe range");
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return n;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Parses a string input into an integer number with strict validation.
|
|
33
|
+
*
|
|
34
|
+
* If parsing fails, this function throws a ResponseError describing the invalid input.
|
|
35
|
+
*
|
|
36
|
+
* @param input - The string to parse as an integer
|
|
37
|
+
* @returns The parsed integer
|
|
38
|
+
* @throws {ResponseError} When the input cannot be parsed as an integer
|
|
39
|
+
*/
|
|
40
|
+
export function stringToInteger(input: string): number {
|
|
41
|
+
try {
|
|
42
|
+
return parseIntegerStrict(input);
|
|
43
|
+
} catch {
|
|
44
|
+
throw new ResponseError(
|
|
45
|
+
"The input parameter must be a valid integer.",
|
|
46
|
+
400
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Parses a string input into a boolean with explicit validation.
|
|
53
|
+
*
|
|
54
|
+
* Accepted true values: "true", "1", "yes", case-insensitive
|
|
55
|
+
* Accepted false values: "false", "0", "no", case-insensitive
|
|
56
|
+
* Any other input is invalid.
|
|
57
|
+
*
|
|
58
|
+
* If parsing fails, this function throws a ResponseError describing the invalid input.
|
|
59
|
+
*
|
|
60
|
+
* @param input - The string to parse as a boolean
|
|
61
|
+
* @returns The parsed boolean
|
|
62
|
+
* @throws {ResponseError} When the input cannot be parsed as a boolean
|
|
63
|
+
*/
|
|
64
|
+
export function stringToBoolean(input: string): boolean {
|
|
65
|
+
const s = input.trim().toLowerCase();
|
|
66
|
+
|
|
67
|
+
if (["true", "1", "yes", "y"].includes(s)) {
|
|
68
|
+
return true;
|
|
69
|
+
}
|
|
70
|
+
if (["false", "0", "no", "n"].includes(s)) {
|
|
71
|
+
return false;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
throw new ResponseError(
|
|
75
|
+
"The input parameter must be a boolean (e.g., true/false, 1/0).",
|
|
76
|
+
400
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Parses a string input into a number with basic validation.
|
|
82
|
+
*
|
|
83
|
+
* If parsing fails, this function throws a ResponseError describing the invalid input.
|
|
84
|
+
*
|
|
85
|
+
* @param input - The string to parse as a number
|
|
86
|
+
* @returns The parsed number
|
|
87
|
+
* @throws {ResponseError} When the input cannot be parsed as a number
|
|
88
|
+
*/
|
|
89
|
+
export function stringToNumber(input: string): number {
|
|
90
|
+
try {
|
|
91
|
+
// Trim and convert
|
|
92
|
+
const n = Number(input.trim());
|
|
93
|
+
|
|
94
|
+
// Allow finite numbers only
|
|
95
|
+
if (!Number.isFinite(n)) {
|
|
96
|
+
throw new Error("Invalid number");
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
return n;
|
|
100
|
+
} catch {
|
|
101
|
+
throw new ResponseError("The input parameter must be a valid number.", 400);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Strictly convert obj (type T1) to T2 using a Zod schema.
|
|
107
|
+
*
|
|
108
|
+
* - Extras in obj are ignored (no throw).
|
|
109
|
+
* - Validates fields with the schema; on failure, throws with a descriptive message.
|
|
110
|
+
* - Returns an object typed as T2 (inferred from the schema).
|
|
111
|
+
*
|
|
112
|
+
* @param obj - Source object of type T1
|
|
113
|
+
* @param schema - Zod schema describing the target type T2
|
|
114
|
+
* @returns T2 inferred from the provided schema
|
|
115
|
+
*/
|
|
116
|
+
export function convert<T1 extends object, T2 extends object>(
|
|
117
|
+
obj: T1,
|
|
118
|
+
schema: z.ZodObject<any>
|
|
119
|
+
): T2 {
|
|
120
|
+
// 1) Derive the runtime keys from the schema's shape
|
|
121
|
+
const shape = (schema as any)._def?.shape as ZodRawShape | undefined;
|
|
122
|
+
if (!shape) {
|
|
123
|
+
throw new ResponseError(
|
|
124
|
+
"convertStrictlyFromSchema: provided schema has no shape.",
|
|
125
|
+
500
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
const keysSchema = Object.keys(shape) as Array<keyof any>;
|
|
130
|
+
|
|
131
|
+
// 2) Build a plain object to pass through Zod for validation
|
|
132
|
+
// Include only keys that exist on the schema (ignore extras in obj)
|
|
133
|
+
const candidate: any = {};
|
|
134
|
+
for (const k of keysSchema) {
|
|
135
|
+
if ((obj as any).hasOwnProperty(k)) {
|
|
136
|
+
candidate[k] = (obj as any)[k];
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// 3) Validate against the schema
|
|
141
|
+
const result = schema.safeParse(candidate);
|
|
142
|
+
if (!result.success) {
|
|
143
|
+
// Modern, non-format error reporting
|
|
144
|
+
const issues = result.error.issues.map((i) => ({
|
|
145
|
+
path: i.path, // where the issue occurred
|
|
146
|
+
message: i.message, // human-friendly message
|
|
147
|
+
code: i.code, // e.g., "too_small", "invalid_type"
|
|
148
|
+
}));
|
|
149
|
+
// You can log issues or throw a structured error
|
|
150
|
+
throw new ResponseError(
|
|
151
|
+
`convertStrictlyFromSchema: validation failed: ${JSON.stringify(issues)}`,
|
|
152
|
+
500
|
|
153
|
+
);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// 4) Return the validated data typed as T2
|
|
157
|
+
return result.data as T2;
|
|
158
|
+
}
|
|
@@ -1,5 +1,53 @@
|
|
|
1
1
|
import { Response } from "express";
|
|
2
|
-
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Represents a standardized error response structure for API endpoints.
|
|
5
|
+
*
|
|
6
|
+
* This class models an API-friendly error, carrying a human message plus
|
|
7
|
+
* optional metadata (status, details, input, code, stack). Extends the built-in Error
|
|
8
|
+
* so it works naturally with try/catch blocks.
|
|
9
|
+
*/
|
|
10
|
+
export class ResponseError extends Error {
|
|
11
|
+
public constructor(
|
|
12
|
+
/**
|
|
13
|
+
* User-facing error message describing what went wrong.
|
|
14
|
+
*/
|
|
15
|
+
public message: string,
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Optional HTTP status code related to the error (e.g., 400, 404, 500).
|
|
19
|
+
*/
|
|
20
|
+
public status?: number,
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Optional human-readable details or context about the error.
|
|
24
|
+
*/
|
|
25
|
+
public details?: string,
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Optional input value that caused the error (useful for logging/diagnostics).
|
|
29
|
+
*/
|
|
30
|
+
public input?: string,
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Optional application-specific error code (e.g., "INVALID_INPUT").
|
|
34
|
+
*/
|
|
35
|
+
public code?: string,
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Optional stack trace string (usually provided by runtime).
|
|
39
|
+
* Note: In many environments, stack is inherited from Error; you may
|
|
40
|
+
* not need to redefine it here unless you have a specific reason.
|
|
41
|
+
*/
|
|
42
|
+
public stack?: string
|
|
43
|
+
) {
|
|
44
|
+
// Ensure the base Error class gets the message for standard properties like name, stack, etc.
|
|
45
|
+
super(message);
|
|
46
|
+
|
|
47
|
+
// If a custom stack is provided, you might assign it; otherwise, the runtime stack will be used.
|
|
48
|
+
if (stack) this.stack = stack;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
3
51
|
|
|
4
52
|
/**
|
|
5
53
|
* Sends a standardized HTTP error response.
|
|
@@ -14,6 +62,18 @@ export function sendHttpError(res: Response, error: ResponseError): void {
|
|
|
14
62
|
res.status(error.status ?? 500).json(error);
|
|
15
63
|
}
|
|
16
64
|
|
|
65
|
+
/**
|
|
66
|
+
* A generic alias representing a tuple of [result, error].
|
|
67
|
+
* - result is either T or null if an error occurred
|
|
68
|
+
* - error is either a ResponseError or null if the operation succeeded
|
|
69
|
+
*/
|
|
70
|
+
export type ReturnInfo<T> = [T | null, ResponseError | null];
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* A Promise-wrapped version of ReturnInfo.
|
|
74
|
+
*/
|
|
75
|
+
export type AsyncReturnInfo<T> = Promise<ReturnInfo<T>>;
|
|
76
|
+
|
|
17
77
|
/**
|
|
18
78
|
* Executes a function and captures a potential error as a ReturnInfo tuple.
|
|
19
79
|
*
|
|
@@ -29,7 +89,7 @@ export function sendHttpError(res: Response, error: ResponseError): void {
|
|
|
29
89
|
* @param error - The error object to return when an exception occurs (typically a ResponseError). If no error is provided, null is used.
|
|
30
90
|
* @returns ReturnInfo<T> A tuple: [value or null, error or null]
|
|
31
91
|
*/
|
|
32
|
-
export function
|
|
92
|
+
export function invoke<T>(
|
|
33
93
|
func: () => T,
|
|
34
94
|
error: ResponseError | null
|
|
35
95
|
): ReturnInfo<T> {
|
|
@@ -40,30 +100,6 @@ export function tryCatch<T>(
|
|
|
40
100
|
}
|
|
41
101
|
}
|
|
42
102
|
|
|
43
|
-
/**
|
|
44
|
-
* Parses a string input into a number (ID) with basic validation.
|
|
45
|
-
*
|
|
46
|
-
* If parsing fails, this function throws a ResponseError describing the invalid input.
|
|
47
|
-
*
|
|
48
|
-
* @param input - The string to parse as an integer ID
|
|
49
|
-
* @returns The parsed number
|
|
50
|
-
* @throws {ResponseError} When the input cannot be parsed as an integer
|
|
51
|
-
*/
|
|
52
|
-
export function parseId(input: string): number {
|
|
53
|
-
try {
|
|
54
|
-
// parseInt may yield NaN for non-numeric input; this example mirrors the original behavior
|
|
55
|
-
// If you want stricter validation, you can check isNaN and throw a more explicit error.
|
|
56
|
-
return parseInt(input);
|
|
57
|
-
} catch {
|
|
58
|
-
throw new ResponseError(
|
|
59
|
-
input,
|
|
60
|
-
400,
|
|
61
|
-
"Wrong input",
|
|
62
|
-
"The id parameter must be an integer number."
|
|
63
|
-
);
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
|
|
67
103
|
/**
|
|
68
104
|
* Creates a successful result from a ReturnInfo tuple.
|
|
69
105
|
*
|
|
File without changes
|
package/src/utilities/types.ts
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Represents a standardized error response structure for API endpoints
|
|
3
|
-
* @class
|
|
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 class ResponseError extends Error {
|
|
11
|
-
public constructor(
|
|
12
|
-
public message: string,
|
|
13
|
-
public status?: number,
|
|
14
|
-
public details?: string,
|
|
15
|
-
public code?: string,
|
|
16
|
-
public stack?: string
|
|
17
|
-
) {
|
|
18
|
-
super(message);
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export type ReturnInfo<T> = [T | null, ResponseError | null];
|
|
23
|
-
export type AsyncReturnInfo<T> = Promise<[T | null, ResponseError | null]>;
|