@epam/uui-db 5.3.0 → 5.4.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/package.json +5 -5
- package/{build/stats.html → stats.html} +1 -1
- package/benchmark/results/filter.json +0 -39
- package/benchmark/results/pkLookup.json +0 -39
- package/benchmark/results/pkUpdate-10.json +0 -51
- package/benchmark/results/pkUpdate-100.json +0 -51
- package/benchmark/results/pkUpdate-1000.json +0 -51
- package/benchmark/results/pkUpdate-10000.json +0 -51
- package/benchmark/results/pkUpdate-100000.json +0 -51
- package/benchmark/results/pkUpdate-1000000.json +0 -51
- package/benchmark/results/query-10.json +0 -63
- package/benchmark/results/query-100.json +0 -63
- package/benchmark/results/query-1000.json +0 -63
- package/benchmark/results/query-10000.json +0 -63
- package/benchmark/results/query-100000.json +0 -63
- package/benchmark/results/sorting.json +0 -33
- package/build/package.json +0 -69
- package/build/readme.md +0 -17
- package/globals.d.ts +0 -9
- package/index.tsx +0 -1
- package/src/Db.ts +0 -89
- package/src/DbRef.ts +0 -254
- package/src/DbTable.ts +0 -264
- package/src/IxSet.ts +0 -251
- package/src/ListLoadingTracker.ts +0 -131
- package/src/Loader.ts +0 -96
- package/src/Scheduler.ts +0 -72
- package/src/SimpleLoadingTracker.ts +0 -17
- package/src/__benchmarks__/filter.ts +0 -50
- package/src/__benchmarks__/index.ts +0 -5
- package/src/__benchmarks__/pkLookup.ts +0 -33
- package/src/__benchmarks__/pkUpdate.ts +0 -75
- package/src/__benchmarks__/query.ts +0 -101
- package/src/__benchmarks__/sorting.ts +0 -33
- package/src/__benchmarks__/testData.ts +0 -15
- package/src/__tests__/ListLoadingTracker.test.ts +0 -83
- package/src/__tests__/Scheduler.test.ts +0 -24
- package/src/__tests__/TaskDb.ts +0 -187
- package/src/__tests__/db.test.ts +0 -293
- package/src/__tests__/dbRef.test.ts +0 -100
- package/src/__tests__/dbTable.test.ts +0 -15
- package/src/__tests__/dbViews.test.ts +0 -76
- package/src/__tests__/ixSet.perf.test.ts +0 -129
- package/src/__tests__/ixSet.test.ts +0 -73
- package/src/__tests__/listLoader.test.ts +0 -85
- package/src/__tests__/loader.test.ts +0 -92
- package/src/__tests__/patchHelpers.test.ts +0 -202
- package/src/__tests__/tempIds.test.ts +0 -98
- package/src/index.ts +0 -8
- package/src/patchHelpers.ts +0 -254
- package/src/reactHooks.ts +0 -28
- package/src/tempIds.tsx +0 -236
- package/src/types.ts +0 -126
- package/src/utils.ts +0 -34
- package/tsconfig.json +0 -12
- /package/{build/index.d.ts → index.d.ts} +0 -0
- /package/{build/index.d.ts.map → index.d.ts.map} +0 -0
- /package/{build/index.esm.js → index.esm.js} +0 -0
- /package/{build/index.esm.js.map → index.esm.js.map} +0 -0
- /package/{build/index.js → index.js} +0 -0
- /package/{build/index.js.map → index.js.map} +0 -0
- /package/{build/src → src}/Db.d.ts +0 -0
- /package/{build/src → src}/Db.d.ts.map +0 -0
- /package/{build/src → src}/DbRef.d.ts +0 -0
- /package/{build/src → src}/DbRef.d.ts.map +0 -0
- /package/{build/src → src}/DbTable.d.ts +0 -0
- /package/{build/src → src}/DbTable.d.ts.map +0 -0
- /package/{build/src → src}/IxSet.d.ts +0 -0
- /package/{build/src → src}/IxSet.d.ts.map +0 -0
- /package/{build/src → src}/ListLoadingTracker.d.ts +0 -0
- /package/{build/src → src}/ListLoadingTracker.d.ts.map +0 -0
- /package/{build/src → src}/Loader.d.ts +0 -0
- /package/{build/src → src}/Loader.d.ts.map +0 -0
- /package/{build/src → src}/Scheduler.d.ts +0 -0
- /package/{build/src → src}/Scheduler.d.ts.map +0 -0
- /package/{build/src → src}/SimpleLoadingTracker.d.ts +0 -0
- /package/{build/src → src}/SimpleLoadingTracker.d.ts.map +0 -0
- /package/{build/src → src}/__benchmarks__/filter.d.ts +0 -0
- /package/{build/src → src}/__benchmarks__/filter.d.ts.map +0 -0
- /package/{build/src → src}/__benchmarks__/index.d.ts +0 -0
- /package/{build/src → src}/__benchmarks__/index.d.ts.map +0 -0
- /package/{build/src → src}/__benchmarks__/pkLookup.d.ts +0 -0
- /package/{build/src → src}/__benchmarks__/pkLookup.d.ts.map +0 -0
- /package/{build/src → src}/__benchmarks__/pkUpdate.d.ts +0 -0
- /package/{build/src → src}/__benchmarks__/pkUpdate.d.ts.map +0 -0
- /package/{build/src → src}/__benchmarks__/query.d.ts +0 -0
- /package/{build/src → src}/__benchmarks__/query.d.ts.map +0 -0
- /package/{build/src → src}/__benchmarks__/sorting.d.ts +0 -0
- /package/{build/src → src}/__benchmarks__/sorting.d.ts.map +0 -0
- /package/{build/src → src}/__benchmarks__/testData.d.ts +0 -0
- /package/{build/src → src}/__benchmarks__/testData.d.ts.map +0 -0
- /package/{build/src → src}/index.d.ts +0 -0
- /package/{build/src → src}/index.d.ts.map +0 -0
- /package/{build/src → src}/patchHelpers.d.ts +0 -0
- /package/{build/src → src}/patchHelpers.d.ts.map +0 -0
- /package/{build/src → src}/reactHooks.d.ts +0 -0
- /package/{build/src → src}/reactHooks.d.ts.map +0 -0
- /package/{build/src → src}/tempIds.d.ts +0 -0
- /package/{build/src → src}/tempIds.d.ts.map +0 -0
- /package/{build/src → src}/types.d.ts +0 -0
- /package/{build/src → src}/types.d.ts.map +0 -0
- /package/{build/src → src}/utils.d.ts +0 -0
- /package/{build/src → src}/utils.d.ts.map +0 -0
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "Find N entities in 1000 dataset by departmentId, sorted by name",
|
|
3
|
-
"date": "2020-06-10T00:29:36.431Z",
|
|
4
|
-
"version": "1.0.0",
|
|
5
|
-
"results": [
|
|
6
|
-
{
|
|
7
|
-
"name": "Array - scan",
|
|
8
|
-
"ops": 278416,
|
|
9
|
-
"margin": 2.35,
|
|
10
|
-
"percentSlower": 87.88
|
|
11
|
-
},
|
|
12
|
-
{
|
|
13
|
-
"name": "Array - with filterPredicate/orderComparer",
|
|
14
|
-
"ops": 68167,
|
|
15
|
-
"margin": 3.37,
|
|
16
|
-
"percentSlower": 97.03
|
|
17
|
-
},
|
|
18
|
-
{
|
|
19
|
-
"name": "BTree - toArray/scan",
|
|
20
|
-
"ops": 23840,
|
|
21
|
-
"margin": 2.65,
|
|
22
|
-
"percentSlower": 98.96
|
|
23
|
-
},
|
|
24
|
-
{
|
|
25
|
-
"name": "I.Map - iterable.filter.sort, then toArray",
|
|
26
|
-
"ops": 22083,
|
|
27
|
-
"margin": 1.73,
|
|
28
|
-
"percentSlower": 99.04
|
|
29
|
-
},
|
|
30
|
-
{
|
|
31
|
-
"name": "I.Map - toArray, then filter/sort",
|
|
32
|
-
"ops": 17308,
|
|
33
|
-
"margin": 1.21,
|
|
34
|
-
"percentSlower": 99.25
|
|
35
|
-
},
|
|
36
|
-
{
|
|
37
|
-
"name": "IxSet - with indexes",
|
|
38
|
-
"ops": 184695,
|
|
39
|
-
"margin": 1.28,
|
|
40
|
-
"percentSlower": 91.96
|
|
41
|
-
},
|
|
42
|
-
{
|
|
43
|
-
"name": "IxSet - no indexes",
|
|
44
|
-
"ops": 21450,
|
|
45
|
-
"margin": 1.04,
|
|
46
|
-
"percentSlower": 99.07
|
|
47
|
-
},
|
|
48
|
-
{
|
|
49
|
-
"name": "DbTable - with index",
|
|
50
|
-
"ops": 2298027,
|
|
51
|
-
"margin": 1.28,
|
|
52
|
-
"percentSlower": 0
|
|
53
|
-
}
|
|
54
|
-
],
|
|
55
|
-
"fastest": {
|
|
56
|
-
"name": "DbTable - with index",
|
|
57
|
-
"index": 7
|
|
58
|
-
},
|
|
59
|
-
"slowest": {
|
|
60
|
-
"name": "I.Map - toArray, then filter/sort",
|
|
61
|
-
"index": 4
|
|
62
|
-
}
|
|
63
|
-
}
|
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "Find N entities in 10000 dataset by departmentId, sorted by name",
|
|
3
|
-
"date": "2020-06-10T00:30:19.909Z",
|
|
4
|
-
"version": "1.0.0",
|
|
5
|
-
"results": [
|
|
6
|
-
{
|
|
7
|
-
"name": "Array - scan",
|
|
8
|
-
"ops": 27704,
|
|
9
|
-
"margin": 3.13,
|
|
10
|
-
"percentSlower": 98.71
|
|
11
|
-
},
|
|
12
|
-
{
|
|
13
|
-
"name": "Array - with filterPredicate/orderComparer",
|
|
14
|
-
"ops": 6806,
|
|
15
|
-
"margin": 3.02,
|
|
16
|
-
"percentSlower": 99.68
|
|
17
|
-
},
|
|
18
|
-
{
|
|
19
|
-
"name": "BTree - toArray/scan",
|
|
20
|
-
"ops": 2544,
|
|
21
|
-
"margin": 1.27,
|
|
22
|
-
"percentSlower": 99.88
|
|
23
|
-
},
|
|
24
|
-
{
|
|
25
|
-
"name": "I.Map - iterable.filter.sort, then toArray",
|
|
26
|
-
"ops": 2458,
|
|
27
|
-
"margin": 1.39,
|
|
28
|
-
"percentSlower": 99.89
|
|
29
|
-
},
|
|
30
|
-
{
|
|
31
|
-
"name": "I.Map - toArray, then filter/sort",
|
|
32
|
-
"ops": 1783,
|
|
33
|
-
"margin": 1.51,
|
|
34
|
-
"percentSlower": 99.92
|
|
35
|
-
},
|
|
36
|
-
{
|
|
37
|
-
"name": "IxSet - with indexes",
|
|
38
|
-
"ops": 118744,
|
|
39
|
-
"margin": 1.19,
|
|
40
|
-
"percentSlower": 94.49
|
|
41
|
-
},
|
|
42
|
-
{
|
|
43
|
-
"name": "IxSet - no indexes",
|
|
44
|
-
"ops": 2063,
|
|
45
|
-
"margin": 3.59,
|
|
46
|
-
"percentSlower": 99.9
|
|
47
|
-
},
|
|
48
|
-
{
|
|
49
|
-
"name": "DbTable - with index",
|
|
50
|
-
"ops": 2154284,
|
|
51
|
-
"margin": 1.22,
|
|
52
|
-
"percentSlower": 0
|
|
53
|
-
}
|
|
54
|
-
],
|
|
55
|
-
"fastest": {
|
|
56
|
-
"name": "DbTable - with index",
|
|
57
|
-
"index": 7
|
|
58
|
-
},
|
|
59
|
-
"slowest": {
|
|
60
|
-
"name": "I.Map - toArray, then filter/sort",
|
|
61
|
-
"index": 4
|
|
62
|
-
}
|
|
63
|
-
}
|
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "Find N entities in 100000 dataset by departmentId, sorted by name",
|
|
3
|
-
"date": "2020-06-10T00:31:03.956Z",
|
|
4
|
-
"version": "1.0.0",
|
|
5
|
-
"results": [
|
|
6
|
-
{
|
|
7
|
-
"name": "Array - scan",
|
|
8
|
-
"ops": 1830,
|
|
9
|
-
"margin": 4.74,
|
|
10
|
-
"percentSlower": 99.91
|
|
11
|
-
},
|
|
12
|
-
{
|
|
13
|
-
"name": "Array - with filterPredicate/orderComparer",
|
|
14
|
-
"ops": 668,
|
|
15
|
-
"margin": 3.19,
|
|
16
|
-
"percentSlower": 99.97
|
|
17
|
-
},
|
|
18
|
-
{
|
|
19
|
-
"name": "BTree - toArray/scan",
|
|
20
|
-
"ops": 183,
|
|
21
|
-
"margin": 5.36,
|
|
22
|
-
"percentSlower": 99.99
|
|
23
|
-
},
|
|
24
|
-
{
|
|
25
|
-
"name": "I.Map - iterable.filter.sort, then toArray",
|
|
26
|
-
"ops": 50,
|
|
27
|
-
"margin": 2.33,
|
|
28
|
-
"percentSlower": 100
|
|
29
|
-
},
|
|
30
|
-
{
|
|
31
|
-
"name": "I.Map - toArray, then filter/sort",
|
|
32
|
-
"ops": 36,
|
|
33
|
-
"margin": 14.94,
|
|
34
|
-
"percentSlower": 100
|
|
35
|
-
},
|
|
36
|
-
{
|
|
37
|
-
"name": "IxSet - with indexes",
|
|
38
|
-
"ops": 76943,
|
|
39
|
-
"margin": 7.77,
|
|
40
|
-
"percentSlower": 96.16
|
|
41
|
-
},
|
|
42
|
-
{
|
|
43
|
-
"name": "IxSet - no indexes",
|
|
44
|
-
"ops": 135,
|
|
45
|
-
"margin": 8.63,
|
|
46
|
-
"percentSlower": 99.99
|
|
47
|
-
},
|
|
48
|
-
{
|
|
49
|
-
"name": "DbTable - with index",
|
|
50
|
-
"ops": 2003311,
|
|
51
|
-
"margin": 4.35,
|
|
52
|
-
"percentSlower": 0
|
|
53
|
-
}
|
|
54
|
-
],
|
|
55
|
-
"fastest": {
|
|
56
|
-
"name": "DbTable - with index",
|
|
57
|
-
"index": 7
|
|
58
|
-
},
|
|
59
|
-
"slowest": {
|
|
60
|
-
"name": "I.Map - toArray, then filter/sort",
|
|
61
|
-
"index": 4
|
|
62
|
-
}
|
|
63
|
-
}
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "Sort array",
|
|
3
|
-
"date": "2020-04-27T23:07:24.758Z",
|
|
4
|
-
"version": "1.0.0",
|
|
5
|
-
"results": [
|
|
6
|
-
{
|
|
7
|
-
"name": "array.sort, hard-coded",
|
|
8
|
-
"ops": 2645,
|
|
9
|
-
"margin": 2.18,
|
|
10
|
-
"percentSlower": 0
|
|
11
|
-
},
|
|
12
|
-
{
|
|
13
|
-
"name": "_.sort, hard-coded",
|
|
14
|
-
"ops": 464,
|
|
15
|
-
"margin": 1.96,
|
|
16
|
-
"percentSlower": 82.46
|
|
17
|
-
},
|
|
18
|
-
{
|
|
19
|
-
"name": "array.sort, getOrderComparer",
|
|
20
|
-
"ops": 1939,
|
|
21
|
-
"margin": 0.47,
|
|
22
|
-
"percentSlower": 26.69
|
|
23
|
-
}
|
|
24
|
-
],
|
|
25
|
-
"fastest": {
|
|
26
|
-
"name": "array.sort, hard-coded",
|
|
27
|
-
"index": 0
|
|
28
|
-
},
|
|
29
|
-
"slowest": {
|
|
30
|
-
"name": "_.sort, hard-coded",
|
|
31
|
-
"index": 1
|
|
32
|
-
}
|
|
33
|
-
}
|
package/build/package.json
DELETED
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@epam/uui-db",
|
|
3
|
-
"version": "5.3.0",
|
|
4
|
-
"description": "UUI - client-side relational state cache",
|
|
5
|
-
"author": "EPAM",
|
|
6
|
-
"license": "MIT",
|
|
7
|
-
"module": "index.esm.js",
|
|
8
|
-
"main": "index.js",
|
|
9
|
-
"typings": "index.d.ts",
|
|
10
|
-
"scripts": {
|
|
11
|
-
"build": "node ../uui-build/scripts/buildModule",
|
|
12
|
-
"perf": "npx ts-node -T ./src/__benchmarks__/index.ts",
|
|
13
|
-
"perf-prof": "node -r ts-node/register/transpile-only --prof ./src/__benchmarks__/index.ts",
|
|
14
|
-
"prepublish": "yarn build"
|
|
15
|
-
},
|
|
16
|
-
"dependencies": {
|
|
17
|
-
"@epam/uui-core": "5.3.0",
|
|
18
|
-
"@types/lodash.countby": "4.6.6",
|
|
19
|
-
"@types/lodash.filter": "4.6.6",
|
|
20
|
-
"@types/lodash.foreach": "4.5.6",
|
|
21
|
-
"@types/lodash.groupby": "4.6.6",
|
|
22
|
-
"@types/lodash.isempty": "4.4.6",
|
|
23
|
-
"@types/lodash.isequal": "4.5.5",
|
|
24
|
-
"@types/lodash.map": "4.6.13",
|
|
25
|
-
"@types/lodash.merge": "4.6.6",
|
|
26
|
-
"@types/lodash.orderby": "4.6.6",
|
|
27
|
-
"@types/lodash.pick": "4.4.6",
|
|
28
|
-
"@types/lodash.range": "3.2.6",
|
|
29
|
-
"@types/lodash.sortby": "4.7.6",
|
|
30
|
-
"@types/lodash.transform": "4.6.6",
|
|
31
|
-
"@types/lodash.zip": "4.2.6",
|
|
32
|
-
"@types/shallowequal": "^1.1.1",
|
|
33
|
-
"immutable": "3.8.2",
|
|
34
|
-
"lodash.countby": "4.6.0",
|
|
35
|
-
"lodash.filter": "4.6.0",
|
|
36
|
-
"lodash.foreach": "4.5.0",
|
|
37
|
-
"lodash.groupby": "4.6.0",
|
|
38
|
-
"lodash.isempty": "4.4.0",
|
|
39
|
-
"lodash.isequal": "4.5.0",
|
|
40
|
-
"lodash.map": "4.6.0",
|
|
41
|
-
"lodash.merge": "4.6.2",
|
|
42
|
-
"lodash.orderby": "4.6.0",
|
|
43
|
-
"lodash.pick": "4.4.0",
|
|
44
|
-
"lodash.range": "3.2.0",
|
|
45
|
-
"lodash.sortby": "4.7.0",
|
|
46
|
-
"lodash.transform": "4.6.0",
|
|
47
|
-
"lodash.zip": "4.2.0",
|
|
48
|
-
"shallowequal": "^1.1.0",
|
|
49
|
-
"sorted-btree": "^1.2.1"
|
|
50
|
-
},
|
|
51
|
-
"devDependencies": {
|
|
52
|
-
"@types/benchmark": "^1.0.31",
|
|
53
|
-
"benny": "^3.6.14",
|
|
54
|
-
"ts-node": "10.9.1"
|
|
55
|
-
},
|
|
56
|
-
"peerDependencies": {
|
|
57
|
-
"prop-types": "*",
|
|
58
|
-
"react": ">=16.0.0",
|
|
59
|
-
"react-dom": ">=16.0.0"
|
|
60
|
-
},
|
|
61
|
-
"repository": {
|
|
62
|
-
"type": "git",
|
|
63
|
-
"url": "https://github.com/epam/UUI"
|
|
64
|
-
},
|
|
65
|
-
"gitHead": "e5bbda766f5bdfd7c42a3c62c34afd9c03fffedd",
|
|
66
|
-
"publishConfig": {
|
|
67
|
-
"directory": "build"
|
|
68
|
-
}
|
|
69
|
-
}
|
package/build/readme.md
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
# UUI DB package
|
|
2
|
-
|
|
3
|
-
This package is a part of [EPAM UUI](https://github.com/epam/UUI) library.
|
|
4
|
-
|
|
5
|
-
@epam/uui-db is an experimental state-management solution. It maintains immutable relational database on client, provides means to load data from server, update it both from client, and save it to server asynchronously with UI operations.
|
|
6
|
-
|
|
7
|
-
## Features
|
|
8
|
-
|
|
9
|
-
- relation data model for state, providing a normalized storage for UI state
|
|
10
|
-
- data loading from server, with automatic GraphQL response normalization into tables
|
|
11
|
-
- synchronous and transactional updates of state from UI
|
|
12
|
-
- asynchronous bi-directional state synchronization between UI and server. UI changes in terms of 'patches' are batched and sent to server. Server can also push updates to UI state
|
|
13
|
-
- GIT-like branch-rebase approach to handle state concurrency
|
|
14
|
-
- tables can be indexed to speed-up queries
|
|
15
|
-
- Views to build arbitrary state projections
|
|
16
|
-
- subscriptions to subscribe parts of UI to changes in Views
|
|
17
|
-
|
package/globals.d.ts
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
/// <reference path="../uui_globals.d.ts" />
|
|
2
|
-
|
|
3
|
-
declare module 'jsurl';
|
|
4
|
-
declare module 'query-string';
|
|
5
|
-
declare module 'draft-js-plugins-editor';
|
|
6
|
-
declare module 'draft-js-clear-formatting';
|
|
7
|
-
declare module 'draft-convert';
|
|
8
|
-
declare module 'draft-js-plugins-utils';
|
|
9
|
-
declare module 'draft-js/lib/*';
|
package/index.tsx
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from './src';
|
package/src/Db.ts
DELETED
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
DbPatch, DbTablesSet, DbTableEntityByTable, DbView, DbRelationType, ViewCacheItem,
|
|
3
|
-
} from './types';
|
|
4
|
-
import { objectKeys, defaultCompareViewDependencies, difference } from './utils';
|
|
5
|
-
import isEqual from 'lodash.isequal';
|
|
6
|
-
|
|
7
|
-
type ViewCache = Map<DbView<any, any, any, any>, Map<string, ViewCacheItem>>;
|
|
8
|
-
|
|
9
|
-
export abstract class Db<TTables extends DbTablesSet<TTables>> {
|
|
10
|
-
private viewCache: ViewCache = new Map();
|
|
11
|
-
constructor(public tables: TTables, reusedCache?: ViewCache) {
|
|
12
|
-
if (reusedCache) {
|
|
13
|
-
this.viewCache = new Map(reusedCache);
|
|
14
|
-
} else {
|
|
15
|
-
this.viewCache = new Map();
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
private update(mutate: (db: this) => void): this {
|
|
20
|
-
const clone = new (this.constructor as any)(this.tables, this.viewCache);
|
|
21
|
-
clone.tables = { ...this.tables };
|
|
22
|
-
mutate(clone);
|
|
23
|
-
return clone;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
public with(patch: DbPatch<TTables>): this {
|
|
27
|
-
return this.update((db) => {
|
|
28
|
-
objectKeys(db.tables).forEach((entityName) => {
|
|
29
|
-
if (patch[entityName]) {
|
|
30
|
-
db.tables[entityName] = db.tables[entityName].with(patch[entityName]);
|
|
31
|
-
}
|
|
32
|
-
});
|
|
33
|
-
});
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
/* Views (cached db projections) */
|
|
37
|
-
|
|
38
|
-
valueAbsent = Symbol('ValueAbsent');
|
|
39
|
-
public runView<TResult, TParams = void, TDependencies = void>(view: DbView<this, TResult, TParams, TDependencies>, params?: TParams) {
|
|
40
|
-
let cache = this.viewCache.get(view);
|
|
41
|
-
|
|
42
|
-
if (!cache) {
|
|
43
|
-
cache = new Map();
|
|
44
|
-
this.viewCache.set(view, cache);
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
const key = view.getKey ? view.getKey(params) : JSON.stringify(params);
|
|
48
|
-
|
|
49
|
-
let cacheItem: ViewCacheItem = cache.get(key);
|
|
50
|
-
|
|
51
|
-
if (!cacheItem) {
|
|
52
|
-
cacheItem = {
|
|
53
|
-
dependencies: this.valueAbsent,
|
|
54
|
-
currentValue: this.valueAbsent,
|
|
55
|
-
computedOnDb: this.valueAbsent,
|
|
56
|
-
};
|
|
57
|
-
cache.set(key, cacheItem);
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
let shouldUpdate = this !== cacheItem.computedOnDb;
|
|
61
|
-
let dependencies: any = this.valueAbsent;
|
|
62
|
-
|
|
63
|
-
if (view.getDependencies) {
|
|
64
|
-
const compare = view.compareDependencies || defaultCompareViewDependencies;
|
|
65
|
-
dependencies = view.getDependencies(this, params);
|
|
66
|
-
shouldUpdate = !compare(cacheItem.dependencies, dependencies);
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
const previousValue = cacheItem.currentValue;
|
|
70
|
-
|
|
71
|
-
if (shouldUpdate) {
|
|
72
|
-
cacheItem.dependencies = dependencies;
|
|
73
|
-
const newValue = view.compute(this, params, dependencies);
|
|
74
|
-
cacheItem.computedOnDb = this;
|
|
75
|
-
|
|
76
|
-
const compareResults = view.compareResults || isEqual;
|
|
77
|
-
|
|
78
|
-
if (!compareResults(previousValue, newValue)) {
|
|
79
|
-
if (view.traceDiff) {
|
|
80
|
-
console.debug(difference(previousValue, newValue));
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
cacheItem.currentValue = newValue;
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
return cacheItem.currentValue as TResult;
|
|
88
|
-
}
|
|
89
|
-
}
|
package/src/DbRef.ts
DELETED
|
@@ -1,254 +0,0 @@
|
|
|
1
|
-
import { Db } from './Db';
|
|
2
|
-
import {
|
|
3
|
-
DbPatch, DbTablesSet, ServerError, DbSaveResponse, DbView, ViewCacheItem, DbSubscription, DbPkFieldType,
|
|
4
|
-
} from './types';
|
|
5
|
-
import {
|
|
6
|
-
makeCumulativePatch, unionPatches, mergeEntityPatches, flattenResponse,
|
|
7
|
-
} from './patchHelpers';
|
|
8
|
-
import { TempIdMap, IClientIdsMap } from './tempIds';
|
|
9
|
-
import { objectKeys, defaultCompareViewDependencies, difference } from './utils';
|
|
10
|
-
import isEmpty from 'lodash.isempty';
|
|
11
|
-
import { Loader, LoaderOptions } from './Loader';
|
|
12
|
-
import { DataQuery, LazyDataSourceApiResponse, batch } from '@epam/uui-core';
|
|
13
|
-
import { SimpleLoadingTracker } from './SimpleLoadingTracker';
|
|
14
|
-
import { ListLoadingTracker, ListLoadingTrackerOptions } from './ListLoadingTracker';
|
|
15
|
-
|
|
16
|
-
export class DbRef<TTables extends DbTablesSet<TTables>, TDb extends Db<TTables>> {
|
|
17
|
-
private base: TDb;
|
|
18
|
-
private log: { patch: DbPatch<TTables> }[] = [];
|
|
19
|
-
private autoSave = true;
|
|
20
|
-
private savedPoint = 0;
|
|
21
|
-
private tempIdMap: TempIdMap<TTables>;
|
|
22
|
-
public db: TDb;
|
|
23
|
-
protected throttleSaveMs = 1000;
|
|
24
|
-
public readonly idMap: IClientIdsMap;
|
|
25
|
-
constructor(public blank: TDb) {
|
|
26
|
-
this.db = blank;
|
|
27
|
-
this.base = blank;
|
|
28
|
-
this.tempIdMap = new TempIdMap(blank);
|
|
29
|
-
this.idMap = this.tempIdMap;
|
|
30
|
-
|
|
31
|
-
window.addEventListener('beforeunload', this.handleBeforeUnload);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
/** Saves all committed patches. Useful only if autoSave is off. */
|
|
35
|
-
public save() {
|
|
36
|
-
return this.enqueueSave();
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
public getAutoSave() {
|
|
40
|
-
return this.autoSave;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
public setAutoSave(val: boolean) {
|
|
44
|
-
if (this.autoSave != val) {
|
|
45
|
-
this.autoSave = val;
|
|
46
|
-
this.autoSave && this.enqueueSave();
|
|
47
|
-
this.update();
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
public revert() {
|
|
52
|
-
this.db = this.base;
|
|
53
|
-
this.log = this.log.slice(0, this.savedPoint);
|
|
54
|
-
this.update();
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
/** Concrete DbRef instances should override and implement their save logic in this method */
|
|
58
|
-
protected savePatch(patch: DbPatch<TTables>): Promise<DbSaveResponse<TTables>> {
|
|
59
|
-
return Promise.resolve({ submit: {} });
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
/* Db Update logic */
|
|
63
|
-
|
|
64
|
-
public commit(patch: DbPatch<TTables>): void {
|
|
65
|
-
const dbBeforeUpdate = this.db.with(patch);
|
|
66
|
-
patch = this.beforeUpdate(patch, dbBeforeUpdate.tables, this.db.tables);
|
|
67
|
-
patch = mergeEntityPatches(this.db.tables, patch);
|
|
68
|
-
this.log.push({ patch });
|
|
69
|
-
this.db = this.db.with(patch);
|
|
70
|
-
|
|
71
|
-
this.autoSave && this.enqueueSave(null, { throttleMs: this.throttleSaveMs });
|
|
72
|
-
this.update();
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
private beforeUpdate(patch: DbPatch<TTables>, tables: TTables, prevTables: TTables): DbPatch<TTables> {
|
|
76
|
-
let patchAndDependencies: DbPatch<TTables> = {};
|
|
77
|
-
|
|
78
|
-
objectKeys(tables)
|
|
79
|
-
.filter((entityName) => patch[entityName] && !tables[entityName].schema.beforeUpdate)
|
|
80
|
-
.forEach((entityName) => {
|
|
81
|
-
patchAndDependencies[entityName] = patch[entityName];
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
objectKeys(tables)
|
|
85
|
-
.filter((entityName) => patch[entityName] && tables[entityName].schema.beforeUpdate)
|
|
86
|
-
.forEach((entityName) => {
|
|
87
|
-
const schema = tables[entityName].schema;
|
|
88
|
-
const { beforeUpdate } = schema;
|
|
89
|
-
const context = {
|
|
90
|
-
clientIdsMap: this.tempIdMap,
|
|
91
|
-
schema,
|
|
92
|
-
tables,
|
|
93
|
-
prevTables,
|
|
94
|
-
};
|
|
95
|
-
|
|
96
|
-
const results = patch[entityName].map((e) => beforeUpdate(e, context));
|
|
97
|
-
const updatedPatch = { [entityName]: results.map((result) => result.entity) } as DbPatch<TTables>;
|
|
98
|
-
const dependentEntityPatchesForUpdate = unionPatches(results.filter((result) => result.dependentEntities).map((result) => result.dependentEntities));
|
|
99
|
-
const dependentEntityPatches = this.beforeUpdate(dependentEntityPatchesForUpdate, tables, prevTables);
|
|
100
|
-
|
|
101
|
-
patchAndDependencies = mergeEntityPatches(tables, unionPatches([
|
|
102
|
-
patchAndDependencies, updatedPatch, dependentEntityPatches,
|
|
103
|
-
]));
|
|
104
|
-
});
|
|
105
|
-
return patchAndDependencies;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
public commitFetch(patch: DbPatch<TTables>): void {
|
|
109
|
-
patch = this.tempIdMap.serverToClientPatch(patch);
|
|
110
|
-
this.rebase(this.base.with(patch));
|
|
111
|
-
this.update();
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
private rebase(newBase: TDb) {
|
|
115
|
-
this.base = newBase;
|
|
116
|
-
this.db = newBase;
|
|
117
|
-
for (let n = this.savedPoint; n < this.log.length; n++) {
|
|
118
|
-
this.db = this.db.with(this.log[n].patch);
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
private makeCumulativePatch() {
|
|
123
|
-
const lastLogEntry = this.log.length;
|
|
124
|
-
const logEntriesToSave = this.log.slice(this.savedPoint, lastLogEntry);
|
|
125
|
-
let cumulativePatch = makeCumulativePatch(
|
|
126
|
-
this.db,
|
|
127
|
-
logEntriesToSave.map((t) => t.patch),
|
|
128
|
-
this.tempIdMap,
|
|
129
|
-
);
|
|
130
|
-
cumulativePatch = this.tempIdMap.clientToServerPatch(cumulativePatch);
|
|
131
|
-
|
|
132
|
-
return cumulativePatch;
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
private applyResponse(response: DbSaveResponse<TTables>, newSavedPoint: number) {
|
|
136
|
-
this.tempIdMap.appendServerMapping(response);
|
|
137
|
-
|
|
138
|
-
let serverPatch = flattenResponse(response.submit, this.db.tables);
|
|
139
|
-
serverPatch = mergeEntityPatches(this.db.tables, serverPatch);
|
|
140
|
-
this.savedPoint = newSavedPoint;
|
|
141
|
-
this.base = this.db;
|
|
142
|
-
this.commitFetch(serverPatch);
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
/* Update subscriptions (aka live views) */
|
|
146
|
-
|
|
147
|
-
private lastSubscriptionId = 1;
|
|
148
|
-
private subscriptions: Map<number, DbSubscription<any, any>> = new Map();
|
|
149
|
-
public subscribe<TValue, TParams, TDependencies>(
|
|
150
|
-
view: DbView<TDb, TValue, TParams, TDependencies>,
|
|
151
|
-
params: TParams,
|
|
152
|
-
onUpdate: (newValue: TValue) => any,
|
|
153
|
-
): DbSubscription<TValue, TParams> {
|
|
154
|
-
const id = this.lastSubscriptionId++;
|
|
155
|
-
|
|
156
|
-
const subscription: DbSubscription<TValue, TParams> = {
|
|
157
|
-
update: (subscriptionParams: TParams) => {
|
|
158
|
-
subscription.currentParams = subscriptionParams;
|
|
159
|
-
subscription.currentValue = this.db.runView(view, subscriptionParams);
|
|
160
|
-
return subscription.currentValue;
|
|
161
|
-
},
|
|
162
|
-
currentParams: null,
|
|
163
|
-
currentValue: null,
|
|
164
|
-
onUpdate,
|
|
165
|
-
unsubscribe: () => {
|
|
166
|
-
this.subscriptions.delete(id);
|
|
167
|
-
},
|
|
168
|
-
};
|
|
169
|
-
|
|
170
|
-
subscription.update(params);
|
|
171
|
-
|
|
172
|
-
this.subscriptions.set(id, subscription);
|
|
173
|
-
|
|
174
|
-
return subscription;
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
updateHandlers: (() => any)[] = [];
|
|
178
|
-
public onUpdate(handler: () => any) {
|
|
179
|
-
this.subscribe(
|
|
180
|
-
{
|
|
181
|
-
compute: (db) => db,
|
|
182
|
-
compareResults: (a, b) => a === b,
|
|
183
|
-
},
|
|
184
|
-
null,
|
|
185
|
-
handler,
|
|
186
|
-
);
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
private update() {
|
|
190
|
-
this.subscriptions.forEach((subscription) => {
|
|
191
|
-
const previousValue = subscription.currentValue;
|
|
192
|
-
subscription.update(subscription.currentParams);
|
|
193
|
-
if (subscription.currentValue !== previousValue && subscription.onUpdate) {
|
|
194
|
-
subscription.onUpdate(subscription.currentValue);
|
|
195
|
-
}
|
|
196
|
-
});
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
/* Error Subscriptions */
|
|
200
|
-
|
|
201
|
-
public saveErrorHandlers: ((request: DbPatch<TTables>, error: any) => void)[] = [];
|
|
202
|
-
public onSaveError(handler: (request: DbPatch<TTables>, error: any) => void) {
|
|
203
|
-
this.saveErrorHandlers.push(handler);
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
private saveError(request: DbPatch<TTables>, error: any) {
|
|
207
|
-
this.saveErrorHandlers.forEach((handler) => handler(request, error));
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
/* Save scheduling */
|
|
211
|
-
|
|
212
|
-
private enqueueSave = batch(async () => {
|
|
213
|
-
const cumulativePatch = this.makeCumulativePatch();
|
|
214
|
-
const lastLogEntry = this.log.length;
|
|
215
|
-
if (isEmpty(cumulativePatch)) {
|
|
216
|
-
return;
|
|
217
|
-
}
|
|
218
|
-
try {
|
|
219
|
-
const response = await this.savePatch(cumulativePatch);
|
|
220
|
-
this.applyResponse(response, lastLogEntry);
|
|
221
|
-
this.update();
|
|
222
|
-
} catch (error) {
|
|
223
|
-
this.saveError(cumulativePatch, error);
|
|
224
|
-
this.update();
|
|
225
|
-
throw error;
|
|
226
|
-
}
|
|
227
|
-
});
|
|
228
|
-
|
|
229
|
-
private handleBeforeUnload = (e: BeforeUnloadEvent) => {
|
|
230
|
-
if (this.enqueueSave.isBusy) {
|
|
231
|
-
e.returnValue = false;
|
|
232
|
-
return false;
|
|
233
|
-
}
|
|
234
|
-
};
|
|
235
|
-
|
|
236
|
-
loaders: Loader<TTables, any, any>[] = [];
|
|
237
|
-
protected makeLoader<TResponse, TRequest>(options: LoaderOptions<TTables, TResponse, TRequest>) {
|
|
238
|
-
const loader = new Loader<TTables, TResponse, TRequest>(this as any, () => new SimpleLoadingTracker<TRequest, TResponse>(), options);
|
|
239
|
-
this.loaders.push(loader);
|
|
240
|
-
return loader;
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
protected makeListLoader<TItem, TResponse = DataQuery<TItem>, TRequest extends DataQuery<TItem> = DataQuery<TItem>>(
|
|
244
|
-
options: LoaderOptions<TTables, TResponse, TRequest> & ListLoadingTrackerOptions<TItem, TResponse>,
|
|
245
|
-
) {
|
|
246
|
-
const loader = new Loader<TTables, TResponse, TRequest>(this as any, () => new ListLoadingTracker<TItem, TRequest, TResponse>(), options);
|
|
247
|
-
this.loaders.push(loader);
|
|
248
|
-
return loader;
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
reload() {
|
|
252
|
-
this.loaders = [];
|
|
253
|
-
}
|
|
254
|
-
}
|