codeweaver 3.0.6 → 3.0.8
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 +1 -1
- package/package.json +1 -1
- package/src/config.ts +3 -2
- package/src/main.ts +1 -1
- package/src/routers/orders/order.controller.ts +1 -1
- package/src/routers/products/product.controller.ts +1 -1
- package/src/routers/users/user.controller.ts +1 -1
- package/src/utilities/conversion.ts +7 -7
- package/src/utilities/logger/base-logger.interface.ts +25 -0
- package/src/utilities/parallel/parallel.ts +4 -1
- package/src/utilities/parallel/worker-pool.ts +4 -2
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
## Overview
|
|
4
4
|
|
|
5
|
-
**Codeweaver** is an
|
|
5
|
+
**Codeweaver** is an microframework built with `Express`, `TypeScript`, and `Zod` (v4), seamlessly integrated with `Swagger` for comprehensive API documentation. Its modular architecture for routers promotes scalability and organized development, making it easy to expand and maintain. Routers are automatically discovered and wired up through a conventional folder structure, simplifying project organization and reducing boilerplate. Routers can be nested, allowing you to compose complex route trees by placing sub-routers inside parent router folders. It also uses `utils-decorators`, a collection of middleware utilities (throttling, caching, and error handling) designed to strengthen application resilience.
|
|
6
6
|
|
|
7
7
|
## Features and Technologies Used
|
|
8
8
|
|
package/package.json
CHANGED
package/src/config.ts
CHANGED
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
} from "./constants";
|
|
11
11
|
import { SwaggerOptions } from "./swagger-options";
|
|
12
12
|
import { stringToBoolean } from "./utilities/conversion";
|
|
13
|
+
import { logger } from "./utilities/logger/logger.config";
|
|
13
14
|
|
|
14
15
|
/**
|
|
15
16
|
* Main application configuration
|
|
@@ -31,7 +32,7 @@ interface Config {
|
|
|
31
32
|
cacheSize: number;
|
|
32
33
|
}
|
|
33
34
|
|
|
34
|
-
|
|
35
|
+
export const config: Config = {
|
|
35
36
|
devMode: process.env.NODE_ENV !== productionEnvironment,
|
|
36
37
|
http: process.env.HTTP || http,
|
|
37
38
|
port: Number(process.env.PORT) || port,
|
|
@@ -66,4 +67,4 @@ let config: Config = {
|
|
|
66
67
|
cacheSize: Number(process.env.CACHE_SIZE) || cacheSize,
|
|
67
68
|
};
|
|
68
69
|
|
|
69
|
-
export
|
|
70
|
+
export const container = { logger };
|
package/src/main.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import express, { NextFunction, Request, Response } from "express";
|
|
2
2
|
import fs from "fs";
|
|
3
3
|
import path from "path";
|
|
4
|
-
import config from "./config";
|
|
4
|
+
import { config } from "./config";
|
|
5
5
|
import { ResponseError } from "./utilities/error-handling";
|
|
6
6
|
import { resolve } from "./utilities/container";
|
|
7
7
|
import { WinstonLoggerService } from "./utilities/logger/winston-logger.service";
|
|
@@ -2,7 +2,7 @@ import { memoizeAsync, onError, rateLimit, timeout } from "utils-decorators";
|
|
|
2
2
|
import { OrderDto, OrderCreationDto, ZodOrderDto } from "./dto/order.dto";
|
|
3
3
|
import { ResponseError } from "@/utilities/error-handling";
|
|
4
4
|
import { convert, stringToInteger } from "@/utilities/conversion";
|
|
5
|
-
import config from "@/config";
|
|
5
|
+
import { config } from "@/config";
|
|
6
6
|
import { orders } from "@/db";
|
|
7
7
|
import { Order, ZodOrder } from "@/entities/order.entity";
|
|
8
8
|
import { MapAsyncCache } from "@/utilities/cache/memory-cache";
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
} from "./dto/product.dto";
|
|
8
8
|
import { MapAsyncCache } from "@/utilities/cache/memory-cache";
|
|
9
9
|
import { convert, stringToInteger } from "@/utilities/conversion";
|
|
10
|
-
import config from "@/config";
|
|
10
|
+
import { config } from "@/config";
|
|
11
11
|
import { ResponseError } from "@/utilities/error-handling";
|
|
12
12
|
import { products } from "@/db";
|
|
13
13
|
import { Product, ZodProduct } from "@/entities/product.entity";
|
|
@@ -2,7 +2,7 @@ import { UserCreationDto, UserDto, ZodUserDto } from "./dto/user.dto";
|
|
|
2
2
|
import { memoizeAsync, onError, rateLimit, timeout } from "utils-decorators";
|
|
3
3
|
import { ResponseError } from "@/utilities/error-handling";
|
|
4
4
|
import { convert, stringToInteger } from "@/utilities/conversion";
|
|
5
|
-
import config from "@/config";
|
|
5
|
+
import { config } from "@/config";
|
|
6
6
|
import { users } from "@/db";
|
|
7
7
|
import { User, ZodUser } from "@/entities/user.entity";
|
|
8
8
|
import { MapAsyncCache } from "@/utilities/cache/memory-cache";
|
|
@@ -11,18 +11,18 @@ function parseIntegerStrict(input: string): number {
|
|
|
11
11
|
|
|
12
12
|
// Empty or just sign is invalid
|
|
13
13
|
if (s.length === 0 || s === "+" || s === "-") {
|
|
14
|
-
throw new
|
|
14
|
+
throw new TypeError("Invalid integer");
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
// Use a regex to ensure the entire string is an optional sign followed by digits
|
|
18
18
|
if (!/^[+-]?\d+$/.test(s)) {
|
|
19
|
-
throw new
|
|
19
|
+
throw new TypeError("Invalid integer");
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
// Safe parse
|
|
23
23
|
const n = Number(s);
|
|
24
24
|
if (!Number.isSafeInteger(n)) {
|
|
25
|
-
throw new
|
|
25
|
+
throw new TypeError("Integer out of safe range");
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
return n;
|
|
@@ -41,7 +41,7 @@ export function stringToInteger(input: string): number {
|
|
|
41
41
|
try {
|
|
42
42
|
return parseIntegerStrict(input);
|
|
43
43
|
} catch {
|
|
44
|
-
throw new
|
|
44
|
+
throw new TypeError("The input parameter must be a valid integer.");
|
|
45
45
|
}
|
|
46
46
|
}
|
|
47
47
|
|
|
@@ -68,7 +68,7 @@ export function stringToBoolean(input: string): boolean {
|
|
|
68
68
|
return false;
|
|
69
69
|
}
|
|
70
70
|
|
|
71
|
-
throw new
|
|
71
|
+
throw new TypeError(
|
|
72
72
|
"The input parameter must be a boolean (e.g., true/false, 1/0)."
|
|
73
73
|
);
|
|
74
74
|
}
|
|
@@ -89,12 +89,12 @@ export function stringToNumber(input: string): number {
|
|
|
89
89
|
|
|
90
90
|
// Allow finite numbers only
|
|
91
91
|
if (!Number.isFinite(n)) {
|
|
92
|
-
throw new
|
|
92
|
+
throw new TypeError("Invalid number");
|
|
93
93
|
}
|
|
94
94
|
|
|
95
95
|
return n;
|
|
96
96
|
} catch {
|
|
97
|
-
throw new
|
|
97
|
+
throw new TypeError("The input parameter must be a valid number.");
|
|
98
98
|
}
|
|
99
99
|
}
|
|
100
100
|
|
|
@@ -1,11 +1,36 @@
|
|
|
1
1
|
// src/logging/BaseLogger.ts
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* The supported log levels for the logger.
|
|
5
|
+
* - fatal: an unrecoverable error that will terminate the process
|
|
6
|
+
* - error: a recoverable error that should be reported
|
|
7
|
+
* - warn: unexpected situation that is not an error
|
|
8
|
+
* - info: general operational information
|
|
9
|
+
* - debug: detailed information useful for debugging
|
|
10
|
+
* - trace: highly verbose information for tracing execution
|
|
11
|
+
*/
|
|
3
12
|
export type LogLevel = "fatal" | "error" | "warn" | "info" | "debug" | "trace";
|
|
4
13
|
|
|
14
|
+
/**
|
|
15
|
+
* Arbitrary metadata attached to log entries.
|
|
16
|
+
* Keys are strings and values can be any serializable data.
|
|
17
|
+
*/
|
|
5
18
|
export interface Meta {
|
|
6
19
|
[key: string]: unknown;
|
|
7
20
|
}
|
|
8
21
|
|
|
22
|
+
/**
|
|
23
|
+
* A minimal base logger interface that defines a single logging method.
|
|
24
|
+
* Implementations should route messages to the appropriate output (console, file, etc.)
|
|
25
|
+
* according to the provided log level, message, and optional metadata.
|
|
26
|
+
*/
|
|
9
27
|
export interface BaseLogger {
|
|
28
|
+
/**
|
|
29
|
+
* Log a message at the specified log level, with optional metadata.
|
|
30
|
+
*
|
|
31
|
+
* @param level - The severity of the log message. One of: "fatal", "error", "warn", "info", "debug", "trace".
|
|
32
|
+
* @param message - The human-readable log message to record.
|
|
33
|
+
* @param meta - Optional additional structured data to accompany the log entry.
|
|
34
|
+
*/
|
|
10
35
|
log(level: LogLevel, message: string, meta?: Meta): void;
|
|
11
36
|
}
|
|
@@ -9,7 +9,10 @@ import { WorkerPool } from "./worker-pool";
|
|
|
9
9
|
* @param {T} source - The source value to which `destination` will be rebound when the returned function runs.
|
|
10
10
|
* @returns {() => void} A function that, when called, rebinds the captured `destination` to `source`.
|
|
11
11
|
*/
|
|
12
|
-
export function set<T extends object>(
|
|
12
|
+
export function set<T extends object>(
|
|
13
|
+
destination: keyof T,
|
|
14
|
+
source: keyof T
|
|
15
|
+
): () => void {
|
|
13
16
|
return () => {
|
|
14
17
|
destination = source;
|
|
15
18
|
};
|
|
@@ -71,9 +71,11 @@ export class WorkerPool<T, R> {
|
|
|
71
71
|
|
|
72
72
|
// Map all items using a round-robin distribution across workers
|
|
73
73
|
async mapAll(items: T[]): Promise<R[]> {
|
|
74
|
-
if (!Array.isArray(items))
|
|
75
|
-
|
|
74
|
+
if (!Array.isArray(items)) {
|
|
75
|
+
throw new TypeError("Items must be an array");
|
|
76
|
+
}
|
|
76
77
|
|
|
78
|
+
const results: R[] = new Array(items.length);
|
|
77
79
|
const workerCount = this.workers.length;
|
|
78
80
|
const tasks: Promise<void>[] = items.map((payload, idx) => {
|
|
79
81
|
const workerIndex = idx % workerCount;
|