Tony Powell commited on
Commit
34cfb9f
·
1 Parent(s): 0b7a4b4

Initial PoC

Browse files

- Load data into duckdb via parquet and httpfs extensions
- Convert data to json via arrow apis
- Render data into table using arbitrary header detection

Files changed (5) hide show
  1. package.json +1 -0
  2. pnpm-lock.yaml +191 -5
  3. src/App.tsx +140 -25
  4. src/duck.ts +30 -0
  5. src/table.tsx +32 -0
package.json CHANGED
@@ -10,6 +10,7 @@
10
  "preview": "vite preview"
11
  },
12
  "dependencies": {
 
13
  "react": "^18.3.1",
14
  "react-dom": "^18.3.1"
15
  },
 
10
  "preview": "vite preview"
11
  },
12
  "dependencies": {
13
+ "@duckdb/duckdb-wasm": "1.28.1-dev106.0",
14
  "react": "^18.3.1",
15
  "react-dom": "^18.3.1"
16
  },
pnpm-lock.yaml CHANGED
@@ -8,6 +8,9 @@ importers:
8
 
9
  .:
10
  dependencies:
 
 
 
11
  react:
12
  specifier: ^18.3.1
13
  version: 18.3.1
@@ -26,7 +29,7 @@ importers:
26
  version: 18.3.0
27
  '@vitejs/plugin-react':
28
  specifier: ^4.3.2
29
- version: 4.3.2([email protected])
30
  eslint:
31
  specifier: ^9.11.1
32
  version: 9.12.0
@@ -47,10 +50,14 @@ importers:
47
48
  vite:
49
  specifier: ^5.4.8
50
- version: 5.4.8
51
 
52
  packages:
53
 
 
 
 
 
54
  '@ampproject/[email protected]':
55
  resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==}
56
  engines: {node: '>=6.0.0'}
@@ -142,6 +149,9 @@ packages:
142
  resolution: {integrity: sha512-vwIVdXG+j+FOpkwqHRcBgHLYNL7XMkufrlaFvL9o6Ai9sJn9+PdyIL5qa0XzTZw084c+u9LOls53eoZWP/W5WQ==}
143
  engines: {node: '>=6.9.0'}
144
 
 
 
 
145
  '@esbuild/[email protected]':
146
  resolution: {integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==}
147
  engines: {node: '>=12'}
@@ -452,12 +462,24 @@ packages:
452
  '@types/[email protected]':
453
  resolution: {integrity: sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==}
454
 
 
 
 
 
 
 
455
  '@types/[email protected]':
456
  resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==}
457
 
458
  '@types/[email protected]':
459
  resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==}
460
 
 
 
 
 
 
 
461
  '@types/[email protected]':
462
  resolution: {integrity: sha512-hCZTSvwbzWGvhqxp/RqVqwU999pBf2vp7hzIjiYOsl8wqOmUxkQ6ddw1cV3l8811+kdUFus/q4d1Y3E3SyEifA==}
463
 
@@ -551,9 +573,21 @@ packages:
551
  resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==}
552
  engines: {node: '>=8'}
553
 
 
 
 
 
554
555
  resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==}
556
 
 
 
 
 
 
 
 
 
557
558
  resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
559
 
@@ -579,6 +613,10 @@ packages:
579
580
  resolution: {integrity: sha512-7LTwJjcRkzKFmtqGsibMeuXmvFDfZq/nzIjnmgCGzKKRVzjD72selLDK1oPF/Oxzmt4fNcPvTDvGqSDG4tCALw==}
581
 
 
 
 
 
582
583
  resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==}
584
  engines: {node: '>=4'}
@@ -600,6 +638,14 @@ packages:
600
601
  resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
602
 
 
 
 
 
 
 
 
 
603
604
  resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
605
 
@@ -722,6 +768,10 @@ packages:
722
  resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==}
723
  engines: {node: '>=8'}
724
 
 
 
 
 
725
726
  resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==}
727
  engines: {node: '>=10'}
@@ -730,6 +780,9 @@ packages:
730
  resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==}
731
  engines: {node: '>=16'}
732
 
 
 
 
733
734
  resolution: {integrity: sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==}
735
 
@@ -812,6 +865,10 @@ packages:
812
  engines: {node: '>=6'}
813
  hasBin: true
814
 
 
 
 
 
815
816
  resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==}
817
 
@@ -837,9 +894,15 @@ packages:
837
  resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==}
838
  engines: {node: '>=10'}
839
 
 
 
 
840
841
  resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==}
