diff --git a/bun.lock b/bun.lock index 8942765..8ab4eca 100644 --- a/bun.lock +++ b/bun.lock @@ -1,19 +1,16 @@ { "lockfileVersion": 1, + "configVersion": 0, "workspaces": { "": { "name": "backend", "dependencies": { "@bufbuild/protobuf": "^2.9.0", - "@bufbuild/protoc-gen-connect-es": "^0.13.0", - "@bufbuild/protoc-gen-es": "^2.9.0", "@connectrpc/connect": "^2.1.0", "@connectrpc/connect-node": "^2.1.0", "@connectrpc/validate": "^0.2.0", "@lemonsqueezy/lemonsqueezy.js": "^4.0.0", "@libsql/client": "^0.15.15", - "@types/luxon": "^3.7.1", - "buf": "bufbuild/buf", "dotenv": "^17.2.3", "drizzle-orm": "^0.44.7", "luxon": "^3.7.2", @@ -24,8 +21,12 @@ "zod": "^4.1.12", }, "devDependencies": { + "@bufbuild/protoc-gen-connect-es": "^0.13.0", + "@bufbuild/protoc-gen-es": "^2.9.0", "@types/bun": "latest", + "@types/luxon": "^3.7.1", "@vitest/ui": "^4.0.3", + "buf": "bufbuild/buf", "drizzle-kit": "^0.31.6", "tsx": "^4.20.6", "vitest": "^4.0.3", @@ -238,7 +239,7 @@ "aws-ssl-profiles": ["aws-ssl-profiles@1.1.2", "", {}, "sha512-NZKeq9AfyQvEeNlN0zSYAaWrmBffJh3IELMZfRpJVWgrpEbtEpnjvzqBPf+mxoI287JohRDoa+/nsfqqiZmF6g=="], - "buf": ["buf@github:bufbuild/buf#d500877", {}, "bufbuild-buf-d500877"], + "buf": ["buf@github:bufbuild/buf#2e53c7d", {}, "bufbuild-buf-2e53c7d"], "buffer-from": ["buffer-from@1.1.2", "", {}, "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="], diff --git a/src/storage/adapter/postgres/handlers/index.ts b/src/storage/adapter/postgres/handlers/index.ts index 0e941dc..72639cb 100644 --- a/src/storage/adapter/postgres/handlers/index.ts +++ b/src/storage/adapter/postgres/handlers/index.ts @@ -4,4 +4,4 @@ export { handleAddPayment } from "./addPayment"; export { handlePriceRequestPayment } from "./priceRequestPayment"; export { handlePriceRequestSdkCall } from "./priceRequestSdkCall"; export { handleAddAiTokenUsage } from "./addAiTokenUsage"; -export { handlePriceRequestAiTokenUsage } from "./priceRequestAiTokenUsage"; \ No newline at end of file +export { handlePriceRequestAiTokenUsage } from "./priceRequestAiTokenUsage"; diff --git a/src/storage/db/postgres/schema.ts b/src/storage/db/postgres/schema.ts index 5b38b94..cb44022 100644 --- a/src/storage/db/postgres/schema.ts +++ b/src/storage/db/postgres/schema.ts @@ -1,4 +1,4 @@ -import { relations } from "drizzle-orm"; +import { relations, sql } from "drizzle-orm"; import { integer, pgTable, @@ -6,6 +6,7 @@ import { timestamp, text, boolean, + uniqueIndex, } from "drizzle-orm/pg-core"; import { USER_ID_CONFIG } from "../../../config/identifiers"; @@ -17,26 +18,34 @@ export const usersRelation = relations(usersTable, ({ many }) => ({ events: many(eventsTable), })); -export const apiKeysTable = pgTable("api_keys", { - id: uuid("id").primaryKey().defaultRandom(), - name: text("name").notNull().unique(), - key: text("key").notNull().unique(), - createdAt: timestamp("created_at", { - withTimezone: true, - mode: "string", - }) - .defaultNow() - .notNull(), - expiresAt: timestamp("expires_at", { - withTimezone: true, - mode: "string", - }).notNull(), - revoked: boolean("revoked").default(false).notNull(), - revokedAt: timestamp("revoked_at", { - withTimezone: true, - mode: "string", +export const apiKeysTable = pgTable( + "api_keys", + { + id: uuid("id").primaryKey().defaultRandom(), + name: text("name").notNull(), + key: text("key").notNull().unique(), + createdAt: timestamp("created_at", { + withTimezone: true, + mode: "string", + }) + .defaultNow() + .notNull(), + expiresAt: timestamp("expires_at", { + withTimezone: true, + mode: "string", + }).notNull(), + revoked: boolean("revoked").default(false).notNull(), + revokedAt: timestamp("revoked_at", { + withTimezone: true, + mode: "string", + }), + }, + (table) => ({ + uniqueActiveName: uniqueIndex("unique_active_name") + .on(table.name) + .where(sql`${table.revoked} = false`), }), -}); +); export const apiKeysRelation = relations(apiKeysTable, ({ many }) => ({ events: many(eventsTable),