Starting Over with Ink
This commit is contained in:
477
.kiro/specs/windows-compatible-tui/design.md
Normal file
477
.kiro/specs/windows-compatible-tui/design.md
Normal file
@@ -0,0 +1,477 @@
|
||||
# Design Document
|
||||
|
||||
## Overview
|
||||
|
||||
This design document outlines the replacement of the Blessed-based TUI with a Windows-compatible alternative using **Ink** (React for CLI) as the primary library choice. Ink provides excellent cross-platform support, modern React-based component architecture, and superior Windows compatibility compared to Blessed. The design maintains all existing functionality while improving performance, maintainability, and user experience across all platforms.
|
||||
|
||||
## Architecture
|
||||
|
||||
### Library Selection: Ink (React for CLI)
|
||||
|
||||
**Primary Choice: Ink v4.x**
|
||||
|
||||
- **Rationale**: Ink is built on React principles, providing a modern component-based architecture
|
||||
- **Windows Compatibility**: Excellent support for Windows Terminal, Command Prompt, and PowerShell
|
||||
- **Performance**: Uses React's reconciliation for efficient updates, reducing flicker
|
||||
- **Ecosystem**: Large ecosystem of pre-built components and utilities
|
||||
- **Maintenance**: Actively maintained by Vercel with strong community support
|
||||
|
||||
**Alternative Considerations**:
|
||||
|
||||
- **Blessed**: Current library with Windows issues (being replaced)
|
||||
- **Terminal-kit**: Good Windows support but more complex API
|
||||
- **Enquirer**: Limited to prompts, not full TUI applications
|
||||
- **Neo-blessed**: Fork of Blessed with some improvements but still has Windows issues
|
||||
|
||||
### Component Architecture
|
||||
|
||||
```
|
||||
TuiApplication (Root)
|
||||
├── AppProvider (Context/State Management)
|
||||
├── Router (Screen Management)
|
||||
├── StatusBar (Global Status)
|
||||
└── Screens/
|
||||
├── MainMenuScreen
|
||||
├── ConfigurationScreen
|
||||
├── OperationScreen
|
||||
├── SchedulingScreen
|
||||
├── LogViewerScreen
|
||||
└── TagAnalysisScreen
|
||||
```
|
||||
|
||||
### State Management
|
||||
|
||||
Using React Context API with custom hooks for:
|
||||
|
||||
- Application state (current screen, navigation history)
|
||||
- Configuration state (environment variables, settings)
|
||||
- Operation state (progress, results, errors)
|
||||
- UI state (focus, selections, modal states)
|
||||
|
||||
## Components and Interfaces
|
||||
|
||||
### Core Components
|
||||
|
||||
#### 1. TuiApplication (Root Component)
|
||||
|
||||
```javascript
|
||||
const TuiApplication = () => {
|
||||
return (
|
||||
<AppProvider>
|
||||
<Box flexDirection="column" height="100%">
|
||||
<StatusBar />
|
||||
<Router />
|
||||
</Box>
|
||||
</AppProvider>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
#### 2. AppProvider (State Management)
|
||||
|
||||
```javascript
|
||||
const AppProvider = ({ children }) => {
|
||||
const [appState, setAppState] = useState({
|
||||
currentScreen: "main-menu",
|
||||
navigationHistory: [],
|
||||
configuration: {},
|
||||
operationState: null,
|
||||
});
|
||||
|
||||
return (
|
||||
<AppContext.Provider value={{ appState, setAppState }}>
|
||||
{children}
|
||||
</AppContext.Provider>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
#### 3. Router (Screen Management)
|
||||
|
||||
```javascript
|
||||
const Router = () => {
|
||||
const { appState } = useContext(AppContext);
|
||||
|
||||
const screens = {
|
||||
"main-menu": MainMenuScreen,
|
||||
configuration: ConfigurationScreen,
|
||||
operation: OperationScreen,
|
||||
scheduling: SchedulingScreen,
|
||||
logs: LogViewerScreen,
|
||||
"tag-analysis": TagAnalysisScreen,
|
||||
};
|
||||
|
||||
const CurrentScreen = screens[appState.currentScreen];
|
||||
return <CurrentScreen />;
|
||||
};
|
||||
```
|
||||
|
||||
#### 4. StatusBar (Global Status Display)
|
||||
|
||||
```javascript
|
||||
const StatusBar = () => {
|
||||
const { connectionStatus, operationProgress } = useAppState();
|
||||
|
||||
return (
|
||||
<Box borderStyle="single" paddingX={1}>
|
||||
<Text color="green">● Connected</Text>
|
||||
<Text> | </Text>
|
||||
<Text>Progress: {operationProgress}%</Text>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
### Screen Components
|
||||
|
||||
#### MainMenuScreen
|
||||
|
||||
- Navigation menu with keyboard shortcuts
|
||||
- Current configuration summary
|
||||
- Quick action buttons
|
||||
- Help information
|
||||
|
||||
#### ConfigurationScreen
|
||||
|
||||
- Environment variable editor
|
||||
- Input validation with real-time feedback
|
||||
- API connection testing
|
||||
- Save/cancel operations
|
||||
|
||||
#### OperationScreen
|
||||
|
||||
- Operation type selection (update/rollback)
|
||||
- Real-time progress display
|
||||
- Product processing information
|
||||
- Error handling and display
|
||||
|
||||
#### SchedulingScreen
|
||||
|
||||
- Date/time picker interface
|
||||
- Schedule management
|
||||
- Countdown display
|
||||
- Cancellation controls
|
||||
|
||||
#### LogViewerScreen
|
||||
|
||||
- Paginated log display
|
||||
- Search and filtering
|
||||
- Log entry details
|
||||
- Export functionality
|
||||
|
||||
#### TagAnalysisScreen
|
||||
|
||||
- Tag listing and statistics
|
||||
- Product count per tag
|
||||
- Sample product display
|
||||
- Recommendations
|
||||
|
||||
### Reusable UI Components
|
||||
|
||||
#### ProgressBar
|
||||
|
||||
```javascript
|
||||
const ProgressBar = ({ progress, label, color = "blue" }) => {
|
||||
const width = 40;
|
||||
const filled = Math.round((progress / 100) * width);
|
||||
|
||||
return (
|
||||
<Box flexDirection="column">
|
||||
<Text>{label}</Text>
|
||||
<Box>
|
||||
<Text color={color}>{"█".repeat(filled)}</Text>
|
||||
<Text color="gray">{"░".repeat(width - filled)}</Text>
|
||||
<Text> {progress}%</Text>
|
||||
</Box>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
#### InputField
|
||||
|
||||
```javascript
|
||||
const InputField = ({ label, value, onChange, validation, placeholder }) => {
|
||||
const [isValid, setIsValid] = useState(true);
|
||||
|
||||
return (
|
||||
<Box flexDirection="column" marginY={1}>
|
||||
<Text>{label}:</Text>
|
||||
<TextInput
|
||||
value={value}
|
||||
onChange={(val) => {
|
||||
onChange(val);
|
||||
setIsValid(validation ? validation(val) : true);
|
||||
}}
|
||||
placeholder={placeholder}
|
||||
/>
|
||||
{!isValid && <Text color="red">Invalid input</Text>}
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
#### MenuList
|
||||
|
||||
```javascript
|
||||
const MenuList = ({ items, selectedIndex, onSelect }) => {
|
||||
return (
|
||||
<Box flexDirection="column">
|
||||
{items.map((item, index) => (
|
||||
<Box key={index} paddingX={2}>
|
||||
<Text color={index === selectedIndex ? "blue" : "white"}>
|
||||
{index === selectedIndex ? "► " : " "}
|
||||
{item.label}
|
||||
</Text>
|
||||
</Box>
|
||||
))}
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
## Data Models
|
||||
|
||||
### Application State
|
||||
|
||||
```javascript
|
||||
interface AppState {
|
||||
currentScreen: string;
|
||||
navigationHistory: string[];
|
||||
configuration: ConfigurationState;
|
||||
operationState: OperationState | null;
|
||||
uiState: UIState;
|
||||
}
|
||||
|
||||
interface ConfigurationState {
|
||||
shopifyDomain: string;
|
||||
accessToken: string;
|
||||
targetTag: string;
|
||||
priceAdjustment: number;
|
||||
operationMode: "update" | "rollback";
|
||||
isValid: boolean;
|
||||
lastTested: Date | null;
|
||||
}
|
||||
|
||||
interface OperationState {
|
||||
type: "update" | "rollback" | "scheduled";
|
||||
status: "idle" | "running" | "completed" | "error";
|
||||
progress: number;
|
||||
currentProduct: string | null;
|
||||
results: OperationResults | null;
|
||||
errors: Error[];
|
||||
}
|
||||
|
||||
interface UIState {
|
||||
focusedComponent: string;
|
||||
modalOpen: boolean;
|
||||
selectedMenuIndex: number;
|
||||
scrollPosition: number;
|
||||
}
|
||||
```
|
||||
|
||||
### Service Integration
|
||||
|
||||
```javascript
|
||||
interface ServiceIntegration {
|
||||
shopifyService: ShopifyService;
|
||||
productService: ProductService;
|
||||
progressService: ProgressService;
|
||||
configService: ConfigurationService;
|
||||
}
|
||||
```
|
||||
|
||||
## Error Handling
|
||||
|
||||
### Error Categories
|
||||
|
||||
1. **Configuration Errors**: Invalid environment variables, API credentials
|
||||
2. **Network Errors**: Connection failures, timeout issues
|
||||
3. **API Errors**: Shopify API rate limits, authentication failures
|
||||
4. **UI Errors**: Component rendering issues, state inconsistencies
|
||||
5. **System Errors**: File system access, permission issues
|
||||
|
||||
### Error Display Strategy
|
||||
|
||||
```javascript
|
||||
const ErrorBoundary = ({ children }) => {
|
||||
const [error, setError] = useState(null);
|
||||
|
||||
if (error) {
|
||||
return (
|
||||
<Box
|
||||
flexDirection="column"
|
||||
padding={2}
|
||||
borderStyle="single"
|
||||
borderColor="red"
|
||||
>
|
||||
<Text color="red" bold>
|
||||
Error Occurred
|
||||
</Text>
|
||||
<Text>{error.message}</Text>
|
||||
<Text color="gray">Press 'r' to retry or 'q' to quit</Text>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
return children;
|
||||
};
|
||||
```
|
||||
|
||||
### Graceful Degradation
|
||||
|
||||
- Fallback to basic text display if advanced features fail
|
||||
- Automatic retry mechanisms for network operations
|
||||
- State persistence to recover from crashes
|
||||
- Clear error messages with suggested actions
|
||||
|
||||
## Testing Strategy
|
||||
|
||||
### Component Testing
|
||||
|
||||
```javascript
|
||||
// Example test using Ink's testing utilities
|
||||
import { render } from "ink-testing-library";
|
||||
import { MainMenuScreen } from "../screens/MainMenuScreen";
|
||||
|
||||
test("renders main menu with correct options", () => {
|
||||
const { lastFrame } = render(<MainMenuScreen />);
|
||||
expect(lastFrame()).toContain("Price Update Operations");
|
||||
expect(lastFrame()).toContain("Configuration");
|
||||
expect(lastFrame()).toContain("View Logs");
|
||||
});
|
||||
```
|
||||
|
||||
### Integration Testing
|
||||
|
||||
- Test service integration with mock services
|
||||
- Verify state management across screen transitions
|
||||
- Test keyboard navigation and input handling
|
||||
- Validate error handling scenarios
|
||||
|
||||
### Cross-Platform Testing
|
||||
|
||||
- Automated testing on Windows, macOS, and Linux
|
||||
- Terminal compatibility testing (Windows Terminal, Command Prompt, PowerShell)
|
||||
- Unicode and color support verification
|
||||
- Performance testing with large datasets
|
||||
|
||||
## Migration Strategy
|
||||
|
||||
### Phase 1: Setup and Core Infrastructure
|
||||
|
||||
1. Install Ink and related dependencies
|
||||
2. Create basic application structure
|
||||
3. Implement state management system
|
||||
4. Set up routing and navigation
|
||||
|
||||
### Phase 2: Screen Implementation
|
||||
|
||||
1. Implement MainMenuScreen (simplest)
|
||||
2. Create ConfigurationScreen with form handling
|
||||
3. Build OperationScreen with progress display
|
||||
4. Add remaining screens (Scheduling, Logs, TagAnalysis)
|
||||
|
||||
### Phase 3: Component Migration
|
||||
|
||||
1. Replace Blessed ProgressBar with Ink version
|
||||
2. Migrate form components and input handling
|
||||
3. Update navigation and keyboard shortcuts
|
||||
4. Implement error handling and validation
|
||||
|
||||
### Phase 4: Testing and Refinement
|
||||
|
||||
1. Comprehensive testing on Windows systems
|
||||
2. Performance optimization and bug fixes
|
||||
3. Documentation updates
|
||||
4. Legacy code cleanup
|
||||
|
||||
### Dependency Changes
|
||||
|
||||
```json
|
||||
{
|
||||
"dependencies": {
|
||||
"ink": "^4.4.1",
|
||||
"react": "^18.2.0",
|
||||
"@ink/text-input": "^5.0.1",
|
||||
"@ink/select-input": "^5.0.1",
|
||||
"@ink/spinner": "^5.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"ink-testing-library": "^3.0.0"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### File Structure Changes
|
||||
|
||||
```
|
||||
src/
|
||||
├── tui/
|
||||
│ ├── components/
|
||||
│ │ ├── common/
|
||||
│ │ │ ├── ProgressBar.jsx
|
||||
│ │ │ ├── InputField.jsx
|
||||
│ │ │ ├── MenuList.jsx
|
||||
│ │ │ └── ErrorBoundary.jsx
|
||||
│ │ ├── screens/
|
||||
│ │ │ ├── MainMenuScreen.jsx
|
||||
│ │ │ ├── ConfigurationScreen.jsx
|
||||
│ │ │ ├── OperationScreen.jsx
|
||||
│ │ │ ├── SchedulingScreen.jsx
|
||||
│ │ │ ├── LogViewerScreen.jsx
|
||||
│ │ │ └── TagAnalysisScreen.jsx
|
||||
│ │ └── providers/
|
||||
│ │ ├── AppProvider.jsx
|
||||
│ │ └── ServiceProvider.jsx
|
||||
│ ├── hooks/
|
||||
│ │ ├── useAppState.js
|
||||
│ │ ├── useNavigation.js
|
||||
│ │ └── useServices.js
|
||||
│ ├── utils/
|
||||
│ │ ├── keyboardHandlers.js
|
||||
│ │ └── validation.js
|
||||
│ └── TuiApplication.jsx
|
||||
└── tui-entry.js (new entry point)
|
||||
```
|
||||
|
||||
## Performance Considerations
|
||||
|
||||
### Rendering Optimization
|
||||
|
||||
- Use React.memo for expensive components
|
||||
- Implement virtual scrolling for large lists
|
||||
- Debounce rapid state updates
|
||||
- Minimize re-renders with proper state structure
|
||||
|
||||
### Memory Management
|
||||
|
||||
- Clean up event listeners and timers
|
||||
- Implement proper component unmounting
|
||||
- Use weak references for large data structures
|
||||
- Monitor memory usage during long operations
|
||||
|
||||
### Windows-Specific Optimizations
|
||||
|
||||
- Use Windows-compatible Unicode characters
|
||||
- Optimize for Windows Terminal performance
|
||||
- Handle Windows-specific keyboard events
|
||||
- Ensure proper color rendering in different terminals
|
||||
|
||||
## Security Considerations
|
||||
|
||||
### Input Validation
|
||||
|
||||
- Sanitize all user inputs
|
||||
- Validate configuration values
|
||||
- Prevent injection attacks through input fields
|
||||
- Secure handling of API credentials
|
||||
|
||||
### State Security
|
||||
|
||||
- Encrypt sensitive data in state
|
||||
- Clear sensitive information on exit
|
||||
- Prevent credential logging
|
||||
- Secure temporary file handling
|
||||
|
||||
This design provides a robust foundation for replacing Blessed with Ink, ensuring excellent Windows compatibility while maintaining all existing functionality and improving the overall user experience.
|
||||
Reference in New Issue
Block a user