Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,5 @@ node_modules
**/screenshots
yarn.build.json
ssh-keypair*

.localstack
43 changes: 43 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,16 @@ export BOOTSTRAP_ENV=terraform/bootstrap
define TFVARS_DATA
target_env = "$(ENV_NAME)"
project_code = "$(PROJECT)"
lz2_code = "$(LZ2_PROJECT)"
build_id = "$(COMMIT_SHA)"
build_info = "$(LAST_COMMIT_MESSAGE)"
endef
export TFVARS_DATA

# AWS Environments variables
export AWS_REGION ?= ca-central-1
APP_SRC_BUCKET = $(LZ2_PROJECT)-$(ENV_NAME)-packages

.PHONY:


Expand Down Expand Up @@ -95,3 +100,41 @@ else
@git tag -fa prod -m "Deploy prod: $(version)"
@git push --force origin refs/tags/prod:refs/tags/prod
endif


# ===================================
# API Build
# ===================================

pre-build:
@echo "++\n***** Pre-build Clean Build Artifact\n++"
@rm -rf ./terraform/build || true
@mkdir -p ./terraform/build
@echo "++\n*****"

build-api: pre-build
@echo 'Deleting existing build dir...\n'
@rm -rf ./.build || true

@echo "++\n***** Building API for AWS\n++"
@yarn || yarn workspace @payment/backend build
@yarn workspaces focus @payment/backend --production

