@minnowdb/core 0.6.9 → 0.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/block-format/block.js +254 -325
- package/dist/block-format/checksum.js +30 -52
- package/dist/block-format/codecs.js +112 -125
- package/dist/block-format/column.js +187 -205
- package/dist/block-format/index.js +5 -1
- package/dist/block-format/physical.js +371 -387
- package/dist/block-format/types.js +4 -1
- package/dist/block-format/unicode.js +30 -39
- package/dist/date-value.d.ts +5 -0
- package/dist/date-value.js +71 -41
- package/dist/engine/artifact-cache.js +106 -116
- package/dist/engine/batch.js +36 -44
- package/dist/engine/buffered-writer.js +156 -158
- package/dist/engine/byte-estimates.js +20 -22
- package/dist/engine/cache-limits.js +24 -25
- package/dist/engine/cancellation.js +5 -3
- package/dist/engine/catalog.js +64 -73
- package/dist/engine/client.js +715 -780
- package/dist/engine/database.js +15952 -18465
- package/dist/engine/defaults.js +104 -111
- package/dist/engine/errors.js +113 -128
- package/dist/engine/fts.js +233 -280
- package/dist/engine/group-index.js +287 -321
- package/dist/engine/index.js +23 -12
- package/dist/engine/join-index.js +177 -186
- package/dist/engine/keyed-live.js +168 -173
- package/dist/engine/live-api.js +0 -1
- package/dist/engine/live-equal.js +32 -37
- package/dist/engine/live.js +603 -647
- package/dist/engine/memory.js +109 -111
- package/dist/engine/optimizer.d.ts +19 -1
- package/dist/engine/optimizer.js +2642 -2515
- package/dist/engine/point-read.d.ts +4 -2
- package/dist/engine/point-read.js +121 -171
- package/dist/engine/query-api.js +12 -3
- package/dist/engine/query-cache.js +61 -69
- package/dist/engine/query.d.ts +45 -0
- package/dist/engine/query.js +8506 -9375
- package/dist/engine/result-wire.js +221 -252
- package/dist/engine/schema-wire.js +97 -112
- package/dist/engine/schema.js +1099 -1254
- package/dist/engine/sort-keys.js +315 -389
- package/dist/engine/sql-domains.d.ts +7 -1
- package/dist/engine/sql-domains.js +648 -734
- package/dist/engine/sql-driver.js +0 -1
- package/dist/engine/sql-functions.d.ts +11 -0
- package/dist/engine/sql-functions.js +1092 -0
- package/dist/engine/sql-json.js +199 -218
- package/dist/engine/sql-semantics.d.ts +25 -4
- package/dist/engine/sql-semantics.js +579 -513
- package/dist/engine/typed-live.js +271 -293
- package/dist/engine/vector.d.ts +7 -1
- package/dist/engine/vector.js +4513 -4580
- package/dist/engine/worker-host.d.ts +8 -63
- package/dist/engine/worker-host.js +28 -1130
- package/dist/engine/worker-indexeddb.d.ts +1 -0
- package/dist/engine/worker-indexeddb.js +3 -0
- package/dist/engine/worker-memory.d.ts +1 -0
- package/dist/engine/worker-memory.js +3 -0
- package/dist/engine/worker-opfs.d.ts +1 -0
- package/dist/engine/worker-opfs.js +3 -0
- package/dist/engine/worker-server.d.ts +93 -0
- package/dist/engine/worker-server.js +999 -0
- package/dist/engine/worker-store-indexeddb.d.ts +2 -0
- package/dist/engine/worker-store-indexeddb.js +11 -0
- package/dist/engine/worker-store-memory.d.ts +2 -0
- package/dist/engine/worker-store-memory.js +6 -0
- package/dist/engine/worker-store-opfs.d.ts +2 -0
- package/dist/engine/worker-store-opfs.js +9 -0
- package/dist/engine/worker.js +0 -12
- package/dist/engine/write-block-planner.js +93 -100
- package/dist/plan/index.js +15 -16
- package/dist/plan/model.d.ts +9 -1
- package/dist/plan/model.js +20 -27
- package/dist/storage/index.js +0 -12
- package/dist/storage/indexeddb.js +11776 -13171
- package/dist/storage/memory.js +1198 -1241
- package/dist/storage/opfs/files.js +238 -295
- package/dist/storage/opfs/index.js +9 -3
- package/dist/storage/opfs/leader.js +4386 -4856
- package/dist/storage/opfs/rpc.js +223 -259
- package/dist/storage/opfs/snapshot-ledger.js +219 -260
- package/dist/storage/opfs/store.js +884 -1003
- package/dist/storage/persistence.js +59 -74
- package/dist/storage/snapshot-stream.js +788 -826
- package/dist/storage/snapshot.js +36 -37
- package/dist/storage/toolkit/extents.js +444 -520
- package/dist/storage/toolkit/index.js +28 -29
- package/dist/storage/toolkit/record-core.js +5792 -6377
- package/dist/storage/toolkit/sync-file.js +34 -42
- package/dist/storage/toolkit/wal.js +92 -127
- package/dist/storage/toolkit/wire.js +232 -256
- package/dist/storage/types.js +2952 -3228
- package/dist/testing/block-store-conformance.js +1556 -1629
- package/dist/testing/index.js +310 -291
- package/dist/testing/opfs-shim.js +280 -312
- package/dist/testing/simulator.js +496 -534
- package/dist/testing/sqllogictest.js +425 -365
- package/dist/transactions/index.js +1464 -1712
- package/dist/worker-protocol/index.js +70 -69
- package/package.json +20 -2
- package/postgres-feature-profile.json +15 -5
- package/sql-feature-matrix.json +252 -2
|
@@ -1,192 +1,187 @@
|
|
|
1
1
|
import { dateMilliseconds } from "../date-value.js";
|
|
2
2
|
import { sameLiveValue } from "./live-equal.js";
|
|
3
3
|
function keyToken(value, name) {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
4
|
+
if (typeof value === "string")
|
|
5
|
+
return `s:${String(value.length)}:${value}`;
|
|
6
|
+
if (typeof value === "boolean")
|
|
7
|
+
return value ? "b:1" : "b:0";
|
|
8
|
+
if (typeof value === "number") {
|
|
9
|
+
if (Number.isNaN(value))
|
|
10
|
+
return "n:NaN";
|
|
11
|
+
if (Object.is(value, -0))
|
|
12
|
+
return "n:-0";
|
|
13
|
+
return `n:${String(value)}`;
|
|
14
|
+
}
|
|
15
|
+
if (value instanceof Date) {
|
|
16
|
+
const time = dateMilliseconds(value);
|
|
17
|
+
if (!Number.isFinite(time)) {
|
|
18
|
+
throw new TypeError(`Live query key ${String(name)} must be a valid Date`);
|
|
14
19
|
}
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
throw new TypeError(`Live query key ${String(name)} must be a valid Date`);
|
|
19
|
-
}
|
|
20
|
-
return `d:${String(time)}`;
|
|
21
|
-
}
|
|
22
|
-
throw new TypeError(`Live query key ${String(name)} must be a non-null string, number, boolean, or Date`);
|
|
20
|
+
return `d:${String(time)}`;
|
|
21
|
+
}
|
|
22
|
+
throw new TypeError(`Live query key ${String(name)} must be a non-null string, number, boolean, or Date`);
|
|
23
23
|
}
|
|
24
24
|
function indexRows(rows, key) {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
}
|
|
34
|
-
indexed.set(token, { row, index });
|
|
25
|
+
const indexed = /* @__PURE__ */ new Map();
|
|
26
|
+
for (let index = 0; index < rows.length; index += 1) {
|
|
27
|
+
const row = rows[index];
|
|
28
|
+
if (row === void 0)
|
|
29
|
+
continue;
|
|
30
|
+
const token = keyToken(row[key], key);
|
|
31
|
+
if (indexed.has(token)) {
|
|
32
|
+
throw new TypeError(`Live query key ${String(key)} is not unique: duplicate at row ${String(index)}`);
|
|
35
33
|
}
|
|
36
|
-
|
|
34
|
+
indexed.set(token, { row, index });
|
|
35
|
+
}
|
|
36
|
+
return indexed;
|
|
37
37
|
}
|
|
38
38
|
function diffRows(previousRows, rows, key) {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
39
|
+
const previous = indexRows(previousRows, key);
|
|
40
|
+
const current = indexRows(rows, key);
|
|
41
|
+
const changes = [];
|
|
42
|
+
for (const [token, old] of previous) {
|
|
43
|
+
if (current.has(token))
|
|
44
|
+
continue;
|
|
45
|
+
changes.push({ type: "delete", key: old.row[key], previous: old.row, index: old.index });
|
|
46
|
+
}
|
|
47
|
+
for (const [token, next] of current) {
|
|
48
|
+
const old = previous.get(token);
|
|
49
|
+
if (old === void 0) {
|
|
50
|
+
changes.push({ type: "insert", row: next.row, index: next.index });
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
if (!sameLiveValue(old.row, next.row)) {
|
|
54
|
+
changes.push({ type: "update", row: next.row, previous: old.row, index: next.index });
|
|
46
55
|
}
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
}
|
|
56
|
-
if (old.index !== next.index) {
|
|
57
|
-
changes.push({
|
|
58
|
-
type: "move",
|
|
59
|
-
key: next.row[key],
|
|
60
|
-
row: next.row,
|
|
61
|
-
from: old.index,
|
|
62
|
-
to: next.index,
|
|
63
|
-
});
|
|
64
|
-
}
|
|
56
|
+
if (old.index !== next.index) {
|
|
57
|
+
changes.push({
|
|
58
|
+
type: "move",
|
|
59
|
+
key: next.row[key],
|
|
60
|
+
row: next.row,
|
|
61
|
+
from: old.index,
|
|
62
|
+
to: next.index
|
|
63
|
+
});
|
|
65
64
|
}
|
|
66
|
-
|
|
65
|
+
}
|
|
66
|
+
return changes;
|
|
67
67
|
}
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
(!Number.isSafeInteger(options.maxRows) || options.maxRows <= 0)) {
|
|
82
|
-
throw new RangeError("Live query window maxRows must be a positive whole number");
|
|
83
|
-
}
|
|
84
|
-
this.#source = source;
|
|
85
|
-
this.#key = options.key;
|
|
86
|
-
this.#maxRows = options.maxRows;
|
|
68
|
+
class KeyedLiveQuery {
|
|
69
|
+
#source;
|
|
70
|
+
#key;
|
|
71
|
+
#maxRows;
|
|
72
|
+
#listeners = /* @__PURE__ */ new Set();
|
|
73
|
+
#sourceUnsubscribe;
|
|
74
|
+
#rows = [];
|
|
75
|
+
#snapshot = { status: "loading", rows: [] };
|
|
76
|
+
#hasReadySnapshot = false;
|
|
77
|
+
#closed = false;
|
|
78
|
+
constructor(source, options) {
|
|
79
|
+
if (options.maxRows !== void 0 && (!Number.isSafeInteger(options.maxRows) || options.maxRows <= 0)) {
|
|
80
|
+
throw new RangeError("Live query window maxRows must be a positive whole number");
|
|
87
81
|
}
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
return;
|
|
102
|
-
subscribed = false;
|
|
103
|
-
this.#listeners.delete(registered);
|
|
104
|
-
if (this.#listeners.size === 0) {
|
|
105
|
-
this.#sourceUnsubscribe?.();
|
|
106
|
-
this.#sourceUnsubscribe = undefined;
|
|
107
|
-
}
|
|
108
|
-
};
|
|
109
|
-
};
|
|
110
|
-
async refresh() {
|
|
111
|
-
if (this.#closed)
|
|
112
|
-
throw new Error("Keyed live query is closed");
|
|
113
|
-
await this.#source.refresh();
|
|
114
|
-
this.#accept(this.#source.getSnapshot());
|
|
82
|
+
this.#source = source;
|
|
83
|
+
this.#key = options.key;
|
|
84
|
+
this.#maxRows = options.maxRows;
|
|
85
|
+
}
|
|
86
|
+
getSnapshot = () => this.#snapshot;
|
|
87
|
+
subscribe = (listener) => {
|
|
88
|
+
if (this.#closed)
|
|
89
|
+
throw new Error("Keyed live query is closed");
|
|
90
|
+
const registered = () => listener();
|
|
91
|
+
this.#listeners.add(registered);
|
|
92
|
+
if (this.#listeners.size === 1) {
|
|
93
|
+
this.#sourceUnsubscribe = this.#source.subscribe(() => this.#accept(this.#source.getSnapshot()));
|
|
94
|
+
this.#accept(this.#source.getSnapshot());
|
|
115
95
|
}
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
96
|
+
let subscribed = true;
|
|
97
|
+
return () => {
|
|
98
|
+
if (!subscribed)
|
|
99
|
+
return;
|
|
100
|
+
subscribed = false;
|
|
101
|
+
this.#listeners.delete(registered);
|
|
102
|
+
if (this.#listeners.size === 0) {
|
|
120
103
|
this.#sourceUnsubscribe?.();
|
|
121
|
-
this.#sourceUnsubscribe =
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
104
|
+
this.#sourceUnsubscribe = void 0;
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
};
|
|
108
|
+
async refresh() {
|
|
109
|
+
if (this.#closed)
|
|
110
|
+
throw new Error("Keyed live query is closed");
|
|
111
|
+
await this.#source.refresh();
|
|
112
|
+
this.#accept(this.#source.getSnapshot());
|
|
113
|
+
}
|
|
114
|
+
close() {
|
|
115
|
+
if (this.#closed)
|
|
116
|
+
return;
|
|
117
|
+
this.#closed = true;
|
|
118
|
+
this.#sourceUnsubscribe?.();
|
|
119
|
+
this.#sourceUnsubscribe = void 0;
|
|
120
|
+
this.#source.close();
|
|
121
|
+
this.#emit();
|
|
122
|
+
this.#listeners.clear();
|
|
123
|
+
}
|
|
124
|
+
#accept(snapshot) {
|
|
125
|
+
if (this.#closed)
|
|
126
|
+
return;
|
|
127
|
+
if (snapshot.status === "loading") {
|
|
128
|
+
if (this.#snapshot.status === "loading")
|
|
129
|
+
return;
|
|
130
|
+
this.#snapshot = { status: "loading", rows: this.#rows };
|
|
131
|
+
this.#emit();
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
if (snapshot.status === "error") {
|
|
135
|
+
this.#snapshot = {
|
|
136
|
+
status: "error",
|
|
137
|
+
rows: this.#rows,
|
|
138
|
+
error: snapshot.error,
|
|
139
|
+
version: snapshot.version
|
|
140
|
+
};
|
|
141
|
+
this.#emit();
|
|
142
|
+
return;
|
|
125
143
|
}
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
}
|
|
157
|
-
else {
|
|
158
|
-
// diffRows builds each old/new key index exactly once and validates duplicates as it goes.
|
|
159
|
-
changes = diffRows(this.#rows, snapshot.rows, this.#key);
|
|
160
|
-
}
|
|
161
|
-
this.#rows = snapshot.rows;
|
|
162
|
-
this.#hasReadySnapshot = true;
|
|
163
|
-
this.#snapshot = {
|
|
164
|
-
status: "ready",
|
|
165
|
-
rows: snapshot.rows,
|
|
166
|
-
changes: Object.freeze(changes),
|
|
167
|
-
initial,
|
|
168
|
-
version: snapshot.version,
|
|
169
|
-
};
|
|
170
|
-
this.#emit();
|
|
171
|
-
}
|
|
172
|
-
catch (error) {
|
|
173
|
-
this.#snapshot = {
|
|
174
|
-
status: "error",
|
|
175
|
-
rows: this.#rows,
|
|
176
|
-
error,
|
|
177
|
-
version: snapshot.version,
|
|
178
|
-
};
|
|
179
|
-
this.#emit();
|
|
180
|
-
}
|
|
144
|
+
try {
|
|
145
|
+
if (this.#maxRows !== void 0 && snapshot.rows.length > this.#maxRows) {
|
|
146
|
+
throw new RangeError(`Live query window returned ${String(snapshot.rows.length)} rows; maximum is ${String(this.#maxRows)}`);
|
|
147
|
+
}
|
|
148
|
+
const initial = !this.#hasReadySnapshot;
|
|
149
|
+
let changes;
|
|
150
|
+
if (initial) {
|
|
151
|
+
indexRows(snapshot.rows, this.#key);
|
|
152
|
+
changes = snapshot.rows.map((row, index) => ({ type: "insert", row, index }));
|
|
153
|
+
} else {
|
|
154
|
+
changes = diffRows(this.#rows, snapshot.rows, this.#key);
|
|
155
|
+
}
|
|
156
|
+
this.#rows = snapshot.rows;
|
|
157
|
+
this.#hasReadySnapshot = true;
|
|
158
|
+
this.#snapshot = {
|
|
159
|
+
status: "ready",
|
|
160
|
+
rows: snapshot.rows,
|
|
161
|
+
changes: Object.freeze(changes),
|
|
162
|
+
initial,
|
|
163
|
+
version: snapshot.version
|
|
164
|
+
};
|
|
165
|
+
this.#emit();
|
|
166
|
+
} catch (error) {
|
|
167
|
+
this.#snapshot = {
|
|
168
|
+
status: "error",
|
|
169
|
+
rows: this.#rows,
|
|
170
|
+
error,
|
|
171
|
+
version: snapshot.version
|
|
172
|
+
};
|
|
173
|
+
this.#emit();
|
|
181
174
|
}
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
}
|
|
190
|
-
}
|
|
175
|
+
}
|
|
176
|
+
#emit() {
|
|
177
|
+
for (const listener of [...this.#listeners]) {
|
|
178
|
+
try {
|
|
179
|
+
listener();
|
|
180
|
+
} catch {
|
|
181
|
+
}
|
|
191
182
|
}
|
|
183
|
+
}
|
|
192
184
|
}
|
|
185
|
+
export {
|
|
186
|
+
KeyedLiveQuery
|
|
187
|
+
};
|
package/dist/engine/live-api.js
CHANGED
|
@@ -1,42 +1,37 @@
|
|
|
1
1
|
import { dateMilliseconds } from "../date-value.js";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
if (
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
right instanceof Date &&
|
|
14
|
-
Object.is(dateMilliseconds(left), dateMilliseconds(right)));
|
|
15
|
-
}
|
|
16
|
-
if (Array.isArray(left) || Array.isArray(right)) {
|
|
17
|
-
if (!Array.isArray(left) || !Array.isArray(right) || left.length !== right.length)
|
|
18
|
-
return false;
|
|
19
|
-
for (let index = 0; index < left.length; index += 1) {
|
|
20
|
-
if (!sameLiveValue(left[index], right[index]))
|
|
21
|
-
return false;
|
|
22
|
-
}
|
|
23
|
-
return true;
|
|
24
|
-
}
|
|
25
|
-
if (typeof left !== "object" || left === null || typeof right !== "object" || right === null) {
|
|
26
|
-
return false;
|
|
27
|
-
}
|
|
28
|
-
const leftRecord = left;
|
|
29
|
-
const rightRecord = right;
|
|
30
|
-
const leftKeys = Object.keys(leftRecord);
|
|
31
|
-
const rightKeys = Object.keys(rightRecord);
|
|
32
|
-
if (leftKeys.length !== rightKeys.length)
|
|
2
|
+
function sameLiveValue(left, right) {
|
|
3
|
+
if (Object.is(left, right))
|
|
4
|
+
return true;
|
|
5
|
+
if (left instanceof Date || right instanceof Date) {
|
|
6
|
+
return left instanceof Date && right instanceof Date && Object.is(dateMilliseconds(left), dateMilliseconds(right));
|
|
7
|
+
}
|
|
8
|
+
if (Array.isArray(left) || Array.isArray(right)) {
|
|
9
|
+
if (!Array.isArray(left) || !Array.isArray(right) || left.length !== right.length)
|
|
10
|
+
return false;
|
|
11
|
+
for (let index = 0; index < left.length; index += 1) {
|
|
12
|
+
if (!sameLiveValue(left[index], right[index]))
|
|
33
13
|
return false;
|
|
34
|
-
for (let index = 0; index < leftKeys.length; index += 1) {
|
|
35
|
-
const key = leftKeys[index];
|
|
36
|
-
if (key === undefined || key !== rightKeys[index])
|
|
37
|
-
return false;
|
|
38
|
-
if (!sameLiveValue(leftRecord[key], rightRecord[key]))
|
|
39
|
-
return false;
|
|
40
14
|
}
|
|
41
15
|
return true;
|
|
16
|
+
}
|
|
17
|
+
if (typeof left !== "object" || left === null || typeof right !== "object" || right === null) {
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
20
|
+
const leftRecord = left;
|
|
21
|
+
const rightRecord = right;
|
|
22
|
+
const leftKeys = Object.keys(leftRecord);
|
|
23
|
+
const rightKeys = Object.keys(rightRecord);
|
|
24
|
+
if (leftKeys.length !== rightKeys.length)
|
|
25
|
+
return false;
|
|
26
|
+
for (let index = 0; index < leftKeys.length; index += 1) {
|
|
27
|
+
const key = leftKeys[index];
|
|
28
|
+
if (key === void 0 || key !== rightKeys[index])
|
|
29
|
+
return false;
|
|
30
|
+
if (!sameLiveValue(leftRecord[key], rightRecord[key]))
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
return true;
|
|
42
34
|
}
|
|
35
|
+
export {
|
|
36
|
+
sameLiveValue
|
|
37
|
+
};
|