@stacksjs/env 0.74.33 → 0.74.35
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/dist/cli.js +2 -2
- package/dist/index.js +18 -18
- package/dist/parser.js +1 -1
- package/dist/plugin.js +2 -2
- package/package.json +3 -3
package/dist/cli.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{
|
|
2
|
+
import{createCipheriv as X,createDecipheriv as H,createHash as I,createPrivateKey as fe,createPublicKey as G,diffieHellman as J,generateKeyPairSync as M,hkdfSync as z,randomBytes as S}from"crypto";var Y="x25519-public:",A="x25519-private:",C="encrypted:v2:",U="encrypted:",q=Buffer.from("stacks-env:v2","utf8"),Z="Environment decryption failed: authentication or format error";function Q(t){if(t.length===32)return t;return I("sha256").update(t).digest()}function Be(t,n){let e=S(16),s=X("aes-256-gcm",Q(n),e);return{ciphertext:Buffer.concat([s.update(t,"utf8"),s.final()]).toString("hex"),iv:e.toString("hex"),authTag:s.getAuthTag().toString("hex")}}function le(t,n,e,s){try{let r=H("aes-256-gcm",Q(n),Buffer.from(e,"hex"));return r.setAuthTag(Buffer.from(s,"hex")),Buffer.concat([r.update(Buffer.from(t,"hex")),r.final()]).toString("utf8")}catch{throw Error("Decryption failed: authentication or format error")}}function x(t){return t.toString("base64url")}function V(t,n,e){if(typeof t!=="string"||t.length>0&&!/^[A-Za-z0-9_-]+$/.test(t))throw Error(`${n} is not canonical base64url`);let s=Buffer.from(t,"base64url");if(x(s)!==t)throw Error(`${n} is not canonical base64url`);if(e!==void 0&&s.length!==e)throw Error(`${n} has an invalid length`);return s}function pe(t){if(!t.startsWith(Y))throw Error("Legacy or invalid public key. Run buddy env:rotate before creating new ciphertext.");let n=G({key:V(t.slice(Y.length),"public key"),format:"der",type:"spki"});if(n.asymmetricKeyType!=="x25519")throw Error("Public key is not X25519");return n}function de(t){if(!t.startsWith(A))throw Error("Private key is not a version 2 X25519 key");let n=fe({key:V(t.slice(A.length),"private key"),format:"der",type:"pkcs8"});if(n.asymmetricKeyType!=="x25519")throw Error("Private key is not X25519");return n}function ee(t){return Buffer.from(`stacks-env:v2;${t.epk};${t.salt};${t.nonce}`,"utf8")}function F(){let{publicKey:t,privateKey:n}=M("x25519"),e=t.export({format:"der",type:"spki"}),s=n.export({format:"der",type:"pkcs8"});return{publicKey:`${Y}${x(e)}`,privateKey:`${A}${x(s)}`}}function W(t,n){let e=pe(n),s=M("x25519"),r=x(s.publicKey.export({format:"der",type:"spki"})),i=S(16),o=S(12),a=J({privateKey:s.privateKey,publicKey:e}),u=Buffer.from(z("sha256",a,i,q,32)),f={epk:r,salt:x(i),nonce:x(o)};try{let c=X("aes-256-gcm",u,o);c.setAAD(ee(f));let l=Buffer.concat([c.update(t,"utf8"),c.final()]),p={v:2,...f,ciphertext:x(l),tag:x(c.getAuthTag())};return`${C}${x(Buffer.from(JSON.stringify(p),"utf8"))}`}finally{a.fill(0),u.fill(0)}}function ye(t){let n=V(t.slice(C.length),"envelope").toString("utf8"),e=JSON.parse(n);if(!e||typeof e!=="object"||Array.isArray(e))throw Error("envelope is not an object");let s=Object.keys(e).sort(),r=["ciphertext","epk","nonce","salt","tag","v"];if(s.length!==r.length||s.some((i,o)=>i!==r[o]))throw Error("envelope fields are invalid");if(e.v!==2)throw Error("envelope version is unsupported");for(let i of["epk","salt","nonce","ciphertext","tag"])if(typeof e[i]!=="string")throw Error(`${i} is invalid`);return e}function ge(t,n){try{let e=ye(t),s=de(n),r=G({key:V(e.epk,"ephemeral public key"),format:"der",type:"spki"});if(r.asymmetricKeyType!=="x25519")throw Error("ephemeral key is not X25519");let i=V(e.salt,"salt",16),o=V(e.nonce,"nonce",12),a=V(e.ciphertext,"ciphertext"),u=V(e.tag,"tag",16),f=J({privateKey:s,publicKey:r}),c=Buffer.from(z("sha256",f,i,q,32));try{let l=H("aes-256-gcm",c,o);return l.setAAD(ee(e)),l.setAuthTag(u),Buffer.concat([l.update(a),l.final()]).toString("utf8")}finally{f.fill(0),c.fill(0)}}catch{throw Error(Z)}}function he(t,n){try{if(!/^[0-9a-f]{64}$/.test(n))throw Error("invalid legacy private key");let e=Buffer.from(t.slice(U.length),"base64");if(e.length<32)throw Error("invalid legacy payload");let s=I("sha256").update(Buffer.from(n,"hex")).digest(),r=I("sha256").update(s).digest();return le(e.subarray(32).toString("hex"),r,e.subarray(0,16).toString("hex"),e.subarray(16,32).toString("hex"))}catch{throw Error(Z)}}function Ie(t){return t.startsWith(U)&&!t.startsWith(C)}function R(t,n){if(!t.startsWith(U))return t;return t.startsWith(C)?ge(t,n):he(t,n)}function Se(t,n,e){return W(R(t,n),e)}function Ye(t){let n=t.match(/^DOTENV_PRIVATE_KEY_(.+)$/);return n&&n[1]?n[1].toLowerCase():""}function Ae(t=""){return t?process.env[`DOTENV_PRIVATE_KEY_${t.toUpperCase()}`]:process.env.DOTENV_PRIVATE_KEY}import{spawnSync as me}from"child_process";import{readFileSync as ve}from"fs";import{arch as Ee,hostname as $e,platform as te,release as ke,userInfo as Ke}from"os";import{basename as we,dirname as be,resolve as Ne}from"path";function T(t,n={}){let e={},s=[],r=[],i=t.split(`
|
|
3
3
|
`);for(let o of i){let a=o.trim();if(!a||a.startsWith("#"))continue;if(a.startsWith("DOTENV_PUBLIC_KEY=")){let l=a.match(/^DOTENV_PUBLIC_KEY=["']?([^"'\n]+)["']?/);if(l&&l[1]!==void 0)e.DOTENV_PUBLIC_KEY=l[1];continue}let u=a.match(/^([^=]+)=(.*)$/);if(!u||u[1]===void 0||u[2]===void 0)continue;let f=u[1].trim(),c=u[2].trim();if(c.startsWith('"')&&c.endsWith('"')||c.startsWith("'")&&c.endsWith("'")){if(c=c.slice(1,-1),c.includes("\\n"))c=c.replace(/\\n/g,`
|
|
4
|
-
`)}if(c.startsWith("encrypted:")||c.startsWith("enc:")){if(!n.privateKey){r.push(f);continue}try{let l=c.startsWith("enc:")?`encrypted:${c.slice(4)}`:c;c=R(l,n.privateKey)}catch(l){s.push(`Failed to decrypt ${f}: ${l instanceof Error?l.message:"Unknown error"}`)}}c=_e(c,{...n.processEnv||process.env,...e}),c=Te(c),e[f]=c}return{parsed:e,errors:s,skippedEncrypted:r}}function _e(t,n){return t.replace(/\$\{([^}]+)\}/g,(e,s)=>{let r=s.match(/^([^:\-+]+)(:-|-)(.+)$/);if(r){let[,o,a,u]=r,f=n[o];if(a===":-")return f||u;else return f!==void 0?f:u}let i=s.match(/^([^:\-+]+)(:?\+)(.+)$/);if(i){let[,o,a,u]=i,f=n[o];if(a===":+")return f?u:"";else return f!==void 0?u:""}return n[s]||""})}var xe=new Set(["date","hostname","whoami","uname","pwd","echo","printf","cat","basename","dirname"]);function Pe(t){let n=[],e="",s=null,r=!1;for(let i of t.trim()){if(r){e+=i,r=!1;continue}if(i==="\\"&&s!=="'"){r=!0;continue}if(s){if(i===s)s=null;else e+=i;continue}if(i==='"'||i==="'"){s=i;continue}if(/\s/.test(i)){if(e)n.push(e),e="";continue}e+=i}if(r||s)throw Error("Command substitution contains an unterminated escape or quote");if(e)n.push(e);return n}function Ve(t){let[n,...e]=t,s=e.some((r)=>r.startsWith("-"));if(n==="echo"&&!s)return e.join(" ");if(n==="printf"&&e.length===1&&!e[0]?.includes("%"))return e[0];if(n==="hostname"&&e.length===0)return $e();if(n==="whoami"&&e.length===0)return Ke().username;if(n==="pwd"&&e.length===0)return process.cwd();if(n==="basename"&&e.length===1)return we(e[0]??"");if(n==="dirname"&&e.length===1)return be(e[0]??"");if(n==="cat"&&e.length>0&&!s)return e.map((r)=>ve(Ne(process.cwd(),r),"utf8")).join("");if(n==="uname"){let r=e[0]??"-s";if(e.length<=1&&r==="-m")return Ee();if(e.length<=1&&r==="-r")return ke();if(e.length<=1&&r==="-s")return{aix:"AIX",android:"Android",cygwin:"CYGWIN",darwin:"Darwin",freebsd:"FreeBSD",haiku:"Haiku",linux:"Linux",netbsd:"NetBSD",openbsd:"OpenBSD",sunos:"SunOS",win32:"Windows_NT"}[te()]??te()}return}function Te(t){return t.replace(/\$\(([^)]+)\)/g,(n,e)=>{try{let s=Pe(e),r=s[0];if(!r||!xe.has(r))return console.warn(`[env] Blocked command substitution for disallowed command: ${r}`),"";let i=Ve(s);if(i!==void 0)return i.trim();let o=me(r,s.slice(1),{encoding:"utf8",env:process.env});if(o.status===0)return o.stdout.trim();let a=o.stderr.trim();console.warn(`[env] Command substitution failed (exit code ${o.status??"unknown"}): ${r}${a?`: ${a}`:""}`)}catch(s){console.warn(`[env] Command substitution error: ${s instanceof Error?s.message:String(s)}`)}return""})}async function Je(t,n={}){let e={},s=[],r=[];for(let i of t)try{let o=Bun.file(i);if(!o.size)continue;let a=await o.text(),{parsed:u,errors:f,skippedEncrypted:c}=T(a,n);s.push(...f),r.push(...c);for(let[l,p]of Object.entries(u)){if(!n.overload&&e[l]!==void 0)continue;e[l]=p}}catch(o){if(o?.code==="ENOENT")continue;s.push(`Failed to read ${i}: ${o instanceof Error?o.message:String(o)}`)}return{parsed:e,errors:s,skippedEncrypted:r}}function et(t,n){if(t)return t;let e=String(n??"").trim();if(!e||e==="development"||e==="dev"||e==="local")return"";if(!/^[\w.-]+$/.test(e))return"";return`.env.${e}`}function oe(t,n){return(!n.key||t.includes(n.key))&&(!n.excludeKey||!t.includes(n.excludeKey))}function Oe(t,n){let e=[];for(let s of t.split(`
|
|
4
|
+
`)}if(c.startsWith("encrypted:")||c.startsWith("enc:")){if(!n.privateKey){r.push(f);continue}try{let l=c.startsWith("enc:")?`encrypted:${c.slice(4)}`:c;c=R(l,n.privateKey)}catch(l){s.push(`Failed to decrypt ${f}: ${l instanceof Error?l.message:"Unknown error"}`)}}c=_e(c,{...n.processEnv||process.env,...e}),c=Te(c),e[f]=c}return{parsed:e,errors:s,skippedEncrypted:r}}function _e(t,n){return t.replace(/\$\{([^}]+)\}/g,(e,s)=>{let r=s.match(/^([^:\-+]+)(:-|-)(.+)$/);if(r){let[,o,a,u]=r,f=n[o];if(a===":-")return f||u;else return f!==void 0?f:u}let i=s.match(/^([^:\-+]+)(:?\+)(.+)$/);if(i){let[,o,a,u]=i,f=n[o];if(a===":+")return f?u:"";else return f!==void 0?u:""}return n[s]||""})}var xe=new Set(["date","hostname","whoami","uname","pwd","echo","printf","cat","basename","dirname"]);function Pe(t){let n=[],e="",s=null,r=!1;for(let i of t.trim()){if(r){e+=i,r=!1;continue}if(i==="\\"&&s!=="'"){r=!0;continue}if(s){if(i===s)s=null;else e+=i;continue}if(i==='"'||i==="'"){s=i;continue}if(/\s/.test(i)){if(e)n.push(e),e="";continue}e+=i}if(r||s)throw Error("Command substitution contains an unterminated escape or quote");if(e)n.push(e);return n}function Ve(t){let[n,...e]=t,s=e.some((r)=>r.startsWith("-"));if(n==="echo"&&!s)return e.join(" ");if(n==="printf"&&e.length===1&&!e[0]?.includes("%"))return e[0];if(n==="hostname"&&e.length===0)return $e();if(n==="whoami"&&e.length===0)return Ke().username;if(n==="pwd"&&e.length===0)return process.cwd();if(n==="basename"&&e.length===1)return we(e[0]??"");if(n==="dirname"&&e.length===1)return be(e[0]??"");if(n==="cat"&&e.length>0&&!s)return e.map((r)=>ve(Ne(process.cwd(),r),"utf8")).join("");if(n==="uname"){let r=e[0]??"-s";if(e.length<=1&&r==="-m")return Ee();if(e.length<=1&&r==="-r")return ke();if(e.length<=1&&r==="-s")return{aix:"AIX",android:"Android",cygwin:"CYGWIN",darwin:"Darwin",freebsd:"FreeBSD",haiku:"Haiku",linux:"Linux",netbsd:"NetBSD",openbsd:"OpenBSD",sunos:"SunOS",win32:"Windows_NT"}[te()]??te()}return}function Te(t){return t.replace(/\$\(([^)]+)\)/g,(n,e)=>{try{let s=Pe(e),r=s[0];if(!r||!xe.has(r))return console.warn(`[env] Blocked command substitution for disallowed command: ${r}`),"";let i=Ve(s);if(i!==void 0)return i.trim();let o=me(r,s.slice(1),{encoding:"utf8",env:process.env});if(o.status===0)return o.stdout.trim();let a=o.stderr.trim();console.warn(`[env] Command substitution failed (exit code ${o.status??"unknown"}): ${r}${a?`: ${a}`:""}`)}catch(s){console.warn(`[env] Command substitution error: ${s instanceof Error?s.message:String(s)}`)}return""})}async function Je(t,n={}){let e={},s=[],r=[];for(let i of t)try{let o=Bun.file(i);if(!o.size)continue;let a=await o.text(),{parsed:u,errors:f,skippedEncrypted:c}=T(a,n);s.push(...f),r.push(...c);for(let[l,p]of Object.entries(u)){if(!n.overload&&e[l]!==void 0)continue;e[l]=p}}catch(o){if(o?.code==="ENOENT")continue;s.push(`Failed to read ${i}: ${o instanceof Error?o.message:String(o)}`)}return{parsed:e,errors:s,skippedEncrypted:r}}import{existsSync as K,readFileSync as k,renameSync as ne,rmSync as re,writeFileSync as b}from"fs";import{basename as se,dirname as j,resolve as E}from"path";function et(t,n){if(t)return t;let e=String(n??"").trim();if(!e||e==="development"||e==="dev"||e==="local")return"";if(!/^[\w.-]+$/.test(e))return"";return`.env.${e}`}function oe(t,n){return(!n.key||t.includes(n.key))&&(!n.excludeKey||!t.includes(n.excludeKey))}function Oe(t,n){let e=[];for(let s of t.split(`
|
|
5
5
|
`)){let r=s.trim();if(!r||r.startsWith("#"))continue;if(r.startsWith("DOTENV_PUBLIC_KEY"))continue;let i=r.match(/^([^=]+)=(.*)$/);if(!i||i[1]===void 0)continue;let o=i[1].trim();if(oe(o,n))e.push(o)}return e}function ce(t,n,e,s){let r=["#/-------------------[DOTENV_PUBLIC_KEY]--------------------/","#/ versioned X25519 encryption for .env files /","#/ [how it works](https://stacksjs.com/encryption) /","#/----------------------------------------------------------/",`${e}="${n}"`,""],i=!1;for(let o of t.split(`
|
|
6
6
|
`)){let a=o.trim();if(a.startsWith("#/"))continue;if(a.startsWith("DOTENV_PUBLIC_KEY"))continue;if(!a&&!i)continue;if(!a||a.startsWith("#")){i=!0,r.push(o);continue}i=!0;let u=a.match(/^([^=]+)=(.*)$/);if(!u||u[1]===void 0||u[2]===void 0){r.push(o);continue}let f=u[1].trim(),c=u[2].trim();if(c.startsWith('"')&&c.endsWith('"')||c.startsWith("'")&&c.endsWith("'"))c=c.slice(1,-1);if(oe(f,s)&&!c.startsWith("encrypted:"))c=W(c,n);r.push(`${f}="${c}"`)}return r.join(`
|
|
7
7
|
`)}function D(t){let e=((t||".env").split("/").pop()||"").replace(/^\.env\./,"").replace(/^\.env$/,"").toUpperCase();return{publicKeyName:e?`DOTENV_PUBLIC_KEY_${e}`:"DOTENV_PUBLIC_KEY",privateKeyName:e?`DOTENV_PRIVATE_KEY_${e}`:"DOTENV_PRIVATE_KEY"}}function ae(t){let{publicKeyName:n}=D(t);return n==="DOTENV_PUBLIC_KEY"?[n]:[n,"DOTENV_PUBLIC_KEY"]}function L(t){let{privateKeyName:n}=D(t);return n==="DOTENV_PRIVATE_KEY"?[n]:[n,"DOTENV_PRIVATE_KEY"]}function ie(t){for(let n of t.split(`
|
package/dist/index.js
CHANGED
|
@@ -1,35 +1,35 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import
|
|
2
|
+
import{createCipheriv as ie,createDecipheriv as se,createHash as H,createPrivateKey as Le,createPublicKey as oe,diffieHellman as de,generateKeyPairSync as ce,hkdfSync as ae,randomBytes as j}from"crypto";var X="x25519-public:",Q="x25519-private:",w="encrypted:v2:",q="encrypted:",ue=Buffer.from("stacks-env:v2","utf8"),fe="Environment decryption failed: authentication or format error";function Ee(e){if(e.length===32)return e;return H("sha256").update(e).digest()}function In(e,n){let t=j(16),r=ie("aes-256-gcm",Ee(n),t);return{ciphertext:Buffer.concat([r.update(e,"utf8"),r.final()]).toString("hex"),iv:t.toString("hex"),authTag:r.getAuthTag().toString("hex")}}function ke(e,n,t,r){try{let i=se("aes-256-gcm",Ee(n),Buffer.from(t,"hex"));return i.setAuthTag(Buffer.from(r,"hex")),Buffer.concat([i.update(Buffer.from(e,"hex")),i.final()]).toString("utf8")}catch{throw Error("Decryption failed: authentication or format error")}}function C(e){return e.toString("base64url")}function b(e,n,t){if(typeof e!=="string"||e.length>0&&!/^[A-Za-z0-9_-]+$/.test(e))throw Error(`${n} is not canonical base64url`);let r=Buffer.from(e,"base64url");if(C(r)!==e)throw Error(`${n} is not canonical base64url`);if(t!==void 0&&r.length!==t)throw Error(`${n} has an invalid length`);return r}function Ue(e){if(!e.startsWith(X))throw Error("Legacy or invalid public key. Run buddy env:rotate before creating new ciphertext.");let n=oe({key:b(e.slice(X.length),"public key"),format:"der",type:"spki"});if(n.asymmetricKeyType!=="x25519")throw Error("Public key is not X25519");return n}function $e(e){if(!e.startsWith(Q))throw Error("Private key is not a version 2 X25519 key");let n=Le({key:b(e.slice(Q.length),"private key"),format:"der",type:"pkcs8"});if(n.asymmetricKeyType!=="x25519")throw Error("Private key is not X25519");return n}function le(e){return Buffer.from(`stacks-env:v2;${e.epk};${e.salt};${e.nonce}`,"utf8")}function U(){let{publicKey:e,privateKey:n}=ce("x25519"),t=e.export({format:"der",type:"spki"}),r=n.export({format:"der",type:"pkcs8"});return{publicKey:`${X}${C(t)}`,privateKey:`${Q}${C(r)}`}}function B(e,n){let t=Ue(n),r=ce("x25519"),i=C(r.publicKey.export({format:"der",type:"spki"})),s=j(16),o=j(12),d=de({privateKey:r.privateKey,publicKey:t}),c=Buffer.from(ae("sha256",d,s,ue,32)),a={epk:i,salt:C(s),nonce:C(o)};try{let u=ie("aes-256-gcm",c,o);u.setAAD(le(a));let f=Buffer.concat([u.update(e,"utf8"),u.final()]),E={v:2,...a,ciphertext:C(f),tag:C(u.getAuthTag())};return`${w}${C(Buffer.from(JSON.stringify(E),"utf8"))}`}finally{d.fill(0),c.fill(0)}}function xe(e){let n=b(e.slice(w.length),"envelope").toString("utf8"),t=JSON.parse(n);if(!t||typeof t!=="object"||Array.isArray(t))throw Error("envelope is not an object");let r=Object.keys(t).sort(),i=["ciphertext","epk","nonce","salt","tag","v"];if(r.length!==i.length||r.some((s,o)=>s!==i[o]))throw Error("envelope fields are invalid");if(t.v!==2)throw Error("envelope version is unsupported");for(let s of["epk","salt","nonce","ciphertext","tag"])if(typeof t[s]!=="string")throw Error(`${s} is invalid`);return t}function we(e,n){try{let t=xe(e),r=$e(n),i=oe({key:b(t.epk,"ephemeral public key"),format:"der",type:"spki"});if(i.asymmetricKeyType!=="x25519")throw Error("ephemeral key is not X25519");let s=b(t.salt,"salt",16),o=b(t.nonce,"nonce",12),d=b(t.ciphertext,"ciphertext"),c=b(t.tag,"tag",16),a=de({privateKey:r,publicKey:i}),u=Buffer.from(ae("sha256",a,s,ue,32));try{let f=se("aes-256-gcm",u,o);return f.setAAD(le(t)),f.setAuthTag(c),Buffer.concat([f.update(d),f.final()]).toString("utf8")}finally{a.fill(0),u.fill(0)}}catch{throw Error(fe)}}function Be(e,n){try{if(!/^[0-9a-f]{64}$/.test(n))throw Error("invalid legacy private key");let t=Buffer.from(e.slice(q.length),"base64");if(t.length<32)throw Error("invalid legacy payload");let r=H("sha256").update(Buffer.from(n,"hex")).digest(),i=H("sha256").update(r).digest();return ke(t.subarray(32).toString("hex"),i,t.subarray(0,16).toString("hex"),t.subarray(16,32).toString("hex"))}catch{throw Error(fe)}}function Nn(e){return e.startsWith(q)&&!e.startsWith(w)}function L(e,n){if(!e.startsWith(q))return e;return e.startsWith(w)?we(e,n):Be(e,n)}function hn(e,n,t){return B(L(e,n),t)}function Pn(e){let n=e.match(/^DOTENV_PRIVATE_KEY_(.+)$/);return n&&n[1]?n[1].toLowerCase():""}function z(e=""){return e?process.env[`DOTENV_PRIVATE_KEY_${e.toUpperCase()}`]:process.env.DOTENV_PRIVATE_KEY}import{spawnSync as Ve}from"child_process";import{readFileSync as Me}from"fs";import{arch as Fe,hostname as Ye,platform as pe,release as We,userInfo as Ge}from"os";import{basename as He,dirname as je,resolve as Xe}from"path";function h(e,n={}){let t={},r=[],i=[],s=e.split(`
|
|
3
3
|
`);for(let o of s){let d=o.trim();if(!d||d.startsWith("#"))continue;if(d.startsWith("DOTENV_PUBLIC_KEY=")){let f=d.match(/^DOTENV_PUBLIC_KEY=["']?([^"'\n]+)["']?/);if(f&&f[1]!==void 0)t.DOTENV_PUBLIC_KEY=f[1];continue}let c=d.match(/^([^=]+)=(.*)$/);if(!c||c[1]===void 0||c[2]===void 0)continue;let a=c[1].trim(),u=c[2].trim();if(u.startsWith('"')&&u.endsWith('"')||u.startsWith("'")&&u.endsWith("'")){if(u=u.slice(1,-1),u.includes("\\n"))u=u.replace(/\\n/g,`
|
|
4
|
-
`)}if(u.startsWith("encrypted:")||u.startsWith("enc:")){if(!n.privateKey){i.push(a);continue}try{let f=u.startsWith("enc:")?`encrypted:${u.slice(4)}`:u;u=L(f,n.privateKey)}catch(f){r.push(`Failed to decrypt ${a}: ${f instanceof Error?f.message:"Unknown error"}`)}}u=Qe(u,{...n.processEnv||process.env,...t}),u=Ze(u),t[a]=u}return{parsed:t,errors:r,skippedEncrypted:i}}function Qe(e,n){return e.replace(/\$\{([^}]+)\}/g,(t,r)=>{let i=r.match(/^([^:\-+]+)(:-|-)(.+)$/);if(i){let[,o,d,c]=i,a=n[o];if(d===":-")return a||c;else return a!==void 0?a:c}let s=r.match(/^([^:\-+]+)(:?\+)(.+)$/);if(s){let[,o,d,c]=s,a=n[o];if(d===":+")return a?c:"";else return a!==void 0?c:""}return n[r]||""})}var qe=new Set(["date","hostname","whoami","uname","pwd","echo","printf","cat","basename","dirname"]);function ze(e){let n=[],t="",r=null,i=!1;for(let s of e.trim()){if(i){t+=s,i=!1;continue}if(s==="\\"&&r!=="'"){i=!0;continue}if(r){if(s===r)r=null;else t+=s;continue}if(s==='"'||s==="'"){r=s;continue}if(/\s/.test(s)){if(t)n.push(t),t="";continue}t+=s}if(i||r)throw Error("Command substitution contains an unterminated escape or quote");if(t)n.push(t);return n}function Je(e){let[n,...t]=e,r=t.some((i)=>i.startsWith("-"));if(n==="echo"&&!r)return t.join(" ");if(n==="printf"&&t.length===1&&!t[0]?.includes("%"))return t[0];if(n==="hostname"&&t.length===0)return Ye();if(n==="whoami"&&t.length===0)return Ge().username;if(n==="pwd"&&t.length===0)return process.cwd();if(n==="basename"&&t.length===1)return He(t[0]??"");if(n==="dirname"&&t.length===1)return je(t[0]??"");if(n==="cat"&&t.length>0&&!r)return t.map((i)=>Me(Xe(process.cwd(),i),"utf8")).join("");if(n==="uname"){let i=t[0]??"-s";if(t.length<=1&&i==="-m")return Fe();if(t.length<=1&&i==="-r")return We();if(t.length<=1&&i==="-s")return{aix:"AIX",android:"Android",cygwin:"CYGWIN",darwin:"Darwin",freebsd:"FreeBSD",haiku:"Haiku",linux:"Linux",netbsd:"NetBSD",openbsd:"OpenBSD",sunos:"SunOS",win32:"Windows_NT"}[pe()]??pe()}return}function Ze(e){return e.replace(/\$\(([^)]+)\)/g,(n,t)=>{try{let r=ze(t),i=r[0];if(!i||!qe.has(i))return console.warn(`[env] Blocked command substitution for disallowed command: ${i}`),"";let s=Je(r);if(s!==void 0)return s.trim();let o=Ve(i,r.slice(1),{encoding:"utf8",env:process.env});if(o.status===0)return o.stdout.trim();let d=o.stderr.trim();console.warn(`[env] Command substitution failed (exit code ${o.status??"unknown"}): ${i}${d?`: ${d}`:""}`)}catch(r){console.warn(`[env] Command substitution error: ${r instanceof Error?r.message:String(r)}`)}return""})}async function Un(e,n={}){let t={},r=[],i=[];for(let s of e)try{let o=Bun.file(s);if(!o.size)continue;let d=await o.text(),{parsed:c,errors:a,skippedEncrypted:u}=h(d,n);r.push(...a),i.push(...u);for(let[f,E]of Object.entries(c)){if(!n.overload&&t[f]!==void 0)continue;t[f]=E}}catch(o){if(o?.code==="ENOENT")continue;r.push(`Failed to read ${s}: ${o instanceof Error?o.message:String(o)}`)}return{parsed:t,errors:r,skippedEncrypted:i}}function x(e){return typeof e==="string"&&(e.startsWith("encrypted:")||e.startsWith("enc:"))}function K(e){if(!e||x(e))return;let n=e.trim().toLowerCase();if(!/^[a-z0-9_-]+$/.test(n))return;if(n==="prod")return"production";if(n==="stage")return"staging";if(n==="dev")return"development";return n}var F=null,Y,W;function en(e,n,t=".env.keys"){let r=M(n,t);if(!V(r))return;try{let{parsed:i}=h(J(r,"utf-8"));if(e){let s=i[`DOTENV_PRIVATE_KEY_${e.toUpperCase()}`];if(s)return s}return i.DOTENV_PRIVATE_KEY}catch{return}}function Z(e={}){return K(e.env)||W||K("development")||K(process.env.DOTENV_ENV)||K(process.env.APP_ENV)||"development"}function nn(e={}){let n=Z(e),t=e.cwd||process.cwd();if(F===n)return Y;let r=z(n);if(!r)r=process.env.DOTENV_PRIVATE_KEY;if(!r)r=en(n,t);return F=n,Y=r,r}function Fn(){F=null,Y=void 0,W=void 0}function ge(e,n={}){if(!x(e))return e;let t=nn(n);if(!t)return;try{let r=e.startsWith("enc:")?`encrypted:${e.slice(4)}`:e;return L(r,t)}catch{return}}function _e(e={}){let{path:n=[".env"],overload:t=!1,env:r,privateKey:i,keysFile:s=".env.keys",quiet:o=!1,cwd:d=process.cwd()}=e,c=Array.isArray(n)?n:[n],a=[],u=0,f=new Set(Object.entries(process.env).filter(([,g])=>g!==void 0&&!x(g)).map(([g])=>g)),E=i;if(!E&&s){let g=M(d,s);if(V(g))try{let l=J(g,"utf-8"),{parsed:y}=h(l);if(r){let v=`DOTENV_PRIVATE_KEY_${r.toUpperCase()}`;E=y[v]}else E=y.DOTENV_PRIVATE_KEY}catch(l){a.push(`Failed to load keys file: ${l instanceof Error?l.message:"Unknown error"}`)}}if(!E)E=z(r||"");for(let g of c){let l=M(d,g);if(!V(l)){if(!o)a.push(`File not found: ${l}`);continue}try{let y=J(l,"utf-8"),{parsed:v,errors:T,skippedEncrypted:O}=h(y,{privateKey:E,processEnv:process.env});if(a.push(...T),O.length>0){for(let I of O)if(x(process.env[I]))delete process.env[I];let _=r?`DOTENV_PRIVATE_KEY_${r.toUpperCase()}`:"DOTENV_PRIVATE_KEY",A=O.slice(0,5).join(", "),R=O.length>5?`, \u2026 +${O.length-5} more`:"";console.warn(`[env] warning: skipped ${O.length} encrypted value(s) in ${g} (${_} not set; defaults apply): ${A}${R}`)}let m=0;for(let[_,A]of Object.entries(v)){if(_==="DOTENV_PUBLIC_KEY")continue;let R=process.env[_],I=x(R)&&A!==R;if(t||!f.has(_)||I)process.env[_]=A,u++,m++}if(!o&&!process.env.__ENV_LOADED__)console.error(`[env] loaded ${m}/${Object.keys(v).length} variables from ${g}`),process.env.__ENV_LOADED__="1"}catch(y){a.push(`Failed to load ${l}: ${y instanceof Error?y.message:"Unknown error"}`)}}return{loaded:u,errors:a}}function tn(e={}){return{name:"env-plugin",setup(n){_e(e)}}}function Yn(e={}){let n=K(e.env)||K("development")||K(process.env.DOTENV_ENV)||K(process.env.APP_ENV)||"development",t=e.cwd||process.cwd();if(W!==n)W=n,F=null,Y=void 0;let r=[],i=(d)=>{if(!r.includes(d)&&V(M(t,d)))r.push(d)};i(".env"),i(".env.local");let s=`.env.${n}`,o=`.env.${n}.local`;return i(s),i(o),_e({...e,path:r,env:n})}var Gn=tn;
|
|
5
|
-
`)){let i=r.trim();if(!i||i.startsWith("#"))continue;if(i.startsWith("DOTENV_PUBLIC_KEY"))continue;let s=i.match(/^([^=]+)=(.*)$/);if(!s||s[1]===void 0)continue;let o=s[1].trim();if(
|
|
6
|
-
`)){let d=o.trim();if(d.startsWith("#/"))continue;if(d.startsWith("DOTENV_PUBLIC_KEY"))continue;if(!d&&!s)continue;if(!d||d.startsWith("#")){s=!0,i.push(o);continue}s=!0;let c=d.match(/^([^=]+)=(.*)$/);if(!c||c[1]===void 0||c[2]===void 0){i.push(o);continue}let a=c[1].trim(),u=c[2].trim();if(u.startsWith('"')&&u.endsWith('"')||u.startsWith("'")&&u.endsWith("'"))u=u.slice(1,-1);if(
|
|
7
|
-
`)}function k(e){let t=((e||".env").split("/").pop()||"").replace(/^\.env\./,"").replace(/^\.env$/,"").toUpperCase();return{publicKeyName:t?`DOTENV_PUBLIC_KEY_${t}`:"DOTENV_PUBLIC_KEY",privateKeyName:t?`DOTENV_PRIVATE_KEY_${t}`:"DOTENV_PRIVATE_KEY"}}function
|
|
8
|
-
`)){let t=n.trim();if(!t||t.startsWith("#"))continue;let r=t.match(/^([^=]+)=(.*)$/);if(!r?.[1]||r[2]===void 0)continue;let i=r[2].trim().replace(/^["']|["']$/g,"");if(i.startsWith("encrypted:")||i.startsWith("enc:"))return!0}return!1}function sn(e,n){let t=
|
|
4
|
+
`)}if(u.startsWith("encrypted:")||u.startsWith("enc:")){if(!n.privateKey){i.push(a);continue}try{let f=u.startsWith("enc:")?`encrypted:${u.slice(4)}`:u;u=L(f,n.privateKey)}catch(f){r.push(`Failed to decrypt ${a}: ${f instanceof Error?f.message:"Unknown error"}`)}}u=Qe(u,{...n.processEnv||process.env,...t}),u=Ze(u),t[a]=u}return{parsed:t,errors:r,skippedEncrypted:i}}function Qe(e,n){return e.replace(/\$\{([^}]+)\}/g,(t,r)=>{let i=r.match(/^([^:\-+]+)(:-|-)(.+)$/);if(i){let[,o,d,c]=i,a=n[o];if(d===":-")return a||c;else return a!==void 0?a:c}let s=r.match(/^([^:\-+]+)(:?\+)(.+)$/);if(s){let[,o,d,c]=s,a=n[o];if(d===":+")return a?c:"";else return a!==void 0?c:""}return n[r]||""})}var qe=new Set(["date","hostname","whoami","uname","pwd","echo","printf","cat","basename","dirname"]);function ze(e){let n=[],t="",r=null,i=!1;for(let s of e.trim()){if(i){t+=s,i=!1;continue}if(s==="\\"&&r!=="'"){i=!0;continue}if(r){if(s===r)r=null;else t+=s;continue}if(s==='"'||s==="'"){r=s;continue}if(/\s/.test(s)){if(t)n.push(t),t="";continue}t+=s}if(i||r)throw Error("Command substitution contains an unterminated escape or quote");if(t)n.push(t);return n}function Je(e){let[n,...t]=e,r=t.some((i)=>i.startsWith("-"));if(n==="echo"&&!r)return t.join(" ");if(n==="printf"&&t.length===1&&!t[0]?.includes("%"))return t[0];if(n==="hostname"&&t.length===0)return Ye();if(n==="whoami"&&t.length===0)return Ge().username;if(n==="pwd"&&t.length===0)return process.cwd();if(n==="basename"&&t.length===1)return He(t[0]??"");if(n==="dirname"&&t.length===1)return je(t[0]??"");if(n==="cat"&&t.length>0&&!r)return t.map((i)=>Me(Xe(process.cwd(),i),"utf8")).join("");if(n==="uname"){let i=t[0]??"-s";if(t.length<=1&&i==="-m")return Fe();if(t.length<=1&&i==="-r")return We();if(t.length<=1&&i==="-s")return{aix:"AIX",android:"Android",cygwin:"CYGWIN",darwin:"Darwin",freebsd:"FreeBSD",haiku:"Haiku",linux:"Linux",netbsd:"NetBSD",openbsd:"OpenBSD",sunos:"SunOS",win32:"Windows_NT"}[pe()]??pe()}return}function Ze(e){return e.replace(/\$\(([^)]+)\)/g,(n,t)=>{try{let r=ze(t),i=r[0];if(!i||!qe.has(i))return console.warn(`[env] Blocked command substitution for disallowed command: ${i}`),"";let s=Je(r);if(s!==void 0)return s.trim();let o=Ve(i,r.slice(1),{encoding:"utf8",env:process.env});if(o.status===0)return o.stdout.trim();let d=o.stderr.trim();console.warn(`[env] Command substitution failed (exit code ${o.status??"unknown"}): ${i}${d?`: ${d}`:""}`)}catch(r){console.warn(`[env] Command substitution error: ${r instanceof Error?r.message:String(r)}`)}return""})}async function Un(e,n={}){let t={},r=[],i=[];for(let s of e)try{let o=Bun.file(s);if(!o.size)continue;let d=await o.text(),{parsed:c,errors:a,skippedEncrypted:u}=h(d,n);r.push(...a),i.push(...u);for(let[f,E]of Object.entries(c)){if(!n.overload&&t[f]!==void 0)continue;t[f]=E}}catch(o){if(o?.code==="ENOENT")continue;r.push(`Failed to read ${s}: ${o instanceof Error?o.message:String(o)}`)}return{parsed:t,errors:r,skippedEncrypted:i}}import{existsSync as V}from"fs";import{readFileSync as J}from"fs";import{resolve as M}from"path";function x(e){return typeof e==="string"&&(e.startsWith("encrypted:")||e.startsWith("enc:"))}function K(e){if(!e||x(e))return;let n=e.trim().toLowerCase();if(!/^[a-z0-9_-]+$/.test(n))return;if(n==="prod")return"production";if(n==="stage")return"staging";if(n==="dev")return"development";return n}var F=null,Y,W;function en(e,n,t=".env.keys"){let r=M(n,t);if(!V(r))return;try{let{parsed:i}=h(J(r,"utf-8"));if(e){let s=i[`DOTENV_PRIVATE_KEY_${e.toUpperCase()}`];if(s)return s}return i.DOTENV_PRIVATE_KEY}catch{return}}function Z(e={}){return K(e.env)||W||K("development")||K(process.env.DOTENV_ENV)||K(process.env.APP_ENV)||"development"}function nn(e={}){let n=Z(e),t=e.cwd||process.cwd();if(F===n)return Y;let r=z(n);if(!r)r=process.env.DOTENV_PRIVATE_KEY;if(!r)r=en(n,t);return F=n,Y=r,r}function Fn(){F=null,Y=void 0,W=void 0}function ge(e,n={}){if(!x(e))return e;let t=nn(n);if(!t)return;try{let r=e.startsWith("enc:")?`encrypted:${e.slice(4)}`:e;return L(r,t)}catch{return}}function _e(e={}){let{path:n=[".env"],overload:t=!1,env:r,privateKey:i,keysFile:s=".env.keys",quiet:o=!1,cwd:d=process.cwd()}=e,c=Array.isArray(n)?n:[n],a=[],u=0,f=new Set(Object.entries(process.env).filter(([,g])=>g!==void 0&&!x(g)).map(([g])=>g)),E=i;if(!E&&s){let g=M(d,s);if(V(g))try{let l=J(g,"utf-8"),{parsed:y}=h(l);if(r){let v=`DOTENV_PRIVATE_KEY_${r.toUpperCase()}`;E=y[v]}else E=y.DOTENV_PRIVATE_KEY}catch(l){a.push(`Failed to load keys file: ${l instanceof Error?l.message:"Unknown error"}`)}}if(!E)E=z(r||"");for(let g of c){let l=M(d,g);if(!V(l)){if(!o)a.push(`File not found: ${l}`);continue}try{let y=J(l,"utf-8"),{parsed:v,errors:T,skippedEncrypted:O}=h(y,{privateKey:E,processEnv:process.env});if(a.push(...T),O.length>0){for(let I of O)if(x(process.env[I]))delete process.env[I];let _=r?`DOTENV_PRIVATE_KEY_${r.toUpperCase()}`:"DOTENV_PRIVATE_KEY",A=O.slice(0,5).join(", "),R=O.length>5?`, \u2026 +${O.length-5} more`:"";console.warn(`[env] warning: skipped ${O.length} encrypted value(s) in ${g} (${_} not set; defaults apply): ${A}${R}`)}let m=0;for(let[_,A]of Object.entries(v)){if(_==="DOTENV_PUBLIC_KEY")continue;let R=process.env[_],I=x(R)&&A!==R;if(t||!f.has(_)||I)process.env[_]=A,u++,m++}if(!o&&!process.env.__ENV_LOADED__)console.error(`[env] loaded ${m}/${Object.keys(v).length} variables from ${g}`),process.env.__ENV_LOADED__="1"}catch(y){a.push(`Failed to load ${l}: ${y instanceof Error?y.message:"Unknown error"}`)}}return{loaded:u,errors:a}}function tn(e={}){return{name:"env-plugin",setup(n){_e(e)}}}function Yn(e={}){let n=K(e.env)||K("development")||K(process.env.DOTENV_ENV)||K(process.env.APP_ENV)||"development",t=e.cwd||process.cwd();if(W!==n)W=n,F=null,Y=void 0;let r=[],i=(d)=>{if(!r.includes(d)&&V(M(t,d)))r.push(d)};i(".env"),i(".env.local");let s=`.env.${n}`,o=`.env.${n}.local`;return i(s),i(o),_e({...e,path:r,env:n})}var Gn=tn;import{existsSync as P,readFileSync as N,renameSync as ye,rmSync as Te,writeFileSync as D}from"fs";import{basename as me,dirname as ne,resolve as S}from"path";function qn(e,n){if(e)return e;let t=String(n??"").trim();if(!t||t==="development"||t==="dev"||t==="local")return"";if(!/^[\w.-]+$/.test(t))return"";return`.env.${t}`}function ve(e,n){return(!n.key||e.includes(n.key))&&(!n.excludeKey||!e.includes(n.excludeKey))}function rn(e,n){let t=[];for(let r of e.split(`
|
|
5
|
+
`)){let i=r.trim();if(!i||i.startsWith("#"))continue;if(i.startsWith("DOTENV_PUBLIC_KEY"))continue;let s=i.match(/^([^=]+)=(.*)$/);if(!s||s[1]===void 0)continue;let o=s[1].trim();if(ve(o,n))t.push(o)}return t}function Oe(e,n,t,r){let i=["#/-------------------[DOTENV_PUBLIC_KEY]--------------------/","#/ versioned X25519 encryption for .env files /","#/ [how it works](https://stacksjs.com/encryption) /","#/----------------------------------------------------------/",`${t}="${n}"`,""],s=!1;for(let o of e.split(`
|
|
6
|
+
`)){let d=o.trim();if(d.startsWith("#/"))continue;if(d.startsWith("DOTENV_PUBLIC_KEY"))continue;if(!d&&!s)continue;if(!d||d.startsWith("#")){s=!0,i.push(o);continue}s=!0;let c=d.match(/^([^=]+)=(.*)$/);if(!c||c[1]===void 0||c[2]===void 0){i.push(o);continue}let a=c[1].trim(),u=c[2].trim();if(u.startsWith('"')&&u.endsWith('"')||u.startsWith("'")&&u.endsWith("'"))u=u.slice(1,-1);if(ve(a,r)&&!u.startsWith("encrypted:"))u=B(u,n);i.push(`${a}="${u}"`)}return i.join(`
|
|
7
|
+
`)}function k(e){let t=((e||".env").split("/").pop()||"").replace(/^\.env\./,"").replace(/^\.env$/,"").toUpperCase();return{publicKeyName:t?`DOTENV_PUBLIC_KEY_${t}`:"DOTENV_PUBLIC_KEY",privateKeyName:t?`DOTENV_PRIVATE_KEY_${t}`:"DOTENV_PRIVATE_KEY"}}function Ae(e){let{publicKeyName:n}=k(e);return n==="DOTENV_PUBLIC_KEY"?[n]:[n,"DOTENV_PUBLIC_KEY"]}function ee(e){let{privateKeyName:n}=k(e);return n==="DOTENV_PRIVATE_KEY"?[n]:[n,"DOTENV_PRIVATE_KEY"]}function Re(e){for(let n of e.split(`
|
|
8
|
+
`)){let t=n.trim();if(!t||t.startsWith("#"))continue;let r=t.match(/^([^=]+)=(.*)$/);if(!r?.[1]||r[2]===void 0)continue;let i=r[2].trim().replace(/^["']|["']$/g,"");if(i.startsWith("encrypted:")||i.startsWith("enc:"))return!0}return!1}function sn(e,n){let t=Ae(n);for(let r of e.split(`
|
|
9
9
|
`)){let i=r.trim();if(!i||i.startsWith("#"))continue;let s=i.match(/^([^=]+)=["']?([^"'\n]+)["']?/);if(!s?.[1]||!s[2])continue;let o=s[1].trim();if(t.includes(o))return{name:o,key:s[2]}}return}function on(e,n){let t,r=!1;for(let i of e.split(`
|
|
10
|
-
`)){let s=i.trim();if(!s||s.startsWith("#"))continue;let o=s.match(/^([^=]+)=(.*)$/);if(!o?.[1]||o[2]===void 0)continue;let d=o[1].trim(),c=o[2].trim().replace(/^["']|["']$/g,"");if(d===n)t=c;else if(c.startsWith("encrypted:")||c.startsWith("enc:"))r=!0}return t&&r?t:void 0}function
|
|
10
|
+
`)){let s=i.trim();if(!s||s.startsWith("#"))continue;let o=s.match(/^([^=]+)=(.*)$/);if(!o?.[1]||o[2]===void 0)continue;let d=o[1].trim(),c=o[2].trim().replace(/^["']|["']$/g,"");if(d===n)t=c;else if(c.startsWith("encrypted:")||c.startsWith("enc:"))r=!0}return t&&r?t:void 0}function zn(e={}){let n=e.cwd||process.cwd(),t=S(n,e.file||".env"),r=S(n,e.keysFile||".env.keys");if(!P(t))return{success:!1,error:`File not found: ${t}`};try{let i,s,o=on(N(t,"utf-8"),k(e.file).publicKeyName);if(o)i=o;else if(P(r)){let a=N(r,"utf-8"),{parsed:u}=h(a),{publicKeyName:f,privateKeyName:E}=k(e.file);if(i=u[f]||"",s=u[E]||"",!i||!s){let g=U();i=g.publicKey,s=g.privateKey;let l=`
|
|
11
11
|
${f}="${i}"
|
|
12
12
|
${E}="${s}"
|
|
13
13
|
`;D(r,a+l,"utf-8")}}else{let a=U();i=a.publicKey,s=a.privateKey;let{publicKeyName:u,privateKeyName:f}=k(e.file),E=`# .env.keys - Keep this file secure and never commit to source control
|
|
14
14
|
${u}="${i}"
|
|
15
15
|
${f}="${s}"
|
|
16
|
-
`;D(r,E,"utf-8")}let d=N(t,"utf-8"),c=
|
|
16
|
+
`;D(r,E,"utf-8")}let d=N(t,"utf-8"),c=Oe(d,i,k(e.file).publicKeyName,e);if(e.stdout)return{success:!0,output:c};return D(t,c,"utf-8"),{success:!0,output:`\u2714 encrypted (${e.file||".env"})
|
|
17
17
|
\u2714 key added to ${e.keysFile||".env.keys"}`}}catch(i){return{success:!1,error:`Failed to encrypt: ${i instanceof Error?i.message:"Unknown error"}`}}}function dn(e={}){let n=e.cwd||process.cwd(),t=S(n,e.file||".env"),r=S(n,e.keysFile||".env.keys");if(!P(t))return{success:!1,error:`File not found: ${t}`};if(!P(r))return{success:!1,error:`Keys file not found: ${r}`};try{let i=N(r,"utf-8"),{parsed:s}=h(i),c=((e.file||".env").split("/").pop()||"").replace(/^\.env\./,"").replace(/^\.env$/,"").toUpperCase(),a=c?`DOTENV_PRIVATE_KEY_${c}`:"DOTENV_PRIVATE_KEY",u=s[a];if(!u)return{success:!1,error:`Private key not found: ${a}`};let f=[u];if(a!=="DOTENV_PRIVATE_KEY"&&s.DOTENV_PRIVATE_KEY&&s.DOTENV_PRIVATE_KEY!==u)f.push(s.DOTENV_PRIVATE_KEY);let g=N(t,"utf-8").split(`
|
|
18
18
|
`),l=[];for(let v of g){let T=v.trim();if(!T||T.startsWith("#")){l.push(v);continue}if(T.startsWith("DOTENV_PUBLIC_KEY"))continue;let O=T.match(/^([^=]+)=(.*)$/);if(!O||O[1]===void 0||O[2]===void 0){l.push(v);continue}let m=O[1].trim(),_=O[2].trim();if(_.startsWith('"')&&_.endsWith('"')||_.startsWith("'")&&_.endsWith("'"))_=_.slice(1,-1);let A=_.startsWith("encrypted:");if(e.key&&!m.includes(e.key))A=!1;if(A){let R,I;for(let G of f)try{R=L(_,G);break}catch(Ke){I=Ke}if(R===void 0)throw I instanceof Error?I:Error(`Unable to decrypt ${m}`);_=R}l.push(`${m}="${_}"`)}let y=l.join(`
|
|
19
|
-
`);if(e.stdout)return{success:!0,output:y};return D(t,y,"utf-8"),{success:!0,output:`\u2714 decrypted (${e.file||".env"})`}}catch(i){return{success:!1,error:`Failed to decrypt: ${i instanceof Error?i.message:"Unknown error"}`}}}function
|
|
20
|
-
`),c=!1,a,E=((t.file||".env").split("/").pop()||"").replace(/^\.env\./,"").replace(/^\.env$/,"").toUpperCase(),g=E?`DOTENV_PUBLIC_KEY_${E}`:"DOTENV_PUBLIC_KEY",l=E?`DOTENV_PRIVATE_KEY_${E}`:"DOTENV_PRIVATE_KEY",y=sn(o,t.file),v=y?.name??g;if(a=y?.key,a){let m=!1;if(P(s)){let A=N(s,"utf-8"),{parsed:R}=h(A);m=ee(t.file).some((I)=>Boolean(R[I]))}let _=ee(t.file).some((A)=>Boolean(process.env[A]));if(!m&&!_&&!
|
|
19
|
+
`);if(e.stdout)return{success:!0,output:y};return D(t,y,"utf-8"),{success:!0,output:`\u2714 decrypted (${e.file||".env"})`}}catch(i){return{success:!1,error:`Failed to decrypt: ${i instanceof Error?i.message:"Unknown error"}`}}}function Jn(e,n,t={}){let r=t.cwd||process.cwd(),i=S(r,t.file||".env"),s=t.keysFile?S(r,t.keysFile):S(ne(i),".env.keys");try{let o="";if(P(i))o=N(i,"utf-8");let d=o.split(`
|
|
20
|
+
`),c=!1,a,E=((t.file||".env").split("/").pop()||"").replace(/^\.env\./,"").replace(/^\.env$/,"").toUpperCase(),g=E?`DOTENV_PUBLIC_KEY_${E}`:"DOTENV_PUBLIC_KEY",l=E?`DOTENV_PRIVATE_KEY_${E}`:"DOTENV_PRIVATE_KEY",y=sn(o,t.file),v=y?.name??g;if(a=y?.key,a){let m=!1;if(P(s)){let A=N(s,"utf-8"),{parsed:R}=h(A);m=ee(t.file).some((I)=>Boolean(R[I]))}let _=ee(t.file).some((A)=>Boolean(process.env[A]));if(!m&&!_&&!Re(o))a=void 0}if(!t.plain&&!a&&Re(o))return{success:!1,error:`${t.file||".env"} already contains encrypted values, but no key that can be used to add another was found.
|
|
21
21
|
Generating one would leave every existing encrypted value unreadable.
|
|
22
22
|
Provide the private key as ${ee(t.file)[0]} in the environment, restore ${s}, or use --plain to write this value unencrypted.`};if(!t.plain&&!a){let m=U();a=m.publicKey;let _="";if(P(s))_=N(s,"utf-8");_+=`
|
|
23
23
|
${g}="${m.publicKey}"
|
|
24
24
|
${l}="${m.privateKey}"
|
|
25
|
-
`,D(s,_,"utf-8");let A=
|
|
26
|
-
`);return D(i,O,"utf-8"),{success:!0,output:`set ${e}${t.plain?"":" with encryption"} (${t.file||".env"})`}}catch(o){return{success:!1,error:`Failed to set: ${o instanceof Error?o.message:"Unknown error"}`}}}function
|
|
27
|
-
`);break;case"json":default:g=n.prettyPrint?JSON.stringify(E,null,2):JSON.stringify(E);break}return{success:!0,output:g}}catch(i){return{success:!1,error:`Failed to get: ${i instanceof Error?i.message:"Unknown error"}`}}}function
|
|
25
|
+
`,D(s,_,"utf-8");let A=Ae(t.file);for(let R=d.length-1;R>=0;R--){let I=d[R];if(I!==void 0&&A.some((G)=>I.trim().startsWith(`${G}=`)))d.splice(R,1)}d.unshift(`${v}="${a}"`)}let T=n;if(!t.plain&&a)T=B(n,a);for(let m=0;m<d.length;m++){let _=d[m];if(_===void 0)continue;if(_.trim().startsWith(`${e}=`)){d[m]=`${e}="${T}"`,c=!0;break}}if(!c)d.push(`${e}="${T}"`);let O=d.join(`
|
|
26
|
+
`);return D(i,O,"utf-8"),{success:!0,output:`set ${e}${t.plain?"":" with encryption"} (${t.file||".env"})`}}catch(o){return{success:!1,error:`Failed to set: ${o instanceof Error?o.message:"Unknown error"}`}}}function Zn(e,n={}){let t=n.cwd||process.cwd(),r=S(t,n.file||".env");if(!P(r))return{success:!1,error:`File not found: ${r}`};try{let i,s=S(t,n.keysFile||".env.keys"),c=((n.file||".env").split("/").pop()||"").replace(/^\.env\./,"").replace(/^\.env$/,"").toUpperCase(),a=c?`DOTENV_PRIVATE_KEY_${c}`:"DOTENV_PRIVATE_KEY";if(P(s)){let l=N(s,"utf-8"),{parsed:y}=h(l);i=y[a]}if(!i)i=process.env[a];let u=N(r,"utf-8"),{parsed:f}=h(u,{privateKey:i});if(e&&!n.all){let l=f[e];if(l===void 0)return{success:!1,error:`Key not found: ${e}`};return{success:!0,output:l}}let E=n.all?{...process.env,...f}:f,g;switch(n.format){case"shell":g=Object.entries(E).map(([l,y])=>`${l}=${y}`).join(" ");break;case"eval":g=Object.entries(E).map(([l,y])=>`${l}="${y}"`).join(`
|
|
27
|
+
`);break;case"json":default:g=n.prettyPrint?JSON.stringify(E,null,2):JSON.stringify(E);break}return{success:!0,output:g}}catch(i){return{success:!1,error:`Failed to get: ${i instanceof Error?i.message:"Unknown error"}`}}}function et(e,n={}){let t=n.cwd||process.cwd(),r=S(t,n.keysFile||".env.keys");if(!P(r))return{success:!1,error:`Keys file not found: ${r}`};try{let i=N(r,"utf-8"),{parsed:s}=h(i),c=((n.file||".env").split("/").pop()||"").replace(/^\.env\./,"").replace(/^\.env$/,"").toUpperCase(),a=c?`DOTENV_PUBLIC_KEY_${c}`:"DOTENV_PUBLIC_KEY",u=c?`DOTENV_PRIVATE_KEY_${c}`:"DOTENV_PRIVATE_KEY";if(e){let g=s[e];if(!g)return{success:!1,error:`Key not found: ${e}`};return{success:!0,output:g}}let f={[a]:s[a],[u]:s[u]};return{success:!0,output:n.format==="shell"?`${a}=${f[a]} ${u}=${f[u]}`:JSON.stringify(f)}}catch(i){return{success:!1,error:`Failed to get keypair: ${i instanceof Error?i.message:"Unknown error"}`}}}function cn(e,n,t,r){let i=e.split(`
|
|
28
28
|
`),s=!1,o=!1;for(let d=0;d<i.length;d++){let c=i[d];if(c===void 0)continue;if(c.startsWith(`${t}=`))i[d]=`${t}="${n.publicKey}"`,s=!0;else if(c.startsWith(`${r}=`))i[d]=`${r}="${n.privateKey}"`,o=!0}if(!s)i.push(`${t}="${n.publicKey}"`);if(!o)i.push(`${r}="${n.privateKey}"`);return`${i.join(`
|
|
29
29
|
`).replace(/\n+$/,"")}
|
|
30
|
-
`}function
|
|
31
|
-
`)}}let a=U(),u=
|
|
32
|
-
`)};let f=N(s),E=N(o),g=cn(E.toString("utf8"),a,d,c),l=`${process.pid}-${Date.now()}`,y=S(ne(s),`.${
|
|
33
|
-
`).map((n)=>n.trim()).filter(Boolean).filter((n)=>n!==".env.example").filter((n)=>/(?:^|\/)\.env(?:\.|$)/.test(n)).filter((n)=>!n.endsWith(".env.keys"))}function
|
|
30
|
+
`}function nt(e={}){let n=dn({file:e.file,keysFile:e.keysFile,stdout:!0,cwd:e.cwd});if(!n.success)return n;if(n.output===void 0)return{success:!1,error:"Rotation produced no decrypted content"};let t=e.cwd||process.cwd(),r=e.file||".env",i=e.keysFile||".env.keys",s=S(t,r),o=S(t,i),{publicKeyName:d,privateKeyName:c}=k(e.file);if(e.dryRun){let T=rn(n.output,e);return{success:!0,output:["Dry run: nothing was written.",`${r}: ${T.length} value${T.length===1?"":"s"} would be re-encrypted under a new ${d}.`,`${i}: ${d} and ${c} would be replaced.`,`The current ${c} decrypts nothing once that happens, so keep a copy until the rotation is verified.`].join(`
|
|
31
|
+
`)}}let a=U(),u=Oe(n.output,a.publicKey,d,e);if(e.stdout)return{success:!0,output:u,notice:[`Nothing was written. To adopt the output above, put this keypair in ${i}:`,"",`${d}="${a.publicKey}"`,`${c}="${a.privateKey}"`,"","Without it that output cannot be decrypted. Run without --stdout to have both applied together."].join(`
|
|
32
|
+
`)};let f=N(s),E=N(o),g=cn(E.toString("utf8"),a,d,c),l=`${process.pid}-${Date.now()}`,y=S(ne(s),`.${me(s)}.${l}.rotate`),v=S(ne(o),`.${me(o)}.${l}.rotate`);try{D(y,u,{encoding:"utf8",mode:384}),D(v,g,{encoding:"utf8",mode:384}),ye(y,s);try{ye(v,o)}catch(T){throw D(s,f),T}return{success:!0,output:`\u2714 rotated (${r}) to encrypted:v2`}}catch(T){if(!P(o))D(o,E,{mode:384});return{success:!1,error:`Failed to rotate without exposing plaintext: ${T instanceof Error?T.message:"Unknown error"}`}}finally{Te(y,{force:!0}),Te(v,{force:!0})}}import p from"process";import{platform as an}from"os";var Se=typeof Bun<"u",Ie=typeof p<"u"&&p.versions?.node!==void 0,un=Se?"bun":Ie?"node":"unknown",st={name:un,version:Se?Bun.version:Ie?p.version:void 0},re=an(),ot=re==="win32",dt=re==="darwin",ct=re==="linux",Ne=Boolean(p.stdout?.isTTY),at=typeof globalThis.window<"u",fn=Boolean(p.env.CI||p.env.CONTINUOUS_INTEGRATION||p.env.BUILD_NUMBER||p.env.RUN_ID),ut=Boolean(p.env.DEBUG||p.env.VERBOSE||p.argv.includes("--debug")||p.argv.includes("--verbose")),En=fn||!Ne,ft=Boolean(!En&&(Ne||p.env.COLORTERM||p.env.FORCE_COLOR||p.env.TERM&&p.env.TERM!=="dumb")),te={github:{name:"GitHub Actions",detected:Boolean(p.env.GITHUB_ACTIONS)},gitlab:{name:"GitLab CI",detected:Boolean(p.env.GITLAB_CI)},circle:{name:"CircleCI",detected:Boolean(p.env.CIRCLECI)},travis:{name:"Travis CI",detected:Boolean(p.env.TRAVIS)},jenkins:{name:"Jenkins",detected:Boolean(p.env.JENKINS_URL)},vercel:{name:"Vercel",detected:Boolean(p.env.VERCEL)},netlify:{name:"Netlify",detected:Boolean(p.env.NETLIFY)},heroku:{name:"Heroku",detected:Boolean(p.env.DYNO)},aws:{name:"AWS",detected:Boolean(p.env.AWS_REGION||p.env.AWS_LAMBDA_FUNCTION_NAME)},azure:{name:"Azure",detected:Boolean(p.env.AZURE_HTTP_USER_AGENT)},cloudflare:{name:"Cloudflare",detected:Boolean(p.env.CF_PAGES)},railway:{name:"Railway",detected:Boolean(p.env.RAILWAY_ENVIRONMENT)},render:{name:"Render",detected:Boolean(p.env.RENDER)}},ln=Object.keys(te).find((e)=>{let n=te[e];return n!==void 0&&n.detected})||"unknown",Et=te[ln]||{name:"Unknown",detected:!1};import mn from"process";import{projectPath as Rn}from"@stacksjs/path";import De from"fs";var he={APP_ENV:["local","dev","development","staging","prod","production"],DB_CONNECTION:["mysql","sqlite","postgres","singlestore","vitess","dynamodb"],DB_MIGRATE_FRESH:["allow","confirm","disabled"],MAIL_MAILER:["smtp","mailgun","ses","log","sendgrid","mailtrap","capture"],SEARCH_ENGINE_DRIVER:["opensearch","meilisearch","algolia","typesense"],FRONTEND_APP_ENV:["development","staging","production"]};function pt(e){return e}function pn(e){return typeof e==="string"&&(e.startsWith("encrypted:")||e.startsWith("enc:"))}var gn=/(?:^|_)(?:PASSWORD|PASSWD|SECRET|TOKEN|APIKEY|API_KEY|CREDENTIAL|CREDENTIALS|PRIVATE|SALT|DSN|CERT|CIPHER|SIGNATURE|WEBHOOK)(?:_|$)|(?:^|_)(?:ACCESS|SECRET)_KEY(?:_|$)|_KEY$/,_n=/^DOTENV_(?:PUBLIC|PRIVATE)_KEY/,yn=/^\$\{[^}]+\}$/;function _t(e,n={}){let{placeholders:t={},strict:r=!1}=n,i=[];for(let[s,o]of Object.entries(e)){if(!o||o.trim()==="")continue;if(pn(o))continue;if(_n.test(s))continue;if(yn.test(o.trim()))continue;let d=gn.test(s),c=Object.prototype.hasOwnProperty.call(t,s)&&t[s]===o;if(d&&!c){i.push({key:s,reason:"plaintext-secret"});continue}if(r)i.push({key:s,reason:"plaintext-value"})}return i}function yt(e){return e.split(`
|
|
33
|
+
`).map((n)=>n.trim()).filter(Boolean).filter((n)=>n!==".env.example").filter((n)=>/(?:^|\/)\.env(?:\.|$)/.test(n)).filter((n)=>!n.endsWith(".env.keys"))}function Pe(e){return`${e.replace(/[^a-z0-9]/gi,"").toUpperCase()}_`}function Tn(e,n={}){let t=n.self?Pe(n.self):void 0,r=(n.tenants??[]).filter((o)=>typeof o==="string"&&o.trim().length>0).map((o)=>({slug:o,prefix:Pe(o)})).filter(({prefix:o})=>o!==t).sort((o,d)=>d.prefix.length-o.prefix.length),i={},s={};for(let[o,d]of Object.entries(e)){let c=r.find(({prefix:a})=>o.startsWith(a));if(c){(s[c.slug]??={})[o]=d;continue}i[o]=d}return{own:i,foreign:s}}function mt(e,n={}){return Tn(e,n).own}function Rt(e){return Object.entries(e.foreign).map(([n,t])=>({tenant:n,keys:Object.keys(t).sort()})).sort((n,t)=>n.tenant.localeCompare(t.tenant))}var Ce=new Set;function vn(e){if(Ce.has(e))return;Ce.add(e);let n=Z();console.warn(`[env] warning: "${e}" is encrypted but no usable private key was found for the "${n}" environment; falling back to its default. Set DOTENV_PRIVATE_KEY_${n.toUpperCase()} or ship .env.keys.`)}var On={get:(e,n)=>{let t=e,r=t[n];if(typeof r==="string"&&(r.startsWith("encrypted:")||r.startsWith("enc:"))){let s=ge(r);if(s===void 0){vn(n),delete t[n];return}t[n]=s,r=s}let i=["_PORT","_TIMEOUT","_TTL","_SIZE","_LIMIT","_MAX","_MIN","_INTERVAL","_RETRIES","_CONCURRENCY","_WORKERS","_CONNECTIONS"];if(typeof r==="string"&&/^\d+$/.test(r)&&!r.startsWith("0")&&i.some((s)=>n.endsWith(s)))return Number(r);if(typeof r==="string"){let s=r.toLowerCase();if(s==="true")return!0;if(s==="false")return!1}return r},set:(e,n,t)=>Reflect.set(e,n,t,e),deleteProperty:(e,n)=>Reflect.deleteProperty(e,n)};function An(){return typeof Bun<"u"?Bun.env:mn.env}var be=new Proxy(An(),On);function ht(e,n,t){let r=t?.path||Rn(".env"),s=De.readFileSync(r,"utf-8").split(`
|
|
34
34
|
`),o=s.findIndex((a)=>a.startsWith(`${e}=`)),c=/[\s"'#$\\]/.test(n)?`"${n.replace(/"/g,"\\\"")}"`:n;if(o!==-1)s[o]=`${e}=${c}`;else s.push(`${e}=${c}`);De.writeFileSync(r,s.join(`
|
|
35
|
-
`))}function Pt(e=be){let n=[],t=e;for(let[r,i]of Object.entries(
|
|
35
|
+
`))}function Pt(e=be){let n=[],t=e;for(let[r,i]of Object.entries(he)){let s=t[r];if(s!==void 0&&s!==""&&!i.includes(String(s)))n.push(`${r}="${s}" is not valid. Allowed values: ${i.join(", ")}`)}return n}function Dt(e,n=be){let t=[],r=n;for(let i of e){let s=r[i];if(s===void 0||s===""||s===null)t.push(i)}if(t.length>0)throw Error(`[env] Missing required environment variable(s): ${t.join(", ")}. Set them in .env or your process environment before booting.`);return n}export{gn as SECRET_NAME_PATTERN,Z as activeEnvName,ke as aesDecrypt,In as aesEncrypt,Yn as autoLoadEnv,sn as declaredEnvPublicKey,dn as decryptEnv,ge as decryptEnvValue,L as decryptValue,pt as defineEnv,zn as encryptEnv,B as encryptValue,be as env,he as envEnum,Re as envHasCiphertext,k as envKeyNames,tn as envPlugin,ee as envPrivateKeyNames,Ae as envPublicKeyNames,Rt as foreignTenantKeys,U as generateKeypair,Zn as getEnv,et as getKeypair,z as getPrivateKey,Ne as hasTTY,at as hasWindow,Se as isBun,fn as isCI,ft as isColorSupported,ut as isDebug,pn as isEncryptedValue,Nn as isLegacyEncryptedValue,ct as isLinux,dt as isMacOS,En as isMinimal,Ie as isNode,ot as isWindows,_e as loadEnv,Un as loadEnvFiles,hn as migrateEncryptedValue,h as parse,Pn as parseEnvFromKey,Tn as partitionTenantEnv,_t as plaintextSecrets,re as platform,An as process,ln as provider,Et as providerInfo,Dt as requireEnv,Fn as resetPrivateKeyCache,qn as resolveEnvFile,nn as resolvePrivateKey,on as reusableEnvPublicKey,nt as rotateKeypair,un as runtime,st as runtimeInfo,Jn as setEnv,mt as stripForeignTenantEnv,Pe as tenantEnvPrefix,yt as trackedEnvFiles,Pt as validateEnv,ht as writeEnv};
|
package/dist/parser.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{
|
|
2
|
+
import{createCipheriv as k,createDecipheriv as b,createHash as m,createPrivateKey as T,createPublicKey as K,diffieHellman as B,generateKeyPairSync as P,hkdfSync as _,randomBytes as y}from"crypto";var E="x25519-public:",w="x25519-private:",g="encrypted:v2:",v="encrypted:",S=Buffer.from("stacks-env:v2","utf8"),R="Environment decryption failed: authentication or format error";function V(t){if(t.length===32)return t;return m("sha256").update(t).digest()}function ie(t,r){let e=y(16),n=k("aes-256-gcm",V(r),e);return{ciphertext:Buffer.concat([n.update(t,"utf8"),n.final()]).toString("hex"),iv:e.toString("hex"),authTag:n.getAuthTag().toString("hex")}}function D(t,r,e,n){try{let i=b("aes-256-gcm",V(r),Buffer.from(e,"hex"));return i.setAuthTag(Buffer.from(n,"hex")),Buffer.concat([i.update(Buffer.from(t,"hex")),i.final()]).toString("utf8")}catch{throw Error("Decryption failed: authentication or format error")}}function l(t){return t.toString("base64url")}function d(t,r,e){if(typeof t!=="string"||t.length>0&&!/^[A-Za-z0-9_-]+$/.test(t))throw Error(`${r} is not canonical base64url`);let n=Buffer.from(t,"base64url");if(l(n)!==t)throw Error(`${r} is not canonical base64url`);if(e!==void 0&&n.length!==e)throw Error(`${r} has an invalid length`);return n}function A(t){if(!t.startsWith(E))throw Error("Legacy or invalid public key. Run buddy env:rotate before creating new ciphertext.");let r=K({key:d(t.slice(E.length),"public key"),format:"der",type:"spki"});if(r.asymmetricKeyType!=="x25519")throw Error("Public key is not X25519");return r}function W(t){if(!t.startsWith(w))throw Error("Private key is not a version 2 X25519 key");let r=T({key:d(t.slice(w.length),"private key"),format:"der",type:"pkcs8"});if(r.asymmetricKeyType!=="x25519")throw Error("Private key is not X25519");return r}function N(t){return Buffer.from(`stacks-env:v2;${t.epk};${t.salt};${t.nonce}`,"utf8")}function se(){let{publicKey:t,privateKey:r}=P("x25519"),e=t.export({format:"der",type:"spki"}),n=r.export({format:"der",type:"pkcs8"});return{publicKey:`${E}${l(e)}`,privateKey:`${w}${l(n)}`}}function C(t,r){let e=A(r),n=P("x25519"),i=l(n.publicKey.export({format:"der",type:"spki"})),s=y(16),a=y(12),c=B({privateKey:n.privateKey,publicKey:e}),f=Buffer.from(_("sha256",c,s,S,32)),u={epk:i,salt:l(s),nonce:l(a)};try{let o=k("aes-256-gcm",f,a);o.setAAD(N(u));let p=Buffer.concat([o.update(t,"utf8"),o.final()]),h={v:2,...u,ciphertext:l(p),tag:l(o.getAuthTag())};return`${g}${l(Buffer.from(JSON.stringify(h),"utf8"))}`}finally{c.fill(0),f.fill(0)}}function I(t){let r=d(t.slice(g.length),"envelope").toString("utf8"),e=JSON.parse(r);if(!e||typeof e!=="object"||Array.isArray(e))throw Error("envelope is not an object");let n=Object.keys(e).sort(),i=["ciphertext","epk","nonce","salt","tag","v"];if(n.length!==i.length||n.some((s,a)=>s!==i[a]))throw Error("envelope fields are invalid");if(e.v!==2)throw Error("envelope version is unsupported");for(let s of["epk","salt","nonce","ciphertext","tag"])if(typeof e[s]!=="string")throw Error(`${s} is invalid`);return e}function F(t,r){try{let e=I(t),n=W(r),i=K({key:d(e.epk,"ephemeral public key"),format:"der",type:"spki"});if(i.asymmetricKeyType!=="x25519")throw Error("ephemeral key is not X25519");let s=d(e.salt,"salt",16),a=d(e.nonce,"nonce",12),c=d(e.ciphertext,"ciphertext"),f=d(e.tag,"tag",16),u=B({privateKey:n,publicKey:i}),o=Buffer.from(_("sha256",u,s,S,32));try{let p=b("aes-256-gcm",o,a);return p.setAAD(N(e)),p.setAuthTag(f),Buffer.concat([p.update(c),p.final()]).toString("utf8")}finally{u.fill(0),o.fill(0)}}catch{throw Error(R)}}function L(t,r){try{if(!/^[0-9a-f]{64}$/.test(r))throw Error("invalid legacy private key");let e=Buffer.from(t.slice(v.length),"base64");if(e.length<32)throw Error("invalid legacy payload");let n=m("sha256").update(Buffer.from(r,"hex")).digest(),i=m("sha256").update(n).digest();return D(e.subarray(32).toString("hex"),i,e.subarray(0,16).toString("hex"),e.subarray(16,32).toString("hex"))}catch{throw Error(R)}}function oe(t){return t.startsWith(v)&&!t.startsWith(g)}function x(t,r){if(!t.startsWith(v))return t;return t.startsWith(g)?F(t,r):L(t,r)}function ae(t,r,e){return C(x(t,r),e)}function ce(t){let r=t.match(/^DOTENV_PRIVATE_KEY_(.+)$/);return r&&r[1]?r[1].toLowerCase():""}function fe(t=""){return t?process.env[`DOTENV_PRIVATE_KEY_${t.toUpperCase()}`]:process.env.DOTENV_PRIVATE_KEY}import{spawnSync as Y}from"child_process";import{readFileSync as X}from"fs";import{arch as j,hostname as U,platform as O,release as H,userInfo as z}from"os";import{basename as M,dirname as q,resolve as G}from"path";function J(t,r={}){let e={},n=[],i=[],s=t.split(`
|
|
3
3
|
`);for(let a of s){let c=a.trim();if(!c||c.startsWith("#"))continue;if(c.startsWith("DOTENV_PUBLIC_KEY=")){let p=c.match(/^DOTENV_PUBLIC_KEY=["']?([^"'\n]+)["']?/);if(p&&p[1]!==void 0)e.DOTENV_PUBLIC_KEY=p[1];continue}let f=c.match(/^([^=]+)=(.*)$/);if(!f||f[1]===void 0||f[2]===void 0)continue;let u=f[1].trim(),o=f[2].trim();if(o.startsWith('"')&&o.endsWith('"')||o.startsWith("'")&&o.endsWith("'")){if(o=o.slice(1,-1),o.includes("\\n"))o=o.replace(/\\n/g,`
|
|
4
4
|
`)}if(o.startsWith("encrypted:")||o.startsWith("enc:")){if(!r.privateKey){i.push(u);continue}try{let p=o.startsWith("enc:")?`encrypted:${o.slice(4)}`:o;o=x(p,r.privateKey)}catch(p){n.push(`Failed to decrypt ${u}: ${p instanceof Error?p.message:"Unknown error"}`)}}o=Z(o,{...r.processEnv||process.env,...e}),o=re(o),e[u]=o}return{parsed:e,errors:n,skippedEncrypted:i}}function Z(t,r){return t.replace(/\$\{([^}]+)\}/g,(e,n)=>{let i=n.match(/^([^:\-+]+)(:-|-)(.+)$/);if(i){let[,a,c,f]=i,u=r[a];if(c===":-")return u||f;else return u!==void 0?u:f}let s=n.match(/^([^:\-+]+)(:?\+)(.+)$/);if(s){let[,a,c,f]=s,u=r[a];if(c===":+")return u?f:"";else return u!==void 0?f:""}return r[n]||""})}var Q=new Set(["date","hostname","whoami","uname","pwd","echo","printf","cat","basename","dirname"]);function ee(t){let r=[],e="",n=null,i=!1;for(let s of t.trim()){if(i){e+=s,i=!1;continue}if(s==="\\"&&n!=="'"){i=!0;continue}if(n){if(s===n)n=null;else e+=s;continue}if(s==='"'||s==="'"){n=s;continue}if(/\s/.test(s)){if(e)r.push(e),e="";continue}e+=s}if(i||n)throw Error("Command substitution contains an unterminated escape or quote");if(e)r.push(e);return r}function te(t){let[r,...e]=t,n=e.some((i)=>i.startsWith("-"));if(r==="echo"&&!n)return e.join(" ");if(r==="printf"&&e.length===1&&!e[0]?.includes("%"))return e[0];if(r==="hostname"&&e.length===0)return U();if(r==="whoami"&&e.length===0)return z().username;if(r==="pwd"&&e.length===0)return process.cwd();if(r==="basename"&&e.length===1)return M(e[0]??"");if(r==="dirname"&&e.length===1)return q(e[0]??"");if(r==="cat"&&e.length>0&&!n)return e.map((i)=>X(G(process.cwd(),i),"utf8")).join("");if(r==="uname"){let i=e[0]??"-s";if(e.length<=1&&i==="-m")return j();if(e.length<=1&&i==="-r")return H();if(e.length<=1&&i==="-s")return{aix:"AIX",android:"Android",cygwin:"CYGWIN",darwin:"Darwin",freebsd:"FreeBSD",haiku:"Haiku",linux:"Linux",netbsd:"NetBSD",openbsd:"OpenBSD",sunos:"SunOS",win32:"Windows_NT"}[O()]??O()}return}function re(t){return t.replace(/\$\(([^)]+)\)/g,(r,e)=>{try{let n=ee(e),i=n[0];if(!i||!Q.has(i))return console.warn(`[env] Blocked command substitution for disallowed command: ${i}`),"";let s=te(n);if(s!==void 0)return s.trim();let a=Y(i,n.slice(1),{encoding:"utf8",env:process.env});if(a.status===0)return a.stdout.trim();let c=a.stderr.trim();console.warn(`[env] Command substitution failed (exit code ${a.status??"unknown"}): ${i}${c?`: ${c}`:""}`)}catch(n){console.warn(`[env] Command substitution error: ${n instanceof Error?n.message:String(n)}`)}return""})}async function me(t,r={}){let e={},n=[],i=[];for(let s of t)try{let a=Bun.file(s);if(!a.size)continue;let c=await a.text(),{parsed:f,errors:u,skippedEncrypted:o}=J(c,r);n.push(...u),i.push(...o);for(let[p,h]of Object.entries(f)){if(!r.overload&&e[p]!==void 0)continue;e[p]=h}}catch(a){if(a?.code==="ENOENT")continue;n.push(`Failed to read ${s}: ${a instanceof Error?a.message:String(a)}`)}return{parsed:e,errors:n,skippedEncrypted:i}}export{me as loadEnvFiles,J as parse};
|
package/dist/plugin.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{
|
|
2
|
+
import{createCipheriv as U,createDecipheriv as j,createHash as R,createPrivateKey as ne,createPublicKey as X,diffieHellman as z,generateKeyPairSync as H,hkdfSync as q,randomBytes as S}from"crypto";var I="x25519-public:",C="x25519-private:",N="encrypted:v2:",F="encrypted:",M=Buffer.from("stacks-env:v2","utf8"),G="Environment decryption failed: authentication or format error";function J(e){if(e.length===32)return e;return R("sha256").update(e).digest()}function Ne(e,t){let n=S(16),r=U("aes-256-gcm",J(t),n);return{ciphertext:Buffer.concat([r.update(e,"utf8"),r.final()]).toString("hex"),iv:n.toString("hex"),authTag:r.getAuthTag().toString("hex")}}function re(e,t,n,r){try{let s=j("aes-256-gcm",J(t),Buffer.from(n,"hex"));return s.setAuthTag(Buffer.from(r,"hex")),Buffer.concat([s.update(Buffer.from(e,"hex")),s.final()]).toString("utf8")}catch{throw Error("Decryption failed: authentication or format error")}}function h(e){return e.toString("base64url")}function y(e,t,n){if(typeof e!=="string"||e.length>0&&!/^[A-Za-z0-9_-]+$/.test(e))throw Error(`${t} is not canonical base64url`);let r=Buffer.from(e,"base64url");if(h(r)!==e)throw Error(`${t} is not canonical base64url`);if(n!==void 0&&r.length!==n)throw Error(`${t} has an invalid length`);return r}function se(e){if(!e.startsWith(I))throw Error("Legacy or invalid public key. Run buddy env:rotate before creating new ciphertext.");let t=X({key:y(e.slice(I.length),"public key"),format:"der",type:"spki"});if(t.asymmetricKeyType!=="x25519")throw Error("Public key is not X25519");return t}function ie(e){if(!e.startsWith(C))throw Error("Private key is not a version 2 X25519 key");let t=ne({key:y(e.slice(C.length),"private key"),format:"der",type:"pkcs8"});if(t.asymmetricKeyType!=="x25519")throw Error("Private key is not X25519");return t}function Z(e){return Buffer.from(`stacks-env:v2;${e.epk};${e.salt};${e.nonce}`,"utf8")}function Oe(){let{publicKey:e,privateKey:t}=H("x25519"),n=e.export({format:"der",type:"spki"}),r=t.export({format:"der",type:"pkcs8"});return{publicKey:`${I}${h(n)}`,privateKey:`${C}${h(r)}`}}function oe(e,t){let n=se(t),r=H("x25519"),s=h(r.publicKey.export({format:"der",type:"spki"})),i=S(16),c=S(12),a=z({privateKey:r.privateKey,publicKey:n}),u=Buffer.from(q("sha256",a,i,M,32)),f={epk:s,salt:h(i),nonce:h(c)};try{let o=U("aes-256-gcm",u,c);o.setAAD(Z(f));let p=Buffer.concat([o.update(e,"utf8"),o.final()]),l={v:2,...f,ciphertext:h(p),tag:h(o.getAuthTag())};return`${N}${h(Buffer.from(JSON.stringify(l),"utf8"))}`}finally{a.fill(0),u.fill(0)}}function ce(e){let t=y(e.slice(N.length),"envelope").toString("utf8"),n=JSON.parse(t);if(!n||typeof n!=="object"||Array.isArray(n))throw Error("envelope is not an object");let r=Object.keys(n).sort(),s=["ciphertext","epk","nonce","salt","tag","v"];if(r.length!==s.length||r.some((i,c)=>i!==s[c]))throw Error("envelope fields are invalid");if(n.v!==2)throw Error("envelope version is unsupported");for(let i of["epk","salt","nonce","ciphertext","tag"])if(typeof n[i]!=="string")throw Error(`${i} is invalid`);return n}function ae(e,t){try{let n=ce(e),r=ie(t),s=X({key:y(n.epk,"ephemeral public key"),format:"der",type:"spki"});if(s.asymmetricKeyType!=="x25519")throw Error("ephemeral key is not X25519");let i=y(n.salt,"salt",16),c=y(n.nonce,"nonce",12),a=y(n.ciphertext,"ciphertext"),u=y(n.tag,"tag",16),f=z({privateKey:r,publicKey:s}),o=Buffer.from(q("sha256",f,i,M,32));try{let p=j("aes-256-gcm",o,c);return p.setAAD(Z(n)),p.setAuthTag(u),Buffer.concat([p.update(a),p.final()]).toString("utf8")}finally{f.fill(0),o.fill(0)}}catch{throw Error(G)}}function fe(e,t){try{if(!/^[0-9a-f]{64}$/.test(t))throw Error("invalid legacy private key");let n=Buffer.from(e.slice(F.length),"base64");if(n.length<32)throw Error("invalid legacy payload");let r=R("sha256").update(Buffer.from(t,"hex")).digest(),s=R("sha256").update(r).digest();return re(n.subarray(32).toString("hex"),s,n.subarray(0,16).toString("hex"),n.subarray(16,32).toString("hex"))}catch{throw Error(G)}}function Te(e){return e.startsWith(F)&&!e.startsWith(N)}function k(e,t){if(!e.startsWith(F))return e;return e.startsWith(N)?ae(e,t):fe(e,t)}function De(e,t,n){return oe(k(e,t),n)}function Be(e){let t=e.match(/^DOTENV_PRIVATE_KEY_(.+)$/);return t&&t[1]?t[1].toLowerCase():""}function W(e=""){return e?process.env[`DOTENV_PRIVATE_KEY_${e.toUpperCase()}`]:process.env.DOTENV_PRIVATE_KEY}import{spawnSync as ue}from"child_process";import{readFileSync as pe}from"fs";import{arch as de,hostname as le,platform as Q,release as ge,userInfo as he}from"os";import{basename as ye,dirname as me,resolve as ve}from"path";function x(e,t={}){let n={},r=[],s=[],i=e.split(`
|
|
3
3
|
`);for(let c of i){let a=c.trim();if(!a||a.startsWith("#"))continue;if(a.startsWith("DOTENV_PUBLIC_KEY=")){let p=a.match(/^DOTENV_PUBLIC_KEY=["']?([^"'\n]+)["']?/);if(p&&p[1]!==void 0)n.DOTENV_PUBLIC_KEY=p[1];continue}let u=a.match(/^([^=]+)=(.*)$/);if(!u||u[1]===void 0||u[2]===void 0)continue;let f=u[1].trim(),o=u[2].trim();if(o.startsWith('"')&&o.endsWith('"')||o.startsWith("'")&&o.endsWith("'")){if(o=o.slice(1,-1),o.includes("\\n"))o=o.replace(/\\n/g,`
|
|
4
|
-
`)}if(o.startsWith("encrypted:")||o.startsWith("enc:")){if(!t.privateKey){s.push(f);continue}try{let p=o.startsWith("enc:")?`encrypted:${o.slice(4)}`:o;o=k(p,t.privateKey)}catch(p){r.push(`Failed to decrypt ${f}: ${p instanceof Error?p.message:"Unknown error"}`)}}o=Ee(o,{...t.processEnv||process.env,...n}),o=_e(o),n[f]=o}return{parsed:n,errors:r,skippedEncrypted:s}}function Ee(e,t){return e.replace(/\$\{([^}]+)\}/g,(n,r)=>{let s=r.match(/^([^:\-+]+)(:-|-)(.+)$/);if(s){let[,c,a,u]=s,f=t[c];if(a===":-")return f||u;else return f!==void 0?f:u}let i=r.match(/^([^:\-+]+)(:?\+)(.+)$/);if(i){let[,c,a,u]=i,f=t[c];if(a===":+")return f?u:"";else return f!==void 0?u:""}return t[r]||""})}var we=new Set(["date","hostname","whoami","uname","pwd","echo","printf","cat","basename","dirname"]);function ke(e){let t=[],n="",r=null,s=!1;for(let i of e.trim()){if(s){n+=i,s=!1;continue}if(i==="\\"&&r!=="'"){s=!0;continue}if(r){if(i===r)r=null;else n+=i;continue}if(i==='"'||i==="'"){r=i;continue}if(/\s/.test(i)){if(n)t.push(n),n="";continue}n+=i}if(s||r)throw Error("Command substitution contains an unterminated escape or quote");if(n)t.push(n);return t}function xe(e){let[t,...n]=e,r=n.some((s)=>s.startsWith("-"));if(t==="echo"&&!r)return n.join(" ");if(t==="printf"&&n.length===1&&!n[0]?.includes("%"))return n[0];if(t==="hostname"&&n.length===0)return le();if(t==="whoami"&&n.length===0)return he().username;if(t==="pwd"&&n.length===0)return process.cwd();if(t==="basename"&&n.length===1)return ye(n[0]??"");if(t==="dirname"&&n.length===1)return me(n[0]??"");if(t==="cat"&&n.length>0&&!r)return n.map((s)=>pe(ve(process.cwd(),s),"utf8")).join("");if(t==="uname"){let s=n[0]??"-s";if(n.length<=1&&s==="-m")return de();if(n.length<=1&&s==="-r")return ge();if(n.length<=1&&s==="-s")return{aix:"AIX",android:"Android",cygwin:"CYGWIN",darwin:"Darwin",freebsd:"FreeBSD",haiku:"Haiku",linux:"Linux",netbsd:"NetBSD",openbsd:"OpenBSD",sunos:"SunOS",win32:"Windows_NT"}[Q()]??Q()}return}function _e(e){return e.replace(/\$\(([^)]+)\)/g,(t,n)=>{try{let r=ke(n),s=r[0];if(!s||!we.has(s))return console.warn(`[env] Blocked command substitution for disallowed command: ${s}`),"";let i=xe(r);if(i!==void 0)return i.trim();let c=ue(s,r.slice(1),{encoding:"utf8",env:process.env});if(c.status===0)return c.stdout.trim();let a=c.stderr.trim();console.warn(`[env] Command substitution failed (exit code ${c.status??"unknown"}): ${s}${a?`: ${a}`:""}`)}catch(r){console.warn(`[env] Command substitution error: ${r instanceof Error?r.message:String(r)}`)}return""})}async function We(e,t={}){let n={},r=[],s=[];for(let i of e)try{let c=Bun.file(i);if(!c.size)continue;let a=await c.text(),{parsed:u,errors:f,skippedEncrypted:o}=x(a,t);r.push(...f),s.push(...o);for(let[p,l]of Object.entries(u)){if(!t.overload&&n[p]!==void 0)continue;n[p]=l}}catch(c){if(c?.code==="ENOENT")continue;r.push(`Failed to read ${i}: ${c instanceof Error?c.message:String(c)}`)}return{parsed:n,errors:r,skippedEncrypted:s}}function _(e){return typeof e==="string"&&(e.startsWith("encrypted:")||e.startsWith("enc:"))}function m(e){if(!e||_(e))return;let t=e.trim().toLowerCase();if(!/^[a-z0-9_-]+$/.test(t))return;if(t==="prod")return"production";if(t==="stage")return"staging";if(t==="dev")return"development";return t}var D=null,B,A;function Pe(e,t,n=".env.keys"){let r=T(t,n);if(!O(r))return;try{let{parsed:s}=x(L(r,"utf-8"));if(e){let i=s[`DOTENV_PRIVATE_KEY_${e.toUpperCase()}`];if(i)return i}return s.DOTENV_PRIVATE_KEY}catch{return}}function be(e={}){return m(e.env)||A||m("development")||m(process.env.DOTENV_ENV)||m(process.env.APP_ENV)||"development"}function Ke(e={}){let t=be(e),n=e.cwd||process.cwd();if(D===t)return B;let r=W(t);if(!r)r=process.env.DOTENV_PRIVATE_KEY;if(!r)r=Pe(t,n);return D=t,B=r,r}function He(){D=null,B=void 0,A=void 0}function qe(e,t={}){if(!_(e))return e;let n=Ke(t);if(!n)return;try{let r=e.startsWith("enc:")?`encrypted:${e.slice(4)}`:e;return k(r,n)}catch{return}}function ee(e={}){let{path:t=[".env"],overload:n=!1,env:r,privateKey:s,keysFile:i=".env.keys",quiet:c=!1,cwd:a=process.cwd()}=e,u=Array.isArray(t)?t:[t],f=[],o=0,p=new Set(Object.entries(process.env).filter(([,d])=>d!==void 0&&!_(d)).map(([d])=>d)),l=s;if(!l&&i){let d=T(a,i);if(O(d))try{let g=L(d,"utf-8"),{parsed:v}=x(g);if(r){let P=`DOTENV_PRIVATE_KEY_${r.toUpperCase()}`;l=v[P]}else l=v.DOTENV_PRIVATE_KEY}catch(g){f.push(`Failed to load keys file: ${g instanceof Error?g.message:"Unknown error"}`)}}if(!l)l=W(r||"");for(let d of u){let g=T(a,d);if(!O(g)){if(!c)f.push(`File not found: ${g}`);continue}try{let v=L(g,"utf-8"),{parsed:P,errors:te,skippedEncrypted:E}=x(v,{privateKey:l,processEnv:process.env});if(f.push(...te),E.length>0){for(let V of E)if(_(process.env[V]))delete process.env[V];let w=r?`DOTENV_PRIVATE_KEY_${r.toUpperCase()}`:"DOTENV_PRIVATE_KEY",b=E.slice(0,5).join(", "),K=E.length>5?`, \u2026 +${E.length-5} more`:"";console.warn(`[env] warning: skipped ${E.length} encrypted value(s) in ${d} (${w} not set; defaults apply): ${b}${K}`)}let Y=0;for(let[w,b]of Object.entries(P)){if(w==="DOTENV_PUBLIC_KEY")continue;let K=process.env[w],V=_(K)&&b!==K;if(n||!p.has(w)||V)process.env[w]=b,o++,Y++}if(!c&&!process.env.__ENV_LOADED__)console.error(`[env] loaded ${Y}/${Object.keys(P).length} variables from ${d}`),process.env.__ENV_LOADED__="1"}catch(v){f.push(`Failed to load ${g}: ${v instanceof Error?v.message:"Unknown error"}`)}}return{loaded:o,errors:f}}function $e(e={}){return{name:"env-plugin",setup(t){ee(e)}}}function Me(e={}){let t=m(e.env)||m("development")||m(process.env.DOTENV_ENV)||m(process.env.APP_ENV)||"development",n=e.cwd||process.cwd();if(A!==t)A=t,D=null,B=void 0;let r=[],s=(a)=>{if(!r.includes(a)&&O(T(n,a)))r.push(a)};s(".env"),s(".env.local");let i=`.env.${t}`,c=`.env.${t}.local`;return s(i),s(c),ee({...e,path:r,env:t})}var Je=$e;export{be as activeEnvName,Me as autoLoadEnv,qe as decryptEnvValue,Je as default,$e as envPlugin,ee as loadEnv,He as resetPrivateKeyCache,Ke as resolvePrivateKey};
|
|
4
|
+
`)}if(o.startsWith("encrypted:")||o.startsWith("enc:")){if(!t.privateKey){s.push(f);continue}try{let p=o.startsWith("enc:")?`encrypted:${o.slice(4)}`:o;o=k(p,t.privateKey)}catch(p){r.push(`Failed to decrypt ${f}: ${p instanceof Error?p.message:"Unknown error"}`)}}o=Ee(o,{...t.processEnv||process.env,...n}),o=_e(o),n[f]=o}return{parsed:n,errors:r,skippedEncrypted:s}}function Ee(e,t){return e.replace(/\$\{([^}]+)\}/g,(n,r)=>{let s=r.match(/^([^:\-+]+)(:-|-)(.+)$/);if(s){let[,c,a,u]=s,f=t[c];if(a===":-")return f||u;else return f!==void 0?f:u}let i=r.match(/^([^:\-+]+)(:?\+)(.+)$/);if(i){let[,c,a,u]=i,f=t[c];if(a===":+")return f?u:"";else return f!==void 0?u:""}return t[r]||""})}var we=new Set(["date","hostname","whoami","uname","pwd","echo","printf","cat","basename","dirname"]);function ke(e){let t=[],n="",r=null,s=!1;for(let i of e.trim()){if(s){n+=i,s=!1;continue}if(i==="\\"&&r!=="'"){s=!0;continue}if(r){if(i===r)r=null;else n+=i;continue}if(i==='"'||i==="'"){r=i;continue}if(/\s/.test(i)){if(n)t.push(n),n="";continue}n+=i}if(s||r)throw Error("Command substitution contains an unterminated escape or quote");if(n)t.push(n);return t}function xe(e){let[t,...n]=e,r=n.some((s)=>s.startsWith("-"));if(t==="echo"&&!r)return n.join(" ");if(t==="printf"&&n.length===1&&!n[0]?.includes("%"))return n[0];if(t==="hostname"&&n.length===0)return le();if(t==="whoami"&&n.length===0)return he().username;if(t==="pwd"&&n.length===0)return process.cwd();if(t==="basename"&&n.length===1)return ye(n[0]??"");if(t==="dirname"&&n.length===1)return me(n[0]??"");if(t==="cat"&&n.length>0&&!r)return n.map((s)=>pe(ve(process.cwd(),s),"utf8")).join("");if(t==="uname"){let s=n[0]??"-s";if(n.length<=1&&s==="-m")return de();if(n.length<=1&&s==="-r")return ge();if(n.length<=1&&s==="-s")return{aix:"AIX",android:"Android",cygwin:"CYGWIN",darwin:"Darwin",freebsd:"FreeBSD",haiku:"Haiku",linux:"Linux",netbsd:"NetBSD",openbsd:"OpenBSD",sunos:"SunOS",win32:"Windows_NT"}[Q()]??Q()}return}function _e(e){return e.replace(/\$\(([^)]+)\)/g,(t,n)=>{try{let r=ke(n),s=r[0];if(!s||!we.has(s))return console.warn(`[env] Blocked command substitution for disallowed command: ${s}`),"";let i=xe(r);if(i!==void 0)return i.trim();let c=ue(s,r.slice(1),{encoding:"utf8",env:process.env});if(c.status===0)return c.stdout.trim();let a=c.stderr.trim();console.warn(`[env] Command substitution failed (exit code ${c.status??"unknown"}): ${s}${a?`: ${a}`:""}`)}catch(r){console.warn(`[env] Command substitution error: ${r instanceof Error?r.message:String(r)}`)}return""})}async function We(e,t={}){let n={},r=[],s=[];for(let i of e)try{let c=Bun.file(i);if(!c.size)continue;let a=await c.text(),{parsed:u,errors:f,skippedEncrypted:o}=x(a,t);r.push(...f),s.push(...o);for(let[p,l]of Object.entries(u)){if(!t.overload&&n[p]!==void 0)continue;n[p]=l}}catch(c){if(c?.code==="ENOENT")continue;r.push(`Failed to read ${i}: ${c instanceof Error?c.message:String(c)}`)}return{parsed:n,errors:r,skippedEncrypted:s}}import{existsSync as O}from"fs";import{readFileSync as L}from"fs";import{resolve as T}from"path";function _(e){return typeof e==="string"&&(e.startsWith("encrypted:")||e.startsWith("enc:"))}function m(e){if(!e||_(e))return;let t=e.trim().toLowerCase();if(!/^[a-z0-9_-]+$/.test(t))return;if(t==="prod")return"production";if(t==="stage")return"staging";if(t==="dev")return"development";return t}var D=null,B,A;function Pe(e,t,n=".env.keys"){let r=T(t,n);if(!O(r))return;try{let{parsed:s}=x(L(r,"utf-8"));if(e){let i=s[`DOTENV_PRIVATE_KEY_${e.toUpperCase()}`];if(i)return i}return s.DOTENV_PRIVATE_KEY}catch{return}}function be(e={}){return m(e.env)||A||m("development")||m(process.env.DOTENV_ENV)||m(process.env.APP_ENV)||"development"}function Ke(e={}){let t=be(e),n=e.cwd||process.cwd();if(D===t)return B;let r=W(t);if(!r)r=process.env.DOTENV_PRIVATE_KEY;if(!r)r=Pe(t,n);return D=t,B=r,r}function He(){D=null,B=void 0,A=void 0}function qe(e,t={}){if(!_(e))return e;let n=Ke(t);if(!n)return;try{let r=e.startsWith("enc:")?`encrypted:${e.slice(4)}`:e;return k(r,n)}catch{return}}function ee(e={}){let{path:t=[".env"],overload:n=!1,env:r,privateKey:s,keysFile:i=".env.keys",quiet:c=!1,cwd:a=process.cwd()}=e,u=Array.isArray(t)?t:[t],f=[],o=0,p=new Set(Object.entries(process.env).filter(([,d])=>d!==void 0&&!_(d)).map(([d])=>d)),l=s;if(!l&&i){let d=T(a,i);if(O(d))try{let g=L(d,"utf-8"),{parsed:v}=x(g);if(r){let P=`DOTENV_PRIVATE_KEY_${r.toUpperCase()}`;l=v[P]}else l=v.DOTENV_PRIVATE_KEY}catch(g){f.push(`Failed to load keys file: ${g instanceof Error?g.message:"Unknown error"}`)}}if(!l)l=W(r||"");for(let d of u){let g=T(a,d);if(!O(g)){if(!c)f.push(`File not found: ${g}`);continue}try{let v=L(g,"utf-8"),{parsed:P,errors:te,skippedEncrypted:E}=x(v,{privateKey:l,processEnv:process.env});if(f.push(...te),E.length>0){for(let V of E)if(_(process.env[V]))delete process.env[V];let w=r?`DOTENV_PRIVATE_KEY_${r.toUpperCase()}`:"DOTENV_PRIVATE_KEY",b=E.slice(0,5).join(", "),K=E.length>5?`, \u2026 +${E.length-5} more`:"";console.warn(`[env] warning: skipped ${E.length} encrypted value(s) in ${d} (${w} not set; defaults apply): ${b}${K}`)}let Y=0;for(let[w,b]of Object.entries(P)){if(w==="DOTENV_PUBLIC_KEY")continue;let K=process.env[w],V=_(K)&&b!==K;if(n||!p.has(w)||V)process.env[w]=b,o++,Y++}if(!c&&!process.env.__ENV_LOADED__)console.error(`[env] loaded ${Y}/${Object.keys(P).length} variables from ${d}`),process.env.__ENV_LOADED__="1"}catch(v){f.push(`Failed to load ${g}: ${v instanceof Error?v.message:"Unknown error"}`)}}return{loaded:o,errors:f}}function $e(e={}){return{name:"env-plugin",setup(t){ee(e)}}}function Me(e={}){let t=m(e.env)||m("development")||m(process.env.DOTENV_ENV)||m(process.env.APP_ENV)||"development",n=e.cwd||process.cwd();if(A!==t)A=t,D=null,B=void 0;let r=[],s=(a)=>{if(!r.includes(a)&&O(T(n,a)))r.push(a)};s(".env"),s(".env.local");let i=`.env.${t}`,c=`.env.${t}.local`;return s(i),s(c),ee({...e,path:r,env:t})}var Je=$e;export{be as activeEnvName,Me as autoLoadEnv,qe as decryptEnvValue,Je as default,$e as envPlugin,ee as loadEnv,He as resetPrivateKeyCache,Ke as resolvePrivateKey};
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@stacksjs/env",
|
|
3
3
|
"type": "module",
|
|
4
4
|
"sideEffects": false,
|
|
5
|
-
"version": "0.74.
|
|
5
|
+
"version": "0.74.35",
|
|
6
6
|
"description": "Stacks env helper methods.",
|
|
7
7
|
"author": "Chris Breuer",
|
|
8
8
|
"contributors": [
|
|
@@ -56,10 +56,10 @@
|
|
|
56
56
|
"prepublishOnly": "bun run build"
|
|
57
57
|
},
|
|
58
58
|
"dependencies": {
|
|
59
|
-
"@stacksjs/path": "0.74.
|
|
59
|
+
"@stacksjs/path": "0.74.35"
|
|
60
60
|
},
|
|
61
61
|
"devDependencies": {
|
|
62
62
|
"better-dx": "^0.2.24",
|
|
63
|
-
"@stacksjs/validation": "0.74.
|
|
63
|
+
"@stacksjs/validation": "0.74.35"
|
|
64
64
|
}
|
|
65
65
|
}
|