@rotorsoft/act 0.6.27 → 0.6.29
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/.tsbuildinfo +1 -1
- package/dist/@types/act-builder.d.ts +286 -41
- package/dist/@types/act-builder.d.ts.map +1 -1
- package/dist/@types/act.d.ts +354 -52
- package/dist/@types/act.d.ts.map +1 -1
- package/dist/@types/adapters/InMemoryStore.d.ts +59 -8
- package/dist/@types/adapters/InMemoryStore.d.ts.map +1 -1
- package/dist/@types/config.d.ts +54 -6
- package/dist/@types/config.d.ts.map +1 -1
- package/dist/@types/ports.d.ts +149 -10
- package/dist/@types/ports.d.ts.map +1 -1
- package/dist/@types/state-builder.d.ts +318 -43
- package/dist/@types/state-builder.d.ts.map +1 -1
- package/dist/@types/types/action.d.ts +122 -10
- package/dist/@types/types/action.d.ts.map +1 -1
- package/dist/@types/types/errors.d.ts +211 -22
- package/dist/@types/types/errors.d.ts.map +1 -1
- package/dist/@types/types/ports.d.ts +204 -28
- package/dist/@types/types/ports.d.ts.map +1 -1
- package/dist/@types/types/reaction.d.ts +107 -18
- package/dist/@types/types/reaction.d.ts.map +1 -1
- package/dist/@types/utils.d.ts +378 -27
- package/dist/@types/utils.d.ts.map +1 -1
- package/dist/index.cjs +352 -50
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +352 -50
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
|
@@ -7,11 +7,53 @@ import { ActorSchema, CausationEventSchema, CommittedMetaSchema, EventMetaSchema
|
|
|
7
7
|
* Types for actions, events, schemas, and state in the Act Framework.
|
|
8
8
|
*/
|
|
9
9
|
/**
|
|
10
|
-
* Represents an actor (user
|
|
10
|
+
* Represents an actor (user or system) performing an action.
|
|
11
|
+
*
|
|
12
|
+
* Actors provide audit trail and authorization context. Every action
|
|
13
|
+
* must specify who is performing it for accountability and access control.
|
|
14
|
+
*
|
|
15
|
+
* @example User actor
|
|
16
|
+
* ```typescript
|
|
17
|
+
* const actor: Actor = {
|
|
18
|
+
* id: "user-123",
|
|
19
|
+
* name: "Alice Smith"
|
|
20
|
+
* };
|
|
21
|
+
* ```
|
|
22
|
+
*
|
|
23
|
+
* @example System actor
|
|
24
|
+
* ```typescript
|
|
25
|
+
* const systemActor: Actor = {
|
|
26
|
+
* id: "system",
|
|
27
|
+
* name: "Background Job"
|
|
28
|
+
* };
|
|
29
|
+
* ```
|
|
11
30
|
*/
|
|
12
31
|
export type Actor = z.infer<typeof ActorSchema>;
|
|
13
32
|
/**
|
|
14
|
-
*
|
|
33
|
+
* Target specification for action execution.
|
|
34
|
+
*
|
|
35
|
+
* Identifies which state instance (stream) should process the action
|
|
36
|
+
* and who is performing it. The target combines the stream identifier
|
|
37
|
+
* with actor context for complete audit trail.
|
|
38
|
+
*
|
|
39
|
+
* @example Basic target
|
|
40
|
+
* ```typescript
|
|
41
|
+
* const target: Target = {
|
|
42
|
+
* stream: "user-123",
|
|
43
|
+
* actor: { id: "admin", name: "Admin User" }
|
|
44
|
+
* };
|
|
45
|
+
*
|
|
46
|
+
* await app.do("updateProfile", target, { email: "new@example.com" });
|
|
47
|
+
* ```
|
|
48
|
+
*
|
|
49
|
+
* @example Dynamic stream ID
|
|
50
|
+
* ```typescript
|
|
51
|
+
* const userId = "user-" + Date.now();
|
|
52
|
+
* await app.do("createUser", {
|
|
53
|
+
* stream: userId,
|
|
54
|
+
* actor: currentUser
|
|
55
|
+
* }, userData);
|
|
56
|
+
* ```
|
|
15
57
|
*/
|
|
16
58
|
export type Target = z.infer<typeof TargetSchema>;
|
|
17
59
|
/**
|
|
@@ -69,28 +111,98 @@ export type ZodTypes<T extends Schemas> = {
|
|
|
69
111
|
};
|
|
70
112
|
/**
|
|
71
113
|
* Represents a message (event or action) with a name and data payload.
|
|
72
|
-
*
|
|
73
|
-
*
|
|
114
|
+
*
|
|
115
|
+
* Messages are the basic building blocks of the event log. Each message
|
|
116
|
+
* has a name (event type) and data (event payload).
|
|
117
|
+
*
|
|
118
|
+
* @template E - Schemas map
|
|
119
|
+
* @template K - Event/action name
|
|
120
|
+
*
|
|
121
|
+
* @example
|
|
122
|
+
* ```typescript
|
|
123
|
+
* const message: Message<{ Incremented: { amount: number } }, "Incremented"> = {
|
|
124
|
+
* name: "Incremented",
|
|
125
|
+
* data: { amount: 5 }
|
|
126
|
+
* };
|
|
127
|
+
* ```
|
|
74
128
|
*/
|
|
75
129
|
export type Message<E extends Schemas, K extends keyof E> = {
|
|
130
|
+
/** The event or action name */
|
|
76
131
|
readonly name: K;
|
|
132
|
+
/** The event or action payload */
|
|
77
133
|
readonly data: Readonly<E[K]>;
|
|
78
134
|
};
|
|
79
135
|
/**
|
|
80
|
-
* A committed event
|
|
81
|
-
*
|
|
82
|
-
*
|
|
136
|
+
* A committed event with complete metadata.
|
|
137
|
+
*
|
|
138
|
+
* Committed events include the message data plus metadata about when and how
|
|
139
|
+
* the event was created, including correlation and causation information for
|
|
140
|
+
* tracing event-driven workflows.
|
|
141
|
+
*
|
|
142
|
+
* @template E - Schemas map
|
|
143
|
+
* @template K - Event name
|
|
144
|
+
*
|
|
145
|
+
* @example
|
|
146
|
+
* ```typescript
|
|
147
|
+
* // Committed events include:
|
|
148
|
+
* // - id: global sequence number
|
|
149
|
+
* // - stream: which state instance
|
|
150
|
+
* // - version: event number within stream
|
|
151
|
+
* // - created: timestamp
|
|
152
|
+
* // - meta: correlation and causation
|
|
153
|
+
*
|
|
154
|
+
* app.on("committed", (snapshots) => {
|
|
155
|
+
* snapshots.forEach(snap => {
|
|
156
|
+
* if (snap.event) {
|
|
157
|
+
* console.log(`Event ${snap.event.name} #${snap.event.id}`);
|
|
158
|
+
* console.log(`Stream: ${snap.event.stream} v${snap.event.version}`);
|
|
159
|
+
* console.log(`Data:`, snap.event.data);
|
|
160
|
+
* }
|
|
161
|
+
* });
|
|
162
|
+
* });
|
|
163
|
+
* ```
|
|
164
|
+
*
|
|
165
|
+
* @see {@link CommittedMeta} for metadata structure
|
|
83
166
|
*/
|
|
84
167
|
export type Committed<E extends Schemas, K extends keyof E> = Message<E, K> & CommittedMeta;
|
|
85
168
|
/**
|
|
86
|
-
*
|
|
87
|
-
*
|
|
88
|
-
*
|
|
169
|
+
* Snapshot of state at a specific point in time.
|
|
170
|
+
*
|
|
171
|
+
* Snapshots represent the current state after applying events. They include
|
|
172
|
+
* metadata about how many events have been applied (patches) and how many
|
|
173
|
+
* snapshots have been taken for optimization.
|
|
174
|
+
*
|
|
175
|
+
* @template S - State schema
|
|
176
|
+
* @template E - Event schemas
|
|
177
|
+
*
|
|
178
|
+
* @example
|
|
179
|
+
* ```typescript
|
|
180
|
+
* const snapshot = await app.load(Counter, "counter-1");
|
|
181
|
+
*
|
|
182
|
+
* console.log(snapshot.state); // { count: 42 }
|
|
183
|
+
* console.log(snapshot.patches); // 8 (events since last snapshot)
|
|
184
|
+
* console.log(snapshot.snaps); // 1 (1 snapshot taken)
|
|
185
|
+
* console.log(snapshot.event); // Last event that created this snapshot
|
|
186
|
+
* ```
|
|
187
|
+
*
|
|
188
|
+
* @example Using snapshot in action handler
|
|
189
|
+
* ```typescript
|
|
190
|
+
* .on("increment", z.object({ by: z.number() }))
|
|
191
|
+
* .emit((action, snapshot) => {
|
|
192
|
+
* console.log("Current count:", snapshot.state.count);
|
|
193
|
+
* console.log("Events applied:", snapshot.patches);
|
|
194
|
+
* return ["Incremented", { amount: action.by }];
|
|
195
|
+
* })
|
|
196
|
+
* ```
|
|
89
197
|
*/
|
|
90
198
|
export type Snapshot<S extends Schema, E extends Schemas> = {
|
|
199
|
+
/** Current state data */
|
|
91
200
|
readonly state: S;
|
|
201
|
+
/** Event that created this snapshot (undefined for initial state) */
|
|
92
202
|
readonly event?: Committed<E, keyof E>;
|
|
203
|
+
/** Number of patches applied since last snapshot */
|
|
93
204
|
readonly patches: number;
|
|
205
|
+
/** Number of snapshots taken for this stream */
|
|
94
206
|
readonly snaps: number;
|
|
95
207
|
};
|
|
96
208
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"action.d.ts","sourceRoot":"","sources":["../../../src/types/action.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,MAAM,KAAK,CAAC;AACjC,OAAO,EACL,WAAW,EACX,oBAAoB,EACpB,mBAAmB,EACnB,eAAe,EACf,WAAW,EACX,YAAY,EACb,MAAM,cAAc,CAAC;AAEtB;;;;;GAKG;AAEH
|
|
1
|
+
{"version":3,"file":"action.d.ts","sourceRoot":"","sources":["../../../src/types/action.ts"],"names":[],"mappings":"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"}
|
|
@@ -15,49 +15,238 @@ export declare const Errors: {
|
|
|
15
15
|
readonly ConcurrencyError: "ERR_CONCURRENCY";
|
|
16
16
|
};
|
|
17
17
|
/**
|
|
18
|
-
* Thrown when
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
18
|
+
* Thrown when an action or event payload fails Zod schema validation.
|
|
19
|
+
*
|
|
20
|
+
* This error indicates that data doesn't match the expected schema defined
|
|
21
|
+
* for an action or event. The `details` property contains the Zod validation
|
|
22
|
+
* error with specific information about what failed.
|
|
23
|
+
*
|
|
24
|
+
* @example Catching validation errors
|
|
25
|
+
* ```typescript
|
|
26
|
+
* import { ValidationError } from "@rotorsoft/act";
|
|
27
|
+
*
|
|
28
|
+
* try {
|
|
29
|
+
* await app.do("createUser", target, {
|
|
30
|
+
* email: "invalid-email", // Missing @ symbol
|
|
31
|
+
* age: -5 // Negative age
|
|
32
|
+
* });
|
|
33
|
+
* } catch (error) {
|
|
34
|
+
* if (error instanceof ValidationError) {
|
|
35
|
+
* console.error("Validation failed for:", error.target);
|
|
36
|
+
* console.error("Invalid payload:", error.payload);
|
|
37
|
+
* console.error("Validation details:", error.details);
|
|
38
|
+
* // details contains Zod error with field-level info
|
|
39
|
+
* }
|
|
40
|
+
* }
|
|
41
|
+
* ```
|
|
42
|
+
*
|
|
43
|
+
* @example Logging validation details
|
|
44
|
+
* ```typescript
|
|
45
|
+
* try {
|
|
46
|
+
* await app.do("updateProfile", target, payload);
|
|
47
|
+
* } catch (error) {
|
|
48
|
+
* if (error instanceof ValidationError) {
|
|
49
|
+
* error.details.errors.forEach((err) => {
|
|
50
|
+
* console.error(`Field ${err.path.join(".")}: ${err.message}`);
|
|
51
|
+
* });
|
|
52
|
+
* }
|
|
53
|
+
* }
|
|
54
|
+
* ```
|
|
55
|
+
*
|
|
56
|
+
* @see {@link https://zod.dev | Zod documentation} for validation details
|
|
24
57
|
*/
|
|
25
58
|
export declare class ValidationError extends Error {
|
|
59
|
+
/** The type of target being validated (e.g., "action", "event") */
|
|
26
60
|
readonly target: string;
|
|
61
|
+
/** The invalid payload that failed validation */
|
|
27
62
|
readonly payload: any;
|
|
63
|
+
/** Zod validation error details */
|
|
28
64
|
readonly details: any;
|
|
29
|
-
constructor(
|
|
65
|
+
constructor(
|
|
66
|
+
/** The type of target being validated (e.g., "action", "event") */
|
|
67
|
+
target: string,
|
|
68
|
+
/** The invalid payload that failed validation */
|
|
69
|
+
payload: any,
|
|
70
|
+
/** Zod validation error details */
|
|
71
|
+
details: any);
|
|
30
72
|
}
|
|
31
73
|
/**
|
|
32
|
-
* Thrown when a
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
74
|
+
* Thrown when a business rule (invariant) is violated during action execution.
|
|
75
|
+
*
|
|
76
|
+
* Invariants are conditions that must hold true for an action to succeed.
|
|
77
|
+
* They're checked after loading the current state but before emitting events.
|
|
78
|
+
* This error provides complete context about what action was attempted and
|
|
79
|
+
* why it was rejected.
|
|
80
|
+
*
|
|
81
|
+
* @template S - State schema type
|
|
82
|
+
* @template E - Event schemas type
|
|
83
|
+
* @template A - Action schemas type
|
|
84
|
+
* @template K - Action name
|
|
85
|
+
*
|
|
86
|
+
* @example Catching invariant violations
|
|
87
|
+
* ```typescript
|
|
88
|
+
* import { InvariantError } from "@rotorsoft/act";
|
|
89
|
+
*
|
|
90
|
+
* try {
|
|
91
|
+
* await app.do("withdraw",
|
|
92
|
+
* { stream: "account-123", actor: { id: "user1", name: "Alice" } },
|
|
93
|
+
* { amount: 1000 }
|
|
94
|
+
* );
|
|
95
|
+
* } catch (error) {
|
|
96
|
+
* if (error instanceof InvariantError) {
|
|
97
|
+
* console.error("Action:", error.action);
|
|
98
|
+
* console.error("Reason:", error.description);
|
|
99
|
+
* console.error("Current state:", error.snapshot.state);
|
|
100
|
+
* console.error("Attempted payload:", error.payload);
|
|
101
|
+
* }
|
|
102
|
+
* }
|
|
103
|
+
* ```
|
|
104
|
+
*
|
|
105
|
+
* @example User-friendly error messages
|
|
106
|
+
* ```typescript
|
|
107
|
+
* try {
|
|
108
|
+
* await app.do("closeTicket", target, payload);
|
|
109
|
+
* } catch (error) {
|
|
110
|
+
* if (error instanceof InvariantError) {
|
|
111
|
+
* // Present friendly message to user
|
|
112
|
+
* if (error.description === "Ticket must be open") {
|
|
113
|
+
* return { error: "This ticket is already closed" };
|
|
114
|
+
* } else if (error.description === "Not authorized") {
|
|
115
|
+
* return { error: "You don't have permission to close this ticket" };
|
|
116
|
+
* }
|
|
117
|
+
* }
|
|
118
|
+
* }
|
|
119
|
+
* ```
|
|
120
|
+
*
|
|
121
|
+
* @example Logging with context
|
|
122
|
+
* ```typescript
|
|
123
|
+
* try {
|
|
124
|
+
* await app.do("transfer", target, { to: "account2", amount: 500 });
|
|
125
|
+
* } catch (error) {
|
|
126
|
+
* if (error instanceof InvariantError) {
|
|
127
|
+
* logger.error({
|
|
128
|
+
* action: error.action,
|
|
129
|
+
* stream: error.target.stream,
|
|
130
|
+
* actor: error.target.actor,
|
|
131
|
+
* reason: error.description,
|
|
132
|
+
* balance: error.snapshot.state.balance,
|
|
133
|
+
* attempted: error.payload.amount
|
|
134
|
+
* }, "Invariant violation");
|
|
135
|
+
* }
|
|
136
|
+
* }
|
|
137
|
+
* ```
|
|
138
|
+
*
|
|
139
|
+
* @see {@link Invariant} for defining business rules
|
|
39
140
|
*/
|
|
40
141
|
export declare class InvariantError<S extends Schema, E extends Schemas, A extends Schemas, K extends keyof A> extends Error {
|
|
142
|
+
/** The action that was attempted */
|
|
41
143
|
readonly action: K;
|
|
144
|
+
/** The action payload that was provided */
|
|
42
145
|
readonly payload: Readonly<A[K]>;
|
|
146
|
+
/** The target stream and actor context */
|
|
43
147
|
readonly target: Target;
|
|
148
|
+
/** The current state snapshot when invariant was checked */
|
|
44
149
|
readonly snapshot: Snapshot<S, E>;
|
|
150
|
+
/** Human-readable description of why the invariant failed */
|
|
45
151
|
readonly description: string;
|
|
46
|
-
constructor(
|
|
152
|
+
constructor(
|
|
153
|
+
/** The action that was attempted */
|
|
154
|
+
action: K,
|
|
155
|
+
/** The action payload that was provided */
|
|
156
|
+
payload: Readonly<A[K]>,
|
|
157
|
+
/** The target stream and actor context */
|
|
158
|
+
target: Target,
|
|
159
|
+
/** The current state snapshot when invariant was checked */
|
|
160
|
+
snapshot: Snapshot<S, E>,
|
|
161
|
+
/** Human-readable description of why the invariant failed */
|
|
162
|
+
description: string);
|
|
47
163
|
}
|
|
48
164
|
/**
|
|
49
|
-
* Thrown when
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
|
-
*
|
|
165
|
+
* Thrown when optimistic concurrency control detects a conflict.
|
|
166
|
+
*
|
|
167
|
+
* This error occurs when trying to commit events to a stream that has been
|
|
168
|
+
* modified by another process since it was last loaded. The version number
|
|
169
|
+
* doesn't match expectations, indicating a concurrent modification.
|
|
170
|
+
*
|
|
171
|
+
* This is a normal occurrence in distributed systems and should be handled
|
|
172
|
+
* by reloading the current state and retrying the action.
|
|
173
|
+
*
|
|
174
|
+
* @example Handling concurrency conflicts with retry
|
|
175
|
+
* ```typescript
|
|
176
|
+
* import { ConcurrencyError } from "@rotorsoft/act";
|
|
177
|
+
*
|
|
178
|
+
* async function transferWithRetry(from, to, amount, maxRetries = 3) {
|
|
179
|
+
* for (let attempt = 0; attempt < maxRetries; attempt++) {
|
|
180
|
+
* try {
|
|
181
|
+
* await app.do("transfer",
|
|
182
|
+
* { stream: from, actor: currentUser },
|
|
183
|
+
* { to, amount }
|
|
184
|
+
* );
|
|
185
|
+
* return { success: true };
|
|
186
|
+
* } catch (error) {
|
|
187
|
+
* if (error instanceof ConcurrencyError) {
|
|
188
|
+
* if (attempt < maxRetries - 1) {
|
|
189
|
+
* console.log(`Concurrent modification detected, retrying... (${attempt + 1}/${maxRetries})`);
|
|
190
|
+
* await sleep(100 * Math.pow(2, attempt)); // Exponential backoff
|
|
191
|
+
* continue;
|
|
192
|
+
* }
|
|
193
|
+
* }
|
|
194
|
+
* throw error;
|
|
195
|
+
* }
|
|
196
|
+
* }
|
|
197
|
+
* return { success: false, reason: "Too many concurrent modifications" };
|
|
198
|
+
* }
|
|
199
|
+
* ```
|
|
200
|
+
*
|
|
201
|
+
* @example Logging concurrency conflicts
|
|
202
|
+
* ```typescript
|
|
203
|
+
* try {
|
|
204
|
+
* await app.do("updateInventory", target, payload);
|
|
205
|
+
* } catch (error) {
|
|
206
|
+
* if (error instanceof ConcurrencyError) {
|
|
207
|
+
* logger.warn({
|
|
208
|
+
* stream: error.stream,
|
|
209
|
+
* expectedVersion: error.expectedVersion,
|
|
210
|
+
* actualVersion: error.lastVersion,
|
|
211
|
+
* events: error.events.map(e => e.name)
|
|
212
|
+
* }, "Concurrent modification detected");
|
|
213
|
+
* }
|
|
214
|
+
* }
|
|
215
|
+
* ```
|
|
216
|
+
*
|
|
217
|
+
* @example User feedback for conflicts
|
|
218
|
+
* ```typescript
|
|
219
|
+
* try {
|
|
220
|
+
* await app.do("editDocument", target, { content: newContent });
|
|
221
|
+
* } catch (error) {
|
|
222
|
+
* if (error instanceof ConcurrencyError) {
|
|
223
|
+
* return {
|
|
224
|
+
* error: "This document was modified by another user. Please refresh and try again.",
|
|
225
|
+
* code: "CONCURRENT_MODIFICATION"
|
|
226
|
+
* };
|
|
227
|
+
* }
|
|
228
|
+
* }
|
|
229
|
+
* ```
|
|
230
|
+
*
|
|
231
|
+
* @see {@link Store.commit} for version checking details
|
|
55
232
|
*/
|
|
56
233
|
export declare class ConcurrencyError extends Error {
|
|
234
|
+
/** The stream that had the concurrent modification */
|
|
57
235
|
readonly stream: string;
|
|
236
|
+
/** The actual current version in the store */
|
|
58
237
|
readonly lastVersion: number;
|
|
238
|
+
/** The events that were being committed */
|
|
59
239
|
readonly events: Message<Schemas, keyof Schemas>[];
|
|
240
|
+
/** The version number that was expected */
|
|
60
241
|
readonly expectedVersion: number;
|
|
61
|
-
constructor(
|
|
242
|
+
constructor(
|
|
243
|
+
/** The stream that had the concurrent modification */
|
|
244
|
+
stream: string,
|
|
245
|
+
/** The actual current version in the store */
|
|
246
|
+
lastVersion: number,
|
|
247
|
+
/** The events that were being committed */
|
|
248
|
+
events: Message<Schemas, keyof Schemas>[],
|
|
249
|
+
/** The version number that was expected */
|
|
250
|
+
expectedVersion: number);
|
|
62
251
|
}
|
|
63
252
|
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../../src/types/errors.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAE9E;;;;;;;;;GASG;AACH,eAAO,MAAM,MAAM;;;;CAIT,CAAC;AAEX
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../../src/types/errors.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAE9E;;;;;;;;;GASG;AACH,eAAO,MAAM,MAAM;;;;CAIT,CAAC;AAEX;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AACH,qBAAa,eAAgB,SAAQ,KAAK;IAEtC,mEAAmE;aACnD,MAAM,EAAE,MAAM;IAC9B,iDAAiD;aACjC,OAAO,EAAE,GAAG;IAC5B,mCAAmC;aACnB,OAAO,EAAE,GAAG;;IAL5B,mEAAmE;IACnD,MAAM,EAAE,MAAM;IAC9B,iDAAiD;IACjC,OAAO,EAAE,GAAG;IAC5B,mCAAmC;IACnB,OAAO,EAAE,GAAG;CAK/B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmEG;AACH,qBAAa,cAAc,CACzB,CAAC,SAAS,MAAM,EAChB,CAAC,SAAS,OAAO,EACjB,CAAC,SAAS,OAAO,EACjB,CAAC,SAAS,MAAM,CAAC,CACjB,SAAQ,KAAK;IAEX,oCAAoC;IACpC,QAAQ,CAAC,MAAM,EAAE,CAAC;IAClB,2CAA2C;IAC3C,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAChC,0CAA0C;IAC1C,QAAQ,CAAC,MAAM,EAAE,MAAM;IACvB,4DAA4D;IAC5D,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC;IACjC,6DAA6D;IAC7D,QAAQ,CAAC,WAAW,EAAE,MAAM;;IAT5B,oCAAoC;IAC3B,MAAM,EAAE,CAAC;IAClB,2CAA2C;IAClC,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAChC,0CAA0C;IACjC,MAAM,EAAE,MAAM;IACvB,4DAA4D;IACnD,QAAQ,EAAE,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC;IACjC,6DAA6D;IACpD,WAAW,EAAE,MAAM;CAK/B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoEG;AACH,qBAAa,gBAAiB,SAAQ,KAAK;IAEvC,sDAAsD;aACtC,MAAM,EAAE,MAAM;IAC9B,8CAA8C;aAC9B,WAAW,EAAE,MAAM;IACnC,2CAA2C;aAC3B,MAAM,EAAE,OAAO,CAAC,OAAO,EAAE,MAAM,OAAO,CAAC,EAAE;IACzD,2CAA2C;aAC3B,eAAe,EAAE,MAAM;;IAPvC,sDAAsD;IACtC,MAAM,EAAE,MAAM;IAC9B,8CAA8C;IAC9B,WAAW,EAAE,MAAM;IACnC,2CAA2C;IAC3B,MAAM,EAAE,OAAO,CAAC,OAAO,EAAE,MAAM,OAAO,CAAC,EAAE;IACzD,2CAA2C;IAC3B,eAAe,EAAE,MAAM;CAW1C"}
|