temba 0.17.0 → 0.19.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 (215) hide show
  1. package/README.md +58 -10
  2. package/package.json +17 -17
  3. package/{config → src/config}/index.d.ts +15 -8
  4. package/src/config/index.d.ts.map +1 -0
  5. package/{config → src/config}/index.js +23 -28
  6. package/src/config/index.js.map +1 -0
  7. package/src/delay/delayMiddleware.d.ts +3 -0
  8. package/src/delay/delayMiddleware.d.ts.map +1 -0
  9. package/src/delay/delayMiddleware.js +13 -0
  10. package/src/delay/delayMiddleware.js.map +1 -0
  11. package/src/index.d.ts +6 -0
  12. package/src/index.d.ts.map +1 -0
  13. package/src/index.js +83 -0
  14. package/src/index.js.map +1 -0
  15. package/src/queries/in-memory.d.ts +3 -0
  16. package/src/queries/in-memory.d.ts.map +1 -0
  17. package/src/queries/in-memory.js +61 -0
  18. package/src/queries/in-memory.js.map +1 -0
  19. package/src/queries/mongo.d.ts +3 -0
  20. package/src/queries/mongo.d.ts.map +1 -0
  21. package/src/queries/mongo.js +75 -0
  22. package/src/queries/mongo.js.map +1 -0
  23. package/src/queries/queries.d.ts +2 -0
  24. package/src/queries/queries.d.ts.map +1 -0
  25. package/src/queries/queries.js +10 -0
  26. package/src/queries/queries.js.map +1 -0
  27. package/src/queries/types.d.ts +15 -0
  28. package/src/queries/types.d.ts.map +1 -0
  29. package/src/queries/types.js +2 -0
  30. package/src/queries/types.js.map +1 -0
  31. package/src/requestBodyInterceptor/interceptRequestBody.d.ts +3 -0
  32. package/src/requestBodyInterceptor/interceptRequestBody.d.ts.map +1 -0
  33. package/src/requestBodyInterceptor/interceptRequestBody.js +14 -0
  34. package/src/requestBodyInterceptor/interceptRequestBody.js.map +1 -0
  35. package/src/requestBodyInterceptor/types.d.ts +12 -0
  36. package/src/requestBodyInterceptor/types.d.ts.map +1 -0
  37. package/src/requestBodyInterceptor/types.js +2 -0
  38. package/src/requestBodyInterceptor/types.js.map +1 -0
  39. package/src/requestHandlers/delete.d.ts +12 -0
  40. package/src/requestHandlers/delete.d.ts.map +1 -0
  41. package/src/requestHandlers/delete.js +22 -0
  42. package/src/requestHandlers/delete.js.map +1 -0
  43. package/src/requestHandlers/get.d.ts +22 -0
  44. package/src/requestHandlers/get.d.ts.map +1 -0
  45. package/src/requestHandlers/get.js +47 -0
  46. package/src/requestHandlers/get.js.map +1 -0
  47. package/src/requestHandlers/index.d.ts +54 -0
  48. package/src/requestHandlers/index.d.ts.map +1 -0
  49. package/src/requestHandlers/index.js +21 -0
  50. package/src/requestHandlers/index.js.map +1 -0
  51. package/src/requestHandlers/patch.d.ts +9 -0
  52. package/src/requestHandlers/patch.d.ts.map +1 -0
  53. package/src/requestHandlers/patch.js +35 -0
  54. package/src/requestHandlers/patch.js.map +1 -0
  55. package/src/requestHandlers/post.d.ts +18 -0
  56. package/src/requestHandlers/post.d.ts.map +1 -0
  57. package/src/requestHandlers/post.js +37 -0
  58. package/src/requestHandlers/post.js.map +1 -0
  59. package/src/requestHandlers/put.d.ts +9 -0
  60. package/src/requestHandlers/put.d.ts.map +1 -0
  61. package/src/requestHandlers/put.js +35 -0
  62. package/src/requestHandlers/put.js.map +1 -0
  63. package/src/requestHandlers/types.d.ts +38 -0
  64. package/src/requestHandlers/types.d.ts.map +1 -0
  65. package/src/requestHandlers/types.js +2 -0
  66. package/src/requestHandlers/types.js.map +1 -0
  67. package/src/requestHandlers/utils.d.ts +2 -0
  68. package/src/requestHandlers/utils.d.ts.map +1 -0
  69. package/src/requestHandlers/utils.js +6 -0
  70. package/src/requestHandlers/utils.js.map +1 -0
  71. package/src/resourceRouter.d.ts +5 -0
  72. package/src/resourceRouter.d.ts.map +1 -0
  73. package/src/resourceRouter.js +95 -0
  74. package/src/resourceRouter.js.map +1 -0
  75. package/src/responseBodyInterceptor/interceptResponseBody.d.ts +3 -0
  76. package/src/responseBodyInterceptor/interceptResponseBody.d.ts.map +1 -0
  77. package/src/responseBodyInterceptor/interceptResponseBody.js +7 -0
  78. package/src/responseBodyInterceptor/interceptResponseBody.js.map +1 -0
  79. package/src/responseBodyInterceptor/types.d.ts +11 -0
  80. package/src/responseBodyInterceptor/types.d.ts.map +1 -0
  81. package/src/responseBodyInterceptor/types.js +2 -0
  82. package/src/responseBodyInterceptor/types.js.map +1 -0
  83. package/src/schema/compile.d.ts +3 -0
  84. package/src/schema/compile.d.ts.map +1 -0
  85. package/src/schema/compile.js +26 -0
  86. package/src/schema/compile.js.map +1 -0
  87. package/src/schema/types.d.ts +25 -0
  88. package/src/schema/types.d.ts.map +1 -0
  89. package/src/schema/types.js +2 -0
  90. package/{routes → src/schema}/types.js.map +1 -1
  91. package/src/schema/validate.d.ts +4 -0
  92. package/src/schema/validate.d.ts.map +1 -0
  93. package/src/schema/validate.js +14 -0
  94. package/src/schema/validate.js.map +1 -0
  95. package/src/urls/urlParser.d.ts +5 -0
  96. package/src/urls/urlParser.d.ts.map +1 -0
  97. package/src/urls/urlParser.js +9 -0
  98. package/src/urls/urlParser.js.map +1 -0
  99. package/test/integration/api-prefix.test.d.ts +2 -0
  100. package/test/integration/api-prefix.test.d.ts.map +1 -0
  101. package/test/integration/api-prefix.test.js +69 -0
  102. package/test/integration/api-prefix.test.js.map +1 -0
  103. package/test/integration/createServer.d.ts +4 -0
  104. package/test/integration/createServer.d.ts.map +1 -0
  105. package/test/integration/createServer.js +4 -0
  106. package/test/integration/createServer.js.map +1 -0
  107. package/test/integration/crud.test.d.ts +2 -0
  108. package/test/integration/crud.test.d.ts.map +1 -0
  109. package/test/integration/crud.test.js +173 -0
  110. package/test/integration/crud.test.js.map +1 -0
  111. package/test/integration/custom-router.test.d.ts +2 -0
  112. package/test/integration/custom-router.test.d.ts.map +1 -0
  113. package/test/integration/custom-router.test.js +74 -0
  114. package/test/integration/custom-router.test.js.map +1 -0
  115. package/test/integration/head-method.test.d.ts +2 -0
  116. package/test/integration/head-method.test.d.ts.map +1 -0
  117. package/test/integration/head-method.test.js +38 -0
  118. package/test/integration/head-method.test.js.map +1 -0
  119. package/test/integration/options-method.test.d.ts +2 -0
  120. package/test/integration/options-method.test.d.ts.map +1 -0
  121. package/test/integration/options-method.test.js +30 -0
  122. package/test/integration/options-method.test.js.map +1 -0
  123. package/test/integration/requestBodyInterceptor/requestBodyInterceptor-change-requestBody.test.d.ts +2 -0
  124. package/test/integration/requestBodyInterceptor/requestBodyInterceptor-change-requestBody.test.d.ts.map +1 -0
  125. package/test/integration/requestBodyInterceptor/requestBodyInterceptor-change-requestBody.test.js +76 -0
  126. package/test/integration/requestBodyInterceptor/requestBodyInterceptor-change-requestBody.test.js.map +1 -0
  127. package/test/integration/requestBodyInterceptor/requestBodyInterceptor-error-string.test.d.ts +2 -0
  128. package/test/integration/requestBodyInterceptor/requestBodyInterceptor-error-string.test.d.ts.map +1 -0
  129. package/test/integration/requestBodyInterceptor/requestBodyInterceptor-error-string.test.js +60 -0
  130. package/test/integration/requestBodyInterceptor/requestBodyInterceptor-error-string.test.js.map +1 -0
  131. package/test/integration/requestBodyInterceptor/requestBodyInterceptor-invalid-return-types.test.d.ts +2 -0
  132. package/test/integration/requestBodyInterceptor/requestBodyInterceptor-invalid-return-types.test.d.ts.map +1 -0
  133. package/test/integration/requestBodyInterceptor/requestBodyInterceptor-invalid-return-types.test.js +89 -0
  134. package/test/integration/requestBodyInterceptor/requestBodyInterceptor-invalid-return-types.test.js.map +1 -0
  135. package/test/integration/requestBodyInterceptor/requestBodyInterceptor-void.test.d.ts +2 -0
  136. package/test/integration/requestBodyInterceptor/requestBodyInterceptor-void.test.d.ts.map +1 -0
  137. package/test/integration/requestBodyInterceptor/requestBodyInterceptor-void.test.js +47 -0
  138. package/test/integration/requestBodyInterceptor/requestBodyInterceptor-void.test.js.map +1 -0
  139. package/test/integration/responseBodyInterceptor.test.d.ts +2 -0
  140. package/test/integration/responseBodyInterceptor.test.d.ts.map +1 -0
  141. package/test/integration/responseBodyInterceptor.test.js +107 -0
  142. package/test/integration/responseBodyInterceptor.test.js.map +1 -0
  143. package/test/integration/returnNullFields.test.d.ts +2 -0
  144. package/test/integration/returnNullFields.test.d.ts.map +1 -0
  145. package/test/integration/returnNullFields.test.js +51 -0
  146. package/test/integration/returnNullFields.test.js.map +1 -0
  147. package/test/integration/root-url.test.d.ts +2 -0
  148. package/test/integration/root-url.test.d.ts.map +1 -0
  149. package/test/integration/root-url.test.js +29 -0
  150. package/test/integration/root-url.test.js.map +1 -0
  151. package/test/integration/schema-validation.test.d.ts +2 -0
  152. package/test/integration/schema-validation.test.d.ts.map +1 -0
  153. package/test/integration/schema-validation.test.js +169 -0
  154. package/test/integration/schema-validation.test.js.map +1 -0
  155. package/test/unit/config/config.test.d.ts +2 -0
  156. package/test/unit/config/config.test.d.ts.map +1 -0
  157. package/test/unit/config/config.test.js +121 -0
  158. package/test/unit/config/config.test.js.map +1 -0
  159. package/test/unit/urls/urlParser.test.d.ts +2 -0
  160. package/test/unit/urls/urlParser.test.d.ts.map +1 -0
  161. package/test/unit/urls/urlParser.test.js +43 -0
  162. package/test/unit/urls/urlParser.test.js.map +1 -0
  163. package/tsconfig.tsbuildinfo +1 -0
  164. package/vitest.config.d.ts +3 -0
  165. package/vitest.config.d.ts.map +1 -0
  166. package/vitest.config.js +10 -0
  167. package/vitest.config.js.map +1 -0
  168. package/config/index.js.map +0 -1
  169. package/delay/delayMiddleware.d.ts +0 -2
  170. package/delay/delayMiddleware.js +0 -16
  171. package/delay/delayMiddleware.js.map +0 -1
  172. package/index.d.ts +0 -5
  173. package/index.js +0 -94
  174. package/index.js.map +0 -1
  175. package/queries/in-memory.d.ts +0 -19
  176. package/queries/in-memory.js +0 -66
  177. package/queries/in-memory.js.map +0 -1
  178. package/queries/mongo.d.ts +0 -19
  179. package/queries/mongo.js +0 -106
  180. package/queries/mongo.js.map +0 -1
  181. package/queries/queries.d.ts +0 -20
  182. package/queries/queries.js +0 -17
  183. package/queries/queries.js.map +0 -1
  184. package/routes/delete.d.ts +0 -4
  185. package/routes/delete.js +0 -39
  186. package/routes/delete.js.map +0 -1
  187. package/routes/get.d.ts +0 -4
  188. package/routes/get.js +0 -71
  189. package/routes/get.js.map +0 -1
  190. package/routes/interceptors.d.ts +0 -3
  191. package/routes/interceptors.js +0 -22
  192. package/routes/interceptors.js.map +0 -1
  193. package/routes/patch.d.ts +0 -4
  194. package/routes/patch.js +0 -47
  195. package/routes/patch.js.map +0 -1
  196. package/routes/post.d.ts +0 -4
  197. package/routes/post.js +0 -47
  198. package/routes/post.js.map +0 -1
  199. package/routes/put.d.ts +0 -4
  200. package/routes/put.js +0 -47
  201. package/routes/put.js.map +0 -1
  202. package/routes/routes.d.ts +0 -6
  203. package/routes/routes.js +0 -61
  204. package/routes/routes.js.map +0 -1
  205. package/routes/types.d.ts +0 -17
  206. package/routes/types.js +0 -3
  207. package/routes/utils.d.ts +0 -3
  208. package/routes/utils.js +0 -8
  209. package/routes/utils.js.map +0 -1
  210. package/urls/urlMiddleware.d.ts +0 -3
  211. package/urls/urlMiddleware.js +0 -30
  212. package/urls/urlMiddleware.js.map +0 -1
  213. package/urls/urlParser.d.ts +0 -5
  214. package/urls/urlParser.js +0 -13
  215. package/urls/urlParser.js.map +0 -1
