Initial commit

This commit is contained in:
Linus Miller 2017-03-15 18:03:15 +01:00
commit 1f4e759225
23 changed files with 1105 additions and 0 deletions

3
.gitmodules vendored Normal file
View File

@ -0,0 +1,3 @@
[submodule "gulp"]
path = gulp
url = https://github.com/thebitmill/gulp

74
bin/initDb.js Executable file
View File

@ -0,0 +1,74 @@
#!/bin/env node
'use strict';
const pg = require('../server/db');
// pg.schema.dropTableIfExists('transactions')
pg.raw('DROP TABLE IF EXISTS companies CASCADE')
.then(() => pg.raw('DROP TABLE IF EXISTS years CASCADE'))
.then(() => pg.raw('DROP TABLE IF EXISTS accounts CASCADE'))
.then(() => pg.raw('DROP TABLE IF EXISTS account_types CASCADE'))
.then(() => pg.raw('DROP TABLE IF EXISTS tickets CASCADE'))
.then(() => pg.raw('DROP TABLE IF EXISTS ticket_types CASCADE'))
.then(() => pg.raw('DROP TABLE IF EXISTS transactions CASCADE'))
.then(() => pg.raw('DROP TABLE IF EXISTS initial_balance CASCADE'))
.then(() => pg.schema.createTable('companies', (table) => {
table.increments();
table.text('name').notNullable().unique();
table.text('organization_number').notNullable().unique();
}))
.then(() => pg.schema.createTable('years', (table) => {
table.increments();
table.integer('company_id').references('companies.id').notNullable().onUpdate('cascade');
table.integer('previous_year_id').references('id');
table.date('start_date').notNullable();
table.date('end_date').notNullable();
table.text('name');
}))
.then(() => pg.schema.createTable('account_types', (table) => {
table.increments();
table.text('name').notNullable().unique();
}))
.then(() => pg.schema.createTable('accounts', (table) => {
table.increments();
table.text('name').notNullable();
table.integer('number').notNullable();
table.integer('sru');
table.integer('account_type_id').notNullable().references('account_types.id').onUpdate('cascade');
}))
.then(() => pg.schema.createTable('initial_balance', (table) => {
table.increments();
table.integer('year_id').notNullable().references('years.id').onUpdate('cascade');
table.integer('account_id').notNullable().references('accounts.id').onUpdate('cascade');
table.decimal('amount').notNullable();
}))
.then(() => pg.schema.createTable('ticket_types', (table) => {
table.increments();
table.integer('number').notNullable();
table.text('name').notNullable().unique();
}))
.then(() => pg.schema.createTableIfNotExists('tickets', (table) => {
table.increments();
table.integer('type');
table.integer('ticket_type_id').references('ticket_types.id').onUpdate('cascade');
// table.integer('ticket_type_id').notNullable().references('ticket_types.id').onUpdate('cascade');
table.integer('number').notNullable();
table.date('date').notNullable();
table.text('title');
table.date('date_created').notNullable();
table.timestamp('uploaded_at').defaultsTo(pg.fn.now());
}))
.then(() => pg.schema.createTableIfNotExists('transactions', (table) => {
table.increments();
table.integer('account_id').notNullable().references('accounts.id').onUpdate('cascade');
table.decimal('amount', 14, 2).notNullable();
table.integer('ticket_id').notNullable().references('tickets.id').onUpdate('cascade');
}))
.then(() => pg('account_types').insert([{ name: 'Tillgång' }, { name: 'Skuld' }, { name: 'Intäkt' }, { name: 'Kostnad' }]))
.then(() => pg.destroy())
.catch((err) => {
console.log(err);
pg.destroy();
});

1
gulp Submodule

@ -0,0 +1 @@
Subproject commit 1daad4b4629c3ddef1f60710a0f7f8a67af9d714

1
gulpfile.js Symbolic link
View File

@ -0,0 +1 @@
gulp/gulpfile.js

30
package.json Normal file
View File

