@brightchain/db 0.20.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.
Files changed (56) hide show
  1. package/README.md +81 -0
  2. package/package.json +18 -0
  3. package/src/__tests__/helpers/mockBlockStore.d.ts +113 -0
  4. package/src/__tests__/helpers/mockBlockStore.js +380 -0
  5. package/src/__tests__/helpers/mockBlockStore.js.map +1 -0
  6. package/src/index.d.ts +31 -0
  7. package/src/index.js +78 -0
  8. package/src/index.js.map +1 -0
  9. package/src/lib/aggregation.d.ts +18 -0
  10. package/src/lib/aggregation.js +407 -0
  11. package/src/lib/aggregation.js.map +1 -0
  12. package/src/lib/cblIndex.d.ts +268 -0
  13. package/src/lib/cblIndex.js +856 -0
  14. package/src/lib/cblIndex.js.map +1 -0
  15. package/src/lib/collection.d.ts +305 -0
  16. package/src/lib/collection.js +991 -0
  17. package/src/lib/collection.js.map +1 -0
  18. package/src/lib/cursor.d.ts +8 -0
  19. package/src/lib/cursor.js +13 -0
  20. package/src/lib/cursor.js.map +1 -0
  21. package/src/lib/database.d.ts +158 -0
  22. package/src/lib/database.js +332 -0
  23. package/src/lib/database.js.map +1 -0
  24. package/src/lib/errors.d.ts +85 -0
  25. package/src/lib/errors.js +103 -0
  26. package/src/lib/errors.js.map +1 -0
  27. package/src/lib/expressMiddleware.d.ts +57 -0
  28. package/src/lib/expressMiddleware.js +488 -0
  29. package/src/lib/expressMiddleware.js.map +1 -0
  30. package/src/lib/headRegistry.d.ts +60 -0
  31. package/src/lib/headRegistry.js +216 -0
  32. package/src/lib/headRegistry.js.map +1 -0
  33. package/src/lib/indexing.d.ts +7 -0
  34. package/src/lib/indexing.js +14 -0
  35. package/src/lib/indexing.js.map +1 -0
  36. package/src/lib/model.d.ts +162 -0
  37. package/src/lib/model.js +260 -0
  38. package/src/lib/model.js.map +1 -0
  39. package/src/lib/pooledStoreAdapter.d.ts +44 -0
  40. package/src/lib/pooledStoreAdapter.js +109 -0
  41. package/src/lib/pooledStoreAdapter.js.map +1 -0
  42. package/src/lib/queryEngine.d.ts +48 -0
  43. package/src/lib/queryEngine.js +461 -0
  44. package/src/lib/queryEngine.js.map +1 -0
  45. package/src/lib/schemaValidation.d.ts +80 -0
  46. package/src/lib/schemaValidation.js +353 -0
  47. package/src/lib/schemaValidation.js.map +1 -0
  48. package/src/lib/transaction.d.ts +7 -0
  49. package/src/lib/transaction.js +12 -0
  50. package/src/lib/transaction.js.map +1 -0
  51. package/src/lib/types.d.ts +360 -0
  52. package/src/lib/types.js +6 -0
  53. package/src/lib/types.js.map +1 -0
  54. package/src/lib/updateEngine.d.ts +7 -0
  55. package/src/lib/updateEngine.js +13 -0
  56. package/src/lib/updateEngine.js.map +1 -0
