powersync-ja / powersync-js

SDK that enables local-first and real-time reactive apps with embedded SQLite for JavaScript clients, including React Native and Web
https://www.powersync.com
Apache License 2.0
307 stars 22 forks source link

`@powersync/web` and `@powersync/react-native` have different `PowerSyncDatabase` constructors #298

Closed guillempuche closed 2 months ago

guillempuche commented 2 months ago

PROBLEM

I'm getting this error This expression is not constructable. Each member of the union type 'typeof PowerSyncDatabase | typeof PowerSyncDatabase' has construct signatures, but none of those signatures are compatible with each other.ts(2351) when calling the constructor new PowerSyncDatabase(...)

Why PowerSyncDatabase of web and React Native have different constructors?

CONTEXT

Versions: @powersync/react-native v1.12.0, @powersync/web v1.6.0

I'm conditionally importing web or react native, below is the code.

// repositories/sqlite/src/powersync_db.ts

import type { PowerSyncDatabase as ReactNativePowerSyncDatabase } from '@powersync/react-native'
import type { PowerSyncDatabase as WebPowerSyncDatabase } from '@powersync/web'
import { Context, Effect, Layer } from 'effect'

export class PowerSyncDb extends Context.Tag('PowerSyncDb')<
    PowerSyncDb,
    typeof WebPowerSyncDatabase | typeof ReactNativePowerSyncDatabase
>() {
    static readonly Web = Layer.effect(
        this,
        Effect.promise(async () => {
            const { PowerSyncDatabase } = await import('@powersync/web')
            return PowerSyncDatabase
        }),
    )

    static readonly ReactNative = Layer.effect(
        this,
        Effect.promise(async () => {
            const { PowerSyncDatabase } = await import('@powersync/react-native')
            return PowerSyncDatabase
        }),
    )
}

// repositories/sqlite/src/powersync_client.ts

import { Config, Context, Effect, Layer } from 'effect'

import {
    Author,
    Collection,
    Creator,
    Editor,
    Platform,
    Profile,
    Quote,
} from '@xiroi/library-domain'
import { toPowerSyncSchema } from '@xiroi/shared-utils-powersync'
import { PowerSyncDb } from './powersync_db'

interface PowerSyncClientConfig {
    readonly dbSqliteName: string
    readonly nodeEnv: string
}

// Convert Library tables to PowerSync schema
export const SqliteSchema = toPowerSyncSchema({
    authors: Author,
    collections: Collection,
    creators: Creator,
    editors: Editor,
    platforms: Platform,
    profiles: Profile,
    quotes: Quote,
})

const make = (config: PowerSyncClientConfig) =>
    Effect.map(
        PowerSyncDb,
        PowerSyncDatabase =>
            new PowerSyncDatabase({ // <-- Here is the compile error
                schema: SqliteSchema,
                database: {
                    dbFilename: `${config.dbSqliteName}.sqlite`,
                    debugMode: config.nodeEnv === 'development',
                },
                flags: {
                    disableSSRWarning: true,
                },
            }),
    )

export class PowerSyncClient extends Context.Tag('PowerSyncClient')<
    PowerSyncClient,
    Effect.Effect.Success<ReturnType<typeof make>>
>() {
    static readonly layer = (config: Config.Config.Wrap<PowerSyncClientConfig>) =>
        Config.unwrap(config).pipe(Effect.flatMap(make), Layer.effect(this))
}
guillempuche commented 2 months ago

The problem was the outdated @powersync/common. Solve updating it "@powersync/common": "^1.16.2" making it the compatible with web and react native dependencies.