nostr-double-ratchet 0.0.31 → 0.0.33
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/README.md +4 -2
- package/dist/Invite.d.ts +5 -0
- package/dist/Invite.d.ts.map +1 -1
- package/dist/SessionManager.d.ts +2 -1
- package/dist/SessionManager.d.ts.map +1 -1
- package/dist/UserRecord.d.ts +78 -31
- package/dist/UserRecord.d.ts.map +1 -1
- package/dist/nostr-double-ratchet.es.js +360 -335
- package/dist/nostr-double-ratchet.umd.js +1 -1
- package/package.json +4 -4
- package/src/Invite.ts +25 -0
- package/src/SessionManager.ts +18 -11
- package/src/UserRecord.ts +235 -146
package/README.md
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
|
+
[](https://deepwiki.com/mmalmi/nostr-double-ratchet)
|
|
2
|
+
|
|
1
3
|
* Double ratchet on nostr
|
|
2
4
|
- [x] 1-on-1 channel
|
|
3
5
|
- [ ] group channel
|
|
4
6
|
* Invites for securely exchanging session keys
|
|
5
7
|
* Breaking changes are likely
|
|
6
8
|
* Stable version on [NPM](https://www.npmjs.com/package/nostr-double-ratchet)
|
|
7
|
-
* check out [tests](https://github.com/mmalmi/nostr-double-ratchet/tree/
|
|
8
|
-
* [Documentation](https://nostr-double-ratchet
|
|
9
|
+
* check out [tests](https://github.com/mmalmi/nostr-double-ratchet/tree/main/tests) for usage
|
|
10
|
+
* [Documentation](https://mmalmi.github.io/nostr-double-ratchet/)
|
|
9
11
|
* [Source code](https://github.com/mmalmi/nostr-double-ratchet)
|
|
10
12
|
|
|
11
13
|
## Installation
|
package/dist/Invite.d.ts
CHANGED
|
@@ -34,6 +34,11 @@ export declare class Invite {
|
|
|
34
34
|
*/
|
|
35
35
|
getUrl(root?: string): string;
|
|
36
36
|
getEvent(): UnsignedEvent;
|
|
37
|
+
/**
|
|
38
|
+
* Creates an "invite tombstone" event that clears the original content and removes the list tag.
|
|
39
|
+
* Used when the inviter logs out and wants to make the invite invisible to other devices.
|
|
40
|
+
*/
|
|
41
|
+
getDeletionEvent(): UnsignedEvent;
|
|
37
42
|
/**
|
|
38
43
|
* Called by the invitee. Accepts the invite and creates a new session with the inviter.
|
|
39
44
|
*
|
package/dist/Invite.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Invite.d.ts","sourceRoot":"","sources":["../src/Invite.ts"],"names":[],"mappings":"AAAA,OAAO,EAAyD,aAAa,EAAE,aAAa,EAAuB,MAAM,aAAa,CAAC;AACvI,OAAO,EAAqB,cAAc,EAAE,WAAW,EAAE,eAAe,EAAE,eAAe,EAAwB,MAAM,SAAS,CAAC;AAEjI,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAQvC;;;;;;;;;GASG;AACH,qBAAa,MAAM;IAEJ,yBAAyB,EAAE,MAAM;IACjC,YAAY,EAAE,MAAM;IACpB,OAAO,EAAE,MAAM;IACf,0BAA0B,CAAC,EAAE,UAAU;IACvC,QAAQ,CAAC,EAAE,MAAM;IACjB,OAAO,CAAC,EAAE,MAAM;IAChB,MAAM,EAAE,MAAM,EAAE;gBANhB,yBAAyB,EAAE,MAAM,EACjC,YAAY,EAAE,MAAM,EACpB,OAAO,EAAE,MAAM,EACf,0BAA0B,CAAC,EAAE,UAAU,YAAA,EACvC,QAAQ,CAAC,EAAE,MAAM,YAAA,EACjB,OAAO,CAAC,EAAE,MAAM,YAAA,EAChB,MAAM,GAAE,MAAM,EAAO;IAIhC,MAAM,CAAC,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM;IAiB9E,MAAM,CAAC,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM;IA2BnC,MAAM,CAAC,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;IAaxC,MAAM,CAAC,SAAS,CAAC,KAAK,EAAE,aAAa,GAAG,MAAM;IAkC9C,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,cAAc,EAAE,QAAQ,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,GAAG,WAAW;
|
|
1
|
+
{"version":3,"file":"Invite.d.ts","sourceRoot":"","sources":["../src/Invite.ts"],"names":[],"mappings":"AAAA,OAAO,EAAyD,aAAa,EAAE,aAAa,EAAuB,MAAM,aAAa,CAAC;AACvI,OAAO,EAAqB,cAAc,EAAE,WAAW,EAAE,eAAe,EAAE,eAAe,EAAwB,MAAM,SAAS,CAAC;AAEjI,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAQvC;;;;;;;;;GASG;AACH,qBAAa,MAAM;IAEJ,yBAAyB,EAAE,MAAM;IACjC,YAAY,EAAE,MAAM;IACpB,OAAO,EAAE,MAAM;IACf,0BAA0B,CAAC,EAAE,UAAU;IACvC,QAAQ,CAAC,EAAE,MAAM;IACjB,OAAO,CAAC,EAAE,MAAM;IAChB,MAAM,EAAE,MAAM,EAAE;gBANhB,yBAAyB,EAAE,MAAM,EACjC,YAAY,EAAE,MAAM,EACpB,OAAO,EAAE,MAAM,EACf,0BAA0B,CAAC,EAAE,UAAU,YAAA,EACvC,QAAQ,CAAC,EAAE,MAAM,YAAA,EACjB,OAAO,CAAC,EAAE,MAAM,YAAA,EAChB,MAAM,GAAE,MAAM,EAAO;IAIhC,MAAM,CAAC,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM;IAiB9E,MAAM,CAAC,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM;IA2BnC,MAAM,CAAC,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;IAaxC,MAAM,CAAC,SAAS,CAAC,KAAK,EAAE,aAAa,GAAG,MAAM;IAkC9C,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,cAAc,EAAE,QAAQ,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,GAAG,WAAW;IAwB1G;;OAEG;IACH,SAAS,IAAI,MAAM;IAYnB;;OAEG;IACH,MAAM,CAAC,IAAI,SAAoB;IAW/B,QAAQ,IAAI,aAAa;IAkBzB;;;OAGG;IACH,gBAAgB,IAAI,aAAa;IAiBjC;;;;;;;;;;;;;;;OAeG;IACG,MAAM,CACR,cAAc,EAAE,cAAc,EAC9B,gBAAgB,EAAE,MAAM,EACxB,SAAS,EAAE,UAAU,GAAG,eAAe,GACxC,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,KAAK,EAAE,aAAa,CAAA;KAAE,CAAC;IAsCtD,MAAM,CAAC,SAAS,EAAE,UAAU,GAAG,eAAe,EAAE,cAAc,EAAE,cAAc,EAAE,SAAS,EAAE,CAAC,QAAQ,EAAE,OAAO,EAAE,SAAS,CAAC,EAAE,MAAM,KAAK,IAAI,GAAG,WAAW;CA0C3J"}
|
package/dist/SessionManager.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { NostrPublish, NostrSubscribe, Rumor } from "./types";
|
|
2
2
|
import { Invite } from "./Invite";
|
|
3
3
|
import { StorageAdapter } from "./StorageAdapter";
|
|
4
|
+
export type OnEventCallback = (event: Rumor, from: string) => void;
|
|
4
5
|
export default class SessionManager {
|
|
5
6
|
private userRecords;
|
|
6
7
|
private nostrSubscribe;
|
|
@@ -28,7 +29,7 @@ export default class SessionManager {
|
|
|
28
29
|
listenToUser(userPubkey: string): void;
|
|
29
30
|
stopListeningToUser(userPubkey: string): void;
|
|
30
31
|
private internalSubscriptions;
|
|
31
|
-
onEvent(callback:
|
|
32
|
+
onEvent(callback: OnEventCallback): () => void;
|
|
32
33
|
close(): void;
|
|
33
34
|
/**
|
|
34
35
|
* Accept an invite as our own device, persist the session, and publish the acceptance event.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SessionManager.d.ts","sourceRoot":"","sources":["../src/SessionManager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAqB,YAAY,EAAE,cAAc,EAAE,KAAK,EAAe,MAAM,SAAS,CAAA;AAE7F,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAA;AAEjC,OAAO,EAAE,cAAc,EAA0B,MAAM,kBAAkB,CAAA;AAIzE,MAAM,CAAC,OAAO,OAAO,cAAc;IAC/B,OAAO,CAAC,WAAW,CAAqC;IACxD,OAAO,CAAC,cAAc,CAAgB;IACtC,OAAO,CAAC,YAAY,CAAc;IAClC,OAAO,CAAC,cAAc,CAAY;IAClC,OAAO,CAAC,kBAAkB,CAAsC;IAChE,OAAO,CAAC,QAAQ,CAAQ;IACxB,OAAO,CAAC,MAAM,CAAC,CAAQ;IACvB,OAAO,CAAC,OAAO,CAAgB;IAC/B,OAAO,CAAC,YAAY,CAA4F;gBAG5G,cAAc,EAAE,UAAU,EAC1B,QAAQ,EAAE,MAAM,EAChB,cAAc,EAAE,cAAc,EAC9B,YAAY,EAAE,YAAY,EAC1B,OAAO,GAAE,cAA6C;IAc1D,OAAO,CAAC,YAAY,CAAQ;IAE5B;;;;OAIG;IACU,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"SessionManager.d.ts","sourceRoot":"","sources":["../src/SessionManager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAqB,YAAY,EAAE,cAAc,EAAE,KAAK,EAAe,MAAM,SAAS,CAAA;AAE7F,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAA;AAEjC,OAAO,EAAE,cAAc,EAA0B,MAAM,kBAAkB,CAAA;AAIzE,MAAM,MAAM,eAAe,GAAG,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;AAElE,MAAM,CAAC,OAAO,OAAO,cAAc;IAC/B,OAAO,CAAC,WAAW,CAAqC;IACxD,OAAO,CAAC,cAAc,CAAgB;IACtC,OAAO,CAAC,YAAY,CAAc;IAClC,OAAO,CAAC,cAAc,CAAY;IAClC,OAAO,CAAC,kBAAkB,CAAsC;IAChE,OAAO,CAAC,QAAQ,CAAQ;IACxB,OAAO,CAAC,MAAM,CAAC,CAAQ;IACvB,OAAO,CAAC,OAAO,CAAgB;IAC/B,OAAO,CAAC,YAAY,CAA4F;gBAG5G,cAAc,EAAE,UAAU,EAC1B,QAAQ,EAAE,MAAM,EAChB,cAAc,EAAE,cAAc,EAC9B,YAAY,EAAE,YAAY,EAC1B,OAAO,GAAE,cAA6C;IAc1D,OAAO,CAAC,YAAY,CAAQ;IAE5B;;;;OAIG;IACU,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;YAwGpB,YAAY;YAiCZ,WAAW;IAOzB,WAAW,IAAI,MAAM;IAIrB,SAAS,IAAI,MAAM;IAOb,QAAQ,CAAC,oBAAoB,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM;IAQnD,SAAS,CAAC,oBAAoB,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,CAAC;IA4DnE,YAAY,CAAC,UAAU,EAAE,MAAM;IA8D/B,mBAAmB,CAAC,UAAU,EAAE,MAAM;IAStC,OAAO,CAAC,qBAAqB,CAAkC;IAE/D,OAAO,CAAC,QAAQ,EAAE,eAAe;IAkBjC,KAAK;IAiBL;;;OAGG;IACU,eAAe,CAAC,MAAM,EAAE,MAAM;CAgB9C"}
|
package/dist/UserRecord.d.ts
CHANGED
|
@@ -1,30 +1,71 @@
|
|
|
1
1
|
import { Session } from './Session';
|
|
2
2
|
import { NostrSubscribe } from './types';
|
|
3
|
+
interface DeviceRecord {
|
|
4
|
+
deviceId: string;
|
|
5
|
+
publicKey: string;
|
|
6
|
+
activeSession?: Session;
|
|
7
|
+
inactiveSessions: Session[];
|
|
8
|
+
isStale: boolean;
|
|
9
|
+
staleTimestamp?: number;
|
|
10
|
+
lastActivity?: number;
|
|
11
|
+
}
|
|
3
12
|
/**
|
|
4
|
-
*
|
|
5
|
-
*
|
|
13
|
+
* Manages sessions for a single user across multiple devices
|
|
14
|
+
* Structure: UserRecord → DeviceRecord → Sessions
|
|
6
15
|
*/
|
|
7
16
|
export declare class UserRecord {
|
|
8
|
-
|
|
9
|
-
private
|
|
17
|
+
readonly userId: string;
|
|
18
|
+
private readonly nostrSubscribe;
|
|
10
19
|
private deviceRecords;
|
|
11
20
|
private isStale;
|
|
12
21
|
private staleTimestamp?;
|
|
13
|
-
constructor(
|
|
22
|
+
constructor(userId: string, nostrSubscribe: NostrSubscribe);
|
|
14
23
|
/**
|
|
15
|
-
*
|
|
24
|
+
* Creates or updates a device record for this user
|
|
16
25
|
*/
|
|
17
|
-
|
|
26
|
+
upsertDevice(deviceId: string, publicKey: string): DeviceRecord;
|
|
18
27
|
/**
|
|
19
|
-
*
|
|
28
|
+
* Gets a device record by deviceId
|
|
20
29
|
*/
|
|
21
|
-
|
|
30
|
+
getDevice(deviceId: string): DeviceRecord | undefined;
|
|
31
|
+
/**
|
|
32
|
+
* Gets all device records for this user
|
|
33
|
+
*/
|
|
34
|
+
getAllDevices(): DeviceRecord[];
|
|
22
35
|
/**
|
|
23
|
-
*
|
|
36
|
+
* Gets all active (non-stale) device records
|
|
24
37
|
*/
|
|
25
|
-
|
|
38
|
+
getActiveDevices(): DeviceRecord[];
|
|
39
|
+
/**
|
|
40
|
+
* Removes a device record and closes all its sessions
|
|
41
|
+
*/
|
|
42
|
+
removeDevice(deviceId: string): boolean;
|
|
43
|
+
/**
|
|
44
|
+
* Adds or updates a session for a specific device
|
|
45
|
+
*/
|
|
46
|
+
upsertSession(deviceId: string, session: Session, publicKey?: string): void;
|
|
47
|
+
/**
|
|
48
|
+
* Gets the active session for a specific device
|
|
49
|
+
*/
|
|
50
|
+
getActiveSession(deviceId: string): Session | undefined;
|
|
51
|
+
/**
|
|
52
|
+
* Gets all sessions (active + inactive) for a specific device
|
|
53
|
+
*/
|
|
54
|
+
getDeviceSessions(deviceId: string): Session[];
|
|
55
|
+
/**
|
|
56
|
+
* Gets all active sessions across all devices for this user
|
|
57
|
+
*/
|
|
58
|
+
getActiveSessions(): Session[];
|
|
59
|
+
/**
|
|
60
|
+
* Gets all sessions (active + inactive) across all devices
|
|
61
|
+
*/
|
|
62
|
+
getAllSessions(): Session[];
|
|
26
63
|
/**
|
|
27
|
-
*
|
|
64
|
+
* Gets sessions that are ready to send messages
|
|
65
|
+
*/
|
|
66
|
+
getSendableSessions(): Session[];
|
|
67
|
+
/**
|
|
68
|
+
* Marks a specific device as stale
|
|
28
69
|
*/
|
|
29
70
|
markDeviceStale(deviceId: string): void;
|
|
30
71
|
/**
|
|
@@ -32,39 +73,45 @@ export declare class UserRecord {
|
|
|
32
73
|
*/
|
|
33
74
|
markUserStale(): void;
|
|
34
75
|
/**
|
|
35
|
-
*
|
|
76
|
+
* Removes stale devices and sessions older than maxLatency
|
|
36
77
|
*/
|
|
37
|
-
|
|
78
|
+
pruneStaleRecords(maxLatency: number): void;
|
|
38
79
|
/**
|
|
39
|
-
*
|
|
80
|
+
* Gets the most recently active device
|
|
40
81
|
*/
|
|
41
|
-
|
|
82
|
+
getMostActiveDevice(): DeviceRecord | undefined;
|
|
42
83
|
/**
|
|
43
|
-
*
|
|
84
|
+
* Gets the preferred session (from most active device)
|
|
44
85
|
*/
|
|
45
|
-
|
|
86
|
+
getPreferredSession(): Session | undefined;
|
|
87
|
+
/**
|
|
88
|
+
* Checks if this user has any active sessions
|
|
89
|
+
*/
|
|
90
|
+
hasActiveSessions(): boolean;
|
|
91
|
+
/**
|
|
92
|
+
* Gets total count of devices
|
|
93
|
+
*/
|
|
94
|
+
getDeviceCount(): number;
|
|
95
|
+
/**
|
|
96
|
+
* Gets total count of active sessions
|
|
97
|
+
*/
|
|
98
|
+
getActiveSessionCount(): number;
|
|
46
99
|
/**
|
|
47
100
|
* Cleanup when destroying the user record
|
|
48
101
|
*/
|
|
49
102
|
close(): void;
|
|
50
103
|
/**
|
|
51
|
-
*
|
|
52
|
-
* For now this means any session in a non-stale device record as well as
|
|
53
|
-
* all sessions added through `addSession`.
|
|
54
|
-
* Prioritizes initiator sessions (can send first message) over responder sessions.
|
|
104
|
+
* @deprecated Use upsertDevice instead
|
|
55
105
|
*/
|
|
56
|
-
|
|
106
|
+
conditionalUpdate(deviceId: string, publicKey: string): void;
|
|
57
107
|
/**
|
|
58
|
-
*
|
|
59
|
-
* user. This is required for `SessionManager.onEvent` so that it can attach
|
|
60
|
-
* listeners to existing sessions.
|
|
108
|
+
* @deprecated Use upsertSession instead
|
|
61
109
|
*/
|
|
62
|
-
|
|
110
|
+
insertSession(deviceId: string, session: Session): void;
|
|
63
111
|
/**
|
|
64
|
-
*
|
|
65
|
-
* (if deviceId provided **and** the record exists) or falls back to the
|
|
66
|
-
* legacy extraSessions list.
|
|
112
|
+
* Creates a new session for a device
|
|
67
113
|
*/
|
|
68
|
-
|
|
114
|
+
createSession(deviceId: string, sharedSecret: Uint8Array, ourCurrentPrivateKey: Uint8Array, isInitiator: boolean, name?: string): Session;
|
|
69
115
|
}
|
|
116
|
+
export {};
|
|
70
117
|
//# sourceMappingURL=UserRecord.d.ts.map
|
package/dist/UserRecord.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"UserRecord.d.ts","sourceRoot":"","sources":["../src/UserRecord.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"UserRecord.d.ts","sourceRoot":"","sources":["../src/UserRecord.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAEzC,UAAU,YAAY;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,gBAAgB,EAAE,OAAO,EAAE,CAAC;IAC5B,OAAO,EAAE,OAAO,CAAC;IACjB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;;GAGG;AACH,qBAAa,UAAU;aAMH,MAAM,EAAE,MAAM;IAC9B,OAAO,CAAC,QAAQ,CAAC,cAAc;IANjC,OAAO,CAAC,aAAa,CAAwC;IAC7D,OAAO,CAAC,OAAO,CAAkB;IACjC,OAAO,CAAC,cAAc,CAAC,CAAS;gBAGd,MAAM,EAAE,MAAM,EACb,cAAc,EAAE,cAAc;IAQjD;;OAEG;IACI,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,YAAY;IAyBtE;;OAEG;IACI,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS;IAI5D;;OAEG;IACI,aAAa,IAAI,YAAY,EAAE;IAItC;;OAEG;IACI,gBAAgB,IAAI,YAAY,EAAE;IAKzC;;OAEG;IACI,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO;IAe9C;;OAEG;IACI,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI;IAclF;;OAEG;IACI,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS;IAK9D;;OAEG;IACI,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,EAAE;IAYrD;;OAEG;IACI,iBAAiB,IAAI,OAAO,EAAE;IAsBrC;;OAEG;IACI,cAAc,IAAI,OAAO,EAAE;IAalC;;OAEG;IACI,mBAAmB,IAAI,OAAO,EAAE;IAUvC;;OAEG;IACI,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAQ9C;;OAEG;IACI,aAAa,IAAI,IAAI;IAK5B;;OAEG;IACI,iBAAiB,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI;IAsBlD;;OAEG;IACI,mBAAmB,IAAI,YAAY,GAAG,SAAS;IAWtD;;OAEG;IACI,mBAAmB,IAAI,OAAO,GAAG,SAAS;IAKjD;;OAEG;IACI,iBAAiB,IAAI,OAAO;IAInC;;OAEG;IACI,cAAc,IAAI,MAAM;IAI/B;;OAEG;IACI,qBAAqB,IAAI,MAAM;IAItC;;OAEG;IACI,KAAK,IAAI,IAAI;IAYpB;;OAEG;IACI,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI;IAInE;;OAEG;IACI,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,IAAI;IAI9D;;OAEG;IACI,aAAa,CAClB,QAAQ,EAAE,MAAM,EAChB,YAAY,EAAE,UAAU,EACxB,oBAAoB,EAAE,UAAU,EAChC,WAAW,EAAE,OAAO,EACpB,IAAI,CAAC,EAAE,MAAM,GACZ,OAAO;CAkBX"}
|