-
Notifications
You must be signed in to change notification settings - Fork 36
TUI love #872
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
TUI love #872
Conversation
WalkthroughAdds a React-based terminal UI (Ink) for envio, new TUI modules/types/bindings, updates ReScript build configs and package manifests, removes the stateUpdatedHook from GlobalStateManager, and refactors Index.res to use a direct getState callback for driving the TUI. Changes
Sequence Diagram(s)sequenceDiagram
participant Index as Index.res
participant GSM as GlobalStateManager
participant TUI as Tui.App (React)
participant Hook as useEffect (poll)
Index->>GSM: create gsManager(globalState, ~onError)
Index->>TUI: Tui.start(~getState)
activate TUI
TUI->>Hook: start polling (every 500ms)
loop poll
Hook->>TUI: trigger re-render
TUI->>Index: getState()
Index->>GSM: read current state
GSM-->>Index: return GlobalState
Index-->>TUI: return chains array
TUI->>TUI: derive TuiData.progress per chain
TUI->>TUI: render ChainLine/TotalEventsProcessed/UI
end
deactivate TUI
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes
Possibly related PRs
Suggested reviewers
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 inconclusive)
✅ Passed checks (2 passed)
✨ Finishing touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 4
🧹 Nitpick comments (1)
codegenerator/cli/npm/envio/src/tui/Tui.res (1)
261-266: Consider whether the returnedrerenderfunction is needed.The
startfunction returns a rerender callback, but inIndex.res(line 225), it's captured as_rerender(unused). If this is intentional for future use, consider adding a comment. Otherwise, simplify to returnunit.
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (2)
codegenerator/cli/npm/envio/pnpm-lock.yamlis excluded by!**/pnpm-lock.yamlscenarios/test_codegen/pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (7)
codegenerator/cli/npm/envio/src/GlobalStateManager.rescodegenerator/cli/npm/envio/src/GlobalStateManager.resicodegenerator/cli/npm/envio/src/tui/Tui.rescodegenerator/cli/npm/envio/src/tui/bindings/Ink.rescodegenerator/cli/npm/envio/src/tui/components/SyncETA.rescodegenerator/cli/npm/envio/src/tui/components/TuiData.rescodegenerator/cli/templates/static/codegen/src/Index.res
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{res,resi}
📄 CodeRabbit inference engine (.cursor/rules/rescript.mdc)
**/*.{res,resi}: Always use ReScript 11 documentation
Never suggest ReasonML syntax
Never use[| item |]to create an array. Use[ item ]instead
Must always use=for setting value to a field. Use:=only for ref values created usingreffunction
Use records when working with structured data, and objects to conveniently pass payload data between functions
Never use %raw to access object fields if you know the type
Files:
codegenerator/cli/npm/envio/src/GlobalStateManager.rescodegenerator/cli/npm/envio/src/GlobalStateManager.resicodegenerator/cli/npm/envio/src/tui/components/SyncETA.rescodegenerator/cli/npm/envio/src/tui/components/TuiData.rescodegenerator/cli/npm/envio/src/tui/bindings/Ink.rescodegenerator/cli/npm/envio/src/tui/Tui.rescodegenerator/cli/templates/static/codegen/src/Index.res
codegenerator/cli/templates/static/**/*.res
📄 CodeRabbit inference engine (.cursor/rules/navigation.mdc)
Static ReScript files must be placed in
codegenerator/cli/templates/static/
Files:
codegenerator/cli/templates/static/codegen/src/Index.res
🧠 Learnings (9)
📚 Learning: 2025-12-04T12:13:23.246Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/subgraph-migration.mdc:0-0
Timestamp: 2025-12-04T12:13:23.246Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/{src/handlers,src/**}/*.ts : ALL external calls (RPC calls, API calls, blockchain state fetching) MUST use the Effect API with `context.effect()` to enable preload optimization and parallelization. Create Effect API functions in `src/effects/` folder for better organization
Applied to files:
codegenerator/cli/templates/static/codegen/src/Index.res
📚 Learning: 2025-12-04T12:12:49.547Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/hyperindex.mdc:0-0
Timestamp: 2025-12-04T12:12:49.547Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/*.{ts,js} : Import and use the Effect API (`S`, `createEffect`) from 'envio' package for external calls in HyperIndex handlers
Applied to files:
codegenerator/cli/templates/static/codegen/src/Index.res
📚 Learning: 2025-12-04T12:13:23.246Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/subgraph-migration.mdc:0-0
Timestamp: 2025-12-04T12:13:23.246Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/*.ts : For Step 6 - Final Migration Verification: Go through each handler and helper function systematically, comparing the logic line-by-line to the original subgraph implementation. Iterate multiple times until logic is completely correct, as first pass often misses subtle differences
Applied to files:
codegenerator/cli/templates/static/codegen/src/Index.res
📚 Learning: 2025-12-04T12:12:49.547Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/hyperindex.mdc:0-0
Timestamp: 2025-12-04T12:12:49.547Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/*.{ts,js} : In Envio HyperIndex, use `entity_id` fields (e.g., `token_id: string`) instead of direct object references for entity relationships
Applied to files:
codegenerator/cli/templates/static/codegen/src/Index.res
📚 Learning: 2025-12-04T12:13:23.246Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/subgraph-migration.mdc:0-0
Timestamp: 2025-12-04T12:13:23.246Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/src/utils/**/*.ts : When implementing helper functions with no entity or handler dependencies, implement the COMPLETE business logic from the original subgraph immediately, not just placeholder TODO comments
Applied to files:
codegenerator/cli/templates/static/codegen/src/Index.res
📚 Learning: 2025-12-04T12:13:23.246Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/subgraph-migration.mdc:0-0
Timestamp: 2025-12-04T12:13:23.246Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/src/**/*.ts : For Step 3 - Refactor file structure to mirror the original subgraph EXACTLY using the same filenames, create separate handler files by contract (e.g., contract1.ts, contract2.ts) instead of a single EventHandlers.ts file, and move handlers from EventHandlers.ts to contract-specific files
Applied to files:
codegenerator/cli/templates/static/codegen/src/Index.res
📚 Learning: 2025-12-04T12:13:23.246Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/subgraph-migration.mdc:0-0
Timestamp: 2025-12-04T12:13:23.246Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/src/effects/**/*.ts : When making external RPC calls, use viem with createPublicClient and batching for efficiency. Define Effect functions with proper schemas using the S module from 'envio': S.object(), S.string, S.number, etc.
Applied to files:
codegenerator/cli/templates/static/codegen/src/Index.res
📚 Learning: 2025-12-04T12:12:49.547Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/hyperindex.mdc:0-0
Timestamp: 2025-12-04T12:12:49.547Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/*.{ts,js} : When updating existing entities in HyperIndex handlers, always use the spread operator for immutability since returned objects are read-only
Applied to files:
codegenerator/cli/templates/static/codegen/src/Index.res
📚 Learning: 2025-12-04T12:13:23.246Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/subgraph-migration.mdc:0-0
Timestamp: 2025-12-04T12:13:23.246Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/EventHandlers.ts : For Step 1 - Clear all boilerplate code from EventHandlers.ts and replace with empty handlers containing TODO comments referencing the original subgraph implementation
Applied to files:
codegenerator/cli/templates/static/codegen/src/Index.res
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: build_and_test
🔇 Additional comments (17)
codegenerator/cli/npm/envio/src/tui/bindings/Ink.res (2)
219-234: LGTM! Well-implemented custom hook.The
useStdoutColumnshook correctly subscribes to stdout resize events, updates state accordingly, and properly cleans up the event listener. The external bindings forgetColumns,on, andofffollow the correct ReScript patterns.
373-376: LGTM! Clean table component binding.The
Tablemodule binding is straightforward and follows the established patterns in this file. The type signatures forheadandrowsare appropriate for tabular data.codegenerator/cli/npm/envio/src/GlobalStateManager.resi (1)
3-3: LGTM!The simplified
makesignature removingstateUpdatedHookis a clean API improvement. The new TUI polling mechanism viagetStateis a more straightforward approach than hook-based notifications.codegenerator/cli/npm/envio/src/tui/components/TuiData.res (1)
1-12: LGTM!The type definitions are well-structured. The record spread syntax for
syncedextendingsyncingis clean ReScript 11 usage. The external bindings for number formatting are correctly defined.Also applies to: 20-46
codegenerator/cli/npm/envio/src/tui/components/SyncETA.res (5)
4-11: LGTM!The type signature update to
array<TuiData.chain>and the reduction logic are correct.
13-26: LGTM!The remaining blocks calculation correctly handles the
endBlockoption and allprogressvariants.
28-56: LGTM!Type signature updates to
array<TuiData.chain>are consistent. The timestamp and block processing calculations handle all progress variants correctly.
58-95: LGTM!The
useShouldDisplayEtahook correctly tracks whether enough batches have been fetched to display a meaningful ETA. The effect returnsNoneappropriately as no cleanup is needed.
97-193: LGTM!The ETA calculation logic is sound, and the component structure cleanly separates the syncing, synced, and calculating states. The interval-based timer with cleanup is properly implemented.
codegenerator/cli/npm/envio/src/tui/Tui.res (4)
22-83: LGTM!The ChainLine rendering logic handles both the loading state and full progress display well. The adaptive layout based on
fitsSameLineis a nice touch for terminal width considerations.
98-115: LGTM!The 500ms polling interval is reasonable for TUI updates. The cleanup function properly clears the interval. The
getStatedependency is stable since it's passed from the parent.
117-197: LGTM!The chain data transformation logic is comprehensive. The handling of edge cases (e.g., no events in block range resulting in
firstEventBlockNumber = None) is well documented in the comment at lines 131-134.
211-258: LGTM!The render tree is well-structured with appropriate components for header, chain lines, totals, sync status, and configuration display.
codegenerator/cli/npm/envio/src/GlobalStateManager.res (2)
14-25: LGTM!The simplified record type and
makefunction are cleaner. RemovingstateUpdatedHookin favor of the polling-based TUI approach is a reasonable simplification.
27-65: LGTM!The dispatch logic remains unchanged and continues to handle state updates, task scheduling, and error handling correctly.
codegenerator/cli/templates/static/codegen/src/Index.res (2)
165-196: LGTM!The chain data construction is cleaner, computing values directly from
cfobjects. The logic correctly handles:
latestFetchedBlockNumberwith a floor of 0knownHeightbased on whether endblock has been processedlatestProcessedBlockreturningNonewhen-1
223-228: LGTM!The initialization flow is clean. The
GlobalStateManager.makecall withoutstateUpdatedHookaligns with the new TUI polling approach. ThegetStatecallback correctly provides access to the manager's state.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (1)
codegenerator/cli/npm/envio/src/tui/Tui.res (1)
219-236: Using array index as React key.Using
i->Int.toStringas the key works if the chain list order is stable and chains aren't dynamically added/removed during rendering. If chain ordering can change, consider using a stable identifier likechainData.chainIdinstead.🔎 Proposed change
{chains - ->Array.mapWithIndex((i, chainData) => { + ->Array.map(chainData => { <ChainLine - key={i->Int.toString} + key={chainData.chainId} chainId={chainData.chainId}
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
sync.gifis excluded by!**/*.gif
📒 Files selected for processing (1)
codegenerator/cli/npm/envio/src/tui/Tui.res
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{res,resi}
📄 CodeRabbit inference engine (.cursor/rules/rescript.mdc)
**/*.{res,resi}: Always use ReScript 11 documentation
Never suggest ReasonML syntax
Never use[| item |]to create an array. Use[ item ]instead
Must always use=for setting value to a field. Use:=only for ref values created usingreffunction
Use records when working with structured data, and objects to conveniently pass payload data between functions
Never use %raw to access object fields if you know the type
Files:
codegenerator/cli/npm/envio/src/tui/Tui.res
🧠 Learnings (1)
📚 Learning: 2025-12-04T12:13:23.246Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/subgraph-migration.mdc:0-0
Timestamp: 2025-12-04T12:13:23.246Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/*.ts : Always verify entity type field names match exactly with the generated entity types. For example, use `token0_id` not `token0`, and `transaction_id` not `transaction`. Run `pnpm tsc --noEmit` to catch type mismatches
Applied to files:
codegenerator/cli/npm/envio/src/tui/Tui.res
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: build_and_test
🔇 Additional comments (5)
codegenerator/cli/npm/envio/src/tui/Tui.res (5)
49-55: Consider edge case wheretoBlock - firstEventBlockis zero or negative.If
firstEventBlockdefaults tostartBlock(line 28) andtoBlockequalsstartBlock, thenoutOfbecomes 0. Similarly,loadedorbufferedcould be negative if block ordering is unexpected. Verify thatBufferedProgressBarhandles these edge cases gracefully, or add guards here.
85-96: LGTM!Clean and simple component with proper text styling and locale-aware number formatting.
105-115: LGTM - Proper polling with cleanup.The interval-based polling with cleanup in the effect return is correctly implemented.
129-174: LGTM - Well-structured progress state derivation.The progress state logic handles the various sync states clearly, with helpful comments explaining edge cases like chains with no events in the block range.
261-266: LGTM!The start function correctly initializes the TUI and returns a rerender callback for external refresh control beyond the internal polling.
|
Merged as a part of #876 |
You can see the gif here https://github.com/enviodev/hyperindex/tree/dz/tui-love
Should probably record dev console, since it looks cooler. But I'll do it after finishing all performance optimizations.
Summary by CodeRabbit
New Features
Refactor
Chores
✏️ Tip: You can customize this high-level summary in your review settings.