dexkit 0.7.0 → 0.9.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +45 -0
- data/README.md +40 -7
- data/gemfiles/mongoid_no_ar.gemfile +10 -0
- data/gemfiles/mongoid_no_ar.gemfile.lock +232 -0
- data/guides/llm/EVENT.md +60 -5
- data/guides/llm/FORM.md +3 -3
- data/guides/llm/OPERATION.md +127 -18
- data/guides/llm/QUERY.md +3 -3
- data/lib/dex/event/bus.rb +7 -0
- data/lib/dex/event/export.rb +56 -0
- data/lib/dex/event/handler.rb +33 -0
- data/lib/dex/event/test_helpers.rb +88 -0
- data/lib/dex/event.rb +27 -0
- data/lib/dex/event_test_helpers.rb +1 -86
- data/lib/dex/form/uniqueness_validator.rb +17 -1
- data/lib/dex/operation/async_proxy.rb +1 -0
- data/lib/dex/operation/explain.rb +208 -0
- data/lib/dex/operation/export.rb +144 -0
- data/lib/dex/operation/guard_wrapper.rb +15 -4
- data/lib/dex/operation/lock_wrapper.rb +15 -2
- data/lib/dex/operation/once_wrapper.rb +23 -15
- data/lib/dex/operation/record_backend.rb +25 -0
- data/lib/dex/operation/record_wrapper.rb +29 -4
- data/lib/dex/operation/test_helpers/assertions.rb +335 -0
- data/lib/dex/operation/test_helpers/execution.rb +30 -0
- data/lib/dex/operation/test_helpers/stubbing.rb +61 -0
- data/lib/dex/operation/test_helpers.rb +150 -0
- data/lib/dex/operation/transaction_adapter.rb +29 -68
- data/lib/dex/operation/transaction_wrapper.rb +10 -16
- data/lib/dex/operation.rb +46 -2
- data/lib/dex/props_setup.rb +25 -2
- data/lib/dex/query/backend.rb +13 -0
- data/lib/dex/query.rb +9 -5
- data/lib/dex/railtie.rb +84 -0
- data/lib/dex/ref_type.rb +4 -0
- data/lib/dex/registry.rb +63 -0
- data/lib/dex/test_helpers.rb +4 -139
- data/lib/dex/tool.rb +115 -0
- data/lib/dex/type_coercion.rb +4 -1
- data/lib/dex/type_serializer.rb +132 -0
- data/lib/dex/version.rb +1 -1
- data/lib/dexkit.rb +11 -5
- metadata +16 -5
- data/lib/dex/test_helpers/assertions.rb +0 -333
- data/lib/dex/test_helpers/execution.rb +0 -28
- data/lib/dex/test_helpers/stubbing.rb +0 -59
- /data/lib/dex/{event_test_helpers → event/test_helpers}/assertions.rb +0 -0
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 41c8e4455fb4a4cca73b1d12da366b53bdbbada2cbae773917a12d344a150dd4
|
|
4
|
+
data.tar.gz: 86c4e76004df8b968c094b7b252a988eafe2f7aee035505ddb7bbeae1f25e04a
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 89a9f6075f3955300dbe3944a9adc9b80ab56c3b4dc60d9458ea370f68c5c83ab5b3f2daad26c6f852d6f423a498ccf068914853e9866c05442765539ac6ac91
|
|
7
|
+
data.tar.gz: cd541ee35700cf9aa877b3630d66f0b9580263d0fddc7f381200afe32c638f832d941112387f646fa59500c26bb552461ad5bf0f0ec79dcf7bb97d76ebcbfb86
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,50 @@
|
|
|
1
1
|
## [Unreleased]
|
|
2
2
|
|
|
3
|
+
## [0.9.0] - 2026-03-09
|
|
4
|
+
|
|
5
|
+
### Breaking
|
|
6
|
+
|
|
7
|
+
- **Mongoid transaction support removed** — `transaction :mongoid` and `config.transaction_adapter = :mongoid` are no longer valid. Dex no longer ships a Mongoid transaction adapter. Before: Mongoid transactions could be enabled via configuration or per-operation DSL. After: both forms raise `ArgumentError` immediately at declaration/configuration time. Mongoid-only apps continue to work — transactions are automatically disabled (no adapter detected), and `after_commit` fires immediately after success. If you need Mongoid multi-document transactions, call `Mongoid.transaction` directly inside `perform`
|
|
8
|
+
- **Recording backends now validate required attributes before use** — Dex no longer silently drops missing `params`, `result`, `status`, or `once` attributes from `record_class`. Before: partial ActiveRecord/Mongoid recording models could appear to work while losing status transitions, replay data, or async params. After: Dex raises `ArgumentError` naming the missing attributes required by core recording, async record jobs, or `once`. Apps using minimal recording models must add the required columns/fields or explicitly disable the features that need them
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
|
|
12
|
+
- **Mongoid-only Rails compatibility** — Dex boots and runs cleanly in Mongoid-only Rails apps without `activerecord` loaded, with prescriptive `LoadError`s for unsupported paths such as `advisory_lock` and async event dispatch without `ActiveJob`
|
|
13
|
+
- **ActiveRecord transaction auto-detection is stricter** — Dex now enables the ActiveRecord transaction adapter only when an ActiveRecord connection pool actually exists. Before: merely loading `activerecord` could make Mongoid-backed operations try to open an ActiveRecord transaction and fail with `ActiveRecord::ConnectionNotDefined`. After: unconfigured ActiveRecord no longer activates transactions implicitly
|
|
14
|
+
- **Mongoid async/recording serialization** — `_Ref(Model)` serializes IDs via `id.as_json`, so `BSON::ObjectId` values round-trip through async operations, async events, and recording without `ActiveJob::SerializationError`. Recording and `once` sanitize untyped Mongoid document results to JSON-safe payloads
|
|
15
|
+
- **Mongoid query and form parity** — query adapter detection and scope merging normalize Mongoid association scopes to `Mongoid::Criteria`, uniqueness validation excludes persisted Mongoid records correctly and uses a case-insensitive regex path for `case_sensitive: false`, and `_Ref(lock: true)` fails fast for model classes that do not support `.lock`
|
|
16
|
+
|
|
17
|
+
## [0.8.0] - 2026-03-09
|
|
18
|
+
|
|
19
|
+
### Added
|
|
20
|
+
|
|
21
|
+
- **Registry** — `Dex::Operation.registry`, `Dex::Event.registry`, and `Dex::Event::Handler.registry` return frozen Sets of all named subclasses. Populated automatically via `inherited`; anonymous and stale (unreachable after code reload) classes are excluded. `deregister(klass)` removes entries. `clear!` empties the registry. Zeitwerk-compatible — registries reflect loaded classes; eager-load to get the full list
|
|
22
|
+
- **Description & prop descriptions** — `description "text"` class-level DSL for operations and events. `desc:` keyword on `prop`/`prop?` for per-property descriptions (validated as String). Both appear in `contract.to_h`, `to_json_schema`, and `explain` output. Optional — no error or warning when omitted
|
|
23
|
+
- **`contract.to_h` export** — serializes the full operation contract to a plain Ruby Hash: `name`, `description`, `params` (with typed strings and `desc`), `success`, `errors`, `guards`, `context`, `pipeline`, `settings`. Types are human-readable strings (`"String"`, `"Integer(1..)"`, `"Ref(Product)"`, `"Nilable(String)"`). Omits nil/empty fields
|
|
24
|
+
- **`contract.to_json_schema` export** — generates JSON Schema (Draft 2020-12) from the operation contract. Default section is `:params` (input schema for LLM tools, form generation, API validation). Also supports `:success`, `:errors`, and `:full` sections
|
|
25
|
+
- **Event export** — `Event.to_h` and `Event.to_json_schema` class methods for serializing event definitions. Same type serialization as operations
|
|
26
|
+
- **Handler export** — `Handler.to_h` returns name, events (array), retries, transaction, and pipeline metadata. `handled_events` returns all subscribed event classes
|
|
27
|
+
- **Bulk export** — `Dex::Operation.export(format: :hash|:json_schema)`, `Dex::Event.export(format: :hash|:json_schema)`, `Dex::Event::Handler.export(format: :hash)`. Returns arrays sorted by name — directly serializable with `JSON.generate`
|
|
28
|
+
- **`Dex::Tool` — ruby-llm integration** — bridges dexkit operations to [ruby-llm](https://rubyllm.com/) tools. `Dex::Tool.from(Op)` generates a `RubyLLM::Tool` from an operation's contract. `Dex::Tool.all` converts all registered operations. `Dex::Tool.from_namespace("Order")` filters by namespace. `Dex::Tool.explain_tool` provides a built-in preflight check tool. Lazy-loaded — ruby-llm is only required when you call `Dex::Tool`
|
|
29
|
+
- **`Dex::TypeSerializer`** — converts Literal types to human-readable strings and JSON Schema. Handles `String`, `Integer`, `Float`, `Boolean`, `Symbol`, `Hash`, `Date`, `Time`, `DateTime`, `BigDecimal`, `_Nilable`, `_Array`, `_Union`, `_Ref`, and range-constrained types (`_Integer(1..)`)
|
|
30
|
+
- **Rake task `dex:export`** — `rake dex:export` with `FORMAT=hash|json_schema`, `SECTION=operations|events|handlers`, `FILE=path` environment variables. Auto-loaded via Railtie in Rails apps
|
|
31
|
+
- **Rake task `dex:guides`** — `rake dex:guides` installs LLM-optimized guides as `AGENTS.md` files in app directories (`app/operations/`, `app/events/`, `app/event_handlers/`, `app/forms/`, `app/queries/`). Only writes to directories that exist. Stamps each file with the installed dexkit version. The event guide is installed to both `app/events/` and `app/event_handlers/` when either exists. Existing hand-written `AGENTS.md` files are detected and skipped (`FORCE=1` to overwrite). Override paths with `OPERATIONS_PATH`, `EVENTS_PATH`, `EVENT_HANDLERS_PATH`, `FORMS_PATH`, `QUERIES_PATH` environment variables
|
|
32
|
+
- **`explain` includes `description`** — `explain` output now contains `:description` when set on the operation
|
|
33
|
+
- **`explain` class method for operations** — `MyOp.explain(**kwargs)` returns a frozen Hash with the full preflight state: resolved props, context source tracking (`:explicit`/`:ambient`/`:default`), per-guard pass/fail results with messages, once key and status (`:fresh`/`:exists`/`:expired`/`:pending`/`:invalid`/`:misconfigured`/`:unavailable`), advisory lock key, record/transaction/rescue/callback settings, pipeline steps, and overall `callable` verdict (accounts for both guard failures and once blocking statuses). No side effects — `perform` is never called. Gracefully handles invalid props — returns partial results with `error` key instead of raising, class-level information always available. Respects pipeline customization — removed steps report inactive. Custom middleware can contribute via `_name_explain` class methods
|
|
34
|
+
|
|
35
|
+
### Breaking
|
|
36
|
+
|
|
37
|
+
- **`contract.to_h` returns rich format** — `contract.to_h` now returns a comprehensive serialized Hash with string-typed params, description, context, pipeline, and settings instead of the raw `Data#to_h` shape. Before: `contract.to_h[:success]` returned `String` (the class). After: it returns `"String"` (a string). Code doing type comparisons like `contract.to_h[:success] == String` must update to use `contract.success` (which still returns raw types) or compare against `"String"`. The raw Ruby types remain accessible via `contract.params`, `contract.success`, `contract.errors`, `contract.guards`
|
|
38
|
+
- **`_Ref` JSON Schema type changed from `"integer"` to `"string"`** — `_Ref(Model)` now serializes as `{ type: "string" }` in JSON Schema. IDs are treated as opaque strings to support Mongoid BSON::ObjectId, UUIDs, and other non-integer primary key formats. Code that relied on `type: "integer"` for Ref params must update
|
|
39
|
+
|
|
40
|
+
### Fixed
|
|
41
|
+
|
|
42
|
+
- **`Handler.deregister` now unsubscribes from Bus** — `Dex::Event::Handler.deregister(klass)` removes the handler from both the registry and the event Bus. Previously, deregistered handlers remained subscribed and would still fire on published events
|
|
43
|
+
- **Registry prunes stale entries** — `registry` now removes unreachable class references from the backing Set during each call, preventing memory leaks from code reload cycles
|
|
44
|
+
- **`description(false)` and `desc: false` now raise `ArgumentError`** — previously accepted as "missing" values due to falsey evaluation. Both DSL methods now validate with `!text.nil?` / `!desc.nil?` to enforce the String requirement, matching the library's fail-fast convention
|
|
45
|
+
- **`prop_descriptions` no longer leaks parent descriptions for redeclared props** — when a child class redefines a prop without `desc:`, the parent's description is cleared instead of being inherited. Providing a new `desc:` on the child works as before
|
|
46
|
+
- **Rake task validates handler format** — `rake dex:export SECTION=handlers FORMAT=json_schema` now raises a clear error instead of hitting `Handler.export`'s `ArgumentError`
|
|
47
|
+
|
|
3
48
|
## [0.7.0] - 2026-03-08
|
|
4
49
|
|
|
5
50
|
### Breaking
|
data/README.md
CHANGED
|
@@ -2,12 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
Rails patterns toolbelt. Equip to gain +4 DEX.
|
|
4
4
|
|
|
5
|
+
> **Active development.** dexkit is pre-1.0 and evolving rapidly. The public API may change between minor versions as the library matures.
|
|
6
|
+
|
|
5
7
|
**[Documentation](https://dex.razorjack.net)**
|
|
6
8
|
|
|
7
9
|
## Operations
|
|
8
10
|
|
|
9
11
|
Service objects with typed properties, transactions, error handling, and more.
|
|
10
12
|
|
|
13
|
+
Mongoid-only Rails apps work too – queries, recording, events, and forms all adapt automatically. Transactions are ActiveRecord-only (Mongoid users who need transactions can call `Mongoid.transaction` inside `perform`); `advisory_lock` is also ActiveRecord-only. Operation/event store models can be Mongoid documents; recording models must define the fields required by the enabled recording features.
|
|
14
|
+
|
|
11
15
|
```ruby
|
|
12
16
|
class Order::Place < Dex::Operation
|
|
13
17
|
prop :customer, _Ref(Customer)
|
|
@@ -132,6 +136,30 @@ end
|
|
|
132
136
|
Order::Place.call(product: product, customer: customer)
|
|
133
137
|
```
|
|
134
138
|
|
|
139
|
+
**Explain** – full preflight check in one call. Context, guards, idempotency, locks, settings – everything the operation would do, without doing it:
|
|
140
|
+
|
|
141
|
+
```ruby
|
|
142
|
+
info = Order::Place.explain(product: product, customer: customer, quantity: 2)
|
|
143
|
+
info[:callable] # => true (all guards pass)
|
|
144
|
+
info[:once][:status] # => :fresh (would execute, not replay)
|
|
145
|
+
info[:context][:source] # => { customer: :ambient }
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
**Registry & Export** — list all operations, export contracts as JSON or JSON Schema, and bridge to LLM function-calling via [ruby-llm](https://rubyllm.com/):
|
|
149
|
+
|
|
150
|
+
```ruby
|
|
151
|
+
# List all operations
|
|
152
|
+
Dex::Operation.registry # => #<Set: {Order::Place, Order::Cancel, ...}>
|
|
153
|
+
|
|
154
|
+
# Export contracts
|
|
155
|
+
Dex::Operation.export(format: :json_schema)
|
|
156
|
+
|
|
157
|
+
# LLM tools (requires ruby-llm gem)
|
|
158
|
+
chat = RubyLLM.chat
|
|
159
|
+
chat.with_tools(*Dex::Tool.all)
|
|
160
|
+
chat.ask("Place an order for 2 units of product #42")
|
|
161
|
+
```
|
|
162
|
+
|
|
135
163
|
**Transactions** on by default, **advisory locking**, **recording** to database, **callbacks**, and a customizable **pipeline** – all composable, all optional.
|
|
136
164
|
|
|
137
165
|
### Testing
|
|
@@ -180,7 +208,7 @@ Order::Placed.publish(order_id: 1, total: 99.99)
|
|
|
180
208
|
|
|
181
209
|
**Zero-config pub/sub** — define events and handlers, publish. No bus setup needed.
|
|
182
210
|
|
|
183
|
-
**Async by default** — handlers dispatched via ActiveJob. `sync: true` for inline.
|
|
211
|
+
**Async by default** — handlers dispatched via ActiveJob. `sync: true` for inline. If ActiveJob is not loaded, async publish raises `LoadError`.
|
|
184
212
|
|
|
185
213
|
**Causality tracing** — link events in chains with shared `trace_id`:
|
|
186
214
|
|
|
@@ -273,7 +301,7 @@ end
|
|
|
273
301
|
|
|
274
302
|
## Queries
|
|
275
303
|
|
|
276
|
-
Declarative query objects for filtering and sorting ActiveRecord
|
|
304
|
+
Declarative query objects for filtering and sorting ActiveRecord and Mongoid scopes.
|
|
277
305
|
|
|
278
306
|
```ruby
|
|
279
307
|
class Order::Query < Dex::Query
|
|
@@ -326,13 +354,18 @@ Full documentation at **[dex.razorjack.net](https://dex.razorjack.net)**.
|
|
|
326
354
|
|
|
327
355
|
## AI Coding Assistant Setup
|
|
328
356
|
|
|
329
|
-
dexkit ships LLM-optimized guides.
|
|
357
|
+
dexkit ships LLM-optimized guides. Install them as `AGENTS.md` files in your app directories so AI coding agents automatically know the API:
|
|
358
|
+
|
|
359
|
+
```bash
|
|
360
|
+
rake dex:guides
|
|
361
|
+
```
|
|
362
|
+
|
|
363
|
+
This copies guides into directories that exist (`app/operations/`, `app/events/`, `app/event_handlers/`, `app/forms/`, `app/queries/`), stamped with the installed dexkit version. Re-run after upgrading dexkit to sync. Existing hand-written `AGENTS.md` files are never overwritten (use `FORCE=1` to override).
|
|
364
|
+
|
|
365
|
+
Override paths for non-standard directory names:
|
|
330
366
|
|
|
331
367
|
```bash
|
|
332
|
-
|
|
333
|
-
cp $(bundle show dexkit)/guides/llm/EVENT.md app/event_handlers/CLAUDE.md
|
|
334
|
-
cp $(bundle show dexkit)/guides/llm/FORM.md app/forms/CLAUDE.md
|
|
335
|
-
cp $(bundle show dexkit)/guides/llm/QUERY.md app/queries/CLAUDE.md
|
|
368
|
+
rake dex:guides OPERATIONS_PATH=app/services
|
|
336
369
|
```
|
|
337
370
|
|
|
338
371
|
## License
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
PATH
|
|
2
|
+
remote: ..
|
|
3
|
+
specs:
|
|
4
|
+
dexkit (0.8.0)
|
|
5
|
+
activemodel (>= 6.1)
|
|
6
|
+
literal (~> 1.9)
|
|
7
|
+
zeitwerk (~> 2.6)
|
|
8
|
+
|
|
9
|
+
GEM
|
|
10
|
+
remote: https://rubygems.org/
|
|
11
|
+
specs:
|
|
12
|
+
actionpack (8.1.2)
|
|
13
|
+
actionview (= 8.1.2)
|
|
14
|
+
activesupport (= 8.1.2)
|
|
15
|
+
nokogiri (>= 1.8.5)
|
|
16
|
+
rack (>= 2.2.4)
|
|
17
|
+
rack-session (>= 1.0.1)
|
|
18
|
+
rack-test (>= 0.6.3)
|
|
19
|
+
rails-dom-testing (~> 2.2)
|
|
20
|
+
rails-html-sanitizer (~> 1.6)
|
|
21
|
+
useragent (~> 0.16)
|
|
22
|
+
actionview (8.1.2)
|
|
23
|
+
activesupport (= 8.1.2)
|
|
24
|
+
builder (~> 3.1)
|
|
25
|
+
erubi (~> 1.11)
|
|
26
|
+
rails-dom-testing (~> 2.2)
|
|
27
|
+
rails-html-sanitizer (~> 1.6)
|
|
28
|
+
activejob (8.1.2)
|
|
29
|
+
activesupport (= 8.1.2)
|
|
30
|
+
globalid (>= 0.3.6)
|
|
31
|
+
activemodel (8.1.2)
|
|
32
|
+
activesupport (= 8.1.2)
|
|
33
|
+
activesupport (8.1.2)
|
|
34
|
+
base64
|
|
35
|
+
bigdecimal
|
|
36
|
+
concurrent-ruby (~> 1.0, >= 1.3.1)
|
|
37
|
+
connection_pool (>= 2.2.5)
|
|
38
|
+
drb
|
|
39
|
+
i18n (>= 1.6, < 2)
|
|
40
|
+
json
|
|
41
|
+
logger (>= 1.4.2)
|
|
42
|
+
minitest (>= 5.1)
|
|
43
|
+
securerandom (>= 0.3)
|
|
44
|
+
tzinfo (~> 2.0, >= 2.0.5)
|
|
45
|
+
uri (>= 0.13.1)
|
|
46
|
+
base64 (0.3.0)
|
|
47
|
+
bigdecimal (4.0.1)
|
|
48
|
+
bson (5.2.0)
|
|
49
|
+
builder (3.3.0)
|
|
50
|
+
concurrent-ruby (1.3.6)
|
|
51
|
+
connection_pool (3.0.2)
|
|
52
|
+
crass (1.0.6)
|
|
53
|
+
date (3.5.1)
|
|
54
|
+
drb (2.2.3)
|
|
55
|
+
erb (6.0.2)
|
|
56
|
+
erubi (1.13.1)
|
|
57
|
+
globalid (1.3.0)
|
|
58
|
+
activesupport (>= 6.1)
|
|
59
|
+
i18n (1.14.8)
|
|
60
|
+
concurrent-ruby (~> 1.0)
|
|
61
|
+
io-console (0.8.2)
|
|
62
|
+
irb (1.17.0)
|
|
63
|
+
pp (>= 0.6.0)
|
|
64
|
+
prism (>= 1.3.0)
|
|
65
|
+
rdoc (>= 4.0.0)
|
|
66
|
+
reline (>= 0.4.2)
|
|
67
|
+
json (2.19.1)
|
|
68
|
+
literal (1.9.0)
|
|
69
|
+
zeitwerk
|
|
70
|
+
logger (1.7.0)
|
|
71
|
+
loofah (2.25.0)
|
|
72
|
+
crass (~> 1.0.2)
|
|
73
|
+
nokogiri (>= 1.12.0)
|
|
74
|
+
minitest (6.0.2)
|
|
75
|
+
drb (~> 2.0)
|
|
76
|
+
prism (~> 1.5)
|
|
77
|
+
mongo (2.23.0)
|
|
78
|
+
base64
|
|
79
|
+
bson (>= 4.14.1, < 6.0.0)
|
|
80
|
+
mongoid (9.0.10)
|
|
81
|
+
activemodel (>= 5.1, < 8.2, != 7.0.0)
|
|
82
|
+
concurrent-ruby (>= 1.0.5, < 2.0)
|
|
83
|
+
mongo (>= 2.18.0, < 3.0.0)
|
|
84
|
+
nokogiri (1.19.1-aarch64-linux-gnu)
|
|
85
|
+
racc (~> 1.4)
|
|
86
|
+
nokogiri (1.19.1-aarch64-linux-musl)
|
|
87
|
+
racc (~> 1.4)
|
|
88
|
+
nokogiri (1.19.1-arm-linux-gnu)
|
|
89
|
+
racc (~> 1.4)
|
|
90
|
+
nokogiri (1.19.1-arm-linux-musl)
|
|
91
|
+
racc (~> 1.4)
|
|
92
|
+
nokogiri (1.19.1-arm64-darwin)
|
|
93
|
+
racc (~> 1.4)
|
|
94
|
+
nokogiri (1.19.1-x86_64-darwin)
|
|
95
|
+
racc (~> 1.4)
|
|
96
|
+
nokogiri (1.19.1-x86_64-linux-gnu)
|
|
97
|
+
racc (~> 1.4)
|
|
98
|
+
nokogiri (1.19.1-x86_64-linux-musl)
|
|
99
|
+
racc (~> 1.4)
|
|
100
|
+
ostruct (0.6.3)
|
|
101
|
+
pp (0.6.3)
|
|
102
|
+
prettyprint
|
|
103
|
+
prettyprint (0.2.0)
|
|
104
|
+
prism (1.9.0)
|
|
105
|
+
psych (5.3.1)
|
|
106
|
+
date
|
|
107
|
+
stringio
|
|
108
|
+
racc (1.8.1)
|
|
109
|
+
rack (3.2.5)
|
|
110
|
+
rack-session (2.1.1)
|
|
111
|
+
base64 (>= 0.1.0)
|
|
112
|
+
rack (>= 3.0.0)
|
|
113
|
+
rack-test (2.2.0)
|
|
114
|
+
rack (>= 1.3)
|
|
115
|
+
rackup (2.3.1)
|
|
116
|
+
rack (>= 3)
|
|
117
|
+
rails-dom-testing (2.3.0)
|
|
118
|
+
activesupport (>= 5.0.0)
|
|
119
|
+
minitest
|
|
120
|
+
nokogiri (>= 1.6)
|
|
121
|
+
rails-html-sanitizer (1.7.0)
|
|
122
|
+
loofah (~> 2.25)
|
|
123
|
+
nokogiri (>= 1.15.7, != 1.16.7, != 1.16.6, != 1.16.5, != 1.16.4, != 1.16.3, != 1.16.2, != 1.16.1, != 1.16.0.rc1, != 1.16.0)
|
|
124
|
+
railties (8.1.2)
|
|
125
|
+
actionpack (= 8.1.2)
|
|
126
|
+
activesupport (= 8.1.2)
|
|
127
|
+
irb (~> 1.13)
|
|
128
|
+
rackup (>= 1.0.0)
|
|
129
|
+
rake (>= 12.2)
|
|
130
|
+
thor (~> 1.0, >= 1.2.2)
|
|
131
|
+
tsort (>= 0.2)
|
|
132
|
+
zeitwerk (~> 2.6)
|
|
133
|
+
rake (13.3.1)
|
|
134
|
+
rdoc (7.2.0)
|
|
135
|
+
erb
|
|
136
|
+
psych (>= 4.0.0)
|
|
137
|
+
tsort
|
|
138
|
+
reline (0.6.3)
|
|
139
|
+
io-console (~> 0.5)
|
|
140
|
+
securerandom (0.4.1)
|
|
141
|
+
stringio (3.2.0)
|
|
142
|
+
thor (1.5.0)
|
|
143
|
+
tsort (0.2.0)
|
|
144
|
+
tzinfo (2.0.6)
|
|
145
|
+
concurrent-ruby (~> 1.0)
|
|
146
|
+
uri (1.1.1)
|
|
147
|
+
useragent (0.16.11)
|
|
148
|
+
zeitwerk (2.7.5)
|
|
149
|
+
|
|
150
|
+
PLATFORMS
|
|
151
|
+
aarch64-linux-gnu
|
|
152
|
+
aarch64-linux-musl
|
|
153
|
+
arm-linux-gnu
|
|
154
|
+
arm-linux-musl
|
|
155
|
+
arm64-darwin
|
|
156
|
+
x86_64-darwin
|
|
157
|
+
x86_64-linux-gnu
|
|
158
|
+
x86_64-linux-musl
|
|
159
|
+
|
|
160
|
+
DEPENDENCIES
|
|
161
|
+
actionpack (>= 6.1)
|
|
162
|
+
activejob (>= 6.1)
|
|
163
|
+
activesupport (>= 6.1)
|
|
164
|
+
dexkit!
|
|
165
|
+
mongoid (>= 8.0)
|
|
166
|
+
ostruct
|
|
167
|
+
railties (>= 6.1)
|
|
168
|
+
|
|
169
|
+
CHECKSUMS
|
|
170
|
+
actionpack (8.1.2) sha256=ced74147a1f0daafaa4bab7f677513fd4d3add574c7839958f7b4f1de44f8423
|
|
171
|
+
actionview (8.1.2) sha256=80455b2588911c9b72cec22d240edacb7c150e800ef2234821269b2b2c3e2e5b
|
|
172
|
+
activejob (8.1.2) sha256=908dab3713b101859536375819f4156b07bdf4c232cc645e7538adb9e302f825
|
|
173
|
+
activemodel (8.1.2) sha256=e21358c11ce68aed3f9838b7e464977bc007b4446c6e4059781e1d5c03bcf33e
|
|
174
|
+
activesupport (8.1.2) sha256=88842578ccd0d40f658289b0e8c842acfe9af751afee2e0744a7873f50b6fdae
|
|
175
|
+
base64 (0.3.0) sha256=27337aeabad6ffae05c265c450490628ef3ebd4b67be58257393227588f5a97b
|
|
176
|
+
bigdecimal (4.0.1) sha256=8b07d3d065a9f921c80ceaea7c9d4ae596697295b584c296fe599dd0ad01c4a7
|
|
177
|
+
bson (5.2.0) sha256=c468c1e8a3cfa1e80531cc519a890f85586986721d8e305f83465cc36bb82608
|
|
178
|
+
builder (3.3.0) sha256=497918d2f9dca528fdca4b88d84e4ef4387256d984b8154e9d5d3fe5a9c8835f
|
|
179
|
+
concurrent-ruby (1.3.6) sha256=6b56837e1e7e5292f9864f34b69c5a2cbc75c0cf5338f1ce9903d10fa762d5ab
|
|
180
|
+
connection_pool (3.0.2) sha256=33fff5ba71a12d2aa26cb72b1db8bba2a1a01823559fb01d29eb74c286e62e0a
|
|
181
|
+
crass (1.0.6) sha256=dc516022a56e7b3b156099abc81b6d2b08ea1ed12676ac7a5657617f012bd45d
|
|
182
|
+
date (3.5.1) sha256=750d06384d7b9c15d562c76291407d89e368dda4d4fff957eb94962d325a0dc0
|
|
183
|
+
dexkit (0.8.0)
|
|
184
|
+
drb (2.2.3) sha256=0b00d6fdb50995fe4a45dea13663493c841112e4068656854646f418fda13373
|
|
185
|
+
erb (6.0.2) sha256=9fe6264d44f79422c87490a1558479bd0e7dad4dd0e317656e67ea3077b5242b
|
|
186
|
+
erubi (1.13.1) sha256=a082103b0885dbc5ecf1172fede897f9ebdb745a4b97a5e8dc63953db1ee4ad9
|
|
187
|
+
globalid (1.3.0) sha256=05c639ad6eb4594522a0b07983022f04aa7254626ab69445a0e493aa3786ff11
|
|
188
|
+
i18n (1.14.8) sha256=285778639134865c5e0f6269e0b818256017e8cde89993fdfcbfb64d088824a5
|
|
189
|
+
io-console (0.8.2) sha256=d6e3ae7a7cc7574f4b8893b4fca2162e57a825b223a177b7afa236c5ef9814cc
|
|
190
|
+
irb (1.17.0) sha256=168c4ddb93d8a361a045c41d92b2952c7a118fa73f23fe14e55609eb7a863aae
|
|
191
|
+
json (2.19.1) sha256=dd94fdc59e48bff85913829a32350b3148156bc4fd2a95a2568a78b11344082d
|
|
192
|
+
literal (1.9.0) sha256=b1dfac91931e71e1c4ebfddd4b459306f2973e9f749e077a647fece6ea15414a
|
|
193
|
+
logger (1.7.0) sha256=196edec7cc44b66cfb40f9755ce11b392f21f7967696af15d274dde7edff0203
|
|
194
|
+
loofah (2.25.0) sha256=df5ed7ac3bac6a4ec802df3877ee5cc86d027299f8952e6243b3dac446b060e6
|
|
195
|
+
minitest (6.0.2) sha256=db6e57956f6ecc6134683b4c87467d6dd792323c7f0eea7b93f66bd284adbc3d
|
|
196
|
+
mongo (2.23.0) sha256=be2fe4cc6f7119fa6b79e82a1963b2406856b4dc92d0ccfb74db543897be3109
|
|
197
|
+
mongoid (9.0.10) sha256=351192e70027276748f3c946b8926fad9254356e36021dacb5cec08d0740f21d
|
|
198
|
+
nokogiri (1.19.1-aarch64-linux-gnu) sha256=cfdb0eafd9a554a88f12ebcc688d2b9005f9fce42b00b970e3dc199587b27f32
|
|
199
|
+
nokogiri (1.19.1-aarch64-linux-musl) sha256=1e2150ab43c3b373aba76cd1190af7b9e92103564063e48c474f7600923620b5
|
|
200
|
+
nokogiri (1.19.1-arm-linux-gnu) sha256=0a39ed59abe3bf279fab9dd4c6db6fe8af01af0608f6e1f08b8ffa4e5d407fa3
|
|
201
|
+
nokogiri (1.19.1-arm-linux-musl) sha256=3a18e559ee499b064aac6562d98daab3d39ba6cbb4074a1542781b2f556db47d
|
|
202
|
+
nokogiri (1.19.1-arm64-darwin) sha256=dfe2d337e6700eac47290407c289d56bcf85805d128c1b5a6434ddb79731cb9e
|
|
203
|
+
nokogiri (1.19.1-x86_64-darwin) sha256=7093896778cc03efb74b85f915a775862730e887f2e58d6921e3fa3d981e68bf
|
|
204
|
+
nokogiri (1.19.1-x86_64-linux-gnu) sha256=1a4902842a186b4f901078e692d12257678e6133858d0566152fe29cdb98456a
|
|
205
|
+
nokogiri (1.19.1-x86_64-linux-musl) sha256=4267f38ad4fc7e52a2e7ee28ed494e8f9d8eb4f4b3320901d55981c7b995fc23
|
|
206
|
+
ostruct (0.6.3) sha256=95a2ed4a4bd1d190784e666b47b2d3f078e4a9efda2fccf18f84ddc6538ed912
|
|
207
|
+
pp (0.6.3) sha256=2951d514450b93ccfeb1df7d021cae0da16e0a7f95ee1e2273719669d0ab9df6
|
|
208
|
+
prettyprint (0.2.0) sha256=2bc9e15581a94742064a3cc8b0fb9d45aae3d03a1baa6ef80922627a0766f193
|
|
209
|
+
prism (1.9.0) sha256=7b530c6a9f92c24300014919c9dcbc055bf4cdf51ec30aed099b06cd6674ef85
|
|
210
|
+
psych (5.3.1) sha256=eb7a57cef10c9d70173ff74e739d843ac3b2c019a003de48447b2963d81b1974
|
|
211
|
+
racc (1.8.1) sha256=4a7f6929691dbec8b5209a0b373bc2614882b55fc5d2e447a21aaa691303d62f
|
|
212
|
+
rack (3.2.5) sha256=4cbd0974c0b79f7a139b4812004a62e4c60b145cba76422e288ee670601ed6d3
|
|
213
|
+
rack-session (2.1.1) sha256=0b6dc07dea7e4b583f58a48e8b806d4c9f1c6c9214ebc202ec94562cbea2e4e9
|
|
214
|
+
rack-test (2.2.0) sha256=005a36692c306ac0b4a9350355ee080fd09ddef1148a5f8b2ac636c720f5c463
|
|
215
|
+
rackup (2.3.1) sha256=6c79c26753778e90983761d677a48937ee3192b3ffef6bc963c0950f94688868
|
|
216
|
+
rails-dom-testing (2.3.0) sha256=8acc7953a7b911ca44588bf08737bc16719f431a1cc3091a292bca7317925c1d
|
|
217
|
+
rails-html-sanitizer (1.7.0) sha256=28b145cceaf9cc214a9874feaa183c3acba036c9592b19886e0e45efc62b1e89
|
|
218
|
+
railties (8.1.2) sha256=1289ece76b4f7668fc46d07e55cc992b5b8751f2ad85548b7da351b8c59f8055
|
|
219
|
+
rake (13.3.1) sha256=8c9e89d09f66a26a01264e7e3480ec0607f0c497a861ef16063604b1b08eb19c
|
|
220
|
+
rdoc (7.2.0) sha256=8650f76cd4009c3b54955eb5d7e3a075c60a57276766ebf36f9085e8c9f23192
|
|
221
|
+
reline (0.6.3) sha256=1198b04973565b36ec0f11542ab3f5cfeeec34823f4e54cebde90968092b1835
|
|
222
|
+
securerandom (0.4.1) sha256=cc5193d414a4341b6e225f0cb4446aceca8e50d5e1888743fac16987638ea0b1
|
|
223
|
+
stringio (3.2.0) sha256=c37cb2e58b4ffbd33fe5cd948c05934af997b36e0b6ca6fdf43afa234cf222e1
|
|
224
|
+
thor (1.5.0) sha256=e3a9e55fe857e44859ce104a84675ab6e8cd59c650a49106a05f55f136425e73
|
|
225
|
+
tsort (0.2.0) sha256=9650a793f6859a43b6641671278f79cfead60ac714148aabe4e3f0060480089f
|
|
226
|
+
tzinfo (2.0.6) sha256=8daf828cc77bcf7d63b0e3bdb6caa47e2272dcfaf4fbfe46f8c3a9df087a829b
|
|
227
|
+
uri (1.1.1) sha256=379fa58d27ffb1387eaada68c749d1426738bd0f654d812fcc07e7568f5c57c6
|
|
228
|
+
useragent (0.16.11) sha256=700e6413ad4bb954bb63547fa098dddf7b0ebe75b40cc6f93b8d54255b173844
|
|
229
|
+
zeitwerk (2.7.5) sha256=d8da92128c09ea6ec62c949011b00ed4a20242b255293dd66bf41545398f73dd
|
|
230
|
+
|
|
231
|
+
BUNDLED WITH
|
|
232
|
+
4.0.4
|
data/guides/llm/EVENT.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Dex::Event — LLM Reference
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Install with `rake dex:guides` or copy manually to `app/events/AGENTS.md`.
|
|
4
4
|
|
|
5
5
|
---
|
|
6
6
|
|
|
@@ -56,7 +56,7 @@ event.publish(sync: true) # sync
|
|
|
56
56
|
OrderPlaced.publish(order_id: 1, total: 99.99, caused_by: parent_event)
|
|
57
57
|
```
|
|
58
58
|
|
|
59
|
-
**Async** (default): handlers dispatched via ActiveJob. **Sync**: handlers called inline.
|
|
59
|
+
**Async** (default): handlers dispatched via ActiveJob. If ActiveJob is not loaded, `publish(sync: false)` raises `LoadError`. **Sync**: handlers called inline.
|
|
60
60
|
|
|
61
61
|
---
|
|
62
62
|
|
|
@@ -109,7 +109,7 @@ class ProcessPayment < Dex::Event::Handler
|
|
|
109
109
|
end
|
|
110
110
|
```
|
|
111
111
|
|
|
112
|
-
When retries exhausted, exception propagates normally.
|
|
112
|
+
When retries exhausted, exception propagates normally. Async handlers and retries require ActiveJob to be loaded.
|
|
113
113
|
|
|
114
114
|
### Callbacks
|
|
115
115
|
|
|
@@ -157,7 +157,7 @@ class FulfillOrder < Dex::Event::Handler
|
|
|
157
157
|
end
|
|
158
158
|
```
|
|
159
159
|
|
|
160
|
-
Transactions are **disabled by default** on handlers (unlike operations). Opt in with `transaction`. The `after_commit` block defers until the transaction commits; on exception, deferred blocks are discarded.
|
|
160
|
+
Transactions are **disabled by default** on handlers (unlike operations). Opt in with `transaction`. The `after_commit` block defers until the transaction commits; on exception, deferred blocks are discarded. Transactions are ActiveRecord-only – in Mongoid-only apps, `after_commit` fires immediately after handler success.
|
|
161
161
|
|
|
162
162
|
### Custom Pipeline
|
|
163
163
|
|
|
@@ -231,6 +231,19 @@ create_table :event_records do |t|
|
|
|
231
231
|
end
|
|
232
232
|
```
|
|
233
233
|
|
|
234
|
+
Mongoid stores work too:
|
|
235
|
+
|
|
236
|
+
```ruby
|
|
237
|
+
class EventRecord
|
|
238
|
+
include Mongoid::Document
|
|
239
|
+
include Mongoid::Timestamps
|
|
240
|
+
|
|
241
|
+
field :event_type, type: String
|
|
242
|
+
field :payload, type: Hash
|
|
243
|
+
field :metadata, type: Hash
|
|
244
|
+
end
|
|
245
|
+
```
|
|
246
|
+
|
|
234
247
|
Persistence failures are silently rescued — they never halt event publishing.
|
|
235
248
|
|
|
236
249
|
---
|
|
@@ -294,7 +307,7 @@ Everything works without configuration. All three settings are optional.
|
|
|
294
307
|
|
|
295
308
|
```ruby
|
|
296
309
|
# test/test_helper.rb
|
|
297
|
-
require "dex/
|
|
310
|
+
require "dex/event/test_helpers"
|
|
298
311
|
|
|
299
312
|
class Minitest::Test
|
|
300
313
|
include Dex::Event::TestHelpers
|
|
@@ -383,4 +396,46 @@ end
|
|
|
383
396
|
|
|
384
397
|
---
|
|
385
398
|
|
|
399
|
+
## Registry, Export & Description
|
|
400
|
+
|
|
401
|
+
### Description
|
|
402
|
+
|
|
403
|
+
Events can declare a human-readable description. Props can include `desc:`:
|
|
404
|
+
|
|
405
|
+
```ruby
|
|
406
|
+
class Order::Placed < Dex::Event
|
|
407
|
+
description "Emitted after an order is successfully placed"
|
|
408
|
+
|
|
409
|
+
prop :order_id, Integer, desc: "The placed order"
|
|
410
|
+
prop :total, BigDecimal, desc: "Order total"
|
|
411
|
+
end
|
|
412
|
+
```
|
|
413
|
+
|
|
414
|
+
### Registry
|
|
415
|
+
|
|
416
|
+
```ruby
|
|
417
|
+
Dex::Event.registry # => #<Set: {Order::Placed, Order::Cancelled, ...}>
|
|
418
|
+
Dex::Event::Handler.registry # => #<Set: {NotifyWarehouse, SendConfirmation, ...}>
|
|
419
|
+
Dex::Event.deregister(klass)
|
|
420
|
+
Dex::Event::Handler.deregister(klass)
|
|
421
|
+
```
|
|
422
|
+
|
|
423
|
+
### Export
|
|
424
|
+
|
|
425
|
+
```ruby
|
|
426
|
+
Order::Placed.to_h
|
|
427
|
+
# => { name: "Order::Placed", description: "...", props: { order_id: { type: "Integer", ... } } }
|
|
428
|
+
|
|
429
|
+
Order::Placed.to_json_schema # JSON Schema (Draft 2020-12)
|
|
430
|
+
|
|
431
|
+
NotifyWarehouse.to_h
|
|
432
|
+
# => { name: "NotifyWarehouse", events: ["Order::Placed"], retries: 3, ... }
|
|
433
|
+
|
|
434
|
+
Dex::Event.export # all events as hashes
|
|
435
|
+
Dex::Event.export(format: :json_schema) # all as JSON Schema
|
|
436
|
+
Dex::Event::Handler.export # all handlers as hashes
|
|
437
|
+
```
|
|
438
|
+
|
|
439
|
+
---
|
|
440
|
+
|
|
386
441
|
**End of reference.**
|
data/guides/llm/FORM.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Dex::Form — LLM Reference
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Install with `rake dex:guides` or copy manually to `app/forms/AGENTS.md`.
|
|
4
4
|
|
|
5
5
|
---
|
|
6
6
|
|
|
@@ -224,7 +224,7 @@ validates :email, uniqueness: true
|
|
|
224
224
|
| `model:` | Explicit model class | `uniqueness: { model: User }` |
|
|
225
225
|
| `attribute:` | Column name if different | `uniqueness: { attribute: :email }` |
|
|
226
226
|
| `scope:` | Scoped uniqueness | `uniqueness: { scope: :tenant_id }` |
|
|
227
|
-
| `case_sensitive:` | Case-insensitive check | `uniqueness: { case_sensitive: false }` |
|
|
227
|
+
| `case_sensitive:` | Case-insensitive check (`LOWER()` on ActiveRecord, case-insensitive regex on Mongoid) | `uniqueness: { case_sensitive: false }` |
|
|
228
228
|
| `conditions:` | Extra query conditions | `uniqueness: { conditions: -> { where(active: true) } }` |
|
|
229
229
|
| `message:` | Custom error message | `uniqueness: { message: "already registered" }` |
|
|
230
230
|
|
|
@@ -237,7 +237,7 @@ validates :email, uniqueness: true
|
|
|
237
237
|
|
|
238
238
|
### Record exclusion
|
|
239
239
|
|
|
240
|
-
When `form.record` is persisted, the current record is excluded from the uniqueness check (for updates).
|
|
240
|
+
When `form.record` is persisted, the current record is excluded from the uniqueness check (for updates) on both ActiveRecord and Mongoid-backed forms.
|
|
241
241
|
|
|
242
242
|
---
|
|
243
243
|
|