firebase-secrets-cli 0.1.0 → 0.1.2

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/README.md ADDED
@@ -0,0 +1,120 @@
1
+ # firebase-secrets-cli
2
+
3
+ CLI interattiva per la gestione centralizzata dei **Firebase Functions Secrets** (Firebase Secrets Manager), con sincronizzazione dei riferimenti anche nei file locali del repository.
4
+
5
+ ## Obiettivo
6
+
7
+ Semplificare e standardizzare le operazioni sui secrets usati dalle Cloud Functions, evitando errori manuali e mantenendo allineati:
8
+
9
+ - **Firebase Secrets Manager (ONLINE)**: valore reale del secret
10
+ - **functions/.secret.local (LOCALE)**: elenco chiavi (e talvolta valori) utile per sviluppo/ops
11
+ - **functions/src/config/secret.ts (CODICE)**: “registry” tipizzato delle chiavi disponibili nel progetto
12
+
13
+ ## Cosa fa la CLI
14
+
15
+ All’avvio, mostra un menu “Firebase Secrets Manager” con queste azioni:
16
+
17
+ - **get**: legge e mostra il valore di una secret (accesso online)
18
+ - **list**: mostra tutte le secrets presenti in `secret.ts` e ne stampa i valori (**con conferma**, perché espone valori a schermo)
19
+ - **set**: crea una nuova secret online e aggiorna anche `.secret.local` + `secret.ts`
20
+ - **update**: aggiorna il valore online e garantisce che la key sia presente in `.secret.local` e `secret.ts`
21
+ - **destroy**: elimina la secret online (con conferma) e poi:
22
+ - commenta la riga corrispondente in `.secret.local`
23
+ - rimuove la key da `secret.ts`
24
+ - **syncToLocal**: prende il valore online e lo scrive in `.secret.local` come `KEY=VALUE`
25
+ - **reviveFromLocal**: ripristina online una secret partendo da una riga commentata ma con valore in `.secret.local` (es. `# KEY=VALORE`), poi:
26
+ - scrive online
27
+ - aggiunge la key a `secret.ts`
28
+ - decommenta e normalizza la riga in `.secret.local`
29
+
30
+ ### Come vengono scelte le secret
31
+
32
+ La CLI propone una lista di chiavi lette da `functions/src/config/secret.ts`, ma permette anche di inserire una chiave manualmente con l’opzione **“Other…”**.
33
+
34
+ ## Sicurezza
35
+
36
+ - L’azione **list** stampa i valori dei secrets: viene richiesta **conferma esplicita**.
37
+ - Le operazioni usano i comandi `firebase functions:secrets:*`, quindi serve:
38
+ - essere autenticati su Firebase
39
+ - avere i permessi corretti sul progetto
40
+
41
+ ## Requisiti
42
+
43
+ - **Node.js** (progetto TypeScript ESM)
44
+ - **Firebase CLI** installata e autenticata (`firebase login`)
45
+ - Repository che contenga (o che tu voglia allineare a) la struttura:
46
+ - `functions/.secret.local`
47
+ - `functions/src/config/secret.ts`
48
+
49
+ > Nota: i path sono risolti con `process.cwd()`. In pratica la CLI si aspetta di essere lanciata dalla root del repo che contiene la cartella `functions/`.
50
+
51
+ ## Installazione
52
+
53
+ ### Globale (da npm)
54
+
55
+ ```bash
56
+ npm i -g firebase-secrets-cli
57
+ ```
58
+
59
+ ### Esecuzione senza installare (consigliato per test)
60
+
61
+ ```bash
62
+ npx firebase-secrets-cli
63
+ ```
64
+
65
+ ## Comandi disponibili
66
+
67
+ Il pacchetto espone questi binari (da `package.json`):
68
+
69
+ - `firebase-secrets` → CLI principale
70
+ - `cic:index` → entrypoint secondario (utility/launcher)
71
+ - `cic:bump` → utility di bump versione
72
+
73
+ Esempi:
74
+
75
+ ```bash
76
+ # CLI principale
77
+ npx firebase-secrets
78
+
79
+ # utility index (se prevista nel tuo flusso)
80
+ npx cic:index
81
+
82
+ # bump versione (se prevista nel tuo flusso)
83
+ npx cic:bump
84
+ ```
85
+
86
+ ## Sviluppo locale
87
+
88
+ Script disponibili:
89
+
90
+ ```bash
91
+ npm run build # compila TypeScript in dist/
92
+ npm run start # build + esegue dist/cic-index.js
93
+ npm run pack # build + npm pack
94
+ npm run deploy # build + bump + pack + publish
95
+ ```
96
+
97
+ Compilazione: TypeScript con `module`/`moduleResolution` **NodeNext**, output in `dist/`.
98
+
99
+ ## Troubleshooting
100
+
101
+ ### “Non trova functions/.secret.local o secret.ts”
102
+ - Verifica di lanciare il comando dalla **root del repo** (dove esiste `functions/`).
103
+ - In caso di repo senza i file, la CLI dovrebbe poterli creare/aggiornare quando esegui operazioni tipo `set`/`update` (dipende dall’implementazione). Se non ci sono controlli ancora, aggiungerli è una buona prossima patch:
104
+ - se manca `functions/` → errore chiaro
105
+ - se manca `.secret.local` → creazione file vuoto
106
+ - se manca `secret.ts` → scaffolding minimale del registry
107
+
108
+ ### Permessi Firebase
109
+ Se i comandi `firebase functions:secrets:*` falliscono:
110
+ - `firebase login`
111
+ - seleziona il progetto corretto (`firebase use <alias|projectId>`)
112
+ - verifica di avere i permessi IAM necessari
113
+
114
+ ---
115
+
116
+ ## Informazioni dal pacchetto
117
+
118
+ - Nome: `firebase-secrets-cli`
119
+ - Versione: `0.1.0`
120
+ - Bin: `firebase-secrets`, `cic:index`, `cic:bump`
package/dist/bump.js ADDED
@@ -0,0 +1,43 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { ensureFileExists, getProjectRoot } from './utils/dir.js';
4
+ function bumpPatch(version) {
5
+ const parts = version.split('.').map((n) => Number(n));
6
+ if (parts.length !== 3 || parts.some((n) => Number.isNaN(n))) {
7
+ throw new Error(`❌ Invalid version format in package.json: "${version}" (expected x.y.z)`);
8
+ }
9
+ parts[2] += 1;
10
+ return parts.join('.');
11
+ }
12
+ export function bumpRootPackageVersion() {
13
+ const rootDir = getProjectRoot();
14
+ const packageJsonPath = path.join(rootDir, 'package.json');
15
+ ensureFileExists(packageJsonPath, 'package.json');
16
+ const raw = fs.readFileSync(packageJsonPath, 'utf8');
17
+ let pkg;
18
+ try {
19
+ pkg = JSON.parse(raw);
20
+ }
21
+ catch {
22
+ throw new Error(`❌ package.json is not valid JSON: ${packageJsonPath}`);
23
+ }
24
+ if (!pkg.version || typeof pkg.version !== 'string') {
25
+ throw new Error(`❌ package.json has no valid "version" field: ${packageJsonPath}`);
26
+ }
27
+ const oldVersion = pkg.version;
28
+ const newVersion = bumpPatch(oldVersion);
29
+ pkg.version = newVersion;
30
+ // mantiene formattazione standard (2 spazi) + newline finale
31
+ fs.writeFileSync(packageJsonPath, JSON.stringify(pkg, null, 2) + '\n', 'utf8');
32
+ return newVersion;
33
+ }
34
+ // esecuzione diretta (cli entrypoint)
35
+ try {
36
+ const v = bumpRootPackageVersion();
37
+ console.log(`✔ Root package.json version bumped to ${v}`);
38
+ }
39
+ catch (err) {
40
+ console.error(err?.message ?? err);
41
+ process.exit(1);
42
+ }
43
+ //# sourceMappingURL=bump.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bump.js","sourceRoot":"","sources":["../src/bump.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAA;AACxB,OAAO,IAAI,MAAM,WAAW,CAAA;AAC5B,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAA;AAEjE,SAAS,SAAS,CAAC,OAAe;IAC9B,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAA;IAEtD,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAC3D,MAAM,IAAI,KAAK,CAAC,8CAA8C,OAAO,oBAAoB,CAAC,CAAA;IAC9F,CAAC;IAED,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAA;IACb,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;AAC1B,CAAC;AAED,MAAM,UAAU,sBAAsB;IAClC,MAAM,OAAO,GAAG,cAAc,EAAE,CAAA;IAChC,MAAM,eAAe,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,cAAc,CAAC,CAAA;IAE1D,gBAAgB,CAAC,eAAe,EAAE,cAAc,CAAC,CAAA;IAEjD,MAAM,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,eAAe,EAAE,MAAM,CAAC,CAAA;IAEpD,IAAI,GAAQ,CAAA;IACZ,IAAI,CAAC;QACD,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;IACzB,CAAC;IAAC,MAAM,CAAC;QACL,MAAM,IAAI,KAAK,CAAC,qCAAqC,eAAe,EAAE,CAAC,CAAA;IAC3E,CAAC;IAED,IAAI,CAAC,GAAG,CAAC,OAAO,IAAI,OAAO,GAAG,CAAC,OAAO,KAAK,QAAQ,EAAE,CAAC;QAClD,MAAM,IAAI,KAAK,CAAC,gDAAgD,eAAe,EAAE,CAAC,CAAA;IACtF,CAAC;IAED,MAAM,UAAU,GAAG,GAAG,CAAC,OAAO,CAAA;IAC9B,MAAM,UAAU,GAAG,SAAS,CAAC,UAAU,CAAC,CAAA;IAExC,GAAG,CAAC,OAAO,GAAG,UAAU,CAAA;IAExB,6DAA6D;IAC7D,EAAE,CAAC,aAAa,CAAC,eAAe,EAAE,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,EAAE,MAAM,CAAC,CAAA;IAE9E,OAAO,UAAU,CAAA;AACrB,CAAC;AAED,sCAAsC;AACtC,IAAI,CAAC;IACD,MAAM,CAAC,GAAG,sBAAsB,EAAE,CAAA;IAClC,OAAO,CAAC,GAAG,CAAC,yCAAyC,CAAC,EAAE,CAAC,CAAA;AAC7D,CAAC;AAAC,OAAO,GAAQ,EAAE,CAAC;IAChB,OAAO,CAAC,KAAK,CAAC,GAAG,EAAE,OAAO,IAAI,GAAG,CAAC,CAAA;IAClC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;AACnB,CAAC"}
@@ -0,0 +1,53 @@
1
+ #!/usr/bin/env node
2
+ import select from '@inquirer/select';
3
+ import inquirer from 'inquirer';
4
+ import { initFirebaseSecretsProject } from './utils/init.js';
5
+ async function main() {
6
+ console.log('✔ cic CLI');
7
+ const action = await select({
8
+ message: 'Menu',
9
+ choices: [
10
+ { name: 'Init (Firebase Secrets)', value: 'init' },
11
+ { name: 'Firebase Secrets Manager', value: 'firebase-secrets' },
12
+ { name: 'Exit', value: 'exit' },
13
+ ],
14
+ });
15
+ if (action === 'init') {
16
+ const { ok } = await inquirer.prompt([
17
+ {
18
+ type: 'confirm',
19
+ name: 'ok',
20
+ message: 'Questa operazione creerà (solo se mancanti) functions/, functions/.secret.local e functions/src/config/secret.ts. Vuoi continuare?',
21
+ default: false,
22
+ },
23
+ ]);
24
+ if (!ok) {
25
+ console.log('annullato');
26
+ return;
27
+ }
28
+ const res = initFirebaseSecretsProject();
29
+ console.log('\n✔ Init completato');
30
+ console.log('Root:', res.rootDir);
31
+ if (res.created.length) {
32
+ console.log('\nCreati:');
33
+ for (const p of res.created)
34
+ console.log(' +', p);
35
+ }
36
+ if (res.alreadyExists.length) {
37
+ console.log('\nGià esistenti (non toccati):');
38
+ for (const p of res.alreadyExists)
39
+ console.log(' =', p);
40
+ }
41
+ return;
42
+ }
43
+ if (action === 'firebase-secrets') {
44
+ await import('./firebase-secrets.js');
45
+ return;
46
+ }
47
+ console.log('bye');
48
+ }
49
+ main().catch((err) => {
50
+ console.error('❌ Errore:', err instanceof Error ? err.message : err);
51
+ process.exit(1);
52
+ });
53
+ //# sourceMappingURL=cic-index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cic-index.js","sourceRoot":"","sources":["../src/cic-index.ts"],"names":[],"mappings":";AAEA,OAAO,MAAM,MAAM,kBAAkB,CAAA;AACrC,OAAO,QAAQ,MAAM,UAAU,CAAA;AAC/B,OAAO,EAAE,0BAA0B,EAAE,MAAM,iBAAiB,CAAA;AAI5D,KAAK,UAAU,IAAI;IACf,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,CAAA;IAExB,MAAM,MAAM,GAAG,MAAM,MAAM,CAAS;QAChC,OAAO,EAAE,MAAM;QACf,OAAO,EAAE;YACL,EAAE,IAAI,EAAE,yBAAyB,EAAE,KAAK,EAAE,MAAM,EAAE;YAClD,EAAE,IAAI,EAAE,0BAA0B,EAAE,KAAK,EAAE,kBAAkB,EAAE;YAC/D,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE;SAClC;KACJ,CAAC,CAAA;IAEF,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;QACpB,MAAM,EAAE,EAAE,EAAE,GAAG,MAAM,QAAQ,CAAC,MAAM,CAAkB;YAClD;gBACI,IAAI,EAAE,SAAS;gBACf,IAAI,EAAE,IAAI;gBACV,OAAO,EACH,oIAAoI;gBACxI,OAAO,EAAE,KAAK;aACjB;SACJ,CAAC,CAAA;QAEF,IAAI,CAAC,EAAE,EAAE,CAAC;YACN,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,CAAA;YACxB,OAAM;QACV,CAAC;QAED,MAAM,GAAG,GAAG,0BAA0B,EAAE,CAAA;QAExC,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAC,CAAA;QAClC,OAAO,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,CAAC,OAAO,CAAC,CAAA;QAEjC,IAAI,GAAG,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;YACrB,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,CAAA;YACxB,KAAK,MAAM,CAAC,IAAI,GAAG,CAAC,OAAO;gBAAE,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,CAAA;QACrD,CAAC;QAED,IAAI,GAAG,CAAC,aAAa,CAAC,MAAM,EAAE,CAAC;YAC3B,OAAO,CAAC,GAAG,CAAC,gCAAgC,CAAC,CAAA;YAC7C,KAAK,MAAM,CAAC,IAAI,GAAG,CAAC,aAAa;gBAAE,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,CAAA;QAC3D,CAAC;QACD,OAAM;IACV,CAAC;IAED,IAAI,MAAM,KAAK,kBAAkB,EAAE,CAAC;QAChC,MAAM,MAAM,CAAC,uBAAuB,CAAC,CAAA;QACrC,OAAM;IACV,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAA;AACtB,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IACjB,OAAO,CAAC,KAAK,CAAC,WAAW,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAA;IACpE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;AACnB,CAAC,CAAC,CAAA"}
@@ -1,15 +1,193 @@
1
- #!/usr/bin/env node
1
+ #!/usr/bin/env tsx
2
2
  import select from '@inquirer/select';
