@squiz/optimization-utils 2.0.1 → 2.0.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 (76) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/dist/cloudflare/ImplCloudflareKVHttpService.d.ts +2 -2
  3. package/dist/cloudflare/ImplCloudflareKVHttpService.js +8 -10
  4. package/dist/cloudflare/ImplCloudflareKVHttpService.js.map +1 -1
  5. package/dist/config/ConfigurationLoader.d.ts +1 -1
  6. package/dist/config/ConfigurationLoader.js +3 -4
  7. package/dist/config/ConfigurationLoader.js.map +1 -1
  8. package/dist/index.d.ts +0 -11
  9. package/dist/index.js +0 -11
  10. package/dist/index.js.map +1 -1
  11. package/dist/scheduler/EventBridgeScheduler.d.ts +1 -1
  12. package/dist/scheduler/EventBridgeScheduler.js +4 -5
  13. package/dist/scheduler/EventBridgeScheduler.js.map +1 -1
  14. package/dist/testing/mock.d.ts +0 -8
  15. package/dist/testing/mock.js +1 -35
  16. package/dist/testing/mock.js.map +1 -1
  17. package/package.json +4 -1
  18. package/src/cloudflare/ImplCloudflareKVHttpService.ts +5 -4
  19. package/src/cloudflare/__tests__/ImplCloudflareKVHttpService.spec.ts +4 -4
  20. package/src/config/ConfigurationLoader.ts +4 -2
  21. package/src/config/__tests__/ConfigurationLoader.spec.ts +3 -3
  22. package/src/event/__tests__/DynamoDBEventMapper.spec.ts +1 -1
  23. package/src/index.ts +0 -16
  24. package/src/scheduler/EventBridgeScheduler.ts +1 -2
  25. package/src/scheduler/__tests__/EventBridgeScheduler.spec.ts +2 -5
  26. package/src/testing/mock.ts +0 -47
  27. package/dist/exception/DomainException.d.ts +0 -18
  28. package/dist/exception/DomainException.js +0 -41
  29. package/dist/exception/DomainException.js.map +0 -1
  30. package/dist/httpClient/FetchHttpClient.d.ts +0 -7
  31. package/dist/httpClient/FetchHttpClient.js +0 -86
  32. package/dist/httpClient/FetchHttpClient.js.map +0 -1
  33. package/dist/httpClient/HttpClient.d.ts +0 -25
  34. package/dist/httpClient/HttpClient.js +0 -45
  35. package/dist/httpClient/HttpClient.js.map +0 -1
  36. package/dist/httpClient/HttpRequestBuilder.d.ts +0 -22
  37. package/dist/httpClient/HttpRequestBuilder.js +0 -126
  38. package/dist/httpClient/HttpRequestBuilder.js.map +0 -1
  39. package/dist/logger/Logger.d.ts +0 -10
  40. package/dist/logger/Logger.js +0 -30
  41. package/dist/logger/Logger.js.map +0 -1
  42. package/dist/logger/LoggerMessage.d.ts +0 -43
  43. package/dist/logger/LoggerMessage.js +0 -111
  44. package/dist/logger/LoggerMessage.js.map +0 -1
  45. package/dist/logger/LogsHandler.d.ts +0 -11
  46. package/dist/logger/LogsHandler.js +0 -66
  47. package/dist/logger/LogsHandler.js.map +0 -1
  48. package/dist/logger/RemoteLogger.d.ts +0 -30
  49. package/dist/logger/RemoteLogger.js +0 -35
  50. package/dist/logger/RemoteLogger.js.map +0 -1
  51. package/dist/logger/SquizRemoteLogger.d.ts +0 -53
  52. package/dist/logger/SquizRemoteLogger.js +0 -128
  53. package/dist/logger/SquizRemoteLogger.js.map +0 -1
  54. package/dist/validation/handleValidation.d.ts +0 -2
  55. package/dist/validation/handleValidation.js +0 -11
  56. package/dist/validation/handleValidation.js.map +0 -1
  57. package/dist/valueObject/TenantId.d.ts +0 -10
  58. package/dist/valueObject/TenantId.js +0 -23
  59. package/dist/valueObject/TenantId.js.map +0 -1
  60. package/src/exception/DomainException.ts +0 -34
  61. package/src/httpClient/FetchHttpClient.ts +0 -92
  62. package/src/httpClient/HttpClient.ts +0 -46
  63. package/src/httpClient/HttpRequestBuilder.ts +0 -120
  64. package/src/httpClient/__tests__/FetchHttpClient.spec.ts +0 -146
  65. package/src/httpClient/__tests__/HttpClient.spec.ts +0 -52
  66. package/src/httpClient/__tests__/httpRequestBuilder.spec.ts +0 -75
  67. package/src/logger/Logger.ts +0 -40
  68. package/src/logger/LoggerMessage.ts +0 -179
  69. package/src/logger/LogsHandler.ts +0 -66
  70. package/src/logger/RemoteLogger.ts +0 -32
  71. package/src/logger/SquizRemoteLogger.ts +0 -154
  72. package/src/logger/__tests__/LoggerMessage.spec.ts +0 -147
  73. package/src/logger/__tests__/LogsHandler.spec.ts +0 -77
  74. package/src/logger/__tests__/SquizRemoteLogger.spec.ts +0 -185
  75. package/src/validation/handleValidation.ts +0 -13
  76. package/src/valueObject/TenantId.ts +0 -27
