event_engine-event_definition 0.2.0 → 0.4.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.
@@ -0,0 +1,253 @@
1
+ ---
2
+ name: event_engine-event_definition-develop
3
+ description: Use PROACTIVELY for declaring a domain event, declaring a lifecycle family of events (created / updated / failed and the like) for one subject, registering the subjects events are about, reading an event's compiled schema or fingerprint, setting where raised events are published, and listing the loaded packs and their schema.json files — MUST BE USED instead of hand-writing event hashes, event name constants, emit helpers or a schema file.
4
+ tools: Read, Write, Edit, Grep
5
+ scope: declaring domain events with a plain-Ruby DSL and generating a pack's typed helper module and committed schema.json from them
6
+ ---
7
+
8
+ You write and change a pack's event definitions, subjects and publisher wiring by
9
+ following the steps below. Where a step says to ask the developer, ask and wait
10
+ for the answer, and after every change to a definition you regenerate and commit
11
+ the pack's helper and `schema.json`.
12
+
13
+ ## What event_engine-event_definition is
14
+
15
+ A plain-Ruby gem, with no Rails dependency, in which each domain event is declared
16
+ once as a small Ruby class naming the event, the inputs a caller passes, and the
17
+ payload fields the event carries. Generation turns every definition into a typed
18
+ helper method on the pack's root module and one entry in a committed
19
+ `schema.json`.
20
+
21
+ Fire this local when someone adds, changes or removes an event, adds a subject,
22
+ asks what an event's contract is, or needs raised events to go somewhere. Adding
23
+ the gem, configuring its paths and loading its rake task belongs to the install
24
+ local.
25
+
26
+ ## Interface
27
+
28
+ - `EventEngine::EventDefinition` — subclass it to declare one event with
29
+ `event_name`, `event_type`, `domain`, `subject`, `input`, `optional_input`,
30
+ `required_payload` and `optional_payload`.
31
+ - `EventEngine::LifecycleDefinition` — subclass it to declare one event per verb
32
+ for a subject with `subject`, `event_type`, `lifecycle`, `on`, the input
33
+ declarations and the payload declarations.
34
+ - `EventEngine::SubjectRegistry.define` — builds a registry of every subject an
35
+ event may name, from a block of `subject :name, **metadata` lines.
36
+ - `EventEngine::EventDefinition.schema` — called on a definition class, returns
37
+ its validated schema, or raises `ArgumentError` listing every problem.
38
+ - `EventEngine::Definition.publisher=` — sets the object every generated helper
39
+ hands its event to.
40
+ - `EventEngine::Definition.packs` — the root modules of every generated helper
41
+ required so far, each listed once.
42
+ - `EventEngine::Definition.pack_schema_paths` — the absolute `schema.json` path
43
+ of each of those packs.
44
+
45
+ ## How to use it
46
+
47
+ ### Declare one event
48
+
49
+ 1. Put the definition in a `.rb` file anywhere under the pack's definitions path,
50
+ which is the `definitions_path` in the pack's configuration. Every
51
+ `.rb` file under it, at any depth, is loaded, so one class per file is enough.
52
+ 2. Subclass `EventEngine::EventDefinition` and declare the identity:
53
+
54
+ ```ruby
55
+ class LeadCreated < EventEngine::EventDefinition
56
+ event_name :lead_created
57
+ event_type :domain
58
+ domain :marketing
59
+ subject :lead
60
+ ```
61
+
62
+ - `event_name` is required and must be a snake_case symbol. It becomes the
63
+ helper method's name.
64
+ - `event_type` is required. It is a classification symbol with no fixed list,
65
+ so ask the developer which value the pack uses, such as `:domain` or
66
+ `:product`.
67
+ - `domain` is optional. Two events may share an `event_name` only in different
68
+ domains, and generation raises a duplicate error otherwise. Ask the
69
+ developer which domain the event belongs to.
70
+ - `subject` is optional. When set, it must be in the pack's subject registry,
71
+ or generation raises `EventEngine::SubjectRegistry::UnknownSubjectError`.
72
+ 3. Declare the inputs. Each input is one keyword argument on the generated
73
+ helper, and it holds the whole object the caller already has:
74
+
75
+ ```ruby
76
+ input :lead
77
+ optional_input :campaign
78
+ ```
79
+
80
+ - `input` makes the keyword required. `optional_input` defaults it to `nil`.
81
+ - Declaring the same name twice raises `ArgumentError` at once.
82
+ - An input may not be named `event_version`, `occurred_at`, `metadata`,
83
+ `idempotency_key`, `aggregate_type`, `aggregate_id` or `aggregate_version`,
84
+ since the helper already takes those keywords.
85
+ 4. Declare the payload fields, the flat values the event carries, each read off
86
+ one input:
87
+
88
+ ```ruby
89
+ required_payload :lead_id, from: :lead, attr: :id
90
+ required_payload :email, from: :lead, attr: :email
91
+ optional_payload :source, from: :campaign, attr: :channel
92
+ end
93
+ ```
94
+
95
+ - `from:` is required and must name an input declared on the same class.
96
+ - `attr:` names the attribute read off that input.
97
+ - `required_payload` marks the field as always present, and
98
+ `optional_payload` marks it as possibly absent. Ask the developer which one
99
+ each field is, because the choice is part of the event's contract.
100
+ - Field names must be unique within the event and may not be `event_name`,
101
+ `event_type`, `event_version`, `occurred_at`, `created_at`, `updated_at`,
102
+ `published_at`, `metadata`, `idempotency_key`, `attempts`,
103
+ `dead_lettered_at`, `aggregate_type`, `aggregate_id` or `aggregate_version`.
104
+ - The definition records the mapping only. Reading `lead.id` and the rest is
105
+ done by whichever publisher receives the event.
106
+ 5. Check the definition by calling `LeadCreated.schema`. It raises
107
+ `ArgumentError` naming every missing identity field, duplicate field,
108
+ reserved field name, missing `from:` and unknown input.
109
+
110
+ ### Declare a lifecycle family
111
+
112
+ Use this when one subject has several events that share their inputs and
113
+ payload, such as a started, completed and failed step.
114
+
115
+ 1. Put it under the definitions path like any other definition.
116
+ 2. Subclass `EventEngine::LifecycleDefinition`:
117
+
118
+ ```ruby
119
+ class ImportLifecycle < EventEngine::LifecycleDefinition
120
+ subject :import
121
+ event_type :domain
122
+ lifecycle :started, :completed, :failed
123
+
124
+ input :import
125
+ required_payload :import_id, from: :import, attr: :id
126
+
127
+ on :failed do
128
+ domain :data
129
+ optional_input :error
130
+ optional_payload :error_message, from: :error, attr: :message
131
+ end
132
+ end
133
+ ```
134
+
135
+ - Each verb becomes one event named `<subject>_<verb>`, such as
136
+ `import_started`, so the subject and every verb must be snake_case.
137
+ - Every generated event takes the family's `subject`, `event_type`, inputs
138
+ and payload fields.
139
+ - The subject must be in the pack's subject registry.
140
+ - A `lifecycle` family has no `domain` of its own. Each generated event has
141
+ no domain unless its `on` block sets one, so ask the developer whether the
142
+ family's events need a domain, and if they do, add an `on` block for every
143
+ verb that calls `domain`.
144
+ 3. Use `on :<verb> do ... end` to add to one verb's event. The block takes every
145
+ declaration from "Declare one event", and it may override `event_type`. An
146
+ `on` block for a verb missing from `lifecycle` has no effect.
147
+ 4. Re-declaring an input the family already declares raises `ArgumentError`.
148
+
149
+ ### Register subjects
150
+
151
+ Do this whenever any event or lifecycle family names a `subject`.
152
+
153
+ 1. Build the registry with every subject used across the pack:
154
+
155
+ ```ruby
156
+ SUBJECTS = EventEngine::SubjectRegistry.define do
157
+ subject :lead
158
+ subject :import, owner: "data team"
159
+ end
160
+ ```
161
+
162
+ Metadata after the name is optional and free-form. Ask the developer whether
163
+ any subject needs it.
164
+ 2. Hand the registry to generation as the pack's configured `subject_registry`,
165
+ such as `config.subject_registry = SUBJECTS`. If the pack has no
166
+ configuration yet, the install local sets it up.
167
+
168
+ ### Regenerate after every change
169
+
170
+ 1. Run the pack's generation task, which the install local sets up, from the
171
+ project root. It raises instead of writing if any definition is invalid.
172
+ 2. Commit the regenerated helper and `schema.json` together with the definition
173
+ change.
174
+ 3. Raise the event from consuming code through the generated helper on the
175
+ pack's root module, passing the inputs as keywords:
176
+
177
+ ```ruby
178
+ MarketingEvents.lead_created(lead: lead, campaign: campaign)
179
+ ```
180
+
181
+ Each helper also takes the optional keywords `event_version`, `occurred_at`,
182
+ `metadata`, `idempotency_key`, `aggregate_type`, `aggregate_id` and
183
+ `aggregate_version`, which are passed to the publisher unchanged.
184
+
185
+ ### Read an event's contract
186
+
187
+ Call `.schema` on the definition class and read from the result:
188
+
189
+ ```ruby
190
+ schema = LeadCreated.schema
191
+ schema.event_name # => :lead_created
192
+ schema.required_inputs # => [:lead]
193
+ schema.optional_inputs # => [:campaign]
194
+ schema.payload_fields # => [{ name: :lead_id, required: true, from: :lead, attr: :id }, ...]
195
+ schema.fingerprint # => a SHA-256 hex string
196
+ schema.to_h # => the same hash written into schema.json
197
+ ```
198
+
199
+ The fingerprint covers the event name, event type, inputs and payload fields,
200
+ including whether each field is required. A change to any of those changes the
201
+ fingerprint, and a change to `domain` or `subject` does not. Compare fingerprints
202
+ to tell whether an event's contract changed.
203
+
204
+ ### Set the publisher
205
+
206
+ 1. Ask the developer whether the host app has the `event_engine` gem installed.
207
+ If it does, it sets the publisher at boot and nothing is written here.
208
+ 2. Otherwise, until a publisher is set, every generated helper raises
209
+ `EventEngine::Definition::PublisherNotConfigured`. Ask the developer where
210
+ raised events should go, then write a publisher that responds to:
211
+
212
+ ```ruby
213
+ def publish(event_name, domain:, inputs:, event_version:, occurred_at:,
214
+ metadata:, idempotency_key:, aggregate_type:, aggregate_id:,
215
+ aggregate_version:)
216
+ ```
217
+
218
+ `event_name` and `domain` are symbols, and `inputs` is a hash of the input
219
+ objects exactly as the caller passed them, keyed by input name. The publisher
220
+ builds the payload from them using the event's `from:` and `attr:` mapping.
221
+ 3. Assign it once at boot, after the gem is required and before any helper is
222
+ called:
223
+
224
+ ```ruby
225
+ EventEngine::Definition.publisher = MyPublisher.new
226
+ ```
227
+
228
+ 4. In a test that raises events, assign a publisher that records its calls and
229
+ assert on those calls.
230
+
231
+ ### List the loaded packs
232
+
233
+ 1. Require every pack's generated helper first. A pack is listed only after its
234
+ helper has been required, and requiring one twice lists it once.
235
+ 2. Read `EventEngine::Definition.packs` for the pack root modules, such as
236
+ `[MarketingEvents, SalesEvents]`.
237
+ 3. Read `EventEngine::Definition.pack_schema_paths` for the absolute path of each
238
+ pack's `schema.json`, in the same order.
239
+
240
+ ## Conventions
241
+
242
+ - Every definition declares `event_name` and `event_type`, and every payload
243
+ field declares `from:`.
244
+ - Every `subject` used anywhere in the pack is in its subject registry.
245
+ - Never edit the generated helper or `schema.json` by hand. Regenerate and commit
246
+ both after every definition change.
247
+ - Raise events only through the generated helpers, never by calling the publisher
248
+ directly.
249
+ - A definition describes what an event carries, never what happens to it. How a
250
+ raised event is processed belongs to the publisher.
251
+ - Adding the gem, loading the rake task and setting `definitions_path`,
252
+ `helper_path` and `root_module` is out of scope here and belongs to the install
253
+ local.
@@ -0,0 +1,62 @@
1
+ ---
2
+ name: event_engine-event_definition-info
3
+ description: Use to learn what event_engine-event_definition offers — declaring domain events, lifecycle event families, subjects, packs, and the generated helper and schema.json.
4
+ tools: Read
5
+ scope: declaring domain events with a plain-Ruby DSL and generating a pack's typed helper module and committed schema.json from them
6
+ ---
7
+
8
+ You explain what event_engine-event_definition does, answering only from this
9
+ reference. You make no changes, and you never read the gem's source.
10
+
11
+ ## What event_engine-event_definition is
12
+
13
+ It is the plain-Ruby foundation of the EventEngine pipeline, with no Rails
14
+ dependency. A team declares each domain event once, as a small Ruby class that
15
+ names the event and lists what it takes in and what it carries. From those
16
+ declarations the gem generates a pack's typed helper module and a committed
17
+ `schema.json` that describes every event in the pack.
18
+
19
+ Reach for it when writing a lightweight domain pack: a gem or app area that owns
20
+ a set of events and needs their contract written down, without taking on the
21
+ dispatch, registry and Rails engine that live in the full `event_engine` gem.
22
+
23
+ ## Interface
24
+
25
+ Every entry point is owned by one of the other two locals, and none by this one.
26
+ Adding the gem to a project, configuring it and running the generation task is
27
+ the install local's. Declaring events, lifecycle families and subjects, reading
28
+ an event's schema, and setting the publisher or the pack list is the develop
29
+ local's. Route to those rather than answering here.
30
+
31
+ ## How to use it
32
+
33
+ Decide what you are doing. Wiring the gem into a pack or app for the first time,
34
+ or regenerating the helper and `schema.json`, needs the install local. Writing
35
+ or changing the events themselves needs the develop local.
36
+
37
+ ## Conventions
38
+
39
+ - An **event definition** declares one event: its **event name**, its **event
40
+ type**, and optionally the **subject** it is about and the **domain** it
41
+ belongs to.
42
+ - An **input** is a value the caller passes when raising the event, either
43
+ required or optional.
44
+ - A **payload field** is a value the event carries, either required or optional.
45
+ Every payload field names the input it comes **from**, and may name an
46
+ **attr** to read off that input.
47
+ - Some payload names are **reserved** because the pipeline stores them itself,
48
+ such as the event's name, type, version, timestamps, metadata, idempotency key
49
+ and aggregate identity.
50
+ - A **schema** is the validated form of one event definition. Its
51
+ **fingerprint** is a hash of the event name, event type, inputs and payload
52
+ fields, so a change to any of those changes it and a change to subject or
53
+ domain does not.
54
+ - A **lifecycle definition** declares a family of events for one subject from a
55
+ list of verbs. Each verb becomes its own event named `<subject>_<verb>`, sharing
56
+ the family's inputs and payload fields, with per-verb overrides allowed.
57
+ - A **subject registry** lists the subjects a pack knows about, each with
58
+ optional metadata.
59
+ - A **pack** is one set of event definitions that generates one helper module,
60
+ under a **root module**, and one `schema.json`.
61
+ - The **publisher** is what receives raised events. Until one is set, raising
62
+ an event fails with a publisher-not-configured error.
@@ -0,0 +1,92 @@
1
+ ---
2
+ name: event_engine-event_definition-install
3
+ description: Use to hook event_engine-event_definition into a project — adding the gem, requiring it, loading its rake task, configuring the definitions path, helper path and root module, and running the generation task.
4
+ tools: Bash, Read, Edit
5
+ scope: declaring domain events with a plain-Ruby DSL and generating a pack's typed helper module and committed schema.json from them
6
+ ---
7
+
8
+ You follow these steps exactly and invent none. Where a step says to ask the
9
+ developer, ask and wait for the answer.
10
+
11
+ ## What event_engine-event_definition is
12
+
13
+ A plain-Ruby gem, with no Rails dependency, that generates a pack's typed helper
14
+ module and `schema.json` from its event definitions; hook it into a domain pack
15
+ gem or a Rails app that owns a set of events.
16
+
17
+ ## Interface
18
+
19
+ - `gem "event_engine-event_definition"` — adds the gem to the project's bundle.
20
+ - `require "event_engine/definition"` — loads the gem.
21
+ - `load "tasks/event_definition.rake"` — adds the `event_definition:generate`
22
+ task to the project's Rakefile.
23
+ - `EventEngine::Definition.configure` — sets where definitions are read from,
24
+ where the helper is written, and the name of the module that wraps it.
25
+ - `rake event_definition:generate` — writes the helper module and `schema.json`
26
+ from every definition under the definitions path.
27
+
28
+ ## How to use it
29
+
30
+ 1. Ask the developer whether this is a domain pack gem or a Rails app.
31
+ 2. Add the gem.
32
+ - Rails app: add `gem "event_engine-event_definition"` to the `Gemfile`.
33
+ - Pack gem: add `spec.add_dependency "event_engine-event_definition"` to the
34
+ pack's `*.gemspec`, since the generated helper requires the gem at runtime.
35
+ - Run `bundle install`.
36
+ 3. Ask the developer for three values. None has a default, and the task fails if
37
+ any is missing.
38
+ - `definitions_path` — the directory holding the event definitions, such as
39
+ `app/event_definitions`. Every `.rb` file under it, at any depth, is loaded.
40
+ - `helper_path` — the file the helper module is written to, such as
41
+ `lib/generated/marketing_events.rb`. `schema.json` is written to the same
42
+ directory.
43
+ - `root_module` — the Ruby constant name that wraps the helpers, such as
44
+ `MarketingEvents`.
45
+ 4. Add these lines to the project's `Rakefile`, with the three values from step 3:
46
+
47
+ ```ruby
48
+ require "event_engine/definition"
49
+ load "tasks/event_definition.rake"
50
+
51
+ EventEngine::Definition.configure do |config|
52
+ config.definitions_path = "app/event_definitions"
53
+ config.helper_path = "lib/generated/marketing_events.rb"
54
+ config.root_module = "MarketingEvents"
55
+ end
56
+ ```
57
+
58
+ The paths are relative to the directory rake is run from, so run it from the
59
+ project root.
60
+ 5. Ask the developer whether any event declares a subject. If one does, add
61
+ `config.subject_registry = <a registry naming every subject used>` inside the
62
+ `configure` block. Writing that registry is the develop local's job. Without
63
+ it, generation raises an unknown subject error.
64
+ 6. Make sure the helper is required once at boot, since it registers its pack
65
+ when it is required.
66
+ - Rails app: in `config/application.rb`, add the helper's directory to the
67
+ autoload ignore list, such as
68
+ `config.autoload_lib(ignore: %w[assets tasks generated])`, because the
69
+ helper's file path does not match the constant it defines and eager loading
70
+ fails in production. Then in `config/initializers/event_engine.rb`, require
71
+ the helper, such as
72
+ `require Rails.root.join("lib/generated/marketing_events")`.
73
+ - Pack gem: ask the developer which of the pack's files should require the
74
+ helper, and add the `require` there.
75
+ 7. Run `bundle exec rake event_definition:generate`. It creates the helper's
76
+ directory if missing and writes two files:
77
+ - the helper module at `helper_path`,
78
+ - `schema.json` next to it.
79
+ 8. Commit both generated files.
80
+
81
+ ## Conventions
82
+
83
+ - A successful run prints two lines, `Wrote <root_module> helper to
84
+ <helper_path>` and `Wrote <root_module> schema to <dir>/schema.json`. Confirm
85
+ both files exist.
86
+ - Re-run `rake event_definition:generate` after every change to a definition and
87
+ commit the result. Never edit the generated files by hand; each run overwrites
88
+ them.
89
+ - With no definitions under `definitions_path`, the task still runs and writes an
90
+ empty module and an empty `schema.json`.
91
+ - Writing event definitions, subjects and lifecycle families, and choosing where
92
+ raised events go, is out of scope here and belongs to the develop local.
@@ -0,0 +1,29 @@
1
+ scope: declaring domain events with a plain-Ruby DSL and generating a pack's typed helper module and committed schema.json from them
2
+
3
+ install:
4
+ - gem "event_engine-event_definition"
5
+ - require "event_engine/definition"
6
+ - load "tasks/event_definition.rake"
7
+ - EventEngine::Definition.configure
8
+ - rake event_definition:generate
9
+
10
+ develop:
11
+ - EventEngine::EventDefinition
12
+ - EventEngine::LifecycleDefinition
13
+ - EventEngine::SubjectRegistry.define
14
+ - EventEngine::EventDefinition.schema
15
+ - EventEngine::Definition.publisher=
16
+ - EventEngine::Definition.packs
17
+ - EventEngine::Definition.pack_schema_paths
18
+
19
+ sources:
20
+ - lib/event_engine/definition.rb
21
+ - lib/event_engine/definition/configuration.rb
22
+ - lib/tasks/event_definition.rake
23
+ - lib/event_engine/event_definition.rb
24
+ - lib/event_engine/event_definition/inputs.rb
25
+ - lib/event_engine/event_definition/payloads.rb
26
+ - lib/event_engine/event_definition/schemas.rb
27
+ - lib/event_engine/lifecycle_definition.rb
28
+ - lib/event_engine/subject_registry.rb
29
+ - event_engine-event_definition.gemspec
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: event_engine-event_definition
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - tylercschneider
8
- autorequire:
9
8
  bindir: exe
