diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5287d99167..5baa63e6a6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -128,6 +128,9 @@ jobs: - name: Lint run: scripts/lint-all.sh + - name: Drizzle _query enforcement + run: pnpm run drizzle:query-check + format-check: needs: changes runs-on: ${{ vars.RUNNER_DEFAULT_LABEL || 'ubuntu-latest' }} diff --git a/.oxlintrc.json b/.oxlintrc.json index 0b446e6112..96e5174bbf 100644 --- a/.oxlintrc.json +++ b/.oxlintrc.json @@ -119,7 +119,11 @@ "@next/next/no-head-import-in-document": "error", "@next/next/no-script-component-in-head": "error", "drizzle/enforce-delete-with-where": ["error", { "drizzleObjectName": ["db", "ctx.db"] }], - "drizzle/enforce-update-with-where": ["error", { "drizzleObjectName": ["db", "ctx.db"] }] + "drizzle/enforce-update-with-where": ["error", { "drizzleObjectName": ["db", "ctx.db"] }], + "drizzle/prefer-underscore-query": [ + "error", + { "drizzleObjectName": ["db", "ctx.db", "this.db", "tx", "trx"] } + ] }, "overrides": [ { diff --git a/apps/web/src/app/admin/api/users/add-credit/route.ts b/apps/web/src/app/admin/api/users/add-credit/route.ts index 6e851ddea4..918f09182e 100644 --- a/apps/web/src/app/admin/api/users/add-credit/route.ts +++ b/apps/web/src/app/admin/api/users/add-credit/route.ts @@ -24,7 +24,7 @@ export async function POST( return warnAndCreateErrorResponse('Invalid email parameter'); } - const user = await db.query.kilocode_users.findFirst({ + const user = await db._query.kilocode_users.findFirst({ where: eq(kilocode_users.google_user_email, email), }); diff --git a/apps/web/src/app/admin/api/users/credit-transactions/route.ts b/apps/web/src/app/admin/api/users/credit-transactions/route.ts index 21c434c06a..6312d76237 100644 --- a/apps/web/src/app/admin/api/users/credit-transactions/route.ts +++ b/apps/web/src/app/admin/api/users/credit-transactions/route.ts @@ -20,7 +20,7 @@ export async function GET( if (!kilo_user_id) throw new Error('kilo_user_id is required'); - const transactions = await db.query.credit_transactions.findMany({ + const transactions = await db._query.credit_transactions.findMany({ where: and( eq(credit_transactions.kilo_user_id, kilo_user_id), isNull(credit_transactions.organization_id) diff --git a/apps/web/src/app/admin/api/users/payment-methods/route.ts b/apps/web/src/app/admin/api/users/payment-methods/route.ts index 5fa0d2d217..5fdd4e1394 100644 --- a/apps/web/src/app/admin/api/users/payment-methods/route.ts +++ b/apps/web/src/app/admin/api/users/payment-methods/route.ts @@ -18,7 +18,7 @@ export async function GET( if (!kilo_user_id) throw new Error('kilo_user_id is required'); - const methods = await db.query.payment_methods.findMany({ + const methods = await db._query.payment_methods.findMany({ where: eq(payment_methods.user_id, kilo_user_id), orderBy: desc(payment_methods.created_at), }); diff --git a/apps/web/src/app/admin/api/users/route.ts b/apps/web/src/app/admin/api/users/route.ts index 4e7d9b5ff1..cdbdd54c76 100644 --- a/apps/web/src/app/admin/api/users/route.ts +++ b/apps/web/src/app/admin/api/users/route.ts @@ -176,7 +176,7 @@ export async function GET( const orderFunction = sortOrder === 'asc' ? asc : desc; const orderCondition = orderFunction(kilocode_users[sortField]); - const users = await db.query.kilocode_users.findMany({ + const users = await db._query.kilocode_users.findMany({ where: whereCondition, orderBy: orderCondition, limit: limit, @@ -196,7 +196,7 @@ export async function GET( const notes = userIds.length <= 0 ? [] - : await db.query.user_admin_notes.findMany({ + : await db._query.user_admin_notes.findMany({ where: inArray(user_admin_notes.kilo_user_id, userIds), orderBy: desc(user_admin_notes.created_at), }); diff --git a/apps/web/src/app/admin/organizations/[id]/webhooks/page.tsx b/apps/web/src/app/admin/organizations/[id]/webhooks/page.tsx index 16e8ae23e5..3ee84e5f1d 100644 --- a/apps/web/src/app/admin/organizations/[id]/webhooks/page.tsx +++ b/apps/web/src/app/admin/organizations/[id]/webhooks/page.tsx @@ -18,7 +18,7 @@ export default async function AdminOrganizationWebhooksPage({ const { id } = await params; const organizationId = decodeURIComponent(id); - const organization = await db.query.organizations.findFirst({ + const organization = await db._query.organizations.findFirst({ columns: { id: true, name: true, diff --git a/apps/web/src/app/admin/users/[id]/page.tsx b/apps/web/src/app/admin/users/[id]/page.tsx index 4f124f56f6..e8cb2ca2fe 100644 --- a/apps/web/src/app/admin/users/[id]/page.tsx +++ b/apps/web/src/app/admin/users/[id]/page.tsx @@ -27,7 +27,7 @@ async function getUserData(userId: string): Promise { return null; } - const notes = await db.query.user_admin_notes.findMany({ + const notes = await db._query.user_admin_notes.findMany({ where: eq(user_admin_notes.kilo_user_id, userId), orderBy: desc(user_admin_notes.created_at), }); @@ -36,7 +36,7 @@ async function getUserData(userId: string): Promise { const admins = adminIds.length > 0 - ? await db.query.kilocode_users.findMany({ + ? await db._query.kilocode_users.findMany({ where: inArray(kilocode_users.id, adminIds), limit: 50, }) @@ -68,7 +68,7 @@ async function getUserData(userId: string): Promise { // Fetch auto-top-up config const autoTopUpConfig = - (await db.query.auto_top_up_configs.findFirst({ + (await db._query.auto_top_up_configs.findFirst({ where: eq(auto_top_up_configs.owned_by_user_id, userId), })) ?? null; diff --git a/apps/web/src/app/admin/users/[id]/webhooks/page.tsx b/apps/web/src/app/admin/users/[id]/webhooks/page.tsx index 3a2735e871..2dcf6793b9 100644 --- a/apps/web/src/app/admin/users/[id]/webhooks/page.tsx +++ b/apps/web/src/app/admin/users/[id]/webhooks/page.tsx @@ -18,7 +18,7 @@ export default async function AdminUserWebhooksPage({ const { id } = await params; const userId = decodeURIComponent(id); - const user = await db.query.kilocode_users.findFirst({ + const user = await db._query.kilocode_users.findFirst({ columns: { id: true, google_user_email: true, diff --git a/apps/web/src/app/api/cron/deployment-threat-scan/route.ts b/apps/web/src/app/api/cron/deployment-threat-scan/route.ts index b085a693f0..e9e5f483a7 100644 --- a/apps/web/src/app/api/cron/deployment-threat-scan/route.ts +++ b/apps/web/src/app/api/cron/deployment-threat-scan/route.ts @@ -38,7 +38,7 @@ export async function GET(request: Request) { // Get deployments pending scan, oldest first (by last_deployed_at) // Uses partial index idx_deployments_threat_status_pending for efficient queries - const pendingDeployments = await db.query.deployments.findMany({ + const pendingDeployments = await db._query.deployments.findMany({ where: eq(deployments.threat_status, 'pending_scan'), orderBy: asc(deployments.last_deployed_at), limit: 25, diff --git a/apps/web/src/app/api/dev/create-kilocode-org/route.ts b/apps/web/src/app/api/dev/create-kilocode-org/route.ts index f55c14afb7..a662011961 100644 --- a/apps/web/src/app/api/dev/create-kilocode-org/route.ts +++ b/apps/web/src/app/api/dev/create-kilocode-org/route.ts @@ -115,7 +115,7 @@ export async function POST(_request: NextRequest): Promise { console.log('[DEV CREATE KILOCODE ORG] Stripe customer ID created'); // Verify membership was created - const newMembership = await db.query.organization_memberships.findFirst({ + const newMembership = await db._query.organization_memberships.findFirst({ where: and( eq(organization_memberships.organization_id, DEV_ORG_ID), eq(organization_memberships.kilo_user_id, user.id) diff --git a/apps/web/src/app/api/up/route.ts b/apps/web/src/app/api/up/route.ts index d286448301..485d136615 100644 --- a/apps/web/src/app/api/up/route.ts +++ b/apps/web/src/app/api/up/route.ts @@ -12,7 +12,7 @@ export async function GET(): Promise< recentAIActivity: false, }; try { - const db_usage_shows_recent_llm_usage = await db.query.microdollar_usage.findFirst({ + const db_usage_shows_recent_llm_usage = await db._query.microdollar_usage.findFirst({ columns: { id: true }, where: and( gte(microdollar_usage.created_at, sql`NOW() - INTERVAL '5 minutes'`), diff --git a/apps/web/src/app/api/user-deployments/webhook/route.ts b/apps/web/src/app/api/user-deployments/webhook/route.ts index 80ee9c74a9..f8c0f6332d 100644 --- a/apps/web/src/app/api/user-deployments/webhook/route.ts +++ b/apps/web/src/app/api/user-deployments/webhook/route.ts @@ -128,7 +128,7 @@ async function resolveRecipientEmails(deployment: { } async function sendDeploymentFailureNotification(deploymentId: string) { - const deployment = await db.query.deployments.findFirst({ + const deployment = await db._query.deployments.findFirst({ where: eq(deployments.id, deploymentId), }); diff --git a/apps/web/src/app/payments/topup/success/actions.tsx b/apps/web/src/app/payments/topup/success/actions.tsx index f68d983b7c..4b3b6d2472 100644 --- a/apps/web/src/app/payments/topup/success/actions.tsx +++ b/apps/web/src/app/payments/topup/success/actions.tsx @@ -33,7 +33,7 @@ export async function fetchCreditTransactionIdForStripeSession(sessionId: string } // Note: This is a bit ugly, because for some reason we sometimes store py_ ids (charges), and sometimes pi_ ids (payment intents) - const creditTransaction = await db.query.credit_transactions.findFirst({ + const creditTransaction = await db._query.credit_transactions.findFirst({ where: inArray(credit_transactions.stripe_payment_id, [ paymentIntent.id, paymentIntent.latest_charge as string, diff --git a/apps/web/src/lib/admin-utils-serverside.ts b/apps/web/src/lib/admin-utils-serverside.ts index 3f3afd887a..4e118c710d 100644 --- a/apps/web/src/lib/admin-utils-serverside.ts +++ b/apps/web/src/lib/admin-utils-serverside.ts @@ -25,7 +25,7 @@ export const describePaymentMethods = ( }; export async function getPaymentStatusByUserIds(userIds: string[]) { - const paymentMethodsData = await db.query.payment_methods.findMany({ + const paymentMethodsData = await db._query.payment_methods.findMany({ where: inArray(payment_methods.user_id, userIds), }); @@ -33,7 +33,7 @@ export async function getPaymentStatusByUserIds(userIds: string[]) { } export async function hasPaymentMethod(userId: string): Promise { - const result = await db.query.payment_methods.findFirst({ + const result = await db._query.payment_methods.findFirst({ columns: { id: true }, where: and(eq(payment_methods.user_id, userId), isNull(payment_methods.deleted_at)), }); diff --git a/apps/web/src/lib/affiliate-attribution.ts b/apps/web/src/lib/affiliate-attribution.ts index 4d43cf4352..59dcc3e05d 100644 --- a/apps/web/src/lib/affiliate-attribution.ts +++ b/apps/web/src/lib/affiliate-attribution.ts @@ -48,7 +48,7 @@ export async function recordAffiliateAttribution(params: { } export async function getAffiliateAttribution(userId: string, provider: AffiliateProvider) { - return await db.query.user_affiliate_attributions.findFirst({ + return await db._query.user_affiliate_attributions.findFirst({ where: and( eq(user_affiliate_attributions.user_id, userId), eq(user_affiliate_attributions.provider, provider) diff --git a/apps/web/src/lib/affiliate-events.ts b/apps/web/src/lib/affiliate-events.ts index 3a7b439bab..bb99352e24 100644 --- a/apps/web/src/lib/affiliate-events.ts +++ b/apps/web/src/lib/affiliate-events.ts @@ -263,7 +263,7 @@ async function getEventByDedupeKey( database: DatabaseClient, dedupeKey: string ): Promise { - const event = await database.query.user_affiliate_events.findFirst({ + const event = await database._query.user_affiliate_events.findFirst({ where: eq(user_affiliate_events.dedupe_key, dedupeKey), }); @@ -701,7 +701,7 @@ async function getAffiliateEventById( database: DatabaseClient, eventId: string ): Promise { - const event = await database.query.user_affiliate_events.findFirst({ + const event = await database._query.user_affiliate_events.findFirst({ where: eq(user_affiliate_events.id, eventId), }); @@ -1054,7 +1054,7 @@ async function persistPendingSaleReversal( async function reconcilePendingSaleReversals( database: DatabaseClient ): Promise<{ materialized: number }> { - const pendingRows = await database.query.pending_impact_sale_reversals.findMany(); + const pendingRows = await database._query.pending_impact_sale_reversals.findMany(); let materialized = 0; for (const pending of pendingRows) { diff --git a/apps/web/src/lib/ai-gateway/processUsage.test.ts b/apps/web/src/lib/ai-gateway/processUsage.test.ts index 9e91d8a83f..aefba10682 100644 --- a/apps/web/src/lib/ai-gateway/processUsage.test.ts +++ b/apps/web/src/lib/ai-gateway/processUsage.test.ts @@ -402,12 +402,12 @@ describe('logMicrodollarUsage', () => { const updatedUser = await findUserById('test-log-user-1'); expect(updatedUser?.microdollars_used).toBe(1500); // 1000 + 500 - const metadataRecord = await db.query.microdollar_usage_metadata.findFirst({ + const metadataRecord = await db._query.microdollar_usage_metadata.findFirst({ where: eq(microdollar_usage_metadata.message_id, 'test-msg-123'), }); expect(metadataRecord).toBeTruthy(); - const usageRecord = await db.query.microdollar_usage.findFirst({ + const usageRecord = await db._query.microdollar_usage.findFirst({ where: eq(microdollar_usage.id, metadataRecord!.id), }); expect(usageRecord).toBeTruthy(); @@ -448,7 +448,7 @@ describe('logMicrodollarUsage', () => { await logMicrodollarUsage(usageStats, usageContext); - const metadataRecord = await db.query.microdollar_usage_metadata.findFirst({ + const metadataRecord = await db._query.microdollar_usage_metadata.findFirst({ where: eq(microdollar_usage_metadata.message_id, 'test-msg-session'), }); expect(metadataRecord).toBeTruthy(); @@ -488,12 +488,12 @@ describe('logMicrodollarUsage', () => { const updatedUser = await findUserById('test-log-user-2'); expect(updatedUser?.microdollars_used).toBe(2000); // unchanged - const metadataRecord = await db.query.microdollar_usage_metadata.findFirst({ + const metadataRecord = await db._query.microdollar_usage_metadata.findFirst({ where: eq(microdollar_usage_metadata.message_id, 'test-msg-456'), }); expect(metadataRecord).toBeTruthy(); - const usageRecord = await db.query.microdollar_usage.findFirst({ + const usageRecord = await db._query.microdollar_usage.findFirst({ where: eq(microdollar_usage.id, metadataRecord!.id), }); expect(usageRecord).toBeTruthy(); @@ -578,7 +578,7 @@ describe('logMicrodollarUsage', () => { expect(updatedUser?.microdollars_used).toBe(4200); // 3000 + 300 + 400 + 500 // Verify all 3 usage records exist - const usageRecords = await db.query.microdollar_usage.findMany({ + const usageRecords = await db._query.microdollar_usage.findMany({ where: eq(microdollar_usage.kilo_user_id, 'test-dedup-user'), }); expect(usageRecords).toHaveLength(3); @@ -650,13 +650,13 @@ describe('logMicrodollarUsage', () => { await logMicrodollarUsage(usageStats, usageContext); - const metadataRecord = await db.query.microdollar_usage_metadata.findFirst({ + const metadataRecord = await db._query.microdollar_usage_metadata.findFirst({ where: eq(microdollar_usage_metadata.message_id, 'test-org-msg-123'), }); expect(metadataRecord).toBeTruthy(); - const usageRecord = await db.query.microdollar_usage.findFirst({ + const usageRecord = await db._query.microdollar_usage.findFirst({ where: eq(microdollar_usage.id, metadataRecord!.id), }); diff --git a/apps/web/src/lib/ai-gateway/processUsage.ts b/apps/web/src/lib/ai-gateway/processUsage.ts index d001dd753f..bcbf8c7b65 100644 --- a/apps/web/src/lib/ai-gateway/processUsage.ts +++ b/apps/web/src/lib/ai-gateway/processUsage.ts @@ -285,7 +285,7 @@ async function isFirstUsage( ): Promise { if (prior_microdollar_usage || usage.organization_id) return false; //perf: we only pay the costs for querying prior microdollar usage for non-org users that have incurred zero cost so far. - return !(await db.query.microdollar_usage.findFirst({ + return !(await db._query.microdollar_usage.findFirst({ where: eq(microdollar_usage.kilo_user_id, usage.kilo_user_id), columns: { created_at: true }, })); diff --git a/apps/web/src/lib/autoTopUp.test.ts b/apps/web/src/lib/autoTopUp.test.ts index 4ca9424f23..e3f64cfb43 100644 --- a/apps/web/src/lib/autoTopUp.test.ts +++ b/apps/web/src/lib/autoTopUp.test.ts @@ -134,7 +134,7 @@ describe('autoTopUp', () => { await maybePerformAutoTopUp(user); // Verify no config was created - const config = await db.query.auto_top_up_configs.findFirst({ + const config = await db._query.auto_top_up_configs.findFirst({ where: eq(auto_top_up_configs.owned_by_user_id, testUser.id), }); expect(config).toBeUndefined(); @@ -152,7 +152,7 @@ describe('autoTopUp', () => { await maybePerformAutoTopUp(user); // Verify no config was created (no lock acquired) - const config = await db.query.auto_top_up_configs.findFirst({ + const config = await db._query.auto_top_up_configs.findFirst({ where: eq(auto_top_up_configs.owned_by_user_id, testUser.id), }); expect(config).toBeUndefined(); @@ -175,7 +175,7 @@ describe('autoTopUp', () => { await maybePerformAutoTopUp(user); // Verify auto_top_up_enabled was set to false - const updatedUser = await db.query.kilocode_users.findFirst({ + const updatedUser = await db._query.kilocode_users.findFirst({ where: eq(kilocode_users.id, testUser.id), }); expect(updatedUser?.auto_top_up_enabled).toBe(false); @@ -206,7 +206,7 @@ describe('autoTopUp', () => { await maybePerformAutoTopUp(user); // Verify the lock is still held (attempt_started_at not cleared) - const config = await db.query.auto_top_up_configs.findFirst({ + const config = await db._query.auto_top_up_configs.findFirst({ where: eq(auto_top_up_configs.owned_by_user_id, testUser.id), }); expect(config?.attempt_started_at).not.toBeNull(); @@ -254,13 +254,13 @@ describe('autoTopUp', () => { await maybePerformAutoTopUp(user); // Verify lock was released - const config = await db.query.auto_top_up_configs.findFirst({ + const config = await db._query.auto_top_up_configs.findFirst({ where: eq(auto_top_up_configs.owned_by_user_id, testUser.id), }); expect(config?.attempt_started_at).toBeNull(); // Verify auto-top-up is still enabled (not disabled) - const updatedUser = await db.query.kilocode_users.findFirst({ + const updatedUser = await db._query.kilocode_users.findFirst({ where: eq(kilocode_users.id, testUser.id), }); expect(updatedUser?.auto_top_up_enabled).toBe(true); @@ -292,7 +292,7 @@ describe('autoTopUp', () => { await maybePerformOrganizationAutoTopUp(org); // Verify no config was created - const config = await db.query.auto_top_up_configs.findFirst({ + const config = await db._query.auto_top_up_configs.findFirst({ where: eq(auto_top_up_configs.owned_by_organization_id, testOrg.id), }); expect(config).toBeUndefined(); @@ -310,7 +310,7 @@ describe('autoTopUp', () => { await maybePerformOrganizationAutoTopUp(org); // Verify no config was created (no lock acquired) - const config = await db.query.auto_top_up_configs.findFirst({ + const config = await db._query.auto_top_up_configs.findFirst({ where: eq(auto_top_up_configs.owned_by_organization_id, testOrg.id), }); expect(config).toBeUndefined(); @@ -333,7 +333,7 @@ describe('autoTopUp', () => { await maybePerformOrganizationAutoTopUp(org); // Verify auto_top_up_enabled was set to false - const updatedOrg = await db.query.organizations.findFirst({ + const updatedOrg = await db._query.organizations.findFirst({ where: eq(organizations.id, testOrg.id), }); expect(updatedOrg?.auto_top_up_enabled).toBe(false); @@ -364,7 +364,7 @@ describe('autoTopUp', () => { await maybePerformOrganizationAutoTopUp(org); // Verify the lock is still held (attempt_started_at not cleared) - const config = await db.query.auto_top_up_configs.findFirst({ + const config = await db._query.auto_top_up_configs.findFirst({ where: eq(auto_top_up_configs.owned_by_organization_id, testOrg.id), }); expect(config?.attempt_started_at).not.toBeNull(); @@ -400,13 +400,13 @@ describe('autoTopUp', () => { await maybePerformOrganizationAutoTopUp(org); // Verify auto_top_up_enabled was set to false - const updatedOrg = await db.query.organizations.findFirst({ + const updatedOrg = await db._query.organizations.findFirst({ where: eq(organizations.id, testOrg.id), }); expect(updatedOrg?.auto_top_up_enabled).toBe(false); // Verify disabled_reason was set - const config = await db.query.auto_top_up_configs.findFirst({ + const config = await db._query.auto_top_up_configs.findFirst({ where: eq(auto_top_up_configs.owned_by_organization_id, testOrg.id), }); expect(config?.disabled_reason).toBe('no_stripe_customer'); @@ -449,13 +449,13 @@ describe('autoTopUp', () => { await maybePerformOrganizationAutoTopUp(org); // Verify lock was released - const config = await db.query.auto_top_up_configs.findFirst({ + const config = await db._query.auto_top_up_configs.findFirst({ where: eq(auto_top_up_configs.owned_by_organization_id, testOrg.id), }); expect(config?.attempt_started_at).toBeNull(); // Verify auto-top-up is still enabled (not disabled) - const updatedOrg = await db.query.organizations.findFirst({ + const updatedOrg = await db._query.organizations.findFirst({ where: eq(organizations.id, testOrg.id), }); expect(updatedOrg?.auto_top_up_enabled).toBe(true); @@ -491,7 +491,7 @@ describe('autoTopUp', () => { await maybePerformOrganizationAutoTopUp(org); // Should have attempted (and failed due to no config), disabling auto-top-up - const updatedOrg = await db.query.organizations.findFirst({ + const updatedOrg = await db._query.organizations.findFirst({ where: eq(organizations.id, testOrg.id), }); expect(updatedOrg?.auto_top_up_enabled).toBe(false); @@ -516,7 +516,7 @@ describe('autoTopUp', () => { await maybePerformOrganizationAutoTopUp(org); // Should NOT have attempted - auto_top_up_enabled should still be true - const updatedOrg = await db.query.organizations.findFirst({ + const updatedOrg = await db._query.organizations.findFirst({ where: eq(organizations.id, testOrg.id), }); expect(updatedOrg?.auto_top_up_enabled).toBe(true); diff --git a/apps/web/src/lib/autoTopUp.ts b/apps/web/src/lib/autoTopUp.ts index bcdf6fe584..21e78b98aa 100644 --- a/apps/web/src/lib/autoTopUp.ts +++ b/apps/web/src/lib/autoTopUp.ts @@ -65,7 +65,7 @@ async function shouldWaitForKiloPassBonusCredits(kiloUserId: string): Promise { userId: testUser.id, }); - const storedReview = await db.query.cloud_agent_code_reviews.findFirst({ + const storedReview = await db._query.cloud_agent_code_reviews.findFirst({ where: eq(cloud_agent_code_reviews.id, review.id), }); @@ -538,7 +538,7 @@ describe('tryDispatchPendingReviews', () => { userId: testUser.id, }); - const storedReview = await db.query.cloud_agent_code_reviews.findFirst({ + const storedReview = await db._query.cloud_agent_code_reviews.findFirst({ where: eq(cloud_agent_code_reviews.id, review.id), }); @@ -580,7 +580,7 @@ describe('tryDispatchPendingReviews', () => { userId: testUser.id, }); - const storedReview = await db.query.cloud_agent_code_reviews.findFirst({ + const storedReview = await db._query.cloud_agent_code_reviews.findFirst({ where: eq(cloud_agent_code_reviews.id, review.id), }); diff --git a/apps/web/src/lib/contributor-champions/service.test.ts b/apps/web/src/lib/contributor-champions/service.test.ts index 663b61ffad..a62229262b 100644 --- a/apps/web/src/lib/contributor-champions/service.test.ts +++ b/apps/web/src/lib/contributor-champions/service.test.ts @@ -220,7 +220,7 @@ describe('contributor champions service', () => { const enrollmentResult = await enrollContributorChampion({ contributorId, tier: null }); expect(enrollmentResult.enrolledTier).toBe('champion'); - const membership = await db.query.contributor_champion_memberships.findFirst({ + const membership = await db._query.contributor_champion_memberships.findFirst({ where: eq(contributor_champion_memberships.contributor_id, contributorId), }); expect(membership?.selected_tier).toBe('champion'); @@ -500,17 +500,17 @@ describe('contributor champions service', () => { expect(result.upgrades[0]?.fromTier).toBe('contributor'); expect(result.upgrades[0]?.toTier).toBe('ambassador'); - const membership = await db.query.contributor_champion_memberships.findFirst({ + const membership = await db._query.contributor_champion_memberships.findFirst({ where: eq(contributor_champion_memberships.contributor_id, contributorId), }); expect(membership?.enrolled_tier).toBe('ambassador'); - const championMembership = await db.query.contributor_champion_memberships.findFirst({ + const championMembership = await db._query.contributor_champion_memberships.findFirst({ where: eq(contributor_champion_memberships.contributor_id, alreadyChampionId), }); expect(championMembership?.enrolled_tier).toBe('champion'); - const staysMembership = await db.query.contributor_champion_memberships.findFirst({ + const staysMembership = await db._query.contributor_champion_memberships.findFirst({ where: eq(contributor_champion_memberships.contributor_id, staysContributorId), }); expect(staysMembership?.enrolled_tier).toBe('contributor'); @@ -561,7 +561,7 @@ describe('contributor champions service', () => { }) ); - const membership = await db.query.contributor_champion_memberships.findFirst({ + const membership = await db._query.contributor_champion_memberships.findFirst({ where: eq(contributor_champion_memberships.contributor_id, contributorId), }); expect(membership?.credits_last_granted_at).not.toBeNull(); @@ -633,7 +633,7 @@ describe('contributor champions service', () => { }) ); - const contributor = await db.query.contributor_champion_contributors.findFirst({ + const contributor = await db._query.contributor_champion_contributors.findFirst({ where: eq(contributor_champion_contributors.github_login, 'manual-user'), }); expect(contributor).toBeTruthy(); @@ -657,7 +657,7 @@ describe('contributor champions service', () => { kiloUserId: user.id, }); - const contributor = await db.query.contributor_champion_contributors.findFirst({ + const contributor = await db._query.contributor_champion_contributors.findFirst({ where: eq(contributor_champion_contributors.github_login, 'remanual-user'), }); const grantedAt = daysAgo(10); @@ -675,7 +675,7 @@ describe('contributor champions service', () => { kiloUserId: user.id, }); - const membership = await db.query.contributor_champion_memberships.findFirst({ + const membership = await db._query.contributor_champion_memberships.findFirst({ where: eq(contributor_champion_memberships.contributor_id, contributor!.id), }); expect(membership?.enrolled_tier).toBe('contributor'); diff --git a/apps/web/src/lib/contributor-champions/service.ts b/apps/web/src/lib/contributor-champions/service.ts index 828dcb939d..cdba4b07e8 100644 --- a/apps/web/src/lib/contributor-champions/service.ts +++ b/apps/web/src/lib/contributor-champions/service.ts @@ -259,7 +259,7 @@ async function mapWithConcurrencyLimit( } async function getCurrentSyncCheckpoint(): Promise { - const row = await db.query.contributor_champion_sync_state.findFirst({ + const row = await db._query.contributor_champion_sync_state.findFirst({ where: eq(contributor_champion_sync_state.repo_full_name, REPO_FULL_NAME), columns: { last_merged_at: true, diff --git a/apps/web/src/lib/creditExpiration.test.ts b/apps/web/src/lib/creditExpiration.test.ts index 4e1d09cbab..7ff9858251 100644 --- a/apps/web/src/lib/creditExpiration.test.ts +++ b/apps/web/src/lib/creditExpiration.test.ts @@ -539,7 +539,7 @@ describe('processLocalExpirations', () => { await processLocalExpirations(user, now); // Get updated next_credit_expiration_at - const updatedUser = await db.query.kilocode_users.findFirst({ + const updatedUser = await db._query.kilocode_users.findFirst({ where: eq(kilocode_users.id, user.id), columns: { next_credit_expiration_at: true }, }); @@ -644,7 +644,7 @@ describe('processLocalExpirations', () => { credit_expiry_date: expiry1, }); - const userAfter1 = await db.query.kilocode_users.findFirst({ + const userAfter1 = await db._query.kilocode_users.findFirst({ where: eq(kilocode_users.id, user.id), }); expect(new Date(userAfter1!.next_credit_expiration_at!).getTime()).toBe(expiry1.getTime()); @@ -659,7 +659,7 @@ describe('processLocalExpirations', () => { credit_expiry_date: expiry2, }); - const userAfter2 = await db.query.kilocode_users.findFirst({ + const userAfter2 = await db._query.kilocode_users.findFirst({ where: eq(kilocode_users.id, user.id), }); expect(new Date(userAfter2!.next_credit_expiration_at!).getTime()).toBe(expiry2.getTime()); @@ -674,7 +674,7 @@ describe('processLocalExpirations', () => { credit_expiry_date: expiry3, }); - const userAfter3 = await db.query.kilocode_users.findFirst({ + const userAfter3 = await db._query.kilocode_users.findFirst({ where: eq(kilocode_users.id, user.id), }); expect(new Date(userAfter3!.next_credit_expiration_at!).getTime()).toBe(expiry2.getTime()); @@ -711,13 +711,13 @@ describe('processLocalExpirations', () => { expect(resultA.success).toBe(true); // Verify grantCreditForCategory set next_credit_expiration_at - const userAfterA = await db.query.kilocode_users.findFirst({ + const userAfterA = await db._query.kilocode_users.findFirst({ where: eq(kilocode_users.id, user.id), }); expect(new Date(userAfterA!.next_credit_expiration_at!).getTime()).toBe(expiryA.getTime()); // Verify A was created with correct original_baseline - const txnA = await db.query.credit_transactions.findFirst({ + const txnA = await db._query.credit_transactions.findFirst({ where: eq(creditTransactionsTable.description, 'Credits A'), }); expect(txnA).toBeDefined(); @@ -731,7 +731,7 @@ describe('processLocalExpirations', () => { .where(eq(kilocode_users.id, user.id)); // Refetch user for next grant - const userAfterUsage1 = await db.query.kilocode_users.findFirst({ + const userAfterUsage1 = await db._query.kilocode_users.findFirst({ where: eq(kilocode_users.id, user.id), }); @@ -747,7 +747,7 @@ describe('processLocalExpirations', () => { expect(resultB.success).toBe(true); // Verify B was created with correct original_baseline - const txnB = await db.query.credit_transactions.findFirst({ + const txnB = await db._query.credit_transactions.findFirst({ where: eq(creditTransactionsTable.description, 'Credits B'), }); expect(txnB).toBeDefined(); @@ -761,7 +761,7 @@ describe('processLocalExpirations', () => { .where(eq(kilocode_users.id, user.id)); // Step 6: Process expiration at Jan 15 (A expires) - const userAtJan15 = await db.query.kilocode_users.findFirst({ + const userAtJan15 = await db._query.kilocode_users.findFirst({ where: eq(kilocode_users.id, user.id), }); const jan15 = new Date('2024-01-15T00:00:00Z'); @@ -799,7 +799,7 @@ describe('processLocalExpirations', () => { .where(eq(kilocode_users.id, user.id)); // Step 8: Process expiration at Jan 25 (B expires) - const userAtJan25 = await db.query.kilocode_users.findFirst({ + const userAtJan25 = await db._query.kilocode_users.findFirst({ where: eq(kilocode_users.id, user.id), }); // Verify next_credit_expiration_at was updated to B's expiry after A expired @@ -873,7 +873,7 @@ describe('processLocalExpirations', () => { expect(expirationTxns[0].original_transaction_id).toBe(initialId); // Verify user balance is unchanged (zero-amount expiration) - const updatedUser = await db.query.kilocode_users.findFirst({ + const updatedUser = await db._query.kilocode_users.findFirst({ where: eq(kilocode_users.id, user.id), }); diff --git a/apps/web/src/lib/creditExpirationOrg.test.ts b/apps/web/src/lib/creditExpirationOrg.test.ts index 9a361b316f..5e55d8a9f9 100644 --- a/apps/web/src/lib/creditExpirationOrg.test.ts +++ b/apps/web/src/lib/creditExpirationOrg.test.ts @@ -17,7 +17,7 @@ async function createTestOrg( if (Object.keys(overrides).length > 0) { await db.update(organizations).set(overrides).where(eq(organizations.id, org.id)); } - return await db.query.organizations.findFirst({ where: eq(organizations.id, org.id) }); + return await db._query.organizations.findFirst({ where: eq(organizations.id, org.id) }); } describe('fetchExpiringTransactionsForOrganization', () => { @@ -203,7 +203,7 @@ describe('processOrganizationExpirations', () => { expect(expirations[0].kilo_user_id).toBe('system'); // Verify org columns updated - const updatedOrg = await db.query.organizations.findFirst({ + const updatedOrg = await db._query.organizations.findFirst({ where: eq(organizations.id, orgId), }); expect(updatedOrg!.total_microdollars_acquired).toBe(3_000_000); @@ -245,7 +245,7 @@ describe('processOrganizationExpirations', () => { new Date('2024-01-15T00:00:00Z') ); - const updatedOrg = await db.query.organizations.findFirst({ + const updatedOrg = await db._query.organizations.findFirst({ where: eq(organizations.id, orgId), }); expect(new Date(updatedOrg!.next_credit_expiration_at!).toISOString()).toBe( @@ -302,7 +302,7 @@ describe('processOrganizationExpirations', () => { expect(result1).not.toBeNull(); // Re-fetch org for second call - const updatedOrg = await db.query.organizations.findFirst({ + const updatedOrg = await db._query.organizations.findFirst({ where: eq(organizations.id, orgId), }); const result2 = await processOrganizationExpirations( diff --git a/apps/web/src/lib/creditTransactions.ts b/apps/web/src/lib/creditTransactions.ts index 88e1ac9713..ff54cb5264 100644 --- a/apps/web/src/lib/creditTransactions.ts +++ b/apps/web/src/lib/creditTransactions.ts @@ -67,7 +67,7 @@ export async function summarizeUserPayments(kiloUserId: string, fromDb: typeof d } export async function getCreditTransactionsForOrganization(organizationId: Organization['id']) { - const res = await db.query.credit_transactions.findMany({ + const res = await db._query.credit_transactions.findMany({ where: eq(credit_transactions.organization_id, organizationId), orderBy: desc(credit_transactions.created_at), limit: 100, @@ -76,7 +76,7 @@ export async function getCreditTransactionsForOrganization(organizationId: Organ } export async function hasUserEverPaid(kiloUserId: string): Promise { - const result = await db.query.credit_transactions.findFirst({ + const result = await db._query.credit_transactions.findFirst({ where: and( eq(credit_transactions.kilo_user_id, kiloUserId), eq(credit_transactions.is_free, false), @@ -90,7 +90,7 @@ export async function hasUserEverPaid(kiloUserId: string): Promise { export async function hasOrganizationEverPaid( organizationId: Organization['id'] ): Promise { - const result = await db.query.credit_transactions.findFirst({ + const result = await db._query.credit_transactions.findFirst({ where: and( eq(credit_transactions.organization_id, organizationId), eq(credit_transactions.is_free, false) diff --git a/apps/web/src/lib/credits.test.ts b/apps/web/src/lib/credits.test.ts index 2d369c9fa7..ee73796632 100644 --- a/apps/web/src/lib/credits.test.ts +++ b/apps/web/src/lib/credits.test.ts @@ -39,7 +39,7 @@ describe('processTopUp', () => { expect(result2).toBe(false); // Only one transaction with this stripe_payment_id should exist - const transactions = await db.query.credit_transactions.findMany({ + const transactions = await db._query.credit_transactions.findMany({ where: and( eq(credit_transactions.kilo_user_id, user.id), eq(credit_transactions.stripe_payment_id, stripePaymentId) diff --git a/apps/web/src/lib/customerInfo.ts b/apps/web/src/lib/customerInfo.ts index e7f9311254..334d8683ac 100644 --- a/apps/web/src/lib/customerInfo.ts +++ b/apps/web/src/lib/customerInfo.ts @@ -29,7 +29,7 @@ export const getCustomerInfo = async ( }); const paymentEligblePromise = (async () => { - const result = await db.query.payment_methods.findFirst({ + const result = await db._query.payment_methods.findFirst({ columns: { id: true }, where: and( eq(payment_methods.user_id, kiloUserId), diff --git a/apps/web/src/lib/impact-referral.test.ts b/apps/web/src/lib/impact-referral.test.ts index 4d06b21150..9dc8c70664 100644 --- a/apps/web/src/lib/impact-referral.test.ts +++ b/apps/web/src/lib/impact-referral.test.ts @@ -411,13 +411,13 @@ describe('impact referral participant registration dispatch', () => { // The new participant is registered but does NOT receive the colliding // code; the incumbent keeps it. - const newParticipant = await db.query.impact_advocate_participants.findFirst({ + const newParticipant = await db._query.impact_advocate_participants.findFirst({ where: eq(impact_advocate_participants.user_id, newUser.id), }); expect(newParticipant?.registration_state).toBe('registered'); expect(newParticipant?.opaque_referral_identifier).toBeNull(); - const incumbentParticipant = await db.query.impact_advocate_participants.findFirst({ + const incumbentParticipant = await db._query.impact_advocate_participants.findFirst({ where: eq(impact_advocate_participants.user_id, incumbent.id), }); expect(incumbentParticipant?.opaque_referral_identifier).toBe('COLLIDING_CODE'); @@ -477,7 +477,7 @@ describe('impact referral participant registration dispatch', () => { // Participant now carries the SaaSquatch code so future referee touches // resolve back to this user. - const participant = await db.query.impact_advocate_participants.findFirst({ + const participant = await db._query.impact_advocate_participants.findFirst({ where: eq(impact_advocate_participants.user_id, user.id), }); expect(participant?.registration_state).toBe('registered'); diff --git a/apps/web/src/lib/impact-referral.ts b/apps/web/src/lib/impact-referral.ts index a80008240c..e961936c8f 100644 --- a/apps/web/src/lib/impact-referral.ts +++ b/apps/web/src/lib/impact-referral.ts @@ -235,7 +235,7 @@ export async function ensureImpactAdvocateParticipantProfile(params: { const participant = insertedParticipant ?? - (await database.query.impact_advocate_participants.findFirst({ + (await database._query.impact_advocate_participants.findFirst({ where: eq(impact_advocate_participants.user_id, params.user.id), columns: { id: true }, })); @@ -399,7 +399,7 @@ export async function queueImpactAdvocateSelfRegistration(params: { countryCode: params.countryCode, }); - const existing = await database.query.impact_advocate_participants.findFirst({ + const existing = await database._query.impact_advocate_participants.findFirst({ where: eq(impact_advocate_participants.id, participant.id), columns: { registration_state: true, opaque_referral_identifier: true }, }); @@ -513,14 +513,14 @@ function nextRegistrationRetryAt(attemptCount: number): string { async function dispatchImpactAdvocateRegistrationAttemptById( attemptId: string ): Promise<'delivered' | 'retried' | 'failed'> { - const attempt = await db.query.impact_advocate_registration_attempts.findFirst({ + const attempt = await db._query.impact_advocate_registration_attempts.findFirst({ where: eq(impact_advocate_registration_attempts.id, attemptId), }); if (!attempt) { return 'failed'; } - const participant = await db.query.impact_advocate_participants.findFirst({ + const participant = await db._query.impact_advocate_participants.findFirst({ where: eq(impact_advocate_participants.id, attempt.participant_id), }); if (!participant) { @@ -604,7 +604,7 @@ async function dispatchImpactAdvocateRegistrationAttemptById( let advocateCodeToPersist: string | null = null; if (advocateCode) { - const conflicting = await db.query.impact_advocate_participants.findFirst({ + const conflicting = await db._query.impact_advocate_participants.findFirst({ where: and( eq(impact_advocate_participants.opaque_referral_identifier, advocateCode), ne(impact_advocate_participants.id, participant.id) diff --git a/apps/web/src/lib/integrations/platforms/github/batch-review-decisions.test.ts b/apps/web/src/lib/integrations/platforms/github/batch-review-decisions.test.ts index a501c5b3f5..418cdeb505 100644 --- a/apps/web/src/lib/integrations/platforms/github/batch-review-decisions.test.ts +++ b/apps/web/src/lib/integrations/platforms/github/batch-review-decisions.test.ts @@ -254,8 +254,15 @@ describe('batch-review-decisions', () => { triggerBatchReviewDecisionFetchIfNeeded(true, testOwner); - // Give it a tick for any resolved promises - await new Promise(r => setTimeout(r, 0)); + // triggerBatchReviewDecisionFetchIfNeeded is fire-and-forget; internally + // it must first await the claimPendingReviewRows Postgres UPDATE before + // it reaches getIntegrationForOwner. A single macrotask tick is enough + // on a fast local DB but not on CI's slower Postgres, so poll-wait for + // the observable signal instead of guessing a tick count. + const deadline = Date.now() + 5000; + while (mockGetIntegration.mock.calls.length === 0 && Date.now() < deadline) { + await new Promise(r => setTimeout(r, 10)); + } expect(mockGetIntegration).toHaveBeenCalled(); }); diff --git a/apps/web/src/lib/kilo-pass/cancel-and-refund.ts b/apps/web/src/lib/kilo-pass/cancel-and-refund.ts index 1f8392e9d5..e003966c5a 100644 --- a/apps/web/src/lib/kilo-pass/cancel-and-refund.ts +++ b/apps/web/src/lib/kilo-pass/cancel-and-refund.ts @@ -65,7 +65,7 @@ export async function cancelAndRefundKiloPassForUser({ adminKiloUserId, noteSuffix, }: CancelAndRefundKiloPassParams): Promise { - const user = await db.query.kilocode_users.findFirst({ + const user = await db._query.kilocode_users.findFirst({ columns: { id: true, stripe_customer_id: true, @@ -87,7 +87,7 @@ export async function cancelAndRefundKiloPassForUser({ return { status: 'skipped', reason: { kind: 'already_canceled' } }; } - const scheduledChange = await db.query.kilo_pass_scheduled_changes.findFirst({ + const scheduledChange = await db._query.kilo_pass_scheduled_changes.findFirst({ columns: { stripe_schedule_id: true }, where: and( eq(kilo_pass_scheduled_changes.stripe_subscription_id, subscription.stripeSubscriptionId), diff --git a/apps/web/src/lib/kilo-pass/scheduled-change-release.ts b/apps/web/src/lib/kilo-pass/scheduled-change-release.ts index 11b847029f..8a9e7016d5 100644 --- a/apps/web/src/lib/kilo-pass/scheduled-change-release.ts +++ b/apps/web/src/lib/kilo-pass/scheduled-change-release.ts @@ -65,7 +65,7 @@ export async function releaseScheduledChangeForSubscription(params: { reason, } = params; - const row = await dbOrTx.query.kilo_pass_scheduled_changes.findFirst({ + const row = await dbOrTx._query.kilo_pass_scheduled_changes.findFirst({ columns: { id: true, kilo_user_id: true, diff --git a/apps/web/src/lib/kilo-pass/stripe-handlers-invoice-paid.test.ts b/apps/web/src/lib/kilo-pass/stripe-handlers-invoice-paid.test.ts index bb3e8d6393..342ed25474 100644 --- a/apps/web/src/lib/kilo-pass/stripe-handlers-invoice-paid.test.ts +++ b/apps/web/src/lib/kilo-pass/stripe-handlers-invoice-paid.test.ts @@ -354,12 +354,12 @@ describe('handleKiloPassInvoicePaid', () => { stripe: stripe as unknown as Stripe, }); - const userRow = await db.query.kilocode_users.findFirst({ + const userRow = await db._query.kilocode_users.findFirst({ where: eq(kilocode_users.id, user.id), }); expect(userRow?.kilo_pass_threshold).toBe(7_000_000 + 1_900 * 10_000); - const subRow = await db.query.kilo_pass_subscriptions.findFirst({ + const subRow = await db._query.kilo_pass_subscriptions.findFirst({ where: eq(kilo_pass_subscriptions.stripe_subscription_id, stripeSubId), }); expect(subRow).toBeTruthy(); @@ -369,7 +369,7 @@ describe('handleKiloPassInvoicePaid', () => { expect(subRow?.status).toBe('active'); expect(subRow?.current_streak_months).toBe(1); - const issuance = await db.query.kilo_pass_issuances.findFirst({ + const issuance = await db._query.kilo_pass_issuances.findFirst({ where: and( eq(kilo_pass_issuances.kilo_pass_subscription_id, subRow?.id ?? ''), eq(kilo_pass_issuances.stripe_invoice_id, invoiceId) @@ -473,7 +473,7 @@ describe('handleKiloPassInvoicePaid', () => { stripe: stripe as unknown as Stripe, }); - const issuance = await db.query.kilo_pass_issuances.findFirst({ + const issuance = await db._query.kilo_pass_issuances.findFirst({ where: eq(kilo_pass_issuances.stripe_invoice_id, invoiceId), }); expect(issuance).toBeTruthy(); @@ -557,12 +557,12 @@ describe('handleKiloPassInvoicePaid', () => { stripe: stripe as unknown as Stripe, }); - const updatedSub = await db.query.kilo_pass_subscriptions.findFirst({ + const updatedSub = await db._query.kilo_pass_subscriptions.findFirst({ where: eq(kilo_pass_subscriptions.id, subscriptionId), }); expect(updatedSub?.current_streak_months).toBe(2); - const issuance = await db.query.kilo_pass_issuances.findFirst({ + const issuance = await db._query.kilo_pass_issuances.findFirst({ where: eq(kilo_pass_issuances.stripe_invoice_id, invoiceId), }); expect(issuance).toBeTruthy(); @@ -635,12 +635,12 @@ describe('handleKiloPassInvoicePaid', () => { stripe: stripe as unknown as Stripe, }); - const userRow = await db.query.kilocode_users.findFirst({ + const userRow = await db._query.kilocode_users.findFirst({ where: eq(kilocode_users.id, user.id), }); expect(userRow?.kilo_pass_threshold).toBe(3_000_000 + 4_900 * 10_000); - const subRow = await db.query.kilo_pass_subscriptions.findFirst({ + const subRow = await db._query.kilo_pass_subscriptions.findFirst({ where: eq(kilo_pass_subscriptions.stripe_subscription_id, stripeSubId), }); expect(subRow).toBeTruthy(); @@ -652,7 +652,7 @@ describe('handleKiloPassInvoicePaid', () => { if (!nextYearlyIssueAt) throw new Error('Expected next_yearly_issue_at to be set'); expect(new Date(nextYearlyIssueAt).toISOString()).toBe('2026-02-08T00:00:00.000Z'); - const issuance = await db.query.kilo_pass_issuances.findFirst({ + const issuance = await db._query.kilo_pass_issuances.findFirst({ where: eq(kilo_pass_issuances.stripe_invoice_id, invoiceId), }); expect(issuance).toBeTruthy(); @@ -796,7 +796,7 @@ describe('handleKiloPassInvoicePaid', () => { expect(release).toHaveBeenCalledWith(stripeScheduleId); - const scheduledChangeRow = await db.query.kilo_pass_scheduled_changes.findFirst({ + const scheduledChangeRow = await db._query.kilo_pass_scheduled_changes.findFirst({ where: eq(kilo_pass_scheduled_changes.id, scheduledChangeId), }); expect(scheduledChangeRow).toBeTruthy(); @@ -804,13 +804,13 @@ describe('handleKiloPassInvoicePaid', () => { expect(scheduledChangeRow?.deleted_at).not.toBeNull(); const syntheticInvoiceId = `kilo-pass-yearly-remaining:${scheduledChangeId}`; - const remainingTx = await db.query.credit_transactions.findFirst({ + const remainingTx = await db._query.credit_transactions.findFirst({ where: eq(credit_transactions.stripe_payment_id, syntheticInvoiceId), }); expect(remainingTx).toBeTruthy(); expect(remainingTx?.amount_microdollars).toBe(171_000_000); - const remainingAuditLog = await db.query.kilo_pass_audit_log.findFirst({ + const remainingAuditLog = await db._query.kilo_pass_audit_log.findFirst({ where: eq(kilo_pass_audit_log.stripe_invoice_id, syntheticInvoiceId), }); expect(remainingAuditLog?.action).toBe(KiloPassAuditLogAction.IssueYearlyRemainingCredits); @@ -968,7 +968,7 @@ describe('handleKiloPassInvoicePaid', () => { }); const syntheticInvoiceId = `kilo-pass-yearly-remaining:${scheduledChangeId}`; - const remainingTx = await db.query.credit_transactions.findFirst({ + const remainingTx = await db._query.credit_transactions.findFirst({ where: eq(credit_transactions.stripe_payment_id, syntheticInvoiceId), }); expect(remainingTx).toBeTruthy(); @@ -977,7 +977,7 @@ describe('handleKiloPassInvoicePaid', () => { // elapsed and 12 remaining × $19 = $228 (wrong). expect(remainingTx?.amount_microdollars).toBe(171_000_000); - const remainingAuditLog = await db.query.kilo_pass_audit_log.findFirst({ + const remainingAuditLog = await db._query.kilo_pass_audit_log.findFirst({ where: eq(kilo_pass_audit_log.stripe_invoice_id, syntheticInvoiceId), }); expect(remainingAuditLog?.payload_json).toEqual( @@ -1099,14 +1099,14 @@ describe('handleKiloPassInvoicePaid', () => { }); const syntheticInvoiceId = `kilo-pass-yearly-remaining:${scheduledChangeId}`; - const remainingTx = await db.query.credit_transactions.findFirst({ + const remainingTx = await db._query.credit_transactions.findFirst({ where: eq(credit_transactions.stripe_payment_id, syntheticInvoiceId), }); expect(remainingTx).toBeTruthy(); // Only 1 month was used (Apr). 11 remaining × $19 = $209. expect(remainingTx?.amount_microdollars).toBe(209_000_000); - const remainingAuditLog = await db.query.kilo_pass_audit_log.findFirst({ + const remainingAuditLog = await db._query.kilo_pass_audit_log.findFirst({ where: eq(kilo_pass_audit_log.stripe_invoice_id, syntheticInvoiceId), }); expect(remainingAuditLog?.payload_json).toEqual( @@ -1235,7 +1235,7 @@ describe('handleKiloPassInvoicePaid', () => { }); const syntheticInvoiceId = `kilo-pass-yearly-remaining:${scheduledChangeId}`; - const remainingTx = await db.query.credit_transactions.findFirst({ + const remainingTx = await db._query.credit_transactions.findFirst({ where: eq(credit_transactions.stripe_payment_id, syntheticInvoiceId), }); expect(remainingTx).toBeTruthy(); @@ -1243,7 +1243,7 @@ describe('handleKiloPassInvoicePaid', () => { // The old monthly issuances (Jan, Feb) must NOT count. expect(remainingTx?.amount_microdollars).toBe(190_000_000); - const remainingAuditLog = await db.query.kilo_pass_audit_log.findFirst({ + const remainingAuditLog = await db._query.kilo_pass_audit_log.findFirst({ where: eq(kilo_pass_audit_log.stripe_invoice_id, syntheticInvoiceId), }); expect(remainingAuditLog?.payload_json).toEqual( @@ -1350,7 +1350,7 @@ describe('handleKiloPassInvoicePaid', () => { // No remaining credits should be issued — full year was used. const syntheticInvoiceId = `kilo-pass-yearly-remaining:${scheduledChangeId}`; - const remainingTx = await db.query.credit_transactions.findFirst({ + const remainingTx = await db._query.credit_transactions.findFirst({ where: eq(credit_transactions.stripe_payment_id, syntheticInvoiceId), }); expect(remainingTx).toBeUndefined(); @@ -1456,14 +1456,14 @@ describe('handleKiloPassInvoicePaid', () => { }); const syntheticInvoiceId = `kilo-pass-yearly-remaining:${scheduledChangeId}`; - const remainingTx = await db.query.credit_transactions.findFirst({ + const remainingTx = await db._query.credit_transactions.findFirst({ where: eq(credit_transactions.stripe_payment_id, syntheticInvoiceId), }); expect(remainingTx).toBeTruthy(); // 1 month used, 11 remaining × $19 = $209 expect(remainingTx?.amount_microdollars).toBe(209_000_000); - const remainingAuditLog = await db.query.kilo_pass_audit_log.findFirst({ + const remainingAuditLog = await db._query.kilo_pass_audit_log.findFirst({ where: eq(kilo_pass_audit_log.stripe_invoice_id, syntheticInvoiceId), }); expect(remainingAuditLog?.payload_json).toEqual( @@ -1564,7 +1564,7 @@ describe('handleKiloPassInvoicePaid', () => { // remaining = 0, so no credits issued. // This is conservative — better to under-issue than over-issue in the fallback. const syntheticInvoiceId = `kilo-pass-yearly-remaining:${scheduledChangeId}`; - const remainingTx = await db.query.credit_transactions.findFirst({ + const remainingTx = await db._query.credit_transactions.findFirst({ where: eq(credit_transactions.stripe_payment_id, syntheticInvoiceId), }); expect(remainingTx).toBeUndefined(); @@ -1668,14 +1668,14 @@ describe('handleKiloPassInvoicePaid', () => { }); const syntheticInvoiceId = `kilo-pass-yearly-remaining:${scheduledChangeId}`; - const remainingTx = await db.query.credit_transactions.findFirst({ + const remainingTx = await db._query.credit_transactions.findFirst({ where: eq(credit_transactions.stripe_payment_id, syntheticInvoiceId), }); expect(remainingTx).toBeTruthy(); // 2 months used (Mar, Apr) in the tier_49 cycle. 10 remaining × $49 = $490. expect(remainingTx?.amount_microdollars).toBe(490_000_000); - const remainingAuditLog = await db.query.kilo_pass_audit_log.findFirst({ + const remainingAuditLog = await db._query.kilo_pass_audit_log.findFirst({ where: eq(kilo_pass_audit_log.stripe_invoice_id, syntheticInvoiceId), }); expect(remainingAuditLog?.payload_json).toEqual( @@ -1764,7 +1764,7 @@ describe('handleKiloPassInvoicePaid', () => { expect(release).toHaveBeenCalledWith(stripeScheduleId); - const scheduledChangeRow = await db.query.kilo_pass_scheduled_changes.findFirst({ + const scheduledChangeRow = await db._query.kilo_pass_scheduled_changes.findFirst({ where: eq(kilo_pass_scheduled_changes.id, scheduledChangeId), }); expect(scheduledChangeRow).toBeTruthy(); @@ -1858,7 +1858,7 @@ describe('handleKiloPassInvoicePaid', () => { }); // Verify the subscription row was NOT resurrected to 'active' - const subRow = await db.query.kilo_pass_subscriptions.findFirst({ + const subRow = await db._query.kilo_pass_subscriptions.findFirst({ where: eq(kilo_pass_subscriptions.stripe_subscription_id, stripeSubId), }); expect(subRow).toBeTruthy(); @@ -1985,7 +1985,7 @@ describe('handleKiloPassInvoicePaid', () => { stripe: stripe as unknown as Stripe, }); - const subRow = await db.query.kilo_pass_subscriptions.findFirst({ + const subRow = await db._query.kilo_pass_subscriptions.findFirst({ where: eq(kilo_pass_subscriptions.stripe_subscription_id, stripeSubId), }); // months 1, 2, 3 (issuances) + month 6 (current) = 4 @@ -2063,7 +2063,7 @@ describe('handleKiloPassInvoicePaid', () => { stripe: stripe as unknown as Stripe, }); - const subRow = await db.query.kilo_pass_subscriptions.findFirst({ + const subRow = await db._query.kilo_pass_subscriptions.findFirst({ where: eq(kilo_pass_subscriptions.stripe_subscription_id, stripeSubId), }); // months 1-5 (issuances) + month 9 (current) = 6; months 6, 7, 8 paused (skipped) @@ -2122,7 +2122,7 @@ describe('handleKiloPassInvoicePaid', () => { stripe: stripe as unknown as Stripe, }); - const subRow = await db.query.kilo_pass_subscriptions.findFirst({ + const subRow = await db._query.kilo_pass_subscriptions.findFirst({ where: eq(kilo_pass_subscriptions.stripe_subscription_id, stripeSubId), }); // month 4 has no issuance and no pause → streak resets to 1 @@ -2181,7 +2181,7 @@ describe('handleKiloPassInvoicePaid', () => { stripe: stripe as unknown as Stripe, }); - const subRow = await db.query.kilo_pass_subscriptions.findFirst({ + const subRow = await db._query.kilo_pass_subscriptions.findFirst({ where: eq(kilo_pass_subscriptions.stripe_subscription_id, stripeSubId), }); // months 1, 2, 3, 4 = streak of 4 diff --git a/apps/web/src/lib/kilo-pass/stripe-handlers-invoice-paid.ts b/apps/web/src/lib/kilo-pass/stripe-handlers-invoice-paid.ts index e64c98047e..c309721989 100644 --- a/apps/web/src/lib/kilo-pass/stripe-handlers-invoice-paid.ts +++ b/apps/web/src/lib/kilo-pass/stripe-handlers-invoice-paid.ts @@ -56,7 +56,7 @@ async function maybeIssueYearlyRemainingCredits(params: { }): Promise { const { tx, stripe, stripeEventId, stripeInvoiceId, scheduledChangeId } = params; - const row = await tx.query.kilo_pass_scheduled_changes.findFirst({ + const row = await tx._query.kilo_pass_scheduled_changes.findFirst({ where: and( eq(kilo_pass_scheduled_changes.id, scheduledChangeId), isNull(kilo_pass_scheduled_changes.deleted_at) @@ -74,7 +74,7 @@ async function maybeIssueYearlyRemainingCredits(params: { if (!isYearly || toPrice < fromPrice) return false; - const subscription = await tx.query.kilo_pass_subscriptions.findFirst({ + const subscription = await tx._query.kilo_pass_subscriptions.findFirst({ columns: { id: true, }, @@ -290,7 +290,7 @@ export async function handleKiloPassInvoicePaid(params: { const issueMonth = getInvoiceIssueMonth(invoice); - const existingSubscription = await tx.query.kilo_pass_subscriptions.findFirst({ + const existingSubscription = await tx._query.kilo_pass_subscriptions.findFirst({ where: eq(kilo_pass_subscriptions.stripe_subscription_id, subscription.id), }); diff --git a/apps/web/src/lib/kilo-pass/stripe-handlers-subscription-events.test.ts b/apps/web/src/lib/kilo-pass/stripe-handlers-subscription-events.test.ts index b6a2d346bd..76aaf5c714 100644 --- a/apps/web/src/lib/kilo-pass/stripe-handlers-subscription-events.test.ts +++ b/apps/web/src/lib/kilo-pass/stripe-handlers-subscription-events.test.ts @@ -141,7 +141,7 @@ describe('handleKiloPassSubscriptionEvent', () => { await handleKiloPassSubscriptionEvent({ eventId, eventType, subscription }); - const subRow = await db.query.kilo_pass_subscriptions.findFirst({ + const subRow = await db._query.kilo_pass_subscriptions.findFirst({ where: eq(kilo_pass_subscriptions.stripe_subscription_id, stripeSubId), }); expect(subRow).toBeTruthy(); @@ -153,7 +153,7 @@ describe('handleKiloPassSubscriptionEvent', () => { expect(toIso(subRow?.started_at)).toBe(new Date(startDateSeconds * 1000).toISOString()); expect(subRow?.ended_at).toBeNull(); - const auditRow = await db.query.kilo_pass_audit_log.findFirst({ + const auditRow = await db._query.kilo_pass_audit_log.findFirst({ where: and( eq(kilo_pass_audit_log.action, KiloPassAuditLogAction.StripeWebhookReceived), eq(kilo_pass_audit_log.stripe_event_id, eventId) @@ -192,7 +192,7 @@ describe('handleKiloPassSubscriptionEvent', () => { subscription, }); - const subRow = await db.query.kilo_pass_subscriptions.findFirst({ + const subRow = await db._query.kilo_pass_subscriptions.findFirst({ where: eq(kilo_pass_subscriptions.stripe_subscription_id, stripeSubId), }); expect(subRow?.status).toBe('active'); @@ -238,7 +238,7 @@ describe('handleKiloPassSubscriptionEvent', () => { subscription, }); - const updated = await db.query.kilo_pass_subscriptions.findFirst({ + const updated = await db._query.kilo_pass_subscriptions.findFirst({ where: eq(kilo_pass_subscriptions.stripe_subscription_id, stripeSubId), }); @@ -274,7 +274,7 @@ describe('handleKiloPassSubscriptionEvent', () => { subscription: subWithCanceledAt, }); - const updatedWithCanceledAt = await db.query.kilo_pass_subscriptions.findFirst({ + const updatedWithCanceledAt = await db._query.kilo_pass_subscriptions.findFirst({ where: eq(kilo_pass_subscriptions.stripe_subscription_id, stripeSubIdCanceledAt), }); expect(updatedWithCanceledAt?.status).toBe('canceled'); @@ -306,7 +306,7 @@ describe('handleKiloPassSubscriptionEvent', () => { const afterSeconds = Math.floor(Date.now() / 1000); - const updatedWithNow = await db.query.kilo_pass_subscriptions.findFirst({ + const updatedWithNow = await db._query.kilo_pass_subscriptions.findFirst({ where: eq(kilo_pass_subscriptions.stripe_subscription_id, stripeSubIdNow), }); expect(updatedWithNow?.status).toBe('unpaid'); @@ -356,7 +356,7 @@ describe('handleKiloPassSubscriptionEvent', () => { subscription, }); - const updated = await db.query.kilo_pass_subscriptions.findFirst({ + const updated = await db._query.kilo_pass_subscriptions.findFirst({ where: eq(kilo_pass_subscriptions.stripe_subscription_id, stripeSubId), }); expect(updated?.status).toBe('active'); @@ -395,7 +395,7 @@ describe('handleKiloPassSubscriptionEvent', () => { subscription, }); - const subRow = await db.query.kilo_pass_subscriptions.findFirst({ + const subRow = await db._query.kilo_pass_subscriptions.findFirst({ where: eq(kilo_pass_subscriptions.stripe_subscription_id, stripeSubId), }); expect(subRow).toBeTruthy(); @@ -444,7 +444,7 @@ describe('handleKiloPassSubscriptionEvent', () => { // DB stores Stripe's reported status (active), not 'paused'. // The state query derives paused from the open pause event. - const subRow = await db.query.kilo_pass_subscriptions.findFirst({ + const subRow = await db._query.kilo_pass_subscriptions.findFirst({ where: eq(kilo_pass_subscriptions.stripe_subscription_id, stripeSubId), }); expect(subRow).toBeTruthy(); @@ -488,7 +488,7 @@ describe('handleKiloPassSubscriptionEvent', () => { subscription: pausedSubscription, }); - const subRow = await db.query.kilo_pass_subscriptions.findFirst({ + const subRow = await db._query.kilo_pass_subscriptions.findFirst({ where: eq(kilo_pass_subscriptions.stripe_subscription_id, stripeSubId), }); expect(subRow).toBeTruthy(); diff --git a/apps/web/src/lib/kilo-pass/stripe-handlers-subscription-events.ts b/apps/web/src/lib/kilo-pass/stripe-handlers-subscription-events.ts index a32b7b704d..42d0e94c5e 100644 --- a/apps/web/src/lib/kilo-pass/stripe-handlers-subscription-events.ts +++ b/apps/web/src/lib/kilo-pass/stripe-handlers-subscription-events.ts @@ -48,7 +48,7 @@ export async function handleKiloPassSubscriptionEvent(params: { const stripeStatus = subscription.status; const cancelAtPeriodEnd = subscription.cancel_at_period_end; - const existing = await tx.query.kilo_pass_subscriptions.findFirst({ + const existing = await tx._query.kilo_pass_subscriptions.findFirst({ where: eq(kilo_pass_subscriptions.stripe_subscription_id, subscription.id), }); diff --git a/apps/web/src/lib/kilo-pass/usage-triggered-bonus.test.ts b/apps/web/src/lib/kilo-pass/usage-triggered-bonus.test.ts index ec503bc7f6..293c334991 100644 --- a/apps/web/src/lib/kilo-pass/usage-triggered-bonus.test.ts +++ b/apps/web/src/lib/kilo-pass/usage-triggered-bonus.test.ts @@ -131,7 +131,7 @@ describe('maybeIssueKiloPassBonusFromUsageThreshold', () => { db, }); - const bonusItem = await db.query.kilo_pass_issuance_items.findFirst({ + const bonusItem = await db._query.kilo_pass_issuance_items.findFirst({ where: and( eq(kilo_pass_issuance_items.kilo_pass_issuance_id, issuanceId), eq(kilo_pass_issuance_items.kind, KiloPassIssuanceItemKind.Bonus) @@ -139,14 +139,14 @@ describe('maybeIssueKiloPassBonusFromUsageThreshold', () => { }); expect(bonusItem).toBeTruthy(); - const bonusTx = await db.query.credit_transactions.findFirst({ + const bonusTx = await db._query.credit_transactions.findFirst({ where: eq(credit_transactions.id, bonusItem?.credit_transaction_id ?? ''), }); expect(bonusTx?.is_free).toBe(true); // tier_19 at streak=2 => base 5% + step 5% * 1 = 10% of $19.00 = $1.90. expect(bonusTx?.amount_microdollars).toBe(1_900_000); - const userRow = await db.query.kilocode_users.findFirst({ + const userRow = await db._query.kilocode_users.findFirst({ where: eq(kilocode_users.id, user.id), }); expect(userRow?.kilo_pass_threshold).toBeNull(); @@ -175,7 +175,7 @@ describe('maybeIssueKiloPassBonusFromUsageThreshold', () => { db, }); - const bonusItem = await db.query.kilo_pass_issuance_items.findFirst({ + const bonusItem = await db._query.kilo_pass_issuance_items.findFirst({ where: and( eq(kilo_pass_issuance_items.kilo_pass_issuance_id, issuanceId), eq(kilo_pass_issuance_items.kind, KiloPassIssuanceItemKind.Bonus) @@ -183,7 +183,7 @@ describe('maybeIssueKiloPassBonusFromUsageThreshold', () => { }); expect(bonusItem).toBeTruthy(); - const bonusTx = await db.query.credit_transactions.findFirst({ + const bonusTx = await db._query.credit_transactions.findFirst({ where: eq(credit_transactions.id, bonusItem?.credit_transaction_id ?? ''), }); // tier_49 monthly price is $49, 50% => $24.50. @@ -237,7 +237,7 @@ describe('maybeIssueKiloPassBonusFromUsageThreshold', () => { db, }); - const bonusItem = await db.query.kilo_pass_issuance_items.findFirst({ + const bonusItem = await db._query.kilo_pass_issuance_items.findFirst({ where: and( eq(kilo_pass_issuance_items.kilo_pass_issuance_id, issuanceId), eq(kilo_pass_issuance_items.kind, KiloPassIssuanceItemKind.Bonus) @@ -245,7 +245,7 @@ describe('maybeIssueKiloPassBonusFromUsageThreshold', () => { }); expect(bonusItem).toBeTruthy(); - const bonusTx = await db.query.credit_transactions.findFirst({ + const bonusTx = await db._query.credit_transactions.findFirst({ where: eq(credit_transactions.id, bonusItem?.credit_transaction_id ?? ''), }); // tier_49 at streak=2 => base 5% + step 5% * 1 = 10% of $49.00 = $4.90. @@ -281,7 +281,7 @@ describe('maybeIssueKiloPassBonusFromUsageThreshold', () => { db, }); - const bonusItem = await db.query.kilo_pass_issuance_items.findFirst({ + const bonusItem = await db._query.kilo_pass_issuance_items.findFirst({ where: and( eq(kilo_pass_issuance_items.kilo_pass_issuance_id, issuanceId), eq(kilo_pass_issuance_items.kind, KiloPassIssuanceItemKind.Bonus) @@ -289,7 +289,7 @@ describe('maybeIssueKiloPassBonusFromUsageThreshold', () => { }); expect(bonusItem).toBeTruthy(); - const bonusTx = await db.query.credit_transactions.findFirst({ + const bonusTx = await db._query.credit_transactions.findFirst({ where: eq(credit_transactions.id, bonusItem?.credit_transaction_id ?? ''), }); @@ -355,7 +355,7 @@ describe('maybeIssueKiloPassBonusFromUsageThreshold', () => { db, }); - const bonusItem = await db.query.kilo_pass_issuance_items.findFirst({ + const bonusItem = await db._query.kilo_pass_issuance_items.findFirst({ where: and( eq(kilo_pass_issuance_items.kilo_pass_issuance_id, issuanceId), eq(kilo_pass_issuance_items.kind, KiloPassIssuanceItemKind.Bonus) @@ -363,7 +363,7 @@ describe('maybeIssueKiloPassBonusFromUsageThreshold', () => { }); expect(bonusItem).toBeTruthy(); - const bonusTx = await db.query.credit_transactions.findFirst({ + const bonusTx = await db._query.credit_transactions.findFirst({ where: eq(credit_transactions.id, bonusItem?.credit_transaction_id ?? ''), }); // tier_49 at streak=3 => base 5% + step 5% * 2 = 15% of $49.00 = $7.35. @@ -392,7 +392,7 @@ describe('maybeIssueKiloPassBonusFromUsageThreshold', () => { db, }); - const bonusItem = await db.query.kilo_pass_issuance_items.findFirst({ + const bonusItem = await db._query.kilo_pass_issuance_items.findFirst({ where: and( eq(kilo_pass_issuance_items.kilo_pass_issuance_id, issuanceId), eq(kilo_pass_issuance_items.kind, KiloPassIssuanceItemKind.Bonus) @@ -400,7 +400,7 @@ describe('maybeIssueKiloPassBonusFromUsageThreshold', () => { }); expect(bonusItem).toBeTruthy(); - const bonusTx = await db.query.credit_transactions.findFirst({ + const bonusTx = await db._query.credit_transactions.findFirst({ where: eq(credit_transactions.id, bonusItem?.credit_transaction_id ?? ''), }); expect(bonusTx?.is_free).toBe(true); @@ -423,7 +423,7 @@ describe('maybeIssueKiloPassBonusFromUsageThreshold', () => { throw new Error('Expected bonus issuance audit payload to be an object'); expect(payload.bonusKind).toBe('promo-50pct'); - const userRow = await db.query.kilocode_users.findFirst({ + const userRow = await db._query.kilocode_users.findFirst({ where: eq(kilocode_users.id, user.id), }); expect(userRow?.kilo_pass_threshold).toBeNull(); @@ -465,7 +465,7 @@ describe('maybeIssueKiloPassBonusFromUsageThreshold', () => { db, }); - const bonusItem = await db.query.kilo_pass_issuance_items.findFirst({ + const bonusItem = await db._query.kilo_pass_issuance_items.findFirst({ where: and( eq(kilo_pass_issuance_items.kilo_pass_issuance_id, issuanceId), eq(kilo_pass_issuance_items.kind, KiloPassIssuanceItemKind.Bonus) @@ -473,7 +473,7 @@ describe('maybeIssueKiloPassBonusFromUsageThreshold', () => { }); expect(bonusItem).toBeTruthy(); - const bonusTx = await db.query.credit_transactions.findFirst({ + const bonusTx = await db._query.credit_transactions.findFirst({ where: eq(credit_transactions.id, bonusItem?.credit_transaction_id ?? ''), }); // tier_19 at streak=1 => 5% of $19.00 = $0.95. @@ -490,7 +490,7 @@ describe('maybeIssueKiloPassBonusFromUsageThreshold', () => { ); expect(promoItems).toHaveLength(0); - const userRow = await db.query.kilocode_users.findFirst({ + const userRow = await db._query.kilocode_users.findFirst({ where: eq(kilocode_users.id, user.id), }); expect(userRow?.kilo_pass_threshold).toBeNull(); @@ -518,7 +518,7 @@ describe('maybeIssueKiloPassBonusFromUsageThreshold', () => { db, }); - const bonusItem = await db.query.kilo_pass_issuance_items.findFirst({ + const bonusItem = await db._query.kilo_pass_issuance_items.findFirst({ where: and( eq(kilo_pass_issuance_items.kilo_pass_issuance_id, issuanceId), eq(kilo_pass_issuance_items.kind, KiloPassIssuanceItemKind.Bonus) @@ -526,13 +526,13 @@ describe('maybeIssueKiloPassBonusFromUsageThreshold', () => { }); expect(bonusItem).toBeTruthy(); - const bonusTx = await db.query.credit_transactions.findFirst({ + const bonusTx = await db._query.credit_transactions.findFirst({ where: eq(credit_transactions.id, bonusItem?.credit_transaction_id ?? ''), }); expect(bonusTx?.is_free).toBe(true); expect(bonusTx?.amount_microdollars).toBe(24_500_000); - const userRow = await db.query.kilocode_users.findFirst({ + const userRow = await db._query.kilocode_users.findFirst({ where: eq(kilocode_users.id, user.id), }); expect(userRow?.kilo_pass_threshold).toBeNull(); diff --git a/apps/web/src/lib/kilo-pass/usage-triggered-bonus.ts b/apps/web/src/lib/kilo-pass/usage-triggered-bonus.ts index 0fe012ee46..5ae7628a3a 100644 --- a/apps/web/src/lib/kilo-pass/usage-triggered-bonus.ts +++ b/apps/web/src/lib/kilo-pass/usage-triggered-bonus.ts @@ -178,7 +178,7 @@ async function getOrCreateIssuanceForYearlyCadence( stripeInvoiceId: null, }); - const issuanceRow = await tx.query.kilo_pass_issuances.findFirst({ + const issuanceRow = await tx._query.kilo_pass_issuances.findFirst({ columns: { stripe_invoice_id: true }, where: eq(kilo_pass_issuances.id, issuanceHeader.issuanceId), }); @@ -216,7 +216,7 @@ async function maybeIssueBonusFromUsageThreshold( return; } - const baseItem = await tx.query.kilo_pass_issuance_items.findFirst({ + const baseItem = await tx._query.kilo_pass_issuance_items.findFirst({ columns: { id: true }, where: and( eq(kilo_pass_issuance_items.kilo_pass_issuance_id, issuance.issuanceId), @@ -228,7 +228,7 @@ async function maybeIssueBonusFromUsageThreshold( return; } - const alreadyIssuedItem = await tx.query.kilo_pass_issuance_items.findFirst({ + const alreadyIssuedItem = await tx._query.kilo_pass_issuance_items.findFirst({ columns: { id: true }, where: and( eq(kilo_pass_issuance_items.kilo_pass_issuance_id, issuance.issuanceId), diff --git a/apps/web/src/lib/kiloclaw-referrals.ts b/apps/web/src/lib/kiloclaw-referrals.ts index 5442eac0eb..2bcf8cb4e7 100644 --- a/apps/web/src/lib/kiloclaw-referrals.ts +++ b/apps/web/src/lib/kiloclaw-referrals.ts @@ -1107,7 +1107,7 @@ async function persistRewardRedemptionFailure(params: { async function dispatchImpactAdvocateRewardRedemptionById( redemptionId: string ): Promise<'redeemed' | 'retried' | 'failed'> { - const redemption = await db.query.impact_advocate_reward_redemptions.findFirst({ + const redemption = await db._query.impact_advocate_reward_redemptions.findFirst({ where: eq(impact_advocate_reward_redemptions.id, redemptionId), }); if (!redemption) return 'failed'; @@ -1350,7 +1350,7 @@ export async function markPersonalKiloClawReferralPaymentAdverse(params: { let impactReportId: string | null = null; const summary = await db.transaction(async tx => { - const conversion = await tx.query.kiloclaw_referral_conversions.findFirst({ + const conversion = await tx._query.kiloclaw_referral_conversions.findFirst({ where: eq(kiloclaw_referral_conversions.source_payment_id, params.sourcePaymentId), }); @@ -1397,7 +1397,7 @@ export async function markPersonalKiloClawReferralPaymentAdverse(params: { } } - const report = await tx.query.impact_conversion_reports.findFirst({ + const report = await tx._query.impact_conversion_reports.findFirst({ where: eq(impact_conversion_reports.conversion_id, conversion.id), columns: { id: true }, }); @@ -1457,7 +1457,7 @@ async function getImpactConversionReportById( reportId: string, database: DatabaseClient ): Promise { - const report = await database.query.impact_conversion_reports.findFirst({ + const report = await database._query.impact_conversion_reports.findFirst({ where: eq(impact_conversion_reports.id, reportId), }); return report ?? null; @@ -1672,7 +1672,7 @@ export async function processPersonalKiloClawPaidConversion(params: { let impactReportId: string | null = null; const rewardBeneficiaryUserIds = new Set(); const disposition = await db.transaction(async tx => { - const existingConversion = await tx.query.kiloclaw_referral_conversions.findFirst({ + const existingConversion = await tx._query.kiloclaw_referral_conversions.findFirst({ where: eq(kiloclaw_referral_conversions.source_payment_id, params.sourcePaymentId), }); @@ -2130,7 +2130,7 @@ export async function processPersonalKiloClawPaidConversion(params: { const existingReport = report ?? - (await tx.query.impact_conversion_reports.findFirst({ + (await tx._query.impact_conversion_reports.findFirst({ where: eq( impact_conversion_reports.dedupe_key, `impact-referral-sale:${params.sourcePaymentId}` diff --git a/apps/web/src/lib/kiloclaw/credit-billing.ts b/apps/web/src/lib/kiloclaw/credit-billing.ts index a697edf5a7..0f16fa81d0 100644 --- a/apps/web/src/lib/kiloclaw/credit-billing.ts +++ b/apps/web/src/lib/kiloclaw/credit-billing.ts @@ -469,7 +469,7 @@ export async function applyStripeFundedKiloClawPeriod(params: { let settlementWasDuplicate = false; await db.transaction(async tx => { - const user = await tx.query.kilocode_users.findFirst({ + const user = await tx._query.kilocode_users.findFirst({ where: eq(kilocode_users.id, userId), }); diff --git a/apps/web/src/lib/organizations/organization-billing.test.ts b/apps/web/src/lib/organizations/organization-billing.test.ts index d65129dc4f..e05b3c6311 100644 --- a/apps/web/src/lib/organizations/organization-billing.test.ts +++ b/apps/web/src/lib/organizations/organization-billing.test.ts @@ -51,7 +51,7 @@ jest.mock('@/lib/credits', () => ({ })); function getOrganizationTopUpEmailMarkers(stripePaymentId: string) { - return db.query.transactional_email_log.findMany({ + return db._query.transactional_email_log.findMany({ where: and( eq(transactional_email_log.email_type, 'organization_credits_top_up_confirmation'), eq(transactional_email_log.idempotency_key, stripePaymentId) @@ -245,7 +245,7 @@ describe('getOrCreateStripeCustomerIdForOrganization', () => { expect(result).toBe('cus_test_preserve'); - const updated = await db.query.organizations.findFirst({ + const updated = await db._query.organizations.findFirst({ where: eq(organizations.id, testOrganization.id), }); expect(updated?.stripe_customer_id).toBe('cus_test_preserve'); @@ -297,7 +297,7 @@ describe('getOrCreateStripeCustomerIdForOrganization', () => { expect(result).toBe('cus_fresh_123'); // Verify the database was actually updated - const updatedOrg = await db.query.organizations.findFirst({ + const updatedOrg = await db._query.organizations.findFirst({ where: eq(organizations.id, freshOrg.id), }); expect(updatedOrg?.stripe_customer_id).toBe('cus_fresh_123'); @@ -560,7 +560,7 @@ describe('processTopupForOrganization', () => { await processTopupForOrganization(testUser.id, testOrganization.id, amountInCents, config); // Verify organization balance was updated - const updatedOrg = await db.query.organizations.findFirst({ + const updatedOrg = await db._query.organizations.findFirst({ where: eq(organizations.id, testOrganization.id), }); @@ -573,7 +573,7 @@ describe('processTopupForOrganization', () => { ); // Verify credit transaction was created - const creditTransaction = await db.query.credit_transactions.findFirst({ + const creditTransaction = await db._query.credit_transactions.findFirst({ where: eq(credit_transactions.stripe_payment_id, stripePaymentId), }); @@ -793,7 +793,7 @@ describe('processTopupForOrganization', () => { } ); - const creditTransaction = await db.query.credit_transactions.findFirst({ + const creditTransaction = await db._query.credit_transactions.findFirst({ where: eq(credit_transactions.stripe_payment_id, stripePaymentId), }); expect(creditTransaction?.organization_id).toBe(organizationWithoutRecipients.id); @@ -869,7 +869,7 @@ describe('processTopupForOrganization', () => { selectMock.mockRestore(); } - const updatedOrg = await db.query.organizations.findFirst({ + const updatedOrg = await db._query.organizations.findFirst({ where: eq(organizations.id, testOrganization.id), }); expect(updatedOrg?.total_microdollars_acquired).toBe( @@ -900,7 +900,7 @@ describe('processTopupForOrganization', () => { }) ).resolves.toBeUndefined(); - const updatedOrg = await db.query.organizations.findFirst({ + const updatedOrg = await db._query.organizations.findFirst({ where: eq(organizations.id, testOrganization.id), }); expect(updatedOrg?.total_microdollars_acquired).toBe( @@ -941,14 +941,14 @@ describe('processTopupForOrganization', () => { stripe_payment_id: stripePaymentId, }); - const updatedOrg = await db.query.organizations.findFirst({ + const updatedOrg = await db._query.organizations.findFirst({ where: eq(organizations.id, testOrganization.id), }); expect(updatedOrg?.total_microdollars_acquired).toBe( testOrganization.total_microdollars_acquired + expectedBalanceIncrease ); - const transactions = await db.query.credit_transactions.findMany({ + const transactions = await db._query.credit_transactions.findMany({ where: and( eq(credit_transactions.organization_id, testOrganization.id), eq(credit_transactions.stripe_payment_id, stripePaymentId) @@ -956,7 +956,7 @@ describe('processTopupForOrganization', () => { }); expect(transactions).toHaveLength(1); - const auditLogs = await db.query.organization_audit_logs.findMany({ + const auditLogs = await db._query.organization_audit_logs.findMany({ where: and( eq(organization_audit_logs.organization_id, testOrganization.id), eq(organization_audit_logs.action, 'organization.purchase_credits') @@ -1009,7 +1009,7 @@ describe('processTopupForOrganization', () => { const emailMarkers = await getOrganizationTopUpEmailMarkers(stripePaymentId); expect(emailMarkers).toHaveLength(1); - const updatedOrg = await db.query.organizations.findFirst({ + const updatedOrg = await db._query.organizations.findFirst({ where: eq(organizations.id, testOrganization.id), }); expect(updatedOrg?.total_microdollars_acquired).toBe( @@ -1037,7 +1037,7 @@ describe('processTopupForOrganization', () => { stripe_payment_id: stripePaymentId, }); - const updatedOrg = await db.query.organizations.findFirst({ + const updatedOrg = await db._query.organizations.findFirst({ where: eq(organizations.id, testOrganization.id), }); expect(updatedOrg?.total_microdollars_acquired).toBe( @@ -1045,7 +1045,7 @@ describe('processTopupForOrganization', () => { ); expect(sendViaMailgunMock).not.toHaveBeenCalled(); - const emailMarkers = await db.query.transactional_email_log.findMany({ + const emailMarkers = await db._query.transactional_email_log.findMany({ where: eq(transactional_email_log.idempotency_key, stripePaymentId), }); expect(emailMarkers).toHaveLength(0); @@ -1069,7 +1069,7 @@ describe('processTopupForOrganization', () => { stripe_payment_id: stripePaymentId, }); - const updatedOrg = await db.query.organizations.findFirst({ + const updatedOrg = await db._query.organizations.findFirst({ where: eq(organizations.id, testOrganization.id), }); expect(updatedOrg?.total_microdollars_acquired).toBe( @@ -1077,7 +1077,7 @@ describe('processTopupForOrganization', () => { ); expect(sendViaMailgunMock).not.toHaveBeenCalled(); - const emailMarkers = await db.query.transactional_email_log.findMany({ + const emailMarkers = await db._query.transactional_email_log.findMany({ where: eq(transactional_email_log.idempotency_key, stripePaymentId), }); expect(emailMarkers).toHaveLength(0); @@ -1105,7 +1105,7 @@ describe('processTopupForOrganization', () => { }); // Verify final balance - const updatedOrg = await db.query.organizations.findFirst({ + const updatedOrg = await db._query.organizations.findFirst({ where: eq(organizations.id, testOrganization.id), }); @@ -1118,7 +1118,7 @@ describe('processTopupForOrganization', () => { ); // Verify both credit transactions were created - const transactions = await db.query.credit_transactions.findMany({ + const transactions = await db._query.credit_transactions.findMany({ where: eq(credit_transactions.organization_id, testOrganization.id), }); @@ -1143,7 +1143,7 @@ describe('processTopupForOrganization', () => { }); // Verify balance was added to existing balance - const updatedOrg = await db.query.organizations.findFirst({ + const updatedOrg = await db._query.organizations.findFirst({ where: eq(organizations.id, testOrganization.id), }); @@ -1165,7 +1165,7 @@ describe('processTopupForOrganization', () => { stripe_payment_id: 'pi_test_timestamp', }); - const updatedOrg = await db.query.organizations.findFirst({ + const updatedOrg = await db._query.organizations.findFirst({ where: eq(organizations.id, testOrganization.id), }); @@ -1185,7 +1185,7 @@ describe('processTopupForOrganization', () => { }); // Verify balance remains unchanged - const updatedOrg = await db.query.organizations.findFirst({ + const updatedOrg = await db._query.organizations.findFirst({ where: eq(organizations.id, testOrganization.id), }); @@ -1194,7 +1194,7 @@ describe('processTopupForOrganization', () => { expect(computedBalanceZero).toBe(initialBalance); // Verify credit transaction was still created with zero amount - const creditTransaction = await db.query.credit_transactions.findFirst({ + const creditTransaction = await db._query.credit_transactions.findFirst({ where: eq(credit_transactions.stripe_payment_id, 'pi_test_zero_amount'), }); @@ -1210,7 +1210,7 @@ describe('processTopupForOrganization', () => { stripe_payment_id: 'pi_test_preserve_fields', }); - const updatedOrg = await db.query.organizations.findFirst({ + const updatedOrg = await db._query.organizations.findFirst({ where: eq(organizations.id, testOrganization.id), }); diff --git a/apps/web/src/lib/organizations/organizations.test.ts b/apps/web/src/lib/organizations/organizations.test.ts index 34fcfff764..399af822f9 100644 --- a/apps/web/src/lib/organizations/organizations.test.ts +++ b/apps/web/src/lib/organizations/organizations.test.ts @@ -721,7 +721,7 @@ describe('Organizations', () => { ); // Verify invitation exists in database - const storedInvitation = await db.query.organization_invitations.findFirst({ + const storedInvitation = await db._query.organization_invitations.findFirst({ where: eq(organization_invitations.id, invitation.id), }); @@ -1365,7 +1365,7 @@ describe('Organizations', () => { expect(userOrgs[0].role).toBe('member'); // Verify invitation is marked as accepted in database - const storedInvitation = await db.query.organization_invitations.findFirst({ + const storedInvitation = await db._query.organization_invitations.findFirst({ where: eq(organization_invitations.token, invitation.token), }); expect(storedInvitation?.accepted_at).toBeDefined(); @@ -1517,7 +1517,7 @@ describe('Organizations', () => { await acceptOrganizationInvite(invitee.id, invitation.token); // Verify membership has correct invited_by information - const membership = await db.query.organization_memberships.findFirst({ + const membership = await db._query.organization_memberships.findFirst({ where: and( eq(organization_memberships.organization_id, organization.id), eq(organization_memberships.kilo_user_id, invitee.id) @@ -1605,13 +1605,13 @@ describe('Organizations', () => { } // Verify invitation is marked as accepted - const storedInvitation = await db.query.organization_invitations.findFirst({ + const storedInvitation = await db._query.organization_invitations.findFirst({ where: eq(organization_invitations.token, invitation.token), }); expect(storedInvitation?.accepted_at).not.toBeNull(); // Verify membership was created - const membership = await db.query.organization_memberships.findFirst({ + const membership = await db._query.organization_memberships.findFirst({ where: and( eq(organization_memberships.organization_id, organization.id), eq(organization_memberships.kilo_user_id, invitee.id) @@ -1646,13 +1646,13 @@ describe('Organizations', () => { await acceptOrganizationInvite(invitee1.id, invitation1.token); // Verify first invitation is accepted - const storedInvitation1 = await db.query.organization_invitations.findFirst({ + const storedInvitation1 = await db._query.organization_invitations.findFirst({ where: eq(organization_invitations.token, invitation1.token), }); expect(storedInvitation1?.accepted_at).not.toBeNull(); // Verify second invitation is still pending - const storedInvitation2 = await db.query.organization_invitations.findFirst({ + const storedInvitation2 = await db._query.organization_invitations.findFirst({ where: eq(organization_invitations.token, invitation2.token), }); expect(storedInvitation2?.accepted_at).toBeNull(); @@ -1726,7 +1726,7 @@ describe('Organizations', () => { expect(result.success).toBe(true); // Verify no usage limit was set for require_seats organization - const userLimit = await db.query.organization_user_limits.findFirst({ + const userLimit = await db._query.organization_user_limits.findFirst({ where: and( eq(organization_user_limits.organization_id, organization.id), eq(organization_user_limits.kilo_user_id, invitee.id), @@ -1756,7 +1756,7 @@ describe('Organizations', () => { expect(result.success).toBe(true); // Verify no usage limit was set for require_seats organization - const userLimit = await db.query.organization_user_limits.findFirst({ + const userLimit = await db._query.organization_user_limits.findFirst({ where: and( eq(organization_user_limits.organization_id, organization.id), eq(organization_user_limits.kilo_user_id, invitee.id), @@ -1785,7 +1785,7 @@ describe('Organizations', () => { expect(result.success).toBe(true); // Verify no usage limit was set for owner - const userLimit = await db.query.organization_user_limits.findFirst({ + const userLimit = await db._query.organization_user_limits.findFirst({ where: and( eq(organization_user_limits.organization_id, organization.id), eq(organization_user_limits.kilo_user_id, invitee.id), @@ -1815,7 +1815,7 @@ describe('Organizations', () => { expect(userOrgs[0].role).toBe('owner'); // Verify no usage limit was set - const userLimit = await db.query.organization_user_limits.findFirst({ + const userLimit = await db._query.organization_user_limits.findFirst({ where: and( eq(organization_user_limits.organization_id, organization.id), eq(organization_user_limits.kilo_user_id, invitee.id), @@ -1845,7 +1845,7 @@ describe('Organizations', () => { expect(result.success).toBe(true); // Verify no usage limit was set for require_seats organization - const userLimit = await db.query.organization_user_limits.findFirst({ + const userLimit = await db._query.organization_user_limits.findFirst({ where: and( eq(organization_user_limits.organization_id, organization.id), eq(organization_user_limits.kilo_user_id, invitee.id), @@ -1875,7 +1875,7 @@ describe('Organizations', () => { expect(result.success).toBe(true); // Verify no usage limit was set for require_seats organization - const userLimit = await db.query.organization_user_limits.findFirst({ + const userLimit = await db._query.organization_user_limits.findFirst({ where: and( eq(organization_user_limits.organization_id, organization.id), eq(organization_user_limits.kilo_user_id, invitee.id), @@ -1921,7 +1921,7 @@ describe('Organizations', () => { expect(result.success).toBe(true); // Verify usage limit was set for non-require_seats organization - const userLimit = await db.query.organization_user_limits.findFirst({ + const userLimit = await db._query.organization_user_limits.findFirst({ where: and( eq(organization_user_limits.organization_id, organization.id), eq(organization_user_limits.kilo_user_id, invitee.id), @@ -1968,7 +1968,7 @@ describe('Organizations', () => { expect(result.success).toBe(true); // Verify usage limit was set for non-require_seats organization - const userLimit = await db.query.organization_user_limits.findFirst({ + const userLimit = await db._query.organization_user_limits.findFirst({ where: and( eq(organization_user_limits.organization_id, organization.id), eq(organization_user_limits.kilo_user_id, invitee.id), diff --git a/apps/web/src/lib/organizations/organizations.ts b/apps/web/src/lib/organizations/organizations.ts index ef08f45755..4dd9608f18 100644 --- a/apps/web/src/lib/organizations/organizations.ts +++ b/apps/web/src/lib/organizations/organizations.ts @@ -32,7 +32,7 @@ export async function getOrganizationById( txn?: DrizzleTransaction ): Promise { return ( - (await (txn || db).query.organizations.findFirst({ + (await (txn || db)._query.organizations.findFirst({ where: and(eq(organizations.id, id), isNull(organizations.deleted_at)), })) || null ); @@ -43,7 +43,7 @@ export async function findOrganizationByStripeCustomerId( txn?: DrizzleTransaction ): Promise { return ( - (await (txn || db).query.organizations.findFirst({ + (await (txn || db)._query.organizations.findFirst({ where: and( eq(organizations.stripe_customer_id, stripeCustomerId), isNull(organizations.deleted_at) @@ -611,7 +611,7 @@ export async function isOrganizationMember( userId: User['id'], fromDb: typeof db = db ) { - const result = await fromDb.query.organization_memberships.findFirst({ + const result = await fromDb._query.organization_memberships.findFirst({ where: and( eq(organization_memberships.organization_id, organizationId), eq(organization_memberships.kilo_user_id, userId) @@ -651,7 +651,7 @@ export async function doesOrgWithSSODomainExist(domain: string): Promise { - const has_github_auth = await db.query.user_auth_provider.findFirst({ + const has_github_auth = await db._query.user_auth_provider.findFirst({ where: and( eq(user_auth_provider.kilo_user_id, customerInfo.user.id), eq(user_auth_provider.provider, 'github') @@ -62,7 +62,7 @@ export function created_before(cutoff: Date): SyncCustomerRequirement { } export const has_githubAuth: CustomerRequirement = async customerInfo => { - const has_github_auth = await db.query.user_auth_provider.findFirst({ + const has_github_auth = await db._query.user_auth_provider.findFirst({ where: and( eq(user_auth_provider.kilo_user_id, customerInfo.user.id), eq(user_auth_provider.provider, 'github') diff --git a/apps/web/src/lib/recomputeNextCreditExpiration.ts b/apps/web/src/lib/recomputeNextCreditExpiration.ts index c8c530ef07..7eac0a7279 100644 --- a/apps/web/src/lib/recomputeNextCreditExpiration.ts +++ b/apps/web/src/lib/recomputeNextCreditExpiration.ts @@ -20,7 +20,7 @@ export async function recomputeNextCreditExpiration( ): Promise { const { dryRun = false } = options; - const user = await db.query.kilocode_users.findFirst({ + const user = await db._query.kilocode_users.findFirst({ where: eq(kilocode_users.id, kiloUserId), columns: { next_credit_expiration_at: true }, }); diff --git a/apps/web/src/lib/recomputeOrganizationBalances.test.ts b/apps/web/src/lib/recomputeOrganizationBalances.test.ts index a1bfe1ac71..99ce7f289d 100644 --- a/apps/web/src/lib/recomputeOrganizationBalances.test.ts +++ b/apps/web/src/lib/recomputeOrganizationBalances.test.ts @@ -19,7 +19,7 @@ async function createTestOrg( if (Object.keys(overrides).length > 0) { await db.update(organizations).set(overrides).where(eq(organizations.id, org.id)); } - return (await db.query.organizations.findFirst({ where: eq(organizations.id, org.id) }))!; + return (await db._query.organizations.findFirst({ where: eq(organizations.id, org.id) }))!; } describe('recomputeOrganizationBalances', () => { @@ -100,7 +100,7 @@ describe('recomputeOrganizationBalances', () => { const result = await recomputeOrganizationBalances({ organizationId: orgId }); expect(result.success).toBe(true); - const updatedOrg = await db.query.organizations.findFirst({ + const updatedOrg = await db._query.organizations.findFirst({ where: eq(organizations.id, orgId), }); expect(updatedOrg!.microdollars_used).toBe(3_000_000); @@ -122,7 +122,7 @@ describe('recomputeOrganizationBalances', () => { const result = await recomputeOrganizationBalances({ organizationId: orgId }); expect(result.success).toBe(true); - const updatedOrg = await db.query.organizations.findFirst({ + const updatedOrg = await db._query.organizations.findFirst({ where: eq(organizations.id, orgId), }); expect(updatedOrg!.microdollars_used).toBe(0); @@ -155,7 +155,7 @@ describe('recomputeOrganizationBalances', () => { } // Org should NOT be updated - const unchangedOrg = await db.query.organizations.findFirst({ + const unchangedOrg = await db._query.organizations.findFirst({ where: eq(organizations.id, orgId), }); expect(unchangedOrg!.microdollars_used).toBe(999); @@ -268,7 +268,7 @@ describe('recomputeOrganizationBalances', () => { const result = await recomputeOrganizationBalances({ organizationId: orgId }); expect(result.success).toBe(true); - const updatedOrg = await db.query.organizations.findFirst({ + const updatedOrg = await db._query.organizations.findFirst({ where: eq(organizations.id, orgId), }); // microdollars_used corrected to 3M @@ -299,7 +299,7 @@ describe('recomputeOrganizationBalances', () => { await recomputeOrganizationBalances({ organizationId: orgId }); - const updatedOrg = await db.query.organizations.findFirst({ + const updatedOrg = await db._query.organizations.findFirst({ where: eq(organizations.id, orgId), }); expect(updatedOrg!.microdollars_balance).toBe( @@ -359,7 +359,7 @@ describe('recomputeOrganizationBalances', () => { const result = await recomputeOrganizationBalances({ organizationId: orgId }); expect(result.success).toBe(true); - const updatedOrg = await db.query.organizations.findFirst({ + const updatedOrg = await db._query.organizations.findFirst({ where: eq(organizations.id, orgId), }); // Recomputed microdollars_used should be LLM ($2) + Exa ($3) = $5 diff --git a/apps/web/src/lib/recomputeOrganizationBalances.ts b/apps/web/src/lib/recomputeOrganizationBalances.ts index 04a7b397dd..8ea792080d 100644 --- a/apps/web/src/lib/recomputeOrganizationBalances.ts +++ b/apps/web/src/lib/recomputeOrganizationBalances.ts @@ -43,7 +43,7 @@ export async function recomputeOrganizationBalances(args: { organizationId: string; dryRun?: boolean; }): Promise> { - const org = await db.query.organizations.findFirst({ + const org = await db._query.organizations.findFirst({ where: eq(organizations.id, args.organizationId), columns: { id: true, diff --git a/apps/web/src/lib/recomputeUserBalances.test.ts b/apps/web/src/lib/recomputeUserBalances.test.ts index d4b69cb174..e25b9ccd95 100644 --- a/apps/web/src/lib/recomputeUserBalances.test.ts +++ b/apps/web/src/lib/recomputeUserBalances.test.ts @@ -70,7 +70,7 @@ describe('recomputeUserBalances', () => { } // Verify no adjustment transaction - const adjustmentTx = await db.query.credit_transactions.findFirst({ + const adjustmentTx = await db._query.credit_transactions.findFirst({ where: and( eq(credit_transactions.kilo_user_id, user.id), eq(credit_transactions.credit_category, 'accounting_adjustment') @@ -110,7 +110,7 @@ describe('recomputeUserBalances', () => { } // Verify adjustment transaction - const adjustmentTx = await db.query.credit_transactions.findFirst({ + const adjustmentTx = await db._query.credit_transactions.findFirst({ where: and( eq(credit_transactions.kilo_user_id, user.id), eq(credit_transactions.credit_category, 'accounting_adjustment') @@ -120,7 +120,7 @@ describe('recomputeUserBalances', () => { expect(adjustmentTx?.amount_microdollars).toBe(2_000_000); // Verify user total acquired is updated to include adjustment (should match original user total) - const updatedUser = await db.query.kilocode_users.findFirst({ + const updatedUser = await db._query.kilocode_users.findFirst({ where: eq(kilocode_users.id, user.id), }); expect(updatedUser?.total_microdollars_acquired).toBe(12_000_000); @@ -170,7 +170,7 @@ describe('recomputeUserBalances', () => { expect(result.success).toBe(true); // Verify baselines - const tx = await db.query.credit_transactions.findFirst({ + const tx = await db._query.credit_transactions.findFirst({ where: eq(credit_transactions.kilo_user_id, user.id), }); expect(tx?.original_baseline_microdollars_used).toBe(1_000_000); @@ -205,7 +205,7 @@ describe('recomputeUserBalances', () => { } // Verify NO adjustment transaction - const adjustmentTx = await db.query.credit_transactions.findFirst({ + const adjustmentTx = await db._query.credit_transactions.findFirst({ where: and( eq(credit_transactions.kilo_user_id, user.id), eq(credit_transactions.credit_category, 'accounting_adjustment') @@ -485,7 +485,7 @@ describe('recomputeUserBalances', () => { expect(result.success).toBe(true); // Recomputed microdollars_used should be LLM ($2) + Exa ($3) = $5 - const updatedUser = await db.query.kilocode_users.findFirst({ + const updatedUser = await db._query.kilocode_users.findFirst({ where: eq(kilocode_users.id, user.id), }); expect(updatedUser!.microdollars_used).toBe(5_000_000); @@ -525,7 +525,7 @@ describe('recomputeUserBalances', () => { expect(result.success).toBe(true); // Only LLM usage (none) should count — org Exa is excluded - const updatedUser = await db.query.kilocode_users.findFirst({ + const updatedUser = await db._query.kilocode_users.findFirst({ where: eq(kilocode_users.id, user.id), }); expect(updatedUser!.microdollars_used).toBe(0); diff --git a/apps/web/src/lib/recomputeUserBalances.ts b/apps/web/src/lib/recomputeUserBalances.ts index 4fe4aa7872..ab452e685c 100644 --- a/apps/web/src/lib/recomputeUserBalances.ts +++ b/apps/web/src/lib/recomputeUserBalances.ts @@ -61,7 +61,7 @@ export type UserBalanceUpdates = { }; async function fetchUserBalanceData(userId: string) { - const user = await db.query.kilocode_users.findFirst({ + const user = await db._query.kilocode_users.findFirst({ where: eq(kilocode_users.id, userId), columns: { id: true, diff --git a/apps/web/src/lib/referral.ts b/apps/web/src/lib/referral.ts index ee77474456..38bb70e655 100644 --- a/apps/web/src/lib/referral.ts +++ b/apps/web/src/lib/referral.ts @@ -159,7 +159,7 @@ async function validateReferralForRedemption(kiloUserId: string) { const { code, referring_kilo_user_id } = referralUsage; // Get the referral code record to check max_redemptions - const referralCodeRecord = await db.query.referral_codes.findFirst({ + const referralCodeRecord = await db._query.referral_codes.findFirst({ where: eq(referral_codes.code, code), }); diff --git a/apps/web/src/lib/stripe.ts b/apps/web/src/lib/stripe.ts index 874ec5b2d4..5386e094a7 100644 --- a/apps/web/src/lib/stripe.ts +++ b/apps/web/src/lib/stripe.ts @@ -94,7 +94,7 @@ export async function isCardFingerprintEligibleForFreeCredits( ): Promise { return ( !!fingerprint && - (await db.query.payment_methods.findFirst({ + (await db._query.payment_methods.findFirst({ columns: { id: true }, where: and( eq(payment_methods.stripe_fingerprint, fingerprint), @@ -142,7 +142,7 @@ export async function ensurePaymentMethodStored( ): Promise { const { http_user_agent: _http_user_agent, ...headersWithoutUserAgent } = headers; - const currentPaymentMethod = await db.query.payment_methods.findFirst({ + const currentPaymentMethod = await db._query.payment_methods.findFirst({ where: and( eq(payment_methods.user_id, kiloUserId), eq(payment_methods.stripe_id, paymentMethod.id), @@ -251,7 +251,7 @@ async function findUserByStripeCustomer( } return ( - (await db.query.kilocode_users.findFirst({ + (await db._query.kilocode_users.findFirst({ where: eq(kilocode_users.stripe_customer_id, customer), })) || null ); @@ -678,7 +678,7 @@ export async function processStripePaymentEventHook(event: Stripe.Event) { const kiloUserId = invoice.metadata?.kiloUserId; if (!kiloUserId) break; - const user = await db.query.kilocode_users.findFirst({ + const user = await db._query.kilocode_users.findFirst({ where: eq(kilocode_users.id, kiloUserId), }); if (!user) break; @@ -744,7 +744,7 @@ export async function processStripePaymentEventHook(event: Stripe.Event) { traceId, }); - const autoTopUpConfig = await db.query.auto_top_up_configs.findFirst({ + const autoTopUpConfig = await db._query.auto_top_up_configs.findFirst({ where: eq(auto_top_up_configs.owned_by_organization_id, organizationId), columns: { created_by_user_id: true }, }); diff --git a/apps/web/src/lib/stytch.test.ts b/apps/web/src/lib/stytch.test.ts index 23687ffb24..d9640979ae 100644 --- a/apps/web/src/lib/stytch.test.ts +++ b/apps/web/src/lib/stytch.test.ts @@ -133,7 +133,7 @@ describe('Stytch Fingerprint Functions', () => { expect(result.kilo_free_tier_allowed).toBe(true); // Verify data was saved to database - const savedFingerprint = await db.query.stytch_fingerprints.findFirst({ + const savedFingerprint = await db._query.stytch_fingerprints.findFirst({ where: eq(stytch_fingerprints.kilo_user_id, user.id), }); @@ -165,7 +165,7 @@ describe('Stytch Fingerprint Functions', () => { expect(result.kilo_free_tier_allowed).toBe(false); - const savedFingerprint = await db.query.stytch_fingerprints.findFirst({ + const savedFingerprint = await db._query.stytch_fingerprints.findFirst({ where: eq(stytch_fingerprints.kilo_user_id, user.id), }); @@ -183,7 +183,7 @@ describe('Stytch Fingerprint Functions', () => { expect(result.kilo_free_tier_allowed).toBe(false); - const savedFingerprint = await db.query.stytch_fingerprints.findFirst({ + const savedFingerprint = await db._query.stytch_fingerprints.findFirst({ where: eq(stytch_fingerprints.kilo_user_id, user2.id), }); @@ -201,7 +201,7 @@ describe('Stytch Fingerprint Functions', () => { await handleSignupPromotion(user, kilo_free_tier_allowed); // Check if credit was granted - const creditTransaction = await db.query.credit_transactions.findFirst({ + const creditTransaction = await db._query.credit_transactions.findFirst({ where: eq(credit_transactions.kilo_user_id, user.id), }); @@ -234,7 +234,7 @@ describe('Stytch Fingerprint Functions', () => { await saveFingerprints(user, fingerprintData, createMockHeaders()); - const updatedUser = await db.query.kilocode_users.findFirst({ + const updatedUser = await db._query.kilocode_users.findFirst({ where: eq(kilocode_users.id, user.id), columns: { blocked_reason: true }, }); @@ -261,7 +261,7 @@ describe('Stytch Fingerprint Functions', () => { await saveFingerprints(user, fingerprintData, createMockHeaders()); - const updatedUser = await db.query.kilocode_users.findFirst({ + const updatedUser = await db._query.kilocode_users.findFirst({ where: eq(kilocode_users.id, user.id), columns: { blocked_reason: true }, }); @@ -283,7 +283,7 @@ describe('Stytch Fingerprint Functions', () => { await saveFingerprints(user, fingerprintData, createMockHeaders()); - const updatedUser = await db.query.kilocode_users.findFirst({ + const updatedUser = await db._query.kilocode_users.findFirst({ where: eq(kilocode_users.id, user.id), columns: { blocked_reason: true }, }); @@ -318,7 +318,7 @@ describe('Stytch Fingerprint Functions', () => { await handleSignupPromotion(user, true, { kind: 'openclaw-security-advisor' }); - const grants = await db.query.credit_transactions.findMany({ + const grants = await db._query.credit_transactions.findMany({ where: eq(credit_transactions.kilo_user_id, user.id), }); @@ -342,7 +342,7 @@ describe('Stytch Fingerprint Functions', () => { await handleSignupPromotion(user, true, null); - const grants = await db.query.credit_transactions.findMany({ + const grants = await db._query.credit_transactions.findMany({ where: eq(credit_transactions.kilo_user_id, user.id), }); @@ -356,7 +356,7 @@ describe('Stytch Fingerprint Functions', () => { await handleSignupPromotion(user, false, { kind: 'openclaw-security-advisor' }); - const grants = await db.query.credit_transactions.findMany({ + const grants = await db._query.credit_transactions.findMany({ where: eq(credit_transactions.kilo_user_id, user.id), }); @@ -371,7 +371,7 @@ describe('Stytch Fingerprint Functions', () => { await handleSignupPromotion(user, true, { kind: 'openclaw-security-advisor' }); await handleSignupPromotion(user, true, { kind: 'openclaw-security-advisor' }); - const bonusRows = await db.query.credit_transactions.findMany({ + const bonusRows = await db._query.credit_transactions.findMany({ where: eq(credit_transactions.kilo_user_id, user.id), }); @@ -423,7 +423,7 @@ describe('Stytch Fingerprint Functions', () => { await handleSignupPromotion(user, true, { kind: 'credit-campaign', slug }); - const grants = await db.query.credit_transactions.findMany({ + const grants = await db._query.credit_transactions.findMany({ where: eq(credit_transactions.kilo_user_id, user.id), }); const byCategory = new Map(grants.map(g => [g.credit_category, g])); @@ -452,7 +452,7 @@ describe('Stytch Fingerprint Functions', () => { slug: `never-created-${Date.now()}`, }); - const grants = await db.query.credit_transactions.findMany({ + const grants = await db._query.credit_transactions.findMany({ where: eq(credit_transactions.kilo_user_id, user.id), }); expect(grants.map(g => g.credit_category).sort()).toEqual(['automatic-welcome-credits']); @@ -467,7 +467,7 @@ describe('Stytch Fingerprint Functions', () => { await handleSignupPromotion(user, true, { kind: 'credit-campaign', slug }); - const grants = await db.query.credit_transactions.findMany({ + const grants = await db._query.credit_transactions.findMany({ where: eq(credit_transactions.kilo_user_id, user.id), }); expect(grants.map(g => g.credit_category).sort()).toEqual(['automatic-welcome-credits']); @@ -487,7 +487,7 @@ describe('Stytch Fingerprint Functions', () => { await handleSignupPromotion(user, true, { kind: 'credit-campaign', slug }); - const grants = await db.query.credit_transactions.findMany({ + const grants = await db._query.credit_transactions.findMany({ where: eq(credit_transactions.kilo_user_id, user.id), }); expect(grants.map(g => g.credit_category).sort()).toEqual(['automatic-welcome-credits']); @@ -511,7 +511,7 @@ describe('Stytch Fingerprint Functions', () => { }); await handleSignupPromotion(secondUser, true, { kind: 'credit-campaign', slug }); - const secondGrants = await db.query.credit_transactions.findMany({ + const secondGrants = await db._query.credit_transactions.findMany({ where: eq(credit_transactions.kilo_user_id, secondUser.id), }); expect(secondGrants.map(g => g.credit_category).sort()).toEqual([ @@ -529,7 +529,7 @@ describe('Stytch Fingerprint Functions', () => { await handleSignupPromotion(user, true, { kind: 'credit-campaign', slug }); await handleSignupPromotion(user, true, { kind: 'credit-campaign', slug }); - const rows = await db.query.credit_transactions.findMany({ + const rows = await db._query.credit_transactions.findMany({ where: eq(credit_transactions.kilo_user_id, user.id), }); const campaignOnly = rows.filter(g => g.credit_category === `c-${slug}`); @@ -545,7 +545,7 @@ describe('Stytch Fingerprint Functions', () => { await handleSignupPromotion(user, false, { kind: 'credit-campaign', slug }); - const grants = await db.query.credit_transactions.findMany({ + const grants = await db._query.credit_transactions.findMany({ where: eq(credit_transactions.kilo_user_id, user.id), }); expect(grants).toHaveLength(0); diff --git a/apps/web/src/lib/stytch.ts b/apps/web/src/lib/stytch.ts index 9e0da8667e..d49441ea18 100644 --- a/apps/web/src/lib/stytch.ts +++ b/apps/web/src/lib/stytch.ts @@ -54,7 +54,7 @@ export const getStytchStatus = async ( }; export async function getStoredFingerprint(kiloUserId: string) { - return await db.query.stytch_fingerprints.findFirst({ + return await db._query.stytch_fingerprints.findFirst({ where: eq(stytch_fingerprints.kilo_user_id, kiloUserId), }); } @@ -63,7 +63,7 @@ export async function isKnownFingerprintOfOtherUser( kiloUserId: string, visitorFingerprint: string ): Promise { - const existingFingerprints = await db.query.stytch_fingerprints.findMany({ + const existingFingerprints = await db._query.stytch_fingerprints.findMany({ where: eq(stytch_fingerprints.visitor_fingerprint, visitorFingerprint), columns: { kilo_user_id: true }, }); diff --git a/apps/web/src/lib/usageDeduction.test.ts b/apps/web/src/lib/usageDeduction.test.ts index 495b0a85d8..8f606ea38b 100644 --- a/apps/web/src/lib/usageDeduction.test.ts +++ b/apps/web/src/lib/usageDeduction.test.ts @@ -60,7 +60,7 @@ describe('Usage deduction for migrated users', () => { expect(result?.newMicrodollarsUsed).toBe(initialMicrodollarsUsed + usageCost); // Verify user's microdollars_used was updated in DB - const updatedUser = await db.query.kilocode_users.findFirst({ + const updatedUser = await db._query.kilocode_users.findFirst({ where: eq(kilocode_users.id, user.id), }); expect(updatedUser?.microdollars_used).toBe(initialMicrodollarsUsed + usageCost); @@ -85,7 +85,7 @@ describe('Usage deduction for migrated users', () => { expect(result?.newMicrodollarsUsed).toBe(usageCost); // Verify usage record was created - const usageRecords = await db.query.microdollar_usage.findMany({ + const usageRecords = await db._query.microdollar_usage.findMany({ where: eq(microdollar_usage.kilo_user_id, user.id), }); expect(usageRecords.length).toBe(1); @@ -116,7 +116,7 @@ describe('Usage deduction for migrated users', () => { } // Verify final state - const updatedUser = await db.query.kilocode_users.findFirst({ + const updatedUser = await db._query.kilocode_users.findFirst({ where: eq(kilocode_users.id, user.id), }); expect(updatedUser?.microdollars_used).toBe(45_000); // 10k + 20k + 15k @@ -139,7 +139,7 @@ describe('Usage deduction for migrated users', () => { await insertUsageRecord(core, metadata); // Verify balance calculation - const updatedUser = await db.query.kilocode_users.findFirst({ + const updatedUser = await db._query.kilocode_users.findFirst({ where: eq(kilocode_users.id, user.id), }); diff --git a/apps/web/src/lib/user.ts b/apps/web/src/lib/user.ts index 94c249466c..579b170764 100644 --- a/apps/web/src/lib/user.ts +++ b/apps/web/src/lib/user.ts @@ -114,7 +114,7 @@ export async function findUserById( userId: string, fromDb: typeof db = db ): Promise { - return await fromDb.query.kilocode_users.findFirst({ + return await fromDb._query.kilocode_users.findFirst({ where: eq(kilocode_users.id, userId), }); } @@ -122,7 +122,7 @@ export async function findUserById( export async function findUsersByIds(userIds: string[]): Promise> { if (userIds.length === 0) return new Map(); const uniqueUserIds = [...new Set(userIds)]; - const users = await db.query.kilocode_users.findMany({ + const users = await db._query.kilocode_users.findMany({ where: inArray(kilocode_users.id, uniqueUserIds), }); @@ -132,7 +132,7 @@ export async function findUsersByIds(userIds: string[]): Promise { - return await db.query.kilocode_users.findFirst({ + return await db._query.kilocode_users.findFirst({ where: eq(kilocode_users.stripe_customer_id, stripeCustomerId), }); } @@ -297,7 +297,7 @@ export async function findAndSyncExistingUser(args: CreateOrUpdateUserArgs) { } export async function findUserByEmail(email: string): Promise { - return await db.query.kilocode_users.findFirst({ + return await db._query.kilocode_users.findFirst({ where: eq(kilocode_users.google_user_email, email), }); } @@ -1170,7 +1170,7 @@ export async function findUserIdByAuthProvider( provider: AuthProviderId, providerAccountId: string ) { - const result = await db.query.user_auth_provider.findFirst({ + const result = await db._query.user_auth_provider.findFirst({ where: and( eq(user_auth_provider.provider, provider), eq(user_auth_provider.provider_account_id, providerAccountId) diff --git a/apps/web/src/lib/web-session-revocation.test.ts b/apps/web/src/lib/web-session-revocation.test.ts index 421ba3c9da..0ecf145d8e 100644 --- a/apps/web/src/lib/web-session-revocation.test.ts +++ b/apps/web/src/lib/web-session-revocation.test.ts @@ -26,7 +26,7 @@ describe('web session revocation', () => { await revokeWebSessions(user.id); - const updated = await db.query.kilocode_users.findFirst({ + const updated = await db._query.kilocode_users.findFirst({ where: eq(kilocode_users.id, user.id), }); @@ -44,7 +44,7 @@ describe('web session revocation', () => { await revokeWebSessions(user.id, tx); }); - const updated = await db.query.kilocode_users.findFirst({ + const updated = await db._query.kilocode_users.findFirst({ where: eq(kilocode_users.id, user.id), }); diff --git a/apps/web/src/routers/admin-app-builder-router.ts b/apps/web/src/routers/admin-app-builder-router.ts index 33cdc1aac9..58216e4949 100644 --- a/apps/web/src/routers/admin-app-builder-router.ts +++ b/apps/web/src/routers/admin-app-builder-router.ts @@ -267,7 +267,7 @@ export const adminAppBuilderRouter = createTRPCRouter({ const { id: projectId } = input; // Verify project exists - const project = await db.query.app_builder_projects.findFirst({ + const project = await db._query.app_builder_projects.findFirst({ where: eq(app_builder_projects.id, projectId), columns: { id: true, diff --git a/apps/web/src/routers/admin-deployments-router.ts b/apps/web/src/routers/admin-deployments-router.ts index 8d2840bff6..afc9db4f6c 100644 --- a/apps/web/src/routers/admin-deployments-router.ts +++ b/apps/web/src/routers/admin-deployments-router.ts @@ -218,7 +218,7 @@ export const adminDeploymentsRouter = createTRPCRouter({ const { id: deploymentId } = input; // Get owner from deployment - const deployment = await db.query.deployments.findFirst({ + const deployment = await db._query.deployments.findFirst({ where: eq(deployments.id, deploymentId), columns: { owned_by_user_id: true, diff --git a/apps/web/src/routers/admin-kiloclaw-instances-router.test.ts b/apps/web/src/routers/admin-kiloclaw-instances-router.test.ts index 62825bee01..849c907c41 100644 --- a/apps/web/src/routers/admin-kiloclaw-instances-router.test.ts +++ b/apps/web/src/routers/admin-kiloclaw-instances-router.test.ts @@ -348,7 +348,7 @@ describe('admin.kiloclawInstances.machineStart', () => { reason: 'admin_request', }); - const updatedInstance = await db.query.kiloclaw_instances.findFirst({ + const updatedInstance = await db._query.kiloclaw_instances.findFirst({ where: eq(kiloclaw_instances.id, instance.id), }); expect(updatedInstance?.inactive_trial_stopped_at).toBeNull(); @@ -394,7 +394,7 @@ describe('admin.kiloclawInstances.machineStart', () => { startedAt: null, }); - const updatedInstance = await db.query.kiloclaw_instances.findFirst({ + const updatedInstance = await db._query.kiloclaw_instances.findFirst({ where: eq(kiloclaw_instances.id, instance.id), }); expect(new Date(String(updatedInstance?.inactive_trial_stopped_at)).toISOString()).toBe( diff --git a/apps/web/src/routers/admin-kiloclaw-user-router.test.ts b/apps/web/src/routers/admin-kiloclaw-user-router.test.ts index 39d18fb55a..94a11ba491 100644 --- a/apps/web/src/routers/admin-kiloclaw-user-router.test.ts +++ b/apps/web/src/routers/admin-kiloclaw-user-router.test.ts @@ -775,7 +775,7 @@ describe('admin.users.updateKiloClawTrialEndAt', () => { expect(result).toEqual({ success: true }); - const updatedSubscription = await db.query.kiloclaw_subscriptions.findFirst({ + const updatedSubscription = await db._query.kiloclaw_subscriptions.findFirst({ where: eq(kiloclaw_subscriptions.user_id, targetUser.id), }); expectSameInstant(updatedSubscription?.trial_ends_at, newTrialEndsAt); @@ -887,7 +887,7 @@ describe('admin.users.updateKiloClawTrialEndAt', () => { 'Transferred KiloClaw subscriptions are historical and cannot be modified. Edit the current subscription instead.' ); - const unchanged = await db.query.kiloclaw_subscriptions.findFirst({ + const unchanged = await db._query.kiloclaw_subscriptions.findFirst({ where: eq(kiloclaw_subscriptions.id, transferredSub.id), }); expect(unchanged?.status).toBe('trialing'); @@ -939,7 +939,7 @@ describe('admin.users.updateKiloClawTrialEndAt', () => { 'Transferred KiloClaw subscriptions are historical and cannot be modified. Edit the current subscription instead.' ); - const unchanged = await db.query.kiloclaw_subscriptions.findFirst({ + const unchanged = await db._query.kiloclaw_subscriptions.findFirst({ where: eq(kiloclaw_subscriptions.id, transferredSub.id), }); expect(unchanged?.status).toBe('canceled'); @@ -979,7 +979,7 @@ describe('admin.users.updateKiloClawTrialEndAt', () => { expect(result).toEqual({ success: true }); - const updatedSubscription = await db.query.kiloclaw_subscriptions.findFirst({ + const updatedSubscription = await db._query.kiloclaw_subscriptions.findFirst({ where: eq(kiloclaw_subscriptions.user_id, targetUser.id), }); expect(updatedSubscription?.status).toBe('trialing'); @@ -1057,7 +1057,7 @@ describe('admin.users.updateKiloClawTrialEndAt', () => { reason: 'admin_request', }); - const updatedInstance = await db.query.kiloclaw_instances.findFirst({ + const updatedInstance = await db._query.kiloclaw_instances.findFirst({ where: eq(kiloclaw_instances.id, instance.id), }); expect(updatedInstance?.inactive_trial_stopped_at).toBeNull(); @@ -1105,7 +1105,7 @@ describe('admin.users.updateKiloClawTrialEndAt', () => { expect(result).toEqual({ success: true }); - const updatedInstance = await db.query.kiloclaw_instances.findFirst({ + const updatedInstance = await db._query.kiloclaw_instances.findFirst({ where: eq(kiloclaw_instances.id, instance.id), }); expect(new Date(String(updatedInstance?.inactive_trial_stopped_at)).toISOString()).toBe( @@ -1137,7 +1137,7 @@ describe('admin.users.cancelKiloClawSubscription', () => { expect(result).toEqual({ success: true }); // DB updated - const updated = await db.query.kiloclaw_subscriptions.findFirst({ + const updated = await db._query.kiloclaw_subscriptions.findFirst({ where: eq(kiloclaw_subscriptions.id, sub.id), }); expect(updated?.cancel_at_period_end).toBe(true); @@ -1167,7 +1167,7 @@ describe('admin.users.cancelKiloClawSubscription', () => { expect(result).toEqual({ success: true }); // DB updated — immediate cancel sets terminal state - const updated = await db.query.kiloclaw_subscriptions.findFirst({ + const updated = await db._query.kiloclaw_subscriptions.findFirst({ where: eq(kiloclaw_subscriptions.id, sub.id), }); expect(updated?.status).toBe('canceled'); @@ -1214,7 +1214,7 @@ describe('admin.users.cancelKiloClawSubscription', () => { expect(result).toEqual({ success: true }); - const updated = await db.query.kiloclaw_subscriptions.findFirst({ + const updated = await db._query.kiloclaw_subscriptions.findFirst({ where: eq(kiloclaw_subscriptions.id, sub.id), }); expect(updated?.status).toBe('canceled'); @@ -1256,7 +1256,7 @@ describe('admin.users.cancelKiloClawSubscription', () => { 'Transferred KiloClaw subscriptions are historical and cannot be modified. Edit the current subscription instead.' ); - const unchanged = await db.query.kiloclaw_subscriptions.findFirst({ + const unchanged = await db._query.kiloclaw_subscriptions.findFirst({ where: eq(kiloclaw_subscriptions.id, transferredSub.id), }); expect(unchanged?.status).toBe('trialing'); @@ -1364,7 +1364,7 @@ describe('admin.users.cancelKiloClawSubscription', () => { cancel_at_period_end: true, }); - const updated = await db.query.kiloclaw_subscriptions.findFirst({ + const updated = await db._query.kiloclaw_subscriptions.findFirst({ where: eq(kiloclaw_subscriptions.id, sub.id), }); expect(updated?.cancel_at_period_end).toBe(true); @@ -1427,7 +1427,7 @@ describe('admin.users.cancelKiloClawSubscription', () => { }) ).rejects.toThrow('Stripe cancellation was applied'); - const changed = await db.query.kiloclaw_subscriptions.findFirst({ + const changed = await db._query.kiloclaw_subscriptions.findFirst({ where: eq(kiloclaw_subscriptions.id, sub.id), }); expect(changed?.transferred_to_subscription_id).toBe(successorSub.id); @@ -1561,7 +1561,7 @@ describe('admin.users.cancelKiloClawSubscription', () => { mode: 'immediate', }); - const updated = await db.query.kiloclaw_subscriptions.findFirst({ + const updated = await db._query.kiloclaw_subscriptions.findFirst({ where: eq(kiloclaw_subscriptions.id, sub.id), }); expect(updated?.status).toBe('canceled'); @@ -1606,7 +1606,7 @@ describe('admin.users.cancelKiloClawSubscription', () => { }) ).rejects.toThrow('Stripe cancellation was applied'); - const updated = await db.query.kiloclaw_subscriptions.findFirst({ + const updated = await db._query.kiloclaw_subscriptions.findFirst({ where: eq(kiloclaw_subscriptions.id, sub.id), }); expect(updated?.status).toBe('canceled'); @@ -1649,7 +1649,7 @@ describe('admin.users.cancelKiloClawSubscription', () => { }); // DB cleared schedule fields - const updated = await db.query.kiloclaw_subscriptions.findFirst({ + const updated = await db._query.kiloclaw_subscriptions.findFirst({ where: eq(kiloclaw_subscriptions.id, sub.id), }); expect(updated?.stripe_schedule_id).toBeNull(); @@ -1725,7 +1725,7 @@ describe('admin.users.cancelKiloClawSubscription', () => { expect(result).toEqual({ success: true }); - const updated = await db.query.kiloclaw_subscriptions.findFirst({ + const updated = await db._query.kiloclaw_subscriptions.findFirst({ where: eq(kiloclaw_subscriptions.id, sub.id), }); expect(updated?.status).toBe('canceled'); diff --git a/apps/web/src/routers/admin-router.ts b/apps/web/src/routers/admin-router.ts index d73515480f..72c3db7648 100644 --- a/apps/web/src/routers/admin-router.ts +++ b/apps/web/src/routers/admin-router.ts @@ -434,7 +434,7 @@ export const adminRouter = createTRPCRouter({ }), checkKiloPass: adminProcedure.input(CheckKiloPassSchema).mutation(async ({ input }) => { - const before = await db.query.kilocode_users.findFirst({ + const before = await db._query.kilocode_users.findFirst({ columns: { microdollars_used: true, kilo_pass_threshold: true, @@ -451,7 +451,7 @@ export const adminRouter = createTRPCRouter({ nowIso: new Date().toISOString(), }); - const after = await db.query.kilocode_users.findFirst({ + const after = await db._query.kilocode_users.findFirst({ columns: { microdollars_used: true, kilo_pass_threshold: true, @@ -466,7 +466,7 @@ export const adminRouter = createTRPCRouter({ .input(ResetToMagicLinkLoginSchema) .mutation(async ({ input }) => { // Check if user has SSO (workos) provider - forbid reset for SSO users - const ssoProvider = await db.query.user_auth_provider.findFirst({ + const ssoProvider = await db._query.user_auth_provider.findFirst({ where: and( eq(user_auth_provider.kilo_user_id, input.userId), eq(user_auth_provider.provider, 'workos') @@ -581,7 +581,7 @@ export const adminRouter = createTRPCRouter({ getKiloPassState: adminProcedure .input(z.object({ userId: z.string() })) .query(async ({ input }) => { - const user = await db.query.kilocode_users.findFirst({ + const user = await db._query.kilocode_users.findFirst({ columns: { microdollars_used: true, total_microdollars_acquired: true, @@ -675,7 +675,7 @@ export const adminRouter = createTRPCRouter({ }), getKiloClawState: adminProcedure.input(GetKiloClawStateSchema).query(async ({ input }) => { - const user = await db.query.kilocode_users.findFirst({ + const user = await db._query.kilocode_users.findFirst({ columns: { id: true, kiloclaw_early_access: true }, where: eq(kilocode_users.id, input.userId), }); @@ -692,7 +692,7 @@ export const adminRouter = createTRPCRouter({ .where(eq(kiloclaw_subscriptions.user_id, input.userId)) .orderBy(desc(kiloclaw_subscriptions.created_at)), getKiloClawEarlybirdStateForUser(input.userId, now), - db.query.kiloclaw_instances.findFirst({ + db._query.kiloclaw_instances.findFirst({ columns: { id: true }, where: and( eq(kiloclaw_instances.user_id, input.userId), @@ -788,7 +788,7 @@ export const adminRouter = createTRPCRouter({ getKiloClawSubscriptionChangeLogs: adminProcedure .input(GetKiloClawSubscriptionChangeLogsSchema) .query(async ({ input }) => { - const subscription = await db.query.kiloclaw_subscriptions.findFirst({ + const subscription = await db._query.kiloclaw_subscriptions.findFirst({ columns: { id: true }, where: and( eq(kiloclaw_subscriptions.id, input.subscriptionId), @@ -819,7 +819,7 @@ export const adminRouter = createTRPCRouter({ updateKiloClawTrialEndAt: adminProcedure .input(UpdateKiloClawTrialEndAtSchema) .mutation(async ({ input, ctx }) => { - const user = await db.query.kilocode_users.findFirst({ + const user = await db._query.kilocode_users.findFirst({ columns: { id: true }, where: eq(kilocode_users.id, input.userId), }); @@ -1337,7 +1337,7 @@ export const adminRouter = createTRPCRouter({ cancelAndRefundKiloPass: adminProcedure .input(CancelAndRefundKiloPassSchema) .mutation(async ({ input, ctx }) => { - const userExists = await db.query.kilocode_users.findFirst({ + const userExists = await db._query.kilocode_users.findFirst({ columns: { id: true }, where: eq(kilocode_users.id, input.userId), }); @@ -1380,7 +1380,7 @@ export const adminRouter = createTRPCRouter({ const { user_id, github_enrichment_data, linkedin_enrichment_data, clay_enrichment_data } = input; - const user = await db.query.kilocode_users.findFirst({ + const user = await db._query.kilocode_users.findFirst({ where: eq(kilocode_users.id, user_id), }); @@ -1391,7 +1391,7 @@ export const adminRouter = createTRPCRouter({ }); } - const existingData = await db.query.enrichment_data.findFirst({ + const existingData = await db._query.enrichment_data.findFirst({ where: eq(enrichment_data.user_id, user_id), }); diff --git a/apps/web/src/routers/admin/custom-llm-router.ts b/apps/web/src/routers/admin/custom-llm-router.ts index c3d6c6bb46..80d4fd581e 100644 --- a/apps/web/src/routers/admin/custom-llm-router.ts +++ b/apps/web/src/routers/admin/custom-llm-router.ts @@ -29,7 +29,7 @@ export const adminCustomLlmRouter = createTRPCRouter({ }), upsert: adminProcedure.input(UpsertCustomLlmSchema).mutation(async ({ input }) => { - const existing = await db.query.custom_llm2.findFirst({ + const existing = await db._query.custom_llm2.findFirst({ where: eq(custom_llm2.public_id, input.public_id), }); diff --git a/apps/web/src/routers/admin/kilo-pass-router.test.ts b/apps/web/src/routers/admin/kilo-pass-router.test.ts index 3aa939b5e8..b6d6c4c65d 100644 --- a/apps/web/src/routers/admin/kilo-pass-router.test.ts +++ b/apps/web/src/routers/admin/kilo-pass-router.test.ts @@ -243,7 +243,7 @@ describe('admin.kiloPass.cancelAndRefundKiloPassBulk', () => { expect(result.results[0].status).toBe('cancelled_and_refunded'); expect(result.results[0].refundedAmountCents).toBeNull(); - const row = await db.query.kilo_pass_subscriptions.findFirst({ + const row = await db._query.kilo_pass_subscriptions.findFirst({ where: eq(kilo_pass_subscriptions.stripe_subscription_id, 'sub_already_refunded'), }); expect(row?.status).toBe('canceled'); @@ -281,14 +281,14 @@ describe('admin.kiloPass.cancelAndRefundKiloPassBulk', () => { expect(row.alreadyBlocked).toBe(false); // Subscription updated - const subRow = await db.query.kilo_pass_subscriptions.findFirst({ + const subRow = await db._query.kilo_pass_subscriptions.findFirst({ where: eq(kilo_pass_subscriptions.stripe_subscription_id, 'sub_happy_path'), }); expect(subRow?.status).toBe('canceled'); expect(subRow?.current_streak_months).toBe(0); // User blocked - const userRow = await db.query.kilocode_users.findFirst({ + const userRow = await db._query.kilocode_users.findFirst({ where: eq(kilocode_users.id, target.id), }); expect(userRow?.blocked_reason).toBe('fraud-ring'); @@ -296,7 +296,7 @@ describe('admin.kiloPass.cancelAndRefundKiloPassBulk', () => { expect(userRow?.total_microdollars_acquired).toBe(1_000_000); // Balance-zero credit transaction inserted - const txnRows = await db.query.credit_transactions.findMany({ + const txnRows = await db._query.credit_transactions.findMany({ where: eq(credit_transactions.kilo_user_id, target.id), }); expect(txnRows).toHaveLength(1); @@ -304,7 +304,7 @@ describe('admin.kiloPass.cancelAndRefundKiloPassBulk', () => { expect(txnRows[0].credit_category).toBe('admin-cancel-refund-kilo-pass'); // Admin note inserted with [bulk] suffix - const noteRows = await db.query.user_admin_notes.findMany({ + const noteRows = await db._query.user_admin_notes.findMany({ where: eq(user_admin_notes.kilo_user_id, target.id), }); expect(noteRows).toHaveLength(1); @@ -375,13 +375,13 @@ describe('admin.kiloPass.cancelAndRefundKiloPassBulk', () => { expect(byEmail.get('bulk-seq-3@example.com')?.status).toBe('cancelled_and_refunded'); // u1 and u3 are committed (blocked); u2 is NOT blocked (rolled back before tx) - const u1Row = await db.query.kilocode_users.findFirst({ + const u1Row = await db._query.kilocode_users.findFirst({ where: eq(kilocode_users.id, u1.id), }); - const u2Row = await db.query.kilocode_users.findFirst({ + const u2Row = await db._query.kilocode_users.findFirst({ where: eq(kilocode_users.id, u2.id), }); - const u3Row = await db.query.kilocode_users.findFirst({ + const u3Row = await db._query.kilocode_users.findFirst({ where: eq(kilocode_users.id, u3.id), }); expect(u1Row?.blocked_reason).toBe('mixed-batch'); @@ -389,13 +389,13 @@ describe('admin.kiloPass.cancelAndRefundKiloPassBulk', () => { expect(u3Row?.blocked_reason).toBe('mixed-batch'); // Subscriptions for successful users are canceled; the failed user's sub is unchanged - const sub1 = await db.query.kilo_pass_subscriptions.findFirst({ + const sub1 = await db._query.kilo_pass_subscriptions.findFirst({ where: eq(kilo_pass_subscriptions.stripe_subscription_id, 'sub_seq_1'), }); - const sub2 = await db.query.kilo_pass_subscriptions.findFirst({ + const sub2 = await db._query.kilo_pass_subscriptions.findFirst({ where: eq(kilo_pass_subscriptions.stripe_subscription_id, 'sub_seq_2'), }); - const sub3 = await db.query.kilo_pass_subscriptions.findFirst({ + const sub3 = await db._query.kilo_pass_subscriptions.findFirst({ where: eq(kilo_pass_subscriptions.stripe_subscription_id, 'sub_seq_3'), }); expect(sub1?.status).toBe('canceled'); @@ -441,7 +441,7 @@ describe('admin.kiloPass.cancelAndRefundKiloPassBulk', () => { expect(result.results[0].status).toBe('cancelled_and_refunded'); expect(result.results[0].alreadyBlocked).toBe(true); - const userRow = await db.query.kilocode_users.findFirst({ + const userRow = await db._query.kilocode_users.findFirst({ where: eq(kilocode_users.id, target.id), }); expect(userRow?.blocked_reason).toBe('previous-block'); @@ -493,10 +493,10 @@ describe('admin.kiloPass.cancelAndRefundKiloPassBulk', () => { expect(result.results[0].error).toContain('Multiple accounts match'); // Neither subscription was canceled - const sub1 = await db.query.kilo_pass_subscriptions.findFirst({ + const sub1 = await db._query.kilo_pass_subscriptions.findFirst({ where: eq(kilo_pass_subscriptions.stripe_subscription_id, 'sub_ambig_1'), }); - const sub2 = await db.query.kilo_pass_subscriptions.findFirst({ + const sub2 = await db._query.kilo_pass_subscriptions.findFirst({ where: eq(kilo_pass_subscriptions.stripe_subscription_id, 'sub_ambig_2'), }); expect(sub1?.status).toBe('active'); diff --git a/apps/web/src/routers/code-reviews-router.test.ts b/apps/web/src/routers/code-reviews-router.test.ts index 31fcf05b41..27faeef2f5 100644 --- a/apps/web/src/routers/code-reviews-router.test.ts +++ b/apps/web/src/routers/code-reviews-router.test.ts @@ -82,7 +82,7 @@ describe('codeReviewRouter.cancel', () => { const caller = await createCallerForUser(testUser.id); const result = await caller.codeReviews.cancel({ reviewId: review.id }); - const storedReview = await db.query.cloud_agent_code_reviews.findFirst({ + const storedReview = await db._query.cloud_agent_code_reviews.findFirst({ where: eq(cloud_agent_code_reviews.id, review.id), }); @@ -101,7 +101,7 @@ describe('codeReviewRouter.cancel', () => { const caller = await createCallerForUser(testUser.id); const result = await caller.codeReviews.cancel({ reviewId: review.id }); - const storedReview = await db.query.cloud_agent_code_reviews.findFirst({ + const storedReview = await db._query.cloud_agent_code_reviews.findFirst({ where: eq(cloud_agent_code_reviews.id, review.id), }); @@ -121,7 +121,7 @@ describe('codeReviewRouter.cancel', () => { const caller = await createCallerForUser(testUser.id); const result = await caller.codeReviews.cancel({ reviewId: review.id }); - const storedReview = await db.query.cloud_agent_code_reviews.findFirst({ + const storedReview = await db._query.cloud_agent_code_reviews.findFirst({ where: eq(cloud_agent_code_reviews.id, review.id), }); @@ -141,7 +141,7 @@ describe('codeReviewRouter.cancel', () => { const caller = await createCallerForUser(testUser.id); const result = await caller.codeReviews.cancel({ reviewId: review.id }); - const storedReview = await db.query.cloud_agent_code_reviews.findFirst({ + const storedReview = await db._query.cloud_agent_code_reviews.findFirst({ where: eq(cloud_agent_code_reviews.id, review.id), }); @@ -160,7 +160,7 @@ describe('codeReviewRouter.cancel', () => { const caller = await createCallerForUser(testUser.id); const result = await caller.codeReviews.cancel({ reviewId: review.id }); - const storedReview = await db.query.cloud_agent_code_reviews.findFirst({ + const storedReview = await db._query.cloud_agent_code_reviews.findFirst({ where: eq(cloud_agent_code_reviews.id, review.id), }); @@ -179,7 +179,7 @@ describe('codeReviewRouter.cancel', () => { const caller = await createCallerForUser(testUser.id); const result = await caller.codeReviews.cancel({ reviewId: review.id }); - const storedReview = await db.query.cloud_agent_code_reviews.findFirst({ + const storedReview = await db._query.cloud_agent_code_reviews.findFirst({ where: eq(cloud_agent_code_reviews.id, review.id), }); diff --git a/apps/web/src/routers/kilo-pass-router.test.ts b/apps/web/src/routers/kilo-pass-router.test.ts index bfe4bcea64..7ec3a9e268 100644 --- a/apps/web/src/routers/kilo-pass-router.test.ts +++ b/apps/web/src/routers/kilo-pass-router.test.ts @@ -1078,7 +1078,7 @@ describe('kiloPassRouter', () => { cancel_at_period_end: true, }); - const updated = await db.query.kilo_pass_subscriptions.findFirst({ + const updated = await db._query.kilo_pass_subscriptions.findFirst({ columns: { status: true, cancel_at_period_end: true }, where: eq(kilo_pass_subscriptions.stripe_subscription_id, 'sub_test_cancel_me'), }); @@ -1137,7 +1137,7 @@ describe('kiloPassRouter', () => { cancel_at_period_end: false, }); - const updated = await db.query.kilo_pass_subscriptions.findFirst({ + const updated = await db._query.kilo_pass_subscriptions.findFirst({ columns: { status: true, cancel_at_period_end: true, ended_at: true }, where: eq(kilo_pass_subscriptions.stripe_subscription_id, 'sub_test_resume_me'), }); @@ -1290,7 +1290,7 @@ describe('kiloPassRouter', () => { }) ); - const rows = await db.query.kilo_pass_scheduled_changes.findMany({ + const rows = await db._query.kilo_pass_scheduled_changes.findMany({ where: eq( kilo_pass_scheduled_changes.stripe_subscription_id, 'sub_test_schedule_change_monthly' @@ -1477,14 +1477,14 @@ describe('kiloPassRouter', () => { expect(stripeMock.subscriptionSchedules.release).toHaveBeenCalledWith(oldScheduleId); - const oldRow = await db.query.kilo_pass_scheduled_changes.findFirst({ + const oldRow = await db._query.kilo_pass_scheduled_changes.findFirst({ where: eq(kilo_pass_scheduled_changes.id, existing.id), }); expect(oldRow).toBeTruthy(); expect(oldRow?.deleted_at).not.toBeNull(); expect(oldRow?.status).toBe(KiloPassScheduledChangeStatus.Released); - const rows = await db.query.kilo_pass_scheduled_changes.findMany({ + const rows = await db._query.kilo_pass_scheduled_changes.findMany({ where: eq( kilo_pass_scheduled_changes.stripe_subscription_id, 'sub_test_schedule_change_replace' @@ -1663,7 +1663,7 @@ describe('kiloPassRouter', () => { expect(stripeMock.subscriptionSchedules.release).toHaveBeenCalledWith(scheduleId); - const updated = await db.query.kilo_pass_scheduled_changes.findFirst({ + const updated = await db._query.kilo_pass_scheduled_changes.findFirst({ where: eq(kilo_pass_scheduled_changes.id, pending.id), }); diff --git a/apps/web/src/routers/kilo-pass-router.ts b/apps/web/src/routers/kilo-pass-router.ts index 27e33d580d..c83ef56f4c 100644 --- a/apps/web/src/routers/kilo-pass-router.ts +++ b/apps/web/src/routers/kilo-pass-router.ts @@ -180,7 +180,7 @@ async function getIsBonusUnlockedForSubscriptionId(subscriptionId: string): Prom const issuanceId = lastIssuance[0]?.id; if (!issuanceId) return false; - const unlockedItem = await db.query.kilo_pass_issuance_items.findFirst({ + const unlockedItem = await db._query.kilo_pass_issuance_items.findFirst({ columns: { id: true }, where: and( eq(kilo_pass_issuance_items.kilo_pass_issuance_id, issuanceId), @@ -640,7 +640,7 @@ export const kiloPassRouter = createTRPCRouter({ }); } - const scheduledChange = await db.query.kilo_pass_scheduled_changes.findFirst({ + const scheduledChange = await db._query.kilo_pass_scheduled_changes.findFirst({ columns: { stripe_schedule_id: true, }, @@ -776,7 +776,7 @@ export const kiloPassRouter = createTRPCRouter({ return { scheduledChange: null }; } - const scheduledChange = await db.query.kilo_pass_scheduled_changes.findFirst({ + const scheduledChange = await db._query.kilo_pass_scheduled_changes.findFirst({ columns: { id: true, from_tier: true, @@ -1018,7 +1018,7 @@ export const kiloPassRouter = createTRPCRouter({ throw new TRPCError({ code: 'BAD_REQUEST', message: 'No Kilo Pass subscription found.' }); } - const scheduledChange = await db.query.kilo_pass_scheduled_changes.findFirst({ + const scheduledChange = await db._query.kilo_pass_scheduled_changes.findFirst({ columns: { id: true, stripe_schedule_id: true }, where: and( eq(kilo_pass_scheduled_changes.stripe_subscription_id, subscription.stripeSubscriptionId), diff --git a/apps/web/src/routers/organizations/organization-admin-router.ts b/apps/web/src/routers/organizations/organization-admin-router.ts index 0adc4ca951..ac8f9a11d1 100644 --- a/apps/web/src/routers/organizations/organization-admin-router.ts +++ b/apps/web/src/routers/organizations/organization-admin-router.ts @@ -145,7 +145,7 @@ export const organizationAdminRouter = createTRPCRouter({ const { organizationId, userId } = input; // Validate that the organization exists - const organization = await db.query.organizations.findFirst({ + const organization = await db._query.organizations.findFirst({ where: eq(organizations.id, organizationId), }); @@ -158,7 +158,7 @@ export const organizationAdminRouter = createTRPCRouter({ // If userId is provided, validate that the user exists if (userId !== null) { - const user = await db.query.kilocode_users.findFirst({ + const user = await db._query.kilocode_users.findFirst({ where: eq(kilocode_users.id, userId), }); @@ -184,7 +184,7 @@ export const organizationAdminRouter = createTRPCRouter({ const { organizationId, free_trial_end_at } = input; // Validate that the organization exists - const organization = await db.query.organizations.findFirst({ + const organization = await db._query.organizations.findFirst({ where: eq(organizations.id, organizationId), }); if (!organization) { @@ -205,7 +205,7 @@ export const organizationAdminRouter = createTRPCRouter({ const { organizationId, suppress_trial_messaging } = input; // Validate that the organization exists - const organization = await db.query.organizations.findFirst({ + const organization = await db._query.organizations.findFirst({ where: eq(organizations.id, organizationId), }); if (!organization) { diff --git a/apps/web/src/routers/organizations/organization-auto-top-up-router.test.ts b/apps/web/src/routers/organizations/organization-auto-top-up-router.test.ts index c089716b34..1c2673d504 100644 --- a/apps/web/src/routers/organizations/organization-auto-top-up-router.test.ts +++ b/apps/web/src/routers/organizations/organization-auto-top-up-router.test.ts @@ -142,7 +142,7 @@ describe('organization auto-top-up router', () => { expect(result).toEqual({ enabled: false }); // Verify DB was updated - const org = await db.query.organizations.findFirst({ + const org = await db._query.organizations.findFirst({ where: eq(organizations.id, testOrg.id), }); expect(org?.auto_top_up_enabled).toBe(false); @@ -167,13 +167,13 @@ describe('organization auto-top-up router', () => { expect(result).toEqual({ enabled: true }); // Verify DB was updated - const org = await db.query.organizations.findFirst({ + const org = await db._query.organizations.findFirst({ where: eq(organizations.id, testOrg.id), }); expect(org?.auto_top_up_enabled).toBe(true); // Verify disabled_reason was cleared - const config = await db.query.auto_top_up_configs.findFirst({ + const config = await db._query.auto_top_up_configs.findFirst({ where: eq(auto_top_up_configs.owned_by_organization_id, testOrg.id), }); expect(config?.disabled_reason).toBeNull(); @@ -222,7 +222,7 @@ describe('organization auto-top-up router', () => { expect(result.success).toBe(true); // Verify DB was updated - const config = await db.query.auto_top_up_configs.findFirst({ + const config = await db._query.auto_top_up_configs.findFirst({ where: eq(auto_top_up_configs.owned_by_organization_id, testOrg.id), }); expect(config?.amount_cents).toBe(10000); @@ -251,13 +251,13 @@ describe('organization auto-top-up router', () => { expect(result.success).toBe(true); // Verify config was deleted - const config = await db.query.auto_top_up_configs.findFirst({ + const config = await db._query.auto_top_up_configs.findFirst({ where: eq(auto_top_up_configs.owned_by_organization_id, testOrg.id), }); expect(config).toBeUndefined(); // Verify auto_top_up_enabled was set to false - const org = await db.query.organizations.findFirst({ + const org = await db._query.organizations.findFirst({ where: eq(organizations.id, testOrg.id), }); expect(org?.auto_top_up_enabled).toBe(false); diff --git a/apps/web/src/routers/organizations/organization-auto-top-up-router.ts b/apps/web/src/routers/organizations/organization-auto-top-up-router.ts index 7d641dc385..700b41df60 100644 --- a/apps/web/src/routers/organizations/organization-auto-top-up-router.ts +++ b/apps/web/src/routers/organizations/organization-auto-top-up-router.ts @@ -24,7 +24,7 @@ export const organizationAutoTopUpRouter = createTRPCRouter({ getConfig: organizationBillingProcedure.query(async ({ input }) => { const { organizationId } = input; - const config = await db.query.auto_top_up_configs.findFirst({ + const config = await db._query.auto_top_up_configs.findFirst({ where: eq(auto_top_up_configs.owned_by_organization_id, organizationId), }); @@ -58,7 +58,7 @@ export const organizationAutoTopUpRouter = createTRPCRouter({ return { enabled: false } as const; } else { // Enabling auto-top-up - const config = await db.query.auto_top_up_configs.findFirst({ + const config = await db._query.auto_top_up_configs.findFirst({ where: eq(auto_top_up_configs.owned_by_organization_id, organizationId), }); diff --git a/apps/web/src/routers/organizations/organization-router.ts b/apps/web/src/routers/organizations/organization-router.ts index 77ee69d562..f060bdc8ff 100644 --- a/apps/web/src/routers/organizations/organization-router.ts +++ b/apps/web/src/routers/organizations/organization-router.ts @@ -318,7 +318,7 @@ export const organizationsRouter = createTRPCRouter({ const org = await getOrganizationById(organizationId); if (!org) throw new TRPCError({ code: 'NOT_FOUND', message: 'Organization not found' }); - const transactions = await db.query.credit_transactions.findMany({ + const transactions = await db._query.credit_transactions.findMany({ where: eq(credit_transactions.organization_id, organizationId), }); diff --git a/apps/web/src/routers/user-router.test.ts b/apps/web/src/routers/user-router.test.ts index 5585567d49..2607406176 100644 --- a/apps/web/src/routers/user-router.test.ts +++ b/apps/web/src/routers/user-router.test.ts @@ -33,7 +33,7 @@ describe('user router - updateProfile', () => { expect(result).toEqual({ success: true }); - const updated = await db.query.kilocode_users.findFirst({ + const updated = await db._query.kilocode_users.findFirst({ where: eq(kilocode_users.id, testUser.id), }); expect(updated?.linkedin_url).toBe('https://linkedin.com/in/testuser'); @@ -48,7 +48,7 @@ describe('user router - updateProfile', () => { expect(result).toEqual({ success: true }); - const updated = await db.query.kilocode_users.findFirst({ + const updated = await db._query.kilocode_users.findFirst({ where: eq(kilocode_users.id, testUser.id), }); expect(updated?.github_url).toBe('https://github.com/testuser'); @@ -64,7 +64,7 @@ describe('user router - updateProfile', () => { expect(result).toEqual({ success: true }); - const updated = await db.query.kilocode_users.findFirst({ + const updated = await db._query.kilocode_users.findFirst({ where: eq(kilocode_users.id, testUser.id), }); expect(updated?.linkedin_url).toBe('https://linkedin.com/in/testuser'); @@ -85,7 +85,7 @@ describe('user router - updateProfile', () => { expect(result).toEqual({ success: true }); - const updated = await db.query.kilocode_users.findFirst({ + const updated = await db._query.kilocode_users.findFirst({ where: eq(kilocode_users.id, testUser.id), }); expect(updated?.linkedin_url).toBeNull(); @@ -152,7 +152,7 @@ describe('user router - submitCustomerSource', () => { expect(result).toEqual({ success: true }); - const updated = await db.query.kilocode_users.findFirst({ + const updated = await db._query.kilocode_users.findFirst({ where: eq(kilocode_users.id, surveyTestUser.id), }); expect(updated?.customer_source).toBe('A YouTube video'); @@ -164,7 +164,7 @@ describe('user router - submitCustomerSource', () => { await caller.user.submitCustomerSource({ source: 'First answer' }); await caller.user.submitCustomerSource({ source: 'Updated answer' }); - const updated = await db.query.kilocode_users.findFirst({ + const updated = await db._query.kilocode_users.findFirst({ where: eq(kilocode_users.id, surveyTestUser.id), }); expect(updated?.customer_source).toBe('Updated answer'); @@ -190,7 +190,7 @@ describe('user router - submitCustomerSource', () => { const result = await caller.user.submitCustomerSource({ source: maxString }); expect(result).toEqual({ success: true }); - const updated = await db.query.kilocode_users.findFirst({ + const updated = await db._query.kilocode_users.findFirst({ where: eq(kilocode_users.id, surveyTestUser.id), }); expect(updated?.customer_source).toBe(maxString); @@ -202,7 +202,7 @@ describe('user router - submitCustomerSource', () => { expect(result).toEqual({ success: true }); - const updated = await db.query.kilocode_users.findFirst({ + const updated = await db._query.kilocode_users.findFirst({ where: eq(kilocode_users.id, surveyTestUser.id), }); expect(updated?.customer_source).toBe('X'); @@ -215,7 +215,7 @@ describe('user router - submitCustomerSource', () => { expect(result).toEqual({ success: true }); - const updated = await db.query.kilocode_users.findFirst({ + const updated = await db._query.kilocode_users.findFirst({ where: eq(kilocode_users.id, surveyTestUser.id), }); expect(updated?.customer_source).toBe(content); @@ -254,7 +254,7 @@ describe('user router - submitCustomerSource', () => { expect(result).toEqual({ success: true }); - const updated = await db.query.kilocode_users.findFirst({ + const updated = await db._query.kilocode_users.findFirst({ where: eq(kilocode_users.id, surveyTestUser.id), }); expect(updated?.customer_source).toBe('hello'); @@ -266,7 +266,7 @@ describe('user router - submitCustomerSource', () => { expect(result).toEqual({ success: true }); - const updated = await db.query.kilocode_users.findFirst({ + const updated = await db._query.kilocode_users.findFirst({ where: eq(kilocode_users.id, surveyTestUser.id), }); expect(updated?.customer_source).toBe('a YouTube video'); @@ -300,7 +300,7 @@ describe('user router - skipCustomerSource', () => { const caller = await createCallerForUser(skipTestUser.id); await caller.user.skipCustomerSource(); - const updated = await db.query.kilocode_users.findFirst({ + const updated = await db._query.kilocode_users.findFirst({ where: eq(kilocode_users.id, skipTestUser.id), }); expect(updated?.customer_source).toBe(''); @@ -315,7 +315,7 @@ describe('user router - skipCustomerSource', () => { const result2 = await caller.user.skipCustomerSource(); expect(result2).toEqual({ success: true }); - const updated = await db.query.kilocode_users.findFirst({ + const updated = await db._query.kilocode_users.findFirst({ where: eq(kilocode_users.id, skipTestUser.id), }); expect(updated?.customer_source).toBe(''); @@ -327,7 +327,7 @@ describe('user router - skipCustomerSource', () => { await caller.user.submitCustomerSource({ source: 'Found it on Hacker News' }); await caller.user.skipCustomerSource(); - const updated = await db.query.kilocode_users.findFirst({ + const updated = await db._query.kilocode_users.findFirst({ where: eq(kilocode_users.id, skipTestUser.id), }); expect(updated?.customer_source).toBe('Found it on Hacker News'); @@ -338,7 +338,7 @@ describe('user router - skipCustomerSource', () => { await caller.user.skipCustomerSource(); await caller.user.submitCustomerSource({ source: 'Changed my mind — Reddit' }); - const updated = await db.query.kilocode_users.findFirst({ + const updated = await db._query.kilocode_users.findFirst({ where: eq(kilocode_users.id, skipTestUser.id), }); expect(updated?.customer_source).toBe('Changed my mind — Reddit'); @@ -347,7 +347,7 @@ describe('user router - skipCustomerSource', () => { describe('session and API token reset mutations', () => { async function findRequiredUser(userId: string): Promise { - const user = await db.query.kilocode_users.findFirst({ + const user = await db._query.kilocode_users.findFirst({ where: eq(kilocode_users.id, userId), }); if (!user) throw new Error(`Expected test user to exist: ${userId}`); diff --git a/apps/web/src/routers/user-router.ts b/apps/web/src/routers/user-router.ts index f6eb3ba0d6..a139dbe21b 100644 --- a/apps/web/src/routers/user-router.ts +++ b/apps/web/src/routers/user-router.ts @@ -314,7 +314,7 @@ export const userRouter = createTRPCRouter({ .query(async ({ ctx }) => { const now = new Date(); - const transactions = await db.query.credit_transactions.findMany({ + const transactions = await db._query.credit_transactions.findMany({ where: and( eq(credit_transactions.kilo_user_id, ctx.user.id), isNull(credit_transactions.organization_id) @@ -432,7 +432,7 @@ export const userRouter = createTRPCRouter({ return { enabled: false } as const; } else { // Enabling auto-top-up - const config = await db.query.auto_top_up_configs.findFirst({ + const config = await db._query.auto_top_up_configs.findFirst({ where: eq(auto_top_up_configs.owned_by_user_id, ctx.user.id), }); @@ -491,7 +491,7 @@ export const userRouter = createTRPCRouter({ }), getAutoTopUpPaymentMethod: baseProcedure.query(async ({ ctx }) => { - const config = await db.query.auto_top_up_configs.findFirst({ + const config = await db._query.auto_top_up_configs.findFirst({ where: eq(auto_top_up_configs.owned_by_user_id, ctx.user.id), }); const paymentMethod = await retrievePaymentMethodInfo(config?.stripe_payment_method_id); @@ -587,14 +587,14 @@ export const userRouter = createTRPCRouter({ }), getDiscordGuildStatus: baseProcedure.query(async ({ ctx }) => { - const discordProvider = await db.query.user_auth_provider.findFirst({ + const discordProvider = await db._query.user_auth_provider.findFirst({ where: and( eq(user_auth_provider.kilo_user_id, ctx.user.id), eq(user_auth_provider.provider, 'discord') ), }); - const user = await db.query.kilocode_users.findFirst({ + const user = await db._query.kilocode_users.findFirst({ where: eq(kilocode_users.id, ctx.user.id), columns: { discord_server_membership_verified_at: true, @@ -610,7 +610,7 @@ export const userRouter = createTRPCRouter({ }), verifyDiscordGuildMembership: baseProcedure.mutation(async ({ ctx }) => { - const discordProvider = await db.query.user_auth_provider.findFirst({ + const discordProvider = await db._query.user_auth_provider.findFirst({ where: and( eq(user_auth_provider.kilo_user_id, ctx.user.id), eq(user_auth_provider.provider, 'discord') diff --git a/apps/web/src/scripts/d2025-07-15_fix-failed-top-ups.ts b/apps/web/src/scripts/d2025-07-15_fix-failed-top-ups.ts index b8cfcb8adb..b07543c2fb 100644 --- a/apps/web/src/scripts/d2025-07-15_fix-failed-top-ups.ts +++ b/apps/web/src/scripts/d2025-07-15_fix-failed-top-ups.ts @@ -60,7 +60,7 @@ const eventIDs = [ export async function fixFailedTopUps() { const uniqueCustomerIDs = new Set(); - const adminUser = await db.query.kilocode_users.findFirst({ + const adminUser = await db._query.kilocode_users.findFirst({ where: eq(kilocode_users.google_user_email, 'remon@kilocode.ai'), }); diff --git a/apps/web/src/scripts/d2025-07-26_replace-stripe-account-for-kilouser.ts b/apps/web/src/scripts/d2025-07-26_replace-stripe-account-for-kilouser.ts index d277a0fd13..5988356443 100644 --- a/apps/web/src/scripts/d2025-07-26_replace-stripe-account-for-kilouser.ts +++ b/apps/web/src/scripts/d2025-07-26_replace-stripe-account-for-kilouser.ts @@ -6,7 +6,7 @@ import { eq } from 'drizzle-orm'; async function createStripeCustomerForUser(kiloUserId: string) { console.log(`Looking up user with ID: ${kiloUserId}`); - const user = await db.query.kilocode_users.findFirst({ + const user = await db._query.kilocode_users.findFirst({ where: eq(kilocode_users.id, kiloUserId), }); diff --git a/apps/web/src/scripts/d2025-08-22_grant-sonic-usage-compensation.ts b/apps/web/src/scripts/d2025-08-22_grant-sonic-usage-compensation.ts index 0fd4849e4b..403374474b 100644 --- a/apps/web/src/scripts/d2025-08-22_grant-sonic-usage-compensation.ts +++ b/apps/web/src/scripts/d2025-08-22_grant-sonic-usage-compensation.ts @@ -50,7 +50,7 @@ async function run() { try { // Fetch the full user object - const user = await db.query.kilocode_users.findFirst({ + const user = await db._query.kilocode_users.findFirst({ where: eq(kilocode_users.id, userData.id), }); diff --git a/apps/web/src/scripts/d2025-09-01_backfill-referral-code-usages.ts b/apps/web/src/scripts/d2025-09-01_backfill-referral-code-usages.ts index 31225e27d9..82e507237a 100644 --- a/apps/web/src/scripts/d2025-09-01_backfill-referral-code-usages.ts +++ b/apps/web/src/scripts/d2025-09-01_backfill-referral-code-usages.ts @@ -170,7 +170,7 @@ async function parseReferredUserNotLoggedEvents(): Promise { await processStripePaymentEventHook(event); - const storedPaymentMethod = await db.query.payment_methods.findFirst({ + const storedPaymentMethod = await db._query.payment_methods.findFirst({ where: and( eq(payment_methods.stripe_id, mockStripePaymentMethod.id), eq(payment_methods.user_id, testUser.id) @@ -566,7 +566,7 @@ describe('processStripePaymentEventHook', () => { await processStripePaymentEventHook(event); - const storedPaymentMethod = await db.query.payment_methods.findFirst({ + const storedPaymentMethod = await db._query.payment_methods.findFirst({ where: and( eq(payment_methods.stripe_id, mockStripePaymentMethod.id), eq(payment_methods.user_id, testUser.id) @@ -597,7 +597,7 @@ describe('processStripePaymentEventHook', () => { await processStripePaymentEventHook(event); - const storedPaymentMethod = await db.query.payment_methods.findMany({ + const storedPaymentMethod = await db._query.payment_methods.findMany({ where: and(eq(payment_methods.user_id, testUser.id)), }); @@ -617,7 +617,7 @@ describe('processStripePaymentEventHook', () => { await processStripePaymentEventHook(event); - const paymentMethodExists = await db.query.payment_methods.findFirst({ + const paymentMethodExists = await db._query.payment_methods.findFirst({ where: eq(payment_methods.user_id, testUser.id), }); @@ -638,7 +638,7 @@ describe('processStripePaymentEventHook', () => { await processStripePaymentEventHook(event); - const paymentMethodExists = await db.query.payment_methods.findFirst({ + const paymentMethodExists = await db._query.payment_methods.findFirst({ where: eq(payment_methods.stripe_id, mockStripePaymentMethod.id), }); @@ -659,7 +659,7 @@ describe('processStripePaymentEventHook', () => { await processStripePaymentEventHook(event); - const paymentMethodExists = await db.query.payment_methods.findFirst({ + const paymentMethodExists = await db._query.payment_methods.findFirst({ where: eq(payment_methods.stripe_id, mockStripePaymentMethod.id), }); @@ -972,13 +972,13 @@ describe('processStripePaymentEventHook', () => { await processStripePaymentEventHook(event); - const updatedRow = await db.query.kilo_pass_scheduled_changes.findFirst({ + const updatedRow = await db._query.kilo_pass_scheduled_changes.findFirst({ where: eq(kilo_pass_scheduled_changes.id, scheduledChangeId), }); expect(updatedRow?.status).toBe(KiloPassScheduledChangeStatus.NotStarted); const syntheticInvoiceId = `kilo-pass-yearly-remaining:${scheduledChangeId}`; - const creditTx = await db.query.credit_transactions.findFirst({ + const creditTx = await db._query.credit_transactions.findFirst({ where: eq(credit_transactions.stripe_payment_id, syntheticInvoiceId), }); @@ -1033,7 +1033,7 @@ describe('processStripePaymentEventHook', () => { await processStripePaymentEventHook(event); - const updatedRow = await db.query.kilo_pass_scheduled_changes.findFirst({ + const updatedRow = await db._query.kilo_pass_scheduled_changes.findFirst({ where: eq(kilo_pass_scheduled_changes.id, scheduledChangeId), }); expect(updatedRow).toBeTruthy(); @@ -1087,7 +1087,7 @@ describe('processStripePaymentEventHook', () => { await processStripePaymentEventHook(event); - const updatedRow = await db.query.kilo_pass_scheduled_changes.findFirst({ + const updatedRow = await db._query.kilo_pass_scheduled_changes.findFirst({ where: eq(kilo_pass_scheduled_changes.id, scheduledChangeId), }); expect(updatedRow).toBeTruthy(); @@ -1141,7 +1141,7 @@ describe('processStripePaymentEventHook', () => { await processStripePaymentEventHook(releasedEvent); - const afterReleased = await db.query.kilo_pass_scheduled_changes.findFirst({ + const afterReleased = await db._query.kilo_pass_scheduled_changes.findFirst({ where: eq(kilo_pass_scheduled_changes.id, scheduledChangeId), }); expect(afterReleased).toBeTruthy(); @@ -1164,7 +1164,7 @@ describe('processStripePaymentEventHook', () => { await processStripePaymentEventHook(notStartedEvent); - const afterOutOfOrder = await db.query.kilo_pass_scheduled_changes.findFirst({ + const afterOutOfOrder = await db._query.kilo_pass_scheduled_changes.findFirst({ where: eq(kilo_pass_scheduled_changes.id, scheduledChangeId), }); @@ -1230,7 +1230,7 @@ describe('releaseScheduledChangeForSubscription', () => { }) ).rejects.toThrow('stripe release failed'); - const row = await db.query.kilo_pass_scheduled_changes.findFirst({ + const row = await db._query.kilo_pass_scheduled_changes.findFirst({ where: eq(kilo_pass_scheduled_changes.id, scheduledChangeId), }); expect(row).toBeTruthy(); @@ -1295,14 +1295,14 @@ describe('releaseScheduledChangeForSubscription', () => { expect(release).toHaveBeenCalledWith(orphanScheduleId); expect(release).not.toHaveBeenCalledWith(activeScheduleId); - const row = await db.query.kilo_pass_scheduled_changes.findFirst({ + const row = await db._query.kilo_pass_scheduled_changes.findFirst({ where: eq(kilo_pass_scheduled_changes.id, scheduledChangeId), }); expect(row).toBeTruthy(); expect(row?.deleted_at).toBeNull(); expect(row?.status).toBe(KiloPassScheduledChangeStatus.NotStarted); - const auditLog = await db.query.kilo_pass_audit_log.findFirst({ + const auditLog = await db._query.kilo_pass_audit_log.findFirst({ where: eq(kilo_pass_audit_log.stripe_event_id, 'evt_release_helper_mismatch'), }); expect(auditLog?.payload_json).toEqual( @@ -1427,7 +1427,7 @@ describe('handleSuccessfulChargeWithPayment (org/user routing & side-effects)', await handleSuccessfulChargeWithPayment(charge, paymentIntent); - const updatedOrg = await db.query.organizations.findFirst({ + const updatedOrg = await db._query.organizations.findFirst({ where: eq(organizations.id, org.id), }); const expectedIncrease = amountInCents * 10_000; @@ -1436,7 +1436,7 @@ describe('handleSuccessfulChargeWithPayment (org/user routing & side-effects)', (updatedOrg?.total_microdollars_acquired ?? 0) - (updatedOrg?.microdollars_used ?? 0); expect(updatedComputedBalance).toBe(orgComputedBalance + expectedIncrease); - const creditTx = await db.query.credit_transactions.findFirst({ + const creditTx = await db._query.credit_transactions.findFirst({ where: eq(credit_transactions.stripe_payment_id, piId), }); @@ -1506,7 +1506,7 @@ describe('handleSuccessfulChargeWithPayment (org/user routing & side-effects)', await handleSuccessfulChargeWithPayment(charge, paymentIntent); // Should NOT create a credit transaction - const creditTx = await db.query.credit_transactions.findFirst({ + const creditTx = await db._query.credit_transactions.findFirst({ where: eq(credit_transactions.stripe_payment_id, chId), }); @@ -1534,7 +1534,7 @@ describe('handleSuccessfulChargeWithPayment (org/user routing & side-effects)', await handleSuccessfulChargeWithPayment(charge, paymentIntent); // For user top-ups, handleSuccessfulChargeWithPayment passes config.stripe_payment_id = charge.id - const creditTx = await db.query.credit_transactions.findFirst({ + const creditTx = await db._query.credit_transactions.findFirst({ where: eq(credit_transactions.stripe_payment_id, chargeId), }); @@ -1547,7 +1547,7 @@ describe('handleSuccessfulChargeWithPayment (org/user routing & side-effects)', expect(creditTx?.description).toBe('Top-up via stripe'); // Verify user aggregate balance fields updated - const updatedUser = await db.query.kilocode_users.findFirst({ + const updatedUser = await db._query.kilocode_users.findFirst({ where: eq(kilocode_users.id, user.id), }); expect(updatedUser?.total_microdollars_acquired).toBe(amountInCents * 10_000); @@ -1567,10 +1567,10 @@ describe('handleSuccessfulChargeWithPayment (org/user routing & side-effects)', await handleSuccessfulChargeWithPayment(charge, paymentIntent); - const txByPi = await db.query.credit_transactions.findFirst({ + const txByPi = await db._query.credit_transactions.findFirst({ where: eq(credit_transactions.stripe_payment_id, piId), }); - const txByCh = await db.query.credit_transactions.findFirst({ + const txByCh = await db._query.credit_transactions.findFirst({ where: eq(credit_transactions.stripe_payment_id, chId), }); @@ -1603,7 +1603,7 @@ describe('handleSuccessfulChargeWithPayment (org/user routing & side-effects)', await handleSuccessfulChargeWithPayment(charge, firstPaymentIntent); - const configAfterFirst = await db.query.auto_top_up_configs.findFirst({ + const configAfterFirst = await db._query.auto_top_up_configs.findFirst({ where: eq(auto_top_up_configs.owned_by_user_id, user.id), }); @@ -1613,7 +1613,7 @@ describe('handleSuccessfulChargeWithPayment (org/user routing & side-effects)', expect(configAfterFirst?.amount_cents).toBe(2000); expect(configAfterFirst?.disabled_reason).toBeNull(); - const userAfterFirst = await db.query.kilocode_users.findFirst({ + const userAfterFirst = await db._query.kilocode_users.findFirst({ where: eq(kilocode_users.id, user.id), }); expect(userAfterFirst?.auto_top_up_enabled).toBe(true); @@ -1638,7 +1638,7 @@ describe('handleSuccessfulChargeWithPayment (org/user routing & side-effects)', .where(eq(auto_top_up_configs.owned_by_user_id, user.id)); expect(configsForUser[0]?.count).toBe(1); - const configAfterSecond = await db.query.auto_top_up_configs.findFirst({ + const configAfterSecond = await db._query.auto_top_up_configs.findFirst({ where: eq(auto_top_up_configs.owned_by_user_id, user.id), }); expect(configAfterSecond?.stripe_payment_method_id).toBe(secondPaymentIntent.payment_method); @@ -1692,7 +1692,7 @@ describe('handleSuccessfulChargeWithPayment (org/user routing & side-effects)', try { await handleSuccessfulChargeWithPayment(charge, firstPaymentIntent); - const configAfterFirst = await db.query.auto_top_up_configs.findFirst({ + const configAfterFirst = await db._query.auto_top_up_configs.findFirst({ where: eq(auto_top_up_configs.owned_by_organization_id, org.id), }); @@ -1702,7 +1702,7 @@ describe('handleSuccessfulChargeWithPayment (org/user routing & side-effects)', expect(configAfterFirst?.amount_cents).toBe(2000); expect(configAfterFirst?.disabled_reason).toBeNull(); - const orgAfterFirst = await db.query.organizations.findFirst({ + const orgAfterFirst = await db._query.organizations.findFirst({ where: eq(organizations.id, org.id), }); expect(orgAfterFirst?.auto_top_up_enabled).toBe(true); @@ -1728,7 +1728,7 @@ describe('handleSuccessfulChargeWithPayment (org/user routing & side-effects)', .where(eq(auto_top_up_configs.owned_by_organization_id, org.id)); expect(configsForOrg[0]?.count).toBe(1); - const configAfterSecond = await db.query.auto_top_up_configs.findFirst({ + const configAfterSecond = await db._query.auto_top_up_configs.findFirst({ where: eq(auto_top_up_configs.owned_by_organization_id, org.id), }); expect(configAfterSecond?.stripe_payment_method_id).toBe(secondPaymentIntent.payment_method); @@ -1783,7 +1783,7 @@ describe('handleSuccessfulChargeWithPayment (org/user routing & side-effects)', try { await handleSuccessfulChargeWithPayment(charge, paymentIntent); - const config = await db.query.auto_top_up_configs.findFirst({ + const config = await db._query.auto_top_up_configs.findFirst({ where: eq(auto_top_up_configs.owned_by_organization_id, org.id), }); @@ -1830,7 +1830,7 @@ describe('handleSuccessfulChargeWithPayment (org/user routing & side-effects)', 'processTopUp test error' ); - const userConfig = await db.query.auto_top_up_configs.findFirst({ + const userConfig = await db._query.auto_top_up_configs.findFirst({ where: eq(auto_top_up_configs.owned_by_user_id, user.id), }); expect(userConfig?.attempt_started_at).toBeNull(); @@ -1879,7 +1879,7 @@ describe('handleSuccessfulChargeWithPayment (org/user routing & side-effects)', 'processTopupForOrganization test error' ); - const orgConfig = await db.query.auto_top_up_configs.findFirst({ + const orgConfig = await db._query.auto_top_up_configs.findFirst({ where: eq(auto_top_up_configs.owned_by_organization_id, org.id), }); expect(orgConfig?.attempt_started_at).toBeNull(); diff --git a/apps/web/tsconfig.json b/apps/web/tsconfig.json index f58f9267a3..4a58e28c9b 100644 --- a/apps/web/tsconfig.json +++ b/apps/web/tsconfig.json @@ -12,6 +12,7 @@ "@/*": ["./src/*"], "@kilocode/db": ["../../packages/db/src/index.ts"], "@kilocode/db/*": ["../../packages/db/src/*"], + "@kilocode/drizzle-shims/*": ["../../packages/drizzle-shims/src/*"], "@kilocode/cloud-agent-profile": ["../../packages/cloud-agent-profile/src/index.ts"], "@kilocode/encryption": ["../../packages/encryption/src/index.ts"], "@kilocode/worker-utils": ["../../packages/worker-utils/src/index.ts"], diff --git a/dev/seed/kiloclaw-billing/inactive-trials.ts b/dev/seed/kiloclaw-billing/inactive-trials.ts index d9b29120b2..a826ebf017 100644 --- a/dev/seed/kiloclaw-billing/inactive-trials.ts +++ b/dev/seed/kiloclaw-billing/inactive-trials.ts @@ -273,7 +273,7 @@ async function updateEligibleTrialFixture(provisioned: ProvisionResponse): Promi trial_ends_at: isoFromNow(4 * 24 * 60 * 60 * 1000), }); - const currentInstance = await db.query.kiloclaw_instances.findFirst({ + const currentInstance = await db._query.kiloclaw_instances.findFirst({ where: eq(kiloclaw_instances.id, ELIGIBLE_INSTANCE_ID), }); @@ -337,7 +337,7 @@ async function loadEligibleFixtureSummary(): Promise<{ subscriptionId: string; }> { const db = getSeedDb(); - const subscription = await db.query.kiloclaw_subscriptions.findFirst({ + const subscription = await db._query.kiloclaw_subscriptions.findFirst({ where: eq(kiloclaw_subscriptions.id, ELIGIBLE_SUBSCRIPTION_ID), }); @@ -345,7 +345,7 @@ async function loadEligibleFixtureSummary(): Promise<{ throw new Error('Eligible fixture summary could not find the provisioned subscription'); } - const instance = await db.query.kiloclaw_instances.findFirst({ + const instance = await db._query.kiloclaw_instances.findFirst({ where: eq(kiloclaw_instances.id, ELIGIBLE_INSTANCE_ID), }); diff --git a/oxlint-plugin-drizzle.js b/oxlint-plugin-drizzle.js index 0142e3cd27..a1a9524dac 100644 --- a/oxlint-plugin-drizzle.js +++ b/oxlint-plugin-drizzle.js @@ -135,9 +135,63 @@ function createRule(method, messageId) { }; } +// Prefer `db._query` over `db.query` in preparation for the drizzle v1 +// migration where the RQB namespace is being renamed. `_query` is aliased to +// `query` at runtime by `@kilocode/drizzle-shims/query-alias`. +// +// oxlint plugins are AST-only (no type info), so the rule is gated on a +// drizzleObjectName allowlist like the other two rules in this file. Known +// receivers in this repo: `db`, `ctx.db`, `this.db`, and transaction callback +// params (`tx`, `trx`). The type-aware ts-morph verifier in +// `scripts/verify-drizzle-underscore-query.ts` is the authoritative check. +const preferUnderscoreQueryRule = { + meta: { + type: 'problem', + fixable: 'code', + messages: { + preferUnderscoreQuery: + 'Read the drizzle RQB namespace via `_query`, not `query`. Drizzle v1 renames this namespace; the alias lets both work for now.', + }, + schema: [ + { + type: 'object', + properties: { + drizzleObjectName: { type: ['string', 'array'] }, + }, + additionalProperties: false, + }, + ], + }, + create(context) { + const drizzleObjectName = (context.options[0] && context.options[0].drizzleObjectName) || []; + return { + MemberExpression(node) { + if ( + node.property.type !== 'Identifier' || + node.property.name !== 'query' || + node.computed + ) { + return; + } + if (!isDrizzleObj(node, drizzleObjectName)) { + return; + } + context.report({ + node: node.property, + messageId: 'preferUnderscoreQuery', + fix(fixer) { + return fixer.replaceText(node.property, '_query'); + }, + }); + }, + }; + }, +}; + module.exports = { rules: { 'enforce-delete-with-where': createRule('delete', 'enforceDeleteWithWhere'), 'enforce-update-with-where': createRule('update', 'enforceUpdateWithWhere'), + 'prefer-underscore-query': preferUnderscoreQueryRule, }, }; diff --git a/package.json b/package.json index a3b89c9819..2d4f927afc 100644 --- a/package.json +++ b/package.json @@ -15,9 +15,11 @@ "format": "oxfmt .", "format:check": "oxfmt --list-different .", "format:changed": "git diff --name-only $(git merge-base origin/main HEAD) --diff-filter=ACMR -- '**/*.js' '**/*.jsx' '**/*.ts' '**/*.tsx' '**/*.json' '**/*.css' '**/*.md' | xargs -r oxfmt --no-error-on-unmatched-pattern", - "validate": "pnpm run typecheck && pnpm run lint && pnpm run test", + "validate": "pnpm run typecheck && pnpm run lint && pnpm run drizzle:query-check && pnpm run test", "drizzle": "pnpm --filter @kilocode/db exec drizzle-kit", "drizzle:verify-bootstrap": "bash scripts/verify-drizzle-bootstrap.sh", + "drizzle:query-check": "tsx scripts/drizzle-query-rename.ts --check", + "drizzle:query-rename": "tsx scripts/drizzle-query-rename.ts --fix", "test:e2e": "pnpm --filter web run test:e2e", "dependency-cycle-check": "pnpm --filter web run dependency-cycle-check", "worktree:prepare": "bash scripts/worktree-prepare.sh", @@ -42,6 +44,7 @@ "oxlint-plugin-react-native": "^0.2.8", "oxlint-tsgolint": "^0.17.1", "react": "^19.2.4", + "ts-morph": "^28.0.0", "tsx": "^4.21.0", "typescript": "catalog:" }, diff --git a/packages/db/package.json b/packages/db/package.json index 543e942c2d..39084642ae 100644 --- a/packages/db/package.json +++ b/packages/db/package.json @@ -14,6 +14,7 @@ "./client": "./src/client.ts" }, "dependencies": { + "@kilocode/drizzle-shims": "workspace:*", "@kilocode/kiloclaw-instance-tiers": "workspace:*", "drizzle-orm": "catalog:", "pg": "^8.20.0", diff --git a/packages/db/src/client.ts b/packages/db/src/client.ts index 6e97276082..496c4e436a 100644 --- a/packages/db/src/client.ts +++ b/packages/db/src/client.ts @@ -1,3 +1,4 @@ +import '@kilocode/drizzle-shims/query-alias'; import { drizzle } from 'drizzle-orm/node-postgres'; import pg, { types } from 'pg'; import * as schema from './schema'; diff --git a/packages/drizzle-shims/package.json b/packages/drizzle-shims/package.json new file mode 100644 index 0000000000..300a4a80ba --- /dev/null +++ b/packages/drizzle-shims/package.json @@ -0,0 +1,20 @@ +{ + "name": "@kilocode/drizzle-shims", + "version": "0.0.1", + "private": true, + "type": "module", + "exports": { + "./query-alias": "./src/query-alias.ts" + }, + "scripts": { + "typecheck": "tsgo --noEmit", + "lint": "pnpm -w exec oxlint --config .oxlintrc.json packages/drizzle-shims/src" + }, + "dependencies": { + "drizzle-orm": "catalog:" + }, + "devDependencies": { + "@typescript/native-preview": "catalog:", + "typescript": "catalog:" + } +} diff --git a/packages/drizzle-shims/src/query-alias.ts b/packages/drizzle-shims/src/query-alias.ts new file mode 100644 index 0000000000..8317faeb55 --- /dev/null +++ b/packages/drizzle-shims/src/query-alias.ts @@ -0,0 +1,53 @@ +/** + * Aliases `_query` to `query` on every drizzle db (and transaction) instance, + * in preparation for the drizzle v1 migration where the RQB namespace is being + * renamed. + * + * This module has a side effect: importing it patches `PgDatabase.prototype` + * and `BaseSQLiteDatabase.prototype` with a `_query` getter that returns + * `this.query`. Since `PgTransaction` / `SQLiteTransaction` extend the + * database base classes, transactions (`tx._query`) are covered too. + * + * Every entry point that constructs or uses a drizzle db should import this + * module for its side effect. New code should read from `_query` only; the + * `drizzle/prefer-underscore-query` oxlint rule enforces that. Once drizzle + * v1 lands, delete this module and the imports. + */ + +import { PgDatabase } from 'drizzle-orm/pg-core'; +import { BaseSQLiteDatabase } from 'drizzle-orm/sqlite-core'; +import type { PgQueryResultHKT } from 'drizzle-orm/pg-core'; +import type { ExtractTablesWithRelations, TablesRelationalConfig } from 'drizzle-orm'; + +for (const proto of [PgDatabase.prototype, BaseSQLiteDatabase.prototype]) { + if (!Object.prototype.hasOwnProperty.call(proto, '_query')) { + Object.defineProperty(proto, '_query', { + get(this: { query: unknown }) { + return this.query; + }, + configurable: true, + enumerable: false, + }); + } +} + +declare module 'drizzle-orm/pg-core' { + interface PgDatabase< + TQueryResult extends PgQueryResultHKT, + TFullSchema extends Record = Record, + TSchema extends TablesRelationalConfig = ExtractTablesWithRelations, + > { + _query: PgDatabase['query']; + } +} + +declare module 'drizzle-orm/sqlite-core' { + interface BaseSQLiteDatabase< + TResultKind extends 'sync' | 'async', + TRunResult, + TFullSchema extends Record = Record, + TSchema extends TablesRelationalConfig = ExtractTablesWithRelations, + > { + _query: BaseSQLiteDatabase['query']; + } +} diff --git a/packages/drizzle-shims/tsconfig.json b/packages/drizzle-shims/tsconfig.json new file mode 100644 index 0000000000..512a73a2d7 --- /dev/null +++ b/packages/drizzle-shims/tsconfig.json @@ -0,0 +1,19 @@ +{ + "compilerOptions": { + "target": "es2022", + "module": "ESNext", + "moduleResolution": "bundler", + "lib": ["esnext"], + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "noEmit": true, + "isolatedModules": true, + "resolveJsonModule": true, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true + }, + "include": ["src/**/*"], + "exclude": ["node_modules"] +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 23a34983f8..12cdfc0c34 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -123,6 +123,9 @@ importers: react: specifier: ^19.2.4 version: 19.2.4 + ts-morph: + specifier: ^28.0.0 + version: 28.0.0 tsx: specifier: ^4.21.0 version: 4.21.0 @@ -967,6 +970,9 @@ importers: packages/db: dependencies: + '@kilocode/drizzle-shims': + specifier: workspace:* + version: link:../drizzle-shims '@kilocode/kiloclaw-instance-tiers': specifier: workspace:* version: link:../kiloclaw-instance-tiers @@ -999,6 +1005,19 @@ importers: specifier: 'catalog:' version: 5.9.3 + packages/drizzle-shims: + dependencies: + drizzle-orm: + specifier: 'catalog:' + version: 0.45.1(@cloudflare/workers-types@4.20260430.1)(@opentelemetry/api@1.9.0)(@types/pg@8.18.0)(bun-types@1.3.13)(pg@8.20.0) + devDependencies: + '@typescript/native-preview': + specifier: 'catalog:' + version: 7.0.0-dev.20260319.1 + typescript: + specifier: 'catalog:' + version: 5.9.3 + packages/encryption: devDependencies: '@types/node': @@ -1207,6 +1226,9 @@ importers: services/ai-attribution: dependencies: + '@kilocode/drizzle-shims': + specifier: workspace:* + version: link:../../packages/drizzle-shims '@kilocode/worker-utils': specifier: workspace:* version: link:../../packages/worker-utils @@ -1247,6 +1269,9 @@ importers: '@ashishkumar472/cf-git': specifier: 1.0.5 version: 1.0.5 + '@kilocode/drizzle-shims': + specifier: workspace:* + version: link:../../packages/drizzle-shims '@kilocode/worker-utils': specifier: workspace:* version: link:../../packages/worker-utils @@ -1355,6 +1380,9 @@ importers: '@kilocode/db': specifier: workspace:* version: link:../../packages/db + '@kilocode/drizzle-shims': + specifier: workspace:* + version: link:../../packages/drizzle-shims '@kilocode/encryption': specifier: workspace:* version: link:../../packages/encryption @@ -1425,6 +1453,9 @@ importers: '@kilocode/db': specifier: workspace:* version: link:../../packages/db + '@kilocode/drizzle-shims': + specifier: workspace:* + version: link:../../packages/drizzle-shims '@kilocode/encryption': specifier: workspace:* version: link:../../packages/encryption @@ -1679,7 +1710,7 @@ importers: version: 7.0.0-dev.20260319.1 jest: specifier: ^30.3.0 - version: 30.3.0(@types/node@24.12.0)(esbuild-register@3.6.0(esbuild@0.27.4)) + version: 30.3.0(@types/node@25.5.0)(esbuild-register@3.6.0(esbuild@0.27.4)) typescript: specifier: 'catalog:' version: 5.9.3 @@ -1929,6 +1960,9 @@ importers: '@kilocode/db': specifier: workspace:* version: link:../../packages/db + '@kilocode/drizzle-shims': + specifier: workspace:* + version: link:../../packages/drizzle-shims '@kilocode/encryption': specifier: workspace:* version: link:../../packages/encryption @@ -2015,6 +2049,9 @@ importers: '@kilocode/db': specifier: workspace:* version: link:../../packages/db + '@kilocode/drizzle-shims': + specifier: workspace:* + version: link:../../packages/drizzle-shims '@kilocode/encryption': specifier: workspace:* version: link:../../packages/encryption @@ -2193,6 +2230,9 @@ importers: services/o11y: dependencies: + '@kilocode/drizzle-shims': + specifier: workspace:* + version: link:../../packages/drizzle-shims '@kilocode/worker-utils': specifier: workspace:* version: link:../../packages/worker-utils @@ -2289,6 +2329,9 @@ importers: '@kilocode/db': specifier: workspace:* version: link:../../packages/db + '@kilocode/drizzle-shims': + specifier: workspace:* + version: link:../../packages/drizzle-shims '@kilocode/worker-utils': specifier: workspace:* version: link:../../packages/worker-utils @@ -2338,6 +2381,9 @@ importers: '@kilocode/db': specifier: workspace:* version: link:../../packages/db + '@kilocode/drizzle-shims': + specifier: workspace:* + version: link:../../packages/drizzle-shims '@kilocode/encryption': specifier: workspace:* version: link:../../packages/encryption @@ -7976,6 +8022,9 @@ packages: resolution: {integrity: sha512-w071DSzP94YfN6XiWhOxnLpYT3uqtxJBDYdh6Jdjzt+Ce6DNspJsPQgpC7rbts/B8tEkq0LHoYuIF/O5Jh5rPg==} engines: {node: '>=18'} + '@ts-morph/common@0.29.0': + resolution: {integrity: sha512-35oUmphHbJvQ/+UTwFNme/t2p3FoKiGJ5auTjjpNTop2dyREspirjMy82PLSC1pnDJ8ah1GU98hwpVt64YXQsg==} + '@tybys/wasm-util@0.10.1': resolution: {integrity: sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==} @@ -9393,6 +9442,9 @@ packages: resolution: {integrity: sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==} engines: {iojs: '>= 1.0.0', node: '>= 0.12.0'} + code-block-writer@13.0.3: + resolution: {integrity: sha512-Oofo0pq3IKnsFtuHqSF7TqBfr71aeyZDVJ0HpmqB7FBM2qEigL0iPONSCZSO9pE9dZTAxANe5XHG9Uy0YMv8cg==} + code-excerpt@4.0.0: resolution: {integrity: sha512-xxodCmBen3iy2i0WtAK8FlFNrRzjUqjRsMfho58xT/wvZU1YTM3fCnRjcy1gJPMepaRlgm/0e6w8SpWHpn3/cA==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} @@ -14717,6 +14769,9 @@ packages: ts-mixer@6.0.4: resolution: {integrity: sha512-ufKpbmrugz5Aou4wcr5Wc1UUFWOLhq+Fm6qa6P0w0K5Qw2yhaUoiWszhCVuNQyNwrlGiscHOmqYoAox1PtvgjA==} + ts-morph@28.0.0: + resolution: {integrity: sha512-Wp3tnZ2bzwxyTZMtgWVzXDfm7lB1Drz+y9DmmYH/L702PQhPyVrp3pkou3yIz4qjS14GY9kcpmLiOOMvl8oG1g==} + tsconfig-paths-webpack-plugin@4.2.0: resolution: {integrity: sha512-zbem3rfRS8BgeNK50Zz5SIQgXzLafiHjOwUAvk/38/o1jHn/V5QAgVUcz884or7WYcPaH3N2CIfUc2u0ul7UcA==} engines: {node: '>=10.13.0'} @@ -17026,7 +17081,7 @@ snapshots: '@storybook/csf': 0.1.13 '@storybook/manager-api': 8.5.8(storybook@9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6)) '@storybook/server-webpack5': 8.5.8(@swc/core@1.15.18)(esbuild@0.27.4)(storybook@9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6))(typescript@5.9.3) - storybook: 9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6)(vite@8.0.0(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)) + storybook: 9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6) ts-dedent: 2.2.0 transitivePeerDependencies: - '@rspack/core' @@ -17050,9 +17105,9 @@ snapshots: '@chromaui/rrweb-snapshot': 2.0.0-alpha.18-noAbsolute '@playwright/test': 1.58.2 '@segment/analytics-node': 2.1.3 - '@storybook/addon-essentials': 8.5.8(@types/react@19.2.14)(storybook@9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6)) + '@storybook/addon-essentials': 8.5.8(@types/react@19.2.14)(storybook@9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6)(vite@8.0.0(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))) '@storybook/csf': 0.1.13 - '@storybook/manager-api': 8.5.8(storybook@9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6)) + '@storybook/manager-api': 8.5.8(storybook@9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6)(vite@8.0.0(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))) '@storybook/server-webpack5': 8.5.8(esbuild@0.27.4)(storybook@9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6)(vite@8.0.0(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)))(typescript@5.9.3) storybook: 9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6)(vite@8.0.0(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)) ts-dedent: 2.2.0 @@ -21954,7 +22009,7 @@ snapshots: '@stitches/core@1.2.8': {} - '@storybook/addon-actions@8.5.8(storybook@9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6))': + '@storybook/addon-actions@8.5.8(storybook@9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6)(vite@8.0.0(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)))': dependencies: '@storybook/global': 5.0.0 '@types/uuid': 9.0.8 @@ -21962,20 +22017,60 @@ snapshots: polished: 4.3.1 storybook: 9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6)(vite@8.0.0(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)) uuid: 9.0.1 + optional: true + + '@storybook/addon-actions@8.5.8(storybook@9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6))': + dependencies: + '@storybook/global': 5.0.0 + '@types/uuid': 9.0.8 + dequal: 2.0.3 + polished: 4.3.1 + storybook: 9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6) + uuid: 9.0.1 + + '@storybook/addon-backgrounds@8.5.8(storybook@9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6)(vite@8.0.0(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)))': + dependencies: + '@storybook/global': 5.0.0 + memoizerific: 1.11.3 + storybook: 9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6)(vite@8.0.0(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)) + ts-dedent: 2.2.0 + optional: true '@storybook/addon-backgrounds@8.5.8(storybook@9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6))': dependencies: '@storybook/global': 5.0.0 memoizerific: 1.11.3 + storybook: 9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6) + ts-dedent: 2.2.0 + + '@storybook/addon-controls@8.5.8(storybook@9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6)(vite@8.0.0(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)))': + dependencies: + '@storybook/global': 5.0.0 + dequal: 2.0.3 storybook: 9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6)(vite@8.0.0(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)) ts-dedent: 2.2.0 + optional: true '@storybook/addon-controls@8.5.8(storybook@9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6))': dependencies: '@storybook/global': 5.0.0 dequal: 2.0.3 + storybook: 9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6) + ts-dedent: 2.2.0 + + '@storybook/addon-docs@8.5.8(@types/react@19.2.14)(storybook@9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6)(vite@8.0.0(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)))': + dependencies: + '@mdx-js/react': 3.1.1(@types/react@19.2.14)(react@19.2.4) + '@storybook/blocks': 8.5.8(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(storybook@9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6)(vite@8.0.0(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))) + '@storybook/csf-plugin': 8.5.8(storybook@9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6)(vite@8.0.0(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))) + '@storybook/react-dom-shim': 8.5.8(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(storybook@9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6)(vite@8.0.0(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))) + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) storybook: 9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6)(vite@8.0.0(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)) ts-dedent: 2.2.0 + transitivePeerDependencies: + - '@types/react' + optional: true '@storybook/addon-docs@8.5.8(@types/react@19.2.14)(storybook@9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6))': dependencies: @@ -21985,7 +22080,7 @@ snapshots: '@storybook/react-dom-shim': 8.5.8(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(storybook@9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6)) react: 19.2.4 react-dom: 19.2.4(react@19.2.4) - storybook: 9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6)(vite@8.0.0(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)) + storybook: 9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6) ts-dedent: 2.2.0 transitivePeerDependencies: - '@types/react' @@ -22003,6 +22098,23 @@ snapshots: transitivePeerDependencies: - '@types/react' + '@storybook/addon-essentials@8.5.8(@types/react@19.2.14)(storybook@9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6)(vite@8.0.0(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)))': + dependencies: + '@storybook/addon-actions': 8.5.8(storybook@9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6)(vite@8.0.0(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))) + '@storybook/addon-backgrounds': 8.5.8(storybook@9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6)(vite@8.0.0(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))) + '@storybook/addon-controls': 8.5.8(storybook@9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6)(vite@8.0.0(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))) + '@storybook/addon-docs': 8.5.8(@types/react@19.2.14)(storybook@9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6)(vite@8.0.0(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))) + '@storybook/addon-highlight': 8.5.8(storybook@9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6)(vite@8.0.0(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))) + '@storybook/addon-measure': 8.5.8(storybook@9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6)(vite@8.0.0(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))) + '@storybook/addon-outline': 8.5.8(storybook@9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6)(vite@8.0.0(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))) + '@storybook/addon-toolbars': 8.5.8(storybook@9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6)(vite@8.0.0(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))) + '@storybook/addon-viewport': 8.5.8(storybook@9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6)(vite@8.0.0(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))) + storybook: 9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6)(vite@8.0.0(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)) + ts-dedent: 2.2.0 + transitivePeerDependencies: + - '@types/react' + optional: true + '@storybook/addon-essentials@8.5.8(@types/react@19.2.14)(storybook@9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6))': dependencies: '@storybook/addon-actions': 8.5.8(storybook@9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6)) @@ -22014,15 +22126,21 @@ snapshots: '@storybook/addon-outline': 8.5.8(storybook@9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6)) '@storybook/addon-toolbars': 8.5.8(storybook@9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6)) '@storybook/addon-viewport': 8.5.8(storybook@9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6)) - storybook: 9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6)(vite@8.0.0(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)) + storybook: 9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6) ts-dedent: 2.2.0 transitivePeerDependencies: - '@types/react' - '@storybook/addon-highlight@8.5.8(storybook@9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6))': + '@storybook/addon-highlight@8.5.8(storybook@9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6)(vite@8.0.0(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)))': dependencies: '@storybook/global': 5.0.0 storybook: 9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6)(vite@8.0.0(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)) + optional: true + + '@storybook/addon-highlight@8.5.8(storybook@9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6))': + dependencies: + '@storybook/global': 5.0.0 + storybook: 9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6) '@storybook/addon-links@9.1.20(react@19.2.4)(storybook@9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6)(vite@8.0.0(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)))': dependencies: @@ -22031,37 +22149,73 @@ snapshots: optionalDependencies: react: 19.2.4 - '@storybook/addon-measure@8.5.8(storybook@9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6))': + '@storybook/addon-measure@8.5.8(storybook@9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6)(vite@8.0.0(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)))': dependencies: '@storybook/global': 5.0.0 storybook: 9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6)(vite@8.0.0(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)) tiny-invariant: 1.3.3 + optional: true - '@storybook/addon-outline@8.5.8(storybook@9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6))': + '@storybook/addon-measure@8.5.8(storybook@9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6))': + dependencies: + '@storybook/global': 5.0.0 + storybook: 9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6) + tiny-invariant: 1.3.3 + + '@storybook/addon-outline@8.5.8(storybook@9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6)(vite@8.0.0(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)))': dependencies: '@storybook/global': 5.0.0 storybook: 9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6)(vite@8.0.0(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)) ts-dedent: 2.2.0 + optional: true + + '@storybook/addon-outline@8.5.8(storybook@9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6))': + dependencies: + '@storybook/global': 5.0.0 + storybook: 9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6) + ts-dedent: 2.2.0 '@storybook/addon-themes@9.1.20(storybook@9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6)(vite@8.0.0(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)))': dependencies: storybook: 9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6)(vite@8.0.0(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)) ts-dedent: 2.2.0 + '@storybook/addon-toolbars@8.5.8(storybook@9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6)(vite@8.0.0(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)))': + dependencies: + storybook: 9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6)(vite@8.0.0(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)) + optional: true + '@storybook/addon-toolbars@8.5.8(storybook@9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6))': dependencies: + storybook: 9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6) + + '@storybook/addon-viewport@8.5.8(storybook@9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6)(vite@8.0.0(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)))': + dependencies: + memoizerific: 1.11.3 storybook: 9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6)(vite@8.0.0(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)) + optional: true '@storybook/addon-viewport@8.5.8(storybook@9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6))': dependencies: memoizerific: 1.11.3 + storybook: 9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6) + + '@storybook/blocks@8.5.8(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(storybook@9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6)(vite@8.0.0(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)))': + dependencies: + '@storybook/csf': 0.1.12 + '@storybook/icons': 1.6.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) storybook: 9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6)(vite@8.0.0(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)) + ts-dedent: 2.2.0 + optionalDependencies: + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + optional: true '@storybook/blocks@8.5.8(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(storybook@9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6))': dependencies: '@storybook/csf': 0.1.12 '@storybook/icons': 1.6.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - storybook: 9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6)(vite@8.0.0(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)) + storybook: 9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6) ts-dedent: 2.2.0 optionalDependencies: react: 19.2.4 @@ -22083,7 +22237,7 @@ snapshots: path-browserify: 1.0.1 process: 0.11.10 semver: 7.7.4 - storybook: 9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6)(vite@8.0.0(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)) + storybook: 9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6) style-loader: 3.3.4(webpack@5.105.4(@swc/core@1.15.18)(esbuild@0.27.4)) terser-webpack-plugin: 5.4.0(@swc/core@1.15.18)(esbuild@0.27.4)(webpack@5.105.4(@swc/core@1.15.18)(esbuild@0.27.4)) ts-dedent: 2.2.0 @@ -22105,7 +22259,7 @@ snapshots: '@storybook/builder-webpack5@8.5.8(esbuild@0.27.4)(storybook@9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6)(vite@8.0.0(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)))(typescript@5.9.3)': dependencies: - '@storybook/core-webpack': 8.5.8(storybook@9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6)) + '@storybook/core-webpack': 8.5.8(storybook@9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6)(vite@8.0.0(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))) '@types/semver': 7.7.1 browser-assert: 1.2.1 case-sensitive-paths-webpack-plugin: 2.4.0 @@ -22167,13 +22321,24 @@ snapshots: - uglify-js - webpack-cli + '@storybook/components@8.5.8(storybook@9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6)(vite@8.0.0(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)))': + dependencies: + storybook: 9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6)(vite@8.0.0(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)) + optional: true + '@storybook/components@8.5.8(storybook@9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6))': + dependencies: + storybook: 9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6) + + '@storybook/core-webpack@8.5.8(storybook@9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6)(vite@8.0.0(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)))': dependencies: storybook: 9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6)(vite@8.0.0(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)) + ts-dedent: 2.2.0 + optional: true '@storybook/core-webpack@8.5.8(storybook@9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6))': dependencies: - storybook: 9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6)(vite@8.0.0(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)) + storybook: 9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6) ts-dedent: 2.2.0 '@storybook/core-webpack@9.1.20(storybook@9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6)(vite@8.0.0(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)))': @@ -22181,10 +22346,16 @@ snapshots: storybook: 9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6)(vite@8.0.0(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)) ts-dedent: 2.2.0 - '@storybook/csf-plugin@8.5.8(storybook@9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6))': + '@storybook/csf-plugin@8.5.8(storybook@9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6)(vite@8.0.0(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)))': dependencies: storybook: 9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6)(vite@8.0.0(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)) unplugin: 1.16.1 + optional: true + + '@storybook/csf-plugin@8.5.8(storybook@9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6))': + dependencies: + storybook: 9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6) + unplugin: 1.16.1 '@storybook/csf-plugin@9.1.20(storybook@9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6)(vite@8.0.0(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)))': dependencies: @@ -22206,9 +22377,14 @@ snapshots: react: 19.2.4 react-dom: 19.2.4(react@19.2.4) - '@storybook/manager-api@8.5.8(storybook@9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6))': + '@storybook/manager-api@8.5.8(storybook@9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6)(vite@8.0.0(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)))': dependencies: storybook: 9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6)(vite@8.0.0(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)) + optional: true + + '@storybook/manager-api@8.5.8(storybook@9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6))': + dependencies: + storybook: 9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6) '@storybook/nextjs@9.1.20(patch_hash=e1857649664eed8f87877c352d277c90d4af5a58d0ad931105f033c8c08165c1)(esbuild@0.27.4)(next@16.1.6(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(@playwright/test@1.58.2)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(storybook@9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6)(vite@8.0.0(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)))(type-fest@4.41.0)(typescript@5.9.3)(webpack-hot-middleware@2.26.1)(webpack@5.105.4(esbuild@0.27.4))': dependencies: @@ -22294,19 +22470,35 @@ snapshots: - uglify-js - webpack-cli + '@storybook/preset-server-webpack@8.5.8(storybook@9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6)(vite@8.0.0(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)))': + dependencies: + '@storybook/core-webpack': 8.5.8(storybook@9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6)(vite@8.0.0(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))) + '@storybook/global': 5.0.0 + '@storybook/server': 8.5.8(storybook@9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6)(vite@8.0.0(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))) + safe-identifier: 0.4.2 + storybook: 9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6)(vite@8.0.0(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)) + ts-dedent: 2.2.0 + yaml-loader: 0.8.1 + optional: true + '@storybook/preset-server-webpack@8.5.8(storybook@9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6))': dependencies: '@storybook/core-webpack': 8.5.8(storybook@9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6)) '@storybook/global': 5.0.0 '@storybook/server': 8.5.8(storybook@9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6)) safe-identifier: 0.4.2 - storybook: 9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6)(vite@8.0.0(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)) + storybook: 9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6) ts-dedent: 2.2.0 yaml-loader: 0.8.1 - '@storybook/preview-api@8.5.8(storybook@9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6))': + '@storybook/preview-api@8.5.8(storybook@9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6)(vite@8.0.0(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)))': dependencies: storybook: 9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6)(vite@8.0.0(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)) + optional: true + + '@storybook/preview-api@8.5.8(storybook@9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6))': + dependencies: + storybook: 9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6) '@storybook/react-docgen-typescript-plugin@1.0.6--canary.9.0c3f3b7.0(typescript@5.9.3)(webpack@5.105.4(esbuild@0.27.4))': dependencies: @@ -22322,11 +22514,18 @@ snapshots: transitivePeerDependencies: - supports-color - '@storybook/react-dom-shim@8.5.8(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(storybook@9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6))': + '@storybook/react-dom-shim@8.5.8(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(storybook@9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6)(vite@8.0.0(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)))': dependencies: react: 19.2.4 react-dom: 19.2.4(react@19.2.4) storybook: 9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6)(vite@8.0.0(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)) + optional: true + + '@storybook/react-dom-shim@8.5.8(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(storybook@9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6))': + dependencies: + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + storybook: 9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6) '@storybook/react-dom-shim@9.1.20(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(storybook@9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6)(vite@8.0.0(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)))': dependencies: @@ -22349,7 +22548,7 @@ snapshots: '@storybook/builder-webpack5': 8.5.8(@swc/core@1.15.18)(esbuild@0.27.4)(storybook@9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6))(typescript@5.9.3) '@storybook/preset-server-webpack': 8.5.8(storybook@9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6)) '@storybook/server': 8.5.8(storybook@9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6)) - storybook: 9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6)(vite@8.0.0(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)) + storybook: 9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6) transitivePeerDependencies: - '@rspack/core' - '@swc/core' @@ -22361,8 +22560,8 @@ snapshots: '@storybook/server-webpack5@8.5.8(esbuild@0.27.4)(storybook@9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6)(vite@8.0.0(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)))(typescript@5.9.3)': dependencies: '@storybook/builder-webpack5': 8.5.8(esbuild@0.27.4)(storybook@9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6)(vite@8.0.0(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)))(typescript@5.9.3) - '@storybook/preset-server-webpack': 8.5.8(storybook@9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6)) - '@storybook/server': 8.5.8(storybook@9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6)) + '@storybook/preset-server-webpack': 8.5.8(storybook@9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6)(vite@8.0.0(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))) + '@storybook/server': 8.5.8(storybook@9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6)(vite@8.0.0(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))) storybook: 9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6)(vite@8.0.0(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)) transitivePeerDependencies: - '@rspack/core' @@ -22373,6 +22572,19 @@ snapshots: - webpack-cli optional: true + '@storybook/server@8.5.8(storybook@9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6)(vite@8.0.0(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)))': + dependencies: + '@storybook/components': 8.5.8(storybook@9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6)(vite@8.0.0(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))) + '@storybook/csf': 0.1.12 + '@storybook/global': 5.0.0 + '@storybook/manager-api': 8.5.8(storybook@9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6)(vite@8.0.0(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))) + '@storybook/preview-api': 8.5.8(storybook@9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6)(vite@8.0.0(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))) + '@storybook/theming': 8.5.8(storybook@9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6)(vite@8.0.0(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))) + storybook: 9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6)(vite@8.0.0(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)) + ts-dedent: 2.2.0 + yaml: 2.8.2 + optional: true + '@storybook/server@8.5.8(storybook@9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6))': dependencies: '@storybook/components': 8.5.8(storybook@9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6)) @@ -22381,7 +22593,7 @@ snapshots: '@storybook/manager-api': 8.5.8(storybook@9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6)) '@storybook/preview-api': 8.5.8(storybook@9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6)) '@storybook/theming': 8.5.8(storybook@9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6)) - storybook: 9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6)(vite@8.0.0(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)) + storybook: 9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6) ts-dedent: 2.2.0 yaml: 2.8.2 @@ -22415,9 +22627,14 @@ snapshots: - supports-color - ts-node - '@storybook/theming@8.5.8(storybook@9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6))': + '@storybook/theming@8.5.8(storybook@9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6)(vite@8.0.0(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)))': dependencies: storybook: 9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6)(vite@8.0.0(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)) + optional: true + + '@storybook/theming@8.5.8(storybook@9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6))': + dependencies: + storybook: 9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6) '@streamparser/json@0.0.22': {} @@ -22623,6 +22840,12 @@ snapshots: '@ts-graphviz/ast': 2.0.7 '@ts-graphviz/common': 2.1.5 + '@ts-morph/common@0.29.0': + dependencies: + minimatch: 10.2.4 + path-browserify: 1.0.1 + tinyglobby: 0.2.15 + '@tybys/wasm-util@0.10.1': dependencies: tslib: 2.8.1 @@ -24167,6 +24390,8 @@ snapshots: co@4.6.0: {} + code-block-writer@13.0.3: {} + code-excerpt@4.0.0: dependencies: convert-to-spaces: 2.0.1 @@ -26635,6 +26860,25 @@ snapshots: - supports-color - ts-node + jest-cli@30.3.0(@types/node@25.5.0)(esbuild-register@3.6.0(esbuild@0.27.4)): + dependencies: + '@jest/core': 30.3.0(esbuild-register@3.6.0(esbuild@0.27.4)) + '@jest/test-result': 30.3.0 + '@jest/types': 30.3.0 + chalk: 4.1.2 + exit-x: 0.2.2 + import-local: 3.2.0 + jest-config: 30.3.0(@types/node@25.5.0)(esbuild-register@3.6.0(esbuild@0.27.4)) + jest-util: 30.3.0 + jest-validate: 30.3.0 + yargs: 17.7.2 + transitivePeerDependencies: + - '@types/node' + - babel-plugin-macros + - esbuild-register + - supports-color + - ts-node + jest-config@29.7.0(@types/node@24.12.0): dependencies: '@babel/core': 7.29.0 @@ -27286,6 +27530,19 @@ snapshots: - supports-color - ts-node + jest@30.3.0(@types/node@25.5.0)(esbuild-register@3.6.0(esbuild@0.27.4)): + dependencies: + '@jest/core': 30.3.0(esbuild-register@3.6.0(esbuild@0.27.4)) + '@jest/types': 30.3.0 + import-local: 3.2.0 + jest-cli: 30.3.0(@types/node@25.5.0)(esbuild-register@3.6.0(esbuild@0.27.4)) + transitivePeerDependencies: + - '@types/node' + - babel-plugin-macros + - esbuild-register + - supports-color + - ts-node + jimp-compact@0.16.1: {} jiti@2.6.1: {} @@ -30529,6 +30786,28 @@ snapshots: stoppable@1.1.0: {} + storybook@9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6): + dependencies: + '@storybook/global': 5.0.0 + '@testing-library/jest-dom': 6.9.1 + '@testing-library/user-event': 14.6.1 + '@vitest/expect': 3.2.4 + '@vitest/mocker': 3.2.4(vite@8.0.0(@types/node@24.12.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)) + '@vitest/spy': 3.2.4 + better-opn: 3.0.2 + esbuild: 0.27.4 + esbuild-register: 3.6.0(esbuild@0.27.4) + recast: 0.23.11 + semver: 7.7.4 + ws: 8.19.0(bufferutil@4.1.0)(utf-8-validate@6.0.6) + transitivePeerDependencies: + - '@testing-library/dom' + - bufferutil + - msw + - supports-color + - utf-8-validate + - vite + storybook@9.1.20(bufferutil@4.1.0)(utf-8-validate@6.0.6)(vite@8.0.0(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)): dependencies: '@storybook/global': 5.0.0 @@ -30972,6 +31251,11 @@ snapshots: ts-mixer@6.0.4: {} + ts-morph@28.0.0: + dependencies: + '@ts-morph/common': 0.29.0 + code-block-writer: 13.0.3 + tsconfig-paths-webpack-plugin@4.2.0: dependencies: chalk: 4.1.2 diff --git a/scripts/drizzle-query-rename.ts b/scripts/drizzle-query-rename.ts new file mode 100644 index 0000000000..9cfb3fecd4 --- /dev/null +++ b/scripts/drizzle-query-rename.ts @@ -0,0 +1,183 @@ +#!/usr/bin/env tsx +/** + * Type-aware rewrite of `.query` -> `._query` for every drizzle db / transaction + * receiver. Used both as a one-shot codemod and as a CI verifier. + * + * Usage: + * tsx scripts/drizzle-query-rename.ts --check # exit 1 if any drizzle .query remain + * tsx scripts/drizzle-query-rename.ts --fix # rewrite in place + * tsx scripts/drizzle-query-rename.ts --fix --dry # report what --fix would do + * + * The check is authoritative: it consults the TypeScript type checker. oxlint's + * `drizzle/prefer-underscore-query` rule only sees AST and is gated on a name + * allowlist (db / ctx.db / this.db / tx / trx); this script catches everything + * else (e.g. dbs renamed at destructuring, helpers returning a drizzle db, + * transactions bound to unusual callback param names). + */ + +import { Project, Node, SyntaxKind } from 'ts-morph'; +import { globSync } from 'node:fs'; +import path from 'node:path'; + +const args = new Set(process.argv.slice(2)); +const CHECK = args.has('--check'); +const FIX = args.has('--fix'); +const DRY = args.has('--dry'); + +if (!CHECK && !FIX) { + console.error('usage: drizzle-query-rename.ts --check | --fix [--dry]'); + process.exit(2); +} + +const repoRoot = path.resolve(__dirname, '..'); + +function findTsconfigs(): string[] { + const patterns = [ + 'apps/*/tsconfig.json', + 'packages/*/tsconfig.json', + 'services/*/tsconfig.json', + 'services/*/wrapper/tsconfig.json', + 'services/gastown/container/tsconfig.json', + 'services/deploy-infra/*/tsconfig.json', + ]; + const out: string[] = []; + for (const pattern of patterns) { + for (const f of globSync(pattern, { cwd: repoRoot })) { + out.push(path.join(repoRoot, f)); + } + } + return out.sort(); +} + +// Files under dev/ and scripts/ run directly via tsx and are not covered by +// any workspace tsconfig. Scan them under an ad-hoc synthetic project so the +// codemod doesn't miss them. +function findOrphanFiles(): string[] { + const patterns = ['dev/**/*.ts', 'scripts/**/*.ts']; + const out: string[] = []; + for (const pattern of patterns) { + for (const f of globSync(pattern, { cwd: repoRoot })) { + if (f.includes('/node_modules/')) continue; + out.push(path.join(repoRoot, f)); + } + } + return out.sort(); +} + +// A member access `receiver.query` is a drizzle RQB access iff the type of +// `receiver` has a `query` property whose declaration sits inside the +// drizzle-orm package. This covers PgDatabase, PgTransaction, +// BaseSQLiteDatabase, SQLiteTransaction, and anything else drizzle exports. +function isDrizzleQueryAccess(node: Node): boolean { + if (!Node.isPropertyAccessExpression(node)) return false; + if (node.getNameNode().getText() !== 'query') return false; + + const checker = node.getProject().getTypeChecker(); + const receiverType = checker.getTypeAtLocation(node.getExpression()); + const queryProp = receiverType.getProperty('query'); + if (!queryProp) return false; + + for (const decl of queryProp.getDeclarations()) { + const file = decl.getSourceFile().getFilePath(); + if (file.includes('/node_modules/') && /\/drizzle-orm(@[^/]+)?\//.test(file)) { + return true; + } + // Handle pnpm virtual store too. + if (/\/drizzle-orm\//.test(file) && file.includes('node_modules')) { + return true; + } + } + return false; +} + +type Hit = { file: string; line: number; col: number }; + +const hits: Hit[] = []; +const seen = new Set(); + +function scanProject(project: Project) { + for (const sourceFile of project.getSourceFiles()) { + const filePath = sourceFile.getFilePath(); + if (filePath.includes('/node_modules/')) continue; + if (!filePath.startsWith(repoRoot)) continue; + if (seen.has(filePath)) continue; + seen.add(filePath); + + let fileChanged = false; + const nodes = sourceFile + .getDescendantsOfKind(SyntaxKind.PropertyAccessExpression) + .filter(isDrizzleQueryAccess); + + for (const node of nodes) { + const nameNode = node.getNameNode(); + const { line, column } = sourceFile.getLineAndColumnAtPos(nameNode.getStart()); + hits.push({ file: path.relative(repoRoot, filePath), line, col: column }); + + if (FIX && !DRY) { + nameNode.replaceWithText('_query'); + fileChanged = true; + } + } + + if (fileChanged) sourceFile.saveSync(); + } +} + +const tsconfigs = findTsconfigs(); +console.log(`[drizzle-query-rename] scanning ${tsconfigs.length} tsconfigs`); + +for (const tsconfig of tsconfigs) { + scanProject( + new Project({ + tsConfigFilePath: tsconfig, + skipAddingFilesFromTsConfig: false, + }) + ); +} + +const orphans = findOrphanFiles(); +if (orphans.length > 0) { + console.log(`[drizzle-query-rename] scanning ${orphans.length} orphan files (dev/, scripts/)`); + const synthetic = new Project({ + compilerOptions: { + target: 99, // ESNext + module: 99, // ESNext + moduleResolution: 100, // Bundler + strict: true, + esModuleInterop: true, + skipLibCheck: true, + allowJs: false, + types: ['node'], + }, + }); + for (const f of orphans) synthetic.addSourceFileAtPath(f); + scanProject(synthetic); +} + +if (hits.length === 0) { + console.log('[drizzle-query-rename] no drizzle `.query` receivers found'); + process.exit(0); +} + +const byFile = new Map(); +for (const h of hits) { + const arr = byFile.get(h.file) ?? []; + arr.push(h); + byFile.set(h.file, arr); +} +for (const [file, list] of [...byFile.entries()].sort()) { + console.log(`${file}: ${list.length} hit(s)`); + for (const h of list) console.log(` ${h.line}:${h.col}`); +} +console.log(`[drizzle-query-rename] total: ${hits.length} hit(s) in ${byFile.size} file(s)`); + +if (CHECK) { + console.error( + '[drizzle-query-rename] failing: use `pnpm drizzle:query-rename` or `oxlint --fix` to migrate.' + ); + process.exit(1); +} + +if (FIX && DRY) { + console.log('[drizzle-query-rename] dry run, no files written'); +} diff --git a/services/ai-attribution/package.json b/services/ai-attribution/package.json index 730f2f8e30..5dcb1cd6ee 100644 --- a/services/ai-attribution/package.json +++ b/services/ai-attribution/package.json @@ -27,6 +27,7 @@ "wrangler": "catalog:" }, "dependencies": { + "@kilocode/drizzle-shims": "workspace:*", "@kilocode/worker-utils": "workspace:*", "drizzle-orm": "catalog:", "hono": "catalog:", diff --git a/services/ai-attribution/src/dos/AttributionTracker.do.ts b/services/ai-attribution/src/dos/AttributionTracker.do.ts index b5c6bee838..802ed3753a 100644 --- a/services/ai-attribution/src/dos/AttributionTracker.do.ts +++ b/services/ai-attribution/src/dos/AttributionTracker.do.ts @@ -1,4 +1,5 @@ import { DurableObject } from 'cloudflare:workers'; +import '@kilocode/drizzle-shims/query-alias'; import { drizzle, type DrizzleSqliteDODatabase } from 'drizzle-orm/durable-sqlite'; import { migrate } from 'drizzle-orm/durable-sqlite/migrator'; import { eq, and, sql, desc } from 'drizzle-orm'; diff --git a/services/app-builder/package.json b/services/app-builder/package.json index ca284a5c83..a3d9fd400a 100644 --- a/services/app-builder/package.json +++ b/services/app-builder/package.json @@ -16,6 +16,7 @@ }, "dependencies": { "@ashishkumar472/cf-git": "1.0.5", + "@kilocode/drizzle-shims": "workspace:*", "@kilocode/worker-utils": "workspace:*", "diff": "^8.0.3", "drizzle-orm": "catalog:", diff --git a/services/app-builder/src/git-repository-do.ts b/services/app-builder/src/git-repository-do.ts index e342b70101..e00bfe189b 100644 --- a/services/app-builder/src/git-repository-do.ts +++ b/services/app-builder/src/git-repository-do.ts @@ -5,6 +5,7 @@ */ import { DurableObject } from 'cloudflare:workers'; +import '@kilocode/drizzle-shims/query-alias'; import { drizzle } from 'drizzle-orm/durable-sqlite'; import type { DrizzleSqliteDODatabase } from 'drizzle-orm/durable-sqlite'; import { migrate } from 'drizzle-orm/durable-sqlite/migrator'; diff --git a/services/cloud-agent-next/package.json b/services/cloud-agent-next/package.json index cfdab3c637..dac8111c78 100644 --- a/services/cloud-agent-next/package.json +++ b/services/cloud-agent-next/package.json @@ -31,6 +31,7 @@ "@hono/trpc-server": "^0.4.2", "@kilocode/cloud-agent-profile": "workspace:*", "@kilocode/db": "workspace:*", + "@kilocode/drizzle-shims": "workspace:*", "@kilocode/encryption": "workspace:*", "@kilocode/worker-utils": "workspace:*", "@trpc/server": "catalog:", diff --git a/services/cloud-agent-next/src/persistence/CloudAgentSession.ts b/services/cloud-agent-next/src/persistence/CloudAgentSession.ts index 170339ba27..ef4db0d3c1 100644 --- a/services/cloud-agent-next/src/persistence/CloudAgentSession.ts +++ b/services/cloud-agent-next/src/persistence/CloudAgentSession.ts @@ -23,6 +23,7 @@ import { import { readProfileBundle } from '../session-profile.js'; import type { EncryptedSecrets } from '../router/schemas.js'; import type { CallbackJob, CallbackTarget } from '../callbacks/index.js'; +import '@kilocode/drizzle-shims/query-alias'; import { drizzle } from 'drizzle-orm/durable-sqlite'; import { logger } from '../logger.js'; import { Limits, BUILTIN_AGENT_MODES } from '../schema.js'; diff --git a/services/cloud-agent/package.json b/services/cloud-agent/package.json index e078cde818..8a73fbb7eb 100644 --- a/services/cloud-agent/package.json +++ b/services/cloud-agent/package.json @@ -28,6 +28,7 @@ "dependencies": { "@cloudflare/sandbox": "0.6.7", "@kilocode/db": "workspace:*", + "@kilocode/drizzle-shims": "workspace:*", "@kilocode/encryption": "workspace:*", "@kilocode/worker-utils": "workspace:*", "@octokit/auth-app": "catalog:", diff --git a/services/cloud-agent/src/persistence/CloudAgentSession.ts b/services/cloud-agent/src/persistence/CloudAgentSession.ts index b743798fba..d1cbde1209 100644 --- a/services/cloud-agent/src/persistence/CloudAgentSession.ts +++ b/services/cloud-agent/src/persistence/CloudAgentSession.ts @@ -6,6 +6,7 @@ import { DurableObject } from 'cloudflare:workers'; import { TRPCError } from '@trpc/server'; +import '@kilocode/drizzle-shims/query-alias'; import { drizzle } from 'drizzle-orm/durable-sqlite'; import { migrate } from 'drizzle-orm/durable-sqlite/migrator'; import migrations from '../../drizzle/migrations'; diff --git a/services/kilo-chat/package.json b/services/kilo-chat/package.json index 283de5871b..f65b7fe5cd 100644 --- a/services/kilo-chat/package.json +++ b/services/kilo-chat/package.json @@ -26,6 +26,7 @@ }, "dependencies": { "@kilocode/db": "workspace:*", + "@kilocode/drizzle-shims": "workspace:*", "@kilocode/encryption": "workspace:*", "@kilocode/event-service": "workspace:*", "@kilocode/kilo-chat": "workspace:*", diff --git a/services/kilo-chat/src/do/conversation-do.ts b/services/kilo-chat/src/do/conversation-do.ts index bf793e3b8b..274556c543 100644 --- a/services/kilo-chat/src/do/conversation-do.ts +++ b/services/kilo-chat/src/do/conversation-do.ts @@ -31,6 +31,7 @@ function parseStoredContent(rawContent: string, messageId: string): ContentBlock return []; } } +import '@kilocode/drizzle-shims/query-alias'; import { drizzle } from 'drizzle-orm/durable-sqlite'; import { migrate } from 'drizzle-orm/durable-sqlite/migrator'; import { eq, lt, desc, and, sql, inArray } from 'drizzle-orm'; diff --git a/services/kilo-chat/src/do/membership-do.ts b/services/kilo-chat/src/do/membership-do.ts index 1f2ac40d32..7be5bcc49e 100644 --- a/services/kilo-chat/src/do/membership-do.ts +++ b/services/kilo-chat/src/do/membership-do.ts @@ -1,4 +1,5 @@ import { DurableObject } from 'cloudflare:workers'; +import '@kilocode/drizzle-shims/query-alias'; import { drizzle } from 'drizzle-orm/durable-sqlite'; import { migrate } from 'drizzle-orm/durable-sqlite/migrator'; import { and, eq, desc, isNull, lt, or, sql, type SQL } from 'drizzle-orm'; diff --git a/services/kilo-chat/src/do/sandbox-status-do.ts b/services/kilo-chat/src/do/sandbox-status-do.ts index 34b3780965..67a67bcc0c 100644 --- a/services/kilo-chat/src/do/sandbox-status-do.ts +++ b/services/kilo-chat/src/do/sandbox-status-do.ts @@ -1,4 +1,5 @@ import { DurableObject } from 'cloudflare:workers'; +import '@kilocode/drizzle-shims/query-alias'; import { drizzle } from 'drizzle-orm/durable-sqlite'; import { migrate } from 'drizzle-orm/durable-sqlite/migrator'; import { eq, sql } from 'drizzle-orm'; diff --git a/services/kiloclaw/package.json b/services/kiloclaw/package.json index 9728408947..5f57c21a8d 100644 --- a/services/kiloclaw/package.json +++ b/services/kiloclaw/package.json @@ -21,6 +21,7 @@ }, "dependencies": { "@kilocode/db": "workspace:*", + "@kilocode/drizzle-shims": "workspace:*", "@kilocode/encryption": "workspace:*", "@kilocode/kilo-chat": "workspace:*", "@kilocode/kiloclaw-instance-tiers": "workspace:*", diff --git a/services/kiloclaw/src/durable-objects/kiloclaw-registry.ts b/services/kiloclaw/src/durable-objects/kiloclaw-registry.ts index c7247e2d44..195799fc58 100644 --- a/services/kiloclaw/src/durable-objects/kiloclaw-registry.ts +++ b/services/kiloclaw/src/durable-objects/kiloclaw-registry.ts @@ -1,4 +1,5 @@ import { DurableObject } from 'cloudflare:workers'; +import '@kilocode/drizzle-shims/query-alias'; import { drizzle, type DrizzleSqliteDODatabase } from 'drizzle-orm/durable-sqlite'; import { migrate } from 'drizzle-orm/durable-sqlite/migrator'; import { eq, isNull, and } from 'drizzle-orm'; diff --git a/services/o11y/package.json b/services/o11y/package.json index 2db9db0163..05ca523eee 100644 --- a/services/o11y/package.json +++ b/services/o11y/package.json @@ -21,6 +21,7 @@ "wrangler": "catalog:" }, "dependencies": { + "@kilocode/drizzle-shims": "workspace:*", "@kilocode/worker-utils": "workspace:*", "drizzle-orm": "catalog:", "hono": "catalog:", diff --git a/services/o11y/src/alerting/AlertConfigDO.ts b/services/o11y/src/alerting/AlertConfigDO.ts index 54d063cbd9..f337731282 100644 --- a/services/o11y/src/alerting/AlertConfigDO.ts +++ b/services/o11y/src/alerting/AlertConfigDO.ts @@ -1,4 +1,5 @@ import { DurableObject } from 'cloudflare:workers'; +import '@kilocode/drizzle-shims/query-alias'; import { drizzle } from 'drizzle-orm/durable-sqlite'; import { migrate } from 'drizzle-orm/durable-sqlite/migrator'; import { eq } from 'drizzle-orm'; diff --git a/services/session-ingest/package.json b/services/session-ingest/package.json index 1c9ccf061d..6b72f415a0 100644 --- a/services/session-ingest/package.json +++ b/services/session-ingest/package.json @@ -14,6 +14,7 @@ }, "dependencies": { "@kilocode/db": "workspace:*", + "@kilocode/drizzle-shims": "workspace:*", "@kilocode/worker-utils": "workspace:*", "@streamparser/json": "^0.0.22", "drizzle-orm": "catalog:", diff --git a/services/session-ingest/src/dos/SessionAccessCacheDO.ts b/services/session-ingest/src/dos/SessionAccessCacheDO.ts index 787714271b..b17e417631 100644 --- a/services/session-ingest/src/dos/SessionAccessCacheDO.ts +++ b/services/session-ingest/src/dos/SessionAccessCacheDO.ts @@ -1,5 +1,6 @@ import { DurableObject } from 'cloudflare:workers'; import { eq, sql } from 'drizzle-orm'; +import '@kilocode/drizzle-shims/query-alias'; import { drizzle, type DrizzleSqliteDODatabase } from 'drizzle-orm/durable-sqlite'; import { migrate } from 'drizzle-orm/durable-sqlite/migrator'; diff --git a/services/session-ingest/src/dos/SessionIngestDO.ts b/services/session-ingest/src/dos/SessionIngestDO.ts index df53e76101..650d931c12 100644 --- a/services/session-ingest/src/dos/SessionIngestDO.ts +++ b/services/session-ingest/src/dos/SessionIngestDO.ts @@ -1,5 +1,6 @@ import { DurableObject } from 'cloudflare:workers'; import { eq, ne, gt, and, sql, inArray, isNotNull } from 'drizzle-orm'; +import '@kilocode/drizzle-shims/query-alias'; import { drizzle, type DrizzleSqliteDODatabase } from 'drizzle-orm/durable-sqlite'; import { migrate } from 'drizzle-orm/durable-sqlite/migrator'; diff --git a/services/webhook-agent-ingest/package.json b/services/webhook-agent-ingest/package.json index 63b8faf923..573e4389fb 100644 --- a/services/webhook-agent-ingest/package.json +++ b/services/webhook-agent-ingest/package.json @@ -22,6 +22,7 @@ }, "dependencies": { "@kilocode/db": "workspace:*", + "@kilocode/drizzle-shims": "workspace:*", "@kilocode/encryption": "workspace:*", "@kilocode/worker-utils": "workspace:*", "croner": "^10.0.1", diff --git a/services/webhook-agent-ingest/src/dos/TriggerDO.ts b/services/webhook-agent-ingest/src/dos/TriggerDO.ts index c47bbcc3a6..86d8f4d2c2 100644 --- a/services/webhook-agent-ingest/src/dos/TriggerDO.ts +++ b/services/webhook-agent-ingest/src/dos/TriggerDO.ts @@ -1,4 +1,5 @@ import { DurableObject } from 'cloudflare:workers'; +import '@kilocode/drizzle-shims/query-alias'; import { drizzle } from 'drizzle-orm/durable-sqlite'; import { migrate } from 'drizzle-orm/durable-sqlite/migrator'; import { eq, inArray, sql, desc } from 'drizzle-orm';