Skip to content

Commit 3b26333

Browse files
committed
checkpoint
1 parent e96bafd commit 3b26333

File tree

5 files changed

+149
-145
lines changed

5 files changed

+149
-145
lines changed

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

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,26 @@ type StringFunctionReturnType<T> = ExtractType<T> extends infer U
3535
: BasicExpression<string | undefined | null>
3636

3737
// Helper type to determine numeric function return type based on input nullability
38+
// This handles string, array, and number inputs for functions like length()
3839
type NumericFunctionReturnType<T> = ExtractType<T> extends infer U
39-
? U extends number | undefined | null
40-
? BasicExpression<U>
40+
? U extends string
41+
? BasicExpression<number>
42+
: U extends string | undefined
43+
? BasicExpression<number | undefined>
44+
: U extends string | null
45+
? BasicExpression<number | null>
46+
: U extends string | undefined | null
47+
? BasicExpression<number | undefined | null>
48+
: U extends Array<any>
49+
? BasicExpression<number>
50+
: U extends Array<any> | undefined
51+
? BasicExpression<number | undefined>
52+
: U extends Array<any> | null
53+
? BasicExpression<number | null>
54+
: U extends Array<any> | undefined | null
55+
? BasicExpression<number | undefined | null>
56+
: U extends number | undefined | null
57+
? BasicExpression<U>
4158
: U extends number
4259
? BasicExpression<number>
4360
: BasicExpression<number | undefined | null>

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

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,9 @@ type SelectValue =
6363
| { [key: string]: SelectValue }
6464
| PrecomputeRefStructure<any>
6565
| Array<Ref<any>>
66+
| true // For __refProxy property in spreads
67+
| Array<string> // For __path property in spreads
68+
| any // For __type property in spreads
6669

6770
export type SelectObject<
6871
T extends Record<string, SelectValue> = Record<string, SelectValue>,
@@ -159,7 +162,7 @@ type NonUndefined<T> = T extends undefined ? never : T
159162
// This transforms { bio: string, contact: { email: string } } into
160163
// { bio: Ref<string>, contact: { email: Ref<string> } }
161164
// Only leaf values are wrapped in RefProxy, intermediate objects remain plain
162-
type PrecomputeRefStructure<T extends Record<string, any>> = {
165+
export type PrecomputeRefStructure<T extends Record<string, any>> = {
163166
[K in keyof T]: IsExactlyUndefined<T[K]> extends true
164167
? Ref<T[K]>
165168
: IsOptional<T[K]> extends true
@@ -209,6 +212,21 @@ export type RefProxy<T = any> = {
209212
}
210213
: {})
211214

215+
// Helper type to extract only the user-facing properties for spreading
216+
export type SpreadableRefProxy<T> = T extends Record<string, any>
217+
? {
218+
[K in keyof T]: IsExactlyUndefined<T[K]> extends true
219+
? Ref<T[K]>
220+
: IsOptional<T[K]> extends true
221+
? NonUndefined<T[K]> extends Record<string, any>
222+
? RefProxy<NonUndefined<T[K]>> | undefined
223+
: Ref<NonUndefined<T[K]>> | undefined
224+
: T[K] extends Record<string, any>
225+
? RefProxy<T[K]>
226+
: Ref<T[K]>
227+
}
228+
: {}
229+
212230
// Clean branded type for better IDE display
213231
// This creates a distinct type that displays as Ref<T> but is structurally compatible
214232
export type Ref<T> = {

packages/db/tests/query/basic.test.ts

Lines changed: 23 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import {
44
eq,
55
gt,
66
upper,
7+
concat,
78
} from "../../src/query/index.js"
89
import { createCollection } from "../../src/collection.js"
910
import { mockSyncCollectionOptions } from "../utls.js"
@@ -786,12 +787,12 @@ function createBasicTests(autoIndex: `off` | `eager`) {
786787
q
787788
.from({ user: usersCollection })
788789
.where(({ user }) =>
789-
eq(user.profile.bio, `Software engineer with 5 years experience`)
790+
eq(user.profile?.bio, `Software engineer with 5 years experience`)
790791
)
791792
.select(({ user }) => ({
792793
id: user.id,
793794
name: user.name,
794-
bio: user.profile.bio,
795+
bio: user.profile?.bio,
795796
})),
796797
})
797798

@@ -808,11 +809,11 @@ function createBasicTests(autoIndex: `off` | `eager`) {
808809
query: (q) =>
809810
q
810811
.from({ user: usersCollection })
811-
.where(({ user }) => eq(user.profile.preferences.theme, `dark`))
812+
.where(({ user }) => eq(user.profile?.preferences.theme, `dark`))
812813
.select(({ user }) => ({
813814
id: user.id,
814815
name: user.name,
815-
theme: user.profile.preferences.theme,
816+
theme: user.profile?.preferences.theme,
816817
})),
817818
})
818819