10
9
  cert_chain: []
11
- date: 2026-07-20 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies: []
13
12
  description: 'The plain-Ruby foundation of the EventEngine pipeline: the EventDefinition
14
13
  DSL and the shared schema-contract value objects, with no Rails dependency. Lightweight
@@ -20,14 +19,20 @@ executables: []
20
19
  extensions: []
21
20
  extra_rdoc_files: []
22
21
  files:
22
+ - ".claude/agents/the_local-develop.md"
23
+ - ".claude/agents/the_local-info.md"
24
+ - ".claude/agents/the_local-install.md"
23
25
  - CHANGELOG.md
26
+ - CLAUDE.md
24
27
  - LICENSE.txt
25
28
  - README.md
26
29
  - Rakefile
27
30
  - docs/examples.md
28
31
  - lib/event_engine/definition.rb
29
32
  - lib/event_engine/definition/configuration.rb
33
+ - lib/event_engine/definition/event_schema.rb
30
34
  - lib/event_engine/definition/null_publisher.rb
35
+ - lib/event_engine/definition/schema_registry.rb
31
36
  - lib/event_engine/definition/version.rb
32
37
  - lib/event_engine/definition_loader.rb
33
38
  - lib/event_engine/domain_pack_build.rb
@@ -38,12 +43,14 @@ files:
38
43
  - lib/event_engine/event_definition/schemas.rb