@ -0,0 +1,30 @@
{
"name": "vizwiz",
"version": "0.0.1",
"description": "",
"main": "server/server.js",
"scripts": {
"gulp": "gulp",
"gulp:production": "NODE_ENV=production gulp",
"gulp:development": "NODE_ENV=development gulp",
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": {
"type": "git",
"url": "git@gitlab.bitmill.co:lohfu/vizwiz.git"
},
"author": "Linus Miller <lohfu@lohfu.io> (https://lohfu.io/)",
"license": "MIT",
"dependencies": {
"body-parser": "^1.16.1",
"busboy": "^0.2.14",
"chalk": "^1.1.3",
"express": "^4.14.1",
"jsx-node": "^0.2.2",
"knex": "^0.12.7",
"midwest": "github:thebitmill/midwest",
"morgan": "^1.8.1",
"multer": "^1.3.0",
"split": "^1.0.0"
}
}

95
server/api/parse.js Normal file
View File

@ -0,0 +1,95 @@
'use strict';
function parseAccount(str) {
// str will look like: 'KONTO 1010 "Balanserade utgifter"'
const [, number, ...name] = str.split(/\s+/);
return {
number: parseInt(number, 10),
name: name.join(' '),
};
}
const accountType = {
T: 1,
S: 2,
I: 3,
K: 4,
};
function parseAccountType(str) {
const [, number, type] = str.split(/\s+/);
return {
number: parseInt(number, 10),
type: accountType[type],
};
}
function parseDate(str) {
const [, year, month, day] = /(\d\d\d\d)(\d\d)(\d\d)/.exec(str);
return new Date(`${year}-${month}-${day}T00:00:00.000Z`);
}
function parseTransaction(str) {
// str looks like: ' #TRANS 6310 {} 1541.00 20150824 '
const [,, account,, amount, date] = str.split(/\s+/);
return {
account: parseInt(account, 10),
amount: parseFloat(amount),
date: parseDate(date),
};
}
function parseTicket(str) {
const arr = str.split('\r\n');
// arr[0] will look like: 'VER 5101 147 20150917 "Binero" 20160224'
const [, type, number, date, ...rest] = arr[0].split(/\s+/);
const dateCreated = rest.pop();
const title = rest.join(' ');
console.log(type);
const transactions = arr.slice(2, -2).map(parseTransaction);
return {
type: parseInt(type, 10),
number: parseInt(number, 10),
date: parseDate(date),
dateCreated: parseDate(date),
title,
transactions,
}
}
// console.log(string.split('\n#').length)
module.exports = function parse(string) {
const accounts = [];
const tickets = [];
string.split(/\n#/g).forEach((str, i) => {
if (str.startsWith('KONTO')) {
accounts.push(parseAccount(str));
} else if (str.startsWith('KTYP')) {
const { number, type } = parseAccountType(str);
// const string = fs.readFileSync('./bitmill2015.se', { encoding: 'UTF8' });
const account = accounts.find((account) => account.number === number);
account.type = type;
} else if (str.startsWith('VER')) {
tickets.push(parseTicket(str));
}
});
return {
accounts,
tickets,
};
};
// console.log(tickets);
// process.exit(0);

137
server/api/parseLine.js Normal file
View File

