Skip to content
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
15 changes: 15 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# package directories
../node_modules
../jspm_packages
../.idea

../package-lock.json

.env
# Serverless directories
.serverless

../.env

.gitignore

10 changes: 9 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,12 @@ Endpoint backend: https://o3lc79zr1i.execute-api.us-east-1.amazonaws.com/dev
#### Description: Get a product by ID
- productId is required
- productId is String
- curl --location --request GET 'https://o3lc79zr1i.execute-api.us-east-1.amazonaws.com/dev/products/ABCDE102030'
- curl --location --request GET 'https://o3lc79zr1i.execute-api.us-east-1.amazonaws.com/dev/products/ABC001'

### POST - Create product - /product
#### Description: Create a product

- title: String - is required
- description: String - is requires
- price: Number - is required
- count": Number - is required
13 changes: 12 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,19 @@
"author": "",
"license": "ISC",
"dependencies": {
"@supercharge/strings": "^1.28.0",
"aws-sdk": "^2.1181.0",
"chai": "^4.3.6",
"dotenv": "^16.0.1",
"lambda-tester": "^4.0.1",
"mocha": "^10.0.0"
"mocha": "^10.0.0",
"pg": "^8.7.3",
"uuid": "^8.3.2",
"webpack": "^5.73.0",
"webpack-node-externals": "^3.0.0"
},
"devDependencies": {
"serverless-dotenv-plugin": "^4.0.1",
"serverless-webpack": "^5.7.1"
}
}
11 changes: 11 additions & 0 deletions product-service/config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
const dotenv = require('dotenv');

module.exports = async ({ options, resolveConfigurationProperty }) => {
// Load env vars into Serverless environment
// You can do more complicated env var resolution with dotenv here
const envVars = dotenv.config({ path: '.env' }).parsed;
return Object.assign(
{},
envVars, // `dotenv` environment variables
);
};
69 changes: 63 additions & 6 deletions product-service/controller/product.controller.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,69 @@
'use strict';
const model = require('../model/product.model').products;
const {db} = require('../utils/util.connection');

