morphix-env 0.3.0 → 0.5.0

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.
Files changed (3) hide show
  1. package/README.md +163 -109
  2. package/dist/cli.js +47 -34
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -26,7 +26,7 @@ npm install -D morphix-env
26
26
  ## Quick Start
27
27
 
28
28
  ```bash
29
- # Run a command with .env.local overrides
29
+ # Run a command with env injection
30
30
  morphix-env run -- next dev
31
31
 
32
32
  # Generate client-side __env.js
@@ -36,6 +36,126 @@ morphix-env generate --out public/__env.js
36
36
  morphix-env inspect
37
37
  ```
38
38
 
39
+ ## How It Works
40
+
41
+ ### Core Flow
42
+
43
+ ```
44
+ morphix-env run -- <command>
45
+ │
46
+ ├─ 1. Read mx-env.config.json
47
+ │
48
+ ├─ 2. Load Infisical secrets ──────────────────────────┐
49
+ │ │ │
50
+ │ ├─ INFISICAL_CLIENT_ID exists? │
51
+ │ │ ├─ Yes → SDK (Machine Identity) ── CI/Docker │
52
+ │ │ └─ No ──┐ │
53
+ │ │ ├─ infisical CLI installed? │
54
+ │ │ │ ├─ Yes → CLI (user login) ── Local │
55
+ │ │ │ └─ No → Skip │
56
+ │ │ │
57
+ │ └─ Inject into process.env (does NOT overwrite) │
58
+ │ │
59
+ ├─ 3. Load .env.local ─────────────────────────────────┐
60
+ │ └─ Inject into process.env (OVERWRITES all) │
61
+ │ │
62
+ ├─ 4. Generate __env.js (if configured) │
63
+ │ └─ Extract NEXT_PUBLIC_* / VITE_* → write file │
64
+ │ │
65
+ └─ 5. Spawn child command │
66
+ └─ Inherits fully assembled process.env │
67
+ ```
68
+
69
+ ### Priority (high → low)
70
+
71
+ ```
72
+ ┌─────────────────────────────────────────────────┐
73
+ │ .env.local ← HIGHEST │
74
+ │ Always wins. Developer's local overrides. │
75
+ ├─────────────────────────────────────────────────┤
76
+ │ Infisical secrets ← MEDIUM │
77
+ │ Pulled via SDK or CLI. Does not overwrite. │
78
+ ├─────────────────────────────────────────────────┤
79
+ │ process.env ← LOWEST │
80
+ │ Docker ENV, CI vars, shell exports. │
81
+ └─────────────────────────────────────────────────┘
82
+ ```
83
+
84
+ ### Authentication Flow
85
+
86
+ ```
87
+ ┌──────────────────────────────────────────────────────────┐
88
+ │ morphix-env starts │
89
+ │ │ │
90
+ │ INFISICAL_CLIENT_ID set? │
91
+ │ / \ │
92
+ │ Yes No │
93
+ │ │ │ │
94
+ │ ┌───────▼────────┐ infisical CLI installed? │
95
+ │ │ SDK Auth │ / \ │
96
+ │ │ (Machine ID) │ Yes No │
97
+ │ │ │ │ │ │
98
+ │ │ CI / Docker / │ ┌──▼───────────┐ │ │
99
+ │ │ Production │ │ CLI Auth │ ▼ │
100
+ │ └────────┬────────┘ │ (User Login) │ Skip │
101
+ │ │ │ │ Infisical │
102
+ │ │ │ Local Dev │ │
103
+ │ │ └──────┬────────┘ │
104
+ │ │ │ │
105
+ │ ▼ ▼ │
106
+ │ Pull secrets from Infisical │
107
+ │ Inject into process.env │
108
+ └──────────────────────────────────────────────────────────┘
109
+ ```
110
+
111
+ ### Local Development
112
+
113
+ ```
114
+ Developer machine:
115
+ 1. infisical login ← one-time, session cached
116
+ 2. pnpm dev ← morphix-env auto-detects CLI
117
+ └─ morphix-env run
118
+ ├─ infisical CLI pulls 69 secrets
119
+ ├─ .env.local overrides API_BASE_URL → localhost
120
+ └─ next dev starts with all vars
121
+ ```
122
+
123
+ ### CI / Docker
124
+
125
+ ```
126
+ Container / CI runner:
127
+ ENV INFISICAL_CLIENT_ID=xxx
128
+ ENV INFISICAL_CLIENT_SECRET=xxx
129
+ ENV DEPLOY_ENV=prod
130
+
131
+ CMD morphix-env run -- node server.js
132
+ └─ morphix-env run
133
+ ├─ SDK pulls secrets (no CLI needed)
134
+ ├─ .env.local not present → skip
135
+ └─ server starts with prod vars
136
+ ```
137
+
138
+ ### `__env.js` — Client-Side Runtime Injection
139
+
140
+ ```
141
+ Build phase (CI):
142
+ morphix-env run -- next build
143
+ ├─ NEXT_PUBLIC_* injected at build time → baked into JS bundle
144
+ └─ Works, but image is environment-specific
145
+
146
+ Runtime injection (Docker, optional):
147
+ morphix-env run -- node server.js
148
+ ├─ morphix-env generates public/__env.js:
149
+ │ window.__ENV = {
150
+ │ "NEXT_PUBLIC_API_URL": "https://api.prod.example.com",
151
+ │ "NEXT_PUBLIC_APP_NAME": "MyApp"
152
+ │ };
153
+ │
154
+ ├─ Browser loads <script src="/__env.js"> before app
155
+ └─ App reads: window.__ENV?.NEXT_PUBLIC_API_URL
156
+ → One build, deploy to any environment
157
+ ```
158
+
39
159
  ## Commands