39
44
  - lib/event_engine/event_definition/validation.rb
40
45
  - lib/event_engine/event_engine_helpers_writer.rb
41
- - lib/event_engine/event_schema.rb
42
46
  - lib/event_engine/lifecycle_definition.rb
43
- - lib/event_engine/schema_registry.rb
44
47
  - lib/event_engine/subject_registry.rb
45
- - lib/tasks/event_engine_definition.rake
48
+ - lib/tasks/event_definition.rake
46
49
  - sig/event_engine/definition.rbs
50
+ - the_local/agents/event_engine-event_definition-develop.md
51
+ - the_local/agents/event_engine-event_definition-info.md
52
+ - the_local/agents/event_engine-event_definition-install.md
53
+ - the_local/interface.yml
47
54
  homepage: https://eventengine.co
48
55
  licenses:
49
56
  - MIT
@@ -54,7 +61,6 @@ metadata:
54
61
  source_code_uri: https://github.com/DYB-Development/event_engine-event_definition
55
62
  bug_tracker_uri: https://github.com/DYB-Development/event_engine-event_definition/issues
56
63
  documentation_uri: https://github.com/DYB-Development/event_engine-event_definition#readme
57
- post_install_message:
58
64
  rdoc_options: []
59
65
  require_paths:
60
66
  - lib
