@vuu-ui/vuu-data-test 5.0.0-alpha.3 → 5.0.0-alpha.4
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/package.json +7 -7
- package/src/core/module/VuuModule.js +16 -1
- package/src/simul/reference-data/instruments-extended.js +5 -0
- package/src/simul/simul-schemas.js +4 -0
- package/src/test/TestModule.js +67 -2
- package/types/core/module/VuuModule.d.ts +7 -1
- package/types/test/TestModule.d.ts +5 -1
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "5.0.0-alpha.
|
|
2
|
+
"version": "5.0.0-alpha.4",
|
|
3
3
|
"main": "./src/index.js",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"author": "heswell",
|
|
@@ -9,16 +9,16 @@
|
|
|
9
9
|
"type-defs": "node ../../scripts/build-type-defs.mjs"
|
|
10
10
|
},
|
|
11
11
|
"dependencies": {
|
|
12
|
-
"@vuu-ui/vuu-data-local": "5.0.0-alpha.
|
|
13
|
-
"@vuu-ui/vuu-utils": "5.0.0-alpha.
|
|
12
|
+
"@vuu-ui/vuu-data-local": "5.0.0-alpha.4",
|
|
13
|
+
"@vuu-ui/vuu-utils": "5.0.0-alpha.4",
|
|
14
14
|
"@heswell/module-admin": "1.1.0",
|
|
15
15
|
"@heswell/user-admin": "1.0.1",
|
|
16
|
-
"@vuu-ui/vuu-data-editing": "5.0.0-alpha.
|
|
16
|
+
"@vuu-ui/vuu-data-editing": "5.0.0-alpha.4"
|
|
17
17
|
},
|
|
18
18
|
"devDependencies": {
|
|
19
|
-
"@vuu-ui/vuu-protocol-types": "5.0.0-alpha.
|
|
20
|
-
"@vuu-ui/vuu-data-types": "5.0.0-alpha.
|
|
21
|
-
"@vuu-ui/vuu-table-types": "5.0.0-alpha.
|
|
19
|
+
"@vuu-ui/vuu-protocol-types": "5.0.0-alpha.4",
|
|
20
|
+
"@vuu-ui/vuu-data-types": "5.0.0-alpha.4",
|
|
21
|
+
"@vuu-ui/vuu-table-types": "5.0.0-alpha.4"
|
|
22
22
|
},
|
|
23
23
|
"sideEffects": false,
|
|
24
24
|
"files": [
|
|
@@ -32,6 +32,7 @@ class VuuModule {
|
|
|
32
32
|
async beforeSessionSave(_sourceTable, _sessionTable) {}
|
|
33
33
|
async afterSessionSave(_sourceTable, _sessionTable) {}
|
|
34
34
|
permissionFunctions;
|
|
35
|
+
validateEdit(_tableName, _column, _value) {}
|
|
35
36
|
getTableSchema(tableName) {
|
|
36
37
|
return this.schemas[tableName] ?? this.#sessionTableMap[tableName]?.schema;
|
|
37
38
|
}
|
|
@@ -337,14 +338,20 @@ class VuuModule {
|
|
|
337
338
|
const { column, data, key } = rpcRequest.params;
|
|
338
339
|
const sessionTable = this.#sessionTableMap[viewPortId];
|
|
339
340
|
let targetTable = sessionTable;
|
|
341
|
+
let sourceTableName = this.#sessionSourceTableMap[viewPortId];
|
|
340
342
|
if (!targetTable) {
|
|
341
343
|
const { dataSource } = this.getSubscriptionByViewport(viewPortId);
|
|
342
|
-
if (dataSource.table)
|
|
344
|
+
if (dataSource.table) {
|
|
345
|
+
sourceTableName = dataSource.table.table;
|
|
346
|
+
targetTable = this.tables[sourceTableName];
|
|
347
|
+
}
|
|
343
348
|
}
|
|
344
349
|
if (targetTable) try {
|
|
345
350
|
const sessionRow = sessionTable?.findByKey(key);
|
|
346
351
|
if (sessionRow?.[sessionTable.map.vuuAction] === "deleteRow") throw Error("editCell: cannot edit a deleted row");
|
|
347
352
|
assertUpdateIsValid(targetTable.schema, column, data);
|
|
353
|
+
const validationError = void 0 === sourceTableName ? void 0 : this.validateEdit(sourceTableName, column, data);
|
|
354
|
+
if (void 0 !== validationError) throw Error(validationError);
|
|
348
355
|
targetTable.update(key, column, data);
|
|
349
356
|
if (sessionTable && sessionTable.findByKey(key)?.[sessionTable.map.vuuAction] !== "addRow") sessionTable.update(key, "vuuAction", "editCell");
|
|
350
357
|
return {
|
|
@@ -492,6 +499,14 @@ class VuuModule {
|
|
|
492
499
|
errorMessage: `addRow: no active session table for viewport ${viewPortId}`
|
|
493
500
|
};
|
|
494
501
|
const { data, key } = rpcRequest.params;
|
|
502
|
+
const sourceTableName = this.#sessionSourceTableMap[sessionTableName];
|
|
503
|
+
if (void 0 !== sourceTableName) for (const [column, value] of Object.entries(data)){
|
|
504
|
+
const validationError = this.validateEdit(sourceTableName, column, value);
|
|
505
|
+
if (void 0 !== validationError) return {
|
|
506
|
+
type: "ERROR_RESULT",
|
|
507
|
+
errorMessage: validationError
|
|
508
|
+
};
|
|
509
|
+
}
|
|
495
510
|
const keyColumn = sessionTable.schema.key;
|
|
496
511
|
const rowKey = data[keyColumn] ?? key ?? uuid();
|
|
497
512
|
const rowData = {
|
|
@@ -29,6 +29,10 @@ const nextClosePrice = scaledDecimalColumn(4, 4, 0, 5000);
|
|
|
29
29
|
const nextFxRate = scaledDecimalColumn(6, 6, 0.5, 2);
|
|
30
30
|
const nextWeight = scaledDecimalColumn(8, 8, 0, 0.05);
|
|
31
31
|
const nextRandom = createRandom(1);
|
|
32
|
+
const FIRST_TRADE_ID = 4000000000000;
|
|
33
|
+
const nextTradeIdGap = createRandom(3);
|
|
34
|
+
let tradeId = FIRST_TRADE_ID;
|
|
35
|
+
const nextTradeId = ()=>tradeId += randomInt(nextTradeIdGap, 1, 1000);
|
|
32
36
|
const ONE_DAY = 86400000;
|
|
33
37
|
const today = new Date();
|
|
34
38
|
today.setHours(0, 0, 0, 0);
|
|
@@ -47,6 +51,7 @@ const instrumentsExtendedData = instrumentsData.map((instrument, rowIndex)=>{
|
|
|
47
51
|
supported: nextRandom() < 0.5,
|
|
48
52
|
wishlist: nextRandom() < 0.5,
|
|
49
53
|
lastUpdated: instrument[InstrumentColumnMap.vuuUpdatedTimestamp],
|
|
54
|
+
tradeId: nextTradeId(),
|
|
50
55
|
price: Math.round(100000 * nextRandom()) / 100,
|
|
51
56
|
notional: nextNotional(rowIndex),
|
|
52
57
|
closePrice: nextClosePrice(rowIndex),
|
package/src/test/TestModule.js
CHANGED
|
@@ -39,6 +39,17 @@ const testEditColumns = [
|
|
|
39
39
|
serverDataType: "long"
|
|
40
40
|
}
|
|
41
41
|
];
|
|
42
|
+
const TEST_EDIT_VALIDATION_QUANTITY_MESSAGE = "quantity must be between 1 and 1000";
|
|
43
|
+
const TEST_EDIT_VALIDATION_PRICE_MESSAGE = "price must be greater than zero";
|
|
44
|
+
const validateTestEditValidation = (column, value)=>{
|
|
45
|
+
if ("quantity" === column) {
|
|
46
|
+
const quantity = Number(value);
|
|
47
|
+
if (!Number.isInteger(quantity) || quantity < 1 || quantity > 1000) return TEST_EDIT_VALIDATION_QUANTITY_MESSAGE;
|
|
48
|
+
} else if ("price" === column) {
|
|
49
|
+
const price = Number(value);
|
|
50
|
+
if (!(price > 0)) return TEST_EDIT_VALIDATION_PRICE_MESSAGE;
|
|
51
|
+
}
|
|
52
|
+
};
|
|
42
53
|
class TestModule extends VuuModule {
|
|
43
54
|
#schemas = {
|
|
44
55
|
TestDates: {
|
|
@@ -185,6 +196,15 @@ class TestModule extends VuuModule {
|
|
|
185
196
|
module: "TEST",
|
|
186
197
|
table: "TestEdit"
|
|
187
198
|
}
|
|
199
|
+
},
|
|
200
|
+
TestEditValidation: {
|
|
201
|
+
columns: testEditColumns,
|
|
202
|
+
key: "id",
|
|
203
|
+
rangeLimits: DEFAULT_RANGE_LIMITS,
|
|
204
|
+
table: {
|
|
205
|
+
module: "TEST",
|
|
206
|
+
table: "TestEditValidation"
|
|
207
|
+
}
|
|
188
208
|
}
|
|
189
209
|
};
|
|
190
210
|
#tables = {
|
|
@@ -562,7 +582,49 @@ class TestModule extends VuuModule {
|
|
|
562
582
|
withNanoMs(Date.now(), 5),
|
|
563
583
|
1000000000000000005n
|
|
564
584
|
]
|
|
565
|
-
], buildDataColumnMap(this.#schemas, "TestEdit"))
|
|
585
|
+
], buildDataColumnMap(this.#schemas, "TestEdit")),
|
|
586
|
+
TestEditValidation: TableContainer.createTable(this.#schemas.TestEditValidation, [
|
|
587
|
+
[
|
|
588
|
+
"VAL-001",
|
|
589
|
+
"Alpha",
|
|
590
|
+
12,
|
|
591
|
+
101.25,
|
|
592
|
+
true,
|
|
593
|
+
1001
|
|
594
|
+
],
|
|
595
|
+
[
|
|
596
|
+
"VAL-002",
|
|
597
|
+
"Bravo",
|
|
598
|
+
24,
|
|
599
|
+
202.5,
|
|
600
|
+
false,
|
|
601
|
+
1002
|
|
602
|
+
],
|
|
603
|
+
[
|
|
604
|
+
"VAL-003",
|
|
605
|
+
"Charlie",
|
|
606
|
+
36,
|
|
607
|
+
303.75,
|
|
608
|
+
true,
|
|
609
|
+
1003
|
|
610
|
+
],
|
|
611
|
+
[
|
|
612
|
+
"VAL-004",
|
|
613
|
+
"Delta",
|
|
614
|
+
48,
|
|
615
|
+
405,
|
|
616
|
+
true,
|
|
617
|
+
1004
|
|
618
|
+
],
|
|
619
|
+
[
|
|
620
|
+
"VAL-005",
|
|
621
|
+
"Echo",
|
|
622
|
+
60,
|
|
623
|
+
506.25,
|
|
624
|
+
false,
|
|
625
|
+
1005
|
|
626
|
+
]
|
|
627
|
+
], buildDataColumnMap(this.#schemas, "TestEditValidation"))
|
|
566
628
|
};
|
|
567
629
|
constructor(){
|
|
568
630
|
super("TEST");
|
|
@@ -577,6 +639,9 @@ class TestModule extends VuuModule {
|
|
|
577
639
|
return this.#tables;
|
|
578
640
|
}
|
|
579
641
|
get visualLinks() {}
|
|
642
|
+
validateEdit(tableName, column, value) {
|
|
643
|
+
return "TestEditValidation" === tableName ? validateTestEditValidation(column, value) : void 0;
|
|
644
|
+
}
|
|
580
645
|
}
|
|
581
646
|
const testModule = new TestModule();
|
|
582
|
-
export { testModule };
|
|
647
|
+
export { TEST_EDIT_VALIDATION_PRICE_MESSAGE, TEST_EDIT_VALIDATION_QUANTITY_MESSAGE, testModule };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { DataSourceBase, DataSourceConfig, DataSourceRowWithBigint, DataSourceSubscribedMessage, DataSourceVisualLinkCreatedMessage, EditSessionMode, CopyOption, SessionDataSourceOverrides, SessionType, TableSchema } from "@vuu-ui/vuu-data-types";
|
|
2
|
-
import type { VuuMenu, VuuLink, LinkDescriptorWithLabel, VuuRpcMenuResponse, VuuCreateVisualLink, VuuRemoveVisualLink, VuuRpcServiceRequest, RpcResultSuccess, RpcResultError, VuuRpcMenuRequest } from "@vuu-ui/vuu-protocol-types";
|
|
2
|
+
import type { VuuMenu, VuuRowDataItemType, VuuLink, LinkDescriptorWithLabel, VuuRpcMenuResponse, VuuCreateVisualLink, VuuRemoveVisualLink, VuuRpcServiceRequest, RpcResultSuccess, RpcResultError, VuuRpcMenuRequest } from "@vuu-ui/vuu-protocol-types";
|
|
3
3
|
import { Table } from "../../Table";
|
|
4
4
|
import { TickingArrayDataSource } from "../../TickingArrayDataSource";
|
|
5
5
|
import { type PermissionFunction } from "../filter/PermissionFilter";
|
|
@@ -59,6 +59,12 @@ export declare abstract class VuuModule<T extends string = string> implements IV
|
|
|
59
59
|
* lazily start a data provider.
|
|
60
60
|
*/
|
|
61
61
|
protected beforeCreateDataSource?(tableName: T): void;
|
|
62
|
+
/**
|
|
63
|
+
* Server-side validation applied to every value submitted by editCell and
|
|
64
|
+
* addRow. `tableName` is the source table, also when the edit targets a
|
|
65
|
+
* session table. Return a message to reject the value, undefined to accept.
|
|
66
|
+
*/
|
|
67
|
+
protected validateEdit(_tableName: T, _column: string, _value: VuuRowDataItemType): string | undefined;
|
|
62
68
|
getTableSchema(tableName: string): Record<T, Readonly<TableSchema>>[T];
|
|
63
69
|
getTableList(): string[];
|
|
64
70
|
protected handlePostSubscribeActivities: ({ clientViewportId, tableSchema, }: DataSourceSubscribedMessage) => void;
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import { type RpcMenuService, VuuModule } from "../core/module/VuuModule";
|
|
2
2
|
import { type Table } from "../Table";
|
|
3
3
|
import type { TableSchema } from "@vuu-ui/vuu-data-types";
|
|
4
|
-
|
|
4
|
+
import type { VuuRowDataItemType } from "@vuu-ui/vuu-protocol-types";
|
|
5
|
+
export type TestTableName = "TestDates" | "TwoHundredColumns" | "LinkParent" | "LinkChild" | "ChartTable" | "MaxScrollEndTable" | "TestEditEmpty" | "TestEdit" | "TestEditValidation";
|
|
6
|
+
export declare const TEST_EDIT_VALIDATION_QUANTITY_MESSAGE = "quantity must be between 1 and 1000";
|
|
7
|
+
export declare const TEST_EDIT_VALIDATION_PRICE_MESSAGE = "price must be greater than zero";
|
|
5
8
|
declare class TestModule extends VuuModule<TestTableName> {
|
|
6
9
|
#private;
|
|
7
10
|
constructor();
|
|
@@ -11,6 +14,7 @@ declare class TestModule extends VuuModule<TestTableName> {
|
|
|
11
14
|
get schemas(): Record<TestTableName, TableSchema>;
|
|
12
15
|
get tables(): Record<TestTableName, Table>;
|
|
13
16
|
get visualLinks(): undefined;
|
|
17
|
+
protected validateEdit(tableName: TestTableName, column: string, value: VuuRowDataItemType): string | undefined;
|
|
14
18
|
}
|
|
15
19
|
export declare const testModule: TestModule;
|
|
16
20
|
export {};
|