@semiont/event-sourcing 0.5.2 → 0.5.4

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
@@ -399,6 +399,36 @@ var EventLog = class {
399
399
  });
400
400
  }
401
401
  };
402
+
403
+ // src/views/projection-reducers.ts
404
+ function applyEntityTypeAdded(current, add) {
405
+ const set = new Set(current);
406
+ set.add(add);
407
+ return Array.from(set).sort((a, b) => a.localeCompare(b));
408
+ }
409
+ function applyTagSchemaAdded(current, add) {
410
+ const existingIdx = current.findIndex((s) => s.id === add.id);
411
+ let warning;
412
+ let next;
413
+ if (existingIdx >= 0) {
414
+ const existing = current[existingIdx];
415
+ if (!sameSchema(existing, add)) {
416
+ warning = {
417
+ schemaId: add.id,
418
+ message: `tag schema "${add.id}" overwritten \u2014 definition changed`
419
+ };
420
+ }
421
+ next = current.slice();
422
+ next[existingIdx] = add;
423
+ } else {
424
+ next = [...current, add];
425
+ }
426
+ next.sort((a, b) => a.id.localeCompare(b.id));
427
+ return warning ? { next, warning } : { next };
428
+ }
429
+ function sameSchema(a, b) {
430
+ return JSON.stringify(a) === JSON.stringify(b);
431
+ }
402
432
  var ResourceNotFoundError = class extends Error {
403
433
  constructor(uri) {
404
434
  super(`No resource found for URI: ${uri}`);
@@ -510,8 +540,7 @@ var ViewMaterializer = class {
510
540
  name: "",
511
541
  representations: [],
512
542
  archived: false,
513
- entityTypes: [],
514
- creationMethod: "api"
543
+ entityTypes: []
515
544
  };
516
545
  const annotations = {
517
546
  resourceId,
@@ -537,7 +566,6 @@ var ViewMaterializer = class {
537
566
  resource.name = event.payload.name;
538
567
  resource.entityTypes = event.payload.entityTypes || [];
539
568
  resource.dateCreated = event.timestamp;
540
- resource.creationMethod = event.payload.creationMethod || "api";
541
569
  resource.wasAttributedTo = didToAgent(event.userId);
542
570
  if (!resource.representations) resource.representations = [];
543
571
  const reps = Array.isArray(resource.representations) ? resource.representations : [resource.representations];
@@ -561,7 +589,6 @@ var ViewMaterializer = class {
561
589
  resource.name = event.payload.name;
562
590
  resource.entityTypes = event.payload.entityTypes || [];
563
591
  resource.dateCreated = event.timestamp;
564
- resource.creationMethod = "clone";
565
592
  resource.sourceResourceId = event.payload.parentResourceId;
566
593
  resource.wasAttributedTo = didToAgent(event.userId);
567
594
  if (!resource.representations) resource.representations = [];
@@ -675,7 +702,8 @@ var ViewMaterializer = class {
675
702
  * Mirrors GraphDBConsumer.rebuildAll() and Smelter.rebuildAll() — this is the
676
703
  * recovery path that makes the ephemeral stateDir safe to wipe. The live
677
704
  * append path (EventStore.appendEvent → materializeIncremental /
678
- * materializeEntityTypes) is unchanged and runs in addition.
705
+ * materializeEntityTypes / materializeTagSchemas) is unchanged and runs in
706
+ * addition.
679
707
  */
680
708
  async rebuildAll(eventLog) {
681
709
  this.logger?.info("[ViewMaterializer] Rebuilding all materialized views from event log");
@@ -685,6 +713,9 @@ var ViewMaterializer = class {
685
713
  for (const event of systemEvents) {
686
714
  if (event.type === "frame:entity-type-added") {
687
715
  await this.materializeEntityTypes(event.payload.entityType);
716
+ } else if (event.type === "frame:tag-schema-added") {
717
+ const payload = event.payload;
718
+ await this.materializeTagSchemas(payload.schema);
688
719
  }
689
720
  }
690
721
  const allResourceIds = await eventLog.getAllResourceIds();
@@ -717,7 +748,11 @@ var ViewMaterializer = class {
717
748
  });
718
749
  }
719
750
  /**
720
- * Materialize entity types view - System-level view
751
+ * Materialize entity types view System-level view.
752
+ *
753
+ * I/O shell around the pure {@link applyEntityTypeAdded} reducer:
754
+ * read JSON file → reduce → write JSON file. The reducer owns the
755
+ * dedup + sort semantics; the shell owns the disk I/O.
721
756
  */
722
757
  async materializeEntityTypes(entityType) {
723
758
  const entityTypesPath = path.join(
@@ -733,12 +768,44 @@ var ViewMaterializer = class {
733
768
  } catch (error) {
734
769
  if (error.code !== "ENOENT") throw error;
735
770
  }
736
- const entityTypeSet = new Set(view.entityTypes);
737
- entityTypeSet.add(entityType);
738
- view.entityTypes = Array.from(entityTypeSet).sort();
771
+ view.entityTypes = applyEntityTypeAdded(view.entityTypes, entityType);
739
772
  await promises.mkdir(path.dirname(entityTypesPath), { recursive: true });
740
773
  await promises.writeFile(entityTypesPath, JSON.stringify(view, null, 2));
741
774
  }
775
+ /**
776
+ * Materialize tag schemas view — System-level view.
777
+ *
778
+ * I/O shell around the pure {@link applyTagSchemaAdded} reducer.
779
+ * The reducer owns the most-recent-wins semantics + the
780
+ * differing-content-overwrite-warning; the shell forwards the
781
+ * warning (when present) to this materializer's logger and writes
782
+ * the resulting state to disk.
783
+ */
784
+ async materializeTagSchemas(schema) {
785
+ const tagSchemasPath = path.join(
786
+ this.config.basePath,
787
+ "projections",
788
+ "__system__",
789
+ "tagschemas.json"
790
+ );
791
+ let view = { tagSchemas: [] };
792
+ try {
793
+ const content = await promises.readFile(tagSchemasPath, "utf-8");
794
+ view = JSON.parse(content);
795
+ } catch (error) {
796
+ if (error.code !== "ENOENT") throw error;
797
+ }
798
+ const result = applyTagSchemaAdded(view.tagSchemas, schema);
799
+ if (result.warning) {
800
+ this.logger?.warn("[ViewMaterializer] Tag schema overwritten", {
801
+ schemaId: result.warning.schemaId,
802
+ message: result.warning.message
803
+ });
804
+ }
805
+ view.tagSchemas = result.next;
806
+ await promises.mkdir(path.dirname(tagSchemasPath), { recursive: true });
807
+ await promises.writeFile(tagSchemasPath, JSON.stringify(view, null, 2));
808
+ }
742
809
  };
743
810
 
744
811
  // src/view-manager.ts
@@ -776,13 +843,15 @@ var ViewManager = class _ViewManager {
776
843
  );
777
844
  }
778
845
  /**
779
- * Update system-level view (currently only entity types).
846
+ * Update system-level view (entity types + tag schemas today).
780
847
  * Serialized through a shared chain — see class doc.
781
848
  */
782
849
  async materializeSystem(eventType, payload) {
783
850
  await serializePerKey(_ViewManager.SYSTEM_KEY, this.systemChains, async () => {
784
851
  if (eventType === "frame:entity-type-added") {
785
852
  await this.materializer.materializeEntityTypes(payload.entityType);
853
+ } else if (eventType === "frame:tag-schema-added") {
854
+ await this.materializer.materializeTagSchemas(payload.schema);
786
855
  }
787
856
  });
788
857
  }
@@ -1047,6 +1116,6 @@ function generateAnnotationId() {
1047
1116
  return nanoid(21);
1048
1117
  }
1049
1118
 
1050
- export { EventLog, EventQuery, EventStorage, EventStore, FilesystemViewStorage, ResourceNotFoundError, ViewManager, ViewMaterializer, createEventStore, generateAnnotationId, getShardPath, jumpConsistentHash, removeStorageUriEntry, resolveStorageUri, sha256, writeStorageUriEntry };
1119
+ export { EventLog, EventQuery, EventStorage, EventStore, FilesystemViewStorage, ResourceNotFoundError, ViewManager, ViewMaterializer, applyEntityTypeAdded, applyTagSchemaAdded, createEventStore, generateAnnotationId, getShardPath, jumpConsistentHash, removeStorageUriEntry, resolveStorageUri, sha256, writeStorageUriEntry };
1051
1120
  //# sourceMappingURL=index.js.map
1052
1121
  //# sourceMappingURL=index.js.map