-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathAvroView.tsx
More file actions
64 lines (57 loc) · 1.99 KB
/
AvroView.tsx
File metadata and controls
64 lines (57 loc) · 1.99 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
import { useEffect, useState } from 'react'
import type { FileSource } from '../../lib/sources/types.js'
import { parseFileSize } from '../../lib/utils.js'
import styles from '../../styles/Json.module.css'
import Json from '../Json.js'
import { Spinner } from '../Layout.js'
import ContentHeader, { ContentSize } from './ContentHeader.js'
import { avroData, avroMetadata } from 'icebird'
interface ViewerProps {
source: FileSource
setError: (error: Error | undefined) => void
}
/**
* Apache Avro viewer component.
*/
export default function AvroView({ source, setError }: ViewerProps) {
const [content, setContent] = useState<ContentSize>()
const [json, setJson] = useState<unknown>()
const [isLoading, setIsLoading] = useState(true)
const { resolveUrl, requestInit } = source
// Load avro content as json
useEffect(() => {
async function loadContent() {
try {
setIsLoading(true)
const res = await fetch(resolveUrl, requestInit)
if (res.status === 401) {
const text = await res.text()
setError(new Error(text))
setContent(undefined)
return
}
// Parse avro file
const buffer = await res.arrayBuffer()
const fileSize = parseFileSize(res.headers) ?? buffer.byteLength
const reader = { view: new DataView(buffer), offset: 0 }
const { metadata, syncMarker } = avroMetadata(reader)
const json = avroData({ reader, metadata, syncMarker })
setError(undefined)
setContent({ fileSize })
setJson(json)
} catch (error) {
setError(error as Error)
} finally {
setIsLoading(false)
}
}
void loadContent()
}, [resolveUrl, requestInit, setError])
const headers = content === undefined && <span>Loading...</span>
return <ContentHeader content={content} headers={headers}>
<code className={styles.jsonView}>
<Json json={json} />
</code>
{isLoading && <div className='center'><Spinner /></div>}
</ContentHeader>
}