@fy-stack/fullstack-construct 0.0.142 → 0.0.144

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,64 +1,75 @@
1
1
  # Fullstack Construct Documentation
2
2
 
3
- ## `FullstackConstruct`
3
+ ## Overview
4
4
 
5
- ### Example
6
- ```typescript
7
- import {
8
- AppGrant,
9
- AppType,
10
- FullStackConstruct,
11
- } from '@fy-stack/fullstack-construct';
5
+ The Fullstack Construct is a high-level AWS CDK construct that enables deploying full-stack applications to AWS infrastructure. It provides an integrated solution for deploying various types of applications with their associated infrastructure.
6
+
7
+ ## Supported Application Types
8
+
9
+ ### 1. Static Applications
10
+ - **Static Website** (`AppType.STATIC_WEBSITE`)
11
+ - Simple static websites with HTML, CSS, and JavaScript
12
+ - Deployed to S3 and served via CloudFront
13
+
14
+ ### 2. Next.js Applications
15
+ - **Next.js Pages Export** (`AppType.NEXT_PAGE_EXPORT`)
16
+ - Static export mode of Next.js applications
17
+ - Optimized for static site generation
18
+ - **Next.js App Router** (`AppType.NEXT_APP_ROUTER`)
19
+ - Support for the newer App Router architecture
20
+ - Includes handling for server components
21
+
22
+ ### 3. Node.js Applications
23
+ - **Node App** (`AppType.NODE_APP`)
24
+ - General purpose Node.js applications
25
+ - Deployable as containers or Lambda functions
26
+ - **Node API** (`AppType.NODE_API`)
27
+ - Specialized for NestJS API applications
28
+ - Includes API Gateway integration
29
+
30
+ ### 4. Container Applications
31
+ - **Image App** (`AppType.IMAGE_APP`)
32
+ - Docker container-based applications
33
+ - Deployable to ECS with Fargate
34
+
35
+ ## Deployment Options
12
36
 
13
- new FullStackConstruct(this, 'FullstackApp', {
14
- appId: `unique-app-id`,
15
- apps: {
16
- api: {
17
- type: AppType.NODE_API,
18
- output: process.cwd() + '/dist/apps/api',
19
- buildParams: { command: 'node main.js' },
20
- attachment: { secrets: true },
21
- grant: [AppGrant.EVENT, AppGrant.SECRETS],
22
- },
23
- eventHandler: {
24
- type: AppType.NODE_APP,
25
- output: process.cwd() + '/dist/apps/event-handler',
26
- buildParams: { handler: 'main.handler' },
27
- attachment: { secrets: true, queue: { batchSize: 10 } },
28
- grant: [AppGrant.SECRETS],
29
- },
30
- web: {
31
- type: AppType.NEXT_PAGE_EXPORT,
32
- output: process.cwd() + '/dist/apps/web',
33
- },
34
- },
35
- secrets: {
36
- SOME_OTHER_ENV: "envValue"
37
- },
38
- events: {
39
- messages: [
40
- { messages: [EventType.DAILY_SPOOL], $resource: 'eventHandler' },
41
- ],
42
- cron: [
43
- {
44
- messages: [EventType.DAILY_SPOOL],
45
- cron: { hour: '0', minute: '0' },
46
- },
47
- ],
48
- },
49
- cdn: {
50
- routes: {
51
- '/*': { $resource: 'web' },
52
- },
53
- domains: [
54
- { domain: 'example.com', records: ['*', 'www'] },
55
- { domain: 'example.com.ng', records: ['*', 'www'] },
56
- ],
57
- },
58
- api: {
59
- routes: {
60
- '/*': { $resource: 'api' },
37
+ ### 1. Lambda Deployment
38
+ - Suitable for serverless applications
39
+ - Configurable memory and timeout settings
40
+ - Environment variable support
41
+ - Example configuration:
42
+
43
+ ```typescript
44
+ {
45
+ type: AppType.NODE_API,
46
+ buildParams: {
47
+ memorySize: 512,
48
+ timeout: 30,
49
+ environment: {
50
+ NODE_ENV: 'production'
61
51
  }
62
52
  }
63
- })
53
+ }
54
+ ```
55
+
56
+
57
+ ### 2. ECS Deployment
58
+ - Container-based deployment with Fargate
59
+ - Supports both service and task patterns
60
+ - Load balancer integration
61
+ - Example configuration:
62
+
63
+ ```typescript
64
+ {
65
+ server: {
66
+ apps: {
67
+ api: {
68
+ type: AppType.NODE_API,
69
+ // ECS-specific configuration
70
+ }
71
+ },
72
+ loadBalancer: {
73
+ // Load balancer configuration
74
+ } }, tasks: { // Background task configurations } }
64
75
  ```
package/dist/index.d.ts CHANGED
@@ -1,3 +1,3 @@
1
1
  export { FullStackConstruct } from './lib/fullstack-construct';
2
- export { type AppAttachment, AppGrant, AppType } from "./lib/types";
2
+ export { type AppAttachment, type FullStackConstructProps } from './lib/types';
3
3
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EAAE,KAAK,aAAa,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,aAAa,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EAAE,KAAK,aAAa,EAAE,KAAK,uBAAuB,EAAE,MAAM,aAAa,CAAC"}
package/dist/index.js CHANGED
@@ -1,8 +1,5 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.AppType = exports.AppGrant = exports.FullStackConstruct = void 0;
3
+ exports.FullStackConstruct = void 0;
4
4
  var fullstack_construct_1 = require("./lib/fullstack-construct");
5
5
  Object.defineProperty(exports, "FullStackConstruct", { enumerable: true, get: function () { return fullstack_construct_1.FullStackConstruct; } });
6
- var types_1 = require("./lib/types");
7
- Object.defineProperty(exports, "AppGrant", { enumerable: true, get: function () { return types_1.AppGrant; } });
8
- Object.defineProperty(exports, "AppType", { enumerable: true, get: function () { return types_1.AppType; } });
@@ -1,30 +1,36 @@
1
1
  import { ApiGatewayConstruct } from '@fy-stack/apigateway-construct';
2
- import { type AppConstruct } from '@fy-stack/app-construct';
2
+ import { EcsConstruct, LambdaConstruct, StaticConstruct } from '@fy-stack/app-construct';
3
3
  import { AuthConstruct } from '@fy-stack/auth-construct';
4
4
  import { CDNConstruct } from '@fy-stack/cdn-construct';
5
5
  import { DatabaseConstruct } from '@fy-stack/database-construct';
6
6
  import { EventConstruct } from '@fy-stack/event-construct';
7
7
  import { SecretsConstruct } from '@fy-stack/secret-construct';
8
8
  import { StorageConstruct } from '@fy-stack/storage-construct';
9
- import { TaskConstruct } from '@fy-stack/task-construct';
9
+ import { AppGrant, Attach, Grant } from '@fy-stack/types';
10
10
  import * as ec2 from 'aws-cdk-lib/aws-ec2';
11
+ import * as iam from 'aws-cdk-lib/aws-iam';
11
12
  import { Construct } from 'constructs';
12
- import { FullStackConstructProps } from './types';
13
+ import { AppAttachment, FullStackConstructProps } from './types';
13
14
  /**
14
15
  *
15
16
  */
16
17
  export declare class FullStackConstruct extends Construct {
17
18
  vpc: ec2.IVpc;
19
+ owner?: iam.IUser | iam.IRole;
18
20
  auth?: AuthConstruct;
19
21
  storage?: StorageConstruct;
20
22
  storagePolicy?: string;
21
23
  database?: DatabaseConstruct;
22
24
  event?: EventConstruct;
23
- apps?: Record<string, AppConstruct>;
24
- tasks?: Record<string, TaskConstruct>;
25
+ ecs?: EcsConstruct;
26
+ lambda?: LambdaConstruct;
27
+ static?: StaticConstruct;
25
28
  cdn?: CDNConstruct;
26
29
  api?: ApiGatewayConstruct;
27
30
  secret: SecretsConstruct;
28
31
  constructor(scope: Construct, id: string, props: FullStackConstructProps);
32
+ fromAttachments(attach: Attach, attachment?: AppAttachment): void;
33
+ fromGrants(grant: Grant, grants?: AppGrant[]): void;
34
+ ownerFromArn(ownerArn?: string): iam.IUser | iam.IRole | undefined;
29
35
  }
30
36
  //# sourceMappingURL=fullstack-construct.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"fullstack-construct.d.ts","sourceRoot":"","sources":["../../src/lib/fullstack-construct.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AACrE,OAAO,EACL,KAAK,YAAY,EAOlB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AACjE,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC3D,OAAO,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAC9D,OAAO,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAC/D,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAEzD,OAAO,KAAK,GAAG,MAAM,qBAAqB,CAAC;AAE3C,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAEvC,OAAO,EAAW,uBAAuB,EAAE,MAAM,SAAS,CAAC;AAW3D;;GAEG;AACH,qBAAa,kBAAmB,SAAQ,SAAS;IACxC,GAAG,EAAE,GAAG,CAAC,IAAI,CAAC;IACd,IAAI,CAAC,EAAE,aAAa,CAAC;IACrB,OAAO,CAAC,EAAE,gBAAgB,CAAC;IAC3B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,EAAE,iBAAiB,CAAC;IAC7B,KAAK,CAAC,EAAE,cAAc,CAAC;IACvB,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;IACpC,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;IACtC,GAAG,CAAC,EAAE,YAAY,CAAC;IACnB,GAAG,CAAC,EAAE,mBAAmB,CAAC;IAC1B,MAAM,EAAE,gBAAgB,CAAC;gBAEpB,KAAK,EAAE,SAAS,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,uBAAuB;CAsLzE"}
1
+ {"version":3,"file":"fullstack-construct.d.ts","sourceRoot":"","sources":["../../src/lib/fullstack-construct.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AACrE,OAAO,EACL,YAAY,EACZ,eAAe,EACf,eAAe,EAChB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AACjE,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC3D,OAAO,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAC9D,OAAO,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAC/D,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAa,MAAM,iBAAiB,CAAC;AAErE,OAAO,KAAK,GAAG,MAAM,qBAAqB,CAAC;AAC3C,OAAO,KAAK,GAAG,MAAM,qBAAqB,CAAC;AAC3C,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAEvC,OAAO,EAAE,aAAa,EAAE,uBAAuB,EAAE,MAAM,SAAS,CAAC;AAEjE;;GAEG;AACH,qBAAa,kBAAmB,SAAQ,SAAS;IACxC,GAAG,EAAE,GAAG,CAAC,IAAI,CAAC;IACd,KAAK,CAAC,EAAE,GAAG,CAAC,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC;IAC9B,IAAI,CAAC,EAAE,aAAa,CAAC;IACrB,OAAO,CAAC,EAAE,gBAAgB,CAAC;IAC3B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,EAAE,iBAAiB,CAAC;IAC7B,KAAK,CAAC,EAAE,cAAc,CAAC;IACvB,GAAG,CAAC,EAAE,YAAY,CAAC;IACnB,MAAM,CAAC,EAAE,eAAe,CAAC;IACzB,MAAM,CAAC,EAAE,eAAe,CAAC;IACzB,GAAG,CAAC,EAAE,YAAY,CAAC;IACnB,GAAG,CAAC,EAAE,mBAAmB,CAAC;IAC1B,MAAM,EAAE,gBAAgB,CAAC;gBAEpB,KAAK,EAAE,SAAS,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,uBAAuB;IAwNxE,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,aAAa;IAU1D,UAAU,CAAC,KAAK,EAAE,KAAK,EAAE,MAAM,CAAC,EAAE,QAAQ,EAAE;IAW5C,YAAY,CAAC,QAAQ,CAAC,EAAE,MAAM;CAgB/B"}
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.FullStackConstruct = void 0;
4
4
  const tslib_1 = require("tslib");
5
+ const path = tslib_1.__importStar(require("node:path"));
5
6
  const apigateway_construct_1 = require("@fy-stack/apigateway-construct");
6
7
  const app_construct_1 = require("@fy-stack/app-construct");
7
8
  const auth_construct_1 = require("@fy-stack/auth-construct");
@@ -10,37 +11,30 @@ const database_construct_1 = require("@fy-stack/database-construct");
10
11
  const event_construct_1 = require("@fy-stack/event-construct");
11
12
  const secret_construct_1 = require("@fy-stack/secret-construct");
12
13
  const storage_construct_1 = require("@fy-stack/storage-construct");
13
- const task_construct_1 = require("@fy-stack/task-construct");
14
14
  const aws_cdk_lib_1 = require("aws-cdk-lib");
15
15
  const ec2 = tslib_1.__importStar(require("aws-cdk-lib/aws-ec2"));
16
- const ecs = tslib_1.__importStar(require("aws-cdk-lib/aws-ecs"));
16
+ const iam = tslib_1.__importStar(require("aws-cdk-lib/aws-iam"));
17
17
  const constructs_1 = require("constructs");
18
- const types_1 = require("./types");
19
- const AppBuilds = {
20
- [types_1.AppType.NEXT_APP_ROUTER]: app_construct_1.NextAppRouterConstruct,
21
- [types_1.AppType.NEXT_PAGE_EXPORT]: app_construct_1.NextPagesExportConstruct,
22
- [types_1.AppType.NODE_APP]: app_construct_1.NodeAppConstruct,
23
- [types_1.AppType.NODE_API]: app_construct_1.NodeApiConstruct,
24
- [types_1.AppType.IMAGE_APP]: app_construct_1.ImageAppConstruct,
25
- [types_1.AppType.STATIC_WEBSITE]: app_construct_1.StaticWebsiteConstruct,
26
- };
27
18
  /**
28
19
  *
29
20
  */
30
21
  class FullStackConstruct extends constructs_1.Construct {
31
22
  vpc;
23
+ owner;
32
24
  auth;
33
25
  storage;
34
26
  storagePolicy;
35
27
  database;
36
28
  event;
37
- apps;
38
- tasks;
29
+ ecs;
30
+ lambda;
31
+ static;
39
32
  cdn;
40
33
  api;
41
34
  secret;
42
35
  constructor(scope, id, props) {
43
36
  super(scope, id);
37
+ this.owner = this.ownerFromArn(props.ownerArn);
44
38
  this.vpc = ec2.Vpc.fromLookup(this, 'VPC', props.vpcId ? { vpcId: props.vpcId } : { isDefault: true });
45
39
  if (props.auth) {
46
40
  this.auth = new auth_construct_1.AuthConstruct(this, 'AuthConstruct', {
@@ -57,117 +51,180 @@ class FullStackConstruct extends constructs_1.Construct {
57
51
  vpcId: this.vpc.vpcId,
58
52
  });
59
53
  }
60
- if (props.apps) {
61
- const apps = {};
62
- Object.assign(apps, Object.fromEntries(Object.entries(props.apps).map(([key, app]) => {
63
- const AppTypeConstruct = AppBuilds[app.type];
64
- return [
65
- key,
66
- new AppTypeConstruct(this, `${key}App`, {
67
- // @ts-expect-error invalid params
68
- buildParams: AppTypeConstruct.parse(app.buildParams ?? {}),
69
- vpc: this.vpc,
70
- ...app
71
- }),
72
- ];
73
- })));
74
- this.apps = apps;
75
- }
76
- if (props.task) {
77
- const tasks = {};
78
- const cluster = new ecs.Cluster(this, 'AppCluster', { vpc: this.vpc });
79
- Object.assign(tasks, Object.fromEntries(Object.entries(props.task).map(([key, task]) => {
80
- return [
81
- key,
82
- new task_construct_1.TaskConstruct(this, `${key}Task`, {
83
- clusterArn: cluster.clusterArn,
84
- vpc: this.vpc,
85
- ...task
86
- }),
87
- ];
88
- })));
89
- this.tasks = tasks;
90
- }
91
- if (props.events) {
54
+ if (props.ecs) {
55
+ this.ecs = new app_construct_1.EcsConstruct(this, 'EcsConstruct', {
56
+ vpc: this.vpc,
57
+ environmentPath: path.join('/', props.name, '/', props.environment),
58
+ environment: props.environment,
59
+ ...props.ecs,
60
+ });
61
+ }
62
+ if (props.lambda) {
63
+ this.lambda = new app_construct_1.LambdaConstruct(this, 'LambdaConstruct', {
64
+ vpc: this.vpc,
65
+ apps: props.lambda,
66
+ });
67
+ }
68
+ if (props.static) {
69
+ this.static = new app_construct_1.StaticConstruct(this, 'StaticConstruct', {
70
+ apps: props.static,
71
+ });
72
+ }
73
+ const resources = {
74
+ ...(this.ecs?.server?.apps ?? {}),
75
+ ...(this.lambda?.apps ?? {}),
76
+ ...(this.static?.apps ?? {}),
77
+ };
78
+ if (props.event) {
92
79
  this.event = new event_construct_1.EventConstruct(this, 'EventConstruct', {
93
- resources: { ...this.apps, ...this.tasks },
94
- ...props.events,
80
+ resources: {
81
+ ...(this.lambda?.apps ?? {}),
82
+ ...(this.ecs?.tasks ?? {}),
83
+ },
84
+ ...props.event,
95
85
  });
96
86
  }
97
- this.secret = new secret_construct_1.SecretsConstruct(this, 'SecretConstruct', {
98
- resources: {
99
- auth: this.auth,
100
- database: this.database,
101
- storage: this.storage,
102
- event: this.event,
103
- },
104
- secrets: props.secrets,
105
- });
106
87
  if (props.cdn) {
107
88
  this.cdn = new cdn_construct_1.CDNConstruct(this, 'CDNConstruct', {
108
89
  routes: props.cdn.routes,
109
90
  domains: props.cdn.domains,
110
- resources: { ...this.apps, storage: this.storage },
111
- });
112
- new aws_cdk_lib_1.CfnOutput(this, 'CDN Url', {
113
- key: 'cdnURl',
114
- value: 'https://' + this.cdn.distribution.domainName,
91
+ resources: {
92
+ ...resources,
93
+ storage: this.storage,
94
+ },
115
95
  });
96
+ if (props.outputs) {
97
+ new aws_cdk_lib_1.CfnOutput(this, 'CDN Url', {
98
+ key: 'cdnURl',
99
+ value: 'https://' + this.cdn.distribution.domainName,
100
+ });
101
+ }
116
102
  }
117
103
  if (props.api) {
118
104
  this.api = new apigateway_construct_1.ApiGatewayConstruct(this, 'ApiConstruct', {
119
105
  routes: props.api.routes,
120
- resources: this.apps,
106
+ resources,
121
107
  });
122
- if (this.api.api.url) {
108
+ if (this.api.api.url && props.outputs) {
123
109
  new aws_cdk_lib_1.CfnOutput(this, 'Api Url', {
124
110
  key: 'apiUrl',
125
111
  value: this.api.api.url,
126
112
  });
127
113
  }
128
114
  }
129
- const resources = {
130
- storage: this.storage,
131
- database: this.database,
132
- auth: this.auth,
133
- secrets: this.secret,
134
- event: this.event,
135
- };
115
+ this.secret = new secret_construct_1.SecretsConstruct(this, 'SecretConstruct', {
116
+ resources: {
117
+ auth: this.auth,
118
+ database: this.database,
119
+ storage: this.storage,
120
+ event: this.event,
121
+ cdn: this.cdn,
122
+ api: this.api,
123
+ },
124
+ secrets: {
125
+ REGION: aws_cdk_lib_1.Stack.of(this).region,
126
+ ENVIRONMENT: props.environment,
127
+ ...props.secret,
128
+ },
129
+ });
130
+ if (props.outputs) {
131
+ new aws_cdk_lib_1.CfnOutput(this, 'SecretsName', {
132
+ key: 'appSecrets',
133
+ value: this.secret.secrets.secretName,
134
+ });
135
+ }
136
+ if (this.ecs && props.ecs) {
137
+ if (this.ecs.server) {
138
+ this.fromGrants(this.ecs.server, props.ecs.server?.grants);
139
+ for (const i in this.ecs.server.apps) {
140
+ if (!props.ecs.server?.apps[i].attachment)
141
+ continue;
142
+ this.fromAttachments(this.ecs.server.apps[i], props.ecs.server.apps[i].attachment);
143
+ }
144
+ }
145
+ for (const i in this.ecs.tasks) {
146
+ if (props.ecs.tasks[i]?.grants) {
147
+ this.fromGrants(this.ecs.tasks[i], props.ecs.tasks[i]?.grants);
148
+ }
149
+ if (props.ecs.tasks[i]?.attachment) {
150
+ this.fromAttachments(this.ecs.tasks[i], props.ecs.tasks[i]?.attachment);
151
+ }
152
+ }
153
+ }
154
+ if (this.lambda && props.lambda) {
155
+ for (const i in this.lambda.apps) {
156
+ if (props.lambda[i].attachment) {
157
+ this.fromAttachments(this.lambda.apps[i], props.lambda[i].attachment);
158
+ }
159
+ if (props.lambda[i].grants) {
160
+ this.fromGrants(this.lambda.apps[i], props.lambda[i].grants);
161
+ }
162
+ }
163
+ }
136
164
  if (this.storage && this.cdn) {
137
165
  this.storagePolicy = JSON.stringify(this.storage.cloudfrontPolicy(this.cdn.distribution.distributionId));
138
166
  new aws_cdk_lib_1.CfnOutput(this, 'StorageBucketCDNPolicy', {
139
167
  key: 'storageBucketCDNPolicy',
140
- value: this.storagePolicy
168
+ value: this.storagePolicy,
141
169
  });
142
170
  }
143
- for (const i in props.apps) {
144
- const attachments = Object.entries(props.apps[i]?.attachment ?? {})
145
- .map(([key]) => [key, resources[key]])
146
- .filter((v) => !!v);
147
- if (attachments.length) {
148
- this.apps?.[i]?.attach(Object.fromEntries(attachments));
149
- }
150
- const grants = props.apps[i]?.grant
151
- ?.map((val) => resources[val])
152
- .filter((v) => !!v) ?? [];
153
- if (grants.length) {
154
- this.apps?.[i]?.grant(...grants);
171
+ aws_cdk_lib_1.Tags.of(this).add('App', props.name);
172
+ aws_cdk_lib_1.Tags.of(this).add('Environment', props.environment);
173
+ if (this.owner) {
174
+ this.owner.addToPrincipalPolicy(new iam.PolicyStatement({
175
+ effect: iam.Effect.ALLOW,
176
+ actions: ['*'],
177
+ resources: ['*'],
178
+ conditions: {
179
+ StringEquals: {
180
+ 'aws:ResourceTag/App': props.name,
181
+ 'aws:ResourceTag/Environment': props.environment,
182
+ },
183
+ },
184
+ }));
185
+ if (this.storage) {
186
+ this.storage.bucket.addToResourcePolicy(new iam.PolicyStatement({
187
+ actions: ['*'],
188
+ resources: [
189
+ 'arn:aws:s3:::' + this.storage.bucket.bucketName + '/*',
190
+ ],
191
+ principals: [this.owner],
192
+ }));
193
+ this.owner.addToPrincipalPolicy(new iam.PolicyStatement({
194
+ actions: ['s3:*'],
195
+ resources: [this.storage.bucket.bucketArn],
196
+ }));
155
197
  }
156
198
  }
157
- for (const i in props.task) {
158
- const attachments = Object.entries(props.task[i]?.attachment ?? {})
159
- .map(([key]) => [key, resources[key]])
160
- .filter((v) => !!v);
161
- if (attachments.length) {
162
- this.tasks?.[i]?.attach(Object.fromEntries(attachments));
163
- }
164
- const grants = props.task[i]?.grant
165
- ?.map((val) => resources[val])
166
- .filter((v) => !!v) ?? [];
167
- if (grants.length) {
168
- this.tasks?.[i]?.grant(...grants);
169
- }
199
+ }
200
+ fromAttachments(attach, attachment) {
201
+ const builtAttachment = Object.entries(attachment ?? {})
202
+ .map(([key]) => [key, this[key]])
203
+ .filter((v) => !!v && !!v[1]);
204
+ if (builtAttachment.length) {
205
+ attach.attach(Object.fromEntries(builtAttachment));
206
+ }
207
+ }
208
+ fromGrants(grant, grants) {
209
+ const builtGrants = grants
210
+ ?.map((val) => this[val])
211
+ .filter((v) => !!v) ?? [];
212
+ if (builtGrants.length) {
213
+ grant.grant(...builtGrants);
214
+ }
215
+ }
216
+ ownerFromArn(ownerArn) {
217
+ if (!ownerArn)
218
+ return;
219
+ const [arn] = ownerArn.split('/');
220
+ const resourceType = arn.split(':').at(-1);
221
+ if (resourceType === 'user') {
222
+ return iam.User.fromUserArn(this, 'Owner', ownerArn);
223
+ }
224
+ if (resourceType === 'role') {
225
+ return iam.Role.fromRoleArn(this, 'Owner', ownerArn);
170
226
  }
227
+ return;
171
228
  }
172
229
  }
173
230
  exports.FullStackConstruct = FullStackConstruct;
@@ -1,63 +1,51 @@
1
+ import type { EcsConstructProps, LambdaConstructProps, StaticConstructProps } from '@fy-stack/app-construct';
1
2
  import type { CDNConstructProps } from '@fy-stack/cdn-construct';
2
3
  import type { DatabaseConstructProps } from '@fy-stack/database-construct';
3
4
  import type { EventConstructProps } from '@fy-stack/event-construct';
4
5
  import type { StorageConstructProps } from '@fy-stack/storage-construct';
5
- import type { TaskConstructsProps } from '@fy-stack/task-construct';
6
- import type { ResourceRef } from '@fy-stack/types';
7
- export declare enum AppType {
8
- NODE_APP = "nodeApp",
9
- NODE_API = "nestApi",
10
- IMAGE_APP = "imageApp",
11
- NEXT_APP_ROUTER = "nextAppRouter",
12
- NEXT_PAGE_EXPORT = "nextPageExport",
13
- STATIC_WEBSITE = "staticWebsite"
14
- }
6
+ import { AppGrant, type ResourceRef } from '@fy-stack/types';
15
7
  export type AppAttachment = {
16
8
  auth?: boolean;
17
9
  storage?: boolean;
18
10
  database?: boolean;
19
- secrets?: boolean;
20
- queue?: {
21
- batchSize?: number;
22
- };
23
- };
24
- export declare enum AppGrant {
25
- AUTH = "auth",
26
- STORAGE = "storage",
27
- DATABASE = "database",
28
- SECRETS = "secrets",
29
- EVENT = "event"
30
- }
31
- export type App = {
32
- type: AppType;
33
- output: string;
34
- attachment?: AppAttachment;
35
- grant?: AppGrant[];
36
- env?: Record<string, string>;
37
- buildParams?: Record<string, unknown>;
38
- };
39
- export type Task = Omit<TaskConstructsProps, "clusterArn" | "vpc"> & {
40
- attachment?: AppAttachment;
41
- grant?: AppGrant[];
11
+ secret?: boolean;
42
12
  };
43
13
  export type AppMessage = ResourceRef & {
44
14
  messages: string[];
45
15
  };
46
16
  export type FullStackConstructProps = {
17
+ name: string;
18
+ environment: string;
47
19
  vpcId?: string;
48
- appId: string;
49
20
  auth?: {
50
21
  groups?: string[];
51
22
  };
52
23
  storage?: StorageConstructProps;
53
24
  database?: DatabaseConstructProps;
54
- apps?: Record<string, App>;
55
- events?: Omit<EventConstructProps, "resources">;
56
- cdn?: Omit<CDNConstructProps, "resources">;
25
+ ecs?: Omit<EcsConstructProps, 'vpc' | 'environmentPath' | 'server' | 'tasks' | 'environment'> & {
26
+ server: Omit<NonNullable<EcsConstructProps['server']>, 'apps'> & {
27
+ grants?: AppGrant[];
28
+ apps: Record<string, NonNullable<EcsConstructProps['server']>['apps'][string] & {
29
+ attachment?: AppAttachment;
30
+ }>;
31
+ };
32
+ tasks: Record<string, NonNullable<EcsConstructProps['tasks']>[string] & {
33
+ grants?: AppGrant[];
34
+ attachment?: AppAttachment;
35
+ }>;
36
+ };
37
+ lambda?: Record<string, NonNullable<LambdaConstructProps['apps']>[string] & {
38
+ grants?: AppGrant[];
39
+ attachment?: AppAttachment;
40
+ }>;
41
+ static?: StaticConstructProps['apps'];
42
+ event?: Omit<EventConstructProps, 'resources'>;
43
+ cdn?: Omit<CDNConstructProps, 'resources'>;
57
44
  api?: {
58
45
  routes: Record<string, ResourceRef>;
59
46
  };
60
- secrets?: Record<string, string | undefined>;
61
- task?: Record<string, Task>;
47
+ secret?: Record<string, string | undefined>;
48
+ outputs?: boolean;
49
+ ownerArn?: string;
62
50
  };
63
51
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/lib/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AACjE,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,8BAA8B,CAAC;AAC3E,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AACrE,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,6BAA6B,CAAC;AACzE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AACpE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAEnD,oBAAY,OAAO;IACjB,QAAQ,YAAY;IACpB,QAAQ,YAAY;IACpB,SAAS,aAAa;IACtB,eAAe,kBAAkB;IACjC,gBAAgB,mBAAmB;IACnC,cAAc,kBAAkB;CACjC;AAED,MAAM,MAAM,aAAa,GAAG;IAC1B,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CAChC,CAAC;AAEF,oBAAY,QAAQ;IAClB,IAAI,SAAS;IACb,OAAO,YAAY;IACnB,QAAQ,aAAa;IACrB,OAAO,YAAY;IACnB,KAAK,UAAU;CAChB;AAED,MAAM,MAAM,GAAG,GAAG;IAChB,IAAI,EAAE,OAAO,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,aAAa,CAAC;IAC3B,KAAK,CAAC,EAAE,QAAQ,EAAE,CAAC;IACnB,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC5B,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACvC,CAAC;AAEF,MAAM,MAAM,IAAI,GAAG,IAAI,CAAC,mBAAmB,EAAE,YAAY,GAAG,KAAK,CAAC,GAAG;IACnE,UAAU,CAAC,EAAE,aAAa,CAAC;IAC3B,KAAK,CAAC,EAAE,QAAQ,EAAE,CAAC;CACpB,CAAA;AAED,MAAM,MAAM,UAAU,GAAG,WAAW,GAAG;IACrC,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,uBAAuB,GAAG;IACpC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;IAC7B,OAAO,CAAC,EAAE,qBAAqB,CAAC;IAChC,QAAQ,CAAC,EAAE,sBAAsB,CAAC;IAClC,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC3B,MAAM,CAAC,EAAE,IAAI,CAAC,mBAAmB,EAAE,WAAW,CAAC,CAAC;IAChD,GAAG,CAAC,EAAE,IAAI,CAAC,iBAAiB,EAAE,WAAW,CAAC,CAAC;IAC3C,GAAG,CAAC,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAA;KAAE,CAAC;IAC9C,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;IAC7C,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;CAC7B,CAAC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/lib/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,iBAAiB,EACjB,oBAAoB,EACpB,oBAAoB,EACrB,MAAM,yBAAyB,CAAC;AACjC,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AACjE,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,8BAA8B,CAAC;AAC3E,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AACrE,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,6BAA6B,CAAC;AACzE,OAAO,EAAE,QAAQ,EAAE,KAAK,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAE7D,MAAM,MAAM,aAAa,GAAG;IAC1B,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG,WAAW,GAAG;IACrC,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,uBAAuB,GAAG;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;IAC7B,OAAO,CAAC,EAAE,qBAAqB,CAAC;IAChC,QAAQ,CAAC,EAAE,sBAAsB,CAAC;IAClC,GAAG,CAAC,EAAE,IAAI,CACR,iBAAiB,EACjB,KAAK,GAAG,iBAAiB,GAAG,QAAQ,GAAG,OAAO,GAAG,aAAa,CAC/D,GAAG;QACF,MAAM,EAAE,IAAI,CAAC,WAAW,CAAC,iBAAiB,CAAC,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC,GAAG;YAC/D,MAAM,CAAC,EAAE,QAAQ,EAAE,CAAC;YACpB,IAAI,EAAE,MAAM,CACV,MAAM,EACN,WAAW,CAAC,iBAAiB,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,GAAG;gBACzD,UAAU,CAAC,EAAE,aAAa,CAAC;aAC5B,CACF,CAAC;SACH,CAAC;QACF,KAAK,EAAE,MAAM,CACX,MAAM,EACN,WAAW,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG;YAChD,MAAM,CAAC,EAAE,QAAQ,EAAE,CAAC;YACpB,UAAU,CAAC,EAAE,aAAa,CAAC;SAC5B,CACF,CAAC;KACH,CAAC;IACF,MAAM,CAAC,EAAE,MAAM,CACb,MAAM,EACN,WAAW,CAAC,oBAAoB,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG;QAClD,MAAM,CAAC,EAAE,QAAQ,EAAE,CAAC;QACpB,UAAU,CAAC,EAAE,aAAa,CAAC;KAC5B,CACF,CAAC;IACF,MAAM,CAAC,EAAE,oBAAoB,CAAC,MAAM,CAAC,CAAC;IACtC,KAAK,CAAC,EAAE,IAAI,CAAC,mBAAmB,EAAE,WAAW,CAAC,CAAC;IAC/C,GAAG,CAAC,EAAE,IAAI,CAAC,iBAAiB,EAAE,WAAW,CAAC,CAAC;IAC3C,GAAG,CAAC,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAA;KAAE,CAAC;IAC9C,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;IAC5C,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC"}
package/dist/lib/types.js CHANGED
@@ -1,20 +1,2 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.AppGrant = exports.AppType = void 0;
4
- var AppType;
5
- (function (AppType) {
6
- AppType["NODE_APP"] = "nodeApp";
7
- AppType["NODE_API"] = "nestApi";
8
- AppType["IMAGE_APP"] = "imageApp";
9
- AppType["NEXT_APP_ROUTER"] = "nextAppRouter";
10
- AppType["NEXT_PAGE_EXPORT"] = "nextPageExport";
11
- AppType["STATIC_WEBSITE"] = "staticWebsite";
12
- })(AppType || (exports.AppType = AppType = {}));
13
- var AppGrant;
14
- (function (AppGrant) {
15
- AppGrant["AUTH"] = "auth";
16
- AppGrant["STORAGE"] = "storage";
17
- AppGrant["DATABASE"] = "database";
18
- AppGrant["SECRETS"] = "secrets";
19
- AppGrant["EVENT"] = "event";
20
- })(AppGrant || (exports.AppGrant = AppGrant = {}));
package/package.json CHANGED
@@ -1,21 +1,21 @@
1
1
  {
2
2
  "name": "@fy-stack/fullstack-construct",
3
- "version": "0.0.142",
3
+ "version": "0.0.144",
4
4
  "repository": "https://github.com/festusyuma/fy-stack",
5
5
  "dependencies": {
6
- "@fy-stack/apigateway-construct": "0.0.142",
7
- "@fy-stack/app-construct": "0.0.142",
8
- "@fy-stack/auth-construct": "0.0.142",
9
- "@fy-stack/cdn-construct": "0.0.142",
10
- "@fy-stack/database-construct": "0.0.142",
11
- "@fy-stack/event-construct": "0.0.142",
12
- "@fy-stack/secret-construct": "0.0.142",
13
- "@fy-stack/storage-construct": "0.0.142",
14
- "@fy-stack/task-construct": "0.0.142",
15
- "tslib": "^2.3.0"
6
+ "@fy-stack/apigateway-construct": "0.0.144",
7
+ "@fy-stack/app-construct": "0.0.144",
8
+ "@fy-stack/auth-construct": "0.0.144",
9
+ "@fy-stack/cdn-construct": "0.0.144",
10
+ "@fy-stack/database-construct": "0.0.144",
11
+ "@fy-stack/event-construct": "0.0.144",
12
+ "@fy-stack/secret-construct": "0.0.144",
13
+ "@fy-stack/storage-construct": "0.0.144",
14
+ "tslib": "^2.3.0",
15
+ "@fy-stack/types": "0.0.144"
16
16
  },
17
17
  "peerDependencies": {
18
- "aws-cdk-lib": "^2.174.1",
18
+ "aws-cdk-lib": "^2.198.0",
19
19
  "constructs": "^10.4.2"
20
20
  },
21
21
  "type": "commonjs",