@cjser/inquirer__external-editor 3.0.2-cjser.2 → 3.0.3-cjser.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/dist/index.d.ts CHANGED
@@ -23,11 +23,13 @@ export declare class ExternalEditor {
23
23
  lastExitStatus: number;
24
24
  private text;
25
25
  private tempFile;
26
+ private tempDir;
26
27
  private fileOptions;
27
28
  constructor(text?: string, fileOptions?: FileOptions);
28
29
  run(): string;
29
30
  runAsync(callback?: StringCallback): Promise<string>;
30
31
  private cleanup;
31
32
  private createTempFile;
33
+ private editorArgs;
32
34
  private readTemporaryFile;
33
35
  }
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { detect } from 'chardet';
2
2
  import { spawn, spawnSync } from 'node:child_process';
3
- import { readFileSync, unlinkSync, writeFileSync } from 'node:fs';
3
+ import { mkdtempSync, readFileSync, rmSync, writeFileSync, } from 'node:fs';
4
4
  import path from 'node:path';
5
5
  import os from 'node:os';
6
6
  import { randomUUID } from 'node:crypto';
@@ -26,6 +26,7 @@ export class ExternalEditor {
26
26
  lastExitStatus = 0;
27
27
  text = '';
28
28
  tempFile = '';
29
+ tempDir = '';
29
30
  fileOptions = {};
30
31
  constructor(text = '', fileOptions = {}) {
31
32
  this.text = text;
@@ -38,7 +39,13 @@ export class ExternalEditor {
38
39
  this.createTempFile();
39
40
  try {
40
41
  try {
41
- const editorProcess = spawnSync(this.editor.bin, this.editor.args.concat([this.tempFile]), { stdio: 'inherit' });
42
+ const editorProcess = spawnSync(this.editor.bin, this.editorArgs(), {
43
+ shell: false,
44
+ stdio: 'inherit',
45
+ });
46
+ if (editorProcess.error) {
47
+ throw editorProcess.error;
48
+ }
42
49
  this.lastExitStatus = editorProcess.status ?? 0;
43
50
  }
44
51
  catch (launchError) {
@@ -55,9 +62,15 @@ export class ExternalEditor {
55
62
  this.createTempFile();
56
63
  const promise = new Promise((resolve, reject) => {
57
64
  try {
58
- const editorProcess = spawn(this.editor.bin, this.editor.args.concat([this.tempFile]), { stdio: 'inherit' });
59
- editorProcess.on('exit', (code) => {
60
- this.lastExitStatus = code;
65
+ const editorProcess = spawn(this.editor.bin, this.editorArgs(), {
66
+ shell: false,
67
+ stdio: 'inherit',
68
+ });
69
+ editorProcess.once('error', (launchError) => {
70
+ reject(new LaunchEditorError(launchError));
71
+ });
72
+ editorProcess.once('exit', (code) => {
73
+ this.lastExitStatus = code ?? 0;
61
74
  resolve();
62
75
  });
63
76
  }
@@ -78,11 +91,12 @@ export class ExternalEditor {
78
91
  return promise;
79
92
  }
80
93
  cleanup() {
81
- if (!this.tempFile)
94
+ if (!this.tempDir)
82
95
  return;
83
96
  try {
84
- unlinkSync(this.tempFile);
97
+ rmSync(this.tempDir, { force: true, recursive: true });
85
98
  this.tempFile = '';
99
+ this.tempDir = '';
86
100
  }
87
101
  catch (removeFileError) {
88
102
  throw new RemoveFileError(removeFileError);
@@ -90,17 +104,13 @@ export class ExternalEditor {
90
104
  }
91
105
  createTempFile() {
92
106
  try {
93
- const baseDir = this.fileOptions.dir ?? os.tmpdir();
107
+ const baseDir = path.resolve(this.fileOptions.dir ?? os.tmpdir());
108
+ this.tempDir = mkdtempSync(path.join(baseDir, 'inquirer-editor-'));
94
109
  const id = randomUUID();
95
110
  const prefix = sanitizeAffix(this.fileOptions.prefix);
96
111
  const postfix = sanitizeAffix(this.fileOptions.postfix);
97
112
  const filename = `${prefix}${id}${postfix}`;
98
- const candidate = path.resolve(baseDir, filename);
99
- const baseResolved = path.resolve(baseDir) + path.sep;
100
- if (!candidate.startsWith(baseResolved)) {
101
- throw new Error('Resolved temporary file escaped the base directory');
102
- }
103
- this.tempFile = candidate;
113
+ this.tempFile = path.join(this.tempDir, filename);
104
114
  const opt = { encoding: 'utf8', flag: 'wx' };
105
115
  if (Object.prototype.hasOwnProperty.call(this.fileOptions, 'mode')) {
106
116
  opt.mode = this.fileOptions.mode;
@@ -111,6 +121,9 @@ export class ExternalEditor {
111
121
  throw new CreateFileError(createFileError);
112
122
  }
113
123
  }
124
+ editorArgs() {
125
+ return [...this.editor.args, this.tempFile];
126
+ }
114
127
  readTemporaryFile() {
115
128
  try {
116
129
  const tempFileBuffer = readFileSync(this.tempFile);
@@ -26,7 +26,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
26
26
  ));
27
27
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
28
28
 
29
- // packages/@cjser/inquirer__external-editor.tmp-25-1780163567980/dist/index.js
29
+ // packages/@cjser/inquirer__external-editor.tmp-26-1780252414390/dist/index.js
30
30
  var index_exports = {};
31
31
  __export(index_exports, {
32
32
  CreateFileError: () => CreateFileError,
@@ -46,7 +46,7 @@ var import_node_os = __toESM(require("node:os"), 1);
46
46
  var import_node_crypto = require("node:crypto");
47
47
  var import_iconv_lite = __toESM(require("iconv-lite"), 1);
48
48
 
49
- // packages/@cjser/inquirer__external-editor.tmp-25-1780163567980/dist/errors.js
49
+ // packages/@cjser/inquirer__external-editor.tmp-26-1780252414390/dist/errors.js
50
50
  var CreateFileError = class extends Error {
51
51
  name = "CreateFileError";
52
52
  originalError;
@@ -80,7 +80,7 @@ var RemoveFileError = class extends Error {
80
80
  }
81
81
  };
82
82
 
83
- // packages/@cjser/inquirer__external-editor.tmp-25-1780163567980/dist/parse-editor-command.js
83
+ // packages/@cjser/inquirer__external-editor.tmp-26-1780252414390/dist/parse-editor-command.js
84
84
  function parseEditorCommand(editor) {
85
85
  let bin;
86
86
  let rest;
@@ -106,7 +106,7 @@ function parseEditorCommand(editor) {
106
106
  return { bin, args: rest ? rest.split(/\s+/) : [] };
107
107
  }
108
108
 
109
- // packages/@cjser/inquirer__external-editor.tmp-25-1780163567980/dist/index.js
109
+ // packages/@cjser/inquirer__external-editor.tmp-26-1780252414390/dist/index.js
110
110
  function edit(text = "", fileOptions) {
111
111
  return new ExternalEditor(text, fileOptions).run();
112
112
  }
@@ -125,6 +125,7 @@ var ExternalEditor = class {
125
125
  lastExitStatus = 0;
126
126
  text = "";
127
127
  tempFile = "";
128
+ tempDir = "";
128
129
  fileOptions = {};
129
130
  constructor(text = "", fileOptions = {}) {
130
131
  this.text = text;
@@ -135,7 +136,13 @@ var ExternalEditor = class {
135
136
  this.createTempFile();
136
137
  try {
137
138
  try {
138
- const editorProcess = (0, import_node_child_process.spawnSync)(this.editor.bin, this.editor.args.concat([this.tempFile]), { stdio: "inherit" });
139
+ const editorProcess = (0, import_node_child_process.spawnSync)(this.editor.bin, this.editorArgs(), {
140
+ shell: false,
141
+ stdio: "inherit"
142
+ });
143
+ if (editorProcess.error) {
144
+ throw editorProcess.error;
145
+ }
139
146
  this.lastExitStatus = editorProcess.status ?? 0;
140
147
  } catch (launchError) {
141
148
  throw new LaunchEditorError(launchError);
@@ -150,9 +157,15 @@ var ExternalEditor = class {
150
157
  this.createTempFile();
151
158
  const promise = new Promise((resolve, reject) => {
152
159
  try {
153
- const editorProcess = (0, import_node_child_process.spawn)(this.editor.bin, this.editor.args.concat([this.tempFile]), { stdio: "inherit" });
154
- editorProcess.on("exit", (code) => {
155
- this.lastExitStatus = code;
160
+ const editorProcess = (0, import_node_child_process.spawn)(this.editor.bin, this.editorArgs(), {
161
+ shell: false,
162
+ stdio: "inherit"
163
+ });
164
+ editorProcess.once("error", (launchError) => {
165
+ reject(new LaunchEditorError(launchError));
166
+ });
167
+ editorProcess.once("exit", (code) => {
168
+ this.lastExitStatus = code ?? 0;
156
169
  resolve();
157
170
  });
158
171
  } catch (launchError) {
@@ -170,28 +183,25 @@ var ExternalEditor = class {
170
183
  return promise;
171
184
  }
172
185
  cleanup() {
173
- if (!this.tempFile)
186
+ if (!this.tempDir)
174
187
  return;
175
188
  try {
176
- (0, import_node_fs.unlinkSync)(this.tempFile);
189
+ (0, import_node_fs.rmSync)(this.tempDir, { force: true, recursive: true });
177
190
  this.tempFile = "";
191
+ this.tempDir = "";
178
192
  } catch (removeFileError) {
179
193
  throw new RemoveFileError(removeFileError);
180
194
  }
181
195
  }
182
196
  createTempFile() {
183
197
  try {
184
- const baseDir = this.fileOptions.dir ?? import_node_os.default.tmpdir();
198
+ const baseDir = import_node_path.default.resolve(this.fileOptions.dir ?? import_node_os.default.tmpdir());
199
+ this.tempDir = (0, import_node_fs.mkdtempSync)(import_node_path.default.join(baseDir, "inquirer-editor-"));
185
200
  const id = (0, import_node_crypto.randomUUID)();
186
201
  const prefix = sanitizeAffix(this.fileOptions.prefix);
187
202
  const postfix = sanitizeAffix(this.fileOptions.postfix);
188
203
  const filename = `${prefix}${id}${postfix}`;
189
- const candidate = import_node_path.default.resolve(baseDir, filename);
190
- const baseResolved = import_node_path.default.resolve(baseDir) + import_node_path.default.sep;
191
- if (!candidate.startsWith(baseResolved)) {
192
- throw new Error("Resolved temporary file escaped the base directory");
193
- }
194
- this.tempFile = candidate;
204
+ this.tempFile = import_node_path.default.join(this.tempDir, filename);
195
205
  const opt = { encoding: "utf8", flag: "wx" };
196
206
  if (Object.prototype.hasOwnProperty.call(this.fileOptions, "mode")) {
197
207
  opt.mode = this.fileOptions.mode;
@@ -201,6 +211,9 @@ var ExternalEditor = class {
201
211
  throw new CreateFileError(createFileError);
202
212
  }
203
213
  }
214
+ editorArgs() {
215
+ return [...this.editor.args, this.tempFile];
216
+ }
204
217
  readTemporaryFile() {
205
218
  try {
206
219
  const tempFileBuffer = (0, import_node_fs.readFileSync)(this.tempFile);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cjser/inquirer__external-editor",
3
- "version": "3.0.2-cjser.2",
3
+ "version": "3.0.3-cjser.2",
4
4
  "description": "Edit a string with the users preferred text editor using $VISUAL or $ENVIRONMENT",
5
5
  "keywords": [
6
6
  "answer",
@@ -95,13 +95,13 @@
95
95
  },
96
96
  "main": "./dist-cjser/index.cjs",
97
97
  "types": "./dist/index.d.ts",
98
- "gitHead": "b43359d803733b1a7c4638addcc270987fb894c3",
98
+ "gitHead": "bfd8710229e3d3c9784bef3bbfbd84c7bd09bb9e",
99
99
  "cjser": {
100
- "sourceVersion": "3.0.2",
100
+ "sourceVersion": "3.0.3",
101
101
  "cjserVersion": 2,
102
102
  "original": {
103
103
  "name": "@inquirer/external-editor",
104
- "version": "3.0.2",
104
+ "version": "3.0.3",
105
105
  "main": "./dist/index.js",
106
106
  "exports": {
107
107
  ".": {