@tolgamorf/env2op-cli 0.2.0 → 0.2.2

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
@@ -1,4 +1,4 @@
1
- # env2op
1
+ # env2op & op2env
2
2
 
3
3
  Push `.env` files to 1Password and pull them back with two simple commands.
4
4
 
@@ -19,7 +19,9 @@ Or in a single command:
19
19
  brew install tolgamorf/tap/env2op-cli
20
20
  ```
21
21
 
22
- ### npm / bun
22
+ ### Package Managers (macOS/Linux/Windows)
23
+
24
+ #### Global installation
23
25
 
24
26
  ```bash
25
27
  # Using bun
@@ -28,10 +30,24 @@ bun add -g @tolgamorf/env2op-cli
28
30
  # Using npm
29
31
  npm install -g @tolgamorf/env2op-cli
30
32
 
31
- # Or run directly with bunx/npx
33
+ # Using pnpm
34
+ pnpm add -g @tolgamorf/env2op-cli
35
+ ```
36
+
37
+ #### Running directly
38
+
39
+ ```bash
40
+ # Using bun
32
41
  bunx @tolgamorf/env2op-cli .env Personal "MyApp"
42
+
43
+ # Using npm
44
+ npx @tolgamorf/env2op-cli .env Personal "MyApp"
45
+
46
+ # Using pnpm
47
+ pnpm dlx @tolgamorf/env2op-cli .env Personal "MyApp"
33
48
  ```
34
49
 
50
+
35
51
  ## Prerequisites
36
52
 
37
53
  - [1Password CLI](https://1password.com/downloads/command-line/) installed and signed in
@@ -81,8 +97,10 @@ env2op .env.production Personal "MyApp" -f
81
97
  | `-f, --force` | Skip confirmation prompts |
82
98
  | `--dry-run` | Preview actions without executing |
83
99
  | `--secret` | Store all fields as 'password' type (default: 'text') |
84
- | `-h, --help` | Show help |
100
+ | `--verbose` | Show op CLI output |
101
+ | `--update` | Check for and install updates |
85
102
  | `-v, --version` | Show version |
103
+ | `-h, --help` | Show help |
86
104
 
87
105
  ## op2env (Pull)
88
106
 
@@ -115,8 +133,10 @@ op2env .env.tpl -f
115
133
  | `-o, --output` | Output .env path (default: template without `.tpl`) |
116
134
  | `-f, --force` | Overwrite without prompting |
117
135
  | `--dry-run` | Preview actions without executing |
118
- | `-h, --help` | Show help |
136
+ | `--verbose` | Show op CLI output |
137
+ | `--update` | Check for and install updates |
119
138
  | `-v, --version` | Show version |
139
+ | `-h, --help` | Show help |
120
140
 
121
141
  ## How It Works
122
142
 
package/dist/cli.js CHANGED
@@ -22,7 +22,7 @@ var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports,
22
22
  var require_package = __commonJS((exports, module) => {
23
23
  module.exports = {
24
24
  name: "@tolgamorf/env2op-cli",
25
- version: "0.2.0",
25
+ version: "0.2.2",
26
26
  description: "Convert .env files to 1Password Secure Notes and generate templates for op inject/run",
27
27
  type: "module",
28
28
  main: "dist/index.js",
@@ -102,15 +102,14 @@ var require_package = __commonJS((exports, module) => {
102
102
  });
103
103
 
104
104
  // src/cli.ts
105
- import pc3 from "picocolors";
105
+ import pc5 from "picocolors";
106
106
 
107
107
  // src/commands/convert.ts
108
108
  import { basename, dirname, join } from "node:path";
109
- import { setTimeout } from "node:timers/promises";
110
109
  import * as p2 from "@clack/prompts";
111
110
 
112
111
  // src/core/env-parser.ts
113
- import { existsSync, readFileSync } from "node:fs";
112
+ import { readFile } from "node:fs/promises";
114
113
 
115
114
  // src/utils/errors.ts
116
115
  class Env2OpError extends Error {
@@ -133,6 +132,7 @@ var ErrorCodes = {
133
132
  VAULT_CREATE_FAILED: "VAULT_CREATE_FAILED",
134
133
  ITEM_EXISTS: "ITEM_EXISTS",
135
134
  ITEM_CREATE_FAILED: "ITEM_CREATE_FAILED",
135
+ ITEM_EDIT_FAILED: "ITEM_EDIT_FAILED",
136
136
  PARSE_ERROR: "PARSE_ERROR",
137
137
  TEMPLATE_NOT_FOUND: "TEMPLATE_NOT_FOUND",
138
138
  INJECT_FAILED: "INJECT_FAILED"
@@ -146,6 +146,7 @@ var errors = {
146
146
  vaultCreateFailed: (message) => new Env2OpError(`Failed to create vault: ${message}`, ErrorCodes.VAULT_CREATE_FAILED),
147
147
  itemExists: (title, vault) => new Env2OpError(`Item "${title}" already exists in vault "${vault}"`, ErrorCodes.ITEM_EXISTS, "Use default behavior (overwrites) or choose a different item name"),
148
148
  itemCreateFailed: (message) => new Env2OpError(`Failed to create 1Password item: ${message}`, ErrorCodes.ITEM_CREATE_FAILED),
149
+ itemEditFailed: (message) => new Env2OpError(`Failed to edit 1Password item: ${message}`, ErrorCodes.ITEM_EDIT_FAILED),
149
150
  parseError: (line, message) => new Env2OpError(`Parse error at line ${line}: ${message}`, ErrorCodes.PARSE_ERROR)
150
151
  };
151
152
 
@@ -193,12 +194,20 @@ function parseValue(raw) {
193
194
  const parts = trimmed.split(/\s+#/);
194
195
  return (parts[0] ?? trimmed).trim();
195
196
  }
196
- function parseEnvFile(filePath) {
197
- if (!existsSync(filePath)) {
197
+ function stripBom(content) {
198
+ if (content.charCodeAt(0) === 65279) {
199
+ return content.slice(1);
200
+ }
201
+ return content;
202
+ }
203
+ async function parseEnvFile(filePath) {
204
+ let rawContent;
205
+ try {
206
+ rawContent = await readFile(filePath, "utf-8");
207
+ } catch {
198
208
  throw errors.envFileNotFound(filePath);
199
209
  }
200
- const rawContent = readFileSync(filePath, "utf-8");
201
- const content = stripHeaders(rawContent);
210
+ const content = stripHeaders(stripBom(rawContent));
202
211
  const rawLines = content.split(`
