diff options
Diffstat (limited to 'js/scripting-lang/web/README.md')
-rw-r--r-- | js/scripting-lang/web/README.md | 447 |
1 files changed, 447 insertions, 0 deletions
diff --git a/js/scripting-lang/web/README.md b/js/scripting-lang/web/README.md new file mode 100644 index 0000000..5c7b1ac --- /dev/null +++ b/js/scripting-lang/web/README.md @@ -0,0 +1,447 @@ +# Baba Yaga's PokeDex + +This application demonstrates how to integrate baba yaga into an interactive web application, and how to use it to perform data transformation and manipulation. + +## Architecture + +### Core TEA Components +- **state.js**: App state definition and helpers +- **update.js**: Pure update function (handles actions/messages) +- **view.js**: Pure view functions (renders HTML as string) +- **app.js**: Entrypoint, main loop, event delegation + +### Baba Yaga Integration +- **api.js**: API fetch logic + Baba Yaga harness integration +- **scripting-harness/**: Baba Yaga FunctionalHarness (which itself includes TEA-inspired state management) +- **lang.js**: Baba Yaga language runtime (imported from parent directory) + +### Data Flow +``` +┌──────────────┐ ┌──────────────┐ ┌──────────────┐ +│ User Input │ ──> │ TEA Actions │ ──> │ API Calls │ +└──────────────┘ └──────────────┘ └──────────────┘ + │ +┌──────────────┐ ┌──────────────┐ ┌─────▼──────┐ +│ UI Update │ <── │ Results │ <── │ Baba Yaga │ +└──────────────┘ └──────────────┘ │ Harness │ + └────────────┘ +``` + +## Pattern + +### TEA Architecture +- **State**: Single immutable state object +- **Update**: Pure function `(state, action) => newState` +- **View**: Pure function `(state) => html` +- **Entrypoint**: Handles events, dispatches actions, triggers re-render + +### Baba Yaga Harness Integration +- **Script Processing**: Pure function `(state) => { model, commands, version }` +- **Command Handling**: Side effects processed by harness adapters +- **State Management**: Automatic versioning and history tracking +- **Error Recovery**: Built-in error handling and recovery mechanisms + +## How to Extend and Use This Template + +### Key Files to Extend +- **src/state.js**: Define the app's state shape and any helper functions for cloning or initializing state. +- **src/update.js**: Add new action/message types and update logic. This is where you handle all state transitions. +- **src/view.js**: Build your UI as a pure function of state. Add new components or views here. +- **src/api.js**: Add or replace API calls as needed for your app's data fetching. **Also contains Baba Yaga integration logic.** +- **src/app.js**: Wire up events, use the generalized `render` function, and add any app-specific logic (e.g., focus management, custom event handling). + +### Using the Generalized `render` Function +The `render` function in `app.js` is designed to be reusable for any app. It takes a config object: + +```js +render({ + root, // DOM element to render into + state, // Current app state + view, // View function: (state) => html + events: [ // Array of event bindings + { selector, event, handler }, + // ... + ], + postRender // Optional: function({ root, state }) for custom logic (e.g., focus) +}); +``` + +## Baba Yaga Language Integration + +### Key Integration Points + +#### **api.js - Baba Yaga Harness Integration** +The `api.js` file contains the core integration logic using the FunctionalHarness: + +```js +// Import the FunctionalHarness +import { FunctionalHarness } from '../../scripting-harness/core/harness.js'; + +// Execute Baba Yaga scripts with the harness +async function executeBabaYagaScript(script, evolutionData) { + // Create harness with the script + const harness = new FunctionalHarness(script, { + logStateChanges: false, + logCommands: false, + debug: false + }); + + // Initialize the harness before use + await harness.initialize(); + + // Process the evolution data through the harness + const result = await harness.update(evolutionData); + + // Extract emitted values from commands + const emittedValues = result.commands + .filter(cmd => cmd.type === 'emit') + .map(cmd => cmd.value); + + return { + result: result.model, + emitted: emittedValues, + evolutionData + }; +} +``` + +#### **State Management for Scripts** +The application state includes Baba Yaga-specific fields: + +```js +// In state.js +{ + babaYagaScript: '', // User's script input + scriptOutput: null, // Script execution results + scriptError: null, // Script execution errors + evolutionChain: null, // Data for ..listen operations +} +``` + +The FunctionalHarness provides additional state management features: +- **Versioning**: Automatic state versioning with history +- **Command Processing**: Structured handling of `..emit` operations +- **Error Recovery**: Built-in error handling and recovery mechanisms +- **State Diffing**: Ability to compare state versions + +#### **UI Components** +The view layer includes dedicated components for script editing and execution: + +- **Script Editor**: Textarea for writing Baba Yaga scripts +- **Example Scripts**: Dropdown with pre-built transformation examples +- **Execution Results**: Display of `..emit` output and final results +- **Error Handling**: Clear error messages for script syntax issues + +### Baba Yaga Script Examples + +The application includes several example scripts demonstrating data transformation using the harness pattern: + +```plaintext +/* Basic Evolution Stages */ +state : ..listen; +/* Extract the evolution chain for easier access */ +chain : state.evolutionChain.chain; +getSpeciesName : stage -> stage.species.name; +evolutionStages : map @getSpeciesName chain.evolves_to; +..emit evolutionStages; + +/* Evolution Methods */ +state : ..listen; +/* Extract the evolution chain for easier access */ +chain : state.evolutionChain.chain; +getEvolutionInfo : evo -> { + species: evo.species.name, + method: evo.evolution_details[0].trigger.name, + level: evo.evolution_details[0].min_level +}; +evolutionMethods : map @getEvolutionInfo chain.evolves_to; +..emit evolutionMethods; + +/* Filter by Evolution Method */ +state : ..listen; +/* Extract the evolution chain for easier access */ +chain : state.evolutionChain.chain; +isLevelUp : evo -> + when evo.evolution_details[0].trigger.name is + "level-up" then true + _ then false; +levelEvolutions : filter @isLevelUp chain.evolves_to; +getSpeciesName : evo -> evo.species.name; +levelEvolutionNames : map @getSpeciesName levelEvolutions; +..emit levelEvolutionNames; +``` + +### State Usage Pattern + +The scripts demonstrate a pattern for working with complex state: + +1. **Capture State**: `state : ..listen;` - Gets the full state object +2. **Extract Substructures**: `chain : state.evolutionChain.chain;` - Extract nested data for easier access +3. **Process Data**: Use the extracted substructures in transformations +4. **Emit Results**: `..emit result;` - Send processed data back + +This pattern helps to avoid deeply nested property access and makes scripts easier to understand. + +### Integration Pattern + +1. **Data Loading**: Fetch external data (Pokémon evolution chains) +2. **Harness Creation**: Create FunctionalHarness instance with Baba Yaga script +3. **Harness Initialization**: Call `await harness.initialize()` (required step) +4. **State Processing**: Use `harness.update()` to execute script with data +5. **Command Extraction**: Extract `..emit` values from `result.commands` +6. **Result Display**: Display transformed results and emitted data +7. **Error Handling**: Leverage harness's built-in error handling and recovery + +This pattern provides a robust, TEA-inspired architecture for embedding Baba Yaga scripts in web applications with proper state management, versioning, and error handling. + +### Key Harness Features Used + +- **State Versioning**: Automatic version tracking with `result.version` +- **Command Processing**: Structured handling of `..emit` operations +- **Error Classification**: Built-in error categorization and recovery +- **Timeout Protection**: Automatic timeout handling for long-running scripts +- **State History**: Access to previous state versions and diffs + +## Versioning Integration Plan + +This application has two separate versioning systems that can be integrated for enhanced debugging and development capabilities: + +### Current Versioning Systems + +#### **Web App Versioning (dev.js)** +- **Purpose**: UI state history for debugging user interactions +- **Features**: + - Step through UI state changes (`dev.next()`, `dev.prev()`) + - Jump to specific states (`dev.goTo(n)`) + - Display history as table (`dev.table()`) + - Console-based debugging interface +- **Scope**: Application state (Pokémon data, script input, UI state) + +#### **Harness Versioning (FunctionalHarness)** +- **Purpose**: Script execution state history for debugging transformations +- **Features**: + - Automatic version tracking for each script execution + - State diffing between versions (`getStateDiff()`) + - Branch creation from specific versions (`createBranch()`) + - Error recovery and rollback capabilities + - Command history tracking +- **Scope**: Script execution state and transformations + +### Integration Opportunities + +#### **1. Unified Versioning Dashboard** +```javascript +// Enhanced dev mode with harness integration +const enhancedDev = { + // Web app versioning + next: () => dev.next(), + prev: () => dev.prev(), + + // Harness versioning + harnessHistory: () => harness.getVersionHistory(), + harnessDiff: (from, to) => harness.getStateDiff(from, to), + + // Combined debugging + scriptExecution: (version) => { + const webState = dev.get(); + const harnessState = harness.stateHistory.getVersion(version); + return { webState, harnessState, diff: harness.getStateDiff(version - 1, version) }; + } +}; +``` + +#### **2. Cross-System State Correlation** +- **Web State → Harness State**: Map UI actions to script execution versions +- **Harness State → Web State**: Track how script results affect UI state +- **Bidirectional Debugging**: Step through both systems simultaneously + +#### **3. Enhanced Debugging Workflow** +```javascript +// Example integration workflow +const debugWorkflow = { + // 1. User performs action (web state changes) + onUserAction: (action) => { + dev.pushState(newState); + console.log(`[Debug] Web state version: ${dev.pointer}`); + }, + + // 2. Script executes (harness state changes) + onScriptExecution: (script, data) => { + const result = await harness.update(data); + console.log(`[Debug] Harness version: ${result.version}`); + console.log(`[Debug] Commands: ${result.commands.length}`); + }, + + // 3. Combined debugging + debugExecution: (webVersion, harnessVersion) => { + const webState = dev.history[webVersion]; + const harnessState = harness.stateHistory.getVersion(harnessVersion); + const diff = harness.getStateDiff(harnessVersion - 1, harnessVersion); + + return { + webState, + harnessState, + scriptDiff: diff, + correlation: `Web v${webVersion} ↔ Harness v${harnessVersion}` + }; + } +}; +``` + +#### **4. Development Tools Enhancement** +```javascript +// Enhanced console API +window.debug = { + // Web app debugging + web: dev, + + // Harness debugging + harness: { + history: () => harness.getVersionHistory(), + diff: (from, to) => harness.getStateDiff(from, to), + branch: (from, name) => harness.createBranch(from, name), + rollback: (version) => harness.rollbackToVersion(version) + }, + + // Combined debugging + combined: { + // Show correlation between web and harness states + correlation: () => { + const webState = dev.get(); + const harnessVersions = harness.getVersionHistory(); + return { webState, harnessVersions }; + }, + + // Step through both systems + step: (direction) => { + if (direction === 'next') { + dev.next(); + // Could also step harness if correlated + } else { + dev.prev(); + } + } + } +}; +``` + +### Implementation Roadmap + +#### **Phase 1: Basic Integration** +- [ ] Extend `dev.js` to expose harness versioning methods +- [ ] Add correlation tracking between web and harness states +- [ ] Create unified console API for both systems + +#### **Phase 2: Enhanced Debugging** +- [ ] Implement bidirectional state stepping +- [ ] Add visual diff display for script transformations +- [ ] Create timeline view showing web ↔ harness correlations + +#### **Phase 3: Advanced Features** +- [ ] Branch management UI for script experimentation +- [ ] State replay capabilities for debugging +- [ ] Performance profiling for script executions + +### Benefits of Integration + +- **Comprehensive Debugging**: Debug both UI interactions and script transformations +- **State Correlation**: Understand how user actions trigger script changes +- **Enhanced Development**: Rich debugging tools for complex data transformations +- **Performance Insights**: Track script execution performance over time +- **Error Recovery**: Leverage harness error recovery in web app context + +## Enhanced Dev Tools Usage + +### Getting Started + +1. **Enable Dev Mode**: Add `?dev=1` to the application URL + ``` + http://localhost:8000/web/?dev=1 + ``` + +2. **Open Console**: Press F12 and navigate to the Console tab + +3. **Test Integration**: Run the automated test suite + ```javascript + testDevTools() + ``` + +### Console API Reference + +#### **Web App Debugging** (`debug.web.*`) +```javascript +// Navigate web state history +debug.web.next() // Step forward +debug.web.prev() // Step backward +debug.web.goTo(n) // Jump to state n +debug.web.get() // Get current state +debug.web.table() // Display as table +debug.web.history // All states array +debug.web.pointer // Current position +``` + +#### **Harness Debugging** (`debug.harness.*`) +```javascript +// Harness versioning and state management +debug.harness.history() // Get version history +debug.harness.diff(from, to) // Compare versions +debug.harness.correlation() // Show correlations +debug.harness.debugExecution(webVer, harnessVer) // Debug execution +``` + +#### **Combined Debugging** (`debug.combined.*`) +```javascript +// Unified debugging operations +debug.combined.correlation() // Current correlation +debug.combined.step('next') // Step both systems +debug.combined.execution(webVer, harnessVer) // Debug execution +``` + +### Example Debugging Session + +```javascript +// 1. Explore web state history +debug.web.table() + +// 2. Check harness versions (after running a script) +debug.harness.history() + +// 3. View correlation between systems +debug.combined.correlation() + +// 4. Compare script execution states +debug.harness.diff(1, 2) + +// 5. Debug specific execution +debug.combined.execution(3, 1) + +// 6. Step through both systems +debug.combined.step('next') +``` + +### Demo Files + +- **`dev-demo.html`**: Comprehensive demo and documentation +- **`test-dev-tools.js`**: Automated test suite for integration verification + +### Troubleshooting + +- **Dev mode not available**: Ensure `?dev=1` is in the URL +- **Harness not available**: Run a Baba Yaga script first to create harness instance +- **Console errors**: Check browser console for detailed error messages + +--- + +Inspired by the [Elm Architecture](https://guide.elm-lang.org/architecture/), but using only browser APIs and ES modules. + +--- + +## MIT License + +Copyright 2025 eli_oat + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file |