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.
- package/README.md +163 -109
- package/dist/cli.js +47 -34
- 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
|
|
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
|
|
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
|
|
181
|
+
Extract public environment variables and write to a JS file for browser runtime injection.
|
|
68
182
|
|
|
69
183
|
```bash
|
|
70
|
-
#
|
|
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
|
|
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 `
|
|
211
|
+
Create `mx-env.config.json` in your project root. Committed to git.
|
|
124
212
|
|
|
125
213
|
```json
|
|
126
214
|
{
|
|
127
215
|
"infisical": {
|
|
128
|
-
"
|
|
129
|
-
"
|
|
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
|
-
|
|
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
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
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
|
-
```
|
|
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 --
|
|
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
|
-
```
|
|
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
|
-
|
|
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
|
-
```
|
|
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
|
-
|
|
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`
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
132
|
-
var
|
|
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,
|
|
142
|
-
if (!(0,
|
|
151
|
+
const configPath = (0, import_path3.resolve)(CONFIG_FILE);
|
|
152
|
+
if (!(0, import_fs3.existsSync)(configPath)) return {};
|
|
143
153
|
try {
|
|
144
|
-
|
|
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(`[
|
|
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
|
|
158
|
-
var
|
|
159
|
-
var VERSION = "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 =
|
|
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:
|
|
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,
|
|
290
|
-
(0,
|
|
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
|
|
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
|
+
"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",
|