@slimr/dbsync 0.0.5 → 0.0.6
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/README.md +5 -5
- package/cjs/DbSync.d.ts +47 -3
- package/cjs/DbSync.js +54 -18
- package/cjs/DbSync.js.map +1 -1
- package/cjs/adapters/RestAdapter.d.ts +17 -0
- package/cjs/adapters/RestAdapter.js +13 -0
- package/cjs/adapters/RestAdapter.js.map +1 -1
- package/cjs/adapters/types.d.ts +13 -0
- package/cjs/internal/AuthManager.d.ts +17 -2
- package/cjs/internal/AuthManager.js +19 -4
- package/cjs/internal/AuthManager.js.map +1 -1
- package/cjs/internal/EventBus.d.ts +12 -0
- package/cjs/internal/EventBus.js +12 -0
- package/cjs/internal/EventBus.js.map +1 -1
- package/cjs/internal/StorageManager.d.ts +21 -0
- package/cjs/internal/StorageManager.js +21 -0
- package/cjs/internal/StorageManager.js.map +1 -1
- package/cjs/internal/SyncEngine.d.ts +29 -3
- package/cjs/internal/SyncEngine.js +31 -5
- package/cjs/internal/SyncEngine.js.map +1 -1
- package/cjs/useDbQuery.js +2 -0
- package/cjs/useDbQuery.js.map +1 -1
- package/cjs/util/promiseWithResolvers.js +3 -0
- package/cjs/util/promiseWithResolvers.js.map +1 -1
- package/docs/Adapters.md +58 -0
- package/docs/LocalAdapter.md +7 -0
- package/docs/RestAdapter.md +69 -0
- package/esm/DbSync.d.ts +47 -3
- package/esm/DbSync.js +54 -18
- package/esm/DbSync.js.map +1 -1
- package/esm/adapters/RestAdapter.d.ts +17 -0
- package/esm/adapters/RestAdapter.js +13 -0
- package/esm/adapters/RestAdapter.js.map +1 -1
- package/esm/adapters/types.d.ts +13 -0
- package/esm/internal/AuthManager.d.ts +17 -2
- package/esm/internal/AuthManager.js +19 -4
- package/esm/internal/AuthManager.js.map +1 -1
- package/esm/internal/EventBus.d.ts +12 -0
- package/esm/internal/EventBus.js +12 -0
- package/esm/internal/EventBus.js.map +1 -1
- package/esm/internal/StorageManager.d.ts +21 -0
- package/esm/internal/StorageManager.js +21 -0
- package/esm/internal/StorageManager.js.map +1 -1
- package/esm/internal/SyncEngine.d.ts +29 -3
- package/esm/internal/SyncEngine.js +31 -5
- package/esm/internal/SyncEngine.js.map +1 -1
- package/esm/useDbQuery.js +2 -0
- package/esm/useDbQuery.js.map +1 -1
- package/esm/util/promiseWithResolvers.js +3 -0
- package/esm/util/promiseWithResolvers.js.map +1 -1
- package/package.json +2 -1
package/esm/DbSync.js
CHANGED
|
@@ -3,115 +3,151 @@ import { EventBus } from "./internal/EventBus.js";
|
|
|
3
3
|
import { StorageManager } from "./internal/StorageManager.js";
|
|
4
4
|
import { SyncEngine } from "./internal/SyncEngine.js";
|
|
5
5
|
import { genUuid } from "./internal/utils.js";
|
|
6
|
+
/**
|
|
7
|
+
* The public facade for the dbsync engine.
|
|
8
|
+
*/
|
|
6
9
|
export class DbSync {
|
|
10
|
+
/** The polling interval used by the sync engine in milliseconds. */
|
|
7
11
|
syncInterval = 5000;
|
|
12
|
+
/** The active configuration passed by the consumer. */
|
|
8
13
|
config;
|
|
9
|
-
|
|
14
|
+
/** The event bus used for local and cross-tab notifications. */
|
|
10
15
|
events;
|
|
16
|
+
/** The storage manager handling IndexedDB state and transactions. */
|
|
11
17
|
storage; // Public for tests currently (we can wrap it later)
|
|
18
|
+
/** The engine responsible for network synchronization. */
|
|
12
19
|
syncEngine;
|
|
20
|
+
/** The manager handling authentication and logout/reset behavior. */
|
|
13
21
|
authManager;
|
|
22
|
+
/**
|
|
23
|
+
* Creates a new `DbSync` instance using the supplied configuration.
|
|
24
|
+
*
|
|
25
|
+
* @param config The backend adapter, schema version, and table definitions.
|
|
26
|
+
*/
|
|
14
27
|
constructor(config) {
|
|
15
28
|
this.config = config;
|
|
16
29
|
this.events = new EventBus();
|
|
17
30
|
const adapter = config.adapter;
|
|
18
31
|
const onSchemaChange = () => this.onSchemaChangeDetected();
|
|
19
32
|
this.storage = new StorageManager(config, this.events, onSchemaChange);
|
|
20
|
-
this.authManager = new AuthManager(adapter, this.storage, () => this.
|
|
33
|
+
this.authManager = new AuthManager(adapter, this.storage, () => { void this.stop(); });
|
|
21
34
|
this.syncEngine = new SyncEngine(config, this.syncInterval, this.events, this.storage, this.authManager, adapter, onSchemaChange);
|
|
22
35
|
}
|
|
23
|
-
|
|
36
|
+
/** Returns a fresh RFC-4122 UUID. */
|
|
24
37
|
genUuid() {
|
|
25
38
|
return genUuid();
|
|
26
39
|
}
|
|
27
|
-
|
|
40
|
+
/** Whether the storage layer has finished initializing. */
|
|
28
41
|
get initted() {
|
|
29
42
|
return this.storage.initted;
|
|
30
43
|
}
|
|
44
|
+
/** Initializes the underlying IndexedDB stores. */
|
|
31
45
|
async init() {
|
|
32
46
|
return this.storage.init();
|
|
33
47
|
}
|
|
48
|
+
/** Returns a queued transaction object for batched writes. */
|
|
34
49
|
getTransaction() {
|
|
35
50
|
return this.storage.getTransaction();
|
|
36
51
|
} // Exported temporarily for tests
|
|
52
|
+
/** Reads a typed record by primary key. */
|
|
37
53
|
async get(storeName, id) {
|
|
38
54
|
return this.storage.get(storeName, id);
|
|
39
55
|
}
|
|
56
|
+
/** Reads all records from the given object store. */
|
|
40
57
|
async findAll(storeName) {
|
|
41
58
|
return this.storage.findAll(storeName);
|
|
42
59
|
}
|
|
60
|
+
/** Inserts a new record into the given object store. */
|
|
43
61
|
async add(storeName, value, key) {
|
|
44
62
|
await this.storage.executeTransaction([{ type: "add", storeName, value, key }]);
|
|
45
63
|
return value;
|
|
46
64
|
}
|
|
65
|
+
/** Upserts a record into the given object store. */
|
|
47
66
|
async put(storeName, value, key) {
|
|
48
67
|
await this.storage.executeTransaction([{ type: "put", storeName, value, key }]);
|
|
49
68
|
return value;
|
|
50
69
|
}
|
|
70
|
+
/** Deletes a record from the given object store. */
|
|
51
71
|
async delete(storeName, key) {
|
|
52
72
|
await this.storage.executeTransaction([{ type: "delete", storeName, key }]);
|
|
53
73
|
}
|
|
74
|
+
/** Clears all records from the given object store. */
|
|
54
75
|
async clear(storeName) {
|
|
55
76
|
await this.storage.executeTransaction([{ type: "clear", storeName }]);
|
|
56
77
|
}
|
|
57
|
-
|
|
78
|
+
/** Subscribes to store update notifications. */
|
|
58
79
|
subscribe(callback) {
|
|
59
80
|
return this.events.subscribe(callback);
|
|
60
81
|
}
|
|
82
|
+
/** Subscribes to sync state changes. */
|
|
61
83
|
onSyncStateChange(callback) {
|
|
62
84
|
return this.events.onSyncStateChange(callback);
|
|
63
85
|
}
|
|
64
|
-
|
|
86
|
+
/** Whether the current backend session is authenticated. */
|
|
65
87
|
get isAuth() {
|
|
66
88
|
return this.authManager.isAuth;
|
|
67
89
|
}
|
|
90
|
+
/** Verifies authentication against the backend adapter. */
|
|
68
91
|
async checkAuth() {
|
|
69
92
|
return this.authManager.checkAuth();
|
|
70
93
|
}
|
|
94
|
+
/** Logs in with the given credentials. */
|
|
71
95
|
async login(email, code) {
|
|
72
96
|
return this.authManager.login(email, code);
|
|
73
97
|
}
|
|
98
|
+
/** Logs out and clears auth state. */
|
|
74
99
|
async logout() {
|
|
75
100
|
return this.authManager.logout();
|
|
76
101
|
}
|
|
102
|
+
/** Logs out and clears the local database. */
|
|
77
103
|
async reset() {
|
|
78
104
|
return this.authManager.reset();
|
|
79
105
|
}
|
|
80
|
-
|
|
81
|
-
get
|
|
82
|
-
return this.syncEngine.
|
|
106
|
+
/** Whether background sync is currently enabled. */
|
|
107
|
+
get isStarted() {
|
|
108
|
+
return this.syncEngine.isStarted;
|
|
83
109
|
}
|
|
110
|
+
/** Whether the sync engine has recently connected successfully. */
|
|
84
111
|
get isLive() {
|
|
85
112
|
return this.syncEngine.isLive;
|
|
86
113
|
}
|
|
87
|
-
|
|
88
|
-
|
|
114
|
+
/** Starts periodic background synchronization. */
|
|
115
|
+
async start() {
|
|
116
|
+
if (!this.initted)
|
|
117
|
+
await this.init();
|
|
118
|
+
this.syncEngine.start();
|
|
89
119
|
}
|
|
90
|
-
|
|
91
|
-
|
|
120
|
+
/** Stops periodic background synchronization. */
|
|
121
|
+
async stop() {
|
|
122
|
+
this.syncEngine.stop();
|
|
92
123
|
}
|
|
124
|
+
/** Waits until the sync engine reports a live connection. */
|
|
93
125
|
async waitForLive() {
|
|
94
126
|
return this.syncEngine.waitForLive();
|
|
95
127
|
}
|
|
128
|
+
/** Triggers a single sync cycle immediately. */
|
|
96
129
|
async triggerSync() {
|
|
97
130
|
return this.syncEngine.triggerSync();
|
|
98
131
|
}
|
|
99
|
-
|
|
132
|
+
/** Legacy alias for `enable()`. */
|
|
100
133
|
startSyncInterval() {
|
|
101
|
-
this.
|
|
134
|
+
this.start();
|
|
102
135
|
}
|
|
136
|
+
/** Legacy alias for `disable()`. */
|
|
103
137
|
stopSyncInterval() {
|
|
104
|
-
this.
|
|
138
|
+
this.stop();
|
|
105
139
|
}
|
|
140
|
+
/** Responds to schema changes by disposing state and reloading the page. */
|
|
106
141
|
onSchemaChangeDetected() {
|
|
107
142
|
this.storage.dispose();
|
|
108
|
-
this.
|
|
143
|
+
this.stop();
|
|
109
144
|
if (typeof window !== "undefined") {
|
|
110
145
|
window.location.reload();
|
|
111
146
|
}
|
|
112
147
|
}
|
|
148
|
+
/** Disposes all background resources and event listeners. */
|
|
113
149
|
dispose() {
|
|
114
|
-
this.
|
|
150
|
+
this.stop();
|
|
115
151
|
this.events.dispose();
|
|
116
152
|
this.storage.dispose();
|
|
117
153
|
}
|
package/esm/DbSync.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DbSync.js","sourceRoot":"","sources":["../src/DbSync.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAA;AACvD,OAAO,EAAE,QAAQ,EAAkB,MAAM,wBAAwB,CAAA;AACjE,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAA;AAC7D,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAA;AACrD,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;
|
|
1
|
+
{"version":3,"file":"DbSync.js","sourceRoot":"","sources":["../src/DbSync.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,13 +1,30 @@
|
|
|
1
1
|
import type { BackendAdapter, SyncPullResult } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Configuration for the built-in REST adapter.
|
|
4
|
+
*/
|
|
2
5
|
export interface RestAdapterConfig {
|
|
6
|
+
/** The base URL of the remote API. */
|
|
3
7
|
url: string;
|
|
4
8
|
}
|
|
9
|
+
/**
|
|
10
|
+
* A REST-backed implementation of the backend adapter contract.
|
|
11
|
+
*/
|
|
5
12
|
export declare class RestAdapter implements BackendAdapter {
|
|
6
13
|
private config;
|
|
14
|
+
/**
|
|
15
|
+
* Stores the adapter configuration, including the API base URL.
|
|
16
|
+
*
|
|
17
|
+
* @param config The REST adapter configuration.
|
|
18
|
+
*/
|
|
7
19
|
constructor(config: RestAdapterConfig);
|
|
20
|
+
/** Checks whether the server session cookie is currently authenticated. */
|
|
8
21
|
checkAuth(): Promise<boolean>;
|
|
22
|
+
/** Logs the user in using an email/code pair. */
|
|
9
23
|
login(email: string, code: string): Promise<boolean>;
|
|
24
|
+
/** Logs the current user out of the remote session. */
|
|
10
25
|
logout(): Promise<void>;
|
|
26
|
+
/** Pulls remote records from the REST backend using the provided cursor. */
|
|
11
27
|
pull(cursor: string): Promise<SyncPullResult>;
|
|
28
|
+
/** Pushes queued local mutations to the REST backend. */
|
|
12
29
|
push(payload: any[]): Promise<void>;
|
|
13
30
|
}
|
|
@@ -1,12 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A REST-backed implementation of the backend adapter contract.
|
|
3
|
+
*/
|
|
1
4
|
export class RestAdapter {
|
|
2
5
|
config;
|
|
6
|
+
/**
|
|
7
|
+
* Stores the adapter configuration, including the API base URL.
|
|
8
|
+
*
|
|
9
|
+
* @param config The REST adapter configuration.
|
|
10
|
+
*/
|
|
3
11
|
constructor(config) {
|
|
4
12
|
this.config = config;
|
|
5
13
|
}
|
|
14
|
+
/** Checks whether the server session cookie is currently authenticated. */
|
|
6
15
|
async checkAuth() {
|
|
7
16
|
const res = await fetch(`${this.config.url}/api/session`, { credentials: "include" });
|
|
8
17
|
return res.ok;
|
|
9
18
|
}
|
|
19
|
+
/** Logs the user in using an email/code pair. */
|
|
10
20
|
async login(email, code) {
|
|
11
21
|
const res = await fetch(`${this.config.url}/api/session/login`, {
|
|
12
22
|
method: "POST",
|
|
@@ -18,9 +28,11 @@ export class RestAdapter {
|
|
|
18
28
|
throw new Error("Login failed");
|
|
19
29
|
return true;
|
|
20
30
|
}
|
|
31
|
+
/** Logs the current user out of the remote session. */
|
|
21
32
|
async logout() {
|
|
22
33
|
await fetch(`${this.config.url}/api/session/logout`, { method: "POST", credentials: "include" });
|
|
23
34
|
}
|
|
35
|
+
/** Pulls remote records from the REST backend using the provided cursor. */
|
|
24
36
|
async pull(cursor) {
|
|
25
37
|
const res = await fetch(`${this.config.url}/api/posts?after=${cursor}&limit=40`, {
|
|
26
38
|
credentials: "include",
|
|
@@ -29,6 +41,7 @@ export class RestAdapter {
|
|
|
29
41
|
throw { status: res.status };
|
|
30
42
|
return await res.json();
|
|
31
43
|
}
|
|
44
|
+
/** Pushes queued local mutations to the REST backend. */
|
|
32
45
|
async push(payload) {
|
|
33
46
|
const res = await fetch(`${this.config.url}/api/posts/upsert-many`, {
|
|
34
47
|
method: "POST",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RestAdapter.js","sourceRoot":"","sources":["../../src/adapters/RestAdapter.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"RestAdapter.js","sourceRoot":"","sources":["../../src/adapters/RestAdapter.ts"],"names":[],"mappings":"AAUA;;GAEG;AACH,MAAM,OAAO,WAAW;IAMH;IALpB;;;;OAIG;IACH,YAAoB,MAAyB;QAAzB,WAAM,GAAN,MAAM,CAAmB;IAAG,CAAC;IAEjD,2EAA2E;IACpE,KAAK,CAAC,SAAS;QACrB,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,cAAc,EAAE,EAAE,WAAW,EAAE,SAAS,EAAE,CAAC,CAAA;QACrF,OAAO,GAAG,CAAC,EAAE,CAAA;IACd,CAAC;IAED,iDAAiD;IAC1C,KAAK,CAAC,KAAK,CAAC,KAAa,EAAE,IAAY;QAC7C,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,oBAAoB,EAAE;YAC/D,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;YAC/C,WAAW,EAAE,SAAS;YACtB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;SACrC,CAAC,CAAA;QACF,IAAI,CAAC,GAAG,CAAC,EAAE;YAAE,MAAM,IAAI,KAAK,CAAC,cAAc,CAAC,CAAA;QAC5C,OAAO,IAAI,CAAA;IACZ,CAAC;IAED,uDAAuD;IAChD,KAAK,CAAC,MAAM;QAClB,MAAM,KAAK,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,qBAAqB,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,SAAS,EAAE,CAAC,CAAA;IACjG,CAAC;IAED,4EAA4E;IACrE,KAAK,CAAC,IAAI,CAAC,MAAc;QAC/B,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,oBAAoB,MAAM,WAAW,EAAE;YAChF,WAAW,EAAE,SAAS;SACtB,CAAC,CAAA;QACF,IAAI,CAAC,GAAG,CAAC,EAAE;YAAE,MAAM,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,CAAA;QACzC,OAAO,MAAM,GAAG,CAAC,IAAI,EAAE,CAAA;IACxB,CAAC;IAED,yDAAyD;IAClD,KAAK,CAAC,IAAI,CAAC,OAAc;QAC/B,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,wBAAwB,EAAE;YACnE,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;YAC/C,WAAW,EAAE,SAAS;YACtB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC;SAC7B,CAAC,CAAA;QACF,IAAI,CAAC,GAAG,CAAC,EAAE;YAAE,MAAM,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,CAAA;IAC1C,CAAC;CACD"}
|
package/esm/adapters/types.d.ts
CHANGED
|
@@ -1,11 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The standard response shape returned by a backend pull request.
|
|
3
|
+
*/
|
|
1
4
|
export interface SyncPullResult {
|
|
5
|
+
/** The records fetched from the remote backend. */
|
|
2
6
|
items: any[];
|
|
7
|
+
/** Whether more results remain to be fetched for the current cursor. */
|
|
3
8
|
hasMore: boolean;
|
|
4
9
|
}
|
|
10
|
+
/**
|
|
11
|
+
* The contract implemented by all sync backends.
|
|
12
|
+
*/
|
|
5
13
|
export interface BackendAdapter {
|
|
14
|
+
/** Checks whether the current session is authenticated. */
|
|
6
15
|
checkAuth(): Promise<boolean>;
|
|
16
|
+
/** Logs the current user in against the backend. */
|
|
7
17
|
login(email: string, code: string): Promise<boolean>;
|
|
18
|
+
/** Logs the current user out of the backend. */
|
|
8
19
|
logout(): Promise<void>;
|
|
20
|
+
/** Pulls remote changes since the provided cursor. */
|
|
9
21
|
pull(cursor: string): Promise<SyncPullResult>;
|
|
22
|
+
/** Pushes queued local mutations to the backend. */
|
|
10
23
|
push(payload: any[]): Promise<void>;
|
|
11
24
|
}
|
|
@@ -1,13 +1,28 @@
|
|
|
1
1
|
import type { BackendAdapter } from "../adapters/types.js";
|
|
2
2
|
import type { StorageManager } from "./StorageManager.js";
|
|
3
|
+
/**
|
|
4
|
+
* Coordinates authentication state and logout/reset behavior for `DbSync`.
|
|
5
|
+
*/
|
|
3
6
|
export declare class AuthManager {
|
|
4
7
|
private adapter;
|
|
5
8
|
private storage;
|
|
6
|
-
private
|
|
9
|
+
private stopSync;
|
|
10
|
+
/** Tracks whether the current backend session is authenticated. */
|
|
7
11
|
isAuth: boolean;
|
|
8
|
-
|
|
12
|
+
/**
|
|
13
|
+
* Creates a new auth manager for the provided backend adapter and storage layer.
|
|
14
|
+
*
|
|
15
|
+
* @param adapter The backend adapter used for auth requests.
|
|
16
|
+
* @param storage The storage manager used for reset operations.
|
|
17
|
+
* @param stopSync The callback used to stop background sync.
|
|
18
|
+
*/
|
|
19
|
+
constructor(adapter: BackendAdapter, storage: StorageManager, stopSync: () => Promise<void> | void);
|
|
20
|
+
/** Checks authentication against the backend adapter and stores the result. */
|
|
9
21
|
checkAuth(): Promise<boolean>;
|
|
22
|
+
/** Logs in through the backend adapter and updates auth state. */
|
|
10
23
|
login(email: string, code: string): Promise<void>;
|
|
24
|
+
/** Logs out, stops sync, and clears auth state. */
|
|
11
25
|
logout(): Promise<void>;
|
|
26
|
+
/** Logs out and clears all local IndexedDB stores and auth markers. */
|
|
12
27
|
reset(): Promise<void>;
|
|
13
28
|
}
|
|
@@ -1,25 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Coordinates authentication state and logout/reset behavior for `DbSync`.
|
|
3
|
+
*/
|
|
1
4
|
export class AuthManager {
|
|
2
5
|
adapter;
|
|
3
6
|
storage;
|
|
4
|
-
|
|
7
|
+
stopSync;
|
|
8
|
+
/** Tracks whether the current backend session is authenticated. */
|
|
5
9
|
isAuth = false;
|
|
6
|
-
|
|
10
|
+
/**
|
|
11
|
+
* Creates a new auth manager for the provided backend adapter and storage layer.
|
|
12
|
+
*
|
|
13
|
+
* @param adapter The backend adapter used for auth requests.
|
|
14
|
+
* @param storage The storage manager used for reset operations.
|
|
15
|
+
* @param stopSync The callback used to stop background sync.
|
|
16
|
+
*/
|
|
17
|
+
constructor(adapter, storage, stopSync) {
|
|
7
18
|
this.adapter = adapter;
|
|
8
19
|
this.storage = storage;
|
|
9
|
-
this.
|
|
20
|
+
this.stopSync = stopSync;
|
|
10
21
|
}
|
|
22
|
+
/** Checks authentication against the backend adapter and stores the result. */
|
|
11
23
|
async checkAuth() {
|
|
12
24
|
this.isAuth = await this.adapter.checkAuth();
|
|
13
25
|
return this.isAuth;
|
|
14
26
|
}
|
|
27
|
+
/** Logs in through the backend adapter and updates auth state. */
|
|
15
28
|
async login(email, code) {
|
|
16
29
|
this.isAuth = await this.adapter.login(email, code);
|
|
17
30
|
}
|
|
31
|
+
/** Logs out, stops sync, and clears auth state. */
|
|
18
32
|
async logout() {
|
|
19
|
-
this.
|
|
33
|
+
await this.stopSync();
|
|
20
34
|
this.isAuth = false;
|
|
21
35
|
await this.adapter.logout();
|
|
22
36
|
}
|
|
37
|
+
/** Logs out and clears all local IndexedDB stores and auth markers. */
|
|
23
38
|
async reset() {
|
|
24
39
|
await this.logout();
|
|
25
40
|
await this.storage.clearAllStores();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AuthManager.js","sourceRoot":"","sources":["../../src/internal/AuthManager.ts"],"names":[],"mappings":"AAGA,MAAM,OAAO,WAAW;
|
|
1
|
+
{"version":3,"file":"AuthManager.js","sourceRoot":"","sources":["../../src/internal/AuthManager.ts"],"names":[],"mappings":"AAGA;;GAEG;AACH,MAAM,OAAO,WAAW;IAYd;IACA;IACA;IAbT,mEAAmE;IAC5D,MAAM,GAAG,KAAK,CAAA;IAErB;;;;;;OAMG;IACH,YACS,OAAuB,EACvB,OAAuB,EACvB,QAAoC;QAFpC,YAAO,GAAP,OAAO,CAAgB;QACvB,YAAO,GAAP,OAAO,CAAgB;QACvB,aAAQ,GAAR,QAAQ,CAA4B;IAC1C,CAAC;IAEJ,+EAA+E;IACxE,KAAK,CAAC,SAAS;QACrB,IAAI,CAAC,MAAM,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,CAAA;QAC5C,OAAO,IAAI,CAAC,MAAM,CAAA;IACnB,CAAC;IAED,kEAAkE;IAC3D,KAAK,CAAC,KAAK,CAAC,KAAa,EAAE,IAAY;QAC7C,IAAI,CAAC,MAAM,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,IAAI,CAAC,CAAA;IACpD,CAAC;IAED,mDAAmD;IAC5C,KAAK,CAAC,MAAM;QAClB,MAAM,IAAI,CAAC,QAAQ,EAAE,CAAA;QACrB,IAAI,CAAC,MAAM,GAAG,KAAK,CAAA;QACnB,MAAM,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAA;IAC5B,CAAC;IAED,uEAAuE;IAChE,KAAK,CAAC,KAAK;QACjB,MAAM,IAAI,CAAC,MAAM,EAAE,CAAA;QACnB,MAAM,IAAI,CAAC,OAAO,CAAC,cAAc,EAAE,CAAA;QACnC,YAAY,CAAC,UAAU,CAAC,sBAAsB,CAAC,CAAA;QAC/C,YAAY,CAAC,UAAU,CAAC,uBAAuB,CAAC,CAAA;IACjD,CAAC;CACD"}
|
|
@@ -1,16 +1,28 @@
|
|
|
1
1
|
export type SyncState = "idle" | "syncing" | "offline" | "error";
|
|
2
|
+
/**
|
|
3
|
+
* Broadcasts store updates and sync state changes to local subscribers.
|
|
4
|
+
*/
|
|
2
5
|
export declare class EventBus {
|
|
6
|
+
/** Subscribers that listen for store updates. */
|
|
3
7
|
private subscribers;
|
|
8
|
+
/** Subscribers that listen for sync state transitions. */
|
|
4
9
|
private stateListeners;
|
|
10
|
+
/** Broadcast channel used to mirror updates across tabs. */
|
|
5
11
|
private bc;
|
|
12
|
+
/** Initializes the broadcast listener for cross-tab update propagation. */
|
|
6
13
|
constructor();
|
|
14
|
+
/** Adds a store-update subscriber and returns a handle for removing it. */
|
|
7
15
|
subscribe(callback: (stores: string[]) => void): {
|
|
8
16
|
close: () => boolean;
|
|
9
17
|
};
|
|
18
|
+
/** Notifies all store subscribers and mirrors the update to other tabs. */
|
|
10
19
|
notifySubscribers(stores: string[]): void;
|
|
20
|
+
/** Adds a sync-state subscriber and returns a handle for removing it. */
|
|
11
21
|
onSyncStateChange(callback: (state: SyncState) => void): {
|
|
12
22
|
close: () => boolean;
|
|
13
23
|
};
|
|
24
|
+
/** Broadcasts a sync-state transition to all subscribers. */
|
|
14
25
|
setState(state: SyncState): void;
|
|
26
|
+
/** Tears down the broadcast channel and stops cross-tab propagation. */
|
|
15
27
|
dispose(): void;
|
|
16
28
|
}
|
package/esm/internal/EventBus.js
CHANGED
|
@@ -1,7 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Broadcasts store updates and sync state changes to local subscribers.
|
|
3
|
+
*/
|
|
1
4
|
export class EventBus {
|
|
5
|
+
/** Subscribers that listen for store updates. */
|
|
2
6
|
subscribers = new Set();
|
|
7
|
+
/** Subscribers that listen for sync state transitions. */
|
|
3
8
|
stateListeners = new Set();
|
|
9
|
+
/** Broadcast channel used to mirror updates across tabs. */
|
|
4
10
|
bc = typeof BroadcastChannel !== "undefined" ? new BroadcastChannel("dbsync_events") : null;
|
|
11
|
+
/** Initializes the broadcast listener for cross-tab update propagation. */
|
|
5
12
|
constructor() {
|
|
6
13
|
if (this.bc) {
|
|
7
14
|
this.bc.onmessage = (e) => {
|
|
@@ -11,22 +18,27 @@ export class EventBus {
|
|
|
11
18
|
};
|
|
12
19
|
}
|
|
13
20
|
}
|
|
21
|
+
/** Adds a store-update subscriber and returns a handle for removing it. */
|
|
14
22
|
subscribe(callback) {
|
|
15
23
|
this.subscribers.add(callback);
|
|
16
24
|
return { close: () => this.subscribers.delete(callback) };
|
|
17
25
|
}
|
|
26
|
+
/** Notifies all store subscribers and mirrors the update to other tabs. */
|
|
18
27
|
notifySubscribers(stores) {
|
|
19
28
|
this.subscribers.forEach((cb) => cb(stores));
|
|
20
29
|
if (this.bc)
|
|
21
30
|
this.bc.postMessage({ type: "DATA_UPDATED", stores });
|
|
22
31
|
}
|
|
32
|
+
/** Adds a sync-state subscriber and returns a handle for removing it. */
|
|
23
33
|
onSyncStateChange(callback) {
|
|
24
34
|
this.stateListeners.add(callback);
|
|
25
35
|
return { close: () => this.stateListeners.delete(callback) };
|
|
26
36
|
}
|
|
37
|
+
/** Broadcasts a sync-state transition to all subscribers. */
|
|
27
38
|
setState(state) {
|
|
28
39
|
this.stateListeners.forEach((cb) => cb(state));
|
|
29
40
|
}
|
|
41
|
+
/** Tears down the broadcast channel and stops cross-tab propagation. */
|
|
30
42
|
dispose() {
|
|
31
43
|
if (this.bc) {
|
|
32
44
|
this.bc.close();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EventBus.js","sourceRoot":"","sources":["../../src/internal/EventBus.ts"],"names":[],"mappings":"AAEA,MAAM,OAAO,QAAQ;
|
|
1
|
+
{"version":3,"file":"EventBus.js","sourceRoot":"","sources":["../../src/internal/EventBus.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,MAAM,OAAO,QAAQ;IACpB,iDAAiD;IACzC,WAAW,GAAG,IAAI,GAAG,EAA8B,CAAA;IAC3D,0DAA0D;IAClD,cAAc,GAAG,IAAI,GAAG,EAA8B,CAAA;IAC9D,4DAA4D;IACpD,EAAE,GACT,OAAO,gBAAgB,KAAK,WAAW,CAAC,CAAC,CAAC,IAAI,gBAAgB,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA;IAEvF,2EAA2E;IAC3E;QACC,IAAI,IAAI,CAAC,EAAE,EAAE,CAAC;YACb,IAAI,CAAC,EAAE,CAAC,SAAS,GAAG,CAAC,CAAC,EAAE,EAAE;gBACzB,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,KAAK,cAAc,EAAE,CAAC;oBACpC,IAAI,CAAC,iBAAiB,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;gBACtC,CAAC;YACF,CAAC,CAAA;QACF,CAAC;IACF,CAAC;IAED,2EAA2E;IACpE,SAAS,CAAC,QAAoC;QACpD,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;QAC9B,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAA;IAC1D,CAAC;IAED,2EAA2E;IACpE,iBAAiB,CAAC,MAAgB;QACxC,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAA;QAC5C,IAAI,IAAI,CAAC,EAAE;YAAE,IAAI,CAAC,EAAE,CAAC,WAAW,CAAC,EAAE,IAAI,EAAE,cAAc,EAAE,MAAM,EAAE,CAAC,CAAA;IACnE,CAAC;IAED,yEAAyE;IAClE,iBAAiB,CAAC,QAAoC;QAC5D,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;QACjC,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAA;IAC7D,CAAC;IAED,6DAA6D;IACtD,QAAQ,CAAC,KAAgB;QAC/B,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAA;IAC/C,CAAC;IAED,wEAAwE;IACjE,OAAO;QACb,IAAI,IAAI,CAAC,EAAE,EAAE,CAAC;YACb,IAAI,CAAC,EAAE,CAAC,KAAK,EAAE,CAAA;YACf,IAAI,CAAC,EAAE,GAAG,IAAI,CAAA;QACf,CAAC;IACF,CAAC;CACD"}
|
|
@@ -1,20 +1,41 @@
|
|
|
1
1
|
import type { DbSyncConfig } from "../DbSync.js";
|
|
2
2
|
import { DbTransaction } from "./DbTransaction.js";
|
|
3
3
|
import type { EventBus } from "./EventBus.js";
|
|
4
|
+
/**
|
|
5
|
+
* Owns IndexedDB initialization, transactions, and record access.
|
|
6
|
+
*/
|
|
4
7
|
export declare class StorageManager {
|
|
5
8
|
private config;
|
|
6
9
|
private events;
|
|
7
10
|
private onSchemaChange;
|
|
11
|
+
/** The active IndexedDB database instance. */
|
|
8
12
|
db: IDBDatabase;
|
|
13
|
+
/** Whether the storage layer has finished initializing. */
|
|
9
14
|
initted: boolean;
|
|
15
|
+
/** The IndexedDB database name used by dbsync. */
|
|
10
16
|
private dbName;
|
|
17
|
+
/**
|
|
18
|
+
* Creates a storage manager for the provided dbsync configuration and event bus.
|
|
19
|
+
*
|
|
20
|
+
* @param config The full dbsync configuration object.
|
|
21
|
+
* @param events The event bus used to broadcast store updates.
|
|
22
|
+
* @param onSchemaChange Callback fired when the IndexedDB schema changes.
|
|
23
|
+
*/
|
|
11
24
|
constructor(config: DbSyncConfig, events: EventBus, onSchemaChange: () => void);
|
|
25
|
+
/** Computes a deterministic schema signature from the configured tables and indexes. */
|
|
12
26
|
private get schemaSignature();
|
|
27
|
+
/** Creates a transaction wrapper used by the sync engine and public facade. */
|
|
13
28
|
getTransaction(): DbTransaction;
|
|
29
|
+
/** Opens IndexedDB and creates the configured stores when needed. */
|
|
14
30
|
init(): Promise<void>;
|
|
31
|
+
/** Executes a batch of writes inside a single IndexedDB transaction. */
|
|
15
32
|
executeTransaction(operations: any[]): Promise<void>;
|
|
33
|
+
/** Reads a typed record by primary key from the requested store. */
|
|
16
34
|
get<T>(storeName: string, id: string | number): Promise<T | undefined>;
|
|
35
|
+
/** Returns every record from the requested store. */
|
|
17
36
|
findAll<T>(storeName: string): Promise<T[]>;
|
|
37
|
+
/** Clears every object store managed by the database. */
|
|
18
38
|
clearAllStores(): Promise<void>;
|
|
39
|
+
/** Closes the underlying IndexedDB connection. */
|
|
19
40
|
dispose(): void;
|
|
20
41
|
}
|
|
@@ -1,17 +1,31 @@
|
|
|
1
1
|
import { promiseWithResolvers } from "../util/promiseWithResolvers.js";
|
|
2
2
|
import { DbTransaction } from "./DbTransaction.js";
|
|
3
|
+
/**
|
|
4
|
+
* Owns IndexedDB initialization, transactions, and record access.
|
|
5
|
+
*/
|
|
3
6
|
export class StorageManager {
|
|
4
7
|
config;
|
|
5
8
|
events;
|
|
6
9
|
onSchemaChange;
|
|
10
|
+
/** The active IndexedDB database instance. */
|
|
7
11
|
db;
|
|
12
|
+
/** Whether the storage layer has finished initializing. */
|
|
8
13
|
initted = false;
|
|
14
|
+
/** The IndexedDB database name used by dbsync. */
|
|
9
15
|
dbName = "dbsync";
|
|
16
|
+
/**
|
|
17
|
+
* Creates a storage manager for the provided dbsync configuration and event bus.
|
|
18
|
+
*
|
|
19
|
+
* @param config The full dbsync configuration object.
|
|
20
|
+
* @param events The event bus used to broadcast store updates.
|
|
21
|
+
* @param onSchemaChange Callback fired when the IndexedDB schema changes.
|
|
22
|
+
*/
|
|
10
23
|
constructor(config, events, onSchemaChange) {
|
|
11
24
|
this.config = config;
|
|
12
25
|
this.events = events;
|
|
13
26
|
this.onSchemaChange = onSchemaChange;
|
|
14
27
|
}
|
|
28
|
+
/** Computes a deterministic schema signature from the configured tables and indexes. */
|
|
15
29
|
get schemaSignature() {
|
|
16
30
|
const tables = Object.keys(this.config.tables)
|
|
17
31
|
.sort()
|
|
@@ -23,9 +37,11 @@ export class StorageManager {
|
|
|
23
37
|
});
|
|
24
38
|
return JSON.stringify(tables);
|
|
25
39
|
}
|
|
40
|
+
/** Creates a transaction wrapper used by the sync engine and public facade. */
|
|
26
41
|
getTransaction() {
|
|
27
42
|
return new DbTransaction((operations) => this.executeTransaction(operations));
|
|
28
43
|
}
|
|
44
|
+
/** Opens IndexedDB and creates the configured stores when needed. */
|
|
29
45
|
async init() {
|
|
30
46
|
const { promise, resolve, reject } = promiseWithResolvers();
|
|
31
47
|
const upgradeFn = (e) => {
|
|
@@ -68,6 +84,7 @@ export class StorageManager {
|
|
|
68
84
|
req.onerror = () => reject(req.error);
|
|
69
85
|
return promise;
|
|
70
86
|
}
|
|
87
|
+
/** Executes a batch of writes inside a single IndexedDB transaction. */
|
|
71
88
|
async executeTransaction(operations) {
|
|
72
89
|
const storeNames = Array.from(new Set(operations.map((o) => o.storeName))).concat([
|
|
73
90
|
"dirtyQueue",
|
|
@@ -111,6 +128,7 @@ export class StorageManager {
|
|
|
111
128
|
});
|
|
112
129
|
return promise;
|
|
113
130
|
}
|
|
131
|
+
/** Reads a typed record by primary key from the requested store. */
|
|
114
132
|
async get(storeName, id) {
|
|
115
133
|
const { promise, resolve, reject } = promiseWithResolvers();
|
|
116
134
|
const tx = this.db.transaction(storeName, "readonly");
|
|
@@ -119,6 +137,7 @@ export class StorageManager {
|
|
|
119
137
|
req.onerror = () => reject(req.error);
|
|
120
138
|
return promise;
|
|
121
139
|
}
|
|
140
|
+
/** Returns every record from the requested store. */
|
|
122
141
|
async findAll(storeName) {
|
|
123
142
|
const { promise, resolve, reject } = promiseWithResolvers();
|
|
124
143
|
const tx = this.db.transaction(storeName, "readonly");
|
|
@@ -127,6 +146,7 @@ export class StorageManager {
|
|
|
127
146
|
req.onerror = () => reject(req.error);
|
|
128
147
|
return promise;
|
|
129
148
|
}
|
|
149
|
+
/** Clears every object store managed by the database. */
|
|
130
150
|
async clearAllStores() {
|
|
131
151
|
const tx = this.db.transaction(Array.from(this.db.objectStoreNames), "readwrite");
|
|
132
152
|
Array.from(this.db.objectStoreNames).forEach((name) => tx.objectStore(name).clear());
|
|
@@ -135,6 +155,7 @@ export class StorageManager {
|
|
|
135
155
|
tx.onerror = () => reject(tx.error);
|
|
136
156
|
});
|
|
137
157
|
}
|
|
158
|
+
/** Closes the underlying IndexedDB connection. */
|
|
138
159
|
dispose() {
|
|
139
160
|
if (this.db) {
|
|
140
161
|
this.db.close();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"StorageManager.js","sourceRoot":"","sources":["../../src/internal/StorageManager.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAA;AACtE,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAGlD,MAAM,OAAO,cAAc;
|
|
1
|
+
{"version":3,"file":"StorageManager.js","sourceRoot":"","sources":["../../src/internal/StorageManager.ts"],"names":[],"mappings":"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"}
|