@powersync/web 1.28.0 → 1.28.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.
- package/dist/index.umd.js +64 -26
- package/dist/index.umd.js.map +1 -1
- package/dist/worker/SharedSyncImplementation.umd.js +13640 -440
- package/dist/worker/SharedSyncImplementation.umd.js.map +1 -1
- package/dist/worker/WASQLiteDB.umd.js +13467 -161
- package/dist/worker/WASQLiteDB.umd.js.map +1 -1
- package/dist/worker/node_modules_bson_lib_bson_mjs.umd.js +66 -38
- package/dist/worker/node_modules_bson_lib_bson_mjs.umd.js.map +1 -1
- package/lib/package.json +6 -5
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/package.json +7 -6
- package/src/db/PowerSyncDatabase.ts +224 -0
- package/src/db/adapters/AbstractWebPowerSyncDatabaseOpenFactory.ts +47 -0
- package/src/db/adapters/AbstractWebSQLOpenFactory.ts +48 -0
- package/src/db/adapters/AsyncDatabaseConnection.ts +40 -0
- package/src/db/adapters/LockedAsyncDatabaseAdapter.ts +358 -0
- package/src/db/adapters/SSRDBAdapter.ts +94 -0
- package/src/db/adapters/WebDBAdapter.ts +20 -0
- package/src/db/adapters/WorkerWrappedAsyncDatabaseConnection.ts +175 -0
- package/src/db/adapters/wa-sqlite/WASQLiteConnection.ts +444 -0
- package/src/db/adapters/wa-sqlite/WASQLiteDBAdapter.ts +86 -0
- package/src/db/adapters/wa-sqlite/WASQLiteOpenFactory.ts +134 -0
- package/src/db/adapters/wa-sqlite/WASQLitePowerSyncDatabaseOpenFactory.ts +24 -0
- package/src/db/adapters/web-sql-flags.ts +135 -0
- package/src/db/sync/SSRWebStreamingSyncImplementation.ts +89 -0
- package/src/db/sync/SharedWebStreamingSyncImplementation.ts +274 -0
- package/src/db/sync/WebRemote.ts +59 -0
- package/src/db/sync/WebStreamingSyncImplementation.ts +34 -0
- package/src/db/sync/userAgent.ts +78 -0
- package/src/index.ts +13 -0
- package/src/shared/navigator.ts +9 -0
- package/src/worker/db/WASQLiteDB.worker.ts +112 -0
- package/src/worker/db/open-worker-database.ts +62 -0
- package/src/worker/sync/AbstractSharedSyncClientProvider.ts +21 -0
- package/src/worker/sync/BroadcastLogger.ts +142 -0
- package/src/worker/sync/SharedSyncImplementation.ts +520 -0
- package/src/worker/sync/SharedSyncImplementation.worker.ts +14 -0
- package/src/worker/sync/WorkerClient.ts +106 -0
- package/dist/worker/node_modules_crypto-browserify_index_js.umd.js +0 -33734
- package/dist/worker/node_modules_crypto-browserify_index_js.umd.js.map +0 -1
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
import {
|
|
2
|
+
type BucketStorageAdapter,
|
|
3
|
+
type PowerSyncBackendConnector,
|
|
4
|
+
type PowerSyncCloseOptions,
|
|
5
|
+
type RequiredAdditionalConnectionOptions,
|
|
6
|
+
AbstractPowerSyncDatabase,
|
|
7
|
+
DBAdapter,
|
|
8
|
+
DEFAULT_POWERSYNC_CLOSE_OPTIONS,
|
|
9
|
+
isDBAdapter,
|
|
10
|
+
isSQLOpenFactory,
|
|
11
|
+
PowerSyncDatabaseOptions,
|
|
12
|
+
PowerSyncDatabaseOptionsWithDBAdapter,
|
|
13
|
+
PowerSyncDatabaseOptionsWithOpenFactory,
|
|
14
|
+
PowerSyncDatabaseOptionsWithSettings,
|
|
15
|
+
SqliteBucketStorage,
|
|
16
|
+
StreamingSyncImplementation
|
|
17
|
+
} from '@powersync/common';
|
|
18
|
+
import { Mutex } from 'async-mutex';
|
|
19
|
+
import { getNavigatorLocks } from '../shared/navigator';
|
|
20
|
+
import { WASQLiteOpenFactory } from './adapters/wa-sqlite/WASQLiteOpenFactory';
|
|
21
|
+
import {
|
|
22
|
+
DEFAULT_WEB_SQL_FLAGS,
|
|
23
|
+
ResolvedWebSQLOpenOptions,
|
|
24
|
+
resolveWebSQLFlags,
|
|
25
|
+
WebSQLFlags
|
|
26
|
+
} from './adapters/web-sql-flags';
|
|
27
|
+
import { WebDBAdapter } from './adapters/WebDBAdapter';
|
|
28
|
+
import { SharedWebStreamingSyncImplementation } from './sync/SharedWebStreamingSyncImplementation';
|
|
29
|
+
import { SSRStreamingSyncImplementation } from './sync/SSRWebStreamingSyncImplementation';
|
|
30
|
+
import { WebRemote } from './sync/WebRemote';
|
|
31
|
+
import {
|
|
32
|
+
WebStreamingSyncImplementation,
|
|
33
|
+
WebStreamingSyncImplementationOptions
|
|
34
|
+
} from './sync/WebStreamingSyncImplementation';
|
|
35
|
+
|
|
36
|
+
export interface WebPowerSyncFlags extends WebSQLFlags {
|
|
37
|
+
/**
|
|
38
|
+
* Externally unload open PowerSync database instances when the window closes.
|
|
39
|
+
* Setting this to `true` requires calling `close` on all open PowerSyncDatabase
|
|
40
|
+
* instances before the window unloads
|
|
41
|
+
*/
|
|
42
|
+
externallyUnload?: boolean;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
type WithWebFlags<Base> = Base & { flags?: WebPowerSyncFlags };
|
|
46
|
+
|
|
47
|
+
export interface WebSyncOptions {
|
|
48
|
+
/**
|
|
49
|
+
* Allows you to override the default sync worker.
|
|
50
|
+
*
|
|
51
|
+
* You can either provide a path to the worker script
|
|
52
|
+
* or a factory method that returns a worker.
|
|
53
|
+
*/
|
|
54
|
+
worker?: string | URL | ((options: ResolvedWebSQLOpenOptions) => SharedWorker);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
type WithWebSyncOptions<Base> = Base & {
|
|
58
|
+
sync?: WebSyncOptions;
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
export interface WebEncryptionOptions {
|
|
62
|
+
/**
|
|
63
|
+
* Encryption key for the database.
|
|
64
|
+
* If set, the database will be encrypted using Multiple Ciphers.
|
|
65
|
+
*/
|
|
66
|
+
encryptionKey?: string;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
type WithWebEncryptionOptions<Base> = Base & WebEncryptionOptions;
|
|
70
|
+
|
|
71
|
+
export type WebPowerSyncDatabaseOptionsWithAdapter = WithWebSyncOptions<
|
|
72
|
+
WithWebFlags<PowerSyncDatabaseOptionsWithDBAdapter>
|
|
73
|
+
>;
|
|
74
|
+
export type WebPowerSyncDatabaseOptionsWithOpenFactory = WithWebSyncOptions<
|
|
75
|
+
WithWebFlags<PowerSyncDatabaseOptionsWithOpenFactory>
|
|
76
|
+
>;
|
|
77
|
+
export type WebPowerSyncDatabaseOptionsWithSettings = WithWebSyncOptions<
|
|
78
|
+
WithWebFlags<WithWebEncryptionOptions<PowerSyncDatabaseOptionsWithSettings>>
|
|
79
|
+
>;
|
|
80
|
+
|
|
81
|
+
export type WebPowerSyncDatabaseOptions = WithWebSyncOptions<WithWebFlags<PowerSyncDatabaseOptions>>;
|
|
82
|
+
|
|
83
|
+
export const DEFAULT_POWERSYNC_FLAGS: Required<WebPowerSyncFlags> = {
|
|
84
|
+
...DEFAULT_WEB_SQL_FLAGS,
|
|
85
|
+
externallyUnload: false
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
export const resolveWebPowerSyncFlags = (flags?: WebPowerSyncFlags): Required<WebPowerSyncFlags> => {
|
|
89
|
+
return {
|
|
90
|
+
...DEFAULT_POWERSYNC_FLAGS,
|
|
91
|
+
...flags,
|
|
92
|
+
...resolveWebSQLFlags(flags)
|
|
93
|
+
};
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Asserts that the database options are valid for custom database constructors.
|
|
98
|
+
*/
|
|
99
|
+
function assertValidDatabaseOptions(options: WebPowerSyncDatabaseOptions): void {
|
|
100
|
+
if ('database' in options && 'encryptionKey' in options) {
|
|
101
|
+
const { database } = options;
|
|
102
|
+
if (isSQLOpenFactory(database) || isDBAdapter(database)) {
|
|
103
|
+
throw new Error(
|
|
104
|
+
`Invalid configuration: 'encryptionKey' should only be included inside the database object when using a custom ${isSQLOpenFactory(database) ? 'WASQLiteOpenFactory' : 'WASQLiteDBAdapter'} constructor.`
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* A PowerSync database which provides SQLite functionality
|
|
112
|
+
* which is automatically synced.
|
|
113
|
+
*
|
|
114
|
+
* @example
|
|
115
|
+
* ```typescript
|
|
116
|
+
* export const db = new PowerSyncDatabase({
|
|
117
|
+
* schema: AppSchema,
|
|
118
|
+
* database: {
|
|
119
|
+
* dbFilename: 'example.db'
|
|
120
|
+
* }
|
|
121
|
+
* });
|
|
122
|
+
* ```
|
|
123
|
+
*/
|
|
124
|
+
export class PowerSyncDatabase extends AbstractPowerSyncDatabase {
|
|
125
|
+
static SHARED_MUTEX = new Mutex();
|
|
126
|
+
|
|
127
|
+
protected unloadListener?: () => Promise<void>;
|
|
128
|
+
protected resolvedFlags: WebPowerSyncFlags;
|
|
129
|
+
|
|
130
|
+
constructor(options: WebPowerSyncDatabaseOptionsWithAdapter);
|
|
131
|
+
constructor(options: WebPowerSyncDatabaseOptionsWithOpenFactory);
|
|
132
|
+
constructor(options: WebPowerSyncDatabaseOptionsWithSettings);
|
|
133
|
+
constructor(options: WebPowerSyncDatabaseOptions);
|
|
134
|
+
constructor(protected options: WebPowerSyncDatabaseOptions) {
|
|
135
|
+
super(options);
|
|
136
|
+
|
|
137
|
+
assertValidDatabaseOptions(options);
|
|
138
|
+
|
|
139
|
+
this.resolvedFlags = resolveWebPowerSyncFlags(options.flags);
|
|
140
|
+
|
|
141
|
+
if (this.resolvedFlags.enableMultiTabs && !this.resolvedFlags.externallyUnload) {
|
|
142
|
+
this.unloadListener = () => this.close({ disconnect: false });
|
|
143
|
+
window.addEventListener('unload', this.unloadListener);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
async _initialize(): Promise<void> {}
|
|
148
|
+
|
|
149
|
+
protected openDBAdapter(options: WebPowerSyncDatabaseOptionsWithSettings): DBAdapter {
|
|
150
|
+
const defaultFactory = new WASQLiteOpenFactory({
|
|
151
|
+
...options.database,
|
|
152
|
+
flags: resolveWebPowerSyncFlags(options.flags),
|
|
153
|
+
encryptionKey: options.encryptionKey
|
|
154
|
+
});
|
|
155
|
+
return defaultFactory.openDB();
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Closes the database connection.
|
|
160
|
+
* By default the sync stream client is only disconnected if
|
|
161
|
+
* multiple tabs are not enabled.
|
|
162
|
+
*/
|
|
163
|
+
close(options: PowerSyncCloseOptions = DEFAULT_POWERSYNC_CLOSE_OPTIONS): Promise<void> {
|
|
164
|
+
if (this.unloadListener) {
|
|
165
|
+
window.removeEventListener('unload', this.unloadListener);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
return super.close({
|
|
169
|
+
// Don't disconnect by default if multiple tabs are enabled
|
|
170
|
+
disconnect: options.disconnect ?? !this.resolvedFlags.enableMultiTabs
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
protected generateBucketStorageAdapter(): BucketStorageAdapter {
|
|
175
|
+
return new SqliteBucketStorage(this.database);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
protected async runExclusive<T>(cb: () => Promise<T>) {
|
|
179
|
+
if (this.resolvedFlags.ssrMode) {
|
|
180
|
+
return PowerSyncDatabase.SHARED_MUTEX.runExclusive(cb);
|
|
181
|
+
}
|
|
182
|
+
return getNavigatorLocks().request(`lock-${this.database.name}`, cb);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
protected generateSyncStreamImplementation(
|
|
186
|
+
connector: PowerSyncBackendConnector,
|
|
187
|
+
options: RequiredAdditionalConnectionOptions
|
|
188
|
+
): StreamingSyncImplementation {
|
|
189
|
+
const remote = new WebRemote(connector, this.logger);
|
|
190
|
+
const syncOptions: WebStreamingSyncImplementationOptions = {
|
|
191
|
+
...(this.options as {}),
|
|
192
|
+
...options,
|
|
193
|
+
flags: this.resolvedFlags,
|
|
194
|
+
adapter: this.bucketStorageAdapter,
|
|
195
|
+
remote,
|
|
196
|
+
uploadCrud: async () => {
|
|
197
|
+
await this.waitForReady();
|
|
198
|
+
await connector.uploadData(this);
|
|
199
|
+
},
|
|
200
|
+
identifier: this.database.name,
|
|
201
|
+
logger: this.logger
|
|
202
|
+
};
|
|
203
|
+
|
|
204
|
+
switch (true) {
|
|
205
|
+
case this.resolvedFlags.ssrMode:
|
|
206
|
+
return new SSRStreamingSyncImplementation(syncOptions);
|
|
207
|
+
case this.resolvedFlags.enableMultiTabs:
|
|
208
|
+
if (!this.resolvedFlags.broadcastLogs) {
|
|
209
|
+
const warning = `
|
|
210
|
+
Multiple tabs are enabled, but broadcasting of logs is disabled.
|
|
211
|
+
Logs for shared sync worker will only be available in the shared worker context
|
|
212
|
+
`;
|
|
213
|
+
const logger = this.options.logger;
|
|
214
|
+
logger ? logger.warn(warning) : console.warn(warning);
|
|
215
|
+
}
|
|
216
|
+
return new SharedWebStreamingSyncImplementation({
|
|
217
|
+
...syncOptions,
|
|
218
|
+
db: this.database as WebDBAdapter // This should always be the case
|
|
219
|
+
});
|
|
220
|
+
default:
|
|
221
|
+
return new WebStreamingSyncImplementation(syncOptions);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import {
|
|
2
|
+
AbstractPowerSyncDatabase,
|
|
3
|
+
AbstractPowerSyncDatabaseOpenFactory,
|
|
4
|
+
PowerSyncDatabaseOptions,
|
|
5
|
+
PowerSyncOpenFactoryOptions
|
|
6
|
+
} from '@powersync/common';
|
|
7
|
+
import {
|
|
8
|
+
PowerSyncDatabase,
|
|
9
|
+
WebPowerSyncDatabaseOptions,
|
|
10
|
+
WebPowerSyncFlags,
|
|
11
|
+
resolveWebPowerSyncFlags
|
|
12
|
+
} from '../../db/PowerSyncDatabase';
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* {@link WebPowerSyncFlags}
|
|
16
|
+
* Maintaining export for consistency with API from previous versions
|
|
17
|
+
* */
|
|
18
|
+
export interface WebPowerSyncOpenFlags extends WebPowerSyncFlags {}
|
|
19
|
+
|
|
20
|
+
export interface WebPowerSyncOpenFactoryOptions extends PowerSyncOpenFactoryOptions {
|
|
21
|
+
flags?: WebPowerSyncOpenFlags;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Intermediate PowerSync Database Open factory for Web which uses a mock
|
|
26
|
+
* SSR DB Adapter if running on server side.
|
|
27
|
+
* Most SQLite DB implementations only run on client side, this will safely return
|
|
28
|
+
* empty query results in SSR which will allow for generating server partial views.
|
|
29
|
+
*/
|
|
30
|
+
export abstract class AbstractWebPowerSyncDatabaseOpenFactory extends AbstractPowerSyncDatabaseOpenFactory {
|
|
31
|
+
constructor(protected options: WebPowerSyncOpenFactoryOptions) {
|
|
32
|
+
super(options);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
generateOptions(): WebPowerSyncDatabaseOptions {
|
|
36
|
+
return {
|
|
37
|
+
...this.options,
|
|
38
|
+
database: this.openDB(),
|
|
39
|
+
schema: this.schema,
|
|
40
|
+
flags: resolveWebPowerSyncFlags(this.options.flags)
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
generateInstance(options: PowerSyncDatabaseOptions): AbstractPowerSyncDatabase {
|
|
45
|
+
return new PowerSyncDatabase(options);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { type ILogger, createLogger, DBAdapter, SQLOpenFactory } from '@powersync/common';
|
|
2
|
+
import { SSRDBAdapter } from './SSRDBAdapter';
|
|
3
|
+
import { ResolvedWebSQLFlags, WebSQLOpenFactoryOptions, isServerSide, resolveWebSQLFlags } from './web-sql-flags';
|
|
4
|
+
|
|
5
|
+
export abstract class AbstractWebSQLOpenFactory implements SQLOpenFactory {
|
|
6
|
+
protected resolvedFlags: ResolvedWebSQLFlags;
|
|
7
|
+
protected logger: ILogger;
|
|
8
|
+
|
|
9
|
+
constructor(protected options: WebSQLOpenFactoryOptions) {
|
|
10
|
+
this.resolvedFlags = resolveWebSQLFlags(options.flags);
|
|
11
|
+
this.logger = options.logger ?? createLogger(`AbstractWebSQLOpenFactory - ${this.options.dbFilename}`);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Opens a DBAdapter if not in SSR mode
|
|
16
|
+
*/
|
|
17
|
+
protected abstract openAdapter(): DBAdapter;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Opens a {@link DBAdapter} using resolved flags.
|
|
21
|
+
* A SSR implementation is loaded if SSR mode is detected.
|
|
22
|
+
*/
|
|
23
|
+
openDB() {
|
|
24
|
+
const {
|
|
25
|
+
resolvedFlags: { disableSSRWarning, enableMultiTabs, ssrMode = isServerSide() }
|
|
26
|
+
} = this;
|
|
27
|
+
if (ssrMode && !disableSSRWarning) {
|
|
28
|
+
this.logger.warn(
|
|
29
|
+
`
|
|
30
|
+
Running PowerSync in SSR mode.
|
|
31
|
+
Only empty query results will be returned.
|
|
32
|
+
Disable this warning by setting 'disableSSRWarning: true' in options.`
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if (!enableMultiTabs) {
|
|
37
|
+
this.logger.warn(
|
|
38
|
+
'Multiple tab support is not enabled. Using this site across multiple tabs may not function correctly.'
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if (ssrMode) {
|
|
43
|
+
return new SSRDBAdapter();
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return this.openAdapter();
|
|
47
|
+
}
|
|
48
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { BatchedUpdateNotification, QueryResult } from '@powersync/common';
|
|
2
|
+
import { ResolvedWebSQLOpenOptions } from './web-sql-flags';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @internal
|
|
6
|
+
* Proxied query result does not contain a function for accessing row values
|
|
7
|
+
*/
|
|
8
|
+
export type ProxiedQueryResult = Omit<QueryResult, 'rows'> & {
|
|
9
|
+
rows: {
|
|
10
|
+
_array: any[];
|
|
11
|
+
length: number;
|
|
12
|
+
};
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* @internal
|
|
17
|
+
*/
|
|
18
|
+
export type OnTableChangeCallback = (event: BatchedUpdateNotification) => void;
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* @internal
|
|
22
|
+
* An async Database connection which provides basic async SQL methods.
|
|
23
|
+
* This is usually a proxied through a web worker.
|
|
24
|
+
*/
|
|
25
|
+
export interface AsyncDatabaseConnection<Config extends ResolvedWebSQLOpenOptions = ResolvedWebSQLOpenOptions> {
|
|
26
|
+
init(): Promise<void>;
|
|
27
|
+
close(): Promise<void>;
|
|
28
|
+
execute(sql: string, params?: any[]): Promise<ProxiedQueryResult>;
|
|
29
|
+
executeRaw(sql: string, params?: any[]): Promise<any[][]>;
|
|
30
|
+
executeBatch(sql: string, params?: any[]): Promise<ProxiedQueryResult>;
|
|
31
|
+
registerOnTableChange(callback: OnTableChangeCallback): Promise<() => void>;
|
|
32
|
+
getConfig(): Promise<Config>;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* @internal
|
|
37
|
+
*/
|
|
38
|
+
export type OpenAsyncDatabaseConnection<Config extends ResolvedWebSQLOpenOptions = ResolvedWebSQLOpenOptions> = (
|
|
39
|
+
config: Config
|
|
40
|
+
) => AsyncDatabaseConnection;
|