@stacksjs/env 0.70.22 → 0.70.25

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/README.md CHANGED
@@ -1,42 +1,438 @@
1
- # Stacks Objects
1
+ # @stacksjs/env
2
2
 
3
- Easily work with objects.
3
+ A secure .env file management package with built-in encryption support for Bun and Node.js.
4
4
 
5
- ## ☘️ Features
5
+ ## Features
6
6
 
7
- - Access to Laravel-like Collections API
8
- - Other object helpers
7
+ - 🔐 **Automatic Encryption/Decryption** - Secure your environment variables with public-key cryptography
8
+ - 🚀 **Bun Plugin** - Seamless integration with Bun's runtime
9
+ - 🔑 **secp256k1 ECIES** - Industry-standard elliptic curve encryption
10
+ - 📝 **Variable Expansion** - Support for `${VAR}`, defaults, and alternates
11
+ - 🔧 **Command Substitution** - Execute commands with `$(command)`
12
+ - 🎯 **Multi-Environment** - Manage multiple .env files for different environments
13
+ - 🛠️ **CLI Tools** - Full-featured CLI via buddy commands
14
+ - 🌍 **Environment Detection** - Native runtime, platform, and CI/CD detection utilities
9
15
 
10
- ## 🤖 Usage
16
+ ## Installation
11
17
 
12
18
  ```bash
13
- bun install -d @stacksjs/objects
19
+ bun add @stacksjs/env
14
20
  ```
15
21
 
16
- Now, you can easily access it in your project:
22
+ ## Quick Start
17
23
 
18
- ```js
19
- import { collect } from '@stacksjs/objects'
24
+ ### 1. Auto-load .env files
20
25
 
21
- const collection = collect([{
22
- name: 'My story',
23
- pages: 176,
24
- }, {
25
- name: 'Fantastic Beasts and Where to Find Them',
26
- pages: 1096,
27
- }])
26
+ ```typescript
27
+ import { autoLoadEnv } from '@stacksjs/env'
28
28
 
29
- console.log(collection.avg('pages')) // 636
29
+ // Automatically loads .env files based on NODE_ENV or DOTENV_ENV
30
+ autoLoadEnv()
31
+
32
+ // Now use your environment variables
33
+ console.log(process.env.MY_SECRET)
34
+ ```
35
+
36
+ ### 2. Programmatic Usage
37
+
38
+ ```typescript
39
+ import { loadEnv } from '@stacksjs/env'
40
+
41
+ // Load specific .env files
42
+ loadEnv({
43
+ path: ['.env.local', '.env'],
44
+ overload: false,
45
+ })
46
+ ```
47
+
48
+ ### 3. Bun Plugin
49
+
50
+ Add to your `bunfig.toml`:
51
+
52
+ ```toml
53
+ preload = ["./storage/framework/core/env/plugin.ts"]
54
+ ```
55
+
56
+ Or import in your preloader:
57
+
58
+ ```typescript
59
+ import '@stacksjs/env/plugin'
60
+ ```
61
+
62
+ ## Encryption
63
+
64
+ ### Encrypting .env Files
65
+
66
+ Use the buddy CLI to encrypt your environment variables:
67
+
68
+ ```bash
69
+ # Encrypt .env file
70
+ buddy env:encrypt
71
+
72
+ # Encrypt specific file
73
+ buddy env:encrypt --file .env.production
74
+
75
+ # Encrypt specific keys only
76
+ buddy env:encrypt -k "SECRET**"
77
+
78
+ # Exclude specific keys from encryption
79
+ buddy env:encrypt -ek "PUBLIC**"
80
+ ```
81
+
82
+ This will:
83
+
84
+ 1. Generate a public/private keypair
85
+ 2. Store keys in `.env.keys` (keep this secure!)
86
+ 3. Encrypt values in your .env file
87
+ 4. Add `DOTENV_PUBLIC_KEY` to your .env file
88
+
89
+ ### Decrypting .env Files
90
+
91
+ ```bash
92
+ # Decrypt .env file
93
+ buddy env:decrypt
94
+
95
+ # Decrypt specific file
96
+ buddy env:decrypt --file .env.production
30
97
  ```
31
98
 
32
- To view the full documentation, please visit [https://stacksjs.org/objects](https://stacksjs.org/objects).
99
+ ### How Encryption Works
100
+
101
+ The encryption uses **secp256k1 ECIES** (Elliptic Curve Integrated Encryption Scheme):
102
+
103
+ 1. A keypair is generated using secp256k1 (same as Bitcoin)
104
+ 2. Each value is encrypted with AES-256-GCM using an ephemeral key
105
+ 3. The ephemeral key is encrypted with the public key
106
+ 4. Only the private key can decrypt the values
107
+
108
+ **Example encrypted .env:**
109
+
110
+ ```ini
111
+ # /-------------------[DOTENV_PUBLIC_KEY]--------------------/
112
+ # / public-key encryption for .env files /
113
+ # / [how it works](https://stacksjs.com/encryption) /
114
+ # /----------------------------------------------------------/
115
+ DOTENV_PUBLIC_KEY="034af93e93708b994c10f236c96ef88e47291066946cce2e8d98c9e02c741ced45"
116
+
117
+ # .env
118
+ API_KEY="encrypted:BDqDBibm4wsYqMpCjTQ6BsDHmMadg9K3dAt+Z9HPMfLEIRVz50hmLXPXRuDBXaJi..."
119
+ DB_PASSWORD="encrypted:AKx8Bh3m5xtZrNqDkUP7CuEInOcfg9L4eBy/2qt59vbSU0aN9WSmN..."
120
+ ```
121
+
122
+ ## CLI Commands
123
+
124
+ All commands are available through the `buddy` CLI:
33
125
 
34
- ## 🧪 Testing
126
+ ### Get Environment Variables
35
127
 
36
128
  ```bash
