bootstrapped project

dev
Jonatan Nilsson 2017-12-09 21:51:18 +00:00
parent 9b07e395b5
commit 0ee7b6f8cb
16 changed files with 346 additions and 0 deletions

5
.babelrc Normal file
View File

@ -0,0 +1,5 @@
{
"plugins": [
"transform-es2015-modules-commonjs"
]
}

32
.circleci/config.yml Normal file
View File

@ -0,0 +1,32 @@
version: 2
jobs:
build:
docker:
- image: docker:latest
environment:
- di: "nfpis/storage-upload"
- dtag: "latest"
working_directory: ~/storage-upload
steps:
- run:
name: Update and install SSH & Git
command: apk update && apk upgrade && apk add --no-cache bash git openssh
- checkout
- setup_remote_docker
- run:
name: Build docker image
command: |
docker build -t test .
docker build --build-arg NODE=production -t ${di}:build_${CIRCLE_BUILD_NUM} -t ${di}:${CIRCLE_SHA1} -t ${di}:${dtag} .
- deploy:
name: Push to docker
command: |
docker login -u $DOCKER_USER -p $DOCKER_PASS
docker push ${di}
workflows:
version: 2
build_deploy:
jobs:
- build:
context: org-global

6
.gitignore vendored
View File

@ -57,3 +57,9 @@ typings/
# dotenv environment variables file
.env
# Local development config file
config/config.json
# lol
package-lock.json

18
Dockerfile Normal file
View File

@ -0,0 +1,18 @@
FROM node:slim
ARG NODE=development
ENV HOME=/app \
NODE_ENV=${NODE}
COPY package.json $HOME/
WORKDIR $HOME
RUN npm install
COPY . $HOME/
EXPOSE 4020
CMD ["npm", "start"]

14
api/defaults.js Normal file
View File

@ -0,0 +1,14 @@
export default function defaults(options, defaults) {
options = options || {}
Object.keys(defaults).forEach(function(key) {
if (typeof options[key] === 'undefined') {
// No need to do clone since we mostly deal with
// flat objects
options[key] = defaults[key]
}
})
return options
}

9
api/router.js Normal file
View File

@ -0,0 +1,9 @@
import Router from 'koa-router'
import * as test from './test/routes'
const router = new Router()
router.get('/api/test', test.testStatic)
export default router

9
api/test/routes.js Normal file
View File

@ -0,0 +1,9 @@
import config from '../../config'
export async function testStatic(ctx) {
ctx.body = {
name: config.get('name'),
version: config.get('version'),
environment: config.get('NODE_ENV'),
}
}

58
config.js Normal file
View File

@ -0,0 +1,58 @@
'use strict'
const _ = require('lodash')
const nconf = require('nconf')
// Helper method for global usage.
nconf.inTest = () => nconf.get('NODE_ENV') === 'test'
// Config follow the following priority check order:
// 1. package.json
// 2. Enviroment variables
// 3. config/config.json
// 4. config/config.default.json
// Load package.json for name and such
let pckg = require('./package.json')
pckg = _.pick(pckg, ['name', 'version', 'description', 'author', 'license', 'homepage'])
// Load overrides as first priority
nconf.overrides(pckg)
// Load enviroment variables as second priority
nconf.env()
// Load any overrides from the appropriate config file
let configFile = 'config/config.json'
/* istanbul ignore else */
if (nconf.get('NODE_ENV') === 'test') {
configFile = 'config/config.test.json'
}
/* istanbul ignore if */
if (nconf.get('NODE_ENV') === 'production') {
configFile = 'config/config.production.json'
}
nconf.file('main', configFile)
// Load defaults
nconf.file('default', 'config/config.default.json')
// Final sanity checks
/* istanbul ignore if */
if (typeof global.it === 'function' & !nconf.inTest()) {
// eslint-disable-next-line no-console
console.log('Critical: potentially running test on production enviroment. Shutting down.')
process.exit(1)
}
module.exports = nconf

View File

@ -0,0 +1,22 @@
{
"NODE_ENV": "development",
"server": {
"port": 4020,
"host": "0.0.0.0"
},
"bunyan": {
"name": "storage-upload",
"streams": [{
"stream": "process.stdout",
"level": "debug"
}
]
},
"jwt": {
"secret": "this-is-my-secret",
"options": {
"expiresIn": 604800
}
},
"fileSize": 524288000
}

3
index.js Normal file
View File

@ -0,0 +1,3 @@
require('babel-register')
require('./server')

38
package.json Normal file
View File

