@okikio/observables 1.0.2

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.
Files changed (131) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +578 -0
  3. package/esm/_dnt.polyfills.d.ts +20 -0
  4. package/esm/_dnt.polyfills.d.ts.map +1 -0
  5. package/esm/_dnt.polyfills.js +12 -0
  6. package/esm/_spec.d.ts +260 -0
  7. package/esm/_spec.d.ts.map +1 -0
  8. package/esm/_spec.js +1 -0
  9. package/esm/_types.d.ts +141 -0
  10. package/esm/_types.d.ts.map +1 -0
  11. package/esm/_types.js +20 -0
  12. package/esm/error.d.ts +331 -0
  13. package/esm/error.d.ts.map +1 -0
  14. package/esm/error.js +408 -0
  15. package/esm/events.d.ts +320 -0
  16. package/esm/events.d.ts.map +1 -0
  17. package/esm/events.js +451 -0
  18. package/esm/helpers/_types.d.ts +188 -0
  19. package/esm/helpers/_types.d.ts.map +1 -0
  20. package/esm/helpers/_types.js +1 -0
  21. package/esm/helpers/mod.d.ts +90 -0
  22. package/esm/helpers/mod.d.ts.map +1 -0
  23. package/esm/helpers/mod.js +90 -0
  24. package/esm/helpers/operations/batch.d.ts +109 -0
  25. package/esm/helpers/operations/batch.d.ts.map +1 -0
  26. package/esm/helpers/operations/batch.js +140 -0
  27. package/esm/helpers/operations/combination.d.ts +162 -0
  28. package/esm/helpers/operations/combination.d.ts.map +1 -0
  29. package/esm/helpers/operations/combination.js +350 -0
  30. package/esm/helpers/operations/conditional.d.ts +211 -0
  31. package/esm/helpers/operations/conditional.d.ts.map +1 -0
  32. package/esm/helpers/operations/conditional.js +280 -0
  33. package/esm/helpers/operations/core.d.ts +198 -0
  34. package/esm/helpers/operations/core.d.ts.map +1 -0
  35. package/esm/helpers/operations/core.js +264 -0
  36. package/esm/helpers/operations/errors.d.ts +277 -0
  37. package/esm/helpers/operations/errors.d.ts.map +1 -0
  38. package/esm/helpers/operations/errors.js +378 -0
  39. package/esm/helpers/operations/mod.d.ts +26 -0
  40. package/esm/helpers/operations/mod.d.ts.map +1 -0
  41. package/esm/helpers/operations/mod.js +25 -0
  42. package/esm/helpers/operations/timing.d.ts +206 -0
  43. package/esm/helpers/operations/timing.d.ts.map +1 -0
  44. package/esm/helpers/operations/timing.js +457 -0
  45. package/esm/helpers/operators.d.ts +520 -0
  46. package/esm/helpers/operators.d.ts.map +1 -0
  47. package/esm/helpers/operators.js +563 -0
  48. package/esm/helpers/pipe.d.ts +118 -0
  49. package/esm/helpers/pipe.d.ts.map +1 -0
  50. package/esm/helpers/pipe.js +129 -0
  51. package/esm/helpers/utils.d.ts +142 -0
  52. package/esm/helpers/utils.d.ts.map +1 -0
  53. package/esm/helpers/utils.js +193 -0
  54. package/esm/mod.d.ts +863 -0
  55. package/esm/mod.d.ts.map +1 -0
  56. package/esm/mod.js +861 -0
  57. package/esm/observable.d.ts +1610 -0
  58. package/esm/observable.d.ts.map +1 -0
  59. package/esm/observable.js +1970 -0
  60. package/esm/package.json +3 -0
  61. package/esm/queue.d.ts +201 -0
  62. package/esm/queue.d.ts.map +1 -0
  63. package/esm/queue.js +273 -0
  64. package/esm/symbol.d.ts +60 -0
  65. package/esm/symbol.d.ts.map +1 -0
  66. package/esm/symbol.js +132 -0
  67. package/package.json +96 -0
  68. package/script/_dnt.polyfills.d.ts +20 -0
  69. package/script/_dnt.polyfills.d.ts.map +1 -0
  70. package/script/_dnt.polyfills.js +13 -0
  71. package/script/_spec.d.ts +260 -0
  72. package/script/_spec.d.ts.map +1 -0
  73. package/script/_spec.js +2 -0
  74. package/script/_types.d.ts +141 -0
  75. package/script/_types.d.ts.map +1 -0
  76. package/script/_types.js +22 -0
  77. package/script/error.d.ts +331 -0
  78. package/script/error.d.ts.map +1 -0
  79. package/script/error.js +414 -0
  80. package/script/events.d.ts +320 -0
  81. package/script/events.d.ts.map +1 -0
  82. package/script/events.js +458 -0
  83. package/script/helpers/_types.d.ts +188 -0
  84. package/script/helpers/_types.d.ts.map +1 -0
  85. package/script/helpers/_types.js +2 -0
  86. package/script/helpers/mod.d.ts +90 -0
  87. package/script/helpers/mod.d.ts.map +1 -0
  88. package/script/helpers/mod.js +106 -0
  89. package/script/helpers/operations/batch.d.ts +109 -0
  90. package/script/helpers/operations/batch.d.ts.map +1 -0
  91. package/script/helpers/operations/batch.js +144 -0
  92. package/script/helpers/operations/combination.d.ts +162 -0
  93. package/script/helpers/operations/combination.d.ts.map +1 -0
  94. package/script/helpers/operations/combination.js +355 -0
  95. package/script/helpers/operations/conditional.d.ts +211 -0
  96. package/script/helpers/operations/conditional.d.ts.map +1 -0
  97. package/script/helpers/operations/conditional.js +286 -0
  98. package/script/helpers/operations/core.d.ts +198 -0
  99. package/script/helpers/operations/core.d.ts.map +1 -0
  100. package/script/helpers/operations/core.js +272 -0
  101. package/script/helpers/operations/errors.d.ts +277 -0
  102. package/script/helpers/operations/errors.d.ts.map +1 -0
  103. package/script/helpers/operations/errors.js +387 -0
  104. package/script/helpers/operations/mod.d.ts +26 -0
  105. package/script/helpers/operations/mod.d.ts.map +1 -0
  106. package/script/helpers/operations/mod.js +41 -0
  107. package/script/helpers/operations/timing.d.ts +206 -0
  108. package/script/helpers/operations/timing.d.ts.map +1 -0
  109. package/script/helpers/operations/timing.js +464 -0
  110. package/script/helpers/operators.d.ts +520 -0
  111. package/script/helpers/operators.d.ts.map +1 -0
  112. package/script/helpers/operators.js +570 -0
  113. package/script/helpers/pipe.d.ts +118 -0
  114. package/script/helpers/pipe.d.ts.map +1 -0
  115. package/script/helpers/pipe.js +132 -0
  116. package/script/helpers/utils.d.ts +142 -0
  117. package/script/helpers/utils.d.ts.map +1 -0
  118. package/script/helpers/utils.js +200 -0
  119. package/script/mod.d.ts +863 -0
  120. package/script/mod.d.ts.map +1 -0
  121. package/script/mod.js +877 -0
  122. package/script/observable.d.ts +1610 -0
  123. package/script/observable.d.ts.map +1 -0
  124. package/script/observable.js +1984 -0
  125. package/script/package.json +3 -0
  126. package/script/queue.d.ts +201 -0
  127. package/script/queue.d.ts.map +1 -0
  128. package/script/queue.js +286 -0
  129. package/script/symbol.d.ts +60 -0
  130. package/script/symbol.d.ts.map +1 -0
  131. package/script/symbol.js +135 -0
