@libp2p/record 0.10.6
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 +4 -0
- package/README.md +40 -0
- package/dist/src/index.d.ts +24 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +52 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/record.d.ts +71 -0
- package/dist/src/record.js +202 -0
- package/dist/src/record.proto +20 -0
- package/dist/src/selectors.d.ts +16 -0
- package/dist/src/selectors.d.ts.map +1 -0
- package/dist/src/selectors.js +38 -0
- package/dist/src/selectors.js.map +1 -0
- package/dist/src/utils.d.ts +11 -0
- package/dist/src/utils.d.ts.map +1 -0
- package/dist/src/utils.js +41 -0
- package/dist/src/utils.js.map +1 -0
- package/dist/src/validators.d.ts +15 -0
- package/dist/src/validators.d.ts.map +1 -0
- package/dist/src/validators.js +58 -0
- package/dist/src/validators.js.map +1 -0
- package/package.json +176 -0
- package/src/index.ts +68 -0
- package/src/record.d.ts +71 -0
- package/src/record.js +202 -0
- package/src/record.proto +20 -0
- package/src/selectors.ts +50 -0
- package/src/utils.ts +46 -0
- package/src/validators.ts +74 -0
package/LICENSE
ADDED
package/README.md
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# js-libp2p-record
|
|
2
|
+
|
|
3
|
+
[](http://ipn.io)
|
|
4
|
+
[](http://libp2p.io/)
|
|
5
|
+
[](http://webchat.freenode.net/?channels=%23libp2p)
|
|
6
|
+
[](https://discuss.libp2p.io)
|
|
7
|
+
[](https://github.com/RichardLitt/standard-readme)
|
|
8
|
+
[](https://coveralls.io/github/libp2p/js-libp2p-record?branch=master)
|
|
9
|
+
[](https://github.com/libp2p/js-libp2p-record/actions/workflows/js-test-and-release.yml)
|
|
10
|
+
[](https://david-dm.org/libp2p/js-libp2p-record) [](https://github.com/feross/standard)
|
|
11
|
+

|
|
12
|
+

|
|
13
|
+
|
|
14
|
+
> JavaScript implementation of libp2p record.
|
|
15
|
+
|
|
16
|
+
## Description
|
|
17
|
+
|
|
18
|
+
Implementation of [go-libp2p-record](https://github.com/libp2p/go-libp2p-record) in JavaScript.
|
|
19
|
+
|
|
20
|
+
## Usage
|
|
21
|
+
|
|
22
|
+
See https://libp2p.github.io/js-libp2p-record/
|
|
23
|
+
|
|
24
|
+
## Contribute
|
|
25
|
+
|
|
26
|
+
The libp2p implementation in JavaScript is a work in progress. As such, there are a few things you can do right now to help out:
|
|
27
|
+
|
|
28
|
+
- Go through the modules and **check out existing issues**. This is especially useful for modules in active development. Some knowledge of IPFS/libp2p may be required, as well as the infrastructure behind it - for instance, you may need to read up on p2p and more complex operations like muxing to be able to help technically.
|
|
29
|
+
- **Perform code reviews**. More eyes will help a) speed the project along b) ensure quality and c) reduce possible future bugs.
|
|
30
|
+
|
|
31
|
+
## License
|
|
32
|
+
|
|
33
|
+
Licensed under either of
|
|
34
|
+
|
|
35
|
+
* Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / http://www.apache.org/licenses/LICENSE-2.0)
|
|
36
|
+
* MIT ([LICENSE-MIT](LICENSE-MIT) / http://opensource.org/licenses/MIT)
|
|
37
|
+
|
|
38
|
+
### Contribution
|
|
39
|
+
|
|
40
|
+
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export declare class Libp2pRecord {
|
|
2
|
+
key: Uint8Array;
|
|
3
|
+
value: Uint8Array;
|
|
4
|
+
timeReceived?: Date;
|
|
5
|
+
constructor(key: Uint8Array, value: Uint8Array, timeReceived?: Date);
|
|
6
|
+
serialize(): Uint8Array;
|
|
7
|
+
/**
|
|
8
|
+
* Return the object format ready to be given to the protobuf library.
|
|
9
|
+
*/
|
|
10
|
+
prepareSerialize(): {
|
|
11
|
+
key: Uint8Array;
|
|
12
|
+
value: Uint8Array;
|
|
13
|
+
timeReceived: string | undefined;
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* Decode a protobuf encoded record
|
|
17
|
+
*/
|
|
18
|
+
static deserialize(raw: Uint8Array): Libp2pRecord;
|
|
19
|
+
/**
|
|
20
|
+
* Create a record from the raw object returned from the protobuf library
|
|
21
|
+
*/
|
|
22
|
+
static fromDeserialized(obj: Record<string, any>): Libp2pRecord;
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAKA,qBAAa,YAAY;IAChB,GAAG,EAAE,UAAU,CAAA;IACf,KAAK,EAAE,UAAU,CAAA;IACjB,YAAY,CAAC,EAAE,IAAI,CAAA;gBAEb,GAAG,EAAE,UAAU,EAAE,KAAK,EAAE,UAAU,EAAE,YAAY,CAAC,EAAE,IAAI;IAcpE,SAAS;IAIT;;OAEG;IACH,gBAAgB;;;;;IAQhB;;OAEG;IACH,MAAM,CAAC,WAAW,CAAE,GAAG,EAAE,UAAU;IAUnC;;OAEG;IACH,MAAM,CAAC,gBAAgB,CAAE,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC;CAYlD"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { Record as PBRecord } from './record.js';
|
|
2
|
+
import * as utils from './utils.js';
|
|
3
|
+
export class Libp2pRecord {
|
|
4
|
+
constructor(key, value, timeReceived) {
|
|
5
|
+
if (!(key instanceof Uint8Array)) {
|
|
6
|
+
throw new Error('key must be a Uint8Array');
|
|
7
|
+
}
|
|
8
|
+
if (!(value instanceof Uint8Array)) {
|
|
9
|
+
throw new Error('value must be a Uint8Array');
|
|
10
|
+
}
|
|
11
|
+
this.key = key;
|
|
12
|
+
this.value = value;
|
|
13
|
+
this.timeReceived = timeReceived;
|
|
14
|
+
}
|
|
15
|
+
serialize() {
|
|
16
|
+
return PBRecord.encode(this.prepareSerialize()).finish();
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Return the object format ready to be given to the protobuf library.
|
|
20
|
+
*/
|
|
21
|
+
prepareSerialize() {
|
|
22
|
+
return {
|
|
23
|
+
key: this.key,
|
|
24
|
+
value: this.value,
|
|
25
|
+
timeReceived: this.timeReceived != null ? utils.toRFC3339(this.timeReceived) : undefined
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Decode a protobuf encoded record
|
|
30
|
+
*/
|
|
31
|
+
static deserialize(raw) {
|
|
32
|
+
const message = PBRecord.decode(raw);
|
|
33
|
+
return Libp2pRecord.fromDeserialized(PBRecord.toObject(message, {
|
|
34
|
+
defaults: false,
|
|
35
|
+
arrays: true,
|
|
36
|
+
longs: Number,
|
|
37
|
+
objects: false
|
|
38
|
+
}));
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Create a record from the raw object returned from the protobuf library
|
|
42
|
+
*/
|
|
43
|
+
static fromDeserialized(obj) {
|
|
44
|
+
let recvtime;
|
|
45
|
+
if (obj.timeReceived != null) {
|
|
46
|
+
recvtime = utils.parseRFC3339(obj.timeReceived);
|
|
47
|
+
}
|
|
48
|
+
const rec = new Libp2pRecord(obj.key, obj.value, recvtime);
|
|
49
|
+
return rec;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,MAAM,IAAI,QAAQ,EACnB,MAAM,aAAa,CAAA;AACpB,OAAO,KAAK,KAAK,MAAM,YAAY,CAAA;AAEnC,MAAM,OAAO,YAAY;IAKvB,YAAa,GAAe,EAAE,KAAiB,EAAE,YAAmB;QAClE,IAAI,CAAC,CAAC,GAAG,YAAY,UAAU,CAAC,EAAE;YAChC,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAA;SAC5C;QAED,IAAI,CAAC,CAAC,KAAK,YAAY,UAAU,CAAC,EAAE;YAClC,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAA;SAC9C;QAED,IAAI,CAAC,GAAG,GAAG,GAAG,CAAA;QACd,IAAI,CAAC,KAAK,GAAG,KAAK,CAAA;QAClB,IAAI,CAAC,YAAY,GAAG,YAAY,CAAA;IAClC,CAAC;IAED,SAAS;QACP,OAAO,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,gBAAgB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAA;IAC1D,CAAC;IAED;;OAEG;IACH,gBAAgB;QACd,OAAO;YACL,GAAG,EAAE,IAAI,CAAC,GAAG;YACb,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,YAAY,EAAE,IAAI,CAAC,YAAY,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,SAAS;SACzF,CAAA;IACH,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,WAAW,CAAE,GAAe;QACjC,MAAM,OAAO,GAAG,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;QACpC,OAAO,YAAY,CAAC,gBAAgB,CAAC,QAAQ,CAAC,QAAQ,CAAC,OAAO,EAAE;YAC9D,QAAQ,EAAE,KAAK;YACf,MAAM,EAAE,IAAI;YACZ,KAAK,EAAE,MAAM;YACb,OAAO,EAAE,KAAK;SACf,CAAC,CAAC,CAAA;IACL,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,gBAAgB,CAAE,GAAwB;QAC/C,IAAI,QAAQ,CAAA;QACZ,IAAI,GAAG,CAAC,YAAY,IAAI,IAAI,EAAE;YAC5B,QAAQ,GAAG,KAAK,CAAC,YAAY,CAAC,GAAG,CAAC,YAAY,CAAC,CAAA;SAChD;QAED,MAAM,GAAG,GAAG,IAAI,YAAY,CAC1B,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,KAAK,EAAE,QAAQ,CAC7B,CAAA;QAED,OAAO,GAAG,CAAA;IACZ,CAAC;CACF"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import * as $protobuf from "protobufjs";
|
|
2
|
+
/** Properties of a Record. */
|
|
3
|
+
export interface IRecord {
|
|
4
|
+
|
|
5
|
+
/** Record key */
|
|
6
|
+
key?: (Uint8Array|null);
|
|
7
|
+
|
|
8
|
+
/** Record value */
|
|
9
|
+
value?: (Uint8Array|null);
|
|
10
|
+
|
|
11
|
+
/** Record timeReceived */
|
|
12
|
+
timeReceived?: (string|null);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/** Represents a Record. */
|
|
16
|
+
export class Record implements IRecord {
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Constructs a new Record.
|
|
20
|
+
* @param [p] Properties to set
|
|
21
|
+
*/
|
|
22
|
+
constructor(p?: IRecord);
|
|
23
|
+
|
|
24
|
+
/** Record key. */
|
|
25
|
+
public key: Uint8Array;
|
|
26
|
+
|
|
27
|
+
/** Record value. */
|
|
28
|
+
public value: Uint8Array;
|
|
29
|
+
|
|
30
|
+
/** Record timeReceived. */
|
|
31
|
+
public timeReceived: string;
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Encodes the specified Record message. Does not implicitly {@link Record.verify|verify} messages.
|
|
35
|
+
* @param m Record message or plain object to encode
|
|
36
|
+
* @param [w] Writer to encode to
|
|
37
|
+
* @returns Writer
|
|
38
|
+
*/
|
|
39
|
+
public static encode(m: IRecord, w?: $protobuf.Writer): $protobuf.Writer;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Decodes a Record message from the specified reader or buffer.
|
|
43
|
+
* @param r Reader or buffer to decode from
|
|
44
|
+
* @param [l] Message length if known beforehand
|
|
45
|
+
* @returns Record
|
|
46
|
+
* @throws {Error} If the payload is not a reader or valid buffer
|
|
47
|
+
* @throws {$protobuf.util.ProtocolError} If required fields are missing
|
|
48
|
+
*/
|
|
49
|
+
public static decode(r: ($protobuf.Reader|Uint8Array), l?: number): Record;
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Creates a Record message from a plain object. Also converts values to their respective internal types.
|
|
53
|
+
* @param d Plain object
|
|
54
|
+
* @returns Record
|
|
55
|
+
*/
|
|
56
|
+
public static fromObject(d: { [k: string]: any }): Record;
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Creates a plain object from a Record message. Also converts values to other types if specified.
|
|
60
|
+
* @param m Record
|
|
61
|
+
* @param [o] Conversion options
|
|
62
|
+
* @returns Plain object
|
|
63
|
+
*/
|
|
64
|
+
public static toObject(m: Record, o?: $protobuf.IConversionOptions): { [k: string]: any };
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Converts this Record to JSON.
|
|
68
|
+
* @returns JSON object
|
|
69
|
+
*/
|
|
70
|
+
public toJSON(): { [k: string]: any };
|
|
71
|
+
}
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
/*eslint-disable*/
|
|
2
|
+
import $protobuf from "protobufjs/minimal.js";
|
|
3
|
+
|
|
4
|
+
// Common aliases
|
|
5
|
+
const $Reader = $protobuf.Reader, $Writer = $protobuf.Writer, $util = $protobuf.util;
|
|
6
|
+
|
|
7
|
+
// Exported root namespace
|
|
8
|
+
const $root = $protobuf.roots["libp2p-record"] || ($protobuf.roots["libp2p-record"] = {});
|
|
9
|
+
|
|
10
|
+
export const Record = $root.Record = (() => {
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Properties of a Record.
|
|
14
|
+
* @exports IRecord
|
|
15
|
+
* @interface IRecord
|
|
16
|
+
* @property {Uint8Array|null} [key] Record key
|
|
17
|
+
* @property {Uint8Array|null} [value] Record value
|
|
18
|
+
* @property {string|null} [timeReceived] Record timeReceived
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Constructs a new Record.
|
|
23
|
+
* @exports Record
|
|
24
|
+
* @classdesc Represents a Record.
|
|
25
|
+
* @implements IRecord
|
|
26
|
+
* @constructor
|
|
27
|
+
* @param {IRecord=} [p] Properties to set
|
|
28
|
+
*/
|
|
29
|
+
function Record(p) {
|
|
30
|
+
if (p)
|
|
31
|
+
for (var ks = Object.keys(p), i = 0; i < ks.length; ++i)
|
|
32
|
+
if (p[ks[i]] != null)
|
|
33
|
+
this[ks[i]] = p[ks[i]];
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Record key.
|
|
38
|
+
* @member {Uint8Array} key
|
|
39
|
+
* @memberof Record
|
|
40
|
+
* @instance
|
|
41
|
+
*/
|
|
42
|
+
Record.prototype.key = $util.newBuffer([]);
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Record value.
|
|
46
|
+
* @member {Uint8Array} value
|
|
47
|
+
* @memberof Record
|
|
48
|
+
* @instance
|
|
49
|
+
*/
|
|
50
|
+
Record.prototype.value = $util.newBuffer([]);
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Record timeReceived.
|
|
54
|
+
* @member {string} timeReceived
|
|
55
|
+
* @memberof Record
|
|
56
|
+
* @instance
|
|
57
|
+
*/
|
|
58
|
+
Record.prototype.timeReceived = "";
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Encodes the specified Record message. Does not implicitly {@link Record.verify|verify} messages.
|
|
62
|
+
* @function encode
|
|
63
|
+
* @memberof Record
|
|
64
|
+
* @static
|
|
65
|
+
* @param {IRecord} m Record message or plain object to encode
|
|
66
|
+
* @param {$protobuf.Writer} [w] Writer to encode to
|
|
67
|
+
* @returns {$protobuf.Writer} Writer
|
|
68
|
+
*/
|
|
69
|
+
Record.encode = function encode(m, w) {
|
|
70
|
+
if (!w)
|
|
71
|
+
w = $Writer.create();
|
|
72
|
+
if (m.key != null && Object.hasOwnProperty.call(m, "key"))
|
|
73
|
+
w.uint32(10).bytes(m.key);
|
|
74
|
+
if (m.value != null && Object.hasOwnProperty.call(m, "value"))
|
|
75
|
+
w.uint32(18).bytes(m.value);
|
|
76
|
+
if (m.timeReceived != null && Object.hasOwnProperty.call(m, "timeReceived"))
|
|
77
|
+
w.uint32(42).string(m.timeReceived);
|
|
78
|
+
return w;
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Decodes a Record message from the specified reader or buffer.
|
|
83
|
+
* @function decode
|
|
84
|
+
* @memberof Record
|
|
85
|
+
* @static
|
|
86
|
+
* @param {$protobuf.Reader|Uint8Array} r Reader or buffer to decode from
|
|
87
|
+
* @param {number} [l] Message length if known beforehand
|
|
88
|
+
* @returns {Record} Record
|
|
89
|
+
* @throws {Error} If the payload is not a reader or valid buffer
|
|
90
|
+
* @throws {$protobuf.util.ProtocolError} If required fields are missing
|
|
91
|
+
*/
|
|
92
|
+
Record.decode = function decode(r, l) {
|
|
93
|
+
if (!(r instanceof $Reader))
|
|
94
|
+
r = $Reader.create(r);
|
|
95
|
+
var c = l === undefined ? r.len : r.pos + l, m = new $root.Record();
|
|
96
|
+
while (r.pos < c) {
|
|
97
|
+
var t = r.uint32();
|
|
98
|
+
switch (t >>> 3) {
|
|
99
|
+
case 1:
|
|
100
|
+
m.key = r.bytes();
|
|
101
|
+
break;
|
|
102
|
+
case 2:
|
|
103
|
+
m.value = r.bytes();
|
|
104
|
+
break;
|
|
105
|
+
case 5:
|
|
106
|
+
m.timeReceived = r.string();
|
|
107
|
+
break;
|
|
108
|
+
default:
|
|
109
|
+
r.skipType(t & 7);
|
|
110
|
+
break;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
return m;
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Creates a Record message from a plain object. Also converts values to their respective internal types.
|
|
118
|
+
* @function fromObject
|
|
119
|
+
* @memberof Record
|
|
120
|
+
* @static
|
|
121
|
+
* @param {Object.<string,*>} d Plain object
|
|
122
|
+
* @returns {Record} Record
|
|
123
|
+
*/
|
|
124
|
+
Record.fromObject = function fromObject(d) {
|
|
125
|
+
if (d instanceof $root.Record)
|
|
126
|
+
return d;
|
|
127
|
+
var m = new $root.Record();
|
|
128
|
+
if (d.key != null) {
|
|
129
|
+
if (typeof d.key === "string")
|
|
130
|
+
$util.base64.decode(d.key, m.key = $util.newBuffer($util.base64.length(d.key)), 0);
|
|
131
|
+
else if (d.key.length)
|
|
132
|
+
m.key = d.key;
|
|
133
|
+
}
|
|
134
|
+
if (d.value != null) {
|
|
135
|
+
if (typeof d.value === "string")
|
|
136
|
+
$util.base64.decode(d.value, m.value = $util.newBuffer($util.base64.length(d.value)), 0);
|
|
137
|
+
else if (d.value.length)
|
|
138
|
+
m.value = d.value;
|
|
139
|
+
}
|
|
140
|
+
if (d.timeReceived != null) {
|
|
141
|
+
m.timeReceived = String(d.timeReceived);
|
|
142
|
+
}
|
|
143
|
+
return m;
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Creates a plain object from a Record message. Also converts values to other types if specified.
|
|
148
|
+
* @function toObject
|
|
149
|
+
* @memberof Record
|
|
150
|
+
* @static
|
|
151
|
+
* @param {Record} m Record
|
|
152
|
+
* @param {$protobuf.IConversionOptions} [o] Conversion options
|
|
153
|
+
* @returns {Object.<string,*>} Plain object
|
|
154
|
+
*/
|
|
155
|
+
Record.toObject = function toObject(m, o) {
|
|
156
|
+
if (!o)
|
|
157
|
+
o = {};
|
|
158
|
+
var d = {};
|
|
159
|
+
if (o.defaults) {
|
|
160
|
+
if (o.bytes === String)
|
|
161
|
+
d.key = "";
|
|
162
|
+
else {
|
|
163
|
+
d.key = [];
|
|
164
|
+
if (o.bytes !== Array)
|
|
165
|
+
d.key = $util.newBuffer(d.key);
|
|
166
|
+
}
|
|
167
|
+
if (o.bytes === String)
|
|
168
|
+
d.value = "";
|
|
169
|
+
else {
|
|
170
|
+
d.value = [];
|
|
171
|
+
if (o.bytes !== Array)
|
|
172
|
+
d.value = $util.newBuffer(d.value);
|
|
173
|
+
}
|
|
174
|
+
d.timeReceived = "";
|
|
175
|
+
}
|
|
176
|
+
if (m.key != null && m.hasOwnProperty("key")) {
|
|
177
|
+
d.key = o.bytes === String ? $util.base64.encode(m.key, 0, m.key.length) : o.bytes === Array ? Array.prototype.slice.call(m.key) : m.key;
|
|
178
|
+
}
|
|
179
|
+
if (m.value != null && m.hasOwnProperty("value")) {
|
|
180
|
+
d.value = o.bytes === String ? $util.base64.encode(m.value, 0, m.value.length) : o.bytes === Array ? Array.prototype.slice.call(m.value) : m.value;
|
|
181
|
+
}
|
|
182
|
+
if (m.timeReceived != null && m.hasOwnProperty("timeReceived")) {
|
|
183
|
+
d.timeReceived = m.timeReceived;
|
|
184
|
+
}
|
|
185
|
+
return d;
|
|
186
|
+
};
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Converts this Record to JSON.
|
|
190
|
+
* @function toJSON
|
|
191
|
+
* @memberof Record
|
|
192
|
+
* @instance
|
|
193
|
+
* @returns {Object.<string,*>} JSON object
|
|
194
|
+
*/
|
|
195
|
+
Record.prototype.toJSON = function toJSON() {
|
|
196
|
+
return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
|
|
197
|
+
};
|
|
198
|
+
|
|
199
|
+
return Record;
|
|
200
|
+
})();
|
|
201
|
+
|
|
202
|
+
export { $root as default };
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
syntax = "proto3";
|
|
2
|
+
|
|
3
|
+
// Record represents a dht record that contains a value
|
|
4
|
+
// for a key value pair
|
|
5
|
+
message Record {
|
|
6
|
+
// The key that references this record
|
|
7
|
+
bytes key = 1;
|
|
8
|
+
|
|
9
|
+
// The actual value this record is storing
|
|
10
|
+
bytes value = 2;
|
|
11
|
+
|
|
12
|
+
// Note: These fields were removed from the Record message
|
|
13
|
+
// hash of the authors public key
|
|
14
|
+
// optional bytes author = 3;
|
|
15
|
+
// A PKI signature for the key+value+author
|
|
16
|
+
// optional bytes signature = 4;
|
|
17
|
+
|
|
18
|
+
// Time the record was received, set by receiver
|
|
19
|
+
string timeReceived = 5;
|
|
20
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { Selectors } from '@libp2p/interfaces/dht';
|
|
2
|
+
/**
|
|
3
|
+
* Select the best record out of the given records
|
|
4
|
+
*/
|
|
5
|
+
export declare function bestRecord(selectors: Selectors, k: Uint8Array, records: Uint8Array[]): number;
|
|
6
|
+
/**
|
|
7
|
+
* Best record selector, for public key records.
|
|
8
|
+
* Simply returns the first record, as all valid public key
|
|
9
|
+
* records are equal
|
|
10
|
+
*/
|
|
11
|
+
declare function publickKey(k: Uint8Array, records: Uint8Array[]): number;
|
|
12
|
+
export declare const selectors: {
|
|
13
|
+
publickKey: typeof publickKey;
|
|
14
|
+
};
|
|
15
|
+
export {};
|
|
16
|
+
//# sourceMappingURL=selectors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"selectors.d.ts","sourceRoot":"","sources":["../../src/selectors.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAA;AAEvD;;GAEG;AACH,wBAAgB,UAAU,CAAE,SAAS,EAAE,SAAS,EAAE,CAAC,EAAE,UAAU,EAAE,OAAO,EAAE,UAAU,EAAE,UA6BrF;AAED;;;;GAIG;AACH,iBAAS,UAAU,CAAE,CAAC,EAAE,UAAU,EAAE,OAAO,EAAE,UAAU,EAAE,UAExD;AAED,eAAO,MAAM,SAAS;;CAErB,CAAA"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import errcode from 'err-code';
|
|
2
|
+
import { toString as uint8ArrayToString } from 'uint8arrays/to-string';
|
|
3
|
+
/**
|
|
4
|
+
* Select the best record out of the given records
|
|
5
|
+
*/
|
|
6
|
+
export function bestRecord(selectors, k, records) {
|
|
7
|
+
if (records.length === 0) {
|
|
8
|
+
const errMsg = 'No records given';
|
|
9
|
+
throw errcode(new Error(errMsg), 'ERR_NO_RECORDS_RECEIVED');
|
|
10
|
+
}
|
|
11
|
+
const kStr = uint8ArrayToString(k);
|
|
12
|
+
const parts = kStr.split('/');
|
|
13
|
+
if (parts.length < 3) {
|
|
14
|
+
const errMsg = 'Record key does not have a selector function';
|
|
15
|
+
throw errcode(new Error(errMsg), 'ERR_NO_SELECTOR_FUNCTION_FOR_RECORD_KEY');
|
|
16
|
+
}
|
|
17
|
+
const selector = selectors[parts[1].toString()];
|
|
18
|
+
if (selector == null) {
|
|
19
|
+
const errMsg = `Unrecognized key prefix: ${parts[1]}`;
|
|
20
|
+
throw errcode(new Error(errMsg), 'ERR_UNRECOGNIZED_KEY_PREFIX');
|
|
21
|
+
}
|
|
22
|
+
if (records.length === 1) {
|
|
23
|
+
return 0;
|
|
24
|
+
}
|
|
25
|
+
return selector(k, records);
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Best record selector, for public key records.
|
|
29
|
+
* Simply returns the first record, as all valid public key
|
|
30
|
+
* records are equal
|
|
31
|
+
*/
|
|
32
|
+
function publickKey(k, records) {
|
|
33
|
+
return 0;
|
|
34
|
+
}
|
|
35
|
+
export const selectors = {
|
|
36
|
+
publickKey
|
|
37
|
+
};
|
|
38
|
+
//# sourceMappingURL=selectors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"selectors.js","sourceRoot":"","sources":["../../src/selectors.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,UAAU,CAAA;AAC9B,OAAO,EAAE,QAAQ,IAAI,kBAAkB,EAAE,MAAM,uBAAuB,CAAA;AAGtE;;GAEG;AACH,MAAM,UAAU,UAAU,CAAE,SAAoB,EAAE,CAAa,EAAE,OAAqB;IACpF,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE;QACxB,MAAM,MAAM,GAAG,kBAAkB,CAAA;QAEjC,MAAM,OAAO,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,EAAE,yBAAyB,CAAC,CAAA;KAC5D;IAED,MAAM,IAAI,GAAG,kBAAkB,CAAC,CAAC,CAAC,CAAA;IAClC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;IAE7B,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE;QACpB,MAAM,MAAM,GAAG,8CAA8C,CAAA;QAE7D,MAAM,OAAO,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,EAAE,yCAAyC,CAAC,CAAA;KAC5E;IAED,MAAM,QAAQ,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAA;IAE/C,IAAI,QAAQ,IAAI,IAAI,EAAE;QACpB,MAAM,MAAM,GAAG,4BAA4B,KAAK,CAAC,CAAC,CAAC,EAAE,CAAA;QAErD,MAAM,OAAO,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,EAAE,6BAA6B,CAAC,CAAA;KAChE;IAED,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE;QACxB,OAAO,CAAC,CAAA;KACT;IAED,OAAO,QAAQ,CAAC,CAAC,EAAE,OAAO,CAAC,CAAA;AAC7B,CAAC;AAED;;;;GAIG;AACH,SAAS,UAAU,CAAE,CAAa,EAAE,OAAqB;IACvD,OAAO,CAAC,CAAA;AACV,CAAC;AAED,MAAM,CAAC,MAAM,SAAS,GAAG;IACvB,UAAU;CACX,CAAA"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Convert a JavaScript date into an `RFC3339Nano` formatted
|
|
3
|
+
* string
|
|
4
|
+
*/
|
|
5
|
+
export declare function toRFC3339(time: Date): string;
|
|
6
|
+
/**
|
|
7
|
+
* Parses a date string formatted as `RFC3339Nano` into a
|
|
8
|
+
* JavaScript Date object
|
|
9
|
+
*/
|
|
10
|
+
export declare function parseRFC3339(time: string): Date;
|
|
11
|
+
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/utils.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,wBAAgB,SAAS,CAAE,IAAI,EAAE,IAAI,UAWpC;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAE,IAAI,EAAE,MAAM,QAwBzC"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Convert a JavaScript date into an `RFC3339Nano` formatted
|
|
3
|
+
* string
|
|
4
|
+
*/
|
|
5
|
+
export function toRFC3339(time) {
|
|
6
|
+
const year = time.getUTCFullYear();
|
|
7
|
+
const month = String(time.getUTCMonth() + 1).padStart(2, '0');
|
|
8
|
+
const day = String(time.getUTCDate()).padStart(2, '0');
|
|
9
|
+
const hour = String(time.getUTCHours()).padStart(2, '0');
|
|
10
|
+
const minute = String(time.getUTCMinutes()).padStart(2, '0');
|
|
11
|
+
const seconds = String(time.getUTCSeconds()).padStart(2, '0');
|
|
12
|
+
const milliseconds = time.getUTCMilliseconds();
|
|
13
|
+
const nanoseconds = milliseconds * 1000 * 1000;
|
|
14
|
+
return `${year}-${month}-${day}T${hour}:${minute}:${seconds}.${nanoseconds}Z`;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Parses a date string formatted as `RFC3339Nano` into a
|
|
18
|
+
* JavaScript Date object
|
|
19
|
+
*/
|
|
20
|
+
export function parseRFC3339(time) {
|
|
21
|
+
const rfc3339Matcher = new RegExp(
|
|
22
|
+
// 2006-01-02T
|
|
23
|
+
'(\\d{4})-(\\d{2})-(\\d{2})T' +
|
|
24
|
+
// 15:04:05
|
|
25
|
+
'(\\d{2}):(\\d{2}):(\\d{2})' +
|
|
26
|
+
// .999999999Z
|
|
27
|
+
'\\.(\\d+)Z');
|
|
28
|
+
const m = String(time).trim().match(rfc3339Matcher);
|
|
29
|
+
if (m == null) {
|
|
30
|
+
throw new Error('Invalid format');
|
|
31
|
+
}
|
|
32
|
+
const year = parseInt(m[1], 10);
|
|
33
|
+
const month = parseInt(m[2], 10) - 1;
|
|
34
|
+
const date = parseInt(m[3], 10);
|
|
35
|
+
const hour = parseInt(m[4], 10);
|
|
36
|
+
const minute = parseInt(m[5], 10);
|
|
37
|
+
const second = parseInt(m[6], 10);
|
|
38
|
+
const millisecond = parseInt(m[7].slice(0, -6), 10);
|
|
39
|
+
return new Date(Date.UTC(year, month, date, hour, minute, second, millisecond));
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/utils.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,UAAU,SAAS,CAAE,IAAU;IACnC,MAAM,IAAI,GAAG,IAAI,CAAC,cAAc,EAAE,CAAA;IAClC,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAA;IAC7D,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAA;IACtD,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAA;IACxD,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAA;IAC5D,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAA;IAC7D,MAAM,YAAY,GAAG,IAAI,CAAC,kBAAkB,EAAE,CAAA;IAC9C,MAAM,WAAW,GAAG,YAAY,GAAG,IAAI,GAAG,IAAI,CAAA;IAE9C,OAAO,GAAG,IAAI,IAAI,KAAK,IAAI,GAAG,IAAI,IAAI,IAAI,MAAM,IAAI,OAAO,IAAI,WAAW,GAAG,CAAA;AAC/E,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,YAAY,CAAE,IAAY;IACxC,MAAM,cAAc,GAAG,IAAI,MAAM;IAC/B,cAAc;IACd,6BAA6B;QAC7B,WAAW;QACX,4BAA4B;QAC5B,cAAc;QACd,YAAY,CACb,CAAA;IACD,MAAM,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,cAAc,CAAC,CAAA;IAEnD,IAAI,CAAC,IAAI,IAAI,EAAE;QACb,MAAM,IAAI,KAAK,CAAC,gBAAgB,CAAC,CAAA;KAClC;IAED,MAAM,IAAI,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAA;IAC/B,MAAM,KAAK,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAA;IACpC,MAAM,IAAI,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAA;IAC/B,MAAM,IAAI,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAA;IAC/B,MAAM,MAAM,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAA;IACjC,MAAM,MAAM,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAA;IACjC,MAAM,WAAW,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAA;IAEnD,OAAO,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC,CAAA;AACjF,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { Libp2pRecord } from './index.js';
|
|
2
|
+
import type { Validators } from '@libp2p/interfaces/dht';
|
|
3
|
+
/**
|
|
4
|
+
* Checks a record and ensures it is still valid.
|
|
5
|
+
* It runs the needed validators.
|
|
6
|
+
* If verification fails the returned Promise will reject with the error.
|
|
7
|
+
*/
|
|
8
|
+
export declare function verifyRecord(validators: Validators, record: Libp2pRecord): Promise<void> | undefined;
|
|
9
|
+
export declare const validators: {
|
|
10
|
+
publicKey: {
|
|
11
|
+
func: (key: Uint8Array, publicKey: Uint8Array) => Promise<void>;
|
|
12
|
+
sign: boolean;
|
|
13
|
+
};
|
|
14
|
+
};
|
|
15
|
+
//# sourceMappingURL=validators.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validators.d.ts","sourceRoot":"","sources":["../../src/validators.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAC9C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAA;AAIxD;;;;GAIG;AACH,wBAAgB,YAAY,CAAE,UAAU,EAAE,UAAU,EAAE,MAAM,EAAE,YAAY,6BAmBzE;AAwCD,eAAO,MAAM,UAAU;;oBA7BqB,UAAU,aAAa,UAAU;;;CA+B5E,CAAA"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import errcode from 'err-code';
|
|
2
|
+
import { toString as uint8ArrayToString } from 'uint8arrays/to-string';
|
|
3
|
+
import { sha256 } from 'multiformats/hashes/sha2';
|
|
4
|
+
import { equals as uint8ArrayEquals } from 'uint8arrays/equals';
|
|
5
|
+
/**
|
|
6
|
+
* Checks a record and ensures it is still valid.
|
|
7
|
+
* It runs the needed validators.
|
|
8
|
+
* If verification fails the returned Promise will reject with the error.
|
|
9
|
+
*/
|
|
10
|
+
export function verifyRecord(validators, record) {
|
|
11
|
+
const key = record.key;
|
|
12
|
+
const keyString = uint8ArrayToString(key);
|
|
13
|
+
const parts = keyString.split('/');
|
|
14
|
+
if (parts.length < 3) {
|
|
15
|
+
// No validator available
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
const validator = validators[parts[1].toString()];
|
|
19
|
+
if (validator == null) {
|
|
20
|
+
const errMsg = 'Invalid record keytype';
|
|
21
|
+
throw errcode(new Error(errMsg), 'ERR_INVALID_RECORD_KEY_TYPE');
|
|
22
|
+
}
|
|
23
|
+
return validator.func(key, record.value);
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Validator for public key records.
|
|
27
|
+
* Verifies that the passed in record value is the PublicKey
|
|
28
|
+
* that matches the passed in key.
|
|
29
|
+
* If validation fails the returned Promise will reject with the error.
|
|
30
|
+
*
|
|
31
|
+
* @param {Uint8Array} key - A valid key is of the form `'/pk/<keymultihash>'`
|
|
32
|
+
* @param {Uint8Array} publicKey - The public key to validate against (protobuf encoded).
|
|
33
|
+
*/
|
|
34
|
+
const validatePublicKeyRecord = async (key, publicKey) => {
|
|
35
|
+
if (!(key instanceof Uint8Array)) {
|
|
36
|
+
throw errcode(new Error('"key" must be a Uint8Array'), 'ERR_INVALID_RECORD_KEY_NOT_BUFFER');
|
|
37
|
+
}
|
|
38
|
+
if (key.byteLength < 5) {
|
|
39
|
+
throw errcode(new Error('invalid public key record'), 'ERR_INVALID_RECORD_KEY_TOO_SHORT');
|
|
40
|
+
}
|
|
41
|
+
const prefix = uint8ArrayToString(key.subarray(0, 4));
|
|
42
|
+
if (prefix !== '/pk/') {
|
|
43
|
+
throw errcode(new Error('key was not prefixed with /pk/'), 'ERR_INVALID_RECORD_KEY_BAD_PREFIX');
|
|
44
|
+
}
|
|
45
|
+
const keyhash = key.slice(4);
|
|
46
|
+
const publicKeyHash = await sha256.digest(publicKey);
|
|
47
|
+
if (!uint8ArrayEquals(keyhash, publicKeyHash.bytes)) {
|
|
48
|
+
throw errcode(new Error('public key does not match passed in key'), 'ERR_INVALID_RECORD_HASH_MISMATCH');
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
const publicKey = {
|
|
52
|
+
func: validatePublicKeyRecord,
|
|
53
|
+
sign: false
|
|
54
|
+
};
|
|
55
|
+
export const validators = {
|
|
56
|
+
publicKey
|
|
57
|
+
};
|
|
58
|
+
//# sourceMappingURL=validators.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validators.js","sourceRoot":"","sources":["../../src/validators.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,UAAU,CAAA;AAC9B,OAAO,EAAE,QAAQ,IAAI,kBAAkB,EAAE,MAAM,uBAAuB,CAAA;AAGtE,OAAO,EAAE,MAAM,EAAE,MAAM,0BAA0B,CAAA;AACjD,OAAO,EAAE,MAAM,IAAI,gBAAgB,EAAE,MAAM,oBAAoB,CAAA;AAE/D;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAAE,UAAsB,EAAE,MAAoB;IACxE,MAAM,GAAG,GAAG,MAAM,CAAC,GAAG,CAAA;IACtB,MAAM,SAAS,GAAG,kBAAkB,CAAC,GAAG,CAAC,CAAA;IACzC,MAAM,KAAK,GAAG,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;IAElC,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE;QACpB,yBAAyB;QACzB,OAAM;KACP;IAED,MAAM,SAAS,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAA;IAEjD,IAAI,SAAS,IAAI,IAAI,EAAE;QACrB,MAAM,MAAM,GAAG,wBAAwB,CAAA;QAEvC,MAAM,OAAO,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,EAAE,6BAA6B,CAAC,CAAA;KAChE;IAED,OAAO,SAAS,CAAC,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,KAAK,CAAC,CAAA;AAC1C,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,uBAAuB,GAAG,KAAK,EAAE,GAAe,EAAE,SAAqB,EAAE,EAAE;IAC/E,IAAI,CAAC,CAAC,GAAG,YAAY,UAAU,CAAC,EAAE;QAChC,MAAM,OAAO,CAAC,IAAI,KAAK,CAAC,4BAA4B,CAAC,EAAE,mCAAmC,CAAC,CAAA;KAC5F;IAED,IAAI,GAAG,CAAC,UAAU,GAAG,CAAC,EAAE;QACtB,MAAM,OAAO,CAAC,IAAI,KAAK,CAAC,2BAA2B,CAAC,EAAE,kCAAkC,CAAC,CAAA;KAC1F;IAED,MAAM,MAAM,GAAG,kBAAkB,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAA;IAErD,IAAI,MAAM,KAAK,MAAM,EAAE;QACrB,MAAM,OAAO,CAAC,IAAI,KAAK,CAAC,gCAAgC,CAAC,EAAE,mCAAmC,CAAC,CAAA;KAChG;IAED,MAAM,OAAO,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;IAE5B,MAAM,aAAa,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,CAAA;IAEpD,IAAI,CAAC,gBAAgB,CAAC,OAAO,EAAE,aAAa,CAAC,KAAK,CAAC,EAAE;QACnD,MAAM,OAAO,CAAC,IAAI,KAAK,CAAC,yCAAyC,CAAC,EAAE,kCAAkC,CAAC,CAAA;KACxG;AACH,CAAC,CAAA;AAED,MAAM,SAAS,GAAG;IAChB,IAAI,EAAE,uBAAuB;IAC7B,IAAI,EAAE,KAAK;CACZ,CAAA;AAED,MAAM,CAAC,MAAM,UAAU,GAAG;IACxB,SAAS;CACV,CAAA"}
|