codeweaver 3.1.3 → 4.0.1

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.
Files changed (79) hide show
  1. package/README.md +56 -73
  2. package/package.json +23 -1
  3. package/src/config.ts +17 -15
  4. package/src/constants.ts +1 -0
  5. package/src/core/aws/api-gateway.ts +187 -0
  6. package/src/core/aws/basic-types.ts +147 -0
  7. package/src/core/aws/dynamodb.ts +187 -0
  8. package/src/core/aws/index.ts +9 -0
  9. package/src/core/aws/lambda.ts +199 -0
  10. package/src/core/aws/message-broker.ts +167 -0
  11. package/src/core/aws/message.ts +259 -0
  12. package/src/core/aws/s3.ts +136 -0
  13. package/src/core/aws/utilities.ts +44 -0
  14. package/src/core/cache/basic-types.ts +17 -0
  15. package/src/core/cache/decorator.ts +72 -0
  16. package/src/core/cache/index.ts +4 -0
  17. package/src/core/cache/memory-cache.class.ts +119 -0
  18. package/src/{utilities/cache/redis-cache.ts → core/cache/redis-cache.class.ts} +58 -10
  19. package/src/core/container/basic-types.ts +10 -0
  20. package/src/{utilities → core/container}/container.ts +7 -17
  21. package/src/core/container/index.ts +2 -0
  22. package/src/{utilities → core/error}/error-handling.ts +1 -65
  23. package/src/core/error/index.ts +3 -0
  24. package/src/core/error/response-error.ts +45 -0
  25. package/src/core/error/send-http-error.ts +15 -0
  26. package/src/core/file/file-helpers.ts +166 -0
  27. package/src/core/file/index.ts +1 -0
  28. package/src/{utilities → core/helpers}/assignment.ts +2 -2
  29. package/src/core/helpers/comparison.ts +86 -0
  30. package/src/{utilities → core/helpers}/conversion.ts +2 -2
  31. package/src/core/helpers/decorators.ts +316 -0
  32. package/src/core/helpers/format.ts +9 -0
  33. package/src/core/helpers/index.ts +7 -0
  34. package/src/core/helpers/range.ts +67 -0
  35. package/src/core/helpers/types.ts +3 -0
  36. package/src/core/logger/index.ts +4 -0
  37. package/src/{utilities/logger/logger.config.ts → core/logger/winston-logger.config.ts} +1 -1
  38. package/src/{utilities → core}/logger/winston-logger.service.ts +3 -3
  39. package/src/core/message-broker/bullmq/basic-types.ts +67 -0
  40. package/src/core/message-broker/bullmq/broker.ts +141 -0
  41. package/src/core/message-broker/bullmq/index.ts +3 -0
  42. package/src/core/message-broker/bullmq/queue.ts +58 -0
  43. package/src/core/message-broker/bullmq/worker.ts +68 -0
  44. package/src/core/message-broker/kafka/basic-types.ts +45 -0
  45. package/src/core/message-broker/kafka/consumer.ts +95 -0
  46. package/src/core/message-broker/kafka/index.ts +3 -0
  47. package/src/core/message-broker/kafka/producer.ts +113 -0
  48. package/src/core/message-broker/rabitmq/basic-types.ts +44 -0
  49. package/src/core/message-broker/rabitmq/channel.ts +95 -0
  50. package/src/core/message-broker/rabitmq/consumer.ts +94 -0
  51. package/src/core/message-broker/rabitmq/index.ts +4 -0
  52. package/src/core/message-broker/rabitmq/producer.ts +100 -0
  53. package/src/core/message-broker/utilities.ts +50 -0
  54. package/src/core/middlewares/basic-types.ts +39 -0
  55. package/src/core/middlewares/decorators.ts +244 -0
  56. package/src/core/middlewares/index.ts +3 -0
  57. package/src/core/middlewares/middlewares.ts +246 -0
  58. package/src/core/parallel/index.ts +3 -0
  59. package/src/{utilities → core}/parallel/parallel.ts +11 -1
  60. package/src/core/rate-limit/basic-types.ts +43 -0
  61. package/src/core/rate-limit/index.ts +4 -0
  62. package/src/core/rate-limit/memory-store.ts +65 -0
  63. package/src/core/rate-limit/rate-limit.ts +134 -0
  64. package/src/core/rate-limit/redis-store.ts +141 -0
  65. package/src/core/retry/basic-types.ts +21 -0
  66. package/src/core/retry/decorator.ts +139 -0
  67. package/src/core/retry/index.ts +2 -0
  68. package/src/main.ts +6 -8
  69. package/src/routers/orders/index.router.ts +5 -1
  70. package/src/routers/orders/order.controller.ts +54 -64
  71. package/src/routers/products/index.router.ts +2 -1
  72. package/src/routers/products/product.controller.ts +33 -68
  73. package/src/routers/users/index.router.ts +1 -1
  74. package/src/routers/users/user.controller.ts +25 -50
  75. package/src/utilities/cache/memory-cache.ts +0 -74
  76. /package/src/{utilities → core}/logger/base-logger.interface.ts +0 -0
  77. /package/src/{utilities → core}/logger/logger.service.ts +0 -0
  78. /package/src/{utilities → core}/parallel/chanel.ts +0 -0
  79. /package/src/{utilities → core}/parallel/worker-pool.ts +0 -0
