Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/olive-guests-bathe.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@tanstack/powersync-db-collection': minor
---

Upgrade PowerSync to version 2.
6 changes: 3 additions & 3 deletions docs/collections/powersync-collection.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ const db = new PowerSyncDatabase({

```ts
import {
AbstractPowerSyncDatabase,
CommonPowerSyncDatabase,
PowerSyncBackendConnector,
PowerSyncCredentials,
} from "@powersync/web"
Expand All @@ -67,11 +67,11 @@ class Connector implements PowerSyncBackendConnector {

/** Upload local changes to the app backend.
*
* Use {@link AbstractPowerSyncDatabase.getCrudBatch} to get a batch of changes to upload.
* Use {@link CommonPowerSyncDatabase.getCrudBatch} to get a batch of changes to upload.
*
* Any thrown errors will result in a retry after the configured wait period (default: 5 seconds).
*/
uploadData: (database: AbstractPowerSyncDatabase) => Promise<void>
uploadData: (database: CommonPowerSyncDatabase) => Promise<void>
}

// Configure the client to connect to a PowerSync service and your backend
Expand Down
6 changes: 3 additions & 3 deletions packages/powersync-db-collection/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,11 @@
"p-defer": "^4.0.1"
},
"peerDependencies": {
"@powersync/common": "^1.41.0"
"@powersync/common": "^2.0.0"
},
"devDependencies": {
"@powersync/common": "1.49.0",
"@powersync/node": "0.18.1",
"@powersync/common": "^2.0.0",
"@powersync/node": "^0.20.0",
"@types/debug": "^4.1.12",
"@vitest/coverage-istanbul": "^3.2.4",
"better-sqlite3": "^12.6.2"
Expand Down
16 changes: 8 additions & 8 deletions packages/powersync-db-collection/src/PowerSyncTransactor.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { sanitizeSQL } from '@powersync/common'
import { sanitizeSQL, LogLevels } from '@powersync/common'
import { LoadSubsetOperationAbortedError } from '@tanstack/db'
import DebugModule from 'debug'
import { PendingOperationStore } from './PendingOperationStore'
import { asPowerSyncRecord, mapOperationToPowerSync } from './helpers'
import type { AbstractPowerSyncDatabase, LockContext } from '@powersync/common'
import type { CommonPowerSyncDatabase, LockContext } from '@powersync/common'
import type { PendingMutation, Transaction } from '@tanstack/db'
import type { PendingOperation } from './PendingOperationStore'
import type {
Expand All @@ -14,7 +14,7 @@ import type {
const debug = DebugModule.debug(`ts/db:powersync`)

export type TransactorOptions = {
database: AbstractPowerSyncDatabase
database: CommonPowerSyncDatabase
}

/**
Expand Down Expand Up @@ -53,7 +53,7 @@ export type TransactorOptions = {
* @returns A promise that resolves when the mutations have been persisted to PowerSync
*/
export class PowerSyncTransactor {
database: AbstractPowerSyncDatabase
database: CommonPowerSyncDatabase
pendingOperationStore: PendingOperationStore

constructor(options: TransactorOptions) {
Expand Down Expand Up @@ -344,10 +344,10 @@ export class PowerSyncTransactor {
// If it's not supported, we don't store metadata.
if (typeof mutation.metadata != `undefined`) {
// Log a warning if metadata is provided but not tracked.
this.database.logger.warn(
`Metadata provided for collection ${mutation.collection.id} but the PowerSync table does not track metadata. The PowerSync table should be configured with trackMetadata: true.`,
mutation.metadata,
)
this.database.logger.log({
level: LogLevels.warn,
message: `Metadata provided for collection ${mutation.collection.id} but the PowerSync table does not track metadata. The PowerSync table should be configured with trackMetadata: true.`,
})
}
return null
} else if (typeof mutation.metadata == `undefined`) {
Expand Down
8 changes: 6 additions & 2 deletions packages/powersync-db-collection/src/definitions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -202,9 +202,13 @@ export type OnDemandSyncHooks = {

export type BasePowerSyncCollectionConfig<
TTable extends Table = Table,
TSchema extends StandardSchemaV1 = never,
TSchema extends StandardSchemaV1<any> = never,
> = Omit<
BaseCollectionConfig<ExtractedTable<TTable>, string, TSchema>,
BaseCollectionConfig<
InferPowerSyncOutputType<TTable, TSchema>,
string,
TSchema
>,
`onInsert` | `onUpdate` | `onDelete` | `getKey` | `syncMode`
> & {
/** The PowerSync schema Table definition */
Expand Down
45 changes: 18 additions & 27 deletions packages/powersync-db-collection/src/helpers.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
import { DiffTriggerOperation } from '@powersync/common'
import type {
BaseColumnType,
ExtractColumnValueType,
Table,
} from '@powersync/common'
import type { ExtractColumnValueType, RowType, Table } from '@powersync/common'

/**
* All PowerSync table records include a UUID `id` column.
Expand All @@ -28,11 +24,11 @@ type OptionalIfUndefined<T> = {
/**
* Provides the base column types for a table. This excludes the `id` column.
*/
export type ExtractedTableColumns<TTable extends Table> = {
[K in keyof TTable[`columnMap`]]: ExtractColumnValueType<
TTable[`columnMap`][K]
>
}
export type ExtractedTableColumns<TTable extends Table<any>> = Omit<
RowType<TTable>,
'id'
>

/**
* Utility type that extracts the typed structure of a table based on its column definitions.
* Maps each column to its corresponding TypeScript type using ExtractColumnValueType.
Expand All @@ -48,25 +44,25 @@ export type ExtractedTableColumns<TTable extends Table> = {
* // Results in: { id: string, name: string | null, age: number | null }
* ```
*/
export type ExtractedTable<TTable extends Table> =
ExtractedTableColumns<TTable> & {
id: string
}
export type ExtractedTable<TTable extends Table> = RowType<TTable>

export type OptionalExtractedTable<TTable extends Table> = OptionalIfUndefined<{
[K in keyof TTable[`columnMap`]]: WithUndefinedIfNull<
ExtractColumnValueType<TTable[`columnMap`][K]>
>
}> & {
id: string
}
export type OptionalExtractedTable<TTable extends Table> =
TTable extends Table<infer Columns>
? OptionalIfUndefined<{
[K in keyof Columns]: WithUndefinedIfNull<
ExtractColumnValueType<Columns[K]>
>
}> & {
id: string
}
: never

/**
* Maps the schema of TTable to a type which
* requires the keys be equal, but the values can have any value type.
*/
export type AnyTableColumnType<TTable extends Table> = {
[K in keyof TTable[`columnMap`]]: any
[K in keyof ExtractedTableColumns<TTable>]: any
} & { id: string }
Comment on lines 60 to 66

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

πŸ“ Maintainability & Code Quality | 🟑 Minor | ⚑ Quick win

Avoid using any types; prefer unknown.

As per coding guidelines: "Avoid using any types; use unknown instead when the type is truly unknown". Using unknown for the column values improves type safety by requiring type guards before operations on the values.

πŸ’» Proposed fix
 export type AnyTableColumnType<TTable extends Table> = {
-  [K in keyof ExtractedTableColumns<TTable>]: any
+  [K in keyof ExtractedTableColumns<TTable>]: unknown
 } & { id: string }
πŸ“ Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
/**
* Maps the schema of TTable to a type which
* requires the keys be equal, but the values can have any value type.
*/
export type AnyTableColumnType<TTable extends Table> = {
[K in keyof TTable[`columnMap`]]: any
[K in keyof ExtractedTableColumns<TTable>]: any
} & { id: string }
/**
* Maps the schema of TTable to a type which
* requires the keys be equal, but the values can have any value type.
*/
export type AnyTableColumnType<TTable extends Table> = {
[K in keyof ExtractedTableColumns<TTable>]: unknown
} & { id: string }
πŸ€– Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/powersync-db-collection/src/helpers.ts` around lines 65 - 71, The
AnyTableColumnType type uses any for column values; replace it with unknown in
the mapped type while preserving the existing keys and id: string requirement.

Source: Coding guidelines


export function asPowerSyncRecord(record: any): PowerSyncRecord {
Expand All @@ -76,11 +72,6 @@ export function asPowerSyncRecord(record: any): PowerSyncRecord {
return record as PowerSyncRecord
}

// Helper type to ensure the keys of TOutput match the Table columns
export type MapBaseColumnType<TOutput> = {
[Key in keyof TOutput]: BaseColumnType<any>
}

/**
* Maps {@link DiffTriggerOperation} to TanstackDB operations
*/
Expand Down
Loading