@procedures/store 0.17.1 → 0.17.3

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/CHANGELOG.md CHANGED
@@ -1,5 +1,30 @@
1
1
  # @procedures/store
2
2
 
3
+ ## 0.17.3
4
+
5
+ ### Patch Changes
6
+
7
+ - d552672: Added: `IndexedDbStorage`, a collection storage in the IndexedDB of a browser (roadmap CLI-22). It is in `@procedures/store/indexeddb` and `@procedures/store/browser`. It is the durable local copy of a `HybridStorage` in a browser app without SignalDB.
8
+
9
+ - Each collection has its own database. The items, their order and the versions of `getChangesSince()` stay after a reload of the page.
10
+ - The entries keep the order of the first set of each id, as a `Map` does.
11
+ - Each write is one transaction of IndexedDB. A batch that fails changes nothing, and two patches at the same time keep each field.
12
+ - The storage has `getEntries()`, `getIds()`, `getChangesSince()`, `query()`, `observe()` and `patch()`. With the option `versionOf`, a write can expect the version of the current item.
13
+ - The storage checks each record that it reads. The contract suite of `@procedures/collections/testing` tests it.
14
+ - The entry `@procedures/store/indexeddb` still does not import the root of the client or zod.
15
+
16
+ PATCH: a new export that is backward compatible, before 1.0.0.
17
+ - @procedures/client@0.17.3
18
+ - @procedures/collections@0.17.3
19
+
20
+ ## 0.17.2
21
+
22
+ ### Patch Changes
23
+
24
+ - Updated dependencies [8b7e20c]
25
+ - @procedures/client@0.17.2
26
+ - @procedures/collections@0.17.2
27
+
3
28
  ## 0.17.1
4
29
 
5
30
  ### Patch Changes
package/README.md CHANGED
@@ -41,8 +41,9 @@ console.log(await client.exec(["math", "addTen"], { x: 5 })); // 15
41
41
 
42
42
  ### The stores of a browser
43
43
 
44
- The entry `@procedures/store/indexeddb` has the stores of a browser. The package root does not import it, and it does not import the client or zod.
44
+ The entry `@procedures/store/indexeddb` has the stores of a browser. The package root does not import it. It does not import the root of the client or zod.
45
45
 
46
+ - `IndexedDbStorage` is a collection storage in IndexedDB. Refer to "The collection storage of a browser".
46
47
  - `IndexedDbProgramStore` keeps the programs in one database, `procedures-programs` by default.
47
48
  - `IndexedDbQueueStore` keeps the queue of a `HybridStorage`. Give each storage its own database.
48
49
  - `hasIndexedDb()` tells if the browser has IndexedDB. `MemoryProgramStore` and `MemoryQueueStore` are the fallbacks.
@@ -111,6 +112,34 @@ Notes:
111
112
  - `HybridStorage.close()` waits for the operations, the switch and the syncs that run. Then it sends the queue, and it closes the remote and the local copy.
112
113
  - `SyncedProcedureRegistry.close()` closes its storage. After it, `register()` and `unregister()` change only the registry in memory.
113
114
 
115
+ ### The collection storage of a browser
116
+
117
+ `IndexedDbStorage` of `@procedures/store/indexeddb` keeps the items of one collection in IndexedDB (roadmap CLI-22). It is the durable local copy of a `HybridStorage` in a browser app without SignalDB.
118
+
119
+ - Give each collection its own database. The storage makes the database at the first operation.
120
+ - The items stay after `close()` and after a reload of the page. A new storage of the same database reads them.
121
+ - The entries keep the order of the first set of each id, as a `Map` does. Each record keeps the number of its first set.
122
+ - `getChangesSince()` gives the changes after a version. A version stays valid after a reload.
123
+ - Each write is one transaction of IndexedDB. A batch that fails changes nothing. Two patches at the same time keep each field.
124
+ - `query()` applies a selector. `patch()` changes an item in one transaction.
125
+ - `observe()` tells each write of this storage before the write resolves. It does not tell the writes of another tab.
126
+ - With the option `versionOf`, a write can expect the version of the current item. The test and the write are one transaction.
127
+ - The storage checks each record that it reads. A record of another application or of another version is an error.
128
+ - The contract suite of `@procedures/collections/testing` tests the storage, and a `HybridStorage` with the storage as its local copy.
129
+ - `InMemoryStorage` of `@procedures/collections` is the fallback for a browser without IndexedDB.
130
+
131
+ ```ts
132
+ import { ApiStorage, HybridStorage, IndexedDbQueueStore, IndexedDbStorage, IndexedDbSyncStateStore } from "@procedures/store/browser";
133
+
134
+ const versionOf = (user: User) => user.rev;
135
+ const users = new HybridStorage(new ApiStorage(client, { collection: "users" }), {
136
+ local: new IndexedDbStorage<User>("users", { versionOf }),
137
+ versionOf,
138
+ queueStore: new IndexedDbQueueStore("users-queue"),
139
+ syncState: new IndexedDbSyncStateStore("users-sync"),
140
+ });
141
+ ```
142
+
114
143
  ## The modes of `HybridStorage`
