diff --git a/packages/card-service/package.json b/packages/card-service/package.json index 4a57e1b30d..106257c74b 100644 --- a/packages/card-service/package.json +++ b/packages/card-service/package.json @@ -17,6 +17,7 @@ "dependencies": { "@adonisjs/fold": "^8.2.0", "@koa/cors": "^5.0.0", + "ioredis": "^5.3.2", "@koa/router": "^12.0.2", "koa-bodyparser": "^4.4.1", "koa": "^2.15.4", diff --git a/packages/card-service/src/config/app.ts b/packages/card-service/src/config/app.ts index 7f1abdf990..af831fad89 100644 --- a/packages/card-service/src/config/app.ts +++ b/packages/card-service/src/config/app.ts @@ -1,3 +1,6 @@ +import { ConnectionOptions } from 'tls' +import * as fs from 'fs' + function envString(name: string, defaultValue?: string): string { const envValue = process.env[name] @@ -27,7 +30,37 @@ export const Config = { enableManualMigrations: envBool('ENABLE_MANUAL_MIGRATIONS', false), trustProxy: envBool('TRUST_PROXY', false), env: envString('NODE_ENV', 'development'), - cardServicePort: envInt('CARD_SERVICE_PORT', 3007) + cardServicePort: envInt('CARD_SERVICE_PORT', 3007), + redisUrl: envString('REDIS_URL', 'redis://127.0.0.1:6379'), + redisTls: parseRedisTlsConfig( + process.env.REDIS_TLS_CA_FILE_PATH, + process.env.REDIS_TLS_KEY_FILE_PATH, + process.env.REDIS_TLS_CERT_FILE_PATH + ) +} + +function parseRedisTlsConfig( + caFile?: string, + keyFile?: string, + certFile?: string +): ConnectionOptions | undefined { + const options: ConnectionOptions = {} + + // self-signed certs. + if (caFile) { + options.ca = fs.readFileSync(caFile) + options.rejectUnauthorized = false + } + + if (certFile) { + options.cert = fs.readFileSync(certFile) + } + + if (keyFile) { + options.key = fs.readFileSync(keyFile) + } + + return Object.keys(options).length > 0 ? options : undefined } export type IAppConfig = typeof Config diff --git a/packages/card-service/src/index.ts b/packages/card-service/src/index.ts index 9d5dba1c0b..f854c5b51c 100644 --- a/packages/card-service/src/index.ts +++ b/packages/card-service/src/index.ts @@ -4,18 +4,22 @@ import { Ioc, IocContract } from '@adonisjs/fold' import createLogger from 'pino' import { knex } from 'knex' import { Model } from 'objection' +import Redis from 'ioredis' +import { createPOSStore, PosStoreService } from './pos-store/service' export function initIocContainer( config: typeof Config ): IocContract { const container: IocContract = new Ioc() container.singleton('config', async () => config) + container.singleton('logger', async (deps: IocContract) => { const config = await deps.use('config') const logger = createLogger() logger.level = config.logLevel return logger }) + container.singleton('knex', async (deps: IocContract) => { const logger = await deps.use('logger') const config = await deps.use('config') @@ -58,6 +62,20 @@ export function initIocContainer( return db }) + container.singleton('redis', async (deps): Promise => { + const config = await deps.use('config') + return new Redis(config.redisUrl, { + tls: config.redisTls, + stringNumbers: true + }) + }) + + container.singleton('pos-store', async (deps): Promise => { + const redis = await deps.use('redis') + const logger = await deps.use('logger') + return createPOSStore({ redis, logger }) + }) + return container } diff --git a/packages/card-service/src/pos-store/service.test.ts b/packages/card-service/src/pos-store/service.test.ts new file mode 100644 index 0000000000..7e8cc99f8c --- /dev/null +++ b/packages/card-service/src/pos-store/service.test.ts @@ -0,0 +1,97 @@ +import { createPOSStore } from './service' +import Redis from 'ioredis' +import { Logger } from 'pino' + +describe('POS Store Service', () => { + let redis: Redis + let logger: jest.Mocked + let service: ReturnType + + const requestId = 'req-123' + const POSHost = 'pos.example.com' + + beforeAll(async () => { + redis = new Redis(process.env.REDIS_URL!) + await redis.ping() + }) + + beforeEach(async () => { + await redis.flushall() + logger = { + child: jest.fn().mockReturnThis(), + info: jest.fn(), + error: jest.fn() + } as unknown as jest.Mocked + service = createPOSStore({ redis, logger }) + }) + + afterAll(async () => { + await redis.quit() + }) + + describe('addPOS', () => { + it('should add a POS for a requestId', async () => { + await service.addPOS(requestId, POSHost) + const value = await redis.get(requestId) + expect(value).toBe(POSHost) + expect(logger.info).toHaveBeenCalledWith( + { requestId, POSHost }, + 'POS was added for the given requestId' + ) + }) + + it('should clear the POS after 5 minutes (TTL)', async () => { + jest.useFakeTimers() + await service.addPOS(requestId, POSHost) + expect(await redis.get(requestId)).toBe(POSHost) + + await expect(service.getPOS(requestId)).resolves.toBe(POSHost) + + jest.advanceTimersByTime(300 * 1000) + // Simulate TTL expiry by manually deleting the key (since fake timers don't affect Redis TTL) + await redis.del(requestId) + await expect(service.getPOS(requestId)).rejects.toThrow( + `No POS found for requestId: ${requestId}` + ) + jest.useRealTimers() + }) + }) + + describe('getPOS', () => { + it('should return the POSHost for a requestId', async () => { + await redis.set(requestId, POSHost, 'EX', 300) + await expect(service.getPOS(requestId)).resolves.toBe(POSHost) + }) + it('should throw if no POS found', async () => { + await redis.del(requestId) + await expect(service.getPOS(requestId)).rejects.toThrow( + `No POS found for requestId: ${requestId}` + ) + expect(logger.error).toHaveBeenCalledWith( + { requestId: 'req-123' }, + 'No POS found for requestId' + ) + }) + }) + + describe('deletePOS', () => { + it('should delete the POS record for a requestId', async () => { + await redis.set(requestId, POSHost, 'EX', 300) + await service.deletePOS(requestId) + const value = await redis.get(requestId) + expect(value).toBe(null) + expect(logger.info).toHaveBeenCalledWith( + `POS record was deleted for requestId: ${requestId}` + ) + }) + it('should throw if no POS record was deleted', async () => { + await redis.del(requestId) + await expect(service.deletePOS(requestId)).rejects.toThrow( + `No POS record was deleted for requestId: ${requestId}` + ) + expect(logger.error).toHaveBeenCalledWith( + `No POS record was deleted for requestId: ${requestId}` + ) + }) + }) +}) diff --git a/packages/card-service/src/pos-store/service.ts b/packages/card-service/src/pos-store/service.ts new file mode 100644 index 0000000000..2d39d162cf --- /dev/null +++ b/packages/card-service/src/pos-store/service.ts @@ -0,0 +1,67 @@ +import Redis from 'ioredis' +import { Logger } from 'pino' + +const POS_TTL = 300 // 5 minutes + +export type StoreDependencies = { + logger: Logger + redis: Redis +} + +export type PosStoreService = { + addPOS: (requestId: string, POSHost: string) => Promise + getPOS: (requestId: string) => Promise + deletePOS: (requestId: string) => Promise +} + +export function createPOSStore(deps_: StoreDependencies): PosStoreService { + const logger = deps_.logger.child({ + service: 'pos-store' + }) + const deps = { + ...deps_, + logger + } + + return { + getPOS: (requestId: string) => getPOS(deps, requestId), + addPOS: (requestId: string, POSHost: string) => + addPOS(deps, requestId, POSHost), + deletePOS: (requestId: string) => deletePOS(deps, requestId) + } +} + +const getPOS = async ( + deps: StoreDependencies, + requestId: string +): Promise => { + const POSHost = await deps.redis.get(requestId) + if (!POSHost) { + deps.logger.error({ requestId }, `No POS found for requestId`) + throw new Error(`No POS found for requestId: ${requestId}`) + } + + return POSHost +} + +const addPOS = async ( + deps: StoreDependencies, + requestId: string, + POSHost: string +) => { + await deps.redis.set(requestId, POSHost, 'EX', POS_TTL) + deps.logger.info( + { requestId, POSHost }, + 'POS was added for the given requestId' + ) +} + +const deletePOS = async (deps: StoreDependencies, requestId: string) => { + const deletedRecords = await deps.redis.del([requestId]) + if (deletedRecords == 0) { + deps.logger.error(`No POS record was deleted for requestId: ${requestId}`) + throw new Error(`No POS record was deleted for requestId: ${requestId}`) + } + + deps.logger.info(`POS record was deleted for requestId: ${requestId}`) +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6ae15240d0..895092ceb8 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -556,6 +556,9 @@ importers: '@koa/cors': specifier: ^5.0.0 version: 5.0.0 + ioredis: + specifier: ^5.3.2 + version: 5.3.2 '@koa/router': specifier: ^12.0.2 version: 12.0.2 @@ -1432,7 +1435,7 @@ packages: engines: {node: ^18.17.1 || ^20.3.0 || >=22.0.0} dependencies: ci-info: 4.2.0 - debug: 4.4.1 + debug: 4.4.1(supports-color@9.4.0) dlv: 1.1.3 dset: 3.1.4 is-docker: 3.0.0 @@ -1488,7 +1491,7 @@ packages: '@babel/traverse': 7.25.9 '@babel/types': 7.26.0 convert-source-map: 2.0.0 - debug: 4.4.1 + debug: 4.4.1(supports-color@9.4.0) gensync: 1.0.0-beta.2 json5: 2.2.3 semver: 6.3.1 @@ -1510,7 +1513,7 @@ packages: '@babel/traverse': 7.26.7 '@babel/types': 7.27.0 convert-source-map: 2.0.0 - debug: 4.4.1 + debug: 4.4.1(supports-color@9.4.0) gensync: 1.0.0-beta.2 json5: 2.2.3 semver: 6.3.1 @@ -1533,7 +1536,7 @@ packages: '@babel/traverse': 7.26.9 '@babel/types': 7.26.9 convert-source-map: 2.0.0 - debug: 4.4.0(supports-color@9.4.0) + debug: 4.4.0 gensync: 1.0.0-beta.2 json5: 2.2.3 semver: 6.3.1 @@ -1556,7 +1559,7 @@ packages: '@babel/traverse': 7.27.4 '@babel/types': 7.27.3 convert-source-map: 2.0.0 - debug: 4.4.1 + debug: 4.4.1(supports-color@9.4.0) gensync: 1.0.0-beta.2 json5: 2.2.3 semver: 6.3.1 @@ -1715,7 +1718,7 @@ packages: '@babel/core': 7.26.9 '@babel/helper-compilation-targets': 7.26.5 '@babel/helper-plugin-utils': 7.26.5 - debug: 4.4.1 + debug: 4.4.1(supports-color@9.4.0) lodash.debounce: 4.0.8 resolve: 1.22.8 transitivePeerDependencies: @@ -3167,7 +3170,7 @@ packages: '@babel/parser': 7.26.7 '@babel/template': 7.25.9 '@babel/types': 7.26.7 - debug: 4.4.1 + debug: 4.4.1(supports-color@9.4.0) globals: 11.12.0 transitivePeerDependencies: - supports-color @@ -3181,7 +3184,7 @@ packages: '@babel/parser': 7.27.0 '@babel/template': 7.25.9 '@babel/types': 7.27.0 - debug: 4.4.1 + debug: 4.4.1(supports-color@9.4.0) globals: 11.12.0 transitivePeerDependencies: - supports-color @@ -3195,7 +3198,7 @@ packages: '@babel/parser': 7.26.9 '@babel/template': 7.26.9 '@babel/types': 7.26.9 - debug: 4.4.1 + debug: 4.4.1(supports-color@9.4.0) globals: 11.12.0 transitivePeerDependencies: - supports-color @@ -3210,7 +3213,7 @@ packages: '@babel/parser': 7.27.5 '@babel/template': 7.27.2 '@babel/types': 7.27.3 - debug: 4.4.1 + debug: 4.4.1(supports-color@9.4.0) globals: 11.12.0 transitivePeerDependencies: - supports-color @@ -4082,7 +4085,7 @@ packages: engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dependencies: ajv: 6.12.6 - debug: 4.4.1 + debug: 4.4.1(supports-color@9.4.0) espree: 9.6.1 globals: 13.19.0 ignore: 5.2.4 @@ -4965,7 +4968,7 @@ packages: '@types/json-stable-stringify': 1.0.34 '@whatwg-node/fetch': 0.9.8 chalk: 4.1.2 - debug: 4.4.0(supports-color@9.4.0) + debug: 4.4.1(supports-color@9.4.0) dotenv: 16.4.7 graphql: 16.11.0 graphql-request: 6.1.0(graphql@16.11.0) @@ -5236,7 +5239,7 @@ packages: deprecated: Use @eslint/config-array instead dependencies: '@humanwhocodes/object-schema': 2.0.3 - debug: 4.4.1 + debug: 4.4.1(supports-color@9.4.0) minimatch: 3.1.2 transitivePeerDependencies: - supports-color @@ -5268,7 +5271,7 @@ packages: '@antfu/install-pkg': 0.4.1 '@antfu/utils': 0.7.10 '@iconify/types': 2.0.0 - debug: 4.4.1 + debug: 4.4.1(supports-color@9.4.0) kolorist: 1.8.0 local-pkg: 0.5.0 mlly: 1.7.3 @@ -6100,7 +6103,7 @@ packages: resolution: {integrity: sha512-sYcHglGKTxGF+hQ6x67xDfkE9o+NhVlRHBqq6gLywaMc6CojK/5vFZByphdonKinYlMLkEkacm+HEse9HzwgTA==} engines: {node: '>= 12'} dependencies: - debug: 4.4.1 + debug: 4.4.1(supports-color@9.4.0) http-errors: 2.0.0 koa-compose: 4.1.0 methods: 1.1.2 @@ -8613,7 +8616,7 @@ packages: '@typescript-eslint/scope-manager': 5.60.1 '@typescript-eslint/type-utils': 5.60.1(eslint@8.57.1)(typescript@5.8.3) '@typescript-eslint/utils': 5.60.1(eslint@8.57.1)(typescript@5.8.3) - debug: 4.4.1 + debug: 4.4.1(supports-color@9.4.0) eslint: 8.57.1 grapheme-splitter: 1.0.4 ignore: 5.2.4 @@ -8667,7 +8670,7 @@ packages: '@typescript-eslint/scope-manager': 5.60.1 '@typescript-eslint/types': 5.60.1 '@typescript-eslint/typescript-estree': 5.60.1(typescript@5.8.3) - debug: 4.4.1 + debug: 4.4.1(supports-color@9.4.0) eslint: 8.57.1 typescript: 5.8.3 transitivePeerDependencies: @@ -8731,7 +8734,7 @@ packages: dependencies: '@typescript-eslint/typescript-estree': 5.60.1(typescript@5.8.3) '@typescript-eslint/utils': 5.60.1(eslint@8.57.1)(typescript@5.8.3) - debug: 4.4.1 + debug: 4.4.1(supports-color@9.4.0) eslint: 8.57.1 tsutils: 3.21.0(typescript@5.8.3) typescript: 5.8.3 @@ -8751,7 +8754,7 @@ packages: dependencies: '@typescript-eslint/typescript-estree': 7.5.0(typescript@5.4.3) '@typescript-eslint/utils': 7.5.0(eslint@8.57.1)(typescript@5.4.3) - debug: 4.4.1 + debug: 4.4.1(supports-color@9.4.0) eslint: 8.57.1 ts-api-utils: 1.0.1(typescript@5.4.3) typescript: 5.4.3 @@ -8785,7 +8788,7 @@ packages: dependencies: '@typescript-eslint/types': 5.60.1 '@typescript-eslint/visitor-keys': 5.60.1 - debug: 4.4.1 + debug: 4.4.1(supports-color@9.4.0) globby: 11.1.0 is-glob: 4.0.3 semver: 7.6.3 @@ -8806,7 +8809,7 @@ packages: dependencies: '@typescript-eslint/types': 5.62.0 '@typescript-eslint/visitor-keys': 5.62.0 - debug: 4.4.1 + debug: 4.4.1(supports-color@9.4.0) globby: 11.1.0 is-glob: 4.0.3 semver: 7.6.3 @@ -8827,7 +8830,7 @@ packages: dependencies: '@typescript-eslint/types': 7.5.0 '@typescript-eslint/visitor-keys': 7.5.0 - debug: 4.4.1 + debug: 4.4.1(supports-color@9.4.0) globby: 11.1.0 is-glob: 4.0.3 minimatch: 9.0.3 @@ -9301,7 +9304,7 @@ packages: resolution: {integrity: sha512-o/zjMZRhJxny7OyEF+Op8X+efiELC7k7yOjMzgfzVqOzXqkBkWI79YoTdOtsuWd5BWhAGAuOY/Xa6xpiaWXiNg==} engines: {node: '>= 14'} dependencies: - debug: 4.4.1 + debug: 4.4.1(supports-color@9.4.0) transitivePeerDependencies: - supports-color dev: true @@ -9711,7 +9714,7 @@ packages: common-ancestor-path: 1.0.1 cookie: 1.0.2 cssesc: 3.0.0 - debug: 4.4.1 + debug: 4.4.1(supports-color@9.4.0) deterministic-object-hash: 2.0.2 devalue: 5.1.1 diff: 5.2.0 @@ -9814,7 +9817,7 @@ packages: common-ancestor-path: 1.0.1 cookie: 1.0.2 cssesc: 3.0.0 - debug: 4.4.1 + debug: 4.4.1(supports-color@9.4.0) deterministic-object-hash: 2.0.2 devalue: 5.1.1 diff: 5.2.0 @@ -11545,7 +11548,7 @@ packages: ms: 2.1.3 dev: true - /debug@4.4.0(supports-color@7.2.0): + /debug@4.4.0: resolution: {integrity: sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==} engines: {node: '>=6.0'} peerDependencies: @@ -11555,10 +11558,10 @@ packages: optional: true dependencies: ms: 2.1.3 - supports-color: 7.2.0 + dev: true - /debug@4.4.0(supports-color@9.4.0): - resolution: {integrity: sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==} + /debug@4.4.1(supports-color@7.2.0): + resolution: {integrity: sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==} engines: {node: '>=6.0'} peerDependencies: supports-color: '*' @@ -11567,9 +11570,9 @@ packages: optional: true dependencies: ms: 2.1.3 - supports-color: 9.4.0 + supports-color: 7.2.0 - /debug@4.4.1: + /debug@4.4.1(supports-color@9.4.0): resolution: {integrity: sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==} engines: {node: '>=6.0'} peerDependencies: @@ -11579,6 +11582,7 @@ packages: optional: true dependencies: ms: 2.1.3 + supports-color: 9.4.0 /decamelize@1.2.0: resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==} @@ -11775,7 +11779,7 @@ packages: resolution: {integrity: sha512-h0Ow21gclbYsZ3mkHDfsYNDqtRhXS8fXr51bU0qr1dxgTMJj0XufbzX+jhNOvA8KuEEzn6JbvLVhXyv+fny9Uw==} engines: {node: '>= 8.0'} dependencies: - debug: 4.4.1 + debug: 4.4.1(supports-color@9.4.0) readable-stream: 3.6.0 split-ca: 1.0.1 ssh2: 1.11.0 @@ -12367,7 +12371,7 @@ packages: eslint: '*' eslint-plugin-import: '*' dependencies: - debug: 4.4.1 + debug: 4.4.1(supports-color@9.4.0) enhanced-resolve: 5.13.0 eslint: 8.57.1 eslint-module-utils: 2.7.4(@typescript-eslint/parser@5.60.1)(eslint-import-resolver-node@0.3.7)(eslint-import-resolver-typescript@3.5.5)(eslint@8.57.1) @@ -14094,7 +14098,7 @@ packages: engines: {node: '>= 14'} dependencies: agent-base: 7.1.0 - debug: 4.4.1 + debug: 4.4.1(supports-color@9.4.0) transitivePeerDependencies: - supports-color dev: true @@ -14109,7 +14113,7 @@ packages: engines: {node: '>= 14'} dependencies: agent-base: 7.1.0 - debug: 4.4.1 + debug: 4.4.1(supports-color@9.4.0) transitivePeerDependencies: - supports-color dev: true @@ -14158,14 +14162,14 @@ packages: resolution: {integrity: sha512-R7F+SH6Aiipuqoq63gtzy6/HVIfcCK1rEmq8bE8NLSufXJPRoXszNs6RpypQi9HJcZvTcIUPFE15bS/HI+T+/A==} dependencies: '@types/debug': 4.1.7 - debug: 4.4.0(supports-color@7.2.0) + debug: 4.4.1(supports-color@7.2.0) supports-color: 7.2.0 /ilp-logger@1.4.5-alpha.2: resolution: {integrity: sha512-WtbscdjUUPVseRkDpRlfb/YUpsq4zfoOz6PlJSkx+aqJot1P5N+YGd4YKW1g9wm6O8muo5e/xBotyJqCQs0g+Q==} dependencies: '@types/debug': 4.1.7 - debug: 4.4.0(supports-color@9.4.0) + debug: 4.4.1(supports-color@9.4.0) supports-color: 9.4.0 dev: false @@ -14352,7 +14356,7 @@ packages: dependencies: '@ioredis/commands': 1.2.0 cluster-key-slot: 1.1.0 - debug: 4.3.4 + debug: 4.4.1(supports-color@9.4.0) denque: 2.1.0 lodash.defaults: 4.2.0 lodash.isarguments: 3.1.0 @@ -14897,7 +14901,7 @@ packages: resolution: {integrity: sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==} engines: {node: '>=10'} dependencies: - debug: 4.4.1 + debug: 4.4.1(supports-color@9.4.0) istanbul-lib-coverage: 3.2.0 source-map: 0.6.1 transitivePeerDependencies: @@ -15636,7 +15640,7 @@ packages: content-disposition: 0.5.4 content-type: 1.0.5 cookies: 0.9.1 - debug: 4.4.0(supports-color@9.4.0) + debug: 4.4.0 delegates: 1.0.0 depd: 2.0.0 destroy: 1.2.0 @@ -15667,7 +15671,7 @@ packages: content-disposition: 0.5.4 content-type: 1.0.5 cookies: 0.9.1 - debug: 4.4.1 + debug: 4.4.1(supports-color@9.4.0) delegates: 1.0.0 depd: 2.0.0 destroy: 1.2.0 @@ -15697,7 +15701,7 @@ packages: content-disposition: 0.5.4 content-type: 1.0.5 cookies: 0.9.1 - debug: 4.4.1 + debug: 4.4.1(supports-color@9.4.0) delegates: 1.0.0 destroy: 1.2.0 encodeurl: 2.0.0 @@ -17089,7 +17093,7 @@ packages: resolution: {integrity: sha512-uD66tJj54JLYq0De10AhWycZWGQNUvDI55xPgk2sQM5kn1JYlhbCMTtEeT27+vAhW2FBQxLlOmS3pmA7/2z4aA==} dependencies: '@types/debug': 4.1.12 - debug: 4.4.1 + debug: 4.4.1(supports-color@9.4.0) decode-named-character-reference: 1.0.2 micromark-core-commonmark: 1.1.0 micromark-factory-space: 1.1.0 @@ -17113,7 +17117,7 @@ packages: resolution: {integrity: sha512-o/sd0nMof8kYff+TqcDx3VSrgBTcZpSvYcAHIfHhv5VAuNmisCxjhx6YmxS8PFEpb9z5WKWKPdzf0jM23ro3RQ==} dependencies: '@types/debug': 4.1.12 - debug: 4.4.1 + debug: 4.4.1(supports-color@9.4.0) decode-named-character-reference: 1.0.2 devlop: 1.1.0 micromark-core-commonmark: 2.0.1 @@ -19404,7 +19408,7 @@ packages: resolution: {integrity: sha512-X34iHADNbNDfr6OTStIAHWSAvvKQRYgLO6duASaVf7J2VA3lvmNYboAHOuLC2huav1IwgZJtyEcJCKVzFxOSMQ==} engines: {node: '>=8.6.0'} dependencies: - debug: 4.4.0(supports-color@9.4.0) + debug: 4.4.1(supports-color@9.4.0) module-details-from-path: 1.0.3 resolve: 1.22.8 transitivePeerDependencies: @@ -21858,7 +21862,7 @@ packages: hasBin: true dependencies: cac: 6.7.14 - debug: 4.4.1 + debug: 4.4.1(supports-color@9.4.0) mlly: 1.7.3 pathe: 1.1.2 picocolors: 1.1.1 @@ -21882,7 +21886,7 @@ packages: hasBin: true dependencies: cac: 6.7.14 - debug: 4.4.1 + debug: 4.4.1(supports-color@9.4.0) mlly: 1.7.3 pathe: 1.1.2 picocolors: 1.1.1 @@ -21906,7 +21910,7 @@ packages: hasBin: true dependencies: cac: 6.7.14 - debug: 4.4.1 + debug: 4.4.1(supports-color@9.4.0) es-module-lexer: 1.6.0 pathe: 1.1.2 vite: 6.2.5(@types/node@18.11.9)(yaml@2.7.0) @@ -21931,7 +21935,7 @@ packages: hasBin: true dependencies: cac: 6.7.14 - debug: 4.4.1 + debug: 4.4.1(supports-color@9.4.0) es-module-lexer: 1.6.0 pathe: 1.1.2 vite: 6.2.5(@types/node@20.12.7)(yaml@2.7.0)