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
package/README.md CHANGED
@@ -1,21 +1,27 @@
1
- # A lightweight framework built on top of Express and TypeScript
1
+ # Codeweaver
2
2
 
3
3
  ## Overview
4
4
 
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.
5
+ **Codeweaver** is a lightweight framework and boilerplate built on top of `Express` and `TypeScript`. 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.
6
6
 
7
7
  ## Features and Technologies Used
8
8
 
9
- - **Node.js**
10
- - **Express**: A lightweight web framework for building server-side applications in Node.js.
11
- - **TypeScript**: Adds strong typing for enhanced development experience and reduced runtime errors.
12
9
  - **Modular Router Structure**: Automates importing and mounting routers, ensuring a clean separation of endpoints and logic for easier scalability.
13
- - **Dependency resolver**: A simple dependency resolver that uses a lightweight container to manage and inject dependencies at runtime.
14
10
  - **Swagger Integration**: Automatically generates interactive API documentation, facilitating easier understanding of available endpoints for developers and consumers.
15
- - **Async Handlers**: Utilizes async/await syntax for cleaner, more maintainable asynchronous code without callback nesting.
16
- - **Zod**: Implements schema validation for input data.
17
- - **Utils-decorators**: A collection of middleware utilities utils-decorators (throttling, caching, and error handling) designed to strengthen application resilience.
11
+ - **Dependency resolver**: A simple dependency resolver that uses a lightweight container to manage and inject dependencies at runtime.
18
12
  - **Logger**: A Winston-based logger (with LogForm) that provides scalable, leveled logging, structured JSON output, and pluggable transports (console and file)
13
+ - **AWS integrations**: API Gateway, Lambda, S3, SNS, SES, SQS, and DynamoDB adapters
14
+ - **IO**: Reading, writing JSON and YAML
15
+ - **Messaging**: Kafka, RabbitMQ, BullMQ adapters
16
+ - **Parallelism**: Channel, Worker-pool
17
+ - **Decorators and Middlewares**:
18
+ - Caching: Memory and Redis backends
19
+ - Rate limiting, Retry, Debounce, Timeout
20
+ - Guard (authentication/authorization)
21
+ - Before/After hooks
22
+ - Memoization
23
+ - Logging: Winston-based, LogForm, structured JSON, pluggable transports
24
+ - Error handling: Centralized error types and handlers
19
25
 
20
26
  Here's a revised Installation section that explicitly supports pnpm in addition to npm. I kept the formatting and steps intact, adding clear pnpm equivalents.
21
27
 
@@ -47,6 +53,14 @@ To get started with the project, follow these steps:
47
53
 
48
54
  3. **Run the application**:
49
55
 
56
+ Using pnpm:
57
+
58
+ ```bash
59
+ pnpm start
60
+ ```
61
+
62
+ Using npm:
63
+
50
64
  ```bash
51
65
  npm start
52
66
  ```
@@ -55,6 +69,15 @@ To get started with the project, follow these steps:
55
69
 
56
70
  5. **Build**: Compile the TypeScript files for the production environment:
57
71
 
72
+ Using pnpm:
73
+
74
+ ```bash
75
+ pnpm run build
76
+ pnpm run serve
77
+ ```
78
+
79
+ Using npm:
80
+
58
81
  ```bash
59
82
  npm run build
60
83
  npm run serve
@@ -101,7 +124,7 @@ Example of a basic router:
101
124
  import { Router, Request, Response } from "express";
102
125
  import asyncHandler from "express-async-handler";
103
126
  import UserController from "./user.controller";
104
- import { resolve } from "@/utilities/container";
127
+ import { resolve } from "@/core/container";
105
128
 
106
129
  const router = Router();
107
130
  const userController = resolve(UserController);
@@ -211,28 +234,23 @@ Here’s a brief breakdown of key components used in the `UserController`:
211
234
 
212
235
  ```typescript
213
236
  import { UserCreationDto, UserDto, ZodUserDto } from "./dto/user.dto";
