Commit 2d6f79b9 authored by Vadym Gidulian's avatar Vadym Gidulian

Initial commit

parents
# Dependency directories
node_modules/
# Logs
logs/
*.log
npm-debug.log*
# Optional npm cache directory
.npm/
# Optional REPL history
.node_repl_history/
services:
- docker:dind
variables:
IMAGE_SNAPSHOT: $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
IMAGE: $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_NAME
IMAGE_LATEST: $CI_REGISTRY_IMAGE:latest
stages:
- build
- release
before_script:
- docker version
- docker info
- docker login -u gitlab-ci-token -p $CI_JOB_TOKEN $CI_REGISTRY
build:
stage: build
script:
- docker build --pull -t $IMAGE_SNAPSHOT .
- docker push $IMAGE_SNAPSHOT
tags:
- dind
release:
stage: release
variables:
GIT_STRATEGY: none
script:
- docker pull $IMAGE_SNAPSHOT
- docker tag $IMAGE_SNAPSHOT $IMAGE
- docker push $IMAGE
tags:
- dind
release:latest:
stage: release
variables:
GIT_STRATEGY: none
script:
- docker pull $IMAGE_SNAPSHOT
- docker tag $IMAGE_SNAPSHOT $IMAGE_LATEST
- docker push $IMAGE_LATEST
when: manual
tags:
- dind
only:
- master
FROM node:8-alpine
MAINTAINER Vadym Gidulian <vadym.gidulian@gvia.group>
COPY src/ /app
COPY package.json /app
COPY yarn.lock /app
WORKDIR /app
RUN yarn install --production &&\
yarn cache clean
CMD ["node", "."]
EXPOSE 80
version: '3'
services:
server:
image: node:8-alpine
volumes:
- .:/app
working_dir: /app
entrypoint: sh
command: -c "yarn && npx nodemon src"
environment:
DB_HOST: mongodb://mongo
DB_NAME: test
links:
- mongo
restart: always
mongo:
image: mongo
restart: always
{
"name": "storage-mongo-node",
"version": "1.0.0",
"dependencies": {
"express": "^4.16.2",
"mongodb": "^3.0.1"
},
"devDependencies": {
"nodemon": "^1.14.8"
}
}
'use strict';
const express = require('express');
const mongo = require('mongodb');
const MongoClient = mongo.MongoClient;
const ObjectID = mongo.ObjectID;
['DB_HOST', 'DB_NAME'].forEach(varname => {
if (!process.env[varname]) {
console.error(`Environment variable ${varname} is not defined!`);
process.exit(1);
}
});
const DB_HOST = process.env.DB_HOST;
const DB_NAME = process.env.DB_NAME;
const app = express();
app.use(express.json({
limit: '16mb'
}));
app.use(function (req, res, next) {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Methods', 'POST, PUT, GET, PATCH, DELETE, OPTIONS');
next();
});
app.post('/:collection', (req, res) => {
if (isObjectEmpty(req.body)) {
res.status(400).send('Body is empty');
return;
}
mongoSafeConnect(res, client => {
client.db(DB_NAME).collection(req.params.collection).insertOne(req.body, (err, result) => {
if (err) throw err;
const record = result.ops[0];
res.status(201).append('Location', `/${req.params.collection}/${record._id}`).send(record);
});
});
});
app.put('/:collection/:id', (req, res) => {
if (isObjectEmpty(req.body)) {
res.status(400).send('Body is empty');
return;
}
mongoSafeConnect(res, client => {
const collection = client.db(DB_NAME).collection(req.params.collection);
collection.findOne({_id: wrapId(req.params.id)}, (err, result) => {
if (err) throw err;
if (result) {
res.status(409).send(`Record with key ${req.params.id} already exists`);
return;
}
collection.insertOne({...req.body, _id: req.params.id}, (err, result) => {
if (err) throw err;
const record = result.ops[0];
res.status(201).append('Location', `/${req.params.collection}/${record._id}`).send(record);
});
});
});
});
app.get('/:collection', (req, res) => {
mongoSafeConnect(res, client => {
client.db(DB_NAME).collection(req.params.collection).find().toArray((err, result) => {
if (err) throw err;
res.status(200).send(result);
});
});
});
app.get('/:collection/:id', (req, res) => {
mongoSafeConnect(res, client => {
client.db(DB_NAME).collection(req.params.collection).findOne({_id: wrapId(req.params.id)}, (err, result) => {
if (err) throw err;
if (result) {
res.status(200).send(result);
} else {
res.status(404).send();
}
});
});
});
app.patch('/:collection/:id', (req, res) => {
if (isObjectEmpty(req.body)) {
res.status(400).send('Body is empty');
return;
}
mongoSafeConnect(res, client => {
delete req.body._id; // Immutable properties shouldn't be tried to change
client.db(DB_NAME).collection(req.params.collection).findOneAndUpdate({_id: wrapId(req.params.id)}, {$set: req.body}, {returnOriginal: false}, (err, result) => {
if (err) throw err;
if (result.value) {
res.status(200).send(result.value);
} else {
res.status(404).send();
}
});
});
});
app.delete('/:collection/:id', (req, res) => {
mongoSafeConnect(res, client => {
client.db(DB_NAME).collection(req.params.collection).findOneAndDelete({_id: wrapId(req.params.id)}, (err, result) => {
if (err) throw err;
if (result.value) {
res.status(200).send(result.value);
} else {
res.status(404).send();
}
});
});
});
app.listen(80, () => {
console.log('Server is started.');
});
function isObjectEmpty(obj) {
for (const key in obj) {
if (obj.hasOwnProperty(key)) return false;
}
return true;
}
function mongoSafeConnect(serverResponse, callback) {
MongoClient.connect(DB_HOST, (err, client) => {
try {
if (err) throw err;
if (callback && client) callback(client);
} catch (e) {
console.log(e);
serverResponse.status(500).send();
} finally {
if (client) client.close();
}
});
}
function wrapId(id) {
return ObjectID.isValid(id) ? new ObjectID(id) : id;
}
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment