@chipmobilesdk/rn-local-db 0.2.0 → 0.2.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 (84) hide show
  1. package/CHANGELOG.md +122 -102
  2. package/README.md +728 -728
  3. package/package.json +59 -62
  4. package/skills/sdk-rn-local-db/SKILL.md +0 -1
  5. package/src/adapter/budgets.ts +67 -67
  6. package/src/adapter/collection.ts +303 -298
  7. package/src/adapter/deletion.ts +252 -252
  8. package/src/adapter/index.ts +64 -68
  9. package/src/adapter/lifecycle.ts +517 -520
  10. package/src/adapter/transaction.ts +71 -71
  11. package/src/artifacts/availability.ts +67 -67
  12. package/src/artifacts/cascade.ts +114 -114
  13. package/src/artifacts/paths.ts +29 -29
  14. package/src/artifacts/reconcile.ts +63 -63
  15. package/src/artifacts/store.ts +334 -345
  16. package/src/contract/adapter.ts +76 -78
  17. package/src/contract/attachment.ts +75 -78
  18. package/src/contract/backup.ts +28 -28
  19. package/src/contract/config.ts +54 -54
  20. package/src/contract/encryption.ts +34 -34
  21. package/src/contract/errors.ts +76 -76
  22. package/src/contract/migration.ts +42 -42
  23. package/src/contract/query.ts +81 -81
  24. package/src/contract/record.ts +46 -51
  25. package/src/contract/schema.ts +36 -36
  26. package/src/contract/scope.ts +36 -36
  27. package/src/contract/transaction.ts +52 -54
  28. package/src/crypto/chunked-cipher.ts +153 -150
  29. package/src/crypto/derive.ts +64 -64
  30. package/src/crypto/key-provider.ts +78 -78
  31. package/src/crypto/provider.ts +81 -81
  32. package/src/diagnostics/dev-log.ts +112 -108
  33. package/src/diagnostics/errors.ts +62 -66
  34. package/src/diagnostics/faults.ts +58 -64
  35. package/src/diagnostics/map-native.ts +108 -106
  36. package/src/diagnostics/redact.ts +137 -141
  37. package/src/index.ts +80 -110
  38. package/src/migration/executor.ts +132 -136
  39. package/src/migration/ledger.ts +95 -97
  40. package/src/migration/validate-chain.ts +65 -65
  41. package/src/platform/backup-android-verify.ts +88 -88
  42. package/src/platform/backup-ios.ts +48 -48
  43. package/src/platform/bytes.ts +144 -144
  44. package/src/platform/fs.ts +89 -89
  45. package/src/platform/location.ts +135 -135
  46. package/src/query/budgets.ts +54 -54
  47. package/src/query/compare.ts +91 -91
  48. package/src/query/cursor.ts +100 -100
  49. package/src/query/filter.ts +82 -82
  50. package/src/query/paginate.ts +51 -51
  51. package/src/query/sort.ts +55 -56
  52. package/src/query/validate.ts +171 -171
  53. package/src/schema/declare.ts +42 -45
  54. package/src/schema/validate-config.ts +158 -158
  55. package/src/scope/hash.ts +131 -134
  56. package/src/scope/normalize.ts +83 -90
  57. package/src/scope/validate.ts +83 -83
  58. package/src/sqlite/adapter.ts +26 -26
  59. package/src/sqlite/batch.ts +242 -242
  60. package/src/sqlite/catalog.ts +105 -108
  61. package/src/sqlite/connection.ts +227 -227
  62. package/src/sqlite/index-coverage.ts +54 -56
  63. package/src/sqlite/native.ts +83 -83
  64. package/src/sqlite/row-codec.ts +217 -221
  65. package/src/sqlite/sql-builder.ts +244 -244
  66. package/src/sqlite/transaction-queue.ts +87 -87
  67. package/src/sqlite/transactions.ts +33 -33
  68. package/src/sqlite/values.ts +24 -24
  69. package/src/testing/conformance/attachments.ts +138 -136
  70. package/src/testing/conformance/encryption.ts +150 -150
  71. package/src/testing/conformance/index.ts +161 -161
  72. package/src/testing/conformance/lifecycle.ts +99 -99
  73. package/src/testing/conformance/migrations.ts +177 -177
  74. package/src/testing/conformance/queries.ts +204 -167
  75. package/src/testing/conformance/records.ts +169 -169
  76. package/src/testing/conformance/scopes.ts +86 -88
  77. package/src/testing/conformance/transactions.ts +149 -149
  78. package/src/testing/faults.ts +21 -21
  79. package/src/testing/index.ts +17 -21
  80. package/src/testing/memory-adapter/collection.ts +214 -219
  81. package/src/testing/memory-adapter/index.ts +510 -492
  82. package/src/testing/memory-adapter/migrations.ts +117 -119
  83. package/src/testing/memory-adapter/reset.ts +50 -50
  84. package/src/testing/memory-adapter/store.ts +128 -134
