@powersync/common 1.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (93) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +6 -0
  3. package/lib/client/AbstractPowerSyncDatabase.d.ts +367 -0
  4. package/lib/client/AbstractPowerSyncDatabase.js +645 -0
  5. package/lib/client/AbstractPowerSyncDatabase.js.map +1 -0
  6. package/lib/client/AbstractPowerSyncOpenFactory.d.ts +29 -0
  7. package/lib/client/AbstractPowerSyncOpenFactory.js +25 -0
  8. package/lib/client/AbstractPowerSyncOpenFactory.js.map +1 -0
  9. package/lib/client/connection/PowerSyncBackendConnector.d.ts +23 -0
  10. package/lib/client/connection/PowerSyncBackendConnector.js +2 -0
  11. package/lib/client/connection/PowerSyncBackendConnector.js.map +1 -0
  12. package/lib/client/connection/PowerSyncCredentials.d.ts +5 -0
  13. package/lib/client/connection/PowerSyncCredentials.js +2 -0
  14. package/lib/client/connection/PowerSyncCredentials.js.map +1 -0
  15. package/lib/client/sync/bucket/BucketStorageAdapter.d.ts +71 -0
  16. package/lib/client/sync/bucket/BucketStorageAdapter.js +8 -0
  17. package/lib/client/sync/bucket/BucketStorageAdapter.js.map +1 -0
  18. package/lib/client/sync/bucket/CrudBatch.d.ts +31 -0
  19. package/lib/client/sync/bucket/CrudBatch.js +26 -0
  20. package/lib/client/sync/bucket/CrudBatch.js.map +1 -0
  21. package/lib/client/sync/bucket/CrudEntry.d.ts +86 -0
  22. package/lib/client/sync/bucket/CrudEntry.js +85 -0
  23. package/lib/client/sync/bucket/CrudEntry.js.map +1 -0
  24. package/lib/client/sync/bucket/CrudTransaction.d.ts +29 -0
  25. package/lib/client/sync/bucket/CrudTransaction.js +25 -0
  26. package/lib/client/sync/bucket/CrudTransaction.js.map +1 -0
  27. package/lib/client/sync/bucket/OpType.d.ts +16 -0
  28. package/lib/client/sync/bucket/OpType.js +23 -0
  29. package/lib/client/sync/bucket/OpType.js.map +1 -0
  30. package/lib/client/sync/bucket/OplogEntry.d.ts +23 -0
  31. package/lib/client/sync/bucket/OplogEntry.js +34 -0
  32. package/lib/client/sync/bucket/OplogEntry.js.map +1 -0
  33. package/lib/client/sync/bucket/SqliteBucketStorage.d.ts +66 -0
  34. package/lib/client/sync/bucket/SqliteBucketStorage.js +299 -0
  35. package/lib/client/sync/bucket/SqliteBucketStorage.js.map +1 -0
  36. package/lib/client/sync/bucket/SyncDataBatch.d.ts +6 -0
  37. package/lib/client/sync/bucket/SyncDataBatch.js +12 -0
  38. package/lib/client/sync/bucket/SyncDataBatch.js.map +1 -0
  39. package/lib/client/sync/bucket/SyncDataBucket.d.ts +40 -0
  40. package/lib/client/sync/bucket/SyncDataBucket.js +41 -0
  41. package/lib/client/sync/bucket/SyncDataBucket.js.map +1 -0
  42. package/lib/client/sync/stream/AbstractRemote.d.ts +25 -0
  43. package/lib/client/sync/stream/AbstractRemote.js +43 -0
  44. package/lib/client/sync/stream/AbstractRemote.js.map +1 -0
  45. package/lib/client/sync/stream/AbstractStreamingSyncImplementation.d.ts +101 -0
  46. package/lib/client/sync/stream/AbstractStreamingSyncImplementation.js +478 -0
  47. package/lib/client/sync/stream/AbstractStreamingSyncImplementation.js.map +1 -0
  48. package/lib/client/sync/stream/streaming-sync-types.d.ts +116 -0
  49. package/lib/client/sync/stream/streaming-sync-types.js +23 -0
  50. package/lib/client/sync/stream/streaming-sync-types.js.map +1 -0
  51. package/lib/db/Column.d.ts +19 -0
  52. package/lib/db/Column.js +26 -0
  53. package/lib/db/Column.js.map +1 -0
  54. package/lib/db/DBAdapter.d.ts +95 -0
  55. package/lib/db/DBAdapter.js +20 -0
  56. package/lib/db/DBAdapter.js.map +1 -0
  57. package/lib/db/crud/SyncStatus.d.ts +38 -0
  58. package/lib/db/crud/SyncStatus.js +58 -0
  59. package/lib/db/crud/SyncStatus.js.map +1 -0
  60. package/lib/db/crud/UploadQueueStatus.d.ts +20 -0
  61. package/lib/db/crud/UploadQueueStatus.js +25 -0
  62. package/lib/db/crud/UploadQueueStatus.js.map +1 -0
  63. package/lib/db/schema/Index.d.ts +22 -0
  64. package/lib/db/schema/Index.js +30 -0
  65. package/lib/db/schema/Index.js.map +1 -0
  66. package/lib/db/schema/IndexedColumn.d.ts +19 -0
  67. package/lib/db/schema/IndexedColumn.js +30 -0
  68. package/lib/db/schema/IndexedColumn.js.map +1 -0
  69. package/lib/db/schema/Schema.d.ts +38 -0
  70. package/lib/db/schema/Schema.js +38 -0
  71. package/lib/db/schema/Schema.js.map +1 -0
  72. package/lib/db/schema/Table.d.ts +51 -0
  73. package/lib/db/schema/Table.js +114 -0
  74. package/lib/db/schema/Table.js.map +1 -0
  75. package/lib/db/schema/TableV2.d.ts +30 -0
  76. package/lib/db/schema/TableV2.js +44 -0
  77. package/lib/db/schema/TableV2.js.map +1 -0
  78. package/lib/index.d.ts +30 -0
  79. package/lib/index.js +31 -0
  80. package/lib/index.js.map +1 -0
  81. package/lib/utils/AbortOperation.d.ts +9 -0
  82. package/lib/utils/AbortOperation.js +19 -0
  83. package/lib/utils/AbortOperation.js.map +1 -0
  84. package/lib/utils/BaseObserver.d.ts +20 -0
  85. package/lib/utils/BaseObserver.js +23 -0
  86. package/lib/utils/BaseObserver.js.map +1 -0
  87. package/lib/utils/mutex.d.ts +7 -0
  88. package/lib/utils/mutex.js +29 -0
  89. package/lib/utils/mutex.js.map +1 -0
  90. package/lib/utils/strings.d.ts +3 -0
  91. package/lib/utils/strings.js +10 -0
  92. package/lib/utils/strings.js.map +1 -0
  93. package/package.json +42 -0
