@pulse-si/init 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 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,85 @@
1
- # Temporary Holding Version
1
+ # @pulse-si/init
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Relie un projet NestJS ou Next.js à [Pulse](https://pulse-app.si) en une commande. À lancer à la racine du projet, avec la clé que l'app Pulse t'affiche :
4
+
5
+ ```bash
6
+ npx @pulse-si/init pk_live_…
7
+ ```
8
+
9
+ ## Ce que ça donne
10
+
11
+ ```
12
+ $ npx @pulse-si/init pk_live_8f2a…
13
+ Projet NestJS détecté (pnpm).
14
+
15
+ Choisis ce que ton app envoie à Pulse. Le signal de vie part toujours.
16
+ Trouvé dans package.json : Prisma, Redis (ioredis), BullMQ, tâches planifiées.
17
+ L'état des dépendances (base, Redis, files) ? [O/n]
18
+ Les tâches planifiées ? [O/n]
19
+ Les journaux de l'app (Pro et Team) ? [O/n]
20
+ Les versions (app, framework, déploiement) ? [O/n] n
21
+ Contrôles ou tâches à ignorer (noms séparés par des virgules, * permis, vide pour aucun) : File emails
22
+ Niveau minimal des journaux (DEBUG, INFO, WARN, ERROR) [DEBUG] : INFO
23
+
24
+ Mode sécurisé (Pro et Team) : tout part chiffré, Pulse ne peut rien lire.
25
+ Clé publique pulse_pub_… affichée dans l'app (vide pour passer) : pulse_pub_Qm9u…
26
+ À laisser en clair pour garder les alertes (status, checks, crons, versions, none) [status] :
27
+ ✓ @pulse-si/nest installé
28
+ ✓ Clé ajoutée dans .env
29
+ ✓ Réglages écrits : PULSE_PUBLIC_KEY, PULSE_SEND, PULSE_EXCLUDE, PULSE_LOG_LEVEL
30
+ ✓ Mode sécurisé : les rapports et les journaux partent chiffrés
31
+ ✓ PulseModule branché dans src/app.module.ts
32
+ Relance ton app : le premier signal apparaît dans Pulse.
33
+ ```
34
+
35
+ Appuyer sur Entrée garde le choix proposé. Une réponse vide au mode sécurisé le laisse de côté : tu pourras l'activer plus tard depuis l'app.
36
+
37
+ ## Ce que la commande touche, et rien d'autre
38
+
39
+ ```
40
+ ton-projet/
41
+ ├── package.json + @pulse-si/nest ou @pulse-si/next (pnpm, yarn, bun ou npm, selon ton lockfile)
42
+ ├── .env ou .env.local + PULSE_KEY et tes réglages, droits 600
43
+ ├── .gitignore + .env si le fichier n'y était pas déjà
44
+ └── src/
45
+ ├── app.module.ts + PulseModule.forRoot() (NestJS)
46
+ └── instrumentation.ts créé s'il n'existe pas (Next.js)
47
+ ```
48
+
49
+ - Une ligne déjà présente est remplacée, jamais dupliquée : relancer la commande avec une nouvelle clé est sans risque.
50
+ - Un `instrumentation.ts` qui existe déjà n'est pas modifié : la commande affiche les lignes à ajouter.
51
+ - Des réglages faux (clé publique mal copiée, niveau inconnu) arrêtent tout avant la moindre écriture.
52
+
53
+ ## Sans questions
54
+
55
+ Pour un script ou une CI, passe les réglages en options (ou `--yes` pour garder les valeurs par défaut) :
56
+
57
+ ```bash
58
+ npx @pulse-si/init pk_live_… --yes
59
+ npx @pulse-si/init pk_live_… --send checks,crons --exclude "File *" --log-level WARN
60
+ npx @pulse-si/init pk_live_… --public-key pulse_pub_… --clear status,checks
61
+ ```
62
+
63
+ | Option | Rôle |
64
+ |---|---|
65
+ | `--dir <chemin>` | dossier du projet, si ce n'est pas le dossier courant |
66
+ | `--no-install` | n'installe pas le package |
67
+ | `--yes` | aucune question, réglages par défaut |
68
+ | `--send <liste>` | données envoyées : `checks`, `crons`, `logs`, `versions` |
69
+ | `--include <liste>` | seuls ces contrôles et tâches (`*` permis) |
70
+ | `--exclude <liste>` | contrôles et tâches ignorés |
71
+ | `--log-level <niveau>` | `DEBUG`, `INFO`, `WARN`, `ERROR` ou `FATAL` |
72
+ | `--public-key <clé>` | active le mode sécurisé |
73
+ | `--endpoint <adresse>` | ton Pulse Relay en mode VPS perso (Team) |
74
+ | `--fingerprint <empreinte>` | empreinte du certificat d'un relais sans domaine |
75
+ | `--clear <liste>` | en mode sécurisé, ce qui reste en clair : `status`, `checks`, `crons`, `versions` ou `none` |
76
+
77
+ ## Sécurité
78
+
79
+ - La clé n'est envoyée nulle part : la commande l'écrit dans ton projet, c'est tout. Aucun appel réseau en dehors de l'installation du package par ton gestionnaire.
80
+ - Le fichier d'environnement passe en lecture pour toi seul (`600`) et rejoint le `.gitignore` : la clé ne part pas dans git par accident.
81
+ - La clé publique du mode sécurisé ne permet que de chiffrer. La clé privée, celle qui ouvre les rapports, ne quitte jamais ton iPhone ou ton Mac.
82
+
83
+ ## Licence
84
+
85
+ MIT
package/dist/args.d.ts ADDED
@@ -0,0 +1,9 @@
1
+ import type { Settings } from './settings';
2
+ export type CliArgs = {
3
+ key?: string;
4
+ dir?: string;
5
+ install: boolean;
6
+ interactive: boolean;
7
+ settings: Settings;
8
+ };
9
+ export declare function parseArgs(args: string[]): CliArgs;
package/dist/args.js ADDED
@@ -0,0 +1,53 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parseArgs = parseArgs;
4
+ const VALUE_FLAGS = [
5
+ '--dir',
6
+ '--public-key',
7
+ '--clear',
8
+ '--send',
9
+ '--include',
10
+ '--exclude',
11
+ '--log-level',
12
+ '--endpoint',
13
+ '--fingerprint',
14
+ ];
15
+ const CONNECTION_FLAGS = ['--dir', '--endpoint', '--fingerprint'];
16
+ const list = (raw) => raw === undefined
17
+ ? undefined
18
+ : raw
19
+ .split(',')
20
+ .map((item) => item.trim())
21
+ .filter(Boolean);
22
+ function parseArgs(args) {
23
+ const values = new Map();
24
+ const positional = [];
25
+ for (let index = 0; index < args.length; index += 1) {
26
+ const arg = args[index];
27
+ if (VALUE_FLAGS.includes(arg)) {
28
+ values.set(arg, args[index + 1] ?? '');
29
+ index += 1;
30
+ }
31
+ else if (!arg.startsWith('--'))
32
+ positional.push(arg);
33
+ }
34
+ const settings = {
35
+ publicKey: values.get('--public-key'),
36
+ clear: list(values.get('--clear')),
37
+ send: list(values.get('--send')),
38
+ include: list(values.get('--include')),
39
+ exclude: list(values.get('--exclude')),
40
+ logLevel: values.get('--log-level'),
41
+ endpoint: values.get('--endpoint'),
42
+ fingerprint: values.get('--fingerprint'),
43
+ };
44
+ const customized = [...values.keys()].some((flag) => !CONNECTION_FLAGS.includes(flag));
45
+ return {
46
+ key: args.includes('--help') ? undefined : positional[0],
47
+ dir: values.get('--dir'),
48
+ install: !args.includes('--no-install'),
49
+ interactive: !args.includes('--yes') && !customized,
50
+ settings,
51
+ };
52
+ }
53
+ //# sourceMappingURL=args.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"args.js","sourceRoot":"","sources":["../src/args.ts"],"names":[],"mappings":";;AAiCA,8BA4BC;AAnDD,MAAM,WAAW,GAAG;IAClB,OAAO;IACP,cAAc;IACd,SAAS;IACT,QAAQ;IACR,WAAW;IACX,WAAW;IACX,aAAa;IACb,YAAY;IACZ,eAAe;CACP,CAAC;AAGX,MAAM,gBAAgB,GAAsB,CAAC,OAAO,EAAE,YAAY,EAAE,eAAe,CAAC,CAAC;AAErF,MAAM,IAAI,GAAG,CAAC,GAAuB,EAAE,EAAE,CACvC,GAAG,KAAK,SAAS;IACf,CAAC,CAAC,SAAS;IACX,CAAC,CAAC,GAAG;SACA,KAAK,CAAC,GAAG,CAAC;SACV,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;SAC1B,MAAM,CAAC,OAAO,CAAC,CAAC;AAEzB,SAAgB,SAAS,CAAC,IAAc;IACtC,MAAM,MAAM,GAAG,IAAI,GAAG,EAAkB,CAAC;IACzC,MAAM,UAAU,GAAa,EAAE,CAAC;IAChC,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,IAAI,CAAC,MAAM,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;QACpD,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAE,CAAC;QACzB,IAAK,WAAiC,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;YACrD,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;YACvC,KAAK,IAAI,CAAC,CAAC;QACb,CAAC;aAAM,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC;YAAE,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACzD,CAAC;IACD,MAAM,QAAQ,GAAa;QACzB,SAAS,EAAE,MAAM,CAAC,GAAG,CAAC,cAAc,CAAC;QACrC,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QAClC,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAChC,OAAO,EAAE,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;QACtC,OAAO,EAAE,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;QACtC,QAAQ,EAAE,MAAM,CAAC,GAAG,CAAC,aAAa,CAAC;QACnC,QAAQ,EAAE,MAAM,CAAC,GAAG,CAAC,YAAY,CAAC;QAClC,WAAW,EAAE,MAAM,CAAC,GAAG,CAAC,eAAe,CAAC;KACzC,CAAC;IACF,MAAM,UAAU,GAAG,CAAC,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,gBAAgB,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC;IACvF,OAAO;QACL,GAAG,EAAE,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC;QACxD,GAAG,EAAE,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC;QACxB,OAAO,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,cAAc,CAAC;QACvC,WAAW,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,UAAU;QACnD,QAAQ;KACT,CAAC;AACJ,CAAC"}
package/dist/cli.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/cli.js ADDED
@@ -0,0 +1,58 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ const promises_1 = require("node:readline/promises");
5
+ const args_1 = require("./args");
6
+ const init_1 = require("./init");
7
+ const questions_1 = require("./questions");
8
+ const USAGE = `Utilisation : npx @pulse-si/init <clé> [options]
9
+
10
+ --dir <chemin> dossier du projet (par défaut : le dossier courant)
11
+ --no-install n'installe pas le package
12
+ --yes ne pose aucune question, garde les réglages par défaut
13
+ --send <liste> données envoyées : checks, crons, logs, versions
14
+ --include <liste> seuls ces contrôles et tâches (noms, * permis)
15
+ --exclude <liste> contrôles et tâches ignorés (noms, * permis)
16
+ --log-level <niveau> niveau minimal des journaux : DEBUG, INFO, WARN, ERROR
17
+ --public-key <clé> mode sécurisé : clé publique pulse_pub_… de l'app Pulse
18
+ --clear <liste> en mode sécurisé, ce qui reste en clair : status, checks, crons, versions, none
19
+ --endpoint <adresse> ton Pulse Relay (VPS perso), par exemple https://relais.kalao.ci
20
+ --fingerprint <empr.> empreinte du certificat d'un relais sans domaine
21
+ `;
22
+ async function main() {
23
+ const args = (0, args_1.parseArgs)(process.argv.slice(2));
24
+ if (!args.key) {
25
+ process.stdout.write(USAGE);
26
+ return 1;
27
+ }
28
+ const print = (line) => process.stdout.write(`${line}\n`);
29
+ const interactive = args.interactive && process.stdin.isTTY;
30
+ const prompt = interactive
31
+ ? (0, promises_1.createInterface)({ input: process.stdin, output: process.stdout })
32
+ : null;
33
+ try {
34
+ return await (0, init_1.init)({
35
+ key: args.key,
36
+ dir: args.dir ?? process.cwd(),
37
+ install: args.install,
38
+ settings: args.settings,
39
+ ask: prompt
40
+ ? (project) => (0, questions_1.askSettings)({ ask: (q) => prompt.question(q), print }, project)
41
+ : undefined,
42
+ print,
43
+ });
44
+ }
45
+ catch (error) {
46
+ if (error.name !== 'AbortError')
47
+ throw error;
48
+ print('\nAnnulé : rien n’a été écrit.');
49
+ return 1;
50
+ }
51
+ finally {
52
+ prompt?.close();
53
+ }
54
+ }
55
+ void main().then((code) => {
56
+ process.exitCode = code;
57
+ });
58
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";;;AACA,qDAAyD;AACzD,iCAAmC;AACnC,iCAA8B;AAC9B,2CAA0C;AAE1C,MAAM,KAAK,GAAG;;;;;;;;;;;;;CAab,CAAC;AAEF,KAAK,UAAU,IAAI;IACjB,MAAM,IAAI,GAAG,IAAA,gBAAS,EAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IAC9C,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;QACd,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAC5B,OAAO,CAAC,CAAC;IACX,CAAC;IACD,MAAM,KAAK,GAAG,CAAC,IAAY,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,IAAI,IAAI,CAAC,CAAC;IAClE,MAAM,WAAW,GAAG,IAAI,CAAC,WAAW,IAAI,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC;IAC5D,MAAM,MAAM,GAAG,WAAW;QACxB,CAAC,CAAC,IAAA,0BAAe,EAAC,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC;QACnE,CAAC,CAAC,IAAI,CAAC;IACT,IAAI,CAAC;QACH,OAAO,MAAM,IAAA,WAAI,EAAC;YAChB,GAAG,EAAE,IAAI,CAAC,GAAG;YACb,GAAG,EAAE,IAAI,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE;YAC9B,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,GAAG,EAAE,MAAM;gBACT,CAAC,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,IAAA,uBAAW,EAAC,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,OAAO,CAAC;gBAC9E,CAAC,CAAC,SAAS;YACb,KAAK;SACN,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAK,KAAe,CAAC,IAAI,KAAK,YAAY;YAAE,MAAM,KAAK,CAAC;QACxD,KAAK,CAAC,gCAAgC,CAAC,CAAC;QACxC,OAAO,CAAC,CAAC;IACX,CAAC;YAAS,CAAC;QACT,MAAM,EAAE,KAAK,EAAE,CAAC;IAClB,CAAC;AACH,CAAC;AAED,KAAK,IAAI,EAAE,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE;IACxB,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC;AAC1B,CAAC,CAAC,CAAC"}
@@ -0,0 +1,6 @@
1
+ export type EnvResult = {
2
+ file: string;
3
+ replaced: boolean;
4
+ gitignoreUpdated: boolean;
5
+ };
6
+ export declare function writeEnv(dir: string, file: string, vars: Record<string, string>): EnvResult;
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.writeEnv = writeEnv;
4
+ const node_fs_1 = require("node:fs");
5
+ const node_path_1 = require("node:path");
6
+ const PRIVATE_FILE_MODE = 0o600;
7
+ function writeEnv(dir, file, vars) {
8
+ const path = (0, node_path_1.join)(dir, file);
9
+ let content = (0, node_fs_1.existsSync)(path) ? (0, node_fs_1.readFileSync)(path, 'utf8') : '';
10
+ const replaced = /^PULSE_KEY=.*$/m.test(content);
11
+ for (const [name, value] of Object.entries(vars)) {
12
+ const pattern = new RegExp(`^${name}=.*$`, 'm');
13
+ const line = `${name}=${value}`;
14
+ content = pattern.test(content)
15
+ ? content.replace(pattern, line)
16
+ : `${content}${content && !content.endsWith('\n') ? '\n' : ''}${line}\n`;
17
+ }
18
+ (0, node_fs_1.writeFileSync)(path, content);
19
+ (0, node_fs_1.chmodSync)(path, PRIVATE_FILE_MODE);
20
+ return { file, replaced, gitignoreUpdated: ignoreFile(dir, file) };
21
+ }
22
+ function ignoreFile(dir, file) {
23
+ const path = (0, node_path_1.join)(dir, '.gitignore');
24
+ const current = (0, node_fs_1.existsSync)(path) ? (0, node_fs_1.readFileSync)(path, 'utf8') : '';
25
+ const patterns = current.split('\n').map((l) => l.trim());
26
+ const covered = patterns.some((p) => p === file ||
27
+ p === `/${file}` ||
28
+ p === '.env*' ||
29
+ (p === '.env*.local' && file.endsWith('.local')));
30
+ if (covered)
31
+ return false;
32
+ (0, node_fs_1.writeFileSync)(path, `${current}${current && !current.endsWith('\n') ? '\n' : ''}${file}\n`);
33
+ return true;
34
+ }
35
+ //# sourceMappingURL=env-file.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env-file.js","sourceRoot":"","sources":["../src/env-file.ts"],"names":[],"mappings":";;AAOA,4BAcC;AArBD,qCAA6E;AAC7E,yCAAiC;AAEjC,MAAM,iBAAiB,GAAG,KAAK,CAAC;AAIhC,SAAgB,QAAQ,CAAC,GAAW,EAAE,IAAY,EAAE,IAA4B;IAC9E,MAAM,IAAI,GAAG,IAAA,gBAAI,EAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IAC7B,IAAI,OAAO,GAAG,IAAA,oBAAU,EAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAA,sBAAY,EAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IACjE,MAAM,QAAQ,GAAG,iBAAiB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACjD,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;QACjD,MAAM,OAAO,GAAG,IAAI,MAAM,CAAC,IAAI,IAAI,MAAM,EAAE,GAAG,CAAC,CAAC;QAChD,MAAM,IAAI,GAAG,GAAG,IAAI,IAAI,KAAK,EAAE,CAAC;QAChC,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC;YAC7B,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,EAAE,IAAI,CAAC;YAChC,CAAC,CAAC,GAAG,OAAO,GAAG,OAAO,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,GAAG,IAAI,IAAI,CAAC;IAC7E,CAAC;IACD,IAAA,uBAAa,EAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IAC7B,IAAA,mBAAS,EAAC,IAAI,EAAE,iBAAiB,CAAC,CAAC;IACnC,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,gBAAgB,EAAE,UAAU,CAAC,GAAG,EAAE,IAAI,CAAC,EAAE,CAAC;AACrE,CAAC;AAGD,SAAS,UAAU,CAAC,GAAW,EAAE,IAAY;IAC3C,MAAM,IAAI,GAAG,IAAA,gBAAI,EAAC,GAAG,EAAE,YAAY,CAAC,CAAC;IACrC,MAAM,OAAO,GAAG,IAAA,oBAAU,EAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAA,sBAAY,EAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IACnE,MAAM,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;IAC1D,MAAM,OAAO,GAAG,QAAQ,CAAC,IAAI,CAC3B,CAAC,CAAC,EAAE,EAAE,CACJ,CAAC,KAAK,IAAI;QACV,CAAC,KAAK,IAAI,IAAI,EAAE;QAChB,CAAC,KAAK,OAAO;QACb,CAAC,CAAC,KAAK,aAAa,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CACnD,CAAC;IACF,IAAI,OAAO;QAAE,OAAO,KAAK,CAAC;IAC1B,IAAA,uBAAa,EAAC,IAAI,EAAE,GAAG,OAAO,GAAG,OAAO,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,GAAG,IAAI,IAAI,CAAC,CAAC;IAC5F,OAAO,IAAI,CAAC;AACd,CAAC"}
package/dist/init.d.ts ADDED
@@ -0,0 +1,12 @@
1
+ import { type Project } from './project';
2
+ import { type Settings } from './settings';
3
+ export type InitOptions = {
4
+ key: string;
5
+ dir: string;
6
+ install: boolean;
7
+ settings?: Settings;
8
+ ask?: (project: Project) => Promise<Settings>;
9
+ print: (line: string) => void;
10
+ run?: (command: string, args: string[], cwd: string) => boolean;
11
+ };
12
+ export declare function init(options: InitOptions): Promise<number>;
package/dist/init.js ADDED
@@ -0,0 +1,71 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.init = init;
4
+ const node_child_process_1 = require("node:child_process");
5
+ const core_1 = require("@pulse-si/core");
6
+ const env_file_1 = require("./env-file");
7
+ const patch_nest_1 = require("./patch-nest");
8
+ const patch_next_1 = require("./patch-next");
9
+ const project_1 = require("./project");
10
+ const settings_1 = require("./settings");
11
+ const runCommand = (command, args, cwd) => (0, node_child_process_1.spawnSync)(command, args, { cwd, stdio: 'inherit', shell: process.platform === 'win32' })
12
+ .status === 0;
13
+ async function init(options) {
14
+ const { key, dir, install, print, run = runCommand } = options;
15
+ if (!(0, core_1.isValidKey)(key)) {
16
+ print('Clé invalide : copie la clé pk_live_… ou pk_test_… affichée dans l’app Pulse.');
17
+ return 1;
18
+ }
19
+ const project = (0, project_1.detectProject)(dir);
20
+ if (!project) {
21
+ print('Aucun projet NestJS ou Next.js ici : lance la commande à la racine du projet.');
22
+ return 1;
23
+ }
24
+ const nest = project.framework === 'nestjs';
25
+ const packageName = nest ? '@pulse-si/nest' : '@pulse-si/next';
26
+ print(`Projet ${nest ? 'NestJS' : 'Next.js'} détecté (${project.packageManager}).`);
27
+ const asked = options.ask ? await options.ask(project) : {};
28
+ const settings = { ...options.settings, ...asked };
29
+ const errors = (0, settings_1.settingsErrors)(settings);
30
+ if (errors.length) {
31
+ errors.forEach((error) => print(error));
32
+ return 1;
33
+ }
34
+ if (install) {
35
+ const [command, args] = (0, project_1.installCommand)(project, packageName);
36
+ if (!run(command, args, dir)) {
37
+ print(`Installation impossible : lance « ${command} ${args.join(' ')} » puis relance npx @pulse-si/init.`);
38
+ return 1;
39
+ }
40
+ print(`✓ ${packageName} installé`);
41
+ }
42
+ const extra = (0, settings_1.envFor)(settings);
43
+ const env = (0, env_file_1.writeEnv)(dir, nest ? '.env' : '.env.local', { PULSE_KEY: key, ...extra });
44
+ print(`✓ Clé ${env.replaced ? 'remplacée' : 'ajoutée'} dans ${env.file}`);
45
+ if (Object.keys(extra).length)
46
+ print(`✓ Réglages écrits : ${Object.keys(extra).join(', ')}`);
47
+ if (extra.PULSE_PUBLIC_KEY)
48
+ print('✓ Mode sécurisé : les rapports et les journaux partent chiffrés');
49
+ if (env.gitignoreUpdated)
50
+ print(`✓ ${env.file} ajouté au .gitignore`);
51
+ const patch = nest ? (0, patch_nest_1.patchNestModule)(dir) : (0, patch_next_1.patchNextInstrumentation)(dir, project.typescript);
52
+ if (patch.status === 'patched')
53
+ print(`✓ ${nest ? 'PulseModule branché' : 'Pulse démarré'} dans ${patch.file}`);
54
+ if (patch.status === 'already')
55
+ print(`✓ Pulse déjà branché dans ${patch.file}`);
56
+ if (patch.status === 'manual') {
57
+ print(`À faire à la main dans ${patch.file} :`);
58
+ print(nest
59
+ ? " import { PulseModule } from '@pulse-si/nest';\n imports: [PulseModule.forRoot(), …]"
60
+ : patch_next_1.NEXT_SNIPPET);
61
+ }
62
+ if (nest && !project.hasNestConfig) {
63
+ print('Attention : sans @nestjs/config, charge .env toi-même (ex. node --env-file=.env) pour que PULSE_KEY soit lue.');
64
+ }
65
+ if (!nest && ((0, project_1.majorOf)(project.frameworkRange) ?? 15) < 15) {
66
+ print('Next.js 14 : active experimental.instrumentationHook dans next.config.');
67
+ }
68
+ print('Relance ton app : le premier signal apparaît dans Pulse.');
69
+ return 0;
70
+ }
71
+ //# sourceMappingURL=init.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../src/init.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ export type PatchResult = {
2
+ status: 'patched' | 'already' | 'manual';
3
+ file: string;
4
+ };
5
+ export declare function patchNestModule(dir: string): PatchResult;
@@ -0,0 +1,43 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.patchNestModule = patchNestModule;
4
+ const node_fs_1 = require("node:fs");
5
+ const node_path_1 = require("node:path");
6
+ const IMPORT_LINE = "import { PulseModule } from '@pulse-si/nest';";
7
+ const MODULE_CALL = 'PulseModule.forRoot()';
8
+ function patchNestModule(dir) {
9
+ const file = ['src/app.module.ts', 'src/app/app.module.ts'].find((f) => (0, node_fs_1.existsSync)((0, node_path_1.join)(dir, f)));
10
+ if (!file)
11
+ return { status: 'manual', file: 'src/app.module.ts' };
12
+ const path = (0, node_path_1.join)(dir, file);
13
+ const source = (0, node_fs_1.readFileSync)(path, 'utf8');
14
+ if (source.includes('PulseModule'))
15
+ return { status: 'already', file };
16
+ let patched;
17
+ if (/@Module\(\s*\{[\s\S]*?\bimports\s*:\s*\[\s*\]/.test(source)) {
18
+ patched = source.replace(/(@Module\(\s*\{[\s\S]*?\bimports\s*:\s*)\[\s*\]/, `$1[${MODULE_CALL}]`);
19
+ }
20
+ else if (/@Module\(\s*\{[\s\S]*?\bimports\s*:\s*\[/.test(source)) {
21
+ patched = source.replace(/(@Module\(\s*\{[\s\S]*?\bimports\s*:\s*\[)/, `$1${MODULE_CALL}, `);
22
+ }
23
+ else if (/@Module\(\s*\{/.test(source)) {
24
+ patched = source.replace(/@Module\(\s*\{/, `@Module({\n imports: [${MODULE_CALL}],`);
25
+ }
26
+ else {
27
+ return { status: 'manual', file };
28
+ }
29
+ const lines = patched.split('\n');
30
+ const lastImport = lines.reduce((last, line, index) => (/^import\s/.test(line) ? index : last), -1);
31
+ const importEnd = lastImport === -1 ? -1 : endOfStatement(lines, lastImport);
32
+ lines.splice(importEnd + 1, 0, IMPORT_LINE);
33
+ (0, node_fs_1.writeFileSync)(path, lines.join('\n'));
34
+ return { status: 'patched', file };
35
+ }
36
+ function endOfStatement(lines, start) {
37
+ for (let index = start; index < lines.length; index += 1) {
38
+ if (lines[index].includes(';') || /from\s+['"][^'"]+['"]\s*$/.test(lines[index]))
39
+ return index;
40
+ }
41
+ return start;
42
+ }
43
+ //# sourceMappingURL=patch-nest.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"patch-nest.js","sourceRoot":"","sources":["../src/patch-nest.ts"],"names":[],"mappings":";;AAQA,0CA6BC;AArCD,qCAAkE;AAClE,yCAAiC;AAIjC,MAAM,WAAW,GAAG,+CAA+C,CAAC;AACpE,MAAM,WAAW,GAAG,uBAAuB,CAAC;AAE5C,SAAgB,eAAe,CAAC,GAAW;IACzC,MAAM,IAAI,GAAG,CAAC,mBAAmB,EAAE,uBAAuB,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAA,oBAAU,EAAC,IAAA,gBAAI,EAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IAClG,IAAI,CAAC,IAAI;QAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,mBAAmB,EAAE,CAAC;IAClE,MAAM,IAAI,GAAG,IAAA,gBAAI,EAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IAC7B,MAAM,MAAM,GAAG,IAAA,sBAAY,EAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IAC1C,IAAI,MAAM,CAAC,QAAQ,CAAC,aAAa,CAAC;QAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;IAEvE,IAAI,OAAe,CAAC;IACpB,IAAI,+CAA+C,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;QACjE,OAAO,GAAG,MAAM,CAAC,OAAO,CACtB,iDAAiD,EACjD,MAAM,WAAW,GAAG,CACrB,CAAC;IACJ,CAAC;SAAM,IAAI,0CAA0C,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;QACnE,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,4CAA4C,EAAE,KAAK,WAAW,IAAI,CAAC,CAAC;IAC/F,CAAC;SAAM,IAAI,gBAAgB,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;QACzC,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,gBAAgB,EAAE,0BAA0B,WAAW,IAAI,CAAC,CAAC;IACxF,CAAC;SAAM,CAAC;QACN,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IACpC,CAAC;IACD,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAClC,MAAM,UAAU,GAAG,KAAK,CAAC,MAAM,CAC7B,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,EAC9D,CAAC,CAAC,CACH,CAAC;IACF,MAAM,SAAS,GAAG,UAAU,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC;IAC7E,KAAK,CAAC,MAAM,CAAC,SAAS,GAAG,CAAC,EAAE,CAAC,EAAE,WAAW,CAAC,CAAC;IAC5C,IAAA,uBAAa,EAAC,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IACtC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;AACrC,CAAC;AAED,SAAS,cAAc,CAAC,KAAe,EAAE,KAAa;IACpD,KAAK,IAAI,KAAK,GAAG,KAAK,EAAE,KAAK,GAAG,KAAK,CAAC,MAAM,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;QACzD,IAAI,KAAK,CAAC,KAAK,CAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,2BAA2B,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAE,CAAC;YAChF,OAAO,KAAK,CAAC;IACjB,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { PatchResult } from './patch-nest';
2
+ export declare const NEXT_SNIPPET = "export async function register() {\n if (process.env.NEXT_RUNTIME === 'nodejs') {\n const { startPulse } = await import('@pulse-si/next');\n startPulse();\n }\n}\n";
3
+ export declare function patchNextInstrumentation(dir: string, typescript: boolean): PatchResult;
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.NEXT_SNIPPET = void 0;
4
+ exports.patchNextInstrumentation = patchNextInstrumentation;
5
+ const node_fs_1 = require("node:fs");
6
+ const node_path_1 = require("node:path");
7
+ exports.NEXT_SNIPPET = `export async function register() {
8
+ if (process.env.NEXT_RUNTIME === 'nodejs') {
9
+ const { startPulse } = await import('@pulse-si/next');
10
+ startPulse();
11
+ }
12
+ }
13
+ `;
14
+ function patchNextInstrumentation(dir, typescript) {
15
+ const usesSrc = (0, node_fs_1.existsSync)((0, node_path_1.join)(dir, 'src', 'app')) || (0, node_fs_1.existsSync)((0, node_path_1.join)(dir, 'src', 'pages'));
16
+ const base = usesSrc ? 'src/instrumentation' : 'instrumentation';
17
+ const existing = ['.ts', '.js', '.mjs']
18
+ .map((ext) => base + ext)
19
+ .find((f) => (0, node_fs_1.existsSync)((0, node_path_1.join)(dir, f)));
20
+ if (existing) {
21
+ const source = (0, node_fs_1.readFileSync)((0, node_path_1.join)(dir, existing), 'utf8');
22
+ return { status: source.includes('@pulse-si/next') ? 'already' : 'manual', file: existing };
23
+ }
24
+ const file = base + (typescript ? '.ts' : '.js');
25
+ (0, node_fs_1.writeFileSync)((0, node_path_1.join)(dir, file), exports.NEXT_SNIPPET);
26
+ return { status: 'patched', file };
27
+ }
28
+ //# sourceMappingURL=patch-next.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"patch-next.js","sourceRoot":"","sources":["../src/patch-next.ts"],"names":[],"mappings":";;;AAYA,4DAaC;AAzBD,qCAAkE;AAClE,yCAAiC;AAGpB,QAAA,YAAY,GAAG;;;;;;CAM3B,CAAC;AAEF,SAAgB,wBAAwB,CAAC,GAAW,EAAE,UAAmB;IACvE,MAAM,OAAO,GAAG,IAAA,oBAAU,EAAC,IAAA,gBAAI,EAAC,GAAG,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,IAAI,IAAA,oBAAU,EAAC,IAAA,gBAAI,EAAC,GAAG,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC;IAC7F,MAAM,IAAI,GAAG,OAAO,CAAC,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,iBAAiB,CAAC;IACjE,MAAM,QAAQ,GAAG,CAAC,KAAK,EAAE,KAAK,EAAE,MAAM,CAAC;SACpC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,GAAG,GAAG,CAAC;SACxB,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAA,oBAAU,EAAC,IAAA,gBAAI,EAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IACzC,IAAI,QAAQ,EAAE,CAAC;QACb,MAAM,MAAM,GAAG,IAAA,sBAAY,EAAC,IAAA,gBAAI,EAAC,GAAG,EAAE,QAAQ,CAAC,EAAE,MAAM,CAAC,CAAC;QACzD,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,QAAQ,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;IAC9F,CAAC;IACD,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;IACjD,IAAA,uBAAa,EAAC,IAAA,gBAAI,EAAC,GAAG,EAAE,IAAI,CAAC,EAAE,oBAAY,CAAC,CAAC;IAC7C,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;AACrC,CAAC"}
@@ -0,0 +1,14 @@
1
+ export type Framework = 'nestjs' | 'nextjs';
2
+ export type PackageManager = 'pnpm' | 'yarn' | 'bun' | 'npm';
3
+ export type Project = {
4
+ dir: string;
5
+ framework: Framework;
6
+ frameworkRange: string;
7
+ packageManager: PackageManager;
8
+ typescript: boolean;
9
+ hasNestConfig: boolean;
10
+ integrations: string[];
11
+ };
12
+ export declare function detectProject(dir: string): Project | null;
13
+ export declare function installCommand(project: Project, packageName: string): [string, string[]];
14
+ export declare function majorOf(range: string): number | null;
@@ -0,0 +1,51 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.detectProject = detectProject;
4
+ exports.installCommand = installCommand;
5
+ exports.majorOf = majorOf;
6
+ const node_fs_1 = require("node:fs");
7
+ const node_path_1 = require("node:path");
8
+ const INTEGRATIONS = [
9
+ ['@prisma/client', 'Prisma'],
10
+ ['typeorm', 'TypeORM'],
11
+ ['mongoose', 'Mongoose'],
12
+ ['ioredis', 'Redis (ioredis)'],
13
+ ['redis', 'Redis'],
14
+ ['bullmq', 'BullMQ'],
15
+ ['@nestjs/schedule', 'tâches planifiées'],
16
+ ];
17
+ const LOCKFILES = [
18
+ ['pnpm-lock.yaml', 'pnpm'],
19
+ ['yarn.lock', 'yarn'],
20
+ ['bun.lockb', 'bun'],
21
+ ['bun.lock', 'bun'],
22
+ ['package-lock.json', 'npm'],
23
+ ];
24
+ function detectProject(dir) {
25
+ const path = (0, node_path_1.join)(dir, 'package.json');
26
+ if (!(0, node_fs_1.existsSync)(path))
27
+ return null;
28
+ const pkg = JSON.parse((0, node_fs_1.readFileSync)(path, 'utf8'));
29
+ const deps = { ...pkg.devDependencies, ...pkg.dependencies };
30
+ const framework = deps['@nestjs/core'] ? 'nestjs' : deps.next ? 'nextjs' : null;
31
+ if (!framework)
32
+ return null;
33
+ return {
34
+ dir,
35
+ framework,
36
+ frameworkRange: (framework === 'nestjs' ? deps['@nestjs/core'] : deps.next) ?? '',
37
+ packageManager: LOCKFILES.find(([file]) => (0, node_fs_1.existsSync)((0, node_path_1.join)(dir, file)))?.[1] ?? 'npm',
38
+ typescript: (0, node_fs_1.existsSync)((0, node_path_1.join)(dir, 'tsconfig.json')),
39
+ hasNestConfig: Boolean(deps['@nestjs/config']),
40
+ integrations: INTEGRATIONS.filter(([dep]) => deps[dep]).map(([, label]) => label),
41
+ };
42
+ }
43
+ function installCommand(project, packageName) {
44
+ const verb = project.packageManager === 'npm' ? 'install' : 'add';
45
+ return [project.packageManager, [verb, packageName]];
46
+ }
47
+ function majorOf(range) {
48
+ const match = /(\d+)/.exec(range);
49
+ return match ? Number(match[1]) : null;
50
+ }
51
+ //# sourceMappingURL=project.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project.js","sourceRoot":"","sources":["../src/project.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import type { Project } from './project';
2
+ import type { Settings } from './settings';
3
+ export type Io = {
4
+ ask: (question: string) => Promise<string>;
5
+ print: (line: string) => void;
6
+ };
7
+ export declare function askSettings(io: Io, project: Project): Promise<Settings>;
@@ -0,0 +1,44 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.askSettings = askSettings;
4
+ const yes = (answer) => answer.trim() === '' || /^(o|oui|y|yes)$/i.test(answer.trim());
5
+ const list = (answer) => answer
6
+ .split(',')
7
+ .map((item) => item.trim())
8
+ .filter(Boolean);
9
+ const DATA = [
10
+ ['checks', 'L’état des dépendances (base, Redis, files) ?'],
11
+ ['crons', 'Les tâches planifiées ?'],
12
+ ['logs', 'Les journaux de l’app (Pro et Team) ?'],
13
+ ['versions', 'Les versions (app, framework, déploiement) ?'],
14
+ ];
15
+ async function askSettings(io, project) {
16
+ io.print('');
17
+ io.print('Choisis ce que ton app envoie à Pulse. Le signal de vie part toujours.');
18
+ if (project.integrations.length) {
19
+ io.print(`Trouvé dans package.json : ${project.integrations.join(', ')}.`);
20
+ }
21
+ const send = [];
22
+ for (const [field, question] of DATA) {
23
+ if (yes(await io.ask(` ${question} [O/n] `)))
24
+ send.push(field);
25
+ }
26
+ const exclude = list(await io.ask(' Contrôles ou tâches à ignorer (noms séparés par des virgules, * permis, vide pour aucun) : '));
27
+ const logLevel = send.includes('logs')
28
+ ? (await io.ask(' Niveau minimal des journaux (DEBUG, INFO, WARN, ERROR) [DEBUG] : ')).trim()
29
+ : '';
30
+ io.print('');
31
+ io.print('Mode sécurisé (Pro et Team) : tout part chiffré, Pulse ne peut rien lire.');
32
+ const publicKey = (await io.ask(' Clé publique pulse_pub_… affichée dans l’app (vide pour passer) : ')).trim();
33
+ const clear = publicKey
34
+ ? list(await io.ask(' À laisser en clair pour garder les alertes (status, checks, crons, versions, none) [status] : '))
35
+ : [];
36
+ return {
37
+ send,
38
+ exclude,
39
+ logLevel: logLevel || undefined,
40
+ publicKey: publicKey || undefined,
41
+ clear: publicKey && clear.length ? clear : undefined,
42
+ };
43
+ }
44
+ //# sourceMappingURL=questions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"questions.js","sourceRoot":"","sources":["../src/questions.ts"],"names":[],"mappings":";;AAmBA,kCAsCC;AApDD,MAAM,GAAG,GAAG,CAAC,MAAc,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,EAAE,IAAI,kBAAkB,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;AAC/F,MAAM,IAAI,GAAG,CAAC,MAAc,EAAE,EAAE,CAC9B,MAAM;KACH,KAAK,CAAC,GAAG,CAAC;KACV,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;KAC1B,MAAM,CAAC,OAAO,CAAC,CAAC;AAErB,MAAM,IAAI,GAAG;IACX,CAAC,QAAQ,EAAE,+CAA+C,CAAC;IAC3D,CAAC,OAAO,EAAE,yBAAyB,CAAC;IACpC,CAAC,MAAM,EAAE,uCAAuC,CAAC;IACjD,CAAC,UAAU,EAAE,8CAA8C,CAAC;CACpD,CAAC;AAEJ,KAAK,UAAU,WAAW,CAAC,EAAM,EAAE,OAAgB;IACxD,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IACb,EAAE,CAAC,KAAK,CAAC,wEAAwE,CAAC,CAAC;IACnF,IAAI,OAAO,CAAC,YAAY,CAAC,MAAM,EAAE,CAAC;QAChC,EAAE,CAAC,KAAK,CAAC,8BAA8B,OAAO,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC7E,CAAC;IACD,MAAM,IAAI,GAAa,EAAE,CAAC;IAC1B,KAAK,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,IAAI,IAAI,EAAE,CAAC;QACrC,IAAI,GAAG,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,KAAK,QAAQ,SAAS,CAAC,CAAC;YAAE,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAClE,CAAC;IACD,MAAM,OAAO,GAAG,IAAI,CAClB,MAAM,EAAE,CAAC,GAAG,CACV,+FAA+F,CAChG,CACF,CAAC;IACF,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC;QACpC,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,qEAAqE,CAAC,CAAC,CAAC,IAAI,EAAE;QAC9F,CAAC,CAAC,EAAE,CAAC;IAEP,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IACb,EAAE,CAAC,KAAK,CAAC,2EAA2E,CAAC,CAAC;IACtF,MAAM,SAAS,GAAG,CAChB,MAAM,EAAE,CAAC,GAAG,CAAC,sEAAsE,CAAC,CACrF,CAAC,IAAI,EAAE,CAAC;IACT,MAAM,KAAK,GAAG,SAAS;QACrB,CAAC,CAAC,IAAI,CACF,MAAM,EAAE,CAAC,GAAG,CACV,kGAAkG,CACnG,CACF;QACH,CAAC,CAAC,EAAE,CAAC;IACP,OAAO;QACL,IAAI;QACJ,OAAO;QACP,QAAQ,EAAE,QAAQ,IAAI,SAAS;QAC/B,SAAS,EAAE,SAAS,IAAI,SAAS;QACjC,KAAK,EAAE,SAAS,IAAI,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS;KACrD,CAAC;AACJ,CAAC"}
@@ -0,0 +1,12 @@
1
+ export type Settings = {
2
+ publicKey?: string;
3
+ clear?: string[];
4
+ send?: string[];
5
+ include?: string[];
6
+ exclude?: string[];
7
+ logLevel?: string;
8
+ endpoint?: string;
9
+ fingerprint?: string;
10
+ };
11
+ export declare function settingsErrors(settings: Settings): string[];
12
+ export declare function envFor(settings: Settings): Record<string, string>;
@@ -0,0 +1,64 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.settingsErrors = settingsErrors;
4
+ exports.envFor = envFor;
5
+ const core_1 = require("@pulse-si/core");
6
+ const outside = (values, allowed) => (values ?? []).filter((value) => value !== 'none' && !allowed.includes(value));
7
+ function settingsErrors(settings) {
8
+ const errors = [];
9
+ if (settings.publicKey && !(0, core_1.parsePublicKey)(settings.publicKey)) {
10
+ errors.push('Clé publique invalide : copie la clé pulse_pub_… affichée dans l’app Pulse.');
11
+ }
12
+ const send = outside(settings.send, core_1.SEND_FIELDS);
13
+ if (send.length)
14
+ errors.push(`Données inconnues : ${send.join(', ')} (${core_1.SEND_FIELDS.join(', ')}).`);
15
+ const clear = outside(settings.clear, core_1.CLEAR_FIELDS);
16
+ if (clear.length)
17
+ errors.push(`Champs en clair inconnus : ${clear.join(', ')} (${core_1.CLEAR_FIELDS.join(', ')}, none).`);
18
+ if (settings.clear && !settings.publicKey) {
19
+ errors.push('Les champs en clair ne servent qu’avec le mode sécurisé (--public-key).');
20
+ }
21
+ const level = settings.logLevel?.toUpperCase();
22
+ if (level && !core_1.LOG_LEVELS.includes(level)) {
23
+ errors.push(`Niveau de journal inconnu : ${settings.logLevel} (${core_1.LOG_LEVELS.join(', ')}).`);
24
+ }
25
+ if (settings.endpoint && !isHttps(settings.endpoint)) {
26
+ errors.push('Adresse du relais invalide : elle commence par https://.');
27
+ }
28
+ if (settings.fingerprint && !(0, core_1.normalizeFingerprint)(settings.fingerprint)) {
29
+ errors.push('Empreinte invalide : copie l’empreinte SHA-256 affichée par ton relais.');
30
+ }
31
+ return errors;
32
+ }
33
+ function isHttps(raw) {
34
+ try {
35
+ return new URL(raw).protocol === 'https:';
36
+ }
37
+ catch {
38
+ return false;
39
+ }
40
+ }
41
+ function envFor(settings) {
42
+ const env = {};
43
+ if (settings.publicKey)
44
+ env.PULSE_PUBLIC_KEY = settings.publicKey.trim();
45
+ if (settings.clear)
46
+ env.PULSE_CLEAR = settings.clear.length ? settings.clear.join(',') : 'none';
47
+ if (settings.send && core_1.SEND_FIELDS.some((field) => !settings.send.includes(field))) {
48
+ env.PULSE_SEND = settings.send.filter((field) => field !== 'none').join(',');
49
+ }
50
+ if (settings.include?.length)
51
+ env.PULSE_INCLUDE = settings.include.join(',');
52
+ if (settings.exclude?.length)
53
+ env.PULSE_EXCLUDE = settings.exclude.join(',');
54
+ const level = settings.logLevel?.toUpperCase();
55
+ if (level && level !== 'DEBUG')
56
+ env.PULSE_LOG_LEVEL = level;
57
+ if (settings.endpoint)
58
+ env.PULSE_ENDPOINT = new URL(settings.endpoint).origin;
59
+ const fingerprint = (0, core_1.normalizeFingerprint)(settings.fingerprint);
60
+ if (fingerprint)
61
+ env.PULSE_RELAY_FINGERPRINT = fingerprint;
62
+ return env;
63
+ }
64
+ //# sourceMappingURL=settings.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"settings.js","sourceRoot":"","sources":["../src/settings.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,47 @@
1
1
  {
2
2
  "name": "@pulse-si/init",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
3
+ "version": "0.0.1",
4
+ "description": "Relie un projet NestJS ou Next.js à Pulse : npx @pulse-si/init <clé>.",
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
+ },
35
+ "bin": {
36
+ "pulse-init": "dist/cli.js"
37
+ },
38
+ "dependencies": {
39
+ "@pulse-si/core": "^0.0.1"
40
+ },
41
+ "scripts": {
42
+ "build": "tsc -p tsconfig.build.json",
43
+ "typecheck": "tsc --noEmit",
44
+ "lint": "eslint \"src/**/*.ts\"",
45
+ "test": "jest"
46
+ }
6
47
  }