@unito/integration-sdk 0.1.0 → 0.1.2

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 (72) hide show
  1. package/README.md +1 -1
  2. package/dist/src/errors.d.ts +3 -2
  3. package/dist/src/errors.js +11 -9
  4. package/dist/src/handler.js +12 -1
  5. package/dist/src/httpErrors.d.ts +3 -0
  6. package/dist/src/httpErrors.js +6 -1
  7. package/dist/src/index.d.ts +2 -1
  8. package/dist/src/index.js +2 -0
  9. package/dist/src/middlewares/credentials.d.ts +4 -1
  10. package/dist/src/resources/provider.d.ts +35 -12
  11. package/dist/src/resources/provider.js +59 -34
  12. package/dist/test/errors.test.js +7 -8
  13. package/dist/test/handler.test.js +26 -2
  14. package/dist/test/resources/provider.test.d.ts +1 -0
  15. package/dist/test/resources/provider.test.js +229 -0
  16. package/package.json +1 -3
  17. package/src/errors.ts +12 -9
  18. package/src/handler.ts +18 -1
  19. package/src/httpErrors.ts +7 -1
  20. package/src/index.ts +4 -0
  21. package/src/middlewares/credentials.ts +1 -1
  22. package/src/resources/provider.ts +89 -47
  23. package/test/errors.test.ts +7 -8
  24. package/test/handler.test.ts +36 -2
  25. package/test/resources/provider.test.ts +285 -0
  26. package/dist/src/api/index.d.ts +0 -2
  27. package/dist/src/api/index.d.ts.map +0 -1
  28. package/dist/src/api/index.js +0 -2
  29. package/dist/src/api/index.js.map +0 -1
  30. package/dist/src/app/errors/HTTPError.d.ts +0 -5
  31. package/dist/src/app/errors/HTTPError.d.ts.map +0 -1
  32. package/dist/src/app/errors/HTTPError.js +0 -8
  33. package/dist/src/app/errors/HTTPError.js.map +0 -1
  34. package/dist/src/app/errors/HTTPNotFoundError.d.ts +0 -5
  35. package/dist/src/app/errors/HTTPNotFoundError.d.ts.map +0 -1
  36. package/dist/src/app/errors/HTTPNotFoundError.js +0 -7
  37. package/dist/src/app/errors/HTTPNotFoundError.js.map +0 -1
  38. package/dist/src/app/errors/HTTPUnprocessableEntityError.d.ts +0 -5
  39. package/dist/src/app/errors/HTTPUnprocessableEntityError.d.ts.map +0 -1
  40. package/dist/src/app/errors/HTTPUnprocessableEntityError.js +0 -7
  41. package/dist/src/app/errors/HTTPUnprocessableEntityError.js.map +0 -1
  42. package/dist/src/app/errors/index.d.ts +0 -4
  43. package/dist/src/app/errors/index.d.ts.map +0 -1
  44. package/dist/src/app/errors/index.js +0 -4
  45. package/dist/src/app/errors/index.js.map +0 -1
  46. package/dist/src/app/index.d.ts +0 -6
  47. package/dist/src/app/index.d.ts.map +0 -1
  48. package/dist/src/app/index.js +0 -80
  49. package/dist/src/app/index.js.map +0 -1
  50. package/dist/src/app/integration.d.ts +0 -5
  51. package/dist/src/app/integration.d.ts.map +0 -1
  52. package/dist/src/app/integration.js +0 -86
  53. package/dist/src/app/integration.js.map +0 -1
  54. package/dist/src/app/itemNode.d.ts +0 -8
  55. package/dist/src/app/itemNode.d.ts.map +0 -1
  56. package/dist/src/app/itemNode.js +0 -13
  57. package/dist/src/app/itemNode.js.map +0 -1
  58. package/dist/src/app/middlewares/withCorrelationId.d.ts +0 -11
  59. package/dist/src/app/middlewares/withCorrelationId.d.ts.map +0 -1
  60. package/dist/src/app/middlewares/withCorrelationId.js +0 -8
  61. package/dist/src/app/middlewares/withCorrelationId.js.map +0 -1
  62. package/dist/src/app/middlewares/withLogger.d.ts +0 -12
  63. package/dist/src/app/middlewares/withLogger.d.ts.map +0 -1
  64. package/dist/src/app/middlewares/withLogger.js +0 -18
  65. package/dist/src/app/middlewares/withLogger.js.map +0 -1
  66. package/dist/src/index.d.ts.map +0 -1
  67. package/dist/src/index.js.map +0 -1
  68. package/dist/src/resources/cache.d.ts.map +0 -1
  69. package/dist/src/resources/cache.js.map +0 -1
  70. package/dist/src/resources/logger.d.ts.map +0 -1
  71. package/dist/src/resources/logger.js.map +0 -1
  72. package/dist/tsconfig.tsbuildinfo +0 -1
