Module: Hecks::Facade::Surface::Chapter

Included in:
Hecks::Facade::Surface
Defined in:
lib/hecks/facade/surface/chapter.rb

Overview

One chapter's module: vision and aggregate roll-call on the singleton, one aggregate door per declared head, and the declaration hook for names the door does not carry.

Instance Method Summary collapse

Instance Method Details

#chapter_module(dispatcher, bluebook) ⇒ Object



12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
# File 'lib/hecks/facade/surface/chapter.rb', line 12

def chapter_module(dispatcher, bluebook)
  chapter = Module.new
  chapter.define_singleton_method(:vision)     { bluebook.vision }
  chapter.define_singleton_method(:aggregates) { bluebook.aggregates.map(&:name).sort }

  # THE CHAPTER, EXPLAINING ITSELF. `Projector::DocsProjector` reads
  # nothing but this bluebook's own IR, so the document cannot drift
  # from the domain — the same guarantee `bin/reference` gives the DSL
  # reference by generating it from the Syntax chapter.
  #
  # A METHOD RATHER THAN ONLY A SCRIPT because that is what gets it
  # read: `QualityControl.docs` in a console, beside `vision` and
  # `aggregates`, at the moment somebody is wondering what a verb
  # wants. Projected on each call rather than memoised — it is a pure
  # read of the IR, and a stale document is the entire thing this
  # exists to prevent.
  chapter.define_singleton_method(:docs) do |**options|
    Projector.call(:docs, bluebook: bluebook, options: options)
  end

  # THE CHAPTER, READ BACK IN ENGLISH — `Projector::NarrateProjector`
  # beside `:docs`, for the reader who needs to confirm the domain is
  # right rather than call it: `QualityControl.narrate` in a console.
  chapter.define_singleton_method(:narrate) do |**options|
    Projector.call(:narrate, bluebook: bluebook, options: options)
  end

  # THE DOMAIN'S OWN IR, PROJECTED. `Projector` has taken
  # `call(name, bluebook:, options:)` since §30, but nothing could
  # reach it from a booted domain — this module already closes
  # over the one `Bluebook` every projector wants and simply
  # never handed it out, so every bin/ projector rebuilt a
  # Registry and reloaded the files to recover what was already
  # sitting here.
  #
  #   Pizzas.project(Projections::OIDC)
  #   Pizzas.project(Projections::Shape, out: "shape.json")
  #
  # No `to_ir` companion: `project(Projections::IR)` already
  # answers with the canonical serialized form, and handing out
  # the live graph as well would be a second way to say the same
  # thing. Anything genuinely needing the graph is a projector,
  # and a projector is given it.
  #
  # `out:` writes and everything else is passed through to the
  # target — so `options` stays the projector's own vocabulary
  # (`audience:` for OIDC) rather than a fixed set this method
  # would have to know about.
  chapter.define_singleton_method(:project) do |target, out: nil, **options|
    key      = Projector.key_for(target)
    artifact = Projector.call(key, bluebook: bluebook, options: options)
    return artifact unless out

    Projector.write(artifact, out, as: Projector.emits_for(key))
  end

  bluebook.aggregates.each do |aggregate|
    chapter.const_set(aggregate.hecks_name, aggregate_module(dispatcher, bluebook.name, aggregate))
  end

  # INSIDE A HECKSAGON, A NAME IS A DECLARATION, NOT A LOOKUP. A
  # `.hecksagon` may name an aggregate this door does not carry — a STALE
  # door from an earlier boot resolving another registry's chapter, the
  # exact hazard the constant tree used to hide by reinstalling on every
  # load. With a collector open, the name becomes a `BindingProxy`
  # recording the same bind the aggregate module would ; without one, it
  # is a genuine NameError, exactly as before.
  #
  # THE OTHER READER OF A MISS is S0b's own bridge (docs/dsl-work-
  # slices.md, const_shim.rb's `ScopedConstant`): a bluebook still being
  # DECLARED that names `#{bluebook.name}::Something` — an event, a
  # command reference, an `admits:` — reaches HERE, not
  # `Object.const_missing`, the moment this chapter's own facade already
  # exists (a previous boot in the same process, or this same chapter
  # re-entering its own name). `ConstShim.active?` is exactly as true
  # here as it is at the top level, mid-declaration, and consulting the
  # SAME resolver is what makes a scoped reference resolve identically
  # whether or not a facade happens to be built yet — the earlier
  # attempt's own failure mode (this file's own history) was a bridge
  # that worked only BEFORE any facade existed.
  chapter.define_singleton_method(:const_missing) do |name|
    collector = Bluebook::DSL::HecksagonBuilder.collector
    return Bluebook::DSL::BindingProxy.new("#{bluebook.name}::#{name}", collector) if collector

    resolver = Bluebook::DSL::ConstShim.resolver
    return resolver.call("#{bluebook.name}::#{name}") if resolver

    super(name)
  end

  chapter
end