Development
This commit is contained in:
parent
d209097045
commit
f35c195680
12 changed files with 189 additions and 192 deletions
|
@ -1,3 +0,0 @@
|
|||
.circleci
|
||||
node_modules
|
||||
public
|
85
.eslintrc
85
.eslintrc
|
@ -1,85 +0,0 @@
|
|||
{
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 9,
|
||||
"sourceType": "module",
|
||||
"ecmaFeatures": {
|
||||
"impliedStrict": true
|
||||
}
|
||||
},
|
||||
"globals": {
|
||||
"FroalaEditor": "readonly",
|
||||
"gapi": "readonly",
|
||||
"m": true
|
||||
},
|
||||
"extends": "eslint:recommended",
|
||||
"env": {
|
||||
"mocha": true,
|
||||
"node": true,
|
||||
"es6": true,
|
||||
"browser": true
|
||||
},
|
||||
"rules": {
|
||||
"require-await": 0,
|
||||
"array-callback-return": 2,
|
||||
"block-scoped-var": 2,
|
||||
"complexity": ["error", 40],
|
||||
"eqeqeq": [2, "smart"],
|
||||
"no-else-return": ["error", { "allowElseIf": false }],
|
||||
"no-extra-bind": 2,
|
||||
"no-implicit-coercion": 2,
|
||||
"no-invalid-this": 2,
|
||||
"no-loop-func": 2,
|
||||
"no-multi-spaces": 2,
|
||||
"no-multi-str": 2,
|
||||
"no-new": 2,
|
||||
"no-param-reassign": [2, {"props": false}],
|
||||
"no-return-assign": 2,
|
||||
"no-return-await": 2,
|
||||
"no-self-compare": 2,
|
||||
"no-sequences": 2,
|
||||
"no-throw-literal": 2,
|
||||
"no-unmodified-loop-condition": 2,
|
||||
"no-useless-call": 2,
|
||||
"no-useless-concat": 2,
|
||||
"no-useless-return": 2,
|
||||
"no-void": 2,
|
||||
"no-warning-comments": 2,
|
||||
"prefer-promise-reject-errors": 2,
|
||||
"no-catch-shadow": 2,
|
||||
"no-shadow": 2,
|
||||
"no-undef-init": 2,
|
||||
"no-undefined": 2,
|
||||
"no-use-before-define": 2,
|
||||
"no-new-require": 2,
|
||||
"no-sync": 2,
|
||||
"array-bracket-newline": [2, "consistent"],
|
||||
"block-spacing": [2, "always"],
|
||||
"brace-style": [2, "1tbs", { "allowSingleLine": true }],
|
||||
"comma-dangle": [2, "always-multiline"],
|
||||
"comma-spacing": 2,
|
||||
"comma-style": 2,
|
||||
"computed-property-spacing": 2,
|
||||
"eol-last": 2,
|
||||
"func-call-spacing": 2,
|
||||
"key-spacing": 2,
|
||||
"keyword-spacing": 2,
|
||||
|
||||
"semi": [2, "never"],
|
||||
"max-len": [1, 120],
|
||||
"prefer-const": 0,
|
||||
"consistent-return": 0,
|
||||
"no-unused-vars": [
|
||||
2,
|
||||
{
|
||||
"args": "after-used",
|
||||
"argsIgnorePattern": "next|res|req|vnode"
|
||||
}
|
||||
],
|
||||
"generator-star-spacing": 0,
|
||||
"global-require": 0,
|
||||
"import/prefer-default-export": 0,
|
||||
"no-underscore-dangle": 0,
|
||||
"strict": 0,
|
||||
"require-yield": 0
|
||||
}
|
||||
}
|
1
.npmrc
Normal file
1
.npmrc
Normal file
|
@ -0,0 +1 @@
|
|||
package-lock=false
|
50
Dockerfile
50
Dockerfile
|
@ -1,50 +0,0 @@
|
|||
###########################
|
||||
# Angular
|
||||
###########################
|
||||
FROM node:12-alpine as build
|
||||
|
||||
ENV HOME=/app
|
||||
|
||||
COPY package.json $HOME/
|
||||
COPY app $HOME/app
|
||||
COPY public $HOME/public
|
||||
|
||||
WORKDIR $HOME
|
||||
|
||||
RUN apk add --update --no-cache --virtual .build-deps gcc g++ make libc6-compat python git && \
|
||||
apk add vips-dev fftw-dev build-base --no-cache \
|
||||
--repository http://dl-3.alpinelinux.org/alpine/v3.10/community \
|
||||
--repository http://dl-3.alpinelinux.org/alpine/v3.10/main && \
|
||||
npm install && \
|
||||
apk del .build-deps gcc g++ make libc6-compat python && \
|
||||
apk del build-base && \
|
||||
npm run build
|
||||
|
||||
###########################
|
||||
# Server
|
||||
###########################
|
||||
FROM node:12-alpine
|
||||
|
||||
ENV HOME=/app
|
||||
|
||||
COPY index.mjs package.json $HOME/
|
||||
|
||||
WORKDIR $HOME
|
||||
|
||||
RUN apk add --update --no-cache --virtual .build-deps gcc g++ make libc6-compat python git && \
|
||||
apk add vips-dev fftw-dev build-base --no-cache \
|
||||
--repository http://dl-3.alpinelinux.org/alpine/v3.10/community \
|
||||
--repository http://dl-3.alpinelinux.org/alpine/v3.10/main && \
|
||||
npm install --production && \
|
||||
rm -Rf $HOME/.npm $HOME/.npm $HOME/.config && \
|
||||
apk del .build-deps gcc g++ make libc6-compat python && \
|
||||
apk del build-base
|
||||
|
||||
COPY api $HOME/api
|
||||
COPY migrations $HOME/migrations
|
||||
COPY config $HOME/config
|
||||
COPY --from=build /app/public $HOME/public
|
||||
|
||||
EXPOSE 4030
|
||||
|
||||
CMD ["npm", "start"]
|
65
api/server_flaska.mjs
Normal file
65
api/server_flaska.mjs
Normal file
|
@ -0,0 +1,65 @@
|
|||
import path from 'path'
|
||||
import fs from 'fs/promises'
|
||||
import { Flaska, FileResponse, HttpError } from 'flaska'
|
||||
|
||||
export function run(http, port, core) {
|
||||
let localUtil = new core.sc.Util(import.meta.url)
|
||||
const staticRoot = localUtil.getPathFromRoot('../public')
|
||||
|
||||
const flaska = new Flaska({
|
||||
log: core.log,
|
||||
}, http)
|
||||
|
||||
flaska.before(function(ctx) {
|
||||
ctx.state.started = new Date().getTime()
|
||||
})
|
||||
|
||||
flaska.after(function(ctx) {
|
||||
let ended = new Date().getTime()
|
||||
var requestTime = ended - ctx.state.started
|
||||
|
||||
let status = ''
|
||||
let level = 'info'
|
||||
if (ctx.status >= 400) {
|
||||
status = ctx.status + ' '
|
||||
level = 'warn'
|
||||
}
|
||||
if (ctx.status >= 500) {
|
||||
level = 'error'
|
||||
}
|
||||
|
||||
ctx.log[level]({
|
||||
duration: requestTime,
|
||||
status: ctx.status,
|
||||
}, `<-- ${status}${ctx.method} ${ctx.url}`)
|
||||
})
|
||||
|
||||
flaska.get('/::file', function(ctx) {
|
||||
if (ctx.params.file.startsWith('api/')) {
|
||||
throw new HttpError(404, 'Not Found: ' + ctx.params.file, { status: 404, message: 'Not Found: ' + ctx.params.file })
|
||||
}
|
||||
|
||||
let file = path.resolve(path.join(staticRoot, ctx.params.file ? ctx.params.file : 'index.html'))
|
||||
|
||||
if (!file.startsWith(staticRoot)) {
|
||||
ctx.status = 404
|
||||
ctx.body = 'HTTP 404 Error'
|
||||
return
|
||||
}
|
||||
|
||||
return fs.stat(file).catch(function(err) {
|
||||
if (err.code === 'ENOENT') {
|
||||
file = path.resolve(path.join(staticRoot, 'index.html'))
|
||||
return fs.stat(file)
|
||||
}
|
||||
return Promise.reject(err)
|
||||
})
|
||||
.then(function(stat) {
|
||||
ctx.body = new FileResponse(file, stat)
|
||||
})
|
||||
})
|
||||
|
||||
return flaska.listenAsync(port).then(function() {
|
||||
core.log.info('Server is listening on port ' + port)
|
||||
})
|
||||
}
|
|
@ -1,6 +1,71 @@
|
|||
const parse = require('parse-link-header')
|
||||
const common = require('./common')
|
||||
|
||||
function hasRel(x) {
|
||||
return x && x.rel;
|
||||
}
|
||||
|
||||
function intoRels (acc, x) {
|
||||
function splitRel (rel) {
|
||||
acc[rel] = xtend(x, { rel: rel });
|
||||
}
|
||||
|
||||
x.rel.split(/\s+/).forEach(splitRel);
|
||||
|
||||
return acc;
|
||||
}
|
||||
|
||||
function createObjects (acc, p) {
|
||||
// rel="next" => 1: rel 2: next
|
||||
var m = p.match(/\s*(.+)\s*=\s*"?([^"]+)"?/)
|
||||
if (m) acc[m[1]] = m[2];
|
||||
return acc;
|
||||
}
|
||||
|
||||
var hasOwnProperty = Object.prototype.hasOwnProperty;
|
||||
|
||||
function extend() {
|
||||
var target = {}
|
||||
|
||||
for (var i = 0; i < arguments.length; i++) {
|
||||
var source = arguments[i]
|
||||
|
||||
for (var key in source) {
|
||||
if (hasOwnProperty.call(source, key)) {
|
||||
target[key] = source[key]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return target
|
||||
}
|
||||
|
||||
function parseLink(link) {
|
||||
try {
|
||||
var m = link.match(/<?([^>]*)>(.*)/)
|
||||
, linkUrl = m[1]
|
||||
, parts = m[2].split(';')
|
||||
, qry = new URL(linkUrl).searchParams;
|
||||
|
||||
parts.shift();
|
||||
|
||||
var info = parts
|
||||
.reduce(createObjects, {});
|
||||
|
||||
info = extend(qry, info);
|
||||
info.url = linkUrl;
|
||||
return info;
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function parse(linkHeader) {
|
||||
return linkHeader.split(/,\s*</)
|
||||
.map(parseLink)
|
||||
.filter(hasRel)
|
||||
.reduce(intoRels, {});
|
||||
}
|
||||
|
||||
exports.fetchPage = function(url) {
|
||||
return common.sendRequest({
|
||||
method: 'GET',
|
||||
|
|
|
@ -35,7 +35,6 @@
|
|||
"expiresIn": 604800
|
||||
}
|
||||
},
|
||||
"googleid": "1076074914074-3no1difo1jq3dfug3glfb25pn1t8idud.apps.googleusercontent.com",
|
||||
"sessionsecret": "this-is-session-secret-lol",
|
||||
"bcrypt": 5,
|
||||
"fileSize": 524288000,
|
||||
|
|
11
db.json
Normal file
11
db.json
Normal file
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"core": {
|
||||
"version": 1,
|
||||
"nfp_moe": {
|
||||
"active": "static",
|
||||
"latestInstalled": "",
|
||||
"updater": "",
|
||||
"versions": []
|
||||
}
|
||||
}
|
||||
}
|
10
dev.mjs
Normal file
10
dev.mjs
Normal file
|
@ -0,0 +1,10 @@
|
|||
import { ServiceCore } from 'service-core'
|
||||
import * as index from './index.mjs'
|
||||
|
||||
var core = new ServiceCore('nfp_moe', import.meta.url)
|
||||
core.setConfig({
|
||||
port: 4030,
|
||||
})
|
||||
core.init(index).then(function() {
|
||||
return core.run()
|
||||
})
|
|
@ -1,3 +1,10 @@
|
|||
import { run } from "./api/server_flaska.mjs"
|
||||
|
||||
export function start(http, port, ctx) {
|
||||
return run(http, port, ctx)
|
||||
}
|
||||
|
||||
/*
|
||||
import log from './api/log.mjs'
|
||||
|
||||
// Run the database script automatically.
|
||||
|
@ -17,3 +24,4 @@ setup().catch(async (error) => {
|
|||
).catch(error => {
|
||||
log.error(error, 'Unknown error starting server')
|
||||
})
|
||||
*/
|
|
@ -1,8 +0,0 @@
|
|||
{
|
||||
"ignore": ["app/**", "public/**"],
|
||||
"watch": [
|
||||
"api/**",
|
||||
"server*",
|
||||
"config/**"
|
||||
]
|
||||
}
|
72
package.json
72
package.json
|
@ -6,34 +6,34 @@
|
|||
"directories": {
|
||||
"test": "test"
|
||||
},
|
||||
"watch": {
|
||||
"test": {
|
||||
"patterns": [
|
||||
"{api,test}/*"
|
||||
],
|
||||
"extensions": "js,mjs",
|
||||
"quiet": false,
|
||||
"inherit": true
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"knex:rollback": "node scripts/rollback.mjs | bunyan",
|
||||
"lint": "eslint .",
|
||||
"start": "node --experimental-modules index.mjs",
|
||||
"build": "sass -s compressed app/app.scss public/assets/app.css && sass -s compressed app/admin.scss public/assets/admin.css && browserify -p tinyify --no-commondir -o public/assets/app.js app/index.js && browserify -p tinyify --no-commondir -o public/assets/admin.js app/admin.js",
|
||||
"build:check": "browserify -o public/assets/app.js app/index.js",
|
||||
"test": "echo \"Error: no test specified\" && exit 1",
|
||||
"watch:api": "nodemon --experimental-modules index.mjs | bunyan",
|
||||
"watch:app:admin": "watchify -g envify -d app/admin.js -o public/assets/admin.js",
|
||||
"watch:app:public": "watchify -g envify -d app/index.js -o public/assets/app.js",
|
||||
"build": "asbundle app/index.js public/assets/app.js && asbundle app/admin.js public/assets/admin.js",
|
||||
"build:watch": "npm-watch build",
|
||||
"dev:server": "node dev.mjs | bunyan",
|
||||
"dev:server:watch": "npm-watch dev:server",
|
||||
"watch:sass:public": "sass --watch app/app.scss public/assets/app.css",
|
||||
"watch:sass:admin": "sass --watch app/admin.scss public/assets/admin.css",
|
||||
"dev": "run-p watch:api watch:app:public watch:app:admin watch:sass:public watch:sass:admin",
|
||||
"prod": "npm run build && npm start",
|
||||
"docker": "docker run -it --rm --name nfp_moe -e knex__connection__host -e NODE_ENV -p 4030:4030 -v \"$PWD\":/usr/src/app -w /usr/src/app node",
|
||||
"docker:install": "npm run docker -- npm install",
|
||||
"docker:dev": "npm run docker -- npm run dev",
|
||||
"docker:prod": "npm run docker -- npm run prod"
|
||||
"prod": "npm run build && npm start"
|
||||
},
|
||||
"watch": {
|
||||
"dev:server": {
|
||||
"patterns": [
|
||||
"api/*"
|
||||
],
|
||||
"extensions": "js,mjs",
|
||||
"quiet": true,
|
||||
"inherit": true
|
||||
},
|
||||
"build": {
|
||||
"patterns": [
|
||||
"app/*"
|
||||
],
|
||||
"extensions": "js,mjs",
|
||||
"quiet": true,
|
||||
"inherit": true
|
||||
}
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
@ -46,38 +46,22 @@
|
|||
},
|
||||
"homepage": "https://github.com/nfp-projects/nfp_moe",
|
||||
"dependencies": {
|
||||
"@koa/cors": "^2.2.3",
|
||||
"bcrypt": "^3.0.8",
|
||||
"bookshelf": "^0.15.1",
|
||||
"bunyan-lite": "^1.0.1",
|
||||
"dot": "^1.1.2",
|
||||
"flaska": "^1.2.2",
|
||||
"format-link-header": "^2.1.0",
|
||||
"http-errors": "^1.7.2",
|
||||
"json-mask": "^0.3.8",
|
||||
"jsonwebtoken": "^8.4.0",
|
||||
"knex-core": "^0.19.5",
|
||||
"koa-bodyparser": "^4.2.1",
|
||||
"koa-jwt": "^3.5.1",
|
||||
"koa-lite": "^2.10.1",
|
||||
"koa-router": "^7.4.0",
|
||||
"koa-send": "^5.0.0",
|
||||
"lodash": "^4.17.11",
|
||||
"multer": "^1.4.1",
|
||||
"nconf-lite": "^1.0.1",
|
||||
"parse-torrent": "^7.0.1",
|
||||
"pg": "^7.8.0",
|
||||
"sharp": "^0.27.0",
|
||||
"pg": "^8.7.3",
|
||||
"striptags": "^3.1.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"browserify": "^16.2.3",
|
||||
"eslint": "^5.14.1",
|
||||
"mithril": "^2.0.3",
|
||||
"nodemon": "^1.18.10",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"parse-link-header": "^1.0.1",
|
||||
"asbundle": "^2.6.1",
|
||||
"mithril": "^2.0.4",
|
||||
"sass": "^1.17.0",
|
||||
"tinyify": "^2.5.1",
|
||||
"watchify": "^3.11.0"
|
||||
"service-core": "^3.0.0-beta.13"
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue