@unito/integration-sdk 0.1.11 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/handler.d.ts +39 -0
- package/dist/src/handler.js +9 -0
- package/dist/src/httpErrors.d.ts +29 -0
- package/dist/src/httpErrors.js +30 -0
- package/dist/src/index.cjs +274 -16
- package/dist/src/index.d.ts +1 -0
- package/dist/src/integration.d.ts +49 -0
- package/dist/src/integration.js +51 -0
- package/dist/src/middlewares/filters.d.ts +11 -2
- package/dist/src/middlewares/secrets.d.ts +5 -0
- package/dist/src/middlewares/signal.d.ts +15 -0
- package/dist/src/middlewares/signal.js +22 -0
- package/dist/src/resources/cache.d.ts +51 -1
- package/dist/src/resources/cache.js +51 -1
- package/dist/src/resources/context.d.ts +42 -13
- package/dist/src/resources/logger.d.ts +17 -0
- package/dist/src/resources/logger.js +17 -0
- package/dist/src/resources/provider.d.ts +90 -5
- package/dist/src/resources/provider.js +92 -11
- package/dist/test/middlewares/signal.test.d.ts +1 -0
- package/dist/test/middlewares/signal.test.js +20 -0
- package/dist/test/resources/provider.test.js +116 -21
- package/package.json +4 -4
- package/src/handler.ts +48 -0
- package/src/httpErrors.ts +30 -0
- package/src/index.ts +1 -0
- package/src/integration.ts +51 -0
- package/src/middlewares/filters.ts +11 -2
- package/src/middlewares/secrets.ts +5 -0
- package/src/middlewares/signal.ts +41 -0
- package/src/resources/cache.ts +51 -1
- package/src/resources/context.ts +50 -33
- package/src/resources/logger.ts +17 -0
- package/src/resources/provider.ts +115 -16
- package/test/middlewares/signal.test.ts +28 -0
- package/test/resources/provider.test.ts +122 -21
package/src/httpErrors.ts
CHANGED
|
@@ -1,48 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error class meant to be returned by integrations in case of exceptions. These errors will be caught and handled
|
|
3
|
+
* appropriately. Any other error would result in an unhandled server error accompanied by a 500 status code.
|
|
4
|
+
*
|
|
5
|
+
* @field message - The error message
|
|
6
|
+
* @field status - The HTTP status code to return
|
|
7
|
+
*/
|
|
1
8
|
export class HttpError extends Error {
|
|
2
9
|
readonly status: number;
|
|
3
10
|
|
|
4
11
|
constructor(message: string, status: number) {
|
|
5
12
|
super(message);
|
|
6
13
|
this.status = status;
|
|
14
|
+
this.name = this.constructor.name;
|
|
7
15
|
}
|
|
8
16
|
}
|
|
9
17
|
|
|
18
|
+
/**
|
|
19
|
+
* Used to generate a 400 Bad Request. Usually used when something is missing to properly handle the request.
|
|
20
|
+
*/
|
|
10
21
|
export class BadRequestError extends HttpError {
|
|
11
22
|
constructor(message?: string) {
|
|
12
23
|
super(message || 'Bad request', 400);
|
|
13
24
|
}
|
|
14
25
|
}
|
|
15
26
|
|
|
27
|
+
/**
|
|
28
|
+
* Used to generate a 401 Unauthorized. Usually used when the credentials are missing or invalid.
|
|
29
|
+
*/
|
|
16
30
|
export class UnauthorizedError extends HttpError {
|
|
17
31
|
constructor(message?: string) {
|
|
18
32
|
super(message || 'Unauthorized', 401);
|
|
19
33
|
}
|
|
20
34
|
}
|
|
21
35
|
|
|
36
|
+
/**
|
|
37
|
+
* Used to generate a 404 Not Found. Usually used when the requested `Item` is not found.
|
|
38
|
+
*/
|
|
22
39
|
export class NotFoundError extends HttpError {
|
|
23
40
|
constructor(message?: string) {
|
|
24
41
|
super(message || 'Not found', 404);
|
|
25
42
|
}
|
|
26
43
|
}
|
|
27
44
|
|
|
45
|
+
/**
|
|
46
|
+
* Used to generate a 408 Timeout Error. Usually used when the call length exceeds the received Operation Deadline.
|
|
47
|
+
*/
|
|
28
48
|
export class TimeoutError extends HttpError {
|
|
29
49
|
constructor(message?: string) {
|
|
30
50
|
super(message || 'Not found', 408);
|
|
31
51
|
}
|
|
32
52
|
}
|
|
33
53
|
|
|
54
|
+
/**
|
|
55
|
+
* Used to generate a 410 Resource Gone.
|
|
56
|
+
*/
|
|
34
57
|
export class ResourceGoneError extends HttpError {
|
|
35
58
|
constructor(message?: string) {
|
|
36
59
|
super(message || 'Resource gone or unavailable', 410);
|
|
37
60
|
}
|
|
38
61
|
}
|
|
39
62
|
|
|
63
|
+
/**
|
|
64
|
+
* Used to generate a 422 Unprocessable Entity. Usually used when an operation is invalid.
|
|
65
|
+
*/
|
|
40
66
|
export class UnprocessableEntityError extends HttpError {
|
|
41
67
|
constructor(message?: string) {
|
|
42
68
|
super(message || 'Unprocessable Entity', 422);
|
|
43
69
|
}
|
|
44
70
|
}
|
|
45
71
|
|
|
72
|
+
/**
|
|
73
|
+
* Used to generate a 429 Unprocessable Entity. Usually used when an operation triggers or would trigger a rate limit
|
|
74
|
+
* error on the provider's side.
|
|
75
|
+
*/
|
|
46
76
|
export class RateLimitExceededError extends HttpError {
|
|
47
77
|
constructor(message?: string) {
|
|
48
78
|
super(message || 'Rate Limit Exceeded', 429);
|
package/src/index.ts
CHANGED
|
@@ -13,4 +13,5 @@ export type { Secrets } from './middlewares/secrets.js';
|
|
|
13
13
|
export type { Credentials } from './middlewares/credentials.js';
|
|
14
14
|
export * as HttpErrors from './httpErrors.js';
|
|
15
15
|
export * from './resources/context.js';
|
|
16
|
+
export { type default as Logger } from './resources/logger.js';
|
|
16
17
|
/* c8 ignore stop */
|
package/src/integration.ts
CHANGED
|
@@ -5,6 +5,7 @@ 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 signalMiddleware from './middlewares/signal.js';
|
|
8
9
|
import secretsMiddleware from './middlewares/secrets.js';
|
|
9
10
|
import selectsMiddleware from './middlewares/selects.js';
|
|
10
11
|
import errorsMiddleware from './middlewares/errors.js';
|
|
@@ -22,6 +23,18 @@ type Options = {
|
|
|
22
23
|
port?: number;
|
|
23
24
|
};
|
|
24
25
|
|
|
26
|
+
/**
|
|
27
|
+
* Main class for the Integration SDK providing an abstraction layer between the Integration's Graph definition
|
|
28
|
+
* and the underlying HTTP server.
|
|
29
|
+
*
|
|
30
|
+
* An `Integration` instance can have multiple handlers configured to handle different routes. Upon receiving a request,
|
|
31
|
+
* the Integration will parse the request to extract meaninful information, match the request to the appropriate handler
|
|
32
|
+
* method and forward that information in the form a {@link Context} object.
|
|
33
|
+
* The Integration also offer standardized error handling and logging to help you build a robust
|
|
34
|
+
* and reliable Integration.
|
|
35
|
+
*
|
|
36
|
+
* See our {@link https://dev.unito.io/docs/ | documentation} for more examples on how to build an integration.
|
|
37
|
+
*/
|
|
25
38
|
export default class Integration {
|
|
26
39
|
private handlers: Handler[];
|
|
27
40
|
|
|
@@ -29,11 +42,41 @@ export default class Integration {
|
|
|
29
42
|
|
|
30
43
|
private port: number;
|
|
31
44
|
|
|
45
|
+
/**
|
|
46
|
+
* Creates a new Integration instance with default port set to 9200.
|
|
47
|
+
*
|
|
48
|
+
* @param options The {@link Options} to configure the Integration instance. Can be used to override the default port.
|
|
49
|
+
*/
|
|
32
50
|
constructor(options: Options = {}) {
|
|
33
51
|
this.port = options.port || 9200;
|
|
34
52
|
this.handlers = [];
|
|
35
53
|
}
|
|
36
54
|
|
|
55
|
+
/**
|
|
56
|
+
* Adds a group of common handlers to the integration.
|
|
57
|
+
*
|
|
58
|
+
* Handlers added to the integration can be one of the following:
|
|
59
|
+
* - `ItemHandlers`: A group of handlers defining the implementation of the Operations available for a given item.
|
|
60
|
+
* - `CredentialAccountHandlers`: A handler returning the CredentialAccount linked to the caller's credentials.
|
|
61
|
+
* - `ParseWebhookHandlers`: A handler parsing the content of an incoming webhook.
|
|
62
|
+
* - `WebhookSubscriptionHandlers`: A handler subscribing or unsubscribing to a particular webhook.
|
|
63
|
+
* - `AcknowledgeWebhookHandlers`: A handler acknowledging the reception of a webhook.
|
|
64
|
+
*
|
|
65
|
+
* To accomodate the fact that ItemHandlers may specify multiple operations, some at the collection level, some at the
|
|
66
|
+
* item level, we need a way to define the route for each of these operations.
|
|
67
|
+
* To achieve this, we assume that if the last part of the path is a variable, then it is the item identifier.
|
|
68
|
+
*
|
|
69
|
+
* @example The following path: `/trainer/:trainerId/pokemons/:pokemonId` will lead to the following
|
|
70
|
+
* routes:
|
|
71
|
+
* - getCollection will be called for `GET /trainer/:trainerId/pokemons/` requests
|
|
72
|
+
* - getItem will be called for `GET /trainer/:trainerId/pokemons/:pokemonId` requests
|
|
73
|
+
* - createItem will be called for `POST /trainer/:trainerId/pokemons/` requests
|
|
74
|
+
* - updateItem will be called for `PATCH /trainer/:trainerId/pokemons/:pokemonId` requests
|
|
75
|
+
* - deleteItem will be called for `DELETE /trainer/:trainerId/pokemons/:pokemonId` requests
|
|
76
|
+
*
|
|
77
|
+
* @param path The path to be used as Route for the handlers.
|
|
78
|
+
* @param handlers The Handlers definition.
|
|
79
|
+
*/
|
|
37
80
|
public addHandler(path: string, handlers: HandlersInput): void {
|
|
38
81
|
if (this.instance) {
|
|
39
82
|
printErrorMessage(`
|
|
@@ -66,6 +109,13 @@ export default class Integration {
|
|
|
66
109
|
}
|
|
67
110
|
}
|
|
68
111
|
|
|
112
|
+
/**
|
|
113
|
+
* Starts the server and listens on the specified port (default to 9200).
|
|
114
|
+
*
|
|
115
|
+
* @remarks
|
|
116
|
+
* This function should be called after all the handlers have been added to the integration
|
|
117
|
+
* and any other configuration is completed.
|
|
118
|
+
*/
|
|
69
119
|
public start() {
|
|
70
120
|
// Express Server initialization
|
|
71
121
|
const app: express.Application = express();
|
|
@@ -83,6 +133,7 @@ export default class Integration {
|
|
|
83
133
|
app.use(credentialsMiddleware);
|
|
84
134
|
app.use(secretsMiddleware);
|
|
85
135
|
app.use(selectsMiddleware);
|
|
136
|
+
app.use(signalMiddleware);
|
|
86
137
|
|
|
87
138
|
// Load handlers as needed.
|
|
88
139
|
if (this.handlers.length) {
|
|
@@ -10,13 +10,22 @@ declare global {
|
|
|
10
10
|
}
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
/**
|
|
14
|
+
* Represents one filter parsed from the filters query param.
|
|
15
|
+
*
|
|
16
|
+
* Given a filters query param containing:
|
|
17
|
+
* `filters=[...],name=John,[...]`
|
|
18
|
+
*
|
|
19
|
+
* Filter for `name=John` will be:
|
|
20
|
+
* `{ field: 'name', operator: 'EQUAL', values: ['John'] }`
|
|
21
|
+
*/
|
|
22
|
+
export type Filter = {
|
|
14
23
|
field: string;
|
|
15
24
|
operator: OperatorType;
|
|
16
25
|
// Without the schema of the item,
|
|
17
26
|
// we can't determine the types of the values (number, boolean, etc).
|
|
18
27
|
values: string[] | undefined;
|
|
19
|
-
}
|
|
28
|
+
};
|
|
20
29
|
|
|
21
30
|
// The operators are ordered by their symbol length, in descending order.
|
|
22
31
|
// This is necessary because the symbol of an operator can be
|
|
@@ -10,6 +10,11 @@ declare global {
|
|
|
10
10
|
}
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
+
/**
|
|
14
|
+
* Represents the secrets parsed from the X-Unito-Secrets header.
|
|
15
|
+
*
|
|
16
|
+
* This is the decrypted payload of the secrets defined in the integration's configuration.
|
|
17
|
+
*/
|
|
13
18
|
export type Secrets = { [keys: string]: unknown };
|
|
14
19
|
|
|
15
20
|
const SECRETS_HEADER = 'X-Unito-Secrets';
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { Request, Response, NextFunction } from 'express';
|
|
2
|
+
import { TimeoutError } from '../httpErrors.js';
|
|
3
|
+
|
|
4
|
+
declare global {
|
|
5
|
+
// eslint-disable-next-line @typescript-eslint/no-namespace
|
|
6
|
+
namespace Express {
|
|
7
|
+
interface Locals {
|
|
8
|
+
/**
|
|
9
|
+
* An AbortSignal instantiated with the X-Unito-Operation-Deadline header. This header contains the timestamp
|
|
10
|
+
* after which Unito will consider the operation to be timed out. You can use this signal to abort any
|
|
11
|
+
* operation that would exceed this time frame.
|
|
12
|
+
*/
|
|
13
|
+
signal: AbortSignal;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const OPERATION_DEADLINE_HEADER = 'X-Unito-Operation-Deadline';
|
|
19
|
+
|
|
20
|
+
const middleware = (req: Request, res: Response, next: NextFunction) => {
|
|
21
|
+
const operationDeadlineHeader = Number(req.header(OPERATION_DEADLINE_HEADER));
|
|
22
|
+
|
|
23
|
+
if (operationDeadlineHeader) {
|
|
24
|
+
// `operationDeadlineHeader` represents a timestamp in the future, in seconds.
|
|
25
|
+
// We need to convert it to a number of milliseconds.
|
|
26
|
+
const deadline = operationDeadlineHeader * 1000 - Date.now();
|
|
27
|
+
|
|
28
|
+
if (deadline > 0) {
|
|
29
|
+
res.locals.signal = AbortSignal.timeout(deadline);
|
|
30
|
+
} else {
|
|
31
|
+
throw new TimeoutError('Request already timed out upon reception');
|
|
32
|
+
}
|
|
33
|
+
} else {
|
|
34
|
+
// Default to 20s, which is the maximum time frame allowed for an operation by Unito.
|
|
35
|
+
res.locals.signal = AbortSignal.timeout(20000);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
next();
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
export default middleware;
|
package/src/resources/cache.ts
CHANGED
|
@@ -2,6 +2,12 @@ import { WriteThroughCache, LocalCache, CacheInstance, FetchingFunction, Cachabl
|
|
|
2
2
|
import * as uuid from 'uuid';
|
|
3
3
|
import Logger from './logger.js';
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* The Cache class provides caching capabilities that can be used across your integration.
|
|
7
|
+
* It can be backed by a Redis instance (by passing it a URL to the instance) or a local cache.
|
|
8
|
+
*
|
|
9
|
+
* @see {@link Cache.create}
|
|
10
|
+
*/
|
|
5
11
|
export class Cache {
|
|
6
12
|
private cacheInstance: CacheInstance;
|
|
7
13
|
|
|
@@ -9,6 +15,19 @@ export class Cache {
|
|
|
9
15
|
this.cacheInstance = cacheInstance;
|
|
10
16
|
}
|
|
11
17
|
|
|
18
|
+
/**
|
|
19
|
+
* Get or fetch a value
|
|
20
|
+
*
|
|
21
|
+
* @param key The key of the value to get
|
|
22
|
+
* @param ttl The time to live of the value in seconds.
|
|
23
|
+
* @param fetchFn The function that can retrieve the original value
|
|
24
|
+
* @param lockTtl Global distributed lock TTL (in seconds) protecting fetching.
|
|
25
|
+
* If undefined, 0 or falsy, locking is not preformed
|
|
26
|
+
* @param shouldCacheError A callback being passed errors, controlling whether
|
|
27
|
+
* to cache or not errors. Defaults to never cache.
|
|
28
|
+
*
|
|
29
|
+
* @returns The cached or fetched value
|
|
30
|
+
*/
|
|
12
31
|
public getOrFetchValue<F extends FetchingFunction = FetchingFunction>(
|
|
13
32
|
key: string,
|
|
14
33
|
ttl: number,
|
|
@@ -19,24 +38,55 @@ export class Cache {
|
|
|
19
38
|
return this.cacheInstance.getOrFetchValue(key, ttl, fetcher, lockTtl, shouldCacheError);
|
|
20
39
|
}
|
|
21
40
|
|
|
41
|
+
/**
|
|
42
|
+
* Get a value from the cache.
|
|
43
|
+
*
|
|
44
|
+
* @param key The key of the value to get.
|
|
45
|
+
*
|
|
46
|
+
* @return The value associated with the key, or undefined if
|
|
47
|
+
* no such value exists.
|
|
48
|
+
*/
|
|
22
49
|
public getValue(key: string): Promise<CachableValue> {
|
|
23
50
|
return this.cacheInstance.getValue(key);
|
|
24
51
|
}
|
|
25
52
|
|
|
53
|
+
/**
|
|
54
|
+
* Set a value in the cache.
|
|
55
|
+
*
|
|
56
|
+
* @param key The key of the value to set.
|
|
57
|
+
* @param value The value to set.
|
|
58
|
+
* @param ttl The time to live of the value in seconds.
|
|
59
|
+
* By default, the value will not expire
|
|
60
|
+
*
|
|
61
|
+
* @return true if the value was stored, false otherwise.
|
|
62
|
+
*/
|
|
26
63
|
public setValue(key: string, value: CachableValue, ttl?: number): Promise<boolean> {
|
|
27
64
|
return this.cacheInstance.setValue(key, value, ttl);
|
|
28
65
|
}
|
|
29
66
|
|
|
67
|
+
/**
|
|
68
|
+
* Delete a value from the cache.
|
|
69
|
+
* @param key — The key of the value to set.
|
|
70
|
+
*/
|
|
30
71
|
public delValue(key: string): Promise<void> {
|
|
31
72
|
return this.cacheInstance.delValue(key);
|
|
32
73
|
}
|
|
33
74
|
|
|
75
|
+
/**
|
|
76
|
+
* Get the TTL of an entry, in ms
|
|
77
|
+
*
|
|
78
|
+
* @param key The key of the entry whose ttl to retrieve
|
|
79
|
+
*
|
|
80
|
+
* @return The remaining TTL on the entry, in ms.
|
|
81
|
+
* undefined if the entry does not exist.
|
|
82
|
+
* 0 if the entry does not expire.
|
|
83
|
+
*/
|
|
34
84
|
public getTtl(key: string): Promise<number | undefined> {
|
|
35
85
|
return this.cacheInstance.getTtl(key);
|
|
36
86
|
}
|
|
37
87
|
|
|
38
88
|
/**
|
|
39
|
-
* Initializes a
|
|
89
|
+
* Initializes a Cache backed by the Redis instance at the provided url if present, or a LocalCache otherwise.
|
|
40
90
|
*
|
|
41
91
|
* @param redisUrl - The redis url to connect to (optional).
|
|
42
92
|
* @returns A cache instance.
|
package/src/resources/context.ts
CHANGED
|
@@ -6,7 +6,21 @@ import { Credentials } from '../middlewares/credentials.js';
|
|
|
6
6
|
import { Secrets } from 'src/middlewares/secrets.js';
|
|
7
7
|
import { Filter } from '../middlewares/filters.js';
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
type Maybe<T> = T | null;
|
|
10
|
+
type Empty = Record<string, never>;
|
|
11
|
+
type Params = Record<string, string>;
|
|
12
|
+
type Query = {
|
|
13
|
+
[key: string]: undefined | string | string[] | Query | Query[];
|
|
14
|
+
};
|
|
15
|
+
type CreateItemBody = API.CreateItemRequestPayload;
|
|
16
|
+
type UpdateItemBody = API.UpdateItemRequestPayload;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* The base context object is passed to every handler function.
|
|
20
|
+
*
|
|
21
|
+
* It contains the parsed request params, query string, credentials, secrets, etc.
|
|
22
|
+
*/
|
|
23
|
+
export type Context<P extends Maybe<Params> = Params, Q extends Maybe<Query> = Query> = {
|
|
10
24
|
/**
|
|
11
25
|
* The parsed credentials associated with the request through the X-Unito-Credentials header.
|
|
12
26
|
*
|
|
@@ -23,6 +37,12 @@ export type Context<P extends Record<string, string>, Q extends ParsedQueryStrin
|
|
|
23
37
|
* The logger pre decorated with the correlation ID and the additionnal metadata provided through the request headers.
|
|
24
38
|
*/
|
|
25
39
|
logger: Logger;
|
|
40
|
+
/**
|
|
41
|
+
* Each request is expected to complete within a certain time frame. This signal object has been instantiated with the
|
|
42
|
+
* X-Unito-Operation-Deadline header. This header contains the timestamp after which Unito will consider the operation
|
|
43
|
+
* to be timed out. You can use this signal to abort any operation that would exceed this time frame.
|
|
44
|
+
*/
|
|
45
|
+
signal: AbortSignal;
|
|
26
46
|
/**
|
|
27
47
|
* The request params.
|
|
28
48
|
*
|
|
@@ -40,15 +60,20 @@ export type Context<P extends Record<string, string>, Q extends ParsedQueryStrin
|
|
|
40
60
|
query: Q;
|
|
41
61
|
};
|
|
42
62
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
63
|
+
/**
|
|
64
|
+
* Context received by the `GetItemHandler`.
|
|
65
|
+
*
|
|
66
|
+
* @see {@link Context}
|
|
67
|
+
*/
|
|
68
|
+
export type GetItemContext<P extends Maybe<Params> = Empty, Q extends Query = Empty> = Context<P, Q>;
|
|
47
69
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
70
|
+
/**
|
|
71
|
+
* Context received by the `GetCollectionHandler`.
|
|
72
|
+
*
|
|
73
|
+
* @filters Array of {@link Filter} representing the filterss parsed from the query params
|
|
74
|
+
* @see {@link Context} for base params
|
|
75
|
+
*/
|
|
76
|
+
export type GetCollectionContext<P extends Maybe<Params> = Empty, Q extends Query = Empty> = Context<P, Q> & {
|
|
52
77
|
/**
|
|
53
78
|
* Parsed filter query param yielding a list of filters.
|
|
54
79
|
*
|
|
@@ -60,6 +85,8 @@ export type GetCollectionContext<
|
|
|
60
85
|
* { field: 'name', operator: 'EQUAL', values: ['John'] },
|
|
61
86
|
* { field: 'department.name', operator: 'EQUAL', values: ['Engineering'] }
|
|
62
87
|
* ]
|
|
88
|
+
*
|
|
89
|
+
* @see {@link Filter}
|
|
63
90
|
*/
|
|
64
91
|
filters: Filter[];
|
|
65
92
|
/**
|
|
@@ -75,46 +102,36 @@ export type GetCollectionContext<
|
|
|
75
102
|
};
|
|
76
103
|
|
|
77
104
|
export type CreateItemContext<
|
|
78
|
-
P extends
|
|
79
|
-
Q extends
|
|
80
|
-
B extends
|
|
105
|
+
P extends Maybe<Params> = Empty,
|
|
106
|
+
Q extends Maybe<Query> = Empty,
|
|
107
|
+
B extends CreateItemBody = API.CreateItemRequestPayload,
|
|
81
108
|
> = Context<P, Q> & { body: B };
|
|
82
109
|
|
|
83
110
|
export type UpdateItemContext<
|
|
84
|
-
P extends
|
|
85
|
-
Q extends
|
|
86
|
-
B extends
|
|
111
|
+
P extends Maybe<Params> = Empty,
|
|
112
|
+
Q extends Maybe<Query> = Empty,
|
|
113
|
+
B extends UpdateItemBody = API.UpdateItemRequestPayload,
|
|
87
114
|
> = Context<P, Q> & { body: B };
|
|
88
115
|
|
|
89
|
-
export type DeleteItemContext<
|
|
90
|
-
P extends Record<string, string> = Record<string, never>,
|
|
91
|
-
Q extends Record<string, string> = Record<string, never>,
|
|
92
|
-
> = Context<P, Q>;
|
|
116
|
+
export type DeleteItemContext<P extends Maybe<Params> = Empty, Q extends Query = Empty> = Context<P, Q>;
|
|
93
117
|
|
|
94
|
-
export type GetCredentialAccountContext<
|
|
95
|
-
P extends Record<string, string> = Record<string, never>,
|
|
96
|
-
Q extends Record<string, string> = Record<string, never>,
|
|
97
|
-
> = Context<P, Q>;
|
|
118
|
+
export type GetCredentialAccountContext<P extends Maybe<Params> = Empty, Q extends Query = Empty> = Context<P, Q>;
|
|
98
119
|
|
|
99
120
|
export type ParseWebhooksContext<
|
|
100
|
-
P extends
|
|
101
|
-
Q extends
|
|
121
|
+
P extends Maybe<Params> = Empty,
|
|
122
|
+
Q extends Maybe<Query> = Empty,
|
|
102
123
|
B extends API.WebhookParseRequestPayload = API.WebhookParseRequestPayload,
|
|
103
124
|
> = Omit<Context<P, Q>, 'credentials'> & { body: B };
|
|
104
125
|
|
|
105
126
|
export type UpdateWebhookSubscriptionsContext<
|
|
106
|
-
P extends
|
|
107
|
-
Q extends
|
|
127
|
+
P extends Maybe<Params> = Empty,
|
|
128
|
+
Q extends Maybe<Query> = Empty,
|
|
108
129
|
B extends API.WebhookSubscriptionRequestPayload = API.WebhookSubscriptionRequestPayload,
|
|
109
130
|
> = Context<P, Q> & { body: B };
|
|
110
131
|
|
|
111
132
|
export type AcknowledgeWebhooksContext<
|
|
112
|
-
P extends
|
|
113
|
-
Q extends
|
|
133
|
+
P extends Maybe<Params> = Empty,
|
|
134
|
+
Q extends Maybe<Query> = Empty,
|
|
114
135
|
B extends API.WebhookParseRequestPayload = API.WebhookParseRequestPayload,
|
|
115
136
|
> = Omit<Context<P, Q>, 'credentials'> & { body: B };
|
|
116
|
-
|
|
117
|
-
interface ParsedQueryString {
|
|
118
|
-
[key: string]: undefined | string | string[] | ParsedQueryString | ParsedQueryString[];
|
|
119
|
-
}
|
|
120
137
|
/* c8 ignore stop */
|
package/src/resources/logger.ts
CHANGED
|
@@ -14,6 +14,9 @@ type Value = {
|
|
|
14
14
|
export type Metadata = Value & { message?: never };
|
|
15
15
|
type ForbidenMetadataKey = 'message';
|
|
16
16
|
|
|
17
|
+
/**
|
|
18
|
+
* Logger class that can be configured with metadata add creation and when logging to add additional context to your logs.
|
|
19
|
+
*/
|
|
17
20
|
export default class Logger {
|
|
18
21
|
private metadata: Metadata;
|
|
19
22
|
|
|
@@ -74,10 +77,21 @@ export default class Logger {
|
|
|
74
77
|
this.metadata = { ...this.metadata, ...metadata };
|
|
75
78
|
}
|
|
76
79
|
|
|
80
|
+
/**
|
|
81
|
+
* Return a copy of the Logger's metadata.
|
|
82
|
+
* @returns The {@link Metadata} associated with the logger.
|
|
83
|
+
*/
|
|
77
84
|
public getMetadata(): Metadata {
|
|
78
85
|
return structuredClone(this.metadata);
|
|
79
86
|
}
|
|
80
87
|
|
|
88
|
+
/**
|
|
89
|
+
* Sets a key-value pair in the metadata. If the key already exists, it will be overwritten.
|
|
90
|
+
*
|
|
91
|
+
* @param key Key of the metadata to be set.
|
|
92
|
+
* May be any string other than 'message', which is reserved for the actual message logged.
|
|
93
|
+
* @param value Value of the metadata to be set.
|
|
94
|
+
*/
|
|
81
95
|
public setMetadata<Key extends string>(
|
|
82
96
|
key: Key extends ForbidenMetadataKey ? never : Key,
|
|
83
97
|
value: PrimitiveValue | Value,
|
|
@@ -85,6 +99,9 @@ export default class Logger {
|
|
|
85
99
|
this.metadata[key] = value;
|
|
86
100
|
}
|
|
87
101
|
|
|
102
|
+
/**
|
|
103
|
+
* Clears the Logger's metadata.
|
|
104
|
+
*/
|
|
88
105
|
public clearMetadata(): void {
|
|
89
106
|
this.metadata = {};
|
|
90
107
|
}
|