@ -0,0 +1,137 @@
'use strict';
function parseAccount(str) {
// str will look like: 'KONTO 1010 "Balanserade utgifter"'
const [, number, ...name] = str.split(/\s+/);
return {
number: parseInt(number, 10),
name: name.join(' ').slice(1, -1),
};
}
const accountType = {
T: 1,
S: 2,
I: 3,
K: 4,
};
function parseCompanyName(str) {
const [, name] = str.split(/\s+/);
return name.slice(1, -1);
}
// str should be `ORGNR "556930-1673"`
function parseOrganizationNumber(str) {
const [, number] = str.split(/\s+/);
return number.slice(1, -1);
}
function parseYearDates(str) {
const [, current, start, end] = str.split(/\s+/);
return {
start: parseDate(start),
end: parseDate(end),
current: current === '0',
};
}
function parseAccountType(str) {
const [, number, type] = str.split(/\s+/);
return {
number: parseInt(number, 10),
type: accountType[type],
};
}
function parseDate(str) {
const [, year, month, day] = /(\d\d\d\d)(\d\d)(\d\d)/.exec(str);
return new Date(`${year}-${month}-${day}T00:00:00.000Z`);
}
function parseSRU(str) {
const [, number, sru] = str.split(/\s+/);
return {
number: parseInt(number, 10),
sru: parseInt(sru, 10),
};
}
function parseTransaction(str) {
// str looks like: ' #TRANS 6310 {} 1541.00 20150824 '
const [, accountNumber,, amount] = str.split(/\s+/);
return {
accountNumber: parseInt(accountNumber, 10),
amount: parseFloat(amount),
};
}
function parseTicket(str) {
const [, type, number, date, ...rest] = str.split(/\s+/);
const dateCreated = rest.pop();
const title = rest.join(' ');
return {
type: parseInt(type, 10),
number: parseInt(number, 10),
date: parseDate(date),
date_created: parseDate(dateCreated),
title: title.slice(1, -1),
};
}
module.exports = {
parseAccountType,
parseAccount,
parseCompanyName,
parseOrganizationNumber,
parseSRU,
parseTransaction,
parseTicket,
parseYearDates,
};
// console.log(string.split('\n#').length)
// module.exports = function parseLine(line) {
// line = line.slice(1);
// if (line.startsWith('KONTO')) {
// const account = parseAccount(line);
// } else if (line.startWith('KTYP') {
// const accountType = parseAccountType(line);
// }
// const accounts = [];
// const tickets = [];
// string.split(/\n#/g).forEach((str, i) => {
// if (str.startsWith('KONTO')) {
// accounts.push(parseAccount(str));
// } else if (str.startsWith('KTYP')) {
// const { number, type } = parseAccountType(str);
// // const string = fs.readFileSync('./bitmill2015.se', { encoding: 'UTF8' });
// const account = accounts.find((account) => account.number === number);
// account.type = type;
// } else if (str.startsWith('VER')) {
// tickets.push(parseTicket(str));
// }
// });
// return {
// accounts,
// tickets,
// };
//};
// console.log(tickets);
// process.exit(0);

7
server/config/dir.js Normal file
View File

@ -0,0 +1,7 @@
'use strict';
const p = require('path');
module.exports = {
static: p.join(PWD, 'public'),
};

View File

@ -0,0 +1,41 @@
'use strict';
const _ = require('lodash');
// const errorTemplate = require('../templates/error.jsx');
const errorTemplate = () => '<h1>Error</h1>';
const defaults = {
post: (req, res, next) => {
res.template = errorTemplate;
next();
},
mystify: {
properties: ['errors', 'message', 'name', 'status', 'statusText'],
},
log: {
// if database = true there has to be a mongoose model name ErrorModel
ignore: [],
},
};
module.exports = _.merge(defaults, {
development: {
log: {
console: true,
},
},
testing: {
log: {
console: false,
},
},
production: {
log: {
console: false,
},
},
}[ENV]);

4
server/config/globals.js Normal file
View File

@ -0,0 +1,4 @@
'use strict';
// global.LOGIN_USER = 'linus.miller@thecodebureau.com'
// global.LOGIN_USER = 'zarac@zarac.se'

View File

@ -0,0 +1,78 @@
'use strict';
const site = require('./site');
module.exports = {
invite: {
from: `${site.title} Robot <${site.emails.robot}>`,
subject: `You have been invited to ${site.title}`,
},
timeouts: {
// 1 day
changePassword: 24 * 60 * 60 * 1000,
// verify email
verifyEmail: 7 * 24 * 60 * 60 * 1000,
},
paths: {
register: '/register',
login: '/login',
forgotPassword: '/forgot-password',
updatePassword: '/change-password',
},
redirects: {
login: '/admin',
logout: '/',
register: '/admin',
},
remember: {
// if expires is defined, it will be used. otherwise maxage
expires: new Date('2038-01-19T03:14:07.000Z'),
// expires: Date.now() - 1,
maxAge: 30 * 24 * 60 * 60 * 1000,
},
messages: {
login: {
notLocal: 'Account requires external login.',
wrongPassword: 'Wrong password.',
noLocalUser: 'No user registered with that email.',
noExternalUser: 'The account is not connected to this website.',
externalLoginFailed: 'External login failed.',
unverified: 'This account has not been verified.',
banned: 'User is banned.',
blocked: 'User is blocked due to too many login attempts.',
},
register: {
missingProperties: 'Oh no missing stuff',
notAuthorized: 'The email is not authorized to create an account.',
duplicateEmail: 'The email has already been registered.',
},
},
passport: {
local: {
usernameField: 'email',
},
scope: ['email'],
//providers: {
// facebook: {
// clientID: 'change-this-fool',
// clientSecret: 'change-this-fool',
// callbackURL: p.join(config.site.domain, '/auth/facebook/callback'),
// passReqToCallback: true
// },
},
// needs to be even
tokenLength: 64,
// needs to be even
saltLength: 16,
};

