Skip to content

Commit ba0d08b

Browse files
committed
refactor(testing): move DbOperations interface to canonical contracts location
- Move DbOperations and DbWhereResult from testing/mock-db.ts to types/contracts/database.ts - Update production imports in version-utils.ts, agent-runs/_post.ts, steps/_post.ts - Re-export from mock-db.ts for backwards compatibility with test imports - Fix type error in dependencies/_get.ts by handling version: string | null - Update knowledge.md with proper import guidance
1 parent 7111953 commit ba0d08b

File tree

7 files changed

+77
-51
lines changed

7 files changed

+77
-51
lines changed

common/src/testing/knowledge.md

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,17 @@ Mock database objects for testing. No real database needed.
44

55
## DbOperations
66

7-
`DbOperations` is a minimal interface in `@codebuff/common/testing/mock-db`. Both the real `CodebuffPgDatabase` and these mocks satisfy it, so you can pass mocks directly to functions without `as any`.
7+
`DbOperations` is a minimal interface defined in `@codebuff/common/types/contracts/database`. Both the real `CodebuffPgDatabase` and test mocks satisfy it, enabling dependency injection without `as any` casts.
8+
9+
**Production code** should import from the contracts location:
10+
```ts
11+
import type { DbOperations } from '@codebuff/common/types/contracts/database'
12+
```
13+
14+
**Test code** can import from either location (mock-db re-exports the interface for convenience):
15+
```ts
16+
import { createMockDb, type DbOperations } from '@codebuff/common/testing/mock-db'
17+
```
818

919
## Utilities
1020

common/src/testing/mock-db.ts

Lines changed: 6 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,11 @@
11
import type { Logger } from '@codebuff/common/types/contracts/logger'
2+
import type {
3+
DbOperations,
4+
DbWhereResult,
5+
} from '@codebuff/common/types/contracts/database'
26

3-
// ============================================================================
4-
// Database Operations Interface
5-
// ============================================================================
6-
7-
/* eslint-disable @typescript-eslint/no-explicit-any */
8-
/**
9-
* Minimal database interface for dependency injection in API routes.
10-
* Both the real CodebuffPgDatabase and test mocks can satisfy this interface.
11-
*
12-
* Uses `any` for table/column parameters to be compatible with Drizzle ORM's
13-
* specific table types while remaining flexible for mocks.
14-
*/
15-
export interface DbOperations {
16-
insert: (table: any) => {
17-
values: (data: any) => PromiseLike<any>
18-
}
19-
update: (table: any) => {
20-
set: (data: any) => {
21-
where: (condition: any) => PromiseLike<any>
22-
}
23-
}
24-
select: (columns?: any) => {
25-
from: (table: any) => {
26-
where: (condition: any) => DbWhereResult
27-
}
28-
}
29-
}
30-
31-
/**
32-
* Result type for where() that supports multiple query patterns:
33-
* - .limit(n) for simple queries
34-
* - .orderBy(...).limit(n) for sorted queries
35-
* - .then() for promise-like resolution
36-
*/
37-
export interface DbWhereResult {
38-
then: <TResult = any[]>(
39-
onfulfilled?: ((value: any[]) => TResult | PromiseLike<TResult>) | null | undefined,
40-
) => PromiseLike<TResult>
41-
limit: (n: number) => PromiseLike<any[]>
42-
orderBy: (...columns: any[]) => {
43-
limit: (n: number) => PromiseLike<any[]>
44-
}
45-
}
46-
/* eslint-enable @typescript-eslint/no-explicit-any */
7+
// Re-export database interfaces for backwards compatibility with test imports
8+
export type { DbOperations, DbWhereResult }
479

4810
// Compatibility layer: use bun:test mock when available, otherwise identity function
4911
// This allows the utilities to work in both Bun and Jest environments

common/src/types/contracts/database.ts

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,51 @@
11
import type { AgentTemplate } from '@codebuff/common/types/agent-template'
22
import type { Logger } from '@codebuff/common/types/contracts/logger'
33

