hecks 1.0.0 → 1.0.2
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/lib/hecks/adapters/driven/in_memory_ordering.rb +9 -1
- data/lib/hecks/adapters/driven/sql_query_builder.rb +13 -2
- data/lib/hecks/bluebook/behaviour/value_object.rb +13 -7
- data/lib/hecks/bluebook/dsl/aggregate_builder.rb +30 -1
- data/lib/hecks/bluebook/dsl/command_builder.rb +53 -0
- data/lib/hecks/bluebook/dsl/domain_port_builder.rb +49 -7
- data/lib/hecks/bluebook/expression/ast_json.rb +149 -0
- data/lib/hecks/bluebook/expression/resolver.rb +25 -0
- data/lib/hecks/bluebook/expression.rb +1 -0
- data/lib/hecks/bluebook/model_check.rb +15 -1
- data/lib/hecks/bluebook/project_register.rb +25 -0
- data/lib/hecks/bluebook/value_object.rb +10 -1
- data/lib/hecks/fuzzing/invalid_value_generator.rb +3 -2
- data/lib/hecks/fuzzing/properties.rb +49 -4
- data/lib/hecks/language/bluebook/aggregate.bluebook +17 -0
- data/lib/hecks/language/hecksagon/domain_port.bluebook +25 -1
- data/lib/hecks/runtime/command_interpreter.rb +70 -23
- data/lib/hecks/runtime/command_rules/admissibility.rb +42 -7
- data/lib/hecks/runtime/command_rules/arithmetic.rb +33 -3
- data/lib/hecks/runtime/dependency_planning.rb +52 -5
- data/lib/hecks/runtime/entity_interpreter.rb +8 -1
- data/lib/hecks/runtime/read_model_interpreter.rb +13 -4
- data/lib/hecks/runtime/value.rb +54 -4
- data/lib/hecks/version.rb +1 -1
- data/lib/hecks.rb +21 -1
- metadata +4 -1
data/lib/hecks/runtime/value.rb
CHANGED
|
@@ -38,8 +38,8 @@ module Hecks
|
|
|
38
38
|
end
|
|
39
39
|
|
|
40
40
|
def type_name = @value_object.hecks_name
|
|
41
|
-
def [](field) = @fields[field
|
|
42
|
-
def key?(field) = @fields.key?(field
|
|
41
|
+
def [](field) = @fields[resolve_field(field)]
|
|
42
|
+
def key?(field) = @fields.key?(resolve_field(field))
|
|
43
43
|
def to_h = @fields.transform_values { |value| self.class.materialize(value) }
|
|
44
44
|
def to_json(*) = JSON.generate(to_h)
|
|
45
45
|
|
|
@@ -48,7 +48,7 @@ module Hecks
|
|
|
48
48
|
end
|
|
49
49
|
|
|
50
50
|
def with(field, value)
|
|
51
|
-
self.class.build(@value_object, @fields.merge(field
|
|
51
|
+
self.class.build(@value_object, @fields.merge(resolve_field(field) => value))
|
|
52
52
|
end
|
|
53
53
|
|
|
54
54
|
def self.materialize(value)
|
|
@@ -114,11 +114,61 @@ module Hecks
|
|
|
114
114
|
def method_missing(name, *args)
|
|
115
115
|
return @fields[name] if @fields.key?(name)
|
|
116
116
|
|
|
117
|
+
# THE LANGUAGE RULE, not a convenience: ANY value object with
|
|
118
|
+
# exactly one declared attribute answers `.value`, whatever that
|
|
119
|
+
# attribute is actually named — a single-attribute value object
|
|
120
|
+
# is a NAME for a scalar, not a genuine group
|
|
121
|
+
# ([[feedback_name_the_scalar_field]], `Behaviour::ValueObject#
|
|
122
|
+
# sole_attribute`), so `money.value` reads `Money`'s own `amount`
|
|
123
|
+
# exactly as `label.value` reads a shorthand-declared `value`.
|
|
124
|
+
# AFTER the real-field lookup above, on purpose: a field
|
|
125
|
+
# literally named `value` is already answered there (and IS the
|
|
126
|
+
# sole attribute whenever the count is one), so this branch only
|
|
127
|
+
# ever aliases, never shadows. A MULTI-attribute value object
|
|
128
|
+
# keeps its NoMethodError — `sole_attribute` answers nil for it,
|
|
129
|
+
# and falling through to `super` is exactly the refusal it
|
|
130
|
+
# always gave: with two or more fields there is no single value
|
|
131
|
+
# `.value` could honestly mean.
|
|
132
|
+
if name == :value
|
|
133
|
+
sole = @value_object.sole_attribute
|
|
134
|
+
return @fields[sole.name] if sole
|
|
135
|
+
end
|
|
136
|
+
|
|
117
137
|
super
|
|
118
138
|
end
|
|
119
139
|
|
|
120
140
|
def respond_to_missing?(name, include_private = false)
|
|
121
|
-
@fields.key?(name)
|
|
141
|
+
return true if @fields.key?(name)
|
|
142
|
+
return true if name == :value && @value_object.sole_attribute
|
|
143
|
+
|
|
144
|
+
super
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
private
|
|
148
|
+
|
|
149
|
+
# THE `.value` ALIAS FOR INDEXED ACCESS — the same language rule
|
|
150
|
+
# `method_missing` above enforces for method reads, applied to
|
|
151
|
+
# `[]`/`key?`/`with`: `:value` names a single-attribute value
|
|
152
|
+
# object's sole field whatever that field is actually called. A
|
|
153
|
+
# REAL key always wins first (a field literally named `value` is
|
|
154
|
+
# its own answer, and is the sole attribute anyway whenever the
|
|
155
|
+
# count is one), so this only ever resolves a `:value` that would
|
|
156
|
+
# otherwise MISS — it can never redirect a genuine field read.
|
|
157
|
+
# `with(:value, x)` in particular NEEDS this: merging a literal
|
|
158
|
+
# `:value` key beside a sole field named `amount` would build a
|
|
159
|
+
# two-key hash for a one-field shape and be refused (or worse,
|
|
160
|
+
# stored) downstream — aliasing at the merge is what keeps the
|
|
161
|
+
# write half of the rule as true as the read half.
|
|
162
|
+
def resolve_field(field)
|
|
163
|
+
sym = field.to_sym
|
|
164
|
+
return sym if @fields.key?(sym)
|
|
165
|
+
|
|
166
|
+
if sym == :value
|
|
167
|
+
sole = @value_object.sole_attribute
|
|
168
|
+
return sole.name if sole
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
sym
|
|
122
172
|
end
|
|
123
173
|
end
|
|
124
174
|
end
|
data/lib/hecks/version.rb
CHANGED
data/lib/hecks.rb
CHANGED
|
@@ -100,7 +100,27 @@ module Hecks
|
|
|
100
100
|
end
|
|
101
101
|
|
|
102
102
|
def hecksagon(name, &block) = collect(:add_hecksagon, Bluebook::DSL::HecksagonBuilder.build(name, &block))
|
|
103
|
-
|
|
103
|
+
# REPOINTED TO DomainPortBuilder — the migration DomainPort's own
|
|
104
|
+
# class comment names as its goal, now landed for the top-level
|
|
105
|
+
# `.port` file callers too (the aggregate-scoped `Thing.port(...)`,
|
|
106
|
+
# binding_proxy.rb, already went through this builder). Every real
|
|
107
|
+
# `.port` file only ever spells `verb`/`signal` (no `.port` file
|
|
108
|
+
# declares operations — that's DomainPort's own newer shape), and
|
|
109
|
+
# DomainPortBuilder's own bare-verb branch produces the exact same
|
|
110
|
+
# `Port` object PortBuilder itself did (dsl_spec.rb's own byte-
|
|
111
|
+
# identity check) — a pure repoint, no behavior change for any
|
|
112
|
+
# existing caller reading `.verb`/`.signal` off what comes back.
|
|
113
|
+
#
|
|
114
|
+
# `legacy_bare_port: true` — the ONE real semantic gap this repoint
|
|
115
|
+
# would otherwise open: `PortBuilder#build` never refused a
|
|
116
|
+
# completely empty build (no verb, no signal even), a real shape
|
|
117
|
+
# dsl_spec.rb's own "a port" tests exercise (`signal`-only, no
|
|
118
|
+
# `verb`). `DomainPortBuilder`'s own "declares no verb and no
|
|
119
|
+
# operations" refusal is real and correct for its OTHER two callers
|
|
120
|
+
# (`BindingProxy#port`, `HecksagonBuilder#port_impl`) — only this,
|
|
121
|
+
# the literal top-level `.port` file entry point, keeps the older,
|
|
122
|
+
# looser rule (see `DomainPortBuilder#initialize`'s own comment).
|
|
123
|
+
def port(name, &block) = collect(:add_port, Bluebook::DSL::DomainPortBuilder.build(name, legacy_bare_port: true, &block))
|
|
104
124
|
def adapter(name, &block) = collect(:add_adapter, Bluebook::DSL::AdapterBuilder.build(name, &block))
|
|
105
125
|
def world(name, &block) = collect(:add_world, Bluebook::DSL::WorldBuilder.build(name, &block))
|
|
106
126
|
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: hecks
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.0.
|
|
4
|
+
version: 1.0.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Chris Young
|
|
@@ -140,6 +140,7 @@ files:
|
|
|
140
140
|
- lib/hecks/bluebook/dsl/world_builder.rb
|
|
141
141
|
- lib/hecks/bluebook/entity.rb
|
|
142
142
|
- lib/hecks/bluebook/expression.rb
|
|
143
|
+
- lib/hecks/bluebook/expression/ast_json.rb
|
|
143
144
|
- lib/hecks/bluebook/expression/canonical_form.rb
|
|
144
145
|
- lib/hecks/bluebook/expression/evaluator.rb
|
|
145
146
|
- lib/hecks/bluebook/expression/projection.json
|
|
@@ -427,6 +428,8 @@ licenses:
|
|
|
427
428
|
metadata:
|
|
428
429
|
allowed_push_host: https://rubygems.org
|
|
429
430
|
source_code_uri: https://github.com/heckslabs/hecks
|
|
431
|
+
changelog_uri: https://github.com/heckslabs/hecks/blob/main/CHANGELOG.md
|
|
432
|
+
documentation_uri: https://rubydoc.info/gems/hecks
|
|
430
433
|
post_install_message:
|
|
431
434
|
rdoc_options: []
|
|
432
435
|
require_paths:
|