@ladjs/api 9.0.2 → 10.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/README.md +0 -9
- package/index.js +54 -42
- package/package.json +12 -49
package/README.md
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
# [**@ladjs/api**](https://github.com/ladjs/api)
|
|
2
2
|
|
|
3
3
|
[](https://travis-ci.org/ladjs/api)
|
|
4
|
-
[](https://codecov.io/gh/ladjs/api)
|
|
5
4
|
[](https://github.com/sindresorhus/xo)
|
|
6
5
|
[](https://github.com/prettier/prettier)
|
|
7
6
|
[](https://lass.js.org)
|
|
@@ -26,12 +25,6 @@
|
|
|
26
25
|
npm install @ladjs/api
|
|
27
26
|
```
|
|
28
27
|
|
|
29
|
-
[yarn][]:
|
|
30
|
-
|
|
31
|
-
```sh
|
|
32
|
-
yarn add @ladjs/api
|
|
33
|
-
```
|
|
34
|
-
|
|
35
28
|
|
|
36
29
|
## Usage
|
|
37
30
|
|
|
@@ -53,5 +46,3 @@ See <https://github.com/ladjs/lad/blob/master/template/api.js> for the most up t
|
|
|
53
46
|
##
|
|
54
47
|
|
|
55
48
|
[npm]: https://www.npmjs.com/
|
|
56
|
-
|
|
57
|
-
[yarn]: https://yarnpkg.com/
|
package/index.js
CHANGED
|
@@ -30,7 +30,7 @@ const responseTime = require('response-time');
|
|
|
30
30
|
const sharedConfig = require('@ladjs/shared-config');
|
|
31
31
|
const { boolean } = require('boolean');
|
|
32
32
|
|
|
33
|
-
const RATE_LIMIT_EXCEEDED =
|
|
33
|
+
const RATE_LIMIT_EXCEEDED = 'Rate limit exceeded, retry in %s.';
|
|
34
34
|
|
|
35
35
|
class API {
|
|
36
36
|
// eslint-disable-next-line complexity
|
|
@@ -41,16 +41,16 @@ class API {
|
|
|
41
41
|
...config
|
|
42
42
|
};
|
|
43
43
|
|
|
44
|
-
//
|
|
44
|
+
// Initialize the app
|
|
45
45
|
const app = new Koa();
|
|
46
46
|
|
|
47
|
-
//
|
|
47
|
+
// Only trust proxy if enabled
|
|
48
48
|
app.proxy = boolean(process.env.TRUST_PROXY);
|
|
49
49
|
|
|
50
|
-
//
|
|
50
|
+
// Specify that this is our api (used by error handler)
|
|
51
51
|
app.context.api = true;
|
|
52
52
|
|
|
53
|
-
//
|
|
53
|
+
// Initialize cabin
|
|
54
54
|
this.logger = _.isPlainObject(this.config.logger)
|
|
55
55
|
? new Cabin(this.config.logger)
|
|
56
56
|
: this.config.logger instanceof Cabin
|
|
@@ -60,7 +60,7 @@ class API {
|
|
|
60
60
|
});
|
|
61
61
|
app.context.logger = this.logger;
|
|
62
62
|
|
|
63
|
-
//
|
|
63
|
+
// Initialize redis
|
|
64
64
|
this.client =
|
|
65
65
|
this.config.redis === false
|
|
66
66
|
? false
|
|
@@ -69,7 +69,7 @@ class API {
|
|
|
69
69
|
: this.config.redis;
|
|
70
70
|
app.context.client = this.client;
|
|
71
71
|
|
|
72
|
-
//
|
|
72
|
+
// Expose passport
|
|
73
73
|
this.passport =
|
|
74
74
|
this.config.passport === false
|
|
75
75
|
? false
|
|
@@ -78,50 +78,55 @@ class API {
|
|
|
78
78
|
: this.config.passport;
|
|
79
79
|
app.context.passport = this.passport;
|
|
80
80
|
|
|
81
|
-
//
|
|
82
|
-
app.on('error', (
|
|
83
|
-
ctx.logger[
|
|
81
|
+
// Listen for errors emitted by app
|
|
82
|
+
app.on('error', (error, ctx) => {
|
|
83
|
+
ctx.logger[error.status && error.status < 500 ? 'warn' : 'error'](error);
|
|
84
84
|
});
|
|
85
85
|
|
|
86
|
-
//
|
|
86
|
+
// Override koa's undocumented error handler
|
|
87
87
|
app.context.onerror = errorHandler(false);
|
|
88
88
|
|
|
89
|
-
//
|
|
89
|
+
// Adds request received hrtime and date symbols to request object
|
|
90
90
|
// (which is used by Cabin internally to add `request.timestamp` to logs
|
|
91
91
|
app.use(requestReceived);
|
|
92
92
|
|
|
93
|
-
//
|
|
93
|
+
// Configure timeout
|
|
94
94
|
if (this.config.timeout) {
|
|
95
95
|
const timeout = new Timeout(this.config.timeout);
|
|
96
96
|
app.use(timeout.middleware);
|
|
97
97
|
}
|
|
98
98
|
|
|
99
|
-
//
|
|
99
|
+
// Adds `X-Response-Time` header to responses
|
|
100
100
|
app.use(koaConnect(responseTime()));
|
|
101
101
|
|
|
102
|
-
//
|
|
102
|
+
// Adds or re-uses `X-Request-Id` header
|
|
103
103
|
app.use(koaConnect(requestId()));
|
|
104
104
|
|
|
105
|
-
//
|
|
105
|
+
// Use the cabin middleware (adds request-based logging and helpers)
|
|
106
106
|
app.use(this.logger.middleware);
|
|
107
107
|
|
|
108
|
-
//
|
|
109
|
-
if (_.isFunction(this.config.hookBeforeSetup))
|
|
108
|
+
// Allow before hooks to get setup
|
|
109
|
+
if (_.isFunction(this.config.hookBeforeSetup)) {
|
|
110
110
|
this.config.hookBeforeSetup(app);
|
|
111
|
+
}
|
|
111
112
|
|
|
112
|
-
//
|
|
113
|
-
if (this.config.auth)
|
|
113
|
+
// Basic auth
|
|
114
|
+
if (this.config.auth) {
|
|
115
|
+
app.use(auth(this.config.auth));
|
|
116
|
+
}
|
|
114
117
|
|
|
115
|
-
//
|
|
118
|
+
// Rate limiting
|
|
116
119
|
if (this.client && this.config.rateLimit) {
|
|
117
120
|
app.use((ctx, next) => {
|
|
118
|
-
//
|
|
121
|
+
// Check against ignored/whitelisted paths
|
|
119
122
|
if (
|
|
120
123
|
Array.isArray(this.config.rateLimitIgnoredGlobs) &&
|
|
121
124
|
this.config.rateLimitIgnoredGlobs.length > 0
|
|
122
125
|
) {
|
|
123
126
|
const match = multimatch(ctx.path, this.config.rateLimitIgnoredGlobs);
|
|
124
|
-
if (Array.isArray(match) && match.length > 0)
|
|
127
|
+
if (Array.isArray(match) && match.length > 0) {
|
|
128
|
+
return next();
|
|
129
|
+
}
|
|
125
130
|
}
|
|
126
131
|
|
|
127
132
|
return ratelimit({
|
|
@@ -138,10 +143,10 @@ class API {
|
|
|
138
143
|
});
|
|
139
144
|
}
|
|
140
145
|
|
|
141
|
-
//
|
|
146
|
+
// Remove trailing slashes
|
|
142
147
|
app.use(removeTrailingSlashes());
|
|
143
148
|
|
|
144
|
-
//
|
|
149
|
+
// I18n
|
|
145
150
|
if (this.config.i18n) {
|
|
146
151
|
const i18n = this.config.i18n.config
|
|
147
152
|
? this.config.i18n
|
|
@@ -149,25 +154,29 @@ class API {
|
|
|
149
154
|
app.use(i18n.middleware);
|
|
150
155
|
}
|
|
151
156
|
|
|
152
|
-
//
|
|
157
|
+
// Conditional-get
|
|
153
158
|
app.use(conditional());
|
|
154
159
|
|
|
155
|
-
//
|
|
160
|
+
// Etag
|
|
156
161
|
app.use(etag());
|
|
157
162
|
|
|
158
|
-
//
|
|
159
|
-
if (this.config.cors)
|
|
163
|
+
// Cors
|
|
164
|
+
if (this.config.cors) {
|
|
165
|
+
app.use(cors(this.config.cors));
|
|
166
|
+
}
|
|
160
167
|
|
|
161
|
-
//
|
|
168
|
+
// Body parser
|
|
162
169
|
app.use(bodyParser());
|
|
163
170
|
|
|
164
|
-
//
|
|
171
|
+
// Pretty-printed json responses
|
|
165
172
|
app.use(json());
|
|
166
173
|
|
|
167
|
-
//
|
|
168
|
-
if (this.passport)
|
|
174
|
+
// Passport
|
|
175
|
+
if (this.passport) {
|
|
176
|
+
app.use(this.passport.initialize());
|
|
177
|
+
}
|
|
169
178
|
|
|
170
|
-
//
|
|
179
|
+
// Store the user's last ip address in the background
|
|
171
180
|
if (this.config.storeIPAddress) {
|
|
172
181
|
const storeIPAddress = new StoreIPAddress({
|
|
173
182
|
logger: this.logger,
|
|
@@ -179,27 +188,30 @@ class API {
|
|
|
179
188
|
// 404 handler
|
|
180
189
|
app.use(koa404Handler);
|
|
181
190
|
|
|
182
|
-
//
|
|
183
|
-
if (_.isFunction(this.config.hookBeforeRoutes))
|
|
191
|
+
// Allow before hooks to get setup
|
|
192
|
+
if (_.isFunction(this.config.hookBeforeRoutes)) {
|
|
184
193
|
this.config.hookBeforeRoutes(app);
|
|
194
|
+
}
|
|
185
195
|
|
|
186
|
-
//
|
|
196
|
+
// Mount the app's defined and nested routes
|
|
187
197
|
if (this.config.routes) {
|
|
188
|
-
if (_.isFunction(this.config.routes.routes))
|
|
198
|
+
if (_.isFunction(this.config.routes.routes)) {
|
|
189
199
|
app.use(this.config.routes.routes());
|
|
190
|
-
else
|
|
200
|
+
} else {
|
|
201
|
+
app.use(this.config.routes);
|
|
202
|
+
}
|
|
191
203
|
}
|
|
192
204
|
|
|
193
|
-
//
|
|
205
|
+
// Start server on either http or https
|
|
194
206
|
this.server =
|
|
195
207
|
this.config.protocol === 'https'
|
|
196
208
|
? https.createServer(this.config.ssl, app.callback())
|
|
197
209
|
: http.createServer(app.callback());
|
|
198
210
|
|
|
199
|
-
//
|
|
211
|
+
// Expose the app
|
|
200
212
|
this.app = app;
|
|
201
213
|
|
|
202
|
-
//
|
|
214
|
+
// Bind listen/close to this
|
|
203
215
|
this.listen = this.listen.bind(this);
|
|
204
216
|
this.close = this.close.bind(this);
|
|
205
217
|
}
|
package/package.json
CHANGED
|
@@ -1,21 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ladjs/api",
|
|
3
3
|
"description": "API server for Lad",
|
|
4
|
-
"version": "
|
|
4
|
+
"version": "10.0.0",
|
|
5
5
|
"author": "Nick Baugh <niftylettuce@gmail.com> (http://niftylettuce.com/)",
|
|
6
|
-
"ava": {
|
|
7
|
-
"failFast": true,
|
|
8
|
-
"verbose": true
|
|
9
|
-
},
|
|
10
6
|
"bugs": {
|
|
11
7
|
"url": "https://github.com/ladjs/api/issues",
|
|
12
8
|
"email": "niftylettuce@gmail.com"
|
|
13
9
|
},
|
|
14
|
-
"commitlint": {
|
|
15
|
-
"extends": [
|
|
16
|
-
"@commitlint/config-conventional"
|
|
17
|
-
]
|
|
18
|
-
},
|
|
19
10
|
"contributors": [
|
|
20
11
|
"Nick Baugh <niftylettuce@gmail.com> (http://niftylettuce.com/)"
|
|
21
12
|
],
|
|
@@ -23,7 +14,7 @@
|
|
|
23
14
|
"@koa/router": "^10.1.1",
|
|
24
15
|
"@ladjs/i18n": "^7.2.6",
|
|
25
16
|
"@ladjs/koa-simple-ratelimit": "^3.0.0",
|
|
26
|
-
"@ladjs/passport": "^5.0.
|
|
17
|
+
"@ladjs/passport": "^5.0.1",
|
|
27
18
|
"@ladjs/redis": "^1.0.7",
|
|
28
19
|
"@ladjs/shared-config": "^7.0.3",
|
|
29
20
|
"@ladjs/store-ip-address": "^0.0.7",
|
|
@@ -34,7 +25,7 @@
|
|
|
34
25
|
"koa": "^2.13.4",
|
|
35
26
|
"koa-404-handler": "^0.1.0",
|
|
36
27
|
"koa-basic-auth": "^4.0.0",
|
|
37
|
-
"koa-better-error-handler": "^
|
|
28
|
+
"koa-better-error-handler": "^9.0.0",
|
|
38
29
|
"koa-better-timeout": "^0.0.6",
|
|
39
30
|
"koa-bodyparser": "^4.3.0",
|
|
40
31
|
"koa-compress": "^5.1.0",
|
|
@@ -53,33 +44,26 @@
|
|
|
53
44
|
"@commitlint/cli": "^17.0.2",
|
|
54
45
|
"@commitlint/config-conventional": "^17.0.2",
|
|
55
46
|
"ava": "^4.3.0",
|
|
56
|
-
"codecov": "^3.8.3",
|
|
57
47
|
"cross-env": "^7.0.3",
|
|
58
|
-
"eslint": "^8.
|
|
59
|
-
"eslint-config-xo-lass": "^
|
|
48
|
+
"eslint": "^8.17.0",
|
|
49
|
+
"eslint-config-xo-lass": "^2.0.1",
|
|
60
50
|
"fixpack": "^4.0.0",
|
|
61
51
|
"husky": "^8.0.1",
|
|
62
52
|
"lint-staged": "13.0.0",
|
|
63
53
|
"mongoose": "^6.3.5",
|
|
64
54
|
"nyc": "^15.1.0",
|
|
65
55
|
"remark-cli": "^10.0.1",
|
|
66
|
-
"remark-preset-github": "^4.0.
|
|
56
|
+
"remark-preset-github": "^4.0.4",
|
|
67
57
|
"supertest": "^6.2.3",
|
|
68
58
|
"xo": "^0.49.0"
|
|
69
59
|
},
|
|
70
60
|
"engines": {
|
|
71
|
-
"node": ">=
|
|
61
|
+
"node": ">=14"
|
|
72
62
|
},
|
|
73
63
|
"files": [
|
|
74
64
|
"index.js"
|
|
75
65
|
],
|
|
76
66
|
"homepage": "https://github.com/ladjs/api",
|
|
77
|
-
"husky": {
|
|
78
|
-
"hooks": {
|
|
79
|
-
"pre-commit": "lint-staged && npm test",
|
|
80
|
-
"commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
|
|
81
|
-
}
|
|
82
|
-
},
|
|
83
67
|
"keywords": [
|
|
84
68
|
"api",
|
|
85
69
|
"error",
|
|
@@ -106,36 +90,15 @@
|
|
|
106
90
|
],
|
|
107
91
|
"license": "MIT",
|
|
108
92
|
"main": "index.js",
|
|
109
|
-
"prettier": {
|
|
110
|
-
"singleQuote": true,
|
|
111
|
-
"bracketSpacing": true,
|
|
112
|
-
"trailingComma": "none"
|
|
113
|
-
},
|
|
114
|
-
"remarkConfig": {
|
|
115
|
-
"plugins": [
|
|
116
|
-
"preset-github"
|
|
117
|
-
]
|
|
118
|
-
},
|
|
119
93
|
"repository": {
|
|
120
94
|
"type": "git",
|
|
121
95
|
"url": "https://github.com/ladjs/api"
|
|
122
96
|
},
|
|
123
97
|
"scripts": {
|
|
124
|
-
"
|
|
125
|
-
"
|
|
126
|
-
"
|
|
127
|
-
"
|
|
128
|
-
"test": "
|
|
129
|
-
"test-coverage": "npm run lint && npm run nyc"
|
|
130
|
-
},
|
|
131
|
-
"xo": {
|
|
132
|
-
"prettier": true,
|
|
133
|
-
"space": true,
|
|
134
|
-
"extends": [
|
|
135
|
-
"xo-lass"
|
|
136
|
-
],
|
|
137
|
-
"ignores": [
|
|
138
|
-
"config.js"
|
|
139
|
-
]
|
|
98
|
+
"lint": "xo && remark . -qfo && fixpack",
|
|
99
|
+
"prepare": "husky install",
|
|
100
|
+
"pretest": "npm run lint",
|
|
101
|
+
"test": "npm run test-coverage",
|
|
102
|
+
"test-coverage": "cross-env NODE_ENV=test nyc ava"
|
|
140
103
|
}
|
|
141
104
|
}
|