@stacksjs/env 0.70.113 → 0.70.115

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 CHANGED
@@ -1,23 +1,23 @@
1
1
  // @bun
2
- import{createCipheriv as S,createDecipheriv as b,createHash as f,randomBytes as x}from"crypto";function P(j,I){let Y=x(16),X=I.length===32?I:Buffer.from(I.toString("hex").slice(0,64),"hex"),q=S("aes-256-gcm",X,Y),Q=Buffer.concat([q.update(j,"utf8"),q.final()]),U=q.getAuthTag();return{ciphertext:Q.toString("hex"),iv:Y.toString("hex"),authTag:U.toString("hex")}}function N(j,I,Y,X){let q=I.length===32?I:Buffer.from(I.toString("hex").slice(0,64),"hex");try{let Q=b("aes-256-gcm",q,Buffer.from(Y,"hex"));return Q.setAuthTag(Buffer.from(X,"hex")),Buffer.concat([Q.update(Buffer.from(j,"hex")),Q.final()]).toString("utf8")}catch(Q){throw Error(`Decryption failed (data may be corrupted or key is incorrect): ${Q instanceof Error?Q.message:String(Q)}`)}}function F(){let j=x(32);return{publicKey:f("sha256").update(j).digest().toString("hex"),privateKey:j.toString("hex")}}function V(j,I){let Y=f("sha256").update(Buffer.from(I,"hex")).digest(),{ciphertext:X,iv:q,authTag:Q}=P(j,Y);return`encrypted:${Buffer.concat([Buffer.from(q,"hex"),Buffer.from(Q,"hex"),Buffer.from(X,"hex")]).toString("base64")}`}function w(j,I){if(!j.startsWith("encrypted:"))return j;let Y=j.slice(10),X=Buffer.from(Y,"base64");if(X.length<32)throw Error("Invalid encrypted data: payload too short (need at least iv + authTag = 32 bytes)");let q=X.subarray(0,16).toString("hex"),Q=X.subarray(16,32).toString("hex"),U=X.subarray(32).toString("hex"),$=f("sha256").update(Buffer.from(I,"hex")).digest(),Z=f("sha256").update($).digest();return N(U,Z,q,Q)}function v(j){let I=j.match(/^DOTENV_PRIVATE_KEY_(.+)$/);return I&&I[1]?I[1].toLowerCase():""}function c(j=""){if(!j)return process.env.DOTENV_PRIVATE_KEY;let I=`DOTENV_PRIVATE_KEY_${j.toUpperCase()}`;return process.env[I]}function C(j,I={}){let Y={},X=[],q=j.split(`
3
- `);for(let Q of q){let U=Q.trim();if(!U||U.startsWith("#"))continue;if(U.startsWith("DOTENV_PUBLIC_KEY=")){let A=U.match(/^DOTENV_PUBLIC_KEY=["']?([^"'\n]+)["']?/);if(A&&A[1]!==void 0)Y.DOTENV_PUBLIC_KEY=A[1];continue}let $=U.match(/^([^=]+)=(.*)$/);if(!$||$[1]===void 0||$[2]===void 0)continue;let Z=$[1].trim(),J=$[2].trim();if(J.startsWith('"')&&J.endsWith('"')||J.startsWith("'")&&J.endsWith("'")){if(J=J.slice(1,-1),J.includes("\\n"))J=J.replace(/\\n/g,`
4
- `)}if(I.privateKey&&(J.startsWith("encrypted:")||J.startsWith("enc:")))try{let A=J.startsWith("enc:")?`encrypted:${J.slice(4)}`:J;J=w(A,I.privateKey)}catch(A){X.push(`Failed to decrypt ${Z}: ${A instanceof Error?A.message:"Unknown error"}`)}J=K(J,{...I.processEnv||process.env,...Y}),J=h(J),Y[Z]=J}return{parsed:Y,errors:X}}function K(j,I){return j.replace(/\$\{([^}]+)\}/g,(Y,X)=>{let q=X.match(/^([^:\-+]+)(:-|-)(.+)$/);if(q){let[,U,$,Z]=q,J=I[U];if($===":-")return J||Z;else return J!==void 0?J:Z}let Q=X.match(/^([^:\-+]+)(:?\+)(.+)$/);if(Q){let[,U,$,Z]=Q,J=I[U];if($===":+")return J?Z:"";else return J!==void 0?Z:""}return I[X]||""})}var m=new Set(["date","hostname","whoami","uname","pwd","echo","printf","cat","basename","dirname"]);function h(j){return j.replace(/\$\(([^)]+)\)/g,(I,Y)=>{try{let X=Y.trim().split(/\s+/),q=X[0];if(!q||!m.has(q))return console.warn(`[env] Blocked command substitution for disallowed command: ${q}`),"";let Q=Bun.spawnSync(X,{stdout:"pipe",stderr:"pipe"});if(Q.exitCode===0)return new TextDecoder().decode(Q.stdout).trim();console.warn(`[env] Command substitution failed (exit code ${Q.exitCode}): ${q}`)}catch(X){console.warn(`[env] Command substitution error: ${X instanceof Error?X.message:String(X)}`)}return""})}async function s(j,I={}){let Y={},X=[];for(let q of j)try{let Q=Bun.file(q);if(!Q.size)continue;let U=await Q.text(),{parsed:$,errors:Z}=C(U,I);X.push(...Z);for(let[J,A]of Object.entries($)){if(!I.overload&&Y[J]!==void 0)continue;Y[J]=A}}catch(Q){if(Q?.code==="ENOENT")continue;X.push(`Failed to read ${q}: ${Q instanceof Error?Q.message:String(Q)}`)}return{parsed:Y,errors:X}}import{existsSync as g,readFileSync as D,writeFileSync as E}from"fs";import{resolve as M}from"path";function k(j={}){let I=j.cwd||process.cwd(),Y=M(I,j.file||".env"),X=M(I,j.keysFile||".env.keys");if(!g(Y))return{success:!1,error:`File not found: ${Y}`};try{let q,Q;if(g(X)){let G=D(X,"utf-8"),{parsed:O}=C(G),W=((j.file||".env").split("/").pop()||"").replace(/^\.env\./,"").replace(/^\.env$/,"").toUpperCase(),z=W?`DOTENV_PUBLIC_KEY_${W}`:"DOTENV_PUBLIC_KEY",R=W?`DOTENV_PRIVATE_KEY_${W}`:"DOTENV_PRIVATE_KEY";if(q=O[z]||"",Q=O[R]||"",!q||!Q){let _=F();q=_.publicKey,Q=_.privateKey;let L=`
5
- ${z}="${q}"
6
- ${R}="${Q}"
7
- `;E(X,G+L,"utf-8")}}else{let G=F();q=G.publicKey,Q=G.privateKey;let B=((j.file||".env").split("/").pop()||"").replace(/^\.env\./,"").replace(/^\.env$/,"").toUpperCase(),W=B?`DOTENV_PUBLIC_KEY_${B}`:"DOTENV_PUBLIC_KEY",z=B?`DOTENV_PRIVATE_KEY_${B}`:"DOTENV_PRIVATE_KEY",R=`# .env.keys - Keep this file secure and never commit to source control
8
- ${W}="${q}"
9
- ${z}="${Q}"
10
- `;E(X,R,"utf-8")}let $=D(Y,"utf-8").split(`
11
- `),Z=[],J=j.file?j.file.replace(/^\.env\./,"").toUpperCase():"",A=J?`DOTENV_PUBLIC_KEY_${J}`:"DOTENV_PUBLIC_KEY";Z.push("#/-------------------[DOTENV_PUBLIC_KEY]--------------------/"),Z.push("#/ public-key encryption for .env files /"),Z.push("#/ [how it works](https://stacksjs.com/encryption) /"),Z.push("#/----------------------------------------------------------/"),Z.push(`${A}="${q}"`),Z.push("");for(let G of $){let O=G.trim();if(!O||O.startsWith("#")){Z.push(G);continue}if(O.startsWith("DOTENV_PUBLIC_KEY"))continue;let H=O.match(/^([^=]+)=(.*)$/);if(!H||H[1]===void 0||H[2]===void 0){Z.push(G);continue}let B=H[1].trim(),W=H[2].trim();if(W.startsWith('"')&&W.endsWith('"')||W.startsWith("'")&&W.endsWith("'"))W=W.slice(1,-1);let z=!0;if(j.key&&!B.includes(j.key))z=!1;if(j.excludeKey&&B.includes(j.excludeKey))z=!1;if(W.startsWith("encrypted:"))z=!1;if(z)W=V(W,q);Z.push(`${B}="${W}"`)}let T=Z.join(`
12
- `);if(j.stdout)return{success:!0,output:T};return E(Y,T,"utf-8"),{success:!0,output:`\u2714 encrypted (${j.file||".env"})
13
- \u2714 key added to ${j.keysFile||".env.keys"}`}}catch(q){return{success:!1,error:`Failed to encrypt: ${q instanceof Error?q.message:"Unknown error"}`}}}function d(j={}){let I=j.cwd||process.cwd(),Y=M(I,j.file||".env"),X=M(I,j.keysFile||".env.keys");if(!g(Y))return{success:!1,error:`File not found: ${Y}`};if(!g(X))return{success:!1,error:`Keys file not found: ${X}`};try{let q=D(X,"utf-8"),{parsed:Q}=C(q),Z=((j.file||".env").split("/").pop()||"").replace(/^\.env\./,"").replace(/^\.env$/,"").toUpperCase(),J=Z?`DOTENV_PRIVATE_KEY_${Z}`:"DOTENV_PRIVATE_KEY",A=Q[J];if(!A)return{success:!1,error:`Private key not found: ${J}`};let G=D(Y,"utf-8").split(`
14
- `),O=[];for(let B of G){let W=B.trim();if(!W||W.startsWith("#")){O.push(B);continue}if(W.startsWith("DOTENV_PUBLIC_KEY"))continue;let z=W.match(/^([^=]+)=(.*)$/);if(!z||z[1]===void 0||z[2]===void 0){O.push(B);continue}let R=z[1].trim(),_=z[2].trim();if(_.startsWith('"')&&_.endsWith('"')||_.startsWith("'")&&_.endsWith("'"))_=_.slice(1,-1);let L=_.startsWith("encrypted:");if(j.key&&!R.includes(j.key))L=!1;if(L)_=w(_,A);O.push(`${R}="${_}"`)}let H=O.join(`
15
- `);if(j.stdout)return{success:!0,output:H};return E(Y,H,"utf-8"),{success:!0,output:`\u2714 decrypted (${j.file||".env"})`}}catch(q){return{success:!1,error:`Failed to decrypt: ${q instanceof Error?q.message:"Unknown error"}`}}}function i(j,I,Y={}){let X=Y.cwd||process.cwd(),q=M(X,Y.file||".env"),Q=M(X,Y.keysFile||".env.keys");try{let U="";if(g(q))U=D(q,"utf-8");let $=U.split(`
16
- `),Z=!1,J,G=((Y.file||".env").split("/").pop()||"").replace(/^\.env\./,"").replace(/^\.env$/,"").toUpperCase(),O=G?`DOTENV_PUBLIC_KEY_${G}`:"DOTENV_PUBLIC_KEY",H=G?`DOTENV_PRIVATE_KEY_${G}`:"DOTENV_PRIVATE_KEY";for(let z of $){let R=z.trim();if(R.startsWith(`${O}=`)){let _=R.match(/^[^=]+=["']?([^"'\n]+)["']?/);if(_)J=_[1];break}}if(J){let z=!1;if(g(Q)){let R=D(Q,"utf-8"),{parsed:_}=C(R);z=Boolean(_[H])}if(!z)J=void 0}if(!Y.plain&&!J){let z=F();J=z.publicKey;let R="";if(g(Q))R=D(Q,"utf-8");R+=`
17
- ${O}="${z.publicKey}"
18
- ${H}="${z.privateKey}"
19
- `,E(Q,R,"utf-8");for(let _=$.length-1;_>=0;_--){let L=$[_];if(L!==void 0&&L.trim().startsWith(`${O}=`))$.splice(_,1)}$.unshift(`${O}="${J}"`)}let B=I;if(!Y.plain&&J)B=V(I,J);for(let z=0;z<$.length;z++){let R=$[z];if(R===void 0)continue;if(R.trim().startsWith(`${j}=`)){$[z]=`${j}="${B}"`,Z=!0;break}}if(!Z)$.push(`${j}="${B}"`);let W=$.join(`
20
- `);return E(q,W,"utf-8"),{success:!0,output:`set ${j}${Y.plain?"":" with encryption"} (${Y.file||".env"})`}}catch(U){return{success:!1,error:`Failed to set: ${U instanceof Error?U.message:"Unknown error"}`}}}function t(j,I={}){let Y=I.cwd||process.cwd(),X=M(Y,I.file||".env");if(!g(X))return{success:!1,error:`File not found: ${X}`};try{let q,Q=M(Y,I.keysFile||".env.keys"),Z=((I.file||".env").split("/").pop()||"").replace(/^\.env\./,"").replace(/^\.env$/,"").toUpperCase(),J=Z?`DOTENV_PRIVATE_KEY_${Z}`:"DOTENV_PRIVATE_KEY";if(g(Q)){let H=D(Q,"utf-8"),{parsed:B}=C(H);q=B[J]}if(!q)q=process.env[J];let A=D(X,"utf-8"),{parsed:T}=C(A,{privateKey:q});if(j&&!I.all){let H=T[j];if(H===void 0)return{success:!1,error:`Key not found: ${j}`};return{success:!0,output:H}}let G=I.all?{...process.env,...T}:T,O;switch(I.format){case"shell":O=Object.entries(G).map(([H,B])=>`${H}=${B}`).join(" ");break;case"eval":O=Object.entries(G).map(([H,B])=>`${H}="${B}"`).join(`
21
- `);break;case"json":default:O=I.prettyPrint?JSON.stringify(G,null,2):JSON.stringify(G);break}return{success:!0,output:O}}catch(q){return{success:!1,error:`Failed to get: ${q instanceof Error?q.message:"Unknown error"}`}}}function e(j,I={}){let Y=I.cwd||process.cwd(),X=M(Y,I.keysFile||".env.keys");if(!g(X))return{success:!1,error:`Keys file not found: ${X}`};try{let q=D(X,"utf-8"),{parsed:Q}=C(q),Z=((I.file||".env").split("/").pop()||"").replace(/^\.env\./,"").replace(/^\.env$/,"").toUpperCase(),J=Z?`DOTENV_PUBLIC_KEY_${Z}`:"DOTENV_PUBLIC_KEY",A=Z?`DOTENV_PRIVATE_KEY_${Z}`:"DOTENV_PRIVATE_KEY";if(j){let O=Q[j];if(!O)return{success:!1,error:`Key not found: ${j}`};return{success:!0,output:O}}let T={[J]:Q[J],[A]:Q[A]};return{success:!0,output:I.format==="shell"?`${J}=${T[J]} ${A}=${T[A]}`:JSON.stringify(T)}}catch(q){return{success:!1,error:`Failed to get keypair: ${q instanceof Error?q.message:"Unknown error"}`}}}function jj(j={}){let I=d({file:j.file,keysFile:j.keysFile,stdout:!0,cwd:j.cwd});if(!I.success)return I;let Y=j.cwd||process.cwd(),X=M(Y,j.file||".env"),q=M(Y,j.keysFile||".env.keys");if(I.output)E(X,I.output,"utf-8");let Q=F(),$=D(q,"utf-8").split(`
22
- `),Z=j.file?j.file.replace(/^\.env\./,"").toUpperCase():"",J=Z?`DOTENV_PUBLIC_KEY_${Z}`:"DOTENV_PUBLIC_KEY",A=Z?`DOTENV_PRIVATE_KEY_${Z}`:"DOTENV_PRIVATE_KEY";for(let T=0;T<$.length;T++){let G=$[T];if(G===void 0)continue;if(G.startsWith(`${J}=`))$[T]=`${J}="${Q.publicKey}"`;else if(G.startsWith(`${A}=`))$[T]=`${A}="${Q.privateKey}"`}return E(q,$.join(`
2
+ import{createCipheriv as S,createDecipheriv as b,createHash as f,randomBytes as x}from"crypto";function P(j,I){let X=x(16),J=I.length===32?I:Buffer.from(I.toString("hex").slice(0,64),"hex"),q=S("aes-256-gcm",J,X),Q=Buffer.concat([q.update(j,"utf8"),q.final()]),U=q.getAuthTag();return{ciphertext:Q.toString("hex"),iv:X.toString("hex"),authTag:U.toString("hex")}}function N(j,I,X,J){let q=I.length===32?I:Buffer.from(I.toString("hex").slice(0,64),"hex");try{let Q=b("aes-256-gcm",q,Buffer.from(X,"hex"));return Q.setAuthTag(Buffer.from(J,"hex")),Buffer.concat([Q.update(Buffer.from(j,"hex")),Q.final()]).toString("utf8")}catch(Q){throw Error(`Decryption failed (data may be corrupted or key is incorrect): ${Q instanceof Error?Q.message:String(Q)}`)}}function F(){let j=x(32);return{publicKey:f("sha256").update(j).digest().toString("hex"),privateKey:j.toString("hex")}}function V(j,I){let X=f("sha256").update(Buffer.from(I,"hex")).digest(),{ciphertext:J,iv:q,authTag:Q}=P(j,X);return`encrypted:${Buffer.concat([Buffer.from(q,"hex"),Buffer.from(Q,"hex"),Buffer.from(J,"hex")]).toString("base64")}`}function w(j,I){if(!j.startsWith("encrypted:"))return j;let X=j.slice(10),J=Buffer.from(X,"base64");if(J.length<32)throw Error("Invalid encrypted data: payload too short (need at least iv + authTag = 32 bytes)");let q=J.subarray(0,16).toString("hex"),Q=J.subarray(16,32).toString("hex"),U=J.subarray(32).toString("hex"),z=f("sha256").update(Buffer.from(I,"hex")).digest(),Y=f("sha256").update(z).digest();return N(U,Y,q,Q)}function v(j){let I=j.match(/^DOTENV_PRIVATE_KEY_(.+)$/);return I&&I[1]?I[1].toLowerCase():""}function c(j=""){if(!j)return process.env.DOTENV_PRIVATE_KEY;let I=`DOTENV_PRIVATE_KEY_${j.toUpperCase()}`;return process.env[I]}function C(j,I={}){let X={},J=[],q=[],Q=j.split(`
3
+ `);for(let U of Q){let z=U.trim();if(!z||z.startsWith("#"))continue;if(z.startsWith("DOTENV_PUBLIC_KEY=")){let A=z.match(/^DOTENV_PUBLIC_KEY=["']?([^"'\n]+)["']?/);if(A&&A[1]!==void 0)X.DOTENV_PUBLIC_KEY=A[1];continue}let Y=z.match(/^([^=]+)=(.*)$/);if(!Y||Y[1]===void 0||Y[2]===void 0)continue;let Z=Y[1].trim(),$=Y[2].trim();if($.startsWith('"')&&$.endsWith('"')||$.startsWith("'")&&$.endsWith("'")){if($=$.slice(1,-1),$.includes("\\n"))$=$.replace(/\\n/g,`
4
+ `)}if($.startsWith("encrypted:")||$.startsWith("enc:")){if(!I.privateKey){q.push(Z);continue}try{let A=$.startsWith("enc:")?`encrypted:${$.slice(4)}`:$;$=w(A,I.privateKey)}catch(A){J.push(`Failed to decrypt ${Z}: ${A instanceof Error?A.message:"Unknown error"}`)}}$=K($,{...I.processEnv||process.env,...X}),$=h($),X[Z]=$}return{parsed:X,errors:J,skippedEncrypted:q}}function K(j,I){return j.replace(/\$\{([^}]+)\}/g,(X,J)=>{let q=J.match(/^([^:\-+]+)(:-|-)(.+)$/);if(q){let[,U,z,Y]=q,Z=I[U];if(z===":-")return Z||Y;else return Z!==void 0?Z:Y}let Q=J.match(/^([^:\-+]+)(:?\+)(.+)$/);if(Q){let[,U,z,Y]=Q,Z=I[U];if(z===":+")return Z?Y:"";else return Z!==void 0?Y:""}return I[J]||""})}var m=new Set(["date","hostname","whoami","uname","pwd","echo","printf","cat","basename","dirname"]);function h(j){return j.replace(/\$\(([^)]+)\)/g,(I,X)=>{try{let J=X.trim().split(/\s+/),q=J[0];if(!q||!m.has(q))return console.warn(`[env] Blocked command substitution for disallowed command: ${q}`),"";let Q=Bun.spawnSync(J,{stdout:"pipe",stderr:"pipe"});if(Q.exitCode===0)return new TextDecoder().decode(Q.stdout).trim();console.warn(`[env] Command substitution failed (exit code ${Q.exitCode}): ${q}`)}catch(J){console.warn(`[env] Command substitution error: ${J instanceof Error?J.message:String(J)}`)}return""})}async function s(j,I={}){let X={},J=[],q=[];for(let Q of j)try{let U=Bun.file(Q);if(!U.size)continue;let z=await U.text(),{parsed:Y,errors:Z,skippedEncrypted:$}=C(z,I);J.push(...Z),q.push(...$);for(let[A,O]of Object.entries(Y)){if(!I.overload&&X[A]!==void 0)continue;X[A]=O}}catch(U){if(U?.code==="ENOENT")continue;J.push(`Failed to read ${Q}: ${U instanceof Error?U.message:String(U)}`)}return{parsed:X,errors:J,skippedEncrypted:q}}import{existsSync as g,readFileSync as D,writeFileSync as L}from"fs";import{resolve as M}from"path";function k(j={}){let I=j.cwd||process.cwd(),X=M(I,j.file||".env"),J=M(I,j.keysFile||".env.keys");if(!g(X))return{success:!1,error:`File not found: ${X}`};try{let q,Q;if(g(J)){let O=D(J,"utf-8"),{parsed:W}=C(O),_=((j.file||".env").split("/").pop()||"").replace(/^\.env\./,"").replace(/^\.env$/,"").toUpperCase(),G=_?`DOTENV_PUBLIC_KEY_${_}`:"DOTENV_PUBLIC_KEY",T=_?`DOTENV_PRIVATE_KEY_${_}`:"DOTENV_PRIVATE_KEY";if(q=W[G]||"",Q=W[T]||"",!q||!Q){let B=F();q=B.publicKey,Q=B.privateKey;let E=`
5
+ ${G}="${q}"
6
+ ${T}="${Q}"
7
+ `;L(J,O+E,"utf-8")}}else{let O=F();q=O.publicKey,Q=O.privateKey;let H=((j.file||".env").split("/").pop()||"").replace(/^\.env\./,"").replace(/^\.env$/,"").toUpperCase(),_=H?`DOTENV_PUBLIC_KEY_${H}`:"DOTENV_PUBLIC_KEY",G=H?`DOTENV_PRIVATE_KEY_${H}`:"DOTENV_PRIVATE_KEY",T=`# .env.keys - Keep this file secure and never commit to source control
8
+ ${_}="${q}"
9
+ ${G}="${Q}"
10
+ `;L(J,T,"utf-8")}let z=D(X,"utf-8").split(`
11
+ `),Y=[],Z=j.file?j.file.replace(/^\.env\./,"").toUpperCase():"",$=Z?`DOTENV_PUBLIC_KEY_${Z}`:"DOTENV_PUBLIC_KEY";Y.push("#/-------------------[DOTENV_PUBLIC_KEY]--------------------/"),Y.push("#/ public-key encryption for .env files /"),Y.push("#/ [how it works](https://stacksjs.com/encryption) /"),Y.push("#/----------------------------------------------------------/"),Y.push(`${$}="${q}"`),Y.push("");for(let O of z){let W=O.trim();if(!W||W.startsWith("#")){Y.push(O);continue}if(W.startsWith("DOTENV_PUBLIC_KEY"))continue;let R=W.match(/^([^=]+)=(.*)$/);if(!R||R[1]===void 0||R[2]===void 0){Y.push(O);continue}let H=R[1].trim(),_=R[2].trim();if(_.startsWith('"')&&_.endsWith('"')||_.startsWith("'")&&_.endsWith("'"))_=_.slice(1,-1);let G=!0;if(j.key&&!H.includes(j.key))G=!1;if(j.excludeKey&&H.includes(j.excludeKey))G=!1;if(_.startsWith("encrypted:"))G=!1;if(G)_=V(_,q);Y.push(`${H}="${_}"`)}let A=Y.join(`
12
+ `);if(j.stdout)return{success:!0,output:A};return L(X,A,"utf-8"),{success:!0,output:`\u2714 encrypted (${j.file||".env"})
13
+ \u2714 key added to ${j.keysFile||".env.keys"}`}}catch(q){return{success:!1,error:`Failed to encrypt: ${q instanceof Error?q.message:"Unknown error"}`}}}function d(j={}){let I=j.cwd||process.cwd(),X=M(I,j.file||".env"),J=M(I,j.keysFile||".env.keys");if(!g(X))return{success:!1,error:`File not found: ${X}`};if(!g(J))return{success:!1,error:`Keys file not found: ${J}`};try{let q=D(J,"utf-8"),{parsed:Q}=C(q),Y=((j.file||".env").split("/").pop()||"").replace(/^\.env\./,"").replace(/^\.env$/,"").toUpperCase(),Z=Y?`DOTENV_PRIVATE_KEY_${Y}`:"DOTENV_PRIVATE_KEY",$=Q[Z];if(!$)return{success:!1,error:`Private key not found: ${Z}`};let O=D(X,"utf-8").split(`
14
+ `),W=[];for(let H of O){let _=H.trim();if(!_||_.startsWith("#")){W.push(H);continue}if(_.startsWith("DOTENV_PUBLIC_KEY"))continue;let G=_.match(/^([^=]+)=(.*)$/);if(!G||G[1]===void 0||G[2]===void 0){W.push(H);continue}let T=G[1].trim(),B=G[2].trim();if(B.startsWith('"')&&B.endsWith('"')||B.startsWith("'")&&B.endsWith("'"))B=B.slice(1,-1);let E=B.startsWith("encrypted:");if(j.key&&!T.includes(j.key))E=!1;if(E)B=w(B,$);W.push(`${T}="${B}"`)}let R=W.join(`
15
+ `);if(j.stdout)return{success:!0,output:R};return L(X,R,"utf-8"),{success:!0,output:`\u2714 decrypted (${j.file||".env"})`}}catch(q){return{success:!1,error:`Failed to decrypt: ${q instanceof Error?q.message:"Unknown error"}`}}}function i(j,I,X={}){let J=X.cwd||process.cwd(),q=M(J,X.file||".env"),Q=M(J,X.keysFile||".env.keys");try{let U="";if(g(q))U=D(q,"utf-8");let z=U.split(`
16
+ `),Y=!1,Z,O=((X.file||".env").split("/").pop()||"").replace(/^\.env\./,"").replace(/^\.env$/,"").toUpperCase(),W=O?`DOTENV_PUBLIC_KEY_${O}`:"DOTENV_PUBLIC_KEY",R=O?`DOTENV_PRIVATE_KEY_${O}`:"DOTENV_PRIVATE_KEY";for(let G of z){let T=G.trim();if(T.startsWith(`${W}=`)){let B=T.match(/^[^=]+=["']?([^"'\n]+)["']?/);if(B)Z=B[1];break}}if(Z){let G=!1;if(g(Q)){let T=D(Q,"utf-8"),{parsed:B}=C(T);G=Boolean(B[R])}if(!G)Z=void 0}if(!X.plain&&!Z){let G=F();Z=G.publicKey;let T="";if(g(Q))T=D(Q,"utf-8");T+=`
17
+ ${W}="${G.publicKey}"
18
+ ${R}="${G.privateKey}"
19
+ `,L(Q,T,"utf-8");for(let B=z.length-1;B>=0;B--){let E=z[B];if(E!==void 0&&E.trim().startsWith(`${W}=`))z.splice(B,1)}z.unshift(`${W}="${Z}"`)}let H=I;if(!X.plain&&Z)H=V(I,Z);for(let G=0;G<z.length;G++){let T=z[G];if(T===void 0)continue;if(T.trim().startsWith(`${j}=`)){z[G]=`${j}="${H}"`,Y=!0;break}}if(!Y)z.push(`${j}="${H}"`);let _=z.join(`
20
+ `);return L(q,_,"utf-8"),{success:!0,output:`set ${j}${X.plain?"":" with encryption"} (${X.file||".env"})`}}catch(U){return{success:!1,error:`Failed to set: ${U instanceof Error?U.message:"Unknown error"}`}}}function t(j,I={}){let X=I.cwd||process.cwd(),J=M(X,I.file||".env");if(!g(J))return{success:!1,error:`File not found: ${J}`};try{let q,Q=M(X,I.keysFile||".env.keys"),Y=((I.file||".env").split("/").pop()||"").replace(/^\.env\./,"").replace(/^\.env$/,"").toUpperCase(),Z=Y?`DOTENV_PRIVATE_KEY_${Y}`:"DOTENV_PRIVATE_KEY";if(g(Q)){let R=D(Q,"utf-8"),{parsed:H}=C(R);q=H[Z]}if(!q)q=process.env[Z];let $=D(J,"utf-8"),{parsed:A}=C($,{privateKey:q});if(j&&!I.all){let R=A[j];if(R===void 0)return{success:!1,error:`Key not found: ${j}`};return{success:!0,output:R}}let O=I.all?{...process.env,...A}:A,W;switch(I.format){case"shell":W=Object.entries(O).map(([R,H])=>`${R}=${H}`).join(" ");break;case"eval":W=Object.entries(O).map(([R,H])=>`${R}="${H}"`).join(`
21
+ `);break;case"json":default:W=I.prettyPrint?JSON.stringify(O,null,2):JSON.stringify(O);break}return{success:!0,output:W}}catch(q){return{success:!1,error:`Failed to get: ${q instanceof Error?q.message:"Unknown error"}`}}}function e(j,I={}){let X=I.cwd||process.cwd(),J=M(X,I.keysFile||".env.keys");if(!g(J))return{success:!1,error:`Keys file not found: ${J}`};try{let q=D(J,"utf-8"),{parsed:Q}=C(q),Y=((I.file||".env").split("/").pop()||"").replace(/^\.env\./,"").replace(/^\.env$/,"").toUpperCase(),Z=Y?`DOTENV_PUBLIC_KEY_${Y}`:"DOTENV_PUBLIC_KEY",$=Y?`DOTENV_PRIVATE_KEY_${Y}`:"DOTENV_PRIVATE_KEY";if(j){let W=Q[j];if(!W)return{success:!1,error:`Key not found: ${j}`};return{success:!0,output:W}}let A={[Z]:Q[Z],[$]:Q[$]};return{success:!0,output:I.format==="shell"?`${Z}=${A[Z]} ${$}=${A[$]}`:JSON.stringify(A)}}catch(q){return{success:!1,error:`Failed to get keypair: ${q instanceof Error?q.message:"Unknown error"}`}}}function jj(j={}){let I=d({file:j.file,keysFile:j.keysFile,stdout:!0,cwd:j.cwd});if(!I.success)return I;let X=j.cwd||process.cwd(),J=M(X,j.file||".env"),q=M(X,j.keysFile||".env.keys");if(I.output)L(J,I.output,"utf-8");let Q=F(),z=D(q,"utf-8").split(`
22
+ `),Y=j.file?j.file.replace(/^\.env\./,"").toUpperCase():"",Z=Y?`DOTENV_PUBLIC_KEY_${Y}`:"DOTENV_PUBLIC_KEY",$=Y?`DOTENV_PRIVATE_KEY_${Y}`:"DOTENV_PRIVATE_KEY";for(let A=0;A<z.length;A++){let O=z[A];if(O===void 0)continue;if(O.startsWith(`${Z}=`))z[A]=`${Z}="${Q.publicKey}"`;else if(O.startsWith(`${$}=`))z[A]=`${$}="${Q.privateKey}"`}return L(q,z.join(`
23
23
  `),"utf-8"),k({file:j.file,keysFile:j.keysFile,key:j.key,excludeKey:j.excludeKey,stdout:j.stdout,cwd:j.cwd})}export{i as setEnv,jj as rotateKeypair,e as getKeypair,t as getEnv,k as encryptEnv,d as decryptEnv};
package/dist/index.js CHANGED
@@ -1,25 +1,25 @@
1
1
  // @bun
2
- import{createCipheriv as r,createDecipheriv as s,createHash as E,randomBytes as k}from"crypto";function a(J,Q){let X=k(16),$=Q.length===32?Q:Buffer.from(Q.toString("hex").slice(0,64),"hex"),Z=r("aes-256-gcm",$,X),j=Buffer.concat([Z.update(J,"utf8"),Z.final()]),A=Z.getAuthTag();return{ciphertext:j.toString("hex"),iv:X.toString("hex"),authTag:A.toString("hex")}}function t(J,Q,X,$){let Z=Q.length===32?Q:Buffer.from(Q.toString("hex").slice(0,64),"hex");try{let j=s("aes-256-gcm",Z,Buffer.from(X,"hex"));return j.setAuthTag(Buffer.from($,"hex")),Buffer.concat([j.update(Buffer.from(J,"hex")),j.final()]).toString("utf8")}catch(j){throw Error(`Decryption failed (data may be corrupted or key is incorrect): ${j instanceof Error?j.message:String(j)}`)}}function w(){let J=k(32);return{publicKey:E("sha256").update(J).digest().toString("hex"),privateKey:J.toString("hex")}}function x(J,Q){let X=E("sha256").update(Buffer.from(Q,"hex")).digest(),{ciphertext:$,iv:Z,authTag:j}=a(J,X);return`encrypted:${Buffer.concat([Buffer.from(Z,"hex"),Buffer.from(j,"hex"),Buffer.from($,"hex")]).toString("base64")}`}function b(J,Q){if(!J.startsWith("encrypted:"))return J;let X=J.slice(10),$=Buffer.from(X,"base64");if($.length<32)throw Error("Invalid encrypted data: payload too short (need at least iv + authTag = 32 bytes)");let Z=$.subarray(0,16).toString("hex"),j=$.subarray(16,32).toString("hex"),A=$.subarray(32).toString("hex"),Y=E("sha256").update(Buffer.from(Q,"hex")).digest(),W=E("sha256").update(Y).digest();return t(A,W,Z,j)}function BJ(J){let Q=J.match(/^DOTENV_PRIVATE_KEY_(.+)$/);return Q&&Q[1]?Q[1].toLowerCase():""}function d(J=""){if(!J)return process.env.DOTENV_PRIVATE_KEY;let Q=`DOTENV_PRIVATE_KEY_${J.toUpperCase()}`;return process.env[Q]}function T(J,Q={}){let X={},$=[],Z=J.split(`
3
- `);for(let j of Z){let A=j.trim();if(!A||A.startsWith("#"))continue;if(A.startsWith("DOTENV_PUBLIC_KEY=")){let D=A.match(/^DOTENV_PUBLIC_KEY=["']?([^"'\n]+)["']?/);if(D&&D[1]!==void 0)X.DOTENV_PUBLIC_KEY=D[1];continue}let Y=A.match(/^([^=]+)=(.*)$/);if(!Y||Y[1]===void 0||Y[2]===void 0)continue;let W=Y[1].trim(),G=Y[2].trim();if(G.startsWith('"')&&G.endsWith('"')||G.startsWith("'")&&G.endsWith("'")){if(G=G.slice(1,-1),G.includes("\\n"))G=G.replace(/\\n/g,`
4
- `)}if(Q.privateKey&&(G.startsWith("encrypted:")||G.startsWith("enc:")))try{let D=G.startsWith("enc:")?`encrypted:${G.slice(4)}`:G;G=b(D,Q.privateKey)}catch(D){$.push(`Failed to decrypt ${W}: ${D instanceof Error?D.message:"Unknown error"}`)}G=e(G,{...Q.processEnv||process.env,...X}),G=QJ(G),X[W]=G}return{parsed:X,errors:$}}function e(J,Q){return J.replace(/\$\{([^}]+)\}/g,(X,$)=>{let Z=$.match(/^([^:\-+]+)(:-|-)(.+)$/);if(Z){let[,A,Y,W]=Z,G=Q[A];if(Y===":-")return G||W;else return G!==void 0?G:W}let j=$.match(/^([^:\-+]+)(:?\+)(.+)$/);if(j){let[,A,Y,W]=j,G=Q[A];if(Y===":+")return G?W:"";else return G!==void 0?W:""}return Q[$]||""})}var JJ=new Set(["date","hostname","whoami","uname","pwd","echo","printf","cat","basename","dirname"]);function QJ(J){return J.replace(/\$\(([^)]+)\)/g,(Q,X)=>{try{let $=X.trim().split(/\s+/),Z=$[0];if(!Z||!JJ.has(Z))return console.warn(`[env] Blocked command substitution for disallowed command: ${Z}`),"";let j=Bun.spawnSync($,{stdout:"pipe",stderr:"pipe"});if(j.exitCode===0)return new TextDecoder().decode(j.stdout).trim();console.warn(`[env] Command substitution failed (exit code ${j.exitCode}): ${Z}`)}catch($){console.warn(`[env] Command substitution error: ${$ instanceof Error?$.message:String($)}`)}return""})}async function zJ(J,Q={}){let X={},$=[];for(let Z of J)try{let j=Bun.file(Z);if(!j.size)continue;let A=await j.text(),{parsed:Y,errors:W}=T(A,Q);$.push(...W);for(let[G,D]of Object.entries(Y)){if(!Q.overload&&X[G]!==void 0)continue;X[G]=D}}catch(j){if(j?.code==="ENOENT")continue;$.push(`Failed to read ${Z}: ${j instanceof Error?j.message:String(j)}`)}return{parsed:X,errors:$}}import{existsSync as f}from"fs";import{readFileSync as u}from"fs";import{resolve as N}from"path";function P(J){return typeof J==="string"&&(J.startsWith("encrypted:")||J.startsWith("enc:"))}function S(J){if(!J||P(J))return;let Q=J.trim().toLowerCase();if(!/^[a-z0-9_-]+$/.test(Q))return;if(Q==="prod")return"production";if(Q==="stage")return"staging";if(Q==="dev")return"development";return Q}function c(J={}){let{path:Q=[".env"],overload:X=!1,env:$,privateKey:Z,keysFile:j=".env.keys",quiet:A=!1,cwd:Y=process.cwd()}=J,W=Array.isArray(Q)?Q:[Q],G=[],D=0,M=new Set(Object.entries(process.env).filter(([,O])=>O!==void 0&&!P(O)).map(([O])=>O)),H=Z;if(!H&&j){let O=N(Y,j);if(f(O))try{let U=u(O,"utf-8"),{parsed:_}=T(U);if($){let R=`DOTENV_PRIVATE_KEY_${$.toUpperCase()}`;H=_[R]}else H=_.DOTENV_PRIVATE_KEY}catch(U){G.push(`Failed to load keys file: ${U instanceof Error?U.message:"Unknown error"}`)}}if(!H)H=d($||"");for(let O of W){let U=N(Y,O);if(!f(U)){if(!A)G.push(`File not found: ${U}`);continue}try{let _=u(U,"utf-8"),{parsed:R,errors:q}=T(_,{privateKey:H,processEnv:process.env});G.push(...q);let I=0;for(let[z,g]of Object.entries(R)){if(z==="DOTENV_PUBLIC_KEY")continue;let m=process.env[z],o=P(m)&&g!==m;if(X||!M.has(z)||o)process.env[z]=g,D++,I++}if(!A&&!process.env.__ENV_LOADED__)console.log(`[env] loaded ${I}/${Object.keys(R).length} variables from ${O}`),process.env.__ENV_LOADED__="1"}catch(_){G.push(`Failed to load ${U}: ${_ instanceof Error?_.message:"Unknown error"}`)}}return{loaded:D,errors:G}}function ZJ(J={}){return{name:"env-plugin",setup(Q){c(J)}}}function VJ(J={}){let Q=S(J.env)||S("development")||S(process.env.DOTENV_ENV)||S(process.env.APP_ENV)||"development",X=J.cwd||process.cwd(),$=[],Z=(Y)=>{if(!$.includes(Y)&&f(N(X,Y)))$.push(Y)};Z(".env"),Z(".env.local");let j=`.env.${Q}`,A=`.env.${Q}.local`;return Z(j),Z(A),c({...J,path:$,env:Q})}var EJ=ZJ;import{existsSync as F,readFileSync as L,writeFileSync as V}from"fs";import{resolve as C}from"path";function $J(J={}){let Q=J.cwd||process.cwd(),X=C(Q,J.file||".env"),$=C(Q,J.keysFile||".env.keys");if(!F(X))return{success:!1,error:`File not found: ${X}`};try{let Z,j;if(F($)){let H=L($,"utf-8"),{parsed:O}=T(H),R=((J.file||".env").split("/").pop()||"").replace(/^\.env\./,"").replace(/^\.env$/,"").toUpperCase(),q=R?`DOTENV_PUBLIC_KEY_${R}`:"DOTENV_PUBLIC_KEY",I=R?`DOTENV_PRIVATE_KEY_${R}`:"DOTENV_PRIVATE_KEY";if(Z=O[q]||"",j=O[I]||"",!Z||!j){let z=w();Z=z.publicKey,j=z.privateKey;let g=`
5
- ${q}="${Z}"
6
- ${I}="${j}"
7
- `;V($,H+g,"utf-8")}}else{let H=w();Z=H.publicKey,j=H.privateKey;let _=((J.file||".env").split("/").pop()||"").replace(/^\.env\./,"").replace(/^\.env$/,"").toUpperCase(),R=_?`DOTENV_PUBLIC_KEY_${_}`:"DOTENV_PUBLIC_KEY",q=_?`DOTENV_PRIVATE_KEY_${_}`:"DOTENV_PRIVATE_KEY",I=`# .env.keys - Keep this file secure and never commit to source control
8
- ${R}="${Z}"
9
- ${q}="${j}"
10
- `;V($,I,"utf-8")}let Y=L(X,"utf-8").split(`
11
- `),W=[],G=J.file?J.file.replace(/^\.env\./,"").toUpperCase():"",D=G?`DOTENV_PUBLIC_KEY_${G}`:"DOTENV_PUBLIC_KEY";W.push("#/-------------------[DOTENV_PUBLIC_KEY]--------------------/"),W.push("#/ public-key encryption for .env files /"),W.push("#/ [how it works](https://stacksjs.com/encryption) /"),W.push("#/----------------------------------------------------------/"),W.push(`${D}="${Z}"`),W.push("");for(let H of Y){let O=H.trim();if(!O||O.startsWith("#")){W.push(H);continue}if(O.startsWith("DOTENV_PUBLIC_KEY"))continue;let U=O.match(/^([^=]+)=(.*)$/);if(!U||U[1]===void 0||U[2]===void 0){W.push(H);continue}let _=U[1].trim(),R=U[2].trim();if(R.startsWith('"')&&R.endsWith('"')||R.startsWith("'")&&R.endsWith("'"))R=R.slice(1,-1);let q=!0;if(J.key&&!_.includes(J.key))q=!1;if(J.excludeKey&&_.includes(J.excludeKey))q=!1;if(R.startsWith("encrypted:"))q=!1;if(q)R=x(R,Z);W.push(`${_}="${R}"`)}let M=W.join(`
12
- `);if(J.stdout)return{success:!0,output:M};return V(X,M,"utf-8"),{success:!0,output:`\u2714 encrypted (${J.file||".env"})
13
- \u2714 key added to ${J.keysFile||".env.keys"}`}}catch(Z){return{success:!1,error:`Failed to encrypt: ${Z instanceof Error?Z.message:"Unknown error"}`}}}function XJ(J={}){let Q=J.cwd||process.cwd(),X=C(Q,J.file||".env"),$=C(Q,J.keysFile||".env.keys");if(!F(X))return{success:!1,error:`File not found: ${X}`};if(!F($))return{success:!1,error:`Keys file not found: ${$}`};try{let Z=L($,"utf-8"),{parsed:j}=T(Z),W=((J.file||".env").split("/").pop()||"").replace(/^\.env\./,"").replace(/^\.env$/,"").toUpperCase(),G=W?`DOTENV_PRIVATE_KEY_${W}`:"DOTENV_PRIVATE_KEY",D=j[G];if(!D)return{success:!1,error:`Private key not found: ${G}`};let H=L(X,"utf-8").split(`
14
- `),O=[];for(let _ of H){let R=_.trim();if(!R||R.startsWith("#")){O.push(_);continue}if(R.startsWith("DOTENV_PUBLIC_KEY"))continue;let q=R.match(/^([^=]+)=(.*)$/);if(!q||q[1]===void 0||q[2]===void 0){O.push(_);continue}let I=q[1].trim(),z=q[2].trim();if(z.startsWith('"')&&z.endsWith('"')||z.startsWith("'")&&z.endsWith("'"))z=z.slice(1,-1);let g=z.startsWith("encrypted:");if(J.key&&!I.includes(J.key))g=!1;if(g)z=b(z,D);O.push(`${I}="${z}"`)}let U=O.join(`
15
- `);if(J.stdout)return{success:!0,output:U};return V(X,U,"utf-8"),{success:!0,output:`\u2714 decrypted (${J.file||".env"})`}}catch(Z){return{success:!1,error:`Failed to decrypt: ${Z instanceof Error?Z.message:"Unknown error"}`}}}function NJ(J,Q,X={}){let $=X.cwd||process.cwd(),Z=C($,X.file||".env"),j=C($,X.keysFile||".env.keys");try{let A="";if(F(Z))A=L(Z,"utf-8");let Y=A.split(`
16
- `),W=!1,G,H=((X.file||".env").split("/").pop()||"").replace(/^\.env\./,"").replace(/^\.env$/,"").toUpperCase(),O=H?`DOTENV_PUBLIC_KEY_${H}`:"DOTENV_PUBLIC_KEY",U=H?`DOTENV_PRIVATE_KEY_${H}`:"DOTENV_PRIVATE_KEY";for(let q of Y){let I=q.trim();if(I.startsWith(`${O}=`)){let z=I.match(/^[^=]+=["']?([^"'\n]+)["']?/);if(z)G=z[1];break}}if(G){let q=!1;if(F(j)){let I=L(j,"utf-8"),{parsed:z}=T(I);q=Boolean(z[U])}if(!q)G=void 0}if(!X.plain&&!G){let q=w();G=q.publicKey;let I="";if(F(j))I=L(j,"utf-8");I+=`
17
- ${O}="${q.publicKey}"
18
- ${U}="${q.privateKey}"
19
- `,V(j,I,"utf-8");for(let z=Y.length-1;z>=0;z--){let g=Y[z];if(g!==void 0&&g.trim().startsWith(`${O}=`))Y.splice(z,1)}Y.unshift(`${O}="${G}"`)}let _=Q;if(!X.plain&&G)_=x(Q,G);for(let q=0;q<Y.length;q++){let I=Y[q];if(I===void 0)continue;if(I.trim().startsWith(`${J}=`)){Y[q]=`${J}="${_}"`,W=!0;break}}if(!W)Y.push(`${J}="${_}"`);let R=Y.join(`
20
- `);return V(Z,R,"utf-8"),{success:!0,output:`set ${J}${X.plain?"":" with encryption"} (${X.file||".env"})`}}catch(A){return{success:!1,error:`Failed to set: ${A instanceof Error?A.message:"Unknown error"}`}}}function PJ(J,Q={}){let X=Q.cwd||process.cwd(),$=C(X,Q.file||".env");if(!F($))return{success:!1,error:`File not found: ${$}`};try{let Z,j=C(X,Q.keysFile||".env.keys"),W=((Q.file||".env").split("/").pop()||"").replace(/^\.env\./,"").replace(/^\.env$/,"").toUpperCase(),G=W?`DOTENV_PRIVATE_KEY_${W}`:"DOTENV_PRIVATE_KEY";if(F(j)){let U=L(j,"utf-8"),{parsed:_}=T(U);Z=_[G]}if(!Z)Z=process.env[G];let D=L($,"utf-8"),{parsed:M}=T(D,{privateKey:Z});if(J&&!Q.all){let U=M[J];if(U===void 0)return{success:!1,error:`Key not found: ${J}`};return{success:!0,output:U}}let H=Q.all?{...process.env,...M}:M,O;switch(Q.format){case"shell":O=Object.entries(H).map(([U,_])=>`${U}=${_}`).join(" ");break;case"eval":O=Object.entries(H).map(([U,_])=>`${U}="${_}"`).join(`
21
- `);break;case"json":default:O=Q.prettyPrint?JSON.stringify(H,null,2):JSON.stringify(H);break}return{success:!0,output:O}}catch(Z){return{success:!1,error:`Failed to get: ${Z instanceof Error?Z.message:"Unknown error"}`}}}function KJ(J,Q={}){let X=Q.cwd||process.cwd(),$=C(X,Q.keysFile||".env.keys");if(!F($))return{success:!1,error:`Keys file not found: ${$}`};try{let Z=L($,"utf-8"),{parsed:j}=T(Z),W=((Q.file||".env").split("/").pop()||"").replace(/^\.env\./,"").replace(/^\.env$/,"").toUpperCase(),G=W?`DOTENV_PUBLIC_KEY_${W}`:"DOTENV_PUBLIC_KEY",D=W?`DOTENV_PRIVATE_KEY_${W}`:"DOTENV_PRIVATE_KEY";if(J){let O=j[J];if(!O)return{success:!1,error:`Key not found: ${J}`};return{success:!0,output:O}}let M={[G]:j[G],[D]:j[D]};return{success:!0,output:Q.format==="shell"?`${G}=${M[G]} ${D}=${M[D]}`:JSON.stringify(M)}}catch(Z){return{success:!1,error:`Failed to get keypair: ${Z instanceof Error?Z.message:"Unknown error"}`}}}function hJ(J={}){let Q=XJ({file:J.file,keysFile:J.keysFile,stdout:!0,cwd:J.cwd});if(!Q.success)return Q;let X=J.cwd||process.cwd(),$=C(X,J.file||".env"),Z=C(X,J.keysFile||".env.keys");if(Q.output)V($,Q.output,"utf-8");let j=w(),Y=L(Z,"utf-8").split(`
22
- `),W=J.file?J.file.replace(/^\.env\./,"").toUpperCase():"",G=W?`DOTENV_PUBLIC_KEY_${W}`:"DOTENV_PUBLIC_KEY",D=W?`DOTENV_PRIVATE_KEY_${W}`:"DOTENV_PRIVATE_KEY";for(let M=0;M<Y.length;M++){let H=Y[M];if(H===void 0)continue;if(H.startsWith(`${G}=`))Y[M]=`${G}="${j.publicKey}"`;else if(H.startsWith(`${D}=`))Y[M]=`${D}="${j.privateKey}"`}return V(Z,Y.join(`
23
- `),"utf-8"),$J({file:J.file,keysFile:J.keysFile,key:J.key,excludeKey:J.excludeKey,stdout:J.stdout,cwd:J.cwd})}import B from"process";import{platform as jJ}from"os";var v=typeof Bun<"u",y=typeof B<"u"&&B.versions?.node!==void 0,GJ=v?"bun":y?"node":"unknown",uJ={name:GJ,version:v?Bun.version:y?B.version:void 0},h=jJ(),cJ=h==="win32",vJ=h==="darwin",yJ=h==="linux",l=Boolean(B.stdout?.isTTY),lJ=typeof globalThis.window<"u",WJ=Boolean(B.env.CI||B.env.CONTINUOUS_INTEGRATION||B.env.BUILD_NUMBER||B.env.RUN_ID),pJ=Boolean(B.env.DEBUG||B.env.VERBOSE||B.argv.includes("--debug")||B.argv.includes("--verbose")),YJ=WJ||!l,iJ=Boolean(!YJ&&(l||B.env.COLORTERM||B.env.FORCE_COLOR||B.env.TERM&&B.env.TERM!=="dumb")),K={github:{name:"GitHub Actions",detected:Boolean(B.env.GITHUB_ACTIONS)},gitlab:{name:"GitLab CI",detected:Boolean(B.env.GITLAB_CI)},circle:{name:"CircleCI",detected:Boolean(B.env.CIRCLECI)},travis:{name:"Travis CI",detected:Boolean(B.env.TRAVIS)},jenkins:{name:"Jenkins",detected:Boolean(B.env.JENKINS_URL)},vercel:{name:"Vercel",detected:Boolean(B.env.VERCEL)},netlify:{name:"Netlify",detected:Boolean(B.env.NETLIFY)},heroku:{name:"Heroku",detected:Boolean(B.env.DYNO)},aws:{name:"AWS",detected:Boolean(B.env.AWS_REGION||B.env.AWS_LAMBDA_FUNCTION_NAME)},azure:{name:"Azure",detected:Boolean(B.env.AZURE_HTTP_USER_AGENT)},cloudflare:{name:"Cloudflare",detected:Boolean(B.env.CF_PAGES)},railway:{name:"Railway",detected:Boolean(B.env.RAILWAY_ENVIRONMENT)},render:{name:"Render",detected:Boolean(B.env.RENDER)}},OJ=Object.keys(K).find((J)=>{let Q=K[J];return Q!==void 0&&Q.detected})||"unknown",nJ=K[OJ]||{name:"Unknown",detected:!1};import AJ from"process";import{projectPath as HJ}from"@stacksjs/path";import i from"fs";var p={APP_ENV:["local","dev","development","staging","prod","production"],DB_CONNECTION:["mysql","sqlite","postgres","dynamodb"],DB_MIGRATE_FRESH:["allow","confirm","disabled"],MAIL_MAILER:["smtp","mailgun","ses","log","sendgrid","mailtrap"],SEARCH_ENGINE_DRIVER:["opensearch","meilisearch","algolia","typesense"],FRONTEND_APP_ENV:["development","staging","production"]};var UJ={get:(J,Q)=>{let X=J[Q],$=["_PORT","_TIMEOUT","_TTL","_SIZE","_LIMIT","_MAX","_MIN","_INTERVAL","_RETRIES","_CONCURRENCY","_WORKERS","_CONNECTIONS"];if(typeof X==="string"&&/^\d+$/.test(X)&&!X.startsWith("0")&&$.some((Z)=>Q.endsWith(Z)))return Number(X);if(typeof X==="string"){let Z=X.toLowerCase();if(Z==="true")return!0;if(Z==="false")return!1}return X}};function _J(){return typeof Bun<"u"?Bun.env:AJ.env}var n=new Proxy(_J(),UJ);function JQ(J,Q,X){let $=X?.path||HJ(".env"),j=i.readFileSync($,"utf-8").split(`
24
- `),A=j.findIndex((G)=>G.startsWith(`${J}=`)),W=/[\s"'#$\\]/.test(Q)?`"${Q.replace(/"/g,"\\\"")}"`:Q;if(A!==-1)j[A]=`${J}=${W}`;else j.push(`${J}=${W}`);i.writeFileSync($,j.join(`
25
- `))}function QQ(J=n){let Q=[];for(let[X,$]of Object.entries(p)){let Z=J[X];if(Z!==void 0&&Z!==""&&!$.includes(String(Z)))Q.push(`${X}="${Z}" is not valid. Allowed values: ${$.join(", ")}`)}return Q}function ZQ(J,Q=n){let X=[];for(let $ of J){let Z=Q[$];if(Z===void 0||Z===""||Z===null)X.push($)}if(X.length>0)throw Error(`[env] Missing required environment variable(s): ${X.join(", ")}. Set them in .env or your process environment before booting.`);return Q}export{JQ as writeEnv,QQ as validateEnv,NJ as setEnv,uJ as runtimeInfo,GJ as runtime,hJ as rotateKeypair,ZQ as requireEnv,nJ as providerInfo,OJ as provider,_J as process,h as platform,BJ as parseEnvFromKey,T as parse,zJ as loadEnvFiles,c as loadEnv,cJ as isWindows,y as isNode,YJ as isMinimal,vJ as isMacOS,yJ as isLinux,pJ as isDebug,iJ as isColorSupported,WJ as isCI,v as isBun,lJ as hasWindow,l as hasTTY,d as getPrivateKey,KJ as getKeypair,PJ as getEnv,w as generateKeypair,ZJ as envPlugin,p as envEnum,n as env,x as encryptValue,$J as encryptEnv,b as decryptValue,XJ as decryptEnv,VJ as autoLoadEnv,a as aesEncrypt,t as aesDecrypt};
2
+ import{createCipheriv as s,createDecipheriv as a,createHash as E,randomBytes as u}from"crypto";function t(J,Q){let X=u(16),$=Q.length===32?Q:Buffer.from(Q.toString("hex").slice(0,64),"hex"),Z=s("aes-256-gcm",$,X),j=Buffer.concat([Z.update(J,"utf8"),Z.final()]),A=Z.getAuthTag();return{ciphertext:j.toString("hex"),iv:X.toString("hex"),authTag:A.toString("hex")}}function e(J,Q,X,$){let Z=Q.length===32?Q:Buffer.from(Q.toString("hex").slice(0,64),"hex");try{let j=a("aes-256-gcm",Z,Buffer.from(X,"hex"));return j.setAuthTag(Buffer.from($,"hex")),Buffer.concat([j.update(Buffer.from(J,"hex")),j.final()]).toString("utf8")}catch(j){throw Error(`Decryption failed (data may be corrupted or key is incorrect): ${j instanceof Error?j.message:String(j)}`)}}function w(){let J=u(32);return{publicKey:E("sha256").update(J).digest().toString("hex"),privateKey:J.toString("hex")}}function K(J,Q){let X=E("sha256").update(Buffer.from(Q,"hex")).digest(),{ciphertext:$,iv:Z,authTag:j}=t(J,X);return`encrypted:${Buffer.concat([Buffer.from(Z,"hex"),Buffer.from(j,"hex"),Buffer.from($,"hex")]).toString("base64")}`}function f(J,Q){if(!J.startsWith("encrypted:"))return J;let X=J.slice(10),$=Buffer.from(X,"base64");if($.length<32)throw Error("Invalid encrypted data: payload too short (need at least iv + authTag = 32 bytes)");let Z=$.subarray(0,16).toString("hex"),j=$.subarray(16,32).toString("hex"),A=$.subarray(32).toString("hex"),Y=E("sha256").update(Buffer.from(Q,"hex")).digest(),G=E("sha256").update(Y).digest();return e(A,G,Z,j)}function DJ(J){let Q=J.match(/^DOTENV_PRIVATE_KEY_(.+)$/);return Q&&Q[1]?Q[1].toLowerCase():""}function c(J=""){if(!J)return process.env.DOTENV_PRIVATE_KEY;let Q=`DOTENV_PRIVATE_KEY_${J.toUpperCase()}`;return process.env[Q]}function L(J,Q={}){let X={},$=[],Z=[],j=J.split(`
3
+ `);for(let A of j){let Y=A.trim();if(!Y||Y.startsWith("#"))continue;if(Y.startsWith("DOTENV_PUBLIC_KEY=")){let _=Y.match(/^DOTENV_PUBLIC_KEY=["']?([^"'\n]+)["']?/);if(_&&_[1]!==void 0)X.DOTENV_PUBLIC_KEY=_[1];continue}let G=Y.match(/^([^=]+)=(.*)$/);if(!G||G[1]===void 0||G[2]===void 0)continue;let W=G[1].trim(),O=G[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(!Q.privateKey){Z.push(W);continue}try{let _=O.startsWith("enc:")?`encrypted:${O.slice(4)}`:O;O=f(_,Q.privateKey)}catch(_){$.push(`Failed to decrypt ${W}: ${_ instanceof Error?_.message:"Unknown error"}`)}}O=JJ(O,{...Q.processEnv||process.env,...X}),O=ZJ(O),X[W]=O}return{parsed:X,errors:$,skippedEncrypted:Z}}function JJ(J,Q){return J.replace(/\$\{([^}]+)\}/g,(X,$)=>{let Z=$.match(/^([^:\-+]+)(:-|-)(.+)$/);if(Z){let[,A,Y,G]=Z,W=Q[A];if(Y===":-")return W||G;else return W!==void 0?W:G}let j=$.match(/^([^:\-+]+)(:?\+)(.+)$/);if(j){let[,A,Y,G]=j,W=Q[A];if(Y===":+")return W?G:"";else return W!==void 0?G:""}return Q[$]||""})}var QJ=new Set(["date","hostname","whoami","uname","pwd","echo","printf","cat","basename","dirname"]);function ZJ(J){return J.replace(/\$\(([^)]+)\)/g,(Q,X)=>{try{let $=X.trim().split(/\s+/),Z=$[0];if(!Z||!QJ.has(Z))return console.warn(`[env] Blocked command substitution for disallowed command: ${Z}`),"";let j=Bun.spawnSync($,{stdout:"pipe",stderr:"pipe"});if(j.exitCode===0)return new TextDecoder().decode(j.stdout).trim();console.warn(`[env] Command substitution failed (exit code ${j.exitCode}): ${Z}`)}catch($){console.warn(`[env] Command substitution error: ${$ instanceof Error?$.message:String($)}`)}return""})}async function IJ(J,Q={}){let X={},$=[],Z=[];for(let j of J)try{let A=Bun.file(j);if(!A.size)continue;let Y=await A.text(),{parsed:G,errors:W,skippedEncrypted:O}=L(Y,Q);$.push(...W),Z.push(...O);for(let[_,U]of Object.entries(G)){if(!Q.overload&&X[_]!==void 0)continue;X[_]=U}}catch(A){if(A?.code==="ENOENT")continue;$.push(`Failed to read ${j}: ${A instanceof Error?A.message:String(A)}`)}return{parsed:X,errors:$,skippedEncrypted:Z}}import{existsSync as h}from"fs";import{readFileSync as v}from"fs";import{resolve as m}from"path";function P(J){return typeof J==="string"&&(J.startsWith("encrypted:")||J.startsWith("enc:"))}function N(J){if(!J||P(J))return;let Q=J.trim().toLowerCase();if(!/^[a-z0-9_-]+$/.test(Q))return;if(Q==="prod")return"production";if(Q==="stage")return"staging";if(Q==="dev")return"development";return Q}function y(J={}){let{path:Q=[".env"],overload:X=!1,env:$,privateKey:Z,keysFile:j=".env.keys",quiet:A=!1,cwd:Y=process.cwd()}=J,G=Array.isArray(Q)?Q:[Q],W=[],O=0,_=new Set(Object.entries(process.env).filter(([,H])=>H!==void 0&&!P(H)).map(([H])=>H)),U=Z;if(!U&&j){let H=m(Y,j);if(h(H))try{let q=v(H,"utf-8"),{parsed:B}=L(q);if($){let z=`DOTENV_PRIVATE_KEY_${$.toUpperCase()}`;U=B[z]}else U=B.DOTENV_PRIVATE_KEY}catch(q){W.push(`Failed to load keys file: ${q instanceof Error?q.message:"Unknown error"}`)}}if(!U)U=c($||"");for(let H of G){let q=m(Y,H);if(!h(q)){if(!A)W.push(`File not found: ${q}`);continue}try{let B=v(q,"utf-8"),{parsed:z,errors:D,skippedEncrypted:M}=L(B,{privateKey:U,processEnv:process.env});if(W.push(...D),M.length>0){for(let S of M)if(P(process.env[S]))delete process.env[S];let T=$?`DOTENV_PRIVATE_KEY_${$.toUpperCase()}`:"DOTENV_PRIVATE_KEY",b=M.slice(0,5).join(", "),x=M.length>5?`, \u2026 +${M.length-5} more`:"";console.warn(`[env] warning: skipped ${M.length} encrypted value(s) in ${H} (${T} not set; defaults apply): ${b}${x}`)}let I=0;for(let[T,b]of Object.entries(z)){if(T==="DOTENV_PUBLIC_KEY")continue;let x=process.env[T],S=P(x)&&b!==x;if(X||!_.has(T)||S)process.env[T]=b,O++,I++}if(!A&&!process.env.__ENV_LOADED__)console.log(`[env] loaded ${I}/${Object.keys(z).length} variables from ${H}`),process.env.__ENV_LOADED__="1"}catch(B){W.push(`Failed to load ${q}: ${B instanceof Error?B.message:"Unknown error"}`)}}return{loaded:O,errors:W}}function $J(J={}){return{name:"env-plugin",setup(Q){y(J)}}}function wJ(J={}){let Q=N(J.env)||N("development")||N(process.env.DOTENV_ENV)||N(process.env.APP_ENV)||"development",X=J.cwd||process.cwd(),$=[],Z=(Y)=>{if(!$.includes(Y)&&h(m(X,Y)))$.push(Y)};Z(".env"),Z(".env.local");let j=`.env.${Q}`,A=`.env.${Q}.local`;return Z(j),Z(A),y({...J,path:$,env:Q})}var xJ=$J;import{existsSync as F,readFileSync as C,writeFileSync as V}from"fs";import{resolve as g}from"path";function XJ(J={}){let Q=J.cwd||process.cwd(),X=g(Q,J.file||".env"),$=g(Q,J.keysFile||".env.keys");if(!F(X))return{success:!1,error:`File not found: ${X}`};try{let Z,j;if(F($)){let U=C($,"utf-8"),{parsed:H}=L(U),z=((J.file||".env").split("/").pop()||"").replace(/^\.env\./,"").replace(/^\.env$/,"").toUpperCase(),D=z?`DOTENV_PUBLIC_KEY_${z}`:"DOTENV_PUBLIC_KEY",M=z?`DOTENV_PRIVATE_KEY_${z}`:"DOTENV_PRIVATE_KEY";if(Z=H[D]||"",j=H[M]||"",!Z||!j){let I=w();Z=I.publicKey,j=I.privateKey;let T=`
5
+ ${D}="${Z}"
6
+ ${M}="${j}"
7
+ `;V($,U+T,"utf-8")}}else{let U=w();Z=U.publicKey,j=U.privateKey;let B=((J.file||".env").split("/").pop()||"").replace(/^\.env\./,"").replace(/^\.env$/,"").toUpperCase(),z=B?`DOTENV_PUBLIC_KEY_${B}`:"DOTENV_PUBLIC_KEY",D=B?`DOTENV_PRIVATE_KEY_${B}`:"DOTENV_PRIVATE_KEY",M=`# .env.keys - Keep this file secure and never commit to source control
8
+ ${z}="${Z}"
9
+ ${D}="${j}"
10
+ `;V($,M,"utf-8")}let Y=C(X,"utf-8").split(`
11
+ `),G=[],W=J.file?J.file.replace(/^\.env\./,"").toUpperCase():"",O=W?`DOTENV_PUBLIC_KEY_${W}`:"DOTENV_PUBLIC_KEY";G.push("#/-------------------[DOTENV_PUBLIC_KEY]--------------------/"),G.push("#/ public-key encryption for .env files /"),G.push("#/ [how it works](https://stacksjs.com/encryption) /"),G.push("#/----------------------------------------------------------/"),G.push(`${O}="${Z}"`),G.push("");for(let U of Y){let H=U.trim();if(!H||H.startsWith("#")){G.push(U);continue}if(H.startsWith("DOTENV_PUBLIC_KEY"))continue;let q=H.match(/^([^=]+)=(.*)$/);if(!q||q[1]===void 0||q[2]===void 0){G.push(U);continue}let B=q[1].trim(),z=q[2].trim();if(z.startsWith('"')&&z.endsWith('"')||z.startsWith("'")&&z.endsWith("'"))z=z.slice(1,-1);let D=!0;if(J.key&&!B.includes(J.key))D=!1;if(J.excludeKey&&B.includes(J.excludeKey))D=!1;if(z.startsWith("encrypted:"))D=!1;if(D)z=K(z,Z);G.push(`${B}="${z}"`)}let _=G.join(`
12
+ `);if(J.stdout)return{success:!0,output:_};return V(X,_,"utf-8"),{success:!0,output:`\u2714 encrypted (${J.file||".env"})
13
+ \u2714 key added to ${J.keysFile||".env.keys"}`}}catch(Z){return{success:!1,error:`Failed to encrypt: ${Z instanceof Error?Z.message:"Unknown error"}`}}}function jJ(J={}){let Q=J.cwd||process.cwd(),X=g(Q,J.file||".env"),$=g(Q,J.keysFile||".env.keys");if(!F(X))return{success:!1,error:`File not found: ${X}`};if(!F($))return{success:!1,error:`Keys file not found: ${$}`};try{let Z=C($,"utf-8"),{parsed:j}=L(Z),G=((J.file||".env").split("/").pop()||"").replace(/^\.env\./,"").replace(/^\.env$/,"").toUpperCase(),W=G?`DOTENV_PRIVATE_KEY_${G}`:"DOTENV_PRIVATE_KEY",O=j[W];if(!O)return{success:!1,error:`Private key not found: ${W}`};let U=C(X,"utf-8").split(`
14
+ `),H=[];for(let B of U){let z=B.trim();if(!z||z.startsWith("#")){H.push(B);continue}if(z.startsWith("DOTENV_PUBLIC_KEY"))continue;let D=z.match(/^([^=]+)=(.*)$/);if(!D||D[1]===void 0||D[2]===void 0){H.push(B);continue}let M=D[1].trim(),I=D[2].trim();if(I.startsWith('"')&&I.endsWith('"')||I.startsWith("'")&&I.endsWith("'"))I=I.slice(1,-1);let T=I.startsWith("encrypted:");if(J.key&&!M.includes(J.key))T=!1;if(T)I=f(I,O);H.push(`${M}="${I}"`)}let q=H.join(`
15
+ `);if(J.stdout)return{success:!0,output:q};return V(X,q,"utf-8"),{success:!0,output:`\u2714 decrypted (${J.file||".env"})`}}catch(Z){return{success:!1,error:`Failed to decrypt: ${Z instanceof Error?Z.message:"Unknown error"}`}}}function PJ(J,Q,X={}){let $=X.cwd||process.cwd(),Z=g($,X.file||".env"),j=g($,X.keysFile||".env.keys");try{let A="";if(F(Z))A=C(Z,"utf-8");let Y=A.split(`
16
+ `),G=!1,W,U=((X.file||".env").split("/").pop()||"").replace(/^\.env\./,"").replace(/^\.env$/,"").toUpperCase(),H=U?`DOTENV_PUBLIC_KEY_${U}`:"DOTENV_PUBLIC_KEY",q=U?`DOTENV_PRIVATE_KEY_${U}`:"DOTENV_PRIVATE_KEY";for(let D of Y){let M=D.trim();if(M.startsWith(`${H}=`)){let I=M.match(/^[^=]+=["']?([^"'\n]+)["']?/);if(I)W=I[1];break}}if(W){let D=!1;if(F(j)){let M=C(j,"utf-8"),{parsed:I}=L(M);D=Boolean(I[q])}if(!D)W=void 0}if(!X.plain&&!W){let D=w();W=D.publicKey;let M="";if(F(j))M=C(j,"utf-8");M+=`
17
+ ${H}="${D.publicKey}"
18
+ ${q}="${D.privateKey}"
19
+ `,V(j,M,"utf-8");for(let I=Y.length-1;I>=0;I--){let T=Y[I];if(T!==void 0&&T.trim().startsWith(`${H}=`))Y.splice(I,1)}Y.unshift(`${H}="${W}"`)}let B=Q;if(!X.plain&&W)B=K(Q,W);for(let D=0;D<Y.length;D++){let M=Y[D];if(M===void 0)continue;if(M.trim().startsWith(`${J}=`)){Y[D]=`${J}="${B}"`,G=!0;break}}if(!G)Y.push(`${J}="${B}"`);let z=Y.join(`
20
+ `);return V(Z,z,"utf-8"),{success:!0,output:`set ${J}${X.plain?"":" with encryption"} (${X.file||".env"})`}}catch(A){return{success:!1,error:`Failed to set: ${A instanceof Error?A.message:"Unknown error"}`}}}function KJ(J,Q={}){let X=Q.cwd||process.cwd(),$=g(X,Q.file||".env");if(!F($))return{success:!1,error:`File not found: ${$}`};try{let Z,j=g(X,Q.keysFile||".env.keys"),G=((Q.file||".env").split("/").pop()||"").replace(/^\.env\./,"").replace(/^\.env$/,"").toUpperCase(),W=G?`DOTENV_PRIVATE_KEY_${G}`:"DOTENV_PRIVATE_KEY";if(F(j)){let q=C(j,"utf-8"),{parsed:B}=L(q);Z=B[W]}if(!Z)Z=process.env[W];let O=C($,"utf-8"),{parsed:_}=L(O,{privateKey:Z});if(J&&!Q.all){let q=_[J];if(q===void 0)return{success:!1,error:`Key not found: ${J}`};return{success:!0,output:q}}let U=Q.all?{...process.env,..._}:_,H;switch(Q.format){case"shell":H=Object.entries(U).map(([q,B])=>`${q}=${B}`).join(" ");break;case"eval":H=Object.entries(U).map(([q,B])=>`${q}="${B}"`).join(`
21
+ `);break;case"json":default:H=Q.prettyPrint?JSON.stringify(U,null,2):JSON.stringify(U);break}return{success:!0,output:H}}catch(Z){return{success:!1,error:`Failed to get: ${Z instanceof Error?Z.message:"Unknown error"}`}}}function hJ(J,Q={}){let X=Q.cwd||process.cwd(),$=g(X,Q.keysFile||".env.keys");if(!F($))return{success:!1,error:`Keys file not found: ${$}`};try{let Z=C($,"utf-8"),{parsed:j}=L(Z),G=((Q.file||".env").split("/").pop()||"").replace(/^\.env\./,"").replace(/^\.env$/,"").toUpperCase(),W=G?`DOTENV_PUBLIC_KEY_${G}`:"DOTENV_PUBLIC_KEY",O=G?`DOTENV_PRIVATE_KEY_${G}`:"DOTENV_PRIVATE_KEY";if(J){let H=j[J];if(!H)return{success:!1,error:`Key not found: ${J}`};return{success:!0,output:H}}let _={[W]:j[W],[O]:j[O]};return{success:!0,output:Q.format==="shell"?`${W}=${_[W]} ${O}=${_[O]}`:JSON.stringify(_)}}catch(Z){return{success:!1,error:`Failed to get keypair: ${Z instanceof Error?Z.message:"Unknown error"}`}}}function mJ(J={}){let Q=jJ({file:J.file,keysFile:J.keysFile,stdout:!0,cwd:J.cwd});if(!Q.success)return Q;let X=J.cwd||process.cwd(),$=g(X,J.file||".env"),Z=g(X,J.keysFile||".env.keys");if(Q.output)V($,Q.output,"utf-8");let j=w(),Y=C(Z,"utf-8").split(`
22
+ `),G=J.file?J.file.replace(/^\.env\./,"").toUpperCase():"",W=G?`DOTENV_PUBLIC_KEY_${G}`:"DOTENV_PUBLIC_KEY",O=G?`DOTENV_PRIVATE_KEY_${G}`:"DOTENV_PRIVATE_KEY";for(let _=0;_<Y.length;_++){let U=Y[_];if(U===void 0)continue;if(U.startsWith(`${W}=`))Y[_]=`${W}="${j.publicKey}"`;else if(U.startsWith(`${O}=`))Y[_]=`${O}="${j.privateKey}"`}return V(Z,Y.join(`
23
+ `),"utf-8"),XJ({file:J.file,keysFile:J.keysFile,key:J.key,excludeKey:J.excludeKey,stdout:J.stdout,cwd:J.cwd})}import R from"process";import{platform as GJ}from"os";var l=typeof Bun<"u",p=typeof R<"u"&&R.versions?.node!==void 0,WJ=l?"bun":p?"node":"unknown",cJ={name:WJ,version:l?Bun.version:p?R.version:void 0},d=GJ(),vJ=d==="win32",yJ=d==="darwin",lJ=d==="linux",o=Boolean(R.stdout?.isTTY),pJ=typeof globalThis.window<"u",YJ=Boolean(R.env.CI||R.env.CONTINUOUS_INTEGRATION||R.env.BUILD_NUMBER||R.env.RUN_ID),oJ=Boolean(R.env.DEBUG||R.env.VERBOSE||R.argv.includes("--debug")||R.argv.includes("--verbose")),OJ=YJ||!o,iJ=Boolean(!OJ&&(o||R.env.COLORTERM||R.env.FORCE_COLOR||R.env.TERM&&R.env.TERM!=="dumb")),k={github:{name:"GitHub Actions",detected:Boolean(R.env.GITHUB_ACTIONS)},gitlab:{name:"GitLab CI",detected:Boolean(R.env.GITLAB_CI)},circle:{name:"CircleCI",detected:Boolean(R.env.CIRCLECI)},travis:{name:"Travis CI",detected:Boolean(R.env.TRAVIS)},jenkins:{name:"Jenkins",detected:Boolean(R.env.JENKINS_URL)},vercel:{name:"Vercel",detected:Boolean(R.env.VERCEL)},netlify:{name:"Netlify",detected:Boolean(R.env.NETLIFY)},heroku:{name:"Heroku",detected:Boolean(R.env.DYNO)},aws:{name:"AWS",detected:Boolean(R.env.AWS_REGION||R.env.AWS_LAMBDA_FUNCTION_NAME)},azure:{name:"Azure",detected:Boolean(R.env.AZURE_HTTP_USER_AGENT)},cloudflare:{name:"Cloudflare",detected:Boolean(R.env.CF_PAGES)},railway:{name:"Railway",detected:Boolean(R.env.RAILWAY_ENVIRONMENT)},render:{name:"Render",detected:Boolean(R.env.RENDER)}},AJ=Object.keys(k).find((J)=>{let Q=k[J];return Q!==void 0&&Q.detected})||"unknown",nJ=k[AJ]||{name:"Unknown",detected:!1};import HJ from"process";import{projectPath as UJ}from"@stacksjs/path";import n from"fs";var i={APP_ENV:["local","dev","development","staging","prod","production"],DB_CONNECTION:["mysql","sqlite","postgres","dynamodb"],DB_MIGRATE_FRESH:["allow","confirm","disabled"],MAIL_MAILER:["smtp","mailgun","ses","log","sendgrid","mailtrap"],SEARCH_ENGINE_DRIVER:["opensearch","meilisearch","algolia","typesense"],FRONTEND_APP_ENV:["development","staging","production"]};var _J={get:(J,Q)=>{let X=J[Q],$=["_PORT","_TIMEOUT","_TTL","_SIZE","_LIMIT","_MAX","_MIN","_INTERVAL","_RETRIES","_CONCURRENCY","_WORKERS","_CONNECTIONS"];if(typeof X==="string"&&/^\d+$/.test(X)&&!X.startsWith("0")&&$.some((Z)=>Q.endsWith(Z)))return Number(X);if(typeof X==="string"){let Z=X.toLowerCase();if(Z==="true")return!0;if(Z==="false")return!1}return X}};function qJ(){return typeof Bun<"u"?Bun.env:HJ.env}var r=new Proxy(qJ(),_J);function QQ(J,Q,X){let $=X?.path||UJ(".env"),j=n.readFileSync($,"utf-8").split(`
24
+ `),A=j.findIndex((W)=>W.startsWith(`${J}=`)),G=/[\s"'#$\\]/.test(Q)?`"${Q.replace(/"/g,"\\\"")}"`:Q;if(A!==-1)j[A]=`${J}=${G}`;else j.push(`${J}=${G}`);n.writeFileSync($,j.join(`
25
+ `))}function ZQ(J=r){let Q=[];for(let[X,$]of Object.entries(i)){let Z=J[X];if(Z!==void 0&&Z!==""&&!$.includes(String(Z)))Q.push(`${X}="${Z}" is not valid. Allowed values: ${$.join(", ")}`)}return Q}function $Q(J,Q=r){let X=[];for(let $ of J){let Z=Q[$];if(Z===void 0||Z===""||Z===null)X.push($)}if(X.length>0)throw Error(`[env] Missing required environment variable(s): ${X.join(", ")}. Set them in .env or your process environment before booting.`);return Q}export{QQ as writeEnv,ZQ as validateEnv,PJ as setEnv,cJ as runtimeInfo,WJ as runtime,mJ as rotateKeypair,$Q as requireEnv,nJ as providerInfo,AJ as provider,qJ as process,d as platform,DJ as parseEnvFromKey,L as parse,IJ as loadEnvFiles,y as loadEnv,vJ as isWindows,p as isNode,OJ as isMinimal,yJ as isMacOS,lJ as isLinux,oJ as isDebug,iJ as isColorSupported,YJ as isCI,l as isBun,pJ as hasWindow,o as hasTTY,c as getPrivateKey,hJ as getKeypair,KJ as getEnv,w as generateKeypair,$J as envPlugin,i as envEnum,r as env,K as encryptValue,XJ as encryptEnv,f as decryptValue,jJ as decryptEnv,wJ as autoLoadEnv,t as aesEncrypt,e as aesDecrypt};
package/dist/parser.d.ts CHANGED
@@ -13,4 +13,5 @@ export declare interface ParseOptions {
13
13
  export declare interface ParseResult {
14
14
  parsed: Record<string, string>
15
15
  errors: string[]
16
+ skippedEncrypted: string[]
16
17
  }
package/dist/parser.js CHANGED
@@ -1,4 +1,4 @@
1
1
  // @bun
2
- import{createCipheriv as G,createDecipheriv as W,createHash as $,randomBytes as w}from"crypto";function A(J,j){let R=w(16),I=j.length===32?j:Buffer.from(j.toString("hex").slice(0,64),"hex"),Q=G("aes-256-gcm",I,R),q=Buffer.concat([Q.update(J,"utf8"),Q.final()]),U=Q.getAuthTag();return{ciphertext:q.toString("hex"),iv:R.toString("hex"),authTag:U.toString("hex")}}function O(J,j,R,I){let Q=j.length===32?j:Buffer.from(j.toString("hex").slice(0,64),"hex");try{let q=W("aes-256-gcm",Q,Buffer.from(R,"hex"));return q.setAuthTag(Buffer.from(I,"hex")),Buffer.concat([q.update(Buffer.from(J,"hex")),q.final()]).toString("utf8")}catch(q){throw Error(`Decryption failed (data may be corrupted or key is incorrect): ${q instanceof Error?q.message:String(q)}`)}}function B(){let J=w(32);return{publicKey:$("sha256").update(J).digest().toString("hex"),privateKey:J.toString("hex")}}function g(J,j){let R=$("sha256").update(Buffer.from(j,"hex")).digest(),{ciphertext:I,iv:Q,authTag:q}=A(J,R);return`encrypted:${Buffer.concat([Buffer.from(Q,"hex"),Buffer.from(q,"hex"),Buffer.from(I,"hex")]).toString("base64")}`}function z(J,j){if(!J.startsWith("encrypted:"))return J;let R=J.slice(10),I=Buffer.from(R,"base64");if(I.length<32)throw Error("Invalid encrypted data: payload too short (need at least iv + authTag = 32 bytes)");let Q=I.subarray(0,16).toString("hex"),q=I.subarray(16,32).toString("hex"),U=I.subarray(32).toString("hex"),X=$("sha256").update(Buffer.from(j,"hex")).digest(),Y=$("sha256").update(X).digest();return O(U,Y,Q,q)}function D(J){let j=J.match(/^DOTENV_PRIVATE_KEY_(.+)$/);return j&&j[1]?j[1].toLowerCase():""}function H(J=""){if(!J)return process.env.DOTENV_PRIVATE_KEY;let j=`DOTENV_PRIVATE_KEY_${J.toUpperCase()}`;return process.env[j]}function S(J,j={}){let R={},I=[],Q=J.split(`
3
- `);for(let q of Q){let U=q.trim();if(!U||U.startsWith("#"))continue;if(U.startsWith("DOTENV_PUBLIC_KEY=")){let Z=U.match(/^DOTENV_PUBLIC_KEY=["']?([^"'\n]+)["']?/);if(Z&&Z[1]!==void 0)R.DOTENV_PUBLIC_KEY=Z[1];continue}let X=U.match(/^([^=]+)=(.*)$/);if(!X||X[1]===void 0||X[2]===void 0)continue;let Y=X[1].trim(),F=X[2].trim();if(F.startsWith('"')&&F.endsWith('"')||F.startsWith("'")&&F.endsWith("'")){if(F=F.slice(1,-1),F.includes("\\n"))F=F.replace(/\\n/g,`
4
- `)}if(j.privateKey&&(F.startsWith("encrypted:")||F.startsWith("enc:")))try{let Z=F.startsWith("enc:")?`encrypted:${F.slice(4)}`:F;F=z(Z,j.privateKey)}catch(Z){I.push(`Failed to decrypt ${Y}: ${Z instanceof Error?Z.message:"Unknown error"}`)}F=_(F,{...j.processEnv||process.env,...R}),F=L(F),R[Y]=F}return{parsed:R,errors:I}}function _(J,j){return J.replace(/\$\{([^}]+)\}/g,(R,I)=>{let Q=I.match(/^([^:\-+]+)(:-|-)(.+)$/);if(Q){let[,U,X,Y]=Q,F=j[U];if(X===":-")return F||Y;else return F!==void 0?F:Y}let q=I.match(/^([^:\-+]+)(:?\+)(.+)$/);if(q){let[,U,X,Y]=q,F=j[U];if(X===":+")return F?Y:"";else return F!==void 0?Y:""}return j[I]||""})}var C=new Set(["date","hostname","whoami","uname","pwd","echo","printf","cat","basename","dirname"]);function L(J){return J.replace(/\$\(([^)]+)\)/g,(j,R)=>{try{let I=R.trim().split(/\s+/),Q=I[0];if(!Q||!C.has(Q))return console.warn(`[env] Blocked command substitution for disallowed command: ${Q}`),"";let q=Bun.spawnSync(I,{stdout:"pipe",stderr:"pipe"});if(q.exitCode===0)return new TextDecoder().decode(q.stdout).trim();console.warn(`[env] Command substitution failed (exit code ${q.exitCode}): ${Q}`)}catch(I){console.warn(`[env] Command substitution error: ${I instanceof Error?I.message:String(I)}`)}return""})}async function M(J,j={}){let R={},I=[];for(let Q of J)try{let q=Bun.file(Q);if(!q.size)continue;let U=await q.text(),{parsed:X,errors:Y}=S(U,j);I.push(...Y);for(let[F,Z]of Object.entries(X)){if(!j.overload&&R[F]!==void 0)continue;R[F]=Z}}catch(q){if(q?.code==="ENOENT")continue;I.push(`Failed to read ${Q}: ${q instanceof Error?q.message:String(q)}`)}return{parsed:R,errors:I}}export{S as parse,M as loadEnvFiles};
2
+ import{createCipheriv as A,createDecipheriv as O,createHash as w,randomBytes as z}from"crypto";function _(F,j){let R=z(16),q=j.length===32?j:Buffer.from(j.toString("hex").slice(0,64),"hex"),J=A("aes-256-gcm",q,R),I=Buffer.concat([J.update(F,"utf8"),J.final()]),U=J.getAuthTag();return{ciphertext:I.toString("hex"),iv:R.toString("hex"),authTag:U.toString("hex")}}function C(F,j,R,q){let J=j.length===32?j:Buffer.from(j.toString("hex").slice(0,64),"hex");try{let I=O("aes-256-gcm",J,Buffer.from(R,"hex"));return I.setAuthTag(Buffer.from(q,"hex")),Buffer.concat([I.update(Buffer.from(F,"hex")),I.final()]).toString("utf8")}catch(I){throw Error(`Decryption failed (data may be corrupted or key is incorrect): ${I instanceof Error?I.message:String(I)}`)}}function D(){let F=z(32);return{publicKey:w("sha256").update(F).digest().toString("hex"),privateKey:F.toString("hex")}}function H(F,j){let R=w("sha256").update(Buffer.from(j,"hex")).digest(),{ciphertext:q,iv:J,authTag:I}=_(F,R);return`encrypted:${Buffer.concat([Buffer.from(J,"hex"),Buffer.from(I,"hex"),Buffer.from(q,"hex")]).toString("base64")}`}function G(F,j){if(!F.startsWith("encrypted:"))return F;let R=F.slice(10),q=Buffer.from(R,"base64");if(q.length<32)throw Error("Invalid encrypted data: payload too short (need at least iv + authTag = 32 bytes)");let J=q.subarray(0,16).toString("hex"),I=q.subarray(16,32).toString("hex"),U=q.subarray(32).toString("hex"),Y=w("sha256").update(Buffer.from(j,"hex")).digest(),X=w("sha256").update(Y).digest();return C(U,X,J,I)}function T(F){let j=F.match(/^DOTENV_PRIVATE_KEY_(.+)$/);return j&&j[1]?j[1].toLowerCase():""}function M(F=""){if(!F)return process.env.DOTENV_PRIVATE_KEY;let j=`DOTENV_PRIVATE_KEY_${F.toUpperCase()}`;return process.env[j]}function L(F,j={}){let R={},q=[],J=[],I=F.split(`
3
+ `);for(let U of I){let Y=U.trim();if(!Y||Y.startsWith("#"))continue;if(Y.startsWith("DOTENV_PUBLIC_KEY=")){let $=Y.match(/^DOTENV_PUBLIC_KEY=["']?([^"'\n]+)["']?/);if($&&$[1]!==void 0)R.DOTENV_PUBLIC_KEY=$[1];continue}let X=Y.match(/^([^=]+)=(.*)$/);if(!X||X[1]===void 0||X[2]===void 0)continue;let Z=X[1].trim(),Q=X[2].trim();if(Q.startsWith('"')&&Q.endsWith('"')||Q.startsWith("'")&&Q.endsWith("'")){if(Q=Q.slice(1,-1),Q.includes("\\n"))Q=Q.replace(/\\n/g,`
4
+ `)}if(Q.startsWith("encrypted:")||Q.startsWith("enc:")){if(!j.privateKey){J.push(Z);continue}try{let $=Q.startsWith("enc:")?`encrypted:${Q.slice(4)}`:Q;Q=G($,j.privateKey)}catch($){q.push(`Failed to decrypt ${Z}: ${$ instanceof Error?$.message:"Unknown error"}`)}}Q=P(Q,{...j.processEnv||process.env,...R}),Q=S(Q),R[Z]=Q}return{parsed:R,errors:q,skippedEncrypted:J}}function P(F,j){return F.replace(/\$\{([^}]+)\}/g,(R,q)=>{let J=q.match(/^([^:\-+]+)(:-|-)(.+)$/);if(J){let[,U,Y,X]=J,Z=j[U];if(Y===":-")return Z||X;else return Z!==void 0?Z:X}let I=q.match(/^([^:\-+]+)(:?\+)(.+)$/);if(I){let[,U,Y,X]=I,Z=j[U];if(Y===":+")return Z?X:"";else return Z!==void 0?X:""}return j[q]||""})}var B=new Set(["date","hostname","whoami","uname","pwd","echo","printf","cat","basename","dirname"]);function S(F){return F.replace(/\$\(([^)]+)\)/g,(j,R)=>{try{let q=R.trim().split(/\s+/),J=q[0];if(!J||!B.has(J))return console.warn(`[env] Blocked command substitution for disallowed command: ${J}`),"";let I=Bun.spawnSync(q,{stdout:"pipe",stderr:"pipe"});if(I.exitCode===0)return new TextDecoder().decode(I.stdout).trim();console.warn(`[env] Command substitution failed (exit code ${I.exitCode}): ${J}`)}catch(q){console.warn(`[env] Command substitution error: ${q instanceof Error?q.message:String(q)}`)}return""})}async function E(F,j={}){let R={},q=[],J=[];for(let I of F)try{let U=Bun.file(I);if(!U.size)continue;let Y=await U.text(),{parsed:X,errors:Z,skippedEncrypted:Q}=L(Y,j);q.push(...Z),J.push(...Q);for(let[$,W]of Object.entries(X)){if(!j.overload&&R[$]!==void 0)continue;R[$]=W}}catch(U){if(U?.code==="ENOENT")continue;q.push(`Failed to read ${I}: ${U instanceof Error?U.message:String(U)}`)}return{parsed:R,errors:q,skippedEncrypted:J}}export{L as parse,E as loadEnvFiles};
package/dist/plugin.js CHANGED
@@ -1,4 +1,4 @@
1
1
  // @bun
2
- import{createCipheriv as x,createDecipheriv as f,createHash as I,randomBytes as S}from"crypto";function k(J,j){let Y=S(16),Q=j.length===32?j:Buffer.from(j.toString("hex").slice(0,64),"hex"),X=x("aes-256-gcm",Q,Y),U=Buffer.concat([X.update(J,"utf8"),X.final()]),Z=X.getAuthTag();return{ciphertext:U.toString("hex"),iv:Y.toString("hex"),authTag:Z.toString("hex")}}function m(J,j,Y,Q){let X=j.length===32?j:Buffer.from(j.toString("hex").slice(0,64),"hex");try{let U=f("aes-256-gcm",X,Buffer.from(Y,"hex"));return U.setAuthTag(Buffer.from(Q,"hex")),Buffer.concat([U.update(Buffer.from(J,"hex")),U.final()]).toString("utf8")}catch(U){throw Error(`Decryption failed (data may be corrupted or key is incorrect): ${U instanceof Error?U.message:String(U)}`)}}function p(){let J=S(32);return{publicKey:I("sha256").update(J).digest().toString("hex"),privateKey:J.toString("hex")}}function v(J,j){let Y=I("sha256").update(Buffer.from(j,"hex")).digest(),{ciphertext:Q,iv:X,authTag:U}=k(J,Y);return`encrypted:${Buffer.concat([Buffer.from(X,"hex"),Buffer.from(U,"hex"),Buffer.from(Q,"hex")]).toString("base64")}`}function g(J,j){if(!J.startsWith("encrypted:"))return J;let Y=J.slice(10),Q=Buffer.from(Y,"base64");if(Q.length<32)throw Error("Invalid encrypted data: payload too short (need at least iv + authTag = 32 bytes)");let X=Q.subarray(0,16).toString("hex"),U=Q.subarray(16,32).toString("hex"),Z=Q.subarray(32).toString("hex"),$=I("sha256").update(Buffer.from(j,"hex")).digest(),G=I("sha256").update($).digest();return m(Z,G,X,U)}function i(J){let j=J.match(/^DOTENV_PRIVATE_KEY_(.+)$/);return j&&j[1]?j[1].toLowerCase():""}function z(J=""){if(!J)return process.env.DOTENV_PRIVATE_KEY;let j=`DOTENV_PRIVATE_KEY_${J.toUpperCase()}`;return process.env[j]}function L(J,j={}){let Y={},Q=[],X=J.split(`
3
- `);for(let U of X){let Z=U.trim();if(!Z||Z.startsWith("#"))continue;if(Z.startsWith("DOTENV_PUBLIC_KEY=")){let W=Z.match(/^DOTENV_PUBLIC_KEY=["']?([^"'\n]+)["']?/);if(W&&W[1]!==void 0)Y.DOTENV_PUBLIC_KEY=W[1];continue}let $=Z.match(/^([^=]+)=(.*)$/);if(!$||$[1]===void 0||$[2]===void 0)continue;let G=$[1].trim(),R=$[2].trim();if(R.startsWith('"')&&R.endsWith('"')||R.startsWith("'")&&R.endsWith("'")){if(R=R.slice(1,-1),R.includes("\\n"))R=R.replace(/\\n/g,`
4
- `)}if(j.privateKey&&(R.startsWith("encrypted:")||R.startsWith("enc:")))try{let W=R.startsWith("enc:")?`encrypted:${R.slice(4)}`:R;R=g(W,j.privateKey)}catch(W){Q.push(`Failed to decrypt ${G}: ${W instanceof Error?W.message:"Unknown error"}`)}R=h(R,{...j.processEnv||process.env,...Y}),R=d(R),Y[G]=R}return{parsed:Y,errors:Q}}function h(J,j){return J.replace(/\$\{([^}]+)\}/g,(Y,Q)=>{let X=Q.match(/^([^:\-+]+)(:-|-)(.+)$/);if(X){let[,Z,$,G]=X,R=j[Z];if($===":-")return R||G;else return R!==void 0?R:G}let U=Q.match(/^([^:\-+]+)(:?\+)(.+)$/);if(U){let[,Z,$,G]=U,R=j[Z];if($===":+")return R?G:"";else return R!==void 0?G:""}return j[Q]||""})}var c=new Set(["date","hostname","whoami","uname","pwd","echo","printf","cat","basename","dirname"]);function d(J){return J.replace(/\$\(([^)]+)\)/g,(j,Y)=>{try{let Q=Y.trim().split(/\s+/),X=Q[0];if(!X||!c.has(X))return console.warn(`[env] Blocked command substitution for disallowed command: ${X}`),"";let U=Bun.spawnSync(Q,{stdout:"pipe",stderr:"pipe"});if(U.exitCode===0)return new TextDecoder().decode(U.stdout).trim();console.warn(`[env] Command substitution failed (exit code ${U.exitCode}): ${X}`)}catch(Q){console.warn(`[env] Command substitution error: ${Q instanceof Error?Q.message:String(Q)}`)}return""})}async function n(J,j={}){let Y={},Q=[];for(let X of J)try{let U=Bun.file(X);if(!U.size)continue;let Z=await U.text(),{parsed:$,errors:G}=L(Z,j);Q.push(...G);for(let[R,W]of Object.entries($)){if(!j.overload&&Y[R]!==void 0)continue;Y[R]=W}}catch(U){if(U?.code==="ENOENT")continue;Q.push(`Failed to read ${X}: ${U instanceof Error?U.message:String(U)}`)}return{parsed:Y,errors:Q}}import{existsSync as H}from"fs";import{readFileSync as N}from"fs";import{resolve as T}from"path";function D(J){return typeof J==="string"&&(J.startsWith("encrypted:")||J.startsWith("enc:"))}function C(J){if(!J||D(J))return;let j=J.trim().toLowerCase();if(!/^[a-z0-9_-]+$/.test(j))return;if(j==="prod")return"production";if(j==="stage")return"staging";if(j==="dev")return"development";return j}function E(J={}){let{path:j=[".env"],overload:Y=!1,env:Q,privateKey:X,keysFile:U=".env.keys",quiet:Z=!1,cwd:$=process.cwd()}=J,G=Array.isArray(j)?j:[j],R=[],W=0,K=new Set(Object.entries(process.env).filter(([,q])=>q!==void 0&&!D(q)).map(([q])=>q)),O=X;if(!O&&U){let q=T($,U);if(H(q))try{let A=N(q,"utf-8"),{parsed:_}=L(A);if(Q){let w=`DOTENV_PRIVATE_KEY_${Q.toUpperCase()}`;O=_[w]}else O=_.DOTENV_PRIVATE_KEY}catch(A){R.push(`Failed to load keys file: ${A instanceof Error?A.message:"Unknown error"}`)}}if(!O)O=z(Q||"");for(let q of G){let A=T($,q);if(!H(A)){if(!Z)R.push(`File not found: ${A}`);continue}try{let _=N(A,"utf-8"),{parsed:w,errors:P}=L(_,{privateKey:O,processEnv:process.env});R.push(...P);let F=0;for(let[B,M]of Object.entries(w)){if(B==="DOTENV_PUBLIC_KEY")continue;let b=process.env[B],V=D(b)&&M!==b;if(Y||!K.has(B)||V)process.env[B]=M,W++,F++}if(!Z&&!process.env.__ENV_LOADED__)console.log(`[env] loaded ${F}/${Object.keys(w).length} variables from ${q}`),process.env.__ENV_LOADED__="1"}catch(_){R.push(`Failed to load ${A}: ${_ instanceof Error?_.message:"Unknown error"}`)}}return{loaded:W,errors:R}}function y(J={}){return{name:"env-plugin",setup(j){E(J)}}}function Qj(J={}){let j=C(J.env)||C("development")||C(process.env.DOTENV_ENV)||C(process.env.APP_ENV)||"development",Y=J.cwd||process.cwd(),Q=[],X=($)=>{if(!Q.includes($)&&H(T(Y,$)))Q.push($)};X(".env"),X(".env.local");let U=`.env.${j}`,Z=`.env.${j}.local`;return X(U),X(Z),E({...J,path:Q,env:j})}var Uj=y;export{E as loadEnv,y as envPlugin,Uj as default,Qj as autoLoadEnv};
2
+ import{createCipheriv as f,createDecipheriv as m,createHash as D,randomBytes as K}from"crypto";function k(J,j){let Y=K(16),Q=j.length===32?j:Buffer.from(j.toString("hex").slice(0,64),"hex"),R=f("aes-256-gcm",Q,Y),U=Buffer.concat([R.update(J,"utf8"),R.final()]),Z=R.getAuthTag();return{ciphertext:U.toString("hex"),iv:Y.toString("hex"),authTag:Z.toString("hex")}}function h(J,j,Y,Q){let R=j.length===32?j:Buffer.from(j.toString("hex").slice(0,64),"hex");try{let U=m("aes-256-gcm",R,Buffer.from(Y,"hex"));return U.setAuthTag(Buffer.from(Q,"hex")),Buffer.concat([U.update(Buffer.from(J,"hex")),U.final()]).toString("utf8")}catch(U){throw Error(`Decryption failed (data may be corrupted or key is incorrect): ${U instanceof Error?U.message:String(U)}`)}}function o(){let J=K(32);return{publicKey:D("sha256").update(J).digest().toString("hex"),privateKey:J.toString("hex")}}function s(J,j){let Y=D("sha256").update(Buffer.from(j,"hex")).digest(),{ciphertext:Q,iv:R,authTag:U}=k(J,Y);return`encrypted:${Buffer.concat([Buffer.from(R,"hex"),Buffer.from(U,"hex"),Buffer.from(Q,"hex")]).toString("base64")}`}function N(J,j){if(!J.startsWith("encrypted:"))return J;let Y=J.slice(10),Q=Buffer.from(Y,"base64");if(Q.length<32)throw Error("Invalid encrypted data: payload too short (need at least iv + authTag = 32 bytes)");let R=Q.subarray(0,16).toString("hex"),U=Q.subarray(16,32).toString("hex"),Z=Q.subarray(32).toString("hex"),$=D("sha256").update(Buffer.from(j,"hex")).digest(),W=D("sha256").update($).digest();return h(Z,W,R,U)}function i(J){let j=J.match(/^DOTENV_PRIVATE_KEY_(.+)$/);return j&&j[1]?j[1].toLowerCase():""}function P(J=""){if(!J)return process.env.DOTENV_PRIVATE_KEY;let j=`DOTENV_PRIVATE_KEY_${J.toUpperCase()}`;return process.env[j]}function F(J,j={}){let Y={},Q=[],R=[],U=J.split(`
3
+ `);for(let Z of U){let $=Z.trim();if(!$||$.startsWith("#"))continue;if($.startsWith("DOTENV_PUBLIC_KEY=")){let q=$.match(/^DOTENV_PUBLIC_KEY=["']?([^"'\n]+)["']?/);if(q&&q[1]!==void 0)Y.DOTENV_PUBLIC_KEY=q[1];continue}let W=$.match(/^([^=]+)=(.*)$/);if(!W||W[1]===void 0||W[2]===void 0)continue;let G=W[1].trim(),X=W[2].trim();if(X.startsWith('"')&&X.endsWith('"')||X.startsWith("'")&&X.endsWith("'")){if(X=X.slice(1,-1),X.includes("\\n"))X=X.replace(/\\n/g,`
4
+ `)}if(X.startsWith("encrypted:")||X.startsWith("enc:")){if(!j.privateKey){R.push(G);continue}try{let q=X.startsWith("enc:")?`encrypted:${X.slice(4)}`:X;X=N(q,j.privateKey)}catch(q){Q.push(`Failed to decrypt ${G}: ${q instanceof Error?q.message:"Unknown error"}`)}}X=c(X,{...j.processEnv||process.env,...Y}),X=u(X),Y[G]=X}return{parsed:Y,errors:Q,skippedEncrypted:R}}function c(J,j){return J.replace(/\$\{([^}]+)\}/g,(Y,Q)=>{let R=Q.match(/^([^:\-+]+)(:-|-)(.+)$/);if(R){let[,Z,$,W]=R,G=j[Z];if($===":-")return G||W;else return G!==void 0?G:W}let U=Q.match(/^([^:\-+]+)(:?\+)(.+)$/);if(U){let[,Z,$,W]=U,G=j[Z];if($===":+")return G?W:"";else return G!==void 0?W:""}return j[Q]||""})}var y=new Set(["date","hostname","whoami","uname","pwd","echo","printf","cat","basename","dirname"]);function u(J){return J.replace(/\$\(([^)]+)\)/g,(j,Y)=>{try{let Q=Y.trim().split(/\s+/),R=Q[0];if(!R||!y.has(R))return console.warn(`[env] Blocked command substitution for disallowed command: ${R}`),"";let U=Bun.spawnSync(Q,{stdout:"pipe",stderr:"pipe"});if(U.exitCode===0)return new TextDecoder().decode(U.stdout).trim();console.warn(`[env] Command substitution failed (exit code ${U.exitCode}): ${R}`)}catch(Q){console.warn(`[env] Command substitution error: ${Q instanceof Error?Q.message:String(Q)}`)}return""})}async function l(J,j={}){let Y={},Q=[],R=[];for(let U of J)try{let Z=Bun.file(U);if(!Z.size)continue;let $=await Z.text(),{parsed:W,errors:G,skippedEncrypted:X}=F($,j);Q.push(...G),R.push(...X);for(let[q,O]of Object.entries(W)){if(!j.overload&&Y[q]!==void 0)continue;Y[q]=O}}catch(Z){if(Z?.code==="ENOENT")continue;Q.push(`Failed to read ${U}: ${Z instanceof Error?Z.message:String(Z)}`)}return{parsed:Y,errors:Q,skippedEncrypted:R}}import{existsSync as g}from"fs";import{readFileSync as V}from"fs";import{resolve as z}from"path";function b(J){return typeof J==="string"&&(J.startsWith("encrypted:")||J.startsWith("enc:"))}function M(J){if(!J||b(J))return;let j=J.trim().toLowerCase();if(!/^[a-z0-9_-]+$/.test(j))return;if(j==="prod")return"production";if(j==="stage")return"staging";if(j==="dev")return"development";return j}function x(J={}){let{path:j=[".env"],overload:Y=!1,env:Q,privateKey:R,keysFile:U=".env.keys",quiet:Z=!1,cwd:$=process.cwd()}=J,W=Array.isArray(j)?j:[j],G=[],X=0,q=new Set(Object.entries(process.env).filter(([,A])=>A!==void 0&&!b(A)).map(([A])=>A)),O=R;if(!O&&U){let A=z($,U);if(g(A))try{let _=V(A,"utf-8"),{parsed:B}=F(_);if(Q){let w=`DOTENV_PRIVATE_KEY_${Q.toUpperCase()}`;O=B[w]}else O=B.DOTENV_PRIVATE_KEY}catch(_){G.push(`Failed to load keys file: ${_ instanceof Error?_.message:"Unknown error"}`)}}if(!O)O=P(Q||"");for(let A of W){let _=z($,A);if(!g(_)){if(!Z)G.push(`File not found: ${_}`);continue}try{let B=V(_,"utf-8"),{parsed:w,errors:E,skippedEncrypted:I}=F(B,{privateKey:O,processEnv:process.env});if(G.push(...E),I.length>0){for(let T of I)if(b(process.env[T]))delete process.env[T];let L=Q?`DOTENV_PRIVATE_KEY_${Q.toUpperCase()}`:"DOTENV_PRIVATE_KEY",C=I.slice(0,5).join(", "),H=I.length>5?`, \u2026 +${I.length-5} more`:"";console.warn(`[env] warning: skipped ${I.length} encrypted value(s) in ${A} (${L} not set; defaults apply): ${C}${H}`)}let S=0;for(let[L,C]of Object.entries(w)){if(L==="DOTENV_PUBLIC_KEY")continue;let H=process.env[L],T=b(H)&&C!==H;if(Y||!q.has(L)||T)process.env[L]=C,X++,S++}if(!Z&&!process.env.__ENV_LOADED__)console.log(`[env] loaded ${S}/${Object.keys(w).length} variables from ${A}`),process.env.__ENV_LOADED__="1"}catch(B){G.push(`Failed to load ${_}: ${B instanceof Error?B.message:"Unknown error"}`)}}return{loaded:X,errors:G}}function d(J={}){return{name:"env-plugin",setup(j){x(J)}}}function Rj(J={}){let j=M(J.env)||M("development")||M(process.env.DOTENV_ENV)||M(process.env.APP_ENV)||"development",Y=J.cwd||process.cwd(),Q=[],R=($)=>{if(!Q.includes($)&&g(z(Y,$)))Q.push($)};R(".env"),R(".env.local");let U=`.env.${j}`,Z=`.env.${j}.local`;return R(U),R(Z),x({...J,path:Q,env:j})}var Xj=d;export{x as loadEnv,d as envPlugin,Xj as default,Rj as autoLoadEnv};
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@stacksjs/env",
3
3
  "type": "module",
4
4
  "sideEffects": false,
5
- "version": "0.70.113",
5
+ "version": "0.70.115",
6
6
  "description": "Stacks env helper methods.",
7
7
  "author": "Chris Breuer",
8
8
  "contributors": [
@@ -50,8 +50,8 @@
50
50
  "prepublishOnly": "bun run build"
51
51
  },
52
52
  "devDependencies": {
53
- "better-dx": "^0.2.16",
54
- "@stacksjs/path": "0.70.113",
55
- "@stacksjs/validation": "0.70.113"
53
+ "better-dx": "catalog:",
54
+ "@stacksjs/path": "0.70.115",
55
+ "@stacksjs/validation": "0.70.115"
56
56
  }
57
57
  }