@geekmidas/envkit 1.0.3 → 1.0.4

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/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # @geekmidas/envkit
2
2
 
3
+ ## 1.0.4
4
+
5
+ ### Patch Changes
6
+
7
+ - 🐛 [`a483d4c`](https://github.com/geekmidas/toolbox/commit/a483d4c193d27673ccad2aeed6f56b1c5708b5b4) Thanks [@geekmidas](https://github.com/geekmidas)! - Fix credentials injection to work with esm/cjs
8
+
3
9
  ## 1.0.3
4
10
 
5
11
  ### Patch Changes
@@ -23,9 +23,13 @@ function decryptCredentials(encrypted, iv, masterKey) {
23
23
  /**
24
24
  * Credentials object for use with EnvironmentParser.
25
25
  *
26
- * In development mode (no embedded credentials), this returns an empty object.
27
- * In production mode, it decrypts embedded credentials using the GKM_MASTER_KEY
28
- * environment variable.
26
+ * Resolution order:
27
+ * 1. **Dev mode (gkm dev/exec)**: Checks `globalThis.__gkm_credentials__` for
28
+ * credentials injected by the CLI preload script. This approach survives
29
+ * CJS/ESM module duplication (where mutating the export would only affect one copy).
30
+ * 2. **Production mode**: Decrypts build-time embedded credentials using the
31
+ * `GKM_MASTER_KEY` environment variable (AES-256-GCM).
32
+ * 3. **Fallback**: Returns empty object (allows graceful fallback to process.env).
29
33
  *
30
34
  * @example
31
35
  * ```typescript
@@ -42,6 +46,8 @@ function decryptCredentials(encrypted, iv, masterKey) {
42
46
  * ```
43
47
  */
44
48
  const Credentials = (() => {
49
+ const injected = globalThis.__gkm_credentials__;
50
+ if (injected) return injected;
45
51
  if (typeof __GKM_ENCRYPTED_CREDENTIALS__ === "undefined" || typeof __GKM_CREDENTIALS_IV__ === "undefined") return {};
46
52
  const masterKey = process.env.GKM_MASTER_KEY;
47
53
  if (!masterKey) {
@@ -1 +1 @@
1
- {"version":3,"file":"credentials.cjs","names":["encrypted: string","iv: string","masterKey: string","Credentials: Record<string, string>"],"sources":["../src/credentials.ts"],"sourcesContent":["import { createDecipheriv } from 'node:crypto';\n\n/**\n * Build-time injected encrypted credentials.\n * These are replaced by tsdown/esbuild --define at build time.\n */\ndeclare const __GKM_ENCRYPTED_CREDENTIALS__: string | undefined;\ndeclare const __GKM_CREDENTIALS_IV__: string | undefined;\n\n/** AES-256-GCM auth tag length */\nconst AUTH_TAG_LENGTH = 16;\n\n/**\n * Decrypt credentials from encrypted payload.\n * Exported for testing purposes.\n */\nexport function decryptCredentials(\n\tencrypted: string,\n\tiv: string,\n\tmasterKey: string,\n): Record<string, string> {\n\tconst key = Buffer.from(masterKey, 'hex');\n\tconst ivBuffer = Buffer.from(iv, 'hex');\n\tconst combined = Buffer.from(encrypted, 'base64');\n\n\t// Split ciphertext and auth tag\n\tconst ciphertext = combined.subarray(0, -AUTH_TAG_LENGTH);\n\tconst authTag = combined.subarray(-AUTH_TAG_LENGTH);\n\n\t// Decrypt using AES-256-GCM\n\tconst decipher = createDecipheriv('aes-256-gcm', key, ivBuffer);\n\tdecipher.setAuthTag(authTag);\n\n\tconst plaintext = Buffer.concat([\n\t\tdecipher.update(ciphertext),\n\t\tdecipher.final(),\n\t]);\n\n\treturn JSON.parse(plaintext.toString('utf-8'));\n}\n\n/**\n * Credentials object for use with EnvironmentParser.\n *\n * In development mode (no embedded credentials), this returns an empty object.\n * In production mode, it decrypts embedded credentials using the GKM_MASTER_KEY\n * environment variable.\n *\n * @example\n * ```typescript\n * import { EnvironmentParser } from '@geekmidas/envkit';\n * import { Credentials } from '@geekmidas/envkit/credentials';\n *\n * export const envParser = new EnvironmentParser({...process.env, ...Credentials})\n * .create((get) => ({\n * database: {\n * url: get('DATABASE_URL').string(),\n * },\n * }))\n * .parse();\n * ```\n */\nexport const Credentials: Record<string, string> = (() => {\n\t// Development mode - no credentials embedded at build time\n\tif (\n\t\ttypeof __GKM_ENCRYPTED_CREDENTIALS__ === 'undefined' ||\n\t\ttypeof __GKM_CREDENTIALS_IV__ === 'undefined'\n\t) {\n\t\treturn {};\n\t}\n\n\t// Production mode - decrypt credentials using master key\n\tconst masterKey = process.env.GKM_MASTER_KEY;\n\n\tif (!masterKey) {\n\t\t// Log warning but don't throw - allows graceful fallback to env vars\n\t\tconsole.error(\n\t\t\t'[gkm] GKM_MASTER_KEY environment variable is required to decrypt credentials.',\n\t\t);\n\t\tconsole.error(\n\t\t\t'[gkm] Falling back to environment variables. Some secrets may be missing.',\n\t\t);\n\t\treturn {};\n\t}\n\n\ttry {\n\t\treturn decryptCredentials(\n\t\t\t__GKM_ENCRYPTED_CREDENTIALS__,\n\t\t\t__GKM_CREDENTIALS_IV__,\n\t\t\tmasterKey,\n\t\t);\n\t} catch (error) {\n\t\tconsole.error('[gkm] Failed to decrypt credentials:', error);\n\t\tconsole.error('[gkm] Falling back to environment variables.');\n\t\treturn {};\n\t}\n})();\n\nexport default Credentials;\n"],"mappings":";;;;;;AAUA,MAAM,kBAAkB;;;;;AAMxB,SAAgB,mBACfA,WACAC,IACAC,WACyB;CACzB,MAAM,MAAM,OAAO,KAAK,WAAW,MAAM;CACzC,MAAM,WAAW,OAAO,KAAK,IAAI,MAAM;CACvC,MAAM,WAAW,OAAO,KAAK,WAAW,SAAS;CAGjD,MAAM,aAAa,SAAS,SAAS,IAAI,gBAAgB;CACzD,MAAM,UAAU,SAAS,UAAU,gBAAgB;CAGnD,MAAM,WAAW,kCAAiB,eAAe,KAAK,SAAS;AAC/D,UAAS,WAAW,QAAQ;CAE5B,MAAM,YAAY,OAAO,OAAO,CAC/B,SAAS,OAAO,WAAW,EAC3B,SAAS,OAAO,AAChB,EAAC;AAEF,QAAO,KAAK,MAAM,UAAU,SAAS,QAAQ,CAAC;AAC9C;;;;;;;;;;;;;;;;;;;;;;AAuBD,MAAaC,cAAsC,CAAC,MAAM;AAEzD,YACQ,kCAAkC,sBAClC,2BAA2B,YAElC,QAAO,CAAE;CAIV,MAAM,YAAY,QAAQ,IAAI;AAE9B,MAAK,WAAW;AAEf,UAAQ,MACP,gFACA;AACD,UAAQ,MACP,4EACA;AACD,SAAO,CAAE;CACT;AAED,KAAI;AACH,SAAO,mBACN,+BACA,wBACA,UACA;CACD,SAAQ,OAAO;AACf,UAAQ,MAAM,wCAAwC,MAAM;AAC5D,UAAQ,MAAM,+CAA+C;AAC7D,SAAO,CAAE;CACT;AACD,IAAG;AAEJ,0BAAe"}
1
+ {"version":3,"file":"credentials.cjs","names":["encrypted: string","iv: string","masterKey: string","Credentials: Record<string, string>"],"sources":["../src/credentials.ts"],"sourcesContent":["import { createDecipheriv } from 'node:crypto';\n\n/**\n * Build-time injected encrypted credentials.\n * These are replaced by tsdown/esbuild --define at build time.\n */\ndeclare const __GKM_ENCRYPTED_CREDENTIALS__: string | undefined;\ndeclare const __GKM_CREDENTIALS_IV__: string | undefined;\n\n/** AES-256-GCM auth tag length */\nconst AUTH_TAG_LENGTH = 16;\n\n/**\n * Decrypt credentials from encrypted payload.\n * Exported for testing purposes.\n */\nexport function decryptCredentials(\n\tencrypted: string,\n\tiv: string,\n\tmasterKey: string,\n): Record<string, string> {\n\tconst key = Buffer.from(masterKey, 'hex');\n\tconst ivBuffer = Buffer.from(iv, 'hex');\n\tconst combined = Buffer.from(encrypted, 'base64');\n\n\t// Split ciphertext and auth tag\n\tconst ciphertext = combined.subarray(0, -AUTH_TAG_LENGTH);\n\tconst authTag = combined.subarray(-AUTH_TAG_LENGTH);\n\n\t// Decrypt using AES-256-GCM\n\tconst decipher = createDecipheriv('aes-256-gcm', key, ivBuffer);\n\tdecipher.setAuthTag(authTag);\n\n\tconst plaintext = Buffer.concat([\n\t\tdecipher.update(ciphertext),\n\t\tdecipher.final(),\n\t]);\n\n\treturn JSON.parse(plaintext.toString('utf-8'));\n}\n\n/**\n * Credentials object for use with EnvironmentParser.\n *\n * Resolution order:\n * 1. **Dev mode (gkm dev/exec)**: Checks `globalThis.__gkm_credentials__` for\n * credentials injected by the CLI preload script. This approach survives\n * CJS/ESM module duplication (where mutating the export would only affect one copy).\n * 2. **Production mode**: Decrypts build-time embedded credentials using the\n * `GKM_MASTER_KEY` environment variable (AES-256-GCM).\n * 3. **Fallback**: Returns empty object (allows graceful fallback to process.env).\n *\n * @example\n * ```typescript\n * import { EnvironmentParser } from '@geekmidas/envkit';\n * import { Credentials } from '@geekmidas/envkit/credentials';\n *\n * export const envParser = new EnvironmentParser({...process.env, ...Credentials})\n * .create((get) => ({\n * database: {\n * url: get('DATABASE_URL').string(),\n * },\n * }))\n * .parse();\n * ```\n */\nexport const Credentials: Record<string, string> = (() => {\n\t// Dev mode: check if gkm exec/dev preload injected credentials via globalThis\n\t// This survives CJS/ESM module duplication where Object.assign on the\n\t// export would only mutate one copy of the module's Credentials object.\n\tconst injected = (globalThis as Record<string, unknown>)\n\t\t.__gkm_credentials__ as Record<string, string> | undefined;\n\tif (injected) {\n\t\treturn injected;\n\t}\n\n\t// Development mode - no credentials embedded at build time\n\tif (\n\t\ttypeof __GKM_ENCRYPTED_CREDENTIALS__ === 'undefined' ||\n\t\ttypeof __GKM_CREDENTIALS_IV__ === 'undefined'\n\t) {\n\t\treturn {};\n\t}\n\n\t// Production mode - decrypt credentials using master key\n\tconst masterKey = process.env.GKM_MASTER_KEY;\n\n\tif (!masterKey) {\n\t\t// Log warning but don't throw - allows graceful fallback to env vars\n\t\tconsole.error(\n\t\t\t'[gkm] GKM_MASTER_KEY environment variable is required to decrypt credentials.',\n\t\t);\n\t\tconsole.error(\n\t\t\t'[gkm] Falling back to environment variables. Some secrets may be missing.',\n\t\t);\n\t\treturn {};\n\t}\n\n\ttry {\n\t\treturn decryptCredentials(\n\t\t\t__GKM_ENCRYPTED_CREDENTIALS__,\n\t\t\t__GKM_CREDENTIALS_IV__,\n\t\t\tmasterKey,\n\t\t);\n\t} catch (error) {\n\t\tconsole.error('[gkm] Failed to decrypt credentials:', error);\n\t\tconsole.error('[gkm] Falling back to environment variables.');\n\t\treturn {};\n\t}\n})();\n\nexport default Credentials;\n"],"mappings":";;;;;;AAUA,MAAM,kBAAkB;;;;;AAMxB,SAAgB,mBACfA,WACAC,IACAC,WACyB;CACzB,MAAM,MAAM,OAAO,KAAK,WAAW,MAAM;CACzC,MAAM,WAAW,OAAO,KAAK,IAAI,MAAM;CACvC,MAAM,WAAW,OAAO,KAAK,WAAW,SAAS;CAGjD,MAAM,aAAa,SAAS,SAAS,IAAI,gBAAgB;CACzD,MAAM,UAAU,SAAS,UAAU,gBAAgB;CAGnD,MAAM,WAAW,kCAAiB,eAAe,KAAK,SAAS;AAC/D,UAAS,WAAW,QAAQ;CAE5B,MAAM,YAAY,OAAO,OAAO,CAC/B,SAAS,OAAO,WAAW,EAC3B,SAAS,OAAO,AAChB,EAAC;AAEF,QAAO,KAAK,MAAM,UAAU,SAAS,QAAQ,CAAC;AAC9C;;;;;;;;;;;;;;;;;;;;;;;;;;AA2BD,MAAaC,cAAsC,CAAC,MAAM;CAIzD,MAAM,WAAY,WAChB;AACF,KAAI,SACH,QAAO;AAIR,YACQ,kCAAkC,sBAClC,2BAA2B,YAElC,QAAO,CAAE;CAIV,MAAM,YAAY,QAAQ,IAAI;AAE9B,MAAK,WAAW;AAEf,UAAQ,MACP,gFACA;AACD,UAAQ,MACP,4EACA;AACD,SAAO,CAAE;CACT;AAED,KAAI;AACH,SAAO,mBACN,+BACA,wBACA,UACA;CACD,SAAQ,OAAO;AACf,UAAQ,MAAM,wCAAwC,MAAM;AAC5D,UAAQ,MAAM,+CAA+C;AAC7D,SAAO,CAAE;CACT;AACD,IAAG;AAEJ,0BAAe"}
@@ -7,9 +7,13 @@ declare function decryptCredentials(encrypted: string, iv: string, masterKey: st
7
7
  /**
8
8
  * Credentials object for use with EnvironmentParser.
9
9
  *
10
- * In development mode (no embedded credentials), this returns an empty object.
11
- * In production mode, it decrypts embedded credentials using the GKM_MASTER_KEY
12
- * environment variable.
10
+ * Resolution order:
11
+ * 1. **Dev mode (gkm dev/exec)**: Checks `globalThis.__gkm_credentials__` for
12
+ * credentials injected by the CLI preload script. This approach survives
13
+ * CJS/ESM module duplication (where mutating the export would only affect one copy).
14
+ * 2. **Production mode**: Decrypts build-time embedded credentials using the
15
+ * `GKM_MASTER_KEY` environment variable (AES-256-GCM).
16
+ * 3. **Fallback**: Returns empty object (allows graceful fallback to process.env).
13
17
  *
14
18
  * @example
15
19
  * ```typescript
@@ -1 +1 @@
1
- {"version":3,"file":"credentials.d.cts","names":[],"sources":["../src/credentials.ts"],"sourcesContent":[],"mappings":";;AAgBA;AA8CA;;iBA9CgB,kBAAA,oDAIb;;;;;;;;;;;;;;;;;;;;;;cA0CU,aAAa"}
1
+ {"version":3,"file":"credentials.d.cts","names":[],"sources":["../src/credentials.ts"],"sourcesContent":[],"mappings":";;AAgBA;AAkDA;;iBAlDgB,kBAAA,oDAIb;;;;;;;;;;;;;;;;;;;;;;;;;;cA8CU,aAAa"}
@@ -7,9 +7,13 @@ declare function decryptCredentials(encrypted: string, iv: string, masterKey: st
7
7
  /**
8
8
  * Credentials object for use with EnvironmentParser.
9
9
  *
10
- * In development mode (no embedded credentials), this returns an empty object.
11
- * In production mode, it decrypts embedded credentials using the GKM_MASTER_KEY
12
- * environment variable.
10
+ * Resolution order:
11
+ * 1. **Dev mode (gkm dev/exec)**: Checks `globalThis.__gkm_credentials__` for
12
+ * credentials injected by the CLI preload script. This approach survives
13
+ * CJS/ESM module duplication (where mutating the export would only affect one copy).
14
+ * 2. **Production mode**: Decrypts build-time embedded credentials using the
15
+ * `GKM_MASTER_KEY` environment variable (AES-256-GCM).
16
+ * 3. **Fallback**: Returns empty object (allows graceful fallback to process.env).
13
17
  *
14
18
  * @example
15
19
  * ```typescript
@@ -1 +1 @@
1
- {"version":3,"file":"credentials.d.mts","names":[],"sources":["../src/credentials.ts"],"sourcesContent":[],"mappings":";;AAgBA;AA8CA;;iBA9CgB,kBAAA,oDAIb;;;;;;;;;;;;;;;;;;;;;;cA0CU,aAAa"}
1
+ {"version":3,"file":"credentials.d.mts","names":[],"sources":["../src/credentials.ts"],"sourcesContent":[],"mappings":";;AAgBA;AAkDA;;iBAlDgB,kBAAA,oDAIb;;;;;;;;;;;;;;;;;;;;;;;;;;cA8CU,aAAa"}
@@ -21,9 +21,13 @@ function decryptCredentials(encrypted, iv, masterKey) {
21
21
  /**
22
22
  * Credentials object for use with EnvironmentParser.
23
23
  *
24
- * In development mode (no embedded credentials), this returns an empty object.
25
- * In production mode, it decrypts embedded credentials using the GKM_MASTER_KEY
26
- * environment variable.
24
+ * Resolution order:
25
+ * 1. **Dev mode (gkm dev/exec)**: Checks `globalThis.__gkm_credentials__` for
26
+ * credentials injected by the CLI preload script. This approach survives
27
+ * CJS/ESM module duplication (where mutating the export would only affect one copy).
28
+ * 2. **Production mode**: Decrypts build-time embedded credentials using the
29
+ * `GKM_MASTER_KEY` environment variable (AES-256-GCM).
30
+ * 3. **Fallback**: Returns empty object (allows graceful fallback to process.env).
27
31
  *
28
32
  * @example
29
33
  * ```typescript
@@ -40,6 +44,8 @@ function decryptCredentials(encrypted, iv, masterKey) {
40
44
  * ```
41
45
  */
42
46
  const Credentials = (() => {
47
+ const injected = globalThis.__gkm_credentials__;
48
+ if (injected) return injected;
43
49
  if (typeof __GKM_ENCRYPTED_CREDENTIALS__ === "undefined" || typeof __GKM_CREDENTIALS_IV__ === "undefined") return {};
44
50
  const masterKey = process.env.GKM_MASTER_KEY;
45
51
  if (!masterKey) {
@@ -1 +1 @@
1
- {"version":3,"file":"credentials.mjs","names":["encrypted: string","iv: string","masterKey: string","Credentials: Record<string, string>"],"sources":["../src/credentials.ts"],"sourcesContent":["import { createDecipheriv } from 'node:crypto';\n\n/**\n * Build-time injected encrypted credentials.\n * These are replaced by tsdown/esbuild --define at build time.\n */\ndeclare const __GKM_ENCRYPTED_CREDENTIALS__: string | undefined;\ndeclare const __GKM_CREDENTIALS_IV__: string | undefined;\n\n/** AES-256-GCM auth tag length */\nconst AUTH_TAG_LENGTH = 16;\n\n/**\n * Decrypt credentials from encrypted payload.\n * Exported for testing purposes.\n */\nexport function decryptCredentials(\n\tencrypted: string,\n\tiv: string,\n\tmasterKey: string,\n): Record<string, string> {\n\tconst key = Buffer.from(masterKey, 'hex');\n\tconst ivBuffer = Buffer.from(iv, 'hex');\n\tconst combined = Buffer.from(encrypted, 'base64');\n\n\t// Split ciphertext and auth tag\n\tconst ciphertext = combined.subarray(0, -AUTH_TAG_LENGTH);\n\tconst authTag = combined.subarray(-AUTH_TAG_LENGTH);\n\n\t// Decrypt using AES-256-GCM\n\tconst decipher = createDecipheriv('aes-256-gcm', key, ivBuffer);\n\tdecipher.setAuthTag(authTag);\n\n\tconst plaintext = Buffer.concat([\n\t\tdecipher.update(ciphertext),\n\t\tdecipher.final(),\n\t]);\n\n\treturn JSON.parse(plaintext.toString('utf-8'));\n}\n\n/**\n * Credentials object for use with EnvironmentParser.\n *\n * In development mode (no embedded credentials), this returns an empty object.\n * In production mode, it decrypts embedded credentials using the GKM_MASTER_KEY\n * environment variable.\n *\n * @example\n * ```typescript\n * import { EnvironmentParser } from '@geekmidas/envkit';\n * import { Credentials } from '@geekmidas/envkit/credentials';\n *\n * export const envParser = new EnvironmentParser({...process.env, ...Credentials})\n * .create((get) => ({\n * database: {\n * url: get('DATABASE_URL').string(),\n * },\n * }))\n * .parse();\n * ```\n */\nexport const Credentials: Record<string, string> = (() => {\n\t// Development mode - no credentials embedded at build time\n\tif (\n\t\ttypeof __GKM_ENCRYPTED_CREDENTIALS__ === 'undefined' ||\n\t\ttypeof __GKM_CREDENTIALS_IV__ === 'undefined'\n\t) {\n\t\treturn {};\n\t}\n\n\t// Production mode - decrypt credentials using master key\n\tconst masterKey = process.env.GKM_MASTER_KEY;\n\n\tif (!masterKey) {\n\t\t// Log warning but don't throw - allows graceful fallback to env vars\n\t\tconsole.error(\n\t\t\t'[gkm] GKM_MASTER_KEY environment variable is required to decrypt credentials.',\n\t\t);\n\t\tconsole.error(\n\t\t\t'[gkm] Falling back to environment variables. Some secrets may be missing.',\n\t\t);\n\t\treturn {};\n\t}\n\n\ttry {\n\t\treturn decryptCredentials(\n\t\t\t__GKM_ENCRYPTED_CREDENTIALS__,\n\t\t\t__GKM_CREDENTIALS_IV__,\n\t\t\tmasterKey,\n\t\t);\n\t} catch (error) {\n\t\tconsole.error('[gkm] Failed to decrypt credentials:', error);\n\t\tconsole.error('[gkm] Falling back to environment variables.');\n\t\treturn {};\n\t}\n})();\n\nexport default Credentials;\n"],"mappings":";;;;AAUA,MAAM,kBAAkB;;;;;AAMxB,SAAgB,mBACfA,WACAC,IACAC,WACyB;CACzB,MAAM,MAAM,OAAO,KAAK,WAAW,MAAM;CACzC,MAAM,WAAW,OAAO,KAAK,IAAI,MAAM;CACvC,MAAM,WAAW,OAAO,KAAK,WAAW,SAAS;CAGjD,MAAM,aAAa,SAAS,SAAS,IAAI,gBAAgB;CACzD,MAAM,UAAU,SAAS,UAAU,gBAAgB;CAGnD,MAAM,WAAW,iBAAiB,eAAe,KAAK,SAAS;AAC/D,UAAS,WAAW,QAAQ;CAE5B,MAAM,YAAY,OAAO,OAAO,CAC/B,SAAS,OAAO,WAAW,EAC3B,SAAS,OAAO,AAChB,EAAC;AAEF,QAAO,KAAK,MAAM,UAAU,SAAS,QAAQ,CAAC;AAC9C;;;;;;;;;;;;;;;;;;;;;;AAuBD,MAAaC,cAAsC,CAAC,MAAM;AAEzD,YACQ,kCAAkC,sBAClC,2BAA2B,YAElC,QAAO,CAAE;CAIV,MAAM,YAAY,QAAQ,IAAI;AAE9B,MAAK,WAAW;AAEf,UAAQ,MACP,gFACA;AACD,UAAQ,MACP,4EACA;AACD,SAAO,CAAE;CACT;AAED,KAAI;AACH,SAAO,mBACN,+BACA,wBACA,UACA;CACD,SAAQ,OAAO;AACf,UAAQ,MAAM,wCAAwC,MAAM;AAC5D,UAAQ,MAAM,+CAA+C;AAC7D,SAAO,CAAE;CACT;AACD,IAAG;AAEJ,0BAAe"}
1
+ {"version":3,"file":"credentials.mjs","names":["encrypted: string","iv: string","masterKey: string","Credentials: Record<string, string>"],"sources":["../src/credentials.ts"],"sourcesContent":["import { createDecipheriv } from 'node:crypto';\n\n/**\n * Build-time injected encrypted credentials.\n * These are replaced by tsdown/esbuild --define at build time.\n */\ndeclare const __GKM_ENCRYPTED_CREDENTIALS__: string | undefined;\ndeclare const __GKM_CREDENTIALS_IV__: string | undefined;\n\n/** AES-256-GCM auth tag length */\nconst AUTH_TAG_LENGTH = 16;\n\n/**\n * Decrypt credentials from encrypted payload.\n * Exported for testing purposes.\n */\nexport function decryptCredentials(\n\tencrypted: string,\n\tiv: string,\n\tmasterKey: string,\n): Record<string, string> {\n\tconst key = Buffer.from(masterKey, 'hex');\n\tconst ivBuffer = Buffer.from(iv, 'hex');\n\tconst combined = Buffer.from(encrypted, 'base64');\n\n\t// Split ciphertext and auth tag\n\tconst ciphertext = combined.subarray(0, -AUTH_TAG_LENGTH);\n\tconst authTag = combined.subarray(-AUTH_TAG_LENGTH);\n\n\t// Decrypt using AES-256-GCM\n\tconst decipher = createDecipheriv('aes-256-gcm', key, ivBuffer);\n\tdecipher.setAuthTag(authTag);\n\n\tconst plaintext = Buffer.concat([\n\t\tdecipher.update(ciphertext),\n\t\tdecipher.final(),\n\t]);\n\n\treturn JSON.parse(plaintext.toString('utf-8'));\n}\n\n/**\n * Credentials object for use with EnvironmentParser.\n *\n * Resolution order:\n * 1. **Dev mode (gkm dev/exec)**: Checks `globalThis.__gkm_credentials__` for\n * credentials injected by the CLI preload script. This approach survives\n * CJS/ESM module duplication (where mutating the export would only affect one copy).\n * 2. **Production mode**: Decrypts build-time embedded credentials using the\n * `GKM_MASTER_KEY` environment variable (AES-256-GCM).\n * 3. **Fallback**: Returns empty object (allows graceful fallback to process.env).\n *\n * @example\n * ```typescript\n * import { EnvironmentParser } from '@geekmidas/envkit';\n * import { Credentials } from '@geekmidas/envkit/credentials';\n *\n * export const envParser = new EnvironmentParser({...process.env, ...Credentials})\n * .create((get) => ({\n * database: {\n * url: get('DATABASE_URL').string(),\n * },\n * }))\n * .parse();\n * ```\n */\nexport const Credentials: Record<string, string> = (() => {\n\t// Dev mode: check if gkm exec/dev preload injected credentials via globalThis\n\t// This survives CJS/ESM module duplication where Object.assign on the\n\t// export would only mutate one copy of the module's Credentials object.\n\tconst injected = (globalThis as Record<string, unknown>)\n\t\t.__gkm_credentials__ as Record<string, string> | undefined;\n\tif (injected) {\n\t\treturn injected;\n\t}\n\n\t// Development mode - no credentials embedded at build time\n\tif (\n\t\ttypeof __GKM_ENCRYPTED_CREDENTIALS__ === 'undefined' ||\n\t\ttypeof __GKM_CREDENTIALS_IV__ === 'undefined'\n\t) {\n\t\treturn {};\n\t}\n\n\t// Production mode - decrypt credentials using master key\n\tconst masterKey = process.env.GKM_MASTER_KEY;\n\n\tif (!masterKey) {\n\t\t// Log warning but don't throw - allows graceful fallback to env vars\n\t\tconsole.error(\n\t\t\t'[gkm] GKM_MASTER_KEY environment variable is required to decrypt credentials.',\n\t\t);\n\t\tconsole.error(\n\t\t\t'[gkm] Falling back to environment variables. Some secrets may be missing.',\n\t\t);\n\t\treturn {};\n\t}\n\n\ttry {\n\t\treturn decryptCredentials(\n\t\t\t__GKM_ENCRYPTED_CREDENTIALS__,\n\t\t\t__GKM_CREDENTIALS_IV__,\n\t\t\tmasterKey,\n\t\t);\n\t} catch (error) {\n\t\tconsole.error('[gkm] Failed to decrypt credentials:', error);\n\t\tconsole.error('[gkm] Falling back to environment variables.');\n\t\treturn {};\n\t}\n})();\n\nexport default Credentials;\n"],"mappings":";;;;AAUA,MAAM,kBAAkB;;;;;AAMxB,SAAgB,mBACfA,WACAC,IACAC,WACyB;CACzB,MAAM,MAAM,OAAO,KAAK,WAAW,MAAM;CACzC,MAAM,WAAW,OAAO,KAAK,IAAI,MAAM;CACvC,MAAM,WAAW,OAAO,KAAK,WAAW,SAAS;CAGjD,MAAM,aAAa,SAAS,SAAS,IAAI,gBAAgB;CACzD,MAAM,UAAU,SAAS,UAAU,gBAAgB;CAGnD,MAAM,WAAW,iBAAiB,eAAe,KAAK,SAAS;AAC/D,UAAS,WAAW,QAAQ;CAE5B,MAAM,YAAY,OAAO,OAAO,CAC/B,SAAS,OAAO,WAAW,EAC3B,SAAS,OAAO,AAChB,EAAC;AAEF,QAAO,KAAK,MAAM,UAAU,SAAS,QAAQ,CAAC;AAC9C;;;;;;;;;;;;;;;;;;;;;;;;;;AA2BD,MAAaC,cAAsC,CAAC,MAAM;CAIzD,MAAM,WAAY,WAChB;AACF,KAAI,SACH,QAAO;AAIR,YACQ,kCAAkC,sBAClC,2BAA2B,YAElC,QAAO,CAAE;CAIV,MAAM,YAAY,QAAQ,IAAI;AAE9B,MAAK,WAAW;AAEf,UAAQ,MACP,gFACA;AACD,UAAQ,MACP,4EACA;AACD,SAAO,CAAE;CACT;AAED,KAAI;AACH,SAAO,mBACN,+BACA,wBACA,UACA;CACD,SAAQ,OAAO;AACf,UAAQ,MAAM,wCAAwC,MAAM;AAC5D,UAAQ,MAAM,+CAA+C;AAC7D,SAAO,CAAE;CACT;AACD,IAAG;AAEJ,0BAAe"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@geekmidas/envkit",
3
- "version": "1.0.3",
3
+ "version": "1.0.4",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "exports": {
@@ -42,9 +42,13 @@ export function decryptCredentials(
42
42
  /**
43
43
  * Credentials object for use with EnvironmentParser.
44
44
  *
45
- * In development mode (no embedded credentials), this returns an empty object.
46
- * In production mode, it decrypts embedded credentials using the GKM_MASTER_KEY
47
- * environment variable.
45
+ * Resolution order:
46
+ * 1. **Dev mode (gkm dev/exec)**: Checks `globalThis.__gkm_credentials__` for
47
+ * credentials injected by the CLI preload script. This approach survives
48
+ * CJS/ESM module duplication (where mutating the export would only affect one copy).
49
+ * 2. **Production mode**: Decrypts build-time embedded credentials using the
50
+ * `GKM_MASTER_KEY` environment variable (AES-256-GCM).
51
+ * 3. **Fallback**: Returns empty object (allows graceful fallback to process.env).
48
52
  *
49
53
  * @example
50
54
  * ```typescript
@@ -61,6 +65,15 @@ export function decryptCredentials(
61
65
  * ```
62
66
  */
63
67
  export const Credentials: Record<string, string> = (() => {
68
+ // Dev mode: check if gkm exec/dev preload injected credentials via globalThis
69
+ // This survives CJS/ESM module duplication where Object.assign on the
70
+ // export would only mutate one copy of the module's Credentials object.
71
+ const injected = (globalThis as Record<string, unknown>)
72
+ .__gkm_credentials__ as Record<string, string> | undefined;
73
+ if (injected) {
74
+ return injected;
75
+ }
76
+
64
77
  // Development mode - no credentials embedded at build time
65
78
  if (
66
79
  typeof __GKM_ENCRYPTED_CREDENTIALS__ === 'undefined' ||