Skip to content

Commit 7b15982

Browse files
committed
fix: resolve TS2322 when passing SQLiteDatabase to createExpoSQLitePersistence
1 parent be656be commit 7b15982

6 files changed

Lines changed: 131 additions & 106 deletions

File tree

packages/expo-db-sqlite-persistence/e2e/expo-runtime-app/App.tsx

Lines changed: 14 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, { useEffect, useMemo, useState } from 'react'
1+
import { useEffect, useMemo, useState } from 'react'
22
import { ScrollView, Text, View } from 'react-native'
33
import * as SQLite from 'expo-sqlite'
44
import { createCollection } from '@tanstack/db'
@@ -14,20 +14,12 @@ import type {
1414
} from '../runtime-protocol'
1515

1616
type DatabaseHandle = Awaited<ReturnType<typeof SQLite.openDatabaseAsync>>
17-
type TransactionHandleLike = {
18-
execAsync: (sql: string) => Promise<void>
19-
getAllAsync: (
20-
sql: string,
21-
params?: ReadonlyArray<unknown> | Record<string, unknown>,
22-
) => Promise<ReadonlyArray<unknown>>
23-
runAsync: (
24-
sql: string,
25-
params?: ReadonlyArray<unknown> | Record<string, unknown>,
26-
) => Promise<unknown>
27-
}
17+
type TransactionHandle = Parameters<
18+
Parameters<DatabaseHandle['withExclusiveTransactionAsync']>[0]
19+
>[0]
2820

