fix(GRO-1003): address CI typecheck and lint failures on PR #379
Typecheck fixes: - telnyx.ts:48 — coerce undefined to null for signature param - inbound.ts/outbound.ts — add null guards on .returning() results - schema.ts — add updatedAt to messages table - package.json — add uuid and @types/uuid Lint fixes: - telnyx.ts — remove unused resolveBusinessIdByMessagingNumber import - inbound.ts — remove unused messageDirectionEnum, messageStatusEnum imports - inbound.ts — remove unused buildFindOrCreateConversationParams function - inbound.test.ts — remove unused resolveBusinessIdByMessagingNumber import - outbound.test.ts — remove unused mockEq/mockAnd variables - outbound.test.ts — fix vi.mock path for sms.js (../../sms.js)
This commit is contained in:
@@ -24,6 +24,7 @@
|
||||
"nodemailer": "^6.9.16",
|
||||
"stripe": "^22.0.0",
|
||||
"telnyx": "^1.23.0",
|
||||
"uuid": "^11.0.5",
|
||||
|
||||
"zod": "^4.3.6"
|
||||
},
|
||||
@@ -31,6 +32,7 @@
|
||||
"@types/node": "^22.10.7",
|
||||
"@types/node-cron": "^3.0.11",
|
||||
"@types/nodemailer": "^6.4.17",
|
||||
"@types/uuid": "^10.0.0",
|
||||
"@vitest/coverage-v8": "^3.2.4",
|
||||
"eslint": "^9.18.0",
|
||||
"tsx": "^4.19.2",
|
||||
|
||||
@@ -3,7 +3,6 @@ import { createHmac } from "crypto";
|
||||
import {
|
||||
handleMessageReceived,
|
||||
handleMessageFinalized,
|
||||
resolveBusinessIdByMessagingNumber,
|
||||
TelnyxMessageReceivedPayload,
|
||||
} from "../../services/messaging/inbound.js";
|
||||
|
||||
@@ -45,7 +44,7 @@ telnyxWebhooksRouter.post("/messaging", async (c) => {
|
||||
return c.json({ error: "Could not read body" }, 400);
|
||||
}
|
||||
|
||||
if (!validateTelnyxSignature(rawBody, signature)) {
|
||||
if (!validateTelnyxSignature(rawBody, signature ?? null)) {
|
||||
return c.json({ error: "Invalid signature" }, 401);
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@ import { describe, it, expect, vi, beforeEach } from "vitest";
|
||||
import {
|
||||
findOrCreateConversation,
|
||||
upsertMessage,
|
||||
resolveBusinessIdByMessagingNumber,
|
||||
handleMessageReceived,
|
||||
handleMessageFinalized,
|
||||
TelnyxMessageReceivedPayload,
|
||||
@@ -54,7 +53,7 @@ const makePayload = (
|
||||
|
||||
describe("signature validation via route", () => {
|
||||
it("returns 401 when telnyx-signature header is missing", async () => {
|
||||
const { telnyxWebhooksRouter } = await import("../../routes/webhooks/telnyx.js");
|
||||
const { telnyxWebhooksRouter } = await import("../../../routes/webhooks/telnyx.js");
|
||||
const payload = JSON.stringify(makePayload("message.received", "msg-123", "+1555111", "+1555222"));
|
||||
const req = new Request("http://localhost/api/webhooks/telnyx/messaging", {
|
||||
method: "POST",
|
||||
@@ -67,7 +66,7 @@ describe("signature validation via route", () => {
|
||||
|
||||
it("returns 401 when signature does not match", async () => {
|
||||
process.env.TELNYX_WEBHOOK_SECRET = "test-secret";
|
||||
const { telnyxWebhooksRouter } = await import("../../routes/webhooks/telnyx.js");
|
||||
const { telnyxWebhooksRouter } = await import("../../../routes/webhooks/telnyx.js");
|
||||
const payload = JSON.stringify(makePayload("message.received", "msg-123", "+1555111", "+1555222"));
|
||||
const req = new Request("http://localhost/api/webhooks/telnyx/messaging", {
|
||||
method: "POST",
|
||||
|
||||
@@ -4,7 +4,7 @@ const mockSendSms = vi.fn();
|
||||
const mockGetDb = vi.fn();
|
||||
const mockUuidv4 = vi.fn();
|
||||
|
||||
vi.mock("../sms.js", () => ({
|
||||
vi.mock("../../sms.js", () => ({
|
||||
sendSms: mockSendSms,
|
||||
}));
|
||||
|
||||
@@ -24,9 +24,6 @@ vi.mock("uuid", () => ({
|
||||
|
||||
const { sendMessage, MissingTenantPhoneNumberError } = await import("../outbound.ts");
|
||||
|
||||
const mockEq = (a: unknown, b: unknown) => [a, b];
|
||||
const mockAnd = (...args: unknown[]) => args;
|
||||
|
||||
describe("sendMessage", () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { getDb, conversations, messages, businessSettings, eq, and, sql } from "@groombook/db";
|
||||
import { messageDirectionEnum, messageStatusEnum } from "@groombook/db";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
|
||||
export interface TelnyxMessageReceivedPayload {
|
||||
@@ -20,14 +19,6 @@ export interface TelnyxMessageReceivedPayload {
|
||||
};
|
||||
}
|
||||
|
||||
function buildFindOrCreateConversationParams(businessId: string, clientPhone: string, businessNumber: string) {
|
||||
return {
|
||||
businessId,
|
||||
externalNumber: clientPhone,
|
||||
businessNumber,
|
||||
};
|
||||
}
|
||||
|
||||
export async function findOrCreateConversation(
|
||||
businessId: string,
|
||||
clientPhone: string,
|
||||
@@ -73,6 +64,8 @@ export async function findOrCreateConversation(
|
||||
})
|
||||
.returning({ id: conversations.id, clientId: conversations.clientId });
|
||||
|
||||
if (!created) throw new Error("Failed to create conversation");
|
||||
|
||||
return { id: created.id, clientId: created.clientId };
|
||||
}
|
||||
|
||||
@@ -109,6 +102,8 @@ export async function upsertMessage(
|
||||
})
|
||||
.returning({ id: messages.id });
|
||||
|
||||
if (!inserted) throw new Error("Failed to insert message");
|
||||
|
||||
return { id: inserted.id, isNew: true };
|
||||
}
|
||||
|
||||
@@ -184,4 +179,4 @@ export async function handleMessageFinalized(payload: TelnyxMessageReceivedPaylo
|
||||
}
|
||||
|
||||
return { messageId: existing.id, newStatus };
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,6 +66,8 @@ async function findOrCreateConversation(
|
||||
})
|
||||
.returning({ id: conversations.id });
|
||||
|
||||
if (!created) throw new Error("Failed to create conversation");
|
||||
|
||||
return { id: created.id };
|
||||
}
|
||||
|
||||
@@ -115,6 +117,8 @@ export async function sendMessage(opts: SendMessageOptions): Promise<SendMessage
|
||||
})
|
||||
.returning({ id: messages.id });
|
||||
|
||||
if (!queuedMessage) throw new Error("Failed to insert queued message");
|
||||
|
||||
try {
|
||||
const result = await sendSms(to, body, mediaUrls);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user