@saasak/tool-env 1.3.0 → 1.4.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/bin/index.js CHANGED
@@ -16,10 +16,14 @@ import {
16
16
  load,
17
17
  } from "../src/core.js";
18
18
 
19
- const args = minimist(process.argv.slice(2), { "--": true });
19
+ const args = minimist(process.argv.slice(2), {
20
+ "--": true,
21
+ boolean: ["strict", "expose", "help", "h"],
22
+ });
20
23
  const __root = process.cwd();
21
24
 
22
- const command = args._[0] || "write";
25
+ let command = args._[0] || "help";
26
+ if (args.help || args.h) command = "help";
23
27
 
24
28
  const secret = resolveSecret(args.secret ? `file://${args.secret}` : '');
25
29
 
@@ -33,6 +37,15 @@ if (commandsRequiringEnvFile.includes(command) && !fs.existsSync(envFile)) {
33
37
  process.exit(1);
34
38
  }
35
39
 
40
+ if (args.strict && commandsRequiringEnvFile.includes(command)) {
41
+ const env = JSON.parse(fs.readFileSync(envFile, "utf8"));
42
+ const result = verifyCanDecrypt(env, secret);
43
+ if (!result.success) {
44
+ console.error(`Strict mode: ${result.error}`);
45
+ process.exit(1);
46
+ }
47
+ }
48
+
36
49
  async function showCommand() {
37
50
  if (!secret) {
38
51
  console.log(
@@ -295,7 +308,8 @@ async function runCommand() {
295
308
  targetEnv: args.target,
296
309
  envPath: args.env,
297
310
  applyToProcess: false,
298
- expose
311
+ expose,
312
+ strict: !!args.strict
299
313
  });
300
314
  } catch (error) {
301
315
  console.error(`wrenv: ${error.message}`);
@@ -322,7 +336,7 @@ async function runCommand() {
322
336
  function helpCommand() {
323
337
  console.log("Usage: wrenv [command] [options]\n");
324
338
  console.log("Commands:");
325
- console.log(" write Write .env files for all packages (default)");
339
+ console.log(" write Write .env files for all packages");
326
340
  console.log(
327
341
  " show Show environment variables without writing files",
328
342
  );
@@ -345,7 +359,10 @@ function helpCommand() {
345
359
  " --target <env> Target environment (dev, staging, prod, all)",
346
360
  );
347
361
  console.log(
348
- " --env <path> Path to env file (default: .env.json)\n",
362
+ " --env <path> Path to env file (default: .env.json)",
363
+ );
364
+ console.log(
365
+ " --strict Error if encrypted values cannot be decrypted\n",
349
366
  );
350
367
  console.log("Environment Variables:");
351
368
  console.log(" WRENV_SECRET Secret for encryption/decryption");
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@saasak/tool-env",
3
3
  "license": "MIT",
4
- "version": "1.3.0",
4
+ "version": "1.4.0",
5
5
  "author": "dev@saasak.studio",
6
6
  "description": "A small util to manage environment variables for your monorepo",
7
7
  "keywords": [
package/src/core.js CHANGED
@@ -17,6 +17,7 @@ import { findMonorepoPackages } from "./utils-pkg.js";
17
17
  * @property {string} [cwd] - Working directory (default: process.cwd())
18
18
  * @property {boolean} [applyToProcess] - Whether to apply to process.env (default: true)
19
19
  * @property {boolean} [expose] - wether to expose the secret or not
20
+ * @property {boolean} [strict] - Error if encrypted values cannot be decrypted
20
21
  */
21
22
 
22
23
  /**
@@ -26,6 +27,7 @@ import { findMonorepoPackages } from "./utils-pkg.js";
26
27
  * @property {string} [envPath] - Path to env.json file (default: '.env.json')
27
28
  * @property {string} [cwd] - Working directory (default: process.cwd())
28
29
  * @property {boolean} [expose] - wether to expose the secret or not
30
+ * @property {boolean} [strict] - Error if encrypted values cannot be decrypted
29
31
  */
30
32
 
31
33
  /**
@@ -290,7 +292,8 @@ export function loadEnvJson(options = {}) {
290
292
  secret: secretParam,
291
293
  envPath = ".env.json",
292
294
  cwd = process.cwd(),
293
- expose = false
295
+ expose = false,
296
+ strict = false
294
297
  } = options;
295
298
 
296
299
  const secret = resolveSecret(secretParam);
@@ -306,6 +309,13 @@ export function loadEnvJson(options = {}) {
306
309
  const envContent = fs.readFileSync(envFile, "utf8");
307
310
  const env = JSON.parse(envContent);
308
311
 
312
+ if (strict) {
313
+ const result = verifyCanDecrypt(env, secret);
314
+ if (!result.success) {
315
+ throw new Error(`Strict mode: ${result.error}`);
316
+ }
317
+ }
318
+
309
319
  const allowedEnvs =
310
320
  env && env.envs && Array.isArray(env.envs) ? env.envs : [DEFAULT_ENV];
311
321
  const resolvedTarget = allowedEnvs.find((e) => e === targetEnv);
@@ -378,7 +388,8 @@ export function load(options = {}) {
378
388
  envPath,
379
389
  cwd = process.cwd(),
380
390
  applyToProcess = true,
381
- expose = false
391
+ expose = false,
392
+ strict = false
382
393
  } = options;
383
394
 
384
395
  // Resolve target first to determine if we're in dev mode
@@ -390,7 +401,8 @@ export function load(options = {}) {
390
401
  targetEnv: resolvedTarget,
391
402
  envPath,
392
403
  cwd,
393
- expose
404
+ expose,
405
+ strict
394
406
  });
395
407
 
396
408
  // Load .env.local overrides only in dev mode (security: prevent local overrides in production)
@@ -446,10 +458,6 @@ export function verifyCanDecrypt(env, secret) {
446
458
  /** @type {EncryptedValueInfo[]} */
447
459
  const encryptedValues = [];
448
460
 
449
- if (!secret) {
450
- return { success: false, path: null, error: "No secret provided" };
451
- }
452
-
453
461
  // Collect all encrypted values from variables
454
462
  if (env.variables) {
455
463
  for (const [varName, varValue] of Object.entries(env.variables)) {
@@ -485,6 +493,10 @@ export function verifyCanDecrypt(env, secret) {
485
493
  return { success: true };
486
494
  }
487
495
 
496
+ if (!secret) {
497
+ return { success: false, path: null, error: "No secret provided" };
498
+ }
499
+
488
500
  // Try to decrypt each encrypted value
489
501
  for (const { path, value } of encryptedValues) {
490
502
  try {
package/src/index.d.ts CHANGED
@@ -12,6 +12,10 @@ export interface LoadOptions {
12
12
  cwd?: string;
13
13
  /** Whether to apply resolved vars to process.env (default: true) */
14
14
  applyToProcess?: boolean;
15
+ /** Whether to expose WRENV_TARGET and WRENV_SECRET in the output (default: false) */
16
+ expose?: boolean;
17
+ /** Error if encrypted values cannot be decrypted (default: false) */
18
+ strict?: boolean;
15
19
  }
16
20
 
17
21
  /**
@@ -28,6 +32,10 @@ export function loadEnvJson(options?: {
28
32
  targetEnv?: string;
29
33
  envPath?: string;
30
34
  cwd?: string;
35
+ /** Whether to expose WRENV_TARGET and WRENV_SECRET in the output (default: false) */
36
+ expose?: boolean;
37
+ /** Error if encrypted values cannot be decrypted (default: false) */
38
+ strict?: boolean;
31
39
  }): EnvRecord;
32
40
 
33
41
  /** Load .env.local overrides if the file exists */