@perspective-dev/client 4.0.1 → 4.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cdn/perspective-server.worker.js +1 -1
- package/dist/cdn/perspective-server.worker.js.map +3 -3
- package/dist/cdn/perspective.js +2 -2
- package/dist/cdn/perspective.js.map +4 -4
- package/dist/esm/perspective.browser.d.ts +5 -1
- package/dist/esm/perspective.inline.js +2 -2
- package/dist/esm/perspective.inline.js.map +4 -4
- package/dist/esm/perspective.js +2 -2
- package/dist/esm/perspective.js.map +4 -4
- package/dist/esm/perspective.node.d.ts +6 -1
- package/dist/esm/perspective.node.js +722 -353
- package/dist/esm/perspective.node.js.map +4 -4
- package/dist/esm/ts-rs/ColumnType.d.ts +4 -0
- package/dist/esm/ts-rs/ViewConfig.d.ts +18 -0
- package/dist/esm/ts-rs/ViewWindow.d.ts +9 -9
- package/dist/esm/virtual_server.d.ts +47 -0
- package/dist/esm/virtual_servers/duckdb.d.ts +39 -0
- package/dist/esm/virtual_servers/duckdb.js +12 -0
- package/dist/esm/virtual_servers/duckdb.js.map +7 -0
- package/dist/esm/wasm/browser.d.ts +1 -1
- package/dist/wasm/perspective-js.d.ts +52 -13
- package/dist/wasm/perspective-js.js +680 -399
- package/dist/wasm/perspective-js.wasm +0 -0
- package/dist/wasm/perspective-js.wasm.d.ts +20 -8
- package/package.json +4 -1
- package/src/rust/client.rs +14 -5
- package/src/rust/lib.rs +11 -1
- package/src/rust/table.rs +3 -2
- package/src/rust/table_data.rs +19 -14
- package/src/rust/utils/browser.rs +0 -4
- package/src/rust/utils/console_logger.rs +3 -2
- package/src/rust/utils/errors.rs +10 -28
- package/src/rust/utils/futures.rs +3 -3
- package/src/rust/utils/json.rs +4 -4
- package/src/rust/virtual_server.rs +746 -0
- package/src/ts/perspective-server.worker.ts +33 -23
- package/src/ts/perspective.browser.ts +17 -2
- package/src/ts/perspective.node.ts +46 -11
- package/src/ts/ts-rs/ColumnType.ts +6 -0
- package/src/ts/ts-rs/ViewConfig.ts +8 -0
- package/src/ts/ts-rs/ViewWindow.ts +3 -3
- package/src/ts/virtual_server.ts +126 -0
- package/src/ts/virtual_servers/duckdb.ts +511 -0
- package/src/ts/wasm/browser.ts +17 -9
- package/tsconfig.json +1 -0
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { Aggregate } from "./Aggregate.js";
|
|
2
|
+
import type { Expressions } from "./Expressions.js";
|
|
3
|
+
import type { Filter } from "./Filter.js";
|
|
4
|
+
import type { FilterReducer } from "./FilterReducer.js";
|
|
5
|
+
import type { Sort } from "./Sort.js";
|
|
6
|
+
export type ViewConfig = {
|
|
7
|
+
group_by: Array<string>;
|
|
8
|
+
split_by: Array<string>;
|
|
9
|
+
sort: Array<Sort>;
|
|
10
|
+
filter: Array<Filter>;
|
|
11
|
+
filter_op?: FilterReducer;
|
|
12
|
+
expressions: Expressions;
|
|
13
|
+
columns: Array<string | null>;
|
|
14
|
+
aggregates: {
|
|
15
|
+
[key in string]?: Aggregate;
|
|
16
|
+
};
|
|
17
|
+
group_by_depth?: number | null;
|
|
18
|
+
};
|
|
@@ -5,19 +5,19 @@
|
|
|
5
5
|
* [`View`].
|
|
6
6
|
*/
|
|
7
7
|
export type ViewWindow = {
|
|
8
|
-
start_row
|
|
9
|
-
start_col
|
|
10
|
-
end_row
|
|
11
|
-
end_col
|
|
12
|
-
id
|
|
13
|
-
index
|
|
14
|
-
leaves_only
|
|
8
|
+
start_row?: number;
|
|
9
|
+
start_col?: number;
|
|
10
|
+
end_row?: number;
|
|
11
|
+
end_col?: number;
|
|
12
|
+
id?: boolean;
|
|
13
|
+
index?: boolean;
|
|
14
|
+
leaves_only?: boolean;
|
|
15
15
|
/**
|
|
16
16
|
* Only impacts [`View::to_csv`]
|
|
17
17
|
*/
|
|
18
|
-
formatted
|
|
18
|
+
formatted?: boolean;
|
|
19
19
|
/**
|
|
20
20
|
* Only impacts [`View::to_arrow`]
|
|
21
21
|
*/
|
|
22
|
-
compression
|
|
22
|
+
compression?: string;
|
|
23
23
|
};
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { ColumnType } from "./ts-rs/ColumnType.ts";
|
|
2
|
+
import { ViewConfig } from "./ts-rs/ViewConfig.ts";
|
|
3
|
+
import { ViewWindow } from "./ts-rs/ViewWindow.ts";
|
|
4
|
+
import type * as perspective from "../../dist/wasm/perspective-js.js";
|
|
5
|
+
/**
|
|
6
|
+
* VirtualServer API for implementing custom data sources in JavaScript/WASM.
|
|
7
|
+
*
|
|
8
|
+
* The VirtualServer pattern allows you to create custom data sources that
|
|
9
|
+
* integrate with Perspective's protocol. This is useful for:
|
|
10
|
+
* - Connecting to external databases (DuckDB, PostgreSQL, etc.)
|
|
11
|
+
* - Streaming data from APIs or message queues
|
|
12
|
+
* - Implementing custom aggregation or transformation logic
|
|
13
|
+
* - Creating data adapters without copying data into Perspective tables
|
|
14
|
+
*
|
|
15
|
+
* @module virtual_server
|
|
16
|
+
*/
|
|
17
|
+
export interface ServerFeatures {
|
|
18
|
+
expressions?: boolean;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Handler interface that you implement to provide custom data sources.
|
|
22
|
+
*
|
|
23
|
+
* All methods will be called by the VirtualServer when handling protocol
|
|
24
|
+
* messages from Perspective clients. Methods can return values directly or
|
|
25
|
+
* return Promises for asynchronous operations (e.g., database queries).
|
|
26
|
+
*/
|
|
27
|
+
export interface VirtualServerHandler {
|
|
28
|
+
getHostedTables(): string[] | Promise<string[]>;
|
|
29
|
+
tableSchema(tableId: string): Record<string, ColumnType> | Promise<Record<string, ColumnType>>;
|
|
30
|
+
tableSize(tableId: string): number | Promise<number>;
|
|
31
|
+
tableMakeView(tableId: string, viewId: string, config: ViewConfig): void | Promise<void>;
|
|
32
|
+
viewDelete(viewId: string): void | Promise<void>;
|
|
33
|
+
viewGetData(viewId: string, config: ViewConfig, viewport: ViewWindow, dataSlice: perspective.JsVirtualDataSlice): void | Promise<void>;
|
|
34
|
+
viewSchema?(viewId: string, config?: ViewConfig): Record<string, ColumnType> | Promise<Record<string, ColumnType>>;
|
|
35
|
+
viewSize?(viewId: string): number | Promise<number>;
|
|
36
|
+
tableValidateExpression?(tableId: string, expression: string): ColumnType | Promise<ColumnType>;
|
|
37
|
+
getFeatures?(): ServerFeatures | Promise<ServerFeatures>;
|
|
38
|
+
makeTable?(tableId: string, data: string | Uint8Array): void | Promise<void>;
|
|
39
|
+
}
|
|
40
|
+
export declare function createMessageHandler(mod: typeof perspective, handler: VirtualServerHandler): MessagePort;
|
|
41
|
+
/**
|
|
42
|
+
* Re-export the WASM VirtualServer and VirtualDataSlice classes with better names.
|
|
43
|
+
*
|
|
44
|
+
* VirtualServer: Handles Perspective protocol messages using your custom handler
|
|
45
|
+
* VirtualDataSlice: Used to fill data in viewGetData callbacks
|
|
46
|
+
*/
|
|
47
|
+
export { JsVirtualServer as VirtualServer, JsVirtualDataSlice as VirtualDataSlice, } from "../../dist/wasm/perspective-js.js";
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { VirtualDataSlice, VirtualServerHandler } from "@perspective-dev/client";
|
|
2
|
+
import type { ColumnType } from "@perspective-dev/client/dist/esm/ts-rs/ColumnType.d.ts";
|
|
3
|
+
import type { ViewConfig } from "@perspective-dev/client/dist/esm/ts-rs/ViewConfig.d.ts";
|
|
4
|
+
import type { ViewWindow } from "@perspective-dev/client/dist/esm/ts-rs/ViewWindow.d.ts";
|
|
5
|
+
import type * as duckdb from "@duckdb/duckdb-wasm";
|
|
6
|
+
export declare class DuckDBHandler implements VirtualServerHandler {
|
|
7
|
+
private db;
|
|
8
|
+
constructor(db: duckdb.AsyncDuckDBConnection);
|
|
9
|
+
getFeatures(): {
|
|
10
|
+
group_by: boolean;
|
|
11
|
+
split_by: boolean;
|
|
12
|
+
sort: boolean;
|
|
13
|
+
expressions: boolean;
|
|
14
|
+
filter_ops: {
|
|
15
|
+
integer: string[];
|
|
16
|
+
float: string[];
|
|
17
|
+
string: string[];
|
|
18
|
+
boolean: string[];
|
|
19
|
+
date: string[];
|
|
20
|
+
datetime: string[];
|
|
21
|
+
};
|
|
22
|
+
aggregates: {
|
|
23
|
+
integer: string[];
|
|
24
|
+
float: string[];
|
|
25
|
+
string: string[];
|
|
26
|
+
boolean: string[];
|
|
27
|
+
date: string[];
|
|
28
|
+
datetime: string[];
|
|
29
|
+
};
|
|
30
|
+
};
|
|
31
|
+
getHostedTables(): Promise<any[]>;
|
|
32
|
+
tableSchema(tableId: string): Promise<Record<string, ColumnType>>;
|
|
33
|
+
viewColumnSize(viewId: string, config: ViewConfig): Promise<number>;
|
|
34
|
+
tableSize(tableId: string): Promise<number>;
|
|
35
|
+
tableMakeView(tableId: string, viewId: string, config: ViewConfig): Promise<void>;
|
|
36
|
+
tableValidateExpression(tableId: string, expression: string): Promise<ColumnType>;
|
|
37
|
+
viewDelete(viewId: string): Promise<void>;
|
|
38
|
+
viewGetData(viewId: string, config: ViewConfig, viewport: ViewWindow, dataSlice: VirtualDataSlice): Promise<void>;
|
|
39
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
var P=["sum","count","any_value","arbitrary","array_agg","avg","bit_and","bit_or","bit_xor","bitstring_agg","bool_and","bool_or","countif","favg","fsum","geomean","kahan_sum","last","max","min","product","string_agg","sumkahan"],A=["count","any_value","arbitrary","first","countif","last","string_agg"],I=["==","!=","LIKE","IS DISTINCT FROM","IS NOT DISTINCT FROM",">=","<=",">","<"];function N(o){if(o==="VARCHAR")return"string";if(o==="DOUBLE"||o==="BIGINT"||o==="HUGEINT"||o.startsWith("Decimal"))return"float";if(o.startsWith("Int")||o==="INTEGER")return"integer";if(o==="Utf8")return"string";if(o==="Date32<DAY>")return"date";if(o==="Float64")return"float";if(o==="DATE")return"date";if(o==="BOOLEAN")return"boolean";if(o==="TIMESTAMP")return"datetime";throw new Error(`Unknown type '${o}'`)}function V(o,r){if(o==null||!(o instanceof Uint32Array||o instanceof Int32Array))return o;let i=BigInt(0);for(let u=0;u<o.length;u++)i|=BigInt(o[u])<<BigInt(u*32);let n=BigInt(2)**BigInt(127);i>=n&&(i-=BigInt(2)**BigInt(128));let a=r.match(/Decimal\[\d+e(\d+)\]/),s=a?parseInt(a[1]):0;return s>0?Number(i)/Math.pow(10,s):Number(i)}async function m(o,r,i={}){r=r.replace(/\s+/g," ").trim();try{let n=await o.query(r);return i.columns?{rows:n.toArray(),columns:n.schema.fields.map(a=>a.name),dtypes:n.schema.fields.map(a=>a.type.toString())}:n.toArray()}catch(n){throw console.error("Query error:",n),console.error("Query:",r),n}}var G=class{db;constructor(r){this.db=r}getFeatures(){return{group_by:!0,split_by:!0,sort:!0,expressions:!0,filter_ops:{integer:I,float:I,string:I,boolean:I,date:I,datetime:I},aggregates:{integer:P,float:P,string:A,boolean:A,date:A,datetime:A}}}async getHostedTables(){return(await m(this.db,"SHOW ALL TABLES")).map(i=>i.toJSON().name)}async tableSchema(r){let i=`DESCRIBE ${r}`,n=await m(this.db,i),a={};for(let s of n){let u=s.toJSON(),y=u.column_name;if(!y.startsWith("__")||!y.endsWith("__")){let h=y.split("_").slice(-1)[0];a[h]=N(u.column_type)}}return a}async viewColumnSize(r,i){let n=`SELECT COUNT(*) FROM (DESCRIBE ${r})`,a=await m(this.db,n),s=i.group_by?.length||0;return Number(Object.values(a[0].toJSON())[0])-(s===0?0:s+(i.split_by?.length===0?1:0))}async tableSize(r){let i=`SELECT COUNT(*) FROM ${r}`,n=await m(this.db,i);return Number(n[0].toJSON()["count_star()"])}async tableMakeView(r,i,n){let a=n.columns||[],s=n.group_by||[],u=n.split_by||[],y=n.aggregates||{},h=n.sort||[],E=n.expressions||{},O=n.filter||[],_=t=>E[t]||`"${t}"`,T=t=>y[t]||null,C=()=>{let t=[];if(s.length>0){for(let c of a)if(c!==null){let l=T(c)||"any_value";t.push(`${l}(${_(c)}) as "${c}"`)}if(u.length===0){for(let l=0;l<s.length;l++)t.push(`${_(s[l])} as __ROW_PATH_${l}__`);let c=s.map(_).join(", ");t.push(`GROUPING_ID(${c}) AS __GROUPING_ID__`)}}else if(a.length>0)for(let c of a)c!==null&&t.push(`${_(c)} as "${c.replace(/"/g,'""')}"`);return t},f=[],S=[],$=[];if(s.length>0)for(let t=0;t<s.length;t++){let c=s.slice(0,t+1).map(_).join(", ");u.length===0&&f.push(`GROUPING_ID(${c}) DESC`);for(let[l,p]of h)if(p!=="none"){let e=T(l)||"any_value";t>=s.length-1?f.push(`${e}(${_(l)}) ${p}`):f.push(`first(${e}(${_(l)})) OVER __WINDOW_${t}__ ${p}`)}f.push(`__ROW_PATH_${t}__ ASC`)}else for(let[t,c]of h)c&&f.push(`${_(t)} ${c}`);if(h.length>0&&s.length>1)for(let t=0;t<s.length-1;t++){let c=Array.from({length:t+1},(e,d)=>`__ROW_PATH_${d}__`).join(", "),l=s.slice(0,t+1).map(_).join(", "),p=s.map(_).join(", ");S.push(`__WINDOW_${t}__ AS (PARTITION BY GROUPING_ID(${l}), ${c} ORDER BY ${p})`)}for(let[t,c,l]of O)if(l!=null){let p=typeof l=="string"?`'${l}'`:String(l);$.push(`${_(t)} ${c} ${p}`)}let g;if(u.length>0?g=`SELECT * FROM ${r}`:g=`SELECT ${C().join(", ")} FROM ${r}`,$.length>0&&(g=`${g} WHERE ${$.join(" AND ")}`),u.length>0){let t=s.map(_).join(", "),c=s.map((e,d)=>`${_(e)} AS __ROW_PATH_${d}__`).join(", "),l=u.map(e=>`"${e}"`).join(", "),p=C().join(", ");g=`
|
|
2
|
+
SELECT * EXCLUDE (${t}), ${c} FROM (
|
|
3
|
+
PIVOT (${g})
|
|
4
|
+
ON ${l}
|
|
5
|
+
USING ${p}
|
|
6
|
+
GROUP BY ${t}
|
|
7
|
+
)
|
|
8
|
+
`}else if(s.length>0){let t=s.map(_).join(", ");g=`${g} GROUP BY ROLLUP(${t})`}S.length>0&&(g=`${g} WINDOW ${S.join(", ")}`),f.length>0&&(g=`${g} ORDER BY ${f.join(", ")}`),g=`CREATE TABLE ${i} AS (${g})`,await m(this.db,g)}async tableValidateExpression(r,i){let n=`DESCRIBE (select ${i} from ${r})`,a=await m(this.db,n);return N(a[0].toJSON().column_type)}async viewDelete(r){let i=`DROP TABLE IF EXISTS ${r}`;await m(this.db,i)}async viewGetData(r,i,n,a){let s=i.group_by||[],u=i.split_by||[],y=n.start_col,h=n.end_col,E=n.start_row||0,O=n.end_row,_="";O!=null&&(_=`LIMIT ${O-E} OFFSET ${E}`);let T=`DESCRIBE ${r}`,C=await m(this.db,T),f=new Map;for(let e of C){let d=e.toJSON();f.set(d.column_name,d.column_type)}let S=Array.from(f.entries()).filter(([e])=>!e.startsWith("__")).slice(y,h),$=[];if(s.length>0){u.length===0&&$.push("__GROUPING_ID__");for(let e=0;e<s.length;e++)$.push(`__ROW_PATH_${e}__`)}let t=`
|
|
9
|
+
SELECT ${[...$.map(e=>`"${e}"`),...S.map(([e])=>`"${e}"`)].join(", ")}
|
|
10
|
+
FROM ${r} ${_}
|
|
11
|
+
`,{rows:c,columns:l,dtypes:p}=await m(this.db,t,{columns:!0});for(let e=0;e<l.length;e++){let d=l[e];if(e===0&&s.length>0&&u.length===0)continue;let R=null,D=null,B=d.match(/__ROW_PATH_(\d+)__/);B&&(R=parseInt(B[1]),D=2**(s.length-R)-1);let L=N(p[e]),U=p[e].startsWith("Decimal"),x=R!==null?"__ROW_PATH__":d.replace(/_/g,"|");for(let w=0;w<c.length;w++){let W=c[w].toArray();if(u.length>0||D===null||W[0]<D){let b=W[e];U&&(b=V(b,p[e])),typeof b=="bigint"&&(b=Number(b)),a.setCol(L,x,w,b,R)}}}}};export{G as DuckDBHandler};
|
|
12
|
+
//# sourceMappingURL=duckdb.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/ts/virtual_servers/duckdb.ts"],
|
|
4
|
+
"sourcesContent": ["// \u250F\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2513\n// \u2503 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588 \u2588 \u2588 \u2588 \u2588 \u2588\u2584 \u2580\u2588\u2588\u2588 \u2588 \u2503\n// \u2503 \u2584\u2584\u2584\u2584\u2584\u2588 \u2588\u2584\u2584\u2584\u2584\u2584 \u2584\u2584\u2584\u2584\u2584\u2588 \u2580\u2580\u2580\u2580\u2580\u2588\u2580\u2580\u2580\u2580\u2580 \u2588 \u2580\u2580\u2580\u2580\u2580\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u258C\u2590\u2588\u2588\u2588 \u2588\u2588\u2588\u2584 \u2580\u2588 \u2588 \u2580\u2580\u2580\u2580\u2580 \u2503\n// \u2503 \u2588\u2580\u2580\u2580\u2580\u2580 \u2588\u2580\u2580\u2580\u2580\u2580 \u2588\u2580\u2588\u2588\u2580\u2580 \u2584\u2584\u2584\u2584\u2584 \u2588 \u2584\u2584\u2584\u2584\u2584\u2588 \u2584\u2584\u2584\u2584\u2584\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u258C\u2590\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2584 \u2588 \u2584\u2584\u2584\u2584\u2584 \u2503\n// \u2503 \u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588 \u2580\u2588\u2584 \u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588 \u2588\u2588\u2588\u258C\u2590\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2584 \u2588 \u2503\n// \u2523\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u252B\n// \u2503 Copyright (c) 2017, the Perspective Authors. \u2503\n// \u2503 \u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C \u2503\n// \u2503 This file is part of the Perspective library, distributed under the terms \u2503\n// \u2503 of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). \u2503\n// \u2517\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u251B\n\nimport type {\n VirtualDataSlice,\n VirtualServerHandler,\n} from \"@perspective-dev/client\";\nimport type { ColumnType } from \"@perspective-dev/client/dist/esm/ts-rs/ColumnType.d.ts\";\nimport type { ViewConfig } from \"@perspective-dev/client/dist/esm/ts-rs/ViewConfig.d.ts\";\nimport type { ViewWindow } from \"@perspective-dev/client/dist/esm/ts-rs/ViewWindow.d.ts\";\nimport type * as duckdb from \"@duckdb/duckdb-wasm\";\n\nconst NUMBER_AGGS = [\n \"sum\",\n \"count\",\n \"any_value\",\n \"arbitrary\",\n \"array_agg\",\n \"avg\",\n \"bit_and\",\n \"bit_or\",\n \"bit_xor\",\n \"bitstring_agg\",\n \"bool_and\",\n \"bool_or\",\n \"countif\",\n \"favg\",\n \"fsum\",\n \"geomean\",\n \"kahan_sum\",\n \"last\",\n \"max\",\n \"min\",\n \"product\",\n \"string_agg\",\n \"sumkahan\",\n];\n\nconst STRING_AGGS = [\n \"count\",\n \"any_value\",\n \"arbitrary\",\n \"first\",\n \"countif\",\n \"last\",\n \"string_agg\",\n];\n\nconst FILTER_OPS = [\n \"==\",\n \"!=\",\n \"LIKE\",\n \"IS DISTINCT FROM\",\n \"IS NOT DISTINCT FROM\",\n \">=\",\n \"<=\",\n \">\",\n \"<\",\n];\n\nfunction duckdbTypeToPsp(name: string): ColumnType {\n if (name === \"VARCHAR\") return \"string\";\n if (name === \"DOUBLE\" || name === \"BIGINT\" || name === \"HUGEINT\")\n return \"float\";\n if (name.startsWith(\"Decimal\")) return \"float\";\n if (name.startsWith(\"Int\")) return \"integer\";\n if (name === \"INTEGER\") return \"integer\";\n if (name === \"Utf8\") return \"string\";\n if (name === \"Date32<DAY>\") return \"date\";\n if (name === \"Float64\") return \"float\";\n if (name === \"DATE\") return \"date\";\n if (name === \"BOOLEAN\") return \"boolean\";\n if (name === \"TIMESTAMP\") return \"datetime\";\n throw new Error(`Unknown type '${name}'`);\n}\n\nfunction convertDecimalToNumber(value: any, dtypeString: string) {\n if (\n value === null ||\n value === undefined ||\n !(value instanceof Uint32Array || value instanceof Int32Array)\n ) {\n return value;\n }\n\n let bigIntValue = BigInt(0);\n for (let i = 0; i < value.length; i++) {\n bigIntValue |= BigInt(value[i]) << BigInt(i * 32);\n }\n\n const maxInt128 = BigInt(2) ** BigInt(127);\n if (bigIntValue >= maxInt128) {\n bigIntValue -= BigInt(2) ** BigInt(128);\n }\n\n const scaleMatch = dtypeString.match(/Decimal\\[\\d+e(\\d+)\\]/);\n const scale = scaleMatch ? parseInt(scaleMatch[1]) : 0;\n\n if (scale > 0) {\n return Number(bigIntValue) / Math.pow(10, scale);\n } else {\n return Number(bigIntValue);\n }\n}\n\nasync function runQuery(\n db: duckdb.AsyncDuckDBConnection,\n query: string,\n options: { columns: true },\n): Promise<{\n rows: any[];\n columns: string[];\n dtypes: string[];\n}>;\n\nasync function runQuery(\n db: duckdb.AsyncDuckDBConnection,\n query: string,\n options?: { columns: boolean },\n): Promise<any[]>;\n\nasync function runQuery(\n db: duckdb.AsyncDuckDBConnection,\n query: string,\n options: { columns?: boolean } = {},\n) {\n query = query.replace(/\\s+/g, \" \").trim();\n // console.log(\"Query:\", query);\n try {\n const result = await db.query(query);\n if (options.columns) {\n return {\n rows: result.toArray(),\n columns: result.schema.fields.map((f) => f.name),\n dtypes: result.schema.fields.map((f) => f.type.toString()),\n };\n }\n\n return result.toArray();\n } catch (error) {\n console.error(\"Query error:\", error);\n console.error(\"Query:\", query);\n throw error;\n }\n}\n\nexport class DuckDBHandler implements VirtualServerHandler {\n private db: duckdb.AsyncDuckDBConnection;\n\n constructor(db: duckdb.AsyncDuckDBConnection) {\n this.db = db;\n }\n\n getFeatures() {\n return {\n group_by: true,\n split_by: true,\n sort: true,\n expressions: true,\n filter_ops: {\n integer: FILTER_OPS,\n float: FILTER_OPS,\n string: FILTER_OPS,\n boolean: FILTER_OPS,\n date: FILTER_OPS,\n datetime: FILTER_OPS,\n },\n aggregates: {\n integer: NUMBER_AGGS,\n float: NUMBER_AGGS,\n string: STRING_AGGS,\n boolean: STRING_AGGS,\n date: STRING_AGGS,\n datetime: STRING_AGGS,\n },\n };\n }\n\n async getHostedTables() {\n const results = await runQuery(this.db, \"SHOW ALL TABLES\");\n return results.map((row) => row.toJSON().name);\n }\n\n async tableSchema(tableId: string) {\n const query = `DESCRIBE ${tableId}`;\n const results = await runQuery(this.db, query);\n const schema = {} as Record<string, ColumnType>;\n for (const result of results) {\n const res = result.toJSON();\n const colName = res.column_name;\n if (!colName.startsWith(\"__\") || !colName.endsWith(\"__\")) {\n const cleanName = colName.split(\"_\").slice(-1)[0] as string;\n schema[cleanName] = duckdbTypeToPsp(res.column_type);\n }\n }\n\n return schema;\n }\n\n async viewColumnSize(viewId: string, config: ViewConfig) {\n const query = `SELECT COUNT(*) FROM (DESCRIBE ${viewId})`;\n const results = await runQuery(this.db, query);\n const gs = config.group_by?.length || 0;\n const count = Number(Object.values(results[0].toJSON())[0]);\n return (\n count -\n (gs === 0 ? 0 : gs + (config.split_by?.length === 0 ? 1 : 0))\n );\n }\n\n async tableSize(tableId: string) {\n const query = `SELECT COUNT(*) FROM ${tableId}`;\n const results = await runQuery(this.db, query);\n return Number(results[0].toJSON()[\"count_star()\"]);\n }\n\n // async viewSchema(viewId: string, config: ViewConfig) {\n // return this.tableSchema(viewId);\n // }\n\n // async viewSize(viewId: string) {\n // return this.tableSize(viewId);\n // }\n\n async tableMakeView(tableId: string, viewId: string, config: ViewConfig) {\n const columns = config.columns || [];\n const group_by = config.group_by || [];\n const split_by = config.split_by || [];\n const aggregates = config.aggregates || {};\n const sort = config.sort || [];\n const expressions = config.expressions || {};\n const filter = config.filter || [];\n\n const colName = (col: string) => {\n const expr = expressions[col];\n return expr || `\"${col}\"`;\n };\n\n const getAggregate = (col: string) => aggregates[col] || null;\n\n const generateSelectClauses = () => {\n const clauses = [];\n if (group_by.length > 0) {\n for (const col of columns) {\n if (col !== null) {\n // TODO texodus\n const agg = getAggregate(col) || \"any_value\";\n clauses.push(`${agg}(${colName(col)}) as \"${col}\"`);\n }\n }\n\n if (split_by.length === 0) {\n for (let idx = 0; idx < group_by.length; idx++) {\n clauses.push(\n `${colName(group_by[idx])} as __ROW_PATH_${idx}__`,\n );\n }\n\n const groups = group_by.map(colName).join(\", \");\n clauses.push(`GROUPING_ID(${groups}) AS __GROUPING_ID__`);\n }\n } else if (columns.length > 0) {\n for (const col of columns) {\n if (col !== null) {\n // TODO texodus\n clauses.push(\n `${colName(col)} as \"${col.replace(/\"/g, '\"\"')}\"`,\n );\n }\n }\n }\n\n return clauses;\n };\n\n const orderByClauses = [];\n const windowClauses = [];\n const whereClauses = [];\n\n if (group_by.length > 0) {\n for (let gidx = 0; gidx < group_by.length; gidx++) {\n const groups = group_by\n .slice(0, gidx + 1)\n .map(colName)\n .join(\", \");\n if (split_by.length === 0) {\n orderByClauses.push(`GROUPING_ID(${groups}) DESC`);\n }\n\n for (const [sort_col, sort_dir] of sort) {\n if (sort_dir !== \"none\") {\n const agg = getAggregate(sort_col) || \"any_value\";\n if (gidx >= group_by.length - 1) {\n orderByClauses.push(\n `${agg}(${colName(sort_col)}) ${sort_dir}`,\n );\n } else {\n orderByClauses.push(\n `first(${agg}(${colName(sort_col)})) OVER __WINDOW_${gidx}__ ${sort_dir}`,\n );\n }\n }\n }\n\n orderByClauses.push(`__ROW_PATH_${gidx}__ ASC`);\n }\n } else {\n for (const [sort_col, sort_dir] of sort) {\n if (sort_dir) {\n orderByClauses.push(`${colName(sort_col)} ${sort_dir}`);\n }\n }\n }\n\n if (sort.length > 0 && group_by.length > 1) {\n for (let gidx = 0; gidx < group_by.length - 1; gidx++) {\n const partition = Array.from(\n { length: gidx + 1 },\n (_, i) => `__ROW_PATH_${i}__`,\n ).join(\", \");\n const sub_groups = group_by\n .slice(0, gidx + 1)\n .map(colName)\n .join(\", \");\n const groups = group_by.map(colName).join(\", \");\n windowClauses.push(\n `__WINDOW_${gidx}__ AS (PARTITION BY GROUPING_ID(${sub_groups}), ${partition} ORDER BY ${groups})`,\n );\n }\n }\n\n for (const [name, op, value] of filter) {\n if (value !== null && value !== undefined) {\n const term_lit =\n typeof value === \"string\" ? `'${value}'` : String(value);\n whereClauses.push(`${colName(name)} ${op} ${term_lit}`);\n }\n }\n\n let query;\n if (split_by.length > 0) {\n query = `SELECT * FROM ${tableId}`;\n } else {\n const selectClauses = generateSelectClauses();\n query = `SELECT ${selectClauses.join(\", \")} FROM ${tableId}`;\n }\n\n if (whereClauses.length > 0) {\n query = `${query} WHERE ${whereClauses.join(\" AND \")}`;\n }\n\n if (split_by.length > 0) {\n const groups = group_by.map(colName).join(\", \");\n const group_aliases = group_by\n .map((x, i) => `${colName(x)} AS __ROW_PATH_${i}__`)\n .join(\", \");\n const pivotOn = split_by.map((c) => `\"${c}\"`).join(\", \");\n const pivotUsing = generateSelectClauses().join(\", \");\n\n query = `\n SELECT * EXCLUDE (${groups}), ${group_aliases} FROM (\n PIVOT (${query})\n ON ${pivotOn}\n USING ${pivotUsing}\n GROUP BY ${groups}\n )\n `;\n } else if (group_by.length > 0) {\n const groups = group_by.map(colName).join(\", \");\n query = `${query} GROUP BY ROLLUP(${groups})`;\n }\n\n if (windowClauses.length > 0) {\n query = `${query} WINDOW ${windowClauses.join(\", \")}`;\n }\n\n if (orderByClauses.length > 0) {\n query = `${query} ORDER BY ${orderByClauses.join(\", \")}`;\n }\n\n query = `CREATE TABLE ${viewId} AS (${query})`;\n await runQuery(this.db, query);\n }\n\n async tableValidateExpression(tableId: string, expression: string) {\n const query = `DESCRIBE (select ${expression} from ${tableId})`;\n const results = await runQuery(this.db, query);\n return duckdbTypeToPsp(results[0].toJSON()[\"column_type\"]);\n }\n\n async viewDelete(viewId: string) {\n const query = `DROP TABLE IF EXISTS ${viewId}`;\n await runQuery(this.db, query);\n }\n\n async viewGetData(\n viewId: string,\n config: ViewConfig,\n viewport: ViewWindow,\n dataSlice: VirtualDataSlice,\n ) {\n const group_by = config.group_by || [];\n const split_by = config.split_by || [];\n const start_col = viewport.start_col;\n const end_col = viewport.end_col;\n const start_row = viewport.start_row || 0;\n const end_row = viewport.end_row;\n\n let limit = \"\";\n if (end_row !== null && end_row !== undefined) {\n limit = `LIMIT ${end_row - start_row} OFFSET ${start_row}`;\n }\n\n const schemaQuery = `DESCRIBE ${viewId}`;\n const schemaResults = await runQuery(this.db, schemaQuery);\n const columnTypes = new Map();\n for (const result of schemaResults) {\n const res = result.toJSON();\n columnTypes.set(res.column_name, res.column_type);\n }\n\n const dataColumns = Array.from(columnTypes.entries())\n .filter(([colName]) => !colName.startsWith(\"__\"))\n .slice(start_col, end_col);\n\n const groupByColsList = [];\n if (group_by.length > 0) {\n if (split_by.length === 0) {\n groupByColsList.push(\"__GROUPING_ID__\");\n }\n for (let idx = 0; idx < group_by.length; idx++) {\n groupByColsList.push(`__ROW_PATH_${idx}__`);\n }\n }\n\n const allColumns = [\n ...groupByColsList.map((col) => `\"${col}\"`),\n ...dataColumns.map(([colName]) => `\"${colName}\"`),\n ];\n\n const query = `\n SELECT ${allColumns.join(\", \")}\n FROM ${viewId} ${limit}\n `;\n\n const { rows, columns, dtypes } = await runQuery(this.db, query, {\n columns: true,\n });\n\n for (let cidx = 0; cidx < columns.length; cidx++) {\n const col = columns[cidx];\n\n if (cidx === 0 && group_by.length > 0 && split_by.length === 0) {\n continue;\n }\n\n let group_by_index = null;\n let max_grouping_id = null;\n const row_path_match = col.match(/__ROW_PATH_(\\d+)__/);\n if (row_path_match) {\n group_by_index = parseInt(row_path_match[1]);\n max_grouping_id = 2 ** (group_by.length - group_by_index) - 1;\n }\n\n const dtype = duckdbTypeToPsp(dtypes[cidx]);\n const isDecimal = dtypes[cidx].startsWith(\"Decimal\");\n const colName =\n group_by_index !== null\n ? \"__ROW_PATH__\"\n : col.replace(/_/g, \"|\");\n\n for (let ridx = 0; ridx < rows.length; ridx++) {\n const row = rows[ridx];\n const rowArray = row.toArray();\n const shouldSet =\n split_by.length > 0 ||\n max_grouping_id === null ||\n rowArray[0] < max_grouping_id;\n\n if (shouldSet) {\n let value = rowArray[cidx];\n\n if (isDecimal) {\n value = convertDecimalToNumber(value, dtypes[cidx]);\n }\n\n if (typeof value === \"bigint\") {\n value = Number(value);\n }\n\n dataSlice.setCol(\n dtype,\n colName,\n ridx,\n value,\n group_by_index,\n );\n }\n }\n }\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["NUMBER_AGGS", "STRING_AGGS", "FILTER_OPS", "duckdbTypeToPsp", "name", "convertDecimalToNumber", "value", "dtypeString", "bigIntValue", "i", "maxInt128", "scaleMatch", "scale", "runQuery", "db", "query", "options", "result", "f", "error", "DuckDBHandler", "row", "tableId", "results", "schema", "res", "colName", "cleanName", "viewId", "config", "gs", "columns", "group_by", "split_by", "aggregates", "sort", "expressions", "filter", "col", "getAggregate", "generateSelectClauses", "clauses", "agg", "idx", "groups", "orderByClauses", "windowClauses", "whereClauses", "gidx", "sort_col", "sort_dir", "partition", "_", "sub_groups", "op", "term_lit", "group_aliases", "x", "pivotOn", "c", "pivotUsing", "expression", "viewport", "dataSlice", "start_col", "end_col", "start_row", "end_row", "limit", "schemaQuery", "schemaResults", "columnTypes", "dataColumns", "groupByColsList", "rows", "dtypes", "cidx", "group_by_index", "max_grouping_id", "row_path_match", "dtype", "isDecimal", "ridx", "rowArray"]
|
|
7
|
+
}
|
|
@@ -5,7 +5,7 @@ import type * as psp from "../../../dist/wasm/perspective-js.d.ts";
|
|
|
5
5
|
* @param module
|
|
6
6
|
* @returns
|
|
7
7
|
*/
|
|
8
|
-
export declare function worker(module: Promise<typeof psp>, server_wasm: Promise<WebAssembly.Module
|
|
8
|
+
export declare function worker(module: Promise<typeof psp>, server_wasm: Promise<WebAssembly.Module> | undefined, perspective_wasm_worker: Promise<SharedWorker | ServiceWorker | Worker | MessagePort>): Promise<psp.Client>;
|
|
9
9
|
/**
|
|
10
10
|
* Create a new client connected via WebSocket to a server implemnting the
|
|
11
11
|
* Perspective Protocol.
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
export function init(): void;
|
|
4
4
|
|
|
5
5
|
export type * from "../../src/ts/ts-rs/ViewWindow.d.ts";
|
|
6
|
+
export type * from "../../src/ts/ts-rs/ColumnType.d.ts";
|
|
6
7
|
export type * from "../../src/ts/ts-rs/ColumnWindow.d.ts";
|
|
7
8
|
export type * from "../../src/ts/ts-rs/TableInitOptions.d.ts";
|
|
8
9
|
export type * from "../../src/ts/ts-rs/ViewConfigUpdate.d.ts";
|
|
@@ -10,9 +11,14 @@ export type * from "../../src/ts/ts-rs/ViewOnUpdateResp.d.ts";
|
|
|
10
11
|
export type * from "../../src/ts/ts-rs/OnUpdateOptions.d.ts";
|
|
11
12
|
export type * from "../../src/ts/ts-rs/UpdateOptions.d.ts";
|
|
12
13
|
export type * from "../../src/ts/ts-rs/DeleteOptions.d.ts";
|
|
14
|
+
export type * from "../../src/ts/ts-rs/Scalar.d.ts";
|
|
13
15
|
export type * from "../../src/ts/ts-rs/SystemInfo.d.ts";
|
|
16
|
+
export type * from "../../src/ts/ts-rs/SortDir.d.ts";
|
|
17
|
+
export type * from "../../src/ts/ts-rs/Filter.d.ts";
|
|
18
|
+
export type * from "../../src/ts/ts-rs/ViewConfig.d.ts";
|
|
14
19
|
|
|
15
20
|
import type {ColumnWindow} from "../../src/ts/ts-rs/ColumnWindow.d.ts";
|
|
21
|
+
import type {ColumnType} from "../../src/ts/ts-rs/ColumnType.d.ts";
|
|
16
22
|
import type {ViewWindow} from "../../src/ts/ts-rs/ViewWindow.d.ts";
|
|
17
23
|
import type {TableInitOptions} from "../../src/ts/ts-rs/TableInitOptions.d.ts";
|
|
18
24
|
import type {ViewConfigUpdate} from "../../src/ts/ts-rs/ViewConfigUpdate.d.ts";
|
|
@@ -63,6 +69,7 @@ import type {SystemInfo} from "../../src/ts/ts-rs/SystemInfo.d.ts";
|
|
|
63
69
|
*/
|
|
64
70
|
export class Client {
|
|
65
71
|
free(): void;
|
|
72
|
+
[Symbol.dispose](): void;
|
|
66
73
|
__getClassname(): string;
|
|
67
74
|
constructor(send_request: Function, close?: Function | null);
|
|
68
75
|
new_proxy_session(on_response: Function): ProxySession;
|
|
@@ -144,7 +151,7 @@ export class Client {
|
|
|
144
151
|
* const table = await client.table(data, { index: "Row ID" });
|
|
145
152
|
* ```
|
|
146
153
|
*/
|
|
147
|
-
table(value: string | ArrayBuffer | Record<string, unknown[]> | Record<string, unknown>[], options?: TableInitOptions | null): Promise<Table>;
|
|
154
|
+
table(value: string | ArrayBuffer | Record<string, unknown[]> | Record<string, unknown>[] | Record<string, ColumnType>, options?: TableInitOptions | null): Promise<Table>;
|
|
148
155
|
/**
|
|
149
156
|
* Terminates this [`Client`], cleaning up any [`crate::View`] handles the
|
|
150
157
|
* [`Client`] has open as well as its callbacks.
|
|
@@ -181,7 +188,7 @@ export class Client {
|
|
|
181
188
|
* const tables = await client.get_hosted_table_names();
|
|
182
189
|
* ```
|
|
183
190
|
*/
|
|
184
|
-
get_hosted_table_names(): Promise<
|
|
191
|
+
get_hosted_table_names(): Promise<string[]>;
|
|
185
192
|
/**
|
|
186
193
|
* Register a callback which is invoked whenever [`Client::table`] (on this
|
|
187
194
|
* [`Client`]) or [`Table::delete`] (on a [`Table`] belinging to this
|
|
@@ -208,8 +215,26 @@ export class Client {
|
|
|
208
215
|
*/
|
|
209
216
|
system_info(): Promise<SystemInfo>;
|
|
210
217
|
}
|
|
218
|
+
export class JsVirtualDataSlice {
|
|
219
|
+
free(): void;
|
|
220
|
+
[Symbol.dispose](): void;
|
|
221
|
+
constructor();
|
|
222
|
+
setCol(dtype: string, name: string, index: number, val: any, group_by_index?: number | null): void;
|
|
223
|
+
setStringCol(name: string, index: number, val: any, group_by_index?: number | null): void;
|
|
224
|
+
setIntegerCol(name: string, index: number, val: any, group_by_index?: number | null): void;
|
|
225
|
+
setFloatCol(name: string, index: number, val: any, group_by_index?: number | null): void;
|
|
226
|
+
setBooleanCol(name: string, index: number, val: any, group_by_index?: number | null): void;
|
|
227
|
+
setDatetimeCol(name: string, index: number, val: any, group_by_index?: number | null): void;
|
|
228
|
+
}
|
|
229
|
+
export class JsVirtualServer {
|
|
230
|
+
free(): void;
|
|
231
|
+
[Symbol.dispose](): void;
|
|
232
|
+
constructor(handler: object);
|
|
233
|
+
handleRequest(bytes: Uint8Array): Promise<any>;
|
|
234
|
+
}
|
|
211
235
|
export class ProxySession {
|
|
212
236
|
free(): void;
|
|
237
|
+
[Symbol.dispose](): void;
|
|
213
238
|
constructor(client: Client, on_response: Function);
|
|
214
239
|
handle_request(value: any): Promise<void>;
|
|
215
240
|
close(): Promise<void>;
|
|
@@ -217,6 +242,7 @@ export class ProxySession {
|
|
|
217
242
|
export class Table {
|
|
218
243
|
private constructor();
|
|
219
244
|
free(): void;
|
|
245
|
+
[Symbol.dispose](): void;
|
|
220
246
|
__getClassname(): string;
|
|
221
247
|
/**
|
|
222
248
|
* Returns the name of the index column for the table.
|
|
@@ -228,7 +254,7 @@ export class Table {
|
|
|
228
254
|
* const index = table.get_index(); // "x"
|
|
229
255
|
* ```
|
|
230
256
|
*/
|
|
231
|
-
get_index(): Promise<string
|
|
257
|
+
get_index(): Promise<string>;
|
|
232
258
|
/**
|
|
233
259
|
* Get a copy of the [`Client`] this [`Table`] came from.
|
|
234
260
|
*/
|
|
@@ -304,7 +330,7 @@ export class Table {
|
|
|
304
330
|
* Note that all [`Table`] columns are _nullable_, regardless of the data
|
|
305
331
|
* type.
|
|
306
332
|
*/
|
|
307
|
-
schema(): Promise<
|
|
333
|
+
schema(): Promise<Record<string, ColumnType>>;
|
|
308
334
|
/**
|
|
309
335
|
* Returns the column names of this [`Table`] in "natural" order (the
|
|
310
336
|
* ordering implied by the input format).
|
|
@@ -393,7 +419,7 @@ export class Table {
|
|
|
393
419
|
* await table.update("x,y\n1,2");
|
|
394
420
|
* ```
|
|
395
421
|
*/
|
|
396
|
-
update(input: string | ArrayBuffer | Record<string, unknown[]> | Record<string, unknown>[], options?: UpdateOptions | null): Promise<any>;
|
|
422
|
+
update(input: string | ArrayBuffer | Record<string, unknown[]> | Record<string, unknown>[] | Record<string, ColumnType>, options?: UpdateOptions | null): Promise<any>;
|
|
397
423
|
/**
|
|
398
424
|
* Create a new [`View`] from this table with a specified
|
|
399
425
|
* [`ViewConfigUpdate`].
|
|
@@ -435,6 +461,7 @@ export class Table {
|
|
|
435
461
|
export class View {
|
|
436
462
|
private constructor();
|
|
437
463
|
free(): void;
|
|
464
|
+
[Symbol.dispose](): void;
|
|
438
465
|
__get_model(): View;
|
|
439
466
|
/**
|
|
440
467
|
* Returns an array of strings containing the column paths of the [`View`]
|
|
@@ -677,17 +704,29 @@ export interface InitOutput {
|
|
|
677
704
|
readonly view_collapse: (a: number, b: number) => number;
|
|
678
705
|
readonly view_expand: (a: number, b: number) => number;
|
|
679
706
|
readonly view_set_depth: (a: number, b: number) => number;
|
|
707
|
+
readonly __wbg_jsvirtualdataslice_free: (a: number, b: number) => void;
|
|
708
|
+
readonly jsvirtualdataslice_new: () => number;
|
|
709
|
+
readonly jsvirtualdataslice_setCol: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number) => void;
|
|
710
|
+
readonly jsvirtualdataslice_setStringCol: (a: number, b: number, c: number, d: number, e: number, f: number, g: number) => void;
|
|
711
|
+
readonly jsvirtualdataslice_setIntegerCol: (a: number, b: number, c: number, d: number, e: number, f: number, g: number) => void;
|
|
712
|
+
readonly jsvirtualdataslice_setFloatCol: (a: number, b: number, c: number, d: number, e: number, f: number, g: number) => void;
|
|
713
|
+
readonly jsvirtualdataslice_setBooleanCol: (a: number, b: number, c: number, d: number, e: number, f: number, g: number) => void;
|
|
714
|
+
readonly jsvirtualdataslice_setDatetimeCol: (a: number, b: number, c: number, d: number, e: number, f: number, g: number) => void;
|
|
715
|
+
readonly __wbg_jsvirtualserver_free: (a: number, b: number) => void;
|
|
716
|
+
readonly jsvirtualserver_new: (a: number, b: number) => void;
|
|
717
|
+
readonly jsvirtualserver_handleRequest: (a: number, b: number, c: number) => number;
|
|
680
718
|
readonly init: () => void;
|
|
681
719
|
readonly proxysession_new: (a: number, b: number) => number;
|
|
682
|
-
readonly
|
|
683
|
-
readonly
|
|
684
|
-
readonly
|
|
685
|
-
readonly
|
|
686
|
-
readonly
|
|
720
|
+
readonly __wasm_bindgen_func_elem_3509: (a: number, b: number, c: number) => void;
|
|
721
|
+
readonly __wasm_bindgen_func_elem_3494: (a: number, b: number) => void;
|
|
722
|
+
readonly __wasm_bindgen_func_elem_553: (a: number, b: number) => number;
|
|
723
|
+
readonly __wasm_bindgen_func_elem_123: (a: number, b: number) => void;
|
|
724
|
+
readonly __wasm_bindgen_func_elem_5064: (a: number, b: number, c: number, d: number) => void;
|
|
725
|
+
readonly __wbindgen_export: (a: number, b: number) => number;
|
|
726
|
+
readonly __wbindgen_export2: (a: number, b: number, c: number, d: number) => number;
|
|
727
|
+
readonly __wbindgen_export3: (a: number) => void;
|
|
728
|
+
readonly __wbindgen_export4: (a: number, b: number, c: number) => void;
|
|
687
729
|
readonly __wbindgen_add_to_stack_pointer: (a: number) => number;
|
|
688
|
-
readonly __wbindgen_export_5: (a: number, b: number) => number;
|
|
689
|
-
readonly __wbindgen_export_6: (a: number, b: number, c: number) => void;
|
|
690
|
-
readonly __wbindgen_export_7: (a: number, b: number, c: number, d: number) => void;
|
|
691
730
|
}
|
|
692
731
|
|
|
693
732
|
export type SyncInitInput = BufferSource | WebAssembly.Module;
|