@volontariapp/health-check 0.0.0-snap-398faec
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 +72 -0
- package/README.md +121 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -0
- package/dist/services/bridges/neo4j-bridge-health-provider.d.ts +7 -0
- package/dist/services/bridges/neo4j-bridge-health-provider.d.ts.map +1 -0
- package/dist/services/bridges/neo4j-bridge-health-provider.js +15 -0
- package/dist/services/bridges/neo4j-bridge-health-provider.js.map +1 -0
- package/dist/services/bridges/postgres-bridge-health-provider.d.ts +7 -0
- package/dist/services/bridges/postgres-bridge-health-provider.d.ts.map +1 -0
- package/dist/services/bridges/postgres-bridge-health-provider.js +15 -0
- package/dist/services/bridges/postgres-bridge-health-provider.js.map +1 -0
- package/dist/services/bridges/redis-bridge-health-provider.d.ts +7 -0
- package/dist/services/bridges/redis-bridge-health-provider.d.ts.map +1 -0
- package/dist/services/bridges/redis-bridge-health-provider.js +15 -0
- package/dist/services/bridges/redis-bridge-health-provider.js.map +1 -0
- package/dist/services/database-health-types.d.ts +9 -0
- package/dist/services/database-health-types.d.ts.map +1 -0
- package/dist/services/database-health-types.js +2 -0
- package/dist/services/database-health-types.js.map +1 -0
- package/dist/services/database-health.orchestrator.d.ts +12 -0
- package/dist/services/database-health.orchestrator.d.ts.map +1 -0
- package/dist/services/database-health.orchestrator.js +15 -0
- package/dist/services/database-health.orchestrator.js.map +1 -0
- package/dist/services/database-health.provider.d.ts +10 -0
- package/dist/services/database-health.provider.d.ts.map +1 -0
- package/dist/services/database-health.provider.js +40 -0
- package/dist/services/database-health.provider.js.map +1 -0
- package/dist/test/int/config.example.d.ts +5 -0
- package/dist/test/int/config.example.d.ts.map +1 -0
- package/dist/test/int/config.example.js +66 -0
- package/dist/test/int/config.example.js.map +1 -0
- package/dist/test/int/database-health.int.spec.d.ts +2 -0
- package/dist/test/int/database-health.int.spec.d.ts.map +1 -0
- package/dist/test/int/database-health.int.spec.js +42 -0
- package/dist/test/int/database-health.int.spec.js.map +1 -0
- package/dist/test/unit/database-health.unit.spec.d.ts +2 -0
- package/dist/test/unit/database-health.unit.spec.d.ts.map +1 -0
- package/dist/test/unit/database-health.unit.spec.js +52 -0
- package/dist/test/unit/database-health.unit.spec.js.map +1 -0
- package/package.json +50 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.1.7
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Updated dependencies []:
|
|
8
|
+
- @volontariapp/bridge@0.2.5
|
|
9
|
+
- @volontariapp/config@1.1.2
|
|
10
|
+
|
|
11
|
+
## 0.1.6
|
|
12
|
+
|
|
13
|
+
### Patch Changes
|
|
14
|
+
|
|
15
|
+
- Standardize test and coverage scripts across packages. Add test:coverage with json-summary reporter for CI reporting.
|
|
16
|
+
|
|
17
|
+
- Updated dependencies []:
|
|
18
|
+
- @volontariapp/bridge@0.2.4
|
|
19
|
+
- @volontariapp/config@1.1.1
|
|
20
|
+
- @volontariapp/errors@0.4.4
|
|
21
|
+
|
|
22
|
+
## 0.1.5
|
|
23
|
+
|
|
24
|
+
### Patch Changes
|
|
25
|
+
|
|
26
|
+
- Updated dependencies []:
|
|
27
|
+
- @volontariapp/errors@0.4.3
|
|
28
|
+
|
|
29
|
+
## 0.1.4
|
|
30
|
+
|
|
31
|
+
### Patch Changes
|
|
32
|
+
|
|
33
|
+
- Updated dependencies []:
|
|
34
|
+
- @volontariapp/config@1.1.0
|
|
35
|
+
|
|
36
|
+
## 0.1.3
|
|
37
|
+
|
|
38
|
+
### Patch Changes
|
|
39
|
+
|
|
40
|
+
- bump global version
|
|
41
|
+
|
|
42
|
+
- Updated dependencies []:
|
|
43
|
+
- @volontariapp/bridge@0.2.3
|
|
44
|
+
- @volontariapp/config@1.0.2
|
|
45
|
+
- @volontariapp/errors@0.4.2
|
|
46
|
+
|
|
47
|
+
## 0.1.2
|
|
48
|
+
|
|
49
|
+
### Patch Changes
|
|
50
|
+
|
|
51
|
+
- bump ci
|
|
52
|
+
|
|
53
|
+
- Updated dependencies []:
|
|
54
|
+
- @volontariapp/bridge@0.2.2
|
|
55
|
+
- @volontariapp/config@1.0.1
|
|
56
|
+
- @volontariapp/errors@0.4.1
|
|
57
|
+
|
|
58
|
+
## 0.1.1
|
|
59
|
+
|
|
60
|
+
### Patch Changes
|
|
61
|
+
|
|
62
|
+
- Updated dependencies []:
|
|
63
|
+
- @volontariapp/errors@0.4.0
|
|
64
|
+
- @volontariapp/bridge@0.2.1
|
|
65
|
+
|
|
66
|
+
All notable changes to this project will be documented in this file.
|
|
67
|
+
|
|
68
|
+
## 0.1.0
|
|
69
|
+
|
|
70
|
+
### Minor Changes
|
|
71
|
+
|
|
72
|
+
- Initial package scaffold.
|
package/README.md
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
# @volontariapp/health-check
|
|
2
|
+
|
|
3
|
+
Bibliothèque Node.js pure pour vérifier la santé des connexions base de données déjà instanciées.
|
|
4
|
+
|
|
5
|
+
Objectif principal:
|
|
6
|
+
- Bridge crée et gère la connexion
|
|
7
|
+
- Health-check vérifie cette connexion
|
|
8
|
+
|
|
9
|
+
Cette lib ne doit pas instancier de base de données.
|
|
10
|
+
|
|
11
|
+
## Ce que fait la librairie
|
|
12
|
+
|
|
13
|
+
- Fournit un contrat standard de résultat de santé
|
|
14
|
+
- Fournit un provider abstrait pour implémenter un check
|
|
15
|
+
- Fournit un orchestrateur pour agréger plusieurs checks
|
|
16
|
+
- Fournit des providers prêts à l'emploi branchés sur @volontariapp/bridge:
|
|
17
|
+
- PostgresBridgeHealthProvider
|
|
18
|
+
- RedisBridgeHealthProvider
|
|
19
|
+
- Neo4jBridgeHealthProvider
|
|
20
|
+
|
|
21
|
+
## Installation
|
|
22
|
+
|
|
23
|
+
Depuis le monorepo:
|
|
24
|
+
- dépendance workspace déjà disponible
|
|
25
|
+
|
|
26
|
+
Depuis un projet externe:
|
|
27
|
+
- installer @volontariapp/health-check
|
|
28
|
+
- installer aussi @volontariapp/bridge
|
|
29
|
+
|
|
30
|
+
## Utilisation rapide (Node pur)
|
|
31
|
+
|
|
32
|
+
~~~ts
|
|
33
|
+
import {
|
|
34
|
+
DatabaseHealthOrchestrator,
|
|
35
|
+
PostgresBridgeHealthProvider,
|
|
36
|
+
RedisBridgeHealthProvider,
|
|
37
|
+
Neo4jBridgeHealthProvider,
|
|
38
|
+
} from '@volontariapp/health-check';
|
|
39
|
+
import {
|
|
40
|
+
PostgresProvider,
|
|
41
|
+
RedisProvider,
|
|
42
|
+
Neo4jProvider,
|
|
43
|
+
} from '@volontariapp/bridge';
|
|
44
|
+
|
|
45
|
+
const postgres = new PostgresProvider({
|
|
46
|
+
host: 'localhost',
|
|
47
|
+
port: 5432,
|
|
48
|
+
username: 'app',
|
|
49
|
+
password: 'app',
|
|
50
|
+
database: 'app_db',
|
|
51
|
+
entities: [],
|
|
52
|
+
synchronize: false,
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
const redis = new RedisProvider({
|
|
56
|
+
host: 'localhost',
|
|
57
|
+
port: 6379,
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
const neo4j = new Neo4jProvider({
|
|
61
|
+
url: 'bolt://localhost:7687',
|
|
62
|
+
authToken: {
|
|
63
|
+
principal: 'neo4j',
|
|
64
|
+
credentials: 'password',
|
|
65
|
+
},
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
await postgres.connect();
|
|
69
|
+
await redis.connect();
|
|
70
|
+
await neo4j.connect();
|
|
71
|
+
|
|
72
|
+
const orchestrator = new DatabaseHealthOrchestrator([
|
|
73
|
+
new PostgresBridgeHealthProvider(postgres),
|
|
74
|
+
new RedisBridgeHealthProvider(redis),
|
|
75
|
+
new Neo4jBridgeHealthProvider(neo4j),
|
|
76
|
+
]);
|
|
77
|
+
|
|
78
|
+
const health = await orchestrator.run();
|
|
79
|
+
console.log(health);
|
|
80
|
+
|
|
81
|
+
await Promise.all([
|
|
82
|
+
postgres.disconnect(),
|
|
83
|
+
redis.disconnect(),
|
|
84
|
+
neo4j.disconnect(),
|
|
85
|
+
]);
|
|
86
|
+
~~~
|
|
87
|
+
|
|
88
|
+
## Résultat attendu
|
|
89
|
+
|
|
90
|
+
Le résultat retourné par run() suit ce format:
|
|
91
|
+
|
|
92
|
+
~~~ts
|
|
93
|
+
type OrchestratedHealthResult = {
|
|
94
|
+
status: 'ok' | 'error';
|
|
95
|
+
checks: Array<{
|
|
96
|
+
name: string;
|
|
97
|
+
status: 'up' | 'down';
|
|
98
|
+
message: string;
|
|
99
|
+
error?: {
|
|
100
|
+
name: string;
|
|
101
|
+
message: string;
|
|
102
|
+
};
|
|
103
|
+
}>;
|
|
104
|
+
};
|
|
105
|
+
~~~
|
|
106
|
+
|
|
107
|
+
## API exportée
|
|
108
|
+
|
|
109
|
+
- AbstractDatabaseHealthProvider
|
|
110
|
+
- DatabaseHealthOrchestrator
|
|
111
|
+
- PostgresBridgeHealthProvider
|
|
112
|
+
- RedisBridgeHealthProvider
|
|
113
|
+
- Neo4jBridgeHealthProvider
|
|
114
|
+
|
|
115
|
+
## Bonnes pratiques
|
|
116
|
+
|
|
117
|
+
- Construire les connexions ailleurs (bridge, bridge-nest, bootstrap applicatif)
|
|
118
|
+
- Garder health-check focalisé sur la vérification
|
|
119
|
+
- Configurer host, port, credentials dans bridge, pas ici
|
|
120
|
+
- Réutiliser les mêmes instances pour l'app métier et le health endpoint
|
|
121
|
+
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export * from './services/bridges/neo4j-bridge-health-provider.js';
|
|
2
|
+
export * from './services/bridges/postgres-bridge-health-provider.js';
|
|
3
|
+
export * from './services/bridges/redis-bridge-health-provider.js';
|
|
4
|
+
export * from './services/database-health-types.js';
|
|
5
|
+
export * from './services/database-health.provider.js';
|
|
6
|
+
export * from './services/database-health.orchestrator.js';
|
|
7
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,oDAAoD,CAAC;AACnE,cAAc,uDAAuD,CAAC;AACtE,cAAc,oDAAoD,CAAC;AAEnE,cAAc,qCAAqC,CAAC;AACpD,cAAc,wCAAwC,CAAC;AACvD,cAAc,4CAA4C,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export * from './services/bridges/neo4j-bridge-health-provider.js';
|
|
2
|
+
export * from './services/bridges/postgres-bridge-health-provider.js';
|
|
3
|
+
export * from './services/bridges/redis-bridge-health-provider.js';
|
|
4
|
+
export * from './services/database-health-types.js';
|
|
5
|
+
export * from './services/database-health.provider.js';
|
|
6
|
+
export * from './services/database-health.orchestrator.js';
|
|
7
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,oDAAoD,CAAC;AACnE,cAAc,uDAAuD,CAAC;AACtE,cAAc,oDAAoD,CAAC;AAEnE,cAAc,qCAAqC,CAAC;AACpD,cAAc,wCAAwC,CAAC;AACvD,cAAc,4CAA4C,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { type Neo4jProvider } from "@volontariapp/bridge";
|
|
2
|
+
import { AbstractDatabaseHealthProvider } from "../database-health.provider.js";
|
|
3
|
+
export declare class Neo4jBridgeHealthProvider extends AbstractDatabaseHealthProvider<Neo4jProvider> {
|
|
4
|
+
constructor(provider: Neo4jProvider);
|
|
5
|
+
protected pingDb(): Promise<void>;
|
|
6
|
+
}
|
|
7
|
+
//# sourceMappingURL=neo4j-bridge-health-provider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"neo4j-bridge-health-provider.d.ts","sourceRoot":"","sources":["../../../src/services/bridges/neo4j-bridge-health-provider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,KAAM,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,8BAA8B,EAAE,MAAM,gCAAgC,CAAC;AAGhF,qBAAa,yBAA0B,SAAQ,8BAA8B,CAAC,aAAa,CAAC;gBAC9E,QAAQ,EAAE,aAAa;cAInB,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;CAWxC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { AbstractDatabaseHealthProvider } from "../database-health.provider.js";
|
|
2
|
+
import { InternalServerError } from "@volontariapp/errors";
|
|
3
|
+
export class Neo4jBridgeHealthProvider extends AbstractDatabaseHealthProvider {
|
|
4
|
+
constructor(provider) {
|
|
5
|
+
super('neo4j', provider);
|
|
6
|
+
}
|
|
7
|
+
async pingDb() {
|
|
8
|
+
if (!this.client.isConnected()) {
|
|
9
|
+
throw new InternalServerError('Neo4j provider is not connected', 'HEALTH_CHECK_NEO4J_NOT_CONNECTED');
|
|
10
|
+
}
|
|
11
|
+
const driver = this.client.getDriver();
|
|
12
|
+
await driver.verifyConnectivity();
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=neo4j-bridge-health-provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"neo4j-bridge-health-provider.js","sourceRoot":"","sources":["../../../src/services/bridges/neo4j-bridge-health-provider.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,8BAA8B,EAAE,MAAM,gCAAgC,CAAC;AAChF,OAAO,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAE3D,MAAM,OAAO,yBAA0B,SAAQ,8BAA6C;IAC1F,YAAY,QAAuB;QACjC,KAAK,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;IAC3B,CAAC;IAES,KAAK,CAAC,MAAM;QACpB,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,EAAE,CAAC;YAC/B,MAAM,IAAI,mBAAmB,CAC3B,iCAAiC,EACjC,kCAAkC,CACnC,CAAC;QACJ,CAAC;QAED,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC;QACvC,MAAM,MAAM,CAAC,kBAAkB,EAAE,CAAC;IACpC,CAAC;CACF"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { AbstractDatabaseHealthProvider } from "../database-health.provider.js";
|
|
2
|
+
import { type PostgresProvider } from "@volontariapp/bridge";
|
|
3
|
+
export declare class PostgresBridgeHealthProvider extends AbstractDatabaseHealthProvider<PostgresProvider> {
|
|
4
|
+
constructor(provider: PostgresProvider);
|
|
5
|
+
protected pingDb(): Promise<void>;
|
|
6
|
+
}
|
|
7
|
+
//# sourceMappingURL=postgres-bridge-health-provider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"postgres-bridge-health-provider.d.ts","sourceRoot":"","sources":["../../../src/services/bridges/postgres-bridge-health-provider.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,8BAA8B,EAAE,MAAM,gCAAgC,CAAC;AAChF,OAAO,EAAE,KAAK,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAE7D,qBAAa,4BAA6B,SAAQ,8BAA8B,CAAC,gBAAgB,CAAC;gBACpF,QAAQ,EAAE,gBAAgB;cAItB,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;CAWxC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { InternalServerError } from "@volontariapp/errors";
|
|
2
|
+
import { AbstractDatabaseHealthProvider } from "../database-health.provider.js";
|
|
3
|
+
export class PostgresBridgeHealthProvider extends AbstractDatabaseHealthProvider {
|
|
4
|
+
constructor(provider) {
|
|
5
|
+
super('postgres', provider);
|
|
6
|
+
}
|
|
7
|
+
async pingDb() {
|
|
8
|
+
if (!this.client.isConnected()) {
|
|
9
|
+
throw new InternalServerError('Postgres provider is not connected', 'HEALTH_CHECK_POSTGRES_NOT_CONNECTED');
|
|
10
|
+
}
|
|
11
|
+
const driver = this.client.getDriver();
|
|
12
|
+
await driver.query('SELECT 1');
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=postgres-bridge-health-provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"postgres-bridge-health-provider.js","sourceRoot":"","sources":["../../../src/services/bridges/postgres-bridge-health-provider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,EAAE,8BAA8B,EAAE,MAAM,gCAAgC,CAAC;AAGhF,MAAM,OAAO,4BAA6B,SAAQ,8BAAgD;IAChG,YAAY,QAA0B;QACpC,KAAK,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;IAC9B,CAAC;IAES,KAAK,CAAC,MAAM;QACpB,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,EAAE,CAAC;YAC/B,MAAM,IAAI,mBAAmB,CAC3B,oCAAoC,EACpC,qCAAqC,CACtC,CAAC;QACJ,CAAC;QAED,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC;QACvC,MAAM,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;IACjC,CAAC;CACF"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { type RedisProvider } from "@volontariapp/bridge";
|
|
2
|
+
import { AbstractDatabaseHealthProvider } from "../database-health.provider.js";
|
|
3
|
+
export declare class RedisBridgeHealthProvider extends AbstractDatabaseHealthProvider<RedisProvider> {
|
|
4
|
+
constructor(provider: RedisProvider);
|
|
5
|
+
protected pingDb(): Promise<void>;
|
|
6
|
+
}
|
|
7
|
+
//# sourceMappingURL=redis-bridge-health-provider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"redis-bridge-health-provider.d.ts","sourceRoot":"","sources":["../../../src/services/bridges/redis-bridge-health-provider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,8BAA8B,EAAE,MAAM,gCAAgC,CAAC;AAGhF,qBAAa,yBAA0B,SAAQ,8BAA8B,CAAC,aAAa,CAAC;gBAC9E,QAAQ,EAAE,aAAa;cAInB,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;CAWxC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { AbstractDatabaseHealthProvider } from "../database-health.provider.js";
|
|
2
|
+
import { InternalServerError } from "@volontariapp/errors";
|
|
3
|
+
export class RedisBridgeHealthProvider extends AbstractDatabaseHealthProvider {
|
|
4
|
+
constructor(provider) {
|
|
5
|
+
super('redis', provider);
|
|
6
|
+
}
|
|
7
|
+
async pingDb() {
|
|
8
|
+
if (!this.client.isConnected()) {
|
|
9
|
+
throw new InternalServerError('Redis provider is not connected', 'HEALTH_CHECK_REDIS_NOT_CONNECTED');
|
|
10
|
+
}
|
|
11
|
+
const driver = this.client.getDriver();
|
|
12
|
+
await driver.ping();
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=redis-bridge-health-provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"redis-bridge-health-provider.js","sourceRoot":"","sources":["../../../src/services/bridges/redis-bridge-health-provider.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,8BAA8B,EAAE,MAAM,gCAAgC,CAAC;AAChF,OAAO,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAE3D,MAAM,OAAO,yBAA0B,SAAQ,8BAA6C;IAC1F,YAAY,QAAuB;QACjC,KAAK,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;IAC3B,CAAC;IAES,KAAK,CAAC,MAAM;QACpB,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,EAAE,CAAC;YAC/B,MAAM,IAAI,mBAAmB,CAC3B,iCAAiC,EACjC,kCAAkC,CACnC,CAAC;QACJ,CAAC;QAED,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC;QACvC,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;IACtB,CAAC;CACF"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { type DatabaseHealthError } from '@volontariapp/errors';
|
|
2
|
+
export type DatabaseHealthStatus = 'up' | 'down';
|
|
3
|
+
export interface DatabaseHealthResult {
|
|
4
|
+
name: string;
|
|
5
|
+
status: DatabaseHealthStatus;
|
|
6
|
+
message: string;
|
|
7
|
+
error?: DatabaseHealthError;
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=database-health-types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"database-health-types.d.ts","sourceRoot":"","sources":["../../src/services/database-health-types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAEhE,MAAM,MAAM,oBAAoB,GAAG,IAAI,GAAG,MAAM,CAAC;AAEjD,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,oBAAoB,CAAC;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,mBAAmB,CAAC;CAC7B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"database-health-types.js","sourceRoot":"","sources":["../../src/services/database-health-types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { DatabaseHealthResult } from './database-health-types.js';
|
|
2
|
+
import type { AbstractDatabaseHealthProvider } from './database-health.provider.js';
|
|
3
|
+
export interface OrchestratedHealthResult {
|
|
4
|
+
status: 'ok' | 'error';
|
|
5
|
+
checks: DatabaseHealthResult[];
|
|
6
|
+
}
|
|
7
|
+
export declare class DatabaseHealthOrchestrator {
|
|
8
|
+
private readonly providers;
|
|
9
|
+
constructor(providers: ReadonlyArray<AbstractDatabaseHealthProvider>);
|
|
10
|
+
run(): Promise<OrchestratedHealthResult>;
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=database-health.orchestrator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"database-health.orchestrator.d.ts","sourceRoot":"","sources":["../../src/services/database-health.orchestrator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAC;AACvE,OAAO,KAAK,EAAE,8BAA8B,EAAE,MAAM,+BAA+B,CAAC;AAEpF,MAAM,WAAW,wBAAwB;IACvC,MAAM,EAAE,IAAI,GAAG,OAAO,CAAC;IACvB,MAAM,EAAE,oBAAoB,EAAE,CAAC;CAChC;AAED,qBAAa,0BAA0B;IACzB,OAAO,CAAC,QAAQ,CAAC,SAAS;gBAAT,SAAS,EAAE,aAAa,CAAC,8BAA8B,CAAC;IAE/E,GAAG,IAAI,OAAO,CAAC,wBAAwB,CAAC;CAS/C"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export class DatabaseHealthOrchestrator {
|
|
2
|
+
providers;
|
|
3
|
+
constructor(providers) {
|
|
4
|
+
this.providers = providers;
|
|
5
|
+
}
|
|
6
|
+
async run() {
|
|
7
|
+
const checks = await Promise.all(this.providers.map((provider) => provider.health()));
|
|
8
|
+
const isHealthy = checks.every((check) => check.status === 'up');
|
|
9
|
+
return {
|
|
10
|
+
status: isHealthy ? 'ok' : 'error',
|
|
11
|
+
checks,
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=database-health.orchestrator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"database-health.orchestrator.js","sourceRoot":"","sources":["../../src/services/database-health.orchestrator.ts"],"names":[],"mappings":"AAQA,MAAM,OAAO,0BAA0B;IACR;IAA7B,YAA6B,SAAwD;QAAxD,cAAS,GAAT,SAAS,CAA+C;IAAG,CAAC;IAEzF,KAAK,CAAC,GAAG;QACP,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QACtF,MAAM,SAAS,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,KAAK,IAAI,CAAC,CAAC;QAEjE,OAAO;YACL,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO;YAClC,MAAM;SACP,CAAC;IACJ,CAAC;CACF"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { DatabaseHealthResult } from './database-health-types.js';
|
|
2
|
+
export declare abstract class AbstractDatabaseHealthProvider<TClient = unknown> {
|
|
3
|
+
readonly name: string;
|
|
4
|
+
protected readonly client: TClient;
|
|
5
|
+
protected constructor(name: string, client: TClient);
|
|
6
|
+
protected abstract pingDb(): Promise<void>;
|
|
7
|
+
health(): Promise<DatabaseHealthResult>;
|
|
8
|
+
private normalizeError;
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=database-health.provider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"database-health.provider.d.ts","sourceRoot":"","sources":["../../src/services/database-health.provider.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAC;AAEvE,8BAAsB,8BAA8B,CAAC,OAAO,GAAG,OAAO;aAElD,IAAI,EAAE,MAAM;IAC5B,SAAS,CAAC,QAAQ,CAAC,MAAM,EAAE,OAAO;IAFpC,SAAS,aACS,IAAI,EAAE,MAAM,EACT,MAAM,EAAE,OAAO;IAGpC,SAAS,CAAC,QAAQ,CAAC,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAEpC,MAAM,IAAI,OAAO,CAAC,oBAAoB,CAAC;IAmB7C,OAAO,CAAC,cAAc;CAavB"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { DatabaseHealthError } from '@volontariapp/errors';
|
|
2
|
+
export class AbstractDatabaseHealthProvider {
|
|
3
|
+
name;
|
|
4
|
+
client;
|
|
5
|
+
constructor(name, client) {
|
|
6
|
+
this.name = name;
|
|
7
|
+
this.client = client;
|
|
8
|
+
}
|
|
9
|
+
async health() {
|
|
10
|
+
try {
|
|
11
|
+
await this.pingDb();
|
|
12
|
+
return {
|
|
13
|
+
name: this.name,
|
|
14
|
+
status: 'up',
|
|
15
|
+
message: `${this.name} connection is healthy`,
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
catch (error) {
|
|
19
|
+
const normalizedError = this.normalizeError(error);
|
|
20
|
+
return {
|
|
21
|
+
name: this.name,
|
|
22
|
+
status: 'down',
|
|
23
|
+
message: `${this.name} connection failed`,
|
|
24
|
+
error: normalizedError,
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
normalizeError(error) {
|
|
29
|
+
if (error instanceof Error) {
|
|
30
|
+
return new DatabaseHealthError(error.message, 'DATABASE_HEALTH_ERROR', {
|
|
31
|
+
causeName: error.name,
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
if (typeof error === 'string') {
|
|
35
|
+
return new DatabaseHealthError(error);
|
|
36
|
+
}
|
|
37
|
+
return new DatabaseHealthError('Unknown error while pinging database');
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=database-health.provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"database-health.provider.js","sourceRoot":"","sources":["../../src/services/database-health.provider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAG3D,MAAM,OAAgB,8BAA8B;IAEhC;IACG;IAFrB,YACkB,IAAY,EACT,MAAe;QADlB,SAAI,GAAJ,IAAI,CAAQ;QACT,WAAM,GAAN,MAAM,CAAS;IACjC,CAAC;IAIJ,KAAK,CAAC,MAAM;QACV,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,MAAM,EAAE,CAAC;YACpB,OAAO;gBACL,IAAI,EAAE,IAAI,CAAC,IAAI;gBACf,MAAM,EAAE,IAAI;gBACZ,OAAO,EAAE,GAAG,IAAI,CAAC,IAAI,wBAAwB;aAC9C,CAAC;QACJ,CAAC;QAAC,OAAO,KAAc,EAAE,CAAC;YACxB,MAAM,eAAe,GAAG,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;YACnD,OAAO;gBACL,IAAI,EAAE,IAAI,CAAC,IAAI;gBACf,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE,GAAG,IAAI,CAAC,IAAI,oBAAoB;gBACzC,KAAK,EAAE,eAAe;aACvB,CAAC;QACJ,CAAC;IACH,CAAC;IAEO,cAAc,CAAC,KAAc;QACnC,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;YAC3B,OAAO,IAAI,mBAAmB,CAAC,KAAK,CAAC,OAAO,EAAE,uBAAuB,EAAE;gBACrE,SAAS,EAAE,KAAK,CAAC,IAAI;aACtB,CAAC,CAAC;QACL,CAAC;QAED,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;YAC9B,OAAO,IAAI,mBAAmB,CAAC,KAAK,CAAC,CAAC;QACxC,CAAC;QAED,OAAO,IAAI,mBAAmB,CAAC,sCAAsC,CAAC,CAAC;IACzE,CAAC;CACF"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { IPostgresConfig, INeo4jConfig, IRedisConfig } from '@volontariapp/bridge';
|
|
2
|
+
export declare const postgresConfig: IPostgresConfig;
|
|
3
|
+
export declare const neo4jConfig: INeo4jConfig;
|
|
4
|
+
export declare const redisConfig: IRedisConfig;
|
|
5
|
+
//# sourceMappingURL=config.example.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.example.d.ts","sourceRoot":"","sources":["../../../src/test/int/config.example.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,eAAe,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AA8BxF,eAAO,MAAM,cAAc,EAAE,eAQ5B,CAAC;AAEF,eAAO,MAAM,WAAW,EAAE,YAOzB,CAAC;AAEF,eAAO,MAAM,WAAW,EAAE,YAOzB,CAAC"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
8
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
9
|
+
};
|
|
10
|
+
import { dirname, resolve } from 'node:path';
|
|
11
|
+
import { fileURLToPath } from 'node:url';
|
|
12
|
+
import { Type } from 'class-transformer';
|
|
13
|
+
import { IsDefined, ValidateNested } from 'class-validator';
|
|
14
|
+
import { BaseConfig, Neo4jConfig, PostgresConfig, RedisConfig, loadConfig, } from '@volontariapp/config';
|
|
15
|
+
class IntegrationConfig extends BaseConfig {
|
|
16
|
+
postgres;
|
|
17
|
+
neo4j;
|
|
18
|
+
redis;
|
|
19
|
+
}
|
|
20
|
+
__decorate([
|
|
21
|
+
IsDefined(),
|
|
22
|
+
ValidateNested(),
|
|
23
|
+
Type(() => PostgresConfig),
|
|
24
|
+
__metadata("design:type", PostgresConfig)
|
|
25
|
+
], IntegrationConfig.prototype, "postgres", void 0);
|
|
26
|
+
__decorate([
|
|
27
|
+
IsDefined(),
|
|
28
|
+
ValidateNested(),
|
|
29
|
+
Type(() => Neo4jConfig),
|
|
30
|
+
__metadata("design:type", Neo4jConfig)
|
|
31
|
+
], IntegrationConfig.prototype, "neo4j", void 0);
|
|
32
|
+
__decorate([
|
|
33
|
+
IsDefined(),
|
|
34
|
+
ValidateNested(),
|
|
35
|
+
Type(() => RedisConfig),
|
|
36
|
+
__metadata("design:type", RedisConfig)
|
|
37
|
+
], IntegrationConfig.prototype, "redis", void 0);
|
|
38
|
+
const currentDir = dirname(fileURLToPath(import.meta.url));
|
|
39
|
+
const configDir = resolve(currentDir, '../config');
|
|
40
|
+
const config = loadConfig(configDir, IntegrationConfig);
|
|
41
|
+
export const postgresConfig = {
|
|
42
|
+
host: config.postgres.host,
|
|
43
|
+
port: config.postgres.port,
|
|
44
|
+
username: config.postgres.username,
|
|
45
|
+
password: config.postgres.password,
|
|
46
|
+
database: config.postgres.database,
|
|
47
|
+
synchronize: true,
|
|
48
|
+
ssl: config.postgres.ssl,
|
|
49
|
+
};
|
|
50
|
+
export const neo4jConfig = {
|
|
51
|
+
url: `${config.neo4j.scheme}://${config.neo4j.host}:${String(config.neo4j.port)}`,
|
|
52
|
+
authToken: {
|
|
53
|
+
scheme: config.neo4j.scheme,
|
|
54
|
+
principal: config.neo4j.username,
|
|
55
|
+
credentials: config.neo4j.password,
|
|
56
|
+
},
|
|
57
|
+
};
|
|
58
|
+
export const redisConfig = {
|
|
59
|
+
host: config.redis.host,
|
|
60
|
+
port: config.redis.port,
|
|
61
|
+
username: config.redis.username,
|
|
62
|
+
password: config.redis.password,
|
|
63
|
+
db: config.redis.dbIndex,
|
|
64
|
+
keyPrefix: config.redis.keyPrefix,
|
|
65
|
+
};
|
|
66
|
+
//# sourceMappingURL=config.example.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.example.js","sourceRoot":"","sources":["../../../src/test/int/config.example.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AACzC,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAE5D,OAAO,EACL,UAAU,EACV,WAAW,EACX,cAAc,EACd,WAAW,EACX,UAAU,GACX,MAAM,sBAAsB,CAAC;AAE9B,MAAM,iBAAkB,SAAQ,UAAU;IAIxC,QAAQ,CAAkB;IAK1B,KAAK,CAAe;IAKpB,KAAK,CAAe;CACrB;AAXC;IAHC,SAAS,EAAE;IACX,cAAc,EAAE;IAChB,IAAI,CAAC,GAAG,EAAE,CAAC,cAAc,CAAC;8BAChB,cAAc;mDAAC;AAK1B;IAHC,SAAS,EAAE;IACX,cAAc,EAAE;IAChB,IAAI,CAAC,GAAG,EAAE,CAAC,WAAW,CAAC;8BAChB,WAAW;gDAAC;AAKpB;IAHC,SAAS,EAAE;IACX,cAAc,EAAE;IAChB,IAAI,CAAC,GAAG,EAAE,CAAC,WAAW,CAAC;8BAChB,WAAW;gDAAC;AAGtB,MAAM,UAAU,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAC3D,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,EAAE,WAAW,CAAC,CAAC;AACnD,MAAM,MAAM,GAAG,UAAU,CAAC,SAAS,EAAE,iBAAiB,CAAC,CAAC;AAExD,MAAM,CAAC,MAAM,cAAc,GAAoB;IAC7C,IAAI,EAAE,MAAM,CAAC,QAAQ,CAAC,IAAI;IAC1B,IAAI,EAAE,MAAM,CAAC,QAAQ,CAAC,IAAI;IAC1B,QAAQ,EAAE,MAAM,CAAC,QAAQ,CAAC,QAAQ;IAClC,QAAQ,EAAE,MAAM,CAAC,QAAQ,CAAC,QAAQ;IAClC,QAAQ,EAAE,MAAM,CAAC,QAAQ,CAAC,QAAQ;IAClC,WAAW,EAAE,IAAI;IACjB,GAAG,EAAE,MAAM,CAAC,QAAQ,CAAC,GAAG;CACzB,CAAC;AAEF,MAAM,CAAC,MAAM,WAAW,GAAiB;IACvC,GAAG,EAAE,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,MAAM,MAAM,CAAC,KAAK,CAAC,IAAI,IAAI,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE;IACjF,SAAS,EAAE;QACT,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,MAAM;QAC3B,SAAS,EAAE,MAAM,CAAC,KAAK,CAAC,QAAQ;QAChC,WAAW,EAAE,MAAM,CAAC,KAAK,CAAC,QAAQ;KACnC;CACF,CAAC;AAEF,MAAM,CAAC,MAAM,WAAW,GAAiB;IACvC,IAAI,EAAE,MAAM,CAAC,KAAK,CAAC,IAAI;IACvB,IAAI,EAAE,MAAM,CAAC,KAAK,CAAC,IAAI;IACvB,QAAQ,EAAE,MAAM,CAAC,KAAK,CAAC,QAAQ;IAC/B,QAAQ,EAAE,MAAM,CAAC,KAAK,CAAC,QAAQ;IAC/B,EAAE,EAAE,MAAM,CAAC,KAAK,CAAC,OAAO;IACxB,SAAS,EAAE,MAAM,CAAC,KAAK,CAAC,SAAS;CAClC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"database-health.int.spec.d.ts","sourceRoot":"","sources":["../../../src/test/int/database-health.int.spec.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { describe, it, expect, beforeAll, afterAll } from '@jest/globals';
|
|
2
|
+
import { Neo4jProvider, PostgresProvider, RedisProvider } from '@volontariapp/bridge';
|
|
3
|
+
import { DatabaseHealthOrchestrator, Neo4jBridgeHealthProvider, PostgresBridgeHealthProvider, RedisBridgeHealthProvider, } from '../../index.js';
|
|
4
|
+
import { neo4jConfig, postgresConfig, redisConfig } from './config.example.js';
|
|
5
|
+
describe('Database health (Integration)', () => {
|
|
6
|
+
let postgresProvider;
|
|
7
|
+
let neo4jProvider;
|
|
8
|
+
let redisProvider;
|
|
9
|
+
beforeAll(async () => {
|
|
10
|
+
postgresProvider = new PostgresProvider(postgresConfig);
|
|
11
|
+
neo4jProvider = new Neo4jProvider(neo4jConfig);
|
|
12
|
+
redisProvider = new RedisProvider(redisConfig);
|
|
13
|
+
await postgresProvider.connect();
|
|
14
|
+
await neo4jProvider.connect();
|
|
15
|
+
await redisProvider.connect();
|
|
16
|
+
});
|
|
17
|
+
afterAll(async () => {
|
|
18
|
+
if (postgresProvider.isConnected()) {
|
|
19
|
+
await postgresProvider.disconnect();
|
|
20
|
+
}
|
|
21
|
+
if (neo4jProvider.isConnected()) {
|
|
22
|
+
await neo4jProvider.disconnect();
|
|
23
|
+
}
|
|
24
|
+
if (redisProvider.isConnected()) {
|
|
25
|
+
await redisProvider.disconnect();
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
it('should report postgres, neo4j and redis as healthy', async () => {
|
|
29
|
+
const orchestrator = new DatabaseHealthOrchestrator([
|
|
30
|
+
new PostgresBridgeHealthProvider(postgresProvider),
|
|
31
|
+
new Neo4jBridgeHealthProvider(neo4jProvider),
|
|
32
|
+
new RedisBridgeHealthProvider(redisProvider),
|
|
33
|
+
]);
|
|
34
|
+
const result = await orchestrator.run();
|
|
35
|
+
expect(result.status).toBe('ok');
|
|
36
|
+
expect(result.checks).toHaveLength(3);
|
|
37
|
+
expect(result.checks.find((check) => check.name === 'postgres')?.status).toBe('up');
|
|
38
|
+
expect(result.checks.find((check) => check.name === 'neo4j')?.status).toBe('up');
|
|
39
|
+
expect(result.checks.find((check) => check.name === 'redis')?.status).toBe('up');
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
//# sourceMappingURL=database-health.int.spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"database-health.int.spec.js","sourceRoot":"","sources":["../../../src/test/int/database-health.int.spec.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAC1E,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACtF,OAAO,EACL,0BAA0B,EAC1B,yBAAyB,EACzB,4BAA4B,EAC5B,yBAAyB,GAC1B,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAE/E,QAAQ,CAAC,+BAA+B,EAAE,GAAG,EAAE;IAC7C,IAAI,gBAAkC,CAAC;IACvC,IAAI,aAA4B,CAAC;IACjC,IAAI,aAA4B,CAAC;IAEjC,SAAS,CAAC,KAAK,IAAI,EAAE;QACnB,gBAAgB,GAAG,IAAI,gBAAgB,CAAC,cAAc,CAAC,CAAC;QACxD,aAAa,GAAG,IAAI,aAAa,CAAC,WAAW,CAAC,CAAC;QAC/C,aAAa,GAAG,IAAI,aAAa,CAAC,WAAW,CAAC,CAAC;QAE/C,MAAM,gBAAgB,CAAC,OAAO,EAAE,CAAC;QACjC,MAAM,aAAa,CAAC,OAAO,EAAE,CAAC;QAC9B,MAAM,aAAa,CAAC,OAAO,EAAE,CAAC;IAChC,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,KAAK,IAAI,EAAE;QAClB,IAAI,gBAAgB,CAAC,WAAW,EAAE,EAAE,CAAC;YACnC,MAAM,gBAAgB,CAAC,UAAU,EAAE,CAAC;QACtC,CAAC;QAED,IAAI,aAAa,CAAC,WAAW,EAAE,EAAE,CAAC;YAChC,MAAM,aAAa,CAAC,UAAU,EAAE,CAAC;QACnC,CAAC;QAED,IAAI,aAAa,CAAC,WAAW,EAAE,EAAE,CAAC;YAChC,MAAM,aAAa,CAAC,UAAU,EAAE,CAAC;QACnC,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oDAAoD,EAAE,KAAK,IAAI,EAAE;QAClE,MAAM,YAAY,GAAG,IAAI,0BAA0B,CAAC;YAClD,IAAI,4BAA4B,CAAC,gBAAgB,CAAC;YAClD,IAAI,yBAAyB,CAAC,aAAa,CAAC;YAC5C,IAAI,yBAAyB,CAAC,aAAa,CAAC;SAC7C,CAAC,CAAC;QAEH,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,GAAG,EAAE,CAAC;QAExC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACjC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QACtC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,UAAU,CAAC,EAAE,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACpF,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,OAAO,CAAC,EAAE,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACjF,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,OAAO,CAAC,EAAE,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACnF,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"database-health.unit.spec.d.ts","sourceRoot":"","sources":["../../../src/test/unit/database-health.unit.spec.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { describe, expect, it } from '@jest/globals';
|
|
2
|
+
import { DatabaseHealthError } from '@volontariapp/errors';
|
|
3
|
+
import { AbstractDatabaseHealthProvider, DatabaseHealthOrchestrator, } from '../../index.js';
|
|
4
|
+
class TestProvider extends AbstractDatabaseHealthProvider {
|
|
5
|
+
pingFn;
|
|
6
|
+
constructor(name, pingFn) {
|
|
7
|
+
super(name, {});
|
|
8
|
+
this.pingFn = pingFn;
|
|
9
|
+
}
|
|
10
|
+
async pingDb() {
|
|
11
|
+
await this.pingFn();
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
describe('Database health core', () => {
|
|
15
|
+
it('returns up when ping succeeds', async () => {
|
|
16
|
+
const provider = new TestProvider('postgres', async () => Promise.resolve());
|
|
17
|
+
await expect(provider.health()).resolves.toEqual({
|
|
18
|
+
name: 'postgres',
|
|
19
|
+
status: 'up',
|
|
20
|
+
message: 'postgres connection is healthy',
|
|
21
|
+
});
|
|
22
|
+
});
|
|
23
|
+
it('normalizes error when ping fails', async () => {
|
|
24
|
+
const provider = new TestProvider('redis', () => Promise.reject(new Error('boom')));
|
|
25
|
+
const result = await provider.health();
|
|
26
|
+
expect(result).toMatchObject({
|
|
27
|
+
name: 'redis',
|
|
28
|
+
status: 'down',
|
|
29
|
+
message: 'redis connection failed',
|
|
30
|
+
});
|
|
31
|
+
expect(result.error).toBeInstanceOf(DatabaseHealthError);
|
|
32
|
+
expect(result.error).toMatchObject({
|
|
33
|
+
name: 'DatabaseHealthError',
|
|
34
|
+
message: 'boom',
|
|
35
|
+
code: 'DATABASE_HEALTH_ERROR',
|
|
36
|
+
details: {
|
|
37
|
+
causeName: 'Error',
|
|
38
|
+
},
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
it('aggregates providers status in orchestrator', async () => {
|
|
42
|
+
const healthyProvider = new TestProvider('postgres', async () => Promise.resolve());
|
|
43
|
+
const failingProvider = new TestProvider('neo4j', () => Promise.reject(new Error('neo4j unavailable')));
|
|
44
|
+
const orchestrator = new DatabaseHealthOrchestrator([healthyProvider, failingProvider]);
|
|
45
|
+
const result = await orchestrator.run();
|
|
46
|
+
expect(result.status).toBe('error');
|
|
47
|
+
expect(result.checks).toHaveLength(2);
|
|
48
|
+
expect(result.checks.find((check) => check.name === 'postgres')?.status).toBe('up');
|
|
49
|
+
expect(result.checks.find((check) => check.name === 'neo4j')?.status).toBe('down');
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
//# sourceMappingURL=database-health.unit.spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"database-health.unit.spec.js","sourceRoot":"","sources":["../../../src/test/unit/database-health.unit.spec.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@volontariapp/health-check",
|
|
3
|
+
"version": "0.0.0-snap-398faec",
|
|
4
|
+
"publishConfig": {
|
|
5
|
+
"access": "public",
|
|
6
|
+
"provenance": true
|
|
7
|
+
},
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+https://github.com/Volontariapp/npm-packages.git"
|
|
11
|
+
},
|
|
12
|
+
"description": "",
|
|
13
|
+
"license": "UNLICENSED",
|
|
14
|
+
"type": "module",
|
|
15
|
+
"main": "./dist/index.js",
|
|
16
|
+
"types": "./dist/index.d.ts",
|
|
17
|
+
"exports": {
|
|
18
|
+
".": {
|
|
19
|
+
"types": "./dist/index.d.ts",
|
|
20
|
+
"import": "./dist/index.js"
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
"files": [
|
|
24
|
+
"dist"
|
|
25
|
+
],
|
|
26
|
+
"engines": {
|
|
27
|
+
"node": ">=24.14.0"
|
|
28
|
+
},
|
|
29
|
+
"scripts": {
|
|
30
|
+
"build": "tsc -p tsconfig.json",
|
|
31
|
+
"lint": "eslint src/",
|
|
32
|
+
"test": "node --experimental-vm-modules $(yarn bin jest)",
|
|
33
|
+
"test:coverage": "node --experimental-vm-modules $(yarn bin jest) --coverage --coverageReporters=\"text\" --coverageReporters=\"json-summary\" --coverageReporters=\"lcov\"",
|
|
34
|
+
"test:watch": "node --experimental-vm-modules $(yarn bin jest) --watch"
|
|
35
|
+
},
|
|
36
|
+
"devDependencies": {
|
|
37
|
+
"@jest/globals": "^30.3.0",
|
|
38
|
+
"@types/jest": "^30.0.0",
|
|
39
|
+
"eslint": "9.18.0",
|
|
40
|
+
"jest": "^30.3.0",
|
|
41
|
+
"ts-jest": "^29.4.9",
|
|
42
|
+
"ts-node": "^10.9.2",
|
|
43
|
+
"typescript": "5.7.3"
|
|
44
|
+
},
|
|
45
|
+
"dependencies": {
|
|
46
|
+
"@volontariapp/bridge": "0.0.0-snap-398faec",
|
|
47
|
+
"@volontariapp/config": "0.0.0-snap-398faec",
|
|
48
|
+
"@volontariapp/errors": "0.4.4"
|
|
49
|
+
}
|
|
50
|
+
}
|