@@ -1,25 +1,26 @@
1
- import { memoizeAsync, onError, rateLimit, timeout } from "utils-decorators";
2
1
  import { OrderDto, OrderCreationDto, ZodOrderDto } from "./dto/order.dto";
3
- import { ResponseError } from "@/utilities/error-handling";
4
- import { convert, stringToInteger } from "@/utilities/conversion";
2
+ import { ResponseError } from "@/core/error";
3
+ import { convert, stringToInteger } from "@/core/helpers";
5
4
  import { config } from "@/config";
6
5
  import { orders } from "@/db";
7
6
  import { Order, ZodOrder } from "@/entities/order.entity";
8
- import { MapAsyncCache } from "@/utilities/cache/memory-cache";
9
- import { Injectable } from "@/utilities/container";
10
- import { parallelMap } from "@/utilities/parallel/parallel";
7
+ import { Invalidate, MapAsyncCache, Memoize } from "@/core/cache";
8
+ import { Injectable } from "@/core/container";
9
+ import { parallelMap } from "@/core/parallel";
10
+ import { RateLimit } from "@/core/rate-limit";
11
+ import { ErrorHandler, Timeout } from "@/core/middlewares";
11
12
 
12
- function exceedHandler() {
13
+ async function exceedHandler() {
13
14
  const message = "Too much call in allowed window";
14
15
  throw new ResponseError(message, 429);
15
16
  }
16
17
 
17
- function invalidInputHandler(e: ResponseError) {
18
+ async function invalidInputHandler(e: ResponseError) {
18
19
  const message = "Invalid input";
19
20
  throw new ResponseError(message, 400, e.message);
20
21
  }
21
22
 
22
- const ordersCache = new MapAsyncCache<OrderDto[]>(config.cacheSize);
23
+ const ordersCache = new MapAsyncCache<OrderDto[]>(1);
23
24
  const orderCache = new MapAsyncCache<OrderDto>(config.cacheSize);
24
25
 
25
26
  @Injectable()
@@ -31,9 +32,7 @@ const orderCache = new MapAsyncCache<OrderDto>(config.cacheSize);
31
32
  export default class OrderController {
32
33
  // constructor(private readonly orderService: OrderService) { }
33
34
 
34
- @onError({
35
- func: invalidInputHandler,
36
- })
35
+ @ErrorHandler(invalidInputHandler)
37
36
  /**
38
37
  * Validates a string ID and converts it to a number.
39
38
  *
@@ -44,9 +43,7 @@ export default class OrderController {
44
43
  return stringToInteger(id);
45
44
  }
46
45
 
47
- @onError({
48
- func: invalidInputHandler,
49
- })
46
+ @ErrorHandler(invalidInputHandler)
50
47
  /**
51
48
  * Validates and creates a new Order from the given DTO.
52
49
  *
@@ -66,11 +63,12 @@ export default class OrderController {
66
63
  return convert(newOrder, ZodOrder);
67
64
  }
68
65
 
69
- @rateLimit({
70
- timeSpanMs: config.rateLimitTimeSpan,
71
- allowedCalls: config.rateLimitAllowedCalls,
72
- exceedHandler,
73
- })
66
+ @Invalidate(ordersCache, true)
67
+ @RateLimit(
68
+ config.rateLimitTimeSpan,
69
+ config.rateLimitAllowedCalls,
70
+ exceedHandler
71
+ )
74
72
  /**
75
73
  * Create a new order
76
74
  * @param {Order} order - Order creation data
@@ -80,41 +78,35 @@ export default class OrderController {
80
78
  */
81
79
  public async create(order: Order): Promise<void> {
82
80
  orders.push(order);
83
- await ordersCache.delete("key");
84
81
  }
85
82
 
86
- @memoizeAsync({
87
- cache: ordersCache,
88
- keyResolver: () => "key",
89
- expirationTimeMs: config.memoizeTime,
90
- })
91
- @timeout(config.timeout)
92
- @rateLimit({
93
- timeSpanMs: config.rateLimitTimeSpan,
94
- allowedCalls: config.rateLimitAllowedCalls,
95
- exceedHandler,
96
- })
83
+ @Memoize(ordersCache, () => "key")
84
+ @Timeout(config.timeout)
85
+ @RateLimit(
86
+ config.rateLimitTimeSpan,
87
+ config.rateLimitAllowedCalls,
88
+ exceedHandler
89
+ )
97
90
  /**
98
91
  * Retrieves all orders
99
92
  * @returns List of orders
100
93
  */
101
- public async getAll(): Promise<OrderDto[]> {
102
- return await parallelMap(
103
- orders,
104
- async (order) => await convert(order, ZodOrderDto)
94
+ public async getAll(
95
+ timeoutSignal?: AbortSignal
96
+ ): Promise<(OrderDto | null)[]> {
97
+ return await parallelMap(orders, async (order) =>
98
+ timeoutSignal?.aborted == false
99
+ ? await convert<Order, OrderDto>(order, ZodOrderDto)
100
+ : null
105
101
  );
106
102
  }
107
103
 
108
- @memoizeAsync({
109
- cache: orderCache,
110
- keyResolver: (id: number) => id.toString(),
111
- expirationTimeMs: config.memoizeTime,
112
- })
113
- @rateLimit({
114
- timeSpanMs: config.rateLimitTimeSpan,
115
- allowedCalls: config.rateLimitAllowedCalls,
116
- exceedHandler,
117
- })
104
+ @Memoize(orderCache)
105
+ @RateLimit(
106
+ config.rateLimitTimeSpan,
107
+ config.rateLimitAllowedCalls,
108
+ exceedHandler
109
+ )
118
110
  /**
119
111
  * Finds an order by its ID
120
112
  * @param {number} id - Order ID as string
@@ -128,11 +120,13 @@ export default class OrderController {
128
120
  return await convert(order, ZodOrder);
129
121
  }
130
122
 
131
- @rateLimit({
132
- timeSpanMs: config.rateLimitTimeSpan,
133
- allowedCalls: config.rateLimitAllowedCalls,
134
- exceedHandler,
135
- })
123
+ @Invalidate(orderCache)
124
+ @Invalidate(ordersCache, true)
125
+ @RateLimit(
126
+ config.rateLimitTimeSpan,
127
+ config.rateLimitAllowedCalls,
128
+ exceedHandler
129
+ )
136
130
  /**
137
131
  * Cancel an existing order
138
132
  * @param {number} id - Order ID to cancel
@@ -145,21 +139,20 @@ export default class OrderController {
145
139
  if (order.status != "Processing") {
146
140
  throw new ResponseError(
147
141
  "Cancellation is not available unless the order is in processing status.",
148
- 400
142
+ 409
149
143
  );
150
144
  }
151
145
  order.status = "Canceled";
152
146
  order.deliveredAt = new Date();
153
-
154
- await orderCache.delete(id.toString());
155
- await ordersCache.delete("key");
156
147
  }
157
148
 
158
- @rateLimit({
159
- timeSpanMs: config.rateLimitTimeSpan,
160
- allowedCalls: config.rateLimitAllowedCalls,
161
- exceedHandler,
162
- })
149
+ @Invalidate(orderCache)
150
+ @Invalidate(ordersCache, true)
151
+ @RateLimit(
152
+ config.rateLimitTimeSpan,
153
+ config.rateLimitAllowedCalls,
154
+ exceedHandler
155
+ )
163
156
  /**
164
157
  * Mark an order as delivered
165
158
  * @param {number} id - Order ID to mark as delivered
@@ -172,13 +165,10 @@ export default class OrderController {
172
165
  if (order.status != "Processing") {
173
166
  throw new ResponseError(
174
167
  "Delivery is only available when the order is in processing status.",
175
- 400
168
+ 409
176
169
  );
177
170
  }
178
171
  order.status = "Delivered";
179
172
  order.deliveredAt = new Date();
180
-
181
- await orderCache.delete(id.toString());
182
- await ordersCache.delete("key");
183
173
  }
184
174
  }
@@ -1,7 +1,7 @@
1
1
  import { Router, Request, Response } from "express";
2
2
  import asyncHandler from "express-async-handler";
3
3
  import ProductController from "./product.controller";
4
- import { resolve } from "@/utilities/container";
4
+ import { resolve } from "@/core/container";
5
5
 
6
6
  const router = Router();
7
7
  const productController = resolve(ProductController);
@@ -201,6 +201,7 @@ router.delete(
201
201
  asyncHandler(async (req: Request, res: Response) => {
202
202
  const id = await productController.validateId(req.params.id);
203
203
  await productController.delete(id);
204
+ res.status(204).send();
204
205
  })
205
206
  );
206
207
 
@@ -1,31 +1,27 @@
1
- import { memoizeAsync, onError, rateLimit, timeout } from "utils-decorators";
2
1
  import {
3
2
  ProductCreationDto,
4
3
  ProductDto,
5
4
  ProductUpdateDto,
6
5
  ZodProductDto,
7
6
  } from "./dto/product.dto";
8
- import { MapAsyncCache } from "@/utilities/cache/memory-cache";
9
- import { convert, stringToInteger } from "@/utilities/conversion";
7
+ import { Invalidate, MapAsyncCache, Memoize } from "@/core/cache";
8
+ import { convert, stringToInteger } from "@/core/helpers";
10
9
  import { config } from "@/config";
11
- import { ResponseError } from "@/utilities/error-handling";
10
+ import { ResponseError } from "@/core/error";
12
11
  import { products } from "@/db";
13
12
  import { Product, ZodProduct } from "@/entities/product.entity";
14
- import { Injectable } from "@/utilities/container";
15
- import assign from "@/utilities/assignment";
16
- import { parallelMap } from "@/utilities/parallel/parallel";
13
+ import { Injectable } from "@/core/container";
14
+ import { assign } from "@/core/helpers";
15
+ import { parallelMap } from "@/core/parallel";
16
+ import { ErrorHandler, Timeout } from "@/core/middlewares";
17
+ import { RateLimit } from "@/core/rate-limit";
17
18
 
18
- function exceedHandler() {
19
- const message = "Too much call in allowed window";
20
- throw new ResponseError(message, 429);
21
- }
22
-
23
- function invalidInputHandler(e: ResponseError) {
19
+ async function invalidInputHandler(e: ResponseError) {
24
20
  const message = "Invalid input";
25
21
  throw new ResponseError(message, 400, e.message);
26
22
  }
27
23
 
28
- const productsCache = new MapAsyncCache<ProductDto[]>(config.cacheSize);
24
+ const productsCache = new MapAsyncCache<ProductDto[]>(1);
29
25
  const productCache = new MapAsyncCache<ProductDto>(config.cacheSize);
30
26
 
31
27
  @Injectable()
@@ -37,9 +33,7 @@ const productCache = new MapAsyncCache<ProductDto>(config.cacheSize);
37
33
  export default class ProductController {
38
34
  // constructor(private readonly productService: ProductService) { }
39
35
 
40
- @onError({
41
- func: invalidInputHandler,
42
- })
36
+ @ErrorHandler(invalidInputHandler)
43
37
  /**
44
38
  * Validates a string ID and converts it to a number.
45
39
  *
@@ -50,9 +44,7 @@ export default class ProductController {
50
44
  return stringToInteger(id);
51
45
  }
52
46
 
53
- @onError({
54
- func: invalidInputHandler,
55
- })
47
+ @ErrorHandler(invalidInputHandler)
56
48
  /**
57
49
  * Validates and creates a new Product from the given DTO.
58
50
  *
@@ -65,9 +57,7 @@ export default class ProductController {
65
57
  return await convert({ ...product, id: products.length + 1 }, ZodProduct);
66
58
  }
67
59
 
68
- @onError({
69
- func: invalidInputHandler,
70
- })
60
+ @ErrorHandler(invalidInputHandler)
71
61
  /**
72
62
  * Validates and creates a new Product from the given DTO.
73
63
  *
@@ -80,11 +70,8 @@ export default class ProductController {
80
70
  return await convert(product, ZodProduct);
81
71
  }
82
72
 
83
- @rateLimit({
84
- timeSpanMs: config.rateLimitTimeSpan,
85
- allowedCalls: config.rateLimitAllowedCalls,
86
- exceedHandler,
87
- })
73
+ @Invalidate(productsCache, true)
74
+ @RateLimit(config.rateLimitTimeSpan, config.rateLimitAllowedCalls)
88
75
  /**
89
76
  * Creates a new product with validated data
90
77
  * @param {Product} product - Product creation data validated by Zod schema
@@ -94,41 +81,27 @@ export default class ProductController {
94
81
  */
95
82
  public async create(product: Product): Promise<void> {
96
83
  products.push(product);
97
- await productsCache.delete("key");
98
84
  }
99
85
 
100
- @memoizeAsync({
101
- cache: productsCache,
102
- keyResolver: () => "key",
103
- expirationTimeMs: config.memoizeTime,
104
- })
105
- @timeout(config.timeout)
106
- @rateLimit({
107
- timeSpanMs: config.rateLimitTimeSpan,
108
- allowedCalls: config.rateLimitAllowedCalls,
109
- exceedHandler,
110
- })
86
+ @Memoize(productsCache, () => "key")
87
+ @Timeout(config.timeout)
88
+ @RateLimit(config.rateLimitTimeSpan, config.rateLimitAllowedCalls)
111
89
  /**
112
90
  * Retrieves all products with truncated descriptions
113
91
  * @returns List of products with summarized descriptions
114
92
  */
115
- public async getAll(): Promise<ProductDto[]> {
116
- return await parallelMap(
117
- products,
118
- async (product) => await convert(product, ZodProductDto)
93
+ public async getAll(
94
+ timeoutSignal?: AbortSignal
95
+ ): Promise<(ProductDto | null)[]> {
96
+ return await parallelMap(products, async (product) =>
97
+ timeoutSignal?.aborted == false
98
+ ? await convert<Product, ProductDto>(product, ZodProductDto)
99
+ : null
119
100
  );
120
101
  }
121
102
 
122
- @memoizeAsync({
123
- cache: productCache,
124
- keyResolver: (id: number) => id.toString(),
125
- expirationTimeMs: config.memoizeTime,
126
- })
127
- @rateLimit({
128
- timeSpanMs: config.rateLimitTimeSpan,
129
- allowedCalls: config.rateLimitAllowedCalls,
130
- exceedHandler,
131
- })
103
+ @Memoize(productCache)
104
+ @RateLimit(config.rateLimitTimeSpan, config.rateLimitAllowedCalls)
132
105
  /**
133
106
  * Finds a product by its ID
134
107
  * @param {number} id - Product ID as string
@@ -142,11 +115,9 @@ export default class ProductController {
142
115
  return await convert(product, ZodProduct);
143
116
  }
144
117
 
145
- @rateLimit({
146
- timeSpanMs: config.rateLimitTimeSpan,
147
- allowedCalls: config.rateLimitAllowedCalls,
148
- exceedHandler,
149
- })
118
+ @Invalidate(productCache)
119
+ @Invalidate(productsCache, true)
120
+ @RateLimit(config.rateLimitTimeSpan, config.rateLimitAllowedCalls)
150
121
  /**
151
122
  * Updates an existing product
152
123
  * @param {number} id - Product ID to update
@@ -162,18 +133,14 @@ export default class ProductController {
162
133
  const product = await this.get(id);
163
134
  if (product != null) {
164
135
  await assign(product, updateData, ZodProduct);
165
- await productCache.delete(updateData.id.toString());
166
- await productsCache.delete("key");
167
136
  } else {
168
137
  throw new ResponseError("Product dose not exist.", 404);
169
138
  }
170
139
  }
171
140
 
172
- @rateLimit({
173
- timeSpanMs: config.rateLimitTimeSpan,
174
- allowedCalls: config.rateLimitAllowedCalls,
175
- exceedHandler,
176
- })
141
+ @Invalidate(productCache)
142
+ @Invalidate(productsCache, true)
143
+ @RateLimit(config.rateLimitTimeSpan, config.rateLimitAllowedCalls)
177
144
  /**
178
145
  * Deletes a product by ID
179
146
  * @param {number} id - Product ID to delete
@@ -186,8 +153,6 @@ export default class ProductController {
186
153
  if (index == -1) {
187
154
  throw new ResponseError("Product dose not exist.", 404);
188
155
  }
189
- await productCache.delete(id.toString());
190
- await productsCache.delete("key");
191
156
  products.splice(index, 1)[0];
192
157
  }
193
158
  }
@@ -1,7 +1,7 @@
1
1
  import { Router, Request, Response } from "express";
2
2
  import asyncHandler from "express-async-handler";
3
3
  import UserController from "./user.controller";
4
- import { resolve } from "@/utilities/container";
4
+ import { resolve } from "@/core/container";
5
5
 
6
6
  const router = Router();
7
7
  const userController = resolve(UserController);
@@ -1,26 +1,22 @@
1
1
  import { UserCreationDto, UserDto, ZodUserDto } from "./dto/user.dto";
2
- import { memoizeAsync, onError, rateLimit, timeout } from "utils-decorators";
3
- import { ResponseError } from "@/utilities/error-handling";
4
- import { convert, stringToInteger } from "@/utilities/conversion";
2
+ import { ResponseError } from "@/core/error";
3
+ import { convert, stringToInteger } from "@/core/helpers";
5
4
  import { config } from "@/config";
6
5
  import { users } from "@/db";
7
6
  import { User, ZodUser } from "@/entities/user.entity";
8
- import { MapAsyncCache } from "@/utilities/cache/memory-cache";
9
- import { Injectable } from "@/utilities/container";
10
- import { parallelMap } from "@/utilities/parallel/parallel";
7
+ import { Invalidate, MapAsyncCache, Memoize } from "@/core/cache";
8
+ import { Injectable } from "@/core/container";
9
+ import { parallelMap } from "@/core/parallel";
10
+ import { ErrorHandler, LogMethod, Timeout } from "@/core/middlewares";
11
+ import { RateLimit } from "@/core/rate-limit";
11
12
 
12
- function exceedHandler() {
13
- const message = "Too much call in allowed window";
14
- throw new ResponseError(message, 429);
15
- }
16
-
17
- function invalidInputHandler(e: ResponseError) {
13
+ async function invalidInputHandler(e: ResponseError) {
18
14
  const message = "Invalid input";
19
15
  throw new ResponseError(message, 400, e?.message);
20
16
  }
21
17
 
22
- const usersCache = new MapAsyncCache<UserDto[]>(config.cacheSize);
23
18
  const userCache = new MapAsyncCache<UserDto>(config.cacheSize);
19
+ const usersCache = new MapAsyncCache<UserDto[]>(1);
24
20
 
25
21
  @Injectable()
26
22
  /**
@@ -31,9 +27,7 @@ const userCache = new MapAsyncCache<UserDto>(config.cacheSize);
31
27
  export default class UserController {
32
28
  // constructor(private readonly userService: UserService) { }
33
29
 
34
- @onError({
35
- func: invalidInputHandler,
36
- })
30
+ @ErrorHandler(invalidInputHandler)
37
31
  /**
38
32
  * Validates a string ID and converts it to a number.
39
33
  *
@@ -44,9 +38,7 @@ export default class UserController {
44
38
  return stringToInteger(id);
45
39
  }
46
40
 
47
- @onError({
48
- func: invalidInputHandler,
49
- })
41
+ @ErrorHandler(invalidInputHandler)
50
42
  /**
51
43
  * Validates and creates a new User from the given DTO.
52
44
  *
@@ -57,11 +49,8 @@ export default class UserController {
57
49
  return await convert(user, ZodUser);
58
50
  }
59
51
 
60
- @rateLimit({
61
- timeSpanMs: config.rateLimitTimeSpan,
62
- allowedCalls: config.rateLimitAllowedCalls,
63
- exceedHandler,
64
- })
52
+ @Invalidate(usersCache, true)
53
+ @RateLimit(config.rateLimitTimeSpan, config.rateLimitAllowedCalls)
65
54
  /**
66
55
  * Create a new user
67
56
  * @param {User} user - User creation data validated by Zod schema
@@ -71,42 +60,28 @@ export default class UserController {
71
60
  */
72
61
  public async create(user: User): Promise<void> {
73
62
  users.push(user);
74
- await usersCache.delete("key");
75
63
  }
76
64
 
77
- @memoizeAsync({
78
- cache: usersCache,
79
- keyResolver: () => "key",
80
- expirationTimeMs: config.memoizeTime,
81
- })
82
- @timeout(config.timeout)
83
- @rateLimit({
84
- timeSpanMs: config.rateLimitTimeSpan,
85
- allowedCalls: config.rateLimitAllowedCalls,
86
- exceedHandler,
87
- })
65
+ @Memoize(usersCache, () => "key")
66
+ @Timeout(config.timeout)
67
+ @RateLimit(config.rateLimitTimeSpan, config.rateLimitAllowedCalls)
88
68
  /**
89
69
  * Get all users
90
70
  * @returns {Promise<UserDto[]>} List of users with hidden password fields
91
71
  * @throws {ResponseError} 500 - When rate limit exceeded
92
72
  */
93
- public async getAll(): Promise<UserDto[]> {
94
- return await parallelMap(
95
- users,
96
- async (user) => await convert(user, ZodUserDto)
73
+ public async getAll(
74
+ timeoutSignal?: AbortSignal
75
+ ): Promise<(UserDto | null)[]> {
76
+ return await parallelMap(users, async (user) =>
77
+ timeoutSignal?.aborted == false
78
+ ? await convert<User, UserDto>(user!, ZodUserDto)
79
+ : null
97
80
  );
98
81
  }
99
82
 
100
- @memoizeAsync({
101
- cache: userCache,
102
- keyResolver: (id: number) => id.toString(),
103
- expirationTimeMs: config.memoizeTime,
104
- })
105
- @rateLimit({
106
- timeSpanMs: config.rateLimitTimeSpan,
107
- allowedCalls: config.rateLimitAllowedCalls,
108
- exceedHandler,
109
- })
83
+ @Memoize(userCache)
84
+ @RateLimit(config.rateLimitTimeSpan, config.rateLimitAllowedCalls)
110
85
  /**
111
86
  * Get user by ID
112
87
  * @param {number} id - User ID as string
@@ -1,74 +0,0 @@
1
- import { AsyncCache } from "utils-decorators";
2
-
3
- /**
4
- * A simple in-memory map-based cache implementing AsyncCache<T>.
5
- * This is a straightforward wrapper around a Map<string, T>.
6
- */
7
- export class MapAsyncCache<T> implements AsyncCache<T> {
8
- public constructor(
9
- private capacity?: number,
10
- private cache?: Map<string, T>
11
- ) {
12
- this.capacity = this.capacity ?? Number.POSITIVE_INFINITY;
13
- this.cache = this.cache ?? new Map<string, T>();
14
- }
15
-
16
- /**
17
- * Asynchronously set a value by key.
18
- * @param key The cache key
19
- * @param value The value to cache
20
- */
21
- async set(key: string, value: T): Promise<void> {
22
- if (value != null) {
23
- if (this.cache?.has(key)) {
24
- this.cache?.set(key, value);
25
- } else {
26
- if (
27
- (this.capacity ?? Number.POSITIVE_INFINITY) > (this.cache?.size ?? 0)
28
- ) {
29
- this.cache?.set(key, value);
30
- }
31
- }
32
- } else {
33
- this.cache?.delete(key);
34
- }
35
- }
36
-
37
- /**
38
- * Asynchronously get a value by key.
39
- * - If the key exists, returns the value.
40
- * - If the key does not exist, returns undefined cast to T to satisfy the Promise<T> return type.
41
- *
42
- * Note: Returning undefined may be surprising for callers expecting a strict A/B.
43
- * Consider returning `T | undefined` from AsyncCache if you can adjust the interface,
44
- * or throw a ResponseError for "not found" depending on your usage.
45
- */
46
- async get(key: string): Promise<T> {
47
- if (this.cache?.has(key)) {
48
- return this.cache?.get(key) ?? (null as T);
49
- }
50
-
51
- return null as T;
52
- }
53
-
54
- /**
55
- * Asynchronously delete a value by key.
56
- */
57
- async delete(key: string): Promise<void> {
58
- this.cache?.delete(key);
59
- }
60
-
61
- /**
62
- * Asynchronously check if a key exists in the cache.
63
- */
64
- async has(key: string): Promise<boolean> {
65
- return this.cache?.has(key) ?? false;
66
- }
67
-
68
- /**
69
- * Asynchronously clear the cache.
70
- */
71
- async clear(key: string): Promise<void> {
72
- this.cache?.clear();
73
- }
74
- }
File without changes
File without changes