From f35c195680674308878178789caf4e0c8f3525a0 Mon Sep 17 00:00:00 2001 From: Jonatan Nilsson Date: Tue, 5 Apr 2022 14:43:23 +0000 Subject: [PATCH] Development --- .eslintignore | 3 -- .eslintrc | 85 -------------------------------------- .npmrc | 1 + Dockerfile | 50 ---------------------- api/server_flaska.mjs | 65 +++++++++++++++++++++++++++++ app/api/pagination.js | 67 +++++++++++++++++++++++++++++- config/config.default.json | 1 - db.json | 11 +++++ dev.mjs | 10 +++++ index.mjs | 8 ++++ nodemon.json | 8 ---- package.json | 72 +++++++++++++------------------- 12 files changed, 189 insertions(+), 192 deletions(-) delete mode 100644 .eslintignore delete mode 100644 .eslintrc create mode 100644 .npmrc delete mode 100644 Dockerfile create mode 100644 api/server_flaska.mjs create mode 100644 db.json create mode 100644 dev.mjs delete mode 100644 nodemon.json diff --git a/.eslintignore b/.eslintignore deleted file mode 100644 index c80ff61..0000000 --- a/.eslintignore +++ /dev/null @@ -1,3 +0,0 @@ -.circleci -node_modules -public diff --git a/.eslintrc b/.eslintrc deleted file mode 100644 index 28b9854..0000000 --- a/.eslintrc +++ /dev/null @@ -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 - } -} diff --git a/.npmrc b/.npmrc new file mode 100644 index 0000000..9cf9495 --- /dev/null +++ b/.npmrc @@ -0,0 +1 @@ +package-lock=false \ No newline at end of file diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index 73fb5ed..0000000 --- a/Dockerfile +++ /dev/null @@ -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"] diff --git a/api/server_flaska.mjs b/api/server_flaska.mjs new file mode 100644 index 0000000..e5f4cc1 --- /dev/null +++ b/api/server_flaska.mjs @@ -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) + }) +} \ No newline at end of file diff --git a/app/api/pagination.js b/app/api/pagination.js index fe3dd7f..bca9076 100644 --- a/app/api/pagination.js +++ b/app/api/pagination.js @@ -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* { ).catch(error => { log.error(error, 'Unknown error starting server') }) +*/ \ No newline at end of file diff --git a/nodemon.json b/nodemon.json deleted file mode 100644 index d8e74ec..0000000 --- a/nodemon.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "ignore": ["app/**", "public/**"], - "watch": [ - "api/**", - "server*", - "config/**" - ] -} \ No newline at end of file diff --git a/package.json b/package.json index 496793a..1799ddc 100644 --- a/package.json +++ b/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" } }