@loaders.gl/parquet 4.5.3 → 5.0.0-alpha.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (790) hide show
  1. package/LICENSE +14 -3
  2. package/dist/bundled.d.ts +9 -0
  3. package/dist/bundled.d.ts.map +1 -0
  4. package/dist/bundled.js +10 -0
  5. package/dist/bundled.js.map +1 -0
  6. package/dist/delta-format.d.ts +9 -0
  7. package/dist/delta-format.d.ts.map +1 -0
  8. package/dist/delta-format.js +12 -0
  9. package/dist/delta-format.js.map +1 -0
  10. package/dist/delta-source-loader-types.d.ts +27 -0
  11. package/dist/delta-source-loader-types.d.ts.map +1 -0
  12. package/dist/delta-source-loader-types.js +28 -0
  13. package/dist/delta-source-loader-types.js.map +1 -0
  14. package/dist/delta-source.d.ts +48 -0
  15. package/dist/delta-source.d.ts.map +1 -0
  16. package/dist/delta-source.js +222 -0
  17. package/dist/delta-source.js.map +1 -0
  18. package/dist/delta-types.d.ts +38 -0
  19. package/dist/delta-types.d.ts.map +1 -0
  20. package/dist/delta-types.js +5 -0
  21. package/dist/delta-types.js.map +1 -0
  22. package/dist/geoparquet-loader-with-parser.d.ts +33 -0
  23. package/dist/geoparquet-loader-with-parser.d.ts.map +1 -0
  24. package/dist/geoparquet-loader-with-parser.js +52 -0
  25. package/dist/geoparquet-loader-with-parser.js.map +1 -0
  26. package/dist/geoparquet-loader.d.ts +59 -0
  27. package/dist/geoparquet-loader.d.ts.map +1 -0
  28. package/dist/geoparquet-loader.js +30 -0
  29. package/dist/geoparquet-loader.js.map +1 -0
  30. package/dist/iceberg-rest-catalog.d.ts +49 -0
  31. package/dist/iceberg-rest-catalog.d.ts.map +1 -0
  32. package/dist/iceberg-rest-catalog.js +78 -0
  33. package/dist/iceberg-rest-catalog.js.map +1 -0
  34. package/dist/iceberg-table-source.d.ts +63 -0
  35. package/dist/iceberg-table-source.d.ts.map +1 -0
  36. package/dist/iceberg-table-source.js +797 -0
  37. package/dist/iceberg-table-source.js.map +1 -0
  38. package/dist/iceberg-types.d.ts +150 -0
  39. package/dist/iceberg-types.d.ts.map +1 -0
  40. package/dist/iceberg-types.js +5 -0
  41. package/dist/iceberg-types.js.map +1 -0
  42. package/dist/index.cjs +41568 -6781
  43. package/dist/index.cjs.map +3 -4
  44. package/dist/index.d.ts +15 -9
  45. package/dist/index.d.ts.map +1 -1
  46. package/dist/index.js +11 -12
  47. package/dist/index.js.map +1 -1
  48. package/dist/lib/arrow/convert-columns-to-row-group.js +3 -0
  49. package/dist/lib/arrow/convert-columns-to-row-group.js.map +1 -1
  50. package/dist/lib/arrow/convert-schema-from-parquet.d.ts +3 -1
  51. package/dist/lib/arrow/convert-schema-from-parquet.d.ts.map +1 -1
  52. package/dist/lib/arrow/convert-schema-from-parquet.js +164 -29
  53. package/dist/lib/arrow/convert-schema-from-parquet.js.map +1 -1
  54. package/dist/lib/arrow/convert-schema-to-parquet.d.ts.map +1 -1
  55. package/dist/lib/arrow/convert-schema-to-parquet.js +16 -7
  56. package/dist/lib/arrow/convert-schema-to-parquet.js.map +1 -1
  57. package/dist/lib/arrow/create-nested-arrow-vector.d.ts +8 -0
  58. package/dist/lib/arrow/create-nested-arrow-vector.d.ts.map +1 -0
  59. package/dist/lib/arrow/create-nested-arrow-vector.js +485 -0
  60. package/dist/lib/arrow/create-nested-arrow-vector.js.map +1 -0
  61. package/dist/lib/constants.d.ts +0 -1
  62. package/dist/lib/constants.d.ts.map +1 -1
  63. package/dist/lib/constants.js +1 -2
  64. package/dist/lib/constants.js.map +1 -1
  65. package/dist/lib/encoders/encode-arrow-to-parquet.d.ts +2 -2
  66. package/dist/lib/encoders/encode-arrow-to-parquet.d.ts.map +1 -1
  67. package/dist/lib/encoders/encode-arrow-to-parquet.js +3 -10
  68. package/dist/lib/encoders/encode-arrow-to-parquet.js.map +1 -1
  69. package/dist/lib/encoders/encode-table-to-parquet-js.d.ts +5 -0
  70. package/dist/lib/encoders/encode-table-to-parquet-js.d.ts.map +1 -0
  71. package/dist/lib/encoders/encode-table-to-parquet-js.js +394 -0
  72. package/dist/lib/encoders/encode-table-to-parquet-js.js.map +1 -0
  73. package/dist/lib/geo/geoparquet-covering.d.ts +19 -0
  74. package/dist/lib/geo/geoparquet-covering.d.ts.map +1 -0
  75. package/dist/lib/geo/geoparquet-covering.js +137 -0
  76. package/dist/lib/geo/geoparquet-covering.js.map +1 -0
  77. package/dist/lib/geo/geospatial-metadata.d.ts +67 -0
  78. package/dist/lib/geo/geospatial-metadata.d.ts.map +1 -0
  79. package/dist/lib/geo/geospatial-metadata.js +412 -0
  80. package/dist/lib/geo/geospatial-metadata.js.map +1 -0
  81. package/dist/lib/parquet-bloom-filter-planner.d.ts +16 -0
  82. package/dist/lib/parquet-bloom-filter-planner.d.ts.map +1 -0
  83. package/dist/lib/parquet-bloom-filter-planner.js +57 -0
  84. package/dist/lib/parquet-bloom-filter-planner.js.map +1 -0
  85. package/dist/lib/parquet-bloom-filter.d.ts +30 -0
  86. package/dist/lib/parquet-bloom-filter.d.ts.map +1 -0
  87. package/dist/lib/parquet-bloom-filter.js +289 -0
  88. package/dist/lib/parquet-bloom-filter.js.map +1 -0
  89. package/dist/lib/parquet-encryption.d.ts +80 -0
  90. package/dist/lib/parquet-encryption.d.ts.map +1 -0
  91. package/dist/lib/parquet-encryption.js +190 -0
  92. package/dist/lib/parquet-encryption.js.map +1 -0
  93. package/dist/lib/parquet-page-index.d.ts +91 -0
  94. package/dist/lib/parquet-page-index.d.ts.map +1 -0
  95. package/dist/lib/parquet-page-index.js +463 -0
  96. package/dist/lib/parquet-page-index.js.map +1 -0
  97. package/dist/lib/parquet-predicate.d.ts +21 -0
  98. package/dist/lib/parquet-predicate.d.ts.map +1 -0
  99. package/dist/lib/parquet-predicate.js +328 -0
  100. package/dist/lib/parquet-predicate.js.map +1 -0
  101. package/dist/lib/parquet-source-worker-client.d.ts +6 -0
  102. package/dist/lib/parquet-source-worker-client.d.ts.map +1 -0
  103. package/dist/lib/parquet-source-worker-client.js +24 -0
  104. package/dist/lib/parquet-source-worker-client.js.map +1 -0
  105. package/dist/lib/parquet-source-worker-decoder.d.ts +7 -0
  106. package/dist/lib/parquet-source-worker-decoder.d.ts.map +1 -0
  107. package/dist/lib/parquet-source-worker-decoder.js +181 -0
  108. package/dist/lib/parquet-source-worker-decoder.js.map +1 -0
  109. package/dist/lib/parquet-source-worker-file.d.ts +24 -0
  110. package/dist/lib/parquet-source-worker-file.d.ts.map +1 -0
  111. package/dist/lib/parquet-source-worker-file.js +40 -0
  112. package/dist/lib/parquet-source-worker-file.js.map +1 -0
  113. package/dist/lib/parquet-source-worker-types.d.ts +121 -0
  114. package/dist/lib/parquet-source-worker-types.d.ts.map +1 -0
  115. package/dist/lib/parquet-source-worker-types.js +5 -0
  116. package/dist/lib/parquet-source-worker-types.js.map +1 -0
  117. package/dist/lib/parquet-worker-transport.d.ts +8 -0
  118. package/dist/lib/parquet-worker-transport.d.ts.map +1 -0
  119. package/dist/lib/parquet-worker-transport.js +40 -0
  120. package/dist/lib/parquet-worker-transport.js.map +1 -0
  121. package/dist/lib/parsers/convert-parquet-tables.d.ts +16 -0
  122. package/dist/lib/parsers/convert-parquet-tables.d.ts.map +1 -0
  123. package/dist/lib/parsers/convert-parquet-tables.js +30 -0
  124. package/dist/lib/parsers/convert-parquet-tables.js.map +1 -0
  125. package/dist/lib/parsers/get-parquet-schema.d.ts.map +1 -1
  126. package/dist/lib/parsers/get-parquet-schema.js +6 -2
  127. package/dist/lib/parsers/get-parquet-schema.js.map +1 -1
  128. package/dist/lib/parsers/parse-geoparquet-to-geojson.d.ts +4 -4
  129. package/dist/lib/parsers/parse-geoparquet-to-geojson.d.ts.map +1 -1
  130. package/dist/lib/parsers/parse-geoparquet-to-geojson.js +19 -6
  131. package/dist/lib/parsers/parse-geoparquet-to-geojson.js.map +1 -1
  132. package/dist/lib/parsers/parse-parquet-tables.d.ts +37 -0
  133. package/dist/lib/parsers/parse-parquet-tables.d.ts.map +1 -0
  134. package/dist/lib/parsers/parse-parquet-tables.js +50 -0
  135. package/dist/lib/parsers/parse-parquet-tables.js.map +1 -0
  136. package/dist/lib/parsers/parse-parquet-to-arrow-js.d.ts +19 -0
  137. package/dist/lib/parsers/parse-parquet-to-arrow-js.d.ts.map +1 -0
  138. package/dist/lib/parsers/parse-parquet-to-arrow-js.js +921 -0
  139. package/dist/lib/parsers/parse-parquet-to-arrow-js.js.map +1 -0
  140. package/dist/lib/parsers/parse-parquet-to-arrow.d.ts +7 -7
  141. package/dist/lib/parsers/parse-parquet-to-arrow.d.ts.map +1 -1
  142. package/dist/lib/parsers/parse-parquet-to-arrow.js +45 -32
  143. package/dist/lib/parsers/parse-parquet-to-arrow.js.map +1 -1
  144. package/dist/lib/parsers/parse-parquet-to-columns.d.ts +3 -3
  145. package/dist/lib/parsers/parse-parquet-to-columns.d.ts.map +1 -1
  146. package/dist/lib/parsers/parse-parquet-to-columns.js +4 -5
  147. package/dist/lib/parsers/parse-parquet-to-columns.js.map +1 -1
  148. package/dist/lib/parsers/parse-parquet-to-json.d.ts +3 -3
  149. package/dist/lib/parsers/parse-parquet-to-json.d.ts.map +1 -1
  150. package/dist/lib/parsers/parse-parquet-to-json.js +95 -28
  151. package/dist/lib/parsers/parse-parquet-to-json.js.map +1 -1
  152. package/dist/lib/slice-parquet-batch.d.ts +9 -0
  153. package/dist/lib/slice-parquet-batch.d.ts.map +1 -0
  154. package/dist/lib/slice-parquet-batch.js +28 -0
  155. package/dist/lib/slice-parquet-batch.js.map +1 -0
  156. package/dist/lib/sources/parquet-range-file.d.ts +80 -0
  157. package/dist/lib/sources/parquet-range-file.d.ts.map +1 -0
  158. package/dist/lib/sources/parquet-range-file.js +267 -0
  159. package/dist/lib/sources/parquet-range-file.js.map +1 -0
  160. package/dist/lib/sources/single-batch-queue.d.ts +24 -0
  161. package/dist/lib/sources/single-batch-queue.d.ts.map +1 -0
  162. package/dist/lib/sources/single-batch-queue.js +91 -0
  163. package/dist/lib/sources/single-batch-queue.js.map +1 -0
  164. package/dist/lib/utils/load-wasm-node.d.ts +3 -0
  165. package/dist/lib/utils/load-wasm-node.d.ts.map +1 -0
  166. package/dist/lib/utils/load-wasm-node.js +23 -0
  167. package/dist/lib/utils/load-wasm-node.js.map +1 -0
  168. package/dist/lib/utils/load-wasm.d.ts +2 -2
  169. package/dist/lib/utils/load-wasm.d.ts.map +1 -1
  170. package/dist/lib/utils/load-wasm.js +28 -12
  171. package/dist/lib/utils/load-wasm.js.map +1 -1
  172. package/dist/lib/utils/make-stream-iterator.d.ts +2 -0
  173. package/dist/lib/utils/make-stream-iterator.d.ts.map +1 -1
  174. package/dist/lib/utils/make-stream-iterator.js +123 -14
  175. package/dist/lib/utils/make-stream-iterator.js.map +1 -1
  176. package/dist/lib/utils/normalize-parquet-options.d.ts +5 -0
  177. package/dist/lib/utils/normalize-parquet-options.d.ts.map +1 -0
  178. package/dist/lib/utils/normalize-parquet-options.js +25 -0
  179. package/dist/lib/utils/normalize-parquet-options.js.map +1 -0
  180. package/dist/parquet-dataset-source.cjs +38974 -0
  181. package/dist/parquet-dataset-source.cjs.map +6 -0
  182. package/dist/parquet-dataset-source.d.ts +81 -0
  183. package/dist/parquet-dataset-source.d.ts.map +1 -0
  184. package/dist/parquet-dataset-source.js +602 -0
  185. package/dist/parquet-dataset-source.js.map +1 -0
  186. package/dist/parquet-encoded-page-types.d.ts +108 -0
  187. package/dist/parquet-encoded-page-types.d.ts.map +1 -0
  188. package/dist/parquet-encoded-page-types.js +5 -0
  189. package/dist/parquet-encoded-page-types.js.map +1 -0
  190. package/dist/parquet-format.d.ts +2 -0
  191. package/dist/parquet-format.d.ts.map +1 -1
  192. package/dist/parquet-format.js +2 -0
  193. package/dist/parquet-format.js.map +1 -1
  194. package/dist/parquet-js-loader-types.d.ts +59 -0
  195. package/dist/parquet-js-loader-types.d.ts.map +1 -0
  196. package/dist/parquet-js-loader-types.js +34 -0
  197. package/dist/parquet-js-loader-types.js.map +1 -0
  198. package/dist/parquet-js-loader.d.ts +18 -22
  199. package/dist/parquet-js-loader.d.ts.map +1 -1
  200. package/dist/parquet-js-loader.js +53 -14
  201. package/dist/parquet-js-loader.js.map +1 -1
  202. package/dist/parquet-js-writer.d.ts +65 -0
  203. package/dist/parquet-js-writer.d.ts.map +1 -0
  204. package/dist/parquet-js-writer.js +28 -0
  205. package/dist/parquet-js-writer.js.map +1 -0
  206. package/dist/parquet-loader-base.d.ts +25 -0
  207. package/dist/parquet-loader-base.d.ts.map +1 -0
  208. package/dist/parquet-loader-base.js +23 -0
  209. package/dist/parquet-loader-base.js.map +1 -0
  210. package/dist/parquet-loader-options.d.ts +55 -0
  211. package/dist/parquet-loader-options.d.ts.map +1 -0
  212. package/dist/parquet-loader-options.js +10 -0
  213. package/dist/parquet-loader-options.js.map +1 -0
  214. package/dist/parquet-loader-types.d.ts +61 -0
  215. package/dist/parquet-loader-types.d.ts.map +1 -0
  216. package/dist/parquet-loader-types.js +17 -0
  217. package/dist/parquet-loader-types.js.map +1 -0
  218. package/dist/parquet-loader.d.ts +42 -0
  219. package/dist/parquet-loader.d.ts.map +1 -0
  220. package/dist/parquet-loader.js +68 -0
  221. package/dist/parquet-loader.js.map +1 -0
  222. package/dist/parquet-source-capabilities.d.ts +43 -0
  223. package/dist/parquet-source-capabilities.d.ts.map +1 -0
  224. package/dist/parquet-source-capabilities.js +32 -0
  225. package/dist/parquet-source-capabilities.js.map +1 -0
  226. package/dist/parquet-source-loader-types.d.ts +82 -0
  227. package/dist/parquet-source-loader-types.d.ts.map +1 -0
  228. package/dist/parquet-source-loader-types.js +84 -0
  229. package/dist/parquet-source-loader-types.js.map +1 -0
  230. package/dist/parquet-source-loader.cjs +38261 -0
  231. package/dist/parquet-source-loader.cjs.map +6 -0
  232. package/dist/parquet-source-loader.d.ts +167 -0
  233. package/dist/parquet-source-loader.d.ts.map +1 -0
  234. package/dist/parquet-source-loader.js +1438 -0
  235. package/dist/parquet-source-loader.js.map +1 -0
  236. package/dist/parquet-source-types.d.ts +534 -0
  237. package/dist/parquet-source-types.d.ts.map +1 -0
  238. package/dist/parquet-source-types.js +5 -0
  239. package/dist/parquet-source-types.js.map +1 -0
  240. package/dist/parquet-source-worker-factory.d.ts +4 -0
  241. package/dist/parquet-source-worker-factory.d.ts.map +1 -0
  242. package/dist/parquet-source-worker-factory.js +6 -0
  243. package/dist/parquet-source-worker-factory.js.map +1 -0
  244. package/dist/parquet-source-worker-url.d.ts +3 -0
  245. package/dist/parquet-source-worker-url.d.ts.map +1 -0
  246. package/dist/parquet-source-worker-url.js +22 -0
  247. package/dist/parquet-source-worker-url.js.map +1 -0
  248. package/dist/parquet-source-worker.js +38871 -0
  249. package/dist/parquet-source-worker.js.map +7 -0
  250. package/dist/parquet-worker-node.cjs +78507 -0
  251. package/dist/parquet-worker-node.cjs.map +7 -0
  252. package/dist/parquet-worker-url.d.ts +3 -0
  253. package/dist/parquet-worker-url.d.ts.map +1 -0
  254. package/dist/parquet-worker-url.js +19 -0
  255. package/dist/parquet-worker-url.js.map +1 -0
  256. package/dist/parquet-worker.js +20094 -0
  257. package/dist/parquet-worker.js.map +7 -0
  258. package/dist/parquet-writer.d.ts +10 -0
  259. package/dist/parquet-writer.d.ts.map +1 -0
  260. package/dist/parquet-writer.js +27 -0
  261. package/dist/parquet-writer.js.map +1 -0
  262. package/dist/parquet_wasm_bg.wasm +0 -0
  263. package/dist/parquetjs/codecs/byte-stream-split.d.ts +9 -0
  264. package/dist/parquetjs/codecs/byte-stream-split.d.ts.map +1 -0
  265. package/dist/parquetjs/codecs/byte-stream-split.js +159 -0
  266. package/dist/parquetjs/codecs/byte-stream-split.js.map +1 -0
  267. package/dist/parquetjs/codecs/declare.d.ts +35 -3
  268. package/dist/parquetjs/codecs/declare.d.ts.map +1 -1
  269. package/dist/parquetjs/codecs/declare.js +17 -1
  270. package/dist/parquetjs/codecs/declare.js.map +1 -1
  271. package/dist/parquetjs/codecs/delta.d.ts +17 -0
  272. package/dist/parquetjs/codecs/delta.d.ts.map +1 -0
  273. package/dist/parquetjs/codecs/delta.js +788 -0
  274. package/dist/parquetjs/codecs/delta.js.map +1 -0
  275. package/dist/parquetjs/codecs/dictionary.d.ts +5 -2
  276. package/dist/parquetjs/codecs/dictionary.d.ts.map +1 -1
  277. package/dist/parquetjs/codecs/dictionary.js +16 -4
  278. package/dist/parquetjs/codecs/dictionary.js.map +1 -1
  279. package/dist/parquetjs/codecs/index.d.ts.map +1 -1
  280. package/dist/parquetjs/codecs/index.js +22 -0
  281. package/dist/parquetjs/codecs/index.js.map +1 -1
  282. package/dist/parquetjs/codecs/plain.d.ts +3 -3
  283. package/dist/parquetjs/codecs/plain.d.ts.map +1 -1
  284. package/dist/parquetjs/codecs/plain.js +231 -78
  285. package/dist/parquetjs/codecs/plain.js.map +1 -1
  286. package/dist/parquetjs/codecs/rle.d.ts +7 -3
  287. package/dist/parquetjs/codecs/rle.d.ts.map +1 -1
  288. package/dist/parquetjs/codecs/rle.js +613 -69
  289. package/dist/parquetjs/codecs/rle.js.map +1 -1
  290. package/dist/parquetjs/compression.d.ts +16 -8
  291. package/dist/parquetjs/compression.d.ts.map +1 -1
  292. package/dist/parquetjs/compression.js +114 -141
  293. package/dist/parquetjs/compression.js.map +1 -1
  294. package/dist/parquetjs/encoder/dictionary-planner.d.ts +17 -0
  295. package/dist/parquetjs/encoder/dictionary-planner.d.ts.map +1 -0
  296. package/dist/parquetjs/encoder/dictionary-planner.js +67 -0
  297. package/dist/parquetjs/encoder/dictionary-planner.js.map +1 -0
  298. package/dist/parquetjs/encoder/page-planner.d.ts +11 -0
  299. package/dist/parquetjs/encoder/page-planner.d.ts.map +1 -0
  300. package/dist/parquetjs/encoder/page-planner.js +60 -0
  301. package/dist/parquetjs/encoder/page-planner.js.map +1 -0
  302. package/dist/parquetjs/encoder/parquet-encoder.d.ts +54 -5
  303. package/dist/parquetjs/encoder/parquet-encoder.d.ts.map +1 -1
  304. package/dist/parquetjs/encoder/parquet-encoder.js +930 -66
  305. package/dist/parquetjs/encoder/parquet-encoder.js.map +1 -1
  306. package/dist/parquetjs/parquet-thrift/BoundingBox.d.ts +29 -0
  307. package/dist/parquetjs/parquet-thrift/BoundingBox.d.ts.map +1 -0
  308. package/dist/parquetjs/parquet-thrift/BoundingBox.js +85 -0
  309. package/dist/parquetjs/parquet-thrift/BoundingBox.js.map +1 -0
  310. package/dist/parquetjs/parquet-thrift/BsonType.d.ts +1 -1
  311. package/dist/parquetjs/parquet-thrift/BsonType.d.ts.map +1 -1
  312. package/dist/parquetjs/parquet-thrift/BsonType.js +1 -1
  313. package/dist/parquetjs/parquet-thrift/BsonType.js.map +1 -1
  314. package/dist/parquetjs/parquet-thrift/ColumnChunk.d.ts +7 -2
  315. package/dist/parquetjs/parquet-thrift/ColumnChunk.d.ts.map +1 -1
  316. package/dist/parquetjs/parquet-thrift/ColumnChunk.js +37 -2
  317. package/dist/parquetjs/parquet-thrift/ColumnChunk.js.map +1 -1
  318. package/dist/parquetjs/parquet-thrift/ColumnCryptoMetaData.d.ts +35 -0
  319. package/dist/parquetjs/parquet-thrift/ColumnCryptoMetaData.d.ts.map +1 -0
  320. package/dist/parquetjs/parquet-thrift/ColumnCryptoMetaData.js +135 -0
  321. package/dist/parquetjs/parquet-thrift/ColumnCryptoMetaData.js.map +1 -0
  322. package/dist/parquetjs/parquet-thrift/ColumnIndex.d.ts +6 -6
  323. package/dist/parquetjs/parquet-thrift/ColumnIndex.d.ts.map +1 -1
  324. package/dist/parquetjs/parquet-thrift/ColumnIndex.js +3 -3
  325. package/dist/parquetjs/parquet-thrift/ColumnIndex.js.map +1 -1
  326. package/dist/parquetjs/parquet-thrift/ColumnMetaData.d.ts +12 -2
  327. package/dist/parquetjs/parquet-thrift/ColumnMetaData.d.ts.map +1 -1
  328. package/dist/parquetjs/parquet-thrift/ColumnMetaData.js +75 -2
  329. package/dist/parquetjs/parquet-thrift/ColumnMetaData.js.map +1 -1
  330. package/dist/parquetjs/parquet-thrift/ColumnOrder.d.ts +1 -1
  331. package/dist/parquetjs/parquet-thrift/ColumnOrder.d.ts.map +1 -1
  332. package/dist/parquetjs/parquet-thrift/ColumnOrder.js +1 -1
  333. package/dist/parquetjs/parquet-thrift/ColumnOrder.js.map +1 -1
  334. package/dist/parquetjs/parquet-thrift/DataPageHeader.d.ts +1 -1
  335. package/dist/parquetjs/parquet-thrift/DataPageHeader.d.ts.map +1 -1
  336. package/dist/parquetjs/parquet-thrift/DataPageHeader.js +1 -1
  337. package/dist/parquetjs/parquet-thrift/DataPageHeader.js.map +1 -1
  338. package/dist/parquetjs/parquet-thrift/DataPageHeaderV2.d.ts +1 -1
  339. package/dist/parquetjs/parquet-thrift/DataPageHeaderV2.d.ts.map +1 -1
  340. package/dist/parquetjs/parquet-thrift/DataPageHeaderV2.js +1 -1
  341. package/dist/parquetjs/parquet-thrift/DataPageHeaderV2.js.map +1 -1
  342. package/dist/parquetjs/parquet-thrift/DateType.d.ts +1 -1
  343. package/dist/parquetjs/parquet-thrift/DateType.d.ts.map +1 -1
  344. package/dist/parquetjs/parquet-thrift/DateType.js +1 -1
  345. package/dist/parquetjs/parquet-thrift/DateType.js.map +1 -1
  346. package/dist/parquetjs/parquet-thrift/DecimalType.d.ts +1 -1
  347. package/dist/parquetjs/parquet-thrift/DecimalType.d.ts.map +1 -1
  348. package/dist/parquetjs/parquet-thrift/DecimalType.js +1 -1
  349. package/dist/parquetjs/parquet-thrift/DecimalType.js.map +1 -1
  350. package/dist/parquetjs/parquet-thrift/DictionaryPageHeader.d.ts +1 -1
  351. package/dist/parquetjs/parquet-thrift/DictionaryPageHeader.d.ts.map +1 -1
  352. package/dist/parquetjs/parquet-thrift/DictionaryPageHeader.js +1 -1
  353. package/dist/parquetjs/parquet-thrift/DictionaryPageHeader.js.map +1 -1
  354. package/dist/parquetjs/parquet-thrift/EdgeInterpolationAlgorithm.d.ts +8 -0
  355. package/dist/parquetjs/parquet-thrift/EdgeInterpolationAlgorithm.d.ts.map +1 -0
  356. package/dist/parquetjs/parquet-thrift/EdgeInterpolationAlgorithm.js +14 -0
  357. package/dist/parquetjs/parquet-thrift/EdgeInterpolationAlgorithm.js.map +1 -0
  358. package/dist/parquetjs/parquet-thrift/Encoding.d.ts +2 -1
  359. package/dist/parquetjs/parquet-thrift/Encoding.d.ts.map +1 -1
  360. package/dist/parquetjs/parquet-thrift/Encoding.js +1 -0
  361. package/dist/parquetjs/parquet-thrift/Encoding.js.map +1 -1
  362. package/dist/parquetjs/parquet-thrift/EncryptionAlgorithm.d.ts +22 -0
  363. package/dist/parquetjs/parquet-thrift/EncryptionAlgorithm.d.ts.map +1 -0
  364. package/dist/parquetjs/parquet-thrift/EncryptionAlgorithm.js +111 -0
  365. package/dist/parquetjs/parquet-thrift/EncryptionAlgorithm.js.map +1 -0
  366. package/dist/parquetjs/parquet-thrift/EnumType.d.ts +1 -1
  367. package/dist/parquetjs/parquet-thrift/EnumType.d.ts.map +1 -1
  368. package/dist/parquetjs/parquet-thrift/EnumType.js +1 -1
  369. package/dist/parquetjs/parquet-thrift/EnumType.js.map +1 -1
  370. package/dist/parquetjs/parquet-thrift/FileCryptoMetaData.d.ts +16 -0
  371. package/dist/parquetjs/parquet-thrift/FileCryptoMetaData.d.ts.map +1 -0
  372. package/dist/parquetjs/parquet-thrift/FileCryptoMetaData.js +57 -0
  373. package/dist/parquetjs/parquet-thrift/FileCryptoMetaData.js.map +1 -0
  374. package/dist/parquetjs/parquet-thrift/FileMetaData.d.ts +7 -2
  375. package/dist/parquetjs/parquet-thrift/FileMetaData.d.ts.map +1 -1
  376. package/dist/parquetjs/parquet-thrift/FileMetaData.js +37 -2
  377. package/dist/parquetjs/parquet-thrift/FileMetaData.js.map +1 -1
  378. package/dist/parquetjs/parquet-thrift/Float16Type.d.ts +9 -0
  379. package/dist/parquetjs/parquet-thrift/Float16Type.d.ts.map +1 -0
  380. package/dist/parquetjs/parquet-thrift/Float16Type.js +27 -0
  381. package/dist/parquetjs/parquet-thrift/Float16Type.js.map +1 -0
  382. package/dist/parquetjs/parquet-thrift/GeographyType.d.ts +14 -0
  383. package/dist/parquetjs/parquet-thrift/GeographyType.d.ts.map +1 -0
  384. package/dist/parquetjs/parquet-thrift/GeographyType.js +51 -0
  385. package/dist/parquetjs/parquet-thrift/GeographyType.js.map +1 -0
  386. package/dist/parquetjs/parquet-thrift/GeometryType.d.ts +11 -0
  387. package/dist/parquetjs/parquet-thrift/GeometryType.d.ts.map +1 -0
  388. package/dist/parquetjs/parquet-thrift/GeometryType.js +41 -0
  389. package/dist/parquetjs/parquet-thrift/GeometryType.js.map +1 -0
  390. package/dist/parquetjs/parquet-thrift/GeospatialStatistics.d.ts +18 -0
  391. package/dist/parquetjs/parquet-thrift/GeospatialStatistics.d.ts.map +1 -0
  392. package/dist/parquetjs/parquet-thrift/GeospatialStatistics.js +62 -0
  393. package/dist/parquetjs/parquet-thrift/GeospatialStatistics.js.map +1 -0
  394. package/dist/parquetjs/parquet-thrift/IndexPageHeader.d.ts +1 -1
  395. package/dist/parquetjs/parquet-thrift/IndexPageHeader.d.ts.map +1 -1
  396. package/dist/parquetjs/parquet-thrift/IndexPageHeader.js +1 -1
  397. package/dist/parquetjs/parquet-thrift/IndexPageHeader.js.map +1 -1
  398. package/dist/parquetjs/parquet-thrift/IntType.d.ts +1 -1
  399. package/dist/parquetjs/parquet-thrift/IntType.d.ts.map +1 -1
  400. package/dist/parquetjs/parquet-thrift/IntType.js +1 -1
  401. package/dist/parquetjs/parquet-thrift/IntType.js.map +1 -1
  402. package/dist/parquetjs/parquet-thrift/JsonType.d.ts +1 -1
  403. package/dist/parquetjs/parquet-thrift/JsonType.d.ts.map +1 -1
  404. package/dist/parquetjs/parquet-thrift/JsonType.js +1 -1
  405. package/dist/parquetjs/parquet-thrift/JsonType.js.map +1 -1
  406. package/dist/parquetjs/parquet-thrift/KeyValue.d.ts +1 -1
  407. package/dist/parquetjs/parquet-thrift/KeyValue.d.ts.map +1 -1
  408. package/dist/parquetjs/parquet-thrift/KeyValue.js +1 -1
  409. package/dist/parquetjs/parquet-thrift/KeyValue.js.map +1 -1
  410. package/dist/parquetjs/parquet-thrift/ListType.d.ts +1 -1
  411. package/dist/parquetjs/parquet-thrift/ListType.d.ts.map +1 -1
  412. package/dist/parquetjs/parquet-thrift/ListType.js +1 -1
  413. package/dist/parquetjs/parquet-thrift/ListType.js.map +1 -1
  414. package/dist/parquetjs/parquet-thrift/LogicalType.d.ts +17 -1
  415. package/dist/parquetjs/parquet-thrift/LogicalType.d.ts.map +1 -1
  416. package/dist/parquetjs/parquet-thrift/LogicalType.js +97 -1
  417. package/dist/parquetjs/parquet-thrift/LogicalType.js.map +1 -1
  418. package/dist/parquetjs/parquet-thrift/MapType.d.ts +1 -1
  419. package/dist/parquetjs/parquet-thrift/MapType.d.ts.map +1 -1
  420. package/dist/parquetjs/parquet-thrift/MapType.js +1 -1
  421. package/dist/parquetjs/parquet-thrift/MapType.js.map +1 -1
  422. package/dist/parquetjs/parquet-thrift/MicroSeconds.d.ts +1 -1
  423. package/dist/parquetjs/parquet-thrift/MicroSeconds.d.ts.map +1 -1
  424. package/dist/parquetjs/parquet-thrift/MicroSeconds.js +1 -1
  425. package/dist/parquetjs/parquet-thrift/MicroSeconds.js.map +1 -1
  426. package/dist/parquetjs/parquet-thrift/MilliSeconds.d.ts +1 -1
  427. package/dist/parquetjs/parquet-thrift/MilliSeconds.d.ts.map +1 -1
  428. package/dist/parquetjs/parquet-thrift/MilliSeconds.js +1 -1
  429. package/dist/parquetjs/parquet-thrift/MilliSeconds.js.map +1 -1
  430. package/dist/parquetjs/parquet-thrift/NanoSeconds.d.ts +9 -0
  431. package/dist/parquetjs/parquet-thrift/NanoSeconds.d.ts.map +1 -0
  432. package/dist/parquetjs/parquet-thrift/NanoSeconds.js +27 -0
  433. package/dist/parquetjs/parquet-thrift/NanoSeconds.js.map +1 -0
  434. package/dist/parquetjs/parquet-thrift/NullType.d.ts +1 -1
  435. package/dist/parquetjs/parquet-thrift/NullType.d.ts.map +1 -1
  436. package/dist/parquetjs/parquet-thrift/NullType.js +1 -1
  437. package/dist/parquetjs/parquet-thrift/NullType.js.map +1 -1
  438. package/dist/parquetjs/parquet-thrift/OffsetIndex.d.ts +1 -1
  439. package/dist/parquetjs/parquet-thrift/OffsetIndex.d.ts.map +1 -1
  440. package/dist/parquetjs/parquet-thrift/OffsetIndex.js +1 -1
  441. package/dist/parquetjs/parquet-thrift/OffsetIndex.js.map +1 -1
  442. package/dist/parquetjs/parquet-thrift/PageEncodingStats.d.ts +1 -1
  443. package/dist/parquetjs/parquet-thrift/PageEncodingStats.d.ts.map +1 -1
  444. package/dist/parquetjs/parquet-thrift/PageEncodingStats.js +1 -1
  445. package/dist/parquetjs/parquet-thrift/PageEncodingStats.js.map +1 -1
  446. package/dist/parquetjs/parquet-thrift/PageHeader.d.ts +1 -1
  447. package/dist/parquetjs/parquet-thrift/PageHeader.d.ts.map +1 -1
  448. package/dist/parquetjs/parquet-thrift/PageHeader.js +1 -1
  449. package/dist/parquetjs/parquet-thrift/PageHeader.js.map +1 -1
  450. package/dist/parquetjs/parquet-thrift/PageLocation.d.ts +2 -2
  451. package/dist/parquetjs/parquet-thrift/PageLocation.d.ts.map +1 -1
  452. package/dist/parquetjs/parquet-thrift/PageLocation.js +2 -2
  453. package/dist/parquetjs/parquet-thrift/PageLocation.js.map +1 -1
  454. package/dist/parquetjs/parquet-thrift/RowGroup.d.ts +2 -2
  455. package/dist/parquetjs/parquet-thrift/RowGroup.d.ts.map +1 -1
  456. package/dist/parquetjs/parquet-thrift/RowGroup.js +2 -2
  457. package/dist/parquetjs/parquet-thrift/RowGroup.js.map +1 -1
  458. package/dist/parquetjs/parquet-thrift/SchemaElement.d.ts +1 -1
  459. package/dist/parquetjs/parquet-thrift/SchemaElement.d.ts.map +1 -1
  460. package/dist/parquetjs/parquet-thrift/SchemaElement.js +1 -1
  461. package/dist/parquetjs/parquet-thrift/SchemaElement.js.map +1 -1
  462. package/dist/parquetjs/parquet-thrift/SizeStatistics.d.ts +26 -0
  463. package/dist/parquetjs/parquet-thrift/SizeStatistics.d.ts.map +1 -0
  464. package/dist/parquetjs/parquet-thrift/SizeStatistics.js +85 -0
  465. package/dist/parquetjs/parquet-thrift/SizeStatistics.js.map +1 -0
  466. package/dist/parquetjs/parquet-thrift/SortingColumn.d.ts +1 -1
  467. package/dist/parquetjs/parquet-thrift/SortingColumn.d.ts.map +1 -1
  468. package/dist/parquetjs/parquet-thrift/SortingColumn.js +1 -1
  469. package/dist/parquetjs/parquet-thrift/SortingColumn.js.map +1 -1
  470. package/dist/parquetjs/parquet-thrift/Statistics.d.ts +14 -10
  471. package/dist/parquetjs/parquet-thrift/Statistics.d.ts.map +1 -1
  472. package/dist/parquetjs/parquet-thrift/Statistics.js +38 -2
  473. package/dist/parquetjs/parquet-thrift/Statistics.js.map +1 -1
  474. package/dist/parquetjs/parquet-thrift/StringType.d.ts +1 -1
  475. package/dist/parquetjs/parquet-thrift/StringType.d.ts.map +1 -1
  476. package/dist/parquetjs/parquet-thrift/StringType.js +1 -1
  477. package/dist/parquetjs/parquet-thrift/StringType.js.map +1 -1
  478. package/dist/parquetjs/parquet-thrift/TimeType.d.ts +1 -1
  479. package/dist/parquetjs/parquet-thrift/TimeType.d.ts.map +1 -1
  480. package/dist/parquetjs/parquet-thrift/TimeType.js +1 -1
  481. package/dist/parquetjs/parquet-thrift/TimeType.js.map +1 -1
  482. package/dist/parquetjs/parquet-thrift/TimeUnit.d.ts +5 -1
  483. package/dist/parquetjs/parquet-thrift/TimeUnit.d.ts.map +1 -1
  484. package/dist/parquetjs/parquet-thrift/TimeUnit.js +25 -1
  485. package/dist/parquetjs/parquet-thrift/TimeUnit.js.map +1 -1
  486. package/dist/parquetjs/parquet-thrift/TimestampType.d.ts +1 -1
  487. package/dist/parquetjs/parquet-thrift/TimestampType.d.ts.map +1 -1
  488. package/dist/parquetjs/parquet-thrift/TimestampType.js +1 -1
  489. package/dist/parquetjs/parquet-thrift/TimestampType.js.map +1 -1
  490. package/dist/parquetjs/parquet-thrift/TypeDefinedOrder.d.ts +1 -1
  491. package/dist/parquetjs/parquet-thrift/TypeDefinedOrder.d.ts.map +1 -1
  492. package/dist/parquetjs/parquet-thrift/TypeDefinedOrder.js +1 -1
  493. package/dist/parquetjs/parquet-thrift/TypeDefinedOrder.js.map +1 -1
  494. package/dist/parquetjs/parquet-thrift/UUIDType.d.ts +1 -1
  495. package/dist/parquetjs/parquet-thrift/UUIDType.d.ts.map +1 -1
  496. package/dist/parquetjs/parquet-thrift/UUIDType.js +1 -1
  497. package/dist/parquetjs/parquet-thrift/UUIDType.js.map +1 -1
  498. package/dist/parquetjs/parquet-thrift/VariantType.d.ts +11 -0
  499. package/dist/parquetjs/parquet-thrift/VariantType.d.ts.map +1 -0
  500. package/dist/parquetjs/parquet-thrift/VariantType.js +41 -0
  501. package/dist/parquetjs/parquet-thrift/VariantType.js.map +1 -0
  502. package/dist/parquetjs/parquet-thrift/index.d.ts +12 -2
  503. package/dist/parquetjs/parquet-thrift/index.d.ts.map +1 -1
  504. package/dist/parquetjs/parquet-thrift/index.js +12 -2
  505. package/dist/parquetjs/parquet-thrift/index.js.map +1 -1
  506. package/dist/parquetjs/parser/decoders.d.ts +23 -3
  507. package/dist/parquetjs/parser/decoders.d.ts.map +1 -1
  508. package/dist/parquetjs/parser/decoders.js +687 -119
  509. package/dist/parquetjs/parser/decoders.js.map +1 -1
  510. package/dist/parquetjs/parser/encoded-pages.d.ts +24 -0
  511. package/dist/parquetjs/parser/encoded-pages.d.ts.map +1 -0
  512. package/dist/parquetjs/parser/encoded-pages.js +206 -0
  513. package/dist/parquetjs/parser/encoded-pages.js.map +1 -0
  514. package/dist/parquetjs/parser/parquet-reader.d.ts +111 -10
  515. package/dist/parquetjs/parser/parquet-reader.d.ts.map +1 -1
  516. package/dist/parquetjs/parser/parquet-reader.js +836 -69
  517. package/dist/parquetjs/parser/parquet-reader.js.map +1 -1
  518. package/dist/parquetjs/schema/declare.d.ts +83 -10
  519. package/dist/parquetjs/schema/declare.d.ts.map +1 -1
  520. package/dist/parquetjs/schema/declare.js.map +1 -1
  521. package/dist/parquetjs/schema/schema.d.ts +3 -0
  522. package/dist/parquetjs/schema/schema.d.ts.map +1 -1
  523. package/dist/parquetjs/schema/schema.js +31 -3
  524. package/dist/parquetjs/schema/schema.js.map +1 -1
  525. package/dist/parquetjs/schema/shred.d.ts +2 -0
  526. package/dist/parquetjs/schema/shred.d.ts.map +1 -1
  527. package/dist/parquetjs/schema/shred.js +285 -29
  528. package/dist/parquetjs/schema/shred.js.map +1 -1
  529. package/dist/parquetjs/schema/types.d.ts.map +1 -1
  530. package/dist/parquetjs/schema/types.js +290 -71
  531. package/dist/parquetjs/schema/types.js.map +1 -1
  532. package/dist/parquetjs/schema/variant.d.ts +3 -0
  533. package/dist/parquetjs/schema/variant.d.ts.map +1 -0
  534. package/dist/parquetjs/schema/variant.js +248 -0
  535. package/dist/parquetjs/schema/variant.js.map +1 -0
  536. package/dist/parquetjs/utils/binary-utils.d.ts +41 -0
  537. package/dist/parquetjs/utils/binary-utils.d.ts.map +1 -0
  538. package/dist/parquetjs/utils/binary-utils.js +106 -0
  539. package/dist/parquetjs/utils/binary-utils.js.map +1 -0
  540. package/dist/parquetjs/utils/crc32.d.ts +3 -0
  541. package/dist/parquetjs/utils/crc32.d.ts.map +1 -0
  542. package/dist/parquetjs/utils/crc32.js +15 -0
  543. package/dist/parquetjs/utils/crc32.js.map +1 -0
  544. package/dist/parquetjs/utils/file-utils.d.ts +1 -1
  545. package/dist/parquetjs/utils/file-utils.d.ts.map +1 -1
  546. package/dist/parquetjs/utils/file-utils.js +3 -3
  547. package/dist/parquetjs/utils/file-utils.js.map +1 -1
  548. package/dist/parquetjs/utils/read-utils.d.ts +25 -7
  549. package/dist/parquetjs/utils/read-utils.d.ts.map +1 -1
  550. package/dist/parquetjs/utils/read-utils.js +66 -39
  551. package/dist/parquetjs/utils/read-utils.js.map +1 -1
  552. package/dist/parquetjs/utils/thrift-runtime.d.ts +106 -0
  553. package/dist/parquetjs/utils/thrift-runtime.d.ts.map +1 -0
  554. package/dist/parquetjs/utils/thrift-runtime.js +50 -0
  555. package/dist/parquetjs/utils/thrift-runtime.js.map +1 -0
  556. package/dist/parquetjs/utils/uint8-array-compact-protocol-writer.d.ts +78 -0
  557. package/dist/parquetjs/utils/uint8-array-compact-protocol-writer.d.ts.map +1 -0
  558. package/dist/parquetjs/utils/uint8-array-compact-protocol-writer.js +213 -0
  559. package/dist/parquetjs/utils/uint8-array-compact-protocol-writer.js.map +1 -0
  560. package/dist/parquetjs/utils/uint8-array-compact-protocol.d.ts +80 -0
  561. package/dist/parquetjs/utils/uint8-array-compact-protocol.d.ts.map +1 -0
  562. package/dist/parquetjs/utils/uint8-array-compact-protocol.js +276 -0
  563. package/dist/parquetjs/utils/uint8-array-compact-protocol.js.map +1 -0
  564. package/dist/parquetjs/utils/uint8-array-transport.d.ts +25 -0
  565. package/dist/parquetjs/utils/uint8-array-transport.d.ts.map +1 -0
  566. package/dist/parquetjs/utils/uint8-array-transport.js +62 -0
  567. package/dist/parquetjs/utils/uint8-array-transport.js.map +1 -0
  568. package/dist/polyfills/process.d.ts +12 -0
  569. package/dist/polyfills/process.d.ts.map +1 -0
  570. package/dist/polyfills/process.js +17 -0
  571. package/dist/polyfills/process.js.map +1 -0
  572. package/dist/unbundled.d.ts +10 -0
  573. package/dist/unbundled.d.ts.map +1 -0
  574. package/dist/unbundled.js +11 -0
  575. package/dist/unbundled.js.map +1 -0
  576. package/dist/wasm.d.ts +3 -0
  577. package/dist/wasm.d.ts.map +1 -0
  578. package/dist/wasm.js +6 -0
  579. package/dist/wasm.js.map +1 -0
  580. package/dist/workers/parquet-source-worker.d.ts +2 -0
  581. package/dist/workers/parquet-source-worker.d.ts.map +1 -0
  582. package/dist/workers/parquet-source-worker.js +17 -0
  583. package/dist/workers/parquet-source-worker.js.map +1 -0
  584. package/dist/workers/parquet-worker-node.d.ts +2 -0
  585. package/dist/workers/parquet-worker-node.d.ts.map +1 -0
  586. package/dist/workers/parquet-worker-node.js +5 -0
  587. package/dist/workers/parquet-worker-node.js.map +1 -0
  588. package/dist/workers/parquet-worker.d.ts +2 -0
  589. package/dist/workers/parquet-worker.d.ts.map +1 -0
  590. package/dist/workers/parquet-worker.js +27 -0
  591. package/dist/workers/parquet-worker.js.map +1 -0
  592. package/package.json +84 -40
  593. package/src/bundled.ts +43 -0
  594. package/src/delta-format.ts +12 -0
  595. package/src/delta-source-loader-types.ts +40 -0
  596. package/src/delta-source.ts +305 -0
  597. package/src/delta-types.ts +40 -0
  598. package/src/geoparquet-loader-with-parser.ts +95 -0
  599. package/src/geoparquet-loader.ts +54 -0
  600. package/src/iceberg-rest-catalog.ts +122 -0
  601. package/src/iceberg-table-source.ts +1037 -0
  602. package/src/iceberg-types.ts +165 -0
  603. package/src/index.ts +105 -26
  604. package/src/lib/arrow/convert-columns-to-row-group.ts +3 -0
  605. package/src/lib/arrow/convert-schema-from-parquet.ts +193 -32
  606. package/src/lib/arrow/convert-schema-to-parquet.ts +16 -7
  607. package/src/lib/arrow/create-nested-arrow-vector.ts +705 -0
  608. package/src/lib/constants.ts +0 -2
  609. package/src/lib/encoders/encode-arrow-to-parquet.ts +10 -16
  610. package/src/lib/encoders/encode-table-to-parquet-js.ts +526 -0
  611. package/src/lib/geo/geoparquet-covering.ts +201 -0
  612. package/src/lib/geo/geospatial-metadata.ts +547 -0
  613. package/src/lib/parquet-bloom-filter-planner.ts +86 -0
  614. package/src/lib/parquet-bloom-filter.ts +345 -0
  615. package/src/lib/parquet-encryption.ts +344 -0
  616. package/src/lib/parquet-page-index.ts +727 -0
  617. package/src/lib/parquet-predicate.ts +410 -0
  618. package/src/lib/parquet-source-worker-client.ts +41 -0
  619. package/src/lib/parquet-source-worker-decoder.ts +252 -0
  620. package/src/lib/parquet-source-worker-file.ts +56 -0
  621. package/src/lib/parquet-source-worker-types.ts +132 -0
  622. package/src/lib/parquet-worker-transport.ts +57 -0
  623. package/src/lib/parsers/convert-parquet-tables.ts +39 -0
  624. package/src/lib/parsers/get-parquet-schema.ts +6 -2
  625. package/src/lib/parsers/parse-geoparquet-to-geojson.ts +27 -14
  626. package/src/lib/parsers/parse-parquet-tables.ts +82 -0
  627. package/src/lib/parsers/parse-parquet-to-arrow-js.ts +1213 -0
  628. package/src/lib/parsers/parse-parquet-to-arrow.ts +62 -36
  629. package/src/lib/parsers/parse-parquet-to-columns.ts +9 -8
  630. package/src/lib/parsers/parse-parquet-to-json.ts +119 -35
  631. package/src/lib/slice-parquet-batch.ts +32 -0
  632. package/src/lib/sources/parquet-range-file.ts +365 -0
  633. package/src/lib/sources/single-batch-queue.ts +95 -0
  634. package/src/lib/utils/load-wasm-node.ts +25 -0
  635. package/src/lib/utils/load-wasm.ts +36 -13
  636. package/src/lib/utils/make-stream-iterator.ts +126 -14
  637. package/src/lib/utils/normalize-parquet-options.ts +30 -0
  638. package/src/parquet-dataset-source.ts +800 -0
  639. package/src/parquet-encoded-page-types.ts +122 -0
  640. package/src/parquet-format.ts +2 -0
  641. package/src/parquet-js-loader-types.ts +53 -0
  642. package/src/parquet-js-loader.ts +76 -19
  643. package/src/parquet-js-writer.ts +98 -0
  644. package/src/parquet-loader-base.ts +34 -0
  645. package/src/parquet-loader-options.ts +62 -0
  646. package/src/parquet-loader-types.ts +35 -0
  647. package/src/parquet-loader.ts +115 -0
  648. package/src/parquet-source-capabilities.ts +73 -0
  649. package/src/parquet-source-loader-types.ts +97 -0
  650. package/src/parquet-source-loader.ts +2254 -0
  651. package/src/parquet-source-types.ts +627 -0
  652. package/src/parquet-source-worker-factory.ts +8 -0
  653. package/src/parquet-source-worker-url.ts +23 -0
  654. package/src/parquet-worker-url.ts +23 -0
  655. package/src/parquet-writer.ts +42 -0
  656. package/src/parquetjs/LICENSE +23 -1
  657. package/src/parquetjs/codecs/byte-stream-split.ts +221 -0
  658. package/src/parquetjs/codecs/declare.ts +62 -3
  659. package/src/parquetjs/codecs/delta.ts +1047 -0
  660. package/src/parquetjs/codecs/dictionary.ts +22 -4
  661. package/src/parquetjs/codecs/index.ts +22 -0
  662. package/src/parquetjs/codecs/plain.ts +317 -89
  663. package/src/parquetjs/codecs/rle.ts +852 -82
  664. package/src/parquetjs/compression.ts +137 -156
  665. package/src/parquetjs/encoder/dictionary-planner.ts +104 -0
  666. package/src/parquetjs/encoder/page-planner.ts +83 -0
  667. package/src/parquetjs/encoder/parquet-encoder.ts +1374 -95
  668. package/src/parquetjs/parquet-thrift/BoundingBox.ts +108 -0
  669. package/src/parquetjs/parquet-thrift/BsonType.ts +1 -1
  670. package/src/parquetjs/parquet-thrift/ColumnChunk.ts +37 -2
  671. package/src/parquetjs/parquet-thrift/ColumnCryptoMetaData.ts +139 -0
  672. package/src/parquetjs/parquet-thrift/ColumnIndex.ts +13 -13
  673. package/src/parquetjs/parquet-thrift/ColumnMetaData.ts +75 -2
  674. package/src/parquetjs/parquet-thrift/ColumnOrder.ts +1 -1
  675. package/src/parquetjs/parquet-thrift/DataPageHeader.ts +1 -1
  676. package/src/parquetjs/parquet-thrift/DataPageHeaderV2.ts +1 -1
  677. package/src/parquetjs/parquet-thrift/DateType.ts +1 -1
  678. package/src/parquetjs/parquet-thrift/DecimalType.ts +1 -1
  679. package/src/parquetjs/parquet-thrift/DictionaryPageHeader.ts +1 -1
  680. package/src/parquetjs/parquet-thrift/EdgeInterpolationAlgorithm.ts +13 -0
  681. package/src/parquetjs/parquet-thrift/Encoding.ts +2 -1
  682. package/src/parquetjs/parquet-thrift/EncryptionAlgorithm.ts +127 -0
  683. package/src/parquetjs/parquet-thrift/EnumType.ts +1 -1
  684. package/src/parquetjs/parquet-thrift/FileCryptoMetaData.ts +60 -0
  685. package/src/parquetjs/parquet-thrift/FileMetaData.ts +37 -2
  686. package/src/parquetjs/parquet-thrift/Float16Type.ts +28 -0
  687. package/src/parquetjs/parquet-thrift/GeographyType.ts +54 -0
  688. package/src/parquetjs/parquet-thrift/GeometryType.ts +43 -0
  689. package/src/parquetjs/parquet-thrift/GeospatialStatistics.ts +68 -0
  690. package/src/parquetjs/parquet-thrift/IndexPageHeader.ts +1 -1
  691. package/src/parquetjs/parquet-thrift/IntType.ts +1 -1
  692. package/src/parquetjs/parquet-thrift/JsonType.ts +1 -1
  693. package/src/parquetjs/parquet-thrift/KeyValue.ts +1 -1
  694. package/src/parquetjs/parquet-thrift/ListType.ts +1 -1
  695. package/src/parquetjs/parquet-thrift/LogicalType.ts +97 -1
  696. package/src/parquetjs/parquet-thrift/MapType.ts +1 -1
  697. package/src/parquetjs/parquet-thrift/MicroSeconds.ts +1 -1
  698. package/src/parquetjs/parquet-thrift/MilliSeconds.ts +1 -1
  699. package/src/parquetjs/parquet-thrift/NanoSeconds.ts +28 -0
  700. package/src/parquetjs/parquet-thrift/NullType.ts +1 -1
  701. package/src/parquetjs/parquet-thrift/OffsetIndex.ts +1 -1
  702. package/src/parquetjs/parquet-thrift/PageEncodingStats.ts +1 -1
  703. package/src/parquetjs/parquet-thrift/PageHeader.ts +1 -1
  704. package/src/parquetjs/parquet-thrift/PageLocation.ts +2 -2
  705. package/src/parquetjs/parquet-thrift/RowGroup.ts +2 -2
  706. package/src/parquetjs/parquet-thrift/SchemaElement.ts +1 -1
  707. package/src/parquetjs/parquet-thrift/SizeStatistics.ts +98 -0
  708. package/src/parquetjs/parquet-thrift/SortingColumn.ts +1 -1
  709. package/src/parquetjs/parquet-thrift/Statistics.ts +50 -14
  710. package/src/parquetjs/parquet-thrift/StringType.ts +1 -1
  711. package/src/parquetjs/parquet-thrift/TimeType.ts +1 -1
  712. package/src/parquetjs/parquet-thrift/TimeUnit.ts +25 -1
  713. package/src/parquetjs/parquet-thrift/TimestampType.ts +1 -1
  714. package/src/parquetjs/parquet-thrift/TypeDefinedOrder.ts +1 -1
  715. package/src/parquetjs/parquet-thrift/UUIDType.ts +1 -1
  716. package/src/parquetjs/parquet-thrift/VariantType.ts +43 -0
  717. package/src/parquetjs/parquet-thrift/index.ts +12 -4
  718. package/src/parquetjs/parser/decoders.ts +922 -143
  719. package/src/parquetjs/parser/encoded-pages.ts +278 -0
  720. package/src/parquetjs/parser/parquet-reader.ts +1334 -83
  721. package/src/parquetjs/schema/declare.ts +121 -9
  722. package/src/parquetjs/schema/schema.ts +33 -3
  723. package/src/parquetjs/schema/shred.ts +345 -41
  724. package/src/parquetjs/schema/types.ts +308 -84
  725. package/src/parquetjs/schema/variant.ts +313 -0
  726. package/src/parquetjs/utils/binary-utils.ts +132 -0
  727. package/src/parquetjs/utils/crc32.ts +15 -0
  728. package/src/parquetjs/utils/file-utils.ts +4 -4
  729. package/src/parquetjs/utils/read-utils.ts +77 -51
  730. package/src/parquetjs/utils/thrift-runtime.ts +109 -0
  731. package/src/parquetjs/utils/uint8-array-compact-protocol-writer.ts +254 -0
  732. package/src/parquetjs/utils/uint8-array-compact-protocol.ts +322 -0
  733. package/src/parquetjs/utils/uint8-array-transport.ts +79 -0
  734. package/src/polyfills/process.ts +17 -0
  735. package/src/unbundled.ts +47 -0
  736. package/src/wasm.ts +6 -0
  737. package/src/workers/parquet-source-worker.ts +21 -0
  738. package/src/workers/parquet-worker-node.ts +5 -0
  739. package/src/workers/parquet-worker.ts +31 -0
  740. package/dist/parquet-arrow-loader.d.ts +0 -43
  741. package/dist/parquet-arrow-loader.d.ts.map +0 -1
  742. package/dist/parquet-arrow-loader.js +0 -49
  743. package/dist/parquet-arrow-loader.js.map +0 -1
  744. package/dist/parquet-arrow-writer.d.ts +0 -9
  745. package/dist/parquet-arrow-writer.d.ts.map +0 -1
  746. package/dist/parquet-arrow-writer.js +0 -23
  747. package/dist/parquet-arrow-writer.js.map +0 -1
  748. package/dist/parquet-json-loader.d.ts +0 -148
  749. package/dist/parquet-json-loader.d.ts.map +0 -1
  750. package/dist/parquet-json-loader.js +0 -106
  751. package/dist/parquet-json-loader.js.map +0 -1
  752. package/dist/parquet-json-writer.d.ts +0 -19
  753. package/dist/parquet-json-writer.d.ts.map +0 -1
  754. package/dist/parquet-json-writer.js +0 -20
  755. package/dist/parquet-json-writer.js.map +0 -1
  756. package/dist/polyfills/buffer/buffer-polyfill.browser.d.ts +0 -3
  757. package/dist/polyfills/buffer/buffer-polyfill.browser.d.ts.map +0 -1
  758. package/dist/polyfills/buffer/buffer-polyfill.browser.js +0 -12
  759. package/dist/polyfills/buffer/buffer-polyfill.browser.js.map +0 -1
  760. package/dist/polyfills/buffer/buffer-polyfill.node.d.ts +0 -3
  761. package/dist/polyfills/buffer/buffer-polyfill.node.d.ts.map +0 -1
  762. package/dist/polyfills/buffer/buffer-polyfill.node.js +0 -17
  763. package/dist/polyfills/buffer/buffer-polyfill.node.js.map +0 -1
  764. package/dist/polyfills/buffer/buffer.d.ts +0 -222
  765. package/dist/polyfills/buffer/buffer.d.ts.map +0 -1
  766. package/dist/polyfills/buffer/buffer.js +0 -1868
  767. package/dist/polyfills/buffer/buffer.js.map +0 -1
  768. package/dist/polyfills/buffer/index.d.ts +0 -4
  769. package/dist/polyfills/buffer/index.d.ts.map +0 -1
  770. package/dist/polyfills/buffer/index.js +0 -9
  771. package/dist/polyfills/buffer/index.js.map +0 -1
  772. package/dist/polyfills/buffer/install-buffer-polyfill.d.ts +0 -2
  773. package/dist/polyfills/buffer/install-buffer-polyfill.d.ts.map +0 -1
  774. package/dist/polyfills/buffer/install-buffer-polyfill.js +0 -10
  775. package/dist/polyfills/buffer/install-buffer-polyfill.js.map +0 -1
  776. package/dist/workers/parquet-json-worker.d.ts +0 -2
  777. package/dist/workers/parquet-json-worker.d.ts.map +0 -1
  778. package/dist/workers/parquet-json-worker.js +0 -7
  779. package/dist/workers/parquet-json-worker.js.map +0 -1
  780. package/src/parquet-arrow-loader.ts +0 -74
  781. package/src/parquet-arrow-writer.ts +0 -33
  782. package/src/parquet-json-loader.ts +0 -160
  783. package/src/parquet-json-writer.ts +0 -27
  784. package/src/parquetjs/modules.d.ts +0 -25
  785. package/src/polyfills/buffer/buffer-polyfill.browser.ts +0 -14
  786. package/src/polyfills/buffer/buffer-polyfill.node.ts +0 -19
  787. package/src/polyfills/buffer/buffer.ts +0 -2205
  788. package/src/polyfills/buffer/index.ts +0 -11
  789. package/src/polyfills/buffer/install-buffer-polyfill.ts +0 -12
  790. package/src/workers/parquet-json-worker.ts +0 -8