2921
type ActiveTransaction = {
30-
transaction: TransactionHandleLike
22+
transaction: TransactionHandle
3123
complete: {
3224
resolve: () => void
3325
reject: (error?: unknown) => void
@@ -63,12 +55,6 @@ async function postJson<TBody extends object>(
6355
}
6456
}
6557

66-
function normalizeSqliteParams(
67-
params?: ReadonlyArray<unknown> | Record<string, unknown>,
68-
): ReadonlyArray<unknown> | Record<string, unknown> | undefined {
69-
return params === undefined ? undefined : params
70-
}
71-
7258
async function closeDatabaseHandle(database: DatabaseHandle): Promise<void> {
7359
const closableDatabase = database as DatabaseHandle & {
7460
closeAsync?: () => Promise<void>
@@ -129,14 +115,7 @@ export default function App() {
129115
): Promise<ExpoRuntimeSmokeTestResult> => {
130116
const database = await SQLite.openDatabaseAsync(databaseName)
131117
const collectionId = `expo-runtime-smoke-${Date.now().toString(36)}`
132-
const persistence = createExpoSQLitePersistence<
133-
{
134-
id: string
135-
title: string
136-
score: number
137-
},
138-
string
139-
>({
118+
const persistence = createExpoSQLitePersistence({
140119
database,
141120
})
142121
const collection = createCollection(
@@ -198,20 +177,18 @@ export default function App() {
198177
command.databaseId,
199178
command.databaseName,
200179
)
201-
const params = normalizeSqliteParams(command.params)
202-
return params === undefined
180+
return command.params === undefined
203181
? database.getAllAsync(command.sql)
204-
: database.getAllAsync(command.sql, params)
182+
: database.getAllAsync(command.sql, command.params)
205183
}
206184
case `db:run`: {
207185
const database = await getDatabase(
208186
command.databaseId,
209187
command.databaseName,
210188
)
211-
const params = normalizeSqliteParams(command.params)
212-
return params === undefined
189+
return command.params === undefined
213190
? database.runAsync(command.sql)
214-
: database.runAsync(command.sql, params)
191+
: database.runAsync(command.sql, command.params)
215192
}
216193
case `db:close`: {
217194
const database = databaseHandles.get(command.databaseId)
@@ -270,20 +247,18 @@ export default function App() {
270247
if (!transaction) {
271248
throw new Error(`Unknown transaction id`)
272249
}
273-
const params = normalizeSqliteParams(command.params)
274-
return params === undefined
250+
return command.params === undefined
275251
? transaction.transaction.getAllAsync(command.sql)
276-
: transaction.transaction.getAllAsync(command.sql, params)
252+
: transaction.transaction.getAllAsync(command.sql, command.params)
277253
}
278254
case `tx:run`: {
279255
const transaction = activeTransactions.get(command.transactionId)
280256
if (!transaction) {
281257
throw new Error(`Unknown transaction id`)
282258
}
283-
const params = normalizeSqliteParams(command.params)
284-
return params === undefined
259+
return command.params === undefined
285260
? transaction.transaction.runAsync(command.sql)
286-
: transaction.transaction.runAsync(command.sql, params)
261+
: transaction.transaction.runAsync(command.sql, command.params)
287262
}
288263
case `tx:commit`: {
289264
const transaction = activeTransactions.get(command.transactionId)

packages/expo-db-sqlite-persistence/e2e/runtime-protocol.ts

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
export type ExpoRuntimeSQLiteBindValue = string | number | boolean | null
2+
export type ExpoRuntimeSQLiteBindParams =
3+
| ReadonlyArray<ExpoRuntimeSQLiteBindValue>
4+
| Record<string, ExpoRuntimeSQLiteBindValue>
5+
16
export type ExpoRuntimeCommand =
27
| {
38
id: string
@@ -12,15 +17,15 @@ export type ExpoRuntimeCommand =
1217
databaseId: string
1318
databaseName: string
1419
sql: string
15-
params?: ReadonlyArray<unknown> | Record<string, unknown>
20+
params?: ExpoRuntimeSQLiteBindParams
1621
}
1722
| {
1823
id: string
1924
type: `db:run`
2025
databaseId: string
2126
databaseName: string
2227
sql: string
23-
params?: ReadonlyArray<unknown> | Record<string, unknown>
28+
params?: ExpoRuntimeSQLiteBindParams
2429
}
2530
| {
2631
id: string
@@ -46,14 +51,14 @@ export type ExpoRuntimeCommand =
4651
type: `tx:getAll`
4752
transactionId: string
4853
sql: string
49-
params?: ReadonlyArray<unknown> | Record<string, unknown>
54+
params?: ExpoRuntimeSQLiteBindParams
5055
}
5156
| {
5257
id: string
5358
type: `tx:run`
5459
transactionId: string
5560
sql: string
56-
params?: ReadonlyArray<unknown> | Record<string, unknown>
61+
params?: ExpoRuntimeSQLiteBindParams
5762
}
5863
| {
5964
id: string

packages/expo-db-sqlite-persistence/src/expo-sqlite-driver.ts

Lines changed: 33 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,29 @@
11
import { InvalidPersistedCollectionConfigError } from '@tanstack/db-sqlite-persistence-core'
22
import type { SQLiteDriver } from '@tanstack/db-sqlite-persistence-core'
3-
4-
export type ExpoSQLiteBindParams =
5-
| ReadonlyArray<unknown>
6-
| Record<string, unknown>
7-
8-
export type ExpoSQLiteRunResult = {
9-
changes: number
10-
lastInsertRowId: number
11-
}
3+
import type {
4+
SQLiteBindParams,
5+
SQLiteBindValue,
6+
SQLiteRunResult,
7+
} from 'expo-sqlite'
128

139
export type ExpoSQLiteQueryable = {
1410
execAsync: (sql: string) => Promise<void>
1511
getAllAsync: <T>(
1612
sql: string,
17-
params?: ExpoSQLiteBindParams,
13+
params?: SQLiteBindParams,
1814
) => Promise<ReadonlyArray<T>>
1915
runAsync: (
2016
sql: string,
21-
params?: ExpoSQLiteBindParams,
22-
) => Promise<ExpoSQLiteRunResult>
17+
params?: SQLiteBindParams,
18+
) => Promise<SQLiteRunResult>
2319
}
2420

2521
export type ExpoSQLiteTransaction = ExpoSQLiteQueryable
2622

2723
export type ExpoSQLiteDatabaseLike = ExpoSQLiteQueryable & {
28-
withExclusiveTransactionAsync: <T>(
29-
task: (transaction: ExpoSQLiteTransaction) => Promise<T>,
30-
) => Promise<T>
24+
withExclusiveTransactionAsync: (
25+
task: (transaction: ExpoSQLiteTransaction) => Promise<void>,
26+
) => Promise<void>
3127
closeAsync?: () => Promise<void>
3228
}
3329

@@ -144,10 +140,12 @@ export class ExpoSQLiteDriver implements SQLiteDriver {
144140
): Promise<T> {
145141
return this.enqueue(async () => {
146142
const database = await this.getDatabase()
147-
return database.withExclusiveTransactionAsync(async (transaction) => {
143+
let result: T | undefined
144+
await database.withExclusiveTransactionAsync(async (transaction) => {
148145
const transactionDriver = this.createTransactionDriver(transaction)
149-
return fn(transactionDriver)
146+
result = await fn(transactionDriver)
150147
})
148+
return result as T
151149
})
152150
}
153151

@@ -225,10 +223,24 @@ export class ExpoSQLiteDriver implements SQLiteDriver {
225223
}
226224
}
227225

228-
function normalizeParams(
229-
params: ReadonlyArray<unknown>,
230-
): ExpoSQLiteBindParams | undefined {
231-
return params.length > 0 ? [...params] : undefined
226+
function normalizeBindValue(value: unknown): SQLiteBindValue {
227+
if (
228+
value === null ||
229+
typeof value === `string` ||
230+
typeof value === `number` ||
231+
typeof value === `boolean` ||
232+
value instanceof Uint8Array
233+
) {
234+
return value
235+
}
236+
237+
throw new TypeError(
238+
`Expo SQLite bind parameters must be strings, numbers, booleans, null, or Uint8Array values`,
239+
)
240+
}
241+
242+
function normalizeParams(params: ReadonlyArray<unknown>): SQLiteBindParams {
243+
return params.map(normalizeBindValue)
232244
}
233245

234246
export function createExpoSQLiteDriver(

packages/expo-db-sqlite-persistence/tests/helpers/expo-emulator-database-factory.ts

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,8 @@ import type {
33
ExpoSQLiteTestDatabase,
44
ExpoSQLiteTestDatabaseFactory,
55
} from './expo-sqlite-test-db'
6-
import type {
7-
ExpoSQLiteBindParams,
8-
ExpoSQLiteTransaction,
9-
} from '../../src/expo-sqlite-driver'
6+
import type { SQLiteBindParams } from 'expo-sqlite'
7+
import type { ExpoSQLiteTransaction } from '../../src/expo-sqlite-driver'
108

119
function resolvePlatform(): `ios` | `android` {
1210
const platform = process.env.TANSTACK_DB_EXPO_RUNTIME_PLATFORM?.trim()
@@ -46,13 +44,13 @@ export function createMobileSQLiteTestDatabaseFactory(): ExpoSQLiteTestDatabaseF
4644
execAsync: async (sql: string) => {
4745
await (await getDatabase()).execAsync(sql)
4846
},
49-
getAllAsync: async <T>(sql: string, params?: ExpoSQLiteBindParams) =>
47+
getAllAsync: async <T>(sql: string, params?: SQLiteBindParams) =>
5048
(await getDatabase()).getAllAsync<T>(sql, params),
51-
runAsync: async (sql: string, params?: ExpoSQLiteBindParams) =>
49+
runAsync: async (sql: string, params?: SQLiteBindParams) =>
5250
(await getDatabase()).runAsync(sql, params),
53-
withExclusiveTransactionAsync: async <T>(
54-
task: (transaction: ExpoSQLiteTransaction) => Promise<T>,
55-
): Promise<T> =>
51+
withExclusiveTransactionAsync: async (
52+
task: (transaction: ExpoSQLiteTransaction) => Promise<void>,
53+
): Promise<void> =>
5654
(await getDatabase()).withExclusiveTransactionAsync(task),
5755
closeAsync: async () => {
5856
if (!databasePromise) {

0 commit comments

Comments
 (0)