842
 
 
 
 
843
844
  resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==}
845
  hasBin: true
@@ -888,6 +951,10 @@ packages:
888
  resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==}
889
  engines: {node: '>=10'}
890
 
 
 
 
 
891
892
  resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==}
893
  engines: {node: '>=6'}
@@ -935,6 +1002,10 @@ packages:
935
  resolution: {integrity: sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==}
936
  engines: {node: '>=0.10.0'}
937
 
 
 
 
 
938
939
  resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==}
940
  engines: {node: '>=4'}
@@ -975,6 +1046,10 @@ packages:
975
  resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==}
976
  engines: {node: '>=0.10.0'}
977
 
 
 
 
 
978
979
  resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==}
980
  engines: {node: '>=8'}
@@ -987,6 +1062,11 @@ packages:
987
  resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==}
988
  engines: {node: '>=8'}
989
 
 
 
 
 
 
990
991
  resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==}
992
 
@@ -1004,6 +1084,9 @@ packages:
1004
  peerDependencies:
1005
  typescript: '>=4.2.0'
1006
 
 
 
 
1007
1008
  resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==}
1009
  engines: {node: '>= 0.8.0'}
@@ -1022,6 +1105,14 @@ packages:
1022
  engines: {node: '>=14.17'}
1023
  hasBin: true
1024
 
 
 
 
 
 
 
 
 
1025
1026
  resolution: {integrity: sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==}
1027
  hasBin: true
@@ -1071,6 +1162,10 @@ packages:
1071
  resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==}
1072
  engines: {node: '>=0.10.0'}
1073
 
 
 
 
 
1074
1075
  resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==}
1076
 
@@ -1080,6 +1175,11 @@ packages:
1080
 
1081
  snapshots:
1082
 
 
 
 
 
 
1083
  '@ampproject/[email protected]':
1084
  dependencies:
1085
  '@jridgewell/gen-mapping': 0.3.5
@@ -1209,6 +1309,10 @@ snapshots:
1209
  '@babel/helper-validator-identifier': 7.25.7
1210
  to-fast-properties: 2.0.0
1211
 
 
 
 
 
1212
  '@esbuild/[email protected]':
1213
  optional: true
1214
 
@@ -1426,10 +1530,18 @@ snapshots:
1426
  dependencies:
1427
  '@babel/types': 7.25.7
1428
 
 
 
 
 
1429
  '@types/[email protected]': {}
1430
 
1431
  '@types/[email protected]': {}
1432
 
 
 
 
 
1433
  '@types/[email protected]': {}
1434
 
1435
  '@types/[email protected]':
@@ -1522,14 +1634,14 @@ snapshots:
1522
  '@typescript-eslint/types': 8.8.0
1523
  eslint-visitor-keys: 3.4.3
1524
 
1525
1526
  dependencies:
1527
  '@babel/core': 7.25.7
1528
  '@babel/plugin-transform-react-jsx-self': 7.25.7(@babel/[email protected])
1529
  '@babel/plugin-transform-react-jsx-source': 7.25.7(@babel/[email protected])
1530
  '@types/babel__core': 7.20.5
1531
  react-refresh: 0.14.2
1532
- vite: 5.4.8
1533
  transitivePeerDependencies:
1534
  - supports-color
1535
 
@@ -1554,8 +1666,25 @@ snapshots:
1554
  dependencies:
1555
  color-convert: 2.0.1
1556
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1557
1558
 
 
 
 
 
1559
1560
 
1561
@@ -1582,6 +1711,10 @@ snapshots:
1582
 
1583
1584
 
 
 
 
 
1585
1586
  dependencies:
1587
  ansi-styles: 3.2.1
@@ -1605,6 +1738,20 @@ snapshots:
1605
 
1606
1607
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1608
1609
 
1610
@@ -1758,6 +1905,10 @@ snapshots:
1758
  dependencies:
1759
  to-regex-range: 5.0.1
1760
 
 
 
 
 
1761
1762
  dependencies:
1763
  locate-path: 6.0.0
@@ -1768,6 +1919,8 @@ snapshots:
1768
  flatted: 3.3.1
1769
  keyv: 4.5.4
1770
 
 
 
1771
1772
 
1773
@@ -1822,6 +1975,8 @@ snapshots:
1822
 
1823
1824
 
 
 
1825
1826
 
1827
@@ -1843,8 +1998,12 @@ snapshots:
1843
  dependencies:
1844
  p-locate: 5.0.0
1845
 
 
 
1846
1847
 
 
 
1848
1849
  dependencies:
1850
  js-tokens: 4.0.0
@@ -1893,6 +2052,10 @@ snapshots:
1893
  dependencies:
1894
  p-limit: 3.1.0
1895
 
 
 
 
 
1896
1897
  dependencies:
1898
  callsites: 3.1.0
@@ -1929,6 +2092,8 @@ snapshots:
1929
  dependencies:
1930
  loose-envify: 1.4.0
1931
 
 
 
1932
1933
 
1934
@@ -1975,6 +2140,8 @@ snapshots:
1975
 
1976
1977
 
 
 
1978
1979
 
1980
@@ -1985,6 +2152,16 @@ snapshots:
1985
  dependencies:
1986
  has-flag: 4.0.0
1987
 
 
 
 
 
 
 
 
 
 
 
1988
1989
 
1990
@@ -1997,6 +2174,8 @@ snapshots:
1997
  dependencies:
1998
  typescript: 5.6.2
1999
 
 
 
2000
2001
  dependencies:
2002
  prelude-ls: 1.2.1
@@ -2014,6 +2193,10 @@ snapshots:
2014
 
2015
2016
 
 
 
 
 
2017
2018
  dependencies:
2019
  browserslist: 4.24.0
@@ -2024,12 +2207,13 @@ snapshots:
2024
  dependencies:
2025
  punycode: 2.3.1
2026
 
2027
2028
  dependencies:
2029
  esbuild: 0.21.5
2030
  postcss: 8.4.47
2031
  rollup: 4.24.0
2032
  optionalDependencies:
 
2033
  fsevents: 2.3.3
2034
 
2035
@@ -2038,6 +2222,8 @@ snapshots:
2038
 
2039
2040
 
 
 
2041
2042
 
2043
 
8
 
9
  .:
10
  dependencies:
11
+ '@duckdb/duckdb-wasm':
12
+ specifier: 1.28.1-dev106.0
13
+ version: 1.28.1-dev106.0
14
  react:
15
  specifier: ^18.3.1
16
  version: 18.3.1
 
29
  version: 18.3.0
30
  '@vitejs/plugin-react':
31
  specifier: ^4.3.2
32
+ version: 4.3.2([email protected](@types/[email protected]))
33
  eslint:
34
  specifier: ^9.11.1
35
  version: 9.12.0
 
50
51
  vite:
52
  specifier: ^5.4.8
53
+ version: 5.4.8(@types/[email protected])
54
 
55
  packages:
56
 
57
+ '@75lb/[email protected]':
58
+ resolution: {integrity: sha512-08K9ou5VNbheZFxM5tDWoqjA3ImC50DiuuJ2tj1yEPRfkp8lLLg6XAaJ4On+a0yAXor/8ay5gHnAIshRM44Kpw==}
59
+ engines: {node: '>=12.17'}
60
+
61
  '@ampproject/[email protected]':
62
  resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==}
63
  engines: {node: '>=6.0.0'}
 
149
  resolution: {integrity: sha512-vwIVdXG+j+FOpkwqHRcBgHLYNL7XMkufrlaFvL9o6Ai9sJn9+PdyIL5qa0XzTZw084c+u9LOls53eoZWP/W5WQ==}
150
  engines: {node: '>=6.9.0'}
151
 
152
+ '@duckdb/[email protected]':
153
+ resolution: {integrity: sha512-HcA9q/Yq1t8nAIg2rl8DmOTjKy1tAHSdBGHlCcWAm5StsfAjcm+f0STBEH3hmWPk0qEtOJF30OR+GfeyUOP+hA==}
154
+
155
  '@esbuild/[email protected]':
156
  resolution: {integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==}
157
  engines: {node: '>=12'}
 
462
  '@types/[email protected]':
463
  resolution: {integrity: sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==}
464
 
465
+ '@types/[email protected]':
466
+ resolution: {integrity: sha512-UuKzKpJJ/Ief6ufIaIzr3A/0XnluX7RvFgwkV89Yzvm77wCh1kFaFmqN8XEnGcN62EuHdedQjEMb8mYxFLGPyA==}
467
+
468
+ '@types/[email protected]':
469
+ resolution: {integrity: sha512-n7RlEEJ+4x4TS7ZQddTmNSxP+zziEG0TNsMfiRIxcIVXt71ENJ9ojeXmGO3wPoTdn7pJcU2xc3CJYMktNT6DPg==}
470
+
471
  '@types/[email protected]':
472
  resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==}
473
 
474
  '@types/[email protected]':
475
  resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==}
476
 
