@squiz/optimization-utils 2.0.1 → 2.0.3

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 (89) hide show
  1. package/dist/cloudflare/ImplCloudflareKVHttpService.d.ts +2 -2
  2. package/dist/cloudflare/ImplCloudflareKVHttpService.js +8 -10
  3. package/dist/cloudflare/ImplCloudflareKVHttpService.js.map +1 -1
  4. package/dist/config/ConfigurationLoader.d.ts +1 -1
  5. package/dist/config/ConfigurationLoader.js +3 -4
  6. package/dist/config/ConfigurationLoader.js.map +1 -1
  7. package/dist/index.d.ts +0 -11
  8. package/dist/index.js +0 -11
  9. package/dist/index.js.map +1 -1
  10. package/dist/scheduler/EventBridgeScheduler.d.ts +1 -1
  11. package/dist/scheduler/EventBridgeScheduler.js +4 -5
  12. package/dist/scheduler/EventBridgeScheduler.js.map +1 -1
  13. package/dist/testing/mock.d.ts +0 -8
  14. package/dist/testing/mock.js +1 -35
  15. package/dist/testing/mock.js.map +1 -1
  16. package/package.json +4 -1
  17. package/CHANGELOG.md +0 -37
  18. package/dist/exception/DomainException.d.ts +0 -18
  19. package/dist/exception/DomainException.js +0 -41
  20. package/dist/exception/DomainException.js.map +0 -1
  21. package/dist/httpClient/FetchHttpClient.d.ts +0 -7
  22. package/dist/httpClient/FetchHttpClient.js +0 -86
  23. package/dist/httpClient/FetchHttpClient.js.map +0 -1
  24. package/dist/httpClient/HttpClient.d.ts +0 -25
  25. package/dist/httpClient/HttpClient.js +0 -45
  26. package/dist/httpClient/HttpClient.js.map +0 -1
  27. package/dist/httpClient/HttpRequestBuilder.d.ts +0 -22
  28. package/dist/httpClient/HttpRequestBuilder.js +0 -126
  29. package/dist/httpClient/HttpRequestBuilder.js.map +0 -1
  30. package/dist/logger/Logger.d.ts +0 -10
  31. package/dist/logger/Logger.js +0 -30
  32. package/dist/logger/Logger.js.map +0 -1
  33. package/dist/logger/LoggerMessage.d.ts +0 -43
  34. package/dist/logger/LoggerMessage.js +0 -111
  35. package/dist/logger/LoggerMessage.js.map +0 -1
  36. package/dist/logger/LogsHandler.d.ts +0 -11
  37. package/dist/logger/LogsHandler.js +0 -66
  38. package/dist/logger/LogsHandler.js.map +0 -1
  39. package/dist/logger/RemoteLogger.d.ts +0 -30
  40. package/dist/logger/RemoteLogger.js +0 -35
  41. package/dist/logger/RemoteLogger.js.map +0 -1
  42. package/dist/logger/SquizRemoteLogger.d.ts +0 -53
  43. package/dist/logger/SquizRemoteLogger.js +0 -128
  44. package/dist/logger/SquizRemoteLogger.js.map +0 -1
  45. package/dist/validation/handleValidation.d.ts +0 -2
  46. package/dist/validation/handleValidation.js +0 -11
  47. package/dist/validation/handleValidation.js.map +0 -1
  48. package/dist/valueObject/TenantId.d.ts +0 -10
  49. package/dist/valueObject/TenantId.js +0 -23
  50. package/dist/valueObject/TenantId.js.map +0 -1
  51. package/src/cloudflare/CloudflareKVHttpService.ts +0 -20
  52. package/src/cloudflare/ImplCloudflareKVHttpService.ts +0 -128
  53. package/src/cloudflare/__tests__/ImplCloudflareKVHttpService.spec.ts +0 -178
  54. package/src/config/ConfigurationLoader.ts +0 -72
  55. package/src/config/__tests__/ConfigurationLoader.spec.ts +0 -62
  56. package/src/date/DateManipulator.ts +0 -29
  57. package/src/date/__tests__/DateManipulator.spec.ts +0 -64
  58. package/src/event/AggregateRoot.ts +0 -5
  59. package/src/event/DomainEvent.ts +0 -53
  60. package/src/event/DynamoDBEventMapper.ts +0 -75
  61. package/src/event/EventHandler.ts +0 -57
  62. package/src/event/__tests__/DynamoDBEventMapper.spec.ts +0 -121
  63. package/src/exception/DomainException.ts +0 -34
  64. package/src/httpClient/FetchHttpClient.ts +0 -92
  65. package/src/httpClient/HttpClient.ts +0 -46
  66. package/src/httpClient/HttpRequestBuilder.ts +0 -120
  67. package/src/httpClient/__tests__/FetchHttpClient.spec.ts +0 -146
  68. package/src/httpClient/__tests__/HttpClient.spec.ts +0 -52
  69. package/src/httpClient/__tests__/httpRequestBuilder.spec.ts +0 -75
  70. package/src/index.ts +0 -37
  71. package/src/logger/Logger.ts +0 -40
  72. package/src/logger/LoggerMessage.ts +0 -179
  73. package/src/logger/LogsHandler.ts +0 -66
  74. package/src/logger/RemoteLogger.ts +0 -32
  75. package/src/logger/SquizRemoteLogger.ts +0 -154
  76. package/src/logger/__tests__/LoggerMessage.spec.ts +0 -147
  77. package/src/logger/__tests__/LogsHandler.spec.ts +0 -77
  78. package/src/logger/__tests__/SquizRemoteLogger.spec.ts +0 -185
  79. package/src/object/__tests__/getProperty.spec.ts +0 -17
  80. package/src/object/getProperty.ts +0 -21
  81. package/src/scheduler/EventBridgeScheduler.ts +0 -173
  82. package/src/scheduler/Scheduler.ts +0 -32
  83. package/src/scheduler/__tests__/EventBridgeScheduler.spec.ts +0 -311
  84. package/src/testing/mock.ts +0 -62
  85. package/src/typesUtils/DynamoDB.ts +0 -17
  86. package/src/typesUtils/utilities.ts +0 -11
  87. package/src/validation/handleValidation.ts +0 -13
  88. package/src/valueObject/TenantId.ts +0 -27
  89. package/tsconfig.json +0 -13
