hazo_chat 2.1.0 → 2.1.1

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.
@@ -56,12 +56,141 @@ npm install react react-dom next
56
56
 
57
57
  ## 3. Database Setup
58
58
 
59
- ### Step 3.1: Create hazo_chat Table
59
+ ### Step 3.1: PostgreSQL Setup (Recommended)
60
60
 
61
- Run this SQL to create the chat messages table:
61
+ For PostgreSQL databases, follow these steps to create the schema with UUID types, enums, and proper defaults.
62
+
63
+ #### Step 3.1.1: Enable UUID Extension
64
+
65
+ First, enable the UUID extension for generating UUIDs:
66
+
67
+ ```sql
68
+ -- Enable UUID extension (required for gen_random_uuid())
69
+ CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
70
+ -- OR for PostgreSQL 13+, use pgcrypto extension
71
+ CREATE EXTENSION IF NOT EXISTS "pgcrypto";
72
+ ```
73
+
74
+ #### Step 3.1.2: Create Enum Types (Optional but Recommended)
75
+
76
+ Create enum types for reference types to ensure data integrity:
62
77
 
63
78
  ```sql
64
- -- hazo_chat table for storing chat messages
79
+ -- Create enum for reference types
80
+ CREATE TYPE hazo_enum_chat_type AS ENUM ('chat', 'field', 'project', 'support', 'general');
81
+
82
+ -- Note: If you need to add more enum values later, use:
83
+ -- ALTER TYPE hazo_chat_reference_type ADD VALUE 'new_type';
84
+ ```
85
+
86
+ #### Step 3.1.3: Create hazo_chat Table
87
+
88
+ Create the chat messages table with UUID types and proper defaults:
89
+
90
+ ```sql
91
+ -- hazo_chat table for storing chat messages (PostgreSQL)
92
+ CREATE TABLE IF NOT EXISTS hazo_chat (
93
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
94
+ reference_id UUID NOT NULL,
95
+ reference_type hazo_enum_chat_type DEFAULT 'chat' NOT NULL,
96
+ sender_user_id UUID NOT NULL,
97
+ receiver_user_id UUID NOT NULL,
98
+ message_text TEXT,
99
+ reference_list JSONB,
100
+ read_at TIMESTAMPTZ,
101
+ deleted_at TIMESTAMPTZ,
102
+ created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
103
+ changed_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
104
+ );
105
+
106
+ -- Performance indexes
107
+ CREATE INDEX IF NOT EXISTS idx_hazo_chat_reference_id ON hazo_chat(reference_id);
108
+ CREATE INDEX IF NOT EXISTS idx_hazo_chat_sender ON hazo_chat(sender_user_id);
109
+ CREATE INDEX IF NOT EXISTS idx_hazo_chat_receiver ON hazo_chat(receiver_user_id);
110
+ CREATE INDEX IF NOT EXISTS idx_hazo_chat_created ON hazo_chat(created_at DESC);
111
+ CREATE INDEX IF NOT EXISTS idx_hazo_chat_reference_type ON hazo_chat(reference_type);
112
+ CREATE INDEX IF NOT EXISTS idx_hazo_chat_read_at ON hazo_chat(read_at) WHERE read_at IS NOT NULL;
113
+ CREATE INDEX IF NOT EXISTS idx_hazo_chat_deleted_at ON hazo_chat(deleted_at) WHERE deleted_at IS NOT NULL;
114
+
115
+ -- Composite index for common query pattern
116
+ CREATE INDEX IF NOT EXISTS idx_hazo_chat_receiver_reference ON hazo_chat(receiver_user_id, reference_id);
117
+ ```
118
+
119
+ **Alternative: Without Enum Type (More Flexible)**
120
+
121
+ If you prefer flexibility over strict enum validation:
122
+
123
+ ```sql
124
+ -- hazo_chat table with TEXT reference_type (more flexible)
125
+ CREATE TABLE IF NOT EXISTS hazo_chat (
126
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
127
+ reference_id UUID NOT NULL,
128
+ reference_type TEXT DEFAULT 'chat' NOT NULL,
129
+ sender_user_id UUID NOT NULL,
130
+ receiver_user_id UUID NOT NULL,
131
+ message_text TEXT,
132
+ reference_list JSONB,
133
+ read_at TIMESTAMPTZ,
134
+ deleted_at TIMESTAMPTZ,
135
+ created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
136
+ changed_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
137
+ );
138
+
139
+ -- Performance indexes (same as above)
140
+ CREATE INDEX IF NOT EXISTS idx_hazo_chat_reference_id ON hazo_chat(reference_id);
141
+ CREATE INDEX IF NOT EXISTS idx_hazo_chat_sender ON hazo_chat(sender_user_id);
142
+ CREATE INDEX IF NOT EXISTS idx_hazo_chat_receiver ON hazo_chat(receiver_user_id);
143
+ CREATE INDEX IF NOT EXISTS idx_hazo_chat_created ON hazo_chat(created_at DESC);
144
+ CREATE INDEX IF NOT EXISTS idx_hazo_chat_reference_type ON hazo_chat(reference_type);
145
+ CREATE INDEX IF NOT EXISTS idx_hazo_chat_read_at ON hazo_chat(read_at) WHERE read_at IS NOT NULL;
146
+ CREATE INDEX IF NOT EXISTS idx_hazo_chat_deleted_at ON hazo_chat(deleted_at) WHERE deleted_at IS NOT NULL;
147
+ CREATE INDEX IF NOT EXISTS idx_hazo_chat_receiver_reference ON hazo_chat(receiver_user_id, reference_id);
148
+ ```
149
+
150
+ #### Step 3.1.4: Ensure Users Table Exists (PostgreSQL)
151
+
152
+ You need a users table with at least these fields:
153
+
154
+ ```sql
155
+ -- Users table for PostgreSQL
156
+ CREATE TABLE IF NOT EXISTS hazo_users (
157
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
158
+ email_address VARCHAR(255) UNIQUE NOT NULL,
159
+ name VARCHAR(255),
160
+ profile_picture_url TEXT,
161
+ is_active BOOLEAN DEFAULT TRUE NOT NULL,
162
+ created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
163
+ changed_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
164
+ );
165
+
166
+ -- Indexes for users table
167
+ CREATE INDEX IF NOT EXISTS idx_hazo_users_email ON hazo_users(email_address);
168
+ CREATE INDEX IF NOT EXISTS idx_hazo_users_active ON hazo_users(is_active) WHERE is_active = TRUE;
169
+ ```
170
+
171
+ #### Step 3.1.5: Add Foreign Key Constraints (Optional)
172
+
173
+ Add foreign key constraints for referential integrity:
174
+
175
+ ```sql
176
+ -- Add foreign key constraints (optional but recommended)
177
+ ALTER TABLE hazo_chat
178
+ ADD CONSTRAINT fk_hazo_chat_sender
179
+ FOREIGN KEY (sender_user_id)
180
+ REFERENCES hazo_users(id)
181
+ ON DELETE RESTRICT,
182
+ ADD CONSTRAINT fk_hazo_chat_receiver
183
+ FOREIGN KEY (receiver_user_id)
184
+ REFERENCES hazo_users(id)
185
+ ON DELETE RESTRICT;
186
+ ```
187
+
188
+ ### Step 3.2: SQLite Setup (Alternative)
189
+
190
+ For SQLite databases (development/testing), use this simplified schema:
191
+
192
+ ```sql
193
+ -- hazo_chat table for storing chat messages (SQLite)
65
194
  CREATE TABLE IF NOT EXISTS hazo_chat (
66
195
  id TEXT PRIMARY KEY,
67
196
  reference_id TEXT NOT NULL,
@@ -72,8 +201,8 @@ CREATE TABLE IF NOT EXISTS hazo_chat (
72
201
  reference_list TEXT,
73
202
  read_at TEXT,
74
203
  deleted_at TEXT,
75
- created_at TEXT NOT NULL,
76
- changed_at TEXT NOT NULL
204
+ created_at TEXT NOT NULL DEFAULT (datetime('now')),
205
+ changed_at TEXT NOT NULL DEFAULT (datetime('now'))
77
206
  );
78
207
 
79
208
  -- Performance indexes
@@ -83,9 +212,7 @@ CREATE INDEX IF NOT EXISTS idx_hazo_chat_receiver ON hazo_chat(receiver_user_id)
83
212
  CREATE INDEX IF NOT EXISTS idx_hazo_chat_created ON hazo_chat(created_at DESC);
84
213
  ```
