From 5b7d57c29bf5a5d8d0675eaa19668ff9455d6733 Mon Sep 17 00:00:00 2001 From: Jayadeep Bejoy Date: Sun, 25 Jan 2026 18:34:06 +0530 Subject: [PATCH 1/3] Removing SDK call event from stream --- proto/event/v1/event.proto | 15 +- src/__tests__/unit/zod/event.test.ts | 78 ++++++++-- src/gen/auth/v1/auth_connect.ts | 3 +- src/gen/auth/v1/auth_pb.ts | 31 ++-- src/gen/event/v1/event_connect.ts | 10 +- src/gen/event/v1/event_pb.ts | 192 ++++++++++-------------- src/gen/payment/v1/payment_connect.ts | 8 +- src/gen/payment/v1/payment_pb.ts | 57 +++---- src/routes/gRPC/events/registerEvent.ts | 4 +- src/routes/gRPC/events/streamEvents.ts | 80 ++++------ src/utils/eventHelpers.ts | 89 ++++------- src/zod/event.ts | 10 +- 12 files changed, 252 insertions(+), 325 deletions(-) diff --git a/proto/event/v1/event.proto b/proto/event/v1/event.proto index 37e0ca2..68fb041 100644 --- a/proto/event/v1/event.proto +++ b/proto/event/v1/event.proto @@ -43,14 +43,13 @@ message RegisterEventResponse { string random = 1; } -message StreamEventRequest { - EventType type = 1; - string userId = 2; - oneof data { - SDKCall sdkCall = 3; - AITokenUsage aiTokenUsage = 4; - } -} +message StreamEventRequest { + EventType type = 1; + string userId = 2; + oneof data { + AITokenUsage aiTokenUsage = 4; + } +} message AITokenUsage { string model = 1; diff --git a/src/__tests__/unit/zod/event.test.ts b/src/__tests__/unit/zod/event.test.ts index 483b545..c8248bb 100644 --- a/src/__tests__/unit/zod/event.test.ts +++ b/src/__tests__/unit/zod/event.test.ts @@ -1,7 +1,11 @@ -import { describe, it, expect } from "vitest"; -import { eventSchema } from "../../../zod/event"; +import { describe, it, expect, vi } from "vitest"; +vi.mock("../../../storage/db/postgres/db", () => ({ + getPostgresDB: vi.fn(() => ({})), +})); -describe("eventSchema", () => { +import { registerEventSchema, streamEventSchema } from "../../../zod/event"; + +describe("registerEventSchema", () => { it("validates and transforms SDK_CALL event with RAW type", async () => { const validEvent = { type: 1, @@ -18,7 +22,7 @@ describe("eventSchema", () => { }, }; - const result = await eventSchema.safeParseAsync(validEvent); + const result = await registerEventSchema.safeParseAsync(validEvent); expect(result.success).toBe(true); if (result.success) { expect(result.data.type).toBe("SDK_CALL"); @@ -46,7 +50,7 @@ describe("eventSchema", () => { }, }; - const result = await eventSchema.safeParseAsync(validEvent); + const result = await registerEventSchema.safeParseAsync(validEvent); expect(result.success).toBe(true); if (result.success) { expect(result.data.type).toBe("SDK_CALL"); @@ -73,7 +77,7 @@ describe("eventSchema", () => { }, }; - const result = await eventSchema.safeParseAsync(validEvent); + const result = await registerEventSchema.safeParseAsync(validEvent); expect(result.success).toBe(true); if (result.success && result.data.type === "SDK_CALL") { expect(result.data.data.debitAmount).toBe(12345); @@ -96,7 +100,7 @@ describe("eventSchema", () => { }, }; - const result = await eventSchema.safeParseAsync(validEvent); + const result = await registerEventSchema.safeParseAsync(validEvent); expect(result.success).toBe(true); if (result.success && result.data.type === "SDK_CALL") { expect(result.data.data).not.toHaveProperty("case"); @@ -121,7 +125,7 @@ describe("eventSchema", () => { }, }; - const result = await eventSchema.safeParseAsync(invalidEvent); + const result = await registerEventSchema.safeParseAsync(invalidEvent); expect(result.success).toBe(false); if (!result.success) { expect(result.error.issues[0]?.message).toBe("Invalid UUID"); @@ -144,7 +148,7 @@ describe("eventSchema", () => { }, }; - const result = await eventSchema.safeParseAsync(invalidEvent); + const result = await registerEventSchema.safeParseAsync(invalidEvent); expect(result.success).toBe(false); }); @@ -164,7 +168,61 @@ describe("eventSchema", () => { }, }; - const result = await eventSchema.safeParseAsync(invalidEvent); + const result = await registerEventSchema.safeParseAsync(invalidEvent); + expect(result.success).toBe(false); + }); +}); + +describe("streamEventSchema", () => { + it("accepts AI_TOKEN_USAGE events", async () => { + const validEvent = { + type: 2, + userId: "550e8400-e29b-41d4-a716-446655440000", + data: { + case: "aiTokenUsage", + value: { + model: "gpt-4", + inputTokens: 100, + outputTokens: 50, + inputDebit: { + case: "inputAmount", + value: 0.01, + }, + outputDebit: { + case: "outputAmount", + value: 0.02, + }, + }, + }, + }; + + const result = await streamEventSchema.safeParseAsync(validEvent); + expect(result.success).toBe(true); + if (result.success) { + expect(result.data.type).toBe("AI_TOKEN_USAGE"); + if (result.data.type === "AI_TOKEN_USAGE") { + expect(result.data.data.model).toBe("gpt-4"); + } + } + }); + + it("rejects SDK_CALL events", async () => { + const invalidEvent = { + type: 1, + userId: "550e8400-e29b-41d4-a716-446655440000", + data: { + case: "sdkCall", + value: { + sdkCallType: 1, + debit: { + case: "amount", + value: 10.5, + }, + }, + }, + }; + + const result = await streamEventSchema.safeParseAsync(invalidEvent); expect(result.success).toBe(false); }); }); diff --git a/src/gen/auth/v1/auth_connect.ts b/src/gen/auth/v1/auth_connect.ts index 10c60b5..07490d9 100644 --- a/src/gen/auth/v1/auth_connect.ts +++ b/src/gen/auth/v1/auth_connect.ts @@ -23,5 +23,6 @@ export const AuthService = { O: CreateAPIKeyResponse, kind: MethodKind.Unary, }, - }, + } } as const; + diff --git a/src/gen/auth/v1/auth_pb.ts b/src/gen/auth/v1/auth_pb.ts index ba83a3b..dcb1106 100644 --- a/src/gen/auth/v1/auth_pb.ts +++ b/src/gen/auth/v1/auth_pb.ts @@ -2,26 +2,15 @@ // @generated from file auth/v1/auth.proto (package auth.v1, syntax proto3) /* eslint-disable */ -import type { - GenFile, - GenMessage, - GenService, -} from "@bufbuild/protobuf/codegenv2"; -import { - fileDesc, - messageDesc, - serviceDesc, -} from "@bufbuild/protobuf/codegenv2"; +import type { GenFile, GenMessage, GenService } from "@bufbuild/protobuf/codegenv2"; +import { fileDesc, messageDesc, serviceDesc } from "@bufbuild/protobuf/codegenv2"; import type { Message } from "@bufbuild/protobuf"; /** * Describes the file auth/v1/auth.proto. */ -export const file_auth_v1_auth: GenFile = - /*@__PURE__*/ - fileDesc( - "ChJhdXRoL3YxL2F1dGgucHJvdG8SB2F1dGgudjEiNgoTQ3JlYXRlQVBJS2V5UmVxdWVzdBIMCgRuYW1lGAEgASgJEhEKCWV4cGlyZXNJbhgCIAEoAyJsChRDcmVhdGVBUElLZXlSZXNwb25zZRIQCghhcGlLZXlJZBgBIAEoCRIOCgZhcGlLZXkYAiABKAkSDAoEbmFtZRgDIAEoCRIRCgljcmVhdGVkQXQYBCABKAkSEQoJZXhwaXJlc0F0GAUgASgJMlwKC0F1dGhTZXJ2aWNlEk0KDENyZWF0ZUFQSUtleRIcLmF1dGgudjEuQ3JlYXRlQVBJS2V5UmVxdWVzdBodLmF1dGgudjEuQ3JlYXRlQVBJS2V5UmVzcG9uc2UiAGIGcHJvdG8z", - ); +export const file_auth_v1_auth: GenFile = /*@__PURE__*/ + fileDesc("ChJhdXRoL3YxL2F1dGgucHJvdG8SB2F1dGgudjEiNgoTQ3JlYXRlQVBJS2V5UmVxdWVzdBIMCgRuYW1lGAEgASgJEhEKCWV4cGlyZXNJbhgCIAEoAyJsChRDcmVhdGVBUElLZXlSZXNwb25zZRIQCghhcGlLZXlJZBgBIAEoCRIOCgZhcGlLZXkYAiABKAkSDAoEbmFtZRgDIAEoCRIRCgljcmVhdGVkQXQYBCABKAkSEQoJZXhwaXJlc0F0GAUgASgJMlwKC0F1dGhTZXJ2aWNlEk0KDENyZWF0ZUFQSUtleRIcLmF1dGgudjEuQ3JlYXRlQVBJS2V5UmVxdWVzdBodLmF1dGgudjEuQ3JlYXRlQVBJS2V5UmVzcG9uc2UiAGIGcHJvdG8z"); /** * @generated from message auth.v1.CreateAPIKeyRequest @@ -44,8 +33,7 @@ export type CreateAPIKeyRequest = Message<"auth.v1.CreateAPIKeyRequest"> & { * Describes the message auth.v1.CreateAPIKeyRequest. * Use `create(CreateAPIKeyRequestSchema)` to create a new message. */ -export const CreateAPIKeyRequestSchema: GenMessage = - /*@__PURE__*/ +export const CreateAPIKeyRequestSchema: GenMessage = /*@__PURE__*/ messageDesc(file_auth_v1_auth, 0); /** @@ -82,8 +70,7 @@ export type CreateAPIKeyResponse = Message<"auth.v1.CreateAPIKeyResponse"> & { * Describes the message auth.v1.CreateAPIKeyResponse. * Use `create(CreateAPIKeyResponseSchema)` to create a new message. */ -export const CreateAPIKeyResponseSchema: GenMessage = - /*@__PURE__*/ +export const CreateAPIKeyResponseSchema: GenMessage = /*@__PURE__*/ messageDesc(file_auth_v1_auth, 1); /** @@ -99,5 +86,7 @@ export const AuthService: GenService<{ methodKind: "unary"; input: typeof CreateAPIKeyRequestSchema; output: typeof CreateAPIKeyResponseSchema; - }; -}> = /*@__PURE__*/ serviceDesc(file_auth_v1_auth, 0); + }, +}> = /*@__PURE__*/ + serviceDesc(file_auth_v1_auth, 0); + diff --git a/src/gen/event/v1/event_connect.ts b/src/gen/event/v1/event_connect.ts index 00fd773..71d6d0e 100644 --- a/src/gen/event/v1/event_connect.ts +++ b/src/gen/event/v1/event_connect.ts @@ -3,12 +3,7 @@ /* eslint-disable */ // @ts-nocheck -import { - RegisterEventRequest, - RegisterEventResponse, - StreamEventRequest, - StreamEventResponse, -} from "./event_pb.js"; +import { RegisterEventRequest, RegisterEventResponse, StreamEventRequest, StreamEventResponse } from "./event_pb.js"; import { MethodKind } from "@bufbuild/protobuf"; /** @@ -39,5 +34,6 @@ export const EventService = { O: StreamEventResponse, kind: MethodKind.ClientStreaming, }, - }, + } } as const; + diff --git a/src/gen/event/v1/event_pb.ts b/src/gen/event/v1/event_pb.ts index c783e32..b5638f5 100644 --- a/src/gen/event/v1/event_pb.ts +++ b/src/gen/event/v1/event_pb.ts @@ -2,28 +2,15 @@ // @generated from file event/v1/event.proto (package event.v1, syntax proto3) /* eslint-disable */ -import type { - GenEnum, - GenFile, - GenMessage, - GenService, -} from "@bufbuild/protobuf/codegenv2"; -import { - enumDesc, - fileDesc, - messageDesc, - serviceDesc, -} from "@bufbuild/protobuf/codegenv2"; +import type { GenEnum, GenFile, GenMessage, GenService } from "@bufbuild/protobuf/codegenv2"; +import { enumDesc, fileDesc, messageDesc, serviceDesc } from "@bufbuild/protobuf/codegenv2"; import type { Message } from "@bufbuild/protobuf"; /** * Describes the file event/v1/event.proto. */ -export const file_event_v1_event: GenFile = - /*@__PURE__*/ - fileDesc( - "ChRldmVudC92MS9ldmVudC5wcm90bxIIZXZlbnQudjEidwoUUmVnaXN0ZXJFdmVudFJlcXVlc3QSIQoEdHlwZRgBIAEoDjITLmV2ZW50LnYxLkV2ZW50VHlwZRIOCgZ1c2VySWQYAiABKAkSJAoHc2RrQ2FsbBgDIAEoCzIRLmV2ZW50LnYxLlNES0NhbGxIAEIGCgRkYXRhIl8KB1NES0NhbGwSKgoLc2RrQ2FsbFR5cGUYASABKA4yFS5ldmVudC52MS5TREtDYWxsVHlwZRIQCgZhbW91bnQYAiABKAJIABINCgN0YWcYAyABKAlIAEIHCgVkZWJpdCInChVSZWdpc3RlckV2ZW50UmVzcG9uc2USDgoGcmFuZG9tGAEgASgJIqUBChJTdHJlYW1FdmVudFJlcXVlc3QSIQoEdHlwZRgBIAEoDjITLmV2ZW50LnYxLkV2ZW50VHlwZRIOCgZ1c2VySWQYAiABKAkSJAoHc2RrQ2FsbBgDIAEoCzIRLmV2ZW50LnYxLlNES0NhbGxIABIuCgxhaVRva2VuVXNhZ2UYBCABKAsyFi5ldmVudC52MS5BSVRva2VuVXNhZ2VIAEIGCgRkYXRhIr0BCgxBSVRva2VuVXNhZ2USDQoFbW9kZWwYASABKAkSEwoLaW5wdXRUb2tlbnMYAiABKAUSFAoMb3V0cHV0VG9rZW5zGAMgASgFEhUKC2lucHV0QW1vdW50GAQgASgCSAASEgoIaW5wdXRUYWcYBSABKAlIABIWCgxvdXRwdXRBbW91bnQYBiABKAJIARITCglvdXRwdXRUYWcYByABKAlIAUIMCgppbnB1dERlYml0Qg0KC291dHB1dERlYml0Ij8KE1N0cmVhbUV2ZW50UmVzcG9uc2USFwoPZXZlbnRzUHJvY2Vzc2VkGAEgASgFEg8KB21lc3NhZ2UYAiABKAkqSQoJRXZlbnRUeXBlEhoKFkVWRU5UX1RZUEVfVU5TUEVDSUZJRUQQABIMCghTREtfQ0FMTBABEhIKDkFJX1RPS0VOX1VTQUdFEAIqSAoLU0RLQ2FsbFR5cGUSGwoXU0RLQ2FsbFR5cGVfVU5TUEVDSUZJRUQQABIHCgNSQVcQARITCg9NSURETEVXQVJFX0NBTEwQAjKzAQoMRXZlbnRTZXJ2aWNlElIKDVJlZ2lzdGVyRXZlbnQSHi5ldmVudC52MS5SZWdpc3RlckV2ZW50UmVxdWVzdBofLmV2ZW50LnYxLlJlZ2lzdGVyRXZlbnRSZXNwb25zZSIAEk8KDFN0cmVhbUV2ZW50cxIcLmV2ZW50LnYxLlN0cmVhbUV2ZW50UmVxdWVzdBodLmV2ZW50LnYxLlN0cmVhbUV2ZW50UmVzcG9uc2UiACgBYgZwcm90bzM", - ); +export const file_event_v1_event: GenFile = /*@__PURE__*/ + fileDesc("ChRldmVudC92MS9ldmVudC5wcm90bxIIZXZlbnQudjEidwoUUmVnaXN0ZXJFdmVudFJlcXVlc3QSIQoEdHlwZRgBIAEoDjITLmV2ZW50LnYxLkV2ZW50VHlwZRIOCgZ1c2VySWQYAiABKAkSJAoHc2RrQ2FsbBgDIAEoCzIRLmV2ZW50LnYxLlNES0NhbGxIAEIGCgRkYXRhIl8KB1NES0NhbGwSKgoLc2RrQ2FsbFR5cGUYASABKA4yFS5ldmVudC52MS5TREtDYWxsVHlwZRIQCgZhbW91bnQYAiABKAJIABINCgN0YWcYAyABKAlIAEIHCgVkZWJpdCInChVSZWdpc3RlckV2ZW50UmVzcG9uc2USDgoGcmFuZG9tGAEgASgJIn8KElN0cmVhbUV2ZW50UmVxdWVzdBIhCgR0eXBlGAEgASgOMhMuZXZlbnQudjEuRXZlbnRUeXBlEg4KBnVzZXJJZBgCIAEoCRIuCgxhaVRva2VuVXNhZ2UYBCABKAsyFi5ldmVudC52MS5BSVRva2VuVXNhZ2VIAEIGCgRkYXRhIr0BCgxBSVRva2VuVXNhZ2USDQoFbW9kZWwYASABKAkSEwoLaW5wdXRUb2tlbnMYAiABKAUSFAoMb3V0cHV0VG9rZW5zGAMgASgFEhUKC2lucHV0QW1vdW50GAQgASgCSAASEgoIaW5wdXRUYWcYBSABKAlIABIWCgxvdXRwdXRBbW91bnQYBiABKAJIARITCglvdXRwdXRUYWcYByABKAlIAUIMCgppbnB1dERlYml0Qg0KC291dHB1dERlYml0Ij8KE1N0cmVhbUV2ZW50UmVzcG9uc2USFwoPZXZlbnRzUHJvY2Vzc2VkGAEgASgFEg8KB21lc3NhZ2UYAiABKAkqSQoJRXZlbnRUeXBlEhoKFkVWRU5UX1RZUEVfVU5TUEVDSUZJRUQQABIMCghTREtfQ0FMTBABEhIKDkFJX1RPS0VOX1VTQUdFEAIqSAoLU0RLQ2FsbFR5cGUSGwoXU0RLQ2FsbFR5cGVfVU5TUEVDSUZJRUQQABIHCgNSQVcQARITCg9NSURETEVXQVJFX0NBTEwQAjKzAQoMRXZlbnRTZXJ2aWNlElIKDVJlZ2lzdGVyRXZlbnQSHi5ldmVudC52MS5SZWdpc3RlckV2ZW50UmVxdWVzdBofLmV2ZW50LnYxLlJlZ2lzdGVyRXZlbnRSZXNwb25zZSIAEk8KDFN0cmVhbUV2ZW50cxIcLmV2ZW50LnYxLlN0cmVhbUV2ZW50UmVxdWVzdBodLmV2ZW50LnYxLlN0cmVhbUV2ZW50UmVzcG9uc2UiACgBYgZwcm90bzM"); /** * @generated from message event.v1.RegisterEventRequest @@ -42,23 +29,20 @@ export type RegisterEventRequest = Message<"event.v1.RegisterEventRequest"> & { /** * @generated from oneof event.v1.RegisterEventRequest.data */ - data: - | { - /** - * @generated from field: event.v1.SDKCall sdkCall = 3; - */ - value: SDKCall; - case: "sdkCall"; - } - | { case: undefined; value?: undefined }; + data: { + /** + * @generated from field: event.v1.SDKCall sdkCall = 3; + */ + value: SDKCall; + case: "sdkCall"; + } | { case: undefined; value?: undefined }; }; /** * Describes the message event.v1.RegisterEventRequest. * Use `create(RegisterEventRequestSchema)` to create a new message. */ -export const RegisterEventRequestSchema: GenMessage = - /*@__PURE__*/ +export const RegisterEventRequestSchema: GenMessage = /*@__PURE__*/ messageDesc(file_event_v1_event, 0); /** @@ -73,49 +57,43 @@ export type SDKCall = Message<"event.v1.SDKCall"> & { /** * @generated from oneof event.v1.SDKCall.debit */ - debit: - | { - /** - * @generated from field: float amount = 2; - */ - value: number; - case: "amount"; - } - | { - /** - * @generated from field: string tag = 3; - */ - value: string; - case: "tag"; - } - | { case: undefined; value?: undefined }; + debit: { + /** + * @generated from field: float amount = 2; + */ + value: number; + case: "amount"; + } | { + /** + * @generated from field: string tag = 3; + */ + value: string; + case: "tag"; + } | { case: undefined; value?: undefined }; }; /** * Describes the message event.v1.SDKCall. * Use `create(SDKCallSchema)` to create a new message. */ -export const SDKCallSchema: GenMessage = - /*@__PURE__*/ +export const SDKCallSchema: GenMessage = /*@__PURE__*/ messageDesc(file_event_v1_event, 1); /** * @generated from message event.v1.RegisterEventResponse */ -export type RegisterEventResponse = - Message<"event.v1.RegisterEventResponse"> & { - /** - * @generated from field: string random = 1; - */ - random: string; - }; +export type RegisterEventResponse = Message<"event.v1.RegisterEventResponse"> & { + /** + * @generated from field: string random = 1; + */ + random: string; +}; /** * Describes the message event.v1.RegisterEventResponse. * Use `create(RegisterEventResponseSchema)` to create a new message. */ -export const RegisterEventResponseSchema: GenMessage = - /*@__PURE__*/ +export const RegisterEventResponseSchema: GenMessage = /*@__PURE__*/ messageDesc(file_event_v1_event, 2); /** @@ -135,30 +113,20 @@ export type StreamEventRequest = Message<"event.v1.StreamEventRequest"> & { /** * @generated from oneof event.v1.StreamEventRequest.data */ - data: - | { - /** - * @generated from field: event.v1.SDKCall sdkCall = 3; - */ - value: SDKCall; - case: "sdkCall"; - } - | { - /** - * @generated from field: event.v1.AITokenUsage aiTokenUsage = 4; - */ - value: AITokenUsage; - case: "aiTokenUsage"; - } - | { case: undefined; value?: undefined }; + data: { + /** + * @generated from field: event.v1.AITokenUsage aiTokenUsage = 4; + */ + value: AITokenUsage; + case: "aiTokenUsage"; + } | { case: undefined; value?: undefined }; }; /** * Describes the message event.v1.StreamEventRequest. * Use `create(StreamEventRequestSchema)` to create a new message. */ -export const StreamEventRequestSchema: GenMessage = - /*@__PURE__*/ +export const StreamEventRequestSchema: GenMessage = /*@__PURE__*/ messageDesc(file_event_v1_event, 3); /** @@ -183,50 +151,43 @@ export type AITokenUsage = Message<"event.v1.AITokenUsage"> & { /** * @generated from oneof event.v1.AITokenUsage.inputDebit */ - inputDebit: - | { - /** - * @generated from field: float inputAmount = 4; - */ - value: number; - case: "inputAmount"; - } - | { - /** - * @generated from field: string inputTag = 5; - */ - value: string; - case: "inputTag"; - } - | { case: undefined; value?: undefined }; + inputDebit: { + /** + * @generated from field: float inputAmount = 4; + */ + value: number; + case: "inputAmount"; + } | { + /** + * @generated from field: string inputTag = 5; + */ + value: string; + case: "inputTag"; + } | { case: undefined; value?: undefined }; /** * @generated from oneof event.v1.AITokenUsage.outputDebit */ - outputDebit: - | { - /** - * @generated from field: float outputAmount = 6; - */ - value: number; - case: "outputAmount"; - } - | { - /** - * @generated from field: string outputTag = 7; - */ - value: string; - case: "outputTag"; - } - | { case: undefined; value?: undefined }; + outputDebit: { + /** + * @generated from field: float outputAmount = 6; + */ + value: number; + case: "outputAmount"; + } | { + /** + * @generated from field: string outputTag = 7; + */ + value: string; + case: "outputTag"; + } | { case: undefined; value?: undefined }; }; /** * Describes the message event.v1.AITokenUsage. * Use `create(AITokenUsageSchema)` to create a new message. */ -export const AITokenUsageSchema: GenMessage = - /*@__PURE__*/ +export const AITokenUsageSchema: GenMessage = /*@__PURE__*/ messageDesc(file_event_v1_event, 4); /** @@ -248,8 +209,7 @@ export type StreamEventResponse = Message<"event.v1.StreamEventResponse"> & { * Describes the message event.v1.StreamEventResponse. * Use `create(StreamEventResponseSchema)` to create a new message. */ -export const StreamEventResponseSchema: GenMessage = - /*@__PURE__*/ +export const StreamEventResponseSchema: GenMessage = /*@__PURE__*/ messageDesc(file_event_v1_event, 5); /** @@ -275,8 +235,7 @@ export enum EventType { /** * Describes the enum event.v1.EventType. */ -export const EventTypeSchema: GenEnum = - /*@__PURE__*/ +export const EventTypeSchema: GenEnum = /*@__PURE__*/ enumDesc(file_event_v1_event, 0); /** @@ -302,8 +261,7 @@ export enum SDKCallType { /** * Describes the enum event.v1.SDKCallType. */ -export const SDKCallTypeSchema: GenEnum = - /*@__PURE__*/ +export const SDKCallTypeSchema: GenEnum = /*@__PURE__*/ enumDesc(file_event_v1_event, 1); /** @@ -319,7 +277,7 @@ export const EventService: GenService<{ methodKind: "unary"; input: typeof RegisterEventRequestSchema; output: typeof RegisterEventResponseSchema; - }; + }, /** * StreamEvents streams events from client to server (e.g., AI token usage) * @@ -329,5 +287,7 @@ export const EventService: GenService<{ methodKind: "client_streaming"; input: typeof StreamEventRequestSchema; output: typeof StreamEventResponseSchema; - }; -}> = /*@__PURE__*/ serviceDesc(file_event_v1_event, 0); + }, +}> = /*@__PURE__*/ + serviceDesc(file_event_v1_event, 0); + diff --git a/src/gen/payment/v1/payment_connect.ts b/src/gen/payment/v1/payment_connect.ts index 2380330..48122d7 100644 --- a/src/gen/payment/v1/payment_connect.ts +++ b/src/gen/payment/v1/payment_connect.ts @@ -3,10 +3,7 @@ /* eslint-disable */ // @ts-nocheck -import { - CreateCheckoutLinkRequest, - CreateCheckoutLinkResponse, -} from "./payment_pb.js"; +import { CreateCheckoutLinkRequest, CreateCheckoutLinkResponse } from "./payment_pb.js"; import { MethodKind } from "@bufbuild/protobuf"; /** @@ -26,5 +23,6 @@ export const PaymentService = { O: CreateCheckoutLinkResponse, kind: MethodKind.Unary, }, - }, + } } as const; + diff --git a/src/gen/payment/v1/payment_pb.ts b/src/gen/payment/v1/payment_pb.ts index 5678d02..25329f0 100644 --- a/src/gen/payment/v1/payment_pb.ts +++ b/src/gen/payment/v1/payment_pb.ts @@ -2,63 +2,48 @@ // @generated from file payment/v1/payment.proto (package payment.v1, syntax proto3) /* eslint-disable */ -import type { - GenFile, - GenMessage, - GenService, -} from "@bufbuild/protobuf/codegenv2"; -import { - fileDesc, - messageDesc, - serviceDesc, -} from "@bufbuild/protobuf/codegenv2"; +import type { GenFile, GenMessage, GenService } from "@bufbuild/protobuf/codegenv2"; +import { fileDesc, messageDesc, serviceDesc } from "@bufbuild/protobuf/codegenv2"; import type { Message } from "@bufbuild/protobuf"; /** * Describes the file payment/v1/payment.proto. */ -export const file_payment_v1_payment: GenFile = - /*@__PURE__*/ - fileDesc( - "ChhwYXltZW50L3YxL3BheW1lbnQucHJvdG8SCnBheW1lbnQudjEiKwoZQ3JlYXRlQ2hlY2tvdXRMaW5rUmVxdWVzdBIOCgZ1c2VySWQYASABKAkiMgoaQ3JlYXRlQ2hlY2tvdXRMaW5rUmVzcG9uc2USFAoMY2hlY2tvdXRMaW5rGAEgASgJMncKDlBheW1lbnRTZXJ2aWNlEmUKEkNyZWF0ZUNoZWNrb3V0TGluaxIlLnBheW1lbnQudjEuQ3JlYXRlQ2hlY2tvdXRMaW5rUmVxdWVzdBomLnBheW1lbnQudjEuQ3JlYXRlQ2hlY2tvdXRMaW5rUmVzcG9uc2UiAGIGcHJvdG8z", - ); +export const file_payment_v1_payment: GenFile = /*@__PURE__*/ + fileDesc("ChhwYXltZW50L3YxL3BheW1lbnQucHJvdG8SCnBheW1lbnQudjEiKwoZQ3JlYXRlQ2hlY2tvdXRMaW5rUmVxdWVzdBIOCgZ1c2VySWQYASABKAkiMgoaQ3JlYXRlQ2hlY2tvdXRMaW5rUmVzcG9uc2USFAoMY2hlY2tvdXRMaW5rGAEgASgJMncKDlBheW1lbnRTZXJ2aWNlEmUKEkNyZWF0ZUNoZWNrb3V0TGluaxIlLnBheW1lbnQudjEuQ3JlYXRlQ2hlY2tvdXRMaW5rUmVxdWVzdBomLnBheW1lbnQudjEuQ3JlYXRlQ2hlY2tvdXRMaW5rUmVzcG9uc2UiAGIGcHJvdG8z"); /** * @generated from message payment.v1.CreateCheckoutLinkRequest */ -export type CreateCheckoutLinkRequest = - Message<"payment.v1.CreateCheckoutLinkRequest"> & { - /** - * @generated from field: string userId = 1; - */ - userId: string; - }; +export type CreateCheckoutLinkRequest = Message<"payment.v1.CreateCheckoutLinkRequest"> & { + /** + * @generated from field: string userId = 1; + */ + userId: string; +}; /** * Describes the message payment.v1.CreateCheckoutLinkRequest. * Use `create(CreateCheckoutLinkRequestSchema)` to create a new message. */ -export const CreateCheckoutLinkRequestSchema: GenMessage = - /*@__PURE__*/ +export const CreateCheckoutLinkRequestSchema: GenMessage = /*@__PURE__*/ messageDesc(file_payment_v1_payment, 0); /** * @generated from message payment.v1.CreateCheckoutLinkResponse */ -export type CreateCheckoutLinkResponse = - Message<"payment.v1.CreateCheckoutLinkResponse"> & { - /** - * @generated from field: string checkoutLink = 1; - */ - checkoutLink: string; - }; +export type CreateCheckoutLinkResponse = Message<"payment.v1.CreateCheckoutLinkResponse"> & { + /** + * @generated from field: string checkoutLink = 1; + */ + checkoutLink: string; +}; /** * Describes the message payment.v1.CreateCheckoutLinkResponse. * Use `create(CreateCheckoutLinkResponseSchema)` to create a new message. */ -export const CreateCheckoutLinkResponseSchema: GenMessage = - /*@__PURE__*/ +export const CreateCheckoutLinkResponseSchema: GenMessage = /*@__PURE__*/ messageDesc(file_payment_v1_payment, 1); /** @@ -74,5 +59,7 @@ export const PaymentService: GenService<{ methodKind: "unary"; input: typeof CreateCheckoutLinkRequestSchema; output: typeof CreateCheckoutLinkResponseSchema; - }; -}> = /*@__PURE__*/ serviceDesc(file_payment_v1_payment, 0); + }, +}> = /*@__PURE__*/ + serviceDesc(file_payment_v1_payment, 0); + diff --git a/src/routes/gRPC/events/registerEvent.ts b/src/routes/gRPC/events/registerEvent.ts index 102c568..608aebc 100644 --- a/src/routes/gRPC/events/registerEvent.ts +++ b/src/routes/gRPC/events/registerEvent.ts @@ -10,7 +10,7 @@ import { apiKeyContextKey } from "../../../context/auth"; import { logger } from "../../../errors/logger"; import { extractApiKeyFromContext, - validateAndParseEvent, + validateAndParseRegisterEvent, createEventInstance, storeEvent, } from "../../../utils/eventHelpers"; @@ -35,7 +35,7 @@ export async function registerEvent( ); // Validate and parse the incoming event - const eventSkeleton = await validateAndParseEvent(req); + const eventSkeleton = await validateAndParseRegisterEvent(req); // Create the appropriate event instance const event = createEventInstance(eventSkeleton); diff --git a/src/routes/gRPC/events/streamEvents.ts b/src/routes/gRPC/events/streamEvents.ts index a80df2e..d9f790c 100644 --- a/src/routes/gRPC/events/streamEvents.ts +++ b/src/routes/gRPC/events/streamEvents.ts @@ -2,7 +2,7 @@ import type { StreamEventRequest, StreamEventResponse, } from "../../../gen/event/v1/event_pb"; -import type { Event, EventKind } from "../../../interface/event/Event"; +import type { SqlRecord } from "../../../interface/event/Event"; import { StreamEventResponseSchema } from "../../../gen/event/v1/event_pb"; import { create } from "@bufbuild/protobuf"; import { EventError } from "../../../errors/event"; @@ -11,10 +11,10 @@ import { apiKeyContextKey } from "../../../context/auth"; import { logger } from "../../../errors/logger"; import { extractApiKeyFromContext, - validateAndParseEvent, + validateAndParseStreamEvent, createEventInstance, - storeEventsBatch, } from "../../../utils/eventHelpers"; +import { handleAddAiTokenUsage } from "../../../storage/adapter/postgres/handlers"; const OPERATION = "StreamEvents"; @@ -23,7 +23,6 @@ export async function streamEvents( context: HandlerContext, ): Promise { let eventsProcessed = 0; - const events: Array> = []; try { // Extract API key ID from context @@ -40,63 +39,38 @@ export async function streamEvents( // Collect all events from the stream for await (const req of requestStream) { - try { - // Validate and parse the incoming event - const eventSkeleton = await validateAndParseEvent(req); + // Validate and parse the incoming event + const eventSkeleton = await validateAndParseStreamEvent(req); - // Create the appropriate event instance - const event = createEventInstance(eventSkeleton); + // Create the appropriate event instance + const event = createEventInstance(eventSkeleton); - // Add to events array instead of storing immediately - events.push(event); - - logger.logOperationInfo( - OPERATION, - "event_validated", - "Event validated and queued", - { - apiKeyId, - userId: eventSkeleton.userId, - eventNumber: events.length, - }, - ); - } catch (error) { - // Log error but continue processing other events - logger.logOperationError( - OPERATION, - "event_validation_failed", - error instanceof EventError ? error.type : "UNKNOWN", - "Failed to validate event in stream", - error instanceof Error ? error : undefined, - { apiKeyId, eventNumber: events.length + 1 }, + const { SQL } = event.serialize(); + if (!SQL) { + throw EventError.serializationError( + "Event serialization returned null or undefined", ); - - // Continue collecting remaining events } - } + if (SQL.type !== "AI_TOKEN_USAGE") { + throw EventError.unsupportedEventType(SQL.type); + } + + await handleAddAiTokenUsage( + [SQL], + apiKeyId, + ); + eventsProcessed += 1; - // Store all events in one batch after stream completes - if (events.length > 0) { logger.logOperationInfo( OPERATION, - "storing_batch", - `Storing ${events.length} events in batch`, - { apiKeyId, totalEvents: events.length }, + "event_processed", + "Event processed and stored", + { + apiKeyId, + userId: eventSkeleton.userId, + eventNumber: eventsProcessed, + }, ); - - try { - await storeEventsBatch(events, apiKeyId); - eventsProcessed = events.length; - } catch (error) { - logger.logOperationError( - OPERATION, - "batch_storage_failed", - error instanceof EventError ? error.type : "UNKNOWN", - "Failed to store events in batch", - error instanceof Error ? error : undefined, - { apiKeyId, totalEvents: events.length }, - ); - } } logger.logOperationInfo( diff --git a/src/utils/eventHelpers.ts b/src/utils/eventHelpers.ts index 7d61dd6..43bbe13 100644 --- a/src/utils/eventHelpers.ts +++ b/src/utils/eventHelpers.ts @@ -2,15 +2,13 @@ import type { HandlerContext } from "@connectrpc/connect"; import { apiKeyContextKey } from "../context/auth"; import { AuthError } from "../errors/auth"; import { EventError } from "../errors/event"; -import { eventSchema } from "../zod/event"; +import { registerEventSchema, streamEventSchema } from "../zod/event"; import { ZodError } from "zod"; -import type { Event, SqlRecord } from "../interface/event/Event"; +import type { Event } from "../interface/event/Event"; import { SDKCall } from "../events/RawEvents/SDKCall"; import { AITokenUsage } from "../events/AIEvents/AITokenUsage"; import { RequestAITokenUsage } from "../events/RequestEvents/RequestAITokenUsage"; import { StorageAdapterFactory } from "../factory"; -import { handleAddAiTokenUsage } from "../storage/adapter/postgres/handlers"; -import { StorageError } from "../errors/storage"; import type { RegisterEventRequest, StreamEventRequest, @@ -30,11 +28,33 @@ export function extractApiKeyFromContext(context: HandlerContext): string { /** * Validate and parse the incoming event request */ -export async function validateAndParseEvent( - req: RegisterEventRequest | StreamEventRequest, +export async function validateAndParseRegisterEvent( + req: RegisterEventRequest, ) { try { - return await eventSchema.parseAsync(req); + return await registerEventSchema.parseAsync(req); + } catch (error) { + if (error instanceof EventError) { + throw error; + } + if (error instanceof ZodError) { + const issues = error.issues + .map((issue) => `${issue.path.join(".")}: ${issue.message}`) + .join("; "); + throw EventError.validationFailed(issues, error); + } + throw EventError.validationFailed( + "Unknown validation error", + error as Error, + ); + } +} + +export async function validateAndParseStreamEvent( + req: StreamEventRequest, +) { + try { + return await streamEventSchema.parseAsync(req); } catch (error) { if (error instanceof EventError) { throw error; @@ -106,58 +126,3 @@ export async function storeEvent( /** * Store multiple events in a batch - groups by type and uses batch operations when possible */ -export async function storeEventsBatch( - events: Event[], - apiKeyId: string, -): Promise { - if (events.length === 0) { - return; - } - - // Group events by type - const eventsByType = new Map(); - for (const event of events) { - const type = event.type; - if (!eventsByType.has(type)) { - eventsByType.set(type, []); - } - eventsByType.get(type)!.push(event); - } - - // Process each type - for (const [type, typeEvents] of eventsByType) { - try { - if (type === "AI_TOKEN_USAGE") { - // Batch process AI_TOKEN_USAGE events - const serializedEvents: Array> = []; - - for (const event of typeEvents) { - const { SQL } = event.serialize(); - if (!SQL) { - throw StorageError.serializationFailed( - "Event serialization returned null or undefined", - ); - } - if (SQL.type !== "AI_TOKEN_USAGE") { - throw StorageError.serializationFailed( - `Expected AI_TOKEN_USAGE but got ${SQL.type}`, - ); - } - serializedEvents.push(SQL as SqlRecord<"AI_TOKEN_USAGE">); - } - - await handleAddAiTokenUsage(serializedEvents, apiKeyId); - } else { - // For other event types, use individual storage - for (const event of typeEvents) { - await storeEvent(event, apiKeyId); - } - } - } catch (error) { - throw EventError.serializationError( - `Failed to store ${type} events`, - error as Error, - ); - } - } -} diff --git a/src/zod/event.ts b/src/zod/event.ts index 88f56df..cd6895c 100644 --- a/src/zod/event.ts +++ b/src/zod/event.ts @@ -173,8 +173,8 @@ const AITokenUsageEvent = BaseEvent.extend({ .transform((obj) => obj.value), }); -export const eventSchema = z.discriminatedUnion("type", [ - SDKCallEvent, - AITokenUsageEvent, -]); -export type EventSchemaType = z.infer; +export const registerEventSchema = SDKCallEvent; +export type RegisterEventSchemaType = z.infer; + +export const streamEventSchema = AITokenUsageEvent; +export type StreamEventSchemaType = z.infer; From 99e8c3921f94e2796698944cae903e140ae1dea9 Mon Sep 17 00:00:00 2001 From: Jayadeep Bejoy Date: Mon, 26 Jan 2026 18:02:54 +0530 Subject: [PATCH 2/3] refactor: streamEvent Signed-off-by: Jayadeep Bejoy --- .gitignore | 1 + .prettierrc | 17 +++ src/gen/auth/v1/auth_connect.ts | 3 +- src/gen/auth/v1/auth_pb.ts | 31 +++-- src/gen/event/v1/event_connect.ts | 10 +- src/gen/event/v1/event_pb.ts | 185 +++++++++++++++---------- src/gen/payment/v1/payment_connect.ts | 8 +- src/gen/payment/v1/payment_pb.ts | 57 +++++--- src/routes/gRPC/events/streamEvents.ts | 19 +-- src/utils/eventHelpers.ts | 8 +- 10 files changed, 203 insertions(+), 136 deletions(-) create mode 100644 .prettierrc diff --git a/.gitignore b/.gitignore index 7b2fa09..699324a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ # dependencies (bun install) node_modules +nul # output out diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..b15c93c --- /dev/null +++ b/.prettierrc @@ -0,0 +1,17 @@ +{ + "printWidth": 80, + "tabWidth": 2, + "useTabs": false, + "semi": true, + "singleQuote": false, + "quoteProps": "as-needed", + "jsxSingleQuote": false, + "trailingComma": "es5", + "bracketSpacing": true, + "bracketSameLine": false, + "arrowParens": "always", + "proseWrap": "preserve", + "htmlWhitespaceSensitivity": "css", + "endOfLine": "lf", + "embeddedLanguageFormatting": "auto" +} diff --git a/src/gen/auth/v1/auth_connect.ts b/src/gen/auth/v1/auth_connect.ts index 07490d9..10c60b5 100644 --- a/src/gen/auth/v1/auth_connect.ts +++ b/src/gen/auth/v1/auth_connect.ts @@ -23,6 +23,5 @@ export const AuthService = { O: CreateAPIKeyResponse, kind: MethodKind.Unary, }, - } + }, } as const; - diff --git a/src/gen/auth/v1/auth_pb.ts b/src/gen/auth/v1/auth_pb.ts index dcb1106..ba83a3b 100644 --- a/src/gen/auth/v1/auth_pb.ts +++ b/src/gen/auth/v1/auth_pb.ts @@ -2,15 +2,26 @@ // @generated from file auth/v1/auth.proto (package auth.v1, syntax proto3) /* eslint-disable */ -import type { GenFile, GenMessage, GenService } from "@bufbuild/protobuf/codegenv2"; -import { fileDesc, messageDesc, serviceDesc } from "@bufbuild/protobuf/codegenv2"; +import type { + GenFile, + GenMessage, + GenService, +} from "@bufbuild/protobuf/codegenv2"; +import { + fileDesc, + messageDesc, + serviceDesc, +} from "@bufbuild/protobuf/codegenv2"; import type { Message } from "@bufbuild/protobuf"; /** * Describes the file auth/v1/auth.proto. */ -export const file_auth_v1_auth: GenFile = /*@__PURE__*/ - fileDesc("ChJhdXRoL3YxL2F1dGgucHJvdG8SB2F1dGgudjEiNgoTQ3JlYXRlQVBJS2V5UmVxdWVzdBIMCgRuYW1lGAEgASgJEhEKCWV4cGlyZXNJbhgCIAEoAyJsChRDcmVhdGVBUElLZXlSZXNwb25zZRIQCghhcGlLZXlJZBgBIAEoCRIOCgZhcGlLZXkYAiABKAkSDAoEbmFtZRgDIAEoCRIRCgljcmVhdGVkQXQYBCABKAkSEQoJZXhwaXJlc0F0GAUgASgJMlwKC0F1dGhTZXJ2aWNlEk0KDENyZWF0ZUFQSUtleRIcLmF1dGgudjEuQ3JlYXRlQVBJS2V5UmVxdWVzdBodLmF1dGgudjEuQ3JlYXRlQVBJS2V5UmVzcG9uc2UiAGIGcHJvdG8z"); +export const file_auth_v1_auth: GenFile = + /*@__PURE__*/ + fileDesc( + "ChJhdXRoL3YxL2F1dGgucHJvdG8SB2F1dGgudjEiNgoTQ3JlYXRlQVBJS2V5UmVxdWVzdBIMCgRuYW1lGAEgASgJEhEKCWV4cGlyZXNJbhgCIAEoAyJsChRDcmVhdGVBUElLZXlSZXNwb25zZRIQCghhcGlLZXlJZBgBIAEoCRIOCgZhcGlLZXkYAiABKAkSDAoEbmFtZRgDIAEoCRIRCgljcmVhdGVkQXQYBCABKAkSEQoJZXhwaXJlc0F0GAUgASgJMlwKC0F1dGhTZXJ2aWNlEk0KDENyZWF0ZUFQSUtleRIcLmF1dGgudjEuQ3JlYXRlQVBJS2V5UmVxdWVzdBodLmF1dGgudjEuQ3JlYXRlQVBJS2V5UmVzcG9uc2UiAGIGcHJvdG8z", + ); /** * @generated from message auth.v1.CreateAPIKeyRequest @@ -33,7 +44,8 @@ export type CreateAPIKeyRequest = Message<"auth.v1.CreateAPIKeyRequest"> & { * Describes the message auth.v1.CreateAPIKeyRequest. * Use `create(CreateAPIKeyRequestSchema)` to create a new message. */ -export const CreateAPIKeyRequestSchema: GenMessage = /*@__PURE__*/ +export const CreateAPIKeyRequestSchema: GenMessage = + /*@__PURE__*/ messageDesc(file_auth_v1_auth, 0); /** @@ -70,7 +82,8 @@ export type CreateAPIKeyResponse = Message<"auth.v1.CreateAPIKeyResponse"> & { * Describes the message auth.v1.CreateAPIKeyResponse. * Use `create(CreateAPIKeyResponseSchema)` to create a new message. */ -export const CreateAPIKeyResponseSchema: GenMessage = /*@__PURE__*/ +export const CreateAPIKeyResponseSchema: GenMessage = + /*@__PURE__*/ messageDesc(file_auth_v1_auth, 1); /** @@ -86,7 +99,5 @@ export const AuthService: GenService<{ methodKind: "unary"; input: typeof CreateAPIKeyRequestSchema; output: typeof CreateAPIKeyResponseSchema; - }, -}> = /*@__PURE__*/ - serviceDesc(file_auth_v1_auth, 0); - + }; +}> = /*@__PURE__*/ serviceDesc(file_auth_v1_auth, 0); diff --git a/src/gen/event/v1/event_connect.ts b/src/gen/event/v1/event_connect.ts index 71d6d0e..00fd773 100644 --- a/src/gen/event/v1/event_connect.ts +++ b/src/gen/event/v1/event_connect.ts @@ -3,7 +3,12 @@ /* eslint-disable */ // @ts-nocheck -import { RegisterEventRequest, RegisterEventResponse, StreamEventRequest, StreamEventResponse } from "./event_pb.js"; +import { + RegisterEventRequest, + RegisterEventResponse, + StreamEventRequest, + StreamEventResponse, +} from "./event_pb.js"; import { MethodKind } from "@bufbuild/protobuf"; /** @@ -34,6 +39,5 @@ export const EventService = { O: StreamEventResponse, kind: MethodKind.ClientStreaming, }, - } + }, } as const; - diff --git a/src/gen/event/v1/event_pb.ts b/src/gen/event/v1/event_pb.ts index b5638f5..4ef3bc2 100644 --- a/src/gen/event/v1/event_pb.ts +++ b/src/gen/event/v1/event_pb.ts @@ -2,15 +2,28 @@ // @generated from file event/v1/event.proto (package event.v1, syntax proto3) /* eslint-disable */ -import type { GenEnum, GenFile, GenMessage, GenService } from "@bufbuild/protobuf/codegenv2"; -import { enumDesc, fileDesc, messageDesc, serviceDesc } from "@bufbuild/protobuf/codegenv2"; +import type { + GenEnum, + GenFile, + GenMessage, + GenService, +} from "@bufbuild/protobuf/codegenv2"; +import { + enumDesc, + fileDesc, + messageDesc, + serviceDesc, +} from "@bufbuild/protobuf/codegenv2"; import type { Message } from "@bufbuild/protobuf"; /** * Describes the file event/v1/event.proto. */ -export const file_event_v1_event: GenFile = /*@__PURE__*/ - fileDesc("ChRldmVudC92MS9ldmVudC5wcm90bxIIZXZlbnQudjEidwoUUmVnaXN0ZXJFdmVudFJlcXVlc3QSIQoEdHlwZRgBIAEoDjITLmV2ZW50LnYxLkV2ZW50VHlwZRIOCgZ1c2VySWQYAiABKAkSJAoHc2RrQ2FsbBgDIAEoCzIRLmV2ZW50LnYxLlNES0NhbGxIAEIGCgRkYXRhIl8KB1NES0NhbGwSKgoLc2RrQ2FsbFR5cGUYASABKA4yFS5ldmVudC52MS5TREtDYWxsVHlwZRIQCgZhbW91bnQYAiABKAJIABINCgN0YWcYAyABKAlIAEIHCgVkZWJpdCInChVSZWdpc3RlckV2ZW50UmVzcG9uc2USDgoGcmFuZG9tGAEgASgJIn8KElN0cmVhbUV2ZW50UmVxdWVzdBIhCgR0eXBlGAEgASgOMhMuZXZlbnQudjEuRXZlbnRUeXBlEg4KBnVzZXJJZBgCIAEoCRIuCgxhaVRva2VuVXNhZ2UYBCABKAsyFi5ldmVudC52MS5BSVRva2VuVXNhZ2VIAEIGCgRkYXRhIr0BCgxBSVRva2VuVXNhZ2USDQoFbW9kZWwYASABKAkSEwoLaW5wdXRUb2tlbnMYAiABKAUSFAoMb3V0cHV0VG9rZW5zGAMgASgFEhUKC2lucHV0QW1vdW50GAQgASgCSAASEgoIaW5wdXRUYWcYBSABKAlIABIWCgxvdXRwdXRBbW91bnQYBiABKAJIARITCglvdXRwdXRUYWcYByABKAlIAUIMCgppbnB1dERlYml0Qg0KC291dHB1dERlYml0Ij8KE1N0cmVhbUV2ZW50UmVzcG9uc2USFwoPZXZlbnRzUHJvY2Vzc2VkGAEgASgFEg8KB21lc3NhZ2UYAiABKAkqSQoJRXZlbnRUeXBlEhoKFkVWRU5UX1RZUEVfVU5TUEVDSUZJRUQQABIMCghTREtfQ0FMTBABEhIKDkFJX1RPS0VOX1VTQUdFEAIqSAoLU0RLQ2FsbFR5cGUSGwoXU0RLQ2FsbFR5cGVfVU5TUEVDSUZJRUQQABIHCgNSQVcQARITCg9NSURETEVXQVJFX0NBTEwQAjKzAQoMRXZlbnRTZXJ2aWNlElIKDVJlZ2lzdGVyRXZlbnQSHi5ldmVudC52MS5SZWdpc3RlckV2ZW50UmVxdWVzdBofLmV2ZW50LnYxLlJlZ2lzdGVyRXZlbnRSZXNwb25zZSIAEk8KDFN0cmVhbUV2ZW50cxIcLmV2ZW50LnYxLlN0cmVhbUV2ZW50UmVxdWVzdBodLmV2ZW50LnYxLlN0cmVhbUV2ZW50UmVzcG9uc2UiACgBYgZwcm90bzM"); +export const file_event_v1_event: GenFile = + /*@__PURE__*/ + fileDesc( + "ChRldmVudC92MS9ldmVudC5wcm90bxIIZXZlbnQudjEidwoUUmVnaXN0ZXJFdmVudFJlcXVlc3QSIQoEdHlwZRgBIAEoDjITLmV2ZW50LnYxLkV2ZW50VHlwZRIOCgZ1c2VySWQYAiABKAkSJAoHc2RrQ2FsbBgDIAEoCzIRLmV2ZW50LnYxLlNES0NhbGxIAEIGCgRkYXRhIl8KB1NES0NhbGwSKgoLc2RrQ2FsbFR5cGUYASABKA4yFS5ldmVudC52MS5TREtDYWxsVHlwZRIQCgZhbW91bnQYAiABKAJIABINCgN0YWcYAyABKAlIAEIHCgVkZWJpdCInChVSZWdpc3RlckV2ZW50UmVzcG9uc2USDgoGcmFuZG9tGAEgASgJIn8KElN0cmVhbUV2ZW50UmVxdWVzdBIhCgR0eXBlGAEgASgOMhMuZXZlbnQudjEuRXZlbnRUeXBlEg4KBnVzZXJJZBgCIAEoCRIuCgxhaVRva2VuVXNhZ2UYBCABKAsyFi5ldmVudC52MS5BSVRva2VuVXNhZ2VIAEIGCgRkYXRhIr0BCgxBSVRva2VuVXNhZ2USDQoFbW9kZWwYASABKAkSEwoLaW5wdXRUb2tlbnMYAiABKAUSFAoMb3V0cHV0VG9rZW5zGAMgASgFEhUKC2lucHV0QW1vdW50GAQgASgCSAASEgoIaW5wdXRUYWcYBSABKAlIABIWCgxvdXRwdXRBbW91bnQYBiABKAJIARITCglvdXRwdXRUYWcYByABKAlIAUIMCgppbnB1dERlYml0Qg0KC291dHB1dERlYml0Ij8KE1N0cmVhbUV2ZW50UmVzcG9uc2USFwoPZXZlbnRzUHJvY2Vzc2VkGAEgASgFEg8KB21lc3NhZ2UYAiABKAkqSQoJRXZlbnRUeXBlEhoKFkVWRU5UX1RZUEVfVU5TUEVDSUZJRUQQABIMCghTREtfQ0FMTBABEhIKDkFJX1RPS0VOX1VTQUdFEAIqSAoLU0RLQ2FsbFR5cGUSGwoXU0RLQ2FsbFR5cGVfVU5TUEVDSUZJRUQQABIHCgNSQVcQARITCg9NSURETEVXQVJFX0NBTEwQAjKzAQoMRXZlbnRTZXJ2aWNlElIKDVJlZ2lzdGVyRXZlbnQSHi5ldmVudC52MS5SZWdpc3RlckV2ZW50UmVxdWVzdBofLmV2ZW50LnYxLlJlZ2lzdGVyRXZlbnRSZXNwb25zZSIAEk8KDFN0cmVhbUV2ZW50cxIcLmV2ZW50LnYxLlN0cmVhbUV2ZW50UmVxdWVzdBodLmV2ZW50LnYxLlN0cmVhbUV2ZW50UmVzcG9uc2UiACgBYgZwcm90bzM", + ); /** * @generated from message event.v1.RegisterEventRequest @@ -29,20 +42,23 @@ export type RegisterEventRequest = Message<"event.v1.RegisterEventRequest"> & { /** * @generated from oneof event.v1.RegisterEventRequest.data */ - data: { - /** - * @generated from field: event.v1.SDKCall sdkCall = 3; - */ - value: SDKCall; - case: "sdkCall"; - } | { case: undefined; value?: undefined }; + data: + | { + /** + * @generated from field: event.v1.SDKCall sdkCall = 3; + */ + value: SDKCall; + case: "sdkCall"; + } + | { case: undefined; value?: undefined }; }; /** * Describes the message event.v1.RegisterEventRequest. * Use `create(RegisterEventRequestSchema)` to create a new message. */ -export const RegisterEventRequestSchema: GenMessage = /*@__PURE__*/ +export const RegisterEventRequestSchema: GenMessage = + /*@__PURE__*/ messageDesc(file_event_v1_event, 0); /** @@ -57,43 +73,49 @@ export type SDKCall = Message<"event.v1.SDKCall"> & { /** * @generated from oneof event.v1.SDKCall.debit */ - debit: { - /** - * @generated from field: float amount = 2; - */ - value: number; - case: "amount"; - } | { - /** - * @generated from field: string tag = 3; - */ - value: string; - case: "tag"; - } | { case: undefined; value?: undefined }; + debit: + | { + /** + * @generated from field: float amount = 2; + */ + value: number; + case: "amount"; + } + | { + /** + * @generated from field: string tag = 3; + */ + value: string; + case: "tag"; + } + | { case: undefined; value?: undefined }; }; /** * Describes the message event.v1.SDKCall. * Use `create(SDKCallSchema)` to create a new message. */ -export const SDKCallSchema: GenMessage = /*@__PURE__*/ +export const SDKCallSchema: GenMessage = + /*@__PURE__*/ messageDesc(file_event_v1_event, 1); /** * @generated from message event.v1.RegisterEventResponse */ -export type RegisterEventResponse = Message<"event.v1.RegisterEventResponse"> & { - /** - * @generated from field: string random = 1; - */ - random: string; -}; +export type RegisterEventResponse = + Message<"event.v1.RegisterEventResponse"> & { + /** + * @generated from field: string random = 1; + */ + random: string; + }; /** * Describes the message event.v1.RegisterEventResponse. * Use `create(RegisterEventResponseSchema)` to create a new message. */ -export const RegisterEventResponseSchema: GenMessage = /*@__PURE__*/ +export const RegisterEventResponseSchema: GenMessage = + /*@__PURE__*/ messageDesc(file_event_v1_event, 2); /** @@ -113,20 +135,23 @@ export type StreamEventRequest = Message<"event.v1.StreamEventRequest"> & { /** * @generated from oneof event.v1.StreamEventRequest.data */ - data: { - /** - * @generated from field: event.v1.AITokenUsage aiTokenUsage = 4; - */ - value: AITokenUsage; - case: "aiTokenUsage"; - } | { case: undefined; value?: undefined }; + data: + | { + /** + * @generated from field: event.v1.AITokenUsage aiTokenUsage = 4; + */ + value: AITokenUsage; + case: "aiTokenUsage"; + } + | { case: undefined; value?: undefined }; }; /** * Describes the message event.v1.StreamEventRequest. * Use `create(StreamEventRequestSchema)` to create a new message. */ -export const StreamEventRequestSchema: GenMessage = /*@__PURE__*/ +export const StreamEventRequestSchema: GenMessage = + /*@__PURE__*/ messageDesc(file_event_v1_event, 3); /** @@ -151,43 +176,50 @@ export type AITokenUsage = Message<"event.v1.AITokenUsage"> & { /** * @generated from oneof event.v1.AITokenUsage.inputDebit */ - inputDebit: { - /** - * @generated from field: float inputAmount = 4; - */ - value: number; - case: "inputAmount"; - } | { - /** - * @generated from field: string inputTag = 5; - */ - value: string; - case: "inputTag"; - } | { case: undefined; value?: undefined }; + inputDebit: + | { + /** + * @generated from field: float inputAmount = 4; + */ + value: number; + case: "inputAmount"; + } + | { + /** + * @generated from field: string inputTag = 5; + */ + value: string; + case: "inputTag"; + } + | { case: undefined; value?: undefined }; /** * @generated from oneof event.v1.AITokenUsage.outputDebit */ - outputDebit: { - /** - * @generated from field: float outputAmount = 6; - */ - value: number; - case: "outputAmount"; - } | { - /** - * @generated from field: string outputTag = 7; - */ - value: string; - case: "outputTag"; - } | { case: undefined; value?: undefined }; + outputDebit: + | { + /** + * @generated from field: float outputAmount = 6; + */ + value: number; + case: "outputAmount"; + } + | { + /** + * @generated from field: string outputTag = 7; + */ + value: string; + case: "outputTag"; + } + | { case: undefined; value?: undefined }; }; /** * Describes the message event.v1.AITokenUsage. * Use `create(AITokenUsageSchema)` to create a new message. */ -export const AITokenUsageSchema: GenMessage = /*@__PURE__*/ +export const AITokenUsageSchema: GenMessage = + /*@__PURE__*/ messageDesc(file_event_v1_event, 4); /** @@ -209,7 +241,8 @@ export type StreamEventResponse = Message<"event.v1.StreamEventResponse"> & { * Describes the message event.v1.StreamEventResponse. * Use `create(StreamEventResponseSchema)` to create a new message. */ -export const StreamEventResponseSchema: GenMessage = /*@__PURE__*/ +export const StreamEventResponseSchema: GenMessage = + /*@__PURE__*/ messageDesc(file_event_v1_event, 5); /** @@ -235,7 +268,8 @@ export enum EventType { /** * Describes the enum event.v1.EventType. */ -export const EventTypeSchema: GenEnum = /*@__PURE__*/ +export const EventTypeSchema: GenEnum = + /*@__PURE__*/ enumDesc(file_event_v1_event, 0); /** @@ -261,7 +295,8 @@ export enum SDKCallType { /** * Describes the enum event.v1.SDKCallType. */ -export const SDKCallTypeSchema: GenEnum = /*@__PURE__*/ +export const SDKCallTypeSchema: GenEnum = + /*@__PURE__*/ enumDesc(file_event_v1_event, 1); /** @@ -277,7 +312,7 @@ export const EventService: GenService<{ methodKind: "unary"; input: typeof RegisterEventRequestSchema; output: typeof RegisterEventResponseSchema; - }, + }; /** * StreamEvents streams events from client to server (e.g., AI token usage) * @@ -287,7 +322,5 @@ export const EventService: GenService<{ methodKind: "client_streaming"; input: typeof StreamEventRequestSchema; output: typeof StreamEventResponseSchema; - }, -}> = /*@__PURE__*/ - serviceDesc(file_event_v1_event, 0); - + }; +}> = /*@__PURE__*/ serviceDesc(file_event_v1_event, 0); diff --git a/src/gen/payment/v1/payment_connect.ts b/src/gen/payment/v1/payment_connect.ts index 48122d7..2380330 100644 --- a/src/gen/payment/v1/payment_connect.ts +++ b/src/gen/payment/v1/payment_connect.ts @@ -3,7 +3,10 @@ /* eslint-disable */ // @ts-nocheck -import { CreateCheckoutLinkRequest, CreateCheckoutLinkResponse } from "./payment_pb.js"; +import { + CreateCheckoutLinkRequest, + CreateCheckoutLinkResponse, +} from "./payment_pb.js"; import { MethodKind } from "@bufbuild/protobuf"; /** @@ -23,6 +26,5 @@ export const PaymentService = { O: CreateCheckoutLinkResponse, kind: MethodKind.Unary, }, - } + }, } as const; - diff --git a/src/gen/payment/v1/payment_pb.ts b/src/gen/payment/v1/payment_pb.ts index 25329f0..5678d02 100644 --- a/src/gen/payment/v1/payment_pb.ts +++ b/src/gen/payment/v1/payment_pb.ts @@ -2,48 +2,63 @@ // @generated from file payment/v1/payment.proto (package payment.v1, syntax proto3) /* eslint-disable */ -import type { GenFile, GenMessage, GenService } from "@bufbuild/protobuf/codegenv2"; -import { fileDesc, messageDesc, serviceDesc } from "@bufbuild/protobuf/codegenv2"; +import type { + GenFile, + GenMessage, + GenService, +} from "@bufbuild/protobuf/codegenv2"; +import { + fileDesc, + messageDesc, + serviceDesc, +} from "@bufbuild/protobuf/codegenv2"; import type { Message } from "@bufbuild/protobuf"; /** * Describes the file payment/v1/payment.proto. */ -export const file_payment_v1_payment: GenFile = /*@__PURE__*/ - fileDesc("ChhwYXltZW50L3YxL3BheW1lbnQucHJvdG8SCnBheW1lbnQudjEiKwoZQ3JlYXRlQ2hlY2tvdXRMaW5rUmVxdWVzdBIOCgZ1c2VySWQYASABKAkiMgoaQ3JlYXRlQ2hlY2tvdXRMaW5rUmVzcG9uc2USFAoMY2hlY2tvdXRMaW5rGAEgASgJMncKDlBheW1lbnRTZXJ2aWNlEmUKEkNyZWF0ZUNoZWNrb3V0TGluaxIlLnBheW1lbnQudjEuQ3JlYXRlQ2hlY2tvdXRMaW5rUmVxdWVzdBomLnBheW1lbnQudjEuQ3JlYXRlQ2hlY2tvdXRMaW5rUmVzcG9uc2UiAGIGcHJvdG8z"); +export const file_payment_v1_payment: GenFile = + /*@__PURE__*/ + fileDesc( + "ChhwYXltZW50L3YxL3BheW1lbnQucHJvdG8SCnBheW1lbnQudjEiKwoZQ3JlYXRlQ2hlY2tvdXRMaW5rUmVxdWVzdBIOCgZ1c2VySWQYASABKAkiMgoaQ3JlYXRlQ2hlY2tvdXRMaW5rUmVzcG9uc2USFAoMY2hlY2tvdXRMaW5rGAEgASgJMncKDlBheW1lbnRTZXJ2aWNlEmUKEkNyZWF0ZUNoZWNrb3V0TGluaxIlLnBheW1lbnQudjEuQ3JlYXRlQ2hlY2tvdXRMaW5rUmVxdWVzdBomLnBheW1lbnQudjEuQ3JlYXRlQ2hlY2tvdXRMaW5rUmVzcG9uc2UiAGIGcHJvdG8z", + ); /** * @generated from message payment.v1.CreateCheckoutLinkRequest */ -export type CreateCheckoutLinkRequest = Message<"payment.v1.CreateCheckoutLinkRequest"> & { - /** - * @generated from field: string userId = 1; - */ - userId: string; -}; +export type CreateCheckoutLinkRequest = + Message<"payment.v1.CreateCheckoutLinkRequest"> & { + /** + * @generated from field: string userId = 1; + */ + userId: string; + }; /** * Describes the message payment.v1.CreateCheckoutLinkRequest. * Use `create(CreateCheckoutLinkRequestSchema)` to create a new message. */ -export const CreateCheckoutLinkRequestSchema: GenMessage = /*@__PURE__*/ +export const CreateCheckoutLinkRequestSchema: GenMessage = + /*@__PURE__*/ messageDesc(file_payment_v1_payment, 0); /** * @generated from message payment.v1.CreateCheckoutLinkResponse */ -export type CreateCheckoutLinkResponse = Message<"payment.v1.CreateCheckoutLinkResponse"> & { - /** - * @generated from field: string checkoutLink = 1; - */ - checkoutLink: string; -}; +export type CreateCheckoutLinkResponse = + Message<"payment.v1.CreateCheckoutLinkResponse"> & { + /** + * @generated from field: string checkoutLink = 1; + */ + checkoutLink: string; + }; /** * Describes the message payment.v1.CreateCheckoutLinkResponse. * Use `create(CreateCheckoutLinkResponseSchema)` to create a new message. */ -export const CreateCheckoutLinkResponseSchema: GenMessage = /*@__PURE__*/ +export const CreateCheckoutLinkResponseSchema: GenMessage = + /*@__PURE__*/ messageDesc(file_payment_v1_payment, 1); /** @@ -59,7 +74,5 @@ export const PaymentService: GenService<{ methodKind: "unary"; input: typeof CreateCheckoutLinkRequestSchema; output: typeof CreateCheckoutLinkResponseSchema; - }, -}> = /*@__PURE__*/ - serviceDesc(file_payment_v1_payment, 0); - + }; +}> = /*@__PURE__*/ serviceDesc(file_payment_v1_payment, 0); diff --git a/src/routes/gRPC/events/streamEvents.ts b/src/routes/gRPC/events/streamEvents.ts index d9f790c..1e2f84f 100644 --- a/src/routes/gRPC/events/streamEvents.ts +++ b/src/routes/gRPC/events/streamEvents.ts @@ -2,7 +2,7 @@ import type { StreamEventRequest, StreamEventResponse, } from "../../../gen/event/v1/event_pb"; -import type { SqlRecord } from "../../../interface/event/Event"; + import { StreamEventResponseSchema } from "../../../gen/event/v1/event_pb"; import { create } from "@bufbuild/protobuf"; import { EventError } from "../../../errors/event"; @@ -13,8 +13,8 @@ import { extractApiKeyFromContext, validateAndParseStreamEvent, createEventInstance, + storeEvent, } from "../../../utils/eventHelpers"; -import { handleAddAiTokenUsage } from "../../../storage/adapter/postgres/handlers"; const OPERATION = "StreamEvents"; @@ -45,20 +45,11 @@ export async function streamEvents( // Create the appropriate event instance const event = createEventInstance(eventSkeleton); - const { SQL } = event.serialize(); - if (!SQL) { - throw EventError.serializationError( - "Event serialization returned null or undefined", - ); - } - if (SQL.type !== "AI_TOKEN_USAGE") { - throw EventError.unsupportedEventType(SQL.type); + if (event.type !== "AI_TOKEN_USAGE") { + throw EventError.unsupportedEventType(event.type); } - await handleAddAiTokenUsage( - [SQL], - apiKeyId, - ); + await storeEvent(event, apiKeyId); eventsProcessed += 1; logger.logOperationInfo( diff --git a/src/utils/eventHelpers.ts b/src/utils/eventHelpers.ts index 43bbe13..53c73c2 100644 --- a/src/utils/eventHelpers.ts +++ b/src/utils/eventHelpers.ts @@ -28,9 +28,7 @@ export function extractApiKeyFromContext(context: HandlerContext): string { /** * Validate and parse the incoming event request */ -export async function validateAndParseRegisterEvent( - req: RegisterEventRequest, -) { +export async function validateAndParseRegisterEvent(req: RegisterEventRequest) { try { return await registerEventSchema.parseAsync(req); } catch (error) { @@ -50,9 +48,7 @@ export async function validateAndParseRegisterEvent( } } -export async function validateAndParseStreamEvent( - req: StreamEventRequest, -) { +export async function validateAndParseStreamEvent(req: StreamEventRequest) { try { return await streamEventSchema.parseAsync(req); } catch (error) { From e8dcabcc237d9b67ae7d998ddcdd6f4dbb9e3ad5 Mon Sep 17 00:00:00 2001 From: Jayadeep Bejoy Date: Mon, 26 Jan 2026 18:05:57 +0530 Subject: [PATCH 3/3] refactor(prettier) Signed-off-by: Jayadeep Bejoy --- .../unit/http/createdCheckout.test.ts | 24 +++++----- src/__tests__/unit/interceptors/auth.test.ts | 10 ++--- .../storage/postgres/addAiTokenUsage.test.ts | 20 ++++----- .../unit/storage/postgres/addKey.test.ts | 16 +++---- .../unit/storage/postgres/addPayment.test.ts | 6 +-- .../unit/storage/postgres/addSdkCall.test.ts | 10 ++--- .../postgres/priceRequestAiTokenUsage.test.ts | 38 ++++++++-------- .../postgres/priceRequestPayment.test.ts | 14 +++--- .../postgres/priceRequestSdkCall.test.ts | 22 +++++----- src/__tests__/unit/zod/apikey.test.ts | 8 ++-- src/errors/apikey.ts | 4 +- src/errors/event.ts | 6 +-- src/errors/logger.ts | 8 ++-- src/errors/payment.ts | 14 +++--- src/errors/storage.ts | 18 ++++---- src/events/AIEvents/AITokenUsage.ts | 2 +- src/events/RawEvents/Payment.ts | 2 +- src/events/RawEvents/SDKCall.ts | 2 +- .../RequestEvents/RequestAITokenUsage.ts | 2 +- src/events/RequestEvents/RequestPayment.ts | 2 +- src/events/RequestEvents/RequestSDKCall.ts | 2 +- src/gen/auth/v1/auth_pb.ts | 2 +- src/gen/event/v1/event_pb.ts | 2 +- src/gen/payment/v1/payment_pb.ts | 2 +- src/interceptors/auth.ts | 18 ++++---- src/routes/gRPC/auth/createAPIKey.ts | 12 ++--- src/routes/gRPC/events/registerEvent.ts | 8 ++-- src/routes/gRPC/events/streamEvents.ts | 10 ++--- src/routes/gRPC/payment/createCheckoutLink.ts | 42 +++++++++--------- src/routes/http/createdCheckout.ts | 36 +++++++-------- src/server.ts | 2 +- .../postgres/handlers/addAiTokenUsage.ts | 44 +++++++++---------- .../adapter/postgres/handlers/addKey.ts | 20 ++++----- .../adapter/postgres/handlers/addPayment.ts | 28 ++++++------ .../adapter/postgres/handlers/addSdkCall.ts | 26 +++++------ .../handlers/priceRequestAiTokenUsage.ts | 28 ++++++------ .../postgres/handlers/priceRequestPayment.ts | 24 +++++----- .../postgres/handlers/priceRequestSdkCall.ts | 26 +++++------ src/storage/adapter/postgres/postgres.ts | 8 ++-- src/storage/db/postgres/schema.ts | 8 ++-- src/utils/apiKeyCache.ts | 4 +- src/utils/eventHelpers.ts | 12 ++--- src/utils/generateInitialAPIKey.ts | 10 ++--- src/zod/apikey.ts | 4 +- src/zod/event.ts | 8 ++-- 45 files changed, 307 insertions(+), 307 deletions(-) diff --git a/src/__tests__/unit/http/createdCheckout.test.ts b/src/__tests__/unit/http/createdCheckout.test.ts index c3d00a9..5875420 100644 --- a/src/__tests__/unit/http/createdCheckout.test.ts +++ b/src/__tests__/unit/http/createdCheckout.test.ts @@ -166,7 +166,7 @@ describe("handleLemonSqueezyWebhook", () => { "MISSING_WEBHOOK_SECRET", "Webhook secret not configured", undefined, - {}, + {} ); }); @@ -194,7 +194,7 @@ describe("handleLemonSqueezyWebhook", () => { "INVALID_SIGNATURE", "Invalid webhook signature", undefined, - {}, + {} ); }); @@ -225,7 +225,7 @@ describe("handleLemonSqueezyWebhook", () => { "INVALID_JSON", "Invalid JSON payload", expect.any(Error), - {}, + {} ); }); @@ -255,7 +255,7 @@ describe("handleLemonSqueezyWebhook", () => { expect((res as any).statusCode).toBe(200); expect((res as any).body).toContain("Event ignored"); expect( - storageModule.StorageAdapterFactory.getStorageAdapter, + storageModule.StorageAdapterFactory.getStorageAdapter ).not.toHaveBeenCalled(); expect(paymentConstructorCalls.length).toBe(0); }); @@ -295,7 +295,7 @@ describe("handleLemonSqueezyWebhook", () => { "MISSING_USER_ID", "Missing user_id in webhook payload", undefined, - {}, + {} ); }); @@ -336,7 +336,7 @@ describe("handleLemonSqueezyWebhook", () => { "MISSING_API_KEY_ID", "Missing apiKeyId in webhook payload", undefined, - { userId: "user-123" }, + { userId: "user-123" } ); }); @@ -346,7 +346,7 @@ describe("handleLemonSqueezyWebhook", () => { const adapterAddMock = vi.fn().mockResolvedValue(undefined); vi.mocked( - storageModule.StorageAdapterFactory.getStorageAdapter, + storageModule.StorageAdapterFactory.getStorageAdapter ).mockResolvedValue({ add: adapterAddMock, } as any); @@ -394,10 +394,10 @@ describe("handleLemonSqueezyWebhook", () => { }); expect( - storageModule.StorageAdapterFactory.getStorageAdapter, + storageModule.StorageAdapterFactory.getStorageAdapter ).toHaveBeenCalledTimes(1); const adapterCall = vi.mocked( - storageModule.StorageAdapterFactory.getStorageAdapter, + storageModule.StorageAdapterFactory.getStorageAdapter ).mock.calls[0]; expect(adapterCall[1]).toBe("api-key-456"); @@ -414,7 +414,7 @@ describe("handleLemonSqueezyWebhook", () => { const dbError = new Error("DB error"); const adapterAddMock = vi.fn().mockRejectedValue(dbError); vi.mocked( - storageModule.StorageAdapterFactory.getStorageAdapter, + storageModule.StorageAdapterFactory.getStorageAdapter ).mockResolvedValue({ add: adapterAddMock, } as any); @@ -464,7 +464,7 @@ describe("handleLemonSqueezyWebhook", () => { "DATABASE_ERROR", "Database error while storing payment", dbError, - { userId: "user-123", apiKeyId: "api-key-456" }, + { userId: "user-123", apiKeyId: "api-key-456" } ); }); @@ -492,7 +492,7 @@ describe("handleLemonSqueezyWebhook", () => { "UNEXPECTED_ERROR", "Unexpected error in webhook handler", expect.any(Error), - {}, + {} ); }); }); diff --git a/src/__tests__/unit/interceptors/auth.test.ts b/src/__tests__/unit/interceptors/auth.test.ts index dd7b49f..d012792 100644 --- a/src/__tests__/unit/interceptors/auth.test.ts +++ b/src/__tests__/unit/interceptors/auth.test.ts @@ -59,24 +59,24 @@ describe("authInterceptor", () => { // Empty Authorization should be rejected await expect(interceptor(next)(makeReq() as any)).rejects.toThrow( - "Missing Authorization header", + "Missing Authorization header" ); // Authorization that does not start with Bearer should be rejected await expect( - interceptor(next)(makeReq("Token abcdef") as any), + interceptor(next)(makeReq("Token abcdef") as any) ).rejects.toThrow( - 'Authorization header must be in format "Bearer "', + 'Authorization header must be in format "Bearer "' ); // Authorization with invalid API key format (not starting with scrn_) should be rejected await expect( - interceptor(next)(makeReq("Bearer " + "a".repeat(37)) as any), + interceptor(next)(makeReq("Bearer " + "a".repeat(37)) as any) ).rejects.toThrow("Invalid API key: Invalid API key format"); // Authorization with invalid API key format (wrong length) should be rejected await expect( - interceptor(next)(makeReq("Bearer scrn_short") as any), + interceptor(next)(makeReq("Bearer scrn_short") as any) ).rejects.toThrow("Invalid API key: Invalid API key format"); }); diff --git a/src/__tests__/unit/storage/postgres/addAiTokenUsage.test.ts b/src/__tests__/unit/storage/postgres/addAiTokenUsage.test.ts index 67309b6..9d8f20e 100644 --- a/src/__tests__/unit/storage/postgres/addAiTokenUsage.test.ts +++ b/src/__tests__/unit/storage/postgres/addAiTokenUsage.test.ts @@ -148,7 +148,7 @@ describe("handleAddAiTokenUsage - Aggregation and Batch Insert", () => { // Find GPT-4 aggregated record const gpt4Record = aiTokenUsageInsertCall[0].find( - (r: any) => r.model === "gpt-4", + (r: any) => r.model === "gpt-4" ); expect(gpt4Record).toEqual({ id: expect.any(String), @@ -161,7 +161,7 @@ describe("handleAddAiTokenUsage - Aggregation and Batch Insert", () => { // Find Claude aggregated record const claudeRecord = aiTokenUsageInsertCall[0].find( - (r: any) => r.model === "claude-3-opus", + (r: any) => r.model === "claude-3-opus" ); expect(claudeRecord).toEqual({ id: expect.any(String), @@ -313,12 +313,12 @@ describe("handleAddAiTokenUsage - Aggregation and Batch Insert", () => { // Verify aggregation: should have 2 gpt-4 records and 1 claude record const gpt4Records = aiTokenUsageInsertCall[0].filter( - (r: any) => r.model === "gpt-4", + (r: any) => r.model === "gpt-4" ); expect(gpt4Records).toHaveLength(2); const claudeRecords = aiTokenUsageInsertCall[0].filter( - (r: any) => r.model === "claude-3-sonnet", + (r: any) => r.model === "claude-3-sonnet" ); expect(claudeRecords).toHaveLength(1); @@ -419,7 +419,7 @@ describe("handleAddAiTokenUsage - Aggregation and Batch Insert", () => { { id: "user-1" }, { id: "user-2" }, { id: "user-3" }, - ]), + ]) ); }); @@ -491,7 +491,7 @@ describe("handleAddAiTokenUsage - Aggregation and Batch Insert", () => { mockTransaction.returning.mockResolvedValueOnce([]); await expect( - handleAddAiTokenUsage(events, "api-key-123"), + handleAddAiTokenUsage(events, "api-key-123") ).rejects.toThrow("Event insert returned no IDs"); }); @@ -527,7 +527,7 @@ describe("handleAddAiTokenUsage - Aggregation and Batch Insert", () => { mockTransaction.returning.mockResolvedValueOnce([{ id: "event-1" }]); await expect( - handleAddAiTokenUsage(events, "api-key-123"), + handleAddAiTokenUsage(events, "api-key-123") ).rejects.toThrow("Expected 2 event IDs but got 1"); }); }); @@ -552,7 +552,7 @@ describe("handleAddAiTokenUsage - Aggregation and Batch Insert", () => { mockDb.transaction.mockRejectedValueOnce(new Error("Transaction failed")); await expect( - handleAddAiTokenUsage(events, "api-key-123"), + handleAddAiTokenUsage(events, "api-key-123") ).rejects.toThrow("Transaction failed"); }); @@ -573,11 +573,11 @@ describe("handleAddAiTokenUsage - Aggregation and Batch Insert", () => { ]; mockTransaction.returning.mockRejectedValueOnce( - new Error("Insert failed"), + new Error("Insert failed") ); await expect( - handleAddAiTokenUsage(events, "api-key-123"), + handleAddAiTokenUsage(events, "api-key-123") ).rejects.toThrow(); }); }); diff --git a/src/__tests__/unit/storage/postgres/addKey.test.ts b/src/__tests__/unit/storage/postgres/addKey.test.ts index 36eb400..713a465 100644 --- a/src/__tests__/unit/storage/postgres/addKey.test.ts +++ b/src/__tests__/unit/storage/postgres/addKey.test.ts @@ -92,7 +92,7 @@ describe("PostgresAdapter - addKey handler", () => { const adapter = new PostgresAdapter(invalidEvent as any); const serialized = invalidEvent.serialize() as any; await expect(adapter.add(serialized)).rejects.toThrow( - "Missing data field", + "Missing data field" ); }); @@ -119,7 +119,7 @@ describe("PostgresAdapter - addKey handler", () => { const adapter = new PostgresAdapter(invalidEvent as any); const serialized = invalidEvent.serialize() as any; await expect(adapter.add(serialized)).rejects.toThrow( - "Invalid or missing 'name'", + "Invalid or missing 'name'" ); }); @@ -146,7 +146,7 @@ describe("PostgresAdapter - addKey handler", () => { const adapter = new PostgresAdapter(invalidEvent as any); const serialized = invalidEvent.serialize() as any; await expect(adapter.add(serialized)).rejects.toThrow( - "Invalid or missing 'key'", + "Invalid or missing 'key'" ); }); @@ -175,7 +175,7 @@ describe("PostgresAdapter - addKey handler", () => { const adapter = new PostgresAdapter(invalidEvent as any); const serialized = invalidEvent.serialize() as any; await expect(adapter.add(serialized)).rejects.toThrow( - "API key cannot be empty", + "API key cannot be empty" ); }); @@ -202,7 +202,7 @@ describe("PostgresAdapter - addKey handler", () => { const adapter = new PostgresAdapter(invalidEvent as any); const serialized = invalidEvent.serialize() as any; await expect(adapter.add(serialized)).rejects.toThrow( - "Timestamp is undefined or empty", + "Timestamp is undefined or empty" ); }); }); @@ -216,7 +216,7 @@ describe("PostgresAdapter - addKey handler", () => { }); mockTransaction.returning.mockRejectedValueOnce( - new Error("Database connection error"), + new Error("Database connection error") ); const adapter = new PostgresAdapter(addKeyEvent); @@ -236,7 +236,7 @@ describe("PostgresAdapter - addKey handler", () => { const adapter = new PostgresAdapter(addKeyEvent); const serialized = addKeyEvent.serialize(); await expect(adapter.add(serialized)).rejects.toThrow( - "API key insert returned no record", + "API key insert returned no record" ); }); @@ -252,7 +252,7 @@ describe("PostgresAdapter - addKey handler", () => { const adapter = new PostgresAdapter(addKeyEvent); const serialized = addKeyEvent.serialize(); await expect(adapter.add(serialized)).rejects.toThrow( - "API key insert returned object without id field", + "API key insert returned object without id field" ); }); }); diff --git a/src/__tests__/unit/storage/postgres/addPayment.test.ts b/src/__tests__/unit/storage/postgres/addPayment.test.ts index 7ab9511..a44056e 100644 --- a/src/__tests__/unit/storage/postgres/addPayment.test.ts +++ b/src/__tests__/unit/storage/postgres/addPayment.test.ts @@ -163,7 +163,7 @@ describe("PostgresAdapter - addPayment handler", () => { const adapter = new PostgresAdapter(invalidEvent as any); const serialized = invalidEvent.serialize() as any; await expect(adapter.add(serialized)).rejects.toThrow( - "Timestamp is undefined or empty", + "Timestamp is undefined or empty" ); }); }); @@ -176,7 +176,7 @@ describe("PostgresAdapter - addPayment handler", () => { mockTransaction.returning.mockResolvedValueOnce([]); mockTransaction.returning.mockRejectedValueOnce( - new Error("Event insert failed"), + new Error("Event insert failed") ); const adapter = new PostgresAdapter(paymentEvent); @@ -195,7 +195,7 @@ describe("PostgresAdapter - addPayment handler", () => { const adapter = new PostgresAdapter(paymentEvent); const serialized = paymentEvent.serialize(); await expect(adapter.add(serialized)).rejects.toThrow( - "Event insert returned no ID", + "Event insert returned no ID" ); }); }); diff --git a/src/__tests__/unit/storage/postgres/addSdkCall.test.ts b/src/__tests__/unit/storage/postgres/addSdkCall.test.ts index 387b634..705ce02 100644 --- a/src/__tests__/unit/storage/postgres/addSdkCall.test.ts +++ b/src/__tests__/unit/storage/postgres/addSdkCall.test.ts @@ -98,10 +98,10 @@ describe("PostgresAdapter - addSdkCall handler", () => { await adapter.add(serialized); const insertedValues = mockTransaction.values.mock.calls.map( - (c: any) => c[0], + (c: any) => c[0] ); const sdkCallRecord = insertedValues.find( - (v: any) => v && v.debitAmount === 500, + (v: any) => v && v.debitAmount === 500 ); expect(sdkCallRecord).toBeDefined(); @@ -117,7 +117,7 @@ describe("PostgresAdapter - addSdkCall handler", () => { }); mockTransaction.returning.mockRejectedValueOnce( - new Error("Event insert failed"), + new Error("Event insert failed") ); const adapter = new PostgresAdapter(sdkCallEvent, "api-key"); @@ -136,7 +136,7 @@ describe("PostgresAdapter - addSdkCall handler", () => { const adapter = new PostgresAdapter(sdkCallEvent, "api-key"); const serialized = sdkCallEvent.serialize(); await expect(adapter.add(serialized)).rejects.toThrow( - "Event insert returned no ID", + "Event insert returned no ID" ); }); }); @@ -163,7 +163,7 @@ describe("PostgresAdapter - addSdkCall handler", () => { const adapter = new PostgresAdapter(invalidEvent as any, "api-key"); const serialized = invalidEvent.serialize() as any; await expect(adapter.add(serialized)).rejects.toThrow( - "Timestamp is undefined or empty", + "Timestamp is undefined or empty" ); }); }); diff --git a/src/__tests__/unit/storage/postgres/priceRequestAiTokenUsage.test.ts b/src/__tests__/unit/storage/postgres/priceRequestAiTokenUsage.test.ts index be7de50..cbd0216 100644 --- a/src/__tests__/unit/storage/postgres/priceRequestAiTokenUsage.test.ts +++ b/src/__tests__/unit/storage/postgres/priceRequestAiTokenUsage.test.ts @@ -27,7 +27,7 @@ describe("PostgresAdapter - priceRequestAiTokenUsage handler", () => { it("calculates price for user with AI token usage events", async () => { const requestEvent = new RequestAITokenUsage( "550e8400-e29b-41d4-a716-446655440000", - null, + null ); mockDb.groupBy.mockResolvedValueOnce([{ price: "2500" }]); @@ -42,7 +42,7 @@ describe("PostgresAdapter - priceRequestAiTokenUsage handler", () => { it("returns zero for user with no AI token usage events", async () => { const requestEvent = new RequestAITokenUsage( "550e8400-e29b-41d4-a716-446655440000", - null, + null ); mockDb.groupBy.mockResolvedValueOnce([]); @@ -57,7 +57,7 @@ describe("PostgresAdapter - priceRequestAiTokenUsage handler", () => { it("returns zero when price is null", async () => { const requestEvent = new RequestAITokenUsage( "550e8400-e29b-41d4-a716-446655440000", - null, + null ); mockDb.groupBy.mockResolvedValueOnce([{ price: null }]); @@ -72,7 +72,7 @@ describe("PostgresAdapter - priceRequestAiTokenUsage handler", () => { it("returns zero when price is undefined", async () => { const requestEvent = new RequestAITokenUsage( "550e8400-e29b-41d4-a716-446655440000", - null, + null ); mockDb.groupBy.mockResolvedValueOnce([{ price: undefined }]); @@ -87,7 +87,7 @@ describe("PostgresAdapter - priceRequestAiTokenUsage handler", () => { it("parses string price to integer", async () => { const requestEvent = new RequestAITokenUsage( "550e8400-e29b-41d4-a716-446655440000", - null, + null ); mockDb.groupBy.mockResolvedValueOnce([{ price: "54321" }]); @@ -103,7 +103,7 @@ describe("PostgresAdapter - priceRequestAiTokenUsage handler", () => { it("handles large price values", async () => { const requestEvent = new RequestAITokenUsage( "550e8400-e29b-41d4-a716-446655440000", - null, + null ); mockDb.groupBy.mockResolvedValueOnce([{ price: "999999999" }]); @@ -156,7 +156,7 @@ describe("PostgresAdapter - priceRequestAiTokenUsage handler", () => { const adapter = new PostgresAdapter(invalidEvent as any); const serialized = invalidEvent.serialize() as any; await expect(adapter.price(serialized)).rejects.toThrow( - "Invalid userId format", + "Invalid userId format" ); }); @@ -179,7 +179,7 @@ describe("PostgresAdapter - priceRequestAiTokenUsage handler", () => { const adapter = new PostgresAdapter(invalidEvent as any); const serialized = invalidEvent.serialize() as any; await expect(adapter.price(serialized)).rejects.toThrow( - "Invalid userId format", + "Invalid userId format" ); }); }); @@ -188,11 +188,11 @@ describe("PostgresAdapter - priceRequestAiTokenUsage handler", () => { it("handles database query failure", async () => { const requestEvent = new RequestAITokenUsage( "550e8400-e29b-41d4-a716-446655440000", - null, + null ); mockDb.groupBy.mockRejectedValueOnce( - new Error("Database connection error"), + new Error("Database connection error") ); const adapter = new PostgresAdapter(requestEvent); @@ -203,7 +203,7 @@ describe("PostgresAdapter - priceRequestAiTokenUsage handler", () => { it("handles null query result", async () => { const requestEvent = new RequestAITokenUsage( "550e8400-e29b-41d4-a716-446655440000", - null, + null ); mockDb.groupBy.mockResolvedValueOnce(null); @@ -211,14 +211,14 @@ describe("PostgresAdapter - priceRequestAiTokenUsage handler", () => { const adapter = new PostgresAdapter(requestEvent); const serialized = requestEvent.serialize(); await expect(adapter.price(serialized)).rejects.toThrow( - "Price query returned null", + "Price query returned null" ); }); it("handles non-array query result", async () => { const requestEvent = new RequestAITokenUsage( "550e8400-e29b-41d4-a716-446655440000", - null, + null ); mockDb.groupBy.mockResolvedValueOnce({ price: "2500" }); @@ -226,14 +226,14 @@ describe("PostgresAdapter - priceRequestAiTokenUsage handler", () => { const adapter = new PostgresAdapter(requestEvent); const serialized = requestEvent.serialize(); await expect(adapter.price(serialized)).rejects.toThrow( - "Query result is not an array", + "Query result is not an array" ); }); it("handles unparseable price value", async () => { const requestEvent = new RequestAITokenUsage( "550e8400-e29b-41d4-a716-446655440000", - null, + null ); mockDb.groupBy.mockResolvedValueOnce([{ price: "not-a-number" }]); @@ -248,7 +248,7 @@ describe("PostgresAdapter - priceRequestAiTokenUsage handler", () => { it("handles empty result array", async () => { const requestEvent = new RequestAITokenUsage( "550e8400-e29b-41d4-a716-446655440000", - null, + null ); mockDb.groupBy.mockResolvedValueOnce([]); @@ -263,7 +263,7 @@ describe("PostgresAdapter - priceRequestAiTokenUsage handler", () => { it("handles result array with undefined first element", async () => { const requestEvent = new RequestAITokenUsage( "550e8400-e29b-41d4-a716-446655440000", - null, + null ); mockDb.groupBy.mockResolvedValueOnce([undefined]); @@ -278,7 +278,7 @@ describe("PostgresAdapter - priceRequestAiTokenUsage handler", () => { it("handles zero price", async () => { const requestEvent = new RequestAITokenUsage( "550e8400-e29b-41d4-a716-446655440000", - null, + null ); mockDb.groupBy.mockResolvedValueOnce([{ price: "0" }]); @@ -293,7 +293,7 @@ describe("PostgresAdapter - priceRequestAiTokenUsage handler", () => { it("handles negative price (logs warning but returns value)", async () => { const requestEvent = new RequestAITokenUsage( "550e8400-e29b-41d4-a716-446655440000", - null, + null ); mockDb.groupBy.mockResolvedValueOnce([{ price: "-100" }]); diff --git a/src/__tests__/unit/storage/postgres/priceRequestPayment.test.ts b/src/__tests__/unit/storage/postgres/priceRequestPayment.test.ts index 35f3657..e427034 100644 --- a/src/__tests__/unit/storage/postgres/priceRequestPayment.test.ts +++ b/src/__tests__/unit/storage/postgres/priceRequestPayment.test.ts @@ -25,7 +25,7 @@ describe("PostgresAdapter - priceRequestPayment handler", () => { return Promise.resolve(mockAiAdapter); } return Promise.resolve(null); - }, + } ); }); @@ -126,7 +126,7 @@ describe("PostgresAdapter - priceRequestPayment handler", () => { } as any; await expect(handlePriceRequestPayment(eventData)).rejects.toThrow( - "Missing userId", + "Missing userId" ); }); @@ -139,7 +139,7 @@ describe("PostgresAdapter - priceRequestPayment handler", () => { }; await expect(handlePriceRequestPayment(eventData)).rejects.toThrow( - "Missing userId", + "Missing userId" ); }); }); @@ -159,7 +159,7 @@ describe("PostgresAdapter - priceRequestPayment handler", () => { return Promise.resolve(null as any); } return Promise.resolve(mockAiAdapter); - }, + } ); await expect(handlePriceRequestPayment(eventData)).rejects.toThrow(); @@ -184,7 +184,7 @@ describe("PostgresAdapter - priceRequestPayment handler", () => { return Promise.resolve(null as any); } return Promise.resolve(null); - }, + } ); await expect(handlePriceRequestPayment(eventData)).rejects.toThrow(); @@ -204,7 +204,7 @@ describe("PostgresAdapter - priceRequestPayment handler", () => { return Promise.resolve(undefined as any); } return Promise.resolve(mockAiAdapter); - }, + } ); await expect(handlePriceRequestPayment(eventData)).rejects.toThrow(); @@ -304,7 +304,7 @@ describe("PostgresAdapter - priceRequestPayment handler", () => { }; mockSdkAdapter.price.mockRejectedValueOnce( - new Error("Database connection failed"), + new Error("Database connection failed") ); await expect(handlePriceRequestPayment(eventData)).rejects.toThrow(); diff --git a/src/__tests__/unit/storage/postgres/priceRequestSdkCall.test.ts b/src/__tests__/unit/storage/postgres/priceRequestSdkCall.test.ts index 38bfcef..380a4a4 100644 --- a/src/__tests__/unit/storage/postgres/priceRequestSdkCall.test.ts +++ b/src/__tests__/unit/storage/postgres/priceRequestSdkCall.test.ts @@ -27,7 +27,7 @@ describe("PostgresAdapter - priceRequestSdkCall handler", () => { it("calculates price for user with SDK call events", async () => { const requestEvent = new RequestSDKCall( "550e8400-e29b-41d4-a716-446655440000", - null, + null ); mockDb.groupBy.mockResolvedValueOnce([{ price: "1500" }]); @@ -42,7 +42,7 @@ describe("PostgresAdapter - priceRequestSdkCall handler", () => { it("returns zero for user with no SDK call events", async () => { const requestEvent = new RequestSDKCall( "550e8400-e29b-41d4-a716-446655440000", - null, + null ); mockDb.groupBy.mockResolvedValueOnce([]); @@ -57,7 +57,7 @@ describe("PostgresAdapter - priceRequestSdkCall handler", () => { it("returns zero when price is null", async () => { const requestEvent = new RequestSDKCall( "550e8400-e29b-41d4-a716-446655440000", - null, + null ); mockDb.groupBy.mockResolvedValueOnce([{ price: null }]); @@ -72,7 +72,7 @@ describe("PostgresAdapter - priceRequestSdkCall handler", () => { it("parses string price to integer", async () => { const requestEvent = new RequestSDKCall( "550e8400-e29b-41d4-a716-446655440000", - null, + null ); mockDb.groupBy.mockResolvedValueOnce([{ price: "12345" }]); @@ -126,7 +126,7 @@ describe("PostgresAdapter - priceRequestSdkCall handler", () => { const adapter = new PostgresAdapter(invalidEvent as any); const serialized = invalidEvent.serialize() as any; await expect(adapter.price(serialized)).rejects.toThrow( - "Invalid userId format", + "Invalid userId format" ); }); }); @@ -135,11 +135,11 @@ describe("PostgresAdapter - priceRequestSdkCall handler", () => { it("handles database query failure", async () => { const requestEvent = new RequestSDKCall( "550e8400-e29b-41d4-a716-446655440000", - null, + null ); mockDb.groupBy.mockRejectedValueOnce( - new Error("Database connection error"), + new Error("Database connection error") ); const adapter = new PostgresAdapter(requestEvent); @@ -150,7 +150,7 @@ describe("PostgresAdapter - priceRequestSdkCall handler", () => { it("handles null query result", async () => { const requestEvent = new RequestSDKCall( "550e8400-e29b-41d4-a716-446655440000", - null, + null ); mockDb.groupBy.mockResolvedValueOnce(null); @@ -158,14 +158,14 @@ describe("PostgresAdapter - priceRequestSdkCall handler", () => { const adapter = new PostgresAdapter(requestEvent); const serialized = requestEvent.serialize(); await expect(adapter.price(serialized)).rejects.toThrow( - "Price query returned null", + "Price query returned null" ); }); it("handles non-array query result", async () => { const requestEvent = new RequestSDKCall( "550e8400-e29b-41d4-a716-446655440000", - null, + null ); mockDb.groupBy.mockResolvedValueOnce({ price: "1500" }); @@ -173,7 +173,7 @@ describe("PostgresAdapter - priceRequestSdkCall handler", () => { const adapter = new PostgresAdapter(requestEvent); const serialized = requestEvent.serialize(); await expect(adapter.price(serialized)).rejects.toThrow( - "Query result is not an array", + "Query result is not an array" ); }); }); diff --git a/src/__tests__/unit/zod/apikey.test.ts b/src/__tests__/unit/zod/apikey.test.ts index 938075e..74c9f7c 100644 --- a/src/__tests__/unit/zod/apikey.test.ts +++ b/src/__tests__/unit/zod/apikey.test.ts @@ -53,7 +53,7 @@ describe("createAPIKeySchema", () => { expect(result.success).toBe(false); if (!result.success) { expect(result.error.issues[0]?.message).toBe( - "API key name must be less than 255 characters", + "API key name must be less than 255 characters" ); } }); @@ -68,7 +68,7 @@ describe("createAPIKeySchema", () => { expect(result.success).toBe(false); if (!result.success) { expect(result.error.issues[0]?.message).toBe( - "Expiration time must be an integer", + "Expiration time must be an integer" ); } }); @@ -83,7 +83,7 @@ describe("createAPIKeySchema", () => { expect(result.success).toBe(false); if (!result.success) { expect(result.error.issues[0]?.message).toBe( - "Expiration time must be at least 60 seconds", + "Expiration time must be at least 60 seconds" ); } }); @@ -98,7 +98,7 @@ describe("createAPIKeySchema", () => { expect(result.success).toBe(false); if (!result.success) { expect(result.error.issues[0]?.message).toBe( - "Expiration time cannot exceed 1 year", + "Expiration time cannot exceed 1 year" ); } }); diff --git a/src/errors/apikey.ts b/src/errors/apikey.ts index 8834afe..a2c3092 100644 --- a/src/errors/apikey.ts +++ b/src/errors/apikey.ts @@ -32,7 +32,7 @@ export class APIKeyError extends ConnectError { static invalidExpiration( details?: string, - originalError?: Error, + originalError?: Error ): APIKeyError { return new APIKeyError({ type: APIKeyErrorType.INVALID_EXPIRATION, @@ -77,7 +77,7 @@ export class APIKeyError extends ConnectError { static revocationFailed( details?: string, - originalError?: Error, + originalError?: Error ): APIKeyError { return new APIKeyError({ type: APIKeyErrorType.REVOCATION_FAILED, diff --git a/src/errors/event.ts b/src/errors/event.ts index 38ec0a8..9c23c7e 100644 --- a/src/errors/event.ts +++ b/src/errors/event.ts @@ -45,7 +45,7 @@ export class EventError extends ConnectError { static unsupportedEventType( eventType: string, - originalError?: Error, + originalError?: Error ): EventError { return new EventError({ type: EventErrorType.UNSUPPORTED_EVENT_TYPE, @@ -66,7 +66,7 @@ export class EventError extends ConnectError { static serializationError( details?: string, - originalError?: Error, + originalError?: Error ): EventError { return new EventError({ type: EventErrorType.SERIALIZATION_ERROR, @@ -99,7 +99,7 @@ export class EventError extends ConnectError { static invalidDataFormat( field: string, expectedFormat: string, - originalError?: Error, + originalError?: Error ): EventError { return new EventError({ type: EventErrorType.INVALID_DATA_FORMAT, diff --git a/src/errors/logger.ts b/src/errors/logger.ts index 9ff1750..f4a0892 100644 --- a/src/errors/logger.ts +++ b/src/errors/logger.ts @@ -63,7 +63,7 @@ class ErrorLogger { errorType: string, message: string, originalError?: Error, - context?: LogContext, + context?: LogContext ): void { if (!this.shouldLog(errorType, message)) { return; @@ -126,7 +126,7 @@ class ErrorLogger { errorType: string, message: string, originalError?: Error, - extra?: Omit, + extra?: Omit ): void { this.logError(errorType, message, originalError, { operation, @@ -139,7 +139,7 @@ class ErrorLogger { operation: string, stage: string, message: string, - extra?: Omit, + extra?: Omit ): void { this.logInfo(message, { operation, stage, ...extra }); } @@ -148,7 +148,7 @@ class ErrorLogger { operation: string, stage: string, message: string, - extra?: Omit, + extra?: Omit ): void { this.logDebug(message, { operation, stage, ...extra }); } diff --git a/src/errors/payment.ts b/src/errors/payment.ts index c3a652d..acf1e20 100644 --- a/src/errors/payment.ts +++ b/src/errors/payment.ts @@ -46,7 +46,7 @@ export class PaymentError extends ConnectError { static checkoutCreationFailed( details?: string, - originalError?: Error, + originalError?: Error ): PaymentError { return new PaymentError({ type: PaymentErrorType.CHECKOUT_CREATION_FAILED, @@ -61,7 +61,7 @@ export class PaymentError extends ConnectError { static validationFailed( details: string, - originalError?: Error, + originalError?: Error ): PaymentError { return new PaymentError({ type: PaymentErrorType.VALIDATION_FAILED, @@ -73,7 +73,7 @@ export class PaymentError extends ConnectError { static lemonSqueezyApiError( details?: string, - originalError?: Error, + originalError?: Error ): PaymentError { return new PaymentError({ type: PaymentErrorType.LEMON_SQUEEZY_API_ERROR, @@ -114,7 +114,7 @@ export class PaymentError extends ConnectError { static invalidCheckoutResponse( details?: string, - originalError?: Error, + originalError?: Error ): PaymentError { return new PaymentError({ type: PaymentErrorType.INVALID_CHECKOUT_RESPONSE, @@ -128,7 +128,7 @@ export class PaymentError extends ConnectError { static priceCalculationFailed( userId?: string, - originalError?: Error, + originalError?: Error ): PaymentError { return new PaymentError({ type: PaymentErrorType.PRICE_CALCULATION_FAILED, @@ -142,7 +142,7 @@ export class PaymentError extends ConnectError { static storageAdapterFailed( details?: string, - originalError?: Error, + originalError?: Error ): PaymentError { return new PaymentError({ type: PaymentErrorType.STORAGE_ADAPTER_FAILED, @@ -156,7 +156,7 @@ export class PaymentError extends ConnectError { static configurationError( details?: string, - originalError?: Error, + originalError?: Error ): PaymentError { return new PaymentError({ type: PaymentErrorType.CONFIGURATION_ERROR, diff --git a/src/errors/storage.ts b/src/errors/storage.ts index 505cfd6..ae8c91e 100644 --- a/src/errors/storage.ts +++ b/src/errors/storage.ts @@ -42,7 +42,7 @@ export class StorageError extends ConnectError { static connectionFailed( details?: string, - originalError?: Error, + originalError?: Error ): StorageError { return new StorageError({ type: StorageErrorType.CONNECTION_FAILED, @@ -56,7 +56,7 @@ export class StorageError extends ConnectError { static transactionFailed( details?: string, - originalError?: Error, + originalError?: Error ): StorageError { return new StorageError({ type: StorageErrorType.TRANSACTION_FAILED, @@ -92,7 +92,7 @@ export class StorageError extends ConnectError { static constraintViolation( constraint?: string, - originalError?: Error, + originalError?: Error ): StorageError { return new StorageError({ type: StorageErrorType.CONSTRAINT_VIOLATION, @@ -128,7 +128,7 @@ export class StorageError extends ConnectError { static serializationFailed( details?: string, - originalError?: Error, + originalError?: Error ): StorageError { return new StorageError({ type: StorageErrorType.SERIALIZATION_FAILED, @@ -142,7 +142,7 @@ export class StorageError extends ConnectError { static unknownEventType( eventType: string, - originalError?: Error, + originalError?: Error ): StorageError { return new StorageError({ type: StorageErrorType.UNKNOWN_EVENT_TYPE, @@ -163,7 +163,7 @@ export class StorageError extends ConnectError { static invalidTimestamp( details?: string, - originalError?: Error, + originalError?: Error ): StorageError { return new StorageError({ type: StorageErrorType.INVALID_TIMESTAMP, @@ -177,7 +177,7 @@ export class StorageError extends ConnectError { static userInsertFailed( userId?: string, - originalError?: Error, + originalError?: Error ): StorageError { return new StorageError({ type: StorageErrorType.USER_INSERT_FAILED, @@ -191,7 +191,7 @@ export class StorageError extends ConnectError { static eventInsertFailed( details?: string, - originalError?: Error, + originalError?: Error ): StorageError { return new StorageError({ type: StorageErrorType.EVENT_INSERT_FAILED, @@ -205,7 +205,7 @@ export class StorageError extends ConnectError { static priceCalculationFailed( userId?: string, - originalError?: Error, + originalError?: Error ): StorageError { return new StorageError({ type: StorageErrorType.PRICE_CALCULATION_FAILED, diff --git a/src/events/AIEvents/AITokenUsage.ts b/src/events/AIEvents/AITokenUsage.ts index 00e7e61..14fcea9 100644 --- a/src/events/AIEvents/AITokenUsage.ts +++ b/src/events/AIEvents/AITokenUsage.ts @@ -11,7 +11,7 @@ export class AITokenUsage implements AITokenUsageEvent { constructor( public userId: UserId, - public data: AITokenUsageEventData, + public data: AITokenUsageEventData ) { this.reported_timestamp = DateTime.utc(); } diff --git a/src/events/RawEvents/Payment.ts b/src/events/RawEvents/Payment.ts index 1ccfba9..e8247f7 100644 --- a/src/events/RawEvents/Payment.ts +++ b/src/events/RawEvents/Payment.ts @@ -11,7 +11,7 @@ export class Payment implements PaymentEvent { constructor( public userId: UserId, - public data: PaymentEventData, + public data: PaymentEventData ) { this.reported_timestamp = DateTime.utc(); } diff --git a/src/events/RawEvents/SDKCall.ts b/src/events/RawEvents/SDKCall.ts index 005cd9b..82d3f28 100644 --- a/src/events/RawEvents/SDKCall.ts +++ b/src/events/RawEvents/SDKCall.ts @@ -11,7 +11,7 @@ export class SDKCall implements SDKCallEvent { constructor( public userId: UserId, - public data: SDKCallEventData, + public data: SDKCallEventData ) { this.reported_timestamp = DateTime.utc(); } diff --git a/src/events/RequestEvents/RequestAITokenUsage.ts b/src/events/RequestEvents/RequestAITokenUsage.ts index 4c31566..bcb2c4a 100644 --- a/src/events/RequestEvents/RequestAITokenUsage.ts +++ b/src/events/RequestEvents/RequestAITokenUsage.ts @@ -11,7 +11,7 @@ export class RequestAITokenUsage implements RequestAITokenUsageEvent { constructor( public userId: UserId, - public data: RequestAITokenUsageEventData, + public data: RequestAITokenUsageEventData ) { this.reported_timestamp = DateTime.utc(); } diff --git a/src/events/RequestEvents/RequestPayment.ts b/src/events/RequestEvents/RequestPayment.ts index af034e7..32554ae 100644 --- a/src/events/RequestEvents/RequestPayment.ts +++ b/src/events/RequestEvents/RequestPayment.ts @@ -11,7 +11,7 @@ export class RequestPayment implements RequestPaymentEvent { constructor( public userId: UserId, - public data: RequestPaymentEventData, + public data: RequestPaymentEventData ) { this.reported_timestamp = DateTime.utc(); } diff --git a/src/events/RequestEvents/RequestSDKCall.ts b/src/events/RequestEvents/RequestSDKCall.ts index b22e7d1..fb58160 100644 --- a/src/events/RequestEvents/RequestSDKCall.ts +++ b/src/events/RequestEvents/RequestSDKCall.ts @@ -11,7 +11,7 @@ export class RequestSDKCall implements RequestSDKCallEvent { constructor( public userId: UserId, - public data: RequestSDKCallEventData, + public data: RequestSDKCallEventData ) { this.reported_timestamp = DateTime.utc(); } diff --git a/src/gen/auth/v1/auth_pb.ts b/src/gen/auth/v1/auth_pb.ts index ba83a3b..8840a7a 100644 --- a/src/gen/auth/v1/auth_pb.ts +++ b/src/gen/auth/v1/auth_pb.ts @@ -20,7 +20,7 @@ import type { Message } from "@bufbuild/protobuf"; export const file_auth_v1_auth: GenFile = /*@__PURE__*/ fileDesc( - "ChJhdXRoL3YxL2F1dGgucHJvdG8SB2F1dGgudjEiNgoTQ3JlYXRlQVBJS2V5UmVxdWVzdBIMCgRuYW1lGAEgASgJEhEKCWV4cGlyZXNJbhgCIAEoAyJsChRDcmVhdGVBUElLZXlSZXNwb25zZRIQCghhcGlLZXlJZBgBIAEoCRIOCgZhcGlLZXkYAiABKAkSDAoEbmFtZRgDIAEoCRIRCgljcmVhdGVkQXQYBCABKAkSEQoJZXhwaXJlc0F0GAUgASgJMlwKC0F1dGhTZXJ2aWNlEk0KDENyZWF0ZUFQSUtleRIcLmF1dGgudjEuQ3JlYXRlQVBJS2V5UmVxdWVzdBodLmF1dGgudjEuQ3JlYXRlQVBJS2V5UmVzcG9uc2UiAGIGcHJvdG8z", + "ChJhdXRoL3YxL2F1dGgucHJvdG8SB2F1dGgudjEiNgoTQ3JlYXRlQVBJS2V5UmVxdWVzdBIMCgRuYW1lGAEgASgJEhEKCWV4cGlyZXNJbhgCIAEoAyJsChRDcmVhdGVBUElLZXlSZXNwb25zZRIQCghhcGlLZXlJZBgBIAEoCRIOCgZhcGlLZXkYAiABKAkSDAoEbmFtZRgDIAEoCRIRCgljcmVhdGVkQXQYBCABKAkSEQoJZXhwaXJlc0F0GAUgASgJMlwKC0F1dGhTZXJ2aWNlEk0KDENyZWF0ZUFQSUtleRIcLmF1dGgudjEuQ3JlYXRlQVBJS2V5UmVxdWVzdBodLmF1dGgudjEuQ3JlYXRlQVBJS2V5UmVzcG9uc2UiAGIGcHJvdG8z" ); /** diff --git a/src/gen/event/v1/event_pb.ts b/src/gen/event/v1/event_pb.ts index 4ef3bc2..a67a220 100644 --- a/src/gen/event/v1/event_pb.ts +++ b/src/gen/event/v1/event_pb.ts @@ -22,7 +22,7 @@ import type { Message } from "@bufbuild/protobuf"; export const file_event_v1_event: GenFile = /*@__PURE__*/ fileDesc( - "ChRldmVudC92MS9ldmVudC5wcm90bxIIZXZlbnQudjEidwoUUmVnaXN0ZXJFdmVudFJlcXVlc3QSIQoEdHlwZRgBIAEoDjITLmV2ZW50LnYxLkV2ZW50VHlwZRIOCgZ1c2VySWQYAiABKAkSJAoHc2RrQ2FsbBgDIAEoCzIRLmV2ZW50LnYxLlNES0NhbGxIAEIGCgRkYXRhIl8KB1NES0NhbGwSKgoLc2RrQ2FsbFR5cGUYASABKA4yFS5ldmVudC52MS5TREtDYWxsVHlwZRIQCgZhbW91bnQYAiABKAJIABINCgN0YWcYAyABKAlIAEIHCgVkZWJpdCInChVSZWdpc3RlckV2ZW50UmVzcG9uc2USDgoGcmFuZG9tGAEgASgJIn8KElN0cmVhbUV2ZW50UmVxdWVzdBIhCgR0eXBlGAEgASgOMhMuZXZlbnQudjEuRXZlbnRUeXBlEg4KBnVzZXJJZBgCIAEoCRIuCgxhaVRva2VuVXNhZ2UYBCABKAsyFi5ldmVudC52MS5BSVRva2VuVXNhZ2VIAEIGCgRkYXRhIr0BCgxBSVRva2VuVXNhZ2USDQoFbW9kZWwYASABKAkSEwoLaW5wdXRUb2tlbnMYAiABKAUSFAoMb3V0cHV0VG9rZW5zGAMgASgFEhUKC2lucHV0QW1vdW50GAQgASgCSAASEgoIaW5wdXRUYWcYBSABKAlIABIWCgxvdXRwdXRBbW91bnQYBiABKAJIARITCglvdXRwdXRUYWcYByABKAlIAUIMCgppbnB1dERlYml0Qg0KC291dHB1dERlYml0Ij8KE1N0cmVhbUV2ZW50UmVzcG9uc2USFwoPZXZlbnRzUHJvY2Vzc2VkGAEgASgFEg8KB21lc3NhZ2UYAiABKAkqSQoJRXZlbnRUeXBlEhoKFkVWRU5UX1RZUEVfVU5TUEVDSUZJRUQQABIMCghTREtfQ0FMTBABEhIKDkFJX1RPS0VOX1VTQUdFEAIqSAoLU0RLQ2FsbFR5cGUSGwoXU0RLQ2FsbFR5cGVfVU5TUEVDSUZJRUQQABIHCgNSQVcQARITCg9NSURETEVXQVJFX0NBTEwQAjKzAQoMRXZlbnRTZXJ2aWNlElIKDVJlZ2lzdGVyRXZlbnQSHi5ldmVudC52MS5SZWdpc3RlckV2ZW50UmVxdWVzdBofLmV2ZW50LnYxLlJlZ2lzdGVyRXZlbnRSZXNwb25zZSIAEk8KDFN0cmVhbUV2ZW50cxIcLmV2ZW50LnYxLlN0cmVhbUV2ZW50UmVxdWVzdBodLmV2ZW50LnYxLlN0cmVhbUV2ZW50UmVzcG9uc2UiACgBYgZwcm90bzM", + "ChRldmVudC92MS9ldmVudC5wcm90bxIIZXZlbnQudjEidwoUUmVnaXN0ZXJFdmVudFJlcXVlc3QSIQoEdHlwZRgBIAEoDjITLmV2ZW50LnYxLkV2ZW50VHlwZRIOCgZ1c2VySWQYAiABKAkSJAoHc2RrQ2FsbBgDIAEoCzIRLmV2ZW50LnYxLlNES0NhbGxIAEIGCgRkYXRhIl8KB1NES0NhbGwSKgoLc2RrQ2FsbFR5cGUYASABKA4yFS5ldmVudC52MS5TREtDYWxsVHlwZRIQCgZhbW91bnQYAiABKAJIABINCgN0YWcYAyABKAlIAEIHCgVkZWJpdCInChVSZWdpc3RlckV2ZW50UmVzcG9uc2USDgoGcmFuZG9tGAEgASgJIn8KElN0cmVhbUV2ZW50UmVxdWVzdBIhCgR0eXBlGAEgASgOMhMuZXZlbnQudjEuRXZlbnRUeXBlEg4KBnVzZXJJZBgCIAEoCRIuCgxhaVRva2VuVXNhZ2UYBCABKAsyFi5ldmVudC52MS5BSVRva2VuVXNhZ2VIAEIGCgRkYXRhIr0BCgxBSVRva2VuVXNhZ2USDQoFbW9kZWwYASABKAkSEwoLaW5wdXRUb2tlbnMYAiABKAUSFAoMb3V0cHV0VG9rZW5zGAMgASgFEhUKC2lucHV0QW1vdW50GAQgASgCSAASEgoIaW5wdXRUYWcYBSABKAlIABIWCgxvdXRwdXRBbW91bnQYBiABKAJIARITCglvdXRwdXRUYWcYByABKAlIAUIMCgppbnB1dERlYml0Qg0KC291dHB1dERlYml0Ij8KE1N0cmVhbUV2ZW50UmVzcG9uc2USFwoPZXZlbnRzUHJvY2Vzc2VkGAEgASgFEg8KB21lc3NhZ2UYAiABKAkqSQoJRXZlbnRUeXBlEhoKFkVWRU5UX1RZUEVfVU5TUEVDSUZJRUQQABIMCghTREtfQ0FMTBABEhIKDkFJX1RPS0VOX1VTQUdFEAIqSAoLU0RLQ2FsbFR5cGUSGwoXU0RLQ2FsbFR5cGVfVU5TUEVDSUZJRUQQABIHCgNSQVcQARITCg9NSURETEVXQVJFX0NBTEwQAjKzAQoMRXZlbnRTZXJ2aWNlElIKDVJlZ2lzdGVyRXZlbnQSHi5ldmVudC52MS5SZWdpc3RlckV2ZW50UmVxdWVzdBofLmV2ZW50LnYxLlJlZ2lzdGVyRXZlbnRSZXNwb25zZSIAEk8KDFN0cmVhbUV2ZW50cxIcLmV2ZW50LnYxLlN0cmVhbUV2ZW50UmVxdWVzdBodLmV2ZW50LnYxLlN0cmVhbUV2ZW50UmVzcG9uc2UiACgBYgZwcm90bzM" ); /** diff --git a/src/gen/payment/v1/payment_pb.ts b/src/gen/payment/v1/payment_pb.ts index 5678d02..3ccf520 100644 --- a/src/gen/payment/v1/payment_pb.ts +++ b/src/gen/payment/v1/payment_pb.ts @@ -20,7 +20,7 @@ import type { Message } from "@bufbuild/protobuf"; export const file_payment_v1_payment: GenFile = /*@__PURE__*/ fileDesc( - "ChhwYXltZW50L3YxL3BheW1lbnQucHJvdG8SCnBheW1lbnQudjEiKwoZQ3JlYXRlQ2hlY2tvdXRMaW5rUmVxdWVzdBIOCgZ1c2VySWQYASABKAkiMgoaQ3JlYXRlQ2hlY2tvdXRMaW5rUmVzcG9uc2USFAoMY2hlY2tvdXRMaW5rGAEgASgJMncKDlBheW1lbnRTZXJ2aWNlEmUKEkNyZWF0ZUNoZWNrb3V0TGluaxIlLnBheW1lbnQudjEuQ3JlYXRlQ2hlY2tvdXRMaW5rUmVxdWVzdBomLnBheW1lbnQudjEuQ3JlYXRlQ2hlY2tvdXRMaW5rUmVzcG9uc2UiAGIGcHJvdG8z", + "ChhwYXltZW50L3YxL3BheW1lbnQucHJvdG8SCnBheW1lbnQudjEiKwoZQ3JlYXRlQ2hlY2tvdXRMaW5rUmVxdWVzdBIOCgZ1c2VySWQYASABKAkiMgoaQ3JlYXRlQ2hlY2tvdXRMaW5rUmVzcG9uc2USFAoMY2hlY2tvdXRMaW5rGAEgASgJMncKDlBheW1lbnRTZXJ2aWNlEmUKEkNyZWF0ZUNoZWNrb3V0TGluaxIlLnBheW1lbnQudjEuQ3JlYXRlQ2hlY2tvdXRMaW5rUmVxdWVzdBomLnBheW1lbnQudjEuQ3JlYXRlQ2hlY2tvdXRMaW5rUmVzcG9uc2UiAGIGcHJvdG8z" ); /** diff --git a/src/interceptors/auth.ts b/src/interceptors/auth.ts index e4b92cc..14935c2 100644 --- a/src/interceptors/auth.ts +++ b/src/interceptors/auth.ts @@ -39,7 +39,7 @@ export function authInterceptor(): Interceptor { AuthErrorType.MISSING_HEADER, error.message, undefined, - { endpoint: req.url }, + { endpoint: req.url } ); throw error; } @@ -50,7 +50,7 @@ export function authInterceptor(): Interceptor { AuthErrorType.INVALID_HEADER_FORMAT, error.message, undefined, - { headerValue: authorization.substring(0, 20) + "..." }, + { headerValue: authorization.substring(0, 20) + "..." } ); throw error; } @@ -64,7 +64,7 @@ export function authInterceptor(): Interceptor { AuthErrorType.INVALID_API_KEY, error.message, undefined, - { endpoint: req.url }, + { endpoint: req.url } ); throw error; } @@ -99,13 +99,13 @@ export function authInterceptor(): Interceptor { apiKeyRecord = result[0]; } catch (err) { const error = AuthError.databaseError( - err instanceof Error ? err : undefined, + err instanceof Error ? err : undefined ); logger.logError( AuthErrorType.DATABASE_ERROR, error.message, err instanceof Error ? err : undefined, - { endpoint: req.url }, + { endpoint: req.url } ); throw error; } @@ -117,7 +117,7 @@ export function authInterceptor(): Interceptor { AuthErrorType.INVALID_API_KEY, error.message, undefined, - { endpoint: req.url }, + { endpoint: req.url } ); throw error; } @@ -129,7 +129,7 @@ export function authInterceptor(): Interceptor { AuthErrorType.REVOKED_API_KEY, error.message, undefined, - { apiKeyId: apiKeyRecord.id }, + { apiKeyId: apiKeyRecord.id } ); throw error; } @@ -146,7 +146,7 @@ export function authInterceptor(): Interceptor { { apiKeyId: apiKeyRecord.id, expiresAt: apiKeyRecord.expiresAt, - }, + } ); throw error; } @@ -173,7 +173,7 @@ export function authInterceptor(): Interceptor { AuthErrorType.UNKNOWN, error.message, err instanceof Error ? err : undefined, - { endpoint: req.url }, + { endpoint: req.url } ); throw error; } diff --git a/src/routes/gRPC/auth/createAPIKey.ts b/src/routes/gRPC/auth/createAPIKey.ts index da592ae..44395b8 100644 --- a/src/routes/gRPC/auth/createAPIKey.ts +++ b/src/routes/gRPC/auth/createAPIKey.ts @@ -20,7 +20,7 @@ const OPERATION = "CreateAPIKey"; export async function createAPIKey( req: CreateAPIKeyRequest, - context: HandlerContext, + context: HandlerContext ): Promise { try { // Get API key ID from context (set by auth interceptor) @@ -35,7 +35,7 @@ export async function createAPIKey( "Request authenticated", { apiKeyId, - }, + } ); // Validate the incoming request against the schema @@ -51,7 +51,7 @@ export async function createAPIKey( } throw APIKeyError.validationFailed( "Unknown validation error", - error as Error, + error as Error ); } @@ -88,7 +88,7 @@ export async function createAPIKey( } catch (error) { throw APIKeyError.creationFailed( "Failed to store API key", - error as Error, + error as Error ); } @@ -99,7 +99,7 @@ export async function createAPIKey( { apiKeyId: keyEventData.id, name: validatedData.name, - }, + } ); return create(CreateAPIKeyResponseSchema, { @@ -116,7 +116,7 @@ export async function createAPIKey( error instanceof APIKeyError ? error.type : "UNKNOWN", "CreateAPIKey handler failed", error instanceof Error ? error : undefined, - { apiKeyId: context.values.get(apiKeyContextKey) }, + { apiKeyId: context.values.get(apiKeyContextKey) } ); // Re-throw APIKeyError as-is diff --git a/src/routes/gRPC/events/registerEvent.ts b/src/routes/gRPC/events/registerEvent.ts index 608aebc..e129709 100644 --- a/src/routes/gRPC/events/registerEvent.ts +++ b/src/routes/gRPC/events/registerEvent.ts @@ -19,7 +19,7 @@ const OPERATION = "RegisterEvent"; export async function registerEvent( req: RegisterEventRequest, - context: HandlerContext, + context: HandlerContext ): Promise { try { // Extract API key ID from context @@ -31,7 +31,7 @@ export async function registerEvent( "Request authenticated", { apiKeyId, - }, + } ); // Validate and parse the incoming event @@ -50,7 +50,7 @@ export async function registerEvent( { apiKeyId, userId: eventSkeleton.userId, - }, + } ); return create(RegisterEventResponseSchema, { @@ -63,7 +63,7 @@ export async function registerEvent( error instanceof EventError ? error.type : "UNKNOWN", "RegisterEvent handler failed", error instanceof Error ? error : undefined, - { apiKeyId: context.values.get(apiKeyContextKey) }, + { apiKeyId: context.values.get(apiKeyContextKey) } ); // Re-throw EventError as-is diff --git a/src/routes/gRPC/events/streamEvents.ts b/src/routes/gRPC/events/streamEvents.ts index 1e2f84f..2b35f53 100644 --- a/src/routes/gRPC/events/streamEvents.ts +++ b/src/routes/gRPC/events/streamEvents.ts @@ -20,7 +20,7 @@ const OPERATION = "StreamEvents"; export async function streamEvents( requestStream: AsyncIterable, - context: HandlerContext, + context: HandlerContext ): Promise { let eventsProcessed = 0; @@ -34,7 +34,7 @@ export async function streamEvents( "Stream authenticated", { apiKeyId, - }, + } ); // Collect all events from the stream @@ -60,7 +60,7 @@ export async function streamEvents( apiKeyId, userId: eventSkeleton.userId, eventNumber: eventsProcessed, - }, + } ); } @@ -71,7 +71,7 @@ export async function streamEvents( { apiKeyId: context.values.get(apiKeyContextKey), eventsProcessed, - }, + } ); return create(StreamEventResponseSchema, { @@ -88,7 +88,7 @@ export async function streamEvents( { apiKeyId: context.values.get(apiKeyContextKey), eventsProcessed, - }, + } ); // Re-throw EventError as-is diff --git a/src/routes/gRPC/payment/createCheckoutLink.ts b/src/routes/gRPC/payment/createCheckoutLink.ts index 4842609..2bfd31c 100644 --- a/src/routes/gRPC/payment/createCheckoutLink.ts +++ b/src/routes/gRPC/payment/createCheckoutLink.ts @@ -25,7 +25,7 @@ const OPERATION = "CreateCheckoutLink"; export async function createCheckoutLink( req: CreateCheckoutLinkRequest, - context: HandlerContext, + context: HandlerContext ): Promise { try { const apiKeyId = context.values.get(apiKeyContextKey); @@ -39,7 +39,7 @@ export async function createCheckoutLink( "Request authenticated", { apiKeyId, - }, + } ); // Read environment configuration @@ -73,7 +73,7 @@ export async function createCheckoutLink( } throw PaymentError.validationFailed( "Unknown validation error", - error as Error, + error as Error ); } @@ -87,7 +87,7 @@ export async function createCheckoutLink( "LEMON_SQUEEZY_SDK_ERROR", "Lemon Squeezy SDK error", error as Error, - {}, + {} ); }, }); @@ -106,7 +106,7 @@ export async function createCheckoutLink( if (!storageAdapter) { throw PaymentError.storageAdapterFailed( - "Storage adapter factory returned null or undefined", + "Storage adapter factory returned null or undefined" ); } @@ -119,7 +119,7 @@ export async function createCheckoutLink( ) { throw PaymentError.priceCalculationFailed( validatedData.userId, - new Error(`Invalid price value: ${custom_price}`), + new Error(`Invalid price value: ${custom_price}`) ); } } catch (error) { @@ -129,7 +129,7 @@ export async function createCheckoutLink( "PRICE_CALCULATION_FAILED", "Failed to calculate price", error as Error, - { userId: validatedData.userId, apiKeyId }, + { userId: validatedData.userId, apiKeyId } ); // Use duck typing instead of instanceof to work with mocked modules @@ -144,7 +144,7 @@ export async function createCheckoutLink( throw PaymentError.priceCalculationFailed( validatedData.userId, - error as Error, + error as Error ); } @@ -169,7 +169,7 @@ export async function createCheckoutLink( api_key_id: String(apiKeyId), }, }, - }, + } ); } catch (error) { let errorMessage = "Unknown error"; @@ -193,19 +193,19 @@ export async function createCheckoutLink( price: custom_price, storeId: LEMON_SQUEEZY_STORE_ID, variantId: LEMON_SQUEEZY_VARIANT_ID, - }, + } ); throw PaymentError.lemonSqueezyApiError( errorMessage, - error instanceof Error ? error : new Error(String(error)), + error instanceof Error ? error : new Error(String(error)) ); } // Validate response from Lemon Squeezy with comprehensive checks if (!checkoutResponse) { throw PaymentError.invalidCheckoutResponse( - "Checkout response is null or undefined", + "Checkout response is null or undefined" ); } @@ -219,32 +219,32 @@ export async function createCheckoutLink( // Validate response structure if (!checkoutResponse.data) { throw PaymentError.invalidCheckoutResponse( - "Missing 'data' field in checkout response", + "Missing 'data' field in checkout response" ); } if (!checkoutResponse.data.data) { throw PaymentError.invalidCheckoutResponse( - "Missing nested 'data' field in checkout response", + "Missing nested 'data' field in checkout response" ); } if (!checkoutResponse.data.data.attributes) { throw PaymentError.invalidCheckoutResponse( - "Missing 'attributes' field in checkout response", + "Missing 'attributes' field in checkout response" ); } const checkoutUrl = checkoutResponse.data.data.attributes.url; if (!checkoutUrl) { throw PaymentError.invalidCheckoutResponse( - "No checkout URL found in response attributes", + "No checkout URL found in response attributes" ); } if (typeof checkoutUrl !== "string" || checkoutUrl.trim().length === 0) { throw PaymentError.invalidCheckoutResponse( - `Invalid checkout URL format: ${typeof checkoutUrl}`, + `Invalid checkout URL format: ${typeof checkoutUrl}` ); } @@ -254,7 +254,7 @@ export async function createCheckoutLink( } catch (urlError) { throw PaymentError.invalidCheckoutResponse( `Checkout URL is not a valid URL: ${checkoutUrl}`, - urlError instanceof Error ? urlError : undefined, + urlError instanceof Error ? urlError : undefined ); } @@ -262,7 +262,7 @@ export async function createCheckoutLink( OPERATION, "completed", "Checkout link created successfully", - { userId: validatedData.userId, apiKeyId, checkoutUrl }, + { userId: validatedData.userId, apiKeyId, checkoutUrl } ); return create(CreateCheckoutLinkResponseSchema, { @@ -281,7 +281,7 @@ export async function createCheckoutLink( : "UNKNOWN", "CreateCheckoutLink handler failed", error instanceof Error ? error : undefined, - { apiKeyId }, + { apiKeyId } ); // Re-throw PaymentError as-is @@ -303,7 +303,7 @@ export async function createCheckoutLink( // Wrap unexpected errors with context throw PaymentError.unknown( - error instanceof Error ? error : new Error(String(error)), + error instanceof Error ? error : new Error(String(error)) ); } } diff --git a/src/routes/http/createdCheckout.ts b/src/routes/http/createdCheckout.ts index 6e0b9fa..2a18a29 100644 --- a/src/routes/http/createdCheckout.ts +++ b/src/routes/http/createdCheckout.ts @@ -22,7 +22,7 @@ if (!LEMON_SQUEEZY_API_KEY) { "LEMON_SQUEEZY_SDK_ERROR", "Lemon Squeezy SDK error in webhook handler", error as Error, - {}, + {} ); }, }); @@ -58,7 +58,7 @@ interface LemonSqueezyWebhookPayload { function verifyWebhookSignature( payload: string, signature: string | undefined, - secret: string, + secret: string ): boolean { if (!signature) { return false; @@ -77,7 +77,7 @@ function verifyWebhookSignature( "SIGNATURE_VERIFICATION_ERROR", "Signature verification error", error as Error, - {}, + {} ); return false; } @@ -106,14 +106,14 @@ function readBody(req: IncomingMessage): Promise { */ export async function handleLemonSqueezyWebhook( req: IncomingMessage, - res: ServerResponse, + res: ServerResponse ): Promise { try { logger.logOperationInfo( OPERATION, "start", "Processing webhook request", - {}, + {} ); // Read the raw body @@ -133,7 +133,7 @@ export async function handleLemonSqueezyWebhook( "MISSING_WEBHOOK_SECRET", "Webhook secret not configured", undefined, - {}, + {} ); res.writeHead(500, { "Content-Type": "application/json" }); res.end(JSON.stringify({ error: "Webhook secret not configured" })); @@ -143,7 +143,7 @@ export async function handleLemonSqueezyWebhook( const isValid = verifyWebhookSignature( rawBody, signature, - LEMON_SQUEEZY_WEBHOOK_SECRET, + LEMON_SQUEEZY_WEBHOOK_SECRET ); if (!isValid) { @@ -153,7 +153,7 @@ export async function handleLemonSqueezyWebhook( "INVALID_SIGNATURE", "Invalid webhook signature", undefined, - {}, + {} ); res.writeHead(401, { "Content-Type": "application/json" }); res.end(JSON.stringify({ error: "Invalid signature" })); @@ -164,7 +164,7 @@ export async function handleLemonSqueezyWebhook( OPERATION, "signature_validated", "Signature validated successfully", - {}, + {} ); // Parse the payload @@ -178,7 +178,7 @@ export async function handleLemonSqueezyWebhook( "INVALID_JSON", "Invalid JSON payload", error as Error, - {}, + {} ); res.writeHead(400, { "Content-Type": "application/json" }); res.end(JSON.stringify({ error: "Invalid JSON payload" })); @@ -191,7 +191,7 @@ export async function handleLemonSqueezyWebhook( OPERATION, "ignored_event", "Ignoring non-order_created event", - { eventName: payload.meta.event_name }, + { eventName: payload.meta.event_name } ); res.writeHead(200, { "Content-Type": "application/json" }); res.end(JSON.stringify({ message: "Event ignored" })); @@ -202,7 +202,7 @@ export async function handleLemonSqueezyWebhook( OPERATION, "processing", "Processing order_created event", - {}, + {} ); // Extract user ID from custom data @@ -216,7 +216,7 @@ export async function handleLemonSqueezyWebhook( "MISSING_USER_ID", "Missing user_id in webhook payload", undefined, - {}, + {} ); res.writeHead(400, { "Content-Type": "application/json" }); res.end(JSON.stringify({ error: "Missing user_id in webhook payload" })); @@ -230,7 +230,7 @@ export async function handleLemonSqueezyWebhook( "MISSING_API_KEY_ID", "Missing apiKeyId in webhook payload", undefined, - { userId }, + { userId } ); res.writeHead(400, { "Content-Type": "application/json" }); res.end(JSON.stringify({ error: "Missing apiKeyId in webhook payload" })); @@ -251,7 +251,7 @@ export async function handleLemonSqueezyWebhook( const paymentEvent = new Payment(userId, { creditAmount }); const adapter = await StorageAdapterFactory.getStorageAdapter( paymentEvent, - apiKeyId, + apiKeyId ); await adapter.add(paymentEvent.serialize()); @@ -260,7 +260,7 @@ export async function handleLemonSqueezyWebhook( OPERATION, "completed", "Payment event stored successfully", - { userId, apiKeyId, creditAmount }, + { userId, apiKeyId, creditAmount } ); res.writeHead(200, { "Content-Type": "application/json" }); @@ -272,7 +272,7 @@ export async function handleLemonSqueezyWebhook( "DATABASE_ERROR", "Database error while storing payment", dbError as Error, - { userId, apiKeyId }, + { userId, apiKeyId } ); res.writeHead(500, { "Content-Type": "application/json" }); res.end(JSON.stringify({ error: "Database error" })); @@ -284,7 +284,7 @@ export async function handleLemonSqueezyWebhook( "UNEXPECTED_ERROR", "Unexpected error in webhook handler", error as Error, - {}, + {} ); res.writeHead(500, { "Content-Type": "application/json" }); res.end(JSON.stringify({ error: "Internal server error" })); diff --git a/src/server.ts b/src/server.ts index 85be559..803a275 100644 --- a/src/server.ts +++ b/src/server.ts @@ -50,7 +50,7 @@ const grpcHandler = connectNodeAdapter({ // Create a combined handler for both gRPC and HTTP webhooks const requestHandler = ( req: http.IncomingMessage, - res: http.ServerResponse, + res: http.ServerResponse ) => { // Handle webhook endpoint if ( diff --git a/src/storage/adapter/postgres/handlers/addAiTokenUsage.ts b/src/storage/adapter/postgres/handlers/addAiTokenUsage.ts index a5284f0..4f872b1 100644 --- a/src/storage/adapter/postgres/handlers/addAiTokenUsage.ts +++ b/src/storage/adapter/postgres/handlers/addAiTokenUsage.ts @@ -23,7 +23,7 @@ type AggregatedEvent = { export async function handleAddAiTokenUsage( events: Array>, - apiKeyId: string, + apiKeyId: string ): Promise<{ id: string } | void> { const connectionObject = getPostgresDB(); @@ -42,7 +42,7 @@ export async function handleAddAiTokenUsage( { eventCount: events.length, apiKeyId, - }, + } ); // Validate all events before processing @@ -52,7 +52,7 @@ export async function handleAddAiTokenUsage( if (typeof inputTokens === "number" && inputTokens < 0) { throw StorageError.insertFailed( `Negative input tokens not allowed for AI token usage for user ${event_data.userId}`, - new Error(`inputTokens ${inputTokens} is negative`), + new Error(`inputTokens ${inputTokens} is negative`) ); } @@ -61,7 +61,7 @@ export async function handleAddAiTokenUsage( if (typeof outputTokens === "number" && outputTokens < 0) { throw StorageError.insertFailed( `Negative output tokens not allowed for AI token usage for user ${event_data.userId}`, - new Error(`outputTokens ${outputTokens} is negative`), + new Error(`outputTokens ${outputTokens} is negative`) ); } @@ -70,7 +70,7 @@ export async function handleAddAiTokenUsage( if (typeof inputDebitAmount === "number" && inputDebitAmount < 0) { throw StorageError.insertFailed( `Negative input debit amount not allowed for AI token usage for user ${event_data.userId}`, - new Error(`inputDebitAmount ${inputDebitAmount} is negative`), + new Error(`inputDebitAmount ${inputDebitAmount} is negative`) ); } @@ -79,7 +79,7 @@ export async function handleAddAiTokenUsage( if (typeof outputDebitAmount === "number" && outputDebitAmount < 0) { throw StorageError.insertFailed( `Negative output debit amount not allowed for AI token usage for user ${event_data.userId}`, - new Error(`outputDebitAmount ${outputDebitAmount} is negative`), + new Error(`outputDebitAmount ${outputDebitAmount} is negative`) ); } } @@ -94,13 +94,13 @@ export async function handleAddAiTokenUsage( } catch (e) { throw StorageError.invalidTimestamp( "Failed to convert reported_timestamp to ISO format", - e instanceof Error ? e : new Error(String(e)), + e instanceof Error ? e : new Error(String(e)) ); } if (!reported_timestamp || reported_timestamp.trim().length === 0) { throw StorageError.invalidTimestamp( - "Timestamp is undefined or empty after conversion", + "Timestamp is undefined or empty after conversion" ); } @@ -141,13 +141,13 @@ export async function handleAddAiTokenUsage( originalCount: events.length, aggregatedCount: aggregatedEvents.length, apiKeyId, - }, + } ); await connectionObject.transaction(async (txn) => { // Collect unique user IDs const uniqueUserIds = Array.from( - new Set(aggregatedEvents.map((event) => event.userId)), + new Set(aggregatedEvents.map((event) => event.userId)) ); // Batch insert users if not exists @@ -162,7 +162,7 @@ export async function handleAddAiTokenUsage( OPERATION, "users_ensured", "Users ensured in database", - { userCount: uniqueUserIds.length }, + { userCount: uniqueUserIds.length } ); } } catch (e) { @@ -175,12 +175,12 @@ export async function handleAddAiTokenUsage( OPERATION, "users_exist", "Users already exist, continuing", - { userCount: uniqueUserIds.length }, + { userCount: uniqueUserIds.length } ); } else { throw StorageError.userInsertFailed( uniqueUserIds.join(", "), - e instanceof Error ? e : new Error(String(e)), + e instanceof Error ? e : new Error(String(e)) ); } } @@ -202,7 +202,7 @@ export async function handleAddAiTokenUsage( } catch (e) { throw StorageError.eventInsertFailed( `Failed to batch insert ${aggregatedEvents.length} aggregated event(s)`, - e instanceof Error ? e : new Error(String(e)), + e instanceof Error ? e : new Error(String(e)) ); } @@ -213,7 +213,7 @@ export async function handleAddAiTokenUsage( if (eventIDs.length !== aggregatedEvents.length) { throw StorageError.insertFailed( `Expected ${aggregatedEvents.length} event IDs but got ${eventIDs.length}`, - new Error("Event ID count mismatch"), + new Error("Event ID count mismatch") ); } @@ -221,7 +221,7 @@ export async function handleAddAiTokenUsage( OPERATION, "events_inserted", `${eventIDs.length} event row(s) inserted`, - { eventCount: eventIDs.length, apiKeyId }, + { eventCount: eventIDs.length, apiKeyId } ); // Prepare AI token usage values for batch insert @@ -230,7 +230,7 @@ export async function handleAddAiTokenUsage( if (!eventId) { throw StorageError.insertFailed( `Missing event ID at index ${index}`, - new Error("Event ID is undefined"), + new Error("Event ID is undefined") ); } return { @@ -254,12 +254,12 @@ export async function handleAddAiTokenUsage( { eventCount: aiTokenUsageValues.length, apiKeyId, - }, + } ); } catch (e) { throw StorageError.insertFailed( `Failed to batch insert AI token usage events`, - e instanceof Error ? e : new Error(String(e)), + e instanceof Error ? e : new Error(String(e)) ); } @@ -267,7 +267,7 @@ export async function handleAddAiTokenUsage( if (!firstEvent || !firstEvent.id) { throw StorageError.insertFailed( "Missing or invalid ID for the first inserted event", - new Error(`Invalid first event ID: ${JSON.stringify(firstEvent)}`), + new Error(`Invalid first event ID: ${JSON.stringify(firstEvent)}`) ); } @@ -282,7 +282,7 @@ export async function handleAddAiTokenUsage( originalCount: events.length, aggregatedCount: aggregatedEvents.length, apiKeyId, - }, + } ); } catch (e) { // Use duck typing instead of instanceof to work with mocked modules @@ -297,7 +297,7 @@ export async function handleAddAiTokenUsage( throw StorageError.transactionFailed( `Transaction failed while storing ${events.length} AI_TOKEN_USAGE event(s)`, - e instanceof Error ? e : new Error(String(e)), + e instanceof Error ? e : new Error(String(e)) ); } } diff --git a/src/storage/adapter/postgres/handlers/addKey.ts b/src/storage/adapter/postgres/handlers/addKey.ts index aec8ee5..5bf5639 100644 --- a/src/storage/adapter/postgres/handlers/addKey.ts +++ b/src/storage/adapter/postgres/handlers/addKey.ts @@ -7,7 +7,7 @@ import { logger } from "../../../../errors/logger"; const OPERATION = "AddKey"; export async function handleAddKey( - event_data: SqlRecord<"ADD_KEY">, + event_data: SqlRecord<"ADD_KEY"> ): Promise<{ id: string } | void> { const connectionObject = getPostgresDB(); @@ -19,13 +19,13 @@ export async function handleAddKey( if (!event_data.data.name || typeof event_data.data.name !== "string") { throw StorageError.invalidData( - "Invalid or missing 'name' in ADD_KEY event data", + "Invalid or missing 'name' in ADD_KEY event data" ); } if (!event_data.data.key || typeof event_data.data.key !== "string") { throw StorageError.invalidData( - "Invalid or missing 'key' in ADD_KEY event data", + "Invalid or missing 'key' in ADD_KEY event data" ); } @@ -45,13 +45,13 @@ export async function handleAddKey( } catch (e) { throw StorageError.invalidTimestamp( "Failed to convert reported_timestamp to ISO format", - e instanceof Error ? e : new Error(String(e)), + e instanceof Error ? e : new Error(String(e)) ); } if (!reported_timestamp || reported_timestamp.trim().length === 0) { throw StorageError.invalidTimestamp( - "Timestamp is undefined or empty after conversion", + "Timestamp is undefined or empty after conversion" ); } @@ -75,13 +75,13 @@ export async function handleAddKey( ) { throw StorageError.constraintViolation( `API key with name '${keyData.data.name}' or key value already exists`, - e, + e ); } throw StorageError.insertFailed( `Failed to insert API key '${keyData.data.name}'`, - e instanceof Error ? e : new Error(String(e)), + e instanceof Error ? e : new Error(String(e)) ); } @@ -91,7 +91,7 @@ export async function handleAddKey( if (!apiKeyRecord.id) { throw StorageError.emptyResult( - "API key insert returned object without id field", + "API key insert returned object without id field" ); } @@ -99,7 +99,7 @@ export async function handleAddKey( OPERATION, "key_inserted", "API key inserted successfully", - { apiKeyId: apiKeyRecord.id, keyName: keyData.data.name }, + { apiKeyId: apiKeyRecord.id, keyName: keyData.data.name } ); return apiKeyRecord; @@ -117,7 +117,7 @@ export async function handleAddKey( throw StorageError.transactionFailed( "Transaction failed while storing ADD_KEY event", - e instanceof Error ? e : new Error(String(e)), + e instanceof Error ? e : new Error(String(e)) ); } } diff --git a/src/storage/adapter/postgres/handlers/addPayment.ts b/src/storage/adapter/postgres/handlers/addPayment.ts index 01e03f7..09a29b3 100644 --- a/src/storage/adapter/postgres/handlers/addPayment.ts +++ b/src/storage/adapter/postgres/handlers/addPayment.ts @@ -12,7 +12,7 @@ const OPERATION = "AddPayment"; export async function handleAddPayment( event_data: SqlRecord<"PAYMENT">, - apiKeyId?: string, + apiKeyId?: string ): Promise<{ id: string } | void> { const connectionObject = getPostgresDB(); @@ -29,8 +29,8 @@ export async function handleAddPayment( ) { throw StorageError.invalidData( `Invalid creditAmount: must be a positive finite number, got ${String( - creditAmount, - )}`, + creditAmount + )}` ); } @@ -53,7 +53,7 @@ export async function handleAddPayment( OPERATION, "user_ensured", "User ensured in database", - { userId: event_data.userId }, + { userId: event_data.userId } ); } catch (e) { if ( @@ -65,12 +65,12 @@ export async function handleAddPayment( OPERATION, "user_exists", "User already exists, continuing", - { userId: event_data.userId }, + { userId: event_data.userId } ); } else { throw StorageError.userInsertFailed( event_data.userId, - e instanceof Error ? e : new Error(String(e)), + e instanceof Error ? e : new Error(String(e)) ); } } @@ -82,13 +82,13 @@ export async function handleAddPayment( } catch (e) { throw StorageError.invalidTimestamp( "Failed to convert reported_timestamp to ISO format", - e instanceof Error ? e : new Error(String(e)), + e instanceof Error ? e : new Error(String(e)) ); } if (!reported_timestamp || reported_timestamp.trim().length === 0) { throw StorageError.invalidTimestamp( - "Timestamp is undefined or empty after conversion", + "Timestamp is undefined or empty after conversion" ); } @@ -106,7 +106,7 @@ export async function handleAddPayment( } catch (e) { throw StorageError.eventInsertFailed( `Failed to insert event for user ${event_data.userId}`, - e instanceof Error ? e : new Error(String(e)), + e instanceof Error ? e : new Error(String(e)) ); } @@ -118,7 +118,7 @@ export async function handleAddPayment( OPERATION, "event_inserted", "Event row inserted", - { eventId: eventID.id, userId: event_data.userId, apiKeyId }, + { eventId: eventID.id, userId: event_data.userId, apiKeyId } ); // Insert payment event @@ -136,12 +136,12 @@ export async function handleAddPayment( eventId: eventID.id, creditAmount: event_data.data.creditAmount, userId: event_data.userId, - }, + } ); } catch (e) { throw StorageError.insertFailed( `Failed to insert payment event for event ID ${eventID.id}`, - e instanceof Error ? e : new Error(String(e)), + e instanceof Error ? e : new Error(String(e)) ); } @@ -152,7 +152,7 @@ export async function handleAddPayment( OPERATION, "completed", "PAYMENT transaction completed successfully", - { userId: event_data.userId, apiKeyId }, + { userId: event_data.userId, apiKeyId } ); } catch (e) { // Use duck typing instead of instanceof to work with mocked modules @@ -167,7 +167,7 @@ export async function handleAddPayment( throw StorageError.transactionFailed( "Transaction failed while storing PAYMENT event", - e instanceof Error ? e : new Error(String(e)), + e instanceof Error ? e : new Error(String(e)) ); } } diff --git a/src/storage/adapter/postgres/handlers/addSdkCall.ts b/src/storage/adapter/postgres/handlers/addSdkCall.ts index e9c52b2..04b7f63 100644 --- a/src/storage/adapter/postgres/handlers/addSdkCall.ts +++ b/src/storage/adapter/postgres/handlers/addSdkCall.ts @@ -12,7 +12,7 @@ const OPERATION = "AddSdkCall"; export async function handleAddSdkCall( event_data: SqlRecord<"SDK_CALL">, - apiKeyId: string, + apiKeyId: string ): Promise<{ id: string } | void> { const connectionObject = getPostgresDB(); @@ -27,7 +27,7 @@ export async function handleAddSdkCall( if (typeof debitAmount === "number" && debitAmount < 0) { throw StorageError.insertFailed( `Negative debit amount not allowed for SDK call for user ${event_data.userId}`, - new Error(`debitAmount ${debitAmount} is negative`), + new Error(`debitAmount ${debitAmount} is negative`) ); } @@ -45,7 +45,7 @@ export async function handleAddSdkCall( OPERATION, "user_ensured", "User ensured in database", - { userId: event_data.userId }, + { userId: event_data.userId } ); } catch (e) { if ( @@ -57,12 +57,12 @@ export async function handleAddSdkCall( OPERATION, "user_exists", "User already exists, continuing", - { userId: event_data.userId }, + { userId: event_data.userId } ); } else { throw StorageError.userInsertFailed( event_data.userId, - e instanceof Error ? e : new Error(String(e)), + e instanceof Error ? e : new Error(String(e)) ); } } @@ -74,13 +74,13 @@ export async function handleAddSdkCall( } catch (e) { throw StorageError.invalidTimestamp( "Failed to convert reported_timestamp to ISO format", - e instanceof Error ? e : new Error(String(e)), + e instanceof Error ? e : new Error(String(e)) ); } if (!reported_timestamp || reported_timestamp.trim().length === 0) { throw StorageError.invalidTimestamp( - "Timestamp is undefined or empty after conversion", + "Timestamp is undefined or empty after conversion" ); } @@ -98,7 +98,7 @@ export async function handleAddSdkCall( } catch (e) { throw StorageError.eventInsertFailed( `Failed to insert event for user ${event_data.userId}`, - e instanceof Error ? e : new Error(String(e)), + e instanceof Error ? e : new Error(String(e)) ); } @@ -110,7 +110,7 @@ export async function handleAddSdkCall( OPERATION, "event_inserted", "Event row inserted", - { eventId: eventID.id, userId: event_data.userId, apiKeyId }, + { eventId: eventID.id, userId: event_data.userId, apiKeyId } ); // Insert SDK call event @@ -131,12 +131,12 @@ export async function handleAddSdkCall( eventId: eventID.id, debitAmount: sdkData.data.debitAmount, userId: event_data.userId, - }, + } ); } catch (e) { throw StorageError.insertFailed( `Failed to insert SDK call event for event ID ${eventID.id}`, - e instanceof Error ? e : new Error(String(e)), + e instanceof Error ? e : new Error(String(e)) ); } @@ -147,7 +147,7 @@ export async function handleAddSdkCall( OPERATION, "completed", "SDK_CALL transaction completed successfully", - { userId: event_data.userId, apiKeyId }, + { userId: event_data.userId, apiKeyId } ); } catch (e) { // Use duck typing instead of instanceof to work with mocked modules @@ -162,7 +162,7 @@ export async function handleAddSdkCall( throw StorageError.transactionFailed( "Transaction failed while storing SDK_CALL event", - e instanceof Error ? e : new Error(String(e)), + e instanceof Error ? e : new Error(String(e)) ); } } diff --git a/src/storage/adapter/postgres/handlers/priceRequestAiTokenUsage.ts b/src/storage/adapter/postgres/handlers/priceRequestAiTokenUsage.ts index 829b8da..e78aa0a 100644 --- a/src/storage/adapter/postgres/handlers/priceRequestAiTokenUsage.ts +++ b/src/storage/adapter/postgres/handlers/priceRequestAiTokenUsage.ts @@ -11,14 +11,14 @@ import { logger } from "../../../../errors/logger"; const OPERATION = "PriceRequestAiTokenUsage"; export async function handlePriceRequestAiTokenUsage( - event_data: SqlRecord<"REQUEST_AI_TOKEN_USAGE">, + event_data: SqlRecord<"REQUEST_AI_TOKEN_USAGE"> ): Promise { const connectionObject = getPostgresDB(); try { if (!event_data.userId) { throw StorageError.invalidData( - "Missing userId in REQUEST_AI_TOKEN_USAGE event", + "Missing userId in REQUEST_AI_TOKEN_USAGE event" ); } @@ -27,7 +27,7 @@ export async function handlePriceRequestAiTokenUsage( event_data.userId.trim().length === 0 ) { throw StorageError.invalidData( - `Invalid userId format: ${typeof event_data.userId}`, + `Invalid userId format: ${typeof event_data.userId}` ); } @@ -35,7 +35,7 @@ export async function handlePriceRequestAiTokenUsage( OPERATION, "start", "Querying price for REQUEST_AI_TOKEN_USAGE", - { userId: event_data.userId }, + { userId: event_data.userId } ); let result; @@ -43,7 +43,7 @@ export async function handlePriceRequestAiTokenUsage( result = await connectionObject .select({ price: sum( - sql`${aiTokenUsageEventsTable.inputDebitAmount} + ${aiTokenUsageEventsTable.outputDebitAmount}`, + sql`${aiTokenUsageEventsTable.inputDebitAmount} + ${aiTokenUsageEventsTable.outputDebitAmount}` ), }) .from(aiTokenUsageEventsTable) @@ -53,19 +53,19 @@ export async function handlePriceRequestAiTokenUsage( } catch (e) { throw StorageError.queryFailed( `Failed to query REQUEST_AI_TOKEN_USAGE events for user ${event_data.userId}`, - e instanceof Error ? e : new Error(String(e)), + e instanceof Error ? e : new Error(String(e)) ); } if (!result) { throw StorageError.emptyResult( - `Price query returned null for user ${event_data.userId}`, + `Price query returned null for user ${event_data.userId}` ); } if (!Array.isArray(result)) { throw StorageError.queryFailed( - `Query result is not an array for user ${event_data.userId}`, + `Query result is not an array for user ${event_data.userId}` ); } @@ -74,7 +74,7 @@ export async function handlePriceRequestAiTokenUsage( OPERATION, "no_events", "No AI token usage events found, returning 0", - { userId: event_data.userId }, + { userId: event_data.userId } ); return 0; } @@ -86,7 +86,7 @@ export async function handlePriceRequestAiTokenUsage( OPERATION, "null_price", "Price is null/undefined, returning 0", - { userId: event_data.userId }, + { userId: event_data.userId } ); return 0; } @@ -97,14 +97,14 @@ export async function handlePriceRequestAiTokenUsage( } catch (e) { throw StorageError.priceCalculationFailed( event_data.userId, - new Error(`Failed to parse price value: ${priceValue}`), + new Error(`Failed to parse price value: ${priceValue}`) ); } if (isNaN(parsedPrice)) { throw StorageError.priceCalculationFailed( event_data.userId, - new Error(`Price parsed to NaN from value: ${priceValue}`), + new Error(`Price parsed to NaN from value: ${priceValue}`) ); } @@ -119,7 +119,7 @@ export async function handlePriceRequestAiTokenUsage( OPERATION, "completed", "Price calculated successfully", - { userId: event_data.userId, price: parsedPrice }, + { userId: event_data.userId, price: parsedPrice } ); return parsedPrice; @@ -136,7 +136,7 @@ export async function handlePriceRequestAiTokenUsage( throw StorageError.priceCalculationFailed( "Failed to calculate price for REQUEST_AI_TOKEN_USAGE event", - e instanceof Error ? e : new Error(String(e)), + e instanceof Error ? e : new Error(String(e)) ); } } diff --git a/src/storage/adapter/postgres/handlers/priceRequestPayment.ts b/src/storage/adapter/postgres/handlers/priceRequestPayment.ts index 01f4a90..0474a3b 100644 --- a/src/storage/adapter/postgres/handlers/priceRequestPayment.ts +++ b/src/storage/adapter/postgres/handlers/priceRequestPayment.ts @@ -8,7 +8,7 @@ import { logger } from "../../../../errors/logger"; const OPERATION = "PriceRequestPayment"; export async function handlePriceRequestPayment( - event_data: SqlRecord<"REQUEST_PAYMENT">, + event_data: SqlRecord<"REQUEST_PAYMENT"> ): Promise { try { if (!event_data.userId) { @@ -19,7 +19,7 @@ export async function handlePriceRequestPayment( OPERATION, "start", "Calculating price for REQUEST_PAYMENT", - { userId: event_data.userId }, + { userId: event_data.userId } ); // Calculate SDK call price @@ -30,8 +30,8 @@ export async function handlePriceRequestPayment( if (!sdkStorageAdapter) { throw StorageError.unknown( new Error( - "Storage adapter factory returned null or undefined for SDK calls", - ), + "Storage adapter factory returned null or undefined for SDK calls" + ) ); } @@ -40,7 +40,7 @@ export async function handlePriceRequestPayment( if (typeof sdkPrice !== "number" || isNaN(sdkPrice)) { throw StorageError.priceCalculationFailed( event_data.userId, - new Error(`Invalid SDK price value returned: ${sdkPrice}`), + new Error(`Invalid SDK price value returned: ${sdkPrice}`) ); } @@ -48,7 +48,7 @@ export async function handlePriceRequestPayment( OPERATION, "sdk_price_calculated", "SDK call price calculated successfully", - { userId: event_data.userId, sdkPrice }, + { userId: event_data.userId, sdkPrice } ); // Calculate AI token usage price @@ -59,8 +59,8 @@ export async function handlePriceRequestPayment( if (!aiStorageAdapter) { throw StorageError.unknown( new Error( - "Storage adapter factory returned null or undefined for AI token usage", - ), + "Storage adapter factory returned null or undefined for AI token usage" + ) ); } @@ -69,7 +69,7 @@ export async function handlePriceRequestPayment( if (typeof aiPrice !== "number" || isNaN(aiPrice)) { throw StorageError.priceCalculationFailed( event_data.userId, - new Error(`Invalid AI price value returned: ${aiPrice}`), + new Error(`Invalid AI price value returned: ${aiPrice}`) ); } @@ -77,7 +77,7 @@ export async function handlePriceRequestPayment( OPERATION, "ai_price_calculated", "AI token usage price calculated successfully", - { userId: event_data.userId, aiPrice }, + { userId: event_data.userId, aiPrice } ); // Sum both prices @@ -87,7 +87,7 @@ export async function handlePriceRequestPayment( OPERATION, "completed", "Total price calculated successfully", - { userId: event_data.userId, sdkPrice, aiPrice, totalPrice }, + { userId: event_data.userId, sdkPrice, aiPrice, totalPrice } ); return totalPrice; @@ -104,7 +104,7 @@ export async function handlePriceRequestPayment( throw StorageError.priceCalculationFailed( "Failed to calculate price for REQUEST_PAYMENT event", - e instanceof Error ? e : new Error(String(e)), + e instanceof Error ? e : new Error(String(e)) ); } } diff --git a/src/storage/adapter/postgres/handlers/priceRequestSdkCall.ts b/src/storage/adapter/postgres/handlers/priceRequestSdkCall.ts index 1b69af6..515f517 100644 --- a/src/storage/adapter/postgres/handlers/priceRequestSdkCall.ts +++ b/src/storage/adapter/postgres/handlers/priceRequestSdkCall.ts @@ -8,14 +8,14 @@ import { logger } from "../../../../errors/logger"; const OPERATION = "PriceRequestSdkCall"; export async function handlePriceRequestSdkCall( - event_data: SqlRecord<"REQUEST_SDK_CALL">, + event_data: SqlRecord<"REQUEST_SDK_CALL"> ): Promise { const connectionObject = getPostgresDB(); try { if (!event_data.userId) { throw StorageError.invalidData( - "Missing userId in REQUEST_SDK_CALL event", + "Missing userId in REQUEST_SDK_CALL event" ); } @@ -24,7 +24,7 @@ export async function handlePriceRequestSdkCall( event_data.userId.trim().length === 0 ) { throw StorageError.invalidData( - `Invalid userId format: ${typeof event_data.userId}`, + `Invalid userId format: ${typeof event_data.userId}` ); } @@ -32,7 +32,7 @@ export async function handlePriceRequestSdkCall( OPERATION, "start", "Querying price for REQUEST_SDK_CALL", - { userId: event_data.userId }, + { userId: event_data.userId } ); let result; @@ -48,19 +48,19 @@ export async function handlePriceRequestSdkCall( } catch (e) { throw StorageError.queryFailed( `Failed to query SDK_CALL events for user ${event_data.userId}`, - e instanceof Error ? e : new Error(String(e)), + e instanceof Error ? e : new Error(String(e)) ); } if (!result) { throw StorageError.emptyResult( - `Price query returned null for user ${event_data.userId}`, + `Price query returned null for user ${event_data.userId}` ); } if (!Array.isArray(result)) { throw StorageError.queryFailed( - `Query result is not an array for user ${event_data.userId}`, + `Query result is not an array for user ${event_data.userId}` ); } @@ -69,7 +69,7 @@ export async function handlePriceRequestSdkCall( OPERATION, "no_events", "No SDK call events found, returning 0", - { userId: event_data.userId }, + { userId: event_data.userId } ); return 0; } @@ -81,7 +81,7 @@ export async function handlePriceRequestSdkCall( OPERATION, "null_price", "Price is null/undefined, returning 0", - { userId: event_data.userId }, + { userId: event_data.userId } ); return 0; } @@ -92,14 +92,14 @@ export async function handlePriceRequestSdkCall( } catch (e) { throw StorageError.priceCalculationFailed( event_data.userId, - new Error(`Failed to parse price value: ${priceValue}`), + new Error(`Failed to parse price value: ${priceValue}`) ); } if (isNaN(parsedPrice)) { throw StorageError.priceCalculationFailed( event_data.userId, - new Error(`Price parsed to NaN from value: ${priceValue}`), + new Error(`Price parsed to NaN from value: ${priceValue}`) ); } @@ -114,7 +114,7 @@ export async function handlePriceRequestSdkCall( OPERATION, "completed", "Price calculated successfully", - { userId: event_data.userId, price: parsedPrice }, + { userId: event_data.userId, price: parsedPrice } ); return parsedPrice; @@ -131,7 +131,7 @@ export async function handlePriceRequestSdkCall( throw StorageError.priceCalculationFailed( "Failed to calculate price for REQUEST_SDK_CALL event", - e instanceof Error ? e : new Error(String(e)), + e instanceof Error ? e : new Error(String(e)) ); } } diff --git a/src/storage/adapter/postgres/postgres.ts b/src/storage/adapter/postgres/postgres.ts index cf47754..b30c8ce 100644 --- a/src/storage/adapter/postgres/postgres.ts +++ b/src/storage/adapter/postgres/postgres.ts @@ -36,7 +36,7 @@ export class PostgresAdapter implements StorageAdapter { if (!event_data) { throw StorageError.serializationFailed( - "Event serialization returned null or undefined", + "Event serialization returned null or undefined" ); } } catch (e) { @@ -51,7 +51,7 @@ export class PostgresAdapter implements StorageAdapter { } throw StorageError.serializationFailed( "Failed to serialize event data", - e instanceof Error ? e : new Error(String(e)), + e instanceof Error ? e : new Error(String(e)) ); } @@ -93,7 +93,7 @@ export class PostgresAdapter implements StorageAdapter { if (!event_data) { throw StorageError.serializationFailed( - "Event serialization returned null or undefined", + "Event serialization returned null or undefined" ); } } catch (e) { @@ -108,7 +108,7 @@ export class PostgresAdapter implements StorageAdapter { } throw StorageError.serializationFailed( "Failed to serialize event data for price calculation", - e instanceof Error ? e : new Error(String(e)), + e instanceof Error ? e : new Error(String(e)) ); } diff --git a/src/storage/db/postgres/schema.ts b/src/storage/db/postgres/schema.ts index cb44022..6d3aaba 100644 --- a/src/storage/db/postgres/schema.ts +++ b/src/storage/db/postgres/schema.ts @@ -44,7 +44,7 @@ export const apiKeysTable = pgTable( uniqueActiveName: uniqueIndex("unique_active_name") .on(table.name) .where(sql`${table.revoked} = false`), - }), + }) ); export const apiKeysRelation = relations(apiKeysTable, ({ many }) => ({ @@ -101,7 +101,7 @@ export const sdkCallEventsRelation = relations( fields: [sdkCallEventsTable.id], references: [eventsTable.id], }), - }), + }) ); export const paymentEventsTable = pgTable("payment_events", { @@ -118,7 +118,7 @@ export const paymentEventsRelation = relations( fields: [paymentEventsTable.id], references: [eventsTable.id], }), - }), + }) ); export const tagsTable = pgTable("tags", { @@ -145,5 +145,5 @@ export const aiTokenUsageEventsRelation = relations( fields: [aiTokenUsageEventsTable.id], references: [eventsTable.id], }), - }), + }) ); diff --git a/src/utils/apiKeyCache.ts b/src/utils/apiKeyCache.ts index 4cce98b..7a21e1d 100644 --- a/src/utils/apiKeyCache.ts +++ b/src/utils/apiKeyCache.ts @@ -106,7 +106,7 @@ class APIKeyCache { this.cache.delete(oldestKey); logger.logDebug( `Evicted LRU cache entry (cache full at ${this.maxSize})`, - {}, + {} ); } } @@ -131,7 +131,7 @@ class APIKeyCache { if (keysToDelete.length > 0) { logger.logDebug( `Cleaned up ${keysToDelete.length} expired cache entries`, - {}, + {} ); } } diff --git a/src/utils/eventHelpers.ts b/src/utils/eventHelpers.ts index 53c73c2..2a24a5b 100644 --- a/src/utils/eventHelpers.ts +++ b/src/utils/eventHelpers.ts @@ -43,7 +43,7 @@ export async function validateAndParseRegisterEvent(req: RegisterEventRequest) { } throw EventError.validationFailed( "Unknown validation error", - error as Error, + error as Error ); } } @@ -63,7 +63,7 @@ export async function validateAndParseStreamEvent(req: StreamEventRequest) { } throw EventError.validationFailed( "Unknown validation error", - error as Error, + error as Error ); } } @@ -85,7 +85,7 @@ export function createEventInstance(eventSkeleton: { case "REQUEST_AI_TOKEN_USAGE": return new RequestAITokenUsage( eventSkeleton.userId, - eventSkeleton.data, + eventSkeleton.data ); default: throw EventError.unsupportedEventType(eventSkeleton.type); @@ -103,18 +103,18 @@ export function createEventInstance(eventSkeleton: { */ export async function storeEvent( event: Event, - apiKeyId: string, + apiKeyId: string ): Promise { try { const adapter = await StorageAdapterFactory.getStorageAdapter( event, - apiKeyId, + apiKeyId ); await adapter.add(event.serialize()); } catch (error) { throw EventError.serializationError( "Failed to store event", - error as Error, + error as Error ); } } diff --git a/src/utils/generateInitialAPIKey.ts b/src/utils/generateInitialAPIKey.ts index 4e586fa..ce933b4 100644 --- a/src/utils/generateInitialAPIKey.ts +++ b/src/utils/generateInitialAPIKey.ts @@ -5,7 +5,7 @@ const HMAC_SECRET = process.env.HMAC_SECRET; if (!HMAC_SECRET) { console.error( - "Error: HMAC_SECRET environment variable is not set. (check .env.example file)", + "Error: HMAC_SECRET environment variable is not set. (check .env.example file)" ); process.exit(1); } @@ -46,7 +46,7 @@ const apiKeyHash = hashAPIKey(apiKey); const name = "Dashboard Key"; const createdAt = new Date().toISOString(); const expiresAt = new Date( - Date.now() + 365 * 24 * 60 * 60 * 1000, + Date.now() + 365 * 24 * 60 * 60 * 1000 ).toISOString(); // 1 year from now console.log("\n=== Initial API Key Generated ==="); @@ -58,7 +58,7 @@ console.log(` Created At: ${createdAt}`); console.log(` Expires At: ${expiresAt}`); console.log("\n\n=== SQL INSERT Statement ===\n"); console.log( - `INSERT INTO api_keys (id, name, key, created_at, expires_at, revoked, revoked_at)`, + `INSERT INTO api_keys (id, name, key, created_at, expires_at, revoked, revoked_at)` ); console.log(`VALUES (`); console.log(` '${apiKeyId}',`); @@ -74,11 +74,11 @@ console.log(`Authorization: Bearer ${apiKey}`); console.log("\n\n=== IMPORTANT ==="); console.log("1. The key is stored as an HMAC-SHA256 hash in the database"); console.log( - "2. Run the SQL INSERT statement above in your PostgreSQL database", + "2. Run the SQL INSERT statement above in your PostgreSQL database" ); console.log("3. Use the PLAINTEXT API key (above) in the Authorization header"); console.log( - "4. Keep this API key secure - it will be used to generate new API keys", + "4. Keep this API key secure - it will be used to generate new API keys" ); console.log("5. The plaintext key is shown only once - save it now!"); console.log("=================\n"); diff --git a/src/zod/apikey.ts b/src/zod/apikey.ts index 4ee53b2..77a9d55 100644 --- a/src/zod/apikey.ts +++ b/src/zod/apikey.ts @@ -10,13 +10,13 @@ export const createAPIKeySchema = z.object({ .transform((val) => (typeof val === "bigint" ? Number(val) : val)) .refine( (val) => val === Math.floor(val), - "Expiration time must be an integer", + "Expiration time must be an integer" ) .refine((val) => val > 0, "Expiration time must be positive") .refine((val) => val >= 60, "Expiration time must be at least 60 seconds") .refine( (val) => val <= 365 * 24 * 60 * 60, - "Expiration time cannot exceed 1 year", + "Expiration time cannot exceed 1 year" ), }); diff --git a/src/zod/event.ts b/src/zod/event.ts index cd6895c..4d62e65 100644 --- a/src/zod/event.ts +++ b/src/zod/event.ts @@ -22,7 +22,7 @@ const SDKCallEvent = BaseEvent.extend({ z .literal(2) .transform( - () => "MIDDLEWARE_CALL", + () => "MIDDLEWARE_CALL" ) as z.ZodType<"MIDDLEWARE_CALL">, ]), debit: z.union([ @@ -49,7 +49,7 @@ const SDKCallEvent = BaseEvent.extend({ if (!tagRow) { throw EventError.validationFailed( - `Tag not found: ${v.debit.value}`, + `Tag not found: ${v.debit.value}` ); } @@ -119,7 +119,7 @@ const AITokenUsageEvent = BaseEvent.extend({ if (!tagRow) { throw EventError.validationFailed( - `Input tag not found: ${v.inputDebit.value}`, + `Input tag not found: ${v.inputDebit.value}` ); } @@ -146,7 +146,7 @@ const AITokenUsageEvent = BaseEvent.extend({ if (!tagRow) { throw EventError.validationFailed( - `Output tag not found: ${v.outputDebit.value}`, + `Output tag not found: ${v.outputDebit.value}` ); }