10
server/config/port.js Normal file
View File

@ -0,0 +1,10 @@
'use strict';
const basePort = 3070;
module.exports = {
development: basePort,
testing: basePort + 1,
staging: basePort + 2,
production: basePort + 3,
}[ENV];

24
server/config/postgres.js Normal file
View File

@ -0,0 +1,24 @@
'use strict';
const defaults = {
user: 'vizwiz', //env var: PGUSER
database: 'vizwiz', //env var: PGDATABASE
password: 'secret', //env var: PGPASSWORD
host: 'localhost', // Server hosting the postgres database
port: 5432, //env var: PGPORT
max: 10, // max number of clients in the pool
idleTimeoutMillis: 30000, // how long a client is allowed to remain idle before being closed
};
// {
// user: 'newseri_supreme', // env var: PGUSER
// database: 'newseri', // env var: PGDATABASE
// password: 'oh-look-it-is-raining-news', // env var: PGPASSWORD
// // host: '192.168.1.11', // Server hosting the postgres database
// host: 'hq.bitmill.co', // Server hosting the postgres database
// // port: 5432, // env var: PGPORT
// port: 6543, // env var: PGPORT
// max: 10, // max number of clients in the pool
// idleTimeoutMillis: 30000, // how long a client is allowed to remain idle before being closed
// };
module.exports = defaults;

38
server/config/session.js Normal file
View File

@ -0,0 +1,38 @@
'use strict';
const chalk = require('chalk');
const session = require('express-session');
let redisStore;
const config = {
secret: 'ohohohogogogoONMYTOETOEthisisacompletelyrandomgeneratedstring.thisisonlyacoincidence.',
resave: false,
saveUninitialized: true,
};
const redisConfig = {
host: 'localhost',
port: 6379,
};
if (ENV === 'production') {
const RedisStore = require('connect-redis')(require('express-session'));
redisStore = new RedisStore(redisConfig);
redisStore.on('connect', () => {
console.info(`[${chalk.cyan('INIT')}] Redis connected succcessfully`);
});
redisStore.on('disconnect', () => {
throw new Error('Unable to connect to redis. Has it been started?');
});
config.store = redisStore;
} else {
config.store = new session.MemoryStore();
}
module.exports = config;

34
server/config/shim.js Normal file
View File

@ -0,0 +1,34 @@
'use strict';
module.exports = {
'https://cdnjs.cloudflare.com/ajax/libs/es5-shim/4.5.9/es5-shim.min.js': [
'chrome <= 12',
'firefox <= 20',
'ie <= 9',
'opera <= 12',
'safari <= 5',
],
'https://cdnjs.cloudflare.com/ajax/libs/es6-shim/0.35.1/es6-shim.min.js': [
// 'https://cdnjs.cloudflare.com/ajax/libs/core-js/2.4.1/core.min.js': [
// 'https://cdnjs.cloudflare.com/ajax/libs/babel-polyfill/6.16.0/polyfill.js': [
'chrome <= 51',
'edge <= 13',
'firefox <= 44',
'ie <= 11',
'safari <= 9',
],
'https://unpkg.com/es7-shim@latest/dist/es7-shim.min.js': [
'chrome <= 50',
'edge <= 14',
'firefox <= 46',
'ie <= 11',
'safari <= 10',
],
'https://cdnjs.cloudflare.com/ajax/libs/fetch/1.0.0/fetch.min.js': [
'chrome <= 41',
'edge <= 13',
'firefox <= 38',
'ie <= 11',
'safari <= 9',
],
};

51
server/config/site.js Normal file
View File

