@microdelta/history 0.0.0 → 0.2.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.
- package/README.md +30 -4
- package/dist/api/history.alpha.d.ts +3 -0
- package/dist/api/history.beta.d.ts +3 -0
- package/dist/api/history.conformance.store.alpha.d.ts +3 -0
- package/dist/api/history.conformance.store.beta.d.ts +3 -0
- package/dist/api/history.conformance.store.public.d.ts +3 -0
- package/dist/api/history.conformance.store.raw.alpha.d.ts +215 -0
- package/dist/api/history.conformance.store.raw.beta.d.ts +215 -0
- package/dist/api/history.conformance.store.raw.public.d.ts +215 -0
- package/dist/api/history.conformance.store.raw.untrimmed.d.ts +215 -0
- package/dist/api/history.conformance.store.untrimmed.d.ts +3 -0
- package/dist/api/history.public.d.ts +3 -0
- package/dist/api/history.root.raw.alpha.d.ts +1371 -0
- package/dist/api/history.root.raw.beta.d.ts +425 -0
- package/dist/api/history.root.raw.public.d.ts +425 -0
- package/dist/api/history.root.raw.untrimmed.d.ts +1372 -0
- package/dist/api/history.shared.alpha.d.ts +1402 -0
- package/dist/api/history.shared.beta.d.ts +456 -0
- package/dist/api/history.shared.public.d.ts +456 -0
- package/dist/api/history.shared.untrimmed.d.ts +1403 -0
- package/dist/api/history.untrimmed.d.ts +3 -0
- package/dist/api/tsdoc-metadata.json +11 -0
- package/dist/src/completed-results.d.ts +99 -0
- package/dist/src/completed-results.d.ts.map +1 -0
- package/dist/src/completed-results.js +2 -0
- package/dist/src/completed-results.js.map +1 -0
- package/dist/src/durable/contracts.d.ts +612 -0
- package/dist/src/durable/contracts.d.ts.map +1 -0
- package/dist/src/durable/contracts.js +2 -0
- package/dist/src/durable/contracts.js.map +1 -0
- package/dist/src/durable/errors.d.ts +94 -0
- package/dist/src/durable/errors.d.ts.map +1 -0
- package/dist/src/durable/errors.js +118 -0
- package/dist/src/durable/errors.js.map +1 -0
- package/dist/src/durable/index.d.ts +9 -0
- package/dist/src/durable/index.d.ts.map +1 -0
- package/dist/src/durable/index.js +770 -0
- package/dist/src/durable/index.js.map +1 -0
- package/dist/src/durable/journal.d.ts +53 -0
- package/dist/src/durable/journal.d.ts.map +1 -0
- package/dist/src/durable/journal.js +174 -0
- package/dist/src/durable/journal.js.map +1 -0
- package/dist/src/durable/locator.d.ts +31 -0
- package/dist/src/durable/locator.d.ts.map +1 -0
- package/dist/src/durable/locator.js +50 -0
- package/dist/src/durable/locator.js.map +1 -0
- package/dist/src/durable/records.d.ts +40 -0
- package/dist/src/durable/records.d.ts.map +1 -0
- package/dist/src/durable/records.js +74 -0
- package/dist/src/durable/records.js.map +1 -0
- package/dist/src/durable/schema.d.ts +37 -0
- package/dist/src/durable/schema.d.ts.map +1 -0
- package/dist/src/durable/schema.js +335 -0
- package/dist/src/durable/schema.js.map +1 -0
- package/dist/src/durable/selected-index.d.ts +94 -0
- package/dist/src/durable/selected-index.d.ts.map +1 -0
- package/dist/src/durable/selected-index.js +594 -0
- package/dist/src/durable/selected-index.js.map +1 -0
- package/dist/src/index.d.ts +28 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +15 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/store/index.d.ts +128 -0
- package/dist/src/store/index.d.ts.map +1 -0
- package/dist/src/store/index.js +33 -0
- package/dist/src/store/index.js.map +1 -0
- package/dist/src/store/memory/index.d.ts +24 -0
- package/dist/src/store/memory/index.d.ts.map +1 -0
- package/dist/src/store/memory/index.js +162 -0
- package/dist/src/store/memory/index.js.map +1 -0
- package/dist/src/types.d.ts +100 -0
- package/dist/src/types.d.ts.map +1 -0
- package/dist/src/types.js +2 -0
- package/dist/src/types.js.map +1 -0
- package/dist/test/conformance/store/index.d.ts +34 -0
- package/dist/test/conformance/store/index.d.ts.map +1 -0
- package/dist/test/conformance/store/index.js +368 -0
- package/dist/test/conformance/store/index.js.map +1 -0
- package/package.json +48 -8
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Result History & Publication. This entry exposes the existing row Store,
|
|
3
|
+
* its memory adapter and compatibility schema unchanged, the exact
|
|
4
|
+
* completed-result reading ports, and the project-private alpha durable
|
|
5
|
+
* authority that owns attempts, the single logical writer, atomic publication,
|
|
6
|
+
* acceptance records, environment namespaces, recorded promotions and Run
|
|
7
|
+
* Supervision's opaque operation journal. It never decides candidate validity
|
|
8
|
+
* or freshness and never interprets journal records.
|
|
9
|
+
* @packageDocumentation
|
|
10
|
+
*/
|
|
11
|
+
export { DuplicateRowError, FingerprintAlgorithmMismatchError, InvalidStorePatchError, MissingRowError, } from './store/index.js';
|
|
12
|
+
export type { FieldRow, GenerationPatch, GenerationRow, Store, StoreMetadata, SubjectPatch, SubjectRow, } from './store/index.js';
|
|
13
|
+
export { createMemoryStore } from './store/memory/index.js';
|
|
14
|
+
export type { MemoryStoreOptions } from './store/memory/index.js';
|
|
15
|
+
export type { ICompletedNavigationReader, ICompletedProjectionReader, ICompletedResultReader, ICompletedResultReference, ISelectedFingerprintRequest, ISelectedFingerprintResolution, ISelectedReadRequest, } from './completed-results.js';
|
|
16
|
+
export type { IAddressSegment, IOperation, ISelectedFact, ISelectedNode, IValueProjectionDescriptor, IValueProjectionFact, IValueProjectionMember, IValueProjectionTraversal, } from '@microdelta/value';
|
|
17
|
+
export { AttemptConflictError, AttemptStateError, HistoryClockError, HistoryIntegrityError, HistorySchemaError, JournalConflictError, JournalVersionError, StaleWriterError, } from './durable/errors.js';
|
|
18
|
+
export { openDurableHistory } from './durable/index.js';
|
|
19
|
+
export type { IAbandonRequest, IAcceptanceRecord, IAcceptanceRequest, IAttemptRecord, IAttemptRequest, IAttemptState, ICompletedEnvelope, IDurableHistory, IDurableHistoryOptions, IHistoryScope, IJournalAddress, IJournalCommit, IJournalDeclaration, IJournalFormat, IJournalQuery, IJournalRecord, IJournalWrite, IOperationJournal, IPromotionQuery, IPromotionRecord, IPromotionRequest, IRecoveryOutcome, IResultVerification, IScopedSubject, IStageRequest, IVersionedRecord, IVersionedSubject, IWriterAcquisition, IWriterAcquisitionRequest, IWriterContention, IWriterLease, IWriterRenewal, } from './durable/contracts.js';
|
|
20
|
+
/**
|
|
21
|
+
* Machine host contracts surfaced by the durable authority's options and by
|
|
22
|
+
* the connections its SQLite capability returns. They are re-exported
|
|
23
|
+
* intentionally, as Value and Tracking re-export the host contracts they
|
|
24
|
+
* surface, so alpha consumers name Machine's exact types from History.
|
|
25
|
+
*/
|
|
26
|
+
export type { IClockCapability, ISha256Capability, ISqliteCapability, ISqliteConnection, ISqliteRow, ISqliteRunResult, ISqliteStatement, ISqliteSynchronousResult, ISqliteValue, } from '@microdelta/machine';
|
|
27
|
+
export type { Divergence, Fingerprint, GenerationState, Identity, Outcome, Path, RecordedRead, ResultKey, Subject, } from './types.js';
|
|
28
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EACL,iBAAiB,EACjB,iCAAiC,EACjC,sBAAsB,EACtB,eAAe,GAChB,MAAM,kBAAkB,CAAC;AAC1B,YAAY,EACV,QAAQ,EACR,eAAe,EACf,aAAa,EACb,KAAK,EACL,aAAa,EACb,YAAY,EACZ,UAAU,GACX,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC5D,YAAY,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAClE,YAAY,EACV,0BAA0B,EAC1B,0BAA0B,EAC1B,sBAAsB,EACtB,yBAAyB,EACzB,2BAA2B,EAC3B,8BAA8B,EAC9B,oBAAoB,GACrB,MAAM,wBAAwB,CAAC;AAChC,YAAY,EACV,eAAe,EACf,UAAU,EACV,aAAa,EACb,aAAa,EACb,0BAA0B,EAC1B,oBAAoB,EACpB,sBAAsB,EACtB,yBAAyB,GAC1B,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,oBAAoB,EACpB,iBAAiB,EACjB,iBAAiB,EACjB,qBAAqB,EACrB,kBAAkB,EAClB,oBAAoB,EACpB,mBAAmB,EACnB,gBAAgB,GACjB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACxD,YAAY,EACV,eAAe,EACf,iBAAiB,EACjB,kBAAkB,EAClB,cAAc,EACd,eAAe,EACf,aAAa,EACb,kBAAkB,EAClB,eAAe,EACf,sBAAsB,EACtB,aAAa,EACb,eAAe,EACf,cAAc,EACd,mBAAmB,EACnB,cAAc,EACd,aAAa,EACb,cAAc,EACd,aAAa,EACb,iBAAiB,EACjB,eAAe,EACf,gBAAgB,EAChB,iBAAiB,EACjB,gBAAgB,EAChB,mBAAmB,EACnB,cAAc,EACd,aAAa,EACb,gBAAgB,EAChB,iBAAiB,EACjB,kBAAkB,EAClB,yBAAyB,EACzB,iBAAiB,EACjB,YAAY,EACZ,cAAc,GACf,MAAM,wBAAwB,CAAC;AAChC;;;;;GAKG;AACH,YAAY,EACV,gBAAgB,EAChB,iBAAiB,EACjB,iBAAiB,EACjB,iBAAiB,EACjB,UAAU,EACV,gBAAgB,EAChB,gBAAgB,EAChB,wBAAwB,EACxB,YAAY,GACb,MAAM,qBAAqB,CAAC;AAC7B,YAAY,EACV,UAAU,EACV,WAAW,EACX,eAAe,EACf,QAAQ,EACR,OAAO,EACP,IAAI,EACJ,YAAY,EACZ,SAAS,EACT,OAAO,GACR,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Result History & Publication. This entry exposes the existing row Store,
|
|
3
|
+
* its memory adapter and compatibility schema unchanged, the exact
|
|
4
|
+
* completed-result reading ports, and the project-private alpha durable
|
|
5
|
+
* authority that owns attempts, the single logical writer, atomic publication,
|
|
6
|
+
* acceptance records, environment namespaces, recorded promotions and Run
|
|
7
|
+
* Supervision's opaque operation journal. It never decides candidate validity
|
|
8
|
+
* or freshness and never interprets journal records.
|
|
9
|
+
* @packageDocumentation
|
|
10
|
+
*/
|
|
11
|
+
export { DuplicateRowError, FingerprintAlgorithmMismatchError, InvalidStorePatchError, MissingRowError, } from './store/index.js';
|
|
12
|
+
export { createMemoryStore } from './store/memory/index.js';
|
|
13
|
+
export { AttemptConflictError, AttemptStateError, HistoryClockError, HistoryIntegrityError, HistorySchemaError, JournalConflictError, JournalVersionError, StaleWriterError, } from './durable/errors.js';
|
|
14
|
+
export { openDurableHistory } from './durable/index.js';
|
|
15
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EACL,iBAAiB,EACjB,iCAAiC,EACjC,sBAAsB,EACtB,eAAe,GAChB,MAAM,kBAAkB,CAAC;AAU1B,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAqB5D,OAAO,EACL,oBAAoB,EACpB,iBAAiB,EACjB,iBAAiB,EACjB,qBAAqB,EACrB,kBAAkB,EAClB,oBAAoB,EACpB,mBAAmB,EACnB,gBAAgB,GACjB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC"}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import type { Fingerprint, GenerationState, Identity, Path, RecordedRead, ResultKey, Subject } from '../types.js';
|
|
2
|
+
/** Persisted format identifiers, checked before using a store's fingerprints. @public */
|
|
3
|
+
export interface StoreMetadata {
|
|
4
|
+
schemaVersion: number;
|
|
5
|
+
fingerprintAlgorithm: string;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* One compare-and-set row per complete result key. Repository owns generation
|
|
9
|
+
* meaning; claim owns lease meaning. Storage only preserves and patches columns.
|
|
10
|
+
* @public
|
|
11
|
+
*/
|
|
12
|
+
export interface SubjectRow {
|
|
13
|
+
key: ResultKey;
|
|
14
|
+
subject: Subject;
|
|
15
|
+
/** Nonnegative safe-integer CAS token, incremented once per successful CAS. */
|
|
16
|
+
version: number;
|
|
17
|
+
currentGeneration: number | null;
|
|
18
|
+
claim: null | {
|
|
19
|
+
generation: number;
|
|
20
|
+
holder: string;
|
|
21
|
+
leaseUntil: number;
|
|
22
|
+
progress: {
|
|
23
|
+
fingerprint: Fingerprint;
|
|
24
|
+
value: unknown;
|
|
25
|
+
} | null;
|
|
26
|
+
};
|
|
27
|
+
durations: number[];
|
|
28
|
+
}
|
|
29
|
+
/** A retained attempt, with lifecycle and numbering supplied by its caller. @public */
|
|
30
|
+
export interface GenerationRow {
|
|
31
|
+
key: ResultKey;
|
|
32
|
+
generation: number;
|
|
33
|
+
state: GenerationState;
|
|
34
|
+
reads: RecordedRead[];
|
|
35
|
+
identity: Identity | undefined;
|
|
36
|
+
startedAt: number;
|
|
37
|
+
endedAt: number | null;
|
|
38
|
+
cost: Record<string, number>;
|
|
39
|
+
arrival: string;
|
|
40
|
+
abandonReason?: 'error' | 'lease-expired' | 'refused';
|
|
41
|
+
error?: {
|
|
42
|
+
message: string;
|
|
43
|
+
stack?: string;
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
/** An immutable value node and its caller-computed fingerprint. @public */
|
|
47
|
+
export interface FieldRow {
|
|
48
|
+
key: ResultKey;
|
|
49
|
+
generation: number;
|
|
50
|
+
path: Path;
|
|
51
|
+
fingerprint: Fingerprint;
|
|
52
|
+
value: unknown;
|
|
53
|
+
}
|
|
54
|
+
/** Writable subject columns; the complete key and CAS token cannot be patched. @public */
|
|
55
|
+
export type SubjectPatch = Partial<Omit<SubjectRow, 'key' | 'version'>>;
|
|
56
|
+
/** Writable generation columns; tuple identity cannot change after insertion. @public */
|
|
57
|
+
export type GenerationPatch = Partial<Omit<GenerationRow, 'key' | 'generation'>>;
|
|
58
|
+
/**
|
|
59
|
+
* Storage mechanism for independent rows, with linearizable subject CAS.
|
|
60
|
+
* All inputs and returned rows are detached snapshots: caller mutation cannot
|
|
61
|
+
* alter persisted data. Values may only change by inserting another generation.
|
|
62
|
+
* There is no transaction spanning these methods; callers must not infer atomic
|
|
63
|
+
* claim/generation publication from the per-row CAS guarantee.
|
|
64
|
+
* @public
|
|
65
|
+
*/
|
|
66
|
+
export interface Store {
|
|
67
|
+
/** Return detached format metadata; opening code must reject algorithm mismatches. */
|
|
68
|
+
meta(): Promise<StoreMetadata>;
|
|
69
|
+
/** Read a detached subject snapshot, or undefined for an absent tuple. */
|
|
70
|
+
getSubject(key: ResultKey): Promise<SubjectRow | undefined>;
|
|
71
|
+
/** Insert only; duplicate tuples reject, as do versions outside safe integers. */
|
|
72
|
+
putSubject(row: SubjectRow): Promise<void>;
|
|
73
|
+
/**
|
|
74
|
+
* Atomically apply a shallow column patch only when the stored version matches.
|
|
75
|
+
* Success increments that version once, even for an empty patch; a missing or
|
|
76
|
+
* stale row returns false without changes. Key/version properties reject at
|
|
77
|
+
* runtime, including extras passed from untyped JavaScript callers.
|
|
78
|
+
* An exhausted MAX_SAFE_INTEGER version rejects rather than reporting success
|
|
79
|
+
* without advancing the token. Neither rejection changes the stored row.
|
|
80
|
+
*/
|
|
81
|
+
casSubject(key: ResultKey, expectedVersion: number, patch: SubjectPatch): Promise<boolean>;
|
|
82
|
+
/** Read a detached generation, or undefined for an absent tuple. */
|
|
83
|
+
getGeneration(key: ResultKey, generation: number): Promise<GenerationRow | undefined>;
|
|
84
|
+
/** Return detached rows for exactly this complete key; ordering is unspecified. */
|
|
85
|
+
listGenerations(key: ResultKey): Promise<GenerationRow[]>;
|
|
86
|
+
/** Insert only; generation numbers are supplied, never allocated by storage. */
|
|
87
|
+
putGeneration(row: GenerationRow): Promise<void>;
|
|
88
|
+
/** Patch an existing row; missing tuples and attempts to change its key reject. */
|
|
89
|
+
updateGeneration(key: ResultKey, generation: number, patch: GenerationPatch): Promise<void>;
|
|
90
|
+
/**
|
|
91
|
+
* Insert an atomic batch of immutable fields. Duplicate addresses, within the
|
|
92
|
+
* batch or already stored, reject the whole batch without inserting anything.
|
|
93
|
+
* This proposed storage refinement enforces retained-value immutability.
|
|
94
|
+
*/
|
|
95
|
+
putFields(rows: FieldRow[]): Promise<void>;
|
|
96
|
+
/** Return requested field snapshots; absent paths are omitted. */
|
|
97
|
+
getFields(key: ResultKey, generation: number, paths: Path[]): Promise<FieldRow[]>;
|
|
98
|
+
/** Return requested fingerprints without reading/deserializing any field value. */
|
|
99
|
+
getFingerprints(key: ResultKey, generation: number, paths: Path[]): Promise<Map<Path, Fingerprint>>;
|
|
100
|
+
/**
|
|
101
|
+
* Query leases strictly less than now, oldest first, with at most limit rows.
|
|
102
|
+
* Zero limit returns no rows. This query never sweeps or changes a claim.
|
|
103
|
+
*/
|
|
104
|
+
expiredClaims(now: number, limit: number): Promise<SubjectRow[]>;
|
|
105
|
+
/** Release resources owned by this store. */
|
|
106
|
+
close(): Promise<void>;
|
|
107
|
+
}
|
|
108
|
+
/** Insert-only storage encountered an existing complete tuple. @public */
|
|
109
|
+
export declare class DuplicateRowError extends Error {
|
|
110
|
+
/** Identify an insert conflict without modifying the retained row. @public */
|
|
111
|
+
constructor(message?: string);
|
|
112
|
+
}
|
|
113
|
+
/** An update targeted a generation that has never been inserted. @public */
|
|
114
|
+
export declare class MissingRowError extends Error {
|
|
115
|
+
/** Identify an absent update target; updates never implicitly insert. @public */
|
|
116
|
+
constructor(message?: string);
|
|
117
|
+
}
|
|
118
|
+
/** A patch attempted to modify an immutable address or managed CAS version. @public */
|
|
119
|
+
export declare class InvalidStorePatchError extends Error {
|
|
120
|
+
/** Identify a structurally forbidden patch before any columns are changed. @public */
|
|
121
|
+
constructor(message?: string);
|
|
122
|
+
}
|
|
123
|
+
/** Stored fingerprints cannot be compared with this runtime's algorithm. @public */
|
|
124
|
+
export declare class FingerprintAlgorithmMismatchError extends Error {
|
|
125
|
+
/** Name both identifiers so migrations are explicit rather than silent misses. @public */
|
|
126
|
+
constructor(storedAlgorithm: string, runtimeAlgorithm: string);
|
|
127
|
+
}
|
|
128
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/store/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/** Insert-only storage encountered an existing complete tuple. @public */
|
|
2
|
+
export class DuplicateRowError extends Error {
|
|
3
|
+
/** Identify an insert conflict without modifying the retained row. @public */
|
|
4
|
+
constructor(message = 'A row already exists at this storage address') {
|
|
5
|
+
super(message);
|
|
6
|
+
this.name = 'DuplicateRowError';
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
/** An update targeted a generation that has never been inserted. @public */
|
|
10
|
+
export class MissingRowError extends Error {
|
|
11
|
+
/** Identify an absent update target; updates never implicitly insert. @public */
|
|
12
|
+
constructor(message = 'No row exists at this storage address') {
|
|
13
|
+
super(message);
|
|
14
|
+
this.name = 'MissingRowError';
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
/** A patch attempted to modify an immutable address or managed CAS version. @public */
|
|
18
|
+
export class InvalidStorePatchError extends Error {
|
|
19
|
+
/** Identify a structurally forbidden patch before any columns are changed. @public */
|
|
20
|
+
constructor(message = 'A storage patch cannot modify its key or managed version') {
|
|
21
|
+
super(message);
|
|
22
|
+
this.name = 'InvalidStorePatchError';
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
/** Stored fingerprints cannot be compared with this runtime's algorithm. @public */
|
|
26
|
+
export class FingerprintAlgorithmMismatchError extends Error {
|
|
27
|
+
/** Name both identifiers so migrations are explicit rather than silent misses. @public */
|
|
28
|
+
constructor(storedAlgorithm, runtimeAlgorithm) {
|
|
29
|
+
super(`Stored fingerprint algorithm ${storedAlgorithm} differs from runtime algorithm ${runtimeAlgorithm}`);
|
|
30
|
+
this.name = 'FingerprintAlgorithmMismatchError';
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/store/index.ts"],"names":[],"mappings":"AAyHA,0EAA0E;AAC1E,MAAM,OAAO,iBAAkB,SAAQ,KAAK;IAC1C,8EAA8E;IAC9E,YAAY,OAAO,GAAG,8CAA8C;QAClE,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,mBAAmB,CAAC;IAClC,CAAC;CACF;AAED,4EAA4E;AAC5E,MAAM,OAAO,eAAgB,SAAQ,KAAK;IACxC,iFAAiF;IACjF,YAAY,OAAO,GAAG,uCAAuC;QAC3D,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAC;IAChC,CAAC;CACF;AAED,uFAAuF;AACvF,MAAM,OAAO,sBAAuB,SAAQ,KAAK;IAC/C,sFAAsF;IACtF,YAAY,OAAO,GAAG,0DAA0D;QAC9E,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,wBAAwB,CAAC;IACvC,CAAC;CACF;AAED,oFAAoF;AACpF,MAAM,OAAO,iCAAkC,SAAQ,KAAK;IAC1D,0FAA0F;IAC1F,YAAY,eAAuB,EAAE,gBAAwB;QAC3D,KAAK,CAAC,gCAAgC,eAAe,mCAAmC,gBAAgB,EAAE,CAAC,CAAC;QAC5G,IAAI,CAAC,IAAI,GAAG,mCAAmC,CAAC;IAClD,CAAC;CACF"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { Store } from '../index.js';
|
|
2
|
+
import type { ISnapshotCapability } from '@microdelta/machine';
|
|
3
|
+
/** Options for the isolated, non-durable test backend. @public */
|
|
4
|
+
export interface MemoryStoreOptions {
|
|
5
|
+
/** Metadata compatibility identifier; the initial store format uses sha256. */
|
|
6
|
+
fingerprintAlgorithm?: string;
|
|
7
|
+
/** Actual value-read boundary, used by the conformance harness. @internal */
|
|
8
|
+
_onValueRead?: () => void;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Create a memory Store with linearizable CAS in a single JavaScript isolate.
|
|
12
|
+
* Each mutation snapshots its arguments before checking and changing the maps;
|
|
13
|
+
* the qualifying check and write have no await or caller callback between them.
|
|
14
|
+
* Values and fingerprints have separate indexes, so verification never touches
|
|
15
|
+
* payloads. The injected snapshot capability owns its supported value domain
|
|
16
|
+
* and failure behavior. This is a test backend, not durable or shared across
|
|
17
|
+
* processes.
|
|
18
|
+
*
|
|
19
|
+
* Only row storage is implemented here. Publication across multiple rows,
|
|
20
|
+
* generation allocation, lease ownership, and reclamation belong to higher layers.
|
|
21
|
+
* @public
|
|
22
|
+
*/
|
|
23
|
+
export declare function createMemoryStore(capability: ISnapshotCapability, options?: MemoryStoreOptions): Store;
|
|
24
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/store/memory/index.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAIV,KAAK,EAGN,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAG/D,kEAAkE;AAClE,MAAM,WAAW,kBAAkB;IACjC,+EAA+E;IAC/E,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,6EAA6E;IAC7E,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;CAC3B;AA+BD;;;;;;;;;;;;GAYG;AACH,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,mBAAmB,EAAE,OAAO,GAAE,kBAAuB,GAAG,KAAK,CA2H1G"}
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import { DuplicateRowError, FingerprintAlgorithmMismatchError, InvalidStorePatchError, MissingRowError, } from '../index.js';
|
|
2
|
+
/** Encode a tuple, preserving separators, Unicode and empty strings in its parts. */
|
|
3
|
+
function address(key, generation, fieldPath) {
|
|
4
|
+
// JSON numbers would collapse NaN and both infinities to null. Storage treats
|
|
5
|
+
// numeric address parts as opaque; deciding valid revisions is a caller rule.
|
|
6
|
+
return JSON.stringify([
|
|
7
|
+
key.step, String(key.revision), key.subjectHash,
|
|
8
|
+
generation === undefined ? null : String(generation), fieldPath ?? null,
|
|
9
|
+
]);
|
|
10
|
+
}
|
|
11
|
+
/** Delegate detached-copy semantics without taking ownership of the codec. */
|
|
12
|
+
function copy(capability, value) {
|
|
13
|
+
return capability.snapshot(value);
|
|
14
|
+
}
|
|
15
|
+
/** CAS tokens must advance exactly, including at JavaScript's integer boundary. */
|
|
16
|
+
function validateVersion(version) {
|
|
17
|
+
if (!Number.isSafeInteger(version) || version < 0) {
|
|
18
|
+
throw new RangeError('A subject version must be a nonnegative safe integer');
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
/** Reject runtime attempts to overwrite an address or a managed version. */
|
|
22
|
+
function guardPatch(patch, managed) {
|
|
23
|
+
if ('key' in patch || managed in patch) {
|
|
24
|
+
throw new InvalidStorePatchError();
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Create a memory Store with linearizable CAS in a single JavaScript isolate.
|
|
29
|
+
* Each mutation snapshots its arguments before checking and changing the maps;
|
|
30
|
+
* the qualifying check and write have no await or caller callback between them.
|
|
31
|
+
* Values and fingerprints have separate indexes, so verification never touches
|
|
32
|
+
* payloads. The injected snapshot capability owns its supported value domain
|
|
33
|
+
* and failure behavior. This is a test backend, not durable or shared across
|
|
34
|
+
* processes.
|
|
35
|
+
*
|
|
36
|
+
* Only row storage is implemented here. Publication across multiple rows,
|
|
37
|
+
* generation allocation, lease ownership, and reclamation belong to higher layers.
|
|
38
|
+
* @public
|
|
39
|
+
*/
|
|
40
|
+
export function createMemoryStore(capability, options = {}) {
|
|
41
|
+
const fingerprintAlgorithm = 'sha256';
|
|
42
|
+
if (options.fingerprintAlgorithm !== undefined && options.fingerprintAlgorithm !== fingerprintAlgorithm) {
|
|
43
|
+
throw new FingerprintAlgorithmMismatchError(options.fingerprintAlgorithm, fingerprintAlgorithm);
|
|
44
|
+
}
|
|
45
|
+
const subjects = new Map();
|
|
46
|
+
const generations = new Map();
|
|
47
|
+
const fieldHeaders = new Map();
|
|
48
|
+
const fieldValues = new Map();
|
|
49
|
+
const onValueRead = options._onValueRead;
|
|
50
|
+
return {
|
|
51
|
+
async meta() {
|
|
52
|
+
return { schemaVersion: 1, fingerprintAlgorithm };
|
|
53
|
+
},
|
|
54
|
+
async getSubject(key) {
|
|
55
|
+
return copy(capability, subjects.get(address(key)));
|
|
56
|
+
},
|
|
57
|
+
async putSubject(row) {
|
|
58
|
+
const snapshot = copy(capability, row);
|
|
59
|
+
validateVersion(snapshot.version);
|
|
60
|
+
const id = address(snapshot.key);
|
|
61
|
+
if (subjects.has(id)) {
|
|
62
|
+
throw new DuplicateRowError();
|
|
63
|
+
}
|
|
64
|
+
subjects.set(id, snapshot);
|
|
65
|
+
},
|
|
66
|
+
async casSubject(key, expectedVersion, patch) {
|
|
67
|
+
const id = address(key);
|
|
68
|
+
guardPatch(patch, 'version');
|
|
69
|
+
const snapshot = copy(capability, patch);
|
|
70
|
+
// Snapshotting can invoke getters. Read the row afterwards, keeping the
|
|
71
|
+
// compare and set indivisible even under reentrant caller-owned accessors.
|
|
72
|
+
const existing = subjects.get(id);
|
|
73
|
+
if (existing === undefined || existing.version !== expectedVersion) {
|
|
74
|
+
return false;
|
|
75
|
+
}
|
|
76
|
+
if (existing.version === Number.MAX_SAFE_INTEGER) {
|
|
77
|
+
throw new RangeError('Subject version exhausted; CAS cannot safely advance');
|
|
78
|
+
}
|
|
79
|
+
subjects.set(id, { ...existing, ...snapshot, version: existing.version + 1 });
|
|
80
|
+
return true;
|
|
81
|
+
},
|
|
82
|
+
async getGeneration(key, generation) {
|
|
83
|
+
return copy(capability, generations.get(address(key, generation)));
|
|
84
|
+
},
|
|
85
|
+
async listGenerations(key) {
|
|
86
|
+
const id = address(key);
|
|
87
|
+
return [...generations.values()]
|
|
88
|
+
.filter(row => address(row.key) === id)
|
|
89
|
+
.map(row => copy(capability, row));
|
|
90
|
+
},
|
|
91
|
+
async putGeneration(row) {
|
|
92
|
+
const snapshot = copy(capability, row);
|
|
93
|
+
const id = address(snapshot.key, snapshot.generation);
|
|
94
|
+
if (generations.has(id)) {
|
|
95
|
+
throw new DuplicateRowError();
|
|
96
|
+
}
|
|
97
|
+
generations.set(id, snapshot);
|
|
98
|
+
},
|
|
99
|
+
async updateGeneration(key, generation, patch) {
|
|
100
|
+
const id = address(key, generation);
|
|
101
|
+
guardPatch(patch, 'generation');
|
|
102
|
+
const snapshot = copy(capability, patch);
|
|
103
|
+
const existing = generations.get(id);
|
|
104
|
+
if (existing === undefined) {
|
|
105
|
+
throw new MissingRowError();
|
|
106
|
+
}
|
|
107
|
+
generations.set(id, { ...existing, ...snapshot });
|
|
108
|
+
},
|
|
109
|
+
async putFields(rows) {
|
|
110
|
+
// Validate the whole detached batch before writing either index. A clone
|
|
111
|
+
// failure or duplicate address cannot leave a partially inserted batch.
|
|
112
|
+
const snapshots = copy(capability, rows);
|
|
113
|
+
const ids = new Set();
|
|
114
|
+
for (const row of snapshots) {
|
|
115
|
+
const id = address(row.key, row.generation, row.path);
|
|
116
|
+
if (ids.has(id) || fieldHeaders.has(id)) {
|
|
117
|
+
throw new DuplicateRowError();
|
|
118
|
+
}
|
|
119
|
+
ids.add(id);
|
|
120
|
+
}
|
|
121
|
+
for (const row of snapshots) {
|
|
122
|
+
const id = address(row.key, row.generation, row.path);
|
|
123
|
+
const { value, ...header } = row;
|
|
124
|
+
fieldHeaders.set(id, header);
|
|
125
|
+
fieldValues.set(id, value);
|
|
126
|
+
}
|
|
127
|
+
},
|
|
128
|
+
async getFields(key, generation, paths) {
|
|
129
|
+
const result = [];
|
|
130
|
+
for (const fieldPath of paths) {
|
|
131
|
+
const id = address(key, generation, fieldPath);
|
|
132
|
+
const header = fieldHeaders.get(id);
|
|
133
|
+
if (header !== undefined) {
|
|
134
|
+
onValueRead?.();
|
|
135
|
+
result.push(copy(capability, { ...header, value: fieldValues.get(id) }));
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
return result;
|
|
139
|
+
},
|
|
140
|
+
async getFingerprints(key, generation, paths) {
|
|
141
|
+
const result = new Map();
|
|
142
|
+
for (const fieldPath of paths) {
|
|
143
|
+
const header = fieldHeaders.get(address(key, generation, fieldPath));
|
|
144
|
+
if (header !== undefined) {
|
|
145
|
+
result.set(fieldPath, header.fingerprint);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
return result;
|
|
149
|
+
},
|
|
150
|
+
async expiredClaims(now, limit) {
|
|
151
|
+
return [...subjects.values()]
|
|
152
|
+
.filter(row => row.claim !== null && row.claim.leaseUntil < now)
|
|
153
|
+
.sort((left, right) => (left.claim?.leaseUntil ?? 0) - (right.claim?.leaseUntil ?? 0))
|
|
154
|
+
.slice(0, Math.max(0, limit))
|
|
155
|
+
.map(row => copy(capability, row));
|
|
156
|
+
},
|
|
157
|
+
async close() {
|
|
158
|
+
// This backend owns no file handles, timers, workers, or external resources.
|
|
159
|
+
},
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/store/memory/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compatibility shapes for the scaffold row Store. Their names and string paths
|
|
3
|
+
* describe that storage port, not the target Value Semantics or identity model.
|
|
4
|
+
*/
|
|
5
|
+
/** Opaque, stable, hex-encoded content digest; equality is string equality. @public */
|
|
6
|
+
export type Fingerprint = string & {
|
|
7
|
+
readonly __fp: unique symbol;
|
|
8
|
+
};
|
|
9
|
+
/** A legacy row-storage address, not the future structured semantic path. @public */
|
|
10
|
+
export type Path = string;
|
|
11
|
+
/**
|
|
12
|
+
* Compatibility identity shape stored in scaffold rows. It does not establish
|
|
13
|
+
* target subject identity, binding correspondence, or collection semantics.
|
|
14
|
+
* @public
|
|
15
|
+
*/
|
|
16
|
+
export type Identity = {
|
|
17
|
+
kind: 'type';
|
|
18
|
+
type: string;
|
|
19
|
+
key: string;
|
|
20
|
+
} | {
|
|
21
|
+
kind: 'step';
|
|
22
|
+
name: string;
|
|
23
|
+
inputs: readonly Identity[];
|
|
24
|
+
} | {
|
|
25
|
+
kind: 'member';
|
|
26
|
+
of: Identity;
|
|
27
|
+
path: Path;
|
|
28
|
+
} | {
|
|
29
|
+
kind: 'collection';
|
|
30
|
+
step: string;
|
|
31
|
+
source: Identity;
|
|
32
|
+
};
|
|
33
|
+
/** Legacy row subject shape; future author-supplied subject identity is separate. @public */
|
|
34
|
+
export type Subject = Extract<Identity, {
|
|
35
|
+
kind: 'step';
|
|
36
|
+
}>;
|
|
37
|
+
/** Complete storage tuple. Backends must preserve boundaries between all three parts. @public */
|
|
38
|
+
export type ResultKey = {
|
|
39
|
+
step: string;
|
|
40
|
+
revision: number;
|
|
41
|
+
subjectHash: string;
|
|
42
|
+
};
|
|
43
|
+
/** Legacy persisted read rows; target observation encoding remains undecided. @public */
|
|
44
|
+
export type RecordedRead = {
|
|
45
|
+
kind: 'field';
|
|
46
|
+
arg: number;
|
|
47
|
+
path: Path;
|
|
48
|
+
fingerprint: Fingerprint;
|
|
49
|
+
} | {
|
|
50
|
+
kind: 'whole';
|
|
51
|
+
arg: number;
|
|
52
|
+
fingerprint: Fingerprint;
|
|
53
|
+
} | {
|
|
54
|
+
kind: 'memo';
|
|
55
|
+
key: ResultKey;
|
|
56
|
+
generation: number;
|
|
57
|
+
};
|
|
58
|
+
/** Retained lifecycle states interpreted by repository and claim, not by storage. @public */
|
|
59
|
+
export type GenerationState = 'claimed' | 'current' | 'superseded' | 'abandoned';
|
|
60
|
+
/** The first observed difference in a persisted read or a nested verification. @public */
|
|
61
|
+
export type Divergence = {
|
|
62
|
+
read: RecordedRead;
|
|
63
|
+
was: Fingerprint;
|
|
64
|
+
now: Fingerprint | 'missing';
|
|
65
|
+
} | {
|
|
66
|
+
read: Extract<RecordedRead, {
|
|
67
|
+
kind: 'memo';
|
|
68
|
+
}>;
|
|
69
|
+
nested: Divergence;
|
|
70
|
+
};
|
|
71
|
+
/** Observable call outcomes; an unmemoized named execution has no storage key. @public */
|
|
72
|
+
export type Outcome = {
|
|
73
|
+
kind: 'served';
|
|
74
|
+
key: ResultKey;
|
|
75
|
+
generation: number;
|
|
76
|
+
} | {
|
|
77
|
+
kind: 'executed';
|
|
78
|
+
key: ResultKey;
|
|
79
|
+
generation: number;
|
|
80
|
+
} | {
|
|
81
|
+
kind: 'checked';
|
|
82
|
+
key: ResultKey;
|
|
83
|
+
wouldExecute: boolean;
|
|
84
|
+
divergence?: Divergence;
|
|
85
|
+
} | {
|
|
86
|
+
kind: 'refused';
|
|
87
|
+
key: ResultKey;
|
|
88
|
+
reason: unknown;
|
|
89
|
+
} | {
|
|
90
|
+
kind: 'failed';
|
|
91
|
+
key: ResultKey;
|
|
92
|
+
error: unknown;
|
|
93
|
+
} | {
|
|
94
|
+
kind: 'abandoned';
|
|
95
|
+
key: ResultKey;
|
|
96
|
+
reason: 'error' | 'lease-expired' | 'refused';
|
|
97
|
+
} | {
|
|
98
|
+
kind: 'ran';
|
|
99
|
+
};
|
|
100
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { Store } from '../../../src/store/index.js';
|
|
2
|
+
/**
|
|
3
|
+
* A backend's test-only counter at its actual value-read/deserialization boundary.
|
|
4
|
+
* The suite resets it after insertion and verifies a positive control with getFields.
|
|
5
|
+
* @public
|
|
6
|
+
*/
|
|
7
|
+
export interface ValueReadProbe {
|
|
8
|
+
reset(): void;
|
|
9
|
+
count(): number;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Opens a fresh store for each test. The optional algorithm models persisted metadata
|
|
13
|
+
* at open time; factories must reject a mismatch with their runtime algorithm.
|
|
14
|
+
* Instrumentation is optional for third-party backends, but both shipped backends
|
|
15
|
+
* must provide it to qualify SA-3 without relying on wall-clock timing.
|
|
16
|
+
* @public
|
|
17
|
+
*/
|
|
18
|
+
export interface StoreConformanceOptions {
|
|
19
|
+
create(options?: {
|
|
20
|
+
fingerprintAlgorithm?: string;
|
|
21
|
+
}): Store | Promise<Store>;
|
|
22
|
+
fingerprintAlgorithm: string;
|
|
23
|
+
probeValueReads?(store: Store): ValueReadProbe;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Register reusable backend qualification tests for SA-1 through SA-7.
|
|
27
|
+
* Register this from a Jest test module; the suite imports no concrete backend.
|
|
28
|
+
* Mutation tests enforce rev 9's retained-value isolation at the storage seam.
|
|
29
|
+
* This suite does not assert atomicity across subject, generation, and field rows:
|
|
30
|
+
* the supplied Store contract does not provide that operation.
|
|
31
|
+
* @public
|
|
32
|
+
*/
|
|
33
|
+
export declare function storeConformance(name: string, options: StoreConformanceOptions): void;
|
|
34
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../test/conformance/store/index.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAA2B,KAAK,EAAc,MAAM,6BAA6B,CAAC;AAE9F;;;;GAIG;AACH,MAAM,WAAW,cAAc;IAC7B,KAAK,IAAI,IAAI,CAAC;IACd,KAAK,IAAI,MAAM,CAAC;CACjB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,uBAAuB;IACtC,MAAM,CAAC,OAAO,CAAC,EAAE;QAAE,oBAAoB,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC;IAC5E,oBAAoB,EAAE,MAAM,CAAC;IAC7B,eAAe,CAAC,CAAC,KAAK,EAAE,KAAK,GAAG,cAAc,CAAC;CAChD;AAyDD;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,uBAAuB,GAAG,IAAI,CAsUrF"}
|