Comparing version 2.3.1 to 2.3.2
@@ -0,1 +1,5 @@ | ||
### Version 2.3.2 (2021-05-20) | ||
- Fixed: cwd is now resolved (using `path.resolve`) before being passed to `spawn`. Previously, just passing `cwd: "."` could cause `npm run` not to find package.json. | ||
### Version 2.3.1 (2021-03-29) | ||
@@ -2,0 +6,0 @@ |
{ | ||
"name": "run-pty", | ||
"version": "2.3.1", | ||
"version": "2.3.2", | ||
"author": "Simon Lydell", | ||
@@ -27,14 +27,15 @@ "license": "MIT", | ||
"dependencies": { | ||
"node-pty": "^0.10.0" | ||
"node-pty": "^0.10.1", | ||
"tiny-decoders": "^6.0.0" | ||
}, | ||
"devDependencies": { | ||
"@types/jest": "26.0.22", | ||
"@typescript-eslint/eslint-plugin": "4.19.0", | ||
"@typescript-eslint/parser": "4.19.0", | ||
"eslint": "7.23.0", | ||
"eslint-plugin-jest": "24.3.2", | ||
"@types/jest": "26.0.23", | ||
"@typescript-eslint/eslint-plugin": "4.24.0", | ||
"@typescript-eslint/parser": "4.24.0", | ||
"eslint": "7.26.0", | ||
"eslint-plugin-jest": "24.3.6", | ||
"jest": "26.6.3", | ||
"jest-environment-node-single-context": "26.2.0", | ||
"prettier": "2.2.1", | ||
"typescript": "4.2.3" | ||
"prettier": "2.3.0", | ||
"typescript": "4.2.4" | ||
}, | ||
@@ -41,0 +42,0 @@ "scripts": { |
227
run-pty.js
@@ -8,2 +8,3 @@ #!/usr/bin/env node | ||
const pty = require("node-pty"); | ||
const Decode = require("tiny-decoders"); | ||
@@ -479,3 +480,4 @@ /** | ||
// - u: Restore cursor position. | ||
const NOT_SIMPLE_LOG_ESCAPE = /\x1B\[(?:\d*[ABEFLMST]|[su]|(?!(?:[01](?:;[01])?)?[fH]\x1B\[[02]?J)(?:\d+(?:;\d+)?)?[fH])/; | ||
const NOT_SIMPLE_LOG_ESCAPE = | ||
/\x1B\[(?:\d*[ABEFLMST]|[su]|(?!(?:[01](?:;[01])?)?[fH]\x1B\[[02]?J)(?:\d+(?:;\d+)?)?[fH])/; | ||
const GRAPHIC_RENDITIONS = /(\x1B\[(?:\d+(?:;\d+)*)?m)/g; | ||
@@ -594,3 +596,3 @@ | ||
status: Array<[RegExp, [string, string] | undefined]> | ||
defaultStatus: [string, string] | undefined | ||
defaultStatus?: [string, string] | ||
}} CommandDescription | ||
@@ -682,19 +684,9 @@ */ | ||
case "[": { | ||
/** @type {unknown} */ | ||
const json = JSON.parse(string); | ||
if (!Array.isArray(json)) { | ||
throw new Error(`Expected an array but got: ${JSON.stringify(json)}`); | ||
try { | ||
return Decode.array(commandDescriptionDecoder)(JSON.parse(string)); | ||
} catch (error) { | ||
throw error instanceof Decode.DecoderError | ||
? new Error(error.format()) | ||
: error; | ||
} | ||
return json.map((item, index) => { | ||
try { | ||
return parseInputItem(item); | ||
} catch (error) { | ||
throw new Error( | ||
`Index ${index}: ${ | ||
error instanceof Error ? error.message : "Unknown parse error" | ||
}` | ||
); | ||
} | ||
}); | ||
} | ||
@@ -711,7 +703,11 @@ | ||
try { | ||
return parseInputItem(JSON.parse(trimmed)); | ||
return commandDescriptionDecoder(JSON.parse(trimmed)); | ||
} catch (error) { | ||
throw new Error( | ||
`Line ${lineIndex + 1}: ${ | ||
error instanceof Error ? error.message : "Unknown parse error" | ||
error instanceof Decode.DecoderError | ||
? error.format() | ||
: error instanceof Error | ||
? error.message | ||
: "Unknown parse error" | ||
}` | ||
@@ -730,148 +726,59 @@ ); | ||
/** | ||
* @param {unknown} json | ||
* @returns {CommandDescription} | ||
* @type {Decode.Decoder<CommandDescription>} | ||
*/ | ||
const parseInputItem = (json) => { | ||
if (typeof json !== "object" || Array.isArray(json) || json === null) { | ||
throw new Error(`Expected a JSON object but got: ${JSON.stringify(json)}`); | ||
} | ||
const commandDescriptionDecoder = Decode.fields( | ||
/** @returns {CommandDescription} */ | ||
(field) => { | ||
const command = field("command", nonEmptyArray(Decode.string)); | ||
/** @type {Partial<CommandDescription>} */ | ||
const commandDescription = {}; | ||
return { | ||
title: field( | ||
"title", | ||
Decode.optional(Decode.string, commandToPresentationName(command)) | ||
), | ||
cwd: field("cwd", Decode.optional(Decode.string, ".")), | ||
command, | ||
status: field( | ||
"status", | ||
Decode.optional( | ||
Decode.chain(Decode.record(statusDecoder), (record) => | ||
Object.entries(record).map(([key, value]) => { | ||
try { | ||
return [RegExp(key, "u"), value]; | ||
} catch (error) { | ||
throw Decode.DecoderError.at(error, key); | ||
} | ||
}) | ||
), | ||
[] | ||
) | ||
), | ||
defaultStatus: field("defaultStatus", Decode.optional(statusDecoder)), | ||
}; | ||
}, | ||
{ exact: "throw" } | ||
); | ||
for (const [key, value] of Object.entries(json)) { | ||
switch (key) { | ||
case "title": | ||
if (typeof value !== "string") { | ||
throw new Error( | ||
`title: Expected a string but got: ${JSON.stringify(value)}` | ||
); | ||
} | ||
commandDescription.title = value; | ||
break; | ||
case "cwd": | ||
if (typeof value !== "string") { | ||
throw new Error( | ||
`cwd: Expected a string but got: ${JSON.stringify(value)}` | ||
); | ||
} | ||
commandDescription.cwd = value; | ||
break; | ||
case "command": { | ||
if (!Array.isArray(value)) { | ||
throw new Error( | ||
`command: Expected an array but got: ${JSON.stringify(value)}` | ||
); | ||
} | ||
const command = []; | ||
for (const [index, item] of value.entries()) { | ||
if (typeof item !== "string") { | ||
throw new Error( | ||
`command[${index}]: Expected a string but got: ${JSON.stringify( | ||
value | ||
)}` | ||
); | ||
} | ||
command.push(item); | ||
} | ||
if (command.length === 0) { | ||
throw new Error("command: Expected a non-empty array"); | ||
} | ||
commandDescription.command = command; | ||
break; | ||
} | ||
case "status": { | ||
if (typeof json !== "object" || Array.isArray(json) || json === null) { | ||
throw new Error( | ||
`status: Expected an object but got: ${JSON.stringify(value)}` | ||
); | ||
} | ||
/** @type {Array<[RegExp, [string, string] | undefined]>} */ | ||
const status = []; | ||
for (const [key2, value2] of Object.entries(value)) { | ||
try { | ||
status.push([RegExp(key2, "u"), parseStatus(value2)]); | ||
} catch (error) { | ||
throw new Error( | ||
`status[${JSON.stringify(key2)}]: ${ | ||
error instanceof SyntaxError | ||
? `This key is not a valid regex: ${error.message}` | ||
: error instanceof Error | ||
? error.message | ||
: "Unknown error" | ||
}` | ||
); | ||
} | ||
} | ||
commandDescription.status = status; | ||
break; | ||
} | ||
case "defaultStatus": | ||
try { | ||
commandDescription.defaultStatus = parseStatus(value); | ||
} catch (error) { | ||
throw new Error( | ||
`defaultStatus: ${ | ||
error instanceof Error ? error.message : "Unknown error" | ||
}` | ||
); | ||
} | ||
break; | ||
default: | ||
throw new Error(`Unknown key: ${key}`); | ||
} | ||
} | ||
if (commandDescription.command === undefined) { | ||
throw new Error("command: This field is required, but was not provided."); | ||
} | ||
const { | ||
command, | ||
title = commandToPresentationName(command), | ||
cwd = ".", | ||
status = [], | ||
defaultStatus, | ||
} = commandDescription; | ||
return { title, cwd, command, status, defaultStatus }; | ||
}; | ||
/** | ||
* @param {unknown} json | ||
* @returns {[string, string] | undefined} | ||
* @template T | ||
* @param {Decode.Decoder<T>} decoder | ||
* @returns {Decode.Decoder<Array<T>>} | ||
*/ | ||
const parseStatus = (json) => { | ||
if (json === null) { | ||
return undefined; | ||
} | ||
function nonEmptyArray(decoder) { | ||
return Decode.chain(Decode.array(decoder), (arr) => { | ||
if (arr.length === 0) { | ||
throw new Decode.DecoderError({ | ||
message: "Expected a non-empty array", | ||
value: arr, | ||
}); | ||
} | ||
return arr; | ||
}); | ||
} | ||
if (!Array.isArray(json) || json.length !== 2) { | ||
throw new Error( | ||
`Expected an array of length 2 but got: ${JSON.stringify(json)}` | ||
); | ||
} | ||
const statusDecoder = Decode.nullable( | ||
Decode.tuple([Decode.string, Decode.string]), | ||
undefined | ||
); | ||
/** @type {unknown} */ | ||
const value1 = json[0]; | ||
/** @type {unknown} */ | ||
const value2 = json[1]; | ||
if (typeof value1 !== "string" || typeof value2 !== "string") { | ||
throw new Error(`Expected two strings but got: ${JSON.stringify(json)}`); | ||
} | ||
return [value1, value2]; | ||
}; | ||
/** | ||
@@ -972,3 +879,3 @@ * @param {Command} command | ||
const terminal = pty.spawn(file, args, { | ||
cwd: this.cwd, | ||
cwd: path.resolve(this.cwd), | ||
cols: process.stdout.columns, | ||
@@ -975,0 +882,0 @@ rows: process.stdout.rows, |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
59498
2
1457
+ Addedtiny-decoders@^6.0.0
+ Addedtiny-decoders@6.0.1(transitive)
Updatednode-pty@^0.10.1