@semiont/event-sourcing 0.4.21 → 0.5.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/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { ResourceId, components, ResourceAnnotations, Logger, EventInput, StoredEvent, EventQuery as EventQuery$1, PersistedEvent, EventBus } from '@semiont/core';
1
+ import { ResourceId, ResourceDescriptor, ResourceAnnotations, Logger, EventInput, StoredEvent, EventQuery as EventQuery$1, PersistedEvent, EventBus } from '@semiont/core';
2
2
  import { SemiontProject } from '@semiont/core/node';
3
3
 
4
4
  /**
@@ -10,7 +10,6 @@ import { SemiontProject } from '@semiont/core/node';
10
10
  * Stores both ResourceDescriptor metadata and ResourceAnnotations, but keeps them logically separate
11
11
  */
12
12
 
13
- type ResourceDescriptor = components['schemas']['ResourceDescriptor'];
14
13
  interface ResourceView {
15
14
  resource: ResourceDescriptor;
16
15
  annotations: ResourceAnnotations;
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/storage/shard-utils.ts","../src/storage/event-storage.ts","../src/event-log.ts","../src/storage/storage-uri-index.ts","../src/views/view-materializer.ts","../src/view-manager.ts","../src/event-store.ts","../src/storage/view-storage.ts","../src/event-store-factory.ts","../src/query/event-query.ts","../src/identifier-utils.ts"],"names":["fs","uuidv4","resourceId","makeResourceId","path","path3","path4"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Sharding Utilities\n *\n * Shared utilities for consistent sharding across all storage layers\n * Uses Google's Jump Consistent Hash algorithm for even distribution\n */\n\nimport { createHash } from 'crypto';\n\n/**\n * TEMPORARY: Simple modulo-based hash sharding\n *\n * ⚠️ TODO: Replace with proper Jump Consistent Hash implementation\n *\n * This is a TEMPORARY implementation using simple modulo. It works and provides\n * good distribution, but does NOT provide the minimal reshuffling property of\n * Jump Consistent Hash when changing bucket counts.\n *\n * The proper implementation should use Google's Jump Consistent Hash algorithm:\n * Reference: \"A Fast, Minimal Memory, Consistent Hash Algorithm\" by Lamping & Veach (2014)\n * https://arxiv.org/abs/1406.2294\n *\n * Working implementations exist in npm packages like:\n * - jumphash (https://www.npmjs.com/package/jumphash)\n * - jump-gouache (https://github.com/bhoudu/jump-gouache)\n *\n * The algorithm requires proper 64-bit integer handling with BigInt to avoid\n * precision loss in JavaScript. The previous attempt failed due to incorrect\n * BigInt arithmetic in the while loop condition.\n *\n * Until replaced, this modulo approach will cause ALL data to be reshuffled\n * if bucket count changes, rather than the optimal O(n/k) reshuffling that\n * Jump Consistent Hash provides.\n *\n * @param key - The key to hash (typically a resource ID)\n * @param numBuckets - Number of shards/buckets (default: 65536 for 4-hex sharding)\n * @returns Shard number (0 to numBuckets-1)\n */\nexport function jumpConsistentHash(key: string, numBuckets: number = 65536): number {\n const hash = hashToUint32(key);\n return hash % numBuckets;\n}\n\n/**\n * Hash string to 32-bit unsigned integer\n */\nfunction hashToUint32(str: string): number {\n let hash = 0;\n for (let i = 0; i < str.length; i++) {\n hash = ((hash << 5) - hash) + str.charCodeAt(i);\n hash = hash & 0xFFFFFFFF;\n }\n return Math.abs(hash);\n}\n\n/**\n * Convert shard number to 4-hex directory path (ab/cd)\n *\n * @param shardId - Shard number (0-65535)\n * @returns Path segments like ['ab', 'cd']\n */\nexport function shardIdToPath(shardId: number): [string, string] {\n if (shardId < 0 || shardId >= 65536) {\n throw new Error(`Invalid shard ID: ${shardId}. Must be 0-65535 for 4-hex sharding.`);\n }\n\n const shardHex = shardId.toString(16).padStart(4, '0');\n const ab = shardHex.substring(0, 2);\n const cd = shardHex.substring(2, 4);\n\n return [ab, cd];\n}\n\n/**\n * Get 4-hex shard path for a key\n *\n * @param key - The key to hash (typically a resource ID)\n * @param numBuckets - Number of shards (default: 65536)\n * @returns Path segments like ['ab', 'cd']\n */\nexport function getShardPath(key: string, numBuckets: number = 65536): [string, string] {\n const shardId = jumpConsistentHash(key, numBuckets);\n return shardIdToPath(shardId);\n}\n\n/**\n * Calculate SHA-256 hash of data\n */\nexport function sha256(data: string | object): string {\n const content = typeof data === 'string' ? data : JSON.stringify(data);\n return createHash('sha256').update(content).digest('hex');\n}","/**\n * Event Storage - Physical Storage Layer\n *\n * Handles file I/O operations for event storage:\n * - JSONL file writing/reading\n * - 4-hex sharding (65,536 shards)\n * - File rotation\n * - Event stream initialization\n *\n * @see docs/EVENT-STORE.md#eventstorage for architecture details\n */\n\nimport { promises as fs } from 'fs';\nimport { execFileSync } from 'child_process';\nimport * as path from 'path';\nimport { createReadStream } from 'fs';\nimport * as readline from 'readline';\nimport { v4 as uuidv4 } from 'uuid';\nimport type { StoredEvent, PersistedEvent, EventMetadata, EventInput, ResourceId, Logger } from '@semiont/core';\nimport { resourceId as makeResourceId } from '@semiont/core';\nimport type { SemiontProject } from '@semiont/core/node';\nimport { jumpConsistentHash } from './shard-utils';\n\nexport interface EventStorageConfig {\n maxEventsPerFile?: number; // File rotation threshold (default: 10000)\n enableSharding?: boolean; // Enable 4-hex sharding (default: true)\n numShards?: number; // Number of shards (default: 65536)\n enableCompression?: boolean; // Gzip rotated files (default: true)\n}\n\n/**\n * EventStorage handles physical storage of events\n * Owns: file I/O, sharding, AND sequence/hash tracking\n */\nexport class EventStorage {\n private config: Required<EventStorageConfig>;\n private project: SemiontProject;\n private logger?: Logger;\n\n // Per-resource sequence tracking: resourceId -> sequence number\n private resourceSequences: Map<string, number> = new Map();\n // Per-resource current file cache: avoids fs.readdir() + countEventsInFile() on every append\n private currentFiles: Map<string, { path: string; eventCount: number }> = new Map();\n\n constructor(project: SemiontProject, config?: EventStorageConfig, logger?: Logger) {\n this.project = project;\n this.logger = logger;\n this.config = {\n maxEventsPerFile: config?.maxEventsPerFile || 10000,\n enableSharding: config?.enableSharding ?? true,\n numShards: config?.numShards || 65536,\n enableCompression: config?.enableCompression ?? true,\n };\n }\n\n /**\n * Calculate shard path for a resource ID\n * Uses jump consistent hash for uniform distribution\n * Special case: __system__ events bypass sharding\n */\n getShardPath(resourceId: ResourceId): string {\n // System events don't get sharded\n if (resourceId === '__system__' || !this.config.enableSharding) {\n return '';\n }\n\n // Jump consistent hash for uniform shard distribution\n const shardIndex = jumpConsistentHash(resourceId, this.config.numShards);\n\n // Convert to 4-hex format (e.g., 0000, 0001, ..., ffff)\n const hex = shardIndex.toString(16).padStart(4, '0');\n const [ab, cd] = [hex.substring(0, 2), hex.substring(2, 4)];\n\n return path.join(ab, cd);\n }\n\n /**\n * Get full path to resource's event directory\n */\n getResourcePath(resourceId: ResourceId): string {\n const shardPath = this.getShardPath(resourceId);\n return path.join(this.project.eventsDir, shardPath, resourceId);\n }\n\n /**\n * Initialize directory structure for a resource's event stream\n * Also loads sequence number and last hash if stream exists\n */\n async initializeResourceStream(resourceId: ResourceId): Promise<void> {\n const docPath = this.getResourcePath(resourceId);\n\n // Check if already initialized\n let exists = false;\n try {\n await fs.access(docPath);\n exists = true;\n } catch {\n // Doesn't exist, create it\n }\n\n if (!exists) {\n // Create directory structure\n await fs.mkdir(docPath, { recursive: true });\n\n // Create initial empty events file\n const filename = this.createEventFilename(1);\n const filePath = path.join(docPath, filename);\n await fs.writeFile(filePath, '', 'utf-8');\n\n // Stage the new event stream directory in git\n if (this.project.gitSync) {\n execFileSync('git', ['add', docPath], { cwd: this.project.root });\n }\n\n // Initialize sequence number\n this.resourceSequences.set(resourceId, 0);\n\n this.logger?.info('[EventStorage] Initialized event stream', { resourceId, path: docPath });\n } else {\n // Load existing sequence number from the last file\n const files = await this.getEventFiles(resourceId);\n if (files.length > 0) {\n const lastFile = files[files.length - 1];\n if (lastFile) {\n const lastEvent = await this.getLastEvent(resourceId, lastFile);\n if (lastEvent) {\n this.resourceSequences.set(resourceId, lastEvent.metadata.sequenceNumber);\n }\n }\n } else {\n this.resourceSequences.set(resourceId, 0);\n }\n }\n }\n\n /**\n * Append an event - handles EVERYTHING for event creation\n * Creates ID, timestamp, metadata, sequence tracking, and writes to disk.\n *\n * Integrity is provided by git at the commit level (when gitSync is enabled),\n * not by per-event chaining metadata. Per-event signatures (the unused\n * `EventSignature` field on StoredEvent) are the planned mechanism for\n * cross-KB authorship binding when federation becomes a real requirement.\n *\n * @param options.correlationId - Optional id propagated from a command. Stored\n * on the event's metadata so subscribers (notably the events-stream → frontend\n * path) can match command-result events back to the POST that initiated them.\n */\n async appendEvent(\n event: EventInput,\n resourceId: ResourceId,\n options?: { correlationId?: string },\n ): Promise<StoredEvent> {\n // Ensure resource stream is initialized\n if (this.getSequenceNumber(resourceId) === 0) {\n await this.initializeResourceStream(resourceId);\n }\n\n // Create complete event with ID and timestamp\n const completeEvent: PersistedEvent = {\n ...event,\n id: uuidv4(),\n timestamp: new Date().toISOString(),\n } as PersistedEvent;\n\n const sequenceNumber = this.getNextSequenceNumber(resourceId);\n\n const metadata: EventMetadata = {\n sequenceNumber,\n streamPosition: 0, // Will be set during write\n ...(options?.correlationId !== undefined && { correlationId: options.correlationId }),\n };\n\n const storedEvent: StoredEvent = {\n ...completeEvent,\n metadata,\n };\n\n await this.writeEvent(storedEvent, resourceId);\n\n return storedEvent;\n }\n\n /**\n * Write an event to storage (append to JSONL)\n * Internal method - use appendEvent() instead\n *\n * Uses currentFiles cache to avoid fs.readdir() + countEventsInFile() on every append.\n * Cache is populated on first append (cold start) and updated on rotation.\n */\n private async writeEvent(event: StoredEvent, resourceId: ResourceId): Promise<void> {\n const docPath = this.getResourcePath(resourceId);\n let current = this.currentFiles.get(resourceId);\n\n if (!current) {\n // Cold start: read from disk once\n const files = await this.getEventFiles(resourceId);\n const lastFile = files[files.length - 1];\n if (lastFile) {\n const count = await this.countEventsInFile(resourceId, lastFile);\n current = { path: lastFile, eventCount: count };\n } else {\n const newFile = await this.createNewEventFile(resourceId);\n current = { path: newFile, eventCount: 0 };\n }\n this.currentFiles.set(resourceId, current);\n }\n\n if (current.eventCount >= this.config.maxEventsPerFile) {\n const newFile = await this.createNewEventFile(resourceId);\n current = { path: newFile, eventCount: 0 };\n this.currentFiles.set(resourceId, current);\n }\n\n // Append event to file (JSONL format)\n const targetPath = path.join(docPath, current.path);\n const eventLine = JSON.stringify(event) + '\\n';\n await fs.appendFile(targetPath, eventLine, 'utf-8');\n current.eventCount++;\n\n // Stage the event log file in git index if configured\n if (this.project.gitSync) {\n execFileSync('git', ['add', targetPath], { cwd: this.project.root });\n }\n }\n\n /**\n * Count events in a specific file\n */\n async countEventsInFile(resourceId: ResourceId, filename: string): Promise<number> {\n const docPath = this.getResourcePath(resourceId);\n const filePath = path.join(docPath, filename);\n\n try {\n const content = await fs.readFile(filePath, 'utf-8');\n const lines = content.trim().split('\\n').filter(line => line.trim() !== '');\n return lines.length;\n } catch (error: any) {\n if (error.code === 'ENOENT') {\n return 0;\n }\n throw error;\n }\n }\n\n /**\n * Read all events from a specific file\n */\n async readEventsFromFile(resourceId: ResourceId, filename: string): Promise<StoredEvent[]> {\n const docPath = this.getResourcePath(resourceId);\n const filePath = path.join(docPath, filename);\n\n const events: StoredEvent[] = [];\n\n try {\n const fileStream = createReadStream(filePath, { encoding: 'utf-8' });\n const rl = readline.createInterface({\n input: fileStream,\n crlfDelay: Infinity,\n });\n\n for await (const line of rl) {\n const trimmed = line.trim();\n if (trimmed === '') continue;\n\n try {\n const parsed = JSON.parse(trimmed);\n // Handle both flat (new) and nested (old) JSONL formats\n if ('event' in parsed && 'metadata' in parsed && !('type' in parsed)) {\n // Old nested format: { event: {...}, metadata: {...} } → flatten\n events.push({ ...parsed.event, metadata: parsed.metadata, signature: parsed.signature } as StoredEvent);\n } else {\n events.push(parsed as StoredEvent);\n }\n } catch (parseError) {\n this.logger?.error('[EventStorage] Failed to parse event', { filePath, error: parseError });\n // Skip malformed lines\n }\n }\n } catch (error: any) {\n if (error.code === 'ENOENT') {\n return []; // File doesn't exist\n }\n throw error;\n }\n\n return events;\n }\n\n /**\n * Get list of event files for a resource (sorted by sequence)\n */\n async getEventFiles(resourceId: ResourceId): Promise<string[]> {\n const docPath = this.getResourcePath(makeResourceId(resourceId));\n\n try {\n const files = await fs.readdir(docPath);\n\n // Filter to .jsonl files and sort by sequence number\n const eventFiles = files\n .filter(f => f.startsWith('events-') && f.endsWith('.jsonl'))\n .sort((a, b) => {\n const seqA = parseInt(a.match(/events-(\\d+)\\.jsonl/)?.[1] || '0');\n const seqB = parseInt(b.match(/events-(\\d+)\\.jsonl/)?.[1] || '0');\n return seqA - seqB;\n });\n\n return eventFiles;\n } catch (error: any) {\n if (error.code === 'ENOENT') {\n return []; // Directory doesn't exist\n }\n throw error;\n }\n }\n\n /**\n * Create a new event file for rotation\n */\n async createNewEventFile(resourceId: ResourceId): Promise<string> {\n const files = await this.getEventFiles(resourceId);\n\n // Determine next sequence number\n const lastFile = files[files.length - 1];\n const lastSeq = lastFile ? parseInt(lastFile.match(/events-(\\d+)\\.jsonl/)?.[1] || '1') : 1;\n const newSeq = lastSeq + 1;\n\n // Create new file\n const filename = this.createEventFilename(newSeq);\n const docPath = this.getResourcePath(resourceId);\n const filePath = path.join(docPath, filename);\n\n await fs.writeFile(filePath, '', 'utf-8');\n\n this.logger?.info('[EventStorage] Created new event file', { filename, resourceId });\n\n return filename;\n }\n\n /**\n * Get the last event from a specific file\n */\n async getLastEvent(resourceId: ResourceId, filename: string): Promise<StoredEvent | null> {\n const events = await this.readEventsFromFile(resourceId, filename);\n const lastEvent = events.length > 0 ? events[events.length - 1] : undefined;\n return lastEvent ?? null;\n }\n\n /**\n * Get all events for a resource across all files\n */\n async getAllEvents(resourceId: ResourceId): Promise<StoredEvent[]> {\n const files = await this.getEventFiles(resourceId);\n const allEvents: StoredEvent[] = [];\n\n for (const file of files) {\n const events = await this.readEventsFromFile(resourceId, file);\n allEvents.push(...events);\n }\n\n return allEvents;\n }\n\n /**\n * Get all resource IDs by scanning shard directories\n */\n async getAllResourceIds(): Promise<ResourceId[]> {\n const eventsDir = this.project.eventsDir;\n const resourceIds: ResourceId[] = [];\n\n try {\n await fs.access(eventsDir);\n } catch {\n return []; // No events directory yet\n }\n\n // Recursively scan shard directories\n const scanDir = async (dir: string) => {\n const entries = await fs.readdir(dir, { withFileTypes: true });\n\n for (const entry of entries) {\n const fullPath = path.join(dir, entry.name);\n\n if (entry.isDirectory()) {\n // Check if this looks like a resource ID (not a shard directory)\n // Shard directories are 2-char hex (00-ff), resource IDs are longer\n if (entry.name.length > 2) {\n resourceIds.push(makeResourceId(entry.name));\n } else {\n // Recurse into shard directory\n await scanDir(fullPath);\n }\n }\n }\n };\n\n await scanDir(eventsDir);\n return resourceIds;\n }\n\n /**\n * Create filename for event file\n */\n private createEventFilename(sequenceNumber: number): string {\n return `events-${sequenceNumber.toString().padStart(6, '0')}.jsonl`;\n }\n\n // ============================================================\n // Sequence/Hash Tracking\n // ============================================================\n\n /**\n * Get current sequence number for a resource\n */\n getSequenceNumber(resourceId: ResourceId): number {\n return this.resourceSequences.get(resourceId) || 0;\n }\n\n /**\n * Increment and return next sequence number for a resource\n */\n getNextSequenceNumber(resourceId: ResourceId): number {\n const current = this.getSequenceNumber(resourceId);\n const next = current + 1;\n this.resourceSequences.set(resourceId, next);\n return next;\n }\n\n}\n","/**\n * EventLog - Event Persistence Layer\n *\n * Single Responsibility: Event persistence only\n * - Appends events to storage (JSONL files)\n * - Retrieves events by resource\n * - Queries events with filters\n *\n * Does NOT handle:\n * - Pub/sub notifications (see EventBus)\n * - View updates (see ViewManager)\n */\n\nimport { type ResourceId, type StoredEvent, type EventQuery, type EventInput, type Logger } from '@semiont/core';\nimport type { SemiontProject } from '@semiont/core/node';\nimport { EventStorage } from './storage/event-storage';\n\nexport interface EventLogConfig {\n project: SemiontProject;\n enableSharding?: boolean;\n maxEventsPerFile?: number;\n}\n\nexport class EventLog {\n // Expose storage for EventQuery (read operations)\n readonly storage: EventStorage;\n\n constructor(config: EventLogConfig, logger?: Logger) {\n this.storage = new EventStorage(config.project, {\n enableSharding: config.enableSharding,\n maxEventsPerFile: config.maxEventsPerFile,\n }, logger?.child({ component: 'EventStorage' }));\n }\n\n /**\n * Append event to log\n * @param event - Resource event (from @semiont/core)\n * @param resourceId - Branded ResourceId (from @semiont/core)\n * @param options.correlationId - Optional command correlation id (stored on metadata)\n * @returns Stored event with metadata (sequence number, timestamp, checksum)\n */\n async append(\n event: EventInput,\n resourceId: ResourceId,\n options?: { correlationId?: string },\n ): Promise<StoredEvent> {\n return this.storage.appendEvent(event, resourceId, options);\n }\n\n /**\n * Get all events for a resource\n * @param resourceId - Branded ResourceId (from @semiont/core)\n */\n async getEvents(resourceId: ResourceId): Promise<StoredEvent[]> {\n return this.storage.getAllEvents(resourceId);\n }\n\n /**\n * Get all resource IDs\n * @returns Array of branded ResourceId types\n */\n async getAllResourceIds(): Promise<ResourceId[]> {\n return this.storage.getAllResourceIds();\n }\n\n /**\n * Query events with filter\n * @param resourceId - Branded ResourceId (from @semiont/core)\n * @param filter - Optional event filter\n */\n async queryEvents(resourceId: ResourceId, filter?: EventQuery): Promise<StoredEvent[]> {\n const events = await this.storage.getAllEvents(resourceId);\n if (!filter) return events;\n\n return events.filter(e => {\n if (filter.eventTypes && !filter.eventTypes.includes(e.type as any)) return false;\n if (filter.fromSequence && e.metadata.sequenceNumber < filter.fromSequence) return false;\n if (filter.fromTimestamp && e.timestamp < filter.fromTimestamp) return false;\n if (filter.toTimestamp && e.timestamp > filter.toTimestamp) return false;\n if (filter.userId && e.userId !== filter.userId) return false;\n return true;\n });\n }\n}\n","/**\n * Storage URI Index\n *\n * Projection that maps file:// URIs → resourceIds.\n * Sharded at:\n * {projectionsDir}/storage-uri/{ab}/{cd}/{uri-hash}.json\n *\n * where {ab}/{cd} comes from jumpConsistentHash(uri) and\n * {uri-hash} is the SHA-256 of the URI string.\n *\n * Each file contains: { uri: string; resourceId: string }\n *\n * This index is maintained by ViewMaterializer (the single owner).\n * It is never modified by Stower or other actors.\n *\n * Archive/unarchive do NOT remove entries from this index.\n * Archived resources are marked in the ResourceView (archived: true)\n * but remain findable by URI.\n */\n\nimport { promises as fs } from 'fs';\nimport path from 'path';\nimport { getShardPath, sha256 } from './shard-utils';\n\nexport interface StorageUriEntry {\n uri: string;\n resourceId: string;\n}\n\n/**\n * Thrown when a URI is not found in the storage-uri index.\n */\nexport class ResourceNotFoundError extends Error {\n constructor(readonly uri: string) {\n super(`No resource found for URI: ${uri}`);\n this.name = 'ResourceNotFoundError';\n }\n}\n\n/**\n * Resolve a file:// URI to a resourceId using the storage-uri index.\n *\n * @param projectionsDir - Path to the projections directory\n * @param uri - file:// URI (e.g. \"file://docs/overview.md\")\n * @returns resourceId\n * @throws ResourceNotFoundError if URI is not in the index\n */\nexport async function resolveStorageUri(\n projectionsDir: string,\n uri: string,\n): Promise<string> {\n const entryPath = uriIndexPath(projectionsDir, uri);\n try {\n const raw = await fs.readFile(entryPath, 'utf-8');\n const entry: StorageUriEntry = JSON.parse(raw);\n return entry.resourceId;\n } catch (error: any) {\n if (error.code === 'ENOENT') {\n throw new ResourceNotFoundError(uri);\n }\n throw error;\n }\n}\n\n/**\n * Write a URI → resourceId mapping to the index.\n *\n * Called by ViewMaterializer when handling resource.created, resource.moved.\n *\n * @param projectionsDir - Path to the projections directory\n * @param uri - file:// URI\n * @param resourceId - resourceId to map to\n */\nexport async function writeStorageUriEntry(\n projectionsDir: string,\n uri: string,\n resourceId: string,\n): Promise<void> {\n const entryPath = uriIndexPath(projectionsDir, uri);\n await fs.mkdir(path.dirname(entryPath), { recursive: true });\n const entry: StorageUriEntry = { uri, resourceId };\n await fs.writeFile(entryPath, JSON.stringify(entry, null, 2));\n}\n\n/**\n * Remove a URI entry from the index.\n *\n * Called by ViewMaterializer when handling resource.moved (old URI only).\n * NOT called on resource.archived — archived resources retain their index entry.\n *\n * @param projectionsDir - Path to the projections directory\n * @param uri - file:// URI to remove\n */\nexport async function removeStorageUriEntry(\n projectionsDir: string,\n uri: string,\n): Promise<void> {\n const entryPath = uriIndexPath(projectionsDir, uri);\n try {\n await fs.unlink(entryPath);\n } catch (error: any) {\n if (error.code !== 'ENOENT') {\n throw error;\n }\n }\n}\n\n/**\n * Compute the filesystem path for a URI index entry.\n */\nfunction uriIndexPath(projectionsDir: string, uri: string): string {\n const uriHash = sha256(uri);\n const [ab, cd] = getShardPath(uri);\n return path.join(projectionsDir, 'storage-uri', ab, cd, `${uriHash}.json`);\n}\n","/**\n * View Materializer - Materialized View Management\n *\n * Materializes resource views from events:\n * - Full view materialization from scratch\n * - Incremental view updates\n * - System-level views (entity types)\n *\n * @see docs/EVENT-STORE.md#viewmaterializer for architecture details\n */\n\nimport { promises as fs } from 'fs';\nimport * as path from 'path';\nimport { didToAgent } from '@semiont/core';\nimport type { components } from '@semiont/core';\n\ntype Representation = components['schemas']['Representation'];\ntype Annotation = components['schemas']['Annotation'];\ntype ResourceDescriptor = components['schemas']['ResourceDescriptor'];\n\nimport type {\n PersistedEvent,\n StoredEvent,\n ResourceAnnotations,\n ResourceId,\n Logger,\n} from '@semiont/core';\nimport { findBodyItem } from '@semiont/core';\nimport type { ViewStorage, ResourceView } from '../storage/view-storage';\nimport { writeStorageUriEntry, removeStorageUriEntry } from '../storage/storage-uri-index';\n\n/**\n * Minimal structural type for the event log dependency of `rebuildAll`.\n * Avoids importing the concrete EventLog class from a sibling directory and\n * keeps the materializer independent of the event-log implementation.\n */\nexport interface RebuildEventSource {\n getEvents(resourceId: ResourceId): Promise<StoredEvent[]>;\n getAllResourceIds(): Promise<ResourceId[]>;\n}\n\nexport interface ViewMaterializerConfig {\n basePath: string;\n}\n\n/**\n * ViewMaterializer builds and maintains materialized views from events\n */\nexport class ViewMaterializer {\n private logger?: Logger;\n\n constructor(\n private viewStorage: ViewStorage,\n private config: ViewMaterializerConfig,\n logger?: Logger\n ) {\n this.logger = logger;\n }\n\n /**\n * Materialize resource view from events\n * Loads existing view if cached, otherwise rebuilds from events\n */\n async materialize(events: StoredEvent[], resourceId: ResourceId): Promise<ResourceView | null> {\n // Try to load existing view\n const existing = await this.viewStorage.get(resourceId);\n if (existing) {\n return existing;\n }\n\n // No view exists - rebuild from events\n if (events.length === 0) return null;\n\n const view = this.materializeFromEvents(events, resourceId);\n\n // Save rebuilt view\n await this.viewStorage.save(resourceId, view);\n\n return view;\n }\n\n /**\n * Materialize view incrementally with a single event\n * Falls back to full rebuild if view doesn't exist\n */\n async materializeIncremental(\n resourceId: ResourceId,\n event: PersistedEvent,\n getAllEvents: () => Promise<StoredEvent[]>\n ): Promise<void> {\n this.logger?.info('[ViewMaterializer] Updating view for resource with event', { resourceId, eventType: event.type });\n\n // Try to load existing view\n let view = await this.viewStorage.get(resourceId);\n\n if (!view) {\n // No view exists - do full rebuild from all events\n this.logger?.info('[ViewMaterializer] No view found, rebuilding from scratch', { resourceId });\n const events = await getAllEvents();\n view = this.materializeFromEvents(events, resourceId);\n } else {\n // Apply single event incrementally to existing view\n this.logger?.info('[ViewMaterializer] Applying event incrementally to existing view', { resourceId, version: view.annotations.version });\n this.applyEventToResource(view.resource, event);\n this.applyEventToAnnotations(view.annotations, event);\n view.annotations.version++;\n view.annotations.updatedAt = event.timestamp;\n }\n\n // Save updated view\n await this.viewStorage.save(resourceId, view);\n this.logger?.info('[ViewMaterializer] View saved', { resourceId, version: view.annotations.version, annotationCount: view.annotations.annotations.length });\n\n // Update storage-uri index for URI-bearing events\n await this.materializeStorageUriIndex(resourceId, event);\n }\n\n /**\n * Update the storage-uri index in response to an event.\n *\n * Only yield:created (with storageUri), yield:moved, need index changes.\n * resource.archived / resource.unarchived do NOT modify the index.\n */\n private async materializeStorageUriIndex(resourceId: ResourceId, event: PersistedEvent): Promise<void> {\n const projectionsDir = path.join(this.config.basePath, 'projections');\n\n if (event.type === 'yield:created' && event.payload.storageUri) {\n await writeStorageUriEntry(projectionsDir, event.payload.storageUri, resourceId as string);\n } else if (event.type === 'yield:moved') {\n // Remove old URI, add new URI\n await removeStorageUriEntry(projectionsDir, event.payload.fromUri);\n await writeStorageUriEntry(projectionsDir, event.payload.toUri, resourceId as string);\n }\n }\n\n /**\n * Materialize view from event list (full rebuild)\n */\n private materializeFromEvents(events: StoredEvent[], resourceId: ResourceId): ResourceView {\n // Start with empty ResourceDescriptor state\n // @id uses bare resource ID; full URI is constructed at the API boundary\n const resource: ResourceDescriptor = {\n '@context': 'https://schema.org/',\n '@id': resourceId as string,\n name: '',\n representations: [],\n archived: false,\n entityTypes: [],\n creationMethod: 'api',\n };\n\n // Start with empty annotations\n const annotations: ResourceAnnotations = {\n resourceId,\n annotations: [],\n version: 0,\n updatedAt: '',\n };\n\n // Apply events in sequenceNumber order\n events.sort((a, b) => a.metadata.sequenceNumber - b.metadata.sequenceNumber);\n\n for (const storedEvent of events) {\n this.applyEventToResource(resource, storedEvent);\n this.applyEventToAnnotations(annotations, storedEvent);\n annotations.version++;\n annotations.updatedAt = storedEvent.timestamp;\n }\n\n return { resource, annotations };\n }\n\n /**\n * Apply an event to ResourceDescriptor state (metadata only)\n */\n private applyEventToResource(resource: ResourceDescriptor, event: PersistedEvent): void {\n switch (event.type) {\n case 'yield:created':\n resource.name = event.payload.name;\n resource.entityTypes = event.payload.entityTypes || [];\n resource.dateCreated = event.timestamp;\n resource.creationMethod = event.payload.creationMethod || 'api';\n resource.wasAttributedTo = didToAgent(event.userId);\n\n // Create representation from format and checksum\n if (!resource.representations) resource.representations = [];\n const reps = Array.isArray(resource.representations) ? resource.representations : [resource.representations];\n reps.push({\n mediaType: event.payload.format,\n checksum: event.payload.contentChecksum,\n byteSize: event.payload.contentByteSize,\n rel: 'original',\n language: event.payload.language,\n } as Representation);\n resource.representations = reps;\n\n // First-class fields\n resource.isDraft = event.payload.isDraft;\n if (event.payload.generatedFrom) resource.wasDerivedFrom = event.payload.generatedFrom.resourceId;\n if (event.payload.generator) resource.generator = event.payload.generator;\n\n // Working-tree URI and current checksum\n if (event.payload.storageUri) {\n resource.storageUri = event.payload.storageUri;\n }\n resource.currentChecksum = event.payload.contentChecksum;\n break;\n\n case 'yield:cloned':\n resource.name = event.payload.name;\n resource.entityTypes = event.payload.entityTypes || [];\n resource.dateCreated = event.timestamp;\n resource.creationMethod = 'clone';\n resource.sourceResourceId = event.payload.parentResourceId;\n resource.wasAttributedTo = didToAgent(event.userId);\n\n // Create representation from format and checksum\n if (!resource.representations) resource.representations = [];\n const reps2 = Array.isArray(resource.representations) ? resource.representations : [resource.representations];\n reps2.push({\n mediaType: event.payload.format,\n checksum: event.payload.contentChecksum,\n byteSize: event.payload.contentByteSize,\n rel: 'original',\n language: event.payload.language,\n } as Representation);\n resource.representations = reps2;\n break;\n\n case 'yield:updated':\n resource.currentChecksum = event.payload.contentChecksum;\n resource.dateModified = event.timestamp;\n break;\n\n case 'yield:moved':\n resource.storageUri = event.payload.toUri;\n resource.dateModified = event.timestamp;\n break;\n\n case 'mark:archived':\n resource.archived = true;\n break;\n\n case 'mark:unarchived':\n resource.archived = false;\n break;\n\n case 'yield:representation-added': {\n const { representation } = event.payload;\n\n // Add to representations array (avoid duplicates by checksum)\n if (!resource.representations) {\n resource.representations = [];\n }\n\n const repsArray = Array.isArray(resource.representations)\n ? resource.representations\n : [resource.representations];\n\n // Check if representation already exists\n const exists = repsArray.some(r => r.checksum === representation.checksum);\n if (!exists) {\n resource.representations = [...repsArray, representation];\n }\n break;\n }\n\n case 'yield:representation-removed': {\n const { checksum } = event.payload;\n\n if (resource.representations) {\n const repsArray = Array.isArray(resource.representations)\n ? resource.representations\n : [resource.representations];\n\n resource.representations = repsArray.filter(r => r.checksum !== checksum);\n }\n break;\n }\n\n case 'mark:entity-tag-added':\n if (!resource.entityTypes) resource.entityTypes = [];\n if (!resource.entityTypes.includes(event.payload.entityType)) {\n resource.entityTypes.push(event.payload.entityType);\n }\n break;\n\n case 'mark:entity-tag-removed':\n if (resource.entityTypes) {\n resource.entityTypes = resource.entityTypes.filter(\n (t: string) => t !== event.payload.entityType\n );\n }\n break;\n\n // Annotation events don't affect resource metadata\n case 'mark:added':\n case 'mark:removed':\n case 'mark:body-updated':\n break;\n\n // Job events don't affect resource metadata\n case 'job:started':\n case 'job:progress':\n case 'job:completed':\n case 'job:failed':\n break;\n\n // System events don't affect resource metadata\n case 'mark:entity-type-added':\n break;\n }\n }\n\n /**\n * Apply an event to ResourceAnnotations (annotation collections only)\n */\n private applyEventToAnnotations(annotations: ResourceAnnotations, event: PersistedEvent): void {\n switch (event.type) {\n case 'mark:added':\n annotations.annotations.push(event.payload.annotation);\n break;\n\n case 'mark:removed':\n annotations.annotations = annotations.annotations.filter(\n (a: Annotation) => a.id !== event.payload.annotationId\n );\n break;\n\n case 'mark:body-updated':\n const annotation = annotations.annotations.find((a: Annotation) =>\n a.id === event.payload.annotationId\n );\n if (annotation) {\n // Ensure body is an array\n if (!Array.isArray(annotation.body)) {\n annotation.body = annotation.body ? [annotation.body] : [];\n }\n\n // Apply each operation\n for (const op of event.payload.operations) {\n if (op.op === 'add') {\n // Add item (idempotent - don't add if already exists)\n const exists = findBodyItem(annotation.body, op.item) !== -1;\n if (!exists) {\n annotation.body.push(op.item);\n }\n } else if (op.op === 'remove') {\n // Remove item\n const index = findBodyItem(annotation.body, op.item);\n if (index !== -1) {\n annotation.body.splice(index, 1);\n }\n } else if (op.op === 'replace') {\n // Replace item\n const index = findBodyItem(annotation.body, op.oldItem);\n if (index !== -1) {\n annotation.body[index] = op.newItem;\n }\n }\n }\n\n // Update modified timestamp\n annotation.modified = new Date(event.timestamp).toISOString();\n }\n break;\n\n // Resource metadata events don't affect annotations\n case 'yield:created':\n case 'yield:cloned':\n case 'yield:updated':\n case 'yield:moved':\n case 'mark:archived':\n case 'mark:unarchived':\n case 'yield:representation-added':\n case 'yield:representation-removed':\n case 'mark:entity-tag-added':\n case 'mark:entity-tag-removed':\n break;\n\n // Job events don't affect annotations\n case 'job:started':\n case 'job:progress':\n case 'job:completed':\n case 'job:failed':\n break;\n\n // System events don't affect annotations\n case 'mark:entity-type-added':\n break;\n }\n }\n\n /**\n * Walk every event stream in the event log and materialize the corresponding\n * view from scratch. Idempotent: existing view files are overwritten.\n *\n * Mirrors GraphDBConsumer.rebuildAll() and Smelter.rebuildAll() — this is the\n * recovery path that makes the ephemeral stateDir safe to wipe. The live\n * append path (EventStore.appendEvent → materializeIncremental /\n * materializeEntityTypes) is unchanged and runs in addition.\n */\n async rebuildAll(eventLog: RebuildEventSource): Promise<void> {\n this.logger?.info('[ViewMaterializer] Rebuilding all materialized views from event log');\n\n const SYSTEM_ID = '__system__' as unknown as ResourceId;\n\n // Pass 1: __system__ events — produces system projections\n // (currently entitytypes.json; future system projections plug in here)\n const systemEvents = await eventLog.getEvents(SYSTEM_ID);\n this.logger?.info('[ViewMaterializer] Replaying system events', { count: systemEvents.length });\n for (const event of systemEvents) {\n if (event.type === 'mark:entity-type-added') {\n await this.materializeEntityTypes((event.payload as { entityType: string }).entityType);\n }\n }\n\n // Pass 2: resource-scoped events — produces resource views and the\n // storage-uri index\n const allResourceIds = await eventLog.getAllResourceIds();\n const resourceIds = allResourceIds.filter(\n (rid) => (rid as unknown as string) !== '__system__'\n );\n this.logger?.info('[ViewMaterializer] Rebuilding resource views', { count: resourceIds.length });\n let skipped = 0;\n for (const rid of resourceIds) {\n try {\n const events = await eventLog.getEvents(rid);\n if (events.length === 0) continue;\n\n const view = this.materializeFromEvents(events, rid);\n await this.viewStorage.save(rid, view);\n\n for (const event of events) {\n await this.materializeStorageUriIndex(rid, event);\n }\n } catch (error) {\n skipped++;\n this.logger?.error('[ViewMaterializer] Failed to rebuild resource view', {\n resourceId: String(rid),\n error: error instanceof Error ? error.message : String(error),\n });\n }\n }\n\n this.logger?.info('[ViewMaterializer] Rebuild complete', {\n systemEvents: systemEvents.length,\n resources: resourceIds.length,\n skipped,\n });\n }\n\n /**\n * Materialize entity types view - System-level view\n */\n async materializeEntityTypes(entityType: string): Promise<void> {\n const entityTypesPath = path.join(\n this.config.basePath,\n 'projections',\n '__system__',\n 'entitytypes.json'\n );\n\n\n // Read current view\n let view = { entityTypes: [] as string[] };\n try {\n const content = await fs.readFile(entityTypesPath, 'utf-8');\n view = JSON.parse(content);\n } catch (error: any) {\n if (error.code !== 'ENOENT') throw error;\n // File doesn't exist - will create it\n }\n\n // Add entity type (idempotent - Set ensures uniqueness)\n const entityTypeSet = new Set(view.entityTypes);\n entityTypeSet.add(entityType);\n view.entityTypes = Array.from(entityTypeSet).sort();\n\n // Write view\n await fs.mkdir(path.dirname(entityTypesPath), { recursive: true });\n await fs.writeFile(entityTypesPath, JSON.stringify(view, null, 2));\n }\n}\n","/**\n * ViewManager - Materialized View Management Layer\n *\n * Single Responsibility: View updates only\n * - Updates resource views from events\n * - Updates system views (entity types)\n * - Rebuilds views when needed\n *\n * Does NOT handle:\n * - Event persistence (see EventLog)\n * - Pub/sub notifications (see EventBus)\n */\n\nimport { type ResourceId, type PersistedEvent, type StoredEvent, type Logger, serializePerKey } from '@semiont/core';\nimport { ViewMaterializer, type ViewMaterializerConfig, type RebuildEventSource } from './views/view-materializer';\nimport type { ViewStorage, ResourceView } from './storage/view-storage';\n\nexport interface ViewManagerConfig {\n basePath: string;\n}\n\n/**\n * ViewManager wraps ViewMaterializer with a clean API\n * Handles both resource and system-level views\n *\n * ## Per-resource serialization\n *\n * `materializeResource` runs read-modify-write cycles on the view file for\n * a given resource (load JSON → apply event → save JSON). When multiple\n * events arrive for the same resource in rapid succession — the canonical\n * example is the reference-detection worker emitting `mark:added` +\n * `job:progress` + `job:completed` within a few milliseconds — concurrent\n * RMW cycles will clobber each other, losing events and occasionally\n * corrupting the view file entirely.\n *\n * ViewManager serializes these via `serializePerKey` from `@semiont/core`:\n * each incoming `materializeResource` call chains onto the previous one\n * for the same `resourceId`, so the work runs strictly sequentially per\n * resource while still parallelizing across different resources. System\n * events go through their own shared chain (keyed by a sentinel).\n *\n * Why this shape and not RxJS `groupBy + concatMap`:\n * ViewManager is called **synchronously** by `EventStore.appendEvent` — it\n * must block the caller until the view is written, so SSE subscribers\n * that see the subsequently-published event get the up-to-date view (a\n * read-your-writes guarantee). The RxJS stream-consumer pattern used by\n * `Smelter`, `GraphDBConsumer`, and `Gatherer` can't provide that\n * guarantee because it's fire-and-forget from the publisher's perspective.\n * Both patterns solve \"serialize work per resource\" — see also\n * `packages/core/src/serialize-per-key.ts` for the shared primitive.\n */\nexport class ViewManager {\n // Expose materializer for direct access to view methods\n readonly materializer: ViewMaterializer;\n\n // Per-resource write serialization. Keyed by the string form of ResourceId;\n // values are promise tails in the in-flight chain for each resource.\n // Entries are removed once the chain empties — see `serializePerKey`.\n private resourceChains = new Map<string, Promise<void>>();\n\n // Shared chain for system-level views (entity types, etc.). A single\n // sentinel key serializes all system-level writes; these events are\n // rare and global, so per-type keying buys nothing.\n private systemChains = new Map<symbol, Promise<void>>();\n private static readonly SYSTEM_KEY = Symbol('system');\n\n constructor(\n viewStorage: ViewStorage,\n config: ViewManagerConfig,\n logger?: Logger\n ) {\n const materializerConfig: ViewMaterializerConfig = {\n basePath: config.basePath,\n };\n this.materializer = new ViewMaterializer(viewStorage, materializerConfig, logger?.child({ component: 'ViewMaterializer' }));\n }\n\n /**\n * Update resource view with a new event.\n * Serialized per resource — see class doc.\n *\n * @param resourceId - Branded ResourceId (from @semiont/core)\n * @param event - Resource event (from @semiont/core)\n * @param getAllEvents - Function to retrieve all events for rebuild if needed\n */\n async materializeResource(\n resourceId: ResourceId,\n event: PersistedEvent,\n getAllEvents: () => Promise<StoredEvent[]>\n ): Promise<void> {\n await serializePerKey(String(resourceId), this.resourceChains, () =>\n this.materializer.materializeIncremental(resourceId, event, getAllEvents),\n );\n }\n\n /**\n * Update system-level view (currently only entity types).\n * Serialized through a shared chain — see class doc.\n */\n async materializeSystem(eventType: string, payload: any): Promise<void> {\n await serializePerKey(ViewManager.SYSTEM_KEY, this.systemChains, async () => {\n if (eventType === 'mark:entity-type-added') {\n await this.materializer.materializeEntityTypes(payload.entityType);\n }\n // Future system views can be added here\n });\n }\n\n /**\n * Rebuild all materialized views from the event log on startup.\n * Mirrors GraphDBConsumer.rebuildAll() — call this once during\n * createKnowledgeBase before the HTTP server begins accepting requests.\n * Idempotent: existing view files are overwritten.\n */\n async rebuildAll(eventLog: RebuildEventSource): Promise<void> {\n return this.materializer.rebuildAll(eventLog);\n }\n\n /**\n * Get resource view (builds from events if needed)\n * @param resourceId - Branded ResourceId (from @semiont/core)\n * @param events - Stored events for the resource (from @semiont/core)\n * @returns Resource view or null if no events\n */\n async getOrMaterialize(\n resourceId: ResourceId,\n events: StoredEvent[]\n ): Promise<ResourceView | null> {\n return this.materializer.materialize(events, resourceId);\n }\n}\n","/**\n * EventStore - Orchestration Layer\n *\n * Coordinates event sourcing operations:\n * - EventLog: Event persistence (append, retrieve, query)\n * - ViewManager: View materialization (resource and system)\n * - Core EventBus: Publishes StoredEvent to typed channels after persistence\n *\n * appendEvent() is the single write path:\n * 1. Persist to EventLog\n * 2. Materialize views\n * 3. Enrich (optional callback — attach post-materialization data)\n * 4. Publish StoredEvent to global and resource-scoped typed channels\n */\n\nimport type {\n EventInput,\n StoredEvent,\n ResourceId,\n Logger,\n} from '@semiont/core';\nimport { EventBus as CoreEventBus } from '@semiont/core';\nimport type { SemiontProject } from '@semiont/core/node';\nimport type { ViewStorage } from './storage/view-storage';\nimport { EventLog } from './event-log';\nimport { ViewManager, type ViewManagerConfig } from './view-manager';\n\nexport type EnrichEvent = (event: StoredEvent, resourceId: ResourceId) => Promise<StoredEvent>;\n\nexport class EventStore {\n readonly log: EventLog;\n readonly views: ViewManager;\n readonly viewStorage: ViewStorage;\n readonly coreEventBus: CoreEventBus;\n private enrichEvent: EnrichEvent | null = null;\n\n constructor(\n project: SemiontProject,\n stateDir: string,\n viewStorage: ViewStorage,\n coreEventBus: CoreEventBus,\n logger?: Logger\n ) {\n this.viewStorage = viewStorage;\n this.coreEventBus = coreEventBus;\n\n this.log = new EventLog({ project }, logger?.child({ component: 'EventLog' }));\n\n const viewConfig: ViewManagerConfig = {\n basePath: stateDir,\n };\n this.views = new ViewManager(viewStorage, viewConfig, logger?.child({ component: 'ViewManager' }));\n }\n\n setEnrichEvent(fn: EnrichEvent): void {\n this.enrichEvent = fn;\n }\n\n /**\n * Append an event to the store\n * Coordinates: persistence → view → enrich → notification\n *\n * @param options.correlationId - Optional id propagated from a command.\n */\n async appendEvent(\n event: EventInput,\n options?: { correlationId?: string },\n ): Promise<StoredEvent> {\n const resourceId: ResourceId | '__system__' = event.resourceId || '__system__';\n\n // 1. Persist event to log\n const storedEvent = await this.log.append(event, resourceId as any, options);\n\n // 2. Update views\n if (resourceId === '__system__') {\n await this.views.materializeSystem(\n storedEvent.type,\n storedEvent.payload\n );\n } else {\n await this.views.materializeResource(\n resourceId as ResourceId,\n storedEvent,\n () => this.log.getEvents(resourceId as ResourceId)\n );\n }\n\n // 3. Enrich (attach post-materialization data like annotations)\n let publishEvent = storedEvent;\n if (this.enrichEvent && resourceId !== '__system__') {\n publishEvent = await this.enrichEvent(storedEvent, resourceId as ResourceId);\n }\n\n // 4. Publish to Core EventBus typed channels\n this.coreEventBus.getDomainEvent(publishEvent.type).next(publishEvent);\n\n if (resourceId !== '__system__') {\n const scopedBus = this.coreEventBus.scope(resourceId as string);\n scopedBus.getDomainEvent(publishEvent.type).next(publishEvent);\n }\n\n return storedEvent;\n }\n}\n","/**\n * View Storage - Materialized Views\n *\n * Stores materialized views of resource state and annotations\n * Built from event streams, can be rebuilt at any time\n *\n * Stores both ResourceDescriptor metadata and ResourceAnnotations, but keeps them logically separate\n */\n\nimport { promises as fs } from 'fs';\nimport * as path from 'path';\nimport { getShardPath } from './shard-utils';\nimport type { SemiontProject } from '@semiont/core/node';\nimport type { components, ResourceAnnotations, ResourceId, Logger } from '@semiont/core';\n\ntype ResourceDescriptor = components['schemas']['ResourceDescriptor'];\n\n// Complete state for a resource in materialized view (metadata + annotations)\nexport interface ResourceView {\n resource: ResourceDescriptor;\n annotations: ResourceAnnotations;\n}\n\nexport interface ViewStorage {\n save(resourceId: ResourceId, view: ResourceView): Promise<void>;\n get(resourceId: ResourceId): Promise<ResourceView | null>;\n delete(resourceId: ResourceId): Promise<void>;\n exists(resourceId: ResourceId): Promise<boolean>;\n getAll(): Promise<ResourceView[]>;\n}\n\nexport class FilesystemViewStorage implements ViewStorage {\n private basePath: string;\n private logger?: Logger;\n\n constructor(project: SemiontProject, logger?: Logger) {\n this.logger = logger;\n this.basePath = project.stateDir;\n }\n\n private getProjectionPath(resourceId: ResourceId): string {\n // Use 4-hex Jump Consistent Hash sharding (65,536 shards)\n const [ab, cd] = getShardPath(resourceId);\n return path.join(this.basePath, 'resources', ab, cd, `${resourceId}.json`);\n }\n\n async save(resourceId: ResourceId, projection: ResourceView): Promise<void> {\n const projPath = this.getProjectionPath(resourceId);\n const projDir = path.dirname(projPath);\n\n // Ensure shard directory exists\n await fs.mkdir(projDir, { recursive: true });\n\n // Atomic write: write to a sibling temp file and rename into place.\n // `fs.writeFile` on its own truncates the target to 0 bytes before\n // writing, so a concurrent reader can observe an empty file and\n // get a `JSON.parse('')` SyntaxError mid-write. `rename` is atomic\n // on POSIX, so readers always see either the old or new content,\n // never a partial one.\n const tmpPath = `${projPath}.${process.pid}.${Date.now()}.tmp`;\n await fs.writeFile(tmpPath, JSON.stringify(projection, null, 2), 'utf-8');\n try {\n await fs.rename(tmpPath, projPath);\n } catch (error) {\n await fs.unlink(tmpPath).catch(() => {});\n throw error;\n }\n }\n\n async get(resourceId: ResourceId): Promise<ResourceView | null> {\n const projPath = this.getProjectionPath(resourceId);\n\n try {\n const content = await fs.readFile(projPath, 'utf-8');\n return JSON.parse(content) as ResourceView;\n } catch (error: any) {\n if (error.code === 'ENOENT') {\n return null;\n }\n // Don't delete on SyntaxError — the old code unlinked the file,\n // which turned a transient race (read-during-write with the\n // pre-atomic `fs.writeFile`) into a permanent \"view missing\"\n // that the next materializer write had to repair from scratch.\n // With atomic `rename` in `save`, SyntaxError should only fire\n // on genuine corruption; either way, the next incremental\n // update will overwrite the file with a good view, so we just\n // log and treat as missing.\n if (error instanceof SyntaxError) {\n this.logger?.error('[ViewStorage] Corrupted view file, treating as missing', {\n resourceId,\n path: projPath,\n error: error.message,\n });\n return null;\n }\n throw error;\n }\n }\n\n async delete(resourceId: ResourceId): Promise<void> {\n const projPath = this.getProjectionPath(resourceId);\n\n try {\n await fs.unlink(projPath);\n } catch (error: any) {\n if (error.code !== 'ENOENT') {\n throw error;\n }\n // Ignore if file doesn't exist\n }\n }\n\n async exists(resourceId: ResourceId): Promise<boolean> {\n const projPath = this.getProjectionPath(resourceId);\n\n try {\n await fs.access(projPath);\n return true;\n } catch {\n return false;\n }\n }\n\n async getAll(): Promise<ResourceView[]> {\n const views: ResourceView[] = [];\n const annotationsPath = path.join(this.basePath, 'resources');\n\n try {\n // Recursively walk through all shard directories\n const walkDir = async (dir: string): Promise<void> => {\n const entries = await fs.readdir(dir, { withFileTypes: true });\n\n for (const entry of entries) {\n const fullPath = path.join(dir, entry.name);\n\n if (entry.isDirectory()) {\n await walkDir(fullPath);\n } else if (entry.isFile() && entry.name.endsWith('.json')) {\n try {\n const content = await fs.readFile(fullPath, 'utf-8');\n const view = JSON.parse(content) as ResourceView;\n views.push(view);\n } catch (error) {\n this.logger?.error('[ViewStorage] Failed to read view', { path: fullPath, error });\n // Skip invalid view files\n }\n }\n }\n };\n\n await walkDir(annotationsPath);\n } catch (error: any) {\n if (error.code === 'ENOENT') {\n // Views directory doesn't exist yet\n return [];\n }\n throw error;\n }\n\n return views;\n }\n}","/**\n * Event Store Factory\n *\n * Factory function for creating EventStore instances with standard configuration.\n * This is the canonical way to instantiate an EventStore.\n */\n\nimport type { SemiontProject } from '@semiont/core/node';\nimport type { EventBus as CoreEventBus, Logger } from '@semiont/core';\nimport { EventStore } from './event-store';\nimport { FilesystemViewStorage } from './storage/view-storage';\n\n/**\n * Create and initialize an EventStore instance\n *\n * @param project - SemiontProject instance\n * @param eventBus - @semiont/core EventBus for publishing domain events\n * @param logger - Optional logger for structured logging\n * @returns Configured EventStore instance ready for use\n */\nexport function createEventStore(\n project: SemiontProject,\n eventBus: CoreEventBus,\n logger?: Logger\n): EventStore {\n const viewStorage = new FilesystemViewStorage(project, logger?.child({ component: 'view-storage' }));\n\n return new EventStore(\n project,\n project.stateDir,\n viewStorage,\n eventBus,\n logger\n );\n}\n","/**\n * Event Query - Read Operations\n *\n * Handles querying and reading events from storage:\n * - Query events with filters (type, user, timestamp, sequence)\n * - Get all events for a resource\n * - Get last event from a file\n * - Efficient streaming reads from JSONL files\n *\n * @see docs/EVENT-STORE.md#eventquery for architecture details\n */\n\nimport type { StoredEvent, EventQuery as EventQueryType, ResourceId } from '@semiont/core';\nimport type { EventStorage } from '../storage/event-storage';\n\n/**\n * EventQuery handles all read operations for events\n * Uses EventStorage for file access, adds query filtering\n */\nexport class EventQuery {\n constructor(private eventStorage: EventStorage) {}\n\n /**\n * Query events with filters\n * Supports filtering by: userId, eventTypes, timestamps, sequence number, limit\n */\n async queryEvents(query: EventQueryType): Promise<StoredEvent[]> {\n if (!query.resourceId) {\n throw new Error('resourceId is required for event queries');\n }\n\n // Get all events from storage\n const allEvents = await this.eventStorage.getAllEvents(query.resourceId);\n\n // Apply filters\n let results = allEvents;\n\n if (query.userId) {\n results = results.filter(e => e.userId === query.userId);\n }\n\n if (query.eventTypes && query.eventTypes.length > 0) {\n results = results.filter(e => query.eventTypes!.includes(e.type));\n }\n\n if (query.fromTimestamp) {\n results = results.filter(e => e.timestamp >= query.fromTimestamp!);\n }\n\n if (query.toTimestamp) {\n results = results.filter(e => e.timestamp <= query.toTimestamp!);\n }\n\n if (query.fromSequence) {\n results = results.filter(e => e.metadata.sequenceNumber >= query.fromSequence!);\n }\n\n // Apply limit\n if (query.limit && query.limit > 0) {\n results = results.slice(0, query.limit);\n }\n\n return results;\n }\n\n /**\n * Get all events for a specific resource (no filters)\n */\n async getResourceEvents(resourceId: ResourceId): Promise<StoredEvent[]> {\n return this.eventStorage.getAllEvents(resourceId);\n }\n\n /**\n * Get the last event from a specific file\n * Useful for initializing sequence numbers and last hashes\n */\n async getLastEvent(resourceId: ResourceId, filename: string): Promise<StoredEvent | null> {\n return this.eventStorage.getLastEvent(resourceId, filename);\n }\n\n /**\n * Get the latest event for a resource across all files\n */\n async getLatestEvent(resourceId: ResourceId): Promise<StoredEvent | null> {\n const files = await this.eventStorage.getEventFiles(resourceId);\n if (files.length === 0) return null;\n\n // Check files in reverse order (newest first)\n for (let i = files.length - 1; i >= 0; i--) {\n const file = files[i];\n if (!file) continue;\n const lastEvent = await this.eventStorage.getLastEvent(resourceId, file);\n if (lastEvent) return lastEvent;\n }\n\n return null;\n }\n\n /**\n * Get event count for a resource\n */\n async getEventCount(resourceId: ResourceId): Promise<number> {\n const events = await this.getResourceEvents(resourceId);\n return events.length;\n }\n\n /**\n * Check if a resource has any events\n */\n async hasEvents(resourceId: ResourceId): Promise<boolean> {\n const files = await this.eventStorage.getEventFiles(resourceId);\n return files.length > 0;\n }\n}\n","/**\n * Identifier utilities for event sourcing\n */\n\nimport { nanoid } from 'nanoid';\n\n/**\n * Generate a unique annotation ID (bare nanoid)\n *\n * @returns A bare annotation ID (e.g., \"V1StGXR8_Z5jdHi6B-myT\")\n */\nexport function generateAnnotationId(): string {\n return nanoid(21);\n}\n"]}
1
+ {"version":3,"sources":["../src/storage/shard-utils.ts","../src/storage/event-storage.ts","../src/event-log.ts","../src/storage/storage-uri-index.ts","../src/views/view-materializer.ts","../src/view-manager.ts","../src/event-store.ts","../src/storage/view-storage.ts","../src/event-store-factory.ts","../src/query/event-query.ts","../src/identifier-utils.ts"],"names":["fs","uuidv4","resourceId","makeResourceId","path","path3","path4"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Sharding Utilities\n *\n * Shared utilities for consistent sharding across all storage layers\n * Uses Google's Jump Consistent Hash algorithm for even distribution\n */\n\nimport { createHash } from 'crypto';\n\n/**\n * TEMPORARY: Simple modulo-based hash sharding\n *\n * ⚠️ TODO: Replace with proper Jump Consistent Hash implementation\n *\n * This is a TEMPORARY implementation using simple modulo. It works and provides\n * good distribution, but does NOT provide the minimal reshuffling property of\n * Jump Consistent Hash when changing bucket counts.\n *\n * The proper implementation should use Google's Jump Consistent Hash algorithm:\n * Reference: \"A Fast, Minimal Memory, Consistent Hash Algorithm\" by Lamping & Veach (2014)\n * https://arxiv.org/abs/1406.2294\n *\n * Working implementations exist in npm packages like:\n * - jumphash (https://www.npmjs.com/package/jumphash)\n * - jump-gouache (https://github.com/bhoudu/jump-gouache)\n *\n * The algorithm requires proper 64-bit integer handling with BigInt to avoid\n * precision loss in JavaScript. The previous attempt failed due to incorrect\n * BigInt arithmetic in the while loop condition.\n *\n * Until replaced, this modulo approach will cause ALL data to be reshuffled\n * if bucket count changes, rather than the optimal O(n/k) reshuffling that\n * Jump Consistent Hash provides.\n *\n * @param key - The key to hash (typically a resource ID)\n * @param numBuckets - Number of shards/buckets (default: 65536 for 4-hex sharding)\n * @returns Shard number (0 to numBuckets-1)\n */\nexport function jumpConsistentHash(key: string, numBuckets: number = 65536): number {\n const hash = hashToUint32(key);\n return hash % numBuckets;\n}\n\n/**\n * Hash string to 32-bit unsigned integer\n */\nfunction hashToUint32(str: string): number {\n let hash = 0;\n for (let i = 0; i < str.length; i++) {\n hash = ((hash << 5) - hash) + str.charCodeAt(i);\n hash = hash & 0xFFFFFFFF;\n }\n return Math.abs(hash);\n}\n\n/**\n * Convert shard number to 4-hex directory path (ab/cd)\n *\n * @param shardId - Shard number (0-65535)\n * @returns Path segments like ['ab', 'cd']\n */\nexport function shardIdToPath(shardId: number): [string, string] {\n if (shardId < 0 || shardId >= 65536) {\n throw new Error(`Invalid shard ID: ${shardId}. Must be 0-65535 for 4-hex sharding.`);\n }\n\n const shardHex = shardId.toString(16).padStart(4, '0');\n const ab = shardHex.substring(0, 2);\n const cd = shardHex.substring(2, 4);\n\n return [ab, cd];\n}\n\n/**\n * Get 4-hex shard path for a key\n *\n * @param key - The key to hash (typically a resource ID)\n * @param numBuckets - Number of shards (default: 65536)\n * @returns Path segments like ['ab', 'cd']\n */\nexport function getShardPath(key: string, numBuckets: number = 65536): [string, string] {\n const shardId = jumpConsistentHash(key, numBuckets);\n return shardIdToPath(shardId);\n}\n\n/**\n * Calculate SHA-256 hash of data\n */\nexport function sha256(data: string | object): string {\n const content = typeof data === 'string' ? data : JSON.stringify(data);\n return createHash('sha256').update(content).digest('hex');\n}","/**\n * Event Storage - Physical Storage Layer\n *\n * Handles file I/O operations for event storage:\n * - JSONL file writing/reading\n * - 4-hex sharding (65,536 shards)\n * - File rotation\n * - Event stream initialization\n *\n * @see docs/EVENT-STORE.md#eventstorage for architecture details\n */\n\nimport { promises as fs } from 'fs';\nimport { execFileSync } from 'child_process';\nimport * as path from 'path';\nimport { createReadStream } from 'fs';\nimport * as readline from 'readline';\nimport { v4 as uuidv4 } from 'uuid';\nimport type { StoredEvent, PersistedEvent, EventMetadata, EventInput, ResourceId, Logger } from '@semiont/core';\nimport { resourceId as makeResourceId } from '@semiont/core';\nimport type { SemiontProject } from '@semiont/core/node';\nimport { jumpConsistentHash } from './shard-utils';\n\nexport interface EventStorageConfig {\n maxEventsPerFile?: number; // File rotation threshold (default: 10000)\n enableSharding?: boolean; // Enable 4-hex sharding (default: true)\n numShards?: number; // Number of shards (default: 65536)\n enableCompression?: boolean; // Gzip rotated files (default: true)\n}\n\n/**\n * EventStorage handles physical storage of events\n * Owns: file I/O, sharding, AND sequence/hash tracking\n */\nexport class EventStorage {\n private config: Required<EventStorageConfig>;\n private project: SemiontProject;\n private logger?: Logger;\n\n // Per-resource sequence tracking: resourceId -> sequence number\n private resourceSequences: Map<string, number> = new Map();\n // Per-resource current file cache: avoids fs.readdir() + countEventsInFile() on every append\n private currentFiles: Map<string, { path: string; eventCount: number }> = new Map();\n\n constructor(project: SemiontProject, config?: EventStorageConfig, logger?: Logger) {\n this.project = project;\n this.logger = logger;\n this.config = {\n maxEventsPerFile: config?.maxEventsPerFile || 10000,\n enableSharding: config?.enableSharding ?? true,\n numShards: config?.numShards || 65536,\n enableCompression: config?.enableCompression ?? true,\n };\n }\n\n /**\n * Calculate shard path for a resource ID\n * Uses jump consistent hash for uniform distribution\n * Special case: __system__ events bypass sharding\n */\n getShardPath(resourceId: ResourceId): string {\n // System events don't get sharded\n if (resourceId === '__system__' || !this.config.enableSharding) {\n return '';\n }\n\n // Jump consistent hash for uniform shard distribution\n const shardIndex = jumpConsistentHash(resourceId, this.config.numShards);\n\n // Convert to 4-hex format (e.g., 0000, 0001, ..., ffff)\n const hex = shardIndex.toString(16).padStart(4, '0');\n const [ab, cd] = [hex.substring(0, 2), hex.substring(2, 4)];\n\n return path.join(ab, cd);\n }\n\n /**\n * Get full path to resource's event directory\n */\n getResourcePath(resourceId: ResourceId): string {\n const shardPath = this.getShardPath(resourceId);\n return path.join(this.project.eventsDir, shardPath, resourceId);\n }\n\n /**\n * Initialize directory structure for a resource's event stream\n * Also loads sequence number and last hash if stream exists\n */\n async initializeResourceStream(resourceId: ResourceId): Promise<void> {\n const docPath = this.getResourcePath(resourceId);\n\n // Check if already initialized\n let exists = false;\n try {\n await fs.access(docPath);\n exists = true;\n } catch {\n // Doesn't exist, create it\n }\n\n if (!exists) {\n // Create directory structure\n await fs.mkdir(docPath, { recursive: true });\n\n // Create initial empty events file\n const filename = this.createEventFilename(1);\n const filePath = path.join(docPath, filename);\n await fs.writeFile(filePath, '', 'utf-8');\n\n // Stage the new event stream directory in git\n if (this.project.gitSync) {\n execFileSync('git', ['add', docPath], { cwd: this.project.root });\n }\n\n // Initialize sequence number\n this.resourceSequences.set(resourceId, 0);\n\n this.logger?.info('[EventStorage] Initialized event stream', { resourceId, path: docPath });\n } else {\n // Load existing sequence number from the last file\n const files = await this.getEventFiles(resourceId);\n if (files.length > 0) {\n const lastFile = files[files.length - 1];\n if (lastFile) {\n const lastEvent = await this.getLastEvent(resourceId, lastFile);\n if (lastEvent) {\n this.resourceSequences.set(resourceId, lastEvent.metadata.sequenceNumber);\n }\n }\n } else {\n this.resourceSequences.set(resourceId, 0);\n }\n }\n }\n\n /**\n * Append an event - handles EVERYTHING for event creation\n * Creates ID, timestamp, metadata, sequence tracking, and writes to disk.\n *\n * Integrity is provided by git at the commit level (when gitSync is enabled),\n * not by per-event chaining metadata. Per-event signatures (the unused\n * `EventSignature` field on StoredEvent) are the planned mechanism for\n * cross-KB authorship binding when federation becomes a real requirement.\n *\n * @param options.correlationId - Optional id propagated from a command. Stored\n * on the event's metadata so subscribers (notably the events-stream → frontend\n * path) can match command-result events back to the POST that initiated them.\n */\n async appendEvent(\n event: EventInput,\n resourceId: ResourceId,\n options?: { correlationId?: string },\n ): Promise<StoredEvent> {\n // Ensure resource stream is initialized\n if (this.getSequenceNumber(resourceId) === 0) {\n await this.initializeResourceStream(resourceId);\n }\n\n // Create complete event with ID and timestamp\n const completeEvent: PersistedEvent = {\n ...event,\n id: uuidv4(),\n timestamp: new Date().toISOString(),\n } as PersistedEvent;\n\n const sequenceNumber = this.getNextSequenceNumber(resourceId);\n\n const metadata: EventMetadata = {\n sequenceNumber,\n streamPosition: 0, // Will be set during write\n ...(options?.correlationId !== undefined && { correlationId: options.correlationId }),\n };\n\n const storedEvent: StoredEvent = {\n ...completeEvent,\n metadata,\n };\n\n await this.writeEvent(storedEvent, resourceId);\n\n return storedEvent;\n }\n\n /**\n * Write an event to storage (append to JSONL)\n * Internal method - use appendEvent() instead\n *\n * Uses currentFiles cache to avoid fs.readdir() + countEventsInFile() on every append.\n * Cache is populated on first append (cold start) and updated on rotation.\n */\n private async writeEvent(event: StoredEvent, resourceId: ResourceId): Promise<void> {\n const docPath = this.getResourcePath(resourceId);\n let current = this.currentFiles.get(resourceId);\n\n if (!current) {\n // Cold start: read from disk once\n const files = await this.getEventFiles(resourceId);\n const lastFile = files[files.length - 1];\n if (lastFile) {\n const count = await this.countEventsInFile(resourceId, lastFile);\n current = { path: lastFile, eventCount: count };\n } else {\n const newFile = await this.createNewEventFile(resourceId);\n current = { path: newFile, eventCount: 0 };\n }\n this.currentFiles.set(resourceId, current);\n }\n\n if (current.eventCount >= this.config.maxEventsPerFile) {\n const newFile = await this.createNewEventFile(resourceId);\n current = { path: newFile, eventCount: 0 };\n this.currentFiles.set(resourceId, current);\n }\n\n // Append event to file (JSONL format)\n const targetPath = path.join(docPath, current.path);\n const eventLine = JSON.stringify(event) + '\\n';\n await fs.appendFile(targetPath, eventLine, 'utf-8');\n current.eventCount++;\n\n // Stage the event log file in git index if configured\n if (this.project.gitSync) {\n execFileSync('git', ['add', targetPath], { cwd: this.project.root });\n }\n }\n\n /**\n * Count events in a specific file\n */\n async countEventsInFile(resourceId: ResourceId, filename: string): Promise<number> {\n const docPath = this.getResourcePath(resourceId);\n const filePath = path.join(docPath, filename);\n\n try {\n const content = await fs.readFile(filePath, 'utf-8');\n const lines = content.trim().split('\\n').filter(line => line.trim() !== '');\n return lines.length;\n } catch (error: any) {\n if (error.code === 'ENOENT') {\n return 0;\n }\n throw error;\n }\n }\n\n /**\n * Read all events from a specific file\n */\n async readEventsFromFile(resourceId: ResourceId, filename: string): Promise<StoredEvent[]> {\n const docPath = this.getResourcePath(resourceId);\n const filePath = path.join(docPath, filename);\n\n const events: StoredEvent[] = [];\n\n try {\n const fileStream = createReadStream(filePath, { encoding: 'utf-8' });\n const rl = readline.createInterface({\n input: fileStream,\n crlfDelay: Infinity,\n });\n\n for await (const line of rl) {\n const trimmed = line.trim();\n if (trimmed === '') continue;\n\n try {\n const parsed = JSON.parse(trimmed);\n // Handle both flat (new) and nested (old) JSONL formats\n if ('event' in parsed && 'metadata' in parsed && !('type' in parsed)) {\n // Old nested format: { event: {...}, metadata: {...} } → flatten\n events.push({ ...parsed.event, metadata: parsed.metadata, signature: parsed.signature } as StoredEvent);\n } else {\n events.push(parsed as StoredEvent);\n }\n } catch (parseError) {\n this.logger?.error('[EventStorage] Failed to parse event', { filePath, error: parseError });\n // Skip malformed lines\n }\n }\n } catch (error: any) {\n if (error.code === 'ENOENT') {\n return []; // File doesn't exist\n }\n throw error;\n }\n\n return events;\n }\n\n /**\n * Get list of event files for a resource (sorted by sequence)\n */\n async getEventFiles(resourceId: ResourceId): Promise<string[]> {\n const docPath = this.getResourcePath(makeResourceId(resourceId));\n\n try {\n const files = await fs.readdir(docPath);\n\n // Filter to .jsonl files and sort by sequence number\n const eventFiles = files\n .filter(f => f.startsWith('events-') && f.endsWith('.jsonl'))\n .sort((a, b) => {\n const seqA = parseInt(a.match(/events-(\\d+)\\.jsonl/)?.[1] || '0');\n const seqB = parseInt(b.match(/events-(\\d+)\\.jsonl/)?.[1] || '0');\n return seqA - seqB;\n });\n\n return eventFiles;\n } catch (error: any) {\n if (error.code === 'ENOENT') {\n return []; // Directory doesn't exist\n }\n throw error;\n }\n }\n\n /**\n * Create a new event file for rotation\n */\n async createNewEventFile(resourceId: ResourceId): Promise<string> {\n const files = await this.getEventFiles(resourceId);\n\n // Determine next sequence number\n const lastFile = files[files.length - 1];\n const lastSeq = lastFile ? parseInt(lastFile.match(/events-(\\d+)\\.jsonl/)?.[1] || '1') : 1;\n const newSeq = lastSeq + 1;\n\n // Create new file\n const filename = this.createEventFilename(newSeq);\n const docPath = this.getResourcePath(resourceId);\n const filePath = path.join(docPath, filename);\n\n await fs.writeFile(filePath, '', 'utf-8');\n\n this.logger?.info('[EventStorage] Created new event file', { filename, resourceId });\n\n return filename;\n }\n\n /**\n * Get the last event from a specific file\n */\n async getLastEvent(resourceId: ResourceId, filename: string): Promise<StoredEvent | null> {\n const events = await this.readEventsFromFile(resourceId, filename);\n const lastEvent = events.length > 0 ? events[events.length - 1] : undefined;\n return lastEvent ?? null;\n }\n\n /**\n * Get all events for a resource across all files\n */\n async getAllEvents(resourceId: ResourceId): Promise<StoredEvent[]> {\n const files = await this.getEventFiles(resourceId);\n const allEvents: StoredEvent[] = [];\n\n for (const file of files) {\n const events = await this.readEventsFromFile(resourceId, file);\n allEvents.push(...events);\n }\n\n return allEvents;\n }\n\n /**\n * Get all resource IDs by scanning shard directories\n */\n async getAllResourceIds(): Promise<ResourceId[]> {\n const eventsDir = this.project.eventsDir;\n const resourceIds: ResourceId[] = [];\n\n try {\n await fs.access(eventsDir);\n } catch {\n return []; // No events directory yet\n }\n\n // Recursively scan shard directories\n const scanDir = async (dir: string) => {\n const entries = await fs.readdir(dir, { withFileTypes: true });\n\n for (const entry of entries) {\n const fullPath = path.join(dir, entry.name);\n\n if (entry.isDirectory()) {\n // Check if this looks like a resource ID (not a shard directory)\n // Shard directories are 2-char hex (00-ff), resource IDs are longer\n if (entry.name.length > 2) {\n resourceIds.push(makeResourceId(entry.name));\n } else {\n // Recurse into shard directory\n await scanDir(fullPath);\n }\n }\n }\n };\n\n await scanDir(eventsDir);\n return resourceIds;\n }\n\n /**\n * Create filename for event file\n */\n private createEventFilename(sequenceNumber: number): string {\n return `events-${sequenceNumber.toString().padStart(6, '0')}.jsonl`;\n }\n\n // ============================================================\n // Sequence/Hash Tracking\n // ============================================================\n\n /**\n * Get current sequence number for a resource\n */\n getSequenceNumber(resourceId: ResourceId): number {\n return this.resourceSequences.get(resourceId) || 0;\n }\n\n /**\n * Increment and return next sequence number for a resource\n */\n getNextSequenceNumber(resourceId: ResourceId): number {\n const current = this.getSequenceNumber(resourceId);\n const next = current + 1;\n this.resourceSequences.set(resourceId, next);\n return next;\n }\n\n}\n","/**\n * EventLog - Event Persistence Layer\n *\n * Single Responsibility: Event persistence only\n * - Appends events to storage (JSONL files)\n * - Retrieves events by resource\n * - Queries events with filters\n *\n * Does NOT handle:\n * - Pub/sub notifications (see EventBus)\n * - View updates (see ViewManager)\n */\n\nimport { type ResourceId, type StoredEvent, type EventQuery, type EventInput, type Logger } from '@semiont/core';\nimport type { SemiontProject } from '@semiont/core/node';\nimport { EventStorage } from './storage/event-storage';\n\nexport interface EventLogConfig {\n project: SemiontProject;\n enableSharding?: boolean;\n maxEventsPerFile?: number;\n}\n\nexport class EventLog {\n // Expose storage for EventQuery (read operations)\n readonly storage: EventStorage;\n\n constructor(config: EventLogConfig, logger?: Logger) {\n this.storage = new EventStorage(config.project, {\n enableSharding: config.enableSharding,\n maxEventsPerFile: config.maxEventsPerFile,\n }, logger?.child({ component: 'EventStorage' }));\n }\n\n /**\n * Append event to log\n * @param event - Resource event (from @semiont/core)\n * @param resourceId - Branded ResourceId (from @semiont/core)\n * @param options.correlationId - Optional command correlation id (stored on metadata)\n * @returns Stored event with metadata (sequence number, timestamp, checksum)\n */\n async append(\n event: EventInput,\n resourceId: ResourceId,\n options?: { correlationId?: string },\n ): Promise<StoredEvent> {\n return this.storage.appendEvent(event, resourceId, options);\n }\n\n /**\n * Get all events for a resource\n * @param resourceId - Branded ResourceId (from @semiont/core)\n */\n async getEvents(resourceId: ResourceId): Promise<StoredEvent[]> {\n return this.storage.getAllEvents(resourceId);\n }\n\n /**\n * Get all resource IDs\n * @returns Array of branded ResourceId types\n */\n async getAllResourceIds(): Promise<ResourceId[]> {\n return this.storage.getAllResourceIds();\n }\n\n /**\n * Query events with filter\n * @param resourceId - Branded ResourceId (from @semiont/core)\n * @param filter - Optional event filter\n */\n async queryEvents(resourceId: ResourceId, filter?: EventQuery): Promise<StoredEvent[]> {\n const events = await this.storage.getAllEvents(resourceId);\n if (!filter) return events;\n\n return events.filter(e => {\n if (filter.eventTypes && !filter.eventTypes.includes(e.type as any)) return false;\n if (filter.fromSequence && e.metadata.sequenceNumber < filter.fromSequence) return false;\n if (filter.fromTimestamp && e.timestamp < filter.fromTimestamp) return false;\n if (filter.toTimestamp && e.timestamp > filter.toTimestamp) return false;\n if (filter.userId && e.userId !== filter.userId) return false;\n return true;\n });\n }\n}\n","/**\n * Storage URI Index\n *\n * Projection that maps file:// URIs → resourceIds.\n * Sharded at:\n * {projectionsDir}/storage-uri/{ab}/{cd}/{uri-hash}.json\n *\n * where {ab}/{cd} comes from jumpConsistentHash(uri) and\n * {uri-hash} is the SHA-256 of the URI string.\n *\n * Each file contains: { uri: string; resourceId: string }\n *\n * This index is maintained by ViewMaterializer (the single owner).\n * It is never modified by Stower or other actors.\n *\n * Archive/unarchive do NOT remove entries from this index.\n * Archived resources are marked in the ResourceView (archived: true)\n * but remain findable by URI.\n */\n\nimport { promises as fs } from 'fs';\nimport path from 'path';\nimport { getShardPath, sha256 } from './shard-utils';\n\nexport interface StorageUriEntry {\n uri: string;\n resourceId: string;\n}\n\n/**\n * Thrown when a URI is not found in the storage-uri index.\n */\nexport class ResourceNotFoundError extends Error {\n constructor(readonly uri: string) {\n super(`No resource found for URI: ${uri}`);\n this.name = 'ResourceNotFoundError';\n }\n}\n\n/**\n * Resolve a file:// URI to a resourceId using the storage-uri index.\n *\n * @param projectionsDir - Path to the projections directory\n * @param uri - file:// URI (e.g. \"file://docs/overview.md\")\n * @returns resourceId\n * @throws ResourceNotFoundError if URI is not in the index\n */\nexport async function resolveStorageUri(\n projectionsDir: string,\n uri: string,\n): Promise<string> {\n const entryPath = uriIndexPath(projectionsDir, uri);\n try {\n const raw = await fs.readFile(entryPath, 'utf-8');\n const entry: StorageUriEntry = JSON.parse(raw);\n return entry.resourceId;\n } catch (error: any) {\n if (error.code === 'ENOENT') {\n throw new ResourceNotFoundError(uri);\n }\n throw error;\n }\n}\n\n/**\n * Write a URI → resourceId mapping to the index.\n *\n * Called by ViewMaterializer when handling resource.created, resource.moved.\n *\n * @param projectionsDir - Path to the projections directory\n * @param uri - file:// URI\n * @param resourceId - resourceId to map to\n */\nexport async function writeStorageUriEntry(\n projectionsDir: string,\n uri: string,\n resourceId: string,\n): Promise<void> {\n const entryPath = uriIndexPath(projectionsDir, uri);\n await fs.mkdir(path.dirname(entryPath), { recursive: true });\n const entry: StorageUriEntry = { uri, resourceId };\n await fs.writeFile(entryPath, JSON.stringify(entry, null, 2));\n}\n\n/**\n * Remove a URI entry from the index.\n *\n * Called by ViewMaterializer when handling resource.moved (old URI only).\n * NOT called on resource.archived — archived resources retain their index entry.\n *\n * @param projectionsDir - Path to the projections directory\n * @param uri - file:// URI to remove\n */\nexport async function removeStorageUriEntry(\n projectionsDir: string,\n uri: string,\n): Promise<void> {\n const entryPath = uriIndexPath(projectionsDir, uri);\n try {\n await fs.unlink(entryPath);\n } catch (error: any) {\n if (error.code !== 'ENOENT') {\n throw error;\n }\n }\n}\n\n/**\n * Compute the filesystem path for a URI index entry.\n */\nfunction uriIndexPath(projectionsDir: string, uri: string): string {\n const uriHash = sha256(uri);\n const [ab, cd] = getShardPath(uri);\n return path.join(projectionsDir, 'storage-uri', ab, cd, `${uriHash}.json`);\n}\n","/**\n * View Materializer - Materialized View Management\n *\n * Materializes resource views from events:\n * - Full view materialization from scratch\n * - Incremental view updates\n * - System-level views (entity types)\n *\n * @see docs/EVENT-STORE.md#viewmaterializer for architecture details\n */\n\nimport { promises as fs } from 'fs';\nimport * as path from 'path';\nimport { didToAgent } from '@semiont/core';\nimport type { components } from '@semiont/core';\n\ntype Representation = components['schemas']['Representation'];\nimport type { Annotation } from '@semiont/core';\nimport type { ResourceDescriptor } from '@semiont/core';\n\nimport type {\n PersistedEvent,\n StoredEvent,\n ResourceAnnotations,\n ResourceId,\n Logger,\n} from '@semiont/core';\nimport { findBodyItem } from '@semiont/core';\nimport type { ViewStorage, ResourceView } from '../storage/view-storage';\nimport { writeStorageUriEntry, removeStorageUriEntry } from '../storage/storage-uri-index';\n\n/**\n * Minimal structural type for the event log dependency of `rebuildAll`.\n * Avoids importing the concrete EventLog class from a sibling directory and\n * keeps the materializer independent of the event-log implementation.\n */\nexport interface RebuildEventSource {\n getEvents(resourceId: ResourceId): Promise<StoredEvent[]>;\n getAllResourceIds(): Promise<ResourceId[]>;\n}\n\nexport interface ViewMaterializerConfig {\n basePath: string;\n}\n\n/**\n * ViewMaterializer builds and maintains materialized views from events\n */\nexport class ViewMaterializer {\n private logger?: Logger;\n\n constructor(\n private viewStorage: ViewStorage,\n private config: ViewMaterializerConfig,\n logger?: Logger\n ) {\n this.logger = logger;\n }\n\n /**\n * Materialize resource view from events\n * Loads existing view if cached, otherwise rebuilds from events\n */\n async materialize(events: StoredEvent[], resourceId: ResourceId): Promise<ResourceView | null> {\n // Try to load existing view\n const existing = await this.viewStorage.get(resourceId);\n if (existing) {\n return existing;\n }\n\n // No view exists - rebuild from events\n if (events.length === 0) return null;\n\n const view = this.materializeFromEvents(events, resourceId);\n\n // Save rebuilt view\n await this.viewStorage.save(resourceId, view);\n\n return view;\n }\n\n /**\n * Materialize view incrementally with a single event\n * Falls back to full rebuild if view doesn't exist\n */\n async materializeIncremental(\n resourceId: ResourceId,\n event: PersistedEvent,\n getAllEvents: () => Promise<StoredEvent[]>\n ): Promise<void> {\n this.logger?.info('[ViewMaterializer] Updating view for resource with event', { resourceId, eventType: event.type });\n\n // Try to load existing view\n let view = await this.viewStorage.get(resourceId);\n\n if (!view) {\n // No view exists - do full rebuild from all events\n this.logger?.info('[ViewMaterializer] No view found, rebuilding from scratch', { resourceId });\n const events = await getAllEvents();\n view = this.materializeFromEvents(events, resourceId);\n } else {\n // Apply single event incrementally to existing view\n this.logger?.info('[ViewMaterializer] Applying event incrementally to existing view', { resourceId, version: view.annotations.version });\n this.applyEventToResource(view.resource, event);\n this.applyEventToAnnotations(view.annotations, event);\n view.annotations.version++;\n view.annotations.updatedAt = event.timestamp;\n }\n\n // Save updated view\n await this.viewStorage.save(resourceId, view);\n this.logger?.info('[ViewMaterializer] View saved', { resourceId, version: view.annotations.version, annotationCount: view.annotations.annotations.length });\n\n // Update storage-uri index for URI-bearing events\n await this.materializeStorageUriIndex(resourceId, event);\n }\n\n /**\n * Update the storage-uri index in response to an event.\n *\n * Only yield:created (with storageUri), yield:moved, need index changes.\n * resource.archived / resource.unarchived do NOT modify the index.\n */\n private async materializeStorageUriIndex(resourceId: ResourceId, event: PersistedEvent): Promise<void> {\n const projectionsDir = path.join(this.config.basePath, 'projections');\n\n if (event.type === 'yield:created' && event.payload.storageUri) {\n await writeStorageUriEntry(projectionsDir, event.payload.storageUri, resourceId as string);\n } else if (event.type === 'yield:moved') {\n // Remove old URI, add new URI\n await removeStorageUriEntry(projectionsDir, event.payload.fromUri);\n await writeStorageUriEntry(projectionsDir, event.payload.toUri, resourceId as string);\n }\n }\n\n /**\n * Materialize view from event list (full rebuild)\n */\n private materializeFromEvents(events: StoredEvent[], resourceId: ResourceId): ResourceView {\n // Start with empty ResourceDescriptor state\n // @id uses bare resource ID; full URI is constructed at the API boundary\n const resource: ResourceDescriptor = {\n '@context': 'https://schema.org/',\n '@id': resourceId,\n name: '',\n representations: [],\n archived: false,\n entityTypes: [],\n creationMethod: 'api',\n };\n\n // Start with empty annotations\n const annotations: ResourceAnnotations = {\n resourceId,\n annotations: [],\n version: 0,\n updatedAt: '',\n };\n\n // Apply events in sequenceNumber order\n events.sort((a, b) => a.metadata.sequenceNumber - b.metadata.sequenceNumber);\n\n for (const storedEvent of events) {\n this.applyEventToResource(resource, storedEvent);\n this.applyEventToAnnotations(annotations, storedEvent);\n annotations.version++;\n annotations.updatedAt = storedEvent.timestamp;\n }\n\n return { resource, annotations };\n }\n\n /**\n * Apply an event to ResourceDescriptor state (metadata only)\n */\n private applyEventToResource(resource: ResourceDescriptor, event: PersistedEvent): void {\n switch (event.type) {\n case 'yield:created':\n resource.name = event.payload.name;\n resource.entityTypes = event.payload.entityTypes || [];\n resource.dateCreated = event.timestamp;\n resource.creationMethod = event.payload.creationMethod || 'api';\n resource.wasAttributedTo = didToAgent(event.userId);\n\n // Create representation from format and checksum\n if (!resource.representations) resource.representations = [];\n const reps = Array.isArray(resource.representations) ? resource.representations : [resource.representations];\n reps.push({\n mediaType: event.payload.format,\n checksum: event.payload.contentChecksum,\n byteSize: event.payload.contentByteSize,\n rel: 'original',\n language: event.payload.language,\n } as Representation);\n resource.representations = reps;\n\n // First-class fields\n resource.isDraft = event.payload.isDraft;\n if (event.payload.generatedFrom) resource.wasDerivedFrom = event.payload.generatedFrom.resourceId;\n if (event.payload.generator) resource.generator = event.payload.generator;\n\n // Working-tree URI and current checksum\n if (event.payload.storageUri) {\n resource.storageUri = event.payload.storageUri;\n }\n resource.currentChecksum = event.payload.contentChecksum;\n break;\n\n case 'yield:cloned':\n resource.name = event.payload.name;\n resource.entityTypes = event.payload.entityTypes || [];\n resource.dateCreated = event.timestamp;\n resource.creationMethod = 'clone';\n resource.sourceResourceId = event.payload.parentResourceId;\n resource.wasAttributedTo = didToAgent(event.userId);\n\n // Create representation from format and checksum\n if (!resource.representations) resource.representations = [];\n const reps2 = Array.isArray(resource.representations) ? resource.representations : [resource.representations];\n reps2.push({\n mediaType: event.payload.format,\n checksum: event.payload.contentChecksum,\n byteSize: event.payload.contentByteSize,\n rel: 'original',\n language: event.payload.language,\n } as Representation);\n resource.representations = reps2;\n break;\n\n case 'yield:updated':\n resource.currentChecksum = event.payload.contentChecksum;\n resource.dateModified = event.timestamp;\n break;\n\n case 'yield:moved':\n resource.storageUri = event.payload.toUri;\n resource.dateModified = event.timestamp;\n break;\n\n case 'mark:archived':\n resource.archived = true;\n break;\n\n case 'mark:unarchived':\n resource.archived = false;\n break;\n\n case 'yield:representation-added': {\n const { representation } = event.payload;\n\n // Add to representations array (avoid duplicates by checksum)\n if (!resource.representations) {\n resource.representations = [];\n }\n\n const repsArray = Array.isArray(resource.representations)\n ? resource.representations\n : [resource.representations];\n\n // Check if representation already exists\n const exists = repsArray.some(r => r.checksum === representation.checksum);\n if (!exists) {\n resource.representations = [...repsArray, representation];\n }\n break;\n }\n\n case 'yield:representation-removed': {\n const { checksum } = event.payload;\n\n if (resource.representations) {\n const repsArray = Array.isArray(resource.representations)\n ? resource.representations\n : [resource.representations];\n\n resource.representations = repsArray.filter(r => r.checksum !== checksum);\n }\n break;\n }\n\n case 'mark:entity-tag-added':\n if (!resource.entityTypes) resource.entityTypes = [];\n if (!resource.entityTypes.includes(event.payload.entityType)) {\n resource.entityTypes.push(event.payload.entityType);\n }\n break;\n\n case 'mark:entity-tag-removed':\n if (resource.entityTypes) {\n resource.entityTypes = resource.entityTypes.filter(\n (t: string) => t !== event.payload.entityType\n );\n }\n break;\n\n // Annotation events don't affect resource metadata\n case 'mark:added':\n case 'mark:removed':\n case 'mark:body-updated':\n break;\n\n // Job events don't affect resource metadata\n case 'job:started':\n case 'job:progress':\n case 'job:completed':\n case 'job:failed':\n break;\n\n // System events don't affect resource metadata\n case 'mark:entity-type-added':\n break;\n }\n }\n\n /**\n * Apply an event to ResourceAnnotations (annotation collections only)\n */\n private applyEventToAnnotations(annotations: ResourceAnnotations, event: PersistedEvent): void {\n switch (event.type) {\n case 'mark:added':\n annotations.annotations.push(event.payload.annotation);\n break;\n\n case 'mark:removed':\n annotations.annotations = annotations.annotations.filter(\n (a: Annotation) => a.id !== event.payload.annotationId\n );\n break;\n\n case 'mark:body-updated':\n const annotation = annotations.annotations.find((a: Annotation) =>\n a.id === event.payload.annotationId\n );\n if (annotation) {\n // Ensure body is an array\n if (!Array.isArray(annotation.body)) {\n annotation.body = annotation.body ? [annotation.body] : [];\n }\n\n // Apply each operation\n for (const op of event.payload.operations) {\n if (op.op === 'add') {\n // Add item (idempotent - don't add if already exists)\n const exists = findBodyItem(annotation.body, op.item) !== -1;\n if (!exists) {\n annotation.body.push(op.item);\n }\n } else if (op.op === 'remove') {\n // Remove item\n const index = findBodyItem(annotation.body, op.item);\n if (index !== -1) {\n annotation.body.splice(index, 1);\n }\n } else if (op.op === 'replace') {\n // Replace item\n const index = findBodyItem(annotation.body, op.oldItem);\n if (index !== -1) {\n annotation.body[index] = op.newItem;\n }\n }\n }\n\n // Update modified timestamp\n annotation.modified = new Date(event.timestamp).toISOString();\n }\n break;\n\n // Resource metadata events don't affect annotations\n case 'yield:created':\n case 'yield:cloned':\n case 'yield:updated':\n case 'yield:moved':\n case 'mark:archived':\n case 'mark:unarchived':\n case 'yield:representation-added':\n case 'yield:representation-removed':\n case 'mark:entity-tag-added':\n case 'mark:entity-tag-removed':\n break;\n\n // Job events don't affect annotations\n case 'job:started':\n case 'job:progress':\n case 'job:completed':\n case 'job:failed':\n break;\n\n // System events don't affect annotations\n case 'mark:entity-type-added':\n break;\n }\n }\n\n /**\n * Walk every event stream in the event log and materialize the corresponding\n * view from scratch. Idempotent: existing view files are overwritten.\n *\n * Mirrors GraphDBConsumer.rebuildAll() and Smelter.rebuildAll() — this is the\n * recovery path that makes the ephemeral stateDir safe to wipe. The live\n * append path (EventStore.appendEvent → materializeIncremental /\n * materializeEntityTypes) is unchanged and runs in addition.\n */\n async rebuildAll(eventLog: RebuildEventSource): Promise<void> {\n this.logger?.info('[ViewMaterializer] Rebuilding all materialized views from event log');\n\n const SYSTEM_ID = '__system__' as unknown as ResourceId;\n\n // Pass 1: __system__ events — produces system projections\n // (currently entitytypes.json; future system projections plug in here)\n const systemEvents = await eventLog.getEvents(SYSTEM_ID);\n this.logger?.info('[ViewMaterializer] Replaying system events', { count: systemEvents.length });\n for (const event of systemEvents) {\n if (event.type === 'mark:entity-type-added') {\n await this.materializeEntityTypes((event.payload as { entityType: string }).entityType);\n }\n }\n\n // Pass 2: resource-scoped events — produces resource views and the\n // storage-uri index\n const allResourceIds = await eventLog.getAllResourceIds();\n const resourceIds = allResourceIds.filter(\n (rid) => (rid as unknown as string) !== '__system__'\n );\n this.logger?.info('[ViewMaterializer] Rebuilding resource views', { count: resourceIds.length });\n let skipped = 0;\n for (const rid of resourceIds) {\n try {\n const events = await eventLog.getEvents(rid);\n if (events.length === 0) continue;\n\n const view = this.materializeFromEvents(events, rid);\n await this.viewStorage.save(rid, view);\n\n for (const event of events) {\n await this.materializeStorageUriIndex(rid, event);\n }\n } catch (error) {\n skipped++;\n this.logger?.error('[ViewMaterializer] Failed to rebuild resource view', {\n resourceId: String(rid),\n error: error instanceof Error ? error.message : String(error),\n });\n }\n }\n\n this.logger?.info('[ViewMaterializer] Rebuild complete', {\n systemEvents: systemEvents.length,\n resources: resourceIds.length,\n skipped,\n });\n }\n\n /**\n * Materialize entity types view - System-level view\n */\n async materializeEntityTypes(entityType: string): Promise<void> {\n const entityTypesPath = path.join(\n this.config.basePath,\n 'projections',\n '__system__',\n 'entitytypes.json'\n );\n\n\n // Read current view\n let view = { entityTypes: [] as string[] };\n try {\n const content = await fs.readFile(entityTypesPath, 'utf-8');\n view = JSON.parse(content);\n } catch (error: any) {\n if (error.code !== 'ENOENT') throw error;\n // File doesn't exist - will create it\n }\n\n // Add entity type (idempotent - Set ensures uniqueness)\n const entityTypeSet = new Set(view.entityTypes);\n entityTypeSet.add(entityType);\n view.entityTypes = Array.from(entityTypeSet).sort();\n\n // Write view\n await fs.mkdir(path.dirname(entityTypesPath), { recursive: true });\n await fs.writeFile(entityTypesPath, JSON.stringify(view, null, 2));\n }\n}\n","/**\n * ViewManager - Materialized View Management Layer\n *\n * Single Responsibility: View updates only\n * - Updates resource views from events\n * - Updates system views (entity types)\n * - Rebuilds views when needed\n *\n * Does NOT handle:\n * - Event persistence (see EventLog)\n * - Pub/sub notifications (see EventBus)\n */\n\nimport { type ResourceId, type PersistedEvent, type StoredEvent, type Logger, serializePerKey } from '@semiont/core';\nimport { ViewMaterializer, type ViewMaterializerConfig, type RebuildEventSource } from './views/view-materializer';\nimport type { ViewStorage, ResourceView } from './storage/view-storage';\n\nexport interface ViewManagerConfig {\n basePath: string;\n}\n\n/**\n * ViewManager wraps ViewMaterializer with a clean API\n * Handles both resource and system-level views\n *\n * ## Per-resource serialization\n *\n * `materializeResource` runs read-modify-write cycles on the view file for\n * a given resource (load JSON → apply event → save JSON). When multiple\n * events arrive for the same resource in rapid succession — the canonical\n * example is the reference-detection worker emitting `mark:added` +\n * `job:progress` + `job:completed` within a few milliseconds — concurrent\n * RMW cycles will clobber each other, losing events and occasionally\n * corrupting the view file entirely.\n *\n * ViewManager serializes these via `serializePerKey` from `@semiont/core`:\n * each incoming `materializeResource` call chains onto the previous one\n * for the same `resourceId`, so the work runs strictly sequentially per\n * resource while still parallelizing across different resources. System\n * events go through their own shared chain (keyed by a sentinel).\n *\n * Why this shape and not RxJS `groupBy + concatMap`:\n * ViewManager is called **synchronously** by `EventStore.appendEvent` — it\n * must block the caller until the view is written, so SSE subscribers\n * that see the subsequently-published event get the up-to-date view (a\n * read-your-writes guarantee). The RxJS stream-consumer pattern used by\n * `Smelter`, `GraphDBConsumer`, and `Gatherer` can't provide that\n * guarantee because it's fire-and-forget from the publisher's perspective.\n * Both patterns solve \"serialize work per resource\" — see also\n * `packages/core/src/serialize-per-key.ts` for the shared primitive.\n */\nexport class ViewManager {\n // Expose materializer for direct access to view methods\n readonly materializer: ViewMaterializer;\n\n // Per-resource write serialization. Keyed by the string form of ResourceId;\n // values are promise tails in the in-flight chain for each resource.\n // Entries are removed once the chain empties — see `serializePerKey`.\n private resourceChains = new Map<string, Promise<void>>();\n\n // Shared chain for system-level views (entity types, etc.). A single\n // sentinel key serializes all system-level writes; these events are\n // rare and global, so per-type keying buys nothing.\n private systemChains = new Map<symbol, Promise<void>>();\n private static readonly SYSTEM_KEY = Symbol('system');\n\n constructor(\n viewStorage: ViewStorage,\n config: ViewManagerConfig,\n logger?: Logger\n ) {\n const materializerConfig: ViewMaterializerConfig = {\n basePath: config.basePath,\n };\n this.materializer = new ViewMaterializer(viewStorage, materializerConfig, logger?.child({ component: 'ViewMaterializer' }));\n }\n\n /**\n * Update resource view with a new event.\n * Serialized per resource — see class doc.\n *\n * @param resourceId - Branded ResourceId (from @semiont/core)\n * @param event - Resource event (from @semiont/core)\n * @param getAllEvents - Function to retrieve all events for rebuild if needed\n */\n async materializeResource(\n resourceId: ResourceId,\n event: PersistedEvent,\n getAllEvents: () => Promise<StoredEvent[]>\n ): Promise<void> {\n await serializePerKey(String(resourceId), this.resourceChains, () =>\n this.materializer.materializeIncremental(resourceId, event, getAllEvents),\n );\n }\n\n /**\n * Update system-level view (currently only entity types).\n * Serialized through a shared chain — see class doc.\n */\n async materializeSystem(eventType: string, payload: any): Promise<void> {\n await serializePerKey(ViewManager.SYSTEM_KEY, this.systemChains, async () => {\n if (eventType === 'mark:entity-type-added') {\n await this.materializer.materializeEntityTypes(payload.entityType);\n }\n // Future system views can be added here\n });\n }\n\n /**\n * Rebuild all materialized views from the event log on startup.\n * Mirrors GraphDBConsumer.rebuildAll() — call this once during\n * createKnowledgeBase before the HTTP server begins accepting requests.\n * Idempotent: existing view files are overwritten.\n */\n async rebuildAll(eventLog: RebuildEventSource): Promise<void> {\n return this.materializer.rebuildAll(eventLog);\n }\n\n /**\n * Get resource view (builds from events if needed)\n * @param resourceId - Branded ResourceId (from @semiont/core)\n * @param events - Stored events for the resource (from @semiont/core)\n * @returns Resource view or null if no events\n */\n async getOrMaterialize(\n resourceId: ResourceId,\n events: StoredEvent[]\n ): Promise<ResourceView | null> {\n return this.materializer.materialize(events, resourceId);\n }\n}\n","/**\n * EventStore - Orchestration Layer\n *\n * Coordinates event sourcing operations:\n * - EventLog: Event persistence (append, retrieve, query)\n * - ViewManager: View materialization (resource and system)\n * - Core EventBus: Publishes StoredEvent to typed channels after persistence\n *\n * appendEvent() is the single write path:\n * 1. Persist to EventLog\n * 2. Materialize views\n * 3. Enrich (optional callback — attach post-materialization data)\n * 4. Publish StoredEvent to global and resource-scoped typed channels\n */\n\nimport type {\n EventInput,\n StoredEvent,\n ResourceId,\n Logger,\n} from '@semiont/core';\nimport { EventBus as CoreEventBus } from '@semiont/core';\nimport type { SemiontProject } from '@semiont/core/node';\nimport type { ViewStorage } from './storage/view-storage';\nimport { EventLog } from './event-log';\nimport { ViewManager, type ViewManagerConfig } from './view-manager';\n\nexport type EnrichEvent = (event: StoredEvent, resourceId: ResourceId) => Promise<StoredEvent>;\n\nexport class EventStore {\n readonly log: EventLog;\n readonly views: ViewManager;\n readonly viewStorage: ViewStorage;\n readonly coreEventBus: CoreEventBus;\n private enrichEvent: EnrichEvent | null = null;\n\n constructor(\n project: SemiontProject,\n stateDir: string,\n viewStorage: ViewStorage,\n coreEventBus: CoreEventBus,\n logger?: Logger\n ) {\n this.viewStorage = viewStorage;\n this.coreEventBus = coreEventBus;\n\n this.log = new EventLog({ project }, logger?.child({ component: 'EventLog' }));\n\n const viewConfig: ViewManagerConfig = {\n basePath: stateDir,\n };\n this.views = new ViewManager(viewStorage, viewConfig, logger?.child({ component: 'ViewManager' }));\n }\n\n setEnrichEvent(fn: EnrichEvent): void {\n this.enrichEvent = fn;\n }\n\n /**\n * Append an event to the store\n * Coordinates: persistence → view → enrich → notification\n *\n * @param options.correlationId - Optional id propagated from a command.\n */\n async appendEvent(\n event: EventInput,\n options?: { correlationId?: string },\n ): Promise<StoredEvent> {\n const resourceId: ResourceId | '__system__' = event.resourceId || '__system__';\n\n // 1. Persist event to log\n const storedEvent = await this.log.append(event, resourceId as any, options);\n\n // 2. Update views\n if (resourceId === '__system__') {\n await this.views.materializeSystem(\n storedEvent.type,\n storedEvent.payload\n );\n } else {\n await this.views.materializeResource(\n resourceId as ResourceId,\n storedEvent,\n () => this.log.getEvents(resourceId as ResourceId)\n );\n }\n\n // 3. Enrich (attach post-materialization data like annotations)\n let publishEvent = storedEvent;\n if (this.enrichEvent && resourceId !== '__system__') {\n publishEvent = await this.enrichEvent(storedEvent, resourceId as ResourceId);\n }\n\n // 4. Publish to Core EventBus typed channels\n this.coreEventBus.getDomainEvent(publishEvent.type).next(publishEvent);\n\n if (resourceId !== '__system__') {\n const scopedBus = this.coreEventBus.scope(resourceId as string);\n scopedBus.getDomainEvent(publishEvent.type).next(publishEvent);\n }\n\n return storedEvent;\n }\n}\n","/**\n * View Storage - Materialized Views\n *\n * Stores materialized views of resource state and annotations\n * Built from event streams, can be rebuilt at any time\n *\n * Stores both ResourceDescriptor metadata and ResourceAnnotations, but keeps them logically separate\n */\n\nimport { promises as fs } from 'fs';\nimport * as path from 'path';\nimport { getShardPath } from './shard-utils';\nimport type { SemiontProject } from '@semiont/core/node';\nimport type { ResourceAnnotations, ResourceDescriptor, ResourceId, Logger } from '@semiont/core';\n\n// Complete state for a resource in materialized view (metadata + annotations)\nexport interface ResourceView {\n resource: ResourceDescriptor;\n annotations: ResourceAnnotations;\n}\n\nexport interface ViewStorage {\n save(resourceId: ResourceId, view: ResourceView): Promise<void>;\n get(resourceId: ResourceId): Promise<ResourceView | null>;\n delete(resourceId: ResourceId): Promise<void>;\n exists(resourceId: ResourceId): Promise<boolean>;\n getAll(): Promise<ResourceView[]>;\n}\n\nexport class FilesystemViewStorage implements ViewStorage {\n private basePath: string;\n private logger?: Logger;\n\n constructor(project: SemiontProject, logger?: Logger) {\n this.logger = logger;\n this.basePath = project.stateDir;\n }\n\n private getProjectionPath(resourceId: ResourceId): string {\n // Use 4-hex Jump Consistent Hash sharding (65,536 shards)\n const [ab, cd] = getShardPath(resourceId);\n return path.join(this.basePath, 'resources', ab, cd, `${resourceId}.json`);\n }\n\n async save(resourceId: ResourceId, projection: ResourceView): Promise<void> {\n const projPath = this.getProjectionPath(resourceId);\n const projDir = path.dirname(projPath);\n\n // Ensure shard directory exists\n await fs.mkdir(projDir, { recursive: true });\n\n // Atomic write: write to a sibling temp file and rename into place.\n // `fs.writeFile` on its own truncates the target to 0 bytes before\n // writing, so a concurrent reader can observe an empty file and\n // get a `JSON.parse('')` SyntaxError mid-write. `rename` is atomic\n // on POSIX, so readers always see either the old or new content,\n // never a partial one.\n const tmpPath = `${projPath}.${process.pid}.${Date.now()}.tmp`;\n await fs.writeFile(tmpPath, JSON.stringify(projection, null, 2), 'utf-8');\n try {\n await fs.rename(tmpPath, projPath);\n } catch (error) {\n await fs.unlink(tmpPath).catch(() => {});\n throw error;\n }\n }\n\n async get(resourceId: ResourceId): Promise<ResourceView | null> {\n const projPath = this.getProjectionPath(resourceId);\n\n try {\n const content = await fs.readFile(projPath, 'utf-8');\n return JSON.parse(content) as ResourceView;\n } catch (error: any) {\n if (error.code === 'ENOENT') {\n return null;\n }\n // Don't delete on SyntaxError — the old code unlinked the file,\n // which turned a transient race (read-during-write with the\n // pre-atomic `fs.writeFile`) into a permanent \"view missing\"\n // that the next materializer write had to repair from scratch.\n // With atomic `rename` in `save`, SyntaxError should only fire\n // on genuine corruption; either way, the next incremental\n // update will overwrite the file with a good view, so we just\n // log and treat as missing.\n if (error instanceof SyntaxError) {\n this.logger?.error('[ViewStorage] Corrupted view file, treating as missing', {\n resourceId,\n path: projPath,\n error: error.message,\n });\n return null;\n }\n throw error;\n }\n }\n\n async delete(resourceId: ResourceId): Promise<void> {\n const projPath = this.getProjectionPath(resourceId);\n\n try {\n await fs.unlink(projPath);\n } catch (error: any) {\n if (error.code !== 'ENOENT') {\n throw error;\n }\n // Ignore if file doesn't exist\n }\n }\n\n async exists(resourceId: ResourceId): Promise<boolean> {\n const projPath = this.getProjectionPath(resourceId);\n\n try {\n await fs.access(projPath);\n return true;\n } catch {\n return false;\n }\n }\n\n async getAll(): Promise<ResourceView[]> {\n const views: ResourceView[] = [];\n const annotationsPath = path.join(this.basePath, 'resources');\n\n try {\n // Recursively walk through all shard directories\n const walkDir = async (dir: string): Promise<void> => {\n const entries = await fs.readdir(dir, { withFileTypes: true });\n\n for (const entry of entries) {\n const fullPath = path.join(dir, entry.name);\n\n if (entry.isDirectory()) {\n await walkDir(fullPath);\n } else if (entry.isFile() && entry.name.endsWith('.json')) {\n try {\n const content = await fs.readFile(fullPath, 'utf-8');\n const view = JSON.parse(content) as ResourceView;\n views.push(view);\n } catch (error) {\n this.logger?.error('[ViewStorage] Failed to read view', { path: fullPath, error });\n // Skip invalid view files\n }\n }\n }\n };\n\n await walkDir(annotationsPath);\n } catch (error: any) {\n if (error.code === 'ENOENT') {\n // Views directory doesn't exist yet\n return [];\n }\n throw error;\n }\n\n return views;\n }\n}","/**\n * Event Store Factory\n *\n * Factory function for creating EventStore instances with standard configuration.\n * This is the canonical way to instantiate an EventStore.\n */\n\nimport type { SemiontProject } from '@semiont/core/node';\nimport type { EventBus as CoreEventBus, Logger } from '@semiont/core';\nimport { EventStore } from './event-store';\nimport { FilesystemViewStorage } from './storage/view-storage';\n\n/**\n * Create and initialize an EventStore instance\n *\n * @param project - SemiontProject instance\n * @param eventBus - @semiont/core EventBus for publishing domain events\n * @param logger - Optional logger for structured logging\n * @returns Configured EventStore instance ready for use\n */\nexport function createEventStore(\n project: SemiontProject,\n eventBus: CoreEventBus,\n logger?: Logger\n): EventStore {\n const viewStorage = new FilesystemViewStorage(project, logger?.child({ component: 'view-storage' }));\n\n return new EventStore(\n project,\n project.stateDir,\n viewStorage,\n eventBus,\n logger\n );\n}\n","/**\n * Event Query - Read Operations\n *\n * Handles querying and reading events from storage:\n * - Query events with filters (type, user, timestamp, sequence)\n * - Get all events for a resource\n * - Get last event from a file\n * - Efficient streaming reads from JSONL files\n *\n * @see docs/EVENT-STORE.md#eventquery for architecture details\n */\n\nimport type { StoredEvent, EventQuery as EventQueryType, ResourceId } from '@semiont/core';\nimport type { EventStorage } from '../storage/event-storage';\n\n/**\n * EventQuery handles all read operations for events\n * Uses EventStorage for file access, adds query filtering\n */\nexport class EventQuery {\n constructor(private eventStorage: EventStorage) {}\n\n /**\n * Query events with filters\n * Supports filtering by: userId, eventTypes, timestamps, sequence number, limit\n */\n async queryEvents(query: EventQueryType): Promise<StoredEvent[]> {\n if (!query.resourceId) {\n throw new Error('resourceId is required for event queries');\n }\n\n // Get all events from storage\n const allEvents = await this.eventStorage.getAllEvents(query.resourceId);\n\n // Apply filters\n let results = allEvents;\n\n if (query.userId) {\n results = results.filter(e => e.userId === query.userId);\n }\n\n if (query.eventTypes && query.eventTypes.length > 0) {\n results = results.filter(e => query.eventTypes!.includes(e.type));\n }\n\n if (query.fromTimestamp) {\n results = results.filter(e => e.timestamp >= query.fromTimestamp!);\n }\n\n if (query.toTimestamp) {\n results = results.filter(e => e.timestamp <= query.toTimestamp!);\n }\n\n if (query.fromSequence) {\n results = results.filter(e => e.metadata.sequenceNumber >= query.fromSequence!);\n }\n\n // Apply limit\n if (query.limit && query.limit > 0) {\n results = results.slice(0, query.limit);\n }\n\n return results;\n }\n\n /**\n * Get all events for a specific resource (no filters)\n */\n async getResourceEvents(resourceId: ResourceId): Promise<StoredEvent[]> {\n return this.eventStorage.getAllEvents(resourceId);\n }\n\n /**\n * Get the last event from a specific file\n * Useful for initializing sequence numbers and last hashes\n */\n async getLastEvent(resourceId: ResourceId, filename: string): Promise<StoredEvent | null> {\n return this.eventStorage.getLastEvent(resourceId, filename);\n }\n\n /**\n * Get the latest event for a resource across all files\n */\n async getLatestEvent(resourceId: ResourceId): Promise<StoredEvent | null> {\n const files = await this.eventStorage.getEventFiles(resourceId);\n if (files.length === 0) return null;\n\n // Check files in reverse order (newest first)\n for (let i = files.length - 1; i >= 0; i--) {\n const file = files[i];\n if (!file) continue;\n const lastEvent = await this.eventStorage.getLastEvent(resourceId, file);\n if (lastEvent) return lastEvent;\n }\n\n return null;\n }\n\n /**\n * Get event count for a resource\n */\n async getEventCount(resourceId: ResourceId): Promise<number> {\n const events = await this.getResourceEvents(resourceId);\n return events.length;\n }\n\n /**\n * Check if a resource has any events\n */\n async hasEvents(resourceId: ResourceId): Promise<boolean> {\n const files = await this.eventStorage.getEventFiles(resourceId);\n return files.length > 0;\n }\n}\n","/**\n * Identifier utilities for event sourcing\n */\n\nimport { nanoid } from 'nanoid';\n\n/**\n * Generate a unique annotation ID (bare nanoid)\n *\n * @returns A bare annotation ID (e.g., \"V1StGXR8_Z5jdHi6B-myT\")\n */\nexport function generateAnnotationId(): string {\n return nanoid(21);\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@semiont/event-sourcing",
3
- "version": "0.4.21",
3
+ "version": "0.5.0",
4
4
  "description": "Event sourcing infrastructure for Semiont - EventLog, EventBus, and ViewManager",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",