85
214
 
86
- ### Step 3.2: Ensure Users Table Exists
87
-
88
- You need a users table with at least these fields:
215
+ **SQLite Users Table:**
89
216
 
90
217
  ```sql
91
218
  CREATE TABLE IF NOT EXISTS hazo_users (
@@ -94,12 +221,91 @@ CREATE TABLE IF NOT EXISTS hazo_users (
94
221
  name TEXT,
95
222
  profile_picture_url TEXT,
96
223
  is_active INTEGER DEFAULT 1,
97
- created_at TEXT NOT NULL,
98
- changed_at TEXT NOT NULL
224
+ created_at TEXT NOT NULL DEFAULT (datetime('now')),
225
+ changed_at TEXT NOT NULL DEFAULT (datetime('now'))
226
+ );
227
+ ```
228
+
229
+ ### Step 3.3: Key Differences Between PostgreSQL and SQLite
230
+
231
+ | Feature | PostgreSQL | SQLite |
232
+ |---------|-----------|--------|
233
+ | **ID Type** | `UUID` with `gen_random_uuid()` default | `TEXT` (manual UUID generation) |
234
+ | **Boolean** | `BOOLEAN` type with `TRUE`/`FALSE` | `INTEGER` with `0`/`1` |
235
+ | **Timestamp** | `TIMESTAMPTZ` with `NOW()` default | `TEXT` with `datetime('now')` |
236
+ | **JSON** | `JSONB` type (binary JSON) | `TEXT` (JSON string) |
237
+ | **Enum** | Native `ENUM` type available | Not supported (use TEXT) |
238
+ | **Extensions** | Requires UUID extension | No extensions needed |
239
+
240
+ #### Step 3.3.1: Verify PostgreSQL Setup
241
+
242
+ Run these queries to verify your PostgreSQL setup:
243
+
244
+ ```sql
245
+ -- Verify UUID extension is enabled
246
+ SELECT extname, extversion FROM pg_extension WHERE extname IN ('uuid-ossp', 'pgcrypto');
247
+
248
+ -- Verify enum type exists (if using enum)
249
+ SELECT typname FROM pg_type WHERE typname = 'hazo_chat_reference_type';
250
+
251
+ -- Verify table structure
252
+ SELECT
253
+ column_name,
254
+ data_type,
255
+ column_default,
256
+ is_nullable
257
+ FROM information_schema.columns
258
+ WHERE table_name = 'hazo_chat'
259
+ ORDER BY ordinal_position;
260
+
261
+ -- Verify indexes
262
+ SELECT indexname, indexdef
263
+ FROM pg_indexes
264
+ WHERE tablename = 'hazo_chat';
265
+
266
+ -- Test UUID generation
267
+ SELECT gen_random_uuid() AS test_uuid;
268
+
269
+ -- Test table insert with defaults (replace UUIDs with valid user IDs)
270
+ INSERT INTO hazo_chat (
271
+ reference_id,
272
+ sender_user_id,
273
+ receiver_user_id,
274
+ message_text
275
+ ) VALUES (
276
+ gen_random_uuid(),
277
+ (SELECT id FROM hazo_users LIMIT 1), -- Use existing user ID
278
+ (SELECT id FROM hazo_users LIMIT 1), -- Use existing user ID
279
+ 'Test message'
99
280
  );
281
+
282
+ -- Verify auto-generated values
283
+ SELECT
284
+ id,
285
+ created_at,
286
+ changed_at,
287
+ reference_type
288
+ FROM hazo_chat
289
+ WHERE message_text = 'Test message'
290
+ LIMIT 1;
291
+
292
+ -- Clean up test data
293
+ DELETE FROM hazo_chat WHERE message_text = 'Test message';
100
294
  ```
