firebase-secrets-cli 0.1.0 → 0.1.3
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 +120 -0
- package/dist/bump.js +43 -0
- package/dist/bump.js.map +1 -0
- package/dist/cic-index.js +53 -0
- package/dist/cic-index.js.map +1 -0
- package/dist/firebase-secrets.js +188 -10
- package/dist/firebase-secrets.js.map +1 -1
- package/dist/utils/dir.js +146 -0
- package/dist/utils/dir.js.map +1 -0
- package/dist/utils/firebaseSecretCli.js +5 -0
- package/dist/utils/firebaseSecretCli.js.map +1 -0
- package/dist/utils/init.js +88 -0
- package/dist/utils/init.js.map +1 -0
- package/dist/utils/logger.js +31 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/package.js +34 -0
- package/dist/utils/package.js.map +1 -0
- package/dist/utils/paths.js +14 -0
- package/dist/utils/paths.js.map +1 -0
- package/dist/utils/run.js +100 -0
- package/dist/utils/run.js.map +1 -0
- package/dist/utils/secretKeyPicker.js +28 -0
- package/dist/utils/secretKeyPicker.js.map +1 -0
- package/dist/utils/secretLocal.js +105 -0
- package/dist/utils/secretLocal.js.map +1 -0
- package/dist/utils/secretTs.js +34 -0
- package/dist/utils/secretTs.js.map +1 -0
- package/package.json +8 -4
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
|
package/dist/bump.js.map
ADDED
|
@@ -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"}
|
package/dist/firebase-secrets.js
CHANGED
|
@@ -1,15 +1,193 @@
|
|
|
1
|
-
#!/usr/bin/env
|
|
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
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
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":";
|
|
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":"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"}
|
|
@@ -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.
|
|
3
|
+
"version": "0.1.3",
|
|
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
|
+
}
|