package/CHANGELOG.md CHANGED
@@ -1,102 +1,122 @@
1
- # Changelog
2
-
3
- All notable changes to `@chipmobilesdk/rn-local-db` are recorded here. The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this package follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
4
-
5
- ## [0.2.0] — 2026-11-01
6
-
7
- Fixes a data-loss defect in transactions and attachment handling that failed on every
8
- Hermes device. **One behaviour change needs a code change** (see Changed).
9
-
10
- ### Fixed
11
-
12
- - **A write from outside a transaction is no longer lost with its rollback.** The
13
- connection routed every statement into whatever transaction was in flight, so a write
14
- from another screen or a background sync while a transaction ran was rolled back with
15
- it, and a reader outside saw uncommitted data. Each handle now queues work behind a
16
- running transaction; only the executor the transaction hands out reaches it. The
17
- memory adapter isolates the same way, so conformance now catches a regression. After
18
- `tx.abort()` the body's remaining statements are refused instead of running in
19
- autocommit.
20
- - **Attachments work on Hermes.** Writes and reads used Node's global `Buffer`, which
21
- Hermes does not have. Byte handling is now `Uint8Array` with a self-contained base64
22
- codec; the encrypted file format is unchanged.
23
- - **A batch upsert over a soft-deleted record restores it**, and a batch insert over one
24
- conflicts — the collection API's rules. The batch used to issue an INSERT and fail the
25
- whole batch on the primary key.
26
- - **Index names are scoped to their collection.** Two collections declaring an index of
27
- the same name used to get only the first one, a UNIQUE constraint included. Existing
28
- indexes are renamed on the next open; no data moves. `explain()` still reports the
29
- declared name.
30
- - **Deleting an encrypted scope no longer needs its key.** A failing or destroyed key
31
- failed the call after the scope was marked, leaving it stuck in `deleting`. The data is
32
- deleted and the outcome sets `recordCountUnavailable`.
33
- - **Cascaded attachment removal is transaction-safe and reported.** Inside a
34
- transaction, files are removed only after it commits, so a rollback no longer leaves a
35
- reference to a deleted file. The reference is deleted before the file, a file that
36
- could not be removed is reported in `failedRemovals`, batch deletes cascade, and the
37
- memory adapter implements cascading.
38
-
39
- ### Changed
40
-
41
- - **Needs a code change:** inside a transaction body, write attachments through
42
- `tx.attachments()` (new) instead of `handle.attachments()`. The handle's call now waits
43
- for the transaction; awaited from inside the body it is refused with
44
- `TRANSACTION_STATE` after 10 seconds and the transaction rolls back, instead of
45
- hanging. The same applies to `handle.collection()`, which inside a transaction was
46
- already documented as a mistake.
47
- - `MigrationContext` no longer includes `attachments()`.
48
-
49
- ### Added
50
-
51
- - `Transaction.attachments()`.
52
- - `WriteOutcome.cascade` on a delete when `cascadeAttachments` is on.
53
- - `DeletionOutcome.recordCountUnavailable`.
54
-
55
- ## [0.1.0] — 2026-08-01
56
-
57
- First release. New package, no existing consumers, no migration burden.
58
-
59
- ### Added
60
-
61
- - **Scope-isolated storage.** One SQLite database file per scope. Scope is bound to a handle at open and immutable for its lifetime; no read, write, or query operation accepts a scope argument, and there is no `switchScope`. Scope components are hashed — only the SHA-256 digest reaches disk, a log, or an error.
62
- - **Records.** `insert`, `update`, `upsert` (reporting created versus updated), `get`, `find`, `delete`, `softDelete`, `restore`. Payloads round-trip with zero coercions, and the four value conditions — record absent, field null, field absent, record soft-deleted — stay distinguishable.
63
- - **Queries.** Twelve operators plus `and`/`or`/`not`, multi-key sorting with a deterministic `id` tiebreaker, keyset pagination, and `count` that always agrees with the corresponding list. An invalid query is an error rather than an empty or complete result. Development-mode index-coverage reporting via `explain`.
64
- - **Transactions and batches.** Real ACID transactions with read-your-own-writes, explicit abort, and terminal-state rejection. Batches of up to 1,000 operations applied as one unit.
65
- - **Migrations.** Ascending, at most once per scope, one transaction each, with a per-scope ledger. A failing chain returns no handle and alters nothing; a downgrade is refused rather than truncating. `resetScope` is the separately named recovery path.
66
- - **Deletion lifecycle.** `deleteScopeData`, `deleteDatabase`, and `resetScope` as module-level functions that work with or without an open handle. Nothing is ever deleted unasked — no expiry, no eviction, no sweep on close or upgrade. Every deletion reports what it removed and what it could not.
67
- - **Attachments.** Package-owned artifacts with availability checks that never open the file, owner-scoped listing, opt-in cascade on record deletion, and app-triggered reconciliation for orphaned files and dangling references. Every filesystem operation is confined to the managed storage area.
68
- - **Encryption at rest.** Opt-in under an app-supplied key. SQLCipher for records; chunked AES-256-GCM with HKDF-derived per-artifact subkeys for files, one 256 KB chunk in flight so memory is flat in artifact size. The package never generates, persists, caches beyond the handle, returns, or logs key material, and depends on no keychain library.
69
- - **Backup posture.** Excluded by default. Enforced on iOS via `NSURLIsExcludedFromBackupKey`; verified and reported on Android, where participation is manifest-owned and unreachable from a library that authors no native code.
70
- - **Typed diagnostics.** Twenty-nine stable `DiagnosticCode` values with `isCode` so no consumer parses a message. Disk-full, filesystem-access, and corruption stay distinct. Redaction happens at construction, so no error carries a payload, query parameter, scope component, or key material in any build.
71
- - **`./testing` entrypoint.** In-memory adapter, the conformance suite both adapters must pass identically, deterministic reset, seeding through production write paths, and fault injection for every diagnostic code.
72
-
73
- ### Documented
74
-
75
- - Six knowing divergences between the in-memory and on-device adapters, in the README.
76
- - The full diagnostic table with recommended recovery per condition.
77
- - The FR-088 budgets, and which four are hard limits.
78
- - The consumer data-behaviour note: what is stored, where, what leaves the device (nothing), the at-rest and backup postures, and what scope deletion does and does not guarantee.
79
-
80
- ### Semver impact
81
-
82
- New package at `0.1.0`. Nothing to migrate from.
83
-
84
- | Surface | Status | Notes |
85
- |---|---|---|
86
- | Lifecycle, records, query, transaction, batch | **Stable** | Breaking changes need a major |
87
- | Scope deletion and reset | **Stable** | |
88
- | Attachments including reconciliation | **Stable** | |
89
- | Diagnostic codes | **Stable, additive** | A new code is a minor; renaming one is breaking |
90
- | Encryption and key provider | **Experimental** | Field-level encryption and posture conversion may extend it |
91
- | Backup posture reporting | **Experimental** | The Android `observed` / `enforcedBy` shape may change as verification improves |
92
- | `StorageAdapter` interface | **Experimental** | Exported so the conformance suite is usable; not yet a stable extension point |
93
- | Testing entrypoint | **Experimental** | |
94
-
95
- Reserved as additive minors: reactive query subscriptions, field-level encryption, in-place encryption-posture conversion, further filter operators, and further diagnostic codes. Any change to the physical layout, the artifact format, or the encryption format ships with an internal migration or is breaking.
96
-
97
- ### Known limitations
98
-
99
- - **Android backup exclusion cannot be enforced by this package.** It ships the exact configuration, verifies coverage at runtime, and reports the observed posture; the manifest entry is the app's.
100
- - **Encryption posture cannot be converted in place.** Export, delete the scope, re-import.
101
- - **A transaction never spans two scopes.** One database file per scope makes this a type error rather than a runtime one.
102
- - **No reactive subscriptions.** Queries are pull-based in this version.
1
+ # @chipmobilesdk/rn-local-db
2
+
3
+ ## 0.2.1
4
+
5
+ ### Patch Changes
6
+
7
+ - Packaging only; no code change. The package no longer declares `engines.node`: a
8
+ React Native package does not run on Node, so the field only produced install
9
+ warnings in apps on another Node version. rn-i18n's command-line tooling does run
10
+ on Node; its README's compatibility table states the version it needs. ([#14](https://github.com/operationd8979/chip-mobile-sdk/pull/14))
11
+
12
+ ## [0.2.0] — 2026-11-01
13
+
14
+ Fixes a data-loss defect in transactions and attachment handling that failed on every
15
+ Hermes device. **One behaviour change needs a code change** (see Changed).
16
+
17
+ ### Fixed
18
+
19
+ - **A write from outside a transaction is no longer lost with its rollback.** The
20
+ connection routed every statement into whatever transaction was in flight, so a write
21
+ from another screen or a background sync while a transaction ran was rolled back with
22
+ it, and a reader outside saw uncommitted data. Each handle now queues work behind a
23
+ running transaction; only the executor the transaction hands out reaches it. The
24
+ memory adapter isolates the same way, so conformance now catches a regression. After
25
+ `tx.abort()` the body's remaining statements are refused instead of running in
26
+ autocommit.
27
+ - **Attachments work on Hermes.** Writes and reads used Node's global `Buffer`, which
28
+ Hermes does not have. Byte handling is now `Uint8Array` with a self-contained base64
29
+ codec; the encrypted file format is unchanged.
30
+ - **A batch upsert over a soft-deleted record restores it**, and a batch insert over one
31
+ conflicts — the collection API's rules. The batch used to issue an INSERT and fail the
32
+ whole batch on the primary key.
33
+ - **Index names are scoped to their collection.** Two collections declaring an index of
34
+ the same name used to get only the first one, a UNIQUE constraint included. Existing
35
+ indexes are renamed on the next open; no data moves. `explain()` still reports the
36
+ declared name.
37
+ - **Deleting an encrypted scope no longer needs its key.** A failing or destroyed key
38
+ failed the call after the scope was marked, leaving it stuck in `deleting`. The data is
39
+ deleted and the outcome sets `recordCountUnavailable`.
40
+ - **Cascaded attachment removal is transaction-safe and reported.** Inside a
41
+ transaction, files are removed only after it commits, so a rollback no longer leaves a
42
+ reference to a deleted file. The reference is deleted before the file, a file that
43
+ could not be removed is reported in `failedRemovals`, batch deletes cascade, and the
44
+ memory adapter implements cascading.
45
+
46
+ ### Changed
47
+
48
+ - **Needs a code change:** inside a transaction body, write attachments through
49
+ `tx.attachments()` (new) instead of `handle.attachments()`. The handle's call now waits
50
+ for the transaction; awaited from inside the body it is refused with
51
+ `TRANSACTION_STATE` after 10 seconds and the transaction rolls back, instead of
52
+ hanging. The same applies to `handle.collection()`, which inside a transaction was
53
+ already documented as a mistake.
54
+ - `MigrationContext` no longer includes `attachments()`.
55
+
56
+ ### Added
57
+
58
+ - `Transaction.attachments()`.
59
+ - `WriteOutcome.cascade` on a delete when `cascadeAttachments` is on.
60
+ - `DeletionOutcome.recordCountUnavailable`.
61
+
62
+ ## [0.1.2] — 2026-09-12
63
+
64
+ ### Changed
65
+
66
+ - The shipped agent skill and the README were clarified. No code change.
67
+
68
+ ## [0.1.1] — 2026-08-01
69
+
70
+ ### Changed
71
+
72
+ - The package now ships its agent skill (`skills/`), which consuming apps
73
+ copy in with `scripts/sync-sdk-skills.mjs`. No code change.
74
+
75
+ ## [0.1.0] — 2026-08-01
76
+
77
+ First release. New package, no existing consumers, no migration burden.
78
+
79
+ ### Added
80
+
81
+ - **Scope-isolated storage.** One SQLite database file per scope. Scope is bound to a handle at open and immutable for its lifetime; no read, write, or query operation accepts a scope argument, and there is no `switchScope`. Scope components are hashed — only the SHA-256 digest reaches disk, a log, or an error.
82
+ - **Records.** `insert`, `update`, `upsert` (reporting created versus updated), `get`, `find`, `delete`, `softDelete`, `restore`. Payloads round-trip with zero coercions, and the four value conditions — record absent, field null, field absent, record soft-deleted — stay distinguishable.
83
+ - **Queries.** Twelve operators plus `and`/`or`/`not`, multi-key sorting with a deterministic `id` tiebreaker, keyset pagination, and `count` that always agrees with the corresponding list. An invalid query is an error rather than an empty or complete result. Development-mode index-coverage reporting via `explain`.
84
+ - **Transactions and batches.** Real ACID transactions with read-your-own-writes, explicit abort, and terminal-state rejection. Batches of up to 1,000 operations applied as one unit.
85
+ - **Migrations.** Ascending, at most once per scope, one transaction each, with a per-scope ledger. A failing chain returns no handle and alters nothing; a downgrade is refused rather than truncating. `resetScope` is the separately named recovery path.
86
+ - **Deletion lifecycle.** `deleteScopeData`, `deleteDatabase`, and `resetScope` as module-level functions that work with or without an open handle. Nothing is ever deleted unasked — no expiry, no eviction, no sweep on close or upgrade. Every deletion reports what it removed and what it could not.
87
+ - **Attachments.** Package-owned artifacts with availability checks that never open the file, owner-scoped listing, opt-in cascade on record deletion, and app-triggered reconciliation for orphaned files and dangling references. Every filesystem operation is confined to the managed storage area.
88
+ - **Encryption at rest.** Opt-in under an app-supplied key. SQLCipher for records; chunked AES-256-GCM with HKDF-derived per-artifact subkeys for files, one 256 KB chunk in flight so memory is flat in artifact size. The package never generates, persists, caches beyond the handle, returns, or logs key material, and depends on no keychain library.
89
+ - **Backup posture.** Excluded by default. Enforced on iOS via `NSURLIsExcludedFromBackupKey`; verified and reported on Android, where participation is manifest-owned and unreachable from a library that authors no native code.
90
+ - **Typed diagnostics.** Twenty-nine stable `DiagnosticCode` values with `isCode` so no consumer parses a message. Disk-full, filesystem-access, and corruption stay distinct. Redaction happens at construction, so no error carries a payload, query parameter, scope component, or key material in any build.
91
+ - **`./testing` entrypoint.** In-memory adapter, the conformance suite both adapters must pass identically, deterministic reset, seeding through production write paths, and fault injection for every diagnostic code.
92
+
93
+ ### Documented
94
+
95
+ - Six knowing divergences between the in-memory and on-device adapters, in the README.
96
+ - The full diagnostic table with recommended recovery per condition.
97
+ - The FR-088 budgets, and which four are hard limits.
98
+ - The consumer data-behaviour note: what is stored, where, what leaves the device (nothing), the at-rest and backup postures, and what scope deletion does and does not guarantee.
99
+
100
+ ### Semver impact
101
+
102
+ New package at `0.1.0`. Nothing to migrate from.
103
+
104
+ | Surface | Status | Notes |
105
+ |---|---|---|
106
+ | Lifecycle, records, query, transaction, batch | **Stable** | Breaking changes need a major |
107
+ | Scope deletion and reset | **Stable** | |
108
+ | Attachments including reconciliation | **Stable** | |
109
+ | Diagnostic codes | **Stable, additive** | A new code is a minor; renaming one is breaking |
110
+ | Encryption and key provider | **Experimental** | Field-level encryption and posture conversion may extend it |
111
+ | Backup posture reporting | **Experimental** | The Android `observed` / `enforcedBy` shape may change as verification improves |
112
+ | `StorageAdapter` interface | **Experimental** | Exported so the conformance suite is usable; not yet a stable extension point |
113
+ | Testing entrypoint | **Experimental** | |
114
+
115
+ Reserved as additive minors: reactive query subscriptions, field-level encryption, in-place encryption-posture conversion, further filter operators, and further diagnostic codes. Any change to the physical layout, the artifact format, or the encryption format ships with an internal migration or is breaking.
116
+
117
+ ### Known limitations
118
+
119
+ - **Android backup exclusion cannot be enforced by this package.** It ships the exact configuration, verifies coverage at runtime, and reports the observed posture; the manifest entry is the app's.
120
+ - **Encryption posture cannot be converted in place.** Export, delete the scope, re-import.
121
+ - **A transaction never spans two scopes.** One database file per scope makes this a type error rather than a runtime one.
122
+ - **No reactive subscriptions.** Queries are pull-based in this version.