@@ -0,0 +1,268 @@
1
+ /**
2
+ * CBLIndex – higher-level CBL index built on top of a brightchain-db Collection.
3
+ *
4
+ * Tracks whitened CBL storage results with metadata, pool scoping,
5
+ * user-level organization, and file version history.
6
+ *
7
+ * Backed by a `Collection<ICBLIndexEntry>` named `__cbl_index__`.
8
+ */
9
+ import { type CBLIndexManifest, type IBlockStore, type ICBLIndexEntry, type ICBLIndexQueryOptions, type IGossipService } from '@brightchain/brightchain-lib';
10
+ import type { BrightChainDb } from './database';
11
+ /**
12
+ * Options for configuring the CBL Index.
13
+ */
14
+ export interface CBLIndexOptions {
15
+ /**
16
+ * Number of FEC parity blocks to generate for the collection's metadata
17
+ * blocks after each mutation. Set to 0 (default) to disable FEC redundancy.
18
+ *
19
+ * Uses the existing `IBlockStore.generateParityBlocks()` method.
20
+ */
21
+ parityCount?: number;
22
+ /**
23
+ * Number of index mutations after which an automatic snapshot is taken.
24
+ * Set to 0 to disable auto-snapshots. Default: 100.
25
+ *
26
+ * Auto-snapshots are best-effort — failures are logged but don't break mutations.
27
+ */
28
+ snapshotInterval?: number;
29
+ /**
30
+ * Enable recovery on startup when the index collection is empty.
31
+ * Recovery order: (1) latest snapshot, (2) FEC parity rebuild, (3) block store scan.
32
+ * Default: true.
33
+ */
34
+ enableRecovery?: boolean;
35
+ /**
36
+ * Optional gossip service for announcing CBL index changes to peers.
37
+ * When provided, new entries and soft-deletions are announced to peers
38
+ * in the same pool via cbl_index_update and cbl_index_delete announcements.
39
+ *
40
+ * @see Requirements 8.1, 8.6
41
+ */
42
+ gossipService?: IGossipService;
43
+ }
44
+ /**
45
+ * Higher-level CBL index built on top of a brightchain-db Collection.
46
+ * Tracks whitened CBL storage results with metadata, pool scoping,
47
+ * and user-level organization.
48
+ */
49
+ export declare class CBLIndex {
50
+ private readonly collection;
51
+ private sequenceCounter;
52
+ private readonly blockStore;
53
+ private readonly parityCount;
54
+ private readonly snapshotInterval;
55
+ private mutationsSinceSnapshot;
56
+ private readonly headRegistry;
57
+ private readonly dbName;
58
+ private readonly enableRecovery;
59
+ private readonly gossipService?;
60
+ constructor(db: BrightChainDb, blockStore: IBlockStore, options?: CBLIndexOptions);
61
+ /**
62
+ * Generate FEC parity blocks for the collection's current head (metadata) block.
63
+ * This is a best-effort operation — failures are logged but do not propagate.
64
+ */
65
+ private generateParityForHead;
66
+ /**
67
+ * Track a mutation and trigger an auto-snapshot if the threshold is reached.
68
+ * Auto-snapshots are best-effort — failures are logged but don't break mutations.
69
+ */
70
+ private trackMutationForAutoSnapshot;
71
+ /**
72
+ * Create a snapshot of the current index state.
73
+ * Serializes all entries (including soft-deleted) and the sequence counter,
74
+ * stores the data as a CBL via the block store, and returns the magnet URL.
75
+ *
76
+ * Persists the snapshot magnet URL in the head registry so recovery can find it.
77
+ * Resets the mutation counter on success so auto-snapshot tracking restarts.
78
+ */
79
+ snapshot(): Promise<string>;
80
+ /**
81
+ * Initialize the sequence counter from existing entries.
82
+ * Call this after construction to resume from the highest existing sequence number.
83
+ *
84
+ * If the collection is empty and recovery is enabled, attempts recovery in order:
85
+ * (1) latest snapshot, (2) FEC parity rebuild, (3) block store scan.
86
+ */
87
+ initialize(): Promise<void>;
88
+ /**
89
+ * Attempt to recover the CBL index from available sources.
90
+ * Recovery order:
91
+ * 1. Latest snapshot (magnet URL stored in head registry)
92
+ * 2. FEC parity rebuild of the collection's head block
93
+ * 3. Block store scan for CBL blocks (partial rebuild — metadata lost)
94
+ *
95
+ * @returns true if any recovery method succeeded, false if all failed
96
+ */
97
+ private recover;
98
+ /**
99
+ * Strategy 1: Restore from the latest snapshot whose magnet URL is
100
+ * persisted in the head registry.
101
+ */
102
+ private recoverFromSnapshot;
103
+ /**
104
+ * Strategy 2: Recover the collection's head metadata block via FEC parity,
105
+ * then let the Collection re-load its documents from the recovered block.
106
+ */
107
+ private recoverFromFEC;
108
+ /**
109
+ * Strategy 3: Scan the block store for CBL blocks and rebuild a minimal
110
+ * index from structural data only. This is a last-resort recovery that
111
+ * loses all user metadata (file names, tags, collections, visibility, etc.).
112
+ *
113
+ * Iterates all blocks in all pools, checks for the BrightChain CBL magic
114
+ * prefix (0xBC), and creates minimal index entries for discovered CBL blocks.
115
+ */
116
+ private recoverFromBlockScan;
117
+ /**
118
+ * Heuristic check for whether block data looks like a CBL block.
119
+ * CBL blocks in BrightChain start with the magic prefix 0xBC.
120
+ */
121
+ private looksLikeCblBlock;
122
+ /**
123
+ * Add a new CBL index entry.
124
+ * Validates that both referenced block IDs exist in the block store,
125
+ * assigns a monotonically increasing sequence number, and inserts.
126
+ */
127
+ addEntry(entry: Omit<ICBLIndexEntry, '_id' | 'sequenceNumber'>): Promise<ICBLIndexEntry>;
128
+ /**
129
+ * Look up a single entry by its magnet URL.
130
+ */
131
+ getByMagnetUrl(magnetUrl: string): Promise<ICBLIndexEntry | null>;
132
+ /**
133
+ * Look up entries by block ID (matches either blockId1 or blockId2).
134
+ */
135
+ getByBlockId(blockId: string): Promise<ICBLIndexEntry[]>;
136
+ /**
137
+ * Query entries with multi-attribute filtering, pagination, and sort.
138
+ */
139
+ query(options: ICBLIndexQueryOptions): Promise<ICBLIndexEntry[]>;
140
+ /**
141
+ * Soft-delete an entry by magnet URL (sets deletedAt timestamp).
142
+ */
143
+ softDelete(magnetUrl: string): Promise<void>;
144
+ /**
145
+ * Aggregate CBL counts per pool.
146
+ * Returns a Map of poolId → count for all non-deleted entries.
147
+ */
148
+ getPoolCBLCounts(): Promise<Map<string, number>>;
149
+ /**
150
+ * Find entries whose XOR component blocks exist in pools other than the given poolId.
151
+ * Returns block IDs and the set of pools they appear in.
152
+ */
153
+ getCrossPoolDependencies(poolId: string): Promise<{
154
+ blockId: string;
155
+ pools: string[];
156
+ }[]>;
157
+ /**
158
+ * Get all CBL entries belonging to a specific pool (for pool deletion validation).
159
+ * Returns all non-deleted entries in the pool so the caller can assess
160
+ * whether the pool is safe to delete.
161
+ *
162
+ * Requirement 5.3: report all CBL entries in a pool as part of deletion validation.
163
+ */
164
+ getPoolEntries(poolId: string): Promise<ICBLIndexEntry[]>;
165
+ /**
166
+ * Share a CBL entry with another user.
167
+ * Adds the userId to the sharedWith array and sets visibility to Shared.
168
+ */
169
+ shareWith(magnetUrl: string, userId: string): Promise<void>;
170
+ /**
171
+ * Restore the index from a snapshot.
172
+ * Retrieves the CBL by magnet URL, deserializes the JSON payload,
173
+ * clears the current collection, and re-inserts all entries from the snapshot.
174
+ * Also restores the sequence counter.
175
+ */
176
+ restoreFromSnapshot(magnetUrl: string): Promise<void>;
177
+ /**
178
+ * Add a new version of a file.
179
+ * Auto-assigns versionNumber (previous max + 1) and sets previousVersion
180
+ * to the current latest version's magnet URL.
181
+ *
182
+ * IMPORTANT: version numbering considers ALL versions including soft-deleted
183
+ * ones so that the version chain remains intact (Requirement 27.8).
184
+ */
185
+ addVersion(fileId: string, entry: Omit<ICBLIndexEntry, '_id' | 'sequenceNumber' | 'fileId' | 'versionNumber' | 'previousVersion'>): Promise<ICBLIndexEntry>;
186
+ /**
187
+ * Get all versions of a file, ordered by versionNumber ascending.
188
+ *
189
+ * @param fileId - The stable file identifier grouping all versions.
190
+ * @param includeDeleted - When true, includes soft-deleted versions in the
191
+ * result. Useful for verifying chain integrity (Requirement 27.8).
192
+ * Defaults to false.
193
+ */
194
+ getVersionHistory(fileId: string, includeDeleted?: boolean): Promise<ICBLIndexEntry[]>;
195
+ /**
196
+ * Get the latest version of a file (O(1) via sort + limit 1).
197
+ *
198
+ * @param fileId - The stable file identifier grouping all versions.
199
+ * @param includeDeleted - When true, considers soft-deleted versions.
200
+ * Used internally by addVersion to maintain chain integrity.
201
+ * Defaults to false.
202
+ */
203
+ getLatestVersion(fileId: string, includeDeleted?: boolean): Promise<ICBLIndexEntry | null>;
204
+ /**
205
+ * Merge an incoming CBL index entry from a remote peer (via gossip).
206
+ *
207
+ * Idempotent: if an entry with the same magnet URL already exists and has
208
+ * identical content (blockId1, blockId2, blockSize), the merge is a no-op.
209
+ *
210
+ * Conflict: if an entry with the same magnet URL exists but has different
211
+ * content, both entries are preserved and flagged with `hasConflict: true`
212
+ * and cross-referenced via `conflictsWith`.
213
+ *
214
+ * New entry: if no entry with the magnet URL exists, the entry is inserted
215
+ * with a new local sequence number.
216
+ *
217
+ * @param entry - The incoming entry from a remote peer.
218
+ * @returns The merged entry (existing, new, or conflict-flagged).
219
+ *
220
+ * @see Requirements 8.2, 8.3
221
+ */
222
+ mergeEntry(entry: ICBLIndexEntry): Promise<ICBLIndexEntry>;
223
+ /**
224
+ * Apply a soft-delete from a remote peer (via gossip).
225
+ *
226
+ * If the entry exists locally and is not already soft-deleted, marks it
227
+ * as deleted with the provided timestamp. If the entry doesn't exist
228
+ * locally or is already deleted, this is a no-op.
229
+ *
230
+ * @param magnetUrl - The magnet URL of the entry to soft-delete.
231
+ * @param deletedAt - The deletion timestamp from the remote peer.
232
+ *
233
+ * @see Requirements 8.6
234
+ */
235
+ mergeSoftDelete(magnetUrl: string, deletedAt: Date): Promise<void>;
236
+ /**
237
+ * Get a CBL index manifest for a specific pool.
238
+ * Returns a list of (magnetUrl, sequenceNumber) pairs for all non-deleted
239
+ * entries in the given pool. Used during pool-scoped reconciliation to
240
+ * compare CBL index state between nodes.
241
+ *
242
+ * @param poolId - The pool to generate a manifest for
243
+ * @param nodeId - The local node ID to include in the manifest
244
+ * @returns A CBLIndexManifest for the specified pool
245
+ * @see Requirements 8.4
246
+ */
247
+ getCBLIndexManifest(poolId: string, nodeId: string): Promise<CBLIndexManifest>;
248
+ /**
249
+ * Reconcile the local CBL index for a pool against a remote manifest.
250
+ * Identifies entries present in the remote manifest but missing locally,
251
+ * and merges them using the provided entry fetcher.
252
+ *
253
+ * @param poolId - The pool being reconciled
254
+ * @param remoteManifest - The remote node's CBL index manifest
255
+ * @param fetchEntry - Callback to fetch a full CBL index entry from the remote peer by magnet URL
256
+ * @returns The number of entries merged
257
+ * @see Requirements 8.4
258
+ */
259
+ reconcileCBLIndex(poolId: string, remoteManifest: CBLIndexManifest, fetchEntry: (magnetUrl: string) => Promise<ICBLIndexEntry | null>): Promise<number>;
260
+ /**
261
+ * Build a FilterQuery from ICBLIndexQueryOptions.
262
+ */
263
+ private buildFilter;
264
+ /**
265
+ * Build a SortSpec from ICBLIndexQueryOptions.
266
+ */
267
+ private buildSort;
268
+ }