Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@uwdata/mosaic-core

Package Overview
Dependencies
Maintainers
2
Versions
20
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@uwdata/mosaic-core - npm Package Compare versions

Comparing version 0.7.1 to 0.8.0

15

package.json
{
"name": "@uwdata/mosaic-core",
"version": "0.7.1",
"version": "0.8.0",
"description": "Scalable and extensible linked data views.",

@@ -26,3 +26,3 @@ "keywords": [

"build": "node ../../esbuild.js mosaic-core",
"lint": "eslint src test --ext .js",
"lint": "eslint src test",
"test": "mocha 'test/**/*-test.js'",

@@ -32,7 +32,10 @@ "prepublishOnly": "npm run test && npm run lint && npm run build"

"dependencies": {
"@duckdb/duckdb-wasm": "^1.28.1-dev109.0",
"@uwdata/mosaic-sql": "^0.7.0",
"apache-arrow": "^15.0.0"
"@duckdb/duckdb-wasm": "^1.28.1-dev194.0",
"@uwdata/mosaic-sql": "^0.8.0",
"apache-arrow": "^15.0.2"
},
"gitHead": "7e6f3ea9b3011ea2c9201c1aa16e8e5664621a4c"
"devDependencies": {
"@uwdata/mosaic-duckdb": "^0.8.0"
},
"gitHead": "a24b4c9f7dfa1c38c6af96ec17e075326c1af9b0"
}

4

src/connectors/wasm.js

@@ -25,3 +25,3 @@ import * as duckdb from '@duckdb/duckdb-wasm';

* Will lazily initialize DuckDB-WASM if not already loaded.
* @returns {duckdb.AsyncDuckDB} The DuckDB-WASM instance.
* @returns {Promise<duckdb.AsyncDuckDB>} The DuckDB-WASM instance.
*/

@@ -36,3 +36,3 @@ async function getDuckDB() {

* Will lazily initialize DuckDB-WASM if not already loaded.
* @returns {duckdb.AsyncDuckDBConnection} The DuckDB-WASM connection.
* @returns {Promise<duckdb.AsyncDuckDBConnection>} The DuckDB-WASM connection.
*/

@@ -39,0 +39,0 @@ async function getConnection() {

@@ -11,4 +11,3 @@ import { socketConnector } from './connectors/socket.js';

* Set or retrieve the coordinator instance.
*
* @param {Coordinator} instance the coordinator instance to set
* @param {Coordinator} [instance] the coordinator instance to set
* @returns {Coordinator} the coordinator instance

@@ -46,3 +45,11 @@ */

configure({ cache = true, consolidate = true, indexes = true }) {
/**
* Set configuration options for this coordinator.
* @param {object} [options] Configration options.
* @param {boolean} [options.cache=true] Boolean flag to enable/disable query caching.
* @param {boolean} [options.consolidate=true] Boolean flag to enable/disable query consolidation.
* @param {boolean|object} [options.indexes=true] Boolean flag to enable/disable
* automatic data cube indexes or an index options object.
*/
configure({ cache = true, consolidate = true, indexes = true } = {}) {
this.manager.cache(cache);

@@ -121,3 +128,2 @@ this.manager.consolidate(consolidate);

* Connect a client to the coordinator.
*
* @param {import('./MosaicClient.js').MosaicClient} client the client to disconnect

@@ -124,0 +130,0 @@ */

@@ -57,3 +57,4 @@ import { Query, and, create, isBetween, scaleTransform, sql } from '@uwdata/mosaic-sql';

const { source } = active;
if (source && source === this.activeView?.source) return true; // we're good!
// exit early if indexes already set up for active view
if (source && source === this.activeView?.source) return true;

@@ -79,3 +80,3 @@ this.clear();

const query = client.query(sel.predicate(client))
.select({ ...activeView.columns, ...index.count })
.select({ ...activeView.columns, ...index.aux })
.groupby(Object.keys(activeView.columns));

@@ -100,2 +101,5 @@

}
// index creation successful
return true;
}

@@ -185,6 +189,9 @@

const dims = [];
let count;
const aux = {}; // auxiliary columns needed by aggregates
let auxAs;
for (const { as, expr: { aggregate } } of q.select()) {
switch (aggregate?.toUpperCase?.()) {
for (const entry of q.select()) {
const { as, expr: { aggregate, args } } = entry;
const op = aggregate?.toUpperCase?.();
switch (op) {
case 'COUNT':

@@ -195,10 +202,24 @@ case 'SUM':

case 'AVG':
count = '_count_';
aggr.push({ [as]: sql`(SUM("${as}" * ${count}) / SUM(${count}))::DOUBLE` });
aux[auxAs = '__count__'] = sql`COUNT(*)`;
aggr.push({ [as]: sql`(SUM("${as}" * ${auxAs}) / SUM(${auxAs}))::DOUBLE` });
break;
case 'ARG_MAX':
aux[auxAs = `__max_${as}__`] = sql`MAX(${args[1]})`;
aggr.push({ [as]: sql`ARG_MAX("${as}", ${auxAs})` });
break;
case 'ARG_MIN':
aux[auxAs = `__min_${as}__`] = sql`MIN(${args[1]})`;
aggr.push({ [as]: sql`ARG_MIN("${as}", ${auxAs})` });
break;
// aggregates that commute directly
case 'MAX':
aggr.push({ [as]: sql`MAX("${as}")` });
break;
case 'MIN':
aggr.push({ [as]: sql`MIN("${as}")` });
case 'BIT_AND':
case 'BIT_OR':
case 'BIT_XOR':
case 'BOOL_AND':
case 'BOOL_OR':
case 'PRODUCT':
aggr.push({ [as]: sql`${op}("${as}")` });
break;

@@ -211,8 +232,3 @@ default:

return {
aggr,
dims,
count: count ? { [count]: sql`COUNT(*)` } : {},
from
};
return { aggr, dims, aux, from };
}

@@ -219,0 +235,0 @@

@@ -49,5 +49,11 @@ import { DataCubeIndexer } from './DataCubeIndexer.js';

/**
* Internal method to process a selection update.
* The return value is passed as a selection callback value.
* @returns {Promise} A Promise that resolves when the update completes.
*/
update() {
const { mc, indexer, clients, selection } = this;
return indexer?.index(clients)
const hasIndex = indexer?.index(clients);
return hasIndex
? indexer.update()

@@ -54,0 +60,0 @@ : defaultUpdate(mc, clients, selection);

@@ -51,2 +51,3 @@ import { throttle } from './util/throttle.js';

* Return an array of fields queried by this client.
* @returns {object[]|null} The fields to retrieve info for.
*/

@@ -59,5 +60,6 @@ fields() {

* Called by the coordinator to set the field info for this client.
* @param {*} info The field info result.
* @returns {this}
*/
fieldInfo() {
fieldInfo(info) { // eslint-disable-line no-unused-vars
return this;

@@ -68,4 +70,6 @@ }

* Return a query specifying the data needed by this client.
* @param {*} [filter] The filtering criteria to apply in the query.
* @returns {*} The client query
*/
query() {
query(filter) { // eslint-disable-line no-unused-vars
return null;

@@ -76,2 +80,3 @@ }

* Called by the coordinator to inform the client that a query is pending.
* @returns {this}
*/

@@ -84,7 +89,6 @@ queryPending() {

* Called by the coordinator to return a query result.
*
* @param {*} data the query result
* @param {*} data The query result.
* @returns {this}
*/
queryResult() {
queryResult(data) { // eslint-disable-line no-unused-vars
return this;

@@ -95,2 +99,4 @@ }

* Called by the coordinator to report a query execution error.
* @param {*} error
* @returns {this}
*/

@@ -125,2 +131,4 @@ queryError(error) {

* For example to (re-)render an interface component.
*
* @returns {this | Promise<any>}
*/

@@ -127,0 +135,0 @@ update() {

@@ -7,3 +7,3 @@ import { AsyncDispatch } from './util/AsyncDispatch.js';

* @param {*} x The value to test.
* @returns {boolean} True if the input is a Param, false otherwise.
* @returns {x is Param} True if the input is a Param, false otherwise.
*/

@@ -47,3 +47,5 @@ export function isParam(x) {

const p = new Param();
const update = () => p.update(values.map(v => isParam(v) ? v.value : v));
const update = () => {
p.update(values.map(v => isParam(v) ? v.value : v));
};
update();

@@ -50,0 +52,0 @@ values.forEach(v => isParam(v) ? v.addEventListener('value', update) : 0);

@@ -8,2 +8,3 @@ import { Query, Ref, isDescribeQuery } from '@uwdata/mosaic-sql';

: typeof setImmediate !== 'undefined' ? setImmediate : setTimeout;
// @ts-ignore
return method(callback);

@@ -86,3 +87,5 @@ }

if (
// @ts-ignore
query.orderby().length || query.where().length ||
// @ts-ignore
query.qualify().length || query.having().length

@@ -102,5 +105,8 @@ ) {

const groupby = query.groupby();
// @ts-ignore
if (groupby.length) {
const map = {}; // expression map (as -> expr)
// @ts-ignore
query.select().forEach(({ as, expr }) => map[as] = expr);
// @ts-ignore
q.$groupby(groupby.map(e => (e instanceof Ref && map[e.column]) || e));

@@ -107,0 +113,0 @@ }

@@ -7,3 +7,3 @@ import { or } from '@uwdata/mosaic-sql';

* @param {*} x The value to test.
* @returns {boolean} True if the input is a Selection, false otherwise.
* @returns {x is Selection} True if the input is a Selection, false otherwise.
*/

@@ -80,3 +80,3 @@ export function isSelection(x) {

* Create a cloned copy of this Selection instance.
* @returns {this} A clone of this selection.
* @returns {Selection} A clone of this selection.
*/

@@ -93,3 +93,3 @@ clone() {

* @param {*} source The clause source to remove.
* @returns {this} A cloned and updated Selection.
* @returns {Selection} A cloned and updated Selection.
*/

@@ -174,5 +174,5 @@ remove(source) {

* @param {string} type The event type.
* @param {*} value The input event value.
* @returns {*} For value-typed events, returns a dispatch queue filter
* function. Otherwise returns null.
* @param {*} value The new event value that will be enqueued.
* @returns {(value: *) => boolean|null} For value-typed events,
* returns a dispatch queue filter function. Otherwise returns null.
*/

@@ -292,3 +292,4 @@ emitQueueFilter(type, value) {

}
return null;
}
}

@@ -19,3 +19,3 @@ /**

* @param {string} type The event type.
* @param {(value: *) => Promise?} callback The event handler
* @param {(value: *) => void | Promise} callback The event handler
* callback function to add. If the callback has already been

@@ -39,3 +39,3 @@ * added for the event type, this method has no effect.

* @param {string} type The event type.
* @param {(value: *) => Promise?} callback The event handler
* @param {(value: *) => void | Promise} callback The event handler
* callback function to remove.

@@ -69,2 +69,3 @@ */

* queued events are filtered)
* @param {string} type The event type.
* @param {*} value The new event value that will be enqueued.

@@ -74,3 +75,3 @@ * @returns {(value: *) => boolean|null} A dispatch queue filter

*/
emitQueueFilter() {
emitQueueFilter(type, value) { // eslint-disable-line no-unused-vars
// removes all pending items

@@ -101,2 +102,4 @@ return null;

if (entry.pending) {
// an earlier emit is still processing
// enqueue the current update, possibly filtering other pending updates
entry.queue.enqueue(value, this.emitQueueFilter(type, value));

@@ -107,11 +110,11 @@ } else {

if (callbacks?.size) {
const promise = Promise
.allSettled(Array.from(callbacks, callback => callback(event)))
.then(() => {
entry.pending = null;
if (!queue.isEmpty()) {
this.emit(type, queue.dequeue());
}
});
entry.pending = promise;
// broadcast update to callbacks, which may return promises
// wait until promises resolve, then process pending updates
const callbackValues = Array.from(callbacks, cb => cb(event));
entry.pending = Promise.allSettled(callbackValues).then(() => {
entry.pending = null;
if (!queue.isEmpty()) {
this.emit(type, queue.dequeue());
}
});
}

@@ -118,0 +121,0 @@ }

@@ -1,6 +0,2 @@

// arrow type ids
const INTEGER = 2;
const FLOAT = 3;
const DECIMAL = 7;
const TIMESTAMP = 10;
import { DataType } from 'apache-arrow';

@@ -12,3 +8,3 @@ /**

* @param {*} values The value to test
* @returns true if the value duck types as Apache Arrow data
* @returns {values is import('apache-arrow').Table} true if the value duck types as Apache Arrow data
*/

@@ -20,15 +16,10 @@ export function isArrowTable(values) {

/**
* Return a JavaScript array type for an Apache Arrow column type.
* @param {*} type an Apache Arrow column type
* @returns a JavaScript array constructor
*/
* Return a JavaScript array type for an Apache Arrow column type.
* @param {DataType} type an Apache Arrow column type
* @returns a JavaScript array constructor
*/
export function convertArrowArrayType(type) {
switch (type.typeId) {
case INTEGER:
case FLOAT:
case DECIMAL:
return Float64Array;
default:
return Array;
}
return DataType.isInt(type) || DataType.isFloat(type) || DataType.isDecimal(type)
? Float64Array
: Array;
}

@@ -42,10 +33,8 @@

* Otherwise, the default Arrow values are used.
* @param {*} type an Apache Arrow column type
* @param {DataType} type an Apache Arrow column type
* @returns a value conversion function
*/
export function convertArrowValue(type) {
const { typeId } = type;
// map timestamp numbers to date objects
if (typeId === TIMESTAMP) {
if (DataType.isTimestamp(type)) {
return v => v == null ? v : new Date(v);

@@ -55,3 +44,3 @@ }

// map bigint to number
if (typeId === INTEGER && type.bitWidth >= 64) {
if (DataType.isInt(type) && type.bitWidth >= 64) {
return v => v == null ? v : Number(v);

@@ -61,3 +50,3 @@ }

// map decimal to number
if (typeId === DECIMAL) {
if (DataType.isDecimal(type)) {
const scale = 1 / Math.pow(10, type.scale);

@@ -82,6 +71,5 @@ return v => v == null ? v : decimalToNumber(v, scale);

const { type } = column;
const { typeId } = type;
// map timestamp numbers to date objects
if (typeId === TIMESTAMP) {
if (DataType.isTimestamp(type)) {
const size = column.length;

@@ -97,3 +85,3 @@ const array = new Array(size);

// map bigint to number
if (typeId === INTEGER && type.bitWidth >= 64) {
if (DataType.isInt(type) && type.bitWidth >= 64) {
const size = column.length;

@@ -109,3 +97,3 @@ const array = new Float64Array(size);

// map decimal to number
if (typeId === DECIMAL) {
if (DataType.isDecimal(type)) {
const scale = 1 / Math.pow(10, type.scale);

@@ -135,6 +123,6 @@ const size = column.length;

* Note: if the value is sufficiently large the conversion may be lossy!
* @param {Uint32Array} v a fixed decimal value
* @param {Uint32Array & { signed: boolean }} v a fixed decimal value
* @param {number} scale a scale factor, corresponding to the
* number of fractional decimal digits in the fixed point value
* @returns the resulting number
* @returns {number} the resulting number
*/

@@ -141,0 +129,0 @@ function decimalToNumber(v, scale) {

@@ -27,2 +27,3 @@ export function jsType(type) {

case 'UUID':
case 'JSON':
return 'string';

@@ -29,0 +30,0 @@ case 'ARRAY':

@@ -5,5 +5,6 @@ export function queryResult() {

const p = new Promise((r, e) => { resolve = r; reject = e; });
p.fulfill = value => (resolve(value), p);
p.reject = err => (reject(err), p);
return p;
return Object.assign(p, {
fulfill: value => (resolve(value), p),
reject: err => (reject(err), p)
});
}

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc