hecks 0.2.0 → 0.3.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 +5 -5
- data/lib/hecks/adapters/driven/claude_code.adapter +3 -0
- data/lib/hecks/adapters/driven/claude_code.rb +127 -0
- data/lib/hecks/adapters/driven/d1.adapter +12 -0
- data/lib/hecks/adapters/driven/d1.rb +403 -0
- data/lib/hecks/adapters/driven/folder.adapter +3 -0
- data/lib/hecks/adapters/driven/folder.rb +199 -0
- data/lib/hecks/adapters/driven/google_authentication.adapter +3 -0
- data/lib/hecks/adapters/driven/google_authentication.rb +100 -0
- data/lib/hecks/adapters/driven/governance_authorization.adapter +3 -0
- data/lib/hecks/adapters/driven/governance_authorization.rb +62 -0
- data/lib/hecks/adapters/driven/heki/journal.rb +51 -0
- data/lib/hecks/adapters/driven/heki/saga_store.rb +0 -0
- data/lib/hecks/adapters/driven/heki/snapshot.rb +38 -0
- data/lib/hecks/adapters/driven/heki.adapter +4 -0
- data/lib/hecks/adapters/driven/heki.rb +148 -0
- data/lib/hecks/adapters/driven/identity_registry.adapter +3 -0
- data/lib/hecks/adapters/driven/identity_registry.rb +26 -0
- data/lib/hecks/adapters/driven/in_memory_ordering.rb +51 -0
- data/lib/hecks/adapters/driven/lambda/client.rb +63 -0
- data/lib/hecks/adapters/driven/lambda.adapter +4 -0
- data/lib/hecks/adapters/driven/lambda.rb +131 -0
- data/lib/hecks/adapters/driven/memory.adapter +3 -0
- data/lib/hecks/adapters/driven/memory.rb +103 -0
- data/lib/hecks/adapters/driven/mock_stripe_adapter.adapter +3 -0
- data/lib/hecks/adapters/driven/mock_stripe_adapter.rb +28 -0
- data/lib/hecks/adapters/driven/postgres/codec.rb +80 -0
- data/lib/hecks/adapters/driven/postgres/schema_builder.rb +168 -0
- data/lib/hecks/adapters/driven/postgres.adapter +5 -0
- data/lib/hecks/adapters/driven/postgres.rb +391 -0
- data/lib/hecks/adapters/driven/postgres_era/lineage/era_store.rb +171 -0
- data/lib/hecks/adapters/driven/postgres_era/lineage/field_cache.rb +190 -0
- data/lib/hecks/adapters/driven/postgres_era/lineage/head_compiler.rb +429 -0
- data/lib/hecks/adapters/driven/postgres_era/lineage/mint_transaction.rb +166 -0
- data/lib/hecks/adapters/driven/postgres_era/lineage/provisioning.rb +286 -0
- data/lib/hecks/adapters/driven/postgres_era/lineage/resumable_backfill.rb +168 -0
- data/lib/hecks/adapters/driven/postgres_era/lineage/tail_merge.rb +163 -0
- data/lib/hecks/adapters/driven/postgres_era/lineage/transform_installer.rb +114 -0
- data/lib/hecks/adapters/driven/postgres_era/lineage.rb +137 -0
- data/lib/hecks/adapters/driven/postgres_era/lineage_manager/coverage_check.rb +89 -0
- data/lib/hecks/adapters/driven/postgres_era/lineage_manager/era_resolver.rb +82 -0
- data/lib/hecks/adapters/driven/postgres_era/lineage_manager/merge_coordinator.rb +43 -0
- data/lib/hecks/adapters/driven/postgres_era/lineage_manager/minter.rb +132 -0
- data/lib/hecks/adapters/driven/postgres_era/lineage_manager.rb +74 -0
- data/lib/hecks/adapters/driven/postgres_era.adapter +6 -0
- data/lib/hecks/adapters/driven/postgres_era.rb +671 -0
- data/lib/hecks/adapters/driven/prism.adapter +3 -0
- data/lib/hecks/adapters/driven/prism.rb +80 -0
- data/lib/hecks/adapters/driven/secure_random_identity.adapter +3 -0
- data/lib/hecks/adapters/driven/secure_random_identity.rb +14 -0
- data/lib/hecks/adapters/driven/sql_query_builder.rb +221 -0
- data/lib/hecks/adapters/driven/sqlite/codec.rb +63 -0
- data/lib/hecks/adapters/driven/sqlite/projection.rb +105 -0
- data/lib/hecks/adapters/driven/sqlite/schema_builder.rb +180 -0
- data/lib/hecks/adapters/driven/sqlite.adapter +9 -0
- data/lib/hecks/adapters/driven/sqlite.rb +285 -0
- data/lib/hecks/adapters/driven/system_clock.adapter +3 -0
- data/lib/hecks/adapters/driven/system_clock.rb +14 -0
- data/lib/hecks/adapters/driven.rb +36 -0
- data/lib/hecks/adapters.rb +6 -0
- data/lib/hecks/behaviors/dsl.rb +96 -0
- data/lib/hecks/behaviors/expectations.rb +280 -0
- data/lib/hecks/behaviors/ir.rb +31 -0
- data/lib/hecks/behaviors/rspec.rb +42 -0
- data/lib/hecks/behaviors/runner.rb +96 -0
- data/lib/hecks/behaviors.rb +25 -0
- data/lib/hecks/bluebook/aggregate.rb +108 -0
- data/lib/hecks/bluebook/assembly/aggregate_assembly.rb +134 -0
- data/lib/hecks/bluebook/assembly/build.rb +48 -0
- data/lib/hecks/bluebook/assembly/contract.rb +112 -0
- data/lib/hecks/bluebook/assembly/contracts.rb +409 -0
- data/lib/hecks/bluebook/assembly/marks.rb +227 -0
- data/lib/hecks/bluebook/assembly/specializer.rb +70 -0
- data/lib/hecks/bluebook/assembly.rb +78 -0
- data/lib/hecks/bluebook/attribute.rb +96 -0
- data/lib/hecks/bluebook/behaviour/aggregate.rb +83 -0
- data/lib/hecks/bluebook/behaviour/attribute.rb +27 -0
- data/lib/hecks/bluebook/behaviour/chapter.rb +72 -0
- data/lib/hecks/bluebook/behaviour/command.rb +116 -0
- data/lib/hecks/bluebook/behaviour/domain_port.rb +25 -0
- data/lib/hecks/bluebook/behaviour/entity.rb +59 -0
- data/lib/hecks/bluebook/behaviour/hexagon.rb +50 -0
- data/lib/hecks/bluebook/behaviour/lifecycle.rb +51 -0
- data/lib/hecks/bluebook/behaviour/policy.rb +52 -0
- data/lib/hecks/bluebook/behaviour/process_manager.rb +38 -0
- data/lib/hecks/bluebook/behaviour/query.rb +10 -0
- data/lib/hecks/bluebook/behaviour/read_model.rb +29 -0
- data/lib/hecks/bluebook/behaviour/traits.rb +81 -0
- data/lib/hecks/bluebook/behaviour/value_object.rb +33 -0
- data/lib/hecks/bluebook/chapter.rb +68 -0
- data/lib/hecks/bluebook/command.rb +124 -0
- data/lib/hecks/bluebook/domain_port.rb +102 -0
- data/lib/hecks/bluebook/dsl/adapter_builder.rb +34 -0
- data/lib/hecks/bluebook/dsl/aggregate_builder.rb +906 -0
- data/lib/hecks/bluebook/dsl/attribute_collector.rb +327 -0
- data/lib/hecks/bluebook/dsl/binding_proxy.rb +71 -0
- data/lib/hecks/bluebook/dsl/bluebook_builder.rb +1018 -0
- data/lib/hecks/bluebook/dsl/command_builder.rb +626 -0
- data/lib/hecks/bluebook/dsl/const_shim.rb +81 -0
- data/lib/hecks/bluebook/dsl/domain_port_builder.rb +79 -0
- data/lib/hecks/bluebook/dsl/entity_builder.rb +305 -0
- data/lib/hecks/bluebook/dsl/generic_dispatch.rb +366 -0
- data/lib/hecks/bluebook/dsl/hecksagon_builder.rb +163 -0
- data/lib/hecks/bluebook/dsl/identity_declaration.rb +191 -0
- data/lib/hecks/bluebook/dsl/lifecycle_builder.rb +44 -0
- data/lib/hecks/bluebook/dsl/malformed.rb +7 -0
- data/lib/hecks/bluebook/dsl/policy_builder.rb +120 -0
- data/lib/hecks/bluebook/dsl/port_builder.rb +30 -0
- data/lib/hecks/bluebook/dsl/port_operation_builder.rb +142 -0
- data/lib/hecks/bluebook/dsl/process_manager_builder.rb +207 -0
- data/lib/hecks/bluebook/dsl/query_builder.rb +113 -0
- data/lib/hecks/bluebook/dsl/read_model_builder.rb +233 -0
- data/lib/hecks/bluebook/dsl/rule_reference.rb +172 -0
- data/lib/hecks/bluebook/dsl/translation_builder.rb +243 -0
- data/lib/hecks/bluebook/dsl/value_object_builder.rb +178 -0
- data/lib/hecks/bluebook/dsl/word_gate.rb +221 -0
- data/lib/hecks/bluebook/dsl/world_builder.rb +77 -0
- data/lib/hecks/bluebook/dsl.rb +45 -0
- data/lib/hecks/bluebook/entity.rb +103 -0
- data/lib/hecks/bluebook/expression/canonical_form.rb +55 -0
- data/lib/hecks/bluebook/expression/evaluator.rb +261 -0
- data/lib/hecks/bluebook/expression/projection.json +170 -0
- data/lib/hecks/bluebook/expression/resolver/block_predicates.rb +233 -0
- data/lib/hecks/bluebook/expression/resolver.rb +630 -0
- data/lib/hecks/bluebook/expression.rb +13 -0
- data/lib/hecks/bluebook/hexagon.rb +60 -0
- data/lib/hecks/bluebook/lifecycle.rb +42 -0
- data/lib/hecks/bluebook/meta_validator/adapter_judge.rb +54 -0
- data/lib/hecks/bluebook/meta_validator/judge.rb +559 -0
- data/lib/hecks/bluebook/meta_validator/plan.rb +332 -0
- data/lib/hecks/bluebook/meta_validator/port_judge.rb +47 -0
- data/lib/hecks/bluebook/meta_validator/readings.rb +350 -0
- data/lib/hecks/bluebook/meta_validator/reconstruction.rb +312 -0
- data/lib/hecks/bluebook/meta_validator/shapes.rb +246 -0
- data/lib/hecks/bluebook/meta_validator/syntax_boot.rb +255 -0
- data/lib/hecks/bluebook/meta_validator/translation_judge.rb +138 -0
- data/lib/hecks/bluebook/meta_validator/world_judge.rb +78 -0
- data/lib/hecks/bluebook/meta_validator.rb +452 -0
- data/lib/hecks/bluebook/model_check.rb +318 -0
- data/lib/hecks/bluebook/pattern_subset.rb +120 -0
- data/lib/hecks/bluebook/policy.rb +41 -0
- data/lib/hecks/bluebook/process_manager.rb +86 -0
- data/lib/hecks/bluebook/project_discovery.rb +30 -0
- data/lib/hecks/bluebook/project_loader.rb +40 -0
- data/lib/hecks/bluebook/project_register.rb +82 -0
- data/lib/hecks/bluebook/query.rb +61 -0
- data/lib/hecks/bluebook/read_model.rb +109 -0
- data/lib/hecks/bluebook/reference.rb +74 -0
- data/lib/hecks/bluebook/smoke_test.rb +166 -0
- data/lib/hecks/bluebook/synthesizer.rb +95 -0
- data/lib/hecks/bluebook/translation.rb +92 -0
- data/lib/hecks/bluebook/value_object.rb +58 -0
- data/lib/hecks/bluebook.rb +74 -0
- data/lib/hecks/codemod.rb +342 -0
- data/lib/hecks/construct.rb +71 -0
- data/lib/hecks/deploy/bluebook/deploy.bluebook +219 -0
- data/lib/hecks/deploy/bluebook/deploy.hecksagon +4 -0
- data/lib/hecks/deploy/oidc.json +18 -0
- data/lib/hecks/doc/reference.rb +389 -0
- data/lib/hecks/embryonaut_bluebook.rb +75 -0
- data/lib/hecks/facade/cli_door.rb +116 -0
- data/lib/hecks/facade/cli_runner.rb +190 -0
- data/lib/hecks/facade/command_request.rb +105 -0
- data/lib/hecks/facade/handle.rb +173 -0
- data/lib/hecks/facade/json_door.rb +154 -0
- data/lib/hecks/facade/surface/aggregate_door.rb +185 -0
- data/lib/hecks/facade/surface/chapter.rb +107 -0
- data/lib/hecks/facade/surface.rb +48 -0
- data/lib/hecks/facade.rb +44 -0
- data/lib/hecks/forms/app.rb +300 -0
- data/lib/hecks/forms/command_form_renderer.rb +113 -0
- data/lib/hecks/forms/examples/banking_console.bluebook +3 -0
- data/lib/hecks/forms/field_renderer.rb +170 -0
- data/lib/hecks/forms/field_shape.rb +232 -0
- data/lib/hecks/forms/html.rb +53 -0
- data/lib/hecks/forms/index_renderer.rb +35 -0
- data/lib/hecks/forms/page.rb +157 -0
- data/lib/hecks/forms/params.rb +132 -0
- data/lib/hecks/forms/query_form_renderer.rb +114 -0
- data/lib/hecks/forms/record_renderer.rb +115 -0
- data/lib/hecks/forms/record_table.rb +63 -0
- data/lib/hecks/forms/reference_options.rb +30 -0
- data/lib/hecks/forms/value_object_shape.rb +46 -0
- data/lib/hecks/forms.rb +54 -0
- data/lib/hecks/fqn.rb +94 -0
- data/lib/hecks/framework/bluebook/compliance.bluebook +1 -0
- data/lib/hecks/framework/bluebook/console_settings.bluebook +489 -0
- data/lib/hecks/framework/bluebook/framework.hecksagon +32 -0
- data/lib/hecks/framework/bluebook/governance.bluebook +130 -0
- data/lib/hecks/framework/bluebook/identity.bluebook +90 -0
- data/lib/hecks/framework/oidc.json +39 -0
- data/lib/hecks/framework.rb +90 -0
- data/lib/hecks/freezer.rb +67 -0
- data/lib/hecks/fuzzing/invalid_value_generator.rb +86 -0
- data/lib/hecks/fuzzing/isolated_boot.rb +92 -0
- data/lib/hecks/fuzzing/properties.rb +1146 -0
- data/lib/hecks/fuzzing/replay.rb +635 -0
- data/lib/hecks/fuzzing/sequence_generator/catalog.rb +93 -0
- data/lib/hecks/fuzzing/sequence_generator/outcome_tracker.rb +54 -0
- data/lib/hecks/fuzzing/sequence_generator/picker.rb +96 -0
- data/lib/hecks/fuzzing/sequence_generator/step_builder.rb +185 -0
- data/lib/hecks/fuzzing/sequence_generator.rb +130 -0
- data/lib/hecks/fuzzing/value_generator.rb +177 -0
- data/lib/hecks/fuzzing.rb +12 -0
- data/lib/hecks/grammar/evolve.rb +291 -0
- data/lib/hecks/grammar/expression.bluebook +417 -0
- data/lib/hecks/grammar/expression_operators.json +1152 -0
- data/lib/hecks/grammar/grammar.hecksagon +20 -0
- data/lib/hecks/grammar/oidc.json +69 -0
- data/lib/hecks/grammar/translation.bluebook +203 -0
- data/lib/hecks/grammar.rb +178 -0
- data/lib/hecks/ir.rb +126 -0
- data/lib/hecks/language/adapter.bluebook +116 -0
- data/lib/hecks/language/bluebook/aggregate.bluebook +581 -0
- data/lib/hecks/language/bluebook/attaches/paging.bluebook +76 -0
- data/lib/hecks/language/bluebook/bluebook.bluebook +256 -0
- data/lib/hecks/language/bluebook/bluebook.hecksagon +24 -0
- data/lib/hecks/language/bluebook/command.bluebook +437 -0
- data/lib/hecks/language/bluebook/entity.bluebook +316 -0
- data/lib/hecks/language/bluebook/policy.bluebook +172 -0
- data/lib/hecks/language/bluebook/process_manager.bluebook +264 -0
- data/lib/hecks/language/bluebook/projection.bluebook +267 -0
- data/lib/hecks/language/bluebook/query.bluebook +245 -0
- data/lib/hecks/language/bluebook/shape.bluebook +292 -0
- data/lib/hecks/language/bluebook/syntax.bluebook +447 -0
- data/lib/hecks/language/bluebook/vocabulary.bluebook +364 -0
- data/lib/hecks/language/hecksagon/adapter_binding.bluebook +51 -0
- data/lib/hecks/language/hecksagon/domain_port.bluebook +76 -0
- data/lib/hecks/language/hecksagon/hecksagon.bluebook +131 -0
- data/lib/hecks/language/hecksagon/port_operation.bluebook +102 -0
- data/lib/hecks/language/oidc.json +313 -0
- data/lib/hecks/language/port.bluebook +92 -0
- data/lib/hecks/language/translation/translation.bluebook +110 -0
- data/lib/hecks/language/translation/translation_aggregate.bluebook +267 -0
- data/lib/hecks/language/world/wiring.bluebook +62 -0
- data/lib/hecks/language/world/world.bluebook +84 -0
- data/lib/hecks/literal.rb +125 -0
- data/lib/hecks/naming.rb +121 -0
- data/lib/hecks/ports/access_control.port +4 -0
- data/lib/hecks/ports/access_control.rb +62 -0
- data/lib/hecks/ports/agent/answers.rb +104 -0
- data/lib/hecks/ports/agent.port +4 -0
- data/lib/hecks/ports/agent.rb +167 -0
- data/lib/hecks/ports/authentication.port +4 -0
- data/lib/hecks/ports/authentication.rb +50 -0
- data/lib/hecks/ports/authorization.port +4 -0
- data/lib/hecks/ports/authorization.rb +59 -0
- data/lib/hecks/ports/clock.port +4 -0
- data/lib/hecks/ports/clock.rb +62 -0
- data/lib/hecks/ports/extraction.port +4 -0
- data/lib/hecks/ports/extraction.rb +37 -0
- data/lib/hecks/ports/identity_assignment.port +4 -0
- data/lib/hecks/ports/identity_assignment.rb +45 -0
- data/lib/hecks/ports/identity_generation.port +4 -0
- data/lib/hecks/ports/identity_generation.rb +49 -0
- data/lib/hecks/ports/identity_resolution.port +4 -0
- data/lib/hecks/ports/identity_resolution.rb +40 -0
- data/lib/hecks/ports/loading.port +4 -0
- data/lib/hecks/ports/loading.rb +13 -0
- data/lib/hecks/ports/persistence/append_only.rb +102 -0
- data/lib/hecks/ports/persistence/binding_policy.rb +56 -0
- data/lib/hecks/ports/persistence/execution.rb +18 -0
- data/lib/hecks/ports/persistence/lineage.rb +277 -0
- data/lib/hecks/ports/persistence/null_saga_store.rb +25 -0
- data/lib/hecks/ports/persistence/remote_runtime.rb +42 -0
- data/lib/hecks/ports/persistence/repository_factory.rb +30 -0
- data/lib/hecks/ports/persistence.port +4 -0
- data/lib/hecks/ports/persistence.rb +39 -0
- data/lib/hecks/ports/projection.port +4 -0
- data/lib/hecks/ports/projection.rb +76 -0
- data/lib/hecks/ports/query/in_memory.rb +60 -0
- data/lib/hecks/ports/query/ordering.rb +41 -0
- data/lib/hecks/ports/query.rb +36 -0
- data/lib/hecks/ports.rb +27 -0
- data/lib/hecks/projections/diagrams.rb +413 -0
- data/lib/hecks/projections/ir.rb +18 -0
- data/lib/hecks/projections/model/deviations.rb +98 -0
- data/lib/hecks/projections/model.rb +145 -0
- data/lib/hecks/projections/oidc.rb +110 -0
- data/lib/hecks/projections/parser_table.rb +159 -0
- data/lib/hecks/projections/reference.rb +38 -0
- data/lib/hecks/projections/shape.rb +31 -0
- data/lib/hecks/projections/statements.rb +110 -0
- data/lib/hecks/projections/vocabulary.rb +100 -0
- data/lib/hecks/projections.rb +32 -0
- data/lib/hecks/projector/cli_projector.rb +437 -0
- data/lib/hecks/projector/docs_projector.rb +321 -0
- data/lib/hecks/projector/exporter.rb +141 -0
- data/lib/hecks/projector/ir_projector.rb +18 -0
- data/lib/hecks/projector/narrate_projector.rb +243 -0
- data/lib/hecks/projector/target.rb +97 -0
- data/lib/hecks/projector.rb +186 -0
- data/lib/hecks/query_ir.rb +392 -0
- data/lib/hecks/query_specification/common/authorization_spec.rb +9 -0
- data/lib/hecks/query_specification/common/comparators.rb +25 -0
- data/lib/hecks/query_specification/common/comparison.rb +174 -0
- data/lib/hecks/query_specification/common/cursor_spec.rb +9 -0
- data/lib/hecks/query_specification/common/dsl.rb +58 -0
- data/lib/hecks/query_specification/common/inspection_spec.rb +9 -0
- data/lib/hecks/query_specification/common/limit_spec.rb +9 -0
- data/lib/hecks/query_specification/common/null_policy.rb +80 -0
- data/lib/hecks/query_specification/common/null_semantics.rb +11 -0
- data/lib/hecks/query_specification/common/offset_spec.rb +9 -0
- data/lib/hecks/query_specification/common/options.rb +32 -0
- data/lib/hecks/query_specification/common/order_by.rb +9 -0
- data/lib/hecks/query_specification/common/specification.rb +10 -0
- data/lib/hecks/query_specification/common/where_clause.rb +9 -0
- data/lib/hecks/query_specification/field_path.rb +89 -0
- data/lib/hecks/query_specification/hop_path.rb +130 -0
- data/lib/hecks/query_specification/read_model/specification.rb +18 -0
- data/lib/hecks/query_specification.rb +14 -0
- data/lib/hecks/rendering.rb +48 -0
- data/lib/hecks/router/namespace_installer.rb +157 -0
- data/lib/hecks/router.rb +70 -0
- data/lib/hecks/runtime/caller.rb +50 -0
- data/lib/hecks/runtime/capability_graph.rb +44 -0
- data/lib/hecks/runtime/command_interpreter/argument_gate.rb +124 -0
- data/lib/hecks/runtime/command_interpreter/mutation_applier.rb +248 -0
- data/lib/hecks/runtime/command_interpreter.rb +413 -0
- data/lib/hecks/runtime/command_rules/admissibility.rb +307 -0
- data/lib/hecks/runtime/command_rules/arithmetic.rb +254 -0
- data/lib/hecks/runtime/command_rules/authorization.rb +64 -0
- data/lib/hecks/runtime/command_rules/emission.rb +34 -0
- data/lib/hecks/runtime/command_rules/references.rb +181 -0
- data/lib/hecks/runtime/command_rules.rb +28 -0
- data/lib/hecks/runtime/dependency_planning.rb +231 -0
- data/lib/hecks/runtime/dispatcher.rb +286 -0
- data/lib/hecks/runtime/entity_element.rb +253 -0
- data/lib/hecks/runtime/entity_interpreter.rb +228 -0
- data/lib/hecks/runtime/era_check.rb +136 -0
- data/lib/hecks/runtime/era_guard/shape_diff.rb +128 -0
- data/lib/hecks/runtime/era_guard.rb +193 -0
- data/lib/hecks/runtime/era_tamper.rb +61 -0
- data/lib/hecks/runtime/errors.rb +100 -0
- data/lib/hecks/runtime/event.rb +51 -0
- data/lib/hecks/runtime/identity.rb +128 -0
- data/lib/hecks/runtime/instance.rb +120 -0
- data/lib/hecks/runtime/interpreting.rb +69 -0
- data/lib/hecks/runtime/loader.rb +143 -0
- data/lib/hecks/runtime/policy_interpreter.rb +366 -0
- data/lib/hecks/runtime/port_operation_interpreter.rb +210 -0
- data/lib/hecks/runtime/query_interpreter.rb +254 -0
- data/lib/hecks/runtime/reaction_invocation.rb +245 -0
- data/lib/hecks/runtime/read_model_interpreter.rb +266 -0
- data/lib/hecks/runtime/rebuild_sweep.rb +74 -0
- data/lib/hecks/runtime/reference_hop.rb +99 -0
- data/lib/hecks/runtime/refusal_wording.rb +124 -0
- data/lib/hecks/runtime/registry/saga_persistence.rb +70 -0
- data/lib/hecks/runtime/registry/verification.rb +158 -0
- data/lib/hecks/runtime/registry.rb +218 -0
- data/lib/hecks/runtime/remote_dispatcher.rb +143 -0
- data/lib/hecks/runtime/routing.rb +96 -0
- data/lib/hecks/runtime/saga_interpreter/correlation.rb +97 -0
- data/lib/hecks/runtime/saga_interpreter.rb +301 -0
- data/lib/hecks/runtime/storage_shape.rb +120 -0
- data/lib/hecks/runtime/tenant_check.rb +84 -0
- data/lib/hecks/runtime/tenant_scope.rb +55 -0
- data/lib/hecks/runtime/value/admission.rb +112 -0
- data/lib/hecks/runtime/value/coercion.rb +500 -0
- data/lib/hecks/runtime/value/invariant_violation.rb +5 -0
- data/lib/hecks/runtime/value.rb +125 -0
- data/lib/hecks/runtime.rb +95 -0
- data/lib/hecks/translation/audit/approval_digest.rb +31 -0
- data/lib/hecks/translation/audit/layer_one.rb +37 -0
- data/lib/hecks/translation/audit/layer_two.rb +77 -0
- data/lib/hecks/translation/audit/unfed_report.rb +42 -0
- data/lib/hecks/translation/audit.rb +70 -0
- data/lib/hecks/translation/reattest.rb +72 -0
- data/lib/hecks/translation/rule_compiler.rb +120 -0
- data/lib/hecks/translation/scaffold/differ.rb +183 -0
- data/lib/hecks/translation/scaffold/renderer.rb +41 -0
- data/lib/hecks/translation/scaffold/writer.rb +28 -0
- data/lib/hecks/translation/scaffold.rb +30 -0
- data/lib/hecks/translation.rb +11 -0
- data/lib/hecks/version.rb +16 -0
- data/lib/hecks/vocabulary.rb +213 -0
- data/lib/hecks.rb +118 -6
- metadata +401 -222
- data/bin/hecks +0 -7
- data/bin/hecks-package +0 -65
- data/bin/hecks_console +0 -12
- data/bin/hecks_serverless +0 -6
- data/lib/cli/build.rb +0 -14
- data/lib/cli/command_runner.rb +0 -28
- data/lib/cli/console.rb +0 -10
- data/lib/cli/generate.rb +0 -37
- data/lib/cli/hecks-cli.rb +0 -27
- data/lib/cli/test.rb +0 -57
- data/lib/console/commands.rb +0 -8
- data/lib/console/hecks-console.rb +0 -1
- data/lib/packager/README.md +0 -0
- data/lib/packager/app_runner.rb +0 -21
- data/lib/packager/args.rb +0 -26
- data/lib/packager/compatibility/fixnum.rb +0 -6
- data/lib/packager/hecks.rb +0 -39
- data/lib/packager/query_runner.rb +0 -21
- data/lib/packager/resources/Dockerfile +0 -11
- data/lib/packager/resources/app_binary +0 -7
- data/lib/packager/resources/bundle_config +0 -3
- data/lib/packager/resources/traveling-ruby-20150715-2.2.2-linux-x86_64.tar.gz +0 -0
- data/lib/packager/resources/traveling-ruby-20150715-2.2.2-osx.tar.gz +0 -0
- data/lib/serverless/Domain +0 -32
- data/lib/serverless/cli.rb +0 -75
- data/lib/serverless/resources/command_name.js +0 -5
- data/lib/serverless/resources/environment.js +0 -7
- data/lib/serverless/resources/handler.js.tt +0 -28
- data/lib/serverless/resources/run_binary.js +0 -22
- data/lib/serverless/resources/serverless.yml +0 -20
|
@@ -0,0 +1,327 @@
|
|
|
1
|
+
module Hecks
|
|
2
|
+
module Bluebook
|
|
3
|
+
module DSL
|
|
4
|
+
module AttributeCollector
|
|
5
|
+
ListOf = Struct.new(:type)
|
|
6
|
+
OneOf = Struct.new(:values)
|
|
7
|
+
|
|
8
|
+
UNSET = Object.new.freeze
|
|
9
|
+
private_constant :UNSET
|
|
10
|
+
|
|
11
|
+
def attributes = @attributes ||= []
|
|
12
|
+
|
|
13
|
+
# Value objects synthesised from inline closed sets, collected here and
|
|
14
|
+
# installed by whoever owns value objects (the aggregate).
|
|
15
|
+
def closed_sets = @closed_sets ||= []
|
|
16
|
+
|
|
17
|
+
# `admits:` names a closed set that is ALREADY DECLARED elsewhere —
|
|
18
|
+
#
|
|
19
|
+
# attribute :op, String, admits: "Vocabulary::QueryComparator"
|
|
20
|
+
#
|
|
21
|
+
# which is the difference between it and `one_of`: `one_of` SYNTHESISES
|
|
22
|
+
# a fresh value object named for the attribute, so it can only ever name
|
|
23
|
+
# something new. `admits` points at a set the language already holds, so
|
|
24
|
+
# the same set can be named from many places without being written twice.
|
|
25
|
+
#
|
|
26
|
+
# QUALIFIED, because a closed set is a value object INSIDE an aggregate
|
|
27
|
+
# and `reference_to` reaches heads only — so this is text, checked where
|
|
28
|
+
# it is read rather than by reference resolution.
|
|
29
|
+
#
|
|
30
|
+
# AND WRITTEN AS TEXT, not as the constant path `Vocabulary::QueryComparator`
|
|
31
|
+
# it reads like. The constant spelling was tried — `ConstShim` returning
|
|
32
|
+
# a Module so Ruby's `::` reaches a second `const_missing` — and it
|
|
33
|
+
# cannot hold: `Facade::Surface` installs every aggregate name as a
|
|
34
|
+
# TOP-LEVEL constant, so the moment any facade exists, `Vocabulary`
|
|
35
|
+
# resolves to that module and the shim is never asked. A spelling that
|
|
36
|
+
# works only until a facade is built is worse than a quoted one.
|
|
37
|
+
#
|
|
38
|
+
# THE TYPE POSITION TAKES A BARE CONSTANT, ALWAYS REQUIRED (ADR 0025,
|
|
39
|
+
# "Attributes") — omitting it (a mint default of String) and quoting
|
|
40
|
+
# it as text both refuse now. Neither had a real reason left: no
|
|
41
|
+
# corpus attribute ever omitted the type, and `ConstShim#const_missing`
|
|
42
|
+
# (S0b) already resolves a bare, not-yet-declared constant to the
|
|
43
|
+
# SAME forward reference the quoted form existed for — a bareword
|
|
44
|
+
# `Name` reaches a value object named "Name" declared later in the
|
|
45
|
+
# same block exactly as `"Name"` used to, `spell`'s own `to_s`
|
|
46
|
+
# renders either one identically. Neither form appears in any frozen
|
|
47
|
+
# era text (checked directly), so both are refused unconditionally —
|
|
48
|
+
# nothing for `MetaValidator.shadow_parsing?` to answer for.
|
|
49
|
+
# RENAMED FROM `attribute` — item #13's full metaprogrammed
|
|
50
|
+
# dispatch (slice 3, whole-project table-unification survey).
|
|
51
|
+
# The word `attribute` itself is no longer a real method any
|
|
52
|
+
# builder answers directly: every (context, word) Keyword row
|
|
53
|
+
# for it carries `calls: "attribute_impl"`, and `GenericDispatch`
|
|
54
|
+
# forwards the whole call here untouched — this method's own
|
|
55
|
+
# body is exactly what `attribute` always was, unchanged, just
|
|
56
|
+
# reached generically now rather than by Ruby's own direct
|
|
57
|
+
# method lookup. `attribute_collector_spec.rb` (`AttributeCollector
|
|
58
|
+
# has no method without a test` — dsl_coverage_spec.rb) and the
|
|
59
|
+
# bootstrap fallback (`GenericDispatch::BOOTSTRAP_CALLS_FALLBACK`) both
|
|
60
|
+
# name this same string; they must never drift apart.
|
|
61
|
+
def attribute_impl(name, type = UNSET, default: nil, optional: false, pattern: nil,
|
|
62
|
+
admits: nil, one_of: nil)
|
|
63
|
+
# moved to the language: FieldName invariant, on Root.Attribute
|
|
64
|
+
|
|
65
|
+
if type.equal?(UNSET)
|
|
66
|
+
raise Malformed, "#{name} declares no type — attribute :#{name}, SomeType is required, " \
|
|
67
|
+
"there is no default"
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# `list_of("X")` carries the same quoted text one level down — a
|
|
71
|
+
# bare constant is required there too, checked before it unwraps
|
|
72
|
+
# below, not after (once unwrapped, a plain String in the `type:`
|
|
73
|
+
# slot looks identical to one that legitimately belongs there).
|
|
74
|
+
quoted = type.is_a?(ListOf) ? type.type : type
|
|
75
|
+
if quoted.is_a?(::String)
|
|
76
|
+
raise Malformed, "#{name}'s type #{quoted.inspect} is quoted text — give the bare constant " \
|
|
77
|
+
"(#{quoted}) instead; a forward reference to a value object declared later " \
|
|
78
|
+
"in the same block already resolves without quoting"
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
refuse_unshared_pattern(name, pattern) if pattern
|
|
82
|
+
|
|
83
|
+
type = synthesise_closed_set(name, type) if type.is_a?(OneOf)
|
|
84
|
+
list = type.is_a?(ListOf)
|
|
85
|
+
attributes << Attribute.new(
|
|
86
|
+
name: name,
|
|
87
|
+
type: list ? type.type : type,
|
|
88
|
+
list: list,
|
|
89
|
+
default: default,
|
|
90
|
+
optional: optional,
|
|
91
|
+
pattern: pattern,
|
|
92
|
+
admits: admits
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
install_inline_closed_set(name, one_of) if one_of
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
# RENAMED FROM `list_of` — item #13's full metaprogrammed
|
|
99
|
+
# dispatch (slice 5). Called in an attribute's own TYPE
|
|
100
|
+
# position (`attribute :x, list_of(Y)`), never through a `def
|
|
101
|
+
# list_of` any ONE builder answers as its own word — reached
|
|
102
|
+
# via `WordGate#word_gate_dispatch`'s new "Type"-context
|
|
103
|
+
# fallback, the same one `one_of_impl` below uses. Bootstrap-
|
|
104
|
+
# reachable (every core chapter's own list-typed attributes use
|
|
105
|
+
# it), so `GenericDispatch::BOOTSTRAP_CALLS_FALLBACK` carries a
|
|
106
|
+
# SINGLE `["Type", "list_of"]` entry rather than one per calling
|
|
107
|
+
# context — the bootstrap branch checks that key too now, same
|
|
108
|
+
# reasoning as the ordinary fallback.
|
|
109
|
+
def list_of_impl(type) = ListOf.new(type)
|
|
110
|
+
|
|
111
|
+
# `reference_to Account` MINTS `:account` — no `_id` — the default
|
|
112
|
+
# every `reference_to`-shaped word (`AggregateBuilder`,
|
|
113
|
+
# `EntityBuilder`, `CommandBuilder#cross_reference`,
|
|
114
|
+
# `QueryBuilder`, `PortOperationBuilder`, all `include
|
|
115
|
+
# AttributeCollector`) shares, since dropping the suffix is what
|
|
116
|
+
# makes `/` a real traversal operator possible at all (ADR 0025,
|
|
117
|
+
# "References" — a hop crosses at `/`, a field walk crosses at
|
|
118
|
+
# `.`; deriving the hop name from `account_id` is what made an
|
|
119
|
+
# explicit operator impossible before).
|
|
120
|
+
#
|
|
121
|
+
# LEGACY UNDER SHADOW-PARSING (S0a's own bridge): frozen era text
|
|
122
|
+
# was minted under the OLD default, and `EraGuard.shadow_parse`
|
|
123
|
+
# reconstructs a held aggregate's shape to DIFF against the
|
|
124
|
+
# current one — reading that text through the NEW default would
|
|
125
|
+
# silently reconstruct the WRONG historical name, not merely
|
|
126
|
+
# refuse a spelling the way S1's `identified_by` legacy forms do.
|
|
127
|
+
# This is a mint DEFAULT changing, not a syntax being removed, so
|
|
128
|
+
# there is nothing to refuse here — only a fork in what gets
|
|
129
|
+
# minted when `as:` is omitted.
|
|
130
|
+
private def default_reference_name(target)
|
|
131
|
+
suffix = MetaValidator.shadow_parsing? ? "_id" : ""
|
|
132
|
+
:"#{Naming.snake(target)}#{suffix}"
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
# A closed set declared INLINE on the attribute:
|
|
136
|
+
#
|
|
137
|
+
# attribute :status, one_of("open", "shut")
|
|
138
|
+
#
|
|
139
|
+
# Desugars to a value object named for the attribute, so it goes through
|
|
140
|
+
# exactly the machinery a hand-written one_of does — and so the
|
|
141
|
+
# attribute's type is still a DECLARED value object, which is now a
|
|
142
|
+
# structural rule rather than a predicate.
|
|
143
|
+
#
|
|
144
|
+
# An earlier reading of this spelling parsed it and threw the values
|
|
145
|
+
# away: the attribute became a plain String and the closed set meant
|
|
146
|
+
# nothing, in a construct that looked supported. The desugaring is
|
|
147
|
+
# pinned now — the same bluebook must always yield the same IR.
|
|
148
|
+
# RENAMED FROM `one_of` — item #13's full metaprogrammed dispatch
|
|
149
|
+
# (slice 5), same reasoning as list_of_impl above. SAME NAME as
|
|
150
|
+
# `ValueObjectBuilder#one_of_impl`'s own override on purpose —
|
|
151
|
+
# that method's own `super(*values)` call (the no-block, bare
|
|
152
|
+
# type-position case) resolves by METHOD NAME up the ancestor
|
|
153
|
+
# chain, and renaming only one side would silently break it.
|
|
154
|
+
def one_of_impl(*values) = OneOf.new(values)
|
|
155
|
+
|
|
156
|
+
private
|
|
157
|
+
|
|
158
|
+
def relationship_attribute(target, kind, name, optional: false, list: false)
|
|
159
|
+
attributes << Attribute.new(
|
|
160
|
+
name: name,
|
|
161
|
+
type: Reference.new(target),
|
|
162
|
+
list: list,
|
|
163
|
+
optional: optional,
|
|
164
|
+
relationship: kind
|
|
165
|
+
)
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
# `one_of:` NAMES A CLOSED SET ON THE FIELD ITSELF (ADR 0025,
|
|
169
|
+
# "Attributes") — joining `pattern:`/`admits:` where value
|
|
170
|
+
# constraints already live, for the one context where it means
|
|
171
|
+
# anything: a `value_object` block, where it replaces the old
|
|
172
|
+
# `one_of do member ... end` wrapper for a SINGLE-FIELD set (a
|
|
173
|
+
# multi-field set still writes bare `member` lines, unwrapped).
|
|
174
|
+
# `ValueObjectBuilder` overrides this; every other includer
|
|
175
|
+
# (Aggregate/Entity/Command/Query/PortOperation) inherits this
|
|
176
|
+
# refusal — those contexts already have the unchanged type-position
|
|
177
|
+
# form (`attribute :status, one_of("open", "shut")`) for an
|
|
178
|
+
# anonymous inline set, so `one_of:` naming a *field* there would be
|
|
179
|
+
# a second spelling of the same idea, not a new one.
|
|
180
|
+
def install_inline_closed_set(name, _values)
|
|
181
|
+
raise Malformed,
|
|
182
|
+
"#{name}'s one_of: only means something inside a value_object — name a closed set " \
|
|
183
|
+
"with the type-position one_of(...) instead"
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
# A pattern is refused AT DECLARATION, not when a value first meets it :
|
|
187
|
+
# a regex whose meaning depends on which engine reads it is a defect in
|
|
188
|
+
# the bluebook, and a bluebook that loads is one whose patterns carry
|
|
189
|
+
# one meaning. PatternSubset says which those are, and why each is refused.
|
|
190
|
+
def refuse_unshared_pattern(name, pattern)
|
|
191
|
+
rejection = PatternSubset.validate(pattern)
|
|
192
|
+
return unless rejection
|
|
193
|
+
|
|
194
|
+
raise Malformed,
|
|
195
|
+
"#{name}'s pattern #{pattern.inspect} uses a #{rejection.construct} — " \
|
|
196
|
+
"#{rejection.reason}"
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
def synthesise_closed_set(name, one_of)
|
|
200
|
+
type = Naming.pascal(name)
|
|
201
|
+
closed_sets << ValueObject.declare(
|
|
202
|
+
name: type,
|
|
203
|
+
attributes: [Attribute.new(name: :value, type: "String")],
|
|
204
|
+
members: one_of.values.map { |value| { value: value.to_s } },
|
|
205
|
+
closed_set: true
|
|
206
|
+
)
|
|
207
|
+
type
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
# Every selected identity head contributes all of its recursively
|
|
211
|
+
# scalar leaves in declaration order. Named, inline and compound-key
|
|
212
|
+
# declarations therefore share one flattening rule.
|
|
213
|
+
def resolve_identity_field!(field, value_objects, context_name)
|
|
214
|
+
attr = attributes.find { |a| a.name == field }
|
|
215
|
+
|
|
216
|
+
# `:id` OR AN `_id`-SUFFIXED NAME WITH NO MATCHING ATTRIBUTE is
|
|
217
|
+
# not a typo to refuse — it is the language's own WALK-PARENT/
|
|
218
|
+
# FALLBACK-IDENTITY convention. The `_id` suffix is the meta-
|
|
219
|
+
# domain's own (the `Command`/`Entity`/`Aggregate` etc. records
|
|
220
|
+
# identify by `owner_id`/`bluebook_id`/`aggregate_id`, supplied
|
|
221
|
+
# by the judge's replay rather than declared locally — see
|
|
222
|
+
# `behavior.bluebook`'s own "owner_id is not a declared
|
|
223
|
+
# attribute" comment); bare `:id` is `Instance#materialize_
|
|
224
|
+
# identity!`'s own fallback name (`@aggregate.identified_by ||
|
|
225
|
+
# :id`) made explicit rather than left implicit — declaring
|
|
226
|
+
# `identified_by :id` says out loud what omitting `identified_by`
|
|
227
|
+
# entirely already meant. `reference_to` mints the `_id` suffix
|
|
228
|
+
# for the same reason `attr.reference?` below resolves bare: an
|
|
229
|
+
# `_id`(-shaped) name is already a scalar by the language's own
|
|
230
|
+
# spelling convention, walk-supplied or locally declared alike.
|
|
231
|
+
return [field.to_s] if attr.nil? && (field.to_s == "id" || field.to_s.end_with?("_id"))
|
|
232
|
+
|
|
233
|
+
raise Malformed, "#{context_name}.identified_by :#{field} names no attribute #{context_name} declares" unless attr
|
|
234
|
+
|
|
235
|
+
identity_paths_for_attribute(attr, value_objects, context_name, field.to_s, [])
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
# A named or inline identity mints one structured field, then expands
|
|
239
|
+
# each scalar leaf beneath it into the existing path-shaped IR.
|
|
240
|
+
def resolve_identity_type!(type, as, insert_at, value_objects, context_name)
|
|
241
|
+
target = Naming.demodulise(type.respond_to?(:hecks_name) ? type.hecks_name : type)
|
|
242
|
+
matches = value_objects.select { |value_object| value_object.hecks_name.to_s == target }
|
|
243
|
+
if matches.size > 1
|
|
244
|
+
raise Malformed, "#{context_name}.identified_by names duplicate value object #{target}"
|
|
245
|
+
end
|
|
246
|
+
|
|
247
|
+
vo = type.respond_to?(:attributes) ? type : matches.first
|
|
248
|
+
raise Malformed, "#{context_name}.identified_by names #{target}, which is not a declared value object" unless vo
|
|
249
|
+
if vo.attributes.empty?
|
|
250
|
+
raise Malformed, "#{context_name}.identified_by names #{target}, which declares no attributes"
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
field = (as || Naming.snake(target)).to_sym
|
|
254
|
+
if attributes.any? { |attribute| attribute.name == field }
|
|
255
|
+
raise Malformed,
|
|
256
|
+
"#{context_name}.identified_by #{target} mints :#{field}, but that attribute is already declared"
|
|
257
|
+
end
|
|
258
|
+
|
|
259
|
+
# `Attribute.new` DIRECTLY, not the public `attribute(...)` DSL
|
|
260
|
+
# entry — `target` is `Naming.demodulise`'d TEXT, not a bareword
|
|
261
|
+
# the bluebook author typed (the type position's own quoted-text
|
|
262
|
+
# refusal is about DSL source, not internal minting), and `vo`
|
|
263
|
+
# ITSELF can't be passed either: it is the real, already-built
|
|
264
|
+
# `ValueObject` subclass, permanently anonymous from Ruby's own
|
|
265
|
+
# `to_s` (only `hecks_name` carries its name) — `Attribute#spell`
|
|
266
|
+
# would demodulise it to "#<Class:0x...>", not "PizzaName".
|
|
267
|
+
attributes << Attribute.new(name: field, type: target)
|
|
268
|
+
# MOVED to `insert_at` — the attribute count AT THE MOMENT
|
|
269
|
+
# `identified_by` was actually called, captured by the caller —
|
|
270
|
+
# not left where `attribute` just appended it. Resolution happens
|
|
271
|
+
# at BUILD time, after every other attribute in the block has
|
|
272
|
+
# already run, so appending would put the identity field LAST
|
|
273
|
+
# regardless of where `identified_by` was actually written.
|
|
274
|
+
# Most real bluebooks write it first (insert_at 0); one (a
|
|
275
|
+
# ScheduledPayment corpus member) writes it after a reference_to
|
|
276
|
+
# and an attribute — this matches either, and whatever a person
|
|
277
|
+
# hand-writing `attribute field, Type` at that exact point,
|
|
278
|
+
# the way this used to be required, would have produced.
|
|
279
|
+
attributes.insert(insert_at, attributes.pop)
|
|
280
|
+
vo.attributes.flat_map do |attribute|
|
|
281
|
+
identity_paths_for_attribute(attribute, value_objects, context_name,
|
|
282
|
+
"#{field}.#{attribute.name}", [target])
|
|
283
|
+
end
|
|
284
|
+
end
|
|
285
|
+
|
|
286
|
+
def identity_paths_for_attribute(attribute, value_objects, context_name, path, visited)
|
|
287
|
+
if attribute.list?
|
|
288
|
+
raise Malformed,
|
|
289
|
+
"#{context_name}'s identity member #{path} is a list — an identity member must be scalar"
|
|
290
|
+
end
|
|
291
|
+
if attribute.optional?
|
|
292
|
+
raise Malformed,
|
|
293
|
+
"#{context_name}'s identity member #{path} is optional — an identity must be wholly known"
|
|
294
|
+
end
|
|
295
|
+
|
|
296
|
+
return [path] if attribute.reference?
|
|
297
|
+
|
|
298
|
+
nested = value_objects.find { |value_object| value_object.hecks_name.to_s == attribute.type.to_s }
|
|
299
|
+
return [path] unless nested
|
|
300
|
+
|
|
301
|
+
if visited.include?(nested.hecks_name.to_s)
|
|
302
|
+
cycle = [*visited, nested.hecks_name.to_s].join(" -> ")
|
|
303
|
+
raise Malformed, "#{context_name}'s identity value objects form a cycle: #{cycle}"
|
|
304
|
+
end
|
|
305
|
+
|
|
306
|
+
# A BARE FIELD DERIVES ONE SCALAR. `identified_by :ref` (or one leg
|
|
307
|
+
# of a compound `identified_by :a, :b`) names a single field, and
|
|
308
|
+
# deriving ITS path only makes sense while every value object along
|
|
309
|
+
# the way wraps exactly one field itself — the same "single-field
|
|
310
|
+
# value object" ADR 0025 names this shape after. A multi-field
|
|
311
|
+
# value object here used to expand silently into every one of its
|
|
312
|
+
# own fields, minting an unannounced compound key nothing declared.
|
|
313
|
+
if nested.attributes.size != 1
|
|
314
|
+
candidates = nested.attributes.map(&:name).join(", ")
|
|
315
|
+
raise Malformed,
|
|
316
|
+
"#{context_name}.identified_by :#{path} names #{nested.hecks_name}, which has " \
|
|
317
|
+
"#{nested.attributes.size} field#{'s' unless nested.attributes.size == 1} (#{candidates})"
|
|
318
|
+
end
|
|
319
|
+
|
|
320
|
+
member = nested.attributes.first
|
|
321
|
+
identity_paths_for_attribute(member, value_objects, context_name, "#{path}.#{member.name}",
|
|
322
|
+
[*visited, nested.hecks_name.to_s])
|
|
323
|
+
end
|
|
324
|
+
end
|
|
325
|
+
end
|
|
326
|
+
end
|
|
327
|
+
end
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
module Hecks
|
|
2
|
+
module Bluebook
|
|
3
|
+
module DSL
|
|
4
|
+
class BindingProxy
|
|
5
|
+
def self.namespace(domain, collector)
|
|
6
|
+
Module.new do
|
|
7
|
+
define_singleton_method(:const_missing) do |aggregate|
|
|
8
|
+
BindingProxy.new("#{domain}::#{aggregate}", collector)
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def initialize(fqn, collector)
|
|
14
|
+
@fqn = fqn
|
|
15
|
+
@collector = collector
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# THE AGGREGATE-SCOPED PORT — `Payments::Payment.port("Gateway") do
|
|
19
|
+
# ... end`, the same receiver a plain bind like `.persisted_by(...)`
|
|
20
|
+
# already reaches, because a port belongs to exactly one aggregate
|
|
21
|
+
# the same way a bind does. A REAL method, not method_missing : its
|
|
22
|
+
# shape (a name and a block building operations) has nothing to do
|
|
23
|
+
# with `Bind`, so it does not belong in that generic verb path.
|
|
24
|
+
def port(name, &block)
|
|
25
|
+
domain, aggregate_name = @fqn.split("::")
|
|
26
|
+
aggregate_ir = Hecks.current_registry.bluebook(domain)&.aggregate(aggregate_name) or
|
|
27
|
+
raise Malformed, "#{@fqn} declares no such aggregate — a port needs one to belong to"
|
|
28
|
+
|
|
29
|
+
# See HecksagonBuilder#port's own comment on why this resolver
|
|
30
|
+
# swap is needed : ConstShim's active resolver is one global for
|
|
31
|
+
# the whole dynamic extent, and it is currently this file's own
|
|
32
|
+
# BindingProxy-minting one, which would turn a bare `Pizza` inside
|
|
33
|
+
# `reference_to Pizza` into another BindingProxy instead of a name.
|
|
34
|
+
built = ConstShim.with(->(const) { const }) { DomainPortBuilder.build(name, owner: aggregate_name, &block) }
|
|
35
|
+
|
|
36
|
+
# A `verb`-shaped port is a plain `Port` — the exact struct
|
|
37
|
+
# `Hecks.port`'s own top-level method registers, so it goes
|
|
38
|
+
# through the same `add_port` the registry already answers for
|
|
39
|
+
# that call. It belongs to no aggregate IR the way an
|
|
40
|
+
# operations-shaped `DomainPort` does; the aggregate above
|
|
41
|
+
# was only needed to resolve `owner` for the operations branch.
|
|
42
|
+
if built.is_a?(Port)
|
|
43
|
+
Hecks.current_registry.add_port(built)
|
|
44
|
+
return self
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
built.operations.each do |operation|
|
|
48
|
+
operation.attributes.select(&:reference?).each { |attribute| attribute.type.declared_in = aggregate_ir }
|
|
49
|
+
end
|
|
50
|
+
aggregate_ir.add_port(built)
|
|
51
|
+
self
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def method_missing(verb, *args, **kwargs, &block)
|
|
55
|
+
@collector << Bind.new(
|
|
56
|
+
aggregate: @fqn,
|
|
57
|
+
verb: verb.to_s,
|
|
58
|
+
adapter: args.first.to_s,
|
|
59
|
+
role: kwargs[:role]&.to_s
|
|
60
|
+
)
|
|
61
|
+
block&.call
|
|
62
|
+
self
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def respond_to_missing?(_name, _include_private = false) = true
|
|
66
|
+
|
|
67
|
+
def to_s = @fqn
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|