Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

task-3: getProducts mock #9

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
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 .prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
.serverless
*.yml
5 changes: 5 additions & 0 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"trailingComma": "es5",
"semi": true,
"singleQuote": true
}
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
# shop-nodejs-aws-serverless

Backend for E-Commerce application (Shop) created with NodeJS, AWS Cloud and Serverless architecture and Serverless framework
8 changes: 2 additions & 6 deletions import-service/configs.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,5 @@ const dotenv = require('dotenv');

module.exports = async () => {
const envVars = dotenv.config({ path: '.env.local' }).parsed;
return Object.assign(
{},
envVars,
process.env,
);
};
return Object.assign({}, envVars, process.env);
};
8 changes: 4 additions & 4 deletions import-service/handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@ import AWS from 'aws-sdk';
import * as handlers from './src';
import { winstonLogger as logger } from './src/utils/winstonLogger';

const s3 = new AWS.S3({ region: 'us-east-1' });
const s3 = new AWS.S3({ region: 'eu-west-1' });

export const getProductById = handlers.importFileParser({
s3,
logger,
s3,
logger,
});

export const getAllProducts = handlers.importProductsFile({
s3,
s3,
});
52 changes: 29 additions & 23 deletions import-service/src/importFileParser.ts
Original file line number Diff line number Diff line change
@@ -1,30 +1,36 @@
import csv from 'csv-parser';
const BUCKET = process.env.BUCKET;

