@unito/integration-sdk 0.1.10 → 0.1.11

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.
@@ -118,13 +118,6 @@ class Logger {
118
118
  }
119
119
  }
120
120
 
121
- /**
122
- * Array of created caches kept to allow for graceful shutdown on exit signals.
123
- */
124
- const caches = [];
125
- const shutdownCaches = async () => {
126
- return Promise.allSettled(caches.map(cache => cache.quit()));
127
- };
128
121
  class Cache {
129
122
  cacheInstance;
130
123
  constructor(cacheInstance) {
@@ -153,8 +146,6 @@ class Cache {
153
146
  */
154
147
  static create(redisUrl) {
155
148
  const cacheInstance = redisUrl ? new cachette.WriteThroughCache(redisUrl) : new cachette.LocalCache();
156
- // Push to the array of caches for graceful shutdown on exit signals.
157
- caches.push(cacheInstance);
158
149
  // Intended: the correlation id will be the same for all logs of Cachette.
159
150
  const correlationId = uuid__namespace.v4();
160
151
  const logger = new Logger({ correlation_id: correlationId });
@@ -265,13 +256,13 @@ function buildHttpError(responseStatus, message) {
265
256
  return httpError;
266
257
  }
267
258
 
268
- const middleware$6 = (req, res, next) => {
259
+ const middleware$7 = (req, res, next) => {
269
260
  res.locals.correlationId = req.header('X-Unito-Correlation-Id') ?? uuid__namespace.v4();
270
261
  next();
271
262
  };
272
263
 
273
264
  const ADDITIONAL_CONTEXT_HEADER = 'X-Unito-Additional-Logging-Context';
274
- const middleware$5 = (req, res, next) => {
265
+ const middleware$6 = (req, res, next) => {
275
266
  const logger = new Logger({ correlation_id: res.locals.correlationId });
276
267
  res.locals.logger = logger;
277
268
  const rawAdditionalContext = req.header(ADDITIONAL_CONTEXT_HEADER);
@@ -288,7 +279,7 @@ const middleware$5 = (req, res, next) => {
288
279
  };
289
280
 
290
281
  const CREDENTIALS_HEADER = 'X-Unito-Credentials';
291
- const middleware$4 = (req, res, next) => {
282
+ const middleware$5 = (req, res, next) => {
292
283
  const credentialsHeader = req.header(CREDENTIALS_HEADER);
293
284
  if (credentialsHeader) {
294
285
  let credentials;
@@ -303,6 +294,22 @@ const middleware$4 = (req, res, next) => {
303
294
  next();
304
295
  };
305
296
 
297
+ const SECRETS_HEADER = 'X-Unito-Secrets';
298
+ const middleware$4 = (req, res, next) => {
299
+ const secretsHeader = req.header(SECRETS_HEADER);
300
+ if (secretsHeader) {
301
+ let secrets;
302
+ try {
303
+ secrets = JSON.parse(Buffer.from(secretsHeader, 'base64').toString('utf8'));
304
+ }
305
+ catch {
306
+ throw new BadRequestError(`Malformed HTTP header ${SECRETS_HEADER}`);
307
+ }
308
+ res.locals.secrets = secrets;
309
+ }
310
+ next();
311
+ };
312
+
306
313
  const middleware$3 = (req, res, next) => {
307
314
  const rawSelect = req.query.select;
308
315
  if (typeof rawSelect === 'string') {
@@ -686,6 +693,7 @@ class Integration {
686
693
  app.use(express.json());
687
694
  // Must be one of the first handlers (to catch all the errors).
688
695
  app.use(middleware$1);
696
+ app.use(middleware$7);
689
697
  app.use(middleware$6);
690
698
  app.use(middleware$5);
691
699
  app.use(middleware$4);
@@ -710,22 +718,6 @@ class Integration {
710
718
  app.use(middleware);
711
719
  // Start the server.
712
720
  this.instance = app.listen(this.port, () => console.info(`Server started on port ${this.port}.`));
713
- // Trap exit signals.
714
- ['SIGTERM', 'SIGINT', 'SIGUSR2'].forEach(signalType => {
715
- process.once(signalType, async () => {
716
- console.info(`Received termination signal ${signalType}. Exiting.`);
717
- try {
718
- if (this.instance) {
719
- this.instance.close();
720
- }
721
- await shutdownCaches();
722
- }
723
- catch (e) {
724
- console.error('Failed to gracefully exit', e);
725
- }
726
- process.exit();
727
- });
728
- });
729
721
  }
730
722
  }
731
723
 
@@ -3,6 +3,7 @@ export { Cache } from './resources/cache.js';
3
3
  export { default as Integration } from './integration.js';
4
4
  export * from './handler.js';
5
5
  export { Provider, type Response as ProviderResponse, type RequestOptions as ProviderRequestOptions, type RateLimiter, } from './resources/provider.js';
6
+ export type { Secrets } from './middlewares/secrets.js';
6
7
  export type { Credentials } from './middlewares/credentials.js';
7
8
  export * as HttpErrors from './httpErrors.js';
8
9
  export * from './resources/context.js';
@@ -3,11 +3,11 @@ import { InvalidHandler } from './errors.js';
3
3
  import correlationIdMiddleware from './middlewares/correlationId.js';
4
4
  import loggerMiddleware from './middlewares/logger.js';
5
5
  import credentialsMiddleware from './middlewares/credentials.js';
6
+ import secretsMiddleware from './middlewares/secrets.js';
6
7
  import selectsMiddleware from './middlewares/selects.js';
7
8
  import errorsMiddleware from './middlewares/errors.js';
8
9
  import finishMiddleware from './middlewares/finish.js';
9
10
  import notFoundMiddleware from './middlewares/notFound.js';
10
- import { shutdownCaches } from './resources/cache.js';
11
11
  import { Handler } from './handler.js';
12
12
  function printErrorMessage(message) {
13
13
  console.error();
@@ -65,6 +65,7 @@ export default class Integration {
65
65
  app.use(correlationIdMiddleware);
66
66
  app.use(loggerMiddleware);
67
67
  app.use(credentialsMiddleware);
68
+ app.use(secretsMiddleware);
68
69
  app.use(selectsMiddleware);
69
70
  // Load handlers as needed.
70
71
  if (this.handlers.length) {
@@ -86,21 +87,5 @@ export default class Integration {
86
87
  app.use(notFoundMiddleware);
87
88
  // Start the server.
88
89
  this.instance = app.listen(this.port, () => console.info(`Server started on port ${this.port}.`));
89
- // Trap exit signals.
90
- ['SIGTERM', 'SIGINT', 'SIGUSR2'].forEach(signalType => {
91
- process.once(signalType, async () => {
92
- console.info(`Received termination signal ${signalType}. Exiting.`);
93
- try {
94
- if (this.instance) {
95
- this.instance.close();
96
- }
97
- await shutdownCaches();
98
- }
99
- catch (e) {
100
- console.error('Failed to gracefully exit', e);
101
- }
102
- process.exit();
103
- });
104
- });
105
90
  }
106
91
  }
@@ -1,5 +1,4 @@
1
1
  import { FetchingFunction, CachableValue } from 'cachette';
2
- export declare const shutdownCaches: () => Promise<PromiseSettledResult<void>[]>;
3
2
  export declare class Cache {
4
3
  private cacheInstance;
5
4
  private constructor();
@@ -1,13 +1,6 @@
1
1
  import { WriteThroughCache, LocalCache } from 'cachette';
2
2
  import * as uuid from 'uuid';
3
3
  import Logger from './logger.js';
4
- /**
5
- * Array of created caches kept to allow for graceful shutdown on exit signals.
6
- */
7
- const caches = [];
8
- export const shutdownCaches = async () => {
9
- return Promise.allSettled(caches.map(cache => cache.quit()));
10
- };
11
4
  export class Cache {
12
5
  cacheInstance;
13
6
  constructor(cacheInstance) {
@@ -36,8 +29,6 @@ export class Cache {
36
29
  */
37
30
  static create(redisUrl) {
38
31
  const cacheInstance = redisUrl ? new WriteThroughCache(redisUrl) : new LocalCache();
39
- // Push to the array of caches for graceful shutdown on exit signals.
40
- caches.push(cacheInstance);
41
32
  // Intended: the correlation id will be the same for all logs of Cachette.
42
33
  const correlationId = uuid.v4();
43
34
  const logger = new Logger({ correlation_id: correlationId });
@@ -9,14 +9,14 @@ import Logger from '../resources/logger.js';
9
9
  * NOTE: make sure to return one of the supported HttpErrors from the SDK, otherwise the error will be translated to a
10
10
  * generic server (500) error.
11
11
  *
12
- * @param context - The credentials of the caller.
12
+ * @param options - The credentials and the logger from the RequestOptions passed with the provider call.
13
13
  * @param targetFunction - The function to call the provider.
14
14
  * @returns The response from the provider.
15
15
  * @throws RateLimitExceededError when the rate limit is exceeded.
16
16
  * @throws WouldExceedRateLimitError when the next call would exceed the rate limit.
17
17
  * @throws HttpError when the provider returns an error.
18
18
  */
19
- export type RateLimiter = <T>(context: {
19
+ export type RateLimiter = <T>(options: {
20
20
  credentials: Credentials;
21
21
  logger: Logger;
22
22
  }, targetFunction: () => Promise<Response<T>>) => Promise<Response<T>>;
@@ -37,7 +37,7 @@ export interface Response<T> {
37
37
  }
38
38
  export declare class Provider {
39
39
  protected rateLimiter: RateLimiter | undefined;
40
- protected prepareRequest: (context: {
40
+ protected prepareRequest: (options: {
41
41
  credentials: Credentials;
42
42
  logger: Logger;
43
43
  }) => {
@@ -1,14 +1,14 @@
1
1
  import assert from 'node:assert/strict';
2
2
  import { describe, it } from 'node:test';
3
3
  import { LocalCache } from 'cachette';
4
- import { Cache, shutdownCaches } from '../../src/resources/cache.js';
4
+ import { Cache } from '../../src/resources/cache.js';
5
5
  describe('Cache', () => {
6
6
  describe('initializeCache', () => {
7
7
  it('no redis url returns Cache with a inner LocalCache', async () => {
8
8
  const cache = Cache.create();
9
9
  assert.ok(cache instanceof Cache);
10
10
  assert.ok(cache['cacheInstance'] instanceof LocalCache);
11
- await shutdownCaches();
11
+ await cache['cacheInstance'].quit();
12
12
  });
13
13
  it('redis url returns (tries) WriteThroughCache', () => {
14
14
  assert.throws(() => Cache.create('fakeredis'), Error, 'Invalid redis url fakereis.');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@unito/integration-sdk",
3
- "version": "0.1.10",
3
+ "version": "0.1.11",
4
4
  "description": "Integration SDK",
5
5
  "type": "module",
6
6
  "types": "dist/src/index.d.ts",
package/src/index.ts CHANGED
@@ -9,6 +9,7 @@ export {
9
9
  type RequestOptions as ProviderRequestOptions,
10
10
  type RateLimiter,
11
11
  } from './resources/provider.js';
12
+ export type { Secrets } from './middlewares/secrets.js';
12
13
  export type { Credentials } from './middlewares/credentials.js';
13
14
  export * as HttpErrors from './httpErrors.js';
14
15
  export * from './resources/context.js';
@@ -5,11 +5,11 @@ import { InvalidHandler } from './errors.js';
5
5
  import correlationIdMiddleware from './middlewares/correlationId.js';
6
6
  import loggerMiddleware from './middlewares/logger.js';
7
7
  import credentialsMiddleware from './middlewares/credentials.js';
8
+ import secretsMiddleware from './middlewares/secrets.js';
8
9
  import selectsMiddleware from './middlewares/selects.js';
9
10
  import errorsMiddleware from './middlewares/errors.js';
10
11
  import finishMiddleware from './middlewares/finish.js';
11
12
  import notFoundMiddleware from './middlewares/notFound.js';
12
- import { shutdownCaches } from './resources/cache.js';
13
13
  import { HandlersInput, Handler } from './handler.js';
14
14
 
15
15
  function printErrorMessage(message: string) {
@@ -81,6 +81,7 @@ export default class Integration {
81
81
  app.use(correlationIdMiddleware);
82
82
  app.use(loggerMiddleware);
83
83
  app.use(credentialsMiddleware);
84
+ app.use(secretsMiddleware);
84
85
  app.use(selectsMiddleware);
85
86
 
86
87
  // Load handlers as needed.
@@ -105,24 +106,5 @@ export default class Integration {
105
106
 
106
107
  // Start the server.
107
108
  this.instance = app.listen(this.port, () => console.info(`Server started on port ${this.port}.`));
108
-
109
- // Trap exit signals.
110
- ['SIGTERM', 'SIGINT', 'SIGUSR2'].forEach(signalType => {
111
- process.once(signalType, async () => {
112
- console.info(`Received termination signal ${signalType}. Exiting.`);
113
-
114
- try {
115
- if (this.instance) {
116
- this.instance.close();
117
- }
118
-
119
- await shutdownCaches();
120
- } catch (e) {
121
- console.error('Failed to gracefully exit', e);
122
- }
123
-
124
- process.exit();
125
- });
126
- });
127
109
  }
128
110
  }
@@ -2,15 +2,6 @@ import { WriteThroughCache, LocalCache, CacheInstance, FetchingFunction, Cachabl
2
2
  import * as uuid from 'uuid';
3
3
  import Logger from './logger.js';
4
4
 
5
- /**
6
- * Array of created caches kept to allow for graceful shutdown on exit signals.
7
- */
8
- const caches: CacheInstance[] = [];
9
-
10
- export const shutdownCaches = async () => {
11
- return Promise.allSettled(caches.map(cache => cache.quit()));
12
- };
13
-
14
5
  export class Cache {
15
6
  private cacheInstance: CacheInstance;
16
7
 
@@ -53,9 +44,6 @@ export class Cache {
53
44
  public static create(redisUrl?: string): Cache {
54
45
  const cacheInstance: CacheInstance = redisUrl ? new WriteThroughCache(redisUrl) : new LocalCache();
55
46
 
56
- // Push to the array of caches for graceful shutdown on exit signals.
57
- caches.push(cacheInstance);
58
-
59
47
  // Intended: the correlation id will be the same for all logs of Cachette.
60
48
  const correlationId = uuid.v4();
61
49
 
@@ -11,7 +11,7 @@ import Logger from '../resources/logger.js';
11
11
  * NOTE: make sure to return one of the supported HttpErrors from the SDK, otherwise the error will be translated to a
12
12
  * generic server (500) error.
13
13
  *
14
- * @param context - The credentials of the caller.
14
+ * @param options - The credentials and the logger from the RequestOptions passed with the provider call.
15
15
  * @param targetFunction - The function to call the provider.
16
16
  * @returns The response from the provider.
17
17
  * @throws RateLimitExceededError when the rate limit is exceeded.
@@ -19,7 +19,7 @@ import Logger from '../resources/logger.js';
19
19
  * @throws HttpError when the provider returns an error.
20
20
  */
21
21
  export type RateLimiter = <T>(
22
- context: { credentials: Credentials; logger: Logger },
22
+ options: { credentials: Credentials; logger: Logger },
23
23
  targetFunction: () => Promise<Response<T>>,
24
24
  ) => Promise<Response<T>>;
25
25
 
@@ -38,7 +38,7 @@ export interface Response<T> {
38
38
 
39
39
  export class Provider {
40
40
  protected rateLimiter: RateLimiter | undefined = undefined;
41
- protected prepareRequest: (context: { credentials: Credentials; logger: Logger }) => {
41
+ protected prepareRequest: (options: { credentials: Credentials; logger: Logger }) => {
42
42
  url: string;
43
43
  headers: Record<string, string>;
44
44
  };
@@ -1,7 +1,7 @@
1
1
  import assert from 'node:assert/strict';
2
2
  import { describe, it } from 'node:test';
3
3
  import { LocalCache } from 'cachette';
4
- import { Cache, shutdownCaches } from '../../src/resources/cache.js';
4
+ import { Cache } from '../../src/resources/cache.js';
5
5
 
6
6
  describe('Cache', () => {
7
7
  describe('initializeCache', () => {
@@ -11,7 +11,7 @@ describe('Cache', () => {
11
11
  assert.ok(cache instanceof Cache);
12
12
  assert.ok(cache['cacheInstance'] instanceof LocalCache);
13
13
 
14
- await shutdownCaches();
14
+ await cache['cacheInstance'].quit();
15
15
  });
16
16
 
17
17
  it('redis url returns (tries) WriteThroughCache', () => {