diff options
Diffstat (limited to 'js/scripting-lang/web/src/dev.js')
-rw-r--r-- | js/scripting-lang/web/src/dev.js | 268 |
1 files changed, 268 insertions, 0 deletions
diff --git a/js/scripting-lang/web/src/dev.js b/js/scripting-lang/web/src/dev.js new file mode 100644 index 0000000..8341d1c --- /dev/null +++ b/js/scripting-lang/web/src/dev.js @@ -0,0 +1,268 @@ +// devMode.js +// Enhanced dev mode with harness integration for unified debugging + +/** + * Initialize enhanced dev mode: exposes an API for stepping through state history + * with integration to Baba Yaga harness versioning capabilities. + * @param {object} opts + * @param {function} opts.getState - returns current app state + * @param {function} opts.setState - sets app state + * @param {function} opts.render - triggers app re-render + * @param {object} opts.harness - Baba Yaga FunctionalHarness instance (optional) + */ +export function initDevMode({ getState, setState, render, harness = null }) { + let history = []; + let pointer = -1; + let firstLoad = true; + let harnessCorrelation = []; // Track web state ↔ harness state correlation + + function pushState(state) { + if (pointer < history.length - 1) history = history.slice(0, pointer + 1); + history.push(clone(state)); + pointer = history.length - 1; + + // Track correlation with harness if available + if (harness) { + const harnessVersion = harness.currentVersion || 0; + harnessCorrelation.push({ + webVersion: pointer, + harnessVersion, + timestamp: Date.now() + }); + } + + logInstructions(); + } + + function goTo(idx) { + if (idx < 0 || idx >= history.length) return; + pointer = idx; + setState(clone(history[pointer])); + render(); + logInstructions(); + } + + function next() { + if (pointer < history.length - 1) goTo(pointer + 1); + } + + function prev() { + if (pointer > 0) goTo(pointer - 1); + } + + function get() { + return history[pointer]; + } + + function clone(obj) { + return JSON.parse(JSON.stringify(obj)); + } + + function table(obj) { + console.table(dev.history); + } + + // Harness integration functions + function getHarnessHistory() { + console.log('[DevMode] getHarnessHistory called, harness available:', !!harness); + if (!harness) { + console.warn('[DevMode] No harness available for versioning - run a Baba Yaga script first'); + return []; + } + const history = harness.getVersionHistory(); + console.log('[DevMode] Harness history:', history.length, 'versions'); + return history; + } + + function getHarnessDiff(from, to) { + if (!harness) { + console.warn('[DevMode] No harness available for diffing'); + return null; + } + return harness.getStateDiff(from, to); + } + + function getCorrelation() { + console.log('[DevMode] getCorrelation called, harness available:', !!harness); + if (!harness) { + console.warn('[DevMode] No harness available for correlation - run a Baba Yaga script first'); + return null; + } + + const webState = get(); + const harnessVersions = getHarnessHistory(); + const currentCorrelation = harnessCorrelation.find(c => c.webVersion === pointer); + + const result = { + webState, + webVersion: pointer, + harnessVersions, + currentCorrelation, + allCorrelations: harnessCorrelation + }; + + console.log('[DevMode] Correlation result:', { + webVersion: result.webVersion, + harnessVersions: result.harnessVersions.length, + correlations: result.allCorrelations.length + }); + + return result; + } + + function debugExecution(webVersion, harnessVersion) { + if (!harness) { + console.warn('[DevMode] No harness available for execution debugging'); + return null; + } + + const webState = history[webVersion]; + const harnessState = harness.stateHistory.getVersion(harnessVersion); + const diff = getHarnessDiff(harnessVersion - 1, harnessVersion); + + return { + webState, + harnessState, + scriptDiff: diff, + correlation: `Web v${webVersion} ↔ Harness v${harnessVersion}` + }; + } + + function stepCombined(direction) { + if (direction === 'next') { + next(); + // Could also step harness if correlated + const correlation = harnessCorrelation.find(c => c.webVersion === pointer); + if (correlation && harness) { + console.log(`[DevMode] Web v${pointer} correlates with Harness v${correlation.harnessVersion}`); + } + } else { + prev(); + } + } + + function logInstructions() { + if (firstLoad) { + console.log('[DevMode] Enhanced state history debugger with harness integration'); + console.log('Web App Debugging:'); + console.log('- dev.next() // step forward'); + console.log('- dev.prev() // step backward'); + console.log('- dev.goTo(n) // jump to state n (1-based)'); + console.log('- dev.get() // get current state'); + console.log('- dev.table() // display history as a table'); + console.log('- dev.history // array of all states'); + console.log('- dev.pointer // current pointer (0-based)'); + + if (harness) { + console.log('\nHarness Integration:'); + console.log('- dev.harnessHistory() // get harness version history'); + console.log('- dev.harnessDiff(from, to) // get state diff'); + console.log('- dev.correlation() // show web ↔ harness correlation'); + console.log('- dev.debugExecution(webVer, harnessVer) // debug specific execution'); + console.log('- dev.stepCombined(direction) // step both systems'); + } + + console.log('\nEnhanced Console API:'); + console.log('- debug.web // web app debugging'); + console.log('- debug.harness // harness debugging'); + console.log('- debug.combined // combined debugging'); + + firstLoad = false; + } + } + + // Function to update harness instance (called after script execution) + function updateHarness(newHarness) { + console.log('[DevMode] updateHarness called with:', !!newHarness); + harness = newHarness; + console.log('[DevMode] Harness instance updated for enhanced debugging'); + + // Re-expose the enhanced debug API with updated harness + window.debug = enhancedDebug; + } + + // Function to check current dev tools status + function getStatus() { + return { + devMode: true, + webStates: history.length, + currentPointer: pointer, + harnessAvailable: !!harness, + harnessVersions: harness ? harness.getVersionHistory().length : 0, + correlations: harnessCorrelation.length + }; + } + + // Enhanced console API + const enhancedDebug = { + // Web app debugging + web: { + next, + prev, + goTo, + get, + table, + get pointer() { return pointer; }, + get history() { return history.slice(); }, + }, + + // Harness debugging + harness: { + history: getHarnessHistory, + diff: getHarnessDiff, + correlation: getCorrelation, + debugExecution, + }, + + // Combined debugging + combined: { + correlation: getCorrelation, + step: stepCombined, + execution: debugExecution, + status: getStatus, + } + }; + + // Expose API globally for console use + window.dev = { + next, + prev, + goTo, + get, + table, + get pointer() { return pointer; }, + get history() { return history.slice(); }, + // Harness integration methods + harnessHistory: getHarnessHistory, + harnessDiff: getHarnessDiff, + correlation: getCorrelation, + debugExecution, + stepCombined, + updateHarness, + getStatus, + }; + + // Debug logging to verify function exposure + console.log('[DevMode] Dev API functions exposed:', { + updateHarness: typeof window.dev.updateHarness, + getStatus: typeof window.dev.getStatus, + harnessHistory: typeof window.dev.harnessHistory, + correlation: typeof window.dev.correlation + }); + + // Expose enhanced debug API + window.debug = enhancedDebug; + + // Debug logging to verify API exposure + console.log('[DevMode] Enhanced debug API exposed:', { + debugAvailable: typeof window.debug !== 'undefined', + webAvailable: typeof window.debug?.web !== 'undefined', + harnessAvailable: typeof window.debug?.harness !== 'undefined', + combinedAvailable: typeof window.debug?.combined !== 'undefined' + }); + + // Initial state + pushState(getState()); + + return { pushState }; +} \ No newline at end of file |