temba 0.16.0 → 0.18.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.
Files changed (67) hide show
  1. package/README.md +77 -45
  2. package/config/index.d.ts +13 -8
  3. package/config/index.js +41 -18
  4. package/config/index.js.map +1 -1
  5. package/delay/delayMiddleware.js +1 -1
  6. package/delay/delayMiddleware.js.map +1 -1
  7. package/index.js +26 -22
  8. package/index.js.map +1 -1
  9. package/package.json +16 -14
  10. package/queries/in-memory.d.ts +9 -8
  11. package/queries/in-memory.js +64 -42
  12. package/queries/in-memory.js.map +1 -1
  13. package/queries/mongo.d.ts +8 -8
  14. package/queries/mongo.js +177 -65
  15. package/queries/mongo.js.map +1 -1
  16. package/queries/queries.d.ts +7 -16
  17. package/queries/queries.js +3 -3
  18. package/queries/queries.js.map +1 -1
  19. package/queries/types.d.ts +14 -0
  20. package/queries/types.js +3 -0
  21. package/queries/types.js.map +1 -0
  22. package/routes/delete.d.ts +5 -2
  23. package/routes/delete.js +55 -17
  24. package/routes/delete.js.map +1 -1
  25. package/routes/get.d.ts +5 -2
  26. package/routes/get.js +92 -48
  27. package/routes/get.js.map +1 -1
  28. package/routes/interceptRequestBody.d.ts +3 -0
  29. package/routes/interceptRequestBody.js +19 -0
  30. package/routes/interceptRequestBody.js.map +1 -0
  31. package/routes/patch.d.ts +6 -2
  32. package/routes/patch.js +82 -27
  33. package/routes/patch.js.map +1 -1
  34. package/routes/post.d.ts +6 -2
  35. package/routes/post.js +67 -27
  36. package/routes/post.js.map +1 -1
  37. package/routes/put.d.ts +6 -2
  38. package/routes/put.js +82 -27
  39. package/routes/put.js.map +1 -1
  40. package/routes/routes.d.ts +3 -1
  41. package/routes/routes.js +51 -22
  42. package/routes/routes.js.map +1 -1
  43. package/routes/types.d.ts +12 -6
  44. package/routes/utils.d.ts +1 -3
  45. package/routes/utils.js +7 -2
  46. package/routes/utils.js.map +1 -1
  47. package/schema/compile.d.ts +2 -0
  48. package/schema/compile.js +41 -0
  49. package/schema/compile.js.map +1 -0
  50. package/schema/transformConfig.d.ts +2 -0
  51. package/schema/transformConfig.js +17 -0
  52. package/schema/transformConfig.js.map +1 -0
  53. package/schema/types.d.ts +35 -0
  54. package/schema/types.js +3 -0
  55. package/schema/types.js.map +1 -0
  56. package/schema/validate.d.ts +3 -0
  57. package/schema/validate.js +19 -0
  58. package/schema/validate.js.map +1 -0
  59. package/urls/urlMiddleware.d.ts +4 -2
  60. package/urls/urlMiddleware.js +21 -10
  61. package/urls/urlMiddleware.js.map +1 -1
  62. package/urls/urlParser.d.ts +3 -3
  63. package/urls/urlParser.js +5 -5
  64. package/urls/urlParser.js.map +1 -1
  65. package/routes/interceptors.d.ts +0 -3
  66. package/routes/interceptors.js +0 -22
  67. package/routes/interceptors.js.map +0 -1
package/README.md CHANGED
@@ -75,7 +75,7 @@ const server = temba.create()
75
75
  server.start()
76
76
  ```
77
77
 
78
- 3.In your console you'll see:
78
+ 3. In your console you'll see:
79
79
 
80
80
  ```
81
81
  ✅ Server listening on port 3000
@@ -109,15 +109,17 @@ The HTTP methods that are supported are `GET`, `POST`, `PATCH`, `PUT`, `DELETE`,
109
109
 
110
110
  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.
111
111
 
112
+ The `OPTIONS` method also works, but because Temba uses Express' default implementation for that, the `Access-Control-Allow-Methods` response header might not always be correct.
113
+
112
114
  ### JSON
113
115
 
114
116
  Temba supports JSON only.
115
117
 
116
118
  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.
117
119
 