115
144
 
116
145
  `HybridStorage` keeps a local copy of a remote collection storage. It has four modes, and `setMode()` changes the mode while the storage operates.
@@ -163,10 +192,11 @@ await users.setMode("write-through"); // The switch sends the queue, then syncs
163
192
 
164
193
  - The option `local` gives the storage of the local copy. The default is a new `InMemoryStorage`.
165
194
  - A durable local copy keeps the items after a restart. `SqliteStorage` of `@procedures/sqlite` keeps them in a SQLite file.
195
+ - `IndexedDbStorage` of `@procedures/store/indexeddb` keeps them in the IndexedDB of a browser.
166
196
  - With a durable local copy, a new storage in `local-only` mode reads the items of the last run. It makes no remote call.
167
197
  - Give a durable `queueStore` with a durable local copy. A restart applies the loaded queue to the local copy again, and the result does not change.
168
198
  - The first sync after a restart reads all remote items. It removes each local item that the remote deleted and that no queued write changes.
169
- - A full sync reads the local ids with `getIds()` of the local copy. `InMemoryStorage` and `SqliteStorage` give the ids without a copy of the values. A local copy without `getIds()` gives its entries.
199
+ - A full sync reads the local ids with `getIds()` of the local copy. `InMemoryStorage`, `SqliteStorage` and `IndexedDbStorage` give the ids without a copy of the values. A local copy without `getIds()` gives its entries.
170
200
  - `HybridStorage.getIds()` gives the ids of the local copy, or of the remote in `remote-only` mode.
171
201
  - `close()` closes the local copy and the remote. A durable local copy keeps its items. A remote stays open when its own `close()` leaves it open, as `ApiStorage.close()` leaves the server.
172
202
 
@@ -244,7 +274,7 @@ const stop = users.onStatus((status) => {
244
274
 
245
275
  ### The changes, the capture, the sync state and the push feed
246
276
 
247
- `HybridStorage` is a sync engine for each local copy: `InMemoryStorage`, `SqliteStorage`, IndexedDB or a SignalDB collection (server stack D9, CLI-21, CLI-15).
277
+ `HybridStorage` is a sync engine for each local copy: `InMemoryStorage`, `SqliteStorage`, `IndexedDbStorage` or a SignalDB collection (server stack D9, CLI-21, CLI-15).
248
278
 
249
279
  - `observe(observer)` gives one batch of `set`, `delete` and `clear` changes for each change of the storage.
250
280
  - A write of the storage gives its batch with the `origin` of its options. A pull and a delta of the feed give their changes with the origin `syncOrigin`, `"sync"` by default.
@@ -311,7 +341,7 @@ The entry `@procedures/store/browser` has the parts of the store that run in a b
311
341
  - `HybridStorage`, its errors and its types.
312
342
  - `ApiStorage`, the remote storage over the collection procedures of a server.
313
343
  - `EventsChangeFeed`, the push feed of the remote changes.
314
- - All of `@procedures/store/indexeddb`: the IndexedDB stores and their fallbacks in memory.
344
+ - All of `@procedures/store/indexeddb`: `IndexedDbStorage`, the IndexedDB stores and their fallbacks in memory.
315
345
 
316
346
  No module of the entry imports a module of Node. The modules import `@procedures/client/browser` and not the root of the client, because the root imports `http` and `ws`. The test `src/browser.test.ts` examines the imports of each module of the entry. The entry is in `client.browser` of `package.json`, so the CI check of the browser entries (`scripts/check-browser-entries.mjs`) bundles it for a browser too.
317
347