feat: embed deno runtime for extension bundling in compiled binaries#452
feat: embed deno runtime for extension bundling in compiled binaries#452
Conversation
Replace the Deno.bundle() API (unavailable in compiled binaries) with deno bundle CLI subprocess. Embed the deno binary inside the compiled swamp binary so extensions work without requiring users to install deno. - Add DenoVersion value object and DenoRuntime interface (domain port) - Add EmbeddedDenoRuntime that extracts embedded deno to ~/.swamp/deno/ in standalone mode, returns Deno.execPath() in dev mode - Rewrite bundleExtension() to use deno bundle subprocess - Add mtime-based bundle caching to .swamp/bundles/ in UserModelLoader - Add download_deno.ts script to fetch deno from GitHub releases - Update compile.ts to download + embed deno via --include resources/deno - Add bundles to SWAMP_SUBDIRS, update .gitignore and deno.json excludes Closes issue #443 and #442.
There was a problem hiding this comment.
Code Review: Embed Deno Runtime for Extension Bundling
This PR is well-designed and follows project guidelines. Approving with minor suggestions.
✅ Domain-Driven Design
The implementation correctly applies DDD patterns:
DenoVersion(src/domain/runtime/deno_version.ts:24) - Proper value object: immutable, equality by value, factory methodsDenoRuntime(src/domain/runtime/deno_runtime.ts:27) - Clean port interface in domain layerEmbeddedDenoRuntime(src/infrastructure/runtime/embedded_deno_runtime.ts:59) - Infrastructure adapter properly separated from domain- Dependency Injection -
UserModelLoaderacceptsDenoRuntimevia constructor, enabling testability
✅ Code Quality
- All new
.tsfiles include AGPLv3 headers - Named exports throughout (no default exports)
- TypeScript strict mode compliance
- The single
deno-lint-ignore no-explicit-anyatembedded_deno_runtime.ts:67is justified sinceDeno.build.standaloneisn't in Deno's type definitions
✅ Test Coverage
Unit tests provided for:
DenoVersion(deno_version_test.ts)bundleExtension(bundle_test.ts)EmbeddedDenoRuntime(embedded_deno_runtime_test.ts)UserModelLoaderupdates (27 existing tests updated + 1 new TypeScript-specific syntax test)
✅ Security
- Downloads from trusted source (GitHub releases) during compile only, not runtime
- No command injection vectors (subprocess args are hardcoded strings)
- Embedded binary verification via version marker
💡 Suggestions (non-blocking)
-
Bundle cache cleanup - Consider adding a way to clear
.swamp/bundles/when deno versions change, since bundles compiled with one deno version might not work with another. Not critical since the mtime check handles source changes. -
Error context in download_deno.ts - Line 855: When
unzipfails, the error message could include thestdoutfor additional context:throw new Error(`unzip failed: ${stderr}\nstdout: ${stdout}`);
-
Windows platform support - The
download_deno.tsusesunzipwhich may not be available on Windows. Consider documenting this or adding a fallback. This only affects cross-compilation scenarios.
Overall, excellent work! The architecture cleanly separates domain concerns from infrastructure, and the implementation is robust.
The extension model skill only mentioned importing zod, but the bundler (introduced in PR #452) resolves all Deno-compatible imports — npm:, jsr:, and https:// URLs. This was undocumented, so users (and Claude) had no guidance on using external packages in their models. Add a 'Using External Dependencies' section to the examples reference with: - A verified lodash-es example showing npm: imports in action - How bundling works (deno bundle, mtime cache, zod externalization) - Import rules table covering all supported specifiers Update SKILL.md Key Rules to mention external imports are supported, linking to the reference for details. Keeps SKILL.md lean per skill-creator guidelines.
The extension model skill only mentioned importing zod, but the bundler (introduced in PR #452) resolves all Deno-compatible imports — npm:, jsr:, and https:// URLs. This was undocumented, so users (and Claude) had no guidance on using external packages in their models. Add a 'Using External Dependencies' section to the examples reference with: - A verified lodash-es example showing npm: imports in action - How bundling works (deno bundle, mtime cache, zod externalization) - Import rules table covering all supported specifiers Update SKILL.md Key Rules to mention external imports are supported, linking to the reference for details. Keeps SKILL.md lean per skill-creator guidelines.
Replace the Deno.bundle() API (unavailable in compiled binaries) with deno bundle CLI subprocess. Embed the deno binary inside the compiled swamp binary so extensions work without requiring users to install deno.
Closes issue #443 and #442.