@@ -1,128 +0,0 @@
1
- "use strict";
2
- var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
- else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
- return c > 3 && r && Object.defineProperty(target, key, r), r;
7
- };
8
- var __metadata = (this && this.__metadata) || function (k, v) {
9
- if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
- };
11
- Object.defineProperty(exports, "__esModule", { value: true });
12
- exports.SquizRemoteLogger = void 0;
13
- const zod_1 = require("zod");
14
- const RemoteLogger_1 = require("./RemoteLogger");
15
- const TenantId_1 = require("../valueObject/TenantId");
16
- const inversify_1 = require("inversify");
17
- const Logger_1 = require("./Logger");
18
- const HttpRequestBuilder_1 = require("../httpClient/HttpRequestBuilder");
19
- const HttpClient_1 = require("../httpClient/HttpClient");
20
- const LoggerMessage_1 = require("./LoggerMessage");
21
- const CREATE_LOGS_REQUEST_BODY_DTO_SCHEMA = zod_1.z
22
- .object({
23
- level: zod_1.z.enum(['INFO', 'WARNING', 'ERROR']),
24
- service: zod_1.z.string(),
25
- timestamp: zod_1.z.string().datetime(),
26
- host: zod_1.z.string().optional(),
27
- userid: zod_1.z.string().optional(),
28
- message: zod_1.z.string().optional(),
29
- tags: zod_1.z.string().optional(),
30
- traceid: zod_1.z.string().optional(),
31
- })
32
- .array();
33
- let SquizRemoteLogger = class SquizRemoteLogger {
34
- config;
35
- logger;
36
- httpRequestBuilderFactory;
37
- constructor(config, logger, httpRequestBuilderFactory) {
38
- this.config = config;
39
- this.logger = logger;
40
- this.httpRequestBuilderFactory = httpRequestBuilderFactory;
41
- }
42
- async info(log) {
43
- await this.callApi(log.tenantId, [
44
- await this.mapRemoteToRequestBody({
45
- ...log,
46
- level: RemoteLogger_1.RemoteLogLevel.INFO,
47
- }),
48
- ]);
49
- }
50
- async warn(log) {
51
- await this.callApi(log.tenantId, [
52
- await this.mapRemoteToRequestBody({
53
- ...log,
54
- level: RemoteLogger_1.RemoteLogLevel.WARN,
55
- }),
56
- ]);
57
- }
58
- async error(log) {
59
- await this.callApi(log.tenantId, [
60
- await this.mapRemoteToRequestBody({
61
- ...log,
62
- level: RemoteLogger_1.RemoteLogLevel.ERROR,
63
- }),
64
- ]);
65
- }
66
- async log(logs) {
67
- const logsGrouped = await logs.reduce(async (acc, log) => {
68
- const resolvedAcc = await acc;
69
- const tenantLogs = resolvedAcc[log.tenantId.valueOf()];
70
- const mappedLog = await this.mapRemoteToRequestBody(log);
71
- const mappedLogs = tenantLogs
72
- ? [...tenantLogs, mappedLog]
73
- : [mappedLog];
74
- return {
75
- ...resolvedAcc,
76
- [log.tenantId.valueOf()]: mappedLogs,
77
- };
78
- }, Promise.resolve({}));
79
- const entries = Object.entries(logsGrouped);
80
- const promises = entries.map(async ([tenantId, logs]) => {
81
- await this.callApi(new TenantId_1.TenantId(tenantId), logs);
82
- });
83
- await Promise.all(promises);
84
- }
85
- async mapRemoteToRequestBody({ tenantId, ...log }) {
86
- const config = await this.config();
87
- const logLevels = new Map([
88
- [RemoteLogger_1.RemoteLogLevel.INFO, 'INFO'],
89
- [RemoteLogger_1.RemoteLogLevel.WARN, 'WARNING'],
90
- [RemoteLogger_1.RemoteLogLevel.ERROR, 'ERROR'],
91
- ]);
92
- return {
93
- ...log,
94
- timestamp: log.timestamp
95
- ? log.timestamp.toISOString()
96
- : new Date().toISOString(),
97
- level: logLevels.get(log.level),
98
- service: config.serviceName,
99
- };
100
- }
101
- async callApi(tenantId, logs) {
102
- if (!logs.length) {
103
- return;
104
- }
105
- const logMessage = (0, LoggerMessage_1.createLog)().attachTenantId(tenantId).create(this);
106
- this.logger.debug(...logMessage(`started receiving config`));
107
- const config = await this.config();
108
- this.logger.debug(...logMessage(`finished receiving config`));
109
- const url = new URL(config.createLogsPath + `/${tenantId.valueOf()}`, config.loggerServiceUrl);
110
- this.logger.debug(...logMessage(`started request to: ${url.toString()}`));
111
- await this.httpRequestBuilderFactory
112
- .create()
113
- .url(url)
114
- .method(HttpClient_1.HttpMethod.POST)
115
- .applicationJson()
116
- .authorizationByXApiKey(config.apiKey)
117
- .body(logs)
118
- .sendRequest();
119
- this.logger.debug(...logMessage(`finished request to: ${url.toString()}`));
120
- }
121
- };
122
- exports.SquizRemoteLogger = SquizRemoteLogger;
123
- exports.SquizRemoteLogger = SquizRemoteLogger = __decorate([
124
- (0, inversify_1.injectable)(),
125
- __metadata("design:paramtypes", [Function, Logger_1.Logger,
126
- HttpRequestBuilder_1.HttpRequestBuilderFactory])
127
- ], SquizRemoteLogger);
128
- //# sourceMappingURL=SquizRemoteLogger.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"SquizRemoteLogger.js","sourceRoot":"","sources":["../../src/logger/SquizRemoteLogger.ts"],"names":[],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- import { SafeParseReturnType } from 'zod';
2
- export declare function handleValidation<T, O>(safeParseResult: SafeParseReturnType<T, O>, errorMessage?: string): O;
@@ -1,11 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.handleValidation = handleValidation;
4
- const DomainException_1 = require("../exception/DomainException");
5
- function handleValidation(safeParseResult, errorMessage = 'Validation Failed') {
6
- if (!safeParseResult.success) {
7
- throw new DomainException_1.ValidationException(errorMessage, safeParseResult.error.issues);
8
- }
9
- return safeParseResult.data;
10
- }
11
- //# sourceMappingURL=handleValidation.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"handleValidation.js","sourceRoot":"","sources":["../../src/validation/handleValidation.ts"],"names":[],"mappings":";;AAGA,4CASC;AAXD,kEAAmE;AAEnE,SAAgB,gBAAgB,CAC9B,eAA0C,EAC1C,YAAY,GAAG,mBAAmB;IAElC,IAAI,CAAC,eAAe,CAAC,OAAO,EAAE,CAAC;QAC7B,MAAM,IAAI,qCAAmB,CAAC,YAAY,EAAE,eAAe,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAC5E,CAAC;IAED,OAAO,eAAe,CAAC,IAAI,CAAC;AAC9B,CAAC"}
@@ -1,10 +0,0 @@
1
- import { z } from 'zod';
2
- export declare const TENANT_ID_SCHEMA: z.ZodString;
3
- export type TenantIdValue = z.infer<typeof TENANT_ID_SCHEMA>;
4
- export declare class TenantId {
5
- private readonly value;
6
- static parse(data: unknown): TenantId;
7
- constructor(value: TenantIdValue);
8
- valueOf(): TenantIdValue;
9
- equals(tenantId: TenantId): boolean;
10
- }
@@ -1,23 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.TenantId = exports.TENANT_ID_SCHEMA = void 0;
4
- const zod_1 = require("zod");
5
- const handleValidation_1 = require("../validation/handleValidation");
6
- exports.TENANT_ID_SCHEMA = zod_1.z.string().min(1);
7
- class TenantId {
8
- value;
9
- static parse(data) {
10
- return new TenantId((0, handleValidation_1.handleValidation)(exports.TENANT_ID_SCHEMA.safeParse(data), 'The validation of tenant id failed'));
11
- }
12
- constructor(value) {
13
- this.value = value;
14
- }
15
- valueOf() {
16
- return this.value;
17
- }
18
- equals(tenantId) {
19
- return this.value === tenantId.value;
20
- }
21
- }
22
- exports.TenantId = TenantId;
23
- //# sourceMappingURL=TenantId.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"TenantId.js","sourceRoot":"","sources":["../../src/valueObject/TenantId.ts"],"names":[],"mappings":";;;AAAA,6BAAwB;AACxB,qEAAkE;AAErD,QAAA,gBAAgB,GAAG,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;AAIlD,MAAa,QAAQ;IAUU;IAT7B,MAAM,CAAC,KAAK,CAAC,IAAa;QACxB,OAAO,IAAI,QAAQ,CACjB,IAAA,mCAAgB,EACd,wBAAgB,CAAC,SAAS,CAAC,IAAI,CAAC,EAChC,oCAAoC,CACrC,CACF,CAAC;IACJ,CAAC;IAED,YAA6B,KAAoB;QAApB,UAAK,GAAL,KAAK,CAAe;IAAG,CAAC;IAErD,OAAO;QACL,OAAO,IAAI,CAAC,KAAK,CAAC;IACpB,CAAC;IAED,MAAM,CAAC,QAAkB;QACvB,OAAO,IAAI,CAAC,KAAK,KAAK,QAAQ,CAAC,KAAK,CAAC;IACvC,CAAC;CACF;AAnBD,4BAmBC"}
@@ -1,20 +0,0 @@
1
- import { injectable } from 'inversify';
2
-
3
- export type CloudflareKey = string;
4
-
5
- export type BatchValueData<T> = Array<{
6
- key: CloudflareKey;
7
- value: T;
8
- }>;
9
-
10
- // https://developers.cloudflare.com/api/operations/workers-kv-namespace-write-multiple-key-value-pairs
11
- export const MAX_BATCH_DATA_ITEMS = 10_000;
12
-
13
- @injectable()
14
- export abstract class CloudflareKVHttpService<TSchema> {
15
- abstract getValues(key: CloudflareKey): Promise<TSchema>;
16
-
17
- abstract putBulk(batchData: BatchValueData<TSchema>): Promise<void>;
18
-
19
- abstract deleteBulk(keys: Array<CloudflareKey>): Promise<void>;
20
- }
@@ -1,128 +0,0 @@
1
- import { injectable } from 'inversify';
2
- import { inspect } from 'util';
3
- import {
4
- BatchValueData,
5
- CloudflareKey,
6
- CloudflareKVHttpService,
7
- MAX_BATCH_DATA_ITEMS,
8
- } from './CloudflareKVHttpService';
9
- import { ZodType } from 'zod';
10
- import { HttpRequestBuilderFactory } from '../httpClient/HttpRequestBuilder';
11
- import { Logger } from '../logger/Logger';
12
- import { HttpMethod } from '../httpClient/HttpClient';
13
- import { createLog } from '../logger/LoggerMessage';
14
-
15
- export type CloudflareConfig = {
16
- domain: string;
17
- accountId: string;
18
- namespace: string;
19
- apiKey: string;
20
- };
21
- export type CloudflareConfigProvider = () => Promise<CloudflareConfig>;
22
-
23
- @injectable()
24
- export class ImplCloudflareKVHttpService<TSchema>
25
- implements CloudflareKVHttpService<TSchema>
26
- {
27
- constructor(
28
- private readonly cloudflareConfigProvider: CloudflareConfigProvider,
29
- private readonly httpRequestBuilderFactory: HttpRequestBuilderFactory,
30
- private readonly logger: Logger,
31
- private readonly schema: TSchema extends ZodType ? TSchema : never,
32
- ) {}
33
-
34
- async getValues(key: string): Promise<TSchema> {
35
- const response = await this.callApi({
36
- path: `/values/${key}`,
37
- method: HttpMethod.GET,
38
- handleNotFoundAsEmpty: true,
39
- });
40
-
41
- return this.schema.parse(
42
- typeof response === 'string' ? JSON.parse(response) : {},
43
- );
44
- }
45
-
46
- async putBulk(batchData: BatchValueData<TSchema>): Promise<void> {
47
- if (!batchData.length) {
48
- return;
49
- }
50
-
51
- if (batchData.length > MAX_BATCH_DATA_ITEMS) {
52
- throw new Error(
53
- `The max items count has been exceeded. The max items count is ${MAX_BATCH_DATA_ITEMS}`,
54
- );
55
- }
56
-
57
- await this.callApi({
58
- method: HttpMethod.PUT,
59
- body: batchData.map((data) => ({
60
- ...data,
61
- value: JSON.stringify(data.value),
62
- })),
63
- path: `/bulk`,
64
- });
65
- }
66
-
67
- async deleteBulk(keys: Array<CloudflareKey>): Promise<void> {
68
- if (!keys.length) {
69
- return;
70
- }
71
-
72
- await this.callApi({
73
- method: HttpMethod.DELETE,
74
- body: keys,
75
- path: `/bulk`,
76
- });
77
- }
78
-
79
- private async callApi({
80
- path,
81
- body,
82
- method,
83
- handleNotFoundAsEmpty = false,
84
- }: {
85
- path: '/bulk' | `/values/${string}`;
86
- method: HttpMethod;
87
- body?: Record<string, string> | Array<unknown>;
88
- handleNotFoundAsEmpty?: boolean;
89
- }): Promise<unknown | undefined> {
90
- const config = await this.cloudflareConfigProvider();
91
- const baseUrl =
92
- `https://${config.domain}/client/v4/accounts/` +
93
- `${config.accountId}/storage/kv/namespaces/` +
94
- `${config.namespace}`;
95
- const url = baseUrl + path;
96
-
97
- const logMessage = createLog()
98
- .attachMetadata({ path, method, url })
99
- .create(this);
100
-
101
- this.logger.debug(...logMessage('started calling http endpoint'));
102
- this.logger.debug(
103
- ...logMessage(`the request body: ${inspect(body, { depth: 4 })}`),
104
- );
105
- const httpBuilder = this.httpRequestBuilderFactory
106
- .create()
107
- .url(url)
108
- .method(method)
109
- .body(body)
110
- .applicationJson()
111
- .authorizationByBearer(config.apiKey);
112
-
113
- handleNotFoundAsEmpty && httpBuilder.handleNotFound();
114
-
115
- const response = await httpBuilder.sendRequest();
116
-
117
- this.logger.debug(...logMessage('finished calling http endpoint'));
118
- this.logger.debug(
119
- ...logMessage(
120
- `returned type: ${typeof response.body}, type: returned: ${inspect(
121
- response.body,
122
- { depth: 4 },
123
- )}`,
124
- ),
125
- );
126
- return response.body;
127
- }
128
- }
@@ -1,178 +0,0 @@
1
- import { createHttpClientMock, createLoggerMock } from '../../testing/mock';
2
- import {
3
- CloudflareConfig,
4
- ImplCloudflareKVHttpService,
5
- } from '../ImplCloudflareKVHttpService';
6
- import { Container } from 'inversify';
7
- import { HttpRequestBuilderFactory } from '../../httpClient/HttpRequestBuilder';
8
- import {
9
- HttpClient,
10
- HttpMethod,
11
- HttpRequestOptions,
12
- HttpResponse,
13
- } from '../../httpClient/HttpClient';
14
- import { Logger } from '../../logger/Logger';
15
- import { faker } from '@faker-js/faker';
16
- import { z } from 'zod';
17
-
18
- describe('CloudflareKVHttpService', () => {
19
- const EXAMPLE_SCHEMA = z.object({
20
- example: z.string(),
21
- });
22
-
23
- type ExampleSchemaType = z.infer<typeof EXAMPLE_SCHEMA>;
24
-
25
- let service: ImplCloudflareKVHttpService<ExampleSchemaType>;
26
- let httpClient: HttpClient;
27
- const config: CloudflareConfig = {
28
- domain: 'test-domain.com',
29
- accountId: 'test-account-id',
30
- namespace: 'test-namespace-id',
31
- apiKey: 'test-api-key',
32
- };
33
- const expectedHeaders = {
34
- 'Content-Type': 'application/json',
35
- Authorization: `Bearer ${config.apiKey}`,
36
- };
37
-
38
- beforeEach(() => {
39
- const container = new Container({ defaultScope: 'Singleton' });
40
-
41
- container
42
- .bind(ImplCloudflareKVHttpService)
43
- .toDynamicValue(({ container: c }) => {
44
- return new ImplCloudflareKVHttpService(
45
- () => Promise.resolve(config),
46
- c.get(HttpRequestBuilderFactory),
47
- c.get(Logger),
48
- EXAMPLE_SCHEMA,
49
- );
50
- });
51
- container.bind(HttpRequestBuilderFactory).toSelf();
52
- container.bind(HttpClient).toConstantValue(createHttpClientMock());
53
- container.bind(Logger).toConstantValue(createLoggerMock());
54
-
55
- service = container.get(ImplCloudflareKVHttpService);
56
- httpClient = container.get(HttpClient);
57
- });
58
-
59
- describe('getValues', () => {
60
- const key = 'example-key';
61
-
62
- it('should get values from Cloudflare KV', async () => {
63
- const expectedResponse = { example: faker.string.uuid() };
64
-
65
- const expectedURL =
66
- 'https://test-domain.com/client/v4/accounts' +
67
- '/test-account-id/storage/kv/namespaces/test-namespace-id' +
68
- `/values/${key}`;
69
-
70
- jest.spyOn(httpClient, 'sendRequest').mockResolvedValueOnce(
71
- new HttpResponse({
72
- statusCode: 200,
73
- body: JSON.stringify(expectedResponse),
74
- }),
75
- );
76
-
77
- const result = await service.getValues(key);
78
-
79
- expect(result).toEqual(expectedResponse);
80
- expect(httpClient.sendRequest).toHaveBeenCalledWith({
81
- url: expectedURL,
82
- method: HttpMethod.GET,
83
- headers: expectedHeaders,
84
- handleHttpErrorStatusCodes: [404],
85
- } as HttpRequestOptions);
86
- });
87
-
88
- it('should throw an error if fetch fails', async () => {
89
- jest.spyOn(httpClient, 'sendRequest').mockRejectedValueOnce(new Error());
90
-
91
- await expect(service.getValues(key)).rejects.toThrow();
92
- });
93
- });
94
-
95
- describe('putBulk', () => {
96
- it('should call the put bulk endpoint', async () => {
97
- const value: ExampleSchemaType = { example: faker.string.uuid() };
98
- const expectedURL =
99
- 'https://test-domain.com/client/v4/accounts' +
100
- '/test-account-id/storage/kv/namespaces/test-namespace-id' +
101
- `/bulk`;
102
-
103
- jest
104
- .spyOn(httpClient, 'sendRequest')
105
- .mockResolvedValueOnce(
106
- new HttpResponse({ statusCode: 200, body: undefined }),
107
- );
108
-
109
- await service.putBulk([
110
- {
111
- key: 'someKey',
112
- value: value,
113
- },
114
- ]);
115
-
116
- expect(httpClient.sendRequest).toHaveBeenCalledWith({
117
- url: expectedURL,
118
- method: HttpMethod.PUT,
119
- headers: expectedHeaders,
120
- body: [
121
- {
122
- key: 'someKey',
123
- value: JSON.stringify(value),
124
- },
125
- ],
126
- } as HttpRequestOptions);
127
- });
128
-
129
- it('should not call the put bulk endpoint if the batch data array is empty', async () => {
130
- await service.putBulk([]);
131
-
132
- expect(httpClient.sendRequest).toHaveBeenCalledTimes(0);
133
- });
134
-
135
- it('should throw exception if the items amount exceeds 10_000', async () => {
136
- const batch = Array(10_001)
137
- .fill('')
138
- .map(() => ({
139
- key: faker.string.uuid(),
140
- value: { example: faker.string.uuid() },
141
- }));
142
-
143
- await expect(() => service.putBulk(batch)).rejects.toThrow(
144
- 'The max items count has been exceeded. The max items count is 10000',
145
- );
146
- });
147
- });
148
-
149
- describe('deleteBulk', () => {
150
- it('should call the delete bulk endpoint', async () => {
151
- const expectedURL =
152
- 'https://test-domain.com/client/v4/accounts' +
153
- '/test-account-id/storage/kv/namespaces/test-namespace-id' +
154
- `/bulk`;
155
-
156
- jest
157
- .spyOn(httpClient, 'sendRequest')
158
- .mockResolvedValueOnce(
159
- new HttpResponse({ statusCode: 200, body: undefined }),
160
- );
161
-
162
- await service.deleteBulk(['someKey']);
163
-
164
- expect(httpClient.sendRequest).toHaveBeenCalledWith({
165
- url: expectedURL,
166
- method: HttpMethod.DELETE,
167
- headers: expectedHeaders,
168
- body: ['someKey'],
169
- } as HttpRequestOptions);
170
- });
171
- });
172
-
173
- it('should not call the delete bulk endpoint if passed empty keys array', async () => {
174
- await service.deleteBulk([]);
175
-
176
- expect(httpClient.sendRequest).toHaveBeenCalledTimes(0);
177
- });
178
- });
@@ -1,72 +0,0 @@
1
- import { config } from 'dotenv';
2
- import * as process from 'process';
3
- import * as path from 'path';
4
- import { injectable } from 'inversify';
5
- import { z, ZodType } from 'zod';
6
- import { HttpRequestBuilderFactory } from '../httpClient/HttpRequestBuilder';
7
- import { HttpMethod } from '../httpClient/HttpClient';
8
-
9
- export abstract class ConfigurationLoader<TSchema extends ZodType> {
10
- abstract load(): Promise<z.infer<TSchema>>;
11
- }
12
-
13
- @injectable()
14
- export class DotEnvConfigurationLoader<TSchema extends ZodType>
15
- implements ConfigurationLoader<TSchema>
16
- {
17
- constructor(private readonly schema: TSchema) {}
18
-
19
- async load(): Promise<z.infer<TSchema>> {
20
- const output = config({
21
- path: path.join(__dirname, '../../../../env/.env'),
22
- });
23
-
24
- if (output.error) {
25
- throw output.error;
26
- }
27
-
28
- return this.schema.parse(process.env);
29
- }
30
- }
31
-
32
- export type LambdaLayerAppConfigConfigurationLoaderConfig = {
33
- appConfigName: string;
34
- env: string;
35
- configurationName: string;
36
- };
37
-
38
- @injectable()
39
- export class LambdaLayerAppConfigConfigurationLoader<TSchema extends ZodType>
40
- implements ConfigurationLoader<TSchema>
41
- {
42
- constructor(
43
- private readonly opts: LambdaLayerAppConfigConfigurationLoaderConfig,
44
- private readonly httpRequestBuilderFactory: HttpRequestBuilderFactory,
45
- private readonly schema: TSchema,
46
- ) {}
47
-
48
- async load(): Promise<z.infer<TSchema>> {
49
- const configuration = await this.fetchFromApi();
50
-
51
- return this.schema.parse(configuration);
52
- }
53
-
54
- private async fetchFromApi(): Promise<unknown> {
55
- const application = this.opts.appConfigName;
56
- const environment = this.opts.env;
57
- const configuration = this.opts.configurationName;
58
- // the http://localhost:2772 represents the URL to the AWS AppConfig Lambda layer
59
- // the documentation: https://docs.aws.amazon.com/appconfig/latest/userguide/appconfig-integration-lambda-extensions.html
60
- const url =
61
- `http://localhost:2772` +
62
- `/applications/${application}/environments/${environment}/configurations/${configuration}`;
63
-
64
- const response = await this.httpRequestBuilderFactory
65
- .create()
66
- .url(url)
67
- .method(HttpMethod.GET)
68
- .sendRequest();
69
-
70
- return response.body;
71
- }
72
- }
@@ -1,62 +0,0 @@
1
- import {
2
- ConfigurationLoader,
3
- LambdaLayerAppConfigConfigurationLoader,
4
- LambdaLayerAppConfigConfigurationLoaderConfig,
5
- } from '../ConfigurationLoader';
6
- import { HttpRequestBuilderFactory } from '../../httpClient/HttpRequestBuilder';
7
- import {
8
- HttpClient,
9
- HttpMethod,
10
- HttpResponse,
11
- } from '../../httpClient/HttpClient';
12
- import { faker } from '@faker-js/faker';
13
- import { createHttpClientMock } from '../../testing/mock';
14
- import { z } from 'zod';
15
-
16
- describe('LambdaLayerAppConfigConfigurationLoader', () => {
17
- const opts: LambdaLayerAppConfigConfigurationLoaderConfig = {
18
- env: 'local',
19
- appConfigName: 'example-app',
20
- configurationName: 'main',
21
- };
22
- const CONFIG_SCHEMA = z.object({
23
- EXAMPLE_VALUE: z.string(),
24
- });
25
-
26
- type Config = z.infer<typeof CONFIG_SCHEMA>;
27
-
28
- let configurationLoader: ConfigurationLoader<typeof CONFIG_SCHEMA>;
29
- let httpClient: HttpClient;
30
-
31
- beforeEach(() => {
32
- httpClient = createHttpClientMock();
33
- configurationLoader = new LambdaLayerAppConfigConfigurationLoader<
34
- typeof CONFIG_SCHEMA
35
- >(opts, new HttpRequestBuilderFactory(httpClient), CONFIG_SCHEMA);
36
- });
37
-
38
- it('should call AWS AppConfig Layer with passed arguments', async () => {
39
- const expectedResult: Config = {
40
- EXAMPLE_VALUE: faker.word.words(),
41
- };
42
-
43
- jest.spyOn(httpClient, 'sendRequest').mockResolvedValueOnce(
44
- new HttpResponse({
45
- body: expectedResult,
46
- statusCode: 200,
47
- }),
48
- );
49
-
50
- const result = await configurationLoader.load();
51
-
52
- const expectedURL =
53
- `http://localhost:2772` +
54
- `/applications/example-app/environments/local/configurations/main`;
55
-
56
- expect(result).toEqual(expectedResult);
57
- expect(httpClient.sendRequest).toHaveBeenCalledWith({
58
- url: expectedURL,
59
- method: HttpMethod.GET,
60
- });
61
- });
62
- });