| 75 | | { ok: false; reason: 'import_in_progress' | 'invalid_payload' | 'import_failed'; message: string } |
| 76 | |
| 77 | function validatePayload(payload: PushImportPayload, isNew: boolean): string | null { |
| 78 | const messages = payload.messages |
| 79 | if (!Array.isArray(messages) || messages.length === 0) return 'messages is required and must be a non-empty array' |
| 80 | |
| 81 | if (isNew) { |
| 82 | if (!payload.chatlab) return 'chatlab is required for new sessions' |
| 83 | if (!payload.meta) return 'meta is required for new sessions' |
| 84 | const m = payload.meta |
| 85 | if (!m.name) return 'meta.name is required' |
| 86 | if (!m.platform) return 'meta.platform is required' |
| 87 | if (!m.type) return 'meta.type is required' |
| 88 | } |
| 89 | |
| 90 | const { metaUpdateMode, memberUpdateMode } = payload.options ?? {} |
| 91 | if (metaUpdateMode !== undefined && metaUpdateMode !== 'patch' && metaUpdateMode !== 'none') { |
| 92 | return `options.metaUpdateMode must be 'patch' or 'none'` |
| 93 | } |
| 94 | if (memberUpdateMode !== undefined && memberUpdateMode !== 'upsert' && memberUpdateMode !== 'none') { |
| 95 | return `options.memberUpdateMode must be 'upsert' or 'none'` |
| 96 | } |
| 97 | |
| 98 | if (payload.members !== undefined && !Array.isArray(payload.members)) return 'members must be an array' |
| 99 | if (payload.members) { |
| 100 | for (let i = 0; i < payload.members.length; i++) { |
| 101 | if (typeof payload.members[i].platformId !== 'string' || payload.members[i].platformId.length === 0) |
| 102 | return `members[${i}].platformId must be a string` |
| 103 | } |
| 104 | } |
| 105 | |
| 106 | for (let i = 0; i < messages.length; i++) { |
| 107 | const msg = messages[i] |
| 108 | if (typeof msg.sender !== 'string' || msg.sender.length === 0) return `messages[${i}].sender must be a string` |
| 109 | if (typeof msg.timestamp !== 'number' || msg.timestamp <= 0) |
| 110 | return `messages[${i}].timestamp must be a positive number` |
| 111 | if (typeof msg.type !== 'number') return `messages[${i}].type must be a number` |
| 112 | if (msg.content !== undefined && msg.content !== null && typeof msg.content !== 'string') |
| 113 | return `messages[${i}].content must be a string or null` |
| 114 | if (msg.platformMessageId !== undefined && typeof msg.platformMessageId !== 'string') |
| 115 | return `messages[${i}].platformMessageId must be a string` |
| 116 | if (msg.replyToMessageId !== undefined && typeof msg.replyToMessageId !== 'string') |
| 117 | return `messages[${i}].replyToMessageId must be a string` |
| 118 | } |
| 119 | |
| 120 | return null |
| 121 | } |
| 122 | |
| 123 | function queryStats(db: DatabaseAdapter): PushImportResult['session'] { |
| 124 | const row = db.prepare('SELECT COUNT(*) as total, MIN(ts) as first, MAX(ts) as last FROM message').get() as { |