477
+ '@types/[email protected]':
478
+ resolution: {integrity: sha512-cumHmIAf6On83X7yP+LrsEyUOf/YlociZelmpRYaGFydoaPdxdt80MAbu6vWerQT2COCp2nPvHdsbD7tHn/YlQ==}
479
+
480
+ '@types/[email protected]':
481
+ resolution: {integrity: sha512-Xd22WCRBydkGSApl5Bw0PhAOHKSVjNL3E3AwzKaps96IMraPqy5BvZIsBVK6JLwdybUzjHnuWVwpDd0JjTfHXA==}
482
+
483
  '@types/[email protected]':
484
  resolution: {integrity: sha512-hCZTSvwbzWGvhqxp/RqVqwU999pBf2vp7hzIjiYOsl8wqOmUxkQ6ddw1cV3l8811+kdUFus/q4d1Y3E3SyEifA==}
485
 
 
573
  resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==}
574
  engines: {node: '>=8'}
575
 
576
577
+ resolution: {integrity: sha512-EBO2xJN36/XoY81nhLcwCJgFwkboDZeyNQ+OPsG7bCoQjc2BT0aTyH/MR6SrL+LirSNz+cYqjGRlupMMlP1aEg==}
578
+ hasBin: true
579
+
580
581
  resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==}
582
 
583
584
+ resolution: {integrity: sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q==}
585
+ engines: {node: '>=6'}
586
+
587
588
+ resolution: {integrity: sha512-gUAZ7HPyb4SJczXAMUXMGAvI976JoK3qEx9v1FTmeYuJj0IBiaKttG1ydtGKdkfqWkIkouke7nG8ufGy77+Cvw==}
589
+ engines: {node: '>=12.17'}
590
+
591
592
  resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
593
 
 
613
614
  resolution: {integrity: sha512-7LTwJjcRkzKFmtqGsibMeuXmvFDfZq/nzIjnmgCGzKKRVzjD72selLDK1oPF/Oxzmt4fNcPvTDvGqSDG4tCALw==}
615
 
616
617
+ resolution: {integrity: sha512-/ghrgmhfY8RaSdeo43hNXxpoHAtxdbskUHjPpfqUWGttFgycUhYPGx3YZBCnUCvOa7Doivn1IZec3DEGFoMgLg==}
618
+ engines: {node: '>=12'}
619
+
620
621
  resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==}
622
  engines: {node: '>=4'}
 
638
639
  resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
640
 
641
642
+ resolution: {integrity: sha512-H4UfQhZyakIjC74I9d34fGYDwk3XpSr17QhEd0Q3I9Xq1CETHo4Hcuo87WyWHpAF1aSLjLRf5lD9ZGX2qStUvg==}
643
+ engines: {node: '>=4.0.0'}
644
+
645
646
+ resolution: {integrity: sha512-NCyznE//MuTjwi3y84QVUGEOT+P5oto1e1Pk/jFPVdPPfsG03qpTIl3yw6etR+v73d0lXsoojRpvbru2sqePxQ==}
647
+ engines: {node: '>=12.20.0'}
648
+
649
650
  resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
651
 
 
768
  resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==}
769
  engines: {node: '>=8'}
770
 
771
772
+ resolution: {integrity: sha512-6Tb2myMioCAgv5kfvP5/PkZZ/ntTpVK39fHY7WkWBgvbeE+VHd/tZuZ4mrC+bxh4cfOZeYKVPaJIZtZXV7GNCQ==}
773
+ engines: {node: '>=4.0.0'}
774
+
775
776
  resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==}
777
  engines: {node: '>=10'}
 
780
  resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==}
781
  engines: {node: '>=16'}
782
 
783
784
+ resolution: {integrity: sha512-vE+SI9vrJDwi1oETtTIFldC/o9GsVKRM+s6EL0nQgxXlYV1Vc4Tk30hj4xGICftInKQKj1F3up2n8UbIVobISQ==}
785
+
786
787
  resolution: {integrity: sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==}
788
 
 
865
  engines: {node: '>=6'}
866
  hasBin: true
867
 
868
869
+ resolution: {integrity: sha512-2WHyXj3OfHSgNyuzDbSxI1w2jgw5gkWSWhS7Qg4bWXx1nLk3jnbwfUeS0PSba3IzpTUWdHxBieELUzXRjQB2zg==}
870
+ engines: {node: '>=0.8'}
871
+
872
873
  resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==}
874
 
 
894
  resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==}
895
  engines: {node: '>=10'}
896
 
