@vuu-ui/vuu-data-test 4.0.0-alpha.1 → 4.0.0-alpha.11

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/README.md CHANGED
@@ -0,0 +1,8 @@
1
+ # `@vuu-ui/vuu-data-test`
2
+
3
+ ## Admin test module dependencies
4
+
5
+ The `USER_ADMIN` and `MODULE_DISCOVERY` test modules use the published
6
+ `@heswell/user-admin` and `@heswell/module-admin` packages. Standard
7
+ `npm install` setup is sufficient. Browser code imports only the browser-safe
8
+ `contracts` subpath for module-admin.
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "4.0.0-alpha.1",
2
+ "version": "4.0.0-alpha.11",
3
3
  "main": "./src/index.js",
4
4
  "type": "module",
5
5
  "author": "heswell",
@@ -10,15 +10,16 @@
10
10
  "type-defs": "node ../../scripts/build-type-defs.mjs"
11
11
  },
12
12
  "dependencies": {
13
- "@vuu-ui/vuu-data-editing": "4.0.0-alpha.1",
14
- "@vuu-ui/vuu-data-local": "4.0.0-alpha.1",
15
- "@vuu-ui/core": "4.0.0-alpha.1",
16
- "@vuu-ui/vuu-utils": "4.0.0-alpha.1"
13
+ "@heswell/module-admin": "1.0.0",
14
+ "@heswell/user-admin": "1.0.1",
15
+ "@vuu-ui/vuu-data-editing": "4.0.0-alpha.11",
16
+ "@vuu-ui/vuu-data-local": "4.0.0-alpha.11",
17
+ "@vuu-ui/vuu-utils": "4.0.0-alpha.11"
17
18
  },
18
19
  "devDependencies": {
19
- "@vuu-ui/vuu-protocol-types": "4.0.0-alpha.1",
20
- "@vuu-ui/vuu-data-types": "4.0.0-alpha.1",
21
- "@vuu-ui/vuu-table-types": "4.0.0-alpha.1"
20
+ "@vuu-ui/vuu-data-types": "4.0.0-alpha.11",
21
+ "@vuu-ui/vuu-protocol-types": "4.0.0-alpha.11",
22
+ "@vuu-ui/vuu-table-types": "4.0.0-alpha.11"
22
23
  },
23
24
  "sideEffects": false,