214
- import { memoizeAsync, onError, rateLimit, timeout } from "utils-decorators";
215
- import { ResponseError } from "@/utilities/error-handling";
216
- import { convert, stringToInteger } from "@/utilities/conversion";
237
+ import { ResponseError } from "@/core/error";
238
+ import { convert, stringToInteger } from "@/core/helpers";
217
239
  import { config } from "@/config";
218
240
  import { users } from "@/db";
219
241
  import { User, ZodUser } from "@/entities/user.entity";
220
- import { MapAsyncCache } from "@/utilities/cache/memory-cache";
221
- import { Injectable } from "@/utilities/container";
222
- import { parallelMap } from "@/utilities/parallel/parallel";
242
+ import { Invalidate, MapAsyncCache, Memoize } from "@/core/cache";
243
+ import { Injectable } from "@/core/container";
244
+ import { parallelMap } from "@/core/parallel";
245
+ import { ErrorHandler, LogMethod, Timeout } from "@/core/middlewares";
246
+ import { RateLimit } from "@/core/rate-limit";
223
247
 
224
- function exceedHandler() {
225
- const message = "Too much call in allowed window";
226
- throw new ResponseError(message, 429);
227
- }
228
-
229
- function invalidInputHandler(e: ResponseError) {
248
+ async function invalidInputHandler(e: ResponseError) {
230
249
  const message = "Invalid input";
231
250
  throw new ResponseError(message, 400, e?.message);
232
251
  }
233
252
 
234
253
  const usersCache = new MapAsyncCache<UserDto[]>(config.cacheSize);
235
- const userCache = new MapAsyncCache<UserDto>(config.cacheSize);
236
254
 
237
255
  @Injectable()
238
256
  /**
@@ -243,9 +261,7 @@ const userCache = new MapAsyncCache<UserDto>(config.cacheSize);
243
261
  export default class UserController {
244
262
  // constructor(private readonly userService: UserService) { }
245
263
 
246
- @onError({
247
- func: invalidInputHandler,
248
- })
264
+ @ErrorHandler(invalidInputHandler)
249
265
  /**
250
266
  * Validates a string ID and converts it to a number.
251
267
  *
@@ -256,9 +272,7 @@ export default class UserController {
256
272
  return stringToInteger(id);
257
273
  }
258
274
 
259
- @onError({
260
- func: invalidInputHandler,
261
- })
275
+ @ErrorHandler(invalidInputHandler)
262
276
  /**
263
277
  * Validates and creates a new User from the given DTO.
264
278
  *
@@ -269,11 +283,8 @@ export default class UserController {
269
283
  return await convert(user, ZodUser);
270
284
  }
271
285
 
272
- @rateLimit({
273
- timeSpanMs: config.rateLimitTimeSpan,
274
- allowedCalls: config.rateLimitAllowedCalls,
275
- exceedHandler,
276
- })
286
+ @Invalidate(usersCache)
287
+ @RateLimit(config.rateLimitTimeSpan, config.rateLimitAllowedCalls)
277
288
  /**
278
289
  * Create a new user
279
290
  * @param {User} user - User creation data validated by Zod schema
@@ -283,42 +294,26 @@ export default class UserController {
283
294
  */
284
295
  public async create(user: User): Promise<void> {
285
296
  users.push(user);
286
- await usersCache.delete("key");
287
297
  }
288
298
 
289
- @memoizeAsync({
290
- cache: usersCache,
291
- keyResolver: () => "key",
292
- expirationTimeMs: config.memoizeTime,
293
- })
294
- @timeout(config.timeout)
295
- @rateLimit({
296
- timeSpanMs: config.rateLimitTimeSpan,
297
- allowedCalls: config.rateLimitAllowedCalls,
298
- exceedHandler,
299
- })
299
+ @Memoize(usersCache)
300
+ @Timeout(config.timeout)
301
+ @RateLimit(config.rateLimitTimeSpan, config.rateLimitAllowedCalls)
300
302
  /**
301
303
  * Get all users
302
304
  * @returns {Promise<UserDto[]>} List of users with hidden password fields
303
305
  * @throws {ResponseError} 500 - When rate limit exceeded
304
306
  */
305
- public async getAll(): Promise<UserDto[]> {
306
- return await parallelMap(
307
- users,
308
- async (user) => await convert(user, ZodUserDto)
307
+ public async getAll(signal?: AbortSignal): Promise<(UserDto | undefined)[]> {
308
+ return await parallelMap(users, async (user) =>
309
+ signal?.aborted == false
310
+ ? await convert<User, UserDto>(user!, ZodUserDto)
311
+ : null
309
312
  );
310
313
  }
311
314
 
312
- @memoizeAsync({
313
- cache: userCache,
314
- keyResolver: (id: number) => id.toString(),
315
- expirationTimeMs: config.memoizeTime,
316
- })
317
- @rateLimit({
318
- timeSpanMs: config.rateLimitTimeSpan,
319
- allowedCalls: config.rateLimitAllowedCalls,
320
- exceedHandler,
321
- })
315
+ @Memoize(usersCache)
316
+ @RateLimit(config.rateLimitTimeSpan, config.rateLimitAllowedCalls)
322
317
  /**
323
318
  * Get user by ID
324
319
  * @param {number} id - User ID as string
@@ -329,7 +324,7 @@ export default class UserController {
329
324
  public async get(id: number): Promise<UserDto> {
330
325
  const user = users.find((user) => user.id === id);
331
326
  if (user == null) {
332
- throw new ResponseError("Product not found");
327
+ throw new ResponseError("User not found");
333
328
  }
334
329
  return convert(user, ZodUserDto);
335
330
  }
@@ -338,18 +333,6 @@ export default class UserController {
338
333
 
339
334
  This structure not only supports effective code organization but also ensures that each part of the application is working towards the same goal: a scalable, maintainable, and robust API.
340
335
 
341
- ### Async Handlers
342
-
343
- To maintain cleaner code and improve error handling, the app suggests the `express-async-handler` package that automatically catches exceptions inside of async express routes and passing them to the express error handlers. This allows you to focus on writing the business logic without worrying about try/catch blocks.
344
-
345
- ### API Documentation
346
-
347
- Once the application is running, visit the Swagger UI at http://localhost:3000/api-docs. This automatically generated documentation will provide you with all available routes along with details on request parameters, response structures, and possible error codes.
348
-
349
- ### Decorators
350
-
351
- To prevent abuse of your API, you can utilize throttling, caching, and error handling decorators from the `utils-decorators` package. This package provides decorators that can be applied directly to your service and controller classes.
352
-
353
336
  ### Contributing
354
337
 
355
338
  Contributions are welcome! If you have suggestions for improvements or new features, feel free to create an issue or submit a pull request.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codeweaver",
3
- "version": "3.1.3",
3
+ "version": "4.0.1",
4
4
  "main": "src/main.ts",
5
5
  "bin": {
6
6
  "codeweaver": "command.js"
@@ -26,13 +26,30 @@
26
26
  "license": "MIT",
27
27
  "description": "An unopinionated microframework built with Express, TypeScript, Zod, Swagger",
28
28
  "dependencies": {
29
+ "@aws-sdk/client-api-gateway": "^3.943.0",
30
+ "@aws-sdk/client-dynamodb": "^3.943.0",
31
+ "@aws-sdk/client-lambda": "^3.942.0",
32
+ "@aws-sdk/client-s3": "^3.940.0",
33
+ "@aws-sdk/client-sesv2": "^3.943.0",
34
+ "@aws-sdk/client-sns": "^3.943.0",
35
+ "@aws-sdk/client-sqs": "^3.943.0",
36
+ "@aws-sdk/lib-dynamodb": "^3.943.0",
37
+ "@aws-sdk/s3-request-presigner": "^3.940.0",
38
+ "amqplib": "^0.10.9",
39
+ "bullmq": "^5.65.1",
29
40
  "cors": "^2.8.5",
30
41
  "dotenv": "^17.2.3",
42
+ "drizzle-orm": "^0.45.0",
31
43
  "express": "^5.1.0",
32
44
  "express-async-handler": "^1.2.0",
33
45
  "express-winston": "^4.2.0",
46
+ "helmet": "^8.1.0",
34
47
  "ioredis": "^5.8.2",
48
+ "js-yaml": "^4.1.1",
49
+ "jsonwebtoken": "^9.0.2",
50
+ "kafkajs": "^2.2.4",
35
51
  "logform": "^2.7.0",
52
+ "passport": "^0.7.0",
36
53
  "reflect-metadata": "^0.2.2",
37
54
  "swagger-jsdoc": "^3.7.0",
38
55
  "utils-decorators": "^2.10.0",
@@ -41,11 +58,16 @@
41
58
  "zod": "^4.0.14"
42
59
  },
43
60
  "devDependencies": {
61
+ "@aws-sdk/types": "^3.936.0",
44
62
  "@types/cors": "^2.8.19",
45
63
  "@types/express": "^5.0.3",
64
+ "@types/js-yaml": "^4.0.9",
65
+ "@types/jsonwebtoken": "^9.0.10",
46
66
  "@types/node": "^24.1.0",
67
+ "@types/passport": "^1.0.17",
47
68
  "copyfiles": "^2.4.1",
48
69
  "cross-env": "^10.0.0",
70
+ "drizzle-kit": "^0.31.8",
49
71
  "nodemon": "^3.1.10",
50
72
  "swagger-ui-express": "^5.0.1",
51
73
  "ts-node": "^10.9.2",
package/src/config.ts CHANGED
@@ -7,10 +7,10 @@ import {
7
7
  port,
8
8
  cacheSize,
9
9
  http,
10
- } from "./constants";
10
+ debounceTimeSpan,
11
+ } from "@/constants";
11
12
  import { SwaggerOptions } from "./swagger-options";
12
- import { stringToBoolean } from "./utilities/conversion";
13
- import { logger } from "./utilities/logger/logger.config";
13
+ import { stringToBoolean } from "@/core/helpers/conversion";
14
14
 
15
15
  /**
16
16
  * Main application configuration
@@ -20,16 +20,18 @@ import { logger } from "./utilities/logger/logger.config";
20
20
  * @property {SwaggerOptions} swaggerOptions - Swagger configuration
21
21
  */
22
22
  interface Config {
23
- devMode: boolean;
24
- http: string;
25
- port: number;
26
- swagger: boolean;
27
- swaggerOptions: SwaggerOptions;
28
- timeout: number;
29
- rateLimitTimeSpan: number;
30
- rateLimitAllowedCalls: number;
31
- memoizeTime: number;
32
- cacheSize: number;
23
+ readonly devMode: boolean;
24
+ readonly http: string;
25
+ readonly port: number;
26
+ readonly swagger: boolean;
27
+ readonly swaggerOptions: SwaggerOptions;
28
+ readonly timeout: number;
29
+ readonly rateLimitTimeSpan: number;
30
+ readonly rateLimitAllowedCalls: number;
31
+ readonly memoizeTime: number;
32
+ readonly cacheSize: number;
33
+ readonly jwtSecretKey: string;
34
+ readonly debounceTimeSpan: number;
33
35
  }
34
36
 
35
37
  export const config: Config = {
@@ -65,6 +67,6 @@ export const config: Config = {
65
67
  Number(process.env.RATE_LIMIT_ALLOWED_CALLS) || rateLimitAllowedCalls,
66
68
  memoizeTime: Number(process.env.MEMOIZE_TIME) || memoizeTime,
67
69
  cacheSize: Number(process.env.CACHE_SIZE) || cacheSize,
70
+ jwtSecretKey: process.env.JWT_SECRET_KEY!,
71
+ debounceTimeSpan: Number(process.env.DEBOUNCE_TIME_SPAN) || debounceTimeSpan,
68
72
  };
69
-
70
- export const container = { logger };
package/src/constants.ts CHANGED
@@ -10,3 +10,4 @@ export const swaggerPath = "/api-docs";
10
10
  export const routerDir = "/routers";
11
11
  export const routerExtension = ".router";
12
12
  export const defaultRouter = "index";
13
+ export const debounceTimeSpan = 10;
@@ -0,0 +1,187 @@
1
+ import {
2
+ APIGatewayClient,
3
+ CreateRestApiCommand,
4
+ GetRestApisCommand,
5
+ CreateResourceCommand,
6
+ PutMethodCommand,
7
+ PutIntegrationCommand,
8
+ CreateDeploymentCommand,
9
+ GetResourcesCommand,
10
+ } from "@aws-sdk/client-api-gateway";
11
+ import { LambdaClient, AddPermissionCommand } from "@aws-sdk/client-lambda";
12
+
13
+ /**
14
+ * Comprehensive TypeScript library for managing AWS API Gateway REST APIs
15
+ * and linking them to AWS Lambda functions.
16
+ * Supports full lifecycle: API creation, resource/method setup,
17
+ * Lambda integration, permissions, and deployment.
18
+ */
19
+ export class APIGateway {
20
+ public apiGateway!: APIGatewayClient;
21
+ public lambda!: LambdaClient;
22
+
23
+ /**
24
+ * Creates an instance of APIGatewayLambdaLinker.
25
+ * @param options - Configuration options.
26
+ * @param [options.region=us-east-1] - AWS region for operations.
27
+ */
28
+ public constructor(region?: string, ...args: any[]) {
29
+ if (region == null) {
30
+ this.apiGateway = new APIGatewayClient({ region, ...args });
31
+ this.lambda = new LambdaClient({ region, ...args });
32
+ }
33
+ }
34
+
35
+ /**
36
+ * Creates a new REST API in API Gateway.
37
+ * @param name - Unique name for the REST API.
38
+ * @param [description] - Optional description of the API.
39
+ * @returns Promise resolving to the created RestApi object containing API ID and details.
40
+ * @throws Will throw if API creation fails (e.g., duplicate name, permissions).
41
+ */
42
+ public async createRestApi(name: string, description?: string): Promise<any> {
43
+ const command = new CreateRestApiCommand({
44
+ name,
45
+ description,
46
+ endpointConfiguration: { types: ["REGIONAL"] },
47
+ });
48
+ return this.apiGateway.send(command);
49
+ }
50
+
51
+ /**
52
+ * Lists all REST APIs in the current region.
53
+ * @returns Promise resolving to array of RestApi objects or empty array.
54
+ */
55
+ public async listRestApis(): Promise<any[]> {
56
+ const command = new GetRestApisCommand({});
57
+ const response = await this.apiGateway.send(command);
58
+ return response.items || [];
59
+ }
60
+
61
+ /**
62
+ * Retrieves all resources for a specific REST API.
63
+ * @param restApiId - The ID of the REST API.
64
+ * @returns Promise resolving to array of Resource objects or empty array.
65
+ */
66
+ public async getResources(restApiId: string): Promise<any[]> {
67
+ const command = new GetResourcesCommand({ restApiId });
68
+ const response = await this.apiGateway.send(command);
69
+ return response.items || [];
70
+ }
71
+
72
+ /**
73
+ * Creates a new resource (path segment) under a parent resource.
74
+ * Use root resource (path '/') as parentId for top-level paths like '/items'.
75
+ * @param restApiId - The ID of the REST API.
76
+ * @param parentId - ID of the parent resource.
77
+ * @param pathPart - Path segment name (e.g., 'items' for '/items').
78
+ * @returns Promise resolving to the created Resource object.
79
+ */
80
+ public async createResource(
81
+ restApiId: string,
82
+ parentId: string,
83
+ pathPart: string
84
+ ): Promise<any> {
85
+ const command = new CreateResourceCommand({
86
+ restApiId,
87
+ parentId,
88
+ pathPart,
89
+ });
90
+ return this.apiGateway.send(command);
91
+ }
92
+
93
+ /**
94
+ * Creates or updates an HTTP method on a resource.
95
+ * @param restApiId - The ID of the REST API.
96
+ * @param resourceId - The ID of the resource.
97
+ * @param httpMethod - HTTP method (GET, POST, PUT, DELETE, etc.).
98
+ * @param [authorizationType="NONE"] - Authorization type (NONE, AWS_IAM, CUSTOM, COGNITO_USER_POOLS).
99
+ * @returns Promise resolving to the method configuration.
100
+ */
101
+ public async putMethod(
102
+ restApiId: string,
103
+ resourceId: string,
104
+ httpMethod: string,
105
+ authorizationType: string = "NONE"
106
+ ): Promise<any> {
107
+ const command = new PutMethodCommand({
108
+ restApiId,
109
+ resourceId,
110
+ httpMethod,
111
+ authorizationType,
112
+ apiKeyRequired: false,
113
+ });
114
+ return this.apiGateway.send(command);
115
+ }
116
+
117
+ /**
118
+ * Links a Lambda function as the backend integration for an HTTP method using AWS_PROXY integration.
119
+ * @param restApiId - The ID of the REST API.
120
+ * @param resourceId - The ID of the resource.
121
+ * @param httpMethod - HTTP method (must match previously created method).
122
+ * @param lambdaArn - Full ARN of the Lambda function.
123
+ * @returns Promise resolving to the integration configuration.
124
+ */
125
+ public async putIntegration(
126
+ restApiId: string,
127
+ resourceId: string,
128
+ httpMethod: string,
129
+ lambdaArn: string
130
+ ): Promise<any> {
131
+ const region = this.apiGateway.config.region || "us-east-1";
132
+ const command = new PutIntegrationCommand({
133
+ restApiId,
134
+ resourceId,
135
+ httpMethod,
136
+ type: "AWS_PROXY",
137
+ integrationHttpMethod: "POST",
138
+ uri: `arn:aws:apigateway:${region}:lambda:path/2015-03-31/functions/${lambdaArn}/invocations`,
139
+ });
140
+ return this.apiGateway.send(command);
141
+ }
142
+
143
+ /**
144
+ * Adds Lambda execution permission for API Gateway to invoke the function.
145
+ * Required for Lambda integration to work.
146
+ * @param functionName - Name or ARN of the Lambda function.
147
+ * @param statementId - Unique ID for this permission statement.
148
+ * @param restApiId - The ID of the REST API.
149
+ * @param region - AWS region.
150
+ * @param accountId - AWS account ID (12 digits).
151
+ * @returns Promise resolving to the permission policy statement.
152
+ */
153
+ public async addLambdaPermission(
154
+ functionName: string,
155
+ statementId: string,
156
+ restApiId: string,
157
+ region: string,
158
+ accountId: string
159
+ ): Promise<any> {
160
+ const sourceArn = `arn:aws:execute-api:${region}:${accountId}:${restApiId}/*/*/*`;
161
+ const command = new AddPermissionCommand({
162
+ FunctionName: functionName,
163
+ StatementId: statementId,
164
+ Action: "lambda:InvokeFunction",
165
+ Principal: "apigateway.amazonaws.com",
166
+ SourceArn: sourceArn,
167
+ });
168
+ return this.lambda.send(command);
169
+ }
170
+
171
+ /**
172
+ * Deploys the REST API to a specific stage, making it accessible via invoke URL.
173
+ * @param restApiId - The ID of the REST API.
174
+ * @param stageName - Stage name (dev, prod, test, etc.).
175
+ * @returns Promise resolving to the deployment object.
176
+ */
177
+ public async createDeployment(
178
+ restApiId: string,
179
+ stageName: string
180
+ ): Promise<any> {
181
+ const command = new CreateDeploymentCommand({
182
+ restApiId,
183
+ stageName,
184
+ });
185
+ return this.apiGateway.send(command);
186
+ }
187
+ }
@@ -0,0 +1,147 @@
1
+ import { Runtime } from "@aws-sdk/client-lambda";
2
+
3
+ /**
4
+ * Lambda function creation parameters
5
+ * @see https://docs.aws.amazon.com/lambda/latest/dg/lambda-runtimes.html
6
+ */
7
+ export interface LambdaCreateParams {
8
+ /** Lambda function name to create or update (if already exists) in AWS */
9
+ functionName: string;
10
+ /**
11
+ * IAM role ARN
12
+ *
13
+ * @default arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
14
+ * @see https://docs.aws.amazon.com/lambda/latest/dg/lambda-permissions.html
15
+ */
16
+ roleArn: string;
17
+ /**
18
+ * Path to zip file containing lambda code
19
+ *
20
+ * @default index.zip
21
+ * @see https://docs.aws.amazon.com/lambda/latest/dg/lambda-zip-file-format.html
22
+ */
23
+ zipFilePath: string;
24
+ /**
25
+ * Lambda handler
26
+ *
27
+ * @default index.handler
28
+ */
29
+ handler: string;
30
+ /**
31
+ * Lambda runtime
32
+ *
33
+ * @default Runtime.nodejs18x
34
+ */
35
+ runtime?: Runtime;
36
+ /**
37
+ * Timeout in seconds
38
+ *
39
+ * @default 15
40
+ */
41
+ timeout?: number;
42
+ /**
43
+ * Memory size in MB
44
+ *
45
+ * @default 128
46
+ */
47
+ memorySize?: number;
48
+ /**
49
+ * Environment variables
50
+ *
51
+ * @default {}
52
+ * @see https://docs.aws.amazon.com/lambda/latest/dg/lambda-environment-variables.html
53
+ */
54
+ environment?: Record<string, string>;
55
+ /**
56
+ * AWS region
57
+
58
+ * @see https://docs.aws.amazon.com/lambda/latest/dg/configuration-regions.html
59
+ */
60
+ region?: string;
61
+ }
62
+
63
+ /**
64
+ * Parameters for uploading a file to an S3 bucket
65
+ */
66
+ export interface UploadParams {
67
+ bucket: string;
68
+ /** Key of the object to create in the bucket */
69
+ key: string;
70
+ filePath: string;
71
+ /**
72
+ * Additional parameters to pass to the PutObjectCommand
73
+ * @see https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObject.html
74
+ */
75
+ extraArgs?: Record<string, any>;
76
+ }
77
+
78
+ /**
79
+ * Parameters for downloading an object from an S3 bucket
80
+ */
81
+ export interface DownloadParams {
82
+ bucket: string;
83
+ /** Key of the object to create in the bucket */
84
+ key: string;
85
+ destPath: string;
86
+ }
87
+
88
+ /**
89
+ * Email message configuration for SES.
90
+ */
91
+ export interface EmailMessage {
92
+ /** Recipient email addresses. */
93
+ to: string[];
94
+ /** Optional CC recipient email addresses. */
95
+ cc?: string[];
96
+ /** Optional BCC recipient email addresses. */
97
+ bcc?: string[];
98
+ /** Email subject line. */
99
+ subject: string;
100
+ /** Plain text body content. */
101
+ textBody?: string;
102
+ /** HTML body content. */
103
+ htmlBody?: string;
104
+ /** Sender email address (must be SES verified). */
105
+ from: string;
106
+ /** Optional reply-to email addresses. */
107
+ replyTo?: string[];
108
+ }
109
+
110
+ /**
111
+ * SMS message configuration for SNS.
112
+ */
113
+ export interface SMSMessage {
114
+ /** Phone number in E.164 format (e.g., '+15551234567'). */
115
+ phoneNumber: string;
116
+ /** Message content (max 160 characters for standard SMS). */
117
+ message: string;
118
+ /** Optional message attributes for customization. */
119
+ attributes?: Record<string, any>;
120
+ }
121
+
122
+ // Define a strict, explicit cache type
123
+ export interface PushPlatformArns {
124
+ /**
125
+ * ARN for the APNS platform application
126
+ * @see https://docs.aws.amazon.com/sns/latest/dg/SNSMobilePush.html
127
+ */
128
+ apns?: string;
129
+ /**
130
+ * ARN for the APNS_SANDBOX platform application
131
+ * @see https://docs.aws.amazon.com/sns/latest/dg/SNSMobilePush.html
132
+ */
133
+ apns_sandbox?: string;
134
+ /**
135
+ * ARN for the FCM platform application
136
+ * @see https://docs.aws.amazon.com/sns/latest/dg/SNSMobilePush.html
137
+ */
138
+ fcm?: string;
139
+ /**
140
+ * ARN for the ADM platform application
141
+ * @see https://docs.aws.amazon.com/sns/latest/dg/SNSMobilePush.html
142
+ */
143
+ adm?: string;
144
+
145
+ /** Additional platforms as needed in a controlled manner */
146
+ [platform: string]: string | undefined;
147
+ }