897
898
+ resolution: {integrity: sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==}
899
+
900
901
  resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==}
902
 
903
904
+ resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==}
905
+
906
907
  resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==}
908
  hasBin: true
 
951
  resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==}
952
  engines: {node: '>=10'}
953
 
954
955
+ resolution: {integrity: sha512-HJxs9K9AztdIQIAIa/OIazRAUW/L6B9hbQDxO4X07roW3eo9XqZc2ur9bn1StH9CnbbI9EgvejHQX7CBpCF1QA==}
956
+ engines: {node: '>=0.10.0'}
957
+
958
959
  resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==}
960
  engines: {node: '>=6'}
 
1002
  resolution: {integrity: sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==}
1003
  engines: {node: '>=0.10.0'}
1004
 
1005
1006
+ resolution: {integrity: sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==}
1007
+ engines: {node: '>=0.10'}
1008
+
1009
1010
  resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==}
1011
  engines: {node: '>=4'}
 
1046
  resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==}
1047
  engines: {node: '>=0.10.0'}
1048
 
1049
1050
+ resolution: {integrity: sha512-EWZT9XOceBPlVJRrYcykW8jyRSZYbkb/0ZK36uLEmoWVO5gxBOnntNTseNzfREsqxqdfEGQrD8SXQ3QWbBmq8A==}
1051
+ engines: {node: '>=10'}
1052
+
1053
1054
  resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==}
1055
  engines: {node: '>=8'}
 
1062
  resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==}
1063
  engines: {node: '>=8'}
1064
 
1065
1066
+ resolution: {integrity: sha512-rpyNZYRw+/C+dYkcQ3Pr+rLxW4CfHpXjPDnG7lYhdRoUcZTUt+KEsX+94RGp/aVp/MQU35JCITv2T/beY4m+hw==}
1067
+ engines: {node: '>=12.17'}
1068
+ hasBin: true
1069
+
1070
1071
  resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==}
1072
 
 
1084
  peerDependencies:
1085
  typescript: '>=4.2.0'
1086
 
1087
1088
+ resolution: {integrity: sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==}
1089
+
1090
1091
  resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==}
1092
  engines: {node: '>= 0.8.0'}
 
1105
  engines: {node: '>=14.17'}
1106
  hasBin: true
1107
 
1108
1109
+ resolution: {integrity: sha512-VAH4IvQ7BDFYglMd7BPRDfLgxZZX4O4TFcRDA6EN5X7erNJJq+McIEp8np9aVtxrCJ6qx4GTYVfOWNjcqwZgRw==}
1110
+ engines: {node: '>=8'}
1111
+
1112
1113
+ resolution: {integrity: sha512-W1+HdVRUl8fS3MZ9ogD51GOb46xMmhAZzR0WPw5jcgIZQJVvkddYzAl4YTU6g5w33Y1iRQLdIi2/1jhi2RNL0g==}
1114
+ engines: {node: '>=12.17'}
1115
+
1116
1117
  resolution: {integrity: sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==}
1118
  hasBin: true
 
1162
  resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==}
1163
  engines: {node: '>=0.10.0'}
1164
 
1165
1166
+ resolution: {integrity: sha512-JNjcULU2e4KJwUNv6CHgI46UvDGitb6dGryHajXTDiLgg1/RiGoPSDw4kZfYnwGtEXf2ZMeIewDQgFGzkCB2Sg==}
1167
+ engines: {node: '>=12.17'}
1168
+
1169
1170
  resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==}
1171
 
 
1175
 
1176
  snapshots:
1177
 
1178
+ '@75lb/[email protected]':
1179
+ dependencies:
1180
+ lodash: 4.17.21
1181
+ typical: 7.2.0
1182
+
1183
  '@ampproject/[email protected]':
1184
  dependencies:
1185
  '@jridgewell/gen-mapping': 0.3.5
 
1309
  '@babel/helper-validator-identifier': 7.25.7
1310
  to-fast-properties: 2.0.0
1311
 
1312
+ '@duckdb/[email protected]':
1313
+ dependencies:
1314
+ apache-arrow: 14.0.2
1315
+
1316
  '@esbuild/[email protected]':
1317
  optional: true
1318
 
 
1530
  dependencies:
1531
  '@babel/types': 7.25.7
1532
 
1533
+ '@types/[email protected]': {}
1534
+
1535
+ '@types/[email protected]': {}
1536
+
1537
  '@types/[email protected]': {}
1538
 
1539
  '@types/[email protected]': {}
1540
 
