@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
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gitignore.js","sourceRoot":"","sources":["../../src/lib/gitignore.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,MAAM,aAAa,CAAC;AAC7B,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEzC,4CAA4C;AAC5C,MAAM,kBAAkB,GAAG,0BAA0B,CAAC;AACtD,MAAM,gBAAgB,GAAG,sBAAsB,CAAC;AAEhD,MAAM,YAAY,GAAG,GAAG,kBAAkB;;;;;;;;EAQxC,gBAAgB,EAAE,CAAC;AAErB;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE;IACvD,MAAM,aAAa,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC;IAEnD,IAAI,QAAQ,GAAG,EAAE,CAAC;IAClB,IAAI,CAAC;QACH,QAAQ,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC;IACvD,CAAC;IAAC,MAAM,CAAC;QACP,uCAAuC;IACzC,CAAC;IAED,IAAI,QAAQ,CAAC,QAAQ,CAAC,kBAAkB,CAAC,EAAE,CAAC;QAC1C,4BAA4B;QAC5B,MAAM,QAAQ,GAAG,QAAQ,CAAC,OAAO,CAAC,kBAAkB,CAAC,CAAC;QACtD,MAAM,MAAM,GAAG,QAAQ,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC;QAClD,IAAI,MAAM,KAAK,CAAC,CAAC,EAAE,CAAC;YAClB,MAAM,OAAO,GACX,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,CAAC;gBAC3B,YAAY;gBACZ,QAAQ,CAAC,KAAK,CAAC,MAAM,GAAG,gBAAgB,CAAC,MAAM,CAAC,CAAC;YACnD,MAAM,EAAE,CAAC,SAAS,CAAC,aAAa,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;QACtD,CAAC;IACH,CAAC;SAAM,CAAC;QACN,mBAAmB;QACnB,MAAM,SAAS,GAAG,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,QAAQ,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;QACzE,MAAM,EAAE,CAAC,SAAS,CAChB,aAAa,EACb,QAAQ,GAAG,SAAS,GAAG,IAAI,GAAG,YAAY,GAAG,IAAI,EACjD,OAAO,CACR,CAAC;IACJ,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,mBAAmB,CAAC,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE;IACrD,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,QAAQ,CAAC,+BAA+B,EAAE;YACvD,GAAG;YACH,QAAQ,EAAE,OAAO;YACjB,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,CAAC;SACpC,CAAC,CAAC;QAEH,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QAClD,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE;YACzB,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;YAC9B,OAAO,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QACxD,CAAC,CAAC,CAAC;IACL,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,iBAAiB;IAC/B,OAAO,YAAY,CAAC;AACtB,CAAC"}
@@ -0,0 +1,30 @@
1
+ export interface KeyPair {
2
+ /** Private key string — starts with AGE-SECRET-KEY-1 */
3
+ identity: string;
4
+ /** Public key string — starts with age1 */
5
+ recipient: string;
6
+ }
7
+ /**
8
+ * Generate a new age X25519 keypair and return the strings.
9
+ */
10
+ export declare function generateKeyPair(): Promise<KeyPair>;
11
+ /**
12
+ * Generate a new keypair and write it to disk.
13
+ *
14
+ * @param outputFolder Directory to write key.txt and key.pub (default: ".age")
15
+ * @param cwd Base directory (default: process.cwd())
16
+ */
17
+ export declare function generateKeyPairToFolder(outputFolder?: string, cwd?: string): Promise<{
18
+ keyFile: string;
19
+ pubFile: string;
20
+ }>;
21
+ /**
22
+ * Read the private key (identity) from a key file.
23
+ * Strips comments and blank lines; returns the first non-comment line.
24
+ */
25
+ export declare function readIdentityFromFile(keyFile: string): Promise<string>;
26
+ /**
27
+ * Read the public key (recipient) from a .pub file.
28
+ */
29
+ export declare function readRecipientFromFile(pubFile: string): Promise<string>;
30
+ //# sourceMappingURL=keygen.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keygen.d.ts","sourceRoot":"","sources":["../../src/lib/keygen.ts"],"names":[],"mappings":"AASA,MAAM,WAAW,OAAO;IACtB,wDAAwD;IACxD,QAAQ,EAAE,MAAM,CAAC;IACjB,2CAA2C;IAC3C,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,wBAAsB,eAAe,IAAI,OAAO,CAAC,OAAO,CAAC,CAIxD;AAED;;;;;GAKG;AACH,wBAAsB,uBAAuB,CAC3C,YAAY,SAAS,EACrB,GAAG,SAAgB,GAClB,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,CAmB/C;AAED;;;GAGG;AACH,wBAAsB,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAW3E;AAED;;GAEG;AACH,wBAAsB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAW5E"}
@@ -0,0 +1,66 @@
1
+ /**
2
+ * Age keypair generation.
3
+ * Produces an identity (private key) and recipient (public key)
4
+ * in the standard age text format.
5
+ */
6
+ import * as age from "age-encryption";
7
+ import fs from "fs/promises";
8
+ import path from "path";
9
+ /**
10
+ * Generate a new age X25519 keypair and return the strings.
11
+ */
12
+ export async function generateKeyPair() {
13
+ const identity = await age.generateIdentity();
14
+ const recipient = await age.identityToRecipient(identity);
15
+ return { identity, recipient };
16
+ }
17
+ /**
18
+ * Generate a new keypair and write it to disk.
19
+ *
20
+ * @param outputFolder Directory to write key.txt and key.pub (default: ".age")
21
+ * @param cwd Base directory (default: process.cwd())
22
+ */
23
+ export async function generateKeyPairToFolder(outputFolder = ".age", cwd = process.cwd()) {
24
+ const { identity, recipient } = await generateKeyPair();
25
+ const absFolder = path.isAbsolute(outputFolder)
26
+ ? outputFolder
27
+ : path.join(cwd, outputFolder);
28
+ await fs.mkdir(absFolder, { recursive: true });
29
+ const keyFile = path.join(absFolder, "key.txt");
30
+ const pubFile = path.join(absFolder, "key.pub");
31
+ const timestamp = new Date().toISOString();
32
+ const keyContent = `# created: ${timestamp}\n# public key: ${recipient}\n${identity}\n`;
33
+ await fs.writeFile(keyFile, keyContent, { encoding: "utf-8", mode: 0o600 });
34
+ await fs.writeFile(pubFile, recipient + "\n", "utf-8");
35
+ return { keyFile, pubFile };
36
+ }
37
+ /**
38
+ * Read the private key (identity) from a key file.
39
+ * Strips comments and blank lines; returns the first non-comment line.
40
+ */
41
+ export async function readIdentityFromFile(keyFile) {
42
+ const contents = await fs.readFile(keyFile, "utf-8");
43
+ const identity = contents
44
+ .split("\n")
45
+ .map((l) => l.trim())
46
+ .find((l) => l && !l.startsWith("#"));
47
+ if (!identity) {
48
+ throw new Error(`No valid age identity found in key file: ${keyFile}`);
49
+ }
50
+ return identity;
51
+ }
52
+ /**
53
+ * Read the public key (recipient) from a .pub file.
54
+ */
55
+ export async function readRecipientFromFile(pubFile) {
56
+ const contents = await fs.readFile(pubFile, "utf-8");
57
+ const recipient = contents
58
+ .split("\n")
59
+ .map((l) => l.trim())
60
+ .find((l) => l && !l.startsWith("#"));
61
+ if (!recipient) {
62
+ throw new Error(`No valid age recipient found in pub file: ${pubFile}`);
63
+ }
64
+ return recipient;
65
+ }
66
+ //# sourceMappingURL=keygen.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keygen.js","sourceRoot":"","sources":["../../src/lib/keygen.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ export declare const logger: {
2
+ /** Informational step message */
3
+ info(msg: string): void;
4
+ /** Success message */
5
+ success(msg: string): void;
6
+ /** Warning message */
7
+ warn(msg: string): void;
8
+ /** Error message */
9
+ error(msg: string): void;
10
+ /** Bold section header */
11
+ header(msg: string): void;
12
+ /** Dimmed detail line */
13
+ detail(msg: string): void;
14
+ /** Raw output with no prefix */
15
+ raw(msg: string): void;
16
+ /** Lock icon line — used when encrypting */
17
+ encrypting(from: string, to: string): void;
18
+ /** Unlock icon line — used when decrypting */
19
+ decrypting(from: string, to: string): void;
20
+ };
21
+ //# sourceMappingURL=logger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/lib/logger.ts"],"names":[],"mappings":"AAMA,eAAO,MAAM,MAAM;IACjB,iCAAiC;cACvB,MAAM,GAAG,IAAI;IAIvB,sBAAsB;iBACT,MAAM,GAAG,IAAI;IAI1B,sBAAsB;cACZ,MAAM,GAAG,IAAI;IAIvB,oBAAoB;eACT,MAAM,GAAG,IAAI;IAIxB,0BAA0B;gBACd,MAAM,GAAG,IAAI;IAIzB,yBAAyB;gBACb,MAAM,GAAG,IAAI;IAIzB,gCAAgC;aACvB,MAAM,GAAG,IAAI;IAItB,4CAA4C;qBAC3B,MAAM,MAAM,MAAM,GAAG,IAAI;IAU1C,8CAA8C;qBAC7B,MAAM,MAAM,MAAM,GAAG,IAAI;CAS3C,CAAC"}
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Colorized logger for the envage CLI.
3
+ * Uses chalk for output — secrets are never logged.
4
+ */
5
+ import chalk from "chalk";
6
+ export const logger = {
7
+ /** Informational step message */
8
+ info(msg) {
9
+ console.log(chalk.cyan("ℹ") + " " + msg);
10
+ },
11
+ /** Success message */
12
+ success(msg) {
13
+ console.log(chalk.green("✔") + " " + chalk.green(msg));
14
+ },
15
+ /** Warning message */
16
+ warn(msg) {
17
+ console.warn(chalk.yellow("⚠") + " " + chalk.yellow(msg));
18
+ },
19
+ /** Error message */
20
+ error(msg) {
21
+ console.error(chalk.red("✖") + " " + chalk.red(msg));
22
+ },
23
+ /** Bold section header */
24
+ header(msg) {
25
+ console.log("\n" + chalk.bold(msg));
26
+ },
27
+ /** Dimmed detail line */
28
+ detail(msg) {
29
+ console.log(" " + chalk.dim(msg));
30
+ },
31
+ /** Raw output with no prefix */
32
+ raw(msg) {
33
+ console.log(msg);
34
+ },
35
+ /** Lock icon line — used when encrypting */
36
+ encrypting(from, to) {
37
+ console.log(chalk.blue("🔐") +
38
+ " Encrypting " +
39
+ chalk.cyan(from) +
40
+ " → " +
41
+ chalk.cyan(to));
42
+ },
43
+ /** Unlock icon line — used when decrypting */
44
+ decrypting(from, to) {
45
+ console.log(chalk.magenta("🔓") +
46
+ " Decrypting " +
47
+ chalk.cyan(from) +
48
+ " → " +
49
+ chalk.cyan(to));
50
+ },
51
+ };
52
+ //# sourceMappingURL=logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/lib/logger.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,MAAM,CAAC,MAAM,MAAM,GAAG;IACpB,iCAAiC;IACjC,IAAI,CAAC,GAAW;QACd,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;IAC3C,CAAC;IAED,sBAAsB;IACtB,OAAO,CAAC,GAAW;QACjB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,GAAG,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;IACzD,CAAC;IAED,sBAAsB;IACtB,IAAI,CAAC,GAAW;QACd,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,GAAG,GAAG,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;IAC5D,CAAC;IAED,oBAAoB;IACpB,KAAK,CAAC,GAAW;QACf,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;IACvD,CAAC;IAED,0BAA0B;IAC1B,MAAM,CAAC,GAAW;QAChB,OAAO,CAAC,GAAG,CAAC,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IACtC,CAAC;IAED,yBAAyB;IACzB,MAAM,CAAC,GAAW;QAChB,OAAO,CAAC,GAAG,CAAC,IAAI,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;IACrC,CAAC;IAED,gCAAgC;IAChC,GAAG,CAAC,GAAW;QACb,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACnB,CAAC;IAED,4CAA4C;IAC5C,UAAU,CAAC,IAAY,EAAE,EAAU;QACjC,OAAO,CAAC,GAAG,CACT,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC;YACd,cAAc;YACd,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC;YAChB,KAAK;YACL,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CACjB,CAAC;IACJ,CAAC;IAED,8CAA8C;IAC9C,UAAU,CAAC,IAAY,EAAE,EAAU;QACjC,OAAO,CAAC,GAAG,CACT,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC;YACjB,cAAc;YACd,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC;YAChB,KAAK;YACL,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CACjB,CAAC;IACJ,CAAC;CACF,CAAC"}
@@ -0,0 +1,14 @@
1
+ import type { EnvStatus, EnvageConfig } from "../types.js";
2
+ /**
3
+ * Check a single folder + env combination.
4
+ */
5
+ export declare function checkEnvStatus(folder: string, env: string): Promise<EnvStatus>;
6
+ /**
7
+ * Check all folder + env combinations defined in a config.
8
+ */
9
+ export declare function getEnvStatus(config: EnvageConfig, cwd?: string): Promise<EnvStatus[]>;
10
+ /**
11
+ * Check a single folder across all envs in a config.
12
+ */
13
+ export declare function getFolderStatus(folder: string, config: EnvageConfig): Promise<EnvStatus[]>;
14
+ //# sourceMappingURL=status.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../src/lib/status.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3D;;GAEG;AACH,wBAAsB,cAAc,CAClC,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,SAAS,CAAC,CAUpB;AAED;;GAEG;AACH,wBAAsB,YAAY,CAChC,MAAM,EAAE,YAAY,EACpB,GAAG,SAAgB,GAClB,OAAO,CAAC,SAAS,EAAE,CAAC,CAWtB;AAED;;GAEG;AACH,wBAAsB,eAAe,CACnC,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,YAAY,GACnB,OAAO,CAAC,SAAS,EAAE,CAAC,CAQtB"}
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Scans folders and reports on the encrypted/decrypted state of env files.
3
+ */
4
+ import fs from "fs/promises";
5
+ import path from "path";
6
+ /**
7
+ * Check a single folder + env combination.
8
+ */
9
+ export async function checkEnvStatus(folder, env) {
10
+ const decryptedPath = path.join(folder, `.env.${env}`);
11
+ const encryptedPath = path.join(folder, `.env.${env}.age`);
12
+ const [decrypted, encrypted] = await Promise.all([
13
+ fileExists(decryptedPath),
14
+ fileExists(encryptedPath),
15
+ ]);
16
+ return { folder, env, decrypted, encrypted, decryptedPath, encryptedPath };
17
+ }
18
+ /**
19
+ * Check all folder + env combinations defined in a config.
20
+ */
21
+ export async function getEnvStatus(config, cwd = process.cwd()) {
22
+ const results = [];
23
+ for (const app of config.apps) {
24
+ const absFolder = path.isAbsolute(app) ? app : path.resolve(cwd, app);
25
+ for (const env of config.envs) {
26
+ results.push(await checkEnvStatus(absFolder, env));
27
+ }
28
+ }
29
+ return results;
30
+ }
31
+ /**
32
+ * Check a single folder across all envs in a config.
33
+ */
34
+ export async function getFolderStatus(folder, config) {
35
+ const absFolder = path.isAbsolute(folder)
36
+ ? folder
37
+ : path.resolve(process.cwd(), folder);
38
+ return Promise.all(config.envs.map((env) => checkEnvStatus(absFolder, env)));
39
+ }
40
+ /** Helper: check if a file exists */
41
+ async function fileExists(filePath) {
42
+ try {
43
+ await fs.access(filePath);
44
+ return true;
45
+ }
46
+ catch {
47
+ return false;
48
+ }
49
+ }
50
+ //# sourceMappingURL=status.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.js","sourceRoot":"","sources":["../../src/lib/status.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAE,MAAM,aAAa,CAAC;AAC7B,OAAO,IAAI,MAAM,MAAM,CAAC;AAGxB;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,MAAc,EACd,GAAW;IAEX,MAAM,aAAa,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,QAAQ,GAAG,EAAE,CAAC,CAAC;IACvD,MAAM,aAAa,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,QAAQ,GAAG,MAAM,CAAC,CAAC;IAE3D,MAAM,CAAC,SAAS,EAAE,SAAS,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;QAC/C,UAAU,CAAC,aAAa,CAAC;QACzB,UAAU,CAAC,aAAa,CAAC;KAC1B,CAAC,CAAC;IAEH,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,SAAS,EAAE,SAAS,EAAE,aAAa,EAAE,aAAa,EAAE,CAAC;AAC7E,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,MAAoB,EACpB,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE;IAEnB,MAAM,OAAO,GAAgB,EAAE,CAAC;IAEhC,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC;QAC9B,MAAM,SAAS,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;QACtE,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC;YAC9B,OAAO,CAAC,IAAI,CAAC,MAAM,cAAc,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC,CAAC;QACrD,CAAC;IACH,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,MAAc,EACd,MAAoB;IAEpB,MAAM,SAAS,GAAG,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC;QACvC,CAAC,CAAC,MAAM;QACR,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,MAAM,CAAC,CAAC;IAExC,OAAO,OAAO,CAAC,GAAG,CAChB,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,cAAc,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC,CACzD,CAAC;AACJ,CAAC;AAED,qCAAqC;AACrC,KAAK,UAAU,UAAU,CAAC,QAAgB;IACxC,IAAI,CAAC;QACH,MAAM,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAC1B,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
@@ -0,0 +1,40 @@
1
+ /** Status of a single env/environment slot within a folder. */
2
+ export interface EnvStatus {
3
+ /** The app folder path (e.g. "apps/web") */
4
+ folder: string;
5
+ /** The environment name (e.g. "dev", "prod") */
6
+ env: string;
7
+ /** Whether the plaintext .env.<env> file exists */
8
+ decrypted: boolean;
9
+ /** Whether the encrypted .env.<env>.age file exists */
10
+ encrypted: boolean;
11
+ /** Full path to the plaintext file */
12
+ decryptedPath: string;
13
+ /** Full path to the encrypted file */
14
+ encryptedPath: string;
15
+ }
16
+ /** Shape of envage.config.json */
17
+ export interface EnvageConfig {
18
+ /** App/package folder paths relative to cwd (e.g. ["apps/web", "packages/api"]) */
19
+ apps: string[];
20
+ /** Environment names to manage (e.g. ["dev", "staging", "prod"]) */
21
+ envs: string[];
22
+ /** Path to the age private key file (default: ".age/key.txt") */
23
+ keyFile: string;
24
+ /** Path to the age public key file (default: ".age/key.pub") */
25
+ keyPubFile?: string;
26
+ }
27
+ /** Options for encryptEnv / decryptEnv */
28
+ export interface EnvOptions {
29
+ /** App/package folder path */
30
+ folder: string;
31
+ /** Environment name */
32
+ env: string;
33
+ /** Path to age key file (for key-based encryption) */
34
+ keyFile?: string;
35
+ /** Passphrase (for passphrase-based encryption) */
36
+ passphrase?: string;
37
+ }
38
+ /** Default config values */
39
+ export declare const DEFAULT_CONFIG: EnvageConfig;
40
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAC/D,MAAM,WAAW,SAAS;IACxB,4CAA4C;IAC5C,MAAM,EAAE,MAAM,CAAC;IACf,gDAAgD;IAChD,GAAG,EAAE,MAAM,CAAC;IACZ,mDAAmD;IACnD,SAAS,EAAE,OAAO,CAAC;IACnB,uDAAuD;IACvD,SAAS,EAAE,OAAO,CAAC;IACnB,sCAAsC;IACtC,aAAa,EAAE,MAAM,CAAC;IACtB,sCAAsC;IACtC,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,kCAAkC;AAClC,MAAM,WAAW,YAAY;IAC3B,mFAAmF;IACnF,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,oEAAoE;IACpE,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,iEAAiE;IACjE,OAAO,EAAE,MAAM,CAAC;IAChB,gEAAgE;IAChE,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,0CAA0C;AAC1C,MAAM,WAAW,UAAU;IACzB,8BAA8B;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,uBAAuB;IACvB,GAAG,EAAE,MAAM,CAAC;IACZ,sDAAsD;IACtD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,mDAAmD;IACnD,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,4BAA4B;AAC5B,eAAO,MAAM,cAAc,EAAE,YAK5B,CAAC"}
package/dist/types.js ADDED
@@ -0,0 +1,8 @@
1
+ /** Default config values */
2
+ export const DEFAULT_CONFIG = {
3
+ apps: [],
4
+ envs: ["dev", "staging", "prod"],
5
+ keyFile: ".age/key.txt",
6
+ keyPubFile: ".age/key.pub",
7
+ };
8
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAwCA,4BAA4B;AAC5B,MAAM,CAAC,MAAM,cAAc,GAAiB;IAC1C,IAAI,EAAE,EAAE;IACR,IAAI,EAAE,CAAC,KAAK,EAAE,SAAS,EAAE,MAAM,CAAC;IAChC,OAAO,EAAE,cAAc;IACvB,UAAU,EAAE,cAAc;CAC3B,CAAC"}
package/package.json ADDED
@@ -0,0 +1,65 @@
1
+ {
2
+ "name": "@asafarim/envage",
3
+ "version": "0.1.0",
4
+ "description": "Secure, age-based encryption/decryption for .env files across multiple environments and monorepo app folders",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "import": "./dist/index.js",
11
+ "types": "./dist/index.d.ts"
12
+ }
13
+ },
14
+ "bin": {
15
+ "envage": "./bin/envage.js"
16
+ },
17
+ "files": [
18
+ "dist",
19
+ "bin",
20
+ "README.md"
21
+ ],
22
+ "keywords": [
23
+ "age",
24
+ "encryption",
25
+ "env",
26
+ "dotenv",
27
+ "monorepo",
28
+ "secrets",
29
+ "cli"
30
+ ],
31
+ "author": "Ali Safarim <asafarim@gmail.com>",
32
+ "license": "MIT",
33
+ "dependencies": {
34
+ "age-encryption": "^0.3.0",
35
+ "chalk": "^5.3.0",
36
+ "commander": "^12.1.0"
37
+ },
38
+ "devDependencies": {
39
+ "@types/jest": "^29.5.12",
40
+ "@types/node": "^20.14.0",
41
+ "jest": "^29.7.0",
42
+ "ts-jest": "^29.1.5",
43
+ "typescript": "^5.5.3"
44
+ },
45
+ "engines": {
46
+ "node": ">=20.0.0"
47
+ },
48
+ "repository": {
49
+ "type": "git",
50
+ "url": "https://github.com/AliSafari-IT/envage.git"
51
+ },
52
+ "bugs": {
53
+ "url": "https://github.com/AliSafari-IT/envage/issues"
54
+ },
55
+ "homepage": "https://AliSafari-IT.github.io/envage",
56
+ "scripts": {
57
+ "build": "tsc",
58
+ "dev": "tsc --watch",
59
+ "test": "node --experimental-vm-modules node_modules/jest/bin/jest.js --config jest.config.cjs",
60
+ "test:watch": "node --experimental-vm-modules node_modules/jest/bin/jest.js --config jest.config.cjs --watch",
61
+ "test:coverage": "node --experimental-vm-modules node_modules/jest/bin/jest.js --config jest.config.cjs --coverage",
62
+ "lint": "tsc --noEmit",
63
+ "typecheck": "tsc --noEmit"
64
+ }
65
+ }