core-services-sdk 1.3.3 → 1.3.4
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/package.json +4 -1
- package/src/core/combine-unique-arrays.js +15 -0
- package/src/core/index.js +5 -0
- package/src/core/normalize-to-array.js +31 -0
- package/src/core/otp-generators.js +113 -0
- package/src/core/regex-utils.js +27 -0
- package/src/core/sanitize-objects.js +50 -0
- package/src/crypto/crypto.js +128 -0
- package/src/crypto/encryption.js +48 -0
- package/src/crypto/index.js +2 -0
- package/src/fastify/error-handlers/with-error-handling.js +5 -1
- package/src/ids/generators.js +73 -0
- package/src/ids/prefixes.js +28 -0
- package/src/index.js +3 -1
- package/src/logger/get-logger.js +64 -0
- package/src/logger/index.js +1 -0
- package/src/mongodb/index.js +3 -73
- package/src/mongodb/initialize-mongodb.js +73 -0
- package/src/mongodb/validate-mongo-uri.js +32 -0
- package/tests/core/combine-unique-arrays.unit.test.js +35 -0
- package/tests/core/normalize-to-array.unit.test.js +43 -0
- package/tests/core/otp-generators.unit.test.js +93 -0
- package/tests/core/regex-utils.unit.test.js +41 -0
- package/tests/core/sanitize-objects.unit.test.js +78 -0
- package/tests/crypto/crypto.unit.test.js +130 -0
- package/tests/crypto/encryption.unit.test.js +73 -0
- package/tests/ids/generators.unit.test.js +72 -0
- package/tests/ids/prefixes.unit.test.js +42 -0
- package/tests/logger/get-logger.unit.test.js +64 -0
- package/src/fastify/error-handlers/with-error-handling.types.js +0 -10
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest'
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
generateId,
|
|
5
|
+
generateUserId,
|
|
6
|
+
generateTenantId,
|
|
7
|
+
generatePrefixedId,
|
|
8
|
+
generatePermissionId,
|
|
9
|
+
generateCorrelationId,
|
|
10
|
+
generateVerificationId,
|
|
11
|
+
generateRolePermissionsId,
|
|
12
|
+
} from '../../src/ids/generators.js'
|
|
13
|
+
import { ID_PREFIXES } from '../../src/ids/prefixes.js'
|
|
14
|
+
|
|
15
|
+
const UUID_V4_REGEX =
|
|
16
|
+
/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i
|
|
17
|
+
|
|
18
|
+
const testPrefixFunction = (fn, expectedPrefix) => {
|
|
19
|
+
const id = fn()
|
|
20
|
+
expect(typeof id).toBe('string')
|
|
21
|
+
const [prefix, uuid] = id.split('_')
|
|
22
|
+
expect(prefix).toBe(expectedPrefix)
|
|
23
|
+
expect(uuid).toMatch(UUID_V4_REGEX)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
describe('generateId', () => {
|
|
27
|
+
it('generates a valid UUID v4', () => {
|
|
28
|
+
const id = generateId()
|
|
29
|
+
expect(typeof id).toBe('string')
|
|
30
|
+
expect(id).toMatch(UUID_V4_REGEX)
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
it('generates unique UUIDs', () => {
|
|
34
|
+
const ids = new Set(Array.from({ length: 10 }, () => generateId()))
|
|
35
|
+
expect(ids.size).toBe(10)
|
|
36
|
+
})
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
describe('generatePrefixedId', () => {
|
|
40
|
+
it('generates an ID with the correct prefix', () => {
|
|
41
|
+
const prefixed = generatePrefixedId('test')
|
|
42
|
+
const [prefix, uuid] = prefixed.split('_')
|
|
43
|
+
expect(prefix).toBe('test')
|
|
44
|
+
expect(uuid).toMatch(UUID_V4_REGEX)
|
|
45
|
+
})
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
describe('generate*Id functions', () => {
|
|
49
|
+
it('generateUserId returns ID with usr_ prefix', () => {
|
|
50
|
+
testPrefixFunction(generateUserId, ID_PREFIXES.USER)
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
it('generateTenantId returns ID with tnt_ prefix', () => {
|
|
54
|
+
testPrefixFunction(generateTenantId, ID_PREFIXES.TENANT)
|
|
55
|
+
})
|
|
56
|
+
|
|
57
|
+
it('generatePermissionId returns ID with prm_ prefix', () => {
|
|
58
|
+
testPrefixFunction(generatePermissionId, ID_PREFIXES.PERMISSION)
|
|
59
|
+
})
|
|
60
|
+
|
|
61
|
+
it('generateCorrelationId returns ID with crln_ prefix', () => {
|
|
62
|
+
testPrefixFunction(generateCorrelationId, ID_PREFIXES.CORRELATION)
|
|
63
|
+
})
|
|
64
|
+
|
|
65
|
+
it('generateVerificationId returns ID with vrf_ prefix', () => {
|
|
66
|
+
testPrefixFunction(generateVerificationId, ID_PREFIXES.VERIFICATION)
|
|
67
|
+
})
|
|
68
|
+
|
|
69
|
+
it('generateRolePermissionsId returns ID with role_ prefix', () => {
|
|
70
|
+
testPrefixFunction(generateRolePermissionsId, ID_PREFIXES.ROLE_PERMISSIONS)
|
|
71
|
+
})
|
|
72
|
+
})
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
2
|
+
import { describe, it, expect } from 'vitest'
|
|
3
|
+
|
|
4
|
+
import { ID_PREFIXES } from '../../src/ids/prefixes.js'
|
|
5
|
+
|
|
6
|
+
describe('ID_PREFIXES', () => {
|
|
7
|
+
it('contains expected keys and values', () => {
|
|
8
|
+
expect(ID_PREFIXES).toEqual({
|
|
9
|
+
USER: 'usr',
|
|
10
|
+
TENANT: 'tnt',
|
|
11
|
+
PERMISSION: 'prm',
|
|
12
|
+
CORRELATION: 'crln',
|
|
13
|
+
VERIFICATION: 'vrf',
|
|
14
|
+
ROLE_PERMISSIONS: 'role',
|
|
15
|
+
})
|
|
16
|
+
})
|
|
17
|
+
|
|
18
|
+
it('has string values for all keys', () => {
|
|
19
|
+
Object.values(ID_PREFIXES).forEach((value) => {
|
|
20
|
+
expect(typeof value).toBe('string')
|
|
21
|
+
})
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
it('has unique values', () => {
|
|
25
|
+
const values = Object.values(ID_PREFIXES)
|
|
26
|
+
const unique = new Set(values)
|
|
27
|
+
expect(unique.size).toBe(values.length)
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
it('is frozen (immutable)', () => {
|
|
31
|
+
expect(Object.isFrozen(ID_PREFIXES)).toBe(true)
|
|
32
|
+
|
|
33
|
+
// Try to mutate
|
|
34
|
+
try {
|
|
35
|
+
ID_PREFIXES.USER = 'hacked'
|
|
36
|
+
} catch (_) {
|
|
37
|
+
// Ignore error in strict mode
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
expect(ID_PREFIXES.USER).toBe('usr')
|
|
41
|
+
})
|
|
42
|
+
})
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { describe, it, expect, vi } from 'vitest'
|
|
2
|
+
import { getLogger } from '../../src/logger/get-logger.js'
|
|
3
|
+
|
|
4
|
+
describe('getLogger', () => {
|
|
5
|
+
it('returns a default pino logger when called with undefined', () => {
|
|
6
|
+
const logger = getLogger(undefined)
|
|
7
|
+
expect(typeof logger.info).toBe('function')
|
|
8
|
+
// @ts-ignore
|
|
9
|
+
expect(logger.level).toBe('info')
|
|
10
|
+
})
|
|
11
|
+
|
|
12
|
+
it('returns a default pino logger when called with true', () => {
|
|
13
|
+
const logger = getLogger(true)
|
|
14
|
+
expect(typeof logger.info).toBe('function')
|
|
15
|
+
// @ts-ignore
|
|
16
|
+
expect(logger.level).toBe('info')
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
it('returns a pino logger when called with { logger: true } and optional level', () => {
|
|
20
|
+
const logger = getLogger({ logger: true, level: 'debug' })
|
|
21
|
+
expect(typeof logger.debug).toBe('function')
|
|
22
|
+
// @ts-ignore
|
|
23
|
+
expect(logger.level).toBe('debug')
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
it('returns the custom logger when provided and valid', () => {
|
|
27
|
+
const mockLogger = {
|
|
28
|
+
info: vi.fn(),
|
|
29
|
+
warn: vi.fn(),
|
|
30
|
+
error: vi.fn(),
|
|
31
|
+
debug: vi.fn(),
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const result = getLogger({ logger: mockLogger })
|
|
35
|
+
expect(result).toBe(mockLogger)
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
it('returns the dummy logger when logger is invalid', () => {
|
|
39
|
+
const invalidLogger = { info: () => {}, warn: () => {} } // missing 'error' and 'debug'
|
|
40
|
+
const logger = getLogger({ logger: invalidLogger })
|
|
41
|
+
|
|
42
|
+
expect(logger.info).toBeDefined()
|
|
43
|
+
expect(logger.warn).toBeDefined()
|
|
44
|
+
expect(logger.error).toBeDefined()
|
|
45
|
+
expect(logger.debug).toBeDefined()
|
|
46
|
+
|
|
47
|
+
// Check that it's the dummy logger (no-op)
|
|
48
|
+
expect(() => logger.info('hello')).not.toThrow()
|
|
49
|
+
// @ts-ignore
|
|
50
|
+
expect(logger.info()).toBeUndefined()
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
it('returns the dummy logger when called with invalid object', () => {
|
|
54
|
+
const result = getLogger({ someOtherKey: 123 })
|
|
55
|
+
expect(result.info).toBeDefined()
|
|
56
|
+
expect(result.warn).toBeDefined()
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
it('logs a message when using internal pino', () => {
|
|
60
|
+
const logger = getLogger({ logger: true, level: 'warn' })
|
|
61
|
+
// @ts-ignore
|
|
62
|
+
expect(logger.level).toBe('warn')
|
|
63
|
+
})
|
|
64
|
+
})
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @typedef {object} Reply
|
|
3
|
-
* @property {(code: number) => Reply} status - Sets the HTTP status code
|
|
4
|
-
* @property {(payload: any) => void} send - Sends the response
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* @typedef {object} Logger
|
|
9
|
-
* @property {(message: string, ...args: any[]) => void} error - Logs an error message
|
|
10
|
-
*/
|