101
295
 
102
296
  ### Verification
297
+
298
+ **PostgreSQL:**
299
+ - [ ] UUID extension enabled (`uuid-ossp` or `pgcrypto`)
300
+ - [ ] Enum type created (if using enum approach)
301
+ - [ ] `hazo_chat` table exists with UUID columns
302
+ - [ ] All indexes created successfully
303
+ - [ ] Users table exists with UUID primary key
304
+ - [ ] Can query: `SELECT * FROM hazo_chat LIMIT 1`
305
+ - [ ] UUID default generation works: `INSERT INTO hazo_chat (...) VALUES (...)` generates UUID automatically
306
+ - [ ] Timestamp defaults work: `created_at` and `changed_at` auto-populate
307
+
308
+ **SQLite:**
103
309
  - [ ] `hazo_chat` table exists in database
104
310
  - [ ] Users table exists with at least one user
105
311
  - [ ] Can query: `SELECT * FROM hazo_chat LIMIT 1`
@@ -917,6 +1123,19 @@ For detailed specifications, see the [UI Design Standards](#ui-design-standards)
917
1123
  - [ ] No TypeScript errors
918
1124
 
919
1125
  ### Database Verification
1126
+
1127
+ **PostgreSQL:**
1128
+ - [ ] UUID extension enabled (check with: `SELECT * FROM pg_extension WHERE extname = 'uuid-ossp' OR extname = 'pgcrypto';`)
1129
+ - [ ] Enum type created (if using): `SELECT typname FROM pg_type WHERE typname = 'hazo_chat_reference_type';`
1130
+ - [ ] `hazo_chat` table exists with correct column types
1131
+ - [ ] All indexes created (check with: `SELECT indexname FROM pg_indexes WHERE tablename = 'hazo_chat';`)
1132
+ - [ ] UUID default generation works: Test insert without providing ID
1133
+ - [ ] Timestamp defaults work: Test insert without providing timestamps
1134
+ - [ ] Boolean columns accept TRUE/FALSE values
1135
+ - [ ] Can insert and query messages
1136
+ - [ ] Foreign key constraints work (if enabled)
1137
+
1138
+ **SQLite:**
920
1139
  - [ ] `hazo_chat` table exists
921
1140
  - [ ] Users table exists with test users
922
1141
  - [ ] Can insert and query messages
@@ -18,9 +18,24 @@
18
18
  *
19
19
  * export { GET, POST };
20
20
  * ```
21
+ *
22
+ * @example
23
+ * ```typescript
24
+ * // app/api/hazo_chat/messages/[id]/route.ts
25
+ * import { createDeleteHandler } from 'hazo_chat/api';
26
+ * import { getHazoConnectSingleton } from 'hazo_connect/nextjs/setup';
27
+ *
28
+ * export const dynamic = 'force-dynamic';
29
+ *
30
+ * const { DELETE } = createDeleteHandler({
31
+ * getHazoConnect: () => getHazoConnectSingleton()
32
+ * });
33
+ *
34
+ * export { DELETE };
35
+ * ```
21
36
  */
22
- export { createMessagesHandler, createMarkAsReadHandler } from './messages.js';
37
+ export { createMessagesHandler, createMarkAsReadHandler, createDeleteHandler, } from './messages.js';
23
38
  export { createUnreadCountFunction } from './unread_count.js';
24
- export type { MessagesHandlerOptions, ChatMessageInput, ChatMessageRecord } from './types.js';
39
+ export type { MessagesHandlerOptions, ChatMessageInput, ChatMessageRecord, ApiErrorResponse, ApiSuccessResponse, PaginationMeta, } from './types.js';
25
40
  export type { UnreadCountFunctionOptions, UnreadCountResult } from './unread_count.js';
26
41
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/api/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAGH,OAAO,EAAE,qBAAqB,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAC;AAC/E,OAAO,EAAE,yBAAyB,EAAE,MAAM,mBAAmB,CAAC;AAG9D,YAAY,EACV,sBAAsB,EACtB,gBAAgB,EAChB,iBAAiB,EAClB,MAAM,YAAY,CAAC;AACpB,YAAY,EACV,0BAA0B,EAC1B,iBAAiB,EAClB,MAAM,mBAAmB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/api/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AAGH,OAAO,EACL,qBAAqB,EACrB,uBAAuB,EACvB,mBAAmB,GACpB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,yBAAyB,EAAE,MAAM,mBAAmB,CAAC;AAG9D,YAAY,EACV,sBAAsB,EACtB,gBAAgB,EAChB,iBAAiB,EACjB,gBAAgB,EAChB,kBAAkB,EAClB,cAAc,GACf,MAAM,YAAY,CAAC;AACpB,YAAY,EAAE,0BAA0B,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC"}
package/dist/api/index.js CHANGED
@@ -18,8 +18,23 @@
18
18
  *
19
19
  * export { GET, POST };
20
20
  * ```
21
+ *
22
+ * @example
23
+ * ```typescript
24
+ * // app/api/hazo_chat/messages/[id]/route.ts
25
+ * import { createDeleteHandler } from 'hazo_chat/api';
26
+ * import { getHazoConnectSingleton } from 'hazo_connect/nextjs/setup';
27
+ *
28
+ * export const dynamic = 'force-dynamic';
29
+ *
30
+ * const { DELETE } = createDeleteHandler({
31
+ * getHazoConnect: () => getHazoConnectSingleton()
32
+ * });
33
+ *
34
+ * export { DELETE };
35
+ * ```
21
36
  */
22
37
  // Export handler factories
23
- export { createMessagesHandler, createMarkAsReadHandler } from './messages.js';
38
+ export { createMessagesHandler, createMarkAsReadHandler, createDeleteHandler, } from './messages.js';
24
39
  export { createUnreadCountFunction } from './unread_count.js';
25
40
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/api/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,2BAA2B;AAC3B,OAAO,EAAE,qBAAqB,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAC;AAC/E,OAAO,EAAE,yBAAyB,EAAE,MAAM,mBAAmB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/api/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AAEH,2BAA2B;AAC3B,OAAO,EACL,qBAAqB,EACrB,uBAAuB,EACvB,mBAAmB,GACpB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,yBAAyB,EAAE,MAAM,mBAAmB,CAAC"}
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Messages API Handler Factory
3
3
  *
4
- * Creates GET and POST handlers for the /api/hazo_chat/messages endpoint.
4
+ * Creates GET, POST, and DELETE handlers for the /api/hazo_chat/messages endpoint.
5
5
  * These handlers should be used in a Next.js API route.
6
6
  *
7
7
  * @example
@@ -49,4 +49,37 @@ export declare function createMarkAsReadHandler(options: MessagesHandlerOptions)
49
49
  }>;
