shell-dsl 0.0.39 → 0.0.41
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/README.md +183 -3
- package/dist/cjs/package.json +1 -1
- package/dist/cjs/src/commands/exit/exit.cjs +84 -0
- package/dist/cjs/src/commands/exit/exit.cjs.map +10 -0
- package/dist/cjs/src/commands/index.cjs +18 -2
- package/dist/cjs/src/commands/index.cjs.map +3 -3
- package/dist/cjs/src/commands/sh/sh.cjs +134 -0
- package/dist/cjs/src/commands/sh/sh.cjs.map +10 -0
- package/dist/cjs/src/index.cjs +9 -1
- package/dist/cjs/src/index.cjs.map +3 -3
- package/dist/cjs/src/input-analysis.cjs +154 -0
- package/dist/cjs/src/input-analysis.cjs.map +10 -0
- package/dist/cjs/src/interpreter/context.cjs +6 -1
- package/dist/cjs/src/interpreter/context.cjs.map +3 -3
- package/dist/cjs/src/interpreter/index.cjs +2 -1
- package/dist/cjs/src/interpreter/index.cjs.map +3 -3
- package/dist/cjs/src/interpreter/interpreter.cjs +434 -82
- package/dist/cjs/src/interpreter/interpreter.cjs.map +3 -3
- package/dist/cjs/src/io/async-queue.cjs +105 -0
- package/dist/cjs/src/io/async-queue.cjs.map +10 -0
- package/dist/cjs/src/io/index.cjs +4 -1
- package/dist/cjs/src/io/index.cjs.map +3 -3
- package/dist/cjs/src/io/input-controller.cjs +113 -0
- package/dist/cjs/src/io/input-controller.cjs.map +10 -0
- package/dist/cjs/src/io/stdout.cjs +9 -6
- package/dist/cjs/src/io/stdout.cjs.map +3 -3
- package/dist/cjs/src/lexer/lexer.cjs +13 -1
- package/dist/cjs/src/lexer/lexer.cjs.map +3 -3
- package/dist/cjs/src/parser/parser.cjs +11 -1
- package/dist/cjs/src/parser/parser.cjs.map +3 -3
- package/dist/cjs/src/shell-dsl.cjs +13 -5
- package/dist/cjs/src/shell-dsl.cjs.map +3 -3
- package/dist/cjs/src/shell-session.cjs +128 -0
- package/dist/cjs/src/shell-session.cjs.map +10 -0
- package/dist/cjs/src/types.cjs.map +2 -2
- package/dist/mjs/package.json +1 -1
- package/dist/mjs/src/commands/exit/exit.mjs +44 -0
- package/dist/mjs/src/commands/exit/exit.mjs.map +10 -0
- package/dist/mjs/src/commands/index.mjs +18 -2
- package/dist/mjs/src/commands/index.mjs.map +3 -3
- package/dist/mjs/src/commands/sh/sh.mjs +94 -0
- package/dist/mjs/src/commands/sh/sh.mjs.map +10 -0
- package/dist/mjs/src/index.mjs +19 -3
- package/dist/mjs/src/index.mjs.map +3 -3
- package/dist/mjs/src/input-analysis.mjs +114 -0
- package/dist/mjs/src/input-analysis.mjs.map +10 -0
- package/dist/mjs/src/interpreter/context.mjs +6 -1
- package/dist/mjs/src/interpreter/context.mjs.map +3 -3
- package/dist/mjs/src/interpreter/index.mjs +3 -2
- package/dist/mjs/src/interpreter/index.mjs.map +2 -2
- package/dist/mjs/src/interpreter/interpreter.mjs +434 -82
- package/dist/mjs/src/interpreter/interpreter.mjs.map +3 -3
- package/dist/mjs/src/io/async-queue.mjs +64 -0
- package/dist/mjs/src/io/async-queue.mjs.map +10 -0
- package/dist/mjs/src/io/index.mjs +4 -1
- package/dist/mjs/src/io/index.mjs.map +3 -3
- package/dist/mjs/src/io/input-controller.mjs +72 -0
- package/dist/mjs/src/io/input-controller.mjs.map +10 -0
- package/dist/mjs/src/io/stdout.mjs +9 -6
- package/dist/mjs/src/io/stdout.mjs.map +3 -3
- package/dist/mjs/src/lexer/lexer.mjs +13 -1
- package/dist/mjs/src/lexer/lexer.mjs.map +3 -3
- package/dist/mjs/src/parser/parser.mjs +11 -1
- package/dist/mjs/src/parser/parser.mjs.map +3 -3
- package/dist/mjs/src/shell-dsl.mjs +13 -5
- package/dist/mjs/src/shell-dsl.mjs.map +3 -3
- package/dist/mjs/src/shell-session.mjs +88 -0
- package/dist/mjs/src/shell-session.mjs.map +10 -0
- package/dist/mjs/src/types.mjs.map +2 -2
- package/dist/types/src/commands/exit/exit.d.ts +2 -0
- package/dist/types/src/commands/index.d.ts +2 -0
- package/dist/types/src/commands/sh/sh.d.ts +5 -0
- package/dist/types/src/index.d.ts +6 -3
- package/dist/types/src/input-analysis.d.ts +14 -0
- package/dist/types/src/interpreter/context.d.ts +4 -1
- package/dist/types/src/interpreter/index.d.ts +1 -1
- package/dist/types/src/interpreter/interpreter.d.ts +36 -1
- package/dist/types/src/io/async-queue.d.ts +12 -0
- package/dist/types/src/io/index.d.ts +1 -0
- package/dist/types/src/io/input-controller.d.ts +15 -0
- package/dist/types/src/io/stdout.d.ts +4 -3
- package/dist/types/src/shell-dsl.d.ts +2 -0
- package/dist/types/src/shell-session.d.ts +23 -0
- package/dist/types/src/types.d.ts +52 -0
- package/package.json +1 -1
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/shell-dsl.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
|
-
"import type {
|
|
5
|
+
"import type {\n ShellConfig,\n Command,\n VirtualFS,\n ExecResult,\n RedirectObjectMap,\n TerminalInfo,\n ShellCommandFallback,\n} from \"./types.cjs\";\nimport { isRawValue, isRedirectObject } from \"./types.cjs\";\nimport type { Token } from \"./lexer/tokens.cjs\";\nimport type { ASTNode } from \"./parser/ast.cjs\";\nimport { Lexer } from \"./lexer/lexer.cjs\";\nimport { Parser } from \"./parser/parser.cjs\";\nimport { Interpreter } from \"./interpreter/interpreter.cjs\";\nimport { ShellPromise } from \"./shell-promise.cjs\";\nimport { escape, escapeForInterpolation } from \"./utils/escape.cjs\";\n\nexport interface Program {\n ast: ASTNode;\n source: string;\n}\n\nexport class ShellDSL {\n private fs: VirtualFS;\n private initialCwd: string;\n private initialEnv: Record<string, string>;\n private currentCwd: string;\n private currentEnv: Record<string, string>;\n private commands: Record<string, Command>;\n private shouldThrow: boolean = true;\n private isTTY: boolean;\n private terminal: TerminalInfo;\n private externalCommand?: ShellCommandFallback;\n\n constructor(config: ShellConfig) {\n this.fs = config.fs;\n this.initialCwd = config.cwd;\n this.initialEnv = { ...config.env };\n this.currentCwd = config.cwd;\n this.currentEnv = { ...config.env };\n this.commands = config.commands;\n this.terminal = config.terminal ?? { isTTY: config.isTTY ?? false };\n this.isTTY = this.terminal.isTTY;\n this.externalCommand = config.externalCommand;\n }\n\n // Template tag function\n tag(strings: TemplateStringsArray, ...values: unknown[]): ShellPromise {\n // Build the command string with escaped interpolations\n let source = strings[0] ?? \"\";\n const redirectObjects: RedirectObjectMap = {};\n let objIndex = 0;\n\n for (let i = 0; i < values.length; i++) {\n const value = values[i];\n const precedingString = strings[i] ?? \"\";\n\n if (isRawValue(value)) {\n source += value.raw;\n } else if (this.isRedirectTarget(precedingString, value)) {\n // Value appears after a redirect operator - store as redirect object\n const marker = `__REDIR_OBJ_${objIndex++}__`;\n redirectObjects[marker] = value as Buffer | Blob | Response | string;\n source += marker;\n } else {\n source += escapeForInterpolation(value);\n }\n source += strings[i + 1] ?? \"\";\n }\n\n return this.createPromise(source, { redirectObjects });\n }\n\n private isRedirectTarget(precedingString: string, value: unknown): boolean {\n // Check if value is a redirect object type AND appears after redirect operator\n if (!isRedirectObject(value) || isRawValue(value)) {\n return false;\n }\n // Check if preceding string ends with redirect operator\n const trimmed = precedingString.trimEnd();\n const afterRedirectOp = /(<|>|>>|2>|2>>|&>|&>>)\\s*$/.test(trimmed);\n\n if (!afterRedirectOp) {\n return false;\n }\n\n // Buffer, Blob, Response are always treated as redirect objects\n if (Buffer.isBuffer(value) || value instanceof Blob || value instanceof Response) {\n return true;\n }\n\n // For strings after input redirect (<), treat as content per spec\n // For strings after output redirect (>), they must be Buffers\n if (typeof value === \"string\") {\n // Only input redirection supports string content\n return /<\\s*$/.test(trimmed);\n }\n\n return false;\n }\n\n private createPromise(source: string, options?: { cwd?: string; env?: Record<string, string>; shouldThrow?: boolean; redirectObjects?: RedirectObjectMap }): ShellPromise {\n const shell = this;\n\n return new ShellPromise({\n execute: async (overrides) => {\n const cwd = overrides?.cwd ?? options?.cwd ?? shell.currentCwd;\n const env = { ...shell.currentEnv, ...options?.env, ...overrides?.env };\n\n const interpreter = new Interpreter({\n fs: shell.fs,\n cwd,\n env,\n commands: shell.commands,\n redirectObjects: options?.redirectObjects,\n terminal: shell.terminal,\n externalCommand: shell.externalCommand,\n });\n\n const tokens = shell.lex(source);\n const ast = shell.parse(tokens);\n return interpreter.execute(ast);\n },\n cwdOverride: options?.cwd,\n envOverride: options?.env,\n shouldThrow: options?.shouldThrow ?? this.shouldThrow,\n });\n }\n\n // Global defaults\n cwd(path: string): void {\n this.currentCwd = path;\n }\n\n env(vars: Record<string, string>): void {\n Object.assign(this.currentEnv, vars);\n }\n\n throws(enable: boolean): void {\n this.shouldThrow = enable;\n }\n\n resetCwd(): void {\n this.currentCwd = this.initialCwd;\n }\n\n resetEnv(): void {\n this.currentEnv = { ...this.initialEnv };\n }\n\n // Utility\n escape(str: string): string {\n return escape(str);\n }\n\n // Low-level API\n lex(source: string): Token[] {\n return new Lexer(source, { preserveNewlines: true }).tokenize();\n }\n\n parse(tokens: Token[]): ASTNode {\n return new Parser(tokens).parse();\n }\n\n compile(ast: ASTNode): Program {\n // For now, the \"program\" is just the AST with source reconstruction\n return {\n ast,\n source: \"\", // Could reconstruct source from AST if needed\n };\n }\n\n async run(program: Program): Promise<ExecResult> {\n const interpreter = new Interpreter({\n fs: this.fs,\n cwd: this.currentCwd,\n env: this.currentEnv,\n commands: this.commands,\n terminal: this.terminal,\n externalCommand: this.externalCommand,\n });\n\n return interpreter.execute(program.ast);\n }\n}\n\n// Factory function that returns a callable template tag\nexport function createShellDSL(config: ShellConfig): ShellDSL & ((strings: TemplateStringsArray, ...values: unknown[]) => ShellPromise) {\n const shell = new ShellDSL(config);\n\n // Create a function that acts as both tag and shell instance\n const tag = (strings: TemplateStringsArray, ...values: unknown[]) => {\n return shell.tag(strings, ...values);\n };\n\n // Copy all properties and methods from shell to tag function\n Object.setPrototypeOf(tag, ShellDSL.prototype);\n Object.assign(tag, {\n fs: (shell as any).fs,\n initialCwd: (shell as any).initialCwd,\n initialEnv: (shell as any).initialEnv,\n currentCwd: (shell as any).currentCwd,\n currentEnv: (shell as any).currentEnv,\n commands: (shell as any).commands,\n shouldThrow: (shell as any).shouldThrow,\n isTTY: (shell as any).isTTY,\n terminal: (shell as any).terminal,\n externalCommand: (shell as any).externalCommand,\n });\n\n // Bind methods\n (tag as any).cwd = shell.cwd.bind(shell);\n (tag as any).env = shell.env.bind(shell);\n (tag as any).throws = shell.throws.bind(shell);\n (tag as any).resetCwd = shell.resetCwd.bind(shell);\n (tag as any).resetEnv = shell.resetEnv.bind(shell);\n (tag as any).escape = shell.escape.bind(shell);\n (tag as any).lex = shell.lex.bind(shell);\n (tag as any).parse = shell.parse.bind(shell);\n (tag as any).compile = shell.compile.bind(shell);\n (tag as any).run = shell.run.bind(shell);\n (tag as any).tag = shell.tag.bind(shell);\n\n return tag as ShellDSL & ((strings: TemplateStringsArray, ...values: unknown[]) => ShellPromise);\n}\n"
|
|
6
6
|
],
|
|
7
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
8
|
-
"debugId": "
|
|
7
|
+
"mappings": "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",
|
|
8
|
+
"debugId": "ECF0DF1AD7027E4E64756E2164756E21",
|
|
9
9
|
"names": []
|
|
10
10
|
}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
5
|
+
function __accessProp(key) {
|
|
6
|
+
return this[key];
|
|
7
|
+
}
|
|
8
|
+
var __toCommonJS = (from) => {
|
|
9
|
+
var entry = (__moduleCache ??= new WeakMap).get(from), desc;
|
|
10
|
+
if (entry)
|
|
11
|
+
return entry;
|
|
12
|
+
entry = __defProp({}, "__esModule", { value: true });
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (var key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(entry, key))
|
|
16
|
+
__defProp(entry, key, {
|
|
17
|
+
get: __accessProp.bind(from, key),
|
|
18
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
__moduleCache.set(from, entry);
|
|
22
|
+
return entry;
|
|
23
|
+
};
|
|
24
|
+
var __moduleCache;
|
|
25
|
+
var __returnValue = (v) => v;
|
|
26
|
+
function __exportSetter(name, newValue) {
|
|
27
|
+
this[name] = __returnValue.bind(null, newValue);
|
|
28
|
+
}
|
|
29
|
+
var __export = (target, all) => {
|
|
30
|
+
for (var name in all)
|
|
31
|
+
__defProp(target, name, {
|
|
32
|
+
get: all[name],
|
|
33
|
+
enumerable: true,
|
|
34
|
+
configurable: true,
|
|
35
|
+
set: __exportSetter.bind(all, name)
|
|
36
|
+
});
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
// src/shell-session.ts
|
|
40
|
+
var exports_shell_session = {};
|
|
41
|
+
__export(exports_shell_session, {
|
|
42
|
+
createShellSession: () => createShellSession,
|
|
43
|
+
ShellSession: () => ShellSession
|
|
44
|
+
});
|
|
45
|
+
module.exports = __toCommonJS(exports_shell_session);
|
|
46
|
+
var import_lexer = require("./lexer/lexer.cjs");
|
|
47
|
+
var import_parser = require("./parser/parser.cjs");
|
|
48
|
+
var import_interpreter = require("./interpreter/interpreter.cjs");
|
|
49
|
+
var import_stdout = require("./io/stdout.cjs");
|
|
50
|
+
var import_async_queue = require("./io/async-queue.cjs");
|
|
51
|
+
|
|
52
|
+
class ShellSession {
|
|
53
|
+
interpreter;
|
|
54
|
+
constructor(options) {
|
|
55
|
+
this.interpreter = new import_interpreter.Interpreter({
|
|
56
|
+
fs: options.fs,
|
|
57
|
+
cwd: options.cwd,
|
|
58
|
+
env: options.env,
|
|
59
|
+
commands: options.commands,
|
|
60
|
+
terminal: options.terminal ?? { isTTY: options.isTTY ?? false },
|
|
61
|
+
externalCommand: options.externalCommand
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
run(source, options = {}) {
|
|
65
|
+
try {
|
|
66
|
+
const tokens = new import_lexer.Lexer(source, { preserveNewlines: true }).tokenize();
|
|
67
|
+
if (tokens.every((token) => token.type === "newline" || token.type === "eof")) {
|
|
68
|
+
return this.createImmediateExecution(0, "", "");
|
|
69
|
+
}
|
|
70
|
+
const ast = new import_parser.Parser(tokens).parse();
|
|
71
|
+
return this.interpreter.executeStreaming(ast, options);
|
|
72
|
+
} catch (err) {
|
|
73
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
74
|
+
return this.createImmediateExecution(2, "", `sh: ${message}
|
|
75
|
+
`);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
runProgram(program, options = {}) {
|
|
79
|
+
return this.interpreter.executeStreaming(program.ast, options);
|
|
80
|
+
}
|
|
81
|
+
getCwd() {
|
|
82
|
+
return this.interpreter.getCwd();
|
|
83
|
+
}
|
|
84
|
+
getEnv() {
|
|
85
|
+
return this.interpreter.getEnv();
|
|
86
|
+
}
|
|
87
|
+
getLastExitCode() {
|
|
88
|
+
return this.interpreter.getLastExitCode();
|
|
89
|
+
}
|
|
90
|
+
async dispose() {}
|
|
91
|
+
createImmediateExecution(exitCode, stdoutText, stderrText) {
|
|
92
|
+
const stdout = import_stdout.createStdout();
|
|
93
|
+
const stderr = import_stdout.createStderr();
|
|
94
|
+
const output = new import_async_queue.AsyncQueue;
|
|
95
|
+
const exit = (async () => {
|
|
96
|
+
if (stdoutText.length > 0) {
|
|
97
|
+
const chunk = new TextEncoder().encode(stdoutText);
|
|
98
|
+
output.push({ fd: 1, chunk });
|
|
99
|
+
await stdout.write(chunk);
|
|
100
|
+
}
|
|
101
|
+
if (stderrText.length > 0) {
|
|
102
|
+
const chunk = new TextEncoder().encode(stderrText);
|
|
103
|
+
output.push({ fd: 2, chunk });
|
|
104
|
+
await stderr.write(chunk);
|
|
105
|
+
}
|
|
106
|
+
stdout.close();
|
|
107
|
+
stderr.close();
|
|
108
|
+
output.close();
|
|
109
|
+
return {
|
|
110
|
+
stdout: await stdout.collect(),
|
|
111
|
+
stderr: await stderr.collect(),
|
|
112
|
+
exitCode
|
|
113
|
+
};
|
|
114
|
+
})();
|
|
115
|
+
return {
|
|
116
|
+
stdout: stdout.getReadableStream(),
|
|
117
|
+
stderr: stderr.getReadableStream(),
|
|
118
|
+
output,
|
|
119
|
+
exit,
|
|
120
|
+
kill: () => {}
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
function createShellSession(config) {
|
|
125
|
+
return new ShellSession(config);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
//# debugId=636F3B47CF304B5264756E2164756E21
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/shell-session.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"import type {\n Command,\n ExecResult,\n ShellCommandFallback,\n ShellConfig,\n ShellExecution,\n ShellExecutionOptions,\n TerminalInfo,\n VirtualFS,\n} from \"./types.cjs\";\nimport type { Program } from \"./shell-dsl.cjs\";\nimport { Lexer } from \"./lexer/lexer.cjs\";\nimport { Parser } from \"./parser/parser.cjs\";\nimport { Interpreter } from \"./interpreter/interpreter.cjs\";\nimport { createStderr, createStdout } from \"./io/stdout.cjs\";\nimport { AsyncQueue } from \"./io/async-queue.cjs\";\nimport type { ShellOutputEvent } from \"./types.cjs\";\n\nexport interface ShellSessionOptions {\n fs: VirtualFS;\n cwd: string;\n env: Record<string, string>;\n commands: Record<string, Command>;\n isTTY?: boolean;\n terminal?: TerminalInfo;\n externalCommand?: ShellCommandFallback;\n}\n\nexport class ShellSession {\n private interpreter: Interpreter;\n\n constructor(options: ShellSessionOptions) {\n this.interpreter = new Interpreter({\n fs: options.fs,\n cwd: options.cwd,\n env: options.env,\n commands: options.commands,\n terminal: options.terminal ?? { isTTY: options.isTTY ?? false },\n externalCommand: options.externalCommand,\n });\n }\n\n run(source: string, options: ShellExecutionOptions = {}): ShellExecution {\n try {\n const tokens = new Lexer(source, { preserveNewlines: true }).tokenize();\n if (tokens.every((token) => token.type === \"newline\" || token.type === \"eof\")) {\n return this.createImmediateExecution(0, \"\", \"\");\n }\n const ast = new Parser(tokens).parse();\n return this.interpreter.executeStreaming(ast, options);\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return this.createImmediateExecution(2, \"\", `sh: ${message}\\n`);\n }\n }\n\n runProgram(program: Program, options: ShellExecutionOptions = {}): ShellExecution {\n return this.interpreter.executeStreaming(program.ast, options);\n }\n\n getCwd(): string {\n return this.interpreter.getCwd();\n }\n\n getEnv(): Record<string, string> {\n return this.interpreter.getEnv();\n }\n\n getLastExitCode(): number {\n return this.interpreter.getLastExitCode();\n }\n\n async dispose(): Promise<void> {\n // Reserved for future resources owned by a session.\n }\n\n private createImmediateExecution(exitCode: number, stdoutText: string, stderrText: string): ShellExecution {\n const stdout = createStdout();\n const stderr = createStderr();\n const output = new AsyncQueue<ShellOutputEvent>();\n\n const exit = (async (): Promise<ExecResult> => {\n if (stdoutText.length > 0) {\n const chunk = new TextEncoder().encode(stdoutText);\n output.push({ fd: 1, chunk });\n await stdout.write(chunk);\n }\n if (stderrText.length > 0) {\n const chunk = new TextEncoder().encode(stderrText);\n output.push({ fd: 2, chunk });\n await stderr.write(chunk);\n }\n stdout.close();\n stderr.close();\n output.close();\n return {\n stdout: await stdout.collect(),\n stderr: await stderr.collect(),\n exitCode,\n };\n })();\n\n return {\n stdout: stdout.getReadableStream(),\n stderr: stderr.getReadableStream(),\n output,\n exit,\n kill: () => {},\n };\n }\n}\n\nexport function createShellSession(config: ShellConfig): ShellSession {\n return new ShellSession(config);\n}\n"
|
|
6
|
+
],
|
|
7
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAWsB,IAAtB;AACuB,IAAvB;AAC4B,IAA5B;AAC2C,IAA3C;AAC2B,IAA3B;AAAA;AAaO,MAAM,aAAa;AAAA,EAChB;AAAA,EAER,WAAW,CAAC,SAA8B;AAAA,IACxC,KAAK,cAAc,IAAI,+BAAY;AAAA,MACjC,IAAI,QAAQ;AAAA,MACZ,KAAK,QAAQ;AAAA,MACb,KAAK,QAAQ;AAAA,MACb,UAAU,QAAQ;AAAA,MAClB,UAAU,QAAQ,YAAY,EAAE,OAAO,QAAQ,SAAS,MAAM;AAAA,MAC9D,iBAAiB,QAAQ;AAAA,IAC3B,CAAC;AAAA;AAAA,EAGH,GAAG,CAAC,QAAgB,UAAiC,CAAC,GAAmB;AAAA,IACvE,IAAI;AAAA,MACF,MAAM,SAAS,IAAI,mBAAM,QAAQ,EAAE,kBAAkB,KAAK,CAAC,EAAE,SAAS;AAAA,MACtE,IAAI,OAAO,MAAM,CAAC,UAAU,MAAM,SAAS,aAAa,MAAM,SAAS,KAAK,GAAG;AAAA,QAC7E,OAAO,KAAK,yBAAyB,GAAG,IAAI,EAAE;AAAA,MAChD;AAAA,MACA,MAAM,MAAM,IAAI,qBAAO,MAAM,EAAE,MAAM;AAAA,MACrC,OAAO,KAAK,YAAY,iBAAiB,KAAK,OAAO;AAAA,MACrD,OAAO,KAAK;AAAA,MACZ,MAAM,UAAU,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAAA,MAC/D,OAAO,KAAK,yBAAyB,GAAG,IAAI,OAAO;AAAA,CAAW;AAAA;AAAA;AAAA,EAIlE,UAAU,CAAC,SAAkB,UAAiC,CAAC,GAAmB;AAAA,IAChF,OAAO,KAAK,YAAY,iBAAiB,QAAQ,KAAK,OAAO;AAAA;AAAA,EAG/D,MAAM,GAAW;AAAA,IACf,OAAO,KAAK,YAAY,OAAO;AAAA;AAAA,EAGjC,MAAM,GAA2B;AAAA,IAC/B,OAAO,KAAK,YAAY,OAAO;AAAA;AAAA,EAGjC,eAAe,GAAW;AAAA,IACxB,OAAO,KAAK,YAAY,gBAAgB;AAAA;AAAA,OAGpC,QAAO,GAAkB;AAAA,EAIvB,wBAAwB,CAAC,UAAkB,YAAoB,YAAoC;AAAA,IACzG,MAAM,SAAS,2BAAa;AAAA,IAC5B,MAAM,SAAS,2BAAa;AAAA,IAC5B,MAAM,SAAS,IAAI;AAAA,IAEnB,MAAM,QAAQ,YAAiC;AAAA,MAC7C,IAAI,WAAW,SAAS,GAAG;AAAA,QACzB,MAAM,QAAQ,IAAI,YAAY,EAAE,OAAO,UAAU;AAAA,QACjD,OAAO,KAAK,EAAE,IAAI,GAAG,MAAM,CAAC;AAAA,QAC5B,MAAM,OAAO,MAAM,KAAK;AAAA,MAC1B;AAAA,MACA,IAAI,WAAW,SAAS,GAAG;AAAA,QACzB,MAAM,QAAQ,IAAI,YAAY,EAAE,OAAO,UAAU;AAAA,QACjD,OAAO,KAAK,EAAE,IAAI,GAAG,MAAM,CAAC;AAAA,QAC5B,MAAM,OAAO,MAAM,KAAK;AAAA,MAC1B;AAAA,MACA,OAAO,MAAM;AAAA,MACb,OAAO,MAAM;AAAA,MACb,OAAO,MAAM;AAAA,MACb,OAAO;AAAA,QACL,QAAQ,MAAM,OAAO,QAAQ;AAAA,QAC7B,QAAQ,MAAM,OAAO,QAAQ;AAAA,QAC7B;AAAA,MACF;AAAA,OACC;AAAA,IAEH,OAAO;AAAA,MACL,QAAQ,OAAO,kBAAkB;AAAA,MACjC,QAAQ,OAAO,kBAAkB;AAAA,MACjC;AAAA,MACA;AAAA,MACA,MAAM,MAAM;AAAA,IACd;AAAA;AAEJ;AAEO,SAAS,kBAAkB,CAAC,QAAmC;AAAA,EACpE,OAAO,IAAI,aAAa,MAAM;AAAA;",
|
|
8
|
+
"debugId": "636F3B47CF304B5264756E2164756E21",
|
|
9
|
+
"names": []
|
|
10
|
+
}
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/types.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
|
-
"// Virtual Filesystem Interface\nexport interface VirtualFSWritable {\n write(chunk: Uint8Array): Promise<void>;\n close(): Promise<void>;\n abort?(reason?: unknown): Promise<void>;\n}\n\nexport interface VirtualFS {\n readFile(path: string): Promise<Buffer>;\n readFile(path: string, encoding: BufferEncoding): Promise<string>;\n readStream(path: string): AsyncIterable<Uint8Array>;\n readdir(path: string): Promise<string[]>;\n stat(path: string): Promise<FileStat>;\n exists(path: string): Promise<boolean>;\n\n writeFile(path: string, data: Buffer | string): Promise<void>;\n appendFile(path: string, data: Buffer | string): Promise<void>;\n writeStream(path: string, opts?: { append?: boolean }): Promise<VirtualFSWritable>;\n mkdir(path: string, opts?: { recursive?: boolean }): Promise<void>;\n\n rm(path: string, opts?: { recursive?: boolean; force?: boolean }): Promise<void>;\n\n resolve(...paths: string[]): string;\n dirname(path: string): string;\n basename(path: string): string;\n glob(pattern: string, opts?: { cwd?: string }): Promise<string[]>;\n}\n\nexport interface FileStat {\n isFile(): boolean;\n isDirectory(): boolean;\n size: number;\n mtime: Date;\n mtimeMs: number;\n}\n\n// Command Interfaces\nexport type Command = (ctx: CommandContext) => Promise<number>;\n\nexport interface CommandContext {\n args: string[];\n stdin: Stdin;\n stdout: Stdout;\n stderr: Stderr;\n fs: VirtualFS;\n cwd: string;\n env: Record<string, string>;\n setCwd: (path: string) => void;\n exec?: (name: string, args: string[]) => Promise<ExecResult>;\n}\n\nexport interface Stdin {\n stream(): AsyncIterable<Uint8Array>;\n buffer(): Promise<Buffer>;\n text(): Promise<string>;\n lines(): AsyncIterable<string>;\n}\n\nexport interface Stdout {\n write(chunk: Uint8Array): Promise<void>;\n writeText(str: string): Promise<void>;\n isTTY: boolean;\n}\n\nexport interface Stderr {\n write(chunk: Uint8Array): Promise<void>;\n writeText(str: string): Promise<void>;\n isTTY: boolean;\n}\n\nexport interface OutputCollector extends Stdout {\n close(): void;\n collect(): Promise<Buffer>;\n getReadableStream(): AsyncIterable<Uint8Array>;\n}\n\n// Execution Result\nexport interface ExecResult {\n stdout: Buffer;\n stderr: Buffer;\n exitCode: number;\n}\n\n// Shell Configuration\nexport interface ShellConfig {\n fs: VirtualFS;\n cwd: string;\n env: Record<string, string>;\n commands: Record<string, Command>;\n isTTY?: boolean;\n}\n\n// Raw escape hatch type\nexport interface RawValue {\n raw: string;\n}\n\nexport function isRawValue(value: unknown): value is RawValue {\n return (\n typeof value === \"object\" &&\n value !== null &&\n \"raw\" in value &&\n typeof (value as RawValue).raw === \"string\"\n );\n}\n\n// JS Object Redirection types\nexport type RedirectObject = Buffer | Blob | Response | string;\n\nexport interface RedirectObjectMap {\n [marker: string]: RedirectObject;\n}\n\nexport function isRedirectObject(value: unknown): value is RedirectObject {\n return (\n Buffer.isBuffer(value) ||\n value instanceof Blob ||\n value instanceof Response ||\n typeof value === \"string\"\n );\n}\n"
|
|
5
|
+
"// Virtual Filesystem Interface\nexport interface VirtualFSWritable {\n write(chunk: Uint8Array): Promise<void>;\n close(): Promise<void>;\n abort?(reason?: unknown): Promise<void>;\n}\n\nexport interface VirtualFS {\n readFile(path: string): Promise<Buffer>;\n readFile(path: string, encoding: BufferEncoding): Promise<string>;\n readStream(path: string): AsyncIterable<Uint8Array>;\n readdir(path: string): Promise<string[]>;\n stat(path: string): Promise<FileStat>;\n exists(path: string): Promise<boolean>;\n\n writeFile(path: string, data: Buffer | string): Promise<void>;\n appendFile(path: string, data: Buffer | string): Promise<void>;\n writeStream(path: string, opts?: { append?: boolean }): Promise<VirtualFSWritable>;\n mkdir(path: string, opts?: { recursive?: boolean }): Promise<void>;\n\n rm(path: string, opts?: { recursive?: boolean; force?: boolean }): Promise<void>;\n\n resolve(...paths: string[]): string;\n dirname(path: string): string;\n basename(path: string): string;\n glob(pattern: string, opts?: { cwd?: string }): Promise<string[]>;\n}\n\nexport interface FileStat {\n isFile(): boolean;\n isDirectory(): boolean;\n size: number;\n mtime: Date;\n mtimeMs: number;\n}\n\n// Command Interfaces\nexport type Command = (ctx: CommandContext) => Promise<number>;\n\nexport interface ShellRunOptions {\n argv0?: string;\n args?: string[];\n}\n\nexport interface ShellCommandApi {\n eval(source: string): Promise<number>;\n source(path: string, args?: string[]): Promise<number>;\n runScript(path: string, args?: string[]): Promise<number>;\n runShell(source: string, options?: ShellRunOptions): Promise<number>;\n getLastExitCode(): number;\n exit(exitCode?: number): never;\n}\n\nexport interface TerminalInfo {\n isTTY: boolean;\n columns?: number;\n rows?: number;\n colorDepth?: number;\n}\n\nexport interface CommandContext {\n args: string[];\n stdin: Stdin;\n stdout: Stdout;\n stderr: Stderr;\n fs: VirtualFS;\n cwd: string;\n env: Record<string, string>;\n terminal: TerminalInfo;\n signal: AbortSignal;\n setCwd: (path: string) => void;\n exec?: (name: string, args: string[]) => Promise<ExecResult>;\n shell?: ShellCommandApi;\n}\n\nexport interface ExternalCommandContext extends CommandContext {\n name: string;\n}\n\nexport type ShellCommandFallback = (ctx: ExternalCommandContext) => Promise<number>;\n\nexport interface Stdin {\n stream(): AsyncIterable<Uint8Array>;\n buffer(): Promise<Buffer>;\n text(): Promise<string>;\n lines(): AsyncIterable<string>;\n}\n\nexport interface ShellInputController extends AsyncIterable<Uint8Array> {\n write(chunk: Uint8Array | string): Promise<void>;\n close(): void;\n abort(reason?: unknown): void;\n}\n\nexport interface Stdout {\n write(chunk: Uint8Array): Promise<void>;\n writeText(str: string): Promise<void>;\n isTTY: boolean;\n}\n\nexport interface Stderr {\n write(chunk: Uint8Array): Promise<void>;\n writeText(str: string): Promise<void>;\n isTTY: boolean;\n}\n\nexport interface OutputCollector extends Stdout {\n close(): void;\n collect(): Promise<Buffer>;\n getReadableStream(): AsyncIterable<Uint8Array>;\n}\n\n// Execution Result\nexport interface ExecResult {\n stdout: Buffer;\n stderr: Buffer;\n exitCode: number;\n}\n\nexport interface ShellOutputEvent {\n fd: 1 | 2;\n chunk: Uint8Array;\n}\n\nexport type ShellInputSource = AsyncIterable<Uint8Array> | Buffer | string | null;\n\nexport interface ShellExecutionOptions {\n stdin?: ShellInputSource;\n stdout?: Stdout;\n stderr?: Stderr;\n terminal?: TerminalInfo;\n signal?: AbortSignal;\n outputMode?: \"separate\" | \"merged\";\n}\n\nexport interface ShellExecution {\n stdout: AsyncIterable<Uint8Array>;\n stderr: AsyncIterable<Uint8Array>;\n output: AsyncIterable<ShellOutputEvent>;\n exit: Promise<ExecResult>;\n kill(reason?: unknown): void;\n}\n\n// Shell Configuration\nexport interface ShellConfig {\n fs: VirtualFS;\n cwd: string;\n env: Record<string, string>;\n commands: Record<string, Command>;\n isTTY?: boolean;\n terminal?: TerminalInfo;\n externalCommand?: ShellCommandFallback;\n}\n\n// Raw escape hatch type\nexport interface RawValue {\n raw: string;\n}\n\nexport function isRawValue(value: unknown): value is RawValue {\n return (\n typeof value === \"object\" &&\n value !== null &&\n \"raw\" in value &&\n typeof (value as RawValue).raw === \"string\"\n );\n}\n\n// JS Object Redirection types\nexport type RedirectObject = Buffer | Blob | Response | string;\n\nexport interface RedirectObjectMap {\n [marker: string]: RedirectObject;\n}\n\nexport function isRedirectObject(value: unknown): value is RedirectObject {\n return (\n Buffer.isBuffer(value) ||\n value instanceof Blob ||\n value instanceof Response ||\n typeof value === \"string\"\n );\n}\n"
|
|
6
6
|
],
|
|
7
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
7
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+JO,SAAS,UAAU,CAAC,OAAmC;AAAA,EAC5D,OACE,OAAO,UAAU,YACjB,UAAU,QACV,SAAS,SACT,OAAQ,MAAmB,QAAQ;AAAA;AAWhC,SAAS,gBAAgB,CAAC,OAAyC;AAAA,EACxE,OACE,OAAO,SAAS,KAAK,KACrB,iBAAiB,QACjB,iBAAiB,YACjB,OAAO,UAAU;AAAA;",
|
|
8
8
|
"debugId": "324A9AF65A2908F664756E2164756E21",
|
|
9
9
|
"names": []
|
|
10
10
|
}
|
package/dist/mjs/package.json
CHANGED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
// src/commands/exit/exit.ts
|
|
2
|
+
function parseExitCode(value) {
|
|
3
|
+
if (!/^[+-]?\d+$/.test(value)) {
|
|
4
|
+
return null;
|
|
5
|
+
}
|
|
6
|
+
return Number(value);
|
|
7
|
+
}
|
|
8
|
+
var exitCmd = async (ctx) => {
|
|
9
|
+
if (!ctx.shell) {
|
|
10
|
+
await ctx.stderr.writeText(`exit: shell control not supported
|
|
11
|
+
`);
|
|
12
|
+
return 1;
|
|
13
|
+
}
|
|
14
|
+
if (ctx.args.length === 0) {
|
|
15
|
+
ctx.shell.exit(ctx.shell.getLastExitCode());
|
|
16
|
+
return 0;
|
|
17
|
+
}
|
|
18
|
+
const rawExitCode = ctx.args[0];
|
|
19
|
+
const exitCode = parseExitCode(rawExitCode);
|
|
20
|
+
if (exitCode === null) {
|
|
21
|
+
await ctx.stderr.writeText(`exit: ${rawExitCode}: numeric argument required
|
|
22
|
+
`);
|
|
23
|
+
ctx.shell.exit(2);
|
|
24
|
+
return 0;
|
|
25
|
+
}
|
|
26
|
+
if (!Number.isFinite(exitCode)) {
|
|
27
|
+
await ctx.stderr.writeText(`exit: ${rawExitCode}: numeric argument required
|
|
28
|
+
`);
|
|
29
|
+
ctx.shell.exit(2);
|
|
30
|
+
return 0;
|
|
31
|
+
}
|
|
32
|
+
if (ctx.args.length > 1) {
|
|
33
|
+
await ctx.stderr.writeText(`exit: too many arguments
|
|
34
|
+
`);
|
|
35
|
+
return 1;
|
|
36
|
+
}
|
|
37
|
+
ctx.shell.exit(exitCode);
|
|
38
|
+
return 0;
|
|
39
|
+
};
|
|
40
|
+
export {
|
|
41
|
+
exitCmd
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
//# debugId=D6B1A7CA5FF6DAE464756E2164756E21
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../../src/commands/exit/exit.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"import type { Command } from \"../../types.mjs\";\n\nfunction parseExitCode(value: string): number | null {\n if (!/^[+-]?\\d+$/.test(value)) {\n return null;\n }\n return Number(value);\n}\n\nexport const exitCmd: Command = async (ctx) => {\n if (!ctx.shell) {\n await ctx.stderr.writeText(\"exit: shell control not supported\\n\");\n return 1;\n }\n\n if (ctx.args.length === 0) {\n ctx.shell.exit(ctx.shell.getLastExitCode());\n return 0;\n }\n\n const rawExitCode = ctx.args[0]!;\n const exitCode = parseExitCode(rawExitCode);\n if (exitCode === null) {\n await ctx.stderr.writeText(`exit: ${rawExitCode}: numeric argument required\\n`);\n ctx.shell.exit(2);\n return 0;\n }\n\n if (!Number.isFinite(exitCode)) {\n await ctx.stderr.writeText(`exit: ${rawExitCode}: numeric argument required\\n`);\n ctx.shell.exit(2);\n return 0;\n }\n\n if (ctx.args.length > 1) {\n await ctx.stderr.writeText(\"exit: too many arguments\\n\");\n return 1;\n }\n\n ctx.shell.exit(exitCode);\n return 0;\n};\n"
|
|
6
|
+
],
|
|
7
|
+
"mappings": ";AAEA,SAAS,aAAa,CAAC,OAA8B;AAAA,EACnD,IAAI,CAAC,aAAa,KAAK,KAAK,GAAG;AAAA,IAC7B,OAAO;AAAA,EACT;AAAA,EACA,OAAO,OAAO,KAAK;AAAA;AAGd,IAAM,UAAmB,OAAO,QAAQ;AAAA,EAC7C,IAAI,CAAC,IAAI,OAAO;AAAA,IACd,MAAM,IAAI,OAAO,UAAU;AAAA,CAAqC;AAAA,IAChE,OAAO;AAAA,EACT;AAAA,EAEA,IAAI,IAAI,KAAK,WAAW,GAAG;AAAA,IACzB,IAAI,MAAM,KAAK,IAAI,MAAM,gBAAgB,CAAC;AAAA,IAC1C,OAAO;AAAA,EACT;AAAA,EAEA,MAAM,cAAc,IAAI,KAAK;AAAA,EAC7B,MAAM,WAAW,cAAc,WAAW;AAAA,EAC1C,IAAI,aAAa,MAAM;AAAA,IACrB,MAAM,IAAI,OAAO,UAAU,SAAS;AAAA,CAA0C;AAAA,IAC9E,IAAI,MAAM,KAAK,CAAC;AAAA,IAChB,OAAO;AAAA,EACT;AAAA,EAEA,IAAI,CAAC,OAAO,SAAS,QAAQ,GAAG;AAAA,IAC9B,MAAM,IAAI,OAAO,UAAU,SAAS;AAAA,CAA0C;AAAA,IAC9E,IAAI,MAAM,KAAK,CAAC;AAAA,IAChB,OAAO;AAAA,EACT;AAAA,EAEA,IAAI,IAAI,KAAK,SAAS,GAAG;AAAA,IACvB,MAAM,IAAI,OAAO,UAAU;AAAA,CAA4B;AAAA,IACvD,OAAO;AAAA,EACT;AAAA,EAEA,IAAI,MAAM,KAAK,QAAQ;AAAA,EACvB,OAAO;AAAA;",
|
|
8
|
+
"debugId": "D6B1A7CA5FF6DAE464756E2164756E21",
|
|
9
|
+
"names": []
|
|
10
|
+
}
|
|
@@ -28,6 +28,8 @@ import { cd } from "./cd/cd.mjs";
|
|
|
28
28
|
import { tr } from "./tr/tr.mjs";
|
|
29
29
|
import { cut } from "./cut/cut.mjs";
|
|
30
30
|
import { od } from "./od/od.mjs";
|
|
31
|
+
import { sh, evalCmd, evalCmd as evalCmd2, source, dot } from "./sh/sh.mjs";
|
|
32
|
+
import { exitCmd, exitCmd as exitCmd2 } from "./exit/exit.mjs";
|
|
31
33
|
import { echo as echo2 } from "./echo/echo.mjs";
|
|
32
34
|
import { printf as printf2 } from "./printf/printf.mjs";
|
|
33
35
|
import { cat as cat2 } from "./cat/cat.mjs";
|
|
@@ -57,6 +59,8 @@ import { cd as cd2 } from "./cd/cd.mjs";
|
|
|
57
59
|
import { tr as tr2 } from "./tr/tr.mjs";
|
|
58
60
|
import { cut as cut2 } from "./cut/cut.mjs";
|
|
59
61
|
import { od as od2 } from "./od/od.mjs";
|
|
62
|
+
import { sh as sh2, evalCmd as evalCmd3, source as source2, dot as dot2 } from "./sh/sh.mjs";
|
|
63
|
+
import { exitCmd as exitCmd3 } from "./exit/exit.mjs";
|
|
60
64
|
var builtinCommands = {
|
|
61
65
|
echo: echo2,
|
|
62
66
|
printf: printf2,
|
|
@@ -89,7 +93,12 @@ var builtinCommands = {
|
|
|
89
93
|
cd: cd2,
|
|
90
94
|
tr: tr2,
|
|
91
95
|
cut: cut2,
|
|
92
|
-
od: od2
|
|
96
|
+
od: od2,
|
|
97
|
+
sh: sh2,
|
|
98
|
+
eval: evalCmd3,
|
|
99
|
+
source: source2,
|
|
100
|
+
".": dot2,
|
|
101
|
+
exit: exitCmd3
|
|
93
102
|
};
|
|
94
103
|
export {
|
|
95
104
|
wc,
|
|
@@ -101,7 +110,9 @@ export {
|
|
|
101
110
|
test,
|
|
102
111
|
tee,
|
|
103
112
|
tail,
|
|
113
|
+
source,
|
|
104
114
|
sort,
|
|
115
|
+
sh,
|
|
105
116
|
sed,
|
|
106
117
|
rm,
|
|
107
118
|
pwd,
|
|
@@ -114,7 +125,12 @@ export {
|
|
|
114
125
|
grep,
|
|
115
126
|
find,
|
|
116
127
|
falseCmd,
|
|
128
|
+
exitCmd2 as exitCmd,
|
|
129
|
+
exitCmd as exit,
|
|
130
|
+
evalCmd2 as evalCmd,
|
|
131
|
+
evalCmd as eval,
|
|
117
132
|
echo,
|
|
133
|
+
dot,
|
|
118
134
|
cut,
|
|
119
135
|
cp,
|
|
120
136
|
continueCmd,
|
|
@@ -127,4 +143,4 @@ export {
|
|
|
127
143
|
awk
|
|
128
144
|
};
|
|
129
145
|
|
|
130
|
-
//# debugId=
|
|
146
|
+
//# debugId=48840C464F27115B64756E2164756E21
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/commands/index.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
|
-
"import type { Command } from \"../types.mjs\";\n\nexport { echo } from \"./echo/echo.mjs\";\nexport { printf } from \"./printf/printf.mjs\";\nexport { cat } from \"./cat/cat.mjs\";\nexport { grep } from \"./grep/grep.mjs\";\nexport { wc } from \"./wc/wc.mjs\";\nexport { head } from \"./head/head.mjs\";\nexport { tail } from \"./tail/tail.mjs\";\nexport { sort } from \"./sort/sort.mjs\";\nexport { uniq } from \"./uniq/uniq.mjs\";\nexport { pwd } from \"./pwd/pwd.mjs\";\nexport { ls } from \"./ls/ls.mjs\";\nexport { mkdir } from \"./mkdir/mkdir.mjs\";\nexport { rm } from \"./rm/rm.mjs\";\nexport { test, bracket } from \"./test/test.mjs\";\nexport { trueCmd, falseCmd } from \"./true-false/true-false.mjs\";\nexport { touch } from \"./touch/touch.mjs\";\nexport { cp } from \"./cp/cp.mjs\";\nexport { mv } from \"./mv/mv.mjs\";\nexport { tee } from \"./tee/tee.mjs\";\nexport { tree } from \"./tree/tree.mjs\";\nexport { find } from \"./find/find.mjs\";\nexport { sed } from \"./sed/sed.mjs\";\nexport { awk } from \"./awk/awk.mjs\";\nexport { breakCmd, continueCmd } from \"./break-continue/break-continue.mjs\";\nexport { colon } from \"./colon/colon.mjs\";\nexport { cd } from \"./cd/cd.mjs\";\nexport { tr } from \"./tr/tr.mjs\";\nexport { cut } from \"./cut/cut.mjs\";\nexport { od } from \"./od/od.mjs\";\n\n// Re-export all commands as a bundle\nimport { echo } from \"./echo/echo.mjs\";\nimport { printf } from \"./printf/printf.mjs\";\nimport { cat } from \"./cat/cat.mjs\";\nimport { grep } from \"./grep/grep.mjs\";\nimport { wc } from \"./wc/wc.mjs\";\nimport { head } from \"./head/head.mjs\";\nimport { tail } from \"./tail/tail.mjs\";\nimport { sort } from \"./sort/sort.mjs\";\nimport { uniq } from \"./uniq/uniq.mjs\";\nimport { pwd } from \"./pwd/pwd.mjs\";\nimport { ls } from \"./ls/ls.mjs\";\nimport { mkdir } from \"./mkdir/mkdir.mjs\";\nimport { rm } from \"./rm/rm.mjs\";\nimport { test, bracket } from \"./test/test.mjs\";\nimport { trueCmd, falseCmd } from \"./true-false/true-false.mjs\";\nimport { touch } from \"./touch/touch.mjs\";\nimport { cp } from \"./cp/cp.mjs\";\nimport { mv } from \"./mv/mv.mjs\";\nimport { tee } from \"./tee/tee.mjs\";\nimport { tree } from \"./tree/tree.mjs\";\nimport { find } from \"./find/find.mjs\";\nimport { sed } from \"./sed/sed.mjs\";\nimport { awk } from \"./awk/awk.mjs\";\nimport { breakCmd, continueCmd } from \"./break-continue/break-continue.mjs\";\nimport { colon } from \"./colon/colon.mjs\";\nimport { cd } from \"./cd/cd.mjs\";\nimport { tr } from \"./tr/tr.mjs\";\nimport { cut } from \"./cut/cut.mjs\";\nimport { od } from \"./od/od.mjs\";\n\nexport const builtinCommands: Record<string, Command> = {\n echo,\n printf,\n cat,\n grep,\n wc,\n head,\n tail,\n sort,\n uniq,\n pwd,\n ls,\n mkdir,\n rm,\n test,\n \"[\": bracket,\n true: trueCmd,\n false: falseCmd,\n touch,\n cp,\n mv,\n tee,\n tree,\n find,\n sed,\n awk,\n break: breakCmd,\n continue: continueCmd,\n \":\": colon,\n cd,\n tr,\n cut,\n od,\n};\n"
|
|
5
|
+
"import type { Command } from \"../types.mjs\";\n\nexport { echo } from \"./echo/echo.mjs\";\nexport { printf } from \"./printf/printf.mjs\";\nexport { cat } from \"./cat/cat.mjs\";\nexport { grep } from \"./grep/grep.mjs\";\nexport { wc } from \"./wc/wc.mjs\";\nexport { head } from \"./head/head.mjs\";\nexport { tail } from \"./tail/tail.mjs\";\nexport { sort } from \"./sort/sort.mjs\";\nexport { uniq } from \"./uniq/uniq.mjs\";\nexport { pwd } from \"./pwd/pwd.mjs\";\nexport { ls } from \"./ls/ls.mjs\";\nexport { mkdir } from \"./mkdir/mkdir.mjs\";\nexport { rm } from \"./rm/rm.mjs\";\nexport { test, bracket } from \"./test/test.mjs\";\nexport { trueCmd, falseCmd } from \"./true-false/true-false.mjs\";\nexport { touch } from \"./touch/touch.mjs\";\nexport { cp } from \"./cp/cp.mjs\";\nexport { mv } from \"./mv/mv.mjs\";\nexport { tee } from \"./tee/tee.mjs\";\nexport { tree } from \"./tree/tree.mjs\";\nexport { find } from \"./find/find.mjs\";\nexport { sed } from \"./sed/sed.mjs\";\nexport { awk } from \"./awk/awk.mjs\";\nexport { breakCmd, continueCmd } from \"./break-continue/break-continue.mjs\";\nexport { colon } from \"./colon/colon.mjs\";\nexport { cd } from \"./cd/cd.mjs\";\nexport { tr } from \"./tr/tr.mjs\";\nexport { cut } from \"./cut/cut.mjs\";\nexport { od } from \"./od/od.mjs\";\nexport { sh, evalCmd as eval, evalCmd, source, dot } from \"./sh/sh.mjs\";\nexport { exitCmd as exit, exitCmd } from \"./exit/exit.mjs\";\n\n// Re-export all commands as a bundle\nimport { echo } from \"./echo/echo.mjs\";\nimport { printf } from \"./printf/printf.mjs\";\nimport { cat } from \"./cat/cat.mjs\";\nimport { grep } from \"./grep/grep.mjs\";\nimport { wc } from \"./wc/wc.mjs\";\nimport { head } from \"./head/head.mjs\";\nimport { tail } from \"./tail/tail.mjs\";\nimport { sort } from \"./sort/sort.mjs\";\nimport { uniq } from \"./uniq/uniq.mjs\";\nimport { pwd } from \"./pwd/pwd.mjs\";\nimport { ls } from \"./ls/ls.mjs\";\nimport { mkdir } from \"./mkdir/mkdir.mjs\";\nimport { rm } from \"./rm/rm.mjs\";\nimport { test, bracket } from \"./test/test.mjs\";\nimport { trueCmd, falseCmd } from \"./true-false/true-false.mjs\";\nimport { touch } from \"./touch/touch.mjs\";\nimport { cp } from \"./cp/cp.mjs\";\nimport { mv } from \"./mv/mv.mjs\";\nimport { tee } from \"./tee/tee.mjs\";\nimport { tree } from \"./tree/tree.mjs\";\nimport { find } from \"./find/find.mjs\";\nimport { sed } from \"./sed/sed.mjs\";\nimport { awk } from \"./awk/awk.mjs\";\nimport { breakCmd, continueCmd } from \"./break-continue/break-continue.mjs\";\nimport { colon } from \"./colon/colon.mjs\";\nimport { cd } from \"./cd/cd.mjs\";\nimport { tr } from \"./tr/tr.mjs\";\nimport { cut } from \"./cut/cut.mjs\";\nimport { od } from \"./od/od.mjs\";\nimport { sh, evalCmd, source, dot } from \"./sh/sh.mjs\";\nimport { exitCmd } from \"./exit/exit.mjs\";\n\nexport const builtinCommands: Record<string, Command> = {\n echo,\n printf,\n cat,\n grep,\n wc,\n head,\n tail,\n sort,\n uniq,\n pwd,\n ls,\n mkdir,\n rm,\n test,\n \"[\": bracket,\n true: trueCmd,\n false: falseCmd,\n touch,\n cp,\n mv,\n tee,\n tree,\n find,\n sed,\n awk,\n break: breakCmd,\n continue: continueCmd,\n \":\": colon,\n cd,\n tr,\n cut,\n od,\n sh,\n eval: evalCmd,\n source,\n \".\": dot,\n exit: exitCmd,\n};\n"
|
|
6
6
|
],
|
|
7
|
-
"mappings": ";AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;
|
|
8
|
-
"debugId": "
|
|
7
|
+
"mappings": ";AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,iCAA8B;AAC9B,6BAA0B;AAG1B,iBAAS;AACT,mBAAS;AACT,gBAAS;AACT,iBAAS;AACT,eAAS;AACT,iBAAS;AACT,iBAAS;AACT,iBAAS;AACT,iBAAS;AACT,gBAAS;AACT,eAAS;AACT,kBAAS;AACT,eAAS;AACT,iBAAS,kBAAM;AACf,oBAAS,sBAAS;AAClB,kBAAS;AACT,eAAS;AACT,eAAS;AACT,gBAAS;AACT,iBAAS;AACT,iBAAS;AACT,gBAAS;AACT,gBAAS;AACT,qBAAS,0BAAU;AACnB,kBAAS;AACT,eAAS;AACT,eAAS;AACT,gBAAS;AACT,eAAS;AACT,eAAS,gBAAI,oBAAS,gBAAQ;AAC9B,oBAAS;AAEF,IAAM,kBAA2C;AAAA,EACtD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,KAAK;AAAA,EACL,MAAM;AAAA,EACN,OAAO;AAAA,EACP;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,OAAO;AAAA,EACP,UAAU;AAAA,EACV,KAAK;AAAA,EACL;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,MAAM;AAAA,EACN;AAAA,EACA,KAAK;AAAA,EACL,MAAM;AACR;",
|
|
8
|
+
"debugId": "48840C464F27115B64756E2164756E21",
|
|
9
9
|
"names": []
|
|
10
10
|
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
// src/commands/sh/sh.ts
|
|
2
|
+
async function readShellFile(fs, cwd, pathName, stderr) {
|
|
3
|
+
const path = fs.resolve(cwd, pathName);
|
|
4
|
+
if (!await fs.exists(path)) {
|
|
5
|
+
await stderr.writeText(`sh: ${pathName}: No such file or directory
|
|
6
|
+
`);
|
|
7
|
+
return { ok: false, exitCode: 127 };
|
|
8
|
+
}
|
|
9
|
+
const stat = await fs.stat(path);
|
|
10
|
+
if (stat.isDirectory()) {
|
|
11
|
+
await stderr.writeText(`sh: ${pathName}: is a directory
|
|
12
|
+
`);
|
|
13
|
+
return { ok: false, exitCode: 126 };
|
|
14
|
+
}
|
|
15
|
+
if (!stat.isFile()) {
|
|
16
|
+
await stderr.writeText(`sh: ${pathName}: not a file
|
|
17
|
+
`);
|
|
18
|
+
return { ok: false, exitCode: 126 };
|
|
19
|
+
}
|
|
20
|
+
try {
|
|
21
|
+
return { ok: true, source: await fs.readFile(path, "utf-8") };
|
|
22
|
+
} catch (err) {
|
|
23
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
24
|
+
await stderr.writeText(`sh: ${pathName}: ${message}
|
|
25
|
+
`);
|
|
26
|
+
return { ok: false, exitCode: 126 };
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
var sh = async (ctx) => {
|
|
30
|
+
if (!ctx.shell) {
|
|
31
|
+
await ctx.stderr.writeText(`sh: shell evaluation not supported
|
|
32
|
+
`);
|
|
33
|
+
return 1;
|
|
34
|
+
}
|
|
35
|
+
if (ctx.args.length === 0) {
|
|
36
|
+
return ctx.shell.runShell(await ctx.stdin.text(), { argv0: "sh", args: [] });
|
|
37
|
+
}
|
|
38
|
+
const first = ctx.args[0];
|
|
39
|
+
if (first === "-c") {
|
|
40
|
+
const source = ctx.args[1];
|
|
41
|
+
if (source === undefined) {
|
|
42
|
+
await ctx.stderr.writeText(`sh: -c requires an argument
|
|
43
|
+
`);
|
|
44
|
+
return 2;
|
|
45
|
+
}
|
|
46
|
+
const argv0 = ctx.args[2] ?? "sh";
|
|
47
|
+
const args = ctx.args[2] === undefined ? [] : ctx.args.slice(3);
|
|
48
|
+
return ctx.shell.runShell(source, { argv0, args });
|
|
49
|
+
}
|
|
50
|
+
if (first.startsWith("-")) {
|
|
51
|
+
await ctx.stderr.writeText(`sh: unsupported option: ${first}
|
|
52
|
+
`);
|
|
53
|
+
return 2;
|
|
54
|
+
}
|
|
55
|
+
const loaded = await readShellFile(ctx.fs, ctx.cwd, first, ctx.stderr);
|
|
56
|
+
if (!loaded.ok) {
|
|
57
|
+
return loaded.exitCode;
|
|
58
|
+
}
|
|
59
|
+
return ctx.shell.runShell(loaded.source, { argv0: first, args: ctx.args.slice(1) });
|
|
60
|
+
};
|
|
61
|
+
var evalCmd = async (ctx) => {
|
|
62
|
+
if (!ctx.shell) {
|
|
63
|
+
await ctx.stderr.writeText(`eval: shell evaluation not supported
|
|
64
|
+
`);
|
|
65
|
+
return 1;
|
|
66
|
+
}
|
|
67
|
+
if (ctx.args.length === 0) {
|
|
68
|
+
return 0;
|
|
69
|
+
}
|
|
70
|
+
return ctx.shell.eval(ctx.args.join(" "));
|
|
71
|
+
};
|
|
72
|
+
var source = async (ctx) => {
|
|
73
|
+
if (!ctx.shell) {
|
|
74
|
+
await ctx.stderr.writeText(`source: shell evaluation not supported
|
|
75
|
+
`);
|
|
76
|
+
return 1;
|
|
77
|
+
}
|
|
78
|
+
const path = ctx.args[0];
|
|
79
|
+
if (path === undefined) {
|
|
80
|
+
await ctx.stderr.writeText(`source: filename argument required
|
|
81
|
+
`);
|
|
82
|
+
return 2;
|
|
83
|
+
}
|
|
84
|
+
return ctx.shell.source(path, ctx.args.slice(1));
|
|
85
|
+
};
|
|
86
|
+
var dot = source;
|
|
87
|
+
export {
|
|
88
|
+
source,
|
|
89
|
+
sh,
|
|
90
|
+
evalCmd,
|
|
91
|
+
dot
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
//# debugId=F711664330E99B5E64756E2164756E21
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../../src/commands/sh/sh.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"import type { Command, Stderr, VirtualFS } from \"../../types.mjs\";\n\nasync function readShellFile(\n fs: VirtualFS,\n cwd: string,\n pathName: string,\n stderr: Stderr\n): Promise<{ ok: true; source: string } | { ok: false; exitCode: number }> {\n const path = fs.resolve(cwd, pathName);\n\n if (!(await fs.exists(path))) {\n await stderr.writeText(`sh: ${pathName}: No such file or directory\\n`);\n return { ok: false, exitCode: 127 };\n }\n\n const stat = await fs.stat(path);\n if (stat.isDirectory()) {\n await stderr.writeText(`sh: ${pathName}: is a directory\\n`);\n return { ok: false, exitCode: 126 };\n }\n if (!stat.isFile()) {\n await stderr.writeText(`sh: ${pathName}: not a file\\n`);\n return { ok: false, exitCode: 126 };\n }\n\n try {\n return { ok: true, source: await fs.readFile(path, \"utf-8\") };\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n await stderr.writeText(`sh: ${pathName}: ${message}\\n`);\n return { ok: false, exitCode: 126 };\n }\n}\n\nexport const sh: Command = async (ctx) => {\n if (!ctx.shell) {\n await ctx.stderr.writeText(\"sh: shell evaluation not supported\\n\");\n return 1;\n }\n\n if (ctx.args.length === 0) {\n return ctx.shell.runShell(await ctx.stdin.text(), { argv0: \"sh\", args: [] });\n }\n\n const first = ctx.args[0]!;\n if (first === \"-c\") {\n const source = ctx.args[1];\n if (source === undefined) {\n await ctx.stderr.writeText(\"sh: -c requires an argument\\n\");\n return 2;\n }\n\n const argv0 = ctx.args[2] ?? \"sh\";\n const args = ctx.args[2] === undefined ? [] : ctx.args.slice(3);\n return ctx.shell.runShell(source, { argv0, args });\n }\n\n if (first.startsWith(\"-\")) {\n await ctx.stderr.writeText(`sh: unsupported option: ${first}\\n`);\n return 2;\n }\n\n const loaded = await readShellFile(ctx.fs, ctx.cwd, first, ctx.stderr);\n if (!loaded.ok) {\n return loaded.exitCode;\n }\n\n return ctx.shell.runShell(loaded.source, { argv0: first, args: ctx.args.slice(1) });\n};\n\nexport const evalCmd: Command = async (ctx) => {\n if (!ctx.shell) {\n await ctx.stderr.writeText(\"eval: shell evaluation not supported\\n\");\n return 1;\n }\n if (ctx.args.length === 0) {\n return 0;\n }\n return ctx.shell.eval(ctx.args.join(\" \"));\n};\n\nexport const source: Command = async (ctx) => {\n if (!ctx.shell) {\n await ctx.stderr.writeText(\"source: shell evaluation not supported\\n\");\n return 1;\n }\n const path = ctx.args[0];\n if (path === undefined) {\n await ctx.stderr.writeText(\"source: filename argument required\\n\");\n return 2;\n }\n return ctx.shell.source(path, ctx.args.slice(1));\n};\n\nexport const dot = source;\n"
|
|
6
|
+
],
|
|
7
|
+
"mappings": "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",
|
|
8
|
+
"debugId": "F711664330E99B5E64756E2164756E21",
|
|
9
|
+
"names": []
|
|
10
|
+
}
|
package/dist/mjs/src/index.mjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// src/index.ts
|
|
2
2
|
import { ShellDSL, createShellDSL } from "./shell-dsl.mjs";
|
|
3
3
|
import { ShellPromise } from "./shell-promise.mjs";
|
|
4
|
+
import { ShellSession, createShellSession } from "./shell-session.mjs";
|
|
4
5
|
import { isRawValue } from "./types.mjs";
|
|
5
6
|
import { ShellError, LexError, ParseError } from "./errors.mjs";
|
|
6
7
|
import { Lexer, lex, tokenToString } from "./lexer/index.mjs";
|
|
@@ -18,7 +19,7 @@ import {
|
|
|
18
19
|
isUntilNode,
|
|
19
20
|
isCaseNode
|
|
20
21
|
} from "./parser/index.mjs";
|
|
21
|
-
import { Interpreter, BreakException, ContinueException } from "./interpreter/index.mjs";
|
|
22
|
+
import { Interpreter, BreakException, ContinueException, ExitException } from "./interpreter/index.mjs";
|
|
22
23
|
import { createVirtualFS } from "./fs/index.mjs";
|
|
23
24
|
import {
|
|
24
25
|
FileSystem,
|
|
@@ -27,7 +28,16 @@ import {
|
|
|
27
28
|
createWebUnderlyingFS
|
|
28
29
|
} from "./fs/index.mjs";
|
|
29
30
|
import { createStdin, StdinImpl } from "./io/index.mjs";
|
|
30
|
-
import {
|
|
31
|
+
import {
|
|
32
|
+
createStdout,
|
|
33
|
+
createStderr,
|
|
34
|
+
createPipe,
|
|
35
|
+
createShellInput,
|
|
36
|
+
OutputCollectorImpl,
|
|
37
|
+
PipeBuffer,
|
|
38
|
+
ShellInputControllerImpl
|
|
39
|
+
} from "./io/index.mjs";
|
|
40
|
+
import { analyzeInput } from "./input-analysis.mjs";
|
|
31
41
|
import { escape, escapeForInterpolation, globVirtualFS } from "./utils/index.mjs";
|
|
32
42
|
import { VersionControlSystem } from "./vcs/index.mjs";
|
|
33
43
|
export {
|
|
@@ -54,12 +64,17 @@ export {
|
|
|
54
64
|
createStdout,
|
|
55
65
|
createStdin,
|
|
56
66
|
createStderr,
|
|
67
|
+
createShellSession,
|
|
68
|
+
createShellInput,
|
|
57
69
|
createShellDSL,
|
|
58
70
|
createPipe,
|
|
71
|
+
analyzeInput,
|
|
59
72
|
WebFileSystem,
|
|
60
73
|
VersionControlSystem,
|
|
61
74
|
StdinImpl,
|
|
75
|
+
ShellSession,
|
|
62
76
|
ShellPromise,
|
|
77
|
+
ShellInputControllerImpl,
|
|
63
78
|
ShellError,
|
|
64
79
|
ShellDSL,
|
|
65
80
|
ReadOnlyFileSystem,
|
|
@@ -71,8 +86,9 @@ export {
|
|
|
71
86
|
LexError,
|
|
72
87
|
Interpreter,
|
|
73
88
|
FileSystem,
|
|
89
|
+
ExitException,
|
|
74
90
|
ContinueException,
|
|
75
91
|
BreakException
|
|
76
92
|
};
|
|
77
93
|
|
|
78
|
-
//# debugId=
|
|
94
|
+
//# debugId=A98B7667567C2E6F64756E2164756E21
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/index.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
|
-
"// Main class exports\nexport { ShellDSL, createShellDSL, type Program } from \"./shell-dsl.mjs\";\nexport { ShellPromise, type ShellPromiseOptions } from \"./shell-promise.mjs\";\n\n// Types\nexport type {\n VirtualFS,\n VirtualFSWritable,\n FileStat,\n Command,\n CommandContext,\n Stdin,\n Stdout,\n Stderr,\n OutputCollector,\n ExecResult,\n ShellConfig,\n RawValue,\n} from \"./types.mjs\";\nexport { isRawValue } from \"./types.mjs\";\n\n// Errors\nexport { ShellError, LexError, ParseError } from \"./errors.mjs\";\n\n// Lexer\nexport { Lexer, lex, tokenToString } from \"./lexer/index.mjs\";\nexport type { Token, RedirectMode } from \"./lexer/index.mjs\";\n\n// Parser\nexport { Parser, parse } from \"./parser/index.mjs\";\nexport type {\n ASTNode,\n Redirect,\n CommandNode,\n PipelineNode,\n AndNode,\n OrNode,\n SequenceNode,\n WordNode,\n WordPart,\n TextPart,\n VariablePart,\n SubstitutionPart,\n ArithmeticPart,\n IfNode,\n ForNode,\n WhileNode,\n UntilNode,\n CaseNode,\n CaseClause,\n} from \"./parser/index.mjs\";\nexport {\n isWordNode,\n isCommandNode,\n isPipelineNode,\n isAndNode,\n isOrNode,\n isSequenceNode,\n isIfNode,\n isForNode,\n isWhileNode,\n isUntilNode,\n isCaseNode,\n} from \"./parser/index.mjs\";\n\n// Interpreter\nexport { Interpreter, type InterpreterOptions, BreakException, ContinueException } from \"./interpreter/index.mjs\";\n\n// Filesystem\nexport { createVirtualFS } from \"./fs/index.mjs\";\nexport {\n FileSystem,\n ReadOnlyFileSystem,\n WebFileSystem,\n createWebUnderlyingFS,\n type PathOps,\n type Permission,\n type PermissionRules,\n type UnderlyingFS,\n} from \"./fs/index.mjs\";\n\n// I/O\nexport { createStdin, StdinImpl } from \"./io/index.mjs\";\nexport {
|
|
5
|
+
"// Main class exports\nexport { ShellDSL, createShellDSL, type Program } from \"./shell-dsl.mjs\";\nexport { ShellPromise, type ShellPromiseOptions } from \"./shell-promise.mjs\";\nexport { ShellSession, createShellSession, type ShellSessionOptions } from \"./shell-session.mjs\";\n\n// Types\nexport type {\n VirtualFS,\n VirtualFSWritable,\n FileStat,\n Command,\n CommandContext,\n Stdin,\n Stdout,\n Stderr,\n OutputCollector,\n ExecResult,\n ShellConfig,\n ShellCommandApi,\n ShellCommandFallback,\n ExternalCommandContext,\n ShellRunOptions,\n TerminalInfo,\n ShellInputController,\n ShellInputSource,\n ShellExecutionOptions,\n ShellExecution,\n ShellOutputEvent,\n RawValue,\n} from \"./types.mjs\";\nexport { isRawValue } from \"./types.mjs\";\n\n// Errors\nexport { ShellError, LexError, ParseError } from \"./errors.mjs\";\n\n// Lexer\nexport { Lexer, lex, tokenToString } from \"./lexer/index.mjs\";\nexport type { Token, RedirectMode } from \"./lexer/index.mjs\";\n\n// Parser\nexport { Parser, parse } from \"./parser/index.mjs\";\nexport type {\n ASTNode,\n Redirect,\n CommandNode,\n PipelineNode,\n AndNode,\n OrNode,\n SequenceNode,\n WordNode,\n WordPart,\n TextPart,\n VariablePart,\n SubstitutionPart,\n ArithmeticPart,\n IfNode,\n ForNode,\n WhileNode,\n UntilNode,\n CaseNode,\n CaseClause,\n} from \"./parser/index.mjs\";\nexport {\n isWordNode,\n isCommandNode,\n isPipelineNode,\n isAndNode,\n isOrNode,\n isSequenceNode,\n isIfNode,\n isForNode,\n isWhileNode,\n isUntilNode,\n isCaseNode,\n} from \"./parser/index.mjs\";\n\n// Interpreter\nexport { Interpreter, type InterpreterOptions, BreakException, ContinueException, ExitException } from \"./interpreter/index.mjs\";\n\n// Filesystem\nexport { createVirtualFS } from \"./fs/index.mjs\";\nexport {\n FileSystem,\n ReadOnlyFileSystem,\n WebFileSystem,\n createWebUnderlyingFS,\n type PathOps,\n type Permission,\n type PermissionRules,\n type UnderlyingFS,\n} from \"./fs/index.mjs\";\n\n// I/O\nexport { createStdin, StdinImpl } from \"./io/index.mjs\";\nexport {\n createStdout,\n createStderr,\n createPipe,\n createShellInput,\n OutputCollectorImpl,\n PipeBuffer,\n ShellInputControllerImpl,\n} from \"./io/index.mjs\";\n\n// Interactive input analysis\nexport { analyzeInput } from \"./input-analysis.mjs\";\nexport type { InputAnalysis, InputIncompleteReason } from \"./input-analysis.mjs\";\n\n// Utilities\nexport { escape, escapeForInterpolation, globVirtualFS } from \"./utils/index.mjs\";\nexport type { GlobVirtualFS, GlobOptions } from \"./utils/index.mjs\";\n\n// Version Control\nexport { VersionControlSystem } from \"./vcs/index.mjs\";\nexport type {\n VCSConfig,\n VCSAttributeRule,\n VCSResolvedAttributes,\n VCSDiffMode,\n VCSPatchSuppressionReason,\n Revision,\n DiffEntry,\n TreeManifest,\n TreeEntry,\n FileEntry,\n DirectoryEntry,\n VCSIndexEntry,\n VCSIndexFile,\n CommitOptions,\n CheckoutOptions,\n LogOptions,\n LogEntry,\n BranchInfo,\n} from \"./vcs/index.mjs\";\n"
|
|
6
6
|
],
|
|
7
|
-
"mappings": ";AACA;AACA;
|
|
8
|
-
"debugId": "
|
|
7
|
+
"mappings": ";AACA;AACA;AACA;AA2BA;AAGA;AAGA;AAIA;AAsBA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAeA;AAGA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAYA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAWA;AAIA;AAIA;",
|
|
8
|
+
"debugId": "A98B7667567C2E6F64756E2164756E21",
|
|
9
9
|
"names": []
|
|
10
10
|
}
|