@ -0,0 +1,51 @@
'use strict';
const _ = require('lodash');
const domain = 'bitmill.co';
const defaults = {
domain,
title: 'Vizwiz',
name: 'vizwiz',
protocol: 'http',
get host() {
return this.port ? `${this.hostname}:${this.port}` : this.hostname;
},
get url() {
return `${this.protocol}://${this.host}/`;
},
emails: {
robot: 'no-reply@thecodebureau.com',
info: 'info@thecodebureau.com',
webmaster: 'webmaster@thecodebureau.com',
order: 'info@thecodebureau.com',
},
};
module.exports = _.merge(defaults, {
development: {
hostname: 'localhost',
port: process.env.EXTERNAL_PORT || process.env.PORT || require('./port'),
},
testing: {
hostname: 'localhost',
port: process.env.PORT || require('./port'),
},
staging: {
hostname: `vizwiz.staging.${domain}`,
},
production: {
hostname: `vizwiz.${domain}`,
protocol: 'https',
emails: {
robot: `no-reply@${domain}`,
info: `info@${domain}`,
webmaster: `webmaster@${domain}`,
order: `order@${domain}`,
},
},
}[ENV]);

15
server/config/smtp.js Normal file
View File

@ -0,0 +1,15 @@
'use strict';
const _ = require('lodash');
const defaults = {
auth: {
user: 'SMTP_Injection',
// dev key
pass: '2eec390c5b3f5d593c9f152179bf51e90b073784',
},
host: 'smtp.sparkpostmail.com',
port: 587,
};
module.exports = _.merge(defaults, {}[ENV]);

16
server/db.js Normal file
View File

@ -0,0 +1,16 @@
'use strict';
// const factory = require('midwest/util/db');
const conf = require('./config/postgres');
// module.exports = factory(conf);
//
const knex = require('knex');
const pg = knex({
client: 'pg',
connection: conf,
});
module.exports = pg;

30
server/middleware.js Normal file
View File

@ -0,0 +1,30 @@
'use strict';
const db = require('./db');
module.exports = {
result(req, res, next) {
db.select().sum('transactions.amount as sum').from('transactions')
.innerJoin('accounts', 'transactions.account_id', 'accounts.id')
.innerJoin('tickets', 'transactions.ticket_id', 'tickets.id')
.whereBetween('tickets.date', ['2015-03-01', '2015-03-31]'])
.andWhereBetween('accounts.account_type_id', [3, 4])
.then((res) => {
console.log(res);
// console.log(res);
// const result = res.reduce((result, t) => {
// console.log(t.amount);
// console.log(parseFloat(t.amount, 2));
// result += parseFloat(t.amount, 2);
// return result;
// }, 0);
// console.log(result);
});
// db.schema.raw(`SELECT * FROM transactions INNER JOIN accounts ON accounts.id = transactions.account_id
// WHERE accounts.account_type_id = 3;`, (result) => {
// console.log(result);
// })
}
};

26
server/render.js Normal file
View File

@ -0,0 +1,26 @@
const { h } = require('jsx-node');
module.exports = function (Component, Master) {
const locals = Object.assign({ query: this.req.query }, this.app.locals, this.locals);
if (typeof Master === 'function') {
if (typeof Component === 'function') {
return this.send(
h(Master, locals,
h(Component, locals)
)
);
}
Component = Master;
}
if (typeof Component !== 'function') {
throw new Error('Not a Component');
} else if (Component.prototype && Component.prototype.render) {
const i = new Component(locals);
this.send(i.render(i.props, i.state));
} else {
this.send(Component(locals));
}
};

251
server/routers/api.js Normal file
View File

