@squiz/dx-common-lib 1.72.0 → 1.72.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.
- package/CHANGELOG.md +18 -0
- package/lib/events/EventBusService.d.ts +107 -0
- package/lib/events/EventBusService.js +196 -0
- package/lib/events/EventBusService.js.map +1 -0
- package/lib/events/EventBusService.spec.d.ts +1 -0
- package/lib/events/EventBusService.spec.js +527 -0
- package/lib/events/EventBusService.spec.js.map +1 -0
- package/lib/index.d.ts +5 -0
- package/lib/index.js +5 -0
- package/lib/index.js.map +1 -1
- package/lib/secret-api-key-service/DevSecretApiKeyService.d.ts +25 -0
- package/lib/secret-api-key-service/DevSecretApiKeyService.js +35 -0
- package/lib/secret-api-key-service/DevSecretApiKeyService.js.map +1 -0
- package/lib/secret-api-key-service/DevSecretApiKeyService.spec.d.ts +1 -0
- package/lib/secret-api-key-service/DevSecretApiKeyService.spec.js +157 -0
- package/lib/secret-api-key-service/DevSecretApiKeyService.spec.js.map +1 -0
- package/lib/secret-api-key-service/SecretApiKeyService.d.ts +0 -9
- package/lib/secret-api-key-service/SecretApiKeyService.js +0 -7
- package/lib/secret-api-key-service/SecretApiKeyService.js.map +1 -1
- package/lib/secret-api-key-service/SecretApiKeyService.spec.js +0 -37
- package/lib/secret-api-key-service/SecretApiKeyService.spec.js.map +1 -1
- package/lib/secret-api-key-service/getSecretApiKeyService.d.ts +20 -0
- package/lib/secret-api-key-service/getSecretApiKeyService.js +41 -0
- package/lib/secret-api-key-service/getSecretApiKeyService.js.map +1 -0
- package/lib/secret-api-key-service/getSecretApiKeyService.spec.d.ts +1 -0
- package/lib/secret-api-key-service/getSecretApiKeyService.spec.js +313 -0
- package/lib/secret-api-key-service/getSecretApiKeyService.spec.js.map +1 -0
- package/lib/stream/EventStreamHandler.d.ts +38 -0
- package/lib/stream/EventStreamHandler.js +128 -0
- package/lib/stream/EventStreamHandler.js.map +1 -0
- package/lib/stream/EventStreamHandler.spec.d.ts +1 -0
- package/lib/stream/EventStreamHandler.spec.js +364 -0
- package/lib/stream/EventStreamHandler.spec.js.map +1 -0
- package/lib/stream/StreamUtils.d.ts +38 -0
- package/lib/stream/StreamUtils.js +59 -0
- package/lib/stream/StreamUtils.js.map +1 -0
- package/lib/stream/StreamUtils.spec.d.ts +1 -0
- package/lib/stream/StreamUtils.spec.js +92 -0
- package/lib/stream/StreamUtils.spec.js.map +1 -0
- package/package.json +3 -2
- package/src/events/EventBusService.spec.ts +707 -0
- package/src/events/EventBusService.ts +316 -0
- package/src/index.ts +5 -0
- package/src/secret-api-key-service/DevSecretApiKeyService.spec.ts +211 -0
- package/src/secret-api-key-service/DevSecretApiKeyService.ts +36 -0
- package/src/secret-api-key-service/SecretApiKeyService.spec.ts +0 -46
- package/src/secret-api-key-service/SecretApiKeyService.ts +0 -13
- package/src/secret-api-key-service/getSecretApiKeyService.spec.ts +405 -0
- package/src/secret-api-key-service/getSecretApiKeyService.ts +45 -0
- package/src/stream/EventStreamHandler.spec.ts +440 -0
- package/src/stream/EventStreamHandler.ts +192 -0
- package/src/stream/StreamUtils.spec.ts +113 -0
- package/src/stream/StreamUtils.ts +58 -0
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright Squiz Australia Pty Ltd. All Rights Reserved.
|
|
4
|
+
*/
|
|
5
|
+
import { extractTenantIdFromArn, getDynamoValue, getActionType } from './StreamUtils';
|
|
6
|
+
|
|
7
|
+
describe('StreamUtils', () => {
|
|
8
|
+
describe('extractTenantIdFromArn', () => {
|
|
9
|
+
it('should extract tenant ID from valid CMP table ARN', () => {
|
|
10
|
+
const arn =
|
|
11
|
+
'arn:aws:dynamodb:us-east-1:123456789012:table/dev.cmp-service.tenant123/stream/2024-01-01T00:00:00.000';
|
|
12
|
+
const tenantId = extractTenantIdFromArn(arn, 'cmp');
|
|
13
|
+
expect(tenantId).toBe('tenant123');
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
it('should extract tenant ID from valid content table ARN', () => {
|
|
17
|
+
const arn =
|
|
18
|
+
'arn:aws:dynamodb:us-east-1:123456789012:table/prod.content-service.acme/stream/2024-01-01T00:00:00.000';
|
|
19
|
+
const tenantId = extractTenantIdFromArn(arn, 'content');
|
|
20
|
+
expect(tenantId).toBe('acme');
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it('should extract only the last segment as tenant ID', () => {
|
|
24
|
+
const arn =
|
|
25
|
+
'arn:aws:dynamodb:us-east-1:123456789012:table/dev.cmp-service.tenant123/stream/2024-01-01T00:00:00.000';
|
|
26
|
+
const tenantId = extractTenantIdFromArn(arn, 'cmp');
|
|
27
|
+
expect(tenantId).toBe('tenant123');
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it('should throw error for invalid ARN format', () => {
|
|
31
|
+
const invalidArn = 'not-a-valid-arn';
|
|
32
|
+
expect(() => extractTenantIdFromArn(invalidArn, 'cmp')).toThrow('Invalid ARN format');
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it('should throw error for invalid table name format', () => {
|
|
36
|
+
const arn = 'arn:aws:dynamodb:us-east-1:123456789012:table/invalid-table-name/stream/2024-01-01T00:00:00.000';
|
|
37
|
+
expect(() => extractTenantIdFromArn(arn, 'cmp')).toThrow('Invalid cmp table name format');
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it('should throw error when service identifier does not match', () => {
|
|
41
|
+
const arn =
|
|
42
|
+
'arn:aws:dynamodb:us-east-1:123456789012:table/dev.content-service.tenant123/stream/2024-01-01T00:00:00.000';
|
|
43
|
+
expect(() => extractTenantIdFromArn(arn, 'cmp')).toThrow('Invalid cmp table name format');
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
it('should throw error for ARN with missing table name segment', () => {
|
|
47
|
+
const arn = 'arn:aws:dynamodb:us-east-1:123456789012:table//stream/2024-01-01T00:00:00.000';
|
|
48
|
+
expect(() => extractTenantIdFromArn(arn, 'cmp')).toThrow('Invalid ARN format');
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
describe('getDynamoValue', () => {
|
|
53
|
+
it('should extract string value from DynamoDB attribute', () => {
|
|
54
|
+
const attr = { S: 'test-value' };
|
|
55
|
+
expect(getDynamoValue(attr)).toBe('test-value');
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it('should extract number value from DynamoDB attribute', () => {
|
|
59
|
+
const attr = { N: '123' };
|
|
60
|
+
expect(getDynamoValue(attr)).toBe('123');
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
it('should prefer string value over number value', () => {
|
|
64
|
+
const attr = { S: 'string-value', N: '123' };
|
|
65
|
+
expect(getDynamoValue(attr)).toBe('string-value');
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
it('should return undefined when attribute is undefined', () => {
|
|
69
|
+
expect(getDynamoValue(undefined)).toBeUndefined();
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
it('should return undefined when both S and N are undefined', () => {
|
|
73
|
+
const attr = {};
|
|
74
|
+
expect(getDynamoValue(attr as any)).toBeUndefined();
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
it('should return undefined when attribute has no S or N property', () => {
|
|
78
|
+
const attr = { M: {} };
|
|
79
|
+
expect(getDynamoValue(attr as any)).toBeUndefined();
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
it('should handle empty string values by returning undefined', () => {
|
|
83
|
+
const attr = { S: '' };
|
|
84
|
+
expect(getDynamoValue(attr)).toBeUndefined();
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
describe('getActionType', () => {
|
|
89
|
+
it('should return create for INSERT events', () => {
|
|
90
|
+
expect(getActionType('INSERT')).toBe('create');
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
it('should return delete for REMOVE events', () => {
|
|
94
|
+
expect(getActionType('REMOVE')).toBe('delete');
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
it('should return update for MODIFY events', () => {
|
|
98
|
+
expect(getActionType('MODIFY')).toBe('update');
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
it('should return update for unknown event types', () => {
|
|
102
|
+
expect(getActionType('UNKNOWN')).toBe('update');
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
it('should return update when event name is undefined', () => {
|
|
106
|
+
expect(getActionType(undefined)).toBe('update');
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
it('should return update when event name is empty string', () => {
|
|
110
|
+
expect(getActionType('')).toBe('update');
|
|
111
|
+
});
|
|
112
|
+
});
|
|
113
|
+
});
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright Squiz Australia Pty Ltd. All Rights Reserved.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Extracts tenant ID from a DynamoDB stream ARN
|
|
8
|
+
*
|
|
9
|
+
* ARN format: arn:aws:dynamodb:region:account:table/tableName/stream/timestamp
|
|
10
|
+
* Table name format: {stackPrefix}.{tableServiceName}-service.{tenantId}
|
|
11
|
+
*
|
|
12
|
+
* @param arn - The event source ARN from the DynamoDB stream record
|
|
13
|
+
* @param tableServiceIdentifier - The service identifier (e.g., 'cmp', 'content') to validate in table name
|
|
14
|
+
* @returns The tenant ID extracted from the table name
|
|
15
|
+
* @throws Error if ARN or table name format is invalid
|
|
16
|
+
*/
|
|
17
|
+
export function extractTenantIdFromArn(arn: string, tableServiceIdentifier: string): string {
|
|
18
|
+
const tableName = arn.split('/')[1];
|
|
19
|
+
if (!tableName) {
|
|
20
|
+
throw new Error(`Invalid ARN format: ${arn}`);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const parts = tableName.split('.');
|
|
24
|
+
if (parts.length < 3 || parts[1] !== `${tableServiceIdentifier}-service`) {
|
|
25
|
+
throw new Error(
|
|
26
|
+
`Invalid ${tableServiceIdentifier} table name format: ${tableName}. Expected format: {prefix}.${tableServiceIdentifier}-service.{tenantId}`,
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return parts[parts.length - 1];
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Extracts string or number value from DynamoDB attribute format
|
|
35
|
+
*
|
|
36
|
+
* DynamoDB represents attributes as objects with type keys (e.g., { S: "value" }, { N: "123" })
|
|
37
|
+
* This helper extracts the actual value.
|
|
38
|
+
*
|
|
39
|
+
* @param value - The DynamoDB attribute value object
|
|
40
|
+
* @returns The extracted string value, or undefined if the attribute is empty
|
|
41
|
+
*/
|
|
42
|
+
export function getDynamoValue(value?: { S?: string; N?: string }): string | undefined {
|
|
43
|
+
return value?.S || value?.N;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Determines the action type based on DynamoDB event name
|
|
48
|
+
*
|
|
49
|
+
* Maps DynamoDB stream event types to semantic action types suitable for event publishing.
|
|
50
|
+
*
|
|
51
|
+
* @param eventName - The DynamoDB stream event name (INSERT, MODIFY, REMOVE)
|
|
52
|
+
* @returns The corresponding action: 'create', 'update', or 'delete'
|
|
53
|
+
*/
|
|
54
|
+
export function getActionType(eventName?: string): 'create' | 'update' | 'delete' {
|
|
55
|
+
if (eventName === 'INSERT') return 'create';
|
|
56
|
+
if (eventName === 'REMOVE') return 'delete';
|
|
57
|
+
return 'update';
|
|
58
|
+
}
|