@@ -0,0 +1,26 @@
1
+ // https://www.sqlite.org/lang_expr.html#castexpr
2
+ export var ColumnType;
3
+ (function (ColumnType) {
4
+ ColumnType["TEXT"] = "TEXT";
5
+ ColumnType["INTEGER"] = "INTEGER";
6
+ ColumnType["REAL"] = "REAL";
7
+ })(ColumnType || (ColumnType = {}));
8
+ export class Column {
9
+ options;
10
+ constructor(options) {
11
+ this.options = options;
12
+ }
13
+ get name() {
14
+ return this.options.name;
15
+ }
16
+ get type() {
17
+ return this.options.type;
18
+ }
19
+ toJSON() {
20
+ return {
21
+ name: this.name,
22
+ type: this.type
23
+ };
24
+ }
25
+ }
26
+ //# sourceMappingURL=Column.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Column.js","sourceRoot":"","sources":["../../src/db/Column.ts"],"names":[],"mappings":"AAAA,iDAAiD;AACjD,MAAM,CAAN,IAAY,UAIX;AAJD,WAAY,UAAU;IACpB,2BAAa,CAAA;IACb,iCAAmB,CAAA;IACnB,2BAAa,CAAA;AACf,CAAC,EAJW,UAAU,KAAV,UAAU,QAIrB;AAOD,MAAM,OAAO,MAAM;IACK;IAAtB,YAAsB,OAAsB;QAAtB,YAAO,GAAP,OAAO,CAAe;IAAG,CAAC;IAEhD,IAAI,IAAI;QACN,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC;IAC3B,CAAC;IAED,IAAI,IAAI;QACN,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC;IAC3B,CAAC;IAED,MAAM;QACJ,OAAO;YACL,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,IAAI,EAAE,IAAI,CAAC,IAAI;SAChB,CAAC;IACJ,CAAC;CACF"}
@@ -0,0 +1,95 @@
1
+ /**
2
+ * Set of generic interfaces to allow PowerSync compatibility with
3
+ * different SQLite DB implementations.
4
+ */
5
+ import { BaseListener, BaseObserverInterface } from '../utils/BaseObserver';
6
+ /**
7
+ * TODO most of these types could be exported to a common `types` package
8
+ * which is used by the DB adapter libraries as well.
9
+ */
10
+ /**
11
+ * Object returned by SQL Query executions.
12
+ */
13
+ export type QueryResult = {
14
+ /** Represents the auto-generated row id if applicable. */
15
+ insertId?: number;
16
+ /** Number of affected rows if result of a update query. */
17
+ rowsAffected: number;
18
+ /** if status is undefined or 0 this object will contain the query results */
19
+ rows?: {
20
+ /** Raw array with all dataset */
21
+ _array: any[];
22
+ /** The length of the dataset */
23
+ length: number;
24
+ /** A convenience function to acess the index based the row object
25
+ * @param idx the row index
26
+ * @returns the row structure identified by column names
27
+ */
28
+ item: (idx: number) => any;
29
+ };
30
+ };
31
+ export interface DBGetUtils {
32
+ /** Execute a read-only query and return results. */
33
+ getAll<T>(sql: string, parameters?: any[]): Promise<T[]>;
34
+ /** Execute a read-only query and return the first result, or null if the ResultSet is empty. */
35
+ getOptional<T>(sql: string, parameters?: any[]): Promise<T | null>;
36
+ /** Execute a read-only query and return the first result, error if the ResultSet is empty. */
37
+ get<T>(sql: string, parameters?: any[]): Promise<T>;
38
+ }
39
+ export interface LockContext extends DBGetUtils {
40
+ /** Execute a single write statement. */
41
+ execute: (query: string, params?: any[] | undefined) => Promise<QueryResult>;
42
+ }
43
+ export interface Transaction extends LockContext {
44
+ /** Commit multiple changes to the local DB using the Transaction context. */
45
+ commit: () => Promise<QueryResult>;
46
+ /** Roll back multiple attempted changes using the Transaction context. */
47
+ rollback: () => Promise<QueryResult>;
48
+ }
49
+ /**
50
+ * Update table operation numbers from SQLite
51
+ */
52
+ export declare enum RowUpdateType {
53
+ SQLITE_INSERT = 18,
54
+ SQLITE_DELETE = 9,
55
+ SQLITE_UPDATE = 23
56
+ }
57
+ export interface TableUpdateOperation {
58
+ opType: RowUpdateType;
59
+ rowId: number;
60
+ }
61
+ /**
62
+ * Notification of an update to one or more tables, for the purpose of realtime change notifications.
63
+ */
64
+ export interface UpdateNotification extends TableUpdateOperation {
65
+ table: string;
66
+ }
67
+ export interface BatchedUpdateNotification {
68
+ rawUpdates: UpdateNotification[];
69
+ tables: string[];
70
+ groupedUpdates: Record<string, TableUpdateOperation[]>;
71
+ }
72
+ export interface DBAdapterListener extends BaseListener {
73
+ /**
74
+ * Listener for table updates.
75
+ * Allows for single table updates in order to maintain API compatibility
76
+ * without the need for a major version bump
77
+ * The DB adapter can also batch update notifications if supported.
78
+ */
79
+ tablesUpdated: (updateNotification: BatchedUpdateNotification | UpdateNotification) => void;
80
+ }
81
+ export interface DBLockOptions {
82
+ timeoutMs?: number;
83
+ }
84
+ export interface DBAdapter extends BaseObserverInterface<DBAdapterListener>, DBGetUtils {
85
+ close: () => void;
86
+ execute: (query: string, params?: any[]) => Promise<QueryResult>;
87
+ executeBatch: (query: string, params?: any[][]) => Promise<QueryResult>;
88
+ name: string;
89
+ readLock: <T>(fn: (tx: LockContext) => Promise<T>, options?: DBLockOptions) => Promise<T>;
90
+ readTransaction: <T>(fn: (tx: Transaction) => Promise<T>, options?: DBLockOptions) => Promise<T>;
91
+ writeLock: <T>(fn: (tx: LockContext) => Promise<T>, options?: DBLockOptions) => Promise<T>;
92
+ writeTransaction: <T>(fn: (tx: Transaction) => Promise<T>, options?: DBLockOptions) => Promise<T>;
93
+ }
94
+ export declare function isBatchedUpdateNotification(update: BatchedUpdateNotification | UpdateNotification): update is BatchedUpdateNotification;
95
+ export declare function extractTableUpdates(update: BatchedUpdateNotification | UpdateNotification): string[];
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Set of generic interfaces to allow PowerSync compatibility with
3
+ * different SQLite DB implementations.
4
+ */
5
+ /**
6
+ * Update table operation numbers from SQLite
7
+ */
8
+ export var RowUpdateType;
9
+ (function (RowUpdateType) {
10
+ RowUpdateType[RowUpdateType["SQLITE_INSERT"] = 18] = "SQLITE_INSERT";
11
+ RowUpdateType[RowUpdateType["SQLITE_DELETE"] = 9] = "SQLITE_DELETE";
12
+ RowUpdateType[RowUpdateType["SQLITE_UPDATE"] = 23] = "SQLITE_UPDATE";
13
+ })(RowUpdateType || (RowUpdateType = {}));
14
+ export function isBatchedUpdateNotification(update) {
15
+ return 'tables' in update;
16
+ }
17
+ export function extractTableUpdates(update) {
18
+ return isBatchedUpdateNotification(update) ? update.tables : [update.table];
19
+ }
20
+ //# sourceMappingURL=DBAdapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DBAdapter.js","sourceRoot":"","sources":["../../src/db/DBAdapter.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAoDH;;GAEG;AACH,MAAM,CAAN,IAAY,aAIX;AAJD,WAAY,aAAa;IACvB,oEAAkB,CAAA;IAClB,mEAAiB,CAAA;IACjB,oEAAkB,CAAA;AACpB,CAAC,EAJW,aAAa,KAAb,aAAa,QAIxB;AA2CD,MAAM,UAAU,2BAA2B,CACzC,MAAsD;IAEtD,OAAO,QAAQ,IAAI,MAAM,CAAC;AAC5B,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,MAAsD;IACxF,OAAO,2BAA2B,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAC9E,CAAC"}
@@ -0,0 +1,38 @@
1
+ export type SyncDataFlowStatus = Partial<{
2
+ downloading: boolean;
3
+ uploading: boolean;
4
+ }>;
5
+ export type SyncStatusOptions = {
6
+ connected?: boolean;
7
+ dataFlow?: SyncDataFlowStatus;
8
+ lastSyncedAt?: Date;
9
+ hasSynced?: boolean;
10
+ };
11
+ export declare class SyncStatus {
12
+ protected options: SyncStatusOptions;
13
+ constructor(options: SyncStatusOptions);
14
+ /**
15
+ * true if currently connected.
16
+ */
17
+ get connected(): boolean;
18
+ /**
19
+ * Time that a last sync has fully completed, if any.
20
+ * Currently this is reset to null after a restart.
21
+ */
22
+ get lastSyncedAt(): Date | undefined;
23
+ /**
24
+ * Indicates whether there has been at least one full sync, if any.
25
+ * Is undefined when unknown, for example when state is still being loaded from the database.
26
+ */
27
+ get hasSynced(): boolean | undefined;
28
+ /**
29
+ * Upload/download status
30
+ */
31
+ get dataFlowStatus(): Partial<{
32
+ downloading: boolean;
33
+ uploading: boolean;
34
+ }>;
35
+ isEqual(status: SyncStatus): boolean;
36
+ getMessage(): string;
37
+ toJSON(): SyncStatusOptions;
38
+ }
@@ -0,0 +1,58 @@
1
+ export class SyncStatus {
2
+ options;
3
+ constructor(options) {
4
+ this.options = options;
5
+ }
6
+ /**
7
+ * true if currently connected.
8
+ */
9
+ get connected() {
10
+ return this.options.connected ?? false;
11
+ }
12
+ /**
13
+ * Time that a last sync has fully completed, if any.
14
+ * Currently this is reset to null after a restart.
15
+ */
16
+ get lastSyncedAt() {
17
+ return this.options.lastSyncedAt;
18
+ }
19
+ /**
20
+ * Indicates whether there has been at least one full sync, if any.
21
+ * Is undefined when unknown, for example when state is still being loaded from the database.
22
+ */
23
+ get hasSynced() {
24
+ return this.options.hasSynced;
25
+ }
26
+ /**
27
+ * Upload/download status
28
+ */
29
+ get dataFlowStatus() {
30
+ return (this.options.dataFlow ?? {
31
+ /**
32
+ * true if actively downloading changes.
33
+ * This is only true when {@link connected} is also true.
34
+ */
35
+ downloading: false,
36
+ /**
37
+ * true if uploading changes.
38
+ */
39
+ uploading: false
40
+ });
41
+ }
42
+ isEqual(status) {
43
+ return JSON.stringify(this.options) == JSON.stringify(status.options);
44
+ }
45
+ getMessage() {
46
+ const dataFlow = this.dataFlowStatus;
47
+ return `SyncStatus<connected: ${this.connected} lastSyncedAt: ${this.lastSyncedAt} hasSynced: ${this.hasSynced}. Downloading: ${dataFlow.downloading}. Uploading: ${dataFlow.uploading}`;
48
+ }
49
+ toJSON() {
50
+ return {
51
+ connected: this.connected,
52
+ dataFlow: this.dataFlowStatus,
53
+ lastSyncedAt: this.lastSyncedAt,
54
+ hasSynced: this.hasSynced
55
+ };
56
+ }
57
+ }
58
+ //# sourceMappingURL=SyncStatus.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SyncStatus.js","sourceRoot":"","sources":["../../../src/db/crud/SyncStatus.ts"],"names":[],"mappings":"AAYA,MAAM,OAAO,UAAU;IACC;IAAtB,YAAsB,OAA0B;QAA1B,YAAO,GAAP,OAAO,CAAmB;IAAG,CAAC;IAEpD;;OAEG;IACH,IAAI,SAAS;QACX,OAAO,IAAI,CAAC,OAAO,CAAC,SAAS,IAAI,KAAK,CAAC;IACzC,CAAC;IAED;;;OAGG;IACH,IAAI,YAAY;QACd,OAAO,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC;IACnC,CAAC;IAED;;;OAGG;IACH,IAAI,SAAS;QACX,OAAO,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC;IAChC,CAAC;IAED;;OAEG;IACH,IAAI,cAAc;QAChB,OAAO,CACL,IAAI,CAAC,OAAO,CAAC,QAAQ,IAAI;YACvB;;;eAGG;YACH,WAAW,EAAE,KAAK;YAClB;;eAEG;YACH,SAAS,EAAE,KAAK;SACjB,CACF,CAAC;IACJ,CAAC;IAED,OAAO,CAAC,MAAkB;QACxB,OAAO,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IACxE,CAAC;IAED,UAAU;QACR,MAAM,QAAQ,GAAG,IAAI,CAAC,cAAc,CAAC;QACrC,OAAO,yBAAyB,IAAI,CAAC,SAAS,kBAAkB,IAAI,CAAC,YAAY,eAAe,IAAI,CAAC,SAAS,kBAAkB,QAAQ,CAAC,WAAW,gBAAgB,QAAQ,CAAC,SAAS,EAAE,CAAC;IAC3L,CAAC;IAED,MAAM;QACJ,OAAO;YACL,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,QAAQ,EAAE,IAAI,CAAC,cAAc;YAC7B,YAAY,EAAE,IAAI,CAAC,YAAY;YAC/B,SAAS,EAAE,IAAI,CAAC,SAAS;SAC1B,CAAC;IACJ,CAAC;CACF"}
@@ -0,0 +1,20 @@
1
+ export declare class UploadQueueStats {
2
+ /**
3
+ * Number of records in the upload queue.
4
+ */
5
+ count: number;
6
+ /**
7
+ * Size of the upload queue in bytes.
8
+ */
9
+ size: number | null;
10
+ constructor(
11
+ /**
12
+ * Number of records in the upload queue.
13
+ */
14
+ count: number,
15
+ /**
16
+ * Size of the upload queue in bytes.
17
+ */
18
+ size?: number | null);
19
+ toString(): string;
20
+ }
@@ -0,0 +1,25 @@
1
+ export class UploadQueueStats {
2
+ count;
3
+ size;
4
+ constructor(
5
+ /**
6
+ * Number of records in the upload queue.
7
+ */
8
+ count,
9
+ /**
10
+ * Size of the upload queue in bytes.
11
+ */
12
+ size = null) {
13
+ this.count = count;
14
+ this.size = size;
15
+ }
16
+ toString() {
17
+ if (this.size == null) {
18
+ return `UploadQueueStats<count:${this.count}>`;
19
+ }
20
+ else {
21
+ return `UploadQueueStats<count: $count size: ${this.size / 1024}kB>`;
22
+ }
23
+ }
24
+ }
25
+ //# sourceMappingURL=UploadQueueStatus.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"UploadQueueStatus.js","sourceRoot":"","sources":["../../../src/db/crud/UploadQueueStatus.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,gBAAgB;IAKlB;IAIA;IART;IACE;;OAEG;IACI,KAAa;IACpB;;OAEG;IACI,OAAsB,IAAI;QAJ1B,UAAK,GAAL,KAAK,CAAQ;QAIb,SAAI,GAAJ,IAAI,CAAsB;IAChC,CAAC;IAEJ,QAAQ;QACN,IAAI,IAAI,CAAC,IAAI,IAAI,IAAI,EAAE,CAAC;YACtB,OAAO,0BAA0B,IAAI,CAAC,KAAK,GAAG,CAAC;QACjD,CAAC;aAAM,CAAC;YACN,OAAO,wCAAwC,IAAI,CAAC,IAAI,GAAG,IAAI,KAAK,CAAC;QACvE,CAAC;IACH,CAAC;CACF"}
@@ -0,0 +1,22 @@
1
+ import { IndexedColumn } from './IndexedColumn';
2
+ import { Table } from './Table';
3
+ export interface IndexOptions {
4
+ name: string;
5
+ columns?: IndexedColumn[];
6
+ }
7
+ export declare const DEFAULT_INDEX_OPTIONS: Partial<IndexOptions>;
8
+ export declare class Index {
9
+ protected options: IndexOptions;
10
+ static createAscending(options: IndexOptions, columnNames: string[]): Index;
11
+ constructor(options: IndexOptions);
12
+ get name(): string;
13
+ get columns(): IndexedColumn[];
14
+ toJSON(table: Table): {
15
+ name: string;
16
+ columns: {
17
+ name: string;
18
+ ascending: boolean | undefined;
19
+ type: import("../Column").ColumnType;
20
+ }[];
21
+ };
22
+ }
@@ -0,0 +1,30 @@
1
+ import { IndexedColumn } from './IndexedColumn';
2
+ export const DEFAULT_INDEX_OPTIONS = {
3
+ columns: []
4
+ };
5
+ export class Index {
6
+ options;
7
+ static createAscending(options, columnNames) {
8
+ return new Index({
9
+ ...options,
10
+ columns: columnNames.map((name) => IndexedColumn.createAscending(name))
11
+ });
12
+ }
13
+ constructor(options) {
14
+ this.options = options;
15
+ this.options = { ...DEFAULT_INDEX_OPTIONS, ...options };
16
+ }
17
+ get name() {
18
+ return this.options.name;
19
+ }
20
+ get columns() {
21
+ return this.options.columns ?? [];
22
+ }
23
+ toJSON(table) {
24
+ return {
25
+ name: this.name,
26
+ columns: this.columns.map((c) => c.toJSON(table))
27
+ };
28
+ }
29
+ }
30
+ //# sourceMappingURL=Index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Index.js","sourceRoot":"","sources":["../../../src/db/schema/Index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAQhD,MAAM,CAAC,MAAM,qBAAqB,GAA0B;IAC1D,OAAO,EAAE,EAAE;CACZ,CAAC;AAEF,MAAM,OAAO,KAAK;IAQM;IAPtB,MAAM,CAAC,eAAe,CAAC,OAAqB,EAAE,WAAqB;QACjE,OAAO,IAAI,KAAK,CAAC;YACf,GAAG,OAAO;YACV,OAAO,EAAE,WAAW,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,aAAa,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;SACxE,CAAC,CAAC;IACL,CAAC;IAED,YAAsB,OAAqB;QAArB,YAAO,GAAP,OAAO,CAAc;QACzC,IAAI,CAAC,OAAO,GAAG,EAAE,GAAG,qBAAqB,EAAE,GAAG,OAAO,EAAE,CAAC;IAC1D,CAAC;IAED,IAAI,IAAI;QACN,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC;IAC3B,CAAC;IAED,IAAI,OAAO;QACT,OAAO,IAAI,CAAC,OAAO,CAAC,OAAO,IAAI,EAAE,CAAC;IACpC,CAAC;IAED,MAAM,CAAC,KAAY;QACjB,OAAO;YACL,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;SAClD,CAAC;IACJ,CAAC;CACF"}
@@ -0,0 +1,19 @@
1
+ import { ColumnType } from '../Column';
2
+ import { Table } from './Table';
3
+ export interface IndexColumnOptions {
4
+ name: string;
5
+ ascending?: boolean;
6
+ }
7
+ export declare const DEFAULT_INDEX_COLUMN_OPTIONS: Partial<IndexColumnOptions>;
8
+ export declare class IndexedColumn {
9
+ protected options: IndexColumnOptions;
10
+ static createAscending(column: string): IndexedColumn;
11
+ constructor(options: IndexColumnOptions);
12
+ get name(): string;
13
+ get ascending(): boolean | undefined;
14
+ toJSON(table: Table): {
15
+ name: string;
16
+ ascending: boolean | undefined;
17
+ type: ColumnType;
18
+ };
19
+ }
@@ -0,0 +1,30 @@
1
+ import { ColumnType } from '../Column';
2
+ export const DEFAULT_INDEX_COLUMN_OPTIONS = {
3
+ ascending: true
4
+ };
5
+ export class IndexedColumn {
6
+ options;
7
+ static createAscending(column) {
8
+ return new IndexedColumn({
9
+ name: column,
10
+ ascending: true
11
+ });
12
+ }
13
+ constructor(options) {
14
+ this.options = { ...DEFAULT_INDEX_COLUMN_OPTIONS, ...options };
15
+ }
16
+ get name() {
17
+ return this.options.name;
18
+ }
19
+ get ascending() {
20
+ return this.options.ascending;
21
+ }
22
+ toJSON(table) {
23
+ return {
24
+ name: this.name,
25
+ ascending: this.ascending,
26
+ type: table.columns.find((column) => column.name === this.name)?.type ?? ColumnType.TEXT
27
+ };
28
+ }
29
+ }
30
+ //# sourceMappingURL=IndexedColumn.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"IndexedColumn.js","sourceRoot":"","sources":["../../../src/db/schema/IndexedColumn.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAQvC,MAAM,CAAC,MAAM,4BAA4B,GAAgC;IACvE,SAAS,EAAE,IAAI;CAChB,CAAC;AAEF,MAAM,OAAO,aAAa;IACd,OAAO,CAAqB;IAEtC,MAAM,CAAC,eAAe,CAAC,MAAc;QACnC,OAAO,IAAI,aAAa,CAAC;YACvB,IAAI,EAAE,MAAM;YACZ,SAAS,EAAE,IAAI;SAChB,CAAC,CAAC;IACL,CAAC;IAED,YAAY,OAA2B;QACrC,IAAI,CAAC,OAAO,GAAG,EAAE,GAAG,4BAA4B,EAAE,GAAG,OAAO,EAAE,CAAC;IACjE,CAAC;IAED,IAAI,IAAI;QACN,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC;IAC3B,CAAC;IAED,IAAI,SAAS;QACX,OAAO,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC;IAChC,CAAC;IAED,MAAM,CAAC,KAAY;QACjB,OAAO;YACL,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,IAAI,EAAE,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,IAAI,UAAU,CAAC,IAAI;SACzF,CAAC;IACJ,CAAC;CACF"}
@@ -0,0 +1,38 @@
1
+ import { Table as ClassicTable } from './Table';
2
+ import { RowType, TableV2 } from './TableV2';
3
+ type SchemaType = Record<string, TableV2<any>>;
4
+ type SchemaTableType<S extends SchemaType> = {
5
+ [K in keyof S]: RowType<S[K]>;
6
+ };
7
+ /**
8
+ * A schema is a collection of tables. It is used to define the structure of a database.
9
+ */
10
+ export declare class Schema<S extends SchemaType = SchemaType> {
11
+ tables: ClassicTable[] | S;
12
+ readonly types: SchemaTableType<S>;
13
+ readonly props: S;
14
+ constructor(tables: ClassicTable[] | S);
15
+ validate(): void;
16
+ toJSON(): {
17
+ tables: {
18
+ name: string;
19
+ view_name: string;
20
+ local_only: boolean;
21
+ insert_only: boolean;
22
+ columns: {
23
+ name: string;
24
+ type: import("../Column").ColumnType | undefined;
25
+ }[];
26
+ indexes: {
27
+ name: string;
28
+ columns: {
29
+ name: string;
30
+ ascending: boolean | undefined;
31
+ type: import("../Column").ColumnType;
32
+ }[];
33
+ }[];
34
+ }[];
35
+ };
36
+ private convertToClassicTables;
37
+ }
38
+ export {};
@@ -0,0 +1,38 @@
1
+ import { Table as ClassicTable } from './Table';
2
+ /**
3
+ * A schema is a collection of tables. It is used to define the structure of a database.
4
+ */
5
+ export class Schema {
6
+ tables;
7
+ /*
8
+ Only available when constructing with mapped typed definition columns
9
+ */
10
+ types;
11
+ props;
12
+ constructor(tables) {
13
+ this.tables = tables;
14
+ if (Array.isArray(tables)) {
15
+ this.tables = tables;
16
+ }
17
+ else {
18
+ this.props = tables;
19
+ this.tables = this.convertToClassicTables(this.props);
20
+ }
21
+ }
22
+ validate() {
23
+ for (const table of this.tables) {
24
+ table.validate();
25
+ }
26
+ }
27
+ toJSON() {
28
+ return {
29
+ tables: this.tables.map((t) => t.toJSON())
30
+ };
31
+ }
32
+ convertToClassicTables(props) {
33
+ return Object.entries(props).map(([name, table]) => {
34
+ return ClassicTable.createTable(name, table);
35
+ });
36
+ }
37
+ }
38
+ //# sourceMappingURL=Schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Schema.js","sourceRoot":"","sources":["../../../src/db/schema/Schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,IAAI,YAAY,EAAE,MAAM,SAAS,CAAC;AAShD;;GAEG;AACH,MAAM,OAAO,MAAM;IAME;IALnB;;MAEE;IACO,KAAK,CAAqB;IAC1B,KAAK,CAAI;IAClB,YAAmB,MAA0B;QAA1B,WAAM,GAAN,MAAM,CAAoB;QAC3C,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;YAC1B,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACvB,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,KAAK,GAAG,MAAW,CAAC;YACzB,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,sBAAsB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACxD,CAAC;IACH,CAAC;IAED,QAAQ;QACN,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,MAAwB,EAAE,CAAC;YAClD,KAAK,CAAC,QAAQ,EAAE,CAAC;QACnB,CAAC;IACH,CAAC;IAED,MAAM;QACJ,OAAO;YACL,MAAM,EAAG,IAAI,CAAC,MAAyB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;SAC/D,CAAC;IACJ,CAAC;IAEO,sBAAsB,CAAC,KAAQ;QACrC,OAAO,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,EAAE;YACjD,OAAO,YAAY,CAAC,WAAW,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QAC/C,CAAC,CAAC,CAAC;IACL,CAAC;CACF"}
@@ -0,0 +1,51 @@
1
+ import { Column } from '../Column';
2
+ import type { Index } from './Index';
3
+ import { TableV2 } from './TableV2';
4
+ export interface TableOptions {
5
+ /**
6
+ * The synced table name, matching sync rules
7
+ */
8
+ name: string;
9
+ columns: Column[];
10
+ indexes?: Index[];
11
+ localOnly?: boolean;
12
+ insertOnly?: boolean;
13
+ viewName?: string;
14
+ }
15
+ export declare const DEFAULT_TABLE_OPTIONS: Partial<TableOptions>;
16
+ export declare const InvalidSQLCharacters: RegExp;
17
+ export declare class Table {
18
+ protected options: TableOptions;
19
+ static createLocalOnly(options: TableOptions): Table;
20
+ static createInsertOnly(options: TableOptions): Table;
21
+ static createTable(name: string, table: TableV2): Table;
22
+ constructor(options: TableOptions);
23
+ get name(): string;
24
+ get viewNameOverride(): string | undefined;
25
+ get viewName(): string;
26
+ get columns(): Column[];
27
+ get indexes(): Index[];
28
+ get localOnly(): boolean;
29
+ get insertOnly(): boolean;
30
+ get internalName(): string;
31
+ get validName(): boolean;
32
+ validate(): void;
33
+ toJSON(): {
34
+ name: string;
35
+ view_name: string;
36
+ local_only: boolean;
37
+ insert_only: boolean;
38
+ columns: {
39
+ name: string;
40
+ type: import("../Column").ColumnType | undefined;
41
+ }[];
42
+ indexes: {
43
+ name: string;
44
+ columns: {
45
+ name: string;
46
+ ascending: boolean | undefined;
47
+ type: import("../Column").ColumnType;
48
+ }[];
49
+ }[];
50
+ };
51
+ }
@@ -0,0 +1,114 @@
1
+ import { Column } from '../Column';
2
+ export const DEFAULT_TABLE_OPTIONS = {
3
+ indexes: [],
4
+ insertOnly: false,
5
+ localOnly: false
6
+ };
7
+ export const InvalidSQLCharacters = /["'%,.#\s[\]]/;
8
+ export class Table {
9
+ options;
10
+ static createLocalOnly(options) {
11
+ return new Table({ ...options, localOnly: true, insertOnly: false });
12
+ }
13
+ static createInsertOnly(options) {
14
+ return new Table({ ...options, localOnly: false, insertOnly: true });
15
+ }
16
+ static createTable(name, table) {
17
+ return new Table({
18
+ name,
19
+ columns: Object.entries(table.columns).map(([name, col]) => new Column({ name, type: col.type })),
20
+ indexes: table.indexes,
21
+ localOnly: table.options.localOnly,
22
+ insertOnly: table.options.insertOnly,
23
+ viewName: table.options.viewName
24
+ });
25
+ }
26
+ constructor(options) {
27
+ this.options = { ...DEFAULT_TABLE_OPTIONS, ...options };
28
+ }
29
+ get name() {
30
+ return this.options.name;
31
+ }
32
+ get viewNameOverride() {
33
+ return this.options.viewName;
34
+ }
35
+ get viewName() {
36
+ return this.viewNameOverride ?? this.name;
37
+ }
38
+ get columns() {
39
+ return this.options.columns;
40
+ }
41
+ get indexes() {
42
+ return this.options.indexes ?? [];
43
+ }
44
+ get localOnly() {
45
+ return this.options.localOnly ?? false;
46
+ }
47
+ get insertOnly() {
48
+ return this.options.insertOnly ?? false;
49
+ }
50
+ get internalName() {
51
+ if (this.options.localOnly) {
52
+ return `ps_data_local__${this.name}`;
53
+ }
54
+ return `ps_data__${this.name}`;
55
+ }
56
+ get validName() {
57
+ if (InvalidSQLCharacters.test(this.name)) {
58
+ return false;
59
+ }
60
+ if (this.viewNameOverride != null && InvalidSQLCharacters.test(this.viewNameOverride)) {
61
+ return false;
62
+ }
63
+ return true;
64
+ }
65
+ validate() {
66
+ if (InvalidSQLCharacters.test(this.name)) {
67
+ throw new Error(`Invalid characters in table name: ${this.name}`);
68
+ }
69
+ if (this.viewNameOverride && InvalidSQLCharacters.test(this.viewNameOverride)) {
70
+ throw new Error(`Invalid characters in view name: ${this.viewNameOverride}`);
71
+ }
72
+ const columnNames = new Set();
73
+ columnNames.add('id');
74
+ for (const column of this.columns) {
75
+ const { name: columnName } = column;
76
+ if (column.name == 'id') {
77
+ throw new Error(`${this.name}: id column is automatically added, custom id columns are not supported`);
78
+ }
79
+ if (columnNames.has(columnName)) {
80
+ throw new Error(`Duplicate column ${columnName}`);
81
+ }
82
+ if (InvalidSQLCharacters.test(columnName)) {
83
+ throw new Error(`Invalid characters in column name: $name.${column}`);
84
+ }
85
+ columnNames.add(columnName);
86
+ }
87
+ const indexNames = new Set();
88
+ for (const index of this.indexes) {
89
+ if (indexNames.has(index.name)) {
90
+ throw new Error(`Duplicate index $name.${index}`);
91
+ }
92
+ if (InvalidSQLCharacters.test(index.name)) {
93
+ throw new Error(`Invalid characters in index name: $name.${index}`);
94
+ }
95
+ for (const column of index.columns) {
96
+ if (!columnNames.has(column.name)) {
97
+ throw new Error(`Column ${column.name} not found for index ${index.name}`);
98
+ }
99
+ }
100
+ indexNames.add(index.name);
101
+ }
102
+ }
103
+ toJSON() {
104
+ return {
105
+ name: this.name,
106
+ view_name: this.viewName,
107
+ local_only: this.localOnly,
108
+ insert_only: this.insertOnly,
109
+ columns: this.columns.map((c) => c.toJSON()),
110
+ indexes: this.indexes.map((e) => e.toJSON(this))
111
+ };
112
+ }
113
+ }
114
+ //# sourceMappingURL=Table.js.map