@@ -0,0 +1,107 @@
1
+ import { describe, beforeEach, test, expect } from 'vitest';
2
+ import request from 'supertest';
3
+ import createServer from './createServer';
4
+ describe('responseBodyInterceptor unusual (but allowed) implementations', () => {
5
+ const noReturnValues = [undefined, null];
6
+ test.each(noReturnValues)('When responseBodyInterceptor returns nothing, return original response body', async (returnValue) => {
7
+ const tembaServer = createServer({
8
+ responseBodyInterceptor: () => {
9
+ //do not return anything when returnValue is undefined
10
+ if (typeof returnValue !== 'undefined')
11
+ return returnValue;
12
+ },
13
+ });
14
+ // Delete all items.
15
+ await request(tembaServer).delete('/stuff');
16
+ // As the responseBodyInterceptor returns nothing, the response body should be the same
17
+ // as it would be without the responseBodyInterceptor.
18
+ const response = await request(tembaServer).get('/stuff');
19
+ expect(response.statusCode).toEqual(200);
20
+ expect(response.text).toEqual('[]');
21
+ // Create an item
22
+ const { body: { id: newId }, } = await request(tembaServer).post('/stuff').send({ name: 'newItem' });
23
+ // As the responseBodyInterceptor returns nothing, the response body should be the same
24
+ // as it would be without the responseBodyInterceptor.
25
+ const response2 = await request(tembaServer).get('/stuff');
26
+ expect(response2.body.length).toBe(1);
27
+ expect(response2.body[0].name).toBe('newItem');
28
+ // Now get the item by its id, which should also just return the same item.
29
+ const response3 = await request(tembaServer).get('/stuff/' + newId);
30
+ expect(response3.body.name).toEqual('newItem');
31
+ });
32
+ test('When responseBodyInterceptor throws an exception, return a 500 status with error details', async () => {
33
+ const tembaServer = createServer({
34
+ responseBodyInterceptor: () => {
35
+ throw new Error('Something went wrong');
36
+ },
37
+ });
38
+ const response = await request(tembaServer).get('/stuff');
39
+ expect(response.statusCode).toEqual(500);
40
+ expect(response.body.message).toEqual(`Something went wrong`);
41
+ });
42
+ test('When responseBodyInterceptor does not return an object or array, still return the intercepted value', async () => {
43
+ const tembaServer = createServer({
44
+ responseBodyInterceptor: (info) => {
45
+ if ('id' in info) {
46
+ return 'A string, instead of an object';
47
+ }
48
+ else {
49
+ return 'A string, instead of an array';
50
+ }
51
+ },
52
+ });
53
+ const { body: { id }, } = await request(tembaServer).post('/stuff').send({ name: 'newItem' });
54
+ const response = await request(tembaServer).get('/stuff');
55
+ expect(response.statusCode).toEqual(200);
56
+ expect(response.body).toEqual('A string, instead of an array');
57
+ const response2 = await request(tembaServer).get('/stuff/' + id);
58
+ expect(response2.statusCode).toEqual(200);
59
+ expect(response2.body).toEqual('A string, instead of an object');
60
+ });
61
+ });
62
+ describe('responseBodyInterceptor returns an updated response', () => {
63
+ const tembaServer = createServer({
64
+ responseBodyInterceptor: (info) => {
65
+ if (info.resource === 'stuff') {
66
+ if ('id' in info) {
67
+ return { ...info.body, extra: 'stuff' };
68
+ }
69
+ else {
70
+ return info.body.map((item, index) => ({
71
+ ...item,
72
+ extra: 'stuff ' + index,
73
+ }));
74
+ }
75
+ }
76
+ },
77
+ });
78
+ beforeEach(async () => {
79
+ // Delete all items
80
+ await request(tembaServer).delete('/stuff');
81
+ });
82
+ test('GET a collection just returns the same collection', async () => {
83
+ // Create 2 items
84
+ await request(tembaServer).post('/stuff').send({ name: 'newItem1' });
85
+ await request(tembaServer).post('/stuff').send({ name: 'newItem2' });
86
+ // Now get the collection, which should have extra stuff
87
+ const getAllResponse = await request(tembaServer).get('/stuff');
88
+ expect(getAllResponse.status).toBe(200);
89
+ expect(getAllResponse.body.length).toBe(2);
90
+ expect(getAllResponse.body[0].name).toBe('newItem1');
91
+ expect(getAllResponse.body[0].extra).toBe('stuff 0');
92
+ expect(getAllResponse.body[1].name).toBe('newItem2');
93
+ expect(getAllResponse.body[1].extra).toBe('stuff 1');
94
+ });
95
+ test('GET an item just returns the same item', async () => {
96
+ // Create an item
97
+ const newItem = { name: 'newItem' };
98
+ const { body: { id }, } = await request(tembaServer).post('/stuff').send(newItem);
99
+ // Now get the item, which should just return the same item.
100
+ const response = await request(tembaServer).get('/stuff/' + id);
101
+ expect(response.statusCode).toEqual(200);
102
+ expect(response.body.name).toEqual('newItem');
103
+ expect(response.body.id).toEqual(id);
104
+ expect(response.body.extra).toEqual('stuff');
105
+ });
106
+ });
107
+ //# sourceMappingURL=responseBodyInterceptor.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"responseBodyInterceptor.test.js","sourceRoot":"","sources":["../../../test/integration/responseBodyInterceptor.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=returnNullFields.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"returnNullFields.test.d.ts","sourceRoot":"","sources":["../../../test/integration/returnNullFields.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,51 @@
1
+ import { test, expect } from 'vitest';
2
+ import request from 'supertest';
3
+ import createServer from './createServer';
4
+ /*
5
+ Tests when configuring returnNullFields.
6
+ */
7
+ test.each([true, false])('returnNullFields setting is %s', async (returnNullFields) => {
8
+ const tembaServer = createServer({ returnNullFields });
9
+ // Create a car
10
+ const createResponse = await request(tembaServer)
11
+ .post('/cars')
12
+ .send({ brand: 'Mercedes-Benz', color: null });
13
+ expect(createResponse.body.brand).toBe('Mercedes-Benz');
14
+ if (returnNullFields)
15
+ expect(createResponse.body.color).toBeNull();
16
+ else
17
+ expect(createResponse.body.color).toBeUndefined();
18
+ // Fetch all cars
19
+ const getAllResponse = await request(tembaServer).get('/cars');
20
+ expect(getAllResponse.body[0].brand).toBe('Mercedes-Benz');
21
+ if (returnNullFields)
22
+ expect(getAllResponse.body[0].color).toBeNull();
23
+ else
24
+ expect(getAllResponse.body[0].color).toBeUndefined();
25
+ // Fetch one car
26
+ const getOneResponse = await request(tembaServer).get('/cars/' + createResponse.body.id);
27
+ expect(getOneResponse.body.brand).toBe('Mercedes-Benz');
28
+ if (returnNullFields)
29
+ expect(getOneResponse.body.color).toBeNull();
30
+ else
31
+ expect(getOneResponse.body.color).toBeUndefined();
32
+ // Replace one car
33
+ const replaceResponse = await request(tembaServer)
34
+ .put('/cars/' + createResponse.body.id)
35
+ .send({ brand: 'Mercedes-Benz', color: null });
36
+ expect(replaceResponse.body.brand).toBe('Mercedes-Benz');
37
+ if (returnNullFields)
38
+ expect(replaceResponse.body.color).toBeNull();
39
+ else
40
+ expect(replaceResponse.body.color).toBeUndefined();
41
+ // Update one car
42
+ const updateResponse = await request(tembaServer)
43
+ .patch('/cars/' + createResponse.body.id)
44
+ .send({ brand: 'Mercedes-Benz', color: null });
45
+ expect(updateResponse.body.brand).toBe('Mercedes-Benz');
46
+ if (returnNullFields)
47
+ expect(updateResponse.body.color).toBeNull();
48
+ else
49
+ expect(updateResponse.body.color).toBeUndefined();
50
+ });
51
+ //# sourceMappingURL=returnNullFields.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"returnNullFields.test.js","sourceRoot":"","sources":["../../../test/integration/returnNullFields.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=root-url.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"root-url.test.d.ts","sourceRoot":"","sources":["../../../test/integration/root-url.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,29 @@
1
+ import { test, expect } from 'vitest';
2
+ import request from 'supertest';
3
+ import createServer from './createServer';
4
+ /*
5
+ Tests on the root URL: "/"
6
+ */
7
+ // This Temba server is created with the default configuration, i.e. no config object is supplied.
8
+ const tembaServer = createServer();
9
+ test('GET on root URL returns welcome text', async () => {
10
+ const response = await request(tembaServer).get('/');
11
+ expect(response.statusCode).toEqual(200);
12
+ expect(response.text).toEqual('It works! ツ');
13
+ });
14
+ test('POST on root URL returns Method Not Allowed error', async () => {
15
+ const response = await request(tembaServer).post('/');
16
+ expect(response.statusCode).toEqual(405);
17
+ expect(response.body.message).toEqual('Method Not Allowed');
18
+ });
19
+ test('PUT on root URL returns Method Not Allowed error', async () => {
20
+ const response = await request(tembaServer).put('/');
21
+ expect(response.statusCode).toEqual(405);
22
+ expect(response.body.message).toEqual('Method Not Allowed');
23
+ });
24
+ test('DELETE on root URL returns Method Not Allowed error', async () => {
25
+ const response = await request(tembaServer).delete('/');
26
+ expect(response.statusCode).toEqual(405);
27
+ expect(response.body.message).toEqual('Method Not Allowed');
28
+ });
29
+ //# sourceMappingURL=root-url.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"root-url.test.js","sourceRoot":"","sources":["../../../test/integration/root-url.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AACrC,OAAO,OAAO,MAAM,WAAW,CAAA;AAC/B,OAAO,YAAY,MAAM,gBAAgB,CAAA;AAEzC;;EAEE;AAEF,kGAAkG;AAClG,MAAM,WAAW,GAAG,YAAY,EAAE,CAAA;AAElC,IAAI,CAAC,sCAAsC,EAAE,KAAK,IAAI,EAAE;IACtD,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,WAAW,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;IAEpD,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;IACxC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,aAAa,CAAC,CAAA;AAC9C,CAAC,CAAC,CAAA;AAEF,IAAI,CAAC,mDAAmD,EAAE,KAAK,IAAI,EAAE;IACnE,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;IAErD,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;IACxC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,oBAAoB,CAAC,CAAA;AAC7D,CAAC,CAAC,CAAA;AAEF,IAAI,CAAC,kDAAkD,EAAE,KAAK,IAAI,EAAE;IAClE,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,WAAW,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;IAEpD,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;IACxC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,oBAAoB,CAAC,CAAA;AAC7D,CAAC,CAAC,CAAA;AAEF,IAAI,CAAC,qDAAqD,EAAE,KAAK,IAAI,EAAE;IACrE,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,WAAW,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;IAEvD,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;IACxC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,oBAAoB,CAAC,CAAA;AAC7D,CAAC,CAAC,CAAA"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=schema-validation.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema-validation.test.d.ts","sourceRoot":"","sources":["../../../test/integration/schema-validation.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,169 @@
1
+ import { test, expect } from 'vitest';
2
+ import request from 'supertest';
3
+ import createServer from './createServer';
4
+ /*
5
+ Tests for JSON Schema validation
6
+ */
7
+ const resourceUrl = `/cars/`;
8
+ test('Schema validation POST/PUT/PATCH', async () => {
9
+ const schemaCreateReplace = {
10
+ type: 'object',
11
+ properties: {
12
+ price: { type: 'integer' },
13
+ brand: { type: 'string' },
14
+ },
15
+ required: ['brand'],
16
+ additionalProperties: false,
17
+ };
18
+ const schemaUpdate = { ...schemaCreateReplace, required: [] };
19
+ const tembaServer = createServer({
20
+ schemas: {
21
+ cars: {
22
+ post: schemaCreateReplace,
23
+ put: schemaCreateReplace,
24
+ patch: schemaUpdate,
25
+ },
26
+ },
27
+ });
28
+ // POST only the required brand
29
+ let response = await request(tembaServer)
30
+ .post(resourceUrl)
31
+ .send({ brand: 'Mercedes-Benz' })
32
+ .set('Content-Type', 'application/json');
33
+ expect(response.statusCode).toEqual(201);
34
+ expect(response.body.message).toBeUndefined();
35
+ const mercedesId = response.body.id;
36
+ // PUT the required brand and the optional price
37
+ response = await request(tembaServer)
38
+ .put(resourceUrl + mercedesId)
39
+ .send({ brand: 'Mercedes-Benz', price: 100000 })
40
+ .set('Content-Type', 'application/json');
41
+ expect(response.statusCode).toEqual(200);
42
+ expect(response.body.message).toBeUndefined();
43
+ // PUT without the required brand
44
+ response = await request(tembaServer)
45
+ .put(resourceUrl + mercedesId)
46
+ .send({})
47
+ .set('Content-Type', 'application/json');
48
+ expect(response.statusCode).toEqual(400);
49
+ expect(response.body.message.length).toBeGreaterThan(0);
50
+ // PUT with an unknown property
51
+ response = await request(tembaServer)
52
+ .put(resourceUrl + mercedesId)
53
+ .send({ unknown: 'property' })
54
+ .set('Content-Type', 'application/json');
55
+ expect(response.statusCode).toEqual(400);
56
+ expect(response.body.message.length).toBeGreaterThan(0);
57
+ // PATCH with an empty body, because none of the properties are required
58
+ response = await request(tembaServer)
59
+ .patch(resourceUrl + mercedesId)
60
+ .send({})
61
+ .set('Content-Type', 'application/json');
62
+ expect(response.statusCode).toEqual(200);
63
+ expect(response.body.message).toBeUndefined();
64
+ // PATCH with a brand
65
+ response = await request(tembaServer)
66
+ .patch(resourceUrl + mercedesId)
67
+ .send({ brand: 'Mercedes-Benz' })
68
+ .set('Content-Type', 'application/json');
69
+ expect(response.statusCode).toEqual(200);
70
+ expect(response.body.message).toBeUndefined();
71
+ // PATCH with a price
72
+ response = await request(tembaServer)
73
+ .patch(resourceUrl + mercedesId)
74
+ .send({ price: 100000 })
75
+ .set('Content-Type', 'application/json');
76
+ expect(response.statusCode).toEqual(200);
77
+ expect(response.body.message).toBeUndefined();
78
+ // PATCH with a brand and price
79
+ response = await request(tembaServer)
80
+ .patch(resourceUrl + mercedesId)
81
+ .send({ brand: 'Mercedes-Benz', price: 100000 })
82
+ .set('Content-Type', 'application/json');
83
+ expect(response.statusCode).toEqual(200);
84
+ expect(response.body.message).toBeUndefined();
85
+ // PATCH with an unknown property
86
+ response = await request(tembaServer)
87
+ .patch(resourceUrl + mercedesId)
88
+ .send({ unknown: 'property' })
89
+ .set('Content-Type', 'application/json');
90
+ expect(response.statusCode).toEqual(400);
91
+ expect(response.body.message.length).toBeGreaterThan(0);
92
+ // POST the required brand and the optional price
93
+ response = await request(tembaServer)
94
+ .post(resourceUrl)
95
+ .send({ brand: 'BMW', price: 100000 })
96
+ .set('Content-Type', 'application/json');
97
+ expect(response.statusCode).toEqual(201);
98
+ expect(response.body.message).toBeUndefined();
99
+ // POST without the required brand
100
+ response = await request(tembaServer)
101
+ .post(resourceUrl)
102
+ .send({})
103
+ .set('Content-Type', 'application/json');
104
+ expect(response.statusCode).toEqual(400);
105
+ expect(response.body.message.length).toBeGreaterThan(0);
106
+ // POST an invalid brand
107
+ response = await request(tembaServer)
108
+ .post(resourceUrl)
109
+ .send({ brand: 123 })
110
+ .set('Content-Type', 'application/json');
111
+ expect(response.statusCode).toEqual(400);
112
+ expect(response.body.message.length).toBeGreaterThan(0);
113
+ // POST the required brand and an invalid price
114
+ response = await request(tembaServer)
115
+ .post(resourceUrl)
116
+ .send({ brand: 'Mercedes-Benz', price: 'not a number' })
117
+ .set('Content-Type', 'application/json');
118
+ expect(response.statusCode).toEqual(400);
119
+ expect(response.body.message.length).toBeGreaterThan(0);
120
+ // POST with an unknown property
121
+ response = await request(tembaServer)
122
+ .post(resourceUrl)
123
+ .send({ unknown: 'property' })
124
+ .set('Content-Type', 'application/json');
125
+ expect(response.statusCode).toEqual(400);
126
+ expect(response.body.message.length).toBeGreaterThan(0);
127
+ });
128
+ test('Schema validation per resource', async () => {
129
+ const schema = {
130
+ type: 'object',
131
+ properties: {
132
+ brand: { type: 'string' },
133
+ },
134
+ required: ['brand'],
135
+ };
136
+ const tembaServer = createServer({
137
+ schemas: {
138
+ cars: {
139
+ post: schema,
140
+ },
141
+ },
142
+ });
143
+ // A car with a brand is valid
144
+ let response = await request(tembaServer)
145
+ .post(resourceUrl)
146
+ .send({ brand: 'Mercedes-Benz' })
147
+ .set('Content-Type', 'application/json');
148
+ expect(response.statusCode).toEqual(201);
149
+ // A car without a brand is invalid
150
+ response = await request(tembaServer)
151
+ .post(resourceUrl)
152
+ .send({})
153
+ .set('Content-Type', 'application/json');
154
+ expect(response.statusCode).toEqual(400);
155
+ // However, the bikes resource does not have a schema,
156
+ // so a bike without a brand is valid
157
+ response = await request(tembaServer)
158
+ .post('/bikes/')
159
+ .send({})
160
+ .set('Content-Type', 'application/json');
161
+ expect(response.statusCode).toEqual(201);
162
+ // You can even POST nonsense to the bikes resource
163
+ response = await request(tembaServer)
164
+ .post('/bikes/')
165
+ .send({ foo: 'bar' })
166
+ .set('Content-Type', 'application/json');
167
+ expect(response.statusCode).toEqual(201);
168
+ });
169
+ //# sourceMappingURL=schema-validation.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema-validation.test.js","sourceRoot":"","sources":["../../../test/integration/schema-validation.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AACrC,OAAO,OAAO,MAAM,WAAW,CAAA;AAC/B,OAAO,YAAY,MAAM,gBAAgB,CAAA;AAGzC;;EAEE;AAEF,MAAM,WAAW,GAAG,QAAQ,CAAA;AAE5B,IAAI,CAAC,kCAAkC,EAAE,KAAK,IAAI,EAAE;IAClD,MAAM,mBAAmB,GAAG;QAC1B,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE;YACV,KAAK,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE;YAC1B,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;SAC1B;QACD,QAAQ,EAAE,CAAC,OAAO,CAAC;QACnB,oBAAoB,EAAE,KAAK;KAC5B,CAAA;IACD,MAAM,YAAY,GAAG,EAAE,GAAG,mBAAmB,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAA;IAE7D,MAAM,WAAW,GAAG,YAAY,CAAC;QAC/B,OAAO,EAAE;YACP,IAAI,EAAE;gBACJ,IAAI,EAAE,mBAAmB;gBACzB,GAAG,EAAE,mBAAmB;gBACxB,KAAK,EAAE,YAAY;aACpB;SACF;KACmB,CAAC,CAAA;IAEvB,+BAA+B;IAC/B,IAAI,QAAQ,GAAG,MAAM,OAAO,CAAC,WAAW,CAAC;SACtC,IAAI,CAAC,WAAW,CAAC;SACjB,IAAI,CAAC,EAAE,KAAK,EAAE,eAAe,EAAE,CAAC;SAChC,GAAG,CAAC,cAAc,EAAE,kBAAkB,CAAC,CAAA;IAC1C,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;IACxC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,aAAa,EAAE,CAAA;IAC7C,MAAM,UAAU,GAAG,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAA;IAEnC,gDAAgD;IAChD,QAAQ,GAAG,MAAM,OAAO,CAAC,WAAW,CAAC;SAClC,GAAG,CAAC,WAAW,GAAG,UAAU,CAAC;SAC7B,IAAI,CAAC,EAAE,KAAK,EAAE,eAAe,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;SAC/C,GAAG,CAAC,cAAc,EAAE,kBAAkB,CAAC,CAAA;IAC1C,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;IACxC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,aAAa,EAAE,CAAA;IAE7C,iCAAiC;IACjC,QAAQ,GAAG,MAAM,OAAO,CAAC,WAAW,CAAC;SAClC,GAAG,CAAC,WAAW,GAAG,UAAU,CAAC;SAC7B,IAAI,CAAC,EAAE,CAAC;SACR,GAAG,CAAC,cAAc,EAAE,kBAAkB,CAAC,CAAA;IAC1C,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;IACxC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAA;IAEvD,+BAA+B;IAC/B,QAAQ,GAAG,MAAM,OAAO,CAAC,WAAW,CAAC;SAClC,GAAG,CAAC,WAAW,GAAG,UAAU,CAAC;SAC7B,IAAI,CAAC,EAAE,OAAO,EAAE,UAAU,EAAE,CAAC;SAC7B,GAAG,CAAC,cAAc,EAAE,kBAAkB,CAAC,CAAA;IAC1C,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;IACxC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAA;IAEvD,wEAAwE;IACxE,QAAQ,GAAG,MAAM,OAAO,CAAC,WAAW,CAAC;SAClC,KAAK,CAAC,WAAW,GAAG,UAAU,CAAC;SAC/B,IAAI,CAAC,EAAE,CAAC;SACR,GAAG,CAAC,cAAc,EAAE,kBAAkB,CAAC,CAAA;IAC1C,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;IACxC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,aAAa,EAAE,CAAA;IAE7C,qBAAqB;IACrB,QAAQ,GAAG,MAAM,OAAO,CAAC,WAAW,CAAC;SAClC,KAAK,CAAC,WAAW,GAAG,UAAU,CAAC;SAC/B,IAAI,CAAC,EAAE,KAAK,EAAE,eAAe,EAAE,CAAC;SAChC,GAAG,CAAC,cAAc,EAAE,kBAAkB,CAAC,CAAA;IAC1C,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;IACxC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,aAAa,EAAE,CAAA;IAE7C,qBAAqB;IACrB,QAAQ,GAAG,MAAM,OAAO,CAAC,WAAW,CAAC;SAClC,KAAK,CAAC,WAAW,GAAG,UAAU,CAAC;SAC/B,IAAI,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;SACvB,GAAG,CAAC,cAAc,EAAE,kBAAkB,CAAC,CAAA;IAC1C,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;IACxC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,aAAa,EAAE,CAAA;IAE7C,+BAA+B;IAC/B,QAAQ,GAAG,MAAM,OAAO,CAAC,WAAW,CAAC;SAClC,KAAK,CAAC,WAAW,GAAG,UAAU,CAAC;SAC/B,IAAI,CAAC,EAAE,KAAK,EAAE,eAAe,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;SAC/C,GAAG,CAAC,cAAc,EAAE,kBAAkB,CAAC,CAAA;IAC1C,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;IACxC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,aAAa,EAAE,CAAA;IAE7C,iCAAiC;IACjC,QAAQ,GAAG,MAAM,OAAO,CAAC,WAAW,CAAC;SAClC,KAAK,CAAC,WAAW,GAAG,UAAU,CAAC;SAC/B,IAAI,CAAC,EAAE,OAAO,EAAE,UAAU,EAAE,CAAC;SAC7B,GAAG,CAAC,cAAc,EAAE,kBAAkB,CAAC,CAAA;IAC1C,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;IACxC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAA;IAEvD,iDAAiD;IACjD,QAAQ,GAAG,MAAM,OAAO,CAAC,WAAW,CAAC;SAClC,IAAI,CAAC,WAAW,CAAC;SACjB,IAAI,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;SACrC,GAAG,CAAC,cAAc,EAAE,kBAAkB,CAAC,CAAA;IAC1C,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;IACxC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,aAAa,EAAE,CAAA;IAE7C,kCAAkC;IAClC,QAAQ,GAAG,MAAM,OAAO,CAAC,WAAW,CAAC;SAClC,IAAI,CAAC,WAAW,CAAC;SACjB,IAAI,CAAC,EAAE,CAAC;SACR,GAAG,CAAC,cAAc,EAAE,kBAAkB,CAAC,CAAA;IAC1C,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;IACxC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAA;IAEvD,wBAAwB;IACxB,QAAQ,GAAG,MAAM,OAAO,CAAC,WAAW,CAAC;SAClC,IAAI,CAAC,WAAW,CAAC;SACjB,IAAI,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC;SACpB,GAAG,CAAC,cAAc,EAAE,kBAAkB,CAAC,CAAA;IAC1C,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;IACxC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAA;IAEvD,+CAA+C;IAC/C,QAAQ,GAAG,MAAM,OAAO,CAAC,WAAW,CAAC;SAClC,IAAI,CAAC,WAAW,CAAC;SACjB,IAAI,CAAC,EAAE,KAAK,EAAE,eAAe,EAAE,KAAK,EAAE,cAAc,EAAE,CAAC;SACvD,GAAG,CAAC,cAAc,EAAE,kBAAkB,CAAC,CAAA;IAC1C,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;IACxC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAA;IAEvD,gCAAgC;IAChC,QAAQ,GAAG,MAAM,OAAO,CAAC,WAAW,CAAC;SAClC,IAAI,CAAC,WAAW,CAAC;SACjB,IAAI,CAAC,EAAE,OAAO,EAAE,UAAU,EAAE,CAAC;SAC7B,GAAG,CAAC,cAAc,EAAE,kBAAkB,CAAC,CAAA;IAC1C,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;IACxC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAA;AACzD,CAAC,CAAC,CAAA;AAEF,IAAI,CAAC,gCAAgC,EAAE,KAAK,IAAI,EAAE;IAChD,MAAM,MAAM,GAAG;QACb,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE;YACV,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;SAC1B;QACD,QAAQ,EAAE,CAAC,OAAO,CAAC;KACpB,CAAA;IAED,MAAM,WAAW,GAAG,YAAY,CAAC;QAC/B,OAAO,EAAE;YACP,IAAI,EAAE;gBACJ,IAAI,EAAE,MAAM;aACb;SACF;KACmB,CAAC,CAAA;IAEvB,8BAA8B;IAC9B,IAAI,QAAQ,GAAG,MAAM,OAAO,CAAC,WAAW,CAAC;SACtC,IAAI,CAAC,WAAW,CAAC;SACjB,IAAI,CAAC,EAAE,KAAK,EAAE,eAAe,EAAE,CAAC;SAChC,GAAG,CAAC,cAAc,EAAE,kBAAkB,CAAC,CAAA;IAC1C,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;IAExC,mCAAmC;IACnC,QAAQ,GAAG,MAAM,OAAO,CAAC,WAAW,CAAC;SAClC,IAAI,CAAC,WAAW,CAAC;SACjB,IAAI,CAAC,EAAE,CAAC;SACR,GAAG,CAAC,cAAc,EAAE,kBAAkB,CAAC,CAAA;IAC1C,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;IAExC,sDAAsD;IACtD,qCAAqC;IACrC,QAAQ,GAAG,MAAM,OAAO,CAAC,WAAW,CAAC;SAClC,IAAI,CAAC,SAAS,CAAC;SACf,IAAI,CAAC,EAAE,CAAC;SACR,GAAG,CAAC,cAAc,EAAE,kBAAkB,CAAC,CAAA;IAC1C,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;IAExC,mDAAmD;IACnD,QAAQ,GAAG,MAAM,OAAO,CAAC,WAAW,CAAC;SAClC,IAAI,CAAC,SAAS,CAAC;SACf,IAAI,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC;SACpB,GAAG,CAAC,cAAc,EAAE,kBAAkB,CAAC,CAAA;IAC1C,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;AAC1C,CAAC,CAAC,CAAA"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=config.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.test.d.ts","sourceRoot":"","sources":["../../../../test/unit/config/config.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,121 @@
1
+ import { test, expect } from 'vitest';
2
+ import { initConfig } from '../../../src/config';
3
+ import express from 'express';
4
+ const defaultConfig = {
5
+ resources: [],
6
+ validateResources: false,
7
+ staticFolder: null,
8
+ apiPrefix: null,
9
+ connectionString: null,
10
+ cacheControl: 'no-store',
11
+ delay: 0,
12
+ requestBodyInterceptor: null,
13
+ responseBodyInterceptor: null,
14
+ customRouter: null,
15
+ returnNullFields: true,
16
+ isTesting: false,
17
+ port: 3000,
18
+ schemas: null,
19
+ };
20
+ test('No config returns default config', () => {
21
+ const initializedConfig = initConfig();
22
+ expect(initializedConfig.resources).toEqual(defaultConfig.resources);
23
+ expect(initializedConfig.validateResources).toBe(defaultConfig.validateResources);
24
+ expect(initializedConfig.staticFolder).toBe(defaultConfig.staticFolder);
25
+ expect(initializedConfig.apiPrefix).toBe(defaultConfig.apiPrefix);
26
+ expect(initializedConfig.connectionString).toBe(defaultConfig.connectionString);
27
+ expect(initializedConfig.cacheControl).toBe(defaultConfig.cacheControl);
28
+ expect(initializedConfig.delay).toBe(defaultConfig.delay);
29
+ expect(initializedConfig.requestBodyInterceptor?.post).toBe(defaultConfig.requestBodyInterceptor?.post);
30
+ expect(initializedConfig.requestBodyInterceptor?.patch).toBe(defaultConfig.requestBodyInterceptor?.patch);
31
+ expect(initializedConfig.requestBodyInterceptor?.put).toBe(defaultConfig.requestBodyInterceptor?.put);
32
+ expect(initializedConfig.responseBodyInterceptor).toBe(defaultConfig.responseBodyInterceptor);
33
+ expect(initializedConfig.customRouter).toBe(defaultConfig.customRouter);
34
+ expect(initializedConfig.returnNullFields).toBe(defaultConfig.returnNullFields);
35
+ expect(initializedConfig.isTesting).toBe(defaultConfig.isTesting);
36
+ expect(initializedConfig.port).toBe(defaultConfig.port);
37
+ expect(initializedConfig.schemas).toBe(defaultConfig.schemas);
38
+ });
39
+ test('Full user config overrides all defaults', () => {
40
+ const customRouter = express.Router();
41
+ customRouter.get('/hello', async (_, res) => {
42
+ return res.send('Hello, World!');
43
+ });
44
+ const config = initConfig({
45
+ resources: ['movies'],
46
+ staticFolder: 'build',
47
+ apiPrefix: 'api',
48
+ connectionString: 'mongodb://localhost:27017',
49
+ cacheControl: 'no-cache',
50
+ delay: 1000,
51
+ requestBodyInterceptor: {
52
+ post: () => {
53
+ // do nothing
54
+ },
55
+ patch: () => {
56
+ // do nothing
57
+ },
58
+ put: () => {
59
+ // do nothing
60
+ },
61
+ },
62
+ responseBodyInterceptor: ({ body }) => {
63
+ return body;
64
+ },
65
+ customRouter,
66
+ returnNullFields: false,
67
+ isTesting: true,
68
+ port: 3001,
69
+ schemas: {
70
+ stuff: {
71
+ post: {
72
+ type: 'object',
73
+ },
74
+ put: {
75
+ type: 'object',
76
+ },
77
+ patch: {
78
+ type: 'object',
79
+ },
80
+ },
81
+ },
82
+ });
83
+ expect(config.resources).toEqual(['movies']);
84
+ expect(config.validateResources).toBe(true);
85
+ expect(config.staticFolder).toBe('build');
86
+ expect(config.apiPrefix).toBe('/api/');
87
+ expect(config.connectionString).toBe('mongodb://localhost:27017');
88
+ expect(config.cacheControl).toBe('no-cache');
89
+ expect(config.delay).toBe(1000);
90
+ expect(config.requestBodyInterceptor.post).toBeInstanceOf(Function);
91
+ expect(config.requestBodyInterceptor.patch).toBeInstanceOf(Function);
92
+ expect(config.requestBodyInterceptor.put).toBeInstanceOf(Function);
93
+ expect(config.responseBodyInterceptor).toBeInstanceOf(Function);
94
+ expect(config.customRouter).not.toBeNull();
95
+ expect(config.returnNullFields).toBe(false);
96
+ expect(config.isTesting).toBe(true);
97
+ expect(config.port).toBe(3001);
98
+ expect(config.schemas).not.toBeNull();
99
+ });
100
+ test('Partial user config applies those, but leaves the rest at default', () => {
101
+ const config = initConfig({
102
+ apiPrefix: 'api',
103
+ });
104
+ expect(config.resources).toEqual(defaultConfig.resources);
105
+ expect(config.validateResources).toBe(defaultConfig.validateResources);
106
+ expect(config.staticFolder).toBe(defaultConfig.staticFolder);
107
+ expect(config.apiPrefix).toBe('/api/');
108
+ expect(config.connectionString).toBe(defaultConfig.connectionString);
109
+ expect(config.cacheControl).toBe(defaultConfig.cacheControl);
110
+ expect(config.delay).toBe(defaultConfig.delay);
111
+ expect(config.requestBodyInterceptor?.post).toBe(defaultConfig.requestBodyInterceptor?.post);
112
+ expect(config.requestBodyInterceptor?.patch).toBe(defaultConfig.requestBodyInterceptor?.patch);
113
+ expect(config.requestBodyInterceptor?.put).toBe(defaultConfig.requestBodyInterceptor?.put);
114
+ expect(config.responseBodyInterceptor).toBe(defaultConfig.responseBodyInterceptor);
115
+ expect(config.customRouter).toBe(defaultConfig.customRouter);
116
+ expect(config.returnNullFields).toBe(defaultConfig.returnNullFields);
117
+ expect(config.isTesting).toBe(defaultConfig.isTesting);
118
+ expect(config.port).toBe(defaultConfig.port);
119
+ expect(config.schemas).toBe(defaultConfig.schemas);
120
+ });
121
+ //# sourceMappingURL=config.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.test.js","sourceRoot":"","sources":["../../../../test/unit/config/config.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=urlParser.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"urlParser.test.d.ts","sourceRoot":"","sources":["../../../../test/unit/urls/urlParser.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,43 @@
1
+ import { test, expect } from 'vitest';
2
+ import { parseUrl } from '../../../src/urls/urlParser';
3
+ const noResourceAndNoId = { resource: null, id: null };
4
+ const resourceOnly = { resource: 'stuff', id: null };
5
+ const resourceAndId = { resource: 'stuff', id: 'foo' };
6
+ test.each([
7
+ ['stuff', resourceOnly],
8
+ ['/stuff', resourceOnly],
9
+ ['stuff/', resourceOnly],
10
+ ['/stuff/', resourceOnly],
11
+ ['//stuff/', resourceOnly],
12
+ ['/stuff//', resourceOnly],
13
+ ])("URL '%s' only has a resource: %o", (url, expected) => {
14
+ const actual = parseUrl(url);
15
+ expect(actual).toEqual(expected);
16
+ });
17
+ test.each([
18
+ ['stuff/foo', resourceAndId],
19
+ ['/stuff/foo', resourceAndId],
20
+ ['stuff/foo/', resourceAndId],
21
+ ['/stuff/foo/', resourceAndId],
22
+ ['/stuff//foo/', resourceAndId],
23
+ ])("URL '%s' has both a resource and id: %o", (url, expected) => {
24
+ const actual = parseUrl(url);
25
+ expect(actual).toEqual(expected);
26
+ });
27
+ test.each([
28
+ ['stuff/foo/bar', resourceAndId],
29
+ ['/stuff/foo/bar', resourceAndId],
30
+ ['stuff/foo/bar/', resourceAndId],
31
+ ['/stuff/foo/bar/', resourceAndId],
32
+ ])("URL '%s' has additional path items next to a resource and id: %o", (url, expected) => {
33
+ const actual = parseUrl(url);
34
+ expect(actual).toEqual(expected);
35
+ });
36
+ test.each([
37
+ ['', noResourceAndNoId],
38
+ [' ', noResourceAndNoId],
39
+ ])("URL '%s' has no resource and id: %o", (url, expected) => {
40
+ const actual = parseUrl(url);
41
+ expect(actual).toEqual(expected);
42
+ });
43
+ //# sourceMappingURL=urlParser.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"urlParser.test.js","sourceRoot":"","sources":["../../../../test/unit/urls/urlParser.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AACrC,OAAO,EAAE,QAAQ,EAAE,MAAM,6BAA6B,CAAA;AAEtD,MAAM,iBAAiB,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,CAAA;AACtD,MAAM,YAAY,GAAG,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAA;AACpD,MAAM,aAAa,GAAG,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,CAAA;AAEtD,IAAI,CAAC,IAAI,CAAC;IACR,CAAC,OAAO,EAAE,YAAY,CAAC;IACvB,CAAC,QAAQ,EAAE,YAAY,CAAC;IACxB,CAAC,QAAQ,EAAE,YAAY,CAAC;IACxB,CAAC,SAAS,EAAE,YAAY,CAAC;IACzB,CAAC,UAAU,EAAE,YAAY,CAAC;IAC1B,CAAC,UAAU,EAAE,YAAY,CAAC;CAC3B,CAAC,CAAC,kCAAkC,EAAE,CAAC,GAAG,EAAE,QAAQ,EAAE,EAAE;IACvD,MAAM,MAAM,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAA;IAC5B,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAA;AAClC,CAAC,CAAC,CAAA;AAEF,IAAI,CAAC,IAAI,CAAC;IACR,CAAC,WAAW,EAAE,aAAa,CAAC;IAC5B,CAAC,YAAY,EAAE,aAAa,CAAC;IAC7B,CAAC,YAAY,EAAE,aAAa,CAAC;IAC7B,CAAC,aAAa,EAAE,aAAa,CAAC;IAC9B,CAAC,cAAc,EAAE,aAAa,CAAC;CAChC,CAAC,CAAC,yCAAyC,EAAE,CAAC,GAAG,EAAE,QAAQ,EAAE,EAAE;IAC9D,MAAM,MAAM,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAA;IAC5B,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAA;AAClC,CAAC,CAAC,CAAA;AAEF,IAAI,CAAC,IAAI,CAAC;IACR,CAAC,eAAe,EAAE,aAAa,CAAC;IAChC,CAAC,gBAAgB,EAAE,aAAa,CAAC;IACjC,CAAC,gBAAgB,EAAE,aAAa,CAAC;IACjC,CAAC,iBAAiB,EAAE,aAAa,CAAC;CACnC,CAAC,CAAC,kEAAkE,EAAE,CAAC,GAAG,EAAE,QAAQ,EAAE,EAAE;IACvF,MAAM,MAAM,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAA;IAC5B,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAA;AAClC,CAAC,CAAC,CAAA;AAEF,IAAI,CAAC,IAAI,CAAC;IACR,CAAC,EAAE,EAAE,iBAAiB,CAAC;IACvB,CAAC,GAAG,EAAE,iBAAiB,CAAC;CACzB,CAAC,CAAC,qCAAqC,EAAE,CAAC,GAAG,EAAE,QAAQ,EAAE,EAAE;IAC1D,MAAM,MAAM,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAA;IAC5B,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAA;AAClC,CAAC,CAAC,CAAA"}