@heswell/vuu-data-engine-local 4.0.0 → 4.2.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/91.js +83 -23
- package/README.md +46 -2
- package/index.js +8 -5
- package/package.json +1 -1
- package/src/EngineDataSource.d.ts +1 -1
- package/src/Table.d.ts +25 -3
- package/src/basket/BasketModule.d.ts +1 -1
- package/src/core/module/VuuModule.d.ts +7 -6
- package/src/core/table/TableContainer.d.ts +49 -6
- package/src/index.d.ts +2 -2
- package/src/nextFrame.d.ts +1 -0
- package/src/notifications/NotificationModule.d.ts +1 -1
- package/src/session-table-utils.d.ts +1 -1
- package/src/simul/SimulModule.d.ts +1 -1
- package/src/simul/reference-data/instruments-extended.d.ts +1 -1
- package/src/simul/reference-data/instruments.d.ts +1 -1
- package/src/simul/reference-data/orders.d.ts +1 -1
- package/src/test/TestModule.d.ts +1 -1
- package/src/user-admin/UserAdminModule.d.ts +1 -1
package/91.js
CHANGED
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
import { JoinTable, Table } from "@heswell/vuu-table";
|
|
2
2
|
import { EventEmitter } from "@vuu-ui/vuu-utils";
|
|
3
|
+
const defaultRangeLimits = new WeakMap();
|
|
4
|
+
const setDefaultRangeLimits = (table, rangeLimits)=>{
|
|
5
|
+
defaultRangeLimits.set(table, rangeLimits);
|
|
6
|
+
};
|
|
3
7
|
class Table_Table extends EventEmitter {
|
|
4
8
|
engineTable;
|
|
5
9
|
#dataMap;
|
|
10
|
+
#destroyed = false;
|
|
6
11
|
#indexOfKey;
|
|
12
|
+
#listener;
|
|
7
13
|
#updateColumnName;
|
|
8
14
|
constructor(schemaOrEngineTable, data = [], dataMap, updateGenerator){
|
|
9
15
|
super();
|
|
@@ -11,12 +17,13 @@ class Table_Table extends EventEmitter {
|
|
|
11
17
|
this.#dataMap = dataMap ?? this.engineTable.columnMap;
|
|
12
18
|
this.#indexOfKey = this.engineTable.indexOfKeyField;
|
|
13
19
|
for (const row of data)this.engineTable.insert(row);
|
|
14
|
-
this
|
|
20
|
+
this.#listener = {
|
|
15
21
|
onInsert: (_rowIdx, row)=>this.emit("insert", row),
|
|
16
22
|
onUpdate: (_rowIdx, row)=>this.emit("update", row, this.#updateColumnName),
|
|
17
23
|
onDelete: (_rowIdx, row)=>this.emit("delete", String(row[this.#indexOfKey])),
|
|
18
24
|
onClear: ()=>void 0
|
|
19
|
-
}
|
|
25
|
+
};
|
|
26
|
+
this.engineTable.addListener(this.#listener);
|
|
20
27
|
updateGenerator?.setTable(this);
|
|
21
28
|
updateGenerator?.setRange({
|
|
22
29
|
from: 0,
|
|
@@ -32,6 +39,18 @@ class Table_Table extends EventEmitter {
|
|
|
32
39
|
get schema() {
|
|
33
40
|
return this.engineTable.schema;
|
|
34
41
|
}
|
|
42
|
+
get rangeLimits() {
|
|
43
|
+
return this.schema.rangeLimits ?? defaultRangeLimits.get(this);
|
|
44
|
+
}
|
|
45
|
+
get destroyed() {
|
|
46
|
+
return this.#destroyed;
|
|
47
|
+
}
|
|
48
|
+
destroy() {
|
|
49
|
+
if (this.#destroyed) return;
|
|
50
|
+
this.#destroyed = true;
|
|
51
|
+
this.engineTable.removeListener(this.#listener);
|
|
52
|
+
if (this.engineTable instanceof JoinTable) this.engineTable.destroy();
|
|
53
|
+
}
|
|
35
54
|
get name() {
|
|
36
55
|
return this.engineTable.name;
|
|
37
56
|
}
|
|
@@ -85,49 +104,88 @@ const DEFAULT_RANGE_LIMITS = {
|
|
|
85
104
|
};
|
|
86
105
|
const tableKey = ({ module, table })=>`${module}:${table}`;
|
|
87
106
|
const createTable = (schema, data = [], dataMap = buildDataColumnMapFromSchema(schema), updateGenerator)=>new Table_Table(schema, data, dataMap, updateGenerator);
|
|
88
|
-
const createJoinTable = (joinTable, table1, table2, joinColumn,
|
|
89
|
-
const { schema
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
...schema1.columns,
|
|
93
|
-
...schema2.columns
|
|
94
|
-
].map((col)=>col.name).sort());
|
|
95
|
-
const combinedSchema = {
|
|
96
|
-
key: schema1.key,
|
|
97
|
-
table: joinTable,
|
|
98
|
-
rangeLimits: DEFAULT_RANGE_LIMITS,
|
|
99
|
-
columns: Array.from(combinedColumns).map((columnName)=>({
|
|
100
|
-
name: columnName,
|
|
101
|
-
serverDataType: getServerDataType(columnName, schema1, schema2)
|
|
102
|
-
}))
|
|
103
|
-
};
|
|
107
|
+
const createJoinTable = (joinTable, table1, table2, joinColumn, joinTypeOrOptions = "inner")=>{
|
|
108
|
+
const { joinType = "inner", columns, schema } = "string" == typeof joinTypeOrOptions ? {
|
|
109
|
+
joinType: joinTypeOrOptions
|
|
110
|
+
} : joinTypeOrOptions;
|
|
104
111
|
const engineJoinTable = new JoinTable({
|
|
105
|
-
schema:
|
|
112
|
+
schema: buildJoinSchema(joinTable, table1.schema, table2.schema, {
|
|
113
|
+
columns,
|
|
114
|
+
schema
|
|
115
|
+
}),
|
|
106
116
|
baseTable: table1.engineTable,
|
|
107
117
|
joinTable: table2.engineTable,
|
|
108
118
|
leftColumn: joinColumn,
|
|
109
119
|
rightColumn: joinColumn,
|
|
110
120
|
joinType
|
|
111
121
|
});
|
|
112
|
-
|
|
122
|
+
const table = new Table_Table(engineJoinTable);
|
|
123
|
+
setDefaultRangeLimits(table, DEFAULT_RANGE_LIMITS);
|
|
124
|
+
return table;
|
|
125
|
+
};
|
|
126
|
+
const buildJoinSchema = (joinTable, schema1, schema2, { columns, schema })=>{
|
|
127
|
+
const name = `${joinTable.module}:${joinTable.table}`;
|
|
128
|
+
const fail = (message)=>{
|
|
129
|
+
throw Error(`[createJoinTable] ${name}: ${message}`);
|
|
130
|
+
};
|
|
131
|
+
if (columns && schema) fail("pass either columns or schema, not both");
|
|
132
|
+
if (schema) {
|
|
133
|
+
const { module, table } = schema.table;
|
|
134
|
+
if (module !== joinTable.module || table !== joinTable.table) fail(`schema is for table ${module}:${table}`);
|
|
135
|
+
if (schema.key !== schema1.key) fail(`schema key ${schema.key} must be the key of ${schema1.table.table} (${schema1.key})`);
|
|
136
|
+
}
|
|
137
|
+
const sourceColumns = new Set([
|
|
138
|
+
...schema1.columns,
|
|
139
|
+
...schema2.columns
|
|
140
|
+
].map((col)=>col.name));
|
|
141
|
+
const columnNames = schema?.columns.map((col)=>col.name) ?? columns ?? Array.from(sourceColumns).sort();
|
|
142
|
+
const seen = new Set();
|
|
143
|
+
for (const columnName of columnNames){
|
|
144
|
+
if (!sourceColumns.has(columnName)) fail(`unknown column ${columnName}, not in ${schema1.table.table} or ${schema2.table.table}`);
|
|
145
|
+
if (seen.has(columnName)) fail(`duplicate column ${columnName}`);
|
|
146
|
+
seen.add(columnName);
|
|
147
|
+
}
|
|
148
|
+
if (!seen.has(schema1.key)) fail(`columns must include the key column ${schema1.key}`);
|
|
149
|
+
const joinColumns = columnNames.map((columnName)=>({
|
|
150
|
+
name: columnName,
|
|
151
|
+
serverDataType: getServerDataType(columnName, schema1, schema2)
|
|
152
|
+
}));
|
|
153
|
+
if (schema) {
|
|
154
|
+
schema.columns.forEach(({ name: columnName, serverDataType }, i)=>{
|
|
155
|
+
if (serverDataType !== joinColumns[i].serverDataType) fail(`column ${columnName} is declared ${serverDataType} but is ${joinColumns[i].serverDataType} in the source table`);
|
|
156
|
+
});
|
|
157
|
+
return schema;
|
|
158
|
+
}
|
|
159
|
+
return {
|
|
160
|
+
key: schema1.key,
|
|
161
|
+
table: joinTable,
|
|
162
|
+
rangeLimits: DEFAULT_RANGE_LIMITS,
|
|
163
|
+
columns: joinColumns
|
|
164
|
+
};
|
|
113
165
|
};
|
|
114
166
|
class TableContainer {
|
|
115
167
|
#tables = new Map();
|
|
168
|
+
#created = new Set();
|
|
116
169
|
createTable = (schema, data = [], dataMap = buildDataColumnMapFromSchema(schema), updateGenerator)=>{
|
|
117
170
|
const table = createTable(schema, data, dataMap, updateGenerator);
|
|
118
171
|
this.addTable(table);
|
|
172
|
+
this.#created.add(table);
|
|
119
173
|
return table;
|
|
120
174
|
};
|
|
121
|
-
createJoinTable(joinTable, table1, table2, joinColumn,
|
|
122
|
-
const newTable = createJoinTable(joinTable, this.getTable(table1), this.getTable(table2), joinColumn,
|
|
175
|
+
createJoinTable(joinTable, table1, table2, joinColumn, joinTypeOrOptions = "inner") {
|
|
176
|
+
const newTable = createJoinTable(joinTable, this.getTable(table1), this.getTable(table2), joinColumn, joinTypeOrOptions);
|
|
123
177
|
this.addTable(newTable);
|
|
178
|
+
this.#created.add(newTable);
|
|
124
179
|
return newTable;
|
|
125
180
|
}
|
|
126
181
|
addTable(table, as = table.schema.table) {
|
|
127
182
|
this.#tables.set(tableKey(as), table);
|
|
128
183
|
}
|
|
129
184
|
removeTable(table) {
|
|
130
|
-
|
|
185
|
+
const key = tableKey(table);
|
|
186
|
+
const found = this.#tables.get(key);
|
|
187
|
+
if (found) this.#created.delete(found);
|
|
188
|
+
return this.#tables.delete(key);
|
|
131
189
|
}
|
|
132
190
|
hasTable(table) {
|
|
133
191
|
return this.#tables.has(tableKey(table));
|
|
@@ -147,6 +205,8 @@ class TableContainer {
|
|
|
147
205
|
return Array.from(this.#tables.values());
|
|
148
206
|
}
|
|
149
207
|
clear() {
|
|
208
|
+
for (const table of this.#created)table.destroy();
|
|
209
|
+
this.#created.clear();
|
|
150
210
|
this.#tables.clear();
|
|
151
211
|
}
|
|
152
212
|
}
|
package/README.md
CHANGED
|
@@ -33,8 +33,9 @@ a second set of React contexts). They are `@vuu-ui/vuu-utils` and `@vuu-ui/vuu-f
|
|
|
33
33
|
## Usage
|
|
34
34
|
|
|
35
35
|
Importing the package has no side effects: no modules, tables or timers are created
|
|
36
|
-
until you ask for them. The main entry needs no DOM, so it runs in plain Node or Bun
|
|
37
|
-
|
|
36
|
+
until you ask for them. The main entry needs no DOM, so it runs in plain Node or Bun with
|
|
37
|
+
no shims: it uses `requestAnimationFrame` when present and falls back to `setTimeout`
|
|
38
|
+
otherwise. The React bindings (`createDataSourceProvider`, `createLocalVuuServer`,
|
|
38
39
|
`LocalDataSourceProvider`) are in `@heswell/vuu-data-engine-local/react`, because
|
|
39
40
|
`@vuu-ui/core` needs a DOM (`ResizeObserver`) at import time.
|
|
40
41
|
|
|
@@ -151,6 +152,49 @@ changes. Pass `"leftOuter"` to keep every `table1` row. For a row with no match,
|
|
|
151
152
|
Sort places nulls first when ascending; relational filters (`<`, `>=`, …) never match
|
|
152
153
|
null; and aggregations skip nulls.
|
|
153
154
|
|
|
155
|
+
By default the join table has every column of both tables, in alphabetical order. To
|
|
156
|
+
control the columns, pass an options object as the fifth argument instead of a join type:
|
|
157
|
+
|
|
158
|
+
```ts
|
|
159
|
+
// an ordered list of column names, possibly a subset (must include table1's key)
|
|
160
|
+
createJoinTable(joinTable, instruments, prices, "ric", {
|
|
161
|
+
joinType: "leftOuter",
|
|
162
|
+
columns: ["ric", "exchange", "bid", "ask"],
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
// or a declared TableSchema for the join table, e.g. the schema vuu-server returns
|
|
166
|
+
createJoinTable(instrumentPricesSchema.table, instruments, prices, "ric", {
|
|
167
|
+
joinType: "leftOuter",
|
|
168
|
+
schema: instrumentPricesSchema,
|
|
169
|
+
});
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
`columns` and `schema` are mutually exclusive, and `joinType` still defaults to `"inner"`.
|
|
173
|
+
Column types come from the source tables; a column in both tables takes its value from
|
|
174
|
+
`table1`. Unknown or duplicate columns, a missing key column, a declared `serverDataType`
|
|
175
|
+
that differs from the source column, or a `schema` whose `table` or `key` does not match
|
|
176
|
+
(`joinTable`, `table1`'s key) throw an error naming the join table and the problem.
|
|
177
|
+
|
|
178
|
+
With `schema`, the join's `Table.schema` is exactly the declared schema (no keys added), so
|
|
179
|
+
it matches `getTableSchema` / TABLE_META_RESP and can be published as a module's
|
|
180
|
+
`schemas`. If the declared schema has no `rangeLimits`, the engine default
|
|
181
|
+
(`maxRangeEnd: 1_000_000`, `maxRangeWidth: 1_000`) still applies, exposed as
|
|
182
|
+
`table.rangeLimits` rather than added to the schema. Joins created without `schema`
|
|
183
|
+
(default or `columns`) generate a schema that includes those default `rangeLimits`.
|
|
184
|
+
|
|
185
|
+
`createJoinTable` returns a `JoinTableHandle` (`Table<JoinTable>`), whose `engineTable` is
|
|
186
|
+
typed as the `@heswell/vuu-table` `JoinTable`. Call `table.destroy()` to detach a join from
|
|
187
|
+
its source tables, after which source changes no longer propagate to it. `destroy()` is
|
|
188
|
+
available on every `Table` and is safe to call more than once. You rarely need to call it
|
|
189
|
+
yourself:
|
|
190
|
+
|
|
191
|
+
- `module.dispose()` (called by `engine.dispose()` for modules the engine owns) destroys the
|
|
192
|
+
join tables the module publishes.
|
|
193
|
+
- `tableContainer.clear()` (also called by `engine.dispose()`) destroys tables created by
|
|
194
|
+
that container's `createTable` / `createJoinTable`.
|
|
195
|
+
- `engine.unregister()` and `tableContainer.removeTable()` do not destroy tables, as they
|
|
196
|
+
may still be in use.
|
|
197
|
+
|
|
154
198
|
### Ranges
|
|
155
199
|
|
|
156
200
|
`subscribe({ range })`, `dataSource.range = …` and `setRange` accept a vuu-utils `Range` or
|
package/index.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { JoinTable } from "@heswell/vuu-table";
|
|
1
2
|
import { Clock, EventEmitter, NULL_RANGE, Range, StaleUpdateError, assertExpectedSessionTable, filterAsQuery, isAddRowRpcRequest, isBeginEditSessionRpcRequest, isConfigChanged, isCreateSessionTableRpcRequest, isDeleteSelectedRowsRpcRequest, isEditCellRpcRequest, isEndEditSessionRpcRequest, isRpcSuccess, isTypeaheadRequest, isUndoRowChangeRpcRequest, metadataKeys, sessionDataSourceConfig, toSchemaColumn, uuid, vanillaConfig, withConfigDefaults } from "@vuu-ui/vuu-utils";
|
|
2
3
|
import { inMemoryDataEngine } from "@heswell/vuu-viewport";
|
|
3
4
|
import { parseFilter } from "@vuu-ui/vuu-filter-parser";
|
|
@@ -147,12 +148,12 @@ class RowKeys {
|
|
|
147
148
|
return key;
|
|
148
149
|
}
|
|
149
150
|
}
|
|
150
|
-
const toRange = (range)=>"function" == typeof range.equals && void 0 !== range.withBuffer ? range : Range(range.from, range.to);
|
|
151
|
-
const { KEY: KEY } = metadataKeys;
|
|
152
151
|
const nextFrame = (callback)=>{
|
|
153
|
-
if ("function" == typeof globalThis.requestAnimationFrame) globalThis.requestAnimationFrame(callback);
|
|
152
|
+
if ("function" == typeof globalThis.requestAnimationFrame) globalThis.requestAnimationFrame(()=>callback());
|
|
154
153
|
else globalThis.setTimeout(callback, 0);
|
|
155
154
|
};
|
|
155
|
+
const toRange = (range)=>"function" == typeof range.equals && void 0 !== range.withBuffer ? range : Range(range.from, range.to);
|
|
156
|
+
const { KEY: KEY } = metadataKeys;
|
|
156
157
|
const buildTableSchema = (columns, keyColumn)=>({
|
|
157
158
|
columns: columns.map(toSchemaColumn),
|
|
158
159
|
key: keyColumn ?? columns[0].name,
|
|
@@ -362,7 +363,8 @@ class EngineDataSource extends EventEmitter {
|
|
|
362
363
|
this.clientCallback = callback;
|
|
363
364
|
this.viewport = viewport;
|
|
364
365
|
this.#status = "subscribed";
|
|
365
|
-
|
|
366
|
+
const rangeLimits = this.#table.rangeLimits;
|
|
367
|
+
if (rangeLimits) this.#maxRangeEnd = rangeLimits.maxRangeEnd;
|
|
366
368
|
let config = this._config;
|
|
367
369
|
const hasConfigProps = aggregations || columns || filterSpec || groupBy || sort;
|
|
368
370
|
if (hasConfigProps) config = {
|
|
@@ -1160,6 +1162,7 @@ class VuuModule {
|
|
|
1160
1162
|
if (this.#engine === engine) this.#engine = void 0;
|
|
1161
1163
|
}
|
|
1162
1164
|
dispose() {
|
|
1165
|
+
for (const table of Object.values(this.tables))if (table.engineTable instanceof JoinTable) table.destroy();
|
|
1163
1166
|
this.#sessionTableMap = {};
|
|
1164
1167
|
this.#sessionSourceTableMap = {};
|
|
1165
1168
|
this.#sessionSnapshots.clear();
|
|
@@ -1228,7 +1231,7 @@ class VuuModule {
|
|
|
1228
1231
|
handlePostSubscribeActivities = ({ clientViewportId, tableSchema })=>{
|
|
1229
1232
|
const visualLinks = this.getVisualLinks(tableSchema.table.table);
|
|
1230
1233
|
const { dataSource } = this.getSubscriptionByViewport(clientViewportId);
|
|
1231
|
-
|
|
1234
|
+
nextFrame(()=>{
|
|
1232
1235
|
dataSource.links = visualLinks;
|
|
1233
1236
|
});
|
|
1234
1237
|
if (this.visualLinks && dataSource.tableSchema) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@heswell/vuu-data-engine-local",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.2.0",
|
|
4
4
|
"description": "In-browser Vuu server (VuuModule, tables, EngineDataSource) built on @heswell/vuu-table and @heswell/vuu-viewport",
|
|
5
5
|
"main": "./index.js",
|
|
6
6
|
"module": "./index.js",
|
|
@@ -95,7 +95,7 @@ export declare class EngineDataSource extends EventEmitter<DataSourceEvents> imp
|
|
|
95
95
|
get size(): number;
|
|
96
96
|
get table(): import("@vuu-ui/vuu-data-types").TableSchemaTable;
|
|
97
97
|
/** The table backing this dataSource */
|
|
98
|
-
get dataTable(): Table
|
|
98
|
+
get dataTable(): Table<import("@heswell/vuu-table").Table>;
|
|
99
99
|
get columnMap(): ColumnMap;
|
|
100
100
|
/**
|
|
101
101
|
* Flat (ungrouped) rows can be resolved at any index. Grouped rows are
|
package/src/Table.d.ts
CHANGED
|
@@ -4,6 +4,12 @@ import type { VuuRowDataItemType } from "@vuu-ui/vuu-protocol-types";
|
|
|
4
4
|
import { type ColumnMap, EventEmitter } from "@vuu-ui/vuu-utils";
|
|
5
5
|
import type { UpdateGenerator } from "./rowUpdates";
|
|
6
6
|
export type TableRow = Array<VuuRowDataItemType | bigint>;
|
|
7
|
+
export type RangeLimits = NonNullable<TableSchema["rangeLimits"]>;
|
|
8
|
+
/**
|
|
9
|
+
* @internal Range limits applied when the table's schema declares none,
|
|
10
|
+
* without adding them to the (exposed) schema.
|
|
11
|
+
*/
|
|
12
|
+
export declare const setDefaultRangeLimits: (table: Table<EngineTable>, rangeLimits: RangeLimits) => void;
|
|
7
13
|
export type TableEvents = {
|
|
8
14
|
delete: (key: string) => void;
|
|
9
15
|
insert: (row: TableRow) => void;
|
|
@@ -17,14 +23,30 @@ export type TableEvents = {
|
|
|
17
23
|
*
|
|
18
24
|
* Events are emitted from engine table listeners, so changes applied
|
|
19
25
|
* directly to the engine table (e.g. by a JoinTable) are also observed.
|
|
26
|
+
*
|
|
27
|
+
* `E` is the type of the engine table, `JoinTable` for tables created by
|
|
28
|
+
* `createJoinTable` (see `JoinTableHandle`).
|
|
20
29
|
*/
|
|
21
|
-
export declare class Table extends EventEmitter<TableEvents> {
|
|
30
|
+
export declare class Table<E extends EngineTable = EngineTable> extends EventEmitter<TableEvents> {
|
|
22
31
|
#private;
|
|
23
|
-
readonly engineTable:
|
|
24
|
-
constructor(schemaOrEngineTable: TableSchema |
|
|
32
|
+
readonly engineTable: E;
|
|
33
|
+
constructor(schemaOrEngineTable: TableSchema | E, data?: TableRow[], dataMap?: ColumnMap, updateGenerator?: UpdateGenerator);
|
|
25
34
|
get data(): TableRow[];
|
|
26
35
|
get map(): ColumnMap;
|
|
27
36
|
get schema(): TableSchema;
|
|
37
|
+
/**
|
|
38
|
+
* The range limits in effect: those of the schema if it declares any,
|
|
39
|
+
* otherwise any engine default (applied to join tables), else undefined
|
|
40
|
+
* (unlimited). Never added to `schema`.
|
|
41
|
+
*/
|
|
42
|
+
get rangeLimits(): RangeLimits | undefined;
|
|
43
|
+
get destroyed(): boolean;
|
|
44
|
+
/**
|
|
45
|
+
* Release the table. For a join table this detaches the join from its
|
|
46
|
+
* source tables, so source changes no longer propagate. This table stops
|
|
47
|
+
* emitting events. Safe to call on any table, and more than once.
|
|
48
|
+
*/
|
|
49
|
+
destroy(): void;
|
|
28
50
|
get name(): string;
|
|
29
51
|
get rowCount(): number;
|
|
30
52
|
delete(key: string): void;
|
|
@@ -43,7 +43,7 @@ export declare class BasketModule extends VuuModule<BasketsTableName> {
|
|
|
43
43
|
priceStrategyType: undefined;
|
|
44
44
|
};
|
|
45
45
|
get menuServices(): Record<BasketsTableName, RpcMenuService[] | undefined> | undefined;
|
|
46
|
-
get tables(): Record<BasketsTableName, Table
|
|
46
|
+
get tables(): Record<BasketsTableName, Table<import("@heswell/vuu-table").Table>>;
|
|
47
47
|
get visualLinks(): {
|
|
48
48
|
basketConstituent: {
|
|
49
49
|
fromColumn: string;
|
|
@@ -55,8 +55,9 @@ export declare abstract class VuuModule<T extends string = string> implements IV
|
|
|
55
55
|
detachEngine(engine: LocalEngine): void;
|
|
56
56
|
/**
|
|
57
57
|
* Release resources (timers, providers). Called by `LocalEngine.dispose`
|
|
58
|
-
* for modules it owns.
|
|
59
|
-
*
|
|
58
|
+
* for modules it owns. Join tables published by the module are destroyed,
|
|
59
|
+
* detaching them from their source tables. Subclasses that start timers
|
|
60
|
+
* should override, calling super.dispose().
|
|
60
61
|
*/
|
|
61
62
|
dispose(): void;
|
|
62
63
|
protected abstract menus?: Record<T, VuuMenu | undefined> | undefined;
|
|
@@ -174,9 +175,9 @@ export declare abstract class VuuModule<T extends string = string> implements IV
|
|
|
174
175
|
private addRow;
|
|
175
176
|
private endEditSession;
|
|
176
177
|
private applyBulkEdits;
|
|
177
|
-
protected createSessionTable(sourceTable: Table, sessionTableName: string, editSessionMode: EditSessionMode | CopyOption, dataSource: ModuleDataSource, sessionType?: SessionType): Table
|
|
178
|
-
protected createSessionTableWithAllRows({ data, schema }: Table, _sessionTableName: string): Table
|
|
179
|
-
protected createEmptySessionTable({ schema }: Table, sessionTableName: string, sessionType?: SessionType): Table
|
|
180
|
-
protected createSessionTableFromSelectedRows({ data, map, schema }: Table, sessionTableName: string, dataSource: ModuleDataSource): Table
|
|
178
|
+
protected createSessionTable(sourceTable: Table, sessionTableName: string, editSessionMode: EditSessionMode | CopyOption, dataSource: ModuleDataSource, sessionType?: SessionType): Table<import("@heswell/vuu-table").Table>;
|
|
179
|
+
protected createSessionTableWithAllRows({ data, schema }: Table, _sessionTableName: string): Table<import("@heswell/vuu-table").Table>;
|
|
180
|
+
protected createEmptySessionTable({ schema }: Table, sessionTableName: string, sessionType?: SessionType): Table<import("@heswell/vuu-table").Table>;
|
|
181
|
+
protected createSessionTableFromSelectedRows({ data, map, schema }: Table, sessionTableName: string, dataSource: ModuleDataSource): Table<import("@heswell/vuu-table").Table>;
|
|
181
182
|
}
|
|
182
183
|
export {};
|
|
@@ -1,39 +1,77 @@
|
|
|
1
|
-
import { type JoinType } from "@heswell/vuu-table";
|
|
1
|
+
import { JoinTable, type JoinType } from "@heswell/vuu-table";
|
|
2
2
|
import type { TableSchema } from "@vuu-ui/vuu-data-types";
|
|
3
3
|
import { Table } from "../../Table";
|
|
4
4
|
import type { VuuRowDataItemType, VuuTable } from "@vuu-ui/vuu-protocol-types";
|
|
5
5
|
import type { ColumnMap } from "@vuu-ui/vuu-utils";
|
|
6
6
|
import type { UpdateGenerator } from "../../rowUpdates";
|
|
7
|
+
/**
|
|
8
|
+
* A Table backed by an engine `JoinTable`, as returned by `createJoinTable`.
|
|
9
|
+
* `destroy()` detaches the join from its source tables.
|
|
10
|
+
*/
|
|
11
|
+
export type JoinTableHandle = Table<JoinTable>;
|
|
7
12
|
/**
|
|
8
13
|
* Create a table. The table is not registered anywhere; it belongs to
|
|
9
14
|
* whichever VuuModule returns it from `tables`.
|
|
10
15
|
*/
|
|
11
|
-
export declare const createTable: (schema: TableSchema, data?: Array<Array<VuuRowDataItemType | bigint>>, dataMap?: ColumnMap, updateGenerator?: UpdateGenerator) => Table
|
|
16
|
+
export declare const createTable: (schema: TableSchema, data?: Array<Array<VuuRowDataItemType | bigint>>, dataMap?: ColumnMap, updateGenerator?: UpdateGenerator) => Table<import("@heswell/vuu-table").Table>;
|
|
17
|
+
export interface CreateJoinTableOptions {
|
|
18
|
+
/** Defaults to "inner". */
|
|
19
|
+
joinType?: JoinType;
|
|
20
|
+
/**
|
|
21
|
+
* Ordered column names of the join table, possibly a subset of the columns
|
|
22
|
+
* of the two source tables. Must include the key column of table1. Types
|
|
23
|
+
* are taken from the source tables. Defaults to every column of both
|
|
24
|
+
* tables, in alphabetical order.
|
|
25
|
+
*/
|
|
26
|
+
columns?: readonly string[];
|
|
27
|
+
/**
|
|
28
|
+
* Declared schema of the join table, e.g. the schema a Vuu server would
|
|
29
|
+
* return in TABLE_META_RESP. Its column order is preserved; every column
|
|
30
|
+
* must exist in one of the source tables, with the same serverDataType, and
|
|
31
|
+
* its key must be the key of table1. Cannot be combined with `columns`.
|
|
32
|
+
* The join's `schema` is exactly this schema; if it declares no
|
|
33
|
+
* `rangeLimits`, the engine default limits are applied without being added
|
|
34
|
+
* to the schema.
|
|
35
|
+
*/
|
|
36
|
+
schema?: TableSchema;
|
|
37
|
+
}
|
|
12
38
|
/**
|
|
13
39
|
* Create a materialized join of two tables, backed by an engine JoinTable,
|
|
14
40
|
* maintained incrementally as either source changes. `joinType` defaults to
|
|
15
41
|
* "inner" (only rows with a match in table2). With "leftOuter" every table1
|
|
16
42
|
* row is present and unmatched table2 columns are null, as in vuu-server.
|
|
43
|
+
*
|
|
44
|
+
* The fifth argument is either a JoinType or a CreateJoinTableOptions, which
|
|
45
|
+
* can also control the columns (and their order) of the join table. Where a
|
|
46
|
+
* column exists in both tables, the value comes from table1.
|
|
47
|
+
*
|
|
48
|
+
* Call `destroy()` on the returned table to detach it from its source tables.
|
|
49
|
+
* Tables published by a module are destroyed when the module is disposed.
|
|
17
50
|
*/
|
|
18
|
-
export declare const createJoinTable: (joinTable: VuuTable, table1: Table, table2: Table, joinColumn: string,
|
|
51
|
+
export declare const createJoinTable: (joinTable: VuuTable, table1: Table, table2: Table, joinColumn: string, joinTypeOrOptions?: JoinType | CreateJoinTableOptions) => JoinTableHandle;
|
|
19
52
|
/**
|
|
20
53
|
* Tables, keyed by `{module, table}`. Each LocalEngine owns one, populated
|
|
21
54
|
* from the tables of its registered modules. Tables created through
|
|
22
|
-
* `createTable` / `createJoinTable` are added to this container
|
|
55
|
+
* `createTable` / `createJoinTable` are added to this container, and are
|
|
56
|
+
* destroyed by `clear()`.
|
|
23
57
|
*/
|
|
24
58
|
export declare class TableContainer {
|
|
25
59
|
#private;
|
|
26
|
-
createTable: (schema: TableSchema, data?: Array<Array<VuuRowDataItemType | bigint>>, dataMap?: ColumnMap, updateGenerator?: UpdateGenerator) => Table
|
|
60
|
+
createTable: (schema: TableSchema, data?: Array<Array<VuuRowDataItemType | bigint>>, dataMap?: ColumnMap, updateGenerator?: UpdateGenerator) => Table<import("@heswell/vuu-table").Table>;
|
|
27
61
|
/**
|
|
28
62
|
* Create a join of two tables already in this container. Pass full
|
|
29
63
|
* `{module, table}` references; a bare name is accepted only if unique.
|
|
30
64
|
*/
|
|
31
|
-
createJoinTable(joinTable: VuuTable, table1: VuuTable | string, table2: VuuTable | string, joinColumn: string,
|
|
65
|
+
createJoinTable(joinTable: VuuTable, table1: VuuTable | string, table2: VuuTable | string, joinColumn: string, joinTypeOrOptions?: JoinType | CreateJoinTableOptions): JoinTableHandle;
|
|
32
66
|
/**
|
|
33
67
|
* Add a table, keyed by `as` if given, otherwise by its schema's
|
|
34
68
|
* `{module, table}`.
|
|
35
69
|
*/
|
|
36
70
|
addTable(table: Table, as?: VuuTable): void;
|
|
71
|
+
/**
|
|
72
|
+
* Remove a table from the container. The table is not destroyed, it may
|
|
73
|
+
* still be in use elsewhere; call its `destroy()` if not.
|
|
74
|
+
*/
|
|
37
75
|
removeTable(table: VuuTable): boolean;
|
|
38
76
|
hasTable(table: VuuTable): boolean;
|
|
39
77
|
/**
|
|
@@ -44,5 +82,10 @@ export declare class TableContainer {
|
|
|
44
82
|
getTable(table: VuuTable | string): Table;
|
|
45
83
|
getTable<T>(table: VuuTable | string): T;
|
|
46
84
|
get tables(): Table[];
|
|
85
|
+
/**
|
|
86
|
+
* Remove every table, destroying those created by this container's
|
|
87
|
+
* `createTable` / `createJoinTable` (detaching join tables from their
|
|
88
|
+
* sources). Tables added with `addTable` are not destroyed.
|
|
89
|
+
*/
|
|
47
90
|
clear(): void;
|
|
48
91
|
}
|
package/src/index.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ export * from "./core/module/VuuModule";
|
|
|
4
4
|
export * from "./core/module/edit-hooks";
|
|
5
5
|
export { type AnyVuuModule, createLocalEngine, ensureVuuModule, getDefaultEngine, LocalEngine, type LocalEngineOptions, resetDefaultEngine, } from "./core/engine/LocalEngine";
|
|
6
6
|
export * from "./core/user/CurrentUser";
|
|
7
|
-
export { createJoinTable, createTable, TableContainer, } from "./core/table/TableContainer";
|
|
7
|
+
export { type CreateJoinTableOptions, createJoinTable, createTable, type JoinTableHandle, TableContainer, } from "./core/table/TableContainer";
|
|
8
8
|
export { tableContainer } from "./core/table/defaultTableContainer";
|
|
9
9
|
export { registerDemoModules, type DemoModules } from "./demo-modules";
|
|
10
10
|
export { BaseUpdateGenerator } from "./UpdateGenerator";
|
|
@@ -15,7 +15,7 @@ export * from "./simul";
|
|
|
15
15
|
export * from "./basket";
|
|
16
16
|
export * from "./module-admin";
|
|
17
17
|
export * from "./user-admin";
|
|
18
|
-
export { buildDataColumnMap, buildDataColumnMapFromSchema, Table, type TableEvents, } from "./Table";
|
|
18
|
+
export { buildDataColumnMap, buildDataColumnMapFromSchema, type RangeLimits, Table, type TableEvents, } from "./Table";
|
|
19
19
|
export * from "./test";
|
|
20
20
|
export * from "./EngineDataSource";
|
|
21
21
|
export * from "./ModuleDataSource";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const nextFrame: (callback: () => void) => void;
|
|
@@ -35,6 +35,6 @@ export declare class NotificationModule extends VuuModule<NotificationsTableName
|
|
|
35
35
|
get menuServices(): undefined;
|
|
36
36
|
get schemas(): Record<"notifications", TableSchema>;
|
|
37
37
|
get services(): Record<"notifications", RpcService[]>;
|
|
38
|
-
get tables(): Record<"notifications", Table
|
|
38
|
+
get tables(): Record<"notifications", Table<import("@heswell/vuu-table").Table>>;
|
|
39
39
|
get visualLinks(): undefined;
|
|
40
40
|
}
|
|
@@ -2,5 +2,5 @@ import type { VuuRowDataItemType } from "@vuu-ui/vuu-protocol-types";
|
|
|
2
2
|
import { Table } from "./Table";
|
|
3
3
|
import type { TableSchema } from "@vuu-ui/vuu-data-types";
|
|
4
4
|
export declare const sessionTableRow: (row: Array<bigint | VuuRowDataItemType>, schema: TableSchema) => (bigint | VuuRowDataItemType)[];
|
|
5
|
-
export declare const createSessionTableFromSelectedRows: (table: Table, selectedRowIds: string[]) => Table
|
|
5
|
+
export declare const createSessionTableFromSelectedRows: (table: Table, selectedRowIds: string[]) => Table<import("@heswell/vuu-table").Table>;
|
|
6
6
|
export declare const sessionTableSchema: (schema: TableSchema) => TableSchema;
|
|
@@ -24,7 +24,7 @@ export declare class SimulModule extends VuuModule<SimulTableName> {
|
|
|
24
24
|
get editServices(): undefined;
|
|
25
25
|
get menuServices(): Record<SimulTableName, RpcMenuService[] | undefined> | undefined;
|
|
26
26
|
get services(): Record<SimulTableName, RpcService[] | undefined> | undefined;
|
|
27
|
-
get tables(): Record<SimulTableName, Table
|
|
27
|
+
get tables(): Record<SimulTableName, Table<import("@heswell/vuu-table").Table>>;
|
|
28
28
|
get visualLinks(): Record<SimulTableName, VuuLink[] | undefined>;
|
|
29
29
|
cancelOrder: MenuServiceHandler;
|
|
30
30
|
startOrders: ServiceHandler;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const createInstrumentsExtendedTable: () => import("../..").Table
|
|
1
|
+
export declare const createInstrumentsExtendedTable: () => import("../..").Table<import("@heswell/vuu-table").Table>;
|
|
@@ -31,4 +31,4 @@ export declare const InstrumentColumnMap: {
|
|
|
31
31
|
};
|
|
32
32
|
export declare const getInstrumentsData: () => InstrumentsDataRow[];
|
|
33
33
|
export declare const getRic: (defaultRic: string) => string;
|
|
34
|
-
export declare const createInstrumentsTable: () => import("../..").Table
|
|
34
|
+
export declare const createInstrumentsTable: () => import("../..").Table<import("@heswell/vuu-table").Table>;
|
|
@@ -32,4 +32,4 @@ export declare const OrderColumnMap: {
|
|
|
32
32
|
readonly trader: 8;
|
|
33
33
|
};
|
|
34
34
|
export declare const getOrdersData: () => OrdersDataRow[];
|
|
35
|
-
export declare const createOrdersTable: () => import("../..").Table
|
|
35
|
+
export declare const createOrdersTable: () => import("../..").Table<import("@heswell/vuu-table").Table>;
|
package/src/test/TestModule.d.ts
CHANGED
|
@@ -10,6 +10,6 @@ export declare class TestModule extends VuuModule<TestTableName> {
|
|
|
10
10
|
get services(): undefined;
|
|
11
11
|
get menuServices(): Record<TestTableName, RpcMenuService[] | undefined> | undefined;
|
|
12
12
|
get schemas(): Record<TestTableName, TableSchema>;
|
|
13
|
-
get tables(): Record<TestTableName, Table
|
|
13
|
+
get tables(): Record<TestTableName, Table<import("@heswell/vuu-table").Table>>;
|
|
14
14
|
get visualLinks(): undefined;
|
|
15
15
|
}
|
|
@@ -23,7 +23,7 @@ export declare class UserAdminModule extends VuuModule<UserAdminTableName> {
|
|
|
23
23
|
get menuServices(): undefined;
|
|
24
24
|
get services(): Record<UserAdminTableName, RpcService[]>;
|
|
25
25
|
reconcile(): Promise<void>;
|
|
26
|
-
protected createSessionTable(sourceTable: Table, sessionTableName: string, editSessionMode: import("@vuu-ui/vuu-data-types").EditSessionMode | import("@vuu-ui/vuu-data-types").CopyOption, dataSource: import("../ModuleDataSource").ModuleDataSource, sessionType?: import("@vuu-ui/vuu-data-types").SessionType): Table
|
|
26
|
+
protected createSessionTable(sourceTable: Table, sessionTableName: string, editSessionMode: import("@vuu-ui/vuu-data-types").EditSessionMode | import("@vuu-ui/vuu-data-types").CopyOption, dataSource: import("../ModuleDataSource").ModuleDataSource, sessionType?: import("@vuu-ui/vuu-data-types").SessionType): Table<import("@heswell/vuu-table").Table>;
|
|
27
27
|
protected beforeSessionSave(sourceTable: Table, sessionTable: Table): Promise<void>;
|
|
28
28
|
protected afterSessionSave(sourceTable: Table, sessionTable: Table): Promise<void>;
|
|
29
29
|
private saveGroupsFromSession;
|