@tltdh61/dotenvrtdb 1.260331.11828 → 1.260331.11957

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 (2) hide show
  1. package/cli.js +352 -154
  2. package/package.json +1 -1
package/cli.js CHANGED
@@ -15,6 +15,33 @@ const spawn = require("cross-spawn");
15
15
  const path = require("path");
16
16
  const fs = require("fs");
17
17
 
18
+ function formatErrorMessage(context = "unknown", err) {
19
+ if (!err) return `[${context}] Unknown error`;
20
+ const message = err && err.message ? err.message : String(err);
21
+ const code = err && err.code ? ` | code=${err.code}` : "";
22
+ const syscall = err && err.syscall ? ` | syscall=${err.syscall}` : "";
23
+ const filePath = err && err.path ? ` | path=${err.path}` : "";
24
+ const cause =
25
+ err && err.cause
26
+ ? ` | cause=${err.cause && err.cause.message ? err.cause.message : String(err.cause)}`
27
+ : "";
28
+ return `[${context}] ${message}${code}${syscall}${filePath}${cause}`;
29
+ }
30
+
31
+ function logSyncStatus(action = "sync", { status = "unknown", file = "-", varCount = 0, message = "" } = {}) {
32
+ const normalizedStatus = `${status || "unknown"}`.toUpperCase();
33
+ const safeAction = `${action || "sync"}`.toUpperCase();
34
+ const detail = message ? ` | reason=${message}` : "";
35
+ console.log(`[${safeAction}] status=${normalizedStatus} | file=${file || "-"} | vars=${Number.isFinite(varCount) ? varCount : 0}${detail}`);
36
+ }
37
+
38
+ function ensureParentDirExists(filePath = "") {
39
+ const target = `${filePath || ""}`.trim();
40
+ if (!target) return;
41
+ const absPath = path.resolve(target);
42
+ fs.mkdirSync(path.dirname(absPath), { recursive: true });
43
+ }
44
+
18
45
  const rtdbUtils = (() => {
19
46
  let rtdbUrl = ``;
20
47
 
@@ -52,6 +79,49 @@ const rtdbUtils = (() => {
52
79
  return resolved.trim();
53
80
  }
54
81
 
82
+ function parseFileValueDirective(value = "") {
83
+ if (typeof value !== "string") return null;
84
+ const v = value.trim();
85
+ if (!v) return null;
86
+
87
+ if (v.startsWith("file:raw:")) {
88
+ const filePath = v.slice("file:raw:".length).trim();
89
+ if (!filePath) return null;
90
+ return { type: "raw", filePath };
91
+ }
92
+ if (v.startsWith("file:base64:")) {
93
+ const filePath = v.slice("file:base64:".length).trim();
94
+ if (!filePath) return null;
95
+ return { type: "base64", filePath };
96
+ }
97
+ return null;
98
+ }
99
+
100
+ function resolveEnvFileDirectives(objVar = {}, options = {}) {
101
+ const baseDir = options && options.baseDir ? options.baseDir : process.cwd();
102
+ const next = { ...objVar };
103
+
104
+ for (const [key, val] of Object.entries(objVar || {})) {
105
+ const directive = parseFileValueDirective(val);
106
+ if (!directive) continue;
107
+
108
+ const fullPath = path.isAbsolute(directive.filePath) ? directive.filePath : path.resolve(baseDir, directive.filePath);
109
+ if (!fs.existsSync(fullPath)) {
110
+ throw new Error(`[directive] File not found for key "${key}": ${fullPath}`);
111
+ }
112
+
113
+ if (directive.type === "raw") {
114
+ next[key] = fs.readFileSync(fullPath, "utf8");
115
+ continue;
116
+ }
117
+ if (directive.type === "base64") {
118
+ next[key] = fs.readFileSync(fullPath).toString("base64");
119
+ }
120
+ }
121
+
122
+ return next;
123
+ }
124
+
55
125
  // --- pushTo ---
56
126
  const pushTo = async (objVar = {}) => {
57
127
  try {
@@ -82,7 +152,7 @@ const rtdbUtils = (() => {
82
152
  }
83
153
  return true;
84
154
  } catch (err) {
85
- console.error(`[rtdb] PATCH error: ${err && err.message ? err.message : err}`);
155
+ console.error(formatErrorMessage("rtdb PATCH error", err));
86
156
  return false;
87
157
  }
88
158
  };
@@ -93,18 +163,21 @@ const rtdbUtils = (() => {
93
163
  const p = `${envPath || ""}`.trim();
94
164
  if (!p) {
95
165
  console.error(`[rtdb] Missing -e <path> for --push`);
96
- return false;
166
+ return { ok: false, file: p || "-", varCount: 0 };
97
167
  }
98
168
  if (!fs.existsSync(p)) {
99
169
  console.error(`[rtdb] Env file not found: ${p}`);
100
- return false;
170
+ return { ok: false, file: p, varCount: 0 };
101
171
  }
102
172
  const content = fs.readFileSync(p, "utf8");
103
173
  const parsed = dotenv.parse(content); // {KEY:VAL}
104
- return await pushTo(parsed);
174
+ const resolvedVars = resolveEnvFileDirectives(parsed, { baseDir: path.dirname(path.resolve(p)) });
175
+ const varCount = Object.keys(resolvedVars || {}).length;
176
+ const ok = await pushTo(resolvedVars);
177
+ return { ok, file: p, varCount, reason: ok ? "" : "RTDB PATCH failed" };
105
178
  } catch (err) {
106
- console.error(`[rtdb] envPathPushTo error: ${err && err.message ? err.message : err}`);
107
- return false;
179
+ console.error(formatErrorMessage("rtdb envPathPushTo error", err));
180
+ return { ok: false, file: `${envPath || "-"} `.trim(), varCount: 0, reason: err && err.message ? err.message : String(err) };
108
181
  }
109
182
  };
110
183
 
@@ -125,7 +198,7 @@ const rtdbUtils = (() => {
125
198
  if (!data || typeof data !== "object" || Array.isArray(data)) return {};
126
199
  return data;
127
200
  } catch (err) {
128
- console.error(`[rtdb] GET error: ${err && err.message ? err.message : err}`);
201
+ console.error(formatErrorMessage("rtdb GET error", err));
129
202
  return {};
130
203
  }
131
204
  };
@@ -199,7 +272,7 @@ const rtdbUtils = (() => {
199
272
  }
200
273
  return { ok: true, value: `${parsed[key] ?? ""}` };
201
274
  } catch (err) {
202
- console.error(`[env] readEnvVarFromPath error: ${err && err.message ? err.message : err}`);
275
+ console.error(formatErrorMessage("env readEnvVarFromPath error", err));
203
276
  return { ok: false, value: "" };
204
277
  }
205
278
  }
@@ -226,7 +299,7 @@ const rtdbUtils = (() => {
226
299
  }
227
300
  return { ok: true, buffer };
228
301
  } catch (err) {
229
- console.error(`[env] decodeBase64ToBuffer error: ${err && err.message ? err.message : err}`);
302
+ console.error(formatErrorMessage("env decodeBase64ToBuffer error", err));
230
303
  return { ok: false, buffer: Buffer.alloc(0) };
231
304
  }
232
305
  }
@@ -304,6 +377,8 @@ const rtdbUtils = (() => {
304
377
  serializeEnv,
305
378
  readEnvVarFromPath,
306
379
  decodeBase64ToBuffer,
380
+ parseFileValueDirective,
381
+ resolveEnvFileDirectives,
307
382
  ensureEnvPathProvidedAndExists,
308
383
  normalizeLegacyArgs,
309
384
  getVietnamDateTime,
@@ -334,7 +409,9 @@ function printHelp() {
334
409
  ' also supports inline env: dotenvrtdb --shell -- FOO=bar "echo %FOO%"',
335
410
  " --writefileraw=<path> write raw value from --var=<name> in -e <path> env file to <path>",
336
411
  " --writefilebase64=<path> read --var=<name> from -e <path>, decode base64, then write binary to <path>",
337
- " --var=<name> env variable name used by --writefileraw/--writefilebase64",
412
+ " --var=<name> env variable name used by --writefileraw/--writefilebase64 (repeatable, mapped by order)",
413
+ " --varraw=<name> optional explicit variable for --writefileraw (repeatable, one-to-one with --writefileraw)",
414
+ " --varbase64=<name> optional explicit variable for --writefilebase64 (repeatable, one-to-one with --writefilebase64)",
338
415
  " -v <name>=<value> put variable <name> into environment using value <value>",
339
416
  " -v <name>=<value> multiple -v flags are allowed",
340
417
  " -p <variable> print value of <variable> to the console. If you specify this, you do not have to specify a `command`",
@@ -356,25 +433,26 @@ function validateCmdVariable(param) {
356
433
  }
357
434
 
358
435
  async function main() {
359
- if (argv.help) {
360
- printHelp();
361
- process.exit();
362
- }
436
+ try {
437
+ if (argv.help) {
438
+ printHelp();
439
+ process.exit();
440
+ }
363
441
 
364
- const override = argv.o || argv.override;
442
+ const override = argv.o || argv.override;
365
443
 
366
- // Handle quiet flag - default is true (quiet), can be disabled with --quiet=false or -q=false
367
- const isQuiet = !(argv.quiet === false || argv.q === false || argv.quiet === "false" || argv.q === "false");
444
+ // Handle quiet flag - default is true (quiet), can be disabled with --quiet=false or -q=false
445
+ const isQuiet = !(argv.quiet === false || argv.q === false || argv.quiet === "false" || argv.q === "false");
368
446
 
369
- if (argv.c && override) {
370
- console.error("Invalid arguments. Cascading env variables conflicts with overrides.");
371
- process.exit(1);
372
- }
447
+ if (argv.c && override) {
448
+ console.error("Invalid arguments. Cascading env variables conflicts with overrides.");
449
+ process.exit(1);
450
+ }
373
451
 
374
- // Setup RTDB URL if provided
375
- if (argv.eUrl) {
376
- rtdbUtils.setUrl(argv.eUrl);
377
- }
452
+ // Setup RTDB URL if provided
453
+ if (argv.eUrl) {
454
+ rtdbUtils.setUrl(argv.eUrl);
455
+ }
378
456
 
379
457
  const executePush = async () => {
380
458
  /**
@@ -383,13 +461,26 @@ async function main() {
383
461
  if (!argv.push) return false;
384
462
  if (!argv.eUrl) {
385
463
  console.error(`Missing --eUrl=<url>. This is required for --push.`);
464
+ logSyncStatus("push", { status: "failed", file: "-", varCount: 0, message: "missing --eUrl" });
386
465
  return true; // đã "xử lý" case push nhưng lỗi => vẫn kết thúc luồng
387
466
  }
388
467
  const { ok, envPath } = rtdbUtils.ensureEnvPathProvidedAndExists();
389
- if (!ok) return true;
468
+ if (!ok) {
469
+ logSyncStatus("push", { status: "failed", file: envPath || "-", varCount: 0, message: "missing/invalid -e path" });
470
+ return true;
471
+ }
390
472
 
391
- const okPush = await rtdbUtils.envPathPushTo(envPath);
392
- if (!okPush) process.exit(1);
473
+ const pushResult = await rtdbUtils.envPathPushTo(envPath);
474
+ if (!pushResult.ok) {
475
+ logSyncStatus("push", {
476
+ status: "failed",
477
+ file: pushResult.file || envPath,
478
+ varCount: pushResult.varCount || 0,
479
+ message: pushResult.reason || "unable to push env vars to RTDB",
480
+ });
481
+ process.exit(1);
482
+ }
483
+ logSyncStatus("push", { status: "success", file: pushResult.file || envPath, varCount: pushResult.varCount || 0 });
393
484
  return true;
394
485
  };
395
486
 
@@ -400,21 +491,47 @@ async function main() {
400
491
  if (!argv.pull) return false;
401
492
  if (!argv.eUrl) {
402
493
  console.error(`Missing --eUrl=<url>. This is required for --pull.`);
494
+ logSyncStatus("pull", { status: "failed", file: "-", varCount: 0, message: "missing --eUrl" });
403
495
  return true; // đã "xử lý" case pull nhưng lỗi => vẫn kết thúc luồng
404
496
  }
405
- const { ok, envPath } = rtdbUtils.ensureEnvPathProvidedAndExists();
406
- if (!ok) return true;
497
+ let envPath = "";
498
+ if (argv.e) {
499
+ envPath = typeof argv.e === "string" ? argv.e : argv.e[0];
500
+ }
501
+ envPath = `${envPath || ""}`.trim();
502
+ if (!envPath) {
503
+ logSyncStatus("pull", { status: "failed", file: "-", varCount: 0, message: "missing -e <path>" });
504
+ return true;
505
+ }
506
+ if (!fs.existsSync(envPath)) {
507
+ try {
508
+ const absPath = path.resolve(envPath);
509
+ fs.mkdirSync(path.dirname(absPath), { recursive: true });
510
+ fs.writeFileSync(absPath, "", "utf8");
511
+ } catch (err) {
512
+ logSyncStatus("pull", {
513
+ status: "failed",
514
+ file: envPath,
515
+ varCount: 0,
516
+ message: formatErrorMessage("pull create env file failed", err),
517
+ });
518
+ process.exit(1);
519
+ }
520
+ }
407
521
 
408
522
  const objVar = {
409
523
  ...rtdbUtils.getDefaultRtdbEnv(),
410
524
  ...(await rtdbUtils.pullFrom()),
411
525
  };
526
+ const pullVarCount = Object.keys(objVar || {}).length;
412
527
 
413
528
  try {
414
529
  const out = rtdbUtils.serializeEnv(objVar);
415
530
  fs.writeFileSync(envPath, out, "utf8");
531
+ logSyncStatus("pull", { status: "success", file: envPath, varCount: pullVarCount });
416
532
  } catch (err) {
417
533
  console.error(`[pull] write error: ${err && err.message ? err.message : err}`);
534
+ logSyncStatus("pull", { status: "failed", file: envPath, varCount: pullVarCount, message: "write file failed" });
418
535
  process.exit(1);
419
536
  }
420
537
  return true;
@@ -426,28 +543,54 @@ async function main() {
426
543
  */
427
544
  if (!argv.writefileraw) return false;
428
545
 
429
- const outPath = typeof argv.writefileraw === "string" ? argv.writefileraw.trim() : "";
430
- if (!outPath) {
546
+ const outPaths = (Array.isArray(argv.writefileraw) ? argv.writefileraw : [argv.writefileraw])
547
+ .map((v) => (typeof v === "string" ? v.trim() : ""))
548
+ .filter(Boolean);
549
+ if (outPaths.length === 0) {
431
550
  console.error(`Missing --writefileraw=<path>.`);
432
551
  return true;
433
552
  }
434
- const varName = typeof argv.var === "string" ? argv.var.trim() : "";
435
- if (!varName) {
436
- console.error(`Missing --var=<name>. This is required for --writefileraw.`);
553
+
554
+ const explicitRawVars = (Array.isArray(argv.varraw || argv.varRaw) ? argv.varraw || argv.varRaw : [argv.varraw || argv.varRaw])
555
+ .map((v) => (typeof v === "string" ? v.trim() : ""))
556
+ .filter(Boolean);
557
+
558
+ const varNames = [];
559
+ if (explicitRawVars.length > 0) {
560
+ if (explicitRawVars.length !== outPaths.length) {
561
+ console.error(`--varraw must have the same number of entries as --writefileraw.`);
562
+ return true;
563
+ }
564
+ varNames.push(...explicitRawVars);
565
+ } else {
566
+ for (let i = 0; i < outPaths.length; i++) {
567
+ const v = varPool[varCursor++] || "";
568
+ varNames.push(v.trim());
569
+ }
570
+ }
571
+
572
+ if (varNames.some((v) => !v)) {
573
+ console.error(`Missing --var=<name>. This is required for --writefileraw (one var per output path).`);
437
574
  return true;
438
575
  }
439
576
 
440
577
  const { ok, envPath } = rtdbUtils.ensureEnvPathProvidedAndExists();
441
578
  if (!ok) return true;
442
579
 
443
- const envVar = rtdbUtils.readEnvVarFromPath(envPath, varName);
444
- if (!envVar.ok) process.exit(1);
580
+ for (let i = 0; i < outPaths.length; i++) {
581
+ const outPath = outPaths[i];
582
+ const varName = varNames[i];
445
583
 
446
- try {
447
- fs.writeFileSync(outPath, envVar.value, "utf8");
448
- } catch (err) {
449
- console.error(`[writefileraw] write error: ${err && err.message ? err.message : err}`);
450
- process.exit(1);
584
+ const envVar = rtdbUtils.readEnvVarFromPath(envPath, varName);
585
+ if (!envVar.ok) process.exit(1);
586
+
587
+ try {
588
+ ensureParentDirExists(outPath);
589
+ fs.writeFileSync(outPath, envVar.value, "utf8");
590
+ } catch (err) {
591
+ console.error(`[writefileraw] write error: ${err && err.message ? err.message : err}`);
592
+ process.exit(1);
593
+ }
451
594
  }
452
595
  return true;
453
596
  };
@@ -458,74 +601,110 @@ async function main() {
458
601
  */
459
602
  if (!argv.writefilebase64) return false;
460
603
 
461
- const outPath = typeof argv.writefilebase64 === "string" ? argv.writefilebase64.trim() : "";
462
- if (!outPath) {
604
+ const outPaths = (Array.isArray(argv.writefilebase64) ? argv.writefilebase64 : [argv.writefilebase64])
605
+ .map((v) => (typeof v === "string" ? v.trim() : ""))
606
+ .filter(Boolean);
607
+ if (outPaths.length === 0) {
463
608
  console.error(`Missing --writefilebase64=<path>.`);
464
609
  return true;
465
610
  }
466
- const varName = typeof argv.var === "string" ? argv.var.trim() : "";
467
- if (!varName) {
468
- console.error(`Missing --var=<name>. This is required for --writefilebase64.`);
611
+
612
+ const explicitB64Vars = (Array.isArray(argv.varbase64 || argv.varBase64) ? argv.varbase64 || argv.varBase64 : [argv.varbase64 || argv.varBase64])
613
+ .map((v) => (typeof v === "string" ? v.trim() : ""))
614
+ .filter(Boolean);
615
+
616
+ const varNames = [];
617
+ if (explicitB64Vars.length > 0) {
618
+ if (explicitB64Vars.length !== outPaths.length) {
619
+ console.error(`--varbase64 must have the same number of entries as --writefilebase64.`);
620
+ return true;
621
+ }
622
+ varNames.push(...explicitB64Vars);
623
+ } else {
624
+ for (let i = 0; i < outPaths.length; i++) {
625
+ const v = varPool[varCursor++] || "";
626
+ varNames.push(v.trim());
627
+ }
628
+ }
629
+
630
+ if (varNames.some((v) => !v)) {
631
+ console.error(`Missing --var=<name>. This is required for --writefilebase64 (one var per output path).`);
469
632
  return true;
470
633
  }
471
634
 
472
635
  const { ok, envPath } = rtdbUtils.ensureEnvPathProvidedAndExists();
473
636
  if (!ok) return true;
474
637
 
475
- const envVar = rtdbUtils.readEnvVarFromPath(envPath, varName);
476
- if (!envVar.ok) process.exit(1);
638
+ for (let i = 0; i < outPaths.length; i++) {
639
+ const outPath = outPaths[i];
640
+ const varName = varNames[i];
477
641
 
478
- const decoded = rtdbUtils.decodeBase64ToBuffer(envVar.value);
479
- if (!decoded.ok) {
480
- console.error(`[writefilebase64] Invalid base64 content in variable: ${varName}`);
481
- process.exit(1);
482
- }
642
+ const envVar = rtdbUtils.readEnvVarFromPath(envPath, varName);
643
+ if (!envVar.ok) process.exit(1);
483
644
 
484
- try {
485
- fs.writeFileSync(outPath, decoded.buffer);
486
- } catch (err) {
487
- console.error(`[writefilebase64] write error: ${err && err.message ? err.message : err}`);
488
- process.exit(1);
645
+ const decoded = rtdbUtils.decodeBase64ToBuffer(envVar.value);
646
+ if (!decoded.ok) {
647
+ console.error(`[writefilebase64] Invalid base64 content in variable: ${varName}`);
648
+ process.exit(1);
649
+ }
650
+
651
+ try {
652
+ ensureParentDirExists(outPath);
653
+ fs.writeFileSync(outPath, decoded.buffer);
654
+ } catch (err) {
655
+ console.error(`[writefilebase64] write error: ${err && err.message ? err.message : err}`);
656
+ process.exit(1);
657
+ }
489
658
  }
490
659
  return true;
491
660
  };
492
661
 
493
- const didPush = await executePush();
494
- const didPull = await executePull();
495
- const didWriteFileRaw = await executeWriteFileRaw();
496
- const didWriteFileBase64 = await executeWriteFileBase64();
497
- if (didPush === true || didPull === true || didWriteFileRaw === true || didWriteFileBase64 === true) {
498
- // Push/Pull/WriteFile là mode riêng, chạy xong thoát
499
- process.exit(0);
500
- }
662
+ const varPool = (Array.isArray(argv.var) ? argv.var : [argv.var])
663
+ .map((v) => (typeof v === "string" ? v.trim() : ""))
664
+ .filter(Boolean);
665
+ let varCursor = 0;
501
666
 
502
- let paths = [];
503
- if (argv.e) {
504
- if (typeof argv.e === "string") {
505
- paths.push(argv.e);
506
- } else {
507
- paths.push(...argv.e);
667
+ const didPush = await executePush();
668
+ if (didPush === true) {
669
+ // push mode riêng
670
+ process.exit(0);
508
671
  }
509
- } else {
510
- paths.push(".env");
511
- }
512
672
 
513
- if (argv.c) {
514
- paths = paths.reduce(
515
- (accumulator, p) =>
516
- accumulator.concat(typeof argv.c === "string" ? [`${p}.${argv.c}.local`, `${p}.local`, `${p}.${argv.c}`, p] : [`${p}.local`, p]),
517
- [],
518
- );
519
- }
673
+ const didPull = await executePull();
674
+ const didWriteFileRaw = await executeWriteFileRaw();
675
+ const didWriteFileBase64 = await executeWriteFileBase64();
676
+ if (didPull === true || didWriteFileRaw === true || didWriteFileBase64 === true) {
677
+ // pull/writefile là mode riêng; cho phép kết hợp pull + writefile trong cùng một lệnh.
678
+ process.exit(0);
679
+ }
520
680
 
521
- const variables = [];
522
- if (argv.v) {
523
- if (typeof argv.v === "string") {
524
- variables.push(validateCmdVariable(argv.v));
681
+ let paths = [];
682
+ if (argv.e) {
683
+ if (typeof argv.e === "string") {
684
+ paths.push(argv.e);
685
+ } else {
686
+ paths.push(...argv.e);
687
+ }
525
688
  } else {
526
- variables.push(...argv.v.map(validateCmdVariable));
689
+ paths.push(".env");
690
+ }
691
+
692
+ if (argv.c) {
693
+ paths = paths.reduce(
694
+ (accumulator, p) =>
695
+ accumulator.concat(typeof argv.c === "string" ? [`${p}.${argv.c}.local`, `${p}.local`, `${p}.${argv.c}`, p] : [`${p}.local`, p]),
696
+ [],
697
+ );
698
+ }
699
+
700
+ const variables = [];
701
+ if (argv.v) {
702
+ if (typeof argv.v === "string") {
703
+ variables.push(validateCmdVariable(argv.v));
704
+ } else {
705
+ variables.push(...argv.v.map(validateCmdVariable));
706
+ }
527
707
  }
528
- }
529
708
 
530
709
  const parseUrlToArgV = async () => {
531
710
  /**
@@ -553,42 +732,52 @@ async function main() {
553
732
  }
554
733
  };
555
734
 
556
- await parseUrlToArgV();
735
+ await parseUrlToArgV();
557
736
 
558
737
  // Merge default env với variables (variables sẽ override default)
559
- const defaultEnv = rtdbUtils.getDefaultRtdbEnv() || {};
560
- const parsedVariables = {
561
- ...defaultEnv,
562
- ...Object.fromEntries(variables),
563
- };
738
+ const defaultEnv = rtdbUtils.getDefaultRtdbEnv() || {};
739
+ const parsedVariables = {
740
+ ...defaultEnv,
741
+ ...Object.fromEntries(variables),
742
+ };
564
743
 
565
- if (argv.debug) {
566
- console.log(paths);
567
- console.log(parsedVariables);
568
- process.exit();
569
- }
744
+ if (argv.debug) {
745
+ console.log(paths);
746
+ console.log(parsedVariables);
747
+ process.exit();
748
+ }
570
749
 
571
- paths.forEach(function (env) {
572
- dotenv.config({ path: path.resolve(env), override, quiet: isQuiet });
573
- });
750
+ paths.forEach(function (env) {
751
+ try {
752
+ dotenv.config({ path: path.resolve(env), override, quiet: isQuiet });
753
+ } catch (err) {
754
+ console.error(formatErrorMessage(`dotenv config failed for ${env}`, err));
755
+ process.exit(1);
756
+ }
757
+ });
574
758
 
575
759
  // Expand when all path configs are loaded
576
- if (argv.expand !== false) {
577
- dotenvExpand({
578
- parsed: process.env,
579
- });
580
- }
760
+ if (argv.expand !== false) {
761
+ try {
762
+ dotenvExpand({
763
+ parsed: process.env,
764
+ });
765
+ } catch (err) {
766
+ console.error(formatErrorMessage("dotenv expand failed", err));
767
+ process.exit(1);
768
+ }
769
+ }
581
770
 
582
- Object.assign(process.env, parsedVariables);
771
+ Object.assign(process.env, parsedVariables);
583
772
 
584
- if (argv.p) {
585
- let value = process.env[argv.p];
586
- if (typeof value === "string") {
587
- value = `${value}`;
773
+ if (argv.p) {
774
+ let value = process.env[argv.p];
775
+ if (typeof value === "string") {
776
+ value = `${value}`;
777
+ }
778
+ console.log(value != null ? value : "");
779
+ process.exit();
588
780
  }
589
- console.log(value != null ? value : "");
590
- process.exit();
591
- }
592
781
 
593
782
  // cross-env-shell style: allow `KEY=VALUE` at the beginning of the command section (after `--`)
594
783
  function parseLeadingEnvAssignments(args = []) {
@@ -608,59 +797,68 @@ async function main() {
608
797
  return { env, rest: args.slice(i) };
609
798
  }
610
799
 
611
- const shellOptRaw = argv.shell;
612
- let shellOpt = shellOptRaw;
613
- if (typeof shellOptRaw === "string") {
614
- const t = shellOptRaw.trim().toLowerCase();
615
- if (t === "true" || t === "1" || t === "yes") shellOpt = true;
616
- else if (t === "false" || t === "0" || t === "no") shellOpt = false;
617
- else shellOpt = shellOptRaw.trim();
618
- }
800
+ const shellOptRaw = argv.shell;
801
+ let shellOpt = shellOptRaw;
802
+ if (typeof shellOptRaw === "string") {
803
+ const t = shellOptRaw.trim().toLowerCase();
804
+ if (t === "true" || t === "1" || t === "yes") shellOpt = true;
805
+ else if (t === "false" || t === "0" || t === "no") shellOpt = false;
806
+ else shellOpt = shellOptRaw.trim();
807
+ }
619
808
 
620
- const runInShell = shellOpt === true || (typeof shellOpt === "string" && shellOpt !== "");
621
- const { env: inlineEnv, rest: cmdArgs } = runInShell ? parseLeadingEnvAssignments(argv._) : { env: {}, rest: argv._ };
809
+ const runInShell = shellOpt === true || (typeof shellOpt === "string" && shellOpt !== "");
810
+ const { env: inlineEnv, rest: cmdArgs } = runInShell ? parseLeadingEnvAssignments(argv._) : { env: {}, rest: argv._ };
622
811
 
623
- if (cmdArgs.length === 0) {
624
- printHelp();
625
- process.exit(1);
626
- }
812
+ if (cmdArgs.length === 0) {
813
+ printHelp();
814
+ process.exit(1);
815
+ }
627
816
 
628
- const childEnv = Object.keys(inlineEnv).length ? Object.assign({}, process.env, inlineEnv) : process.env;
817
+ const childEnv = Object.keys(inlineEnv).length ? Object.assign({}, process.env, inlineEnv) : process.env;
629
818
 
630
- const spawnOpts = {
631
- stdio: "inherit",
632
- env: childEnv,
633
- };
819
+ const spawnOpts = {
820
+ stdio: "inherit",
821
+ env: childEnv,
822
+ };
634
823
 
635
824
  // If --shell is provided:
636
825
  // - boolean true => use platform default shell
637
826
  // - string => pass through to node spawn `shell` option (advanced)
638
- let child;
639
- if (runInShell) {
640
- const shellCommand = cmdArgs.length === 1 ? cmdArgs[0] : cmdArgs.join(" ");
641
- const shellVal = typeof shellOpt === "string" ? shellOpt : true;
642
- child = spawn(shellCommand, [], Object.assign({}, spawnOpts, { shell: shellVal }));
643
- } else {
644
- const command = cmdArgs[0];
645
- child = spawn(command, cmdArgs.slice(1), spawnOpts);
646
- }
647
-
648
- child.on("exit", function (exitCode, signal) {
649
- if (typeof exitCode === "number") {
650
- process.exit(exitCode);
827
+ let child;
828
+ if (runInShell) {
829
+ const shellCommand = cmdArgs.length === 1 ? cmdArgs[0] : cmdArgs.join(" ");
830
+ const shellVal = typeof shellOpt === "string" ? shellOpt : true;
831
+ child = spawn(shellCommand, [], Object.assign({}, spawnOpts, { shell: shellVal }));
651
832
  } else {
652
- process.kill(process.pid, signal);
833
+ const command = cmdArgs[0];
834
+ child = spawn(command, cmdArgs.slice(1), spawnOpts);
653
835
  }
654
- });
655
836
 
656
- for (const signal of ["SIGINT", "SIGTERM", "SIGPIPE", "SIGHUP", "SIGBREAK", "SIGWINCH", "SIGUSR1", "SIGUSR2"]) {
657
- process.on(signal, function () {
658
- child.kill(signal);
837
+ child.on("error", function (err) {
838
+ console.error(formatErrorMessage("spawn process error", err));
839
+ process.exit(1);
659
840
  });
841
+
842
+ child.on("exit", function (exitCode, signal) {
843
+ if (typeof exitCode === "number") {
844
+ process.exit(exitCode);
845
+ } else {
846
+ process.kill(process.pid, signal);
847
+ }
848
+ });
849
+
850
+ for (const signal of ["SIGINT", "SIGTERM", "SIGPIPE", "SIGHUP", "SIGBREAK", "SIGWINCH", "SIGUSR1", "SIGUSR2"]) {
851
+ process.on(signal, function () {
852
+ child.kill(signal);
853
+ });
854
+ }
855
+ } catch (err) {
856
+ console.error(formatErrorMessage("main error", err));
857
+ process.exit(1);
660
858
  }
661
859
  }
662
860
 
663
861
  main().catch((err) => {
664
- console.error(err && err.message ? err.message : err);
862
+ console.error(formatErrorMessage("fatal error", err));
665
863
  process.exit(1);
666
864
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tltdh61/dotenvrtdb",
3
- "version": "1.260331.11828",
3
+ "version": "1.260331.11957",
4
4
  "description": "A CLI tool to load environment variables from .env files with remote database support",
5
5
  "main": "cli.js",
6
6
  "bin": {