203
212
  `);
204
213
  const variables = [];
@@ -263,33 +272,34 @@ async function exec(command, args = [], options = {}) {
263
272
  const proc = spawn(command, args, {
264
273
  stdio: ["ignore", "pipe", "pipe"]
265
274
  });
266
- let stdout = "";
267
- let stderr = "";
275
+ const stdoutChunks = [];
276
+ const stderrChunks = [];
268
277
  proc.stdout?.on("data", (data) => {
269
- const text = data.toString();
270
- stdout += text;
278
+ const text = Buffer.isBuffer(data) ? data.toString() : String(data);
279
+ stdoutChunks.push(text);
271
280
  if (verbose) {
272
281
  process.stdout.write(text);
273
282
  }
274
283
  });
275
284
  proc.stderr?.on("data", (data) => {
276
- const text = data.toString();
277
- stderr += text;
285
+ const text = Buffer.isBuffer(data) ? data.toString() : String(data);
286
+ stderrChunks.push(text);
278
287
  if (verbose) {
279
288
  process.stderr.write(text);
280
289
  }
281
290
  });
282
291
  proc.on("close", (code) => {
283
292
  resolve({
284
- stdout,
285
- stderr,
286
- exitCode: code ?? 0
293
+ stdout: stdoutChunks.join(""),
294
+ stderr: stderrChunks.join(""),
295
+ exitCode: code ?? 1
287
296
  });
288
297
  });
289
- proc.on("error", () => {
298
+ proc.on("error", (err) => {
299
+ stderrChunks.push(err.message);
290
300
  resolve({
291
- stdout,
292
- stderr,
301
+ stdout: stdoutChunks.join(""),
302
+ stderr: stderrChunks.join(""),
293
303
  exitCode: 1
294
304
  });
295
305
  });
@@ -305,27 +315,36 @@ async function execWithStdin(command, args = [], options) {
305
315
  const proc = spawn(command, args, {
306
316
  stdio: ["pipe", "pipe", "pipe"]
307
317
  });
308
- let stdout = "";
309
- let stderr = "";
318
+ const stdoutChunks = [];
319
+ const stderrChunks = [];
310
320
  proc.stdin?.write(stdinContent);
311
321
  proc.stdin?.end();
312
322
  proc.stdout?.on("data", (data) => {
313
- const text = data.toString();
314
- stdout += text;
323
+ const text = Buffer.isBuffer(data) ? data.toString() : String(data);
324
+ stdoutChunks.push(text);
315
325
  if (verbose)
316
326
  process.stdout.write(text);
317
327
  });
318
328
  proc.stderr?.on("data", (data) => {
319
- const text = data.toString();
320
- stderr += text;
329
+ const text = Buffer.isBuffer(data) ? data.toString() : String(data);
330
+ stderrChunks.push(text);
321
331
  if (verbose)
322
332
  process.stderr.write(text);
323
333
  });
324
334
  proc.on("close", (code) => {
325
- resolve({ stdout, stderr, exitCode: code ?? 0 });
335
+ resolve({
336
+ stdout: stdoutChunks.join(""),
337
+ stderr: stderrChunks.join(""),
338
+ exitCode: code ?? 1
339
+ });
326
340
  });
327
- proc.on("error", () => {
328
- resolve({ stdout, stderr, exitCode: 1 });
341
+ proc.on("error", (err) => {
342
+ stderrChunks.push(err.message);
343
+ resolve({
344
+ stdout: stdoutChunks.join(""),
345
+ stderr: stderrChunks.join(""),
346
+ exitCode: 1
347
+ });
329
348
  });
330
349
  });
331
350
  }
@@ -445,7 +464,7 @@ async function editSecureNote(options) {
445
464
  };
446
465
  } catch (error) {
447
466
  const message = error instanceof Error ? error.message : String(error);
448
- throw errors.itemCreateFailed(message);
467
+ throw errors.itemEditFailed(message);
449
468
  }
450
469
  }
451
470
 
@@ -606,18 +625,21 @@ ${pc2.bold(pc2.underline(title))}`);
606
625
  }
