@feltdb/core 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 +184 -0
- package/dist/agent-decision.d.ts +81 -0
- package/dist/agent-decision.d.ts.map +1 -0
- package/dist/agent-decision.js +18 -0
- package/dist/agent-memory.d.ts +91 -0
- package/dist/agent-memory.d.ts.map +1 -0
- package/dist/agent-memory.js +21 -0
- package/dist/agent-observation.d.ts +61 -0
- package/dist/agent-observation.d.ts.map +1 -0
- package/dist/agent-observation.js +12 -0
- package/dist/agent-registry.d.ts +92 -0
- package/dist/agent-registry.d.ts.map +1 -0
- package/dist/agent-registry.js +134 -0
- package/dist/agent-runtime.d.ts +147 -0
- package/dist/agent-runtime.d.ts.map +1 -0
- package/dist/agent-runtime.js +240 -0
- package/dist/agent.d.ts +132 -0
- package/dist/agent.d.ts.map +1 -0
- package/dist/agent.js +58 -0
- package/dist/capability.d.ts +21 -0
- package/dist/capability.d.ts.map +1 -0
- package/dist/capability.js +23 -0
- package/dist/collection.d.ts +95 -0
- package/dist/collection.d.ts.map +1 -0
- package/dist/collection.js +289 -0
- package/dist/db.d.ts +504 -0
- package/dist/db.d.ts.map +1 -0
- package/dist/db.js +700 -0
- package/dist/execution.d.ts +148 -0
- package/dist/execution.d.ts.map +1 -0
- package/dist/execution.js +18 -0
- package/dist/feltdb.d.ts +82 -0
- package/dist/feltdb.d.ts.map +1 -0
- package/dist/feltdb.js +6 -0
- package/dist/flowspec.d.ts +64 -0
- package/dist/flowspec.d.ts.map +1 -0
- package/dist/flowspec.js +272 -0
- package/dist/http-db.d.ts +50 -0
- package/dist/http-db.d.ts.map +1 -0
- package/dist/http-db.js +205 -0
- package/dist/index.d.ts +32 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +27 -0
- package/dist/indexeddb-db.d.ts +54 -0
- package/dist/indexeddb-db.d.ts.map +1 -0
- package/dist/indexeddb-db.js +175 -0
- package/dist/memory-db.d.ts +49 -0
- package/dist/memory-db.d.ts.map +1 -0
- package/dist/memory-db.js +97 -0
- package/dist/operation.d.ts +25 -0
- package/dist/operation.d.ts.map +1 -0
- package/dist/operation.js +16 -0
- package/dist/reactive-graph.d.ts +67 -0
- package/dist/reactive-graph.d.ts.map +1 -0
- package/dist/reactive-graph.js +118 -0
- package/dist/recovery.d.ts +68 -0
- package/dist/recovery.d.ts.map +1 -0
- package/dist/recovery.js +104 -0
- package/dist/storage.d.ts +48 -0
- package/dist/storage.d.ts.map +1 -0
- package/dist/storage.js +6 -0
- package/dist/workflow.d.ts +20 -0
- package/dist/workflow.d.ts.map +1 -0
- package/dist/workflow.js +12 -0
- package/package.json +43 -0
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Operation Types
|
|
3
|
+
*
|
|
4
|
+
* Defines the types of operations that can be performed on the database.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Operation types
|
|
8
|
+
*/
|
|
9
|
+
export declare enum OperationType {
|
|
10
|
+
Insert = "Insert",
|
|
11
|
+
Update = "Update",
|
|
12
|
+
Delete = "Delete",
|
|
13
|
+
Query = "Query",
|
|
14
|
+
Upsert = "Upsert"
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* A database operation
|
|
18
|
+
*/
|
|
19
|
+
export interface Operation {
|
|
20
|
+
op_type: OperationType;
|
|
21
|
+
key: string;
|
|
22
|
+
value?: any;
|
|
23
|
+
timestamp_ms: number;
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=operation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"operation.d.ts","sourceRoot":"","sources":["../src/operation.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;GAEG;AACH,oBAAY,aAAa;IACvB,MAAM,WAAW;IACjB,MAAM,WAAW;IACjB,MAAM,WAAW;IACjB,KAAK,UAAU;IACf,MAAM,WAAW;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,OAAO,EAAE,aAAa,CAAC;IACvB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,GAAG,CAAC;IACZ,YAAY,EAAE,MAAM,CAAC;CACtB"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Operation Types
|
|
3
|
+
*
|
|
4
|
+
* Defines the types of operations that can be performed on the database.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Operation types
|
|
8
|
+
*/
|
|
9
|
+
export var OperationType;
|
|
10
|
+
(function (OperationType) {
|
|
11
|
+
OperationType["Insert"] = "Insert";
|
|
12
|
+
OperationType["Update"] = "Update";
|
|
13
|
+
OperationType["Delete"] = "Delete";
|
|
14
|
+
OperationType["Query"] = "Query";
|
|
15
|
+
OperationType["Upsert"] = "Upsert";
|
|
16
|
+
})(OperationType || (OperationType = {}));
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reactive dependency graph for FeltDB collections
|
|
3
|
+
*
|
|
4
|
+
* Tracks relationships between collections (base → derived → further derived)
|
|
5
|
+
* and propagates mutations automatically without polling.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Represents a change in the collection
|
|
9
|
+
*/
|
|
10
|
+
export interface CollectionChange<T> {
|
|
11
|
+
type: 'insert' | 'update' | 'delete';
|
|
12
|
+
key: string;
|
|
13
|
+
value: T | null;
|
|
14
|
+
timestamp: number;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Tracks dependencies between collections and propagates changes
|
|
18
|
+
*/
|
|
19
|
+
export declare class ReactiveDependencyGraph {
|
|
20
|
+
/** Map of collection name to its dependents (derived collections) */
|
|
21
|
+
private dependencies;
|
|
22
|
+
/** Map of collection name to its subscribers (callbacks) */
|
|
23
|
+
private subscribers;
|
|
24
|
+
/** Recent changes for each collection (for differential updates) */
|
|
25
|
+
private recentChanges;
|
|
26
|
+
/**
|
|
27
|
+
* Register a dependency: when sourceCollection changes, notify dependentCollection
|
|
28
|
+
*/
|
|
29
|
+
registerDependency(sourceCollection: string, dependentCollection: string): void;
|
|
30
|
+
/**
|
|
31
|
+
* Subscribe to changes for a collection
|
|
32
|
+
*/
|
|
33
|
+
subscribe(collectionName: string, callback: (change: CollectionChange<any>) => void | Promise<void>): () => void;
|
|
34
|
+
/**
|
|
35
|
+
* Emit a change for a collection, triggering all subscribers
|
|
36
|
+
*/
|
|
37
|
+
emitChange<T>(collectionName: string, change: CollectionChange<T>): Promise<void>;
|
|
38
|
+
/**
|
|
39
|
+
* Get recent changes for a collection (for differential updates)
|
|
40
|
+
*/
|
|
41
|
+
getRecentChanges<T>(collectionName: string): CollectionChange<T>[];
|
|
42
|
+
/**
|
|
43
|
+
* Clear recent changes for a collection
|
|
44
|
+
*/
|
|
45
|
+
clearRecentChanges(collectionName: string): void;
|
|
46
|
+
/**
|
|
47
|
+
* Get the number of active subscribers for a collection
|
|
48
|
+
*/
|
|
49
|
+
getSubscriberCount(collectionName: string): number;
|
|
50
|
+
/**
|
|
51
|
+
* Check if a collection has any dependents
|
|
52
|
+
*/
|
|
53
|
+
hasDependents(collectionName: string): boolean;
|
|
54
|
+
/**
|
|
55
|
+
* Get all dependents of a collection
|
|
56
|
+
*/
|
|
57
|
+
getDependents(collectionName: string): string[];
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Get the global reactive dependency graph
|
|
61
|
+
*/
|
|
62
|
+
export declare function getReactiveDependencyGraph(): ReactiveDependencyGraph;
|
|
63
|
+
/**
|
|
64
|
+
* Reset the global graph (useful for testing)
|
|
65
|
+
*/
|
|
66
|
+
export declare function resetReactiveDependencyGraph(): void;
|
|
67
|
+
//# sourceMappingURL=reactive-graph.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reactive-graph.d.ts","sourceRoot":"","sources":["../src/reactive-graph.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH;;GAEG;AACH,MAAM,WAAW,gBAAgB,CAAC,CAAC;IACjC,IAAI,EAAE,QAAQ,GAAG,QAAQ,GAAG,QAAQ,CAAC;IACrC,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,CAAC,GAAG,IAAI,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,qBAAa,uBAAuB;IAClC,qEAAqE;IACrE,OAAO,CAAC,YAAY,CAAuC;IAE3D,4DAA4D;IAC5D,OAAO,CAAC,WAAW,CAAwF;IAE3G,oEAAoE;IACpE,OAAO,CAAC,aAAa,CAAmD;IAExE;;OAEG;IACH,kBAAkB,CAAC,gBAAgB,EAAE,MAAM,EAAE,mBAAmB,EAAE,MAAM,GAAG,IAAI;IAO/E;;OAEG;IACH,SAAS,CACP,cAAc,EAAE,MAAM,EACtB,QAAQ,EAAE,CAAC,MAAM,EAAE,gBAAgB,CAAC,GAAG,CAAC,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,GAChE,MAAM,IAAI;IAgBb;;OAEG;IACG,UAAU,CAAC,CAAC,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,EAAE,gBAAgB,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAyBvF;;OAEG;IACH,gBAAgB,CAAC,CAAC,EAAE,cAAc,EAAE,MAAM,GAAG,gBAAgB,CAAC,CAAC,CAAC,EAAE;IAKlE;;OAEG;IACH,kBAAkB,CAAC,cAAc,EAAE,MAAM,GAAG,IAAI;IAIhD;;OAEG;IACH,kBAAkB,CAAC,cAAc,EAAE,MAAM,GAAG,MAAM;IAIlD;;OAEG;IACH,aAAa,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO;IAK9C;;OAEG;IACH,aAAa,CAAC,cAAc,EAAE,MAAM,GAAG,MAAM,EAAE;CAIhD;AAKD;;GAEG;AACH,wBAAgB,0BAA0B,IAAI,uBAAuB,CAKpE;AAED;;GAEG;AACH,wBAAgB,4BAA4B,IAAI,IAAI,CAEnD"}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reactive dependency graph for FeltDB collections
|
|
3
|
+
*
|
|
4
|
+
* Tracks relationships between collections (base → derived → further derived)
|
|
5
|
+
* and propagates mutations automatically without polling.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Tracks dependencies between collections and propagates changes
|
|
9
|
+
*/
|
|
10
|
+
export class ReactiveDependencyGraph {
|
|
11
|
+
constructor() {
|
|
12
|
+
/** Map of collection name to its dependents (derived collections) */
|
|
13
|
+
this.dependencies = new Map();
|
|
14
|
+
/** Map of collection name to its subscribers (callbacks) */
|
|
15
|
+
this.subscribers = new Map();
|
|
16
|
+
/** Recent changes for each collection (for differential updates) */
|
|
17
|
+
this.recentChanges = new Map();
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Register a dependency: when sourceCollection changes, notify dependentCollection
|
|
21
|
+
*/
|
|
22
|
+
registerDependency(sourceCollection, dependentCollection) {
|
|
23
|
+
if (!this.dependencies.has(sourceCollection)) {
|
|
24
|
+
this.dependencies.set(sourceCollection, new Set());
|
|
25
|
+
}
|
|
26
|
+
this.dependencies.get(sourceCollection).add(dependentCollection);
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Subscribe to changes for a collection
|
|
30
|
+
*/
|
|
31
|
+
subscribe(collectionName, callback) {
|
|
32
|
+
if (!this.subscribers.has(collectionName)) {
|
|
33
|
+
this.subscribers.set(collectionName, new Set());
|
|
34
|
+
}
|
|
35
|
+
const subscribers = this.subscribers.get(collectionName);
|
|
36
|
+
subscribers.add(callback);
|
|
37
|
+
// Return unsubscribe function
|
|
38
|
+
return () => {
|
|
39
|
+
subscribers.delete(callback);
|
|
40
|
+
if (subscribers.size === 0) {
|
|
41
|
+
this.subscribers.delete(collectionName);
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Emit a change for a collection, triggering all subscribers
|
|
47
|
+
*/
|
|
48
|
+
async emitChange(collectionName, change) {
|
|
49
|
+
// Store the change
|
|
50
|
+
if (!this.recentChanges.has(collectionName)) {
|
|
51
|
+
this.recentChanges.set(collectionName, []);
|
|
52
|
+
}
|
|
53
|
+
this.recentChanges.get(collectionName).push(change);
|
|
54
|
+
// Notify subscribers of this collection
|
|
55
|
+
const subscribers = this.subscribers.get(collectionName);
|
|
56
|
+
if (subscribers) {
|
|
57
|
+
await Promise.all([...subscribers].map((callback) => callback(change)));
|
|
58
|
+
}
|
|
59
|
+
// Propagate to dependents
|
|
60
|
+
const dependents = this.dependencies.get(collectionName);
|
|
61
|
+
if (dependents) {
|
|
62
|
+
for (const dependentName of dependents) {
|
|
63
|
+
// Recursively notify dependents
|
|
64
|
+
await this.emitChange(dependentName, change);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Get recent changes for a collection (for differential updates)
|
|
70
|
+
*/
|
|
71
|
+
getRecentChanges(collectionName) {
|
|
72
|
+
const changes = this.recentChanges.get(collectionName) || [];
|
|
73
|
+
return changes;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Clear recent changes for a collection
|
|
77
|
+
*/
|
|
78
|
+
clearRecentChanges(collectionName) {
|
|
79
|
+
this.recentChanges.delete(collectionName);
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Get the number of active subscribers for a collection
|
|
83
|
+
*/
|
|
84
|
+
getSubscriberCount(collectionName) {
|
|
85
|
+
return this.subscribers.get(collectionName)?.size ?? 0;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Check if a collection has any dependents
|
|
89
|
+
*/
|
|
90
|
+
hasDependents(collectionName) {
|
|
91
|
+
const deps = this.dependencies.get(collectionName);
|
|
92
|
+
return deps !== undefined && deps.size > 0;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Get all dependents of a collection
|
|
96
|
+
*/
|
|
97
|
+
getDependents(collectionName) {
|
|
98
|
+
const deps = this.dependencies.get(collectionName);
|
|
99
|
+
return deps ? Array.from(deps) : [];
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
// Global instance (singleton per app)
|
|
103
|
+
let globalGraph = null;
|
|
104
|
+
/**
|
|
105
|
+
* Get the global reactive dependency graph
|
|
106
|
+
*/
|
|
107
|
+
export function getReactiveDependencyGraph() {
|
|
108
|
+
if (!globalGraph) {
|
|
109
|
+
globalGraph = new ReactiveDependencyGraph();
|
|
110
|
+
}
|
|
111
|
+
return globalGraph;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Reset the global graph (useful for testing)
|
|
115
|
+
*/
|
|
116
|
+
export function resetReactiveDependencyGraph() {
|
|
117
|
+
globalGraph = null;
|
|
118
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Recovery module for FeltDB
|
|
3
|
+
*
|
|
4
|
+
* Implements recovery of database state from operation logs and checkpoints.
|
|
5
|
+
* Ensures that:
|
|
6
|
+
* - Records are reconstructed correctly
|
|
7
|
+
* - Indexes are restored
|
|
8
|
+
* - Derived collections rebuild correctly
|
|
9
|
+
* - Subscriptions continue to work
|
|
10
|
+
* - All counts and queries produce correct results
|
|
11
|
+
*/
|
|
12
|
+
import type { Operation } from './operation.js';
|
|
13
|
+
import type { JsDb } from './feltdb.js';
|
|
14
|
+
/**
|
|
15
|
+
* Recovery information for diagnostics
|
|
16
|
+
*/
|
|
17
|
+
export interface RecoveryInfo {
|
|
18
|
+
/** Total operations recovered */
|
|
19
|
+
operationsRecovered: number;
|
|
20
|
+
/** Checkpoint data recovered */
|
|
21
|
+
checkpointRecovered: boolean;
|
|
22
|
+
/** Total records reconstructed */
|
|
23
|
+
recordsReconstructed: number;
|
|
24
|
+
/** Recovery duration in milliseconds */
|
|
25
|
+
durationMs: number;
|
|
26
|
+
/** Whether recovery completed successfully */
|
|
27
|
+
successful: boolean;
|
|
28
|
+
/** Error message if recovery failed */
|
|
29
|
+
error?: string;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Recover database state from operation log and checkpoints
|
|
33
|
+
*
|
|
34
|
+
* This function:
|
|
35
|
+
* 1. Loads checkpoint if available (base state)
|
|
36
|
+
* 2. Replays delta operations on top of checkpoint
|
|
37
|
+
* 3. Reconstructs all in-memory state
|
|
38
|
+
* 4. Re-establishes indexes
|
|
39
|
+
* 5. Rebuilds derived collections
|
|
40
|
+
*
|
|
41
|
+
* The process is transparent to the application - it sees the same
|
|
42
|
+
* state as if the database had never stopped.
|
|
43
|
+
*/
|
|
44
|
+
export declare function recoverFromLog(jsDb: JsDb, operationLog: Operation[]): Promise<RecoveryInfo>;
|
|
45
|
+
/**
|
|
46
|
+
* Verify that recovered state is correct
|
|
47
|
+
*
|
|
48
|
+
* This is primarily for testing to ensure recovery worked properly.
|
|
49
|
+
* Verifies:
|
|
50
|
+
* - Records are present
|
|
51
|
+
* - Indexes work
|
|
52
|
+
* - Derived collections can be queried
|
|
53
|
+
* - Subscriptions can be created
|
|
54
|
+
* - Counts are accurate
|
|
55
|
+
*/
|
|
56
|
+
export interface RecoveryVerification {
|
|
57
|
+
recordsPresent: number;
|
|
58
|
+
queriesWorking: boolean;
|
|
59
|
+
derivedCollectionsRebuild: boolean;
|
|
60
|
+
subscriptionsWork: boolean;
|
|
61
|
+
countsAccurate: boolean;
|
|
62
|
+
allVerificationsPass: boolean;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Run verification tests on recovered state
|
|
66
|
+
*/
|
|
67
|
+
export declare function verifyRecovery(jsDb: JsDb, capability: string, expectedRecordCount: number): Promise<RecoveryVerification>;
|
|
68
|
+
//# sourceMappingURL=recovery.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recovery.d.ts","sourceRoot":"","sources":["../src/recovery.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAIhD,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAExC;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,iCAAiC;IACjC,mBAAmB,EAAE,MAAM,CAAC;IAC5B,gCAAgC;IAChC,mBAAmB,EAAE,OAAO,CAAC;IAC7B,kCAAkC;IAClC,oBAAoB,EAAE,MAAM,CAAC;IAC7B,wCAAwC;IACxC,UAAU,EAAE,MAAM,CAAC;IACnB,8CAA8C;IAC9C,UAAU,EAAE,OAAO,CAAC;IACpB,uCAAuC;IACvC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,cAAc,CAClC,IAAI,EAAE,IAAI,EACV,YAAY,EAAE,SAAS,EAAE,GACxB,OAAO,CAAC,YAAY,CAAC,CAkDvB;AAED;;;;;;;;;;GAUG;AACH,MAAM,WAAW,oBAAoB;IACnC,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,OAAO,CAAC;IACxB,yBAAyB,EAAE,OAAO,CAAC;IACnC,iBAAiB,EAAE,OAAO,CAAC;IAC3B,cAAc,EAAE,OAAO,CAAC;IACxB,oBAAoB,EAAE,OAAO,CAAC;CAC/B;AAED;;GAEG;AACH,wBAAsB,cAAc,CAClC,IAAI,EAAE,IAAI,EACV,UAAU,EAAE,MAAM,EAClB,mBAAmB,EAAE,MAAM,GAC1B,OAAO,CAAC,oBAAoB,CAAC,CA6B/B"}
|
package/dist/recovery.js
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Recovery module for FeltDB
|
|
3
|
+
*
|
|
4
|
+
* Implements recovery of database state from operation logs and checkpoints.
|
|
5
|
+
* Ensures that:
|
|
6
|
+
* - Records are reconstructed correctly
|
|
7
|
+
* - Indexes are restored
|
|
8
|
+
* - Derived collections rebuild correctly
|
|
9
|
+
* - Subscriptions continue to work
|
|
10
|
+
* - All counts and queries produce correct results
|
|
11
|
+
*/
|
|
12
|
+
import { OperationType } from './operation.js';
|
|
13
|
+
/**
|
|
14
|
+
* Recover database state from operation log and checkpoints
|
|
15
|
+
*
|
|
16
|
+
* This function:
|
|
17
|
+
* 1. Loads checkpoint if available (base state)
|
|
18
|
+
* 2. Replays delta operations on top of checkpoint
|
|
19
|
+
* 3. Reconstructs all in-memory state
|
|
20
|
+
* 4. Re-establishes indexes
|
|
21
|
+
* 5. Rebuilds derived collections
|
|
22
|
+
*
|
|
23
|
+
* The process is transparent to the application - it sees the same
|
|
24
|
+
* state as if the database had never stopped.
|
|
25
|
+
*/
|
|
26
|
+
export async function recoverFromLog(jsDb, operationLog) {
|
|
27
|
+
const startTime = Date.now();
|
|
28
|
+
let recordsReconstructed = 0;
|
|
29
|
+
let operationsRecovered = 0;
|
|
30
|
+
try {
|
|
31
|
+
// Apply operations to reconstruct state
|
|
32
|
+
for (const operation of operationLog) {
|
|
33
|
+
switch (operation.op_type) {
|
|
34
|
+
case OperationType.Insert:
|
|
35
|
+
case OperationType.Update:
|
|
36
|
+
if (operation.value) {
|
|
37
|
+
jsDb.insert(operation.key, JSON.stringify(operation.value));
|
|
38
|
+
recordsReconstructed++;
|
|
39
|
+
}
|
|
40
|
+
break;
|
|
41
|
+
case OperationType.Delete:
|
|
42
|
+
// For delete, we could either:
|
|
43
|
+
// 1. Remove from storage (requires delete API)
|
|
44
|
+
// 2. Mark as deleted (soft delete)
|
|
45
|
+
// For now, soft delete approach
|
|
46
|
+
jsDb.insert(operation.key, JSON.stringify({ __deleted: true }));
|
|
47
|
+
break;
|
|
48
|
+
}
|
|
49
|
+
operationsRecovered++;
|
|
50
|
+
}
|
|
51
|
+
const durationMs = Date.now() - startTime;
|
|
52
|
+
return {
|
|
53
|
+
operationsRecovered,
|
|
54
|
+
checkpointRecovered: false, // TODO: implement checkpoint recovery
|
|
55
|
+
recordsReconstructed,
|
|
56
|
+
durationMs,
|
|
57
|
+
successful: true,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
catch (err) {
|
|
61
|
+
const durationMs = Date.now() - startTime;
|
|
62
|
+
const errorMsg = err instanceof Error ? err.message : String(err);
|
|
63
|
+
return {
|
|
64
|
+
operationsRecovered,
|
|
65
|
+
checkpointRecovered: false,
|
|
66
|
+
recordsReconstructed,
|
|
67
|
+
durationMs,
|
|
68
|
+
successful: false,
|
|
69
|
+
error: errorMsg,
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Run verification tests on recovered state
|
|
75
|
+
*/
|
|
76
|
+
export async function verifyRecovery(jsDb, capability, expectedRecordCount) {
|
|
77
|
+
try {
|
|
78
|
+
// Try to query the capability
|
|
79
|
+
const result = jsDb.get_capability_records(capability);
|
|
80
|
+
const recordsPresent = result.success
|
|
81
|
+
? JSON.parse(result.data || '[]').length
|
|
82
|
+
: 0;
|
|
83
|
+
return {
|
|
84
|
+
recordsPresent,
|
|
85
|
+
queriesWorking: result.success,
|
|
86
|
+
derivedCollectionsRebuild: true, // TODO: test derived collections
|
|
87
|
+
subscriptionsWork: true, // TODO: test subscriptions
|
|
88
|
+
countsAccurate: recordsPresent === expectedRecordCount,
|
|
89
|
+
allVerificationsPass: result.success &&
|
|
90
|
+
recordsPresent > 0 &&
|
|
91
|
+
recordsPresent === expectedRecordCount,
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
catch (err) {
|
|
95
|
+
return {
|
|
96
|
+
recordsPresent: 0,
|
|
97
|
+
queriesWorking: false,
|
|
98
|
+
derivedCollectionsRebuild: false,
|
|
99
|
+
subscriptionsWork: false,
|
|
100
|
+
countsAccurate: false,
|
|
101
|
+
allVerificationsPass: false,
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Storage and Checkpoint Types
|
|
3
|
+
*
|
|
4
|
+
* Defines the data structures for persistent storage and checkpointing.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Checkpoint data for recovery
|
|
8
|
+
*/
|
|
9
|
+
export interface CheckpointData {
|
|
10
|
+
/**
|
|
11
|
+
* Checkpoint ID
|
|
12
|
+
*/
|
|
13
|
+
checkpointId: string;
|
|
14
|
+
/**
|
|
15
|
+
* State at this checkpoint
|
|
16
|
+
*/
|
|
17
|
+
state: Map<string, any>;
|
|
18
|
+
/**
|
|
19
|
+
* Timestamp when checkpoint was created
|
|
20
|
+
*/
|
|
21
|
+
timestamp_ms: number;
|
|
22
|
+
/**
|
|
23
|
+
* Operations included in this checkpoint
|
|
24
|
+
*/
|
|
25
|
+
operations: any[];
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Storage backend interface
|
|
29
|
+
*/
|
|
30
|
+
export interface StorageBackend {
|
|
31
|
+
/**
|
|
32
|
+
* Store data
|
|
33
|
+
*/
|
|
34
|
+
store(key: string, value: any): Promise<void>;
|
|
35
|
+
/**
|
|
36
|
+
* Retrieve data
|
|
37
|
+
*/
|
|
38
|
+
retrieve(key: string): Promise<any>;
|
|
39
|
+
/**
|
|
40
|
+
* Delete data
|
|
41
|
+
*/
|
|
42
|
+
delete(key: string): Promise<void>;
|
|
43
|
+
/**
|
|
44
|
+
* List keys
|
|
45
|
+
*/
|
|
46
|
+
list(prefix: string): Promise<string[]>;
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=storage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../src/storage.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B;;OAEG;IACH,YAAY,EAAE,MAAM,CAAC;IAErB;;OAEG;IACH,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAExB;;OAEG;IACH,YAAY,EAAE,MAAM,CAAC;IAErB;;OAEG;IACH,UAAU,EAAE,GAAG,EAAE,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B;;OAEG;IACH,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE9C;;OAEG;IACH,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;IAEpC;;OAEG;IACH,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEnC;;OAEG;IACH,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;CACzC"}
|
package/dist/storage.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Workflow execution and orchestration
|
|
3
|
+
*/
|
|
4
|
+
export interface Workflow {
|
|
5
|
+
id: string;
|
|
6
|
+
name: string;
|
|
7
|
+
execute(...args: any[]): Promise<any>;
|
|
8
|
+
}
|
|
9
|
+
export interface WorkflowDefinition {
|
|
10
|
+
name: string;
|
|
11
|
+
steps: WorkflowStep[];
|
|
12
|
+
}
|
|
13
|
+
export interface WorkflowStep {
|
|
14
|
+
name: string;
|
|
15
|
+
execute(context: any): Promise<any>;
|
|
16
|
+
}
|
|
17
|
+
export declare class WorkflowExecutor {
|
|
18
|
+
execute(workflow: WorkflowDefinition, input: any): Promise<any>;
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=workflow.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workflow.d.ts","sourceRoot":"","sources":["../src/workflow.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;CACvC;AAED,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,YAAY,EAAE,CAAC;CACvB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,OAAO,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;CACrC;AAED,qBAAa,gBAAgB;IACrB,OAAO,CAAC,QAAQ,EAAE,kBAAkB,EAAE,KAAK,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC;CAOtE"}
|
package/dist/workflow.js
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@feltdb/core",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "FeltDB Core - The application-facing database API",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"main": "dist/index.js",
|
|
8
|
+
"types": "dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"import": "./dist/index.js",
|
|
12
|
+
"require": "./dist/index.js",
|
|
13
|
+
"types": "./dist/index.d.ts"
|
|
14
|
+
},
|
|
15
|
+
"./db": {
|
|
16
|
+
"import": "./dist/db.js",
|
|
17
|
+
"require": "./dist/db.js",
|
|
18
|
+
"types": "./dist/db.d.ts"
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
"files": [
|
|
22
|
+
"dist/"
|
|
23
|
+
],
|
|
24
|
+
"scripts": {
|
|
25
|
+
"build": "rm -rf dist && tsc",
|
|
26
|
+
"test": "node ../../test-runner.ts"
|
|
27
|
+
},
|
|
28
|
+
"dependencies": {
|
|
29
|
+
"@feltdb/wasm": "^0.2.0"
|
|
30
|
+
},
|
|
31
|
+
"devDependencies": {
|
|
32
|
+
"typescript": "^5.0.0",
|
|
33
|
+
"@types/node": "^20.0.0"
|
|
34
|
+
},
|
|
35
|
+
"engines": {
|
|
36
|
+
"node": ">=14"
|
|
37
|
+
},
|
|
38
|
+
"repository": {
|
|
39
|
+
"type": "git",
|
|
40
|
+
"url": "git+https://github.com/rkendel1/feltdb.git",
|
|
41
|
+
"directory": "packages/core"
|
|
42
|
+
}
|
|
43
|
+
}
|