@@ -0,0 +1,1037 @@
1
+ // loaders.gl
2
+ // SPDX-License-Identifier: MIT
3
+ // Copyright (c) vis.gl contributors
4
+
5
+ import type {
6
+ CoreAPI,
7
+ ScanQueryMetadata,
8
+ ScanQueryMetadataOptions,
9
+ TableScanSource
10
+ } from '@loaders.gl/loader-utils';
11
+ import {
12
+ createScanQueryMetadata,
13
+ DataSource as BaseDataSource,
14
+ emitScanExecutionTelemetry
15
+ } from '@loaders.gl/loader-utils';
16
+ import * as arrow from 'apache-arrow';
17
+
18
+ import type {
19
+ IcebergDataFile,
20
+ IcebergBoundingBox,
21
+ IcebergSpatialFilter,
22
+ IcebergDeleteFile,
23
+ IcebergManifestFile,
24
+ IcebergParquetFile,
25
+ IcebergScanPlan,
26
+ IcebergSnapshot,
27
+ IcebergTableMetadata,
28
+ IcebergTableSourceOptions
29
+ } from './iceberg-types';
30
+ import {parseAvro} from '@loaders.gl/avro/avro-parser';
31
+ import {ParquetDatasetSource} from './parquet-dataset-source';
32
+ import {PARQUET_TABLE_QUERY_CAPABILITIES} from './parquet-source-capabilities';
33
+ import type {
34
+ ParquetDatasetBatch,
35
+ ParquetComparisonPredicate,
36
+ ParquetDatasetPartitionValue,
37
+ ParquetPredicate,
38
+ ParquetInPredicate,
39
+ ParquetDatasetReadOptions,
40
+ ParquetDatasetExplain,
41
+ ParquetDatasetSourceOptions
42
+ } from './parquet-source-types';
43
+ import type {ScanExecutionTelemetry} from '@loaders.gl/loader-utils';
44
+
45
+ type IcebergEqualityDelete = {
46
+ /** Top-level data-column names covered by the delete. */
47
+ readonly fields: readonly string[];
48
+ /** Equality key values in the same order as `fields`. */
49
+ readonly rows: readonly (readonly unknown[])[];
50
+ /** Partition values limiting the delete's applicability, when present. */
51
+ readonly partition?: Readonly<Record<string, unknown>>;
52
+ /** Delete sequence number used to avoid applying stale deletes. */
53
+ readonly dataSequenceNumber?: number;
54
+ };
55
+
56
+ type IcebergPositionDelete = {
57
+ readonly positions: ReadonlySet<number>;
58
+ readonly dataSequenceNumber?: number;
59
+ };
60
+
61
+ /** Options accepted by `IcebergTableSource`. */
62
+ export type IcebergSourceOptions = ParquetDatasetSourceOptions & {
63
+ iceberg?: IcebergTableSourceOptions;
64
+ };
65
+
66
+ /** Options for scanning the current Iceberg snapshot as Parquet batches. */
67
+ export type IcebergScanOptions = ParquetDatasetReadOptions & {
68
+ /** Reads a specific snapshot instead of the table's current snapshot. */
69
+ snapshotId?: number;
70
+ /** Reads the snapshot selected by a named Iceberg branch or tag. */
71
+ snapshotRef?: string;
72
+ /** Applies Iceberg position deletes after Parquet batches are decoded. */
73
+ applyDeletes?: boolean;
74
+ /** Conservatively prunes files whose declared geometry bounds miss this envelope. */
75
+ spatialFilter?: IcebergSpatialFilter;
76
+ };
77
+
78
+ /**
79
+ * Read-only Iceberg table metadata source.
80
+ *
81
+ * The source owns Iceberg metadata and manifest discovery, then delegates selected data files to
82
+ * `ParquetDatasetSource` for projection, filtering, range access, workers, and Arrow materialization.
83
+ */
84
+ export class IcebergTableSource
85
+ extends BaseDataSource<string, IcebergSourceOptions>
86
+ implements TableScanSource<ParquetDatasetBatch, ParquetPredicate>
87
+ {
88
+ private metadataPromise: Promise<IcebergTableMetadata> | null = null;
89
+ private readonly closeController = new AbortController();
90
+ private closed = false;
91
+
92
+ constructor(data: string, options: IcebergSourceOptions = {}, coreApi?: CoreAPI) {
93
+ super(data, options, undefined, coreApi);
94
+ }
95
+
96
+ /** Loads and validates the table metadata JSON. Results are cached for the source lifetime. */
97
+ async getMetadata(signal?: AbortSignal): Promise<IcebergTableMetadata> {
98
+ this.assertOpen();
99
+ if (!this.metadataPromise) {
100
+ this.metadataPromise = this.loadMetadata(signal).catch(error => {
101
+ this.metadataPromise = null;
102
+ throw error;
103
+ });
104
+ }
105
+ return this.metadataPromise;
106
+ }
107
+
108
+ /** Returns the snapshot selected by the table metadata, if one exists. */
109
+ async getCurrentSnapshot(signal?: AbortSignal): Promise<IcebergSnapshot | undefined> {
110
+ return this.getSnapshot(undefined, undefined, signal);
111
+ }
112
+
113
+ /** Returns a selected snapshot, defaulting to the table's current snapshot. */
114
+ private async getSnapshot(
115
+ snapshotId: number | undefined,
116
+ snapshotRef: string | undefined,
117
+ signal?: AbortSignal
118
+ ): Promise<IcebergSnapshot | undefined> {
119
+ const metadata = await this.getMetadata(signal);
120
+ if (snapshotId !== undefined && snapshotRef !== undefined) {
121
+ throw new Error('Iceberg snapshotId and snapshotRef are mutually exclusive');
122
+ }
123
+ const reference = snapshotRef ? metadata.refs?.[snapshotRef] : undefined;
124
+ if (snapshotRef && !reference)
125
+ throw new Error(`Iceberg snapshot reference not found: ${snapshotRef}`);
126
+ const selectedSnapshotId =
127
+ snapshotId ?? reference?.['snapshot-id'] ?? metadata['current-snapshot-id'];
128
+ if (selectedSnapshotId === undefined || selectedSnapshotId === -1) return undefined;
129
+ return metadata.snapshots?.find(snapshot => snapshot['snapshot-id'] === selectedSnapshotId);
130
+ }
131
+
132
+ /** Builds a data and delete-file plan from one snapshot without opening data files. */
133
+ async getScanPlan(
134
+ signal?: AbortSignal,
135
+ snapshotId?: number,
136
+ snapshotRef?: string
137
+ ): Promise<IcebergScanPlan> {
138
+ const metadata = await this.getMetadata(signal);
139
+ const snapshot = await this.getSnapshot(snapshotId, snapshotRef, signal);
140
+ if (!snapshot?.['manifest-list'])
141
+ return {dataFiles: [], deleteFiles: [], snapshotId, snapshotRef};
142
+ const schemaId = snapshot['schema-id'] ?? metadata['current-schema-id'];
143
+ const manifestList = await this.readAvroRecords<IcebergManifestFile>(
144
+ resolveIcebergLocation(metadata.location, snapshot['manifest-list']),
145
+ signal
146
+ );
147
+ const dataFiles: IcebergParquetFile[] = [];
148
+ const deleteFiles: IcebergDeleteFile[] = [];
149
+ for (const manifest of manifestList) {
150
+ const isDelete = isDeleteManifest(manifest);
151
+ if (!isDelete && !isDataManifest(manifest)) continue;
152
+ const entries = await this.readAvroRecords<Record<string, unknown>>(
153
+ resolveIcebergLocation(metadata.location, manifest.manifest_path),
154
+ signal
155
+ );
156
+ for (const entry of entries) {
157
+ if (isDeletedManifestEntry(entry)) continue;
158
+ const dataFile = entry.data_file as IcebergDataFile | undefined;
159
+ if (!dataFile || typeof dataFile.file_path !== 'string') continue;
160
+ if (isDelete) {
161
+ deleteFiles.push(
162
+ createIcebergDeleteFile(
163
+ metadata.location,
164
+ dataFile,
165
+ manifest,
166
+ snapshot['snapshot-id'],
167
+ schemaId
168
+ )
169
+ );
170
+ } else if (dataFile.file_format?.toLowerCase() === 'parquet') {
171
+ dataFiles.push(
172
+ createIcebergParquetFile(
173
+ metadata.location,
174
+ dataFile,
175
+ manifest,
176
+ snapshot['snapshot-id'],
177
+ schemaId
178
+ )
179
+ );
180
+ }
181
+ }
182
+ }
183
+ return {dataFiles, deleteFiles, snapshotId: snapshot['snapshot-id'], snapshotRef};
184
+ }
185
+
186
+ /** Reads the selected snapshot's active Parquet data files. */
187
+ async getParquetFiles(
188
+ signal?: AbortSignal,
189
+ snapshotId?: number,
190
+ snapshotRef?: string
191
+ ): Promise<readonly IcebergParquetFile[]> {
192
+ return (await this.getScanPlan(signal, snapshotId, snapshotRef)).dataFiles;
193
+ }
194
+
195
+ /** Reads delete files from the selected snapshot without applying them to Parquet rows. */
196
+ async getDeleteFiles(
197
+ signal?: AbortSignal,
198
+ snapshotId?: number,
199
+ snapshotRef?: string
200
+ ): Promise<readonly IcebergDeleteFile[]> {
201
+ return (await this.getScanPlan(signal, snapshotId, snapshotRef)).deleteFiles;
202
+ }
203
+
204
+ /** Discovers the current snapshot schema and aggregate file statistics without decoding rows. */
205
+ async getQueryMetadata(options: ScanQueryMetadataOptions = {}): Promise<ScanQueryMetadata> {
206
+ this.assertOpen();
207
+ const metadata = await this.getMetadata(options.signal);
208
+ const plan = await this.getScanPlan(options.signal);
209
+ if (!plan.dataFiles.length) {
210
+ throw new Error('Iceberg snapshot contains no active Parquet data files');
211
+ }
212
+ const parquetSource = this.createParquetDataset(plan, metadata, {});
213
+ try {
214
+ const schema = await parquetSource.getSchema({signal: options.signal});
215
+ return createScanQueryMetadata({
216
+ sourceType: 'iceberg',
217
+ queryType: 'table',
218
+ execution: {status: 'supported', method: 'read'},
219
+ name: this.data,
220
+ schema,
221
+ capabilities: {table: PARQUET_TABLE_QUERY_CAPABILITIES},
222
+ statistics: {
223
+ rowCount: plan.dataFiles.reduce((sum, file) => sum + Number(file.recordCount || 0), 0),
224
+ byteLength: plan.dataFiles.reduce((sum, file) => sum + Number(file.fileSize || 0), 0)
225
+ }
226
+ });
227
+ } finally {
228
+ await parquetSource.close();
229
+ }
230
+ }
231
+
232
+ /** Explains Iceberg manifest pruning and the delegated Parquet dataset plan. */
233
+ async explain(options: IcebergScanOptions = {}): Promise<ParquetDatasetExplain> {
234
+ this.assertOpen();
235
+ const metadata = await this.getMetadata(options.signal);
236
+ const plan = await this.getScanPlan(options.signal, options.snapshotId, options.snapshotRef);
237
+ const parquetSource = this.createParquetDataset(plan, metadata, options);
238
+ try {
239
+ return await parquetSource.getScanPlan(options);
240
+ } finally {
241
+ await parquetSource.close();
242
+ }
243
+ }
244
+
245
+ /** Common table-scan entry point for the selected Iceberg snapshot. */
246
+ read(options: IcebergScanOptions = {}): AsyncIterable<ParquetDatasetBatch> {
247
+ return this.scan(options);
248
+ }
249
+
250
+ /** Reads the current snapshot as Arrow batches through the existing Parquet dataset source. */
251
+ async *scan(options: IcebergScanOptions = {}): AsyncIterable<ParquetDatasetBatch> {
252
+ this.assertOpen();
253
+ const metadata = await this.getMetadata(options.signal);
254
+ const plan = await this.getScanPlan(options.signal, options.snapshotId, options.snapshotRef);
255
+ const positionDeletes = options.applyDeletes
256
+ ? await this.loadPositionDeletes(plan.deleteFiles, metadata.location, options.signal)
257
+ : undefined;
258
+ const equalityDeletes = options.applyDeletes
259
+ ? await this.loadEqualityDeletes(plan.deleteFiles, metadata, options.signal)
260
+ : [];
261
+ const equalityColumns = getEqualityDeleteColumns(equalityDeletes);
262
+ let childTelemetry: ScanExecutionTelemetry | undefined;
263
+ const readOptions = {
264
+ ...addEqualityColumns(options, equalityColumns),
265
+ onTelemetry: (telemetry: ScanExecutionTelemetry) => {
266
+ childTelemetry = telemetry;
267
+ }
268
+ };
269
+ const parquetSource = this.createParquetDataset(plan, metadata, options);
270
+ let completed = false;
271
+ let readError: unknown;
272
+ let rowsReturned = 0;
273
+ try {
274
+ for await (const batch of parquetSource.read(readOptions)) {
275
+ const filteredBatch = options.applyDeletes
276
+ ? applyIcebergDeletes(batch, positionDeletes, equalityDeletes, options.columns)
277
+ : batch;
278
+ if (filteredBatch.length > 0) {
279
+ rowsReturned += filteredBatch.length;
280
+ yield filteredBatch;
281
+ }
282
+ }
283
+ completed = true;
284
+ } catch (error) {
285
+ readError = error;
286
+ throw error;
287
+ } finally {
288
+ await parquetSource.close();
289
+ if (childTelemetry) {
290
+ const cancelled = options.signal?.aborted === true;
291
+ const status: ScanExecutionTelemetry['status'] = readError
292
+ ? cancelled
293
+ ? 'cancelled'
294
+ : 'failed'
295
+ : completed
296
+ ? childTelemetry.status
297
+ : 'early-terminated';
298
+ emitScanExecutionTelemetry(options.onTelemetry, {
299
+ ...childTelemetry,
300
+ status,
301
+ rowsReturned,
302
+ ...(readError === undefined ? {} : {error: readError})
303
+ });
304
+ }
305
+ }
306
+ }
307
+
308
+ /** Creates the delegated Parquet dataset after Iceberg metadata-level pruning. */
309
+ private createParquetDataset(
310
+ plan: IcebergScanPlan,
311
+ metadata: IcebergTableMetadata,
312
+ options: IcebergScanOptions
313
+ ): ParquetDatasetSource {
314
+ return new ParquetDatasetSource(
315
+ plan.dataFiles
316
+ .filter(
317
+ file =>
318
+ canMatchIcebergPredicate(file, options.predicate, metadata) &&
319
+ canMatchIcebergSpatialFilter(file, options.spatialFilter, metadata)
320
+ )
321
+ .map(file => ({
322
+ data: file.data,
323
+ id: file.data,
324
+ partitions: getIcebergPartitions(
325
+ file.partition,
326
+ file.partitionSpecId,
327
+ file.schemaId,
328
+ metadata
329
+ ),
330
+ metadata: {
331
+ iceberg: {
332
+ fileSize: file.fileSize,
333
+ recordCount: file.recordCount,
334
+ partition: file.partition,
335
+ lowerBounds: file.lowerBounds,
336
+ upperBounds: file.upperBounds,
337
+ dataSequenceNumber: file.dataSequenceNumber
338
+ }
339
+ }
340
+ })),
341
+ this.options,
342
+ this.coreApi
343
+ );
344
+ }
345
+
346
+ /** Permanently closes the source and aborts an in-flight metadata request. */
347
+ async close(): Promise<void> {
348
+ if (!this.closed) {
349
+ this.closed = true;
350
+ this.closeController.abort();
351
+ }
352
+ }
353
+
354
+ private async loadMetadata(signal?: AbortSignal): Promise<IcebergTableMetadata> {
355
+ const abortController = new AbortController();
356
+ const abortSignal = combineAbortSignals(signal, this.closeController.signal, abortController);
357
+ try {
358
+ const response = await this.fetch(this.data, {
359
+ headers: this.options.iceberg?.headers,
360
+ signal: abortSignal.signal
361
+ });
362
+ if (!response.ok) {
363
+ throw new Error(`Iceberg metadata request failed with HTTP ${response.status}`);
364
+ }
365
+ const metadata = (await response.json()) as IcebergTableMetadata;
366
+ validateIcebergTableMetadata(metadata);
367
+ return metadata;
368
+ } finally {
369
+ abortSignal.dispose();
370
+ }
371
+ }
372
+
373
+ private async readAvroRecords<RecordT>(url: string, signal?: AbortSignal): Promise<RecordT[]> {
374
+ const abortController = new AbortController();
375
+ const abortSignal = combineAbortSignals(signal, this.closeController.signal, abortController);
376
+ try {
377
+ const response = await this.fetch(url, {
378
+ headers: this.options.iceberg?.headers,
379
+ signal: abortSignal.signal
380
+ });
381
+ if (!response.ok)
382
+ throw new Error(`Iceberg manifest request failed with HTTP ${response.status}`);
383
+ const table = await parseAvro(await response.arrayBuffer(), {longType: 'number'});
384
+ return table.data.toArray() as RecordT[];
385
+ } finally {
386
+ abortSignal.dispose();
387
+ }
388
+ }
389
+
390
+ /** Reads position-delete files into a source-file to row-position index. */
391
+ private async loadPositionDeletes(
392
+ deleteFiles: readonly IcebergDeleteFile[],
393
+ baseLocation: string,
394
+ signal?: AbortSignal
395
+ ): Promise<ReadonlyMap<string, readonly IcebergPositionDelete[]>> {
396
+ const positions = new Map<string, IcebergPositionDelete[]>();
397
+ for (const deleteFile of deleteFiles) {
398
+ if (!isPositionDelete(deleteFile)) continue;
399
+ const records = await this.readAvroRecords<Record<string, unknown>>(deleteFile.data, signal);
400
+ const filePositions = new Map<string, Set<number>>();
401
+ for (const record of records) {
402
+ if (typeof record.file_path !== 'string' || typeof record.pos !== 'number') continue;
403
+ const filePath = resolveIcebergLocation(baseLocation, record.file_path);
404
+ const rowPositions = filePositions.get(filePath) || new Set<number>();
405
+ rowPositions.add(record.pos);
406
+ filePositions.set(filePath, rowPositions);
407
+ }
408
+ for (const [filePath, rowPositions] of filePositions) {
409
+ const deletes = positions.get(filePath) || [];
410
+ deletes.push({positions: rowPositions, dataSequenceNumber: deleteFile.dataSequenceNumber});
411
+ positions.set(filePath, deletes);
412
+ }
413
+ }
414
+ return positions;
415
+ }
416
+
417
+ /** Reads equality-delete files and resolves their Iceberg field IDs to current schema names. */
418
+ private async loadEqualityDeletes(
419
+ deleteFiles: readonly IcebergDeleteFile[],
420
+ metadata: IcebergTableMetadata,
421
+ signal?: AbortSignal
422
+ ): Promise<readonly IcebergEqualityDelete[]> {
423
+ const equalityDeletes: IcebergEqualityDelete[] = [];
424
+ for (const deleteFile of deleteFiles) {
425
+ if (!isEqualityDelete(deleteFile)) continue;
426
+ if (deleteFile.format.toLowerCase() !== 'avro') {
427
+ throw new Error(`Unsupported equality delete format: ${deleteFile.format}`);
428
+ }
429
+ const fieldIds = deleteFile.equalityFieldIds;
430
+ if (!fieldIds?.length) throw new Error('Equality delete file has no field IDs');
431
+ const fields = resolveIcebergFieldNames(fieldIds, metadata, deleteFile.schemaId);
432
+ const records = await this.readAvroRecords<Record<string, unknown>>(deleteFile.data, signal);
433
+ equalityDeletes.push({
434
+ fields,
435
+ partition: deleteFile.partition,
436
+ dataSequenceNumber: deleteFile.dataSequenceNumber,
437
+ rows: records.map(record =>
438
+ fields.map((field, index) => getDeleteRecordValue(record, field, fieldIds[index]))
439
+ )
440
+ });
441
+ }
442
+ return equalityDeletes;
443
+ }
444
+
445
+ private assertOpen(): void {
446
+ if (this.closed) throw new Error('Iceberg table source is closed');
447
+ }
448
+ }
449
+
450
+ /** Identifies a position-delete plan entry. */
451
+ function isPositionDelete(deleteFile: IcebergDeleteFile): boolean {
452
+ return deleteFile.content === 1 || deleteFile.content === 'position';
453
+ }
454
+
455
+ /** Identifies an equality-delete plan entry. */
456
+ function isEqualityDelete(deleteFile: IcebergDeleteFile): boolean {
457
+ return deleteFile.content === 2 || deleteFile.content === 'equality';
458
+ }
459
+
460
+ /** Adds equality-delete columns to the Parquet read without changing requested output columns. */
461
+ function addEqualityColumns(
462
+ options: IcebergScanOptions,
463
+ equalityColumns: readonly string[]
464
+ ): IcebergScanOptions {
465
+ if (!options.applyDeletes || equalityColumns.length === 0 || !options.columns) return options;
466
+ const columns = [...options.columns];
467
+ for (const column of equalityColumns) {
468
+ if (!columns.includes(column)) columns.push(column);
469
+ }
470
+ return {...options, columns};
471
+ }
472
+
473
+ /** Removes position and equality-deleted rows while retaining Arrow output and provenance. */
474
+ function applyIcebergDeletes(
475
+ batch: ParquetDatasetBatch,
476
+ positionsByFile: ReadonlyMap<string, readonly IcebergPositionDelete[]> | undefined,
477
+ equalityDeletes: readonly IcebergEqualityDelete[],
478
+ outputColumns: readonly string[] | undefined
479
+ ): ParquetDatasetBatch {
480
+ const sourcePositions = positionsByFile?.get(batch.sourceUrl || batch.source);
481
+ const keptIndexes: number[] = [];
482
+ for (let index = 0; index < batch.length; index++) {
483
+ const sourcePosition = batch.rowIndices?.[index] ?? batch.rowOffset + index;
484
+ if (
485
+ sourcePositions?.some(
486
+ deleteFile =>
487
+ deleteFile.positions.has(sourcePosition) &&
488
+ isDeleteSequenceApplicable(batch, deleteFile.dataSequenceNumber)
489
+ )
490
+ )
491
+ continue;
492
+ if (equalityDeletes.some(deleteFile => matchesEqualityDelete(batch, index, deleteFile))) {
493
+ continue;
494
+ }
495
+ keptIndexes.push(index);
496
+ }
497
+ const allColumns = batch.data.schema.fields.map(field => field.name);
498
+ const selectedColumns = outputColumns ? [...outputColumns] : allColumns;
499
+ const needsColumnProjection =
500
+ selectedColumns.length !== allColumns.length ||
501
+ selectedColumns.some((column, index) => column !== allColumns[index]);
502
+ if (keptIndexes.length === batch.length && !needsColumnProjection) return batch;
503
+ const columns: Record<string, unknown[]> = {};
504
+ for (const columnName of selectedColumns) {
505
+ const column = batch.data.getChild(columnName);
506
+ if (!column)
507
+ throw new Error(`Equality delete column is missing from Parquet output: ${columnName}`);
508
+ columns[columnName] = keptIndexes.map(index => column.get(index));
509
+ }
510
+ const rowGroupRowIndices = keptIndexes.map(
511
+ index => batch.rowGroupRowIndices?.[index] ?? batch.rowGroupRowOffset + index
512
+ );
513
+ const rowIndices = keptIndexes.map(index => batch.rowIndices?.[index] ?? batch.rowOffset + index);
514
+ const data = arrow.tableFromArrays(columns);
515
+ return {
516
+ ...batch,
517
+ data,
518
+ length: keptIndexes.length,
519
+ rowCount: keptIndexes.length,
520
+ rowGroupRowIndices,
521
+ rowIndices,
522
+ metadata: batch.metadata ? {...batch.metadata, rowCount: keptIndexes.length} : batch.metadata
523
+ };
524
+ }
525
+
526
+ /** Tests one decoded row against one equality-delete key. */
527
+ function matchesEqualityDelete(
528
+ batch: ParquetDatasetBatch,
529
+ rowIndex: number,
530
+ deleteFile: IcebergEqualityDelete
531
+ ): boolean {
532
+ if (!matchesDeletePartition(batch, deleteFile) || !matchesDeleteSequence(batch, deleteFile)) {
533
+ return false;
534
+ }
535
+ return deleteFile.rows.some(values =>
536
+ deleteFile.fields.every((field, index) => {
537
+ const column = batch.data.getChild(field);
538
+ return column ? compareDeleteValues(column.get(rowIndex), values[index]) : false;
539
+ })
540
+ );
541
+ }
542
+
543
+ /** Conservatively limits equality deletes to the data-file partition they describe. */
544
+ function matchesDeletePartition(
545
+ batch: ParquetDatasetBatch,
546
+ deleteFile: IcebergEqualityDelete
547
+ ): boolean {
548
+ if (!deleteFile.partition || !batch.datasetPartitions) return true;
549
+ return Object.entries(deleteFile.partition).every(([key, value]) => {
550
+ const actual = batch.datasetPartitions?.[key];
551
+ return actual === undefined || compareDeleteValues(actual, value);
552
+ });
553
+ }
554
+
555
+ /** Avoids applying a delete whose sequence is not newer than the data file. */
556
+ function matchesDeleteSequence(
557
+ batch: ParquetDatasetBatch,
558
+ deleteFile: IcebergEqualityDelete
559
+ ): boolean {
560
+ return isDeleteSequenceApplicable(batch, deleteFile.dataSequenceNumber);
561
+ }
562
+
563
+ /** Returns whether a delete sequence is newer than the current data-file sequence. */
564
+ function isDeleteSequenceApplicable(batch: ParquetDatasetBatch, deleteSequence?: number): boolean {
565
+ if (deleteSequence === undefined) return true;
566
+ const metadata = batch.datasetFileMetadata?.iceberg;
567
+ if (!metadata || typeof metadata !== 'object') return true;
568
+ const dataSequenceNumber = (metadata as {dataSequenceNumber?: unknown}).dataSequenceNumber;
569
+ return typeof dataSequenceNumber !== 'number' || deleteSequence > dataSequenceNumber;
570
+ }
571
+
572
+ /** Compares delete-key values, including binary, date, and numeric representations. */
573
+ function compareDeleteValues(left: unknown, right: unknown): boolean {
574
+ if (left instanceof Uint8Array && right instanceof Uint8Array) {
575
+ return left.length === right.length && left.every((value, index) => value === right[index]);
576
+ }
577
+ if (left instanceof Date && right instanceof Date) return left.getTime() === right.getTime();
578
+ if (
579
+ (typeof left === 'number' || typeof left === 'bigint') &&
580
+ (typeof right === 'number' || typeof right === 'bigint')
581
+ ) {
582
+ return Number(left) === Number(right);
583
+ }
584
+ return Object.is(left, right);
585
+ }
586
+
587
+ /** Resolves equality-delete field IDs through the schema selected by the snapshot. */
588
+ function resolveIcebergFieldNames(
589
+ fieldIds: readonly number[],
590
+ metadata: IcebergTableMetadata,
591
+ schemaId?: number
592
+ ): string[] {
593
+ const schema = metadata.schemas?.find(
594
+ candidate => candidate['schema-id'] === (schemaId ?? metadata['current-schema-id'])
595
+ );
596
+ return fieldIds.map(fieldId => {
597
+ const field = schema?.fields?.find(candidate => candidate.id === fieldId);
598
+ if (typeof field?.name !== 'string') {
599
+ throw new Error(
600
+ `Equality delete field ID ${fieldId} is absent from the selected Iceberg schema`
601
+ );
602
+ }
603
+ return field.name;
604
+ });
605
+ }
606
+
607
+ /** Reads a delete value by schema name, falling back to a numeric field-ID key. */
608
+ function getDeleteRecordValue(
609
+ record: Readonly<Record<string, unknown>>,
610
+ fieldName: string,
611
+ fieldId: number
612
+ ): unknown {
613
+ if (Object.prototype.hasOwnProperty.call(record, fieldName)) return record[fieldName];
614
+ return record[String(fieldId)];
615
+ }
616
+
617
+ /** Returns the unique top-level columns required to evaluate equality deletes. */
618
+ function getEqualityDeleteColumns(equalityDeletes: readonly IcebergEqualityDelete[]): string[] {
619
+ return [...new Set(equalityDeletes.flatMap(deleteFile => deleteFile.fields))];
620
+ }
621
+
622
+ /** Conservatively tests whether an Iceberg file's bounds can satisfy a Parquet predicate. */
623
+ function canMatchIcebergPredicate(
624
+ file: IcebergParquetFile,
625
+ predicate: ParquetPredicate | undefined,
626
+ metadata: IcebergTableMetadata
627
+ ): boolean {
628
+ if (!predicate) return true;
629
+ if (predicate.op === 'and')
630
+ return predicate.args.every(child => canMatchIcebergPredicate(file, child, metadata));
631
+ if (predicate.op === 'or')
632
+ return predicate.args.some(child => canMatchIcebergPredicate(file, child, metadata));
633
+ if (predicate.op === 'not') return true;
634
+ if (predicate.op === 'isNull') return true;
635
+
636
+ const leaf = predicate as ParquetComparisonPredicate | ParquetInPredicate;
637
+ const property = getPredicateProperty(leaf);
638
+ const bounds = getIcebergBounds(file, property, metadata);
639
+ if (!bounds) return true;
640
+ if (leaf.op === 'in') {
641
+ return leaf.args[1].some(value => canMatchIcebergComparison(bounds, '=', value));
642
+ }
643
+ return canMatchIcebergComparison(bounds, leaf.op, leaf.args[1]);
644
+ }
645
+
646
+ /** Conservatively determines whether a data file can intersect a spatial envelope. */
647
+ function canMatchIcebergSpatialFilter(
648
+ file: IcebergParquetFile,
649
+ spatialFilter: IcebergSpatialFilter | undefined,
650
+ metadata: IcebergTableMetadata
651
+ ): boolean {
652
+ if (!spatialFilter) return true;
653
+ const bounds = getIcebergSpatialBounds(file, spatialFilter.column, metadata);
654
+ if (!bounds) return true;
655
+ return !areBoundingBoxesDisjoint(bounds, spatialFilter.bbox);
656
+ }
657
+
658
+ /** Resolves a geometry column's conservative bounds from Iceberg lower/upper bounds. */
659
+ function getIcebergSpatialBounds(
660
+ file: IcebergParquetFile,
661
+ property: string,
662
+ metadata: IcebergTableMetadata
663
+ ): IcebergBoundingBox | undefined {
664
+ const lowerBounds = file.lowerBounds;
665
+ const upperBounds = file.upperBounds;
666
+ if (!lowerBounds || !upperBounds) return undefined;
667
+ const schema = metadata.schemas?.find(
668
+ candidate => candidate['schema-id'] === (file.schemaId ?? metadata['current-schema-id'])
669
+ );
670
+ const field = schema?.fields?.find(candidate => candidate.name === property);
671
+ const fieldId = typeof field?.id === 'number' ? field.id : undefined;
672
+ const lower = lowerBounds[property] ?? (fieldId === undefined ? undefined : lowerBounds[fieldId]);
673
+ const upper = upperBounds[property] ?? (fieldId === undefined ? undefined : upperBounds[fieldId]);
674
+ return normalizeIcebergBoundingBox(lower, upper);
675
+ }
676
+
677
+ /** Normalizes common Iceberg/GeoParquet bounding-box representations without guessing unknown data. */
678
+ function normalizeIcebergBoundingBox(
679
+ lower: unknown,
680
+ upper: unknown
681
+ ): IcebergBoundingBox | undefined {
682
+ const lowerValues = getBoundingBoxValues(lower);
683
+ const upperValues = getBoundingBoxValues(upper);
684
+ if (lowerValues?.length === 4) {
685
+ return [lowerValues[0], lowerValues[1], lowerValues[2], lowerValues[3]];
686
+ }
687
+ if (lowerValues?.length === 2 && upperValues?.length === 2) {
688
+ return [lowerValues[0], lowerValues[1], upperValues[0], upperValues[1]];
689
+ }
690
+ return undefined;
691
+ }
692
+
693
+ /** Reads numeric bounds from arrays or common named-bound objects. */
694
+ function getBoundingBoxValues(value: unknown): number[] | undefined {
695
+ if (Array.isArray(value) && (value.length === 2 || value.length === 4)) {
696
+ const numbers = value.map(getNumberValue);
697
+ return numbers.every(isNumber) ? numbers : undefined;
698
+ }
699
+ if (!value || typeof value !== 'object') return undefined;
700
+ const record = value as Record<string, unknown>;
701
+ const keys = ['xmin', 'ymin', 'xmax', 'ymax'];
702
+ const numbers = keys.map(key => getNumberValue(record[key]));
703
+ return numbers.every(isNumber) ? numbers : undefined;
704
+ }
705
+
706
+ /** Tests two axis-aligned envelopes without excluding touching boundaries. */
707
+ function areBoundingBoxesDisjoint(left: IcebergBoundingBox, right: IcebergBoundingBox): boolean {
708
+ return left[2] < right[0] || left[0] > right[2] || left[3] < right[1] || left[1] > right[3];
709
+ }
710
+
711
+ /** Returns the top-level field name used by a Parquet predicate. */
712
+ function getPredicateProperty(predicate: ParquetComparisonPredicate | ParquetInPredicate): string {
713
+ const property = predicate.args[0].property;
714
+ return typeof property === 'string' ? property : property[0];
715
+ }
716
+
717
+ /** Resolves an Iceberg field's lower and upper bounds by name or schema field identifier. */
718
+ function getIcebergBounds(
719
+ file: IcebergParquetFile,
720
+ property: string,
721
+ metadata: IcebergTableMetadata
722
+ ): {lower: unknown; upper: unknown} | undefined {
723
+ const lowerBounds = file.lowerBounds;
724
+ const upperBounds = file.upperBounds;
725
+ if (!lowerBounds || !upperBounds) return undefined;
726
+ let fieldId: number | undefined;
727
+ const schema = metadata.schemas?.find(
728
+ candidate => candidate['schema-id'] === (file.schemaId ?? metadata['current-schema-id'])
729
+ );
730
+ let fieldType: unknown;
731
+ for (const field of schema?.fields || []) {
732
+ if (field.name === property) {
733
+ fieldType = field.type;
734
+ if (typeof field.id === 'number') fieldId = field.id;
735
+ }
736
+ }
737
+ const lower = decodeIcebergBound(
738
+ lowerBounds[property] ?? (fieldId === undefined ? undefined : lowerBounds[fieldId]),
739
+ fieldType
740
+ );
741
+ const upper = decodeIcebergBound(
742
+ upperBounds[property] ?? (fieldId === undefined ? undefined : upperBounds[fieldId]),
743
+ fieldType
744
+ );
745
+ if (lower === undefined || upper === undefined) return undefined;
746
+ return {lower, upper};
747
+ }
748
+
749
+ /** Decodes an Iceberg binary bound when the table schema identifies a primitive type. */
750
+ function decodeIcebergBound(value: unknown, fieldType: unknown): unknown {
751
+ if (!(value instanceof Uint8Array)) return value;
752
+ const typeName =
753
+ typeof fieldType === 'string'
754
+ ? fieldType
755
+ : fieldType && typeof fieldType === 'object' && 'type' in fieldType
756
+ ? (fieldType as {type?: unknown}).type
757
+ : undefined;
758
+ if (typeof typeName !== 'string') return undefined;
759
+ const dataView = new DataView(value.buffer, value.byteOffset, value.byteLength);
760
+ switch (typeName) {
761
+ case 'boolean':
762
+ return value.length === 1 ? value[0] !== 0 : undefined;
763
+ case 'int':
764
+ case 'date':
765
+ return value.length === 4 ? dataView.getInt32(0, false) : undefined;
766
+ case 'long':
767
+ case 'time':
768
+ case 'timestamp':
769
+ case 'timestz':
770
+ return value.length === 8 ? dataView.getBigInt64(0, false) : undefined;
771
+ case 'float':
772
+ return value.length === 4 ? dataView.getFloat32(0, false) : undefined;
773
+ case 'double':
774
+ return value.length === 8 ? dataView.getFloat64(0, false) : undefined;
775
+ case 'string':
776
+ return new TextDecoder().decode(value);
777
+ default:
778
+ return undefined;
779
+ }
780
+ }
781
+
782
+ /** Converts scalar Iceberg partition fields into the dataset source's reusable partition filter. */
783
+ function getIcebergPartitions(
784
+ partition: Readonly<Record<string, unknown>> | undefined,
785
+ partitionSpecId: number | undefined,
786
+ schemaId: number | undefined,
787
+ metadata: IcebergTableMetadata
788
+ ): Readonly<Record<string, ParquetDatasetPartitionValue>> | undefined {
789
+ if (!partition) return undefined;
790
+ const result: Record<string, ParquetDatasetPartitionValue> = {};
791
+ for (const [key, value] of Object.entries(partition)) {
792
+ if (
793
+ value === null ||
794
+ typeof value === 'string' ||
795
+ typeof value === 'number' ||
796
+ typeof value === 'boolean'
797
+ ) {
798
+ result[key] = value;
799
+ }
800
+ }
801
+ const partitionSpec = metadata['partition-specs']?.find(
802
+ candidate => candidate['spec-id'] === partitionSpecId
803
+ );
804
+ const schema = metadata.schemas?.find(
805
+ candidate => candidate['schema-id'] === (schemaId ?? metadata['current-schema-id'])
806
+ );
807
+ for (const field of partitionSpec?.fields || []) {
808
+ if (field.transform !== 'identity' || typeof field['source-id'] !== 'number') continue;
809
+ const schemaField = schema?.fields?.find(candidate => candidate.id === field['source-id']);
810
+ if (typeof schemaField?.name !== 'string' || typeof field.name !== 'string') continue;
811
+ const value = result[field.name];
812
+ if (value !== undefined) result[schemaField.name] = value;
813
+ }
814
+ return result;
815
+ }
816
+
817
+ /** Normalizes Avro map values, which may decode as JavaScript Maps or plain objects. */
818
+ function normalizeIcebergMap(value: unknown): Readonly<Record<string, unknown>> | undefined {
819
+ if (!value) return undefined;
820
+ if (value instanceof Map) return Object.fromEntries(value.entries());
821
+ if (typeof value === 'object') return value as Readonly<Record<string, unknown>>;
822
+ return undefined;
823
+ }
824
+
825
+ /** Reads a field from plain manifest records and Arrow StructRow-like records. */
826
+ function getIcebergRecordValue(record: unknown, key: string): unknown {
827
+ if (!record || typeof record !== 'object') return undefined;
828
+ if (key in record) return (record as Record<string, unknown>)[key];
829
+ if ('get' in record && typeof (record as {get?: unknown}).get === 'function') {
830
+ return (record as {get: (field: string) => unknown}).get(key);
831
+ }
832
+ return undefined;
833
+ }
834
+
835
+ /** Normalizes Avro array values that may be decoded as Arrow vectors or JavaScript arrays. */
836
+ function normalizeNumberArray(value: unknown): readonly number[] | undefined {
837
+ if (typeof value === 'number') return [value];
838
+ if (Array.isArray(value)) return value.map(getNumberValue).filter(isNumber);
839
+ if (value && typeof value === 'object' && 'toArray' in value) {
840
+ const arrayValue = (value as {toArray: () => unknown[]}).toArray();
841
+ return arrayValue.map(getNumberValue).filter(isNumber);
842
+ }
843
+ if (value && typeof value !== 'string' && Symbol.iterator in Object(value)) {
844
+ return Array.from(value as Iterable<unknown>)
845
+ .map(getNumberValue)
846
+ .filter(isNumber);
847
+ }
848
+ return undefined;
849
+ }
850
+
851
+ /** Extracts a number from a JavaScript value or an Arrow scalar wrapper. */
852
+ function getNumberValue(value: unknown): number | undefined {
853
+ if (typeof value === 'number') return value;
854
+ if (typeof value === 'bigint') return Number(value);
855
+ if (value && typeof value === 'object' && 'value' in value) {
856
+ const scalarValue = (value as {value?: unknown}).value;
857
+ if (typeof scalarValue === 'number') return scalarValue;
858
+ if (typeof scalarValue === 'bigint') return Number(scalarValue);
859
+ }
860
+ if (value && typeof value === 'object' && 'toJSON' in value) {
861
+ const jsonValue = (value as {toJSON: () => unknown}).toJSON();
862
+ return typeof jsonValue === 'number' ? jsonValue : undefined;
863
+ }
864
+ return undefined;
865
+ }
866
+
867
+ /** Narrows an optional number after delete-array normalization. */
868
+ function isNumber(value: number | undefined): value is number {
869
+ return value !== undefined;
870
+ }
871
+
872
+ /** Applies a comparison to file bounds without pruning values that cannot be compared safely. */
873
+ function canMatchIcebergComparison(
874
+ bounds: {lower: unknown; upper: unknown},
875
+ operator: '=' | '<>' | '<' | '<=' | '>' | '>=',
876
+ value: unknown
877
+ ): boolean {
878
+ const lowerComparison = compareIcebergValues(bounds.lower, value);
879
+ const upperComparison = compareIcebergValues(bounds.upper, value);
880
+ if (lowerComparison === undefined || upperComparison === undefined) return true;
881
+ if (operator === '=') return lowerComparison <= 0 && upperComparison >= 0;
882
+ if (operator === '<>') return bounds.lower !== bounds.upper || lowerComparison !== 0;
883
+ if (operator === '<') return lowerComparison < 0;
884
+ if (operator === '<=') return lowerComparison <= 0;
885
+ if (operator === '>') return upperComparison > 0;
886
+ return upperComparison >= 0;
887
+ }
888
+
889
+ /** Compares manifest-bound values when their JavaScript representations are safely compatible. */
890
+ function compareIcebergValues(left: unknown, right: unknown): number | undefined {
891
+ if (left instanceof Uint8Array || right instanceof Uint8Array) return undefined;
892
+ if (left instanceof Date || right instanceof Date) {
893
+ if (!(left instanceof Date) || !(right instanceof Date)) return undefined;
894
+ return left.getTime() - right.getTime();
895
+ }
896
+ const numeric =
897
+ (typeof left === 'number' || typeof left === 'bigint') &&
898
+ (typeof right === 'number' || typeof right === 'bigint');
899
+ if (!numeric && typeof left !== typeof right) return undefined;
900
+ if (!['string', 'number', 'bigint', 'boolean'].includes(typeof left)) return undefined;
901
+ if (!['string', 'number', 'bigint', 'boolean'].includes(typeof right)) return undefined;
902
+ const comparableLeft = left as string | number | bigint | boolean;
903
+ const comparableRight = right as string | number | bigint | boolean;
904
+ return comparableLeft < comparableRight ? -1 : comparableLeft > comparableRight ? 1 : 0;
905
+ }
906
+
907
+ function isDataManifest(manifest: IcebergManifestFile): boolean {
908
+ return manifest.content === undefined || manifest.content === 0 || manifest.content === 'data';
909
+ }
910
+
911
+ /** Identifies delete manifests without depending on a particular Iceberg version. */
912
+ function isDeleteManifest(manifest: IcebergManifestFile): boolean {
913
+ return manifest.content === 1 || manifest.content === 'deletes' || manifest.content === 'delete';
914
+ }
915
+
916
+ /** Creates a Parquet data-file plan from an Iceberg manifest entry. */
917
+ function createIcebergParquetFile(
918
+ baseLocation: string,
919
+ dataFile: IcebergDataFile,
920
+ manifest: IcebergManifestFile,
921
+ snapshotId: number,
922
+ schemaId: number | undefined
923
+ ): IcebergParquetFile {
924
+ return {
925
+ data: resolveIcebergLocation(baseLocation, dataFile.file_path),
926
+ fileSize: dataFile.file_size_in_bytes,
927
+ recordCount: dataFile.record_count,
928
+ partition: normalizeIcebergMap(dataFile.partition),
929
+ lowerBounds: normalizeIcebergMap(dataFile.lower_bounds),
930
+ upperBounds: normalizeIcebergMap(dataFile.upper_bounds),
931
+ manifestPath: manifest.manifest_path,
932
+ partitionSpecId: manifest.partition_spec_id,
933
+ snapshotId,
934
+ schemaId,
935
+ dataSequenceNumber:
936
+ dataFile.data_sequence_number ??
937
+ (getIcebergRecordValue(dataFile, 'data_sequence_number') as number | undefined)
938
+ };
939
+ }
940
+
941
+ /** Creates a delete-file plan while retaining only metadata needed by a future delete reader. */
942
+ function createIcebergDeleteFile(
943
+ baseLocation: string,
944
+ dataFile: IcebergDataFile,
945
+ manifest: IcebergManifestFile,
946
+ snapshotId: number,
947
+ schemaId: number | undefined
948
+ ): IcebergDeleteFile {
949
+ return {
950
+ data: resolveIcebergLocation(baseLocation, dataFile.file_path),
951
+ format: dataFile.file_format,
952
+ content: dataFile.content ?? manifest.content,
953
+ referencedDataFile:
954
+ typeof dataFile.referenced_data_file === 'string'
955
+ ? resolveIcebergLocation(baseLocation, dataFile.referenced_data_file)
956
+ : undefined,
957
+ equalityFieldIds: normalizeNumberArray(
958
+ getIcebergRecordValue(dataFile, 'equality_ids') ??
959
+ getIcebergRecordValue(dataFile, 'equality-ids')
960
+ ),
961
+ fileSize: dataFile.file_size_in_bytes,
962
+ recordCount: dataFile.record_count,
963
+ partition: normalizeIcebergMap(dataFile.partition),
964
+ manifestPath: manifest.manifest_path,
965
+ partitionSpecId: manifest.partition_spec_id,
966
+ snapshotId,
967
+ schemaId,
968
+ dataSequenceNumber:
969
+ dataFile.data_sequence_number ??
970
+ (getIcebergRecordValue(dataFile, 'data_sequence_number') as number | undefined)
971
+ };
972
+ }
973
+
974
+ function isDeletedManifestEntry(entry: Record<string, unknown>): boolean {
975
+ return entry.status === 2 || entry.status === 'deleted' || entry.status === 'DELETE';
976
+ }
977
+
978
+ function resolveIcebergLocation(baseLocation: string, childLocation: string): string {
979
+ if (/^(?:s3a?):\/\//i.test(childLocation)) return resolveS3Location(childLocation);
980
+ if (/^[a-z][a-z\d+.-]*:/i.test(childLocation)) return childLocation;
981
+ try {
982
+ const baseUrl = new URL(baseLocation.endsWith('/') ? baseLocation : `${baseLocation}/`);
983
+ return normalizeS3Location(new URL(childLocation, baseUrl).toString());
984
+ } catch {
985
+ return normalizeS3Location(
986
+ `${baseLocation.replace(/\/+$/, '')}/${childLocation.replace(/^\/+/, '')}`
987
+ );
988
+ }
989
+ }
990
+
991
+ /** Maps S3 URI forms used in table metadata to browser-fetchable virtual-host-neutral URLs. */
992
+ function normalizeS3Location(location: string): string {
993
+ return /^(?:s3a?):\/\//i.test(location) ? resolveS3Location(location) : location;
994
+ }
995
+
996
+ /** Resolves an S3 or S3A URI through the anonymous S3 HTTPS endpoint. */
997
+ function resolveS3Location(location: string): string {
998
+ const match = location.match(/^s3a?:\/\/([^/]+)\/(.*)$/i);
999
+ if (!match) return location;
1000
+ return `https://s3.amazonaws.com/${match[1]}/${match[2]}`;
1001
+ }
1002
+
1003
+ function validateIcebergTableMetadata(metadata: IcebergTableMetadata): void {
1004
+ if (!metadata || typeof metadata !== 'object') {
1005
+ throw new Error('Iceberg metadata must be a JSON object');
1006
+ }
1007
+ if (![1, 2, 3].includes(metadata['format-version'])) {
1008
+ throw new Error(
1009
+ `Unsupported Iceberg metadata format version: ${String(metadata['format-version'])}`
1010
+ );
1011
+ }
1012
+ if (typeof metadata.location !== 'string' || metadata.location.length === 0) {
1013
+ throw new Error('Iceberg metadata location must be a non-empty string');
1014
+ }
1015
+ if (metadata.snapshots !== undefined && !Array.isArray(metadata.snapshots)) {
1016
+ throw new Error('Iceberg metadata snapshots must be an array');
1017
+ }
1018
+ }
1019
+
1020
+ function combineAbortSignals(
1021
+ signal: AbortSignal | undefined,
1022
+ closeSignal: AbortSignal,
1023
+ controller: AbortController
1024
+ ): {signal: AbortSignal; dispose: () => void} {
1025
+ const signals = [signal, closeSignal].filter((candidate): candidate is AbortSignal =>
1026
+ Boolean(candidate)
1027
+ );
1028
+ const abort = () => controller.abort();
1029
+ for (const candidate of signals) {
1030
+ if (candidate.aborted) controller.abort();
1031
+ else candidate.addEventListener('abort', abort, {once: true});
1032
+ }
1033
+ return {
1034
+ signal: controller.signal,
1035
+ dispose: () => signals.forEach(candidate => candidate.removeEventListener('abort', abort))
1036
+ };
1037
+ }