607
626
  };
608
627
 
609
- // src/commands/convert.ts
628
+ // src/utils/timing.ts
629
+ import { setTimeout } from "node:timers/promises";
610
630
  var MIN_SPINNER_TIME = 500;
611
631
  async function withMinTime(promise, minTime = MIN_SPINNER_TIME) {
612
632
  const [result] = await Promise.all([promise, setTimeout(minTime)]);
613
633
  return result;
614
634
  }
635
+
636
+ // src/commands/convert.ts
615
637
  async function runConvert(options) {
616
638
  const { envFile, vault, itemName, output, dryRun, secret, force, verbose } = options;
617
639
  const pkg2 = await Promise.resolve().then(() => __toESM(require_package(), 1));
618
640
  logger.intro("env2op", pkg2.version, dryRun);
619
641
  try {
620
- const parseResult = parseEnvFile(envFile);
642
+ const parseResult = await parseEnvFile(envFile);
621
643
  validateParseResult(parseResult, envFile);
622
644
  const { variables, lines } = parseResult;
623
645
  const varCount = variables.length;
@@ -728,7 +750,7 @@ async function runConvert(options) {
728
750
  }
729
751
  pushSpinner.stop(existingItemId ? `Updated "${itemResult.title}" in vault "${itemResult.vault}"` : `Created "${itemResult.title}" in vault "${itemResult.vault}"`);
730
752
  } catch (error) {
731
- pushSpinner.stop(existingItemId ? "Failed to update Secure Note" : "Failed to create Secure Note");
753
+ pushSpinner.stop();
732
754
  throw error;
733
755
  }
734
756
  }