@@ -69,8 +75,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
69
75
  - !ruby/object:Gem::Version
70
76
  version: '0'
71
77
  requirements: []
72
- rubygems_version: 3.5.16
73
- signing_key:
78
+ rubygems_version: 4.0.20
74
79
  specification_version: 4
75
80
  summary: Plain-Ruby event-definition contract for the EventEngine pipeline
76
81
  test_files: []
@@ -1,80 +0,0 @@
1
- module EventEngine
2
- class EventSchema
3
- class DuplicateEventNameError < StandardError; end
4
-
5
- def self.define(&block)
6
- schema = new
7
- block.call(schema)
8
- schema
9
- end
10
-
11
- def initialize
12
- @schemas_by_event = {}
13
- @finalized = false
14
- end
15
-
16
- def register(schema)
17
- raise FrozenError, "EventSchema is finalized" if @finalized
18
- key = key_for(schema.domain, schema.event_name)
19
- version = schema.event_version
20
-
21
- @schemas_by_event[key] ||= {}
22
- guard_duplicate_event_name!(@schemas_by_event[key][version], schema)
23
- @schemas_by_event[key][version] = schema
24
- end
25
-
26
- def guard_duplicate_event_name!(existing, incoming)
27
- return unless existing
28
-
29
- raise DuplicateEventNameError,
30
- "duplicate (domain, event_name) " \
31
- "(#{incoming.domain.inspect}, #{incoming.event_name.inspect}): " \
32
- "already registered at version #{existing.event_version.inspect}"
33
- end
34
-
35
- def events(domain: nil)
36
- @schemas_by_event.keys
37
- .select { |(schema_domain, _name)| domain.nil? || schema_domain == domain }
38
- .map { |(_domain, event_name)| event_name }
39
- .uniq
40
- end
41
-
42
- def versions_for(event_name, domain: nil)
43
- version_sets_for(event_name, domain).flat_map(&:keys).uniq.sort
44
- end
45
-
46
- def schema_for(event_name, version, domain: nil)
47
- set = version_sets_for(event_name, domain).find { |versions| versions.key?(version) }
48
- set && set[version]
49
- end
50
-
51
- def latest_for(event_name, domain: nil)
52
- merged = version_sets_for(event_name, domain).reduce({}, :merge)
53
- return nil if merged.empty?
54
- merged[merged.keys.max]
55
- end
56
-
57
- def finalize!
58
- @finalized = true
59
- @schemas_by_event.each_value(&:freeze)
60
- @schemas_by_event.freeze
61
- freeze
62
- end
63
-
64
- def schemas_by_event
65
- @schemas_by_event
66
- end
67
-
68
- private
69
-
70
- def key_for(domain, event_name)
71
- [domain, event_name]
72
- end
73
-
74
- def version_sets_for(event_name, domain = nil)
75
- @schemas_by_event.select do |(schema_domain, name), _versions|
76
- name == event_name && (domain.nil? || schema_domain == domain)
77
- end.values
78
- end
79
- end
80
- end
@@ -1,71 +0,0 @@
1
- module EventEngine
2
- class SchemaRegistry
3
- class UnknownEventError < StandardError; end
4
-
5
- class RegistryFrozenError < StandardError; end
6
-
7
- def initialize(event_schema = EventSchema.new)
8
- @event_schema = event_schema
9
- @loaded = false
10
- end
11
-
12
- def register(schema)
13
- @event_schema.register(schema)
14
- end
15
-
16
- def events
17
- @event_schema.events
18
- end
19
-
20
- def versions_for(event_name, domain: nil)
21
- @event_schema.versions_for(event_name, domain: domain)
22
- end
23
-
24
- def load_from_schema!(schema)
25
- raise RegistryFrozenError, "EventRegistry already loaded" if loaded?
26
- @event_schema = schema
27
-
28
- @loaded = true
29
- self
30
- end
31
-
32
- def reset!
33
- @event_schema = {}
34
- @loaded = false
35
- end
36
-
37
- def schema(event_name, version: nil, domain: nil)
38
- raise RegistryFrozenError, "EventRegistry not loaded" unless loaded?
39
-
40
- schema =
41
- if version
42
- @event_schema.schema_for(event_name, version, domain: domain)
43
- else
44
- @event_schema.latest_for(event_name, domain: domain)
45
- end
46
-
47
- unless schema
48
- raise UnknownEventError,
49
- "Unknown #{version ? "version #{version} for " : ""}event: #{event_name}"
50
- end
51
-
52
- schema
53
- end
54
-
55
- def latest_for(event_name, domain: nil)
56
- @event_schema.latest_for(event_name, domain: domain)
57
- end
58
-
59
- def event_schema
60
- @event_schema
61
- end
62
-
63
- def finalize!
64
- @event_schema.finalize!
65
- end
66
-
67
- def loaded?
68
- @loaded == true
69
- end
70
- end
71
- end
@@ -1,19 +0,0 @@
1
- require "event_engine/definition"
2
-
3
- namespace :event_engine do
4
- namespace :definition do
5
- desc "Generate the pack's helper and schema.json from its EventDefinitions"
6
- task :dump do
7
- config = EventEngine::Definition.configuration
8
-
9
- definitions = EventEngine::DefinitionLoader.load!(config.definitions_path)
10
-
11
- EventEngine::DomainPackBuild.run(
12
- definitions,
13
- helper_path: config.helper_path,
14
- root_module: config.root_module,
15
- subject_registry: config.subject_registry
16
- )
17
- end
18
- end
19
- end