@computesdk/just-bash 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.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 computesdk
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 ADDED
@@ -0,0 +1,387 @@
1
+ # @computesdk/just-bash
2
+
3
+ [just-bash](https://justbash.dev/) provider for ComputeSDK - Local sandboxed bash execution with a virtual filesystem. No external services, containers, or authentication required.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @computesdk/just-bash
9
+ ```
10
+
11
+ ## Quick Start
12
+
13
+ ### Gateway Mode (Recommended)
14
+
15
+ Use the gateway for zero-config auto-detection:
16
+
17
+ ```typescript
18
+ import { compute } from 'computesdk';
19
+
20
+ // just-bash is always available - no credentials needed
21
+ const sandbox = await compute.sandbox.create();
22
+
23
+ const result = await sandbox.runCode('echo "Hello from just-bash!"');
24
+ console.log(result.output); // "Hello from just-bash!"
25
+
26
+ await sandbox.destroy();
27
+ ```
28
+
29
+ ### Direct Mode
30
+
31
+ For direct SDK usage without the gateway:
32
+
33
+ ```typescript
34
+ import { justBash } from '@computesdk/just-bash';
35
+
36
+ const compute = justBash({});
37
+
38
+ const sandbox = await compute.sandbox.create();
39
+
40
+ const result = await sandbox.runCommand('echo "Hello" | tr a-z A-Z');
41
+ console.log(result.stdout); // "HELLO"
42
+
43
+ await sandbox.destroy();
44
+ ```
45
+
46
+ ## Configuration
47
+
48
+ ### Environment Variables
49
+
50
+ No environment variables are required. just-bash runs entirely locally.
51
+
52
+ ### Configuration Options
53
+
54
+ ```typescript
55
+ interface JustBashConfig {
56
+ /** Enable Python support via pyodide (disabled by default) */
57
+ python?: boolean;
58
+ /** Initial files to populate in the virtual filesystem */
59
+ files?: Record<string, string>;
60
+ /** Initial environment variables */
61
+ env?: Record<string, string>;
62
+ /** Working directory (defaults to /home/user) */
63
+ cwd?: string;
64
+ /** Custom filesystem implementation (see Filesystem Backends below) */
65
+ fs?: IFileSystem;
66
+ /** Custom commands created with defineCommand() (see Custom Commands below) */
67
+ customCommands?: CustomCommand[];
68
+ /** Network configuration for curl (disabled by default) */
69
+ network?: NetworkConfig;
70
+ }
71
+ ```
72
+
73
+ ## Filesystem Backends
74
+
75
+ By default, just-bash uses an **InMemoryFs** — a pure in-memory filesystem. You can swap in alternative backends depending on your use case:
76
+
77
+ ### InMemoryFs (default)
78
+
79
+ All files live in memory. Fast, deterministic, fully isolated.
80
+
81
+ ```typescript
82
+ const compute = justBash({}); // InMemoryFs is the default
83
+ ```
84
+
85
+ ### OverlayFs (copy-on-write)
86
+
87
+ Reads from a real directory on disk; writes stay in memory. The underlying directory is never modified.
88
+
89
+ ```typescript
90
+ import { OverlayFs } from 'just-bash';
91
+
92
+ const compute = justBash({
93
+ fs: new OverlayFs({ root: '/path/to/project' }),
94
+ cwd: '/path/to/project',
95
+ });
96
+ ```
97
+
98
+ ### ReadWriteFs (direct disk access)
99
+
100
+ Reads and writes go directly to a real directory. Use with caution — changes are real.
101
+
102
+ ```typescript
103
+ import { ReadWriteFs } from 'just-bash';
104
+
105
+ const compute = justBash({
106
+ fs: new ReadWriteFs({ root: '/tmp/sandbox' }),
107
+ });
108
+ ```
109
+
110
+ ### MountableFs (compose multiple filesystems)
111
+
112
+ Mount different filesystem backends at different paths.
113
+
114
+ ```typescript
115
+ import { MountableFs, InMemoryFs } from 'just-bash';
116
+ import { OverlayFs } from 'just-bash';
117
+
118
+ const compute = justBash({
119
+ fs: new MountableFs({
120
+ base: new InMemoryFs(),
121
+ mounts: [
122
+ { mountPoint: '/project', filesystem: new OverlayFs({ root: '/real/project' }) },
123
+ ],
124
+ }),
125
+ cwd: '/project',
126
+ });
127
+ ```
128
+
129
+ ## Custom Commands
130
+
131
+ You can extend just-bash with custom commands using `defineCommand()`:
132
+
133
+ ```typescript
134
+ import { justBash } from '@computesdk/just-bash';
135
+ import { defineCommand } from 'just-bash';
136
+
137
+ const hello = defineCommand('hello', async (args, ctx) => {
138
+ const name = args[0] || 'world';
139
+ return {
140
+ stdout: `Hello, ${name}!\n`,
141
+ stderr: '',
142
+ exitCode: 0,
143
+ };
144
+ });
145
+
146
+ const compute = justBash({ customCommands: [hello] });
147
+ const sandbox = await compute.sandbox.create();
148
+
149
+ const result = await sandbox.runCommand('hello Alice');
150
+ console.log(result.stdout); // "Hello, Alice!\n"
151
+ ```
152
+
153
+ Custom commands receive a context object (`ctx`) with access to:
154
+ - `ctx.fs` — the virtual filesystem
155
+ - `ctx.cwd` — current working directory
156
+ - `ctx.env` — environment variables
157
+ - `ctx.stdin` — standard input
158
+ - `ctx.exec(command)` — run subcommands
159
+
160
+ ## API Reference
161
+
162
+ ### Code Execution
163
+
164
+ ```typescript
165
+ // Execute bash scripts
166
+ const result = await sandbox.runCode(`
167
+ for i in 1 2 3; do
168
+ echo "Number: $i"
169
+ done
170
+ `);
171
+ console.log(result.output);
172
+ // Number: 1
173
+ // Number: 2
174
+ // Number: 3
175
+
176
+ // Execute Python code (requires python: true in config)
177
+ const compute = justBash({ python: true });
178
+ const sandbox = await compute.sandbox.create();
179
+
180
+ const result = await sandbox.runCode(`
181
+ import json
182
+ data = {"message": "Hello from Python"}
183
+ print(json.dumps(data))
184
+ `, 'python');
185
+ ```
186
+
187
+ ### Command Execution
188
+
189
+ ```typescript
190
+ // Pipes and text processing
191
+ const result = await sandbox.runCommand('echo -e "banana\\napple\\ncherry" | sort');
192
+ console.log(result.stdout); // "apple\nbanana\ncherry\n"
193
+
194
+ // JSON processing with jq
195
+ await sandbox.filesystem.writeFile('/data.json', '[{"name":"Alice"},{"name":"Bob"}]');
196
+ const result = await sandbox.runCommand('cat /data.json | jq ".[].name"');
197
+
198
+ // Environment variables per command
199
+ const result = await sandbox.runCommand('echo $MY_VAR', { env: { MY_VAR: 'hello' } });
200
+
201
+ // Working directory per command
202
+ const result = await sandbox.runCommand('cat config.json', { cwd: '/app' });
203
+ ```
204
+
205
+ ### Filesystem Operations
206
+
207
+ ```typescript
208
+ // Write file
209
+ await sandbox.filesystem.writeFile('/tmp/hello.txt', 'Hello World');
210
+
211
+ // Read file
212
+ const content = await sandbox.filesystem.readFile('/tmp/hello.txt');
213
+
214
+ // Create directory
215
+ await sandbox.filesystem.mkdir('/tmp/data');
216
+
217
+ // List directory contents
218
+ const files = await sandbox.filesystem.readdir('/tmp');
219
+
220
+ // Check if file exists
221
+ const exists = await sandbox.filesystem.exists('/tmp/hello.txt');
222
+
223
+ // Remove file or directory
224
+ await sandbox.filesystem.remove('/tmp/hello.txt');
225
+ ```
226
+
227
+ ### Sandbox Management
228
+
229
+ ```typescript
230
+ // Get sandbox info
231
+ const info = await sandbox.getInfo();
232
+ console.log(info.id, info.provider, info.status);
233
+
234
+ // List all active sandboxes
235
+ const sandboxes = await compute.sandbox.list();
236
+
237
+ // Get sandbox by ID
238
+ const existing = await compute.sandbox.getById('sandbox-id');
239
+
240
+ // Destroy sandbox
241
+ await sandbox.destroy();
242
+ ```
243
+
244
+ ### Pre-populated Files
245
+
246
+ ```typescript
247
+ const compute = justBash({
248
+ files: {
249
+ '/app/config.json': '{"port": 3000}',
250
+ '/app/data.csv': 'name,age\nAlice,25\nBob,30',
251
+ },
252
+ env: {
253
+ APP_ENV: 'production',
254
+ },
255
+ cwd: '/app',
256
+ });
257
+
258
+ const sandbox = await compute.sandbox.create();
259
+ const result = await sandbox.runCommand('cat config.json');
260
+ console.log(result.stdout); // {"port": 3000}
261
+ ```
262
+
263
+ ## Built-in Commands
264
+
265
+ just-bash includes 60+ built-in commands:
266
+
267
+ | Category | Commands |
268
+ |----------|----------|
269
+ | **File ops** | `cat`, `cp`, `ls`, `mkdir`, `mv`, `rm`, `touch`, `tree`, `ln`, `find` |
270
+ | **Text processing** | `awk`, `grep`, `sed`, `cut`, `sort`, `uniq`, `wc`, `head`, `tail`, `tr` |
271
+ | **Data processing** | `jq` (JSON), `yq` (YAML/XML), `sqlite3` (SQLite), CSV tools |
272
+ | **Compression** | `gzip`, `tar` |
273
+ | **Utilities** | `echo`, `printf`, `date`, `seq`, `timeout`, `basename`, `dirname` |
274
+ | **Shell** | `export`, `source`, `alias`, `test`, `read`, `set`, `unset` |
275
+
276
+ ## Error Handling
277
+
278
+ ```typescript
279
+ import { justBash } from '@computesdk/just-bash';
280
+
281
+ const compute = justBash({});
282
+ const sandbox = await compute.sandbox.create();
283
+
284
+ const result = await sandbox.runCommand('cat /nonexistent');
285
+ if (result.exitCode !== 0) {
286
+ console.error('Command failed:', result.stderr);
287
+ }
288
+
289
+ // getUrl throws since just-bash has no network
290
+ try {
291
+ await sandbox.getUrl({ port: 3000 });
292
+ } catch (error) {
293
+ console.error(error.message); // "just-bash is a local sandbox without network capabilities..."
294
+ }
295
+ ```
296
+
297
+ ## Examples
298
+
299
+ ### Data Pipeline
300
+
301
+ ```typescript
302
+ import { justBash } from '@computesdk/just-bash';
303
+
304
+ const compute = justBash({});
305
+ const sandbox = await compute.sandbox.create();
306
+
307
+ // Create CSV data
308
+ await sandbox.filesystem.writeFile('/data/sales.csv',
309
+ 'product,quantity,price\nWidget,100,9.99\nGadget,50,24.99\nDoohickey,200,4.99'
310
+ );
311
+
312
+ // Process with awk
313
+ const result = await sandbox.runCommand(
314
+ 'cat /data/sales.csv | tail -n +2 | awk -F, \'{ total += $2 * $3 } END { printf "Total revenue: $%.2f\\n", total }\''
315
+ );
316
+ console.log(result.stdout); // Total revenue: $3247.50
317
+
318
+ await sandbox.destroy();
319
+ ```
320
+
321
+ ### JSON Processing
322
+
323
+ ```typescript
324
+ import { justBash } from '@computesdk/just-bash';
325
+
326
+ const compute = justBash({
327
+ files: {
328
+ '/data/users.json': JSON.stringify([
329
+ { name: 'Alice', age: 30, role: 'admin' },
330
+ { name: 'Bob', age: 25, role: 'user' },
331
+ { name: 'Charlie', age: 35, role: 'admin' },
332
+ ]),
333
+ },
334
+ });
335
+ const sandbox = await compute.sandbox.create();
336
+
337
+ // Filter admins and extract names
338
+ const result = await sandbox.runCommand(
339
+ 'cat /data/users.json | jq \'[.[] | select(.role == "admin") | .name]\''
340
+ );
341
+ console.log(result.stdout); // ["Alice", "Charlie"]
342
+
343
+ await sandbox.destroy();
344
+ ```
345
+
346
+ ### Script Execution
347
+
348
+ ```typescript
349
+ import { justBash } from '@computesdk/just-bash';
350
+
351
+ const compute = justBash({});
352
+ const sandbox = await compute.sandbox.create();
353
+
354
+ const result = await sandbox.runCode(`
355
+ #!/bin/bash
356
+ count=0
357
+ for f in /proc/self/status /etc/hostname; do
358
+ if test -f "$f"; then
359
+ count=$((count + 1))
360
+ fi
361
+ done
362
+ echo "Found $count system files"
363
+ `);
364
+
365
+ console.log(result.output);
366
+
367
+ await sandbox.destroy();
368
+ ```
369
+
370
+ ## Limitations
371
+
372
+ - **No Network Access** - `getUrl()` is not supported; `curl` requires explicit `network` config
373
+ - **No Real Processes** - Commands are interpreted in TypeScript, not executed as real OS processes
374
+ - **No Node.js Runtime** - `runCode` with `node` runtime executes as bash, not actual Node.js
375
+ - **In-Memory by Default** - Files don't persist unless you use `OverlayFs`, `ReadWriteFs`, or `MountableFs`
376
+ - **Python via Pyodide** - Python support requires `python: true` and uses pyodide (WebAssembly-based)
377
+
378
+ ## When to Use just-bash
379
+
380
+ - **Testing & Development** - Fast, no-cost sandbox for development and CI
381
+ - **AI Agent Tools** - Secure bash execution for AI code generation
382
+ - **Offline Environments** - No network or API keys required
383
+ - **Unit Tests** - Deterministic, isolated test environments
384
+
385
+ ## License
386
+
387
+ MIT
@@ -0,0 +1,48 @@
1
+ import * as _computesdk_provider from '@computesdk/provider';
2
+ import { Bash, BashOptions } from 'just-bash';
3
+
4
+ /**
5
+ * just-bash-specific configuration options
6
+ */
7
+ interface JustBashConfig {
8
+ /** Enable Python support via pyodide (disabled by default) */
9
+ python?: boolean;
10
+ /** Initial files to populate in the virtual filesystem */
11
+ files?: BashOptions['files'];
12
+ /** Initial environment variables */
13
+ env?: Record<string, string>;
14
+ /** Working directory (defaults to /home/user) */
15
+ cwd?: string;
16
+ /**
17
+ * Custom filesystem implementation.
18
+ * Defaults to InMemoryFs. Use OverlayFs for copy-on-write over a real directory,
19
+ * ReadWriteFs for direct disk access, or MountableFs to combine multiple filesystems.
20
+ */
21
+ fs?: BashOptions['fs'];
22
+ /**
23
+ * Custom commands to register alongside built-in commands.
24
+ * Created with `defineCommand()` from just-bash.
25
+ */
26
+ customCommands?: BashOptions['customCommands'];
27
+ /** Network configuration for commands like curl */
28
+ network?: BashOptions['network'];
29
+ }
30
+ /** Internal sandbox state */
31
+ interface JustBashSandbox {
32
+ bash: Bash;
33
+ id: string;
34
+ createdAt: Date;
35
+ config: JustBashConfig;
36
+ }
37
+ /**
38
+ * Create a just-bash provider instance using the factory pattern
39
+ *
40
+ * just-bash provides local sandboxed bash execution with:
41
+ * - Virtual filesystem (in-memory)
42
+ * - 60+ built-in commands (cat, grep, sed, awk, jq, etc.)
43
+ * - Python support via pyodide
44
+ * - No external dependencies or authentication required
45
+ */
46
+ declare const justBash: (config: JustBashConfig) => _computesdk_provider.Provider<JustBashSandbox, any, any>;
47
+
48
+ export { type JustBashConfig, type JustBashSandbox, justBash };
@@ -0,0 +1,48 @@
1
+ import * as _computesdk_provider from '@computesdk/provider';
2
+ import { Bash, BashOptions } from 'just-bash';
3
+
4
+ /**
5
+ * just-bash-specific configuration options
6
+ */
7
+ interface JustBashConfig {
8
+ /** Enable Python support via pyodide (disabled by default) */
9
+ python?: boolean;
10
+ /** Initial files to populate in the virtual filesystem */
11
+ files?: BashOptions['files'];
12
+ /** Initial environment variables */
13
+ env?: Record<string, string>;
14
+ /** Working directory (defaults to /home/user) */
15
+ cwd?: string;
16
+ /**
17
+ * Custom filesystem implementation.
18
+ * Defaults to InMemoryFs. Use OverlayFs for copy-on-write over a real directory,
19
+ * ReadWriteFs for direct disk access, or MountableFs to combine multiple filesystems.
20
+ */
21
+ fs?: BashOptions['fs'];
22
+ /**
23
+ * Custom commands to register alongside built-in commands.
24
+ * Created with `defineCommand()` from just-bash.
25
+ */
26
+ customCommands?: BashOptions['customCommands'];
27
+ /** Network configuration for commands like curl */
28
+ network?: BashOptions['network'];
29
+ }
30
+ /** Internal sandbox state */
31
+ interface JustBashSandbox {
32
+ bash: Bash;
33
+ id: string;
34
+ createdAt: Date;
35
+ config: JustBashConfig;
36
+ }
37
+ /**
38
+ * Create a just-bash provider instance using the factory pattern
39
+ *
40
+ * just-bash provides local sandboxed bash execution with:
41
+ * - Virtual filesystem (in-memory)
42
+ * - 60+ built-in commands (cat, grep, sed, awk, jq, etc.)
43
+ * - Python support via pyodide
44
+ * - No external dependencies or authentication required
45
+ */
46
+ declare const justBash: (config: JustBashConfig) => _computesdk_provider.Provider<JustBashSandbox, any, any>;
47
+
48
+ export { type JustBashConfig, type JustBashSandbox, justBash };
package/dist/index.js ADDED
@@ -0,0 +1,236 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ justBash: () => justBash
24
+ });
25
+ module.exports = __toCommonJS(index_exports);
26
+ var import_just_bash = require("just-bash");
27
+ var import_provider = require("@computesdk/provider");
28
+ var activeSandboxes = /* @__PURE__ */ new Map();
29
+ var justBash = (0, import_provider.defineProvider)({
30
+ name: "just-bash",
31
+ methods: {
32
+ sandbox: {
33
+ /**
34
+ * Create a new just-bash sandbox
35
+ */
36
+ create: async (config, options) => {
37
+ const sandboxId = options?.sandboxId || `just-bash-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
38
+ if (options?.sandboxId && activeSandboxes.has(options.sandboxId)) {
39
+ const existing = activeSandboxes.get(options.sandboxId);
40
+ return { sandbox: existing, sandboxId: existing.id };
41
+ }
42
+ const bash = new import_just_bash.Bash({
43
+ files: config.files,
44
+ env: {
45
+ ...config.env,
46
+ ...options?.envs
47
+ },
48
+ cwd: config.cwd || "/home/user",
49
+ python: config.python ?? options?.runtime === "python",
50
+ fs: config.fs,
51
+ customCommands: config.customCommands,
52
+ network: config.network
53
+ });
54
+ const sandbox = {
55
+ bash,
56
+ id: sandboxId,
57
+ createdAt: /* @__PURE__ */ new Date(),
58
+ config
59
+ };
60
+ activeSandboxes.set(sandboxId, sandbox);
61
+ return { sandbox, sandboxId };
62
+ },
63
+ /**
64
+ * Get an existing just-bash sandbox by ID
65
+ */
66
+ getById: async (_config, sandboxId) => {
67
+ const sandbox = activeSandboxes.get(sandboxId);
68
+ if (!sandbox) return null;
69
+ return { sandbox, sandboxId };
70
+ },
71
+ /**
72
+ * List all active just-bash sandboxes
73
+ */
74
+ list: async (_config) => {
75
+ return Array.from(activeSandboxes.entries()).map(([sandboxId, sandbox]) => ({
76
+ sandbox,
77
+ sandboxId
78
+ }));
79
+ },
80
+ /**
81
+ * Destroy a just-bash sandbox
82
+ */
83
+ destroy: async (_config, sandboxId) => {
84
+ activeSandboxes.delete(sandboxId);
85
+ },
86
+ /**
87
+ * Execute code in the sandbox
88
+ *
89
+ * For Python: executes via the built-in python3 command (pyodide)
90
+ * For Node/JS: wraps code in a bash script that evaluates it
91
+ */
92
+ runCode: async (sandbox, code, runtime) => {
93
+ const effectiveRuntime = runtime || (code.includes("print(") || code.includes("import ") || code.includes("def ") || code.includes("sys.") || code.includes("json.") || code.includes("__") || code.includes('f"') || code.includes("f'") || code.includes("raise ") ? "python" : "node");
94
+ let result;
95
+ if (effectiveRuntime === "python") {
96
+ const tempFile = `/tmp/_computesdk_run_${Date.now()}.py`;
97
+ await sandbox.bash.writeFile(tempFile, code);
98
+ result = await sandbox.bash.exec(`python3 ${tempFile}`);
99
+ } else {
100
+ const tempFile = `/tmp/_computesdk_run_${Date.now()}.sh`;
101
+ await sandbox.bash.writeFile(tempFile, code);
102
+ result = await sandbox.bash.exec(`bash ${tempFile}`);
103
+ }
104
+ const output = result.stderr ? `${result.stdout}${result.stdout && result.stderr ? "\n" : ""}${result.stderr}` : result.stdout;
105
+ return {
106
+ output,
107
+ exitCode: result.exitCode,
108
+ language: effectiveRuntime
109
+ };
110
+ },
111
+ /**
112
+ * Execute a shell command in the sandbox
113
+ */
114
+ runCommand: async (sandbox, command, options) => {
115
+ const startTime = Date.now();
116
+ try {
117
+ const execOptions = {};
118
+ if (options?.env && Object.keys(options.env).length > 0) {
119
+ execOptions.env = options.env;
120
+ }
121
+ if (options?.cwd) {
122
+ execOptions.cwd = options.cwd;
123
+ }
124
+ const result = await sandbox.bash.exec(
125
+ command,
126
+ Object.keys(execOptions).length > 0 ? execOptions : void 0
127
+ );
128
+ return {
129
+ stdout: result.stdout || "",
130
+ stderr: result.stderr || "",
131
+ exitCode: result.exitCode,
132
+ durationMs: Date.now() - startTime
133
+ };
134
+ } catch (error) {
135
+ return {
136
+ stdout: "",
137
+ stderr: error instanceof Error ? error.message : String(error),
138
+ exitCode: 127,
139
+ durationMs: Date.now() - startTime
140
+ };
141
+ }
142
+ },
143
+ /**
144
+ * Get sandbox information
145
+ */
146
+ getInfo: async (sandbox) => {
147
+ return {
148
+ id: sandbox.id,
149
+ provider: "just-bash",
150
+ runtime: sandbox.config.python ? "python" : "node",
151
+ status: "running",
152
+ createdAt: sandbox.createdAt,
153
+ timeout: 0,
154
+ // No timeout - local execution
155
+ metadata: {
156
+ type: "local",
157
+ cwd: sandbox.bash.getCwd()
158
+ }
159
+ };
160
+ },
161
+ /**
162
+ * Get URL for a port - not supported for local execution
163
+ */
164
+ getUrl: async (_sandbox, options) => {
165
+ throw new Error(
166
+ `just-bash is a local sandbox without network capabilities. Cannot expose port ${options.port}.`
167
+ );
168
+ },
169
+ /**
170
+ * Filesystem operations using the just-bash virtual filesystem
171
+ */
172
+ filesystem: {
173
+ readFile: async (sandbox, path, _runCommand) => {
174
+ return sandbox.bash.readFile(path);
175
+ },
176
+ writeFile: async (sandbox, path, content, _runCommand) => {
177
+ const parentDir = path.substring(0, path.lastIndexOf("/")) || "/";
178
+ if (parentDir !== "/") {
179
+ await sandbox.bash.exec(`mkdir -p ${parentDir}`);
180
+ }
181
+ await sandbox.bash.writeFile(path, content);
182
+ },
183
+ mkdir: async (sandbox, path, _runCommand) => {
184
+ const result = await sandbox.bash.exec(`mkdir -p ${path}`);
185
+ if (result.exitCode !== 0) {
186
+ throw new Error(`Failed to create directory ${path}: ${result.stderr}`);
187
+ }
188
+ },
189
+ readdir: async (sandbox, path, _runCommand) => {
190
+ const result = await sandbox.bash.exec(`ls -la ${path}`);
191
+ if (result.exitCode !== 0) {
192
+ throw new Error(`Failed to list directory ${path}: ${result.stderr}`);
193
+ }
194
+ const entries = [];
195
+ const lines = result.stdout.trim().split("\n");
196
+ for (const line of lines) {
197
+ if (!line || line.startsWith("total")) continue;
198
+ const parts = line.split(/\s+/);
199
+ if (parts.length < 9) continue;
200
+ const permissions = parts[0];
201
+ const name = parts.slice(8).join(" ");
202
+ if (name === "." || name === "..") continue;
203
+ entries.push({
204
+ name,
205
+ type: permissions.startsWith("d") ? "directory" : "file",
206
+ size: parseInt(parts[4], 10) || 0,
207
+ modified: /* @__PURE__ */ new Date()
208
+ });
209
+ }
210
+ return entries;
211
+ },
212
+ exists: async (sandbox, path, _runCommand) => {
213
+ const result = await sandbox.bash.exec(`test -f ${path} || test -d ${path}`);
214
+ return result.exitCode === 0;
215
+ },
216
+ remove: async (sandbox, path, _runCommand) => {
217
+ const result = await sandbox.bash.exec(`rm -rf ${path}`);
218
+ if (result.exitCode !== 0) {
219
+ throw new Error(`Failed to remove ${path}: ${result.stderr}`);
220
+ }
221
+ }
222
+ },
223
+ /**
224
+ * Get the native JustBashSandbox instance for advanced usage
225
+ */
226
+ getInstance: (sandbox) => {
227
+ return sandbox;
228
+ }
229
+ }
230
+ }
231
+ });
232
+ // Annotate the CommonJS export names for ESM import in node:
233
+ 0 && (module.exports = {
234
+ justBash
235
+ });
236
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * just-bash Provider - Factory-based Implementation\n *\n * Local sandboxed bash execution using the just-bash package.\n * Provides a virtual filesystem and bash shell environment\n * without requiring any external services or containers.\n *\n * Features:\n * - Pure TypeScript bash interpreter (no real processes)\n * - In-memory virtual filesystem\n * - Python support via pyodide (optional)\n * - Shell command execution with 60+ built-in commands\n * - No authentication required - runs entirely locally\n */\n\nimport { Bash } from 'just-bash';\nimport type { BashExecResult, BashOptions } from 'just-bash';\nimport { defineProvider } from '@computesdk/provider';\nimport type {\n CodeResult,\n CommandResult,\n SandboxInfo,\n Runtime,\n CreateSandboxOptions,\n FileEntry,\n RunCommandOptions,\n} from 'computesdk';\n\n/**\n * just-bash-specific configuration options\n */\nexport interface JustBashConfig {\n /** Enable Python support via pyodide (disabled by default) */\n python?: boolean;\n /** Initial files to populate in the virtual filesystem */\n files?: BashOptions['files'];\n /** Initial environment variables */\n env?: Record<string, string>;\n /** Working directory (defaults to /home/user) */\n cwd?: string;\n /**\n * Custom filesystem implementation.\n * Defaults to InMemoryFs. Use OverlayFs for copy-on-write over a real directory,\n * ReadWriteFs for direct disk access, or MountableFs to combine multiple filesystems.\n */\n fs?: BashOptions['fs'];\n /**\n * Custom commands to register alongside built-in commands.\n * Created with `defineCommand()` from just-bash.\n */\n customCommands?: BashOptions['customCommands'];\n /** Network configuration for commands like curl */\n network?: BashOptions['network'];\n}\n\n/** Internal sandbox state */\ninterface JustBashSandbox {\n bash: Bash;\n id: string;\n createdAt: Date;\n config: JustBashConfig;\n}\n\n/** Active sandboxes registry */\nconst activeSandboxes = new Map<string, JustBashSandbox>();\n\n/**\n * Create a just-bash provider instance using the factory pattern\n *\n * just-bash provides local sandboxed bash execution with:\n * - Virtual filesystem (in-memory)\n * - 60+ built-in commands (cat, grep, sed, awk, jq, etc.)\n * - Python support via pyodide\n * - No external dependencies or authentication required\n */\nexport const justBash = defineProvider<JustBashSandbox, JustBashConfig>({\n name: 'just-bash',\n methods: {\n sandbox: {\n /**\n * Create a new just-bash sandbox\n */\n create: async (config: JustBashConfig, options?: CreateSandboxOptions) => {\n const sandboxId = options?.sandboxId || `just-bash-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;\n\n // Check if reconnecting to existing sandbox\n if (options?.sandboxId && activeSandboxes.has(options.sandboxId)) {\n const existing = activeSandboxes.get(options.sandboxId)!;\n return { sandbox: existing, sandboxId: existing.id };\n }\n\n const bash = new Bash({\n files: config.files,\n env: {\n ...config.env,\n ...options?.envs,\n },\n cwd: config.cwd || '/home/user',\n python: config.python ?? (options?.runtime === 'python'),\n fs: config.fs,\n customCommands: config.customCommands,\n network: config.network,\n });\n\n const sandbox: JustBashSandbox = {\n bash,\n id: sandboxId,\n createdAt: new Date(),\n config,\n };\n\n activeSandboxes.set(sandboxId, sandbox);\n return { sandbox, sandboxId };\n },\n\n /**\n * Get an existing just-bash sandbox by ID\n */\n getById: async (_config: JustBashConfig, sandboxId: string) => {\n const sandbox = activeSandboxes.get(sandboxId);\n if (!sandbox) return null;\n return { sandbox, sandboxId };\n },\n\n /**\n * List all active just-bash sandboxes\n */\n list: async (_config: JustBashConfig) => {\n return Array.from(activeSandboxes.entries()).map(([sandboxId, sandbox]) => ({\n sandbox,\n sandboxId,\n }));\n },\n\n /**\n * Destroy a just-bash sandbox\n */\n destroy: async (_config: JustBashConfig, sandboxId: string) => {\n activeSandboxes.delete(sandboxId);\n },\n\n /**\n * Execute code in the sandbox\n *\n * For Python: executes via the built-in python3 command (pyodide)\n * For Node/JS: wraps code in a bash script that evaluates it\n */\n runCode: async (sandbox: JustBashSandbox, code: string, runtime?: Runtime): Promise<CodeResult> => {\n const effectiveRuntime = runtime || (\n code.includes('print(') ||\n code.includes('import ') ||\n code.includes('def ') ||\n code.includes('sys.') ||\n code.includes('json.') ||\n code.includes('__') ||\n code.includes('f\"') ||\n code.includes(\"f'\") ||\n code.includes('raise ')\n ? 'python'\n : 'node'\n );\n\n let result: BashExecResult;\n\n if (effectiveRuntime === 'python') {\n // Use python3 command (requires python: true in config)\n // Write code to a temp file and execute it to avoid quoting issues\n const tempFile = `/tmp/_computesdk_run_${Date.now()}.py`;\n await sandbox.bash.writeFile(tempFile, code);\n result = await sandbox.bash.exec(`python3 ${tempFile}`);\n } else {\n // For node/JS, execute as bash script\n // just-bash doesn't have a real Node.js runtime,\n // so we execute the code as a bash script\n const tempFile = `/tmp/_computesdk_run_${Date.now()}.sh`;\n await sandbox.bash.writeFile(tempFile, code);\n result = await sandbox.bash.exec(`bash ${tempFile}`);\n }\n\n const output = result.stderr\n ? `${result.stdout}${result.stdout && result.stderr ? '\\n' : ''}${result.stderr}`\n : result.stdout;\n\n return {\n output,\n exitCode: result.exitCode,\n language: effectiveRuntime,\n };\n },\n\n /**\n * Execute a shell command in the sandbox\n */\n runCommand: async (sandbox: JustBashSandbox, command: string, options?: RunCommandOptions): Promise<CommandResult> => {\n const startTime = Date.now();\n try {\n const execOptions: { env?: Record<string, string>; cwd?: string } = {};\n\n if (options?.env && Object.keys(options.env).length > 0) {\n execOptions.env = options.env;\n }\n\n if (options?.cwd) {\n execOptions.cwd = options.cwd;\n }\n\n const result = await sandbox.bash.exec(\n command,\n Object.keys(execOptions).length > 0 ? execOptions : undefined\n );\n\n return {\n stdout: result.stdout || '',\n stderr: result.stderr || '',\n exitCode: result.exitCode,\n durationMs: Date.now() - startTime,\n };\n } catch (error) {\n return {\n stdout: '',\n stderr: error instanceof Error ? error.message : String(error),\n exitCode: 127,\n durationMs: Date.now() - startTime,\n };\n }\n },\n\n /**\n * Get sandbox information\n */\n getInfo: async (sandbox: JustBashSandbox): Promise<SandboxInfo> => {\n return {\n id: sandbox.id,\n provider: 'just-bash',\n runtime: sandbox.config.python ? 'python' : 'node',\n status: 'running',\n createdAt: sandbox.createdAt,\n timeout: 0, // No timeout - local execution\n metadata: {\n type: 'local',\n cwd: sandbox.bash.getCwd(),\n },\n };\n },\n\n /**\n * Get URL for a port - not supported for local execution\n */\n getUrl: async (_sandbox: JustBashSandbox, options: { port: number; protocol?: string }): Promise<string> => {\n throw new Error(\n `just-bash is a local sandbox without network capabilities. Cannot expose port ${options.port}.`\n );\n },\n\n /**\n * Filesystem operations using the just-bash virtual filesystem\n */\n filesystem: {\n readFile: async (sandbox: JustBashSandbox, path: string, _runCommand): Promise<string> => {\n return sandbox.bash.readFile(path);\n },\n\n writeFile: async (sandbox: JustBashSandbox, path: string, content: string, _runCommand): Promise<void> => {\n // Ensure parent directory exists\n const parentDir = path.substring(0, path.lastIndexOf('/')) || '/';\n if (parentDir !== '/') {\n await sandbox.bash.exec(`mkdir -p ${parentDir}`);\n }\n await sandbox.bash.writeFile(path, content);\n },\n\n mkdir: async (sandbox: JustBashSandbox, path: string, _runCommand): Promise<void> => {\n const result = await sandbox.bash.exec(`mkdir -p ${path}`);\n if (result.exitCode !== 0) {\n throw new Error(`Failed to create directory ${path}: ${result.stderr}`);\n }\n },\n\n readdir: async (sandbox: JustBashSandbox, path: string, _runCommand): Promise<FileEntry[]> => {\n const result = await sandbox.bash.exec(`ls -la ${path}`);\n if (result.exitCode !== 0) {\n throw new Error(`Failed to list directory ${path}: ${result.stderr}`);\n }\n\n const entries: FileEntry[] = [];\n const lines = result.stdout.trim().split('\\n');\n\n for (const line of lines) {\n // Skip total line and empty lines\n if (!line || line.startsWith('total')) continue;\n\n const parts = line.split(/\\s+/);\n if (parts.length < 9) continue;\n\n const permissions = parts[0];\n const name = parts.slice(8).join(' ');\n\n // Skip . and ..\n if (name === '.' || name === '..') continue;\n\n entries.push({\n name,\n type: permissions.startsWith('d') ? 'directory' as const : 'file' as const,\n size: parseInt(parts[4], 10) || 0,\n modified: new Date(),\n });\n }\n\n return entries;\n },\n\n exists: async (sandbox: JustBashSandbox, path: string, _runCommand): Promise<boolean> => {\n const result = await sandbox.bash.exec(`test -f ${path} || test -d ${path}`);\n return result.exitCode === 0;\n },\n\n remove: async (sandbox: JustBashSandbox, path: string, _runCommand): Promise<void> => {\n const result = await sandbox.bash.exec(`rm -rf ${path}`);\n if (result.exitCode !== 0) {\n throw new Error(`Failed to remove ${path}: ${result.stderr}`);\n }\n },\n },\n\n /**\n * Get the native JustBashSandbox instance for advanced usage\n */\n getInstance: (sandbox: JustBashSandbox): JustBashSandbox => {\n return sandbox;\n },\n },\n },\n});\n\n// Export types\nexport type { JustBashSandbox };\n"],"mappings":"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","names":[]}
package/dist/index.mjs ADDED
@@ -0,0 +1,211 @@
1
+ // src/index.ts
2
+ import { Bash } from "just-bash";
3
+ import { defineProvider } from "@computesdk/provider";
4
+ var activeSandboxes = /* @__PURE__ */ new Map();
5
+ var justBash = defineProvider({
6
+ name: "just-bash",
7
+ methods: {
8
+ sandbox: {
9
+ /**
10
+ * Create a new just-bash sandbox
11
+ */
12
+ create: async (config, options) => {
13
+ const sandboxId = options?.sandboxId || `just-bash-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
14
+ if (options?.sandboxId && activeSandboxes.has(options.sandboxId)) {
15
+ const existing = activeSandboxes.get(options.sandboxId);
16
+ return { sandbox: existing, sandboxId: existing.id };
17
+ }
18
+ const bash = new Bash({
19
+ files: config.files,
20
+ env: {
21
+ ...config.env,
22
+ ...options?.envs
23
+ },
24
+ cwd: config.cwd || "/home/user",
25
+ python: config.python ?? options?.runtime === "python",
26
+ fs: config.fs,
27
+ customCommands: config.customCommands,
28
+ network: config.network
29
+ });
30
+ const sandbox = {
31
+ bash,
32
+ id: sandboxId,
33
+ createdAt: /* @__PURE__ */ new Date(),
34
+ config
35
+ };
36
+ activeSandboxes.set(sandboxId, sandbox);
37
+ return { sandbox, sandboxId };
38
+ },
39
+ /**
40
+ * Get an existing just-bash sandbox by ID
41
+ */
42
+ getById: async (_config, sandboxId) => {
43
+ const sandbox = activeSandboxes.get(sandboxId);
44
+ if (!sandbox) return null;
45
+ return { sandbox, sandboxId };
46
+ },
47
+ /**
48
+ * List all active just-bash sandboxes
49
+ */
50
+ list: async (_config) => {
51
+ return Array.from(activeSandboxes.entries()).map(([sandboxId, sandbox]) => ({
52
+ sandbox,
53
+ sandboxId
54
+ }));
55
+ },
56
+ /**
57
+ * Destroy a just-bash sandbox
58
+ */
59
+ destroy: async (_config, sandboxId) => {
60
+ activeSandboxes.delete(sandboxId);
61
+ },
62
+ /**
63
+ * Execute code in the sandbox
64
+ *
65
+ * For Python: executes via the built-in python3 command (pyodide)
66
+ * For Node/JS: wraps code in a bash script that evaluates it
67
+ */
68
+ runCode: async (sandbox, code, runtime) => {
69
+ const effectiveRuntime = runtime || (code.includes("print(") || code.includes("import ") || code.includes("def ") || code.includes("sys.") || code.includes("json.") || code.includes("__") || code.includes('f"') || code.includes("f'") || code.includes("raise ") ? "python" : "node");
70
+ let result;
71
+ if (effectiveRuntime === "python") {
72
+ const tempFile = `/tmp/_computesdk_run_${Date.now()}.py`;
73
+ await sandbox.bash.writeFile(tempFile, code);
74
+ result = await sandbox.bash.exec(`python3 ${tempFile}`);
75
+ } else {
76
+ const tempFile = `/tmp/_computesdk_run_${Date.now()}.sh`;
77
+ await sandbox.bash.writeFile(tempFile, code);
78
+ result = await sandbox.bash.exec(`bash ${tempFile}`);
79
+ }
80
+ const output = result.stderr ? `${result.stdout}${result.stdout && result.stderr ? "\n" : ""}${result.stderr}` : result.stdout;
81
+ return {
82
+ output,
83
+ exitCode: result.exitCode,
84
+ language: effectiveRuntime
85
+ };
86
+ },
87
+ /**
88
+ * Execute a shell command in the sandbox
89
+ */
90
+ runCommand: async (sandbox, command, options) => {
91
+ const startTime = Date.now();
92
+ try {
93
+ const execOptions = {};
94
+ if (options?.env && Object.keys(options.env).length > 0) {
95
+ execOptions.env = options.env;
96
+ }
97
+ if (options?.cwd) {
98
+ execOptions.cwd = options.cwd;
99
+ }
100
+ const result = await sandbox.bash.exec(
101
+ command,
102
+ Object.keys(execOptions).length > 0 ? execOptions : void 0
103
+ );
104
+ return {
105
+ stdout: result.stdout || "",
106
+ stderr: result.stderr || "",
107
+ exitCode: result.exitCode,
108
+ durationMs: Date.now() - startTime
109
+ };
110
+ } catch (error) {
111
+ return {
112
+ stdout: "",
113
+ stderr: error instanceof Error ? error.message : String(error),
114
+ exitCode: 127,
115
+ durationMs: Date.now() - startTime
116
+ };
117
+ }
118
+ },
119
+ /**
120
+ * Get sandbox information
121
+ */
122
+ getInfo: async (sandbox) => {
123
+ return {
124
+ id: sandbox.id,
125
+ provider: "just-bash",
126
+ runtime: sandbox.config.python ? "python" : "node",
127
+ status: "running",
128
+ createdAt: sandbox.createdAt,
129
+ timeout: 0,
130
+ // No timeout - local execution
131
+ metadata: {
132
+ type: "local",
133
+ cwd: sandbox.bash.getCwd()
134
+ }
135
+ };
136
+ },
137
+ /**
138
+ * Get URL for a port - not supported for local execution
139
+ */
140
+ getUrl: async (_sandbox, options) => {
141
+ throw new Error(
142
+ `just-bash is a local sandbox without network capabilities. Cannot expose port ${options.port}.`
143
+ );
144
+ },
145
+ /**
146
+ * Filesystem operations using the just-bash virtual filesystem
147
+ */
148
+ filesystem: {
149
+ readFile: async (sandbox, path, _runCommand) => {
150
+ return sandbox.bash.readFile(path);
151
+ },
152
+ writeFile: async (sandbox, path, content, _runCommand) => {
153
+ const parentDir = path.substring(0, path.lastIndexOf("/")) || "/";
154
+ if (parentDir !== "/") {
155
+ await sandbox.bash.exec(`mkdir -p ${parentDir}`);
156
+ }
157
+ await sandbox.bash.writeFile(path, content);
158
+ },
159
+ mkdir: async (sandbox, path, _runCommand) => {
160
+ const result = await sandbox.bash.exec(`mkdir -p ${path}`);
161
+ if (result.exitCode !== 0) {
162
+ throw new Error(`Failed to create directory ${path}: ${result.stderr}`);
163
+ }
164
+ },
165
+ readdir: async (sandbox, path, _runCommand) => {
166
+ const result = await sandbox.bash.exec(`ls -la ${path}`);
167
+ if (result.exitCode !== 0) {
168
+ throw new Error(`Failed to list directory ${path}: ${result.stderr}`);
169
+ }
170
+ const entries = [];
171
+ const lines = result.stdout.trim().split("\n");
172
+ for (const line of lines) {
173
+ if (!line || line.startsWith("total")) continue;
174
+ const parts = line.split(/\s+/);
175
+ if (parts.length < 9) continue;
176
+ const permissions = parts[0];
177
+ const name = parts.slice(8).join(" ");
178
+ if (name === "." || name === "..") continue;
179
+ entries.push({
180
+ name,
181
+ type: permissions.startsWith("d") ? "directory" : "file",
182
+ size: parseInt(parts[4], 10) || 0,
183
+ modified: /* @__PURE__ */ new Date()
184
+ });
185
+ }
186
+ return entries;
187
+ },
188
+ exists: async (sandbox, path, _runCommand) => {
189
+ const result = await sandbox.bash.exec(`test -f ${path} || test -d ${path}`);
190
+ return result.exitCode === 0;
191
+ },
192
+ remove: async (sandbox, path, _runCommand) => {
193
+ const result = await sandbox.bash.exec(`rm -rf ${path}`);
194
+ if (result.exitCode !== 0) {
195
+ throw new Error(`Failed to remove ${path}: ${result.stderr}`);
196
+ }
197
+ }
198
+ },
199
+ /**
200
+ * Get the native JustBashSandbox instance for advanced usage
201
+ */
202
+ getInstance: (sandbox) => {
203
+ return sandbox;
204
+ }
205
+ }
206
+ }
207
+ });
208
+ export {
209
+ justBash
210
+ };
211
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * just-bash Provider - Factory-based Implementation\n *\n * Local sandboxed bash execution using the just-bash package.\n * Provides a virtual filesystem and bash shell environment\n * without requiring any external services or containers.\n *\n * Features:\n * - Pure TypeScript bash interpreter (no real processes)\n * - In-memory virtual filesystem\n * - Python support via pyodide (optional)\n * - Shell command execution with 60+ built-in commands\n * - No authentication required - runs entirely locally\n */\n\nimport { Bash } from 'just-bash';\nimport type { BashExecResult, BashOptions } from 'just-bash';\nimport { defineProvider } from '@computesdk/provider';\nimport type {\n CodeResult,\n CommandResult,\n SandboxInfo,\n Runtime,\n CreateSandboxOptions,\n FileEntry,\n RunCommandOptions,\n} from 'computesdk';\n\n/**\n * just-bash-specific configuration options\n */\nexport interface JustBashConfig {\n /** Enable Python support via pyodide (disabled by default) */\n python?: boolean;\n /** Initial files to populate in the virtual filesystem */\n files?: BashOptions['files'];\n /** Initial environment variables */\n env?: Record<string, string>;\n /** Working directory (defaults to /home/user) */\n cwd?: string;\n /**\n * Custom filesystem implementation.\n * Defaults to InMemoryFs. Use OverlayFs for copy-on-write over a real directory,\n * ReadWriteFs for direct disk access, or MountableFs to combine multiple filesystems.\n */\n fs?: BashOptions['fs'];\n /**\n * Custom commands to register alongside built-in commands.\n * Created with `defineCommand()` from just-bash.\n */\n customCommands?: BashOptions['customCommands'];\n /** Network configuration for commands like curl */\n network?: BashOptions['network'];\n}\n\n/** Internal sandbox state */\ninterface JustBashSandbox {\n bash: Bash;\n id: string;\n createdAt: Date;\n config: JustBashConfig;\n}\n\n/** Active sandboxes registry */\nconst activeSandboxes = new Map<string, JustBashSandbox>();\n\n/**\n * Create a just-bash provider instance using the factory pattern\n *\n * just-bash provides local sandboxed bash execution with:\n * - Virtual filesystem (in-memory)\n * - 60+ built-in commands (cat, grep, sed, awk, jq, etc.)\n * - Python support via pyodide\n * - No external dependencies or authentication required\n */\nexport const justBash = defineProvider<JustBashSandbox, JustBashConfig>({\n name: 'just-bash',\n methods: {\n sandbox: {\n /**\n * Create a new just-bash sandbox\n */\n create: async (config: JustBashConfig, options?: CreateSandboxOptions) => {\n const sandboxId = options?.sandboxId || `just-bash-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;\n\n // Check if reconnecting to existing sandbox\n if (options?.sandboxId && activeSandboxes.has(options.sandboxId)) {\n const existing = activeSandboxes.get(options.sandboxId)!;\n return { sandbox: existing, sandboxId: existing.id };\n }\n\n const bash = new Bash({\n files: config.files,\n env: {\n ...config.env,\n ...options?.envs,\n },\n cwd: config.cwd || '/home/user',\n python: config.python ?? (options?.runtime === 'python'),\n fs: config.fs,\n customCommands: config.customCommands,\n network: config.network,\n });\n\n const sandbox: JustBashSandbox = {\n bash,\n id: sandboxId,\n createdAt: new Date(),\n config,\n };\n\n activeSandboxes.set(sandboxId, sandbox);\n return { sandbox, sandboxId };\n },\n\n /**\n * Get an existing just-bash sandbox by ID\n */\n getById: async (_config: JustBashConfig, sandboxId: string) => {\n const sandbox = activeSandboxes.get(sandboxId);\n if (!sandbox) return null;\n return { sandbox, sandboxId };\n },\n\n /**\n * List all active just-bash sandboxes\n */\n list: async (_config: JustBashConfig) => {\n return Array.from(activeSandboxes.entries()).map(([sandboxId, sandbox]) => ({\n sandbox,\n sandboxId,\n }));\n },\n\n /**\n * Destroy a just-bash sandbox\n */\n destroy: async (_config: JustBashConfig, sandboxId: string) => {\n activeSandboxes.delete(sandboxId);\n },\n\n /**\n * Execute code in the sandbox\n *\n * For Python: executes via the built-in python3 command (pyodide)\n * For Node/JS: wraps code in a bash script that evaluates it\n */\n runCode: async (sandbox: JustBashSandbox, code: string, runtime?: Runtime): Promise<CodeResult> => {\n const effectiveRuntime = runtime || (\n code.includes('print(') ||\n code.includes('import ') ||\n code.includes('def ') ||\n code.includes('sys.') ||\n code.includes('json.') ||\n code.includes('__') ||\n code.includes('f\"') ||\n code.includes(\"f'\") ||\n code.includes('raise ')\n ? 'python'\n : 'node'\n );\n\n let result: BashExecResult;\n\n if (effectiveRuntime === 'python') {\n // Use python3 command (requires python: true in config)\n // Write code to a temp file and execute it to avoid quoting issues\n const tempFile = `/tmp/_computesdk_run_${Date.now()}.py`;\n await sandbox.bash.writeFile(tempFile, code);\n result = await sandbox.bash.exec(`python3 ${tempFile}`);\n } else {\n // For node/JS, execute as bash script\n // just-bash doesn't have a real Node.js runtime,\n // so we execute the code as a bash script\n const tempFile = `/tmp/_computesdk_run_${Date.now()}.sh`;\n await sandbox.bash.writeFile(tempFile, code);\n result = await sandbox.bash.exec(`bash ${tempFile}`);\n }\n\n const output = result.stderr\n ? `${result.stdout}${result.stdout && result.stderr ? '\\n' : ''}${result.stderr}`\n : result.stdout;\n\n return {\n output,\n exitCode: result.exitCode,\n language: effectiveRuntime,\n };\n },\n\n /**\n * Execute a shell command in the sandbox\n */\n runCommand: async (sandbox: JustBashSandbox, command: string, options?: RunCommandOptions): Promise<CommandResult> => {\n const startTime = Date.now();\n try {\n const execOptions: { env?: Record<string, string>; cwd?: string } = {};\n\n if (options?.env && Object.keys(options.env).length > 0) {\n execOptions.env = options.env;\n }\n\n if (options?.cwd) {\n execOptions.cwd = options.cwd;\n }\n\n const result = await sandbox.bash.exec(\n command,\n Object.keys(execOptions).length > 0 ? execOptions : undefined\n );\n\n return {\n stdout: result.stdout || '',\n stderr: result.stderr || '',\n exitCode: result.exitCode,\n durationMs: Date.now() - startTime,\n };\n } catch (error) {\n return {\n stdout: '',\n stderr: error instanceof Error ? error.message : String(error),\n exitCode: 127,\n durationMs: Date.now() - startTime,\n };\n }\n },\n\n /**\n * Get sandbox information\n */\n getInfo: async (sandbox: JustBashSandbox): Promise<SandboxInfo> => {\n return {\n id: sandbox.id,\n provider: 'just-bash',\n runtime: sandbox.config.python ? 'python' : 'node',\n status: 'running',\n createdAt: sandbox.createdAt,\n timeout: 0, // No timeout - local execution\n metadata: {\n type: 'local',\n cwd: sandbox.bash.getCwd(),\n },\n };\n },\n\n /**\n * Get URL for a port - not supported for local execution\n */\n getUrl: async (_sandbox: JustBashSandbox, options: { port: number; protocol?: string }): Promise<string> => {\n throw new Error(\n `just-bash is a local sandbox without network capabilities. Cannot expose port ${options.port}.`\n );\n },\n\n /**\n * Filesystem operations using the just-bash virtual filesystem\n */\n filesystem: {\n readFile: async (sandbox: JustBashSandbox, path: string, _runCommand): Promise<string> => {\n return sandbox.bash.readFile(path);\n },\n\n writeFile: async (sandbox: JustBashSandbox, path: string, content: string, _runCommand): Promise<void> => {\n // Ensure parent directory exists\n const parentDir = path.substring(0, path.lastIndexOf('/')) || '/';\n if (parentDir !== '/') {\n await sandbox.bash.exec(`mkdir -p ${parentDir}`);\n }\n await sandbox.bash.writeFile(path, content);\n },\n\n mkdir: async (sandbox: JustBashSandbox, path: string, _runCommand): Promise<void> => {\n const result = await sandbox.bash.exec(`mkdir -p ${path}`);\n if (result.exitCode !== 0) {\n throw new Error(`Failed to create directory ${path}: ${result.stderr}`);\n }\n },\n\n readdir: async (sandbox: JustBashSandbox, path: string, _runCommand): Promise<FileEntry[]> => {\n const result = await sandbox.bash.exec(`ls -la ${path}`);\n if (result.exitCode !== 0) {\n throw new Error(`Failed to list directory ${path}: ${result.stderr}`);\n }\n\n const entries: FileEntry[] = [];\n const lines = result.stdout.trim().split('\\n');\n\n for (const line of lines) {\n // Skip total line and empty lines\n if (!line || line.startsWith('total')) continue;\n\n const parts = line.split(/\\s+/);\n if (parts.length < 9) continue;\n\n const permissions = parts[0];\n const name = parts.slice(8).join(' ');\n\n // Skip . and ..\n if (name === '.' || name === '..') continue;\n\n entries.push({\n name,\n type: permissions.startsWith('d') ? 'directory' as const : 'file' as const,\n size: parseInt(parts[4], 10) || 0,\n modified: new Date(),\n });\n }\n\n return entries;\n },\n\n exists: async (sandbox: JustBashSandbox, path: string, _runCommand): Promise<boolean> => {\n const result = await sandbox.bash.exec(`test -f ${path} || test -d ${path}`);\n return result.exitCode === 0;\n },\n\n remove: async (sandbox: JustBashSandbox, path: string, _runCommand): Promise<void> => {\n const result = await sandbox.bash.exec(`rm -rf ${path}`);\n if (result.exitCode !== 0) {\n throw new Error(`Failed to remove ${path}: ${result.stderr}`);\n }\n },\n },\n\n /**\n * Get the native JustBashSandbox instance for advanced usage\n */\n getInstance: (sandbox: JustBashSandbox): JustBashSandbox => {\n return sandbox;\n },\n },\n },\n});\n\n// Export types\nexport type { JustBashSandbox };\n"],"mappings":"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","names":[]}
package/package.json ADDED
@@ -0,0 +1,68 @@
1
+ {
2
+ "name": "@computesdk/just-bash",
3
+ "version": "0.1.0",
4
+ "description": "just-bash provider for ComputeSDK - local sandboxed bash execution with virtual filesystem",
5
+ "author": "ComputeSDK",
6
+ "license": "MIT",
7
+ "main": "./dist/index.js",
8
+ "module": "./dist/index.mjs",
9
+ "types": "./dist/index.d.ts",
10
+ "exports": {
11
+ ".": {
12
+ "types": "./dist/index.d.ts",
13
+ "import": "./dist/index.mjs",
14
+ "require": "./dist/index.js"
15
+ }
16
+ },
17
+ "files": [
18
+ "dist"
19
+ ],
20
+ "dependencies": {
21
+ "computesdk": "2.3.0",
22
+ "@computesdk/provider": "1.0.28"
23
+ },
24
+ "peerDependencies": {
25
+ "just-bash": ">=2.0.0"
26
+ },
27
+ "devDependencies": {
28
+ "just-bash": "^2.11.5",
29
+ "@types/node": "^20.0.0",
30
+ "@vitest/coverage-v8": "^1.0.0",
31
+ "eslint": "^8.37.0",
32
+ "rimraf": "^5.0.0",
33
+ "tsup": "^8.0.0",
34
+ "typescript": "^5.0.0",
35
+ "vitest": "^1.0.0",
36
+ "@computesdk/test-utils": "1.5.1"
37
+ },
38
+ "keywords": [
39
+ "computesdk",
40
+ "just-bash",
41
+ "sandbox",
42
+ "code-execution",
43
+ "bash",
44
+ "shell",
45
+ "virtual-filesystem",
46
+ "provider",
47
+ "local"
48
+ ],
49
+ "repository": {
50
+ "type": "git",
51
+ "url": "https://github.com/computesdk/computesdk.git",
52
+ "directory": "packages/just-bash"
53
+ },
54
+ "homepage": "https://www.computesdk.com",
55
+ "bugs": {
56
+ "url": "https://github.com/computesdk/computesdk/issues"
57
+ },
58
+ "scripts": {
59
+ "build": "tsup",
60
+ "clean": "rimraf dist",
61
+ "dev": "tsup --watch",
62
+ "test": "vitest run",
63
+ "test:watch": "vitest watch",
64
+ "test:coverage": "vitest run --coverage",
65
+ "typecheck": "tsc --noEmit",
66
+ "lint": "eslint"
67
+ }
68
+ }