-
Notifications
You must be signed in to change notification settings - Fork 0
Open
Labels
enhancementNew feature or requestNew feature or request
Description
Refactor resequences epic for better declarative composition
The current resequences
epic in client/lib/keys.ts
handles grid selection → time range conversion in a single monolithic function. While functional, it could be more literate and composable by breaking down the transformation pipeline into smaller, named operations.
Current Issues
- Dense transformation logic - The
concatMap
contains complex coordinate conversion, data lookup, and edge case handling all in one place - Mixed abstraction levels - Low-level array operations mixed with high-level domain logic
- Hard to test - The entire transformation is one big function
- Not reusable - Grid coordinate logic is embedded in the epic
Proposed Refactor
Break the epic into a pipeline of smaller, named transformations:
// Domain-specific operators
const gridSelectionsOnly = () => pipe(
map((s: State) => s.view),
filter((view): view is GridView => view.type === 'grid'),
distinctBy(selectionModeKey),
filter(isDoubleSelection)
);
const toGridCoordinates = () => pipe(
map(({ input: { selection } }) =>
parseGridSelection(selection.value)
)
);
const toTimeRange = (gridData: Observable<GridData>) => pipe(
withLatestFrom(gridData),
map(([coordinates, data]) =>
coordinatesToTimeRange(coordinates, data)
)
);
// Pure functions for transformations
const parseGridSelection = (selection: string[]): [number, number] => { /* ... */ };
const coordinatesToTimeRange = (coords: [number, number], data: GridData): TraversalCommand => { /* ... */ };
const selectionModeKey = (view: GridView) => /* ... */;
const isDoubleSelection = (view: GridView): view is DoubleSelectionView => /* ... */;
// Composed epic
export const resequences: AppEpic<TraversalCommand> = (cmds, state) => {
const gridData$ = state.pipe(map(select.data), shareReplay(1));
return state.pipe(
gridSelectionsOnly(),
toGridCoordinates(),
toTimeRange(gridData$)
);
};
Benefits
- Testable components - Each transformation can be unit tested
- Reusable logic - Grid coordinate parsing could be used elsewhere
- Clear intent - Each operator has a single, named responsibility
- Easier debugging - Can log/tap between stages
- Type safety - Smaller functions are easier to type correctly
Implementation Notes
- Keep the existing behavior exactly the same
- Extract pure functions first, then build operators around them
- Consider moving grid coordinate logic to a separate module
- Maintain the same error handling and edge cases
Metadata
Metadata
Assignees
Labels
enhancementNew feature or requestNew feature or request