Skip to content

Commit 57ec777

Browse files
committed
checkpoint
1 parent f44031d commit 57ec777

File tree

5 files changed

+48
-39
lines changed

5 files changed

+48
-39
lines changed

packages/db/src/query/builder/functions.ts

Lines changed: 25 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2,71 +2,72 @@ import { Aggregate, Func } from "../ir"
22
import { toExpression } from "./ref-proxy.js"
33
import type { BasicExpression } from "../ir"
44
import type { RefProxy } from "./ref-proxy.js"
5+
import type { Ref } from "./types.js"
56

67
// Helper type for any expression-like value
7-
type ExpressionLike = BasicExpression | RefProxy<any> | any
8+
type ExpressionLike = BasicExpression | RefProxy<any> | Ref<any> | any
89

910
// Operators
1011

1112
export function eq<T>(
12-
left: RefProxy<T>,
13-
right: T | RefProxy<T> | BasicExpression<T>
13+
left: RefProxy<T> | undefined,
14+
right: T | RefProxy<T> | BasicExpression<T> | undefined
1415
): BasicExpression<boolean>
1516
export function eq<T extends string | number | boolean>(
16-
left: T | BasicExpression<T>,
17-
right: T | BasicExpression<T>
17+
left: T | BasicExpression<T> | undefined,
18+
right: T | BasicExpression<T> | undefined
1819
): BasicExpression<boolean>
1920
export function eq<T>(left: Aggregate<T>, right: any): BasicExpression<boolean>
2021
export function eq(left: any, right: any): BasicExpression<boolean> {
2122
return new Func(`eq`, [toExpression(left), toExpression(right)])
2223
}
2324

2425
export function gt<T>(
25-
left: RefProxy<T>,
26-
right: T | RefProxy<T> | BasicExpression<T>
26+
left: RefProxy<T> | undefined,
27+
right: T | RefProxy<T> | BasicExpression<T> | undefined
2728
): BasicExpression<boolean>
2829
export function gt<T extends string | number>(
29-
left: T | BasicExpression<T>,
30-
right: T | BasicExpression<T>
30+
left: T | BasicExpression<T> | undefined,
31+
right: T | BasicExpression<T> | undefined
3132
): BasicExpression<boolean>
3233
export function gt<T>(left: Aggregate<T>, right: any): BasicExpression<boolean>
3334
export function gt(left: any, right: any): BasicExpression<boolean> {
3435
return new Func(`gt`, [toExpression(left), toExpression(right)])
3536
}
3637

3738
export function gte<T>(
38-
left: RefProxy<T>,
39-
right: T | RefProxy<T> | BasicExpression<T>
39+
left: RefProxy<T> | undefined,
40+
right: T | RefProxy<T> | BasicExpression<T> | undefined
4041
): BasicExpression<boolean>
4142
export function gte<T extends string | number>(
42-
left: T | BasicExpression<T>,
43-
right: T | BasicExpression<T>
43+
left: T | BasicExpression<T> | undefined,
44+
right: T | BasicExpression<T> | undefined
4445
): BasicExpression<boolean>
4546
export function gte<T>(left: Aggregate<T>, right: any): BasicExpression<boolean>
4647
export function gte(left: any, right: any): BasicExpression<boolean> {
4748
return new Func(`gte`, [toExpression(left), toExpression(right)])
4849
}
4950

5051
export function lt<T>(
51-
left: RefProxy<T>,
52-
right: T | RefProxy<T> | BasicExpression<T>
52+
left: RefProxy<T> | undefined,
53+
right: T | RefProxy<T> | BasicExpression<T> | undefined
5354
): BasicExpression<boolean>
5455
export function lt<T extends string | number>(
55-
left: T | BasicExpression<T>,
56-
right: T | BasicExpression<T>
56+
left: T | BasicExpression<T> | undefined,
57+
right: T | BasicExpression<T> | undefined
5758
): BasicExpression<boolean>
5859
export function lt<T>(left: Aggregate<T>, right: any): BasicExpression<boolean>
5960
export function lt(left: any, right: any): BasicExpression<boolean> {
6061
return new Func(`lt`, [toExpression(left), toExpression(right)])
6162
}
6263

