@lafken/main 0.10.2
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/LICENCE +21 -0
- package/README.md +219 -0
- package/lib/app/app.d.ts +41 -0
- package/lib/app/app.js +123 -0
- package/lib/app/app.types.d.ts +135 -0
- package/lib/app/app.types.js +2 -0
- package/lib/app/index.d.ts +2 -0
- package/lib/app/index.js +18 -0
- package/lib/aspect/aspect.d.ts +17 -0
- package/lib/aspect/aspect.js +78 -0
- package/lib/aspect/aspect.types.d.ts +15 -0
- package/lib/aspect/aspect.types.js +2 -0
- package/lib/context/context.d.ts +5 -0
- package/lib/context/context.js +14 -0
- package/lib/context/context.types.d.ts +6 -0
- package/lib/context/context.types.js +2 -0
- package/lib/index.d.ts +2 -0
- package/lib/index.js +18 -0
- package/lib/module/index.d.ts +2 -0
- package/lib/module/index.js +18 -0
- package/lib/module/module.d.ts +35 -0
- package/lib/module/module.js +91 -0
- package/lib/module/module.types.d.ts +42 -0
- package/lib/module/module.types.js +2 -0
- package/package.json +63 -0
package/LICENCE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Aníbal Emilio Jorquera Cornejo
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
# @lafken/main
|
|
2
|
+
|
|
3
|
+
Core entry point for a Lafken serverless application. `@lafken/main` initializes the AWS provider, orchestrates resolvers and modules, and synthesizes the resulting Terraform configuration through CDKTN. It provides `createApp` to bootstrap the application and `createModule` to organize resources into logical groups.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @lafken/main
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Getting Started
|
|
12
|
+
|
|
13
|
+
Create an application with resolvers and modules, then let Lafken generate all the infrastructure:
|
|
14
|
+
|
|
15
|
+
```typescript
|
|
16
|
+
import { createApp, createModule } from '@lafken/main';
|
|
17
|
+
import { ApiResolver } from '@lafken/api/resolver';
|
|
18
|
+
import { QueueResolver } from '@lafken/queue/resolver';
|
|
19
|
+
|
|
20
|
+
// 1. Define modules that group related resources
|
|
21
|
+
const userModule = createModule({
|
|
22
|
+
name: 'users',
|
|
23
|
+
resources: [UserApi, UserQueue],
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
const billingModule = createModule({
|
|
27
|
+
name: 'billing',
|
|
28
|
+
resources: [InvoiceSchedule],
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
// 2. Create the application
|
|
32
|
+
await createApp({
|
|
33
|
+
name: 'my-app',
|
|
34
|
+
modules: [userModule, billingModule],
|
|
35
|
+
resolvers: [
|
|
36
|
+
new ApiResolver({ restApi: { name: 'my-api' } }),
|
|
37
|
+
new QueueResolver(),
|
|
38
|
+
],
|
|
39
|
+
});
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Features
|
|
43
|
+
|
|
44
|
+
### createApp
|
|
45
|
+
|
|
46
|
+
`createApp` is the main entry point. It initializes the AWS stack, runs all resolver lifecycle hooks (`beforeCreate` → `create` → `afterCreate`), and synthesizes the Terraform output:
|
|
47
|
+
|
|
48
|
+
```typescript
|
|
49
|
+
await createApp({
|
|
50
|
+
name: 'my-app',
|
|
51
|
+
modules: [userModule, billingModule],
|
|
52
|
+
resolvers: [new ApiResolver(), new QueueResolver()],
|
|
53
|
+
globalConfig: {
|
|
54
|
+
lambda: {
|
|
55
|
+
memory: 512,
|
|
56
|
+
timeout: 30,
|
|
57
|
+
runtime: 22,
|
|
58
|
+
services: ['dynamodb', 's3', 'sqs'],
|
|
59
|
+
},
|
|
60
|
+
tags: {
|
|
61
|
+
environment: 'production',
|
|
62
|
+
team: 'platform',
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
awsProviderConfig: {
|
|
66
|
+
region: 'us-east-1',
|
|
67
|
+
profile: 'my-aws-profile',
|
|
68
|
+
},
|
|
69
|
+
s3Backend: {
|
|
70
|
+
bucket: 'my-terraform-state',
|
|
71
|
+
key: 'app/terraform.tfstate',
|
|
72
|
+
region: 'us-east-1',
|
|
73
|
+
},
|
|
74
|
+
extend: async (scope) => {
|
|
75
|
+
// Add custom CDKTN constructs after all resolvers finish
|
|
76
|
+
},
|
|
77
|
+
});
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
#### Application Options
|
|
81
|
+
|
|
82
|
+
| Option | Type | Required | Description |
|
|
83
|
+
| ------------------- | ------------------- | -------- | --------------------------------------------------------- |
|
|
84
|
+
| `name` | `string` | Yes | Application name, used as the stack identifier |
|
|
85
|
+
| `modules` | `StackModule[]` | Yes | Modules created with `createModule` |
|
|
86
|
+
| `resolvers` | `ResolverType[]` | Yes | Resolvers that process decorated resources |
|
|
87
|
+
| `globalConfig` | `GlobalConfig` | No | Shared Lambda and tag settings for all resources |
|
|
88
|
+
| `awsProviderConfig` | `AwsProviderConfig` | No | AWS provider settings (region, profile, etc.) |
|
|
89
|
+
| `s3Backend` | `S3BackendConfig` | No | Remote S3 backend for Terraform state |
|
|
90
|
+
| `extend` | `(scope) => void` | No | Callback invoked after all resolvers finish |
|
|
91
|
+
|
|
92
|
+
### createModule
|
|
93
|
+
|
|
94
|
+
`createModule` groups related resources into a logical unit with its own scope, IAM role, and configuration. Each resource inside the module is processed by the matching resolver based on its decorator type:
|
|
95
|
+
|
|
96
|
+
```typescript
|
|
97
|
+
const orderModule = createModule({
|
|
98
|
+
name: 'orders',
|
|
99
|
+
resources: [OrderApi, OrderQueue, OrderSchedule],
|
|
100
|
+
globalConfig: {
|
|
101
|
+
lambda: {
|
|
102
|
+
memory: 256,
|
|
103
|
+
timeout: 15,
|
|
104
|
+
services: ['dynamodb', 'sqs'],
|
|
105
|
+
},
|
|
106
|
+
tags: {
|
|
107
|
+
domain: 'orders',
|
|
108
|
+
},
|
|
109
|
+
},
|
|
110
|
+
});
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
#### Module Options
|
|
114
|
+
|
|
115
|
+
| Option | Type | Required | Description |
|
|
116
|
+
| -------------- | ----------------- | -------- | ----------------------------------------------------- |
|
|
117
|
+
| `name` | `string` | Yes | Module name, used as scope and tag identifier |
|
|
118
|
+
| `resources` | `ClassResource[]` | Yes | Decorated classes to be processed by resolvers |
|
|
119
|
+
| `globalConfig` | `GlobalConfig` | No | Lambda and tag settings scoped to this module |
|
|
120
|
+
|
|
121
|
+
### Global Configuration
|
|
122
|
+
|
|
123
|
+
Global configuration applies default settings to all Lambda functions and resources. Values cascade from application to module to individual resource, with more specific settings taking precedence:
|
|
124
|
+
|
|
125
|
+
```
|
|
126
|
+
App globalConfig → Module globalConfig → Resource-level config
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
#### Lambda Configuration
|
|
130
|
+
|
|
131
|
+
| Option | Type | Description |
|
|
132
|
+
| ------------- | ---------------- | --------------------------------------------------------- |
|
|
133
|
+
| `memory` | `number` | Memory allocation in MB |
|
|
134
|
+
| `timeout` | `number` | Execution timeout in seconds |
|
|
135
|
+
| `runtime` | `20 \| 22 \| 24` | Node.js runtime version |
|
|
136
|
+
| `services` | `Services[]` | AWS services the Lambda can access (creates IAM role) |
|
|
137
|
+
| `enableTrace` | `boolean` | Enable AWS X-Ray tracing |
|
|
138
|
+
| `env` | `EnvironmentValue` | Environment variables for Lambda functions |
|
|
139
|
+
|
|
140
|
+
#### Available Services
|
|
141
|
+
|
|
142
|
+
Services define which AWS resources the Lambda IAM role can access:
|
|
143
|
+
|
|
144
|
+
| Service | Description |
|
|
145
|
+
| --------------- | -------------------------------- |
|
|
146
|
+
| `dynamodb` | Amazon DynamoDB |
|
|
147
|
+
| `s3` | Amazon S3 |
|
|
148
|
+
| `lambda` | AWS Lambda |
|
|
149
|
+
| `cloudwatch` | Amazon CloudWatch Logs |
|
|
150
|
+
| `sqs` | Amazon SQS |
|
|
151
|
+
| `state_machine` | AWS Step Functions |
|
|
152
|
+
| `kms` | AWS KMS |
|
|
153
|
+
| `ssm` | AWS Systems Manager Parameter Store |
|
|
154
|
+
| `event` | Amazon EventBridge |
|
|
155
|
+
|
|
156
|
+
For fine-grained control, specify individual permissions:
|
|
157
|
+
|
|
158
|
+
```typescript
|
|
159
|
+
services: [
|
|
160
|
+
'cloudwatch',
|
|
161
|
+
{ type: 'dynamodb', permissions: ['Query', 'GetItem'] },
|
|
162
|
+
{ type: 's3', permissions: ['GetObject'], resources: ['arn:aws:s3:::my-bucket/*'] },
|
|
163
|
+
{ type: 'custom', serviceName: 'ses', permissions: ['SendEmail'] },
|
|
164
|
+
]
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
#### Tags
|
|
168
|
+
|
|
169
|
+
Tags are applied automatically to all taggable resources. Module-level tags merge with app-level tags, and resource-specific tags take highest precedence:
|
|
170
|
+
|
|
171
|
+
```typescript
|
|
172
|
+
// App-level tags
|
|
173
|
+
globalConfig: {
|
|
174
|
+
tags: {
|
|
175
|
+
environment: 'production',
|
|
176
|
+
project: 'my-app',
|
|
177
|
+
},
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// Module-level tags (merged with app tags)
|
|
181
|
+
globalConfig: {
|
|
182
|
+
tags: {
|
|
183
|
+
domain: 'orders',
|
|
184
|
+
},
|
|
185
|
+
}
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
Lafken also adds automatic tags: `lafken:app` with the app name and `lafken:module` with the module name.
|
|
189
|
+
|
|
190
|
+
### S3 Backend
|
|
191
|
+
|
|
192
|
+
Store Terraform state remotely in an S3 bucket for team collaboration and state locking:
|
|
193
|
+
|
|
194
|
+
```typescript
|
|
195
|
+
await createApp({
|
|
196
|
+
name: 'my-app',
|
|
197
|
+
s3Backend: {
|
|
198
|
+
bucket: 'terraform-state-bucket',
|
|
199
|
+
key: 'apps/my-app/terraform.tfstate',
|
|
200
|
+
region: 'us-east-1',
|
|
201
|
+
dynamodbTable: 'terraform-locks',
|
|
202
|
+
},
|
|
203
|
+
});
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
### Extending the Application
|
|
207
|
+
|
|
208
|
+
The `extend` callback runs after all resolvers have finished processing. Use it to add custom infrastructure that is not covered by the standard resolvers:
|
|
209
|
+
|
|
210
|
+
```typescript
|
|
211
|
+
await createApp({
|
|
212
|
+
name: 'my-app',
|
|
213
|
+
modules: [userModule],
|
|
214
|
+
resolvers: [new ApiResolver()],
|
|
215
|
+
extend: async (scope) => {
|
|
216
|
+
// Add any CDKTN construct directly to the stack
|
|
217
|
+
},
|
|
218
|
+
});
|
|
219
|
+
```
|
package/lib/app/app.d.ts
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { App, TerraformStack } from 'cdktn';
|
|
2
|
+
import type { CreateAppProps } from './app.types';
|
|
3
|
+
export declare class AppStack extends TerraformStack {
|
|
4
|
+
id: string;
|
|
5
|
+
private props;
|
|
6
|
+
constructor(scope: App, id: string, props: CreateAppProps);
|
|
7
|
+
init(): Promise<void>;
|
|
8
|
+
private triggerHook;
|
|
9
|
+
private resolveModuleResources;
|
|
10
|
+
private createRole;
|
|
11
|
+
private addAspectProperties;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Creates and synthesizes a Lafken serverless application.
|
|
15
|
+
*
|
|
16
|
+
* Initializes the CDKTN application, sets up the AWS stack with the
|
|
17
|
+
* provided modules and resolvers, executes the full resolver lifecycle
|
|
18
|
+
* (beforeCreate → create → afterCreate), and synthesizes the resulting
|
|
19
|
+
* Terraform configuration.
|
|
20
|
+
*
|
|
21
|
+
* @param props - The application configuration including name, modules,
|
|
22
|
+
* resolvers, global settings, and optional extensions.
|
|
23
|
+
* @returns The CDKTN `App` instance and the `AppStack` created for the application.
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* await createApp({
|
|
27
|
+
* name: 'my-app',
|
|
28
|
+
* modules: [
|
|
29
|
+
* //... ,
|
|
30
|
+
* ],
|
|
31
|
+
* resolvers: [new ApiResolver({ restApi: { name: 'my-api' } })],
|
|
32
|
+
* globalConfig: {
|
|
33
|
+
* lambda: { runtime: 22, memory: 512 },
|
|
34
|
+
* tags: { environment: 'production' },
|
|
35
|
+
* },
|
|
36
|
+
* });
|
|
37
|
+
*/
|
|
38
|
+
export declare const createApp: (props: CreateAppProps) => Promise<{
|
|
39
|
+
app: App;
|
|
40
|
+
appStack: AppStack;
|
|
41
|
+
}>;
|
package/lib/app/app.js
ADDED
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createApp = exports.AppStack = void 0;
|
|
4
|
+
const provider_1 = require("@cdktn/provider-aws/lib/provider");
|
|
5
|
+
const common_1 = require("@lafken/common");
|
|
6
|
+
const resolver_1 = require("@lafken/resolver");
|
|
7
|
+
const cdktn_1 = require("cdktn");
|
|
8
|
+
const aspect_1 = require("../aspect/aspect");
|
|
9
|
+
const context_1 = require("../context/context");
|
|
10
|
+
(0, common_1.enableBuildEnvVariable)();
|
|
11
|
+
class AppStack extends cdktn_1.TerraformStack {
|
|
12
|
+
id;
|
|
13
|
+
props;
|
|
14
|
+
constructor(scope, id, props) {
|
|
15
|
+
super(scope, id);
|
|
16
|
+
this.id = id;
|
|
17
|
+
this.props = props;
|
|
18
|
+
new context_1.AppContext(this, {
|
|
19
|
+
contextName: resolver_1.ContextName.app,
|
|
20
|
+
globalConfig: props.globalConfig?.lambda,
|
|
21
|
+
contextCreator: props.name,
|
|
22
|
+
});
|
|
23
|
+
new provider_1.AwsProvider(this, 'AWS', props.awsProviderConfig);
|
|
24
|
+
if (props.s3Backend) {
|
|
25
|
+
new cdktn_1.S3Backend(this, props.s3Backend);
|
|
26
|
+
}
|
|
27
|
+
this.createRole();
|
|
28
|
+
}
|
|
29
|
+
async init() {
|
|
30
|
+
const { resolvers, extend } = this.props;
|
|
31
|
+
await this.triggerHook(resolvers, 'beforeCreate');
|
|
32
|
+
await this.resolveModuleResources();
|
|
33
|
+
await this.triggerHook(resolvers, 'afterCreate');
|
|
34
|
+
this.addAspectProperties();
|
|
35
|
+
await resolver_1.lafkenResource.callDependentCallbacks();
|
|
36
|
+
await resolver_1.lambdaAssets.createAssets();
|
|
37
|
+
if (extend) {
|
|
38
|
+
await extend(this);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
async triggerHook(resolvers, trigger) {
|
|
42
|
+
for (const resolver of resolvers) {
|
|
43
|
+
if (resolver[trigger] !== undefined) {
|
|
44
|
+
await resolver[trigger](this);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
async resolveModuleResources() {
|
|
49
|
+
const { modules, resolvers } = this.props;
|
|
50
|
+
const resolversByType = resolvers.reduce((acc, resolver) => {
|
|
51
|
+
acc[resolver.type] = resolver;
|
|
52
|
+
return acc;
|
|
53
|
+
}, {});
|
|
54
|
+
await Promise.all(modules.map((module) => module(this, resolversByType)));
|
|
55
|
+
}
|
|
56
|
+
createRole() {
|
|
57
|
+
const roleName = `${this.props.name}-global-role`;
|
|
58
|
+
const lambdaRole = new resolver_1.Role(this, roleName, {
|
|
59
|
+
name: roleName,
|
|
60
|
+
services: this.props.globalConfig?.lambda?.services || [
|
|
61
|
+
'dynamodb',
|
|
62
|
+
's3',
|
|
63
|
+
'lambda',
|
|
64
|
+
'cloudwatch',
|
|
65
|
+
'sqs',
|
|
66
|
+
'state_machine',
|
|
67
|
+
'kms',
|
|
68
|
+
'ssm',
|
|
69
|
+
'event',
|
|
70
|
+
],
|
|
71
|
+
});
|
|
72
|
+
lambdaRole.isGlobal('app', roleName);
|
|
73
|
+
}
|
|
74
|
+
addAspectProperties() {
|
|
75
|
+
cdktn_1.Aspects.of(this).add(new aspect_1.AppAspect(this, 'app', {
|
|
76
|
+
tags: {
|
|
77
|
+
...(this.props.globalConfig?.tags || {}),
|
|
78
|
+
'lafken:app': this.id,
|
|
79
|
+
},
|
|
80
|
+
environment: this.props.globalConfig?.lambda?.env,
|
|
81
|
+
vpc: this.props.globalConfig?.lambda?.vpcConfig,
|
|
82
|
+
}));
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
exports.AppStack = AppStack;
|
|
86
|
+
/**
|
|
87
|
+
* Creates and synthesizes a Lafken serverless application.
|
|
88
|
+
*
|
|
89
|
+
* Initializes the CDKTN application, sets up the AWS stack with the
|
|
90
|
+
* provided modules and resolvers, executes the full resolver lifecycle
|
|
91
|
+
* (beforeCreate → create → afterCreate), and synthesizes the resulting
|
|
92
|
+
* Terraform configuration.
|
|
93
|
+
*
|
|
94
|
+
* @param props - The application configuration including name, modules,
|
|
95
|
+
* resolvers, global settings, and optional extensions.
|
|
96
|
+
* @returns The CDKTN `App` instance and the `AppStack` created for the application.
|
|
97
|
+
*
|
|
98
|
+
* @example
|
|
99
|
+
* await createApp({
|
|
100
|
+
* name: 'my-app',
|
|
101
|
+
* modules: [
|
|
102
|
+
* //... ,
|
|
103
|
+
* ],
|
|
104
|
+
* resolvers: [new ApiResolver({ restApi: { name: 'my-api' } })],
|
|
105
|
+
* globalConfig: {
|
|
106
|
+
* lambda: { runtime: 22, memory: 512 },
|
|
107
|
+
* tags: { environment: 'production' },
|
|
108
|
+
* },
|
|
109
|
+
* });
|
|
110
|
+
*/
|
|
111
|
+
const createApp = async (props) => {
|
|
112
|
+
const app = new cdktn_1.App({
|
|
113
|
+
skipValidation: true,
|
|
114
|
+
});
|
|
115
|
+
const appStack = new AppStack(app, props.name, props);
|
|
116
|
+
await appStack.init();
|
|
117
|
+
app.synth();
|
|
118
|
+
return {
|
|
119
|
+
app,
|
|
120
|
+
appStack,
|
|
121
|
+
};
|
|
122
|
+
};
|
|
123
|
+
exports.createApp = createApp;
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import type { AwsProviderConfig } from '@cdktn/provider-aws/lib/provider';
|
|
2
|
+
import type { LambdaGlobalConfig, ResolverType } from '@lafken/resolver';
|
|
3
|
+
import type { S3BackendConfig } from 'cdktn';
|
|
4
|
+
import type { StackModule } from '../module';
|
|
5
|
+
import type { ModuleResolverType } from '../module/module.types';
|
|
6
|
+
import type { AppStack } from './app';
|
|
7
|
+
/**
|
|
8
|
+
* Global configuration for the application.
|
|
9
|
+
*
|
|
10
|
+
* Defines shared settings that apply across all resources and Lambda
|
|
11
|
+
* functions in the application. Individual resources can override
|
|
12
|
+
* these values with their own specific configuration.
|
|
13
|
+
*/
|
|
14
|
+
export interface GlobalConfig {
|
|
15
|
+
/**
|
|
16
|
+
* Global Lambda configuration.
|
|
17
|
+
*
|
|
18
|
+
* Specifies default properties for all Lambda functions in the
|
|
19
|
+
* application, such as memory, timeout, runtime, and services.
|
|
20
|
+
* These values can be overridden at the module or resource level.
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* lambda: {
|
|
24
|
+
* memory: 512,
|
|
25
|
+
* timeout: 30,
|
|
26
|
+
* runtime: 22,
|
|
27
|
+
* services: ['s3', 'dynamodb'],
|
|
28
|
+
* }
|
|
29
|
+
*/
|
|
30
|
+
lambda?: LambdaGlobalConfig;
|
|
31
|
+
/**
|
|
32
|
+
* Global resource tags.
|
|
33
|
+
*
|
|
34
|
+
* Specifies a set of tags that will be applied to all resources
|
|
35
|
+
* unless a resource explicitly defines its own tags. In that case,
|
|
36
|
+
* the resource-specific tags will override the global values.
|
|
37
|
+
*/
|
|
38
|
+
tags?: Record<string, string>;
|
|
39
|
+
}
|
|
40
|
+
export interface CreateAppProps {
|
|
41
|
+
/**
|
|
42
|
+
* Application name.
|
|
43
|
+
*
|
|
44
|
+
* Specifies the name of the application, which is used within
|
|
45
|
+
* the AWS stack as an identifier for resources.
|
|
46
|
+
*
|
|
47
|
+
* @example
|
|
48
|
+
* name: "my-awesome-app"
|
|
49
|
+
*/
|
|
50
|
+
name: string;
|
|
51
|
+
/**
|
|
52
|
+
* Application modules.
|
|
53
|
+
*
|
|
54
|
+
* Defines the set of modules to be created within the application.
|
|
55
|
+
* Each module groups related resources and handlers into a logical
|
|
56
|
+
* unit with shared configuration. Modules are created using
|
|
57
|
+
* `createModule()` and receive the application stack scope along
|
|
58
|
+
* with the registered resolvers.
|
|
59
|
+
*
|
|
60
|
+
* @example
|
|
61
|
+
* modules: [
|
|
62
|
+
* createModule({
|
|
63
|
+
* name: 'users',
|
|
64
|
+
* resources: [UserApi, UserQueue],
|
|
65
|
+
* }),
|
|
66
|
+
* ]
|
|
67
|
+
*/
|
|
68
|
+
modules: ((scope: AppStack, resources: Record<string, ModuleResolverType>) => Promise<StackModule>)[];
|
|
69
|
+
/**
|
|
70
|
+
* Resource resolvers.
|
|
71
|
+
*
|
|
72
|
+
* Defines the list of resolvers responsible for creating and configuring
|
|
73
|
+
* resources loaded by the stacks. Each resolver can receive detailed
|
|
74
|
+
* configuration options depending on the type of resource it manages.
|
|
75
|
+
*
|
|
76
|
+
* For example, an `ApiResolver` can include REST API settings,
|
|
77
|
+
* deployment options, and authorization configurations.
|
|
78
|
+
*/
|
|
79
|
+
resolvers: ResolverType[];
|
|
80
|
+
/**
|
|
81
|
+
* Global configuration for the application.
|
|
82
|
+
*
|
|
83
|
+
* Provides settings that are applied across all resources, stacks,
|
|
84
|
+
* and Lambda functions unless overridden at a lower level.
|
|
85
|
+
* This includes global Lambda properties, environment configuration,
|
|
86
|
+
* and resource tags.
|
|
87
|
+
*/
|
|
88
|
+
globalConfig?: GlobalConfig;
|
|
89
|
+
/**
|
|
90
|
+
* AWS provider configuration.
|
|
91
|
+
*
|
|
92
|
+
* Specifies the configuration for the AWS provider used by the
|
|
93
|
+
* application stack. This includes settings such as the AWS region,
|
|
94
|
+
* profile, and other provider-level options required for
|
|
95
|
+
* deploying resources.
|
|
96
|
+
*
|
|
97
|
+
* @example
|
|
98
|
+
* awsProviderConfig: {
|
|
99
|
+
* region: 'us-east-1',
|
|
100
|
+
* profile: 'my-aws-profile',
|
|
101
|
+
* }
|
|
102
|
+
*/
|
|
103
|
+
awsProviderConfig?: AwsProviderConfig;
|
|
104
|
+
/**
|
|
105
|
+
* S3 backend configuration for Terraform state.
|
|
106
|
+
*
|
|
107
|
+
* Configures an S3 bucket as the remote backend for storing the
|
|
108
|
+
* Terraform state file. This enables team collaboration, state
|
|
109
|
+
* locking, and centralized state management.
|
|
110
|
+
*
|
|
111
|
+
* @example
|
|
112
|
+
* s3Backend: {
|
|
113
|
+
* bucket: 'my-terraform-state',
|
|
114
|
+
* key: 'app/terraform.tfstate',
|
|
115
|
+
* region: 'us-east-1',
|
|
116
|
+
* }
|
|
117
|
+
*/
|
|
118
|
+
s3Backend?: S3BackendConfig;
|
|
119
|
+
/**
|
|
120
|
+
* Extension callback.
|
|
121
|
+
*
|
|
122
|
+
* An optional async callback that is invoked after all modules and
|
|
123
|
+
* resolvers have been fully processed. Use this to add custom
|
|
124
|
+
* infrastructure or perform additional configuration on the
|
|
125
|
+
* application stack that is not covered by the standard resolvers.
|
|
126
|
+
*
|
|
127
|
+
* @param scope - The application stack instance.
|
|
128
|
+
*
|
|
129
|
+
* @example
|
|
130
|
+
* extend: async (scope) => {
|
|
131
|
+
* new S3Bucket(scope, 'custom-bucket', { bucket: 'my-bucket' });
|
|
132
|
+
* }
|
|
133
|
+
*/
|
|
134
|
+
extend?: (scope: AppStack) => Promise<void>;
|
|
135
|
+
}
|
package/lib/app/index.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./app"), exports);
|
|
18
|
+
__exportStar(require("./app.types"), exports);
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { IAspect } from 'cdktn';
|
|
2
|
+
import type { Construct, IConstruct } from 'constructs';
|
|
3
|
+
import type { AppAspectProps } from './aspect.types';
|
|
4
|
+
export declare class AppAspect implements IAspect {
|
|
5
|
+
private scope;
|
|
6
|
+
private id;
|
|
7
|
+
private props;
|
|
8
|
+
private env;
|
|
9
|
+
private vpcConfig;
|
|
10
|
+
constructor(scope: Construct, id: string, props: AppAspectProps);
|
|
11
|
+
visit(node: IConstruct): void;
|
|
12
|
+
private initializeEnvironment;
|
|
13
|
+
private initializeVpcConfig;
|
|
14
|
+
private addEnvironmentValues;
|
|
15
|
+
private addVpcConfig;
|
|
16
|
+
private isTaggableResource;
|
|
17
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AppAspect = void 0;
|
|
4
|
+
const lambda_function_1 = require("@cdktn/provider-aws/lib/lambda-function");
|
|
5
|
+
const resolver_1 = require("@lafken/resolver");
|
|
6
|
+
const lambdaValues = {
|
|
7
|
+
env: {},
|
|
8
|
+
vpcConfig: {},
|
|
9
|
+
};
|
|
10
|
+
class AppAspect {
|
|
11
|
+
scope;
|
|
12
|
+
id;
|
|
13
|
+
props;
|
|
14
|
+
env;
|
|
15
|
+
vpcConfig;
|
|
16
|
+
constructor(scope, id, props) {
|
|
17
|
+
this.scope = scope;
|
|
18
|
+
this.id = id;
|
|
19
|
+
this.props = props;
|
|
20
|
+
this.initializeEnvironment();
|
|
21
|
+
this.initializeVpcConfig();
|
|
22
|
+
}
|
|
23
|
+
visit(node) {
|
|
24
|
+
if (this.props.tags && this.isTaggableResource(node)) {
|
|
25
|
+
const currentTags = node.tagsInput || {};
|
|
26
|
+
node.tags = { ...this.props.tags, ...currentTags };
|
|
27
|
+
}
|
|
28
|
+
if (node instanceof lambda_function_1.LambdaFunction) {
|
|
29
|
+
this.addEnvironmentValues(node);
|
|
30
|
+
this.addVpcConfig(node);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
initializeEnvironment() {
|
|
34
|
+
if (!this.props.environment) {
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
const values = new resolver_1.Environment(this.scope, `${this.id}-env`, this.props.environment).getValues();
|
|
38
|
+
if (values === false) {
|
|
39
|
+
throw new Error(`resources in ${this.id} env not found`);
|
|
40
|
+
}
|
|
41
|
+
this.env = values;
|
|
42
|
+
}
|
|
43
|
+
initializeVpcConfig() {
|
|
44
|
+
if (!this.props.vpc) {
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
this.vpcConfig =
|
|
48
|
+
typeof this.props.vpc === 'function'
|
|
49
|
+
? this.props.vpc((0, resolver_1.resolverSSMValues)(this.scope))
|
|
50
|
+
: this.props.vpc;
|
|
51
|
+
}
|
|
52
|
+
addEnvironmentValues(node) {
|
|
53
|
+
if (!this.env) {
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
const currentVars = node.environmentInput?.variables || {};
|
|
57
|
+
lambdaValues.env[node.node.addr] ??= currentVars;
|
|
58
|
+
node.putEnvironment({
|
|
59
|
+
variables: {
|
|
60
|
+
...currentVars,
|
|
61
|
+
...this.env,
|
|
62
|
+
...lambdaValues.env[node.node.addr],
|
|
63
|
+
},
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
addVpcConfig(node) {
|
|
67
|
+
if (!this.vpcConfig) {
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
lambdaValues.vpcConfig[node.node.addr] ??= node.vpcConfigInput || {};
|
|
71
|
+
const hasProperties = Object.keys(lambdaValues.vpcConfig[node.node.addr]).length > 0;
|
|
72
|
+
node.putVpcConfig(hasProperties ? lambdaValues.vpcConfig[node.node.addr] : this.vpcConfig);
|
|
73
|
+
}
|
|
74
|
+
isTaggableResource(resource) {
|
|
75
|
+
return 'tags' in resource && 'tagsInput' in resource;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
exports.AppAspect = AppAspect;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { EnvironmentValue, VpcConfigValue } from '@lafken/common';
|
|
2
|
+
import type { Construct } from 'constructs';
|
|
3
|
+
export interface TaggableResource extends Construct {
|
|
4
|
+
tags?: Record<string, string>;
|
|
5
|
+
tagsInput?: Record<string, string>;
|
|
6
|
+
}
|
|
7
|
+
export interface AppAspectProps {
|
|
8
|
+
tags?: Record<string, string>;
|
|
9
|
+
environment?: EnvironmentValue;
|
|
10
|
+
vpc?: VpcConfigValue;
|
|
11
|
+
}
|
|
12
|
+
export interface OriginalLambdaValue {
|
|
13
|
+
env: Record<string, Record<string, string>>;
|
|
14
|
+
vpcConfig: Record<string, any>;
|
|
15
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AppContext = void 0;
|
|
4
|
+
class AppContext {
|
|
5
|
+
constructor(scope, props) {
|
|
6
|
+
const { contextName, globalConfig = {} } = props;
|
|
7
|
+
const { services: _services, vpcConfig: _vpcConfig, env: _env, ...contextData } = globalConfig || {};
|
|
8
|
+
scope.node.setContext(contextName, {
|
|
9
|
+
...contextData,
|
|
10
|
+
contextCreator: props.contextCreator,
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
exports.AppContext = AppContext;
|
package/lib/index.d.ts
ADDED
package/lib/index.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./app"), exports);
|
|
18
|
+
__exportStar(require("./module"), exports);
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./module"), exports);
|
|
18
|
+
__exportStar(require("./module.types"), exports);
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { Construct } from 'constructs';
|
|
2
|
+
import type { CreateModuleProps, ModuleConstruct, ModuleProps, ModuleResolverType } from './module.types';
|
|
3
|
+
export declare class StackModule extends Construct {
|
|
4
|
+
id: string;
|
|
5
|
+
private props;
|
|
6
|
+
constructor(scope: Construct, id: string, props: ModuleProps);
|
|
7
|
+
generateResources(): Promise<void>;
|
|
8
|
+
private createRole;
|
|
9
|
+
private addAspectProperties;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Creates a module factory for the Lafken application.
|
|
13
|
+
*
|
|
14
|
+
* Returns a function that, when invoked by `createApp`, instantiates a
|
|
15
|
+
* `StackModule` and processes all its declared resources through the
|
|
16
|
+
* registered resolvers. Each module groups related resources into a
|
|
17
|
+
* logical unit with its own scope, IAM role, tags, and optional
|
|
18
|
+
* Lambda configuration.
|
|
19
|
+
*
|
|
20
|
+
* @param props - The module configuration including name, resources, and
|
|
21
|
+
* optional global settings scoped to this module.
|
|
22
|
+
* @returns A factory function consumed by `createApp` to build the module
|
|
23
|
+
* within the application stack.
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* createModule({
|
|
27
|
+
* name: 'users',
|
|
28
|
+
* resources: [UserApi, UserQueue],
|
|
29
|
+
* globalConfig: {
|
|
30
|
+
* lambda: { memory: 256, services: ['dynamodb'] },
|
|
31
|
+
* tags: { team: 'backend' },
|
|
32
|
+
* },
|
|
33
|
+
* })
|
|
34
|
+
*/
|
|
35
|
+
export declare const createModule: (props: CreateModuleProps) => (scope: ModuleConstruct, resolvers: Record<string, ModuleResolverType>) => Promise<StackModule>;
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createModule = exports.StackModule = void 0;
|
|
4
|
+
const common_1 = require("@lafken/common");
|
|
5
|
+
const resolver_1 = require("@lafken/resolver");
|
|
6
|
+
const cdktn_1 = require("cdktn");
|
|
7
|
+
const constructs_1 = require("constructs");
|
|
8
|
+
const aspect_1 = require("../aspect/aspect");
|
|
9
|
+
const context_1 = require("../context/context");
|
|
10
|
+
class StackModule extends constructs_1.Construct {
|
|
11
|
+
id;
|
|
12
|
+
props;
|
|
13
|
+
constructor(scope, id, props) {
|
|
14
|
+
super(scope, id);
|
|
15
|
+
this.id = id;
|
|
16
|
+
this.props = props;
|
|
17
|
+
new context_1.AppContext(this, {
|
|
18
|
+
contextName: resolver_1.ContextName.module,
|
|
19
|
+
globalConfig: props.globalConfig?.lambda,
|
|
20
|
+
contextCreator: props.name,
|
|
21
|
+
});
|
|
22
|
+
this.createRole();
|
|
23
|
+
}
|
|
24
|
+
async generateResources() {
|
|
25
|
+
const { resources } = this.props;
|
|
26
|
+
for (const resource of resources) {
|
|
27
|
+
const metadata = (0, common_1.getResourceMetadata)(resource);
|
|
28
|
+
const resolver = this.props.resolvers[metadata.type];
|
|
29
|
+
if (!resolver) {
|
|
30
|
+
throw new Error(`There is no resolver for the resource ${metadata.type}`);
|
|
31
|
+
}
|
|
32
|
+
await resolver.create(this, resource);
|
|
33
|
+
}
|
|
34
|
+
this.addAspectProperties();
|
|
35
|
+
}
|
|
36
|
+
createRole() {
|
|
37
|
+
if (!this.props.globalConfig?.lambda?.services?.length) {
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
const roleName = `${this.props.name}-module-role`;
|
|
41
|
+
const lambdaRole = new resolver_1.Role(this, roleName, {
|
|
42
|
+
name: roleName,
|
|
43
|
+
services: this.props.globalConfig?.lambda?.services || [],
|
|
44
|
+
});
|
|
45
|
+
lambdaRole.isGlobal('module', roleName);
|
|
46
|
+
}
|
|
47
|
+
addAspectProperties() {
|
|
48
|
+
cdktn_1.Aspects.of(this).add(new aspect_1.AppAspect(this, this.props.name, {
|
|
49
|
+
tags: {
|
|
50
|
+
...(this.props.globalConfig?.tags || {}),
|
|
51
|
+
'lafken:module': this.props.name,
|
|
52
|
+
},
|
|
53
|
+
environment: this.props.globalConfig?.lambda?.env,
|
|
54
|
+
vpc: this.props.globalConfig?.lambda?.vpcConfig,
|
|
55
|
+
}));
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
exports.StackModule = StackModule;
|
|
59
|
+
/**
|
|
60
|
+
* Creates a module factory for the Lafken application.
|
|
61
|
+
*
|
|
62
|
+
* Returns a function that, when invoked by `createApp`, instantiates a
|
|
63
|
+
* `StackModule` and processes all its declared resources through the
|
|
64
|
+
* registered resolvers. Each module groups related resources into a
|
|
65
|
+
* logical unit with its own scope, IAM role, tags, and optional
|
|
66
|
+
* Lambda configuration.
|
|
67
|
+
*
|
|
68
|
+
* @param props - The module configuration including name, resources, and
|
|
69
|
+
* optional global settings scoped to this module.
|
|
70
|
+
* @returns A factory function consumed by `createApp` to build the module
|
|
71
|
+
* within the application stack.
|
|
72
|
+
*
|
|
73
|
+
* @example
|
|
74
|
+
* createModule({
|
|
75
|
+
* name: 'users',
|
|
76
|
+
* resources: [UserApi, UserQueue],
|
|
77
|
+
* globalConfig: {
|
|
78
|
+
* lambda: { memory: 256, services: ['dynamodb'] },
|
|
79
|
+
* tags: { team: 'backend' },
|
|
80
|
+
* },
|
|
81
|
+
* })
|
|
82
|
+
*/
|
|
83
|
+
const createModule = (props) => async (scope, resolvers) => {
|
|
84
|
+
const module = new StackModule(scope, props.name, {
|
|
85
|
+
...props,
|
|
86
|
+
resolvers,
|
|
87
|
+
});
|
|
88
|
+
await module.generateResources();
|
|
89
|
+
return module;
|
|
90
|
+
};
|
|
91
|
+
exports.createModule = createModule;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { ClassResource, ResourceMetadata } from '@lafken/common';
|
|
2
|
+
import type { ResolverType } from '@lafken/resolver';
|
|
3
|
+
import type { Construct } from 'constructs';
|
|
4
|
+
import type { GlobalConfig } from '../app/app.types';
|
|
5
|
+
import type { StackModule } from './module';
|
|
6
|
+
export interface CreateModuleProps {
|
|
7
|
+
/**
|
|
8
|
+
* Module name.
|
|
9
|
+
*
|
|
10
|
+
* Specifies the name of the module, which will be used as an identifier
|
|
11
|
+
* for all resources created within this stack.
|
|
12
|
+
*/
|
|
13
|
+
name: string;
|
|
14
|
+
/**
|
|
15
|
+
* Module resources.
|
|
16
|
+
*
|
|
17
|
+
* Defines the list of resources to be created within this stack.
|
|
18
|
+
* Each item represents a resource such as Api, Queue, StateMachine, etc.
|
|
19
|
+
*/
|
|
20
|
+
resources: ClassResource[];
|
|
21
|
+
/**
|
|
22
|
+
* Module-level global configuration.
|
|
23
|
+
*
|
|
24
|
+
* Provides settings that are applied to all resources and Lambda functions
|
|
25
|
+
* within this specific module. This configuration behaves similarly to
|
|
26
|
+
* the application-wide `GlobalConfig`, but excludes environment settings (`env`),
|
|
27
|
+
* which are managed at the application level.
|
|
28
|
+
*/
|
|
29
|
+
globalConfig?: Omit<GlobalConfig, 'env'>;
|
|
30
|
+
}
|
|
31
|
+
export interface ModuleProps extends CreateModuleProps {
|
|
32
|
+
resolvers: Record<string, ResolverType>;
|
|
33
|
+
}
|
|
34
|
+
export interface ModuleResource {
|
|
35
|
+
module: StackModule;
|
|
36
|
+
metadata: ResourceMetadata;
|
|
37
|
+
Resource: ClassResource;
|
|
38
|
+
}
|
|
39
|
+
export interface ModuleResolverType extends ResolverType {
|
|
40
|
+
}
|
|
41
|
+
export interface ModuleConstruct extends Construct {
|
|
42
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@lafken/main",
|
|
3
|
+
"version": "0.10.2",
|
|
4
|
+
"private": false,
|
|
5
|
+
"description": "Lafken core engine - orchestrate AWS serverless infrastructure using decorators with automatic CDKTN code generation",
|
|
6
|
+
"keywords": [
|
|
7
|
+
"aws",
|
|
8
|
+
"serverless",
|
|
9
|
+
"lafken",
|
|
10
|
+
"infrastructure",
|
|
11
|
+
"infrastructure-as-code",
|
|
12
|
+
"cdktn",
|
|
13
|
+
"typescript",
|
|
14
|
+
"decorators",
|
|
15
|
+
"terraform"
|
|
16
|
+
],
|
|
17
|
+
"homepage": "https://github.com/Hero64/lafken#readme",
|
|
18
|
+
"bugs": "https://github.com/Hero64/lafken/issues",
|
|
19
|
+
"repository": {
|
|
20
|
+
"type": "git",
|
|
21
|
+
"url": "https://github.com/Hero64/lafken",
|
|
22
|
+
"directory": "packages/main"
|
|
23
|
+
},
|
|
24
|
+
"license": "MIT",
|
|
25
|
+
"author": "Aníbal Jorquera",
|
|
26
|
+
"main": "lib/index.js",
|
|
27
|
+
"types": "lib/index.d.ts",
|
|
28
|
+
"files": [
|
|
29
|
+
"lib"
|
|
30
|
+
],
|
|
31
|
+
"dependencies": {
|
|
32
|
+
"reflect-metadata": "^0.2.2",
|
|
33
|
+
"@lafken/resolver": "0.10.2"
|
|
34
|
+
},
|
|
35
|
+
"devDependencies": {
|
|
36
|
+
"@cdktn/provider-aws": "^23.5.0",
|
|
37
|
+
"cdktn": "^0.22.1",
|
|
38
|
+
"cdktn-vitest": "^1.0.0",
|
|
39
|
+
"constructs": "^10.6.0",
|
|
40
|
+
"typescript": "6.0.2",
|
|
41
|
+
"vitest": "^4.1.2",
|
|
42
|
+
"@lafken/common": "0.10.2"
|
|
43
|
+
},
|
|
44
|
+
"peerDependencies": {
|
|
45
|
+
"@cdktn/provider-aws": ">=23.0.0",
|
|
46
|
+
"cdktn": ">=0.22.0",
|
|
47
|
+
"constructs": "^10.4.5",
|
|
48
|
+
"@lafken/common": "0.10.2"
|
|
49
|
+
},
|
|
50
|
+
"engines": {
|
|
51
|
+
"node": ">=20.19"
|
|
52
|
+
},
|
|
53
|
+
"publishConfig": {
|
|
54
|
+
"access": "public"
|
|
55
|
+
},
|
|
56
|
+
"scripts": {
|
|
57
|
+
"build": "pnpm clean && tsc -p ./tsconfig.build.json",
|
|
58
|
+
"check-types": "tsc --noEmit -p ./tsconfig.build.json",
|
|
59
|
+
"clean": "rm -rf ./lib",
|
|
60
|
+
"dev": "tsc -w",
|
|
61
|
+
"test": "vitest"
|
|
62
|
+
}
|
|
63
|
+
}
|