forked from hugojosefson/deno-run-simple
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
2bd2a6f
commit 490cff8
Showing
7 changed files
with
165 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
export { mapKeys } from "https://deno.land/[email protected]/collections/map_keys.ts"; | ||
export { mapValues } from "https://deno.land/[email protected]/collections/map_values.ts"; | ||
|
||
export { camelCase } from "https://deno.land/x/[email protected]/mod.ts"; | ||
export { Select } from "https://deno.land/x/[email protected]/prompt/select.ts"; | ||
export { fetch as fetchFile } from "https://deno.land/x/[email protected]/mod.ts"; | ||
export { default as _parseColumns } from "https://cdn.skypack.dev/pin/[email protected]/mode=imports/optimized/parse-columns.js"; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,2 @@ | ||
export { run } from "./src/run.ts"; | ||
export type { CommandFailure, RunOptions, SimpleValue } from "./src/run.ts"; | ||
export { jsonRun, run } from "./src/run.ts"; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
export function isString(s?: string | unknown): s is string { | ||
return typeof s === "string"; | ||
} | ||
|
||
const decoder = new TextDecoder(); | ||
export function asString(buf: Uint8Array | null | undefined): string { | ||
if (!buf) { | ||
return ""; | ||
} | ||
return decoder.decode(buf).trim(); | ||
} | ||
export function j(obj: unknown, indentation = 2): string { | ||
return JSON.stringify(obj, null, indentation); | ||
} | ||
|
||
export function parseJsonSafe(input: string | unknown): string | unknown { | ||
if (isString(input)) { | ||
try { | ||
return JSON.parse(input); | ||
} catch (_ignore) { | ||
/* intentional fall-through, and return the input as-is */ | ||
} | ||
} | ||
return input; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
export async function weakEnvGet( | ||
variable: string, | ||
): Promise<false | string | undefined> { | ||
const query = { name: "env" as const, variable }; | ||
const permissionResponse = await Deno.permissions.query(query); | ||
const isGranted = permissionResponse.state === "granted"; | ||
return isGranted && Deno.env.get(variable); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,118 @@ | ||
export async function run() { | ||
throw new Error("Work In Progress; not implemented yet."); | ||
import { asString, isString, j, parseJsonSafe } from "./fn.ts"; | ||
import { weakEnvGet } from "./os.ts"; | ||
|
||
/** Item in the command array. */ | ||
export type SimpleValue = string | number | boolean; | ||
|
||
/** | ||
* What the promise is rejected with, if the command exits with a non-zero exit code. | ||
*/ | ||
export interface CommandFailure { | ||
/** {@link Deno.ProcessStatus} from the underlying {@link Deno.Process}. */ | ||
status: Deno.ProcessStatus; | ||
/** What the command printed to STDERR. */ | ||
stderr: string; | ||
/** What the command printed to STDOUT (as far as it got). */ | ||
stdout: string; | ||
} | ||
|
||
export interface RunOptions { | ||
/** If specified, will be supplied as STDIN to the command. */ | ||
stdin?: string; | ||
/** Print extra details to STDERR; default to whether env variable `"VERBOSE"` has a truthy value, and `--allow-env` is enabled. */ | ||
verbose?: boolean; | ||
} | ||
|
||
const defaultRunOptions: RunOptions = { | ||
verbose: !!await weakEnvGet("VERBOSE"), | ||
}; | ||
|
||
async function tryRun( | ||
cmd: string[], | ||
options: RunOptions = defaultRunOptions, | ||
): Promise<string> { | ||
options = { ...defaultRunOptions, ...options }; | ||
|
||
const pipeStdIn = isString(options.stdin); | ||
|
||
if (options.verbose) { | ||
console.error(` | ||
=============================================================================== | ||
${j({ cmd, stdin: options.stdin })} | ||
-------------------------------------------------------------------------------`); | ||
} | ||
const process = Deno.run({ | ||
cmd, | ||
stdin: pipeStdIn ? "piped" : "null", | ||
stdout: "piped", | ||
stderr: "piped", | ||
}); | ||
|
||
if (pipeStdIn) { | ||
const stdinBuf = new TextEncoder().encode(options.stdin); | ||
try { | ||
await process.stdin?.write(stdinBuf); | ||
} finally { | ||
process.stdin?.close(); | ||
} | ||
} | ||
|
||
const [ | ||
status, | ||
stdout, | ||
stderr, | ||
] = await Promise.all([ | ||
process.status(), | ||
process.output(), | ||
process.stderrOutput(), | ||
]); | ||
process.close(); | ||
|
||
if (status.success) { | ||
const stdoutString = asString(stdout); | ||
if (options.verbose) { | ||
console.error(stdoutString); | ||
} | ||
return stdoutString; | ||
} | ||
const reason: CommandFailure = { | ||
status, | ||
stderr: asString(stderr), | ||
stdout: asString(stdout), | ||
}; | ||
return Promise.reject(reason); | ||
} | ||
|
||
/** | ||
* Runs command, returning a Promise for what the command prints to STDOUT. If the command exits with non-zero exit code, the promise rejects with a {@link CommandFailure}. | ||
* @param command The command to run, as an array of strings, or as a single string. You do not need to quote arguments that contain spaces, when supplying the command as an array. If using the single string format, be careful with spaces. | ||
* @param options Options for the execution. | ||
*/ | ||
export async function run( | ||
command: string | SimpleValue[], | ||
options: RunOptions = defaultRunOptions, | ||
): Promise<string> { | ||
const cmd: string[] = isString(command) | ||
? command.split(" ") | ||
: command.map((segment) => `${segment}`); | ||
try { | ||
return await tryRun(cmd, options); | ||
} catch (error) { | ||
if (options.verbose) { | ||
console.error(j({ cmd, error })); | ||
} | ||
throw error; | ||
} | ||
} | ||
|
||
/** | ||
* Runs a command, just like {@link run}, but parses the response as JSON if possible. Otherwise, returns it as-is. | ||
* @param command The command to run, as an array of strings, or as a single string. You do not need to quote arguments that contain spaces, when supplying the command as an array. If using the single string format, be careful with spaces. | ||
* @param options {@link RunOptions} for the execution. | ||
*/ | ||
export async function jsonRun<T>( | ||
command: string | SimpleValue[], | ||
options: RunOptions = defaultRunOptions, | ||
): Promise<T> { | ||
return parseJsonSafe(await run(command, options)) as T; | ||
} |