vaulter 0.2.0 → 0.2.1

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
@@ -324,20 +324,100 @@ security:
324
324
 
325
325
  ## Monorepo Support
326
326
 
327
+ Vaulter auto-discovers services with `.vaulter/` directories and supports config inheritance.
328
+
329
+ ### NX Monorepo
330
+
327
331
  ```
328
- my-monorepo/
332
+ my-nx-workspace/
329
333
  ├── .vaulter/
330
- │ ├── config.yaml # Root config
334
+ │ ├── config.yaml # Shared config (backend, encryption)
331
335
  │ └── environments/
332
- ├── services/
333
- ├── api/
336
+ │ └── dev.env # Shared dev vars
337
+ ├── apps/
338
+ │ ├── web/
334
339
  │ │ └── .vaulter/
335
- │ │ ├── config.yaml # extends: ../../../.vaulter/config.yaml
340
+ │ │ ├── config.yaml # extends: ../../../.vaulter/config.yaml
336
341
  │ │ └── environments/
337
- │ └── worker/
342
+ └── dev.env # App-specific vars
343
+ │ └── api/
338
344
  │ └── .vaulter/
345
+ │ ├── config.yaml
346
+ │ └── environments/
347
+ ├── libs/ # No .vaulter needed for libs
348
+ ├── nx.json
349
+ └── package.json
350
+ ```
351
+
352
+ ```bash
353
+ # From workspace root
354
+ vaulter services # List: web, api
355
+
356
+ # Sync all apps
357
+ vaulter sync -e dev --all
358
+
359
+ # Sync single app (from root or app dir)
360
+ vaulter sync -e dev -s api
361
+ cd apps/api && vaulter sync -e dev
362
+
363
+ # NX run with env vars
364
+ eval $(vaulter export -e dev -s api) && nx serve api
365
+ ```
366
+
367
+ ### Turborepo
368
+
369
+ ```
370
+ my-turbo-monorepo/
371
+ ├── .vaulter/
372
+ │ ├── config.yaml # Root config
373
+ │ └── environments/
374
+ ├── apps/
375
+ │ ├── web/
376
+ │ │ ├── .vaulter/
377
+ │ │ │ ├── config.yaml # extends: ../../../.vaulter/config.yaml
378
+ │ │ │ └── environments/
379
+ │ │ └── package.json
380
+ │ └── docs/
381
+ │ └── .vaulter/
382
+ ├── packages/ # Shared packages (no .vaulter)
383
+ ├── turbo.json
384
+ └── package.json
385
+ ```
386
+
387
+ ```bash
388
+ # List discovered services
389
+ vaulter services
390
+
391
+ # Batch sync before turbo build
392
+ vaulter sync -e prd --all && turbo build
393
+
394
+ # Export for specific app
395
+ cd apps/web && eval $(vaulter export -e dev)
396
+
397
+ # Turbo with env passthrough (turbo.json)
398
+ # { "pipeline": { "build": { "env": ["DATABASE_URL", "API_KEY"] } } }
399
+ vaulter export -e prd -s web --format=shell >> apps/web/.env
400
+ turbo build --filter=web
339
401
  ```
340
402
 
403
+ ### Service Config Inheritance
404
+
405
+ ```yaml
406
+ # apps/api/.vaulter/config.yaml
407
+ extends: ../../../.vaulter/config.yaml # Inherit root config
408
+
409
+ service: api # Override service name
410
+
411
+ # Override or add service-specific settings
412
+ sync:
413
+ required:
414
+ prd:
415
+ - DATABASE_URL
416
+ - REDIS_URL
417
+ ```
418
+
419
+ ### Commands
420
+
341
421
  ```bash
342
422
  # List services
343
423
  vaulter services
@@ -345,8 +425,12 @@ vaulter services
345
425
  # Sync all services
346
426
  vaulter sync -e dev --all
347
427
 
348
- # Sync specific services
428
+ # Sync specific services (glob supported)
349
429
  vaulter sync -e dev -s api,worker
430
+ vaulter sync -e dev -s "svc-*"
431
+
432
+ # Batch export
433
+ vaulter export -e prd --all --format=json
350
434
  ```
351
435
 
