@semiont/event-sourcing 0.5.4 → 0.5.5

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.
@@ -1,51 +0,0 @@
1
- /**
2
- * EventLog - Event Persistence Layer
3
- *
4
- * Single Responsibility: Event persistence only
5
- * - Appends events to storage (JSONL files)
6
- * - Retrieves events by resource
7
- * - Queries events with filters
8
- *
9
- * Does NOT handle:
10
- * - Pub/sub notifications (see EventBus)
11
- * - View updates (see ViewManager)
12
- */
13
- import { type ResourceId, type StoredEvent, type EventQuery, type EventInput, type Logger } from '@semiont/core';
14
- import type { SemiontProject } from '@semiont/core/node';
15
- import { EventStorage } from './storage/event-storage';
16
- export interface EventLogConfig {
17
- project: SemiontProject;
18
- enableSharding?: boolean;
19
- maxEventsPerFile?: number;
20
- }
21
- export declare class EventLog {
22
- readonly storage: EventStorage;
23
- constructor(config: EventLogConfig, logger?: Logger);
24
- /**
25
- * Append event to log
26
- * @param event - Resource event (from @semiont/core)
27
- * @param resourceId - Branded ResourceId (from @semiont/core)
28
- * @param options.correlationId - Optional command correlation id (stored on metadata)
29
- * @returns Stored event with metadata (sequence number, timestamp, checksum)
30
- */
31
- append(event: EventInput, resourceId: ResourceId, options?: {
32
- correlationId?: string;
33
- }): Promise<StoredEvent>;
34
- /**
35
- * Get all events for a resource
36
- * @param resourceId - Branded ResourceId (from @semiont/core)
37
- */
38
- getEvents(resourceId: ResourceId): Promise<StoredEvent[]>;
39
- /**
40
- * Get all resource IDs
41
- * @returns Array of branded ResourceId types
42
- */
43
- getAllResourceIds(): Promise<ResourceId[]>;
44
- /**
45
- * Query events with filter
46
- * @param resourceId - Branded ResourceId (from @semiont/core)
47
- * @param filter - Optional event filter
48
- */
49
- queryEvents(resourceId: ResourceId, filter?: EventQuery): Promise<StoredEvent[]>;
50
- }
51
- //# sourceMappingURL=event-log.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"event-log.d.ts","sourceRoot":"","sources":["../src/event-log.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,KAAK,UAAU,EAAE,KAAK,WAAW,EAAE,KAAK,UAAU,EAAE,KAAK,UAAU,EAAE,KAAK,MAAM,EAAE,MAAM,eAAe,CAAC;AACjH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAEvD,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,cAAc,CAAC;IACxB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,qBAAa,QAAQ;IAEnB,QAAQ,CAAC,OAAO,EAAE,YAAY,CAAC;gBAEnB,MAAM,EAAE,cAAc,EAAE,MAAM,CAAC,EAAE,MAAM;IAOnD;;;;;;OAMG;IACG,MAAM,CACV,KAAK,EAAE,UAAU,EACjB,UAAU,EAAE,UAAU,EACtB,OAAO,CAAC,EAAE;QAAE,aAAa,CAAC,EAAE,MAAM,CAAA;KAAE,GACnC,OAAO,CAAC,WAAW,CAAC;IAIvB;;;OAGG;IACG,SAAS,CAAC,UAAU,EAAE,UAAU,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IAI/D;;;OAGG;IACG,iBAAiB,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC;IAIhD;;;;OAIG;IACG,WAAW,CAAC,UAAU,EAAE,UAAU,EAAE,MAAM,CAAC,EAAE,UAAU,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;CAavF"}
@@ -1,19 +0,0 @@
1
- /**
2
- * Event Store Factory
3
- *
4
- * Factory function for creating EventStore instances with standard configuration.
5
- * This is the canonical way to instantiate an EventStore.
6
- */
7
- import type { SemiontProject } from '@semiont/core/node';
8
- import type { EventBus as CoreEventBus, Logger } from '@semiont/core';
9
- import { EventStore } from './event-store';
10
- /**
11
- * Create and initialize an EventStore instance
12
- *
13
- * @param project - SemiontProject instance
14
- * @param eventBus - @semiont/core EventBus for publishing domain events
15
- * @param logger - Optional logger for structured logging
16
- * @returns Configured EventStore instance ready for use
17
- */
18
- export declare function createEventStore(project: SemiontProject, eventBus: CoreEventBus, logger?: Logger): EventStore;
19
- //# sourceMappingURL=event-store-factory.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"event-store-factory.d.ts","sourceRoot":"","sources":["../src/event-store-factory.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,KAAK,EAAE,QAAQ,IAAI,YAAY,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AACtE,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAG3C;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,cAAc,EACvB,QAAQ,EAAE,YAAY,EACtB,MAAM,CAAC,EAAE,MAAM,GACd,UAAU,CAUZ"}
@@ -1,40 +0,0 @@
1
- /**
2
- * EventStore - Orchestration Layer
3
- *
4
- * Coordinates event sourcing operations:
5
- * - EventLog: Event persistence (append, retrieve, query)
6
- * - ViewManager: View materialization (resource and system)
7
- * - Core EventBus: Publishes StoredEvent to typed channels after persistence
8
- *
9
- * appendEvent() is the single write path:
10
- * 1. Persist to EventLog
11
- * 2. Materialize views
12
- * 3. Enrich (optional callback — attach post-materialization data)
13
- * 4. Publish StoredEvent to global and resource-scoped typed channels
14
- */
15
- import type { EventInput, StoredEvent, ResourceId, Logger } from '@semiont/core';
16
- import { EventBus as CoreEventBus } from '@semiont/core';
17
- import type { SemiontProject } from '@semiont/core/node';
18
- import type { ViewStorage } from './storage/view-storage';
19
- import { EventLog } from './event-log';
20
- import { ViewManager } from './view-manager';
21
- export type EnrichEvent = (event: StoredEvent, resourceId: ResourceId) => Promise<StoredEvent>;
22
- export declare class EventStore {
23
- readonly log: EventLog;
24
- readonly views: ViewManager;
25
- readonly viewStorage: ViewStorage;
26
- readonly coreEventBus: CoreEventBus;
27
- private enrichEvent;
28
- constructor(project: SemiontProject, stateDir: string, viewStorage: ViewStorage, coreEventBus: CoreEventBus, logger?: Logger);
29
- setEnrichEvent(fn: EnrichEvent): void;
30
- /**
31
- * Append an event to the store
32
- * Coordinates: persistence → view → enrich → notification
33
- *
34
- * @param options.correlationId - Optional id propagated from a command.
35
- */
36
- appendEvent(event: EventInput, options?: {
37
- correlationId?: string;
38
- }): Promise<StoredEvent>;
39
- }
40
- //# sourceMappingURL=event-store.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"event-store.d.ts","sourceRoot":"","sources":["../src/event-store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EACV,UAAU,EACV,WAAW,EACX,UAAU,EACV,MAAM,EACP,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,QAAQ,IAAI,YAAY,EAAE,MAAM,eAAe,CAAC;AACzD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,OAAO,EAAE,WAAW,EAA0B,MAAM,gBAAgB,CAAC;AAErE,MAAM,MAAM,WAAW,GAAG,CAAC,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,UAAU,KAAK,OAAO,CAAC,WAAW,CAAC,CAAC;AAE/F,qBAAa,UAAU;IACrB,QAAQ,CAAC,GAAG,EAAE,QAAQ,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC;IAC5B,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAC;IAClC,QAAQ,CAAC,YAAY,EAAE,YAAY,CAAC;IACpC,OAAO,CAAC,WAAW,CAA4B;gBAG7C,OAAO,EAAE,cAAc,EACvB,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,WAAW,EACxB,YAAY,EAAE,YAAY,EAC1B,MAAM,CAAC,EAAE,MAAM;IAajB,cAAc,CAAC,EAAE,EAAE,WAAW,GAAG,IAAI;IAIrC;;;;;OAKG;IACG,WAAW,CACf,KAAK,EAAE,UAAU,EACjB,OAAO,CAAC,EAAE;QAAE,aAAa,CAAC,EAAE,MAAM,CAAA;KAAE,GACnC,OAAO,CAAC,WAAW,CAAC;CAoCxB"}
@@ -1,10 +0,0 @@
1
- /**
2
- * Identifier utilities for event sourcing
3
- */
4
- /**
5
- * Generate a unique annotation ID (bare nanoid)
6
- *
7
- * @returns A bare annotation ID (e.g., "V1StGXR8_Z5jdHi6B-myT")
8
- */
9
- export declare function generateAnnotationId(): string;
10
- //# sourceMappingURL=identifier-utils.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"identifier-utils.d.ts","sourceRoot":"","sources":["../src/identifier-utils.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH;;;;GAIG;AACH,wBAAgB,oBAAoB,IAAI,MAAM,CAE7C"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,EAAE,UAAU,EAAE,KAAK,WAAW,EAAE,MAAM,eAAe,CAAC;AAC7D,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,QAAQ,EAAE,KAAK,cAAc,EAAE,MAAM,aAAa,CAAC;AAC5D,OAAO,EAAE,WAAW,EAAE,KAAK,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAGrE,OAAO,EAAE,KAAK,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAClE,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,EACL,KAAK,WAAW,EAChB,KAAK,YAAY,EACjB,qBAAqB,GACtB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,YAAY,EAAE,MAAM,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AACjF,OAAO,EACL,iBAAiB,EACjB,oBAAoB,EACpB,qBAAqB,EACrB,qBAAqB,EACrB,KAAK,eAAe,GACrB,MAAM,6BAA6B,CAAC;AAIrC,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAGjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAC7D,OAAO,EACL,oBAAoB,EACpB,mBAAmB,EACnB,KAAK,yBAAyB,GAC/B,MAAM,6BAA6B,CAAC;AAGrC,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC"}
@@ -1,48 +0,0 @@
1
- /**
2
- * Event Query - Read Operations
3
- *
4
- * Handles querying and reading events from storage:
5
- * - Query events with filters (type, user, timestamp, sequence)
6
- * - Get all events for a resource
7
- * - Get last event from a file
8
- * - Efficient streaming reads from JSONL files
9
- *
10
- * @see docs/EVENT-STORE.md#eventquery for architecture details
11
- */
12
- import type { StoredEvent, EventQuery as EventQueryType, ResourceId } from '@semiont/core';
13
- import type { EventStorage } from '../storage/event-storage';
14
- /**
15
- * EventQuery handles all read operations for events
16
- * Uses EventStorage for file access, adds query filtering
17
- */
18
- export declare class EventQuery {
19
- private eventStorage;
20
- constructor(eventStorage: EventStorage);
21
- /**
22
- * Query events with filters
23
- * Supports filtering by: userId, eventTypes, timestamps, sequence number, limit
24
- */
25
- queryEvents(query: EventQueryType): Promise<StoredEvent[]>;
26
- /**
27
- * Get all events for a specific resource (no filters)
28
- */
29
- getResourceEvents(resourceId: ResourceId): Promise<StoredEvent[]>;
30
- /**
31
- * Get the last event from a specific file
32
- * Useful for initializing sequence numbers and last hashes
33
- */
34
- getLastEvent(resourceId: ResourceId, filename: string): Promise<StoredEvent | null>;
35
- /**
36
- * Get the latest event for a resource across all files
37
- */
38
- getLatestEvent(resourceId: ResourceId): Promise<StoredEvent | null>;
39
- /**
40
- * Get event count for a resource
41
- */
42
- getEventCount(resourceId: ResourceId): Promise<number>;
43
- /**
44
- * Check if a resource has any events
45
- */
46
- hasEvents(resourceId: ResourceId): Promise<boolean>;
47
- }
48
- //# sourceMappingURL=event-query.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"event-query.d.ts","sourceRoot":"","sources":["../../src/query/event-query.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,IAAI,cAAc,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3F,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAE7D;;;GAGG;AACH,qBAAa,UAAU;IACT,OAAO,CAAC,YAAY;gBAAZ,YAAY,EAAE,YAAY;IAE9C;;;OAGG;IACG,WAAW,CAAC,KAAK,EAAE,cAAc,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IAuChE;;OAEG;IACG,iBAAiB,CAAC,UAAU,EAAE,UAAU,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IAIvE;;;OAGG;IACG,YAAY,CAAC,UAAU,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC;IAIzF;;OAEG;IACG,cAAc,CAAC,UAAU,EAAE,UAAU,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC;IAezE;;OAEG;IACG,aAAa,CAAC,UAAU,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC;IAK5D;;OAEG;IACG,SAAS,CAAC,UAAU,EAAE,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC;CAI1D"}
@@ -1,111 +0,0 @@
1
- /**
2
- * Event Storage - Physical Storage Layer
3
- *
4
- * Handles file I/O operations for event storage:
5
- * - JSONL file writing/reading
6
- * - 4-hex sharding (65,536 shards)
7
- * - File rotation
8
- * - Event stream initialization
9
- *
10
- * @see docs/EVENT-STORE.md#eventstorage for architecture details
11
- */
12
- import type { StoredEvent, EventInput, ResourceId, Logger } from '@semiont/core';
13
- import type { SemiontProject } from '@semiont/core/node';
14
- export interface EventStorageConfig {
15
- maxEventsPerFile?: number;
16
- enableSharding?: boolean;
17
- numShards?: number;
18
- enableCompression?: boolean;
19
- }
20
- /**
21
- * EventStorage handles physical storage of events
22
- * Owns: file I/O, sharding, AND sequence/hash tracking
23
- */
24
- export declare class EventStorage {
25
- private config;
26
- private project;
27
- private logger?;
28
- private resourceSequences;
29
- private currentFiles;
30
- constructor(project: SemiontProject, config?: EventStorageConfig, logger?: Logger);
31
- /**
32
- * Calculate shard path for a resource ID
33
- * Uses jump consistent hash for uniform distribution
34
- * Special case: __system__ events bypass sharding
35
- */
36
- getShardPath(resourceId: ResourceId): string;
37
- /**
38
- * Get full path to resource's event directory
39
- */
40
- getResourcePath(resourceId: ResourceId): string;
41
- /**
42
- * Initialize directory structure for a resource's event stream
43
- * Also loads sequence number and last hash if stream exists
44
- */
45
- initializeResourceStream(resourceId: ResourceId): Promise<void>;
46
- /**
47
- * Append an event - handles EVERYTHING for event creation
48
- * Creates ID, timestamp, metadata, sequence tracking, and writes to disk.
49
- *
50
- * Integrity is provided by git at the commit level (when gitSync is enabled),
51
- * not by per-event chaining metadata. Per-event signatures (the unused
52
- * `EventSignature` field on StoredEvent) are the planned mechanism for
53
- * cross-KB authorship binding when federation becomes a real requirement.
54
- *
55
- * @param options.correlationId - Optional id propagated from a command. Stored
56
- * on the event's metadata so subscribers (notably the events-stream → frontend
57
- * path) can match command-result events back to the POST that initiated them.
58
- */
59
- appendEvent(event: EventInput, resourceId: ResourceId, options?: {
60
- correlationId?: string;
61
- }): Promise<StoredEvent>;
62
- /**
63
- * Write an event to storage (append to JSONL)
64
- * Internal method - use appendEvent() instead
65
- *
66
- * Uses currentFiles cache to avoid fs.readdir() + countEventsInFile() on every append.
67
- * Cache is populated on first append (cold start) and updated on rotation.
68
- */
69
- private writeEvent;
70
- /**
71
- * Count events in a specific file
72
- */
73
- countEventsInFile(resourceId: ResourceId, filename: string): Promise<number>;
74
- /**
75
- * Read all events from a specific file
76
- */
77
- readEventsFromFile(resourceId: ResourceId, filename: string): Promise<StoredEvent[]>;
78
- /**
79
- * Get list of event files for a resource (sorted by sequence)
80
- */
81
- getEventFiles(resourceId: ResourceId): Promise<string[]>;
82
- /**
83
- * Create a new event file for rotation
84
- */
85
- createNewEventFile(resourceId: ResourceId): Promise<string>;
86
- /**
87
- * Get the last event from a specific file
88
- */
89
- getLastEvent(resourceId: ResourceId, filename: string): Promise<StoredEvent | null>;
90
- /**
91
- * Get all events for a resource across all files
92
- */
93
- getAllEvents(resourceId: ResourceId): Promise<StoredEvent[]>;
94
- /**
95
- * Get all resource IDs by scanning shard directories
96
- */
97
- getAllResourceIds(): Promise<ResourceId[]>;
98
- /**
99
- * Create filename for event file
100
- */
101
- private createEventFilename;
102
- /**
103
- * Get current sequence number for a resource
104
- */
105
- getSequenceNumber(resourceId: ResourceId): number;
106
- /**
107
- * Increment and return next sequence number for a resource
108
- */
109
- getNextSequenceNumber(resourceId: ResourceId): number;
110
- }
111
- //# sourceMappingURL=event-storage.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"event-storage.d.ts","sourceRoot":"","sources":["../../src/storage/event-storage.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAQH,OAAO,KAAK,EAAE,WAAW,EAAiC,UAAU,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAEhH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAGzD,MAAM,WAAW,kBAAkB;IACjC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED;;;GAGG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,MAAM,CAA+B;IAC7C,OAAO,CAAC,OAAO,CAAiB;IAChC,OAAO,CAAC,MAAM,CAAC,CAAS;IAGxB,OAAO,CAAC,iBAAiB,CAAkC;IAE3D,OAAO,CAAC,YAAY,CAAgE;gBAExE,OAAO,EAAE,cAAc,EAAE,MAAM,CAAC,EAAE,kBAAkB,EAAE,MAAM,CAAC,EAAE,MAAM;IAWjF;;;;OAIG;IACH,YAAY,CAAC,UAAU,EAAE,UAAU,GAAG,MAAM;IAgB5C;;OAEG;IACH,eAAe,CAAC,UAAU,EAAE,UAAU,GAAG,MAAM;IAK/C;;;OAGG;IACG,wBAAwB,CAAC,UAAU,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IA+CrE;;;;;;;;;;;;OAYG;IACG,WAAW,CACf,KAAK,EAAE,UAAU,EACjB,UAAU,EAAE,UAAU,EACtB,OAAO,CAAC,EAAE;QAAE,aAAa,CAAC,EAAE,MAAM,CAAA;KAAE,GACnC,OAAO,CAAC,WAAW,CAAC;IA+BvB;;;;;;OAMG;YACW,UAAU;IAoCxB;;OAEG;IACG,iBAAiB,CAAC,UAAU,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAgBlF;;OAEG;IACG,kBAAkB,CAAC,UAAU,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IAyC1F;;OAEG;IACG,aAAa,CAAC,UAAU,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAwB9D;;OAEG;IACG,kBAAkB,CAAC,UAAU,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC;IAoBjE;;OAEG;IACG,YAAY,CAAC,UAAU,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC;IAMzF;;OAEG;IACG,YAAY,CAAC,UAAU,EAAE,UAAU,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IAYlE;;OAEG;IACG,iBAAiB,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC;IAkChD;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAQ3B;;OAEG;IACH,iBAAiB,CAAC,UAAU,EAAE,UAAU,GAAG,MAAM;IAIjD;;OAEG;IACH,qBAAqB,CAAC,UAAU,EAAE,UAAU,GAAG,MAAM;CAOtD"}
@@ -1,56 +0,0 @@
1
- /**
2
- * Sharding Utilities
3
- *
4
- * Shared utilities for consistent sharding across all storage layers
5
- * Uses Google's Jump Consistent Hash algorithm for even distribution
6
- */
7
- /**
8
- * TEMPORARY: Simple modulo-based hash sharding
9
- *
10
- * ⚠️ TODO: Replace with proper Jump Consistent Hash implementation
11
- *
12
- * This is a TEMPORARY implementation using simple modulo. It works and provides
13
- * good distribution, but does NOT provide the minimal reshuffling property of
14
- * Jump Consistent Hash when changing bucket counts.
15
- *
16
- * The proper implementation should use Google's Jump Consistent Hash algorithm:
17
- * Reference: "A Fast, Minimal Memory, Consistent Hash Algorithm" by Lamping & Veach (2014)
18
- * https://arxiv.org/abs/1406.2294
19
- *
20
- * Working implementations exist in npm packages like:
21
- * - jumphash (https://www.npmjs.com/package/jumphash)
22
- * - jump-gouache (https://github.com/bhoudu/jump-gouache)
23
- *
24
- * The algorithm requires proper 64-bit integer handling with BigInt to avoid
25
- * precision loss in JavaScript. The previous attempt failed due to incorrect
26
- * BigInt arithmetic in the while loop condition.
27
- *
28
- * Until replaced, this modulo approach will cause ALL data to be reshuffled
29
- * if bucket count changes, rather than the optimal O(n/k) reshuffling that
30
- * Jump Consistent Hash provides.
31
- *
32
- * @param key - The key to hash (typically a resource ID)
33
- * @param numBuckets - Number of shards/buckets (default: 65536 for 4-hex sharding)
34
- * @returns Shard number (0 to numBuckets-1)
35
- */
36
- export declare function jumpConsistentHash(key: string, numBuckets?: number): number;
37
- /**
38
- * Convert shard number to 4-hex directory path (ab/cd)
39
- *
40
- * @param shardId - Shard number (0-65535)
41
- * @returns Path segments like ['ab', 'cd']
42
- */
43
- export declare function shardIdToPath(shardId: number): [string, string];
44
- /**
45
- * Get 4-hex shard path for a key
46
- *
47
- * @param key - The key to hash (typically a resource ID)
48
- * @param numBuckets - Number of shards (default: 65536)
49
- * @returns Path segments like ['ab', 'cd']
50
- */
51
- export declare function getShardPath(key: string, numBuckets?: number): [string, string];
52
- /**
53
- * Calculate SHA-256 hash of data
54
- */
55
- export declare function sha256(data: string | object): string;
56
- //# sourceMappingURL=shard-utils.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"shard-utils.d.ts","sourceRoot":"","sources":["../../src/storage/shard-utils.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,GAAE,MAAc,GAAG,MAAM,CAGlF;AAcD;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAU/D;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,GAAE,MAAc,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAGtF;AAED;;GAEG;AACH,wBAAgB,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAGpD"}
@@ -1,60 +0,0 @@
1
- /**
2
- * Storage URI Index
3
- *
4
- * Projection that maps file:// URIs → resourceIds.
5
- * Sharded at:
6
- * {projectionsDir}/storage-uri/{ab}/{cd}/{uri-hash}.json
7
- *
8
- * where {ab}/{cd} comes from jumpConsistentHash(uri) and
9
- * {uri-hash} is the SHA-256 of the URI string.
10
- *
11
- * Each file contains: { uri: string; resourceId: string }
12
- *
13
- * This index is maintained by ViewMaterializer (the single owner).
14
- * It is never modified by Stower or other actors.
15
- *
16
- * Archive/unarchive do NOT remove entries from this index.
17
- * Archived resources are marked in the ResourceView (archived: true)
18
- * but remain findable by URI.
19
- */
20
- export interface StorageUriEntry {
21
- uri: string;
22
- resourceId: string;
23
- }
24
- /**
25
- * Thrown when a URI is not found in the storage-uri index.
26
- */
27
- export declare class ResourceNotFoundError extends Error {
28
- readonly uri: string;
29
- constructor(uri: string);
30
- }
31
- /**
32
- * Resolve a file:// URI to a resourceId using the storage-uri index.
33
- *
34
- * @param projectionsDir - Path to the projections directory
35
- * @param uri - file:// URI (e.g. "file://docs/overview.md")
36
- * @returns resourceId
37
- * @throws ResourceNotFoundError if URI is not in the index
38
- */
39
- export declare function resolveStorageUri(projectionsDir: string, uri: string): Promise<string>;
40
- /**
41
- * Write a URI → resourceId mapping to the index.
42
- *
43
- * Called by ViewMaterializer when handling resource.created, resource.moved.
44
- *
45
- * @param projectionsDir - Path to the projections directory
46
- * @param uri - file:// URI
47
- * @param resourceId - resourceId to map to
48
- */
49
- export declare function writeStorageUriEntry(projectionsDir: string, uri: string, resourceId: string): Promise<void>;
50
- /**
51
- * Remove a URI entry from the index.
52
- *
53
- * Called by ViewMaterializer when handling resource.moved (old URI only).
54
- * NOT called on resource.archived — archived resources retain their index entry.
55
- *
56
- * @param projectionsDir - Path to the projections directory
57
- * @param uri - file:// URI to remove
58
- */
59
- export declare function removeStorageUriEntry(projectionsDir: string, uri: string): Promise<void>;
60
- //# sourceMappingURL=storage-uri-index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"storage-uri-index.d.ts","sourceRoot":"","sources":["../../src/storage/storage-uri-index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAMH,MAAM,WAAW,eAAe;IAC9B,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,qBAAa,qBAAsB,SAAQ,KAAK;IAClC,QAAQ,CAAC,GAAG,EAAE,MAAM;gBAAX,GAAG,EAAE,MAAM;CAIjC;AAED;;;;;;;GAOG;AACH,wBAAsB,iBAAiB,CACrC,cAAc,EAAE,MAAM,EACtB,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,MAAM,CAAC,CAYjB;AAED;;;;;;;;GAQG;AACH,wBAAsB,oBAAoB,CACxC,cAAc,EAAE,MAAM,EACtB,GAAG,EAAE,MAAM,EACX,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,IAAI,CAAC,CAKf;AAED;;;;;;;;GAQG;AACH,wBAAsB,qBAAqB,CACzC,cAAc,EAAE,MAAM,EACtB,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,IAAI,CAAC,CASf"}
@@ -1,33 +0,0 @@
1
- /**
2
- * View Storage - Materialized Views
3
- *
4
- * Stores materialized views of resource state and annotations
5
- * Built from event streams, can be rebuilt at any time
6
- *
7
- * Stores both ResourceDescriptor metadata and ResourceAnnotations, but keeps them logically separate
8
- */
9
- import type { SemiontProject } from '@semiont/core/node';
10
- import type { ResourceAnnotations, ResourceDescriptor, ResourceId, Logger } from '@semiont/core';
11
- export interface ResourceView {
12
- resource: ResourceDescriptor;
13
- annotations: ResourceAnnotations;
14
- }
15
- export interface ViewStorage {
16
- save(resourceId: ResourceId, view: ResourceView): Promise<void>;
17
- get(resourceId: ResourceId): Promise<ResourceView | null>;
18
- delete(resourceId: ResourceId): Promise<void>;
19
- exists(resourceId: ResourceId): Promise<boolean>;
20
- getAll(): Promise<ResourceView[]>;
21
- }
22
- export declare class FilesystemViewStorage implements ViewStorage {
23
- private basePath;
24
- private logger?;
25
- constructor(project: SemiontProject, logger?: Logger);
26
- private getProjectionPath;
27
- save(resourceId: ResourceId, projection: ResourceView): Promise<void>;
28
- get(resourceId: ResourceId): Promise<ResourceView | null>;
29
- delete(resourceId: ResourceId): Promise<void>;
30
- exists(resourceId: ResourceId): Promise<boolean>;
31
- getAll(): Promise<ResourceView[]>;
32
- }
33
- //# sourceMappingURL=view-storage.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"view-storage.d.ts","sourceRoot":"","sources":["../../src/storage/view-storage.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAKH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,KAAK,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAGjG,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,kBAAkB,CAAC;IAC7B,WAAW,EAAE,mBAAmB,CAAC;CAClC;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,CAAC,UAAU,EAAE,UAAU,EAAE,IAAI,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAChE,GAAG,CAAC,UAAU,EAAE,UAAU,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAAC;IAC1D,MAAM,CAAC,UAAU,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9C,MAAM,CAAC,UAAU,EAAE,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACjD,MAAM,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC;CACnC;AAED,qBAAa,qBAAsB,YAAW,WAAW;IACvD,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,MAAM,CAAC,CAAS;gBAEZ,OAAO,EAAE,cAAc,EAAE,MAAM,CAAC,EAAE,MAAM;IAKpD,OAAO,CAAC,iBAAiB;IAMnB,IAAI,CAAC,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAuBrE,GAAG,CAAC,UAAU,EAAE,UAAU,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC;IA8BzD,MAAM,CAAC,UAAU,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAa7C,MAAM,CAAC,UAAU,EAAE,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC;IAWhD,MAAM,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC;CAsCxC"}
@@ -1,84 +0,0 @@
1
- /**
2
- * ViewManager - Materialized View Management Layer
3
- *
4
- * Single Responsibility: View updates only
5
- * - Updates resource views from events
6
- * - Updates system views (entity types)
7
- * - Rebuilds views when needed
8
- *
9
- * Does NOT handle:
10
- * - Event persistence (see EventLog)
11
- * - Pub/sub notifications (see EventBus)
12
- */
13
- import { type ResourceId, type PersistedEvent, type StoredEvent, type Logger } from '@semiont/core';
14
- import { ViewMaterializer, type RebuildEventSource } from './views/view-materializer';
15
- import type { ViewStorage, ResourceView } from './storage/view-storage';
16
- export interface ViewManagerConfig {
17
- basePath: string;
18
- }
19
- /**
20
- * ViewManager wraps ViewMaterializer with a clean API
21
- * Handles both resource and system-level views
22
- *
23
- * ## Per-resource serialization
24
- *
25
- * `materializeResource` runs read-modify-write cycles on the view file for
26
- * a given resource (load JSON → apply event → save JSON). When multiple
27
- * events arrive for the same resource in rapid succession — the canonical
28
- * example is the reference-detection worker emitting `mark:added` +
29
- * `job:progress` + `job:completed` within a few milliseconds — concurrent
30
- * RMW cycles will clobber each other, losing events and occasionally
31
- * corrupting the view file entirely.
32
- *
33
- * ViewManager serializes these via `serializePerKey` from `@semiont/core`:
34
- * each incoming `materializeResource` call chains onto the previous one
35
- * for the same `resourceId`, so the work runs strictly sequentially per
36
- * resource while still parallelizing across different resources. System
37
- * events go through their own shared chain (keyed by a sentinel).
38
- *
39
- * Why this shape and not RxJS `groupBy + concatMap`:
40
- * ViewManager is called **synchronously** by `EventStore.appendEvent` — it
41
- * must block the caller until the view is written, so SSE subscribers
42
- * that see the subsequently-published event get the up-to-date view (a
43
- * read-your-writes guarantee). The RxJS stream-consumer pattern used by
44
- * `Smelter`, `GraphDBConsumer`, and `Gatherer` can't provide that
45
- * guarantee because it's fire-and-forget from the publisher's perspective.
46
- * Both patterns solve "serialize work per resource" — see also
47
- * `packages/core/src/serialize-per-key.ts` for the shared primitive.
48
- */
49
- export declare class ViewManager {
50
- readonly materializer: ViewMaterializer;
51
- private resourceChains;
52
- private systemChains;
53
- private static readonly SYSTEM_KEY;
54
- constructor(viewStorage: ViewStorage, config: ViewManagerConfig, logger?: Logger);
55
- /**
56
- * Update resource view with a new event.
57
- * Serialized per resource — see class doc.
58
- *
59
- * @param resourceId - Branded ResourceId (from @semiont/core)
60
- * @param event - Resource event (from @semiont/core)
61
- * @param getAllEvents - Function to retrieve all events for rebuild if needed
62
- */
63
- materializeResource(resourceId: ResourceId, event: PersistedEvent, getAllEvents: () => Promise<StoredEvent[]>): Promise<void>;
64
- /**
65
- * Update system-level view (entity types + tag schemas today).
66
- * Serialized through a shared chain — see class doc.
67
- */
68
- materializeSystem(eventType: string, payload: any): Promise<void>;
69
- /**
70
- * Rebuild all materialized views from the event log on startup.
71
- * Mirrors GraphDBConsumer.rebuildAll() — call this once during
72
- * createKnowledgeBase before the HTTP server begins accepting requests.
73
- * Idempotent: existing view files are overwritten.
74
- */
75
- rebuildAll(eventLog: RebuildEventSource): Promise<void>;
76
- /**
77
- * Get resource view (builds from events if needed)
78
- * @param resourceId - Branded ResourceId (from @semiont/core)
79
- * @param events - Stored events for the resource (from @semiont/core)
80
- * @returns Resource view or null if no events
81
- */
82
- getOrMaterialize(resourceId: ResourceId, events: StoredEvent[]): Promise<ResourceView | null>;
83
- }
84
- //# sourceMappingURL=view-manager.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"view-manager.d.ts","sourceRoot":"","sources":["../src/view-manager.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,KAAK,UAAU,EAAE,KAAK,cAAc,EAAE,KAAK,WAAW,EAAE,KAAK,MAAM,EAAmB,MAAM,eAAe,CAAC;AACrH,OAAO,EAAE,gBAAgB,EAA+B,KAAK,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AACnH,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAExE,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,qBAAa,WAAW;IAEtB,QAAQ,CAAC,YAAY,EAAE,gBAAgB,CAAC;IAKxC,OAAO,CAAC,cAAc,CAAoC;IAK1D,OAAO,CAAC,YAAY,CAAoC;IACxD,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAoB;gBAGpD,WAAW,EAAE,WAAW,EACxB,MAAM,EAAE,iBAAiB,EACzB,MAAM,CAAC,EAAE,MAAM;IAQjB;;;;;;;OAOG;IACG,mBAAmB,CACvB,UAAU,EAAE,UAAU,EACtB,KAAK,EAAE,cAAc,EACrB,YAAY,EAAE,MAAM,OAAO,CAAC,WAAW,EAAE,CAAC,GACzC,OAAO,CAAC,IAAI,CAAC;IAMhB;;;OAGG;IACG,iBAAiB,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC;IAWvE;;;;;OAKG;IACG,UAAU,CAAC,QAAQ,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC;IAI7D;;;;;OAKG;IACG,gBAAgB,CACpB,UAAU,EAAE,UAAU,EACtB,MAAM,EAAE,WAAW,EAAE,GACpB,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC;CAGhC"}
@@ -1,73 +0,0 @@
1
- /**
2
- * Projection reducers — the pure core of the system-level projection
3
- * materializers in `view-materializer.ts`.
4
- *
5
- * Each reducer takes the current state of a `__system__` projection and
6
- * a single command payload, and returns the next state plus any
7
- * side-effect signals (currently just optional warnings). The
8
- * surrounding I/O — read JSON file → reduce → write JSON file — lives
9
- * in the `ViewMaterializer` shell.
10
- *
11
- * Why this split: tests for the projection-update semantics shouldn't
12
- * need the filesystem or an Apple-container event store to assert
13
- * "registering identical content twice is a no-op." The shell is
14
- * already covered by integration tests at `tag-schemas-reader.test.ts`
15
- * (Stower → materializer → reader round-trip) and
16
- * `local-transport.test.ts` (real client → bus → cache invalidation).
17
- *
18
- * The reducers also become the natural home for the deferred schema-
19
- * evolution work in `.plans/EVOLVE-TAG-SCHEMA.md` — migration
20
- * commands (rename/remove a category, version-bump a schema id) are
21
- * additional pure functions on the same view shapes.
22
- *
23
- * Load-bearing properties (sortedness, uniqueness, idempotence,
24
- * most-recent-wins, no-mutation) are pinned by axiom-style fast-check
25
- * tests in `__tests__/views/projection-reducers.test.ts`. See
26
- * `docs/system/PROJECTION-PATTERN.md` for the full axiom catalog and
27
- * the architectural narrative.
28
- */
29
- import type { TagSchema } from '@semiont/core';
30
- /**
31
- * Apply a `frame:entity-type-added` event to the entity-types
32
- * projection. Idempotent — dedup via a `Set` + locale-aware sort.
33
- *
34
- * Sort uses `localeCompare` to match {@link applyTagSchemaAdded}'s
35
- * id-sort and to give a sensible ordering across mixed-case + symbol
36
- * tags. (The pre-refactor materializer used `Array.sort()` with no
37
- * comparator, which is codepoint order — `_x` would sort *after* `A`
38
- * because `_` (0x5F) > `A` (0x41). Surfaced by an axiom test in
39
- * `projection-reducers.test.ts`.)
40
- */
41
- export declare function applyEntityTypeAdded(current: readonly string[], add: string): string[];
42
- /**
43
- * Result of {@link applyTagSchemaAdded}.
44
- *
45
- * The reducer is pure — it doesn't log warnings itself. Instead it
46
- * returns the would-be warning as data; the I/O shell decides whether
47
- * to forward it to the logger. This keeps the function trivially
48
- * testable and lets callers compose multiple reductions without
49
- * threading a logger through.
50
- */
51
- export interface ApplyTagSchemaAddedResult {
52
- /** The next state of the tagSchemas list, sorted by id. */
53
- next: TagSchema[];
54
- /**
55
- * Set when an existing schema with the same id was overwritten with
56
- * differing content (deep-not-equal). Identical re-registrations
57
- * return `undefined` here — the projection silently no-ops.
58
- */
59
- warning?: {
60
- schemaId: string;
61
- message: string;
62
- };
63
- }
64
- /**
65
- * Apply a `frame:tag-schema-added` event to the tag-schemas projection.
66
- *
67
- * Most-recent-wins by `schema.id`:
68
- * - new id → append + sort
69
- * - existing id with identical content → no-op (warning undefined)
70
- * - existing id with differing content → replace + warning emitted
71
- */
72
- export declare function applyTagSchemaAdded(current: readonly TagSchema[], add: TagSchema): ApplyTagSchemaAddedResult;
73
- //# sourceMappingURL=projection-reducers.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"projection-reducers.d.ts","sourceRoot":"","sources":["../../src/views/projection-reducers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAI/C;;;;;;;;;;GAUG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,SAAS,MAAM,EAAE,EAC1B,GAAG,EAAE,MAAM,GACV,MAAM,EAAE,CAIV;AAID;;;;;;;;GAQG;AACH,MAAM,WAAW,yBAAyB;IACxC,2DAA2D;IAC3D,IAAI,EAAE,SAAS,EAAE,CAAC;IAClB;;;;OAIG;IACH,OAAO,CAAC,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;CACjD;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,SAAS,SAAS,EAAE,EAC7B,GAAG,EAAE,SAAS,GACb,yBAAyB,CAqB3B"}