@@ -1,146 +0,0 @@
1
- import {
2
- HttpClient,
3
- HttpMethod,
4
- HttpRequestOptions,
5
- HttpResponse,
6
- } from '../HttpClient';
7
- import { Container } from 'inversify';
8
- import { FetchHttpClient } from '../FetchHttpClient';
9
- import fetch from 'node-fetch-commonjs';
10
- import { faker } from '@faker-js/faker';
11
- import Mock = jest.Mock;
12
- import { Logger } from '../../logger/Logger';
13
- import {
14
- createLoggerMock,
15
- createResponse,
16
- FetchMock,
17
- } from '../../testing/mock';
18
-
19
- jest.mock('node-fetch-commonjs');
20
-
21
- describe('FetchHttpClient', () => {
22
- let httpClient: HttpClient;
23
- let mockFetch: FetchMock;
24
- let params: HttpRequestOptions;
25
-
26
- beforeEach(() => {
27
- const container = new Container();
28
-
29
- container.bind(Logger).toConstantValue(createLoggerMock());
30
- container.bind(HttpClient).to(FetchHttpClient);
31
- mockFetch = fetch as Mock;
32
- mockFetch.mockReset();
33
- httpClient = container.get(HttpClient);
34
-
35
- params = {
36
- url: faker.internet.url(),
37
- body: faker.word.words(),
38
- headers: {
39
- 'example-header': faker.word.words(),
40
- },
41
- method: faker.helpers.arrayElement(Object.values(HttpMethod)),
42
- };
43
- });
44
-
45
- describe('passing params to fetch', () => {
46
- it('should call the fetch with passed parameters', async () => {
47
- mockFetch.mockResolvedValueOnce(createResponse(200, {}));
48
-
49
- await httpClient.sendRequest(params);
50
-
51
- expect(mockFetch).toHaveBeenCalledWith(params.url, {
52
- body: params.body,
53
- method: params.method,
54
- headers: params.headers,
55
- });
56
- });
57
-
58
- it('should parse request body to JSON if passed Content-Type: application/json', async () => {
59
- mockFetch.mockResolvedValueOnce(createResponse(200, {}));
60
- const body = { example: faker.word.words() };
61
-
62
- await httpClient.sendRequest({
63
- ...params,
64
- body,
65
- headers: {
66
- 'Content-Type': 'application/json',
67
- },
68
- });
69
-
70
- expect(mockFetch).toHaveBeenCalledWith(params.url, {
71
- body: JSON.stringify(body),
72
- method: params.method,
73
- headers: {
74
- 'Content-Type': 'application/json',
75
- },
76
- });
77
- });
78
- });
79
-
80
- describe('handling response', () => {
81
- it('should return a JSON if the response contains Content-Type: application/json in the response', async () => {
82
- const expectedResponse = JSON.stringify({ example: faker.word.words() });
83
-
84
- mockFetch.mockResolvedValueOnce(
85
- createResponse(200, expectedResponse, {
86
- 'Content-Type': 'application/json',
87
- }),
88
- );
89
-
90
- const response = await httpClient.sendRequest(params);
91
-
92
- expect(response).toEqual(
93
- new HttpResponse({
94
- statusCode: 200,
95
- body: expectedResponse,
96
- }),
97
- );
98
- });
99
-
100
- it('should return text if the response do not contain the Content-Type: application/json in the response', async () => {
101
- mockFetch.mockResolvedValueOnce(createResponse(200, {}));
102
-
103
- const response = await httpClient.sendRequest(params);
104
-
105
- expect(response).toEqual({
106
- statusCode: 200,
107
- body: expect.any(String),
108
- });
109
- });
110
-
111
- it('should throw exception if the response is not OK', async () => {
112
- mockFetch.mockResolvedValueOnce(
113
- createResponse(faker.number.int({ min: 400 }), {}),
114
- );
115
-
116
- await expect(() => httpClient.sendRequest(params)).rejects.toThrow();
117
- });
118
- });
119
-
120
- describe('handleHttpErrorStatusCodes', () => {
121
- it('should throw exception if the handleHttpErrorStatusCodes does not contain the status code to handle', async () => {
122
- mockFetch.mockResolvedValueOnce(createResponse(404, {}));
123
-
124
- await expect(() =>
125
- httpClient.sendRequest({
126
- ...params,
127
- handleHttpErrorStatusCodes: [401],
128
- }),
129
- ).rejects.toThrow();
130
- });
131
-
132
- it('should return response if the handleHttpErrorStatusCodes contains the status code to handle', async () => {
133
- mockFetch.mockResolvedValueOnce(createResponse(404, {}));
134
-
135
- const response = await httpClient.sendRequest({
136
- ...params,
137
- handleHttpErrorStatusCodes: [404],
138
- });
139
-
140
- expect(response).toEqual({
141
- statusCode: 404,
142
- body: expect.anything(),
143
- });
144
- });
145
- });
146
- });
@@ -1,52 +0,0 @@
1
- import { HttpResponse } from '../HttpClient';
2
- import { faker } from '@faker-js/faker';
3
-
4
- describe('HttpResponse', () => {
5
- describe('hasHttpStatus', () => {
6
- it('should return true if the statusCode is as expected', () => {
7
- const httpResponse = new HttpResponse({
8
- statusCode: 200,
9
- body: undefined,
10
- });
11
-
12
- const result = httpResponse.hasHttpStatus(200);
13
-
14
- expect(result).toBeTruthy();
15
- });
16
-
17
- it('should return false if the statusCode is not as expected', () => {
18
- const httpResponse = new HttpResponse({
19
- statusCode: 200,
20
- body: undefined,
21
- });
22
-
23
- const result = httpResponse.hasHttpStatus(faker.number.int({ min: 201 }));
24
-
25
- expect(result).toBeFalsy();
26
- });
27
- });
28
-
29
- describe('isNotFound', () => {
30
- it('should return true if the statusCode is 404', () => {
31
- const httpResponse = new HttpResponse({
32
- statusCode: 404,
33
- body: undefined,
34
- });
35
-
36
- const result = httpResponse.isNotFound();
37
-
38
- expect(result).toBeTruthy();
39
- });
40
-
41
- it('should return false if the statusCode is different than 404', () => {
42
- const httpResponse = new HttpResponse({
43
- statusCode: 200,
44
- body: undefined,
45
- });
46
-
47
- const result = httpResponse.isNotFound();
48
-
49
- expect(result).toBeFalsy();
50
- });
51
- });
52
- });
@@ -1,75 +0,0 @@
1
- import { Container } from 'inversify';
2
- import { faker } from '@faker-js/faker';
3
- import {
4
- HttpClient,
5
- HttpMethod,
6
- HttpRequestOptions,
7
- HttpResponse,
8
- } from '../HttpClient';
9
- import { HttpRequestBuilderFactory } from '../HttpRequestBuilder';
10
- import { createHttpClientMock } from '../../testing/mock';
11
-
12
- describe('HttpRequestBuilder', () => {
13
- let httpClient: HttpClient;
14
- let httpRequestBuilderFactory: HttpRequestBuilderFactory;
15
-
16
- beforeEach(() => {
17
- const container = new Container();
18
-
19
- container.bind(HttpClient).toConstantValue(createHttpClientMock());
20
- container.bind(HttpRequestBuilderFactory).to(HttpRequestBuilderFactory);
21
-
22
- httpClient = container.get(HttpClient);
23
- httpRequestBuilderFactory = container.get(HttpRequestBuilderFactory);
24
- });
25
-
26
- it('should compose all params and call HttpClient from builder', async () => {
27
- const expectedResponse = new HttpResponse({
28
- statusCode: 200,
29
- body: undefined,
30
- });
31
- const params = {
32
- url: faker.internet.url(),
33
- method: faker.helpers.arrayElement(Object.values(HttpMethod)),
34
- headers: {
35
- example: faker.word.words(),
36
- },
37
- body: {
38
- exampleBody: faker.word.words(),
39
- },
40
- handleHttpErrorStatusCodes: [401, 403, 404],
41
- };
42
- const bearerToken = faker.word.words();
43
- const apiKey = faker.word.words();
44
-
45
- jest
46
- .spyOn(httpClient, 'sendRequest')
47
- .mockResolvedValueOnce(expectedResponse);
48
-
49
- const response = await httpRequestBuilderFactory
50
- .create()
51
- .url(params.url)
52
- .method(params.method)
53
- .body(params.body)
54
- .headers(params.headers)
55
- .applicationJson()
56
- .authorizationByBearer(bearerToken)
57
- .authorizationByXApiKey(apiKey)
58
- .handleErrorStatusCode(params.handleHttpErrorStatusCodes[0])
59
- .handleErrorStatusCode(params.handleHttpErrorStatusCodes[1])
60
- .handleNotFound()
61
- .sendRequest();
62
-
63
- expect(response).toEqual(expectedResponse);
64
- expect(httpClient.sendRequest).toHaveBeenCalledWith({
65
- ...params,
66
- headers: expect.objectContaining({
67
- ...params.headers,
68
- Authorization: `Bearer ${bearerToken}`,
69
- 'x-api-key': apiKey,
70
- 'Content-Type': 'application/json',
71
- }),
72
- handleHttpErrorStatusCodes: params.handleHttpErrorStatusCodes,
73
- } as HttpRequestOptions);
74
- });
75
- });
@@ -1,40 +0,0 @@
1
- import {
2
- createLogger as createWinstonLogger,
3
- format,
4
- LeveledLogMethod,
5
- Logform,
6
- LogMethod,
7
- transports,
8
- } from 'winston';
9
-
10
- export abstract class Logger {
11
- abstract log: LogMethod;
12
- abstract error: LeveledLogMethod;
13
- abstract warn: LeveledLogMethod;
14
- abstract info: LeveledLogMethod;
15
- abstract debug: LeveledLogMethod;
16
- abstract verbose: LeveledLogMethod;
17
- }
18
-
19
- const lambdaFormat = (): Logform.Format => {
20
- return format.printf(({ ...attrs }) => {
21
- // https://docs.aws.amazon.com/lambda/latest/dg/configuration-envvars.html#configuration-envvars-runtime
22
- return JSON.stringify({
23
- type: 'app',
24
- env: process.env.ENV,
25
- name: process.env.AWS_LAMBDA_FUNCTION_NAME,
26
- version: process.env.AWS_LAMBDA_FUNCTION_VERSION,
27
- region: process.env.AWS_REGION,
28
- trace: process.env._X_AMZN_TRACE_ID,
29
- ...attrs,
30
- });
31
- });
32
- };
33
-
34
- export function createLogger(): Logger {
35
- return createWinstonLogger({
36
- level: process.env.LOGGING_LEVEL || 'debug',
37
- format: format.combine(format.timestamp(), format.splat(), lambdaFormat()),
38
- transports: [new transports.Console()],
39
- });
40
- }
@@ -1,179 +0,0 @@
1
- /* eslint-disable @typescript-eslint/no-explicit-any */
2
- import { randomUUID } from 'crypto';
3
- import { TenantId } from '../valueObject/TenantId';
4
-
5
- type ValueOf = {
6
- valueOf(): string;
7
- };
8
-
9
- const normalizeCaller = <T extends abstract new (...args: any) => any>(
10
- stringOrClassInstance: string | InstanceType<T>,
11
- ): string =>
12
- typeof stringOrClassInstance === 'string'
13
- ? stringOrClassInstance
14
- : stringOrClassInstance.constructor.name;
15
-
16
- /**
17
- * @deprecated
18
- */
19
- export function createLogMessage<T extends abstract new (...args: any) => any>(
20
- ...metadata: Array<string | InstanceType<T>>
21
- ): (message?: string) => string {
22
- const context = randomUUID();
23
-
24
- const formattedMetadata = [...metadata, `Context: ${context}`]
25
- .filter((data) => !!data)
26
- .map((data) => `[${normalizeCaller(data)}]`)
27
- .join('');
28
-
29
- return (message) => `${formattedMetadata} ${message ?? ''}`;
30
- }
31
-
32
- export const TENANT_ID_METADATA = (
33
- tenantId: string | ValueOf,
34
- ): {
35
- tenantId: string;
36
- } => ({
37
- tenantId: typeof tenantId === 'string' ? tenantId : tenantId.valueOf(),
38
- });
39
-
40
- export const PROCESSABLE_LOG_METADATA = { processable: true } as const;
41
- export const REMOTE_LOG_METADATA = { remote: true } as const;
42
-
43
- export interface LogMessage {
44
- (message: string | any): [string | any, ...Array<any>];
45
-
46
- remote(message: string | any): [string | any, ...Array<any>];
47
-
48
- remote(
49
- message: string | any,
50
- /**
51
- * The param is not needed if it is passed in the metadata
52
- */
53
- tenantId: TenantId,
54
- ): [string | any, ...Array<any>];
55
- }
56
-
57
- export type CreateLog = {
58
- attachMetadata: (metadata: Record<string, unknown>) => CreateLog;
59
- attachEventName: (eventName: string) => CreateLog;
60
- attachCorrelationId: (id: string) => CreateLog;
61
- attachTenantId: (tenantId: string | ValueOf) => CreateLog;
62
- attachExperimentId: (experimentId: string | ValueOf) => CreateLog;
63
- attachCaller: <T extends abstract new (...args: any) => any>(
64
- caller: InstanceType<T> | string,
65
- ) => CreateLog;
66
- isProcessable: () => CreateLog;
67
- remote: () => CreateLog;
68
- getMetadata: () => Record<string, unknown>;
69
- create: <T extends abstract new (...args: any) => any>(
70
- caller?: InstanceType<T> | string,
71
- ) => LogMessage;
72
- };
73
-
74
- export function createLog(opts?: {
75
- message?: string;
76
- metadata?: Record<string, string | boolean | unknown>;
77
- }): CreateLog {
78
- opts = {
79
- metadata: {
80
- context: randomUUID(),
81
- ...opts?.metadata,
82
- },
83
- message: opts?.message,
84
- };
85
-
86
- const attachMetadata = (
87
- metadata: Record<string, string | boolean | unknown>,
88
- ): CreateLog => {
89
- return createLog({
90
- ...(opts && opts),
91
- metadata: {
92
- ...opts?.metadata,
93
- ...metadata,
94
- },
95
- });
96
- };
97
-
98
- const attachTenantId = (tenantId: string | ValueOf): CreateLog => {
99
- return attachMetadata(TENANT_ID_METADATA(tenantId));
100
- };
101
-
102
- const attachExperimentId = (experimentId: string | ValueOf): CreateLog => {
103
- return attachMetadata({
104
- experimentId:
105
- typeof experimentId === 'string'
106
- ? experimentId
107
- : experimentId.valueOf(),
108
- });
109
- };
110
-
111
- const attachEventName = (eventName: string): CreateLog => {
112
- return attachMetadata({
113
- eventName,
114
- });
115
- };
116
-
117
- const attachCorrelationId = (id: string): CreateLog => {
118
- return attachMetadata({
119
- correlationId: id,
120
- });
121
- };
122
-
123
- const isProcessable = (): CreateLog => {
124
- return attachMetadata(PROCESSABLE_LOG_METADATA);
125
- };
126
-
127
- const remote = (): CreateLog => {
128
- return attachMetadata(REMOTE_LOG_METADATA);
129
- };
130
-
131
- const attachCaller = <T extends abstract new (...args: any) => any>(
132
- caller: T | string,
133
- ): CreateLog => {
134
- return attachMetadata({
135
- caller: normalizeCaller(caller),
136
- });
137
- };
138
-
139
- const create = <T extends abstract new (...args: any) => any>(
140
- caller?: T | string,
141
- ): LogMessage => {
142
- const metadata = {
143
- ...opts?.metadata,
144
- ...(caller && {
145
- caller: normalizeCaller(caller),
146
- }),
147
- };
148
-
149
- function log(message: string | any) {
150
- return [message, metadata];
151
- }
152
-
153
- log.remote = (message: string | any, tenantId?: TenantId) => {
154
- return [
155
- message,
156
- {
157
- ...metadata,
158
- ...REMOTE_LOG_METADATA,
159
- ...(tenantId && { ...TENANT_ID_METADATA(tenantId) }),
160
- },
161
- ];
162
- };
163
-
164
- return log as LogMessage;
165
- };
166
-
167
- return {
168
- attachMetadata,
169
- attachTenantId,
170
- attachExperimentId,
171
- attachEventName,
172
- attachCorrelationId,
173
- isProcessable,
174
- attachCaller,
175
- getMetadata: () => opts?.metadata ?? {},
176
- remote,
177
- create,
178
- };
179
- }
@@ -1,66 +0,0 @@
1
- import type { CloudWatchLogsEvent } from 'aws-lambda';
2
- import zlib from 'zlib';
3
- import { inject, injectable } from 'inversify';
4
- import { inspect } from 'util';
5
- import type { CloudWatchLogsLogEvent } from 'aws-lambda/trigger/cloudwatch-logs';
6
- import { REMOTE_LOG_SCHEMA, RemoteLog, RemoteLogger } from './RemoteLogger';
7
- import { Logger } from './Logger';
8
- import { createLog, LogMessage } from './LoggerMessage';
9
-
10
- @injectable()
11
- export class LogsHandler {
12
- constructor(
13
- @inject(RemoteLogger)
14
- private readonly remoteLogger: RemoteLogger,
15
- @inject(Logger)
16
- private readonly logger: Logger,
17
- ) {}
18
-
19
- async handle(event: CloudWatchLogsEvent): Promise<void> {
20
- const logMessage = createLog().create(this);
21
-
22
- this.logger.debug(...logMessage(`started mapping CloudWatchLogsEvent`));
23
- const remoteLogs = this.mapLogs(event, logMessage);
24
-
25
- this.logger.debug(logMessage(`finished mapping CloudWatchLogsEvent`));
26
-
27
- this.logger.debug(
28
- logMessage(
29
- `started sending logs (count: ${remoteLogs.length}) into the RemoteLogger`,
30
- ),
31
- );
32
- await this.remoteLogger.log(remoteLogs);
33
- this.logger.debug(
34
- logMessage('finished sending logs into the RemoteLogger'),
35
- );
36
- }
37
-
38
- private mapLogs(
39
- event: CloudWatchLogsEvent,
40
- logMessage: LogMessage,
41
- ): Array<RemoteLog> {
42
- const logs = this.decodeLogs(event);
43
-
44
- this.logger.debug(
45
- logMessage(`received decoded logs: ${inspect(logs, { depth: 4 })}`),
46
- );
47
- const isRemoteLog = (log: undefined | RemoteLog): log is RemoteLog => !!log;
48
-
49
- return logs
50
- .map((log) => {
51
- const result = REMOTE_LOG_SCHEMA.safeParse(JSON.parse(log.message));
52
-
53
- return result.success ? result.data : undefined;
54
- })
55
- .filter(isRemoteLog);
56
- }
57
-
58
- private decodeLogs(
59
- event: CloudWatchLogsEvent,
60
- ): Array<CloudWatchLogsLogEvent> {
61
- const payload = Buffer.from(event.awslogs.data, 'base64');
62
- const logs = JSON.parse(zlib.unzipSync(payload).toString());
63
-
64
- return logs.logEvents;
65
- }
66
- }
@@ -1,32 +0,0 @@
1
- import { TenantId } from './../valueObject/TenantId';
2
- import { injectable } from 'inversify';
3
- import { z } from 'zod';
4
-
5
- export enum RemoteLogLevel {
6
- INFO = 'info',
7
- WARN = 'warn',
8
- ERROR = 'error',
9
- }
10
-
11
- export const REMOTE_LOG_SCHEMA = z.object({
12
- tenantId: z.string().transform((v) => new TenantId(v)),
13
- message: z.string(),
14
- timestamp: z
15
- .string()
16
- .datetime()
17
- .transform((v) => new Date(v))
18
- .optional(),
19
- level: z.nativeEnum(RemoteLogLevel),
20
- });
21
- export type RemoteLog = z.infer<typeof REMOTE_LOG_SCHEMA>;
22
-
23
- @injectable()
24
- export abstract class RemoteLogger {
25
- abstract info(log: Omit<RemoteLog, 'level'>): Promise<void>;
26
-
27
- abstract warn(log: Omit<RemoteLog, 'level'>): Promise<void>;
28
-
29
- abstract error(log: Omit<RemoteLog, 'level'>): Promise<void>;
30
-
31
- abstract log(logs: ReadonlyArray<RemoteLog>): Promise<void>;
32
- }