40
160
 
41
161
  ### `morphix-env run [options] -- <command>`
@@ -43,7 +163,7 @@ morphix-env inspect
43
163
  Load environment variables, then execute a command. The child process inherits all injected vars.
44
164
 
45
165
  ```bash
46
- # Basic: load .env.local, run dev server
166
+ # Basic: load env, run dev server
47
167
  morphix-env run -- next dev --turbo -p 3004
48
168
 
49
169
  # Custom env file
@@ -56,46 +176,14 @@ morphix-env run --no-infisical -- npm start
56
176
  morphix-env run -v -- node server.js
57
177
  ```
58
178
 
59
- **Loading priority (high to low):**
60
-
61
- 1. `.env.local` (or `--env-file`) — always wins
62
- 2. Infisical secrets — pulled via SDK
63
- 3. Existing `process.env` — Docker ENV, CI vars, etc.
64
-
65
179
  ### `morphix-env generate [options]`
66
180
 
67
- Extract public environment variables (`NEXT_PUBLIC_*`, `VITE_*`, `EXPO_PUBLIC_*`) and write them to a JS file for browser runtime injection.
181
+ Extract public environment variables and write to a JS file for browser runtime injection.
68
182
 
69
183
  ```bash
70
- # Default: public/__env.js
71
- morphix-env generate
72
-
73
- # Custom output path (Vite projects)
74
- morphix-env generate --out dist/__env.js
75
-
76
- # Only include specific prefix
77
- morphix-env generate --filter NEXT_PUBLIC_
78
- ```
79
-
80
- Output file content:
81
-
82
- ```js
83
- window.__ENV={"NEXT_PUBLIC_API_URL":"https://api.example.com","NEXT_PUBLIC_APP_NAME":"MyApp"};
84
- ```
85
-
86
- Load it in your HTML before your app bundle:
87
-
88
- ```html
89
- <script src="/__env.js"></script>
90
- ```
91
-
92
- Read in your app:
93
-
94
- ```ts
95
- function getEnv(key: string, fallback = ''): string {
96
- if (typeof window === 'undefined') return process.env[key] || fallback
97
- return window.__ENV?.[key] || process.env[key] || fallback
98
- }
184
+ morphix-env generate # → public/__env.js
185
+ morphix-env generate --out dist/__env.js # Vite projects
186
+ morphix-env generate --filter NEXT_PUBLIC_ # Only Next.js vars
99
187
  ```
100
188
 
101
189
  ### `morphix-env inspect [options]`
@@ -115,19 +203,18 @@ morphix-env inspect -f .env.production
115
203
  | `--env-file <path>` | `-f` | Env file to load (default: `.env.local`, repeatable) |
116
204
  | `--out <path>` | `-o` | Output path for generate (default: `public/__env.js`) |
117
205
  | `--filter <prefix>` | | Only include vars with this prefix |
118
- | `--no-infisical` | | Skip Infisical SDK fetch |
206
+ | `--no-infisical` | | Skip Infisical fetch entirely |
119
207
  | `--verbose` | `-v` | Show loaded variable names |
120
208
 
121
209
  ## Config File
122
210
 