1541
+ '@types/[email protected]': {}
1542
+
1543
+ '@types/[email protected]': {}
1544
+
1545
  '@types/[email protected]': {}
1546
 
1547
  '@types/[email protected]':
 
1634
  '@typescript-eslint/types': 8.8.0
1635
  eslint-visitor-keys: 3.4.3
1636
 
1637
1638
  dependencies:
1639
  '@babel/core': 7.25.7
1640
  '@babel/plugin-transform-react-jsx-self': 7.25.7(@babel/[email protected])
1641
  '@babel/plugin-transform-react-jsx-source': 7.25.7(@babel/[email protected])
1642
  '@types/babel__core': 7.20.5
1643
  react-refresh: 0.14.2
1644
+ vite: 5.4.8(@types/[email protected])
1645
  transitivePeerDependencies:
1646
  - supports-color
1647
 
 
1666
  dependencies:
1667
  color-convert: 2.0.1
1668
 
1669
1670
+ dependencies:
1671
+ '@types/command-line-args': 5.2.0
1672
+ '@types/command-line-usage': 5.0.2
1673
+ '@types/node': 20.3.0
1674
+ '@types/pad-left': 2.1.1
1675
+ command-line-args: 5.2.1
1676
+ command-line-usage: 7.0.1
1677
+ flatbuffers: 23.5.26
1678
+ json-bignum: 0.0.3
1679
+ pad-left: 2.1.0
1680
+ tslib: 2.7.0
1681
+
1682
1683
 
1684
1685
+
1686
1687
+
1688
1689
 
1690
 
1711
 
1712
1713
 
1714
1715
+ dependencies:
1716
+ chalk: 4.1.2
1717
+
1718
1719
  dependencies:
1720
  ansi-styles: 3.2.1
 
1738
 
1739
1740
 
1741
1742
+ dependencies:
1743
+ array-back: 3.1.0
1744
+ find-replace: 3.0.0
1745
+ lodash.camelcase: 4.3.0
1746
+ typical: 4.0.0
1747
+
1748
1749
+ dependencies:
1750
+ array-back: 6.2.2
1751
+ chalk-template: 0.4.0
1752
+ table-layout: 3.0.2
1753
+ typical: 7.2.0
1754
+
1755
1756
 
1757
 
1905
  dependencies:
1906
  to-regex-range: 5.0.1
1907
 
1908
1909
+ dependencies:
1910
+ array-back: 3.1.0
1911
+
1912
1913
  dependencies:
1914
  locate-path: 6.0.0
 
1919
  flatted: 3.3.1
1920
  keyv: 4.5.4
1921
 
1922
1923
+
1924
1925
 
1926
 
1975
 
1976
1977
 
1978
1979
+
1980
1981
 
1982
 
1998
  dependencies:
1999
  p-locate: 5.0.0
2000
 
2001
2002
+
2003
2004
 
2005
2006
+
2007
2008
  dependencies:
2009
  js-tokens: 4.0.0
 
2052
  dependencies:
2053
  p-limit: 3.1.0
2054
 
2055
2056
+ dependencies:
2057
+ repeat-string: 1.6.1
2058
+
2059
2060
  dependencies:
2061
  callsites: 3.1.0
 
2092
  dependencies:
2093
  loose-envify: 1.4.0
2094
 
2095
2096
+
2097
2098
 
2099
 
2140
 
2141
2142
 
2143
2144
+
2145
2146
 
2147
 
2152
  dependencies:
2153
  has-flag: 4.0.0
2154
 
2155
2156
+ dependencies:
2157
+ '@75lb/deep-merge': 1.1.2
2158
+ array-back: 6.2.2
2159
+ command-line-args: 5.2.1
2160
+ command-line-usage: 7.0.1
2161
+ stream-read-all: 3.0.1
2162
+ typical: 7.2.0
2163
+ wordwrapjs: 5.1.0
2164
+
2165
2166
 
2167
 
2174
  dependencies:
2175
  typescript: 5.6.2
2176
 
2177
2178
+
2179
2180
  dependencies:
2181
  prelude-ls: 1.2.1
 
2193
 
2194
2195
 
2196
2197
+
2198
2199
+
2200
2201
  dependencies:
2202
  browserslist: 4.24.0
 
2207
  dependencies:
2208
  punycode: 2.3.1
2209
 
2210
2211
  dependencies:
2212
  esbuild: 0.21.5
2213
  postcss: 8.4.47
2214
  rollup: 4.24.0
2215
  optionalDependencies:
2216
+ '@types/node': 20.3.0
2217
  fsevents: 2.3.3