37
- bun test
129
+ # Get a specific variable
130
+ buddy env:get API_KEY
131
+
132
+ # Get all variables as JSON
133
+ buddy env:get --all
134
+
135
+ # Get all variables in shell format
136
+ buddy env:get --all --format shell
137
+
138
+ # Pretty print JSON
139
+ buddy env:get --all --pretty
140
+ ```
141
+
142
+ ### Set Environment Variables
143
+
144
+ ```bash
145
+ # Set a variable (encrypted by default)
146
+ buddy env:set API_KEY "my-secret-value"
147
+
148
+ # Set without encryption
149
+ buddy env:set PUBLIC_URL "https://example.com" --plain
150
+
151
+ # Set in specific file
152
+ buddy env:set API_KEY "value" --file .env.production
153
+ ```
154
+
155
+ ### Manage Keypairs
156
+
157
+ ```bash
158
+ # View keypair
159
+ buddy env:keypair
160
+
161
+ # View keypair for specific environment
162
+ buddy env:keypair --file .env.production
163
+
164
+ # Get specific key
165
+ buddy env:keypair DOTENV_PRIVATE_KEY
166
+
167
+ # Output in shell format
168
+ buddy env:keypair --format shell
169
+ ```
170
+
171
+ ### Rotate Keys
172
+
173
+ ```bash
174
+ # Rotate keypair and re-encrypt all values
175
+ buddy env:rotate
176
+
177
+ # Rotate for specific environment
178
+ buddy env:rotate --file .env.production
179
+ ```
180
+
181
+ ## Variable Expansion
182
+
183
+ The env parser supports advanced variable expansion:
184
+
185
+ ### Basic Expansion
186
+
187
+ ```ini
188
+ USERNAME="john"
189
+ DATABASE_URL="postgres://${USERNAME}@localhost/mydb"
190
+ # Result: postgres://john@localhost/mydb
191
+ ```
192
+
193
+ ### Default Values
194
+
195
+ ```ini
196
+ # Use default if unset or empty
197
+ DATABASE_HOST=${DB_HOST:-localhost}
198
+ DATABASE_PORT=${DB_PORT:-5432}
199
+
200
+ # Use default only if unset (empty is ok)
201
+ API_URL=${API_BASE_URL-https://api.example.com}
202
+ ```
203
+
204
+ ### Alternate Values
205
+
206
+ ```ini
207
+ NODE_ENV=production
208
+
209
+ # Use alternate if set and non-empty
210
+ DEBUG_MODE=${NODE_ENV:+false}
211
+ LOG_LEVEL=${NODE_ENV:+error}
212
+
213
+ # Use alternate if set (empty is ok)
214
+ CACHE_ENABLED=${NODE_ENV+true}
38
215
  ```
39
216
 
217
+ ### Command Substitution
218
+
219
+ ```ini
220
+ # Execute command and use output
221
+ CURRENT_USER=$(whoami)
222
+ BUILD_TIME=$(date +%s)
223
+ GIT_COMMIT=$(git rev-parse HEAD)
224
+ ```
225
+
226
+ ## Environment Detection
227
+
228
+ The package includes native utilities to detect runtime, platform, and CI/CD environments:
229
+
230
+ ```typescript
231
+ import {
232
+ // Runtime detection
233
+ isBun,
234
+ isNode,
235
+ runtime,
236
+ runtimeInfo,
237
+
238
+ // Platform detection
239
+ platform,
240
+ isWindows,
241
+ isMacOS,
242
+ isLinux,
243
+
244
+ // Environment detection
245
+ hasTTY,
246
+ hasWindow,
247
+ isCI,
248
+ isDebug,
249
+ isMinimal,
250
+ isColorSupported,
251
+
252
+ // Provider detection
253
+ provider,
254
+ providerInfo,
255
+ } from '@stacksjs/env'
256
+
257
+ // Check runtime
258
+ console.log(runtime) // 'bun' | 'node' | 'unknown'
259
+ console.log(runtimeInfo) // { name: 'bun', version: '1.3.2' }
260
+
261
+ // Check platform
262
+ console.log(platform) // 'darwin' | 'linux' | 'win32' | etc.
263
+ console.log(isMacOS) // true/false
264
+
265
+ // Check CI environment
266
+ console.log(isCI) // true/false
267
+ console.log(provider) // 'github' | 'gitlab' | 'vercel' | etc.
268
+ console.log(providerInfo) // { name: 'GitHub Actions', detected: true }
269
+ ```
270
+
271
+ ### Supported CI/CD Providers
272
+
273
+ - GitHub Actions
274
+ - GitLab CI
275
+ - CircleCI
276
+ - Travis CI
277
+ - Jenkins
278
+ - Vercel
279
+ - Netlify
280
+ - Heroku
281
+ - AWS
282
+ - Azure
283
+ - Cloudflare Pages
284
+ - Railway
285
+ - Render
286
+
287
+ ## Multi-Environment Support
288
+
289
+ Load different .env files based on environment:
290
+
291
+ ```bash
292
+ # .env.local (highest priority)
293
+ # .env.development
294
+ # .env.production
295
+ # .env (lowest priority)
296
+ ```
297
+
298
+ The loader will automatically detect `NODE_ENV` or `DOTENV_ENV` and load the appropriate files.
299
+
300
+ ### Environment-Specific Keys
301
+
302
+ Keys are automatically namespaced by environment:
303
+
304
+ ```ini
305
+ # .env.keys
306
+ DOTENV_PUBLIC_KEY="..."
307
+ DOTENV_PRIVATE_KEY="..."
308
+
309
+ DOTENV_PUBLIC_KEY_PRODUCTION="..."
310
+ DOTENV_PRIVATE_KEY_PRODUCTION="..."
311
+
312
+ DOTENV_PUBLIC_KEY_CI="..."
313
+ DOTENV_PRIVATE_KEY_CI="..."
314
+ ```
315
+
316
+ ## Security Best Practices
317
+
318
+ 1. **Never commit `.env.keys`** - Add to `.gitignore`
319
+ 2. **Commit encrypted `.env` files** - They're safe to commit
320
+ 3. **Store private keys securely** - Use your CI/CD secrets manager
321
+ 4. **Rotate keys regularly** - Use `buddy env:rotate`
322
+ 5. **Use environment-specific keys** - Different keys for dev/staging/prod
323
+
324
+ ## API Reference
325
+
326
+ ### `autoLoadEnv(options?)`
327
+
328
+ Automatically load .env files based on environment.
329
+
330
+ ```typescript
331
+ import { autoLoadEnv } from '@stacksjs/env'
332
+
333
+ autoLoadEnv({
334
+ env: 'production', // Override environment detection
335
+ overload: false, // Don't override existing vars
336
+ quiet: true, // Suppress output
337
+ cwd: '/path/to/project'
338
+ })
339
+ ```
340
+
341
+ ### `loadEnv(options)`
342
+
343
+ Load specific .env files.
344
+
345
+ ```typescript
346
+ import { loadEnv } from '@stacksjs/env'
347
+
348
+ loadEnv({
349
+ path: ['.env.local', '.env'],
350
+ overload: false,
351
+ privateKey: 'your-private-key',
352
+ keysFile: '.env.keys',
353
+ quiet: false
354
+ })
355
+ ```
356
+
357
+ ### `encryptEnv(options)`
358
+
359
+ Encrypt a .env file.
360
+
361
+ ```typescript
362
+ import { encryptEnv } from '@stacksjs/env'
363
+
364
+ const result = encryptEnv({
365
+ file: '.env',
366
+ keysFile: '.env.keys',
367
+ key: 'SECRET**', // Only encrypt keys matching pattern
368
+ excludeKey: 'PUBLIC**', // Exclude keys matching pattern
369
+ stdout: false
370
+ })
371
+ ```
372
+
373
+ ### `decryptEnv(options)`
374
+
375
+ Decrypt a .env file.
376
+
377
+ ```typescript
378
+ import { decryptEnv } from '@stacksjs/env'
379
+
380
+ const result = decryptEnv({
381
+ file: '.env',
382
+ keysFile: '.env.keys',
383
+ stdout: false
384
+ })
385
+ ```
386
+
387
+ ### `setEnv(key, value, options)`
388
+
389
+ Set an environment variable.
390
+
391
+ ```typescript
392
+ import { setEnv } from '@stacksjs/env'
393
+
394
+ setEnv('API_KEY', 'my-secret', {
395
+ file: '.env',
396
+ keysFile: '.env.keys',
397
+ plain: false // Encrypt by default
398
+ })
399
+ ```
400
+
401
+ ### `getEnv(key?, options)`
402
+
403
+ Get environment variable(s).
404
+
405
+ ```typescript
406
+ import { getEnv } from '@stacksjs/env'
407
+
408
+ // Get single value
409
+ const result = getEnv('API_KEY', {
410
+ file: '.env',
411
+ keysFile: '.env.keys'
412
+ })
413
+
414
+ // Get all values
415
+ const result = getEnv(undefined, {
416
+ all: true,
417
+ format: 'json', // or 'shell' or 'eval'
418
+ prettyPrint: true
419
+ })
420
+ ```
421
+
422
+ ## Migration from dotenvx
423
+
424
+ This package replaces `@dotenvx/dotenvx` and `bun-plugin-dotenvx` with a native Bun implementation.
425
+
426
+ ### Breaking Changes
427
+
428
+ None! The API is designed to be compatible with dotenvx.
429
+
430
+ ### Migration Steps
431
+
432
+ 1. Update your `bunfig.toml` preload
433
+ 2. Update imports from `@dotenvx/dotenvx` to `@stacksjs/env`
434
+ 3. buddy commands remain the same
435
+
40
436
  ## 📈 Changelog
41
437
 
42
438
  Please see our [releases](https://github.com/stacksjs/stacks/releases) page for more information on what has changed recently.
@@ -55,15 +451,6 @@ For casual chit-chat with others using this package:
55
451
 
56
452
  [Join the Stacks Discord Server](https://discord.gg/stacksjs)
57
453
 
58
- ## 🙏🏼 Credits
59
-
60
- Many thanks to the following core technologies & people who have contributed to this package:
61
-
62
- - [Collect.js](https://github.com/ecrmnn/collect.js)
63
- - [Laravel](https://laravel.com/)
64
- - [Chris Breuer](https://github.com/chrisbbreuer)
65
- - [All Contributors](../../contributors)
66
-
67
454
  ## 📄 License
68
455
 
69
456
  The MIT License (MIT). Please see [LICENSE](https://github.com/stacksjs/stacks/tree/main/LICENSE.md) for more information.
package/dist/index.js CHANGED
@@ -1,10 +1,25 @@
1
1
  // @bun
2
- var gE=Object.create;var{getPrototypeOf:bE,defineProperty:iq,getOwnPropertyNames:iE}=Object;var hE=Object.prototype.hasOwnProperty;var lE=(q,n,E)=>{E=q!=null?gE(bE(q)):{};let y=n||!q||!q.__esModule?iq(E,"default",{value:q,enumerable:!0}):E;for(let J of iE(q))if(!hE.call(y,J))iq(y,J,{get:()=>q[J],enumerable:!0});return y};var X=(q,n)=>()=>(n||q((n={exports:{}}).exports,n),n.exports);var u=import.meta.require;var Q=X((pE)=>{pE.fromCallback=function(q){return Object.defineProperty(function(...n){if(typeof n[n.length-1]==="function")q.apply(this,n);else return new Promise((E,y)=>{n.push((J,O)=>J!=null?y(J):E(O)),q.apply(this,n)})},"name",{value:q.name})};pE.fromPromise=function(q){return Object.defineProperty(function(...n){let E=n[n.length-1];if(typeof E!=="function")return q.apply(this,n);else n.pop(),q.apply(this,n).then((y)=>E(null,y),E)},"name",{value:q.name})}});var lq=X((XO,hq)=>{var f=u("node:constants"),fE=process.cwd,Pq=null,dE=process.env.GRACEFUL_FS_PLATFORM||process.platform;process.cwd=function(){if(!Pq)Pq=fE.call(process);return Pq};try{process.cwd()}catch(q){}if(typeof process.chdir==="function"){if(Aq=process.chdir,process.chdir=function(q){Pq=null,Aq.call(process,q)},Object.setPrototypeOf)Object.setPrototypeOf(process.chdir,Aq)}var Aq;hq.exports=rE;function rE(q){if(f.hasOwnProperty("O_SYMLINK")&&process.version.match(/^v0\.6\.[0-2]|^v0\.5\./))n(q);if(!q.lutimes)E(q);if(q.chown=O(q.chown),q.fchown=O(q.fchown),q.lchown=O(q.lchown),q.chmod=y(q.chmod),q.fchmod=y(q.fchmod),q.lchmod=y(q.lchmod),q.chownSync=_(q.chownSync),q.fchownSync=_(q.fchownSync),q.lchownSync=_(q.lchownSync),q.chmodSync=J(q.chmodSync),q.fchmodSync=J(q.fchmodSync),q.lchmodSync=J(q.lchmodSync),q.stat=U(q.stat),q.fstat=U(q.fstat),q.lstat=U(q.lstat),q.statSync=j(q.statSync),q.fstatSync=j(q.fstatSync),q.lstatSync=j(q.lstatSync),q.chmod&&!q.lchmod)q.lchmod=function(V,A,L){if(L)process.nextTick(L)},q.lchmodSync=function(){};if(q.chown&&!q.lchown)q.lchown=function(V,A,L,K){if(K)process.nextTick(K)},q.lchownSync=function(){};if(dE==="win32")q.rename=typeof q.rename!=="function"?q.rename:function(V){function A(L,K,P){var N=Date.now(),C=0;V(L,K,function R(h){if(h&&(h.code==="EACCES"||h.code==="EPERM"||h.code==="EBUSY")&&Date.now()-N<60000){if(setTimeout(function(){q.stat(K,function(m,Jq){if(m&&m.code==="ENOENT")V(L,K,R);else P(h)})},C),C<100)C+=10;return}if(P)P(h)})}if(Object.setPrototypeOf)Object.setPrototypeOf(A,V);return A}(q.rename);q.read=typeof q.read!=="function"?q.read:function(V){function A(L,K,P,N,C,R){var h;if(R&&typeof R==="function"){var m=0;h=function(Jq,gq,bq){if(Jq&&Jq.code==="EAGAIN"&&m<10)return m++,V.call(q,L,K,P,N,C,h);R.apply(this,arguments)}}return V.call(q,L,K,P,N,C,h)}if(Object.setPrototypeOf)Object.setPrototypeOf(A,V);return A}(q.read),q.readSync=typeof q.readSync!=="function"?q.readSync:function(V){return function(A,L,K,P,N){var C=0;while(!0)try{return V.call(q,A,L,K,P,N)}catch(R){if(R.code==="EAGAIN"&&C<10){C++;continue}throw R}}}(q.readSync);function n(V){V.lchmod=function(A,L,K){V.open(A,f.O_WRONLY|f.O_SYMLINK,L,function(P,N){if(P){if(K)K(P);return}V.fchmod(N,L,function(C){V.close(N,function(R){if(K)K(C||R)})})})},V.lchmodSync=function(A,L){var K=V.openSync(A,f.O_WRONLY|f.O_SYMLINK,L),P=!0,N;try{N=V.fchmodSync(K,L),P=!1}finally{if(P)try{V.closeSync(K)}catch(C){}else V.closeSync(K)}return N}}function E(V){if(f.hasOwnProperty("O_SYMLINK")&&V.futimes)V.lutimes=function(A,L,K,P){V.open(A,f.O_SYMLINK,function(N,C){if(N){if(P)P(N);return}V.futimes(C,L,K,function(R){V.close(C,function(h){if(P)P(R||h)})})})},V.lutimesSync=function(A,L,K){var P=V.openSync(A,f.O_SYMLINK),N,C=!0;try{N=V.futimesSync(P,L,K),C=!1}finally{if(C)try{V.closeSync(P)}catch(R){}else V.closeSync(P)}return N};else if(V.futimes)V.lutimes=function(A,L,K,P){if(P)process.nextTick(P)},V.lutimesSync=function(){}}function y(V){if(!V)return V;return function(A,L,K){return V.call(q,A,L,function(P){if($(P))P=null;if(K)K.apply(this,arguments)})}}function J(V){if(!V)return V;return function(A,L){try{return V.call(q,A,L)}catch(K){if(!$(K))throw K}}}function O(V){if(!V)return V;return function(A,L,K,P){return V.call(q,A,L,K,function(N){if($(N))N=null;if(P)P.apply(this,arguments)})}}function _(V){if(!V)return V;return function(A,L,K){try{return V.call(q,A,L,K)}catch(P){if(!$(P))throw P}}}function U(V){if(!V)return V;return function(A,L,K){if(typeof L==="function")K=L,L=null;function P(N,C){if(C){if(C.uid<0)C.uid+=4294967296;if(C.gid<0)C.gid+=4294967296}if(K)K.apply(this,arguments)}return L?V.call(q,A,L,P):V.call(q,A,P)}}function j(V){if(!V)return V;return function(A,L){var K=L?V.call(q,A,L):V.call(q,A);if(K){if(K.uid<0)K.uid+=4294967296;if(K.gid<0)K.gid+=4294967296}return K}}function $(V){if(!V)return!0;if(V.code==="ENOSYS")return!0;var A=!process.getuid||process.getuid()!==0;if(A){if(V.code==="EINVAL"||V.code==="EPERM")return!0}return!1}}});var oq=X((YO,cq)=>{var pq=u("node:stream").Stream;cq.exports=aE;function aE(q){return{ReadStream:n,WriteStream:E};function n(y,J){if(!(this instanceof n))return new n(y,J);pq.call(this);var O=this;this.path=y,this.fd=null,this.readable=!0,this.paused=!1,this.flags="r",this.mode=438,this.bufferSize=65536,J=J||{};var _=Object.keys(J);for(var U=0,j=_.length;U<j;U++){var $=_[U];this[$]=J[$]}if(this.encoding)this.setEncoding(this.encoding);if(this.start!==void 0){if(typeof this.start!=="number")throw TypeError("start must be a Number");if(this.end===void 0)this.end=1/0;else if(typeof this.end!=="number")throw TypeError("end must be a Number");if(this.start>this.end)throw new Error("start must be <= end");this.pos=this.start}if(this.fd!==null){process.nextTick(function(){O._read()});return}q.open(this.path,this.flags,this.mode,function(V,A){if(V){O.emit("error",V),O.readable=!1;return}O.fd=A,O.emit("open",A),O._read()})}function E(y,J){if(!(this instanceof E))return new E(y,J);pq.call(this),this.path=y,this.fd=null,this.writable=!0,this.flags="w",this.encoding="binary",this.mode=438,this.bytesWritten=0,J=J||{};var O=Object.keys(J);for(var _=0,U=O.length;_<U;_++){var j=O[_];this[j]=J[j]}if(this.start!==void 0){if(typeof this.start!=="number")throw TypeError("start must be a Number");if(this.start<0)throw new Error("start must be >= zero");this.pos=this.start}if(this.busy=!1,this._queue=[],this.fd===null)this._open=q.open,this._queue.push([this._open,this.path,this.flags,this.mode,void 0]),this.flush()}}});var dq=X((ZO,fq)=>{fq.exports=tE;var eE=Object.getPrototypeOf||function(q){return q.__proto__};function tE(q){if(q===null||typeof q!=="object")return q;if(q instanceof Object)var n={__proto__:eE(q)};else var n=Object.create(null);return Object.getOwnPropertyNames(q).forEach(function(E){Object.defineProperty(n,E,Object.getOwnPropertyDescriptor(q,E))}),n}});var qq=X((CO,Iq)=>{var B=u("node:fs"),sE=lq(),qy=oq(),ny=dq(),Gq=u("node:util"),F,Yq;if(typeof Symbol==="function"&&typeof Symbol.for==="function")F=Symbol.for("graceful-fs.queue"),Yq=Symbol.for("graceful-fs.previous");else F="___graceful-fs.queue",Yq="___graceful-fs.previous";function Ey(){}function aq(q,n){Object.defineProperty(q,F,{get:function(){return n}})}var e=Ey;if(Gq.debuglog)e=Gq.debuglog("gfs4");else if(/\bgfs4\b/i.test(process.env.NODE_DEBUG||""))e=function(){var q=Gq.format.apply(Gq,arguments);q="GFS4: "+q.split(/\n/).join(`
3
- GFS4: `),console.error(q)};if(!B[F]){if(wq=global[F]||[],aq(B,wq),B.close=function(q){function n(E,y){return q.call(B,E,function(J){if(!J)rq();if(typeof y==="function")y.apply(this,arguments)})}return Object.defineProperty(n,Yq,{value:q}),n}(B.close),B.closeSync=function(q){function n(E){q.apply(B,arguments),rq()}return Object.defineProperty(n,Yq,{value:q}),n}(B.closeSync),/\bgfs4\b/i.test(process.env.NODE_DEBUG||""))process.on("exit",function(){e(B[F]),u("node:assert").equal(B[F].length,0)})}var wq;if(!global[F])aq(global,B[F]);Iq.exports=Bq(ny(B));if(process.env.TEST_GRACEFUL_FS_GLOBAL_PATCH&&!B.__patched)Iq.exports=Bq(B),B.__patched=!0;function Bq(q){sE(q),q.gracefulify=Bq,q.createReadStream=gq,q.createWriteStream=bq;var n=q.readFile;q.readFile=E;function E(z,Z,Y){if(typeof Z==="function")Y=Z,Z=null;return M(z,Z,Y);function M(T,I,w,D){return n(T,I,function(H){if(H&&(H.code==="EMFILE"||H.code==="ENFILE"))s([M,[T,I,w],H,D||Date.now(),Date.now()]);else if(typeof w==="function")w.apply(this,arguments)})}}var y=q.writeFile;q.writeFile=J;function J(z,Z,Y,M){if(typeof Y==="function")M=Y,Y=null;return T(z,Z,Y,M);function T(I,w,D,H,k){return y(I,w,D,function(x){if(x&&(x.code==="EMFILE"||x.code==="ENFILE"))s([T,[I,w,D,H],x,k||Date.now(),Date.now()]);else if(typeof H==="function")H.apply(this,arguments)})}}var O=q.appendFile;if(O)q.appendFile=_;function _(z,Z,Y,M){if(typeof Y==="function")M=Y,Y=null;return T(z,Z,Y,M);function T(I,w,D,H,k){return O(I,w,D,function(x){if(x&&(x.code==="EMFILE"||x.code==="ENFILE"))s([T,[I,w,D,H],x,k||Date.now(),Date.now()]);else if(typeof H==="function")H.apply(this,arguments)})}}var U=q.copyFile;if(U)q.copyFile=j;function j(z,Z,Y,M){if(typeof Y==="function")M=Y,Y=0;return T(z,Z,Y,M);function T(I,w,D,H,k){return U(I,w,D,function(x){if(x&&(x.code==="EMFILE"||x.code==="ENFILE"))s([T,[I,w,D,H],x,k||Date.now(),Date.now()]);else if(typeof H==="function")H.apply(this,arguments)})}}var $=q.readdir;q.readdir=A;var V=/^v[0-5]\./;function A(z,Z,Y){if(typeof Z==="function")Y=Z,Z=null;var M=V.test(process.version)?function I(w,D,H,k){return $(w,T(w,D,H,k))}:function I(w,D,H,k){return $(w,D,T(w,D,H,k))};return M(z,Z,Y);function T(I,w,D,H){return function(k,x){if(k&&(k.code==="EMFILE"||k.code==="ENFILE"))s([M,[I,w,D],k,H||Date.now(),Date.now()]);else{if(x&&x.sort)x.sort();if(typeof D==="function")D.call(this,k,x)}}}}if(process.version.substr(0,4)==="v0.8"){var L=qy(q);R=L.ReadStream,m=L.WriteStream}var K=q.ReadStream;if(K)R.prototype=Object.create(K.prototype),R.prototype.open=h;var P=q.WriteStream;if(P)m.prototype=Object.create(P.prototype),m.prototype.open=Jq;Object.defineProperty(q,"ReadStream",{get:function(){return R},set:function(z){R=z},enumerable:!0,configurable:!0}),Object.defineProperty(q,"WriteStream",{get:function(){return m},set:function(z){m=z},enumerable:!0,configurable:!0});var N=R;Object.defineProperty(q,"FileReadStream",{get:function(){return N},set:function(z){N=z},enumerable:!0,configurable:!0});var C=m;Object.defineProperty(q,"FileWriteStream",{get:function(){return C},set:function(z){C=z},enumerable:!0,configurable:!0});function R(z,Z){if(this instanceof R)return K.apply(this,arguments),this;else return R.apply(Object.create(R.prototype),arguments)}function h(){var z=this;Rq(z.path,z.flags,z.mode,function(Z,Y){if(Z){if(z.autoClose)z.destroy();z.emit("error",Z)}else z.fd=Y,z.emit("open",Y),z.read()})}function m(z,Z){if(this instanceof m)return P.apply(this,arguments),this;else return m.apply(Object.create(m.prototype),arguments)}function Jq(){var z=this;Rq(z.path,z.flags,z.mode,function(Z,Y){if(Z)z.destroy(),z.emit("error",Z);else z.fd=Y,z.emit("open",Y)})}function gq(z,Z){return new q.ReadStream(z,Z)}function bq(z,Z){return new q.WriteStream(z,Z)}var SE=q.open;q.open=Rq;function Rq(z,Z,Y,M){if(typeof Y==="function")M=Y,Y=null;return T(z,Z,Y,M);function T(I,w,D,H,k){return SE(I,w,D,function(x,PO){if(x&&(x.code==="EMFILE"||x.code==="ENFILE"))s([T,[I,w,D,H],x,k||Date.now(),Date.now()]);else if(typeof H==="function")H.apply(this,arguments)})}}return q}function s(q){e("ENQUEUE",q[0].name,q[1]),B[F].push(q),Dq()}var Xq;function rq(){var q=Date.now();for(var n=0;n<B[F].length;++n)if(B[F][n].length>2)B[F][n][3]=q,B[F][n][4]=q;Dq()}function Dq(){if(clearTimeout(Xq),Xq=void 0,B[F].length===0)return;var q=B[F].shift(),n=q[0],E=q[1],y=q[2],J=q[3],O=q[4];if(J===void 0)e("RETRY",n.name,E),n.apply(null,E);else if(Date.now()-J>=60000){e("TIMEOUT",n.name,E);var _=E.pop();if(typeof _==="function")_.call(null,y)}else{var U=Date.now()-O,j=Math.max(O-J,1),$=Math.min(j*1.2,100);if(U>=$)e("RETRY",n.name,E),n.apply(null,E.concat([J]));else B[F].push(q)}if(Xq===void 0)Xq=setTimeout(Dq,0)}});var g=X((uq)=>{var eq=Q().fromCallback,S=qq(),yy=["access","appendFile","chmod","chown","close","copyFile","cp","fchmod","fchown","fdatasync","fstat","fsync","ftruncate","futimes","glob","lchmod","lchown","lutimes","link","lstat","mkdir","mkdtemp","open","opendir","readdir","readFile","readlink","realpath","rename","rm","rmdir","stat","statfs","symlink","truncate","unlink","utimes","writeFile"].filter((q)=>{return typeof S[q]==="function"});Object.assign(uq,S);yy.forEach((q)=>{uq[q]=eq(S[q])});uq.exists=function(q,n){if(typeof n==="function")return S.exists(q,n);return new Promise((E)=>{return S.exists(q,E)})};uq.read=function(q,n,E,y,J,O){if(typeof O==="function")return S.read(q,n,E,y,J,O);return new Promise((_,U)=>{S.read(q,n,E,y,J,(j,$,V)=>{if(j)return U(j);_({bytesRead:$,buffer:V})})})};uq.write=function(q,n,...E){if(typeof E[E.length-1]==="function")return S.write(q,n,...E);return new Promise((y,J)=>{S.write(q,n,...E,(O,_,U)=>{if(O)return J(O);y({bytesWritten:_,buffer:U})})})};uq.readv=function(q,n,...E){if(typeof E[E.length-1]==="function")return S.readv(q,n,...E);return new Promise((y,J)=>{S.readv(q,n,...E,(O,_,U)=>{if(O)return J(O);y({bytesRead:_,buffers:U})})})};uq.writev=function(q,n,...E){if(typeof E[E.length-1]==="function")return S.writev(q,n,...E);return new Promise((y,J)=>{S.writev(q,n,...E,(O,_,U)=>{if(O)return J(O);y({bytesWritten:_,buffers:U})})})};if(typeof S.realpath.native==="function")uq.realpath.native=eq(S.realpath.native);else process.emitWarning("fs.realpath.native is not a function. Is fs being monkey-patched?","Warning","fs-extra-WARN0003")});var sq=X((zy,tq)=>{var Uy=u("node:path");zy.checkPath=function q(n){if(process.platform==="win32"){if(/[<>:"|?*]/.test(n.replace(Uy.parse(n).root,""))){let y=new Error(`Path contains invalid characters: ${n}`);throw y.code="EINVAL",y}}}});var yn=X((Py,Qq)=>{var qn=g(),{checkPath:nn}=sq(),En=(q)=>{let n={mode:511};if(typeof q==="number")return q;return{...n,...q}.mode};Py.makeDir=async(q,n)=>{return nn(q),qn.mkdir(q,{mode:En(n),recursive:!0})};Py.makeDirSync=(q,n)=>{return nn(q),qn.mkdirSync(q,{mode:En(n),recursive:!0})}});var l=X((xO,Jn)=>{var Xy=Q().fromPromise,{makeDir:Yy,makeDirSync:Wq}=yn(),Mq=Xy(Yy);Jn.exports={mkdirs:Mq,mkdirsSync:Wq,mkdirp:Mq,mkdirpSync:Wq,ensureDir:Mq,ensureDirSync:Wq}});var d=X((jO,_n)=>{var Zy=Q().fromPromise,On=g();function Cy(q){return On.access(q).then(()=>!0).catch(()=>!1)}_n.exports={pathExists:Zy(Cy),pathExistsSync:On.existsSync}});var Tq=X((RO,Vn)=>{var nq=g(),Hy=Q().fromPromise;async function Ny(q,n,E){let y=await nq.open(q,"r+"),J=null;try{await nq.futimes(y,n,E)}finally{try{await nq.close(y)}catch(O){J=O}}if(J)throw J}function xy(q,n,E){let y=nq.openSync(q,"r+");return nq.futimesSync(y,n,E),nq.closeSync(y)}Vn.exports={utimesMillis:Hy(Ny),utimesMillisSync:xy}});var t=X((wO,Ln)=>{var Eq=g(),W=u("node:path"),Kn=Q().fromPromise;function jy(q,n,E){let y=E.dereference?(J)=>Eq.stat(J,{bigint:!0}):(J)=>Eq.lstat(J,{bigint:!0});return Promise.all([y(q),y(n).catch((J)=>{if(J.code==="ENOENT")return null;throw J})]).then(([J,O])=>({srcStat:J,destStat:O}))}function Ry(q,n,E){let y,J=E.dereference?(_)=>Eq.statSync(_,{bigint:!0}):(_)=>Eq.lstatSync(_,{bigint:!0}),O=J(q);try{y=J(n)}catch(_){if(_.code==="ENOENT")return{srcStat:O,destStat:null};throw _}return{srcStat:O,destStat:y}}async function wy(q,n,E,y){let{srcStat:J,destStat:O}=await jy(q,n,y);if(O){if(Oq(J,O)){let _=W.basename(q),U=W.basename(n);if(E==="move"&&_!==U&&_.toLowerCase()===U.toLowerCase())return{srcStat:J,destStat:O,isChangingCase:!0};throw new Error("Source and destination must not be the same.")}if(J.isDirectory()&&!O.isDirectory())throw new Error(`Cannot overwrite non-directory '${n}' with directory '${q}'.`);if(!J.isDirectory()&&O.isDirectory())throw new Error(`Cannot overwrite directory '${n}' with non-directory '${q}'.`)}if(J.isDirectory()&&kq(q,n))throw new Error(Zq(q,n,E));return{srcStat:J,destStat:O}}function By(q,n,E,y){let{srcStat:J,destStat:O}=Ry(q,n,y);if(O){if(Oq(J,O)){let _=W.basename(q),U=W.basename(n);if(E==="move"&&_!==U&&_.toLowerCase()===U.toLowerCase())return{srcStat:J,destStat:O,isChangingCase:!0};throw new Error("Source and destination must not be the same.")}if(J.isDirectory()&&!O.isDirectory())throw new Error(`Cannot overwrite non-directory '${n}' with directory '${q}'.`);if(!J.isDirectory()&&O.isDirectory())throw new Error(`Cannot overwrite directory '${n}' with non-directory '${q}'.`)}if(J.isDirectory()&&kq(q,n))throw new Error(Zq(q,n,E));return{srcStat:J,destStat:O}}async function Un(q,n,E,y){let J=W.resolve(W.dirname(q)),O=W.resolve(W.dirname(E));if(O===J||O===W.parse(O).root)return;let _;try{_=await Eq.stat(O,{bigint:!0})}catch(U){if(U.code==="ENOENT")return;throw U}if(Oq(n,_))throw new Error(Zq(q,E,y));return Un(q,n,O,y)}function zn(q,n,E,y){let J=W.resolve(W.dirname(q)),O=W.resolve(W.dirname(E));if(O===J||O===W.parse(O).root)return;let _;try{_=Eq.statSync(O,{bigint:!0})}catch(U){if(U.code==="ENOENT")return;throw U}if(Oq(n,_))throw new Error(Zq(q,E,y));return zn(q,n,O,y)}function Oq(q,n){return n.ino&&n.dev&&n.ino===q.ino&&n.dev===q.dev}function kq(q,n){let E=W.resolve(q).split(W.sep).filter((J)=>J),y=W.resolve(n).split(W.sep).filter((J)=>J);return E.every((J,O)=>y[O]===J)}function Zq(q,n,E){return`Cannot ${E} '${q}' to a subdirectory of itself, '${n}'.`}Ln.exports={checkPaths:Kn(wy),checkPathsSync:By,checkParentPaths:Kn(Un),checkParentPathsSync:zn,isSrcSubdir:kq,areIdentical:Oq}});var Yn=X((BO,Xn)=>{var v=g(),_q=u("node:path"),{mkdirs:Dy}=l(),{pathExists:Iy}=d(),{utimesMillis:uy}=Tq(),Vq=t();async function Qy(q,n,E={}){if(typeof E==="function")E={filter:E};if(E.clobber="clobber"in E?!!E.clobber:!0,E.overwrite="overwrite"in E?!!E.overwrite:E.clobber,E.preserveTimestamps&&process.arch==="ia32")process.emitWarning(`Using the preserveTimestamps option in 32-bit node is not recommended;
4
-
5
- see https://github.com/jprichardson/node-fs-extra/issues/269`,"Warning","fs-extra-WARN0001");let{srcStat:y,destStat:J}=await Vq.checkPaths(q,n,"copy",E);if(await Vq.checkParentPaths(q,y,n,"copy"),!await An(q,n,E))return;let _=_q.dirname(n);if(!await Iy(_))await Dy(_);await Gn(J,q,n,E)}async function An(q,n,E){if(!E.filter)return!0;return E.filter(q,n)}async function Gn(q,n,E,y){let O=await(y.dereference?v.stat:v.lstat)(n);if(O.isDirectory())return ky(O,q,n,E,y);if(O.isFile()||O.isCharacterDevice()||O.isBlockDevice())return Wy(O,q,n,E,y);if(O.isSymbolicLink())return Fy(q,n,E,y);if(O.isSocket())throw new Error(`Cannot copy a socket file: ${n}`);if(O.isFIFO())throw new Error(`Cannot copy a FIFO pipe: ${n}`);throw new Error(`Unknown file: ${n}`)}async function Wy(q,n,E,y,J){if(!n)return Pn(q,E,y,J);if(J.overwrite)return await v.unlink(y),Pn(q,E,y,J);if(J.errorOnExist)throw new Error(`'${y}' already exists`)}async function Pn(q,n,E,y){if(await v.copyFile(n,E),y.preserveTimestamps){if(My(q.mode))await Ty(E,q.mode);let J=await v.stat(n);await uy(E,J.atime,J.mtime)}return v.chmod(E,q.mode)}function My(q){return(q&128)===0}function Ty(q,n){return v.chmod(q,n|128)}async function ky(q,n,E,y,J){if(!n)await v.mkdir(y);let O=[];for await(let _ of await v.opendir(E)){let U=_q.join(E,_.name),j=_q.join(y,_.name);O.push(An(U,j,J).then(($)=>{if($)return Vq.checkPaths(U,j,"copy",J).then(({destStat:V})=>{return Gn(V,U,j,J)})}))}if(await Promise.all(O),!n)await v.chmod(y,q.mode)}async function Fy(q,n,E,y){let J=await v.readlink(n);if(y.dereference)J=_q.resolve(process.cwd(),J);if(!q)return v.symlink(J,E);let O=null;try{O=await v.readlink(E)}catch(_){if(_.code==="EINVAL"||_.code==="UNKNOWN")return v.symlink(J,E);throw _}if(y.dereference)O=_q.resolve(process.cwd(),O);if(Vq.isSrcSubdir(J,O))throw new Error(`Cannot copy '${J}' to a subdirectory of itself, '${O}'.`);if(Vq.isSrcSubdir(O,J))throw new Error(`Cannot overwrite '${O}' with '${J}'.`);return await v.unlink(E),v.symlink(J,E)}Xn.exports=Qy});var xn=X((DO,Nn)=>{var b=qq(),Kq=u("node:path"),$y=l().mkdirsSync,vy=Tq().utimesMillisSync,Uq=t();function my(q,n,E){if(typeof E==="function")E={filter:E};if(E=E||{},E.clobber="clobber"in E?!!E.clobber:!0,E.overwrite="overwrite"in E?!!E.overwrite:E.clobber,E.preserveTimestamps&&process.arch==="ia32")process.emitWarning(`Using the preserveTimestamps option in 32-bit node is not recommended;
6
-
7
- see https://github.com/jprichardson/node-fs-extra/issues/269`,"Warning","fs-extra-WARN0002");let{srcStat:y,destStat:J}=Uq.checkPathsSync(q,n,"copy",E);if(Uq.checkParentPathsSync(q,y,n,"copy"),E.filter&&!E.filter(q,n))return;let O=Kq.dirname(n);if(!b.existsSync(O))$y(O);return Zn(J,q,n,E)}function Zn(q,n,E,y){let O=(y.dereference?b.statSync:b.lstatSync)(n);if(O.isDirectory())return py(O,q,n,E,y);else if(O.isFile()||O.isCharacterDevice()||O.isBlockDevice())return Sy(O,q,n,E,y);else if(O.isSymbolicLink())return fy(q,n,E,y);else if(O.isSocket())throw new Error(`Cannot copy a socket file: ${n}`);else if(O.isFIFO())throw new Error(`Cannot copy a FIFO pipe: ${n}`);throw new Error(`Unknown file: ${n}`)}function Sy(q,n,E,y,J){if(!n)return Cn(q,E,y,J);return gy(q,E,y,J)}function gy(q,n,E,y){if(y.overwrite)return b.unlinkSync(E),Cn(q,n,E,y);else if(y.errorOnExist)throw new Error(`'${E}' already exists`)}function Cn(q,n,E,y){if(b.copyFileSync(n,E),y.preserveTimestamps)by(q.mode,n,E);return Fq(E,q.mode)}function by(q,n,E){if(iy(q))hy(E,q);return ly(n,E)}function iy(q){return(q&128)===0}function hy(q,n){return Fq(q,n|128)}function Fq(q,n){return b.chmodSync(q,n)}function ly(q,n){let E=b.statSync(q);return vy(n,E.atime,E.mtime)}function py(q,n,E,y,J){if(!n)return cy(q.mode,E,y,J);return Hn(E,y,J)}function cy(q,n,E,y){return b.mkdirSync(E),Hn(n,E,y),Fq(E,q)}function Hn(q,n,E){let y=b.opendirSync(q);try{let J;while((J=y.readSync())!==null)oy(J.name,q,n,E)}finally{y.closeSync()}}function oy(q,n,E,y){let J=Kq.join(n,q),O=Kq.join(E,q);if(y.filter&&!y.filter(J,O))return;let{destStat:_}=Uq.checkPathsSync(J,O,"copy",y);return Zn(_,J,O,y)}function fy(q,n,E,y){let J=b.readlinkSync(n);if(y.dereference)J=Kq.resolve(process.cwd(),J);if(!q)return b.symlinkSync(J,E);else{let O;try{O=b.readlinkSync(E)}catch(_){if(_.code==="EINVAL"||_.code==="UNKNOWN")return b.symlinkSync(J,E);throw _}if(y.dereference)O=Kq.resolve(process.cwd(),O);if(Uq.isSrcSubdir(J,O))throw new Error(`Cannot copy '${J}' to a subdirectory of itself, '${O}'.`);if(Uq.isSrcSubdir(O,J))throw new Error(`Cannot overwrite '${O}' with '${J}'.`);return dy(J,E)}}function dy(q,n){return b.unlinkSync(n),b.symlinkSync(q,n)}Nn.exports=my});var Cq=X((IO,jn)=>{var ry=Q().fromPromise;jn.exports={copy:ry(Yn()),copySync:xn()}});var zq=X((uO,wn)=>{var Rn=qq(),ay=Q().fromCallback;function ey(q,n){Rn.rm(q,{recursive:!0,force:!0},n)}function ty(q){Rn.rmSync(q,{recursive:!0,force:!0})}wn.exports={remove:ay(ey),removeSync:ty}});var Tn=X((QO,Mn)=>{var sy=Q().fromPromise,In=g(),un=u("node:path"),Qn=l(),Wn=zq(),Bn=sy(async function q(n){let E;try{E=await In.readdir(n)}catch{return Qn.mkdirs(n)}return Promise.all(E.map((y)=>Wn.remove(un.join(n,y))))});function Dn(q){let n;try{n=In.readdirSync(q)}catch{return Qn.mkdirsSync(q)}n.forEach((E)=>{E=un.join(q,E),Wn.removeSync(E)})}Mn.exports={emptyDirSync:Dn,emptydirSync:Dn,emptyDir:Bn,emptydir:Bn}});var vn=X((WO,$n)=>{var qJ=Q().fromPromise,kn=u("node:path"),c=g(),Fn=l();async function nJ(q){let n;try{n=await c.stat(q)}catch{}if(n&&n.isFile())return;let E=kn.dirname(q),y=null;try{y=await c.stat(E)}catch(J){if(J.code==="ENOENT"){await Fn.mkdirs(E),await c.writeFile(q,"");return}else throw J}if(y.isDirectory())await c.writeFile(q,"");else await c.readdir(E)}function EJ(q){let n;try{n=c.statSync(q)}catch{}if(n&&n.isFile())return;let E=kn.dirname(q);try{if(!c.statSync(E).isDirectory())c.readdirSync(E)}catch(y){if(y&&y.code==="ENOENT")Fn.mkdirsSync(E);else throw y}c.writeFileSync(q,"")}$n.exports={createFile:qJ(nJ),createFileSync:EJ}});var hn=X((MO,bn)=>{var yJ=Q().fromPromise,mn=u("node:path"),r=g(),Sn=l(),{pathExists:JJ}=d(),{areIdentical:gn}=t();async function OJ(q,n){let E;try{E=await r.lstat(n)}catch{}let y;try{y=await r.lstat(q)}catch(_){throw _.message=_.message.replace("lstat","ensureLink"),_}if(E&&gn(y,E))return;let J=mn.dirname(n);if(!await JJ(J))await Sn.mkdirs(J);await r.link(q,n)}function _J(q,n){let E;try{E=r.lstatSync(n)}catch{}try{let O=r.lstatSync(q);if(E&&gn(O,E))return}catch(O){throw O.message=O.message.replace("lstat","ensureLink"),O}let y=mn.dirname(n);if(r.existsSync(y))return r.linkSync(q,n);return Sn.mkdirsSync(y),r.linkSync(q,n)}bn.exports={createLink:yJ(OJ),createLinkSync:_J}});var pn=X((TO,ln)=>{var a=u("node:path"),Lq=g(),{pathExists:VJ}=d(),KJ=Q().fromPromise;async function UJ(q,n){if(a.isAbsolute(q)){try{await Lq.lstat(q)}catch(O){throw O.message=O.message.replace("lstat","ensureSymlink"),O}return{toCwd:q,toDst:q}}let E=a.dirname(n),y=a.join(E,q);if(await VJ(y))return{toCwd:y,toDst:q};try{await Lq.lstat(q)}catch(O){throw O.message=O.message.replace("lstat","ensureSymlink"),O}return{toCwd:q,toDst:a.relative(E,q)}}function zJ(q,n){if(a.isAbsolute(q)){if(!Lq.existsSync(q))throw new Error("absolute srcpath does not exist");return{toCwd:q,toDst:q}}let E=a.dirname(n),y=a.join(E,q);if(Lq.existsSync(y))return{toCwd:y,toDst:q};if(!Lq.existsSync(q))throw new Error("relative srcpath does not exist");return{toCwd:q,toDst:a.relative(E,q)}}ln.exports={symlinkPaths:KJ(UJ),symlinkPathsSync:zJ}});var fn=X((kO,on)=>{var cn=g(),LJ=Q().fromPromise;async function PJ(q,n){if(n)return n;let E;try{E=await cn.lstat(q)}catch{return"file"}return E&&E.isDirectory()?"dir":"file"}function AJ(q,n){if(n)return n;let E;try{E=cn.lstatSync(q)}catch{return"file"}return E&&E.isDirectory()?"dir":"file"}on.exports={symlinkType:LJ(PJ),symlinkTypeSync:AJ}});var en=X((FO,an)=>{var GJ=Q().fromPromise,dn=u("node:path"),p=g(),{mkdirs:XJ,mkdirsSync:YJ}=l(),{symlinkPaths:ZJ,symlinkPathsSync:CJ}=pn(),{symlinkType:HJ,symlinkTypeSync:NJ}=fn(),{pathExists:xJ}=d(),{areIdentical:rn}=t();async function jJ(q,n,E){let y;try{y=await p.lstat(n)}catch{}if(y&&y.isSymbolicLink()){let[U,j]=await Promise.all([p.stat(q),p.stat(n)]);if(rn(U,j))return}let J=await ZJ(q,n);q=J.toDst;let O=await HJ(J.toCwd,E),_=dn.dirname(n);if(!await xJ(_))await XJ(_);return p.symlink(q,n,O)}function RJ(q,n,E){let y;try{y=p.lstatSync(n)}catch{}if(y&&y.isSymbolicLink()){let U=p.statSync(q),j=p.statSync(n);if(rn(U,j))return}let J=CJ(q,n);q=J.toDst,E=NJ(J.toCwd,E);let O=dn.dirname(n);if(p.existsSync(O))return p.symlinkSync(q,n,E);return YJ(O),p.symlinkSync(q,n,E)}an.exports={createSymlink:GJ(jJ),createSymlinkSync:RJ}});var OE=X(($O,JE)=>{var{createFile:tn,createFileSync:sn}=vn(),{createLink:qE,createLinkSync:nE}=hn(),{createSymlink:EE,createSymlinkSync:yE}=en();JE.exports={createFile:tn,createFileSync:sn,ensureFile:tn,ensureFileSync:sn,createLink:qE,createLinkSync:nE,ensureLink:qE,ensureLinkSync:nE,createSymlink:EE,createSymlinkSync:yE,ensureSymlink:EE,ensureSymlinkSync:yE}});var Hq=X((vO,_E)=>{function wJ(q,{EOL:n=`
8
- `,finalEOL:E=!0,replacer:y=null,spaces:J}={}){let O=E?n:"";return JSON.stringify(q,y,J).replace(/\n/g,n)+O}function BJ(q){if(Buffer.isBuffer(q))q=q.toString("utf8");return q.replace(/^\uFEFF/,"")}_E.exports={stringify:wJ,stripBom:BJ}});var zE=X((mO,UE)=>{var yq;try{yq=qq()}catch(q){yq=u("node:fs")}var Nq=Q(),{stringify:VE,stripBom:KE}=Hq();async function DJ(q,n={}){if(typeof n==="string")n={encoding:n};let E=n.fs||yq,y="throws"in n?n.throws:!0,J=await Nq.fromCallback(E.readFile)(q,n);J=KE(J);let O;try{O=JSON.parse(J,n?n.reviver:null)}catch(_){if(y)throw _.message=`${q}: ${_.message}`,_;else return null}return O}var IJ=Nq.fromPromise(DJ);function uJ(q,n={}){if(typeof n==="string")n={encoding:n};let E=n.fs||yq,y="throws"in n?n.throws:!0;try{let J=E.readFileSync(q,n);return J=KE(J),JSON.parse(J,n.reviver)}catch(J){if(y)throw J.message=`${q}: ${J.message}`,J;else return null}}async function QJ(q,n,E={}){let y=E.fs||yq,J=VE(n,E);await Nq.fromCallback(y.writeFile)(q,J,E)}var WJ=Nq.fromPromise(QJ);function MJ(q,n,E={}){let y=E.fs||yq,J=VE(n,E);return y.writeFileSync(q,J,E)}var TJ={readFile:IJ,readFileSync:uJ,writeFile:WJ,writeFileSync:MJ};UE.exports=TJ});var PE=X((SO,LE)=>{var xq=zE();LE.exports={readJson:xq.readFile,readJsonSync:xq.readFileSync,writeJson:xq.writeFile,writeJsonSync:xq.writeFileSync}});var jq=X((gO,XE)=>{var kJ=Q().fromPromise,$q=g(),AE=u("node:path"),GE=l(),FJ=d().pathExists;async function $J(q,n,E="utf-8"){let y=AE.dirname(q);if(!await FJ(y))await GE.mkdirs(y);return $q.writeFile(q,n,E)}function vJ(q,...n){let E=AE.dirname(q);if(!$q.existsSync(E))GE.mkdirsSync(E);$q.writeFileSync(q,...n)}XE.exports={outputFile:kJ($J),outputFileSync:vJ}});var ZE=X((bO,YE)=>{var{stringify:mJ}=Hq(),{outputFile:SJ}=jq();async function gJ(q,n,E={}){let y=mJ(n,E);await SJ(q,y,E)}YE.exports=gJ});var HE=X((iO,CE)=>{var{stringify:bJ}=Hq(),{outputFileSync:iJ}=jq();function hJ(q,n,E){let y=bJ(n,E);iJ(q,y,E)}CE.exports=hJ});var xE=X((hO,NE)=>{var lJ=Q().fromPromise,i=PE();i.outputJson=lJ(ZE());i.outputJsonSync=HE();i.outputJSON=i.outputJson;i.outputJSONSync=i.outputJsonSync;i.writeJSON=i.writeJson;i.writeJSONSync=i.writeJsonSync;i.readJSON=i.readJson;i.readJSONSync=i.readJsonSync;NE.exports=i});var DE=X((lO,BE)=>{var pJ=g(),jE=u("node:path"),{copy:cJ}=Cq(),{remove:wE}=zq(),{mkdirp:oJ}=l(),{pathExists:fJ}=d(),RE=t();async function dJ(q,n,E={}){let y=E.overwrite||E.clobber||!1,{srcStat:J,isChangingCase:O=!1}=await RE.checkPaths(q,n,"move",E);await RE.checkParentPaths(q,J,n,"move");let _=jE.dirname(n);if(jE.parse(_).root!==_)await oJ(_);return rJ(q,n,y,O)}async function rJ(q,n,E,y){if(!y){if(E)await wE(n);else if(await fJ(n))throw new Error("dest already exists.")}try{await pJ.rename(q,n)}catch(J){if(J.code!=="EXDEV")throw J;await aJ(q,n,E)}}async function aJ(q,n,E){return await cJ(q,n,{overwrite:E,errorOnExist:!0,preserveTimestamps:!0}),wE(q)}BE.exports=dJ});var ME=X((pO,WE)=>{var uE=qq(),mq=u("node:path"),eJ=Cq().copySync,QE=zq().removeSync,tJ=l().mkdirpSync,IE=t();function sJ(q,n,E){E=E||{};let y=E.overwrite||E.clobber||!1,{srcStat:J,isChangingCase:O=!1}=IE.checkPathsSync(q,n,"move",E);if(IE.checkParentPathsSync(q,J,n,"move"),!qO(n))tJ(mq.dirname(n));return nO(q,n,y,O)}function qO(q){let n=mq.dirname(q);return mq.parse(n).root===n}function nO(q,n,E,y){if(y)return vq(q,n,E);if(E)return QE(n),vq(q,n,E);if(uE.existsSync(n))throw new Error("dest already exists.");return vq(q,n,E)}function vq(q,n,E){try{uE.renameSync(q,n)}catch(y){if(y.code!=="EXDEV")throw y;return EO(q,n,E)}}function EO(q,n,E){return eJ(q,n,{overwrite:E,errorOnExist:!0,preserveTimestamps:!0}),QE(q)}WE.exports=sJ});var kE=X((cO,TE)=>{var yO=Q().fromPromise;TE.exports={move:yO(DE()),moveSync:ME()}});var $E=X((oO,FE)=>{FE.exports={...g(),...Cq(),...Tn(),...OE(),...xE(),...l(),...kE(),...jq(),...d(),...zq()}});var Sq=lE($E(),1);import OO from"node:process";import{projectPath as _O}from"@stacksjs/path";import{ValidationBoolean as VO,ValidationEnum as KO,ValidationNumber as UO}from"@stacksjs/validation";import{schema as o}from"@stacksjs/validation";import{schema as G}from"@stacksjs/validation";var vE={APP_NAME:{validation:G.string(),default:"Stacks"},APP_ENV:{validation:G.enum(["local","dev","stage","prod"]),default:"local"},APP_KEY:{validation:G.string(),default:"base64:1234567890"},PORT:{validation:G.number(),default:3000},PORT_BACKEND:{validation:G.number(),default:3000},PORT_ADMIN:{validation:G.number(),default:3000},PORT_LIBRARY:{validation:G.number(),default:3000},PORT_DESKTOP:{validation:G.number(),default:3000},PORT_EMAIL:{validation:G.number(),default:3000},PORT_DOCS:{validation:G.number(),default:3000},PORT_INSPECT:{validation:G.number(),default:3000},PORT_API:{validation:G.number(),default:3000},PORT_SYSTEM_TRAY:{validation:G.number(),default:3000},APP_MAINTENANCE:{validation:G.boolean(),default:!1},DEBUG:{validation:G.boolean(),default:!1},API_PREFIX:{validation:G.string(),default:"/api"},DOCS_PREFIX:{validation:G.string(),default:"/docs"},DB_CONNECTION:{validation:G.enum(["mysql","sqlite","postgres"]),default:"mysql"},DB_HOST:{validation:G.string(),default:"localhost"},DB_PORT:{validation:G.number(),default:3306},AWS_ACCOUNT_ID:{validation:G.string(),default:""},AWS_ACCESS_KEY_ID:{validation:G.string(),default:""},AWS_SECRET_ACCESS_KEY:{validation:G.string(),default:""},AWS_DEFAULT_REGION:{validation:G.string(),default:""},AWS_DEFAULT_PASSWORD:{validation:G.string(),default:""},MAIL_MAILER:{validation:G.enum(["ses","sendmail","log","smtp"]),default:"ses"},MAIL_HOST:{validation:G.string(),default:""},MAIL_PORT:{validation:G.number(),default:465},MAIL_USERNAME:{validation:G.string(),default:""},MAIL_PASSWORD:{validation:G.string(),default:""},MAIL_FROM_ADDRESS:{validation:G.string(),default:""},SEARCH_ENGINE_DRIVER:{validation:G.enum(["meilisearch","algolia","typesense"]),default:"meilisearch"},MEILISEARCH_HOST:{validation:G.string(),default:""},MEILISEARCH_KEY:{validation:G.string(),default:""},FRONTEND_APP_ENV:{validation:G.enum(["development","staging","production"]),default:"development"},FRONTEND_APP_URL:{validation:G.string(),default:""}};var mE={APP_ENV:["local","dev","development","staging","prod","production"],DB_CONNECTION:["mysql","sqlite","postgres","dynamodb"],MAIL_MAILER:["smtp","mailgun","ses","postmark","sendmail","log"],SEARCH_ENGINE_DRIVER:["opensearch"],FRONTEND_APP_ENV:["development","staging","production"]},JO=Object.entries(vE).reduce((q,[n,E])=>{if(typeof E==="object"&&E!==null&&"validation"in E)return q[n]=E.validation,q;let y;switch(typeof E){case"string":y=o.string();break;case"number":y=o.number();break;case"boolean":y=o.boolean();break;default:if(Array.isArray(E)){y=o.enum(E);break}if(typeof E==="object"&&E!==null){let J=Symbol.for("schema_name"),O=E[J];if(O==="vine.string"){y=o.string();break}if(O==="vine.number"){y=o.number();break}if(O==="vine.boolean"){y=o.boolean();break}if(!O&&n in mE){y=o.enum(mE[n]);break}console.error("Unknown env value type",typeof E)}throw new Error(`Invalid env value for ${n}`)}return q[n]=y,q},{}),eO=o.object(JO);var zO={get:(q,n)=>{let E=q[n];if(typeof E==="string"&&/^\d+$/.test(E)&&n!=="AWS_ACCOUNT_ID")return Number(E);if(typeof E==="string"&&/^true|false$/.test(E))return E==="true";if(E instanceof KO)return q[n];if(E instanceof VO)return!!q[n];if(E instanceof UO)return Number(q[n]);return E}};function LO(){return typeof Bun!=="undefined"?Bun.env:OO.env}var E_=new Proxy(LO(),zO);function y_(q,n,E){let y=E?.path||_O(".env"),O=Sq.default.readFileSync(y,"utf-8").split(`
9
- `),_=O.findIndex((U)=>U.startsWith(`${q}=`));if(_!==-1)O[_]=`${q}=${n}`;else O.push(`${q}=${n}`);Sq.default.writeFileSync(y,O.join(`
10
- `))}export{y_ as writeEnv,LO as process,eO as envSchema,mE as envEnum,E_ as env};
2
+ import XJ from"process";import{projectPath as jJ}from"@stacksjs/path";import y from"fs";var K={APP_ENV:["local","dev","development","staging","prod","production"],DB_CONNECTION:["mysql","sqlite","postgres","dynamodb"],MAIL_MAILER:["smtp","mailgun","ses","postmark","sendmail","log","sendgrid","mailtrap"],SEARCH_ENGINE_DRIVER:["opensearch","meilisearch","algolia","typesense"],FRONTEND_APP_ENV:["development","staging","production"]};import{createCipheriv as p,createDecipheriv as i,createHash as f,randomBytes as m}from"crypto";function a(J,Q){let $=m(16),z=Q.length===32?Q:Buffer.from(Q.toString("hex").slice(0,64),"hex"),Z=p("aes-256-gcm",z,$),X=Buffer.concat([Z.update(J,"utf8"),Z.final()]),W=Z.getAuthTag();return{ciphertext:X.toString("hex"),iv:$.toString("hex"),authTag:W.toString("hex")}}function n(J,Q,$,z){let Z=Q.length===32?Q:Buffer.from(Q.toString("hex").slice(0,64),"hex");try{let X=i("aes-256-gcm",Z,Buffer.from($,"hex"));return X.setAuthTag(Buffer.from(z,"hex")),Buffer.concat([X.update(Buffer.from(J,"hex")),X.final()]).toString("utf8")}catch(X){throw Error(`Decryption failed (data may be corrupted or key is incorrect): ${X instanceof Error?X.message:String(X)}`)}}function b(){let J=m(32);return{publicKey:f("sha256").update(J).digest().toString("hex"),privateKey:J.toString("hex")}}function S(J,Q){let $=f("sha256").update(Buffer.from(Q,"hex")).digest(),{ciphertext:z,iv:Z,authTag:X}=a(J,$);return`encrypted:${Buffer.concat([Buffer.from(Z,"hex"),Buffer.from(X,"hex"),Buffer.from(z,"hex")]).toString("base64")}`}function x(J,Q){if(!J.startsWith("encrypted:"))return J;let $=J.slice(10),z=Buffer.from($,"base64");if(z.length<32)throw Error("Invalid encrypted data: payload too short (need at least iv + authTag = 32 bytes)");let Z=z.subarray(0,16).toString("hex"),X=z.subarray(16,32).toString("hex"),W=z.subarray(32).toString("hex"),H=f("sha256").update(Buffer.from(Q,"hex")).digest(),G=f("sha256").update(H).digest();return n(W,G,Z,X)}function AJ(J){let Q=J.match(/^DOTENV_PRIVATE_KEY_(.+)$/);return Q&&Q[1]?Q[1].toLowerCase():""}function h(J=""){if(!J)return process.env.DOTENV_PRIVATE_KEY;let Q=`DOTENV_PRIVATE_KEY_${J.toUpperCase()}`;return process.env[Q]}function C(J,Q={}){let $={},z=[],Z=J.split(`
3
+ `);for(let X of Z){let W=X.trim();if(!W||W.startsWith("#"))continue;if(W.startsWith("DOTENV_PUBLIC_KEY=")){let O=W.match(/^DOTENV_PUBLIC_KEY=["']?([^"'\n]+)["']?/);if(O&&O[1]!==void 0)$.DOTENV_PUBLIC_KEY=O[1];continue}let H=W.match(/^([^=]+)=(.*)$/);if(!H||H[1]===void 0||H[2]===void 0)continue;let G=H[1].trim(),j=H[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(Q.privateKey&&(j.startsWith("encrypted:")||j.startsWith("enc:")))try{let O=j.startsWith("enc:")?`encrypted:${j.slice(4)}`:j;j=x(O,Q.privateKey)}catch(O){z.push(`Failed to decrypt ${G}: ${O instanceof Error?O.message:"Unknown error"}`)}j=r(j,{...Q.processEnv||process.env,...$}),j=s(j),$[G]=j}return{parsed:$,errors:z}}function r(J,Q){return J.replace(/\$\{([^}]+)\}/g,($,z)=>{let Z=z.match(/^([^:\-+]+)(:-|-)(.+)$/);if(Z){let[,W,H,G]=Z,j=Q[W];if(H===":-")return j||G;else return j!==void 0?j:G}let X=z.match(/^([^:\-+]+)(:?\+)(.+)$/);if(X){let[,W,H,G]=X,j=Q[W];if(H===":+")return j?G:"";else return j!==void 0?G:""}return Q[z]||""})}var o=new Set(["date","hostname","whoami","uname","pwd","echo","printf","cat","basename","dirname"]);function s(J){return J.replace(/\$\(([^)]+)\)/g,(Q,$)=>{try{let z=$.trim().split(/\s+/),Z=z[0];if(!Z||!o.has(Z))return console.warn(`[env] Blocked command substitution for disallowed command: ${Z}`),"";let X=Bun.spawnSync(z,{stdout:"pipe",stderr:"pipe"});if(X.exitCode===0)return new TextDecoder().decode(X.stdout).trim();console.warn(`[env] Command substitution failed (exit code ${X.exitCode}): ${Z}`)}catch(z){console.warn(`[env] Command substitution error: ${z instanceof Error?z.message:String(z)}`)}return""})}async function _J(J,Q={}){let $={},z=[];for(let Z of J)try{let X=Bun.file(Z);if(!X.size)continue;let W=await X.text(),{parsed:H,errors:G}=C(W,Q);z.push(...G);for(let[j,O]of Object.entries(H)){if(!Q.overload&&$[j]!==void 0)continue;$[j]=O}}catch(X){if(X?.code==="ENOENT")continue;z.push(`Failed to read ${Z}: ${X instanceof Error?X.message:String(X)}`)}return{parsed:$,errors:z}}import{existsSync as F}from"fs";import{readFileSync as k}from"fs";import{resolve as V}from"path";function d(J={}){let{path:Q=[".env"],overload:$=!1,env:z,privateKey:Z,keysFile:X,quiet:W=!1,cwd:H=process.cwd()}=J,G=Array.isArray(Q)?Q:[Q],j=[],O=0,Y=Z;if(!Y&&X){let U=V(H,X);if(F(U))try{let A=k(U,"utf-8"),{parsed:B}=C(A);if(z){let M=`DOTENV_PRIVATE_KEY_${z.toUpperCase()}`;Y=B[M]}else Y=B.DOTENV_PRIVATE_KEY}catch(A){j.push(`Failed to load keys file: ${A instanceof Error?A.message:"Unknown error"}`)}}if(!Y)Y=h(z||"");for(let U of G){let A=V(H,U);if(!F(A)){if(!W)j.push(`File not found: ${A}`);continue}try{let B=k(A,"utf-8"),{parsed:M,errors:q}=C(B,{privateKey:Y,processEnv:process.env});j.push(...q);for(let[I,R]of Object.entries(M)){if(I==="DOTENV_PUBLIC_KEY")continue;if($||process.env[I]===void 0)process.env[I]=R,O++}if(!W&&!process.env.__ENV_LOADED__)console.log(`[env] loaded ${Object.keys(M).length} variables from ${U}`),process.env.__ENV_LOADED__="1"}catch(B){j.push(`Failed to load ${A}: ${B instanceof Error?B.message:"Unknown error"}`)}}return{loaded:O,errors:j}}function CJ(J={}){return{name:"env-plugin",setup(Q){d(J)}}}function LJ(J={}){let Q=J.env||"development",$=J.cwd||process.cwd(),z=[],Z=`.env.${Q}`,X=`.env.${Q}.local`;if(F(V($,X)))z.push(X);if(F(V($,Z)))z.push(Z);if(F(V($,".env.local")))z.push(".env.local");if(F(V($,".env")))z.push(".env");return d({...J,path:z,env:Q})}import{existsSync as g,readFileSync as L,writeFileSync as E}from"fs";import{resolve as T}from"path";function t(J={}){let Q=J.cwd||process.cwd(),$=T(Q,J.file||".env"),z=T(Q,J.keysFile||".env.keys");if(!g($))return{success:!1,error:`File not found: ${$}`};try{let Z,X;if(g(z)){let U=L(z,"utf-8"),{parsed:A}=C(U),q=((J.file||".env").split("/").pop()||"").replace(/^\.env\./,"").replace(/^\.env$/,"").toUpperCase(),I=q?`DOTENV_PUBLIC_KEY_${q}`:"DOTENV_PUBLIC_KEY",R=q?`DOTENV_PRIVATE_KEY_${q}`:"DOTENV_PRIVATE_KEY";if(Z=A[I]||"",X=A[R]||"",!Z||!X){let D=b();Z=D.publicKey,X=D.privateKey;let w=`
5
+ ${I}="${Z}"
6
+ ${R}="${X}"
7
+ `;E(z,U+w,"utf-8")}}else{let U=b();Z=U.publicKey,X=U.privateKey;let M=((J.file||".env").split("/").pop()||"").replace(/^\.env\./,"").replace(/^\.env$/,"").toUpperCase(),q=M?`DOTENV_PUBLIC_KEY_${M}`:"DOTENV_PUBLIC_KEY",I=M?`DOTENV_PRIVATE_KEY_${M}`:"DOTENV_PRIVATE_KEY",R=`# .env.keys - Keep this file secure and never commit to source control
8
+ ${q}="${Z}"
9
+ ${I}="${X}"
10
+ `;E(z,R,"utf-8")}let H=L($,"utf-8").split(`
11
+ `),G=[],j=J.file?J.file.replace(/^\.env\./,"").toUpperCase():"",O=j?`DOTENV_PUBLIC_KEY_${j}`:"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 H){let A=U.trim();if(!A||A.startsWith("#")){G.push(U);continue}if(A.startsWith("DOTENV_PUBLIC_KEY"))continue;let B=A.match(/^([^=]+)=(.*)$/);if(!B||B[1]===void 0||B[2]===void 0){G.push(U);continue}let M=B[1].trim(),q=B[2].trim();if(q.startsWith('"')&&q.endsWith('"')||q.startsWith("'")&&q.endsWith("'"))q=q.slice(1,-1);let I=!0;if(J.key&&!M.includes(J.key))I=!1;if(J.excludeKey&&M.includes(J.excludeKey))I=!1;if(q.startsWith("encrypted:"))I=!1;if(I)q=S(q,Z);G.push(`${M}="${q}"`)}let Y=G.join(`
12
+ `);if(J.stdout)return{success:!0,output:Y};return E($,Y,"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 e(J={}){let Q=J.cwd||process.cwd(),$=T(Q,J.file||".env"),z=T(Q,J.keysFile||".env.keys");if(!g($))return{success:!1,error:`File not found: ${$}`};if(!g(z))return{success:!1,error:`Keys file not found: ${z}`};try{let Z=L(z,"utf-8"),{parsed:X}=C(Z),G=((J.file||".env").split("/").pop()||"").replace(/^\.env\./,"").replace(/^\.env$/,"").toUpperCase(),j=G?`DOTENV_PRIVATE_KEY_${G}`:"DOTENV_PRIVATE_KEY",O=X[j];if(!O)return{success:!1,error:`Private key not found: ${j}`};let U=L($,"utf-8").split(`
14
+ `),A=[];for(let M of U){let q=M.trim();if(!q||q.startsWith("#")){A.push(M);continue}if(q.startsWith("DOTENV_PUBLIC_KEY"))continue;let I=q.match(/^([^=]+)=(.*)$/);if(!I||I[1]===void 0||I[2]===void 0){A.push(M);continue}let R=I[1].trim(),D=I[2].trim();if(D.startsWith('"')&&D.endsWith('"')||D.startsWith("'")&&D.endsWith("'"))D=D.slice(1,-1);let w=D.startsWith("encrypted:");if(J.key&&!R.includes(J.key))w=!1;if(w)D=x(D,O);A.push(`${R}="${D}"`)}let B=A.join(`
15
+ `);if(J.stdout)return{success:!0,output:B};return E($,B,"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 wJ(J,Q,$={}){let z=$.cwd||process.cwd(),Z=T(z,$.file||".env");try{let X="";if(g(Z))X=L(Z,"utf-8");let W=X.split(`
16
+ `),H=!1,G;for(let Y of W){let U=Y.trim();if(U.startsWith("DOTENV_PUBLIC_KEY=")){let A=U.match(/^DOTENV_PUBLIC_KEY=["']?([^"'\n]+)["']?/);if(A)G=A[1];break}}if(!$.plain&&!G){let Y=T(z,$.keysFile||".env.keys"),U=b();G=U.publicKey;let A="";if(g(Y))A=L(Y,"utf-8");let q=(($.file||".env").split("/").pop()||"").replace(/^\.env\./,"").replace(/^\.env$/,"").toUpperCase(),I=q?`DOTENV_PUBLIC_KEY_${q}`:"DOTENV_PUBLIC_KEY",R=q?`DOTENV_PRIVATE_KEY_${q}`:"DOTENV_PRIVATE_KEY";A+=`
17
+ ${I}="${U.publicKey}"
18
+ ${R}="${U.privateKey}"
19
+ `,E(Y,A,"utf-8"),W.unshift(`${I}="${G}"`)}let j=Q;if(!$.plain&&G)j=S(Q,G);for(let Y=0;Y<W.length;Y++){let U=W[Y];if(U===void 0)continue;if(U.trim().startsWith(`${J}=`)){W[Y]=`${J}="${j}"`,H=!0;break}}if(!H)W.push(`${J}="${j}"`);let O=W.join(`
20
+ `);return E(Z,O,"utf-8"),{success:!0,output:`set ${J}${$.plain?"":" with encryption"} (${$.file||".env"})`}}catch(X){return{success:!1,error:`Failed to set: ${X instanceof Error?X.message:"Unknown error"}`}}}function fJ(J,Q={}){let $=Q.cwd||process.cwd(),z=T($,Q.file||".env");if(!g(z))return{success:!1,error:`File not found: ${z}`};try{let Z,X=T($,Q.keysFile||".env.keys");if(g(X)){let O=L(X,"utf-8"),{parsed:Y}=C(O),B=((Q.file||".env").split("/").pop()||"").replace(/^\.env\./,"").replace(/^\.env$/,"").toUpperCase(),M=B?`DOTENV_PRIVATE_KEY_${B}`:"DOTENV_PRIVATE_KEY";Z=Y[M]}let W=L(z,"utf-8"),{parsed:H}=C(W,{privateKey:Z});if(J&&!Q.all){let O=H[J];if(O===void 0)return{success:!1,error:`Key not found: ${J}`};return{success:!0,output:O}}let G=Q.all?{...process.env,...H}:H,j;switch(Q.format){case"shell":j=Object.entries(G).map(([O,Y])=>`${O}=${Y}`).join(" ");break;case"eval":j=Object.entries(G).map(([O,Y])=>`${O}="${Y}"`).join(`
21
+ `);break;case"json":default:j=Q.prettyPrint?JSON.stringify(G,null,2):JSON.stringify(G);break}return{success:!0,output:j}}catch(Z){return{success:!1,error:`Failed to get: ${Z instanceof Error?Z.message:"Unknown error"}`}}}function xJ(J,Q={}){let $=Q.cwd||process.cwd(),z=T($,Q.keysFile||".env.keys");if(!g(z))return{success:!1,error:`Keys file not found: ${z}`};try{let Z=L(z,"utf-8"),{parsed:X}=C(Z),G=((Q.file||".env").split("/").pop()||"").replace(/^\.env\./,"").replace(/^\.env$/,"").toUpperCase(),j=G?`DOTENV_PUBLIC_KEY_${G}`:"DOTENV_PUBLIC_KEY",O=G?`DOTENV_PRIVATE_KEY_${G}`:"DOTENV_PRIVATE_KEY";if(J){let A=X[J];if(!A)return{success:!1,error:`Key not found: ${J}`};return{success:!0,output:A}}let Y={[j]:X[j],[O]:X[O]};return{success:!0,output:Q.format==="shell"?`${j}=${Y[j]} ${O}=${Y[O]}`:JSON.stringify(Y)}}catch(Z){return{success:!1,error:`Failed to get keypair: ${Z instanceof Error?Z.message:"Unknown error"}`}}}function SJ(J={}){let Q=e({file:J.file,keysFile:J.keysFile,stdout:!0,cwd:J.cwd});if(!Q.success)return Q;let $=J.cwd||process.cwd(),z=T($,J.file||".env"),Z=T($,J.keysFile||".env.keys");if(Q.output)E(z,Q.output,"utf-8");let X=b(),H=L(Z,"utf-8").split(`
22
+ `),G=J.file?J.file.replace(/^\.env\./,"").toUpperCase():"",j=G?`DOTENV_PUBLIC_KEY_${G}`:"DOTENV_PUBLIC_KEY",O=G?`DOTENV_PRIVATE_KEY_${G}`:"DOTENV_PRIVATE_KEY";for(let Y=0;Y<H.length;Y++){let U=H[Y];if(U===void 0)continue;if(U.startsWith(`${j}=`))H[Y]=`${j}="${X.publicKey}"`;else if(U.startsWith(`${O}=`))H[Y]=`${O}="${X.privateKey}"`}return E(Z,H.join(`
23
+ `),"utf-8"),t({file:J.file,keysFile:J.keysFile,key:J.key,excludeKey:J.excludeKey,stdout:J.stdout,cwd:J.cwd})}import _ from"process";import{platform as JJ}from"os";var u=typeof Bun<"u",c=typeof _<"u"&&_.versions?.node!==void 0,QJ=u?"bun":c?"node":"unknown",mJ={name:QJ,version:u?Bun.version:c?_.version:void 0},P=JJ(),hJ=P==="win32",kJ=P==="darwin",dJ=P==="linux",v=Boolean(_.stdout?.isTTY),uJ=typeof globalThis.window<"u",ZJ=Boolean(_.env.CI||_.env.CONTINUOUS_INTEGRATION||_.env.BUILD_NUMBER||_.env.RUN_ID),cJ=Boolean(_.env.DEBUG||_.env.VERBOSE||_.argv.includes("--debug")||_.argv.includes("--verbose")),$J=ZJ||!v,vJ=Boolean(!$J&&(v||_.env.COLORTERM||_.env.FORCE_COLOR||_.env.TERM&&_.env.TERM!=="dumb")),N={github:{name:"GitHub Actions",detected:Boolean(_.env.GITHUB_ACTIONS)},gitlab:{name:"GitLab CI",detected:Boolean(_.env.GITLAB_CI)},circle:{name:"CircleCI",detected:Boolean(_.env.CIRCLECI)},travis:{name:"Travis CI",detected:Boolean(_.env.TRAVIS)},jenkins:{name:"Jenkins",detected:Boolean(_.env.JENKINS_URL)},vercel:{name:"Vercel",detected:Boolean(_.env.VERCEL)},netlify:{name:"Netlify",detected:Boolean(_.env.NETLIFY)},heroku:{name:"Heroku",detected:Boolean(_.env.DYNO)},aws:{name:"AWS",detected:Boolean(_.env.AWS_REGION||_.env.AWS_LAMBDA_FUNCTION_NAME)},azure:{name:"Azure",detected:Boolean(_.env.AZURE_HTTP_USER_AGENT)},cloudflare:{name:"Cloudflare",detected:Boolean(_.env.CF_PAGES)},railway:{name:"Railway",detected:Boolean(_.env.RAILWAY_ENVIRONMENT)},render:{name:"Render",detected:Boolean(_.env.RENDER)}},zJ=Object.keys(N).find((J)=>{let Q=N[J];return Q!==void 0&&Q.detected})||"unknown",yJ=N[zJ]||{name:"Unknown",detected:!1};var GJ={get:(J,Q)=>{let $=J[Q],z=["_PORT","_TIMEOUT","_TTL","_SIZE","_LIMIT","_MAX","_MIN","_INTERVAL","_RETRIES","_CONCURRENCY","_WORKERS","_CONNECTIONS"];if(typeof $==="string"&&/^\d+$/.test($)&&!$.startsWith("0")&&z.some((Z)=>Q.endsWith(Z)))return Number($);if(typeof $==="string"){let Z=$.toLowerCase();if(Z==="true")return!0;if(Z==="false")return!1}return $}};function WJ(){return typeof Bun<"u"?Bun.env:XJ.env}var l=new Proxy(WJ(),GJ);function rJ(J,Q,$){let z=$?.path||jJ(".env"),X=y.readFileSync(z,"utf-8").split(`
24
+ `),W=X.findIndex((j)=>j.startsWith(`${J}=`)),G=/[\s"'#$\\]/.test(Q)?`"${Q.replace(/"/g,"\\\"")}"`:Q;if(W!==-1)X[W]=`${J}=${G}`;else X.push(`${J}=${G}`);y.writeFileSync(z,X.join(`
25
+ `))}function oJ(J=l){let Q=[];for(let[$,z]of Object.entries(K)){let Z=J[$];if(Z!==void 0&&Z!==""&&!z.includes(String(Z)))Q.push(`${$}="${Z}" is not valid. Allowed values: ${z.join(", ")}`)}return Q}function sJ(J,Q=l){let $=[];for(let z of J){let Z=Q[z];if(Z===void 0||Z===""||Z===null)$.push(z)}if($.length>0)throw Error(`[env] Missing required environment variable(s): ${$.join(", ")}. Set them in .env or your process environment before booting.`);return Q}export{rJ as writeEnv,oJ as validateEnv,wJ as setEnv,mJ as runtimeInfo,QJ as runtime,SJ as rotateKeypair,sJ as requireEnv,yJ as providerInfo,zJ as provider,WJ as process,P as platform,AJ as parseEnvFromKey,C as parse,_J as loadEnvFiles,d as loadEnv,hJ as isWindows,c as isNode,$J as isMinimal,kJ as isMacOS,dJ as isLinux,cJ as isDebug,vJ as isColorSupported,ZJ as isCI,u as isBun,uJ as hasWindow,v as hasTTY,h as getPrivateKey,xJ as getKeypair,fJ as getEnv,b as generateKeypair,CJ as envPlugin,K as envEnum,l as env,S as encryptValue,t as encryptEnv,x as decryptValue,e as decryptEnv,LJ as autoLoadEnv,a as aesEncrypt,n as aesDecrypt};
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Encrypt .env file
3
+ */
4
+ export declare function encryptEnv(options?: EncryptOptions): { success: boolean, output?: string, error?: string };
5
+ /**
6
+ * Decrypt .env file
7
+ */
8
+ export declare function decryptEnv(options?: DecryptOptions): { success: boolean, output?: string, error?: string };
9
+ /**
10
+ * Set an environment variable
11
+ */
12
+ export declare function setEnv(key: string, value: string, options?: SetOptions): { success: boolean, output?: string, error?: string };
13
+ /**
14
+ * Get environment variable(s)
15
+ */
16
+ export declare function getEnv(key?: string, options?: GetOptions): { success: boolean, output?: string, error?: string };
17
+ /**
18
+ * Get keypair for .env file
19
+ */
20
+ export declare function getKeypair(keyName?: string, options?: { file?: string, keysFile?: string, format?: 'json' | 'shell', cwd?: string }): { success: boolean, output?: string, error?: string };
21
+ /**
22
+ * Rotate keypair and re-encrypt all values
23
+ */
24
+ export declare function rotateKeypair(options?: { file?: string, keysFile?: string, key?: string, excludeKey?: string, stdout?: boolean, cwd?: string }): { success: boolean, output?: string, error?: string };
25
+ export declare interface EncryptOptions {
26
+ file?: string
27
+ keysFile?: string
28
+ key?: string
29
+ excludeKey?: string
30
+ stdout?: boolean
31
+ cwd?: string
32
+ }
33
+ export declare interface DecryptOptions {
34
+ file?: string
35
+ keysFile?: string
36
+ key?: string
37
+ stdout?: boolean
38
+ cwd?: string
39
+ }
40
+ export declare interface SetOptions {
41
+ file?: string
42
+ keysFile?: string
43
+ plain?: boolean
44
+ cwd?: string
45
+ }
46
+ export declare interface GetOptions {
47
+ file?: string
48
+ keysFile?: string
49
+ all?: boolean
50
+ format?: 'json' | 'shell' | 'eval'
51
+ prettyPrint?: boolean
52
+ cwd?: string
53
+ }
@@ -0,0 +1,13 @@
1
+ // AES-256-GCM encryption using Node.js crypto
2
+ export declare function aesEncrypt(plaintext: string, key: Buffer): { ciphertext: string, iv: string, authTag: string };
3
+ export declare function aesDecrypt(ciphertext: string, key: Buffer, iv: string, authTag: string): string;
4
+ // secp256k1 key generation
5
+ export declare function generateKeypair(): { publicKey: string, privateKey: string };
6
+ // Encrypt a value using public key
7
+ export declare function encryptValue(value: string, publicKey: string): string;
8
+ // Decrypt a value using private key
9
+ export declare function decryptValue(encryptedValue: string, privateKey: string): string;
10
+ // Parse environment name from private key variable
11
+ export declare function parseEnvFromKey(keyName: string): string;
12
+ // Get appropriate private key for environment
13
+ export declare function getPrivateKey(env?: string): string | undefined;
@@ -0,0 +1,6 @@
1
+ import type { EnvKey } from '../../../env';
2
+ import type { StacksEnv } from './types';
3
+ export declare function process(): StacksEnv;
4
+ // eslint-disable-next-line pickier/no-unused-vars
5
+ export declare function writeEnv(key: EnvKey, value: string, options?: { path: string }): void;
6
+ export declare const env: StacksEnv;
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Parse a .env file content
3
+ */
4
+ export declare function parse(src: string, options?: ParseOptions): ParseResult;
5
+ /**
6
+ * Load and parse multiple .env files
7
+ */
8
+ export declare function loadEnvFiles(files: string[], options?: ParseOptions & { overload?: boolean }): Promise<ParseResult>;
9
+ export declare interface ParseOptions {
10
+ privateKey?: string
11
+ processEnv?: Record<string, string>
12
+ }
13
+ export declare interface ParseResult {
14
+ parsed: Record<string, string>
15
+ errors: string[]
16
+ }
@@ -0,0 +1,24 @@
1
+ import type { BunPlugin } from 'bun';
2
+ /**
3
+ * Load .env files and inject into process.env
4
+ */
5
+ export declare function loadEnv(options?: EnvPluginOptions): { loaded: number, errors: string[] };
6
+ /**
7
+ * Bun plugin for automatic .env loading
8
+ */
9
+ export declare function envPlugin(options?: EnvPluginOptions): BunPlugin;
10
+ /**
11
+ * Auto-detect and load .env files based on environment
12
+ */
13
+ export declare function autoLoadEnv(options?: Omit<EnvPluginOptions, 'path'>): { loaded: number, errors: string[] };
14
+ export declare interface EnvPluginOptions {
15
+ path?: string | string[]
16
+ overload?: boolean
17
+ env?: string
18
+ privateKey?: string
19
+ keysFile?: string
20
+ quiet?: boolean
21
+ cwd?: string
22
+ }
23
+ // Default export for easy usage
24
+ export default envPlugin;
@@ -0,0 +1,142 @@
1
+ import type { BooleanValidatorType, EnumValidatorType, NumberValidatorType, StringValidatorType } from '@stacksjs/ts-validation';
2
+ import type { EnvKey } from '../../../env';
3
+ export declare const envEnum: EnumObject;
4
+ declare interface EnumObject {
5
+ [key: string]: string[]
6
+ }
7
+ declare interface StringEnvConfig {
8
+ validation: StringValidatorType
9
+ default: string
10
+ }
11
+ declare interface NumberEnvConfig {
12
+ validation: NumberValidatorType
13
+ default: number
14
+ }
15
+ declare interface BooleanEnvConfig {
16
+ validation: BooleanValidatorType
17
+ default: boolean
18
+ }
19
+ declare interface EnumEnvConfig {
20
+ validation: EnumValidatorType
21
+ default: string
22
+ }
23
+ export declare interface StacksEnv {
24
+ APP_NAME: string | undefined
25
+ APP_ENV: 'local' | 'dev' | 'stage' | 'prod' | undefined
26
+ APP_KEY: string | undefined
27
+ APP_URL: string | undefined
28
+ APP_DOMAIN: string | undefined
29
+ APP_MAINTENANCE: boolean | undefined
30
+ APP_MAINTENANCE_SECRET: string | undefined
31
+ APP_COMING_SOON: boolean | undefined
32
+ APP_COMING_SOON_SECRET: string | undefined
33
+ APP_ROOT: string | undefined
34
+ DEBUG: boolean | undefined
35
+ PORT: number | undefined
36
+ PORT_BACKEND: number | undefined
37
+ PORT_ADMIN: number | undefined
38
+ PORT_LIBRARY: number | undefined
39
+ PORT_DESKTOP: number | undefined
40
+ PORT_EMAIL: number | undefined
41
+ PORT_DOCS: number | undefined
42
+ PORT_INSPECT: number | undefined
43
+ PORT_API: number | undefined
44
+ PORT_SYSTEM_TRAY: number | undefined
45
+ API_PREFIX: string | undefined
46
+ DOCS_PREFIX: string | undefined
47
+ DB_CONNECTION: 'mysql' | 'sqlite' | 'postgres' | undefined
48
+ DB_HOST: string | undefined
49
+ DB_PORT: number | undefined
50
+ DB_DATABASE: string | undefined
51
+ DB_DATABASE_PATH: string | undefined
52
+ DB_USERNAME: string | undefined
53
+ DB_PASSWORD: string | undefined
54
+ DB_PREFIX: string | undefined
55
+ DB_SCHEMA: string | undefined
56
+ DB_QUERY_LOGGING_ENABLED: boolean | undefined
57
+ DB_QUERY_LOGGING_SLOW_THRESHOLD: number | undefined
58
+ DB_QUERY_LOGGING_RETENTION_DAYS: number | undefined
59
+ DB_QUERY_LOGGING_PRUNE_FREQUENCY: number | undefined
60
+ DB_QUERY_LOGGING_ANALYSIS_ENABLED: boolean | undefined
61
+ DB_QUERY_LOGGING_ANALYZE_ALL: boolean | undefined
62
+ DB_QUERY_LOGGING_EXPLAIN_PLAN: boolean | undefined
63
+ DB_QUERY_LOGGING_SUGGESTIONS: boolean | undefined
64
+ DATABASE_URL: string | undefined
65
+ AWS_ACCOUNT_ID: string | undefined
66
+ AWS_ACCESS_KEY_ID: string | undefined
67
+ AWS_SECRET_ACCESS_KEY: string | undefined
68
+ AWS_DEFAULT_REGION: string | undefined
69
+ AWS_DEFAULT_PASSWORD: string | undefined
70
+ AWS_REGION: string | undefined
71
+ AWS_HOSTED_ZONE_ID: string | undefined
72
+ AWS_S3_BUCKET: string | undefined
73
+ AWS_S3_PREFIX: string | undefined
74
+ AWS_SES_REGION: string | undefined
75
+ MAIL_MAILER: string | undefined
76
+ MAIL_HOST: string | undefined
77
+ MAIL_PORT: number | undefined
78
+ MAIL_USERNAME: string | undefined
79
+ MAIL_PASSWORD: string | undefined
80
+ MAIL_ENCRYPTION: string | undefined
81
+ MAIL_FROM_NAME: string | undefined
82
+ MAIL_FROM_ADDRESS: string | undefined
83
+ MAIL_DOMAIN: string | undefined
84
+ MAIL_DRIVER: string | undefined
85
+ MAIL_SERVER_MODE: string | undefined
86
+ MAIL_SERVER_PATH: string | undefined
87
+ SEARCH_ENGINE_DRIVER: string | undefined
88
+ MEILISEARCH_HOST: string | undefined
89
+ MEILISEARCH_KEY: string | undefined
90
+ STRIPE_SECRET_KEY: string | undefined
91
+ STRIPE_PUBLISHABLE_KEY: string | undefined
92
+ FRONTEND_APP_ENV: 'development' | 'staging' | 'production' | undefined
93
+ FRONTEND_APP_URL: string | undefined
94
+ REALTIME_MODE: string | undefined
95
+ BROADCAST_DRIVER: string | undefined
96
+ BROADCAST_HOST: string | undefined
97
+ BROADCAST_PORT: number | undefined
98
+ BROADCAST_SCHEME: string | undefined
99
+ BROADCAST_APP_ID: string | undefined
100
+ BROADCAST_APP_KEY: string | undefined
101
+ BROADCAST_APP_SECRET: string | undefined
102
+ BROADCAST_CORS_ORIGIN: string | undefined
103
+ BROADCAST_DEBUG: boolean | undefined
104
+ BROADCAST_REDIS_ENABLED: boolean | undefined
105
+ BROADCAST_REDIS_PREFIX: string | undefined
106
+ BROADCAST_RATE_LIMIT_ENABLED: boolean | undefined
107
+ BROADCAST_METRICS_ENABLED: boolean | undefined
108
+ REDIS_HOST: string | undefined
109
+ REDIS_PORT: number | undefined
110
+ REDIS_PASSWORD: string | undefined
111
+ PUSHER_APP_ID: string | undefined
112
+ PUSHER_APP_KEY: string | undefined
113
+ PUSHER_APP_SECRET: string | undefined
114
+ PUSHER_APP_CLUSTER: string | undefined
115
+ PUSHER_APP_USE_TLS: boolean | undefined
116
+ SSL_DOMAINS: string | undefined
117
+ LETSENCRYPT_EMAIL: string | undefined
118
+ CONNECT_INSTANCE_ALIAS: string | undefined
119
+ PHONE_NOTIFY_EMAIL: string | undefined
120
+ PHONE_FORWARD_NUMBER: string | undefined
121
+ STORAGE_DRIVER: string | undefined
122
+ STORAGE_ROOT: string | undefined
123
+ STORAGE_PUBLIC_URL: string | undefined
124
+ QUEUE_DRIVER: string | undefined
125
+ AUTH_USERNAME_FIELD: string | undefined
126
+ AUTH_PASSWORD_FIELD: string | undefined
127
+ AUTH_TOKEN_EXPIRY: number | undefined
128
+ AUTH_TOKEN_ROTATION: number | undefined
129
+ AUTH_PASSWORD_RESET_EXPIRE: number | undefined
130
+ AUTH_PASSWORD_RESET_THROTTLE: number | undefined
131
+ [key: string]: string | number | boolean | undefined
132
+ }
133
+ export declare interface FrontendEnv {
134
+ FRONTEND_APP_ENV: 'local' | 'development' | 'staging' | 'production'
135
+ FRONTEND_APP_URL: string
136
+ }
137
+ declare type EnvValueConfig = StringEnvConfig | NumberEnvConfig | BooleanEnvConfig | EnumEnvConfig;
138
+ export type EnvConfig = Partial<Record<EnvKey, EnvValueConfig>>;
139
+ /** @deprecated Use `StacksEnv` instead */
140
+ export type Env = StacksEnv;
141
+ export type EnvSchema = any;
142
+ export type FrontendEnvKeys = keyof FrontendEnv;
@@ -0,0 +1,24 @@
1
+ // Runtime detection
2
+ export declare const isBun: boolean;
3
+ export declare const isNode: boolean;
4
+ export declare const runtime: 'bun' | 'node' | 'unknown';
5
+ export declare const runtimeInfo: { name: 'bun' | 'node' | 'unknown', version: string | undefined };
6
+ // Platform detection
7
+ export declare const platform: NodeJS.Platform;
8
+ export declare const isWindows: boolean;
9
+ export declare const isMacOS: boolean;
10
+ export declare const isLinux: boolean;
11
+ // TTY detection
12
+ export declare const hasTTY: boolean;
13
+ // Window detection (browser environment)
14
+ export declare const hasWindow: boolean;
15
+ // CI detection
16
+ export declare const isCI: boolean;
17
+ // Debug mode detection
18
+ export declare const isDebug: boolean;
19
+ // Minimal mode detection (CI or non-interactive)
20
+ export declare const isMinimal: boolean;
21
+ // Color support detection
22
+ export declare const isColorSupported: boolean;
23
+ export declare const provider: string;
24
+ export declare const providerInfo: { name: string, detected: boolean };
package/package.json CHANGED
@@ -1,10 +1,12 @@
1
1
  {
2
2
  "name": "@stacksjs/env",
3
3
  "type": "module",
4
- "version": "0.70.22",
4
+ "version": "0.70.25",
5
5
  "description": "Stacks env helper methods.",
6
6
  "author": "Chris Breuer",
7
- "contributors": ["Chris Breuer <chris@stacksjs.org>"],
7
+ "contributors": [
8
+ "Chris Breuer <chris@stacksjs.com>"
9
+ ],
8
10
  "license": "MIT",
9
11
  "funding": "https://github.com/sponsors/chrisbbreuer",
10
12
  "homepage": "https://github.com/stacksjs/stacks/tree/main/storage/framework/core/env#readme",
@@ -16,9 +18,16 @@
16
18
  "bugs": {
17
19
  "url": "https://github.com/stacksjs/stacks/issues"
18
20
  },
19
- "keywords": ["env", "utilities", "functions", "stacks"],
21
+ "keywords": [
22
+ "env",
23
+ "utilities",
24
+ "functions",
25
+ "stacks"
26
+ ],
20
27
  "exports": {
21
28
  ".": {
29
+ "bun": "./src/index.ts",
30
+ "types": "./dist/index.d.ts",
22
31
  "import": "./dist/index.js"
23
32
  },
24
33
  "./*": {
@@ -26,20 +35,18 @@
26
35
  "import": "./dist/*"
27
36
  }
28
37
  },
29
- "files": ["README.md", "dist"],
38
+ "files": [
39
+ "README.md",
40
+ "dist"
41
+ ],
30
42
  "scripts": {
31
43
  "build": "bun build.ts",
32
44
  "typecheck": "bun tsc --noEmit",
33
45
  "prepublishOnly": "bun run build"
34
46
  },
35
- "dependencies": {
36
- "@dotenvx/dotenvx": "^1.39.0"
37
- },
38
47
  "devDependencies": {
39
- "@stacksjs/development": "0.70.18",
40
- "@stacksjs/path": "0.70.18",
41
- "@stacksjs/validation": "0.70.18",
42
- "fs-extra": "^11.3.0",
43
- "std-env": "^3.8.1"
48
+ "better-dx": "^0.2.12",
49
+ "@stacksjs/path": "0.70.23",
50
+ "@stacksjs/validation": "0.70.23"
44
51
  }
45
52
  }
package/dist/index.d.ts DELETED
@@ -1,11 +0,0 @@
1
- import type { Env } from './types';
2
- import type { EnvKey } from '../../../env';
3
-
4
- declare const handler: {
5
- get: (target: Env, key: EnvKey) => unknown
6
- };
7
- export declare function process(): Env;
8
- export declare const env: Env;
9
- export declare function writeEnv(key: EnvKey, value: string, options?: { path: , string }): void;
10
-
11
- export * from './types'
package/dist/types.d.ts DELETED
@@ -1,97 +0,0 @@
1
- import type { EnvKey } from '../../../env';
2
- import type { Infer, VineBoolean, VineEnum, VineNumber, VineString } from '@stacksjs/validation';
3
- import type { SchemaTypes } from '@vinejs/vine/types';
4
-
5
- declare interface EnumObject {
6
- [key: string]: string[]
7
- }
8
- export declare const envEnum: EnumObject;
9
- declare interface StringEnvConfig {
10
- validation: VineString
11
- default: string
12
- }
13
- declare interface NumberEnvConfig {
14
- validation: VineNumber
15
- default: number
16
- }
17
- declare interface BooleanEnvConfig {
18
- validation: VineBoolean
19
- default: boolean
20
- }
21
- declare interface EnumEnvConfig {
22
- validation: VineEnum<any>
23
- default: string
24
- }
25
- declare type EnvValueConfig = StringEnvConfig | NumberEnvConfig | BooleanEnvConfig | EnumEnvConfig
26
-
27
- export type EnvConfig = Partial<Record<EnvKey, EnvValueConfig>>
28
-
29
- type EnvMap = Record<string, SchemaTypes>
30
-
31
- const envStructure: EnvMap = Object.entries(env).reduce((acc, [key, value]) => {
32
- if (typeof value === 'object' && value !== null && 'validation' in value) {
33
- acc[key] = (value as EnvValueConfig).validation
34
- return acc
35
- }
36
-
37
- let validatorType: SchemaTypes
38
- switch (typeof value) {
39
- case 'string':
40
- validatorType = schema.string()
41
- break
42
- case 'number':
43
- validatorType = schema.number()
44
- break
45
- case 'boolean':
46
- validatorType = schema.boolean()
47
- break
48
- default:
49
- if (Array.isArray(value)) {
50
- validatorType = schema.enum(value as string[])
51
- break
52
- }
53
-
54
- if (typeof value === 'object' && value !== null) {
55
- const schemaNameSymbol = Symbol.for('schema_name')
56
- const schemaName = (value as { [key: symbol]: string })[schemaNameSymbol]
57
-
58
- if (schemaName === 'vine.string') {
59
- validatorType = schema.string()
60
- break
61
- }
62
-
63
- if (schemaName === 'vine.number') {
64
- validatorType = schema.number()
65
- break
66
- }
67
-
68
- if (schemaName === 'vine.boolean') {
69
- validatorType = schema.boolean()
70
- break
71
- }
72
-
73
- if (!schemaName && key in envEnum) {
74
- validatorType = schema.enum(envEnum[key as keyof typeof envEnum])
75
- break
76
- }
77
-
78
- console.error('Unknown env value type', typeof value)
79
- }
80
-
81
- throw new Error(`Invalid env value for ${key}`)
82
- }
83
-
84
- acc[key] = validatorType
85
- return acc
86
- }, {} as EnvMap)
87
-
88
- export const envSchema: ReturnType<typeof schema.object> = schema.object(envStructure)
89
- export type Env = Infer<typeof envSchema>
90
-
91
- export type EnvOptions = Env
92
-
93
- export interface FrontendEnv {
94
- FRONTEND_APP_ENV: 'local' | 'development' | 'staging' | 'production'
95
- FRONTEND_APP_URL: string
96
- }
97
- export type FrontendEnvKeys = keyof FrontendEnv
package/dist/utils.d.ts DELETED
@@ -1,18 +0,0 @@
1
- export {
2
- hasTTY,
3
- hasWindow,
4
- isBun,
5
- isCI,
6
- isColorSupported,
7
- isDebug,
8
- isLinux,
9
- isMacOS,
10
- isMinimal,
11
- isNode,
12
- isWindows,
13
- platform,
14
- provider,
15
- providerInfo,
16
- runtime,
17
- runtimeInfo,
18
- } from 'std-env'