4+
// ============================================================================
5+
// Database Operations Interface
6+
// ============================================================================
7+
8+
/* eslint-disable @typescript-eslint/no-explicit-any */
9+
/**
10+
* Minimal database interface for dependency injection in API routes.
11+
* Both the real CodebuffPgDatabase and test mocks can satisfy this interface.
12+
*
13+
* Uses `any` for table/column parameters to be compatible with Drizzle ORM's
14+
* specific table types while remaining flexible for mocks.
15+
*/
16+
export interface DbOperations {
17+
insert: (table: any) => {
18+
values: (data: any) => PromiseLike<any>
19+
}
20+
update: (table: any) => {
21+
set: (data: any) => {
22+
where: (condition: any) => PromiseLike<any>
23+
}
24+
}
25+
select: (columns?: any) => {
26+
from: (table: any) => {
27+
where: (condition: any) => DbWhereResult
28+
}
29+
}
30+
}
31+
32+
/**
33+
* Result type for where() that supports multiple query patterns:
34+
* - .limit(n) for simple queries
35+
* - .orderBy(...).limit(n) for sorted queries
36+
* - .then() for promise-like resolution
37+
*/
38+
export interface DbWhereResult {
39+
then: <TResult = any[]>(
40+
onfulfilled?: ((value: any[]) => TResult | PromiseLike<TResult>) | null | undefined,
41+
) => PromiseLike<TResult>
42+
limit: (n: number) => PromiseLike<any[]>
43+
orderBy: (...columns: any[]) => {
44+
limit: (n: number) => PromiseLike<any[]>
45+
}
46+
}
47+
/* eslint-enable @typescript-eslint/no-explicit-any */
48+
449
type User = {
550
id: string
651
email: string

packages/internal/src/utils/version-utils.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { and, desc, eq } from 'drizzle-orm'
22

33
import * as schema from '@codebuff/internal/db/schema'
44

5-
import type { DbOperations } from '@codebuff/common/testing/mock-db'
5+
import type { DbOperations } from '@codebuff/common/types/contracts/database'
66

77
export type Version = { major: number; minor: number; patch: number }
88

web/src/app/api/agents/[publisherId]/[agentId]/[version]/dependencies/_get.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,8 +152,13 @@ function createBatchingAgentLookup(
152152
return async function lookupAgent(
153153
publisher: string,
154154
agentId: string,
155-
version: string,
155+
version: string | null,
156156
): Promise<AgentLookupResult | null> {
157+
// Can't look up an agent without a version
158+
if (version === null) {
159+
return null
160+
}
161+
157162
const cacheKey = `${publisher}/${agentId}@${version}`
158163

159164
// Return from cache if available

web/src/app/api/v1/agent-runs/[runId]/steps/_post.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,10 @@ import { NextResponse } from 'next/server'
77
import { z } from 'zod'
88

99
import type { TrackEventFn } from '@codebuff/common/types/contracts/analytics'
10-
import type { GetUserInfoFromApiKeyFn } from '@codebuff/common/types/contracts/database'
11-
import type { DbOperations } from '@codebuff/common/testing/mock-db'
10+
import type {
11+
DbOperations,
12+
GetUserInfoFromApiKeyFn,
13+
} from '@codebuff/common/types/contracts/database'
1214
import type {
1315
Logger,
1416
LoggerWithContextFn,

web/src/app/api/v1/agent-runs/_post.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,10 @@ import { NextResponse } from 'next/server'
77
import { z } from 'zod'
88

99
import type { TrackEventFn } from '@codebuff/common/types/contracts/analytics'
10-
import type { GetUserInfoFromApiKeyFn } from '@codebuff/common/types/contracts/database'
11-
import type { DbOperations } from '@codebuff/common/testing/mock-db'
10+
import type {
11+
DbOperations,
12+
GetUserInfoFromApiKeyFn,
13+
} from '@codebuff/common/types/contracts/database'
1214
import type {
1315
Logger,
1416
LoggerWithContextFn,

0 commit comments

Comments
 (0)