@@ -831,9 +832,9 @@ function createBasicTests(autoIndex: `off` | `eager`) {
831832
q.from({ user: usersCollection }).select(({ user }) => ({
832833
id: user.id,
833834
name: user.name,
834-
preferences: user.profile.preferences,
835-
city: user.address.city,
836-
coordinates: user.address.coordinates,
835+
preferences: user.profile?.preferences,
836+
city: user.address?.city,
837+
coordinates: user.address?.coordinates,
837838
})),
838839
})
839840

@@ -899,8 +900,8 @@ function createBasicTests(autoIndex: `off` | `eager`) {
899900
q.from({ user: usersCollection }).select(({ user }) => ({
900901
id: user.id,
901902
name: user.name,
902-
theme: user.profile.preferences.theme,
903-
notifications: user.profile.preferences.notifications,
903+
theme: user.profile?.preferences.theme,
904+
notifications: user.profile?.preferences.notifications,
904905
})),
905906
})
906907

@@ -991,10 +992,10 @@ function createBasicTests(autoIndex: `off` | `eager`) {
991992
q.from({ user: usersCollection }).select(({ user }) => ({
992993
id: user.id,
993994
name: user.name,
994-
street: user.address.street,
995-
city: user.address.city,
996-
country: user.address.country,
997-
coordinates: user.address.coordinates,
995+
street: user.address?.street,
996+
city: user.address?.city,
997+
country: user.address?.country,
998+
coordinates: user.address?.coordinates,
998999
})),
9991000
})
10001001

@@ -1021,12 +1022,12 @@ function createBasicTests(autoIndex: `off` | `eager`) {
10211022
query: (q) =>
10221023
q
10231024
.from({ user: usersCollection })
1024-
.where(({ user }) => eq(user.address.city, `New York`))
1025+
.where(({ user }) => eq(user.address?.city, `New York`))
10251026
.select(({ user }) => ({
10261027
id: user.id,
10271028
name: user.name,
1028-
lat: user.address.coordinates.lat,
1029-
lng: user.address.coordinates.lng,
1029+
lat: user.address?.coordinates.lat,
1030+
lng: user.address?.coordinates.lng,
10301031
})),
10311032
})
10321033

@@ -1044,11 +1045,11 @@ function createBasicTests(autoIndex: `off` | `eager`) {
10441045
query: (q) =>
10451046
q
10461047
.from({ user: usersCollection })
1047-
.where(({ user }) => gt(user.address.coordinates.lat, 38))
1048+
.where(({ user }) => gt(user.address?.coordinates.lat, 38))
10481049
.select(({ user }) => ({
10491050
id: user.id,
10501051
name: user.name,
1051-
city: user.address.city,
1052+
city: user.address?.city,
10521053
})),
10531054
})
10541055

@@ -1067,10 +1068,10 @@ function createBasicTests(autoIndex: `off` | `eager`) {
10671068
q.from({ user: usersCollection }).select(({ user }) => ({
10681069
id: user.id,
10691070
name: user.name,
1070-
city: user.address.city,
1071-
country: user.address.country,
1072-
hasNotifications: user.profile.preferences.notifications,
1073-
profileSummary: concat(upper(user.name), ` - `, user.profile.bio),
1071+
city: user.address?.city,
1072+
country: user.address?.country,
1073+
hasNotifications: user.profile?.preferences.notifications,
1074+
profileSummary: concat(upper(user.name), ` - `, user.profile?.bio),
10741075
})),
10751076
})
10761077

0 commit comments

Comments
 (0)