Skip to content

feat: embed deno runtime for extension bundling in compiled binaries#452

Merged
stack72 merged 1 commit intomainfrom
bundle-extensions
Feb 24, 2026
Merged

feat: embed deno runtime for extension bundling in compiled binaries#452
stack72 merged 1 commit intomainfrom
bundle-extensions

Conversation

@adamhjk
Copy link
Copy Markdown
Contributor

@adamhjk adamhjk commented Feb 24, 2026

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.

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.
Copy link
Copy Markdown

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 methods
  • DenoRuntime (src/domain/runtime/deno_runtime.ts:27) - Clean port interface in domain layer
  • EmbeddedDenoRuntime (src/infrastructure/runtime/embedded_deno_runtime.ts:59) - Infrastructure adapter properly separated from domain
  • Dependency Injection - UserModelLoader accepts DenoRuntime via constructor, enabling testability

✅ Code Quality

  • All new .ts files include AGPLv3 headers
  • Named exports throughout (no default exports)
  • TypeScript strict mode compliance
  • The single deno-lint-ignore no-explicit-any at embedded_deno_runtime.ts:67 is justified since Deno.build.standalone isn'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)
  • UserModelLoader updates (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)

  1. 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.

  2. Error context in download_deno.ts - Line 855: When unzip fails, the error message could include the stdout for additional context:

    throw new Error(`unzip failed: ${stderr}\nstdout: ${stdout}`);
  3. Windows platform support - The download_deno.ts uses unzip which 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.

@stack72 stack72 merged commit 49ca5d2 into main Feb 24, 2026
4 checks passed
@stack72 stack72 deleted the bundle-extensions branch February 24, 2026 21:20
stack72 added a commit that referenced this pull request Feb 24, 2026
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.
stack72 added a commit that referenced this pull request Feb 24, 2026
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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants