@asafarim/envage 0.1.0

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.
Files changed (63) hide show
  1. package/README.md +367 -0
  2. package/bin/envage.js +11 -0
  3. package/dist/cli/commands/decrypt.d.ts +12 -0
  4. package/dist/cli/commands/decrypt.d.ts.map +1 -0
  5. package/dist/cli/commands/decrypt.js +91 -0
  6. package/dist/cli/commands/decrypt.js.map +1 -0
  7. package/dist/cli/commands/encrypt.d.ts +11 -0
  8. package/dist/cli/commands/encrypt.d.ts.map +1 -0
  9. package/dist/cli/commands/encrypt.js +95 -0
  10. package/dist/cli/commands/encrypt.js.map +1 -0
  11. package/dist/cli/commands/init-key.d.ts +13 -0
  12. package/dist/cli/commands/init-key.d.ts.map +1 -0
  13. package/dist/cli/commands/init-key.js +32 -0
  14. package/dist/cli/commands/init-key.js.map +1 -0
  15. package/dist/cli/commands/status.d.ts +11 -0
  16. package/dist/cli/commands/status.d.ts.map +1 -0
  17. package/dist/cli/commands/status.js +73 -0
  18. package/dist/cli/commands/status.js.map +1 -0
  19. package/dist/cli/index.d.ts +13 -0
  20. package/dist/cli/index.d.ts.map +1 -0
  21. package/dist/cli/index.js +44 -0
  22. package/dist/cli/index.js.map +1 -0
  23. package/dist/cli/prompt.d.ts +9 -0
  24. package/dist/cli/prompt.d.ts.map +1 -0
  25. package/dist/cli/prompt.js +62 -0
  26. package/dist/cli/prompt.js.map +1 -0
  27. package/dist/index.d.ts +16 -0
  28. package/dist/index.d.ts.map +1 -0
  29. package/dist/index.js +15 -0
  30. package/dist/index.js.map +1 -0
  31. package/dist/lib/config.d.ts +16 -0
  32. package/dist/lib/config.d.ts.map +1 -0
  33. package/dist/lib/config.js +41 -0
  34. package/dist/lib/config.js.map +1 -0
  35. package/dist/lib/decrypt.d.ts +10 -0
  36. package/dist/lib/decrypt.d.ts.map +1 -0
  37. package/dist/lib/decrypt.js +60 -0
  38. package/dist/lib/decrypt.js.map +1 -0
  39. package/dist/lib/encrypt.d.ts +20 -0
  40. package/dist/lib/encrypt.d.ts.map +1 -0
  41. package/dist/lib/encrypt.js +75 -0
  42. package/dist/lib/encrypt.js.map +1 -0
  43. package/dist/lib/gitignore.d.ts +19 -0
  44. package/dist/lib/gitignore.d.ts.map +1 -0
  45. package/dist/lib/gitignore.js +82 -0
  46. package/dist/lib/gitignore.js.map +1 -0
  47. package/dist/lib/keygen.d.ts +30 -0
  48. package/dist/lib/keygen.d.ts.map +1 -0
  49. package/dist/lib/keygen.js +66 -0
  50. package/dist/lib/keygen.js.map +1 -0
  51. package/dist/lib/logger.d.ts +21 -0
  52. package/dist/lib/logger.d.ts.map +1 -0
  53. package/dist/lib/logger.js +52 -0
  54. package/dist/lib/logger.js.map +1 -0
  55. package/dist/lib/status.d.ts +14 -0
  56. package/dist/lib/status.d.ts.map +1 -0
  57. package/dist/lib/status.js +50 -0
  58. package/dist/lib/status.js.map +1 -0
  59. package/dist/types.d.ts +40 -0
  60. package/dist/types.d.ts.map +1 -0
  61. package/dist/types.js +8 -0
  62. package/dist/types.js.map +1 -0
  63. package/package.json +65 -0
