Awesome-claude-code create-event-store
Generates Event Store pattern for PHP 8.4. Creates event sourcing storage infrastructure with event streams, stored events, optimistic locking, and version tracking. Includes unit tests.
install
source · Clone the upstream repo
git clone https://github.com/dykyi-roman/awesome-claude-code
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/dykyi-roman/awesome-claude-code "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/create-event-store" ~/.claude/skills/dykyi-roman-awesome-claude-code-create-event-store && rm -rf "$T"
manifest:
skills/create-event-store/SKILL.mdsource content
Event Store Generator
Creates Event Store infrastructure for event sourcing with aggregate history and event replay.
When to Use
| Scenario | Example |
|---|---|
| Event sourcing | Aggregate state from events |
| Audit trail | Complete change history |
| Event replay | Rebuild projections from events |
| Temporal queries | Query state at any point in time |
Component Characteristics
StoredEvent
- Immutable event wrapper
- Contains aggregate metadata (id, type, version)
- Serialized payload
- Creation timestamp
EventStream
- Ordered collection of stored events
- Implements IteratorAggregate
- Tracks current version
- Supports appending new events
EventStoreInterface
- Append events with optimistic locking
- Load full event stream for aggregate
- Load events from specific version
- Stream-based reading for large aggregates
Generation Process
Step 1: Generate Domain Components
Path:
src/Domain/{BoundedContext}/EventStore/
— Immutable stored event value objectStoredEvent.php
— Event stream contractEventStreamInterface.php
— Event stream implementationEventStream.php
— Event store contractEventStoreInterface.php
Step 2: Generate Infrastructure
Path:
src/Infrastructure/{BoundedContext}/EventStore/
— Doctrine DBAL implementation with optimistic lockingDoctrineEventStore.php- Database migration SQL
Step 3: Generate Tests
— Stored event immutability testsStoredEventTest.php
— Stream operations testsEventStreamTest.php
— Integration testsDoctrineEventStoreTest.php
File Placement
| Component | Path |
|---|---|
| StoredEvent | |
| EventStream | |
| EventStoreInterface | |
| DoctrineEventStore | |
| Unit Tests | |
| Integration Tests | |
Naming Conventions
| Component | Pattern | Example |
|---|---|---|
| Stored Event | | |
| Stream Interface | | |
| Stream | | |
| Store Interface | | |
| Store Impl | | |
| Exception | | |
| Test | | |
Quick Template Reference
StoredEvent
final readonly class StoredEvent { public function __construct( public string $aggregateId, public string $aggregateType, public string $eventType, public string $payload, public int $version, public \DateTimeImmutable $createdAt ) {} public static function fromDomainEvent(string $aggregateId, string $aggregateType, int $version, object $event): self; public function toArray(): array; public static function fromArray(array $data): self; }
EventStoreInterface
interface EventStoreInterface { public function append(string $aggregateId, EventStream $events, int $expectedVersion): void; public function load(string $aggregateId): EventStream; public function loadFromVersion(string $aggregateId, int $fromVersion): EventStream; }
EventStream
final class EventStream implements \IteratorAggregate, \Countable { public static function empty(): self; public static function fromEvents(array $events): self; public function append(StoredEvent $event): self; public function getVersion(): int; public function isEmpty(): bool; public function getIterator(): \ArrayIterator; public function count(): int; }
Usage Example
// Append events $events = EventStream::fromEvents([ StoredEvent::fromDomainEvent($orderId, 'Order', 1, $orderCreated), StoredEvent::fromDomainEvent($orderId, 'Order', 2, $itemAdded), ]); $eventStore->append($orderId, $events, expectedVersion: 0); // Load and replay $stream = $eventStore->load($orderId); foreach ($stream as $event) { $aggregate->apply($event); }
Database Schema
CREATE TABLE event_store ( id BIGINT AUTO_INCREMENT PRIMARY KEY, aggregate_id VARCHAR(36) NOT NULL, aggregate_type VARCHAR(255) NOT NULL, event_type VARCHAR(255) NOT NULL, payload JSON NOT NULL, version INT NOT NULL, created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, UNIQUE INDEX idx_aggregate_version (aggregate_id, version), INDEX idx_aggregate_type (aggregate_type), INDEX idx_event_type (event_type), INDEX idx_created_at (created_at) );
Anti-patterns to Avoid
| Anti-pattern | Problem | Solution |
|---|---|---|
| Mutable Events | History changes | Immutable StoredEvent |
| Missing Version | No optimistic locking | Version per aggregate |
| No Idempotency | Duplicate appends | Unique aggregate_id + version |
| Large Payloads | Slow reads | Serialize only essential data |
| No Snapshots | Slow rebuilds for long streams | Use create-snapshot |
| Global Stream Only | Can't load per-aggregate | Per-aggregate stream support |
References
For complete PHP templates and examples, see:
— StoredEvent, EventStream, EventStoreInterface, DoctrineEventStore templatesreferences/templates.md
— Order event store usage and testsreferences/examples.md