2218
 
2219
 
2222
 
2223
2224
 
2225
2226
+
2227
2228
 
2229
src/App.tsx CHANGED
@@ -1,35 +1,150 @@
1
- import { useState } from 'react'
2
- import reactLogo from './assets/react.svg'
3
- import viteLogo from '/vite.svg'
4
- import './App.css'
 
 
 
 
 
 
 
 
 
 
 
 
5
 
6
  function App() {
7
- const [count, setCount] = useState(0)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8
 
9
  return (
10
  <>
11
- <div>
12
- <a href="https://vitejs.dev" target="_blank">
13
- <img src={viteLogo} className="logo" alt="Vite logo" />
14
- </a>
15
- <a href="https://react.dev" target="_blank">
16
- <img src={reactLogo} className="logo react" alt="React logo" />
17
- </a>
18
- </div>
19
- <h1>Vite + React</h1>
20
- <div className="card">
21
- <button onClick={() => setCount((count) => count + 1)}>
22
- count is {count}
 
 
 
 
 
 
 
 
23
  </button>
24
- <p>
25
- Edit <code>src/App.tsx</code> and save to test HMR
26
- </p>
 
 
 
 
 
 
 
 
 
 
 
 
 
27
  </div>
28
- <p className="read-the-docs">
29
- Click on the Vite and React logos to learn more
30
- </p>
31
  </>
32
- )
33
  }
34
 
35
- export default App
 
1
+ import { useEffect, useState } from "react";
2
+ import "./App.css";
3
+ import { createDb } from "./duck";
4
+ import { Table } from "./table";
5
+ import { AsyncDuckDBConnection } from "@duckdb/duckdb-wasm";
6
+
7
+ const DEFAULT_DATASET_URL =
8
+ "https://huggingface.co/datasets/openai/openai_humaneval/resolve/main/openai_humaneval/test-00000-of-00001.parquet";
9
+
10
+ // https://duckdb.org/docs/api/wasm/query#arrow-table-to-json
11
+ // TODO: import the arrow lib and use the correct type
12
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
13
+ const arrowResultToJson = (arrowResult: any) => {
14
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
15
+ return arrowResult.toArray().map((row: any) => row.toJSON());
16
+ };
17
 
18
  function App() {
19
+ const [loading, setLoading] = useState(false);
20
+ const [datasetUrl, setDatasetUrl] = useState("");
21
+ const [textField, setTextField] = useState("");
22
+ const [db, setDb] = useState<Awaited<ReturnType<typeof createDb>> | null>(
23
+ null
24
+ );
25
+ const [dataset, setDataset] = useState<null>(null);
26
+ const [error, setError] = useState<string | null>(null);
27
+ useEffect(() => {
28
+ const status = {
29
+ killed: false,
30
+ };
31
+ const initDb = async () => {
32
+ const db = await createDb();
33
+ if (status.killed) {
34
+ db.terminate();
35
+ return;
36
+ }
37
+ setDb(db);
38
+ };
39
+ initDb();
40
+
41
+ return () => {
42
+ status.killed = true;
43
+ setDb((db) => {
44
+ if (db) {
45
+ db.terminate();
46
+ }
47
+ return null;
48
+ });
49
+ };
50
+ }, []);
51
+
52
+ useEffect(() => {
53
+ if (db && datasetUrl) {
54
+ setLoading(true);
55
+ setDataset(null);
56
+ setError(null);
57
+ console.log("Loading", datasetUrl);
58
+ const status: { conn: AsyncDuckDBConnection | null; killed: boolean } = {
59
+ conn: null,
60
+ killed: false,
61
+ };
62
+ db.connect().then((conn) => {
63
+ if (status.killed) {
64
+ conn.close();
65
+ return;
66
+ }
67
+ status.conn = conn;
68
+ conn
69
+ // we get httpfs for free with cors restrictions
70
+ // we get parquet downloaded as we load it
71
+ // https://duckdb.org/docs/api/wasm/extensions
72
+ // https://duckdb.org/docs/api/wasm/data_ingestion#parquet
73
+ .query(
74
+ `LOAD parquet;LOAD httpfs;SELECT * FROM '${datasetUrl}' LIMIT 10`
75
+ )
76
+ .then((result) => setDataset(arrowResultToJson(result)))
77
+ .catch((err) => {
78
+ console.error(err);
79
+ setError(err.message);
80
+ setDataset(null);
81
+ })
82
+ .finally(() => {
83
+ conn.close();
84
+ setLoading(false);
85
+ });
86
+ });
87
+
88
+ return () => {
89
+ status.killed = true;
90
+ if (status.conn) {
91
+ console.log("Closing connection");
92
+ status.conn.close();
93
+ }
94
+ };
95
+ } else if (db) {
96
+ console.log("Resetting db");
97
+ db.reset();
98
+ }
99
+ }, [db, datasetUrl]);
100
+
101
+ const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
102
+ e.preventDefault();
103
+ setDatasetUrl(textField);
104
+ };
105
 