@ -0,0 +1,251 @@
'use strict';
const _ = require('lodash');
const router = new (require('express').Router)();
const Busboy = require('busboy');
const split = require('split');
const db = require('../db');
const parse = require('../api/parse');
const {
parseAccount,
parseAccountType,
parseCompanyName,
parseSRU,
parseTransaction,
parseTicket,
parseYearDates,
parseOrganizationNumber,
} = require('../api/parseLine');
const queries = {
saveAccount(account) {
db('accounts').insert(h)
}
}
const handlers = require('../handlers');
router.get('/parse', (req, res) => res.send('<h1>Parse</h1>'));
router.post('/sie', (req, res) => {
const busboy = new Busboy({ headers: req.headers });
busboy.on('file', function(fieldname, file, filename, encoding, mimetype) {
let accounts = [];
let ticketId = null;
let companyDone = false;
let yearDone = false;
let accountsDone = false;
let accountIds = [];
let details = {};
const transactions = [];
let currentYearDates = [];
let currentYear;
let previousYearDates = [];
let company;
// let saving = false;
const splitStream = file.pipe(split())
.on('data', async (line) => {
line = line.trim();
if (line[0] !== '#') return;
const lineType = line.slice(1, line.indexOf(' '));
console.log(lineType);
if (!companyDone) {
switch (lineType) {
case 'ORGNR': {
const organizationNumber = parseOrganizationNumber(line);
splitStream.pause();
company = await handlers.getCompanyByOrganizationNumber(organizationNumber) || { organization_number: organizationNumber };
splitStream.resume();
return;
}
case 'FNAMN': {
const companyName = parseCompanyName(line);
if (!company.name || company.name !== companyName) {
company.name = companyName;
}
return;
}
case 'RAR': {
if (!company.id) {
splitStream.pause();
company = await handlers.createCompany(company);
companyDone = true;
splitStream.resume();
}
}
}
}
if (companyDone && !yearDone) {
switch (lineType) {
case 'RAR': {
const dates = parseYearDates(line);
if (dates.current) {
currentYearDates = _.omit(dates, 'current');
} else {
previousYearDates = _.omit(dates, 'current');
}
return;
}
case 'KONTO': {
splitStream.pause();
const previousYear = await handlers.getYearByCompanyIdAndDates(company.id, previousYearDates);
// currentYear = await handlers.getYearByCompanyIdAndDates(company.id, currentYearDates) || Object.assign({ company_id: company.id }, _.mapKeys(currentYearDates, (value, key) => `${key}_date`);
currentYear = Object.assign({ company_id: company.id }, _.mapKeys(currentYearDates, (value, key) => `${key}_date`));
if (previousYear) currentYear.previous_year_id = previousYear.id;
// TODO remove all entries for year
currentYear = await handlers.createYear(currentYear);
yearDone = true;
splitStream.resume();
}
}
}
if (companyDone && yearDone && !accountsDone) {
console.log(lineType);
console.log(line);
switch (lineType) {
case 'KONTO':
const account = parseAccount(line);
if (!account || !account.number) console.log(account);
accounts.push(account);
return;
case 'KTYP': {
const { number, type } = parseAccountType(line);
const account = accounts.find((account) => account.number === number) || { number };
if (account) account.account_type_id = type;
return;
}
case 'SRU': {
const { number, sru } = parseSRU(line);
const account = accounts.find((account) => account.number === number) || { number };
// if (account)
account.sru = sru;
return;
}
case 'VER':
console.log('shhould be saviung accounts');
splitStream.pause();
// console.log(accounts);
accounts.forEach((account) => {
if (!account.account_type_id) console.log(account);
});
await db('accounts').returning(['id', 'number']).insert(accounts).then((res) => {
accounts = res;
}).catch((err) => {
console.log(err);
});
accountsDone = true;
splitStream.resume();
}
}
return;
if (companyDone && yearDone && accountsDone) {
switch (lineType) {
case 'VER': {
splitStream.pause();
const ticket = parseTicket(line);
await db('tickets').returning('id').insert(_.omit(ticket, 'transactions')).then((res) => {
ticketId = res[0];
}).catch((err) => console.log(err));
splitStream.resume();
return;
}
case 'TRANS': {
const transaction = parseTransaction(line);
transaction.ticket_id = ticketId;
const account = accounts.find((account) => account.number === transaction.accountNumber);
delete transaction.accountNumber;
transaction.account_id = account.id;
transactions.push(transaction);
return;
}
}
}
})
.on('end', () => {
db('transactions').insert(transactions)
.catch((err) => console.log(err));
});
});
busboy.on('field', function(fieldname, val, fieldnameTruncated, valTruncated, encoding, mimetype) {
console.log('Field [' + fieldname + ']: value: ' + inspect(val));
});
busboy.on('finish', function() {
console.log('Done parsing form!');
// res.writeHead(303, { Connection: 'close', Location: '/' });
// res.end();
res.sendStatus(204);
});
req.pipe(busboy);
// tickets.forEach(({ type, number, date, dateCreated, title, transactions }) => {
// db.query(`INSERT INTO tickets (number, type, title, date, date_created) VALUES ('${number}', '${type}', '${title}', '2016-11-01', '2016-11-01') RETURNING id`, (err, result) => {
// if (err) throw err;
// console.log(result.rows[0]);
// const ticketId = result.rows[0].id;
// transactions.forEach(({ account, amount }) => {
// db.query(`INSERT INTO transactions (account, amount, ticket) VALUES ('${account}', '${amount}', '${ticketId}')`, (err, result) => {
// console.log(result);
// });
// });
// });
// })
});
module.exports = router;

