hecks 2.6.0 → 2.8.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/exe/hecks +13 -0
- data/lib/hecks/adapters/driven/google_authentication.rb +1 -1
- data/lib/hecks/adapters/driven/lambda/client.rb +1 -1
- data/lib/hecks/adapters/driven/memory.rb +1 -1
- data/lib/hecks/adapters/driven/postgres.rb +1 -1
- data/lib/hecks/adapters/driven/prism.rb +2 -2
- data/lib/hecks/adapters/driven/sqlite/projection.rb +1 -1
- data/lib/hecks/adapters/driven/tenant_provisioner.rb +31 -10
- data/lib/hecks/behaviors/expectations.rb +2 -2
- data/lib/hecks/bluebook/assembly/contract.rb +1 -1
- data/lib/hecks/bluebook/assembly/contracts.rb +5 -5
- data/lib/hecks/bluebook/assembly/specializer.rb +2 -2
- data/lib/hecks/bluebook/assembly.rb +1 -1
- data/lib/hecks/bluebook/behaviour/chapter.rb +5 -2
- data/lib/hecks/bluebook/behaviour/read_model.rb +18 -0
- data/lib/hecks/bluebook/capabilities.rb +2 -2
- data/lib/hecks/bluebook/chapter.rb +1 -1
- data/lib/hecks/bluebook/dsl/aggregate_builder.rb +2 -2
- data/lib/hecks/bluebook/dsl/binding_proxy.rb +6 -1
- data/lib/hecks/bluebook/dsl/bluebook_builder.rb +2 -2
- data/lib/hecks/bluebook/dsl/bootstrap_table.rb +2 -0
- data/lib/hecks/bluebook/dsl/command_builder.rb +3 -3
- data/lib/hecks/bluebook/dsl/entity_builder.rb +1 -1
- data/lib/hecks/bluebook/dsl/generic_dispatch.rb +1 -1
- data/lib/hecks/bluebook/dsl/hecksagon_builder.rb +14 -9
- data/lib/hecks/bluebook/dsl/port_operation_builder.rb +1 -1
- data/lib/hecks/bluebook/dsl/rule_reference.rb +3 -3
- data/lib/hecks/bluebook/dsl/translation_builder.rb +1 -1
- data/lib/hecks/bluebook/dsl/world_builder.rb +47 -3
- data/lib/hecks/bluebook/hexagon.rb +15 -7
- data/lib/hecks/bluebook/meta_validator/judge.rb +3 -3
- data/lib/hecks/bluebook/meta_validator/plan.rb +4 -4
- data/lib/hecks/bluebook/meta_validator/readings.rb +1 -1
- data/lib/hecks/bluebook/meta_validator/reconstruction.rb +2 -2
- data/lib/hecks/bluebook/meta_validator/shapes.rb +1 -1
- data/lib/hecks/bluebook/meta_validator/syntax_boot.rb +11 -10
- data/lib/hecks/bluebook/meta_validator/world_judge.rb +3 -1
- data/lib/hecks/bluebook/meta_validator.rb +1 -1
- data/lib/hecks/bluebook/model_check/client_profile.rb +4 -70
- data/lib/hecks/bluebook/model_check.rb +13 -14
- data/lib/hecks/cache_dir.rb +103 -0
- data/lib/hecks/cli/document.rb +104 -0
- data/lib/hecks/cli/ir.rb +47 -0
- data/lib/hecks/cli/mcp.rb +32 -0
- data/lib/hecks/cli/mcp_door.rb +461 -0
- data/lib/hecks/cli/model_check.rb +270 -0
- data/lib/hecks/cli/project_cli.rb +123 -0
- data/lib/hecks/cli/project_diagrams.rb +43 -0
- data/lib/hecks/cli/run.rb +219 -0
- data/lib/hecks/cli/smoke_test.rb +59 -0
- data/lib/hecks/cli/stores.rb +54 -0
- data/lib/hecks/cli.rb +166 -0
- data/lib/hecks/embryonaut_bluebook/lock.rb +72 -0
- data/lib/hecks/embryonaut_bluebook/shape.rb +47 -0
- data/lib/hecks/embryonaut_bluebook/vendor.rb +194 -0
- data/lib/hecks/embryonaut_bluebook/vendor_cli.rb +88 -0
- data/lib/hecks/embryonaut_bluebook.rb +29 -3
- data/lib/hecks/facade/handle.rb +2 -2
- data/lib/hecks/facade/surface/aggregate_door.rb +1 -1
- data/lib/hecks/forms/value_object_shape.rb +1 -1
- data/lib/hecks/framework/bluebook/console_settings.bluebook +3 -3
- data/lib/hecks/language/bluebook/vocabulary.bluebook +16 -0
- data/lib/hecks/language/world/world.bluebook +32 -2
- data/lib/hecks/mcp_door_scope.rb +176 -0
- data/lib/hecks/ports/key_vault.rb +1 -1
- data/lib/hecks/ports/persistence/append_only.rb +1 -1
- data/lib/hecks/ports/persistence/binding_policy.rb +16 -5
- data/lib/hecks/ports/persistence/plugins/era/era_check.rb +3 -2
- data/lib/hecks/ports/persistence/plugins/era/era_guard.rb +2 -2
- data/lib/hecks/ports/persistence/plugins/era/era_tamper.rb +2 -2
- data/lib/hecks/ports/persistence/plugins/era/expected_era.rb +132 -0
- data/lib/hecks/ports/persistence/plugins/era/lineage.rb +1 -1
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/era_store.rb +2 -2
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/head_compiler.rb +1 -1
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/minter.rb +1 -1
- data/lib/hecks/ports/persistence/plugins/era/translation/rule_compiler.rb +13 -7
- data/lib/hecks/ports/persistence/plugins/era.rb +7 -4
- data/lib/hecks/ports/persistence/postgres_dump/connection.rb +73 -0
- data/lib/hecks/ports/persistence/postgres_dump.rb +125 -0
- data/lib/hecks/ports/persistence/repository_factory.rb +2 -2
- data/lib/hecks/ports/persistence/state_codec.rb +1 -1
- data/lib/hecks/ports/persistence.rb +4 -0
- data/lib/hecks/projections/deploy/fargate/assembly.rb +193 -0
- data/lib/hecks/projections/deploy/fargate/cdn.rb +318 -0
- data/lib/hecks/projections/deploy/fargate/cdn_default.rb +87 -0
- data/lib/hecks/projections/deploy/fargate/check.rb +172 -0
- data/lib/hecks/projections/deploy/fargate/containers.rb +412 -0
- data/lib/hecks/projections/deploy/fargate/extras.rb +268 -0
- data/lib/hecks/projections/deploy/fargate/monitoring.rb +448 -0
- data/lib/hecks/projections/deploy/fargate/settings.rb +235 -0
- data/lib/hecks/projections/deploy/fargate/yaml.rb +116 -0
- data/lib/hecks/projections/deploy/fargate.rb +188 -139
- data/lib/hecks/projections/deploy/lambda.rb +8 -8
- data/lib/hecks/projections/deploy/preview/access_yaml.rb +145 -0
- data/lib/hecks/projections/deploy/preview/containers.rb +218 -0
- data/lib/hecks/projections/deploy/preview/preview.sh.erb +446 -0
- data/lib/hecks/projections/deploy/preview/routing_yaml.rb +216 -0
- data/lib/hecks/projections/deploy/preview/script.rb +40 -0
- data/lib/hecks/projections/deploy/preview/settings.rb +140 -0
- data/lib/hecks/projections/deploy/preview/task_yaml.rb +215 -0
- data/lib/hecks/projections/deploy/preview/template.rb +247 -0
- data/lib/hecks/projections/deploy/preview/yaml_text.rb +48 -0
- data/lib/hecks/projections/deploy/preview.rb +103 -0
- data/lib/hecks/projections/deploy/scripts/deploy-service.sh.tmpl +182 -0
- data/lib/hecks/projections/deploy/scripts/expected-era.header +17 -0
- data/lib/hecks/projections/deploy/scripts/hosting.mk.tmpl +54 -0
- data/lib/hecks/projections/deploy/scripts/settings.rb +114 -0
- data/lib/hecks/projections/deploy/scripts/smoke-after-deploy.sh.tmpl +232 -0
- data/lib/hecks/projections/deploy/scripts.rb +171 -0
- data/lib/hecks/projections/deploy/smoke/harness.js +366 -0
- data/lib/hecks/projections/deploy/smoke/workflow.yml.tmpl +56 -0
- data/lib/hecks/projections/deploy/smoke.rb +159 -0
- data/lib/hecks/projections/deploy/template_diff/comparer.rb +231 -0
- data/lib/hecks/projections/deploy/template_diff/loader.rb +105 -0
- data/lib/hecks/projections/deploy/template_diff.rb +173 -0
- data/lib/hecks/projections/glossary/sensitivity.rb +1 -1
- data/lib/hecks/projections/reference.rb +7 -1
- data/lib/hecks/projections.rb +2 -0
- data/lib/hecks/projector/exporter.rb +4 -4
- data/lib/hecks/projector/target.rb +1 -1
- data/lib/hecks/release/gem_pin/published_versions.rb +58 -0
- data/lib/hecks/release/gem_pin.rb +112 -0
- data/lib/hecks/release/runner/ci_publisher.rb +96 -0
- data/lib/hecks/release/runner/commands.rb +68 -0
- data/lib/hecks/release/runner/console.rb +52 -0
- data/lib/hecks/release/runner/gem_publisher.rb +44 -0
- data/lib/hecks/release/runner/git.rb +48 -0
- data/lib/hecks/release/runner/npm_publisher.rb +89 -0
- data/lib/hecks/release/runner/preflight.rb +119 -0
- data/lib/hecks/release/runner/published.rb +55 -0
- data/lib/hecks/release/runner/tagger.rb +87 -0
- data/lib/hecks/release/runner.rb +244 -0
- data/lib/hecks/router/namespace_installer.rb +1 -1
- data/lib/hecks/runtime/command_interpreter.rb +3 -3
- data/lib/hecks/runtime/command_rules/admissibility.rb +2 -2
- data/lib/hecks/runtime/command_rules/arithmetic.rb +2 -2
- data/lib/hecks/runtime/entity_element.rb +1 -1
- data/lib/hecks/runtime/entity_interpreter.rb +1 -1
- data/lib/hecks/runtime/invocation.rb +1 -1
- data/lib/hecks/runtime/loader.rb +27 -3
- data/lib/hecks/runtime/outbox.rb +1 -1
- data/lib/hecks/runtime/reaction_invocation.rb +3 -3
- data/lib/hecks/runtime/read_model_interpreter.rb +37 -15
- data/lib/hecks/runtime/reference_hop.rb +4 -4
- data/lib/hecks/runtime/registry/saga_persistence.rb +8 -2
- data/lib/hecks/runtime/registry/verification.rb +15 -13
- data/lib/hecks/runtime/registry/world_defaults.rb +106 -0
- data/lib/hecks/runtime/registry.rb +22 -13
- data/lib/hecks/runtime/saga_interpreter.rb +1 -1
- data/lib/hecks/runtime/tenant_check.rb +1 -1
- data/lib/hecks/runtime/value/coercion.rb +3 -3
- data/lib/hecks/runtime/value/entity_list_coercion.rb +1 -1
- data/lib/hecks/storehouse.rb +18 -12
- data/lib/hecks/vendoring/git_environment.rb +35 -0
- data/lib/hecks/vendoring/git_source.rb +102 -0
- data/lib/hecks/vendoring.rb +102 -0
- data/lib/hecks/version.rb +1 -1
- data/lib/hecks/vocabulary.rb +5 -0
- data/lib/hecks.rb +8 -2
- metadata +72 -58
- data/lib/hecks/bench/cli.rb +0 -74
- data/lib/hecks/bench/environment.rb +0 -100
- data/lib/hecks/bench/postgres_probe.rb +0 -41
- data/lib/hecks/bench/report.rb +0 -116
- data/lib/hecks/bench/ruby_runner.rb +0 -151
- data/lib/hecks/bench/run.rb +0 -55
- data/lib/hecks/bench/rust_runner.rb +0 -165
- data/lib/hecks/bench/stats.rb +0 -75
- data/lib/hecks/bench/suite.rb +0 -172
- data/lib/hecks/bench/workload.rb +0 -137
- data/lib/hecks/bench.rb +0 -28
- data/lib/hecks/codemod.rb +0 -443
- data/lib/hecks/corpus.rb +0 -479
- data/lib/hecks/doc/reference.rb +0 -585
- data/lib/hecks/fuzzing/bounded_exhaustive_expressions.rb +0 -684
- data/lib/hecks/fuzzing/combination_miner.rb +0 -178
- data/lib/hecks/fuzzing/concurrent_dispatch.rb +0 -469
- data/lib/hecks/fuzzing/coverage_campaign.rb +0 -161
- data/lib/hecks/fuzzing/differential.rb +0 -192
- data/lib/hecks/fuzzing/domain_generator.rb +0 -871
- data/lib/hecks/fuzzing/era_boundary.rb +0 -154
- data/lib/hecks/fuzzing/form_census.rb +0 -285
- data/lib/hecks/fuzzing/generated_domain_check.rb +0 -171
- data/lib/hecks/fuzzing/invalid_value_generator.rb +0 -125
- data/lib/hecks/fuzzing/isolated_boot.rb +0 -604
- data/lib/hecks/fuzzing/nondeterministic.rb +0 -79
- data/lib/hecks/fuzzing/persistence_parity.rb +0 -253
- data/lib/hecks/fuzzing/properties/corrections.rb +0 -125
- data/lib/hecks/fuzzing/properties/dispatch_and_mutations.rb +0 -688
- data/lib/hecks/fuzzing/properties/guards.rb +0 -398
- data/lib/hecks/fuzzing/properties/invariants_and_aggregation.rb +0 -399
- data/lib/hecks/fuzzing/properties/lifecycle_and_replay.rb +0 -137
- data/lib/hecks/fuzzing/properties/outbox.rb +0 -180
- data/lib/hecks/fuzzing/properties/querying.rb +0 -260
- data/lib/hecks/fuzzing/properties.rb +0 -267
- data/lib/hecks/fuzzing/qa_settings.rb +0 -164
- data/lib/hecks/fuzzing/replay.rb +0 -930
- data/lib/hecks/fuzzing/rotation_priority.rb +0 -114
- data/lib/hecks/fuzzing/rust_gap_manifest.rb +0 -139
- data/lib/hecks/fuzzing/self_consistency.rb +0 -825
- data/lib/hecks/fuzzing/sequence_generator/adversary.rb +0 -532
- data/lib/hecks/fuzzing/sequence_generator/catalog.rb +0 -171
- data/lib/hecks/fuzzing/sequence_generator/outcome_tracker.rb +0 -127
- data/lib/hecks/fuzzing/sequence_generator/picker.rb +0 -116
- data/lib/hecks/fuzzing/sequence_generator/query_binding.rb +0 -138
- data/lib/hecks/fuzzing/sequence_generator/step_builder.rb +0 -344
- data/lib/hecks/fuzzing/sequence_generator.rb +0 -311
- data/lib/hecks/fuzzing/shrinker.rb +0 -309
- data/lib/hecks/fuzzing/structural_skips.rb +0 -53
- data/lib/hecks/fuzzing/sweep_depth.rb +0 -61
- data/lib/hecks/fuzzing/target_capabilities.rb +0 -255
- data/lib/hecks/fuzzing/value_generator.rb +0 -340
- data/lib/hecks/fuzzing.rb +0 -23
- data/lib/hecks/grammar/evolve.rb +0 -524
- data/lib/hecks/query_ir.rb +0 -482
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 66f85d62ad01467ff2ae17c6d3be63c706bea69a9e6f7b20839d9f5fc22234a5
|
|
4
|
+
data.tar.gz: 45413f0bd639bfe548ca9f8f7970d5136ed6aa30a25765870ca0212806af3c90
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: b817baff1d4e990f1161080d23f9f10fadd2e1eb8a6f76b1ed551fe021992311f10d64f0eef63218e515905fa2757d879a607abc4b40ecfeb4d0d45a6011a8a6
|
|
7
|
+
data.tar.gz: '0819f496494a76afe81697f8a83301c07acef480b218501748616f1537f0c5d3c0148d67271dea0fd4eea6b6bcb9bbb278331a203883b3c169c08cd59f384451'
|
data/exe/hecks
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
|
|
3
|
+
# The `hecks` command the gem installs: run, read, check and serve a domain you
|
|
4
|
+
# supply. `hecks` with no arguments lists the subcommands; `hecks <command> --help`
|
|
5
|
+
# prints one's usage. The router is `Hecks::CLI` (lib/hecks/cli.rb).
|
|
6
|
+
#
|
|
7
|
+
# The gem's own `lib` goes first on the load path, as it does for the `bin/`
|
|
8
|
+
# scripts, so this file also runs straight from a checkout.
|
|
9
|
+
|
|
10
|
+
$LOAD_PATH.unshift File.expand_path("../lib", __dir__)
|
|
11
|
+
require "hecks/cli"
|
|
12
|
+
|
|
13
|
+
exit Hecks::CLI.start(ARGV)
|
|
@@ -6,7 +6,7 @@ module Hecks
|
|
|
6
6
|
module Adapters
|
|
7
7
|
# **Google's own OIDC handshake** — the `authentication` port's one real
|
|
8
8
|
# implementation today. Consolidates what was hand-rolled per-app
|
|
9
|
-
# (
|
|
9
|
+
# (a console app's `google_auth.rb` did this on its own) into
|
|
10
10
|
# one adapter, so any hecks-based app gets Google sign-in for free, the
|
|
11
11
|
# same "one adapter, reusable everywhere" value every other adapter
|
|
12
12
|
# in this directory already has.
|
|
@@ -29,7 +29,7 @@ module Hecks
|
|
|
29
29
|
# exist precisely so a domain whose AWS identity predates a rename
|
|
30
30
|
# keeps targeting the stack that is actually live rather than
|
|
31
31
|
# standing up a second, empty one beside it. A real one:
|
|
32
|
-
#
|
|
32
|
+
# a client site deploys under a fixed stack name, and no
|
|
33
33
|
# value of `domain` (or of `DOMAIN_NAME`, the deployed-Lambda
|
|
34
34
|
# override callers already pass) can make this computation produce
|
|
35
35
|
# a name with no dash after "hecks". Every Ruby-side read and
|
|
@@ -217,7 +217,7 @@ module Hecks
|
|
|
217
217
|
#
|
|
218
218
|
# @param id [Integer] the row id `outbox_enqueue` assigned
|
|
219
219
|
# @return [Boolean] true when the row was pending and is now claimed; false when it is
|
|
220
|
-
# unknown or
|
|
220
|
+
# unknown or not pending
|
|
221
221
|
def outbox_claim(id) # rubocop:disable Naming/PredicateMethod
|
|
222
222
|
row = @outbox.find { |held| held.id == id }
|
|
223
223
|
return false unless row&.pending?
|
|
@@ -247,7 +247,7 @@ module Hecks
|
|
|
247
247
|
# an update to apply; nil writes unconditionally. Ignored for a delete
|
|
248
248
|
# @return [Runtime::Instance, PG::Result, nil] for a save, a new instance over the
|
|
249
249
|
# entry's state with `version` set to the stored `hecks_version`, or nil when
|
|
250
|
-
# `expected_version`
|
|
250
|
+
# `expected_version` did not match and nothing was written; for a delete, the
|
|
251
251
|
# `DELETE` statement's `PG::Result`
|
|
252
252
|
# @raise [PG::Error] if the statement fails
|
|
253
253
|
# rubocop:disable Metrics/AbcSize -- the CAS/plain upsert split is one
|
|
@@ -72,7 +72,7 @@ module Hecks
|
|
|
72
72
|
# That's invisible to anything that virtualizes the filesystem at
|
|
73
73
|
# the Ruby level instead of the OS level (e.g. tebako's memfs,
|
|
74
74
|
# which presses a hecks-based app into a single executable —
|
|
75
|
-
# see domain/README.md's "Deploying" section in
|
|
75
|
+
# see domain/README.md's "Deploying" section in a client site's domain for
|
|
76
76
|
# why that matters). ::Prism.parse(File.read(file)) parses the
|
|
77
77
|
# exact same bytes, just read through Ruby's File.read first,
|
|
78
78
|
# which those tools do intercept.
|
|
@@ -85,7 +85,7 @@ module Hecks
|
|
|
85
85
|
# never edited out from under it), but wrong for anything that
|
|
86
86
|
# legitimately reloads an edited file in-process: a stale cached
|
|
87
87
|
# tree reports a `given`/`ensures` block at its old line number,
|
|
88
|
-
# which
|
|
88
|
+
# which does not match the freshly re-executed file's own
|
|
89
89
|
# `block.source_location` — surfacing as "did not survive
|
|
90
90
|
# extraction" on a perfectly valid file. Built for real building
|
|
91
91
|
# `Hecks::Codemod` (lib/hecks/codemod.rb), which needs exactly this
|
|
@@ -15,7 +15,7 @@ module Hecks
|
|
|
15
15
|
# Rebuilds a read store from the authoritative journal, entry by entry.
|
|
16
16
|
# A value object is written as its JSON object and a reference as the
|
|
17
17
|
# bare id it holds — the same shapes the command path writes, so there
|
|
18
|
-
# is no second representation to accept here
|
|
18
|
+
# is no second representation to accept here.
|
|
19
19
|
class SqliteProjection < Sqlite
|
|
20
20
|
# Replaces or deletes the read store's row for one journal entry, encoding the entry's
|
|
21
21
|
# state directly rather than through a `Runtime::Instance`.
|
|
@@ -4,7 +4,7 @@ require "fileutils"
|
|
|
4
4
|
|
|
5
5
|
module Hecks
|
|
6
6
|
module Adapters
|
|
7
|
-
#
|
|
7
|
+
# The imperative half of provisioning a tenant, pulled out of
|
|
8
8
|
# `bin/project_tenant` and behind a real driven port
|
|
9
9
|
# (`Deploy::Tenant.port "TenantProvisioning"`) instead — the same
|
|
10
10
|
# hexagonal reasoning `GithubChecks` already gives for its own
|
|
@@ -16,34 +16,55 @@ module Hecks
|
|
|
16
16
|
# `PortOperationInterpreter#ask`'s own "every failure is an answer"
|
|
17
17
|
# comment for why nothing here needs its own rescue.
|
|
18
18
|
#
|
|
19
|
-
#
|
|
19
|
+
# ## What it leaves out
|
|
20
|
+
#
|
|
21
|
+
# Deliberately does not boot the target domain — that step (proving
|
|
20
22
|
# it boots for real, running the tenant_capable? gate) stays in
|
|
21
|
-
# `bin/project_tenant` itself, called
|
|
23
|
+
# `bin/project_tenant` itself, called after this operation answers,
|
|
22
24
|
# not nested inside it. Booting a whole domain from inside an
|
|
23
25
|
# adapter method that is itself running mid-dispatch (this port
|
|
24
26
|
# operation) is a real, separate concern from writing one file, and
|
|
25
27
|
# keeping the two apart avoids a nested `Hecks.boot` call ever
|
|
26
28
|
# running inside another boot's own dispatch call stack.
|
|
27
29
|
#
|
|
28
|
-
#
|
|
29
|
-
#
|
|
30
|
+
# ## Return shape
|
|
31
|
+
#
|
|
32
|
+
# Returns a hash shaped like `Tenancy::Tenant.Register`'s own
|
|
33
|
+
# arguments, on purpose — `tenancy.hecksagon`'s own `translates`
|
|
30
34
|
# reaction forwards an answered event's payload verbatim, so this
|
|
31
|
-
# adapter's own return value
|
|
35
|
+
# adapter's own return value is the translation from Deploy's
|
|
32
36
|
# vocabulary into Tenancy's, decided here rather than in a mapping
|
|
33
37
|
# layer neither side could see into.
|
|
34
38
|
class TenantProvisioner
|
|
39
|
+
# Accepts the arguments every driven adapter is built with and keeps none of them.
|
|
40
|
+
#
|
|
41
|
+
# @param aggregate [Object, nil] unused
|
|
42
|
+
# @param settings [Hash] unused
|
|
43
|
+
# @param root [String, nil] unused
|
|
35
44
|
def initialize(aggregate: nil, settings: {}, root: nil); end
|
|
36
45
|
|
|
37
|
-
#
|
|
46
|
+
# Writes the tenant's environment overlay file under its domain directory.
|
|
47
|
+
#
|
|
48
|
+
# `directory:` is required, not derived from `domain` — a real,
|
|
38
49
|
# confirmed bug found only under CI's own real-Postgres suite: a
|
|
39
|
-
# domain's own
|
|
50
|
+
# domain's own declared name (`domain`, e.g. "Scratch") is not a
|
|
40
51
|
# filesystem path, and File.expand_path(domain, Dir.pwd) silently
|
|
41
52
|
# resolved to the wrong directory (relative to whatever the
|
|
42
|
-
#
|
|
53
|
+
# running process' own cwd happened to be) whenever the CLI's own
|
|
43
54
|
# `--domain=` value didn't happen to equal its own directory
|
|
44
55
|
# argument by coincidence. `bin/project_tenant` passes its own
|
|
45
56
|
# real `domain_directory` local straight through.
|
|
46
|
-
|
|
57
|
+
#
|
|
58
|
+
# Every argument arrives either bare or wrapped as `{ value: ... }`; both are read.
|
|
59
|
+
#
|
|
60
|
+
# @param slug [String, Hash] the tenant's slug, which names the overlay file
|
|
61
|
+
# @param domain [String, Hash] the declared domain name the overlay is for
|
|
62
|
+
# @param realm [String, Hash] the realm the overlay declares
|
|
63
|
+
# @param schema [String, Hash] the schema the overlay declares
|
|
64
|
+
# @param database [String, Hash] the database the overlay declares
|
|
65
|
+
# @param adapter [String, Hash] the persistence adapter the overlay declares
|
|
66
|
+
# @param directory [String, Hash] the domain's own directory on disk
|
|
67
|
+
# @return [Hash{Symbol => Object}] `:slug`, `:domain`, `:realm` and `:schema`, as given
|
|
47
68
|
def provision(slug:, domain:, realm:, schema:, database:, adapter:, directory:)
|
|
48
69
|
domain_directory = File.expand_path(directory[:value] || directory)
|
|
49
70
|
|
|
@@ -228,7 +228,7 @@ module Hecks
|
|
|
228
228
|
# the dispatch's own result
|
|
229
229
|
# @return [Hash{Symbol => Object}] the settled record's current state, read
|
|
230
230
|
# back from the repository; `result.state` (or `{}`) when the result has no
|
|
231
|
-
# id or the repository
|
|
231
|
+
# id or the repository does not have that aggregate/record
|
|
232
232
|
def settled_state(runtime, verb, result)
|
|
233
233
|
return result.state || {} unless result.respond_to?(:id) && result.id
|
|
234
234
|
|
|
@@ -266,7 +266,7 @@ module Hecks
|
|
|
266
266
|
# only so long as nothing else ever asked it to resolve a port-operation
|
|
267
267
|
# verb. Now that a `policy` can legitimately `trigger` a port operation
|
|
268
268
|
# (`ReactionInvocation#resolve_target`'s own port-operation branch),
|
|
269
|
-
# that raise
|
|
269
|
+
# that raise does not happen, so this checks directly instead.
|
|
270
270
|
#
|
|
271
271
|
# @param runtime [Runtime::Dispatcher, Runtime::RemoteDispatcher] the suite's
|
|
272
272
|
# booted runtime
|
|
@@ -151,7 +151,7 @@ module Hecks
|
|
|
151
151
|
# Entity's contract claims `owner: :parent`
|
|
152
152
|
#
|
|
153
153
|
# `shape` and `handler` are not on this list — S17 (ADR 0026) made Member and
|
|
154
|
-
# Dispatch nested entities, so neither is a parent field
|
|
154
|
+
# Dispatch nested entities, so neither is a parent field the way
|
|
155
155
|
# `owner` is. `spec/assembly_spec` derives this set from `Plan` and the
|
|
156
156
|
# contracts directly and fails on any drift, rather than trusting this list to
|
|
157
157
|
# stay in sync with a second hand-written copy kept by the model generator.
|
|
@@ -243,7 +243,7 @@ module Hecks
|
|
|
243
243
|
|
|
244
244
|
# S17, ADR 0026 — Handler is a genuine entity now, nested under
|
|
245
245
|
# ProcessManager (`entity "Handler"`, reaction.bluebook). Neither
|
|
246
|
-
# `position` nor `handler` is a stored field
|
|
246
|
+
# `position` nor `handler` is a stored field: a saga
|
|
247
247
|
# answers each event once, so `event_type` is Handler's own real,
|
|
248
248
|
# non-positional identity (no walk-minted `position` to derive),
|
|
249
249
|
# and the process manager it belongs to is structural now — which
|
|
@@ -429,10 +429,10 @@ module Hecks
|
|
|
429
429
|
# A member's pairs are an open map, which is why Member is its own root in
|
|
430
430
|
# the language. The IR keeps them as a plain hash on the value object, so
|
|
431
431
|
# they are assembled with their shape rather than as a construct.
|
|
432
|
-
# S17, ADR 0026 — Member is a genuine entity
|
|
433
|
-
# ValueObject (`entity "Member"`, shape.bluebook). It no
|
|
434
|
-
#
|
|
435
|
-
#
|
|
432
|
+
# S17, ADR 0026 — Member is a genuine entity, nested under
|
|
433
|
+
# ValueObject (`entity "Member"`, shape.bluebook). It holds no
|
|
434
|
+
# `shape` field at all (a free-text, un-parsed spelling would suit
|
|
435
|
+
# only a standalone root ; an entity's element is
|
|
436
436
|
# never serialized as text) — only `position` (walk-minted, see
|
|
437
437
|
# `entity_own_identity`, judge.rb) and `pairs` (still an open map,
|
|
438
438
|
# still one row per entry, still why a value object cannot hold it
|
|
@@ -21,8 +21,8 @@ module Hecks
|
|
|
21
21
|
module Specializer
|
|
22
22
|
module_function
|
|
23
23
|
|
|
24
|
-
# S17, ADR 0026 — `Handler` is a genuine entity
|
|
25
|
-
# `ProcessManager`, so `.aggregate` alone
|
|
24
|
+
# S17, ADR 0026 — `Handler` is a genuine entity, nested under
|
|
25
|
+
# `ProcessManager`, so `.aggregate` alone does not find it —
|
|
26
26
|
# it hangs off some aggregate's own `.entities` instead
|
|
27
27
|
# (searched recursively, the same reason `Value::Coercion#find_
|
|
28
28
|
# entity` does: a nested entity, like `Dispatch` inside
|
|
@@ -31,7 +31,7 @@ module Hecks
|
|
|
31
31
|
# ## What stays hand-written
|
|
32
32
|
#
|
|
33
33
|
# The containment — which construct holds which — stays hand-written; it is
|
|
34
|
-
# not a field table. The runtime surface is
|
|
34
|
+
# not a field table. The runtime surface is not built here at all — the
|
|
35
35
|
# door is a per-boot projection, facade/surface.rb.
|
|
36
36
|
class Assembly
|
|
37
37
|
# Builds the graph the runtime runs from one chapter's declared hash.
|
|
@@ -91,15 +91,18 @@ module Hecks
|
|
|
91
91
|
@ports_by_name[port.name] = port
|
|
92
92
|
end
|
|
93
93
|
|
|
94
|
-
# A
|
|
94
|
+
# A translated reaction is also declared in the hecksagon —
|
|
95
95
|
# `HecksagonBuilder#translates` builds an ordinary `Policy` (same
|
|
96
96
|
# shape, same `PolicyInterpreter` runtime, as one written inside a
|
|
97
97
|
# `policy` block in this chapter's own `.bluebook`) and attaches it
|
|
98
98
|
# here, after the chapter already exists, the same reasoning
|
|
99
99
|
# `add_port` gives one method up. Kept out of the bluebook itself
|
|
100
|
-
# on purpose: which
|
|
100
|
+
# on purpose: which foreign domain's event this chapter reacts to
|
|
101
101
|
# is a wiring/context-mapping decision, not a fact the domain
|
|
102
102
|
# states about its own model.
|
|
103
|
+
#
|
|
104
|
+
# @param policy [Bluebook::Policy] the translated reaction to attach
|
|
105
|
+
# @return [Array<Bluebook::Policy>] this chapter's policies, with `policy` appended
|
|
103
106
|
def add_policy(policy)
|
|
104
107
|
@policies << policy
|
|
105
108
|
end
|
|
@@ -9,6 +9,24 @@ module Hecks
|
|
|
9
9
|
# @return [Array<Symbol>] each declared `group_by` field's name, in declaration order
|
|
10
10
|
def group_by_fields = @group_by.map { |row| row[:field].to_sym }
|
|
11
11
|
|
|
12
|
+
# Reports whether this read model's `group_by` names every identity head
|
|
13
|
+
# of the aggregate it groups (ADR 0061, decision D1).
|
|
14
|
+
#
|
|
15
|
+
# Such a key path cannot be shared by two rows, so it is accepted from the
|
|
16
|
+
# declaration alone and never checked for a collision at dispatch. Any
|
|
17
|
+
# other key path is checked per request.
|
|
18
|
+
#
|
|
19
|
+
# @param aggregate [Bluebook::Aggregate, nil] the aggregate of this read
|
|
20
|
+
# model's one many-side head
|
|
21
|
+
# @return [Boolean] false when `aggregate` is nil or declares no identity,
|
|
22
|
+
# since uniqueness cannot then be shown
|
|
23
|
+
def groups_by_identity?(aggregate)
|
|
24
|
+
return false unless aggregate
|
|
25
|
+
|
|
26
|
+
identity = Array(aggregate.identity_heads).map(&:to_sym)
|
|
27
|
+
!identity.empty? && (identity - group_by_fields).empty?
|
|
28
|
+
end
|
|
29
|
+
|
|
12
30
|
# `!!` rather than a bare `@count` — the DSL/reconstruction
|
|
13
31
|
# boundary (ReadModel#initialize) already normalises to
|
|
14
32
|
# `true`/`nil`, so this is belt and braces against a future
|
|
@@ -19,11 +19,11 @@ module Hecks
|
|
|
19
19
|
# Who may sign in, and with what role — rust/host's Google-OAuth
|
|
20
20
|
# provision/member_rows resolve this instead of an env var naming
|
|
21
21
|
# the aggregate (HECKS_MEMBERSHIP_AGGREGATE). Same declared-
|
|
22
|
-
# not-named shape AUTHORIZATION already is for Governance.
|
|
22
|
+
# not-named shape `AUTHORIZATION` already is for Governance.
|
|
23
23
|
MEMBERSHIP = "membership".freeze
|
|
24
24
|
# A stable organizational identity, independent of how it was
|
|
25
25
|
# authenticated — recognised by declaration, not the literal name
|
|
26
|
-
# "Identity". Same declared-not-named shape AUTHORIZATION already
|
|
26
|
+
# "Identity". Same declared-not-named shape `AUTHORIZATION` already
|
|
27
27
|
# is. rust/host does not build this chapter's payloads; any field
|
|
28
28
|
# mapping lives on the consuming hecksagon's `translates` ACL.
|
|
29
29
|
IDENTITY = "identity".freeze
|
|
@@ -4,7 +4,7 @@ require_relative "../ir"
|
|
|
4
4
|
|
|
5
5
|
module Hecks
|
|
6
6
|
module Bluebook
|
|
7
|
-
# The chapter,
|
|
7
|
+
# The chapter, which is not the namespace it lives in.
|
|
8
8
|
#
|
|
9
9
|
# `Hecks::Bluebook` was briefly a class, because dropping the
|
|
10
10
|
# old `IR::` segment would otherwise have produced
|
|
@@ -198,7 +198,7 @@ module Hecks
|
|
|
198
198
|
# never `[]`). Wave 6 (identity-and-relationships arc) un-deprecates
|
|
199
199
|
# all three for real: a relationship word now retains the author's
|
|
200
200
|
# domain concept in IR — still stored as one or more target
|
|
201
|
-
# identities, but
|
|
201
|
+
# identities, but not collapsed to a bare `reference_to`
|
|
202
202
|
# during assembly. `MetaValidator.shadow_parsing?` still routes to
|
|
203
203
|
# `legacy_has_many`/`legacy_has_one` so frozen era text written
|
|
204
204
|
# under the old (lying/collapsing) meaning still parses the way it
|
|
@@ -511,7 +511,7 @@ module Hecks
|
|
|
511
511
|
# are this construct's own refusal wording, not shared, since
|
|
512
512
|
# `declared_by:` only exists here so far. Unresolved (no
|
|
513
513
|
# candidate yet, or `declared_by:` naming an aggregate that
|
|
514
|
-
# hasn't declared it yet) is
|
|
514
|
+
# hasn't declared it yet) is not a fourth branch that
|
|
515
515
|
# raises here — see `#pending_chapter_given`, below, for why:
|
|
516
516
|
# a chapter split across files can genuinely reference a
|
|
517
517
|
# precondition a later file declares, and "not found among
|
|
@@ -77,7 +77,7 @@ module Hecks
|
|
|
77
77
|
end
|
|
78
78
|
|
|
79
79
|
def method_missing(verb, *args, **kwargs, &block)
|
|
80
|
-
# A
|
|
80
|
+
# **A bare call** — no args, no kwargs, no block — starts (or
|
|
81
81
|
# continues, on `AttributePath` itself below) a Privacy
|
|
82
82
|
# marking chain: `Registration.attendee.medications.has_phi(
|
|
83
83
|
# readable_by: "Privacy officer")`. No existing real
|
|
@@ -115,10 +115,15 @@ module Hecks
|
|
|
115
115
|
@path = path
|
|
116
116
|
end
|
|
117
117
|
|
|
118
|
+
# Records a `has_<category>` marking, or extends the attribute path by one segment.
|
|
119
|
+
#
|
|
118
120
|
# @param verb [Symbol] `has_<category>` to record the marking and end the chain;
|
|
119
121
|
# any other bare name to extend the path one segment further
|
|
120
122
|
# @param readable_by [String] required only for a `has_<category>` call — the
|
|
121
123
|
# Governance role a read must hold to see this field unredacted
|
|
124
|
+
# @param args [Array] must be empty; a positional argument is refused
|
|
125
|
+
# @param kwargs [Hash] must be empty; any keyword but `readable_by:` is refused
|
|
126
|
+
# @param block [Proc, nil] must be absent; a block is refused
|
|
122
127
|
# @return [Bluebook::DSL::AttributePath, nil] a longer chain for a plain segment;
|
|
123
128
|
# `nil` (nothing further to chain) for a `has_<category>` call
|
|
124
129
|
# @raise [Malformed] if a `has_<category>` call omits `readable_by:`, or any call
|
|
@@ -431,9 +431,9 @@ module Hecks
|
|
|
431
431
|
# manager's own structural check fails
|
|
432
432
|
def self.build(name, version: nil, &block)
|
|
433
433
|
registry = Hecks.current_registry
|
|
434
|
-
#
|
|
434
|
+
# Which file called `Hecks.bluebook`, recorded for
|
|
435
435
|
# `Registry#record_bluebook_source` — two frames up: this
|
|
436
|
-
# method's own caller is `Hecks.bluebook` (hecks.rb), and
|
|
436
|
+
# method's own caller is `Hecks.bluebook` (hecks.rb), and its
|
|
437
437
|
# caller is the real `.bluebook` file's own top-level call site.
|
|
438
438
|
caller_location = caller_locations(2, 1)&.first
|
|
439
439
|
registry&.record_bluebook_source(name, caller_location&.path)
|
|
@@ -82,6 +82,8 @@ module Hecks
|
|
|
82
82
|
["Type", "one_of"] => :one_of_impl,
|
|
83
83
|
["World", "realm"] => :realm_impl,
|
|
84
84
|
["World", "latest"] => :latest_impl,
|
|
85
|
+
["World", "default_database"] => :default_database_impl,
|
|
86
|
+
["World", "default_adapter"] => :default_adapter_impl,
|
|
85
87
|
["DomainPort", "operation"] => :tells_impl,
|
|
86
88
|
["DomainPort", "tells"] => :tells_impl,
|
|
87
89
|
["DomainPort", "asks"] => :asks_impl,
|
|
@@ -22,7 +22,7 @@ module Hecks
|
|
|
22
22
|
# same as an absent `to:` and falls through to `from` (also
|
|
23
23
|
# absent), so `then_set :accepted, to: false` raised "names no
|
|
24
24
|
# operation" for the one value most likely to be written that way
|
|
25
|
-
# (a boolean flip). Confirmed real, live:
|
|
25
|
+
# (a boolean flip). Confirmed real, live: an external project's
|
|
26
26
|
# dream_interpretation.bluebook (`then_set :accepted, to: false`)
|
|
27
27
|
# and transparency.bluebook (`then_set :always, to: false`). TODO
|
|
28
28
|
# upstream via bin/evolve.
|
|
@@ -262,7 +262,7 @@ module Hecks
|
|
|
262
262
|
# era keeps booting, which is the whole point of the rename column.
|
|
263
263
|
#
|
|
264
264
|
# Vendored addition, not (yet) upstream hecks: `then_set
|
|
265
|
-
# :target, from: :source_field` (
|
|
265
|
+
# :target, from: :source_field` (an external project, found
|
|
266
266
|
# live in body/doctor/bluebook/doctor.bluebook) -- semantically
|
|
267
267
|
# identical to `to:` (copy this argument/field into the target),
|
|
268
268
|
# different word. TODO upstream via bin/evolve (migration plan
|
|
@@ -271,7 +271,7 @@ module Hecks
|
|
|
271
271
|
#
|
|
272
272
|
# Vendored addition, not (yet) upstream hecks (migration plan
|
|
273
273
|
# task 4, i106 in-DSL math): `multiply:`/`clamp:` -- per-tick organ
|
|
274
|
-
# math (
|
|
274
|
+
# math (an external project's organ bluebook: strength decays ×0.98,
|
|
275
275
|
# weight/strength clamp to [0, 1]), moved into the bluebook itself
|
|
276
276
|
# from shell-side awk. `multiply:` mirrors
|
|
277
277
|
# increment/decrement's shape exactly (a Numeric amount, applied
|
|
@@ -243,7 +243,7 @@ module Hecks
|
|
|
243
243
|
# since ADR 0028, `command` only queues a descriptor and actually
|
|
244
244
|
# builds at `#drain_pending!` time, well after this whole block
|
|
245
245
|
# (including every `given` in it) has already run, so textual
|
|
246
|
-
# order within the block
|
|
246
|
+
# order within the block does not actually matter here; named
|
|
247
247
|
# for the reader anyway, since `given`'s own resolution logic
|
|
248
248
|
# (`CommandBuilder#reference_named_given`) still reads whatever
|
|
249
249
|
# `@named_givens` holds at the command's own build time, not by
|
|
@@ -8,7 +8,7 @@ module Hecks
|
|
|
8
8
|
# already shipped) only checks a word's admissibility; this module
|
|
9
9
|
# executes the safe, mechanical subset of what a word actually
|
|
10
10
|
# does, read live off the same self-hosted grammar table — so a
|
|
11
|
-
# builder method for one of these words
|
|
11
|
+
# builder method for one of these words need not be
|
|
12
12
|
# hand-written at all. Called from `WordGate#method_missing`'s own
|
|
13
13
|
# "admitted here, no builder method for it yet" branch, so it only
|
|
14
14
|
# ever sees a word whose (context, word) pair the grammar already
|
|
@@ -31,7 +31,7 @@ module Hecks
|
|
|
31
31
|
@translates = []
|
|
32
32
|
end
|
|
33
33
|
|
|
34
|
-
# Marks
|
|
34
|
+
# Marks this chapter as a bounded context — a consumer-owned chapter
|
|
35
35
|
# that `uses_framework` / `uses_embryonaut_bluebook` will not load.
|
|
36
36
|
# Framework and vendored packages get the mark automatically from
|
|
37
37
|
# those words; they never write `bounded` in their own bluebooks.
|
|
@@ -158,12 +158,12 @@ module Hecks
|
|
|
158
158
|
bluebook_ir.add_port(built)
|
|
159
159
|
end
|
|
160
160
|
|
|
161
|
-
# A
|
|
161
|
+
# A translation boundary, not a business rule — `translates "Name"
|
|
162
162
|
# do on Foreign::Domain::SomeEvent; trigger Local.Command; end`
|
|
163
|
-
# builds the
|
|
163
|
+
# builds the exact same `Policy` a `policy` block inside this
|
|
164
164
|
# domain's own `.bluebook` would (same `on_impl`/`trigger_impl`,
|
|
165
165
|
# same `PolicyInterpreter` runtime — reusing `PolicyBuilder`
|
|
166
|
-
# directly, zero new runtime semantics). What's new is only
|
|
166
|
+
# directly, zero new runtime semantics). What's new is only where
|
|
167
167
|
# it can be written: a cross-domain reaction is a wiring/context-
|
|
168
168
|
# mapping decision (this chapter conforming to a foreign chapter's
|
|
169
169
|
# published event), the same kind of decision `port`/
|
|
@@ -171,23 +171,28 @@ module Hecks
|
|
|
171
171
|
# model states about itself, which `policy` (inside the bluebook)
|
|
172
172
|
# remains the right word for.
|
|
173
173
|
#
|
|
174
|
-
#
|
|
175
|
-
# call's arguments are evaluated eagerly, under
|
|
174
|
+
# Must be a block, not `translates Event, into: Command` — a flat
|
|
175
|
+
# call's arguments are evaluated eagerly, under this builder's own
|
|
176
176
|
# `ConstShim` resolver (`BindingProxy.namespace`, set up by
|
|
177
|
-
# `self.build` below), which mints a `BindingProxy`
|
|
177
|
+
# `self.build` below), which mints a `BindingProxy` instance per
|
|
178
178
|
# segment and cannot answer a further `::` (it is not a Module) —
|
|
179
179
|
# a multi-segment reference like `Deploy::Tenant::TenantProvisioned`
|
|
180
180
|
# would raise before this method ever ran. `port_impl`'s own
|
|
181
181
|
# `ConstShim.with(->(const) { const })` swap only works because
|
|
182
182
|
# its own callers never pass a multi-segment bare constant as an
|
|
183
183
|
# eagerly-evaluated argument — everything of that shape lives
|
|
184
|
-
# inside
|
|
184
|
+
# inside its block, evaluated later, under the swapped resolver.
|
|
185
185
|
# A block defers evaluation the same way; a flat call cannot.
|
|
186
|
+
#
|
|
187
|
+
# @param name [String, Symbol] the reaction's name
|
|
188
|
+
# @yield the `on`/`trigger` block, evaluated later under the scoped resolver
|
|
189
|
+
# @return [Array<Bluebook::Policy>] the chapter's policies, with the new one appended
|
|
190
|
+
# @raise [Malformed] if no bluebook is registered for this domain to attach the reaction to
|
|
186
191
|
def translates(name, &block)
|
|
187
192
|
bluebook_ir = Hecks.current_registry.bluebook(@domain) or
|
|
188
193
|
raise Malformed, "#{@domain} declares no such bluebook — translates needs one to attach its reaction to"
|
|
189
194
|
|
|
190
|
-
#
|
|
195
|
+
# Same resolver BluebookBuilder itself uses for a `policy`
|
|
191
196
|
# block's own `on`/`trigger` (bluebook_builder.rb) — a
|
|
192
197
|
# `ScopedConstant`, not the bare passthrough `port_impl` swaps
|
|
193
198
|
# to, because `on`/`trigger` here take genuinely multi-segment
|
|
@@ -34,7 +34,7 @@ module Hecks
|
|
|
34
34
|
# only external facts with attribute" the refusal message
|
|
35
35
|
# describes) rather than folding `to:` into identity_attribute's
|
|
36
36
|
# existing Reference-attribute scan, which every operation already
|
|
37
|
-
# in the corpus (Banking, pizzas,
|
|
37
|
+
# in the corpus (Banking, pizzas, a client site's own vendored
|
|
38
38
|
# PaymentGateway) still relies on unchanged.
|
|
39
39
|
#
|
|
40
40
|
# @param name [String] the operation's name
|
|
@@ -147,8 +147,8 @@ module Hecks
|
|
|
147
147
|
.find { |rule| rule.description == description }
|
|
148
148
|
end
|
|
149
149
|
|
|
150
|
-
# **Which construct uses which primitive** —
|
|
151
|
-
# Hash
|
|
150
|
+
# **Which construct uses which primitive** — not a Ruby-only
|
|
151
|
+
# Hash, because the
|
|
152
152
|
# user's own correction — "my goal is that if they read the same
|
|
153
153
|
# table they behave identically" — means a table only Ruby ever
|
|
154
154
|
# reads cannot deliver that, no matter how faithfully it is
|
|
@@ -172,7 +172,7 @@ module Hecks
|
|
|
172
172
|
# after `grammar_registry` is fully built and memoized, so reads
|
|
173
173
|
# the real table, every time, no exception.
|
|
174
174
|
#
|
|
175
|
-
#
|
|
175
|
+
# Not kept in sync by hand — the same `resolves_via`/
|
|
176
176
|
# `disambiguator` columns, projected ahead of time into the
|
|
177
177
|
# committed lib/hecks/bluebook/dsl/bootstrap_table.rb
|
|
178
178
|
# (bin/project_bootstrap_table, pinned by spec/bootstrap_table_spec.rb).
|
|
@@ -268,7 +268,7 @@ module Hecks
|
|
|
268
268
|
# Parses a whole `.translation` file into a `Translation` — the
|
|
269
269
|
# domain's own `from:`/`to:` era pair, its list of `aggregate`
|
|
270
270
|
# translation blocks (each built by `TranslationAggregateBuilder`
|
|
271
|
-
# above), and any `retired` aggregates that
|
|
271
|
+
# above), and any `retired` aggregates that do not exist in the
|
|
272
272
|
# destination era.
|
|
273
273
|
class TranslationBuilder
|
|
274
274
|
GRAMMAR_CONTEXT = "Translation".freeze
|
|
@@ -11,8 +11,22 @@ module Hecks
|
|
|
11
11
|
# Starts with no settings recorded.
|
|
12
12
|
def initialize = @values = {}
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
# A call with a block records the block's own settings as a nested Hash, so a bind can
|
|
15
|
+
# group settings (`preview do ... end`); a call without one records its argument.
|
|
16
|
+
#
|
|
17
|
+
# @param key [Symbol] the setting's name, recorded verbatim
|
|
18
|
+
# @param args [Array] the setting's value: one argument is kept as is, several as an array
|
|
19
|
+
# @param block [Proc, nil] a nested settings block, evaluated on a fresh collector
|
|
20
|
+
# @return [Object] the value recorded under `key`
|
|
21
|
+
def method_missing(key, *args, &block)
|
|
22
|
+
@values[key.to_sym] =
|
|
23
|
+
if block
|
|
24
|
+
nested = SettingsCollector.new
|
|
25
|
+
nested.instance_eval(&block)
|
|
26
|
+
nested.to_h
|
|
27
|
+
else
|
|
28
|
+
args.size == 1 ? args.first : args
|
|
29
|
+
end
|
|
16
30
|
end
|
|
17
31
|
|
|
18
32
|
def respond_to_missing?(_name, _include_private = false) = true
|
|
@@ -96,6 +110,35 @@ module Hecks
|
|
|
96
110
|
@latest = required(value, "latest version")
|
|
97
111
|
end
|
|
98
112
|
|
|
113
|
+
# Names the connection every chapter's database-taking persistence adapter uses
|
|
114
|
+
# unless that chapter's own world settings name one.
|
|
115
|
+
#
|
|
116
|
+
# Answers the `default_database` word through the table's `calls:` column, the
|
|
117
|
+
# same way `realm_impl` does. A chapter's own
|
|
118
|
+
# `persisted_by("Adapter") { database ... }` still wins for that adapter.
|
|
119
|
+
#
|
|
120
|
+
# @param value [String] the connection, such as a database URL; blankness is
|
|
121
|
+
# judged by the world language at `build`, not here
|
|
122
|
+
# @return [String] the connection as stored
|
|
123
|
+
def default_database_impl(value)
|
|
124
|
+
@default_database = required(value, "default database")
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
# Names the persistence adapter every aggregate binds to unless its own chapter's
|
|
128
|
+
# hecksagon binds it.
|
|
129
|
+
#
|
|
130
|
+
# Answers the `default_adapter` word through the table's `calls:` column, the same
|
|
131
|
+
# way `realm_impl` does. Sits between an explicit bind and the framework's
|
|
132
|
+
# in-memory fallback; whether the adapter really is a persistence adapter is
|
|
133
|
+
# judged at boot, where adapters are known.
|
|
134
|
+
#
|
|
135
|
+
# @param value [String, Symbol] the adapter's declared name, such as `"PostgresEra"`;
|
|
136
|
+
# blankness is judged by the world language at `build`, not here
|
|
137
|
+
# @return [String] the adapter name as stored
|
|
138
|
+
def default_adapter_impl(value)
|
|
139
|
+
@default_adapter = required(value, "default adapter")
|
|
140
|
+
end
|
|
141
|
+
|
|
99
142
|
def method_missing(verb, *args, **kwargs, &block)
|
|
100
143
|
result = word_gate_dispatch(verb, args, kwargs, block)
|
|
101
144
|
return result unless result.equal?(WordGate::NOT_ADMITTED)
|
|
@@ -134,7 +177,8 @@ module Hecks
|
|
|
134
177
|
# as a blank `realm`
|
|
135
178
|
def build
|
|
136
179
|
MetaValidator.call_world(
|
|
137
|
-
World.new(domain: @domain, realm: @realm, latest: @latest, settings: @settings
|
|
180
|
+
World.new(domain: @domain, realm: @realm, latest: @latest, settings: @settings,
|
|
181
|
+
default_database: @default_database, default_adapter: @default_adapter)
|
|
138
182
|
)
|
|
139
183
|
end
|
|
140
184
|
|