const selectAll = function () {
return model;

const selectAll = async () => {
try {
console.log(`selectedAll executing`);
console.log(`DB Connection`);
const client = await db.connect();
console.log(`Selecting from Product Table`);
const select = await client.query('SELECT p.*, s.count FROM product p INNER JOIN stock s ON p.id = s.product_id');
client.release();
console.log(`Products: ${JSON.stringify(select.rows)}`);
return select.rows;
} catch (error) {
console.log(`Error occurred: ${error}`);
return undefined;
}
}

const selectById = function (product_id) {
return model.find(product => product.id === product_id);
const selectById = async (id) => {
try {
console.log(`selectById executing`);
console.log(`DB Connection`);
const client = await db.connect();
console.log(`Selecting from Product Table by ${id}`);
const select = await client.query(
`SELECT p.*, s.count FROM product p INNER JOIN stock s ON p.id = s.product_id WHERE p.id = $1`,
[id]
);
client.release();
console.log(`Product: ${JSON.stringify(select.rows)}`);
return select.rows;
} catch (error) {
console.log(`Error occurred: ${error}`);
return undefined;
}
}

module.exports = {selectAll, selectById};
const create = async (product) => {
console.log(`create product executing`);
console.log(`DB Connection`);
const client = await db.connect();
let isCreated = true;
try {
console.log(`BEGIN TRANSACTION`);
await client.query('BEGIN');

console.log(`INSERT product`);
await client.query(
'INSERT INTO public.product (id, title, description, price) VALUES ($1, $2, $3, $4)',
[product.id, product.title, product.description, product.price]
);
console.log(`COMMIT TRANSACTION`);
await client.query('COMMIT');

} catch (error) {
console.log(`ROLLBACK TRANSACTION`);
await client.query('ROLLBACK');
console.log(`An error occurred ${error}`);
isCreated = false;
} finally {
client.release();
}

return isCreated;
};

module.exports = {selectAll, selectById, create};
29 changes: 29 additions & 0 deletions product-service/controller/stock.controller.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
'use strict';
const {db} = require('../utils/util.connection');

const create = async (stock) => {
console.log(`create stock executing`);
console.log(`DB Connection`);
const client = await db.connect();
let isCreated = true;
try {
console.log(`BEGIN TRANSACTION`);
await client.query('BEGIN');

console.log(`INSERT stock`);
await client.query('INSERT INTO public.stock (product_id, count) VALUES ($1, $2)', [stock.productId, stock.count]);

console.log(`COMMIT TRANSACTION`);
await client.query('COMMIT');
} catch (error) {
console.log(`ROLLBACK TRANSACTION`);
await client.query('ROLLBACK');
console.log(`An error occurred ${error}`);
isCreated = false;
} finally {
client.release();
}
return isCreated;
};

module.exports = {create};
74 changes: 74 additions & 0 deletions product-service/create-product.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
'use strict';
const {v4: uuidv4} = require('uuid');

const product = require('./controller/product.controller').create;
const stock = require('./controller/stock.controller').create;

const utils = require('./utils/utils.functions');

module.exports.createProduct = async (event) => {
let data;
let status = 201;

try {
if (!event.body) {
status = 501;
data = 'Data not provided'
} else {
let body = JSON.parse(event.body);

if (body.title === undefined
|| body.description === undefined
|| body.price === undefined
|| body.count === undefined) {
status = 502;
data = 'Missing Data';
} else {

if (!utils.validateProductData(body)) {
status = 400;
data = 'Data is Invalid';
} else {
const p = {}
p.id = uuidv4();
p.title = body.title;
p.price = body.price;

let isCreated = await product(p);

if(isCreated) {
console.log(`Create Stock from Product`);
const s = {};
s.productId = p.id;
s.count = body.count;

isCreated = await stock(s);

if(isCreated) {
data = `Product created ID: ${p.id}`;
} else {
status = 504;
data = `An error occurred on Stock creation`;
}
} else {
status = 503;
data = `Can't created product, an error occurred`;
}
}
}
}
} catch (error) {
console.log(`Error: ${error}`);
status = 500;
data = `An error occurred`
}

return {
statusCode: status,
headers: {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Credentials': true,
},
body: JSON.stringify(data)
};
}
8 changes: 6 additions & 2 deletions product-service/get-product.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,22 @@

const getById = require('./controller/product.controller').selectById;

module.exports.getProductsById = async (event) => {
module.exports.getProductById = async (event) => {
let status = 200;
let product = {}
if (event[`pathParameters`].productId === '' || !event[`pathParameters`].productId) {
status = 500;
} else {
const id = event[`pathParameters`].productId;
product = getById(id);
product = await getById(id);
if(product === undefined) {
status = 404
product = {
message: 'Product not found'
}
}
}
console.log(product);
return {
statusCode: status,
headers: {
Expand Down
5 changes: 4 additions & 1 deletion product-service/get-products.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@
const selectAll = require('./controller/product.controller').selectAll;

module.exports.getProductsList = async () => {
const products = selectAll();
console.log('getProductsList Started')
const products = await selectAll();
console.log('getProductsList executed')
console.log(JSON.stringify(products));
return {
statusCode: 200,
headers: {
Expand Down
1 change: 1 addition & 0 deletions product-service/path.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"pathParameters":{"productId":"ABCDE102030"}}
63 changes: 48 additions & 15 deletions product-service/serverless.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,23 @@ provider:
runtime: nodejs12.x
stage: dev
region: us-east-1
environment:
USER_DB: ${self:custom.dotenvVars.USER_DB, env:USER_DB, ''}
HOST_DB: ${self:custom.dotenvVars.HOST_DB, env:HOST_DB, ''}
PWD_DB: ${self:custom.dotenvVars.PWD_DB, env:PWD_DB, ''}
PORT_DB: ${self:custom.dotenvVars.PORT_DB, env:PORT_DB, ''}
DB_NAME: ${self:custom.dotenvVars.DB_NAME, env:DB_NAME, ''}

plugins:
- serverless-webpack
- serverless-dotenv-plugin

custom:
dotenvVars: ${./configs.js)}
webpack:
webpackConfig: 'webpack.config.js' # Name of webpack configuration file
includeModules: false
packager: 'npm'

# you can overwrite defaults here
# stage: dev
Expand All @@ -47,23 +64,39 @@ functions:
- X-Amz-Security-Token
- X-Amz-User-Agent
allowCredentials: false
getProductsById:
getProductById:
handler: get-product.getProductById
events:
- http:
path: /products/{productId}
method: get
cors:
origins: '*'
headers:
- Content-Type
- X-Amz-Date
- Authorization
- X-Api-Key
- X-Amz-Security-Token
- X-Amz-User-Agent
allowCredentials: false
request:
parameters:
paths:
productId: true
cors:
origins: '*'
headers:
- Content-Type
- X-Amz-Date
- Authorization
- X-Api-Key
- X-Amz-Security-Token
- X-Amz-User-Agent
allowCredentials: false
request:
parameters:
paths:
productId: true
createProduct:
handler: create-product.createProduct
events:
- http:
path: products
method: post
cors:
origin: '*' # <-- Specify allowed origin
headers: # <-- Specify allowed headers
- Content-Type
- X-Amz-Date
- Authorization
- X-Api-Key
- X-Amz-Security-Token
- X-Amz-User-Agent
allowCredentials: false
Loading