@interop/edv-client 17.0.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/LICENSE +27 -0
- package/README.md +276 -0
- package/dist/EdvClient.d.ts +412 -0
- package/dist/EdvClient.d.ts.map +1 -0
- package/dist/EdvClient.js +663 -0
- package/dist/EdvClient.js.map +1 -0
- package/dist/EdvClientCore.d.ts +264 -0
- package/dist/EdvClientCore.d.ts.map +1 -0
- package/dist/EdvClientCore.js +698 -0
- package/dist/EdvClientCore.js.map +1 -0
- package/dist/EdvDocument.d.ts +92 -0
- package/dist/EdvDocument.d.ts.map +1 -0
- package/dist/EdvDocument.js +149 -0
- package/dist/EdvDocument.js.map +1 -0
- package/dist/HttpsTransport.d.ts +87 -0
- package/dist/HttpsTransport.d.ts.map +1 -0
- package/dist/HttpsTransport.js +415 -0
- package/dist/HttpsTransport.js.map +1 -0
- package/dist/IndexHelper.d.ts +163 -0
- package/dist/IndexHelper.d.ts.map +1 -0
- package/dist/IndexHelper.js +539 -0
- package/dist/IndexHelper.js.map +1 -0
- package/dist/LegacyIndexHelperVersion1.d.ts +150 -0
- package/dist/LegacyIndexHelperVersion1.d.ts.map +1 -0
- package/dist/LegacyIndexHelperVersion1.js +475 -0
- package/dist/LegacyIndexHelperVersion1.js.map +1 -0
- package/dist/Transport.d.ts +142 -0
- package/dist/Transport.d.ts.map +1 -0
- package/dist/Transport.js +181 -0
- package/dist/Transport.js.map +1 -0
- package/dist/assert.d.ts +6 -0
- package/dist/assert.d.ts.map +1 -0
- package/dist/assert.js +61 -0
- package/dist/assert.js.map +1 -0
- package/dist/baseX.d.ts +7 -0
- package/dist/baseX.d.ts.map +1 -0
- package/dist/baseX.js +8 -0
- package/dist/baseX.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -0
- package/dist/util.d.ts +3 -0
- package/dist/util.d.ts.map +1 -0
- package/dist/util.js +13 -0
- package/dist/util.js.map +1 -0
- package/package.json +112 -0
|
@@ -0,0 +1,539 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) 2019-2023 Digital Bazaar, Inc. All rights reserved.
|
|
3
|
+
*/
|
|
4
|
+
import { base64url } from './baseX.js';
|
|
5
|
+
import canonicalize from 'canonicalize';
|
|
6
|
+
import { LruCache } from '@interop/lru-memoize';
|
|
7
|
+
import { sha256 } from './util.js';
|
|
8
|
+
import split from 'split-string';
|
|
9
|
+
const ATTRIBUTE_PREFIXES = ['content', 'meta'];
|
|
10
|
+
export class IndexHelper {
|
|
11
|
+
indexes;
|
|
12
|
+
compoundIndexes;
|
|
13
|
+
_cache;
|
|
14
|
+
/**
|
|
15
|
+
* Creates a new IndexHelper instance that can be used to blind EDV
|
|
16
|
+
* document attributes to enable indexing.
|
|
17
|
+
*
|
|
18
|
+
* @returns {IndexHelper} An IndexHelper instance.
|
|
19
|
+
*/
|
|
20
|
+
constructor() {
|
|
21
|
+
this.indexes = new Map();
|
|
22
|
+
this.compoundIndexes = new Map();
|
|
23
|
+
this._cache = new LruCache({
|
|
24
|
+
// each entry size ~64 bytes, 1000 entries ~= 64KiB
|
|
25
|
+
max: 1000
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Ensures that future documents inserted or updated using this client
|
|
30
|
+
* instance will be indexed according to the given attribute, provided that
|
|
31
|
+
* they contain that attribute. Compound indexes can be specified by
|
|
32
|
+
* providing an array for `attribute`.
|
|
33
|
+
*
|
|
34
|
+
* Queries may be performed using compound indexes without specifying all
|
|
35
|
+
* attributes in the compound index so long as there is at least one value
|
|
36
|
+
* (or the attribute name for "has" queries) specified for consecutive
|
|
37
|
+
* attributes starting with the first. This allows for querying using only
|
|
38
|
+
* a prefix of a compound index. However, uniqueness will not be enforced
|
|
39
|
+
* unless all attributes in the compound index are present in a document.
|
|
40
|
+
*
|
|
41
|
+
* @param {object} options - The options to use.
|
|
42
|
+
* @param {string|string[]} options.attribute - The attribute name or an
|
|
43
|
+
* array of attribute names to create a unique compound index.
|
|
44
|
+
* @param {boolean} [options.unique=false] - Set to `true` if the index
|
|
45
|
+
* should be considered unique, `false` if not.
|
|
46
|
+
* @param {object} [options.hmac] - An optional HMAC API with `id`, `sign`,
|
|
47
|
+
* and `verify` properties for prewarming caches.
|
|
48
|
+
*/
|
|
49
|
+
ensureIndex({ attribute, unique = false, hmac } = {}) {
|
|
50
|
+
let attributes = attribute;
|
|
51
|
+
if (!Array.isArray(attribute)) {
|
|
52
|
+
attributes = [attribute];
|
|
53
|
+
}
|
|
54
|
+
if (!(attributes.length > 0 &&
|
|
55
|
+
attributes.every((x) => typeof x === 'string'))) {
|
|
56
|
+
throw new TypeError('"attribute" must be a string or an array of strings.');
|
|
57
|
+
}
|
|
58
|
+
if (attributes.length === 1) {
|
|
59
|
+
// add simple index
|
|
60
|
+
this.indexes.set(attributes[0], unique);
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
// add compound index
|
|
64
|
+
const key = attributes.map((x) => encodeURIComponent(x)).join('|');
|
|
65
|
+
this.compoundIndexes.set(key, { attributes, unique });
|
|
66
|
+
}
|
|
67
|
+
if (hmac) {
|
|
68
|
+
_assertHmac(hmac);
|
|
69
|
+
// ignore errors during prewarm; they are not fatal
|
|
70
|
+
this._prewarmCache({ attributes, hmac }).catch(() => { });
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Creates an indexable entry of blinded attributes for the given document
|
|
75
|
+
* using the HMAC associated with this instance.
|
|
76
|
+
*
|
|
77
|
+
* @param {object} options - The options to use.
|
|
78
|
+
* @param {object} options.hmac - An HMAC API with `id`, `sign`, and `verify`
|
|
79
|
+
* properties.
|
|
80
|
+
* @param {object} options.doc - The document to create the indexable entry
|
|
81
|
+
* for.
|
|
82
|
+
*
|
|
83
|
+
* @returns {Promise<object>} - Resolves to the new indexable entry.
|
|
84
|
+
*/
|
|
85
|
+
async createEntry({ hmac, doc }) {
|
|
86
|
+
_assertHmac(hmac);
|
|
87
|
+
const entry = {
|
|
88
|
+
hmac: {
|
|
89
|
+
id: hmac.id,
|
|
90
|
+
type: hmac.type
|
|
91
|
+
},
|
|
92
|
+
sequence: doc.sequence,
|
|
93
|
+
attributes: await this._buildBlindAttributes({ hmac, doc })
|
|
94
|
+
};
|
|
95
|
+
return entry;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Returns a shallow copy of the array of indexed entries for the given
|
|
99
|
+
* document where any existing entry matching the HMAC associated with this
|
|
100
|
+
* instance is updated to include the current document attributes. If no
|
|
101
|
+
* existing entry is found, a new entry is appended to the shallow copy
|
|
102
|
+
* prior to its return.
|
|
103
|
+
*
|
|
104
|
+
* @param {object} options - The options to use.
|
|
105
|
+
* @param {object} options.hmac - An HMAC API with `id`, `sign`, and `verify`
|
|
106
|
+
* properties.
|
|
107
|
+
* @param {object} options.doc - The document to create or update an indexable
|
|
108
|
+
* entry for.
|
|
109
|
+
*
|
|
110
|
+
* @returns {Promise<Array>} - Resolves to the updated array of indexable
|
|
111
|
+
* entries.
|
|
112
|
+
*/
|
|
113
|
+
async updateEntry({ hmac, doc }) {
|
|
114
|
+
_assertHmac(hmac);
|
|
115
|
+
// get previously indexed entries to update
|
|
116
|
+
let { indexed = [] } = doc;
|
|
117
|
+
if (!Array.isArray(indexed)) {
|
|
118
|
+
throw new TypeError('"indexed" must be an array.');
|
|
119
|
+
}
|
|
120
|
+
// create new entry
|
|
121
|
+
const entry = await this.createEntry({ hmac, doc });
|
|
122
|
+
// find existing entry in `indexed` by hmac ID and type
|
|
123
|
+
const i = indexed.findIndex((e) => e.hmac.id === hmac.id && e.hmac.type === hmac.type);
|
|
124
|
+
// replace or append new entry
|
|
125
|
+
indexed = indexed.slice();
|
|
126
|
+
if (i === -1) {
|
|
127
|
+
indexed.push(entry);
|
|
128
|
+
}
|
|
129
|
+
else {
|
|
130
|
+
indexed[i] = entry;
|
|
131
|
+
}
|
|
132
|
+
return indexed;
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Builds a query that can be submitted to an EDV index service.
|
|
136
|
+
*
|
|
137
|
+
* @param {object} options - The options to use.
|
|
138
|
+
* @param {object} options.hmac - An HMAC API with `id`, `sign`, and `verify`
|
|
139
|
+
* properties.
|
|
140
|
+
* @param {object|Array} [options.equals] - An object with key-value
|
|
141
|
+
* attribute pairs to match or an array of such objects.
|
|
142
|
+
* @param {string|Array} [options.has] - A string with an attribute name to
|
|
143
|
+
* match or an array of such strings.
|
|
144
|
+
*
|
|
145
|
+
* @returns {Promise<object>} - Resolves to the built query.
|
|
146
|
+
*/
|
|
147
|
+
async buildQuery({ hmac, equals, has }) {
|
|
148
|
+
_assertHmac(hmac);
|
|
149
|
+
// validate params
|
|
150
|
+
if (equals === undefined && has === undefined) {
|
|
151
|
+
throw new Error('Either "equals" or "has" must be defined.');
|
|
152
|
+
}
|
|
153
|
+
if (equals !== undefined && has !== undefined) {
|
|
154
|
+
throw new Error('Only one of "equals" or "has" may be defined at once.');
|
|
155
|
+
}
|
|
156
|
+
if (equals !== undefined) {
|
|
157
|
+
if (Array.isArray(equals)) {
|
|
158
|
+
if (!equals.every((x) => x && typeof x === 'object')) {
|
|
159
|
+
throw new TypeError('"equals" must be an array of objects.');
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
else if (!(equals && typeof equals === 'object')) {
|
|
163
|
+
throw new TypeError('"equals" must be an object or an array of objects.');
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
if (has !== undefined) {
|
|
167
|
+
if (Array.isArray(has)) {
|
|
168
|
+
if (!has.every((x) => x && typeof x === 'string')) {
|
|
169
|
+
throw new TypeError('"has" must be an array of strings.');
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
else if (typeof has !== 'string') {
|
|
173
|
+
throw new TypeError('"has" must be a string or an array of strings.');
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
const query = {
|
|
177
|
+
index: hmac.id
|
|
178
|
+
};
|
|
179
|
+
if (equals) {
|
|
180
|
+
// normalize to array
|
|
181
|
+
if (!Array.isArray(equals)) {
|
|
182
|
+
equals = [equals];
|
|
183
|
+
}
|
|
184
|
+
// blind all values in each `equal`
|
|
185
|
+
query.equals = await Promise.all(equals.map(async (equal) => {
|
|
186
|
+
const result = {};
|
|
187
|
+
const blinded = await this._buildBlindAttributes({ hmac, equal });
|
|
188
|
+
for (const { name, value } of blinded) {
|
|
189
|
+
result[name] = value;
|
|
190
|
+
}
|
|
191
|
+
return result;
|
|
192
|
+
}));
|
|
193
|
+
}
|
|
194
|
+
else if (has !== undefined) {
|
|
195
|
+
// normalize to array
|
|
196
|
+
if (!Array.isArray(has)) {
|
|
197
|
+
has = [has];
|
|
198
|
+
}
|
|
199
|
+
// blind every attribute name in `has`
|
|
200
|
+
query.has = (await this._buildBlindAttributes({ hmac, has })).map(({ name }) => name);
|
|
201
|
+
}
|
|
202
|
+
return query;
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Blinds a Uint8Array of bytes using the given HMAC API.
|
|
206
|
+
*
|
|
207
|
+
* @param {object} hmac - An HMAC API with `id`, `sign`, and `verify`
|
|
208
|
+
* properties.
|
|
209
|
+
* @param {Uint8Array} data - The value to blind.
|
|
210
|
+
*
|
|
211
|
+
* @returns {Promise<string>} - Resolves to the blinded value.
|
|
212
|
+
*/
|
|
213
|
+
async _blindData(hmac, data) {
|
|
214
|
+
// convert value to Uint8Array and hash it
|
|
215
|
+
const signature = await this._cachedHmac({ hmac, data });
|
|
216
|
+
if (typeof signature === 'string') {
|
|
217
|
+
// presume base64url-encoded
|
|
218
|
+
return signature;
|
|
219
|
+
}
|
|
220
|
+
// base64url-encode Uint8Array signature
|
|
221
|
+
return base64url.encode(signature);
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* Blinds a hashed attribute (compound or simple) using the given HMAC API.
|
|
225
|
+
*
|
|
226
|
+
* @param {object} options - The options to use.
|
|
227
|
+
* @param {object} options.hmac - An HMAC API with `id`, `sign`, and `verify`
|
|
228
|
+
* properties.
|
|
229
|
+
* @param {object} options.hashedAttribute - The attribute with `name`,
|
|
230
|
+
* `value`, and optional `unique` property; `name` and `value` MUST be
|
|
231
|
+
* Uint8Arrays.
|
|
232
|
+
*
|
|
233
|
+
* @returns {Promise<object>} - Resolves to an object
|
|
234
|
+
* `{name, value, unique?}`.
|
|
235
|
+
*/
|
|
236
|
+
async _blindHashedAttribute({ hmac, hashedAttribute }) {
|
|
237
|
+
// salt values with key to prevent cross-key leakage
|
|
238
|
+
const saltedValue = await sha256(_joinHashes([hashedAttribute.name, hashedAttribute.value]));
|
|
239
|
+
const [name, value] = await Promise.all([
|
|
240
|
+
this._blindData(hmac, hashedAttribute.name),
|
|
241
|
+
this._blindData(hmac, saltedValue)
|
|
242
|
+
]);
|
|
243
|
+
const blindAttribute = { name, value };
|
|
244
|
+
if (hashedAttribute.unique) {
|
|
245
|
+
blindAttribute.unique = true;
|
|
246
|
+
}
|
|
247
|
+
return blindAttribute;
|
|
248
|
+
}
|
|
249
|
+
async _buildBlindAttributes({ hmac, doc, equal, has }) {
|
|
250
|
+
const hashedAttributes = [];
|
|
251
|
+
// get all matching indexes and corresponding attribute values
|
|
252
|
+
const { simpleMatches, compoundMatches, attributeValues } = this._getMatchingIndexes({ doc, equal, has });
|
|
253
|
+
// compute and store all hashed attributes in parallel
|
|
254
|
+
const hashedAttributeMap = new Map();
|
|
255
|
+
const hashPromises = [];
|
|
256
|
+
for (const [name, valueSet] of attributeValues.entries()) {
|
|
257
|
+
// create a hashed set for each attribute name; it will hold the
|
|
258
|
+
// hashed attribute associated with each name+value pair
|
|
259
|
+
const hashedSet = new Set();
|
|
260
|
+
hashedAttributeMap.set(name, hashedSet);
|
|
261
|
+
for (const value of valueSet) {
|
|
262
|
+
// use an IIFE to push a promise onto `hashPromises` to await all
|
|
263
|
+
// promises in parallel and within IIFE add the resolved hashed
|
|
264
|
+
// attribute to the current attribute's `hashedSet`
|
|
265
|
+
hashPromises.push((async () => {
|
|
266
|
+
hashedSet.add(await this._hashAttribute({ hmac, name, value }));
|
|
267
|
+
})());
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
await Promise.all(hashPromises);
|
|
271
|
+
// add all matching simple index hashed attributes and track simple
|
|
272
|
+
// attributes to avoid duplicating entries when processing compound
|
|
273
|
+
// indexes
|
|
274
|
+
const simpleAttributes = new Set();
|
|
275
|
+
for (const { attribute: name, unique } of simpleMatches) {
|
|
276
|
+
const hashedSet = hashedAttributeMap.get(name);
|
|
277
|
+
for (const hashed of hashedSet) {
|
|
278
|
+
hashedAttributes.push({ ...hashed, unique });
|
|
279
|
+
}
|
|
280
|
+
simpleAttributes.add(name);
|
|
281
|
+
}
|
|
282
|
+
// compute and add all matching compound index hashed attributes
|
|
283
|
+
const compoundPromises = [];
|
|
284
|
+
for (const { attributes: names, unique } of compoundMatches) {
|
|
285
|
+
/* Note: For each matching index, there are some number of matching
|
|
286
|
+
attributes that need to be combinatorially spread. For example, for this
|
|
287
|
+
index: `['content.a', 'content.b', 'content.c']`, there may be multiple
|
|
288
|
+
values for each attribute such as `A` values for `content.a`, `B` values
|
|
289
|
+
for `content.b`, and `C` values for `content.c`. Each combination these
|
|
290
|
+
values will ultimately produce a new blinded attribute to add to `entry`.
|
|
291
|
+
Combinations must also include partial ones, e.g., combinations of
|
|
292
|
+
values for `content.a` alone as well as values for `content.a` and
|
|
293
|
+
`content.b` without `content.c`. */
|
|
294
|
+
const combinations = [];
|
|
295
|
+
let previous = [[]];
|
|
296
|
+
for (const name of names) {
|
|
297
|
+
const hashedSet = hashedAttributeMap.get(name);
|
|
298
|
+
if (!hashedSet) {
|
|
299
|
+
// no values for current attribute name; no more entries to produce
|
|
300
|
+
break;
|
|
301
|
+
}
|
|
302
|
+
// produce a new combination for every `hashed` value and every
|
|
303
|
+
// combination from the previous attribute
|
|
304
|
+
const next = [];
|
|
305
|
+
for (const hashed of hashedSet) {
|
|
306
|
+
for (const combination of previous) {
|
|
307
|
+
next.push([...combination, hashed]);
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
combinations.push(...next);
|
|
311
|
+
previous = next;
|
|
312
|
+
}
|
|
313
|
+
// now generate entries from every combination
|
|
314
|
+
for (const combination of combinations) {
|
|
315
|
+
// skip generating an entry for this combination if it has just the
|
|
316
|
+
// first attribute and an entry for it was already added
|
|
317
|
+
if (combination.length === 1 && simpleAttributes.has(names[0])) {
|
|
318
|
+
continue;
|
|
319
|
+
}
|
|
320
|
+
// use an IIFE to push a promise onto `compoundPromises` to await all
|
|
321
|
+
// promises in parallel and within IIFE return hashed attribute to
|
|
322
|
+
// blind and add to `entry` below
|
|
323
|
+
compoundPromises.push((async () => {
|
|
324
|
+
const attribute = await this._hashCompoundAttribute({
|
|
325
|
+
hashedAttributes: combination
|
|
326
|
+
});
|
|
327
|
+
// an encrypted attribute is only unique for a compound index when
|
|
328
|
+
// it contains a value for every attribute in the index
|
|
329
|
+
attribute.unique = unique && combination.length === names.length;
|
|
330
|
+
return attribute;
|
|
331
|
+
})());
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
hashedAttributes.push(...(await Promise.all(compoundPromises)));
|
|
335
|
+
// blind all hashed attributes and return them
|
|
336
|
+
return Promise.all(hashedAttributes.map(async (hashedAttribute) => this._blindHashedAttribute({ hmac, hashedAttribute })));
|
|
337
|
+
}
|
|
338
|
+
_getMatchingIndexes({ doc, equal, has } = {}) {
|
|
339
|
+
// build a map of `attribute name => set of values` whilst matching
|
|
340
|
+
const attributeValues = new Map();
|
|
341
|
+
let matchFn;
|
|
342
|
+
if (doc) {
|
|
343
|
+
// build a map of `attribute name => set of values` whilst matching
|
|
344
|
+
// against the document
|
|
345
|
+
matchFn = ({ attribute }) => {
|
|
346
|
+
return this._matchDocument({ attribute, attributeValues, doc });
|
|
347
|
+
};
|
|
348
|
+
}
|
|
349
|
+
else {
|
|
350
|
+
// any attribute in `equal` or `has` entry is a match
|
|
351
|
+
let attributes;
|
|
352
|
+
if (equal) {
|
|
353
|
+
attributes = Object.keys(equal);
|
|
354
|
+
for (const [name, value] of Object.entries(equal)) {
|
|
355
|
+
attributeValues.set(name, new Set([value]));
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
else {
|
|
359
|
+
attributes = has;
|
|
360
|
+
for (const name of has) {
|
|
361
|
+
// use dummy value of `true`; values will not be used in a `has`
|
|
362
|
+
// query; note that this could be optimized to avoid the unnecessary
|
|
363
|
+
// blinding of values in the future with more complex code
|
|
364
|
+
attributeValues.set(name, new Set([true]));
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
matchFn = ({ attribute }) => attributes.includes(attribute);
|
|
368
|
+
}
|
|
369
|
+
const result = this._matchIndexes({ matchFn });
|
|
370
|
+
return { ...result, attributeValues };
|
|
371
|
+
}
|
|
372
|
+
/**
|
|
373
|
+
* Hashes a single attribute, converting its name and value into a hashed
|
|
374
|
+
* name and hashed value.
|
|
375
|
+
*
|
|
376
|
+
* @param {object} options - The options to use.
|
|
377
|
+
* @param {string} options.name - A name associated with a value.
|
|
378
|
+
* @param {any} options.value - The value associated with the name for the
|
|
379
|
+
* attribute.
|
|
380
|
+
*
|
|
381
|
+
* @returns {Promise<object>} - Resolves to an object `{name, value}`.
|
|
382
|
+
*/
|
|
383
|
+
async _hashAttribute({ name, value }) {
|
|
384
|
+
// canonicalize value to get consistent representation and hash
|
|
385
|
+
value = canonicalize(value);
|
|
386
|
+
const [hashedName, hashedValue] = await Promise.all([
|
|
387
|
+
_hashString(name),
|
|
388
|
+
_hashString(value)
|
|
389
|
+
]);
|
|
390
|
+
return { name: hashedName, value: hashedValue };
|
|
391
|
+
}
|
|
392
|
+
/**
|
|
393
|
+
* Builds a hashed compound attribute from an array of hashed attributes
|
|
394
|
+
* via the given HMAC API.
|
|
395
|
+
*
|
|
396
|
+
* @param {object} options - The options to use.
|
|
397
|
+
* @param {Array} options.hashedAttributes - The hashed attributes that
|
|
398
|
+
* comprise the compound index.
|
|
399
|
+
* @param {number} [options.length=options.hashedAttributes.length] - The
|
|
400
|
+
* number of hashed attributes to go into the compound attribute
|
|
401
|
+
* (<= `hashedAttributes.length`).
|
|
402
|
+
*
|
|
403
|
+
* @returns {Promise<string>} - Resolves to the hashed compound attribute.
|
|
404
|
+
*/
|
|
405
|
+
async _hashCompoundAttribute({ hashedAttributes, length = hashedAttributes.length }) {
|
|
406
|
+
const selection = length === hashedAttributes.length
|
|
407
|
+
? hashedAttributes
|
|
408
|
+
: hashedAttributes.slice(0, length);
|
|
409
|
+
const nameInput = _joinHashes(selection.map((x) => x.name));
|
|
410
|
+
const valueInput = _joinHashes(selection.map((x) => x.value));
|
|
411
|
+
const [name, value] = await Promise.all([
|
|
412
|
+
sha256(nameInput),
|
|
413
|
+
sha256(valueInput)
|
|
414
|
+
]);
|
|
415
|
+
return { name, value };
|
|
416
|
+
}
|
|
417
|
+
_matchIndexes({ matchFn } = {}) {
|
|
418
|
+
// any simple index that has a value defined for its attribute is a match
|
|
419
|
+
const simpleMatches = [];
|
|
420
|
+
for (const [attribute, unique] of this.indexes.entries()) {
|
|
421
|
+
if (matchFn({ attribute })) {
|
|
422
|
+
simpleMatches.push({ attribute, unique });
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
// any compound index that has a value defined for its first attribute is a
|
|
426
|
+
// match; continue to process consecutive attributes whilst at least one
|
|
427
|
+
// value per consecutive attribute is defined
|
|
428
|
+
const compoundMatches = [];
|
|
429
|
+
for (const index of this.compoundIndexes.values()) {
|
|
430
|
+
let first = true;
|
|
431
|
+
const { attributes } = index;
|
|
432
|
+
for (const attribute of attributes) {
|
|
433
|
+
if (!matchFn({ attribute })) {
|
|
434
|
+
// consecutive value not defined
|
|
435
|
+
break;
|
|
436
|
+
}
|
|
437
|
+
if (first) {
|
|
438
|
+
first = false;
|
|
439
|
+
compoundMatches.push(index);
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
return { simpleMatches, compoundMatches };
|
|
444
|
+
}
|
|
445
|
+
_matchDocument({ attribute, attributeValues, doc }) {
|
|
446
|
+
// get attribute value from document
|
|
447
|
+
const value = this._dereferenceAttribute({ attribute, doc });
|
|
448
|
+
if (value === undefined) {
|
|
449
|
+
return false;
|
|
450
|
+
}
|
|
451
|
+
// get set of values
|
|
452
|
+
let valueSet = attributeValues.get(attribute);
|
|
453
|
+
if (!valueSet) {
|
|
454
|
+
attributeValues.set(attribute, (valueSet = new Set()));
|
|
455
|
+
}
|
|
456
|
+
// add each value in an array as a separate attribute value
|
|
457
|
+
if (Array.isArray(value)) {
|
|
458
|
+
value.forEach(valueSet.add, valueSet);
|
|
459
|
+
}
|
|
460
|
+
else {
|
|
461
|
+
valueSet.add(value);
|
|
462
|
+
}
|
|
463
|
+
return true;
|
|
464
|
+
}
|
|
465
|
+
_parseAttribute(attribute) {
|
|
466
|
+
const keys = split(attribute);
|
|
467
|
+
if (keys.length === 0) {
|
|
468
|
+
throw new Error(`Invalid attribute "${attribute}"; it must be of the form ` +
|
|
469
|
+
'"content.foo.bar".');
|
|
470
|
+
}
|
|
471
|
+
// ensure prefix is valid
|
|
472
|
+
if (!ATTRIBUTE_PREFIXES.includes(keys[0])) {
|
|
473
|
+
throw new Error('Attribute "${attribute}" must be prefixed with one of the ' +
|
|
474
|
+
`following: ${ATTRIBUTE_PREFIXES.join(', ')}`);
|
|
475
|
+
}
|
|
476
|
+
return keys;
|
|
477
|
+
}
|
|
478
|
+
_dereferenceAttribute({ attribute, keys, doc }) {
|
|
479
|
+
keys = keys || this._parseAttribute(attribute);
|
|
480
|
+
let value = doc;
|
|
481
|
+
while (keys.length > 0) {
|
|
482
|
+
if (!(value && typeof value === 'object')) {
|
|
483
|
+
return undefined;
|
|
484
|
+
}
|
|
485
|
+
const key = keys.shift();
|
|
486
|
+
value = value[key];
|
|
487
|
+
if (Array.isArray(value)) {
|
|
488
|
+
// there are more keys, so recurse into array
|
|
489
|
+
return value
|
|
490
|
+
.map((v) => this._dereferenceAttribute({ keys: keys.slice(), doc: v }))
|
|
491
|
+
.filter((v) => v !== undefined);
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
return value;
|
|
495
|
+
}
|
|
496
|
+
async _prewarmCache({ attributes, hmac }) {
|
|
497
|
+
const promises = [];
|
|
498
|
+
const compound = [];
|
|
499
|
+
for (const [i, name] of attributes.entries()) {
|
|
500
|
+
const hashed = await _hashString(name);
|
|
501
|
+
compound.push(hashed);
|
|
502
|
+
const data = i === 0 ? hashed : await sha256(_joinHashes(compound));
|
|
503
|
+
promises.push(this._cachedHmac({ hmac, data }));
|
|
504
|
+
}
|
|
505
|
+
return Promise.all(promises);
|
|
506
|
+
}
|
|
507
|
+
async _cachedHmac({ hmac, data }) {
|
|
508
|
+
return this._cache.memoize({
|
|
509
|
+
key: `${encodeURIComponent(hmac.id)}:${base64url.encode(data)}`,
|
|
510
|
+
fn: () => hmac.sign({ data })
|
|
511
|
+
});
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
function _assertHmac(hmac) {
|
|
515
|
+
if (!(hmac &&
|
|
516
|
+
typeof hmac === 'object' &&
|
|
517
|
+
typeof hmac.id === 'string' &&
|
|
518
|
+
typeof hmac.sign === 'function' &&
|
|
519
|
+
typeof hmac.verify === 'function')) {
|
|
520
|
+
throw new TypeError('"hmac" must be an object with "id", "sign", and "verify" properties.');
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
async function _hashString(str) {
|
|
524
|
+
return sha256(new TextEncoder().encode(str));
|
|
525
|
+
}
|
|
526
|
+
// `hashes` is an array of Uint8Arrays, each MUST have the same length
|
|
527
|
+
function _joinHashes(hashes) {
|
|
528
|
+
if (hashes.length === 0) {
|
|
529
|
+
return new Uint8Array(0);
|
|
530
|
+
}
|
|
531
|
+
const joined = new Uint8Array(hashes.length * hashes[0].length);
|
|
532
|
+
let offset = 0;
|
|
533
|
+
for (const hash of hashes) {
|
|
534
|
+
joined.set(hash, offset);
|
|
535
|
+
offset += hash.length;
|
|
536
|
+
}
|
|
537
|
+
return joined;
|
|
538
|
+
}
|
|
539
|
+
//# sourceMappingURL=IndexHelper.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"IndexHelper.js","sourceRoot":"","sources":["../src/IndexHelper.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AACtC,OAAO,YAAY,MAAM,cAAc,CAAA;AACvC,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAA;AAC/C,OAAO,EAAE,MAAM,EAAE,MAAM,WAAW,CAAA;AAClC,OAAO,KAAK,MAAM,cAAc,CAAA;AAEhC,MAAM,kBAAkB,GAAG,CAAC,SAAS,EAAE,MAAM,CAAC,CAAA;AAE9C,MAAM,OAAO,WAAW;IACtB,OAAO,CAAK;IACZ,eAAe,CAAK;IACpB,MAAM,CAAK;IAEX;;;;;OAKG;IACH;QACE,IAAI,CAAC,OAAO,GAAG,IAAI,GAAG,EAAE,CAAA;QACxB,IAAI,CAAC,eAAe,GAAG,IAAI,GAAG,EAAE,CAAA;QAChC,IAAI,CAAC,MAAM,GAAG,IAAI,QAAQ,CAAC;YACzB,mDAAmD;YACnD,GAAG,EAAE,IAAI;SACV,CAAC,CAAA;IACJ,CAAC;IAED;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,WAAW,CAAC,EAAE,SAAS,EAAE,MAAM,GAAG,KAAK,EAAE,IAAI,KAAU,EAAE;QACvD,IAAI,UAAU,GAAG,SAAS,CAAA;QAC1B,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC;YAC9B,UAAU,GAAG,CAAC,SAAS,CAAC,CAAA;QAC1B,CAAC;QACD,IACE,CAAC,CACC,UAAU,CAAC,MAAM,GAAG,CAAC;YACrB,UAAU,CAAC,KAAK,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,CACpD,EACD,CAAC;YACD,MAAM,IAAI,SAAS,CACjB,sDAAsD,CACvD,CAAA;QACH,CAAC;QAED,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC5B,mBAAmB;YACnB,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAA;QACzC,CAAC;aAAM,CAAC;YACN,qBAAqB;YACrB,MAAM,GAAG,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;YACvE,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,UAAU,EAAE,MAAM,EAAE,CAAC,CAAA;QACvD,CAAC;QAED,IAAI,IAAI,EAAE,CAAC;YACT,WAAW,CAAC,IAAI,CAAC,CAAA;YACjB,mDAAmD;YACnD,IAAI,CAAC,aAAa,CAAC,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAA;QAC1D,CAAC;IACH,CAAC;IAED;;;;;;;;;;;OAWG;IACH,KAAK,CAAC,WAAW,CAAC,EAAE,IAAI,EAAE,GAAG,EAAO;QAClC,WAAW,CAAC,IAAI,CAAC,CAAA;QACjB,MAAM,KAAK,GAAG;YACZ,IAAI,EAAE;gBACJ,EAAE,EAAE,IAAI,CAAC,EAAE;gBACX,IAAI,EAAE,IAAI,CAAC,IAAI;aAChB;YACD,QAAQ,EAAE,GAAG,CAAC,QAAQ;YACtB,UAAU,EAAE,MAAM,IAAI,CAAC,qBAAqB,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC;SAC5D,CAAA;QACD,OAAO,KAAK,CAAA;IACd,CAAC;IAED;;;;;;;;;;;;;;;OAeG;IACH,KAAK,CAAC,WAAW,CAAC,EAAE,IAAI,EAAE,GAAG,EAAO;QAClC,WAAW,CAAC,IAAI,CAAC,CAAA;QAEjB,2CAA2C;QAC3C,IAAI,EAAE,OAAO,GAAG,EAAE,EAAE,GAAG,GAAG,CAAA;QAC1B,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;YAC5B,MAAM,IAAI,SAAS,CAAC,6BAA6B,CAAC,CAAA;QACpD,CAAC;QAED,mBAAmB;QACnB,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,CAAA;QAEnD,uDAAuD;QACvD,MAAM,CAAC,GAAG,OAAO,CAAC,SAAS,CACzB,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,IAAI,CAAC,EAAE,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI,CAC/D,CAAA;QAED,8BAA8B;QAC9B,OAAO,GAAG,OAAO,CAAC,KAAK,EAAE,CAAA;QACzB,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC;YACb,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QACrB,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,CAAC,CAAC,GAAG,KAAK,CAAA;QACpB,CAAC;QAED,OAAO,OAAO,CAAA;IAChB,CAAC;IAED;;;;;;;;;;;;OAYG;IACH,KAAK,CAAC,UAAU,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAO;QACzC,WAAW,CAAC,IAAI,CAAC,CAAA;QAEjB,kBAAkB;QAClB,IAAI,MAAM,KAAK,SAAS,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;YAC9C,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAA;QAC9D,CAAC;QACD,IAAI,MAAM,KAAK,SAAS,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;YAC9C,MAAM,IAAI,KAAK,CAAC,uDAAuD,CAAC,CAAA;QAC1E,CAAC;QACD,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YACzB,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;gBAC1B,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,IAAI,OAAO,CAAC,KAAK,QAAQ,CAAC,EAAE,CAAC;oBAC1D,MAAM,IAAI,SAAS,CAAC,uCAAuC,CAAC,CAAA;gBAC9D,CAAC;YACH,CAAC;iBAAM,IAAI,CAAC,CAAC,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,CAAC,EAAE,CAAC;gBACnD,MAAM,IAAI,SAAS,CACjB,oDAAoD,CACrD,CAAA;YACH,CAAC;QACH,CAAC;QACD,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;YACtB,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;gBACvB,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,IAAI,OAAO,CAAC,KAAK,QAAQ,CAAC,EAAE,CAAC;oBACvD,MAAM,IAAI,SAAS,CAAC,oCAAoC,CAAC,CAAA;gBAC3D,CAAC;YACH,CAAC;iBAAM,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;gBACnC,MAAM,IAAI,SAAS,CAAC,gDAAgD,CAAC,CAAA;YACvE,CAAC;QACH,CAAC;QAED,MAAM,KAAK,GAAQ;YACjB,KAAK,EAAE,IAAI,CAAC,EAAE;SACf,CAAA;QAED,IAAI,MAAM,EAAE,CAAC;YACX,qBAAqB;YACrB,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;gBAC3B,MAAM,GAAG,CAAC,MAAM,CAAC,CAAA;YACnB,CAAC;YACD,mCAAmC;YACnC,KAAK,CAAC,MAAM,GAAG,MAAM,OAAO,CAAC,GAAG,CAC9B,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,KAAU,EAAE,EAAE;gBAC9B,MAAM,MAAM,GAAQ,EAAE,CAAA;gBACtB,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,qBAAqB,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAA;gBACjE,KAAK,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,OAAO,EAAE,CAAC;oBACtC,MAAM,CAAC,IAAI,CAAC,GAAG,KAAK,CAAA;gBACtB,CAAC;gBACD,OAAO,MAAM,CAAA;YACf,CAAC,CAAC,CACH,CAAA;QACH,CAAC;aAAM,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;YAC7B,qBAAqB;YACrB,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;gBACxB,GAAG,GAAG,CAAC,GAAG,CAAC,CAAA;YACb,CAAC;YACD,sCAAsC;YACtC,KAAK,CAAC,GAAG,GAAG,CAAC,MAAM,IAAI,CAAC,qBAAqB,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,GAAG,CAC/D,CAAC,EAAE,IAAI,EAAO,EAAE,EAAE,CAAC,IAAI,CACxB,CAAA;QACH,CAAC;QACD,OAAO,KAAK,CAAA;IACd,CAAC;IAED;;;;;;;;OAQG;IACH,KAAK,CAAC,UAAU,CAAC,IAAS,EAAE,IAAS;QACnC,0CAA0C;QAC1C,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAA;QACxD,IAAI,OAAO,SAAS,KAAK,QAAQ,EAAE,CAAC;YAClC,4BAA4B;YAC5B,OAAO,SAAS,CAAA;QAClB,CAAC;QACD,wCAAwC;QACxC,OAAO,SAAS,CAAC,MAAM,CAAC,SAAS,CAAC,CAAA;IACpC,CAAC;IAED;;;;;;;;;;;;OAYG;IACH,KAAK,CAAC,qBAAqB,CAAC,EAAE,IAAI,EAAE,eAAe,EAAO;QACxD,oDAAoD;QACpD,MAAM,WAAW,GAAG,MAAM,MAAM,CAC9B,WAAW,CAAC,CAAC,eAAe,CAAC,IAAI,EAAE,eAAe,CAAC,KAAK,CAAC,CAAC,CAC3D,CAAA;QACD,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;YACtC,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,eAAe,CAAC,IAAI,CAAC;YAC3C,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,WAAW,CAAC;SACnC,CAAC,CAAA;QACF,MAAM,cAAc,GAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,CAAA;QAC3C,IAAI,eAAe,CAAC,MAAM,EAAE,CAAC;YAC3B,cAAc,CAAC,MAAM,GAAG,IAAI,CAAA;QAC9B,CAAC;QACD,OAAO,cAAc,CAAA;IACvB,CAAC;IAED,KAAK,CAAC,qBAAqB,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,EAAO;QACxD,MAAM,gBAAgB,GAAG,EAAE,CAAA;QAE3B,8DAA8D;QAC9D,MAAM,EAAE,aAAa,EAAE,eAAe,EAAE,eAAe,EAAE,GACvD,IAAI,CAAC,mBAAmB,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAA;QAE/C,sDAAsD;QACtD,MAAM,kBAAkB,GAAG,IAAI,GAAG,EAAE,CAAA;QACpC,MAAM,YAAY,GAAG,EAAE,CAAA;QACvB,KAAK,MAAM,CAAC,IAAI,EAAE,QAAQ,CAAC,IAAI,eAAe,CAAC,OAAO,EAAE,EAAE,CAAC;YACzD,gEAAgE;YAChE,wDAAwD;YACxD,MAAM,SAAS,GAAG,IAAI,GAAG,EAAE,CAAA;YAC3B,kBAAkB,CAAC,GAAG,CAAC,IAAI,EAAE,SAAS,CAAC,CAAA;YACvC,KAAK,MAAM,KAAK,IAAI,QAAQ,EAAE,CAAC;gBAC7B,iEAAiE;gBACjE,+DAA+D;gBAC/D,mDAAmD;gBACnD,YAAY,CAAC,IAAI,CACf,CAAC,KAAK,IAAI,EAAE;oBACV,SAAS,CAAC,GAAG,CAAC,MAAM,IAAI,CAAC,cAAc,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,CAAA;gBACjE,CAAC,CAAC,EAAE,CACL,CAAA;YACH,CAAC;QACH,CAAC;QACD,MAAM,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,CAAA;QAE/B,mEAAmE;QACnE,mEAAmE;QACnE,UAAU;QACV,MAAM,gBAAgB,GAAG,IAAI,GAAG,EAAE,CAAA;QAClC,KAAK,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,aAAa,EAAE,CAAC;YACxD,MAAM,SAAS,GAAG,kBAAkB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;YAC9C,KAAK,MAAM,MAAM,IAAI,SAAS,EAAE,CAAC;gBAC/B,gBAAgB,CAAC,IAAI,CAAC,EAAE,GAAG,MAAM,EAAE,MAAM,EAAE,CAAC,CAAA;YAC9C,CAAC;YACD,gBAAgB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;QAC5B,CAAC;QAED,gEAAgE;QAChE,MAAM,gBAAgB,GAAG,EAAE,CAAA;QAC3B,KAAK,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,eAAe,EAAE,CAAC;YAC5D;;;;;;;;+CAQmC;YACnC,MAAM,YAAY,GAAG,EAAE,CAAA;YACvB,IAAI,QAAQ,GAAU,CAAC,EAAE,CAAC,CAAA;YAC1B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;gBACzB,MAAM,SAAS,GAAG,kBAAkB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;gBAC9C,IAAI,CAAC,SAAS,EAAE,CAAC;oBACf,mEAAmE;oBACnE,MAAK;gBACP,CAAC;gBACD,+DAA+D;gBAC/D,0CAA0C;gBAC1C,MAAM,IAAI,GAAG,EAAE,CAAA;gBACf,KAAK,MAAM,MAAM,IAAI,SAAS,EAAE,CAAC;oBAC/B,KAAK,MAAM,WAAW,IAAI,QAAQ,EAAE,CAAC;wBACnC,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,WAAW,EAAE,MAAM,CAAC,CAAC,CAAA;oBACrC,CAAC;gBACH,CAAC;gBACD,YAAY,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,CAAA;gBAC1B,QAAQ,GAAG,IAAI,CAAA;YACjB,CAAC;YAED,8CAA8C;YAC9C,KAAK,MAAM,WAAW,IAAI,YAAY,EAAE,CAAC;gBACvC,mEAAmE;gBACnE,wDAAwD;gBACxD,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC,IAAI,gBAAgB,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;oBAC/D,SAAQ;gBACV,CAAC;gBAED,qEAAqE;gBACrE,kEAAkE;gBAClE,iCAAiC;gBACjC,gBAAgB,CAAC,IAAI,CACnB,CAAC,KAAK,IAAI,EAAE;oBACV,MAAM,SAAS,GAAQ,MAAM,IAAI,CAAC,sBAAsB,CAAC;wBACvD,gBAAgB,EAAE,WAAW;qBAC9B,CAAC,CAAA;oBACF,kEAAkE;oBAClE,uDAAuD;oBACvD,SAAS,CAAC,MAAM,GAAG,MAAM,IAAI,WAAW,CAAC,MAAM,KAAK,KAAK,CAAC,MAAM,CAAA;oBAChE,OAAO,SAAS,CAAA;gBAClB,CAAC,CAAC,EAAE,CACL,CAAA;YACH,CAAC;QACH,CAAC;QACD,gBAAgB,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAA;QAE/D,8CAA8C;QAC9C,OAAO,OAAO,CAAC,GAAG,CAChB,gBAAgB,CAAC,GAAG,CAAC,KAAK,EAAC,eAAe,EAAC,EAAE,CAC3C,IAAI,CAAC,qBAAqB,CAAC,EAAE,IAAI,EAAE,eAAe,EAAE,CAAC,CACtD,CACF,CAAA;IACH,CAAC;IAED,mBAAmB,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,KAAU,EAAE;QAC/C,mEAAmE;QACnE,MAAM,eAAe,GAAG,IAAI,GAAG,EAAE,CAAA;QACjC,IAAI,OAAO,CAAA;QACX,IAAI,GAAG,EAAE,CAAC;YACR,mEAAmE;YACnE,uBAAuB;YACvB,OAAO,GAAG,CAAC,EAAE,SAAS,EAAO,EAAE,EAAE;gBAC/B,OAAO,IAAI,CAAC,cAAc,CAAC,EAAE,SAAS,EAAE,eAAe,EAAE,GAAG,EAAE,CAAC,CAAA;YACjE,CAAC,CAAA;QACH,CAAC;aAAM,CAAC;YACN,qDAAqD;YACrD,IAAI,UAAU,CAAA;YACd,IAAI,KAAK,EAAE,CAAC;gBACV,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;gBAC/B,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;oBAClD,eAAe,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;gBAC7C,CAAC;YACH,CAAC;iBAAM,CAAC;gBACN,UAAU,GAAG,GAAG,CAAA;gBAChB,KAAK,MAAM,IAAI,IAAI,GAAG,EAAE,CAAC;oBACvB,gEAAgE;oBAChE,oEAAoE;oBACpE,0DAA0D;oBAC1D,eAAe,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;gBAC5C,CAAC;YACH,CAAC;YACD,OAAO,GAAG,CAAC,EAAE,SAAS,EAAO,EAAE,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAA;QAClE,CAAC;QACD,MAAM,MAAM,GAAG,IAAI,CAAC,aAAa,CAAC,EAAE,OAAO,EAAE,CAAC,CAAA;QAC9C,OAAO,EAAE,GAAG,MAAM,EAAE,eAAe,EAAE,CAAA;IACvC,CAAC;IAED;;;;;;;;;;OAUG;IACH,KAAK,CAAC,cAAc,CAAC,EAAE,IAAI,EAAE,KAAK,EAAO;QACvC,+DAA+D;QAC/D,KAAK,GAAG,YAAY,CAAC,KAAK,CAAC,CAAA;QAC3B,MAAM,CAAC,UAAU,EAAE,WAAW,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;YAClD,WAAW,CAAC,IAAI,CAAC;YACjB,WAAW,CAAC,KAAK,CAAC;SACnB,CAAC,CAAA;QACF,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,WAAW,EAAE,CAAA;IACjD,CAAC;IAED;;;;;;;;;;;;OAYG;IACH,KAAK,CAAC,sBAAsB,CAAC,EAC3B,gBAAgB,EAChB,MAAM,GAAG,gBAAgB,CAAC,MAAM,EAC5B;QACJ,MAAM,SAAS,GACb,MAAM,KAAK,gBAAgB,CAAC,MAAM;YAChC,CAAC,CAAC,gBAAgB;YAClB,CAAC,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,CAAC,CAAA;QACvC,MAAM,SAAS,GAAG,WAAW,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAA;QAChE,MAAM,UAAU,GAAG,WAAW,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAA;QAClE,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;YACtC,MAAM,CAAC,SAAS,CAAC;YACjB,MAAM,CAAC,UAAU,CAAC;SACnB,CAAC,CAAA;QACF,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,CAAA;IACxB,CAAC;IAED,aAAa,CAAC,EAAE,OAAO,KAAU,EAAE;QACjC,yEAAyE;QACzE,MAAM,aAAa,GAAG,EAAE,CAAA;QACxB,KAAK,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,IAAI,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC;YACzD,IAAI,OAAO,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,CAAC;gBAC3B,aAAa,CAAC,IAAI,CAAC,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC,CAAA;YAC3C,CAAC;QACH,CAAC;QAED,2EAA2E;QAC3E,wEAAwE;QACxE,6CAA6C;QAC7C,MAAM,eAAe,GAAG,EAAE,CAAA;QAC1B,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,eAAe,CAAC,MAAM,EAAE,EAAE,CAAC;YAClD,IAAI,KAAK,GAAG,IAAI,CAAA;YAChB,MAAM,EAAE,UAAU,EAAE,GAAG,KAAK,CAAA;YAC5B,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;gBACnC,IAAI,CAAC,OAAO,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,CAAC;oBAC5B,gCAAgC;oBAChC,MAAK;gBACP,CAAC;gBACD,IAAI,KAAK,EAAE,CAAC;oBACV,KAAK,GAAG,KAAK,CAAA;oBACb,eAAe,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;gBAC7B,CAAC;YACH,CAAC;QACH,CAAC;QAED,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,CAAA;IAC3C,CAAC;IAED,cAAc,CAAC,EAAE,SAAS,EAAE,eAAe,EAAE,GAAG,EAAO;QACrD,oCAAoC;QACpC,MAAM,KAAK,GAAG,IAAI,CAAC,qBAAqB,CAAC,EAAE,SAAS,EAAE,GAAG,EAAE,CAAC,CAAA;QAC5D,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACxB,OAAO,KAAK,CAAA;QACd,CAAC;QAED,oBAAoB;QACpB,IAAI,QAAQ,GAAG,eAAe,CAAC,GAAG,CAAC,SAAS,CAAC,CAAA;QAC7C,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,eAAe,CAAC,GAAG,CAAC,SAAS,EAAE,CAAC,QAAQ,GAAG,IAAI,GAAG,EAAE,CAAC,CAAC,CAAA;QACxD,CAAC;QAED,2DAA2D;QAC3D,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;YACzB,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAA;QACvC,CAAC;aAAM,CAAC;YACN,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,CAAA;QACrB,CAAC;QAED,OAAO,IAAI,CAAA;IACb,CAAC;IAED,eAAe,CAAC,SAAc;QAC5B,MAAM,IAAI,GAAG,KAAK,CAAC,SAAS,CAAC,CAAA;QAC7B,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACtB,MAAM,IAAI,KAAK,CACb,sBAAsB,SAAS,4BAA4B;gBACzD,oBAAoB,CACvB,CAAA;QACH,CAAC;QACD,yBAAyB;QACzB,IAAI,CAAC,kBAAkB,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YAC1C,MAAM,IAAI,KAAK,CACb,4DAA4D;gBAC1D,cAAc,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAChD,CAAA;QACH,CAAC;QACD,OAAO,IAAI,CAAA;IACb,CAAC;IAED,qBAAqB,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,EAAO;QACjD,IAAI,GAAG,IAAI,IAAI,IAAI,CAAC,eAAe,CAAC,SAAS,CAAC,CAAA;QAC9C,IAAI,KAAK,GAAG,GAAG,CAAA;QACf,OAAO,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACvB,IAAI,CAAC,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,CAAC,EAAE,CAAC;gBAC1C,OAAO,SAAS,CAAA;YAClB,CAAC;YACD,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,EAAE,CAAA;YACxB,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,CAAA;YAClB,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;gBACzB,6CAA6C;gBAC7C,OAAO,KAAK;qBACT,GAAG,CAAC,CAAC,CAAM,EAAE,EAAE,CACd,IAAI,CAAC,qBAAqB,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,KAAK,EAAE,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,CAC3D;qBACA,MAAM,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,KAAK,SAAS,CAAC,CAAA;YACxC,CAAC;QACH,CAAC;QACD,OAAO,KAAK,CAAA;IACd,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,EAAE,UAAU,EAAE,IAAI,EAAO;QAC3C,MAAM,QAAQ,GAAG,EAAE,CAAA;QACnB,MAAM,QAAQ,GAAG,EAAE,CAAA;QACnB,KAAK,MAAM,CAAC,CAAC,EAAE,IAAI,CAAC,IAAI,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC;YAC7C,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,IAAI,CAAC,CAAA;YACtC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;YACrB,MAAM,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,MAAM,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC,CAAA;YACnE,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAA;QACjD,CAAC;QACD,OAAO,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;IAC9B,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,EAAE,IAAI,EAAE,IAAI,EAAO;QACnC,OAAO,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC;YACzB,GAAG,EAAE,GAAG,kBAAkB,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE;YAC/D,EAAE,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,CAAC;SAC9B,CAAC,CAAA;IACJ,CAAC;CACF;AAED,SAAS,WAAW,CAAC,IAAS;IAC5B,IACE,CAAC,CACC,IAAI;QACJ,OAAO,IAAI,KAAK,QAAQ;QACxB,OAAO,IAAI,CAAC,EAAE,KAAK,QAAQ;QAC3B,OAAO,IAAI,CAAC,IAAI,KAAK,UAAU;QAC/B,OAAO,IAAI,CAAC,MAAM,KAAK,UAAU,CAClC,EACD,CAAC;QACD,MAAM,IAAI,SAAS,CACjB,sEAAsE,CACvE,CAAA;IACH,CAAC;AACH,CAAC;AAED,KAAK,UAAU,WAAW,CAAC,GAAQ;IACjC,OAAO,MAAM,CAAC,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAA;AAC9C,CAAC;AAED,sEAAsE;AACtE,SAAS,WAAW,CAAC,MAAW;IAC9B,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxB,OAAO,IAAI,UAAU,CAAC,CAAC,CAAC,CAAA;IAC1B,CAAC;IAED,MAAM,MAAM,GAAG,IAAI,UAAU,CAAC,MAAM,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAA;IAC/D,IAAI,MAAM,GAAG,CAAC,CAAA;IACd,KAAK,MAAM,IAAI,IAAI,MAAM,EAAE,CAAC;QAC1B,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,CAAA;QACxB,MAAM,IAAI,IAAI,CAAC,MAAM,CAAA;IACvB,CAAC;IAED,OAAO,MAAM,CAAA;AACf,CAAC"}
|