bootstrapped project
This commit is contained in:
parent
9b07e395b5
commit
0ee7b6f8cb
16 changed files with 346 additions and 0 deletions
5
.babelrc
Normal file
5
.babelrc
Normal file
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"plugins": [
|
||||
"transform-es2015-modules-commonjs"
|
||||
]
|
||||
}
|
32
.circleci/config.yml
Normal file
32
.circleci/config.yml
Normal 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
6
.gitignore
vendored
|
@ -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
18
Dockerfile
Normal 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
14
api/defaults.js
Normal 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
9
api/router.js
Normal 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
9
api/test/routes.js
Normal 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
58
config.js
Normal 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
|
22
config/config.default.json
Normal file
22
config/config.default.json
Normal 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
3
index.js
Normal file
|
@ -0,0 +1,3 @@
|
|||
require('babel-register')
|
||||
|
||||
require('./server')
|
38
package.json
Normal file
38
package.json
Normal 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
0
public/.gitkeep
Normal file
13
server.js
Normal file
13
server.js
Normal 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
89
test/helper.client.js
Normal 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
8
test/helper.server.js
Normal 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
22
test/server.test.js
Normal 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)
|
||||
})
|
||||
)
|
||||
})
|
Loading…
Reference in a new issue