@uwdata/mosaic-inputs 0.1.0 → 0.3.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/mosaic-inputs.js +1628 -676
- package/dist/mosaic-inputs.min.js +4 -4
- package/package.json +4 -4
- package/src/Menu.js +17 -6
- package/src/Search.js +10 -2
- package/src/Slider.js +8 -2
- package/src/Table.js +58 -36
- package/src/index.js +4 -4
- package/src/input.js +7 -0
package/dist/mosaic-inputs.js
CHANGED
|
@@ -328,8 +328,8 @@ function joinUint8Arrays(chunks, size) {
|
|
|
328
328
|
}
|
|
329
329
|
return [buffer || new Uint8Array(0), result.slice(index), byteLength - (buffer ? buffer.byteLength : 0)];
|
|
330
330
|
}
|
|
331
|
-
function toArrayBufferView(ArrayBufferViewCtor,
|
|
332
|
-
let value = isIteratorResult(
|
|
331
|
+
function toArrayBufferView(ArrayBufferViewCtor, input2) {
|
|
332
|
+
let value = isIteratorResult(input2) ? input2.value : input2;
|
|
333
333
|
if (value instanceof ArrayBufferViewCtor) {
|
|
334
334
|
if (ArrayBufferViewCtor === Uint8Array) {
|
|
335
335
|
return new ArrayBufferViewCtor(value.buffer, value.byteOffset, value.byteLength);
|
|
@@ -353,17 +353,17 @@ function toArrayBufferView(ArrayBufferViewCtor, input) {
|
|
|
353
353
|
}
|
|
354
354
|
return !ArrayBuffer.isView(value) ? ArrayBufferViewCtor.from(value) : value.byteLength <= 0 ? new ArrayBufferViewCtor(0) : new ArrayBufferViewCtor(value.buffer, value.byteOffset, value.byteLength / ArrayBufferViewCtor.BYTES_PER_ELEMENT);
|
|
355
355
|
}
|
|
356
|
-
var toInt8Array = (
|
|
357
|
-
var toInt16Array = (
|
|
358
|
-
var toInt32Array = (
|
|
359
|
-
var toBigInt64Array = (
|
|
360
|
-
var toUint8Array = (
|
|
361
|
-
var toUint16Array = (
|
|
362
|
-
var toUint32Array = (
|
|
363
|
-
var toBigUint64Array = (
|
|
364
|
-
var toFloat32Array = (
|
|
365
|
-
var toFloat64Array = (
|
|
366
|
-
var toUint8ClampedArray = (
|
|
356
|
+
var toInt8Array = (input2) => toArrayBufferView(Int8Array, input2);
|
|
357
|
+
var toInt16Array = (input2) => toArrayBufferView(Int16Array, input2);
|
|
358
|
+
var toInt32Array = (input2) => toArrayBufferView(Int32Array, input2);
|
|
359
|
+
var toBigInt64Array = (input2) => toArrayBufferView(BigInt64ArrayCtor, input2);
|
|
360
|
+
var toUint8Array = (input2) => toArrayBufferView(Uint8Array, input2);
|
|
361
|
+
var toUint16Array = (input2) => toArrayBufferView(Uint16Array, input2);
|
|
362
|
+
var toUint32Array = (input2) => toArrayBufferView(Uint32Array, input2);
|
|
363
|
+
var toBigUint64Array = (input2) => toArrayBufferView(BigUint64ArrayCtor, input2);
|
|
364
|
+
var toFloat32Array = (input2) => toArrayBufferView(Float32Array, input2);
|
|
365
|
+
var toFloat64Array = (input2) => toArrayBufferView(Float64Array, input2);
|
|
366
|
+
var toUint8ClampedArray = (input2) => toArrayBufferView(Uint8ClampedArray, input2);
|
|
367
367
|
var pump = (iterator) => {
|
|
368
368
|
iterator.next();
|
|
369
369
|
return iterator;
|
|
@@ -381,15 +381,15 @@ function* toArrayBufferViewIterator(ArrayCtor, source) {
|
|
|
381
381
|
}(buffers[Symbol.iterator]()));
|
|
382
382
|
return new ArrayCtor();
|
|
383
383
|
}
|
|
384
|
-
var toInt8ArrayIterator = (
|
|
385
|
-
var toInt16ArrayIterator = (
|
|
386
|
-
var toInt32ArrayIterator = (
|
|
387
|
-
var toUint8ArrayIterator = (
|
|
388
|
-
var toUint16ArrayIterator = (
|
|
389
|
-
var toUint32ArrayIterator = (
|
|
390
|
-
var toFloat32ArrayIterator = (
|
|
391
|
-
var toFloat64ArrayIterator = (
|
|
392
|
-
var toUint8ClampedArrayIterator = (
|
|
384
|
+
var toInt8ArrayIterator = (input2) => toArrayBufferViewIterator(Int8Array, input2);
|
|
385
|
+
var toInt16ArrayIterator = (input2) => toArrayBufferViewIterator(Int16Array, input2);
|
|
386
|
+
var toInt32ArrayIterator = (input2) => toArrayBufferViewIterator(Int32Array, input2);
|
|
387
|
+
var toUint8ArrayIterator = (input2) => toArrayBufferViewIterator(Uint8Array, input2);
|
|
388
|
+
var toUint16ArrayIterator = (input2) => toArrayBufferViewIterator(Uint16Array, input2);
|
|
389
|
+
var toUint32ArrayIterator = (input2) => toArrayBufferViewIterator(Uint32Array, input2);
|
|
390
|
+
var toFloat32ArrayIterator = (input2) => toArrayBufferViewIterator(Float32Array, input2);
|
|
391
|
+
var toFloat64ArrayIterator = (input2) => toArrayBufferViewIterator(Float64Array, input2);
|
|
392
|
+
var toUint8ClampedArrayIterator = (input2) => toArrayBufferViewIterator(Uint8ClampedArray, input2);
|
|
393
393
|
function toArrayBufferViewAsyncIterator(ArrayCtor, source) {
|
|
394
394
|
return __asyncGenerator(this, arguments, function* toArrayBufferViewAsyncIterator_1() {
|
|
395
395
|
if (isPromise(source)) {
|
|
@@ -425,15 +425,15 @@ function toArrayBufferViewAsyncIterator(ArrayCtor, source) {
|
|
|
425
425
|
return yield __await(new ArrayCtor());
|
|
426
426
|
});
|
|
427
427
|
}
|
|
428
|
-
var toInt8ArrayAsyncIterator = (
|
|
429
|
-
var toInt16ArrayAsyncIterator = (
|
|
430
|
-
var toInt32ArrayAsyncIterator = (
|
|
431
|
-
var toUint8ArrayAsyncIterator = (
|
|
432
|
-
var toUint16ArrayAsyncIterator = (
|
|
433
|
-
var toUint32ArrayAsyncIterator = (
|
|
434
|
-
var toFloat32ArrayAsyncIterator = (
|
|
435
|
-
var toFloat64ArrayAsyncIterator = (
|
|
436
|
-
var toUint8ClampedArrayAsyncIterator = (
|
|
428
|
+
var toInt8ArrayAsyncIterator = (input2) => toArrayBufferViewAsyncIterator(Int8Array, input2);
|
|
429
|
+
var toInt16ArrayAsyncIterator = (input2) => toArrayBufferViewAsyncIterator(Int16Array, input2);
|
|
430
|
+
var toInt32ArrayAsyncIterator = (input2) => toArrayBufferViewAsyncIterator(Int32Array, input2);
|
|
431
|
+
var toUint8ArrayAsyncIterator = (input2) => toArrayBufferViewAsyncIterator(Uint8Array, input2);
|
|
432
|
+
var toUint16ArrayAsyncIterator = (input2) => toArrayBufferViewAsyncIterator(Uint16Array, input2);
|
|
433
|
+
var toUint32ArrayAsyncIterator = (input2) => toArrayBufferViewAsyncIterator(Uint32Array, input2);
|
|
434
|
+
var toFloat32ArrayAsyncIterator = (input2) => toArrayBufferViewAsyncIterator(Float32Array, input2);
|
|
435
|
+
var toFloat64ArrayAsyncIterator = (input2) => toArrayBufferViewAsyncIterator(Float64Array, input2);
|
|
436
|
+
var toUint8ClampedArrayAsyncIterator = (input2) => toArrayBufferViewAsyncIterator(Uint8ClampedArray, input2);
|
|
437
437
|
function rebaseValueOffsets(offset, length2, valueOffsets) {
|
|
438
438
|
if (offset !== 0) {
|
|
439
439
|
valueOffsets = valueOffsets.slice(0, length2 + 1);
|
|
@@ -2621,31 +2621,31 @@ function clampRange(source, begin, end, then) {
|
|
|
2621
2621
|
return then ? then(source, lhs, rhs) : [lhs, rhs];
|
|
2622
2622
|
}
|
|
2623
2623
|
var isNaNFast = (value) => value !== value;
|
|
2624
|
-
function createElementComparator(
|
|
2625
|
-
const typeofSearch = typeof
|
|
2626
|
-
if (typeofSearch !== "object" ||
|
|
2627
|
-
if (isNaNFast(
|
|
2624
|
+
function createElementComparator(search2) {
|
|
2625
|
+
const typeofSearch = typeof search2;
|
|
2626
|
+
if (typeofSearch !== "object" || search2 === null) {
|
|
2627
|
+
if (isNaNFast(search2)) {
|
|
2628
2628
|
return isNaNFast;
|
|
2629
2629
|
}
|
|
2630
|
-
return (value) => value ===
|
|
2630
|
+
return (value) => value === search2;
|
|
2631
2631
|
}
|
|
2632
|
-
if (
|
|
2633
|
-
const valueOfSearch =
|
|
2632
|
+
if (search2 instanceof Date) {
|
|
2633
|
+
const valueOfSearch = search2.valueOf();
|
|
2634
2634
|
return (value) => value instanceof Date ? value.valueOf() === valueOfSearch : false;
|
|
2635
2635
|
}
|
|
2636
|
-
if (ArrayBuffer.isView(
|
|
2637
|
-
return (value) => value ? compareArrayLike(
|
|
2636
|
+
if (ArrayBuffer.isView(search2)) {
|
|
2637
|
+
return (value) => value ? compareArrayLike(search2, value) : false;
|
|
2638
2638
|
}
|
|
2639
|
-
if (
|
|
2640
|
-
return createMapComparator(
|
|
2639
|
+
if (search2 instanceof Map) {
|
|
2640
|
+
return createMapComparator(search2);
|
|
2641
2641
|
}
|
|
2642
|
-
if (Array.isArray(
|
|
2643
|
-
return createArrayLikeComparator(
|
|
2642
|
+
if (Array.isArray(search2)) {
|
|
2643
|
+
return createArrayLikeComparator(search2);
|
|
2644
2644
|
}
|
|
2645
|
-
if (
|
|
2646
|
-
return createVectorComparator(
|
|
2645
|
+
if (search2 instanceof Vector) {
|
|
2646
|
+
return createVectorComparator(search2);
|
|
2647
2647
|
}
|
|
2648
|
-
return createObjectComparator(
|
|
2648
|
+
return createObjectComparator(search2, true);
|
|
2649
2649
|
}
|
|
2650
2650
|
function createArrayLikeComparator(lhs) {
|
|
2651
2651
|
const comparators = [];
|
|
@@ -3470,21 +3470,21 @@ var getListByteLength = ({ valueOffsets, stride, children }, index) => {
|
|
|
3470
3470
|
const child = children[0];
|
|
3471
3471
|
const { [index * stride]: start } = valueOffsets;
|
|
3472
3472
|
const { [index * stride + 1]: end } = valueOffsets;
|
|
3473
|
-
const
|
|
3473
|
+
const visit2 = instance5.getVisitFn(child.type);
|
|
3474
3474
|
const slice = child.slice(start, end - start);
|
|
3475
3475
|
let size = 8;
|
|
3476
3476
|
for (let idx = -1, len = end - start; ++idx < len; ) {
|
|
3477
|
-
size +=
|
|
3477
|
+
size += visit2(slice, idx);
|
|
3478
3478
|
}
|
|
3479
3479
|
return size;
|
|
3480
3480
|
};
|
|
3481
3481
|
var getFixedSizeListByteLength = ({ stride, children }, index) => {
|
|
3482
3482
|
const child = children[0];
|
|
3483
3483
|
const slice = child.slice(index * stride, stride);
|
|
3484
|
-
const
|
|
3484
|
+
const visit2 = instance5.getVisitFn(child.type);
|
|
3485
3485
|
let size = 0;
|
|
3486
3486
|
for (let idx = -1, len = slice.length; ++idx < len; ) {
|
|
3487
|
-
size +=
|
|
3487
|
+
size += visit2(slice, idx);
|
|
3488
3488
|
}
|
|
3489
3489
|
return size;
|
|
3490
3490
|
};
|
|
@@ -3512,9 +3512,9 @@ var _a2;
|
|
|
3512
3512
|
var visitorsByTypeId = {};
|
|
3513
3513
|
var vectorPrototypesByTypeId = {};
|
|
3514
3514
|
var Vector = class {
|
|
3515
|
-
constructor(
|
|
3515
|
+
constructor(input2) {
|
|
3516
3516
|
var _b2, _c2, _d2;
|
|
3517
|
-
const data =
|
|
3517
|
+
const data = input2[0] instanceof Vector ? input2.flatMap((x) => x.data) : input2;
|
|
3518
3518
|
if (data.length === 0 || data.some((x) => !(x instanceof Data))) {
|
|
3519
3519
|
throw new TypeError("Vector constructor expects an Array of Data instances.");
|
|
3520
3520
|
}
|
|
@@ -4958,8 +4958,8 @@ var Builder2 = class {
|
|
|
4958
4958
|
* This checks a required field has been set in a given table that has
|
|
4959
4959
|
* just been constructed.
|
|
4960
4960
|
*/
|
|
4961
|
-
requiredField(
|
|
4962
|
-
const table_start = this.bb.capacity() -
|
|
4961
|
+
requiredField(table2, field) {
|
|
4962
|
+
const table_start = this.bb.capacity() - table2;
|
|
4963
4963
|
const vtable_start = table_start - this.bb.readInt32(table_start);
|
|
4964
4964
|
const ok = this.bb.readInt16(vtable_start + field) != 0;
|
|
4965
4965
|
if (!ok) {
|
|
@@ -10903,13 +10903,13 @@ var RecordBatchWriter = class extends ReadableInterop {
|
|
|
10903
10903
|
toUint8Array(sync = false) {
|
|
10904
10904
|
return this._sink.toUint8Array(sync);
|
|
10905
10905
|
}
|
|
10906
|
-
writeAll(
|
|
10907
|
-
if (isPromise(
|
|
10908
|
-
return
|
|
10909
|
-
} else if (isAsyncIterable(
|
|
10910
|
-
return writeAllAsync(this,
|
|
10906
|
+
writeAll(input2) {
|
|
10907
|
+
if (isPromise(input2)) {
|
|
10908
|
+
return input2.then((x) => this.writeAll(x));
|
|
10909
|
+
} else if (isAsyncIterable(input2)) {
|
|
10910
|
+
return writeAllAsync(this, input2);
|
|
10911
10911
|
}
|
|
10912
|
-
return writeAll(this,
|
|
10912
|
+
return writeAll(this, input2);
|
|
10913
10913
|
}
|
|
10914
10914
|
get closed() {
|
|
10915
10915
|
return this._sink.closed;
|
|
@@ -11076,26 +11076,26 @@ var RecordBatchWriter = class extends ReadableInterop {
|
|
|
11076
11076
|
};
|
|
11077
11077
|
var RecordBatchStreamWriter = class extends RecordBatchWriter {
|
|
11078
11078
|
/** @nocollapse */
|
|
11079
|
-
static writeAll(
|
|
11079
|
+
static writeAll(input2, options) {
|
|
11080
11080
|
const writer = new RecordBatchStreamWriter(options);
|
|
11081
|
-
if (isPromise(
|
|
11082
|
-
return
|
|
11083
|
-
} else if (isAsyncIterable(
|
|
11084
|
-
return writeAllAsync(writer,
|
|
11081
|
+
if (isPromise(input2)) {
|
|
11082
|
+
return input2.then((x) => writer.writeAll(x));
|
|
11083
|
+
} else if (isAsyncIterable(input2)) {
|
|
11084
|
+
return writeAllAsync(writer, input2);
|
|
11085
11085
|
}
|
|
11086
|
-
return writeAll(writer,
|
|
11086
|
+
return writeAll(writer, input2);
|
|
11087
11087
|
}
|
|
11088
11088
|
};
|
|
11089
11089
|
var RecordBatchFileWriter = class extends RecordBatchWriter {
|
|
11090
11090
|
/** @nocollapse */
|
|
11091
|
-
static writeAll(
|
|
11091
|
+
static writeAll(input2) {
|
|
11092
11092
|
const writer = new RecordBatchFileWriter();
|
|
11093
|
-
if (isPromise(
|
|
11094
|
-
return
|
|
11095
|
-
} else if (isAsyncIterable(
|
|
11096
|
-
return writeAllAsync(writer,
|
|
11093
|
+
if (isPromise(input2)) {
|
|
11094
|
+
return input2.then((x) => writer.writeAll(x));
|
|
11095
|
+
} else if (isAsyncIterable(input2)) {
|
|
11096
|
+
return writeAllAsync(writer, input2);
|
|
11097
11097
|
}
|
|
11098
|
-
return writeAll(writer,
|
|
11098
|
+
return writeAll(writer, input2);
|
|
11099
11099
|
}
|
|
11100
11100
|
constructor() {
|
|
11101
11101
|
super();
|
|
@@ -11110,11 +11110,11 @@ var RecordBatchFileWriter = class extends RecordBatchWriter {
|
|
|
11110
11110
|
return super._writeFooter(schema)._write(buffer)._write(Int32Array.of(buffer.byteLength))._writeMagic();
|
|
11111
11111
|
}
|
|
11112
11112
|
};
|
|
11113
|
-
function writeAll(writer,
|
|
11114
|
-
let chunks =
|
|
11115
|
-
if (
|
|
11116
|
-
chunks =
|
|
11117
|
-
writer.reset(void 0,
|
|
11113
|
+
function writeAll(writer, input2) {
|
|
11114
|
+
let chunks = input2;
|
|
11115
|
+
if (input2 instanceof Table) {
|
|
11116
|
+
chunks = input2.batches;
|
|
11117
|
+
writer.reset(void 0, input2.schema);
|
|
11118
11118
|
}
|
|
11119
11119
|
for (const batch of chunks) {
|
|
11120
11120
|
writer.write(batch);
|
|
@@ -11389,8 +11389,8 @@ function recordBatchWriterThroughDOMStream(writableStrategy, readableStrategy) {
|
|
|
11389
11389
|
}
|
|
11390
11390
|
|
|
11391
11391
|
// ../../node_modules/apache-arrow/ipc/serialization.mjs
|
|
11392
|
-
function tableFromIPC(
|
|
11393
|
-
const reader = RecordBatchReader.from(
|
|
11392
|
+
function tableFromIPC(input2) {
|
|
11393
|
+
const reader = RecordBatchReader.from(input2);
|
|
11394
11394
|
if (isPromise(reader)) {
|
|
11395
11395
|
return reader.then((reader2) => tableFromIPC(reader2));
|
|
11396
11396
|
}
|
|
@@ -11417,8 +11417,8 @@ RecordBatchWriter["throughDOM"] = recordBatchWriterThroughDOMStream;
|
|
|
11417
11417
|
RecordBatchFileWriter["throughDOM"] = recordBatchWriterThroughDOMStream;
|
|
11418
11418
|
RecordBatchStreamWriter["throughDOM"] = recordBatchWriterThroughDOMStream;
|
|
11419
11419
|
|
|
11420
|
-
// ../core/src/
|
|
11421
|
-
function
|
|
11420
|
+
// ../core/src/connectors/socket.js
|
|
11421
|
+
function socketConnector(uri = "ws://localhost:3000/") {
|
|
11422
11422
|
const queue = [];
|
|
11423
11423
|
let connected = false;
|
|
11424
11424
|
let request = null;
|
|
@@ -11537,22 +11537,35 @@ function jsType(type) {
|
|
|
11537
11537
|
|
|
11538
11538
|
// ../sql/src/ref.js
|
|
11539
11539
|
var Ref = class {
|
|
11540
|
-
|
|
11541
|
-
|
|
11542
|
-
|
|
11540
|
+
/**
|
|
11541
|
+
* Create a new Ref instance.
|
|
11542
|
+
* @param {string|Ref|null} table The table name.
|
|
11543
|
+
* @param {string|null} column The column name.
|
|
11544
|
+
*/
|
|
11545
|
+
constructor(table2, column2) {
|
|
11546
|
+
if (table2)
|
|
11547
|
+
this.table = String(table2);
|
|
11543
11548
|
if (column2)
|
|
11544
11549
|
this.column = column2;
|
|
11545
11550
|
}
|
|
11551
|
+
/**
|
|
11552
|
+
* Get the list of referenced columns. Either a single element array
|
|
11553
|
+
* if column is non-null, otherwise an empty array.
|
|
11554
|
+
*/
|
|
11546
11555
|
get columns() {
|
|
11547
11556
|
return this.column ? [this.column] : [];
|
|
11548
11557
|
}
|
|
11558
|
+
/**
|
|
11559
|
+
* Generate a SQL string for this reference.
|
|
11560
|
+
* @returns {string} The SQL string.
|
|
11561
|
+
*/
|
|
11549
11562
|
toString() {
|
|
11550
|
-
const { table, column: column2 } = this;
|
|
11563
|
+
const { table: table2, column: column2 } = this;
|
|
11551
11564
|
if (column2) {
|
|
11552
|
-
const col = column2
|
|
11553
|
-
return
|
|
11565
|
+
const col = column2.startsWith("*") ? column2 : `"${column2}"`;
|
|
11566
|
+
return `${table2 ? `"${table2}".` : ""}${col}`;
|
|
11554
11567
|
} else {
|
|
11555
|
-
return `"${
|
|
11568
|
+
return table2 ? `"${table2}"` : "NULL";
|
|
11556
11569
|
}
|
|
11557
11570
|
}
|
|
11558
11571
|
};
|
|
@@ -11568,25 +11581,34 @@ function asRelation(value) {
|
|
|
11568
11581
|
function relation(name) {
|
|
11569
11582
|
return new Ref(name);
|
|
11570
11583
|
}
|
|
11571
|
-
function column(
|
|
11572
|
-
|
|
11584
|
+
function column(table2, column2) {
|
|
11585
|
+
if (arguments.length === 1) {
|
|
11586
|
+
column2 = table2;
|
|
11587
|
+
table2 = null;
|
|
11588
|
+
}
|
|
11589
|
+
return new Ref(table2, column2);
|
|
11573
11590
|
}
|
|
11574
11591
|
|
|
11575
11592
|
// ../sql/src/to-sql.js
|
|
11576
|
-
function toSQL(value) {
|
|
11577
|
-
return typeof value === "string" ? `"${value}"` : literalToSQL(value);
|
|
11578
|
-
}
|
|
11579
11593
|
function literalToSQL(value) {
|
|
11580
11594
|
switch (typeof value) {
|
|
11581
11595
|
case "boolean":
|
|
11582
11596
|
return value ? "TRUE" : "FALSE";
|
|
11583
11597
|
case "string":
|
|
11584
11598
|
return `'${value}'`;
|
|
11599
|
+
case "number":
|
|
11600
|
+
return Number.isFinite(value) ? String(value) : "NULL";
|
|
11585
11601
|
default:
|
|
11586
11602
|
if (value == null) {
|
|
11587
11603
|
return "NULL";
|
|
11588
11604
|
} else if (value instanceof Date) {
|
|
11589
|
-
|
|
11605
|
+
const ts = +value;
|
|
11606
|
+
if (Number.isNaN(ts))
|
|
11607
|
+
return "NULL";
|
|
11608
|
+
const y = value.getUTCFullYear();
|
|
11609
|
+
const m = value.getUTCMonth();
|
|
11610
|
+
const d = value.getUTCDate();
|
|
11611
|
+
return ts === Date.UTC(y, m, d) ? `MAKE_DATE(${y}, ${m + 1}, ${d})` : `EPOCH_MS(${ts})`;
|
|
11590
11612
|
} else if (value instanceof RegExp) {
|
|
11591
11613
|
return `'${value.source}'`;
|
|
11592
11614
|
} else {
|
|
@@ -11596,263 +11618,406 @@ function literalToSQL(value) {
|
|
|
11596
11618
|
}
|
|
11597
11619
|
|
|
11598
11620
|
// ../sql/src/expression.js
|
|
11599
|
-
|
|
11600
|
-
|
|
11621
|
+
var isParamLike = (value) => typeof value?.addEventListener === "function";
|
|
11622
|
+
function isSQLExpression(value) {
|
|
11623
|
+
return value instanceof SQLExpression;
|
|
11601
11624
|
}
|
|
11602
11625
|
var SQLExpression = class {
|
|
11603
|
-
|
|
11604
|
-
|
|
11605
|
-
|
|
11606
|
-
|
|
11607
|
-
|
|
11608
|
-
|
|
11609
|
-
|
|
11610
|
-
|
|
11611
|
-
|
|
11612
|
-
|
|
11613
|
-
|
|
11614
|
-
|
|
11615
|
-
|
|
11616
|
-
|
|
11617
|
-
|
|
11618
|
-
|
|
11619
|
-
|
|
11620
|
-
|
|
11621
|
-
|
|
11622
|
-
return (value) => expr(func2(value), asColumn(value).columns, label);
|
|
11623
|
-
}
|
|
11624
|
-
|
|
11625
|
-
// ../sql/src/literal.js
|
|
11626
|
-
var Literal = class {
|
|
11627
|
-
constructor(value) {
|
|
11628
|
-
this.value = value;
|
|
11629
|
-
}
|
|
11630
|
-
toString() {
|
|
11631
|
-
return literalToSQL(this.value);
|
|
11626
|
+
/**
|
|
11627
|
+
* Create a new SQL expression instance.
|
|
11628
|
+
* @param {(string|SQLExpression|Ref)[]} parts The parts of the expression.
|
|
11629
|
+
* @param {string[]} [columns=[]] The column dependencies
|
|
11630
|
+
* @param {object} [props] Additional properties for this expression.
|
|
11631
|
+
*/
|
|
11632
|
+
constructor(parts, columns, props) {
|
|
11633
|
+
this._expr = Array.isArray(parts) ? parts : [parts];
|
|
11634
|
+
this._deps = columns || [];
|
|
11635
|
+
this.annotate(props);
|
|
11636
|
+
const params = this._expr.filter((part) => isParamLike(part));
|
|
11637
|
+
if (params.length > 0) {
|
|
11638
|
+
this._params = Array.from(new Set(params));
|
|
11639
|
+
this._params.forEach((param) => {
|
|
11640
|
+
param.addEventListener("value", () => update(this, this.map?.get("value")));
|
|
11641
|
+
});
|
|
11642
|
+
} else {
|
|
11643
|
+
this.addEventListener = void 0;
|
|
11644
|
+
}
|
|
11632
11645
|
}
|
|
11633
|
-
|
|
11634
|
-
|
|
11635
|
-
|
|
11636
|
-
|
|
11637
|
-
|
|
11638
|
-
|
|
11639
|
-
}
|
|
11640
|
-
var Compare1 = class {
|
|
11641
|
-
constructor(op, a) {
|
|
11642
|
-
this.op = op;
|
|
11643
|
-
this.a = asColumn(a);
|
|
11646
|
+
/**
|
|
11647
|
+
* A reference to this expression.
|
|
11648
|
+
* Provides compatibility with param-like objects.
|
|
11649
|
+
*/
|
|
11650
|
+
get value() {
|
|
11651
|
+
return this;
|
|
11644
11652
|
}
|
|
11653
|
+
/**
|
|
11654
|
+
* The column dependencies of this expression.
|
|
11655
|
+
* @returns {string[]} The columns dependencies.
|
|
11656
|
+
*/
|
|
11645
11657
|
get columns() {
|
|
11646
|
-
|
|
11647
|
-
|
|
11648
|
-
|
|
11649
|
-
|
|
11650
|
-
|
|
11651
|
-
|
|
11652
|
-
|
|
11653
|
-
|
|
11654
|
-
|
|
11655
|
-
|
|
11656
|
-
|
|
11657
|
-
|
|
11658
|
-
|
|
11659
|
-
var not = compare1("NOT");
|
|
11660
|
-
var isNull = compare1("IS NULL");
|
|
11661
|
-
var isNotNull = compare1("IS NOT NULL");
|
|
11662
|
-
var Compare2 = class {
|
|
11663
|
-
constructor(op, a, b) {
|
|
11664
|
-
this.op = op;
|
|
11665
|
-
this.a = asColumn(a);
|
|
11666
|
-
this.b = asColumn(b);
|
|
11658
|
+
const { _params, _deps } = this;
|
|
11659
|
+
if (_params) {
|
|
11660
|
+
const pset = new Set(_params.flatMap((p) => {
|
|
11661
|
+
const cols = p.value?.columns;
|
|
11662
|
+
return Array.isArray(cols) ? cols : [];
|
|
11663
|
+
}));
|
|
11664
|
+
if (pset.size) {
|
|
11665
|
+
const set = new Set(_deps);
|
|
11666
|
+
pset.forEach((col) => set.add(col));
|
|
11667
|
+
return Array.from(set);
|
|
11668
|
+
}
|
|
11669
|
+
}
|
|
11670
|
+
return _deps;
|
|
11667
11671
|
}
|
|
11668
|
-
|
|
11669
|
-
|
|
11672
|
+
/**
|
|
11673
|
+
* The first column dependency in this expression, or undefined if none.
|
|
11674
|
+
* @returns {string} The first column dependency.
|
|
11675
|
+
*/
|
|
11676
|
+
get column() {
|
|
11677
|
+
return this._deps.length ? this._deps[0] : this.columns[0];
|
|
11670
11678
|
}
|
|
11671
|
-
|
|
11672
|
-
|
|
11679
|
+
/**
|
|
11680
|
+
* Annotate this expression instance with additional properties.
|
|
11681
|
+
* @param {object[]} [props] One or more objects with properties to add.
|
|
11682
|
+
* @returns {this} This SQL expression.
|
|
11683
|
+
*/
|
|
11684
|
+
annotate(...props) {
|
|
11685
|
+
return Object.assign(this, ...props);
|
|
11673
11686
|
}
|
|
11687
|
+
/**
|
|
11688
|
+
* Generate a SQL code string corresponding to this expression.
|
|
11689
|
+
* @returns {string} A SQL code string.
|
|
11690
|
+
*/
|
|
11674
11691
|
toString() {
|
|
11675
|
-
|
|
11676
|
-
return `(${toSQL(a)} ${op} ${toSQL(b)})`;
|
|
11677
|
-
}
|
|
11678
|
-
};
|
|
11679
|
-
function compare2(op) {
|
|
11680
|
-
return (a, b) => new Compare2(op, a, b);
|
|
11681
|
-
}
|
|
11682
|
-
var eq = compare2("=");
|
|
11683
|
-
var neq = compare2("<>");
|
|
11684
|
-
var lt = compare2("<");
|
|
11685
|
-
var gt = compare2(">");
|
|
11686
|
-
var lte = compare2("<=");
|
|
11687
|
-
var gte = compare2(">=");
|
|
11688
|
-
var isDistinct = compare2("IS DISTINCT FROM");
|
|
11689
|
-
var isNotDistinct = compare2("IS NOT DISTINCT FROM");
|
|
11690
|
-
var Range = class {
|
|
11691
|
-
constructor(op, expr2, value) {
|
|
11692
|
-
this.op = op;
|
|
11693
|
-
this.expr = asColumn(expr2);
|
|
11694
|
-
this.value = value?.map(asColumn);
|
|
11695
|
-
}
|
|
11696
|
-
get columns() {
|
|
11697
|
-
return extractColumns(this.expr, this.value);
|
|
11698
|
-
}
|
|
11699
|
-
visit(callback) {
|
|
11700
|
-
callback(this.op, this);
|
|
11692
|
+
return this._expr.map((p) => isParamLike(p) && !isSQLExpression(p) ? literalToSQL(p.value) : p).join("");
|
|
11701
11693
|
}
|
|
11702
|
-
|
|
11703
|
-
|
|
11704
|
-
|
|
11705
|
-
|
|
11706
|
-
|
|
11707
|
-
|
|
11694
|
+
/**
|
|
11695
|
+
* Add an event listener callback for the provided event type.
|
|
11696
|
+
* @param {string} type The event type to listen for (for example, "value").
|
|
11697
|
+
* @param {(a: SQLExpression) => Promise?} callback The callback function to
|
|
11698
|
+
* invoke upon updates. A callback may optionally return a Promise that
|
|
11699
|
+
* upstream listeners may await before proceeding.
|
|
11700
|
+
*/
|
|
11701
|
+
addEventListener(type, callback) {
|
|
11702
|
+
const map = this.map || (this.map = /* @__PURE__ */ new Map());
|
|
11703
|
+
const set = map.get(type) || (map.set(type, /* @__PURE__ */ new Set()), map.get(type));
|
|
11704
|
+
set.add(callback);
|
|
11708
11705
|
}
|
|
11709
11706
|
};
|
|
11710
|
-
function
|
|
11711
|
-
|
|
11712
|
-
|
|
11713
|
-
var isBetween = range("BETWEEN");
|
|
11714
|
-
var isNotBetween = range("NOT BETWEEN");
|
|
11715
|
-
var CompareN = class {
|
|
11716
|
-
constructor(op, value) {
|
|
11717
|
-
this.op = op;
|
|
11718
|
-
this.value = value.map(asColumn);
|
|
11707
|
+
function update(expr, callbacks) {
|
|
11708
|
+
if (callbacks?.size) {
|
|
11709
|
+
return Promise.allSettled(Array.from(callbacks, (fn) => fn(expr)));
|
|
11719
11710
|
}
|
|
11720
|
-
|
|
11721
|
-
|
|
11722
|
-
|
|
11723
|
-
|
|
11724
|
-
|
|
11725
|
-
|
|
11726
|
-
|
|
11727
|
-
|
|
11728
|
-
|
|
11729
|
-
|
|
11711
|
+
}
|
|
11712
|
+
function parseSQL(strings, exprs) {
|
|
11713
|
+
const spans = [strings[0]];
|
|
11714
|
+
const cols = /* @__PURE__ */ new Set();
|
|
11715
|
+
const n = exprs.length;
|
|
11716
|
+
for (let i = 0, k = 0; i < n; ) {
|
|
11717
|
+
const e = exprs[i];
|
|
11718
|
+
if (isParamLike(e)) {
|
|
11719
|
+
spans[++k] = e;
|
|
11720
|
+
} else {
|
|
11721
|
+
if (Array.isArray(e?.columns)) {
|
|
11722
|
+
e.columns.forEach((col) => cols.add(col));
|
|
11723
|
+
}
|
|
11724
|
+
spans[k] += typeof e === "string" ? e : literalToSQL(e);
|
|
11725
|
+
}
|
|
11726
|
+
const s = strings[++i];
|
|
11727
|
+
if (isParamLike(spans[k])) {
|
|
11728
|
+
spans[++k] = s;
|
|
11729
|
+
} else {
|
|
11730
|
+
spans[k] += s;
|
|
11731
|
+
}
|
|
11730
11732
|
}
|
|
11731
|
-
};
|
|
11732
|
-
function and(...clauses) {
|
|
11733
|
-
return new CompareN("AND", clauses.flat());
|
|
11733
|
+
return { spans, cols: Array.from(cols) };
|
|
11734
11734
|
}
|
|
11735
|
-
function
|
|
11736
|
-
|
|
11735
|
+
function sql(strings, ...exprs) {
|
|
11736
|
+
const { spans, cols } = parseSQL(strings, exprs);
|
|
11737
|
+
return new SQLExpression(spans, cols);
|
|
11737
11738
|
}
|
|
11738
11739
|
|
|
11739
|
-
// ../sql/src/
|
|
11740
|
-
|
|
11741
|
-
|
|
11742
|
-
|
|
11743
|
-
|
|
11744
|
-
|
|
11745
|
-
|
|
11746
|
-
|
|
11740
|
+
// ../sql/src/desc.js
|
|
11741
|
+
function desc(expr) {
|
|
11742
|
+
const e = asColumn(expr);
|
|
11743
|
+
return sql`${e} DESC NULLS LAST`.annotate({ label: e?.label, desc: true });
|
|
11744
|
+
}
|
|
11745
|
+
|
|
11746
|
+
// ../sql/src/literal.js
|
|
11747
|
+
var literal = (value) => ({
|
|
11748
|
+
value,
|
|
11749
|
+
toString: () => literalToSQL(value)
|
|
11750
|
+
});
|
|
11751
|
+
|
|
11752
|
+
// ../sql/src/operators.js
|
|
11753
|
+
function visit(callback) {
|
|
11754
|
+
callback(this.op, this);
|
|
11755
|
+
this.children?.forEach((v) => v.visit(callback));
|
|
11756
|
+
}
|
|
11757
|
+
function logical(op, clauses) {
|
|
11758
|
+
const children = clauses.filter((x) => x != null).map(asColumn);
|
|
11759
|
+
const strings = children.map((c, i) => i ? ` ${op} ` : "");
|
|
11760
|
+
if (clauses.length)
|
|
11761
|
+
strings.push("");
|
|
11762
|
+
return sql(strings, ...children).annotate({ op, children, visit });
|
|
11763
|
+
}
|
|
11764
|
+
var and = (...clauses) => logical("AND", clauses.flat());
|
|
11765
|
+
var or = (...clauses) => logical("OR", clauses.flat());
|
|
11766
|
+
var unaryOp = (op) => (a) => sql`(${op} ${asColumn(a)})`.annotate({ op, a, visit });
|
|
11767
|
+
var not = unaryOp("NOT");
|
|
11768
|
+
var unaryPostOp = (op) => (a) => sql`(${asColumn(a)} ${op})`.annotate({ op, a, visit });
|
|
11769
|
+
var isNull = unaryPostOp("IS NULL");
|
|
11770
|
+
var isNotNull = unaryPostOp("IS NOT NULL");
|
|
11771
|
+
var binaryOp = (op) => (a, b) => sql`(${asColumn(a)} ${op} ${asColumn(b)})`.annotate({ op, a, b, visit });
|
|
11772
|
+
var eq = binaryOp("=");
|
|
11773
|
+
var neq = binaryOp("<>");
|
|
11774
|
+
var lt = binaryOp("<");
|
|
11775
|
+
var gt = binaryOp(">");
|
|
11776
|
+
var lte = binaryOp("<=");
|
|
11777
|
+
var gte = binaryOp(">=");
|
|
11778
|
+
var isDistinct = binaryOp("IS DISTINCT FROM");
|
|
11779
|
+
var isNotDistinct = binaryOp("IS NOT DISTINCT FROM");
|
|
11780
|
+
function rangeOp(op, a, range, exclusive) {
|
|
11781
|
+
a = asColumn(a);
|
|
11782
|
+
const prefix2 = op.startsWith("NOT ") ? "NOT " : "";
|
|
11783
|
+
const expr = !range ? sql`` : exclusive ? sql`${prefix2}(${range[0]} <= ${a} AND ${a} < ${range[1]})` : sql`(${a} ${op} ${range[0]} AND ${range[1]})`;
|
|
11784
|
+
return expr.annotate({ op, visit, field: a, range });
|
|
11785
|
+
}
|
|
11786
|
+
var isBetween = (a, range, exclusive) => rangeOp("BETWEEN", a, range, exclusive);
|
|
11787
|
+
|
|
11788
|
+
// ../sql/src/repeat.js
|
|
11789
|
+
function repeat(length2, str) {
|
|
11790
|
+
return Array.from({ length: length2 }, () => str);
|
|
11791
|
+
}
|
|
11792
|
+
|
|
11793
|
+
// ../sql/src/functions.js
|
|
11794
|
+
function functionCall(op, type) {
|
|
11795
|
+
return (...values) => {
|
|
11796
|
+
const args = values.map(asColumn);
|
|
11797
|
+
const cast2 = type ? `::${type}` : "";
|
|
11798
|
+
const expr = args.length ? sql([`${op}(`, ...repeat(args.length - 1, ", "), `)${cast2}`], ...args) : sql`${op}()${cast2}`;
|
|
11799
|
+
return expr.annotate({ func: op, args });
|
|
11800
|
+
};
|
|
11801
|
+
}
|
|
11802
|
+
var regexp_matches = functionCall("REGEXP_MATCHES");
|
|
11803
|
+
var contains = functionCall("CONTAINS");
|
|
11804
|
+
var prefix = functionCall("PREFIX");
|
|
11805
|
+
var suffix = functionCall("SUFFIX");
|
|
11806
|
+
var lower = functionCall("LOWER");
|
|
11807
|
+
var upper = functionCall("UPPER");
|
|
11808
|
+
var length = functionCall("LENGTH");
|
|
11809
|
+
var isNaN2 = functionCall("ISNAN");
|
|
11810
|
+
var isFinite = functionCall("ISFINITE");
|
|
11811
|
+
var isInfinite = functionCall("ISINF");
|
|
11812
|
+
|
|
11813
|
+
// ../sql/src/windows.js
|
|
11814
|
+
var WindowFunction = class extends SQLExpression {
|
|
11815
|
+
constructor(op, func, type, name, group = "", order = "", frame = "") {
|
|
11816
|
+
let expr;
|
|
11817
|
+
const noWindowParams = !(group || order || frame);
|
|
11818
|
+
if (name && noWindowParams) {
|
|
11819
|
+
expr = name ? sql`${func} OVER "${name}"` : sql`${func} OVER ()`;
|
|
11820
|
+
} else {
|
|
11821
|
+
const s1 = group && order ? " " : "";
|
|
11822
|
+
const s2 = (group || order) && frame ? " " : "";
|
|
11823
|
+
expr = sql`${func} OVER (${name ? `"${name}" ` : ""}${group}${s1}${order}${s2}${frame})`;
|
|
11824
|
+
}
|
|
11825
|
+
if (type) {
|
|
11826
|
+
expr = sql`(${expr})::${type}`;
|
|
11827
|
+
}
|
|
11828
|
+
const { _expr, _deps } = expr;
|
|
11829
|
+
super(_expr, _deps, { window: op, func, type, name, group, order, frame });
|
|
11747
11830
|
}
|
|
11748
|
-
get
|
|
11749
|
-
return this.
|
|
11831
|
+
get basis() {
|
|
11832
|
+
return this.column;
|
|
11750
11833
|
}
|
|
11751
|
-
|
|
11752
|
-
const { func
|
|
11753
|
-
return
|
|
11754
|
-
}
|
|
11755
|
-
|
|
11756
|
-
|
|
11757
|
-
|
|
11758
|
-
}
|
|
11759
|
-
|
|
11760
|
-
|
|
11761
|
-
|
|
11762
|
-
|
|
11763
|
-
|
|
11764
|
-
|
|
11765
|
-
|
|
11766
|
-
|
|
11767
|
-
|
|
11768
|
-
|
|
11769
|
-
|
|
11770
|
-
|
|
11771
|
-
|
|
11772
|
-
|
|
11773
|
-
|
|
11774
|
-
|
|
11834
|
+
get label() {
|
|
11835
|
+
const { func } = this;
|
|
11836
|
+
return func.label ?? func.toString();
|
|
11837
|
+
}
|
|
11838
|
+
over(name) {
|
|
11839
|
+
const { window: op, func, type, group, order, frame } = this;
|
|
11840
|
+
return new WindowFunction(op, func, type, name, group, order, frame);
|
|
11841
|
+
}
|
|
11842
|
+
partitionby(...expr) {
|
|
11843
|
+
const exprs = expr.flat().filter((x) => x).map(asColumn);
|
|
11844
|
+
const group = sql(
|
|
11845
|
+
["PARTITION BY ", repeat(exprs.length - 1, ", "), ""],
|
|
11846
|
+
...exprs
|
|
11847
|
+
);
|
|
11848
|
+
const { window: op, func, type, name, order, frame } = this;
|
|
11849
|
+
return new WindowFunction(op, func, type, name, group, order, frame);
|
|
11850
|
+
}
|
|
11851
|
+
orderby(...expr) {
|
|
11852
|
+
const exprs = expr.flat().filter((x) => x).map(asColumn);
|
|
11853
|
+
const order = sql(
|
|
11854
|
+
["ORDER BY ", repeat(exprs.length - 1, ", "), ""],
|
|
11855
|
+
...exprs
|
|
11856
|
+
);
|
|
11857
|
+
const { window: op, func, type, name, group, frame } = this;
|
|
11858
|
+
return new WindowFunction(op, func, type, name, group, order, frame);
|
|
11859
|
+
}
|
|
11860
|
+
rows(expr) {
|
|
11861
|
+
const frame = windowFrame("ROWS", expr);
|
|
11862
|
+
const { window: op, func, type, name, group, order } = this;
|
|
11863
|
+
return new WindowFunction(op, func, type, name, group, order, frame);
|
|
11864
|
+
}
|
|
11865
|
+
range(expr) {
|
|
11866
|
+
const frame = windowFrame("RANGE", expr);
|
|
11867
|
+
const { window: op, func, type, name, group, order } = this;
|
|
11868
|
+
return new WindowFunction(op, func, type, name, group, order, frame);
|
|
11869
|
+
}
|
|
11870
|
+
};
|
|
11871
|
+
function windowFrame(type, frame) {
|
|
11872
|
+
if (isParamLike(frame)) {
|
|
11873
|
+
const expr = sql`${frame}`;
|
|
11874
|
+
expr.toString = () => `${type} ${frameToSQL(frame.value)}`;
|
|
11875
|
+
return expr;
|
|
11876
|
+
}
|
|
11877
|
+
return `${type} ${frameToSQL(frame)}`;
|
|
11878
|
+
}
|
|
11879
|
+
function frameToSQL(frame) {
|
|
11880
|
+
const [prev, next] = frame;
|
|
11881
|
+
const a = prev === 0 ? "CURRENT ROW" : Number.isFinite(prev) ? `${Math.abs(prev)} PRECEDING` : "UNBOUNDED PRECEDING";
|
|
11882
|
+
const b = next === 0 ? "CURRENT ROW" : Number.isFinite(next) ? `${Math.abs(next)} FOLLOWING` : "UNBOUNDED FOLLOWING";
|
|
11883
|
+
return `BETWEEN ${a} AND ${b}`;
|
|
11884
|
+
}
|
|
11885
|
+
function winf(op, type) {
|
|
11886
|
+
return (...values) => {
|
|
11887
|
+
const func = functionCall(op)(...values);
|
|
11888
|
+
return new WindowFunction(op, func, type);
|
|
11889
|
+
};
|
|
11890
|
+
}
|
|
11891
|
+
var row_number = winf("ROW_NUMBER", "INTEGER");
|
|
11892
|
+
var rank = winf("RANK", "INTEGER");
|
|
11893
|
+
var dense_rank = winf("DENSE_RANK", "INTEGER");
|
|
11894
|
+
var percent_rank = winf("PERCENT_RANK");
|
|
11895
|
+
var cume_dist = winf("CUME_DIST");
|
|
11896
|
+
var ntile = winf("NTILE");
|
|
11897
|
+
var lag = winf("LAG");
|
|
11898
|
+
var lead = winf("LEAD");
|
|
11899
|
+
var first_value = winf("FIRST_VALUE");
|
|
11900
|
+
var last_value = winf("LAST_VALUE");
|
|
11901
|
+
var nth_value = winf("NTH_VALUE");
|
|
11902
|
+
|
|
11903
|
+
// ../sql/src/aggregates.js
|
|
11904
|
+
var AggregateFunction = class extends SQLExpression {
|
|
11905
|
+
constructor(op, args, type, isDistinct2, filter) {
|
|
11906
|
+
args = (args || []).map(asColumn);
|
|
11907
|
+
const { strings, exprs } = aggExpr(op, args, type, isDistinct2, filter);
|
|
11908
|
+
const { spans, cols } = parseSQL(strings, exprs);
|
|
11909
|
+
super(spans, cols, { aggregate: op, args, type, isDistinct: isDistinct2, filter });
|
|
11910
|
+
}
|
|
11911
|
+
get basis() {
|
|
11912
|
+
return this.column;
|
|
11775
11913
|
}
|
|
11776
11914
|
get label() {
|
|
11777
|
-
|
|
11915
|
+
const { aggregate: op, args, isDistinct: isDistinct2 } = this;
|
|
11916
|
+
const dist = isDistinct2 ? "DISTINCT" + (args.length ? " " : "") : "";
|
|
11917
|
+
const tail = args.length ? `(${dist}${args.map(unquoted).join(", ")})` : "";
|
|
11918
|
+
return `${op.toLowerCase()}${tail}`;
|
|
11778
11919
|
}
|
|
11779
|
-
|
|
11780
|
-
|
|
11920
|
+
distinct() {
|
|
11921
|
+
const { aggregate: op, args, type, filter } = this;
|
|
11922
|
+
return new AggregateFunction(op, args, type, true, filter);
|
|
11781
11923
|
}
|
|
11782
|
-
|
|
11783
|
-
|
|
11924
|
+
where(filter) {
|
|
11925
|
+
const { aggregate: op, args, type, isDistinct: isDistinct2 } = this;
|
|
11926
|
+
return new AggregateFunction(op, args, type, isDistinct2, filter);
|
|
11784
11927
|
}
|
|
11785
|
-
|
|
11786
|
-
|
|
11787
|
-
|
|
11928
|
+
window() {
|
|
11929
|
+
const { aggregate: op, args, type, isDistinct: isDistinct2 } = this;
|
|
11930
|
+
const func = new AggregateFunction(op, args, null, isDistinct2);
|
|
11931
|
+
return new WindowFunction(op, func, type);
|
|
11788
11932
|
}
|
|
11789
|
-
|
|
11790
|
-
this.
|
|
11791
|
-
return this;
|
|
11933
|
+
partitionby(...expr) {
|
|
11934
|
+
return this.window().partitionby(...expr);
|
|
11792
11935
|
}
|
|
11793
|
-
|
|
11794
|
-
|
|
11795
|
-
|
|
11796
|
-
|
|
11797
|
-
|
|
11798
|
-
|
|
11799
|
-
|
|
11800
|
-
|
|
11801
|
-
}
|
|
11802
|
-
|
|
11803
|
-
|
|
11804
|
-
}
|
|
11805
|
-
|
|
11806
|
-
|
|
11807
|
-
|
|
11808
|
-
|
|
11809
|
-
|
|
11810
|
-
|
|
11811
|
-
|
|
11812
|
-
|
|
11813
|
-
|
|
11814
|
-
|
|
11815
|
-
|
|
11816
|
-
|
|
11817
|
-
|
|
11818
|
-
|
|
11819
|
-
|
|
11820
|
-
|
|
11821
|
-
|
|
11822
|
-
|
|
11823
|
-
|
|
11824
|
-
|
|
11825
|
-
|
|
11826
|
-
var
|
|
11827
|
-
var
|
|
11828
|
-
var
|
|
11829
|
-
var
|
|
11830
|
-
var
|
|
11831
|
-
var
|
|
11832
|
-
var
|
|
11833
|
-
var
|
|
11834
|
-
var
|
|
11835
|
-
var
|
|
11836
|
-
var
|
|
11837
|
-
var
|
|
11838
|
-
var
|
|
11839
|
-
var
|
|
11936
|
+
orderby(...expr) {
|
|
11937
|
+
return this.window().orderby(...expr);
|
|
11938
|
+
}
|
|
11939
|
+
rows(prev, next) {
|
|
11940
|
+
return this.window().rows(prev, next);
|
|
11941
|
+
}
|
|
11942
|
+
range(prev, next) {
|
|
11943
|
+
return this.window().range(prev, next);
|
|
11944
|
+
}
|
|
11945
|
+
};
|
|
11946
|
+
function aggExpr(op, args, type, isDistinct2, filter) {
|
|
11947
|
+
const close = `)${type ? `::${type}` : ""}`;
|
|
11948
|
+
let strings = [`${op}(${isDistinct2 ? "DISTINCT " : ""}`];
|
|
11949
|
+
let exprs = [];
|
|
11950
|
+
if (args.length) {
|
|
11951
|
+
strings = strings.concat([
|
|
11952
|
+
...repeat(args.length - 1, ", "),
|
|
11953
|
+
`${close}${filter ? " FILTER (WHERE " : ""}`,
|
|
11954
|
+
...filter ? [")"] : []
|
|
11955
|
+
]);
|
|
11956
|
+
exprs = [...args, ...filter ? [filter] : []];
|
|
11957
|
+
} else {
|
|
11958
|
+
strings[0] += "*" + close;
|
|
11959
|
+
}
|
|
11960
|
+
return { exprs, strings };
|
|
11961
|
+
}
|
|
11962
|
+
function unquoted(value) {
|
|
11963
|
+
const s = literalToSQL(value);
|
|
11964
|
+
return s && s.startsWith('"') && s.endsWith('"') ? s.slice(1, -1) : s;
|
|
11965
|
+
}
|
|
11966
|
+
function aggf(op, type) {
|
|
11967
|
+
return (...args) => new AggregateFunction(op, args, type);
|
|
11968
|
+
}
|
|
11969
|
+
var count = aggf("COUNT", "INTEGER");
|
|
11970
|
+
var avg = aggf("AVG");
|
|
11971
|
+
var mean = aggf("AVG");
|
|
11972
|
+
var mad = aggf("MAD");
|
|
11973
|
+
var max = aggf("MAX");
|
|
11974
|
+
var min = aggf("MIN");
|
|
11975
|
+
var sum2 = aggf("SUM", "DOUBLE");
|
|
11976
|
+
var product = aggf("PRODUCT");
|
|
11977
|
+
var median = aggf("MEDIAN");
|
|
11978
|
+
var quantile = aggf("QUANTILE");
|
|
11979
|
+
var mode = aggf("MODE");
|
|
11980
|
+
var variance = aggf("VARIANCE");
|
|
11981
|
+
var stddev = aggf("STDDEV");
|
|
11982
|
+
var skewness = aggf("SKEWNESS");
|
|
11983
|
+
var kurtosis = aggf("KURTOSIS");
|
|
11984
|
+
var entropy = aggf("ENTROPY");
|
|
11985
|
+
var varPop = aggf("VAR_POP");
|
|
11986
|
+
var stddevPop = aggf("STDDEV_POP");
|
|
11987
|
+
var corr = aggf("CORR");
|
|
11988
|
+
var covarPop = aggf("COVAR_POP");
|
|
11989
|
+
var regrIntercept = aggf("REGR_INTERCEPT");
|
|
11990
|
+
var regrSlope = aggf("REGR_SLOPE");
|
|
11991
|
+
var regrCount = aggf("REGR_COUNT");
|
|
11992
|
+
var regrR2 = aggf("REGR_R2");
|
|
11993
|
+
var regrSYY = aggf("REGR_SYY");
|
|
11994
|
+
var regrSXX = aggf("REGR_SXX");
|
|
11995
|
+
var regrSXY = aggf("REGR_SXY");
|
|
11996
|
+
var regrAvgX = aggf("REGR_AVGX");
|
|
11997
|
+
var regrAvgY = aggf("REGR_AVGY");
|
|
11998
|
+
var first = aggf("FIRST");
|
|
11999
|
+
var last = aggf("LAST");
|
|
12000
|
+
var argmin = aggf("ARG_MIN");
|
|
12001
|
+
var argmax = aggf("ARG_MAX");
|
|
12002
|
+
var stringAgg = aggf("STRING_AGG");
|
|
12003
|
+
var arrayAgg = aggf("ARRAY_AGG");
|
|
11840
12004
|
|
|
11841
12005
|
// ../sql/src/datetime.js
|
|
11842
|
-
var epoch_ms =
|
|
11843
|
-
|
|
11844
|
-
)
|
|
12006
|
+
var epoch_ms = (expr) => {
|
|
12007
|
+
const d = asColumn(expr);
|
|
12008
|
+
return sql`(1000 * (epoch(${d}) - second(${d})) + millisecond(${d}))::DOUBLE`;
|
|
12009
|
+
};
|
|
11845
12010
|
|
|
11846
12011
|
// ../sql/src/Query.js
|
|
11847
12012
|
var Query = class {
|
|
11848
|
-
static select(...
|
|
11849
|
-
return new Query().select(...
|
|
12013
|
+
static select(...expr) {
|
|
12014
|
+
return new Query().select(...expr);
|
|
11850
12015
|
}
|
|
11851
|
-
static from(...
|
|
11852
|
-
return new Query().from(...
|
|
12016
|
+
static from(...expr) {
|
|
12017
|
+
return new Query().from(...expr);
|
|
11853
12018
|
}
|
|
11854
|
-
static with(...
|
|
11855
|
-
return new Query().with(...
|
|
12019
|
+
static with(...expr) {
|
|
12020
|
+
return new Query().with(...expr);
|
|
11856
12021
|
}
|
|
11857
12022
|
static union(...queries) {
|
|
11858
12023
|
return new SetOperation("UNION", queries.flat());
|
|
@@ -11884,9 +12049,9 @@ var Query = class {
|
|
|
11884
12049
|
q.query = { ...this.query };
|
|
11885
12050
|
return q;
|
|
11886
12051
|
}
|
|
11887
|
-
with(...
|
|
12052
|
+
with(...expr) {
|
|
11888
12053
|
const { query } = this;
|
|
11889
|
-
if (
|
|
12054
|
+
if (expr.length === 0) {
|
|
11890
12055
|
return query.with;
|
|
11891
12056
|
} else {
|
|
11892
12057
|
const list = [];
|
|
@@ -11895,7 +12060,7 @@ var Query = class {
|
|
|
11895
12060
|
query2.cteFor = this;
|
|
11896
12061
|
list.push({ as, query: query2 });
|
|
11897
12062
|
};
|
|
11898
|
-
|
|
12063
|
+
expr.flat().forEach((e) => {
|
|
11899
12064
|
if (e == null) {
|
|
11900
12065
|
} else if (e.as && e.query) {
|
|
11901
12066
|
add(e.as, e.query);
|
|
@@ -11909,13 +12074,13 @@ var Query = class {
|
|
|
11909
12074
|
return this;
|
|
11910
12075
|
}
|
|
11911
12076
|
}
|
|
11912
|
-
select(...
|
|
12077
|
+
select(...expr) {
|
|
11913
12078
|
const { query } = this;
|
|
11914
|
-
if (
|
|
12079
|
+
if (expr.length === 0) {
|
|
11915
12080
|
return query.select;
|
|
11916
12081
|
} else {
|
|
11917
12082
|
const list = [];
|
|
11918
|
-
|
|
12083
|
+
for (const e of expr.flat()) {
|
|
11919
12084
|
if (e == null) {
|
|
11920
12085
|
} else if (typeof e === "string") {
|
|
11921
12086
|
list.push({ as: e, expr: asColumn(e) });
|
|
@@ -11928,32 +12093,32 @@ var Query = class {
|
|
|
11928
12093
|
list.push({ as: unquote(as), expr: asColumn(e[as]) });
|
|
11929
12094
|
}
|
|
11930
12095
|
}
|
|
11931
|
-
}
|
|
12096
|
+
}
|
|
11932
12097
|
query.select = query.select.concat(list);
|
|
11933
12098
|
return this;
|
|
11934
12099
|
}
|
|
11935
12100
|
}
|
|
11936
|
-
$select(...
|
|
12101
|
+
$select(...expr) {
|
|
11937
12102
|
this.query.select = [];
|
|
11938
|
-
return this.select(...
|
|
12103
|
+
return this.select(...expr);
|
|
11939
12104
|
}
|
|
11940
12105
|
distinct(value = true) {
|
|
11941
12106
|
this.query.distinct = !!value;
|
|
11942
12107
|
return this;
|
|
11943
12108
|
}
|
|
11944
|
-
from(...
|
|
12109
|
+
from(...expr) {
|
|
11945
12110
|
const { query } = this;
|
|
11946
|
-
if (
|
|
12111
|
+
if (expr.length === 0) {
|
|
11947
12112
|
return query.from;
|
|
11948
12113
|
} else {
|
|
11949
12114
|
const list = [];
|
|
11950
|
-
|
|
12115
|
+
expr.flat().forEach((e) => {
|
|
11951
12116
|
if (e == null) {
|
|
11952
12117
|
} else if (typeof e === "string") {
|
|
11953
12118
|
list.push({ as: e, from: asRelation(e) });
|
|
11954
12119
|
} else if (e instanceof Ref) {
|
|
11955
12120
|
list.push({ as: e.table, from: e });
|
|
11956
|
-
} else if (isQuery(e) ||
|
|
12121
|
+
} else if (isQuery(e) || isSQLExpression(e)) {
|
|
11957
12122
|
list.push({ from: e });
|
|
11958
12123
|
} else if (Array.isArray(e)) {
|
|
11959
12124
|
list.push({ as: unquote(e[0]), from: asRelation(e[1]) });
|
|
@@ -11967,67 +12132,71 @@ var Query = class {
|
|
|
11967
12132
|
return this;
|
|
11968
12133
|
}
|
|
11969
12134
|
}
|
|
11970
|
-
$from(...
|
|
12135
|
+
$from(...expr) {
|
|
11971
12136
|
this.query.from = [];
|
|
11972
|
-
return this.from(...
|
|
12137
|
+
return this.from(...expr);
|
|
11973
12138
|
}
|
|
11974
|
-
sample(value) {
|
|
12139
|
+
sample(value, method) {
|
|
11975
12140
|
const { query } = this;
|
|
11976
12141
|
if (arguments.length === 0) {
|
|
11977
12142
|
return query.sample;
|
|
11978
12143
|
} else {
|
|
11979
12144
|
let spec = value;
|
|
11980
12145
|
if (typeof value === "number") {
|
|
11981
|
-
spec = value > 0 && value < 1 ? { perc: 100 * value } : { rows: Math.round(value) };
|
|
12146
|
+
spec = value > 0 && value < 1 ? { perc: 100 * value, method } : { rows: Math.round(value), method };
|
|
11982
12147
|
}
|
|
11983
12148
|
query.sample = spec;
|
|
11984
12149
|
return this;
|
|
11985
12150
|
}
|
|
11986
12151
|
}
|
|
11987
|
-
where(...
|
|
12152
|
+
where(...expr) {
|
|
11988
12153
|
const { query } = this;
|
|
11989
|
-
if (
|
|
12154
|
+
if (expr.length === 0) {
|
|
11990
12155
|
return query.where;
|
|
11991
12156
|
} else {
|
|
11992
12157
|
query.where = query.where.concat(
|
|
11993
|
-
|
|
12158
|
+
expr.flat().filter((x) => x)
|
|
11994
12159
|
);
|
|
11995
12160
|
return this;
|
|
11996
12161
|
}
|
|
11997
12162
|
}
|
|
11998
|
-
$where(...
|
|
12163
|
+
$where(...expr) {
|
|
11999
12164
|
this.query.where = [];
|
|
12000
|
-
return this.where(...
|
|
12165
|
+
return this.where(...expr);
|
|
12001
12166
|
}
|
|
12002
|
-
groupby(...
|
|
12167
|
+
groupby(...expr) {
|
|
12003
12168
|
const { query } = this;
|
|
12004
|
-
if (
|
|
12169
|
+
if (expr.length === 0) {
|
|
12005
12170
|
return query.groupby;
|
|
12006
12171
|
} else {
|
|
12007
12172
|
query.groupby = query.groupby.concat(
|
|
12008
|
-
|
|
12173
|
+
expr.flat().filter((x) => x).map(asColumn)
|
|
12009
12174
|
);
|
|
12010
12175
|
return this;
|
|
12011
12176
|
}
|
|
12012
12177
|
}
|
|
12013
|
-
|
|
12178
|
+
$groupby(...expr) {
|
|
12179
|
+
this.query.groupby = [];
|
|
12180
|
+
return this.groupby(...expr);
|
|
12181
|
+
}
|
|
12182
|
+
having(...expr) {
|
|
12014
12183
|
const { query } = this;
|
|
12015
|
-
if (
|
|
12184
|
+
if (expr.length === 0) {
|
|
12016
12185
|
return query.having;
|
|
12017
12186
|
} else {
|
|
12018
12187
|
query.having = query.having.concat(
|
|
12019
|
-
|
|
12188
|
+
expr.flat().filter((x) => x)
|
|
12020
12189
|
);
|
|
12021
12190
|
return this;
|
|
12022
12191
|
}
|
|
12023
12192
|
}
|
|
12024
|
-
window(...
|
|
12193
|
+
window(...expr) {
|
|
12025
12194
|
const { query } = this;
|
|
12026
|
-
if (
|
|
12195
|
+
if (expr.length === 0) {
|
|
12027
12196
|
return query.window;
|
|
12028
12197
|
} else {
|
|
12029
12198
|
const list = [];
|
|
12030
|
-
|
|
12199
|
+
expr.flat().forEach((e) => {
|
|
12031
12200
|
if (e == null) {
|
|
12032
12201
|
} else {
|
|
12033
12202
|
for (const as in e) {
|
|
@@ -12039,24 +12208,24 @@ var Query = class {
|
|
|
12039
12208
|
return this;
|
|
12040
12209
|
}
|
|
12041
12210
|
}
|
|
12042
|
-
qualify(...
|
|
12211
|
+
qualify(...expr) {
|
|
12043
12212
|
const { query } = this;
|
|
12044
|
-
if (
|
|
12213
|
+
if (expr.length === 0) {
|
|
12045
12214
|
return query.qualify;
|
|
12046
12215
|
} else {
|
|
12047
12216
|
query.qualify = query.qualify.concat(
|
|
12048
|
-
|
|
12217
|
+
expr.flat().filter((x) => x)
|
|
12049
12218
|
);
|
|
12050
12219
|
return this;
|
|
12051
12220
|
}
|
|
12052
12221
|
}
|
|
12053
|
-
orderby(...
|
|
12222
|
+
orderby(...expr) {
|
|
12054
12223
|
const { query } = this;
|
|
12055
|
-
if (
|
|
12224
|
+
if (expr.length === 0) {
|
|
12056
12225
|
return query.orderby;
|
|
12057
12226
|
} else {
|
|
12058
12227
|
query.orderby = query.orderby.concat(
|
|
12059
|
-
|
|
12228
|
+
expr.flat().filter((x) => x).map(asColumn)
|
|
12060
12229
|
);
|
|
12061
12230
|
return this;
|
|
12062
12231
|
}
|
|
@@ -12116,7 +12285,7 @@ var Query = class {
|
|
|
12116
12285
|
sql2.push(`WITH ${list.join(", ")}`);
|
|
12117
12286
|
}
|
|
12118
12287
|
const sels = select.map(
|
|
12119
|
-
({ as, expr
|
|
12288
|
+
({ as, expr }) => isColumnRefFor(expr, as) && !expr.table ? `${expr}` : `${expr} AS "${as}"`
|
|
12120
12289
|
);
|
|
12121
12290
|
sql2.push(`SELECT${distinct2 ? " DISTINCT" : ""} ${sels.join(", ")}`);
|
|
12122
12291
|
if (from.length) {
|
|
@@ -12126,17 +12295,17 @@ var Query = class {
|
|
|
12126
12295
|
});
|
|
12127
12296
|
sql2.push(`FROM ${rels.join(", ")}`);
|
|
12128
12297
|
}
|
|
12298
|
+
if (where.length) {
|
|
12299
|
+
const clauses = where.map(String).filter((x) => x).join(" AND ");
|
|
12300
|
+
if (clauses)
|
|
12301
|
+
sql2.push(`WHERE ${clauses}`);
|
|
12302
|
+
}
|
|
12129
12303
|
if (sample) {
|
|
12130
12304
|
const { rows, perc, method, seed } = sample;
|
|
12131
12305
|
const size = rows ? `${rows} ROWS` : `${perc} PERCENT`;
|
|
12132
12306
|
const how = method ? ` (${method}${seed != null ? `, ${seed}` : ""})` : "";
|
|
12133
12307
|
sql2.push(`USING SAMPLE ${size}${how}`);
|
|
12134
12308
|
}
|
|
12135
|
-
if (where.length) {
|
|
12136
|
-
const clauses = where.map(String).filter((x) => x).join(" AND ");
|
|
12137
|
-
if (clauses)
|
|
12138
|
-
sql2.push(`WHERE ${clauses}`);
|
|
12139
|
-
}
|
|
12140
12309
|
if (groupby.length) {
|
|
12141
12310
|
sql2.push(`GROUP BY ${groupby.join(", ")}`);
|
|
12142
12311
|
}
|
|
@@ -12146,7 +12315,7 @@ var Query = class {
|
|
|
12146
12315
|
sql2.push(`HAVING ${clauses}`);
|
|
12147
12316
|
}
|
|
12148
12317
|
if (window.length) {
|
|
12149
|
-
const windows = window.map(({ as, expr
|
|
12318
|
+
const windows = window.map(({ as, expr }) => `"${as}" AS (${expr})`);
|
|
12150
12319
|
sql2.push(`WINDOW ${windows.join(", ")}`);
|
|
12151
12320
|
}
|
|
12152
12321
|
if (qualify.length) {
|
|
@@ -12177,13 +12346,13 @@ var SetOperation = class {
|
|
|
12177
12346
|
q.query = { ...this.query };
|
|
12178
12347
|
return q;
|
|
12179
12348
|
}
|
|
12180
|
-
orderby(...
|
|
12349
|
+
orderby(...expr) {
|
|
12181
12350
|
const { query } = this;
|
|
12182
|
-
if (
|
|
12351
|
+
if (expr.length === 0) {
|
|
12183
12352
|
return query.orderby;
|
|
12184
12353
|
} else {
|
|
12185
12354
|
query.orderby = query.orderby.concat(
|
|
12186
|
-
|
|
12355
|
+
expr.flat().filter((x) => x).map(asColumn)
|
|
12187
12356
|
);
|
|
12188
12357
|
return this;
|
|
12189
12358
|
}
|
|
@@ -12250,8 +12419,8 @@ var statMap = {
|
|
|
12250
12419
|
[Min]: min,
|
|
12251
12420
|
[Nulls]: (column2) => count().where(isNull(column2))
|
|
12252
12421
|
};
|
|
12253
|
-
function summarize({ table, column: column2 }, stats) {
|
|
12254
|
-
return Query.from(
|
|
12422
|
+
function summarize({ table: table2, column: column2 }, stats) {
|
|
12423
|
+
return Query.from(table2).select(stats.map((s) => [s, statMap[s](column2)]));
|
|
12255
12424
|
}
|
|
12256
12425
|
|
|
12257
12426
|
// ../core/src/Catalog.js
|
|
@@ -12264,38 +12433,35 @@ var Catalog = class {
|
|
|
12264
12433
|
clear() {
|
|
12265
12434
|
this.tables = object();
|
|
12266
12435
|
}
|
|
12267
|
-
|
|
12436
|
+
tableInfo(table2) {
|
|
12268
12437
|
const cache = this.tables;
|
|
12269
|
-
if (cache[
|
|
12270
|
-
return cache[
|
|
12438
|
+
if (cache[table2]) {
|
|
12439
|
+
return cache[table2];
|
|
12271
12440
|
}
|
|
12272
|
-
const
|
|
12273
|
-
|
|
12274
|
-
|
|
12275
|
-
);
|
|
12276
|
-
return cache[table] = q.then((result) => {
|
|
12277
|
-
const columns = object();
|
|
12278
|
-
for (const entry of result) {
|
|
12279
|
-
columns[entry.column_name] = {
|
|
12280
|
-
table,
|
|
12281
|
-
column: entry.column_name,
|
|
12282
|
-
sqlType: entry.column_type,
|
|
12283
|
-
type: jsType(entry.column_type),
|
|
12284
|
-
nullable: entry.null === "YES"
|
|
12285
|
-
};
|
|
12286
|
-
}
|
|
12287
|
-
return columns;
|
|
12441
|
+
const infoPromise = getTableInfo(this.mc, table2).catch((err) => {
|
|
12442
|
+
cache[table2] = null;
|
|
12443
|
+
throw err;
|
|
12288
12444
|
});
|
|
12445
|
+
return cache[table2] = infoPromise;
|
|
12289
12446
|
}
|
|
12290
|
-
async fieldInfo({ table, column: column2, stats }) {
|
|
12291
|
-
const tableInfo = await this.tableInfo(
|
|
12447
|
+
async fieldInfo({ table: table2, column: column2, stats }) {
|
|
12448
|
+
const tableInfo = await this.tableInfo(table2);
|
|
12292
12449
|
const colInfo = tableInfo[column2];
|
|
12293
12450
|
if (colInfo == null)
|
|
12294
12451
|
return;
|
|
12295
12452
|
if (!stats?.length)
|
|
12296
12453
|
return colInfo;
|
|
12297
|
-
const result = await this.mc.query(
|
|
12454
|
+
const result = await this.mc.query(
|
|
12455
|
+
summarize(colInfo, stats),
|
|
12456
|
+
{ persist: true }
|
|
12457
|
+
);
|
|
12298
12458
|
const info = { ...colInfo, ...Array.from(result)[0] };
|
|
12459
|
+
for (const key in info) {
|
|
12460
|
+
const value = info[key];
|
|
12461
|
+
if (typeof value === "bigint") {
|
|
12462
|
+
info[key] = Number(value);
|
|
12463
|
+
}
|
|
12464
|
+
}
|
|
12299
12465
|
return info;
|
|
12300
12466
|
}
|
|
12301
12467
|
async queryFields(fields) {
|
|
@@ -12304,6 +12470,23 @@ var Catalog = class {
|
|
|
12304
12470
|
return data.filter((x) => x);
|
|
12305
12471
|
}
|
|
12306
12472
|
};
|
|
12473
|
+
async function getTableInfo(mc, table2) {
|
|
12474
|
+
const result = await mc.query(
|
|
12475
|
+
`DESCRIBE "${table2}"`,
|
|
12476
|
+
{ type: "json", cache: false }
|
|
12477
|
+
);
|
|
12478
|
+
const columns = object();
|
|
12479
|
+
for (const entry of result) {
|
|
12480
|
+
columns[entry.column_name] = {
|
|
12481
|
+
table: table2,
|
|
12482
|
+
column: entry.column_name,
|
|
12483
|
+
sqlType: entry.column_type,
|
|
12484
|
+
type: jsType(entry.column_type),
|
|
12485
|
+
nullable: entry.null === "YES"
|
|
12486
|
+
};
|
|
12487
|
+
}
|
|
12488
|
+
return columns;
|
|
12489
|
+
}
|
|
12307
12490
|
async function resolveFields(catalog, list) {
|
|
12308
12491
|
return list.length === 1 && list[0].column === "*" ? Object.values(await catalog.tableInfo(list[0].table)) : list;
|
|
12309
12492
|
}
|
|
@@ -12332,11 +12515,6 @@ function fnv_mix(a) {
|
|
|
12332
12515
|
return a & 4294967295;
|
|
12333
12516
|
}
|
|
12334
12517
|
|
|
12335
|
-
// ../core/src/util/skip-client.js
|
|
12336
|
-
function skipClient(client, clause) {
|
|
12337
|
-
return clause?.clients?.has(client);
|
|
12338
|
-
}
|
|
12339
|
-
|
|
12340
12518
|
// ../core/src/DataTileIndexer.js
|
|
12341
12519
|
var identity = (x) => x;
|
|
12342
12520
|
var DataTileIndexer = class {
|
|
@@ -12351,32 +12529,38 @@ var DataTileIndexer = class {
|
|
|
12351
12529
|
this.indices = null;
|
|
12352
12530
|
this.activeView = null;
|
|
12353
12531
|
}
|
|
12532
|
+
clear() {
|
|
12533
|
+
if (this.indices) {
|
|
12534
|
+
this.mc.cancel(Array.from(this.indices.values(), (index) => index.result));
|
|
12535
|
+
this.indices = null;
|
|
12536
|
+
}
|
|
12537
|
+
}
|
|
12354
12538
|
index(clients, active) {
|
|
12355
12539
|
if (this.clients !== clients) {
|
|
12356
|
-
const cols = Array.from(clients
|
|
12540
|
+
const cols = Array.from(clients, getIndexColumns);
|
|
12357
12541
|
const from = cols[0]?.from;
|
|
12358
12542
|
this.enabled = cols.every((c) => c && c.from === from);
|
|
12359
12543
|
this.clients = clients;
|
|
12360
|
-
this.indices = null;
|
|
12361
12544
|
this.activeView = null;
|
|
12545
|
+
this.clear();
|
|
12362
12546
|
}
|
|
12363
12547
|
if (!this.enabled)
|
|
12364
12548
|
return false;
|
|
12365
12549
|
active = active || this.selection.active;
|
|
12366
12550
|
const { source } = active;
|
|
12551
|
+
if (source && source === this.activeView?.source)
|
|
12552
|
+
return true;
|
|
12553
|
+
this.clear();
|
|
12367
12554
|
if (!source)
|
|
12368
12555
|
return false;
|
|
12369
|
-
if (source === this.activeView?.source)
|
|
12370
|
-
return true;
|
|
12371
12556
|
const activeView = this.activeView = getActiveView(active);
|
|
12372
12557
|
if (!activeView)
|
|
12373
12558
|
return false;
|
|
12374
12559
|
this.mc.logger().warn("DATA TILE INDEX CONSTRUCTION");
|
|
12375
|
-
const sel = this.selection.
|
|
12560
|
+
const sel = this.selection.remove(source);
|
|
12376
12561
|
const indices = this.indices = /* @__PURE__ */ new Map();
|
|
12377
|
-
const promises = [];
|
|
12378
12562
|
for (const client of clients) {
|
|
12379
|
-
if (sel.
|
|
12563
|
+
if (sel.skip(client, active))
|
|
12380
12564
|
continue;
|
|
12381
12565
|
const index = getIndexColumns(client);
|
|
12382
12566
|
const query = client.query(sel.predicate(client)).select({ ...activeView.columns, ...index.count }).groupby(Object.keys(activeView.columns));
|
|
@@ -12387,11 +12571,10 @@ var DataTileIndexer = class {
|
|
|
12387
12571
|
}
|
|
12388
12572
|
const sql2 = query.toString();
|
|
12389
12573
|
const id = (fnv_hash(sql2) >>> 0).toString(16);
|
|
12390
|
-
const
|
|
12391
|
-
|
|
12392
|
-
|
|
12574
|
+
const table2 = `tile_index_${id}`;
|
|
12575
|
+
const result = createIndex(this.mc, table2, sql2);
|
|
12576
|
+
indices.set(client, { table: table2, result, ...index });
|
|
12393
12577
|
}
|
|
12394
|
-
return promises;
|
|
12395
12578
|
}
|
|
12396
12579
|
async update() {
|
|
12397
12580
|
const { clients, selection, activeView } = this;
|
|
@@ -12407,11 +12590,9 @@ var DataTileIndexer = class {
|
|
|
12407
12590
|
if (!filter) {
|
|
12408
12591
|
filter = this.activeView.predicate(this.selection.active.predicate);
|
|
12409
12592
|
}
|
|
12410
|
-
const { table, dims, aggr } = index;
|
|
12411
|
-
|
|
12412
|
-
|
|
12413
|
-
Query.select(dims, aggr).from(table).groupby(dims).where(filter)
|
|
12414
|
-
);
|
|
12593
|
+
const { table: table2, dims, aggr } = index;
|
|
12594
|
+
const query = Query.select(dims, aggr).from(table2).groupby(dims).where(filter);
|
|
12595
|
+
return this.mc.updateClient(client, query);
|
|
12415
12596
|
}
|
|
12416
12597
|
};
|
|
12417
12598
|
function getActiveView(clause) {
|
|
@@ -12419,19 +12600,19 @@ function getActiveView(clause) {
|
|
|
12419
12600
|
let columns = clause.predicate?.columns;
|
|
12420
12601
|
if (!schema || !columns)
|
|
12421
12602
|
return null;
|
|
12422
|
-
const { type, scales } = schema;
|
|
12603
|
+
const { type, scales, pixelSize = 1 } = schema;
|
|
12423
12604
|
let predicate;
|
|
12424
12605
|
if (type === "interval" && scales) {
|
|
12425
|
-
const bins = scales.map((s) => binInterval(s));
|
|
12606
|
+
const bins = scales.map((s) => binInterval(s, pixelSize));
|
|
12426
12607
|
if (bins.some((b) => b == null))
|
|
12427
12608
|
return null;
|
|
12428
12609
|
if (bins.length === 1) {
|
|
12429
|
-
predicate = (p) => p ? isBetween("active0", p.
|
|
12430
|
-
columns = { active0: bins[0](clause.predicate.
|
|
12610
|
+
predicate = (p) => p ? isBetween("active0", p.range.map(bins[0])) : [];
|
|
12611
|
+
columns = { active0: bins[0](clause.predicate.field) };
|
|
12431
12612
|
} else {
|
|
12432
|
-
predicate = (p) => p ? and(p.
|
|
12613
|
+
predicate = (p) => p ? and(p.children.map(({ range }, i) => isBetween(`active${i}`, range.map(bins[i])))) : [];
|
|
12433
12614
|
columns = Object.fromEntries(
|
|
12434
|
-
clause.predicate.
|
|
12615
|
+
clause.predicate.children.map((p, i) => [`active${i}`, bins[i](p.field)])
|
|
12435
12616
|
);
|
|
12436
12617
|
}
|
|
12437
12618
|
} else if (type === "point") {
|
|
@@ -12442,49 +12623,43 @@ function getActiveView(clause) {
|
|
|
12442
12623
|
}
|
|
12443
12624
|
return { source, columns, predicate };
|
|
12444
12625
|
}
|
|
12445
|
-
function binInterval(scale) {
|
|
12446
|
-
const { type, domain, range
|
|
12447
|
-
let lift,
|
|
12626
|
+
function binInterval(scale, pixelSize) {
|
|
12627
|
+
const { type, domain, range } = scale;
|
|
12628
|
+
let lift, toSql;
|
|
12448
12629
|
switch (type) {
|
|
12449
12630
|
case "linear":
|
|
12450
12631
|
lift = identity;
|
|
12451
|
-
|
|
12632
|
+
toSql = asColumn;
|
|
12452
12633
|
break;
|
|
12453
12634
|
case "log":
|
|
12454
12635
|
lift = Math.log;
|
|
12455
|
-
|
|
12636
|
+
toSql = (c) => sql`LN(${asColumn(c)})`;
|
|
12456
12637
|
break;
|
|
12457
12638
|
case "symlog":
|
|
12458
12639
|
lift = (x) => Math.sign(x) * Math.log1p(Math.abs(x));
|
|
12459
|
-
|
|
12640
|
+
toSql = (c) => (c = asColumn(c), sql`SIGN(${c}) * LN(1 + ABS(${c}))`);
|
|
12460
12641
|
break;
|
|
12461
12642
|
case "sqrt":
|
|
12462
12643
|
lift = Math.sqrt;
|
|
12463
|
-
|
|
12644
|
+
toSql = (c) => sql`SQRT(${asColumn(c)})`;
|
|
12464
12645
|
break;
|
|
12465
12646
|
case "utc":
|
|
12466
12647
|
case "time":
|
|
12467
12648
|
lift = (x) => +x;
|
|
12468
|
-
|
|
12649
|
+
toSql = (c) => c instanceof Date ? +c : epoch_ms(asColumn(c));
|
|
12469
12650
|
break;
|
|
12470
12651
|
}
|
|
12471
|
-
return lift ? binFunction(domain,
|
|
12652
|
+
return lift ? binFunction(domain, range, pixelSize, lift, toSql) : null;
|
|
12472
12653
|
}
|
|
12473
|
-
function binFunction(domain,
|
|
12654
|
+
function binFunction(domain, range, pixelSize, lift, toSql) {
|
|
12474
12655
|
const lo = lift(Math.min(domain[0], domain[1]));
|
|
12475
12656
|
const hi = lift(Math.max(domain[0], domain[1]));
|
|
12476
|
-
const a = Math.abs(lift(
|
|
12477
|
-
|
|
12478
|
-
|
|
12479
|
-
asColumn(value).columns
|
|
12480
|
-
);
|
|
12657
|
+
const a = Math.abs(lift(range[1]) - lift(range[0])) / (hi - lo) / pixelSize;
|
|
12658
|
+
const s = pixelSize === 1 ? "" : `${pixelSize}::INTEGER * `;
|
|
12659
|
+
return (value) => sql`${s}FLOOR(${a}::DOUBLE * (${toSql(value)} - ${lo}::DOUBLE))::INTEGER`;
|
|
12481
12660
|
}
|
|
12482
|
-
|
|
12483
|
-
|
|
12484
|
-
await mc.exec(`CREATE TEMP TABLE IF NOT EXISTS ${table} AS ${query}`);
|
|
12485
|
-
} catch (err) {
|
|
12486
|
-
mc.logger().error(err);
|
|
12487
|
-
}
|
|
12661
|
+
function createIndex(mc, table2, query) {
|
|
12662
|
+
return mc.exec(`CREATE TEMP TABLE IF NOT EXISTS ${table2} AS ${query}`);
|
|
12488
12663
|
}
|
|
12489
12664
|
var NO_INDEX = { from: NaN };
|
|
12490
12665
|
function getIndexColumns(client) {
|
|
@@ -12495,24 +12670,24 @@ function getIndexColumns(client) {
|
|
|
12495
12670
|
if (!from || !q.groupby)
|
|
12496
12671
|
return NO_INDEX;
|
|
12497
12672
|
const g = new Set(q.groupby().map((c) => c.column));
|
|
12498
|
-
|
|
12499
|
-
|
|
12673
|
+
const aggr = [];
|
|
12674
|
+
const dims = [];
|
|
12500
12675
|
let count2;
|
|
12501
12676
|
for (const { as, expr: { aggregate } } of q.select()) {
|
|
12502
12677
|
switch (aggregate?.toUpperCase()) {
|
|
12503
12678
|
case "COUNT":
|
|
12504
12679
|
case "SUM":
|
|
12505
|
-
aggr.push({ [as]:
|
|
12680
|
+
aggr.push({ [as]: sql`SUM("${as}")::DOUBLE` });
|
|
12506
12681
|
break;
|
|
12507
12682
|
case "AVG":
|
|
12508
12683
|
count2 = "_count_";
|
|
12509
|
-
aggr.push({ [as]:
|
|
12684
|
+
aggr.push({ [as]: sql`(SUM("${as}" * ${count2}) / SUM(${count2}))::DOUBLE` });
|
|
12510
12685
|
break;
|
|
12511
12686
|
case "MAX":
|
|
12512
|
-
aggr.push({ [as]:
|
|
12687
|
+
aggr.push({ [as]: sql`MAX("${as}")` });
|
|
12513
12688
|
break;
|
|
12514
12689
|
case "MIN":
|
|
12515
|
-
aggr.push({ [as]:
|
|
12690
|
+
aggr.push({ [as]: sql`MIN("${as}")` });
|
|
12516
12691
|
break;
|
|
12517
12692
|
default:
|
|
12518
12693
|
if (g.has(as))
|
|
@@ -12524,7 +12699,7 @@ function getIndexColumns(client) {
|
|
|
12524
12699
|
return {
|
|
12525
12700
|
aggr,
|
|
12526
12701
|
dims,
|
|
12527
|
-
count: count2 ? { [count2]:
|
|
12702
|
+
count: count2 ? { [count2]: sql`COUNT(*)` } : {},
|
|
12528
12703
|
from
|
|
12529
12704
|
};
|
|
12530
12705
|
}
|
|
@@ -12537,7 +12712,7 @@ function getBaseTable(query) {
|
|
|
12537
12712
|
if (subq.length === 0)
|
|
12538
12713
|
return from[0].from.table;
|
|
12539
12714
|
}
|
|
12540
|
-
|
|
12715
|
+
const base = getBaseTable(subq[0]);
|
|
12541
12716
|
for (let i = 1; i < subq.length; ++i) {
|
|
12542
12717
|
const from = getBaseTable(subq[i]);
|
|
12543
12718
|
if (from === void 0)
|
|
@@ -12561,42 +12736,6 @@ function subqueryPushdown(query, cols) {
|
|
|
12561
12736
|
pushdown(query);
|
|
12562
12737
|
}
|
|
12563
12738
|
|
|
12564
|
-
// ../core/src/util/throttle.js
|
|
12565
|
-
var NIL = {};
|
|
12566
|
-
function throttle(callback, debounce = false) {
|
|
12567
|
-
let curr;
|
|
12568
|
-
let next;
|
|
12569
|
-
let pending = NIL;
|
|
12570
|
-
function invoke(event) {
|
|
12571
|
-
curr = callback(event).then(() => {
|
|
12572
|
-
if (next) {
|
|
12573
|
-
const { value } = next;
|
|
12574
|
-
next = null;
|
|
12575
|
-
invoke(value);
|
|
12576
|
-
} else {
|
|
12577
|
-
curr = null;
|
|
12578
|
-
}
|
|
12579
|
-
});
|
|
12580
|
-
}
|
|
12581
|
-
function enqueue(event) {
|
|
12582
|
-
next = { event };
|
|
12583
|
-
}
|
|
12584
|
-
function process(event) {
|
|
12585
|
-
curr ? enqueue(event) : invoke(event);
|
|
12586
|
-
}
|
|
12587
|
-
function delay(event) {
|
|
12588
|
-
if (pending !== event) {
|
|
12589
|
-
requestAnimationFrame(() => {
|
|
12590
|
-
const e = pending;
|
|
12591
|
-
pending = NIL;
|
|
12592
|
-
process(e);
|
|
12593
|
-
});
|
|
12594
|
-
}
|
|
12595
|
-
pending = event;
|
|
12596
|
-
}
|
|
12597
|
-
return debounce ? delay : process;
|
|
12598
|
-
}
|
|
12599
|
-
|
|
12600
12739
|
// ../core/src/FilterGroup.js
|
|
12601
12740
|
var FilterGroup = class {
|
|
12602
12741
|
constructor(coordinator2, selection, index = true) {
|
|
@@ -12605,10 +12744,8 @@ var FilterGroup = class {
|
|
|
12605
12744
|
this.clients = /* @__PURE__ */ new Set();
|
|
12606
12745
|
this.indexer = index ? new DataTileIndexer(this.mc, selection) : null;
|
|
12607
12746
|
const { value, activate } = this.handlers = {
|
|
12608
|
-
value:
|
|
12609
|
-
activate: (clause) =>
|
|
12610
|
-
this.indexer?.index(this.clients, clause);
|
|
12611
|
-
}
|
|
12747
|
+
value: () => this.update(),
|
|
12748
|
+
activate: (clause) => this.indexer?.index(this.clients, clause)
|
|
12612
12749
|
};
|
|
12613
12750
|
selection.addEventListener("value", value);
|
|
12614
12751
|
selection.addEventListener("activate", activate);
|
|
@@ -12631,7 +12768,7 @@ var FilterGroup = class {
|
|
|
12631
12768
|
}
|
|
12632
12769
|
return this;
|
|
12633
12770
|
}
|
|
12634
|
-
|
|
12771
|
+
update() {
|
|
12635
12772
|
const { mc, indexer, clients, selection } = this;
|
|
12636
12773
|
return indexer?.index(clients) ? indexer.update() : defaultUpdate(mc, clients, selection);
|
|
12637
12774
|
}
|
|
@@ -12645,79 +12782,425 @@ function defaultUpdate(mc, clients, selection) {
|
|
|
12645
12782
|
}));
|
|
12646
12783
|
}
|
|
12647
12784
|
|
|
12648
|
-
// ../core/src/
|
|
12649
|
-
|
|
12650
|
-
|
|
12651
|
-
|
|
12652
|
-
|
|
12653
|
-
|
|
12785
|
+
// ../core/src/util/query-result.js
|
|
12786
|
+
function queryResult() {
|
|
12787
|
+
let resolve;
|
|
12788
|
+
let reject;
|
|
12789
|
+
const p = new Promise((r, e) => {
|
|
12790
|
+
resolve = r;
|
|
12791
|
+
reject = e;
|
|
12792
|
+
});
|
|
12793
|
+
p.fulfill = (value) => (resolve(value), p);
|
|
12794
|
+
p.reject = (err) => (reject(err), p);
|
|
12795
|
+
return p;
|
|
12796
|
+
}
|
|
12797
|
+
|
|
12798
|
+
// ../core/src/QueryConsolidator.js
|
|
12799
|
+
function consolidator(enqueue, cache, record) {
|
|
12800
|
+
let pending = [];
|
|
12801
|
+
let id = 0;
|
|
12802
|
+
function run() {
|
|
12803
|
+
const groups = entryGroups(pending, cache);
|
|
12804
|
+
pending = [];
|
|
12805
|
+
id = 0;
|
|
12806
|
+
for (const group of groups) {
|
|
12807
|
+
consolidate(group, enqueue, record);
|
|
12808
|
+
processResults(group, cache);
|
|
12809
|
+
}
|
|
12654
12810
|
}
|
|
12655
|
-
|
|
12656
|
-
|
|
12657
|
-
|
|
12658
|
-
|
|
12659
|
-
|
|
12660
|
-
|
|
12661
|
-
|
|
12662
|
-
|
|
12663
|
-
|
|
12664
|
-
|
|
12665
|
-
|
|
12811
|
+
return {
|
|
12812
|
+
add(entry, priority) {
|
|
12813
|
+
if (entry.request.type === "arrow") {
|
|
12814
|
+
id = id || requestAnimationFrame(() => run());
|
|
12815
|
+
pending.push({ entry, priority, index: pending.length });
|
|
12816
|
+
} else {
|
|
12817
|
+
enqueue(entry, priority);
|
|
12818
|
+
}
|
|
12819
|
+
}
|
|
12820
|
+
};
|
|
12821
|
+
}
|
|
12822
|
+
function entryGroups(entries, cache) {
|
|
12823
|
+
const groups = [];
|
|
12824
|
+
const groupMap = /* @__PURE__ */ new Map();
|
|
12825
|
+
for (const query of entries) {
|
|
12826
|
+
const { entry: { request } } = query;
|
|
12827
|
+
const key = consolidationKey(request.query, cache);
|
|
12828
|
+
if (!groupMap.has(key)) {
|
|
12829
|
+
const list = [];
|
|
12830
|
+
groups.push(list);
|
|
12831
|
+
groupMap.set(key, list);
|
|
12832
|
+
}
|
|
12833
|
+
groupMap.get(key).push(query);
|
|
12666
12834
|
}
|
|
12667
|
-
|
|
12668
|
-
|
|
12835
|
+
return groups;
|
|
12836
|
+
}
|
|
12837
|
+
function consolidationKey(query, cache) {
|
|
12838
|
+
const sql2 = `${query}`;
|
|
12839
|
+
if (query instanceof Query && !cache.get(sql2)) {
|
|
12840
|
+
if (query.orderby().length || query.where().length || query.qualify().length || query.having().length) {
|
|
12841
|
+
return sql2;
|
|
12842
|
+
}
|
|
12843
|
+
const q = query.clone().$select("*");
|
|
12844
|
+
const groupby = query.groupby();
|
|
12845
|
+
if (groupby.length) {
|
|
12846
|
+
const map = {};
|
|
12847
|
+
query.select().forEach(({ as, expr }) => map[as] = expr);
|
|
12848
|
+
q.$groupby(groupby.map((e) => e instanceof Ref && map[e.column] || e));
|
|
12849
|
+
}
|
|
12850
|
+
return `${q}`;
|
|
12851
|
+
} else {
|
|
12852
|
+
return sql2;
|
|
12669
12853
|
}
|
|
12670
|
-
|
|
12671
|
-
|
|
12672
|
-
|
|
12673
|
-
|
|
12674
|
-
|
|
12854
|
+
}
|
|
12855
|
+
function consolidate(group, enqueue, record) {
|
|
12856
|
+
if (shouldConsolidate(group)) {
|
|
12857
|
+
enqueue({
|
|
12858
|
+
request: {
|
|
12859
|
+
type: "arrow",
|
|
12860
|
+
cache: false,
|
|
12861
|
+
record: false,
|
|
12862
|
+
query: consolidatedQuery(group, record)
|
|
12863
|
+
},
|
|
12864
|
+
result: group.result = queryResult()
|
|
12865
|
+
});
|
|
12866
|
+
} else {
|
|
12867
|
+
for (const { entry, priority } of group) {
|
|
12868
|
+
enqueue(entry, priority);
|
|
12869
|
+
}
|
|
12870
|
+
}
|
|
12871
|
+
}
|
|
12872
|
+
function shouldConsolidate(group) {
|
|
12873
|
+
if (group.length > 1) {
|
|
12874
|
+
const sql2 = `${group[0].entry.request.query}`;
|
|
12875
|
+
for (let i = 1; i < group.length; ++i) {
|
|
12876
|
+
if (sql2 !== `${group[i].entry.request.query}`) {
|
|
12877
|
+
return true;
|
|
12878
|
+
}
|
|
12879
|
+
}
|
|
12880
|
+
}
|
|
12881
|
+
return false;
|
|
12882
|
+
}
|
|
12883
|
+
function consolidatedQuery(group, record) {
|
|
12884
|
+
const maps = group.maps = [];
|
|
12885
|
+
const fields = /* @__PURE__ */ new Map();
|
|
12886
|
+
for (const item of group) {
|
|
12887
|
+
const { query: query2 } = item.entry.request;
|
|
12888
|
+
const fieldMap = [];
|
|
12889
|
+
maps.push(fieldMap);
|
|
12890
|
+
for (const { as, expr } of query2.select()) {
|
|
12891
|
+
const e = `${expr}`;
|
|
12892
|
+
if (!fields.has(e)) {
|
|
12893
|
+
fields.set(e, [`col${fields.size}`, expr]);
|
|
12894
|
+
}
|
|
12895
|
+
const [name] = fields.get(e);
|
|
12896
|
+
fieldMap.push([name, as]);
|
|
12897
|
+
}
|
|
12898
|
+
record(`${query2}`);
|
|
12899
|
+
}
|
|
12900
|
+
const query = group[0].entry.request.query.clone();
|
|
12901
|
+
const groupby = query.groupby();
|
|
12902
|
+
if (groupby.length) {
|
|
12903
|
+
const map = {};
|
|
12904
|
+
group.maps[0].forEach(([name, as]) => map[as] = name);
|
|
12905
|
+
query.$groupby(groupby.map((e) => e instanceof Ref && map[e.column] || e));
|
|
12906
|
+
}
|
|
12907
|
+
return query.$select(Array.from(fields.values()));
|
|
12908
|
+
}
|
|
12909
|
+
async function processResults(group, cache) {
|
|
12910
|
+
const { maps, result } = group;
|
|
12911
|
+
if (!maps)
|
|
12912
|
+
return;
|
|
12913
|
+
let data;
|
|
12914
|
+
try {
|
|
12915
|
+
data = await result;
|
|
12916
|
+
} catch (err) {
|
|
12917
|
+
for (const { entry } of group) {
|
|
12918
|
+
entry.result.reject(err);
|
|
12919
|
+
}
|
|
12920
|
+
return;
|
|
12921
|
+
}
|
|
12922
|
+
group.forEach(({ entry }, index) => {
|
|
12923
|
+
const { request, result: result2 } = entry;
|
|
12924
|
+
const projected = projectResult(data, maps[index]);
|
|
12925
|
+
if (request.cache) {
|
|
12926
|
+
cache.set(String(request.query), projected);
|
|
12927
|
+
}
|
|
12928
|
+
result2.fulfill(projected);
|
|
12929
|
+
});
|
|
12930
|
+
}
|
|
12931
|
+
function projectResult(data, map) {
|
|
12932
|
+
if (map) {
|
|
12933
|
+
const cols = {};
|
|
12934
|
+
for (const [name, as] of map) {
|
|
12935
|
+
cols[as] = data.getChild(name);
|
|
12675
12936
|
}
|
|
12937
|
+
return new data.constructor(cols);
|
|
12938
|
+
} else {
|
|
12939
|
+
return data;
|
|
12676
12940
|
}
|
|
12677
|
-
|
|
12678
|
-
|
|
12679
|
-
|
|
12680
|
-
|
|
12681
|
-
|
|
12682
|
-
|
|
12941
|
+
}
|
|
12942
|
+
|
|
12943
|
+
// ../core/src/util/cache.js
|
|
12944
|
+
var requestIdle = typeof requestIdleCallback !== "undefined" ? requestIdleCallback : setTimeout;
|
|
12945
|
+
var voidCache = () => ({
|
|
12946
|
+
get: () => void 0,
|
|
12947
|
+
set: (key, value) => value,
|
|
12948
|
+
clear: () => {
|
|
12683
12949
|
}
|
|
12684
|
-
|
|
12685
|
-
|
|
12950
|
+
});
|
|
12951
|
+
function lruCache({
|
|
12952
|
+
max: max2 = 1e3,
|
|
12953
|
+
// max entries
|
|
12954
|
+
ttl = 3 * 60 * 60 * 1e3
|
|
12955
|
+
// time-to-live, default 3 hours
|
|
12956
|
+
} = {}) {
|
|
12957
|
+
let cache = /* @__PURE__ */ new Map();
|
|
12958
|
+
function evict() {
|
|
12959
|
+
const expire = performance.now() - ttl;
|
|
12686
12960
|
let lruKey = null;
|
|
12687
12961
|
let lruLast = Infinity;
|
|
12688
|
-
for (const [key, value] of
|
|
12962
|
+
for (const [key, value] of cache) {
|
|
12689
12963
|
const { last: last2 } = value;
|
|
12690
12964
|
if (last2 < lruLast) {
|
|
12691
12965
|
lruKey = key;
|
|
12692
12966
|
lruLast = last2;
|
|
12693
12967
|
}
|
|
12694
12968
|
if (expire > last2) {
|
|
12695
|
-
|
|
12969
|
+
cache.delete(key);
|
|
12696
12970
|
}
|
|
12697
12971
|
}
|
|
12698
12972
|
if (lruKey) {
|
|
12699
|
-
|
|
12973
|
+
cache.delete(lruKey);
|
|
12700
12974
|
}
|
|
12701
12975
|
}
|
|
12702
|
-
};
|
|
12703
|
-
|
|
12704
|
-
// ../core/src/util/void-logger.js
|
|
12705
|
-
function voidLogger() {
|
|
12706
12976
|
return {
|
|
12707
|
-
|
|
12708
|
-
|
|
12709
|
-
|
|
12710
|
-
|
|
12711
|
-
|
|
12977
|
+
get(key) {
|
|
12978
|
+
const entry = cache.get(key);
|
|
12979
|
+
if (entry) {
|
|
12980
|
+
entry.last = performance.now();
|
|
12981
|
+
return entry.value;
|
|
12982
|
+
}
|
|
12712
12983
|
},
|
|
12713
|
-
|
|
12984
|
+
set(key, value) {
|
|
12985
|
+
cache.set(key, { last: performance.now(), value });
|
|
12986
|
+
if (cache.size > max2)
|
|
12987
|
+
requestIdle(evict);
|
|
12988
|
+
return value;
|
|
12714
12989
|
},
|
|
12715
|
-
|
|
12990
|
+
clear() {
|
|
12991
|
+
cache = /* @__PURE__ */ new Map();
|
|
12716
12992
|
}
|
|
12717
12993
|
};
|
|
12718
12994
|
}
|
|
12719
12995
|
|
|
12720
|
-
// ../core/src/
|
|
12996
|
+
// ../core/src/util/priority-queue.js
|
|
12997
|
+
function priorityQueue(ranks) {
|
|
12998
|
+
const queue = Array.from(
|
|
12999
|
+
{ length: ranks },
|
|
13000
|
+
() => ({ head: null, tail: null })
|
|
13001
|
+
);
|
|
13002
|
+
return {
|
|
13003
|
+
/**
|
|
13004
|
+
* Indicate if the queue is empty.
|
|
13005
|
+
* @returns [boolean] true if empty, false otherwise.
|
|
13006
|
+
*/
|
|
13007
|
+
isEmpty() {
|
|
13008
|
+
return queue.every((list) => !list.head);
|
|
13009
|
+
},
|
|
13010
|
+
/**
|
|
13011
|
+
* Insert an item into the queue with a given priority rank.
|
|
13012
|
+
* @param {*} item The item to add.
|
|
13013
|
+
* @param {number} rank The integer priority rank.
|
|
13014
|
+
* Priority ranks are integers starting at zero.
|
|
13015
|
+
* Lower ranks indicate higher priority.
|
|
13016
|
+
*/
|
|
13017
|
+
insert(item, rank2) {
|
|
13018
|
+
const list = queue[rank2];
|
|
13019
|
+
if (!list) {
|
|
13020
|
+
throw new Error(`Invalid queue priority rank: ${rank2}`);
|
|
13021
|
+
}
|
|
13022
|
+
const node = { item, next: null };
|
|
13023
|
+
if (list.head === null) {
|
|
13024
|
+
list.head = list.tail = node;
|
|
13025
|
+
} else {
|
|
13026
|
+
list.tail = list.tail.next = node;
|
|
13027
|
+
}
|
|
13028
|
+
},
|
|
13029
|
+
/**
|
|
13030
|
+
* Remove a set of items from the queue, regardless of priority rank.
|
|
13031
|
+
* If a provided item is not in the queue it will be ignored.
|
|
13032
|
+
* @param {(item: *) => boolean} test A predicate function to test
|
|
13033
|
+
* if an item should be removed (true to drop, false to keep).
|
|
13034
|
+
*/
|
|
13035
|
+
remove(test) {
|
|
13036
|
+
for (const list of queue) {
|
|
13037
|
+
let { head, tail } = list;
|
|
13038
|
+
for (let prev = null, curr = head; curr; prev = curr, curr = curr.next) {
|
|
13039
|
+
if (test(curr.item)) {
|
|
13040
|
+
if (curr === head) {
|
|
13041
|
+
head = curr.next;
|
|
13042
|
+
} else {
|
|
13043
|
+
prev.next = curr.next;
|
|
13044
|
+
}
|
|
13045
|
+
if (curr === tail)
|
|
13046
|
+
tail = prev || head;
|
|
13047
|
+
}
|
|
13048
|
+
}
|
|
13049
|
+
list.head = head;
|
|
13050
|
+
list.tail = tail;
|
|
13051
|
+
}
|
|
13052
|
+
},
|
|
13053
|
+
/**
|
|
13054
|
+
* Remove and return the next highest priority item.
|
|
13055
|
+
* @returns {*} The next item in the queue,
|
|
13056
|
+
* or undefined if this queue is empty.
|
|
13057
|
+
*/
|
|
13058
|
+
next() {
|
|
13059
|
+
for (const list of queue) {
|
|
13060
|
+
const { head } = list;
|
|
13061
|
+
if (head !== null) {
|
|
13062
|
+
list.head = head.next;
|
|
13063
|
+
if (list.tail === head) {
|
|
13064
|
+
list.tail = null;
|
|
13065
|
+
}
|
|
13066
|
+
return head.item;
|
|
13067
|
+
}
|
|
13068
|
+
}
|
|
13069
|
+
}
|
|
13070
|
+
};
|
|
13071
|
+
}
|
|
13072
|
+
|
|
13073
|
+
// ../core/src/QueryManager.js
|
|
13074
|
+
var Priority = { High: 0, Normal: 1, Low: 2 };
|
|
13075
|
+
function QueryManager() {
|
|
13076
|
+
const queue = priorityQueue(3);
|
|
13077
|
+
let db;
|
|
13078
|
+
let clientCache;
|
|
13079
|
+
let logger;
|
|
13080
|
+
let recorders = [];
|
|
13081
|
+
let pending = null;
|
|
13082
|
+
let consolidate2;
|
|
13083
|
+
function next() {
|
|
13084
|
+
if (pending || queue.isEmpty())
|
|
13085
|
+
return;
|
|
13086
|
+
const { request, result } = queue.next();
|
|
13087
|
+
pending = submit(request, result);
|
|
13088
|
+
pending.finally(() => {
|
|
13089
|
+
pending = null;
|
|
13090
|
+
next();
|
|
13091
|
+
});
|
|
13092
|
+
}
|
|
13093
|
+
function enqueue(entry, priority = Priority.Normal) {
|
|
13094
|
+
queue.insert(entry, priority);
|
|
13095
|
+
next();
|
|
13096
|
+
}
|
|
13097
|
+
function recordQuery(sql2) {
|
|
13098
|
+
if (recorders.length && sql2) {
|
|
13099
|
+
recorders.forEach((rec) => rec.add(sql2));
|
|
13100
|
+
}
|
|
13101
|
+
}
|
|
13102
|
+
async function submit(request, result) {
|
|
13103
|
+
try {
|
|
13104
|
+
const { query, type, cache = false, record = true, options } = request;
|
|
13105
|
+
const sql2 = query ? `${query}` : null;
|
|
13106
|
+
if (record) {
|
|
13107
|
+
recordQuery(sql2);
|
|
13108
|
+
}
|
|
13109
|
+
if (cache) {
|
|
13110
|
+
const cached = clientCache.get(sql2);
|
|
13111
|
+
if (cached) {
|
|
13112
|
+
logger.debug("Cache");
|
|
13113
|
+
result.fulfill(cached);
|
|
13114
|
+
return;
|
|
13115
|
+
}
|
|
13116
|
+
}
|
|
13117
|
+
const t0 = performance.now();
|
|
13118
|
+
const data = await db.query({ type, sql: sql2, ...options });
|
|
13119
|
+
if (cache)
|
|
13120
|
+
clientCache.set(sql2, data);
|
|
13121
|
+
logger.debug(`Request: ${(performance.now() - t0).toFixed(1)}`);
|
|
13122
|
+
result.fulfill(data);
|
|
13123
|
+
} catch (err) {
|
|
13124
|
+
result.reject(err);
|
|
13125
|
+
}
|
|
13126
|
+
}
|
|
13127
|
+
return {
|
|
13128
|
+
cache(value) {
|
|
13129
|
+
return value !== void 0 ? clientCache = value === true ? lruCache() : value || voidCache() : clientCache;
|
|
13130
|
+
},
|
|
13131
|
+
logger(value) {
|
|
13132
|
+
return value ? logger = value : logger;
|
|
13133
|
+
},
|
|
13134
|
+
connector(connector) {
|
|
13135
|
+
return connector ? db = connector : db;
|
|
13136
|
+
},
|
|
13137
|
+
consolidate(flag) {
|
|
13138
|
+
if (flag && !consolidate2) {
|
|
13139
|
+
consolidate2 = consolidator(enqueue, clientCache, recordQuery);
|
|
13140
|
+
} else if (!flag && consolidate2) {
|
|
13141
|
+
consolidate2 = null;
|
|
13142
|
+
}
|
|
13143
|
+
},
|
|
13144
|
+
request(request, priority = Priority.Normal) {
|
|
13145
|
+
const result = queryResult();
|
|
13146
|
+
const entry = { request, result };
|
|
13147
|
+
if (consolidate2) {
|
|
13148
|
+
consolidate2.add(entry, priority);
|
|
13149
|
+
} else {
|
|
13150
|
+
enqueue(entry, priority);
|
|
13151
|
+
}
|
|
13152
|
+
return result;
|
|
13153
|
+
},
|
|
13154
|
+
cancel(requests) {
|
|
13155
|
+
const set = new Set(requests);
|
|
13156
|
+
queue.remove(({ result }) => set.has(result));
|
|
13157
|
+
},
|
|
13158
|
+
clear() {
|
|
13159
|
+
queue.remove(({ result }) => {
|
|
13160
|
+
result.reject("Cleared");
|
|
13161
|
+
return true;
|
|
13162
|
+
});
|
|
13163
|
+
},
|
|
13164
|
+
record() {
|
|
13165
|
+
let state = [];
|
|
13166
|
+
const recorder = {
|
|
13167
|
+
add(query) {
|
|
13168
|
+
state.push(query);
|
|
13169
|
+
},
|
|
13170
|
+
reset() {
|
|
13171
|
+
state = [];
|
|
13172
|
+
},
|
|
13173
|
+
snapshot() {
|
|
13174
|
+
return state.slice();
|
|
13175
|
+
},
|
|
13176
|
+
stop() {
|
|
13177
|
+
recorders = recorders.filter((x) => x !== recorder);
|
|
13178
|
+
return state;
|
|
13179
|
+
}
|
|
13180
|
+
};
|
|
13181
|
+
recorders.push(recorder);
|
|
13182
|
+
return recorder;
|
|
13183
|
+
}
|
|
13184
|
+
};
|
|
13185
|
+
}
|
|
13186
|
+
|
|
13187
|
+
// ../core/src/util/void-logger.js
|
|
13188
|
+
function voidLogger() {
|
|
13189
|
+
return {
|
|
13190
|
+
debug() {
|
|
13191
|
+
},
|
|
13192
|
+
info() {
|
|
13193
|
+
},
|
|
13194
|
+
log() {
|
|
13195
|
+
},
|
|
13196
|
+
warn() {
|
|
13197
|
+
},
|
|
13198
|
+
error() {
|
|
13199
|
+
}
|
|
13200
|
+
};
|
|
13201
|
+
}
|
|
13202
|
+
|
|
13203
|
+
// ../core/src/Coordinator.js
|
|
12721
13204
|
var _instance;
|
|
12722
13205
|
function coordinator(instance9) {
|
|
12723
13206
|
if (instance9) {
|
|
@@ -12728,21 +13211,28 @@ function coordinator(instance9) {
|
|
|
12728
13211
|
return _instance;
|
|
12729
13212
|
}
|
|
12730
13213
|
var Coordinator = class {
|
|
12731
|
-
constructor(db =
|
|
13214
|
+
constructor(db = socketConnector(), options = {}) {
|
|
12732
13215
|
this.catalog = new Catalog(this);
|
|
13216
|
+
this.manager = options.manager || QueryManager();
|
|
12733
13217
|
this.logger(options.logger || console);
|
|
12734
13218
|
this.configure(options);
|
|
12735
|
-
this.
|
|
13219
|
+
this.databaseConnector(db);
|
|
12736
13220
|
this.clear();
|
|
12737
13221
|
}
|
|
12738
13222
|
logger(logger) {
|
|
12739
|
-
|
|
13223
|
+
if (arguments.length) {
|
|
13224
|
+
this._logger = logger || voidLogger();
|
|
13225
|
+
this.manager.logger(this._logger);
|
|
13226
|
+
}
|
|
13227
|
+
return this._logger;
|
|
12740
13228
|
}
|
|
12741
|
-
configure({ cache = true, indexes = true }) {
|
|
12742
|
-
this.cache
|
|
13229
|
+
configure({ cache = true, consolidate: consolidate2 = true, indexes = true }) {
|
|
13230
|
+
this.manager.cache(cache);
|
|
13231
|
+
this.manager.consolidate(consolidate2);
|
|
12743
13232
|
this.indexes = indexes;
|
|
12744
13233
|
}
|
|
12745
13234
|
clear({ clients = true, cache = true, catalog = false } = {}) {
|
|
13235
|
+
this.manager.clear();
|
|
12746
13236
|
if (clients) {
|
|
12747
13237
|
this.clients?.forEach((client) => this.disconnect(client));
|
|
12748
13238
|
this.filterGroups?.forEach((group) => group.finalize());
|
|
@@ -12750,57 +13240,59 @@ var Coordinator = class {
|
|
|
12750
13240
|
this.filterGroups = /* @__PURE__ */ new Map();
|
|
12751
13241
|
}
|
|
12752
13242
|
if (cache)
|
|
12753
|
-
this.cache.clear();
|
|
13243
|
+
this.manager.cache().clear();
|
|
12754
13244
|
if (catalog)
|
|
12755
13245
|
this.catalog.clear();
|
|
12756
13246
|
}
|
|
12757
|
-
|
|
12758
|
-
|
|
12759
|
-
this.db = db;
|
|
12760
|
-
}
|
|
12761
|
-
return this.db;
|
|
13247
|
+
databaseConnector(db) {
|
|
13248
|
+
return this.manager.connector(db);
|
|
12762
13249
|
}
|
|
12763
|
-
|
|
12764
|
-
|
|
12765
|
-
|
|
12766
|
-
} catch (err) {
|
|
12767
|
-
this._logger.error(err);
|
|
12768
|
-
}
|
|
13250
|
+
// -- Query Management ----
|
|
13251
|
+
cancel(requests) {
|
|
13252
|
+
this.manager.cancel(requests);
|
|
12769
13253
|
}
|
|
12770
|
-
|
|
12771
|
-
|
|
12772
|
-
const t0 = performance.now();
|
|
12773
|
-
const cached = this.cache.get(sql2);
|
|
12774
|
-
if (cached) {
|
|
12775
|
-
this._logger.debug("Cache");
|
|
12776
|
-
return cached;
|
|
12777
|
-
} else {
|
|
12778
|
-
const request = this.db.query({ type, sql: sql2 });
|
|
12779
|
-
const result = cache ? this.cache.set(sql2, request) : request;
|
|
12780
|
-
result.then(() => this._logger.debug(`Query: ${performance.now() - t0}`));
|
|
12781
|
-
return result;
|
|
12782
|
-
}
|
|
13254
|
+
exec(query, { priority = Priority.Normal } = {}) {
|
|
13255
|
+
return this.manager.request({ type: "exec", query }, priority);
|
|
12783
13256
|
}
|
|
12784
|
-
|
|
12785
|
-
|
|
12786
|
-
|
|
12787
|
-
|
|
12788
|
-
|
|
12789
|
-
|
|
12790
|
-
|
|
12791
|
-
|
|
12792
|
-
|
|
12793
|
-
}
|
|
12794
|
-
|
|
12795
|
-
|
|
12796
|
-
|
|
12797
|
-
|
|
12798
|
-
|
|
13257
|
+
query(query, {
|
|
13258
|
+
type = "arrow",
|
|
13259
|
+
cache = true,
|
|
13260
|
+
priority = Priority.Normal,
|
|
13261
|
+
...options
|
|
13262
|
+
} = {}) {
|
|
13263
|
+
return this.manager.request({ type, query, cache, options }, priority);
|
|
13264
|
+
}
|
|
13265
|
+
prefetch(query, options = {}) {
|
|
13266
|
+
return this.query(query, { ...options, cache: true, priority: Priority.Low });
|
|
13267
|
+
}
|
|
13268
|
+
createBundle(name, queries, priority = Priority.Low) {
|
|
13269
|
+
const options = { name, queries };
|
|
13270
|
+
return this.manager.request({ type: "create-bundle", options }, priority);
|
|
13271
|
+
}
|
|
13272
|
+
loadBundle(name, priority = Priority.High) {
|
|
13273
|
+
const options = { name };
|
|
13274
|
+
return this.manager.request({ type: "load-bundle", options }, priority);
|
|
12799
13275
|
}
|
|
12800
|
-
|
|
13276
|
+
// -- Client Management ----
|
|
13277
|
+
updateClient(client, query, priority = Priority.Normal) {
|
|
13278
|
+
client.queryPending();
|
|
13279
|
+
return this.query(query, { priority }).then(
|
|
13280
|
+
(data) => client.queryResult(data).update(),
|
|
13281
|
+
(err) => {
|
|
13282
|
+
client.queryError(err);
|
|
13283
|
+
this._logger.error(err);
|
|
13284
|
+
}
|
|
13285
|
+
);
|
|
13286
|
+
}
|
|
13287
|
+
requestQuery(client, query) {
|
|
12801
13288
|
this.filterGroups.get(client.filterBy)?.reset();
|
|
12802
13289
|
return query ? this.updateClient(client, query) : client.update();
|
|
12803
13290
|
}
|
|
13291
|
+
/**
|
|
13292
|
+
* Connect a client to the coordinator.
|
|
13293
|
+
*
|
|
13294
|
+
* @param {import('./MosaicClient.js').MosaicClient} client the client to disconnect
|
|
13295
|
+
*/
|
|
12804
13296
|
async connect(client) {
|
|
12805
13297
|
const { catalog, clients, filterGroups, indexes } = this;
|
|
12806
13298
|
if (clients.has(client)) {
|
|
@@ -12809,7 +13301,7 @@ var Coordinator = class {
|
|
|
12809
13301
|
clients.add(client);
|
|
12810
13302
|
const fields = client.fields();
|
|
12811
13303
|
if (fields?.length) {
|
|
12812
|
-
client.
|
|
13304
|
+
client.fieldInfo(await catalog.queryFields(fields));
|
|
12813
13305
|
}
|
|
12814
13306
|
const filter = client.filterBy;
|
|
12815
13307
|
if (filter) {
|
|
@@ -12822,6 +13314,11 @@ var Coordinator = class {
|
|
|
12822
13314
|
}
|
|
12823
13315
|
client.requestQuery();
|
|
12824
13316
|
}
|
|
13317
|
+
/**
|
|
13318
|
+
* Disconnect a client from the coordinator.
|
|
13319
|
+
*
|
|
13320
|
+
* @param {import('./MosaicClient.js').MosaicClient} client the client to disconnect
|
|
13321
|
+
*/
|
|
12825
13322
|
disconnect(client) {
|
|
12826
13323
|
const { clients, filterGroups } = this;
|
|
12827
13324
|
if (!clients.has(client))
|
|
@@ -12831,6 +13328,42 @@ var Coordinator = class {
|
|
|
12831
13328
|
}
|
|
12832
13329
|
};
|
|
12833
13330
|
|
|
13331
|
+
// ../core/src/util/throttle.js
|
|
13332
|
+
var NIL = {};
|
|
13333
|
+
function throttle(callback, debounce = false) {
|
|
13334
|
+
let curr;
|
|
13335
|
+
let next;
|
|
13336
|
+
let pending = NIL;
|
|
13337
|
+
function invoke(event) {
|
|
13338
|
+
curr = callback(event).then(() => {
|
|
13339
|
+
if (next) {
|
|
13340
|
+
const { value } = next;
|
|
13341
|
+
next = null;
|
|
13342
|
+
invoke(value);
|
|
13343
|
+
} else {
|
|
13344
|
+
curr = null;
|
|
13345
|
+
}
|
|
13346
|
+
});
|
|
13347
|
+
}
|
|
13348
|
+
function enqueue(event) {
|
|
13349
|
+
next = { event };
|
|
13350
|
+
}
|
|
13351
|
+
function process(event) {
|
|
13352
|
+
curr ? enqueue(event) : invoke(event);
|
|
13353
|
+
}
|
|
13354
|
+
function delay(event) {
|
|
13355
|
+
if (pending !== event) {
|
|
13356
|
+
requestAnimationFrame(() => {
|
|
13357
|
+
const e = pending;
|
|
13358
|
+
pending = NIL;
|
|
13359
|
+
process(e);
|
|
13360
|
+
});
|
|
13361
|
+
}
|
|
13362
|
+
pending = event;
|
|
13363
|
+
}
|
|
13364
|
+
return debounce ? delay : process;
|
|
13365
|
+
}
|
|
13366
|
+
|
|
12834
13367
|
// ../core/src/MosaicClient.js
|
|
12835
13368
|
var MosaicClient = class {
|
|
12836
13369
|
/**
|
|
@@ -12864,10 +13397,10 @@ var MosaicClient = class {
|
|
|
12864
13397
|
return null;
|
|
12865
13398
|
}
|
|
12866
13399
|
/**
|
|
12867
|
-
* Called by the coordinator to set the field
|
|
13400
|
+
* Called by the coordinator to set the field info for this client.
|
|
12868
13401
|
* @returns {this}
|
|
12869
13402
|
*/
|
|
12870
|
-
|
|
13403
|
+
fieldInfo() {
|
|
12871
13404
|
return this;
|
|
12872
13405
|
}
|
|
12873
13406
|
/**
|
|
@@ -12884,6 +13417,9 @@ var MosaicClient = class {
|
|
|
12884
13417
|
}
|
|
12885
13418
|
/**
|
|
12886
13419
|
* Called by the coordinator to return a query result.
|
|
13420
|
+
*
|
|
13421
|
+
* @param {*} data the query result
|
|
13422
|
+
* @returns {this}
|
|
12887
13423
|
*/
|
|
12888
13424
|
queryResult() {
|
|
12889
13425
|
return this;
|
|
@@ -12922,6 +13458,163 @@ var MosaicClient = class {
|
|
|
12922
13458
|
}
|
|
12923
13459
|
};
|
|
12924
13460
|
|
|
13461
|
+
// ../core/src/util/AsyncDispatch.js
|
|
13462
|
+
var AsyncDispatch = class {
|
|
13463
|
+
/**
|
|
13464
|
+
* Create a new asynchronous dispatcher instance.
|
|
13465
|
+
*/
|
|
13466
|
+
constructor() {
|
|
13467
|
+
this._callbacks = /* @__PURE__ */ new Map();
|
|
13468
|
+
}
|
|
13469
|
+
/**
|
|
13470
|
+
* Add an event listener callback for the provided event type.
|
|
13471
|
+
* @param {string} type The event type.
|
|
13472
|
+
* @param {(value: *) => Promise?} callback The event handler
|
|
13473
|
+
* callback function to add. If the callback has already been
|
|
13474
|
+
* added for the event type, this method has no effect.
|
|
13475
|
+
*/
|
|
13476
|
+
addEventListener(type, callback) {
|
|
13477
|
+
if (!this._callbacks.has(type)) {
|
|
13478
|
+
this._callbacks.set(type, {
|
|
13479
|
+
callbacks: /* @__PURE__ */ new Set(),
|
|
13480
|
+
pending: null,
|
|
13481
|
+
queue: new DispatchQueue()
|
|
13482
|
+
});
|
|
13483
|
+
}
|
|
13484
|
+
const entry = this._callbacks.get(type);
|
|
13485
|
+
entry.callbacks.add(callback);
|
|
13486
|
+
}
|
|
13487
|
+
/**
|
|
13488
|
+
* Remove an event listener callback for the provided event type.
|
|
13489
|
+
* @param {string} type The event type.
|
|
13490
|
+
* @param {(value: *) => Promise?} callback The event handler
|
|
13491
|
+
* callback function to remove.
|
|
13492
|
+
*/
|
|
13493
|
+
removeEventListener(type, callback) {
|
|
13494
|
+
const entry = this._callbacks.get(type);
|
|
13495
|
+
if (entry) {
|
|
13496
|
+
entry.callbacks.delete(callback);
|
|
13497
|
+
}
|
|
13498
|
+
}
|
|
13499
|
+
/**
|
|
13500
|
+
* Lifecycle method that returns the event value to emit.
|
|
13501
|
+
* This default implementation simply returns the input value as-is.
|
|
13502
|
+
* Subclasses may override this method to implement custom transformations
|
|
13503
|
+
* prior to emitting an event value to all listeners.
|
|
13504
|
+
* @param {string} type The event type.
|
|
13505
|
+
* @param {*} value The event value.
|
|
13506
|
+
* @returns The (possibly transformed) event value to emit.
|
|
13507
|
+
*/
|
|
13508
|
+
willEmit(type, value) {
|
|
13509
|
+
return value;
|
|
13510
|
+
}
|
|
13511
|
+
/**
|
|
13512
|
+
* Lifecycle method that returns a filter function for updating the
|
|
13513
|
+
* queue of unemitted event values prior to enqueueing a new value.
|
|
13514
|
+
* This default implementation simply returns null, indicating that
|
|
13515
|
+
* any other unemitted event values should be dropped (that is, all
|
|
13516
|
+
* queued events are filtered)
|
|
13517
|
+
* @param {*} value The new event value that will be enqueued.
|
|
13518
|
+
* @returns {(value: *) => boolean|null} A dispatch queue filter
|
|
13519
|
+
* function, or null if all unemitted event values should be filtered.
|
|
13520
|
+
*/
|
|
13521
|
+
emitQueueFilter() {
|
|
13522
|
+
return null;
|
|
13523
|
+
}
|
|
13524
|
+
/**
|
|
13525
|
+
* Cancel all unemitted event values for the given event type.
|
|
13526
|
+
* @param {string} type The event type.
|
|
13527
|
+
*/
|
|
13528
|
+
cancel(type) {
|
|
13529
|
+
const entry = this._callbacks.get(type);
|
|
13530
|
+
entry?.queue.clear();
|
|
13531
|
+
}
|
|
13532
|
+
/**
|
|
13533
|
+
* Emit an event value to listeners for the given event type.
|
|
13534
|
+
* If a previous emit has not yet resolved, the event value
|
|
13535
|
+
* will be queued to be emitted later.
|
|
13536
|
+
* The actual event value given to listeners will be the result
|
|
13537
|
+
* of passing the input value through the emitValue() method.
|
|
13538
|
+
* @param {string} type The event type.
|
|
13539
|
+
* @param {*} value The event value.
|
|
13540
|
+
*/
|
|
13541
|
+
emit(type, value) {
|
|
13542
|
+
const entry = this._callbacks.get(type) || {};
|
|
13543
|
+
if (entry.pending) {
|
|
13544
|
+
entry.queue.enqueue(value, this.emitQueueFilter(type, value));
|
|
13545
|
+
} else {
|
|
13546
|
+
const event = this.willEmit(type, value);
|
|
13547
|
+
const { callbacks, queue } = entry;
|
|
13548
|
+
if (callbacks?.size) {
|
|
13549
|
+
const promise = Promise.allSettled(Array.from(callbacks, (callback) => callback(event))).then(() => {
|
|
13550
|
+
entry.pending = null;
|
|
13551
|
+
if (!queue.isEmpty()) {
|
|
13552
|
+
this.emit(type, queue.dequeue());
|
|
13553
|
+
}
|
|
13554
|
+
});
|
|
13555
|
+
entry.pending = promise;
|
|
13556
|
+
}
|
|
13557
|
+
}
|
|
13558
|
+
}
|
|
13559
|
+
};
|
|
13560
|
+
var DispatchQueue = class {
|
|
13561
|
+
/**
|
|
13562
|
+
* Create a new dispatch queue instance.
|
|
13563
|
+
*/
|
|
13564
|
+
constructor() {
|
|
13565
|
+
this.clear();
|
|
13566
|
+
}
|
|
13567
|
+
/**
|
|
13568
|
+
* Clear the queue state of all event values.
|
|
13569
|
+
*/
|
|
13570
|
+
clear() {
|
|
13571
|
+
this.next = null;
|
|
13572
|
+
}
|
|
13573
|
+
/**
|
|
13574
|
+
* Indicate if the queue is empty.
|
|
13575
|
+
* @returns {boolean} True if queue is empty, false otherwise.
|
|
13576
|
+
*/
|
|
13577
|
+
isEmpty() {
|
|
13578
|
+
return !this.next;
|
|
13579
|
+
}
|
|
13580
|
+
/**
|
|
13581
|
+
* Add a new value to the queue, and optionally filter the
|
|
13582
|
+
* current queue content in response.
|
|
13583
|
+
* @param {*} value The value to add.
|
|
13584
|
+
* @param {(value: *) => boolean} [filter] An optional filter
|
|
13585
|
+
* function to apply to existing queue content. If unspecified
|
|
13586
|
+
* or falsy, all previously queued values are removed. Otherwise,
|
|
13587
|
+
* the provided function is applied to all queue entries. The
|
|
13588
|
+
* entry is retained if the filter function returns a truthy value,
|
|
13589
|
+
* otherwise the entry is removed.
|
|
13590
|
+
*/
|
|
13591
|
+
enqueue(value, filter) {
|
|
13592
|
+
const tail = { value };
|
|
13593
|
+
if (filter && this.next) {
|
|
13594
|
+
let curr = this;
|
|
13595
|
+
while (curr.next) {
|
|
13596
|
+
if (filter(curr.next.value)) {
|
|
13597
|
+
curr = curr.next;
|
|
13598
|
+
} else {
|
|
13599
|
+
curr.next = curr.next.next;
|
|
13600
|
+
}
|
|
13601
|
+
}
|
|
13602
|
+
curr.next = tail;
|
|
13603
|
+
} else {
|
|
13604
|
+
this.next = tail;
|
|
13605
|
+
}
|
|
13606
|
+
}
|
|
13607
|
+
/**
|
|
13608
|
+
* Remove and return the next queued event value.
|
|
13609
|
+
* @returns {*} The next event value in the queue.
|
|
13610
|
+
*/
|
|
13611
|
+
dequeue() {
|
|
13612
|
+
const { next } = this;
|
|
13613
|
+
this.next = next?.next;
|
|
13614
|
+
return next?.value;
|
|
13615
|
+
}
|
|
13616
|
+
};
|
|
13617
|
+
|
|
12925
13618
|
// ../core/src/util/distinct.js
|
|
12926
13619
|
function distinct(a, b) {
|
|
12927
13620
|
return a === b ? false : a instanceof Date && b instanceof Date ? +a !== +b : Array.isArray(a) && Array.isArray(b) ? distinctArray(a, b) : true;
|
|
@@ -12940,40 +13633,74 @@ function distinctArray(a, b) {
|
|
|
12940
13633
|
function isParam(x) {
|
|
12941
13634
|
return x instanceof Param;
|
|
12942
13635
|
}
|
|
12943
|
-
var Param = class {
|
|
13636
|
+
var Param = class extends AsyncDispatch {
|
|
13637
|
+
/**
|
|
13638
|
+
* Create a new Param instance.
|
|
13639
|
+
* @param {*} value The initial value of the Param.
|
|
13640
|
+
*/
|
|
12944
13641
|
constructor(value) {
|
|
13642
|
+
super();
|
|
12945
13643
|
this._value = value;
|
|
12946
|
-
this._listeners = /* @__PURE__ */ new Map();
|
|
12947
13644
|
}
|
|
13645
|
+
/**
|
|
13646
|
+
* Create a new Param instance with the given initial value.
|
|
13647
|
+
* @param {*} value The initial value of the Param.
|
|
13648
|
+
* @returns {Param} The new Param instance.
|
|
13649
|
+
*/
|
|
12948
13650
|
static value(value) {
|
|
12949
13651
|
return new Param(value);
|
|
12950
13652
|
}
|
|
13653
|
+
/**
|
|
13654
|
+
* Create a new Param instance over an array of initial values,
|
|
13655
|
+
* which may contain nested Params.
|
|
13656
|
+
* @param {*} values The initial values of the Param.
|
|
13657
|
+
* @returns {Param} The new Param instance.
|
|
13658
|
+
*/
|
|
13659
|
+
static array(values) {
|
|
13660
|
+
if (values.some((v) => isParam(v))) {
|
|
13661
|
+
const p = new Param();
|
|
13662
|
+
const update2 = () => p.update(values.map((v) => isParam(v) ? v.value : v));
|
|
13663
|
+
update2();
|
|
13664
|
+
values.forEach((v) => isParam(v) ? v.addEventListener("value", update2) : 0);
|
|
13665
|
+
return p;
|
|
13666
|
+
}
|
|
13667
|
+
return new Param(values);
|
|
13668
|
+
}
|
|
13669
|
+
/**
|
|
13670
|
+
* The current value of the Param.
|
|
13671
|
+
*/
|
|
12951
13672
|
get value() {
|
|
12952
13673
|
return this._value;
|
|
12953
13674
|
}
|
|
13675
|
+
/**
|
|
13676
|
+
* Update the Param value
|
|
13677
|
+
* @param {*} value The new value of the Param.
|
|
13678
|
+
* @param {object} [options] The update options.
|
|
13679
|
+
* @param {boolean} [options.force] A boolean flag indicating if the Param
|
|
13680
|
+
* should emit a 'value' event even if the internal value is unchanged.
|
|
13681
|
+
* @returns {this} This Param instance.
|
|
13682
|
+
*/
|
|
12954
13683
|
update(value, { force } = {}) {
|
|
12955
|
-
const
|
|
12956
|
-
if (
|
|
12957
|
-
this.
|
|
12958
|
-
|
|
12959
|
-
this.
|
|
12960
|
-
return this;
|
|
12961
|
-
}
|
|
12962
|
-
addEventListener(type, callback) {
|
|
12963
|
-
let list = this._listeners.get(type) || [];
|
|
12964
|
-
if (!list.includes(callback)) {
|
|
12965
|
-
list = list.concat(callback);
|
|
13684
|
+
const shouldEmit = distinct(this._value, value) || force;
|
|
13685
|
+
if (shouldEmit) {
|
|
13686
|
+
this.emit("value", value);
|
|
13687
|
+
} else {
|
|
13688
|
+
this.cancel("value");
|
|
12966
13689
|
}
|
|
12967
|
-
this
|
|
13690
|
+
return this;
|
|
12968
13691
|
}
|
|
12969
|
-
|
|
12970
|
-
|
|
12971
|
-
|
|
12972
|
-
|
|
13692
|
+
/**
|
|
13693
|
+
* Upon value-typed updates, sets the current value to the input value
|
|
13694
|
+
* immediately prior to the event value being emitted to listeners.
|
|
13695
|
+
* @param {string} type The event type.
|
|
13696
|
+
* @param {*} value The input event value.
|
|
13697
|
+
* @returns {*} The input event value.
|
|
13698
|
+
*/
|
|
13699
|
+
willEmit(type, value) {
|
|
13700
|
+
if (type === "value") {
|
|
13701
|
+
this._value = value;
|
|
12973
13702
|
}
|
|
12974
|
-
|
|
12975
|
-
emit(type, event) {
|
|
12976
|
-
this._listeners.get(type)?.forEach((l) => l(event));
|
|
13703
|
+
return value;
|
|
12977
13704
|
}
|
|
12978
13705
|
};
|
|
12979
13706
|
|
|
@@ -12982,66 +13709,254 @@ function isSelection(x) {
|
|
|
12982
13709
|
return x instanceof Selection;
|
|
12983
13710
|
}
|
|
12984
13711
|
var Selection = class extends Param {
|
|
12985
|
-
|
|
12986
|
-
|
|
13712
|
+
/**
|
|
13713
|
+
* Create a new Selection instance with an
|
|
13714
|
+
* intersect (conjunction) resolution strategy.
|
|
13715
|
+
* @param {object} [options] The selection options.
|
|
13716
|
+
* @param {boolean} [options.cross=false] Boolean flag indicating
|
|
13717
|
+
* cross-filtered resolution. If true, selection clauses will not
|
|
13718
|
+
* be applied to the clients they are associated with.
|
|
13719
|
+
* @returns {Selection} The new Selection instance.
|
|
13720
|
+
*/
|
|
13721
|
+
static intersect({ cross = false } = {}) {
|
|
13722
|
+
return new Selection(new SelectionResolver({ cross }));
|
|
12987
13723
|
}
|
|
12988
|
-
|
|
12989
|
-
|
|
13724
|
+
/**
|
|
13725
|
+
* Create a new Selection instance with a
|
|
13726
|
+
* union (disjunction) resolution strategy.
|
|
13727
|
+
* @param {object} [options] The selection options.
|
|
13728
|
+
* @param {boolean} [options.cross=false] Boolean flag indicating
|
|
13729
|
+
* cross-filtered resolution. If true, selection clauses will not
|
|
13730
|
+
* be applied to the clients they are associated with.
|
|
13731
|
+
* @returns {Selection} The new Selection instance.
|
|
13732
|
+
*/
|
|
13733
|
+
static union({ cross = false } = {}) {
|
|
13734
|
+
return new Selection(new SelectionResolver({ cross, union: true }));
|
|
12990
13735
|
}
|
|
12991
|
-
|
|
12992
|
-
|
|
13736
|
+
/**
|
|
13737
|
+
* Create a new Selection instance with a singular resolution strategy
|
|
13738
|
+
* that keeps only the most recent selection clause.
|
|
13739
|
+
* @param {object} [options] The selection options.
|
|
13740
|
+
* @param {boolean} [options.cross=false] Boolean flag indicating
|
|
13741
|
+
* cross-filtered resolution. If true, selection clauses will not
|
|
13742
|
+
* be applied to the clients they are associated with.
|
|
13743
|
+
* @returns {Selection} The new Selection instance.
|
|
13744
|
+
*/
|
|
13745
|
+
static single({ cross = false } = {}) {
|
|
13746
|
+
return new Selection(new SelectionResolver({ cross, single: true }));
|
|
12993
13747
|
}
|
|
12994
|
-
|
|
12995
|
-
|
|
13748
|
+
/**
|
|
13749
|
+
* Create a new Selection instance with a
|
|
13750
|
+
* cross-filtered intersect resolution strategy.
|
|
13751
|
+
* @returns {Selection} The new Selection instance.
|
|
13752
|
+
*/
|
|
13753
|
+
static crossfilter() {
|
|
13754
|
+
return new Selection(new SelectionResolver({ cross: true }));
|
|
12996
13755
|
}
|
|
12997
|
-
|
|
13756
|
+
/**
|
|
13757
|
+
* Create a new Selection instance.
|
|
13758
|
+
* @param {SelectionResolver} resolver The selection resolution
|
|
13759
|
+
* strategy to apply.
|
|
13760
|
+
*/
|
|
13761
|
+
constructor(resolver = new SelectionResolver()) {
|
|
12998
13762
|
super([]);
|
|
12999
|
-
this.
|
|
13000
|
-
this.
|
|
13001
|
-
this.cross = !!cross;
|
|
13002
|
-
this.single = !!single;
|
|
13763
|
+
this._resolved = this._value;
|
|
13764
|
+
this._resolver = resolver;
|
|
13003
13765
|
}
|
|
13766
|
+
/**
|
|
13767
|
+
* Create a cloned copy of this Selection instance.
|
|
13768
|
+
* @returns {this} A clone of this selection.
|
|
13769
|
+
*/
|
|
13004
13770
|
clone() {
|
|
13005
|
-
const s = new Selection();
|
|
13006
|
-
s.
|
|
13007
|
-
s
|
|
13008
|
-
|
|
13009
|
-
|
|
13771
|
+
const s = new Selection(this._resolver);
|
|
13772
|
+
s._value = s._resolved = this._value;
|
|
13773
|
+
return s;
|
|
13774
|
+
}
|
|
13775
|
+
/**
|
|
13776
|
+
* Create a clone of this Selection with clauses corresponding
|
|
13777
|
+
* to provided source removed.
|
|
13778
|
+
* @param {*} source The clause source to remove.
|
|
13779
|
+
* @returns {this} A cloned and updated Selection.
|
|
13780
|
+
*/
|
|
13781
|
+
remove(source) {
|
|
13782
|
+
const s = this.clone();
|
|
13783
|
+
s._value = s._resolved = s._resolver.resolve(this._resolved, { source });
|
|
13784
|
+
s._value.active = { source };
|
|
13010
13785
|
return s;
|
|
13011
13786
|
}
|
|
13787
|
+
/**
|
|
13788
|
+
* The current active (most recently updated) selection clause.
|
|
13789
|
+
*/
|
|
13790
|
+
get active() {
|
|
13791
|
+
return this.clauses.active;
|
|
13792
|
+
}
|
|
13793
|
+
/**
|
|
13794
|
+
* The value corresponding to the current active selection clause.
|
|
13795
|
+
* This method ensures compatibility where a normal Param is expected.
|
|
13796
|
+
*/
|
|
13012
13797
|
get value() {
|
|
13013
|
-
|
|
13014
|
-
return clauses[clauses.length - 1]?.value;
|
|
13798
|
+
return this.active?.value;
|
|
13015
13799
|
}
|
|
13800
|
+
/**
|
|
13801
|
+
* The current array of selection clauses.
|
|
13802
|
+
*/
|
|
13016
13803
|
get clauses() {
|
|
13017
13804
|
return super.value;
|
|
13018
13805
|
}
|
|
13806
|
+
/**
|
|
13807
|
+
* Indicate if this selection has a single resolution strategy.
|
|
13808
|
+
*/
|
|
13809
|
+
get single() {
|
|
13810
|
+
return this._resolver.single;
|
|
13811
|
+
}
|
|
13812
|
+
/**
|
|
13813
|
+
* Emit an activate event with the given selection clause.
|
|
13814
|
+
* @param {*} clause The clause repesenting the potential activation.
|
|
13815
|
+
*/
|
|
13019
13816
|
activate(clause) {
|
|
13020
13817
|
this.emit("activate", clause);
|
|
13021
13818
|
}
|
|
13819
|
+
/**
|
|
13820
|
+
* Update the selection with a new selection clause.
|
|
13821
|
+
* @param {*} clause The selection clause to add.
|
|
13822
|
+
* @returns {this} This Selection instance.
|
|
13823
|
+
*/
|
|
13022
13824
|
update(clause) {
|
|
13825
|
+
this._resolved = this._resolver.resolve(this._resolved, clause, true);
|
|
13826
|
+
this._resolved.active = clause;
|
|
13827
|
+
return super.update(this._resolved);
|
|
13828
|
+
}
|
|
13829
|
+
/**
|
|
13830
|
+
* Upon value-typed updates, sets the current clause list to the
|
|
13831
|
+
* input value and returns the active clause value.
|
|
13832
|
+
* @param {string} type The event type.
|
|
13833
|
+
* @param {*} value The input event value.
|
|
13834
|
+
* @returns {*} For value-typed events, returns the active clause
|
|
13835
|
+
* values. Otherwise returns the input event value as-is.
|
|
13836
|
+
*/
|
|
13837
|
+
willEmit(type, value) {
|
|
13838
|
+
if (type === "value") {
|
|
13839
|
+
this._value = value;
|
|
13840
|
+
return this.value;
|
|
13841
|
+
}
|
|
13842
|
+
return value;
|
|
13843
|
+
}
|
|
13844
|
+
/**
|
|
13845
|
+
* Upon value-typed updates, returns a dispatch queue filter function.
|
|
13846
|
+
* The return value depends on the selection resolution strategy.
|
|
13847
|
+
* @param {string} type The event type.
|
|
13848
|
+
* @param {*} value The input event value.
|
|
13849
|
+
* @returns {*} For value-typed events, returns a dispatch queue filter
|
|
13850
|
+
* function. Otherwise returns null.
|
|
13851
|
+
*/
|
|
13852
|
+
emitQueueFilter(type, value) {
|
|
13853
|
+
return type === "value" ? this._resolver.queueFilter(value) : null;
|
|
13854
|
+
}
|
|
13855
|
+
/**
|
|
13856
|
+
* Indicates if a selection clause should not be applied to a given client.
|
|
13857
|
+
* The return value depends on the selection resolution strategy.
|
|
13858
|
+
* @param {*} client The selection clause.
|
|
13859
|
+
* @param {*} clause The client to test.
|
|
13860
|
+
* @returns True if the client should be skipped, false otherwise.
|
|
13861
|
+
*/
|
|
13862
|
+
skip(client, clause) {
|
|
13863
|
+
return this._resolver.skip(client, clause);
|
|
13864
|
+
}
|
|
13865
|
+
/**
|
|
13866
|
+
* Return a selection query predicate for the given client.
|
|
13867
|
+
* @param {*} client The client whose data may be filtered.
|
|
13868
|
+
* @returns {*} The query predicate for filtering client data,
|
|
13869
|
+
* based on the current state of this selection.
|
|
13870
|
+
*/
|
|
13871
|
+
predicate(client) {
|
|
13872
|
+
const { clauses } = this;
|
|
13873
|
+
return this._resolver.predicate(clauses, clauses.active, client);
|
|
13874
|
+
}
|
|
13875
|
+
};
|
|
13876
|
+
var SelectionResolver = class {
|
|
13877
|
+
/**
|
|
13878
|
+
* Create a new selection resolved instance.
|
|
13879
|
+
* @param {object} [options] The resolution strategy options.
|
|
13880
|
+
* @param {boolean} [options.union=false] Boolean flag to indicate a union strategy.
|
|
13881
|
+
* If false, an intersection strategy is used.
|
|
13882
|
+
* @param {boolean} [options.cross=false] Boolean flag to indicate cross-filtering.
|
|
13883
|
+
* @param {boolean} [options.single=false] Boolean flag to indicate single clauses only.
|
|
13884
|
+
*/
|
|
13885
|
+
constructor({ union, cross, single } = {}) {
|
|
13886
|
+
this.union = !!union;
|
|
13887
|
+
this.cross = !!cross;
|
|
13888
|
+
this.single = !!single;
|
|
13889
|
+
}
|
|
13890
|
+
/**
|
|
13891
|
+
* Resolve a list of selection clauses according to the resolution strategy.
|
|
13892
|
+
* @param {*[]} clauseList An array of selection clauses.
|
|
13893
|
+
* @param {*} clause A new selection clause to add.
|
|
13894
|
+
* @returns {*[]} An updated array of selection clauses.
|
|
13895
|
+
*/
|
|
13896
|
+
resolve(clauseList, clause, reset = false) {
|
|
13023
13897
|
const { source, predicate } = clause;
|
|
13024
|
-
|
|
13025
|
-
const clauses = this.single ? [] :
|
|
13898
|
+
const filtered = clauseList.filter((c) => source !== c.source);
|
|
13899
|
+
const clauses = this.single ? [] : filtered;
|
|
13900
|
+
if (this.single && reset)
|
|
13901
|
+
filtered.forEach((c) => c.source?.reset?.());
|
|
13026
13902
|
if (predicate)
|
|
13027
13903
|
clauses.push(clause);
|
|
13028
|
-
return
|
|
13904
|
+
return clauses;
|
|
13029
13905
|
}
|
|
13030
|
-
|
|
13031
|
-
|
|
13032
|
-
|
|
13906
|
+
/**
|
|
13907
|
+
* Indicates if a selection clause should not be applied to a given client.
|
|
13908
|
+
* The return value depends on the resolution strategy.
|
|
13909
|
+
* @param {*} client The selection clause.
|
|
13910
|
+
* @param {*} clause The client to test.
|
|
13911
|
+
* @returns True if the client should be skipped, false otherwise.
|
|
13912
|
+
*/
|
|
13913
|
+
skip(client, clause) {
|
|
13914
|
+
return this.cross && clause?.clients?.has(client);
|
|
13915
|
+
}
|
|
13916
|
+
/**
|
|
13917
|
+
* Return a selection query predicate for the given client.
|
|
13918
|
+
* @param {*[]} clauseList An array of selection clauses.
|
|
13919
|
+
* @param {*} active The current active selection clause.
|
|
13920
|
+
* @param {*} client The client whose data may be filtered.
|
|
13921
|
+
* @returns {*} The query predicate for filtering client data,
|
|
13922
|
+
* based on the current state of this selection.
|
|
13923
|
+
*/
|
|
13924
|
+
predicate(clauseList, active, client) {
|
|
13925
|
+
const { union } = this;
|
|
13926
|
+
if (this.skip(client, active))
|
|
13033
13927
|
return void 0;
|
|
13034
|
-
const
|
|
13035
|
-
return union &&
|
|
13928
|
+
const predicates = clauseList.filter((clause) => !this.skip(client, clause)).map((clause) => clause.predicate);
|
|
13929
|
+
return union && predicates.length > 1 ? or(predicates) : predicates;
|
|
13930
|
+
}
|
|
13931
|
+
/**
|
|
13932
|
+
* Returns a filter function for queued selection updates.
|
|
13933
|
+
* @param {*} value The new event value that will be enqueued.
|
|
13934
|
+
* @returns {(value: *) => boolean|null} A dispatch queue filter
|
|
13935
|
+
* function, or null if all unemitted event values should be filtered.
|
|
13936
|
+
*/
|
|
13937
|
+
queueFilter(value) {
|
|
13938
|
+
if (this.cross) {
|
|
13939
|
+
const source = value.active?.source;
|
|
13940
|
+
return (clauses) => clauses.active?.source !== source;
|
|
13941
|
+
}
|
|
13036
13942
|
}
|
|
13037
13943
|
};
|
|
13038
13944
|
|
|
13945
|
+
// src/input.js
|
|
13946
|
+
function input(InputClass, options) {
|
|
13947
|
+
const input2 = new InputClass(options);
|
|
13948
|
+
coordinator().connect(input2);
|
|
13949
|
+
return input2.element;
|
|
13950
|
+
}
|
|
13951
|
+
|
|
13039
13952
|
// src/Menu.js
|
|
13040
13953
|
var isObject2 = (v) => {
|
|
13041
13954
|
return v && typeof v === "object" && !Array.isArray(v);
|
|
13042
13955
|
};
|
|
13956
|
+
var menu = (options) => input(Menu, options);
|
|
13043
13957
|
var Menu = class extends MosaicClient {
|
|
13044
13958
|
constructor({
|
|
13959
|
+
element,
|
|
13045
13960
|
filterBy,
|
|
13046
13961
|
from,
|
|
13047
13962
|
column: column2,
|
|
@@ -13057,7 +13972,7 @@ var Menu = class extends MosaicClient {
|
|
|
13057
13972
|
this.column = column2;
|
|
13058
13973
|
this.selection = as;
|
|
13059
13974
|
this.format = format2;
|
|
13060
|
-
this.element = document.createElement("div");
|
|
13975
|
+
this.element = element ?? document.createElement("div");
|
|
13061
13976
|
this.element.setAttribute("class", "input");
|
|
13062
13977
|
this.element.value = this;
|
|
13063
13978
|
const lab = document.createElement("label");
|
|
@@ -13069,13 +13984,12 @@ var Menu = class extends MosaicClient {
|
|
|
13069
13984
|
this.update();
|
|
13070
13985
|
}
|
|
13071
13986
|
value = value ?? this.selection?.value ?? this.data?.[0]?.value;
|
|
13072
|
-
this.select.value = value;
|
|
13073
13987
|
if (this.selection?.value === void 0)
|
|
13074
13988
|
this.publish(value);
|
|
13075
13989
|
this.element.appendChild(this.select);
|
|
13076
13990
|
if (this.selection) {
|
|
13077
13991
|
this.select.addEventListener("input", () => {
|
|
13078
|
-
this.publish(this.selectedValue()
|
|
13992
|
+
this.publish(this.selectedValue() ?? null);
|
|
13079
13993
|
});
|
|
13080
13994
|
if (!isSelection(this.selection)) {
|
|
13081
13995
|
this.selection.addEventListener("value", (value2) => {
|
|
@@ -13091,9 +14005,17 @@ var Menu = class extends MosaicClient {
|
|
|
13091
14005
|
const index = this.select.selectedIndex;
|
|
13092
14006
|
return this.data[index].value;
|
|
13093
14007
|
} else {
|
|
13094
|
-
this.
|
|
14008
|
+
const index = this.data?.findIndex((opt) => opt.value === value);
|
|
14009
|
+
if (index >= 0) {
|
|
14010
|
+
this.select.selectedIndex = index;
|
|
14011
|
+
} else {
|
|
14012
|
+
this.select.value = String(value);
|
|
14013
|
+
}
|
|
13095
14014
|
}
|
|
13096
14015
|
}
|
|
14016
|
+
reset() {
|
|
14017
|
+
this.select.selectedIndex = this.from ? 0 : -1;
|
|
14018
|
+
}
|
|
13097
14019
|
publish(value) {
|
|
13098
14020
|
const { selection, column: column2 } = this;
|
|
13099
14021
|
if (isSelection(selection)) {
|
|
@@ -13127,7 +14049,7 @@ var Menu = class extends MosaicClient {
|
|
|
13127
14049
|
this.select.appendChild(opt);
|
|
13128
14050
|
}
|
|
13129
14051
|
if (this.selection) {
|
|
13130
|
-
this.
|
|
14052
|
+
this.selectedValue(this.selection?.value ?? "");
|
|
13131
14053
|
}
|
|
13132
14054
|
return this;
|
|
13133
14055
|
}
|
|
@@ -13136,13 +14058,15 @@ var Menu = class extends MosaicClient {
|
|
|
13136
14058
|
// src/Search.js
|
|
13137
14059
|
var FUNCTIONS = { contains, prefix, suffix, regexp: regexp_matches };
|
|
13138
14060
|
var _id = 0;
|
|
14061
|
+
var search = (options) => input(Search, options);
|
|
13139
14062
|
var Search = class extends MosaicClient {
|
|
13140
14063
|
constructor({
|
|
14064
|
+
element,
|
|
13141
14065
|
filterBy,
|
|
13142
14066
|
from,
|
|
13143
14067
|
column: column2,
|
|
13144
14068
|
label,
|
|
13145
|
-
type,
|
|
14069
|
+
type = "contains",
|
|
13146
14070
|
as
|
|
13147
14071
|
} = {}) {
|
|
13148
14072
|
super(filterBy);
|
|
@@ -13151,7 +14075,7 @@ var Search = class extends MosaicClient {
|
|
|
13151
14075
|
this.from = from;
|
|
13152
14076
|
this.column = column2;
|
|
13153
14077
|
this.selection = as;
|
|
13154
|
-
this.element = document.createElement("div");
|
|
14078
|
+
this.element = element ?? document.createElement("div");
|
|
13155
14079
|
this.element.setAttribute("class", "input");
|
|
13156
14080
|
this.element.value = this;
|
|
13157
14081
|
if (label) {
|
|
@@ -13178,6 +14102,9 @@ var Search = class extends MosaicClient {
|
|
|
13178
14102
|
}
|
|
13179
14103
|
}
|
|
13180
14104
|
}
|
|
14105
|
+
reset() {
|
|
14106
|
+
this.searchbox.value = "";
|
|
14107
|
+
}
|
|
13181
14108
|
publish(value) {
|
|
13182
14109
|
const { selection, column: column2, type } = this;
|
|
13183
14110
|
if (isSelection(selection)) {
|
|
@@ -13220,8 +14147,10 @@ var Search = class extends MosaicClient {
|
|
|
13220
14147
|
|
|
13221
14148
|
// src/Slider.js
|
|
13222
14149
|
var _id2 = 0;
|
|
14150
|
+
var slider = (options) => input(Slider, options);
|
|
13223
14151
|
var Slider = class extends MosaicClient {
|
|
13224
14152
|
constructor({
|
|
14153
|
+
element,
|
|
13225
14154
|
filterBy,
|
|
13226
14155
|
as,
|
|
13227
14156
|
min: min2,
|
|
@@ -13230,7 +14159,8 @@ var Slider = class extends MosaicClient {
|
|
|
13230
14159
|
from,
|
|
13231
14160
|
column: column2,
|
|
13232
14161
|
label = column2,
|
|
13233
|
-
value = as?.value
|
|
14162
|
+
value = as?.value,
|
|
14163
|
+
width
|
|
13234
14164
|
} = {}) {
|
|
13235
14165
|
super(filterBy);
|
|
13236
14166
|
this.id = "slider_" + ++_id2;
|
|
@@ -13240,7 +14170,7 @@ var Slider = class extends MosaicClient {
|
|
|
13240
14170
|
this.min = min2;
|
|
13241
14171
|
this.max = max2;
|
|
13242
14172
|
this.step = step;
|
|
13243
|
-
this.element = document.createElement("div");
|
|
14173
|
+
this.element = element || document.createElement("div");
|
|
13244
14174
|
this.element.setAttribute("class", "input");
|
|
13245
14175
|
this.element.value = this;
|
|
13246
14176
|
if (label) {
|
|
@@ -13252,6 +14182,8 @@ var Slider = class extends MosaicClient {
|
|
|
13252
14182
|
this.slider = document.createElement("input");
|
|
13253
14183
|
this.slider.setAttribute("id", this.id);
|
|
13254
14184
|
this.slider.setAttribute("type", "range");
|
|
14185
|
+
if (width != null)
|
|
14186
|
+
this.slider.style.width = `${+width}px`;
|
|
13255
14187
|
if (min2 != null)
|
|
13256
14188
|
this.slider.setAttribute("min", min2);
|
|
13257
14189
|
if (max2 != null)
|
|
@@ -13347,33 +14279,40 @@ function localize(f) {
|
|
|
13347
14279
|
|
|
13348
14280
|
// src/Table.js
|
|
13349
14281
|
var _id3 = -1;
|
|
14282
|
+
var table = (options) => input(Table2, options);
|
|
13350
14283
|
var Table2 = class extends MosaicClient {
|
|
13351
14284
|
constructor({
|
|
14285
|
+
element,
|
|
13352
14286
|
filterBy,
|
|
13353
14287
|
from,
|
|
13354
14288
|
columns = ["*"],
|
|
14289
|
+
align = {},
|
|
13355
14290
|
format: format2,
|
|
13356
|
-
rowBatch = 100,
|
|
13357
14291
|
width,
|
|
13358
|
-
|
|
14292
|
+
maxWidth,
|
|
14293
|
+
height = 500,
|
|
14294
|
+
rowBatch = 100
|
|
13359
14295
|
} = {}) {
|
|
13360
14296
|
super(filterBy);
|
|
13361
14297
|
this.id = `table-${++_id3}`;
|
|
13362
14298
|
this.from = from;
|
|
13363
14299
|
this.columns = columns;
|
|
13364
14300
|
this.format = format2;
|
|
14301
|
+
this.align = align;
|
|
14302
|
+
this.widths = typeof width === "object" ? width : {};
|
|
13365
14303
|
this.offset = 0;
|
|
13366
14304
|
this.limit = +rowBatch;
|
|
13367
14305
|
this.pending = false;
|
|
13368
14306
|
this.sortHeader = null;
|
|
13369
14307
|
this.sortColumn = null;
|
|
13370
14308
|
this.sortDesc = false;
|
|
13371
|
-
this.element = document.createElement("div");
|
|
14309
|
+
this.element = element || document.createElement("div");
|
|
13372
14310
|
this.element.setAttribute("id", this.id);
|
|
13373
14311
|
this.element.value = this;
|
|
13374
|
-
if (width)
|
|
13375
|
-
this.element.style.
|
|
13376
|
-
|
|
14312
|
+
if (typeof width === "number")
|
|
14313
|
+
this.element.style.width = `${width}px`;
|
|
14314
|
+
if (maxWidth)
|
|
14315
|
+
this.element.style.maxWidth = `${maxWidth}px`;
|
|
13377
14316
|
this.element.style.maxHeight = `${height}px`;
|
|
13378
14317
|
this.element.style.overflow = "auto";
|
|
13379
14318
|
let prevScrollTop = -1;
|
|
@@ -13386,9 +14325,7 @@ var Table2 = class extends MosaicClient {
|
|
|
13386
14325
|
return;
|
|
13387
14326
|
if (scrollHeight - scrollTop < 2 * clientHeight) {
|
|
13388
14327
|
this.pending = true;
|
|
13389
|
-
this.offset
|
|
13390
|
-
const query = this.queryInternal(this.filterBy?.predicate(this));
|
|
13391
|
-
this.requestQuery(query);
|
|
14328
|
+
this.requestData(this.offset + this.limit);
|
|
13392
14329
|
}
|
|
13393
14330
|
});
|
|
13394
14331
|
this.tbl = document.createElement("table");
|
|
@@ -13400,15 +14337,21 @@ var Table2 = class extends MosaicClient {
|
|
|
13400
14337
|
this.style = document.createElement("style");
|
|
13401
14338
|
this.element.appendChild(this.style);
|
|
13402
14339
|
}
|
|
14340
|
+
requestData(offset = 0) {
|
|
14341
|
+
this.offset = offset;
|
|
14342
|
+
const query = this.query(this.filterBy?.predicate(this));
|
|
14343
|
+
this.requestQuery(query);
|
|
14344
|
+
coordinator().prefetch(query.clone().offset(offset + this.limit));
|
|
14345
|
+
}
|
|
13403
14346
|
fields() {
|
|
13404
14347
|
return this.columns.map((name) => column(this.from, name));
|
|
13405
14348
|
}
|
|
13406
|
-
|
|
13407
|
-
this.
|
|
14349
|
+
fieldInfo(info) {
|
|
14350
|
+
this.schema = info;
|
|
13408
14351
|
const thead = this.head;
|
|
13409
14352
|
thead.innerHTML = "";
|
|
13410
14353
|
const tr = document.createElement("tr");
|
|
13411
|
-
for (const { column: column2 } of
|
|
14354
|
+
for (const { column: column2 } of info) {
|
|
13412
14355
|
const th = document.createElement("th");
|
|
13413
14356
|
th.addEventListener("click", (evt) => this.sort(evt, column2));
|
|
13414
14357
|
th.appendChild(document.createElement("span"));
|
|
@@ -13416,17 +14359,17 @@ var Table2 = class extends MosaicClient {
|
|
|
13416
14359
|
tr.appendChild(th);
|
|
13417
14360
|
}
|
|
13418
14361
|
thead.appendChild(tr);
|
|
13419
|
-
this.formats = formatof(this.format,
|
|
13420
|
-
this.style.innerText = tableCSS(
|
|
14362
|
+
this.formats = formatof(this.format, info);
|
|
14363
|
+
this.style.innerText = tableCSS(
|
|
14364
|
+
this.id,
|
|
14365
|
+
alignof(this.align, info),
|
|
14366
|
+
widthof(this.widths, info)
|
|
14367
|
+
);
|
|
13421
14368
|
return this;
|
|
13422
14369
|
}
|
|
13423
|
-
query(filter) {
|
|
13424
|
-
|
|
13425
|
-
return
|
|
13426
|
-
}
|
|
13427
|
-
queryInternal(filter = []) {
|
|
13428
|
-
const { from, limit, offset, stats, sortColumn, sortDesc } = this;
|
|
13429
|
-
return Query.from(from).select(stats.map((s) => s.column)).where(filter).orderby(sortColumn ? sortDesc ? desc(sortColumn) : sortColumn : []).limit(limit).offset(offset);
|
|
14370
|
+
query(filter = []) {
|
|
14371
|
+
const { from, limit, offset, schema, sortColumn, sortDesc } = this;
|
|
14372
|
+
return Query.from(from).select(schema.map((s) => s.column)).where(filter).orderby(sortColumn ? sortDesc ? desc(sortColumn) : sortColumn : []).limit(limit).offset(offset);
|
|
13430
14373
|
}
|
|
13431
14374
|
queryResult(data) {
|
|
13432
14375
|
if (!this.pending) {
|
|
@@ -13437,14 +14380,14 @@ var Table2 = class extends MosaicClient {
|
|
|
13437
14380
|
return this;
|
|
13438
14381
|
}
|
|
13439
14382
|
update() {
|
|
13440
|
-
const { body, formats, data,
|
|
13441
|
-
const nf =
|
|
14383
|
+
const { body, formats, data, schema, limit } = this;
|
|
14384
|
+
const nf = schema.length;
|
|
13442
14385
|
let count2 = 0;
|
|
13443
14386
|
for (const row of data) {
|
|
13444
14387
|
++count2;
|
|
13445
14388
|
const tr = document.createElement("tr");
|
|
13446
14389
|
for (let i = 0; i < nf; ++i) {
|
|
13447
|
-
const value = row[
|
|
14390
|
+
const value = row[schema[i].column];
|
|
13448
14391
|
const td = document.createElement("td");
|
|
13449
14392
|
td.innerText = value == null ? "" : formats[i](value);
|
|
13450
14393
|
tr.appendChild(td);
|
|
@@ -13476,12 +14419,11 @@ var Table2 = class extends MosaicClient {
|
|
|
13476
14419
|
this.sortHeader = th;
|
|
13477
14420
|
th.firstChild.textContent = this.sortDesc ? "\u25BE" : "\u25B4";
|
|
13478
14421
|
}
|
|
13479
|
-
|
|
13480
|
-
this.requestQuery(query);
|
|
14422
|
+
this.requestData();
|
|
13481
14423
|
}
|
|
13482
14424
|
};
|
|
13483
|
-
function formatof(base = {},
|
|
13484
|
-
return
|
|
14425
|
+
function formatof(base = {}, schema, locale) {
|
|
14426
|
+
return schema.map(({ column: column2, type }) => {
|
|
13485
14427
|
if (column2 in base) {
|
|
13486
14428
|
return base[column2];
|
|
13487
14429
|
} else {
|
|
@@ -13496,8 +14438,8 @@ function formatof(base = {}, stats, locale) {
|
|
|
13496
14438
|
}
|
|
13497
14439
|
});
|
|
13498
14440
|
}
|
|
13499
|
-
function alignof(base = {},
|
|
13500
|
-
return
|
|
14441
|
+
function alignof(base = {}, schema) {
|
|
14442
|
+
return schema.map(({ column: column2, type }) => {
|
|
13501
14443
|
if (column2 in base) {
|
|
13502
14444
|
return base[column2];
|
|
13503
14445
|
} else if (type === "number") {
|
|
@@ -13507,11 +14449,17 @@ function alignof(base = {}, stats) {
|
|
|
13507
14449
|
}
|
|
13508
14450
|
});
|
|
13509
14451
|
}
|
|
13510
|
-
function
|
|
14452
|
+
function widthof(base = {}, schema) {
|
|
14453
|
+
return schema.map(({ column: column2 }) => base[column2]);
|
|
14454
|
+
}
|
|
14455
|
+
function tableCSS(id, aligns, widths) {
|
|
13511
14456
|
const styles = [];
|
|
13512
|
-
|
|
13513
|
-
|
|
13514
|
-
|
|
14457
|
+
aligns.forEach((a, i) => {
|
|
14458
|
+
const w = +widths[i];
|
|
14459
|
+
if (a !== "left" || w) {
|
|
14460
|
+
const align = a !== "left" ? `text-align:${a};` : "";
|
|
14461
|
+
const width = w ? `width:${w}px;max-width:${w}px;` : "";
|
|
14462
|
+
styles.push(`#${id} tr>:nth-child(${i + 1}) {${align}${width}}`);
|
|
13515
14463
|
}
|
|
13516
14464
|
});
|
|
13517
14465
|
return styles.join(" ");
|
|
@@ -13520,5 +14468,9 @@ export {
|
|
|
13520
14468
|
Menu,
|
|
13521
14469
|
Search,
|
|
13522
14470
|
Slider,
|
|
13523
|
-
Table2 as Table
|
|
14471
|
+
Table2 as Table,
|
|
14472
|
+
menu,
|
|
14473
|
+
search,
|
|
14474
|
+
slider,
|
|
14475
|
+
table
|
|
13524
14476
|
};
|