123
- Create `morphix-env.config.json` in your project root to declare project-level settings. This file is committed to git.
211
+ Create `mx-env.config.json` in your project root. Committed to git.
124
212
 
125
213
  ```json
126
214
  {
127
215
  "infisical": {
128
- "projectId": "your-project-id",
129
- "paths": ["/ai/shared", "/ai/web"],
130
- "env": "$DEPLOY_ENV"
216
+ "paths": ["/ai"],
217
+ "env": "dev"
131
218
  },
132
219
  "envFiles": [".env.local"],
133
220
  "generate": {
@@ -137,56 +224,55 @@ Create `morphix-env.config.json` in your project root to declare project-level s
137
224
  }
138
225
  ```
139
226
 
140
- | Field | Description | Committed to git? |
141
- |-------|-------------|-------------------|
142
- | `infisical.projectId` | Infisical project ID | Yes — not a secret |
143
- | `infisical.paths` | Secret paths to pull | Yes — not a secret |
144
- | `infisical.env` | Environment name, supports `$VAR` references | Yes |
145
- | `envFiles` | Local override files to load | Yes |
146
- | `generate` | Client-side __env.js output config | Yes |
227
+ ### Config vs Environment Variables
147
228
 
148
- **Infisical authentication** is always via environment variables — never in the config file:
149
-
150
- | Env Var | Description |
151
- |---------|-------------|
152
- | `INFISICAL_CLIENT_ID` | Machine Identity client ID |
153
- | `INFISICAL_CLIENT_SECRET` | Machine Identity client secret |
154
- | `DEPLOY_ENV` | Environment name (`dev` / `staging` / `prod`) |
229
+ ```
230
+ ┌──────────────────────────────────────────────────────┐
231
+ │ mx-env.config.json (committed to git) │
232
+ │ ├─ paths → which secrets to pull │
233
+ │ ├─ env → which environment │
234
+ │ ├─ envFiles → which override files to load │
235
+ │ └─ generate → __env.js output config │
236
+ │ │
237
+ │ These are PROJECT CONFIG, not secrets. │
238
+ ├──────────────────────────────────────────────────────┤
239
+ │ Environment Variables (NEVER committed) │
240
+ │ ├─ INFISICAL_CLIENT_ID → Machine Identity │
241
+ │ ├─ INFISICAL_CLIENT_SECRET → Machine Identity │
242
+ │ └─ DEPLOY_ENV → prod / staging / dev │
243
+ │ │
244
+ │ These are CREDENTIALS, set in CI/Docker only. │
245
+ │ Local dev uses infisical CLI login instead. │
246
+ └──────────────────────────────────────────────────────┘
247
+ ```
155
248
 
156
249
  ## Usage Examples
157
250
 
158
251
  ### Next.js
159
252
 
160
- ```json
253
+ ```jsonc
254
+ // package.json
161
255
  {
162
256
  "scripts": {
163
257
  "dev": "morphix-env run -- next dev --turbo -p 3004",
164
258
  "build": "morphix-env run -- next build",
165
- "start": "morphix-env run -- node server.js"
259
+ "start": "morphix-env run -- next start"
166
260
  }
167
261
  }
168
262
  ```
169
263
 
170
- `morphix-env.config.json`:
171
-
172
264
  ```json
265
+ // mx-env.config.json
173
266
  {
174
- "infisical": {
175
- "projectId": "xxx",
176
- "paths": ["/ai/shared", "/ai/web"],
177
- "env": "$DEPLOY_ENV"
178
- },
267
+ "infisical": { "paths": ["/ai"], "env": "dev" },
179
268
  "envFiles": [".env.local"],
180
- "generate": {
181
- "out": "public/__env.js",
182
- "filter": "NEXT_PUBLIC_"
183
- }
269
+ "generate": { "out": "public/__env.js", "filter": "NEXT_PUBLIC_" }
184
270
  }
185
271
  ```
186
272
 
187
273
  ### Vite (React / Vue / Ionic)
188
274
 
189
- ```json
275
+ ```jsonc
190
276
  {
191
277
  "scripts": {
192
278
  "dev": "morphix-env run -- vite",
@@ -197,21 +283,14 @@ Create `morphix-env.config.json` in your project root to declare project-level s
197
283
 
198
284
  ```json
199
285
  {
200
- "infisical": {
201
- "projectId": "xxx",
202
- "paths": ["/ai/shared", "/ai/shell"],
203
- "env": "$DEPLOY_ENV"
204
- },
205
- "generate": {
206
- "out": "dist/__env.js",
207
- "filter": "VITE_"
208
- }
286
+ "infisical": { "paths": ["/frontend"], "env": "dev" },
287
+ "generate": { "out": "dist/__env.js", "filter": "VITE_" }
209
288
  }
