@mbc-cqrs-serverless/cli 0.1.23-beta.0 → 0.1.25-beta.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.
@@ -32,11 +32,14 @@ async function newAction(name = '', options, command) {
32
32
  const destDir = path_1.default.join(process.cwd(), projectName);
33
33
  console.log('Generating MBC cqrs serverless application in', destDir);
34
34
  (0, fs_1.mkdirSync)(destDir, { recursive: true });
35
- (0, fs_1.cpSync)(path_1.default.join(__dirname, '../../templates'), destDir, { recursive: true });
35
+ useTemplate(destDir);
36
36
  usePackageVersion(destDir, packageVersion, projectName);
37
37
  const gitignore = path_1.default.join(destDir, 'gitignore');
38
38
  (0, fs_1.copyFileSync)(gitignore, path_1.default.join(destDir, '.gitignore'));
39
39
  (0, fs_1.unlinkSync)(gitignore);
40
+ const infraGitignore = path_1.default.join(destDir, 'infra/gitignore');
41
+ (0, fs_1.copyFileSync)(infraGitignore, path_1.default.join(destDir, 'infra/.gitignore'));
42
+ (0, fs_1.unlinkSync)(infraGitignore);
40
43
  (0, fs_1.copyFileSync)(path_1.default.join(destDir, '.env.local'), path_1.default.join(destDir, '.env'));
41
44
  let logs = (0, child_process_1.execSync)('git init', { cwd: destDir });
42
45
  console.log(logs.toString());
@@ -45,6 +48,26 @@ async function newAction(name = '', options, command) {
45
48
  console.log(logs.toString());
46
49
  }
47
50
  exports.default = newAction;
51
+ function useTemplate(destDir) {
52
+ if (isLatestCli()) {
53
+ (0, fs_1.cpSync)(path_1.default.join(__dirname, '../../templates'), destDir, {
54
+ recursive: true,
55
+ });
56
+ }
57
+ else {
58
+ (0, child_process_1.execSync)('npm i @mbc-cqrs-serverless/cli', { cwd: destDir });
59
+ (0, fs_1.cpSync)(path_1.default.join(destDir, 'node_modules/@mbc-cqrs-serverless/cli/templates'), destDir, { recursive: true });
60
+ (0, fs_1.rmSync)(path_1.default.join(destDir, 'node_modules'), {
61
+ recursive: true,
62
+ });
63
+ }
64
+ }
65
+ function isLatestCli() {
66
+ const latestVersion = getPackageVersion('@mbc-cqrs-serverless/cli', true)[0];
67
+ const packageJson = JSON.parse((0, fs_1.readFileSync)(path_1.default.join(__dirname, '../../package.json')).toString());
68
+ const curVersion = packageJson.version;
69
+ return latestVersion === curVersion;
70
+ }
48
71
  function usePackageVersion(destDir, packageVersion, projectName) {
49
72
  const packageJson = JSON.parse((0, fs_1.readFileSync)(path_1.default.join(__dirname, '../../package.json')).toString());
50
73
  const fname = path_1.default.join(destDir, 'package.json');
@@ -70,6 +93,7 @@ function getPackageVersion(packageName, isLatest = false) {
70
93
  exports.exportsForTesting = {
71
94
  usePackageVersion,
72
95
  getPackageVersion,
96
+ isLatestCli,
73
97
  };
74
98
  if (process.env.NODE_ENV !== 'test') {
75
99
  exports.exportsForTesting = undefined;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mbc-cqrs-serverless/cli",
3
- "version": "0.1.23-beta.0",
3
+ "version": "0.1.25-beta.0",
4
4
  "description": "a CLI to get started with MBC CQRS serverless framework",
5
5
  "keywords": [
6
6
  "mbc",
@@ -49,5 +49,5 @@
49
49
  "devDependencies": {
50
50
  "@faker-js/faker": "^8.3.1"
51
51
  },
52
- "gitHead": "7fb8a6963920e0b39cf4d64fafdfd8d68ce6c317"
52
+ "gitHead": "7c50d386295bdd70d6db5d325e6892f0cb4d9f62"
53
53
  }
@@ -0,0 +1,11 @@
1
+ infra
2
+ infra-local
3
+ test
4
+ dist
5
+ dist_layer
6
+ node_modules
7
+ .envrc
8
+ .eslintrc.js
9
+ .prettierrc
10
+ jest.config.js
11
+ README.md
@@ -0,0 +1,32 @@
1
+ FROM node:20-bullseye-slim AS builder
2
+
3
+ # RUN apk update
4
+ # RUN apk --no-cache add make gcc g++ --virtual .builds-deps build-base python3 musl-dev openssl-dev
5
+
6
+ WORKDIR /app
7
+
8
+ COPY package*.json ./
9
+ COPY prisma ./prisma/
10
+
11
+ RUN npm install
12
+
13
+ COPY . .
14
+
15
+ RUN npm run build:prod
16
+
17
+ FROM node:20-bullseye-slim
18
+
19
+ # RUN apk update
20
+ # RUN apk --no-cache add make gcc g++ --virtual .builds-deps build-base python3 musl-dev openssl-dev
21
+
22
+ WORKDIR /app
23
+
24
+ COPY --from=builder /app/package*.json ./
25
+ COPY prisma ./prisma/
26
+ RUN npm ci --omit=dev
27
+
28
+ COPY --from=builder /app/dist ./dist
29
+
30
+ # COPY .env .env
31
+
32
+ CMD ["npm", "run", "start:prod"]
@@ -0,0 +1,8 @@
1
+ {
2
+ "semi": false,
3
+ "singleQuote": true,
4
+ "trailingComma": "all",
5
+ "endOfLine": "auto",
6
+ "tabWidth": 2,
7
+ "useTabs": false
8
+ }
@@ -0,0 +1,25 @@
1
+ # Welcome to your CDK TypeScript project
2
+
3
+ This is a blank project for CDK development with TypeScript.
4
+
5
+ The `cdk.json` file tells the CDK Toolkit how to execute your app.
6
+
7
+ ## Use SSO profile
8
+
9
+ ```bash
10
+ export AWS_PROFILE=
11
+ ```
12
+
13
+ ## Useful commands
14
+
15
+ - `npm run build` compile typescript to js
16
+ - `npm run watch` watch for changes and compile
17
+ - `npm run test` perform the jest unit tests
18
+ - `cdk deploy` deploy this stack to your default AWS account/region
19
+ - `cdk diff` compare deployed stack with current state
20
+ - `cdk synth` emits the synthesized CloudFormation template
21
+
22
+ ## Useful resources
23
+
24
+ - https://constructs.dev/
25
+ - https://docs.aws.amazon.com/cdk/v2/guide/best-practices.html
@@ -0,0 +1,32 @@
1
+ type Message @aws_api_key @aws_iam @aws_cognito_user_pools @aws_oidc {
2
+ id: String!
3
+ table: String!
4
+ pk: String!
5
+ sk: String!
6
+ tenantCode: String!
7
+ action: String!
8
+ content: AWSJSON!
9
+ }
10
+
11
+ type Query {
12
+ getMessage(id: String!): Message
13
+ }
14
+
15
+ type Mutation {
16
+ sendMessage(message: AWSJSON!): Message! @aws_iam
17
+ }
18
+
19
+ type Subscription {
20
+ onMessage(tenantCode: String!, action: String, id: String): Message
21
+ @aws_subscribe(mutations: ["sendMessage"])
22
+ @aws_api_key
23
+ @aws_iam
24
+ @aws_cognito_user_pools
25
+ @aws_oidc
26
+ }
27
+
28
+ schema {
29
+ query: Query
30
+ mutation: Mutation
31
+ subscription: Subscription
32
+ }
@@ -0,0 +1,47 @@
1
+ #!/usr/bin/env node
2
+ import 'source-map-support/register'
3
+ import * as cdk from 'aws-cdk-lib'
4
+ // import { InfraStack } from '../libs/infra-stack'
5
+
6
+ // import * as dotenv from 'dotenv'
7
+ // import { Env } from '../config/type'
8
+ // import { getConfig } from '../config'
9
+ import { PipelineStack } from '../libs/pipeline-stack'
10
+ import { Env, PIPELINE_NAME } from '../config'
11
+ // dotenv.config()
12
+
13
+ const app = new cdk.App()
14
+
15
+ // const env: Env = app.node.tryGetContext('env') || 'dev'
16
+ // console.log('stack environment:', env)
17
+ // const config = getConfig(env)
18
+
19
+ const cdkEnv: cdk.Environment = {
20
+ account: '',
21
+ region: '',
22
+ }
23
+
24
+ // new InfraStack(app, 'InfraStack', {
25
+ // config,
26
+ // /* If you don't specify 'env', this stack will be environment-agnostic.
27
+ // * Account/Region-dependent features and context lookups will not work,
28
+ // * but a single synthesized template can be deployed anywhere. */
29
+ // /* Uncomment the next line to specialize this stack for the AWS Account
30
+ // * and Region that are implied by the current CLI configuration. */
31
+ // // env: { account: process.env.CDK_DEFAULT_ACCOUNT, region: process.env.CDK_DEFAULT_REGION },
32
+ // /* Uncomment the next line if you know exactly what Account and Region you
33
+ // * want to deploy the stack to. */
34
+ // env: cdkEnv,
35
+ // /* For more information, see https://docs.aws.amazon.com/cdk/latest/guide/environments.html */
36
+ // })
37
+
38
+ const envs: Env[] = ['dev']
39
+
40
+ for (const env of envs) {
41
+ new PipelineStack(app, env + '-' + PIPELINE_NAME + '-pipeline-stack', {
42
+ env: cdkEnv,
43
+ envName: env,
44
+ })
45
+ }
46
+
47
+ app.synth()
@@ -0,0 +1,48 @@
1
+ {
2
+ "app": "npx ts-node --prefer-ts-exts bin/infra.ts",
3
+ "watch": {
4
+ "include": ["**"],
5
+ "exclude": [
6
+ "README.md",
7
+ "cdk*.json",
8
+ "**/*.d.ts",
9
+ "**/*.jsx",
10
+ "tsconfig.json",
11
+ "package*.json",
12
+ "yarn.lock",
13
+ "node_modules",
14
+ "test"
15
+ ]
16
+ },
17
+ "context": {
18
+ "@aws-cdk/aws-lambda:recognizeLayerVersion": true,
19
+ "@aws-cdk/core:checkSecretUsage": true,
20
+ "@aws-cdk/core:target-partitions": ["aws", "aws-cn"],
21
+ "@aws-cdk-containers/ecs-service-extensions:enableDefaultLogDriver": true,
22
+ "@aws-cdk/aws-ec2:uniqueImdsv2TemplateName": true,
23
+ "@aws-cdk/aws-ecs:arnFormatIncludesClusterName": true,
24
+ "@aws-cdk/aws-iam:minimizePolicies": true,
25
+ "@aws-cdk/core:validateSnapshotRemovalPolicy": true,
26
+ "@aws-cdk/aws-codepipeline:crossAccountKeyAliasStackSafeResourceName": true,
27
+ "@aws-cdk/aws-s3:createDefaultLoggingPolicy": true,
28
+ "@aws-cdk/aws-sns-subscriptions:restrictSqsDescryption": true,
29
+ "@aws-cdk/aws-apigateway:disableCloudWatchRole": true,
30
+ "@aws-cdk/core:enablePartitionLiterals": true,
31
+ "@aws-cdk/aws-events:eventsTargetQueueSameAccount": true,
32
+ "@aws-cdk/aws-iam:standardizedServicePrincipals": true,
33
+ "@aws-cdk/aws-ecs:disableExplicitDeploymentControllerForCircuitBreaker": true,
34
+ "@aws-cdk/aws-iam:importedRoleStackSafeDefaultPolicyName": true,
35
+ "@aws-cdk/aws-s3:serverAccessLogsUseBucketPolicy": true,
36
+ "@aws-cdk/aws-route53-patters:useCertificate": true,
37
+ "@aws-cdk/customresources:installLatestAwsSdkDefault": false,
38
+ "@aws-cdk/aws-rds:databaseProxyUniqueResourceName": true,
39
+ "@aws-cdk/aws-codedeploy:removeAlarmsFromDeploymentGroup": true,
40
+ "@aws-cdk/aws-apigateway:authorizerChangeDeploymentLogicalId": true,
41
+ "@aws-cdk/aws-ec2:launchTemplateDefaultUserData": true,
42
+ "@aws-cdk/aws-secretsmanager:useAttachedSecretResourcePolicyForSecretTargetAttachments": true,
43
+ "@aws-cdk/aws-redshift:columnId": true,
44
+ "@aws-cdk/aws-stepfunctions-tasks:enableEmrServicePolicyV2": true,
45
+ "@aws-cdk/aws-ec2:restrictDefaultSecurityGroup": true,
46
+ "@aws-cdk/aws-apigateway:requestValidatorUniqueId": true
47
+ }
48
+ }
@@ -0,0 +1,8 @@
1
+ export const PIPELINE_NAME = ''
2
+ export const GIT_REPO = ''
3
+ export const GIT_CONNECTION_ARN = ''
4
+ export const ACM_HTTP_CERTIFICATE_ARN = '' // ACM_US_EAST_1
5
+ export const ACM_APPSYNC_CERTIFICATE_ARN = '' // ACM_US_EAST_1
6
+ export const HOSTED_ZONE_ID = ''
7
+ export const HOSTED_ZONE_NAME = ''
8
+ export const COGNITO_URL = ''
@@ -0,0 +1,48 @@
1
+ import { ApplicationLogLevel, SystemLogLevel } from 'aws-cdk-lib/aws-lambda'
2
+ import { Config } from '../type'
3
+
4
+ const config: Config = {
5
+ env: 'dev',
6
+ appName: '',
7
+
8
+ domain: {
9
+ http: '',
10
+ appsync: '',
11
+ },
12
+
13
+ userPoolId: '',
14
+
15
+ vpc: {
16
+ id: '',
17
+ subnetIds: [],
18
+ securityGroupIds: [],
19
+ },
20
+ rds: {
21
+ accountSsmKey: '',
22
+ endpoint: '',
23
+ dbName: '',
24
+ },
25
+
26
+ logLevel: {
27
+ lambdaSystem: SystemLogLevel.DEBUG,
28
+ lambdaApplication: ApplicationLogLevel.TRACE,
29
+ level: 'verbose',
30
+ },
31
+
32
+ frontBaseUrl: '',
33
+ fromEmailAddress: '',
34
+
35
+ // wafArn: '',
36
+
37
+ // ecs: {
38
+ // maxInstances: 1,
39
+ // minInstances: 1,
40
+ // cpu: 512,
41
+ // memory: 1024,
42
+ // cpuThreshold: 70,
43
+ // scaleStep: 1,
44
+ // autoRollback: false,
45
+ // },
46
+ }
47
+
48
+ export default config
@@ -0,0 +1,17 @@
1
+ import { Config, Env } from './type'
2
+ import dev from './dev'
3
+ import stg from './stg'
4
+ import prod from './prod'
5
+
6
+ export function getConfig(env: Env): Config {
7
+ if (env === 'prod') {
8
+ return prod
9
+ }
10
+ if (env === 'stg') {
11
+ return stg
12
+ }
13
+ return dev
14
+ }
15
+
16
+ export * from './constant'
17
+ export * from './type'
@@ -0,0 +1,48 @@
1
+ import { SystemLogLevel, ApplicationLogLevel } from 'aws-cdk-lib/aws-lambda'
2
+ import { Config } from '../type'
3
+
4
+ const config: Config = {
5
+ env: 'prod',
6
+ appName: '',
7
+
8
+ domain: {
9
+ http: '',
10
+ appsync: '',
11
+ },
12
+
13
+ userPoolId: '',
14
+
15
+ vpc: {
16
+ id: '',
17
+ subnetIds: [],
18
+ securityGroupIds: [],
19
+ },
20
+ rds: {
21
+ accountSsmKey: '',
22
+ endpoint: '',
23
+ dbName: '',
24
+ },
25
+
26
+ logLevel: {
27
+ lambdaSystem: SystemLogLevel.DEBUG,
28
+ lambdaApplication: ApplicationLogLevel.TRACE,
29
+ level: 'info',
30
+ },
31
+
32
+ frontBaseUrl: '',
33
+ fromEmailAddress: '',
34
+
35
+ // wafArn: '',
36
+
37
+ // ecs: {
38
+ // maxInstances: 2,
39
+ // minInstances: 1,
40
+ // cpu: 2048,
41
+ // memory: 4096,
42
+ // cpuThreshold: 70,
43
+ // scaleStep: 1,
44
+ // autoRollback: true,
45
+ // },
46
+ }
47
+
48
+ export default config
@@ -0,0 +1,48 @@
1
+ import { SystemLogLevel, ApplicationLogLevel } from 'aws-cdk-lib/aws-lambda'
2
+ import { Config } from '../type'
3
+
4
+ const config: Config = {
5
+ env: 'stg',
6
+ appName: '',
7
+
8
+ domain: {
9
+ http: '',
10
+ appsync: '',
11
+ },
12
+
13
+ userPoolId: '',
14
+
15
+ vpc: {
16
+ id: '',
17
+ subnetIds: [],
18
+ securityGroupIds: [],
19
+ },
20
+ rds: {
21
+ accountSsmKey: '',
22
+ endpoint: '',
23
+ dbName: '',
24
+ },
25
+
26
+ logLevel: {
27
+ lambdaSystem: SystemLogLevel.DEBUG,
28
+ lambdaApplication: ApplicationLogLevel.TRACE,
29
+ level: 'info',
30
+ },
31
+
32
+ frontBaseUrl: '',
33
+ fromEmailAddress: '',
34
+
35
+ // wafArn: '',
36
+
37
+ // ecs: {
38
+ // maxInstances: 1,
39
+ // minInstances: 1,
40
+ // cpu: 512,
41
+ // memory: 1024,
42
+ // cpuThreshold: 70,
43
+ // scaleStep: 1,
44
+ // autoRollback: true,
45
+ // },
46
+ }
47
+
48
+ export default config
@@ -0,0 +1,53 @@
1
+ import { ApplicationLogLevel, SystemLogLevel } from 'aws-cdk-lib/aws-lambda'
2
+
3
+ export type Env = 'dev' | 'stg' | 'prod'
4
+
5
+ export type Config = {
6
+ env: Env
7
+ appName: string
8
+
9
+ // domain
10
+ domain: {
11
+ http: string
12
+ appsync: string
13
+ }
14
+
15
+ // existing resources
16
+ userPoolId?: string
17
+
18
+ vpc: {
19
+ id: string
20
+ subnetIds: string[]
21
+ securityGroupIds: string[]
22
+ }
23
+
24
+ rds: {
25
+ accountSsmKey: string
26
+ endpoint: string
27
+ dbName: string
28
+ }
29
+
30
+ systemAccountSsmKey?: string
31
+
32
+ logLevel?: {
33
+ lambdaSystem?: SystemLogLevel
34
+ lambdaApplication?: ApplicationLogLevel
35
+ level?: 'verbose' | 'debug' | 'info' | 'warn' | 'error' | 'fatal'
36
+ }
37
+
38
+ frontBaseUrl: string
39
+ fromEmailAddress: string
40
+
41
+ wafArn?: string
42
+
43
+ ecs?: {
44
+ // https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task_definition_parameters.html
45
+ maxInstances: number
46
+ minInstances: number
47
+ cpu: number
48
+ memory: number
49
+ cpuThreshold?: number
50
+ scaleStep?: number
51
+ autoRollback?: boolean
52
+ }
53
+ }
@@ -0,0 +1,8 @@
1
+ *.js
2
+ !jest.config.js
3
+ *.d.ts
4
+ node_modules
5
+
6
+ # CDK asset staging directory
7
+ .cdk.staging
8
+ cdk.out
@@ -0,0 +1,8 @@
1
+ module.exports = {
2
+ testEnvironment: 'node',
3
+ roots: ['<rootDir>/test'],
4
+ testMatch: ['**/*.test.ts'],
5
+ transform: {
6
+ '^.+\\.tsx?$': 'ts-jest',
7
+ },
8
+ }
@@ -0,0 +1,85 @@
1
+ import { execSync } from 'child_process'
2
+ import { existsSync } from 'fs'
3
+ import * as path from 'path'
4
+ import { Env } from '../config'
5
+
6
+ let isBuild = false
7
+
8
+ export function buildApp(env: Env, isLocal = false) {
9
+ const cwd = path.resolve(__dirname, '../..')
10
+ console.log('build app started with cwd:', env, cwd)
11
+
12
+ const layerPath = 'dist_layer'
13
+ const appPath = 'dist'
14
+ const layerFullPath = path.resolve(cwd, layerPath)
15
+ const appFullPath = path.resolve(cwd, appPath)
16
+
17
+ if (isLocal || (existsSync(layerFullPath) && existsSync(appFullPath))) {
18
+ console.log('return from cached build folder')
19
+ return {
20
+ layerPath: layerFullPath,
21
+ appPath: appFullPath,
22
+ }
23
+ }
24
+
25
+ const runCommand = function (cmd: string) {
26
+ console.log(cmd)
27
+ const ret = execSync(cmd, { cwd })
28
+ console.log(ret.toString())
29
+ }
30
+
31
+ // clean up
32
+ console.log('============= clean up =============')
33
+ runCommand(`rm -rf ${layerPath}`)
34
+ runCommand(`rm -rf ${appPath}`)
35
+ runCommand(`rm -rf node_modules`)
36
+
37
+ // install packages
38
+ console.log('============= install packages =============')
39
+ runCommand('npm ci')
40
+
41
+ // build nestjs application
42
+ console.log('============= build nestjs application =============')
43
+ runCommand('npm run build:prod')
44
+
45
+ // remove unnecessary packages
46
+ console.log('============= remove unnecessary packages =============')
47
+ runCommand('npm ci --omit=dev --omit=optional')
48
+ const prunePath = `${layerPath}/prune`
49
+ runCommand(`mkdir -p ${prunePath}`)
50
+ runCommand(`npm --prefix ./${prunePath} i node-prune modclean`)
51
+ runCommand(`npm --prefix ./${prunePath} exec node-prune`)
52
+ runCommand(
53
+ `npm --prefix ./${prunePath} exec modclean -- -n default:safe,default:caution -r`,
54
+ )
55
+ runCommand(`rm -rf ${prunePath}`)
56
+ runCommand(
57
+ 'mv node_modules/.prisma/client/libquery_engine-linux-arm64-* prisma',
58
+ )
59
+ runCommand('rm -rf node_modules/.prisma/client/libquery_engine-*')
60
+ runCommand(
61
+ 'mv prisma/libquery_engine-linux-arm64-* node_modules/.prisma/client',
62
+ )
63
+ runCommand('rm -rf node_modules/prisma/libquery_engine-*')
64
+ runCommand('rm -rf node_modules/@prisma/engines/**')
65
+
66
+ // copy to layer
67
+ console.log('============= copy to layer =============')
68
+ const nodejsLayerPath = `${layerPath}/nodejs`
69
+ runCommand(`mkdir -p ${nodejsLayerPath}`)
70
+ runCommand(`mv node_modules ${nodejsLayerPath}`)
71
+
72
+ console.log('============= build app finished =============')
73
+
74
+ if (isLocal) {
75
+ console.log('============= install local packages =============')
76
+ runCommand('npm install')
77
+ }
78
+
79
+ isBuild = true
80
+
81
+ return {
82
+ layerPath: layerFullPath,
83
+ appPath: appFullPath,
84
+ }
85
+ }