Skip to content

Commit

Permalink
Offer a "oneshot" module that doesn't require initializing a class
Browse files Browse the repository at this point in the history
  • Loading branch information
ericcornelissen committed Aug 19, 2023
1 parent 76fb88c commit 2fec11c
Show file tree
Hide file tree
Showing 9 changed files with 265 additions and 5 deletions.
2 changes: 2 additions & 0 deletions .eslintrc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -741,5 +741,7 @@ ignorePatterns:
- node_modules/
- index.cjs
- index.d.cts
- oneshot.cjs
- oneshot.d.cts
- testing.cjs
- testing.d.cts
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ _reports/
crash-*
index.cjs
index.d.cts
oneshot.cjs
oneshot.d.cts
testing.cjs
testing.d.cts

Expand Down
4 changes: 4 additions & 0 deletions .npmignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@
!index.d.cts
!index.d.ts
!index.js
!oneshot.cjs
!oneshot.d.cts
!oneshot.d.ts
!oneshot.js
!package.json
!LICENSE
!README.md
Expand Down
6 changes: 3 additions & 3 deletions index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
*
* @since 2.0.0
*/
interface ShescapeOptions {
export interface ShescapeOptions {
/**
* Whether or not to protect against flag and option (such as `--verbose`)
* injection
Expand Down Expand Up @@ -67,7 +67,7 @@ interface ShescapeOptions {
* spawnOptions
* );
*/
interface Shescape {
export class Shescape {
/**
* Create a new {@link Shescape} instance.
*
Expand All @@ -77,7 +77,7 @@ interface Shescape {
* @throws {Error} The shell is not supported.
* @since 2.0.0
*/
new (options: ShescapeOptions): Shescape;
new(options: ShescapeOptions): Shescape;

/**
* Take a single value, the argument, and escape any dangerous characters.
Expand Down
108 changes: 108 additions & 0 deletions oneshot.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
/**
* @overview Contains TypeScript type definitions for Shescape's oneshot
* alternative.
* @license MPL-2.0
*/

import type { ShescapeOptions } from "shescape";

/**
* Take a single value, the argument, and escape any dangerous characters.
*
* Non-string inputs will be converted to strings using a `toString()` method.
*
* @example
* import { spawn } from "node:child_process";
* spawn(
* "echo",
* ["Hello", shescape.escape(userInput, { shell: false })],
* null // `options.shell` MUST be falsy
* );
* @param {string} arg The argument to escape.
* @param {object} [options] The escape options.
* @param {boolean} [options.flagProtection=true] Is flag protection enabled.
* @param {boolean | string} [options.shell=true] The shell to escape for.
* @returns {string} The escaped argument.
* @throws {TypeError} The argument is not stringable.
* @throws {Error} The shell is not supported.
* @since 0.1.0
*/
export function escape(arg: string, options?: ShescapeOptions): string;

/**
* Take an array of values, the arguments, and escape any dangerous characters
* in every argument.
*
* Non-array inputs will be converted to one-value arrays and non-string values
* will be converted to strings using a `toString()` method.
*
* @example
* import { spawn } from "node:child_process";
* spawn(
* "echo",
* shescape.escapeAll(["Hello", userInput], { shell: false }),
* null // `options.shell` MUST be falsy
* );
* @param {string[]} args The arguments to escape.
* @param {object} [options] The escape options.
* @param {boolean} [options.flagProtection=true] Is flag protection enabled.
* @param {boolean | string} [options.shell=true] The shell to escape for.
* @returns {string[]} The escaped arguments.
* @throws {TypeError} One of the arguments is not stringable.
* @throws {Error} The shell is not supported.
* @since 1.1.0
*/
export function escapeAll(args: string[], options?: ShescapeOptions): string[];

/**
* Take a single value, the argument, put shell-specific quotes around it and
* escape any dangerous characters.
*
* Non-string inputs will be converted to strings using a `toString()` method.
*
* @example
* import { spawn } from "node:child_process";
* const spawnOptions = { shell: true }; // `options.shell` SHOULD be truthy
* spawn(
* "echo",
* ["Hello", shescape.quote(userInput, { shell: spawnOptions.shell })],
* spawnOptions
* );
* @param {string} arg The argument to quote and escape.
* @param {object} [options] The escape options.
* @param {boolean} [options.flagProtection=true] Is flag protection enabled.
* @param {boolean | string} [options.shell=true] The shell to escape for.
* @returns {string} The quoted and escaped argument.
* @throws {TypeError} The argument is not stringable.
* @throws {Error} The shell is not supported.
* @throws {Error} Quoting is not supported with `shell: false`.
* @since 0.3.0
*/
export function quote(arg: string, options?: ShescapeOptions): string;

/**
* Take an array of values, the arguments, put shell-specific quotes around
* every argument and escape any dangerous characters in every argument.
*
* Non-array inputs will be converted to one-value arrays and non-string
* values will be converted to strings using a `toString()` method.
*
* @example
* import { spawn } from "node:child_process";
* const spawnOptions = { shell: true }; // `options.shell` SHOULD be truthy
* spawn(
* "echo",
* shescape.quoteAll(["Hello", userInput], { shell: spawnOptions.shell }),
* spawnOptions
* );
* @param {string[]} args The arguments to quote and escape.
* @param {object} [options] The escape options.
* @param {boolean} [options.flagProtection=true] Is flag protection enabled.
* @param {boolean | string} [options.shell=true] The shell to escape for.
* @returns {string[]} The quoted and escaped arguments.
* @throws {TypeError} One of the arguments is not stringable.
* @throws {Error} The shell is not supported.
* @throws {Error} Quoting is not supported with `shell: false`.
* @since 0.4.0
*/
export function quoteAll(args: string[], options?: ShescapeOptions): string[];
119 changes: 119 additions & 0 deletions oneshot.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
/**
* @overview Alternative entrypoint for the library requiring no setup.
* @license MPL-2.0
*/

import { Shescape } from "./index.js";

/**
* Take a single value, the argument, and escape any dangerous characters.
*
* Non-string inputs will be converted to strings using a `toString()` method.
*
* @example
* import { spawn } from "node:child_process";
* spawn(
* "echo",
* ["Hello", shescape.escape(userInput, { shell: false })],
* null // `options.shell` MUST be falsy
* );
* @param {string} arg The argument to escape.
* @param {object} [options] The escape options.
* @param {boolean} [options.flagProtection=true] Is flag protection enabled.
* @param {boolean | string} [options.shell=true] The shell to escape for.
* @returns {string} The escaped argument.
* @throws {TypeError} The argument is not stringable.
* @throws {Error} The shell is not supported.
* @since 0.1.0
*/
export function escape(arg, options) {
const shescape = new Shescape(options);
return shescape.escape(arg);
}

/**
* Take an array of values, the arguments, and escape any dangerous characters
* in every argument.
*
* Non-array inputs will be converted to one-value arrays and non-string values
* will be converted to strings using a `toString()` method.
*
* @example
* import { spawn } from "node:child_process";
* spawn(
* "echo",
* shescape.escapeAll(["Hello", userInput], { shell: false }),
* null // `options.shell` MUST be falsy
* );
* @param {string[]} args The arguments to escape.
* @param {object} [options] The escape options.
* @param {boolean} [options.flagProtection=true] Is flag protection enabled.
* @param {boolean | string} [options.shell=true] The shell to escape for.
* @returns {string[]} The escaped arguments.
* @throws {TypeError} One of the arguments is not stringable.
* @throws {Error} The shell is not supported.
* @since 1.1.0
*/
export function escapeAll(args, options) {
const shescape = new Shescape(options);
return shescape.escapeAll(args);
}

/**
* Take a single value, the argument, put shell-specific quotes around it and
* escape any dangerous characters.
*
* Non-string inputs will be converted to strings using a `toString()` method.
*
* @example
* import { spawn } from "node:child_process";
* const spawnOptions = { shell: true }; // `options.shell` SHOULD be truthy
* spawn(
* "echo",
* ["Hello", shescape.quote(userInput, { shell: spawnOptions.shell })],
* spawnOptions
* );
* @param {string} arg The argument to quote and escape.
* @param {object} [options] The escape options.
* @param {boolean} [options.flagProtection=true] Is flag protection enabled.
* @param {boolean | string} [options.shell=true] The shell to escape for.
* @returns {string} The quoted and escaped argument.
* @throws {TypeError} The argument is not stringable.
* @throws {Error} The shell is not supported.
* @throws {Error} Quoting is not supported with `shell: false`.
* @since 0.3.0
*/
export function quote(arg, options) {
const shescape = new Shescape(options);
return shescape.quote(arg);
}

/**
* Take an array of values, the arguments, put shell-specific quotes around
* every argument and escape any dangerous characters in every argument.
*
* Non-array inputs will be converted to one-value arrays and non-string
* values will be converted to strings using a `toString()` method.
*
* @example
* import { spawn } from "node:child_process";
* const spawnOptions = { shell: true }; // `options.shell` SHOULD be truthy
* spawn(
* "echo",
* shescape.quoteAll(["Hello", userInput], { shell: spawnOptions.shell }),
* spawnOptions
* );
* @param {string[]} args The arguments to quote and escape.
* @param {object} [options] The escape options.
* @param {boolean} [options.flagProtection=true] Is flag protection enabled.
* @param {boolean | string} [options.shell=true] The shell to escape for.
* @returns {string[]} The quoted and escaped arguments.
* @throws {TypeError} One of the arguments is not stringable.
* @throws {Error} The shell is not supported.
* @throws {Error} Quoting is not supported with `shell: false`.
* @since 0.4.0
*/
export function quoteAll(args, options) {
const shescape = new Shescape(options);
return shescape.quoteAll(args);
}
12 changes: 11 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,16 @@
"default": "./index.cjs"
}
},
"./oneshot": {
"import": {
"types": "./oneshot.d.ts",
"default": "./oneshot.js"
},
"require": {
"types": "./oneshot.d.cts",
"default": "./oneshot.cjs"
}
},
"./testing": {
"import": {
"types": "./testing.d.ts",
Expand Down Expand Up @@ -127,7 +137,7 @@
"test:e2e": "ava test/e2e/**/*.test.js --timeout 1m",
"test:integration": "ava test/integration/**/*.test.js --timeout 1m",
"test:unit": "ava test/unit/**/*.test.js",
"transpile": "rollup --config rollup.config.js && cp index.d.ts index.d.cts && cp testing.d.ts testing.d.cts",
"transpile": "rollup --config rollup.config.js && cp index.d.ts index.d.cts && cp oneshot.d.ts oneshot.d.cts && cp testing.d.ts testing.d.cts",
"verify": "npm run format:check && npm run license-check && npm run lint && npm run coverage && npm run vet",
"vet": "npm run vet:deps",
"vet:deps": "knip --config .knip.jsonc"
Expand Down
8 changes: 8 additions & 0 deletions rollup.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,14 @@ export default [
},
external,
},
{
input: "oneshot.js",
output: {
file: "oneshot.cjs",
format: "cjs",
},
external,
},
{
input: "testing.js",
output: {
Expand Down
9 changes: 8 additions & 1 deletion script/clean.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,14 @@
import * as fs from "node:fs";
import * as path from "node:path";

const files = ["index.cjs", "index.d.cts", "testing.cjs", "testing.d.cts"];
const files = [
"index.cjs",
"index.d.cts",
"oneshot.cjs",
"oneshot.d.cts",
"testing.cjs",
"testing.d.cts",
];
const folders = ["./.corpus", "./.nyc_output", "./.temp", "./_reports"];

for (const file of files) {
Expand Down

0 comments on commit 2fec11c

Please sign in to comment.