@embed-ai/sdk 0.1.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 ADDED
@@ -0,0 +1,27 @@
1
+ Copyright (c) 2025-present ZKAI Labs Pte. Ltd.
2
+
3
+ All rights reserved.
4
+
5
+ Redistribution and use in source and binary forms, with or without modification, are permitted
6
+ provided that the following conditions are met:
7
+
8
+ 1. Redistributions of source code must retain the above copyright notice, this list of
9
+ conditions and the following disclaimer.
10
+
11
+ 2. Redistributions in binary form must reproduce the above copyright notice, this list of
12
+ conditions and the following disclaimer in the documentation and/or other materials
13
+ provided with the distribution.
14
+
15
+ 3. Neither the name of the copyright holder nor the names of its contributors may
16
+ be used to endorse or promote products derived from this software without specific prior
17
+ written permission.
18
+
19
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
20
+ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
21
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
22
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26
+ OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
+ POSSIBILITY OF SUCH DAMAGE.
package/README.md ADDED
@@ -0,0 +1,347 @@
1
+ # Embed TypeScript
2
+
3
+ The core TypeScript package for embed APIs, featuring an Effect-based HTTP client with robust error handling and configurable retry logic for mbd.xyz API.
4
+
5
+ ## Features
6
+
7
+ - 🚀 **Effect-based HTTP client** with structured error handling
8
+ - 🔄 **Configurable retry logic** with exponential backoff
9
+ - 🛡️ **Type-safe error handling** with tagged error types
10
+ - ⏱️ **Request timeouts** with proper timeout handling
11
+ - 🔐 **Automatic authentication** with Bearer tokens
12
+ - 📝 **All required headers** set automatically
13
+ - 📊 **Built-in logging** of failed requests and retries
14
+ - 🎯 **Selective retry logic** for different error types
15
+
16
+ ## Quick Start
17
+
18
+ ### Basic Usage
19
+
20
+ ```typescript
21
+ import { getClient } from "@embed-ai/sdk"
22
+ const client = getClient(process.env.API_KEY_EMBED)
23
+ const feed = await client.feed.byUserId("16085")
24
+ console.log("✅ Success we got:", feed.length, "items")
25
+ ```
26
+
27
+ ## Error Handling Guide
28
+
29
+ The @embed-ai/sdk package provides comprehensive error handling with typed errors and automatic retries. Here's everything you need to know.
30
+
31
+ ### What Gets Retried Automatically
32
+
33
+ - ✅ **Network errors** (connection failures, DNS issues)
34
+ - ✅ **Timeout errors** (requests taking too long)
35
+ - ✅ **Server errors** (500, 502, 503, 504 by default)
36
+ - ✅ **Rate limiting** (429 when configured)
37
+ - ❌ **Parse errors** (malformed JSON responses)
38
+ - ❌ **Client errors** (4xx except when configured)
39
+
40
+ ### Basic Error Handling
41
+
42
+ For simple applications, basic try/catch is sufficient:
43
+
44
+ ```typescript
45
+ import { getClient } from "@embed-ai/sdk"
46
+
47
+ const client = getClient(process.env.API_KEY_EMBED)
48
+
49
+ try {
50
+ const feed = await client.feed.byUserId("16085")
51
+ return feed
52
+ } catch (error) {
53
+ console.error("API request failed:", error)
54
+ throw error // Re-throw or handle as needed
55
+ }
56
+ ```
57
+
58
+ ### Understanding Error Types
59
+
60
+ The package exports four specific error types for structured error handling:
61
+
62
+ ```typescript
63
+ import {
64
+ HttpRequestError, // HTTP response errors (4xx, 5xx)
65
+ NetworkError, // Network connection issues
66
+ TimeoutError, // Request timeout errors
67
+ ParseError // JSON parsing errors
68
+ } from "@embed-ai/sdk"
69
+ ```
70
+
71
+ Each error type contains rich information to help you understand and handle the issue:
72
+
73
+ ```typescript
74
+ // HttpRequestError - HTTP response errors
75
+ {
76
+ status: 401, // HTTP status code
77
+ statusText: "Unauthorized", // Status text
78
+ url: "https://api.mbd.xyz/...", // Request URL
79
+ body: "Invalid API key" // Response body (if available)
80
+ }
81
+
82
+ // NetworkError - Connection issues
83
+ {
84
+ message: "Failed to fetch", // Error description
85
+ cause: Error // Original error
86
+ }
87
+
88
+ // TimeoutError - Request timeouts
89
+ {
90
+ message: "Request timed out", // Error description
91
+ timeoutMs: 30000 // Timeout duration
92
+ }
93
+
94
+ // ParseError - JSON parsing issues
95
+ {
96
+ message: "Failed to parse JSON", // Error description
97
+ cause: SyntaxError // Original parsing error
98
+ }
99
+ ```
100
+
101
+ ### Basic Usage with Error Handling
102
+
103
+ ```typescript
104
+ import { getClient, HttpRequestError, NetworkError, TimeoutError } from "@embed-ai/sdk"
105
+
106
+ const client = getClient(process.env.API_KEY_EMBED)
107
+
108
+ try {
109
+ const feed = await client.feed.byUserId("16085")
110
+ console.log("✅ Success:", feed.length, "items")
111
+ } catch (error) {
112
+ console.error("❌ Error:", error)
113
+
114
+ // Handle specific error types
115
+ if (error instanceof HttpRequestError) {
116
+ console.error(`HTTP ${error.status}: ${error.statusText}`)
117
+ } else if (error instanceof NetworkError) {
118
+ console.error("Network connection failed")
119
+ } else if (error instanceof TimeoutError) {
120
+ console.error(`Request timed out after ${error.timeoutMs}ms`)
121
+ }
122
+ }
123
+ ```
124
+
125
+ ### Typed Error Handling
126
+
127
+ For production applications, use typed error handling for better control:
128
+
129
+ ```typescript
130
+ import {
131
+ getClient,
132
+ HttpRequestError,
133
+ NetworkError,
134
+ TimeoutError,
135
+ ParseError
136
+ } from "@embed-ai/sdk"
137
+
138
+ const client = getClient(process.env.API_KEY_EMBED)
139
+
140
+ async function getFeedWithErrorHandling(userId: string) {
141
+ try {
142
+ return await client.feed.byUserId(userId)
143
+ } catch (error) {
144
+ if (error instanceof HttpRequestError) {
145
+ switch (error.status) {
146
+ case 401:
147
+ throw new Error("Invalid API key - please check your credentials")
148
+ case 403:
149
+ throw new Error("Access denied - check your API permissions")
150
+ case 404:
151
+ throw new Error("User not found")
152
+ case 429:
153
+ throw new Error("Rate limit exceeded - please try again later")
154
+ case 500:
155
+ case 502:
156
+ case 503:
157
+ case 504:
158
+ throw new Error("Server error - please try again later")
159
+ default:
160
+ throw new Error(`HTTP error ${error.status}: ${error.statusText}`)
161
+ }
162
+ } else if (error instanceof NetworkError) {
163
+ throw new Error("Network connection failed - check your internet connection")
164
+ } else if (error instanceof TimeoutError) {
165
+ throw new Error(`Request timed out after ${error.timeoutMs}ms`)
166
+ } else if (error instanceof ParseError) {
167
+ throw new Error("Invalid response from server")
168
+ } else {
169
+ throw new Error("Unknown error occurred")
170
+ }
171
+ }
172
+ }
173
+ ```
174
+
175
+ ### Custom Retry Configuration
176
+
177
+ Configure retry behavior for your specific needs:
178
+
179
+ ```typescript
180
+ import { getClient } from "@embed-ai/sdk"
181
+
182
+ const client = getClient(process.env.API_KEY_EMBED, {
183
+ retry: {
184
+ maxRetries: 5, // Max retry attempts
185
+ initialDelay: 1000, // Initial delay in ms
186
+ exponentialBackoff: true, // Use exponential backoff
187
+ maxDelay: 15000, // Max delay between retries
188
+ retryableStatusCodes: [429, 500, 502, 503, 504], // HTTP codes to retry
189
+ timeoutMs: 60000 // Request timeout in ms
190
+ }
191
+ })
192
+
193
+ // Now all requests will use this retry configuration
194
+ const feed = await client.feed.byWalletAddress("0x123...")
195
+ ```
196
+
197
+ ### What Happens When Retries Fail
198
+
199
+ When all retry attempts are exhausted, you receive the **last error that occurred** with full context:
200
+
201
+ ```typescript
202
+ try {
203
+ const feed = await client.feed.byUserId("16085")
204
+ } catch (error) {
205
+ // This error represents the final failure after all retries
206
+ if (error instanceof HttpRequestError) {
207
+ console.error(`Final HTTP error after retries: ${error.status}`)
208
+ console.error(`Request URL: ${error.url}`)
209
+ console.error(`Response body: ${error.body}`)
210
+ } else if (error instanceof NetworkError) {
211
+ console.error(`Final network error after retries: ${error.message}`)
212
+ }
213
+ }
214
+ ```
215
+
216
+ **Error Flow:**
217
+ 1. **Request made** → Network fails
218
+ 2. **Retry 1** → Network fails
219
+ 3. **Retry 2** → Network fails
220
+ 4. **Retry 3** → Network fails
221
+ 5. **Final error** → `NetworkError` with original failure details
222
+
223
+ ### Error Handling Best Practices
224
+
225
+ #### 1. **Use Typed Error Handling in Production**
226
+
227
+ ```typescript
228
+ // ✅ Good - Specific error handling
229
+ try {
230
+ const feed = await client.feed.byUserId(userId)
231
+ } catch (error) {
232
+ if (error instanceof HttpRequestError) {
233
+ // Handle specific HTTP errors
234
+ } else if (error instanceof NetworkError) {
235
+ // Handle network issues
236
+ }
237
+ }
238
+
239
+ // ❌ Avoid - Generic error handling
240
+ try {
241
+ const feed = await client.feed.byUserId(userId)
242
+ } catch (error) {
243
+ console.error("Something went wrong:", error) // Too generic
244
+ }
245
+ ```
246
+
247
+ #### 2. **Provide User-Friendly Error Messages**
248
+
249
+ ```typescript
250
+ function getUserFriendlyError(error: unknown): string {
251
+ if (error instanceof HttpRequestError) {
252
+ switch (error.status) {
253
+ case 401: return "Please check your API key"
254
+ case 429: return "Too many requests - please wait a moment"
255
+ case 500: return "Server is temporarily unavailable"
256
+ default: return "Something went wrong with the request"
257
+ }
258
+ } else if (error instanceof NetworkError) {
259
+ return "Please check your internet connection"
260
+ } else if (error instanceof TimeoutError) {
261
+ return "Request took too long - please try again"
262
+ }
263
+ return "An unexpected error occurred"
264
+ }
265
+ ```
266
+
267
+ #### 3. **Implement Fallback Strategies**
268
+
269
+ ```typescript
270
+ async function getFeedWithFallback(userId: string) {
271
+ try {
272
+ return await client.feed.byUserId(userId)
273
+ } catch (error) {
274
+ if (error instanceof HttpRequestError && error.status === 404) {
275
+ // User not found - return empty feed
276
+ return []
277
+ } else if (error instanceof NetworkError || error instanceof TimeoutError) {
278
+ // Network issues - return cached data if available
279
+ return getCachedFeed(userId) || []
280
+ }
281
+ throw error // Re-throw other errors
282
+ }
283
+ }
284
+ ```
285
+
286
+ #### 4. **Log Errors for Monitoring**
287
+
288
+ ```typescript
289
+ import { getClient, HttpRequestError } from "@embed-ai/sdk"
290
+
291
+ const client = getClient(process.env.API_KEY_EMBED)
292
+
293
+ async function getFeedWithLogging(userId: string) {
294
+ try {
295
+ return await client.feed.byUserId(userId)
296
+ } catch (error) {
297
+ // Log error details for monitoring
298
+ if (error instanceof HttpRequestError) {
299
+ console.error("API Error:", {
300
+ status: error.status,
301
+ url: error.url,
302
+ userId,
303
+ timestamp: new Date().toISOString()
304
+ })
305
+ }
306
+ throw error
307
+ }
308
+ }
309
+ ```
310
+
311
+ ## API Methods
312
+
313
+ ### Available Methods
314
+
315
+ ```typescript
316
+ // Get personalized "For You" feed by user ID
317
+ await client.feed.byUserId(userId: string, options?: FeedOptions)
318
+
319
+ // Get personalized "For You" feed by wallet address
320
+ await client.feed.byWalletAddress(walletAddress: string, options?: FeedOptions)
321
+
322
+ // Feed management to create new feeds and manage these custom feeds e.g. as custom feed per user in your app, which can be built on top of base feeds
323
+ await client.feed.createConfig(options: CreateFeedOptions)
324
+ await client.feed.getConfig(configId: string)
325
+ await client.feed.listConfigs(visibility?: "private" | "public")
326
+ await client.feed.updateConfig(options: UpdateFeedOptions)
327
+ ```
328
+
329
+ ### Factory Function
330
+
331
+ ```typescript
332
+ import { getClient } from "@embed-ai/sdk"
333
+
334
+ // Create client with factory function
335
+ const client = getClient(process.env.API_KEY_EMBED, {
336
+ retry: { maxRetries: 5 }
337
+ })
338
+ ```
339
+
340
+
341
+ ## Why Effect?
342
+
343
+ - **Structured Error Handling**: Type-safe error channels prevent runtime surprises
344
+ - **Composable**: Chain and combine operations with powerful combinators
345
+ - **Reliable**: Automatic retries handle transient failures gracefully
346
+ - **Observable**: Built-in logging and tracing for debugging
347
+ - **Type-Safe**: Full TypeScript support with inferred types
package/package.json ADDED
@@ -0,0 +1,30 @@
1
+ {
2
+ "name": "@embed-ai/sdk",
3
+ "version": "0.1.0",
4
+ "type": "module",
5
+ "license": "BSD-3-Clause",
6
+ "description": "The typescript sdk package for embed AI APIs.",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "https://github.com/ZKAI-Network/embed-sdk/",
10
+ "directory": "packages/sdk"
11
+ },
12
+ "publishConfig": {
13
+ "access": "public",
14
+ "directory": "dist"
15
+ },
16
+ "scripts": {
17
+ "build": "bun run build-esm && bun run build-annotate && bun run build-cjs && cp package.json README.md LICENSE dist/ && bun run fix-deps",
18
+ "build-esm": "tsc --project tsconfig.build.json --noEmit && tsc --project tsconfig.src.json",
19
+ "build-cjs": "babel dist --plugins @babel/transform-export-namespace-from --plugins @babel/transform-modules-commonjs --out-dir dist --source-maps",
20
+ "build-annotate": "babel dist --plugins annotate-pure-calls --out-dir dist --source-maps",
21
+ "fix-deps": "bun scripts/fix-deps.js",
22
+ "check": "tsc -b tsconfig.json",
23
+ "test": "vitest",
24
+ "coverage": "vitest --coverage"
25
+ },
26
+ "dependencies": {
27
+ "@embed-ai/types": "^0.1.0",
28
+ "effect": "latest"
29
+ }
30
+ }
@@ -0,0 +1,165 @@
1
+ import { FeedNamespace } from "./feed/namespace.js";
2
+ declare const NetworkError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }) => import("effect/Cause").YieldableError & {
3
+ readonly _tag: "NetworkError";
4
+ } & Readonly<A>;
5
+ /**
6
+ * Network-related errors (connection issues, DNS failures, etc.)
7
+ */
8
+ export declare class NetworkError extends NetworkError_base<{
9
+ readonly message: string;
10
+ readonly cause?: unknown;
11
+ }> {
12
+ }
13
+ declare const HttpRequestError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }) => import("effect/Cause").YieldableError & {
14
+ readonly _tag: "HttpRequestError";
15
+ } & Readonly<A>;
16
+ /**
17
+ * HTTP response errors (4xx, 5xx status codes)
18
+ */
19
+ export declare class HttpRequestError extends HttpRequestError_base<{
20
+ readonly status: number;
21
+ readonly statusText: string;
22
+ readonly url: string;
23
+ readonly body?: string;
24
+ }> {
25
+ }
26
+ declare const ParseError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }) => import("effect/Cause").YieldableError & {
27
+ readonly _tag: "ParseError";
28
+ } & Readonly<A>;
29
+ /**
30
+ * JSON parsing errors
31
+ */
32
+ export declare class ParseError extends ParseError_base<{
33
+ readonly message: string;
34
+ readonly cause?: unknown;
35
+ }> {
36
+ }
37
+ declare const TimeoutError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }) => import("effect/Cause").YieldableError & {
38
+ readonly _tag: "TimeoutError";
39
+ } & Readonly<A>;
40
+ /**
41
+ * Timeout errors
42
+ */
43
+ export declare class TimeoutError extends TimeoutError_base<{
44
+ readonly message: string;
45
+ readonly timeoutMs: number;
46
+ }> {
47
+ }
48
+ /**
49
+ * Union of all possible HTTP client errors
50
+ */
51
+ export type HttpClientError = NetworkError | HttpRequestError | ParseError | TimeoutError;
52
+ /**
53
+ * Configuration for retry behavior
54
+ *
55
+ * @example
56
+ * ```typescript
57
+ * const client = getClient('your-api-key', {
58
+ * retry: {
59
+ * maxRetries: 5,
60
+ * initialDelay: 1000,
61
+ * exponentialBackoff: true,
62
+ * timeoutMs: 30000
63
+ * }
64
+ * })
65
+ * ```
66
+ */
67
+ export interface RetryConfig {
68
+ /** Maximum number of retry attempts (default: 3) */
69
+ readonly maxRetries?: number;
70
+ /** Initial delay between retries in milliseconds (default: 1000) */
71
+ readonly initialDelay?: number;
72
+ /** Whether to use exponential backoff (default: true) */
73
+ readonly exponentialBackoff?: boolean;
74
+ /** Maximum delay between retries in milliseconds (default: 10000) */
75
+ readonly maxDelay?: number;
76
+ /** HTTP status codes that should trigger a retry (default: [500, 502, 503, 504]) */
77
+ readonly retryableStatusCodes?: ReadonlyArray<number>;
78
+ /** Request timeout in milliseconds (default: 30000) */
79
+ readonly timeoutMs?: number;
80
+ }
81
+ /**
82
+ * Configuration for the Embed API client
83
+ *
84
+ * @example
85
+ * ```typescript
86
+ * const client = getClient('your-api-key', {
87
+ * title: 'my-app',
88
+ * retry: {
89
+ * maxRetries: 3,
90
+ * timeoutMs: 30000
91
+ * }
92
+ * })
93
+ * ```
94
+ */
95
+ export interface mbdClientConfig {
96
+ /** Base URL for the API (default: https://api.mbd.xyz) */
97
+ readonly baseUrl?: string;
98
+ /** API token for authentication */
99
+ readonly token?: string;
100
+ /** HTTP referer header value */
101
+ readonly referer?: string;
102
+ /** Application title for tracking (default: embed_sdk_typescript) */
103
+ readonly title?: string;
104
+ /** Retry configuration */
105
+ readonly retry?: RetryConfig;
106
+ }
107
+ /**
108
+ * Main Embed API client providing access to personalized feeds and feed management
109
+ *
110
+ * @example
111
+ * ```typescript
112
+ * import { getClient } from '@embed-ai/sdk'
113
+ *
114
+ * const client = getClient('your-api-key')
115
+ *
116
+ * // Get personalized feed
117
+ * const feed = await client.feed.byUserId('16085')
118
+ *
119
+ * // Create a custom feed
120
+ * const customFeed = await client.feed.createConfig({
121
+ * name: 'My Custom Feed',
122
+ * description: 'A feed for my app'
123
+ * })
124
+ * ```
125
+ */
126
+ export declare class mbdClient {
127
+ private http;
128
+ readonly feed: FeedNamespace;
129
+ constructor(token?: string, options?: mbdClientConfig);
130
+ }
131
+ /**
132
+ * Get a new Embed Client instance
133
+ *
134
+ * @param token - API token required for authentication
135
+ * @param options - Optional client configuration
136
+ * @returns Embed Client instance with namespaced methods
137
+ *
138
+ * @example
139
+ * ```typescript
140
+ * import { getClient } from '@embed-ai/sdk'
141
+ *
142
+ * // Basic usage
143
+ * const client = getClient('your-api-key')
144
+ *
145
+ * // Get personalized feed
146
+ * const feed = await client.feed.byUserId('16085')
147
+ *
148
+ * // Create a custom feed
149
+ * const customFeed = await client.feed.createConfig({
150
+ * name: 'My Custom Feed',
151
+ * description: 'A feed for my app'
152
+ * })
153
+ *
154
+ * // With configuration
155
+ * const client = getClient('your-api-key', {
156
+ * retry: {
157
+ * maxRetries: 3,
158
+ * timeoutMs: 30000
159
+ * }
160
+ * })
161
+ * ```
162
+ */
163
+ export declare function getClient(token?: string, options?: mbdClientConfig): mbdClient;
164
+ export {};
165
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/client.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;;;;AAOnD;;GAEG;AACH,qBAAa,YAAa,SAAQ,kBAAiC;IACjE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAA;CACzB,CAAC;CAAG;;;;AAEL;;GAEG;AACH,qBAAa,gBAAiB,SAAQ,sBAAqC;IACzE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAC3B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CACvB,CAAC;CAAG;;;;AAEL;;GAEG;AACH,qBAAa,UAAW,SAAQ,gBAA+B;IAC7D,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAA;CACzB,CAAC;CAAG;;;;AAEL;;GAEG;AACH,qBAAa,YAAa,SAAQ,kBAAiC;IACjE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;CAC3B,CAAC;CAAG;AAEL;;GAEG;AACH,MAAM,MAAM,eAAe,GAAG,YAAY,GAAG,gBAAgB,GAAG,UAAU,GAAG,YAAY,CAAA;AAMzF;;;;;;;;;;;;;;GAcG;AACH,MAAM,WAAW,WAAW;IAC1B,oDAAoD;IACpD,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAA;IAC5B,oEAAoE;IACpE,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAA;IAC9B,yDAAyD;IACzD,QAAQ,CAAC,kBAAkB,CAAC,EAAE,OAAO,CAAA;IACrC,qEAAqE;IACrE,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;IAC1B,oFAAoF;IACpF,QAAQ,CAAC,oBAAoB,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAA;IACrD,uDAAuD;IACvD,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAC5B;AAkBD;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,eAAe;IAC9B,0DAA0D;IAC1D,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAA;IACzB,mCAAmC;IACnC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAA;IACvB,gCAAgC;IAChC,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAA;IACzB,qEAAqE;IACrE,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAA;IACvB,0BAA0B;IAC1B,QAAQ,CAAC,KAAK,CAAC,EAAE,WAAW,CAAA;CAC7B;AA+PD;;;;;;;;;;;;;;;;;;GAkBG;AACH,qBAAa,SAAS;IACpB,OAAO,CAAC,IAAI,CAAY;IACxB,SAAgB,IAAI,EAAE,aAAa,CAAA;gBAEvB,KAAK,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,eAAe;CAatD;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,wBAAgB,SAAS,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,eAAe,GAAG,SAAS,CAE9E"}