@@ -766,6 +788,274 @@ async function runConvert(options) {
766
788
  }
767
789
  }
768
790
 
791
+ // src/commands/update.ts
792
+ import * as p4 from "@clack/prompts";
793
+ import pc4 from "picocolors";
794
+
795
+ // src/lib/package-manager.ts
796
+ var UPDATE_COMMANDS = {
797
+ homebrew: "brew upgrade tolgamorf/tap/env2op-cli",
798
+ npm: "npm update -g @tolgamorf/env2op-cli",
799
+ bun: "bun update -g @tolgamorf/env2op-cli",
800
+ pnpm: "pnpm update -g @tolgamorf/env2op-cli",
801
+ unknown: "npm update -g @tolgamorf/env2op-cli"
802
+ };
803
+ var DISPLAY_NAMES = {
804
+ homebrew: "Homebrew",
805
+ npm: "npm",
806
+ bun: "Bun",
807
+ pnpm: "pnpm",
808
+ unknown: "npm (default)"
809
+ };
810
+ function detectFromPath() {
811
+ const binPath = process.argv[1] ?? "";
812
+ if (binPath.includes("/Cellar/") || binPath.includes("/homebrew/") || binPath.includes("/opt/homebrew/") || binPath.includes("/home/linuxbrew/")) {
813
+ return "homebrew";
814
+ }
815
+ if (binPath.includes("/.bun/")) {
816
+ return "bun";
817
+ }
818
+ if (binPath.includes("/pnpm/") || binPath.includes("/.pnpm/")) {
819
+ return "pnpm";
820
+ }
821
+ if (binPath.includes("/node_modules/")) {
822
+ return "npm";
823
+ }
824
+ return null;
825
+ }
826
+ async function detectFromCommands() {
827
+ const brewResult = await exec("brew", ["list", "env2op-cli"], { verbose: false });
828
+ if (brewResult.exitCode === 0) {
829
+ return "homebrew";
830
+ }
831
+ return "npm";
832
+ }
833
+ async function detectPackageManager() {
834
+ const fromPath = detectFromPath();
835
+ if (fromPath) {
836
+ return {
837
+ type: fromPath,
838
+ updateCommand: UPDATE_COMMANDS[fromPath],
839
+ displayName: DISPLAY_NAMES[fromPath]
840
+ };
841
+ }
842
+ const fromCommands = await detectFromCommands();
843
+ return {
844
+ type: fromCommands,
845
+ updateCommand: UPDATE_COMMANDS[fromCommands],
846
+ displayName: DISPLAY_NAMES[fromCommands]
847
+ };
848
+ }
849
+
850
+ // src/lib/update.ts
851
+ import { existsSync, mkdirSync, readFileSync, unlinkSync, writeFileSync as writeFileSync2 } from "node:fs";
852
+ import { homedir } from "node:os";
853
+ import { join as join2 } from "node:path";
854
+ var CACHE_DIR = join2(homedir(), ".env2op");
855
+ var CACHE_FILE = join2(CACHE_DIR, "update-check.json");
856
+ var CHECK_INTERVAL_MS = 24 * 60 * 60 * 1000;
857
+ function getCliVersion() {
858
+ try {
859
+ const pkg2 = require_package();
860
+ return pkg2.version ?? "0.0.0";
861
+ } catch {
862
+ return "0.0.0";
863
+ }
864
+ }
865
+ function loadCache() {
866
+ try {
867
+ if (existsSync(CACHE_FILE)) {
868
+ const content = readFileSync(CACHE_FILE, "utf-8");
869
+ return JSON.parse(content);
870
+ }
871
+ } catch {}
872
+ return { lastCheck: 0, latestVersion: null };
873
+ }
874
+ function saveCache(cache) {
875
+ try {
876
+ if (!existsSync(CACHE_DIR)) {
877
+ mkdirSync(CACHE_DIR, { recursive: true });
878
+ }
879
+ writeFileSync2(CACHE_FILE, JSON.stringify(cache, null, 2));
880
+ } catch {}
881
+ }
882
+ function shouldCheckForUpdate(cache) {
883
+ const now = Date.now();
884
+ return now - cache.lastCheck > CHECK_INTERVAL_MS;
885
+ }
886
+ async function fetchLatestVersion() {
887
+ try {
888
+ const response = await fetch("https://registry.npmjs.org/@tolgamorf/env2op-cli/latest");
889
+ if (!response.ok)
890
+ return null;
891
+ const data = await response.json();
892
+ return data.version ?? null;
893
+ } catch {
894
+ return null;
895
+ }
896
+ }
897
+ function compareVersions(v1, v2) {
898
+ const parts1 = v1.split(".").map(Number);
899
+ const parts2 = v2.split(".").map(Number);
900
+ for (let i = 0;i < 3; i++) {
901
+ const p1 = parts1[i] || 0;
902
+ const p22 = parts2[i] || 0;
903
+ if (p1 < p22)
904
+ return -1;
905
+ if (p1 > p22)
906
+ return 1;
907
+ }
908
+ return 0;
909
+ }
910
+ async function checkForUpdate(forceCheck = false) {
911
+ const currentVersion = getCliVersion();
912
+ const cache = loadCache();
913
+ if (!forceCheck && !shouldCheckForUpdate(cache) && cache.latestVersion) {
914
+ const updateAvailable2 = compareVersions(currentVersion, cache.latestVersion) < 0;
915
+ const isSkipped2 = cache.skipVersion === cache.latestVersion;
916
+ return {
917
+ currentVersion,
918
+ latestVersion: cache.latestVersion,
919
+ updateAvailable: updateAvailable2,
920
+ isSkipped: isSkipped2,
921
+ fromCache: true
922
+ };
923
+ }
924
+ const latestVersion = await fetchLatestVersion();
925
+ saveCache({
926
+ ...cache,
927
+ lastCheck: Date.now(),
928
+ latestVersion
929
+ });
930
+ if (!latestVersion) {
931
+ return {
932
+ currentVersion,
933
+ latestVersion: null,
934
+ updateAvailable: false,
935
+ isSkipped: false,
936
+ fromCache: false
937
+ };
938
+ }
939
+ const updateAvailable = compareVersions(currentVersion, latestVersion) < 0;
940
+ const isSkipped = cache.skipVersion === latestVersion;
941
+ return {
942
+ currentVersion,
943
+ latestVersion,
944
+ updateAvailable,
945
+ isSkipped,
946
+ fromCache: false
947
+ };
948
+ }
949
+ async function performUpdate(pm) {
950
+ const packageManager = pm ?? await detectPackageManager();
951
+ try {
952
+ const [command, ...args] = packageManager.updateCommand.split(" ");
953
+ const result = await exec(command, args, { verbose: false });
954
+ if (result.exitCode !== 0) {
955
+ return {
956
+ success: false,
957
+ error: result.stderr || `Command exited with code ${result.exitCode}`
958
+ };
959
+ }
960
+ return { success: true };
961
+ } catch (error) {
962
+ const message = error instanceof Error ? error.message : String(error);
963
+ return { success: false, error: message };
964
+ }
965
+ }
966
+ function skipVersion(version) {
967
+ const cache = loadCache();
968
+ cache.skipVersion = version;
969
+ saveCache(cache);
970
+ }
971
+
972
+ // src/lib/update-prompts.ts
973
+ import * as p3 from "@clack/prompts";
974
+ import pc3 from "picocolors";
975
+ var S_BAR_START = "┌";
976
+ var S_BAR_END = "└";
977
+ function showUpdateNotification(result, cliName = "env2op") {
978
+ console.log();
979
+ console.log(`${pc3.gray(S_BAR_START)}${pc3.gray("─")} ${pc3.yellow("Update available:")} ${pc3.dim(result.currentVersion)} ${pc3.dim("→")} ${pc3.green(result.latestVersion)}`);
980
+ console.log(`${pc3.gray(S_BAR_END)}${pc3.gray("─")} Run ${pc3.cyan(`'${cliName} update'`)} to update`);
981
+ }
982
+ async function askToUpdate(result) {
983
+ const response = await p3.select({
984
+ message: "Would you like to update?",
985
+ options: [
986
+ { value: "update", label: "Update now", hint: "Download and install the latest version" },
987
+ { value: "later", label: "Remind me later", hint: "Ask again next time" },
988
+ { value: "skip", label: "Skip this version", hint: `Don't ask about ${result.latestVersion} again` }
989
+ ]
990
+ });
991
+ if (p3.isCancel(response)) {
992
+ return "later";
993
+ }
994
+ return response;
995
+ }
996
+ function showUpdateAvailable(result) {
997
+ p3.log.success(`Update available: ${pc3.dim(result.currentVersion)} ${pc3.dim("→")} ${pc3.green(result.latestVersion)}`);
998
+ }
999
+ function showUpToDate(currentVersion) {
1000
+ p3.log.success(`You're on the latest version ${pc3.green(`(${currentVersion})`)}`);
1001
+ }
1002
+ function showPackageManagerInfo(pm) {
1003
+ console.log();
1004
+ console.log(` ${pc3.dim("Detected:")} ${pm.displayName} installation`);
1005
+ console.log(` ${pc3.dim("Command:")} ${pc3.cyan(pm.updateCommand)}`);
1006
+ console.log();
1007
+ }
1008
+ function showUpdateSuccess(newVersion) {
1009
+ p3.log.success(`Updated to version ${pc3.green(newVersion)}`);
1010
+ p3.log.info("Please restart to use the new version.");
1011
+ }
1012
+ function showUpdateError(error, pm) {
1013
+ if (error) {
1014
+ p3.log.error(pc3.dim(error));
1015
+ }
1016
+ p3.log.info(`Try running manually: ${pc3.cyan(pm.updateCommand)}`);
1017
+ }
1018
+
1019
+ // src/commands/update.ts
1020
+ async function runUpdate(options) {
1021
+ const { force = false, cliName = "env2op" } = options;
1022
+ p4.intro(pc4.bgCyan(pc4.black(` ${cliName} update `)));
1023
+ const spinner4 = p4.spinner();
1024
+ spinner4.start("Checking for updates...");
1025
+ const result = await checkForUpdate(true);
1026
+ spinner4.stop("Checked for updates");
1027
+ if (!result.updateAvailable || !result.latestVersion) {
1028
+ showUpToDate(result.currentVersion);
1029
+ return;
1030
+ }
1031
+ showUpdateAvailable(result);
1032
+ const pm = await detectPackageManager();
1033
+ showPackageManagerInfo(pm);
1034
+ if (!force) {
1035
+ const choice = await askToUpdate(result);
1036
+ if (choice === "skip") {
1037
+ skipVersion(result.latestVersion);
1038
+ p4.log.info(`Skipped version ${result.latestVersion}`);
1039
+ return;
1040
+ }
1041
+ if (choice === "later") {
1042
+ p4.log.info("Update postponed");
1043
+ return;
1044
+ }
1045
+ }
1046
+ const updateSpinner = p4.spinner();
1047
+ updateSpinner.start(`Updating to ${result.latestVersion}...`);
1048
+ const updateResult = await performUpdate(pm);
1049
+ if (updateResult.success) {
1050
+ updateSpinner.stop("Update completed");
1051
+ showUpdateSuccess(result.latestVersion);
1052
+ } else {
1053
+ updateSpinner.stop("Update failed");
1054
+ showUpdateError(updateResult.error, pm);
1055
+ process.exit(1);
1056
+ }
1057
+ }
1058
+
769
1059
  // src/cli.ts
