@aetherionfw/infra 1.0.0 → 1.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.
@@ -1,5 +1,20 @@
1
1
  import { Construct } from 'constructs';
2
2
  import { TerraformStack } from 'cdktf';
3
3
  export declare class FrameworkStack extends TerraformStack {
4
+ /** All created Lambda functions indexed by their function name */
5
+ private lambdaFunctions;
6
+ /** All created Cognito User Pools indexed by their props.name */
7
+ private cognitoPools;
4
8
  constructor(scope: Construct, id: string);
9
+ private buildRestApiGateway;
10
+ private buildHttpApiGateway;
11
+ private wireRestApiRoute;
12
+ private wireHttpApiRoute;
13
+ /**
14
+ * Parses a path like `/users/{id}/orders` and creates intermediate
15
+ * API Gateway resources, reusing already-created segments.
16
+ */
17
+ private getOrCreateRestResource;
18
+ private getOrCreateAuthorizer;
19
+ private createCorsOptionsMethod;
5
20
  }
@@ -16,15 +16,36 @@ const iam_role_policy_1 = require("@cdktf/provider-aws/lib/iam-role-policy");
16
16
  const db_instance_1 = require("@cdktf/provider-aws/lib/db-instance");
17
17
  const lambda_function_1 = require("@cdktf/provider-aws/lib/lambda-function");
18
18
  const lambda_event_source_mapping_1 = require("@cdktf/provider-aws/lib/lambda-event-source-mapping");
19
+ const lambda_permission_1 = require("@cdktf/provider-aws/lib/lambda-permission");
20
+ const api_gateway_rest_api_1 = require("@cdktf/provider-aws/lib/api-gateway-rest-api");
21
+ const api_gateway_resource_1 = require("@cdktf/provider-aws/lib/api-gateway-resource");
22
+ const api_gateway_method_1 = require("@cdktf/provider-aws/lib/api-gateway-method");
23
+ const api_gateway_integration_1 = require("@cdktf/provider-aws/lib/api-gateway-integration");
24
+ const api_gateway_deployment_1 = require("@cdktf/provider-aws/lib/api-gateway-deployment");
25
+ const api_gateway_stage_1 = require("@cdktf/provider-aws/lib/api-gateway-stage");
26
+ const api_gateway_authorizer_1 = require("@cdktf/provider-aws/lib/api-gateway-authorizer");
27
+ const api_gateway_method_response_1 = require("@cdktf/provider-aws/lib/api-gateway-method-response");
28
+ const api_gateway_integration_response_1 = require("@cdktf/provider-aws/lib/api-gateway-integration-response");
29
+ const apigatewayv2_api_1 = require("@cdktf/provider-aws/lib/apigatewayv2-api");
30
+ const apigatewayv2_integration_1 = require("@cdktf/provider-aws/lib/apigatewayv2-integration");
31
+ const apigatewayv2_route_1 = require("@cdktf/provider-aws/lib/apigatewayv2-route");
32
+ const apigatewayv2_stage_1 = require("@cdktf/provider-aws/lib/apigatewayv2-stage");
19
33
  const core_1 = require("@aetherionfw/core");