3
+ import inquirer from 'inquirer';
4
+ import { run, runCapture } from './utils/run.js';
5
+ import { setSecretOnline } from './utils/firebaseSecretCli.js';
6
+ import { upsertSecretLocalKey, commentSecretLocalKey, upsertSecretLocalKeyValue, listCommentedSecretsWithValue, uncommentAndSetSecretLocal } from './utils/secretLocal.js';
7
+ import { parseExistingSecretKeysFromTs, writeSecretTs, removeSecretKeyFromTs } from './utils/secretTs.js';
8
+ import { pickSecretKey } from './utils/secretKeyPicker.js';
9
+ import { hr, hrLight, coloredSecretKV } from './utils/logger.js';
10
+ import { assertPathsExist } from './utils/dir.js';
11
+ import { FUNCTIONS_DIR, SECRET_TS_FILE } from './utils/paths.js';
12
+ const COMMANDS = {
13
+ get: 'Vedere il valore di una variabile (secret)',
14
+ list: 'Vedere tutte le variabili (secrets)',
15
+ set: 'Scrivere una variabile (secret)',
16
+ update: 'Aggiornare una variabile (secret)',
17
+ destroy: 'Eliminare una variabile (secret)',
18
+ syncToLocal: 'Allinea una key ONLINE in .secret.local',
19
+ reviveFromLocal: 'Revive da .secret.local (commentate con valore)',
20
+ exit: 'Esci'
21
+ };
3
22
  async function main() {
4
- const cmd = await select({
5
- message: 'Firebase Secrets CLI',
6
- choices: [
7
- { name: 'Ping', value: 'ping' },
8
- { name: 'Exit', value: 'exit' }
9
- ]
10
- });
11
- if (cmd === 'ping')
12
- console.log('pong');
23
+ // fail-fast: se manca qualcosa, errore ed exit subito
24
+ try {
25
+ assertPathsExist([SECRET_TS_FILE, FUNCTIONS_DIR]);
26
+ }
27
+ catch (err) {
28
+ console.error('\n' + err.message);
29
+ process.exit(1);
30
+ }
31
+ while (true) {
32
+ const cmd = await select({
33
+ message: 'Firebase Secrets Manager',
34
+ choices: Object.keys(COMMANDS).map((key) => ({
35
+ name: COMMANDS[key],
36
+ value: key
37
+ }))
38
+ });
39
+ if (cmd === 'exit')
40
+ process.exit(0);
41
+ try {
42
+ if (cmd === 'get') {
43
+ const keys = parseExistingSecretKeysFromTs();
44
+ const key = await pickSecretKey({
45
+ message: 'Seleziona la secret da visualizzare',
46
+ keys,
47
+ otherLabel: 'Other… (scrivi a mano)'
48
+ });
49
+ hrLight();
50
+ const value = await runCapture(`firebase functions:secrets:access ${key}`, `Carico ${key}`);
51
+ console.log(coloredSecretKV(key, value));
52
+ hr();
53
+ continue;
54
+ }
55
+ if (cmd === 'list') {
56
+ const { ok } = await inquirer.prompt([
57
+ {
58
+ type: 'confirm',
59
+ name: 'ok',
60
+ message: 'Attenzione: verranno mostrati a schermo i VALORI dei secrets. Vuoi continuare?',
61
+ default: false
62
+ }
63
+ ]);
64
+ if (!ok)
65
+ continue;
66
+ const keys = parseExistingSecretKeysFromTs().sort((a, b) => a.localeCompare(b));
67
+ hrLight();
68
+ for (const key of keys) {
69
+ const value = await runCapture(`firebase functions:secrets:access ${key}`, `Carico ${key}`);
70
+ console.log(coloredSecretKV(key, value));
71
+ }
72
+ console.log('\n✔ Fine lista secrets');
73
+ hr();
74
+ continue;
75
+ }
76
+ if (cmd === 'set') {
77
+ const { name } = await inquirer.prompt([
78
+ { type: 'input', name: 'name', message: 'Nome secret', validate: (v) => !!v.trim() || 'Obbligatorio' }
79
+ ]);
80
+ const { value } = await inquirer.prompt([
81
+ { type: 'password', name: 'value', message: 'Valore secret', mask: '*', validate: (v) => !!v.trim() || 'Obbligatorio' }
82
+ ]);
83
+ const key = name.trim();
84
+ const val = value.trim();
85
+ hrLight();
86
+ // 1) online first
87
+ await setSecretOnline(key, val);
88
+ // 2) local files
89
+ upsertSecretLocalKey(key);
90
+ const existing = parseExistingSecretKeysFromTs();
91
+ writeSecretTs([...existing, key]);
92
+ console.log(`\n✔ Secret "${key}" salvata online + aggiornata .secret.local + secret.ts`);
93
+ hr();
94
+ continue;
95
+ }
96
+ if (cmd === 'update') {
97
+ const keys = parseExistingSecretKeysFromTs();
98
+ const key = await pickSecretKey({
99
+ message: 'Seleziona la secret da aggiornare',
100
+ keys,
101
+ otherLabel: 'Other… (scrivi a mano)'
102
+ });
103
+ const { value } = await inquirer.prompt([
104
+ { type: 'password', name: 'value', message: `Nuovo valore per ${key}`, mask: '*', validate: (v) => !!v.trim() || 'Obbligatorio' }
105
+ ]);
106
+ const val = value.trim();
107
+ hrLight();
108
+ // 1) online first
109
+ await setSecretOnline(key, val);
110
+ // 2) local files
111
+ upsertSecretLocalKey(key); // mantiene KEY= (se era commentata la lascia commentata: ok per set/update)
112
+ const existing = parseExistingSecretKeysFromTs();
113
+ writeSecretTs([...existing, key]);
114
+ console.log(`\n✔ Secret "${key}" aggiornata online + aggiornata .secret.local + secret.ts`);
115
+ hr();
116
+ continue;
117
+ }
118
+ if (cmd === 'destroy') {
119
+ const keys = parseExistingSecretKeysFromTs();
120
+ const key = await pickSecretKey({
121
+ message: 'Seleziona la secret da eliminare',
122
+ keys,
123
+ otherLabel: 'Other… (scrivi a mano)'
124
+ });
125
+ const { ok } = await inquirer.prompt([
126
+ { type: 'confirm', name: 'ok', message: `Confermi eliminazione ONLINE di "${key}"?`, default: false }
127
+ ]);
128
+ if (!ok)
129
+ continue;
130
+ hrLight();
131
+ // 1) elimina online senza ulteriore prompt Firebase
132
+ await run(`firebase functions:secrets:destroy ${key} --force`);
133
+ // 2) aggiorna files locali SOLO se online è andata a buon fine
134
+ commentSecretLocalKey(key);
135
+ const existing = parseExistingSecretKeysFromTs();
136
+ const updated = removeSecretKeyFromTs(existing, key);
137
+ writeSecretTs(updated);
138
+ console.log(`\n✔ Secret "${key}" eliminata online + aggiornata .secret.local + secret.ts`);
139
+ hr();
140
+ continue;
141
+ }
142
+ if (cmd === 'syncToLocal') {
143
+ const keys = parseExistingSecretKeysFromTs();
144
+ const key = await pickSecretKey({
145
+ message: 'Seleziona la secret da allineare in .secret.local',
146
+ keys,
147
+ otherLabel: 'Other… (scrivi a mano)'
148
+ });
149
+ hrLight();
150
+ const value = await runCapture(`firebase functions:secrets:access ${key}`, `Carico ${key}`);
151
+ upsertSecretLocalKeyValue(key, value);
152
+ console.log(`\n✔ Allineata ${key} in functions/.secret.local`);
153
+ hr();
154
+ continue;
155
+ }
156
+ if (cmd === 'reviveFromLocal') {
157
+ const candidates = listCommentedSecretsWithValue();
158
+ if (candidates.length === 0) {
159
+ console.log('\nℹ Nessuna secret commentata con valore trovata in functions/.secret.local');
160
+ hr();
161
+ continue;
162
+ }
163
+ const key = await pickSecretKey({
164
+ message: 'Seleziona la secret da ripristinare (revive)',
165
+ keys: candidates.map((c) => c.key),
166
+ otherLabel: 'Other… (scrivi a mano)'
167
+ });
168
+ const found = candidates.find((c) => c.key === key);
169
+ if (!found) {
170
+ console.log(`\n❌ La key "${key}" non è tra le commentate con valore in .secret.local`);
171
+ hr();
172
+ continue;
173
+ }
174
+ hrLight();
175
+ // 1) push online
176
+ await setSecretOnline(key, found.value);
177
+ // 1.5) aggiungi key a secret.ts
178
+ const existing = parseExistingSecretKeysFromTs();
179
+ writeSecretTs([...existing, key]);
180
+ // 2) decommenta + set value in .secret.local
181
+ uncommentAndSetSecretLocal(key, found.value);
182
+ console.log(`\n✔ Revive completato: ${coloredSecretKV(key, found.value)}`);
183
+ hr();
184
+ continue;
185
+ }
186
+ }
187
+ catch (err) {
188
+ console.error('\n❌ Errore:', err.message);
189
+ }
190
+ }
13
191
  }
