@tolgamorf/env2op-cli 0.2.0 → 0.2.1

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 (All Operating Systems)
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
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.1",
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",
@@ -106,11 +106,10 @@ import pc3 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
  }
package/dist/index.d.ts CHANGED
@@ -113,7 +113,7 @@ interface TemplateOptions {
113
113
  * @returns ParseResult containing variables and any errors
114
114
  * @throws Env2OpError if file not found
115
115
  */
116
- declare function parseEnvFile(filePath: string): ParseResult;
116
+ declare function parseEnvFile(filePath: string): Promise<ParseResult>;
117
117
  /**
118
118
  * Validate that the parsed result has variables
119
119
  *
@@ -198,6 +198,7 @@ declare const ErrorCodes: {
198
198
  readonly VAULT_CREATE_FAILED: "VAULT_CREATE_FAILED";
199
199
  readonly ITEM_EXISTS: "ITEM_EXISTS";
200
200
  readonly ITEM_CREATE_FAILED: "ITEM_CREATE_FAILED";
201
+ readonly ITEM_EDIT_FAILED: "ITEM_EDIT_FAILED";
201
202
  readonly PARSE_ERROR: "PARSE_ERROR";
202
203
  readonly TEMPLATE_NOT_FOUND: "TEMPLATE_NOT_FOUND";
203
204
  readonly INJECT_FAILED: "INJECT_FAILED";
@@ -215,6 +216,7 @@ declare const errors: {
215
216
  vaultCreateFailed: (message: string) => Env2OpError;
216
217
  itemExists: (title: string, vault: string) => Env2OpError;
217
218
  itemCreateFailed: (message: string) => Env2OpError;
219
+ itemEditFailed: (message: string) => Env2OpError;
218
220
  parseError: (line: number, message: string) => Env2OpError;
219
221
  };
220
222
  export { writeTemplate, vaultExists, validateParseResult, signIn, parseEnvFile, itemExists2 as itemExists, generateUsageInstructions, generateTemplateContent, errors, editSecureNote, createVault, createSecureNote, checkSignedIn, checkOpCli, TemplateOptions, ParseResult, ErrorCodes, EnvVariable, EnvLine, Env2OpError, CreateItemResult, CreateItemOptions, ConvertOptions };
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  // src/core/env-parser.ts
2
- import { existsSync, readFileSync } from "node:fs";
2
+ import { readFile } from "node:fs/promises";
3
3
 
4
4
  // src/utils/errors.ts
5
5
  class Env2OpError extends Error {
@@ -22,6 +22,7 @@ var ErrorCodes = {
22
22
  VAULT_CREATE_FAILED: "VAULT_CREATE_FAILED",
23
23
  ITEM_EXISTS: "ITEM_EXISTS",
24
24
  ITEM_CREATE_FAILED: "ITEM_CREATE_FAILED",
25
+ ITEM_EDIT_FAILED: "ITEM_EDIT_FAILED",
25
26
  PARSE_ERROR: "PARSE_ERROR",
26
27
  TEMPLATE_NOT_FOUND: "TEMPLATE_NOT_FOUND",
27
28
  INJECT_FAILED: "INJECT_FAILED"
@@ -35,6 +36,7 @@ var errors = {
35
36
  vaultCreateFailed: (message) => new Env2OpError(`Failed to create vault: ${message}`, ErrorCodes.VAULT_CREATE_FAILED),
36
37
  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"),
37
38
  itemCreateFailed: (message) => new Env2OpError(`Failed to create 1Password item: ${message}`, ErrorCodes.ITEM_CREATE_FAILED),
39
+ itemEditFailed: (message) => new Env2OpError(`Failed to edit 1Password item: ${message}`, ErrorCodes.ITEM_EDIT_FAILED),
38
40
  parseError: (line, message) => new Env2OpError(`Parse error at line ${line}: ${message}`, ErrorCodes.PARSE_ERROR)
39
41
  };
40
42
 
@@ -82,12 +84,20 @@ function parseValue(raw) {
82
84
  const parts = trimmed.split(/\s+#/);
83
85
  return (parts[0] ?? trimmed).trim();
84
86
  }
85
- function parseEnvFile(filePath) {
86
- if (!existsSync(filePath)) {
87
+ function stripBom(content) {
88
+ if (content.charCodeAt(0) === 65279) {
89
+ return content.slice(1);
90
+ }
91
+ return content;
92
+ }
93
+ async function parseEnvFile(filePath) {
94
+ let rawContent;
95
+ try {
96
+ rawContent = await readFile(filePath, "utf-8");
97
+ } catch {
87
98
  throw errors.envFileNotFound(filePath);
88
99
  }
89
- const rawContent = readFileSync(filePath, "utf-8");
90
- const content = stripHeaders(rawContent);
100
+ const content = stripHeaders(stripBom(rawContent));
91
101
  const rawLines = content.split(`
92
102
  `);
93
103
  const variables = [];
@@ -151,33 +161,34 @@ async function exec(command, args = [], options = {}) {
151
161
  const proc = spawn(command, args, {
152
162
  stdio: ["ignore", "pipe", "pipe"]
153
163
  });
154
- let stdout = "";
155
- let stderr = "";
164
+ const stdoutChunks = [];
165
+ const stderrChunks = [];
156
166
  proc.stdout?.on("data", (data) => {
157
- const text = data.toString();
158
- stdout += text;
167
+ const text = Buffer.isBuffer(data) ? data.toString() : String(data);
168
+ stdoutChunks.push(text);
159
169
  if (verbose) {
160
170
  process.stdout.write(text);
161
171
  }
162
172
  });
163
173
  proc.stderr?.on("data", (data) => {
164
- const text = data.toString();
165
- stderr += text;
174
+ const text = Buffer.isBuffer(data) ? data.toString() : String(data);
175
+ stderrChunks.push(text);
166
176
  if (verbose) {
167
177
  process.stderr.write(text);
168
178
  }
169
179
  });
170
180
  proc.on("close", (code) => {
171
181
  resolve({
172
- stdout,
173
- stderr,
174
- exitCode: code ?? 0
182
+ stdout: stdoutChunks.join(""),
183
+ stderr: stderrChunks.join(""),
184
+ exitCode: code ?? 1
175
185
  });
176
186
  });
177
- proc.on("error", () => {
187
+ proc.on("error", (err) => {
188
+ stderrChunks.push(err.message);
178
189
  resolve({
179
- stdout,
180
- stderr,
190
+ stdout: stdoutChunks.join(""),
191
+ stderr: stderrChunks.join(""),
181
192
  exitCode: 1
182
193
  });
183
194
  });
@@ -193,27 +204,36 @@ async function execWithStdin(command, args = [], options) {
193
204
  const proc = spawn(command, args, {
194
205
  stdio: ["pipe", "pipe", "pipe"]
195
206
  });
196
- let stdout = "";
197
- let stderr = "";
207
+ const stdoutChunks = [];
208
+ const stderrChunks = [];
198
209
  proc.stdin?.write(stdinContent);
199
210
  proc.stdin?.end();
200
211
  proc.stdout?.on("data", (data) => {
201
- const text = data.toString();
202
- stdout += text;
212
+ const text = Buffer.isBuffer(data) ? data.toString() : String(data);
213
+ stdoutChunks.push(text);
203
214
  if (verbose)
204
215
  process.stdout.write(text);
205
216
  });
206
217
  proc.stderr?.on("data", (data) => {
207
- const text = data.toString();
208
- stderr += text;
218
+ const text = Buffer.isBuffer(data) ? data.toString() : String(data);
219
+ stderrChunks.push(text);
209
220
  if (verbose)
210
221
  process.stderr.write(text);
211
222
  });
212
223
  proc.on("close", (code) => {
213
- resolve({ stdout, stderr, exitCode: code ?? 0 });
224
+ resolve({
225
+ stdout: stdoutChunks.join(""),
226
+ stderr: stderrChunks.join(""),
227
+ exitCode: code ?? 1
228
+ });
214
229
  });
215
- proc.on("error", () => {
216
- resolve({ stdout, stderr, exitCode: 1 });
230
+ proc.on("error", (err) => {
231
+ stderrChunks.push(err.message);
232
+ resolve({
233
+ stdout: stdoutChunks.join(""),
234
+ stderr: stderrChunks.join(""),
235
+ exitCode: 1
236
+ });
217
237
  });
218
238
  });
219
239
  }
@@ -333,7 +353,7 @@ async function editSecureNote(options) {
333
353
  };
334
354
  } catch (error) {
335
355
  const message = error instanceof Error ? error.message : String(error);
336
- throw errors.itemCreateFailed(message);
356
+ throw errors.itemEditFailed(message);
337
357
  }
338
358
  }
339
359
  // src/core/template-generator.ts
@@ -341,7 +361,7 @@ import { writeFileSync } from "node:fs";
341
361
  // package.json
342
362
  var package_default = {
343
363
  name: "@tolgamorf/env2op-cli",
344
- version: "0.2.0",
364
+ version: "0.2.1",
345
365
  description: "Convert .env files to 1Password Secure Notes and generate templates for op inject/run",
346
366
  type: "module",
347
367
  main: "dist/index.js",
@@ -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.1",
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",
@@ -105,13 +105,12 @@ var require_package = __commonJS((exports, module) => {
105
105
  import pc3 from "picocolors";
106
106
 
107
107
  // src/commands/inject.ts
108
- import { existsSync as existsSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "node:fs";
108
+ import { existsSync, readFileSync, writeFileSync as writeFileSync2 } from "node:fs";
109
109
  import { basename } from "node:path";
110
- import { setTimeout } from "node:timers/promises";
111
110
  import * as p2 from "@clack/prompts";
112
111
 
113
112
  // src/core/env-parser.ts
114
- import { existsSync, readFileSync } from "node:fs";
113
+ import { readFile } from "node:fs/promises";
115
114
 
116
115
  // src/utils/errors.ts
117
116
  class Env2OpError extends Error {
@@ -134,6 +133,7 @@ var ErrorCodes = {
134
133
  VAULT_CREATE_FAILED: "VAULT_CREATE_FAILED",
135
134
  ITEM_EXISTS: "ITEM_EXISTS",
136
135
  ITEM_CREATE_FAILED: "ITEM_CREATE_FAILED",
136
+ ITEM_EDIT_FAILED: "ITEM_EDIT_FAILED",
137
137
  PARSE_ERROR: "PARSE_ERROR",
138
138
  TEMPLATE_NOT_FOUND: "TEMPLATE_NOT_FOUND",
139
139
  INJECT_FAILED: "INJECT_FAILED"
@@ -147,6 +147,7 @@ var errors = {
147
147
  vaultCreateFailed: (message) => new Env2OpError(`Failed to create vault: ${message}`, ErrorCodes.VAULT_CREATE_FAILED),
148
148
  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"),
149
149
  itemCreateFailed: (message) => new Env2OpError(`Failed to create 1Password item: ${message}`, ErrorCodes.ITEM_CREATE_FAILED),
150
+ itemEditFailed: (message) => new Env2OpError(`Failed to edit 1Password item: ${message}`, ErrorCodes.ITEM_EDIT_FAILED),
150
151
  parseError: (line, message) => new Env2OpError(`Parse error at line ${line}: ${message}`, ErrorCodes.PARSE_ERROR)
151
152
  };
152
153
 
@@ -194,12 +195,20 @@ function parseValue(raw) {
194
195
  const parts = trimmed.split(/\s+#/);
195
196
  return (parts[0] ?? trimmed).trim();
196
197
  }
197
- function parseEnvFile(filePath) {
198
- if (!existsSync(filePath)) {
198
+ function stripBom(content) {
199
+ if (content.charCodeAt(0) === 65279) {
200
+ return content.slice(1);
201
+ }
202
+ return content;
203
+ }
204
+ async function parseEnvFile(filePath) {
205
+ let rawContent;
206
+ try {
207
+ rawContent = await readFile(filePath, "utf-8");
208
+ } catch {
199
209
  throw errors.envFileNotFound(filePath);
200
210
  }
201
- const rawContent = readFileSync(filePath, "utf-8");
202
- const content = stripHeaders(rawContent);
211
+ const content = stripHeaders(stripBom(rawContent));
203
212
  const rawLines = content.split(`
204
213
  `);
205
214
  const variables = [];
@@ -264,33 +273,34 @@ async function exec(command, args = [], options = {}) {
264
273
  const proc = spawn(command, args, {
265
274
  stdio: ["ignore", "pipe", "pipe"]
266
275
  });
267
- let stdout = "";
268
- let stderr = "";
276
+ const stdoutChunks = [];
277
+ const stderrChunks = [];
269
278
  proc.stdout?.on("data", (data) => {
270
- const text = data.toString();
271
- stdout += text;
279
+ const text = Buffer.isBuffer(data) ? data.toString() : String(data);
280
+ stdoutChunks.push(text);
272
281
  if (verbose) {
273
282
  process.stdout.write(text);
274
283
  }
275
284
  });
276
285
  proc.stderr?.on("data", (data) => {
277
- const text = data.toString();
278
- stderr += text;
286
+ const text = Buffer.isBuffer(data) ? data.toString() : String(data);
287
+ stderrChunks.push(text);
279
288
  if (verbose) {
280
289
  process.stderr.write(text);
281
290
  }
282
291
  });
283
292
  proc.on("close", (code) => {
284
293
  resolve({
285
- stdout,
286
- stderr,
287
- exitCode: code ?? 0
294
+ stdout: stdoutChunks.join(""),
295
+ stderr: stderrChunks.join(""),
296
+ exitCode: code ?? 1
288
297
  });
289
298
  });
290
- proc.on("error", () => {
299
+ proc.on("error", (err) => {
300
+ stderrChunks.push(err.message);
291
301
  resolve({
292
- stdout,
293
- stderr,
302
+ stdout: stdoutChunks.join(""),
303
+ stderr: stderrChunks.join(""),
294
304
  exitCode: 1
295
305
  });
296
306
  });
@@ -306,27 +316,36 @@ async function execWithStdin(command, args = [], options) {
306
316
  const proc = spawn(command, args, {
307
317
  stdio: ["pipe", "pipe", "pipe"]
308
318
  });
309
- let stdout = "";
310
- let stderr = "";
319
+ const stdoutChunks = [];
320
+ const stderrChunks = [];
311
321
  proc.stdin?.write(stdinContent);
312
322
  proc.stdin?.end();
313
323
  proc.stdout?.on("data", (data) => {
314
- const text = data.toString();
315
- stdout += text;
324
+ const text = Buffer.isBuffer(data) ? data.toString() : String(data);
325
+ stdoutChunks.push(text);
316
326
  if (verbose)
317
327
  process.stdout.write(text);
318
328
  });
319
329
  proc.stderr?.on("data", (data) => {
320
- const text = data.toString();
321
- stderr += text;
330
+ const text = Buffer.isBuffer(data) ? data.toString() : String(data);
331
+ stderrChunks.push(text);
322
332
  if (verbose)
323
333
  process.stderr.write(text);
324
334
  });
325
335
  proc.on("close", (code) => {
326
- resolve({ stdout, stderr, exitCode: code ?? 0 });
336
+ resolve({
337
+ stdout: stdoutChunks.join(""),
338
+ stderr: stderrChunks.join(""),
339
+ exitCode: code ?? 1
340
+ });
327
341
  });
328
- proc.on("error", () => {
329
- resolve({ stdout, stderr, exitCode: 1 });
342
+ proc.on("error", (err) => {
343
+ stderrChunks.push(err.message);
344
+ resolve({
345
+ stdout: stdoutChunks.join(""),
346
+ stderr: stderrChunks.join(""),
347
+ exitCode: 1
348
+ });
330
349
  });
331
350
  });
332
351
  }
@@ -446,7 +465,7 @@ async function editSecureNote(options) {
446
465
  };
447
466
  } catch (error) {
448
467
  const message = error instanceof Error ? error.message : String(error);
449
- throw errors.itemCreateFailed(message);
468
+ throw errors.itemEditFailed(message);
450
469
  }
451
470
  }
452
471
 
@@ -607,12 +626,15 @@ ${pc2.bold(pc2.underline(title))}`);
607
626
  }
608
627
  };
609
628
 
610
- // src/commands/inject.ts
629
+ // src/utils/timing.ts
630
+ import { setTimeout } from "node:timers/promises";
611
631
  var MIN_SPINNER_TIME = 500;
612
632
  async function withMinTime(promise, minTime = MIN_SPINNER_TIME) {
613
633
  const [result] = await Promise.all([promise, setTimeout(minTime)]);
614
634
  return result;
615
635
  }
636
+
637
+ // src/commands/inject.ts
616
638
  function deriveOutputPath(templatePath) {
617
639
  if (templatePath.endsWith(".tpl")) {
618
640
  return templatePath.slice(0, -4);
@@ -625,7 +647,7 @@ async function runInject(options) {
625
647
  const pkg2 = await Promise.resolve().then(() => __toESM(require_package(), 1));
626
648
  logger.intro("op2env", pkg2.version, dryRun);
627
649
  try {
628
- if (!existsSync2(templateFile)) {
650
+ if (!existsSync(templateFile)) {
629
651
  throw new Env2OpError(`Template file not found: ${templateFile}`, "TEMPLATE_NOT_FOUND", "Ensure the file exists and the path is correct");
630
652
  }
631
653
  logger.success(`Found template: ${basename(templateFile)}`);
@@ -653,7 +675,7 @@ async function runInject(options) {
653
675
  }
654
676
  authSpinner.stop("1Password CLI ready");
655
677
  }
656
- const outputExists = existsSync2(outputPath);
678
+ const outputExists = existsSync(outputPath);
657
679
  if (dryRun) {
658
680
  if (outputExists) {
659
681
  logger.warn(`Would overwrite: ${outputPath}`);
@@ -679,7 +701,7 @@ async function runInject(options) {
679
701
  if (result.exitCode !== 0) {
680
702
  throw new Error(result.stderr);
681
703
  }
682
- const rawContent = readFileSync2(outputPath, "utf-8");
704
+ const rawContent = readFileSync(outputPath, "utf-8");
683
705
  const envContent = stripHeaders(rawContent);
684
706
  const header = generateEnvHeader(basename(outputPath)).join(`
685
707
  `);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tolgamorf/env2op-cli",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "description": "Convert .env files to 1Password Secure Notes and generate templates for op inject/run",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",