24
25
  "files": [
@@ -29,6 +30,7 @@
29
30
  "exports": {
30
31
  ".": {
31
32
  "import": "./src/index.js",
33
+ "default": "./src/index.js",
32
34
  "types": "./types/index.d.ts"
33
35
  }
34
36
  },
package/src/Table.js CHANGED
@@ -20,7 +20,7 @@ class Table extends EventEmitter {
20
20
  }
21
21
  buildIndex() {
22
22
  for(let i = 0; i < this.#data.length; i++){
23
- const key = this.#data[i][this.#indexOfKey];
23
+ const key = String(this.#data[i][this.#indexOfKey]);
24
24
  this.#index.set(key, i);
25
25
  }
26
26
  }
@@ -41,7 +41,7 @@ class Table extends EventEmitter {
41
41
  if (-1 !== index) {
42
42
  this.#index.delete(key);
43
43
  this.#data.splice(index, 1);
44
- for(let i = index; i < this.#data.length; i++)this.#index.set(this.#data[i][this.#indexOfKey], i);
44
+ for(let i = index; i < this.#data.length; i++)this.#index.set(String(this.#data[i][this.#indexOfKey]), i);
45
45
  if (emitEvent) this.emit("delete", key);
46
46
  } else throw Error(`[Table] delete key ${key} not found`);
47
47
  }
@@ -51,7 +51,7 @@ class Table extends EventEmitter {
51
51
  row[this.#dataMap.vuuUpdatedTimestamp] = createdTime;
52
52
  row[this.#dataMap.vuuCreatedTimestamp] = createdTime;
53
53
  this.#data.push(row);
54
- const key = row[this.#indexOfKey];
54
+ const key = String(row[this.#indexOfKey]);
55
55
  this.#index.set(key, index);
56
56
  if (emitEvent) this.emit("insert", row);
57
57
  }
@@ -60,7 +60,7 @@ class Table extends EventEmitter {
60
60
  return this.#data[index];
61
61
  }
62
62
  update(key, columnName, value) {
63
- const rowIndex = this.#data.findIndex((row)=>row[this.#indexOfKey] === key);
63
+ const rowIndex = this.#data.findIndex((row)=>String(row[this.#indexOfKey]) === key);
64
64
  const colIndex = this.#dataMap[columnName];
65
65
  if (-1 !== rowIndex) {
66
66
  const row = this.#data[rowIndex];
@@ -77,7 +77,7 @@ class Table extends EventEmitter {
77
77
  }
78
78
  updateRow(row) {
79
79
  const key = row[this.#indexOfKey];
80
- const rowIndex = this.#data.findIndex((row)=>row[this.#indexOfKey] === key);
80
+ const rowIndex = this.#data.findIndex((row)=>String(row[this.#indexOfKey]) === String(key));
81
81
  if (-1 !== rowIndex) {
82
82
  const tsIndex = this.#dataMap.vuuUpdatedTimestamp;
83
83
  const lastUpdated = Date.now();
@@ -132,8 +132,10 @@ class TickingArrayDataSource extends ArrayDataSource {
132
132
  data: rowData
133
133
  }
134
134
  });
135
- if (isRpcSuccess(response)) return true;
136
- return response?.errorMessage ?? "addRow failed";
135
+ return response ?? {
136
+ type: "ERROR_RESULT",
137
+ errorMessage: "addRow failed"
138
+ };
137
139
  };
138
140
  deleteRow = async (key, mode = "hard")=>{
139
141
  const response = await this.rpcRequest({
@@ -8,6 +8,9 @@ class ModuleContainer {
8
8
  register(module) {
9
9
  this.#modules.set(module.name, module);
10
10
  }
11
+ has(name) {
12
+ return this.#modules.has(name);
13
+ }
11
14
  get(name) {
12
15
  const module = this.#modules.get(name);
13
16
  if (module) return module;
@@ -18,4 +21,9 @@ class ModuleContainer {
18
21
  }
19
22
  }
20
23
  var module_ModuleContainer = ModuleContainer.instance;
24
+ const ensureVuuModule = (module)=>{
25
+ if (!ModuleContainer.instance.has(module.name)) ModuleContainer.instance.register(module);
26
+ return module;
27
+ };
21
28
  export default module_ModuleContainer;
29
+ export { ensureVuuModule };
@@ -22,6 +22,11 @@ class VuuModule {
22
22
  this.#sessionTableMessageColumn = sessionTableMessageColumn;
23
23
  ModuleContainer.register(this);
24
24
  }
25
+ get includeDefaultServices() {
26
+ return true;
27
+ }
28
+ async beforeSessionSave(_sourceTable, _sessionTable) {}
29
+ async afterSessionSave(_sourceTable, _sessionTable) {}
25
30
  getTableSchema(tableName) {
26
31
  return this.schemas[tableName] ?? this.#sessionTableMap[tableName]?.schema;
27
32
  }
@@ -155,8 +160,9 @@ class VuuModule {
155
160
  };
156
161
  getServices(tableName) {
157
162
  const tableServices = this.services?.[tableName];
158
- if (Array.isArray(tableServices)) return this.#moduleServices.concat(tableServices);
159
- return this.#moduleServices;
163
+ const defaultServices = this.includeDefaultServices ? this.#moduleServices : [];
164
+ if (Array.isArray(tableServices)) return defaultServices.concat(tableServices);
165
+ return defaultServices;
160
166
  }
161
167
  getMenuServices(tableName) {
162
168
  const tableServices = this.menuServices?.[tableName];
@@ -212,13 +218,9 @@ class VuuModule {
212
218
  if (sessionTable) {
213
219
  const { dataSource } = this.getSubscriptionByViewport(viewPortId);
214
220
  const selectedRowIds = dataSource.getSelectedRowIds();
215
- const deletedKeys = [];
216
221
  if (selectedRowIds.length > 0) {
217
- for (const key of selectedRowIds){
218
- if ("soft" === mode) sessionTable.update(key, "vuuAction", "deleteRow");
219
- else sessionTable.delete(key);
220
- deletedKeys.push(key);
221
- }
222
+ for (const key of selectedRowIds)if ("soft" === mode) sessionTable.update(key, "vuuAction", "deleteRow");
223
+ else sessionTable.delete(key);
222
224
  dataSource.select?.({
223
225
  type: "DESELECT_ALL"
224
226
  });
@@ -226,7 +228,7 @@ class VuuModule {
226
228
  return {
227
229
  type: "SUCCESS_RESULT",
228
230
  data: {
229
- deletedKeys
231
+ deletedKeys: selectedRowIds
230
232
  }
231
233
  };
232
234
  }
@@ -498,6 +500,14 @@ class VuuModule {
498
500
  data: void 0
499
501
  };
500
502
  {
503
+ try {
504
+ await this.beforeSessionSave(sourceTable, sessionTable);
505
+ } catch (error) {
506
+ return {
507
+ errorMessage: error instanceof Error ? error.message : "Unable to prepare session changes",
508
+ type: "ERROR_RESULT"
509
+ };
510
+ }
501
511
  let rejectedCount = 0;
502
512
  const vuuMsgIdx = sessionTable.map[this.#sessionTableMessageColumn];
503
513
  const actionIdx = sessionTable.map.vuuAction;
@@ -532,6 +542,14 @@ class VuuModule {
532
542
  errorMessage: "stale update",
533
543
  type: "ERROR_RESULT"
534
544
  };
545
+ try {
546
+ await this.afterSessionSave(sourceTable, sessionTable);
547
+ } catch (error) {
548
+ return {
549
+ errorMessage: error instanceof Error ? error.message : "Unable to finalize session changes",
550
+ type: "ERROR_RESULT"
551
+ };
552
+ }
535
553
  return {
536
554
  type: "SUCCESS_RESULT",
537
555
  data: void 0
@@ -10,7 +10,7 @@ class TableContainer {
10
10
  return TableContainer.#instance;
11
11
  }
12
12
  #tables = new Map();
13
- createTable = (schema, data, dataMap, updateGenerator)=>{
13
+ createTable = (schema, data = [], dataMap = buildDataColumnMapFromSchema(schema), updateGenerator)=>{
14
14
  const table = new Table(schema, data, dataMap, updateGenerator);
15
15
  this.addTable(table);
16
16
  return table;
package/src/index.js CHANGED
@@ -5,8 +5,11 @@ export * from "./makeSuggestions.js";
5
5
  export * from "./schemas.js";
6
6
  export * from "./simul/index.js";
7
7
  export * from "./basket/index.js";
8
+ export * from "./module-admin/index.js";
9
+ export * from "./user-admin/index.js";
8
10
  export * from "./test/index.js";
9
11
  export * from "./TickingArrayDataSource.js";
10
12
  export * from "./vuu-row-generator.js";
13
+ export { ensureVuuModule } from "./core/module/ModuleContainer.js";
11
14
  export { default as tableContainer } from "./core/table/TableContainer.js";
12
15
  export { Table, buildDataColumnMap, buildDataColumnMapFromSchema } from "./Table.js";
@@ -0,0 +1,60 @@
1
+ import { DEFAULT_MODULE_DEFINITIONS } from "@heswell/module-admin/contracts";
2
+ import { VuuModule } from "../core/module/VuuModule.js";
3
+ import TableContainer from "../core/table/TableContainer.js";
4
+ import { buildDataColumnMapFromSchema } from "../Table.js";
5
+ import { MODULE_ADMIN_MODULE_NAME, MODULE_ADMIN_TABLE_SCHEMAS } from "./module-admin-schemas.js";
6
+ import { reconcileModuleAdminTables } from "./snapshot-projection.js";
7
+ const createTable = (tableName)=>{
8
+ const schema = MODULE_ADMIN_TABLE_SCHEMAS[tableName];
9
+ return TableContainer.createTable(schema, [], buildDataColumnMapFromSchema(schema));
10
+ };
11
+ const createTables = ()=>({
12
+ modulePermissions: createTable("modulePermissions"),
13
+ modules: createTable("modules")
14
+ });
15
+ const MODULE_ADMIN_INITIAL_SNAPSHOT = {
16
+ moduleAccessRoles: [
17
+ {
18
+ moduleName: "moduleAdmin",
19
+ role: "module-admin-access"
20
+ },
21
+ {
22
+ moduleName: "userAdmin",
23
+ role: "user-admin-access"
24
+ },
25
+ {
26
+ moduleName: "basket-trading",
27
+ role: "basket-trading-access"
28
+ }
29
+ ],
30
+ modules: DEFAULT_MODULE_DEFINITIONS,
31
+ timestamp: 1710000000000
32
+ };
33
+ class ModuleAdminModule extends VuuModule {
34
+ #tables;
35
+ constructor(snapshot = MODULE_ADMIN_INITIAL_SNAPSHOT){
36
+ super(MODULE_ADMIN_MODULE_NAME);
37
+ this.#tables = createTables();
38
+ reconcileModuleAdminTables(snapshot, this.#tables);
39
+ }
40
+ get menus() {
41
+ return {
42
+ modulePermissions: void 0,
43
+ modules: void 0
44
+ };
45
+ }
46
+ get includeDefaultServices() {
47
+ return false;
48
+ }
49
+ get menuServices() {}
50
+ get schemas() {
51
+ return MODULE_ADMIN_TABLE_SCHEMAS;
52
+ }
53
+ get services() {}
54
+ get tables() {
55
+ return this.#tables;
56
+ }
57
+ get visualLinks() {}
58
+ }
59
+ const moduleAdminModule = new ModuleAdminModule();
60
+ export { MODULE_ADMIN_INITIAL_SNAPSHOT, ModuleAdminModule, moduleAdminModule };
@@ -0,0 +1,3 @@
1
+ export { MODULE_ADMIN_INITIAL_SNAPSHOT, ModuleAdminModule, moduleAdminModule } from "./ModuleAdminModule.js";
2
+ export { MODULE_ADMIN_MODULE_NAME, MODULE_ADMIN_TABLE_SCHEMAS } from "./module-admin-schemas.js";
3
+ export { projectModuleAdminSnapshot, reconcileModuleAdminTables } from "./snapshot-projection.js";
@@ -0,0 +1,99 @@
1
+ import { VUU_DEFAULT_COLUMNS } from "../default-column-definitions.js";
2
+ const DEFAULT_RANGE_LIMITS = {
3
+ maxRangeEnd: 1000000,
4
+ maxRangeWidth: 1000
5
+ };
6
+ const MODULE_ADMIN_MODULE_NAME = "MODULE_DISCOVERY";
7
+ const MODULE_ADMIN_TABLE_SCHEMAS = {
8
+ modules: {
9
+ columns: [
10
+ {
11
+ name: "id",
12
+ serverDataType: "int"
13
+ },
14
+ {
15
+ name: "name",
16
+ serverDataType: "string"
17
+ },
18
+ {
19
+ name: "title",
20
+ serverDataType: "string"
21
+ },
22
+ {
23
+ name: "description",
24
+ serverDataType: "string"
25
+ },
26
+ {
27
+ name: "version",
28
+ serverDataType: "int"
29
+ },
30
+ {
31
+ name: "enabled",
32
+ serverDataType: "boolean"
33
+ },
34
+ {
35
+ name: "location",
36
+ serverDataType: "string"
37
+ },
38
+ {
39
+ name: "path",
40
+ serverDataType: "string"
41
+ },
42
+ {
43
+ name: "mfComponent",
44
+ serverDataType: "string"
45
+ },
46
+ {
47
+ name: "mfScope",
48
+ serverDataType: "string"
49
+ },
50
+ {
51
+ name: "mfUrl",
52
+ serverDataType: "string"
53
+ },
54
+ {
55
+ name: "vuuConnectionId",
56
+ serverDataType: "string"
57
+ },
58
+ {
59
+ name: "vuuWebsocketUrl",
60
+ serverDataType: "string"
61
+ },
62
+ {
63
+ name: "vuuRestUrl",
64
+ serverDataType: "string"
65
+ },
66
+ ...VUU_DEFAULT_COLUMNS
67
+ ],
68
+ key: "id",
69
+ rangeLimits: DEFAULT_RANGE_LIMITS,
70
+ table: {
71
+ module: MODULE_ADMIN_MODULE_NAME,
72
+ table: "modules"
73
+ }
74
+ },
75
+ modulePermissions: {
76
+ columns: [
77
+ {
78
+ name: "id",
79
+ serverDataType: "int"
80
+ },
81
+ {
82
+ name: "module_id",
83
+ serverDataType: "int"
84
+ },
85
+ {
86
+ name: "role",
87
+ serverDataType: "string"
88
+ },
89
+ ...VUU_DEFAULT_COLUMNS
90
+ ],
91
+ key: "id",
92
+ rangeLimits: DEFAULT_RANGE_LIMITS,
93
+ table: {
94
+ module: MODULE_ADMIN_MODULE_NAME,
95
+ table: "modulePermissions"
96
+ }
97
+ }
98
+ };
99
+ export { MODULE_ADMIN_MODULE_NAME, MODULE_ADMIN_TABLE_SCHEMAS };
@@ -0,0 +1,57 @@
1
+ import { moduleDefinitionsToRows, modulePermissionsFor } from "@heswell/module-admin/contracts";
2
+ const rowsEqual = (left, right)=>left.length === right.length && left.every((value, index)=>value === right[index]);
3
+ const systemValues = (timestamp)=>({
4
+ vuuCreatedTimestamp: timestamp,
5
+ vuuMsg: "",
6
+ vuuUpdatedTimestamp: timestamp
7
+ });
8
+ const toRow = (table, values)=>table.schema.columns.map(({ name })=>values[name] ?? "");
9
+ const moduleValues = ([id, name, title, description, version, enabled, location, path, mfComponent, mfScope, mfUrl, vuuConnectionId, vuuWebsocketUrl, vuuRestUrl], timestamp)=>({
10
+ ...systemValues(timestamp),
11
+ description,
12
+ enabled,
13
+ id,
14
+ location,
15
+ mfComponent,
16
+ mfScope,
17
+ mfUrl,
18
+ name,
19
+ path,
20
+ title,
21
+ version,
22
+ vuuConnectionId,
23
+ vuuRestUrl,
24
+ vuuWebsocketUrl
25
+ });
26
+ const permissionValues = ([id, moduleId, role], timestamp)=>({
27
+ ...systemValues(timestamp),
28
+ id,
29
+ module_id: moduleId,
30
+ role
31
+ });
32
+ const projectModuleAdminSnapshot = (snapshot, tables)=>({
33
+ modulePermissions: modulePermissionsFor(snapshot.modules, snapshot.moduleAccessRoles).map((row)=>toRow(tables.modulePermissions, permissionValues(row, snapshot.timestamp))),
34
+ modules: moduleDefinitionsToRows(snapshot.modules).map((row)=>toRow(tables.modules, moduleValues(row, snapshot.timestamp)))
35
+ });
36
+ const reconcileModuleAdminTables = (snapshot, tables)=>{
37
+ const projected = projectModuleAdminSnapshot(snapshot, tables);
38
+ for (const tableName of Object.keys(tables)){
39
+ const table = tables[tableName];
40
+ const desiredRows = projected[tableName];
41
+ const keyIndex = table.map[table.schema.key];
42
+ const desiredKeys = new Set(desiredRows.map((row)=>String(row[keyIndex])));
43
+ for (const existingRow of [
44
+ ...table.data
45
+ ]){
46
+ const key = String(existingRow[keyIndex]);
47
+ if (!desiredKeys.has(key)) table.delete(key);
48
+ }
49
+ for (const row of desiredRows){
50
+ const key = String(row[keyIndex]);
51
+ const existingRow = table.findByKey(key);
52
+ if (void 0 === existingRow) table.insert(row);
53
+ else if (!rowsEqual(existingRow, row)) table.updateRow(row);
54
+ }
55
+ }
56
+ };
57
+ export { projectModuleAdminSnapshot, reconcileModuleAdminTables };
package/src/schemas.js CHANGED
@@ -1,15 +1,21 @@
1
1
  import { schemas } from "./basket/basket-schemas.js";
2
2
  import { schemas as simul_schemas_js_schemas } from "./simul/simul-schemas.js";
3
3
  import { testModule } from "./test/TestModule.js";
4
+ import { USER_ADMIN_TABLE_SCHEMAS } from "@heswell/user-admin/contracts";
5
+ import { MODULE_ADMIN_TABLE_SCHEMAS } from "./module-admin/index.js";
4
6
  const schemas_schemas = {
5
7
  ...schemas,
6
8
  ...simul_schemas_js_schemas,
7
- ...testModule.schemas
9
+ ...testModule.schemas,
10
+ ...USER_ADMIN_TABLE_SCHEMAS,
11
+ ...MODULE_ADMIN_TABLE_SCHEMAS
8
12
  };
9
13
  const allSchemas = {
10
14
  ...schemas,
11
15
  ...simul_schemas_js_schemas,
12
- ...testModule.schemas
16
+ ...testModule.schemas,
17
+ ...USER_ADMIN_TABLE_SCHEMAS,
18
+ ...MODULE_ADMIN_TABLE_SCHEMAS
13
19
  };
14
20
  const getAllSchemas = ()=>schemas_schemas;
15
21
  const getSchema = (tableName)=>{