@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.
- package/CHANGELOG.md +122 -102
- package/README.md +728 -728
- package/package.json +59 -62
- package/skills/sdk-rn-local-db/SKILL.md +0 -1
- package/src/adapter/budgets.ts +67 -67
- package/src/adapter/collection.ts +303 -298
- package/src/adapter/deletion.ts +252 -252
- package/src/adapter/index.ts +64 -68
- package/src/adapter/lifecycle.ts +517 -520
- package/src/adapter/transaction.ts +71 -71
- package/src/artifacts/availability.ts +67 -67
- package/src/artifacts/cascade.ts +114 -114
- package/src/artifacts/paths.ts +29 -29
- package/src/artifacts/reconcile.ts +63 -63
- package/src/artifacts/store.ts +334 -345
- package/src/contract/adapter.ts +76 -78
- package/src/contract/attachment.ts +75 -78
- package/src/contract/backup.ts +28 -28
- package/src/contract/config.ts +54 -54
- package/src/contract/encryption.ts +34 -34
- package/src/contract/errors.ts +76 -76
- package/src/contract/migration.ts +42 -42
- package/src/contract/query.ts +81 -81
- package/src/contract/record.ts +46 -51
- package/src/contract/schema.ts +36 -36
- package/src/contract/scope.ts +36 -36
- package/src/contract/transaction.ts +52 -54
- package/src/crypto/chunked-cipher.ts +153 -150
- package/src/crypto/derive.ts +64 -64
- package/src/crypto/key-provider.ts +78 -78
- package/src/crypto/provider.ts +81 -81
- package/src/diagnostics/dev-log.ts +112 -108
- package/src/diagnostics/errors.ts +62 -66
- package/src/diagnostics/faults.ts +58 -64
- package/src/diagnostics/map-native.ts +108 -106
- package/src/diagnostics/redact.ts +137 -141
- package/src/index.ts +80 -110
- package/src/migration/executor.ts +132 -136
- package/src/migration/ledger.ts +95 -97
- package/src/migration/validate-chain.ts +65 -65
- package/src/platform/backup-android-verify.ts +88 -88
- package/src/platform/backup-ios.ts +48 -48
- package/src/platform/bytes.ts +144 -144
- package/src/platform/fs.ts +89 -89
- package/src/platform/location.ts +135 -135
- package/src/query/budgets.ts +54 -54
- package/src/query/compare.ts +91 -91
- package/src/query/cursor.ts +100 -100
- package/src/query/filter.ts +82 -82
- package/src/query/paginate.ts +51 -51
- package/src/query/sort.ts +55 -56
- package/src/query/validate.ts +171 -171
- package/src/schema/declare.ts +42 -45
- package/src/schema/validate-config.ts +158 -158
- package/src/scope/hash.ts +131 -134
- package/src/scope/normalize.ts +83 -90
- package/src/scope/validate.ts +83 -83
- package/src/sqlite/adapter.ts +26 -26
- package/src/sqlite/batch.ts +242 -242
- package/src/sqlite/catalog.ts +105 -108
- package/src/sqlite/connection.ts +227 -227
- package/src/sqlite/index-coverage.ts +54 -56
- package/src/sqlite/native.ts +83 -83
- package/src/sqlite/row-codec.ts +217 -221
- package/src/sqlite/sql-builder.ts +244 -244
- package/src/sqlite/transaction-queue.ts +87 -87
- package/src/sqlite/transactions.ts +33 -33
- package/src/sqlite/values.ts +24 -24
- package/src/testing/conformance/attachments.ts +138 -136
- package/src/testing/conformance/encryption.ts +150 -150
- package/src/testing/conformance/index.ts +161 -161
- package/src/testing/conformance/lifecycle.ts +99 -99
- package/src/testing/conformance/migrations.ts +177 -177
- package/src/testing/conformance/queries.ts +204 -167
- package/src/testing/conformance/records.ts +169 -169
- package/src/testing/conformance/scopes.ts +86 -88
- package/src/testing/conformance/transactions.ts +149 -149
- package/src/testing/faults.ts +21 -21
- package/src/testing/index.ts +17 -21
- package/src/testing/memory-adapter/collection.ts +214 -219
- package/src/testing/memory-adapter/index.ts +510 -492
- package/src/testing/memory-adapter/migrations.ts +117 -119
- package/src/testing/memory-adapter/reset.ts +50 -50
- package/src/testing/memory-adapter/store.ts +128 -134
|
@@ -1,63 +1,63 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Reconciliation: the two ways the database and the disk can disagree.
|
|
3
|
-
*
|
|
4
|
-
* An **orphaned artifact** is a file with no reference — left by a rolled-back
|
|
5
|
-
* transaction, or by a crash between the write and the insert. A **dangling
|
|
6
|
-
* reference** is the reverse: a row pointing at a file the operating system
|
|
7
|
-
* reclaimed, or the user deleted through a file manager.
|
|
8
|
-
*
|
|
9
|
-
* App-triggered only (FR-073d). A background sweep would run during a user's
|
|
10
|
-
* session without their knowledge, delete files it believes are orphans, and
|
|
11
|
-
* have no way to distinguish "orphan" from "written by a transaction that has
|
|
12
|
-
* not committed yet". Handing the trigger to the app makes that an explicit
|
|
13
|
-
* decision at a moment the app knows is quiet.
|
|
14
|
-
*/
|
|
15
|
-
|
|
16
|
-
import type { ReconciliationReport } from '../contract/attachment';
|
|
17
|
-
import { fileSystem, removeIfPresent } from '../platform/fs';
|
|
18
|
-
import { byteOrder } from '../query/compare';
|
|
19
|
-
import type { Executor } from '../sqlite/connection';
|
|
20
|
-
import { artifactPath, artifactsDirectory } from './paths';
|
|
21
|
-
import { listReferences, type ArtifactContext } from './store';
|
|
22
|
-
|
|
23
|
-
export type ReconcileOptions = {
|
|
24
|
-
/** Off by default: deleting a user's file is never an implied yes. */
|
|
25
|
-
removeOrphans?: boolean;
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
async function filesOnDisk(context: ArtifactContext): Promise<string[]> {
|
|
29
|
-
try {
|
|
30
|
-
return await fileSystem().readdir(artifactsDirectory(context.layout, context.scopeKey));
|
|
31
|
-
} catch {
|
|
32
|
-
// No directory means no artifacts, which is a valid answer rather than
|
|
33
|
-
// a failure — a scope that never wrote one never created it.
|
|
34
|
-
return [];
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
export async function reconcileArtifacts(
|
|
39
|
-
context: ArtifactContext,
|
|
40
|
-
executor: Executor,
|
|
41
|
-
options: ReconcileOptions = {},
|
|
42
|
-
): Promise<ReconciliationReport> {
|
|
43
|
-
const references = await listReferences(executor);
|
|
44
|
-
const referenced = new Set(references.map(reference => reference.id));
|
|
45
|
-
const present = new Set(await filesOnDisk(context));
|
|
46
|
-
|
|
47
|
-
const orphanedArtifacts = [...present].filter(id => !referenced.has(id)).sort(byteOrder);
|
|
48
|
-
const danglingReferences = references
|
|
49
|
-
.filter(reference => !present.has(reference.id))
|
|
50
|
-
.map(reference => reference.id)
|
|
51
|
-
.sort(byteOrder);
|
|
52
|
-
|
|
53
|
-
const removedArtifacts: string[] = [];
|
|
54
|
-
if (options.removeOrphans) {
|
|
55
|
-
for (const id of orphanedArtifacts) {
|
|
56
|
-
if (await removeIfPresent(artifactPath(context.layout, context.scopeKey, id))) {
|
|
57
|
-
removedArtifacts.push(id);
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
return { orphanedArtifacts, danglingReferences, removedArtifacts };
|
|
63
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* Reconciliation: the two ways the database and the disk can disagree.
|
|
3
|
+
*
|
|
4
|
+
* An **orphaned artifact** is a file with no reference — left by a rolled-back
|
|
5
|
+
* transaction, or by a crash between the write and the insert. A **dangling
|
|
6
|
+
* reference** is the reverse: a row pointing at a file the operating system
|
|
7
|
+
* reclaimed, or the user deleted through a file manager.
|
|
8
|
+
*
|
|
9
|
+
* App-triggered only (FR-073d). A background sweep would run during a user's
|
|
10
|
+
* session without their knowledge, delete files it believes are orphans, and
|
|
11
|
+
* have no way to distinguish "orphan" from "written by a transaction that has
|
|
12
|
+
* not committed yet". Handing the trigger to the app makes that an explicit
|
|
13
|
+
* decision at a moment the app knows is quiet.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import type { ReconciliationReport } from '../contract/attachment';
|
|
17
|
+
import { fileSystem, removeIfPresent } from '../platform/fs';
|
|
18
|
+
import { byteOrder } from '../query/compare';
|
|
19
|
+
import type { Executor } from '../sqlite/connection';
|
|
20
|
+
import { artifactPath, artifactsDirectory } from './paths';
|
|
21
|
+
import { listReferences, type ArtifactContext } from './store';
|
|
22
|
+
|
|
23
|
+
export type ReconcileOptions = {
|
|
24
|
+
/** Off by default: deleting a user's file is never an implied yes. */
|
|
25
|
+
removeOrphans?: boolean;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
async function filesOnDisk(context: ArtifactContext): Promise<string[]> {
|
|
29
|
+
try {
|
|
30
|
+
return await fileSystem().readdir(artifactsDirectory(context.layout, context.scopeKey));
|
|
31
|
+
} catch {
|
|
32
|
+
// No directory means no artifacts, which is a valid answer rather than
|
|
33
|
+
// a failure — a scope that never wrote one never created it.
|
|
34
|
+
return [];
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export async function reconcileArtifacts(
|
|
39
|
+
context: ArtifactContext,
|
|
40
|
+
executor: Executor,
|
|
41
|
+
options: ReconcileOptions = {},
|
|
42
|
+
): Promise<ReconciliationReport> {
|
|
43
|
+
const references = await listReferences(executor);
|
|
44
|
+
const referenced = new Set(references.map(reference => reference.id));
|
|
45
|
+
const present = new Set(await filesOnDisk(context));
|
|
46
|
+
|
|
47
|
+
const orphanedArtifacts = [...present].filter(id => !referenced.has(id)).sort(byteOrder);
|
|
48
|
+
const danglingReferences = references
|
|
49
|
+
.filter(reference => !present.has(reference.id))
|
|
50
|
+
.map(reference => reference.id)
|
|
51
|
+
.sort(byteOrder);
|
|
52
|
+
|
|
53
|
+
const removedArtifacts: string[] = [];
|
|
54
|
+
if (options.removeOrphans) {
|
|
55
|
+
for (const id of orphanedArtifacts) {
|
|
56
|
+
if (await removeIfPresent(artifactPath(context.layout, context.scopeKey, id))) {
|
|
57
|
+
removedArtifacts.push(id);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return { orphanedArtifacts, danglingReferences, removedArtifacts };
|
|
63
|
+
}
|