UNPKG

2.88 kBJavaScriptView Raw
1require('dotenv').config();
2require('q3-locale');
3
4const { get } = require('lodash');
5const walker = require('q3-core-walker');
6const { AccessControl } = require('q3-core-access');
7const {
8 handleUncaughtExceptions,
9} = require('q3-core-responder');
10
11const { middleware } = require('q3-core-composer');
12const { config } = require('q3-core-mailer');
13const path = require('path');
14const locale = require('q3-locale');
15const runner = require('./config');
16const app = require('./config/express');
17const mongoose = require('./config/mongoose');
18const models = require('./models');
19
20/**
21 * When testing, frameworks like supertest attach listeners.
22 */
23const connectToDB = (res, rej) => (err) => {
24 if (err) return rej(err);
25 app.use(handleUncaughtExceptions);
26 if (process.env.NODE_ENV !== 'test')
27 app.listen(process.env.PORT);
28
29 return res(null);
30};
31
32const registerLocale = ({ location }) => () =>
33 new Promise((resolve) => {
34 try {
35 locale(location);
36 } catch (e) {
37 // noop
38 }
39
40 resolve();
41 });
42
43/**
44 * See q3-core-mailer for more details.
45 * Essentially, it uses the location to register event handlers by the file system architecture.
46 */
47const registerChores = ({ location, chores }) => () =>
48 chores && location ? config(chores).walk(location) : null;
49
50/**
51 * Uses the package.json file to locate app index.
52 */
53const locate = () => {
54 try {
55 const root = process.cwd();
56 // eslint-disable-next-line
57 const r = require(path.resolve(root, './package.json'));
58 return path.parse(path.resolve(root, r.main)).dir;
59 } catch (e) {
60 return null;
61 }
62};
63
64const Q3 = {
65 protect(grants = []) {
66 AccessControl.init(grants);
67 return this;
68 },
69
70 config(args = {}) {
71 const location = locate();
72
73 if (!location && !args.location)
74 throw new Error('App requires a location');
75
76 Object.assign(
77 app.locals,
78 {
79 location,
80 },
81 args,
82 );
83
84 return this;
85 },
86
87 routes() {
88 const { location } = app.locals;
89 app.use(middleware(models.Users));
90 runner();
91
92 app.use(walker(__dirname));
93 app.use(walker(location));
94 return this;
95 },
96
97 model(name) {
98 if (!(name in mongoose.models))
99 throw new Error('Unknown model');
100
101 return get(mongoose.models, name);
102 },
103
104 setModel(name, Schema) {
105 return mongoose.model(name, Schema);
106 },
107
108 connect: async () =>
109 new Promise((resolve, reject) => {
110 mongoose.connect(
111 process.env.CONNECTION,
112 connectToDB(resolve, reject),
113 );
114 })
115 .then(registerLocale(app.locals))
116 .then(registerChores(app.locals))
117
118 .catch(() => {
119 process.exit(0);
120 }),
121};
122
123Q3.$app = app;
124Q3.$mongoose = mongoose;
125
126Object.assign(Q3, models);
127module.exports = Q3;