50
50
  }) => Promise<NextResponse>;
51
51
  };
52
+ /**
53
+ * Creates a DELETE handler for soft-deleting a message
54
+ *
55
+ * This handler should be used in a Next.js API route like:
56
+ * /api/hazo_chat/messages/[id]/route.ts
57
+ *
58
+ * @example
59
+ * ```typescript
60
+ * // app/api/hazo_chat/messages/[id]/route.ts
61
+ * import { createDeleteHandler } from 'hazo_chat/api';
62
+ * import { getHazoConnectSingleton } from 'hazo_connect/nextjs/setup';
63
+ *
64
+ * export const dynamic = 'force-dynamic';
65
+ *
66
+ * const { DELETE } = createDeleteHandler({
67
+ * getHazoConnect: () => getHazoConnectSingleton()
68
+ * });
69
+ *
70
+ * export { DELETE };
71
+ * ```
72
+ *
73
+ * @param options - Configuration options
74
+ * @returns DELETE handler function
75
+ */
76
+ export declare function createDeleteHandler(options: MessagesHandlerOptions): {
77
+ DELETE: (request: NextRequest, context: {
78
+ params: {
79
+ id: string;
80
+ } | Promise<{
81
+ id: string;
82
+ }>;
83
+ }) => Promise<NextResponse>;
84
+ };
52
85
  //# sourceMappingURL=messages.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"messages.d.ts","sourceRoot":"","sources":["../../src/api/messages.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAIxD,OAAO,KAAK,EAAE,sBAAsB,EAAuC,MAAM,YAAY,CAAC;AAmB9F;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,sBAAsB;mBAWvC,WAAW,KAAG,OAAO,CAAC,YAAY,CAAC;oBA+FlC,WAAW,KAAG,OAAO,CAAC,YAAY,CAAC;EA0GjE;AAED;;;;;;;;GAQG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,sBAAsB;qBAY1D,WAAW,WACX;QAAE,MAAM,EAAE;YAAE,EAAE,EAAE,MAAM,CAAA;SAAE,GAAG,OAAO,CAAC;YAAE,EAAE,EAAE,MAAM,CAAA;SAAE,CAAC,CAAA;KAAE,KAC5D,OAAO,CAAC,YAAY,CAAC;EA8HzB"}
