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,191 @@
|
|
|
1
|
+
module Hecks
|
|
2
|
+
module Bluebook
|
|
3
|
+
module DSL
|
|
4
|
+
# `identified_by` — SHARED by AggregateBuilder and EntityBuilder
|
|
5
|
+
# only (S9, ADR 0025 — "EntityBuilder's duplicate identified_by and
|
|
6
|
+
# resolve_pending_identity! go"): a piece's own identity cannot
|
|
7
|
+
# spell differently from its aggregate's, and until this slice it
|
|
8
|
+
# was hand-duplicated onto both rather than shared.
|
|
9
|
+
#
|
|
10
|
+
# A SEPARATE MODULE from AttributeCollector on purpose — every
|
|
11
|
+
# `attribute()`-taking builder (Command, Query, PortOperation,
|
|
12
|
+
# ValueObject, ...) `include`s that one too, and none of THEM
|
|
13
|
+
# declares an identity of its own ; folding `identified_by` in
|
|
14
|
+
# there made it answer for six builders that never earned the
|
|
15
|
+
# word (`syntax_conformance_spec.rb` catches exactly this — a
|
|
16
|
+
# builder answering a method the grammar never grants it).
|
|
17
|
+
#
|
|
18
|
+
# Requires its includer to ALSO `include AttributeCollector`
|
|
19
|
+
# (for `attributes`/`resolve_identity_field!`/`resolve_identity_
|
|
20
|
+
# type!`, still declared there since every includer of THAT
|
|
21
|
+
# module needs them) and to supply `identity_pool` (private) —
|
|
22
|
+
# the value-object list a bare field's own type resolves
|
|
23
|
+
# against: AggregateBuilder's own `@value_objects + closed_sets`,
|
|
24
|
+
# or EntityBuilder's OWNER's, since a piece mints none of its own.
|
|
25
|
+
module IdentityDeclaration
|
|
26
|
+
# There are three live forms, deliberately distinguishable at the
|
|
27
|
+
# declaration site:
|
|
28
|
+
#
|
|
29
|
+
# identified_by AccountNumber, as: :number # one identity concept
|
|
30
|
+
# identified_by do ... end # a bespoke concept
|
|
31
|
+
# identified_by :branch, :number # an existing compound key
|
|
32
|
+
#
|
|
33
|
+
# One symbol is retired: it cannot say whether the author means a
|
|
34
|
+
# value concept or a field-shaped database key. Frozen source still
|
|
35
|
+
# reaches the old interpretation through `legacy_identified_by`.
|
|
36
|
+
# RENAMED FROM `identified_by` — item #13's full metaprogrammed
|
|
37
|
+
# dispatch (slice 4c), same shared-mixin shape `attribute_impl`
|
|
38
|
+
# already proved in slice 3: ONE renamed method, both Aggregate
|
|
39
|
+
# and Entity Keyword rows name it in `calls:`. Bootstrap-
|
|
40
|
+
# reachable (every self-hosted aggregate/entity declares an
|
|
41
|
+
# identity), so in BOOTSTRAP_CALLS_FALLBACK for both contexts.
|
|
42
|
+
def identified_by_impl(*targets, as: nil, &definition)
|
|
43
|
+
return legacy_identified_by(*targets, as: as, &definition) if MetaValidator.shadow_parsing?
|
|
44
|
+
|
|
45
|
+
refuse_second_identity!
|
|
46
|
+
|
|
47
|
+
if definition
|
|
48
|
+
raise Malformed,
|
|
49
|
+
"#{@name}.identified_by cannot combine a value-object type with a block" unless targets.empty?
|
|
50
|
+
|
|
51
|
+
type_name = identity_value_object_name
|
|
52
|
+
value_object =
|
|
53
|
+
begin
|
|
54
|
+
ValueObjectBuilder.build(
|
|
55
|
+
type_name,
|
|
56
|
+
owner_value_objects: identity_pool,
|
|
57
|
+
&definition
|
|
58
|
+
)
|
|
59
|
+
rescue NameError => error
|
|
60
|
+
# A REMOVED SPELLING MUST REFUSE LOUDLY, not degrade into a raw
|
|
61
|
+
# Ruby error — the one contract `EraGuard.shadow_parse` leans
|
|
62
|
+
# on to know a normal parse genuinely could not read this text
|
|
63
|
+
# (only `Malformed` triggers its shadow-mode retry, era_guard.rb's
|
|
64
|
+
# own comment). The OLD `identified_by { name.value }` — a block
|
|
65
|
+
# whose text was NEVER CALLED, only extracted (legacy_
|
|
66
|
+
# identified_by, below) — is exactly this shape: read under the
|
|
67
|
+
# CURRENT grammar it is instead instance_eval'd as a value-object
|
|
68
|
+
# DEFINITION, and a bare identifier like `name` inside it resolves
|
|
69
|
+
# to nothing WordGate#method_missing recognizes, so Ruby itself
|
|
70
|
+
# raises NameError. Left uncaught, that NameError skipped
|
|
71
|
+
# shadow_parse's rescue entirely and reached callers as a raw
|
|
72
|
+
# crash instead of the frozen-era fallback that exists for
|
|
73
|
+
# precisely this text.
|
|
74
|
+
raise Malformed,
|
|
75
|
+
"#{@name}.identified_by do ... end could not be read as a value-object " \
|
|
76
|
+
"definition: #{error.message}"
|
|
77
|
+
end
|
|
78
|
+
if value_object.attributes.empty?
|
|
79
|
+
raise Malformed, "#{@name}.identified_by do declares no identity attributes"
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
install_identity_value_object!(value_object)
|
|
83
|
+
@identity_type_pending = [value_object, as || :identity, attributes.size]
|
|
84
|
+
return
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
raise Malformed, "#{@name}.identified_by names no identity" if targets.empty?
|
|
88
|
+
|
|
89
|
+
if targets.one? && identity_type?(targets.first)
|
|
90
|
+
@identity_type_pending = [targets.first, as, attributes.size]
|
|
91
|
+
return
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
if targets.one?
|
|
95
|
+
field = targets.first
|
|
96
|
+
raise Malformed,
|
|
97
|
+
"#{@name}.identified_by takes no as: — name the declared field itself" if as
|
|
98
|
+
# Transitional compatibility: the self-hosted language and live
|
|
99
|
+
# corpus still contain this form. Keep it readable until their
|
|
100
|
+
# exemplar-led migration is complete; the final lifecycle cutover
|
|
101
|
+
# replaces this assignment with the targeted refusal.
|
|
102
|
+
@identity_field_pending = field
|
|
103
|
+
return
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
unless targets.all? { |target| !identity_type?(target) }
|
|
107
|
+
raise Malformed,
|
|
108
|
+
"#{@name}.identified_by takes one value-object type or two or more attribute names, not both"
|
|
109
|
+
end
|
|
110
|
+
raise Malformed, "#{@name}.identified_by compound keys take no as:" if as
|
|
111
|
+
|
|
112
|
+
@identity_fields_pending = targets
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
private
|
|
116
|
+
|
|
117
|
+
# RESOLVES whichever of the three `identified_by` shapes is
|
|
118
|
+
# pending, against `identity_pool` — the includer's own private
|
|
119
|
+
# hook. Called at BUILD time, not at `identified_by`'s own call
|
|
120
|
+
# time — see `AttributeCollector#resolve_identity_field!`'s own
|
|
121
|
+
# comment on why.
|
|
122
|
+
def resolve_pending_identity!
|
|
123
|
+
if @identity_type_pending
|
|
124
|
+
type, as, insert_at = @identity_type_pending
|
|
125
|
+
@identity_paths = resolve_identity_type!(type, as, insert_at, identity_pool, @name)
|
|
126
|
+
elsif @identity_field_pending
|
|
127
|
+
@identity_paths = resolve_identity_field!(@identity_field_pending, identity_pool, @name)
|
|
128
|
+
elsif @identity_fields_pending
|
|
129
|
+
@identity_paths = @identity_fields_pending.flat_map do |field|
|
|
130
|
+
resolve_identity_field!(field, identity_pool, @name)
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def identity_type?(target) = target.to_s.match?(/\A[A-Z]/)
|
|
136
|
+
|
|
137
|
+
def refuse_second_identity!
|
|
138
|
+
# During the staged migration a transitional one-symbol declaration
|
|
139
|
+
# may be replaced by the new declaration later in the same builder.
|
|
140
|
+
# This keeps existing builder fixtures/source readable while their
|
|
141
|
+
# exemplar is migrated. Once one-symbol identity is retired this
|
|
142
|
+
# compatibility branch disappears with it.
|
|
143
|
+
if @identity_field_pending && !@identity_type_pending && !@identity_fields_pending
|
|
144
|
+
@identity_field_pending = nil
|
|
145
|
+
return
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
return unless @identity_type_pending || @identity_field_pending || @identity_fields_pending ||
|
|
149
|
+
(@identity_paths && !@identity_paths.empty?)
|
|
150
|
+
|
|
151
|
+
raise Malformed, "#{@name} declares identified_by more than once"
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
# LEGACY — the two removed spellings (a value object + as:, and the
|
|
155
|
+
# multi-line block), kept alive ONLY for `EraGuard.shadow_parse`
|
|
156
|
+
# (S0a, ADR 0025) to still make sense of frozen era text that used
|
|
157
|
+
# them; unreachable outside `MetaValidator.shadow_parsing?`.
|
|
158
|
+
def legacy_identified_by(*targets, as:, &path)
|
|
159
|
+
target = targets.first
|
|
160
|
+
if target
|
|
161
|
+
raise Malformed, "#{@name}.identified_by takes a field name/value object or a block, not both" if path
|
|
162
|
+
|
|
163
|
+
if targets.size > 1
|
|
164
|
+
raise Malformed, "#{@name}.identified_by takes no as: with a compound key" if as
|
|
165
|
+
|
|
166
|
+
@identity_fields_pending = targets
|
|
167
|
+
return
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
if identity_type?(target)
|
|
171
|
+
@identity_type_pending = [target, as, attributes.size]
|
|
172
|
+
else
|
|
173
|
+
raise Malformed,
|
|
174
|
+
"#{@name}.identified_by :#{target} takes no as: — as: only applies to identified_by ValueObject" if as
|
|
175
|
+
|
|
176
|
+
@identity_field_pending = target
|
|
177
|
+
end
|
|
178
|
+
return
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
raise Malformed, "#{@name}.identified_by names no field" unless path
|
|
182
|
+
|
|
183
|
+
paths = Ports::Extraction.canonical(path).to_s.split(" ").reject(&:empty?)
|
|
184
|
+
raise Malformed, "#{@name}.identified_by names no field" if paths.empty?
|
|
185
|
+
|
|
186
|
+
@identity_paths = paths
|
|
187
|
+
end
|
|
188
|
+
end
|
|
189
|
+
end
|
|
190
|
+
end
|
|
191
|
+
end
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
require_relative "word_gate"
|
|
2
|
+
module Hecks
|
|
3
|
+
module Bluebook
|
|
4
|
+
module DSL
|
|
5
|
+
class LifecycleBuilder
|
|
6
|
+
GRAMMAR_CONTEXT = "Lifecycle"
|
|
7
|
+
|
|
8
|
+
include WordGate
|
|
9
|
+
|
|
10
|
+
def initialize(field, default:)
|
|
11
|
+
@field = field
|
|
12
|
+
@default = default
|
|
13
|
+
@transitions = []
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# RENAMED FROM `transition` — item #13's full metaprogrammed
|
|
17
|
+
# dispatch (slice 4c). Bootstrap-reachable (syntax.bluebook's
|
|
18
|
+
# own Keyword/Argument entities describe their `status`
|
|
19
|
+
# lifecycle with it), so in BOOTSTRAP_CALLS_FALLBACK.
|
|
20
|
+
def transition_impl(mapping)
|
|
21
|
+
mapping = mapping.dup
|
|
22
|
+
from = mapping.delete(:from)
|
|
23
|
+
|
|
24
|
+
mapping.each do |command, target|
|
|
25
|
+
@transitions << [
|
|
26
|
+
command.to_s,
|
|
27
|
+
StateTransition.new(target: target, from: from)
|
|
28
|
+
]
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def build
|
|
33
|
+
Lifecycle.new(field: @field, default: @default, transitions: @transitions)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def self.build(field, default:, &block)
|
|
37
|
+
builder = new(field, default: default)
|
|
38
|
+
builder.instance_eval(&block) if block
|
|
39
|
+
builder.build
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
require_relative "word_gate"
|
|
2
|
+
module Hecks
|
|
3
|
+
module Bluebook
|
|
4
|
+
module DSL
|
|
5
|
+
class PolicyBuilder
|
|
6
|
+
GRAMMAR_CONTEXT = "Policy"
|
|
7
|
+
|
|
8
|
+
include WordGate
|
|
9
|
+
|
|
10
|
+
def initialize(name)
|
|
11
|
+
@name = name
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
# `on` — item #13's full metaprogrammed dispatch, slice 1
|
|
15
|
+
# (whole-project table-unification survey): a bare, kind-driven
|
|
16
|
+
# coerce-and-assign, now executed by `GenericDispatch`.
|
|
17
|
+
|
|
18
|
+
# `with:` — WHAT THE TRIGGER IS GIVEN, when the event's own shape
|
|
19
|
+
# is not it. Omitted, the whole event payload forwards verbatim,
|
|
20
|
+
# which is what every policy did before this existed.
|
|
21
|
+
#
|
|
22
|
+
# Same `key => value` shape a saga's own `dispatch ..., with:`
|
|
23
|
+
# takes, and read the same way at runtime: a Symbol names a field
|
|
24
|
+
# on the triggering event, anything else is a literal the policy
|
|
25
|
+
# supplies itself. The reason it exists is the reason a saga's
|
|
26
|
+
# does — a reaction crosses an aggregate boundary, and the event
|
|
27
|
+
# on one side is under no obligation to be shaped like the
|
|
28
|
+
# command on the other. Without it the target has to DECLARE
|
|
29
|
+
# every field the event happens to carry, whether it reads them
|
|
30
|
+
# or not.
|
|
31
|
+
# THE COMMAND ITSELF, NOT ITS NAME (ADR 0025, "events and
|
|
32
|
+
# reactions" — command references become first-class): `trigger
|
|
33
|
+
# Account::Debit`, a bare constant `ConstShim` resolves the same
|
|
34
|
+
# way `reference_to Account` always has, not a quoted verb string.
|
|
35
|
+
# Collapses the qualified/unqualified split this word and a
|
|
36
|
+
# saga's own `dispatch` used to disagree about — see
|
|
37
|
+
# `Naming.command_ref`'s own header for how the `::`/`.` rewrite
|
|
38
|
+
# works, and `SagaInterpreter#qualified` for why an unqualified
|
|
39
|
+
# form has always been enough (same-domain is the fallback, so
|
|
40
|
+
# `Account::Debit` and `Banking::Account::Debit` mean the same
|
|
41
|
+
# thing here).
|
|
42
|
+
#
|
|
43
|
+
# LEGACY UNDER SHADOW-PARSING (S0a's own bridge) — frozen era
|
|
44
|
+
# text still writes the quoted form.
|
|
45
|
+
#
|
|
46
|
+
# RENAMED FROM `trigger` — item #13's full metaprogrammed
|
|
47
|
+
# dispatch (slice 4), same reasoning as has_many_impl above: not
|
|
48
|
+
# bootstrap-reachable, reached through calls: with no fallback
|
|
49
|
+
# needed.
|
|
50
|
+
def trigger_impl(command_ref, with: nil)
|
|
51
|
+
if command_ref.is_a?(::String) && !MetaValidator.shadow_parsing?
|
|
52
|
+
raise Malformed,
|
|
53
|
+
"#{@name}'s trigger #{command_ref.inspect} is quoted text — give the bare command " \
|
|
54
|
+
"constant instead, e.g. trigger Account::Debit"
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
@trigger_command = Naming.command_ref(command_ref)
|
|
58
|
+
@with_spec = (with || {}).to_a
|
|
59
|
+
@projection_declared = !with.nil?
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# `across` — item #13's full metaprogrammed dispatch, slice 1:
|
|
63
|
+
# same shape as `on`, above.
|
|
64
|
+
|
|
65
|
+
# THE GUARD — same extraction CommandBuilder#given/#ensures already
|
|
66
|
+
# use (Ports::Extraction reads the block's SOURCE ; the block itself
|
|
67
|
+
# is never called, here or at runtime — Runtime::PolicyInterpreter
|
|
68
|
+
# evaluates the extracted text through the same
|
|
69
|
+
# Bluebook::Expression::Evaluator a command's own given/ensures run
|
|
70
|
+
# through). No description argument the way given/ensures each
|
|
71
|
+
# carry one : a given's description becomes a GivenNotMet message,
|
|
72
|
+
# and a where that does not hold refuses nothing — it just means
|
|
73
|
+
# this policy does not apply to this event, exactly like an
|
|
74
|
+
# `event_qualifier` miss, which carries no message either.
|
|
75
|
+
#
|
|
76
|
+
# Evaluated against the triggering EVENT's OWN PAYLOAD, not a
|
|
77
|
+
# stored record — a policy reacts to what just happened, and has no
|
|
78
|
+
# aggregate instance of its own to read state from.
|
|
79
|
+
def where(&predicate)
|
|
80
|
+
canonical = Ports::Extraction.canonical(predicate)
|
|
81
|
+
|
|
82
|
+
if canonical.to_s.empty?
|
|
83
|
+
raise Malformed,
|
|
84
|
+
"#{@name}'s where did not survive extraction — its source " \
|
|
85
|
+
"could not be read, so no other runtime could ever evaluate it"
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
@where = canonical
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
# THE FAN-OUT SOURCE — a query verb, "Aggregate.query_name" or
|
|
92
|
+
# "Domain::Aggregate.query_name", the same qualified-or-not shape a
|
|
93
|
+
# saga's own `dispatch` command name already takes
|
|
94
|
+
# (SagaInterpreter#qualified). Runtime::PolicyInterpreter runs the
|
|
95
|
+
# named query against the triggering event's own payload and fires
|
|
96
|
+
# `trigger` once per row, instead of once for the event.
|
|
97
|
+
# `for_each` — item #13's full metaprogrammed dispatch, slice 1:
|
|
98
|
+
# same shape as `on`, above.
|
|
99
|
+
|
|
100
|
+
def build
|
|
101
|
+
Policy.new(
|
|
102
|
+
name: @name,
|
|
103
|
+
on_event: @on_event,
|
|
104
|
+
trigger_command: @trigger_command,
|
|
105
|
+
target_domain: @target_domain,
|
|
106
|
+
where: @where,
|
|
107
|
+
for_each: @for_each,
|
|
108
|
+
with_spec: @with_spec || []
|
|
109
|
+
).tap { |policy| policy.instance_variable_set(:@projection_declared, !!@projection_declared) }
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def self.build(name, &block)
|
|
113
|
+
builder = new(name)
|
|
114
|
+
builder.instance_eval(&block) if block
|
|
115
|
+
builder.build
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
require_relative "word_gate"
|
|
2
|
+
module Hecks
|
|
3
|
+
module Bluebook
|
|
4
|
+
module DSL
|
|
5
|
+
class PortBuilder
|
|
6
|
+
GRAMMAR_CONTEXT = "Port"
|
|
7
|
+
|
|
8
|
+
include WordGate
|
|
9
|
+
|
|
10
|
+
def initialize(name)
|
|
11
|
+
@name = name
|
|
12
|
+
@signal = :reply
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def verb(value) = @verb = value.to_s
|
|
16
|
+
def signal(value) = @signal = value.to_sym
|
|
17
|
+
|
|
18
|
+
def build
|
|
19
|
+
MetaValidator.call_port(Port.new(name: @name, verb: @verb, signal: @signal))
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def self.build(name, &block)
|
|
23
|
+
builder = new(name)
|
|
24
|
+
builder.instance_eval(&block) if block
|
|
25
|
+
builder.build
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
require_relative "word_gate"
|
|
2
|
+
module Hecks
|
|
3
|
+
module Bluebook
|
|
4
|
+
module DSL
|
|
5
|
+
class PortOperationBuilder
|
|
6
|
+
GRAMMAR_CONTEXT = "PortOperation"
|
|
7
|
+
|
|
8
|
+
include AttributeCollector
|
|
9
|
+
include WordGate
|
|
10
|
+
|
|
11
|
+
# `to:` — THE SANCTIONED REPLACEMENT for `reference_to` inside an
|
|
12
|
+
# operation body, added here rather than left as a documented-but-
|
|
13
|
+
# unbuilt promise: reference_to_impl's own refusal message has told
|
|
14
|
+
# authors to "pass the receiving aggregate in to:" since #335, but
|
|
15
|
+
# no `to:` argument existed anywhere in DomainPort's own grammar
|
|
16
|
+
# (domain_port.bluebook) for operation/tells/asks to receive it —
|
|
17
|
+
# confirmed by grep across every lib/hecks/language file, not
|
|
18
|
+
# assumed.
|
|
19
|
+
#
|
|
20
|
+
# GENUINE ROUTING METADATA, NOT AN ATTRIBUTE — matching
|
|
21
|
+
# rust/parser/src/parse/domain_port.rs's own header comment ("The
|
|
22
|
+
# receiving aggregate is routing metadata supplied by to:, not an
|
|
23
|
+
# operation attribute"), which anticipated this shape before either
|
|
24
|
+
# side actually built it. Stored separately (below, threaded to
|
|
25
|
+
# PortOperation as `to:`) rather than reusing reference_to_impl's
|
|
26
|
+
# own attribute-adding path — Dispatcher#port_invocation
|
|
27
|
+
# (lib/hecks/runtime/dispatcher.rb) is the ONE place that resolves
|
|
28
|
+
# routing at dispatch time; it gained a second, purely additive
|
|
29
|
+
# branch for this (falls back to a plain attribute NAMED for the
|
|
30
|
+
# owning aggregate's own identified_by field, the same "declare
|
|
31
|
+
# only external facts with attribute" the refusal message
|
|
32
|
+
# describes) rather than folding `to:` into identity_attribute's
|
|
33
|
+
# existing Reference-attribute scan, which every operation already
|
|
34
|
+
# in the corpus (Banking, pizzas, lifeadelics' own vendored
|
|
35
|
+
# PaymentGateway) still relies on unchanged.
|
|
36
|
+
def initialize(name, to: nil, owner: nil, direction: :inbound)
|
|
37
|
+
@name = name
|
|
38
|
+
@to = to && Naming.demodulise(to)
|
|
39
|
+
@owner = owner
|
|
40
|
+
@direction = direction
|
|
41
|
+
@emits = []
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# ALWAYS an attribute, never the self-reference `CommandBuilder`
|
|
45
|
+
# spells — a port operation has no `creates?`/`acts_on` distinction
|
|
46
|
+
# to protect, so there is nothing for the self-reference branch to be
|
|
47
|
+
# FOR here. `reference_to Payment, as: :payment_id` reads the same
|
|
48
|
+
# even though the target happens to equal the owning aggregate.
|
|
49
|
+
# RENAMED FROM `reference_to` — item #13's full metaprogrammed
|
|
50
|
+
# dispatch (slice 4b). Bootstrap-reachable, in
|
|
51
|
+
# GenericDispatch::BOOTSTRAP_CALLS_FALLBACK.
|
|
52
|
+
#
|
|
53
|
+
# DISABLED, #335 — kept only for MetaValidator's own shadow-parsing
|
|
54
|
+
# pass (the self-hosted grammar's own KeywordSeed/ArgumentSeed rows
|
|
55
|
+
# for "reference_to" in this context are themselves declared using
|
|
56
|
+
# this construct, one level up — deleting the Ruby method would
|
|
57
|
+
# break the language describing itself, not just old domain
|
|
58
|
+
# authors). Every REAL domain author reaches `to:` instead, above —
|
|
59
|
+
# a genuinely different mechanism now, not a relocated spelling of
|
|
60
|
+
# this one (see `to:`'s own comment).
|
|
61
|
+
def reference_to_impl(type, as: nil)
|
|
62
|
+
unless MetaValidator.shadow_parsing?
|
|
63
|
+
raise Malformed,
|
|
64
|
+
"#{@name}.reference_to is behavioral routing, not retained domain state — " \
|
|
65
|
+
"pass the receiving aggregate in to: and declare only external facts with attribute"
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
add_reference!(type, as: as)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def emits(event_name) = @emits << event_name.to_s
|
|
72
|
+
|
|
73
|
+
# THE TWO HALVES OF AN `asks`. An outbound call has exactly two
|
|
74
|
+
# endings and the chapter names both — `answers` for what came back,
|
|
75
|
+
# `refuses` for what the outside said instead. They are separate words
|
|
76
|
+
# rather than two `emits` because a reader has to be able to tell them
|
|
77
|
+
# apart without reading the adapter: one is the thing you wanted, the
|
|
78
|
+
# other is the thing you have to handle.
|
|
79
|
+
# `answers`/`refuses` — item #13's full metaprogrammed dispatch,
|
|
80
|
+
# slice 1 (whole-project table-unification survey): both a bare,
|
|
81
|
+
# kind-driven coerce-and-assign with nothing else, now executed
|
|
82
|
+
# by `GenericDispatch`.
|
|
83
|
+
|
|
84
|
+
def build
|
|
85
|
+
outbound = @direction == :outbound
|
|
86
|
+
refuse_wrong_words!(outbound)
|
|
87
|
+
|
|
88
|
+
operation = PortOperation.new(
|
|
89
|
+
name: @name, attributes: attributes, emits: @emits,
|
|
90
|
+
direction: @direction, answers: @answers, refuses: @refuses, to: @to
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
# AN INBOUND OPERATION STILL HAS TO SAY SOMETHING. Only inbound: an
|
|
94
|
+
# `asks` says it with `answers`/`refuses` instead, and
|
|
95
|
+
# `refuse_wrong_words!` above has already insisted on both.
|
|
96
|
+
raise Malformed,
|
|
97
|
+
"#{@name} declares no emits — an operation with nothing to say " \
|
|
98
|
+
"afterward is a call into nothing" if !outbound && @emits.empty?
|
|
99
|
+
|
|
100
|
+
operation
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
private
|
|
104
|
+
|
|
105
|
+
# THE ONE PLACE a reference attribute actually gets added — both
|
|
106
|
+
# `to:` (initialize, above) and reference_to_impl's own shadow-
|
|
107
|
+
# parsing branch call this, so there is exactly one real
|
|
108
|
+
# implementation of "carry a Reference-typed external fact,"
|
|
109
|
+
# not two that could drift.
|
|
110
|
+
def add_reference!(type, as: nil)
|
|
111
|
+
target = Naming.demodulise(type)
|
|
112
|
+
attribute_impl(as || default_reference_name(target), Reference.new(target))
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
# EACH DIRECTION REFUSES THE OTHER'S WORDS. `emits` on an `asks` looks
|
|
116
|
+
# right and is not: it would name one ending and leave the other
|
|
117
|
+
# nowhere. `answers` on a `tells` is worse — there is no channel back
|
|
118
|
+
# to an inbound caller at all, so it would read as a promise the
|
|
119
|
+
# runtime cannot keep.
|
|
120
|
+
def refuse_wrong_words!(outbound)
|
|
121
|
+
if outbound
|
|
122
|
+
raise Malformed, "#{@name} is an asks and declares emits — name its two endings with " \
|
|
123
|
+
"answers and refuses instead" unless @emits.empty?
|
|
124
|
+
raise Malformed, "#{@name} declares no answers — an ask with no word for what came " \
|
|
125
|
+
"back cannot be reacted to" unless @answers
|
|
126
|
+
raise Malformed, "#{@name} declares no refuses — an ask that cannot fail is a call " \
|
|
127
|
+
"into a system you do not control, pretending otherwise" unless @refuses
|
|
128
|
+
else
|
|
129
|
+
raise Malformed, "#{@name} is a tells and declares #{@answers ? 'answers' : 'refuses'} — " \
|
|
130
|
+
"an inbound fact has no channel back to whoever sent it" if @answers || @refuses
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def self.build(name, to: nil, owner: nil, direction: :inbound, &block)
|
|
135
|
+
builder = new(name, to: to, owner: owner, direction: direction)
|
|
136
|
+
builder.instance_eval(&block) if block
|
|
137
|
+
builder.build
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
end
|