6364
export function lte<T>(
64-
left: RefProxy<T>,
65-
right: T | RefProxy<T> | BasicExpression<T>
65+
left: RefProxy<T> | undefined,
66+
right: T | RefProxy<T> | BasicExpression<T> | undefined
6667
): BasicExpression<boolean>
6768
export function lte<T extends string | number>(
68-
left: T | BasicExpression<T>,
69-
right: T | BasicExpression<T>
69+
left: T | BasicExpression<T> | undefined,
70+
right: T | BasicExpression<T> | undefined
7071
): BasicExpression<boolean>
7172
export function lte<T>(left: Aggregate<T>, right: any): BasicExpression<boolean>
7273
export function lte(left: any, right: any): BasicExpression<boolean> {
@@ -211,6 +212,9 @@ export function upper(
211212
| RefProxy<string>
212213
| RefProxy<string | undefined>
213214
| RefProxy<string | null>
215+
| Ref<string>
216+
| Ref<string | undefined>
217+
| Ref<string | null>
214218
| string
215219
| string | undefined
216220
| string | null

packages/db/src/query/builder/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -795,4 +795,4 @@ export type ExtractContext<T> =
795795
: never
796796

797797
// Export the types from types.ts for convenience
798-
export type { Context, Source, GetResult } from "./types.js"
798+
export type { Context, Source, GetResult, Ref } from "./types.js"

packages/db/src/query/builder/types.ts

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -58,10 +58,11 @@ type SelectValue =
5858
| Aggregate
5959
| RefProxy
6060
| RefProxyFor<any>
61+
| Ref<any>
6162
| undefined
6263
| { [key: string]: SelectValue }
6364
| PrecomputeRefStructure<any>
64-
| Array<RefProxy<any>>
65+
| Array<Ref<any>>
6566

6667
export type SelectObject<
6768
T extends Record<string, SelectValue> = Record<string, SelectValue>,
@@ -158,14 +159,14 @@ type NonUndefined<T> = T extends undefined ? never : T
158159
// Only leaf values are wrapped in RefProxy, intermediate objects remain plain
159160
type PrecomputeRefStructure<T extends Record<string, any>> = {
160161
[K in keyof T]: IsExactlyUndefined<T[K]> extends true
161-
? RefProxy<T[K]>
162+
? Ref<T[K]>
162163
: IsOptional<T[K]> extends true
163164
? NonUndefined<T[K]> extends Record<string, any>
164165
? PrecomputeRefStructure<NonUndefined<T[K]>> | undefined
165-
: RefProxy<NonUndefined<T[K]>> | undefined
166+
: Ref<NonUndefined<T[K]>> | undefined
166167
: T[K] extends Record<string, any>
167168
? PrecomputeRefStructure<T[K]>
168-
: RefProxy<T[K]>
169+
: Ref<T[K]>
169170
}
170171

171172
// Helper type for backward compatibility and reusable query callbacks
@@ -180,10 +181,6 @@ export type RefProxyFor<T> = IsExactlyUndefined<T> extends true
180181
? PrecomputeRefStructure<T>
181182
: RefProxy<T>
182183

183-
// This is the public type that is exported from the query builder
184-
// and is used when constructing reusable query callbacks.
185-
export type Ref<T> = RefProxyFor<T>
186-
187184
type OmitRefProxy<T> = Omit<T, `__refProxy` | `__path` | `__type`>
188185

189186
// The core RefProxy interface with recursive structure
@@ -204,6 +201,14 @@ export type RefProxy<T = any> = {
204201
}
205202
: {})
206203

204+
// Clean branded type for better IDE display
205+
// This creates a distinct type that displays as Ref<T> but is structurally compatible
206+
export type Ref<T> = {
207+
readonly __refProxy: true
208+
readonly __path: Array<string>
209+
readonly __type: T
210+
}
211+
207212
// Helper type to apply join optionality immediately when merging contexts
208213
export type MergeContextWithJoinType<
209214
TContext extends Context,

packages/db/tests/query/builder/buildQuery.test.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,11 +63,11 @@ describe(`buildQuery function`, () => {
6363
.join(
6464
{ departments: departmentsCollection },
6565
({ employees, departments }) =>
66-
eq(employees.department_id, departments.id)
66+
eq(employees.department_id, departments?.id)
6767
)
6868
.select(({ employees, departments }) => ({
6969
employee_name: employees.name,
70-
department_name: departments.name,
70+
department_name: departments?.name,
7171
}))
7272
)
7373

@@ -122,7 +122,7 @@ describe(`buildQuery function`, () => {
122122
q
123123
.from({ comment: commentsCollection })
124124
.join({ user: usersCollection }, ({ comment, user }) =>
125-
eq(comment.user_id, user.id)
125+
eq(comment.user_id, user?.id)
126126
)
127127
.where(({ comment }) => or(eq(comment.id, 1), eq(comment.id, 2)))
128128
.orderBy(({ comment }) => comment.date, `desc`)

packages/db/tests/query/builder/join.test.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -101,8 +101,8 @@ describe(`QueryBuilder.join`, () => {
101101
.select(({ employees, departments }) => ({
102102
id: employees.id,
103103
name: employees.name,
104-
department_name: departments.name,
105-
department_budget: departments.budget,
104+
department_name: departments?.name,
105+
department_budget: departments?.budget,
106106
}))
107107

108108
const builtQuery = getQueryIR(query)
@@ -122,7 +122,7 @@ describe(`QueryBuilder.join`, () => {
122122
({ employees, departments }) =>
123123
eq(employees.department_id, departments.id)
124124
)
125-
.where(({ departments }) => gt(departments.budget, 1000000))
125+
.where(({ departments }) => gt(departments?.budget, 1000000))
126126

127127
const builtQuery = getQueryIR(query)
128128
expect(builtQuery.where).toBeDefined()
@@ -160,13 +160,13 @@ describe(`QueryBuilder.join`, () => {
160160
eq(employees.department_id, departments.id)
161161
)
162162
.where(({ employees, departments }) =>
163-
and(gt(employees.salary, 50000), gt(departments.budget, 1000000))
163+
and(gt(employees.salary, 50000), gt(departments?.budget, 1000000))
164164
)
165165
.select(({ employees, departments }) => ({
166166
id: employees.id,
167167
name: employees.name,
168-
department_name: departments.name,
169-
dept_location: departments.location,
168+
department_name: departments?.name,
169+
dept_location: departments?.location,
170170
}))
171171

172172
const builtQuery = getQueryIR(query)

0 commit comments

Comments
 (0)