@pulse-si/nest 0.0.0-stage → 0.0.1
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/LICENSE +21 -0
- package/README.md +173 -2
- package/dist/index.d.ts +4 -0
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -0
- package/dist/pulse.module.d.ts +5 -0
- package/dist/pulse.module.js +30 -0
- package/dist/pulse.module.js.map +1 -0
- package/dist/pulse.options.d.ts +6 -0
- package/dist/pulse.options.js +5 -0
- package/dist/pulse.options.js.map +1 -0
- package/dist/pulse.service.d.ts +18 -0
- package/dist/pulse.service.js +95 -0
- package/dist/pulse.service.js.map +1 -0
- package/package.json +54 -3
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Charles Désiré Bally
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,174 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @pulse-si/nest
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Ton app NestJS surveillée par [Pulse](https://pulse-app.si), sur ton iPhone et ton Mac. Tu branches le module, Pulse trouve tout seul ta base, ton Redis, tes files BullMQ et tes crons, et te prévient dès que quelque chose cloche.
|
|
4
|
+
|
|
5
|
+
```
|
|
6
|
+
ton app NestJS ton iPhone, ton Mac
|
|
7
|
+
┌─────────────────────────┐ HTTPS ┌──────────┐ ┌──────────────┐
|
|
8
|
+
│ PulseModule │ ──────────────────▶ │ Pulse │ ────▶ │ app Pulse │
|
|
9
|
+
│ ├ PostgreSQL SELECT 1 │ état, tâches, │ (API) │ push │ alertes, │
|
|
10
|
+
│ ├ Redis PING │ journaux │ │ ◀──── │ journaux, │
|
|
11
|
+
│ ├ BullMQ compteurs│ (chiffrés si tu │ │ SSE │ en direct │
|
|
12
|
+
│ └ crons passages │ le veux) └──────────┘ └──────────────┘
|
|
13
|
+
└─────────────────────────┘
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## En deux minutes
|
|
17
|
+
|
|
18
|
+
À la racine du projet, avec la clé que l'app Pulse t'affiche quand tu ajoutes une app :
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
npx @pulse-si/init pk_live_…
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
La commande installe `@pulse-si/nest`, écrit la clé dans `.env` (en lecture pour toi seul, et ajouté au `.gitignore`), branche le module dans `app.module.ts`, puis te demande ce que tu veux envoyer. Relance ton app : le premier signal arrive dans Pulse dans les secondes qui suivent.
|
|
25
|
+
|
|
26
|
+
### Ou à la main
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
npm install @pulse-si/nest
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
```ts
|
|
33
|
+
import { PulseModule } from '@pulse-si/nest';
|
|
34
|
+
|
|
35
|
+
@Module({
|
|
36
|
+
imports: [ConfigModule.forRoot(), PulseModule.forRoot()],
|
|
37
|
+
})
|
|
38
|
+
export class AppModule {}
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
`PULSE_KEY` doit se trouver dans `process.env`, par `@nestjs/config` ou avec `node --env-file=.env`.
|
|
42
|
+
|
|
43
|
+
## Ce que Pulse surveille
|
|
44
|
+
|
|
45
|
+
| Dépendance trouvée | Ce que Pulse fait | Nom affiché |
|
|
46
|
+
|---|---|---|
|
|
47
|
+
| Prisma (PostgreSQL, MySQL, SQL Server, SQLite) | `SELECT 1` | PostgreSQL, MySQL… |
|
|
48
|
+
| Prisma MongoDB, Mongoose | `ping` | MongoDB |
|
|
49
|
+
| TypeORM | `SELECT 1` | selon le moteur |
|
|
50
|
+
| ioredis, node-redis | `PING` | Redis |
|
|
51
|
+
| BullMQ | lit le nombre de tâches en attente | File emails, File factures… |
|
|
52
|
+
| `@nestjs/schedule` | planning, dernier et prochain passage | le nom du cron |
|
|
53
|
+
|
|
54
|
+
Chaque contrôle a 5 secondes pour répondre et ne fait que lire. Une dépendance en échec, une tâche qui a planté ou qui a sauté son passage de plus de 5 minutes, et l'app passe en « dégradée » dans Pulse avec une notification qui dit quoi.
|
|
55
|
+
|
|
56
|
+
Pour qu'un cron en échec remonte (NestJS ne sait que quand il a tourné, pas s'il a réussi), enveloppe son travail :
|
|
57
|
+
|
|
58
|
+
```ts
|
|
59
|
+
constructor(private readonly pulse: PulseService) {}
|
|
60
|
+
|
|
61
|
+
@Cron('0 * * * *', { name: 'relance-abonnements' })
|
|
62
|
+
relance() {
|
|
63
|
+
return this.pulse.track('relance-abonnements', () => this.abonnements.relancer());
|
|
64
|
+
}
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Choisir ce qui part
|
|
68
|
+
|
|
69
|
+
Tu décides de ce que ton app raconte à Pulse. Le signal de vie part toujours, le reste se règle :
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
# Seulement l'état des dépendances et les journaux, pas les crons ni les versions
|
|
73
|
+
PULSE_SEND=checks,logs
|
|
74
|
+
|
|
75
|
+
# Ignorer certaines instances ou certaines tâches (* sert de joker)
|
|
76
|
+
PULSE_EXCLUDE=File emails,nettoyage-*
|
|
77
|
+
|
|
78
|
+
# Ou au contraire, ne suivre que celles-ci
|
|
79
|
+
PULSE_INCLUDE=PostgreSQL,Redis,relance-abonnements
|
|
80
|
+
|
|
81
|
+
# Journaux : seulement les avertissements et les erreurs
|
|
82
|
+
PULSE_LOG_LEVEL=WARN
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Les mêmes réglages existent dans le code, ils passent avant les variables :
|
|
86
|
+
|
|
87
|
+
```ts
|
|
88
|
+
PulseModule.forRoot({
|
|
89
|
+
send: ['checks', 'crons', 'logs'],
|
|
90
|
+
exclude: ['File emails'],
|
|
91
|
+
logLevel: 'WARN',
|
|
92
|
+
probes: [httpProbe('Route /health', 'http://localhost:3000/health')],
|
|
93
|
+
});
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## Journaux et mode direct (Pro et Team)
|
|
97
|
+
|
|
98
|
+
Pulse recopie ce que ton app écrit (logger de NestJS, pino, `console`) sans rien changer à ce que tu vois dans ton terminal. Le niveau et le contexte sont reconnus (`[PaymentsService]`), les couleurs retirées, et les secrets masqués avant de partir (`token=***`, `Bearer ***`, identifiants dans les URL de connexion).
|
|
99
|
+
|
|
100
|
+
```
|
|
101
|
+
[Nest] 4120 - 20/10/2026 12:12:56 ERROR [PaymentsService] Paiement refusé token=abc123
|
|
102
|
+
│
|
|
103
|
+
▼ dans l'app Pulse
|
|
104
|
+
ERROR PaymentsService Paiement refusé token=***
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
Quand tu ouvres l'app dans Pulse, le serveur prévient le package qu'on le regarde : l'état part toutes les 5 secondes et les journaux chaque seconde, puis tout revient au calme 30 secondes après que tu as quitté l'écran. Les journaux sont gardés 3 jours en Pro et 7 jours en Team. Sans journaux dans ton offre, rien n'est capturé : ton app ne paie aucun surcoût.
|
|
108
|
+
|
|
109
|
+
## Mode sécurisé : Pulse ne peut rien lire
|
|
110
|
+
|
|
111
|
+
C'est l'option pour qui ne veut confier ses données à personne, nous compris. Ton iPhone ou ton Mac fabrique une paire de clés. La clé publique va dans ton `.env`, la clé privée ne quitte jamais tes appareils.
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
PULSE_PUBLIC_KEY=pulse_pub_… # copiée depuis l'app, Réglages de l'app > Mode sécurisé
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
```
|
|
118
|
+
ton app ──── rapport chiffré (HPKE, X25519 + AES-256-GCM) ────▶ Pulse ──▶ ton iPhone
|
|
119
|
+
│ │
|
|
120
|
+
garde un paquet ouvre avec
|
|
121
|
+
qu'il ne sait pas la clé privée
|
|
122
|
+
ouvrir du trousseau
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
Un serveur qui ne lit rien ne peut pas alerter. C'est pour ça qu'un petit résumé reste en clair par défaut : « tout va bien » ou « 2 soucis », sans nom ni message. La notification dit alors simplement « 2 soucis signalés, le détail est chiffré ». Tu peux en laisser plus, ou rien du tout :
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
PULSE_CLEAR=status # par défaut : un booléen et un nombre
|
|
129
|
+
PULSE_CLEAR=status,checks # Pulse peut dire « Redis ne répond plus »
|
|
130
|
+
PULSE_CLEAR=none # silence complet : Pulse ne sait plus que si l'app est en vie
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
Une fois le mode actif, Pulse refuse tout rapport en clair : un `.env` oublié ne fuit pas.
|
|
134
|
+
|
|
135
|
+
## Sécurité, en clair
|
|
136
|
+
|
|
137
|
+
- **Ton app d'abord.** Le package ne lève jamais d'erreur. Pulse injoignable : un seul avertissement, ton app continue. Clé refusée : les envois s'arrêtent.
|
|
138
|
+
- **Rien n'est écrit chez toi.** Les contrôles ne font que lire (`SELECT 1`, `PING`), avec 5 secondes au plus.
|
|
139
|
+
- **Rien de superflu ne part.** Ni requête, ni donnée métier, ni variable d'environnement. Les messages d'erreur sont nettoyés et coupés à 300 caractères.
|
|
140
|
+
- **La clé ne voyage qu'en HTTPS**, dans un en-tête, jamais dans une URL. Elle ne sert qu'à écrire l'état de cette app : elle n'ouvre pas ton compte. Tu peux la remplacer depuis l'app à tout moment.
|
|
141
|
+
- **Aucune dépendance** en dehors de `@pulse-si/core`, qui n'utilise que la bibliothèque standard de Node.
|
|
142
|
+
|
|
143
|
+
## Variables
|
|
144
|
+
|
|
145
|
+
| Variable | Défaut | Rôle |
|
|
146
|
+
|---|---|---|
|
|
147
|
+
| `PULSE_KEY` | (obligatoire) | clé de l'app : `pk_live_…` en production, `pk_test_…` en staging |
|
|
148
|
+
| `PULSE_SEND` | `checks,crons,logs,versions` | ce qui part en plus du signal de vie |
|
|
149
|
+
| `PULSE_INCLUDE` | (tout) | seuls ces contrôles et tâches, noms séparés par des virgules, `*` permis |
|
|
150
|
+
| `PULSE_EXCLUDE` | (rien) | contrôles et tâches ignorés |
|
|
151
|
+
| `PULSE_LOG_LEVEL` | `DEBUG` | niveau minimal des journaux envoyés |
|
|
152
|
+
| `PULSE_LOGS` | `true` | `false` coupe les journaux |
|
|
153
|
+
| `PULSE_PUBLIC_KEY` | (aucune) | active le mode sécurisé |
|
|
154
|
+
| `PULSE_CLEAR` | `status` | en mode sécurisé, ce qui reste lisible par Pulse |
|
|
155
|
+
| `PULSE_ENDPOINT` | `https://api.pulse-app.si` | ton Pulse Relay en mode VPS perso (Team), par exemple `https://relais.kalao.ci` |
|
|
156
|
+
| `PULSE_RELAY_FINGERPRINT` | (aucune) | empreinte du certificat d'un relais sans domaine : rien ne part si elle ne correspond pas |
|
|
157
|
+
| `PULSE_APP_VERSION` | version du `package.json` | version affichée dans Pulse |
|
|
158
|
+
| `PULSE_DISABLED` | `false` | `true` coupe tout (tests, CI) |
|
|
159
|
+
|
|
160
|
+
## Si rien n'arrive
|
|
161
|
+
|
|
162
|
+
| Message | Ce qu'il faut faire |
|
|
163
|
+
|---|---|
|
|
164
|
+
| `PULSE_KEY absente` | la variable n'est pas chargée : vérifie `@nestjs/config` ou `--env-file` |
|
|
165
|
+
| `Clé Pulse refusée` | la clé a été remplacée dans l'app : recopie la nouvelle |
|
|
166
|
+
| `Mode sécurisé actif pour cette app` | ajoute `PULSE_PUBLIC_KEY` |
|
|
167
|
+
| `PULSE_PUBLIC_KEY ne correspond plus` | la clé a changé sur ton téléphone : recopie la clé publique |
|
|
168
|
+
| `Pulse injoignable` | réseau ou pare-feu : l'app continue, les envois reprennent seuls |
|
|
169
|
+
|
|
170
|
+
Le rythme des rapports suit celui de l'app dans Pulse (30 secondes en Pro, 5 minutes en Gratuit).
|
|
171
|
+
|
|
172
|
+
## Licence
|
|
173
|
+
|
|
174
|
+
MIT
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PulseService = exports.PulseModule = exports.httpProbe = void 0;
|
|
4
|
+
var core_1 = require("@pulse-si/core");
|
|
5
|
+
Object.defineProperty(exports, "httpProbe", { enumerable: true, get: function () { return core_1.httpProbe; } });
|
|
6
|
+
var pulse_module_1 = require("./pulse.module");
|
|
7
|
+
Object.defineProperty(exports, "PulseModule", { enumerable: true, get: function () { return pulse_module_1.PulseModule; } });
|
|
8
|
+
var pulse_service_1 = require("./pulse.service");
|
|
9
|
+
Object.defineProperty(exports, "PulseService", { enumerable: true, get: function () { return pulse_service_1.PulseService; } });
|
|
10
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,uCAAuD;AAA9C,iGAAA,SAAS,OAAA;AAClB,+CAA6C;AAApC,2GAAA,WAAW,OAAA;AAEpB,iDAA+C;AAAtC,6GAAA,YAAY,OAAA"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
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;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var PulseModule_1;
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.PulseModule = void 0;
|
|
11
|
+
const common_1 = require("@nestjs/common");
|
|
12
|
+
const core_1 = require("@nestjs/core");
|
|
13
|
+
const pulse_options_1 = require("./pulse.options");
|
|
14
|
+
const pulse_service_1 = require("./pulse.service");
|
|
15
|
+
let PulseModule = PulseModule_1 = class PulseModule {
|
|
16
|
+
static forRoot(options = {}) {
|
|
17
|
+
return {
|
|
18
|
+
module: PulseModule_1,
|
|
19
|
+
global: true,
|
|
20
|
+
imports: [core_1.DiscoveryModule],
|
|
21
|
+
providers: [{ provide: pulse_options_1.PULSE_OPTIONS, useValue: options }, pulse_service_1.PulseService],
|
|
22
|
+
exports: [pulse_service_1.PulseService],
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
exports.PulseModule = PulseModule;
|
|
27
|
+
exports.PulseModule = PulseModule = PulseModule_1 = __decorate([
|
|
28
|
+
(0, common_1.Module)({})
|
|
29
|
+
], PulseModule);
|
|
30
|
+
//# sourceMappingURL=pulse.module.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pulse.module.js","sourceRoot":"","sources":["../src/pulse.module.ts"],"names":[],"mappings":";;;;;;;;;;AAAA,2CAA4D;AAC5D,uCAA+C;AAC/C,mDAAuE;AACvE,mDAA+C;AAGxC,IAAM,WAAW,mBAAjB,MAAM,WAAW;IACtB,MAAM,CAAC,OAAO,CAAC,UAA4B,EAAE;QAC3C,OAAO;YACL,MAAM,EAAE,aAAW;YACnB,MAAM,EAAE,IAAI;YACZ,OAAO,EAAE,CAAC,sBAAe,CAAC;YAC1B,SAAS,EAAE,CAAC,EAAE,OAAO,EAAE,6BAAa,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,4BAAY,CAAC;YACxE,OAAO,EAAE,CAAC,4BAAY,CAAC;SACxB,CAAC;IACJ,CAAC;CACF,CAAA;AAVY,kCAAW;sBAAX,WAAW;IADvB,IAAA,eAAM,EAAC,EAAE,CAAC;GACE,WAAW,CAUvB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pulse.options.js","sourceRoot":"","sources":["../src/pulse.options.ts"],"names":[],"mappings":";;;AAEa,QAAA,aAAa,GAAG,MAAM,CAAC,eAAe,CAAC,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { type OnApplicationBootstrap, type OnApplicationShutdown } from '@nestjs/common';
|
|
2
|
+
import { DiscoveryService, ModuleRef } from '@nestjs/core';
|
|
3
|
+
import { PulseReporter, type Probe } from '@pulse-si/core';
|
|
4
|
+
import { type PulseNestOptions } from './pulse.options';
|
|
5
|
+
export declare class PulseService implements OnApplicationBootstrap, OnApplicationShutdown {
|
|
6
|
+
private readonly options;
|
|
7
|
+
private readonly discovery;
|
|
8
|
+
private readonly moduleRef;
|
|
9
|
+
private readonly logger;
|
|
10
|
+
readonly reporter: PulseReporter;
|
|
11
|
+
constructor(options: PulseNestOptions, discovery: DiscoveryService, moduleRef: ModuleRef);
|
|
12
|
+
onApplicationBootstrap(): void;
|
|
13
|
+
onApplicationShutdown(): void;
|
|
14
|
+
addProbe(probe: Probe): void;
|
|
15
|
+
track<T>(cronName: string, task: () => Promise<T>): Promise<T>;
|
|
16
|
+
private watchCrons;
|
|
17
|
+
private schedulerRegistry;
|
|
18
|
+
}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
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;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
12
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.PulseService = void 0;
|
|
16
|
+
const node_path_1 = require("node:path");
|
|
17
|
+
const common_1 = require("@nestjs/common");
|
|
18
|
+
const core_1 = require("@nestjs/core");
|
|
19
|
+
const core_2 = require("@pulse-si/core");
|
|
20
|
+
const pulse_options_1 = require("./pulse.options");
|
|
21
|
+
let PulseService = class PulseService {
|
|
22
|
+
options;
|
|
23
|
+
discovery;
|
|
24
|
+
moduleRef;
|
|
25
|
+
logger = new common_1.Logger('Pulse');
|
|
26
|
+
reporter;
|
|
27
|
+
constructor(options, discovery, moduleRef) {
|
|
28
|
+
this.options = options;
|
|
29
|
+
this.discovery = discovery;
|
|
30
|
+
this.moduleRef = moduleRef;
|
|
31
|
+
this.reporter = new core_2.PulseReporter({
|
|
32
|
+
packageName: 'pulse-nest',
|
|
33
|
+
packageVersion: (0, core_2.ownVersion)((0, node_path_1.join)(__dirname, '..')),
|
|
34
|
+
framework: 'nestjs',
|
|
35
|
+
frameworkVersion: (0, core_2.installedVersion)('@nestjs/core', __dirname),
|
|
36
|
+
}, {
|
|
37
|
+
logger: { warn: (m) => this.logger.warn(m), error: (m) => this.logger.error(m) },
|
|
38
|
+
...options,
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
onApplicationBootstrap() {
|
|
42
|
+
if (!this.reporter.enabled)
|
|
43
|
+
return;
|
|
44
|
+
for (const probe of this.options.probes ?? [])
|
|
45
|
+
this.reporter.addProbe(probe);
|
|
46
|
+
if (this.options.autoDetect !== false) {
|
|
47
|
+
const instances = this.discovery.getProviders().map((wrapper) => wrapper.instance);
|
|
48
|
+
for (const probe of (0, core_2.detectProbes)(instances))
|
|
49
|
+
this.reporter.addProbe(probe);
|
|
50
|
+
this.watchCrons();
|
|
51
|
+
}
|
|
52
|
+
this.reporter.start();
|
|
53
|
+
}
|
|
54
|
+
onApplicationShutdown() {
|
|
55
|
+
this.reporter.stop();
|
|
56
|
+
}
|
|
57
|
+
addProbe(probe) {
|
|
58
|
+
this.reporter.addProbe(probe);
|
|
59
|
+
}
|
|
60
|
+
async track(cronName, task) {
|
|
61
|
+
try {
|
|
62
|
+
const result = await task();
|
|
63
|
+
this.reporter.recordCronRun(cronName, true);
|
|
64
|
+
return result;
|
|
65
|
+
}
|
|
66
|
+
catch (error) {
|
|
67
|
+
this.reporter.recordCronRun(cronName, false, error);
|
|
68
|
+
throw error;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
watchCrons() {
|
|
72
|
+
const registry = this.schedulerRegistry();
|
|
73
|
+
if (registry)
|
|
74
|
+
this.reporter.addCronSource(() => (0, core_2.cronSnapshots)(registry.getCronJobs()));
|
|
75
|
+
}
|
|
76
|
+
schedulerRegistry() {
|
|
77
|
+
try {
|
|
78
|
+
const schedule = require('@nestjs/schedule');
|
|
79
|
+
return this.moduleRef.get(schedule.SchedulerRegistry, {
|
|
80
|
+
strict: false,
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
catch {
|
|
84
|
+
return null;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
exports.PulseService = PulseService;
|
|
89
|
+
exports.PulseService = PulseService = __decorate([
|
|
90
|
+
(0, common_1.Injectable)(),
|
|
91
|
+
__param(0, (0, common_1.Inject)(pulse_options_1.PULSE_OPTIONS)),
|
|
92
|
+
__metadata("design:paramtypes", [Object, core_1.DiscoveryService,
|
|
93
|
+
core_1.ModuleRef])
|
|
94
|
+
], PulseService);
|
|
95
|
+
//# sourceMappingURL=pulse.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pulse.service.js","sourceRoot":"","sources":["../src/pulse.service.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,57 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pulse-si/nest",
|
|
3
|
-
"version": "0.0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "Surveillance Pulse pour NestJS : signal de vie, base de données, Redis, files et tâches planifiées détectés tout seuls.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"files": [
|
|
9
|
+
"dist"
|
|
10
|
+
],
|
|
11
|
+
"engines": {
|
|
12
|
+
"node": ">=18.17"
|
|
13
|
+
},
|
|
14
|
+
"homepage": "https://pulse-app.si",
|
|
15
|
+
"jest": {
|
|
16
|
+
"rootDir": "src",
|
|
17
|
+
"testRegex": ".*\\.spec\\.ts$",
|
|
18
|
+
"transform": {
|
|
19
|
+
"^.+\\.ts$": "ts-jest"
|
|
20
|
+
},
|
|
21
|
+
"testEnvironment": "node"
|
|
22
|
+
},
|
|
23
|
+
"devDependencies": {
|
|
24
|
+
"@eslint/js": "^9.39.5",
|
|
25
|
+
"@types/jest": "^30.0.0",
|
|
26
|
+
"@types/node": "^22.20.5",
|
|
27
|
+
"eslint": "^9.39.5",
|
|
28
|
+
"eslint-config-prettier": "^10.1.8",
|
|
29
|
+
"globals": "^17.13.0",
|
|
30
|
+
"jest": "^30.5.2",
|
|
31
|
+
"ts-jest": "^29.4.15",
|
|
32
|
+
"typescript": "~5.9.3",
|
|
33
|
+
"typescript-eslint": "^8.71.2",
|
|
34
|
+
"@nestjs/common": "^11.2.7",
|
|
35
|
+
"@nestjs/core": "^11.2.7",
|
|
36
|
+
"@nestjs/testing": "^11.2.7",
|
|
37
|
+
"@nestjs/schedule": "^6.0.1",
|
|
38
|
+
"reflect-metadata": "^0.2.2",
|
|
39
|
+
"rxjs": "^7.8.2"
|
|
40
|
+
},
|
|
41
|
+
"dependencies": {
|
|
42
|
+
"@pulse-si/core": "^0.0.1"
|
|
43
|
+
},
|
|
44
|
+
"peerDependencies": {
|
|
45
|
+
"@nestjs/common": ">=10 <13",
|
|
46
|
+
"@nestjs/core": ">=10 <13",
|
|
47
|
+
"reflect-metadata": "*",
|
|
48
|
+
"rxjs": "^7"
|
|
49
|
+
},
|
|
50
|
+
"peerDependenciesMeta": {},
|
|
51
|
+
"scripts": {
|
|
52
|
+
"build": "tsc -p tsconfig.build.json",
|
|
53
|
+
"typecheck": "tsc --noEmit",
|
|
54
|
+
"lint": "eslint \"src/**/*.ts\"",
|
|
55
|
+
"test": "jest"
|
|
56
|
+
}
|
|
6
57
|
}
|