352
436
  ## MCP Tools
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vaulter",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "description": "Multi-backend environment variable and secrets manager with AES-256-GCM encryption",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -1,17 +0,0 @@
1
- #!/usr/bin/env node
2
- "use strict";var Q=Object.create;var _=Object.defineProperty;var X=Object.getOwnPropertyDescriptor;var J=Object.getOwnPropertyNames;var ee=Object.getPrototypeOf,ne=Object.prototype.hasOwnProperty;var te=(n,e,r,t)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of J(e))!ne.call(n,i)&&i!==r&&_(n,i,{get:()=>e[i],enumerable:!(t=X(e,i))||t.enumerable});return n};var E=(n,e,r)=>(r=n!=null?Q(ee(n)):{},te(e||!n||!n.__esModule?_(r,"default",{value:n,enumerable:!0}):r,n));process.setMaxListeners(50);var G=require("@modelcontextprotocol/sdk/server/index.js"),Z=require("@modelcontextprotocol/sdk/server/stdio.js"),p=require("@modelcontextprotocol/sdk/types.js");var I=require("s3db.js"),re=`file://${process.env.HOME||"/tmp"}/.minienv/store`,ie="minienv-default-dev-key",g=class{db=null;resource=null;connectionString;passphrase;initialized=!1;constructor(e={}){this.connectionString=e.connectionString||re,this.passphrase=e.passphrase||ie}async connect(){this.initialized||(this.db=new I.S3db({connectionString:this.connectionString,passphrase:this.passphrase}),await this.db.connect(),this.resource=await this.db.createResource({name:"environment-variables",attributes:{key:"string|required",value:"secret|required",project:"string|required",service:"string|optional",environment:"enum:dev,stg,prd,sbx,dr|required",tags:"array|items:string|optional",metadata:{description:"string|optional",owner:"string|optional",rotateAfter:"date|optional",source:"enum:manual,sync,import|optional"}},partitions:{byProject:{fields:{project:"string"}},byProjectEnv:{fields:{project:"string",environment:"string"}},byProjectServiceEnv:{fields:{project:"string",service:"string",environment:"string"}}},behavior:"body-overflow",timestamps:!0,asyncPartitions:!0}),this.initialized=!0)}ensureConnected(){if(!this.initialized||!this.resource)throw new Error("MiniEnvClient not initialized. Call connect() first.")}async get(e,r,t,i){this.ensureConnected();let s=i?"byProjectServiceEnv":"byProjectEnv",o=i?{project:r,service:i,environment:t}:{project:r,environment:t};return(await this.resource.list({partition:s,partitionValues:o})).find(l=>l.key===e)||null}async set(e){this.ensureConnected();let r=await this.get(e.key,e.project,e.environment,e.service);return r?await this.resource.update(r.id,{value:e.value,tags:e.tags,metadata:{...r.metadata,...e.metadata,source:e.metadata?.source||"manual"}}):await this.resource.insert({...e,metadata:{...e.metadata,source:e.metadata?.source||"manual"}})}async delete(e,r,t,i){this.ensureConnected();let s=await this.get(e,r,t,i);return s?(await this.resource.delete(s.id),!0):!1}async list(e={}){this.ensureConnected();let{project:r,service:t,environment:i,limit:s,offset:o}=e,a,c;r&&t&&i?(a="byProjectServiceEnv",c={project:r,service:t,environment:i}):r&&i?(a="byProjectEnv",c={project:r,environment:i}):r&&(a="byProject",c={project:r});let l={};return a&&c&&(l.partition=a,l.partitionValues=c),s&&(l.limit=s),o&&(l.offset=o),await this.resource.list(l)}async insertMany(e){this.ensureConnected();let r=[];for(let t of e){let i=await this.set(t);r.push(i)}return r}async deleteAll(e,r,t){this.ensureConnected();let i=await this.list({project:e,environment:r,service:t}),s=0;for(let o of i)await this.resource.delete(o.id),s++;return s}async export(e,r,t){let i=await this.list({project:e,environment:r,service:t}),s={};for(let o of i)s[o.key]=o.value;return s}async sync(e,r,t,i,s={}){this.ensureConnected();let o=await this.list({project:r,environment:t,service:i}),a=new Map(o.map(l=>[l.key,l])),c={added:[],updated:[],deleted:[],unchanged:[],conflicts:[]};for(let[l,d]of Object.entries(e)){let u=a.get(l);u?u.value!==d?(await this.set({key:l,value:d,project:r,environment:t,service:i,metadata:{source:s.source||"sync"}}),c.updated.push(l)):c.unchanged.push(l):(await this.set({key:l,value:d,project:r,environment:t,service:i,metadata:{source:s.source||"sync"}}),c.added.push(l)),a.delete(l)}for(let[l]of a)c.deleted.push(l);return c}async disconnect(){this.db&&(await this.db.disconnect(),this.db=null,this.resource=null,this.initialized=!1)}isConnected(){return this.initialized}getConnectionString(){return this.connectionString}};var v=E(require("node:fs"),1),f=E(require("node:path"),1),A=require("yaml");function se(n){let e=new URL(n);if(e.protocol==="s3:"){let r=e.hostname,t=e.pathname.slice(1),i=e.searchParams.get("region")||void 0;return{bucket:r,key:t,region:i}}if(e.protocol==="http:"||e.protocol==="https:"){let r=`${e.protocol}//${e.host}`,t=e.pathname.slice(1).split("/"),i=t[0],s=t.slice(1).join("/");return{bucket:i,key:s,endpoint:r,accessKeyId:e.username||void 0,secretAccessKey:e.password||void 0}}throw new Error(`Unsupported S3 URL format: ${n}`)}async function oe(n){try{let{S3Client:e,GetObjectCommand:r}=await import("@aws-sdk/client-s3"),t={};n.region&&(t.region=n.region),n.endpoint&&(t.endpoint=n.endpoint,t.forcePathStyle=!0),n.accessKeyId&&n.secretAccessKey&&(t.credentials={accessKeyId:n.accessKeyId,secretAccessKey:n.secretAccessKey});let i=new e(t),s=new r({Bucket:n.bucket,Key:n.key}),o=await i.send(s);if(!o.Body)throw new Error("Empty response from S3");return(await o.Body.transformToString()).trim()}catch(e){throw e.code==="ERR_MODULE_NOT_FOUND"||e.message?.includes("Cannot find module")?new Error("AWS SDK not installed. To use S3 key source, install: pnpm add @aws-sdk/client-s3"):new Error(`Failed to fetch key from S3: ${e.message}`)}}async function T(n){let e=se(n);return oe(e)}var ae=".minienv",O="config.yaml",ce=5,M=10,V={version:"1",project:"",environments:["dev","stg","prd","sbx","dr"],default_environment:"dev",sync:{conflict:"local"},security:{paranoid:!1,confirm_production:!0,auto_encrypt:{patterns:["*_KEY","*_SECRET","*_TOKEN","*_PASSWORD","*_CREDENTIAL","DATABASE_URL","REDIS_URL"]}}};function $(n=process.cwd()){let e=f.default.resolve(n),r=0;for(;r<ce;){let t=f.default.join(e,ae),i=f.default.join(t,O);if(v.default.existsSync(i))return t;let s=f.default.dirname(e);if(s===e)break;e=s,r++}return null}function le(n){if(!v.default.existsSync(n))throw new Error(`Config file not found: ${n}`);let e=v.default.readFileSync(n,"utf-8");return(0,A.parse)(e)||{}}function C(n,e){let r={...n};for(let t of Object.keys(e)){let i=e[t],s=r[t];i!=null&&typeof i=="object"&&!Array.isArray(i)&&s!==null&&s!==void 0&&typeof s=="object"&&!Array.isArray(s)?r[t]=C(s,i):i!==void 0&&(r[t]=i)}return r}function N(n,e=new Set,r=0){if(r>M)throw new Error(`Config inheritance depth exceeded (max ${M})`);let t=f.default.resolve(n);if(e.has(t))throw new Error(`Circular config inheritance detected: ${t}`);e.add(t);let i=le(t);if(i.extends){let s=f.default.resolve(f.default.dirname(t),i.extends),o=N(s,e,r+1),{extends:a,...c}=i;return C(o,c)}return C(V,i)}function w(n){let e=$(n);if(!e)return{...V};let r=f.default.join(e,O);return N(r)}function de(n){return f.default.join(n,"environments")}function D(n,e){return f.default.join(de(n),`${e}.env`)}async function j(n){let e=n.encryption?.key_source||[];for(let r of e)if("env"in r){let t=process.env[r.env];if(t)return t}else if("file"in r){let t=f.default.resolve(r.file);if(v.default.existsSync(t))return v.default.readFileSync(t,"utf-8").trim()}else if("s3"in r)try{let t=await T(r.s3);if(t)return t}catch(t){process.env.MINIENV_VERBOSE&&console.warn(`Failed to load key from S3: ${t.message}`)}return process.env.MINIENV_KEY?process.env.MINIENV_KEY:null}var K=E(require("node:fs"),1),P=100;function F(n,e={}){let r=K.default.readFileSync(n,"utf-8");return ue(r,e)}function ue(n,e={}){let{expand:r=!0,env:t=process.env}=e,i={},s=n.split(/\r?\n/),o=0;for(;o<s.length;){let a=s[o].trim();if(o++,!a||a.startsWith("#")||a.startsWith(";"))continue;let c=a.match(/^([a-zA-Z_][a-zA-Z0-9_]*)\s*=\s*(.*)$/);if(!c)continue;let l=c[1],d=c[2];if(d.startsWith('"')){let u=pe(d,s,o);d=u.value,o=u.nextIndex}else if(d.startsWith("'")){let u=fe(d,s,o);d=u.value,o=u.nextIndex}else if(d.startsWith("`")){let u=me(d,s,o);d=u.value,o=u.nextIndex}else{let u=d.indexOf("#");u>0&&(d=d.substring(0,u).trim())}r&&(d=ge(d,{...t,...i})),i[l]=d}return i}function pe(n,e,r){let t=n.substring(1),i=0,s="",o=0,a=r;for(;i<P;){for(;o<t.length;){let c=t[o];if(c==="\\"&&o+1<t.length){let l=t[o+1];switch(l){case"n":s+=`
3
- `;break;case"r":s+="\r";break;case"t":s+=" ";break;case'"':s+='"';break;case"\\":s+="\\";break;case"$":s+="$";break;default:s+=c+l}o+=2}else{if(c==='"')return{value:s,nextIndex:a};s+=c,o++}}if(a>=e.length)break;s+=`
4
- `,t=e[a],a++,o=0,i++}return{value:s,nextIndex:a}}function fe(n,e,r){let t=n.substring(1),i=0,s="",o=0,a=r;for(;i<P;){for(;o<t.length;){let c=t[o];if(c==="'"&&t[o+1]!=="'")return{value:s,nextIndex:a};c==="'"&&t[o+1]==="'"?(s+="'",o+=2):(s+=c,o++)}if(a>=e.length)break;s+=`
5
- `,t=e[a],a++,o=0,i++}return{value:s,nextIndex:a}}function me(n,e,r){let t=n.substring(1),i=0,s="",o=0,a=r;for(;i<P;){let c=t.indexOf("`",o);if(c!==-1)return s+=t.substring(o,c),{value:s,nextIndex:a};if(s+=t.substring(o),a>=e.length)break;s+=`
6
- `,t=e[a],a++,o=0,i++}return{value:s,nextIndex:a}}function ge(n,e){return n=n.replace(/\$\{([a-zA-Z_][a-zA-Z0-9_]*):-([^}]*)\}/g,(r,t,i)=>e[t]??i),n=n.replace(/\$\{([a-zA-Z_][a-zA-Z0-9_]*)\}/g,(r,t)=>e[t]??""),n=n.replace(/\$([a-zA-Z_][a-zA-Z0-9_]*)/g,(r,t)=>e[t]??""),n}var L=E(require("node:fs"),1);async function ve(){let n=null;try{n=w()}catch{}let e=n?.backend?.url,r=n?await j(n):void 0;return{client:new g({connectionString:e||void 0,passphrase:r||void 0}),config:n}}function U(){return[{name:"minienv_get",description:"Get the value of an environment variable",inputSchema:{type:"object",properties:{key:{type:"string",description:"The name of the environment variable"},environment:{type:"string",description:"Environment (dev/stg/prd/sbx/dr)",enum:["dev","stg","prd","sbx","dr"],default:"dev"},project:{type:"string",description:"Project name (optional, defaults to config)"},service:{type:"string",description:"Service name for monorepos (optional)"}},required:["key"]}},{name:"minienv_set",description:"Set an environment variable value",inputSchema:{type:"object",properties:{key:{type:"string",description:"The name of the environment variable"},value:{type:"string",description:"The value to set"},environment:{type:"string",description:"Environment (dev/stg/prd/sbx/dr)",enum:["dev","stg","prd","sbx","dr"],default:"dev"},project:{type:"string",description:"Project name (optional, defaults to config)"},service:{type:"string",description:"Service name for monorepos (optional)"}},required:["key","value"]}},{name:"minienv_delete",description:"Delete an environment variable",inputSchema:{type:"object",properties:{key:{type:"string",description:"The name of the environment variable to delete"},environment:{type:"string",description:"Environment (dev/stg/prd/sbx/dr)",enum:["dev","stg","prd","sbx","dr"],default:"dev"},project:{type:"string",description:"Project name (optional, defaults to config)"},service:{type:"string",description:"Service name for monorepos (optional)"}},required:["key"]}},{name:"minienv_list",description:"List all environment variables for a project/environment",inputSchema:{type:"object",properties:{environment:{type:"string",description:"Environment (dev/stg/prd/sbx/dr)",enum:["dev","stg","prd","sbx","dr"],default:"dev"},project:{type:"string",description:"Project name (optional, defaults to config)"},service:{type:"string",description:"Service name for monorepos (optional)"},showValues:{type:"boolean",description:"Show values (default: false for security)",default:!1}}}},{name:"minienv_export",description:"Export environment variables in shell format",inputSchema:{type:"object",properties:{environment:{type:"string",description:"Environment (dev/stg/prd/sbx/dr)",enum:["dev","stg","prd","sbx","dr"],default:"dev"},project:{type:"string",description:"Project name (optional, defaults to config)"},service:{type:"string",description:"Service name for monorepos (optional)"},format:{type:"string",description:"Output format",enum:["shell","env","json","yaml"],default:"shell"}}}},{name:"minienv_sync",description:"Sync local .env file with backend storage",inputSchema:{type:"object",properties:{environment:{type:"string",description:"Environment (dev/stg/prd/sbx/dr)",enum:["dev","stg","prd","sbx","dr"],default:"dev"},project:{type:"string",description:"Project name (optional, defaults to config)"},service:{type:"string",description:"Service name for monorepos (optional)"},dryRun:{type:"boolean",description:"Show what would be changed without making changes",default:!1}}}}]}async function z(n,e){let{client:r,config:t}=await ve(),i=e.project||t?.project||"",s=e.environment||t?.default_environment||"dev",o=e.service;if(!i)return{content:[{type:"text",text:"Error: Project not specified. Either set project in args or run from a directory with .minienv/config.yaml"}]};try{switch(await r.connect(),n){case"minienv_get":{let a=e.key,c=await r.get(a,i,s,o);return{content:[{type:"text",text:c!==null?c.value:`Variable ${a} not found`}]}}case"minienv_set":{let a=e.key,c=e.value;return await r.set({key:a,value:c,project:i,environment:s,service:o,metadata:{source:"manual"}}),{content:[{type:"text",text:`\u2713 Set ${a} in ${i}/${s}`}]}}case"minienv_delete":{let a=e.key;return{content:[{type:"text",text:await r.delete(a,i,s,o)?`\u2713 Deleted ${a}`:`Variable ${a} not found`}]}}case"minienv_list":{let a=e.showValues||!1,c=await r.list({project:i,environment:s,service:o});if(c.length===0)return{content:[{type:"text",text:`No variables found for ${i}/${s}`}]};let l=c.map(d=>a?`${d.key}=${d.value}`:d.key);return{content:[{type:"text",text:`Variables in ${i}/${s}:
7
- ${l.join(`
8
- `)}`}]}}case"minienv_export":{let a=e.format||"shell",c=await r.export(i,s,o),l;switch(a){case"json":l=JSON.stringify(c,null,2);break;case"yaml":l=Object.entries(c).map(([d,u])=>`${d}: "${u.replace(/"/g,'\\"')}"`).join(`
9
- `);break;case"env":l=Object.entries(c).map(([d,u])=>`${d}=${u}`).join(`
10
- `);break;default:l=Object.entries(c).map(([d,u])=>`export ${d}="${u.replace(/"/g,'\\"')}"`).join(`
11
- `)}return{content:[{type:"text",text:l}]}}case"minienv_sync":{let a=e.dryRun||!1,c=$();if(!c)return{content:[{type:"text",text:"Error: No .minienv directory found"}]};let l=D(c,s);if(!L.default.existsSync(l))return{content:[{type:"text",text:`Error: Environment file not found: ${l}`}]};let d=F(l);if(a){let k=await r.export(i,s,o),x=[],b=[],S=[];for(let[m,Y]of Object.entries(d))m in k?k[m]!==Y&&b.push(m):x.push(m);for(let m of Object.keys(k))m in d||S.push(m);let h=["Dry run - changes that would be made:"];return x.length>0&&h.push(` Add: ${x.join(", ")}`),b.length>0&&h.push(` Update: ${b.join(", ")}`),S.length>0&&h.push(` Delete: ${S.join(", ")}`),x.length===0&&b.length===0&&S.length===0&&h.push(" No changes needed"),{content:[{type:"text",text:h.join(`
12
- `)}]}}let u=await r.sync(d,i,s,o,{source:"sync"}),y=[`\u2713 Synced ${i}/${s}`];return u.added.length>0&&y.push(` Added: ${u.added.length}`),u.updated.length>0&&y.push(` Updated: ${u.updated.length}`),u.deleted.length>0&&y.push(` Deleted: ${u.deleted.length}`),u.unchanged.length>0&&y.push(` Unchanged: ${u.unchanged.length}`),{content:[{type:"text",text:y.join(`
13
- `)}]}}default:return{content:[{type:"text",text:`Unknown tool: ${n}`}]}}}finally{await r.disconnect()}}var q=["dev","stg","prd","sbx","dr"];async function W(){let n=null;try{n=w()}catch{}let e=n?.backend?.url,r=n?await j(n):void 0;return{client:new g({connectionString:e||void 0,passphrase:r||void 0}),config:n}}function ye(n){let e=n.match(/^minienv:\/\/([^/]+)\/([^/]+)(?:\/([^/]+))?$/);if(!e)return null;let[,r,t,i]=e;return q.includes(t)?{project:r,environment:t,service:i}:null}async function H(){let{config:n}=await W();if(!n?.project)return[];let e=n.project,r=n.environments||q,t=n.service,i=[];for(let s of r){let o=t?`minienv://${e}/${s}/${t}`:`minienv://${e}/${s}`;i.push({uri:o,name:`${e}/${s}${t?`/${t}`:""}`,description:`Environment variables for ${e} in ${s}`,mimeType:"text/plain"})}return i}async function B(n){let e=ye(n);if(!e)throw new Error(`Invalid resource URI: ${n}. Expected format: minienv://project/environment[/service]`);let{project:r,environment:t,service:i}=e,{client:s}=await W();try{await s.connect();let o=await s.export(r,t,i),a=Object.entries(o);if(a.length===0)return{contents:[{uri:n,mimeType:"text/plain",text:`# No variables found for ${r}/${t}`}]};let c=a.map(([l,d])=>`${l}=${d}`).join(`
14
- `);return{contents:[{uri:n,mimeType:"text/plain",text:`# Environment: ${r}/${t}${i?`/${i}`:""}
15
- # Variables: ${a.length}
16
-
17
- ${c}`}]}}finally{await s.disconnect()}}var he="minienv",Ee="0.1.0";function xe(){let n=new G.Server({name:he,version:Ee},{capabilities:{tools:{},resources:{}}});return n.setRequestHandler(p.ListToolsRequestSchema,async()=>({tools:U()})),n.setRequestHandler(p.CallToolRequestSchema,async e=>{let{name:r,arguments:t}=e.params;try{return await z(r,t||{})}catch(i){let s=i instanceof Error?i.message:String(i);throw new p.McpError(p.ErrorCode.InternalError,s)}}),n.setRequestHandler(p.ListResourcesRequestSchema,async()=>({resources:await H()})),n.setRequestHandler(p.ReadResourceRequestSchema,async e=>{let{uri:r}=e.params;try{return await B(r)}catch(t){let i=t instanceof Error?t.message:String(t);throw new p.McpError(p.ErrorCode.InternalError,i)}}),n}async function R(){let n=xe(),e=new Z.StdioServerTransport;await n.connect(e),process.on("SIGINT",async()=>{await n.close(),process.exit(0)}),process.on("SIGTERM",async()=>{await n.close(),process.exit(0)})}(process.argv[1]?.endsWith("server.js")||process.argv[1]?.endsWith("server.ts"))&&R().catch(n=>{console.error("Failed to start MCP server:",n),process.exit(1)});R().catch(n=>{console.error("Failed to start MCP server:",n),process.exit(1)});
@@ -1,146 +0,0 @@
1
- #!/usr/bin/env node
2
- "use strict";var Be=Object.create;var q=Object.defineProperty;var We=Object.getOwnPropertyDescriptor;var ze=Object.getOwnPropertyNames;var Ye=Object.getPrototypeOf,He=Object.prototype.hasOwnProperty;var qe=(n,e,o,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of ze(e))!He.call(n,i)&&i!==o&&q(n,i,{get:()=>e[i],enumerable:!(r=We(e,i))||r.enumerable});return n};var h=(n,e,o)=>(o=n!=null?Be(Ye(n)):{},qe(e||!n||!n.__esModule?q(o,"default",{value:n,enumerable:!0}):o,n));process.setMaxListeners(50);var Je=h(require("minimist"),1);var k=h(require("node:fs"),1),x=h(require("node:path"),1),X=require("yaml");function Qe(n){let e=new URL(n);if(e.protocol==="s3:"){let o=e.hostname,r=e.pathname.slice(1),i=e.searchParams.get("region")||void 0;return{bucket:o,key:r,region:i}}if(e.protocol==="http:"||e.protocol==="https:"){let o=`${e.protocol}//${e.host}`,r=e.pathname.slice(1).split("/"),i=r[0],t=r.slice(1).join("/");return{bucket:i,key:t,endpoint:o,accessKeyId:e.username||void 0,secretAccessKey:e.password||void 0}}throw new Error(`Unsupported S3 URL format: ${n}`)}async function Ze(n){try{let{S3Client:e,GetObjectCommand:o}=await import("@aws-sdk/client-s3"),r={};n.region&&(r.region=n.region),n.endpoint&&(r.endpoint=n.endpoint,r.forcePathStyle=!0),n.accessKeyId&&n.secretAccessKey&&(r.credentials={accessKeyId:n.accessKeyId,secretAccessKey:n.secretAccessKey});let i=new e(r),t=new o({Bucket:n.bucket,Key:n.key}),s=await i.send(t);if(!s.Body)throw new Error("Empty response from S3");return(await s.Body.transformToString()).trim()}catch(e){throw e.code==="ERR_MODULE_NOT_FOUND"||e.message?.includes("Cannot find module")?new Error("AWS SDK not installed. To use S3 key source, install: pnpm add @aws-sdk/client-s3"):new Error(`Failed to fetch key from S3: ${e.message}`)}}async function Q(n){let e=Qe(n);return Ze(e)}var Xe=".minienv",W="config.yaml",en=5,Z=10,ee={version:"1",project:"",environments:["dev","stg","prd","sbx","dr"],default_environment:"dev",sync:{conflict:"local"},security:{paranoid:!1,confirm_production:!0,auto_encrypt:{patterns:["*_KEY","*_SECRET","*_TOKEN","*_PASSWORD","*_CREDENTIAL","DATABASE_URL","REDIS_URL"]}}};function w(n=process.cwd()){let e=x.default.resolve(n),o=0;for(;o<en;){let r=x.default.join(e,Xe),i=x.default.join(r,W);if(k.default.existsSync(i))return r;let t=x.default.dirname(e);if(t===e)break;e=t,o++}return null}function nn(n){if(!k.default.existsSync(n))throw new Error(`Config file not found: ${n}`);let e=k.default.readFileSync(n,"utf-8");return(0,X.parse)(e)||{}}function B(n,e){let o={...n};for(let r of Object.keys(e)){let i=e[r],t=o[r];i!=null&&typeof i=="object"&&!Array.isArray(i)&&t!==null&&t!==void 0&&typeof t=="object"&&!Array.isArray(t)?o[r]=B(t,i):i!==void 0&&(o[r]=i)}return o}function ne(n,e=new Set,o=0){if(o>Z)throw new Error(`Config inheritance depth exceeded (max ${Z})`);let r=x.default.resolve(n);if(e.has(r))throw new Error(`Circular config inheritance detected: ${r}`);e.add(r);let i=nn(r);if(i.extends){let t=x.default.resolve(x.default.dirname(r),i.extends),s=ne(t,e,o+1),{extends:f,...l}=i;return B(s,l)}return B(ee,i)}function D(n){let e=w(n);if(!e)return{...ee};let o=x.default.join(e,W);return ne(o)}function oe(n,e){if(n.project)return n.project;let o=e||process.cwd();return x.default.basename(o)}function re(n){return x.default.join(n,"environments")}function P(n,e){return x.default.join(re(n),`${e}.env`)}function te(n){return w(n)!==null}async function y(n){let e=n.encryption?.key_source||[];for(let o of e)if("env"in o){let r=process.env[o.env];if(r)return r}else if("file"in o){let r=x.default.resolve(o.file);if(k.default.existsSync(r))return k.default.readFileSync(r,"utf-8").trim()}else if("s3"in o)try{let r=await Q(o.s3);if(r)return r}catch(r){process.env.MINIENV_VERBOSE&&console.warn(`Failed to load key from S3: ${r.message}`)}return process.env.MINIENV_KEY?process.env.MINIENV_KEY:null}function ie(n,e,o={}){let r={version:"1",project:e,...o};k.default.existsSync(n)||k.default.mkdirSync(n,{recursive:!0});let i=re(n);k.default.existsSync(i)||k.default.mkdirSync(i,{recursive:!0});let t=x.default.join(n,W),s=`# MiniEnv Configuration
3
- # Version: 1
4
-
5
- version: "1"
6
-
7
- # Project identification
8
- project: ${e}
9
- # service: optional-service-name
10
-
11
- # Backend configuration
12
- # backend:
13
- # url: s3://bucket/envs?region=us-east-1
14
- # url: file://${process.env.HOME}/.minienv/store
15
- # url: memory://test
16
-
17
- # Encryption settings
18
- # encryption:
19
- # key_source:
20
- # - env: MINIENV_KEY
21
- # - file: .minienv/.key
22
-
23
- # Available environments
24
- environments:
25
- - dev
26
- - stg
27
- - prd
28
- - sbx
29
- - dr
30
-
31
- # Default environment
32
- default_environment: dev
33
-
34
- # Sync behavior
35
- sync:
36
- conflict: local # local | remote | prompt | error
37
-
38
- # Security settings
39
- security:
40
- confirm_production: true
41
- auto_encrypt:
42
- patterns:
43
- - "*_KEY"
44
- - "*_SECRET"
45
- - "*_TOKEN"
46
- - "*_PASSWORD"
47
- - "DATABASE_URL"
48
- `;k.default.writeFileSync(t,s)}var A=h(require("node:fs"),1),N=h(require("node:path"),1);async function se(n){let{args:e,verbose:o,dryRun:r,jsonOutput:i}=n;if(te()){let c=w();e.force||(i?console.log(JSON.stringify({error:"already_initialized",path:c})):(console.error(`MiniEnv already initialized at ${c}`),console.error("Use --force to reinitialize")),process.exit(1))}let t=e.project||e.p||N.default.basename(process.cwd()),s=N.default.join(process.cwd(),".minienv");if(o&&(console.log(`Initializing minienv for project: ${t}`),console.log(`Config directory: ${s}`)),r){i?console.log(JSON.stringify({action:"init",project:t,configDir:s,dryRun:!0})):(console.log("Dry run - would create:"),console.log(` ${s}/config.yaml`),console.log(` ${s}/environments/`));return}ie(s,t);let f=N.default.join(s,".gitignore");A.default.existsSync(f)||A.default.writeFileSync(f,`# MiniEnv sensitive files
49
- .key
50
- *.key
51
- *.pem
52
- `);let l=N.default.join(s,"environments"),u=["dev","stg","prd","sbx","dr"];for(let c of u){let a=N.default.join(l,`${c}.env`);A.default.existsSync(a)||A.default.writeFileSync(a,`# ${c.toUpperCase()} Environment Variables
53
- # Add your ${c} environment variables here
54
- # Example: DATABASE_URL=postgres://localhost/${c}_db
55
- `)}i?console.log(JSON.stringify({success:!0,project:t,configDir:s,files:["config.yaml",".gitignore",...u.map(c=>`environments/${c}.env`)]})):(console.log(`\u2713 Initialized minienv for project: ${t}`),console.log(` Config: ${s}/config.yaml`),console.log(` Environments: ${l}/`),console.log(""),console.log("Next steps:"),console.log(" 1. Edit .minienv/config.yaml to configure your backend"),console.log(" 2. Add environment variables to .minienv/environments/*.env"),console.log(' 3. Run "minienv sync -e dev" to sync with backend'))}var ce=require("s3db.js"),on=`file://${process.env.HOME||"/tmp"}/.minienv/store`,rn="minienv-default-dev-key",m=class{db=null;resource=null;connectionString;passphrase;initialized=!1;constructor(e={}){this.connectionString=e.connectionString||on,this.passphrase=e.passphrase||rn}async connect(){this.initialized||(this.db=new ce.S3db({connectionString:this.connectionString,passphrase:this.passphrase}),await this.db.connect(),this.resource=await this.db.createResource({name:"environment-variables",attributes:{key:"string|required",value:"secret|required",project:"string|required",service:"string|optional",environment:"enum:dev,stg,prd,sbx,dr|required",tags:"array|items:string|optional",metadata:{description:"string|optional",owner:"string|optional",rotateAfter:"date|optional",source:"enum:manual,sync,import|optional"}},partitions:{byProject:{fields:{project:"string"}},byProjectEnv:{fields:{project:"string",environment:"string"}},byProjectServiceEnv:{fields:{project:"string",service:"string",environment:"string"}}},behavior:"body-overflow",timestamps:!0,asyncPartitions:!0}),this.initialized=!0)}ensureConnected(){if(!this.initialized||!this.resource)throw new Error("MiniEnvClient not initialized. Call connect() first.")}async get(e,o,r,i){this.ensureConnected();let t=i?"byProjectServiceEnv":"byProjectEnv",s=i?{project:o,service:i,environment:r}:{project:o,environment:r};return(await this.resource.list({partition:t,partitionValues:s})).find(u=>u.key===e)||null}async set(e){this.ensureConnected();let o=await this.get(e.key,e.project,e.environment,e.service);return o?await this.resource.update(o.id,{value:e.value,tags:e.tags,metadata:{...o.metadata,...e.metadata,source:e.metadata?.source||"manual"}}):await this.resource.insert({...e,metadata:{...e.metadata,source:e.metadata?.source||"manual"}})}async delete(e,o,r,i){this.ensureConnected();let t=await this.get(e,o,r,i);return t?(await this.resource.delete(t.id),!0):!1}async list(e={}){this.ensureConnected();let{project:o,service:r,environment:i,limit:t,offset:s}=e,f,l;o&&r&&i?(f="byProjectServiceEnv",l={project:o,service:r,environment:i}):o&&i?(f="byProjectEnv",l={project:o,environment:i}):o&&(f="byProject",l={project:o});let u={};return f&&l&&(u.partition=f,u.partitionValues=l),t&&(u.limit=t),s&&(u.offset=s),await this.resource.list(u)}async insertMany(e){this.ensureConnected();let o=[];for(let r of e){let i=await this.set(r);o.push(i)}return o}async deleteAll(e,o,r){this.ensureConnected();let i=await this.list({project:e,environment:o,service:r}),t=0;for(let s of i)await this.resource.delete(s.id),t++;return t}async export(e,o,r){let i=await this.list({project:e,environment:o,service:r}),t={};for(let s of i)t[s.key]=s.value;return t}async sync(e,o,r,i,t={}){this.ensureConnected();let s=await this.list({project:o,environment:r,service:i}),f=new Map(s.map(u=>[u.key,u])),l={added:[],updated:[],deleted:[],unchanged:[],conflicts:[]};for(let[u,c]of Object.entries(e)){let a=f.get(u);a?a.value!==c?(await this.set({key:u,value:c,project:o,environment:r,service:i,metadata:{source:t.source||"sync"}}),l.updated.push(u)):l.unchanged.push(u):(await this.set({key:u,value:c,project:o,environment:r,service:i,metadata:{source:t.source||"sync"}}),l.added.push(u)),f.delete(u)}for(let[u]of f)l.deleted.push(u);return l}async disconnect(){this.db&&(await this.db.disconnect(),this.db=null,this.resource=null,this.initialized=!1)}isConnected(){return this.initialized}getConnectionString(){return this.connectionString}};async function ae(n){let{args:e,config:o,project:r,service:i,environment:t,verbose:s,jsonOutput:f}=n,l=e._[1];l||(console.error("Error: Key name is required"),console.error("Usage: minienv get <key> [-e <env>]"),process.exit(1)),r||(console.error("Error: Project not specified and no config found"),console.error('Run "minienv init" or specify --project'),process.exit(1)),s&&console.error(`Getting ${l} for ${r}/${i||"(no service)"}/${t}`);let u=e.backend||e.b||o?.backend?.url,c=o?await y(o):void 0,a=new m({connectionString:u||void 0,passphrase:c||void 0});try{await a.connect();let g=await a.get(l,r,t,i);g||(f?console.log(JSON.stringify({error:"not_found",key:l,project:r,environment:t})):console.error(`Variable ${l} not found`),process.exit(1)),console.log(f?JSON.stringify({key:g.key,value:g.value,project:g.project,service:g.service,environment:g.environment,tags:g.tags,metadata:g.metadata,createdAt:g.createdAt,updatedAt:g.updatedAt}):g.value)}finally{await a.disconnect()}}function tn(n){return n==="prd"||n==="dr"}async function le(n){let{args:e,config:o,project:r,service:i,environment:t,verbose:s,dryRun:f,jsonOutput:l}=n,u=e._[1],c=e._[2];if(u||(console.error("Error: Key name is required"),console.error("Usage: minienv set <key> <value> [-e <env>]"),process.exit(1)),c===void 0&&(console.error("Error: Value is required"),console.error("Usage: minienv set <key> <value> [-e <env>]"),process.exit(1)),r||(console.error("Error: Project not specified and no config found"),console.error('Run "minienv init" or specify --project'),process.exit(1)),tn(t)&&o?.security?.confirm_production&&!e.force&&(console.error(`Warning: You are modifying ${t} (production) environment`),console.error("Use --force to confirm this action"),process.exit(1)),s&&console.error(`Setting ${u} for ${r}/${i||"(no service)"}/${t}`),f){console.log(l?JSON.stringify({action:"set",key:u,project:r,service:i,environment:t,dryRun:!0}):`Dry run - would set ${u} in ${r}/${t}`);return}let a=e.backend||e.b||o?.backend?.url,g=o?await y(o):void 0,d=new m({connectionString:a||void 0,passphrase:g||void 0});try{await d.connect();let p=await d.set({key:u,value:c,project:r,service:i,environment:t,metadata:{source:"manual"}});console.log(l?JSON.stringify({success:!0,key:p.key,project:p.project,service:p.service,environment:p.environment,createdAt:p.createdAt,updatedAt:p.updatedAt}):`\u2713 Set ${u} in ${r}/${t}`)}finally{await d.disconnect()}}function sn(n){return n==="prd"||n==="dr"}async function fe(n){let{args:e,config:o,project:r,service:i,environment:t,verbose:s,dryRun:f,jsonOutput:l}=n,u=e._[1];if(u||(console.error("Error: Key name is required"),console.error("Usage: minienv delete <key> [-e <env>]"),process.exit(1)),r||(console.error("Error: Project not specified and no config found"),console.error('Run "minienv init" or specify --project'),process.exit(1)),sn(t)&&o?.security?.confirm_production&&!e.force&&(console.error(`Warning: You are deleting from ${t} (production) environment`),console.error("Use --force to confirm this action"),process.exit(1)),s&&console.error(`Deleting ${u} from ${r}/${i||"(no service)"}/${t}`),f){console.log(l?JSON.stringify({action:"delete",key:u,project:r,service:i,environment:t,dryRun:!0}):`Dry run - would delete ${u} from ${r}/${t}`);return}let c=e.backend||e.b||o?.backend?.url,a=o?await y(o):void 0,g=new m({connectionString:c||void 0,passphrase:a||void 0});try{await g.connect(),await g.delete(u,r,t,i)||(l?console.log(JSON.stringify({error:"not_found",key:u,project:r,environment:t})):console.error(`Variable ${u} not found`),process.exit(1)),console.log(l?JSON.stringify({success:!0,deleted:u,project:r,service:i,environment:t}):`\u2713 Deleted ${u} from ${r}/${t}`)}finally{await g.disconnect()}}function ue(n,e=!1){return e?n:n.length<=8?"****":n.substring(0,4)+"****"+n.substring(n.length-4)}function cn(n,e){if(n.length===0)return"No variables found";let o=Math.max(4,...n.map(s=>s.key.length)),r=e?Math.max(5,...n.map(s=>ue(s.value,e).length)):12,i=3,t=[];t.push("KEY".padEnd(o)+" "+"VALUE".padEnd(r)+" ENV"),t.push("-".repeat(o+r+i+4));for(let s of n)t.push(s.key.padEnd(o)+" "+ue(s.value,e).padEnd(r)+" "+s.environment);return t.join(`
56
- `)}async function ge(n){let{args:e,config:o,project:r,service:i,environment:t,verbose:s,jsonOutput:f}=n;r||(console.error("Error: Project not specified and no config found"),console.error('Run "minienv init" or specify --project'),process.exit(1)),s&&console.error(`Listing variables for ${r}/${i||"(no service)"}/${t}`);let l=e.backend||e.b||o?.backend?.url,u=o?await y(o):void 0,c=new m({connectionString:l||void 0,passphrase:u||void 0});try{await c.connect();let a=await c.list({project:r,service:i,environment:e.all?void 0:t});if(f)console.log(JSON.stringify({project:r,service:i,environment:e.all?"all":t,count:a.length,variables:a.map(g=>({key:g.key,value:g.value,environment:g.environment,tags:g.tags,metadata:g.metadata,createdAt:g.createdAt,updatedAt:g.updatedAt}))}));else{let g=e.verbose||e.v||!1;console.log(cn(a,g)),!g&&a.length>0&&(console.log(""),console.log("(use -v to show full values)"))}}finally{await c.disconnect()}}var de=h(require("node:fs"),1),z=100;function K(n,e={}){let o=de.default.readFileSync(n,"utf-8");return pe(o,e)}function pe(n,e={}){let{expand:o=!0,env:r=process.env}=e,i={},t=n.split(/\r?\n/),s=0;for(;s<t.length;){let f=t[s].trim();if(s++,!f||f.startsWith("#")||f.startsWith(";"))continue;let l=f.match(/^([a-zA-Z_][a-zA-Z0-9_]*)\s*=\s*(.*)$/);if(!l)continue;let u=l[1],c=l[2];if(c.startsWith('"')){let a=an(c,t,s);c=a.value,s=a.nextIndex}else if(c.startsWith("'")){let a=ln(c,t,s);c=a.value,s=a.nextIndex}else if(c.startsWith("`")){let a=fn(c,t,s);c=a.value,s=a.nextIndex}else{let a=c.indexOf("#");a>0&&(c=c.substring(0,a).trim())}o&&(c=un(c,{...r,...i})),i[u]=c}return i}function an(n,e,o){let r=n.substring(1),i=0,t="",s=0,f=o;for(;i<z;){for(;s<r.length;){let l=r[s];if(l==="\\"&&s+1<r.length){let u=r[s+1];switch(u){case"n":t+=`
57
- `;break;case"r":t+="\r";break;case"t":t+=" ";break;case'"':t+='"';break;case"\\":t+="\\";break;case"$":t+="$";break;default:t+=l+u}s+=2}else{if(l==='"')return{value:t,nextIndex:f};t+=l,s++}}if(f>=e.length)break;t+=`
58
- `,r=e[f],f++,s=0,i++}return{value:t,nextIndex:f}}function ln(n,e,o){let r=n.substring(1),i=0,t="",s=0,f=o;for(;i<z;){for(;s<r.length;){let l=r[s];if(l==="'"&&r[s+1]!=="'")return{value:t,nextIndex:f};l==="'"&&r[s+1]==="'"?(t+="'",s+=2):(t+=l,s++)}if(f>=e.length)break;t+=`
59
- `,r=e[f],f++,s=0,i++}return{value:t,nextIndex:f}}function fn(n,e,o){let r=n.substring(1),i=0,t="",s=0,f=o;for(;i<z;){let l=r.indexOf("`",s);if(l!==-1)return t+=r.substring(s,l),{value:t,nextIndex:f};if(t+=r.substring(s),f>=e.length)break;t+=`
60
- `,r=e[f],f++,s=0,i++}return{value:t,nextIndex:f}}function un(n,e){return n=n.replace(/\$\{([a-zA-Z_][a-zA-Z0-9_]*):-([^}]*)\}/g,(o,r,i)=>e[r]??i),n=n.replace(/\$\{([a-zA-Z_][a-zA-Z0-9_]*)\}/g,(o,r)=>e[r]??""),n=n.replace(/\$([a-zA-Z_][a-zA-Z0-9_]*)/g,(o,r)=>e[r]??""),n}function L(n){let e=[];for(let[o,r]of Object.entries(n))if(r.includes(`
61
- `)||r.includes(" ")||r.includes("#")||r.includes('"')||r.includes("'")||r.includes("$")||r.includes("=")){let t=r.replace(/\\/g,"\\\\").replace(/"/g,'\\"').replace(/\n/g,"\\n").replace(/\r/g,"\\r").replace(/\t/g,"\\t");e.push(`${o}="${t}"`)}else e.push(`${o}=${r}`);return e.join(`
62
- `)}async function T(n={}){return new Promise((e,o)=>{let r="";process.stdin.setEncoding("utf8"),process.stdin.on("data",i=>{r+=i}),process.stdin.on("end",()=>{try{let i=pe(r,n);e(i)}catch(i){o(i)}}),process.stdin.on("error",o)})}function F(){return!process.stdin.isTTY}function gn(n){return/[^a-zA-Z0-9_\-.:\/]/.test(n)?"'"+n.replace(/'/g,`'"'"'`)+"'":n}function me(n){return Object.entries(n).map(([e,o])=>`export ${e}=${gn(o)}`).join(`
63
- `)}function dn(n){return JSON.stringify(n,null,2)}function pn(n){return Object.entries(n).map(([e,o])=>o.includes(":")||o.includes("#")||o.includes(`
64
- `)||o.startsWith(" ")||o.endsWith(" ")||o===""||o==="true"||o==="false"||o==="null"||!isNaN(Number(o))?`${e}: "${o.replace(/"/g,'\\"').replace(/\n/g,"\\n")}"`:`${e}: ${o}`).join(`
65
- `)}function mn(n){return Object.entries(n).map(([e,o])=>`${e.toLowerCase()} = "${o.replace(/"/g,'\\"')}"`).join(`
66
- `)}async function ve(n){let{args:e,config:o,project:r,service:i,environment:t,verbose:s,jsonOutput:f}=n;r||(console.error("Error: Project not specified and no config found"),console.error('Run "minienv init" or specify --project'),process.exit(1));let l="shell";if(e.format){let g=["shell","json","yaml","env","tfvars"];g.includes(e.format)||(console.error(`Error: Invalid format "${e.format}"`),console.error(`Valid formats: ${g.join(", ")}`),process.exit(1)),l=e.format}else f&&(l="json");s&&console.error(`Exporting ${r}/${i||"(no service)"}/${t} as ${l}`);let u=e.backend||e.b||o?.backend?.url,c=o?await y(o):void 0,a=new m({connectionString:u||void 0,passphrase:c||void 0});try{await a.connect();let g=await a.export(r,t,i),d;switch(l){case"shell":d=me(g);break;case"json":d=dn(g);break;case"yaml":d=pn(g);break;case"env":d=L(g);break;case"tfvars":d=mn(g);break;default:d=me(g)}console.log(d)}finally{await a.disconnect()}}var we=h(require("node:fs"),1),je=h(require("node:path"),1);var V=h(require("node:fs"),1),$=h(require("node:path"),1);var ye=".minienv",he="config.yaml",vn=5;function I(n=process.cwd()){let e=[],o=new Set;function r(i,t){if(t>vn)return;let s=$.default.resolve(i);if(!o.has(s)){o.add(s);try{let f=V.default.readdirSync(s,{withFileTypes:!0});for(let l of f){if(!l.isDirectory()||yn(l.name))continue;let u=$.default.join(s,l.name),c=$.default.join(u,ye),a=$.default.join(c,he);if(V.default.existsSync(a))try{let g=D(u),d=g.service||l.name;e.push({name:d,path:u,configDir:c,config:g})}catch{}r(u,t+1)}}catch{}}}return r(n,0),e}function yn(n){return["node_modules",".git",".svn",".hg","dist","build","coverage",".cache",".next",".nuxt",".output","__pycache__","venv",".venv","vendor","target",".terraform",".terragrunt-cache"].includes(n)||n.startsWith(".")}function be(n,e){let o=e.split(",").map(r=>r.trim()).filter(Boolean);return o.length===0?n:n.filter(r=>o.some(i=>i===r.name?!0:i.includes("*")?new RegExp("^"+i.replace(/\*/g,".*").replace(/\?/g,".")+"$").test(r.name):!1))}function U(n=process.cwd()){let e=$.default.resolve(n),o=null;for(;;){let r=$.default.join(e,ye),i=$.default.join(r,he);V.default.existsSync(i)&&(o=e);let t=$.default.dirname(e);if(t===e)break;e=t}return o}function Ee(n){if(n.length===0)return"No services found";let e=["Services found:"];for(let o of n){let r=$.default.relative(process.cwd(),o.path);e.push(` \u2022 ${o.name} (${r||"."})`)}return e.join(`
67
- `)}async function Se(n,e,o,r={}){let{concurrency:i=1,stopOnError:t=!1,verbose:s=!1,onProgress:f}=r,l=[],u=0,c=0;for(let a=0;a<n.length;a++){let g=n[a];f&&f(a,n.length,g);let d=Date.now();try{let p=await o(g,e),v=Date.now()-d;l.push({service:g,environment:e,result:p,duration:v}),u++}catch(p){let v=Date.now()-d;if(l.push({service:g,environment:e,error:p instanceof Error?p:new Error(String(p)),duration:v}),c++,t)break}}return{total:n.length,successful:u,failed:c,operations:l}}function xe(n,e){let o=[];if(o.push(""),o.push("Batch Operation Summary:"),o.push(` Total: ${n.total}`),o.push(` Successful: ${n.successful}`),o.push(` Failed: ${n.failed}`),o.push(""),n.failed>0){o.push("Failures:");for(let r of n.operations)r.error&&o.push(` \u2717 ${r.service.name}: ${r.error.message}`);o.push("")}if(e){o.push("Details:");for(let r of n.operations)o.push(` ${e(r)}`)}return o.join(`
68
- `)}function ke(n){return{total:n.total,successful:n.successful,failed:n.failed,operations:n.operations.map(e=>({service:e.service.name,path:e.service.path,environment:e.environment,success:!e.error,error:e.error?.message,duration:e.duration,result:e.result}))}}function $e(n){return n==="prd"||n==="dr"}async function Ce(n,e){let{args:o,config:r,project:i,service:t,environment:s,verbose:f,dryRun:l,jsonOutput:u}=n,c=e?.config||r,a=e?.config.project||i,g=e?.name||t,d;if(F()&&!e)f&&console.error("Reading variables from stdin..."),d=await T();else{let E=o.file||o.f,S;if(E&&!e)S=je.default.resolve(E);else{let j=e?.configDir||w();if(!j)throw new Error("No config directory found and no file specified");S=P(j,s)}if(!we.default.existsSync(S))throw new Error(`File not found: ${S}`);f&&console.error(`Reading variables from ${S}`),d=K(S)}f&&console.error(`Found ${Object.keys(d).length} local variables`);let p=o.backend||o.b||c?.backend?.url,v=c?await y(c):void 0,b=new m({connectionString:p||void 0,passphrase:v||void 0});try{if(await b.connect(),l){let E=await b.export(a,s,g),S=[],j=[],C=[],M=[];for(let[O,Ge]of Object.entries(d))O in E?E[O]!==Ge?j.push(O):M.push(O):S.push(O);for(let O of Object.keys(E))O in d||C.push(O);return{added:S,updated:j,deleted:C,unchanged:M,conflicts:[]}}return await b.sync(d,a,s,g,{source:"sync"})}finally{await b.disconnect()}}async function Oe(n){let{args:e,config:o,project:r,service:i,environment:t,verbose:s,dryRun:f,jsonOutput:l}=n,u=e.all,c=e.service||e.s;if(u||c&&c.includes(",")){await hn(n);return}r||(console.error("Error: Project not specified and no config found"),console.error('Run "minienv init" or specify --project'),process.exit(1)),$e(t)&&o?.security?.confirm_production&&!e.force&&(console.error(`Warning: You are syncing to ${t} (production) environment`),console.error("Use --force to confirm this action"),process.exit(1));try{let a=await Ce(n);l?console.log(JSON.stringify({success:!0,dryRun:f,project:r,service:i,environment:t,added:a.added,updated:a.updated,deleted:a.deleted,unchanged:a.unchanged,conflicts:a.conflicts})):f?(console.log("Dry run - changes that would be made:"),a.added.length>0&&console.log(` Add (${a.added.length}): ${a.added.join(", ")}`),a.updated.length>0&&console.log(` Update (${a.updated.length}): ${a.updated.join(", ")}`),a.deleted.length>0&&console.log(` Delete (${a.deleted.length}): ${a.deleted.join(", ")}`),a.unchanged.length>0&&console.log(` Unchanged: ${a.unchanged.length} variables`),a.added.length===0&&a.updated.length===0&&a.deleted.length===0&&console.log(" No changes needed")):(console.log(`\u2713 Synced ${r}/${t}`),a.added.length>0&&console.log(` Added: ${a.added.length} (${a.added.join(", ")})`),a.updated.length>0&&console.log(` Updated: ${a.updated.length} (${a.updated.join(", ")})`),a.deleted.length>0&&console.log(` Deleted: ${a.deleted.length} (${a.deleted.join(", ")})`),a.unchanged.length>0&&console.log(` Unchanged: ${a.unchanged.length}`))}catch(a){console.error(`Error: ${a.message}`),process.exit(1)}}async function hn(n){let{args:e,environment:o,verbose:r,dryRun:i,jsonOutput:t}=n,s=U();s||(console.error("Error: Not inside a monorepo"),console.error("Run this command from within a project that has nested .minienv directories"),process.exit(1));let f=I(s);f.length===0&&(console.error("Error: No services found in monorepo"),process.exit(1));let l=e.service||e.s;if(l&&!e.all&&(f=be(f,l),f.length===0)){console.error(`Error: No services match pattern: ${l}`),console.error(""),console.error("Available services:");let c=I(s);for(let a of c)console.error(` \u2022 ${a.name}`);process.exit(1)}r&&(console.error(Ee(f)),console.error("")),$e(o)&&!e.force&&(console.error(`Warning: You are syncing ${f.length} services to ${o} (production)`),console.error("Use --force to confirm this action"),process.exit(1));let u=await Se(f,o,async(c,a)=>Ce({...n,config:c.config},c),{verbose:r,onProgress:r?(c,a,g)=>{console.error(`[${c+1}/${a}] Syncing ${g.name}...`)}:void 0});console.log(t?JSON.stringify(ke(u)):xe(u,c=>{if(c.error)return`\u2717 ${c.service.name}: ${c.error.message}`;let a=c.result,g=a.added.length+a.updated.length+a.deleted.length;return`\u2713 ${c.service.name}: ${g} changes (${c.duration}ms)`})),u.failed>0&&process.exit(1)}var _=h(require("node:fs"),1),Y=h(require("node:path"),1);async function Pe(n){let{args:e,config:o,project:r,service:i,environment:t,verbose:s,dryRun:f,jsonOutput:l}=n;r||(console.error("Error: Project not specified and no config found"),console.error('Run "minienv init" or specify --project'),process.exit(1));let u=e.output||e.o||e.file||e.f,c=null;if(u)c=Y.default.resolve(u);else{let p=w();p&&(c=P(p,t))}s&&(console.error(`Pulling ${r}/${i||"(no service)"}/${t}`),console.error(c?`Output: ${c}`:"Output: stdout"));let a=e.backend||e.b||o?.backend?.url,g=o?await y(o):void 0,d=new m({connectionString:a||void 0,passphrase:g||void 0});try{await d.connect();let p=await d.export(r,t,i),v=Object.keys(p).length;if(v===0){l?console.log(JSON.stringify({warning:"no_variables",project:r,service:i,environment:t})):console.error(`Warning: No variables found for ${r}/${t}`);return}let b=L(p);if(f){l?console.log(JSON.stringify({dryRun:!0,project:r,service:i,environment:t,variableCount:v,outputPath:c,variables:Object.keys(p)})):(console.log(`Dry run - would pull ${v} variables:`),console.log(` Variables: ${Object.keys(p).join(", ")}`),console.log(c?` Output: ${c}`:" Output: stdout"));return}if(c){_.default.existsSync(c)&&!e.force&&(console.error(`Warning: File exists: ${c}`),console.error("Use --force to overwrite"),process.exit(1));let E=Y.default.dirname(c);_.default.existsSync(E)||_.default.mkdirSync(E,{recursive:!0}),_.default.writeFileSync(c,b+`
69
- `),console.log(l?JSON.stringify({success:!0,project:r,service:i,environment:t,variableCount:v,outputPath:c}):`\u2713 Pulled ${v} variables to ${c}`)}else console.log(l?JSON.stringify({success:!0,project:r,service:i,environment:t,variables:p}):b)}finally{await d.disconnect()}}var Ne=h(require("node:fs"),1),Re=h(require("node:path"),1);function bn(n){return n==="prd"||n==="dr"}async function Ae(n){let{args:e,config:o,project:r,service:i,environment:t,verbose:s,dryRun:f,jsonOutput:l}=n;r||(console.error("Error: Project not specified and no config found"),console.error('Run "minienv init" or specify --project'),process.exit(1)),bn(t)&&o?.security?.confirm_production&&!e.force&&(console.error(`Warning: You are pushing to ${t} (production) environment`),console.error("Use --force to confirm this action"),process.exit(1));let u;if(F())s&&console.error("Reading variables from stdin..."),u=await T();else{let p=e.file||e.f,v;if(p)v=Re.default.resolve(p);else{let b=w();b||(console.error("Error: No config directory found and no file specified"),console.error("Use -f <file> to specify the .env file"),process.exit(1)),v=P(b,t)}Ne.default.existsSync(v)||(console.error(`Error: File not found: ${v}`),process.exit(1)),s&&console.error(`Reading variables from ${v}`),u=K(v)}let c=Object.keys(u).length;if(c===0){l?console.log(JSON.stringify({warning:"no_variables",message:"No variables found in source"})):console.error("Warning: No variables found in source");return}s&&console.error(`Found ${c} variables to push`);let a=e.backend||e.b||o?.backend?.url,g=o?await y(o):void 0,d=new m({connectionString:a||void 0,passphrase:g||void 0});try{if(await d.connect(),f){let b=await d.export(r,t,i),E=[],S=[],j=[];for(let[C,M]of Object.entries(u))C in b?b[C]!==M?S.push(C):j.push(C):E.push(C);l?console.log(JSON.stringify({dryRun:!0,project:r,service:i,environment:t,changes:{add:E,update:S,unchanged:j}})):(console.log("Dry run - changes that would be made:"),E.length>0&&console.log(` Add (${E.length}): ${E.join(", ")}`),S.length>0&&console.log(` Update (${S.length}): ${S.join(", ")}`),j.length>0&&console.log(` Unchanged: ${j.length} variables`),E.length===0&&S.length===0&&console.log(" No changes needed"));return}let p=0,v=0;for(let[b,E]of Object.entries(u)){let S=await d.get(b,r,t,i);await d.set({key:b,value:E,project:r,service:i,environment:t,metadata:{source:"sync"}}),S?v++:p++}l?console.log(JSON.stringify({success:!0,project:r,service:i,environment:t,added:p,updated:v,total:c})):(console.log(`\u2713 Pushed ${c} variables to ${r}/${t}`),p>0&&console.log(` Added: ${p}`),v>0&&console.log(` Updated: ${v}`))}finally{await d.disconnect()}}function En(n){return Buffer.from(n).toString("base64")}function J(n){return n.toLowerCase().replace(/[^a-z0-9-]/g,"-").replace(/--+/g,"-").replace(/^-|-$/g,"")}async function Ie(n){let{args:e,config:o,project:r,service:i,environment:t,verbose:s,jsonOutput:f}=n;r||(console.error("Error: Project not specified"),process.exit(1));let l=e.namespace||e.n||o?.integrations?.kubernetes?.namespace||`${r}-${t}`,u=o?.integrations?.kubernetes?.secret_name||(i?`${i}-secrets`:`${r}-secrets`);s&&console.error(`Generating K8s Secret: ${l}/${u}`);let c=e.backend||e.b||o?.backend?.url,a=o?await y(o):void 0,g=new m({connectionString:c||void 0,passphrase:a||void 0});try{await g.connect();let d=await g.export(r,t,i);if(Object.keys(d).length===0){console.error("Warning: No variables found");return}let p=Sn(J(u),J(l),d,{project:r,service:i,environment:t,managedBy:"minienv"});console.log(f?JSON.stringify({kind:"Secret",name:u,namespace:l,variableCount:Object.keys(d).length}):p)}finally{await g.disconnect()}}async function _e(n){let{args:e,config:o,project:r,service:i,environment:t,verbose:s,jsonOutput:f}=n;r||(console.error("Error: Project not specified"),process.exit(1));let l=e.namespace||e.n||o?.integrations?.kubernetes?.namespace||`${r}-${t}`,u=o?.integrations?.kubernetes?.configmap_name||(i?`${i}-config`:`${r}-config`);s&&console.error(`Generating K8s ConfigMap: ${l}/${u}`);let c=e.backend||e.b||o?.backend?.url,a=o?await y(o):void 0,g=new m({connectionString:c||void 0,passphrase:a||void 0});try{await g.connect();let d=await g.export(r,t,i);if(Object.keys(d).length===0){console.error("Warning: No variables found");return}let p=xn(J(u),J(l),d,{project:r,service:i,environment:t,managedBy:"minienv"});console.log(f?JSON.stringify({kind:"ConfigMap",name:u,namespace:l,variableCount:Object.keys(d).length}):p)}finally{await g.disconnect()}}function Sn(n,e,o,r){let i=["# Generated by minienv","# DO NOT EDIT - changes will be overwritten","apiVersion: v1","kind: Secret","metadata:",` name: ${n}`,` namespace: ${e}`," labels:"];for(let[t,s]of Object.entries(r))s&&i.push(` app.kubernetes.io/${t}: "${s}"`);i.push("type: Opaque"),i.push("data:");for(let[t,s]of Object.entries(o))i.push(` ${t}: ${En(s)}`);return i.join(`
70
- `)}function xn(n,e,o,r){let i=["# Generated by minienv","# DO NOT EDIT - changes will be overwritten","apiVersion: v1","kind: ConfigMap","metadata:",` name: ${n}`,` namespace: ${e}`," labels:"];for(let[t,s]of Object.entries(r))s&&i.push(` app.kubernetes.io/${t}: "${s}"`);i.push("data:");for(let[t,s]of Object.entries(o))s.includes(":")||s.includes("#")||s.includes(`
71
- `)||s.startsWith(" ")||s.endsWith(" ")?i.push(` ${t}: "${s.replace(/"/g,'\\"').replace(/\n/g,"\\n")}"`):i.push(` ${t}: ${s}`);return i.join(`
72
- `)}async function De(n){let{args:e,config:o,project:r,service:i,environment:t,verbose:s,jsonOutput:f}=n;r||(console.error("Error: Project not specified"),process.exit(1)),s&&console.error(`Generating Helm values for ${r}/${t}`);let l=e.backend||e.b||o?.backend?.url,u=o?await y(o):void 0,c=new m({connectionString:l||void 0,passphrase:u||void 0});try{await c.connect();let a=await c.export(r,t,i);if(Object.keys(a).length===0){console.error("Warning: No variables found");return}if(f)console.log(JSON.stringify({format:"helm-values",project:r,environment:t,variableCount:Object.keys(a).length}));else{let g=kn(a,{project:r,service:i,environment:t});console.log(g)}}finally{await c.disconnect()}}function kn(n,e){let o=["# Generated by minienv",`# Project: ${e.project}`,`# Environment: ${e.environment}`,e.service?`# Service: ${e.service}`:null,"# DO NOT EDIT - changes will be overwritten","","# Environment variables (plain)","env:"].filter(Boolean);for(let[r,i]of Object.entries(n))o.push(` ${r}: ${Me(i)}`);o.push(""),o.push("# Secrets (same values, for use with secretKeyRef)"),o.push("secrets:");for(let[r,i]of Object.entries(n))o.push(` ${r}: ${Me(i)}`);return o.join(`
73
- `)}function Me(n){return n===""||n==="true"||n==="false"||n==="null"||n==="yes"||n==="no"||!isNaN(Number(n))||n.includes(":")||n.includes("#")||n.includes(`
74
- `)||n.includes('"')||n.includes("'")||n.startsWith(" ")||n.endsWith(" ")||n.startsWith("{")||n.startsWith("[")?`"${n.replace(/\\/g,"\\\\").replace(/"/g,'\\"').replace(/\n/g,"\\n")}"`:n}async function Le(n){let{args:e,config:o,project:r,service:i,environment:t,verbose:s,jsonOutput:f}=n;r||(console.error("Error: Project not specified"),process.exit(1)),s&&console.error(`Generating Terraform tfvars for ${r}/${t}`);let l=e.backend||e.b||o?.backend?.url,u=o?await y(o):void 0,c=new m({connectionString:l||void 0,passphrase:u||void 0});try{await c.connect();let a=await c.export(r,t,i);if(Object.keys(a).length===0){console.error("Warning: No variables found");return}if(f)console.log(JSON.stringify({format:"tfvars",project:r,environment:t,variableCount:Object.keys(a).length}));else{let g=wn(a,{project:r,service:i,environment:t});console.log(g)}}finally{await c.disconnect()}}async function Te(n){let{args:e,config:o,project:r,service:i,environment:t,verbose:s,jsonOutput:f}=n;r||(console.error("Error: Project not specified"),process.exit(1)),s&&console.error(`Generating Terraform JSON for ${r}/${t}`);let l=e.backend||e.b||o?.backend?.url,u=o?await y(o):void 0,c=new m({connectionString:l||void 0,passphrase:u||void 0});try{await c.connect();let a=await c.export(r,t,i);if(Object.keys(a).length===0){console.error("Warning: No variables found");return}let g={};for(let[p,v]of Object.entries(a)){let b=p.toLowerCase();g[b]=v}let d={...g,env_vars:a};console.log(JSON.stringify(d,null,2))}finally{await c.disconnect()}}function wn(n,e){let o=["# Generated by minienv",`# Project: ${e.project}`,`# Environment: ${e.environment}`,e.service?`# Service: ${e.service}`:null,"# DO NOT EDIT - changes will be overwritten",""].filter(Boolean);for(let[r,i]of Object.entries(n)){let t=r.toLowerCase();o.push(`${t} = ${Ke(i)}`)}o.push(""),o.push("# All environment variables as a map"),o.push("env_vars = {");for(let[r,i]of Object.entries(n))o.push(` "${r}" = ${Ke(i)}`);return o.push("}"),o.join(`
75
- `)}function Ke(n){return`"${n.replace(/\\/g,"\\\\").replace(/"/g,'\\"').replace(/\n/g,"\\n").replace(/\r/g,"\\r").replace(/\t/g,"\\t")}"`}var Fe=h(require("node:crypto"),1),R=h(require("node:fs"),1),G=h(require("node:path"),1);function jn(){return Fe.default.randomBytes(32).toString("base64")}async function Ve(n){let{args:e,config:o,verbose:r,dryRun:i,jsonOutput:t}=n,s=e._[1];switch(s){case"generate":case"gen":await $n(n);break;case"show":await Cn(n);break;case"rotate":await On(n);break;default:console.error(`Unknown key subcommand: ${s||"(none)"}`),console.error("Available subcommands: generate, show, rotate"),console.error(""),console.error("Examples:"),console.error(" minienv key generate # Generate new key to stdout"),console.error(" minienv key generate -o .key # Generate key to file"),console.error(" minienv key show # Show current key source"),process.exit(1)}}async function $n(n){let{args:e,verbose:o,dryRun:r,jsonOutput:i}=n,t=e.output||e.o;o&&console.error("Generating new AES-256 encryption key...");let s=jn();if(r){i?console.log(JSON.stringify({dryRun:!0,action:"generate_key",outputPath:t||"stdout",keyLength:32,algorithm:"aes-256-gcm"})):(console.log("Dry run - would generate new encryption key"),console.log(t?` Output: ${t}`:" Output: stdout"));return}if(t){let f=G.default.resolve(t);R.default.existsSync(f)&&!e.force&&(console.error(`Error: File exists: ${f}`),console.error("Use --force to overwrite"),process.exit(1));let l=G.default.dirname(f);R.default.existsSync(l)||R.default.mkdirSync(l,{recursive:!0}),R.default.writeFileSync(f,s+`
76
- `,{mode:384}),i?console.log(JSON.stringify({success:!0,outputPath:f,keyLength:32,algorithm:"aes-256-gcm"})):(console.log(`\u2713 Generated encryption key: ${f}`),console.log(" Store this key securely - it cannot be recovered!"),console.log(""),console.log("To use this key:"),console.log(` 1. Set environment variable: export MINIENV_KEY=$(cat ${f})`),console.log(" 2. Or configure in .minienv/config.yaml:"),console.log(" encryption:"),console.log(" key_source:"),console.log(` - file: ${t}`))}else console.log(i?JSON.stringify({key:s,keyLength:32,algorithm:"aes-256-gcm"}):s)}async function Cn(n){let{config:e,jsonOutput:o}=n;e||(console.error("Error: No minienv configuration found"),console.error('Run "minienv init" first'),process.exit(1));let r=e.encryption?.key_source||[],i=[];for(let t of r)"env"in t?i.push({type:"env",source:t.env,available:!!process.env[t.env]}):"file"in t?i.push({type:"file",source:t.file,available:R.default.existsSync(G.default.resolve(t.file))}):"s3"in t&&i.push({type:"s3",source:t.s3,available:!1});if(i.some(t=>t.type==="env"&&t.source==="MINIENV_KEY")||i.push({type:"env",source:"MINIENV_KEY",available:!!process.env.MINIENV_KEY}),o)console.log(JSON.stringify({configured:r.length>0,sources:i,activeSource:i.find(t=>t.available)?.source||null}));else{if(console.log("Key Sources:"),i.length===0)console.log(" (none configured)");else for(let s of i){let f=s.available?"\u2713":"\u2717";console.log(` ${f} ${s.type}: ${s.source}`)}let t=i.find(s=>s.available);t?(console.log(""),console.log(`Active key source: ${t.type}:${t.source}`)):(console.log(""),console.log("Warning: No encryption key available"),console.log('Run "minienv key generate -o .minienv/.key" to create one'))}}async function On(n){let{config:e,dryRun:o,jsonOutput:r}=n;e||(console.error("Error: No minienv configuration found"),console.error('Run "minienv init" first'),process.exit(1)),r?console.log(JSON.stringify({error:"not_implemented",message:"Key rotation is not yet fully automated"})):(console.log("Key rotation steps:"),console.log(""),console.log("1. Generate a new key:"),console.log(" minienv key generate -o .minienv/.key.new"),console.log(""),console.log("2. Export current values (with old key):"),console.log(" minienv export -e <env> > vars.env"),console.log(""),console.log("3. Update to new key:"),console.log(" mv .minienv/.key.new .minienv/.key"),console.log(""),console.log("4. Re-import values (with new key):"),console.log(" cat vars.env | minienv sync -e <env>"),console.log(""),console.log("5. Clean up:"),console.log(" rm vars.env"),console.log(""),console.log("Note: Repeat steps 2-4 for each environment."),o&&(console.log(""),console.log("(dry-run mode - no changes made)")))}var H=h(require("node:path"),1);async function Ue(n){let{args:e,verbose:o,jsonOutput:r}=n,i=e._[1];switch(i){case"list":case"ls":case void 0:await Pn(n);break;default:console.error(`Unknown services subcommand: ${i}`),console.error("Available subcommands: list"),console.error(""),console.error("Examples:"),console.error(" minienv services # List all services"),console.error(" minienv services list # Same as above"),console.error(" minienv services list --json # JSON output"),process.exit(1)}}async function Pn(n){let{verbose:e,jsonOutput:o}=n,r=U();r||(o?console.log(JSON.stringify({error:"not_in_monorepo",message:"Not inside a minienv project"})):(console.error("Not inside a minienv project"),console.error('Run "minienv init" first')),process.exit(1));let i=I(r);if(o)console.log(JSON.stringify({root:r,count:i.length,services:i.map(t=>({name:t.name,path:H.default.relative(process.cwd(),t.path)||".",project:t.config.project,environments:t.config.environments||["dev","stg","prd","sbx","dr"],defaultEnvironment:t.config.default_environment||"dev"}))}));else if(i.length===0)console.log("No services found"),console.log(""),console.log("This might be a single-project setup (no nested .minienv directories)");else{console.log(`Found ${i.length} service(s) in monorepo:`),console.log("");for(let t of i){let s=H.default.relative(process.cwd(),t.path)||".";console.log(` ${t.name}`),console.log(` Path: ${s}`),console.log(` Project: ${t.config.project}`),e&&(console.log(` Environments: ${(t.config.environments||["dev","stg","prd"]).join(", ")}`),console.log(` Default: ${t.config.default_environment||"dev"}`),t.config.backend?.url&&console.log(` Backend: ${t.config.backend.url}`)),console.log("")}}}var Nn="0.1.0";function Rn(){return(0,Je.default)(process.argv.slice(2),{string:["project","p","service","s","env","e","backend","b","key","k","file","f","output","o","namespace","n","format"],boolean:["verbose","v","dry-run","json","no-color","help","h","version","force","all"],alias:{p:"project",s:"service",e:"env",b:"backend",k:"key",v:"verbose",f:"file",o:"output",h:"help",n:"namespace"},default:{verbose:!1,"dry-run":!1,json:!1,"no-color":!1}})}function An(){console.log(`
77
- minienv - Multi-backend environment variable and secrets manager
78
-
79
- Usage:
80
- minienv <command> [options]
81
-
82
- Commands:
83
- init Initialize a new .minienv configuration
84
- get <key> Get a single environment variable
85
- set <key> <value> Set an environment variable
86
- delete <key> Delete an environment variable
87
- list List all environment variables
88
- export Export variables for shell evaluation
89
- sync Sync local .env file with backend
90
- pull Pull variables from backend to local .env
91
- push Push local .env to backend
92
- key generate Generate a new encryption key
93
- services List services in monorepo
94
- config Manage configuration
95
-
96
- Integration Commands:
97
- k8s:secret Generate Kubernetes Secret YAML
98
- k8s:configmap Generate Kubernetes ConfigMap YAML
99
- helm:values Generate Helm values.yaml
100
- tf:vars Generate Terraform .tfvars
101
- tf:json Generate Terraform JSON
102
-
103
- Global Options:
104
- -p, --project <name> Project name (default: from config or directory)
105
- -s, --service <name> Service name (for monorepos, supports comma-separated)
106
- -e, --env <env> Environment (dev/stg/prd/sbx/dr)
107
- -b, --backend <url> Backend URL override
108
- -k, --key <path> Encryption key path
109
- -v, --verbose Enable verbose output
110
- --all Apply to all services in monorepo
111
- --dry-run Show what would be done without making changes
112
- --json Output in JSON format
113
- --no-color Disable colored output
114
- -h, --help Show this help message
115
- --version Show version
116
-
117
- Examples:
118
- # Initialize project
119
- minienv init
120
-
121
- # Get a variable
122
- minienv get DATABASE_URL -e prd
123
-
124
- # Set a variable
125
- minienv set API_KEY "sk-..." -e prd
126
-
127
- # Export for shell
128
- eval $(minienv export -e dev)
129
-
130
- # Sync local .env
131
- minienv sync -f .env.local -e dev
132
-
133
- # Sync all services in monorepo
134
- minienv sync -e dev --all
135
-
136
- # Sync specific services
137
- minienv sync -e dev -s svc-auth,svc-api
138
-
139
- # List services in monorepo
140
- minienv services
141
-
142
- # Generate K8s secret
143
- minienv k8s:secret -e prd | kubectl apply -f -
144
-
145
- Documentation: https://github.com/tetis-io/minienv
146
- `)}function In(){console.log(`minienv v${Nn}`)}async function _n(){let n=Rn();if(n.version){In();return}if(n.help||n.h||n._.length===0){An();return}let e=n._[0],o;try{o=D()}catch{o=null}let r=n.env||n.e||o?.default_environment||"dev",i=n.project||n.p||(o?oe(o):""),t=n.service||n.s||o?.service,s=n.verbose||n.v||!1,f=n["dry-run"]||!1,l=n.json||!1,u=n["no-color"]||!1,c={args:n,config:o,project:i,service:t,environment:r,verbose:s,dryRun:f,jsonOutput:l,noColor:u};try{switch(e){case"init":await se(c);break;case"get":await ae(c);break;case"set":await le(c);break;case"delete":case"rm":case"remove":await fe(c);break;case"list":case"ls":await ge(c);break;case"export":await ve(c);break;case"sync":await Oe(c);break;case"pull":await Pe(c);break;case"push":await Ae(c);break;case"key":await Ve(c);break;case"services":case"svc":await Ue(c);break;case"config":console.log("config command not yet implemented");break;case"k8s:secret":await Ie(c);break;case"k8s:configmap":await _e(c);break;case"helm:values":await De(c);break;case"tf:vars":await Le(c);break;case"tf:json":await Te(c);break;default:console.error(`Unknown command: ${e}`),console.error('Run "minienv --help" for usage information'),process.exit(1)}}catch(a){console.error(s?a:`Error: ${a.message}`),process.exit(1)}}_n().catch(n=>{console.error("Fatal error:",n.message),process.exit(1)});