@anvia/sandbox 0.4.1 → 0.5.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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cli.ts","../src/image-builder.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { lstat, mkdir, readFile, rm, writeFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { assertDockerCli } from \"./docker-cli\";\nimport {\n renderSandboxImageContext,\n resolveSandboxImageSpec,\n type SandboxImageFeature,\n type SandboxImageInput,\n type SandboxImageManifest,\n type SandboxImageRuntime,\n type SandboxImageVersions,\n unpinnedSandboxImagePackages,\n} from \"./image-builder\";\n\ninterface CliOptions {\n command?: string;\n name?: string;\n tag?: string;\n output?: string;\n runtimes: SandboxImageRuntime[];\n features: SandboxImageFeature[];\n apt: string[];\n npm: string[];\n uv: string[];\n versions: Partial<SandboxImageVersions>;\n dockerPath: string;\n build: boolean;\n buildExplicit: boolean;\n dryRun: boolean;\n force: boolean;\n help: boolean;\n}\n\nexport interface SandboxImageCliIo {\n log(message: string): void;\n warn(message: string): void;\n error(message: string): void;\n stdout(chunk: Uint8Array): void;\n stderr(chunk: Uint8Array): void;\n}\n\nexport interface SandboxImagePromptResult {\n name: string;\n runtimes: SandboxImageRuntime[];\n features: SandboxImageFeature[];\n apt: string[];\n npm: string[];\n uv: string[];\n tag?: string;\n output?: string;\n build: boolean;\n}\n\nexport interface SandboxImageCliDependencies {\n isTTY?: boolean;\n packageVersion?: string;\n prompt?: (options: Readonly<CliOptions>) => Promise<SandboxImagePromptResult | undefined>;\n buildImage?: (input: {\n contextPath: string;\n tag: string;\n dockerPath: string;\n io: SandboxImageCliIo;\n }) => Promise<void>;\n}\n\nconst generatedFileNames = new Set([\n \".dockerignore\",\n \"Dockerfile\",\n \"anvia-sandbox.json\",\n \"package.json\",\n \"pyproject.toml\",\n]);\n\nconst commonAptPackages = [\n { value: \"git\", label: \"Git\", hint: \"Source control and repository operations\" },\n { value: \"curl\", label: \"curl\", hint: \"HTTP downloads and API debugging\" },\n { value: \"jq\", label: \"jq\", hint: \"JSON processing from the shell\" },\n { value: \"ffmpeg\", label: \"FFmpeg\", hint: \"Audio and video processing\" },\n { value: \"imagemagick\", label: \"ImageMagick\", hint: \"Image conversion and editing\" },\n { value: \"poppler-utils\", label: \"Poppler tools\", hint: \"PDF inspection and conversion\" },\n { value: \"libreoffice\", label: \"LibreOffice\", hint: \"Large; office document conversion\" },\n] as const;\n\nconst commonNpmPackages = [\n { value: \"pdfkit@0.19.1\", label: \"PDFKit\", hint: \"Generate PDF documents\" },\n { value: \"sharp@0.35.3\", label: \"Sharp\", hint: \"Resize and transform images\" },\n { value: \"exceljs@4.4.0\", label: \"ExcelJS\", hint: \"Read and write Excel workbooks\" },\n { value: \"docx@9.7.1\", label: \"docx\", hint: \"Generate Word documents\" },\n { value: \"pptxgenjs@4.0.1\", label: \"PptxGenJS\", hint: \"Generate PowerPoint presentations\" },\n] as const;\n\nconst commonUvPackages = [\n { value: \"httpx==0.28.1\", label: \"HTTPX\", hint: \"Modern HTTP client\" },\n { value: \"beautifulsoup4==4.15.0\", label: \"Beautiful Soup\", hint: \"HTML and XML parsing\" },\n { value: \"scipy==1.18.0\", label: \"SciPy\", hint: \"Scientific computing\" },\n { value: \"scikit-learn==1.9.0\", label: \"scikit-learn\", hint: \"Machine learning utilities\" },\n { value: \"polars==1.42.1\", label: \"Polars\", hint: \"Fast dataframe processing\" },\n] as const;\n\nconst defaultIo: SandboxImageCliIo = {\n log: console.log,\n warn: console.warn,\n error: console.error,\n stdout: (chunk) => process.stdout.write(chunk),\n stderr: (chunk) => process.stderr.write(chunk),\n};\n\nexport async function runCli(\n argv: string[] = process.argv.slice(2),\n cwd = process.cwd(),\n io: SandboxImageCliIo = defaultIo,\n dependencies: SandboxImageCliDependencies = {},\n): Promise<number> {\n let options: CliOptions;\n try {\n options = parseArgs(argv);\n } catch (error) {\n io.error(errorMessage(error));\n io.log(helpText());\n return 1;\n }\n\n if (options.help || options.command === undefined) {\n io.log(helpText());\n return 0;\n }\n if (options.command !== \"create-image\") {\n io.error(`Unknown command: ${options.command}`);\n io.log(helpText());\n return 1;\n }\n\n try {\n const shouldPrompt =\n options.name === undefined ||\n (options.runtimes.length === 0 &&\n options.features.length === 0 &&\n options.npm.length === 0 &&\n options.uv.length === 0);\n if (shouldPrompt) {\n const isTTY = dependencies.isTTY ?? (process.stdin.isTTY && process.stdout.isTTY);\n if (!isTTY) {\n throw new Error(\n \"Non-interactive create-image requires --name and at least one --runtime or --feature.\",\n );\n }\n const prompt = dependencies.prompt ?? promptForImage;\n const result = await prompt(options);\n if (result === undefined) return 130;\n options = applyPromptResult(options, result);\n }\n\n const input: SandboxImageInput = {\n name: required(options.name, \"Image name is required.\"),\n runtimes: options.runtimes,\n features: options.features,\n packages: {\n apt: options.apt,\n npm: options.npm,\n uv: options.uv,\n },\n versions: options.versions,\n };\n if (options.tag !== undefined) input.tag = options.tag;\n\n const spec = resolveSandboxImageSpec(input);\n const packageVersion = dependencies.packageVersion ?? (await readPackageVersion());\n const context = renderSandboxImageContext(spec, packageVersion);\n const outputPath = path.resolve(\n cwd,\n options.output ?? path.join(\".anvia\", \"sandbox-images\", spec.name),\n );\n const displayPath = relativeDisplayPath(cwd, outputPath);\n const unpinned = unpinnedSandboxImagePackages(spec);\n if (unpinned.length > 0) {\n io.warn(`Unpinned custom packages may change on rebuild: ${unpinned.join(\", \")}`);\n }\n\n if (options.dryRun) {\n printDryRun(context.files, displayPath, spec.tag, io);\n return 0;\n }\n\n await writeImageContext(outputPath, context.manifest, context.files, options.force);\n io.log(`Created ${displayPath}`);\n\n if (!options.build) {\n io.log(\"\");\n io.log(\"Build later:\");\n io.log(` ${shellCommand([options.dockerPath, \"build\", \"--tag\", spec.tag, displayPath])}`);\n printUsageSnippet(spec.tag, io);\n return 0;\n }\n\n const buildImage = dependencies.buildImage ?? buildDockerImage;\n await buildImage({\n contextPath: outputPath,\n tag: spec.tag,\n dockerPath: options.dockerPath,\n io,\n });\n io.log(`Built ${spec.tag}`);\n printUsageSnippet(spec.tag, io);\n return 0;\n } catch (error) {\n io.error(errorMessage(error));\n return 1;\n }\n}\n\nasync function promptForImage(\n options: Readonly<CliOptions>,\n): Promise<SandboxImagePromptResult | undefined> {\n assertInteractiveNodeVersion();\n const prompts = await import(\"@clack/prompts\");\n prompts.intro(\"Create an Anvia sandbox image\");\n\n const nameResult =\n options.name ??\n (await prompts.text({\n message: \"Image name\",\n placeholder: \"reports\",\n validate: (value) =>\n /^[a-z0-9][a-z0-9-]{0,62}$/.test(value ?? \"\")\n ? undefined\n : \"Use 1-63 lowercase letters, numbers, or hyphens.\",\n }));\n if (prompts.isCancel(nameResult)) return cancelPrompt(prompts);\n const name = String(nameResult);\n\n let runtimes = [...options.runtimes];\n let features = [...options.features];\n if (\n runtimes.length === 0 &&\n features.length === 0 &&\n options.npm.length === 0 &&\n options.uv.length === 0\n ) {\n const capabilities = await prompts.multiselect<SandboxImageRuntime | SandboxImageFeature>({\n message: \"Select runtimes and features\",\n required: true,\n options: [\n { value: \"node\", label: \"Node.js\", hint: \"Includes npm and pnpm\" },\n { value: \"bun\", label: \"Bun\", hint: \"Includes bun and bunx\" },\n { value: \"python\", label: \"Python\", hint: \"Includes uv and uvx\" },\n { value: \"artifacts\", label: \"Reporting and artifacts\", hint: \"Adds Python automatically\" },\n { value: \"playwright\", label: \"Playwright + Chromium\", hint: \"Adds Node.js automatically\" },\n ],\n });\n if (prompts.isCancel(capabilities)) return cancelPrompt(prompts);\n runtimes = capabilities.filter(isRuntime);\n features = capabilities.filter(isFeature);\n }\n\n const aptResult = await selectCommonPackages(\n prompts,\n \"Select common apt tools (optional)\",\n commonAptPackages,\n options.apt,\n );\n if (aptResult === undefined) return cancelPrompt(prompts);\n const npmResult = await selectCommonPackages(\n prompts,\n \"Select common npm libraries (optional)\",\n commonNpmPackages,\n options.npm,\n );\n if (npmResult === undefined) return cancelPrompt(prompts);\n const uvResult = await selectCommonPackages(\n prompts,\n \"Select common Python libraries with uv (optional)\",\n commonUvPackages,\n options.uv,\n );\n if (uvResult === undefined) return cancelPrompt(prompts);\n\n const tagResult =\n options.tag ??\n (await prompts.text({\n message: \"Docker image tag\",\n initialValue: `anvia-sandbox-${name}:latest`,\n }));\n if (prompts.isCancel(tagResult)) return cancelPrompt(prompts);\n const outputResult =\n options.output ??\n (await prompts.text({\n message: \"Generated source directory\",\n initialValue: path.join(\".anvia\", \"sandbox-images\", name),\n }));\n if (prompts.isCancel(outputResult)) return cancelPrompt(prompts);\n\n const buildResult = options.buildExplicit\n ? options.build\n : await prompts.confirm({ message: \"Build the image now?\", initialValue: true });\n if (prompts.isCancel(buildResult)) return cancelPrompt(prompts);\n const confirmed = await prompts.confirm({\n message: \"Create this sandbox image?\",\n initialValue: true,\n });\n if (prompts.isCancel(confirmed) || !confirmed) return cancelPrompt(prompts);\n\n prompts.outro(\"Configuration ready\");\n return {\n name,\n runtimes,\n features,\n apt: aptResult,\n npm: npmResult,\n uv: uvResult,\n tag: String(tagResult),\n output: String(outputResult),\n build: Boolean(buildResult),\n };\n}\n\nasync function selectCommonPackages(\n prompts: typeof import(\"@clack/prompts\"),\n message: string,\n options: readonly { value: string; label: string; hint: string }[],\n existing: readonly string[],\n): Promise<string[] | undefined> {\n const commonValues = new Set(options.map((option) => option.value));\n const result = await prompts.multiselect<string>({\n message,\n required: false,\n options: [...options],\n initialValues: existing.filter((value) => commonValues.has(value)),\n });\n if (prompts.isCancel(result)) return undefined;\n return [...new Set([...existing, ...result])];\n}\n\nfunction cancelPrompt(prompts: typeof import(\"@clack/prompts\")): undefined {\n prompts.cancel(\"Image creation cancelled.\");\n return undefined;\n}\n\nasync function buildDockerImage(input: {\n contextPath: string;\n tag: string;\n dockerPath: string;\n io: SandboxImageCliIo;\n}): Promise<void> {\n await assertDockerCli([\"build\", \"--tag\", input.tag, input.contextPath], {\n dockerPath: input.dockerPath,\n onStdout: input.io.stdout,\n onStderr: input.io.stderr,\n });\n}\n\nasync function writeImageContext(\n outputPath: string,\n manifest: SandboxImageManifest,\n files: ReadonlyMap<string, string>,\n force: boolean,\n): Promise<void> {\n const outputStat = await safeLstat(outputPath);\n if (outputStat?.isSymbolicLink()) {\n throw new Error(`Refusing to write through symlink: ${outputPath}`);\n }\n\n if (outputStat !== undefined) {\n if (!outputStat.isDirectory()) throw new Error(`Output path is not a directory: ${outputPath}`);\n const previousManifest = await readGeneratedManifest(outputPath);\n if (previousManifest === undefined) {\n throw new Error(\n `Output directory already exists but was not generated by @anvia/sandbox: ${outputPath}`,\n );\n }\n if (!force) throw new Error(`Output directory already exists. Use --force to regenerate it.`);\n\n for (const filename of previousManifest.generatedFiles) {\n const target = path.join(outputPath, filename);\n const targetStat = await safeLstat(target);\n if (targetStat?.isSymbolicLink()) throw new Error(`Refusing to replace symlink: ${target}`);\n if (targetStat !== undefined) await rm(target);\n }\n } else {\n await mkdir(outputPath, { recursive: true });\n }\n\n for (const [filename, content] of files) {\n if (!generatedFileNames.has(filename))\n throw new Error(`Unexpected generated filename: ${filename}`);\n const target = path.join(outputPath, filename);\n const targetStat = await safeLstat(target);\n if (targetStat?.isSymbolicLink()) throw new Error(`Refusing to replace symlink: ${target}`);\n await writeFile(target, content, \"utf8\");\n }\n\n if (!files.has(\"anvia-sandbox.json\") || manifest.generatedFiles.length !== files.size) {\n throw new Error(\"Generated image context manifest is inconsistent.\");\n }\n}\n\nasync function readGeneratedManifest(\n outputPath: string,\n): Promise<SandboxImageManifest | undefined> {\n const manifestPath = path.join(outputPath, \"anvia-sandbox.json\");\n const stat = await safeLstat(manifestPath);\n if (stat === undefined) return undefined;\n if (stat.isSymbolicLink() || !stat.isFile()) {\n throw new Error(`Invalid generated manifest: ${manifestPath}`);\n }\n\n let value: unknown;\n try {\n value = JSON.parse(await readFile(manifestPath, \"utf8\"));\n } catch (error) {\n throw new Error(`Unable to read generated manifest: ${manifestPath}`, { cause: error });\n }\n if (!isGeneratedManifest(value)) {\n throw new Error(\n `Output manifest is not recognized as an @anvia/sandbox manifest: ${manifestPath}`,\n );\n }\n return value;\n}\n\nfunction isGeneratedManifest(value: unknown): value is SandboxImageManifest {\n if (typeof value !== \"object\" || value === null) return false;\n const record = value as Record<string, unknown>;\n const generatedBy = record.generatedBy as Record<string, unknown> | undefined;\n const files = record.generatedFiles;\n return (\n record.schemaVersion === 1 &&\n generatedBy?.package === \"@anvia/sandbox\" &&\n Array.isArray(files) &&\n files.every((file) => typeof file === \"string\" && generatedFileNames.has(file))\n );\n}\n\nasync function safeLstat(target: string) {\n try {\n return await lstat(target);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") return undefined;\n throw error;\n }\n}\n\nfunction printDryRun(\n files: ReadonlyMap<string, string>,\n outputPath: string,\n tag: string,\n io: SandboxImageCliIo,\n): void {\n io.log(`Would create ${outputPath}`);\n for (const [filename, content] of files) {\n io.log(\"\");\n io.log(`--- ${filename}`);\n io.log(content.trimEnd());\n }\n io.log(\"\");\n io.log(`Would build ${tag}`);\n}\n\nfunction printUsageSnippet(tag: string, io: SandboxImageCliIo): void {\n io.log(\"\");\n io.log(\"Use with @anvia/sandbox:\");\n io.log(\" const sandbox = new DockerSandbox({\");\n io.log(` image: ${JSON.stringify(tag)},`);\n io.log(' pull: \"never\",');\n io.log(\" });\");\n}\n\nfunction applyPromptResult(options: CliOptions, result: SandboxImagePromptResult): CliOptions {\n const next: CliOptions = {\n ...options,\n name: result.name,\n runtimes: result.runtimes,\n features: result.features,\n apt: result.apt,\n npm: result.npm,\n uv: result.uv,\n build: result.build,\n buildExplicit: true,\n };\n if (result.tag !== undefined) next.tag = result.tag;\n if (result.output !== undefined) next.output = result.output;\n return next;\n}\n\nfunction parseArgs(argv: string[]): CliOptions {\n const options: CliOptions = {\n runtimes: [],\n features: [],\n apt: [],\n npm: [],\n uv: [],\n versions: {},\n dockerPath: \"docker\",\n build: true,\n buildExplicit: false,\n dryRun: false,\n force: false,\n help: false,\n };\n\n for (let index = 0; index < argv.length; index += 1) {\n const argument = argv[index] ?? \"\";\n if (!argument.startsWith(\"-\")) {\n if (options.command !== undefined) throw new Error(`Unexpected argument: ${argument}`);\n options.command = argument;\n continue;\n }\n\n const [flag, inlineValue] = splitFlag(argument);\n const value = () => inlineValue ?? required(argv[++index], `${flag} requires a value.`);\n switch (flag) {\n case \"-h\":\n case \"--help\":\n options.help = true;\n break;\n case \"--name\":\n options.name = value();\n break;\n case \"--tag\":\n options.tag = value();\n break;\n case \"--output\":\n options.output = value();\n break;\n case \"--runtime\":\n options.runtimes.push(parseRuntime(value()));\n break;\n case \"--feature\":\n options.features.push(parseFeature(value()));\n break;\n case \"--apt\":\n options.apt.push(value());\n break;\n case \"--npm\":\n options.npm.push(value());\n break;\n case \"--uv\":\n options.uv.push(value());\n break;\n case \"--node-version\":\n options.versions.node = value();\n break;\n case \"--pnpm-version\":\n options.versions.pnpm = value();\n break;\n case \"--bun-version\":\n options.versions.bun = value();\n break;\n case \"--python-version\":\n options.versions.python = value();\n break;\n case \"--uv-version\":\n options.versions.uv = value();\n break;\n case \"--playwright-version\":\n options.versions.playwright = value();\n break;\n case \"--docker-path\":\n options.dockerPath = value();\n break;\n case \"--no-build\":\n rejectInlineValue(flag, inlineValue);\n options.build = false;\n options.buildExplicit = true;\n break;\n case \"--dry-run\":\n rejectInlineValue(flag, inlineValue);\n options.dryRun = true;\n break;\n case \"--force\":\n rejectInlineValue(flag, inlineValue);\n options.force = true;\n break;\n default:\n throw new Error(`Unknown option: ${flag}`);\n }\n }\n return options;\n}\n\nfunction splitFlag(argument: string): [string, string | undefined] {\n const separator = argument.indexOf(\"=\");\n return separator === -1\n ? [argument, undefined]\n : [argument.slice(0, separator), argument.slice(separator + 1)];\n}\n\nfunction rejectInlineValue(flag: string, value: string | undefined): void {\n if (value !== undefined) throw new Error(`${flag} does not accept a value.`);\n}\n\nfunction parseRuntime(value: string): SandboxImageRuntime {\n if (isRuntime(value)) return value;\n throw new Error(`Unknown runtime: ${value}. Expected node, bun, or python.`);\n}\n\nfunction parseFeature(value: string): SandboxImageFeature {\n if (isFeature(value)) return value;\n throw new Error(`Unknown feature: ${value}. Expected artifacts or playwright.`);\n}\n\nfunction isRuntime(value: string): value is SandboxImageRuntime {\n return value === \"node\" || value === \"bun\" || value === \"python\";\n}\n\nfunction isFeature(value: string): value is SandboxImageFeature {\n return value === \"artifacts\" || value === \"playwright\";\n}\n\nfunction assertInteractiveNodeVersion(): void {\n const [major = 0, minor = 0] = process.versions.node.split(\".\").map(Number);\n if (major < 20 || (major === 20 && minor < 12)) {\n throw new Error(\"The interactive create-image wizard requires Node.js 20.12 or newer.\");\n }\n}\n\nasync function readPackageVersion(): Promise<string> {\n const packageJson = JSON.parse(\n await readFile(new URL(\"../package.json\", import.meta.url), \"utf8\"),\n ) as {\n version?: unknown;\n };\n return typeof packageJson.version === \"string\" ? packageJson.version : \"unknown\";\n}\n\nfunction relativeDisplayPath(cwd: string, target: string): string {\n const relative = path.relative(cwd, target);\n return relative && !relative.startsWith(\"..\") ? relative : target;\n}\n\nfunction shellCommand(args: readonly string[]): string {\n return args.map(shellArgument).join(\" \");\n}\n\nfunction shellArgument(value: string): string {\n if (/^[a-zA-Z0-9_./:@+-]+$/.test(value)) return value;\n return `'${value.replaceAll(\"'\", `'\"'\"'`)}'`;\n}\n\nfunction required<T>(value: T | undefined, message: string): T {\n if (value === undefined || value === \"\") throw new Error(message);\n return value;\n}\n\nfunction errorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\nfunction helpText(): string {\n return `Usage:\n pnpm dlx @anvia/sandbox create-image [options]\n\nOptions:\n --name <slug> Image profile name\n --runtime <node|bun|python> Runtime to include; repeatable\n --feature <artifacts|playwright>\n Curated feature to include; repeatable\n --apt <package> Additional apt package; repeatable\n --npm <package[@version]> Additional npm package; repeatable\n --uv <requirement> Additional Python package installed with uv; repeatable\n --tag <tag> Local image tag\n --output <directory> Generated context directory\n --node-version <version> Override Node.js version\n --pnpm-version <version> Override pnpm version\n --bun-version <version> Override Bun version\n --python-version <version> Override Python version\n --uv-version <version> Override uv version\n --playwright-version <version> Override Playwright and browser image version\n --docker-path <path> Docker CLI path (default: docker)\n --no-build Generate files without building\n --dry-run Print generated files without writing or building\n --force Regenerate a context previously created by this CLI\n -h, --help Show this help\n\nExamples:\n pnpm dlx @anvia/sandbox create-image\n pnpm dlx @anvia/sandbox create-image --name reports --feature artifacts\n pnpm dlx @anvia/sandbox create-image --name browser --runtime bun --feature playwright`;\n}\n\nconst invokedPath = process.argv[1] === undefined ? undefined : path.resolve(process.argv[1]);\nif (invokedPath !== undefined && invokedPath === fileURLToPath(import.meta.url)) {\n runCli().then((code) => {\n process.exitCode = code;\n });\n}\n","export type SandboxImageRuntime = \"node\" | \"bun\" | \"python\";\nexport type SandboxImageFeature = \"artifacts\" | \"playwright\";\n\nexport interface SandboxImageVersions {\n node: string;\n pnpm: string;\n bun: string;\n python: string;\n uv: string;\n playwright: string;\n}\n\nexport interface SandboxImagePackages {\n apt: string[];\n npm: string[];\n uv: string[];\n}\n\nexport interface SandboxImageInput {\n name: string;\n tag?: string;\n runtimes?: readonly SandboxImageRuntime[];\n features?: readonly SandboxImageFeature[];\n packages?: Partial<SandboxImagePackages>;\n versions?: Partial<SandboxImageVersions>;\n}\n\nexport interface SandboxImageSpec {\n name: string;\n tag: string;\n runtimes: SandboxImageRuntime[];\n features: SandboxImageFeature[];\n packages: SandboxImagePackages;\n versions: SandboxImageVersions;\n}\n\nexport interface SandboxImageManifest extends SandboxImageSpec {\n schemaVersion: 1;\n generatedBy: {\n package: \"@anvia/sandbox\";\n version: string;\n };\n generatedFiles: string[];\n}\n\nexport interface SandboxImageContext {\n manifest: SandboxImageManifest;\n files: ReadonlyMap<string, string>;\n}\n\nexport const defaultSandboxImageVersions: Readonly<SandboxImageVersions> = {\n node: \"24.18.0\",\n pnpm: \"11.0.4\",\n bun: \"1.3.14\",\n python: \"3.13.14\",\n uv: \"0.11.29\",\n playwright: \"1.61.0\",\n};\n\nexport const artifactPythonPackages = [\n \"matplotlib==3.11.1\",\n \"seaborn==0.13.2\",\n \"Pillow==12.3.0\",\n \"ReportLab==5.0.0\",\n \"pypdf==6.14.2\",\n \"pandas==3.0.3\",\n \"openpyxl==3.1.5\",\n \"XlsxWriter==3.2.9\",\n \"python-docx==1.2.0\",\n] as const;\n\nconst runtimeOrder: SandboxImageRuntime[] = [\"node\", \"bun\", \"python\"];\nconst featureOrder: SandboxImageFeature[] = [\"artifacts\", \"playwright\"];\nconst commonAptPackages = [\"bash\", \"ca-certificates\", \"findutils\", \"libstdc++6\", \"procps\"];\n\nexport function resolveSandboxImageSpec(input: SandboxImageInput): SandboxImageSpec {\n validateName(input.name);\n\n const runtimes = new Set(input.runtimes ?? []);\n const features = new Set(input.features ?? []);\n const packages: SandboxImagePackages = {\n apt: unique(input.packages?.apt ?? []),\n npm: unique(input.packages?.npm ?? []),\n uv: unique(input.packages?.uv ?? []),\n };\n\n for (const runtime of runtimes) validateRuntime(runtime);\n for (const feature of features) validateFeature(feature);\n for (const packageName of packages.apt) validateAptPackage(packageName);\n for (const packageSpec of packages.npm) parseNpmPackageSpec(packageSpec);\n for (const requirement of packages.uv) validateUvRequirement(requirement);\n\n if (features.has(\"artifacts\") || packages.uv.length > 0) runtimes.add(\"python\");\n if (features.has(\"playwright\")) runtimes.add(\"node\");\n if (packages.npm.length > 0 && !runtimes.has(\"node\") && !runtimes.has(\"bun\")) {\n runtimes.add(\"node\");\n }\n\n if (runtimes.size === 0) {\n throw new Error(\"Select at least one runtime or feature.\");\n }\n\n const versions = { ...defaultSandboxImageVersions, ...input.versions };\n for (const [name, version] of Object.entries(versions)) validateVersion(name, version);\n\n const tag = input.tag ?? `anvia-sandbox-${input.name}:latest`;\n validateImageTag(tag);\n\n return {\n name: input.name,\n tag,\n runtimes: runtimeOrder.filter((runtime) => runtimes.has(runtime)),\n features: featureOrder.filter((feature) => features.has(feature)),\n packages,\n versions,\n };\n}\n\nexport function renderSandboxImageContext(\n spec: SandboxImageSpec,\n generatorVersion: string,\n): SandboxImageContext {\n const files = new Map<string, string>();\n const pythonRequirements = [\n ...(spec.features.includes(\"artifacts\") ? artifactPythonPackages : []),\n ...spec.packages.uv,\n ];\n const npmDependencies = npmDependenciesFor(spec);\n\n files.set(\"Dockerfile\", `${renderDockerfile(spec, pythonRequirements, npmDependencies)}\\n`);\n files.set(\n \".dockerignore\",\n renderDockerignore(pythonRequirements.length > 0, npmDependencies.size > 0),\n );\n\n if (pythonRequirements.length > 0) {\n files.set(\"pyproject.toml\", renderPythonProject(spec, unique(pythonRequirements)));\n }\n if (npmDependencies.size > 0) {\n files.set(\n \"package.json\",\n `${JSON.stringify(\n {\n private: true,\n description: `Generated dependencies for ${spec.name}`,\n dependencies: Object.fromEntries(npmDependencies),\n },\n null,\n 2,\n )}\\n`,\n );\n }\n\n const generatedFiles = [...files.keys(), \"anvia-sandbox.json\"].sort();\n const manifest: SandboxImageManifest = {\n schemaVersion: 1,\n generatedBy: {\n package: \"@anvia/sandbox\",\n version: generatorVersion,\n },\n ...spec,\n generatedFiles,\n };\n files.set(\"anvia-sandbox.json\", `${JSON.stringify(manifest, null, 2)}\\n`);\n\n return { manifest, files };\n}\n\nexport function unpinnedSandboxImagePackages(spec: SandboxImageSpec): string[] {\n const unpinned: string[] = [];\n for (const value of spec.packages.npm) {\n if (parseNpmPackageSpec(value).version === \"latest\") unpinned.push(value);\n }\n for (const value of spec.packages.uv) {\n if (!/===|==|@\\s*https?:/i.test(value)) unpinned.push(value);\n }\n return unpinned;\n}\n\nfunction renderDockerfile(\n spec: SandboxImageSpec,\n pythonRequirements: readonly string[],\n npmDependencies: ReadonlyMap<string, string>,\n): string {\n const hasNode = spec.runtimes.includes(\"node\");\n const hasBun = spec.runtimes.includes(\"bun\");\n const hasPython = spec.runtimes.includes(\"python\");\n const hasPlaywright = spec.features.includes(\"playwright\");\n const lines = [\n \"# Generated by @anvia/sandbox. Edit the manifest and regenerate instead of editing this file.\",\n ];\n\n if (hasNode) lines.push(`FROM node:${spec.versions.node}-bookworm-slim AS node-runtime`);\n if (hasPython) lines.push(`FROM python:${spec.versions.python}-slim-bookworm AS python-runtime`);\n if (hasBun) lines.push(`FROM oven/bun:${spec.versions.bun}-slim AS bun-runtime`);\n if (hasPython) lines.push(`FROM ghcr.io/astral-sh/uv:${spec.versions.uv} AS uv-runtime`);\n\n if (hasPlaywright) {\n lines.push(`FROM mcr.microsoft.com/playwright:v${spec.versions.playwright}-noble AS final`);\n } else if (hasPython) {\n lines.push(\"FROM python-runtime AS final\");\n } else if (hasNode) {\n lines.push(\"FROM node-runtime AS final\");\n } else {\n lines.push(\"FROM bun-runtime AS final\");\n }\n\n lines.push(\"\", \"USER root\");\n\n if (hasPython && (hasPlaywright || !isFinalRuntime(spec, \"python\"))) {\n lines.push(\"COPY --from=python-runtime /usr/local/ /usr/local/\");\n }\n if (hasNode && (hasPlaywright || !isFinalRuntime(spec, \"node\"))) {\n lines.push(\"COPY --from=node-runtime /usr/local/bin/ /usr/local/bin/\");\n lines.push(\n \"COPY --from=node-runtime /usr/local/lib/node_modules/ /usr/local/lib/node_modules/\",\n );\n }\n if (hasBun && !isFinalRuntime(spec, \"bun\")) {\n lines.push(\"COPY --from=bun-runtime /usr/local/bin/bun /usr/local/bin/bun\");\n lines.push(\"RUN ln -sf /usr/local/bin/bun /usr/local/bin/bunx\");\n }\n if (hasPython) {\n lines.push(\"COPY --from=uv-runtime /uv /uvx /usr/local/bin/\");\n }\n\n const aptPackages = unique([\n ...commonAptPackages,\n ...(spec.features.includes(\"artifacts\") ? [\"fonts-dejavu-core\"] : []),\n ...spec.packages.apt,\n ]).sort();\n lines.push(\n \"\",\n \"RUN apt-get update \\\\\",\n ` && apt-get install -y --no-install-recommends ${aptPackages.map(shellQuote).join(\" \")} \\\\`,\n \" && rm -rf /var/lib/apt/lists/*\",\n );\n\n if (hasNode) {\n lines.push(\n \"\",\n `RUN npm install --global ${shellQuote(`pnpm@${spec.versions.pnpm}`)} --no-audit --no-fund \\\\`,\n \" && npm cache clean --force\",\n );\n }\n\n if (pythonRequirements.length > 0) {\n lines.push(\n \"\",\n \"COPY pyproject.toml /opt/anvia-python/pyproject.toml\",\n \"RUN cd /opt/anvia-python \\\\\",\n \" && uv sync --no-dev --no-cache --no-install-project\",\n \"ENV VIRTUAL_ENV=/opt/anvia-python/.venv\",\n \"ENV PATH=/opt/anvia-python/.venv/bin:$PATH\",\n );\n }\n\n if (npmDependencies.size > 0) {\n lines.push(\"\", \"COPY package.json /opt/anvia-js/package.json\");\n if (hasNode) {\n lines.push(\n \"RUN npm install --prefix /opt/anvia-js --omit=dev --no-audit --no-fund \\\\\",\n \" && ln -s /opt/anvia-js/node_modules /node_modules \\\\\",\n \" && npm cache clean --force\",\n );\n } else {\n lines.push(\n \"RUN cd /opt/anvia-js \\\\\",\n \" && bun install --production --no-save \\\\\",\n \" && ln -s /opt/anvia-js/node_modules /node_modules\",\n );\n }\n lines.push(\"ENV NODE_PATH=/opt/anvia-js/node_modules\");\n lines.push(\"ENV PATH=/opt/anvia-js/node_modules/.bin:$PATH\");\n }\n\n lines.push(\n \"\",\n ...(hasPlaywright ? [\"ENV PLAYWRIGHT_BROWSERS_PATH=/ms-playwright\"] : []),\n \"RUN mkdir -p /workspace\",\n \"WORKDIR /workspace\",\n \"ENTRYPOINT []\",\n 'CMD [\"sh\", \"-c\", \"trap \\'exit 0\\' TERM INT; while :; do sleep 3600 & wait $!; done\"]',\n );\n\n return lines.join(\"\\n\");\n}\n\nfunction renderDockerignore(hasPython: boolean, hasNpm: boolean): string {\n return [\n \"**\",\n \"!Dockerfile\",\n \"!.dockerignore\",\n \"!anvia-sandbox.json\",\n ...(hasPython ? [\"!pyproject.toml\"] : []),\n ...(hasNpm ? [\"!package.json\"] : []),\n \"\",\n ].join(\"\\n\");\n}\n\nfunction renderPythonProject(spec: SandboxImageSpec, requirements: readonly string[]): string {\n const [major, minor] = spec.versions.python.split(\".\");\n return [\n \"[project]\",\n `name = ${JSON.stringify(`anvia-sandbox-${spec.name}`)}`,\n 'version = \"0.0.0\"',\n `requires-python = ${JSON.stringify(`>=${major}.${minor}`)}`,\n \"dependencies = [\",\n ...requirements.map((requirement) => ` ${JSON.stringify(requirement)},`),\n \"]\",\n \"\",\n ].join(\"\\n\");\n}\n\nfunction npmDependenciesFor(spec: SandboxImageSpec): Map<string, string> {\n const dependencies = new Map<string, string>();\n if (spec.features.includes(\"playwright\")) {\n dependencies.set(\"playwright\", spec.versions.playwright);\n }\n for (const packageSpec of spec.packages.npm) {\n const parsed = parseNpmPackageSpec(packageSpec);\n if (dependencies.has(parsed.name)) {\n throw new Error(`Duplicate npm package: ${parsed.name}`);\n }\n dependencies.set(parsed.name, parsed.version);\n }\n return new Map([...dependencies.entries()].sort(([left], [right]) => left.localeCompare(right)));\n}\n\nfunction isFinalRuntime(spec: SandboxImageSpec, runtime: SandboxImageRuntime): boolean {\n if (spec.features.includes(\"playwright\")) return false;\n if (spec.runtimes.includes(\"python\")) return runtime === \"python\";\n if (spec.runtimes.includes(\"node\")) return runtime === \"node\";\n return runtime === \"bun\";\n}\n\nfunction validateName(name: string): void {\n if (!/^[a-z0-9][a-z0-9-]{0,62}$/.test(name)) {\n throw new Error(\n \"Image name must be 1-63 lowercase letters, numbers, or hyphens and cannot start with a hyphen.\",\n );\n }\n}\n\nfunction validateRuntime(runtime: string): asserts runtime is SandboxImageRuntime {\n if (!runtimeOrder.includes(runtime as SandboxImageRuntime)) {\n throw new Error(`Unknown runtime: ${runtime}. Expected node, bun, or python.`);\n }\n}\n\nfunction validateFeature(feature: string): asserts feature is SandboxImageFeature {\n if (!featureOrder.includes(feature as SandboxImageFeature)) {\n throw new Error(`Unknown feature: ${feature}. Expected artifacts or playwright.`);\n }\n}\n\nfunction validateAptPackage(packageName: string): void {\n if (!/^[a-zA-Z0-9][a-zA-Z0-9.+:~=-]*$/.test(packageName)) {\n throw new Error(`Invalid apt package: ${packageName}`);\n }\n}\n\nfunction parseNpmPackageSpec(packageSpec: string): { name: string; version: string } {\n if (/\\s/.test(packageSpec) || hasControlCharacter(packageSpec)) {\n throw new Error(`Invalid npm package spec: ${packageSpec}`);\n }\n\n const separator = packageSpec.startsWith(\"@\")\n ? packageSpec.indexOf(\"@\", packageSpec.indexOf(\"/\") + 1)\n : packageSpec.indexOf(\"@\");\n const name = separator === -1 ? packageSpec : packageSpec.slice(0, separator);\n const version = separator === -1 ? \"latest\" : packageSpec.slice(separator + 1);\n\n if (!/^(?:@[a-z0-9][a-z0-9._-]*\\/)?[a-z0-9][a-z0-9._-]*$/i.test(name) || !version) {\n throw new Error(`Invalid npm package spec: ${packageSpec}`);\n }\n if (/[\\s'\"`$;&|<>\\\\]/.test(version) || hasControlCharacter(version)) {\n throw new Error(`Invalid npm package version in: ${packageSpec}`);\n }\n return { name, version };\n}\n\nfunction validateUvRequirement(requirement: string): void {\n if (!requirement || requirement.startsWith(\"-\") || hasControlCharacter(requirement)) {\n throw new Error(`Invalid uv package requirement: ${requirement}`);\n }\n}\n\nfunction validateVersion(name: string, version: string): void {\n if (!/^[a-zA-Z0-9][a-zA-Z0-9._-]*$/.test(version)) {\n throw new Error(`Invalid ${name} version: ${version}`);\n }\n}\n\nfunction validateImageTag(tag: string): void {\n if (\n !tag ||\n tag.startsWith(\"-\") ||\n tag.includes(\"@\") ||\n /\\s/.test(tag) ||\n hasControlCharacter(tag)\n ) {\n throw new Error(`Invalid Docker image tag: ${tag}`);\n }\n}\n\nfunction unique(values: readonly string[]): string[] {\n return [...new Set(values)];\n}\n\nfunction hasControlCharacter(value: string): boolean {\n return [...value].some((character) => character.charCodeAt(0) < 32);\n}\n\nfunction shellQuote(value: string): string {\n return `'${value.replaceAll(\"'\", `'\"'\"'`)}'`;\n}\n"],"mappings":"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","names":["commonAptPackages"]}
package/dist/index.js CHANGED
@@ -1,3 +1,18 @@
1
+ import {
2
+ SandboxDockerCommandError,
3
+ SandboxDockerUnavailableError,
4
+ SandboxError,
5
+ SandboxFileSizeError,
6
+ SandboxPathError,
7
+ SandboxPortError,
8
+ SandboxProcessError,
9
+ SandboxSessionDestroyedError,
10
+ SandboxTimeoutError,
11
+ SandboxToolPolicyError,
12
+ assertDockerCli,
13
+ runDockerCli
14
+ } from "./chunk-FTNNCT6S.js";
15
+
1
16
  // src/capabilities.ts
2
17
  function isSandboxPortSession(session) {
3
18
  const candidate = session;
@@ -14,146 +29,8 @@ import { mkdtemp, rm, writeFile } from "fs/promises";
14
29
  import os from "os";
15
30
  import path2 from "path";
16
31
 
17
- // src/docker-cli.ts
18
- import { spawn } from "child_process";
19
-
20
- // src/errors.ts
21
- var SandboxError = class extends Error {
22
- constructor(message, cause) {
23
- super(message);
24
- this.cause = cause;
25
- this.name = new.target.name;
26
- }
27
- cause;
28
- };
29
- var SandboxDockerUnavailableError = class extends SandboxError {
30
- };
31
- var SandboxDockerCommandError = class extends SandboxError {
32
- constructor(message, result) {
33
- super(message);
34
- this.result = result;
35
- }
36
- result;
37
- };
38
- var SandboxSessionDestroyedError = class extends SandboxError {
39
- };
40
- var SandboxPathError = class extends SandboxError {
41
- };
42
- var SandboxTimeoutError = class extends SandboxError {
43
- };
44
- var SandboxFileSizeError = class extends SandboxError {
45
- };
46
- var SandboxToolPolicyError = class extends SandboxError {
47
- };
48
- var SandboxPortError = class extends SandboxError {
49
- };
50
- var SandboxProcessError = class extends SandboxError {
51
- };
52
-
53
- // src/docker-cli.ts
54
- var defaultMaxOutputBytes = 1024 * 1024;
55
- async function runDockerCli(args, options) {
56
- const startedAt = Date.now();
57
- const maxOutputBytes = options.maxOutputBytes ?? defaultMaxOutputBytes;
58
- const stdout = createOutputCollector(maxOutputBytes, options.onStdout);
59
- const stderr = createOutputCollector(maxOutputBytes, options.onStderr);
60
- return new Promise((resolve, reject) => {
61
- const child = spawn(options.dockerPath, args, {
62
- stdio: ["pipe", "pipe", "pipe"]
63
- });
64
- let timedOut = false;
65
- let aborted = false;
66
- let settled = false;
67
- const timeout = options.timeoutMs === void 0 ? void 0 : setTimeout(() => {
68
- timedOut = true;
69
- child.kill("SIGKILL");
70
- }, options.timeoutMs);
71
- const abort = () => {
72
- aborted = true;
73
- child.kill("SIGKILL");
74
- };
75
- if (options.signal?.aborted === true) {
76
- abort();
77
- } else {
78
- options.signal?.addEventListener("abort", abort, { once: true });
79
- }
80
- child.stdout.on("data", (chunk) => stdout.accept(chunk));
81
- child.stderr.on("data", (chunk) => stderr.accept(chunk));
82
- child.on("error", (error) => {
83
- if (settled) {
84
- return;
85
- }
86
- settled = true;
87
- clearTimeout(timeout);
88
- options.signal?.removeEventListener("abort", abort);
89
- if (error.code === "ENOENT") {
90
- reject(new SandboxDockerUnavailableError("Docker CLI was not found.", error));
91
- return;
92
- }
93
- reject(error);
94
- });
95
- child.on("close", (code) => {
96
- if (settled) {
97
- return;
98
- }
99
- settled = true;
100
- clearTimeout(timeout);
101
- options.signal?.removeEventListener("abort", abort);
102
- resolve({
103
- stdout: stdout.text(),
104
- stderr: stderr.text(),
105
- exitCode: code ?? 1,
106
- durationMs: Date.now() - startedAt,
107
- timedOut,
108
- aborted,
109
- stdoutTruncated: stdout.truncated,
110
- stderrTruncated: stderr.truncated
111
- });
112
- });
113
- if (options.input !== void 0) {
114
- child.stdin.end(options.input);
115
- } else {
116
- child.stdin.end();
117
- }
118
- });
119
- }
120
- async function assertDockerCli(args, options) {
121
- const result = await runDockerCli(args, options);
122
- if (result.exitCode !== 0) {
123
- throw new SandboxDockerCommandError(`Docker command failed: docker ${args.join(" ")}`, result);
124
- }
125
- return result.stdout.trim();
126
- }
127
- function createOutputCollector(maxBytes, onChunk) {
128
- const chunks = [];
129
- let length = 0;
130
- let truncated = false;
131
- return {
132
- get truncated() {
133
- return truncated;
134
- },
135
- accept(chunk) {
136
- onChunk?.(chunk);
137
- if (length >= maxBytes) {
138
- truncated = true;
139
- return;
140
- }
141
- const remaining = maxBytes - length;
142
- const next = chunk.length > remaining ? chunk.subarray(0, remaining) : chunk;
143
- chunks.push(next);
144
- length += next.length;
145
- if (next.length < chunk.length) {
146
- truncated = true;
147
- }
148
- },
149
- text() {
150
- return Buffer.concat(chunks, length).toString("utf8");
151
- }
152
- };
153
- }
154
-
155
32
  // src/docker-process.ts
156
- import { spawn as spawn2 } from "child_process";
33
+ import { spawn } from "child_process";
157
34
  import { randomUUID } from "crypto";
158
35
 
159
36
  // src/path.ts
@@ -242,7 +119,7 @@ var DockerProcessManager = class {
242
119
  const id = randomUUID();
243
120
  const marker = `${processMarkerPrefix}:${id}`;
244
121
  const dockerArgs = this.createExecArgs(options, marker);
245
- const child = spawn2(this.options.dockerPath, dockerArgs, {
122
+ const child = spawn(this.options.dockerPath, dockerArgs, {
246
123
  stdio: ["pipe", "pipe", "pipe"]
247
124
  });
248
125
  child.stdin.end();
@@ -667,7 +544,7 @@ async function waitForDelay(timeoutMs) {
667
544
  var defaultImage = "node:22-bookworm";
668
545
  var defaultWorkdir = "/workspace";
669
546
  var defaultTimeoutMs = 3e4;
670
- var defaultMaxOutputBytes2 = 1024 * 1024;
547
+ var defaultMaxOutputBytes = 1024 * 1024;
671
548
  var defaultMaxProcesses = 4;
672
549
  var portProbeScript = [
673
550
  `port="$(printf '%04X' "$1")"`,
@@ -907,7 +784,7 @@ var DockerSandbox = class _DockerSandbox {
907
784
  cliOptions() {
908
785
  return {
909
786
  dockerPath: this.dockerPath,
910
- maxOutputBytes: this.limits.maxOutputBytes ?? defaultMaxOutputBytes2
787
+ maxOutputBytes: this.limits.maxOutputBytes ?? defaultMaxOutputBytes
911
788
  };
912
789
  }
913
790
  async cleanup(containerName, volumeName) {
@@ -954,7 +831,7 @@ var DockerSandboxSessionImpl = class {
954
831
  dockerPath: this.dockerPath,
955
832
  workdir: this.workdir,
956
833
  env: this.env,
957
- maxOutputBytes: this.limits.maxOutputBytes ?? defaultMaxOutputBytes2,
834
+ maxOutputBytes: this.limits.maxOutputBytes ?? defaultMaxOutputBytes,
958
835
  maxProcesses: this.limits.maxProcesses ?? defaultMaxProcesses,
959
836
  startupTimeoutMs: this.limits.timeoutMs ?? defaultTimeoutMs,
960
837
  onStart: async (process) => {
@@ -1218,7 +1095,7 @@ var DockerSandboxSessionImpl = class {
1218
1095
  cliOptions() {
1219
1096
  return {
1220
1097
  dockerPath: this.dockerPath,
1221
- maxOutputBytes: this.limits.maxOutputBytes ?? defaultMaxOutputBytes2
1098
+ maxOutputBytes: this.limits.maxOutputBytes ?? defaultMaxOutputBytes
1222
1099
  };
1223
1100
  }
1224
1101
  async isPortListening(containerPort, timeoutMs) {
@@ -1260,7 +1137,7 @@ var DockerSandboxSessionImpl = class {
1260
1137
  const cliOptions = {
1261
1138
  dockerPath: this.dockerPath,
1262
1139
  timeoutMs: options.timeoutMs ?? this.limits.timeoutMs ?? defaultTimeoutMs,
1263
- maxOutputBytes: this.limits.maxOutputBytes ?? defaultMaxOutputBytes2
1140
+ maxOutputBytes: this.limits.maxOutputBytes ?? defaultMaxOutputBytes
1264
1141
  };
1265
1142
  if (options.input !== void 0) cliOptions.input = options.input;
1266
1143
  if (options.signal !== void 0) cliOptions.signal = options.signal;