Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
5dffc21
Add ruby_event_store-cli gem skeleton
tomaszpatrzek Apr 22, 2026
38ea9c0
Add EventStoreResolver for CLI connection setup
tomaszpatrzek Apr 22, 2026
21dc696
Add command routing with dry-cli registry
tomaszpatrzek Apr 22, 2026
71ffcbd
Implement stream events command
tomaszpatrzek Apr 22, 2026
cb39f3e
Add filtering options to stream events command
tomaszpatrzek Apr 22, 2026
d431d16
Show friendly error message for unknown event type
tomaszpatrzek Apr 22, 2026
5399143
Add --follow / -f flag to res stream events
tomaszpatrzek Apr 22, 2026
6f279dd
Implement res stream show command
tomaszpatrzek Apr 22, 2026
bcb2524
Implement res event show command
tomaszpatrzek Apr 22, 2026
e06f693
Implement res event streams command
tomaszpatrzek Apr 22, 2026
bf1a93b
Implement res trace command
tomaszpatrzek Apr 22, 2026
a60ff22
Implement res search command with shared EventRenderer
tomaszpatrzek Apr 22, 2026
75578a9
Implement res stats command
tomaszpatrzek Apr 22, 2026
f5a0d58
Show unique event types in res stats
tomaszpatrzek Apr 22, 2026
422ff74
Implement res watch command — live event view grouped by namespace
tomaszpatrzek Apr 22, 2026
c84a981
Add Makefile and clean up Gemfile
tomaszpatrzek Apr 22, 2026
b2b1a31
Add CI workflow for ruby_event_store-cli
tomaszpatrzek Apr 22, 2026
74870e7
Add mutant config
tomaszpatrzek Apr 22, 2026
e433e98
Add README
tomaszpatrzek Apr 22, 2026
35a1e2f
Improve command descriptions and add namespace subcommand hints
tomaszpatrzek Apr 22, 2026
2764a77
Add missing platforms to Gemfile.lock
tomaszpatrzek Apr 22, 2026
eec0777
Move event store resolution to bin/res, remove EventStoreResolver
tomaszpatrzek Apr 23, 2026
3e3edb9
Extract Base command class with event_store private method
tomaszpatrzek Apr 23, 2026
c54933a
Read event store from Rails.configuration instead of global constant
tomaszpatrzek Apr 23, 2026
36a682a
Extract named methods in Watch#prepare
tomaszpatrzek Apr 23, 2026
ba3b86a
Remove Follow command accidentally added during Watch rename
tomaszpatrzek Apr 23, 2026
ab173a5
Extract watch loop into private method in Watch command
tomaszpatrzek Apr 23, 2026
627605e
Refactor Watch#render into named helper methods
tomaszpatrzek Apr 23, 2026
ceee4ee
Guard against missing config/environment.rb with a friendly error
tomaszpatrzek Apr 23, 2026
f36ca3d
Add integration specs covering all CLI commands via Dry::CLI dispatch
tomaszpatrzek Apr 23, 2026
801c28b
Refactor StreamEvents#call into build_reader and tail methods
tomaszpatrzek Apr 23, 2026
d18b3ea
Extract print_event method in EventShow command
tomaszpatrzek Apr 23, 2026
f9b8305
Extract streams_of private method in EventStreams command
tomaszpatrzek Apr 23, 2026
ae4e0e2
Extract ReadEvents class with self.of(specification, ...) for shared …
tomaszpatrzek Apr 23, 2026
e7b9cf9
Refactor Stats#call into print_stats and print_event_types methods
tomaszpatrzek Apr 23, 2026
8c74b7c
Use ReadEvents.of in tail, make limit optional
tomaszpatrzek Apr 23, 2026
9b19e67
Refactor StreamShow#call into print_stream method
tomaszpatrzek Apr 23, 2026
7bd166e
Refactor Trace#call into events_for, print_causation_tree, root_event…
tomaszpatrzek Apr 23, 2026
37fa1d1
Rename test event classes to past tense convention
tomaszpatrzek Apr 23, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 55 additions & 0 deletions .github/workflows/ruby_event_store-cli_test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
name: ruby_event_store-cli_test
on:
workflow_dispatch:
repository_dispatch:
types:
- script
push:
branches:
- master
paths:
- contrib/ruby_event_store-cli/**
- ".github/workflows/ruby_event_store-cli_test.yml"
- support/**
- "!support/bundler/**"
- "!support/ci/**"
pull_request:
paths:
- contrib/ruby_event_store-cli/**
- ".github/workflows/ruby_event_store-cli_test.yml"
- support/**
- "!support/bundler/**"
- "!support/ci/**"
jobs:
test:
runs-on: ubuntu-latest
timeout-minutes: 120
env:
WORKING_DIRECTORY: contrib/ruby_event_store-cli
RUBY_VERSION: "${{ matrix.ruby_version }}"
BUNDLE_GEMFILE: "${{ matrix.bundle_gemfile }}"
strategy:
fail-fast: false
matrix:
include:
- ruby_version: ruby-3.4
bundle_gemfile: Gemfile
- ruby_version: ruby-3.3
bundle_gemfile: Gemfile
- ruby_version: ruby-3.2
bundle_gemfile: Gemfile
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 1
- run: test -e ${{ env.BUNDLE_GEMFILE }}.lock
working-directory: "${{ env.WORKING_DIRECTORY }}"
- uses: ruby/setup-ruby@v1
with:
ruby-version: "${{ env.RUBY_VERSION }}"
bundler-cache: true
working-directory: "${{ env.WORKING_DIRECTORY }}"
- run: make test
working-directory: "${{ env.WORKING_DIRECTORY }}"
env:
RUBYOPT: "--enable-frozen-string-literal"
16 changes: 16 additions & 0 deletions contrib/ruby_event_store-cli/.mutant.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# https://github.com/mbj/mutant/blob/master/docs/configuration.md

usage: opensource
requires:
- ruby_event_store/cli
includes:
- lib
integration:
name: rspec
mutation:
operators: light
coverage_criteria:
process_abort: true
matcher:
subjects:
- RubyEventStore::CLI*
8 changes: 8 additions & 0 deletions contrib/ruby_event_store-cli/Gemfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# frozen_string_literal: true

source "https://rubygems.org"
gemspec

eval_gemfile "../../support/bundler/Gemfile.shared"

gem "ruby_event_store", path: "../../ruby_event_store"
104 changes: 104 additions & 0 deletions contrib/ruby_event_store-cli/Gemfile.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
PATH
remote: ../../ruby_event_store
specs:
ruby_event_store (2.18.0)
concurrent-ruby (~> 1.0, >= 1.1.6)

PATH
remote: .
specs:
ruby_event_store-cli (0.1.0)
dry-cli (>= 1.0)
ruby_event_store (>= 1.0.0)

GEM
remote: https://rubygems.org/
specs:
ast (2.4.3)
concurrent-ruby (1.3.6)
date (3.5.1)
diff-lcs (1.6.2)
drb (2.2.3)
dry-cli (1.4.1)
erb (6.0.2)
io-console (0.8.2)
irb (1.17.0)
pp (>= 0.6.0)
prism (>= 1.3.0)
rdoc (>= 4.0.0)
reline (>= 0.4.2)
minitest (6.0.2)
drb (~> 2.0)
prism (~> 1.5)
mutant (0.15.1)
diff-lcs (>= 1.6, < 3)
irb (~> 1.15)
parser (~> 3.3.10)
regexp_parser (~> 2.10)
sorbet-runtime (~> 0.6.0)
unparser (~> 0.8.2)
mutant-minitest (0.15.1)
minitest (>= 5.11, < 7)
mutant (= 0.15.1)
mutex_m (~> 0.2)
mutant-rspec (0.15.1)
mutant (= 0.15.1)
rspec-core (>= 3.8.0, < 5.0.0)
mutex_m (0.3.0)
parser (3.3.10.2)
ast (~> 2.4.1)
racc
pp (0.6.3)
prettyprint
prettyprint (0.2.0)
prism (1.9.0)
psych (5.3.1)
date
stringio
racc (1.8.1)
rake (13.3.1)
rdoc (7.2.0)
erb
psych (>= 4.0.0)
tsort
regexp_parser (2.11.3)
reline (0.6.3)
io-console (~> 0.5)
rspec (3.13.2)
rspec-core (~> 3.13.0)
rspec-expectations (~> 3.13.0)
rspec-mocks (~> 3.13.0)
rspec-core (3.13.6)
rspec-support (~> 3.13.0)
rspec-expectations (3.13.5)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.13.0)
rspec-mocks (3.13.8)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.13.0)
rspec-support (3.13.7)
sorbet-runtime (0.6.13055)
stringio (3.2.0)
tsort (0.2.0)
unparser (0.8.2)
diff-lcs (>= 1.6, < 3)
parser (>= 3.3.0)
prism (>= 1.5.1)

PLATFORMS
arm64-darwin
x86_64-darwin
x86_64-linux

DEPENDENCIES
irb
mutant
mutant-minitest
mutant-rspec
rake (>= 10.0)
rspec
ruby_event_store!
ruby_event_store-cli!

BUNDLED WITH
2.7.1
8 changes: 8 additions & 0 deletions contrib/ruby_event_store-cli/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
GEM_VERSION = $(shell cat lib/ruby_event_store/cli/version.rb | grep VERSION | egrep -o '[0-9]+\.[0-9]+\.[0-9]+')
GEM_NAME = ruby_event_store-cli

include ../../support/make/install.mk
include ../../support/make/test.mk
include ../../support/make/mutant.mk
include ../../support/make/gem.mk
include ../../support/make/help.mk
98 changes: 98 additions & 0 deletions contrib/ruby_event_store-cli/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
# ruby_event_store-cli

Command-line interface for inspecting a RubyEventStore event store without needing `rails console`.

## Installation

Add to your application's Gemfile:

```ruby
gem "ruby_event_store-cli"
```

The `res` executable will be available in your project. Run all commands from your Rails app root directory — the CLI autodetects `config/environment.rb` and loads your environment.

## Commands

### Stream

```bash
# List events in a stream (default: last 50)
bundle exec res stream events MyStream
bundle exec res stream events MyStream --limit 20
bundle exec res stream events MyStream --format json
bundle exec res stream events MyStream --type OrderPlaced
bundle exec res stream events MyStream --after 2024-01-01T00:00:00Z
bundle exec res stream events MyStream --before 2024-03-01T00:00:00Z
bundle exec res stream events MyStream --from <event_uuid>

# Follow a stream for new events (Ctrl+C to stop)
bundle exec res stream events MyStream --follow
bundle exec res stream events MyStream -f

# Show stream summary
bundle exec res stream show MyStream
```

### Event

```bash
# Show full event details (data, metadata, timestamps)
bundle exec res event show <uuid>

# List all streams an event belongs to
bundle exec res event streams <uuid>
```

### Search

Search events across all streams or within a specific one:

```bash
bundle exec res search --type OrderPlaced
bundle exec res search --type OrderPlaced --limit 100
bundle exec res search --type OrderPlaced --after 2024-01-01T00:00:00Z
bundle exec res search --stream Orders --type OrderPlaced
bundle exec res search --format json | jq '.[].data'
```

### Trace

Display the causal tree for a correlation ID — all events triggered by a single request, in order:

```bash
bundle exec res trace <correlation_id>
```

### Stats

```bash
# Total event count and unique event types
bundle exec res stats

# Stats for a specific stream
bundle exec res stats --stream Orders
```

### Watch

Live view of new events as they arrive, grouped by bounded context (namespace prefix of the class name):

```bash
# Watch all new events (Ctrl+C to stop)
bundle exec res watch

# Filter to specific namespace(s)
bundle exec res watch --namespace Ordering
bundle exec res watch --namespace Ordering,Payments

# Watch events from a point in time
bundle exec res watch --since 2024-01-15T10:00:00Z

# Adjust polling interval and max events shown per namespace
bundle exec res watch --interval 2 --limit 20
```

## License

MIT
20 changes: 20 additions & 0 deletions contrib/ruby_event_store-cli/bin/res
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#!/usr/bin/env ruby
# frozen_string_literal: true

require "dry/cli"
require_relative "../lib/ruby_event_store/cli"
require_relative "../lib/ruby_event_store/cli/commands"

env_file = File.expand_path("config/environment.rb")

abort "Could not find config/environment.rb. Run `res` from the root of your Rails application." unless File.exist?(env_file)

require env_file

abort <<~MSG unless defined?(Rails) && Rails.configuration.respond_to?(:event_store)
Could not find event store instance after loading config/environment.rb.

Expected Rails.configuration.event_store to be set (standard RES setup).
MSG

Dry::CLI.new(RubyEventStore::CLI::Commands).call
8 changes: 8 additions & 0 deletions contrib/ruby_event_store-cli/lib/ruby_event_store/cli.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# frozen_string_literal: true

require_relative "cli/version"

module RubyEventStore
module CLI
end
end
38 changes: 38 additions & 0 deletions contrib/ruby_event_store-cli/lib/ruby_event_store/cli/commands.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# frozen_string_literal: true

require "dry/cli"
require_relative "commands/base"
require_relative "commands/stream_events"
require_relative "commands/stream_show"
require_relative "commands/event_show"
require_relative "commands/event_streams"
require_relative "commands/trace"
require_relative "commands/search"
require_relative "commands/stats"
require_relative "commands/watch"

module RubyEventStore
module CLI
module Commands
extend Dry::CLI::Registry

register "stream", Class.new(Dry::CLI::Command) {
desc "Inspect a stream"
def call(**) = warn "Usage: res stream SUBCOMMAND\n\nSubcommands: events, show\n\nRun `res stream --help` for details."
}
register "stream events", StreamEvents
register "stream show", StreamShow

register "event", Class.new(Dry::CLI::Command) {
desc "Inspect an event"
def call(**) = warn "Usage: res event SUBCOMMAND\n\nSubcommands: show, streams\n\nRun `res event --help` for details."
}
register "event show", EventShow
register "event streams", EventStreams
register "trace", Trace
register "search", Search
register "stats", Stats
register "watch", Watch
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# frozen_string_literal: true

require "dry/cli"

module RubyEventStore
module CLI
module Commands
class Base < Dry::CLI::Command
private

def event_store
Rails.configuration.event_store
end
end
end
end
end
Loading
Loading