@gscdump/lakehouse 0.1.0

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.
@@ -0,0 +1,549 @@
1
+ import { AsyncBuffer } from "./hyparquet.mjs";
2
+ import { Writer } from "hyparquet-writer/src/types.js";
3
+ interface WriterOptions {
4
+ /**
5
+ * If `'*'`, the writer must create the object only if it does not already
6
+ * exist (S3 conditional write: `If-None-Match: *`). On collision the
7
+ * underlying `finish()` rejects with an error whose `status` is 412 (or 409
8
+ * on some providers). The HTTP/S3 `urlResolver` translates this to the
9
+ * `If-None-Match` header. Other resolvers may honor or ignore it.
10
+ */
11
+ ifNoneMatch?: '*';
12
+ }
13
+ interface Resolver {
14
+ reader: (path: string, byteLength?: number) => AsyncBuffer | Promise<AsyncBuffer>;
15
+ writer?: (path: string, options?: WriterOptions) => Writer;
16
+ deleter?: (path: string) => Promise<void>;
17
+ }
18
+ type Lister = (path: string) => Promise<string[]>;
19
+ /** Catalogs */
20
+ interface RestCatalogContext {
21
+ type: 'rest';
22
+ url: string;
23
+ prefix: string;
24
+ defaults: Record<string, string>;
25
+ overrides: Record<string, string>;
26
+ requestInit?: RequestInit;
27
+ }
28
+ interface FileCatalog {
29
+ type: 'file';
30
+ resolver: Resolver;
31
+ lister?: Lister;
32
+ /**
33
+ * Opt in to S3-safe metadata commits: every `vN.metadata.json` (the
34
+ * initial create and every subsequent commit) is written with
35
+ * `If-None-Match: *` and `version-hint.text` is best-effort. High-level
36
+ * write functions retry on 412/409 by reloading the latest metadata and
37
+ * re-staging. `icebergCreateTable` and `icebergTransaction` do not retry.
38
+ * Default false preserves backwards-compatible (overwrite) behavior.
39
+ */
40
+ conditionalCommits?: boolean;
41
+ }
42
+ type Catalog = RestCatalogContext | FileCatalog;
43
+ interface TableIdentifier {
44
+ namespace: string[];
45
+ name: string;
46
+ }
47
+ interface LoadTableResponse {
48
+ metadataLocation?: string;
49
+ metadata: TableMetadata;
50
+ config: Record<string, string>;
51
+ }
52
+ interface TableMetadata {
53
+ 'format-version': number;
54
+ 'table-uuid': string;
55
+ location: string;
56
+ 'last-sequence-number': number; // missing in V1, required in V2+
57
+ 'last-updated-ms': number;
58
+ 'last-column-id': number;
59
+ 'current-schema-id': number; // optional in V1, required in V2+
60
+ schemas: Schema[]; // optional in V1, required in V2+
61
+ 'default-spec-id': number; // optional in V1, required in V2+
62
+ 'partition-specs': PartitionSpec[]; // optional in V1, required in V2+
63
+ 'last-partition-id': number; // optional in V1, required in V2+
64
+ properties?: Record<string, string>;
65
+ 'current-snapshot-id'?: number | bigint;
66
+ snapshots?: Snapshot[];
67
+ 'snapshot-log'?: SnapshotLog[];
68
+ 'metadata-log'?: MetadataLog[];
69
+ 'sort-orders': SortOrder[]; // optional in V1, required in V2+
70
+ 'default-sort-order-id': number; // optional in V1, required in V2+
71
+ refs?: Record<string, SnapshotRef>;
72
+ statistics?: TableStatistics[];
73
+ 'partition-statistics'?: PartitionStatistics[];
74
+ 'next-row-id'?: number | bigint; // required in V3
75
+ 'encryption-keys'?: EncryptionKey[]; // V3
76
+ }
77
+ interface Schema {
78
+ type: 'struct';
79
+ 'schema-id': number;
80
+ 'identifier-field-ids'?: number[];
81
+ fields: Field[];
82
+ }
83
+ interface Field {
84
+ id: number;
85
+ name: string;
86
+ required: boolean;
87
+ type: IcebergType;
88
+ doc?: string;
89
+ 'initial-default'?: any;
90
+ 'write-default'?: any;
91
+ }
92
+ type IcebergType = 'unknown' | 'boolean' | 'int' | 'long' | 'float' | 'double' | 'date' | 'time' | 'timestamp' | 'timestamptz' | 'timestamp_ns' | 'timestamptz_ns' | 'string' | 'uuid' | `fixed[${number}]` | 'binary' | `decimal(${number},${number})` | `decimal(${number}, ${number})` | 'variant' | 'geometry' | `geometry(${string})` | 'geography' | `geography(${string})` | IcebergNestedType;
93
+ type IcebergNestedType = Schema | {
94
+ type: 'list';
95
+ 'element-id': number;
96
+ 'element-required': boolean;
97
+ element: IcebergType;
98
+ } | {
99
+ type: 'map';
100
+ 'key-id': number;
101
+ key: IcebergType;
102
+ 'value-id': number;
103
+ 'value-required': boolean;
104
+ value: IcebergType;
105
+ };
106
+ interface PartitionSpec {
107
+ 'spec-id': number;
108
+ fields: PartitionField[];
109
+ }
110
+ interface PartitionField {
111
+ 'source-id'?: number;
112
+ 'source-ids'?: number[];
113
+ 'field-id': number;
114
+ name: string;
115
+ transform: PartitionTransform;
116
+ }
117
+ type PartitionTransform = 'identity' | `bucket[${number}]` | `truncate[${number}]` | 'year' | 'month' | 'day' | 'hour' | 'void' | string;
118
+ interface PartitionStatistics {
119
+ 'snapshot-id': bigint;
120
+ 'statistics-path': string;
121
+ 'file-size-in-bytes': bigint;
122
+ }
123
+ interface SortOrder {
124
+ 'order-id': number;
125
+ 'fields': SortField[];
126
+ }
127
+ interface SortField {
128
+ transform: string;
129
+ 'source-id'?: number;
130
+ 'source-ids'?: number[]; // V3
131
+ 'direction': 'asc' | 'desc';
132
+ 'null-order': 'nulls-first' | 'nulls-last';
133
+ }
134
+ interface Snapshot {
135
+ 'snapshot-id': number | bigint;
136
+ 'parent-snapshot-id'?: number | bigint;
137
+ 'sequence-number': number;
138
+ 'timestamp-ms': number;
139
+ 'manifest-list': string;
140
+ manifests?: Manifest[];
141
+ summary: {
142
+ // spec: "value of these fields should be of string type"
143
+ operation: string; // 'spark.app.id'?: string
144
+ 'added-data-files'?: string;
145
+ 'added-records'?: string;
146
+ 'deleted-data-files'?: string;
147
+ 'deleted-records'?: string;
148
+ 'removed-files-size'?: string;
149
+ 'added-delete-files'?: string;
150
+ 'removed-delete-files'?: string;
151
+ 'added-position-deletes'?: string;
152
+ 'removed-position-deletes'?: string;
153
+ 'added-equality-deletes'?: string;
154
+ 'removed-equality-deletes'?: string;
155
+ 'added-dvs'?: string;
156
+ 'removed-dvs'?: string;
157
+ 'added-files-size'?: string;
158
+ 'changed-partition-count'?: string;
159
+ 'total-records'?: string;
160
+ 'total-files-size'?: string;
161
+ 'total-data-files'?: string;
162
+ 'total-delete-files'?: string;
163
+ 'total-position-deletes'?: string;
164
+ 'total-equality-deletes'?: string;
165
+ };
166
+ 'schema-id'?: number;
167
+ 'first-row-id'?: number; // V3
168
+ 'added-rows'?: number; // V3
169
+ 'key-id'?: string; // V3
170
+ }
171
+ interface TableStatistics {
172
+ 'snapshot-id': number | bigint;
173
+ 'statistics-path': string;
174
+ 'file-size-in-bytes': bigint;
175
+ 'file-footer-size-in-bytes': bigint;
176
+ }
177
+ interface SnapshotLog {
178
+ 'timestamp-ms': number;
179
+ 'snapshot-id': number | bigint;
180
+ }
181
+ interface SnapshotRef {
182
+ 'snapshot-id': number | bigint;
183
+ type: 'branch' | 'tag';
184
+ 'min-snapshots-to-keep'?: number;
185
+ 'max-snapshot-age-ms'?: number;
186
+ 'max-ref-age-ms'?: number;
187
+ }
188
+ interface EncryptionKey {
189
+ 'key-id': string;
190
+ 'key-metadata': string;
191
+ }
192
+ /**
193
+ * Iceberg REST `TableRequirement`s recognized by `checkRequirements`.
194
+ */
195
+ interface MetadataLog {
196
+ 'timestamp-ms': number;
197
+ 'metadata-file': string;
198
+ }
199
+ interface Manifest {
200
+ manifest_path: string;
201
+ manifest_length: bigint;
202
+ partition_spec_id: number;
203
+ content: 0 | 1; // 0=data, 1=deletes
204
+ sequence_number?: bigint;
205
+ min_sequence_number?: bigint;
206
+ added_snapshot_id: bigint;
207
+ added_files_count: number;
208
+ existing_files_count: number;
209
+ deleted_files_count: number;
210
+ added_rows_count: bigint;
211
+ existing_rows_count: bigint;
212
+ deleted_rows_count: bigint;
213
+ partitions?: FieldSummary[]; // key_metadata?: unknown
214
+ first_row_id?: bigint | number;
215
+ }
216
+ interface ManifestEntry {
217
+ status: 0 | 1 | 2; // 0=existing, 1=added, 2=deleted
218
+ snapshot_id?: bigint;
219
+ sequence_number?: bigint;
220
+ file_sequence_number?: bigint;
221
+ partition_spec_id?: number;
222
+ data_file: DataFile;
223
+ }
224
+ interface FieldSummary {
225
+ contains_null: boolean;
226
+ contains_nan?: boolean | null;
227
+ lower_bound?: Uint8Array | null;
228
+ upper_bound?: Uint8Array | null;
229
+ }
230
+ interface DataFile {
231
+ content: 0 | 1 | 2; // 0=data, 1=position_delete, 2=equality_delete
232
+ file_path: string;
233
+ file_format: 'avro' | 'orc' | 'parquet' | 'puffin';
234
+ partition: Record<string, unknown>; // keyed by partition-field name in Avro
235
+ record_count: bigint;
236
+ file_size_in_bytes: bigint;
237
+ column_sizes?: Record<number, bigint>;
238
+ value_counts?: Record<number, bigint>;
239
+ null_value_counts?: Record<number, bigint>;
240
+ nan_value_counts?: Record<number, bigint>;
241
+ lower_bounds?: Record<number, unknown>;
242
+ upper_bounds?: Record<number, unknown>; // key_metadata?: string
243
+ split_offsets?: bigint[];
244
+ equality_ids?: number[];
245
+ sort_order_id?: number;
246
+ first_row_id?: bigint | number;
247
+ referenced_data_file?: string;
248
+ content_offset?: bigint;
249
+ content_size_in_bytes?: bigint;
250
+ }
251
+ /**
252
+ * Build a SigV4-signing `Resolver` for private S3-compatible buckets (AWS S3,
253
+ * Cloudflare R2, MinIO, etc.). Signs every request with AWS Signature V4
254
+ * using static credentials. Works in browsers and Node via the Web Crypto API.
255
+ *
256
+ * Credentials are taken as inputs; profile/STS/IMDS chains are out of scope.
257
+ * For Iceberg REST catalogs that vend per-table credentials (R2, AWS Glue),
258
+ * pass the `s3.*` keys from `restCatalogLoadCredentials` or `LoadTable.config`.
259
+ *
260
+ * Accepts paths as `s3://bucket/key`, `s3a://bucket/key`, or full https URLs.
261
+ *
262
+ * @param {object} options
263
+ * @param {string} options.accessKeyId
264
+ * @param {string} options.secretAccessKey
265
+ * @param {string} [options.sessionToken] - For temporary credentials (STS/vended).
266
+ * @param {string} options.region - e.g. 'us-east-1', or 'auto' for R2.
267
+ * @param {string} [options.endpoint] - HTTPS endpoint root for non-AWS providers
268
+ * (e.g. `https://<account>.r2.cloudflarestorage.com`). Defaults to AWS S3.
269
+ * @param {boolean} [options.pathStyle] - When true, URLs are
270
+ * `<endpoint>/<bucket>/<key>`; when false (default), virtual-hosted-style
271
+ * `<bucket>.<endpoint-host>/<key>`. R2 requires true.
272
+ * @returns {Resolver}
273
+ */
274
+ declare function s3SignedResolver({
275
+ accessKeyId,
276
+ secretAccessKey,
277
+ sessionToken,
278
+ region,
279
+ endpoint,
280
+ pathStyle
281
+ }: {
282
+ accessKeyId: string;
283
+ secretAccessKey: string;
284
+ sessionToken?: string | undefined;
285
+ region: string;
286
+ endpoint?: string | undefined;
287
+ pathStyle?: boolean | undefined;
288
+ }): Resolver;
289
+ /**
290
+ * Returns manifest entries for a snapshot. Defaults to the current snapshot;
291
+ * pass `snapshotId` to time-travel to a prior snapshot in the metadata's
292
+ * snapshot log.
293
+ *
294
+ * @import {Resolver, TableMetadata, Manifest, ManifestEntry} from '../src/types.js'
295
+ * @typedef {{ url: string, entries: ManifestEntry[] }[]} ManifestList
296
+ * @param {object} options
297
+ * @param {TableMetadata} options.metadata
298
+ * @param {Resolver} [options.resolver]
299
+ * @param {number | bigint} [options.snapshotId] - Optional snapshot id; defaults to `current-snapshot-id`.
300
+ * @returns {Promise<ManifestList>}
301
+ */
302
+ declare function icebergManifests({
303
+ metadata,
304
+ resolver,
305
+ snapshotId,
306
+ partitionFilter
307
+ }: {
308
+ metadata: TableMetadata;
309
+ resolver?: Resolver | undefined;
310
+ snapshotId?: number | bigint | undefined;
311
+ partitionFilter?: ManifestPartitionFilter | undefined;
312
+ }): Promise<ManifestList>;
313
+ /**
314
+ * Predicate applied to each manifest's manifest-list `partitions` field-summary
315
+ * array before entry fetch. Return `false` to skip the manifest's entry fetch.
316
+ */
317
+ type ManifestPartitionFilter = (partitions: Manifest['partitions'], partitionSpecId: number, manifest: Manifest) => boolean;
318
+ /**
319
+ * Returns manifest entries for a snapshot. Defaults to the current snapshot;
320
+ * pass `snapshotId` to time-travel to a prior snapshot in the metadata's
321
+ * snapshot log.
322
+ */
323
+ type ManifestList = {
324
+ url: string;
325
+ entries: ManifestEntry[];
326
+ }[];
327
+ /**
328
+ * Append rows to a table in one call: load metadata, stage the parquet writes
329
+ * + manifest + new snapshot, commit through the catalog.
330
+ *
331
+ * @param {object} options
332
+ * @param {Catalog} options.catalog
333
+ * @param {string | string[]} [options.namespace] - REST catalog only.
334
+ * @param {string} [options.table] - REST catalog only.
335
+ * @param {string} [options.tableUrl] - File catalog only.
336
+ * @param {Resolver} [options.resolver]
337
+ * @param {Record<string, any>[]} options.records
338
+ * @param {number} [options.sortOrderId] - Sort order id to apply; defaults to the table default.
339
+ * @returns {Promise<TableMetadata>}
340
+ */
341
+ declare function icebergAppend({
342
+ catalog,
343
+ namespace,
344
+ table,
345
+ tableUrl,
346
+ resolver,
347
+ records,
348
+ sortOrderId,
349
+ snapshotProperties
350
+ }: {
351
+ catalog: Catalog;
352
+ namespace?: string | string[] | undefined;
353
+ table?: string | undefined;
354
+ tableUrl?: string | undefined;
355
+ resolver?: Resolver | undefined;
356
+ records: Record<string, any>[];
357
+ sortOrderId?: number | undefined;
358
+ snapshotProperties?: Record<string, string> | undefined;
359
+ }): Promise<TableMetadata>;
360
+ /**
361
+ * Create a new table. REST: delegates to the catalog's create endpoint.
362
+ * File: writes the initial `v1.metadata.json` and `version-hint.text` under
363
+ * `tableUrl` via `catalog.resolver`.
364
+ *
365
+ * @param {object} options
366
+ * @param {Catalog} options.catalog
367
+ * @param {string | string[]} [options.namespace] - REST catalog only.
368
+ * @param {string} [options.table] - REST catalog only.
369
+ * @param {string} [options.tableUrl] - File catalog only; also passed as `location` for REST.
370
+ * @param {Schema} [options.schema]
371
+ * @param {PartitionSpec} [options.partitionSpec]
372
+ * @param {SortOrder} [options.sortOrder]
373
+ * @param {Record<string, string>} [options.properties]
374
+ * @param {2 | 3} [options.formatVersion] - File catalog only.
375
+ * @param {boolean} [options.stageCreate] - REST catalog only.
376
+ * @returns {Promise<TableMetadata>}
377
+ */
378
+ declare function icebergCreateTable({
379
+ catalog,
380
+ namespace,
381
+ table,
382
+ tableUrl,
383
+ schema,
384
+ partitionSpec,
385
+ sortOrder,
386
+ properties,
387
+ formatVersion,
388
+ stageCreate
389
+ }: {
390
+ catalog: Catalog;
391
+ namespace?: string | string[] | undefined;
392
+ table?: string | undefined;
393
+ tableUrl?: string | undefined;
394
+ schema?: Schema | undefined;
395
+ partitionSpec?: PartitionSpec | undefined;
396
+ sortOrder?: SortOrder | undefined;
397
+ properties?: Record<string, string> | undefined;
398
+ formatVersion?: 2 | 3 | undefined;
399
+ stageCreate?: boolean | undefined;
400
+ }): Promise<TableMetadata>;
401
+ /**
402
+ * Drop a table. REST: delegates to the catalog's drop endpoint, forwarding
403
+ * `purgeRequested`. File: lists `metadata/` (and `data/` when `purgeRequested`)
404
+ * via `lister` and deletes each file via `catalog.resolver.deleter`. File
405
+ * purges do not recurse into partition subdirectories.
406
+ *
407
+ * @param {object} options
408
+ * @param {Catalog} options.catalog
409
+ * @param {string | string[]} [options.namespace] - REST catalog only.
410
+ * @param {string} [options.table] - REST catalog only.
411
+ * @param {string} [options.tableUrl] - File catalog only.
412
+ * @param {Lister} [options.lister] - File catalog only; required to enumerate files to delete.
413
+ * @param {boolean} [options.purgeRequested] - REST: forwarded to the server. File: also delete `data/`.
414
+ * @returns {Promise<void>}
415
+ */
416
+ declare function icebergDropTable({
417
+ catalog,
418
+ namespace,
419
+ table,
420
+ tableUrl,
421
+ lister,
422
+ purgeRequested
423
+ }: {
424
+ catalog: Catalog;
425
+ namespace?: string | string[] | undefined;
426
+ table?: string | undefined;
427
+ tableUrl?: string | undefined;
428
+ lister?: Lister | undefined;
429
+ purgeRequested?: boolean | undefined;
430
+ }): Promise<void>;
431
+ /**
432
+ * Iceberg REST Catalog client.
433
+ *
434
+ * Plain async functions over a stateless context object — no classes.
435
+ * The catalog client never imports from the read path; callers glue the
436
+ * two together by passing `metadata` and `metadata.location` from
437
+ * `restCatalogLoadTable` into `icebergRead`.
438
+ *
439
+ * @import {LoadTableResponse, PartitionSpec, RestCatalogContext, Schema, SortOrder, StorageCredential, TableIdentifier, TableMetadata, TableRequirement, TableUpdate} from '../../src/types.js'
440
+ */
441
+ /**
442
+ * Connect to a REST catalog by fetching `/v1/config`.
443
+ * Returns a frozen context object that holds the prefix, defaults, overrides
444
+ * and the user-supplied requestInit (for auth) for use in subsequent calls.
445
+ *
446
+ * @param {object} options
447
+ * @param {string} options.url - catalog base URL, with or without trailing slash
448
+ * @param {string} [options.warehouse] - optional warehouse query param sent to /v1/config
449
+ * @param {RequestInit} [options.requestInit] - fetch options (e.g. Authorization header)
450
+ * @returns {Promise<RestCatalogContext>}
451
+ */
452
+ declare function restCatalogConnect({
453
+ url,
454
+ warehouse,
455
+ requestInit
456
+ }: {
457
+ url: string;
458
+ warehouse?: string | undefined;
459
+ requestInit?: RequestInit | undefined;
460
+ }): Promise<RestCatalogContext>;
461
+ /**
462
+ * List tables within a namespace.
463
+ * Follows pagination (`next-page-token`) until exhausted.
464
+ *
465
+ * @param {RestCatalogContext} ctx
466
+ * @param {object} options
467
+ * @param {string | string[]} options.namespace
468
+ * @returns {Promise<TableIdentifier[]>}
469
+ */
470
+ declare function restCatalogListTables(ctx: RestCatalogContext, {
471
+ namespace
472
+ }: {
473
+ namespace: string | string[];
474
+ }): Promise<TableIdentifier[]>;
475
+ /**
476
+ * Load a single table. Returns the inline TableMetadata, the metadata
477
+ * file location, and any per-table config the server returned.
478
+ *
479
+ * The returned `metadata` and `metadata.location` can be passed directly
480
+ * into `icebergRead({ tableUrl: metadata.location, metadata })`.
481
+ *
482
+ * @param {RestCatalogContext} ctx
483
+ * @param {object} options
484
+ * @param {string | string[]} options.namespace
485
+ * @param {string} options.table
486
+ * @returns {Promise<LoadTableResponse>}
487
+ */
488
+ declare function restCatalogLoadTable(ctx: RestCatalogContext, {
489
+ namespace,
490
+ table
491
+ }: {
492
+ namespace: string | string[];
493
+ table: string;
494
+ }): Promise<LoadTableResponse>;
495
+ /**
496
+ * Create a namespace. Returns the namespace as the server stored it (which may
497
+ * include defaulted properties).
498
+ *
499
+ * @param {RestCatalogContext} ctx
500
+ * @param {object} options
501
+ * @param {string | string[]} options.namespace
502
+ * @param {Record<string, string>} [options.properties]
503
+ * @returns {Promise<{namespace: string[], properties: Record<string, string>}>}
504
+ */
505
+ declare function restCatalogCreateNamespace(ctx: RestCatalogContext, {
506
+ namespace,
507
+ properties
508
+ }: {
509
+ namespace: string | string[];
510
+ properties?: Record<string, string> | undefined;
511
+ }): Promise<{
512
+ namespace: string[];
513
+ properties: Record<string, string>;
514
+ }>;
515
+ /**
516
+ * Wrap a `Resolver` so reads of the same path share one HTTP fetch and
517
+ * subsequent range reads share one in-memory buffer. Writes and deletes
518
+ * through the same resolver invalidate the cache entry for their path on
519
+ * success, so a commit pipeline (`icebergAppend` → reload metadata) sees the
520
+ * new bytes without manual invalidation.
521
+ *
522
+ * - `reader(path)` is memoized by path. The returned buffer is passed through
523
+ * `cachedAsyncBuffer` so range reads within a single file are also deduped.
524
+ * `byteLength` is a fetch hint and not part of the cache key — the bytes
525
+ * are the same either way.
526
+ * - `writer(path).finish()` invalidates the cache entry only when the
527
+ * underlying finish resolves; a rejected finish (e.g. an `If-None-Match: *`
528
+ * collision returning 412/409) leaves the cached bytes intact, since the
529
+ * server-side object hasn't changed.
530
+ * - `deleter(path)` invalidates the cache entry on success.
531
+ * - `writer` and `deleter` are omitted when the base resolver omits them, so
532
+ * wrapping a read-only resolver still yields a read-only resolver.
533
+ *
534
+ * Iceberg writes are almost entirely create-new-path (data parquets, manifest
535
+ * avros, snapshot avros, vN.metadata.json all live at fresh paths per
536
+ * commit). Only `version-hint.text` and equivalent catalog-pointer files are
537
+ * truly mutated in place, so path-level invalidation is sufficient to keep
538
+ * single-process write-then-read pipelines consistent.
539
+ *
540
+ * Cross-process freshness is out of scope: a reader in process B does not
541
+ * see writes committed by process A through a different cache. Use a
542
+ * short-lived resolver, an external coordination layer, or wrap with TTL /
543
+ * conditional-GET revalidation if you need that.
544
+ *
545
+ * @param {Resolver} base
546
+ * @returns {Resolver}
547
+ */
548
+ declare function cachingResolver(base: Resolver): Resolver;
549
+ export { cachingResolver, icebergAppend, icebergCreateTable, icebergDropTable, icebergManifests, restCatalogConnect, restCatalogCreateNamespace, restCatalogListTables, restCatalogLoadTable, s3SignedResolver };