temba 0.10.13 → 0.11.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 +114 -28
- package/config/index.d.ts +15 -1
- package/config/index.js +11 -0
- package/config/index.js.map +1 -1
- package/index.js +6 -0
- package/index.js.map +1 -1
- package/package.json +3 -2
- package/routes/patch.d.ts +4 -0
- package/routes/patch.js +43 -0
- package/routes/patch.js.map +1 -0
- package/routes/put.js +2 -2
- package/routes/put.js.map +1 -1
- package/routes/routes.d.ts +2 -2
- package/routes/routes.js +6 -1
- package/routes/routes.js.map +1 -1
- package/routes/types.d.ts +3 -2
package/README.md
CHANGED
|
@@ -62,13 +62,13 @@ Alternatively, add Temba to your app manually:
|
|
|
62
62
|
2. Example code to create a Temba server:
|
|
63
63
|
|
|
64
64
|
```js
|
|
65
|
-
import temba from
|
|
66
|
-
const server = temba.create()
|
|
65
|
+
import temba from "temba"
|
|
66
|
+
const server = temba.create()
|
|
67
67
|
|
|
68
|
-
const port = process.env.PORT || 3000
|
|
68
|
+
const port = process.env.PORT || 3000
|
|
69
69
|
server.listen(port, () => {
|
|
70
|
-
console.log(`Temba is running on port ${port}`)
|
|
71
|
-
})
|
|
70
|
+
console.log(`Temba is running on port ${port}`)
|
|
71
|
+
})
|
|
72
72
|
```
|
|
73
73
|
|
|
74
74
|
### Configuration
|
|
@@ -79,20 +79,23 @@ By passing a config object to the `create` function you can customize Temba's be
|
|
|
79
79
|
|
|
80
80
|
Out of the box, Temba gives you a CRUD REST API to any resource name you can think of.
|
|
81
81
|
|
|
82
|
-
Whether you `GET` either `/people`, `/movies`, `/pokemons`, or whatever, it all returns a `200 OK` with a `[]` JSON response. As soon as you `POST` a new resource, followed by a `GET` of that resource, the new resource will be returned. You can also `DELETE`, or `PUT` resources by its ID.
|
|
82
|
+
Whether you `GET` either `/people`, `/movies`, `/pokemons`, or whatever, it all returns a `200 OK` with a `[]` JSON response. As soon as you `POST` a new resource, followed by a `GET` of that resource, the new resource will be returned. You can also `DELETE`, `PATCH`, or `PUT` resources by its ID.
|
|
83
83
|
|
|
84
84
|
For every resource (`movies` is just an example), Temba supports the following requests:
|
|
85
85
|
|
|
86
86
|
- `GET /movies` - Get all movies
|
|
87
87
|
- `GET /movies/:id` - Get a movie by its ID
|
|
88
88
|
- `POST /movies` - Create a new movie
|
|
89
|
-
- `
|
|
89
|
+
- `PATCH /movies/:id` - Partially update a movie by its ID
|
|
90
|
+
- `PUT /movies/:id` - Fully replace a movie by its ID
|
|
90
91
|
- `DELETE /movies` - Delete all movies
|
|
91
92
|
- `DELETE /movies/:id` - Delete a movie by its ID
|
|
93
|
+
- `HEAD /movies` - Get all movies, but without the response body
|
|
94
|
+
- `HEAD /movies/:id` - Get a movie by its ID, but without the response body
|
|
92
95
|
|
|
93
96
|
### Supported HTTP methods
|
|
94
97
|
|
|
95
|
-
The HTTP methods that are supported are `GET`, `POST`, `PUT` and `
|
|
98
|
+
The HTTP methods that are supported are `GET`, `POST`, `PATCH`, `PUT`, `DELETE`, and `HEAD`.
|
|
96
99
|
|
|
97
100
|
On the root URI (e.g. http://localhost:8080/) only a `GET` request is supported, which shows you a message indicating the API is working. All other HTTP methods on the root URI return a `405 Method Not Allowed` response.
|
|
98
101
|
|
|
@@ -100,7 +103,7 @@ On the root URI (e.g. http://localhost:8080/) only a `GET` request is supported,
|
|
|
100
103
|
|
|
101
104
|
Temba supports JSON only.
|
|
102
105
|
|
|
103
|
-
Request bodies sent with a `POST` and `PUT` requests are valid when the request body is either empty, or when it's valid formatted JSON. Adding a `Content-Type: application/json` header is required. If you send a request with invalid formatted JSON, a `400 Bad Request` response is returned.
|
|
106
|
+
Request bodies sent with a `POST`, `PATCH`, and `PUT` requests are valid when the request body is either empty, or when it's valid formatted JSON. Adding a `Content-Type: application/json` header is required. If you send a request with invalid formatted JSON, a `400 Bad Request` response is returned.
|
|
104
107
|
|
|
105
108
|
Any valid formatted JSON is accepted and stored. If you want to validate or even change the JSON in the request bodies, check out the [`requestBodyValidator`](#request-body-validation-or-mutation) callbacks.
|
|
106
109
|
|
|
@@ -134,29 +137,37 @@ Requests on these resources only give a `404 Not Found` if the ID does not exist
|
|
|
134
137
|
|
|
135
138
|
### Static assets
|
|
136
139
|
|
|
137
|
-
If you want to host static assets next to the
|
|
140
|
+
If you want to host static assets, next to the API, configure the `staticFolder`:
|
|
138
141
|
|
|
139
142
|
```js
|
|
140
143
|
const config = { staticFolder: 'build' }
|
|
141
144
|
const server = temba.create(config)
|
|
142
145
|
```
|
|
143
146
|
|
|
144
|
-
|
|
147
|
+
With this setting, sending a `GET` request to the root URL, returns the content that is in the `'./build'` folder in your project.
|
|
145
148
|
|
|
146
|
-
|
|
149
|
+
This way, you could create an API, and the web app consuming it, in one project.
|
|
147
150
|
|
|
148
|
-
|
|
151
|
+
Without configuring a `staticFolder`, a `GET` to the root URL returns `"It works! ツ"`. When the `staticFolder` is configured, it returns whatever is in the `build` folder in your project, for example an HTML page.
|
|
149
152
|
|
|
150
|
-
|
|
153
|
+
However, this might cause conflicts between the API resources and the web app routes: If the web app in the `build` folder has a route to `/products`, but there is also a `/products` API resource, the web app route is returned.
|
|
154
|
+
|
|
155
|
+
To be able to still access the `/products` API resource, configure an `apiPrefix`:
|
|
156
|
+
|
|
157
|
+
### API prefix
|
|
158
|
+
|
|
159
|
+
With the `apiPrefix` config setting, all resources get an extra path segment in front of them. If the `apiPrefix` is `'api'`, then `/movies/12345` becomes `/api/movies/12345`:
|
|
151
160
|
|
|
152
161
|
```js
|
|
153
162
|
const config = { apiPrefix: 'api' }
|
|
154
163
|
const server = temba.create(config)
|
|
155
164
|
```
|
|
156
165
|
|
|
157
|
-
|
|
166
|
+
A request to the `apiPrefix` (e.g. http://localhost:1234/api) will now return the `"It works! ツ"` response message.
|
|
158
167
|
|
|
159
|
-
|
|
168
|
+
After configuring the `apiPrefix`, requests to the root URL (e.g. http://localhost:1234/), instead of the `"It works! ツ"` response message, will now either return a `404 Not Found` on `GET` requests, or a `405 Method Not Allowed` for all other HTTP methods.
|
|
169
|
+
|
|
170
|
+
However, if you configured both an `apiPrefix` and a `staticFolder`, a `GET` on the root URL will return the content in the `staticFolder`.
|
|
160
171
|
|
|
161
172
|
### Request body validation or mutation
|
|
162
173
|
|
|
@@ -178,9 +189,7 @@ POST /movies
|
|
|
178
189
|
}
|
|
179
190
|
```
|
|
180
191
|
|
|
181
|
-
You can even omit a request body when doing a `POST` or `PUT`. If you don't want that, and
|
|
182
|
-
|
|
183
|
-
If you want to do input validation before the `POST` or `PUT` request body is saved to the database, configure Temba as follows:
|
|
192
|
+
You can even omit a request body when doing a `POST`, `PATCH`, or `PUT`. If you don't want that, and want to have proper validation, use the `requestBodyValidator` config setting:
|
|
184
193
|
|
|
185
194
|
```js
|
|
186
195
|
const config = {
|
|
@@ -191,13 +200,16 @@ const config = {
|
|
|
191
200
|
put: (resourceName, requestBody) => {
|
|
192
201
|
// Validate, or even change the requestBody
|
|
193
202
|
},
|
|
203
|
+
patch: (resourceName, requestBody) => {
|
|
204
|
+
// Validate, or even change the requestBody
|
|
205
|
+
},
|
|
194
206
|
},
|
|
195
207
|
}
|
|
196
208
|
|
|
197
209
|
const server = temba.create(config)
|
|
198
210
|
```
|
|
199
211
|
|
|
200
|
-
The `requestBodyValidator` is an object with a `post` and/or `put` field, which contains the callback function you want Temba to call before the JSON is saved to the database.
|
|
212
|
+
The `requestBodyValidator` is an object with a `post`, and/or `patch`, and/or `put` field, which contains the callback function you want Temba to call before the JSON is saved to the database.
|
|
201
213
|
|
|
202
214
|
The callback function receives two arguments: The `resourceName`, which for example is `movies` if you request `POST /movies`. The second argument is the `requestBody`, which is the JSON object in the request body.
|
|
203
215
|
|
|
@@ -232,6 +244,79 @@ const config = {
|
|
|
232
244
|
const server = temba.create(config)
|
|
233
245
|
```
|
|
234
246
|
|
|
247
|
+
## Custom router
|
|
248
|
+
|
|
249
|
+
Although `temba.create()` returns an Express instance, adding your own routes, as you would normally do with Express, is not possible:
|
|
250
|
+
|
|
251
|
+
```js
|
|
252
|
+
const server = temba.create()
|
|
253
|
+
|
|
254
|
+
// 🛑 Although `server` is an Express instance, the following does not work:
|
|
255
|
+
server.get('/hello', (req, res) => {
|
|
256
|
+
res.send('hello world')
|
|
257
|
+
})
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
The reason is that Temba is in charge of all Express routes, to make sure only resource routes can be overruled by a custom router. To add your own routes, create an Express router, and configure it as a `customRouter`:
|
|
261
|
+
|
|
262
|
+
```js
|
|
263
|
+
// Example code of how to create an Express router, from the official Express docs at https://expressjs.com/en/guide/routing.html:
|
|
264
|
+
const express = require('express')
|
|
265
|
+
const router = express.Router()
|
|
266
|
+
|
|
267
|
+
// middleware that is specific to this router
|
|
268
|
+
router.use((req, res, next) => {
|
|
269
|
+
console.log('Time: ', Date.now())
|
|
270
|
+
next()
|
|
271
|
+
})
|
|
272
|
+
// define the home page route
|
|
273
|
+
router.get('/', (req, res) => {
|
|
274
|
+
res.send('Birds home page')
|
|
275
|
+
})
|
|
276
|
+
// define the about route
|
|
277
|
+
router.get('/about', (req, res) => {
|
|
278
|
+
res.send('About birds')
|
|
279
|
+
})
|
|
280
|
+
|
|
281
|
+
// Add the custom router to Temba config
|
|
282
|
+
const config = {
|
|
283
|
+
customRouter: router
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
const server = temba.create(config)
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
> 💁 Don't overuse `customRouter`, as it defeats the purpose of Temba being a simple out-of-the-box solution.
|
|
290
|
+
|
|
291
|
+
A `customRouter` can only overrule resource routes. The root URL (with or without `staticFolder`) will always be handled by Temba.
|
|
292
|
+
|
|
293
|
+
So for the following router and config:
|
|
294
|
+
|
|
295
|
+
```
|
|
296
|
+
router.get('/', (req, res) => {
|
|
297
|
+
res.send('Birds home page')
|
|
298
|
+
})
|
|
299
|
+
router.get('/stuff', (req, res) => {
|
|
300
|
+
res.send('Some stuff')
|
|
301
|
+
})
|
|
302
|
+
router.get('api/stuff', (req, res) => {
|
|
303
|
+
res.send('Some API stuff')
|
|
304
|
+
})
|
|
305
|
+
|
|
306
|
+
const config = {
|
|
307
|
+
resourceNames: ['stuff'],
|
|
308
|
+
staticFolder: 'build',
|
|
309
|
+
apiPrefix: 'api',
|
|
310
|
+
customRouter: router,
|
|
311
|
+
}
|
|
312
|
+
const server = temba.create(config)
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
* `/` will be handled by Temba, and will return the `staticFolder` (`build`) folder contents
|
|
316
|
+
* `/stuff` and `/api/stuff` will be handled by the custom router
|
|
317
|
+
* `/movies` will return a `404 Not Found`, because of `apiPrefix`
|
|
318
|
+
* `/api/movies` will return movies, handled by Temba
|
|
319
|
+
|
|
235
320
|
### Config settings overview
|
|
236
321
|
|
|
237
322
|
Configuring Temba is optional, it already works out of the box.
|
|
@@ -244,12 +329,16 @@ const config = {
|
|
|
244
329
|
connectionString: 'mongodb://localhost:27017',
|
|
245
330
|
staticFolder: 'build',
|
|
246
331
|
apiPrefix: 'api',
|
|
332
|
+
customRouter: router,
|
|
247
333
|
cacheControl: 'public, max-age=300',
|
|
248
334
|
delay: 500,
|
|
249
335
|
requestBodyValidator: {
|
|
250
336
|
post: (resourceName, requestBody) => {
|
|
251
337
|
// Validate, or even change the requestBody
|
|
252
338
|
},
|
|
339
|
+
patch: (resourceName, requestBody) => {
|
|
340
|
+
// Validate, or even change the requestBody
|
|
341
|
+
},
|
|
253
342
|
put: (resourceName, requestBody) => {
|
|
254
343
|
// Validate, or even change the requestBody
|
|
255
344
|
},
|
|
@@ -258,7 +347,7 @@ const config = {
|
|
|
258
347
|
const server = temba.create(config)
|
|
259
348
|
```
|
|
260
349
|
|
|
261
|
-
None of the settings are required, and
|
|
350
|
+
None of the settings are required, and only the settings you define are used.
|
|
262
351
|
|
|
263
352
|
These are all the possible settings:
|
|
264
353
|
|
|
@@ -267,7 +356,8 @@ These are all the possible settings:
|
|
|
267
356
|
| `resourceNames` | See [Allowing specific resources only](#allowing-specific-resources-only) |
|
|
268
357
|
| `connectionString` | See [MongoDB](#mongodb) |
|
|
269
358
|
| `staticFolder` | See [Static assets](#static-assets) |
|
|
270
|
-
| `apiPrefix` | See [
|
|
359
|
+
| `apiPrefix` | See [API prefix](#api-prefix) |
|
|
360
|
+
| `customRouter` | See [Custom router](#custom-router) |
|
|
271
361
|
| `cacheControl` | The `Cache-control` response header value for each GET request. |
|
|
272
362
|
| `delay` | After processing the request, the delay in milliseconds before the request should be sent. |
|
|
273
363
|
| `requestBodyValidator` | See [Request body validation or mutation](#request-body-validation-or-mutation) |
|
|
@@ -276,17 +366,13 @@ These are all the possible settings:
|
|
|
276
366
|
|
|
277
367
|
The following features would be very nice for Temba to support:
|
|
278
368
|
|
|
279
|
-
### `PATCH` requests
|
|
280
|
-
|
|
281
|
-
Partial updates using `PATCH`, or other HTTP methods are not (yet?) supported.
|
|
282
|
-
|
|
283
369
|
### Auth
|
|
284
370
|
|
|
285
371
|
Temba offers no ways for authentication or authorization (yet?), so if someone knows how to reach the API, they can read and mutate all your data, unless you restrict this in another way.
|
|
286
372
|
|
|
287
373
|
### Nested parent-child resources
|
|
288
374
|
|
|
289
|
-
Also nested (parent-child) routes are not supported (yet?)
|
|
375
|
+
Also nested (parent-child) URI routes are not supported (yet?). So every URI has the /:resource/:id structure and there is no way to indicate any deeper relation through the URI.
|
|
290
376
|
|
|
291
377
|
### Filtering and sorting
|
|
292
378
|
|
|
@@ -294,7 +380,7 @@ And there is no filtering, sorting, searching, etc. (yet?).
|
|
|
294
380
|
|
|
295
381
|
## Under the hood
|
|
296
382
|
|
|
297
|
-
Temba is built with JavaScript, [Node](https://nodejs.org), [Express](https://expressjs.com/), [Jest](https://jestjs.io/), [
|
|
383
|
+
Temba is built with JavaScript, [Node](https://nodejs.org), [Express](https://expressjs.com/), [Jest](https://jestjs.io/), [Supertest](https://www.npmjs.com/package/supertest), and [@rakered/mongo](https://www.npmjs.com/package/@rakered/mongo).
|
|
298
384
|
|
|
299
385
|
## Which problem does Temba solve?
|
|
300
386
|
|
package/config/index.d.ts
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
|
+
import { Router } from 'express';
|
|
1
2
|
import { RequestBodyValidator } from '../routes/types';
|
|
2
3
|
export declare type Config = {
|
|
4
|
+
validateResources: boolean;
|
|
5
|
+
resourceNames: string[];
|
|
6
|
+
apiPrefix: string;
|
|
7
|
+
cacheControl: string;
|
|
8
|
+
requestBodyValidator: RequestBodyValidator;
|
|
9
|
+
staticFolder: string;
|
|
10
|
+
connectionString: string;
|
|
11
|
+
delay: number;
|
|
12
|
+
customRouter: Router;
|
|
13
|
+
};
|
|
14
|
+
export declare type RouterConfig = Pick<Config, 'validateResources' | 'resourceNames' | 'apiPrefix' | 'cacheControl' | 'requestBodyValidator'>;
|
|
15
|
+
export declare type UserConfig = {
|
|
3
16
|
resourceNames?: string[];
|
|
4
17
|
validateResources?: boolean;
|
|
5
18
|
staticFolder?: string;
|
|
@@ -8,5 +21,6 @@ export declare type Config = {
|
|
|
8
21
|
cacheControl?: string;
|
|
9
22
|
delay?: number;
|
|
10
23
|
requestBodyValidator?: RequestBodyValidator;
|
|
24
|
+
customRouter?: Router;
|
|
11
25
|
};
|
|
12
|
-
export declare function initConfig(userConfig:
|
|
26
|
+
export declare function initConfig(userConfig: UserConfig): Config;
|
package/config/index.js
CHANGED
|
@@ -13,10 +13,14 @@ const defaultConfig = {
|
|
|
13
13
|
post: () => {
|
|
14
14
|
// do nothing
|
|
15
15
|
},
|
|
16
|
+
patch: () => {
|
|
17
|
+
// do nothing
|
|
18
|
+
},
|
|
16
19
|
put: () => {
|
|
17
20
|
// do nothing
|
|
18
21
|
},
|
|
19
22
|
},
|
|
23
|
+
customRouter: null,
|
|
20
24
|
};
|
|
21
25
|
function initConfig(userConfig) {
|
|
22
26
|
if (!userConfig)
|
|
@@ -51,11 +55,18 @@ function initConfig(userConfig) {
|
|
|
51
55
|
typeof userConfig.requestBodyValidator.post === 'function') {
|
|
52
56
|
config.requestBodyValidator.post = userConfig.requestBodyValidator.post;
|
|
53
57
|
}
|
|
58
|
+
if (userConfig.requestBodyValidator.patch &&
|
|
59
|
+
typeof userConfig.requestBodyValidator.patch === 'function') {
|
|
60
|
+
config.requestBodyValidator.patch = userConfig.requestBodyValidator.patch;
|
|
61
|
+
}
|
|
54
62
|
if (userConfig.requestBodyValidator.put &&
|
|
55
63
|
typeof userConfig.requestBodyValidator.put === 'function') {
|
|
56
64
|
config.requestBodyValidator.put = userConfig.requestBodyValidator.put;
|
|
57
65
|
}
|
|
58
66
|
}
|
|
67
|
+
if (userConfig.customRouter) {
|
|
68
|
+
config.customRouter = userConfig.customRouter;
|
|
69
|
+
}
|
|
59
70
|
return config;
|
|
60
71
|
}
|
|
61
72
|
exports.initConfig = initConfig;
|
package/config/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/config/index.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/config/index.ts"],"names":[],"mappings":";;;AAmCA,MAAM,aAAa,GAAW;IAC5B,aAAa,EAAE,EAAE;IACjB,iBAAiB,EAAE,KAAK;IACxB,YAAY,EAAE,IAAI;IAClB,SAAS,EAAE,EAAE;IACb,gBAAgB,EAAE,IAAI;IACtB,YAAY,EAAE,UAAU;IACxB,KAAK,EAAE,CAAC;IACR,oBAAoB,EAAE;QACpB,IAAI,EAAE,GAAG,EAAE;YACT,aAAa;QACf,CAAC;QACD,KAAK,EAAE,GAAG,EAAE;YACV,aAAa;QACf,CAAC;QACD,GAAG,EAAE,GAAG,EAAE;YACR,aAAa;QACf,CAAC;KACF;IACD,YAAY,EAAE,IAAI;CACnB,CAAA;AAED,SAAgB,UAAU,CAAC,UAAsB;IAC/C,IAAI,CAAC,UAAU;QAAE,OAAO,aAAa,CAAA;IAErC,MAAM,MAAM,GAAG,kBAAK,aAAa,CAAY,CAAA;IAE7C,IAAI,UAAU,CAAC,aAAa,IAAI,UAAU,CAAC,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE;QACnE,MAAM,CAAC,aAAa,GAAG,UAAU,CAAC,aAAa,CAAA;QAC/C,MAAM,CAAC,iBAAiB,GAAG,IAAI,CAAA;KAChC;IAED,IAAI,UAAU,CAAC,YAAY,EAAE;QAC3B,MAAM,CAAC,YAAY,GAAG,UAAU,CAAC,YAAY,CAAC,OAAO,CAAC,eAAe,EAAE,EAAE,CAAC,CAAA;KAC3E;IAED,IAAI,UAAU,CAAC,SAAS,EAAE;QACxB,MAAM,CAAC,SAAS;YACd,GAAG,GAAG,UAAU,CAAC,SAAS,CAAC,OAAO,CAAC,eAAe,EAAE,EAAE,CAAC,GAAG,GAAG,CAAA;KAChE;IAED,IAAI,UAAU,CAAC,gBAAgB,IAAI,UAAU,CAAC,gBAAgB,CAAC,MAAM,GAAG,CAAC,EAAE;QACzE,MAAM,CAAC,gBAAgB,GAAG,UAAU,CAAC,gBAAgB,CAAA;KACtD;IAED,IAAI,UAAU,CAAC,YAAY,IAAI,UAAU,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE;QACjE,MAAM,CAAC,YAAY,GAAG,UAAU,CAAC,YAAY,CAAA;KAC9C;IAED,IACE,UAAU,CAAC,KAAK;QAChB,UAAU,CAAC,KAAK,KAAK,CAAC;QACtB,OAAO,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,KAAK,QAAQ;QAC5C,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC;QAC5B,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,GAAG,KAAK,EAChC;QACA,MAAM,CAAC,KAAK,GAAG,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,CAAA;KACxC;IAED,IAAI,UAAU,CAAC,oBAAoB,EAAE;QACnC,IACE,UAAU,CAAC,oBAAoB,CAAC,IAAI;YACpC,OAAO,UAAU,CAAC,oBAAoB,CAAC,IAAI,KAAK,UAAU,EAC1D;YACA,MAAM,CAAC,oBAAoB,CAAC,IAAI,GAAG,UAAU,CAAC,oBAAoB,CAAC,IAAI,CAAA;SACxE;QACD,IACE,UAAU,CAAC,oBAAoB,CAAC,KAAK;YACrC,OAAO,UAAU,CAAC,oBAAoB,CAAC,KAAK,KAAK,UAAU,EAC3D;YACA,MAAM,CAAC,oBAAoB,CAAC,KAAK,GAAG,UAAU,CAAC,oBAAoB,CAAC,KAAK,CAAA;SAC1E;QACD,IACE,UAAU,CAAC,oBAAoB,CAAC,GAAG;YACnC,OAAO,UAAU,CAAC,oBAAoB,CAAC,GAAG,KAAK,UAAU,EACzD;YACA,MAAM,CAAC,oBAAoB,CAAC,GAAG,GAAG,UAAU,CAAC,oBAAoB,CAAC,GAAG,CAAA;SACtE;KACF;IAED,IAAI,UAAU,CAAC,YAAY,EAAE;QAC3B,MAAM,CAAC,YAAY,GAAG,UAAU,CAAC,YAAY,CAAA;KAC9C;IAED,OAAO,MAAM,CAAA;AACf,CAAC;AA/DD,gCA+DC"}
|
package/index.js
CHANGED
|
@@ -44,6 +44,8 @@ function createServer(userConfig) {
|
|
|
44
44
|
const delayMiddleware = (0, delayMiddleware_1.createDelayMiddleware)(config.delay);
|
|
45
45
|
app.use(delayMiddleware);
|
|
46
46
|
}
|
|
47
|
+
//TODO customRoutes:
|
|
48
|
+
// - Al deze routing code naar een aparte functie
|
|
47
49
|
// Serve a static folder, if configured.
|
|
48
50
|
if (config.staticFolder) {
|
|
49
51
|
app.use(express_1.default.static(config.staticFolder));
|
|
@@ -51,11 +53,15 @@ function createServer(userConfig) {
|
|
|
51
53
|
// On the root URL (with apiPrefix if applicable) only a GET is allowed.
|
|
52
54
|
const rootPath = config.apiPrefix ? `${config.apiPrefix}` : '/';
|
|
53
55
|
app.use(rootPath, routes_1.rootRouter);
|
|
56
|
+
if (config.customRouter) {
|
|
57
|
+
app.use(config.customRouter);
|
|
58
|
+
}
|
|
54
59
|
// For all other URLs, only GET, POST, PUT and DELETE are allowed and handled.
|
|
55
60
|
const resourceRouter = (0, routes_1.createResourceRouter)(queries, config);
|
|
56
61
|
const resourcePath = config.apiPrefix ? `${config.apiPrefix}*` : '*';
|
|
57
62
|
app.use(resourcePath, resourceRouter);
|
|
58
63
|
// In case of an API prefix, GET, POST, PUT and DELETE requests to all other URLs return a 404 Not Found.
|
|
64
|
+
//TODO Hier missen toch HTTP methods?
|
|
59
65
|
if (config.apiPrefix) {
|
|
60
66
|
app.get('*', routes_1.handleNotFound);
|
|
61
67
|
app.post('*', routes_1.handleNotFound);
|
package/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AAAA,mDAAuC;AACvC,oDAA2B;AAC3B,4CAA8C;AAC9C,4CAKwB;AACxB,+CAAiD;AACjD,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AAAA,mDAAuC;AACvC,oDAA2B;AAC3B,4CAA8C;AAC9C,4CAKwB;AACxB,+CAAiD;AACjD,qCAAyD;AACzD,gDAAuB;AACvB,6DAA+D;AAE/D,SAAS,YAAY,CAAC,UAAuB;IAC3C,MAAM,MAAM,GAAG,IAAA,mBAAU,EAAC,UAAU,CAAC,CAAA;IAErC,MAAM,OAAO,GAAG,IAAA,uBAAa,EAAC,MAAM,CAAC,gBAAgB,CAAC,CAAA;IAEtD,MAAM,GAAG,GAAG,IAAA,iBAAO,GAAE,CAAA;IACrB,GAAG,CAAC,GAAG,CAAC,IAAA,cAAI,GAAE,CAAC,CAAA;IAEf,4BAA4B;IAC5B,GAAG,CAAC,GAAG,CAAC,IAAA,gBAAM,EAAC,MAAM,CAAC,CAAC,CAAA;IAEvB,gCAAgC;IAChC,GAAG,CAAC,GAAG,CAAC,IAAA,cAAI,EAAC,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC,CAAC,CAAA;IAElD,IAAI,MAAM,CAAC,KAAK,GAAG,CAAC,EAAE;QACpB,MAAM,eAAe,GAAG,IAAA,uCAAqB,EAAC,MAAM,CAAC,KAAK,CAAC,CAAA;QAC3D,GAAG,CAAC,GAAG,CAAC,eAAe,CAAC,CAAA;KACzB;IAED,oBAAoB;IACpB,iDAAiD;IAEjD,wCAAwC;IACxC,IAAI,MAAM,CAAC,YAAY,EAAE;QACvB,GAAG,CAAC,GAAG,CAAC,iBAAO,CAAC,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAA;KAC7C;IAED,wEAAwE;IACxE,MAAM,QAAQ,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,GAAG,CAAA;IAC/D,GAAG,CAAC,GAAG,CAAC,QAAQ,EAAE,mBAAU,CAAC,CAAA;IAE7B,IAAI,MAAM,CAAC,YAAY,EAAE;QACvB,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,YAAY,CAAC,CAAA;KAC7B;IAED,8EAA8E;IAC9E,MAAM,cAAc,GAAG,IAAA,6BAAoB,EAAC,OAAO,EAAE,MAAM,CAAC,CAAA;IAC5D,MAAM,YAAY,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC,GAAG,CAAA;IACpE,GAAG,CAAC,GAAG,CAAC,YAAY,EAAE,cAAc,CAAC,CAAA;IAErC,yGAAyG;IACzG,qCAAqC;IACrC,IAAI,MAAM,CAAC,SAAS,EAAE;QACpB,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,uBAAc,CAAC,CAAA;QAC5B,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,uBAAc,CAAC,CAAA;QAC7B,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,uBAAc,CAAC,CAAA;QAC5B,GAAG,CAAC,MAAM,CAAC,GAAG,EAAE,uBAAc,CAAC,CAAA;KAChC;IAED,gDAAgD;IAChD,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,+BAAsB,CAAC,CAAA;IACpC,IAAI,MAAM,CAAC,SAAS;QAAE,GAAG,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,SAAS,GAAG,EAAE,+BAAsB,CAAC,CAAA;IAE7E,oBAAoB;IACpB,GAAG,CAAC,GAAG,CAAC,qBAAY,CAAC,CAAA;IAErB,OAAO,GAAG,CAAA;AACZ,CAAC;AAED,SAAgB,MAAM,CAAC,UAAmB;IACxC,OAAO,YAAY,CAAC,UAAU,CAAC,CAAA;AACjC,CAAC;AAFD,wBAEC"}
|
package/package.json
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "temba",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.11.0",
|
|
4
4
|
"description": "Get a simple MongoDB REST API with zero coding in less than 30 seconds (seriously).",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"scripts": {
|
|
7
7
|
"build": "rm -rf dist && tsc && cp package.json README.md ./dist",
|
|
8
|
-
"test": "jest --
|
|
8
|
+
"test": "jest --silent --no-cache",
|
|
9
|
+
"test:watch": "jest --watch --no-cache",
|
|
9
10
|
"lint": "eslint --ignore-path .gitignore --ext .js,.ts .",
|
|
10
11
|
"format": "prettier --ignore-path .gitignore --write \"**/*.+(js|ts|json)\""
|
|
11
12
|
},
|
package/routes/patch.js
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.createPatchRoutes = void 0;
|
|
13
|
+
const errors_1 = require("../errors/errors");
|
|
14
|
+
const validator_1 = require("./validator");
|
|
15
|
+
function createPatchRoutes(queries, requestBodyValidator) {
|
|
16
|
+
function handlePatch(req, res, next) {
|
|
17
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
18
|
+
try {
|
|
19
|
+
const { resourceName, id } = req.requestInfo;
|
|
20
|
+
const requestBody = (0, validator_1.validateRequestBody)(requestBodyValidator.patch, req);
|
|
21
|
+
if (typeof requestBody === 'string')
|
|
22
|
+
return res.status(400).json({ message: requestBody }).send();
|
|
23
|
+
let item = null;
|
|
24
|
+
if (id)
|
|
25
|
+
item = yield queries.getById(resourceName, id);
|
|
26
|
+
// TODO return a response instead of calling next
|
|
27
|
+
if (!item)
|
|
28
|
+
return next((0, errors_1.new404NotFoundError)(`ID '${id}' not found`));
|
|
29
|
+
item = Object.assign(Object.assign(Object.assign({}, item), requestBody), { id });
|
|
30
|
+
const updatedItem = yield queries.update(resourceName, item);
|
|
31
|
+
return res.status(200).json(updatedItem).send();
|
|
32
|
+
}
|
|
33
|
+
catch (error) {
|
|
34
|
+
return next(error);
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
return {
|
|
39
|
+
handlePatch,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
exports.createPatchRoutes = createPatchRoutes;
|
|
43
|
+
//# sourceMappingURL=patch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"patch.js","sourceRoot":"","sources":["../../src/routes/patch.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,6CAAsD;AACtD,2CAAiD;AAEjD,SAAS,iBAAiB,CAAC,OAAO,EAAE,oBAAoB;IACtD,SAAe,WAAW,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI;;YACvC,IAAI;gBACF,MAAM,EAAE,YAAY,EAAE,EAAE,EAAE,GAAG,GAAG,CAAC,WAAW,CAAA;gBAE5C,MAAM,WAAW,GAAG,IAAA,+BAAmB,EAAC,oBAAoB,CAAC,KAAK,EAAE,GAAG,CAAC,CAAA;gBAExE,IAAI,OAAO,WAAW,KAAK,QAAQ;oBACjC,OAAO,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC,CAAC,IAAI,EAAE,CAAA;gBAE9D,IAAI,IAAI,GAAG,IAAI,CAAA;gBACf,IAAI,EAAE;oBAAE,IAAI,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,YAAY,EAAE,EAAE,CAAC,CAAA;gBAEtD,iDAAiD;gBACjD,IAAI,CAAC,IAAI;oBAAE,OAAO,IAAI,CAAC,IAAA,4BAAmB,EAAC,OAAO,EAAE,aAAa,CAAC,CAAC,CAAA;gBAEnE,IAAI,iDAAQ,IAAI,GAAK,WAAW,KAAE,EAAE,GAAE,CAAA;gBAEtC,MAAM,WAAW,GAAG,MAAM,OAAO,CAAC,MAAM,CAAC,YAAY,EAAE,IAAI,CAAC,CAAA;gBAE5D,OAAO,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,IAAI,EAAE,CAAA;aAChD;YAAC,OAAO,KAAc,EAAE;gBACvB,OAAO,IAAI,CAAC,KAAK,CAAC,CAAA;aACnB;QACH,CAAC;KAAA;IAED,OAAO;QACL,WAAW;KACZ,CAAA;AACH,CAAC;AAEQ,8CAAiB"}
|
package/routes/put.js
CHANGED
|
@@ -27,8 +27,8 @@ function createPutRoutes(queries, requestBodyValidator) {
|
|
|
27
27
|
if (!item)
|
|
28
28
|
return next((0, errors_1.new404NotFoundError)(`ID '${id}' not found`));
|
|
29
29
|
item = Object.assign(Object.assign({}, requestBody), { id });
|
|
30
|
-
const
|
|
31
|
-
return res.status(200).json(
|
|
30
|
+
const replacedItem = yield queries.update(resourceName, item);
|
|
31
|
+
return res.status(200).json(replacedItem).send();
|
|
32
32
|
}
|
|
33
33
|
catch (error) {
|
|
34
34
|
return next(error);
|
package/routes/put.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"put.js","sourceRoot":"","sources":["../../src/routes/put.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,6CAAsD;AACtD,2CAAiD;AAEjD,SAAS,eAAe,CAAC,OAAO,EAAE,oBAAoB;IACpD,SAAe,SAAS,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI;;YACrC,IAAI;gBACF,MAAM,EAAE,YAAY,EAAE,EAAE,EAAE,GAAG,GAAG,CAAC,WAAW,CAAA;gBAE5C,MAAM,WAAW,GAAG,IAAA,+BAAmB,EAAC,oBAAoB,CAAC,GAAG,EAAE,GAAG,CAAC,CAAA;gBAEtE,IAAI,OAAO,WAAW,KAAK,QAAQ;oBACjC,OAAO,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC,CAAC,IAAI,EAAE,CAAA;gBAE9D,IAAI,IAAI,GAAG,IAAI,CAAA;gBACf,IAAI,EAAE;oBAAE,IAAI,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,YAAY,EAAE,EAAE,CAAC,CAAA;gBAEtD,iDAAiD;gBACjD,IAAI,CAAC,IAAI;oBAAE,OAAO,IAAI,CAAC,IAAA,4BAAmB,EAAC,OAAO,EAAE,aAAa,CAAC,CAAC,CAAA;gBAEnE,IAAI,mCAAQ,WAAW,KAAE,EAAE,GAAE,CAAA;gBAE7B,MAAM,
|
|
1
|
+
{"version":3,"file":"put.js","sourceRoot":"","sources":["../../src/routes/put.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,6CAAsD;AACtD,2CAAiD;AAEjD,SAAS,eAAe,CAAC,OAAO,EAAE,oBAAoB;IACpD,SAAe,SAAS,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI;;YACrC,IAAI;gBACF,MAAM,EAAE,YAAY,EAAE,EAAE,EAAE,GAAG,GAAG,CAAC,WAAW,CAAA;gBAE5C,MAAM,WAAW,GAAG,IAAA,+BAAmB,EAAC,oBAAoB,CAAC,GAAG,EAAE,GAAG,CAAC,CAAA;gBAEtE,IAAI,OAAO,WAAW,KAAK,QAAQ;oBACjC,OAAO,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC,CAAC,IAAI,EAAE,CAAA;gBAE9D,IAAI,IAAI,GAAG,IAAI,CAAA;gBACf,IAAI,EAAE;oBAAE,IAAI,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,YAAY,EAAE,EAAE,CAAC,CAAA;gBAEtD,iDAAiD;gBACjD,IAAI,CAAC,IAAI;oBAAE,OAAO,IAAI,CAAC,IAAA,4BAAmB,EAAC,OAAO,EAAE,aAAa,CAAC,CAAC,CAAA;gBAEnE,IAAI,mCAAQ,WAAW,KAAE,EAAE,GAAE,CAAA;gBAE7B,MAAM,YAAY,GAAG,MAAM,OAAO,CAAC,MAAM,CAAC,YAAY,EAAE,IAAI,CAAC,CAAA;gBAE7D,OAAO,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,IAAI,EAAE,CAAA;aACjD;YAAC,OAAO,KAAc,EAAE;gBACvB,OAAO,IAAI,CAAC,KAAK,CAAC,CAAA;aACnB;QACH,CAAC;KAAA;IAED,OAAO;QACL,SAAS;KACV,CAAA;AACH,CAAC;AAEQ,0CAAe"}
|
package/routes/routes.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
declare function createResourceRouter(queries: any,
|
|
1
|
+
import { RouterConfig } from '../config';
|
|
2
|
+
declare function createResourceRouter(queries: any, routerCounfig: RouterConfig): import("express-serve-static-core").Router;
|
|
3
3
|
declare const rootRouter: import("express-serve-static-core").Router;
|
|
4
4
|
declare function handleMethodNotAllowed(_: any, res: any): void;
|
|
5
5
|
declare function handleNotFound(_: any, res: any): void;
|
package/routes/routes.js
CHANGED
|
@@ -16,21 +16,26 @@ exports.handleNotFound = exports.handleMethodNotAllowed = exports.rootRouter = e
|
|
|
16
16
|
const get_1 = require("./get");
|
|
17
17
|
const post_1 = require("./post");
|
|
18
18
|
const put_1 = require("./put");
|
|
19
|
+
const patch_1 = require("./patch");
|
|
19
20
|
const delete_1 = require("./delete");
|
|
20
21
|
const urlMiddleware_1 = require("../urls/urlMiddleware");
|
|
21
22
|
const express_1 = __importDefault(require("express"));
|
|
22
|
-
function createResourceRouter(queries,
|
|
23
|
+
function createResourceRouter(queries, routerCounfig) {
|
|
24
|
+
const { validateResources, resourceNames, apiPrefix, cacheControl, requestBodyValidator, } = routerCounfig;
|
|
23
25
|
const { handleGetResource } = (0, get_1.createGetRoutes)(queries, cacheControl);
|
|
24
26
|
const { handlePost } = (0, post_1.createPostRoutes)(queries, requestBodyValidator);
|
|
25
27
|
const { handlePut } = (0, put_1.createPutRoutes)(queries, requestBodyValidator);
|
|
28
|
+
const { handlePatch } = (0, patch_1.createPatchRoutes)(queries, requestBodyValidator);
|
|
26
29
|
const { handleDelete } = (0, delete_1.createDeleteRoutes)(queries);
|
|
27
30
|
const validateResource = (0, urlMiddleware_1.createValidateResourceMiddleware)(validateResources, resourceNames);
|
|
28
31
|
const getResourceAndId = (0, urlMiddleware_1.createResourceAndIdParser)(apiPrefix);
|
|
29
32
|
const resourceRouter = express_1.default.Router();
|
|
30
33
|
resourceRouter
|
|
34
|
+
// The router.get() function automatically handles HEAD requests as well, unless router.head is called first.
|
|
31
35
|
.get('*', getResourceAndId, validateResource, handleGetResource)
|
|
32
36
|
.post('*', getResourceAndId, validateResource, handlePost)
|
|
33
37
|
.put('*', getResourceAndId, validateResource, handlePut)
|
|
38
|
+
.patch('*', getResourceAndId, validateResource, handlePatch)
|
|
34
39
|
.delete('*', getResourceAndId, validateResource, handleDelete);
|
|
35
40
|
return resourceRouter;
|
|
36
41
|
}
|
package/routes/routes.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"routes.js","sourceRoot":"","sources":["../../src/routes/routes.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,+BAAuC;AACvC,iCAAyC;AACzC,+BAAuC;AACvC,qCAA6C;AAC7C,yDAG8B;AAE9B,sDAA6B;AAG7B,SAAS,oBAAoB,CAC3B,OAAO,EACP,
|
|
1
|
+
{"version":3,"file":"routes.js","sourceRoot":"","sources":["../../src/routes/routes.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,+BAAuC;AACvC,iCAAyC;AACzC,+BAAuC;AACvC,mCAA2C;AAC3C,qCAA6C;AAC7C,yDAG8B;AAE9B,sDAA6B;AAG7B,SAAS,oBAAoB,CAC3B,OAAO,EACP,aAA2B;IAG3B,MAAM,EACJ,iBAAiB,EACjB,aAAa,EACb,SAAS,EACT,YAAY,EACZ,oBAAoB,GACrB,GAAG,aAAa,CAAA;IACjB,MAAM,EAAE,iBAAiB,EAAE,GAAG,IAAA,qBAAe,EAAC,OAAO,EAAE,YAAY,CAAC,CAAA;IACpE,MAAM,EAAE,UAAU,EAAE,GAAG,IAAA,uBAAgB,EAAC,OAAO,EAAE,oBAAoB,CAAC,CAAA;IACtE,MAAM,EAAE,SAAS,EAAE,GAAG,IAAA,qBAAe,EAAC,OAAO,EAAE,oBAAoB,CAAC,CAAA;IACpE,MAAM,EAAE,WAAW,EAAE,GAAG,IAAA,yBAAiB,EAAC,OAAO,EAAE,oBAAoB,CAAC,CAAA;IACxE,MAAM,EAAE,YAAY,EAAE,GAAG,IAAA,2BAAkB,EAAC,OAAO,CAAC,CAAA;IAEpD,MAAM,gBAAgB,GAAG,IAAA,gDAAgC,EACvD,iBAAiB,EACjB,aAAa,CACd,CAAA;IACD,MAAM,gBAAgB,GAAG,IAAA,yCAAyB,EAAC,SAAS,CAAC,CAAA;IAE7D,MAAM,cAAc,GAAG,iBAAO,CAAC,MAAM,EAAE,CAAA;IAEvC,cAAc;QACZ,6GAA6G;SAC5G,GAAG,CAAC,GAAG,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,iBAAiB,CAAC;SAC/D,IAAI,CAAC,GAAG,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,UAAU,CAAC;SACzD,GAAG,CAAC,GAAG,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,SAAS,CAAC;SACvD,KAAK,CAAC,GAAG,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,WAAW,CAAC;SAC3D,MAAM,CAAC,GAAG,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,YAAY,CAAC,CAAA;IAEhE,OAAO,cAAc,CAAA;AACvB,CAAC;AAsBC,oDAAoB;AApBtB,iDAAiD;AACjD,MAAM,UAAU,GAAG,iBAAO,CAAC,MAAM,EAAE,CAAA;AAoBjC,gCAAU;AAnBZ,UAAU,CAAC,GAAG,CAAC,GAAG,EAAE,CAAO,CAAC,EAAE,GAAG,EAAE,EAAE;IACnC,OAAO,GAAG,CAAC,IAAI,CAAC,aAAa,CAAC,CAAA;AAChC,CAAC,CAAA,CAAC,CAAA;AAEF,sDAAsD;AACtD,UAAU,CAAC,GAAG,CAAC,GAAG,EAAE,sBAAsB,CAAC,CAAA;AAE3C,0CAA0C;AAC1C,SAAS,sBAAsB,CAAC,CAAC,EAAE,GAAG;IACpC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,oBAAoB,EAAE,CAAC,CAAA;AACzD,CAAC;AAUC,wDAAsB;AARxB,gCAAgC;AAChC,SAAS,cAAc,CAAC,CAAC,EAAE,GAAG;IAC5B,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC,CAAA;AAChD,CAAC;AAMC,wCAAc"}
|
package/routes/types.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export declare type ValidatorCallback = (resourceName: string, requestBody: unknown) => void | string | object;
|
|
2
2
|
export declare type RequestBodyValidator = {
|
|
3
|
-
post
|
|
4
|
-
|
|
3
|
+
post?: ValidatorCallback;
|
|
4
|
+
patch?: ValidatorCallback;
|
|
5
|
+
put?: ValidatorCallback;
|
|
5
6
|
};
|