20
34
  class FrameworkStack extends cdktf_1.TerraformStack {
35
+ /** All created Lambda functions indexed by their function name */
36
+ lambdaFunctions = new Map();
37
+ /** All created Cognito User Pools indexed by their props.name */
38
+ cognitoPools = new Map();
21
39
  constructor(scope, id) {
22
40
  super(scope, id);
23
41
  new provider_1.AwsProvider(this, 'AWS', {
24
42
  region: 'us-east-1',
25
43
  });
26
44
  const registry = core_1.MetadataRegistry.getInstance();
45
+ // ────────────────────────────────────────────
27
46
  // 1. Build Infra Resources
47
+ // ────────────────────────────────────────────
48
+ const apiGatewayConfigs = new Map();
28
49
  const infraClasses = registry.getInfraClasses();
29
50
  for (const target of infraClasses) {
30
51
  const resources = registry.getInfraResources(target);
@@ -34,7 +55,6 @@ class FrameworkStack extends cdktf_1.TerraformStack {
34
55
  case 'S3Bucket':
35
56
  new s3_bucket_1.S3Bucket(this, res.name, {
36
57
  bucket: res.props.name,
37
- // Minimal abstracted configuration mapped to raw CDKTF
38
58
  });
39
59
  break;
40
60
  case 'DynamoTable':
@@ -64,7 +84,6 @@ class FrameworkStack extends cdktf_1.TerraformStack {
64
84
  });
65
85
  break;
66
86
  case 'CloudFrontDistribution':
67
- // Simplified mapping for a highly complex resource
68
87
  new cloudfront_distribution_1.CloudfrontDistribution(this, res.name, {
69
88
  enabled: true,
70
89
  origin: [{
@@ -83,11 +102,13 @@ class FrameworkStack extends cdktf_1.TerraformStack {
83
102
  restrictions: { geoRestriction: { restrictionType: 'none' } },
84
103
  });
85
104
  break;
86
- case 'CognitoUserPool':
87
- new cognito_user_pool_1.CognitoUserPool(this, res.name, {
105
+ case 'CognitoUserPool': {
106
+ const pool = new cognito_user_pool_1.CognitoUserPool(this, res.name, {
88
107
  name: res.props.name,
89
108
  });
109
+ this.cognitoPools.set(res.props.name, pool);
90
110
  break;
111
+ }
91
112
  case 'Vpc':
92
113
  new vpc_1.Vpc(this, res.name, {
93
114
  cidrBlock: res.props.cidr,
@@ -99,7 +120,7 @@ class FrameworkStack extends cdktf_1.TerraformStack {
99
120
  case 'IamRole':
100
121
  new iam_role_1.IamRole(this, res.name, {
101
122
  name: res.props.name,
102
- assumeRolePolicy: res.props.assumedBy, // Assume this is a JSON string passed in
123
+ assumeRolePolicy: res.props.assumedBy,
103
124
  });
104
125
  break;
105
126
  case 'RdsInstance':
@@ -107,23 +128,27 @@ class FrameworkStack extends cdktf_1.TerraformStack {
107
128
  engine: res.props.engine,
108
129
  instanceClass: res.props.size,
109
130
  dbName: res.props.dbName,
110
- skipFinalSnapshot: true, // safe default for dev frameworks
131
+ skipFinalSnapshot: true,
111
132
  });
112
133
  break;
134
+ case 'ApiGateway':
135
+ // Collect for later processing (after Lambdas are created)
136
+ apiGatewayConfigs.set(res.props.name, { infraResource: res, props: res.props });
137
+ break;
113
138
  default:
114
139
  console.warn(`Unknown infra resource type: ${res.type}`);
115
140
  }
116
141
  }
117
142
  }
143
+ // ────────────────────────────────────────────
118
144
  // 2. Build Lambdas and IAM Policies (1:1 Lambda per Handle Architecture)
145
+ // ────────────────────────────────────────────
119
146
  const controllers = registry.getControllers();
120
147
  for (const [target, controllerMeta] of controllers) {
121
148
  const handles = registry.getHandles(target);
122
149
  const iamPermissions = registry.getIamPermissions(target);
123
- const routes = registry.getRoutes(target);
124
150
  const sqsTriggers = registry.getSqsTriggers(target);
125
151
  if (handles.length === 0) {
126
- // Fallback or skip if no methods are decorated with @Handle
127
152
  continue;
128
153
  }
129
154
  for (const handle of handles) {
@@ -145,7 +170,6 @@ class FrameworkStack extends cdktf_1.TerraformStack {
145
170
  // 2b. Attach IAM Policies (Method overrides Class)
146
171
  let handlePerms = iamPermissions.find(p => p.methodName === methodName);
147
172
  if (!handlePerms) {
148
- // Fallback to class-level permissions
149
173
  handlePerms = iamPermissions.find(p => !p.methodName);
150
174
  }
151
175
  if (handlePerms) {
@@ -178,26 +202,344 @@ class FrameworkStack extends cdktf_1.TerraformStack {
178
202
  memorySize: handle.memorySize || controllerMeta.memorySize || 128,
179
203
  timeout: handle.timeout || controllerMeta.timeout || 3,
180
204
  role: role.arn,
181
- filename: 'dummy.zip', // CDKTF requires a deployment package
205
+ filename: 'dummy.zip',
182
206
  handler: 'index.handler',
183
207
  environment: {
184
208
  variables: {
185
- AETHERION_TARGET_CLASS: controllerMeta.lambdaName, // Storing for debug
209
+ AETHERION_TARGET_CLASS: controllerMeta.lambdaName,
186
210
  AETHERION_TARGET_METHOD: methodName,
187
211
  }
188
212
  }
189
213
  });
214
+ this.lambdaFunctions.set(lambdaName, lambdaFunction);
190
215
  // 2d. Check for SQS Triggers targeting this handle
191
216
  const handleTriggers = sqsTriggers.filter(t => t.methodName === methodName);
192
217
  for (const trigger of handleTriggers) {
193
218
  console.log(`Linking SQS Trigger ${trigger.queueName} to ${lambdaName}`);
194
219
  new lambda_event_source_mapping_1.LambdaEventSourceMapping(this, `${lambdaName}-${trigger.queueName}-mapping`, {
195
220
  functionName: lambdaFunction.arn,
196
- eventSourceArn: `arn:aws:sqs:us-east-1:123456789012:${trigger.queueName}`, // mock
221
+ eventSourceArn: `arn:aws:sqs:us-east-1:123456789012:${trigger.queueName}`,
197
222
  });
198
223
  }
199
224
  }
200
225
  }
226
+ // ────────────────────────────────────────────
227
+ // 3. Build API Gateways and wire Routes
228
+ // ────────────────────────────────────────────
229
+ const apiRefs = new Map();
230
+ // 3a. Create or import each API Gateway
231
+ for (const [apiName, config] of apiGatewayConfigs) {
232
+ const props = config.props;
233
+ console.log(`Building API Gateway: ${apiName} (${props.type})`);
234
+ if (props.type === 'REST') {
235
+ this.buildRestApiGateway(apiName, props, apiRefs);
236
+ }
237
+ else {
238
+ this.buildHttpApiGateway(apiName, props, apiRefs);
239
+ }
240
+ }
241
+ // 3b. Wire controllers to their API Gateways
242
+ for (const [target, controllerMeta] of controllers) {
243
+ if (!controllerMeta.apiGateway)
244
+ continue;
245
+ const apiRef = apiRefs.get(controllerMeta.apiGateway);
246
+ if (!apiRef) {
247
+ console.warn(`API Gateway "${controllerMeta.apiGateway}" not found for controller "${controllerMeta.lambdaName}"`);
248
+ continue;
249
+ }
250
+ const routes = registry.getRoutes(target);
251
+ const handles = registry.getHandles(target);
252
+ for (const route of routes) {
253
+ // Find the matching handle for this route to get the lambda name
254
+ const handle = handles.find(h => h.methodName === route.methodName);
255
+ if (!handle)
256
+ continue;
257
+ const lambdaName = `${controllerMeta.lambdaName}-${route.methodName}`;
258
+ const lambdaFn = this.lambdaFunctions.get(lambdaName);
259
+ if (!lambdaFn)
260
+ continue;
261
+ console.log(`Wiring ${route.method} ${route.path} → ${lambdaName}`);
262
+ if (apiRef.metadata.type === 'REST') {
263
+ this.wireRestApiRoute(apiRef, route, lambdaFn, lambdaName);
264
+ }
265
+ else {
266
+ this.wireHttpApiRoute(apiRef, route, lambdaFn, lambdaName);
267
+ }
268
+ }
269
+ }
270
+ // 3c. Create Deployments and Stages
271
+ for (const [apiName, apiRef] of apiRefs) {
272
+ const stageName = apiRef.metadata.stageName || 'dev';
273
+ if (apiRef.metadata.type === 'REST' && apiRef.restApi && !apiRef.metadata.existingApiId) {
274
+ const deployment = new api_gateway_deployment_1.ApiGatewayDeployment(this, `${apiName}-deployment`, {
275
+ restApiId: apiRef.restApi.id,
276
+ lifecycle: {
277
+ createBeforeDestroy: true,
278
+ },
279
+ });
280
+ new api_gateway_stage_1.ApiGatewayStage(this, `${apiName}-stage`, {
281
+ restApiId: apiRef.restApi.id,
282
+ deploymentId: deployment.id,
283
+ stageName,
284
+ });
285
+ console.log(`Created REST API deployment: ${apiName} → stage "${stageName}"`);
286
+ }
287
+ else if (apiRef.metadata.type === 'HTTP' && apiRef.httpApi) {
288
+ new apigatewayv2_stage_1.Apigatewayv2Stage(this, `${apiName}-stage`, {
289
+ apiId: apiRef.httpApi.id,
290
+ name: stageName,
291
+ autoDeploy: true,
292
+ });
293
+ console.log(`Created HTTP API stage: ${apiName} → "${stageName}"`);
294
+ }
295
+ }
296
+ }
297
+ // ────────────────────────────────────────────
298
+ // REST API Gateway Builder
299
+ // ────────────────────────────────────────────
300
+ buildRestApiGateway(apiName, props, apiRefs) {
301
+ if (props.existingApiId) {
302
+ // Import existing REST API
303
+ console.log(`Importing existing REST API: ${props.existingApiId}`);
304
+ apiRefs.set(apiName, {
305
+ metadata: props,
306
+ rootResourceId: props.existingRootResourceId || '',
307
+ resourceMap: new Map(),
308
+ authorizerMap: new Map(),
309
+ methodIds: [],
310
+ });
311
+ }
312
+ else {
313
+ // Create new REST API
314
+ const restApi = new api_gateway_rest_api_1.ApiGatewayRestApi(this, apiName, {
315
+ name: props.name,
316
+ description: props.description || `API Gateway for ${props.name}`,
317
+ });
318
+ apiRefs.set(apiName, {
319
+ metadata: props,
320
+ restApi,
321
+ rootResourceId: restApi.rootResourceId,
322
+ resourceMap: new Map(),
323
+ authorizerMap: new Map(),
324
+ methodIds: [],
325
+ });
326
+ }
327
+ }
328
+ // ────────────────────────────────────────────
329
+ // HTTP API Gateway Builder
330
+ // ────────────────────────────────────────────
331
+ buildHttpApiGateway(apiName, props, apiRefs) {
332
+ if (props.existingApiId) {
333
+ console.log(`Importing existing HTTP API: ${props.existingApiId}`);
334
+ apiRefs.set(apiName, {
335
+ metadata: props,
336
+ rootResourceId: '',
337
+ resourceMap: new Map(),
338
+ authorizerMap: new Map(),
339
+ methodIds: [],
340
+ });
341
+ }
342
+ else {
343
+ const corsConfig = props.corsEnabled !== false ? {
344
+ allowOrigins: props.corsOrigins || ['*'],
345
+ allowMethods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS'],
346
+ allowHeaders: ['Content-Type', 'Authorization', 'X-Amz-Date', 'X-Api-Key'],
347
+ } : undefined;
348
+ const httpApi = new apigatewayv2_api_1.Apigatewayv2Api(this, apiName, {
349
+ name: props.name,
350
+ protocolType: 'HTTP',
351
+ description: props.description || `HTTP API for ${props.name}`,
352
+ corsConfiguration: corsConfig,
353
+ });
354
+ apiRefs.set(apiName, {
355
+ metadata: props,
356
+ httpApi,
357
+ rootResourceId: '',
358
+ resourceMap: new Map(),
359
+ authorizerMap: new Map(),
360
+ methodIds: [],
361
+ });
362
+ }
363
+ }
364
+ // ────────────────────────────────────────────
365
+ // REST API Route Wiring
366
+ // ────────────────────────────────────────────
367
+ wireRestApiRoute(apiRef, route, lambdaFn, lambdaName) {
368
+ const restApi = apiRef.restApi;
369
+ const restApiId = restApi ? restApi.id : apiRef.metadata.existingApiId;
370
+ // Build hierarchical resources for the path
371
+ const resourceId = this.getOrCreateRestResource(apiRef, route.path, restApiId);
372
+ // Determine authorization type
373
+ let authorizationType = 'NONE';
374
+ let authorizerId;
375
+ if (route.authorizer) {
376
+ const authorizer = this.getOrCreateAuthorizer(apiRef, route.authorizer, restApiId);
377
+ if (authorizer) {
378
+ authorizationType = 'COGNITO_USER_POOLS';
379
+ authorizerId = authorizer.id;
380
+ }
381
+ }
382
+ const methodId = `${lambdaName}-${route.method}`;
383
+ // Create Method
384
+ const method = new api_gateway_method_1.ApiGatewayMethod(this, methodId, {
385
+ restApiId,
386
+ resourceId,
387
+ httpMethod: route.method.toUpperCase(),
388
+ authorization: authorizationType,
389
+ authorizerId,
390
+ });
391
+ apiRef.methodIds.push(methodId);
392
+ // Create Integration (AWS_PROXY)
393
+ new api_gateway_integration_1.ApiGatewayIntegration(this, `${methodId}-integration`, {
394
+ restApiId,
395
+ resourceId,
396
+ httpMethod: method.httpMethod,
397
+ type: 'AWS_PROXY',
398
+ integrationHttpMethod: 'POST',
399
+ uri: lambdaFn.invokeArn,
400
+ });
401
+ // Grant API Gateway permission to invoke Lambda
402
+ new lambda_permission_1.LambdaPermission(this, `${methodId}-permission`, {
403
+ statementId: `AllowAPIGateway-${methodId}`,
404
+ action: 'lambda:InvokeFunction',
405
+ functionName: lambdaFn.functionName,
406
+ principal: 'apigateway.amazonaws.com',
407
+ });
408
+ // CORS: Create OPTIONS method if CORS is enabled
409
+ if (apiRef.metadata.corsEnabled !== false) {
410
+ this.createCorsOptionsMethod(apiRef, route.path, restApiId, resourceId, lambdaName);
411
+ }
412
+ }
413
+ // ────────────────────────────────────────────
414
+ // HTTP API Route Wiring
415
+ // ────────────────────────────────────────────
416
+ wireHttpApiRoute(apiRef, route, lambdaFn, lambdaName) {
417
+ const httpApi = apiRef.httpApi;
418
+ const apiId = httpApi ? httpApi.id : apiRef.metadata.existingApiId;
419
+ const integrationId = `${lambdaName}-${route.method}-int`;
420
+ // Create Integration
421
+ const integration = new apigatewayv2_integration_1.Apigatewayv2Integration(this, integrationId, {
422
+ apiId,
423
+ integrationType: 'AWS_PROXY',
424
+ integrationUri: lambdaFn.invokeArn,
425
+ payloadFormatVersion: '2.0',
426
+ });
427
+ // Create Route
428
+ const routeKey = `${route.method.toUpperCase()} ${route.path}`;
429
+ new apigatewayv2_route_1.Apigatewayv2Route(this, `${lambdaName}-${route.method}-route`, {
430
+ apiId,
431
+ routeKey,
432
+ target: `integrations/${integration.id}`,
433
+ });
434
+ // Grant API Gateway permission to invoke Lambda
435
+ new lambda_permission_1.LambdaPermission(this, `${lambdaName}-${route.method}-permission`, {
436
+ statementId: `AllowHTTPAPI-${lambdaName}-${route.method}`,
437
+ action: 'lambda:InvokeFunction',
438
+ functionName: lambdaFn.functionName,
439
+ principal: 'apigateway.amazonaws.com',
440
+ });
441
+ }
442
+ // ────────────────────────────────────────────
443
+ // Hierarchical Resource Builder (REST API)
444
+ // ────────────────────────────────────────────
445
+ /**
446
+ * Parses a path like `/users/{id}/orders` and creates intermediate
447
+ * API Gateway resources, reusing already-created segments.
448
+ */
449
+ getOrCreateRestResource(apiRef, path, restApiId) {
450
+ if (path === '/')
451
+ return apiRef.rootResourceId;
452
+ const segments = path.split('/').filter(Boolean);
453
+ let currentParentId = apiRef.rootResourceId;
454
+ let currentPath = '';
455
+ for (const segment of segments) {
456
+ currentPath += `/${segment}`;
457
+ if (apiRef.resourceMap.has(currentPath)) {
458
+ currentParentId = apiRef.resourceMap.get(currentPath).id;
459
+ continue;
460
+ }
461
+ const resource = new api_gateway_resource_1.ApiGatewayResource(this, `resource-${currentPath.replace(/[/{}]/g, '-')}`, {
462
+ restApiId,
463
+ parentId: currentParentId,
464
+ pathPart: segment,
465
+ });
466
+ apiRef.resourceMap.set(currentPath, resource);
467
+ currentParentId = resource.id;
468
+ }
469
+ return currentParentId;
470
+ }
471
+ // ────────────────────────────────────────────
472
+ // Cognito Authorizer Builder (REST API)
473
+ // ────────────────────────────────────────────
474
+ getOrCreateAuthorizer(apiRef, authorizerName, restApiId) {
475
+ // Reuse existing authorizer if already created for this API
476
+ if (apiRef.authorizerMap.has(authorizerName)) {
477
+ return apiRef.authorizerMap.get(authorizerName);
478
+ }
479
+ // Look up the Cognito User Pool by name
480
+ const pool = this.cognitoPools.get(authorizerName);
481
+ if (!pool) {
482
+ console.warn(`Authorizer "${authorizerName}" references a Cognito User Pool that was not found in @Infra resources.`);
483
+ return undefined;
484
+ }
485
+ const authorizer = new api_gateway_authorizer_1.ApiGatewayAuthorizer(this, `${authorizerName}-authorizer`, {
486
+ name: `${authorizerName}-cognito-authorizer`,
487
+ restApiId,
488
+ type: 'COGNITO_USER_POOLS',
489
+ providerArns: [pool.arn],
490
+ });
491
+ apiRef.authorizerMap.set(authorizerName, authorizer);
492
+ return authorizer;
493
+ }
494
+ // ────────────────────────────────────────────
495
+ // CORS OPTIONS Method (REST API)
496
+ // ────────────────────────────────────────────
497
+ createCorsOptionsMethod(apiRef, path, restApiId, resourceId, lambdaName) {
498
+ const corsId = `${lambdaName}-OPTIONS-${path.replace(/[/{}]/g, '-')}`;
499
+ // Avoid duplicate OPTIONS methods on the same resource
500
+ if (apiRef.methodIds.includes(corsId))
501
+ return;
502
+ apiRef.methodIds.push(corsId);
503
+ const origins = apiRef.metadata.corsOrigins?.join(',') || '*';
504
+ const headers = 'Content-Type,Authorization,X-Amz-Date,X-Api-Key,X-Amz-Security-Token';
505
+ const methods = 'GET,POST,PUT,PATCH,DELETE,OPTIONS';
506
+ const optionsMethod = new api_gateway_method_1.ApiGatewayMethod(this, corsId, {
507
+ restApiId,
508
+ resourceId,
509
+ httpMethod: 'OPTIONS',
510
+ authorization: 'NONE',
511
+ });
512
+ new api_gateway_integration_1.ApiGatewayIntegration(this, `${corsId}-integration`, {
513
+ restApiId,
514
+ resourceId,
515
+ httpMethod: optionsMethod.httpMethod,
516
+ type: 'MOCK',
517
+ requestTemplates: {
518
+ 'application/json': '{"statusCode": 200}',
519
+ },
520
+ });
521
+ new api_gateway_method_response_1.ApiGatewayMethodResponse(this, `${corsId}-response`, {
522
+ restApiId,
523
+ resourceId,
524
+ httpMethod: optionsMethod.httpMethod,
525
+ statusCode: '200',
526
+ responseParameters: {
527
+ 'method.response.header.Access-Control-Allow-Headers': true,
528
+ 'method.response.header.Access-Control-Allow-Methods': true,
529
+ 'method.response.header.Access-Control-Allow-Origin': true,
530
+ },
531
+ });
532
+ new api_gateway_integration_response_1.ApiGatewayIntegrationResponse(this, `${corsId}-int-response`, {
533
+ restApiId,
534
+ resourceId,
535
+ httpMethod: optionsMethod.httpMethod,
536
+ statusCode: '200',
537
+ responseParameters: {
538
+ 'method.response.header.Access-Control-Allow-Headers': `'${headers}'`,
539
+ 'method.response.header.Access-Control-Allow-Methods': `'${methods}'`,
540
+ 'method.response.header.Access-Control-Allow-Origin': `'${origins}'`,
541
+ },
542
+ });
201
543
  }
202
544
  }
203
545
  exports.FrameworkStack = FrameworkStack;
package/package.json CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "@aetherionfw/infra",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "description": "CDKTF Builder for Aetherion Framework",
5
5
  "main": "dist/main.js",
6
6
  "dependencies": {
7
7
  "cdktf": "^0.20.0",
8
8
  "constructs": "^10.3.0",
9
9
  "@cdktf/provider-aws": "^19.0.0",
10
- "@aetherionfw/core": "1.0.0"
10
+ "@aetherionfw/core": "1.1.0"
11
11
  },
12
12
  "devDependencies": {
13
13
  "typescript": "^5.5.4"