diff --git a/src/lib/server/__tests__/syncCurrentUser.test.ts b/src/actions/__tests__/syncCurrentUser.test.ts similarity index 95% rename from src/lib/server/__tests__/syncCurrentUser.test.ts rename to src/actions/__tests__/syncCurrentUser.test.ts index dca84a3108..b341500175 100644 --- a/src/lib/server/__tests__/syncCurrentUser.test.ts +++ b/src/actions/__tests__/syncCurrentUser.test.ts @@ -1,11 +1,12 @@ -// pnpm test src/lib/server/__tests__/syncCurrentUser.test.ts +// pnpm test src/actions/__tests__/syncCurrentUser.test.ts import { db } from '@/db'; import { users, orgs } from '@/db/schema'; import { eq } from 'drizzle-orm'; +import { logger } from '@/lib/server/logger'; + import { syncCurrentUser } from '../sync'; -import { logger } from '../logger'; const testUserId = 'fake-user-id'; const testOrgId = 'fake-org-id'; @@ -21,11 +22,8 @@ vi.mock('@clerk/nextjs/server', () => ({ }), })); -vi.mock('../logger', () => ({ - logger: { - info: vi.fn(), - error: vi.fn(), - }, +vi.mock('@/lib/server/logger', () => ({ + logger: { info: vi.fn(), error: vi.fn() }, })); describe('syncCurrentUser', () => { diff --git a/src/lib/server/__tests__/syncOrg.test.ts b/src/actions/__tests__/syncOrg.test.ts similarity index 94% rename from src/lib/server/__tests__/syncOrg.test.ts rename to src/actions/__tests__/syncOrg.test.ts index 9faef2d800..c7260a9726 100644 --- a/src/lib/server/__tests__/syncOrg.test.ts +++ b/src/actions/__tests__/syncOrg.test.ts @@ -1,13 +1,13 @@ -// pnpm test src/lib/server/__tests__/syncOrg.test.ts +// pnpm test src/actions/__tests__/syncOrg.test.ts import { eq } from 'drizzle-orm'; import { clerkClient } from '@clerk/nextjs/server'; import { db } from '@/db'; import { orgs } from '@/db/schema'; +import { logger } from '@/lib/server/logger'; import { syncOrg } from '../sync'; -import { logger } from '../logger'; vi.mock('@clerk/nextjs/server', () => ({ clerkClient: vi.fn().mockResolvedValue({ @@ -22,11 +22,8 @@ vi.mock('@clerk/nextjs/server', () => ({ }), })); -vi.mock('../logger', () => ({ - logger: { - info: vi.fn(), - error: vi.fn(), - }, +vi.mock('@/lib/server/logger', () => ({ + logger: { info: vi.fn(), error: vi.fn() }, })); describe('syncOrg', () => { diff --git a/src/actions/analytics.ts b/src/actions/analytics.ts index 5b18860602..0c1d39038e 100644 --- a/src/actions/analytics.ts +++ b/src/actions/analytics.ts @@ -1,10 +1,41 @@ 'use server'; import { z } from 'zod'; -import { TelemetryEventName } from '@roo-code/types'; -import { type TimePeriod } from '@/schemas'; -import { client } from '@/lib/server/analytics'; +import { + TelemetryEventName, + type RooCodeTelemetryEvent, +} from '@roo-code/types'; + +import type { TimePeriod } from '@/types'; +import { analytics } from '@/lib/server'; + +/** + * captureEvent + */ + +type AnalyticsEvent = { + id: string; + orgId: string; + userId: string; + timestamp: number; + event: RooCodeTelemetryEvent; +}; + +export const captureEvent = async ({ + event: { properties, ...cloudEvent }, + ...analyticsEvent +}: AnalyticsEvent) => { + // The destructuring here flattens the `AnalyticsEvent` to match the ClickHouse + // schema. + const value = { ...analyticsEvent, ...cloudEvent, ...properties }; + + await analytics.insert({ + table: 'events', + values: [value], + format: 'JSONEachRow', + }); +}; /** * Usage @@ -38,7 +69,7 @@ export const getUsage = async ({ return {}; } - const resultSet = await client.query({ + const resultSet = await analytics.query({ query: ` SELECT type, diff --git a/src/actions/apiUtils.ts b/src/actions/apiUtils.ts deleted file mode 100644 index ea3903c5df..0000000000 --- a/src/actions/apiUtils.ts +++ /dev/null @@ -1,53 +0,0 @@ -import { auth } from '@clerk/nextjs/server'; -import { logger } from '@/lib/server/logger'; - -export type ApiResponse = { - success: boolean; - message?: string; - error?: string; -}; - -/** - * Validates user authentication and organization membership - * @returns User and organization IDs if authenticated, or error response if not - */ -export async function validateAuth(): Promise< - { userId: string; orgId: string } | ApiResponse -> { - const { userId, orgId } = await auth(); - - if (!userId) { - return { success: false, error: 'Unauthorized: User required' }; - } - - if (!orgId) { - return { success: false, error: 'Unauthorized: Organization required' }; - } - - return { userId, orgId }; -} - -export function isAuthSuccess( - result: { userId: string; orgId: string } | ApiResponse, -): result is { userId: string; orgId: string } { - return !('error' in result); -} - -/** - * Generic error handler for all operations - * @param error The caught error - * @param eventPrefix Prefix for logging events - * @returns Error response - */ -export function handleError(error: unknown, eventPrefix: string): ApiResponse { - logger.error({ - event: `${eventPrefix}_update_error`, - error: error instanceof Error ? error.message : 'Unknown error', - }); - - return { - success: false, - error: - error instanceof Error ? error.message : 'An unexpected error occurred', - }; -} diff --git a/src/actions/auditLogs.ts b/src/actions/auditLogs.ts index 6d18bb45ee..741e29e076 100644 --- a/src/actions/auditLogs.ts +++ b/src/actions/auditLogs.ts @@ -2,9 +2,9 @@ import { eq, gte, and, desc } from 'drizzle-orm'; -import { db } from '@/db'; -import { auditLogs, type AuditLog } from '@/db/schema'; -import { logger } from '@/lib/server/logger'; +import { logger } from '@/lib/server'; +import { db, type DB_OR_TX } from '@/db'; +import { auditLogs, type AuditLog, type CreateAuditLog } from '@/db/schema'; export const getAuditLogs = async ({ orgId, @@ -57,3 +57,27 @@ export const getAuditLogs = async ({ throw error; } }; + +export async function insertAuditLog( + db: DB_OR_TX, + values: CreateAuditLog, +): Promise { + await db.insert(auditLogs).values(values); + const { userId, orgId, targetType } = values; + logger.info({ userId, orgId, targetType }); +} + +export async function createAuditLog(values: CreateAuditLog): Promise<{ + success: boolean; + error?: string | Record; +}> { + try { + await insertAuditLog(db, values); + return { success: true }; + } catch (e) { + const error = + e instanceof Error ? e.message : 'An unexpected error occurred'; + logger.error({ event: 'audit_log_creation_error', error }); + return { success: false, error }; + } +} diff --git a/src/actions/auth.ts b/src/actions/auth.ts new file mode 100644 index 0000000000..096a58d980 --- /dev/null +++ b/src/actions/auth.ts @@ -0,0 +1,51 @@ +'use server'; + +import { auth } from '@clerk/nextjs/server'; + +import type { ApiResponse } from '@/types'; +import { Env, logger } from '@/lib/server'; + +export async function validateAuth(): Promise< + { userId: string; orgId: string } | ApiResponse +> { + const { userId, orgId } = await auth(); + + if (!userId) { + return { success: false, error: 'Unauthorized: User required' }; + } + + if (!orgId) { + return { success: false, error: 'Unauthorized: Organization required' }; + } + + return { userId, orgId }; +} + +// Default expiration is 30 days (2592000 seconds). +export async function getSignInToken( + userId: string, +): Promise { + const response = await fetch('https://api.clerk.com/v1/sign_in_tokens', { + method: 'POST', + headers: { + Authorization: `Bearer ${Env.CLERK_SECRET_KEY}`, + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ user_id: userId }), + }); + + if (!response.ok) { + logger.error({ + event: 'sign_in_token_creation_failed', + error: await response.json(), + userId, + }); + + throw new Error('Failed to create sign-in token'); + } + + // TODO: Validate response with a schema. + const data = await response.json(); + logger.info({ event: 'sign_in_token_created', userId }); + return data.token; +} diff --git a/src/actions/defaultParameters.ts b/src/actions/defaultParameters.ts index 522dd337be..63369c0ea5 100644 --- a/src/actions/defaultParameters.ts +++ b/src/actions/defaultParameters.ts @@ -1,18 +1,15 @@ 'use server'; +import { sql } from 'drizzle-orm'; import { z } from 'zod'; +import { type ApiResponse, ORGANIZATION_ALLOW_ALL } from '@/types'; import { db } from '@/db'; import { AuditLogTargetType, orgSettings } from '@/db/schema'; -import { insertAuditLog } from '@/lib/server/auditLogs'; -import { - handleError, - isAuthSuccess, - validateAuth, - type ApiResponse, -} from './apiUtils'; -import { sql } from 'drizzle-orm'; -import { ORGANIZATION_ALLOW_ALL } from '@/schemas'; +import { isAuthSuccess, handleError } from '@/lib/server'; + +import { validateAuth } from './auth'; +import { insertAuditLog } from './auditLogs'; const defaultParametersSchema = z.object({ experimentalPowerSteering: z.boolean().optional(), diff --git a/src/actions/organizationSettings.ts b/src/actions/organizationSettings.ts index 2484df065b..0fab7f71c2 100644 --- a/src/actions/organizationSettings.ts +++ b/src/actions/organizationSettings.ts @@ -1,24 +1,23 @@ 'use server'; -import { auth } from '@clerk/nextjs/server'; -import { db } from '@/db'; -import { AuditLogTargetType, orgSettings } from '@/db/schema'; import { eq, sql } from 'drizzle-orm'; +import { auth } from '@clerk/nextjs/server'; +import { z } from 'zod'; + import { + type ApiResponse, ORGANIZATION_ALLOW_ALL, ORGANIZATION_DEFAULT, type OrganizationSettings, organizationAllowListSchema, organizationDefaultSettingsSchema, -} from '@/schemas'; -import { z } from 'zod'; -import { - handleError, - isAuthSuccess, - validateAuth, - type ApiResponse, -} from './apiUtils'; -import { insertAuditLog } from '@/lib/server/auditLogs'; +} from '@/types'; +import { db } from '@/db'; +import { AuditLogTargetType, orgSettings } from '@/db/schema'; +import { handleError, isAuthSuccess } from '@/lib/server'; + +import { validateAuth } from './auth'; +import { insertAuditLog } from './auditLogs'; export async function getOrganizationSettings(): Promise< OrganizationSettings | undefined diff --git a/src/actions/providerWhitelist.ts b/src/actions/providerWhitelist.ts index 24bd0106a8..1aa2f4b968 100644 --- a/src/actions/providerWhitelist.ts +++ b/src/actions/providerWhitelist.ts @@ -2,14 +2,12 @@ import { z } from 'zod'; +import type { ApiResponse } from '@/types'; +import { handleError, isAuthSuccess } from '@/lib/server'; import { AuditLogTargetType } from '@/db/schema'; -import { createAuditLog } from '@/lib/server/auditLogs'; -import { - handleError, - isAuthSuccess, - validateAuth, - type ApiResponse, -} from './apiUtils'; + +import { validateAuth } from './auth'; +import { createAuditLog } from './auditLogs'; const allowAllProvidersSchema = z.object({ allowAllProviders: z.boolean(), diff --git a/src/lib/server/sync.ts b/src/actions/sync.ts similarity index 98% rename from src/lib/server/sync.ts rename to src/actions/sync.ts index 76d2a0dc29..c0684807aa 100644 --- a/src/lib/server/sync.ts +++ b/src/actions/sync.ts @@ -1,10 +1,12 @@ +'use server'; + import { eq } from 'drizzle-orm'; import { clerkClient, currentUser } from '@clerk/nextjs/server'; import { db } from '@/db'; import { users, type CreateUser, orgs, type CreateOrg } from '@/db/schema'; -import { logger } from './logger'; +import { logger } from '../lib/server/logger'; export async function syncCurrentUser({ userId, diff --git a/src/app/(authenticated)/audit-logs/AuditLogs.tsx b/src/app/(authenticated)/audit-logs/AuditLogs.tsx index 6487574b04..f7878cdd4a 100644 --- a/src/app/(authenticated)/audit-logs/AuditLogs.tsx +++ b/src/app/(authenticated)/audit-logs/AuditLogs.tsx @@ -4,8 +4,8 @@ import { useState } from 'react'; import { useAuth } from '@clerk/nextjs'; import { useQuery } from '@tanstack/react-query'; +import { type TimePeriod, timePeriods } from '@/types'; import type { AuditLog } from '@/db/schema'; -import { timePeriods, type TimePeriod } from '@/schemas'; import { getAuditLogs } from '@/actions/auditLogs'; import { Button, diff --git a/src/app/(authenticated)/org/[[...organization-profile]]/DefaultParameters.tsx b/src/app/(authenticated)/org/[[...organization-profile]]/DefaultParameters.tsx index 521c32593a..bafd606a64 100644 --- a/src/app/(authenticated)/org/[[...organization-profile]]/DefaultParameters.tsx +++ b/src/app/(authenticated)/org/[[...organization-profile]]/DefaultParameters.tsx @@ -14,7 +14,7 @@ import { import { updateDefaultParameters } from '@/actions/defaultParameters'; import { getOrganizationSettings } from '@/actions/organizationSettings'; -import { type OrganizationSettings } from '@/schemas'; +import { type OrganizationSettings } from '@/types'; import { Button, Checkbox, diff --git a/src/app/(authenticated)/org/[[...organization-profile]]/ProviderWhitelist.tsx b/src/app/(authenticated)/org/[[...organization-profile]]/ProviderWhitelist.tsx index 626dd97580..7c410c729d 100644 --- a/src/app/(authenticated)/org/[[...organization-profile]]/ProviderWhitelist.tsx +++ b/src/app/(authenticated)/org/[[...organization-profile]]/ProviderWhitelist.tsx @@ -3,19 +3,20 @@ import { useTranslations } from 'next-intl'; import { useState } from 'react'; import { useQuery, useQueryClient } from '@tanstack/react-query'; +import { toast } from 'sonner'; +import { type ProviderName } from '@roo-code/types'; + +import { + type OrganizationAllowList, + type OrganizationSettings, + ORGANIZATION_ALLOW_ALL, +} from '@/types'; import { getOrganizationSettings, updateOrganization, } from '@/actions/organizationSettings'; import { Badge, Button, Checkbox, Label } from '@/components/ui'; -import { toast } from 'sonner'; -import { - ORGANIZATION_ALLOW_ALL, - type OrganizationAllowList, - type OrganizationSettings, -} from '@/schemas'; -import { type ProviderName } from '@roo-code/types'; type ProviderSetting = { allowAll: boolean; diff --git a/src/app/api/events/route.ts b/src/app/api/events/route.ts index e5298c544a..a8136695c3 100644 --- a/src/app/api/events/route.ts +++ b/src/app/api/events/route.ts @@ -4,7 +4,7 @@ import { v4 as uuidv4 } from 'uuid'; import { rooCodeTelemetryEventSchema } from '@roo-code/types'; -import { captureEvent } from '@/lib/server/analytics'; +import { captureEvent } from '@/actions/analytics'; export async function POST(request: NextRequest) { const { userId, orgId } = await auth(); diff --git a/src/app/api/organization-settings/route.ts b/src/app/api/organization-settings/route.ts index 6bfaa43f63..f254b625dc 100644 --- a/src/app/api/organization-settings/route.ts +++ b/src/app/api/organization-settings/route.ts @@ -1,7 +1,8 @@ -import { auth } from '@clerk/nextjs/server'; import { NextResponse } from 'next/server'; +import { auth } from '@clerk/nextjs/server'; + +import { type OrganizationSettings, ORGANIZATION_ALLOW_ALL } from '@/types'; import { getOrganizationSettings } from '@/actions/organizationSettings'; -import { ORGANIZATION_ALLOW_ALL, type OrganizationSettings } from '@/schemas'; export async function GET() { try { diff --git a/src/app/extension/sign-in/page.tsx b/src/app/extension/sign-in/page.tsx index 3063d7620f..efb00dd705 100644 --- a/src/app/extension/sign-in/page.tsx +++ b/src/app/extension/sign-in/page.tsx @@ -1,8 +1,8 @@ import { redirect } from 'next/navigation'; import { auth } from '@clerk/nextjs/server'; -import { getSignInToken } from '@/lib/server/clerk'; -import { Env } from '@/lib/server/env'; +import { Env } from '@/lib/server'; +import { getSignInToken } from '@/actions/auth'; import { DeepLink } from './DeepLink'; diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 31b692e085..b41a1b9990 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -5,7 +5,7 @@ import { getLocale, getTranslations, setRequestLocale } from 'next-intl/server'; import { auth } from '@clerk/nextjs/server'; import { getClerkLocale } from '@/i18n/locale'; -import { syncAuth } from '@/lib/server/sync'; +import { syncAuth } from '@/actions/sync'; import { Toaster } from '@/components/ui'; import { ThemeProvider, diff --git a/src/components/usage/UsageCard.tsx b/src/components/usage/UsageCard.tsx index 27d8b34f90..b0459b3fd1 100644 --- a/src/components/usage/UsageCard.tsx +++ b/src/components/usage/UsageCard.tsx @@ -10,7 +10,7 @@ import { ArrowRightIcon } from 'lucide-react'; import { TelemetryEventName } from '@roo-code/types'; -import { type TimePeriod, timePeriods } from '@/schemas'; +import { type TimePeriod, timePeriods } from '@/types'; import { getUsage } from '@/actions/analytics'; import { formatCurrency } from '@/lib/formatters'; diff --git a/src/db/index.ts b/src/db/index.ts index 0f17699ad0..9984eab722 100644 --- a/src/db/index.ts +++ b/src/db/index.ts @@ -1,7 +1,7 @@ import { drizzle } from 'drizzle-orm/node-postgres'; import { Pool } from 'pg'; -import { Env } from '@/lib/server/env'; +import { Env } from '@/lib/server'; const pool = new Pool({ connectionString: process.env.DATABASE_URL, diff --git a/src/db/schema.ts b/src/db/schema.ts index e05c6c89ea..f5aa28e22d 100644 --- a/src/db/schema.ts +++ b/src/db/schema.ts @@ -10,10 +10,10 @@ import { import { relations } from 'drizzle-orm'; import { - ORGANIZATION_ALLOW_ALL, type OrganizationDefaultSettings, type OrganizationAllowList, -} from '@/schemas'; + ORGANIZATION_ALLOW_ALL, +} from '@/types'; /** * users diff --git a/src/lib/server/analytics.ts b/src/lib/server/analytics.ts index 1c8f80c3bc..2cb5aed715 100644 --- a/src/lib/server/analytics.ts +++ b/src/lib/server/analytics.ts @@ -1,35 +1,9 @@ import { createClient } from '@clickhouse/client'; -import type { RooCodeTelemetryEvent } from '@roo-code/types'; - import { Env } from './env'; -export const client = createClient({ +export const analytics = createClient({ url: Env.CLICKHOUSE_URL, username: Env.CLICKHOUSE_USERNAME, password: Env.CLICKHOUSE_PASSWORD, }); - -type AnalyticsEvent = { - id: string; - orgId: string; - userId: string; - timestamp: number; - event: RooCodeTelemetryEvent; -}; - -export const captureEvent = async ({ - event: { properties, ...cloudEvent }, - ...analyticsEvent -}: AnalyticsEvent) => { - // The destructuring here flattens the `AnalyticsEvent` to match the ClickHouse - // schema. - const value = { ...analyticsEvent, ...cloudEvent, ...properties }; - console.log(`captureEvent`, value); - - await client.insert({ - table: 'events', - values: [value], - format: 'JSONEachRow', - }); -}; diff --git a/src/lib/server/api.ts b/src/lib/server/api.ts new file mode 100644 index 0000000000..7e0381481a --- /dev/null +++ b/src/lib/server/api.ts @@ -0,0 +1,14 @@ +import type { ApiResponse } from '@/types'; +import { logger } from '@/lib/server'; + +export function isAuthSuccess( + result: { userId: string; orgId: string } | ApiResponse, +): result is { userId: string; orgId: string } { + return !('error' in result); +} + +export function handleError(e: unknown, eventPrefix: string): ApiResponse { + const error = e instanceof Error ? e.message : 'Unknown error'; + logger.error({ event: `${eventPrefix}_error`, error }); + return { success: false, error }; +} diff --git a/src/lib/server/auditLogs.ts b/src/lib/server/auditLogs.ts deleted file mode 100644 index 1ec49f5026..0000000000 --- a/src/lib/server/auditLogs.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { db, type DB_OR_TX } from '@/db'; -import { auditLogs, type CreateAuditLog } from '@/db/schema'; -import { logger } from '@/lib/server/logger'; - -export async function insertAuditLog( - db: DB_OR_TX, - values: CreateAuditLog, -): Promise { - await db.insert(auditLogs).values(values); - const { userId, orgId, targetType } = values; - logger.info({ userId, orgId, targetType }); -} - -export async function createAuditLog(values: CreateAuditLog): Promise<{ - success: boolean; - error?: string | Record; -}> { - try { - await insertAuditLog(db, values); - return { success: true }; - } catch (e) { - const error = - e instanceof Error ? e.message : 'An unexpected error occurred'; - logger.error({ event: 'audit_log_creation_error', error }); - return { success: false, error }; - } -} diff --git a/src/lib/server/clerk.ts b/src/lib/server/clerk.ts deleted file mode 100644 index 57ef19797f..0000000000 --- a/src/lib/server/clerk.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { Env } from './env'; -import { logger } from './logger'; - -export async function getSignInToken( - userId: string, -): Promise { - const response = await fetch('https://api.clerk.com/v1/sign_in_tokens', { - method: 'POST', - headers: { - Authorization: `Bearer ${Env.CLERK_SECRET_KEY}`, - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ - user_id: userId, - // Default expiration is 30 days (2592000 seconds) - }), - }); - - if (!response.ok) { - const errorData = await response.json(); - logger.error({ - event: 'sign_in_token_creation_failed', - error: errorData, - userId, - }); - - throw new Error("Failed to create sign-in token"); - } - - const data = await response.json(); - - logger.info({ - event: 'sign_in_token_created', - userId, - }); - - return data.token; -} diff --git a/src/lib/server/index.ts b/src/lib/server/index.ts new file mode 100644 index 0000000000..5072d0410d --- /dev/null +++ b/src/lib/server/index.ts @@ -0,0 +1,4 @@ +export { Env } from './env'; +export { logger } from './logger'; +export { isAuthSuccess, handleError } from './api'; +export { analytics } from './analytics'; diff --git a/src/lib/server/logger.ts b/src/lib/server/logger.ts index 7a0ea1d270..3498f7d9a2 100644 --- a/src/lib/server/logger.ts +++ b/src/lib/server/logger.ts @@ -1,22 +1,17 @@ -import type { DestinationStream } from 'pino'; -import logtail from '@logtail/pino'; -import pino from 'pino'; +import pino, { type DestinationStream } from 'pino'; import pretty from 'pino-pretty'; +import logtail from '@logtail/pino'; import { Env } from './env'; -let stream: DestinationStream; - -if (Env.LOGTAIL_SOURCE_TOKEN) { - stream = pino.multistream([ - await logtail({ - sourceToken: Env.LOGTAIL_SOURCE_TOKEN, - options: { sendLogsToBetterStack: true }, - }), - { stream: pretty() }, // Prints logs to the console. - ]); -} else { - stream = pretty({ colorize: true }); -} +const stream: DestinationStream = Env.LOGTAIL_SOURCE_TOKEN + ? pino.multistream([ + await logtail({ + sourceToken: Env.LOGTAIL_SOURCE_TOKEN, + options: { sendLogsToBetterStack: true }, + }), + { stream: pretty() }, // Prints logs to the console. + ]) + : pretty({ colorize: true }); export const logger = pino({ base: undefined }, stream); diff --git a/src/types/api.ts b/src/types/api.ts new file mode 100644 index 0000000000..8d02c28ded --- /dev/null +++ b/src/types/api.ts @@ -0,0 +1,5 @@ +export type ApiResponse = { + success: boolean; + message?: string; + error?: string; +}; diff --git a/src/types/index.ts b/src/types/index.ts new file mode 100644 index 0000000000..b137ade6c8 --- /dev/null +++ b/src/types/index.ts @@ -0,0 +1,3 @@ +export * from './api'; +export * from './org'; +export * from './time-period'; diff --git a/src/schemas/index.ts b/src/types/org.ts similarity index 93% rename from src/schemas/index.ts rename to src/types/org.ts index dc4314e9bc..0c8f95ce81 100644 --- a/src/schemas/index.ts +++ b/src/types/org.ts @@ -1,14 +1,6 @@ -/** - * TimePeriod - */ - import { providerNames } from '@roo-code/types'; import { z } from 'zod'; -export const timePeriods = [7, 30, 90] as const; - -export type TimePeriod = (typeof timePeriods)[number]; - export const organizationAllowListSchema = z.object({ allowAll: z.boolean(), providers: z.record( diff --git a/src/types/time-period.ts b/src/types/time-period.ts new file mode 100644 index 0000000000..98b928e78c --- /dev/null +++ b/src/types/time-period.ts @@ -0,0 +1,3 @@ +export const timePeriods = [7, 30, 90] as const; + +export type TimePeriod = (typeof timePeriods)[number]; diff --git a/vitest-global-setup.ts b/vitest-global-setup.ts index 4a36f20852..8f043cc9c7 100644 --- a/vitest-global-setup.ts +++ b/vitest-global-setup.ts @@ -1,6 +1,6 @@ import { sql } from 'drizzle-orm'; -import { Env } from '@/lib/server/env'; +import { Env } from '@/lib/server'; import { testDb, disconnect } from '@/db'; async function resetTestDatabase() {