lakeql 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.
package/dist/index.js ADDED
@@ -0,0 +1 @@
1
+ export { AggregationBuilder, CacheApiCache, ERROR_CODES, IcebergRestCatalog, IcebergTable, IcebergUnsupportedCatalog, LaQLError, Lake, MemoryCache, MemoryCheckpointAdapter, MemoryObjectStore, MemorySpillAdapter, ObjectStoreIcebergCommitCatalog, PACKAGE, ParquetScanAdapter, QueryBuilder, QueryResult, ResumedQuery, advanceTaskCheckpoint, and, applyIcebergDeletes, assertBookmarkMatches, asyncBufferFromStore, bboxMayIntersect, between, broadcastJoin, buildBBoxIndex, buildMinMaxIndex, cacheApiCache, classifyPredicate, col, createBookmark, createParquetLake as createLake, createOutputManifest, createOutputManifestFromCheckpoints, createParquetLake, createParquetTableAs, createTaskManifest, deserializeAggregateOperatorState, deserializeSortOperatorState, deserializeTopKOperatorState, encodeJsonLine, eq, evaluate, fingerprint, fn, gt, gte, icebergGlueCatalog, icebergNessieCatalog, icebergRestCatalog, ilike, isIn, isLaQLError, isNotNull, isNull, jsonSafeValue, like, lit, loadIcebergTable, loadIcebergTableFromObjectStore, loadIcebergTableFromRest, loadTable, lookupJoin, lt, lte, matches, memoryCache, memoryCheckpointAdapter, memorySpillAdapter, memoryStore, ne, not, notIn, or, parquetScanner, parseHivePartitions, parseJsonQuery, partitionedParquetOutputEntries, planFiles, planRowGroups, planRowGroupsFromMetadata, pruneFilesWithIndex, readControlSignal, readIcebergParquetDeletes, readOutputManifest, readParquetMetadata, readParquetObjectBatches, readParquetObjects, rejectUnsupportedParquetSchema, rowGroupMayMatch, scanBatches, scanPlannedIcebergRows, scanRows, serializeAggregateOperatorState, serializeSortOperatorState, serializeTopKOperatorState, signPaginationToken, stableStringify, throwIfAborted, transitionTaskCheckpoint, verifyPaginationToken, withObjectStoreReadControls, writeOutputManifest, writeParquet, writePartitionedParquet, writePartitionedParquetTask } from './chunk-VRJ72DGA.js';
package/dist/node.d.ts ADDED
@@ -0,0 +1,27 @@
1
+ import { ObjectInfo, ObjectStore, ConditionalObjectStore } from './index.js';
2
+ export { AggregateExpr, AggregateGroupSnapshot, AggregateOp, AggregateOperatorState, AggregateOptions, AggregateResult, AggregateSnapshotValue, AggregateSpec, AggregateStateSnapshot, AggregationBuilder, ApplyIcebergDeletesOptions, BBoxIndex, BetweenExpr, Bookmark, BookmarkInit, BookmarkPosition, BookmarkQuery, BroadcastJoinOptions, CacheAdapter, CacheApiCache, CacheApiCacheOptions, CacheEntry, CallExpr, CheckpointAdapter, CheckpointStore, Clock, ColumnExpr, ColumnInput, CompareExpr, CompareOp, ConditionalPutOptions, CreateParquetTableAsOptions, CreateParquetTableAsQuery, CreateParquetTableAsResult, CsvStreamOptions, DecodedIcebergDeletes, DecodedIcebergParquetDeletes, ERROR_CODES, EngineFilePlan, EngineTable, ErrorDetails, ExplainJson, ExplainResult, Expr, IcebergAppendFile, IcebergAppendOptions, IcebergAppendOutputManifestOptions, IcebergAppendResult, IcebergCatalog, IcebergCommitCatalog, IcebergCommitInput, IcebergCommitResult, IcebergDeleteFile, IcebergDeletionVector, IcebergEnginePlan, IcebergEngineTable, IcebergEqualityDelete, IcebergField, IcebergGlueCatalogOptions, IcebergNessieCatalogOptions, IcebergParquetDeleteFile, IcebergParquetDeleteFileContent, IcebergPartitionField, IcebergPartitionSpec, IcebergPlan, IcebergPositionDelete, IcebergReadMode, IcebergRestCatalog, IcebergRestCatalogOptions, IcebergRowBatch, IcebergSortOrder, IcebergTable, IcebergTableIdentifier, IcebergUnsupportedCatalog, IdGenerator, InExpr, IndexPruneResult, IndexValue, InsertValidationRules, JoinType, JsonExpr, JsonOrderByTerm, JsonQueryV1, LaQLError, LaQLErrorCode, Lake, LakeConfig, LikeExpr, ListOptions, LiteralExpr, LoadIcebergEngineTableOptions, LoadIcebergTableFromObjectStoreOptions, LoadIcebergTableFromRestOptions, LoadIcebergTableOptions, LoadParquetEngineTableOptions, LoadTableOptions, LockAdapter, LogHook, LogicalExpr, LookupJoinFunction, LookupJoinOptions, Manifest, ManifestDeleteFile, ManifestFile, MemoryCache, MemoryCheckpointAdapter, MemoryObjectStore, MemorySpillAdapter, MemorySpillAdapterOptions, MetadataFile, MetricsHook, MinMaxColumnIndex, NotExpr, NullCheckExpr, ObjectHead, ObjectStoreIcebergCommitCatalog, ObjectStoreReadControls, OperatorSnapshotValue, OrderByTerm, OutputManifest, OutputManifestEntry, PACKAGE, ParquetEnginePlan, ParquetEngineTable, ParquetLakeConfig, ParquetMetadata, ParquetRowBatch, ParquetRowGroupPlan, ParquetScanAdapter, PartitionedParquetOutputEntryOptions, PathQueryInit, PlanIcebergFilesOptions, PlanParquetRowGroupsOptions, PlannedIcebergFile, PlannedParquetRowGroup, PredicatePlan, PredicatePlanOptions, ProjectIcebergRowOptions, PutOptions, QueryBudget, QueryBuilder, QueryPolicy, QueryPolicyContext, QueryResult, QueryRunOptions, QueryStats, QueueAdapter, ReadParquetBatchOptions, ReadParquetOptions, ResumableBatchOptions, ResumedQuery, Row, RuntimeSubstrate, Scalar, ScanAdapter, ScanBatch, ScanEngineOptions, ScanOptions, ScanPlannedIcebergRowsOptions, ScanTaskPlan, ScanTaskPlanOptions, SidecarFileIndex, SliceOptions, SliceResult, Snapshot, SortOperatorState, SortOptions, SortResult, SortRunState, SpillAdapter, SpillRef, SpillUsage, SqlBoolean, TaskCheckpoint, TaskInput, TaskManifest, TaskManifestTask, TaskState, TaskTransitionInput, TopKOperatorState, TopKOptions, TopKResult, ValueInput, WriteParquetOptions, WriteParquetRowsOptions, WritePartitionedParquetFile, WritePartitionedParquetResult, WritePartitionedParquetTaskOptions, WritePartitionedParquetTaskResult, advanceTaskCheckpoint, and, applyIcebergDeletes, assertBookmarkMatches, asyncBufferFromStore, bboxMayIntersect, between, broadcastJoin, buildBBoxIndex, buildMinMaxIndex, cacheApiCache, classifyPredicate, col, createBookmark, createLake, createOutputManifest, createOutputManifestFromCheckpoints, createLake as createParquetLake, createParquetTableAs, createTaskManifest, deserializeAggregateOperatorState, deserializeSortOperatorState, deserializeTopKOperatorState, encodeJsonLine, eq, evaluate, fingerprint, fn, gt, gte, icebergGlueCatalog, icebergNessieCatalog, icebergRestCatalog, ilike, isIn, isLaQLError, isNotNull, isNull, jsonSafeValue, like, lit, loadIcebergTable, loadIcebergTableFromObjectStore, loadIcebergTableFromRest, loadTable, lookupJoin, lt, lte, matches, memoryCache, memoryCheckpointAdapter, memorySpillAdapter, memoryStore, ne, not, notIn, or, parquetScanner, parseHivePartitions, parseJsonQuery, partitionedParquetOutputEntries, planFiles, planRowGroups, planRowGroupsFromMetadata, pruneFilesWithIndex, readControlSignal, readIcebergParquetDeletes, readOutputManifest, readParquetMetadata, readParquetObjectBatches, readParquetObjects, rejectUnsupportedParquetSchema, rowGroupMayMatch, scanBatches, scanPlannedIcebergRows, scanRows, serializeAggregateOperatorState, serializeSortOperatorState, serializeTopKOperatorState, signPaginationToken, stableStringify, throwIfAborted, transitionTaskCheckpoint, verifyPaginationToken, withObjectStoreReadControls, writeOutputManifest, writeParquet, writePartitionedParquet, writePartitionedParquetTask } from './index.js';
3
+ import 'hyparquet/src/types.js';
4
+ import 'hyparquet';
5
+ import 'hyparquet-writer';
6
+
7
+ interface HttpStoreOptions {
8
+ baseUrl: string;
9
+ fetch?: typeof fetch;
10
+ headers?: HeadersInit;
11
+ objects?: ObjectInfo[];
12
+ }
13
+ declare function httpStore(options: HttpStoreOptions): ObjectStore;
14
+
15
+ interface S3StoreOptions {
16
+ endpoint: string;
17
+ bucket: string;
18
+ region: string;
19
+ accessKeyId: string;
20
+ secretAccessKey: string;
21
+ sessionToken?: string;
22
+ fetch?: typeof fetch;
23
+ now?: () => Date;
24
+ }
25
+ declare function s3Store(options: S3StoreOptions): ConditionalObjectStore;
26
+
27
+ export { ConditionalObjectStore, ObjectInfo, ObjectStore, httpStore, s3Store };
package/dist/node.js ADDED
@@ -0,0 +1,422 @@
1
+ import { LaQLError } from './chunk-VRJ72DGA.js';
2
+ export { AggregationBuilder, CacheApiCache, ERROR_CODES, IcebergRestCatalog, IcebergTable, IcebergUnsupportedCatalog, LaQLError, Lake, MemoryCache, MemoryCheckpointAdapter, MemoryObjectStore, MemorySpillAdapter, ObjectStoreIcebergCommitCatalog, PACKAGE, ParquetScanAdapter, QueryBuilder, QueryResult, ResumedQuery, advanceTaskCheckpoint, and, applyIcebergDeletes, assertBookmarkMatches, asyncBufferFromStore, bboxMayIntersect, between, broadcastJoin, buildBBoxIndex, buildMinMaxIndex, cacheApiCache, classifyPredicate, col, createBookmark, createParquetLake as createLake, createOutputManifest, createOutputManifestFromCheckpoints, createParquetLake, createParquetTableAs, createTaskManifest, deserializeAggregateOperatorState, deserializeSortOperatorState, deserializeTopKOperatorState, encodeJsonLine, eq, evaluate, fingerprint, fn, gt, gte, icebergGlueCatalog, icebergNessieCatalog, icebergRestCatalog, ilike, isIn, isLaQLError, isNotNull, isNull, jsonSafeValue, like, lit, loadIcebergTable, loadIcebergTableFromObjectStore, loadIcebergTableFromRest, loadTable, lookupJoin, lt, lte, matches, memoryCache, memoryCheckpointAdapter, memorySpillAdapter, memoryStore, ne, not, notIn, or, parquetScanner, parseHivePartitions, parseJsonQuery, partitionedParquetOutputEntries, planFiles, planRowGroups, planRowGroupsFromMetadata, pruneFilesWithIndex, readControlSignal, readIcebergParquetDeletes, readOutputManifest, readParquetMetadata, readParquetObjectBatches, readParquetObjects, rejectUnsupportedParquetSchema, rowGroupMayMatch, scanBatches, scanPlannedIcebergRows, scanRows, serializeAggregateOperatorState, serializeSortOperatorState, serializeTopKOperatorState, signPaginationToken, stableStringify, throwIfAborted, transitionTaskCheckpoint, verifyPaginationToken, withObjectStoreReadControls, writeOutputManifest, writeParquet, writePartitionedParquet, writePartitionedParquetTask } from './chunk-VRJ72DGA.js';
3
+ import { AwsClient } from 'aws4fetch';
4
+ import { XMLParser } from 'fast-xml-parser';
5
+
6
+ // ../http/dist/index.js
7
+ function httpStore(options) {
8
+ return new HttpObjectStore(options);
9
+ }
10
+ var HttpObjectStore = class {
11
+ baseUrl;
12
+ fetchImpl;
13
+ headers;
14
+ objects;
15
+ constructor(options) {
16
+ this.baseUrl = options.baseUrl.endsWith("/") ? options.baseUrl : `${options.baseUrl}/`;
17
+ this.fetchImpl = options.fetch ?? fetch.bind(globalThis);
18
+ this.headers = options.headers;
19
+ this.objects = options.objects;
20
+ }
21
+ async get(path) {
22
+ const response = await this.fetchPath(path, { method: "GET" });
23
+ if (response.status === 404)
24
+ return null;
25
+ assertOk(response, path);
26
+ return new Uint8Array(await response.arrayBuffer());
27
+ }
28
+ async getRange(path, range) {
29
+ if (range.offset < 0 || range.length < 0) {
30
+ throw new LaQLError("LAQL_OBJECT_NOT_FOUND", `Invalid range for ${path}`, { path, range });
31
+ }
32
+ const response = await this.fetchPath(path, {
33
+ method: "GET",
34
+ headers: { Range: `bytes=${range.offset}-${range.offset + range.length - 1}` }
35
+ });
36
+ assertOk(response, path);
37
+ const bytes = new Uint8Array(await response.arrayBuffer());
38
+ if (response.status !== 206 && bytes.length > range.length) {
39
+ return bytes.subarray(range.offset, range.offset + range.length);
40
+ }
41
+ return bytes;
42
+ }
43
+ async put(path, body, options) {
44
+ const headers = new Headers(this.headers);
45
+ if (options?.contentType)
46
+ headers.set("content-type", options.contentType);
47
+ const response = await this.fetchPath(path, { method: "PUT", headers, body: bodyInit(body) });
48
+ assertOk(response, path);
49
+ }
50
+ async delete(path) {
51
+ const response = await this.fetchPath(path, { method: "DELETE" });
52
+ assertOk(response, path);
53
+ }
54
+ async *list(prefix, options) {
55
+ if (!this.objects) {
56
+ throw new LaQLError("LAQL_UNSUPPORTED_PUSHDOWN", "HTTP store list requires an object index", {
57
+ prefix
58
+ });
59
+ }
60
+ let emitted = 0;
61
+ for (const object of this.objects.filter((candidate) => candidate.path.startsWith(prefix)).sort((a, b) => a.path.localeCompare(b.path))) {
62
+ if (options?.limit !== void 0 && emitted >= options.limit)
63
+ return;
64
+ yield object;
65
+ emitted += 1;
66
+ }
67
+ }
68
+ async head(path) {
69
+ const response = await this.fetchPath(path, {
70
+ method: "GET",
71
+ headers: { Range: "bytes=0-0" }
72
+ });
73
+ if (response.status === 404)
74
+ return null;
75
+ assertOk(response, path);
76
+ await response.arrayBuffer().catch(() => void 0);
77
+ const total = parseContentRangeTotal(response.headers.get("content-range"));
78
+ const contentLength = response.headers.get("content-length");
79
+ const size = total ?? (contentLength ? Number(contentLength) : Number.NaN);
80
+ if (!Number.isFinite(size)) {
81
+ throw new LaQLError("LAQL_OBJECT_NOT_FOUND", `Missing size for ${path}`, { path });
82
+ }
83
+ const head = { size };
84
+ const etag = response.headers.get("etag");
85
+ const lastModified = response.headers.get("last-modified");
86
+ const contentType = response.headers.get("content-type");
87
+ if (etag !== null)
88
+ head.etag = etag;
89
+ if (lastModified !== null)
90
+ head.lastModified = new Date(lastModified);
91
+ if (contentType !== null)
92
+ head.contentType = contentType;
93
+ return head;
94
+ }
95
+ fetchPath(path, init) {
96
+ const headers = new Headers(this.headers);
97
+ if (init.headers) {
98
+ for (const [key, value] of new Headers(init.headers))
99
+ headers.set(key, value);
100
+ }
101
+ return this.fetchImpl(this.urlForPath(path), { ...init, headers });
102
+ }
103
+ urlForPath(path) {
104
+ const base = new URL(this.baseUrl);
105
+ const url = new URL(encodeObjectPath(path), base);
106
+ if (url.origin !== base.origin || !url.pathname.startsWith(base.pathname)) {
107
+ throw new LaQLError("LAQL_VALIDATION_ERROR", `Object path escapes HTTP base URL: ${path}`, {
108
+ path,
109
+ baseUrl: this.baseUrl
110
+ });
111
+ }
112
+ return url;
113
+ }
114
+ };
115
+ function encodeObjectPath(path) {
116
+ if (/^(?:[a-z][a-z0-9+.-]*:)?\/\//iu.test(path) || path.startsWith("/")) {
117
+ throw new LaQLError("LAQL_VALIDATION_ERROR", `Object path must be relative: ${path}`, {
118
+ path
119
+ });
120
+ }
121
+ if (path === "")
122
+ return "";
123
+ return path.split("/").map((segment) => {
124
+ let decoded;
125
+ try {
126
+ decoded = decodeURIComponent(segment);
127
+ } catch {
128
+ throw new LaQLError("LAQL_VALIDATION_ERROR", `Object path has invalid encoding: ${path}`, {
129
+ path
130
+ });
131
+ }
132
+ if (decoded === "." || decoded === "..") {
133
+ throw new LaQLError("LAQL_VALIDATION_ERROR", `Object path contains traversal: ${path}`, {
134
+ path
135
+ });
136
+ }
137
+ return encodeURIComponent(segment);
138
+ }).join("/");
139
+ }
140
+ function parseContentRangeTotal(header) {
141
+ if (!header)
142
+ return void 0;
143
+ const match = /\/(\d+)\s*$/.exec(header);
144
+ if (!match)
145
+ return void 0;
146
+ const total = Number(match[1]);
147
+ return Number.isFinite(total) ? total : void 0;
148
+ }
149
+ function assertOk(response, path) {
150
+ if (response.ok || response.status === 206)
151
+ return;
152
+ if (response.status === 404) {
153
+ throw new LaQLError("LAQL_OBJECT_NOT_FOUND", `No object at ${path}`, { path });
154
+ }
155
+ throw new LaQLError("LAQL_OBJECT_NOT_FOUND", `HTTP object request failed for ${path}`, {
156
+ path,
157
+ status: response.status
158
+ });
159
+ }
160
+ function bodyInit(body) {
161
+ if (body instanceof Uint8Array) {
162
+ const copy = new Uint8Array(body.byteLength);
163
+ copy.set(body);
164
+ return copy.buffer;
165
+ }
166
+ return body;
167
+ }
168
+ function s3Store(options) {
169
+ return new S3ObjectStore(options);
170
+ }
171
+ var S3ObjectStore = class {
172
+ options;
173
+ fetchImpl;
174
+ now;
175
+ aws;
176
+ constructor(options) {
177
+ this.options = options;
178
+ this.fetchImpl = options.fetch ?? fetch;
179
+ this.now = options.now ?? (() => /* @__PURE__ */ new Date());
180
+ const awsOptions = {
181
+ accessKeyId: options.accessKeyId,
182
+ secretAccessKey: options.secretAccessKey,
183
+ region: options.region,
184
+ service: "s3",
185
+ retries: 0
186
+ };
187
+ if (options.sessionToken !== void 0)
188
+ awsOptions.sessionToken = options.sessionToken;
189
+ this.aws = new AwsClient(awsOptions);
190
+ }
191
+ async get(path) {
192
+ const response = await this.request("GET", path);
193
+ if (response.status === 404)
194
+ return null;
195
+ assertOk2(response, path);
196
+ return new Uint8Array(await response.arrayBuffer());
197
+ }
198
+ async getRange(path, range) {
199
+ const response = await this.request("GET", path, {
200
+ Range: `bytes=${range.offset}-${range.offset + range.length - 1}`
201
+ });
202
+ assertOk2(response, path);
203
+ return new Uint8Array(await response.arrayBuffer());
204
+ }
205
+ async put(path, body, options) {
206
+ const headers = {};
207
+ if (options?.contentType)
208
+ headers["content-type"] = options.contentType;
209
+ const response = await this.request("PUT", path, headers, body);
210
+ assertOk2(response, path);
211
+ }
212
+ async conditionalPut(path, body, options) {
213
+ const headers = {};
214
+ if (options.contentType)
215
+ headers["content-type"] = options.contentType;
216
+ if (options.expectedEtag === null)
217
+ headers["if-none-match"] = "*";
218
+ else
219
+ headers["if-match"] = options.expectedEtag;
220
+ const response = await this.request("PUT", path, headers, body);
221
+ if (response.status === 409 || response.status === 412)
222
+ return false;
223
+ assertOk2(response, path);
224
+ return true;
225
+ }
226
+ async delete(path) {
227
+ const response = await this.request("DELETE", path);
228
+ assertOk2(response, path);
229
+ }
230
+ async *list(prefix, options) {
231
+ let continuationToken;
232
+ let emitted = 0;
233
+ do {
234
+ const query = new URLSearchParams({ "list-type": "2", prefix });
235
+ if (options?.limit !== void 0)
236
+ query.set("max-keys", String(options.limit - emitted));
237
+ if (options?.delimiter !== void 0)
238
+ query.set("delimiter", options.delimiter);
239
+ if (continuationToken !== void 0)
240
+ query.set("continuation-token", continuationToken);
241
+ const response = await this.request("GET", "", {}, void 0, query);
242
+ assertOk2(response, prefix);
243
+ const result = parseListObjectsV2(await response.text());
244
+ for (const object of result.objects) {
245
+ if (options?.limit !== void 0 && emitted >= options.limit)
246
+ return;
247
+ yield object;
248
+ emitted += 1;
249
+ }
250
+ continuationToken = result.nextContinuationToken;
251
+ } while (continuationToken !== void 0 && (options?.limit === void 0 || emitted < options.limit));
252
+ }
253
+ async head(path) {
254
+ const response = await this.request("HEAD", path);
255
+ if (response.status === 404)
256
+ return null;
257
+ assertOk2(response, path);
258
+ const contentLength = response.headers.get("content-length");
259
+ if (contentLength === null) {
260
+ throw new LaQLError("LAQL_OBJECT_NOT_FOUND", `Missing S3 content-length for ${path}`, {
261
+ path
262
+ });
263
+ }
264
+ const head = { size: Number(contentLength) };
265
+ const etag = response.headers.get("etag");
266
+ const contentType = response.headers.get("content-type");
267
+ const lastModified = response.headers.get("last-modified");
268
+ if (etag !== null)
269
+ head.etag = etag;
270
+ if (contentType !== null)
271
+ head.contentType = contentType;
272
+ if (lastModified !== null)
273
+ head.lastModified = new Date(lastModified);
274
+ return head;
275
+ }
276
+ async request(method, path, headers = {}, body, query = new URLSearchParams()) {
277
+ const url = new URL(`${encodeURIComponent(this.options.bucket)}/${encodeObjectPath2(path)}`, ensureSlash(this.options.endpoint));
278
+ url.search = query.toString();
279
+ const signRequest = {
280
+ method,
281
+ url,
282
+ headers,
283
+ region: this.options.region,
284
+ accessKeyId: this.options.accessKeyId,
285
+ secretAccessKey: this.options.secretAccessKey,
286
+ now: this.now()
287
+ };
288
+ if (this.options.sessionToken !== void 0)
289
+ signRequest.sessionToken = this.options.sessionToken;
290
+ const requestBody = body === void 0 ? void 0 : bodyInit2(body);
291
+ const signed = await signS3Request(signRequest, this.aws, requestBody);
292
+ const init = { method, headers: signed };
293
+ if (requestBody !== void 0)
294
+ init.body = requestBody;
295
+ return this.fetchImpl(url, init);
296
+ }
297
+ };
298
+ async function signS3Request(request, client = s3SignerClient(request), body) {
299
+ const headers = new Headers(request.headers);
300
+ if (!headers.has("x-amz-content-sha256")) {
301
+ headers.set("x-amz-content-sha256", "UNSIGNED-PAYLOAD");
302
+ }
303
+ const init = {
304
+ method: request.method,
305
+ headers,
306
+ aws: {
307
+ datetime: timestamp(request.now)
308
+ }
309
+ };
310
+ if (body !== void 0)
311
+ init.body = body;
312
+ const signed = await client.sign(request.url, init);
313
+ return signed.headers;
314
+ }
315
+ function s3SignerClient(request) {
316
+ const options = {
317
+ accessKeyId: request.accessKeyId,
318
+ secretAccessKey: request.secretAccessKey,
319
+ region: request.region,
320
+ service: "s3",
321
+ retries: 0
322
+ };
323
+ if (request.sessionToken !== void 0)
324
+ options.sessionToken = request.sessionToken;
325
+ return new AwsClient(options);
326
+ }
327
+ var listObjectsParser = new XMLParser({
328
+ ignoreAttributes: true,
329
+ parseTagValue: false,
330
+ trimValues: true
331
+ });
332
+ function parseListObjectsV2(xml) {
333
+ const parsed = listObjectsParser.parse(xml);
334
+ const result = parsed.ListBucketResult ?? {};
335
+ const objects = [];
336
+ for (const content of arrayOf(result.Contents)) {
337
+ const key = stringValue(content.Key);
338
+ const size = Number(stringValue(content.Size));
339
+ if (!key || !Number.isFinite(size))
340
+ continue;
341
+ const info = { path: key, size };
342
+ const etag = stringValue(content.ETag);
343
+ const lastModified = stringValue(content.LastModified);
344
+ if (etag)
345
+ info.etag = etag;
346
+ if (lastModified)
347
+ info.lastModified = new Date(lastModified);
348
+ objects.push(info);
349
+ }
350
+ const nextContinuationToken = isTrue(result.IsTruncated) ? stringValue(result.NextContinuationToken) : "";
351
+ return {
352
+ objects,
353
+ ...nextContinuationToken ? { nextContinuationToken } : {}
354
+ };
355
+ }
356
+ function arrayOf(value) {
357
+ if (value === void 0 || value === null)
358
+ return [];
359
+ return Array.isArray(value) ? value : [value];
360
+ }
361
+ function stringValue(value) {
362
+ if (value === void 0 || value === null)
363
+ return "";
364
+ return String(value);
365
+ }
366
+ function isTrue(value) {
367
+ return value === true || String(value).toLowerCase() === "true";
368
+ }
369
+ function ensureSlash(value) {
370
+ return value.endsWith("/") ? value : `${value}/`;
371
+ }
372
+ function encodeObjectPath2(path) {
373
+ if (/^(?:[a-z][a-z0-9+.-]*:)?\/\//iu.test(path) || path.startsWith("/")) {
374
+ throw new LaQLError("LAQL_VALIDATION_ERROR", `Object path must be relative: ${path}`, {
375
+ path
376
+ });
377
+ }
378
+ if (path === "")
379
+ return "";
380
+ return path.split("/").map((segment) => {
381
+ let decoded;
382
+ try {
383
+ decoded = decodeURIComponent(segment);
384
+ } catch {
385
+ throw new LaQLError("LAQL_VALIDATION_ERROR", `Object path has invalid encoding: ${path}`, {
386
+ path
387
+ });
388
+ }
389
+ if (decoded === "." || decoded === "..") {
390
+ throw new LaQLError("LAQL_VALIDATION_ERROR", `Object path contains traversal: ${path}`, {
391
+ path
392
+ });
393
+ }
394
+ return encodeURIComponent(segment);
395
+ }).join("/");
396
+ }
397
+ function assertOk2(response, path) {
398
+ if (response.ok || response.status === 206)
399
+ return;
400
+ if (response.status === 404) {
401
+ throw new LaQLError("LAQL_OBJECT_NOT_FOUND", `No object at ${path}`, { path });
402
+ }
403
+ throw new LaQLError("LAQL_OBJECT_NOT_FOUND", `S3 request failed for ${path}`, {
404
+ path,
405
+ status: response.status
406
+ });
407
+ }
408
+ function timestamp(date) {
409
+ return date.toISOString().replace(/[:-]|\.\d{3}/gu, "");
410
+ }
411
+ function bodyInit2(body) {
412
+ if (body instanceof Uint8Array)
413
+ return arrayBuffer(body);
414
+ return body;
415
+ }
416
+ function arrayBuffer(bytes) {
417
+ const copy = new Uint8Array(bytes.byteLength);
418
+ copy.set(bytes);
419
+ return copy.buffer;
420
+ }
421
+
422
+ export { httpStore, s3Store };
package/package.json ADDED
@@ -0,0 +1,72 @@
1
+ {
2
+ "name": "lakeql",
3
+ "version": "0.1.0",
4
+ "description": "LaQL: lightweight TypeScript query engine for Iceberg + Parquet on object storage",
5
+ "keywords": [
6
+ "lakehouse",
7
+ "parquet",
8
+ "iceberg",
9
+ "query-engine",
10
+ "object-storage"
11
+ ],
12
+ "author": "Erik Aronesty",
13
+ "license": "MIT",
14
+ "type": "module",
15
+ "main": "./dist/index.js",
16
+ "types": "./dist/index.d.ts",
17
+ "exports": {
18
+ ".": {
19
+ "types": "./dist/index.d.ts",
20
+ "default": "./dist/index.js"
21
+ },
22
+ "./cloudflare": {
23
+ "types": "./dist/cloudflare.d.ts",
24
+ "default": "./dist/cloudflare.js"
25
+ },
26
+ "./node": {
27
+ "types": "./dist/node.d.ts",
28
+ "default": "./dist/node.js"
29
+ }
30
+ },
31
+ "files": [
32
+ "dist",
33
+ "README.md",
34
+ "LICENSE"
35
+ ],
36
+ "scripts": {
37
+ "build": "tsup",
38
+ "prepack": "pnpm -w build && pnpm --filter lakeql build"
39
+ },
40
+ "repository": {
41
+ "type": "git",
42
+ "url": "https://github.com/earonesty/laql.git",
43
+ "directory": "packages/laql"
44
+ },
45
+ "homepage": "https://laql.dev",
46
+ "engines": {
47
+ "node": ">=22"
48
+ },
49
+ "publishConfig": {
50
+ "access": "public"
51
+ },
52
+ "dependencies": {
53
+ "@turf/boolean-contains": "^7.2.0",
54
+ "@turf/boolean-intersects": "^7.2.0",
55
+ "avsc": "^5.7.9",
56
+ "aws4fetch": "^1.0.20",
57
+ "fast-xml-parser": "^5.9.0",
58
+ "h3-js": "^4.4.0",
59
+ "hyparquet": "^1.26.0",
60
+ "hyparquet-writer": "^0.15.6"
61
+ },
62
+ "devDependencies": {
63
+ "@laql/core": "workspace:*",
64
+ "@laql/fixtures": "workspace:*",
65
+ "@laql/http": "workspace:*",
66
+ "@laql/iceberg": "workspace:*",
67
+ "@laql/parquet": "workspace:*",
68
+ "@laql/r2": "workspace:*",
69
+ "@laql/s3": "workspace:*",
70
+ "tsup": "^8.5.0"
71
+ }
72
+ }