# Local Development — `@coda/sandbox`

This runbook covers setup, verification, and common development workflows for the `@coda/sandbox` package.

---

## Prerequisites

- **Node >= 24** — required for isolated-vm v6 compatibility. isolated-vm v6 dropped support for older Node versions when migrating to C++20. Check your version with `node --version`.
- **pnpm** — the monorepo package manager. Install via `npm install -g pnpm` if not present.
- **C++ build tools** — required to compile the isolated-vm native addon:
  - macOS: Xcode Command Line Tools (`xcode-select --install`). Xcode 15+ recommended for C++20 support.
  - Ubuntu/Debian: `sudo apt-get install build-essential`
  - Other Linux: ensure `gcc`/`g++` >= 11 and Python 3 are available (for node-gyp).

---

## Setup

```bash
# From the monorepo root
pnpm install
```

This installs all workspace dependencies and compiles native addons. The isolated-vm C++ addon compilation runs automatically via node-gyp. A successful build prints `gyp info ok` near the end of the install output.

If the build fails, see the [Troubleshooting runbook](sandbox-troubleshooting.md#build-failures).

---

## Verifying the Setup

Run these from the `sandbox/` directory to confirm everything is working:

```bash
cd sandbox

# Type check (no emit)
pnpm typecheck

# Lint
pnpm lint

# Unit tests
pnpm test:unit

# Build
pnpm build
```

All four should complete without errors on a clean setup. If `test:unit` hangs, see [Isolate tests hang](sandbox-troubleshooting.md#isolate-tests-hang-never-complete) in the troubleshooting runbook.

---

## Development Workflow

| Location                   | Purpose                              |
| -------------------------- | ------------------------------------ |
| `sandbox/src/`             | All TypeScript source                |
| `sandbox/src/**/*.test.ts` | Tests, co-located with source        |
| `sandbox/dist/`            | Build output (generated, gitignored) |
| `sandbox/wasm/`            | WASM binaries and JS binding scripts |

Run `pnpm dev` from `sandbox/` to start watch mode. The package rebuilds automatically when source files change.

---

## Adding a New Test

1. Create `sandbox/src/path/to/feature.test.ts` alongside the file being tested.

2. Import from local source using the `.js` extension (ESM convention; ts-jest resolves `.ts` files transparently):

   ```typescript
   import { Foo } from "./foo.js";
   ```

3. Run the new test file directly:
   ```bash
   node --experimental-vm-modules node_modules/jest/bin/jest.js src/path/to/feature.test.ts
   ```

See the [Testing guide](../../guides/testing.md) for guidelines on unit vs integration tests and cleanup requirements.

---

## Adding a New WASM Module

1. Place the `.wasm` binary and its JS binding script in `sandbox/wasm/` (or a configured path).

2. Add a `WasmModuleConfig` entry to the engine configuration:

   ```typescript
   {
     name: 'my-module',
     wasmPath: './wasm/my-module.wasm',
     jsBindingPath: './wasm/my-module-bindings.js',
   }
   ```

3. Call `wasmLoader.loadAll([...newConfig])` before submitting any executions that use the module.

4. Write a unit test that loads the module and verifies the binding is available in the isolate context. Reference `src/execution/wasm/wasm-loader.test.ts` for the pattern.

---

## Common Development Commands

All commands should be run from the `sandbox/` directory unless otherwise noted.

```bash
# Type check (no emit)
pnpm typecheck

# Lint (ESLint)
pnpm lint

# Format (Prettier)
pnpm format

# Build (tsdown, produces dist/)
pnpm build

# Watch mode (rebuilds on file changes)
pnpm dev

# Full test run (lint + unit tests + coverage)
pnpm test

# Unit tests only
pnpm test:unit

# Unit tests with coverage report
pnpm test:unit --coverage

# Unit tests, specific file
node --experimental-vm-modules node_modules/jest/bin/jest.js src/bridge/session.test.ts

# Unit tests matching a name pattern
node --experimental-vm-modules node_modules/jest/bin/jest.js --testNamePattern "timeout"

# Clean build artifacts
pnpm clean
```

After running `pnpm test:unit --coverage`, open the HTML report:

```bash
open coverage/lcov-report/index.html
```

---

## Monorepo Integration

**Workspace registration:** The `sandbox` package is listed in the root `pnpm-workspace.yaml` under `packages:`. pnpm treats it as a local workspace package and links it into other packages by name.

**Native addon build:** `isolated-vm` is listed in the root `pnpm-workspace.yaml` (or root `package.json`) under `onlyBuiltDependencies` to ensure node-gyp compiles the C++ addon during `pnpm install`. Without this, pnpm may skip the build step.

**Importing from other packages:**

```typescript
import { SandboxEngine } from "@coda/sandbox";
```

**Package exports:** The package uses the `exports` field in `sandbox/package.json` for ESM-only distribution:

```json
{
  "exports": {
    ".": "./dist/index.mjs"
  }
}
```

Type declarations are provided via `./dist/index.d.mts`. There is no CommonJS entry point; importing packages must be ESM.
