@sectui/operations 0.0.0-stage → 0.1.0

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.
Files changed (147) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +50 -2
  3. package/dist/args.d.ts +8 -0
  4. package/dist/args.js +47 -0
  5. package/dist/args.js.map +1 -0
  6. package/dist/cli-flags.d.ts +7 -0
  7. package/dist/cli-flags.js +28 -0
  8. package/dist/cli-flags.js.map +1 -0
  9. package/dist/cli.d.ts +2 -0
  10. package/dist/cli.js +185 -0
  11. package/dist/cli.js.map +1 -0
  12. package/dist/completions.d.ts +3 -0
  13. package/dist/completions.js +113 -0
  14. package/dist/completions.js.map +1 -0
  15. package/dist/display.d.ts +4 -0
  16. package/dist/display.js +29 -0
  17. package/dist/display.js.map +1 -0
  18. package/dist/errors.d.ts +6 -0
  19. package/dist/errors.js +7 -0
  20. package/dist/errors.js.map +1 -0
  21. package/dist/index.d.ts +4 -0
  22. package/dist/index.js +5 -0
  23. package/dist/index.js.map +1 -0
  24. package/dist/operation.d.ts +64 -0
  25. package/dist/operation.js +5 -0
  26. package/dist/operation.js.map +1 -0
  27. package/dist/operations/base/alphabets.d.ts +28 -0
  28. package/dist/operations/base/alphabets.js +27 -0
  29. package/dist/operations/base/alphabets.js.map +1 -0
  30. package/dist/operations/base/base32.d.ts +33 -0
  31. package/dist/operations/base/base32.js +85 -0
  32. package/dist/operations/base/base32.js.map +1 -0
  33. package/dist/operations/base/base58.d.ts +34 -0
  34. package/dist/operations/base/base58.js +43 -0
  35. package/dist/operations/base/base58.js.map +1 -0
  36. package/dist/operations/base/base62.d.ts +28 -0
  37. package/dist/operations/base/base62.js +43 -0
  38. package/dist/operations/base/base62.js.map +1 -0
  39. package/dist/operations/base/base64.d.ts +19 -0
  40. package/dist/operations/base/base64.js +72 -0
  41. package/dist/operations/base/base64.js.map +1 -0
  42. package/dist/operations/base/base64url.d.ts +15 -0
  43. package/dist/operations/base/base64url.js +44 -0
  44. package/dist/operations/base/base64url.js.map +1 -0
  45. package/dist/operations/base/big-number.d.ts +6 -0
  46. package/dist/operations/base/big-number.js +54 -0
  47. package/dist/operations/base/big-number.js.map +1 -0
  48. package/dist/operations/color/hex-to-rgb.d.ts +14 -0
  49. package/dist/operations/color/hex-to-rgb.js +41 -0
  50. package/dist/operations/color/hex-to-rgb.js.map +1 -0
  51. package/dist/operations/data/json-format.d.ts +20 -0
  52. package/dist/operations/data/json-format.js +33 -0
  53. package/dist/operations/data/json-format.js.map +1 -0
  54. package/dist/operations/data/json.d.ts +20 -0
  55. package/dist/operations/data/json.js +59 -0
  56. package/dist/operations/data/json.js.map +1 -0
  57. package/dist/operations/data/yaml.d.ts +21 -0
  58. package/dist/operations/data/yaml.js +54 -0
  59. package/dist/operations/data/yaml.js.map +1 -0
  60. package/dist/operations/extract/extract.d.ts +55 -0
  61. package/dist/operations/extract/extract.js +129 -0
  62. package/dist/operations/extract/extract.js.map +1 -0
  63. package/dist/operations/hash/bcrypt.d.ts +16 -0
  64. package/dist/operations/hash/bcrypt.js +45 -0
  65. package/dist/operations/hash/bcrypt.js.map +1 -0
  66. package/dist/operations/hash/hashes.d.ts +10 -0
  67. package/dist/operations/hash/hashes.js +29 -0
  68. package/dist/operations/hash/hashes.js.map +1 -0
  69. package/dist/operations/hex/from-hex.d.ts +1 -0
  70. package/dist/operations/hex/from-hex.js +31 -0
  71. package/dist/operations/hex/from-hex.js.map +1 -0
  72. package/dist/operations/hex/to-hex.d.ts +31 -0
  73. package/dist/operations/hex/to-hex.js +44 -0
  74. package/dist/operations/hex/to-hex.js.map +1 -0
  75. package/dist/operations/html/entities.d.ts +2 -0
  76. package/dist/operations/html/entities.js +69 -0
  77. package/dist/operations/html/entities.js.map +1 -0
  78. package/dist/operations/html/html-decode.d.ts +1 -0
  79. package/dist/operations/html/html-decode.js +36 -0
  80. package/dist/operations/html/html-decode.js.map +1 -0
  81. package/dist/operations/html/html-encode.d.ts +8 -0
  82. package/dist/operations/html/html-encode.js +30 -0
  83. package/dist/operations/html/html-encode.js.map +1 -0
  84. package/dist/operations/text/case.d.ts +14 -0
  85. package/dist/operations/text/case.js +85 -0
  86. package/dist/operations/text/case.js.map +1 -0
  87. package/dist/operations/text/count.d.ts +19 -0
  88. package/dist/operations/text/count.js +59 -0
  89. package/dist/operations/text/count.js.map +1 -0
  90. package/dist/operations/text/line-operations.d.ts +48 -0
  91. package/dist/operations/text/line-operations.js +134 -0
  92. package/dist/operations/text/line-operations.js.map +1 -0
  93. package/dist/operations/text/lines.d.ts +13 -0
  94. package/dist/operations/text/lines.js +22 -0
  95. package/dist/operations/text/lines.js.map +1 -0
  96. package/dist/operations/text/text-operations.d.ts +37 -0
  97. package/dist/operations/text/text-operations.js +79 -0
  98. package/dist/operations/text/text-operations.js.map +1 -0
  99. package/dist/operations/url/url-decode.d.ts +8 -0
  100. package/dist/operations/url/url-decode.js +56 -0
  101. package/dist/operations/url/url-decode.js.map +1 -0
  102. package/dist/operations/url/url-encode.d.ts +8 -0
  103. package/dist/operations/url/url-encode.js +37 -0
  104. package/dist/operations/url/url-encode.js.map +1 -0
  105. package/dist/registry.d.ts +395 -0
  106. package/dist/registry.js +131 -0
  107. package/dist/registry.js.map +1 -0
  108. package/dist/template.d.ts +23 -0
  109. package/dist/template.js +198 -0
  110. package/dist/template.js.map +1 -0
  111. package/package.json +67 -4
  112. package/src/args.ts +47 -0
  113. package/src/cli-flags.ts +29 -0
  114. package/src/cli.ts +189 -0
  115. package/src/completions.ts +129 -0
  116. package/src/display.ts +29 -0
  117. package/src/errors.ts +6 -0
  118. package/src/index.ts +4 -0
  119. package/src/operation.ts +62 -0
  120. package/src/operations/base/alphabets.ts +33 -0
  121. package/src/operations/base/base32.ts +84 -0
  122. package/src/operations/base/base58.ts +45 -0
  123. package/src/operations/base/base62.ts +44 -0
  124. package/src/operations/base/base64.ts +76 -0
  125. package/src/operations/base/base64url.ts +45 -0
  126. package/src/operations/base/big-number.ts +54 -0
  127. package/src/operations/color/hex-to-rgb.ts +42 -0
  128. package/src/operations/data/json-format.ts +33 -0
  129. package/src/operations/data/json.ts +53 -0
  130. package/src/operations/data/yaml.ts +56 -0
  131. package/src/operations/extract/extract.ts +135 -0
  132. package/src/operations/hash/bcrypt.ts +44 -0
  133. package/src/operations/hash/hashes.ts +64 -0
  134. package/src/operations/hex/from-hex.ts +31 -0
  135. package/src/operations/hex/to-hex.ts +46 -0
  136. package/src/operations/html/entities.ts +71 -0
  137. package/src/operations/html/html-decode.ts +36 -0
  138. package/src/operations/html/html-encode.ts +31 -0
  139. package/src/operations/text/case.ts +140 -0
  140. package/src/operations/text/count.ts +61 -0
  141. package/src/operations/text/line-operations.ts +144 -0
  142. package/src/operations/text/lines.ts +22 -0
  143. package/src/operations/text/text-operations.ts +85 -0
  144. package/src/operations/url/url-decode.ts +55 -0
  145. package/src/operations/url/url-encode.ts +38 -0
  146. package/src/registry.ts +152 -0
  147. package/src/template.ts +214 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Hadi
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,51 @@
1
- # Temporary Holding Version
1
+ # @sectui/operations
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Data transformation operations (encoding, decoding, hashing, extraction) inspired by [CyberChef](https://github.com/gchq/CyberChef), written in TypeScript for [Node.js](https://nodejs.org) 26 or later. Part of the **sectui** family of security tools for the terminal.
4
+
5
+ ## Install
6
+
7
+ With npm (Node.js 26 or later):
8
+
9
+ ```sh
10
+ npx @sectui/operations to-base64 hello # run without installing
11
+ npm install -g @sectui/operations # then: ops to-base64 hello
12
+ ```
13
+
14
+ With Nix, from the [sectui NUR](https://github.com/sectui/nur):
15
+
16
+ ```sh
17
+ nix run github:sectui/nur#operations -- to-base64 hello
18
+ ```
19
+
20
+ ```nix
21
+ # flake: inputs.nur-sectui.url = "github:sectui/nur";
22
+ environment.systemPackages = [ nur-sectui.packages.${system}.operations ];
23
+
24
+ # or through NUR
25
+ environment.systemPackages = [ pkgs.nur.repos.sectui.operations ];
26
+ ```
27
+
28
+ Each [GitHub release](https://github.com/sectui/operations/releases) also has the CLI as a single file, `node ops-<version>.mjs`.
29
+
30
+ ## Documentation
31
+
32
+ - [Operations](docs/operations.md): every supported operation and its arguments
33
+ - [Library](docs/library.md): using `@sectui/operations` from TypeScript
34
+ - [CLI](docs/cli.md): the `ops` command
35
+ - [Templates](docs/template.md): the `operation{...}` text syntax
36
+
37
+ ## Quick start
38
+
39
+ ```sh
40
+ ops to-base64 hello # aGVsbG8=
41
+ cat token.txt | ops from-base64 | ops url-encode --encode-all
42
+ ops render "hello my name is to-base64{hadi}" # hello my name is aGFkaQ==
43
+ ```
44
+
45
+ ```ts
46
+ import { runText } from "@sectui/operations";
47
+ import { render } from "@sectui/operations/template";
48
+
49
+ runText("to-base64", "hello"); // "aGVsbG8="
50
+ render("hello my name is to-base64{hadi}"); // "hello my name is aGFkaQ=="
51
+ ```
package/dist/args.d.ts ADDED
@@ -0,0 +1,8 @@
1
+ import type { ArgDef, Operation } from "./operation.ts";
2
+ export declare const kebab: (key: string) => string;
3
+ /** Finds an argument by its kebab-case name, as used by the CLI and templates. */
4
+ export declare function findArg(op: Operation, name: string): [key: string, def: ArgDef] | undefined;
5
+ /** Throws a readable error if `value` does not fit the argument definition. */
6
+ export declare function checkArg(def: ArgDef, name: string, value: unknown): void;
7
+ /** Converts a raw CLI or template value to the argument's type, then checks it. */
8
+ export declare function coerceArg(def: ArgDef, name: string, raw: string | boolean): unknown;
package/dist/args.js ADDED
@@ -0,0 +1,47 @@
1
+ export const kebab = (key) => key.replace(/[A-Z]/g, (c) => `-${c.toLowerCase()}`);
2
+ /** Finds an argument by its kebab-case name, as used by the CLI and templates. */
3
+ export function findArg(op, name) {
4
+ return Object.entries(op.args).find(([key]) => kebab(key) === name);
5
+ }
6
+ /** Throws a readable error if `value` does not fit the argument definition. */
7
+ export function checkArg(def, name, value) {
8
+ switch (def.type) {
9
+ case "boolean":
10
+ if (typeof value !== "boolean")
11
+ throw new Error(`"${name}" expects true or false, got ${JSON.stringify(value)}`);
12
+ return;
13
+ case "string":
14
+ if (typeof value !== "string")
15
+ throw new Error(`"${name}" expects a string, got ${JSON.stringify(value)}`);
16
+ return;
17
+ case "number":
18
+ if (typeof value !== "number" || Number.isNaN(value)) {
19
+ throw new Error(`"${name}" expects a number, got ${JSON.stringify(value)}`);
20
+ }
21
+ if ((def.min !== undefined && value < def.min) || (def.max !== undefined && value > def.max)) {
22
+ throw new Error(`"${name}" must be between ${def.min ?? "-∞"} and ${def.max ?? "∞"}, got ${value}`);
23
+ }
24
+ return;
25
+ case "select":
26
+ if (!def.options.some((o) => o.value === value)) {
27
+ const expected = def.options.map((o) => o.value).join(", ");
28
+ throw new Error(`Invalid value ${JSON.stringify(value)} for "${name}" (expected: ${expected})`);
29
+ }
30
+ }
31
+ }
32
+ /** Converts a raw CLI or template value to the argument's type, then checks it. */
33
+ export function coerceArg(def, name, raw) {
34
+ let value = raw;
35
+ if (typeof raw === "string") {
36
+ if (def.type === "boolean" && (raw === "true" || raw === "false"))
37
+ value = raw === "true";
38
+ if (def.type === "number" && raw.trim() !== "")
39
+ value = Number(raw);
40
+ }
41
+ if (def.type === "number" && typeof value !== "number") {
42
+ throw new Error(`"${name}" expects a number, got ${JSON.stringify(raw)}`);
43
+ }
44
+ checkArg(def, name, value);
45
+ return value;
46
+ }
47
+ //# sourceMappingURL=args.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"args.js","sourceRoot":"","sources":["../src/args.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import type { ArgDef, Example, Operation } from "./operation.ts";
2
+ /** The flag users type: booleans that default to true are toggled with `--no-*`. */
3
+ export declare function cliFlag(key: string, def: ArgDef): string;
4
+ /** Quotes a value for a POSIX shell, using $'...' when it contains control characters. */
5
+ export declare function shellQuote(value: string): string;
6
+ /** The CLI invocation of an example, e.g. `ops to-base64 --no-padding hi`. */
7
+ export declare function cliExample(op: Operation, example: Example): string;
@@ -0,0 +1,28 @@
1
+ import { kebab } from "./args.js";
2
+ /** The flag users type: booleans that default to true are toggled with `--no-*`. */
3
+ export function cliFlag(key, def) {
4
+ return def.type === "boolean" && def.default ? `--no-${kebab(key)}` : `--${kebab(key)}`;
5
+ }
6
+ /** Quotes a value for a POSIX shell, using $'...' when it contains control characters. */
7
+ export function shellQuote(value) {
8
+ if (/^[\w\-.,/=+:@%]+$/.test(value))
9
+ return value;
10
+ if (!/[\x00-\x1f\x7f]/.test(value))
11
+ return `'${value.replaceAll("'", `'\\''`)}'`;
12
+ const escaped = value.replace(/[\\'\x00-\x1f\x7f]/g, (c) => c === "\n" ? "\\n" : c === "\t" ? "\\t" : c === "\\" || c === "'" ? `\\${c}` : `\\x${c.charCodeAt(0).toString(16).padStart(2, "0")}`);
13
+ return `$'${escaped}'`;
14
+ }
15
+ /** The CLI invocation of an example, e.g. `ops to-base64 --no-padding hi`. */
16
+ export function cliExample(op, example) {
17
+ const parts = ["ops", op.id];
18
+ for (const [key, value] of Object.entries(example.args ?? {})) {
19
+ const def = op.args[key];
20
+ if (def.type !== "boolean")
21
+ parts.push(`--${kebab(key)}`, shellQuote(String(value)));
22
+ else if (value !== def.default)
23
+ parts.push(cliFlag(key, def));
24
+ }
25
+ parts.push(shellQuote(example.input));
26
+ return parts.join(" ");
27
+ }
28
+ //# sourceMappingURL=cli-flags.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli-flags.js","sourceRoot":"","sources":["../src/cli-flags.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,WAAW,CAAC;AAGlC,oFAAoF;AACpF,MAAM,UAAU,OAAO,CAAC,GAAW,EAAE,GAAW;IAC9C,OAAO,GAAG,CAAC,IAAI,KAAK,SAAS,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;AAC1F,CAAC;AAED,0FAA0F;AAC1F,MAAM,UAAU,UAAU,CAAC,KAAa;IACtC,IAAI,mBAAmB,CAAC,IAAI,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IAClD,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,KAAK,CAAC;QAAE,OAAO,IAAI,KAAK,CAAC,UAAU,CAAC,GAAG,EAAE,OAAO,CAAC,GAAG,CAAC;IACjF,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,qBAAqB,EAAE,CAAC,CAAC,EAAE,EAAE,CACzD,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CACrI,CAAC;IACF,OAAO,KAAK,OAAO,GAAG,CAAC;AACzB,CAAC;AAED,8EAA8E;AAC9E,MAAM,UAAU,UAAU,CAAC,EAAa,EAAE,OAAgB;IACxD,MAAM,KAAK,GAAG,CAAC,KAAK,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC;IAC7B,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,IAAI,EAAE,CAAC,EAAE,CAAC;QAC9D,MAAM,GAAG,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,CAAE,CAAC;QAC1B,IAAI,GAAG,CAAC,IAAI,KAAK,SAAS;YAAE,KAAK,CAAC,IAAI,CAAC,KAAK,KAAK,CAAC,GAAG,CAAC,EAAE,EAAE,UAAU,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;aAChF,IAAI,KAAK,KAAK,GAAG,CAAC,OAAO;YAAE,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;IAChE,CAAC;IACD,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC;IACtC,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACzB,CAAC"}
package/dist/cli.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/cli.js ADDED
@@ -0,0 +1,185 @@
1
+ #!/usr/bin/env node
2
+ import { readFileSync } from "node:fs";
3
+ import { buffer } from "node:stream/consumers";
4
+ import { parseArgs } from "node:util";
5
+ import { coerceArg, kebab } from "./args.js";
6
+ import { cliExample, cliFlag } from "./cli-flags.js";
7
+ import { completions, SHELLS } from "./completions.js";
8
+ import { hexdump, isPrintable } from "./display.js";
9
+ import { OperationError } from "./errors.js";
10
+ import { getOperation, isOperationId, operations, run } from "./registry.js";
11
+ import { renderBytes } from "./template.js";
12
+ // Read at run time: the same relative path works from src/ and from the built dist/.
13
+ const pkg = typeof BUNDLED_PACKAGE !== "undefined"
14
+ ? BUNDLED_PACKAGE
15
+ : JSON.parse(readFileSync(new URL("../package.json", import.meta.url), "utf8"));
16
+ class UsageError extends Error {
17
+ }
18
+ const USAGE = `ops ${pkg.version} - ${pkg.description}
19
+
20
+ Usage:
21
+ ops <operation> [options] [input] Apply an operation (input from stdin if omitted)
22
+ ops render [text] Replace operation{...} blocks in text
23
+ ops list List available operations
24
+ ops help [operation] Show help
25
+ ops completions <${SHELLS.join("|")}> Print a shell completion script
26
+
27
+ Global options:
28
+ --raw Write binary output to the terminal as is (by default it is shown as a hexdump)
29
+ --help Show help
30
+
31
+ Examples:
32
+ ops to-base64 hello
33
+ echo -n aGVsbG8= | ops from-base64
34
+ cat token.txt | ops from-base64 | ops url-encode --encode-all
35
+ ops render "hello my name is to-base64{hadi}"`;
36
+ const RENDER_HELP = `ops render [--raw] [text]
37
+
38
+ Replaces every operation{...} block in the text (or stdin) with the result of the operation.
39
+ Arguments go between parentheses: to-hex(delimiter=colon){hadi}
40
+
41
+ Example:
42
+ ops render "hello my name is to-base64{hadi}"`;
43
+ function describeArg(key, def) {
44
+ const value = def.type === "select" ? ` <${def.options.map((o) => o.value).join("|")}>` : def.type === "boolean" ? "" : ` <${def.type}>`;
45
+ const details = [def.name, def.description, def.type === "boolean" ? undefined : `default: ${def.default}`].filter(Boolean).join(". ");
46
+ return ` ${cliFlag(key, def)}${value}\n ${details}`;
47
+ }
48
+ function operationHelp(op) {
49
+ const lines = [`${op.id} - ${op.name}`, "", op.description];
50
+ if (op.aliases?.length)
51
+ lines.push("", `Aliases: ${op.aliases.join(", ")}`);
52
+ if (op.inverse)
53
+ lines.push(`Inverse: ${op.inverse}`);
54
+ const args = Object.entries(op.args);
55
+ if (args.length)
56
+ lines.push("", "Options:", ...args.map(([key, def]) => describeArg(key, def)));
57
+ lines.push("", "Examples:", ...op.examples.map((ex) => ` ${cliExample(op, ex)}\n -> ${JSON.stringify(ex.output)}`));
58
+ return lines.join("\n");
59
+ }
60
+ function list() {
61
+ const byCategory = Map.groupBy(operations, (op) => op.category);
62
+ const width = Math.max(...operations.map((op) => op.id.length));
63
+ return [...byCategory]
64
+ .map(([category, ops]) => [category, ...ops.map((op) => ` ${op.id.padEnd(width)} ${op.name}`)].join("\n"))
65
+ .join("\n\n");
66
+ }
67
+ /** Extracts the global flags, which are only recognized before a `--` separator. */
68
+ function splitGlobalFlags(argv) {
69
+ const end = argv.includes("--") ? argv.indexOf("--") : argv.length;
70
+ const isGlobal = (arg, i) => i < end && ["--raw", "--help", "-h"].includes(arg);
71
+ return {
72
+ raw: argv.some((arg, i) => isGlobal(arg, i) && arg === "--raw"),
73
+ help: argv.some((arg, i) => isGlobal(arg, i) && arg !== "--raw"),
74
+ rest: argv.filter((arg, i) => !isGlobal(arg, i)),
75
+ };
76
+ }
77
+ function parse(argv, options, helpHint) {
78
+ try {
79
+ return parseArgs({ args: argv, options, allowPositionals: true, allowNegative: true, strict: true });
80
+ }
81
+ catch (error) {
82
+ throw new UsageError(`${error.message} (see: ${helpHint})`);
83
+ }
84
+ }
85
+ function parseOperationArgs(op, argv) {
86
+ const options = {};
87
+ for (const [key, def] of Object.entries(op.args)) {
88
+ options[kebab(key)] = { type: def.type === "boolean" ? "boolean" : "string" };
89
+ }
90
+ const parsed = parse(argv, options, `ops help ${op.id}`);
91
+ const args = {};
92
+ for (const [key, def] of Object.entries(op.args)) {
93
+ const raw = parsed.values[kebab(key)];
94
+ if (raw === undefined || Array.isArray(raw))
95
+ continue;
96
+ try {
97
+ args[key] = coerceArg(def, `--${kebab(key)}`, raw);
98
+ }
99
+ catch (error) {
100
+ throw new UsageError(error.message);
101
+ }
102
+ }
103
+ return { args, positionals: parsed.positionals };
104
+ }
105
+ async function readInput(positionals) {
106
+ if (positionals.length)
107
+ return new TextEncoder().encode(positionals.join(" "));
108
+ if (process.stdin.isTTY)
109
+ throw new UsageError("No input: pass it as an argument or pipe it through stdin");
110
+ return new Uint8Array(await buffer(process.stdin));
111
+ }
112
+ async function write(output, { raw = false } = {}) {
113
+ let bytes = typeof output === "string" ? new TextEncoder().encode(output) : output;
114
+ if (process.stdout.isTTY) {
115
+ // Decoded data may hold escape sequences that would drive the terminal.
116
+ if (!raw && !isPrintable(bytes)) {
117
+ console.error("ops: output contains binary data or control characters, shown as a hexdump (use --raw to print it as is)");
118
+ bytes = new TextEncoder().encode(hexdump(bytes));
119
+ }
120
+ // Keep the shell prompt off the output line, without altering piped bytes.
121
+ bytes = new Uint8Array([...bytes, 0x0a]);
122
+ }
123
+ await new Promise((resolve, reject) => process.stdout.write(bytes, (error) => (error ? reject(error) : resolve())));
124
+ }
125
+ async function main(argv) {
126
+ const [command, ...args] = argv;
127
+ const { raw, help, rest } = splitGlobalFlags(args);
128
+ if (command === undefined || command === "--help" || command === "-h")
129
+ return write(USAGE);
130
+ if (command === "--version" || command === "-v")
131
+ return write(pkg.version);
132
+ if (command === "list")
133
+ return write(list());
134
+ if (command === "help") {
135
+ const id = rest[0];
136
+ if (id === undefined)
137
+ return write(USAGE);
138
+ if (id === "render")
139
+ return write(RENDER_HELP);
140
+ if (!isOperationId(id))
141
+ throw new UsageError(`Unknown operation "${id}" (see: ops list)`);
142
+ return write(operationHelp(getOperation(id)));
143
+ }
144
+ if (command === "completions") {
145
+ const shell = rest[0];
146
+ if (!SHELLS.includes(shell))
147
+ throw new UsageError(`Expected a shell: ${SHELLS.join(", ")}`);
148
+ return write(completions(shell));
149
+ }
150
+ if (command === "render") {
151
+ if (help)
152
+ return write(RENDER_HELP);
153
+ const { positionals } = parse(rest, {}, "ops help render");
154
+ const input = await readInput(positionals);
155
+ return write(renderBytes(new TextDecoder().decode(input)), { raw });
156
+ }
157
+ if (!isOperationId(command))
158
+ throw new UsageError(`Unknown operation "${command}" (see: ops list)`);
159
+ const op = getOperation(command);
160
+ if (help)
161
+ return write(operationHelp(op));
162
+ const { args: opArgs, positionals } = parseOperationArgs(op, rest);
163
+ return write(run(command, await readInput(positionals), opArgs), { raw });
164
+ }
165
+ if (import.meta.main) {
166
+ // The reader went away (e.g. `ops ... | head`): stop quietly like other Unix tools.
167
+ process.stdout.on("error", (error) => {
168
+ if (error.code === "EPIPE")
169
+ process.exit(0);
170
+ throw error;
171
+ });
172
+ try {
173
+ await main(process.argv.slice(2));
174
+ }
175
+ catch (error) {
176
+ // The reader went away (e.g. `ops ... | head`): stop quietly like other Unix tools.
177
+ if (error.code === "EPIPE")
178
+ process.exit(0);
179
+ const message = error instanceof Error ? error.message : String(error);
180
+ const prefix = error instanceof OperationError && error.operation ? `${error.operation}: ` : "";
181
+ console.error(`ops: ${prefix}${message}`);
182
+ process.exit(error instanceof UsageError ? 2 : 1);
183
+ }
184
+ }
185
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export declare const SHELLS: readonly ["bash", "zsh", "fish"];
2
+ export type Shell = (typeof SHELLS)[number];
3
+ export declare function completions(shell: Shell): string;
@@ -0,0 +1,113 @@
1
+ import { cliFlag } from "./cli-flags.js";
2
+ import { operations } from "./registry.js";
3
+ export const SHELLS = ["bash", "zsh", "fish"];
4
+ const COMMANDS = [
5
+ ["list", "List available operations"],
6
+ ["help", "Show help"],
7
+ ["render", "Replace operation{...} blocks in text"],
8
+ ["completions", "Print a shell completion script"],
9
+ ];
10
+ const GLOBAL_FLAGS = [
11
+ ["--raw", "Write raw bytes even to a terminal"],
12
+ ["--help", "Show help"],
13
+ ];
14
+ const ops = operations;
15
+ /** Wraps a string in single quotes for any POSIX-like shell. */
16
+ const sq = (s) => `'${s.replaceAll("'", `'\\''`)}'`;
17
+ function flagsOf(op) {
18
+ return Object.entries(op.args).map(([key, def]) => ({
19
+ flag: cliFlag(key, def),
20
+ description: def.name,
21
+ values: def.type === "select" ? def.options.map((o) => o.value) : def.type === "boolean" ? undefined : [],
22
+ }));
23
+ }
24
+ function bash() {
25
+ const ids = ops.map((op) => op.id).join(" ");
26
+ const cases = ops.map((op) => {
27
+ const flags = flagsOf(op);
28
+ const valueCases = flags
29
+ .filter((f) => f.values)
30
+ .map((f) => ` ${f.flag}) COMPREPLY=($(compgen -W ${sq(f.values.join(" "))} -- "$cur")); return ;;`);
31
+ const all = [...flags.map((f) => f.flag), ...GLOBAL_FLAGS.map(([f]) => f)].join(" ");
32
+ return [
33
+ ` ${op.id})`,
34
+ ...(valueCases.length ? [' case "$prev" in', ...valueCases, " esac"] : []),
35
+ ` [[ $cur == -* ]] && COMPREPLY=($(compgen -W ${sq(all)} -- "$cur"))`,
36
+ " ;;",
37
+ ].join("\n");
38
+ });
39
+ return `# bash completion for ops
40
+ _ops() {
41
+ local cur="\${COMP_WORDS[COMP_CWORD]}" prev="\${COMP_WORDS[COMP_CWORD-1]}"
42
+ if (( COMP_CWORD == 1 )); then
43
+ COMPREPLY=($(compgen -W ${sq(`${COMMANDS.map(([c]) => c).join(" ")} ${ids}`)} -- "$cur"))
44
+ return
45
+ fi
46
+ case "\${COMP_WORDS[1]}" in
47
+ help) (( COMP_CWORD == 2 )) && COMPREPLY=($(compgen -W ${sq(ids)} -- "$cur")) ;;
48
+ completions) (( COMP_CWORD == 2 )) && COMPREPLY=($(compgen -W ${sq(SHELLS.join(" "))} -- "$cur")) ;;
49
+ render) [[ $cur == -* ]] && COMPREPLY=($(compgen -W ${sq(GLOBAL_FLAGS.map(([f]) => f).join(" "))} -- "$cur")) ;;
50
+ ${cases.join("\n")}
51
+ esac
52
+ }
53
+ complete -F _ops ops
54
+ `;
55
+ }
56
+ function zsh() {
57
+ // Escapes characters that are special in _describe entries and _arguments specs.
58
+ const esc = (s) => s.replace(/([:[\]\\])/g, "\\$1");
59
+ const describe = (items) => items.map(([n, d]) => sq(`${esc(n)}:${esc(d)}`)).join(" ");
60
+ const globals = GLOBAL_FLAGS.map(([f, d]) => sq(`${f}[${esc(d)}]`)).join(" ");
61
+ const cases = ops.map((op) => {
62
+ const specs = flagsOf(op).map((f) => {
63
+ const action = f.values === undefined ? "" : f.values.length ? `:value:(${f.values.join(" ")})` : ":value:";
64
+ return sq(`${f.flag}[${esc(f.description)}]${action}`);
65
+ });
66
+ return ` ${op.id}) _arguments ${[...specs, globals, sq("*:input:")].join(" ")} ;;`;
67
+ });
68
+ return `#compdef ops
69
+ _ops() {
70
+ if (( CURRENT == 2 )); then
71
+ local -a commands=(${describe([...COMMANDS, ...ops.map((op) => [op.id, op.name])])})
72
+ _describe command commands
73
+ return
74
+ fi
75
+ local cmd=$words[2]
76
+ shift words
77
+ (( CURRENT-- ))
78
+ case $cmd in
79
+ help) (( CURRENT == 2 )) && { local -a ids=(${describe(ops.map((op) => [op.id, op.name]))}); _describe operation ids } ;;
80
+ completions) (( CURRENT == 2 )) && _values shell ${SHELLS.join(" ")} ;;
81
+ render) _arguments ${globals} ${sq("*:text:")} ;;
82
+ ${cases.join("\n")}
83
+ esac
84
+ }
85
+ if [[ $funcstack[1] == _ops ]]; then _ops "$@"; else compdef _ops ops; fi
86
+ `;
87
+ }
88
+ function fish() {
89
+ const lines = ["# fish completion for ops", "complete -c ops -f"];
90
+ for (const [command, description] of COMMANDS) {
91
+ lines.push(`complete -c ops -n __fish_use_subcommand -a ${command} -d ${sq(description)}`);
92
+ }
93
+ for (const op of ops)
94
+ lines.push(`complete -c ops -n __fish_use_subcommand -a ${op.id} -d ${sq(op.name)}`);
95
+ const ids = sq(ops.map((op) => op.id).join(" "));
96
+ lines.push(`complete -c ops -n '__fish_seen_subcommand_from help' -a ${ids}`);
97
+ lines.push(`complete -c ops -n '__fish_seen_subcommand_from completions' -a ${sq(SHELLS.join(" "))}`);
98
+ const withGlobals = ["render", ...ops.map((op) => op.id)].join(" ");
99
+ for (const [flag, description] of GLOBAL_FLAGS) {
100
+ lines.push(`complete -c ops -n ${sq(`__fish_seen_subcommand_from ${withGlobals}`)} -l ${flag.slice(2)} -d ${sq(description)}`);
101
+ }
102
+ for (const op of ops) {
103
+ for (const f of flagsOf(op)) {
104
+ const values = f.values === undefined ? "" : f.values.length ? ` -x -a ${sq(f.values.join(" "))}` : " -x";
105
+ lines.push(`complete -c ops -n ${sq(`__fish_seen_subcommand_from ${op.id}`)} -l ${f.flag.slice(2)}${values} -d ${sq(f.description)}`);
106
+ }
107
+ }
108
+ return `${lines.join("\n")}\n`;
109
+ }
110
+ export function completions(shell) {
111
+ return { bash, zsh, fish }[shell]();
112
+ }
113
+ //# sourceMappingURL=completions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"completions.js","sourceRoot":"","sources":["../src/completions.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ /** True if the bytes are valid UTF-8 text without characters that can control a terminal. */
2
+ export declare function isPrintable(bytes: Uint8Array): boolean;
3
+ /** Canonical hex+ASCII dump, like `hexdump -C`. */
4
+ export declare function hexdump(bytes: Uint8Array): string;
@@ -0,0 +1,29 @@
1
+ // C0 controls except tab/LF/CR, DEL, C1 controls (e.g. U+009B is a CSI on some terminals),
2
+ // and bidi overrides that can make text display differently from its content.
3
+ const UNSAFE_CHARS = /[\u0000-\u0008\u000b\u000c\u000e-\u001f\u007f-\u009f‪-‮⁦-⁩]/;
4
+ /** True if the bytes are valid UTF-8 text without characters that can control a terminal. */
5
+ export function isPrintable(bytes) {
6
+ let text;
7
+ try {
8
+ text = new TextDecoder("utf-8", { fatal: true }).decode(bytes);
9
+ }
10
+ catch {
11
+ return false;
12
+ }
13
+ return !UNSAFE_CHARS.test(text);
14
+ }
15
+ /** Canonical hex+ASCII dump, like `hexdump -C`. */
16
+ export function hexdump(bytes) {
17
+ const lines = [];
18
+ for (let offset = 0; offset < bytes.length; offset += 16) {
19
+ const row = bytes.subarray(offset, offset + 16);
20
+ const hex = [...row].map((b) => b.toString(16).padStart(2, "0"));
21
+ const left = hex.slice(0, 8).join(" ");
22
+ const right = hex.slice(8).join(" ");
23
+ const ascii = [...row].map((b) => (b >= 0x20 && b < 0x7f ? String.fromCharCode(b) : ".")).join("");
24
+ lines.push(`${offset.toString(16).padStart(8, "0")} ${left.padEnd(23)} ${right.padEnd(23)} |${ascii}|`);
25
+ }
26
+ lines.push(bytes.length.toString(16).padStart(8, "0"));
27
+ return lines.join("\n");
28
+ }
29
+ //# sourceMappingURL=display.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"display.js","sourceRoot":"","sources":["../src/display.ts"],"names":[],"mappings":"AAAA,2FAA2F;AAC3F,8EAA8E;AAC9E,MAAM,YAAY,GAAG,6DAA6D,CAAC;AAEnF,6FAA6F;AAC7F,MAAM,UAAU,WAAW,CAAC,KAAiB;IAC3C,IAAI,IAAY,CAAC;IACjB,IAAI,CAAC;QACH,IAAI,GAAG,IAAI,WAAW,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACjE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;IACD,OAAO,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAClC,CAAC;AAED,mDAAmD;AACnD,MAAM,UAAU,OAAO,CAAC,KAAiB;IACvC,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,IAAI,MAAM,GAAG,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC,MAAM,EAAE,MAAM,IAAI,EAAE,EAAE,CAAC;QACzD,MAAM,GAAG,GAAG,KAAK,CAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,EAAE,CAAC,CAAC;QAChD,MAAM,GAAG,GAAG,CAAC,GAAG,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;QACjE,MAAM,IAAI,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACvC,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACrC,MAAM,KAAK,GAAG,CAAC,GAAG,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,IAAI,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACnG,KAAK,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,KAAK,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,KAAK,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,KAAK,GAAG,CAAC,CAAC;IAC7G,CAAC;IACD,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;IACvD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC"}
@@ -0,0 +1,6 @@
1
+ /** Error raised when an operation cannot process its input or arguments. */
2
+ export declare class OperationError extends Error {
3
+ name: string;
4
+ /** Id of the failing operation, set by `run`. */
5
+ operation?: string;
6
+ }
package/dist/errors.js ADDED
@@ -0,0 +1,7 @@
1
+ /** Error raised when an operation cannot process its input or arguments. */
2
+ export class OperationError extends Error {
3
+ name = "OperationError";
4
+ /** Id of the failing operation, set by `run`. */
5
+ operation;
6
+ }
7
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAC5E,MAAM,OAAO,cAAe,SAAQ,KAAK;IAC9B,IAAI,GAAG,gBAAgB,CAAC;IACjC,iDAAiD;IACjD,SAAS,CAAU;CACpB"}
@@ -0,0 +1,4 @@
1
+ export * from "./display.ts";
2
+ export * from "./errors.ts";
3
+ export * from "./operation.ts";
4
+ export * from "./registry.ts";
package/dist/index.js ADDED
@@ -0,0 +1,5 @@
1
+ export * from "./display.js";
2
+ export * from "./errors.js";
3
+ export * from "./operation.js";
4
+ export * from "./registry.js";
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAC5B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC"}