@echo 'Creating build dir...\n' && mkdir -p .build/backend
@echo 'Copy Node modules....\n' && cp -r node_modules .build/backend
@echo 'Unlink local packages...\n' && rm -rf .build/backend/node_modules/@payment/*
@echo 'Copy backend dist build files ...\n' && cp -r apps/backend/dist/* .build/backend

@echo 'Creating Zip ...\n' && cd .build && mkdir pkg && zip -r ./pkg/backend.zip ./backend && cd ..
@echo "Done!++\n****"

# ===================================
# AWS Deployments
# ===================================

sync-app:
aws s3 sync ./.build/pkg s3://$(APP_SRC_BUCKET) --delete

# Full redirection to /dev/null is required to not leak env variables
deploy-api:
aws lambda update-function-code --function-name Payment_Common_Component_API --zip-file fileb://./.build/pkg/backend.zip --region $(AWS_REGION) > /dev/null
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,15 @@

### Technical Setup

Prerequisites:

- Docker
- Docker Compose
- Python 3 & pip
- AWS Cli V2 - (https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html)
- Localstack `awslocal` https://docs.localstack.cloud/integrations/aws-cli/#localstack-aws-cli-awslocal
- Cyberduck - To browse s3 files


#### Yarn Workspaces Setup

Expand Down
37 changes: 0 additions & 37 deletions apps/backend/lambdas/lambda_pub.ts

This file was deleted.

51 changes: 0 additions & 51 deletions apps/backend/lambdas/lambda_sub.ts

This file was deleted.

29 changes: 17 additions & 12 deletions apps/backend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@
"build": "rimraf dist && nest build",
"format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
"start": "nest start",
"start:dev": "nest start --watch",
"start:dev": "NODE_ENV=local nest start --watch",
"start:debug": "nest start --debug --watch",
"start:prod": "node dist/main",
"start:prod": "NODE_ENV=prod node dist/main",
"lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
"test": "jest",
"test:watch": "jest --watch",
Expand All @@ -21,16 +21,21 @@
"test:e2e": "jest --config ./test/jest-e2e.json"
},
"dependencies": {
"@nestjs/common": "^8.0.0",
"@nestjs/core": "^8.0.0",
"@nestjs/platform-express": "^8.0.0",
"aws-lambda": "^1.0.7",
"nats": "^2.7.1",
"nest-winston": "^1.6.2",
"node-nats-streaming": "^0.3.2",
"reflect-metadata": "^0.1.13",
"rimraf": "^3.0.2",
"rxjs": "^7.2.0",
"@nestjs/common": "8.0.0",
"@nestjs/config": "2.2.0",
"@nestjs/core": "8.0.0",
"@nestjs/platform-express": "8.0.0",
"@vendia/serverless-express": "^4.10.1",
"aws-lambda": "1.0.7",
"aws-sdk": "^2.1230.0",
"class-transformer": "^0.5.1",
"class-validator": "^0.13.2",
"nest-aws-sdk": "^3.0.0",
"nest-winston": "1.6.2",
"node-nats-streaming": "0.3.2",
"reflect-metadata": "0.1.13",
"rimraf": "3.0.2",
"rxjs": "7.2.0",
"winston": "3.3.3"
},
"devDependencies": {
Expand Down
88 changes: 88 additions & 0 deletions apps/backend/src/app.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import { NestFactory } from '@nestjs/core';
import {
BadRequestException,
ValidationError,
ValidationPipe,
ValidationPipeOptions,
} from '@nestjs/common';
import { ExpressAdapter, NestExpressApplication } from '@nestjs/platform-express';
import express from 'express';

import { AppModule } from './app.module';
import { AppLogger } from './common/logger.service';
import { API_PREFIX } from './config';
import { TrimPipe } from './trim.pipe';

interface ValidationErrorMessage {
property: string;
errors: string[];
}

export const validationPipeConfig: ValidationPipeOptions = {
transform: true,
whitelist: true,
forbidNonWhitelisted: false,
enableDebugMessages: false,
disableErrorMessages: true,
exceptionFactory: errors => {
const getErrorMessages = (error: ValidationError): ValidationErrorMessage[] => {
const messages: ValidationErrorMessage[] = [];
if (error.constraints) {
messages.push({
property: error.property,
errors: Object.values(error.constraints),
});
}
if (error.children && error.children?.length > 0) {
messages.push(...error.children.map(getErrorMessages).reduce((a, c) => a.concat(c), []));
}
return messages;
};
const errorMessages = errors.map(error => getErrorMessages(error));
throw new BadRequestException(errorMessages);
},
};

export async function createNestApp(): Promise<{
app: NestExpressApplication;
expressApp: express.Application;
}> {
// Express app
const expressApp = express();
expressApp.disable('x-powered-by');

// Nest Application With Express Adapter
let app: NestExpressApplication;
if (process.env.RUNTIME_ENV === 'local') {
app = await NestFactory.create(AppModule, {
logger: new AppLogger(),
});
} else {
app = await NestFactory.create<NestExpressApplication>(
AppModule,
new ExpressAdapter(expressApp),
);
// Adding winston logger
app.useLogger(new AppLogger());
}

// Validation pipe
app.useGlobalPipes(new TrimPipe(), new ValidationPipe(validationPipeConfig));

// Api prefix api/v1/
app.setGlobalPrefix(API_PREFIX);

// Printing the environment variables
// eslint-disable-next-line no-console
console.table({
project: process.env.PROJECT,
envName: process.env.ENV_NAME,
nodeEnv: process.env.NODE_ENV,
runtimeEnv: process.env.RUNTIME_ENV,
alertsEnabled: Boolean(false),
});
return {
app,
expressApp,
};
}
14 changes: 10 additions & 4 deletions apps/backend/src/app.controller.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
import { Controller, Get } from '@nestjs/common';
import { Controller, Get, InternalServerErrorException } from '@nestjs/common';
import { AppService } from './app.service';

@Controller()
export class AppController {
constructor(private readonly appService: AppService) {}

@Get()
getHello(): string {
return this.appService.getHello();

@Get('/version')
getVersion(): object {
return this.appService.getVersionInfo();
}

@Get('/error')
getError(): object {
throw new InternalServerErrorException('Breaking uptime');
}
}
29 changes: 27 additions & 2 deletions apps/backend/src/app.module.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,36 @@
import { S3ManagerModule } from './s3-manager/s3-manager.module';
import { FixedWidthRecordModule } from './common/fixedWidthRecord/fixedWidthRecord.module';
import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { AppLogger } from './common/logger.service';
import { Nats } from './nats/nats.service';
import { SalesModule } from './sales/sales.module';
import { FirehoseModule } from './firehose/firehose.module';
import { AwsSdkModule } from 'nest-aws-sdk';
import { Firehose, S3 } from 'aws-sdk';

@Module({
imports: [Nats],

imports: [
S3ManagerModule,
FixedWidthRecordModule,
SalesModule,
FirehoseModule,
ConfigModule.forRoot({
ignoreEnvFile: process.env.NODE_ENV === 'local' ? false : true,
}),
AwsSdkModule.forRoot({
defaultServiceOptions: {
...process.env.NODE_ENV === 'local' ? {
endpoint: process.env.AWS_ENDPOINT,
region: process.env.AWS_REGION,
s3ForcePathStyle: true,
} : {}
},
services: [Firehose, S3],
}),
],
controllers: [AppController],
providers: [AppService, AppLogger],
})
Expand Down
8 changes: 6 additions & 2 deletions apps/backend/src/app.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@ import { Injectable } from '@nestjs/common';

@Injectable()
export class AppService {
getHello(): string {
return 'Hello World!';
getVersionInfo(): object {
return {
buildId: process.env.BUILD_ID ?? 'NA',
info: process.env.BUILD_INFO ?? 'NA',
env: process.env.ENV_NAME ?? 'NA',
};
}
}
Loading