14
192
  main();
15
193
  //# sourceMappingURL=firebase-secrets.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"firebase-secrets.js","sourceRoot":"","sources":["../src/firebase-secrets.ts"],"names":[],"mappings":";AACA,OAAO,MAAM,MAAM,kBAAkB,CAAA;AAErC,KAAK,UAAU,IAAI;IACf,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC;QACrB,OAAO,EAAE,sBAAsB;QAC/B,OAAO,EAAE;YACL,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE;YAC/B,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE;SAClC;KACJ,CAAC,CAAA;IAEF,IAAI,GAAG,KAAK,MAAM;QAAE,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAA;AAC3C,CAAC;AAED,IAAI,EAAE,CAAA"}
1
+ {"version":3,"file":"firebase-secrets.js","sourceRoot":"","sources":["../src/firebase-secrets.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,146 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ /**
4
+ * Risolve la root del progetto Firebase risalendo le cartelle a partire da process.cwd().
5
+ * Condizioni per essere considerata root:
6
+ * - esiste firebase.json
7
+ * - esiste package.json
8
+ * - esiste la cartella functions
9
+ *
10
+ * Sicurezza anti-loop:
11
+ * - si ferma quando parent === current (root del filesystem)
12
+ * - ha un maxDepth failsafe
13
+ */
14
+ export function getProjectRoot(startDir = process.cwd(), maxDepth = 5) {
15
+ let current = path.resolve(startDir);
16
+ let depth = 0;
17
+ while (depth < maxDepth) {
18
+ const hasFirebaseJson = fs.existsSync(path.join(current, 'firebase.json'));
19
+ const hasPackageJson = fs.existsSync(path.join(current, 'package.json'));
20
+ const hasFunctionsDir = isDir(path.join(current, 'functions'));
21
+ if (hasFirebaseJson && hasPackageJson && hasFunctionsDir) {
22
+ return current;
23
+ }
24
+ const parent = path.dirname(current);
25
+ // ✅ anti-loop: siamo arrivati in cima al filesystem
26
+ if (parent === current)
27
+ break;
28
+ current = parent;
29
+ depth++;
30
+ }
31
+ throw new Error('❌ Project root not found. Expected firebase.json + package.json + functions/ in the same directory. ' +
32
+ `Start dir: ${startDir}`);
33
+ }
34
+ /**
35
+ * Restituisce un path assoluto relativo alla root del progetto (risolta automaticamente).
36
+ * Esempio: projectPath('functions', '.secret.local')
37
+ */
38
+ export function projectPath(...segments) {
39
+ const root = getProjectRoot();
40
+ return path.join(root, ...segments);
41
+ }
42
+ /**
43
+ * Verifica che un percorso esista ed è una directory.
44
+ */
45
+ export function isDir(dirPath) {
46
+ try {
47
+ return fs.statSync(dirPath).isDirectory();
48
+ }
49
+ catch {
50
+ return false;
51
+ }
52
+ }
53
+ /**
54
+ * Verifica che un percorso esista ed è un file.
55
+ */
56
+ export function isFile(filePath) {
57
+ try {
58
+ return fs.statSync(filePath).isFile();
59
+ }
60
+ catch {
61
+ return false;
62
+ }
63
+ }
64
+ /**
65
+ * Controllo generico: assicura che esista una directory.
66
+ * Lancia errore con messaggio chiaro se manca.
67
+ */
68
+ export function ensureDirExists(dirPath, label) {
69
+ if (!isDir(dirPath)) {
70
+ throw new Error(`❌ Directory not found: ${label ?? dirPath}`);
71
+ }
72
+ }
73
+ /**
74
+ * Controllo generico: assicura che esista un file.
75
+ * Lancia errore con messaggio chiaro se manca.
76
+ */
77
+ export function ensureFileExists(filePath, label) {
78
+ if (!isFile(filePath)) {
79
+ throw new Error(`❌ File not found: ${label ?? filePath}`);
80
+ }
81
+ }
82
+ /**
83
+ * Utility: crea un file vuoto se non esiste (senza sovrascrivere).
84
+ * Utile per `.secret.local` al primo avvio.
85
+ */
86
+ export function ensureFile(filePath, initialContent = '') {
87
+ if (!fs.existsSync(filePath)) {
88
+ fs.mkdirSync(path.dirname(filePath), { recursive: true });
89
+ fs.writeFileSync(filePath, initialContent, 'utf8');
90
+ }
91
+ }
92
+ /**
93
+ * Bootstrap “coerente” per la CLI:
94
+ * - valida di essere dentro un progetto Firebase (root detection)
95
+ * - valida che esista functions/
96
+ * - valida che esista secret.ts (obbligatorio per la tua CLI)
97
+ * - crea .secret.local se manca
98
+ *
99
+ * Ritorna i path risolti così li puoi usare subito.
100
+ */
101
+ export function bootstrapProjectFs() {
102
+ const rootDir = getProjectRoot();
103
+ const functionsDir = path.join(rootDir, 'functions');
104
+ const secretLocalFile = path.join(functionsDir, '.secret.local');
105
+ const secretTsFile = path.join(functionsDir, 'src', 'config', 'secret.ts');
106
+ ensureDirExists(functionsDir, 'functions/');
107
+ ensureFileExists(path.join(rootDir, 'firebase.json'), 'firebase.json');
108
+ ensureFileExists(path.join(rootDir, 'package.json'), 'package.json');
109
+ // per la tua CLI: secret.ts deve esistere
110
+ ensureFileExists(secretTsFile, 'functions/src/config/secret.ts');
111
+ // .secret.local può essere creato automaticamente
112
+ ensureFile(secretLocalFile, '');
113
+ return { rootDir, functionsDir, secretLocalFile, secretTsFile };
114
+ }
115
+ /**
116
+ * Controlla che una lista di path (file o directory) esista.
117
+ * NON crea nulla.
118
+ *
119
+ * Ritorna:
120
+ * - existing: path trovati
121
+ * - missing: path mancanti
122
+ */
123
+ export function checkPathsExist(paths) {
124
+ const existing = [];
125
+ const missing = [];
126
+ for (const p of paths) {
127
+ if (fs.existsSync(p)) {
128
+ existing.push(p);
129
+ }
130
+ else {
131
+ missing.push(p);
132
+ }
133
+ }
134
+ return { existing, missing };
135
+ }
136
+ /**
137
+ * Controlla che una lista di path (file o directory) esista, ma se manca qualcosa lancia errore (fail-fast).
138
+ */
139
+ export function assertPathsExist(paths) {
140
+ const { missing } = checkPathsExist(paths);
141
+ if (missing.length > 0) {
142
+ throw new Error('❌ Missing required paths:\n' +
143
+ missing.map((p) => ` - ${p}`).join('\n'));
144
+ }
145
+ }
146
+ //# sourceMappingURL=dir.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dir.js","sourceRoot":"","sources":["../../src/utils/dir.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAA;AACxB,OAAO,IAAI,MAAM,WAAW,CAAA;AAE5B;;;;;;;;;;GAUG;AACH,MAAM,UAAU,cAAc,CAAC,WAAmB,OAAO,CAAC,GAAG,EAAE,EAAE,WAAmB,CAAC;IACjF,IAAI,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAA;IACpC,IAAI,KAAK,GAAG,CAAC,CAAA;IAEb,OAAO,KAAK,GAAG,QAAQ,EAAE,CAAC;QACtB,MAAM,eAAe,GAAG,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,eAAe,CAAC,CAAC,CAAA;QAC1E,MAAM,cAAc,GAAG,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,cAAc,CAAC,CAAC,CAAA;QACxE,MAAM,eAAe,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC,CAAA;QAE9D,IAAI,eAAe,IAAI,cAAc,IAAI,eAAe,EAAE,CAAC;YACvD,OAAO,OAAO,CAAA;QAClB,CAAC;QAED,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAA;QAEpC,oDAAoD;QACpD,IAAI,MAAM,KAAK,OAAO;YAAE,MAAK;QAE7B,OAAO,GAAG,MAAM,CAAA;QAChB,KAAK,EAAE,CAAA;IACX,CAAC;IAED,MAAM,IAAI,KAAK,CACX,sGAAsG;QACtG,cAAc,QAAQ,EAAE,CAC3B,CAAA;AACL,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,WAAW,CAAC,GAAG,QAAkB;IAC7C,MAAM,IAAI,GAAG,cAAc,EAAE,CAAA;IAC7B,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,QAAQ,CAAC,CAAA;AACvC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,KAAK,CAAC,OAAe;IACjC,IAAI,CAAC;QACD,OAAO,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,WAAW,EAAE,CAAA;IAC7C,CAAC;IAAC,MAAM,CAAC;QACL,OAAO,KAAK,CAAA;IAChB,CAAC;AACL,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,MAAM,CAAC,QAAgB;IACnC,IAAI,CAAC;QACD,OAAO,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,MAAM,EAAE,CAAA;IACzC,CAAC;IAAC,MAAM,CAAC;QACL,OAAO,KAAK,CAAA;IAChB,CAAC;AACL,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,OAAe,EAAE,KAAc;IAC3D,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC;QAClB,MAAM,IAAI,KAAK,CAAC,0BAA0B,KAAK,IAAI,OAAO,EAAE,CAAC,CAAA;IACjE,CAAC;AACL,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAAC,QAAgB,EAAE,KAAc;IAC7D,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC;QACpB,MAAM,IAAI,KAAK,CAAC,qBAAqB,KAAK,IAAI,QAAQ,EAAE,CAAC,CAAA;IAC7D,CAAC;AACL,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,UAAU,CAAC,QAAgB,EAAE,cAAc,GAAG,EAAE;IAC5D,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC3B,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;QACzD,EAAE,CAAC,aAAa,CAAC,QAAQ,EAAE,cAAc,EAAE,MAAM,CAAC,CAAA;IACtD,CAAC;AACL,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,kBAAkB;IAM9B,MAAM,OAAO,GAAG,cAAc,EAAE,CAAA;IAChC,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,WAAW,CAAC,CAAA;IACpD,MAAM,eAAe,GAAG,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,eAAe,CAAC,CAAA;IAChE,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,KAAK,EAAE,QAAQ,EAAE,WAAW,CAAC,CAAA;IAE1E,eAAe,CAAC,YAAY,EAAE,YAAY,CAAC,CAAA;IAC3C,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,eAAe,CAAC,EAAE,eAAe,CAAC,CAAA;IACtE,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,cAAc,CAAC,EAAE,cAAc,CAAC,CAAA;IAEpE,0CAA0C;IAC1C,gBAAgB,CAAC,YAAY,EAAE,gCAAgC,CAAC,CAAA;IAEhE,kDAAkD;IAClD,UAAU,CAAC,eAAe,EAAE,EAAE,CAAC,CAAA;IAE/B,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,YAAY,EAAE,CAAA;AACnE,CAAC;AAGD;;;;;;;GAOG;AACH,MAAM,UAAU,eAAe,CAAC,KAAe;IAI3C,MAAM,QAAQ,GAAa,EAAE,CAAA;IAC7B,MAAM,OAAO,GAAa,EAAE,CAAA;IAE5B,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;QACpB,IAAI,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC;YACnB,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;QACpB,CAAC;aAAM,CAAC;YACJ,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;QACnB,CAAC;IACL,CAAC;IAED,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAA;AAChC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,KAAe;IAC5C,MAAM,EAAE,OAAO,EAAE,GAAG,eAAe,CAAC,KAAK,CAAC,CAAA;IAC1C,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACrB,MAAM,IAAI,KAAK,CACX,6BAA6B;YAC7B,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAC3C,CAAA;IACL,CAAC;AACL,CAAC"}
@@ -0,0 +1,5 @@
1
+ import { runWithStdin } from './run.js';
2
+ export async function setSecretOnline(key, val) {
3
+ await runWithStdin(`firebase functions:secrets:set ${key}`, `${val}\n`);
4
+ }
5
+ //# sourceMappingURL=firebaseSecretCli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"firebaseSecretCli.js","sourceRoot":"","sources":["../../src/utils/firebaseSecretCli.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAA;AAEvC,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,GAAW,EAAE,GAAW;IAC1D,MAAM,YAAY,CAAC,kCAAkC,GAAG,EAAE,EAAE,GAAG,GAAG,IAAI,CAAC,CAAA;AAC3E,CAAC"}
@@ -0,0 +1,88 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ /**
4
+ * Cerca la root del progetto risalendo le cartelle e fermandosi in modo sicuro:
5
+ * - si ferma quando parent === current (root del filesystem)
6
+ * - maxDepth evita qualunque loop “strano”
7
+ *
8
+ * Per l'init NON richiediamo functions/ (perché potremmo doverla creare),
9
+ * ma richiediamo almeno:
10
+ * - firebase.json
11
+ * - package.json
12
+ */
13
+ function findProjectRootForInit(startDir = process.cwd(), maxDepth = 10) {
14
+ let current = path.resolve(startDir);
15
+ let depth = 0;
16
+ while (depth < maxDepth) {
17
+ const hasFirebaseJson = fs.existsSync(path.join(current, 'firebase.json'));
18
+ const hasPackageJson = fs.existsSync(path.join(current, 'package.json'));
19
+ if (hasFirebaseJson && hasPackageJson)
20
+ return current;
21
+ const parent = path.dirname(current);
22
+ if (parent === current)
23
+ break;
24
+ current = parent;
25
+ depth++;
26
+ }
27
+ throw new Error('❌ Project root not found for init. Expected firebase.json + package.json in the same directory (somewhere above).\n' +
28
+ `Start dir: ${startDir}`);
29
+ }
30
+ /**
31
+ * Crea una directory se non esiste (recursive).
32
+ * Se esiste già, non fa nulla.
33
+ */
34
+ function ensureDir(dirPath, created, alreadyExists) {
35
+ if (fs.existsSync(dirPath)) {
36
+ alreadyExists.push(dirPath);
37
+ return;
38
+ }
39
+ fs.mkdirSync(dirPath, { recursive: true });
40
+ created.push(dirPath);
41
+ }
42
+ /**
43
+ * Crea un file SOLO se non esiste.
44
+ * - se serve, crea anche la directory padre
45
+ * - non sovrascrive mai
46
+ */
47
+ function ensureFile(filePath, content, created, alreadyExists) {
48
+ if (fs.existsSync(filePath)) {
49
+ alreadyExists.push(filePath);
50
+ return;
51
+ }
52
+ fs.mkdirSync(path.dirname(filePath), { recursive: true });
53
+ fs.writeFileSync(filePath, content, 'utf8');
54
+ created.push(filePath);
55
+ }
56
+ /**
57
+ * Inizializza i file/cartelle minimi per la Firebase Secrets CLI.
58
+ * Cosa fa:
59
+ * - trova la root (firebase.json + package.json)
60
+ * - crea functions/ se manca
61
+ * - crea functions/.secret.local se manca (vuoto)
62
+ * - crea functions/src/config/secret.ts se manca (template con oggetto vuoto coerente con secretTs.ts)
63
+ *
64
+ * NON sovrascrive nulla se esiste già.
65
+ */
66
+ export function initFirebaseSecretsProject(startDir = process.cwd()) {
67
+ const rootDir = findProjectRootForInit(startDir);
68
+ const created = [];
69
+ const alreadyExists = [];
70
+ const functionsDir = path.join(rootDir, 'functions');
71
+ const secretLocalFile = path.join(functionsDir, '.secret.local');
72
+ const secretTsFile = path.join(functionsDir, 'src', 'config', 'secret.ts');
73
+ // 1) functions/
74
+ ensureDir(functionsDir, created, alreadyExists);
75
+ // 2) .secret.local (vuoto)
76
+ ensureFile(secretLocalFile, '', created, alreadyExists);
77
+ // 3) secret.ts (template coerente con parseExistingSecretKeysFromTs / writeSecretTs)
78
+ const secretTsTemplate = [
79
+ '// functions/src/config/secret.ts',
80
+ '',
81
+ 'export const secret = {',
82
+ '} as const;',
83
+ ''
84
+ ].join('\n');
85
+ ensureFile(secretTsFile, secretTsTemplate, created, alreadyExists);
86
+ return { rootDir, created, alreadyExists };
87
+ }
88
+ //# sourceMappingURL=init.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/utils/init.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ const RESET = '\x1b[0m';
2
+ const DIM = '\x1b[2m';
3
+ const COLORS = {
4
+ black: '\x1b[30m',
5
+ red: '\x1b[31m',
6
+ green: '\x1b[32m',
7
+ yellow: '\x1b[33m',
8
+ blue: '\x1b[34m',
9
+ magenta: '\x1b[35m',
10
+ cyan: '\x1b[36m',
11
+ white: '\x1b[37m',
12
+ gray: '\x1b[90m',
13
+ brightRed: '\x1b[91m',
14
+ brightGreen: '\x1b[92m',
15
+ brightYellow: '\x1b[93m',
16
+ brightBlue: '\x1b[94m',
17
+ brightMagenta: '\x1b[95m',
18
+ brightCyan: '\x1b[96m',
19
+ brightWhite: '\x1b[97m'
20
+ };
21
+ export function colorizer(text, color, dim = false) {
22
+ const c = COLORS[color];
23
+ const d = dim ? DIM : '';
24
+ return `${d}${c}${text}${RESET}`;
25
+ }
26
+ export function hrLight(color = 'cyan') { console.log(colorizer('-----------------------------------------------', color)); }
27
+ export function hr(color = 'cyan') { console.log(colorizer('===============================================', color)); }
28
+ export function coloredSecretKV(key, value) {
29
+ return `${colorizer(key, 'green')} ${colorizer('=', 'gray', true)} ${colorizer(value, 'magenta')}`;
30
+ }
31
+ //# sourceMappingURL=logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"AAAA,MAAM,KAAK,GAAG,SAAS,CAAA;AACvB,MAAM,GAAG,GAAG,SAAS,CAAA;AAErB,MAAM,MAAM,GAAG;IACX,KAAK,EAAE,UAAU;IACjB,GAAG,EAAE,UAAU;IACf,KAAK,EAAE,UAAU;IACjB,MAAM,EAAE,UAAU;IAClB,IAAI,EAAE,UAAU;IAChB,OAAO,EAAE,UAAU;IACnB,IAAI,EAAE,UAAU;IAChB,KAAK,EAAE,UAAU;IACjB,IAAI,EAAE,UAAU;IAChB,SAAS,EAAE,UAAU;IACrB,WAAW,EAAE,UAAU;IACvB,YAAY,EAAE,UAAU;IACxB,UAAU,EAAE,UAAU;IACtB,aAAa,EAAE,UAAU;IACzB,UAAU,EAAE,UAAU;IACtB,WAAW,EAAE,UAAU;CACjB,CAAA;AAIV,MAAM,UAAU,SAAS,CAAC,IAAY,EAAE,KAAe,EAAE,GAAG,GAAG,KAAK;IAChE,MAAM,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,CAAA;IACvB,MAAM,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAA;IACxB,OAAO,GAAG,CAAC,GAAG,CAAC,GAAG,IAAI,GAAG,KAAK,EAAE,CAAA;AACpC,CAAC;AAED,MAAM,UAAU,OAAO,CAAC,QAAkB,MAAM,IAAU,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,iDAAiD,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;AAC7I,MAAM,UAAU,EAAE,CAAC,QAAkB,MAAM,IAAU,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,iDAAiD,EAAE,KAAK,CAAC,CAAC,CAAA,CAAC,CAAC;AAEvI,MAAM,UAAU,eAAe,CAAC,GAAW,EAAE,KAAa;IACtD,OAAO,GAAG,SAAS,CAAC,GAAG,EAAE,OAAO,CAAC,IAAI,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,IAAI,SAAS,CAAC,KAAK,EAAE,SAAS,CAAC,EAAE,CAAA;AACtG,CAAC"}
@@ -0,0 +1,34 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ /**
4
+ * Incrementa la versione del package.json del progetto corrente.
5
+ * Default: patch
6
+ *
7
+ * @returns newVersion
8
+ */
9
+ export function bumpPackageVersion(type = 'patch', packageJsonPath = path.resolve(process.cwd(), 'package.json')) {
10
+ if (!fs.existsSync(packageJsonPath)) {
11
+ throw new Error(`package.json non trovato: ${packageJsonPath}`);
12
+ }
13
+ const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
14
+ if (typeof packageJson.version !== 'string') {
15
+ throw new Error('Campo "version" mancante o non valido in package.json');
16
+ }
17
+ const parts = packageJson.version.split('.').map(Number);
18
+ if (parts.length !== 3 || parts.some(Number.isNaN)) {
19
+ throw new Error(`Versione non valida in package.json: "${packageJson.version}" (attesa x.y.z)`);
20
+ }
21
+ const [major, minor, patch] = parts;
22
+ let next;
23
+ if (type === 'major')
24
+ next = [major + 1, 0, 0];
25
+ else if (type === 'minor')
26
+ next = [major, minor + 1, 0];
27
+ else
28
+ next = [major, minor, patch + 1];
29
+ const newVersion = next.join('.');
30
+ packageJson.version = newVersion;
31
+ fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2) + '\n', 'utf8');
32
+ return newVersion;
33
+ }
34
+ //# sourceMappingURL=package.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"package.js","sourceRoot":"","sources":["../../src/utils/package.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAA;AACxB,OAAO,IAAI,MAAM,WAAW,CAAA;AAI5B;;;;;GAKG;AACH,MAAM,UAAU,kBAAkB,CAC9B,OAAiB,OAAO,EACxB,eAAe,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,cAAc,CAAC;IAE7D,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,eAAe,CAAC,EAAE,CAAC;QAClC,MAAM,IAAI,KAAK,CAAC,6BAA6B,eAAe,EAAE,CAAC,CAAA;IACnE,CAAC;IAED,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,eAAe,EAAE,MAAM,CAAC,CAAC,CAAA;IAExE,IAAI,OAAO,WAAW,CAAC,OAAO,KAAK,QAAQ,EAAE,CAAC;QAC1C,MAAM,IAAI,KAAK,CAAC,uDAAuD,CAAC,CAAA;IAC5E,CAAC;IAED,MAAM,KAAK,GAAG,WAAW,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAA;IACxD,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;QACjD,MAAM,IAAI,KAAK,CACX,yCAAyC,WAAW,CAAC,OAAO,kBAAkB,CACjF,CAAA;IACL,CAAC;IAED,MAAM,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,GAAG,KAAK,CAAA;IAEnC,IAAI,IAAc,CAAA;IAClB,IAAI,IAAI,KAAK,OAAO;QAAE,IAAI,GAAG,CAAC,KAAK,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAA;SACzC,IAAI,IAAI,KAAK,OAAO;QAAE,IAAI,GAAG,CAAC,KAAK,EAAE,KAAK,GAAG,CAAC,EAAE,CAAC,CAAC,CAAA;;QAClD,IAAI,GAAG,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,GAAG,CAAC,CAAC,CAAA;IAErC,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;IACjC,WAAW,CAAC,OAAO,GAAG,UAAU,CAAA;IAEhC,EAAE,CAAC,aAAa,CACZ,eAAe,EACf,IAAI,CAAC,SAAS,CAAC,WAAW,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,EAC3C,MAAM,CACT,CAAA;IAED,OAAO,UAAU,CAAA;AACrB,CAAC"}
@@ -0,0 +1,14 @@
1
+ import { projectPath } from "./dir.js";
2
+ /**
3
+ * Path assoluto a functions/.secret.local (robusto: non dipende da process.cwd()).
4
+ */
5
+ export const SECRET_LOCAL_FILE = projectPath('functions', '.secret.local');
6
+ /**
7
+ * Path assoluto a functions/src/config/secret.ts (robusto: non dipende da process.cwd()).
8
+ */
9
+ export const SECRET_TS_FILE = projectPath('functions', 'src', 'config', 'secret.ts');
10
+ /**
11
+ * Path assoluto alla cartella functions/ (robusto: non dipende da process.cwd()).
12
+ */
13
+ export const FUNCTIONS_DIR = projectPath('functions');
14
+ //# sourceMappingURL=paths.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paths.js","sourceRoot":"","sources":["../../src/utils/paths.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAA;AAEtC;;GAEG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,WAAW,CAAC,WAAW,EAAE,eAAe,CAAC,CAAA;AAE1E;;GAEG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,WAAW,CAAC,WAAW,EAAE,KAAK,EAAE,QAAQ,EAAE,WAAW,CAAC,CAAA;AAEpF;;GAEG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,WAAW,CAAC,WAAW,CAAC,CAAA"}
@@ -0,0 +1,100 @@
1
+ import { spawn } from 'node:child_process';
2
+ /* ----------------------------------
3
+ * Spinner (riutilizzabile)
4
+ * ---------------------------------- */
5
+ const SPINNER_FRAMES = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
6
+ function createSpinner(label = 'loading ') {
7
+ const enabled = process.stdout.isTTY && !process.env.CI;
8
+ let i = 0;
9
+ let timer;
10
+ const start = () => {
11
+ if (!enabled)
12
+ return;
13
+ process.stdout.write(`${SPINNER_FRAMES[i]} ${label}`);
14
+ timer = setInterval(() => {
15
+ i = (i + 1) % SPINNER_FRAMES.length;
16
+ process.stdout.write(`\r${SPINNER_FRAMES[i]} ${label}`);
17
+ }, 80);
18
+ };
19
+ const stop = () => {
20
+ if (!enabled)
21
+ return;
22
+ if (timer)
23
+ clearInterval(timer);
24
+ process.stdout.write('\r\x1b[2K'); // clear line
25
+ };
26
+ return { start, stop };
27
+ }
28
+ /* ----------------------------------
29
+ * run (stdout diretto)
30
+ * ---------------------------------- */
31
+ export function run(command, label) {
32
+ return new Promise((resolve, reject) => {
33
+ const spinner = createSpinner(label);
34
+ spinner.start();
35
+ const child = spawn(command, { shell: true, stdio: 'inherit' });
36
+ child.on('error', (e) => {
37
+ spinner.stop();
38
+ reject(e);
39
+ });
40
+ child.on('exit', (code) => {
41
+ spinner.stop();
42
+ code === 0
43
+ ? resolve()
44
+ : reject(new Error(`Command failed (${code}): ${command}`));
45
+ });
46
+ });
47
+ }
48
+ /* ----------------------------------
49
+ * runWithStdin
50
+ * ---------------------------------- */
51
+ export function runWithStdin(command, stdinText, label) {
52
+ return new Promise((resolve, reject) => {
53
+ const spinner = createSpinner(label);
54
+ spinner.start();
55
+ const child = spawn(command, {
56
+ shell: true,
57
+ stdio: ['pipe', 'inherit', 'inherit']
58
+ });
59
+ child.on('error', (e) => {
60
+ spinner.stop();
61
+ reject(e);
62
+ });
63
+ child.on('exit', (code) => {
64
+ spinner.stop();
65
+ code === 0
66
+ ? resolve()
67
+ : reject(new Error(`Command failed (${code}): ${command}`));
68
+ });
69
+ child.stdin?.write(stdinText);
70
+ child.stdin?.end();
71
+ });
72
+ }
73
+ /* ----------------------------------
74
+ * runCapture (stdout catturato)
75
+ * ---------------------------------- */
76
+ export function runCapture(command, label) {
77
+ return new Promise((resolve, reject) => {
78
+ const spinner = createSpinner(label);
79
+ spinner.start();
80
+ const child = spawn(command, {
81
+ shell: true,
82
+ stdio: ['ignore', 'pipe', 'pipe']
83
+ });
84
+ let out = '';
85
+ let err = '';
86
+ child.stdout.on('data', (d) => (out += d.toString()));
87
+ child.stderr.on('data', (d) => (err += d.toString()));
88
+ child.on('error', (e) => {
89
+ spinner.stop();
90
+ reject(e);
91
+ });
92
+ child.on('exit', (code) => {
93
+ spinner.stop();
94
+ code === 0
95
+ ? resolve(out.trim())
96
+ : reject(new Error(err || `Command failed (${code}): ${command}`));
97
+ });
98
+ });
99
+ }
100
+ //# sourceMappingURL=run.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run.js","sourceRoot":"","sources":["../../src/utils/run.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ import select from '@inquirer/select';
2
+ import inquirer from 'inquirer';
3
+ export async function pickSecretKey(opts) {
4
+ const otherLabel = opts.otherLabel ?? 'Other…';
5
+ const choices = [
6
+ ...opts.keys
7
+ .slice()
8
+ .sort((a, b) => a.localeCompare(b))
9
+ .map((k) => ({ name: k, value: k })),
10
+ { name: otherLabel, value: '__OTHER__' }
11
+ ];
12
+ const picked = await select({
13
+ message: opts.message,
14
+ choices
15
+ });
16
+ if (picked !== '__OTHER__')
17
+ return picked;
18
+ const { name } = await inquirer.prompt([
19
+ {
20
+ type: 'input',
21
+ name: 'name',
22
+ message: 'Nome secret',
23
+ validate: (v) => !!v.trim() || 'Obbligatorio'
24
+ }
25
+ ]);
26
+ return name.trim();
27
+ }
28
+ //# sourceMappingURL=secretKeyPicker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"secretKeyPicker.js","sourceRoot":"","sources":["../../src/utils/secretKeyPicker.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,kBAAkB,CAAA;AACrC,OAAO,QAAQ,MAAM,UAAU,CAAA;AAE/B,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,IAInC;IACC,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,IAAI,QAAQ,CAAA;IAE9C,MAAM,OAAO,GAAG;QACd,GAAG,IAAI,CAAC,IAAI;aACT,KAAK,EAAE;aACP,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;aAClC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC;QACtC,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,WAAoB,EAAE;KAClD,CAAA;IAED,MAAM,MAAM,GAAG,MAAM,MAAM,CAAS;QAClC,OAAO,EAAE,IAAI,CAAC,OAAO;QACrB,OAAO;KACR,CAAC,CAAA;IAEF,IAAI,MAAM,KAAK,WAAW;QAAE,OAAO,MAAM,CAAA;IAEzC,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,QAAQ,CAAC,MAAM,CAAmB;QACvD;YACE,IAAI,EAAE,OAAO;YACb,IAAI,EAAE,MAAM;YACZ,OAAO,EAAE,aAAa;YACtB,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,IAAI,cAAc;SAC9C;KACF,CAAC,CAAA;IAEF,OAAO,IAAI,CAAC,IAAI,EAAE,CAAA;AACpB,CAAC"}
@@ -0,0 +1,105 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { SECRET_LOCAL_FILE } from './paths.js';
4
+ function ensureFileDir(filePath) {
5
+ fs.mkdirSync(path.dirname(filePath), { recursive: true });
6
+ }
7
+ function readLines(filePath) {
8
+ if (!fs.existsSync(filePath))
9
+ return [];
10
+ return fs
11
+ .readFileSync(filePath, 'utf-8')
12
+ .split('\n')
13
+ .map((l) => l.trim())
14
+ .filter(Boolean);
15
+ }
16
+ export function upsertSecretLocalKey(key) {
17
+ ensureFileDir(SECRET_LOCAL_FILE);
18
+ const lines = readLines(SECRET_LOCAL_FILE);
19
+ const filtered = lines.filter((l) => !l.startsWith(`${key}=`));
20
+ filtered.push(`${key}=`); // solo KEY=
21
+ filtered.sort((a, b) => a.localeCompare(b));
22
+ fs.writeFileSync(SECRET_LOCAL_FILE, filtered.join('\n') + '\n', 'utf-8');
23
+ }
24
+ export function commentSecretLocalKey(key) {
25
+ ensureFileDir(SECRET_LOCAL_FILE);
26
+ const lines = readLines(SECRET_LOCAL_FILE);
27
+ const keyRegex = new RegExp(`^\\s*#?\\s*${key}=.*$`);
28
+ const updated = lines.map((line) => {
29
+ if (!keyRegex.test(line))
30
+ return line;
31
+ const trimmed = line.trim();
32
+ // già commentata → normalizza solo lo spazio
33
+ if (trimmed.startsWith('#')) {
34
+ return `# ${trimmed.replace(/^#+\s*/, '')}`;
35
+ }
36
+ // non commentata → commenta mantenendo valore
37
+ return `# ${trimmed}`;
38
+ });
39
+ fs.writeFileSync(SECRET_LOCAL_FILE, updated.join('\n'), 'utf-8');
40
+ }
41
+ export function upsertSecretLocalKeyValue(key, value) {
42
+ ensureFileDir(SECRET_LOCAL_FILE);
43
+ const lines = readLines(SECRET_LOCAL_FILE);
44
+ const rx = new RegExp(`^\\s*(#\\s*)?${key}=.*$`);
45
+ let found = false;
46
+ const updated = lines.map((line) => {
47
+ if (!rx.test(line))
48
+ return line;
49
+ found = true;
50
+ return `${key}=${value}`; // decommenta + set value
51
+ });
52
+ if (!found)
53
+ updated.push(`${key}=${value}`);
54
+ // opzionale: stabilità del file
55
+ const normalized = updated
56
+ .map((l) => l.trimEnd())
57
+ .filter((l) => l.length > 0);
58
+ fs.writeFileSync(SECRET_LOCAL_FILE, normalized.join('\n') + '\n', 'utf-8');
59
+ }
60
+ export function listCommentedSecretsWithValue() {
61
+ ensureFileDir(SECRET_LOCAL_FILE);
62
+ const lines = readLines(SECRET_LOCAL_FILE);
63
+ const out = [];
64
+ for (const line of lines) {
65
+ const trimmed = line.trim();
66
+ // Solo commentate
67
+ if (!trimmed.startsWith('#'))
68
+ continue;
69
+ // rimuovi il commento: "#", "# ", "## " ecc.
70
+ const uncommented = trimmed.replace(/^#+\s*/, '');
71
+ const eq = uncommented.indexOf('=');
72
+ if (eq <= 0)
73
+ continue;
74
+ const key = uncommented.slice(0, eq).trim();
75
+ const value = uncommented.slice(eq + 1);
76
+ if (!key)
77
+ continue;
78
+ if (value.trim().length === 0)
79
+ continue; // value non deve essere solo spazi
80
+ out.push({ key, value: value.trim() });
81
+ }
82
+ // dedup: ultima occorrenza vince
83
+ const map = new Map();
84
+ for (const item of out)
85
+ map.set(item.key, item.value);
86
+ return Array.from(map.entries())
87
+ .map(([key, value]) => ({ key, value }))
88
+ .sort((a, b) => a.key.localeCompare(b.key));
89
+ }
90
+ export function uncommentAndSetSecretLocal(key, value) {
91
+ ensureFileDir(SECRET_LOCAL_FILE);
92
+ const lines = readLines(SECRET_LOCAL_FILE);
93
+ const rx = new RegExp(`^\\s*(#\\s*)?${key}=.*$`);
94
+ let found = false;
95
+ const updated = lines.map((line) => {
96
+ if (!rx.test(line))
97
+ return line;
98
+ found = true;
99
+ return `${key}=${value}`; // decommenta + set value (preserva value)
100
+ });
101
+ if (!found)
102
+ updated.push(`${key}=${value}`);
103
+ fs.writeFileSync(SECRET_LOCAL_FILE, updated.join('\n') + '\n', 'utf-8');
104
+ }
105
+ //# sourceMappingURL=secretLocal.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"secretLocal.js","sourceRoot":"","sources":["../../src/utils/secretLocal.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,34 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { SECRET_TS_FILE } from './paths.js';
4
+ function ensureFileDir(filePath) {
5
+ fs.mkdirSync(path.dirname(filePath), { recursive: true });
6
+ }
7
+ export function parseExistingSecretKeysFromTs() {
8
+ if (!fs.existsSync(SECRET_TS_FILE))
9
+ return [];
10
+ const content = fs.readFileSync(SECRET_TS_FILE, 'utf-8');
11
+ const re = /^\s*([A-Z0-9_]+)\s*:\s*'([A-Z0-9_]+)'\s*,?\s*$/gm;
12
+ const keys = new Set();
13
+ let m;
14
+ while ((m = re.exec(content)))
15
+ keys.add(m[1]);
16
+ return Array.from(keys);
17
+ }
18
+ export function writeSecretTs(keys) {
19
+ ensureFileDir(SECRET_TS_FILE);
20
+ const unique = Array.from(new Set(keys)).sort((a, b) => a.localeCompare(b));
21
+ const lines = [
22
+ '// functions/src/config/secret.ts',
23
+ '',
24
+ 'export const secret = {',
25
+ ...unique.map((k) => ` ${k}: '${k}',`),
26
+ '} as const;',
27
+ ''
28
+ ];
29
+ fs.writeFileSync(SECRET_TS_FILE, lines.join('\n'), 'utf-8');
30
+ }
31
+ export function removeSecretKeyFromTs(keys, keyToRemove) {
32
+ return keys.filter((k) => k !== keyToRemove);
33
+ }
34
+ //# sourceMappingURL=secretTs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"secretTs.js","sourceRoot":"","sources":["../../src/utils/secretTs.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAA;AACxB,OAAO,IAAI,MAAM,WAAW,CAAA;AAC5B,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAE3C,SAAS,aAAa,CAAC,QAAgB;IACrC,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;AAC3D,CAAC;AAED,MAAM,UAAU,6BAA6B;IAC3C,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,cAAc,CAAC;QAAE,OAAO,EAAE,CAAA;IAC7C,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,cAAc,EAAE,OAAO,CAAC,CAAA;IAExD,MAAM,EAAE,GAAG,kDAAkD,CAAA;IAC7D,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAA;IAC9B,IAAI,CAAyB,CAAA;IAE7B,OAAO,CAAC,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;IAE7C,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;AACzB,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,IAAc;IAC1C,aAAa,CAAC,cAAc,CAAC,CAAA;IAE7B,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAA;IAE3E,MAAM,KAAK,GAAG;QACZ,mCAAmC;QACnC,EAAE;QACF,yBAAyB;QACzB,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC;QACzC,aAAa;QACb,EAAE;KACH,CAAA;IAED,EAAE,CAAC,aAAa,CAAC,cAAc,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC,CAAA;AAC7D,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,IAAc,EAAE,WAAmB;IACvE,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,WAAW,CAAC,CAAA;AAC9C,CAAC"}
package/package.json CHANGED
@@ -1,9 +1,11 @@
1
1
  {
2
2
  "name": "firebase-secrets-cli",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "type": "module",
5
5
  "bin": {
6
- "firebase-secrets": "./dist/firebase-secrets.js"
6
+ "firebase-secrets": "./dist/firebase-secrets.js",
7
+ "cic:index": "./dist/cic-index.js",
8
+ "cic:bump": "./dist/bump.js"
7
9
  },
8
10
  "files": [
9
11
  "dist"
@@ -11,7 +13,9 @@
11
13
  "scripts": {
12
14
  "clean": "node -e \"require('fs').rmSync('dist',{recursive:true,force:true})\"",
13
15
  "build": "npm run clean && tsc -p tsconfig.json",
14
- "pack": "npm run build && npm pack"
16
+ "pack": "npm run build && npm pack",
17
+ "deploy": "npm run build && node scripts/bump-version.cjs && npm pack && npm publish --access public",
18
+ "start": "npm run build && node dist/cic-index.js"
15
19
  },
16
20
  "dependencies": {
17
21
  "@inquirer/select": "^5.0.4",
@@ -21,4 +25,4 @@
21
25
  "@types/node": "^25.0.10",
22
26
  "typescript": "^5.9.3"
23
27
  }
24
- }
28
+ }