210
289
  ```
211
290
 
212
291
  ### Express API
213
292
 
214
- ```json
293
+ ```jsonc
215
294
  {
216
295
  "scripts": {
217
296
  "dev": "morphix-env run -- tsx watch src/index.ts",
@@ -222,15 +301,12 @@ Create `morphix-env.config.json` in your project root to declare project-level s
222
301
 
223
302
  ```json
224
303
  {
225
- "infisical": {
226
- "projectId": "xxx",
227
- "paths": ["/ai/shared", "/ai/api"],
228
- "env": "$DEPLOY_ENV"
229
- }
304
+ "infisical": { "paths": ["/ai"], "env": "dev" },
305
+ "envFiles": [".env.local"]
230
306
  }
231
307
  ```
232
308
 
233
- No `generate` field — server-side apps don't need `__env.js`.
309
+ No `generate` — server-side apps don't need `__env.js`.
234
310
 
235
311
  ### Docker
236
312
 
@@ -240,7 +316,6 @@ WORKDIR /app
240
316
  COPY . .
241
317
  RUN pnpm install && pnpm build
242
318
 
243
- # Only these 3 vars needed at runtime
244
319
  ENV INFISICAL_CLIENT_ID=""
245
320
  ENV INFISICAL_CLIENT_SECRET=""
246
321
  ENV DEPLOY_ENV="prod"
@@ -250,27 +325,6 @@ CMD ["npx", "morphix-env", "run", "--", "node", "server.js"]
250
325
 
251
326
  No Infisical CLI binary needed in the image.
252
327
 
253
- ### Local Development with Infisical CLI
254
-
255
- If you already use `infisical run` locally, morphix-env still adds value as the override layer:
256
-
257
- ```json
258
- {
259
- "dev": "infisical run --path=/ai --env=dev -- morphix-env run -- next dev",
260
- "dev:local": "infisical run --path=/ai --env=dev -- morphix-env run -- next dev"
261
- }
262
- ```
263
-
264
- `.env.local` overrides take effect on top of Infisical CLI injection.
265
-
266
- ## How It Works
267
-
268
- 1. Read `morphix-env.config.json` for project settings
269
- 2. If `INFISICAL_CLIENT_ID` + `INFISICAL_CLIENT_SECRET` exist → fetch secrets via SDK, inject into `process.env` (does not overwrite existing vars)
270
- 3. Read `.env.local` → inject into `process.env` (overwrites everything, highest priority)
271
- 4. If `generate` is configured → write `__env.js` with public vars
272
- 5. Spawn child command — it inherits the fully assembled `process.env`
273
-
274
328
  ## License
275
329
 
276
330
  MIT
package/dist/cli.js CHANGED
@@ -61,11 +61,13 @@ function extractPublicVars() {
61
61
  // src/infisical.ts
62
62
  var import_sdk = require("@infisical/sdk");
63
63
  var import_child_process = require("child_process");
64
+ var import_fs2 = require("fs");
65
+ var import_path2 = require("path");
64
66
  var import_dotenv2 = require("dotenv");
65
67
  function getInfisicalConfig() {
66
68
  const clientId = process.env.INFISICAL_CLIENT_ID;
67
69
  const clientSecret = process.env.INFISICAL_CLIENT_SECRET;
68
- const projectId = process.env.INFISICAL_PROJECT_ID;
70
+ const projectId = process.env.INFISICAL_PROJECT_ID || readInfisicalJson().workspaceId;
69
71
  if (!clientId || !clientSecret || !projectId) return null;
70
72
  return {
71
73
  clientId,
@@ -76,7 +78,11 @@ function getInfisicalConfig() {
76
78
  siteUrl: process.env.INFISICAL_SITE_URL
77
79
  };
78
80
  }
79
- async function fetchInfisicalSecrets(config) {
81
+ function applyPrefix(key, prefix) {
82
+ if (!prefix) return key;
83
+ return key.startsWith(prefix) ? key : prefix + key;
84
+ }
85
+ async function fetchInfisicalSecrets(config, envPrefix) {
80
86
  const client = new import_sdk.InfisicalSDK({
81
87
  ...config.siteUrl ? { siteUrl: config.siteUrl } : {}
82
88
  });
@@ -94,7 +100,8 @@ async function fetchInfisicalSecrets(config) {
94
100
  viewSecretValue: true
95
101
  });
96
102
  for (const secret of result.secrets) {
97
- process.env[secret.secretKey] = secret.secretValue;
103
+ const key = applyPrefix(secret.secretKey, envPrefix);
104
+ process.env[key] = secret.secretValue;
98
105
  count++;
99
106
  }
100
107
  }
@@ -108,7 +115,16 @@ function hasInfisicalCLI() {
108
115
  return false;
109
116
  }
110
117
  }
111
- function fetchSecretsViaCLI(environment, paths) {
118
+ function readInfisicalJson() {
119
+ const filePath = (0, import_path2.resolve)(".infisical.json");
120
+ if (!(0, import_fs2.existsSync)(filePath)) return {};
121
+ try {
122
+ return JSON.parse((0, import_fs2.readFileSync)(filePath, "utf8"));
123
+ } catch {
124
+ return {};
125
+ }
126
+ }
127
+ function fetchSecretsViaCLI(environment, paths, envPrefix) {
112
128
  let count = 0;
113
129
  for (const secretPath of paths) {
114
130
  try {
@@ -118,7 +134,7 @@ function fetchSecretsViaCLI(environment, paths) {
118
134
  );
119
135
  const vars = (0, import_dotenv2.parse)(output);
120
136
  for (const [key, value] of Object.entries(vars)) {
121
- process.env[key] = value;
137
+ process.env[applyPrefix(key, envPrefix)] = value;
122
138
  count++;
123
139
  }
124
140
  } catch {
@@ -128,35 +144,25 @@ function fetchSecretsViaCLI(environment, paths) {
128
144
  }
129
145
 
130
146
  // src/config.ts
131
- var import_fs2 = require("fs");
132
- var import_path2 = require("path");
147
+ var import_fs3 = require("fs");
148
+ var import_path3 = require("path");
133
149
  var CONFIG_FILE = "mx-env.config.json";
134
- function resolveEnvRef(value) {
135
- if (value.startsWith("$")) {
136
- return process.env[value.slice(1)] || "";
137
- }
138
- return value;
139
- }
140
150
  function loadConfig() {
141
- const configPath = (0, import_path2.resolve)(CONFIG_FILE);
142
- if (!(0, import_fs2.existsSync)(configPath)) return {};
151
+ const configPath = (0, import_path3.resolve)(CONFIG_FILE);
152
+ if (!(0, import_fs3.existsSync)(configPath)) return {};
143
153
  try {
144
- const raw = JSON.parse((0, import_fs2.readFileSync)(configPath, "utf8"));
145
- if (raw.infisical?.env) {
146
- raw.infisical.env = resolveEnvRef(raw.infisical.env);
147
- }
148
- return raw;
154
+ return JSON.parse((0, import_fs3.readFileSync)(configPath, "utf8"));
149
155
  } catch (e) {
150
- console.warn(`[mx-env] Failed to parse ${CONFIG_FILE}: ${e.message}`);
156
+ console.warn(`[morphix-env] Failed to parse ${CONFIG_FILE}: ${e.message}`);
151
157
  return {};
152
158
  }
153
159
  }
154
160
 
155
161
  // src/cli.ts
156
162
  var import_cross_spawn = __toESM(require("cross-spawn"));
157
- var import_fs3 = require("fs");
158
- var import_path3 = require("path");
159
- var VERSION = "0.3.0";
163
+ var import_fs4 = require("fs");
164
+ var import_path4 = require("path");
165
+ var VERSION = "0.5.0";
160
166
  var DEFAULT_ENV_FILE = ".env.local";
161
167
  function parseArgs(argv) {
162
168
  const args = {
@@ -166,7 +172,8 @@ function parseArgs(argv) {
166
172
  outFile: null,
167
173
  verbose: false,
168
174
  filter: null,
169
- noInfisical: false
175
+ noInfisical: false,
176
+ env: null
170
177
  };
171
178
  let i = 2;
172
179
  const command = argv[i];
@@ -188,6 +195,9 @@ function parseArgs(argv) {
188
195
  } else if (arg === "--filter") {
189
196
  i++;
190
197
  if (argv[i]) args.filter = argv[i];
198
+ } else if (arg === "--env" || arg === "-e") {
199
+ i++;
200
+ if (argv[i]) args.env = argv[i];
191
201
  } else if (arg === "--verbose" || arg === "-v") {
192
202
  args.verbose = true;
193
203
  } else if (arg === "--no-infisical") {
@@ -216,28 +226,30 @@ function mergeWithConfig(args, config) {
216
226
  }
217
227
  async function loadAllEnv(args, config) {
218
228
  if (!args.noInfisical) {
219
- const env = config.infisical?.env || process.env.DEPLOY_ENV || process.env.INFISICAL_ENV || "dev";
229
+ const env = args.env || process.env.DEPLOY_ENV || process.env.INFISICAL_ENV || "prod";
220
230
  const paths = config.infisical?.paths || ["/"];
231
+ const resolvedProjectId = process.env.INFISICAL_PROJECT_ID || config.infisical?.projectId || readInfisicalJson().workspaceId || "";
221
232
  const infisicalConfig = config.infisical ? {
222
233
  clientId: process.env.INFISICAL_CLIENT_ID || "",
223
234
  clientSecret: process.env.INFISICAL_CLIENT_SECRET || "",
224
- projectId: config.infisical.projectId,
235
+ projectId: resolvedProjectId,
225
236
  environment: env,
226
237
  paths,
227
238
  siteUrl: config.infisical.siteUrl
228
239
  } : getInfisicalConfig();
240
+ const envPrefix = config.infisical?.envPrefix;
229
241
  if (infisicalConfig && infisicalConfig.clientId && infisicalConfig.clientSecret) {
230
242
  try {
231
- const count = await fetchInfisicalSecrets(infisicalConfig);
232
- console.log(`[morphix-env] Infisical SDK: loaded ${count} secrets (${env}: ${paths.join(", ")})`);
243
+ const count = await fetchInfisicalSecrets(infisicalConfig, envPrefix);
244
+ console.log(`[morphix-env] Infisical SDK: loaded ${count} secrets (${env}: ${paths.join(", ")})${envPrefix ? ` [prefix: ${envPrefix}]` : ""}`);
233
245
  } catch (e) {
234
246
  console.warn(`[morphix-env] Infisical SDK: failed - ${e.message}`);
235
247
  }
236
248
  } else if (hasInfisicalCLI()) {
237
249
  try {
238
- const count = fetchSecretsViaCLI(env, paths);
250
+ const count = fetchSecretsViaCLI(env, paths, envPrefix);
239
251
  if (count > 0) {
240
- console.log(`[morphix-env] Infisical CLI: loaded ${count} secrets (${env}: ${paths.join(", ")})`);
252
+ console.log(`[morphix-env] Infisical CLI: loaded ${count} secrets (${env}: ${paths.join(", ")})${envPrefix ? ` [prefix: ${envPrefix}]` : ""}`);
241
253
  } else {
242
254
  console.log(`[morphix-env] Infisical CLI: no secrets found (run 'infisical login' first?)`);
243
255
  }
@@ -286,8 +298,8 @@ function generateClientEnv(outFile, filter) {
286
298
  );
287
299
  }
288
300
  const js = `window.__ENV=${JSON.stringify(vars)};`;
289
- (0, import_fs3.mkdirSync)((0, import_path3.dirname)(outFile), { recursive: true });
290
- (0, import_fs3.writeFileSync)(outFile, js);
301
+ (0, import_fs4.mkdirSync)((0, import_path4.dirname)(outFile), { recursive: true });
302
+ (0, import_fs4.writeFileSync)(outFile, js);
291
303
  console.log(`[morphix-env] Generated ${outFile} (${Object.keys(vars).length} client vars)`);
292
304
  }
293
305
  async function cmdGenerate(args, config) {
@@ -339,8 +351,9 @@ Usage:
339
351
  Options:
340
352
  -f, --env-file <path> Env file to load (default: .env.local, repeatable)
341
353
  -o, --out <path> Output path for generate (default: public/__env.js)
354
+ -e, --env <name> Infisical environment (dev/staging/prod), overrides config
342
355
  --filter <prefix> Only include vars with this prefix
343
- --no-infisical Skip Infisical SDK fetch
356
+ --no-infisical Skip Infisical fetch entirely
344
357
  -v, --verbose Show loaded variable names
345
358
  --help, -h Show this help
346
359
  --version Show version
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "morphix-env",
3
- "version": "0.3.0",
3
+ "version": "0.5.0",
4
4
  "description": "Environment variable toolkit — Infisical integration, local overrides, and client-side runtime injection for Next.js / Vite / Express.",
5
5
  "author": "MorphixAI <dev@morphixai.com>",
6
6
  "homepage": "https://github.com/Morphicai/morphix-env#readme",