lakeql 0.1.7 → 0.1.8
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/bin.js +1 -1
- package/dist/{chunk-BFLGC6Y5.js → chunk-5K5JMJ2M.js} +396 -70
- package/dist/{chunk-RZL45ZSN.js → chunk-MXGEAVHL.js} +363 -16
- package/dist/cloudflare.d.ts +20 -3
- package/dist/cloudflare.js +102 -3
- package/dist/index.d.ts +83 -7
- package/dist/index.js +2 -2
- package/dist/node.d.ts +28 -5
- package/dist/node.js +175 -19
- package/package.json +10 -8
package/dist/node.js
CHANGED
|
@@ -1,10 +1,110 @@
|
|
|
1
|
-
|
|
2
|
-
export {
|
|
1
|
+
import { objectStoreJsonCache } from './chunk-5K5JMJ2M.js';
|
|
2
|
+
export { IcebergRestCatalog, IcebergTable, IcebergUnsupportedCatalog, InMemoryRowsScanner, InMemoryRowsStore, ObjectStoreIcebergCommitCatalog, ObjectStoreJsonCache, PACKAGE, applyIcebergDeletes, createInMemoryLake, icebergGlueCatalog, icebergNessieCatalog, icebergRestCatalog, inMemoryRowsScanner, loadIcebergTable, loadIcebergTableFromObjectStore, loadIcebergTableFromRest, loadTable, objectStoreJsonCache, planFiles, scanBatches, scanPlannedIcebergRows, scanRows, vectorHashJoin } from './chunk-5K5JMJ2M.js';
|
|
3
|
+
export { AggregationBuilder, CacheApiCache, Lake, MemoryCache, MemoryCheckpointAdapter, MemoryObjectStore, MemorySpillAdapter, ParquetScanAdapter, QueryBuilder, QueryResult, ResumedQuery, SharedMemoryCache, add, advanceTaskCheckpoint, aggregateParquetGroupTask, aggregateParquetGroupTasks, aggregateParquetGroupTasksBatch, aggregateParquetTask, aggregateParquetTasks, and, assertBookmarkMatches, asyncBufferFromStore, batchExprValues, batchFromColumns, batchFromVectors, bboxMayIntersect, between, broadcastJoin, buildBBoxIndex, buildMinMaxIndex, cacheApiCache, cachedObjectStore, classifyPredicate, col, concatBatches, createBookmark, createParquetLake as createLake, createOutputManifest, createOutputManifestFromCheckpoints, createParquetLake, createParquetTableAs, createTaskManifest, createVectorAggregateStates, createVectorGroupByState, deserializeAggregateOperatorState, deserializeSortOperatorState, deserializeTopKOperatorState, div, enforceVectorGroupByBudget, eq, fanInWorkUnits, finalizeVectorAggregateStates, finalizeVectorGroupByBatch, finalizeVectorGroupByRows, fingerprint, fn, gatherBatch, getOrCreateVectorGroup, gt, gte, ilike, isIn, isNotNull, isNull, jsonWorkUnitBoundary, like, lit, lookupJoin, lt, lte, materializeBatchRows, materializeSelectedBatchRows, memoryCache, memoryCheckpointAdapter, memorySpillAdapter, memoryStore, mergeVectorAggregateStateSnapshots, mergeVectorAggregateStates, mergeVectorGroupByStates, mod, mul, ne, not, notIn, or, parquetScanner, parseHivePartitions, parseJsonQuery, partitionedParquetOutputEntries, planParquetTaskWorkUnits, planRowGroups, planRowGroupsFromMetadata, predicateSelection, pruneFilesWithIndex, readControlSignal, readIcebergParquetDeletes, readOutputManifest, readParquetColumnBatches, readParquetMetadata, readParquetObjectBatches, readParquetObjects, rejectUnsupportedParquetSchema, restoreVectorAggregateStates, restoreVectorGroupByState, rowGroupMayMatch, rowGroupMustMatch, scalarVectorValue, scanParquetTaskBatches, scanParquetTaskColumnBatches, selectedRowCount, selectedRowIndices, serializeAggregateOperatorState, serializeSortOperatorState, serializeTopKOperatorState, signPaginationToken, snapshotVectorAggregateStates, snapshotVectorGroupByState, stableStringify, sub, throwIfAborted, transitionTaskCheckpoint, tryPredicateSelection, updateVectorAggregateStateValue, updateVectorAggregateStates, updateVectorGroupAggregateValue, updateVectorGroupByState, uriObjectStore, vectorAggregateBatch, vectorFromValues, vectorGroupByBatch, vectorLength, vectorOrderByBatch, vectorProjectBatch, vectorSortIndices, vectorTopKBatch, vectorTopKIndices, vectorValue, verifyPaginationToken, withObjectStoreReadControls, writeOutputManifest, writeParquet, writePartitionedParquet, writePartitionedParquetTask } from './chunk-MXGEAVHL.js';
|
|
3
4
|
import { LakeqlError } from './chunk-TFD5RFKB.js';
|
|
4
5
|
export { ERROR_CODES, LakeqlError, TimestampValue, bboxIntersects, compareTimestampValues, encodeJsonLine, ensureGeoBackendForExprs, envelopeFromGeometry, envelopeOf, evaluate, isLakeqlError, isTimestampValue, jsonSafeValue, loadGeoBackend, matches, parseGeometry, requireGeoBackend, setGeoBackend, timestampEpochForUnit, timestampFromEpoch, timestampToIsoString, timestampValueFromIso, toGeometry } from './chunk-TFD5RFKB.js';
|
|
6
|
+
import { readFile, mkdir, writeFile, rm } from 'fs/promises';
|
|
7
|
+
import { join } from 'path';
|
|
5
8
|
import { AwsClient } from 'aws4fetch';
|
|
6
9
|
import { XMLParser } from 'fast-xml-parser';
|
|
7
10
|
|
|
11
|
+
function fsJsonCache(options) {
|
|
12
|
+
return new FsJsonCache(options);
|
|
13
|
+
}
|
|
14
|
+
var FsJsonCache = class {
|
|
15
|
+
root;
|
|
16
|
+
prefix;
|
|
17
|
+
ttlMs;
|
|
18
|
+
now;
|
|
19
|
+
space;
|
|
20
|
+
constructor(options) {
|
|
21
|
+
this.root = options.root;
|
|
22
|
+
this.prefix = normalizedPrefix(options.prefix ?? "lakeql");
|
|
23
|
+
this.ttlMs = options.ttlMs;
|
|
24
|
+
this.now = options.now ?? Date.now;
|
|
25
|
+
this.space = options.space;
|
|
26
|
+
}
|
|
27
|
+
async get(key) {
|
|
28
|
+
const path = this.pathFor(key);
|
|
29
|
+
let bytes;
|
|
30
|
+
try {
|
|
31
|
+
bytes = await readFile(path);
|
|
32
|
+
} catch (cause) {
|
|
33
|
+
if (isNodeError(cause) && cause.code === "ENOENT")
|
|
34
|
+
return void 0;
|
|
35
|
+
throw cause;
|
|
36
|
+
}
|
|
37
|
+
const parsed = JSON.parse(bytes.toString("utf8"));
|
|
38
|
+
if (!isStoredFsJsonCacheEntry(parsed)) {
|
|
39
|
+
throw new LakeqlError("LAKEQL_CATALOG_ERROR", `Invalid filesystem cache entry at ${path}`, {
|
|
40
|
+
path
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
if (parsed.expiresAt !== void 0 && parsed.expiresAt <= this.now()) {
|
|
44
|
+
await this.delete(key);
|
|
45
|
+
return void 0;
|
|
46
|
+
}
|
|
47
|
+
const entry = { value: parsed.value };
|
|
48
|
+
if (parsed.expiresAt !== void 0)
|
|
49
|
+
entry.expiresAt = parsed.expiresAt;
|
|
50
|
+
return entry;
|
|
51
|
+
}
|
|
52
|
+
async set(key, entry) {
|
|
53
|
+
const path = this.pathFor(key);
|
|
54
|
+
await mkdir(join(this.root, this.prefix), { recursive: true });
|
|
55
|
+
const stored = { value: entry.value };
|
|
56
|
+
if (entry.expiresAt !== void 0) {
|
|
57
|
+
stored.expiresAt = entry.expiresAt;
|
|
58
|
+
} else if (this.ttlMs !== void 0) {
|
|
59
|
+
stored.expiresAt = this.now() + this.ttlMs;
|
|
60
|
+
}
|
|
61
|
+
await writeFile(path, jsonCacheValue(stored, key, this.space));
|
|
62
|
+
}
|
|
63
|
+
async delete(key) {
|
|
64
|
+
await rm(this.pathFor(key), { force: true });
|
|
65
|
+
}
|
|
66
|
+
pathFor(key) {
|
|
67
|
+
if (key.length === 0) {
|
|
68
|
+
throw new LakeqlError("LAKEQL_VALIDATION_ERROR", "filesystem cache key must not be empty");
|
|
69
|
+
}
|
|
70
|
+
return join(this.root, this.prefix, `${encodeURIComponent(key)}.json`);
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
function normalizedPrefix(prefix) {
|
|
74
|
+
const parts = prefix.split("/").filter((part) => part.length > 0);
|
|
75
|
+
if (parts.length === 0 || parts.some((part) => part === "." || part === "..")) {
|
|
76
|
+
throw new LakeqlError("LAKEQL_VALIDATION_ERROR", "filesystem cache prefix must be relative", {
|
|
77
|
+
prefix
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
return parts.join("/");
|
|
81
|
+
}
|
|
82
|
+
function isStoredFsJsonCacheEntry(value) {
|
|
83
|
+
return typeof value === "object" && value !== null && "value" in value;
|
|
84
|
+
}
|
|
85
|
+
function jsonCacheValue(value, key, space) {
|
|
86
|
+
if (value.value === void 0) {
|
|
87
|
+
throw new LakeqlError("LAKEQL_TYPE_ERROR", "filesystem JSON cache value is not JSON serializable", { key });
|
|
88
|
+
}
|
|
89
|
+
try {
|
|
90
|
+
const json = JSON.stringify(value, void 0, space);
|
|
91
|
+
if (json === void 0) {
|
|
92
|
+
throw new LakeqlError("LAKEQL_TYPE_ERROR", "filesystem JSON cache value is not JSON serializable", { key });
|
|
93
|
+
}
|
|
94
|
+
return json;
|
|
95
|
+
} catch (cause) {
|
|
96
|
+
if (cause instanceof LakeqlError)
|
|
97
|
+
throw cause;
|
|
98
|
+
throw new LakeqlError("LAKEQL_TYPE_ERROR", "filesystem JSON cache value is not JSON serializable", {
|
|
99
|
+
key,
|
|
100
|
+
cause
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
function isNodeError(value) {
|
|
105
|
+
return value instanceof Error && "code" in value;
|
|
106
|
+
}
|
|
107
|
+
|
|
8
108
|
// ../http/dist/index.js
|
|
9
109
|
function httpStore(options) {
|
|
10
110
|
return new HttpObjectStore(options);
|
|
@@ -173,25 +273,26 @@ function bodyInit(body) {
|
|
|
173
273
|
function s3Store(options) {
|
|
174
274
|
return new S3ObjectStore(options);
|
|
175
275
|
}
|
|
276
|
+
function s3JsonCache(options) {
|
|
277
|
+
return objectStoreJsonCache({
|
|
278
|
+
store: s3Store(options),
|
|
279
|
+
prefix: options.prefix,
|
|
280
|
+
...options.ttlMs !== void 0 ? { ttlMs: options.ttlMs } : {}
|
|
281
|
+
});
|
|
282
|
+
}
|
|
176
283
|
var S3ObjectStore = class {
|
|
177
284
|
options;
|
|
178
285
|
fetchImpl;
|
|
179
286
|
now;
|
|
180
|
-
|
|
287
|
+
credentialsSnapshot;
|
|
288
|
+
credentialsPromise;
|
|
181
289
|
constructor(options) {
|
|
182
290
|
this.options = options;
|
|
183
291
|
this.fetchImpl = options.fetch ?? fetch;
|
|
184
292
|
this.now = options.now ?? (() => /* @__PURE__ */ new Date());
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
region: options.region,
|
|
189
|
-
service: "s3",
|
|
190
|
-
retries: 0
|
|
191
|
-
};
|
|
192
|
-
if (options.sessionToken !== void 0)
|
|
193
|
-
awsOptions.sessionToken = options.sessionToken;
|
|
194
|
-
this.aws = new AwsClient(awsOptions);
|
|
293
|
+
if (options.credentials === void 0) {
|
|
294
|
+
this.credentialsSnapshot = staticCredentials(options);
|
|
295
|
+
}
|
|
195
296
|
}
|
|
196
297
|
async get(path) {
|
|
197
298
|
const response = await this.request("GET", path);
|
|
@@ -286,19 +387,41 @@ var S3ObjectStore = class {
|
|
|
286
387
|
url,
|
|
287
388
|
headers,
|
|
288
389
|
region: this.options.region,
|
|
289
|
-
|
|
290
|
-
secretAccessKey: this.options.secretAccessKey,
|
|
390
|
+
...await this.currentCredentials(),
|
|
291
391
|
now: this.now()
|
|
292
392
|
};
|
|
293
|
-
if (this.options.sessionToken !== void 0)
|
|
294
|
-
signRequest.sessionToken = this.options.sessionToken;
|
|
295
393
|
const requestBody = body === void 0 ? void 0 : bodyInit2(body);
|
|
296
|
-
const signed = await signS3Request(signRequest,
|
|
394
|
+
const signed = await signS3Request(signRequest, void 0, requestBody);
|
|
297
395
|
const init = { method, headers: signed };
|
|
298
396
|
if (requestBody !== void 0)
|
|
299
397
|
init.body = requestBody;
|
|
300
398
|
return this.fetchImpl(url, init);
|
|
301
399
|
}
|
|
400
|
+
async currentCredentials() {
|
|
401
|
+
if (this.options.credentials === void 0) {
|
|
402
|
+
if (this.credentialsSnapshot === void 0)
|
|
403
|
+
this.credentialsSnapshot = staticCredentials(this.options);
|
|
404
|
+
return this.credentialsSnapshot;
|
|
405
|
+
}
|
|
406
|
+
if (this.credentialsSnapshot !== void 0 && !credentialsNeedRefresh(this.credentialsSnapshot, this.now(), this.credentialRefreshWindowMs())) {
|
|
407
|
+
return this.credentialsSnapshot;
|
|
408
|
+
}
|
|
409
|
+
if (this.credentialsPromise === void 0) {
|
|
410
|
+
this.credentialsPromise = Promise.resolve(this.options.credentials()).then((credentials) => {
|
|
411
|
+
const normalized = validateCredentials(credentials);
|
|
412
|
+
this.credentialsSnapshot = normalized;
|
|
413
|
+
this.credentialsPromise = void 0;
|
|
414
|
+
return normalized;
|
|
415
|
+
}).catch((cause) => {
|
|
416
|
+
this.credentialsPromise = void 0;
|
|
417
|
+
throw cause;
|
|
418
|
+
});
|
|
419
|
+
}
|
|
420
|
+
return await this.credentialsPromise;
|
|
421
|
+
}
|
|
422
|
+
credentialRefreshWindowMs() {
|
|
423
|
+
return this.options.credentialRefreshWindowMs ?? 3e5;
|
|
424
|
+
}
|
|
302
425
|
};
|
|
303
426
|
async function signS3Request(request, client = s3SignerClient(request), body) {
|
|
304
427
|
const headers = new Headers(request.headers);
|
|
@@ -329,6 +452,39 @@ function s3SignerClient(request) {
|
|
|
329
452
|
options.sessionToken = request.sessionToken;
|
|
330
453
|
return new AwsClient(options);
|
|
331
454
|
}
|
|
455
|
+
function staticCredentials(options) {
|
|
456
|
+
if (options.accessKeyId === void 0 || options.secretAccessKey === void 0) {
|
|
457
|
+
throw new LakeqlError("LAKEQL_VALIDATION_ERROR", "S3 credentials are required", {
|
|
458
|
+
bucket: options.bucket
|
|
459
|
+
});
|
|
460
|
+
}
|
|
461
|
+
return validateCredentials({
|
|
462
|
+
accessKeyId: options.accessKeyId,
|
|
463
|
+
secretAccessKey: options.secretAccessKey,
|
|
464
|
+
...options.sessionToken !== void 0 ? { sessionToken: options.sessionToken } : {}
|
|
465
|
+
});
|
|
466
|
+
}
|
|
467
|
+
function validateCredentials(credentials) {
|
|
468
|
+
const accessKeyId = credentials.accessKeyId.trim();
|
|
469
|
+
const secretAccessKey = credentials.secretAccessKey.trim();
|
|
470
|
+
if (accessKeyId === "" || secretAccessKey === "") {
|
|
471
|
+
throw new LakeqlError("LAKEQL_VALIDATION_ERROR", "S3 credentials are required");
|
|
472
|
+
}
|
|
473
|
+
const normalized = {
|
|
474
|
+
accessKeyId,
|
|
475
|
+
secretAccessKey
|
|
476
|
+
};
|
|
477
|
+
if (credentials.sessionToken !== void 0)
|
|
478
|
+
normalized.sessionToken = credentials.sessionToken;
|
|
479
|
+
if (credentials.expiresAt !== void 0)
|
|
480
|
+
normalized.expiresAt = credentials.expiresAt;
|
|
481
|
+
return normalized;
|
|
482
|
+
}
|
|
483
|
+
function credentialsNeedRefresh(credentials, now, refreshWindowMs) {
|
|
484
|
+
if (credentials.expiresAt === void 0)
|
|
485
|
+
return false;
|
|
486
|
+
return credentials.expiresAt.getTime() - now.getTime() <= refreshWindowMs;
|
|
487
|
+
}
|
|
332
488
|
var listObjectsParser = new XMLParser({
|
|
333
489
|
ignoreAttributes: true,
|
|
334
490
|
parseTagValue: false,
|
|
@@ -424,4 +580,4 @@ function arrayBuffer(bytes) {
|
|
|
424
580
|
return copy.buffer;
|
|
425
581
|
}
|
|
426
582
|
|
|
427
|
-
export { httpStore, s3Store };
|
|
583
|
+
export { fsJsonCache, httpStore, s3JsonCache, s3Store };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lakeql",
|
|
3
3
|
"sideEffects": false,
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.8",
|
|
5
5
|
"description": "lakeql: lightweight TypeScript query engine for Iceberg + Parquet on object storage",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"lakehouse",
|
|
@@ -55,6 +55,7 @@
|
|
|
55
55
|
"avsc": "^5.7.9",
|
|
56
56
|
"aws4fetch": "^1.0.20",
|
|
57
57
|
"fast-xml-parser": "^5.9.0",
|
|
58
|
+
"fzstd": "^0.1.1",
|
|
58
59
|
"h3-js": "^4.4.0",
|
|
59
60
|
"hyparquet": "^1.26.0",
|
|
60
61
|
"hyparquet-writer": "^0.15.6"
|
|
@@ -62,13 +63,14 @@
|
|
|
62
63
|
"devDependencies": {
|
|
63
64
|
"tsup": "^8.5.0",
|
|
64
65
|
"lakeql-fixtures": "0.0.1",
|
|
65
|
-
"lakeql-core": "0.1.
|
|
66
|
-
"lakeql-
|
|
67
|
-
"lakeql-iceberg": "0.0.
|
|
68
|
-
"lakeql-parquet": "0.0.
|
|
69
|
-
"lakeql-
|
|
70
|
-
"lakeql-
|
|
71
|
-
"lakeql-
|
|
66
|
+
"lakeql-core": "0.1.3",
|
|
67
|
+
"lakeql-fs": "0.0.2",
|
|
68
|
+
"lakeql-iceberg": "0.0.5",
|
|
69
|
+
"lakeql-parquet": "0.0.5",
|
|
70
|
+
"lakeql-http": "0.0.5",
|
|
71
|
+
"lakeql-r2": "0.0.5",
|
|
72
|
+
"lakeql-s3": "0.0.5",
|
|
73
|
+
"lakeql-sql": "0.0.5"
|
|
72
74
|
},
|
|
73
75
|
"scripts": {
|
|
74
76
|
"build": "tsup"
|