7
server/routers/index.js Normal file
View File

@ -0,0 +1,7 @@
'use strict';
const router = new (require('express').Router)();
router.get('/', (req, res) => res.send('<h1>Hello</h1>'));
module.exports = router;

132
server/server.js Normal file
View File

@ -0,0 +1,132 @@
'use strict';
/*
* The main file that sets up the Express instance and node
*
* @module server/server
* @type {Express instance}
*/
// set up some globals (these are also set in Epiphany if not already set)
global.ENV = process.env.NODE_ENV || 'development';
global.PWD = process.env.NODE_PWD || process.cwd();
// modules > native
const p = require('path');
// output filename in console log and colour console.dir
if (ENV === 'development') {
require('midwest/util/console');
// needed so symlinked modules get access to main projects node_modules/
require('app-module-path').addPath(p.join(PWD, 'node_modules'));
}
// make node understand `*.jsx` files
require('jsx-node').install();
// modules > 3rd party
const chalk = require('chalk');
const express = require('express');
// const passport = require('passport');
const requireDir = require('require-dir');
// modules > express middlewares
const bodyParser = require('body-parser');
// const session = require('express-session');
// const cookieParser = require('cookie-parser');
// modules > midwest
const colorizeStack = require('midwest/util/colorize-stack');
const config = requireDir('./config', { camelcase: true });
// make error output stack pretty
process.on('uncaughtException', (err) => {
console.error(chalk.red('UNCAUGHT EXCEPTION'));
if (err.stack) {
console.error(colorizeStack(err.stack));
} else {
console.error(err);
}
process.exit(1);
});
const prewares = [
express.static(config.dir.static, ENV === 'production' ? { maxAge: '1 year' } : null),
bodyParser.json(),
bodyParser.urlencoded({ extended: true }),
// cookieParser(),
// session(config.session),
// passport.initialize(),
// passport.session(),
];
if (ENV === 'development') {
// only log requests to console in development mode
prewares.unshift(require('morgan')('dev'));
// automatically login global.LOGIN_USER
// prewares.push(require('midwest-module-membership/passport/automatic-login'));
}
const postwares = [
require('midwest/middleware/ensure-found'),
// transform and log error
require('midwest/factories/error-handler')(config.errorHandler),
// respond
require('midwest/middleware/responder'),
];
const server = express();
// get IP & whatnot from nginx proxy
server.set('trust proxy', true);
Object.assign(server.locals, {
site: require('./config/site'),
});
// override default response render method for
server.response.render = require('./render.js');
try {
server.locals.js = require(p.join(PWD, 'public/js.json'));
} catch (e) {}
try {
server.locals.css = require(p.join(PWD, 'public/css.json'));
} catch (e) {}
// load all prewares
server.use(...prewares);
// routes
server.use(require('./routers/index'));
server.use('/api', require('./routers/api'));
// routes > authentication
// server.use('/auth', require('midwest-module-membership/passport/router'));
// routes > api > membership
// server.use('/api/roles', require('midwest-module-membership/services/roles/router'));
// server.use('/api/permissions', require('midwest-module-membership/services/permissions/router'));
// server.use('/api/invites', require('midwest-module-membership/services/invites/router'));
// server.use('/api/users', require('midwest-module-membership/services/users/router'));
// load all postwares
server.use(...postwares);
// mpromise (built in mongoose promise library) is deprecated,
// tell mongoose to use native Promises instead
// Only start Express server when it is the main module (ie not required by test)
if (require.main === module) {
server.http = server.listen(config.port, () => {
console.info(`[${chalk.cyan('INIT')}] HTTP Server listening on port ${chalk.magenta(config.port)} (${chalk.yellow(ENV)})`);
});
}
const mw = require('./middleware');
mw.result();
module.exports = server;