fix(api): use notInArray + inArray in unread-count subqueries
the sql.join() form of NOT IN crashed the route handler before it could respond — vercel surfaced the crash as a plaintext 404 instead of going through hono's exception handler. switching to drizzle's notInArray() / inArray() emits stable parameter bindings and resolves both /v1/me/topics (fresh endpoint) and /v1/topics (older endpoint with the same ANY() pattern bug). also cleans up debug instrumentation that was added while chasing the 404. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -41,8 +41,9 @@ export async function request<T = unknown>(opts: RequestOpts): Promise<T> {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (!res.ok) {
|
if (!res.ok) {
|
||||||
let body: unknown;
|
const text = await res.text();
|
||||||
try { body = await res.json(); } catch { body = await res.text(); }
|
let body: unknown = text;
|
||||||
|
try { body = JSON.parse(text); } catch { /* leave as text */ }
|
||||||
throw new ApiError(res.status, res.statusText, body);
|
throw new ApiError(res.status, res.statusText, body);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ import {
|
|||||||
messageQueue,
|
messageQueue,
|
||||||
presence,
|
presence,
|
||||||
} from "@turbostarter/db/schema/mesh";
|
} from "@turbostarter/db/schema/mesh";
|
||||||
import { and, asc, count, desc, eq, gt, inArray, isNull, lt, sql } from "drizzle-orm";
|
import { and, asc, count, desc, eq, gt, inArray, isNull, lt, notInArray, sql } from "drizzle-orm";
|
||||||
|
|
||||||
import { validate } from "../../middleware";
|
import { validate } from "../../middleware";
|
||||||
import {
|
import {
|
||||||
@@ -596,10 +596,7 @@ export const v1Router = new Hono<Env>()
|
|||||||
and(
|
and(
|
||||||
inArray(meshTopicMessage.topicId, topicIds),
|
inArray(meshTopicMessage.topicId, topicIds),
|
||||||
sql`${meshTopicMessage.createdAt} > COALESCE(${meshTopicMember.lastReadAt}, '1970-01-01'::timestamp)`,
|
sql`${meshTopicMessage.createdAt} > COALESCE(${meshTopicMember.lastReadAt}, '1970-01-01'::timestamp)`,
|
||||||
sql`${meshTopicMessage.senderMemberId} NOT IN (${sql.join(
|
notInArray(meshTopicMessage.senderMemberId, myMemberIds),
|
||||||
myMemberIds.map((id) => sql`${id}`),
|
|
||||||
sql`, `,
|
|
||||||
)})`,
|
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.groupBy(meshTopicMessage.topicId);
|
.groupBy(meshTopicMessage.topicId);
|
||||||
@@ -688,7 +685,7 @@ export const v1Router = new Hono<Env>()
|
|||||||
)
|
)
|
||||||
.where(
|
.where(
|
||||||
and(
|
and(
|
||||||
sql`${meshTopicMessage.topicId} = ANY(${topicIds})`,
|
inArray(meshTopicMessage.topicId, topicIds),
|
||||||
sql`${meshTopicMessage.createdAt} > COALESCE(${meshTopicMember.lastReadAt}, '1970-01-01'::timestamp)`,
|
sql`${meshTopicMessage.createdAt} > COALESCE(${meshTopicMember.lastReadAt}, '1970-01-01'::timestamp)`,
|
||||||
sql`${meshTopicMessage.senderMemberId} <> ${key.issuedByMemberId}`,
|
sql`${meshTopicMessage.senderMemberId} <> ${key.issuedByMemberId}`,
|
||||||
),
|
),
|
||||||
|
|||||||
Reference in New Issue
Block a user