package/README.md ADDED
@@ -0,0 +1,367 @@
1
+ # @asafarim/envage
2
+
3
+ > **Secure, age-based encryption for `.env` files across monorepo environments.**
4
+
5
+ `envage` lets you safely commit encrypted `.env` files to Git while keeping the
6
+ decrypted secrets out of version control. It uses the battle-tested
7
+ [age](https://age-encryption.org) encryption format — the same tool used by
8
+ Go, Rust, and DevSecOps toolchains worldwide.
9
+
10
+ ---
11
+
12
+ ## Features
13
+
14
+ - 🔐 **age encryption** — uses `age-encryption` (pure TypeScript, no native deps)
15
+ - 🌍 **Multi-environment** — `dev`, `staging`, `prod` and any custom names
16
+ - 📁 **Monorepo-aware** — encrypt/decrypt all apps at once with `--all`
17
+ - 🔑 **Key or passphrase** — supports X25519 keypairs and passphrase-based encryption
18
+ - 🛡 **Git-safe** — auto-updates `.gitignore`; warns if you stage a decrypted file
19
+ - ✅ **Production guard** — interactive confirmation required to decrypt `prod` files
20
+ - 🧩 **Programmatic API** — use as a library in your own scripts
21
+ - 📦 **pnpm / monorepo friendly** — works seamlessly with pnpm workspaces
22
+
23
+ ---
24
+
25
+ ## Installation
26
+
27
+ ```bash
28
+ # In your monorepo root
29
+ pnpm add -D @asafarim/envage
30
+
31
+ # Or globally
32
+ pnpm add -g @asafarim/envage
33
+ ```
34
+
35
+ ---
36
+
37
+ ## Quick Start
38
+
39
+ ### 1. Generate a keypair
40
+
41
+ ```bash
42
+ npx envage init-key
43
+ ```
44
+
45
+ This creates:
46
+ ```
47
+ .age/key.txt ← private key (mode 0600, gitignored automatically)
48
+ .age/key.pub ← public key (safe to share with teammates)
49
+ ```
50
+
51
+ ### 2. Create your config
52
+
53
+ ```bash
54
+ # envage.config.json (at the monorepo root)
55
+ {
56
+ "apps": ["apps/web", "apps/admin", "packages/api"],
57
+ "envs": ["dev", "staging", "prod"],
58
+ "keyFile": ".age/key.txt"
59
+ }
60
+ ```
61
+
62
+ ### 3. Encrypt your env files
63
+
64
+ ```bash
65
+ # Encrypt a single app/env
66
+ npx envage encrypt apps/web --env dev
67
+
68
+ # Encrypt all apps at once
69
+ npx envage encrypt --all --env prod
70
+ ```
71
+
72
+ ### 4. Check status
73
+
74
+ ```bash
75
+ npx envage status
76
+ ```
77
+
78
+ ```
79
+ apps/web
80
+ dev 🔒 encrypted
81
+ staging 🔒 encrypted
82
+ prod 🔒 encrypted
83
+
84
+ apps/admin
85
+ dev 🔓 decrypted (not yet encrypted)
86
+ prod 🔒 encrypted
87
+
88
+ packages/api
89
+ dev 🔒 encrypted
90
+ prod 🔒 encrypted
91
+
92
+ 9 entries — 8 encrypted 1 decrypted
93
+ ```
94
+
95
+ ### 5. Decrypt on a new machine
96
+
97
+ ```bash
98
+ # Copy your private key to .age/key.txt (never commit it!)
99
+ npx envage decrypt apps/web --env dev
100
+
101
+ # Decrypt all at once
102
+ npx envage decrypt --all --env dev
103
+ ```
104
+
105
+ ---
106
+
107
+ ## CLI Reference
108
+
109
+ ### `envage init-key`
110
+
111
+ Generate a new age X25519 keypair.
112
+
113
+ ```bash
114
+ envage init-key [--output <folder>]
115
+ ```
116
+
117
+ | Option | Default | Description |
118
+ |--------|---------|-------------|
119
+ | `--output` | `.age` | Output folder for `key.txt` and `key.pub` |
120
+
121
+ ---
122
+
123
+ ### `envage encrypt`
124
+
125
+ Encrypt `.env.<env>` → `.env.<env>.age`.
126
+
127
+ ```bash
128
+ envage encrypt [path] [options]
129
+ ```
130
+
131
+ | Option | Default | Description |
132
+ |--------|---------|-------------|
133
+ | `--env` | `dev` | Environment name |
134
+ | `--key` | auto-detected | Path to age key file |
135
+ | `--passphrase` | — | Passphrase (prompted if omitted) |
136
+ | `--all` | — | Encrypt all apps in `envage.config.json` |
137
+
138
+ **Examples:**
139
+ ```bash
140
+ envage encrypt apps/web --env dev
141
+ envage encrypt apps/web --env prod --key .age/key.txt
142
+ envage encrypt --all --env staging
143
+ envage encrypt apps/web --env dev --passphrase "my secret"
144
+ ```
145
+
146
+ ---
147
+
148
+ ### `envage decrypt`
149
+
150
+ Decrypt `.env.<env>.age` → `.env.<env>`.
151
+
152
+ ```bash
153
+ envage decrypt [path] [options]
154
+ ```
155
+
156
+ | Option | Default | Description |
157
+ |--------|---------|-------------|
158
+ | `--env` | `dev` | Environment name |
159
+ | `--key` | auto-detected | Path to age private key file |
160
+ | `--passphrase` | — | Passphrase |
161
+ | `--all` | — | Decrypt all apps in `envage.config.json` |
162
+
163
+ > ⚠️ Decrypting `prod` or `production` environments always prompts for
164
+ > manual confirmation.
165
+
166
+ **Examples:**
167
+ ```bash
168
+ envage decrypt apps/web --env dev
169
+ envage decrypt --all --env prod
170
+ ```
171
+
172
+ ---
173
+
174
+ ### `envage status`
175
+
176
+ Show encryption status for all configured apps and environments.
177
+
178
+ ```bash
179
+ envage status [path]
180
+ ```
181
+
182
+ | Option | Description |
183
+ |--------|-------------|
184
+ | `--env` | Filter output to a single environment |
185
+
186
+ ---
187
+
188
+ ## Configuration — `envage.config.json`
189
+
190
+ Place this file at the root of your monorepo:
191
+
192
+ ```json
193
+ {
194
+ "apps": [
195
+ "apps/web",
196
+ "apps/admin",
197
+ "packages/api"
198
+ ],
199
+ "envs": ["dev", "staging", "prod"],
200
+ "keyFile": ".age/key.txt",
201
+ "keyPubFile": ".age/key.pub"
202
+ }
203
+ ```
204
+
205
+ | Field | Type | Default | Description |
206
+ |-------|------|---------|-------------|
207
+ | `apps` | `string[]` | `[]` | App folder paths (relative to cwd) |
208
+ | `envs` | `string[]` | `["dev","staging","prod"]` | Environment names to manage |
209
+ | `keyFile` | `string` | `.age/key.txt` | Path to private key |
210
+ | `keyPubFile` | `string` | `.age/key.pub` | Path to public key |
211
+
212
+ ---
213
+
214
+ ## Programmatic API
215
+
216
+ ```typescript
217
+ import {
218
+ encryptEnv,
219
+ decryptEnv,
220
+ generateKeyPair,
221
+ generateKeyPairToFolder,
222
+ getEnvStatus,
223
+ loadConfig,
224
+ ensureGitignore,
225
+ } from "@asafarim/envage";
226
+
227
+ // Generate a keypair
228
+ const { identity, recipient } = await generateKeyPair();
229
+
230
+ // Write keypair to disk
231
+ await generateKeyPairToFolder(".age");
232
+
233
+ // Encrypt a file (key-based)
234
+ await encryptEnv({
235
+ folder: "apps/web",
236
+ env: "dev",
237
+ keyFile: ".age/key.txt",
238
+ });
239
+
240
+ // Encrypt a file (passphrase-based)
241
+ await encryptEnv({
242
+ folder: "apps/web",
243
+ env: "dev",
244
+ passphrase: "my-secret-passphrase",
245
+ });
246
+
247
+ // Decrypt a file
248
+ await decryptEnv({
249
+ folder: "apps/web",
250
+ env: "dev",
251
+ keyFile: ".age/key.txt",
252
+ });
253
+
254
+ // Check status
255
+ const config = await loadConfig();
256
+ const statuses = await getEnvStatus(config);
257
+ statuses.forEach((s) => {
258
+ console.log(`${s.folder} [${s.env}]: encrypted=${s.encrypted} decrypted=${s.decrypted}`);
259
+ });
260
+
261
+ // Ensure .gitignore rules are present
262
+ await ensureGitignore();
263
+ ```
264
+
265
+ ---
266
+
267
+ ## Git Integration
268
+
269
+ ### `.gitignore` rules
270
+
271
+ Running `envage init-key` automatically adds these rules to your `.gitignore`:
272
+
273
+ ```gitignore
274
+ # --- envage managed ---
275
+ # Decrypted env files — never commit
276
+ .env*
277
+ !.env*.age
278
+ !.env.example
279
+ !.env.template
280
+ # Age private key
281
+ .age/key.txt
282
+ # --- end envage ---
283
+ ```
284
+
285
+ ### Staged file warning
286
+
287
+ If you accidentally `git add` a decrypted env file before encrypting, the
288
+ `encrypt` command will catch it and exit with:
289
+
290
+ ```
291
+ ✖ You are trying to commit a decrypted env file.
292
+ ✖ Only encrypted .age files are allowed.
293
+ apps/web/.env.prod
294
+ ```
295
+
296
+ ### Optional: pre-commit hook
297
+
298
+ Add this to `.git/hooks/pre-commit` to prevent accidental commits entirely:
299
+
300
+ ```bash
301
+ #!/usr/bin/env bash
302
+ npx envage status 2>/dev/null | grep -q "decrypted" && \
303
+ echo "❌ You have decrypted env files. Run: npx envage encrypt --all" && \
304
+ exit 1
305
+ exit 0
306
+ ```
307
+
308
+ ---
309
+
310
+ ## Monorepo Structure
311
+
312
+ ```
313
+ monorepo/
314
+ ├── .age/
315
+ │ ├── key.txt ← private key (gitignored)
316
+ │ └── key.pub ← public key (commit this)
317
+ ├── apps/
318
+ │ ├── web/
319
+ │ │ ├── .env.dev ← decrypted (gitignored)
320
+ │ │ ├── .env.dev.age ← encrypted (committed ✅)
321
+ │ │ ├── .env.prod ← decrypted (gitignored)
322
+ │ │ └── .env.prod.age← encrypted (committed ✅)
323
+ │ └── admin/
324
+ │ ├── .env.dev.age
325
+ │ └── .env.prod.age
326
+ ├── packages/
327
+ │ └── api/
328
+ │ ├── .env.dev.age
329
+ │ └── .env.prod.age
330
+ ├── envage.config.json ← committed ✅
331
+ └── .gitignore ← auto-updated by envage
332
+ ```
333
+
334
+ ---
335
+
336
+ ## Security Notes
337
+
338
+ - **Never commit `.age/key.txt`** — it is your private key. Share it with
339
+ teammates via a secrets manager (1Password, Vault, AWS SSM, etc.)
340
+ - **Decrypted values are never logged** — not in verbose mode, not in errors
341
+ - **Production decryption is gated** — always requires explicit `y` confirmation
342
+ - **Encrypted files are binary** — they cannot be accidentally read as text
343
+ - The `age` format provides authenticated encryption; tampering is detectable
344
+
345
+ ---
346
+
347
+ ## Development
348
+
349
+ ```bash
350
+ # Install dependencies
351
+ pnpm install
352
+
353
+ # Build
354
+ pnpm build
355
+
356
+ # Run tests
357
+ pnpm test
358
+
359
+ # Type-check only
360
+ pnpm lint
361
+ ```
362
+
363
+ ---
364
+
365
+ ## License
366
+
367
+ MIT © [Ali Safarim](https://github.com/asafarim)
package/bin/envage.js ADDED
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * @asafarim/envage CLI entrypoint
4
+ * Compiled output lives in dist/cli/index.js
5
+ */
6
+ import { runCLI } from "../dist/cli/index.js";
7
+
8
+ runCLI().catch((err) => {
9
+ console.error(err instanceof Error ? err.message : String(err));
10
+ process.exit(1);
11
+ });
@@ -0,0 +1,12 @@
1
+ /**
2
+ * CLI `decrypt` command.
3
+ *
4
+ * Usage:
5
+ * envage decrypt [path] [--env prod] [--key .age/key.txt]
6
+ * envage decrypt --all [--env prod]
7
+ *
8
+ * Production decryption always prompts for manual confirmation.
9
+ */
10
+ import type { Command } from "commander";
11
+ export declare function registerDecrypt(program: Command): void;
12
+ //# sourceMappingURL=decrypt.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"decrypt.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/decrypt.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAgBzC,wBAAgB,eAAe,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA6CtD"}
@@ -0,0 +1,91 @@
1
+ import path from "path";
2
+ import { decryptEnv } from "../../lib/decrypt.js";
3
+ import { loadConfig } from "../../lib/config.js";
4
+ import { logger } from "../../lib/logger.js";
5
+ import { confirm, promptPassphrase } from "../prompt.js";
6
+ const PROD_ENVS = new Set(["prod", "production"]);
7
+ export function registerDecrypt(program) {
8
+ program
9
+ .command("decrypt [path]")
10
+ .description("Decrypt .env.<env>.age → .env.<env>")
11
+ .option("-e, --env <env>", "environment name (e.g. dev, prod)", "dev")
12
+ .option("-k, --key <keyFile>", "path to age private key file (.age/key.txt)")
13
+ .option("-p, --passphrase <pass>", "passphrase for decryption")
14
+ .option("--all", "decrypt all apps defined in envage.config.json")
15
+ .action(async (folderArg, opts) => {
16
+ const envName = opts.env ?? "dev";
17
+ let keyFile = opts.key;
18
+ let passphrase = opts.passphrase;
19
+ // Production guard — always require explicit confirmation
20
+ if (PROD_ENVS.has(envName)) {
21
+ logger.warn(`You are about to decrypt PRODUCTION environment files.`);
22
+ const ok = await confirm("Are you sure you want to continue?");
23
+ if (!ok) {
24
+ logger.info("Aborted.");
25
+ process.exit(0);
26
+ }
27
+ }
28
+ // Resolve credential
29
+ if (!passphrase && !keyFile) {
30
+ const config = await loadConfig();
31
+ const defaultKey = config.keyFile;
32
+ try {
33
+ const { readIdentityFromFile } = await import("../../lib/keygen.js");
34
+ await readIdentityFromFile(path.resolve(process.cwd(), defaultKey));
35
+ keyFile = path.resolve(process.cwd(), defaultKey);
36
+ logger.detail(`Using key file: ${keyFile}`);
37
+ }
38
+ catch {
39
+ logger.info("No key file found. Enter the passphrase for decryption:");
40
+ passphrase = await promptPassphrase();
41
+ }
42
+ }
43
+ if (opts.all) {
44
+ await decryptAll(envName, keyFile, passphrase);
45
+ }
46
+ else {
47
+ const folder = folderArg ? path.resolve(process.cwd(), folderArg) : process.cwd();
48
+ await decryptOne(folder, envName, keyFile, passphrase);
49
+ }
50
+ });
51
+ }
52
+ async function decryptOne(folder, env, keyFile, passphrase) {
53
+ const fromFile = path.join(folder, `.env.${env}.age`);
54
+ const toFile = path.join(folder, `.env.${env}`);
55
+ logger.decrypting(fromFile, toFile);
56
+ try {
57
+ await decryptEnv({ folder, env, keyFile, passphrase });
58
+ logger.success("Done");
59
+ }
60
+ catch (err) {
61
+ const msg = err instanceof Error ? err.message : String(err);
62
+ logger.error(msg);
63
+ process.exit(1);
64
+ }
65
+ }
66
+ async function decryptAll(env, keyFile, passphrase) {
67
+ const config = await loadConfig();
68
+ if (config.apps.length === 0) {
69
+ logger.warn("No apps defined in envage.config.json. Nothing to decrypt.");
70
+ return;
71
+ }
72
+ let anyFailed = false;
73
+ for (const app of config.apps) {
74
+ const folder = path.resolve(process.cwd(), app);
75
+ const fromFile = path.join(folder, `.env.${env}.age`);
76
+ const toFile = path.join(folder, `.env.${env}`);
77
+ logger.decrypting(fromFile, toFile);
78
+ try {
79
+ await decryptEnv({ folder, env, keyFile, passphrase });
80
+ logger.success("Done");
81
+ }
82
+ catch (err) {
83
+ const msg = err instanceof Error ? err.message : String(err);
84
+ logger.error(msg);
85
+ anyFailed = true;
86
+ }
87
+ }
88
+ if (anyFailed)
89
+ process.exit(1);
90
+ }
91
+ //# sourceMappingURL=decrypt.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"decrypt.js","sourceRoot":"","sources":["../../../src/cli/commands/decrypt.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * CLI `encrypt` command.
3
+ *
4
+ * Usage:
5
+ * envage encrypt [path] [--env dev] [--key .age/key.txt] [--passphrase ...]
6
+ * envage encrypt --all [--env dev] [--key .age/key.txt]
7
+ */
8
+ import type { Command } from "commander";
9
+ export declare function registerEncrypt(program: Command): void;
10
+ export declare function runEncryptAll(env: string, keyFile?: string, passphrase?: string): Promise<void>;
11
+ //# sourceMappingURL=encrypt.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"encrypt.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/encrypt.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAezC,wBAAgB,eAAe,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA+CtD;AAqDD,wBAAsB,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAErG"}
@@ -0,0 +1,95 @@
1
+ import path from "path";
2
+ import { encryptEnv } from "../../lib/encrypt.js";
3
+ import { loadConfig } from "../../lib/config.js";
4
+ import { checkStagedEnvFiles } from "../../lib/gitignore.js";
5
+ import { logger } from "../../lib/logger.js";
6
+ import { promptPassphrase } from "../prompt.js";
7
+ export function registerEncrypt(program) {
8
+ program
9
+ .command("encrypt [path]")
10
+ .description("Encrypt .env.<env> → .env.<env>.age")
11
+ .option("-e, --env <env>", "environment name (e.g. dev, prod)", "dev")
12
+ .option("-k, --key <keyFile>", "path to age key file (.age/key.txt or .age/key.pub)")
13
+ .option("-p, --passphrase <pass>", "passphrase for encryption (not recommended via CLI arg — use without value to be prompted)")
14
+ .option("--all", "encrypt all apps defined in envage.config.json")
15
+ .action(async (folderArg, opts) => {
16
+ // Warn about staged decrypted files first
17
+ const staged = checkStagedEnvFiles();
18
+ if (staged.length > 0) {
19
+ logger.error("You are trying to commit a decrypted env file.");
20
+ logger.error("Only encrypted .age files are allowed.");
21
+ staged.forEach((f) => logger.detail(f));
22
+ process.exit(1);
23
+ }
24
+ // Resolve encryption credential
25
+ let passphrase = opts.passphrase;
26
+ let keyFile = opts.key;
27
+ if (!passphrase && !keyFile) {
28
+ // Auto-detect default key file
29
+ const config = await loadConfig();
30
+ const defaultKey = config.keyFile;
31
+ try {
32
+ const { readIdentityFromFile } = await import("../../lib/keygen.js");
33
+ await readIdentityFromFile(path.resolve(process.cwd(), defaultKey));
34
+ keyFile = path.resolve(process.cwd(), defaultKey);
35
+ logger.detail(`Using key file: ${keyFile}`);
36
+ }
37
+ catch {
38
+ // No key file found — prompt for passphrase
39
+ logger.info("No key file found. Enter a passphrase for encryption:");
40
+ passphrase = await promptPassphrase();
41
+ }
42
+ }
43
+ const envName = opts.env ?? "dev";
44
+ if (opts.all) {
45
+ await encryptAll(envName, keyFile, passphrase);
46
+ }
47
+ else {
48
+ const folder = folderArg ? path.resolve(process.cwd(), folderArg) : process.cwd();
49
+ await encryptOne(folder, envName, keyFile, passphrase);
50
+ }
51
+ });
52
+ }
53
+ async function encryptOne(folder, env, keyFile, passphrase) {
54
+ const fromFile = path.join(folder, `.env.${env}`);
55
+ const toFile = path.join(folder, `.env.${env}.age`);
56
+ logger.encrypting(fromFile, toFile);
57
+ try {
58
+ await encryptEnv({ folder, env, keyFile, passphrase });
59
+ logger.success("Done");
60
+ }
61
+ catch (err) {
62
+ const msg = err instanceof Error ? err.message : String(err);
63
+ logger.error(msg);
64
+ process.exit(1);
65
+ }
66
+ }
67
+ async function encryptAll(env, keyFile, passphrase) {
68
+ const config = await loadConfig();
69
+ if (config.apps.length === 0) {
70
+ logger.warn("No apps defined in envage.config.json. Nothing to encrypt.");
71
+ return;
72
+ }
73
+ let anyFailed = false;
74
+ for (const app of config.apps) {
75
+ const folder = path.resolve(process.cwd(), app);
76
+ const fromFile = path.join(folder, `.env.${env}`);
77
+ const toFile = path.join(folder, `.env.${env}.age`);
78
+ logger.encrypting(fromFile, toFile);
79
+ try {
80
+ await encryptEnv({ folder, env, keyFile, passphrase });
81
+ logger.success("Done");
82
+ }
83
+ catch (err) {
84
+ const msg = err instanceof Error ? err.message : String(err);
85
+ logger.error(msg);
86
+ anyFailed = true;
87
+ }
88
+ }
89
+ if (anyFailed)
90
+ process.exit(1);
91
+ }
92
+ export async function runEncryptAll(env, keyFile, passphrase) {
93
+ await encryptAll(env, keyFile, passphrase);
94
+ }
95
+ //# sourceMappingURL=encrypt.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"encrypt.js","sourceRoot":"","sources":["../../../src/cli/commands/encrypt.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * CLI `init-key` command.
3
+ *
4
+ * Usage:
5
+ * envage init-key [--output .age]
6
+ *
7
+ * Generates a new age X25519 keypair and writes:
8
+ * .age/key.txt (private key, mode 0600)
9
+ * .age/key.pub (public key)
10
+ */
11
+ import type { Command } from "commander";
12
+ export declare function registerInitKey(program: Command): void;
13
+ //# sourceMappingURL=init-key.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init-key.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/init-key.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AASzC,wBAAgB,eAAe,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAkCtD"}
@@ -0,0 +1,32 @@
1
+ import { generateKeyPairToFolder } from "../../lib/keygen.js";
2
+ import { ensureGitignore } from "../../lib/gitignore.js";
3
+ import { logger } from "../../lib/logger.js";
4
+ export function registerInitKey(program) {
5
+ program
6
+ .command("init-key")
7
+ .description("Generate a new age keypair (.age/key.txt and .age/key.pub)")
8
+ .option("-o, --output <folder>", "output folder for the keypair", ".age")
9
+ .action(async (opts) => {
10
+ const outputFolder = opts.output ?? ".age";
11
+ logger.info(`Generating age X25519 keypair in ${outputFolder}/`);
12
+ try {
13
+ const { keyFile, pubFile } = await generateKeyPairToFolder(outputFolder);
14
+ logger.success(`Private key written to: ${keyFile}`);
15
+ logger.success(`Public key written to: ${pubFile}`);
16
+ logger.info("Updating .gitignore to protect the private key…");
17
+ await ensureGitignore();
18
+ logger.success(".gitignore updated.");
19
+ logger.warn("IMPORTANT: Never commit your private key (.age/key.txt).");
20
+ logger.warn("Share .age/key.pub with teammates who need to encrypt files.");
21
+ logger.raw("");
22
+ logger.raw(" To encrypt: envage encrypt apps/web --env dev");
23
+ logger.raw(" To decrypt: envage decrypt apps/web --env dev");
24
+ }
25
+ catch (err) {
26
+ const msg = err instanceof Error ? err.message : String(err);
27
+ logger.error(`Failed to generate keypair: ${msg}`);
28
+ process.exit(1);
29
+ }
30
+ });
31
+ }
32
+ //# sourceMappingURL=init-key.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init-key.js","sourceRoot":"","sources":["../../../src/cli/commands/init-key.ts"],"names":[],"mappings":"AAWA,OAAO,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAC;AAC9D,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAM7C,MAAM,UAAU,eAAe,CAAC,OAAgB;IAC9C,OAAO;SACJ,OAAO,CAAC,UAAU,CAAC;SACnB,WAAW,CAAC,4DAA4D,CAAC;SACzE,MAAM,CAAC,uBAAuB,EAAE,+BAA+B,EAAE,MAAM,CAAC;SACxE,MAAM,CAAC,KAAK,EAAE,IAAoB,EAAE,EAAE;QACrC,MAAM,YAAY,GAAG,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC;QAE3C,MAAM,CAAC,IAAI,CAAC,oCAAoC,YAAY,GAAG,CAAC,CAAC;QAEjE,IAAI,CAAC;YACH,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,MAAM,uBAAuB,CAAC,YAAY,CAAC,CAAC;YACzE,MAAM,CAAC,OAAO,CAAC,2BAA2B,OAAO,EAAE,CAAC,CAAC;YACrD,MAAM,CAAC,OAAO,CAAC,2BAA2B,OAAO,EAAE,CAAC,CAAC;YAErD,MAAM,CAAC,IAAI,CAAC,iDAAiD,CAAC,CAAC;YAC/D,MAAM,eAAe,EAAE,CAAC;YACxB,MAAM,CAAC,OAAO,CAAC,qBAAqB,CAAC,CAAC;YAEtC,MAAM,CAAC,IAAI,CAAC,0DAA0D,CAAC,CAAC;YACxE,MAAM,CAAC,IAAI,CAAC,8DAA8D,CAAC,CAAC;YAC5E,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YACf,MAAM,CAAC,GAAG,CACR,kDAAkD,CACnD,CAAC;YACF,MAAM,CAAC,GAAG,CACR,kDAAkD,CACnD,CAAC;QACJ,CAAC;QAAC,OAAO,GAAY,EAAE,CAAC;YACtB,MAAM,GAAG,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YAC7D,MAAM,CAAC,KAAK,CAAC,+BAA+B,GAAG,EAAE,CAAC,CAAC;YACnD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC,CAAC,CAAC;AACP,CAAC"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * CLI `status` command.
3
+ *
4
+ * Usage:
5
+ * envage status [path]
6
+ *
7
+ * Shows which env files are encrypted/decrypted for all configured apps.
8
+ */
9
+ import type { Command } from "commander";
10
+ export declare function registerStatus(program: Command): void;
11
+ //# sourceMappingURL=status.d.ts.map