anchordb-angular 1.3.2 → 1.4.0

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 (3) hide show
  1. package/CHANGELOG.md +415 -0
  2. package/README.md +6 -0
  3. package/package.json +4 -3
package/CHANGELOG.md ADDED
@@ -0,0 +1,415 @@
1
+ # Changelog
2
+
3
+ All notable changes to the `anchordb` packages.
4
+
5
+ This project follows [semantic versioning](https://semver.org/). While the version is `0.x`, minor
6
+ releases may contain breaking changes.
7
+
8
+ ## 1.4.0
9
+
10
+ **Transactions, migrations, recovery, TTL indexes, encryption, a test kit — and guides that ship in the
11
+ package.** Asked for by the expense-tracker team after building an offline-first app on 1.3; every
12
+ item has tests, and nothing existing changes behaviour except as noted.
13
+
14
+ ### New
15
+
16
+ - **`db.transaction(async (session) => …)`** — writes across collections, all or nothing, with
17
+ Mongoose's API: `{ session }` on `create`, `insertOne/Many`, `update*`, `replaceOne`, `delete*`,
18
+ `findOneAnd*`, `bulkWrite`, `aggregate`, the index methods and `doc.save()`, and `.session()` on
19
+ queries. A throw rolls every collection back; `change` events and queued sync mutations wait for
20
+ the commit. A call inside made without the session times out the transaction with
21
+ `TransactionTimeoutError` (`transactionTimeoutMs`, default 30 s) instead of hanging. Expo, Capacitor,
22
+ `node:sqlite` and memory; IndexedDB refuses with an explanation. `AnchorSession` / `ClientSession`.
23
+ - **Versioned migrations**: `createAnchorDB({ version, migrations: { 2: async (ctx) => … } })`, run by
24
+ `open()`, each step in its own transaction that records the version reached. A failed step is
25
+ rolled back and reported as `MigrationError`; `open()` can be retried. Older apps refuse newer data.
26
+ - **Recovery**: open failures are `DatabaseOpenError`, or `CorruptDatabaseError` /
27
+ `DatabaseLockedError`, with the driver's error as `cause`. `db.reset()` deletes the storage even
28
+ when it no longer opens. `integrityCheck: true` runs `PRAGMA quick_check` on open.
29
+ `db.rebuildIndexes()` rebuilds index entries from the documents.
30
+ - **TTL indexes are enforced.** `expireAfterSeconds` was stored and never applied; a sweep now deletes
31
+ expired documents with MongoDB's rules, every 60 s (`ttlIntervalMs`, `ttl: false`), and `db.expire()`
32
+ sweeps on demand.
33
+ - **Encryption**: `ExpoSqliteAdapter({ encryptionKey })` opens the file with SQLCipher, and refuses
34
+ rather than store plain text when expo-sqlite is built without it.
35
+ - **Observability**: `db:open`, `db:transaction` and `db:slowQuery` (with `slowQueryMs`) events, and
36
+ `db.diagnostics()` for the storage queue depth.
37
+ - **`anchordb/testing`**: `fakeExpoSqlite` and `fakeCapacitorSqlite` run the real adapters in Node,
38
+ and `runAdapterConformance` holds any adapter to the storage contract. The Expo stand-in is the
39
+ expense-tracker team's, which found the 1.3.2 bugs.
40
+ - **Default file name**: an Expo or Capacitor adapter built without a name takes the database's —
41
+ `new ExpoSqliteAdapter({ sqlite })` with `name: "expense-tracker"` opens `expense-tracker.db`.
42
+ - `anchordb-react`: **`useAnchorStatus(db)`** documented as the way to render opening, failure and retry.
43
+ - **Guides in the package**, under `docs/`: sync, concurrency and transactions, migrations / recovery
44
+ / TTL / encryption, aggregation, testing, the inspector. Sync existed since 1.0 but was never
45
+ explained, which is why the team built their own.
46
+ - **Every package ships this changelog**, and each release is tagged on GitHub.
47
+
48
+ ### Changed
49
+
50
+ - Every storage adapter queues all of its calls, reads included, per database. Concurrency was already
51
+ safe for writes in 1.3.3; reads now also never see another caller's uncommitted transaction.
52
+ - An error from `open()` is now a `DatabaseOpenError` (message prefixed "The database did not open:")
53
+ instead of the driver's bare error, which is kept as `cause`. Code that matched on the message still
54
+ finds it inside.
55
+ - `node:sqlite` adapter: prepared statements are dropped when the schema changes. One planned against
56
+ a partial index inside a transaction otherwise kept that plan and matched nothing when reused.
57
+
58
+ ### Not yet
59
+
60
+ - Sync on a timer: `autoSync` and `intervalMs` are still reserved; call `db.sync.now()`.
61
+ - Suspense for `useFind`; server-side expiry of sync delete markers; transactions on IndexedDB.
62
+
63
+ ## 1.3.3
64
+
65
+ **Writes through Expo and Capacitor SQLite are safe under concurrency, and work on a device.** Found
66
+ in an expense tracker on 1.3.2; every case below has a regression test.
67
+
68
+ - **Concurrent writes no longer share a transaction** (Expo, Capacitor). Every driver call awaits each
69
+ statement, so two writes started together interleaved, and the second ran inside the first's
70
+ transaction: a write reported as failed could be partly saved, and one caller's rollback could undo
71
+ another's committed write. `SqlAdapterBase` now queues every driver call, reads included.
72
+ - **Expo SQLite writes no longer fail with `database is locked`.** Inside
73
+ `withExclusiveTransactionAsync` statements now go to the `txn` connection expo-sqlite hands over,
74
+ instead of the outer one the exclusive lock blocks. Apps that mapped the exclusive transaction onto
75
+ `withTransactionAsync` as a workaround keep working.
76
+ - **Concurrent upserts of the same new key** now insert once and update the rest, as MongoDB 4.2+ does,
77
+ instead of rejecting with E11000. A duplicate on some other unique field is still reported.
78
+ - **A failed `db.open()` can be retried.** The rejection was cached, so a transient failure needed a
79
+ new `AnchorDB`.
80
+ - **Duplicate-key errors name the configured database** — `expense-tracker.metas`, not
81
+ `anchor.metas`. `ExpoSqliteAdapter` defaults its name to the file name without `.db`, and
82
+ `createAnchorDB` passes `config.name`.
83
+ - `anchordb-react`: **`useAnchorReady` no longer waits forever when the database fails to open.** It
84
+ throws the error during render, for an error boundary. The new `useAnchorStatus(db)` returns
85
+ `{ status, ready, error, retry }` to show the failure and retry in place, and `anchorOpenStore(db)`
86
+ is the store both read. Neither starts work while rendering any more.
87
+
88
+ ## 1.3.2
89
+
90
+ Documentation only — no code changes.
91
+
92
+ - **Bugs, support and feedback go to the AnchorDB project page**, at
93
+ [nisalanadeera.com/projects/anchordb](https://www.nisalanadeera.com/projects/anchordb#feedback): a form
94
+ that asks for the package, version and platform, and a reply by email.
95
+ - Every package's npm **Homepage** is that page, and **Report a bug** (`npm bugs`) opens the form.
96
+ - Every README links the overview and the form, and says what a bug report that can be acted on
97
+ includes.
98
+ - The package READMEs' family tables list all six packages, with `anchordb-lens-link`.
99
+ - All six packages move to 1.3.2 together.
100
+
101
+ ## 1.3.1
102
+
103
+ **Lens Link keeps both apps running in the background.** Found on a phone: switching from the app to
104
+ Anchor Lens let the phone stop the app within seconds, and the link went with it.
105
+
106
+ - `anchordb-lens-link`: while the link is on, the app runs an Android foreground service with an
107
+ ongoing notification — *Anchor Lens Link on*, then *Anchor Lens connected* — which is what Android
108
+ lets an app use to keep running. `keepAlive: false` turns it off; `link.keepAliveError` says why it
109
+ could not start.
110
+ - `startKeepAlive`, `updateKeepAlive` and `stopKeepAlive` keep a client running the same way. Anchor
111
+ Lens uses them while it is connected to an app, so you can switch between the two.
112
+ - `backgroundStatus()`, `askNotificationPermission()`, `askBatteryUnrestricted()`,
113
+ `openNotificationSettings()` and `openBackgroundSettings()`: the permissions and settings that stop a
114
+ phone overruling it, including Xiaomi's Autostart screen.
115
+ - Only `anchordb-lens-link` changes. The other packages stay at 1.3.0.
116
+
117
+ ## 1.3.0
118
+
119
+ **Anchor Lens Link: open a QA build's database in Anchor Lens on the same phone, from a file.** Asked
120
+ for after testing on a phone, where reaching another app took a laptop, the relay, an address, a room, a
121
+ QR scan and a pairing code.
122
+
123
+ - **New package, `anchordb-lens-link`.** `enableLensLink(db, { allowInProduction: true })` starts a
124
+ WebSocket server on 127.0.0.1, puts an `InspectorAgent` behind it and writes a sealed
125
+ `Android/media/<package>/anchor-lens/<database>.anchorlens`. In Anchor Lens, *Open app from file*
126
+ reads it, connects and authenticates with nothing typed. The port and the secret change every
127
+ launch. Android only; the native part is a small Expo module on Java-WebSocket. It is a separate
128
+ package, and does nothing unless the app calls it, so production apps need never ship it.
129
+ - **`auth.sharedSecret` for the inspector.** An agent can authenticate a secret both sides already
130
+ hold instead of a code shown on screen. It is proved the same way, as an HMAC over a single-use
131
+ challenge, but it is not burned, so a client can reconnect; a spent or expired challenge is replaced
132
+ at once. Secrets shorter than 32 characters are refused. Pairing codes work as before.
133
+ - **`assertInspectorAllowed` is exported**, so a package that starts an agent applies the same
134
+ production guard as the relay connection.
135
+ - Tested in Node end to end: the sealed file, an agent with a shared secret behind a WebSocket server
136
+ that behaves like the native one, and a Lens client that reads the file, proves the secret, reads and
137
+ writes through the Model API, reconnects with the same file, and is shut out after `close()`.
138
+
139
+ ## 1.2.0
140
+
141
+ Anchor Lens can create and drop indexes, and a malformed `_id` is refused instead of stored. Both
142
+ found while testing Lens on a phone.
143
+
144
+ - **Create Index and Drop Index on the inspector protocol.** `InspectorClient.createIndex(collection,
145
+ key, options)` and `dropIndex(collection, name)`, routed through `Model.createIndex()` and
146
+ `dropIndex()`. Agents had advertised `indexes:write` with no method behind it. Keys are checked
147
+ (`1` or `-1`, no `$` fields), read-only sessions refuse both, a unique index over values that already
148
+ collide fails with `duplicate_key`, and `_id_` cannot be dropped.
149
+ - **`getSchema(collection)` on the inspector protocol** — a declared model's fields with their type,
150
+ required flag, enum and plain default, nested objects as dotted paths. What Lens needs to offer
151
+ "Add all fields" on Insert document. Validator functions and function defaults are not sent; a
152
+ collection with no declared model returns no fields.
153
+ - **An insert stored an object `_id` as "[object Object]".** Insert skipped the `_id` handling updates
154
+ apply, and storage keys rows by the id's string form — so Extended JSON pasted into Lens, with
155
+ `{ "$oid": … }` read as a plain object, produced such a row, and every such document would have
156
+ collided on it. Objects that are not ObjectIds are now refused with a `CastError`. Strings and
157
+ numbers are kept, as the driver keeps them.
158
+
159
+ ## 1.1.0
160
+
161
+ **Anchor Lens can read other apps.** Pointing Lens at a second app on a real phone found every step of
162
+ that path broken or missing.
163
+
164
+ - **`inspector: { enabled, relayUrl }` did nothing.** It ran a production check and never connected.
165
+ With `relayUrl` set the database now publishes itself to `anchor-relay` on construction, stays
166
+ connected, reconnects after a drop, and reports pairing codes through `inspector.onPairing` and the
167
+ `inspector:pairing` / `inspector:state` events. `db.inspector` exposes the connection, and
168
+ `connectInspectorToRelay(db, options)` does the same at runtime.
169
+ - **Pairing asked for a 32-character hex challenge, typed on a phone.** The agent now sends it with
170
+ `connect` as `ConnectResult.challenge` — a nonce, not a secret; the code never leaves the app — and
171
+ opens a fresh pairing window, announcing its code, when the last one was spent or expired. Lens types
172
+ only the code.
173
+ - **The production guard never fired on React Native.** It read `process.env.NODE_ENV` through
174
+ `globalThis`, which Metro does not inline, so a release build looked like development. `__DEV__ ===
175
+ false` now counts as production too.
176
+ - **`anchordb-relay`:**
177
+ - With `--host 0.0.0.0` it printed `ws://0.0.0.0:9440` — the listen address, which no device can
178
+ dial. It now prints the machine's network addresses.
179
+ - It prints the Lens link as a QR code in the terminal.
180
+ - `--room <id>` fixes the room, so an app built with the agent URL survives relay restarts.
181
+ - The room it printed was reclaimed after 30 idle minutes, so an app connecting later got "unknown
182
+ room". It is now kept for the life of the relay.
183
+ - Stopping it hung while an app or Lens was connected: neither `wss.close` nor `http.close` ends
184
+ established connections. They are now terminated.
185
+ - Tested over real sockets: a relay server, an app publishing with `connectInspectorToRelay`, and a Lens
186
+ client that pairs with only the code, reads and writes, then shuts down cleanly.
187
+
188
+ ## 1.0.6
189
+
190
+ Crash on launch in React Native apps that load `anchordb` before `anchordb-react`.
191
+
192
+ - **Importing `anchordb` needed a crypto source.** `ObjectId` drew its per-process random block and
193
+ its counter seed when the module loaded. On React Native, `globalThis.crypto` comes from the
194
+ `react-native-get-random-values` polyfill that `anchordb-react` loads — so an app that evaluated
195
+ `anchordb` first died with `No cryptographically secure random source is available` before it
196
+ generated a single id. Lens React did exactly that through a re-export and closed the instant it
197
+ launched on a phone; the Contacts app survived only because its first import happened to be
198
+ `createAnchorDB`. Both values are now drawn on the first `ObjectId`, and a failed draw caches
199
+ nothing, so a polyfill that loads later still works.
200
+ - The error message now points React Native users at `anchordb-react`'s `createAnchorDB`.
201
+ - A new test imports the whole package with no crypto source. Without this fix it fails with the
202
+ original error.
203
+
204
+ ## 1.0.5
205
+
206
+ Inspector fix, found by building Anchor Lens on a database on the device.
207
+
208
+ - **Schemaless collections were reported to Lens as schema-backed.** `db.collection(name)` — which
209
+ the inspector agent uses for any collection without a model, including every collection Lens
210
+ creates by inserting into it — registers an internal `__collection__<name>` model.
211
+ `getCollections` counted it as a schema, so Lens showed `hasSchema: true` and a model pill reading
212
+ `__collection__notes` instead of "schemaless". The agent now reports only models the app declared.
213
+ - **`modelForCollection` returned whichever model registered first.** A collection reached through
214
+ `db.collection()` before its model was declared resolved to the schemaless model, so an export
215
+ emitted ObjectIds and Dates as bare strings. A declared model now always wins.
216
+
217
+ ## 1.0.4
218
+
219
+ `anchordb-angular` in native Capacitor builds. No change to database behaviour.
220
+
221
+ - **Capacitor links native plugins only from the package.json of the app.** `@capacitor-community/sqlite`
222
+ arrives through `anchordb-angular`, so it was installed but `npx cap sync` left it out of the
223
+ Android project — found by building the Ionic test app, whose `capacitor.settings.gradle` had no
224
+ SQLite plugin. On a device the first query would have failed with
225
+ `"CapacitorSQLite" plugin is not implemented on android`. `ionicAdapter` now checks
226
+ `Capacitor.isPluginAvailable("CapacitorSQLite")` and throws naming
227
+ `npm install @capacitor-community/sqlite` and `npx cap sync`. It does not fall back to IndexedDB,
228
+ which would strand the data in a store the app abandons once the plugin is linked.
229
+ - **`@capacitor/core` was declared `^8.5.2` and `@capacitor-community/sqlite` `^8.1.1`** — the same
230
+ `npm install -w` caret rewrite as `anchordb-react` 1.0.1. A Capacitor 6 or 7 app would have got a
231
+ second `@capacitor/core`, and plugins registered on one instance are invisible to the other. Both
232
+ are now `>=6`, held by a regression test.
233
+ - The README and package reference showed `inject(AnchorService)` and `AnchorModule.forRoot(...)`
234
+ inside `imports`. Neither works: the providers use string tokens, and `forRoot` returns plain
235
+ providers. Both now show `@Inject("AnchorService")` and spread `.providers`.
236
+ - Verified in the Ionic test app on Capacitor 8.5.2: with the plugin listed, `cap sync` reports
237
+ `@capacitor-community/sqlite@8.1.1` for Android and the Gradle settings include it.
238
+
239
+ ## 1.0.3
240
+
241
+ Guidance fix for Expo apps. No change to database behaviour.
242
+
243
+ - **`createAnchorDB` and the `anchordb-react` README recommended `npx expo install --fix`**, which
244
+ cannot help: it only realigns packages listed in the package.json of the app, and `expo-sqlite`
245
+ and `react-native-get-random-values` arrive through `anchordb-react`. Both now name
246
+ `npx expo install expo-sqlite react-native-get-random-values`, which pins the drivers at the top
247
+ level where the wide ranges from 1.0.2 dedupe onto them.
248
+ - Verified in an Expo SDK 56 app: with the pins, both drivers resolve to the versions the SDK pins
249
+ (`expo-sqlite` 56.0.6, `react-native-get-random-values` 1.11.0), deduped, and
250
+ `npx expo install --check` reports dependencies up to date. Without the pin the polyfill resolves
251
+ to 2.0.0 against the 1.11 native module Expo Go ships.
252
+
253
+ ## 1.0.2
254
+
255
+ `anchordb-react` pinned its native drivers to a single Expo SDK.
256
+
257
+ - **`expo-sqlite` was declared `^57.0.3`**, so an app on Expo SDK 56 (`expo-sqlite ~56.0.4`) could
258
+ not dedupe it. npm nested a second, SDK 57 `expo-sqlite` whose JavaScript no longer matched the
259
+ native build of the app. The intended range was `>=14`; `npm install -w` rewrote it with a caret
260
+ when the dependency was added. Both drivers now take wide ranges (`expo-sqlite >=14`,
261
+ `react-native-get-random-values >=1.11`), so npm reuses whatever version the Expo SDK of the app
262
+ already installed.
263
+ - A test now asserts both ranges accept the drivers Expo SDK 56 and 57 ship and are not caret- or
264
+ tilde-pinned, so a future `npm install -w` cannot silently narrow them again.
265
+
266
+ Found by comparing against a working Expo SDK 56 app on the same machine.
267
+
268
+ ## 1.0.1
269
+
270
+ Two defects in `anchordb-angular`, both in its *documented* usage, found by building a real Ionic
271
+ app against the published package for the first time.
272
+
273
+ - **The provider arrays did not typecheck against Angular.** `Provider.useFactory` was declared
274
+ optional, so the array was not assignable to Angular’s `Provider[]` and the documented
275
+ `bootstrapApplication` example failed to compile. It is now required, matching what every
276
+ provider in the package actually returns, and `useValue` — declared but never used — is gone.
277
+ - **`.toObservable()` was documented but implemented nowhere.** The real API is
278
+ `AnchorService.find$` / `findOne$` / `count$`, which return an RxJS-interop `AnchorObservable`
279
+ the `async` pipe accepts directly. The documentation now shows that.
280
+
281
+ ## 1.0.0
282
+
283
+ **Versioning changes with this release.** The major version now tracks the React / Angular major the
284
+ packages are built against: React 18 stays on the `0.x` line, React 19 begins at `1.x`. Projects on
285
+ React 18 remain on 0.2.1, preserved on the
286
+ [`release/0.x-react18`](https://github.com/knnadeera/anchordb/tree/release/0.x-react18) branch.
287
+
288
+ ### One install, ready to use
289
+
290
+ `npm install anchordb-react` now brings the database, the SQLite driver and the crypto polyfill —
291
+ and `createAnchorDB({ name })` needs no adapter wiring. `npm install anchordb-angular` does the
292
+ same, with `provideAnchorIonic` choosing Capacitor SQLite on a device and IndexedDB under
293
+ `ionic serve`.
294
+
295
+ - `anchordb-react` gains `createAnchorDB`, and depends on `expo-sqlite` and
296
+ `react-native-get-random-values`
297
+ - `anchordb-angular` gains `ionicAdapter` and `provideAnchorIonic`, and depends on
298
+ `@capacitor/core` and `@capacitor-community/sqlite`
299
+
300
+ ### Breaking
301
+
302
+ - **`anchordb-react` is now React Native only.** It imports `react-native-get-random-values`, which
303
+ imports React Native internals, so a React web build fails. Browser apps use `anchordb` directly
304
+ with `anchordb/storage/indexeddb`, which is unchanged.
305
+ - **React 19 is required** by `anchordb-react`, since `expo-sqlite` pulls React Native.
306
+
307
+ ### Fixed
308
+
309
+ - **Subpath imports were unusable under `moduleResolution: Node10`.** Neither `anchordb` nor
310
+ `anchordb-sync-server` declared `typesVersions`, so `anchordb/storage/expo-sqlite` and friends
311
+ resolved to nothing for any consumer on classic resolution — and broke this repo's own CommonJS
312
+ build. Every `node10` result in are-the-types-wrong is now green where most were previously
313
+ failing.
314
+ - **The `ExpoDatabase` interface did not match the real `expo-sqlite`.** `params` was declared
315
+ optional where the driver requires it, and typed `unknown[]` where SQLite accepts only five bind
316
+ types. The actual module was therefore not assignable to the interface, so every TypeScript user
317
+ following the documented usage got an error. Caught by typechecking against the real package for
318
+ the first time.
319
+ - **`sideEffects: false` on `anchordb-react`** would have let a bundler tree-shake away the crypto
320
+ polyfill, making the first `ObjectId` throw. It now names the built entries.
321
+
322
+ ## 0.2.1
323
+
324
+ Documentation and discoverability only — no code changes.
325
+
326
+ - Every package README now carries a **The AnchorDB family** table, so someone landing on
327
+ `anchordb-react` from an npm search can see the other four and what each is for.
328
+ - npm keywords added to `anchordb-react`, `anchordb-angular`, `anchordb-sync-server` and
329
+ `anchordb-relay`, which had none and so did not surface in npm search at all. `anchordb` gained
330
+ aggregation, schema and document-database terms.
331
+ - Corrected stale `0.1.0` version claims in three READMEs.
332
+
333
+ ## 0.2.0 — first published release
334
+
335
+ Published as the unscoped `anchordb` family. The `@anchor` scope was never available: it needs an
336
+ npm organization, so the packages took unscoped names instead.
337
+
338
+ ### Added
339
+
340
+ - **Bulk writes on the inspector protocol** — `updateMany` and `deleteMany`, behind a new
341
+ `documents:bulk` capability, routed through the ordinary Model API so a bulk write from Anchor
342
+ Lens validates, stamps and queues exactly like an app write. An empty filter is refused unless
343
+ explicitly acknowledged.
344
+ - **CSV export and import** (`toCsv`, `fromCsv`, `detectImportFormat`), matching
345
+ `mongoexport --type=csv`. Values are cast through the collection schema on import.
346
+ - **A `filter` option on export**, for exporting query results rather than a whole collection.
347
+ - **A `default` Extended JSON mode**, alongside `relaxed` and `canonical`.
348
+ - **A MongoDB bridge** (`MongoBridgeClient` here, `MongoBridge` in `anchordb-relay`), so Lens can
349
+ pull collections from a real MongoDB or push a device into one.
350
+
351
+ ### Fixed
352
+
353
+ - **`modifiedCount` could never be 0.** `updatedAt` and the version key were stamped before the
354
+ change comparison, so every matched document counted as modified and a no-op still bumped the
355
+ timestamp. A no-op update is now matched but not modified, and writes nothing — which also stops a
356
+ bulk update over 10,000 documents queueing 10,000 mutations when only a few hundred changed.
357
+ - **`MongooseStore` was never exported** from `anchordb-sync-server`, so it was absent from the
358
+ published types and unreachable by anyone following the README.
359
+
360
+ ## 0.1.0 — never published
361
+
362
+ The initial implementation. Superseded by 0.2.0 before anything reached npm.
363
+
364
+ First release. Five packages, published together.
365
+
366
+ ### `anchordb`
367
+
368
+ - **Local-first database** with a Mongoose-shaped API. No `sync` block means a purely local
369
+ database: no mutation queue, no network code, no sync metadata, hard deletes.
370
+ - **Mongoose parity**: `Schema`, `model()`, documents with `.save()`/`.isModified()`, virtuals,
371
+ methods, statics, `pre`/`post` hooks, `ValidationError`/`CastError` shapes, and `code: 11000`.
372
+ - **Decorators** (`anchordb/decorators`) matching `@nestjs/mongoose` — `@Schema`, `@Prop`,
373
+ `SchemaFactory`, `raw()` — so one decorated class can be shared with a NestJS backend.
374
+ Metadata is optional: explicit `@Prop(String)` works with `emitDecoratorMetadata` off.
375
+ - **Real MongoDB ObjectId**, generated on-device, cross-validated byte-for-byte against `bson`.
376
+ - **Indexes** — single, compound, multikey, `unique`, `sparse`, `partialFilterExpression`, TTL —
377
+ with unique violations enforced at the storage layer and reported as `E11000`.
378
+ - **Lazy chainable query builder**: `.populate().sort().skip().limit().select().exec()`, thenable,
379
+ async-iterable, with `explain()`.
380
+ - **Aggregation pipeline** with streaming execution, index pushdown, and a `mongoCompatible` strict
381
+ mode that rejects non-portable constructs at development time.
382
+ - **UTC-canonical timestamps** with IANA timezone support, validated at construction.
383
+ - **Extended JSON v2 interop** — `export()` feeds `mongoimport`; `mongoexport` output imports back.
384
+ - **Offline mutation queue** and sync engine with five conflict strategies
385
+ (`last-write-wins`, `server-wins`, `client-wins`, `field-level`, `custom`).
386
+ - **Inspector protocol v1** with pairing, sessions, and live change events.
387
+ - **Five storage adapters**: Memory, Node SQLite, IndexedDB, Expo SQLite, Capacitor SQLite.
388
+
389
+ ### `anchordb-sync-server`
390
+
391
+ - Framework-agnostic protocol engine over a pluggable `ServerStore`.
392
+ - Express, NestJS and Next.js adapters, all held to one conformance suite.
393
+ - `MemoryStore` (default) and `MongooseStore`.
394
+
395
+ ### `anchordb-react`
396
+
397
+ - `useFind`, `useFindOne`, `useCount`, `useAggregate`, `useSyncStatus`, `useAnchorEvent`.
398
+
399
+ ### `anchordb-angular`
400
+
401
+ - `AnchorModule.forRoot`/`forFeature`, `getModelToken`, `AnchorService` with RxJS-compatible
402
+ observables. Angular and RxJS are optional peers and are never imported.
403
+
404
+ ### `anchordb-relay`
405
+
406
+ - Development-only WebSocket relay plus the `anchor-relay` CLI.
407
+
408
+ ### Known limitations
409
+
410
+ - **Expo SQLite and Capacitor SQLite are unverified** — written and typechecked, never executed on
411
+ a device. Test before production use.
412
+ - The REST sync transport and `MongooseStore` have no live-server tests.
413
+ - Not supported in v1: discriminators, `refPath`, transactions, server-side change streams,
414
+ text/geo/hashed indexes, collation, and the `$graphLookup`/`$geoNear`/`$search`/`$merge`/`$out`/
415
+ `$unionWith` aggregation stages.
package/README.md CHANGED
@@ -133,6 +133,12 @@ Each one needs a different third-party framework as a peer dependency, and npm r
133
133
  package rather than per import — which is why they are not one package. Full reasoning and API
134
134
  reference: [github.com/knnadeera/anchordb](https://github.com/knnadeera/anchordb).
135
135
 
136
+ ## Changes
137
+
138
+ What changed in each version is in [CHANGELOG.md](./CHANGELOG.md), shipped in this package — one
139
+ changelog for the whole family, since all six packages are released together. Releases are also
140
+ tagged on [GitHub](https://github.com/knnadeera/anchordb/releases).
141
+
136
142
  ## Bugs, support and feedback
137
143
 
138
144
  Report a bug, ask for help or suggest a feature on the [AnchorDB project page](https://www.nisalanadeera.com/projects/anchordb#feedback) —
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "anchordb-angular",
3
- "version": "1.3.2",
3
+ "version": "1.4.0",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "sideEffects": false,
@@ -23,7 +23,8 @@
23
23
  "files": [
24
24
  "dist",
25
25
  "README.md",
26
- "LICENSE"
26
+ "LICENSE",
27
+ "CHANGELOG.md"
27
28
  ],
28
29
  "scripts": {
29
30
  "build": "rimraf dist && tsc -p tsconfig.build.json && tsc -p tsconfig.build.cjs.json && node ../core/scripts/finalize-dist.mjs",
@@ -34,7 +35,7 @@
34
35
  "dependencies": {
35
36
  "@capacitor-community/sqlite": ">=6",
36
37
  "@capacitor/core": ">=6",
37
- "anchordb": "^1.3.0"
38
+ "anchordb": "^1.4.0"
38
39
  },
39
40
  "devDependencies": {
40
41
  "rimraf": "^6.0.1"