770
1060
  var pkg2 = await Promise.resolve().then(() => __toESM(require_package(), 1));
771
1061
  var args = process.argv.slice(2);
@@ -792,10 +1082,19 @@ for (let i = 0;i < args.length; i++) {
792
1082
  }
793
1083
  var hasHelp = flags.has("h") || flags.has("help");
794
1084
  var hasVersion = flags.has("v") || flags.has("version");
1085
+ var hasUpdate = flags.has("update");
795
1086
  if (hasVersion) {
796
1087
  console.log(pkg2.version);
797
1088
  process.exit(0);
798
1089
  }
1090
+ if (hasUpdate) {
1091
+ await runUpdate({
1092
+ force: flags.has("f") || flags.has("force"),
1093
+ verbose: flags.has("verbose"),
1094
+ cliName: "env2op"
1095
+ });
1096
+ process.exit(0);
1097
+ }
799
1098
  if (hasHelp || positional.length === 0) {
800
1099
  showHelp();
801
1100
  process.exit(0);
@@ -815,48 +1114,55 @@ await runConvert({
815
1114
  force: flags.has("f") || flags.has("force"),
816
1115
  verbose: flags.has("verbose")
817
1116
  });
1117
+ try {
1118
+ const updateResult = await checkForUpdate();
1119
+ if (updateResult.updateAvailable && !updateResult.isSkipped) {
1120
+ showUpdateNotification(updateResult, "env2op");
1121
+ }
1122
+ } catch {}
818
1123
  function showHelp() {
819
- const name = pc3.bold(pc3.cyan("env2op"));
820
- const version = pc3.dim(`v${pkg2.version}`);
1124
+ const name = pc5.bold(pc5.cyan("env2op"));
1125
+ const version = pc5.dim(`v${pkg2.version}`);
821
1126
  console.log(`
822
1127
  ${name} ${version}
823
1128
  ${pkg2.description}
824
1129
 
825
- ${pc3.bold("USAGE")}
826
- ${pc3.cyan("$")} env2op ${pc3.yellow("<env_file>")} ${pc3.yellow("<vault>")} ${pc3.yellow("<item_name>")} ${pc3.dim("[options]")}
1130
+ ${pc5.bold("USAGE")}
1131
+ ${pc5.cyan("$")} env2op ${pc5.yellow("<env_file>")} ${pc5.yellow("<vault>")} ${pc5.yellow("<item_name>")} ${pc5.dim("[options]")}
827
1132
 
828
- ${pc3.bold("ARGUMENTS")}
829
- ${pc3.yellow("env_file")} Path to .env file
830
- ${pc3.yellow("vault")} 1Password vault name
831
- ${pc3.yellow("item_name")} Name for the Secure Note in 1Password
1133
+ ${pc5.bold("ARGUMENTS")}
1134
+ ${pc5.yellow("env_file")} Path to .env file
1135
+ ${pc5.yellow("vault")} 1Password vault name
1136
+ ${pc5.yellow("item_name")} Name for the Secure Note in 1Password
832
1137
 
833
- ${pc3.bold("OPTIONS")}
834
- ${pc3.cyan("-o, --output")} Output template path (default: <env_file>.tpl)
835
- ${pc3.cyan("-f, --force")} Skip confirmation prompts
836
- ${pc3.cyan("--dry-run")} Preview actions without executing
837
- ${pc3.cyan("--secret")} Store all fields as password type (hidden)
838
- ${pc3.cyan("--verbose")} Show op CLI output
839
- ${pc3.cyan("-h, --help")} Show this help message
840
- ${pc3.cyan("-v, --version")} Show version
1138
+ ${pc5.bold("OPTIONS")}
1139
+ ${pc5.cyan("-o, --output")} Output template path (default: <env_file>.tpl)
1140
+ ${pc5.cyan("-f, --force")} Skip confirmation prompts
1141
+ ${pc5.cyan(" --dry-run")} Preview actions without executing
1142
+ ${pc5.cyan(" --secret")} Store all fields as password type (hidden)
1143
+ ${pc5.cyan(" --verbose")} Show op CLI output
1144
+ ${pc5.cyan(" --update")} Check for and install updates
1145
+ ${pc5.cyan("-v, --version")} Show version
1146
+ ${pc5.cyan("-h, --help")} Show this help message
841
1147
 
842
- ${pc3.bold("EXAMPLES")}
843
- ${pc3.dim("# Basic usage")}
844
- ${pc3.cyan("$")} env2op .env.production Personal "MyApp - Production"
1148
+ ${pc5.bold("EXAMPLES")}
1149
+ ${pc5.dim("# Basic usage")}
1150
+ ${pc5.cyan("$")} env2op .env.production Personal "MyApp - Production"
845
1151
 
846
- ${pc3.dim("# Custom output path")}
847
- ${pc3.cyan("$")} env2op .env Personal "MyApp" -o secrets.tpl
1152
+ ${pc5.dim("# Custom output path")}
1153
+ ${pc5.cyan("$")} env2op .env Personal "MyApp" -o secrets.tpl
848
1154
 
849
- ${pc3.dim("# Preview without making changes")}
850
- ${pc3.cyan("$")} env2op .env Personal "MyApp" --dry-run
1155
+ ${pc5.dim("# Preview without making changes")}
1156
+ ${pc5.cyan("$")} env2op .env Personal "MyApp" --dry-run
851
1157
 
852
- ${pc3.dim("# Store as hidden password fields")}
853
- ${pc3.cyan("$")} env2op .env Personal "MyApp" --secret
1158
+ ${pc5.dim("# Store as hidden password fields")}
1159
+ ${pc5.cyan("$")} env2op .env Personal "MyApp" --secret
854
1160
 
855
- ${pc3.dim("# Skip confirmation prompts (for CI/scripts)")}
856
- ${pc3.cyan("$")} env2op .env Personal "MyApp" -f
1161
+ ${pc5.dim("# Skip confirmation prompts (for CI/scripts)")}
1162
+ ${pc5.cyan("$")} env2op .env Personal "MyApp" -f
857
1163
 
858
- ${pc3.bold("DOCUMENTATION")}
859
- ${pc3.dim("https://github.com/tolgamorf/env2op-cli")}
1164
+ ${pc5.bold("DOCUMENTATION")}
1165
+ ${pc5.dim("https://github.com/tolgamorf/env2op-cli")}
860
1166
  `);
861
1167
  }
862
1168
  function showMissingArgsError(provided) {
@@ -868,17 +1174,17 @@ function showMissingArgsError(provided) {
868
1174
  if (provided.length < 3)
869
1175
  missing.push("item_name");
870
1176
  console.log(`
871
- ${pc3.red(pc3.bold("Error:"))} Missing required arguments
1177
+ ${pc5.red(pc5.bold("Error:"))} Missing required arguments
872
1178
 
873
- ${pc3.bold("Usage:")} env2op ${pc3.yellow("<env_file>")} ${pc3.yellow("<vault>")} ${pc3.yellow("<item_name>")} ${pc3.dim("[options]")}
1179
+ ${pc5.bold("Usage:")} env2op ${pc5.yellow("<env_file>")} ${pc5.yellow("<vault>")} ${pc5.yellow("<item_name>")} ${pc5.dim("[options]")}
874
1180
 
875
- ${pc3.bold("Missing:")}
876
- ${missing.map((arg) => ` ${pc3.red("•")} ${pc3.yellow(arg)}`).join(`
1181
+ ${pc5.bold("Missing:")}
1182
+ ${missing.map((arg) => ` ${pc5.red("•")} ${pc5.yellow(arg)}`).join(`
877
1183
  `)}
878
1184
 
879
- ${pc3.bold("Example:")}
880
- ${pc3.cyan("$")} env2op .env.production Personal "MyApp - Production"
1185
+ ${pc5.bold("Example:")}
1186
+ ${pc5.cyan("$")} env2op .env.production Personal "MyApp - Production"
881
1187
 
882
- Run ${pc3.cyan("env2op --help")} for more information.
1188
+ Run ${pc5.cyan("env2op --help")} for more information.
883
1189
  `);
884
1190
  }