Skip to content

Commit 136304c

Browse files
committed
feat: breaking rewrite to support better structure
1 parent 544c00a commit 136304c

File tree

4 files changed

+602
-149
lines changed

4 files changed

+602
-149
lines changed

index.js

Lines changed: 38 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ const util = require('util');
55

66
const Cabin = require('cabin');
77
const I18N = require('@ladjs/i18n');
8+
const Passport = require('@ladjs/passport');
89
const Koa = require('koa');
910
const Redis = require('@ladjs/redis');
1011
const StoreIPAddress = require('@ladjs/store-ip-address');
@@ -32,39 +33,52 @@ const { boolean } = require('boolean');
3233
const RATE_LIMIT_EXCEEDED = `Rate limit exceeded, retry in %s.`;
3334

3435
class API {
35-
constructor(config, client) {
36+
// eslint-disable-next-line complexity
37+
constructor(config, Users) {
3638
this.config = {
3739
...sharedConfig('API'),
3840
rateLimitIgnoredGlobs: [],
3941
...config
4042
};
4143

42-
const cabin = new Cabin({
43-
logger: this.config.logger,
44-
...this.config.cabin
45-
});
46-
47-
// initialize redis
48-
this.client = client
49-
? client
50-
: new Redis(this.config.redis, cabin, this.config.redisMonitor);
51-
5244
// initialize the app
5345
const app = new Koa();
5446

55-
// allow middleware to access redis client
47+
// initialize cabin
48+
this.logger = _.isPlainObject(this.config.logger)
49+
? new Cabin(this.config.logger)
50+
: this.config.logger instanceof Cabin
51+
? this.config.logger
52+
: new Cabin({
53+
logger: this.config.logger ? this.config.logger : console
54+
});
55+
app.context.logger = this.logger;
56+
57+
// initialize redis
58+
this.client =
59+
this.config.redis === false
60+
? false
61+
: _.isPlainObject(this.config.redis)
62+
? new Redis(this.config.redis, this.logger, this.config.redisMonitor)
63+
: this.config.redis;
5664
app.context.client = this.client;
5765

58-
// listen for error and log events emitted by app
66+
// expose passport
67+
this.passport =
68+
this.config.passport === false
69+
? false
70+
: _.isPlainObject(this.config.passport)
71+
? new Passport(this.config.passport, Users)
72+
: this.config.passport;
73+
app.context.passport = this.passport;
74+
75+
// listen for errors emitted by app
5976
app.on('error', (err, ctx) => {
60-
const level = err.status && err.status < 500 ? 'warn' : 'error';
61-
if (ctx.logger) ctx.logger[level](err);
62-
else cabin[level](err);
77+
ctx.logger[err.status && err.status < 500 ? 'warn' : 'error'](err);
6378
});
64-
app.on('log', cabin.log);
6579

6680
// override koa's undocumented error handler
67-
app.context.onerror = errorHandler(false, cabin);
81+
app.context.onerror = errorHandler(false, this.logger);
6882

6983
// only trust proxy if enabled
7084
app.proxy = boolean(process.env.TRUST_PROXY);
@@ -89,7 +103,7 @@ class API {
89103
app.use(koaConnect(requestId()));
90104

91105
// use the cabin middleware (adds request-based logging and helpers)
92-
app.use(cabin.middleware);
106+
app.use(this.logger.middleware);
93107

94108
// allow before hooks to get setup
95109
if (_.isFunction(this.config.hookBeforeSetup))
@@ -99,7 +113,7 @@ class API {
99113
if (this.config.auth) app.use(auth(this.config.auth));
100114

101115
// rate limiting
102-
if (this.config.rateLimit) {
116+
if (this.client && this.config.rateLimit) {
103117
app.use((ctx, next) => {
104118
// check against ignored/whitelisted paths
105119
if (
@@ -113,7 +127,7 @@ class API {
113127
return ratelimit({
114128
...this.config.rateLimit,
115129
db: this.client,
116-
logger: cabin,
130+
logger: this.logger,
117131
errorMessage(exp) {
118132
const fn =
119133
typeof ctx.request.t === 'function' ? ctx.request.t : util.format;
@@ -131,7 +145,7 @@ class API {
131145
if (this.config.i18n) {
132146
const i18n = this.config.i18n.config
133147
? this.config.i18n
134-
: new I18N({ ...this.config.i18n, logger: cabin });
148+
: new I18N({ ...this.config.i18n, logger: this.logger });
135149
app.use(i18n.middleware);
136150
}
137151

@@ -151,12 +165,12 @@ class API {
151165
app.use(json());
152166

153167
// passport
154-
if (this.config.passport) app.use(this.config.passport.initialize());
168+
if (this.passport) app.use(this.passport.initialize());
155169

156170
// store the user's last ip address in the background
157171
if (this.config.storeIPAddress) {
158172
const storeIPAddress = new StoreIPAddress({
159-
logger: cabin,
173+
logger: this.logger,
160174
...this.config.storeIPAddress
161175
});
162176
app.use(storeIPAddress.middleware);

package.json

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
"@ladjs/i18n": "^7.2.6",
2525
"@ladjs/koa-simple-ratelimit": "^3.0.0",
2626
"@ladjs/redis": "^1.0.7",
27-
"@ladjs/shared-config": "^7.0.0",
27+
"@ladjs/shared-config": "^7.0.3",
2828
"@ladjs/store-ip-address": "^0.0.7",
2929
"boolean": "^3.2.0",
3030
"cabin": "^9.1.2",
@@ -49,20 +49,21 @@
4949
"response-time": "^2.3.2"
5050
},
5151
"devDependencies": {
52-
"@commitlint/cli": "^17.0.1",
53-
"@commitlint/config-conventional": "^17.0.0",
54-
"ava": "^4.2.0",
52+
"@commitlint/cli": "^17.0.2",
53+
"@commitlint/config-conventional": "^17.0.2",
54+
"@ladjs/passport": "^5.0.0",
55+
"ava": "^4.3.0",
5556
"codecov": "^3.8.3",
5657
"cross-env": "^7.0.3",
5758
"eslint": "^8.16.0",
5859
"eslint-config-xo-lass": "^1.0.6",
5960
"fixpack": "^4.0.0",
6061
"husky": "^8.0.1",
61-
"lint-staged": "12.4.3",
62-
"mongoose": "^6.3.4",
62+
"lint-staged": "13.0.0",
63+
"mongoose": "^6.3.5",
6364
"nyc": "^15.1.0",
6465
"remark-cli": "^10.0.1",
65-
"remark-preset-github": "^4.0.1",
66+
"remark-preset-github": "^4.0.2",
6667
"supertest": "^6.2.3",
6768
"xo": "^0.49.0"
6869
},

test/test.js

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1-
const test = require('ava');
2-
const request = require('supertest');
1+
const Passport = require('@ladjs/passport');
32
const Router = require('@koa/router');
3+
const request = require('supertest');
4+
const test = require('ava');
5+
46
const API = require('..');
57

68
test('allows custom routes', async (t) => {
@@ -18,3 +20,28 @@ test('allows custom routes', async (t) => {
1820
t.is(response.status, 200);
1921
t.is(response.body.ok, 'ok');
2022
});
23+
24+
test('with redis instance', (t) => {
25+
const api = new API();
26+
t.is(typeof api.client, 'object');
27+
t.is(typeof api.app.context.client, 'object');
28+
});
29+
30+
test('without redis instance', (t) => {
31+
const api = new API({ redis: false });
32+
t.is(api.client, false);
33+
t.is(api.app.context.client, false);
34+
});
35+
36+
test('with passport instance', (t) => {
37+
const passport = new Passport({});
38+
const api = new API({ passport });
39+
t.is(typeof api.passport, 'object');
40+
t.is(typeof api.app.context.passport, 'object');
41+
});
42+
43+
test('without passport instance', (t) => {
44+
const api = new API();
45+
t.is(api.passport, false);
46+
t.is(api.app.context.passport, false);
47+
});

0 commit comments

Comments
 (0)