hazo_chat 2.0.15 → 2.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/README.md +60 -8
- package/SETUP_CHECKLIST.md +37 -0
- package/dist/api/index.d.ts +26 -0
- package/dist/api/index.d.ts.map +1 -0
- package/dist/api/index.js +25 -0
- package/dist/api/index.js.map +1 -0
- package/dist/api/messages.d.ts +52 -0
- package/dist/api/messages.d.ts.map +1 -0
- package/dist/api/messages.js +330 -0
- package/dist/api/messages.js.map +1 -0
- package/dist/api/types.d.ts +69 -0
- package/dist/api/types.d.ts.map +1 -0
- package/dist/api/types.js +8 -0
- package/dist/api/types.js.map +1 -0
- package/dist/api/unread_count.d.ts +57 -0
- package/dist/api/unread_count.d.ts.map +1 -0
- package/dist/api/unread_count.js +86 -0
- package/dist/api/unread_count.js.map +1 -0
- package/dist/components/hazo_chat/hazo_chat.d.ts +28 -0
- package/dist/components/hazo_chat/hazo_chat.d.ts.map +1 -0
- package/dist/components/hazo_chat/hazo_chat.js +220 -0
- package/dist/components/hazo_chat/hazo_chat.js.map +1 -0
- package/dist/components/hazo_chat/hazo_chat_attachment_preview.d.ts +17 -0
- package/dist/components/hazo_chat/hazo_chat_attachment_preview.d.ts.map +1 -0
- package/dist/components/hazo_chat/hazo_chat_attachment_preview.js +60 -0
- package/dist/components/hazo_chat/hazo_chat_attachment_preview.js.map +1 -0
- package/dist/components/hazo_chat/hazo_chat_context.d.ts +42 -0
- package/dist/components/hazo_chat/hazo_chat_context.d.ts.map +1 -0
- package/dist/components/hazo_chat/hazo_chat_context.js +273 -0
- package/dist/components/hazo_chat/hazo_chat_context.js.map +1 -0
- package/dist/components/hazo_chat/hazo_chat_document_viewer.d.ts +15 -0
- package/dist/components/hazo_chat/hazo_chat_document_viewer.d.ts.map +1 -0
- package/dist/components/hazo_chat/hazo_chat_document_viewer.js +140 -0
- package/dist/components/hazo_chat/hazo_chat_document_viewer.js.map +1 -0
- package/dist/components/hazo_chat/hazo_chat_header.d.ts +16 -0
- package/dist/components/hazo_chat/hazo_chat_header.d.ts.map +1 -0
- package/dist/components/hazo_chat/hazo_chat_header.js +32 -0
- package/dist/components/hazo_chat/hazo_chat_header.js.map +1 -0
- package/dist/components/hazo_chat/hazo_chat_input.d.ts +16 -0
- package/dist/components/hazo_chat/hazo_chat_input.d.ts.map +1 -0
- package/dist/components/hazo_chat/hazo_chat_input.js +75 -0
- package/dist/components/hazo_chat/hazo_chat_input.js.map +1 -0
- package/dist/components/hazo_chat/hazo_chat_messages.d.ts +17 -0
- package/dist/components/hazo_chat/hazo_chat_messages.d.ts.map +1 -0
- package/dist/components/hazo_chat/hazo_chat_messages.js +215 -0
- package/dist/components/hazo_chat/hazo_chat_messages.js.map +1 -0
- package/dist/components/hazo_chat/hazo_chat_reference_list.d.ts +16 -0
- package/dist/components/hazo_chat/hazo_chat_reference_list.d.ts.map +1 -0
- package/dist/components/hazo_chat/hazo_chat_reference_list.js +59 -0
- package/dist/components/hazo_chat/hazo_chat_reference_list.js.map +1 -0
- package/dist/components/hazo_chat/hazo_chat_sidebar.d.ts +18 -0
- package/dist/components/hazo_chat/hazo_chat_sidebar.d.ts.map +1 -0
- package/dist/components/hazo_chat/hazo_chat_sidebar.js +72 -0
- package/dist/components/hazo_chat/hazo_chat_sidebar.js.map +1 -0
- package/dist/components/hazo_chat/index.d.ts +16 -0
- package/dist/components/hazo_chat/index.d.ts.map +1 -0
- package/dist/components/hazo_chat/index.js +19 -0
- package/dist/components/hazo_chat/index.js.map +1 -0
- package/dist/components/index.d.ts +9 -0
- package/dist/components/index.d.ts.map +1 -0
- package/dist/components/index.js +11 -0
- package/dist/components/index.js.map +1 -0
- package/dist/components/ui/avatar.d.ts +13 -0
- package/dist/components/ui/avatar.d.ts.map +1 -0
- package/dist/components/ui/avatar.js +28 -0
- package/dist/components/ui/avatar.js.map +1 -0
- package/dist/components/ui/badge.d.ts +16 -0
- package/dist/components/ui/badge.d.ts.map +1 -0
- package/dist/components/ui/badge.js +36 -0
- package/dist/components/ui/badge.js.map +1 -0
- package/dist/components/ui/button.d.ts +18 -0
- package/dist/components/ui/button.d.ts.map +1 -0
- package/dist/components/ui/button.js +47 -0
- package/dist/components/ui/button.js.map +1 -0
- package/dist/components/ui/chat_bubble.d.ts +18 -0
- package/dist/components/ui/chat_bubble.d.ts.map +1 -0
- package/dist/components/ui/chat_bubble.js +130 -0
- package/dist/components/ui/chat_bubble.js.map +1 -0
- package/dist/components/ui/hover-card.d.ts +13 -0
- package/dist/components/ui/hover-card.d.ts.map +1 -0
- package/dist/components/ui/hover-card.js +17 -0
- package/dist/components/ui/hover-card.js.map +1 -0
- package/dist/components/ui/index.d.ts +19 -0
- package/dist/components/ui/index.d.ts.map +1 -0
- package/dist/components/ui/index.js +21 -0
- package/dist/components/ui/index.js.map +1 -0
- package/dist/components/ui/input.d.ts +11 -0
- package/dist/components/ui/input.d.ts.map +1 -0
- package/dist/components/ui/input.js +18 -0
- package/dist/components/ui/input.js.map +1 -0
- package/dist/components/ui/loading_skeleton.d.ts +19 -0
- package/dist/components/ui/loading_skeleton.d.ts.map +1 -0
- package/dist/components/ui/loading_skeleton.js +30 -0
- package/dist/components/ui/loading_skeleton.js.map +1 -0
- package/dist/components/ui/scroll-area.d.ts +12 -0
- package/dist/components/ui/scroll-area.d.ts.map +1 -0
- package/dist/components/ui/scroll-area.js +25 -0
- package/dist/components/ui/scroll-area.js.map +1 -0
- package/dist/components/ui/separator.d.ts +11 -0
- package/dist/components/ui/separator.d.ts.map +1 -0
- package/dist/components/ui/separator.js +18 -0
- package/dist/components/ui/separator.js.map +1 -0
- package/dist/components/ui/skeleton.d.ts +9 -0
- package/dist/components/ui/skeleton.d.ts.map +1 -0
- package/dist/components/ui/skeleton.js +16 -0
- package/dist/components/ui/skeleton.js.map +1 -0
- package/dist/components/ui/textarea.d.ts +11 -0
- package/dist/components/ui/textarea.d.ts.map +1 -0
- package/dist/components/ui/textarea.js +18 -0
- package/dist/components/ui/textarea.js.map +1 -0
- package/dist/components/ui/tooltip.d.ts +14 -0
- package/dist/components/ui/tooltip.d.ts.map +1 -0
- package/dist/components/ui/tooltip.js +30 -0
- package/dist/components/ui/tooltip.js.map +1 -0
- package/dist/hooks/index.d.ts +10 -0
- package/dist/hooks/index.d.ts.map +1 -0
- package/dist/hooks/index.js +10 -0
- package/dist/hooks/index.js.map +1 -0
- package/dist/hooks/use_chat_messages.d.ts +33 -0
- package/dist/hooks/use_chat_messages.d.ts.map +1 -0
- package/dist/hooks/use_chat_messages.js +485 -0
- package/dist/hooks/use_chat_messages.js.map +1 -0
- package/dist/hooks/use_chat_references.d.ts +17 -0
- package/dist/hooks/use_chat_references.d.ts.map +1 -0
- package/dist/hooks/use_chat_references.js +133 -0
- package/dist/hooks/use_chat_references.js.map +1 -0
- package/dist/hooks/use_file_upload.d.ts +23 -0
- package/dist/hooks/use_file_upload.d.ts.map +1 -0
- package/dist/hooks/use_file_upload.js +212 -0
- package/dist/hooks/use_file_upload.js.map +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +17 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/config.d.ts +41 -0
- package/dist/lib/config.d.ts.map +1 -0
- package/dist/lib/config.js +93 -0
- package/dist/lib/config.js.map +1 -0
- package/dist/lib/constants.d.ts +41 -0
- package/dist/lib/constants.d.ts.map +1 -0
- package/dist/lib/constants.js +72 -0
- package/dist/lib/constants.js.map +1 -0
- package/dist/lib/index.d.ts +9 -0
- package/dist/lib/index.d.ts.map +1 -0
- package/dist/lib/index.js +9 -0
- package/dist/lib/index.js.map +1 -0
- package/dist/lib/utils.d.ts +17 -0
- package/dist/lib/utils.d.ts.map +1 -0
- package/dist/lib/utils.js +20 -0
- package/dist/lib/utils.js.map +1 -0
- package/dist/types/index.d.ts +405 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +11 -0
- package/dist/types/index.js.map +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -12,7 +12,7 @@ A full-featured React chat component library for 1-1 communication with document
|
|
|
12
12
|
- 📄 **Document Viewer** - Built-in PDF and image viewer with expand/collapse toggle, download, and open in new tab actions
|
|
13
13
|
- 👤 **User Profiles** - Avatar display and user information
|
|
14
14
|
- 🔄 **Infinite Scroll** - Cursor-based pagination for message history
|
|
15
|
-
- ✅ **Read Receipts** -
|
|
15
|
+
- ✅ **Read Receipts** - Automatic mark-as-read when messages become visible using Intersection Observer
|
|
16
16
|
- 🗑️ **Soft Delete** - Delete messages with undo capability
|
|
17
17
|
- 🎨 **Customizable** - TailwindCSS-based theming
|
|
18
18
|
- 🚀 **API-First** - No server-side dependencies in client components
|
|
@@ -242,19 +242,28 @@ This section defines the visual design standards and component behavior specific
|
|
|
242
242
|
|
|
243
243
|
**Message Timestamp Display:**
|
|
244
244
|
- Location: Chat bubble footer (`ChatBubble`)
|
|
245
|
-
- Only timestamp is displayed (no status icons for sent/unread messages)
|
|
246
245
|
- Font size: `text-xs`
|
|
247
246
|
- Color: `text-muted-foreground`
|
|
248
|
-
-
|
|
247
|
+
- Time format: 24-hour format (e.g., "10:37", "15:51")
|
|
248
|
+
- Date prefix: Messages before today show date in `dd/MMM` format (e.g., "02/Dec 10:37")
|
|
249
249
|
- Timezone: Respects `timezone` prop (default: "GMT+10")
|
|
250
250
|
|
|
251
|
-
**
|
|
251
|
+
**Message Status Indicators (Sender's Messages Only):**
|
|
252
252
|
- Location: Chat bubble footer, after timestamp
|
|
253
|
-
- Icon: `IoCheckmarkDoneSharp` (from `react-icons/io5`)
|
|
254
|
-
- Size: `h-4 w-4` (16px × 16px)
|
|
255
|
-
- Color: `text-green-500`
|
|
256
|
-
- Display condition: Only shown when `read_at` is not null AND message is from sender
|
|
257
253
|
- Position: After timestamp with `gap-1` spacing
|
|
254
|
+
- Size: `h-4 w-4` (16px × 16px)
|
|
255
|
+
|
|
256
|
+
**Sent Indicator (Grey Single Check):**
|
|
257
|
+
- Icon: `IoCheckmark` (from `react-icons/io5`)
|
|
258
|
+
- Color: `text-muted-foreground` (grey)
|
|
259
|
+
- Display condition: Shown when message is sent but `read_at` is null
|
|
260
|
+
- Meaning: Message delivered but not yet read by recipient
|
|
261
|
+
|
|
262
|
+
**Read Receipt (Green Double Check):**
|
|
263
|
+
- Icon: `IoCheckmarkDoneSharp` (from `react-icons/io5`)
|
|
264
|
+
- Color: `text-green-500` (green)
|
|
265
|
+
- Display condition: Only shown when `read_at` is not null
|
|
266
|
+
- Meaning: Message has been read by recipient
|
|
258
267
|
|
|
259
268
|
#### Component Behavior
|
|
260
269
|
|
|
@@ -293,6 +302,20 @@ This section defines the visual design standards and component behavior specific
|
|
|
293
302
|
- Indicator: Chevron icon (`IoChevronDown` when collapsed, `IoChevronUp` when expanded)
|
|
294
303
|
- Default state: Collapsed when no references, expanded when references exist
|
|
295
304
|
|
|
305
|
+
**Automatic Mark-as-Read:**
|
|
306
|
+
- Detection: Uses Intersection Observer API to detect when messages become visible
|
|
307
|
+
- Trigger threshold: Messages marked as read when 50% visible in the ScrollArea viewport
|
|
308
|
+
- Scope: Only marks messages where the current user is the receiver (not the sender)
|
|
309
|
+
- State tracking: Prevents duplicate marking using in-memory Set
|
|
310
|
+
- API endpoint: Requires `PATCH /api/hazo_chat/messages/[id]/read` route
|
|
311
|
+
- Visual indicator: Green double-checkmark (IoCheckmarkDoneSharp) appears after timestamp
|
|
312
|
+
- Automatic: No user action required - messages are marked as read automatically when scrolled into view
|
|
313
|
+
|
|
314
|
+
**Note:** The mark-as-read functionality requires:
|
|
315
|
+
1. The `HazoChat` component (includes all hooks and logic)
|
|
316
|
+
2. The API route for marking messages as read (see API Routes Setup below)
|
|
317
|
+
3. Messages must be received by the current user (messages sent by current user are not marked)
|
|
318
|
+
|
|
296
319
|
#### Layout Standards
|
|
297
320
|
|
|
298
321
|
**Chat Input Area:**
|
|
@@ -476,6 +499,7 @@ hazo_chat requires these API endpoints:
|
|
|
476
499
|
|----------|--------|-------------|
|
|
477
500
|
| `/api/hazo_chat/messages` | GET | Fetch chat messages |
|
|
478
501
|
| `/api/hazo_chat/messages` | POST | Send a new message |
|
|
502
|
+
| `/api/hazo_chat/messages/[id]/read` | PATCH | Mark a message as read (automatic) |
|
|
479
503
|
| `/api/hazo_chat/unread_count` | GET | Get unread message counts by reference_id (optional) |
|
|
480
504
|
| `/api/hazo_auth/me` | GET | Get current authenticated user |
|
|
481
505
|
| `/api/hazo_auth/profiles` | POST | Fetch user profiles by IDs |
|
|
@@ -501,6 +525,34 @@ const { GET, POST } = createMessagesHandler({
|
|
|
501
525
|
export { GET, POST };
|
|
502
526
|
```
|
|
503
527
|
|
|
528
|
+
```typescript
|
|
529
|
+
// app/api/hazo_chat/messages/[id]/read/route.ts
|
|
530
|
+
import { NextRequest } from 'next/server';
|
|
531
|
+
import { createMarkAsReadHandler } from 'hazo_chat/api';
|
|
532
|
+
import { getHazoConnectSingleton } from 'hazo_connect/nextjs/setup';
|
|
533
|
+
|
|
534
|
+
export const dynamic = 'force-dynamic';
|
|
535
|
+
|
|
536
|
+
const { PATCH } = createMarkAsReadHandler({
|
|
537
|
+
getHazoConnect: () => getHazoConnectSingleton(),
|
|
538
|
+
// Optional: custom authentication
|
|
539
|
+
getUserIdFromRequest: async (request) => {
|
|
540
|
+
// Return user ID from your auth system
|
|
541
|
+
return request.cookies.get('user_id')?.value || null;
|
|
542
|
+
}
|
|
543
|
+
});
|
|
544
|
+
|
|
545
|
+
// Wrapper to handle Next.js App Router params
|
|
546
|
+
async function handlePATCH(
|
|
547
|
+
request: NextRequest,
|
|
548
|
+
context: { params: { id: string } | Promise<{ id: string }> }
|
|
549
|
+
) {
|
|
550
|
+
return PATCH(request, context);
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
export { handlePATCH as PATCH };
|
|
554
|
+
```
|
|
555
|
+
|
|
504
556
|
### Custom Implementation
|
|
505
557
|
|
|
506
558
|
If you need more control, implement the endpoints manually. See [SETUP_CHECKLIST.md](./SETUP_CHECKLIST.md) for detailed examples.
|
package/SETUP_CHECKLIST.md
CHANGED
|
@@ -132,6 +132,41 @@ const { GET, POST } = createMessagesHandler({
|
|
|
132
132
|
export { GET, POST };
|
|
133
133
|
```
|
|
134
134
|
|
|
135
|
+
### Step 4.1.5: Mark as Read API (Automatic Read Receipts)
|
|
136
|
+
|
|
137
|
+
**File: `src/app/api/hazo_chat/messages/[id]/read/route.ts`**
|
|
138
|
+
|
|
139
|
+
```typescript
|
|
140
|
+
/**
|
|
141
|
+
* API route to mark a chat message as read
|
|
142
|
+
* Uses the exportable handler from hazo_chat package
|
|
143
|
+
* Supports PATCH for marking messages as read
|
|
144
|
+
*/
|
|
145
|
+
|
|
146
|
+
export const dynamic = 'force-dynamic';
|
|
147
|
+
|
|
148
|
+
import { NextRequest } from 'next/server';
|
|
149
|
+
import { createMarkAsReadHandler } from 'hazo_chat/api';
|
|
150
|
+
import { getHazoConnectSingleton } from 'hazo_connect/nextjs/setup';
|
|
151
|
+
|
|
152
|
+
// Create handler using the exportable factory from hazo_chat
|
|
153
|
+
const { PATCH: patchHandler } = createMarkAsReadHandler({
|
|
154
|
+
getHazoConnect: () => getHazoConnectSingleton()
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
// Wrapper to handle Next.js App Router params
|
|
158
|
+
async function PATCH(
|
|
159
|
+
request: NextRequest,
|
|
160
|
+
context: { params: { id: string } | Promise<{ id: string }> }
|
|
161
|
+
) {
|
|
162
|
+
return patchHandler(request, context);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
export { PATCH };
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
**Note:** This endpoint is called automatically by the `HazoChat` component when messages become visible in the viewport. It uses the Intersection Observer API to detect visibility and marks messages as read when they are at least 50% visible.
|
|
169
|
+
|
|
135
170
|
### Step 4.2: Auth Me API
|
|
136
171
|
|
|
137
172
|
**File: `src/app/api/hazo_auth/me/route.ts`**
|
|
@@ -327,6 +362,7 @@ export async function GET(request: NextRequest) {
|
|
|
327
362
|
| Endpoint | Method | File | Purpose |
|
|
328
363
|
|----------|--------|------|---------|
|
|
329
364
|
| `/api/hazo_chat/messages` | GET, POST | `api/hazo_chat/messages/route.ts` | Message CRUD |
|
|
365
|
+
| `/api/hazo_chat/messages/[id]/read` | PATCH | `api/hazo_chat/messages/[id]/read/route.ts` | Mark message as read (automatic) |
|
|
330
366
|
| `/api/hazo_chat/unread_count` | GET | `api/hazo_chat/unread_count/route.ts` | Get unread counts (optional) |
|
|
331
367
|
| `/api/hazo_auth/me` | GET | `api/hazo_auth/me/route.ts` | Get current user |
|
|
332
368
|
| `/api/hazo_auth/profiles` | POST | `api/hazo_auth/profiles/route.ts` | Get user profiles |
|
|
@@ -336,6 +372,7 @@ export async function GET(request: NextRequest) {
|
|
|
336
372
|
- [ ] `GET /api/hazo_auth/me` returns user data when logged in
|
|
337
373
|
- [ ] `POST /api/hazo_auth/profiles` returns profiles for given IDs
|
|
338
374
|
- [ ] `GET /api/hazo_chat/messages?receiver_user_id=xxx` works
|
|
375
|
+
- [ ] `PATCH /api/hazo_chat/messages/[message-id]/read` marks message as read
|
|
339
376
|
- [ ] `GET /api/hazo_chat/unread_count?receiver_user_id=xxx` returns unread counts (if implemented)
|
|
340
377
|
|
|
341
378
|
---
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* hazo_chat API Module
|
|
3
|
+
*
|
|
4
|
+
* Provides exportable API route handlers for Next.js applications.
|
|
5
|
+
* These handlers can be imported and re-exported in your API routes.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```typescript
|
|
9
|
+
* // app/api/hazo_chat/messages/route.ts
|
|
10
|
+
* import { createMessagesHandler } from 'hazo_chat/api';
|
|
11
|
+
* import { getHazoConnectSingleton } from 'hazo_connect/nextjs/setup';
|
|
12
|
+
*
|
|
13
|
+
* export const dynamic = 'force-dynamic';
|
|
14
|
+
*
|
|
15
|
+
* const { GET, POST } = createMessagesHandler({
|
|
16
|
+
* getHazoConnect: () => getHazoConnectSingleton()
|
|
17
|
+
* });
|
|
18
|
+
*
|
|
19
|
+
* export { GET, POST };
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
export { createMessagesHandler, createMarkAsReadHandler } from './messages.js';
|
|
23
|
+
export { createUnreadCountFunction } from './unread_count.js';
|
|
24
|
+
export type { MessagesHandlerOptions, ChatMessageInput, ChatMessageRecord } from './types.js';
|
|
25
|
+
export type { UnreadCountFunctionOptions, UnreadCountResult } from './unread_count.js';
|
|
26
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* hazo_chat API Module
|
|
3
|
+
*
|
|
4
|
+
* Provides exportable API route handlers for Next.js applications.
|
|
5
|
+
* These handlers can be imported and re-exported in your API routes.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```typescript
|
|
9
|
+
* // app/api/hazo_chat/messages/route.ts
|
|
10
|
+
* import { createMessagesHandler } from 'hazo_chat/api';
|
|
11
|
+
* import { getHazoConnectSingleton } from 'hazo_connect/nextjs/setup';
|
|
12
|
+
*
|
|
13
|
+
* export const dynamic = 'force-dynamic';
|
|
14
|
+
*
|
|
15
|
+
* const { GET, POST } = createMessagesHandler({
|
|
16
|
+
* getHazoConnect: () => getHazoConnectSingleton()
|
|
17
|
+
* });
|
|
18
|
+
*
|
|
19
|
+
* export { GET, POST };
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
// Export handler factories
|
|
23
|
+
export { createMessagesHandler, createMarkAsReadHandler } from './messages.js';
|
|
24
|
+
export { createUnreadCountFunction } from './unread_count.js';
|
|
25
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +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"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Messages API Handler Factory
|
|
3
|
+
*
|
|
4
|
+
* Creates GET and POST handlers for the /api/hazo_chat/messages endpoint.
|
|
5
|
+
* These handlers should be used in a Next.js API route.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```typescript
|
|
9
|
+
* // app/api/hazo_chat/messages/route.ts
|
|
10
|
+
* import { createMessagesHandler } from 'hazo_chat/api';
|
|
11
|
+
* import { getHazoConnectSingleton } from 'hazo_connect/nextjs/setup';
|
|
12
|
+
*
|
|
13
|
+
* export const dynamic = 'force-dynamic';
|
|
14
|
+
*
|
|
15
|
+
* const { GET, POST } = createMessagesHandler({
|
|
16
|
+
* getHazoConnect: () => getHazoConnectSingleton()
|
|
17
|
+
* });
|
|
18
|
+
*
|
|
19
|
+
* export { GET, POST };
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
import { NextRequest, NextResponse } from 'next/server';
|
|
23
|
+
import type { MessagesHandlerOptions } from './types.js';
|
|
24
|
+
/**
|
|
25
|
+
* Creates GET and POST handlers for chat messages
|
|
26
|
+
*
|
|
27
|
+
* @param options - Configuration options
|
|
28
|
+
* @returns Object with GET and POST handlers
|
|
29
|
+
*/
|
|
30
|
+
export declare function createMessagesHandler(options: MessagesHandlerOptions): {
|
|
31
|
+
GET: (request: NextRequest) => Promise<NextResponse>;
|
|
32
|
+
POST: (request: NextRequest) => Promise<NextResponse>;
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* Creates a PATCH handler for marking a message as read
|
|
36
|
+
*
|
|
37
|
+
* This handler should be used in a Next.js API route like:
|
|
38
|
+
* /api/hazo_chat/messages/[id]/read/route.ts
|
|
39
|
+
*
|
|
40
|
+
* @param options - Configuration options
|
|
41
|
+
* @returns PATCH handler function
|
|
42
|
+
*/
|
|
43
|
+
export declare function createMarkAsReadHandler(options: MessagesHandlerOptions): {
|
|
44
|
+
PATCH: (request: NextRequest, context: {
|
|
45
|
+
params: {
|
|
46
|
+
id: string;
|
|
47
|
+
} | Promise<{
|
|
48
|
+
id: string;
|
|
49
|
+
}>;
|
|
50
|
+
}) => Promise<NextResponse>;
|
|
51
|
+
};
|
|
52
|
+
//# sourceMappingURL=messages.d.ts.map
|
|
@@ -0,0 +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"}
|
|
@@ -0,0 +1,330 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Messages API Handler Factory
|
|
3
|
+
*
|
|
4
|
+
* Creates GET and POST handlers for the /api/hazo_chat/messages endpoint.
|
|
5
|
+
* These handlers should be used in a Next.js API route.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```typescript
|
|
9
|
+
* // app/api/hazo_chat/messages/route.ts
|
|
10
|
+
* import { createMessagesHandler } from 'hazo_chat/api';
|
|
11
|
+
* import { getHazoConnectSingleton } from 'hazo_connect/nextjs/setup';
|
|
12
|
+
*
|
|
13
|
+
* export const dynamic = 'force-dynamic';
|
|
14
|
+
*
|
|
15
|
+
* const { GET, POST } = createMessagesHandler({
|
|
16
|
+
* getHazoConnect: () => getHazoConnectSingleton()
|
|
17
|
+
* });
|
|
18
|
+
*
|
|
19
|
+
* export { GET, POST };
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
import { NextResponse } from 'next/server';
|
|
23
|
+
import { cookies } from 'next/headers';
|
|
24
|
+
import { createCrudService, getSqliteAdminService } from 'hazo_connect/server';
|
|
25
|
+
// UUID generation for message IDs
|
|
26
|
+
function generateUUID() {
|
|
27
|
+
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
|
|
28
|
+
const r = Math.random() * 16 | 0;
|
|
29
|
+
const v = c === 'x' ? r : (r & 0x3 | 0x8);
|
|
30
|
+
return v.toString(16);
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Default function to get user ID from request cookies
|
|
35
|
+
*/
|
|
36
|
+
async function defaultGetUserIdFromRequest() {
|
|
37
|
+
const cookieStore = await cookies();
|
|
38
|
+
return cookieStore.get('hazo_auth_user_id')?.value || null;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Creates GET and POST handlers for chat messages
|
|
42
|
+
*
|
|
43
|
+
* @param options - Configuration options
|
|
44
|
+
* @returns Object with GET and POST handlers
|
|
45
|
+
*/
|
|
46
|
+
export function createMessagesHandler(options) {
|
|
47
|
+
const { getHazoConnect, getUserIdFromRequest } = options;
|
|
48
|
+
/**
|
|
49
|
+
* GET handler - Fetch chat messages
|
|
50
|
+
*
|
|
51
|
+
* Query params:
|
|
52
|
+
* - receiver_user_id (required): The other user in the conversation
|
|
53
|
+
* - reference_id (optional): Filter by reference ID
|
|
54
|
+
* - reference_type (optional): Filter by reference type
|
|
55
|
+
*/
|
|
56
|
+
async function GET(request) {
|
|
57
|
+
try {
|
|
58
|
+
// Get current user ID
|
|
59
|
+
const current_user_id = getUserIdFromRequest
|
|
60
|
+
? await getUserIdFromRequest(request)
|
|
61
|
+
: await defaultGetUserIdFromRequest();
|
|
62
|
+
if (!current_user_id) {
|
|
63
|
+
console.error('[hazo_chat/messages GET] No user ID - not authenticated');
|
|
64
|
+
return NextResponse.json({ success: false, error: 'User not authenticated', messages: [] }, { status: 401 });
|
|
65
|
+
}
|
|
66
|
+
// Get query params
|
|
67
|
+
const { searchParams } = new URL(request.url);
|
|
68
|
+
const receiver_user_id = searchParams.get('receiver_user_id');
|
|
69
|
+
const reference_id = searchParams.get('reference_id') || '';
|
|
70
|
+
const reference_type = searchParams.get('reference_type') || '';
|
|
71
|
+
if (!receiver_user_id) {
|
|
72
|
+
console.error('[hazo_chat/messages GET] Missing receiver_user_id');
|
|
73
|
+
return NextResponse.json({ success: false, error: 'receiver_user_id is required', messages: [] }, { status: 400 });
|
|
74
|
+
}
|
|
75
|
+
console.log('[hazo_chat/messages GET] Fetching messages:', {
|
|
76
|
+
current_user_id,
|
|
77
|
+
receiver_user_id,
|
|
78
|
+
reference_id,
|
|
79
|
+
reference_type,
|
|
80
|
+
});
|
|
81
|
+
// Get hazo_connect instance and create CRUD service
|
|
82
|
+
const hazoConnect = getHazoConnect();
|
|
83
|
+
const chatService = createCrudService(hazoConnect, 'hazo_chat');
|
|
84
|
+
let messages = [];
|
|
85
|
+
try {
|
|
86
|
+
// Fetch all messages with reference filters
|
|
87
|
+
const all_messages = await chatService.list((qb) => {
|
|
88
|
+
let builder = qb.select('*');
|
|
89
|
+
if (reference_id) {
|
|
90
|
+
builder = builder.where('reference_id', 'eq', reference_id);
|
|
91
|
+
}
|
|
92
|
+
if (reference_type) {
|
|
93
|
+
builder = builder.where('reference_type', 'eq', reference_type);
|
|
94
|
+
}
|
|
95
|
+
return builder.order('created_at', 'asc');
|
|
96
|
+
});
|
|
97
|
+
// Filter to only messages between current user and receiver
|
|
98
|
+
messages = all_messages.filter((msg) => {
|
|
99
|
+
const is_sent_by_me = msg.sender_user_id === current_user_id && msg.receiver_user_id === receiver_user_id;
|
|
100
|
+
const is_sent_to_me = msg.sender_user_id === receiver_user_id && msg.receiver_user_id === current_user_id;
|
|
101
|
+
return is_sent_by_me || is_sent_to_me;
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
catch (dbError) {
|
|
105
|
+
console.error('[hazo_chat/messages GET] Database error:', dbError);
|
|
106
|
+
throw dbError;
|
|
107
|
+
}
|
|
108
|
+
console.log('[hazo_chat/messages GET] Found messages:', messages.length);
|
|
109
|
+
return NextResponse.json({
|
|
110
|
+
success: true,
|
|
111
|
+
messages,
|
|
112
|
+
current_user_id,
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
catch (error) {
|
|
116
|
+
const error_message = error instanceof Error ? error.message : 'Unknown error';
|
|
117
|
+
console.error('[hazo_chat/messages GET] Error:', error_message, error);
|
|
118
|
+
return NextResponse.json({ success: false, error: 'Failed to fetch messages', messages: [] }, { status: 500 });
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* POST handler - Create a new chat message
|
|
123
|
+
*
|
|
124
|
+
* Request body:
|
|
125
|
+
* - receiver_user_id (required): The recipient user ID
|
|
126
|
+
* - message_text (required): The message content
|
|
127
|
+
* - reference_id (optional): Reference ID for context grouping
|
|
128
|
+
* - reference_type (optional): Reference type (default: 'chat')
|
|
129
|
+
*/
|
|
130
|
+
async function POST(request) {
|
|
131
|
+
try {
|
|
132
|
+
// Get current user ID (sender)
|
|
133
|
+
const sender_user_id = getUserIdFromRequest
|
|
134
|
+
? await getUserIdFromRequest(request)
|
|
135
|
+
: await defaultGetUserIdFromRequest();
|
|
136
|
+
if (!sender_user_id) {
|
|
137
|
+
console.error('[hazo_chat/messages POST] No user ID - not authenticated');
|
|
138
|
+
return NextResponse.json({ success: false, error: 'User not authenticated' }, { status: 401 });
|
|
139
|
+
}
|
|
140
|
+
// Parse request body
|
|
141
|
+
const body = await request.json();
|
|
142
|
+
const { receiver_user_id, message_text, reference_id, reference_type } = body;
|
|
143
|
+
// Validate required fields
|
|
144
|
+
if (!receiver_user_id) {
|
|
145
|
+
console.error('[hazo_chat/messages POST] Missing receiver_user_id');
|
|
146
|
+
return NextResponse.json({ success: false, error: 'receiver_user_id is required' }, { status: 400 });
|
|
147
|
+
}
|
|
148
|
+
if (!message_text || message_text.trim() === '') {
|
|
149
|
+
console.error('[hazo_chat/messages POST] Missing or empty message_text');
|
|
150
|
+
return NextResponse.json({ success: false, error: 'message_text is required' }, { status: 400 });
|
|
151
|
+
}
|
|
152
|
+
// Get hazo_connect instance and create CRUD service
|
|
153
|
+
const hazoConnect = getHazoConnect();
|
|
154
|
+
const chatService = createCrudService(hazoConnect, 'hazo_chat');
|
|
155
|
+
// Generate message ID and timestamps
|
|
156
|
+
const message_id = generateUUID();
|
|
157
|
+
const now = new Date().toISOString();
|
|
158
|
+
// Create message record
|
|
159
|
+
const message_record = {
|
|
160
|
+
id: message_id,
|
|
161
|
+
reference_id: reference_id || '',
|
|
162
|
+
reference_type: reference_type || 'chat',
|
|
163
|
+
sender_user_id,
|
|
164
|
+
receiver_user_id,
|
|
165
|
+
message_text: message_text.trim(),
|
|
166
|
+
reference_list: null,
|
|
167
|
+
read_at: null,
|
|
168
|
+
deleted_at: null,
|
|
169
|
+
created_at: now,
|
|
170
|
+
changed_at: now,
|
|
171
|
+
};
|
|
172
|
+
console.log('[hazo_chat/messages POST] Saving message:', {
|
|
173
|
+
id: message_id,
|
|
174
|
+
sender_user_id,
|
|
175
|
+
receiver_user_id,
|
|
176
|
+
reference_id: reference_id || '',
|
|
177
|
+
reference_type: reference_type || 'chat',
|
|
178
|
+
message_length: message_text.length,
|
|
179
|
+
});
|
|
180
|
+
// Save to database
|
|
181
|
+
try {
|
|
182
|
+
await chatService.insert(message_record);
|
|
183
|
+
}
|
|
184
|
+
catch (dbError) {
|
|
185
|
+
console.error('[hazo_chat/messages POST] Database error:', dbError);
|
|
186
|
+
throw dbError;
|
|
187
|
+
}
|
|
188
|
+
console.log('[hazo_chat/messages POST] Message saved successfully:', message_id);
|
|
189
|
+
return NextResponse.json({
|
|
190
|
+
success: true,
|
|
191
|
+
message: {
|
|
192
|
+
id: message_id,
|
|
193
|
+
sender_user_id,
|
|
194
|
+
receiver_user_id,
|
|
195
|
+
reference_id: reference_id || '',
|
|
196
|
+
reference_type: reference_type || 'chat',
|
|
197
|
+
message_text: message_text.trim(),
|
|
198
|
+
reference_list: null,
|
|
199
|
+
read_at: null,
|
|
200
|
+
deleted_at: null,
|
|
201
|
+
created_at: now,
|
|
202
|
+
changed_at: now,
|
|
203
|
+
},
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
catch (error) {
|
|
207
|
+
const error_message = error instanceof Error ? error.message : 'Unknown error';
|
|
208
|
+
console.error('[hazo_chat/messages POST] Error:', error_message, error);
|
|
209
|
+
return NextResponse.json({ success: false, error: 'Failed to save message' }, { status: 500 });
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
return { GET, POST };
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Creates a PATCH handler for marking a message as read
|
|
216
|
+
*
|
|
217
|
+
* This handler should be used in a Next.js API route like:
|
|
218
|
+
* /api/hazo_chat/messages/[id]/read/route.ts
|
|
219
|
+
*
|
|
220
|
+
* @param options - Configuration options
|
|
221
|
+
* @returns PATCH handler function
|
|
222
|
+
*/
|
|
223
|
+
export function createMarkAsReadHandler(options) {
|
|
224
|
+
const { getHazoConnect, getUserIdFromRequest } = options;
|
|
225
|
+
/**
|
|
226
|
+
* PATCH handler - Mark a message as read
|
|
227
|
+
*
|
|
228
|
+
* Route params:
|
|
229
|
+
* - id (required): The message ID to mark as read
|
|
230
|
+
*
|
|
231
|
+
* Note: In Next.js 13+ App Router, params may be a Promise
|
|
232
|
+
*/
|
|
233
|
+
async function PATCH(request, context) {
|
|
234
|
+
try {
|
|
235
|
+
// Get current user ID
|
|
236
|
+
const current_user_id = getUserIdFromRequest
|
|
237
|
+
? await getUserIdFromRequest(request)
|
|
238
|
+
: await defaultGetUserIdFromRequest();
|
|
239
|
+
if (!current_user_id) {
|
|
240
|
+
console.error('[hazo_chat/messages/[id]/read PATCH] No user ID - not authenticated');
|
|
241
|
+
return NextResponse.json({ success: false, error: 'User not authenticated' }, { status: 401 });
|
|
242
|
+
}
|
|
243
|
+
// Handle params as Promise (Next.js 15+) or direct object (Next.js 13-14)
|
|
244
|
+
const params = context.params instanceof Promise ? await context.params : context.params;
|
|
245
|
+
const message_id = params.id;
|
|
246
|
+
if (!message_id) {
|
|
247
|
+
console.error('[hazo_chat/messages/[id]/read PATCH] Missing message ID');
|
|
248
|
+
return NextResponse.json({ success: false, error: 'Message ID is required' }, { status: 400 });
|
|
249
|
+
}
|
|
250
|
+
console.log('[hazo_chat/messages/[id]/read PATCH] Marking message as read:', {
|
|
251
|
+
message_id,
|
|
252
|
+
current_user_id,
|
|
253
|
+
});
|
|
254
|
+
// Get hazo_connect instance and create CRUD service
|
|
255
|
+
const hazoConnect = getHazoConnect();
|
|
256
|
+
const chatService = createCrudService(hazoConnect, 'hazo_chat');
|
|
257
|
+
// First, fetch the message to verify ownership
|
|
258
|
+
let message = null;
|
|
259
|
+
try {
|
|
260
|
+
const messages = await chatService.list((qb) => qb.select('*').where('id', 'eq', message_id));
|
|
261
|
+
message = messages[0] || null;
|
|
262
|
+
}
|
|
263
|
+
catch (dbError) {
|
|
264
|
+
console.error('[hazo_chat/messages/[id]/read PATCH] Database error fetching message:', dbError);
|
|
265
|
+
throw dbError;
|
|
266
|
+
}
|
|
267
|
+
if (!message) {
|
|
268
|
+
console.error('[hazo_chat/messages/[id]/read PATCH] Message not found:', message_id);
|
|
269
|
+
return NextResponse.json({ success: false, error: 'Message not found' }, { status: 404 });
|
|
270
|
+
}
|
|
271
|
+
// Verify that the current user is the receiver (only receivers can mark as read)
|
|
272
|
+
if (message.receiver_user_id !== current_user_id) {
|
|
273
|
+
console.error('[hazo_chat/messages/[id]/read PATCH] User is not the receiver:', {
|
|
274
|
+
message_id,
|
|
275
|
+
current_user_id,
|
|
276
|
+
receiver_user_id: message.receiver_user_id,
|
|
277
|
+
});
|
|
278
|
+
return NextResponse.json({ success: false, error: 'Unauthorized - only the receiver can mark messages as read' }, { status: 403 });
|
|
279
|
+
}
|
|
280
|
+
// Don't update if already read
|
|
281
|
+
if (message.read_at) {
|
|
282
|
+
console.log('[hazo_chat/messages/[id]/read PATCH] Message already read:', message_id);
|
|
283
|
+
return NextResponse.json({
|
|
284
|
+
success: true,
|
|
285
|
+
message: {
|
|
286
|
+
...message,
|
|
287
|
+
read_at: message.read_at,
|
|
288
|
+
},
|
|
289
|
+
});
|
|
290
|
+
}
|
|
291
|
+
// Update the read_at timestamp
|
|
292
|
+
// Use SQLite admin service's updateRows method for reliable updates
|
|
293
|
+
const now = new Date().toISOString();
|
|
294
|
+
try {
|
|
295
|
+
// Use the SQLite admin service which has updateRows method
|
|
296
|
+
const sqliteService = getSqliteAdminService();
|
|
297
|
+
const updated_rows = await sqliteService.updateRows('hazo_chat', { id: message_id }, // criteria: update where id matches
|
|
298
|
+
{ read_at: now, changed_at: now } // data to update
|
|
299
|
+
);
|
|
300
|
+
if (updated_rows.length === 0) {
|
|
301
|
+
console.warn('[hazo_chat/messages/[id]/read PATCH] No rows updated - message may not exist:', message_id);
|
|
302
|
+
// Don't throw error, just log warning - message might have been deleted
|
|
303
|
+
}
|
|
304
|
+
else {
|
|
305
|
+
console.log('[hazo_chat/messages/[id]/read PATCH] Successfully updated', updated_rows.length, 'row(s)');
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
catch (dbError) {
|
|
309
|
+
console.error('[hazo_chat/messages/[id]/read PATCH] Database error updating message:', dbError);
|
|
310
|
+
throw dbError;
|
|
311
|
+
}
|
|
312
|
+
console.log('[hazo_chat/messages/[id]/read PATCH] Message marked as read successfully:', message_id);
|
|
313
|
+
return NextResponse.json({
|
|
314
|
+
success: true,
|
|
315
|
+
message: {
|
|
316
|
+
...message,
|
|
317
|
+
read_at: now,
|
|
318
|
+
changed_at: now,
|
|
319
|
+
},
|
|
320
|
+
});
|
|
321
|
+
}
|
|
322
|
+
catch (error) {
|
|
323
|
+
const error_message = error instanceof Error ? error.message : 'Unknown error';
|
|
324
|
+
console.error('[hazo_chat/messages/[id]/read PATCH] Error:', error_message, error);
|
|
325
|
+
return NextResponse.json({ success: false, error: 'Failed to mark message as read' }, { status: 500 });
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
return { PATCH };
|
|
329
|
+
}
|
|
330
|
+
//# sourceMappingURL=messages.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"messages.js","sourceRoot":"","sources":["../../src/api/messages.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,EAAe,YAAY,EAAE,MAAM,aAAa,CAAC;AACxD,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAI/E,kCAAkC;AAClC,SAAS,YAAY;IACnB,OAAO,sCAAsC,CAAC,OAAO,CAAC,OAAO,EAAE,UAAS,CAAC;QACvE,MAAM,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;QACjC,MAAM,CAAC,GAAG,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;QAC1C,OAAO,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;IACxB,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;GAEG;AACH,KAAK,UAAU,2BAA2B;IACxC,MAAM,WAAW,GAAG,MAAM,OAAO,EAAE,CAAC;IACpC,OAAO,WAAW,CAAC,GAAG,CAAC,mBAAmB,CAAC,EAAE,KAAK,IAAI,IAAI,CAAC;AAC7D,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,qBAAqB,CAAC,OAA+B;IACnE,MAAM,EAAE,cAAc,EAAE,oBAAoB,EAAE,GAAG,OAAO,CAAC;IAEzD;;;;;;;OAOG;IACH,KAAK,UAAU,GAAG,CAAC,OAAoB;QACrC,IAAI,CAAC;YACH,sBAAsB;YACtB,MAAM,eAAe,GAAG,oBAAoB;gBAC1C,CAAC,CAAC,MAAM,oBAAoB,CAAC,OAAO,CAAC;gBACrC,CAAC,CAAC,MAAM,2BAA2B,EAAE,CAAC;YAExC,IAAI,CAAC,eAAe,EAAE,CAAC;gBACrB,OAAO,CAAC,KAAK,CAAC,yDAAyD,CAAC,CAAC;gBACzE,OAAO,YAAY,CAAC,IAAI,CACtB,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,wBAAwB,EAAE,QAAQ,EAAE,EAAE,EAAE,EACjE,EAAE,MAAM,EAAE,GAAG,EAAE,CAChB,CAAC;YACJ,CAAC;YAED,mBAAmB;YACnB,MAAM,EAAE,YAAY,EAAE,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;YAC9C,MAAM,gBAAgB,GAAG,YAAY,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC;YAC9D,MAAM,YAAY,GAAG,YAAY,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,EAAE,CAAC;YAC5D,MAAM,cAAc,GAAG,YAAY,CAAC,GAAG,CAAC,gBAAgB,CAAC,IAAI,EAAE,CAAC;YAEhE,IAAI,CAAC,gBAAgB,EAAE,CAAC;gBACtB,OAAO,CAAC,KAAK,CAAC,mDAAmD,CAAC,CAAC;gBACnE,OAAO,YAAY,CAAC,IAAI,CACtB,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,8BAA8B,EAAE,QAAQ,EAAE,EAAE,EAAE,EACvE,EAAE,MAAM,EAAE,GAAG,EAAE,CAChB,CAAC;YACJ,CAAC;YAED,OAAO,CAAC,GAAG,CAAC,6CAA6C,EAAE;gBACzD,eAAe;gBACf,gBAAgB;gBAChB,YAAY;gBACZ,cAAc;aACf,CAAC,CAAC;YAEH,oDAAoD;YACpD,MAAM,WAAW,GAAG,cAAc,EAAwB,CAAC;YAC3D,MAAM,WAAW,GAAG,iBAAiB,CAAoB,WAAW,EAAE,WAAW,CAAC,CAAC;YAEnF,IAAI,QAAQ,GAAwB,EAAE,CAAC;YAEvC,IAAI,CAAC;gBACH,4CAA4C;gBAC5C,MAAM,YAAY,GAAG,MAAM,WAAW,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE;oBACjD,IAAI,OAAO,GAAG,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;oBAE7B,IAAI,YAAY,EAAE,CAAC;wBACjB,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,cAAc,EAAE,IAAI,EAAE,YAAY,CAAC,CAAC;oBAC9D,CAAC;oBACD,IAAI,cAAc,EAAE,CAAC;wBACnB,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,gBAAgB,EAAE,IAAI,EAAE,cAAc,CAAC,CAAC;oBAClE,CAAC;oBAED,OAAO,OAAO,CAAC,KAAK,CAAC,YAAY,EAAE,KAAK,CAAC,CAAC;gBAC5C,CAAC,CAAC,CAAC;gBAEH,4DAA4D;gBAC5D,QAAQ,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE;oBACrC,MAAM,aAAa,GAAG,GAAG,CAAC,cAAc,KAAK,eAAe,IAAI,GAAG,CAAC,gBAAgB,KAAK,gBAAgB,CAAC;oBAC1G,MAAM,aAAa,GAAG,GAAG,CAAC,cAAc,KAAK,gBAAgB,IAAI,GAAG,CAAC,gBAAgB,KAAK,eAAe,CAAC;oBAC1G,OAAO,aAAa,IAAI,aAAa,CAAC;gBACxC,CAAC,CAAC,CAAC;YACL,CAAC;YAAC,OAAO,OAAO,EAAE,CAAC;gBACjB,OAAO,CAAC,KAAK,CAAC,0CAA0C,EAAE,OAAO,CAAC,CAAC;gBACnE,MAAM,OAAO,CAAC;YAChB,CAAC;YAED,OAAO,CAAC,GAAG,CAAC,0CAA0C,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;YAEzE,OAAO,YAAY,CAAC,IAAI,CAAC;gBACvB,OAAO,EAAE,IAAI;gBACb,QAAQ;gBACR,eAAe;aAChB,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,aAAa,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC;YAC/E,OAAO,CAAC,KAAK,CAAC,iCAAiC,EAAE,aAAa,EAAE,KAAK,CAAC,CAAC;YAEvE,OAAO,YAAY,CAAC,IAAI,CACtB,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,0BAA0B,EAAE,QAAQ,EAAE,EAAE,EAAE,EACnE,EAAE,MAAM,EAAE,GAAG,EAAE,CAChB,CAAC;QACJ,CAAC;IACH,CAAC;IAED;;;;;;;;OAQG;IACH,KAAK,UAAU,IAAI,CAAC,OAAoB;QACtC,IAAI,CAAC;YACH,+BAA+B;YAC/B,MAAM,cAAc,GAAG,oBAAoB;gBACzC,CAAC,CAAC,MAAM,oBAAoB,CAAC,OAAO,CAAC;gBACrC,CAAC,CAAC,MAAM,2BAA2B,EAAE,CAAC;YAExC,IAAI,CAAC,cAAc,EAAE,CAAC;gBACpB,OAAO,CAAC,KAAK,CAAC,0DAA0D,CAAC,CAAC;gBAC1E,OAAO,YAAY,CAAC,IAAI,CACtB,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,wBAAwB,EAAE,EACnD,EAAE,MAAM,EAAE,GAAG,EAAE,CAChB,CAAC;YACJ,CAAC;YAED,qBAAqB;YACrB,MAAM,IAAI,GAAqB,MAAM,OAAO,CAAC,IAAI,EAAE,CAAC;YACpD,MAAM,EAAE,gBAAgB,EAAE,YAAY,EAAE,YAAY,EAAE,cAAc,EAAE,GAAG,IAAI,CAAC;YAE9E,2BAA2B;YAC3B,IAAI,CAAC,gBAAgB,EAAE,CAAC;gBACtB,OAAO,CAAC,KAAK,CAAC,oDAAoD,CAAC,CAAC;gBACpE,OAAO,YAAY,CAAC,IAAI,CACtB,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,8BAA8B,EAAE,EACzD,EAAE,MAAM,EAAE,GAAG,EAAE,CAChB,CAAC;YACJ,CAAC;YAED,IAAI,CAAC,YAAY,IAAI,YAAY,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;gBAChD,OAAO,CAAC,KAAK,CAAC,yDAAyD,CAAC,CAAC;gBACzE,OAAO,YAAY,CAAC,IAAI,CACtB,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,0BAA0B,EAAE,EACrD,EAAE,MAAM,EAAE,GAAG,EAAE,CAChB,CAAC;YACJ,CAAC;YAED,oDAAoD;YACpD,MAAM,WAAW,GAAG,cAAc,EAAwB,CAAC;YAC3D,MAAM,WAAW,GAAG,iBAAiB,CAAoB,WAAW,EAAE,WAAW,CAAC,CAAC;YAEnF,qCAAqC;YACrC,MAAM,UAAU,GAAG,YAAY,EAAE,CAAC;YAClC,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;YAErC,wBAAwB;YACxB,MAAM,cAAc,GAA+B;gBACjD,EAAE,EAAE,UAAU;gBACd,YAAY,EAAE,YAAY,IAAI,EAAE;gBAChC,cAAc,EAAE,cAAc,IAAI,MAAM;gBACxC,cAAc;gBACd,gBAAgB;gBAChB,YAAY,EAAE,YAAY,CAAC,IAAI,EAAE;gBACjC,cAAc,EAAE,IAAI;gBACpB,OAAO,EAAE,IAAI;gBACb,UAAU,EAAE,IAAI;gBAChB,UAAU,EAAE,GAAG;gBACf,UAAU,EAAE,GAAG;aAChB,CAAC;YAEF,OAAO,CAAC,GAAG,CAAC,2CAA2C,EAAE;gBACvD,EAAE,EAAE,UAAU;gBACd,cAAc;gBACd,gBAAgB;gBAChB,YAAY,EAAE,YAAY,IAAI,EAAE;gBAChC,cAAc,EAAE,cAAc,IAAI,MAAM;gBACxC,cAAc,EAAE,YAAY,CAAC,MAAM;aACpC,CAAC,CAAC;YAEH,mBAAmB;YACnB,IAAI,CAAC;gBACH,MAAM,WAAW,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC;YAC3C,CAAC;YAAC,OAAO,OAAO,EAAE,CAAC;gBACjB,OAAO,CAAC,KAAK,CAAC,2CAA2C,EAAE,OAAO,CAAC,CAAC;gBACpE,MAAM,OAAO,CAAC;YAChB,CAAC;YAED,OAAO,CAAC,GAAG,CAAC,uDAAuD,EAAE,UAAU,CAAC,CAAC;YAEjF,OAAO,YAAY,CAAC,IAAI,CAAC;gBACvB,OAAO,EAAE,IAAI;gBACb,OAAO,EAAE;oBACP,EAAE,EAAE,UAAU;oBACd,cAAc;oBACd,gBAAgB;oBAChB,YAAY,EAAE,YAAY,IAAI,EAAE;oBAChC,cAAc,EAAE,cAAc,IAAI,MAAM;oBACxC,YAAY,EAAE,YAAY,CAAC,IAAI,EAAE;oBACjC,cAAc,EAAE,IAAI;oBACpB,OAAO,EAAE,IAAI;oBACb,UAAU,EAAE,IAAI;oBAChB,UAAU,EAAE,GAAG;oBACf,UAAU,EAAE,GAAG;iBAChB;aACF,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,aAAa,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC;YAC/E,OAAO,CAAC,KAAK,CAAC,kCAAkC,EAAE,aAAa,EAAE,KAAK,CAAC,CAAC;YAExE,OAAO,YAAY,CAAC,IAAI,CACtB,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,wBAAwB,EAAE,EACnD,EAAE,MAAM,EAAE,GAAG,EAAE,CAChB,CAAC;QACJ,CAAC;IACH,CAAC;IAED,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC;AACvB,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,uBAAuB,CAAC,OAA+B;IACrE,MAAM,EAAE,cAAc,EAAE,oBAAoB,EAAE,GAAG,OAAO,CAAC;IAEzD;;;;;;;OAOG;IACH,KAAK,UAAU,KAAK,CAClB,OAAoB,EACpB,OAA6D;QAE7D,IAAI,CAAC;YACH,sBAAsB;YACtB,MAAM,eAAe,GAAG,oBAAoB;gBAC1C,CAAC,CAAC,MAAM,oBAAoB,CAAC,OAAO,CAAC;gBACrC,CAAC,CAAC,MAAM,2BAA2B,EAAE,CAAC;YAExC,IAAI,CAAC,eAAe,EAAE,CAAC;gBACrB,OAAO,CAAC,KAAK,CAAC,qEAAqE,CAAC,CAAC;gBACrF,OAAO,YAAY,CAAC,IAAI,CACtB,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,wBAAwB,EAAE,EACnD,EAAE,MAAM,EAAE,GAAG,EAAE,CAChB,CAAC;YACJ,CAAC;YAED,0EAA0E;YAC1E,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,YAAY,OAAO,CAAC,CAAC,CAAC,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC;YACzF,MAAM,UAAU,GAAG,MAAM,CAAC,EAAE,CAAC;YAE7B,IAAI,CAAC,UAAU,EAAE,CAAC;gBAChB,OAAO,CAAC,KAAK,CAAC,yDAAyD,CAAC,CAAC;gBACzE,OAAO,YAAY,CAAC,IAAI,CACtB,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,wBAAwB,EAAE,EACnD,EAAE,MAAM,EAAE,GAAG,EAAE,CAChB,CAAC;YACJ,CAAC;YAED,OAAO,CAAC,GAAG,CAAC,+DAA+D,EAAE;gBAC3E,UAAU;gBACV,eAAe;aAChB,CAAC,CAAC;YAEH,oDAAoD;YACpD,MAAM,WAAW,GAAG,cAAc,EAAwB,CAAC;YAC3D,MAAM,WAAW,GAAG,iBAAiB,CAAoB,WAAW,EAAE,WAAW,CAAC,CAAC;YAEnF,+CAA+C;YAC/C,IAAI,OAAO,GAA6B,IAAI,CAAC;YAC7C,IAAI,CAAC;gBACH,MAAM,QAAQ,GAAG,MAAM,WAAW,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAC7C,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,IAAI,EAAE,IAAI,EAAE,UAAU,CAAC,CAC7C,CAAC;gBACF,OAAO,GAAG,QAAQ,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC;YAChC,CAAC;YAAC,OAAO,OAAO,EAAE,CAAC;gBACjB,OAAO,CAAC,KAAK,CAAC,uEAAuE,EAAE,OAAO,CAAC,CAAC;gBAChG,MAAM,OAAO,CAAC;YAChB,CAAC;YAED,IAAI,CAAC,OAAO,EAAE,CAAC;gBACb,OAAO,CAAC,KAAK,CAAC,yDAAyD,EAAE,UAAU,CAAC,CAAC;gBACrF,OAAO,YAAY,CAAC,IAAI,CACtB,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,mBAAmB,EAAE,EAC9C,EAAE,MAAM,EAAE,GAAG,EAAE,CAChB,CAAC;YACJ,CAAC;YAED,iFAAiF;YACjF,IAAI,OAAO,CAAC,gBAAgB,KAAK,eAAe,EAAE,CAAC;gBACjD,OAAO,CAAC,KAAK,CAAC,gEAAgE,EAAE;oBAC9E,UAAU;oBACV,eAAe;oBACf,gBAAgB,EAAE,OAAO,CAAC,gBAAgB;iBAC3C,CAAC,CAAC;gBACH,OAAO,YAAY,CAAC,IAAI,CACtB,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,4DAA4D,EAAE,EACvF,EAAE,MAAM,EAAE,GAAG,EAAE,CAChB,CAAC;YACJ,CAAC;YAED,+BAA+B;YAC/B,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;gBACpB,OAAO,CAAC,GAAG,CAAC,4DAA4D,EAAE,UAAU,CAAC,CAAC;gBACtF,OAAO,YAAY,CAAC,IAAI,CAAC;oBACvB,OAAO,EAAE,IAAI;oBACb,OAAO,EAAE;wBACP,GAAG,OAAO;wBACV,OAAO,EAAE,OAAO,CAAC,OAAO;qBACzB;iBACF,CAAC,CAAC;YACL,CAAC;YAED,+BAA+B;YAC/B,oEAAoE;YACpE,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;YACrC,IAAI,CAAC;gBACH,2DAA2D;gBAC3D,MAAM,aAAa,GAAG,qBAAqB,EAAE,CAAC;gBAC9C,MAAM,YAAY,GAAG,MAAM,aAAa,CAAC,UAAU,CACjD,WAAW,EACX,EAAE,EAAE,EAAE,UAAU,EAAE,EAAE,oCAAoC;gBACxD,EAAE,OAAO,EAAE,GAAG,EAAE,UAAU,EAAE,GAAG,EAAE,CAAC,iBAAiB;iBACpD,CAAC;gBAEF,IAAI,YAAY,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;oBAC9B,OAAO,CAAC,IAAI,CAAC,+EAA+E,EAAE,UAAU,CAAC,CAAC;oBAC1G,wEAAwE;gBAC1E,CAAC;qBAAM,CAAC;oBACN,OAAO,CAAC,GAAG,CAAC,2DAA2D,EAAE,YAAY,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;gBAC1G,CAAC;YACH,CAAC;YAAC,OAAO,OAAO,EAAE,CAAC;gBACjB,OAAO,CAAC,KAAK,CAAC,uEAAuE,EAAE,OAAO,CAAC,CAAC;gBAChG,MAAM,OAAO,CAAC;YAChB,CAAC;YAED,OAAO,CAAC,GAAG,CAAC,2EAA2E,EAAE,UAAU,CAAC,CAAC;YAErG,OAAO,YAAY,CAAC,IAAI,CAAC;gBACvB,OAAO,EAAE,IAAI;gBACb,OAAO,EAAE;oBACP,GAAG,OAAO;oBACV,OAAO,EAAE,GAAG;oBACZ,UAAU,EAAE,GAAG;iBAChB;aACF,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,aAAa,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC;YAC/E,OAAO,CAAC,KAAK,CAAC,6CAA6C,EAAE,aAAa,EAAE,KAAK,CAAC,CAAC;YAEnF,OAAO,YAAY,CAAC,IAAI,CACtB,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,gCAAgC,EAAE,EAC3D,EAAE,MAAM,EAAE,GAAG,EAAE,CAChB,CAAC;QACJ,CAAC;IACH,CAAC;IAED,OAAO,EAAE,KAAK,EAAE,CAAC;AACnB,CAAC"}
|