-
Notifications
You must be signed in to change notification settings - Fork 58
feat: Converting Drizzle tables to Powersync tables #408
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 12 commits
Commits
Show all changes
19 commits
Select commit
Hold shift + click to select a range
b153571
Added PowerSyncSQLiteDatabase type as part of exported members.
Chriztiaan 01039ba
Added mechanism to map Drizzle table to a PowerSync table.
Chriztiaan 34e8bec
Transforming index options from Drizzle tables.
Chriztiaan dadddfd
Merge branch 'main' into feat/drizzle-schema
Chriztiaan a1a8bd9
Merge branch 'main' into feat/drizzle-schema
Chriztiaan 1e0b18b
Added toPowerSyncSchema()
Chriztiaan 4b7c60f
Added working types to toPowerSyncTable and toPowerSyncSchema.
Chriztiaan 95fb832
Updated Readme.
Chriztiaan 8c84bbf
Added unit tests.
Chriztiaan 2cfd592
Added changeset.
Chriztiaan b3882ac
Update readme for slightly improved flow
benitav 31759b7
Tweak
benitav 0461feb
Merge branch 'main' into feat/drizzle-schema
Chriztiaan e4eddd3
Removed `@powersync/common` dependency.
Chriztiaan 102f7ba
Merge branch 'feat/drizzle-schema' of github.com:powersync-ja/powersy…
Chriztiaan 1a1dca7
Updated lock file.
Chriztiaan e312705
Introduced DrizzleAppSchema constructor.
Chriztiaan 3238948
Dropped `toPowerSyncSchema` in favour of `DrizzleAppSchema` constructor.
Chriztiaan 3f4f471
Merge branch 'main' into feat/drizzle-schema
Chriztiaan File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
'@powersync/drizzle-driver': minor | ||
--- | ||
|
||
Added `toPowersyncTable` and `toPowerSyncSchema` helper functions to convert a Drizzle schema into a PowerSync app schema |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,26 @@ | ||
import { wrapPowerSyncWithDrizzle, type PowerSyncSQLiteDatabase } from './sqlite/db'; | ||
import { toCompilableQuery } from './utils/compilableQuery'; | ||
import { | ||
toPowerSyncSchema, | ||
toPowerSyncTable, | ||
type DrizzleTablePowerSyncOptions, | ||
type DrizzleTableWithPowerSyncOptions, | ||
type Expand, | ||
type ExtractPowerSyncColumns, | ||
type TableName, | ||
type TablesFromSchemaEntries | ||
} from './utils/schema'; | ||
|
||
export { wrapPowerSyncWithDrizzle, toCompilableQuery, PowerSyncSQLiteDatabase }; | ||
export { | ||
DrizzleTablePowerSyncOptions, | ||
DrizzleTableWithPowerSyncOptions, | ||
Expand, | ||
ExtractPowerSyncColumns, | ||
PowerSyncSQLiteDatabase, | ||
TableName, | ||
TablesFromSchemaEntries, | ||
toCompilableQuery, | ||
toPowerSyncSchema, | ||
toPowerSyncTable, | ||
wrapPowerSyncWithDrizzle | ||
}; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
import { column, IndexShorthand, Schema, Table, type BaseColumnType, type TableV2Options } from '@powersync/common'; | ||
import { InferSelectModel, isTable, Relations } from 'drizzle-orm'; | ||
import { | ||
getTableConfig, | ||
SQLiteInteger, | ||
SQLiteReal, | ||
SQLiteText, | ||
type SQLiteTableWithColumns, | ||
type TableConfig | ||
} from 'drizzle-orm/sqlite-core'; | ||
|
||
export type ExtractPowerSyncColumns<T extends SQLiteTableWithColumns<any>> = { | ||
[K in keyof InferSelectModel<T> as K extends 'id' ? never : K]: BaseColumnType<InferSelectModel<T>[K]>; | ||
}; | ||
|
||
export type Expand<T> = T extends infer O ? { [K in keyof O]: O[K] } : never; | ||
|
||
export function toPowerSyncTable<T extends SQLiteTableWithColumns<any>>( | ||
table: T, | ||
options?: Omit<TableV2Options, 'indexes'> | ||
): Table<Expand<ExtractPowerSyncColumns<T>>> { | ||
const { columns: drizzleColumns, indexes: drizzleIndexes } = getTableConfig(table); | ||
|
||
const columns: { [key: string]: BaseColumnType<number | string | null> } = {}; | ||
for (const drizzleColumn of drizzleColumns) { | ||
// Skip the id column | ||
if (drizzleColumn.name === 'id') { | ||
continue; | ||
} | ||
|
||
let mappedType: BaseColumnType<number | string | null>; | ||
switch (drizzleColumn.columnType) { | ||
case SQLiteText.name: | ||
mappedType = column.text; | ||
break; | ||
case SQLiteInteger.name: | ||
mappedType = column.integer; | ||
break; | ||
case SQLiteReal.name: | ||
mappedType = column.real; | ||
break; | ||
default: | ||
throw new Error(`Unsupported column type: ${drizzleColumn.columnType}`); | ||
} | ||
columns[drizzleColumn.name] = mappedType; | ||
} | ||
const indexes: IndexShorthand = {}; | ||
|
||
for (const index of drizzleIndexes) { | ||
index.config; | ||
if (!index.config.columns.length) { | ||
continue; | ||
} | ||
const columns: string[] = []; | ||
for (const indexColumn of index.config.columns) { | ||
columns.push((indexColumn as { name: string }).name); | ||
} | ||
|
||
indexes[index.config.name] = columns; | ||
} | ||
return new Table(columns, { ...options, indexes }) as Table<Expand<ExtractPowerSyncColumns<T>>>; | ||
} | ||
|
||
export type DrizzleTablePowerSyncOptions = Omit<TableV2Options, 'indexes'>; | ||
|
||
export type DrizzleTableWithPowerSyncOptions = { | ||
tableDefinition: SQLiteTableWithColumns<any>; | ||
options?: DrizzleTablePowerSyncOptions | undefined; | ||
}; | ||
|
||
export type TableName<T> = | ||
T extends SQLiteTableWithColumns<any> | ||
? T['_']['name'] | ||
: T extends DrizzleTableWithPowerSyncOptions | ||
? T['tableDefinition']['_']['name'] | ||
: never; | ||
|
||
export type TablesFromSchemaEntries<T> = { | ||
[K in keyof T as T[K] extends Relations | ||
? never | ||
: T[K] extends SQLiteTableWithColumns<any> | DrizzleTableWithPowerSyncOptions | ||
? TableName<T[K]> | ||
: never]: T[K] extends SQLiteTableWithColumns<any> | ||
? Table<Expand<ExtractPowerSyncColumns<T[K]>>> | ||
: T[K] extends DrizzleTableWithPowerSyncOptions | ||
? Table<Expand<ExtractPowerSyncColumns<T[K]['tableDefinition']>>> | ||
: never; | ||
}; | ||
|
||
export function toPowerSyncSchema< | ||
T extends Record<string, SQLiteTableWithColumns<any> | Relations | DrizzleTableWithPowerSyncOptions> | ||
>(schemaEntries: T): Schema<Expand<TablesFromSchemaEntries<T>>> { | ||
const tables: Record<string, Table> = {}; | ||
for (const schemaEntry of Object.values(schemaEntries)) { | ||
let maybeTable: SQLiteTableWithColumns<any> | Relations | undefined = undefined; | ||
let maybeOptions: DrizzleTablePowerSyncOptions | undefined = undefined; | ||
|
||
if (typeof schemaEntry === 'object' && 'tableDefinition' in schemaEntry) { | ||
const tableWithOptions = schemaEntry as DrizzleTableWithPowerSyncOptions; | ||
maybeTable = tableWithOptions.tableDefinition; | ||
maybeOptions = tableWithOptions.options; | ||
} else { | ||
maybeTable = schemaEntry; | ||
} | ||
|
||
if (isTable(maybeTable)) { | ||
const { name } = getTableConfig(maybeTable); | ||
tables[name] = toPowerSyncTable(maybeTable as SQLiteTableWithColumns<TableConfig>, maybeOptions); | ||
} | ||
} | ||
|
||
return new Schema(tables) as Schema<Expand<TablesFromSchemaEntries<T>>>; | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.