Commit fa088d3
feat: Add portable recipes with QuickJS + LLRT integration (#49)
* feat: add portable recipes with QuickJS + LLRT integration
Adds cross-platform JavaScript automation support via embedded QuickJS
runtime with LLRT modules for Node.js compatibility.
**Features:**
- QuickJS runtime via rquickjs 0.10 (git)
- LLRT modules: console, buffer, fs, child_process, path
- Fabrik APIs: glob, exists, exec, hashFile, readFile, writeFile, cache
- Console output: console.log, console.error, console.warn
- Buffer API: Buffer.from(), base64 encoding, atob/btoa
- Full async/await support
**Architecture:**
- src/recipe/runtime.rs - QuickJS runtime with Fabrik APIs + LLRT modules
- src/recipe/executor.rs - Recipe execution (root-level & function-based)
- src/recipe/metadata.rs - Recipe metadata parsing (placeholder)
- src/recipe/mod.rs - Module exports
**Current Limitations:**
- ES module imports not yet working (import { ... } from 'fs')
- TextEncoder/TextDecoder not available (use Buffer instead)
- LLRT modules registered but need dynamic import support
**Documentation:**
- Updated CLAUDE.md with portable recipes section
- Added runtime architecture, API reference, examples
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* fix: resolve clippy warnings in recipe tests
- Remove unused PathBuf import
- Use struct initialization instead of field reassignment
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* chore: run cargo fmt
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* fix: update recipe tests to match QuickJS implementation
- Update Fabrik.exec() tests to expect number (exit code) instead of object
- Simplify file operation tests to avoid Buffer/TextEncoder issues
- Use Uint8Array-free approaches for better QuickJS compatibility
- Remove unused imports
All 65 tests now passing
* fix: escape Windows backslashes in JavaScript path strings
- Replace backslashes with double backslashes for Windows paths
- Fixes recipe tests on Windows platform
- Tests pass on macOS/Linux/Windows
* docs: simplify metadata module comment
* refactor: remove recipe metadata parsing functionality
- Remove RecipeMetadata struct and parsing logic
- Recipes are now pure JS files with business logic at root
- Simplifies recipe model - no metadata overhead
- All tests passing (61 tests)
* feat: add remote recipe parser with @ prefix syntax
- Parse @org/repo/path/script.js@ref format
- Support GitHub (default), GitLab, self-hosted Git servers
- XDG cache directory structure: ~/.cache/fabrik/recipes/
- Comprehensive test coverage (9 tests)
- Added dirs crate for XDG directory support
Examples:
@tuist/recipes/build.js → github.com/tuist/recipes
@gitlab.com/org/repo/script.js → gitlab.com/org/repo
@git.company.com/team/project/script.js@v1.0.0
* feat: implement Git repository fetching for remote recipes
- Add async fetch() method with shallow clone (--depth 1)
- XDG cache directory: ~/.cache/fabrik/recipes/{host}/{org}/{repo}/{ref}/
- Smart caching: skip fetch if already cached
- Comprehensive error handling and logging
- Verifies script exists after clone
Usage:
let recipe = RemoteRecipe::parse("@tuist/recipes/build.js@v1.0.0")?;
let script_path = recipe.fetch().await?;
// script_path: ~/.cache/fabrik/recipes/github.com/tuist/recipes/v1.0.0/build.js
* feat: add remote recipe execution support
- Added detection logic for @ prefix in fabrik run command
- Implemented run_remote_recipe function to handle remote recipes
- Remote recipes are fetched to XDG cache and executed with RecipeExecutor
- Added recipe module to main.rs to enable imports in commands
- Supports optional target function via script_args
Usage: fabrik run @tuist/recipes/build.js [-- target]
* test: add comprehensive remote recipe acceptance tests
- Added 5 integration tests for remote recipe functionality
- Tests cover parsing, cache directory structure, error handling
- Tests verify Git URL generation and nested paths
- All tests passing (5/5)
- Includes temporary Git repo setup for realistic testing
* docs: update recipe README with QuickJS/LLRT and remote execution
- Completely rewritten to reflect QuickJS runtime (not Deno)
- Added comprehensive remote recipe documentation
- Documented @ prefix syntax and Git repository fetching
- Added XDG cache directory structure examples
- Included API reference (Fabrik.exec, glob, exists)
- Added multiple recipe examples (simple, multi-target, remote)
- Comparison table between script and portable recipes
- Troubleshooting section for common issues
- Removed outdated Deno/metadata references
* docs: restructure recipes documentation and add remote recipes
- Renamed 'Scripts' section to 'Recipes' in sidebar
- Reorganized as hierarchical structure:
- Recipes (collapsed)
- Local (collapsed) - moved from scripts/
- Remote (collapsed) - new documentation
- Made all sections collapsed by default
- Moved existing script docs to cache/recipes/local/
- Created comprehensive remote recipes documentation:
- index.md - Introduction with QuickJS/LLRT explanation
- syntax.md - Complete @ prefix syntax reference
- examples.md - Real-world usage examples
- Added important admonition explaining embedded QuickJS runtime
- Removed outdated cross-references
* refactor: simplify recipes to root-level execution only
BREAKING CHANGE: Recipes no longer support exported functions with target
parameters. All recipes must be root-level scripts.
Changes:
- Simplified RecipeExecutor.execute() to remove target parameter
- Updated all tests to use root-level execution
- Removed target function support from run_remote_recipe
- Updated all documentation examples to be root-level scripts
- All recipe examples now work without -- target syntax
Migration guide:
- Before: fabrik run recipe.js -- build
- After: fabrik run recipe.js (entire script runs)
- Before: async function build() { ... }
- After: console.log("Building..."); await Fabrik.exec(...);
Recipes are now simpler and more straightforward - they execute from
top to bottom like regular scripts.
* docs: clarify Git as distribution mechanism and recipe isolation
Added important note explaining:
- Git repositories are purely a distribution mechanism
- Recipes are self-contained JavaScript files
- Recipes cannot depend on other recipes
- No external module imports allowed
- Each recipe runs independently with Fabrik APIs only
* docs: fix admonition title formatting
Changed from:
[!NOTE]
**Git as Distribution Mechanism**
To:
[!NOTE] Git as Distribution Mechanism
This uses the proper VitePress syntax for custom admonition titles.
* docs: convert 'Why Remote Recipes?' section to bullet list format
* docs: convert 'Cloning Behavior' section to bullet list format
* docs: remove Error Messages and Tips sections from syntax reference
* docs: expand CI reusable steps comparison in remote recipes
- Change section title from 'GitHub Actions' to 'CI Reusable Steps'
- Include GitHub Actions, GitLab CI Components, and Forgejo Actions
- Generalize platform-specific references to be provider-agnostic
- Make it clear that remote recipes work across all CI platforms
* docs: fix remote recipe examples to use correct module imports
- Replace Fabrik.exec() with spawn() from 'child_process' module
- Replace Fabrik.exists() with existsSync() from 'fs' module
- Replace Fabrik.glob() with glob() from 'fabrik:fs' module
- Add proper import statements to all examples
- Ensure consistency with actual API implementation
* docs: add JavaScript API reference for Fabrik recipe modules
- Create comprehensive API documentation for fabrik:* modules
- Document fabrik:cache (runCached, needsRun)
- Document fabrik:fs (glob, hashFile)
- Document fabrik:kv (get, set, has)
- Include standard LLRT modules (fs, child_process, path, buffer)
- Add configuration discovery explanation
- Add complete usage examples
- Cross-reference from remote recipe docs
* docs: add JavaScript API reference to sidebar navigation
- Add 'JavaScript API Reference' link at top of Recipes section
- Makes the API documentation discoverable in the sidebar
* docs: move JavaScript API reference into Remote recipes section
- Move API reference from top-level Recipes to inside Remote section
- Better organization since remote recipes use JavaScript APIs
- Now appears: Recipes > Remote > JavaScript API Reference
* refactor: rename to standard and portable recipes
- Rename modules: recipe_local → recipe, recipe_remote → recipe_portable
- Reorganize fixtures: flatten structure, rename remote → portable
- Update documentation: local → standard, remote → portable
- Add 9 portable recipe examples for acceptance testing
- Clarify conceptual model: portability (embedded runtime) vs standard (system runtimes)
- Update examples documentation to focus on caching use cases
* docs: update navigation to use standard/portable naming
* docs: add hyperlinks to portable recipes from standard recipes page
* docs: simplify standard vs portable comparison table
* docs: remove output examples from standard recipes page
* docs: rename reference to annotations and add hyperlinks
* docs: explain that annotations use language-specific comment symbols
* fix: resolve module naming after rebase
- Rename mod script to mod recipe_portable in main.rs
- Update imports in commands/run.rs to use correct module paths
- Fix references from crate::script to crate::recipe
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* docs: fix portable recipe API description
Update the description to accurately list Fabrik cache APIs
(fabrik:cache, fabrik:kv, fabrik:fs) instead of generic modules.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* feat: add support for local portable recipes
- Detect .js files and route them to QuickJS runtime
- Add run_local_portable_recipe function
- Update syntax.md to document both local and remote recipes
Local portable recipes can now be run with:
fabrik run build.js
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* feat: add comprehensive comment style support for script annotations
- Add support for comment styles of 70+ scripting languages/runtimes:
- Hash (#): bash, python, ruby, perl, R, PowerShell, etc.
- Double-slash (//): node, deno, swift, kotlin, go, etc.
- Semicolon (;): lisp, clojure, scheme, racket, elisp, etc.
- Double-dash (--): lua, SQL, haskell, ada, vhdl
- Percent (%): erlang
- REM: Windows batch/cmd
- Single-quote ('): VBScript
- Fix module import paths after rebase (script -> recipe)
- Add comprehensive unit tests for all comment prefix styles
- Add integration tests parsing full scripts for multiple languages
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* fix: correct fixture path and .js file routing in acceptance tests
- Update acceptance tests to use correct fixtures path (recipes/ not scripts/)
- Add shebang detection to distinguish standard recipes from portable recipes
- .js files with `fabrik run <runtime>` shebang use external runtime (standard recipe)
- .js files without fabrik shebang use QuickJS runtime (portable recipe)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* fix: use cross-platform path assertions in test_cache_dir_structure
The test was using forward slashes in the expected path which fails
on Windows where backslashes are used. Changed to individual component
checks to be cross-platform.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* docs: update api-reference.md to reflect actual implementation
- Add Fabrik Global Object section documenting all global APIs
- Document Fabrik.readFile, writeFile, exists, glob, exec, hashFile
- Document Fabrik.cache low-level operations
- Update examples to use Fabrik.exec() instead of spawn
- Add note about LLRT child_process differences
- Update complete example at bottom of file
* Restructure fixtures directory layout
- Move fixtures/cache/build-systems to fixtures/build-systems
- Move fixtures/cache/recipes to fixtures/recipes
- Reorganize recipes: standard/ for bash/node scripts, portable/ for QuickJS recipes
- Consolidate duplicate turborepo fixtures
- Remove examples/ directory (moved to fixtures/recipes/portable)
- Fix portable recipe fixtures to use correct Fabrik APIs (Fabrik.exec instead of spawn)
- Update all test file paths to match new structure
- Add cache-api-demo.js demonstrating all available Fabrik global APIs
- Remove build artifacts from fixtures (node_modules, .gradle, etc.)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Make Fabrik.writeFile accept strings like Node.js
- Update Fabrik.writeFile to accept String instead of Vec<u8>
- Fix all portable recipe fixtures to use the available Fabrik APIs
- Remove usage of unavailable LLRT fs module imports
- All fixtures now work correctly with the QuickJS runtime
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* fix: Resolve paths relative to recipe directory
- Update Fabrik APIs (readFile, writeFile, exists, glob, exec, hashFile)
to resolve paths relative to the recipe directory instead of the current
working directory
- writeFile now automatically creates parent directories
- exec now runs commands in the recipe directory
- Remove unnecessary mkdir -p calls from fixtures
- Add recipe test output directories to .gitignore
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Co-authored-by: Claude <noreply@anthropic.com>1 parent ad2467c commit fa088d3
File tree
106 files changed
+5782
-482
lines changed- docs
- .vitepress
- cache/recipes
- portable
- standard
- fixtures
- build-systems
- bazel
- simple
- swift
- gradle/app
- app
- src/main/kotlin/com/example
- gradle/wrapper
- metro/simple
- src
- nx
- apps/demo
- src
- tipi/simple
- .tipi
- turborepo
- packages/app
- xcode/ios-app
- Fabrik.xcodeproj
- project.xcworkspace
- Fabrik
- Assets.xcassets
- AccentColor.colorset
- AppIcon.appiconset
- cache
- build-systems/turborepo
- packages/app
- scripts/bash
- recipes
- portable
- standard
- bash
- node
- turborepo/packages/app
- src
- commands
- recipe_portable
- recipe
- script
- tests
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
106 files changed
+5782
-482
lines changed| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
64 | 64 | | |
65 | 65 | | |
66 | 66 | | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
0 commit comments