118
- 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 [`requestBodyInterceptor`](#request-body-validation-or-mutation) callbacks.
120
+ Any valid formatted JSON is accepted and stored. If you want to validate or even change the JSON in the request bodies, check out [JSON Schema request body validation](#json-schema-request-body-validation) and the [`requestBodyInterceptor`](#request-body-validation-or-mutation).
119
121
 
120
- IDs are auto generated when creating resources. IDs in the JSON request body are ignored for any request.
122
+ IDs are auto generated when creating resources. IDs in the JSON request body are always ignored.
121
123
 
122
124
  ## Usage
123
125
 
@@ -136,11 +138,11 @@ For every resource you use in your requests, a collection is created in the data
136
138
 
137
139
  ### Allowing specific resources only
138
140
 
139
- If you only want to allow specific resource names, configure them by providing a `resourceNames` key in the config object when creating the Temba server:
141
+ If you only want to allow specific resource names, configure them by providing a `resources` key in the config object when creating the Temba server:
140
142
 
141
143
  ```js
142
144
  const config = {
143
- resourceNames: ['movies', 'actors'],
145
+ resources: ['movies', 'actors'],
144
146
  }
145
147
  const server = temba.create(config)
146
148
  ```
@@ -149,7 +151,7 @@ Requests on these resources only give a `404 Not Found` if the ID does not exist
149
151
 
150
152
  ### Static assets
151
153
 
152
- If you want to host static assets, next to the API, configure the `staticFolder`:
154
+ If you want to host static assets, for example next to the API, a web app consuming it, you can configure a `staticFolder`:
153
155
 
154
156
  ```js
155
157
  const config = {
@@ -160,8 +162,6 @@ const server = temba.create(config)
160
162
 
161
163
  With this setting, sending a `GET` request to the root URL, returns the content that is in the `'./build'` folder in your project.
162
164
 
163
- This way, you could create an API, and the web app consuming it, in one project.
164
-
165
165
  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.
166
166
 
167
167
  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.
@@ -185,9 +185,9 @@ After configuring the `apiPrefix`, requests to the root URL (e.g. http://localho
185
185
 
186
186
  However, if you configured both an `apiPrefix` and a `staticFolder`, a `GET` on the root URL will return the content in the `staticFolder`.
187
187
 
188
- ### Request body validation or mutation
188
+ ### JSON Schema request body validation
189
189
 
190
- Temba does not validate request bodies.
190
+ By default, Temba does not validate request bodies.
191
191
 
192
192
  This means you can store your resources in any format you like. So creating the following two (very different) _movies_ is perfectly fine:
193
193
 
@@ -205,19 +205,55 @@ POST /movies
205
205
  }
206
206
  ```
207
207
 
208
- 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 `requestBodyInterceptor` config setting:
208
+ You can even omit a request body when doing a `POST`, `PATCH`, or `PUT`. While this might be fine or even convenient when using Temba for prototyping, at some some point you might want to validate the request body.
209
+
210
+ With the `schema` setting, you can define a [JSON Schema](https://json-schema.org/), per resource, and per request method. Here we define that when creating or replacing a movie, the `title` is required, the `description` is optional, and we don't allow any other fields. Updating movies has the same schema, except there are no required fields:
211
+
212
+ ```js
213
+ const schemaNewMovie = {
214
+ type: 'object',
215
+ properties: {
216
+ title: { type: 'string' },
217
+ description: { type: 'string' },
218
+ },
219
+ required: ['title'],
220
+ additionalProperties: false,
221
+ }
222
+
223
+ const schemaUpdateMovie = { ...schemaNewMovie, required: [] }
224
+
225
+ const config = {
226
+ schema: {
227
+ movies: {
228
+ post: schemaNewMovie,
229
+ put: schemaNewMovie,
230
+ patch: schemaUpdateMovie,
231
+ },
232
+ },
233
+ }
234
+
235
+ const server = temba.create(config)
236
+ ```
237
+
238
+ If a request is not valid according to the schema, a `400 Bad Request` response is returned, and a message in the response body indicating the validation error.
239
+
240
+ ### Intercepting requests
241
+
242
+ In addition to (or instead of) validating the request using JSON Schema, you can also intercept the request body before it goes to the database, using the `requestBodyInterceptor` setting.
243
+
244
+ It allows you to implement your own validation, or even change the request body.
209
245
 
210
246
  ```js
211
247
  const config = {
212
248
  requestBodyInterceptor: {
213
- post: ({ resourceName, requestBody }) => {
214
- // Validate, or even change the requestBody
249
+ post: ({ resource, body }) => {
250
+ // Validate, or even change the request body
215
251
  },
216
- put: ({ resourceName, requestBody }) => {
217
- // Validate, or even change the requestBody
252
+ put: ({ resource, body }) => {
253
+ // Validate, or even change the request body
218
254
  },
219
- patch: ({ resourceName, requestBody }) => {
220
- // Validate, or even change the requestBody
255
+ patch: ({ resource, body }) => {
256
+ // Validate, or even change the request body
221
257
  },
222
258
  },
223
259
  }
@@ -227,7 +263,7 @@ const server = temba.create(config)
227
263
 
228
264
  The `requestBodyInterceptor` 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.
229
265
 
230
- The callback function receives an object containing the `resourceName`, which for example is `movies` if you request `POST /movies`, and the `requestBody`, which is the JSON object of the request body.
266
+ The callback function receives an object containing the `resource`, which for example is `movies` if you request `POST /movies`, and the `body`, which is the JSON object of the request body.
231
267
 
232
268
  Your callback function can return the following things:
233
269
 
@@ -240,13 +276,13 @@ Example:
240
276
  ```js
241
277
  const config = {
242
278
  requestBodyInterceptor: {
243
- post: ({ resourceName, requestBody }) => {
244
- // Do not allow Pokemons to be created: 400 Bad Request
245
- if (resourceName === 'pokemons') return 'You are not allowed to create new Pokemons'
279
+ post: ({ resource, body }) => {
280
+ // Do not allow Pokemons to be created: 400 Bad Req best
281
+ if (resource === 'pokemons') return 'You are not allowed to create new Pokemons'
246
282
 
247
283
  // Add a genre to Star Trek films:
248
- if (resourceName === 'movies' && requestBody.title.startsWith('Star Trek'))
249
- return { ...requestBody, genre: 'Science Fiction' }
284
+ if (resource === 'movies' && body.title.startsWith('Star Trek'))
285
+ return { ...body, genre: 'Science Fiction' }
250
286
 
251
287
  // If you end up here, void will be returned, so the request will just be saved.
252
288
  },
@@ -262,17 +298,17 @@ To change the response body of a `GET` request, before it's being sent to the cl
262
298
 
263
299
  ```js
264
300
  const config = {
265
- responseBodyInterceptor: ({ resourceName, responseBody, id }) => {
266
- if (resourceName === 'movies') {
301
+ responseBodyInterceptor: ({ resource, body, id }) => {
302
+ if (resource === 'movies') {
267
303
  if (id) {
268
- // responseBody is an object
304
+ // response body is an object
269
305
  return {
270
- ...responseBody,
306
+ ...body,
271
307
  stuff: 'more stuff',
272
308
  }
273
309
  } else {
274
- // responseBody is an array
275
- return responseBody.map((x) => ({
310
+ // response body is an array
311
+ return body.map((x) => ({
276
312
  ...x,
277
313
  stuff: 'more stuff',
278
314
  }))
@@ -286,9 +322,9 @@ const config = {
286
322
  const server = temba.create(config)
287
323
  ```
288
324
 
289
- `responseBodyInterceptor` is a callback function that provides an object containing the `resourceName`, `responseBody`, and the `id`. Depending on whether it's a collection or item request, the `responseBody` is either an array or object, and the `id' can be `undefined`.
325
+ `responseBodyInterceptor` is a callback function that provides an object containing the `resource`, `body`, and the `id`. Depending on whether it's a collection or item request, the `body` is either an array or object, and the `id` can be `undefined`.
290
326
 
291
- In the example above we check for the `id` being defined, but a runtime check to determine the type of `responseBody` would also suffice.
327
+ In the example above we check for the `id` being defined, but a runtime check to determine the type of `body` would also suffice.
292
328
 
293
329
  Whatever you return in this function will become the response body and will be serialized as JSON and returned to the client.
294
330
 
@@ -347,7 +383,7 @@ router.get('api/stuff', (req, res) => {
347
383
  const config = {
348
384
  apiPrefix: 'api',
349
385
  customRouter: router,
350
- resourceNames: ['stuff'],
386
+ resources: ['stuff'],
351
387
  staticFolder: 'build',
352
388
  }
353
389
  const server = temba.create(config)
@@ -373,18 +409,18 @@ const config = {
373
409
  delay: 500,
374
410
  port: 4321,
375
411
  requestBodyInterceptor: {
376
- post: ({ resourceName, requestBody }) => {
377
- // Validate, or even change the requestBody
412
+ post: ({ resource, body }) => {
413
+ // Validate, or even change the request body
378
414
  },
379
- patch: ({ resourceName, requestBody }) => {
380
- // Validate, or even change the requestBody
415
+ patch: ({ resource, body }) => {
416
+ // Validate, or even change the request body
381
417
  },
382
- put: ({ resourceName, requestBody }) => {
383
- // Validate, or even change the requestBody
418
+ put: ({ resource, body }) => {
419
+ // Validate, or even change the request body
384
420
  },
385
421
  },
386
- resourceNames: ['movies', 'actors'],
387
- responseBodyInterceptor: ({ resourceName, responseBody, id }) => {
422
+ resources: ['movies', 'actors'],
423
+ responseBodyInterceptor: ({ resource, body, id }) => {
388
424
  // Change the response body before it is sent to the client
389
425
  },
390
426
  returnNullFields: false,
@@ -404,7 +440,7 @@ These are all the possible settings:
404
440
  | `delay` | After processing the request, the delay in milliseconds before the request should be sent. | `0` |
405
441
  | `port` | The port your Temba server listens on | `3000` |
406
442
  | `requestBodyInterceptor` | See [Request body validation or mutation](#request-body-validation-or-mutation) | `noop` |
407
- | `resourceNames` | See [Allowing specific resources only](#allowing-specific-resources-only) | `[]` |
443
+ | `resources` | See [Allowing specific resources only](#allowing-specific-resources-only) | `[]` |
408
444
  | `responseBodyInterceptor` | See [Response body interception](#request-body-validation-or-mutation) | `noop` |
409
445
  | `returnNullFields` | Whether fields with a `null` value should be returned in responses. | `true` |
410
446
  | `staticFolder` | See [Static assets](#static-assets) | `null` |
@@ -417,16 +453,12 @@ Although I won't promise if and when, these are some things to consider for the
417
453
 
418
454
  - Better **security**, for example CORS, CSRF, etc.
419
455
 
420
- - Connecting to a **SQLite** database, see https://github.com/bouwe77/temba/issues/24
421
-
422
456
  - Opt-in logging with debug-js events
423
457
 
424
458
  - Generic **filtering and sorting**, for example: `GET /api/movies?filter=releaseYear ge 1980 and releaseYear le 1989&sort=-releaseYear,title&page=2&limit=20&fields=title,releaseYear,genre`
425
459
 
426
460
  - Intial data seed when using in-memory.
427
461
 
428
- - Get rid of Express?
429
-
430
462
  ## Under the hood
431
463
 
432
464
  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).
package/config/index.d.ts CHANGED
@@ -1,23 +1,26 @@
1
1
  import { Router } from 'express';
2
2
  import { RequestBodyInterceptor, ResponseBodyInterceptor } from '../routes/types';
3
+ import { ConfiguredSchemas } from '../schema/types';
3
4
  export type Config = {
4
5
  validateResources: boolean;
5
- resourceNames: string[];
6
- apiPrefix: string;
6
+ resources: string[];
7
+ apiPrefix: string | null;
7
8
  cacheControl: string;
8
9
  requestBodyInterceptor: RequestBodyInterceptor;
9
10
  responseBodyInterceptor: ResponseBodyInterceptor;
10
- staticFolder: string;
11
- connectionString: string;
11
+ staticFolder: string | null;
12
+ connectionString: string | null;
12
13
  delay: number;
13
- customRouter: Router;
14
+ customRouter: Router | null;
14
15
  returnNullFields: boolean;
15
16
  isTesting: boolean;
16
17
  port: number;
18
+ schemas: ConfiguredSchemas | null;
17
19
  };
18
- export type RouterConfig = Pick<Config, 'validateResources' | 'resourceNames' | 'apiPrefix' | 'cacheControl' | 'requestBodyInterceptor' | 'responseBodyInterceptor' | 'returnNullFields'>;
20
+ export type ConfigKey = keyof Config;
21
+ export type RouterConfig = Pick<Config, 'validateResources' | 'resources' | 'apiPrefix' | 'cacheControl' | 'requestBodyInterceptor' | 'responseBodyInterceptor' | 'returnNullFields'>;
19
22
  export type UserConfig = {
20
- resourceNames?: string[];
23
+ resources?: string[];
21
24
  staticFolder?: string;
22
25
  apiPrefix?: string;
23
26
  connectionString?: string;
@@ -29,5 +32,7 @@ export type UserConfig = {
29
32
  returnNullFields?: boolean;
30
33
  isTesting?: boolean;
31
34
  port?: number;
35
+ schemas?: ConfiguredSchemas;
32
36
  };
33
- export declare function initConfig(userConfig: UserConfig): Config;
37
+ export declare function initConfig(userConfig?: UserConfig): Config;
38
+ export declare const isUndefined: (value: unknown) => value is undefined;
package/config/index.js CHANGED
@@ -1,40 +1,52 @@
1
1
  "use strict";
2
+ var __assign = (this && this.__assign) || function () {
3
+ __assign = Object.assign || function(t) {
4
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
5
+ s = arguments[i];
6
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
7
+ t[p] = s[p];
8
+ }
9
+ return t;
10
+ };
11
+ return __assign.apply(this, arguments);
12
+ };
2
13
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.initConfig = void 0;
4
- const defaultConfig = {
5
- resourceNames: [],
14
+ exports.isUndefined = exports.initConfig = void 0;
15
+ var defaultConfig = {
16
+ resources: [],
6
17
  validateResources: false,
7
18
  staticFolder: null,
8
- apiPrefix: '',
19
+ apiPrefix: null,
9
20
  connectionString: null,
10
21
  cacheControl: 'no-store',
11
22
  delay: 0,
12
23
  requestBodyInterceptor: {
13
- post: () => {
24
+ post: function () {
14
25
  // do nothing
15
26
  },
16
- patch: () => {
27
+ patch: function () {
17
28
  // do nothing
18
29
  },
19
- put: () => {
30
+ put: function () {
20
31
  // do nothing
21
32
  },
22
33
  },
23
- responseBodyInterceptor: ({ responseBody }) => {
24
- return responseBody;
34
+ responseBodyInterceptor: function (_a) {
35
+ var body = _a.body;
36
+ return body;
25
37
  },
26
38
  customRouter: null,
27
39
  returnNullFields: true,
28
40
  isTesting: false,
29
41
  port: 3000,
42
+ schemas: null,
30
43
  };
31
44
  function initConfig(userConfig) {
32
- var _a, _b, _c;
33
45
  if (!userConfig)
34
46
  return defaultConfig;
35
- const config = Object.assign({}, defaultConfig);
36
- if (userConfig.resourceNames && userConfig.resourceNames.length > 0) {
37
- config.resourceNames = userConfig.resourceNames;
47
+ var config = __assign({}, defaultConfig);
48
+ if (userConfig.resources && userConfig.resources.length > 0) {
49
+ config.resources = userConfig.resources;
38
50
  config.validateResources = true;
39
51
  }
40
52
  if (userConfig.staticFolder) {
@@ -53,8 +65,8 @@ function initConfig(userConfig) {
53
65
  userConfig.delay !== 0 &&
54
66
  typeof Number(userConfig.delay) === 'number' &&
55
67
  Number(userConfig.delay) > 0 &&
56
- Number(userConfig.delay) < 10000) {
57
- config.delay = Number(userConfig.delay);
68
+ Number(userConfig.delay) < 100000) {
69
+ config.delay = userConfig.delay;
58
70
  }
59
71
  if (userConfig.requestBodyInterceptor) {
60
72
  if (userConfig.requestBodyInterceptor.post &&
@@ -76,10 +88,21 @@ function initConfig(userConfig) {
76
88
  if (userConfig.customRouter) {
77
89
  config.customRouter = userConfig.customRouter;
78
90
  }
79
- config.returnNullFields = (_a = userConfig.returnNullFields) !== null && _a !== void 0 ? _a : true;
80
- config.isTesting = (_b = userConfig.isTesting) !== null && _b !== void 0 ? _b : false;
81
- config.port = (_c = userConfig.port) !== null && _c !== void 0 ? _c : 3000;
91
+ if (!(0, exports.isUndefined)(userConfig.returnNullFields)) {
92
+ config.returnNullFields = userConfig.returnNullFields;
93
+ }
94
+ if (!(0, exports.isUndefined)(userConfig.isTesting)) {
95
+ config.isTesting = userConfig.isTesting;
96
+ }
97
+ if (!(0, exports.isUndefined)(userConfig.port)) {
98
+ config.port = userConfig.port;
99
+ }
100
+ if (userConfig.schemas) {
101
+ config.schemas = userConfig.schemas;
102
+ }
82
103
  return config;
83
104
  }
84
105
  exports.initConfig = initConfig;
106
+ var isUndefined = function (value) { return typeof value === 'undefined'; };
107
+ exports.isUndefined = isUndefined;
85
108
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/config/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/config/index.ts"],"names":[],"mappings":"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"}
@@ -4,7 +4,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.createDelayMiddleware = void 0;
7
- const connect_pause_1 = __importDefault(require("connect-pause"));
7
+ var connect_pause_1 = __importDefault(require("connect-pause"));
8
8
  function createDelayMiddleware(delay) {
9
9
  return function (req, res, next) {
10
10
  console.log('Start delay...');
@@ -1 +1 @@
1
- {"version":3,"file":"delayMiddleware.js","sourceRoot":"","sources":["../../src/delay/delayMiddleware.ts"],"names":[],"mappings":";;;;;;AAAA,kEAAiC;AAEjC,SAAS,qBAAqB,CAAC,KAAK;IAClC,OAAO,UAAU,GAAG,EAAE,GAAG,EAAE,IAAI;QAC7B,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAA;QAC7B,IAAA,uBAAK,EAAC,KAAK,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,CAAC,CAAA;QAC5B,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAA;IAChC,CAAC,CAAA;AACH,CAAC;AAEQ,sDAAqB"}
1
+ {"version":3,"file":"delayMiddleware.js","sourceRoot":"","sources":["../../src/delay/delayMiddleware.ts"],"names":[],"mappings":";;;;;;AAAA,gEAAiC;AAEjC,SAAS,qBAAqB,CAAC,KAAK;IAClC,OAAO,UAAU,GAAG,EAAE,GAAG,EAAE,IAAI;QAC7B,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAA;QAC7B,IAAA,uBAAK,EAAC,KAAK,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,CAAC,CAAA;QAC5B,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAA;IAChC,CAAC,CAAA;AACH,CAAC;AAEQ,sDAAqB"}
package/index.js CHANGED
@@ -27,60 +27,64 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
27
27
  };
28
28
  Object.defineProperty(exports, "__esModule", { value: true });
29
29
  exports.create = void 0;
30
- const express_1 = __importStar(require("express"));
31
- const morgan_1 = __importDefault(require("morgan"));
32
- const routes_1 = require("./routes/routes");
33
- const queries_1 = require("./queries/queries");
34
- const config_1 = require("./config");
35
- const cors_1 = __importDefault(require("cors"));
36
- const delayMiddleware_1 = require("./delay/delayMiddleware");
30
+ var express_1 = __importStar(require("express"));
31
+ var morgan_1 = __importDefault(require("morgan"));
32
+ var routes_1 = require("./routes/routes");
33
+ var queries_1 = require("./queries/queries");
34
+ var config_1 = require("./config");
35
+ var cors_1 = __importDefault(require("cors"));
36
+ var delayMiddleware_1 = require("./delay/delayMiddleware");
37
+ var compile_1 = require("./schema/compile");
37
38
  function createServer(userConfig) {
38
- const config = (0, config_1.initConfig)(userConfig);
39
- const queries = (0, queries_1.createQueries)(config.connectionString);
40
- const app = (0, express_1.default)();
39
+ var config = (0, config_1.initConfig)(userConfig);
40
+ var queries = (0, queries_1.createQueries)(config.connectionString);
41
+ var app = (0, express_1.default)();
41
42
  app.use((0, express_1.json)());
42
43
  // Add HTTP request logging.
43
44
  app.use((0, morgan_1.default)('tiny'));
44
45
  // Enable CORS for all requests.
45
46
  app.use((0, cors_1.default)({ origin: true, credentials: true }));
46
47
  if (config.delay > 0) {
47
- const delayMiddleware = (0, delayMiddleware_1.createDelayMiddleware)(config.delay);
48
+ var delayMiddleware = (0, delayMiddleware_1.createDelayMiddleware)(config.delay);
48
49
  app.use(delayMiddleware);
49
50
  }
50
51
  // Serve a static folder, if configured.
51
52
  if (config.staticFolder) {
52
53
  app.use(express_1.default.static(config.staticFolder));
53
54
  }
54
- // On the root URL (with apiPrefix if applicable) only a GET is allowed.
55
- const rootPath = config.apiPrefix ? `${config.apiPrefix}` : '/';
55
+ // On the root URL (with apiPrefix, if applicable) only a GET is allowed.
56
+ var rootPath = config.apiPrefix ? "".concat(config.apiPrefix) : '/';
56
57
  app.use(rootPath, routes_1.rootRouter);
57
58
  if (config.customRouter) {
58
59
  app.use(config.customRouter);
59
60
  }
60
- // For all other URLs, only GET, POST, PUT and DELETE are allowed and handled.
61
- const resourceRouter = (0, routes_1.createResourceRouter)(queries, config);
62
- const resourcePath = config.apiPrefix ? `${config.apiPrefix}*` : '*';
61
+ // Temba supports the GET, POST, PUT, PATCH, DELETE, and HEAD methods for resource URLs.
62
+ // HEAD is not implemented here, because Express supports it out of the box.
63
+ // Create a router on all other URLs, for all supported methods
64
+ var resourcePath = config.apiPrefix ? "".concat(config.apiPrefix, "*") : '*';
65
+ var schemas = (0, compile_1.compileAndTransformSchemas)(config.schemas);
66
+ var resourceRouter = (0, routes_1.createResourceRouter)(queries, schemas, config);
63
67
  app.use(resourcePath, resourceRouter);
64
- // In case of an API prefix, GET, POST, PUT and DELETE requests to all other URLs return a 404 Not Found.
65
- //TODO Hier missen toch HTTP methods?
68
+ // In case of an API prefix, resource URLs outside of the API prefix return a 404 Not Found.
66
69
  if (config.apiPrefix) {
67
70
  app.get('*', routes_1.handleNotFound);
68
71
  app.post('*', routes_1.handleNotFound);
69
72
  app.put('*', routes_1.handleNotFound);
70
73
  app.delete('*', routes_1.handleNotFound);
74
+ app.patch('*', routes_1.handleNotFound);
71
75
  }
72
76
  // All other methods to any URL are not allowed.
73
77
  app.all('*', routes_1.handleMethodNotAllowed);
74
78
  if (config.apiPrefix)
75
- app.all(`${config.apiPrefix}*`, routes_1.handleMethodNotAllowed);
79
+ app.all("".concat(config.apiPrefix, "*"), routes_1.handleMethodNotAllowed);
76
80
  return {
77
- start: () => {
81
+ start: function () {
78
82
  if (config.isTesting) {
79
83
  console.log('⛔️ Server not started. Remove or disable isTesting from your config.');
80
84
  return;
81
85
  }
82
- app.listen(config.port, () => {
83
- console.log(`✅ Server listening on port ${config.port}`);
86
+ app.listen(config.port, function () {
87
+ console.log("\u2705 Server listening on port ".concat(config.port));
84
88
  });
85
89
  },
86
90
  // Expose Express for testing purposes only, e.g. usage with supertest.
package/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,iDAAuC;AACvC,kDAA2B;AAC3B,0CAKwB;AACxB,6CAAiD;AACjD,mCAAyD;AACzD,8CAAuB;AACvB,2DAA+D;AAC/D,4CAA6D;AAE7D,SAAS,YAAY,CAAC,UAAuB;IAC3C,IAAM,MAAM,GAAG,IAAA,mBAAU,EAAC,UAAU,CAAC,CAAA;IAErC,IAAM,OAAO,GAAG,IAAA,uBAAa,EAAC,MAAM,CAAC,gBAAgB,CAAC,CAAA;IAEtD,IAAM,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,IAAM,eAAe,GAAG,IAAA,uCAAqB,EAAC,MAAM,CAAC,KAAK,CAAC,CAAA;QAC3D,GAAG,CAAC,GAAG,CAAC,eAAe,CAAC,CAAA;KACzB;IAED,wCAAwC;IACxC,IAAI,MAAM,CAAC,YAAY,EAAE;QACvB,GAAG,CAAC,GAAG,CAAC,iBAAO,CAAC,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAA;KAC7C;IAED,yEAAyE;IACzE,IAAM,QAAQ,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,UAAG,MAAM,CAAC,SAAS,CAAE,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,wFAAwF;IACxF,4EAA4E;IAE5E,+DAA+D;IAC/D,IAAM,YAAY,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,UAAG,MAAM,CAAC,SAAS,MAAG,CAAC,CAAC,CAAC,GAAG,CAAA;IACpE,IAAM,OAAO,GAAG,IAAA,oCAA0B,EAAC,MAAM,CAAC,OAAO,CAAC,CAAA;IAC1D,IAAM,cAAc,GAAG,IAAA,6BAAoB,EAAC,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC,CAAA;IACrE,GAAG,CAAC,GAAG,CAAC,YAAY,EAAE,cAAc,CAAC,CAAA;IAErC,4FAA4F;IAC5F,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;QAC/B,GAAG,CAAC,KAAK,CAAC,GAAG,EAAE,uBAAc,CAAC,CAAA;KAC/B;IAED,gDAAgD;IAChD,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,+BAAsB,CAAC,CAAA;IACpC,IAAI,MAAM,CAAC,SAAS;QAAE,GAAG,CAAC,GAAG,CAAC,UAAG,MAAM,CAAC,SAAS,MAAG,EAAE,+BAAsB,CAAC,CAAA;IAE7E,OAAO;QACL,KAAK,EAAE;YACL,IAAI,MAAM,CAAC,SAAS,EAAE;gBACpB,OAAO,CAAC,GAAG,CAAC,sEAAsE,CAAC,CAAA;gBACnF,OAAM;aACP;YAED,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE;gBACtB,OAAO,CAAC,GAAG,CAAC,0CAA8B,MAAM,CAAC,IAAI,CAAE,CAAC,CAAA;YAC1D,CAAC,CAAC,CAAA;QACJ,CAAC;QACD,uEAAuE;QACvE,OAAO,EAAE,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS;KAC5C,CAAA;AACH,CAAC;AAED,SAAgB,MAAM,CAAC,UAAmB;IACxC,OAAO,YAAY,CAAC,UAAU,CAAC,CAAA;AACjC,CAAC;AAFD,wBAEC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "temba",
3
- "version": "0.16.0",
3
+ "version": "0.18.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": {
@@ -18,24 +18,26 @@
18
18
  "author": "Bouwe (https://bouwe.io)",
19
19
  "license": "ISC",
20
20
  "devDependencies": {
21
- "@types/cors": "^2.8.13",
22
- "@types/express": "^4.17.17",
23
- "@types/jest": "^29.5.3",
24
- "@types/morgan": "^1.9.4",
25
- "@types/supertest": "^2.0.12",
26
- "@typescript-eslint/eslint-plugin": "^6.0.0",
27
- "@typescript-eslint/parser": "^6.0.0",
28
- "eslint": "^8.45.0",
29
- "eslint-config-prettier": "^8.8.0",
30
- "jest": "^29.6.1",
31
- "jest-extended": "^4.0.0",
32
- "prettier": "^3.0.0",
21
+ "@types/cors": "^2.8.15",
22
+ "@types/express": "^4.17.20",
23
+ "@types/jest": "^29.5.7",
24
+ "@types/morgan": "^1.9.8",
25
+ "@types/supertest": "^2.0.15",
26
+ "@typescript-eslint/eslint-plugin": "^6.10.0",
27
+ "@typescript-eslint/parser": "^6.10.0",
28
+ "eslint": "^8.53.0",
29
+ "eslint-config-prettier": "^9.0.0",
30
+ "jest": "^29.7.0",
31
+ "jest-extended": "^4.0.2",
32
+ "prettier": "^3.0.3",
33
33
  "supertest": "^6.3.3",
34
34
  "ts-jest": "^29.1.1",
35
- "typescript": "^5.1.6"
35
+ "ts-node": "^10.9.1",
36
+ "typescript": "^5.2.2"
36
37
  },
37
38
  "dependencies": {
38
39
  "@rakered/mongo": "^1.6.0",
40
+ "ajv": "^8.12.0",
39
41
  "connect-pause": "^0.1.0",
40
42
  "cors": "^2.8.5",
41
43
  "express": "^4.18.2",
@@ -1,11 +1,12 @@
1
- declare function connectToDatabase(): void;
2
- declare function getAll(resourceName: any): Promise<unknown>;
3
- declare function getById(resourceName: any, id: any): Promise<unknown>;
4
- declare function create(resourceName: any, item: any): Promise<unknown>;
5
- declare function update(resourceName: any, item: any): Promise<unknown>;
6
- declare function replace(resourceName: any, item: any): Promise<unknown>;
7
- declare function deleteById(resourceName: any, id: any): Promise<void>;
8
- declare function deleteAll(resourceName: any): Promise<unknown>;
1
+ import { Item } from './types';
2
+ declare function connectToDatabase(): Promise<void>;
3
+ declare function getAll(resource: string): Promise<unknown[]>;
4
+ declare function getById(resource: string, id: string): Promise<unknown>;
5
+ declare function create(resource: string, item: Item): Promise<unknown>;
6
+ declare function update(resource: string, item: Item): Promise<unknown>;
7
+ declare function replace(resource: string, item: Item): Promise<unknown>;
8
+ declare function deleteById(resource: string, id: string): Promise<void>;
9
+ declare function deleteAll(resource: string): Promise<void>;
9
10
  declare const _default: {
10
11
  connectToDatabase: typeof connectToDatabase;
11
12
  getAll: typeof getAll;