hecks 3.0.5 → 3.1.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 +24 -12
- data/lib/hecks/adapters/driven/lambda/client.rb +1 -1
- data/lib/hecks/adapters/driven/lambda.rb +1 -1
- data/lib/hecks/adapters/driven/tenant_provisioner.rb +2 -2
- data/lib/hecks/bluebook/dsl/hecksagon_builder.rb +59 -32
- data/lib/hecks/bluebook/hexagon.rb +45 -25
- data/lib/hecks/bluebook/model_check.rb +7 -7
- data/lib/hecks/chapters.rb +31 -3
- data/lib/hecks/cli/check_era.rb +1 -1
- data/lib/hecks/cli/deploy_template_diff.rb +1 -1
- data/lib/hecks/cli/doc_coverage.rb +1 -1
- data/lib/hecks/cli/domain_stub.rb +128 -0
- data/lib/hecks/cli/interview_draft.rb +246 -0
- data/lib/hecks/cli/model_check.rb +1 -1
- data/lib/hecks/cli/project_cli.rb +51 -29
- data/lib/hecks/cli/reference.rb +2 -1
- data/lib/hecks/cli/refresh_rspec_runtime_baseline.rb +1 -1
- data/lib/hecks/cli/seed_semantics_corpus.rb +3 -3
- data/lib/hecks/cli/spec_example.rb +1 -1
- data/lib/hecks/cli/stress_concurrency_specs.rb +14 -5
- data/lib/hecks/corpus.rb +11 -8
- data/lib/hecks/deploy/bluebook/deploy.bluebook +85 -12
- data/lib/hecks/deploy/oidc.json +5 -0
- data/lib/hecks/doc/reference.rb +4 -3
- data/lib/hecks/doors/cli_door.rb +13 -13
- data/lib/hecks/doors/cli_runner.rb +52 -32
- data/lib/hecks/doors/launcher_options.rb +5 -5
- data/lib/hecks/doors/mcp_door.rb +40 -18
- data/lib/hecks/doors/mcp_door_scope.rb +244 -24
- data/lib/hecks/doors.rb +1 -1
- data/lib/hecks/embryonaut_bluebook.rb +2 -2
- data/lib/hecks/forms/banking_presentation.rb +1 -1
- data/lib/hecks/framework/bluebook/compliance.bluebook +1 -1
- data/lib/hecks/framework/bluebook/console_settings.bluebook +1 -1
- data/lib/hecks/framework/bluebook/framework.hecksagon +4 -4
- data/lib/hecks/framework.rb +1 -1
- data/lib/hecks/fuzzing/combination_miner.rb +1 -1
- data/lib/hecks/fuzzing/concurrent_dispatch.rb +1 -1
- data/lib/hecks/fuzzing/differential.rb +4 -2
- data/lib/hecks/fuzzing/era_boundary.rb +1 -1
- data/lib/hecks/fuzzing/form_census.rb +2 -2
- data/lib/hecks/fuzzing/generated_domain_check.rb +1 -1
- data/lib/hecks/fuzzing/isolated_boot.rb +10 -3
- data/lib/hecks/fuzzing/persistence_parity.rb +2 -2
- data/lib/hecks/fuzzing/target_capabilities.rb +3 -3
- data/lib/hecks/gate/stages.yml +5 -5
- data/lib/hecks/grammar/grammar.hecksagon +2 -2
- data/lib/hecks/hecks/adapters/deploy_toolchain.rb +4 -4
- data/lib/hecks/hecks/adapters/host_http.rb +4 -3
- data/lib/hecks/hecks/adapters/local_files.rb +59 -0
- data/lib/hecks/hecks/adapters/site_toolchain.adapter +7 -0
- data/lib/hecks/hecks/adapters/site_toolchain.rb +54 -0
- data/lib/hecks/hecks/codebase.bluebook +4 -3
- data/lib/hecks/hecks/context_map.hecksagon +2 -2
- data/lib/hecks/hecks/custodian.bluebook +45 -3
- data/lib/hecks/hecks/hecks.hecksagon +10 -4
- data/lib/hecks/hecks/hecks.world +6 -6
- data/lib/hecks/hecks/site.behaviors +17 -0
- data/lib/hecks/hecks/site.world +10 -0
- data/lib/hecks/language/bluebook/bluebook.hecksagon +1 -1
- data/lib/hecks/language/hecksagon/hecksagon.bluebook +24 -47
- data/lib/hecks/ports/persistence/plugins/era/era_check.rb +4 -4
- data/lib/hecks/projections/deploy/box/settings.rb +248 -0
- data/lib/hecks/projections/deploy/box/templates/box.yaml.tmpl +267 -0
- data/lib/hecks/projections/deploy/box/templates/deploy-box.sh.tmpl +70 -0
- data/lib/hecks/projections/deploy/box/templates/fetch-secrets.sh +21 -0
- data/lib/hecks/projections/deploy/box/templates/rds.yaml.tmpl +165 -0
- data/lib/hecks/projections/deploy/box/templates/render-compose.sh.tmpl +43 -0
- data/lib/hecks/projections/deploy/box.rb +387 -0
- data/lib/hecks/projections/deploy/fargate/cdn.rb +13 -1
- data/lib/hecks/projections/deploy/fargate.rb +1 -1
- data/lib/hecks/projections/deploy/lambda.rb +11 -10
- data/lib/hecks/projections/deploy/scripts/hosting.mk.tmpl +1 -1
- data/lib/hecks/projections/diagrams.rb +2 -2
- data/lib/hecks/projections/site/edge/behaviours.rb +107 -0
- data/lib/hecks/projections/site/edge/checks.rb +137 -0
- data/lib/hecks/projections/site/edge/pattern.rb +50 -0
- data/lib/hecks/projections/site/edge/rules.rb +128 -0
- data/lib/hecks/projections/site/edge.rb +136 -0
- data/lib/hecks/projections/site/regions.rb +44 -0
- data/lib/hecks/projections/site/routes_ts.rb +284 -0
- data/lib/hecks/projections/site/site_cdn.rb +78 -0
- data/lib/hecks/projections/site/table/checks.rb +124 -0
- data/lib/hecks/projections/site/table/row_builder.rb +155 -0
- data/lib/hecks/projections/site/table.rb +98 -0
- data/lib/hecks/projections.rb +2 -0
- data/lib/hecks/projector/cli_projector.rb +122 -104
- data/lib/hecks/quality_control/adapters/agent.adapter +1 -1
- data/lib/hecks/quality_control/adapters/agent.rb +2 -2
- data/lib/hecks/quality_control/cli/qa_concurrency_racer.rb +3 -3
- data/lib/hecks/quality_control/cli/qa_discover_external_domains.rb +8 -8
- data/lib/hecks/quality_control/cli/qa_domain_novelty.rb +3 -3
- data/lib/hecks/quality_control/cli/qa_generated_domains.rb +4 -4
- data/lib/hecks/quality_control/cli/qa_log_bug.rb +2 -2
- data/lib/hecks/quality_control/cli/qa_mine_combinations.rb +6 -5
- data/lib/hecks/quality_control/cli/qa_postgres_migrate.rb +2 -2
- data/lib/hecks/quality_control/cli/qa_postgres_role.rb +5 -5
- data/lib/hecks/quality_control/cli/qa_pr_check.rb +3 -3
- data/lib/hecks/quality_control/cli/qa_sweep/all_mode.rb +3 -3
- data/lib/hecks/quality_control/cli/qa_sweep/checks.rb +2 -2
- data/lib/hecks/quality_control/cli/qa_sweep.rb +10 -9
- data/lib/hecks/quality_control/cli/qa_tick.rb +3 -3
- data/lib/hecks/quality_control/quality_control.bluebook +18 -18
- data/lib/hecks/quality_control/quality_control.hecksagon +1 -1
- data/lib/hecks/runtime/registry/verification.rb +15 -29
- data/lib/hecks/runtime/registry.rb +14 -20
- data/lib/hecks/rust_build/append_optionals.rb +79 -0
- data/lib/hecks/rust_build/conformance_fuzz.rb +2 -1
- data/lib/hecks/rust_build/domain_name.rb +26 -0
- data/lib/hecks/rust_build/kernel_input.rb +58 -0
- data/lib/hecks/rust_build/project_rust/codegen_run.rb +143 -0
- data/lib/hecks/rust_build/project_rust/root_mod.rb +1 -1
- data/lib/hecks/rust_build/project_rust.rb +57 -24
- data/lib/hecks/rust_build/rust_literal.rb +33 -0
- data/lib/hecks/rust_build/write_if_changed.rb +86 -0
- data/lib/hecks/site/bluebook/site.bluebook +205 -0
- data/lib/hecks/site/bluebook/site.hecksagon +5 -0
- data/lib/hecks/site/bluebook/site.ports.hecksagon +15 -0
- data/lib/hecks/sme/bluebook/sme.bluebook +336 -0
- data/lib/hecks/sme/bluebook/sme.hecksagon +5 -0
- data/lib/hecks/storehouse.rb +37 -7
- data/lib/hecks/tenancy/bluebook/tenancy.bluebook +1 -1
- data/lib/hecks/three_zero/forms.yml +88 -88
- data/lib/hecks/tools/ci_gates.rb +1 -1
- data/lib/hecks/tools/deploy_recipe.rb +14 -6
- data/lib/hecks/tools/oidc_manifests.rb +2 -1
- data/lib/hecks/tools/sequence_script.rb +2 -2
- data/lib/hecks/tools/site_routes.rb +152 -0
- data/lib/hecks/tools/tenant_provisioning.rb +1 -1
- data/lib/hecks/tools.rb +1 -0
- data/lib/hecks/version.rb +1 -1
- data/rust/build/src/cargo_sync.rs +1 -1
- data/rust/build/src/pipeline.rs +23 -16
- data/rust/build/src/resolve.rs +39 -6
- data/rust/host/HECKS_RELEASE +1 -1
- data/rust/host/src/api.rs +1 -1
- data/rust/host/src/dispatch.rs +87 -7
- data/rust/host/src/needs.rs +111 -0
- data/rust/parser/src/keywords.rs +7 -6
- data/rust/parser/src/main.rs +4 -3
- data/rust/parser/src/parse/chapter.rs +1 -1
- data/rust/parser/src/parse/hecksagon.rs +25 -10
- data/rust/project/mutations.rb +4 -30
- data/rust/project/naming.rb +8 -28
- data/rust/project/write_if_changed.rb +4 -80
- data/rust/project_rust_pipeline.rb +16 -12
- data/rust/src/kernel/cli.rs +2 -0
- data/rust/src/kernel/needs.rs +74 -1
- metadata +37 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 29694d3639f1ad69a3d0a81bf4e6494c5a6d60a88ca9897af3a01224944d654e
|
|
4
|
+
data.tar.gz: b9fb1376266fe98b2d09c6127bbbbe3a954c11e9441c3f01976e54f44b63eaf7
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 6eea28ed2426948aeca13df88967f06a5d64acf29dbb376a16b53d82367e90383f3646928ee4940ff9d93969ea7721ed29fb4467096eb8a2b88bc14f7f7ede47
|
|
7
|
+
data.tar.gz: 52d5f117ce1b1bae946f939dad3c73567a44c5c466257c37cbaf5bb7bcecb0cb3a3ea92e9c41b3edde78efbdb674669d08f56305287f46313c1cb4ce813d3042
|
data/exe/hecks
CHANGED
|
@@ -2,12 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
# Hecks's command line — GENERATED by hecks project_cli. Do not edit.
|
|
4
4
|
#
|
|
5
|
-
# A launcher, not a CLI: the
|
|
5
|
+
# A launcher, not a CLI: the commands, their arguments and their refusals are
|
|
6
6
|
# projected from the bluebook beside it every time this runs, so a change
|
|
7
7
|
# to the chapter shows up here without re-minting anything.
|
|
8
8
|
#
|
|
9
|
-
# exe/hecks every
|
|
10
|
-
# exe/hecks <
|
|
9
|
+
# exe/hecks every command, and every question
|
|
10
|
+
# exe/hecks <command> --help what it wants, and how it refuses
|
|
11
11
|
|
|
12
12
|
Encoding.default_external = Encoding::UTF_8
|
|
13
13
|
Encoding.default_internal = Encoding::UTF_8
|
|
@@ -21,15 +21,17 @@ if LEGACY.include?(ARGV.first)
|
|
|
21
21
|
exit Hecks::CLI.start(ARGV) unless Hecks::CLI.launcher_form?(ARGV)
|
|
22
22
|
end
|
|
23
23
|
|
|
24
|
-
# These
|
|
25
|
-
#
|
|
26
|
-
|
|
27
|
-
|
|
24
|
+
# These commands keep nothing worth a database, so they run on Memory unless told otherwise.
|
|
25
|
+
# A person is at them: they wait for their result, say why when they are refused, and print
|
|
26
|
+
# no record when they end well.
|
|
27
|
+
MEMORY_COMMANDS = %w[console init].freeze
|
|
28
|
+
ENV["HECKS_ENVIRONMENT"] ||= "memory" if MEMORY_COMMANDS.include?(ARGV.first.to_s.chomp("!"))
|
|
29
|
+
ARGV << "--wait" if MEMORY_COMMANDS.include?(ARGV.first.to_s.chomp("!")) && !ARGV.include?("--wait")
|
|
28
30
|
|
|
29
31
|
require "hecks"
|
|
30
32
|
|
|
31
33
|
# Usage is answered from the projected chapter alone: no adapter is bound and no
|
|
32
|
-
# database is opened. Only a line that runs a
|
|
34
|
+
# database is opened. Only a line that runs a command boots the domain,
|
|
33
35
|
# and it boots from what the usage check already loaded.
|
|
34
36
|
domain = File.expand_path("../lib/hecks/hecks", __dir__)
|
|
35
37
|
program = "hecks"
|
|
@@ -44,7 +46,7 @@ text, status, reason = Hecks::Doors::CliRunner.usage(
|
|
|
44
46
|
)
|
|
45
47
|
unless text
|
|
46
48
|
runtime = begin
|
|
47
|
-
Hecks::Doors::LauncherOptions.quietly(hold:
|
|
49
|
+
Hecks::Doors::LauncherOptions.quietly(hold: MEMORY_COMMANDS.include?(ARGV.first.to_s.chomp("!"))) { Hecks.boot_described(described, install_doors: false) }
|
|
48
50
|
rescue StandardError => e
|
|
49
51
|
abort "cannot open Hecks: #{e.message.lines.first.strip}"
|
|
50
52
|
end
|
|
@@ -58,9 +60,19 @@ end
|
|
|
58
60
|
# A `--wait` run that failed answers its settled record on stdout, so `| jq` reads it
|
|
59
61
|
# either way, and says why on stderr.
|
|
60
62
|
if reason
|
|
61
|
-
|
|
62
|
-
|
|
63
|
+
if MEMORY_COMMANDS.include?(ARGV.first.to_s.chomp("!"))
|
|
64
|
+
why = begin
|
|
65
|
+
require "json"
|
|
66
|
+
JSON.parse(text).dig("state", "refusal", "value")
|
|
67
|
+
rescue JSON::ParserError
|
|
68
|
+
nil
|
|
69
|
+
end
|
|
70
|
+
warn(why ? why.sub(/\A(\w+::)+\w+: /, "") : reason)
|
|
71
|
+
else
|
|
72
|
+
puts text
|
|
73
|
+
warn reason
|
|
74
|
+
end
|
|
63
75
|
exit status
|
|
64
76
|
end
|
|
65
|
-
exit 0 if status.zero? &&
|
|
77
|
+
exit 0 if status.zero? && MEMORY_COMMANDS.include?(ARGV.first.to_s.chomp("!"))
|
|
66
78
|
status.zero? ? puts(text) : abort(text)
|
|
@@ -7,7 +7,7 @@ module Hecks
|
|
|
7
7
|
# Runtime::RemoteDispatcher's writes: one Lambda invoke, one JSON round trip.
|
|
8
8
|
#
|
|
9
9
|
# The function name defaults to `"hecks-#{domain.downcase}"`, matching
|
|
10
|
-
# `hecks deploy project`'s `stack_name` computation. A domain whose stack
|
|
10
|
+
# `hecks deploy recipe.project`'s `stack_name` computation. A domain whose stack
|
|
11
11
|
# name doesn't follow that pattern must pass `function` explicitly, via
|
|
12
12
|
# a `.world`'s `persisted_by("Lambda")`/`dispatched_by("Lambda")` block.
|
|
13
13
|
class Client
|
|
@@ -38,7 +38,7 @@ module Hecks
|
|
|
38
38
|
function = setting(settings, :function, nil)
|
|
39
39
|
# `domain` only prefixes the instances lookup; the function to call is named by
|
|
40
40
|
# DOMAIN_NAME (set in a deployed Lambda, where root is always /var/task), else by
|
|
41
|
-
# root's basename, which matches hecks deploy project's stack name on a local boot.
|
|
41
|
+
# root's basename, which matches hecks deploy recipe.project's stack name on a local boot.
|
|
42
42
|
function_domain = ENV["DOMAIN_NAME"] || (root ? File.basename(root) : domain)
|
|
43
43
|
@client = Client.new(domain: function_domain, region: region, function: function)
|
|
44
44
|
@prefix = "#{domain}::#{aggregate.hecks_name}#"
|
|
@@ -5,8 +5,8 @@ require "fileutils"
|
|
|
5
5
|
module Hecks
|
|
6
6
|
module Adapters
|
|
7
7
|
# The imperative half of tenant provisioning, behind `Deploy::Tenant.port
|
|
8
|
-
# "TenantProvisioning"`, for `Tenant.Provision` and for hecks deploy provision; booting
|
|
9
|
-
# domain and its capability gate stay in hecks deploy provision.
|
|
8
|
+
# "TenantProvisioning"`, for `Tenant.Provision` and for hecks deploy tenant.provision; booting
|
|
9
|
+
# the domain and its capability gate stay in hecks deploy tenant.provision.
|
|
10
10
|
class TenantProvisioner
|
|
11
11
|
# Raised when a value is outside its allow-list or the overlay path leaves `environments/`.
|
|
12
12
|
class Refused < ArgumentError; end
|
|
@@ -3,7 +3,7 @@ module Hecks
|
|
|
3
3
|
module Bluebook
|
|
4
4
|
module DSL
|
|
5
5
|
# Parses a `.hecksagon` file's DSL block into a Hecksagon: a domain's adapter bindings,
|
|
6
|
-
#
|
|
6
|
+
# attachments and subscriptions — wiring, not part of the bluebook.
|
|
7
7
|
class HecksagonBuilder
|
|
8
8
|
GRAMMAR_CONTEXT = "Hecksagon".freeze
|
|
9
9
|
|
|
@@ -57,20 +57,22 @@ module Hecks
|
|
|
57
57
|
end
|
|
58
58
|
end
|
|
59
59
|
|
|
60
|
-
|
|
60
|
+
# The release that drops the deprecated spellings of `attaches`; kept in step with
|
|
61
|
+
# `Hecks::Doors::REMOVAL`, which this file cannot require.
|
|
62
|
+
REMOVAL = "3.2.0".freeze
|
|
63
|
+
|
|
64
|
+
attr_reader :binds, :subscriptions, :attachments
|
|
61
65
|
|
|
62
66
|
def initialize(domain)
|
|
63
67
|
@domain = domain
|
|
64
68
|
@binds = []
|
|
65
69
|
@subscriptions = []
|
|
66
|
-
@
|
|
67
|
-
@vendored_bluebooks = []
|
|
68
|
-
@attached_chapters = []
|
|
70
|
+
@attachments = []
|
|
69
71
|
@bounded = false
|
|
70
72
|
@translates = []
|
|
71
73
|
end
|
|
72
74
|
|
|
73
|
-
# Marks this chapter as a bounded context;
|
|
75
|
+
# Marks this chapter as a bounded context; an attachment marks its chapter bounded too.
|
|
74
76
|
# Must declare at least one `translates` ACL or boot refuses.
|
|
75
77
|
def bounded
|
|
76
78
|
@bounded = true
|
|
@@ -79,35 +81,37 @@ module Hecks
|
|
|
79
81
|
# Subscribes to an event from outside this domain's own bluebook.
|
|
80
82
|
def subscribe(event) = @subscriptions << event.to_s
|
|
81
83
|
|
|
82
|
-
# Attaches a
|
|
84
|
+
# Attaches a chapter by name and loads it into the current registry, marked bounded.
|
|
85
|
+
#
|
|
86
|
+
# Without `from:` the name is a chapter the gem carries (a framework member such as
|
|
87
|
+
# Governance, or a language chapter such as Deploy) with the ports and adapters it
|
|
88
|
+
# ships. `from: :vendor` loads `vendor/embryonaut_bluebooks/<name>/bluebook` instead,
|
|
89
|
+
# and is never a fallback for a misspelt gem name.
|
|
90
|
+
#
|
|
91
|
+
# @param name [String, Symbol] a gem chapter's name or a vendored package's directory name
|
|
92
|
+
# @param from [Symbol, nil] `:vendor` for a vendored package, nil for a gem chapter
|
|
93
|
+
# @raise [Runtime::WiringError] if the name is unknown, or `from:` names another source
|
|
94
|
+
def attaches(name, from: nil)
|
|
95
|
+
unless [nil, :vendor].include?(from)
|
|
96
|
+
raise Runtime::WiringError,
|
|
97
|
+
"attaches #{name.to_s.inspect}, from: #{from.inspect} — `from:` takes only :vendor"
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
from == :vendor ? attach_vendored(name) : attach_gem(name)
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
# The deprecated spelling of `attaches "Name"` for a framework member.
|
|
83
104
|
def uses_framework(name)
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
# anti-corruption layer.
|
|
105
|
+
deprecated_word("uses_framework", "attaches #{name.to_s.inspect}")
|
|
106
|
+
@attachments << Attachment.new(name: name.to_s, source: :gem)
|
|
107
|
+
self.class.with_real_modules { Hecks::Framework.load!(name) }
|
|
88
108
|
Hecks.current_registry&.mark_bounded(name.to_s)
|
|
89
109
|
end
|
|
90
110
|
|
|
91
|
-
#
|
|
92
|
-
# registry. Recorded separately from @framework_members, which is load-bearing for
|
|
93
|
-
# governance checks.
|
|
111
|
+
# The deprecated spelling of `attaches "name", from: :vendor`.
|
|
94
112
|
def uses_embryonaut_bluebook(name)
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
# Marks the chapter bounded, same as `uses_framework`; the directory name Pascal-cases
|
|
98
|
-
# to the chapter name (`"membership"` → `Membership`).
|
|
99
|
-
Hecks.current_registry&.mark_bounded(Hecks::Naming.pascal(name.to_s))
|
|
100
|
-
end
|
|
101
|
-
|
|
102
|
-
# Attaches a chapter the gem carries (the language, Expression, Tenancy, Deploy,
|
|
103
|
-
# QualityControl) by name and loads its files into the registry, with the ports and
|
|
104
|
-
# adapters it ships. Marked bounded like a framework member, since this hecksagon is its
|
|
105
|
-
# anti-corruption layer.
|
|
106
|
-
def attaches(name)
|
|
107
|
-
require_relative "../../chapters"
|
|
108
|
-
@attached_chapters << name.to_s
|
|
109
|
-
self.class.with_real_modules { Hecks::Chapters.load!(name) }
|
|
110
|
-
Hecks.current_registry&.mark_bounded(name.to_s)
|
|
113
|
+
deprecated_word("uses_embryonaut_bluebook", "attaches #{name.to_s.inspect}, from: :vendor")
|
|
114
|
+
attach_vendored(name)
|
|
111
115
|
end
|
|
112
116
|
|
|
113
117
|
# Declares a port at the hecksagon's root — the chapter as a whole, not one aggregate.
|
|
@@ -145,9 +149,32 @@ module Hecks
|
|
|
145
149
|
# No ungoverned-role check here — it runs once on the merged result at verify! time.
|
|
146
150
|
def build
|
|
147
151
|
Hecksagon.new(domain: @domain, binds: @binds, subscriptions: @subscriptions,
|
|
148
|
-
|
|
149
|
-
|
|
152
|
+
attachments: @attachments, bounded: @bounded, translates: @translates)
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
# Loads a chapter the gem carries and records it as attached from the gem.
|
|
156
|
+
def attach_gem(name)
|
|
157
|
+
require_relative "../../chapters"
|
|
158
|
+
@attachments << Attachment.new(name: name.to_s, source: :gem)
|
|
159
|
+
self.class.with_real_modules { Hecks::Chapters.attach!(name) }
|
|
160
|
+
Hecks.current_registry&.mark_bounded(name.to_s)
|
|
161
|
+
end
|
|
162
|
+
private :attach_gem
|
|
163
|
+
|
|
164
|
+
# Loads a vendored package and records it as attached from `vendor/`. The directory name
|
|
165
|
+
# Pascal-cases to the chapter name (`"membership"` becomes `Membership`).
|
|
166
|
+
def attach_vendored(name)
|
|
167
|
+
@attachments << Attachment.new(name: name.to_s, source: :vendor)
|
|
168
|
+
Hecks::EmbryonautBluebook.load!(name)
|
|
169
|
+
Hecks.current_registry&.mark_bounded(Hecks::Naming.pascal(name.to_s))
|
|
170
|
+
end
|
|
171
|
+
private :attach_vendored
|
|
172
|
+
|
|
173
|
+
# Tells the author that a word is going away.
|
|
174
|
+
def deprecated_word(word, instead)
|
|
175
|
+
warn "[hecks] `#{word}` is deprecated and is removed in #{REMOVAL}; use `#{instead}`"
|
|
150
176
|
end
|
|
177
|
+
private :deprecated_word
|
|
151
178
|
|
|
152
179
|
# Records any verb the grammar doesn't own as a domain-wide default bind, e.g. bare
|
|
153
180
|
# `persisted_by "Heki"` at the top of a block, applied unless an aggregate overrides it.
|
|
@@ -20,6 +20,23 @@ module Hecks
|
|
|
20
20
|
def aggregate_name = Naming.demodulise(aggregate)
|
|
21
21
|
end
|
|
22
22
|
|
|
23
|
+
# One chapter a hecksagon attaches, with where it was found.
|
|
24
|
+
#
|
|
25
|
+
# `source` is `:gem` for a chapter the gem carries (a framework member such as Governance,
|
|
26
|
+
# or a language chapter such as Deploy) and `:vendor` for a package vendored into the
|
|
27
|
+
# consuming project, whose `name` is the package's directory name (`"membership"`).
|
|
28
|
+
Attachment = Struct.new(:name, :source, keyword_init: true) do
|
|
29
|
+
# @return [Boolean] whether the chapter is a vendored package
|
|
30
|
+
def vendor? = source == :vendor
|
|
31
|
+
|
|
32
|
+
# @return [String] the chapter's name in the registry: a gem chapter's own name, a
|
|
33
|
+
# vendored package's directory name in Pascal case
|
|
34
|
+
def chapter_name = vendor? ? Naming.pascal(name) : name
|
|
35
|
+
|
|
36
|
+
# @return [Hash{Symbol => String}] the attachment as plain data
|
|
37
|
+
def to_h = { name: name.to_s, source: source.to_s }
|
|
38
|
+
end
|
|
39
|
+
|
|
23
40
|
# The built form of a `.hecksagon` file, produced by `DSL::HecksagonBuilder`.
|
|
24
41
|
# `Behaviour::Hecksagon` supplies the bind lookups; this class holds the declared data.
|
|
25
42
|
class Hecksagon
|
|
@@ -27,39 +44,31 @@ module Hecks
|
|
|
27
44
|
include Behaviour::Hecksagon
|
|
28
45
|
|
|
29
46
|
emits_ir(
|
|
30
|
-
domain:
|
|
31
|
-
binds:
|
|
32
|
-
subscriptions:
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
bounded: :bounded?,
|
|
37
|
-
translates: -> { translates.map(&:to_s) }
|
|
47
|
+
domain: :domain,
|
|
48
|
+
binds: many(:binds),
|
|
49
|
+
subscriptions: -> { subscriptions.map(&:to_s) },
|
|
50
|
+
attachments: -> { attachments.map(&:to_h) },
|
|
51
|
+
bounded: :bounded?,
|
|
52
|
+
translates: -> { translates.map(&:to_s) }
|
|
38
53
|
)
|
|
39
54
|
|
|
40
|
-
attr_reader :domain, :binds, :subscriptions, :
|
|
41
|
-
:attached_chapters, :translates
|
|
55
|
+
attr_reader :domain, :binds, :subscriptions, :attachments, :translates
|
|
42
56
|
|
|
43
57
|
# @param domain [String, Symbol] the domain this hecksagon wires
|
|
44
58
|
# @param binds [Array<Bluebook::Bind>] the declared adapter binds
|
|
45
59
|
# @param subscriptions [Array<String, Symbol>] the external events this domain
|
|
46
60
|
# subscribes to
|
|
47
|
-
# @param
|
|
48
|
-
#
|
|
49
|
-
# bluebook package names this domain attaches
|
|
50
|
-
# @param attached_chapters [Array<String, Symbol>] chapters the gem carries, attached by name
|
|
61
|
+
# @param attachments [Array<Bluebook::Attachment>] every chapter this hecksagon attaches,
|
|
62
|
+
# each with its source (`:gem` or `:vendor`)
|
|
51
63
|
# @param bounded [Boolean] whether this chapter is an explicit bounded context
|
|
52
|
-
# (consumer-owned; `
|
|
53
|
-
# attached chapters bounded on the registry instead)
|
|
64
|
+
# (consumer-owned; `attaches` marks attached chapters bounded on the registry instead)
|
|
54
65
|
# @param translates [Array<String>] names of `translates` ACL blocks declared here
|
|
55
|
-
def initialize(domain:, binds: [], subscriptions: [],
|
|
56
|
-
|
|
66
|
+
def initialize(domain:, binds: [], subscriptions: [], attachments: [], bounded: false,
|
|
67
|
+
translates: [])
|
|
57
68
|
@domain = domain.to_s
|
|
58
69
|
@binds = binds
|
|
59
70
|
@subscriptions = subscriptions
|
|
60
|
-
@
|
|
61
|
-
@vendored_bluebooks = vendored_bluebooks
|
|
62
|
-
@attached_chapters = attached_chapters
|
|
71
|
+
@attachments = attachments
|
|
63
72
|
@bounded = bounded ? true : false
|
|
64
73
|
@translates = Array(translates).map(&:to_s)
|
|
65
74
|
end
|
|
@@ -69,11 +78,22 @@ module Hecks
|
|
|
69
78
|
# @return [Boolean] whether `bounded` was declared on this block
|
|
70
79
|
def bounded? = @bounded
|
|
71
80
|
|
|
72
|
-
# Every chapter this hecksagon brings into its domain's registry
|
|
73
|
-
#
|
|
81
|
+
# Every chapter this hecksagon brings into its domain's registry, gem and vendored alike.
|
|
82
|
+
#
|
|
83
|
+
# @return [Array<String>] the chapters' names as the registry holds them, in the order
|
|
84
|
+
# they were attached
|
|
85
|
+
def member_chapters = attachments.map(&:chapter_name)
|
|
86
|
+
|
|
87
|
+
# Says whether this hecksagon attaches a chapter, whatever its source.
|
|
88
|
+
#
|
|
89
|
+
# @param chapter [String, Symbol] a chapter's name as the registry holds it
|
|
90
|
+
# @return [Boolean] whether that chapter is attached here
|
|
91
|
+
def attaches?(chapter) = member_chapters.include?(chapter.to_s)
|
|
92
|
+
|
|
93
|
+
# The vendored packages this hecksagon attaches.
|
|
74
94
|
#
|
|
75
|
-
# @return [Array<String>]
|
|
76
|
-
def
|
|
95
|
+
# @return [Array<String>] their directory names, in the order they were attached
|
|
96
|
+
def vendored_packages = attachments.select(&:vendor?).map { |attachment| attachment.name.to_s }
|
|
77
97
|
end
|
|
78
98
|
|
|
79
99
|
# The built form of a `.world` file, produced by `DSL::WorldBuilder`.
|
|
@@ -27,7 +27,7 @@ module Hecks
|
|
|
27
27
|
# @param hecksagon [Bluebook::Hecksagon, nil] this bluebook's own sibling wiring
|
|
28
28
|
# file, if the caller loaded one
|
|
29
29
|
# @param known_domains [Set<String>, nil] every bluebook/hecksagon name booted
|
|
30
|
-
# anywhere in this corpus scan, checked to catch a typo'd across/
|
|
30
|
+
# anywhere in this corpus scan, checked to catch a typo'd across/attaches target
|
|
31
31
|
# @param global_emitted_events [Set<String>, nil] every event emitted anywhere in
|
|
32
32
|
# the corpus, checked as a fallback so a translates reaction isn't flagged deaf
|
|
33
33
|
# @param profile [Symbol, nil] :client adds ClientProfile's error findings
|
|
@@ -371,7 +371,7 @@ module Hecks
|
|
|
371
371
|
findings
|
|
372
372
|
end
|
|
373
373
|
|
|
374
|
-
# `
|
|
374
|
+
# `attaches` is a Shared Kernel relationship (X merges in, no boundary);
|
|
375
375
|
# `across` is Customer/Supplier (real cross-Lambda RPC). This checks the choice
|
|
376
376
|
# between them instead of leaving it as an unenforced comment. (ADR 0025)
|
|
377
377
|
def cross_domain_policy_findings(policy, hecksagon, known_domains)
|
|
@@ -382,13 +382,13 @@ module Hecks
|
|
|
382
382
|
target = policy.target_domain
|
|
383
383
|
findings = []
|
|
384
384
|
|
|
385
|
-
if hecksagon.
|
|
385
|
+
if hecksagon.attaches?(target)
|
|
386
386
|
# Shared Kernel and Customer/Supplier are mutually exclusive claims about
|
|
387
387
|
# the same target — declaring both means either a pointless RPC to a
|
|
388
|
-
# domain already local, or
|
|
388
|
+
# domain already local, or an attaches that isn't doing its job.
|
|
389
389
|
findings << Finding.new(kind: :contradictory_relationship, severity: :error, subject: policy.name,
|
|
390
390
|
message: "across #{target.inspect} dispatches over RPC (Customer/Supplier), " \
|
|
391
|
-
"but this hecksagon also
|
|
391
|
+
"but this hecksagon also attaches #{target.inspect} (Shared " \
|
|
392
392
|
"Kernel) — #{target} is already loaded in-process here, so the two " \
|
|
393
393
|
"relationship declarations contradict each other for the same " \
|
|
394
394
|
"target domain")
|
|
@@ -399,7 +399,7 @@ module Hecks
|
|
|
399
399
|
message: "across #{target.inspect} declares a Customer/Supplier " \
|
|
400
400
|
"relationship, but nothing in this hecksagon records the " \
|
|
401
401
|
"expectation — add subscribe \"#{target}.SomeEvent\" for what " \
|
|
402
|
-
"you expect back from it, or
|
|
402
|
+
"you expect back from it, or attaches #{target.inspect} to " \
|
|
403
403
|
"attach it in-process instead")
|
|
404
404
|
end
|
|
405
405
|
|
|
@@ -426,7 +426,7 @@ module Hecks
|
|
|
426
426
|
reached = []
|
|
427
427
|
reached << "#{target} is a domain this corpus boots" if known_domains&.include?(target)
|
|
428
428
|
if hecksagon
|
|
429
|
-
reached << "this hecksagon
|
|
429
|
+
reached << "this hecksagon attaches #{target.inspect}" if hecksagon.attaches?(target)
|
|
430
430
|
if hecksagon.subscriptions.any? { |subscribed| Naming.qualifier(subscribed) == target }
|
|
431
431
|
reached << "this hecksagon subscribes to #{target}"
|
|
432
432
|
end
|
data/lib/hecks/chapters.rb
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
require_relative "naming"
|
|
2
|
+
require_relative "framework"
|
|
2
3
|
require_relative "runtime/registry"
|
|
3
4
|
require_relative "bluebook/meta_validator"
|
|
4
5
|
|
|
5
6
|
module Hecks
|
|
6
7
|
# The chapters the gem carries that a hecksagon can attach by name (ADR 0080): the language
|
|
7
|
-
# declared in itself, Expression, Tenancy, Deploy and QualityControl. Framework members stay
|
|
8
|
-
# `Framework
|
|
8
|
+
# declared in itself, Expression, Tenancy, Deploy, Site and QualityControl. Framework members stay
|
|
9
|
+
# in `Framework`; `table` and `attach!` find a name across both.
|
|
9
10
|
#
|
|
10
11
|
# A chapter is named by the `Hecks.bluebook "Name"` header of its files, and may span several.
|
|
11
12
|
# Beside its bluebook a chapter may carry what every hecksagon attaching it needs, whatever
|
|
@@ -14,7 +15,7 @@ module Hecks
|
|
|
14
15
|
module Chapters
|
|
15
16
|
# Where attachable chapters live, relative to `lib/hecks/`.
|
|
16
17
|
GLOBS = %w[language/**/*.bluebook grammar/expression.bluebook tenancy/bluebook/*.bluebook
|
|
17
|
-
deploy/bluebook/*.bluebook quality_control/*.bluebook].freeze
|
|
18
|
+
deploy/bluebook/*.bluebook site/bluebook/*.bluebook quality_control/*.bluebook].freeze
|
|
18
19
|
|
|
19
20
|
# Every attachable chapter, by name, with the files that declare it.
|
|
20
21
|
#
|
|
@@ -26,6 +27,33 @@ module Hecks
|
|
|
26
27
|
.freeze
|
|
27
28
|
end
|
|
28
29
|
|
|
30
|
+
# Every chapter the gem carries, whichever module loads it: the one lookup table `attaches`
|
|
31
|
+
# finds a name in.
|
|
32
|
+
#
|
|
33
|
+
# @return [Hash{String => Array<String>}] chapter name to its files' absolute paths, the
|
|
34
|
+
# framework members (`Framework.members`) and the attachable chapters (`index`) together
|
|
35
|
+
def self.table
|
|
36
|
+
Framework.members.transform_values { |path| [path] }.merge(index)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# Loads one gem chapter by name, found in `table`: a framework member through
|
|
40
|
+
# `Framework.load!`, any other chapter through `load!`.
|
|
41
|
+
#
|
|
42
|
+
# @param name [String, Symbol] the chapter's name, such as `"Governance"` or `"Deploy"`
|
|
43
|
+
# @return [Boolean, nil] true when this call loaded it, nil when it was already held
|
|
44
|
+
# @raise [Runtime::WiringError] if the gem carries no chapter of that name; the message
|
|
45
|
+
# lists the known names and says how to attach a vendored package
|
|
46
|
+
def self.attach!(name)
|
|
47
|
+
key = name.to_s
|
|
48
|
+
return Framework.load!(key) if Framework.members.key?(key)
|
|
49
|
+
return load!(key) if index.key?(key)
|
|
50
|
+
|
|
51
|
+
raise Runtime::WiringError,
|
|
52
|
+
"attaches #{name.inspect}: the gem carries no chapter of that name — known: " \
|
|
53
|
+
"#{table.keys.sort.join(', ')}. To attach a vendored package, write " \
|
|
54
|
+
"`attaches #{name.to_s.inspect}, from: :vendor`"
|
|
55
|
+
end
|
|
56
|
+
|
|
29
57
|
# Loads a chapter's files into the current registry, unless it already holds the chapter.
|
|
30
58
|
#
|
|
31
59
|
# The files load together inside `MetaValidator.defer`, so a chapter spread over several files
|
data/lib/hecks/cli/check_era.rb
CHANGED
|
@@ -28,7 +28,7 @@ module Hecks
|
|
|
28
28
|
# @raise [Errno::ENOENT, Errno::EACCES] if the file cannot be read
|
|
29
29
|
# @raise [Runtime::EraCheck::ExpectedEra::Unreachable] if the host cannot be reached
|
|
30
30
|
# @raise [Runtime::EraCheck::ExpectedEra::BadResponse] if it answers no era
|
|
31
|
-
def assess(url, file, timeout:
|
|
31
|
+
def assess(url, file, timeout:)
|
|
32
32
|
expected = Runtime::EraCheck::ExpectedEra
|
|
33
33
|
allowed = expected.parse(File.read(file))
|
|
34
34
|
document = expected.fetch_version(url, timeout: timeout)
|
|
@@ -5,7 +5,7 @@ require_relative "../projections/deploy/template_diff"
|
|
|
5
5
|
|
|
6
6
|
module Hecks
|
|
7
7
|
module CLI
|
|
8
|
-
# The command behind `hecks deploy diff
|
|
8
|
+
# The command behind `hecks deploy template_comparison.diff`: compares two
|
|
9
9
|
# CloudFormation templates offline and reports differences by logical id; `--strict` also
|
|
10
10
|
# counts cosmetic differences (comments, key order).
|
|
11
11
|
module DeployTemplateDiff
|
|
@@ -24,7 +24,7 @@ module Hecks
|
|
|
24
24
|
return 0 if clean
|
|
25
25
|
|
|
26
26
|
err.puts "docs/implemented/reference/ is behind the language. " \
|
|
27
|
-
"Regenerate with hecks project_reference to see the words in place."
|
|
27
|
+
"Regenerate with hecks language_run.project_reference to see the words in place."
|
|
28
28
|
1
|
|
29
29
|
end
|
|
30
30
|
end
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
require_relative "../naming"
|
|
2
|
+
|
|
3
|
+
module Hecks
|
|
4
|
+
module CLI
|
|
5
|
+
# The files `hecks init` writes: a stub domain that boots as it stands and that the author
|
|
6
|
+
# then edits into a real one (ADR 0087).
|
|
7
|
+
#
|
|
8
|
+
# Pure: it answers the text of each file and writes none, so the adapter that does the writing
|
|
9
|
+
# can check every target before it writes the first, and a spec can boot the result.
|
|
10
|
+
module DomainStub
|
|
11
|
+
# A domain's name: a capital, then letters and digits, as its bluebook spells it.
|
|
12
|
+
NAME = /\A[A-Z][A-Za-z0-9]*\z/
|
|
13
|
+
|
|
14
|
+
SQLITE_URL = 'default_database "data/%<snake>s.db"'.freeze
|
|
15
|
+
POSTGRES_URL = 'default_database "postgres://localhost/%<snake>s"'.freeze
|
|
16
|
+
private_constant :SQLITE_URL, :POSTGRES_URL
|
|
17
|
+
|
|
18
|
+
# Persistence adapters a stub can be bound to, each with the world lines that bind it, the
|
|
19
|
+
# data it keeps under `data/` (so a `.gitignore` is written), and whether it needs a server
|
|
20
|
+
# (so a memory overlay is written and the first run needs no database).
|
|
21
|
+
ADAPTERS = {
|
|
22
|
+
"Memory" => { world: ['default_adapter "Memory"'], local_data: false, server: false },
|
|
23
|
+
"SqlitePersistence" => { world: ['default_adapter "SqlitePersistence"', SQLITE_URL],
|
|
24
|
+
local_data: true, server: false },
|
|
25
|
+
"Heki" => { world: ['default_adapter "Heki"', 'persisted_by("Heki") { dir "data" }'],
|
|
26
|
+
local_data: true, server: false },
|
|
27
|
+
"Postgres" => { world: ['default_adapter "Postgres"', POSTGRES_URL],
|
|
28
|
+
local_data: false, server: true },
|
|
29
|
+
"PostgresEra" => { world: ['default_adapter "PostgresEra"', POSTGRES_URL],
|
|
30
|
+
local_data: false, server: true }
|
|
31
|
+
}.freeze
|
|
32
|
+
|
|
33
|
+
# What `init` binds a stub to when no adapter is named: it needs no server and keeps its data.
|
|
34
|
+
DEFAULT_ADAPTER = "SqlitePersistence".freeze
|
|
35
|
+
|
|
36
|
+
module_function
|
|
37
|
+
|
|
38
|
+
# @return [Array<String>] the adapter names `init` accepts
|
|
39
|
+
def adapters = ADAPTERS.keys
|
|
40
|
+
|
|
41
|
+
# @param name [String] the domain's name, as its bluebook spells it (`Lending`)
|
|
42
|
+
# @param adapter [String, nil] an adapter named in `ADAPTERS`; the default when nil
|
|
43
|
+
# @return [Hash{String => String}] each file's path under the domain directory, and its text
|
|
44
|
+
# @raise [ArgumentError] when the name is not a capitalised word or the adapter is unknown
|
|
45
|
+
def files(name:, adapter: nil)
|
|
46
|
+
adapter ||= DEFAULT_ADAPTER
|
|
47
|
+
check!(name, adapter)
|
|
48
|
+
{ "bluebook/#{Naming.snake(name)}.bluebook" => bluebook(name) }.merge(support_files(name: name, adapter: adapter))
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# The files around a domain's bluebook: its world bound to the adapter, the memory overlay for
|
|
52
|
+
# an adapter that needs a server, and a `.gitignore` for one that keeps data. `hecks init`
|
|
53
|
+
# writes them beside a stub, and an interview draft beside the bluebook it renders (ADR 0088).
|
|
54
|
+
#
|
|
55
|
+
# @param name [String] the domain's name
|
|
56
|
+
# @param adapter [String, nil] an adapter named in `ADAPTERS`; the default when nil
|
|
57
|
+
# @return [Hash{String => String}] each file's path under the domain directory, and its text
|
|
58
|
+
# @raise [ArgumentError] when the name is not a capitalised word or the adapter is unknown
|
|
59
|
+
def support_files(name:, adapter: nil)
|
|
60
|
+
adapter ||= DEFAULT_ADAPTER
|
|
61
|
+
check!(name, adapter)
|
|
62
|
+
snake = Naming.snake(name)
|
|
63
|
+
files = { "bluebook/#{snake}.world" => world(name, snake, adapter) }
|
|
64
|
+
files["bluebook/environments/memory.world"] = overlay(name) if ADAPTERS.fetch(adapter).fetch(:server)
|
|
65
|
+
files[".gitignore"] = "data/\n" if ADAPTERS.fetch(adapter).fetch(:local_data)
|
|
66
|
+
files
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# @param name [String] a domain name
|
|
70
|
+
# @return [String] the directory `init` writes into when none is named
|
|
71
|
+
def directory(name) = Naming.snake(name)
|
|
72
|
+
|
|
73
|
+
# @api private
|
|
74
|
+
def check!(name, adapter)
|
|
75
|
+
unless name.to_s.match?(NAME)
|
|
76
|
+
raise ArgumentError, "#{name.inspect} is not a domain name: a capital, then letters and digits (Lending)"
|
|
77
|
+
end
|
|
78
|
+
return if ADAPTERS.key?(adapter)
|
|
79
|
+
|
|
80
|
+
raise ArgumentError, "unknown adapter #{adapter.inspect}; choose one of #{adapters.join(', ')}"
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
# @api private
|
|
84
|
+
def bluebook(name)
|
|
85
|
+
<<~BLUEBOOK
|
|
86
|
+
Hecks.bluebook "#{name}" do
|
|
87
|
+
vision "TODO: say in one sentence what #{name} is for."
|
|
88
|
+
supporting
|
|
89
|
+
|
|
90
|
+
# TODO: rename Example to the main thing #{name} keeps track of.
|
|
91
|
+
aggregate "Example" do
|
|
92
|
+
description "TODO: describe what an Example is."
|
|
93
|
+
|
|
94
|
+
identified_by :name
|
|
95
|
+
|
|
96
|
+
attribute :name, ExampleName
|
|
97
|
+
|
|
98
|
+
value_object "ExampleName" do
|
|
99
|
+
attribute :value, String, pattern: '[^ \\t\\n\\r]'
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
# TODO: replace Create with the first thing that happens to an Example.
|
|
103
|
+
command "Create" do
|
|
104
|
+
goal "TODO: say what Create does"
|
|
105
|
+
|
|
106
|
+
attribute :name, ExampleName
|
|
107
|
+
|
|
108
|
+
emits "ExampleCreated"
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
BLUEBOOK
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
# @api private
|
|
116
|
+
def world(name, snake, adapter)
|
|
117
|
+
lines = ADAPTERS.fetch(adapter).fetch(:world).map { |line| " #{format(line, snake: snake)}" }
|
|
118
|
+
note = adapter == "PostgresEra" ? " # PostgresEra refuses a superuser role; use an ordinary one in the URL.\n" : ""
|
|
119
|
+
"Hecks.world \"#{name}\" do\n realm \"#{name}\"\n#{note}#{lines.join("\n")}\nend\n"
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
# @api private
|
|
123
|
+
def overlay(name)
|
|
124
|
+
"Hecks.world \"#{name}\" do\n default_adapter \"Memory\"\nend\n"
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
end
|