@semiont/event-sourcing 0.4.13 → 0.4.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -4,7 +4,7 @@ import * as path from 'path';
4
4
  import path__default from 'path';
5
5
  import * as readline from 'readline';
6
6
  import { v4 } from 'uuid';
7
- import { resourceId, isSystemEvent, isResourceEvent, didToAgent, findBodyItem } from '@semiont/core';
7
+ import { resourceId, didToAgent, findBodyItem } from '@semiont/core';
8
8
  import { createHash } from 'crypto';
9
9
  import { nanoid } from 'nanoid';
10
10
 
@@ -124,8 +124,12 @@ var EventStorage = class {
124
124
  /**
125
125
  * Append an event - handles EVERYTHING for event creation
126
126
  * Creates ID, timestamp, metadata, checksum, sequence tracking, and writes to disk
127
+ *
128
+ * @param options.correlationId - Optional id propagated from a command. Stored
129
+ * on the event's metadata so subscribers (notably the events-stream → frontend
130
+ * path) can match command-result events back to the POST that initiated them.
127
131
  */
128
- async appendEvent(event, resourceId) {
132
+ async appendEvent(event, resourceId, options) {
129
133
  if (this.getSequenceNumber(resourceId) === 0) {
130
134
  await this.initializeResourceStream(resourceId);
131
135
  }
@@ -140,12 +144,12 @@ var EventStorage = class {
140
144
  sequenceNumber,
141
145
  streamPosition: 0,
142
146
  // Will be set during write
143
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
144
147
  prevEventHash: prevEventHash || void 0,
145
- checksum: sha256(completeEvent)
148
+ checksum: sha256(completeEvent),
149
+ ...options?.correlationId !== void 0 && { correlationId: options.correlationId }
146
150
  };
147
151
  const storedEvent = {
148
- event: completeEvent,
152
+ ...completeEvent,
149
153
  metadata
150
154
  };
151
155
  await this.writeEvent(storedEvent, resourceId);
@@ -221,8 +225,12 @@ var EventStorage = class {
221
225
  const trimmed = line.trim();
222
226
  if (trimmed === "") continue;
223
227
  try {
224
- const event = JSON.parse(trimmed);
225
- events.push(event);
228
+ const parsed = JSON.parse(trimmed);
229
+ if ("event" in parsed && "metadata" in parsed && !("type" in parsed)) {
230
+ events.push({ ...parsed.event, metadata: parsed.metadata, signature: parsed.signature });
231
+ } else {
232
+ events.push(parsed);
233
+ }
226
234
  } catch (parseError) {
227
235
  this.logger?.error("[EventStorage] Failed to parse event", { filePath, error: parseError });
228
236
  }
@@ -369,10 +377,11 @@ var EventLog = class {
369
377
  * Append event to log
370
378
  * @param event - Resource event (from @semiont/core)
371
379
  * @param resourceId - Branded ResourceId (from @semiont/core)
380
+ * @param options.correlationId - Optional command correlation id (stored on metadata)
372
381
  * @returns Stored event with metadata (sequence number, timestamp, checksum)
373
382
  */
374
- async append(event, resourceId) {
375
- return this.storage.appendEvent(event, resourceId);
383
+ async append(event, resourceId, options) {
384
+ return this.storage.appendEvent(event, resourceId, options);
376
385
  }
377
386
  /**
378
387
  * Get all events for a resource
@@ -397,224 +406,15 @@ var EventLog = class {
397
406
  const events = await this.storage.getAllEvents(resourceId);
398
407
  if (!filter) return events;
399
408
  return events.filter((e) => {
400
- if (filter.eventTypes && !filter.eventTypes.includes(e.event.type)) return false;
409
+ if (filter.eventTypes && !filter.eventTypes.includes(e.type)) return false;
401
410
  if (filter.fromSequence && e.metadata.sequenceNumber < filter.fromSequence) return false;
402
- if (filter.fromTimestamp && e.event.timestamp < filter.fromTimestamp) return false;
403
- if (filter.toTimestamp && e.event.timestamp > filter.toTimestamp) return false;
404
- if (filter.userId && e.event.userId !== filter.userId) return false;
411
+ if (filter.fromTimestamp && e.timestamp < filter.fromTimestamp) return false;
412
+ if (filter.toTimestamp && e.timestamp > filter.toTimestamp) return false;
413
+ if (filter.userId && e.userId !== filter.userId) return false;
405
414
  return true;
406
415
  });
407
416
  }
408
417
  };
409
-
410
- // src/subscriptions/event-subscriptions.ts
411
- var EventSubscriptions = class {
412
- // Per-resource subscriptions: ResourceId -> Set of callbacks
413
- subscriptions = /* @__PURE__ */ new Map();
414
- // Global subscriptions for system-level events (no resourceId)
415
- globalSubscriptions = /* @__PURE__ */ new Set();
416
- logger;
417
- constructor(logger) {
418
- this.logger = logger;
419
- }
420
- /**
421
- * Subscribe to events for a specific resource
422
- * Returns an EventSubscription with unsubscribe function
423
- */
424
- subscribe(resourceId, callback) {
425
- if (!this.subscriptions.has(resourceId)) {
426
- this.subscriptions.set(resourceId, /* @__PURE__ */ new Set());
427
- }
428
- const callbacks = this.subscriptions.get(resourceId);
429
- callbacks.add(callback);
430
- this.logger?.info("[EventSubscriptions] Subscription added for resource", { resourceId, totalSubscribers: callbacks.size });
431
- return {
432
- resourceId,
433
- callback,
434
- unsubscribe: () => {
435
- callbacks.delete(callback);
436
- this.logger?.info("[EventSubscriptions] Subscription removed for resource", { resourceId, remainingSubscribers: callbacks.size });
437
- if (callbacks.size === 0) {
438
- this.subscriptions.delete(resourceId);
439
- this.logger?.info("[EventSubscriptions] No more subscribers for resource, removed from subscriptions map", { resourceId });
440
- }
441
- }
442
- };
443
- }
444
- /**
445
- * Subscribe to all system-level events (no resourceId)
446
- * Returns an EventSubscription with unsubscribe function
447
- *
448
- * Use this for consumers that need to react to global events like:
449
- * - entitytype.added (global entity type collection changes)
450
- * - Future system-level events (user.created, workspace.created, etc.)
451
- */
452
- subscribeGlobal(callback) {
453
- this.globalSubscriptions.add(callback);
454
- this.logger?.info("[EventSubscriptions] Global subscription added", { totalSubscribers: this.globalSubscriptions.size });
455
- return {
456
- resourceId: "__global__",
457
- // Special marker for global subscriptions
458
- callback,
459
- unsubscribe: () => {
460
- this.globalSubscriptions.delete(callback);
461
- this.logger?.info("[EventSubscriptions] Global subscription removed", { remainingSubscribers: this.globalSubscriptions.size });
462
- }
463
- };
464
- }
465
- /**
466
- * Notify all subscribers for a resource when a new event is appended
467
- * @param resourceId - Bare resource ID
468
- */
469
- async notifySubscribers(resourceId, event) {
470
- const callbacks = this.subscriptions.get(resourceId);
471
- if (!callbacks || callbacks.size === 0) {
472
- this.logger?.info("[EventSubscriptions] Event - no subscribers to notify", { eventType: event.event.type, resourceId });
473
- return;
474
- }
475
- this.logger?.info("[EventSubscriptions] Notifying subscribers of event", { subscriberCount: callbacks.size, eventType: event.event.type, resourceId });
476
- Array.from(callbacks).forEach((callback, index) => {
477
- Promise.resolve(callback(event)).then(() => {
478
- this.logger?.info("[EventSubscriptions] Subscriber successfully notified", { subscriberIndex: index + 1, eventType: event.event.type });
479
- }).catch((error) => {
480
- this.logger?.error("[EventSubscriptions] Error in subscriber", { subscriberIndex: index + 1, resourceId, eventType: event.event.type, error });
481
- });
482
- });
483
- }
484
- /**
485
- * Notify all global subscribers when a system-level event is appended
486
- */
487
- async notifyGlobalSubscribers(event) {
488
- if (this.globalSubscriptions.size === 0) {
489
- this.logger?.info("[EventSubscriptions] System event - no global subscribers to notify", { eventType: event.event.type });
490
- return;
491
- }
492
- this.logger?.info("[EventSubscriptions] Notifying global subscribers of system event", { subscriberCount: this.globalSubscriptions.size, eventType: event.event.type });
493
- Array.from(this.globalSubscriptions).forEach((callback, index) => {
494
- Promise.resolve(callback(event)).then(() => {
495
- this.logger?.info("[EventSubscriptions] Global subscriber successfully notified", { subscriberIndex: index + 1, eventType: event.event.type });
496
- }).catch((error) => {
497
- this.logger?.error("[EventSubscriptions] Error in global subscriber", { subscriberIndex: index + 1, eventType: event.event.type, error });
498
- });
499
- });
500
- }
501
- /**
502
- * Get subscription count for a resource (useful for debugging)
503
- */
504
- getSubscriptionCount(resourceId) {
505
- return this.subscriptions.get(resourceId)?.size || 0;
506
- }
507
- /**
508
- * Get total number of active subscriptions across all resources
509
- */
510
- getTotalSubscriptions() {
511
- let total = 0;
512
- for (const callbacks of this.subscriptions.values()) {
513
- total += callbacks.size;
514
- }
515
- return total;
516
- }
517
- /**
518
- * Get total number of global subscriptions
519
- */
520
- getGlobalSubscriptionCount() {
521
- return this.globalSubscriptions.size;
522
- }
523
- };
524
- var globalEventSubscriptions = null;
525
- function getEventSubscriptions(logger) {
526
- if (!globalEventSubscriptions) {
527
- globalEventSubscriptions = new EventSubscriptions(logger);
528
- logger?.info("[EventSubscriptions] Created global singleton instance");
529
- }
530
- return globalEventSubscriptions;
531
- }
532
-
533
- // src/event-bus.ts
534
- var EventBus = class {
535
- // Expose subscriptions for direct access
536
- subscriptions;
537
- logger;
538
- constructor(logger) {
539
- this.logger = logger;
540
- this.subscriptions = getEventSubscriptions(logger?.child({ component: "EventSubscriptions" }));
541
- }
542
- /**
543
- * Publish event to subscribers
544
- * - Resource events: notifies BOTH resource-scoped AND global subscribers
545
- * - System events: notifies global subscribers only
546
- * @param event - Stored event (from @semiont/core)
547
- */
548
- async publish(event) {
549
- if (isSystemEvent(event.event)) {
550
- await this.subscriptions.notifyGlobalSubscribers(event);
551
- } else if (isResourceEvent(event.event)) {
552
- const rid = resourceId(event.event.resourceId);
553
- await this.subscriptions.notifySubscribers(rid, event);
554
- await this.subscriptions.notifyGlobalSubscribers(event);
555
- } else {
556
- this.logger?.warn("[EventBus] Event is neither resource nor system event", { eventType: event.event.type });
557
- }
558
- }
559
- /**
560
- * Subscribe to events for a specific resource
561
- * @param resourceId - Branded ResourceId (from @semiont/core)
562
- * @param callback - Event callback function
563
- * @returns EventSubscription with unsubscribe function
564
- */
565
- subscribe(resourceId, callback) {
566
- return this.subscriptions.subscribe(resourceId, callback);
567
- }
568
- /**
569
- * Subscribe to all system-level events
570
- * @param callback - Event callback function
571
- * @returns EventSubscription with unsubscribe function
572
- */
573
- subscribeGlobal(callback) {
574
- return this.subscriptions.subscribeGlobal(callback);
575
- }
576
- /**
577
- * Unsubscribe from resource events
578
- * @param resourceId - Branded ResourceId (from @semiont/core)
579
- * @param callback - Event callback function to remove
580
- */
581
- unsubscribe(resourceId, callback) {
582
- const callbacks = this.subscriptions.subscriptions.get(resourceId);
583
- if (callbacks) {
584
- callbacks.delete(callback);
585
- if (callbacks.size === 0) {
586
- this.subscriptions.subscriptions.delete(resourceId);
587
- }
588
- }
589
- }
590
- /**
591
- * Unsubscribe from global events
592
- * @param callback - Event callback function to remove
593
- */
594
- unsubscribeGlobal(callback) {
595
- this.subscriptions.globalSubscriptions.delete(callback);
596
- }
597
- /**
598
- * Get subscriber count for a resource
599
- * @param resourceId - Branded ResourceId (from @semiont/core)
600
- * @returns Number of active subscribers
601
- */
602
- getSubscriberCount(resourceId) {
603
- return this.subscriptions.getSubscriptionCount(resourceId);
604
- }
605
- /**
606
- * Get total number of active subscriptions across all resources
607
- */
608
- getTotalSubscriptions() {
609
- return this.subscriptions.getTotalSubscriptions();
610
- }
611
- /**
612
- * Get total number of global subscriptions
613
- */
614
- getGlobalSubscriptionCount() {
615
- return this.subscriptions.getGlobalSubscriptionCount();
616
- }
617
- };
618
418
  var ResourceNotFoundError = class extends Error {
619
419
  constructor(uri) {
620
420
  super(`No resource found for URI: ${uri}`);
@@ -704,14 +504,14 @@ var ViewMaterializer = class {
704
504
  /**
705
505
  * Update the storage-uri index in response to an event.
706
506
  *
707
- * Only resource.created (with storageUri), resource.moved, need index changes.
507
+ * Only yield:created (with storageUri), yield:moved, need index changes.
708
508
  * resource.archived / resource.unarchived do NOT modify the index.
709
509
  */
710
510
  async materializeStorageUriIndex(resourceId, event) {
711
511
  const projectionsDir = path.join(this.config.basePath, "projections");
712
- if (event.type === "resource.created" && event.payload.storageUri) {
512
+ if (event.type === "yield:created" && event.payload.storageUri) {
713
513
  await writeStorageUriEntry(projectionsDir, event.payload.storageUri, resourceId);
714
- } else if (event.type === "resource.moved") {
514
+ } else if (event.type === "yield:moved") {
715
515
  await removeStorageUriEntry(projectionsDir, event.payload.fromUri);
716
516
  await writeStorageUriEntry(projectionsDir, event.payload.toUri, resourceId);
717
517
  }
@@ -737,10 +537,10 @@ var ViewMaterializer = class {
737
537
  };
738
538
  events.sort((a, b) => a.metadata.sequenceNumber - b.metadata.sequenceNumber);
739
539
  for (const storedEvent of events) {
740
- this.applyEventToResource(resource, storedEvent.event);
741
- this.applyEventToAnnotations(annotations, storedEvent.event);
540
+ this.applyEventToResource(resource, storedEvent);
541
+ this.applyEventToAnnotations(annotations, storedEvent);
742
542
  annotations.version++;
743
- annotations.updatedAt = storedEvent.event.timestamp;
543
+ annotations.updatedAt = storedEvent.timestamp;
744
544
  }
745
545
  return { resource, annotations };
746
546
  }
@@ -749,7 +549,7 @@ var ViewMaterializer = class {
749
549
  */
750
550
  applyEventToResource(resource, event) {
751
551
  switch (event.type) {
752
- case "resource.created":
552
+ case "yield:created":
753
553
  resource.name = event.payload.name;
754
554
  resource.entityTypes = event.payload.entityTypes || [];
755
555
  resource.dateCreated = event.timestamp;
@@ -773,7 +573,7 @@ var ViewMaterializer = class {
773
573
  }
774
574
  resource.currentChecksum = event.payload.contentChecksum;
775
575
  break;
776
- case "resource.cloned":
576
+ case "yield:cloned":
777
577
  resource.name = event.payload.name;
778
578
  resource.entityTypes = event.payload.entityTypes || [];
779
579
  resource.dateCreated = event.timestamp;
@@ -791,21 +591,21 @@ var ViewMaterializer = class {
791
591
  });
792
592
  resource.representations = reps2;
793
593
  break;
794
- case "resource.updated":
594
+ case "yield:updated":
795
595
  resource.currentChecksum = event.payload.contentChecksum;
796
596
  resource.dateModified = event.timestamp;
797
597
  break;
798
- case "resource.moved":
598
+ case "yield:moved":
799
599
  resource.storageUri = event.payload.toUri;
800
600
  resource.dateModified = event.timestamp;
801
601
  break;
802
- case "resource.archived":
602
+ case "mark:archived":
803
603
  resource.archived = true;
804
604
  break;
805
- case "resource.unarchived":
605
+ case "mark:unarchived":
806
606
  resource.archived = false;
807
607
  break;
808
- case "representation.added": {
608
+ case "yield:representation-added": {
809
609
  const { representation } = event.payload;
810
610
  if (!resource.representations) {
811
611
  resource.representations = [];
@@ -817,7 +617,7 @@ var ViewMaterializer = class {
817
617
  }
818
618
  break;
819
619
  }
820
- case "representation.removed": {
620
+ case "yield:representation-removed": {
821
621
  const { checksum } = event.payload;
822
622
  if (resource.representations) {
823
623
  const repsArray = Array.isArray(resource.representations) ? resource.representations : [resource.representations];
@@ -825,13 +625,13 @@ var ViewMaterializer = class {
825
625
  }
826
626
  break;
827
627
  }
828
- case "entitytag.added":
628
+ case "mark:entity-tag-added":
829
629
  if (!resource.entityTypes) resource.entityTypes = [];
830
630
  if (!resource.entityTypes.includes(event.payload.entityType)) {
831
631
  resource.entityTypes.push(event.payload.entityType);
832
632
  }
833
633
  break;
834
- case "entitytag.removed":
634
+ case "mark:entity-tag-removed":
835
635
  if (resource.entityTypes) {
836
636
  resource.entityTypes = resource.entityTypes.filter(
837
637
  (t) => t !== event.payload.entityType
@@ -845,15 +645,15 @@ var ViewMaterializer = class {
845
645
  */
846
646
  applyEventToAnnotations(annotations, event) {
847
647
  switch (event.type) {
848
- case "annotation.added":
648
+ case "mark:added":
849
649
  annotations.annotations.push(event.payload.annotation);
850
650
  break;
851
- case "annotation.removed":
651
+ case "mark:removed":
852
652
  annotations.annotations = annotations.annotations.filter(
853
653
  (a) => a.id !== event.payload.annotationId
854
654
  );
855
655
  break;
856
- case "annotation.body.updated":
656
+ case "mark:body-updated":
857
657
  const annotation = annotations.annotations.find(
858
658
  (a) => a.id === event.payload.annotationId
859
659
  );
@@ -884,6 +684,44 @@ var ViewMaterializer = class {
884
684
  break;
885
685
  }
886
686
  }
687
+ /**
688
+ * Walk every event stream in the event log and materialize the corresponding
689
+ * view from scratch. Idempotent: existing view files are overwritten.
690
+ *
691
+ * Mirrors GraphDBConsumer.rebuildAll() and Smelter.rebuildAll() — this is the
692
+ * recovery path that makes the ephemeral stateDir safe to wipe. The live
693
+ * append path (EventStore.appendEvent → materializeIncremental /
694
+ * materializeEntityTypes) is unchanged and runs in addition.
695
+ */
696
+ async rebuildAll(eventLog) {
697
+ this.logger?.info("[ViewMaterializer] Rebuilding all materialized views from event log");
698
+ const SYSTEM_ID = "__system__";
699
+ const systemEvents = await eventLog.getEvents(SYSTEM_ID);
700
+ this.logger?.info("[ViewMaterializer] Replaying system events", { count: systemEvents.length });
701
+ for (const event of systemEvents) {
702
+ if (event.type === "mark:entity-type-added") {
703
+ await this.materializeEntityTypes(event.payload.entityType);
704
+ }
705
+ }
706
+ const allResourceIds = await eventLog.getAllResourceIds();
707
+ const resourceIds = allResourceIds.filter(
708
+ (rid) => rid !== "__system__"
709
+ );
710
+ this.logger?.info("[ViewMaterializer] Rebuilding resource views", { count: resourceIds.length });
711
+ for (const rid of resourceIds) {
712
+ const events = await eventLog.getEvents(rid);
713
+ if (events.length === 0) continue;
714
+ const view = this.materializeFromEvents(events, rid);
715
+ await this.viewStorage.save(rid, view);
716
+ for (const event of events) {
717
+ await this.materializeStorageUriIndex(rid, event);
718
+ }
719
+ }
720
+ this.logger?.info("[ViewMaterializer] Rebuild complete", {
721
+ systemEvents: systemEvents.length,
722
+ resources: resourceIds.length
723
+ });
724
+ }
887
725
  /**
888
726
  * Materialize entity types view - System-level view
889
727
  */
@@ -935,10 +773,19 @@ var ViewManager = class {
935
773
  * @param payload - Event payload
936
774
  */
937
775
  async materializeSystem(eventType, payload) {
938
- if (eventType === "entitytype.added") {
776
+ if (eventType === "mark:entity-type-added") {
939
777
  await this.materializer.materializeEntityTypes(payload.entityType);
940
778
  }
941
779
  }
780
+ /**
781
+ * Rebuild all materialized views from the event log on startup.
782
+ * Mirrors GraphDBConsumer.rebuildAll() — call this once during
783
+ * createKnowledgeBase before the HTTP server begins accepting requests.
784
+ * Idempotent: existing view files are overwritten.
785
+ */
786
+ async rebuildAll(eventLog) {
787
+ return this.materializer.rebuildAll(eventLog);
788
+ }
942
789
  /**
943
790
  * Get resource view (builds from events if needed)
944
791
  * @param resourceId - Branded ResourceId (from @semiont/core)
@@ -954,7 +801,6 @@ var ViewManager = class {
954
801
  var EventStore = class {
955
802
  // Focused components - each with single responsibility
956
803
  log;
957
- bus;
958
804
  views;
959
805
  viewStorage;
960
806
  coreEventBus;
@@ -962,7 +808,6 @@ var EventStore = class {
962
808
  this.viewStorage = viewStorage;
963
809
  this.coreEventBus = coreEventBus;
964
810
  this.log = new EventLog({ project }, logger?.child({ component: "EventLog" }));
965
- this.bus = new EventBus(logger?.child({ component: "EventBus" }));
966
811
  const viewConfig = {
967
812
  basePath: stateDir
968
813
  };
@@ -971,28 +816,31 @@ var EventStore = class {
971
816
  /**
972
817
  * Append an event to the store
973
818
  * Coordinates: persistence → view → notification
819
+ *
820
+ * @param options.correlationId - Optional id propagated from a command. Stored
821
+ * on the event's metadata so that subscribers (notably the events-stream
822
+ * route) can match command-result events back to the POST that initiated
823
+ * them. Pass through from your route handler when handling commands.
974
824
  */
975
- async appendEvent(event) {
825
+ async appendEvent(event, options) {
976
826
  const resourceId = event.resourceId || "__system__";
977
- const storedEvent = await this.log.append(event, resourceId);
827
+ const storedEvent = await this.log.append(event, resourceId, options);
978
828
  if (resourceId === "__system__") {
979
829
  await this.views.materializeSystem(
980
- storedEvent.event.type,
981
- storedEvent.event.payload
830
+ storedEvent.type,
831
+ storedEvent.payload
982
832
  );
983
833
  } else {
984
834
  await this.views.materializeResource(
985
835
  resourceId,
986
- storedEvent.event,
836
+ storedEvent,
987
837
  () => this.log.getEvents(resourceId)
988
838
  );
989
839
  }
990
- await this.bus.publish(storedEvent);
991
- if (this.coreEventBus && resourceId !== "__system__") {
840
+ this.coreEventBus.getDomainEvent(storedEvent.type).next(storedEvent);
841
+ if (resourceId !== "__system__") {
992
842
  const scopedBus = this.coreEventBus.scope(resourceId);
993
- const eventChannel = storedEvent.event.type.replace(/\./g, ":");
994
- scopedBus.get(eventChannel).next(storedEvent.event);
995
- scopedBus.get("make-meaning:event").next(storedEvent.event);
843
+ scopedBus.getDomainEvent(storedEvent.type).next(storedEvent);
996
844
  }
997
845
  return storedEvent;
998
846
  }
@@ -1115,16 +963,16 @@ var EventQuery = class {
1115
963
  const allEvents = await this.eventStorage.getAllEvents(query.resourceId);
1116
964
  let results = allEvents;
1117
965
  if (query.userId) {
1118
- results = results.filter((e) => e.event.userId === query.userId);
966
+ results = results.filter((e) => e.userId === query.userId);
1119
967
  }
1120
968
  if (query.eventTypes && query.eventTypes.length > 0) {
1121
- results = results.filter((e) => query.eventTypes.includes(e.event.type));
969
+ results = results.filter((e) => query.eventTypes.includes(e.type));
1122
970
  }
1123
971
  if (query.fromTimestamp) {
1124
- results = results.filter((e) => e.event.timestamp >= query.fromTimestamp);
972
+ results = results.filter((e) => e.timestamp >= query.fromTimestamp);
1125
973
  }
1126
974
  if (query.toTimestamp) {
1127
- results = results.filter((e) => e.event.timestamp <= query.toTimestamp);
975
+ results = results.filter((e) => e.timestamp <= query.toTimestamp);
1128
976
  }
1129
977
  if (query.fromSequence) {
1130
978
  results = results.filter((e) => e.metadata.sequenceNumber >= query.fromSequence);
@@ -1178,6 +1026,10 @@ var EventQuery = class {
1178
1026
  };
1179
1027
 
1180
1028
  // src/validation/event-validator.ts
1029
+ function extractPersistedEvent(stored) {
1030
+ const { metadata, signature, ...event } = stored;
1031
+ return event;
1032
+ }
1181
1033
  var EventValidator = class {
1182
1034
  /**
1183
1035
  * Validate event chain integrity for a resource's events
@@ -1194,7 +1046,7 @@ var EventValidator = class {
1194
1046
  `Event chain broken at sequence ${curr.metadata.sequenceNumber}: prevEventHash=${curr.metadata.prevEventHash} but previous checksum=${prev.metadata.checksum}`
1195
1047
  );
1196
1048
  }
1197
- const calculated = sha256(curr.event);
1049
+ const calculated = sha256(extractPersistedEvent(curr));
1198
1050
  if (calculated !== curr.metadata.checksum) {
1199
1051
  errors.push(
1200
1052
  `Checksum mismatch at sequence ${curr.metadata.sequenceNumber}: calculated=${calculated} but stored=${curr.metadata.checksum}`
@@ -1211,7 +1063,7 @@ var EventValidator = class {
1211
1063
  * Useful for validating events before writing them
1212
1064
  */
1213
1065
  validateEventChecksum(event) {
1214
- const calculated = sha256(event.event);
1066
+ const calculated = sha256(extractPersistedEvent(event));
1215
1067
  return calculated === event.metadata.checksum;
1216
1068
  }
1217
1069
  /**
@@ -1229,6 +1081,6 @@ function generateAnnotationId() {
1229
1081
  return nanoid(21);
1230
1082
  }
1231
1083
 
1232
- export { EventBus, EventLog, EventQuery, EventStorage, EventStore, EventSubscriptions, EventValidator, FilesystemViewStorage, ResourceNotFoundError, ViewManager, ViewMaterializer, createEventStore, generateAnnotationId, getEventSubscriptions, getShardPath, jumpConsistentHash, removeStorageUriEntry, resolveStorageUri, sha256, writeStorageUriEntry };
1084
+ export { EventLog, EventQuery, EventStorage, EventStore, EventValidator, FilesystemViewStorage, ResourceNotFoundError, ViewManager, ViewMaterializer, createEventStore, generateAnnotationId, getShardPath, jumpConsistentHash, removeStorageUriEntry, resolveStorageUri, sha256, writeStorageUriEntry };
1233
1085
  //# sourceMappingURL=index.js.map
1234
1086
  //# sourceMappingURL=index.js.map