106
  return (
107
  <>
108
+ <h1>Quack</h1>
109
+ <h2>Enter a hugging face dataset url</h2>
110
+ <form onSubmit={handleSubmit}>
111
+ <input
112
+ type="text"
113
+ name="textField"
114
+ onChange={(e) => setTextField(e.target.value)}
115
+ value={textField}
116
+ />
117
+ <button type="submit" disabled={!textField || textField === datasetUrl}>
118
+ Load
119
+ </button>
120
+ <button
121
+ type="button"
122
+ onClick={() => {
123
+ setTextField(DEFAULT_DATASET_URL);
124
+ setDatasetUrl(DEFAULT_DATASET_URL);
125
+ }}
126
+ >
127
+ Load Default
128
  </button>
129
+ <button
130
+ type="button"
131
+ onClick={() => {
132
+ setTextField("");
133
+ setDataset(null);
134
+ setDatasetUrl("");
135
+ }}
136
+ >
137
+ Clear
138
+ </button>
139
+ </form>
140
+ <div>
141
+ <h2>Dataset</h2>
142
+ {loading && <p>Loading...</p>}
143
+ {error && <p style={{ color: "red" }}>{error}</p>}
144
+ {dataset && <Table data={dataset} />}
145
  </div>
 
 
 
146
  </>
147
+ );
148
  }
149
 
150
+ export default App;
src/duck.ts ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import * as duckdb from "@duckdb/duckdb-wasm";
2
+ import duckdb_wasm from "@duckdb/duckdb-wasm/dist/duckdb-mvp.wasm?url";
3
+ import mvp_worker from "@duckdb/duckdb-wasm/dist/duckdb-browser-mvp.worker.js?url";
4
+ import duckdb_wasm_eh from "@duckdb/duckdb-wasm/dist/duckdb-eh.wasm?url";
5
+ import eh_worker from "@duckdb/duckdb-wasm/dist/duckdb-browser-eh.worker.js?url";
6
+
7
+ const MANUAL_BUNDLES: duckdb.DuckDBBundles = {
8
+ mvp: {
9
+ mainModule: duckdb_wasm,
10
+ mainWorker: mvp_worker,
11
+ },
12
+ eh: {
13
+ mainModule: duckdb_wasm_eh,
14
+ mainWorker: eh_worker,
15
+ },
16
+ };
17
+
18
+ // https://duckdb.org/docs/api/wasm/instantiation#vite
19
+ export const createDb = async () => {
20
+ // Select a bundle based on browser checks
21
+ const bundle = await duckdb.selectBundle(MANUAL_BUNDLES);
22
+ // Instantiate the asynchronus version of DuckDB-wasm
23
+ const worker = new Worker(bundle.mainWorker!);
24
+ const logger = new duckdb.ConsoleLogger();
25
+ const db = new duckdb.AsyncDuckDB(logger, worker);
26
+ await db.instantiate(bundle.mainModule, bundle.pthreadWorker);
27
+ return db;
28
+ };
29
+
30
+ export type DuckDB = typeof duckdb;
src/table.tsx ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import React, { useMemo } from "react";
2
+
3
+ interface TableProps {
4
+ data: Record<string, unknown>[];
5
+ }
6
+
7
+ export const Table: React.FC<TableProps> = ({ data }) => {
8
+ const headers = useMemo(() => Object.keys(data[0]), [data]);
9
+
10
+ if (data.length === 0) return null;
11
+
12
+ return (
13
+ <table>
14
+ <thead>
15
+ <tr>
16
+ {headers.map((header) => (
17
+ <th key={header}>{header}</th>
18
+ ))}
19
+ </tr>
20
+ </thead>
21
+ <tbody>
22
+ {data.map((row, rowIndex) => (
23
+ <tr key={rowIndex}>
24
+ {headers.map((header) => (
25
+ <td key={`${rowIndex}-${header}`}>{String(row[header])}</td>
26
+ ))}
27
+ </tr>
28
+ ))}
29
+ </tbody>
30
+ </table>
31
+ );
32
+ };