core-services-sdk 1.3.20 → 1.3.22

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/.eslintrc.json ADDED
@@ -0,0 +1,14 @@
1
+ {
2
+ "env": {
3
+ "es2021": true,
4
+ "node": true
5
+ },
6
+ "extends": ["eslint:recommended", "plugin:prettier/recommended"],
7
+ "plugins": ["prettier"],
8
+ "rules": {
9
+ "prettier/prettier": "error",
10
+ "no-unused-vars": "warn",
11
+ "no-console": "off"
12
+ },
13
+ "ignores": ["node_modules", "dist", ".next"]
14
+ }
@@ -12,5 +12,10 @@
12
12
  },
13
13
  "javascript.preferences.importModuleSpecifierEnding": "js",
14
14
  "js/ts.implicitProjectConfig.checkJs": true,
15
- "javascript.validate.enable": true
15
+ "javascript.validate.enable": true,
16
+ "eslint.validate": ["javascript"],
17
+
18
+ "editor.codeActionsOnSave": {
19
+ "source.fixAll.eslint": "explicit"
20
+ }
16
21
  }
@@ -0,0 +1,21 @@
1
+ import eslintPluginPrettier from 'eslint-plugin-prettier'
2
+
3
+ /** @type {import("eslint").Linter.FlatConfig} */
4
+ export default [
5
+ {
6
+ files: ['**/*.js'],
7
+ languageOptions: {
8
+ sourceType: 'module',
9
+ ecmaVersion: 'latest',
10
+ },
11
+ plugins: {
12
+ prettier: eslintPluginPrettier,
13
+ },
14
+ rules: {
15
+ 'no-console': 'off',
16
+ 'no-unused-vars': 'warn',
17
+ 'curly': ['error', 'all'],
18
+ 'prettier/prettier': 'error',
19
+ },
20
+ },
21
+ ]
package/package.json CHANGED
@@ -1,10 +1,14 @@
1
1
  {
2
2
  "name": "core-services-sdk",
3
- "version": "1.3.20",
3
+ "version": "1.3.22",
4
4
  "main": "src/index.js",
5
5
  "type": "module",
6
6
  "scripts": {
7
- "test": "vitest run --coverage"
7
+ "lint": "eslint .",
8
+ "lint:fix": "eslint . --fix",
9
+ "test": "vitest run --coverage",
10
+ "format": "prettier --write .",
11
+ "bump": "node ./scripts/bump-version.js"
8
12
  },
9
13
  "repository": {
10
14
  "type": "git",
@@ -30,13 +34,18 @@
30
34
  "mongodb": "^6.18.0",
31
35
  "nodemailer": "^7.0.5",
32
36
  "pino": "^9.7.0",
37
+ "ulid": "^3.0.1",
33
38
  "uuid": "^11.1.0",
34
39
  "xml2js": "^0.6.2"
35
40
  },
36
41
  "devDependencies": {
37
42
  "@vitest/coverage-v8": "^3.2.4",
43
+ "eslint": "^9.30.0",
44
+ "eslint-config-prettier": "^10.1.5",
45
+ "eslint-plugin-prettier": "^5.5.1",
38
46
  "path": "^0.12.7",
47
+ "prettier": "^3.6.2",
39
48
  "url": "^0.11.4",
40
49
  "vitest": "^3.2.4"
41
50
  }
42
- }
51
+ }
@@ -0,0 +1,68 @@
1
+ import fs from 'fs'
2
+ import path from 'path'
3
+ import { execSync } from 'child_process'
4
+
5
+ const type = process.argv[2] // "major" | "minor" | "patch" | "-major" | "-minor" | "-patch"
6
+
7
+ if (!['major', 'minor', 'patch', '-major', '-minor', '-patch'].includes(type)) {
8
+ console.error(`Usage: npm run bump <major|minor|patch|-major|-minor|-patch>`)
9
+ process.exit(1)
10
+ }
11
+
12
+ const pkgPath = path.resolve(process.cwd(), 'package.json')
13
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'))
14
+
15
+ let [major, minor, patch] = pkg.version.split('.').map(Number)
16
+
17
+ const bump = () => {
18
+ switch (type) {
19
+ case 'major':
20
+ return [major + 1, 0, 0]
21
+ case 'minor':
22
+ return [major, minor + 1, 0]
23
+ case 'patch':
24
+ return [major, minor, patch + 1]
25
+ case '-major':
26
+ if (major === 0) {
27
+ throw new Error('Cannot decrement major below 0')
28
+ }
29
+ return [major - 1, 0, 0]
30
+ case '-minor':
31
+ if (minor === 0) {
32
+ if (major === 0) {
33
+ throw new Error('Cannot decrement minor below 0.0')
34
+ }
35
+ return [major - 1, 0, 0]
36
+ }
37
+ return [major, minor - 1, 0]
38
+ case '-patch':
39
+ if (patch === 0) {
40
+ if (minor === 0) {
41
+ if (major === 0) {
42
+ throw new Error('Cannot decrement below 0.0.0')
43
+ }
44
+ return [major - 1, 0, 0]
45
+ }
46
+ return [major, minor - 1, 0]
47
+ }
48
+ return [major, minor, patch - 1]
49
+ }
50
+ }
51
+
52
+ const [newMajor, newMinor, newPatch] = bump()
53
+ const newVersion = `${newMajor}.${newMinor}.${newPatch}`
54
+
55
+ pkg.version = newVersion
56
+ fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + '\n')
57
+
58
+ console.log(`✔ Updated version to ${newVersion}`)
59
+
60
+ // update package-lock.json if exists
61
+ if (fs.existsSync('./package-lock.json')) {
62
+ try {
63
+ execSync('npm install --package-lock-only', { stdio: 'inherit' })
64
+ console.log('✔ package-lock.json updated')
65
+ } catch (err) {
66
+ console.error('Failed to update package-lock.json', err)
67
+ }
68
+ }
@@ -7,10 +7,9 @@ import * as raw from 'google-libphonenumber'
7
7
  export function getLib() {
8
8
  // Prefer direct (CJS-style or ESM w/ named), else default
9
9
  // e.g. raw.PhoneNumberUtil OR raw.default.PhoneNumberUtil
10
- // eslint-disable-next-line no-unused-vars
11
10
  /** @type {any} */
12
11
  const anyRaw = raw
13
- const lib = anyRaw.PhoneNumberUtil ? anyRaw : anyRaw.default ?? anyRaw
12
+ const lib = anyRaw.PhoneNumberUtil ? anyRaw : (anyRaw.default ?? anyRaw)
14
13
 
15
14
  if (!lib || !lib.PhoneNumberUtil || !lib.PhoneNumberFormat) {
16
15
  throw new Error('google-libphonenumber failed to load (exports not found)')
@@ -71,7 +70,9 @@ export function normalizePhoneOrThrowIntl(input) {
71
70
  try {
72
71
  const util = phoneUtil()
73
72
  const parsed = util.parseAndKeepRawInput(clean(input))
74
- if (!util.isValidNumber(parsed)) throw new Error('x')
73
+ if (!util.isValidNumber(parsed)) {
74
+ throw new Error('Phone number failed validation')
75
+ }
75
76
  return toResult(parsed)
76
77
  } catch (e) {
77
78
  const err = new Error('Invalid phone number')
@@ -91,7 +92,9 @@ export function normalizePhoneOrThrowWithRegion(input, defaultRegion) {
91
92
  try {
92
93
  const util = phoneUtil()
93
94
  const parsed = util.parseAndKeepRawInput(clean(input), defaultRegion)
94
- if (!util.isValidNumber(parsed)) throw new Error('x')
95
+ if (!util.isValidNumber(parsed)) {
96
+ throw new Error('Phone number failed validation')
97
+ }
95
98
  return toResult(parsed)
96
99
  } catch (e) {
97
100
  const err = new Error('Invalid phone number')
@@ -16,8 +16,12 @@
16
16
  */
17
17
 
18
18
  export const isValidRegex = (pattern) => {
19
- if (pattern instanceof RegExp) return true
20
- if (typeof pattern !== 'string') return false
19
+ if (pattern instanceof RegExp) {
20
+ return true
21
+ }
22
+ if (typeof pattern !== 'string') {
23
+ return false
24
+ }
21
25
  try {
22
26
  new RegExp(pattern)
23
27
  return true
package/src/http/http.js CHANGED
@@ -83,7 +83,9 @@ const tryGetJsonResponse = async (response) => {
83
83
  jsonText = await getTextResponse(response)
84
84
  return tryConvertJsonResponse(jsonText)
85
85
  } catch (error) {
86
- if (!jsonText) throw error
86
+ if (!jsonText) {
87
+ throw error
88
+ }
87
89
  return jsonText
88
90
  }
89
91
  }
@@ -100,7 +102,9 @@ const tryGetXmlResponse = async (response) => {
100
102
  xmlText = await getTextResponse(response)
101
103
  return await parseStringPromise(xmlText)
102
104
  } catch (error) {
103
- if (!xmlText) throw error
105
+ if (!xmlText) {
106
+ throw error
107
+ }
104
108
  return xmlText
105
109
  }
106
110
  }
@@ -1,26 +1,28 @@
1
- import { v4 as uuidv4 } from 'uuid'
1
+ import { ulid } from 'ulid'
2
2
  import { ID_PREFIXES } from './prefixes.js'
3
3
 
4
4
  /**
5
- * Generates a new UUID v4 string.
5
+ * Generates a new ULID string.
6
6
  *
7
- * @returns {string} A new UUID (version 4).
7
+ * ULIDs are 26-character, lexicographically sortable identifiers.
8
+ *
9
+ * @returns {string} A new ULID.
8
10
  *
9
11
  * @example
10
- * generateId() // '550e8400-e29b-41d4-a716-446655440000'
12
+ * generateId() // '01HZY3M7K4FJ9A8Q4Y1ZB5NX3T'
11
13
  */
12
14
  export const generateId = () => {
13
- return uuidv4()
15
+ return ulid()
14
16
  }
15
17
 
16
18
  /**
17
19
  * Generates a unique ID with the given prefix.
18
20
  *
19
- * @param {string} prefix - A prefix string to prepend to the UUID.
20
- * @returns {string} A unique ID in the format `${prefix}_${uuid}`.
21
+ * @param {string} prefix - A prefix string to prepend to the ULID.
22
+ * @returns {string} A unique ID in the format `${prefix}_${ulid}`.
21
23
  *
22
24
  * @example
23
- * generatePrefixedId('usr') // 'usr_550e8400-e29b-41d4-a716-446655440000'
25
+ * generatePrefixedId('usr') // 'usr_01HZY3M7K4FJ9A8Q4Y1ZB5NX3T'
24
26
  */
25
27
  export const generatePrefixedId = (prefix) => {
26
28
  return `${prefix}_${generateId()}`
@@ -73,9 +75,9 @@ export const generateRolePermissionsId = () =>
73
75
  generatePrefixedId(ID_PREFIXES.ROLE_PERMISSIONS)
74
76
 
75
77
  /**
76
- * Generates a onboarding ID with a `onb_` prefix.
78
+ * Generates an onboarding ID with a `onb_` prefix.
77
79
  *
78
- * @returns {string} A onboarding ID.
80
+ * @returns {string} An onboarding ID.
79
81
  */
80
82
  export const generateOnboardingId = () =>
81
83
  generatePrefixedId(ID_PREFIXES.ONBOARDING)
@@ -83,6 +85,6 @@ export const generateOnboardingId = () =>
83
85
  /**
84
86
  * Generates a session ID with a `sess_` prefix.
85
87
  *
86
- * @returns {string} A onboarding ID.
88
+ * @returns {string} A session ID.
87
89
  */
88
90
  export const generateSessionId = () => generatePrefixedId(ID_PREFIXES.SESSION)
@@ -1,8 +1,8 @@
1
1
  /**
2
2
  * Mapping of entity types to their unique ID prefixes.
3
3
  *
4
- * These prefixes are prepended to UUIDs to create consistent and identifiable IDs across the system.
5
- * For example: 'usr_550e8400-e29b-41d4-a716-446655440000'
4
+ * These prefixes are prepended to ULIDs to create consistent and identifiable IDs across the system.
5
+ * For example: 'usr_01HZY3M7K4FJ9A8Q4Y1ZB5NX3T'
6
6
  *
7
7
  * @readonly
8
8
  * @enum {string}
@@ -26,7 +26,7 @@ export function isValidMongoUri(uri) {
26
26
  const hasHostname = Boolean(parsed.hostname)
27
27
 
28
28
  return isValidProtocol && hasHostname
29
- } catch (e) {
29
+ } catch {
30
30
  return false
31
31
  }
32
32
  }
@@ -1,48 +1,83 @@
1
1
  // @ts-nocheck
2
2
  import * as amqp from 'amqplib'
3
- import { v4 as uuidv4 } from 'uuid'
3
+ import { ulid } from 'ulid'
4
4
 
5
5
  /**
6
6
  * @typedef {Object} Log
7
- * @property {(msg: string) => void} info
8
- * @property {(msg: string, ...args: any[]) => void} error
7
+ * @property {(obj: any, msg?: string) => void} info
8
+ * @property {(obj: any, msg?: string) => void} error
9
+ * @property {(obj: any, msg?: string) => void} debug
9
10
  */
10
11
 
12
+ const generateMsgId = () => `rbt_${ulid()}`
13
+
11
14
  /**
12
- * Connects to RabbitMQ server.
13
- * @param {{ host: string }} options
15
+ * Connects to a RabbitMQ server.
16
+ *
17
+ * @param {{ host: string, log: import('pino').Logger }} options
14
18
  * @returns {Promise<amqp.Connection>}
15
19
  */
16
- export const connectQueueService = async ({ host }) => {
20
+ export const connectQueueService = async ({ host, log }) => {
21
+ const t0 = Date.now()
22
+ const logger = log.child({ op: 'connectQueueService', host })
23
+
17
24
  try {
18
- return await amqp.connect(host)
19
- } catch (error) {
20
- console.error('Failed to connect to RabbitMQ:', error)
21
- throw error
25
+ logger.debug('start')
26
+ const connection = await amqp.connect(host)
27
+
28
+ logger.info({
29
+ event: 'ok',
30
+ ms: Date.now() - t0,
31
+ })
32
+
33
+ return connection
34
+ } catch (err) {
35
+ logger.error(err, {
36
+ event: 'error',
37
+ ms: Date.now() - t0,
38
+ })
39
+ throw err
22
40
  }
23
41
  }
24
42
 
25
43
  /**
26
- * Creates a channel from RabbitMQ connection.
27
- * @param {{ host: string }} options
44
+ * Creates a channel from a RabbitMQ connection.
45
+ *
46
+ * @param {{ host: string, log: import('pino').Logger }} options
28
47
  * @returns {Promise<amqp.Channel>}
29
48
  */
30
- export const createChannel = async ({ host }) => {
49
+ export const createChannel = async ({ host, log }) => {
50
+ const t0 = Date.now()
51
+ const logger = log.child({ op: 'createChannel', host })
52
+
31
53
  try {
54
+ logger.debug('start')
32
55
  const connection = /** @type {amqp.Connection} */ (
33
- await connectQueueService({ host })
56
+ await connectQueueService({ host, log })
34
57
  )
35
- return await connection.createChannel()
36
- } catch (error) {
37
- console.error('Failed to create channel:', error)
38
- throw error
58
+ const channel = await connection.createChannel()
59
+
60
+ logger.debug('channel-created')
61
+ logger.info({
62
+ event: 'ok',
63
+ ms: Date.now() - t0,
64
+ })
65
+
66
+ return channel
67
+ } catch (err) {
68
+ logger.error(err, {
69
+ event: 'error',
70
+ ms: Date.now() - t0,
71
+ })
72
+ throw err
39
73
  }
40
74
  }
41
75
 
42
76
  /**
43
- * Parses a RabbitMQ message.
77
+ * Parses a RabbitMQ message into a structured object.
78
+ *
44
79
  * @param {amqp.ConsumeMessage} msgInfo
45
- * @returns {{ msgId: string, data: any }}
80
+ * @returns {{ msgId: string, data: any, correlationId?: string }}
46
81
  */
47
82
  const parseMessage = (msgInfo) => {
48
83
  return JSON.parse(msgInfo.content.toString())
@@ -54,8 +89,8 @@ const parseMessage = (msgInfo) => {
54
89
  * @param {Object} options
55
90
  * @param {import('amqplib').Channel} options.channel - RabbitMQ channel
56
91
  * @param {string} options.queue - Queue name to subscribe to
57
- * @param {(data: any) => Promise<void>} options.onReceive - Async handler for incoming message
58
- * @param {Log} options.log - Logging utility
92
+ * @param {(data: any, correlationId?: string) => Promise<void>} options.onReceive - Async handler
93
+ * @param {import('pino').Logger} options.log - Base logger
59
94
  * @param {boolean} [options.nackOnError=false] - Whether to nack the message on error (default: false)
60
95
  * @param {number} [options.prefetch=1] - Max unacked messages per consumer (default: 1)
61
96
  *
@@ -69,29 +104,48 @@ export const subscribeToQueue = async ({
69
104
  onReceive,
70
105
  nackOnError = false,
71
106
  }) => {
107
+ const logger = log.child({ op: 'subscribeToQueue', queue })
108
+
72
109
  try {
73
110
  await channel.assertQueue(queue, { durable: true })
74
-
75
111
  !!prefetch && (await channel.prefetch(prefetch))
76
112
 
77
113
  channel.consume(queue, async (msgInfo) => {
78
- if (!msgInfo) return
114
+ if (!msgInfo) {
115
+ return
116
+ }
117
+ const t0 = Date.now()
118
+
119
+ const { msgId, data, correlationId } = parseMessage(msgInfo)
120
+ const child = logger.child({ msgId, correlationId })
79
121
 
80
122
  try {
81
- const { msgId, data } = parseMessage(msgInfo)
82
- log.info(`Handling message from '${queue}' msgId: ${msgId}`)
83
- await onReceive(data)
123
+ child.debug('start')
124
+ child.info('message-received')
125
+
126
+ await onReceive(data, correlationId)
84
127
  channel.ack(msgInfo)
85
- } catch (error) {
86
- const { msgId } = parseMessage(msgInfo)
87
- log.error(`Error handling message: ${msgId} on queue '${queue}'`)
88
- log.error(error)
128
+
129
+ child.info({
130
+ event: 'ok',
131
+ ms: Date.now() - t0,
132
+ })
133
+ return
134
+ } catch (err) {
89
135
  nackOnError ? channel.nack(msgInfo) : channel.ack(msgInfo)
136
+
137
+ child.error(err, {
138
+ event: 'error',
139
+ ms: Date.now() - t0,
140
+ })
141
+ return
90
142
  }
91
143
  })
92
- } catch (error) {
93
- console.error('Failed to subscribe to queue:', error)
94
- throw error
144
+ } catch (err) {
145
+ logger.error(err, {
146
+ event: 'error',
147
+ })
148
+ throw err
95
149
  }
96
150
  }
97
151
 
@@ -99,57 +153,73 @@ export const subscribeToQueue = async ({
99
153
  * Initializes RabbitMQ integration with publish and subscribe support.
100
154
  *
101
155
  * @param {Object} options
102
- * @param {string} options.host - RabbitMQ connection URI (e.g., 'amqp://user:pass@localhost:5672')
103
- * @param {Log} options.log - Logging utility with `info()` and `error()` methods
156
+ * @param {string} options.host - RabbitMQ connection URI
157
+ * @param {import('pino').Logger} options.log - Logger
104
158
  *
105
159
  * @returns {Promise<{
106
- * publish: (queue: string, data: any) => Promise<boolean>,
160
+ * publish: (queue: string, data: any, correlationId?: string) => Promise<boolean>,
107
161
  * subscribe: (options: {
108
162
  * queue: string,
109
- * onReceive: (data: any) => Promise<void>,
163
+ * onReceive: (data: any, correlationId?: string) => Promise<void>,
110
164
  * nackOnError?: boolean
111
165
  * }) => Promise<void>,
112
166
  * channel: amqp.Channel
113
167
  * }>}
114
- *
115
- * @example
116
- * const rabbit = await initializeQueue({ host, log });
117
- * await rabbit.publish('jobs', { task: 'sendEmail' });
118
- * await rabbit.subscribe({
119
- * queue: 'jobs',
120
- * onReceive: async (data) => { console.log(data); },
121
- * });
122
168
  */
123
169
  export const initializeQueue = async ({ host, log }) => {
124
- const channel = await createChannel({ host })
170
+ const channel = await createChannel({ host, log })
171
+ const logger = log.child({ op: 'initializeQueue' })
125
172
 
126
173
  /**
127
- * Publishes a message to a queue.
128
- * @param {string} queue
129
- * @param {any} data
130
- * @returns {Promise<boolean>}
174
+ * Publishes a message to a queue with a generated `rbt_<ulid>` ID.
175
+ *
176
+ * @param {string} queue - Queue name
177
+ * @param {any} data - Payload to send
178
+ * @param {string} [correlationId] - Correlation ID for tracing
179
+ * @returns {Promise<boolean>} True if the message was sent successfully
131
180
  */
132
- const publish = async (queue, data) => {
133
- const msgId = uuidv4()
181
+ const publish = async (queue, data, correlationId) => {
182
+ const msgId = generateMsgId()
183
+ const t0 = Date.now()
184
+ const logChild = logger.child({
185
+ op: 'publish',
186
+ queue,
187
+ msgId,
188
+ correlationId,
189
+ })
190
+
134
191
  try {
192
+ logChild.debug('start')
193
+
135
194
  await channel.assertQueue(queue, { durable: true })
136
- log.info(`Publishing to '${queue}' msgId: ${msgId}`)
137
- return channel.sendToQueue(
195
+ const payload = { msgId, data, correlationId }
196
+ const sent = channel.sendToQueue(
138
197
  queue,
139
- Buffer.from(JSON.stringify({ msgId, data })),
198
+ Buffer.from(JSON.stringify(payload)),
140
199
  )
141
- } catch (error) {
142
- log.error(`Error publishing to '${queue}' msgId: ${msgId}`)
143
- log.error(error)
144
- throw error
200
+
201
+ logChild.debug('message-sent')
202
+ logChild.info({
203
+ event: 'ok',
204
+ ms: Date.now() - t0,
205
+ })
206
+
207
+ return sent
208
+ } catch (err) {
209
+ logChild.error(err, {
210
+ event: 'error',
211
+ ms: Date.now() - t0,
212
+ })
213
+ throw err
145
214
  }
146
215
  }
147
216
 
148
217
  /**
149
- * Subscribes to a queue.
218
+ * Subscribes to a queue for incoming messages.
219
+ *
150
220
  * @param {{
151
221
  * queue: string,
152
- * onReceive: (data: any) => Promise<void>,
222
+ * onReceive: (data: any, correlationId?: string) => Promise<void>,
153
223
  * nackOnError?: boolean
154
224
  * }} options
155
225
  * @returns {Promise<void>}
@@ -166,7 +236,8 @@ export const initializeQueue = async ({ host, log }) => {
166
236
  }
167
237
 
168
238
  /**
169
- * Builds RabbitMQ URI from environment variables.
239
+ * Builds a RabbitMQ URI string from environment variables.
240
+ *
170
241
  * @param {{
171
242
  * RABBIT_HOST: string,
172
243
  * RABBIT_PORT: string | number,
@@ -20,7 +20,7 @@ describe('HTTP_METHODS constant', () => {
20
20
  // Attempt to mutate and verify it fails
21
21
  try {
22
22
  HTTP_METHODS.NEW = 'NEW'
23
- } catch (err) {
23
+ } catch {
24
24
  // Ignore in strict mode
25
25
  }
26
26
 
@@ -14,25 +14,25 @@ import {
14
14
  } from '../../src/ids/generators.js'
15
15
  import { ID_PREFIXES } from '../../src/ids/prefixes.js'
16
16
 
17
- const UUID_V4_REGEX =
18
- /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i
17
+ // ULID is a 26-character Base32 string (no I, L, O, U).
18
+ const ULID_REGEX = /^[0-9A-HJKMNP-TV-Z]{26}$/
19
19
 
20
20
  const testPrefixFunction = (fn, expectedPrefix) => {
21
21
  const id = fn()
22
22
  expect(typeof id).toBe('string')
23
- const [prefix, uuid] = id.split('_')
23
+ const [prefix, ulid] = id.split('_')
24
24
  expect(prefix).toBe(expectedPrefix)
25
- expect(uuid).toMatch(UUID_V4_REGEX)
25
+ expect(ulid).toMatch(ULID_REGEX)
26
26
  }
27
27
 
28
28
  describe('generateId', () => {
29
- it('generates a valid UUID v4', () => {
29
+ it('generates a valid ULID', () => {
30
30
  const id = generateId()
31
31
  expect(typeof id).toBe('string')
32
- expect(id).toMatch(UUID_V4_REGEX)
32
+ expect(id).toMatch(ULID_REGEX)
33
33
  })
34
34
 
35
- it('generates unique UUIDs', () => {
35
+ it('generates unique ULIDs', () => {
36
36
  const ids = new Set(Array.from({ length: 10 }, () => generateId()))
37
37
  expect(ids.size).toBe(10)
38
38
  })
@@ -41,9 +41,9 @@ describe('generateId', () => {
41
41
  describe('generatePrefixedId', () => {
42
42
  it('generates an ID with the correct prefix', () => {
43
43
  const prefixed = generatePrefixedId('test')
44
- const [prefix, uuid] = prefixed.split('_')
44
+ const [prefix, ulid] = prefixed.split('_')
45
45
  expect(prefix).toBe('test')
46
- expect(uuid).toMatch(UUID_V4_REGEX)
46
+ expect(ulid).toMatch(ULID_REGEX)
47
47
  })
48
48
  })
49
49
 
@@ -35,7 +35,7 @@ describe('ID_PREFIXES', () => {
35
35
  // Try to mutate
36
36
  try {
37
37
  ID_PREFIXES.USER = 'hacked'
38
- } catch (_) {
38
+ } catch {
39
39
  // Ignore error in strict mode
40
40
  }
41
41
 
@@ -7,6 +7,10 @@ const sleep = (ms) => new Promise((res) => setTimeout(res, ms))
7
7
  const testLog = {
8
8
  info: () => {},
9
9
  error: console.error,
10
+ debug: console.debug,
11
+ child() {
12
+ return testLog
13
+ },
10
14
  }
11
15
 
12
16
  describe('RabbitMQ SDK', () => {
@@ -1,4 +1,3 @@
1
- import dot from 'dot'
2
1
  import * as fs from 'fs/promises'
3
2
  import { describe, it, expect, vi, beforeEach } from 'vitest'
4
3
 
@@ -7,9 +6,6 @@ import { loadTemplates } from '../../src/templates/template-loader.js'
7
6
  vi.mock('fs/promises')
8
7
 
9
8
  describe('loadTemplates', () => {
10
- // @ts-ignore
11
- const mockCompile = vi.spyOn(dot, 'compile')
12
-
13
9
  beforeEach(() => {
14
10
  vi.resetAllMocks()
15
11
  })