@ladjs/api 8.0.0 → 9.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.js +49 -25
- package/package.json +14 -12
package/index.js
CHANGED
|
@@ -5,6 +5,7 @@ const util = require('util');
|
|
|
5
5
|
|
|
6
6
|
const Cabin = require('cabin');
|
|
7
7
|
const I18N = require('@ladjs/i18n');
|
|
8
|
+
const Passport = require('@ladjs/passport');
|
|
8
9
|
const Koa = require('koa');
|
|
9
10
|
const Redis = require('@ladjs/redis');
|
|
10
11
|
const StoreIPAddress = require('@ladjs/store-ip-address');
|
|
@@ -19,49 +20,65 @@ const etag = require('koa-etag');
|
|
|
19
20
|
const json = require('koa-json');
|
|
20
21
|
const koa404Handler = require('koa-404-handler');
|
|
21
22
|
const koaConnect = require('koa-connect');
|
|
23
|
+
const ms = require('ms');
|
|
22
24
|
const multimatch = require('multimatch');
|
|
25
|
+
const ratelimit = require('@ladjs/koa-simple-ratelimit');
|
|
23
26
|
const removeTrailingSlashes = require('koa-no-trailing-slash');
|
|
24
27
|
const requestId = require('express-request-id');
|
|
25
28
|
const requestReceived = require('request-received');
|
|
26
29
|
const responseTime = require('response-time');
|
|
27
30
|
const sharedConfig = require('@ladjs/shared-config');
|
|
28
31
|
const { boolean } = require('boolean');
|
|
29
|
-
|
|
32
|
+
|
|
33
|
+
const RATE_LIMIT_EXCEEDED = `Rate limit exceeded, retry in %s.`;
|
|
30
34
|
|
|
31
35
|
class API {
|
|
32
|
-
|
|
36
|
+
// eslint-disable-next-line complexity
|
|
37
|
+
constructor(config, Users) {
|
|
33
38
|
this.config = {
|
|
34
39
|
...sharedConfig('API'),
|
|
35
40
|
rateLimitIgnoredGlobs: [],
|
|
36
41
|
...config
|
|
37
42
|
};
|
|
38
43
|
|
|
39
|
-
const cabin = new Cabin({
|
|
40
|
-
logger: this.config.logger,
|
|
41
|
-
...this.config.cabin
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
// initialize redis
|
|
45
|
-
this.client = client
|
|
46
|
-
? client
|
|
47
|
-
: new Redis(this.config.redis, cabin, this.config.redisMonitor);
|
|
48
|
-
|
|
49
44
|
// initialize the app
|
|
50
45
|
const app = new Koa();
|
|
51
46
|
|
|
52
|
-
//
|
|
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;
|
|
53
64
|
app.context.client = this.client;
|
|
54
65
|
|
|
55
|
-
//
|
|
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
|
|
56
76
|
app.on('error', (err, ctx) => {
|
|
57
|
-
|
|
58
|
-
if (ctx.logger) ctx.logger[level](err);
|
|
59
|
-
else cabin[level](err);
|
|
77
|
+
ctx.logger[err.status && err.status < 500 ? 'warn' : 'error'](err);
|
|
60
78
|
});
|
|
61
|
-
app.on('log', cabin.log);
|
|
62
79
|
|
|
63
80
|
// override koa's undocumented error handler
|
|
64
|
-
app.context.onerror = errorHandler(false,
|
|
81
|
+
app.context.onerror = errorHandler(false, this.logger);
|
|
65
82
|
|
|
66
83
|
// only trust proxy if enabled
|
|
67
84
|
app.proxy = boolean(process.env.TRUST_PROXY);
|
|
@@ -86,7 +103,7 @@ class API {
|
|
|
86
103
|
app.use(koaConnect(requestId()));
|
|
87
104
|
|
|
88
105
|
// use the cabin middleware (adds request-based logging and helpers)
|
|
89
|
-
app.use(
|
|
106
|
+
app.use(this.logger.middleware);
|
|
90
107
|
|
|
91
108
|
// allow before hooks to get setup
|
|
92
109
|
if (_.isFunction(this.config.hookBeforeSetup))
|
|
@@ -96,7 +113,7 @@ class API {
|
|
|
96
113
|
if (this.config.auth) app.use(auth(this.config.auth));
|
|
97
114
|
|
|
98
115
|
// rate limiting
|
|
99
|
-
if (this.config.rateLimit) {
|
|
116
|
+
if (this.client && this.config.rateLimit) {
|
|
100
117
|
app.use((ctx, next) => {
|
|
101
118
|
// check against ignored/whitelisted paths
|
|
102
119
|
if (
|
|
@@ -109,7 +126,14 @@ class API {
|
|
|
109
126
|
|
|
110
127
|
return ratelimit({
|
|
111
128
|
...this.config.rateLimit,
|
|
112
|
-
db: this.client
|
|
129
|
+
db: this.client,
|
|
130
|
+
logger: this.logger,
|
|
131
|
+
errorMessage(exp) {
|
|
132
|
+
const fn =
|
|
133
|
+
typeof ctx.request.t === 'function' ? ctx.request.t : util.format;
|
|
134
|
+
// NOTE: ms does not support i18n localization
|
|
135
|
+
return fn(RATE_LIMIT_EXCEEDED, ms(exp, { long: true }));
|
|
136
|
+
}
|
|
113
137
|
})(ctx, next);
|
|
114
138
|
});
|
|
115
139
|
}
|
|
@@ -121,7 +145,7 @@ class API {
|
|
|
121
145
|
if (this.config.i18n) {
|
|
122
146
|
const i18n = this.config.i18n.config
|
|
123
147
|
? this.config.i18n
|
|
124
|
-
: new I18N({ ...this.config.i18n, logger:
|
|
148
|
+
: new I18N({ ...this.config.i18n, logger: this.logger });
|
|
125
149
|
app.use(i18n.middleware);
|
|
126
150
|
}
|
|
127
151
|
|
|
@@ -141,12 +165,12 @@ class API {
|
|
|
141
165
|
app.use(json());
|
|
142
166
|
|
|
143
167
|
// passport
|
|
144
|
-
if (this.
|
|
168
|
+
if (this.passport) app.use(this.passport.initialize());
|
|
145
169
|
|
|
146
170
|
// store the user's last ip address in the background
|
|
147
171
|
if (this.config.storeIPAddress) {
|
|
148
172
|
const storeIPAddress = new StoreIPAddress({
|
|
149
|
-
logger:
|
|
173
|
+
logger: this.logger,
|
|
150
174
|
...this.config.storeIPAddress
|
|
151
175
|
});
|
|
152
176
|
app.use(storeIPAddress.middleware);
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ladjs/api",
|
|
3
3
|
"description": "API server for Lad",
|
|
4
|
-
"version": "
|
|
4
|
+
"version": "9.0.0",
|
|
5
5
|
"author": "Nick Baugh <niftylettuce@gmail.com> (http://niftylettuce.com/)",
|
|
6
6
|
"ava": {
|
|
7
7
|
"failFast": true,
|
|
@@ -22,8 +22,9 @@
|
|
|
22
22
|
"dependencies": {
|
|
23
23
|
"@koa/router": "^10.1.1",
|
|
24
24
|
"@ladjs/i18n": "^7.2.6",
|
|
25
|
+
"@ladjs/koa-simple-ratelimit": "^3.0.0",
|
|
25
26
|
"@ladjs/redis": "^1.0.7",
|
|
26
|
-
"@ladjs/shared-config": "^
|
|
27
|
+
"@ladjs/shared-config": "^7.0.3",
|
|
27
28
|
"@ladjs/store-ip-address": "^0.0.7",
|
|
28
29
|
"boolean": "^3.2.0",
|
|
29
30
|
"cabin": "^9.1.2",
|
|
@@ -41,29 +42,30 @@
|
|
|
41
42
|
"koa-etag": "^4.0.0",
|
|
42
43
|
"koa-json": "^2.0.2",
|
|
43
44
|
"koa-no-trailing-slash": "^2.1.0",
|
|
44
|
-
"koa-simple-ratelimit": "^5.1.1",
|
|
45
45
|
"lodash": "^4.17.21",
|
|
46
|
+
"ms": "^2.1.3",
|
|
46
47
|
"multimatch": "5",
|
|
47
48
|
"request-received": "^0.0.3",
|
|
48
49
|
"response-time": "^2.3.2"
|
|
49
50
|
},
|
|
50
51
|
"devDependencies": {
|
|
51
|
-
"@commitlint/cli": "^
|
|
52
|
-
"@commitlint/config-conventional": "^
|
|
53
|
-
"
|
|
52
|
+
"@commitlint/cli": "^17.0.2",
|
|
53
|
+
"@commitlint/config-conventional": "^17.0.2",
|
|
54
|
+
"@ladjs/passport": "^5.0.0",
|
|
55
|
+
"ava": "^4.3.0",
|
|
54
56
|
"codecov": "^3.8.3",
|
|
55
57
|
"cross-env": "^7.0.3",
|
|
56
|
-
"eslint": "^8.
|
|
58
|
+
"eslint": "^8.16.0",
|
|
57
59
|
"eslint-config-xo-lass": "^1.0.6",
|
|
58
60
|
"fixpack": "^4.0.0",
|
|
59
|
-
"husky": "^
|
|
60
|
-
"lint-staged": "
|
|
61
|
-
"mongoose": "^6.3.
|
|
61
|
+
"husky": "^8.0.1",
|
|
62
|
+
"lint-staged": "13.0.0",
|
|
63
|
+
"mongoose": "^6.3.5",
|
|
62
64
|
"nyc": "^15.1.0",
|
|
63
65
|
"remark-cli": "^10.0.1",
|
|
64
|
-
"remark-preset-github": "^4.0.
|
|
66
|
+
"remark-preset-github": "^4.0.2",
|
|
65
67
|
"supertest": "^6.2.3",
|
|
66
|
-
"xo": "^0.
|
|
68
|
+
"xo": "^0.49.0"
|
|
67
69
|
},
|
|
68
70
|
"engines": {
|
|
69
71
|
"node": ">=10.10.0"
|