@@ -2,15 +2,15 @@ import { ReactNode } from 'react'
22import Page , { PageProps } from './Page.js'
33import Welcome from './Welcome.js'
44
5- import type { DataFrame , DataFrameEvents , ResolvedValue , UnsortableDataFrame } from 'hightable'
6- import { createEventTarget , sortableDataFrame } from 'hightable'
5+ import type { DataFrame , DataFrameEvents , ResolvedValue } from 'hightable'
6+ import { checkSignal , createEventTarget , sortableDataFrame , validateFetchParams , validateGetCellParams , validateGetRowNumberParams } from 'hightable'
77import { icebergListVersions , icebergMetadata , icebergRead } from 'icebird'
88import type { Snapshot , TableMetadata } from 'icebird/src/types.js'
99import { useCallback , useEffect , useState } from 'react'
1010import Layout from './Layout.js'
1111
1212const empty : DataFrame = {
13- header : [ ] ,
13+ columnDescriptors : [ ] ,
1414 numRows : 0 ,
1515 eventTarget : createEventTarget < DataFrameEvents > ( ) ,
1616 getRowNumber : ( ) => undefined ,
@@ -89,7 +89,7 @@ function icebergDataFrame(tableUrl: string, metadataFileName: string, metadata:
8989 const currentSchemaId = metadata [ 'current-schema-id' ]
9090 const schema = metadata . schemas . find ( s => s [ 'schema-id' ] === currentSchemaId )
9191 if ( ! schema ) throw new Error ( 'Current schema not found in metadata' )
92- const header = schema . fields . map ( f => f . name )
92+ const columnDescriptors = schema . fields . map ( ( { name } ) => ( { name } ) )
9393 const eventTarget = createEventTarget < DataFrameEvents > ( )
9494
9595 type CachedValue < T > = {
@@ -101,16 +101,15 @@ function icebergDataFrame(tableUrl: string, metadataFileName: string, metadata:
101101
102102 const rowNumberCache : CachedValue < number > [ ] = [ ]
103103 const cellCache = new Map < string , CachedValue < unknown > [ ] > ( )
104- header . forEach ( column => cellCache . set ( column , [ ] ) )
104+ columnDescriptors . forEach ( ( { name } ) => cellCache . set ( name , [ ] ) )
105105
106- function getRowNumber ( { row } : { row : number } ) : ResolvedValue < number > | undefined {
107- validateRow ( { row, data : { numRows } } )
106+ function getRowNumber ( { row } : { row : number } ) : ResolvedValue < number > | undefined {
107+ validateGetRowNumberParams ( { row, data : { numRows, columnDescriptors } } )
108108 const cachedValue = rowNumberCache [ row ]
109109 return cachedValue ?. kind === 'fetched' ? cachedValue . value : undefined
110110 }
111- function getCell ( { row, column } : { row : number , column : string } ) : ResolvedValue < unknown > | undefined {
112- validateRow ( { row, data : { numRows } } )
113- validateColumn ( { column, data : { header } } )
111+ function getCell ( { row, column } : { row : number , column : string } ) : ResolvedValue < unknown > | undefined {
112+ validateGetCellParams ( { row, column, data : { numRows, columnDescriptors } } )
114113 const cachedValue = cellCache . get ( column ) ?. [ row ]
115114 return cachedValue ?. kind === 'fetched' ? cachedValue . value : undefined
116115 }
@@ -120,14 +119,14 @@ function icebergDataFrame(tableUrl: string, metadataFileName: string, metadata:
120119
121120 // TODO: fetch by row groups, to avoid fetching row by row when we scroll
122121
123- const unsortableDataFrame : UnsortableDataFrame = {
124- header ,
122+ const unsortableDataFrame : DataFrame = {
123+ columnDescriptors ,
125124 numRows,
126125 eventTarget,
127126 getRowNumber,
128127 getCell,
129128 async fetch ( { rowStart, rowEnd, columns, signal } ) {
130- validateFetchParams ( { rowStart, rowEnd, columns, data : { numRows, header } } )
129+ validateFetchParams ( { rowStart, rowEnd, columns, data : { numRows, columnDescriptors } } )
131130 checkSignal ( signal )
132131
133132 const ranges = [ ]
@@ -200,27 +199,3 @@ function icebergDataFrame(tableUrl: string, metadataFileName: string, metadata:
200199 return sortableDataFrame ( unsortableDataFrame )
201200
202201}
203-
204- function validateFetchParams ( { rowStart, rowEnd, columns, data : { numRows, header } } : { rowStart : number , rowEnd : number , columns ?: string [ ] , data : Pick < DataFrame , 'numRows' | 'header' > } ) : void {
205- if ( rowStart < 0 || rowEnd > numRows || ! Number . isInteger ( rowStart ) || ! Number . isInteger ( rowEnd ) || rowStart > rowEnd ) {
206- throw new Error ( `Invalid row range: ${ rowStart } - ${ rowEnd } , numRows: ${ numRows } ` )
207- }
208- if ( columns ?. some ( column => ! header . includes ( column ) ) ) {
209- throw new Error ( `Invalid columns: ${ columns . join ( ', ' ) } . Available columns: ${ header . join ( ', ' ) } ` )
210- }
211- }
212- function validateRow ( { row, data : { numRows } } : { row : number , data : Pick < DataFrame , 'numRows' > } ) : void {
213- if ( row < 0 || row >= numRows || ! Number . isInteger ( row ) ) {
214- throw new Error ( `Invalid row index: ${ row } , numRows: ${ numRows } ` )
215- }
216- }
217- function validateColumn ( { column, data : { header } } : { column : string , data : Pick < DataFrame , 'header' > } ) : void {
218- if ( ! header . includes ( column ) ) {
219- throw new Error ( `Invalid column: ${ column } . Available columns: ${ header . join ( ', ' ) } ` )
220- }
221- }
222- function checkSignal ( signal ?: AbortSignal ) : void {
223- if ( signal ?. aborted ) {
224- throw new DOMException ( 'The operation was aborted.' , 'AbortError' )
225- }
226- }
0 commit comments