@@ -0,0 +1,331 @@
1
+ /**
2
+ * Error primitives and guards for Observable pipelines.
3
+ *
4
+ * This entrypoint explains the error values that travel through this library
5
+ * when an operator uses pass-through error handling. It exports the
6
+ * `ObservableError` class plus helper functions for narrowing and asserting
7
+ * those wrapped failures without losing the original error object, stack, or
8
+ * operator context.
9
+ *
10
+ * Reach for this module when you want to inspect failures as data, recover from
11
+ * an upstream step without throwing away buffered values, or surface richer
12
+ * debugging information than a plain `Error` can carry on its own.
13
+ *
14
+ * @module
15
+ */
16
+ import "./_dnt.polyfills.js";
17
+ import type { SpecObserver } from "./_spec.js";
18
+ /**
19
+ * Represents an error that occurred during Observable operations,
20
+ * with the ability to aggregate multiple underlying errors.
21
+ *
22
+ * This class extends AggregateError to provide additional context about
23
+ * where and how errors occurred in an Observable pipeline. It can collect
24
+ * multiple errors that occur during a chain of operations while preserving
25
+ * the contextual information about each error.
26
+ *
27
+ * In addition, this class solves a crucial problem with error handling in ReadableStreams. When we call
28
+ * `controller.error()` on a ReadableStream, it immediately puts the stream in an errored state,
29
+ * which can cause values emitted before the error to be lost. By wrapping errors as special
30
+ * values that flow through the normal value channel, we ensure all values emitted before an
31
+ * error are properly processed.
32
+ *
33
+ * Key features:
34
+ * - Tracks which operator caused the error
35
+ * - Captures the value being processed when the error occurred
36
+ * - Aggregates multiple errors from a pipeline
37
+ * - Preserves the original error objects
38
+ * - Builds an error chain showing the full path of error propagation
39
+ */
40
+ export declare class ObservableError extends AggregateError {
41
+ /** The operator where the error occurred */
42
+ readonly operator?: string;
43
+ /** The value being processed when the error occurred */
44
+ readonly value?: unknown;
45
+ /** Helpful potential fixes for errors */
46
+ readonly tip?: unknown;
47
+ /**
48
+ * Creates a new ObservableError.
49
+ *
50
+ * @param errors - The error(s) that caused this error
51
+ * @param message - The error message
52
+ * @param options - Additional error context
53
+ */
54
+ constructor(errors: Error | Error[] | unknown | unknown[], message: string, options?: {
55
+ operator?: string;
56
+ value?: unknown;
57
+ cause?: unknown;
58
+ tip?: unknown;
59
+ });
60
+ /**
61
+ * Returns a string representation of the error including the operator
62
+ * and value context if available.
63
+ */
64
+ toString(): string;
65
+ /**
66
+ * Creates an ObservableError from any error that occurs during
67
+ * operator execution.
68
+ *
69
+ * @param error - The original error
70
+ * @param operator - The operator name
71
+ * @param value - The value being processed
72
+ * @returns An ObservableError
73
+ */
74
+ static from(error: unknown, operator?: string, value?: unknown, tip?: unknown): ObservableError;
75
+ }
76
+ /**
77
+ * Asserts that a value is not an ObservableError and narrows the TypeScript type.
78
+ *
79
+ * This function acts as a TypeScript assertion function that:
80
+ * 1. **Type Narrowing**: If the function returns normally, TypeScript knows the value is definitely T (not T | ObservableError)
81
+ * 2. **Error Handling**: If the value is an ObservableError, either delegates to observer.error or throws
82
+ * 3. **Never Returns on Error**: When value is ObservableError, this function never returns normally
83
+ *
84
+ * **Key Behavior Changes**:
85
+ * - Now uses TypeScript's `asserts value is T` for proper type narrowing
86
+ * - When observer handles error, the function still doesn't return normally (assertion still fails)
87
+ * - Only returns normally when value is definitely not an ObservableError
88
+ *
89
+ * **Intent**: Provide type-safe error checking with automatic TypeScript type narrowing.
90
+ *
91
+ * **Usage Patterns**:
92
+ * ```typescript
93
+ * // Type narrowing in operator results
94
+ * const result: string | ObservableError = someOperation();
95
+ * assertObservableError(result); // Throws if error
96
+ * // TypeScript now knows result is string, not string | ObservableError
97
+ * console.log(result.toUpperCase()); // ✅ No type error
98
+ *
99
+ * // With observer error handling
100
+ * const observer = { error: err => console.error('Error:', err) };
101
+ * assertObservableError(result, observer);
102
+ * // Still throws/doesn't return normally on error, but observer is notified first
103
+ *
104
+ * // In subscribe callbacks
105
+ * observable.subscribe({
106
+ * next(value) { // value is T | ObservableError
107
+ * assertObservableError(value);
108
+ * // value is now narrowed to T
109
+ * processCleanValue(value);
110
+ * }
111
+ * });
112
+ * ```
113
+ *
114
+ * @template T - The expected type of the value when it's not an error
115
+ * @param value - The value to check, which may be either T or ObservableError
116
+ * @param obs - Optional observer that may contain an error handler function
117
+ *
118
+ * @throws {ObservableError} When value is an ObservableError (after notifying observer if provided)
119
+ *
120
+ * @example Basic type narrowing
121
+ * ```typescript
122
+ * const mixed: string | ObservableError = getValue();
123
+ * assertObservableError(mixed); // Throws if ObservableError
124
+ * console.log(mixed.length); // ✅ TypeScript knows mixed is string
125
+ * ```
126
+ *
127
+ * @example With error observer
128
+ * ```typescript
129
+ * const observer = {
130
+ * error: (err) => analytics.track('error', { message: err.message })
131
+ * };
132
+ *
133
+ * const mixed: User | ObservableError = fetchUser();
134
+ * assertObservableError(mixed, observer); // Observer notified, then throws
135
+ * console.log(mixed.name); // ✅ TypeScript knows mixed is User
136
+ * ```
137
+ *
138
+ * @example In operator pipeline
139
+ * ```typescript
140
+ * import { pipe, map, tap } from './helpers/mod.ts';
141
+ *
142
+ * pipe(
143
+ * source,
144
+ * map(x => processX(x)), // Returns T | ObservableError
145
+ * tap(result => {
146
+ * assertObservableError(result); // Type narrows from T | ObservableError to T
147
+ * sendAnalytics(result); // ✅ result is definitely T
148
+ * })
149
+ * )
150
+ * ```
151
+ */
152
+ export declare function assertObservableError<T>(value: T | ObservableError, obs?: SpecObserver<T>): asserts value is T;
153
+ /**
154
+ * Checks if a value is an ObservableError without throwing exceptions.
155
+ *
156
+ * When working with Observable pipelines, you often receive values that could be either successful
157
+ * results or errors. This creates a dilemma: how do you safely check what you got without risking
158
+ * crashes or poor performance? That's exactly what this function solves.
159
+ *
160
+ * **Why This Function Exists**:
161
+ *
162
+ * Imagine you're processing a stream of data where some items might be errors. Without a proper
163
+ * way to distinguish between good data and errors, you'd have to either:
164
+ * - Risk calling methods on errors (which crashes your app)
165
+ * - Write repetitive `instanceof` checks everywhere (which clutters your code)
166
+ * - Use try/catch blocks for control flow (which hurts performance)
167
+ *
168
+ * This function eliminates all those problems by giving you a clean, fast way to ask:
169
+ * "Is this thing an error?" If yes, you can handle it appropriately. If no, you can
170
+ * safely process it as valid data.
171
+ *
172
+ * **How It Fits With Other Functions**:
173
+ *
174
+ * Think of this as the gentle cousin of `assertObservableError()`. While `assertObservableError()`
175
+ * says "this better not be an error or I'm throwing an exception," this function politely asks
176
+ * "excuse me, are you an error?" and gives you a yes/no answer.
177
+ *
178
+ * This makes it perfect for situations where you want to handle both success and error cases
179
+ * gracefully, rather than just crashing when something goes wrong.
180
+ *
181
+ * **Performance Story**:
182
+ *
183
+ * Under the hood, this function uses a simple `instanceof` check. Now, you might wonder:
184
+ * "Why not just use `instanceof` directly?" The answer lies in convenience and consistency.
185
+ *
186
+ * Here's what actually happens performance-wise:
187
+ * - This function IS an `instanceof` check (no performance difference there)
188
+ * - Modern JavaScript engines are extremely good at optimizing `instanceof`
189
+ * - The real performance win comes from avoiding try/catch blocks for control flow
190
+ * - When the engine inlines this function, the overhead becomes virtually zero
191
+ *
192
+ * **Performance Reality Check**:
193
+ * - `isObservableError(value)` and `value instanceof ObservableError` perform identically
194
+ * - Both are fast enough that you'll never notice the difference in real applications
195
+ * - The real performance benefit is architectural: avoiding exceptions for normal control flow
196
+ * - Exception throwing/catching can be 10-100x slower, but that's comparing apples to oranges
197
+ *
198
+ * In practice, use this function because it's clearer and more consistent with the library's
199
+ * design patterns, not because of micro-optimizations.
200
+ *
201
+ * **Common Ways to Use This Function**:
202
+ *
203
+ * Let's walk through the most common scenarios where this function shines:
204
+ *
205
+ * ```typescript
206
+ * // Scenario 1: Branching logic in data processing
207
+ * function processItem<T>(item: T | ObservableError) {
208
+ * if (isObservableError(item)) {
209
+ * // TypeScript now knows item is an ObservableError
210
+ * console.error('Something went wrong:', item.message);
211
+ * return null; // or however you want to handle errors
212
+ * }
213
+ *
214
+ * // TypeScript now knows item is T - no more type errors!
215
+ * return transformData(item);
216
+ * }
217
+ *
218
+ * // Scenario 2: Filtering out errors from a collection
219
+ * // Note: You need proper type predicates for TypeScript to understand
220
+ * const cleanData = mixedResults.filter((item): item is T => !isObservableError(item));
221
+ * // cleanData is now properly typed as T[]
222
+ *
223
+ * // Scenario 3: Separating errors from successes
224
+ * const errors = results.filter(isObservableError);
225
+ * const successes = results.filter((item): item is T => !isObservableError(item));
226
+ * // Now you can handle each group with proper typing
227
+ *
228
+ * // Scenario 4: Early exit optimization
229
+ * function expensiveCalculation<T, U>(input: T | ObservableError): U | ObservableError {
230
+ * if (isObservableError(input)) {
231
+ * return input; // Don't waste time processing errors
232
+ * }
233
+ *
234
+ * // Only do expensive work on valid data
235
+ * return performComplexOperation(input);
236
+ * }
237
+ * ```
238
+ *
239
+ * **What Makes This Function Safe**:
240
+ *
241
+ * Unlike functions that might throw exceptions, this one is designed to never fail.
242
+ * It gracefully handles all the weird edge cases you might encounter:
243
+ * - Null or undefined values? Returns false (they're not errors)
244
+ * - Numbers, strings, or other primitives? Returns false (can't be ObservableErrors)
245
+ * - Objects that aren't ObservableErrors? Returns false (not what we're looking for)
246
+ * - Subclasses of ObservableError? Returns true (proper inheritance support)
247
+ *
248
+ * This means you can safely call it on anything without worrying about crashes.
249
+ *
250
+ * **When to Use This vs Other Options**:
251
+ *
252
+ * Choose `isObservableError()` when:
253
+ * - You want to handle both error and success cases in your code
254
+ * - You're filtering or sorting mixed arrays of results and errors
255
+ * - You're building conditional logic that branches based on error state
256
+ * - You want to avoid exceptions and prefer explicit error handling
257
+ *
258
+ * Choose `assertObservableError()` instead when:
259
+ * - You expect the value to NOT be an error, and want to crash if it is
260
+ * - You're in a context where errors should stop processing immediately
261
+ * - You want TypeScript to automatically narrow types via assertion
262
+ *
263
+ * @template T - The expected type for successful (non-error) values
264
+ * @param value - Any value that might or might not be an ObservableError
265
+ * @returns true if the value is an ObservableError, false otherwise
266
+ *
267
+ * @example Simple error checking
268
+ * ```typescript
269
+ * const result: string | ObservableError = fetchData();
270
+ *
271
+ * if (isObservableError(result)) {
272
+ * console.error('Oops, something went wrong:', result.message);
273
+ * // result is typed as ObservableError here
274
+ * return;
275
+ * }
276
+ *
277
+ * // result is typed as string here
278
+ * console.log('Success! Got:', result.toUpperCase());
279
+ * ```
280
+ *
281
+ * @example Filtering errors from a list
282
+ * ```typescript
283
+ * const mixedResults: (User | ObservableError)[] = await fetchAllUsers();
284
+ *
285
+ * // Get only the successful results (with proper type predicate)
286
+ * const validUsers = mixedResults.filter((item): item is User => !isObservableError(item));
287
+ * // validUsers is now correctly typed as User[]
288
+ *
289
+ * // Get only the errors
290
+ * const errors = mixedResults.filter(isObservableError);
291
+ * // errors is now typed as ObservableError[]
292
+ *
293
+ * // Process each group separately
294
+ * if (errors.length > 0) {
295
+ * console.error(`Found ${errors.length} errors:`, errors);
296
+ * }
297
+ * console.log(`Processing ${validUsers.length} valid users`);
298
+ * ```
299
+ *
300
+ * @example Building error-resilient operators
301
+ * ```typescript
302
+ * import { pipe } from './helpers/mod.ts';
303
+ *
304
+ * function safeMap<T, U>(transform: (value: T) => U) {
305
+ * return (source: Observable<T | ObservableError>) => {
306
+ * return pipe(
307
+ * source,
308
+ * map(value => {
309
+ * // Skip processing errors - just pass them through
310
+ * if (isObservableError(value)) return value;
311
+ *
312
+ * // Only transform valid values
313
+ * try {
314
+ * return transform(value);
315
+ * } catch (error) {
316
+ * return ObservableError.from(error, 'safeMap', value);
317
+ * }
318
+ * })
319
+ * );
320
+ * };
321
+ * }
322
+ *
323
+ * // Usage
324
+ * const result = pipe(
325
+ * mixedDataStream,
326
+ * safeMap(user => user.name.toUpperCase())
327
+ * );
328
+ * ```
329
+ */
330
+ export declare function isObservableError<T = unknown>(value: T | ObservableError): value is ObservableError;
331
+ //# sourceMappingURL=error.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"error.d.ts","sourceRoot":"","sources":["../src/error.ts"],"names":[],"mappings":"AACA;;;;;;;;;;;;;;GAcG;AACH,OAAO,qBAAqB,CAAC;AAG7B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/C;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,qBAAa,eAAgB,SAAQ,cAAc;IACjD,4CAA4C;IAC5C,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAE3B,wDAAwD;IACxD,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;IAEzB,yCAAyC;IACzC,QAAQ,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC;IAEvB;;;;;;OAMG;gBAED,MAAM,EAAE,KAAK,GAAG,KAAK,EAAE,GAAG,OAAO,GAAG,OAAO,EAAE,EAC7C,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE;QACR,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,KAAK,CAAC,EAAE,OAAO,CAAC;QAChB,KAAK,CAAC,EAAE,OAAO,CAAC;QAChB,GAAG,CAAC,EAAE,OAAO,CAAC;KACf;IAeH;;;OAGG;IACM,QAAQ,IAAI,MAAM;IA6B3B;;;;;;;;OAQG;IACH,MAAM,CAAC,IAAI,CACT,KAAK,EAAE,OAAO,EACd,QAAQ,CAAC,EAAE,MAAM,EACjB,KAAK,CAAC,EAAE,OAAO,EACf,GAAG,CAAC,EAAE,OAAO,GACZ,eAAe;CAyBnB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2EG;AACH,wBAAgB,qBAAqB,CAAC,CAAC,EACrC,KAAK,EAAE,CAAC,GAAG,eAAe,EAC1B,GAAG,CAAC,EAAE,YAAY,CAAC,CAAC,CAAC,GACpB,OAAO,CAAC,KAAK,IAAI,CAAC,CAoBpB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgLG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,GAAG,OAAO,EAC3C,KAAK,EAAE,CAAC,GAAG,eAAe,GACzB,KAAK,IAAI,eAAe,CAI1B"}