Skip to content
Merged
5 changes: 5 additions & 0 deletions .changeset/sharp-donuts-push.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@powersync/common': minor
---

Merge `Table` and `TableV2` but kept `TableV2` to avoid making this a breaking change.
4 changes: 3 additions & 1 deletion .prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,6 @@
**/android/**
**/assets/**
**/bin/**
**/ios/**
**/ios/**

pnpm-lock.yaml
6 changes: 3 additions & 3 deletions demos/example-vite/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ class DummyConnector {
async uploadData(database) {}
}

export const AppSchema = new Schema([
new Table({ name: 'customers', columns: [new Column({ name: 'name', type: ColumnType.TEXT })] })
]);
const customers = new Table({ name: column.text })

export const AppSchema = new Schema(customers);

let PowerSync;

Expand Down
8 changes: 4 additions & 4 deletions demos/example-webpack/src/index.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Column, ColumnType, Schema, Table, PowerSyncDatabase } from '@powersync/web';
import { Column, ColumnType, Schema, Table, PowerSyncDatabase, column } from '@powersync/web';
import Logger from 'js-logger';

Logger.useDefaults();
Expand All @@ -19,9 +19,9 @@ class DummyConnector {
async uploadData(database) {}
}

export const AppSchema = new Schema([
new Table({ name: 'customers', columns: [new Column({ name: 'name', type: ColumnType.TEXT })] })
]);
const customers = new Table({ name: column.text })

export const AppSchema = new Schema(customers);

let PowerSync;

Expand Down
2 changes: 1 addition & 1 deletion demos/react-multi-client/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,4 @@ yarn-error.log*
.vercel

# typescript
*.tsbuildinfo
*.tsbuildinfo
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { column, Schema, TableV2 } from '@powersync/web';
import { column, Schema, Table } from '@powersync/web';

export const LISTS_TABLE = 'lists';
export const TODOS_TABLE = 'todos';

const todos = new TableV2(
const todos = new Table(
{
list_id: column.text,
created_at: column.text,
Expand All @@ -16,7 +16,7 @@ const todos = new TableV2(
{ indexes: { list: ['list_id'] } }
);

const lists = new TableV2({
const lists = new Table({
created_at: column.text,
name: column.text,
owner_id: column.text
Expand Down
30 changes: 0 additions & 30 deletions packages/common/src/db/Column.ts

This file was deleted.

60 changes: 60 additions & 0 deletions packages/common/src/db/schema/Column.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
// https://www.sqlite.org/lang_expr.html#castexpr
export enum ColumnType {
TEXT = 'TEXT',
INTEGER = 'INTEGER',
REAL = 'REAL'
}

export interface ColumnOptions {
name: string;
type?: ColumnType;
}

export type BaseColumnType<T extends number | string | null> = {
type: ColumnType;
};

export type ColumnsType = Record<string, BaseColumnType<any>>;

export type ExtractColumnValueType<T extends BaseColumnType<any>> = T extends BaseColumnType<infer R> ? R : unknown;

const text: BaseColumnType<string | null> = {
type: ColumnType.TEXT
};

const integer: BaseColumnType<number | null> = {
type: ColumnType.INTEGER
};

const real: BaseColumnType<number | null> = {
type: ColumnType.REAL
};

// There is maximum of 127 arguments for any function in SQLite. Currently we use json_object which uses 1 arg per key (column name)
// and one per value, which limits it to 63 arguments.
export const MAX_AMOUNT_OF_COLUMNS = 63;

export const column = {
text,
integer,
real
};

export class Column {
constructor(protected options: ColumnOptions) {}

get name() {
return this.options.name;
}

get type() {
return this.options.type;
}

toJSON() {
return {
name: this.name,
type: this.type
};
}
}
2 changes: 1 addition & 1 deletion packages/common/src/db/schema/IndexedColumn.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ColumnType } from '../Column';
import { ColumnType } from './Column';
import { Table } from './Table';

export interface IndexColumnOptions {
Expand Down
24 changes: 16 additions & 8 deletions packages/common/src/db/schema/Schema.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { Table as ClassicTable } from './Table';
import { RowType, TableV2 } from './TableV2';
import { RowType, Table } from './Table';

type SchemaType = Record<string, TableV2<any>>;
type SchemaType = Record<string, Table<any>>;

type SchemaTableType<S extends SchemaType> = {
[K in keyof S]: RowType<S[K]>;
Expand All @@ -16,9 +15,9 @@ export class Schema<S extends SchemaType = SchemaType> {
*/
readonly types: SchemaTableType<S>;
readonly props: S;
readonly tables: ClassicTable[];
readonly tables: Table[];

constructor(tables: ClassicTable[] | S) {
constructor(tables: Table[] | S) {
if (Array.isArray(tables)) {
this.tables = tables;
} else {
Expand All @@ -28,20 +27,29 @@ export class Schema<S extends SchemaType = SchemaType> {
}

validate() {
for (const table of this.tables as ClassicTable[]) {
for (const table of this.tables) {
table.validate();
}
}

toJSON() {
return {
tables: (this.tables as ClassicTable[]).map((t) => t.toJSON())
// This is required because "name" field is not present in TableV2
tables: this.tables.map((t) => t.toJSON())
};
}

private convertToClassicTables(props: S) {
return Object.entries(props).map(([name, table]) => {
return ClassicTable.createTable(name, table);
const convertedTable = new Table({
name,
columns: table.columns,
indexes: table.indexes,
localOnly: table.localOnly,
insertOnly: table.insertOnly,
viewName: table.viewNameOverride || name
});
return convertedTable;
});
}
}
Loading
Loading