@feltdb/core 0.11.8 → 0.11.9
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/cli/index.js +0 -0
- package/dist/composition.d.ts +697 -0
- package/dist/composition.d.ts.map +1 -0
- package/dist/composition.js +1218 -0
- package/dist/create/package-versions.js +1 -1
- package/dist/create/server-source/crates/feltdb/src/lib.rs +363 -2
- package/dist/create/server-source/crates/feltdb/src/read_basis.rs +257 -0
- package/dist/create/server-source/crates/feltdb/src/state_contract.rs +442 -73
- package/dist/create/server-source/crates/feltdb/src/workload_diagnostics.rs +18 -4
- package/dist/create/server-source/crates/feltdb-server/src/main.rs +198 -10
- package/dist/db.d.ts +12 -1
- package/dist/db.d.ts.map +1 -1
- package/dist/db.js +19 -1
- package/dist/embedded-transaction.d.ts +21 -1
- package/dist/embedded-transaction.d.ts.map +1 -1
- package/dist/embedded-transaction.js +96 -0
- package/dist/feltdb.d.ts +8 -0
- package/dist/feltdb.d.ts.map +1 -1
- package/dist/file-db.d.ts +8 -1
- package/dist/file-db.d.ts.map +1 -1
- package/dist/file-db.js +20 -1
- package/dist/flowspec.d.ts +7 -0
- package/dist/flowspec.d.ts.map +1 -1
- package/dist/flowspec.js +13 -1
- package/dist/http-db.d.ts +7 -0
- package/dist/http-db.d.ts.map +1 -1
- package/dist/http-db.js +38 -6
- package/dist/index-core.d.ts +1 -0
- package/dist/index-core.d.ts.map +1 -1
- package/dist/index-core.js +1 -0
- package/dist/indexeddb-db.d.ts +3 -1
- package/dist/indexeddb-db.d.ts.map +1 -1
- package/dist/indexeddb-db.js +50 -2
- package/dist/intent.d.ts +4 -2
- package/dist/intent.d.ts.map +1 -1
- package/dist/memory-db.d.ts +2 -1
- package/dist/memory-db.d.ts.map +1 -1
- package/dist/memory-db.js +13 -1
- package/dist/proposal.d.ts +5 -0
- package/dist/proposal.d.ts.map +1 -1
- package/dist/proposal.js +6 -2
- package/dist/state-impact.d.ts +245 -0
- package/dist/state-impact.d.ts.map +1 -0
- package/dist/state-impact.js +404 -0
- package/dist/studio-app/assets/{feltdb_wasm-D58hv7aa.js → feltdb_wasm-DGGqm9GK.js} +1 -1
- package/dist/studio-app/assets/feltdb_wasm_bg-BYJo87WY.wasm +0 -0
- package/dist/studio-app/assets/index-qLeZcPW_.js +30 -0
- package/dist/studio-app/index.html +1 -1
- package/dist/transaction.d.ts +61 -1
- package/dist/transaction.d.ts.map +1 -1
- package/dist/transaction.js +59 -0
- package/dist/wasm/feltdb_wasm_bg.wasm +0 -0
- package/package.json +1 -1
- package/dist/create/server-source/crates/feltdb-wasm/test.db +0 -0
- package/dist/create/server-source/crates/feltdb-wasm/test_wasm.db.lock +0 -0
- package/dist/studio-app/assets/feltdb_wasm_bg-BgFXYOtc.wasm +0 -0
- package/dist/studio-app/assets/index-Ccecp6rc.js +0 -30
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
<!doctype html><html lang="en"><head><meta charset="UTF-8"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#17211b"/><title>FeltDB Studio</title> <script type="module" crossorigin src="/assets/index-
|
|
1
|
+
<!doctype html><html lang="en"><head><meta charset="UTF-8"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#17211b"/><title>FeltDB Studio</title> <script type="module" crossorigin src="/assets/index-qLeZcPW_.js"></script>
|
|
2
2
|
<link rel="stylesheet" crossorigin href="/assets/index-BrsF-kWL.css">
|
|
3
3
|
</head><body><div id="root"></div></body></html>
|
package/dist/transaction.d.ts
CHANGED
|
@@ -102,8 +102,48 @@ export interface AtomicTransactionOperationRequest {
|
|
|
102
102
|
export interface AtomicTransactionDocument {
|
|
103
103
|
transactionId?: string;
|
|
104
104
|
preconditions?: AtomicTransactionPrecondition[];
|
|
105
|
+
fences?: TransactionReadBasis[];
|
|
105
106
|
operations: AtomicTransactionOperationRequest[];
|
|
106
107
|
}
|
|
108
|
+
/**
|
|
109
|
+
* State a decision was read from: records by identity, and equality
|
|
110
|
+
* predicates over a collection ("every record of `collection` whose fields
|
|
111
|
+
* equal these values", including records that do not exist yet).
|
|
112
|
+
*
|
|
113
|
+
* Generic: it names collections, ids, fields, and values, never what they mean.
|
|
114
|
+
*/
|
|
115
|
+
export interface TransactionReadSet {
|
|
116
|
+
records?: Array<{
|
|
117
|
+
collection: string;
|
|
118
|
+
id: string;
|
|
119
|
+
}>;
|
|
120
|
+
predicates?: Array<{
|
|
121
|
+
collection: string;
|
|
122
|
+
where: Array<{
|
|
123
|
+
field: string;
|
|
124
|
+
eq: unknown;
|
|
125
|
+
}>;
|
|
126
|
+
}>;
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* A read set, and what the authority held for it at one moment.
|
|
130
|
+
*
|
|
131
|
+
* Issued by `db.readBasis()`. The token is opaque and meaningful only to the
|
|
132
|
+
* authority that issued it: a transaction that carries this basis as a fence
|
|
133
|
+
* commits only if re-reading the same set, inside the commit decision, yields
|
|
134
|
+
* the same token. Records and predicates outside the set never conflict.
|
|
135
|
+
*/
|
|
136
|
+
export interface TransactionReadBasis {
|
|
137
|
+
reads: TransactionReadSet;
|
|
138
|
+
token: string;
|
|
139
|
+
}
|
|
140
|
+
/** Largest number of records plus predicates one read basis may name. */
|
|
141
|
+
export declare const TRANSACTION_READ_SET_LIMIT = 1000;
|
|
142
|
+
/**
|
|
143
|
+
* Validate, de-duplicate, and order a read set, so that two descriptions of
|
|
144
|
+
* the same reads are one read set and one token.
|
|
145
|
+
*/
|
|
146
|
+
export declare function normaliseReadSet(reads: TransactionReadSet): Required<TransactionReadSet>;
|
|
107
147
|
export interface AtomicTransactionRequest {
|
|
108
148
|
transactionId: string;
|
|
109
149
|
operations: AtomicTransactionOperationRequest[];
|
|
@@ -114,6 +154,12 @@ export interface AtomicTransactionRequest {
|
|
|
114
154
|
* would make the guard a mutation.
|
|
115
155
|
*/
|
|
116
156
|
preconditions?: AtomicTransactionPrecondition[];
|
|
157
|
+
/**
|
|
158
|
+
* Read bases the transaction depends on. Each is re-evaluated inside the
|
|
159
|
+
* commit decision; if the state it names differs from what was read, the
|
|
160
|
+
* transaction is refused as a conflict and nothing is written.
|
|
161
|
+
*/
|
|
162
|
+
fences?: TransactionReadBasis[];
|
|
117
163
|
}
|
|
118
164
|
export interface AtomicTransactionResult {
|
|
119
165
|
/** Durable identity of the transaction. Stable across restart and replay. */
|
|
@@ -158,10 +204,21 @@ export interface AtomicTransactionScope {
|
|
|
158
204
|
* ```
|
|
159
205
|
*/
|
|
160
206
|
require(condition: AtomicTransactionPrecondition): AtomicTransactionScope;
|
|
207
|
+
/**
|
|
208
|
+
* Commit only if the state `basis` read is unchanged.
|
|
209
|
+
*
|
|
210
|
+
* ```ts
|
|
211
|
+
* const basis = await db.readBasis({ records: [{ collection: 'a', id: '1' }] });
|
|
212
|
+
* await db.transaction(tx => { tx.fence(basis); tx.collection('b').set('2', next); });
|
|
213
|
+
* ```
|
|
214
|
+
*/
|
|
215
|
+
fence(basis: TransactionReadBasis): AtomicTransactionScope;
|
|
161
216
|
/** Operations staged so far. */
|
|
162
217
|
readonly operations: readonly AtomicTransactionOperationRequest[];
|
|
163
218
|
/** Preconditions staged so far. */
|
|
164
219
|
readonly preconditions: readonly AtomicTransactionPrecondition[];
|
|
220
|
+
/** Read bases staged so far. */
|
|
221
|
+
readonly fences: readonly TransactionReadBasis[];
|
|
165
222
|
}
|
|
166
223
|
export interface AtomicTransactionOptions {
|
|
167
224
|
/**
|
|
@@ -179,7 +236,7 @@ export declare class AtomicTransactionError extends Error {
|
|
|
179
236
|
}
|
|
180
237
|
/** Which predicate failed, and what the authority actually holds. */
|
|
181
238
|
export interface ConditionalConflictDetail {
|
|
182
|
-
predicate: 'version' | 'epoch' | 'lease' | 'present' | 'missing';
|
|
239
|
+
predicate: 'version' | 'epoch' | 'lease' | 'present' | 'missing' | 'fence';
|
|
183
240
|
collection: string;
|
|
184
241
|
key: string;
|
|
185
242
|
expected?: number | string;
|
|
@@ -242,12 +299,15 @@ export declare class AtomicTransactionBuilder implements AtomicTransactionScope
|
|
|
242
299
|
readonly transactionId: string;
|
|
243
300
|
private readonly staged;
|
|
244
301
|
private readonly required;
|
|
302
|
+
private readonly fenced;
|
|
245
303
|
private sealed;
|
|
246
304
|
constructor(transactionId?: string);
|
|
247
305
|
get operations(): readonly AtomicTransactionOperationRequest[];
|
|
248
306
|
collection<T = unknown>(name: string): AtomicTransactionCollection<T>;
|
|
249
307
|
get preconditions(): readonly AtomicTransactionPrecondition[];
|
|
250
308
|
require(condition: AtomicTransactionPrecondition): AtomicTransactionScope;
|
|
309
|
+
get fences(): readonly TransactionReadBasis[];
|
|
310
|
+
fence(basis: TransactionReadBasis): AtomicTransactionScope;
|
|
251
311
|
/** Freeze the builder and produce the request to send. */
|
|
252
312
|
seal(): AtomicTransactionRequest;
|
|
253
313
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transaction.d.ts","sourceRoot":"","sources":["../src/transaction.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,6BAA6B;IAC5C,UAAU,EAAE,MAAM,CAAC;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,iCAAiC;IACjC,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB;;;;;;;;;OASG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,sEAAsE;IACtE,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,oCAAoC;IACpC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,iEAAiE;IACjE,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,yDAAyD;AACzD,MAAM,WAAW,sBAAsB;IACrC,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,uEAAuE;IACvE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,0DAA0D;AAC1D,MAAM,WAAW,iCAAiC;IAChD,UAAU,EAAE,MAAM,CAAC;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,iFAAiF;IACjF,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,uEAAuE;IACvE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,4DAA4D;IAC5D,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,WAAW,yBAAyB;IACxC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,aAAa,CAAC,EAAE,6BAA6B,EAAE,CAAC;IAChD,UAAU,EAAE,iCAAiC,EAAE,CAAC;CACjD;AAED,MAAM,WAAW,wBAAwB;IACvC,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,iCAAiC,EAAE,CAAC;IAChD;;;;;OAKG;IACH,aAAa,CAAC,EAAE,6BAA6B,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"transaction.d.ts","sourceRoot":"","sources":["../src/transaction.ts"],"names":[],"mappings":"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"}
|
package/dist/transaction.js
CHANGED
|
@@ -22,6 +22,50 @@
|
|
|
22
22
|
* a runtime that cannot provide that path refuses the transaction rather than
|
|
23
23
|
* silently degrading it into a sequence of independent writes.
|
|
24
24
|
*/
|
|
25
|
+
/** Largest number of records plus predicates one read basis may name. */
|
|
26
|
+
export const TRANSACTION_READ_SET_LIMIT = 1_000;
|
|
27
|
+
const READ_SET_SEGMENT = /^[A-Za-z0-9._-]{1,128}$/;
|
|
28
|
+
/**
|
|
29
|
+
* Validate, de-duplicate, and order a read set, so that two descriptions of
|
|
30
|
+
* the same reads are one read set and one token.
|
|
31
|
+
*/
|
|
32
|
+
export function normaliseReadSet(reads) {
|
|
33
|
+
if (!reads || typeof reads !== 'object')
|
|
34
|
+
throw new Error('a read set is required');
|
|
35
|
+
const records = new Map();
|
|
36
|
+
for (const record of reads.records ?? []) {
|
|
37
|
+
const collection = String(record?.collection ?? '');
|
|
38
|
+
const id = String(record?.id ?? '');
|
|
39
|
+
if (!READ_SET_SEGMENT.test(collection) || !READ_SET_SEGMENT.test(id))
|
|
40
|
+
throw new Error(`invalid read ${collection}:${id}`);
|
|
41
|
+
records.set(`${collection}:${id}`, { collection, id });
|
|
42
|
+
}
|
|
43
|
+
const predicates = new Map();
|
|
44
|
+
for (const predicate of reads.predicates ?? []) {
|
|
45
|
+
const collection = String(predicate?.collection ?? '');
|
|
46
|
+
if (!READ_SET_SEGMENT.test(collection))
|
|
47
|
+
throw new Error(`invalid predicate collection ${collection}`);
|
|
48
|
+
if (!Array.isArray(predicate.where) || predicate.where.length === 0) {
|
|
49
|
+
throw new Error(`a predicate over ${collection} must name at least one field; a whole-collection read is not a narrow fence`);
|
|
50
|
+
}
|
|
51
|
+
const where = predicate.where.map(condition => {
|
|
52
|
+
if (typeof condition?.field !== 'string' || !condition.field || !('eq' in condition)) {
|
|
53
|
+
throw new Error(`a predicate over ${collection} takes { field, eq } conditions`);
|
|
54
|
+
}
|
|
55
|
+
return { field: condition.field, eq: condition.eq };
|
|
56
|
+
}).sort((left, right) => (left.field < right.field ? -1 : left.field > right.field ? 1 : 0));
|
|
57
|
+
predicates.set(`${collection}\u0000${JSON.stringify(where)}`, { collection, where });
|
|
58
|
+
}
|
|
59
|
+
if (records.size + predicates.size === 0)
|
|
60
|
+
throw new Error('a read set that names nothing fences nothing');
|
|
61
|
+
if (records.size + predicates.size > TRANSACTION_READ_SET_LIMIT) {
|
|
62
|
+
throw new Error(`a read set may name at most ${TRANSACTION_READ_SET_LIMIT} records and predicates`);
|
|
63
|
+
}
|
|
64
|
+
return {
|
|
65
|
+
records: [...records.entries()].sort(([left], [right]) => (left < right ? -1 : 1)).map(([, value]) => value),
|
|
66
|
+
predicates: [...predicates.entries()].sort(([left], [right]) => (left < right ? -1 : 1)).map(([, value]) => value),
|
|
67
|
+
};
|
|
68
|
+
}
|
|
25
69
|
/** Thrown when a transaction cannot be committed. Nothing was applied. */
|
|
26
70
|
export class AtomicTransactionError extends Error {
|
|
27
71
|
transactionId;
|
|
@@ -119,6 +163,7 @@ export class AtomicTransactionBuilder {
|
|
|
119
163
|
transactionId;
|
|
120
164
|
staged = [];
|
|
121
165
|
required = [];
|
|
166
|
+
fenced = [];
|
|
122
167
|
sealed = false;
|
|
123
168
|
constructor(transactionId) {
|
|
124
169
|
this.transactionId = transactionId || generateTransactionId();
|
|
@@ -205,6 +250,19 @@ export class AtomicTransactionBuilder {
|
|
|
205
250
|
this.required.push({ ...normalised, id: String(condition.id) });
|
|
206
251
|
return this;
|
|
207
252
|
}
|
|
253
|
+
get fences() {
|
|
254
|
+
return this.fenced;
|
|
255
|
+
}
|
|
256
|
+
fence(basis) {
|
|
257
|
+
if (this.sealed) {
|
|
258
|
+
throw new Error('this transaction has already been committed; start a new one');
|
|
259
|
+
}
|
|
260
|
+
if (!basis || typeof basis.token !== 'string' || !basis.token) {
|
|
261
|
+
throw new Error('a fence requires a read basis issued by db.readBasis()');
|
|
262
|
+
}
|
|
263
|
+
this.fenced.push({ reads: normaliseReadSet(basis.reads), token: basis.token });
|
|
264
|
+
return this;
|
|
265
|
+
}
|
|
208
266
|
/** Freeze the builder and produce the request to send. */
|
|
209
267
|
seal() {
|
|
210
268
|
this.sealed = true;
|
|
@@ -212,6 +270,7 @@ export class AtomicTransactionBuilder {
|
|
|
212
270
|
transactionId: this.transactionId,
|
|
213
271
|
operations: [...this.staged],
|
|
214
272
|
preconditions: [...this.required],
|
|
273
|
+
...(this.fenced.length ? { fences: [...this.fenced] } : {}),
|
|
215
274
|
};
|
|
216
275
|
}
|
|
217
276
|
}
|
|
Binary file
|
package/package.json
CHANGED
|
File without changes
|
|
File without changes
|
|
Binary file
|