@ -0,0 +1,38 @@
{
"name": "storage-upload",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"dev": "nodemon index.js",
"start": "node index.js",
"test": "env NODE_ENV=test mocha --require babel-register --recursive --reporter dot",
"docker": "docker run -it --rm --name my-running-script -v \"$PWD\":/usr/src/app -w /usr/src/app node:slim",
"docker:test": "npm run docker -- npm install && npm run test",
"docker:dev": "npm run docker -- npm install && npm run dev",
"docker:prod": "npm run docker -- npm install && npm run start"
},
"repository": {
"type": "git",
"url": "git+https://github.com/nfp-projects/storage-upload.git"
},
"author": "Jonatan Nilsson",
"license": "WTFPL",
"bugs": {
"url": "https://github.com/nfp-projects/storage-upload/issues"
},
"homepage": "https://github.com/nfp-projects/storage-upload#readme",
"dependencies": {
"babel-plugin-transform-es2015-modules-commonjs": "^6.26.0",
"babel-register": "^6.26.0",
"koa": "^2.3.0",
"koa-router": "^7.2.1",
"nconf": "^0.8.5"
},
"devDependencies": {
"assert-extended": "^1.0.1",
"mocha": "^4.0.1",
"nodemon": "^1.12.1",
"request-json": "^0.6.2"
}
}

0
public/.gitkeep Normal file
View File

13
server.js Normal file
View File

@ -0,0 +1,13 @@
import Koa from 'koa'
import config from './config'
import router from './api/router'
const app = new Koa()
app.use(router.routes())
app.use(router.allowedMethods())
const server = app.listen(config.get('server:port'))
export default server

89
test/helper.client.js Normal file
View File

@ -0,0 +1,89 @@
import request from 'request-json'
import defaults from '../api/defaults'
import config from '../config'
function parseBody(body, reject) {
try {
return JSON.parse(body)
} catch (error) {
// eslint-disable-next-line no-console
console.log(body)
return reject(error)
}
}
function callback(resolve, reject) {
return (err, res, rawBody) => {
let body = rawBody
if (err) {
return reject(err)
}
if (typeof body === 'string' && body) {
body = parseBody(body, reject)
}
if (res.statusCode >= 300 ||
res.statusCode < 200) {
return reject(body)
}
resolve(body)
}
}
export default function createClient(host = config.get('server:port'), opts) {
let options = defaults(opts, {})
let client = request.createClient('', options)
let prefix
prefix = `http://localhost:${host}`
client.headers['x-request-id'] = 'asdf'
client.auth = (user) => {
// let m = helperDB.model('user', {
// id: user.id,
// level: (user.get && user.get('level')) || 1,
// institute_id: (user.get && user.get('institute_id')) || null,
// password: (user.get && user.get('password')) || null,
// })
// let token = jwt.createUserToken(m)
// client.headers.authorization = `Bearer ${token}`
}
// Simple wrappers to wrap into promises
client.getAsync = (path) =>
new Promise((resolve, reject) => {
if (path.slice(0, 4) === 'http') {
return client.get(path, callback(resolve, reject))
}
client.get(prefix + path, callback(resolve, reject))
})
// Simple wrappers to wrap into promises
client.saveFileAsync = (path, destination) =>
new Promise((resolve, reject) => {
client.saveFile(prefix + path, destination, callback(resolve, reject, true))
})
client.postAsync = (path, data) =>
new Promise((resolve, reject) => {
client.post(prefix + path, data, callback(resolve, reject))
})
client.putAsync = (path, data) =>
new Promise((resolve, reject) => {
client.put(prefix + path, data, callback(resolve, reject))
})
client.deleteAsync = (path) =>
new Promise((resolve, reject) => {
client.del(prefix + path, callback(resolve, reject))
})
client.sendFileAsync = (path, files, data) =>
new Promise((resolve, reject) => {
client.sendFile(prefix + path, files, data || {}, callback(resolve, reject))
})
return client
}

8
test/helper.server.js Normal file
View File

@ -0,0 +1,8 @@
// import _ from 'lodash'
// import sinon from 'sinon'
import server from '../server'
import client from './helper.client'
after(() => server.close())
export const createClient = client

22
test/server.test.js Normal file
View File

@ -0,0 +1,22 @@
import assert from 'assert-extended'
import * as server from './helper.server'
describe('Server', () => {
let client
beforeEach(() => {
client = server.createClient()
})
it('should run', () =>
assert.isFulfilled(
client.getAsync('/api/test')
)
.then(data => {
assert.ok(data)
assert.ok(data.name)
assert.ok(data.version)
})
)
})