feat: add api liveness and readiness checks
This commit is contained in:
@@ -2,9 +2,10 @@ import { Module } from '@nestjs/common';
|
|||||||
import { ConfigurationModule } from '../../../libs/configuration/src';
|
import { ConfigurationModule } from '../../../libs/configuration/src';
|
||||||
import { AppController } from './app.controller';
|
import { AppController } from './app.controller';
|
||||||
import { AppService } from './app.service';
|
import { AppService } from './app.service';
|
||||||
|
import { HealthModule } from './health/health.module';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [ConfigurationModule],
|
imports: [ConfigurationModule, HealthModule],
|
||||||
controllers: [AppController],
|
controllers: [AppController],
|
||||||
providers: [AppService],
|
providers: [AppService],
|
||||||
})
|
})
|
||||||
|
|||||||
29
backend/apps/api/src/health/health.controller.spec.ts
Normal file
29
backend/apps/api/src/health/health.controller.spec.ts
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
import { Test } from '@nestjs/testing';
|
||||||
|
import { HealthController } from './health.controller';
|
||||||
|
import { ReadinessService } from './readiness.service';
|
||||||
|
|
||||||
|
describe('HealthController', () => {
|
||||||
|
it('returns liveness without dependency checks', async () => {
|
||||||
|
const readiness = { check: jest.fn() };
|
||||||
|
const moduleRef = await Test.createTestingModule({
|
||||||
|
controllers: [HealthController],
|
||||||
|
providers: [{ provide: ReadinessService, useValue: readiness }],
|
||||||
|
}).compile();
|
||||||
|
|
||||||
|
expect(moduleRef.get(HealthController).live()).toEqual({ status: 'ok' });
|
||||||
|
expect(readiness.check).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('delegates readiness to dependency checks', async () => {
|
||||||
|
const readiness = { check: jest.fn().mockResolvedValue({ status: 'ok' }) };
|
||||||
|
const moduleRef = await Test.createTestingModule({
|
||||||
|
controllers: [HealthController],
|
||||||
|
providers: [{ provide: ReadinessService, useValue: readiness }],
|
||||||
|
}).compile();
|
||||||
|
|
||||||
|
await expect(moduleRef.get(HealthController).ready()).resolves.toEqual({
|
||||||
|
status: 'ok',
|
||||||
|
});
|
||||||
|
expect(readiness.check).toHaveBeenCalledTimes(1);
|
||||||
|
});
|
||||||
|
});
|
||||||
17
backend/apps/api/src/health/health.controller.ts
Normal file
17
backend/apps/api/src/health/health.controller.ts
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
import { Controller, Get } from '@nestjs/common';
|
||||||
|
import { ReadinessService } from './readiness.service';
|
||||||
|
|
||||||
|
@Controller()
|
||||||
|
export class HealthController {
|
||||||
|
constructor(private readonly readiness: ReadinessService) {}
|
||||||
|
|
||||||
|
@Get('health/live')
|
||||||
|
live(): { status: 'ok' } {
|
||||||
|
return { status: 'ok' };
|
||||||
|
}
|
||||||
|
|
||||||
|
@Get('health/ready')
|
||||||
|
ready(): Promise<{ status: 'ok' }> {
|
||||||
|
return this.readiness.check();
|
||||||
|
}
|
||||||
|
}
|
||||||
14
backend/apps/api/src/health/health.module.ts
Normal file
14
backend/apps/api/src/health/health.module.ts
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
import { Module } from '@nestjs/common';
|
||||||
|
import {
|
||||||
|
PostgresModule,
|
||||||
|
RedisModule,
|
||||||
|
} from '../../../../libs/infrastructure/src';
|
||||||
|
import { HealthController } from './health.controller';
|
||||||
|
import { ReadinessService } from './readiness.service';
|
||||||
|
|
||||||
|
@Module({
|
||||||
|
imports: [PostgresModule, RedisModule],
|
||||||
|
controllers: [HealthController],
|
||||||
|
providers: [ReadinessService],
|
||||||
|
})
|
||||||
|
export class HealthModule {}
|
||||||
22
backend/apps/api/src/health/readiness.service.ts
Normal file
22
backend/apps/api/src/health/readiness.service.ts
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
import { Inject, Injectable } from '@nestjs/common';
|
||||||
|
import type { Pool } from 'pg';
|
||||||
|
import type Redis from 'ioredis';
|
||||||
|
import {
|
||||||
|
POSTGRES_POOL,
|
||||||
|
REDIS_CLIENT,
|
||||||
|
} from '../../../../libs/infrastructure/src';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class ReadinessService {
|
||||||
|
constructor(
|
||||||
|
@Inject(POSTGRES_POOL) private readonly postgresPool: Pool,
|
||||||
|
@Inject(REDIS_CLIENT) private readonly redis: Redis,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
async check(): Promise<{ status: 'ok' }> {
|
||||||
|
await this.postgresPool.query('SELECT 1');
|
||||||
|
const pong = await this.redis.ping();
|
||||||
|
if (pong !== 'PONG') throw new Error('Redis ping failed');
|
||||||
|
return { status: 'ok' as const };
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,10 +1,16 @@
|
|||||||
|
import { RequestMethod } from '@nestjs/common';
|
||||||
import { NestFactory } from '@nestjs/core';
|
import { NestFactory } from '@nestjs/core';
|
||||||
import { ApiModule } from './api.module';
|
import { ApiModule } from './api.module';
|
||||||
|
|
||||||
export async function bootstrapApi(): Promise<void> {
|
export async function bootstrapApi(): Promise<void> {
|
||||||
const app = await NestFactory.create(ApiModule);
|
const app = await NestFactory.create(ApiModule);
|
||||||
app.enableShutdownHooks();
|
app.enableShutdownHooks();
|
||||||
app.setGlobalPrefix('api/v1');
|
app.setGlobalPrefix('api/v1', {
|
||||||
|
exclude: [
|
||||||
|
{ path: 'health/live', method: RequestMethod.GET },
|
||||||
|
{ path: 'health/ready', method: RequestMethod.GET },
|
||||||
|
],
|
||||||
|
});
|
||||||
await app.listen(3000, '0.0.0.0');
|
await app.listen(3000, '0.0.0.0');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
import { Module } from '@nestjs/common';
|
import { Module } from '@nestjs/common';
|
||||||
import { ConfigurationModule } from '../../../libs/configuration/src';
|
import { ConfigurationModule } from '../../../libs/configuration/src';
|
||||||
|
import { PostgresModule, RedisModule } from '../../../libs/infrastructure/src';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [ConfigurationModule],
|
imports: [ConfigurationModule, PostgresModule, RedisModule],
|
||||||
})
|
})
|
||||||
export class WorkerModule {}
|
export class WorkerModule {}
|
||||||
|
|||||||
2
backend/libs/infrastructure/src/index.ts
Normal file
2
backend/libs/infrastructure/src/index.ts
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
export * from './postgres/postgres.module';
|
||||||
|
export * from './redis/redis.module';
|
||||||
27
backend/libs/infrastructure/src/postgres/postgres.module.ts
Normal file
27
backend/libs/infrastructure/src/postgres/postgres.module.ts
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
import { Inject, Injectable, Module, OnModuleDestroy } from '@nestjs/common';
|
||||||
|
import { Pool } from 'pg';
|
||||||
|
import { APP_ENVIRONMENT, AppEnvironment } from '../../../configuration/src';
|
||||||
|
|
||||||
|
export const POSTGRES_POOL = Symbol('POSTGRES_POOL');
|
||||||
|
|
||||||
|
export const postgresPoolProvider = {
|
||||||
|
provide: POSTGRES_POOL,
|
||||||
|
inject: [APP_ENVIRONMENT],
|
||||||
|
useFactory: (env: AppEnvironment) =>
|
||||||
|
new Pool({ connectionString: env.databaseUrl }),
|
||||||
|
};
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
class PostgresLifecycle implements OnModuleDestroy {
|
||||||
|
constructor(@Inject(POSTGRES_POOL) private readonly pool: Pool) {}
|
||||||
|
|
||||||
|
async onModuleDestroy(): Promise<void> {
|
||||||
|
await this.pool.end();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Module({
|
||||||
|
providers: [postgresPoolProvider, PostgresLifecycle],
|
||||||
|
exports: [postgresPoolProvider],
|
||||||
|
})
|
||||||
|
export class PostgresModule {}
|
||||||
27
backend/libs/infrastructure/src/redis/redis.module.ts
Normal file
27
backend/libs/infrastructure/src/redis/redis.module.ts
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
import { Inject, Injectable, Module, OnModuleDestroy } from '@nestjs/common';
|
||||||
|
import Redis from 'ioredis';
|
||||||
|
import { APP_ENVIRONMENT, AppEnvironment } from '../../../configuration/src';
|
||||||
|
|
||||||
|
export const REDIS_CLIENT = Symbol('REDIS_CLIENT');
|
||||||
|
|
||||||
|
export const redisClientProvider = {
|
||||||
|
provide: REDIS_CLIENT,
|
||||||
|
inject: [APP_ENVIRONMENT],
|
||||||
|
useFactory: (env: AppEnvironment) =>
|
||||||
|
new Redis(env.redisUrl, { lazyConnect: false }),
|
||||||
|
};
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
class RedisLifecycle implements OnModuleDestroy {
|
||||||
|
constructor(@Inject(REDIS_CLIENT) private readonly client: Redis) {}
|
||||||
|
|
||||||
|
async onModuleDestroy(): Promise<void> {
|
||||||
|
await this.client.quit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Module({
|
||||||
|
providers: [redisClientProvider, RedisLifecycle],
|
||||||
|
exports: [redisClientProvider],
|
||||||
|
})
|
||||||
|
export class RedisModule {}
|
||||||
@@ -26,6 +26,8 @@
|
|||||||
"@nestjs/common": "^11.0.1",
|
"@nestjs/common": "^11.0.1",
|
||||||
"@nestjs/core": "^11.0.1",
|
"@nestjs/core": "^11.0.1",
|
||||||
"@nestjs/platform-express": "^11.0.1",
|
"@nestjs/platform-express": "^11.0.1",
|
||||||
|
"ioredis": "^6.0.0",
|
||||||
|
"pg": "^8.23.0",
|
||||||
"reflect-metadata": "^0.2.2",
|
"reflect-metadata": "^0.2.2",
|
||||||
"rxjs": "^7.8.1"
|
"rxjs": "^7.8.1"
|
||||||
},
|
},
|
||||||
@@ -38,6 +40,7 @@
|
|||||||
"@types/express": "^5.0.0",
|
"@types/express": "^5.0.0",
|
||||||
"@types/jest": "^30.0.0",
|
"@types/jest": "^30.0.0",
|
||||||
"@types/node": "^24.0.0",
|
"@types/node": "^24.0.0",
|
||||||
|
"@types/pg": "^8.21.0",
|
||||||
"@types/supertest": "^7.0.0",
|
"@types/supertest": "^7.0.0",
|
||||||
"eslint": "^9.18.0",
|
"eslint": "^9.18.0",
|
||||||
"eslint-config-prettier": "^10.0.1",
|
"eslint-config-prettier": "^10.0.1",
|
||||||
@@ -62,8 +65,13 @@
|
|||||||
],
|
],
|
||||||
"rootDir": ".",
|
"rootDir": ".",
|
||||||
"testRegex": ".*\\.spec\\.ts$",
|
"testRegex": ".*\\.spec\\.ts$",
|
||||||
"testPathIgnorePatterns": ["<rootDir>/node_modules/", "<rootDir>/dist/"],
|
"testPathIgnorePatterns": [
|
||||||
"setupFiles": ["<rootDir>/test/setup-env.ts"],
|
"<rootDir>/node_modules/",
|
||||||
|
"<rootDir>/dist/"
|
||||||
|
],
|
||||||
|
"setupFiles": [
|
||||||
|
"<rootDir>/test/setup-env.ts"
|
||||||
|
],
|
||||||
"transform": {
|
"transform": {
|
||||||
"^.+\\.(t|j)s$": "ts-jest"
|
"^.+\\.(t|j)s$": "ts-jest"
|
||||||
},
|
},
|
||||||
|
|||||||
168
pnpm-lock.yaml
generated
168
pnpm-lock.yaml
generated
@@ -19,6 +19,12 @@ importers:
|
|||||||
'@nestjs/platform-express':
|
'@nestjs/platform-express':
|
||||||
specifier: ^11.0.1
|
specifier: ^11.0.1
|
||||||
version: 11.2.1(@nestjs/common@11.2.1(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.2.1)
|
version: 11.2.1(@nestjs/common@11.2.1(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.2.1)
|
||||||
|
ioredis:
|
||||||
|
specifier: ^6.0.0
|
||||||
|
version: 6.0.0
|
||||||
|
pg:
|
||||||
|
specifier: ^8.23.0
|
||||||
|
version: 8.23.0
|
||||||
reflect-metadata:
|
reflect-metadata:
|
||||||
specifier: ^0.2.2
|
specifier: ^0.2.2
|
||||||
version: 0.2.2
|
version: 0.2.2
|
||||||
@@ -50,6 +56,9 @@ importers:
|
|||||||
'@types/node':
|
'@types/node':
|
||||||
specifier: ^24.0.0
|
specifier: ^24.0.0
|
||||||
version: 24.13.3
|
version: 24.13.3
|
||||||
|
'@types/pg':
|
||||||
|
specifier: ^8.21.0
|
||||||
|
version: 8.21.0
|
||||||
'@types/supertest':
|
'@types/supertest':
|
||||||
specifier: ^7.0.0
|
specifier: ^7.0.0
|
||||||
version: 7.2.1
|
version: 7.2.1
|
||||||
@@ -1011,6 +1020,9 @@ packages:
|
|||||||
'@types/node':
|
'@types/node':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
'@ioredis/commands@2.0.0':
|
||||||
|
resolution: {integrity: sha512-vrx0AE/T0h7cRZwfo1M39Cr+ZhZrkf0V8mQN75wucKCxCLD9l/VX6no3gFvrLqD1IlG/1LtzWovqEw3t0Vr9zg==}
|
||||||
|
|
||||||
'@isaacs/cliui@8.0.2':
|
'@isaacs/cliui@8.0.2':
|
||||||
resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==}
|
resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==}
|
||||||
engines: {node: '>=12'}
|
engines: {node: '>=12'}
|
||||||
@@ -1880,6 +1892,9 @@ packages:
|
|||||||
'@types/node@24.13.3':
|
'@types/node@24.13.3':
|
||||||
resolution: {integrity: sha512-Dh8vAsV36ig5wa9OX4pXvMc9D3Veibfw2wix0CUwYODLD8nkj9UsLjASr49nPg+2eKzxhBV+v7L8pXvT4e639Q==}
|
resolution: {integrity: sha512-Dh8vAsV36ig5wa9OX4pXvMc9D3Veibfw2wix0CUwYODLD8nkj9UsLjASr49nPg+2eKzxhBV+v7L8pXvT4e639Q==}
|
||||||
|
|
||||||
|
'@types/pg@8.21.0':
|
||||||
|
resolution: {integrity: sha512-AYdtudzabjLZgVgRZmAnU8bAnVUXzuJX2IYHeSIiIHm68olD+LgQYCGWdtcNYnP0uq9c4S4NibVG3Ni7VbKW7Q==}
|
||||||
|
|
||||||
'@types/qs@6.15.1':
|
'@types/qs@6.15.1':
|
||||||
resolution: {integrity: sha512-GZHUBZR9hckSUhrxmp1nG6NwdpM9fCunJwyThLW1X3AyHgd9IlHb6VANpQQqDr2o/qQp6McZ3y/IA2rVzKzSbw==}
|
resolution: {integrity: sha512-GZHUBZR9hckSUhrxmp1nG6NwdpM9fCunJwyThLW1X3AyHgd9IlHb6VANpQQqDr2o/qQp6McZ3y/IA2rVzKzSbw==}
|
||||||
|
|
||||||
@@ -2506,6 +2521,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==}
|
resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==}
|
||||||
engines: {node: '>=0.8'}
|
engines: {node: '>=0.8'}
|
||||||
|
|
||||||
|
cluster-key-slot@1.1.1:
|
||||||
|
resolution: {integrity: sha512-rwHwUfXL40Chm1r08yrhU3qpUvdVlgkKNeyeGPOxnW8/SyVDvgRaed/Uz54AqWNaTCAThlj6QAs3TZcKI0xDEw==}
|
||||||
|
engines: {node: '>=0.10.0'}
|
||||||
|
|
||||||
co@4.6.0:
|
co@4.6.0:
|
||||||
resolution: {integrity: sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==}
|
resolution: {integrity: sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==}
|
||||||
engines: {iojs: '>= 1.0.0', node: '>= 0.12.0'}
|
engines: {iojs: '>= 1.0.0', node: '>= 0.12.0'}
|
||||||
@@ -2650,6 +2669,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==}
|
resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==}
|
||||||
engines: {node: '>=0.4.0'}
|
engines: {node: '>=0.4.0'}
|
||||||
|
|
||||||
|
denque@2.1.0:
|
||||||
|
resolution: {integrity: sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==}
|
||||||
|
engines: {node: '>=0.10'}
|
||||||
|
|
||||||
depd@2.0.0:
|
depd@2.0.0:
|
||||||
resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==}
|
resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==}
|
||||||
engines: {node: '>= 0.8'}
|
engines: {node: '>= 0.8'}
|
||||||
@@ -3185,6 +3208,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-IBTdIkzZNOpqm7q3dRqJvMaldXjDHWkEDfrwGEQTs5eaQMWV+djAhR+wahyNNMAa+qpbDUhBMVt4ZKNwpPm7xQ==}
|
resolution: {integrity: sha512-IBTdIkzZNOpqm7q3dRqJvMaldXjDHWkEDfrwGEQTs5eaQMWV+djAhR+wahyNNMAa+qpbDUhBMVt4ZKNwpPm7xQ==}
|
||||||
engines: {node: ^20.17.0 || >=22.9.0}
|
engines: {node: ^20.17.0 || >=22.9.0}
|
||||||
|
|
||||||
|
ioredis@6.0.0:
|
||||||
|
resolution: {integrity: sha512-f+Dtubxfpf6KYFq7WVXJoOLn0bk4TJrMrN9SzeE+jrWrCWj7XX3fA6vkryafhADX+GMymRxgDJDOI33COkJc0w==}
|
||||||
|
engines: {node: '>=20.0.0'}
|
||||||
|
|
||||||
ip-address@10.5.0:
|
ip-address@10.5.0:
|
||||||
resolution: {integrity: sha512-R5SnVLJmgYYvf2F2ZgwSBnelz5G4q5AxIC277GDfUaNbrZKNANcBC7RHqYYePlszf4kBolVkJauG0ZjHHFh55g==}
|
resolution: {integrity: sha512-R5SnVLJmgYYvf2F2ZgwSBnelz5G4q5AxIC277GDfUaNbrZKNANcBC7RHqYYePlszf4kBolVkJauG0ZjHHFh55g==}
|
||||||
engines: {node: '>= 12'}
|
engines: {node: '>= 12'}
|
||||||
@@ -3906,6 +3933,40 @@ packages:
|
|||||||
pathe@2.0.3:
|
pathe@2.0.3:
|
||||||
resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==}
|
resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==}
|
||||||
|
|
||||||
|
pg-cloudflare@1.4.0:
|
||||||
|
resolution: {integrity: sha512-Vo7z/6rrQYxpNRylp4Tlob2elzbh+N/MOQbxFVWCxS7oEx6jF53GTJFxK2WWpKuBRkmiin4Mt+xofFDjx09R0A==}
|
||||||
|
|
||||||
|
pg-connection-string@2.14.0:
|
||||||
|
resolution: {integrity: sha512-XwWDGcLRGCXAR8F/AM5bG7Q+A3Wm2s6QeEjlOKZLlH3UYcguiqCWKyWXVag5TLTIjR7oOJUY8kcADaZgWPyLeg==}
|
||||||
|
|
||||||
|
pg-int8@1.0.1:
|
||||||
|
resolution: {integrity: sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==}
|
||||||
|
engines: {node: '>=4.0.0'}
|
||||||
|
|
||||||
|
pg-pool@3.14.0:
|
||||||
|
resolution: {integrity: sha512-gKtPkFdQPU3DksooVLi9LsjZxrsBUZIpa+7aVx+LV5pNh0KzP4Zleud2po+ConrxbuXGBJ6Hfer6hdgpIBpBaw==}
|
||||||
|
peerDependencies:
|
||||||
|
pg: '>=8.0'
|
||||||
|
|
||||||
|
pg-protocol@1.16.0:
|
||||||
|
resolution: {integrity: sha512-sILXutLVjCLjcDuOmvhX5e2Z4cS5qG/6Bu3VkpFwdf/633ElGLpEh9bgmuI5I4sqKqkifQiGyiCcx1HdtrK7tg==}
|
||||||
|
|
||||||
|
pg-types@2.2.0:
|
||||||
|
resolution: {integrity: sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==}
|
||||||
|
engines: {node: '>=4'}
|
||||||
|
|
||||||
|
pg@8.23.0:
|
||||||
|
resolution: {integrity: sha512-Ip2EQCngowJLGOfCwkFhPXU7/ljlhn6Rxlmy4XYfL2Y+vyRM59+8uR2xqRWKdYmbXmxCFOAmKxBuSUCdF34qLg==}
|
||||||
|
engines: {node: '>= 16.0.0'}
|
||||||
|
peerDependencies:
|
||||||
|
pg-native: '>=3.0.1'
|
||||||
|
peerDependenciesMeta:
|
||||||
|
pg-native:
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
pgpass@1.0.5:
|
||||||
|
resolution: {integrity: sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==}
|
||||||
|
|
||||||
picocolors@1.1.1:
|
picocolors@1.1.1:
|
||||||
resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==}
|
resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==}
|
||||||
|
|
||||||
@@ -3954,6 +4015,22 @@ packages:
|
|||||||
resolution: {integrity: sha512-u82N74LFzG8ca+dD8puPnplTXoGH4fTPpVGuIbt36G3qvNlkvfD0lEAZSxaly3KX8TS/L1A1gsCEmvKmBcVbkQ==}
|
resolution: {integrity: sha512-u82N74LFzG8ca+dD8puPnplTXoGH4fTPpVGuIbt36G3qvNlkvfD0lEAZSxaly3KX8TS/L1A1gsCEmvKmBcVbkQ==}
|
||||||
engines: {node: ^10 || ^12 || >=14}
|
engines: {node: ^10 || ^12 || >=14}
|
||||||
|
|
||||||
|
postgres-array@2.0.0:
|
||||||
|
resolution: {integrity: sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==}
|
||||||
|
engines: {node: '>=4'}
|
||||||
|
|
||||||
|
postgres-bytea@1.0.1:
|
||||||
|
resolution: {integrity: sha512-5+5HqXnsZPE65IJZSMkZtURARZelel2oXUEO8rH83VS/hxH5vv1uHquPg5wZs8yMAfdv971IU+kcPUczi7NVBQ==}
|
||||||
|
engines: {node: '>=0.10.0'}
|
||||||
|
|
||||||
|
postgres-date@1.0.7:
|
||||||
|
resolution: {integrity: sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==}
|
||||||
|
engines: {node: '>=0.10.0'}
|
||||||
|
|
||||||
|
postgres-interval@1.2.0:
|
||||||
|
resolution: {integrity: sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==}
|
||||||
|
engines: {node: '>=0.10.0'}
|
||||||
|
|
||||||
prelude-ls@1.2.1:
|
prelude-ls@1.2.1:
|
||||||
resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==}
|
resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==}
|
||||||
engines: {node: '>= 0.8.0'}
|
engines: {node: '>= 0.8.0'}
|
||||||
@@ -4016,6 +4093,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-Kko+Y5XQ6fM+Ce3dq3m9YGxnacYZYl9cA1wZjaF3Vbry2L3i1qVg8+CAgNPsXRArPMUMCaOR7oa9Nqntc43JKA==}
|
resolution: {integrity: sha512-Kko+Y5XQ6fM+Ce3dq3m9YGxnacYZYl9cA1wZjaF3Vbry2L3i1qVg8+CAgNPsXRArPMUMCaOR7oa9Nqntc43JKA==}
|
||||||
engines: {node: '>= 20.19.0'}
|
engines: {node: '>= 20.19.0'}
|
||||||
|
|
||||||
|
redis-errors@1.2.0:
|
||||||
|
resolution: {integrity: sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w==}
|
||||||
|
engines: {node: '>=4'}
|
||||||
|
|
||||||
reflect-metadata@0.2.2:
|
reflect-metadata@0.2.2:
|
||||||
resolution: {integrity: sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==}
|
resolution: {integrity: sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==}
|
||||||
|
|
||||||
@@ -4211,6 +4292,10 @@ packages:
|
|||||||
spdx-license-ids@3.0.23:
|
spdx-license-ids@3.0.23:
|
||||||
resolution: {integrity: sha512-CWLcCCH7VLu13TgOH+r8p1O/Znwhqv/dbb6lqWy67G+pT1kHmeD/+V36AVb/vq8QMIQwVShJ6Ssl5FPh0fuSdw==}
|
resolution: {integrity: sha512-CWLcCCH7VLu13TgOH+r8p1O/Znwhqv/dbb6lqWy67G+pT1kHmeD/+V36AVb/vq8QMIQwVShJ6Ssl5FPh0fuSdw==}
|
||||||
|
|
||||||
|
split2@4.2.0:
|
||||||
|
resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==}
|
||||||
|
engines: {node: '>= 10.x'}
|
||||||
|
|
||||||
sprintf-js@1.0.3:
|
sprintf-js@1.0.3:
|
||||||
resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==}
|
resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==}
|
||||||
|
|
||||||
@@ -4225,6 +4310,9 @@ packages:
|
|||||||
stackback@0.0.2:
|
stackback@0.0.2:
|
||||||
resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==}
|
resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==}
|
||||||
|
|
||||||
|
standard-as-callback@2.1.0:
|
||||||
|
resolution: {integrity: sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A==}
|
||||||
|
|
||||||
statuses@2.0.2:
|
statuses@2.0.2:
|
||||||
resolution: {integrity: sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==}
|
resolution: {integrity: sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==}
|
||||||
engines: {node: '>= 0.8'}
|
engines: {node: '>= 0.8'}
|
||||||
@@ -4781,6 +4869,10 @@ packages:
|
|||||||
xmlchars@2.2.0:
|
xmlchars@2.2.0:
|
||||||
resolution: {integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==}
|
resolution: {integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==}
|
||||||
|
|
||||||
|
xtend@4.0.2:
|
||||||
|
resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==}
|
||||||
|
engines: {node: '>=0.4'}
|
||||||
|
|
||||||
y18n@5.0.8:
|
y18n@5.0.8:
|
||||||
resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==}
|
resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==}
|
||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
@@ -5720,6 +5812,8 @@ snapshots:
|
|||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
'@types/node': 24.13.3
|
'@types/node': 24.13.3
|
||||||
|
|
||||||
|
'@ioredis/commands@2.0.0': {}
|
||||||
|
|
||||||
'@isaacs/cliui@8.0.2':
|
'@isaacs/cliui@8.0.2':
|
||||||
dependencies:
|
dependencies:
|
||||||
string-width: 5.1.2
|
string-width: 5.1.2
|
||||||
@@ -6614,6 +6708,12 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
undici-types: 7.18.2
|
undici-types: 7.18.2
|
||||||
|
|
||||||
|
'@types/pg@8.21.0':
|
||||||
|
dependencies:
|
||||||
|
'@types/node': 24.13.3
|
||||||
|
pg-protocol: 1.16.0
|
||||||
|
pg-types: 2.2.0
|
||||||
|
|
||||||
'@types/qs@6.15.1': {}
|
'@types/qs@6.15.1': {}
|
||||||
|
|
||||||
'@types/range-parser@1.2.7': {}
|
'@types/range-parser@1.2.7': {}
|
||||||
@@ -7305,6 +7405,8 @@ snapshots:
|
|||||||
|
|
||||||
clone@1.0.4: {}
|
clone@1.0.4: {}
|
||||||
|
|
||||||
|
cluster-key-slot@1.1.1: {}
|
||||||
|
|
||||||
co@4.6.0: {}
|
co@4.6.0: {}
|
||||||
|
|
||||||
collect-v8-coverage@1.0.3: {}
|
collect-v8-coverage@1.0.3: {}
|
||||||
@@ -7426,6 +7528,8 @@ snapshots:
|
|||||||
|
|
||||||
delayed-stream@1.0.0: {}
|
delayed-stream@1.0.0: {}
|
||||||
|
|
||||||
|
denque@2.1.0: {}
|
||||||
|
|
||||||
depd@2.0.0: {}
|
depd@2.0.0: {}
|
||||||
|
|
||||||
detect-libc@2.1.2:
|
detect-libc@2.1.2:
|
||||||
@@ -8025,6 +8129,17 @@ snapshots:
|
|||||||
|
|
||||||
ini@6.0.0: {}
|
ini@6.0.0: {}
|
||||||
|
|
||||||
|
ioredis@6.0.0:
|
||||||
|
dependencies:
|
||||||
|
'@ioredis/commands': 2.0.0
|
||||||
|
cluster-key-slot: 1.1.1
|
||||||
|
debug: 4.4.3
|
||||||
|
denque: 2.1.0
|
||||||
|
redis-errors: 1.2.0
|
||||||
|
standard-as-callback: 2.1.0
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- supports-color
|
||||||
|
|
||||||
ip-address@10.5.0: {}
|
ip-address@10.5.0: {}
|
||||||
|
|
||||||
ipaddr.js@1.9.1: {}
|
ipaddr.js@1.9.1: {}
|
||||||
@@ -8971,6 +9086,41 @@ snapshots:
|
|||||||
|
|
||||||
pathe@2.0.3: {}
|
pathe@2.0.3: {}
|
||||||
|
|
||||||
|
pg-cloudflare@1.4.0:
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
pg-connection-string@2.14.0: {}
|
||||||
|
|
||||||
|
pg-int8@1.0.1: {}
|
||||||
|
|
||||||
|
pg-pool@3.14.0(pg@8.23.0):
|
||||||
|
dependencies:
|
||||||
|
pg: 8.23.0
|
||||||
|
|
||||||
|
pg-protocol@1.16.0: {}
|
||||||
|
|
||||||
|
pg-types@2.2.0:
|
||||||
|
dependencies:
|
||||||
|
pg-int8: 1.0.1
|
||||||
|
postgres-array: 2.0.0
|
||||||
|
postgres-bytea: 1.0.1
|
||||||
|
postgres-date: 1.0.7
|
||||||
|
postgres-interval: 1.2.0
|
||||||
|
|
||||||
|
pg@8.23.0:
|
||||||
|
dependencies:
|
||||||
|
pg-connection-string: 2.14.0
|
||||||
|
pg-pool: 3.14.0(pg@8.23.0)
|
||||||
|
pg-protocol: 1.16.0
|
||||||
|
pg-types: 2.2.0
|
||||||
|
pgpass: 1.0.5
|
||||||
|
optionalDependencies:
|
||||||
|
pg-cloudflare: 1.4.0
|
||||||
|
|
||||||
|
pgpass@1.0.5:
|
||||||
|
dependencies:
|
||||||
|
split2: 4.2.0
|
||||||
|
|
||||||
picocolors@1.1.1: {}
|
picocolors@1.1.1: {}
|
||||||
|
|
||||||
picomatch@2.3.2: {}
|
picomatch@2.3.2: {}
|
||||||
@@ -9005,6 +9155,16 @@ snapshots:
|
|||||||
picocolors: 1.1.1
|
picocolors: 1.1.1
|
||||||
source-map-js: 1.2.1
|
source-map-js: 1.2.1
|
||||||
|
|
||||||
|
postgres-array@2.0.0: {}
|
||||||
|
|
||||||
|
postgres-bytea@1.0.1: {}
|
||||||
|
|
||||||
|
postgres-date@1.0.7: {}
|
||||||
|
|
||||||
|
postgres-interval@1.2.0:
|
||||||
|
dependencies:
|
||||||
|
xtend: 4.0.2
|
||||||
|
|
||||||
prelude-ls@1.2.1: {}
|
prelude-ls@1.2.1: {}
|
||||||
|
|
||||||
prettier-linter-helpers@1.0.1:
|
prettier-linter-helpers@1.0.1:
|
||||||
@@ -9059,6 +9219,8 @@ snapshots:
|
|||||||
|
|
||||||
readdirp@5.1.1: {}
|
readdirp@5.1.1: {}
|
||||||
|
|
||||||
|
redis-errors@1.2.0: {}
|
||||||
|
|
||||||
reflect-metadata@0.2.2: {}
|
reflect-metadata@0.2.2: {}
|
||||||
|
|
||||||
require-directory@2.1.1: {}
|
require-directory@2.1.1: {}
|
||||||
@@ -9324,6 +9486,8 @@ snapshots:
|
|||||||
|
|
||||||
spdx-license-ids@3.0.23: {}
|
spdx-license-ids@3.0.23: {}
|
||||||
|
|
||||||
|
split2@4.2.0: {}
|
||||||
|
|
||||||
sprintf-js@1.0.3: {}
|
sprintf-js@1.0.3: {}
|
||||||
|
|
||||||
ssri@13.0.1:
|
ssri@13.0.1:
|
||||||
@@ -9336,6 +9500,8 @@ snapshots:
|
|||||||
|
|
||||||
stackback@0.0.2: {}
|
stackback@0.0.2: {}
|
||||||
|
|
||||||
|
standard-as-callback@2.1.0: {}
|
||||||
|
|
||||||
statuses@2.0.2: {}
|
statuses@2.0.2: {}
|
||||||
|
|
||||||
std-env@4.2.0: {}
|
std-env@4.2.0: {}
|
||||||
@@ -9858,6 +10024,8 @@ snapshots:
|
|||||||
|
|
||||||
xmlchars@2.2.0: {}
|
xmlchars@2.2.0: {}
|
||||||
|
|
||||||
|
xtend@4.0.2: {}
|
||||||
|
|
||||||
y18n@5.0.8: {}
|
y18n@5.0.8: {}
|
||||||
|
|
||||||
yallist@3.1.1: {}
|
yallist@3.1.1: {}
|
||||||
|
|||||||
Reference in New Issue
Block a user