export const importFileParser = ({
s3,
logger,
}) => async (event) => {
event.Records.forEach(record => {
const s3Stream = s3.getObject({
Bucket: BUCKET,
Key: record.s3.object.key
}).createReadStream();
export const importFileParser =
({ s3, logger }) =>
async (event) => {
event.Records.forEach((record) => {
const s3Stream = s3
.getObject({
Bucket: BUCKET,
Key: record.s3.object.key,
})
.createReadStream();

s3Stream.pipe(csv())
.on('data', (data) => {
logger.log(data);
})
.on('end', async () => {
logger.log(`Copy from ${BUCKET}/${record.s3.object.key}`);
s3Stream
.pipe(csv())
.on('data', (data) => {
logger.log(data);
})
.on('end', async () => {
logger.log(`Copy from ${BUCKET}/${record.s3.object.key}`);

await s3.copyObject({
Bucket: BUCKET,
CopySource: `${BUCKET}/${record.s3.object.key}`,
Key: record.s3.object.key.replace('uploaded', 'parsed')
}).promise();
await s3
.copyObject({
Bucket: BUCKET,
CopySource: `${BUCKET}/${record.s3.object.key}`,
Key: record.s3.object.key.replace('uploaded', 'parsed'),
})
.promise();

logger.log(`Copied into ${BUCKET}/${record.s3.object.key.replace('uploaded', 'parsed')}`);
});
logger.log(
`Copied into ${BUCKET}/${record.s3.object.key.replace('uploaded', 'parsed')}`
);
});
});
}
};
38 changes: 19 additions & 19 deletions import-service/src/importProductsFile.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,24 @@
const BUCKET = process.env.BUCKET;
import { errorResponse, successResponse } from "./utils/apiResponseBuilder";
import { errorResponse, successResponse } from './utils/apiResponseBuilder';

export const importProductsFile = ({
s3,
}) => async (event) => {
export const importProductsFile =
({ s3 }) =>
async (event) => {
try {
const catalogName = event.queryStringParameters.name;
const catalogPath = `uploaded/${catalogName}`;
const params = {
Bucket: BUCKET,
Key: catalogPath,
Expires: 60,
ContentType: 'text/csv'
};
const url = await s3.getSignedUrlPromise('putObject', params)
return successResponse(url);
const catalogName = event.queryStringParameters.name;
const catalogPath = `uploaded/${catalogName}`;

const params = {
Bucket: BUCKET,
Key: catalogPath,
Expires: 60,
ContentType: 'text/csv',
};

const url = await s3.getSignedUrlPromise('putObject', params);

return successResponse(url);
} catch (error) {
errorResponse(error);
errorResponse(error);
}
}
};
62 changes: 35 additions & 27 deletions import-service/src/utils/apiResponseBuilder.ts
Original file line number Diff line number Diff line change
@@ -1,39 +1,47 @@
import {winstonLogger} from "./winstonLogger";
import { winstonLogger } from './winstonLogger';

interface ResponseInterface {
statusCode: number
headers: Object,
body: Object
statusCode: number;
headers: Object;
body: Object;
}

const defaultHeaders = {
'Access-Control-Allow-Methods': '*',
'Access-Control-Allow-Headers': '*',
'Access-Control-Allow-Origin': '*'
'Access-Control-Allow-Methods': '*',
'Access-Control-Allow-Headers': '*',
'Access-Control-Allow-Origin': '*',
};

const errorResponse = ( err: Error, statusCode: number = 500 ): ResponseInterface => {
winstonLogger.logError( `Error: ${ err.message }` );
const errorResponse = (
err: Error,
statusCode: number = 500
): ResponseInterface => {
winstonLogger.logError(`Error: ${err.message}`);

return {
statusCode,
headers: {
...defaultHeaders
},
body: JSON.stringify( { message: err.message || 'Something went wrong !!!' })
}
}
return {
statusCode,
headers: {
...defaultHeaders,
},
body: JSON.stringify({
message: err.message || 'Something went wrong !!!',
}),
};
};

const successResponse = ( body: Object, statusCode: number = 200 ): ResponseInterface => {
winstonLogger.logRequest( `Lambda successfully invoked and finished` );
const successResponse = (
body: Object,
statusCode: number = 200
): ResponseInterface => {
winstonLogger.logRequest(`Lambda successfully invoked and finished`);

return {
statusCode,
headers: {
...defaultHeaders
},
body: JSON.stringify( body )
}
}
return {
statusCode,
headers: {
...defaultHeaders,
},
body: JSON.stringify(body),
};
};

export { errorResponse, successResponse, ResponseInterface };
54 changes: 28 additions & 26 deletions import-service/src/utils/winstonLogger.ts
Original file line number Diff line number Diff line change
@@ -1,38 +1,40 @@
import winston from 'winston';

interface LoggerInterface {
logRequest: ( message: string ) => void
logError: ( message: string ) => void
logRequest: (message: string) => void;
logError: (message: string) => void;
}

class WinstonLogger implements LoggerInterface {
private readonly logger: any;
private readonly format: any;
private readonly logger: any;
private readonly format: any;

constructor() {
this.format = winston.format.combine(
winston.format.colorize(),
winston.format.timestamp(),
winston.format.align(),
winston.format.printf(info => `${info.timestamp} ${info.level}: ${info.message}`)
);
constructor() {
this.format = winston.format.combine(
winston.format.colorize(),
winston.format.timestamp(),
winston.format.align(),
winston.format.printf(
(info) => `${info.timestamp} ${info.level}: ${info.message}`
)
);

this.logger = winston.createLogger({
level: process.env.ENV_STAGE === 'prod' ? 'error' : 'info',
transports: [
new winston.transports.Console({
format: this.format
})
]
});
}
logRequest( message: string ){
this.logger.info( message );
}
this.logger = winston.createLogger({
level: process.env.ENV_STAGE === 'prod' ? 'error' : 'info',
transports: [
new winston.transports.Console({
format: this.format,
}),
],
});
}
logRequest(message: string) {
this.logger.info(message);
}

logError( message: string ){
this.logger.error( message );
}
logError(message: string) {
this.logger.error(message);
}
}

const winstonLogger = new WinstonLogger();
Expand Down
6 changes: 4 additions & 2 deletions import-service/webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ module.exports = {
context: __dirname,
mode: slsw.lib.webpack.isLocal ? 'development' : 'production',
entry: slsw.lib.entries,
devtool: slsw.lib.webpack.isLocal ? 'cheap-module-eval-source-map' : 'source-map',
devtool: slsw.lib.webpack.isLocal
? 'cheap-module-eval-source-map'
: 'source-map',
resolve: {
extensions: ['.mjs', '.json', '.ts'],
symlinks: false,
Expand Down Expand Up @@ -39,5 +41,5 @@ module.exports = {
},
},
],
}
},
};
28 changes: 27 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,8 @@
"bugs": {
"url": "https://github.com/EPAM-JS-Competency-center/shop-nodejs-aws-serverless/issues"
},
"homepage": "https://github.com/EPAM-JS-Competency-center/shop-nodejs-aws-serverless#readme"
"homepage": "https://github.com/EPAM-JS-Competency-center/shop-nodejs-aws-serverless#readme",
"devDependencies": {
"prettier": "3.2.5"
}
}
8 changes: 2 additions & 6 deletions product-service/configs.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,5 @@ const dotenv = require('dotenv');

module.exports = async () => {
const envVars = dotenv.config({ path: '.env.local' }).parsed;
return Object.assign(
{},
envVars,
process.env,
);
};
return Object.assign({}, envVars, process.env);
};
17 changes: 8 additions & 9 deletions product-service/handler.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
import * as handlers from './src';
import { Client } from 'pg';
import { PostgresProductService } from './src/services/postgres-memory-product-service';
import { InMemoryProductService } from './src/services/in-memory-product-service';

console.log(process.env);
const inMemoryProductService = new InMemoryProductService();

const databaseClient = new Client();
databaseClient.connect();
const productService = new PostgresProductService(databaseClient)
export const getProductById = handlers.getProductByIdHandler(
inMemoryProductService
);

export const getProductById = handlers.getProductByIdHandler(productService);
export const getAllProducts = handlers.getAllProductsHandler(productService);
export const createProduct = handlers.createProductHandler(productService);
export const getProductsList = handlers.getProductsListHandler(
inMemoryProductService
);
Loading