Skip to content

Commit fa088d3

Browse files
pepicrftclaude
andauthored
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

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

.gitignore

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,3 +64,9 @@ docs/.vitepress/dist/
6464
docs/.vitepress/cache/
6565
node_modules/
6666
package-lock.json
67+
68+
# Recipe test outputs
69+
generated/
70+
final/
71+
coverage/
72+
output/

0 commit comments

Comments
 (0)