@korajs/store 1.0.0-beta.11 → 1.0.0-beta.12
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/dist/index.cjs +66 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +13 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.js +66 -0
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -3050,6 +3050,10 @@ var SubscriptionManager = class {
|
|
|
3050
3050
|
* Schedules a microtask flush to batch multiple mutations in the same tick.
|
|
3051
3051
|
*/
|
|
3052
3052
|
notify(collection, _operation) {
|
|
3053
|
+
this.invalidate(collection);
|
|
3054
|
+
}
|
|
3055
|
+
/** Invalidate a collection after a local-view change that has no domain operation. */
|
|
3056
|
+
invalidate(collection) {
|
|
3053
3057
|
this.pendingCollections.add(collection);
|
|
3054
3058
|
this.scheduleFlush();
|
|
3055
3059
|
}
|
|
@@ -3792,6 +3796,9 @@ var Store = class {
|
|
|
3792
3796
|
*/
|
|
3793
3797
|
async open() {
|
|
3794
3798
|
await this.adapter.open(this.schema);
|
|
3799
|
+
await this.adapter.execute(
|
|
3800
|
+
"CREATE TABLE IF NOT EXISTS _kora_scope_retractions (collection TEXT NOT NULL, record_id TEXT NOT NULL, PRIMARY KEY (collection, record_id))"
|
|
3801
|
+
);
|
|
3795
3802
|
await this.runMigrationsIfNeeded();
|
|
3796
3803
|
this.nodeId = await this.loadOrGenerateNodeId();
|
|
3797
3804
|
this.clock = new import_core23.HybridLogicalClock(this.nodeId);
|
|
@@ -3911,6 +3918,22 @@ var Store = class {
|
|
|
3911
3918
|
[op.id]
|
|
3912
3919
|
);
|
|
3913
3920
|
if (existing.length > 0) {
|
|
3921
|
+
const retracted = await this.adapter.query(
|
|
3922
|
+
"SELECT record_id FROM _kora_scope_retractions WHERE collection = ? AND record_id = ?",
|
|
3923
|
+
[collection, op.recordId]
|
|
3924
|
+
);
|
|
3925
|
+
if (retracted.length > 0) {
|
|
3926
|
+
await this.adapter.transaction(async (tx) => {
|
|
3927
|
+
await tx.execute(`UPDATE ${(0, import_core23.quoteIdent)(collection)} SET _deleted = 0 WHERE id = ?`, [
|
|
3928
|
+
op.recordId
|
|
3929
|
+
]);
|
|
3930
|
+
await tx.execute(
|
|
3931
|
+
"DELETE FROM _kora_scope_retractions WHERE collection = ? AND record_id = ?",
|
|
3932
|
+
[collection, op.recordId]
|
|
3933
|
+
);
|
|
3934
|
+
});
|
|
3935
|
+
this.subscriptionManager.invalidate(collection);
|
|
3936
|
+
}
|
|
3914
3937
|
return "duplicate";
|
|
3915
3938
|
}
|
|
3916
3939
|
if (this.clock) {
|
|
@@ -4096,6 +4119,49 @@ var Store = class {
|
|
|
4096
4119
|
this.subscriptionManager.notify(collection, op);
|
|
4097
4120
|
return "applied";
|
|
4098
4121
|
}
|
|
4122
|
+
/**
|
|
4123
|
+
* Hide a record from this client's authorized materialized view. This writes no
|
|
4124
|
+
* replicated operation and therefore cannot be mistaken for a domain deletion.
|
|
4125
|
+
* The marker lets a later authoritative backfill reactivate the retained row.
|
|
4126
|
+
*/
|
|
4127
|
+
async applyScopeRetraction(collection, recordId) {
|
|
4128
|
+
this.ensureOpen();
|
|
4129
|
+
if (!this.schema.collections[collection]) return;
|
|
4130
|
+
await this.adapter.transaction(async (tx) => {
|
|
4131
|
+
await tx.execute(`UPDATE ${(0, import_core23.quoteIdent)(collection)} SET _deleted = 1 WHERE id = ?`, [recordId]);
|
|
4132
|
+
await tx.execute(
|
|
4133
|
+
"INSERT OR REPLACE INTO _kora_scope_retractions (collection, record_id) VALUES (?, ?)",
|
|
4134
|
+
[collection, recordId]
|
|
4135
|
+
);
|
|
4136
|
+
});
|
|
4137
|
+
this.subscriptionManager.invalidate(collection);
|
|
4138
|
+
}
|
|
4139
|
+
/** Hide all live rows that no longer match a newly accepted server scope. */
|
|
4140
|
+
async applyScopeNarrowing(scopes) {
|
|
4141
|
+
this.ensureOpen();
|
|
4142
|
+
const retractions = [];
|
|
4143
|
+
for (const [collection, definition] of Object.entries(this.schema.collections)) {
|
|
4144
|
+
const rows = await this.adapter.query(
|
|
4145
|
+
`SELECT * FROM ${(0, import_core23.quoteIdent)(collection)} WHERE _deleted = 0`
|
|
4146
|
+
);
|
|
4147
|
+
const predicate = scopes[collection];
|
|
4148
|
+
for (const row of rows) {
|
|
4149
|
+
const record = deserializeRecord(row, definition.fields);
|
|
4150
|
+
const matches = predicate !== void 0 && Object.entries(predicate).every(([field, expected]) => {
|
|
4151
|
+
if (expected && typeof expected === "object" && !Array.isArray(expected) && "$in" in expected) {
|
|
4152
|
+
const values = expected.$in;
|
|
4153
|
+
return Array.isArray(values) && values.some((value) => Object.is(record[field], value));
|
|
4154
|
+
}
|
|
4155
|
+
return Object.is(record[field], expected);
|
|
4156
|
+
});
|
|
4157
|
+
if (!matches) {
|
|
4158
|
+
await this.applyScopeRetraction(collection, String(record.id));
|
|
4159
|
+
retractions.push({ collection, recordId: String(record.id) });
|
|
4160
|
+
}
|
|
4161
|
+
}
|
|
4162
|
+
}
|
|
4163
|
+
return retractions;
|
|
4164
|
+
}
|
|
4099
4165
|
/**
|
|
4100
4166
|
* Materialize update/delete operations that were logged for a record BEFORE
|
|
4101
4167
|
* its insert arrived (reordered delivery). Runs inside the insert's write
|