@@ -0,0 +1,285 @@
1
+ import assert from 'node:assert/strict';
2
+ import { describe, it } from 'node:test';
3
+
4
+ import { Provider } from '../../src/resources/provider.js';
5
+
6
+ describe('Provider', () => {
7
+ const provider = new Provider({
8
+ prepareRequest: requestOptions => {
9
+ return {
10
+ url: `www.${requestOptions.credentials.domain ?? 'myApi.com'}`,
11
+ headers: {
12
+ 'X-Custom-Provider-Header': 'value',
13
+ 'X-Provider-Credential-Header': requestOptions.credentials.apiKey as string,
14
+ },
15
+ };
16
+ },
17
+ });
18
+
19
+ it('get', async context => {
20
+ const response = new Response('{"data": "value"}', {
21
+ status: 200,
22
+ headers: { 'Content-Type': 'application/json' },
23
+ });
24
+
25
+ const fetchMock = context.mock.method(global, 'fetch', () => Promise.resolve(response));
26
+
27
+ const actualResponse = await provider.get('/endpoint', {
28
+ credentials: { apiKey: 'apikey#1111' },
29
+ additionnalheaders: { 'X-Additional-Header': 'value1' },
30
+ });
31
+
32
+ assert.equal(fetchMock.mock.calls.length, 1);
33
+ assert.deepEqual(fetchMock.mock.calls[0]?.arguments, [
34
+ 'www.myApi.com/endpoint',
35
+ {
36
+ method: 'GET',
37
+ body: null,
38
+ headers: {
39
+ 'Content-Type': 'application/json',
40
+ Accept: 'application/json',
41
+ 'X-Custom-Provider-Header': 'value',
42
+ 'X-Provider-Credential-Header': 'apikey#1111',
43
+ 'X-Additional-Header': 'value1',
44
+ },
45
+ },
46
+ ]);
47
+ assert.deepEqual(actualResponse, { status: 200, headers: response.headers, data: { data: 'value' } });
48
+ });
49
+
50
+ it('post with url encoded body', async context => {
51
+ const response = new Response('{"data": "value"}', {
52
+ status: 201,
53
+ headers: { 'Content-Type': 'application/json' },
54
+ });
55
+
56
+ const fetchMock = context.mock.method(global, 'fetch', () => Promise.resolve(response));
57
+
58
+ const actualResponse = await provider.post(
59
+ '/endpoint',
60
+ {
61
+ data: 'createdItemInfo',
62
+ },
63
+ {
64
+ credentials: { apiKey: 'apikey#1111' },
65
+ additionnalheaders: { 'X-Additional-Header': 'value1' },
66
+ },
67
+ );
68
+
69
+ assert.equal(fetchMock.mock.calls.length, 1);
70
+ assert.deepEqual(fetchMock.mock.calls[0]?.arguments, [
71
+ 'www.myApi.com/endpoint',
72
+ {
73
+ method: 'POST',
74
+ body: 'data=createdItemInfo',
75
+ headers: {
76
+ 'Content-Type': 'application/x-www-form-urlencoded',
77
+ Accept: 'application/json',
78
+ 'X-Custom-Provider-Header': 'value',
79
+ 'X-Provider-Credential-Header': 'apikey#1111',
80
+ 'X-Additional-Header': 'value1',
81
+ },
82
+ },
83
+ ]);
84
+ assert.deepEqual(actualResponse, { status: 201, headers: response.headers, data: { data: 'value' } });
85
+ });
86
+
87
+ it('put with json body', async context => {
88
+ const response = new Response('{"data": "value"}', {
89
+ status: 201,
90
+ headers: { 'Content-Type': 'application/json' },
91
+ });
92
+
93
+ const fetchMock = context.mock.method(global, 'fetch', () => Promise.resolve(response));
94
+
95
+ // Removing leading '/' on endpoint to make sure we support both cases
96
+ const actualResponse = await provider.put(
97
+ 'endpoint/123',
98
+ {
99
+ data: 'updatedItemInfo',
100
+ },
101
+ {
102
+ credentials: { apiKey: 'apikey#1111' },
103
+ additionnalheaders: { 'X-Additional-Header': 'value1', 'Content-Type': 'application/json' },
104
+ },
105
+ );
106
+
107
+ assert.equal(fetchMock.mock.calls.length, 1);
108
+ assert.deepEqual(fetchMock.mock.calls[0]?.arguments, [
109
+ 'www.myApi.com/endpoint/123',
110
+ {
111
+ method: 'PUT',
112
+ body: JSON.stringify({ data: 'updatedItemInfo' }),
113
+ headers: {
114
+ 'Content-Type': 'application/json',
115
+ Accept: 'application/json',
116
+ 'X-Custom-Provider-Header': 'value',
117
+ 'X-Provider-Credential-Header': 'apikey#1111',
118
+ 'X-Additional-Header': 'value1',
119
+ },
120
+ },
121
+ ]);
122
+ assert.deepEqual(actualResponse, { status: 201, headers: response.headers, data: { data: 'value' } });
123
+ });
124
+
125
+ it('patch with query params', async context => {
126
+ const response = new Response('{"data": "value"}', {
127
+ status: 201,
128
+ headers: { 'Content-Type': 'application/json' },
129
+ });
130
+
131
+ const fetchMock = context.mock.method(global, 'fetch', () => Promise.resolve(response));
132
+
133
+ const actualResponse = await provider.patch(
134
+ '/endpoint/123',
135
+ {
136
+ data: 'updatedItemInfo',
137
+ },
138
+ {
139
+ credentials: { apiKey: 'apikey#1111' },
140
+ queryParams: { param1: 'value1', param2: 'value2' },
141
+ additionnalheaders: { 'X-Additional-Header': 'value1', 'Content-Type': 'application/json' },
142
+ },
143
+ );
144
+
145
+ assert.equal(fetchMock.mock.calls.length, 1);
146
+ assert.deepEqual(fetchMock.mock.calls[0]?.arguments, [
147
+ 'www.myApi.com/endpoint/123?param1=value1&param2=value2',
148
+ {
149
+ method: 'PATCH',
150
+ body: JSON.stringify({ data: 'updatedItemInfo' }),
151
+ headers: {
152
+ 'Content-Type': 'application/json',
153
+ Accept: 'application/json',
154
+ 'X-Custom-Provider-Header': 'value',
155
+ 'X-Provider-Credential-Header': 'apikey#1111',
156
+ 'X-Additional-Header': 'value1',
157
+ },
158
+ },
159
+ ]);
160
+ assert.deepEqual(actualResponse, { status: 201, headers: response.headers, data: { data: 'value' } });
161
+ });
162
+
163
+ it('delete', async context => {
164
+ const response = new Response(undefined, {
165
+ status: 204,
166
+ headers: { 'Content-Type': 'application/json' },
167
+ });
168
+
169
+ const fetchMock = context.mock.method(global, 'fetch', () => Promise.resolve(response));
170
+
171
+ const actualResponse = await provider.delete('/endpoint/123', {
172
+ credentials: { apiKey: 'apikey#1111' },
173
+ additionnalheaders: { 'X-Additional-Header': 'value1', 'Content-Type': 'application/json' },
174
+ });
175
+
176
+ assert.equal(fetchMock.mock.calls.length, 1);
177
+ assert.deepEqual(fetchMock.mock.calls[0]?.arguments, [
178
+ 'www.myApi.com/endpoint/123',
179
+ {
180
+ method: 'DELETE',
181
+ body: null,
182
+ headers: {
183
+ 'Content-Type': 'application/json',
184
+ Accept: 'application/json',
185
+ 'X-Custom-Provider-Header': 'value',
186
+ 'X-Provider-Credential-Header': 'apikey#1111',
187
+ 'X-Additional-Header': 'value1',
188
+ },
189
+ },
190
+ ]);
191
+ assert.deepEqual(actualResponse, { status: 204, headers: response.headers, data: undefined });
192
+ });
193
+
194
+ it('uses rate limiter if provided', async context => {
195
+ const mockRateLimiter = context.mock.fn((_context, request) => Promise.resolve(request()));
196
+
197
+ const rateLimitedProvider = new Provider({
198
+ prepareRequest: requestOptions => {
199
+ return {
200
+ url: `www.${requestOptions.credentials.domain ?? 'myApi.com'}`,
201
+ headers: {
202
+ 'X-Custom-Provider-Header': 'value',
203
+ 'X-Provider-Credential-Header': requestOptions.credentials.apiKey as string,
204
+ },
205
+ };
206
+ },
207
+ rateLimiter: mockRateLimiter,
208
+ });
209
+
210
+ const response = new Response(undefined, {
211
+ status: 204,
212
+ headers: { 'Content-Type': 'application/json' },
213
+ });
214
+
215
+ const fetchMock = context.mock.method(global, 'fetch', () => Promise.resolve(response));
216
+
217
+ const options = {
218
+ credentials: { apiKey: 'apikey#1111' },
219
+ additionnalheaders: { 'X-Additional-Header': 'value1', 'Content-Type': 'application/json' },
220
+ };
221
+
222
+ const actualResponse = await rateLimitedProvider.delete('/endpoint/123', options);
223
+
224
+ assert.equal(mockRateLimiter.mock.calls.length, 1);
225
+ assert.deepEqual(mockRateLimiter.mock.calls[0]?.arguments[0]?.credentials, options.credentials);
226
+ assert.equal(fetchMock.mock.calls.length, 1);
227
+ assert.deepEqual(fetchMock.mock.calls[0]?.arguments, [
228
+ 'www.myApi.com/endpoint/123',
229
+ {
230
+ method: 'DELETE',
231
+ body: null,
232
+ headers: {
233
+ 'Content-Type': 'application/json',
234
+ Accept: 'application/json',
235
+ 'X-Custom-Provider-Header': 'value',
236
+ 'X-Provider-Credential-Header': 'apikey#1111',
237
+ 'X-Additional-Header': 'value1',
238
+ },
239
+ },
240
+ ]);
241
+ assert.deepEqual(actualResponse, { status: 204, headers: response.headers, data: undefined });
242
+ });
243
+
244
+ it('throws on invalid json response', async context => {
245
+ const response = new Response('{invalidJSON}', {
246
+ status: 200,
247
+ });
248
+
249
+ context.mock.method(global, 'fetch', () => Promise.resolve(response));
250
+
251
+ assert.rejects(() =>
252
+ provider.get('/endpoint/123', {
253
+ credentials: { apiKey: 'apikey#1111' },
254
+ }),
255
+ );
256
+ });
257
+
258
+ it('throws on status 400', async context => {
259
+ const response = new Response(undefined, {
260
+ status: 400,
261
+ });
262
+
263
+ context.mock.method(global, 'fetch', () => Promise.resolve(response));
264
+
265
+ assert.rejects(() =>
266
+ provider.get('/endpoint/123', {
267
+ credentials: { apiKey: 'apikey#1111' },
268
+ }),
269
+ );
270
+ });
271
+
272
+ it('throws on status 429', async context => {
273
+ const response = new Response(undefined, {
274
+ status: 429,
275
+ });
276
+
277
+ context.mock.method(global, 'fetch', () => Promise.resolve(response));
278
+
279
+ assert.rejects(() =>
280
+ provider.get('/endpoint/123', {
281
+ credentials: { apiKey: 'apikey#1111' },
282
+ }),
283
+ );
284
+ });
285
+ });
@@ -1,2 +0,0 @@
1
- export * from '@unito/integration-api';
2
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/api/index.ts"],"names":[],"mappings":"AAAA,cAAc,wBAAwB,CAAC"}
@@ -1,2 +0,0 @@
1
- export * from '@unito/integration-api';
2
- //# sourceMappingURL=index.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/api/index.ts"],"names":[],"mappings":"AAAA,cAAc,wBAAwB,CAAC"}
@@ -1,5 +0,0 @@
1
- export declare class HTTPError extends Error {
2
- readonly status: number;
3
- constructor(message: string, status: number);
4
- }
5
- //# sourceMappingURL=HTTPError.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"HTTPError.d.ts","sourceRoot":"","sources":["../../../../src/app/errors/HTTPError.ts"],"names":[],"mappings":"AAAA,qBAAa,SAAU,SAAQ,KAAK;IAClC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAO;gBAElB,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;CAI5C"}
@@ -1,8 +0,0 @@
1
- export class HTTPError extends Error {
2
- status = 500;
3
- constructor(message, status) {
4
- super(message);
5
- this.status = status;
6
- }
7
- }
8
- //# sourceMappingURL=HTTPError.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"HTTPError.js","sourceRoot":"","sources":["../../../../src/app/errors/HTTPError.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,SAAU,SAAQ,KAAK;IACzB,MAAM,GAAW,GAAG,CAAC;IAE9B,YAAY,OAAe,EAAE,MAAc;QACzC,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;CACF"}
@@ -1,5 +0,0 @@
1
- import { HTTPError } from './HTTPError.js';
2
- export declare class HTTPNotFoundError extends HTTPError {
3
- constructor(message?: string);
4
- }
5
- //# sourceMappingURL=HTTPNotFoundError.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"HTTPNotFoundError.d.ts","sourceRoot":"","sources":["../../../../src/app/errors/HTTPNotFoundError.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAE3C,qBAAa,iBAAkB,SAAQ,SAAS;gBAClC,OAAO,CAAC,EAAE,MAAM;CAG7B"}
@@ -1,7 +0,0 @@
1
- import { HTTPError } from './HTTPError.js';
2
- export class HTTPNotFoundError extends HTTPError {
3
- constructor(message) {
4
- super(message || 'Not found', 404);
5
- }
6
- }
7
- //# sourceMappingURL=HTTPNotFoundError.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"HTTPNotFoundError.js","sourceRoot":"","sources":["../../../../src/app/errors/HTTPNotFoundError.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAE3C,MAAM,OAAO,iBAAkB,SAAQ,SAAS;IAC9C,YAAY,OAAgB;QAC1B,KAAK,CAAC,OAAO,IAAI,WAAW,EAAE,GAAG,CAAC,CAAC;IACrC,CAAC;CACF"}
@@ -1,5 +0,0 @@
1
- import { HTTPError } from './HTTPError.js';
2
- export declare class HTTPUnprocessableEntityError extends HTTPError {
3
- constructor(message?: string);
4
- }
5
- //# sourceMappingURL=HTTPUnprocessableEntityError.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"HTTPUnprocessableEntityError.d.ts","sourceRoot":"","sources":["../../../../src/app/errors/HTTPUnprocessableEntityError.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAE3C,qBAAa,4BAA6B,SAAQ,SAAS;gBAC7C,OAAO,CAAC,EAAE,MAAM;CAG7B"}
@@ -1,7 +0,0 @@
1
- import { HTTPError } from './HTTPError.js';
2
- export class HTTPUnprocessableEntityError extends HTTPError {
3
- constructor(message) {
4
- super(message || 'Unprocessable Entity', 422);
5
- }
6
- }
7
- //# sourceMappingURL=HTTPUnprocessableEntityError.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"HTTPUnprocessableEntityError.js","sourceRoot":"","sources":["../../../../src/app/errors/HTTPUnprocessableEntityError.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAE3C,MAAM,OAAO,4BAA6B,SAAQ,SAAS;IACzD,YAAY,OAAgB;QAC1B,KAAK,CAAC,OAAO,IAAI,sBAAsB,EAAE,GAAG,CAAC,CAAC;IAChD,CAAC;CACF"}
@@ -1,4 +0,0 @@
1
- export { HTTPError } from './HTTPError.js';
2
- export { HTTPNotFoundError } from './HTTPNotFoundError.js';
3
- export { HTTPUnprocessableEntityError } from './HTTPUnprocessableEntityError.js';
4
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/app/errors/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,4BAA4B,EAAE,MAAM,mCAAmC,CAAC"}
@@ -1,4 +0,0 @@
1
- export { HTTPError } from './HTTPError.js';
2
- export { HTTPNotFoundError } from './HTTPNotFoundError.js';
3
- export { HTTPUnprocessableEntityError } from './HTTPUnprocessableEntityError.js';
4
- //# sourceMappingURL=index.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/app/errors/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,4BAA4B,EAAE,MAAM,mCAAmC,CAAC"}
@@ -1,6 +0,0 @@
1
- import express from 'express';
2
- export declare const createApp: (options: {
3
- router: express.Router;
4
- middlewares?: express.RequestHandler[];
5
- }) => void;
6
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/app/index.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,SAAS,CAAC;AAO9B,eAAO,MAAM,SAAS,YAAa;IAAE,MAAM,EAAE,QAAQ,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,QAAQ,cAAc,EAAE,CAAA;CAAE,SA6FpG,CAAC"}
@@ -1,80 +0,0 @@
1
- import express from 'express';
2
- import withCorrelationId from './middlewares/withCorrelationId.js';
3
- import withLogger from './middlewares/withLogger.js';
4
- import { HTTPError } from './errors/index.js';
5
- export const createApp = (options) => {
6
- // Express Server initialization
7
- const app = express();
8
- // Parse query strings with https://github.com/ljharb/qs.
9
- app.set('query parser', 'extended');
10
- app.use(express.json());
11
- // Extract the correlation id.
12
- app.use(withCorrelationId);
13
- app.use(withLogger);
14
- // Must be one of the first handlers (to catch all the errors).
15
- app.use((req, res, next) => {
16
- if (req.originalUrl !== '/health') {
17
- res.on('finish', function () {
18
- const loggerLevel = res.statusCode >= 500 ? 'error' : 'info';
19
- // eslint-disable-next-line
20
- res.locals.logger[loggerLevel](`${req.method} ${req.originalUrl} ${res.statusCode}`);
21
- });
22
- }
23
- next();
24
- });
25
- // Load the middlewares.
26
- options.middlewares?.forEach(middleware => app.use(middleware));
27
- // Load the routes.
28
- app.use(options.router);
29
- // Must be the (last - 1) handler.
30
- app.use((err, _req, res, next) => {
31
- if (res.headersSent) {
32
- return next(err);
33
- }
34
- if (process.env.NODE_ENV !== 'production') {
35
- // eslint-disable-next-line
36
- res.locals.logger.error(err);
37
- }
38
- if (err instanceof HTTPError) {
39
- return res.status(err.status).json(err.message);
40
- }
41
- const originalError = {
42
- code: err.name,
43
- message: err.message,
44
- };
45
- res.status(500).json({
46
- code: '500',
47
- message: 'Oops! Something went wrong',
48
- originalError: originalError,
49
- });
50
- });
51
- // Must be the last handler.
52
- app.use((req, res, _next) => {
53
- const error = {
54
- code: '404',
55
- message: `Path ${req.path} not found.`,
56
- };
57
- res.status(404).json(error);
58
- });
59
- const instance = app.listen(process.env.PORT || 9200, () =>
60
- // eslint-disable-next-line
61
- console.info(`Server started on port ${process.env.PORT || 9200}.`));
62
- // Trap exit signals.
63
- ['SIGTERM', 'SIGINT', 'SIGUSR2'].forEach(signalType => {
64
- process.once(signalType, async () => {
65
- // eslint-disable-next-line
66
- console.info(`Received termination signal ${signalType}. Exiting.`);
67
- try {
68
- if (instance) {
69
- instance.close();
70
- }
71
- }
72
- catch (e) {
73
- // eslint-disable-next-line
74
- console.error('Failed to gracefully exit', e);
75
- }
76
- process.exit();
77
- });
78
- });
79
- };
80
- //# sourceMappingURL=index.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/app/index.ts"],"names":[],"mappings":"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"}
@@ -1,5 +0,0 @@
1
- export declare class Integration {
2
- private middlewares;
3
- start(): void;
4
- }
5
- //# sourceMappingURL=integration.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"integration.d.ts","sourceRoot":"","sources":["../../../src/app/integration.ts"],"names":[],"mappings":"AAQA,qBAAa,WAAW;IACtB,OAAO,CAAC,WAAW,CAAgC;IAK5C,KAAK;CA8Fb"}
@@ -1,86 +0,0 @@
1
- import express from 'express';
2
- import withCorrelationId from './middlewares/withCorrelationId.js';
3
- import withLogger from './middlewares/withLogger.js';
4
- import { HTTPError } from './errors/index.js';
5
- // import { ItemNode } from './itemNode.js';
6
- export class Integration {
7
- middlewares = [];
8
- // private router: express.Router = express.Router();
9
- // private graph: ItemNode = new ItemNode(''); // Take root node from .unito.json
10
- start() {
11
- // Express Server initialization
12
- const app = express();
13
- // Parse query strings with https://github.com/ljharb/qs.
14
- app.set('query parser', 'extended');
15
- app.use(express.json());
16
- // Extract the correlation id.
17
- app.use(withCorrelationId);
18
- app.use(withLogger);
19
- // Must be one of the first handlers (to catch all the errors).
20
- app.use((req, res, next) => {
21
- if (req.originalUrl !== '/health') {
22
- res.on('finish', function () {
23
- const loggerLevel = res.statusCode >= 500 ? 'error' : 'info';
24
- // eslint-disable-next-line
25
- res.locals.logger[loggerLevel](`${req.method} ${req.originalUrl} ${res.statusCode}`);
26
- });
27
- }
28
- next();
29
- });
30
- // Load the middlewares.
31
- this.middlewares?.forEach(middleware => app.use(middleware));
32
- // Load the routes.
33
- app.use(this.router);
34
- // Must be the (last - 1) handler.
35
- app.use((err, _req, res, next) => {
36
- if (res.headersSent) {
37
- return next(err);
38
- }
39
- if (process.env.NODE_ENV !== 'production') {
40
- // eslint-disable-next-line
41
- res.locals.logger.error(err);
42
- }
43
- if (err instanceof HTTPError) {
44
- return res.status(err.status).json(err.message);
45
- }
46
- const originalError = {
47
- code: err.name,
48
- message: err.message,
49
- };
50
- res.status(500).json({
51
- code: '500',
52
- message: 'Oops! Something went wrong',
53
- originalError: originalError,
54
- });
55
- });
56
- // Must be the last handler.
57
- app.use((req, res, _next) => {
58
- const error = {
59
- code: '404',
60
- message: `Path ${req.path} not found.`,
61
- };
62
- res.status(404).json(error);
63
- });
64
- const instance = app.listen(process.env.PORT || 9200, () =>
65
- // eslint-disable-next-line
66
- console.info(`Server started on port ${process.env.PORT || 9200}.`));
67
- // Trap exit signals.
68
- ['SIGTERM', 'SIGINT', 'SIGUSR2'].forEach(signalType => {
69
- process.once(signalType, async () => {
70
- // eslint-disable-next-line
71
- console.info(`Received termination signal ${signalType}. Exiting.`);
72
- try {
73
- if (instance) {
74
- instance.close();
75
- }
76
- }
77
- catch (e) {
78
- // eslint-disable-next-line
79
- console.error('Failed to gracefully exit', e);
80
- }
81
- process.exit();
82
- });
83
- });
84
- }
85
- }
86
- //# sourceMappingURL=integration.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"integration.js","sourceRoot":"","sources":["../../../src/app/integration.ts"],"names":[],"mappings":"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"}
@@ -1,8 +0,0 @@
1
- export declare class ItemNode {
2
- private path;
3
- private router;
4
- private relations;
5
- constructor(path: string);
6
- getRelations(): ItemNode[];
7
- }
8
- //# sourceMappingURL=itemNode.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"itemNode.d.ts","sourceRoot":"","sources":["../../../src/app/itemNode.ts"],"names":[],"mappings":"AAEA,qBAAa,QAAQ;IACnB,OAAO,CAAC,IAAI,CAAS;IACrB,OAAO,CAAC,MAAM,CAAoC;IAClD,OAAO,CAAC,SAAS,CAAkB;gBAEvB,IAAI,EAAE,MAAM;IAIxB,YAAY;CAKb"}
@@ -1,13 +0,0 @@
1
- import express from 'express';
2
- export class ItemNode {
3
- path;
4
- router = express.Router();
5
- relations = [];
6
- constructor(path) {
7
- this.path = path;
8
- }
9
- getRelations() {
10
- return this.relations;
11
- }
12
- }
13
- //# sourceMappingURL=itemNode.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"itemNode.js","sourceRoot":"","sources":["../../../src/app/itemNode.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,SAAS,CAAC;AAE9B,MAAM,OAAO,QAAQ;IACX,IAAI,CAAS;IACb,MAAM,GAAmB,OAAO,CAAC,MAAM,EAAE,CAAC;IAC1C,SAAS,GAAe,EAAE,CAAC;IAEnC,YAAY,IAAY;QACtB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;IAED,YAAY;QACV,OAAO,IAAI,CAAC,SAAS,CAAC;IACxB,CAAC;CAGF"}
@@ -1,11 +0,0 @@
1
- import { Request, Response, NextFunction } from 'express';
2
- declare global {
3
- namespace Express {
4
- interface Locals {
5
- correlationId: string;
6
- }
7
- }
8
- }
9
- declare const withCorrelationId: (req: Request, res: Response, next: NextFunction) => void;
10
- export default withCorrelationId;
11
- //# sourceMappingURL=withCorrelationId.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"withCorrelationId.d.ts","sourceRoot":"","sources":["../../../../src/app/middlewares/withCorrelationId.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAG1D,OAAO,CAAC,MAAM,CAAC;IAEb,UAAU,OAAO,CAAC;QAChB,UAAU,MAAM;YACd,aAAa,EAAE,MAAM,CAAC;SACvB;KACF;CACF;AAED,QAAA,MAAM,iBAAiB,QAAS,OAAO,OAAO,QAAQ,QAAQ,YAAY,SAMzE,CAAC;AAEF,eAAe,iBAAiB,CAAC"}
@@ -1,8 +0,0 @@
1
- import * as uuid from 'uuid';
2
- const withCorrelationId = (req, res, next) => {
3
- const correlationIdHeader = req.header('X-Unito-Correlation-Id');
4
- res.locals.correlationId = correlationIdHeader ?? uuid.v4();
5
- next();
6
- };
7
- export default withCorrelationId;
8
- //# sourceMappingURL=withCorrelationId.js.map