1
+ {"version":3,"file":"messages.d.ts","sourceRoot":"","sources":["../../src/api/messages.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAIxD,OAAO,KAAK,EAAE,sBAAsB,EAA6E,MAAM,YAAY,CAAC;AAkEpI;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,sBAAsB;mBAcvC,WAAW,KAAG,OAAO,CAAC,YAAY,CAAC;oBAoKlC,WAAW,KAAG,OAAO,CAAC,YAAY,CAAC;EAqIjE;AAED;;;;;;;;GAQG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,sBAAsB;qBAY1D,WAAW,WACX;QAAE,MAAM,EAAE;YAAE,EAAE,EAAE,MAAM,CAAA;SAAE,GAAG,OAAO,CAAC;YAAE,EAAE,EAAE,MAAM,CAAA;SAAE,CAAC,CAAA;KAAE,KAC5D,OAAO,CAAC,YAAY,CAAC;EA8HzB;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,sBAAsB;sBAatD,WAAW,WACX;QAAE,MAAM,EAAE;YAAE,EAAE,EAAE,MAAM,CAAA;SAAE,GAAG,OAAO,CAAC;YAAE,EAAE,EAAE,MAAM,CAAA;SAAE,CAAC,CAAA;KAAE,KAC5D,OAAO,CAAC,YAAY,CAAC;EAwHzB"}