@subsquid/evm-stream 0.0.1-2-0.3887d2
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/lib/index.d.ts +3 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +19 -0
- package/lib/index.js.map +1 -0
- package/lib/query.d.ts +43 -0
- package/lib/query.d.ts.map +1 -0
- package/lib/query.js +148 -0
- package/lib/query.js.map +1 -0
- package/lib/schema.d.ts +210 -0
- package/lib/schema.d.ts.map +1 -0
- package/lib/schema.js +218 -0
- package/lib/schema.js.map +1 -0
- package/lib/source.d.ts +348 -0
- package/lib/source.d.ts.map +1 -0
- package/lib/source.js +193 -0
- package/lib/source.js.map +1 -0
- package/package.json +31 -0
- package/src/index.ts +2 -0
- package/src/query.ts +195 -0
- package/src/schema.ts +263 -0
- package/src/source.ts +261 -0
package/lib/source.js
ADDED
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getBlockValidator = exports.EvmPortalDataSource = void 0;
|
|
4
|
+
exports.mapBlock = mapBlock;
|
|
5
|
+
const util_internal_range_1 = require("@subsquid/util-internal-range");
|
|
6
|
+
const portal_client_1 = require("@subsquid/portal-client");
|
|
7
|
+
const util_internal_1 = require("@subsquid/util-internal");
|
|
8
|
+
const util_internal_validation_1 = require("@subsquid/util-internal-validation");
|
|
9
|
+
const schema_1 = require("./schema");
|
|
10
|
+
const query_1 = require("./query");
|
|
11
|
+
const data_source_1 = require("@subsquid/data-source");
|
|
12
|
+
class EvmPortalDataSource {
|
|
13
|
+
constructor(options) {
|
|
14
|
+
this.portal = typeof options.portal === 'string' ? new portal_client_1.PortalClient({ url: options.portal }) : options.portal;
|
|
15
|
+
this.fields = options.query.fields;
|
|
16
|
+
this.requests = (0, util_internal_range_1.mergeRangeRequests)(options.query.requests, query_1.mergeDataRequests);
|
|
17
|
+
}
|
|
18
|
+
getHeight() {
|
|
19
|
+
return this.portal.getFinalizedHeight();
|
|
20
|
+
}
|
|
21
|
+
getFinalizedHeight() {
|
|
22
|
+
return this.portal.getFinalizedHeight();
|
|
23
|
+
}
|
|
24
|
+
getBlockStream(range, stopOnHead) {
|
|
25
|
+
let fields = getFields(this.fields);
|
|
26
|
+
let requests = (0, util_internal_range_1.applyRangeBound)(this.requests, range);
|
|
27
|
+
let { writable, readable } = new TransformStream({
|
|
28
|
+
transform: async (data, controller) => {
|
|
29
|
+
let blocks = data.map((b) => {
|
|
30
|
+
let block = mapBlock(b, fields);
|
|
31
|
+
Object.defineProperty(block, data_source_1.DataSource.blockRef, {
|
|
32
|
+
value: { hash: block.header.hash, number: block.header.number },
|
|
33
|
+
});
|
|
34
|
+
return block;
|
|
35
|
+
});
|
|
36
|
+
Object.defineProperty(blocks, data_source_1.DataSource.finalizedHead, {
|
|
37
|
+
value: data[portal_client_1.PortalClient.finalizedHead],
|
|
38
|
+
});
|
|
39
|
+
controller.enqueue(blocks);
|
|
40
|
+
},
|
|
41
|
+
});
|
|
42
|
+
const ingest = async () => {
|
|
43
|
+
for (let request of requests) {
|
|
44
|
+
let query = {
|
|
45
|
+
type: 'evm',
|
|
46
|
+
fromBlock: request.range.from,
|
|
47
|
+
toBlock: request.range.to,
|
|
48
|
+
fields,
|
|
49
|
+
...request.request,
|
|
50
|
+
};
|
|
51
|
+
await this.portal.getFinalizedStream(query, { stopOnHead }).pipeTo(writable, {
|
|
52
|
+
preventClose: true,
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
ingest()
|
|
57
|
+
.then(() => writable.close(), (reason) => writable.abort(reason))
|
|
58
|
+
.catch(() => { });
|
|
59
|
+
return readable;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
exports.EvmPortalDataSource = EvmPortalDataSource;
|
|
63
|
+
exports.getBlockValidator = (0, util_internal_1.weakMemo)((fields) => {
|
|
64
|
+
let BlockHeader = (0, util_internal_validation_1.object)((0, schema_1.getBlockHeaderProps)(fields.block, true));
|
|
65
|
+
let Transaction = (0, util_internal_validation_1.object)({
|
|
66
|
+
hash: fields.transaction?.hash ? util_internal_validation_1.BYTES : undefined,
|
|
67
|
+
...(0, schema_1.getTxProps)(fields.transaction, true),
|
|
68
|
+
sighash: fields.transaction?.sighash ? (0, util_internal_validation_1.withDefault)('0x', util_internal_validation_1.BYTES) : undefined,
|
|
69
|
+
...(0, schema_1.getTxReceiptProps)(fields.transaction, true),
|
|
70
|
+
});
|
|
71
|
+
let Log = (0, util_internal_validation_1.object)((0, schema_1.getLogProps)(fields.log, true));
|
|
72
|
+
let Trace = (0, schema_1.getTraceFrameValidator)(fields.trace, true);
|
|
73
|
+
let stateDiffBase = {
|
|
74
|
+
transactionIndex: util_internal_validation_1.NAT,
|
|
75
|
+
address: util_internal_validation_1.BYTES,
|
|
76
|
+
key: util_internal_validation_1.STRING,
|
|
77
|
+
};
|
|
78
|
+
let StateDiff = (0, util_internal_validation_1.taggedUnion)('kind', {
|
|
79
|
+
['=']: (0, util_internal_validation_1.object)({ ...stateDiffBase }),
|
|
80
|
+
['+']: (0, util_internal_validation_1.object)({ ...stateDiffBase, ...(0, schema_1.project)(fields.stateDiff, { next: util_internal_validation_1.BYTES }) }),
|
|
81
|
+
['*']: (0, util_internal_validation_1.object)({ ...stateDiffBase, ...(0, schema_1.project)(fields.stateDiff, { prev: util_internal_validation_1.BYTES, next: util_internal_validation_1.BYTES }) }),
|
|
82
|
+
['-']: (0, util_internal_validation_1.object)({ ...stateDiffBase, ...(0, schema_1.project)(fields.stateDiff, { prev: util_internal_validation_1.BYTES }) }),
|
|
83
|
+
});
|
|
84
|
+
return (0, util_internal_validation_1.object)({
|
|
85
|
+
header: BlockHeader,
|
|
86
|
+
transactions: (0, util_internal_validation_1.withDefault)([], (0, util_internal_validation_1.array)(Transaction)),
|
|
87
|
+
logs: (0, util_internal_validation_1.withDefault)([], (0, util_internal_validation_1.array)(Log)),
|
|
88
|
+
traces: (0, util_internal_validation_1.withDefault)([], (0, util_internal_validation_1.array)(Trace)),
|
|
89
|
+
stateDiffs: (0, util_internal_validation_1.withDefault)([], (0, util_internal_validation_1.array)(StateDiff)),
|
|
90
|
+
});
|
|
91
|
+
});
|
|
92
|
+
function mapBlock(rawBlock, fields) {
|
|
93
|
+
let validator = (0, exports.getBlockValidator)(fields);
|
|
94
|
+
let block = (0, util_internal_validation_1.cast)(validator, rawBlock);
|
|
95
|
+
// let {number, hash, parentHash, ...hdr} = src.header
|
|
96
|
+
// if (hdr.timestamp) {
|
|
97
|
+
// hdr.timestamp = hdr.timestamp * 1000 // convert to ms
|
|
98
|
+
// }
|
|
99
|
+
// let header = new BlockHeader(number, hash, parentHash)
|
|
100
|
+
// Object.assign(header, hdr)
|
|
101
|
+
// let block = new Block(header)
|
|
102
|
+
// if (src.transactions) {
|
|
103
|
+
// for (let {transactionIndex, ...props} of src.transactions) {
|
|
104
|
+
// let tx = new Transaction(header, transactionIndex)
|
|
105
|
+
// Object.assign(tx, props)
|
|
106
|
+
// block.transactions.push(tx)
|
|
107
|
+
// }
|
|
108
|
+
// }
|
|
109
|
+
// if (src.logs) {
|
|
110
|
+
// for (let {logIndex, transactionIndex, ...props} of src.logs) {
|
|
111
|
+
// let log = new Log(header, logIndex, transactionIndex)
|
|
112
|
+
// Object.assign(log, props)
|
|
113
|
+
// block.logs.push(log)
|
|
114
|
+
// }
|
|
115
|
+
// }
|
|
116
|
+
// if (src.traces) {
|
|
117
|
+
// for (let {transactionIndex, traceAddress, type, ...props} of src.traces) {
|
|
118
|
+
// transactionIndex = assertNotNull(transactionIndex)
|
|
119
|
+
// let trace: Trace
|
|
120
|
+
// switch (type) {
|
|
121
|
+
// case 'create':
|
|
122
|
+
// trace = new TraceCreate(header, transactionIndex, traceAddress)
|
|
123
|
+
// break
|
|
124
|
+
// case 'call':
|
|
125
|
+
// trace = new TraceCall(header, transactionIndex, traceAddress)
|
|
126
|
+
// break
|
|
127
|
+
// case 'suicide':
|
|
128
|
+
// trace = new TraceSuicide(header, transactionIndex, traceAddress)
|
|
129
|
+
// break
|
|
130
|
+
// case 'reward':
|
|
131
|
+
// trace = new TraceReward(header, transactionIndex, traceAddress)
|
|
132
|
+
// break
|
|
133
|
+
// default:
|
|
134
|
+
// throw unexpectedCase()
|
|
135
|
+
// }
|
|
136
|
+
// Object.assign(trace, props)
|
|
137
|
+
// block.traces.push(trace)
|
|
138
|
+
// }
|
|
139
|
+
// }
|
|
140
|
+
// if (src.stateDiffs) {
|
|
141
|
+
// for (let {transactionIndex, address, key, kind, ...props} of src.stateDiffs) {
|
|
142
|
+
// let diff: StateDiff
|
|
143
|
+
// switch (kind) {
|
|
144
|
+
// case '=':
|
|
145
|
+
// diff = new StateDiffNoChange(header, transactionIndex, address, key)
|
|
146
|
+
// break
|
|
147
|
+
// case '+':
|
|
148
|
+
// diff = new StateDiffAdd(header, transactionIndex, address, key)
|
|
149
|
+
// break
|
|
150
|
+
// case '*':
|
|
151
|
+
// diff = new StateDiffChange(header, transactionIndex, address, key)
|
|
152
|
+
// break
|
|
153
|
+
// case '-':
|
|
154
|
+
// diff = new StateDiffDelete(header, transactionIndex, address, key)
|
|
155
|
+
// break
|
|
156
|
+
// default:
|
|
157
|
+
// throw unexpectedCase()
|
|
158
|
+
// }
|
|
159
|
+
// Object.assign(diff, props)
|
|
160
|
+
// block.stateDiffs.push(diff)
|
|
161
|
+
// }
|
|
162
|
+
// }
|
|
163
|
+
// setUpRelations(block)
|
|
164
|
+
return block;
|
|
165
|
+
}
|
|
166
|
+
function getFields(fields) {
|
|
167
|
+
return (0, query_1.mergeSelection)(REQUIRED_FIELDS, fields);
|
|
168
|
+
}
|
|
169
|
+
const REQUIRED_FIELDS = {
|
|
170
|
+
block: {
|
|
171
|
+
number: true,
|
|
172
|
+
hash: true,
|
|
173
|
+
parentHash: true,
|
|
174
|
+
},
|
|
175
|
+
// transaction: {
|
|
176
|
+
// transactionIndex: true,
|
|
177
|
+
// },
|
|
178
|
+
// log: {
|
|
179
|
+
// logIndex: true,
|
|
180
|
+
// transactionIndex: true,
|
|
181
|
+
// },
|
|
182
|
+
// trace: {
|
|
183
|
+
// transactionIndex: true,
|
|
184
|
+
// traceAddress: true,
|
|
185
|
+
// type: true,
|
|
186
|
+
// },
|
|
187
|
+
// stateDiff: {
|
|
188
|
+
// transactionIndex: true,
|
|
189
|
+
// address: true,
|
|
190
|
+
// key: true,
|
|
191
|
+
// },
|
|
192
|
+
};
|
|
193
|
+
//# sourceMappingURL=source.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"source.js","sourceRoot":"","sources":["../src/source.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@subsquid/evm-stream",
|
|
3
|
+
"version": "0.0.1-2-0.3887d2",
|
|
4
|
+
"description": "EVM block data streamer",
|
|
5
|
+
"license": "GPL-3.0-or-later",
|
|
6
|
+
"repository": "git@github.com:subsquid/squid.git",
|
|
7
|
+
"publishConfig": {
|
|
8
|
+
"access": "public"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"lib",
|
|
12
|
+
"src"
|
|
13
|
+
],
|
|
14
|
+
"main": "lib/index.js",
|
|
15
|
+
"dependencies": {
|
|
16
|
+
"@subsquid/logger": "^1.3.3",
|
|
17
|
+
"@subsquid/portal-client": "0.1.0-2-0.3887d2",
|
|
18
|
+
"@subsquid/util-internal": "3.3.0-2-0.3887d2",
|
|
19
|
+
"@subsquid/util-internal-range": "~0.3.0",
|
|
20
|
+
"@subsquid/http-client": "1.7.0-2-0.3887d2",
|
|
21
|
+
"@subsquid/util-internal-validation": "~0.7.0",
|
|
22
|
+
"@subsquid/data-source": "0.0.1-2-0.3887d2"
|
|
23
|
+
},
|
|
24
|
+
"devDependencies": {
|
|
25
|
+
"@types/node": "^18.18.14",
|
|
26
|
+
"typescript": "~5.5.4"
|
|
27
|
+
},
|
|
28
|
+
"scripts": {
|
|
29
|
+
"build": "rm -rf lib && tsc"
|
|
30
|
+
}
|
|
31
|
+
}
|
package/src/index.ts
ADDED
package/src/query.ts
ADDED
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
import {applyRangeBound, mergeRangeRequests, Range, RangeRequest} from '@subsquid/util-internal-range'
|
|
2
|
+
import type {Evm} from '@subsquid/portal-client'
|
|
3
|
+
import type {MergeSelection, MergeSelectionAll, Selection} from '@subsquid/util-internal'
|
|
4
|
+
|
|
5
|
+
export * from '@subsquid/portal-client/lib/query/evm'
|
|
6
|
+
|
|
7
|
+
export type RequestOptions<R> = {range?: Range; request: R}
|
|
8
|
+
export type LogRequestOptions = RequestOptions<Evm.LogRequest>
|
|
9
|
+
export type TransactionRequestOptions = RequestOptions<Evm.TransactionRequest>
|
|
10
|
+
export type TraceRequestOptions = RequestOptions<Evm.TraceRequest>
|
|
11
|
+
export type StateDiffRequestOptions = RequestOptions<Evm.StateDiffRequest>
|
|
12
|
+
|
|
13
|
+
export type EvmQueryOptions<F extends Evm.FieldSelection = Evm.FieldSelection> = {
|
|
14
|
+
fields: F
|
|
15
|
+
requests: RangeRequest<Evm.DataRequest>[]
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export class EvmQueryBuilder<F extends Evm.FieldSelection = {block: {number: true; hash: true}}> {
|
|
19
|
+
private range: Range = {from: 0}
|
|
20
|
+
private requests: RangeRequest<Evm.DataRequest>[] = []
|
|
21
|
+
private fields: F = {
|
|
22
|
+
block: {number: true, hash: true},
|
|
23
|
+
} as F
|
|
24
|
+
|
|
25
|
+
addLog(options: LogRequestOptions): this {
|
|
26
|
+
this.requests.push({
|
|
27
|
+
range: options.range ?? {from: 0},
|
|
28
|
+
request: {
|
|
29
|
+
logs: [mapRequest(options)],
|
|
30
|
+
},
|
|
31
|
+
})
|
|
32
|
+
return this
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
addTransaction(options: TransactionRequestOptions): this {
|
|
36
|
+
this.requests.push({
|
|
37
|
+
range: options.range ?? {from: 0},
|
|
38
|
+
request: {
|
|
39
|
+
transactions: [mapRequest(options)],
|
|
40
|
+
},
|
|
41
|
+
})
|
|
42
|
+
return this
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
addTrace(options: TraceRequestOptions): this {
|
|
46
|
+
this.requests.push({
|
|
47
|
+
range: options.range ?? {from: 0},
|
|
48
|
+
request: {
|
|
49
|
+
traces: [mapRequest(options)],
|
|
50
|
+
},
|
|
51
|
+
})
|
|
52
|
+
return this
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
addStateDiff(options: StateDiffRequestOptions): this {
|
|
56
|
+
this.requests.push({
|
|
57
|
+
range: options.range ?? {from: 0},
|
|
58
|
+
request: {
|
|
59
|
+
stateDiffs: [mapRequest(options)],
|
|
60
|
+
},
|
|
61
|
+
})
|
|
62
|
+
return this
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
setRange(range: Range): this {
|
|
66
|
+
this.range = range
|
|
67
|
+
return this
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
setFields<F extends Evm.FieldSelection>(fields: F): EvmQueryBuilder<F> {
|
|
71
|
+
this.fields = fields as any
|
|
72
|
+
return this as any
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
build(): EvmQueryOptions<F> {
|
|
76
|
+
let requests = mergeRangeRequests(this.requests, mergeDataRequests)
|
|
77
|
+
|
|
78
|
+
return {
|
|
79
|
+
fields: this.fields,
|
|
80
|
+
requests: applyRangeBound(requests, this.range),
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export function mergeDataRequests(...requests: Evm.DataRequest[]): Evm.DataRequest {
|
|
86
|
+
let res: Evm.DataRequest = {}
|
|
87
|
+
|
|
88
|
+
for (let req of requests) {
|
|
89
|
+
res.transactions = concatRequestLists(res.transactions, req.transactions)
|
|
90
|
+
res.logs = concatRequestLists(res.logs, req.logs)
|
|
91
|
+
res.traces = concatRequestLists(res.traces, req.traces)
|
|
92
|
+
res.stateDiffs = concatRequestLists(res.stateDiffs, req.stateDiffs)
|
|
93
|
+
if (res.includeAllBlocks || req.includeAllBlocks) {
|
|
94
|
+
res.includeAllBlocks = true
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
return res
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export type MergeFieldSelection<T extends Evm.FieldSelection, U extends Evm.FieldSelection> = MergeSelection<T, U>
|
|
102
|
+
|
|
103
|
+
// NOTE: without condition creates ugly type for some reason
|
|
104
|
+
export type MergeQueryOptions<T extends EvmQueryOptions, U extends EvmQueryOptions> = EvmQueryOptions<
|
|
105
|
+
MergeSelection<T['fields'], U['fields']>
|
|
106
|
+
> extends infer R
|
|
107
|
+
? R
|
|
108
|
+
: never
|
|
109
|
+
|
|
110
|
+
export type MergeQueryOptionsAll<T extends readonly EvmQueryOptions[]> = T extends readonly [infer F, ...infer R]
|
|
111
|
+
? F extends EvmQueryOptions
|
|
112
|
+
? R extends [EvmQueryOptions, ...EvmQueryOptions[]]
|
|
113
|
+
? MergeQueryOptions<F, MergeQueryOptionsAll<R>>
|
|
114
|
+
: F
|
|
115
|
+
: never
|
|
116
|
+
: never
|
|
117
|
+
|
|
118
|
+
type Test = MergeQueryOptionsAll<
|
|
119
|
+
[
|
|
120
|
+
EvmQueryOptions<{
|
|
121
|
+
block: {number: true; hash: true}
|
|
122
|
+
transaction: {from: true; to: true; hash: true}
|
|
123
|
+
}>,
|
|
124
|
+
EvmQueryOptions<{block: {number: true; hash: true; difficulty: true}}>,
|
|
125
|
+
EvmQueryOptions<{block: {number: true; hash: true; nonce: true}}>
|
|
126
|
+
]
|
|
127
|
+
>
|
|
128
|
+
|
|
129
|
+
export function mergeRequests(...requests: RangeRequest<Evm.DataRequest>[]): RangeRequest<Evm.DataRequest>[] {
|
|
130
|
+
return mergeRangeRequests(requests, mergeDataRequests)
|
|
131
|
+
}
|
|
132
|
+
export function mergeQueries<T extends EvmQueryOptions, U extends EvmQueryOptions>(a: T, b: U): MergeQueryOptions<T, U>
|
|
133
|
+
export function mergeQueries<T extends readonly EvmQueryOptions[]>(...queries: T): MergeQueryOptionsAll<T>
|
|
134
|
+
export function mergeQueries<T extends readonly EvmQueryOptions[]>(...queries: T) {
|
|
135
|
+
return {
|
|
136
|
+
fields: mergeSelection(...queries.map((q) => q.fields)),
|
|
137
|
+
requests: mergeRequests(...queries.flatMap((q) => q.requests)),
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
let test = mergeQueries(
|
|
142
|
+
{} as EvmQueryOptions<{
|
|
143
|
+
block: {number: true; hash: true}
|
|
144
|
+
transaction: {from: true; to: true; hash: true}
|
|
145
|
+
}>,
|
|
146
|
+
{} as EvmQueryOptions<{
|
|
147
|
+
transaction: {from: true}
|
|
148
|
+
block: {number: true; hash: true; difficulty: true}
|
|
149
|
+
}>,
|
|
150
|
+
{} as EvmQueryOptions<{block: {number: true; hash: true; nonce: true}}>
|
|
151
|
+
)
|
|
152
|
+
|
|
153
|
+
function concatRequestLists<T extends object>(a?: T[], b?: T[]): T[] | undefined {
|
|
154
|
+
let result: T[] = []
|
|
155
|
+
if (a) {
|
|
156
|
+
result.push(...a)
|
|
157
|
+
}
|
|
158
|
+
if (b) {
|
|
159
|
+
result.push(...b)
|
|
160
|
+
}
|
|
161
|
+
return result.length == 0 ? undefined : result
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
function mapRequest<T>(options: RequestOptions<T>): T {
|
|
165
|
+
let req = {...options.request}
|
|
166
|
+
for (let key in req) {
|
|
167
|
+
let val = (req as any)[key]
|
|
168
|
+
if (Array.isArray(val)) {
|
|
169
|
+
;(req as any)[key] = val.map((s) => {
|
|
170
|
+
return typeof s == 'string' ? s.toLowerCase() : s
|
|
171
|
+
})
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
return req
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
export function mergeSelection<T extends Selection, U extends Selection>(a: T, b: U): MergeSelection<T, U>
|
|
178
|
+
export function mergeSelection<T extends readonly Selection[]>(...selections: T): MergeSelectionAll<T>
|
|
179
|
+
export function mergeSelection<T extends readonly Selection[]>(...selections: T) {
|
|
180
|
+
let res: Selection = {}
|
|
181
|
+
|
|
182
|
+
for (let selection of selections) {
|
|
183
|
+
for (let key in selection) {
|
|
184
|
+
if (res[key] == null) {
|
|
185
|
+
res[key] = selection[key]
|
|
186
|
+
} else if (res[key] === true || selection[key] === true) {
|
|
187
|
+
res[key] === true
|
|
188
|
+
} else if (typeof res[key] === 'object' && typeof selection[key] === 'object') {
|
|
189
|
+
res[key] = mergeSelection(res[key], selection[key])
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
return res
|
|
195
|
+
}
|