hecks 2.7.0 → 2.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/exe/hecks +11 -0
- data/lib/hecks/adapters/driven/claude_code.rb +4 -104
- data/lib/hecks/adapters/driven/d1.rb +44 -237
- data/lib/hecks/adapters/driven/folder.rb +17 -76
- data/lib/hecks/adapters/driven/google_authentication.rb +15 -49
- data/lib/hecks/adapters/driven/governance_authorization.rb +23 -70
- data/lib/hecks/adapters/driven/heki/journal.rb +8 -41
- data/lib/hecks/adapters/driven/heki/saga_store.rb +12 -54
- data/lib/hecks/adapters/driven/heki/snapshot.rb +4 -12
- data/lib/hecks/adapters/driven/heki.rb +13 -42
- data/lib/hecks/adapters/driven/identity_registry.rb +3 -14
- data/lib/hecks/adapters/driven/in_memory_ordering.rb +9 -26
- data/lib/hecks/adapters/driven/in_process_key_vault.rb +2 -14
- data/lib/hecks/adapters/driven/lambda/client.rb +10 -51
- data/lib/hecks/adapters/driven/lambda.rb +10 -84
- data/lib/hecks/adapters/driven/local_storage.rb +5 -40
- data/lib/hecks/adapters/driven/memory.rb +18 -99
- data/lib/hecks/adapters/driven/mock_stripe_adapter.rb +5 -21
- data/lib/hecks/adapters/driven/postgres/codec.rb +6 -28
- data/lib/hecks/adapters/driven/postgres/outbox.rb +3 -12
- data/lib/hecks/adapters/driven/postgres/reconnect.rb +4 -30
- data/lib/hecks/adapters/driven/postgres/schema_builder.rb +34 -108
- data/lib/hecks/adapters/driven/postgres.rb +145 -134
- data/lib/hecks/adapters/driven/postgres_era.adapter +4 -15
- data/lib/hecks/adapters/driven/prism.rb +7 -30
- data/lib/hecks/adapters/driven/sql_query_builder.rb +21 -121
- data/lib/hecks/adapters/driven/sqlite/codec.rb +8 -40
- data/lib/hecks/adapters/driven/sqlite/projection.rb +26 -82
- data/lib/hecks/adapters/driven/sqlite/schema_builder.rb +40 -84
- data/lib/hecks/adapters/driven/sqlite.rb +128 -65
- data/lib/hecks/adapters/driven/tenant_provisioner.rb +15 -37
- data/lib/hecks/adapters/driven.rb +5 -36
- data/lib/hecks/adapters/driving/github_webhook.rb +8 -76
- data/lib/hecks/behaviors/dsl.rb +7 -25
- data/lib/hecks/behaviors/expectations.rb +32 -142
- data/lib/hecks/behaviors/ir.rb +7 -20
- data/lib/hecks/behaviors/rspec.rb +6 -17
- data/lib/hecks/behaviors/runner.rb +10 -34
- data/lib/hecks/behaviors.rb +4 -8
- data/lib/hecks/bluebook/aggregate.rb +9 -75
- data/lib/hecks/bluebook/assembly/aggregate_assembly.rb +9 -38
- data/lib/hecks/bluebook/assembly/build.rb +4 -15
- data/lib/hecks/bluebook/assembly/contract.rb +15 -136
- data/lib/hecks/bluebook/assembly/contracts.rb +54 -174
- data/lib/hecks/bluebook/assembly/marks.rb +31 -223
- data/lib/hecks/bluebook/assembly/specializer.rb +6 -52
- data/lib/hecks/bluebook/assembly.rb +6 -45
- data/lib/hecks/bluebook/attribute.rb +12 -61
- data/lib/hecks/bluebook/behaviour/aggregate.rb +10 -39
- data/lib/hecks/bluebook/behaviour/attribute.rb +3 -14
- data/lib/hecks/bluebook/behaviour/chapter.rb +17 -42
- data/lib/hecks/bluebook/behaviour/command.rb +14 -66
- data/lib/hecks/bluebook/behaviour/domain_port.rb +4 -20
- data/lib/hecks/bluebook/behaviour/entity.rb +7 -27
- data/lib/hecks/bluebook/behaviour/hexagon.rb +23 -41
- data/lib/hecks/bluebook/behaviour/lifecycle.rb +15 -40
- data/lib/hecks/bluebook/behaviour/policy.rb +23 -52
- data/lib/hecks/bluebook/behaviour/process_manager.rb +30 -57
- data/lib/hecks/bluebook/behaviour/read_model.rb +38 -26
- data/lib/hecks/bluebook/behaviour/traits.rb +27 -64
- data/lib/hecks/bluebook/behaviour/value_object.rb +5 -24
- data/lib/hecks/bluebook/capabilities.rb +17 -49
- data/lib/hecks/bluebook/chapter.rb +10 -48
- data/lib/hecks/bluebook/command.rb +23 -81
- data/lib/hecks/bluebook/domain_port.rb +14 -63
- data/lib/hecks/bluebook/dsl/aggregate_builder/sealing.rb +50 -229
- data/lib/hecks/bluebook/dsl/aggregate_builder.rb +50 -377
- data/lib/hecks/bluebook/dsl/attribute_collector.rb +33 -204
- data/lib/hecks/bluebook/dsl/binding_proxy.rb +17 -65
- data/lib/hecks/bluebook/dsl/bluebook_builder/validation.rb +86 -708
- data/lib/hecks/bluebook/dsl/bluebook_builder.rb +56 -170
- data/lib/hecks/bluebook/dsl/bootstrap_table.rb +1 -0
- data/lib/hecks/bluebook/dsl/command_builder.rb +74 -546
- data/lib/hecks/bluebook/dsl/const_shim.rb +8 -41
- data/lib/hecks/bluebook/dsl/domain_port_builder.rb +12 -87
- data/lib/hecks/bluebook/dsl/entity_builder.rb +44 -330
- data/lib/hecks/bluebook/dsl/generic_dispatch.rb +20 -269
- data/lib/hecks/bluebook/dsl/hecksagon_builder.rb +26 -189
- data/lib/hecks/bluebook/dsl/identity_declaration.rb +13 -88
- data/lib/hecks/bluebook/dsl/lifecycle_builder.rb +6 -20
- data/lib/hecks/bluebook/dsl/policy_builder.rb +16 -88
- data/lib/hecks/bluebook/dsl/port_builder.rb +2 -6
- data/lib/hecks/bluebook/dsl/port_operation_builder.rb +22 -96
- data/lib/hecks/bluebook/dsl/process_manager_builder.rb +31 -184
- data/lib/hecks/bluebook/dsl/query_builder.rb +11 -42
- data/lib/hecks/bluebook/dsl/read_model_builder.rb +75 -201
- data/lib/hecks/bluebook/dsl/rule_reference.rb +22 -163
- data/lib/hecks/bluebook/dsl/translation_builder.rb +28 -114
- data/lib/hecks/bluebook/dsl/value_object_builder.rb +10 -124
- data/lib/hecks/bluebook/dsl/word_gate.rb +16 -162
- data/lib/hecks/bluebook/dsl/world_builder.rb +19 -106
- data/lib/hecks/bluebook/entity.rb +13 -71
- data/lib/hecks/bluebook/expression/ast_json.rb +24 -190
- data/lib/hecks/bluebook/expression/ast_reader.rb +12 -54
- data/lib/hecks/bluebook/expression/canonical_form.rb +11 -88
- data/lib/hecks/bluebook/expression/evaluator.rb +47 -295
- data/lib/hecks/bluebook/expression/resolver/block_predicates.rb +30 -147
- data/lib/hecks/bluebook/expression/resolver.rb +37 -660
- data/lib/hecks/bluebook/hexagon.rb +5 -28
- data/lib/hecks/bluebook/lifecycle.rb +5 -16
- data/lib/hecks/bluebook/meta_validator/adapter_judge.rb +1 -7
- data/lib/hecks/bluebook/meta_validator/judge.rb +111 -361
- data/lib/hecks/bluebook/meta_validator/plan.rb +33 -162
- data/lib/hecks/bluebook/meta_validator/port_judge.rb +2 -7
- data/lib/hecks/bluebook/meta_validator/readings.rb +56 -342
- data/lib/hecks/bluebook/meta_validator/reconstruction.rb +24 -176
- data/lib/hecks/bluebook/meta_validator/shapes.rb +54 -268
- data/lib/hecks/bluebook/meta_validator/syntax_boot.rb +47 -308
- data/lib/hecks/bluebook/meta_validator/translation_judge.rb +7 -43
- data/lib/hecks/bluebook/meta_validator/world_judge.rb +6 -18
- data/lib/hecks/bluebook/meta_validator.rb +79 -349
- data/lib/hecks/bluebook/model_check/client_profile.rb +10 -91
- data/lib/hecks/bluebook/model_check.rb +102 -600
- data/lib/hecks/bluebook/pattern_subset.rb +11 -69
- data/lib/hecks/bluebook/process_manager.rb +13 -83
- data/lib/hecks/bluebook/project_loader.rb +3 -39
- data/lib/hecks/bluebook/project_register.rb +12 -60
- data/lib/hecks/bluebook/query.rb +9 -48
- data/lib/hecks/bluebook/read_model.rb +57 -81
- data/lib/hecks/bluebook/reference.rb +7 -41
- data/lib/hecks/bluebook/smoke_test.rb +8 -98
- data/lib/hecks/bluebook/synthesizer.rb +13 -62
- data/lib/hecks/bluebook/translation.rb +26 -62
- data/lib/hecks/bluebook/value_object.rb +11 -36
- data/lib/hecks/bluebook.rb +5 -22
- data/lib/hecks/cache_dir.rb +84 -0
- data/lib/hecks/cli/document.rb +86 -0
- data/lib/hecks/cli/ir.rb +45 -0
- data/lib/hecks/cli/mcp.rb +31 -0
- data/lib/hecks/cli/mcp_door.rb +366 -0
- data/lib/hecks/cli/model_check.rb +203 -0
- data/lib/hecks/cli/project_cli.rb +90 -0
- data/lib/hecks/cli/project_diagrams.rb +36 -0
- data/lib/hecks/cli/run.rb +173 -0
- data/lib/hecks/cli/smoke_test.rb +45 -0
- data/lib/hecks/cli/stores.rb +53 -0
- data/lib/hecks/cli.rb +160 -0
- data/lib/hecks/construct.rb +8 -34
- data/lib/hecks/deploy/bluebook/deploy.bluebook +33 -142
- data/lib/hecks/deploy/bluebook/deploy.hecksagon +2 -9
- data/lib/hecks/embryonaut_bluebook/lock.rb +3 -35
- data/lib/hecks/embryonaut_bluebook/shape.rb +1 -17
- data/lib/hecks/embryonaut_bluebook/vendor.rb +8 -53
- data/lib/hecks/embryonaut_bluebook/vendor_cli.rb +4 -19
- data/lib/hecks/embryonaut_bluebook.rb +4 -71
- data/lib/hecks/facade/cli_door.rb +24 -106
- data/lib/hecks/facade/cli_runner.rb +28 -172
- data/lib/hecks/facade/command_request.rb +13 -33
- data/lib/hecks/facade/handle.rb +34 -121
- data/lib/hecks/facade/json_door.rb +31 -146
- data/lib/hecks/facade/surface/aggregate_door.rb +39 -104
- data/lib/hecks/facade/surface/chapter.rb +10 -54
- data/lib/hecks/facade/surface.rb +8 -23
- data/lib/hecks/facade.rb +10 -25
- data/lib/hecks/forms/app.rb +15 -70
- data/lib/hecks/forms/command_form_renderer.rb +10 -29
- data/lib/hecks/forms/field_renderer.rb +17 -156
- data/lib/hecks/forms/field_shape.rb +30 -222
- data/lib/hecks/forms/html.rb +12 -47
- data/lib/hecks/forms/index_renderer.rb +1 -4
- data/lib/hecks/forms/page.rb +3 -9
- data/lib/hecks/forms/params.rb +14 -60
- data/lib/hecks/forms/port_argument.rb +2 -19
- data/lib/hecks/forms/query_form_renderer.rb +4 -79
- data/lib/hecks/forms/record_renderer.rb +8 -75
- data/lib/hecks/forms/record_table.rb +7 -50
- data/lib/hecks/forms/reference_options.rb +3 -30
- data/lib/hecks/forms/value_object_shape.rb +8 -35
- data/lib/hecks/forms.rb +5 -33
- data/lib/hecks/fqn.rb +5 -12
- data/lib/hecks/framework/bluebook/compliance.bluebook +16 -65
- data/lib/hecks/framework/bluebook/console_settings.bluebook +47 -134
- data/lib/hecks/framework/bluebook/framework.hecksagon +5 -14
- data/lib/hecks/framework/bluebook/governance.bluebook +13 -34
- data/lib/hecks/framework/bluebook/identity.bluebook +11 -26
- data/lib/hecks/framework/bluebook/privacy.bluebook +8 -33
- data/lib/hecks/framework.rb +11 -80
- data/lib/hecks/freezer.rb +5 -39
- data/lib/hecks/grammar/expression.bluebook +15 -40
- data/lib/hecks/grammar/translation.bluebook +3 -6
- data/lib/hecks/grammar.rb +16 -41
- data/lib/hecks/ir.rb +14 -83
- data/lib/hecks/language/adapter.bluebook +2 -7
- data/lib/hecks/language/bluebook/aggregate.bluebook +56 -221
- data/lib/hecks/language/bluebook/attaches/paging.bluebook +6 -15
- data/lib/hecks/language/bluebook/bluebook.bluebook +15 -83
- data/lib/hecks/language/bluebook/bluebook.hecksagon +3 -15
- data/lib/hecks/language/bluebook/command.bluebook +27 -144
- data/lib/hecks/language/bluebook/entity.bluebook +24 -97
- data/lib/hecks/language/bluebook/policy.bluebook +16 -67
- data/lib/hecks/language/bluebook/process_manager.bluebook +28 -151
- data/lib/hecks/language/bluebook/projection.bluebook +126 -60
- data/lib/hecks/language/bluebook/query.bluebook +12 -43
- data/lib/hecks/language/bluebook/shape.bluebook +23 -73
- data/lib/hecks/language/bluebook/syntax.bluebook +51 -262
- data/lib/hecks/language/bluebook/vocabulary.bluebook +98 -197
- data/lib/hecks/language/hecksagon/adapter_binding.bluebook +3 -10
- data/lib/hecks/language/hecksagon/domain_port.bluebook +4 -19
- data/lib/hecks/language/hecksagon/hecksagon.bluebook +6 -25
- data/lib/hecks/language/hecksagon/port_operation.bluebook +3 -14
- data/lib/hecks/language/oidc.json +35 -0
- data/lib/hecks/language/port.bluebook +4 -17
- data/lib/hecks/language/translation/translation.bluebook +3 -9
- data/lib/hecks/language/translation/translation_aggregate.bluebook +5 -24
- data/lib/hecks/language/world/wiring.bluebook +1 -3
- data/lib/hecks/language/world/world.bluebook +5 -7
- data/lib/hecks/literal.rb +8 -50
- data/lib/hecks/mcp_door_scope.rb +95 -0
- data/lib/hecks/mcp_stdio_guard.rb +4 -41
- data/lib/hecks/naming.rb +29 -137
- data/lib/hecks/ports/access_control.rb +7 -23
- data/lib/hecks/ports/agent/answers.rb +5 -23
- data/lib/hecks/ports/agent.rb +47 -172
- data/lib/hecks/ports/authentication.rb +12 -39
- data/lib/hecks/ports/authorization.rb +16 -43
- data/lib/hecks/ports/clock.rb +5 -45
- data/lib/hecks/ports/extraction.rb +7 -12
- data/lib/hecks/ports/identity_assignment.rb +8 -29
- data/lib/hecks/ports/identity_generation.rb +6 -29
- data/lib/hecks/ports/identity_resolution.rb +2 -10
- data/lib/hecks/ports/key_vault.rb +9 -45
- data/lib/hecks/ports/persistence/append_only.rb +62 -65
- data/lib/hecks/ports/persistence/binding_policy.rb +4 -14
- data/lib/hecks/ports/persistence/codec_boundary.rb +20 -80
- data/lib/hecks/ports/persistence/null_saga_store.rb +4 -20
- data/lib/hecks/ports/persistence/plugin.rb +13 -42
- data/lib/hecks/ports/persistence/plugins/era/era_check.rb +38 -141
- data/lib/hecks/ports/persistence/plugins/era/era_guard/shape_diff.rb +15 -115
- data/lib/hecks/ports/persistence/plugins/era/era_guard.rb +16 -84
- data/lib/hecks/ports/persistence/plugins/era/era_tamper.rb +7 -26
- data/lib/hecks/ports/persistence/plugins/era/expected_era.rb +3 -22
- data/lib/hecks/ports/persistence/plugins/era/lineage.rb +55 -181
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/events.rb +77 -0
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/era_store.rb +12 -122
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/field_cache.rb +28 -128
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/head_compiler.rb +73 -474
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/mint_transaction.rb +31 -124
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/provisioning.rb +45 -219
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/resumable_backfill.rb +13 -108
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/tail_merge.rb +18 -75
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/transform_installer.rb +9 -49
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage.rb +6 -123
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/coverage_check.rb +23 -55
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/era_resolver.rb +14 -72
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/merge_coordinator.rb +7 -16
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/minter.rb +14 -115
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager.rb +13 -45
- data/lib/hecks/ports/persistence/plugins/era/postgres_era.rb +127 -554
- data/lib/hecks/ports/persistence/plugins/era/storage_shape.rb +13 -63
- data/lib/hecks/ports/persistence/plugins/era/translation/audit/approval_digest.rb +2 -17
- data/lib/hecks/ports/persistence/plugins/era/translation/audit/layer_one.rb +3 -14
- data/lib/hecks/ports/persistence/plugins/era/translation/audit/layer_two.rb +13 -58
- data/lib/hecks/ports/persistence/plugins/era/translation/audit/unfed_report.rb +3 -17
- data/lib/hecks/ports/persistence/plugins/era/translation/audit.rb +9 -26
- data/lib/hecks/ports/persistence/plugins/era/translation/reattest.rb +9 -25
- data/lib/hecks/ports/persistence/plugins/era/translation/rule_compiler.rb +22 -122
- data/lib/hecks/ports/persistence/plugins/era/translation/scaffold/differ.rb +34 -123
- data/lib/hecks/ports/persistence/plugins/era/translation/scaffold/renderer.rb +5 -12
- data/lib/hecks/ports/persistence/plugins/era/translation/scaffold/writer.rb +3 -9
- data/lib/hecks/ports/persistence/plugins/era/translation/scaffold.rb +2 -14
- data/lib/hecks/ports/persistence/plugins/era.rb +4 -23
- data/lib/hecks/ports/persistence/postgres_dump/connection.rb +7 -23
- data/lib/hecks/ports/persistence/postgres_dump.rb +4 -35
- data/lib/hecks/ports/persistence/remote_runtime.rb +2 -24
- data/lib/hecks/ports/persistence/repository_factory.rb +8 -27
- data/lib/hecks/ports/persistence/state_codec.rb +23 -103
- data/lib/hecks/ports/persistence.rb +7 -14
- data/lib/hecks/ports/projection.rb +42 -84
- data/lib/hecks/ports/query/in_memory.rb +10 -58
- data/lib/hecks/ports/query/ordering.rb +11 -32
- data/lib/hecks/ports/query.rb +14 -37
- data/lib/hecks/ports.rb +2 -8
- data/lib/hecks/projections/bootstrap_table.rb +11 -43
- data/lib/hecks/projections/deploy/fargate/assembly.rb +2 -15
- data/lib/hecks/projections/deploy/fargate/cdn.rb +1 -48
- data/lib/hecks/projections/deploy/fargate/cdn_default.rb +2 -11
- data/lib/hecks/projections/deploy/fargate/check.rb +5 -14
- data/lib/hecks/projections/deploy/fargate/containers.rb +3 -78
- data/lib/hecks/projections/deploy/fargate/extras.rb +3 -44
- data/lib/hecks/projections/deploy/fargate/monitoring.rb +0 -44
- data/lib/hecks/projections/deploy/fargate/settings.rb +2 -54
- data/lib/hecks/projections/deploy/fargate/yaml.rb +13 -58
- data/lib/hecks/projections/deploy/fargate.rb +35 -202
- data/lib/hecks/projections/deploy/lambda.rb +151 -679
- data/lib/hecks/projections/deploy/preview/access_yaml.rb +1 -33
- data/lib/hecks/projections/deploy/preview/containers.rb +6 -111
- data/lib/hecks/projections/deploy/preview/routing_yaml.rb +4 -56
- data/lib/hecks/projections/deploy/preview/script.rb +2 -14
- data/lib/hecks/projections/deploy/preview/settings.rb +3 -33
- data/lib/hecks/projections/deploy/preview/task_yaml.rb +2 -38
- data/lib/hecks/projections/deploy/preview/template.rb +2 -58
- data/lib/hecks/projections/deploy/preview.rb +2 -67
- data/lib/hecks/projections/deploy/scripts/settings.rb +3 -25
- data/lib/hecks/projections/deploy/scripts.rb +4 -57
- data/lib/hecks/projections/deploy/shared.rb +47 -146
- data/lib/hecks/projections/deploy/smoke.rb +4 -61
- data/lib/hecks/projections/deploy/template_diff/comparer.rb +3 -25
- data/lib/hecks/projections/deploy/template_diff/loader.rb +2 -11
- data/lib/hecks/projections/deploy/template_diff.rb +5 -57
- data/lib/hecks/projections/diagrams.rb +20 -582
- data/lib/hecks/projections/glossary/html.rb +14 -130
- data/lib/hecks/projections/glossary/markdown.rb +8 -69
- data/lib/hecks/projections/glossary/mermaid.rb +9 -66
- data/lib/hecks/projections/glossary/sensitivity.rb +5 -34
- data/lib/hecks/projections/glossary/sentences.rb +14 -159
- data/lib/hecks/projections/glossary.rb +30 -222
- data/lib/hecks/projections/ir.rb +3 -10
- data/lib/hecks/projections/model/deviations.rb +15 -42
- data/lib/hecks/projections/model.rb +12 -51
- data/lib/hecks/projections/oidc.rb +12 -56
- data/lib/hecks/projections/parser_table.rb +9 -28
- data/lib/hecks/projections/reference.rb +9 -16
- data/lib/hecks/projections/rust_vocabulary.rb +12 -250
- data/lib/hecks/projections/shape.rb +3 -29
- data/lib/hecks/projections/statements.rb +7 -86
- data/lib/hecks/projections/vocabulary.rb +6 -22
- data/lib/hecks/projections.rb +2 -16
- data/lib/hecks/projector/cli_projector.rb +60 -375
- data/lib/hecks/projector/docs_projector.rb +10 -201
- data/lib/hecks/projector/exporter.rb +46 -138
- data/lib/hecks/projector/ir_projector.rb +2 -9
- data/lib/hecks/projector/narrate_projector.rb +15 -189
- data/lib/hecks/projector/target.rb +13 -76
- data/lib/hecks/projector.rb +30 -121
- data/lib/hecks/query_specification/common/comparators.rb +5 -26
- data/lib/hecks/query_specification/common/comparison.rb +35 -143
- data/lib/hecks/query_specification/common/dsl.rb +8 -24
- data/lib/hecks/query_specification/common/null_policy.rb +20 -70
- data/lib/hecks/query_specification/common/options.rb +2 -6
- data/lib/hecks/query_specification/common/where_clause.rb +2 -10
- data/lib/hecks/query_specification/field_path.rb +37 -77
- data/lib/hecks/query_specification/hop_path.rb +12 -76
- data/lib/hecks/release/gem_pin.rb +2 -26
- data/lib/hecks/release/runner/ci_publisher.rb +93 -0
- data/lib/hecks/release/runner/commands.rb +66 -0
- data/lib/hecks/release/runner/console.rb +52 -0
- data/lib/hecks/release/runner/gem_publisher.rb +43 -0
- data/lib/hecks/release/runner/git.rb +48 -0
- data/lib/hecks/release/runner/npm_publisher.rb +75 -0
- data/lib/hecks/release/runner/preflight.rb +104 -0
- data/lib/hecks/release/runner/published.rb +55 -0
- data/lib/hecks/release/runner/tagger.rb +80 -0
- data/lib/hecks/release/runner.rb +215 -0
- data/lib/hecks/rendering.rb +4 -26
- data/lib/hecks/router/namespace_installer.rb +12 -36
- data/lib/hecks/router.rb +4 -8
- data/lib/hecks/runtime/aggregate_lock.rb +8 -33
- data/lib/hecks/runtime/boot_gates.rb +3 -18
- data/lib/hecks/runtime/caller.rb +19 -59
- data/lib/hecks/runtime/capability_graph.rb +5 -21
- data/lib/hecks/runtime/command_interpreter/argument_gate.rb +16 -78
- data/lib/hecks/runtime/command_interpreter/mutation_applier.rb +23 -160
- data/lib/hecks/runtime/command_interpreter.rb +125 -307
- data/lib/hecks/runtime/command_rules/admissibility.rb +95 -366
- data/lib/hecks/runtime/command_rules/arithmetic.rb +66 -196
- data/lib/hecks/runtime/command_rules/authorization.rb +13 -45
- data/lib/hecks/runtime/command_rules/emission.rb +8 -21
- data/lib/hecks/runtime/command_rules/references.rb +23 -202
- data/lib/hecks/runtime/dependency_planning.rb +30 -102
- data/lib/hecks/runtime/dispatcher.rb +82 -241
- data/lib/hecks/runtime/entity_element.rb +40 -462
- data/lib/hecks/runtime/entity_interpreter.rb +65 -220
- data/lib/hecks/runtime/errors.rb +32 -115
- data/lib/hecks/runtime/event.rb +3 -25
- data/lib/hecks/runtime/identity.rb +18 -154
- data/lib/hecks/runtime/instance.rb +18 -150
- data/lib/hecks/runtime/interpreting.rb +11 -70
- data/lib/hecks/runtime/invocation.rb +28 -164
- data/lib/hecks/runtime/loader.rb +48 -186
- data/lib/hecks/runtime/outbox.rb +38 -261
- data/lib/hecks/runtime/policy_interpreter.rb +38 -200
- data/lib/hecks/runtime/port_operation_interpreter.rb +26 -87
- data/lib/hecks/runtime/query_interpreter.rb +45 -187
- data/lib/hecks/runtime/reaction_invocation.rb +36 -138
- data/lib/hecks/runtime/read_model_interpreter.rb +139 -208
- data/lib/hecks/runtime/rebuild_sweep.rb +8 -54
- data/lib/hecks/runtime/reference_hop.rb +8 -81
- data/lib/hecks/runtime/refusal_wording.rb +8 -89
- data/lib/hecks/runtime/registry/saga_persistence.rb +10 -102
- data/lib/hecks/runtime/registry/verification.rb +52 -225
- data/lib/hecks/runtime/registry/world_defaults.rb +4 -53
- data/lib/hecks/runtime/registry.rb +103 -244
- data/lib/hecks/runtime/remote_dispatcher.rb +37 -152
- data/lib/hecks/runtime/routing.rb +4 -15
- data/lib/hecks/runtime/saga_interpreter/correlation.rb +14 -61
- data/lib/hecks/runtime/saga_interpreter.rb +79 -263
- data/lib/hecks/runtime/saga_pending_dispatch.rb +2 -43
- data/lib/hecks/runtime/tenant_check.rb +6 -68
- data/lib/hecks/runtime/tenant_scope.rb +3 -28
- data/lib/hecks/runtime/value/admission.rb +16 -67
- data/lib/hecks/runtime/value/coercion.rb +155 -641
- data/lib/hecks/runtime/value/entity_list_coercion.rb +26 -219
- data/lib/hecks/runtime/value.rb +12 -84
- data/lib/hecks/runtime.rb +17 -65
- data/lib/hecks/storehouse.rb +146 -567
- data/lib/hecks/tenancy/bluebook/tenancy.bluebook +8 -32
- data/lib/hecks/tenancy/bluebook/tenancy.hecksagon +6 -23
- data/lib/hecks/vendoring/git_environment.rb +2 -8
- data/lib/hecks/vendoring/git_source.rb +4 -10
- data/lib/hecks/vendoring.rb +7 -46
- data/lib/hecks/version.rb +3 -14
- data/lib/hecks/vocabulary.rb +5 -0
- data/lib/hecks.rb +32 -82
- data/lib/rubocop/cop/hecks/fallback_hash_lookup.rb +8 -46
- data/lib/rubocop/cop/hecks/sequential_hash_rename_in_loop.rb +11 -80
- data/lib/rubocop/cop/hecks/thread_shared_ivar_mutation.rb +10 -99
- metadata +30 -59
- data/lib/hecks/bench/cli.rb +0 -74
- data/lib/hecks/bench/environment.rb +0 -100
- data/lib/hecks/bench/postgres_probe.rb +0 -41
- data/lib/hecks/bench/report.rb +0 -116
- data/lib/hecks/bench/ruby_runner.rb +0 -151
- data/lib/hecks/bench/run.rb +0 -55
- data/lib/hecks/bench/rust_runner.rb +0 -165
- data/lib/hecks/bench/stats.rb +0 -75
- data/lib/hecks/bench/suite.rb +0 -172
- data/lib/hecks/bench/workload.rb +0 -137
- data/lib/hecks/bench.rb +0 -28
- data/lib/hecks/codemod.rb +0 -443
- data/lib/hecks/corpus.rb +0 -479
- data/lib/hecks/doc/reference.rb +0 -585
- data/lib/hecks/fuzzing/bounded_exhaustive_expressions.rb +0 -684
- data/lib/hecks/fuzzing/combination_miner.rb +0 -178
- data/lib/hecks/fuzzing/concurrent_dispatch.rb +0 -469
- data/lib/hecks/fuzzing/coverage_campaign.rb +0 -161
- data/lib/hecks/fuzzing/differential.rb +0 -192
- data/lib/hecks/fuzzing/domain_generator.rb +0 -871
- data/lib/hecks/fuzzing/era_boundary.rb +0 -154
- data/lib/hecks/fuzzing/form_census.rb +0 -285
- data/lib/hecks/fuzzing/generated_domain_check.rb +0 -171
- data/lib/hecks/fuzzing/invalid_value_generator.rb +0 -125
- data/lib/hecks/fuzzing/isolated_boot.rb +0 -658
- data/lib/hecks/fuzzing/nondeterministic.rb +0 -79
- data/lib/hecks/fuzzing/persistence_parity.rb +0 -253
- data/lib/hecks/fuzzing/properties/corrections.rb +0 -125
- data/lib/hecks/fuzzing/properties/dispatch_and_mutations.rb +0 -688
- data/lib/hecks/fuzzing/properties/guards.rb +0 -398
- data/lib/hecks/fuzzing/properties/invariants_and_aggregation.rb +0 -399
- data/lib/hecks/fuzzing/properties/lifecycle_and_replay.rb +0 -137
- data/lib/hecks/fuzzing/properties/outbox.rb +0 -180
- data/lib/hecks/fuzzing/properties/querying.rb +0 -260
- data/lib/hecks/fuzzing/properties.rb +0 -267
- data/lib/hecks/fuzzing/qa_settings.rb +0 -164
- data/lib/hecks/fuzzing/replay.rb +0 -930
- data/lib/hecks/fuzzing/rotation_priority.rb +0 -114
- data/lib/hecks/fuzzing/rust_gap_manifest.rb +0 -139
- data/lib/hecks/fuzzing/self_consistency.rb +0 -825
- data/lib/hecks/fuzzing/sequence_generator/adversary.rb +0 -532
- data/lib/hecks/fuzzing/sequence_generator/catalog.rb +0 -171
- data/lib/hecks/fuzzing/sequence_generator/outcome_tracker.rb +0 -127
- data/lib/hecks/fuzzing/sequence_generator/picker.rb +0 -116
- data/lib/hecks/fuzzing/sequence_generator/query_binding.rb +0 -138
- data/lib/hecks/fuzzing/sequence_generator/step_builder.rb +0 -344
- data/lib/hecks/fuzzing/sequence_generator.rb +0 -311
- data/lib/hecks/fuzzing/shrinker.rb +0 -309
- data/lib/hecks/fuzzing/structural_skips.rb +0 -53
- data/lib/hecks/fuzzing/sweep_depth.rb +0 -61
- data/lib/hecks/fuzzing/target_capabilities.rb +0 -255
- data/lib/hecks/fuzzing/value_generator.rb +0 -340
- data/lib/hecks/fuzzing.rb +0 -23
- data/lib/hecks/grammar/evolve.rb +0 -524
- data/lib/hecks/query_ir.rb +0 -482
|
@@ -7,18 +7,14 @@ require_relative "params"
|
|
|
7
7
|
|
|
8
8
|
module Hecks
|
|
9
9
|
module Forms
|
|
10
|
-
#
|
|
11
|
-
#
|
|
12
|
-
# form-bluebook.md). Every command in every loaded, exposed bluebook
|
|
13
|
-
# renders through here — nothing here is per-command code; see that
|
|
14
|
-
# doc for the 1:1 rule this deliberately holds to for now.
|
|
10
|
+
# Renders a command as the page body of its HTML form; no per-command code
|
|
11
|
+
# (see docs/command-form-and-query-form-bluebook.md).
|
|
15
12
|
module CommandFormRenderer
|
|
16
13
|
# Lists every field a command's form shows: the `to` identity picker first (unless the
|
|
17
14
|
# command creates its aggregate), then one field per command attribute.
|
|
18
15
|
#
|
|
19
|
-
# The same
|
|
20
|
-
#
|
|
21
|
-
# renders an input the submit handler doesn't also expect.
|
|
16
|
+
# The same list `Params.extract` casts a POST against, so a page never renders
|
|
17
|
+
# an input the submit handler does not expect.
|
|
22
18
|
#
|
|
23
19
|
# @param aggregate [Bluebook::Aggregate] the aggregate that declares the command
|
|
24
20
|
# @param command [Bluebook::Command] the command the form submits
|
|
@@ -33,25 +29,14 @@ module Hecks
|
|
|
33
29
|
# Renders the page body for one command: header, refusal banner, the form itself, and
|
|
34
30
|
# the inspect panel.
|
|
35
31
|
#
|
|
36
|
-
# `registry`
|
|
37
|
-
#
|
|
38
|
-
# for a non-creating command — see `identity_field` below). `values`/
|
|
39
|
-
# `error` carry a sticky re-render after a refused submission; leave
|
|
40
|
-
# both nil for a fresh form. `prefill` carries values a caller
|
|
41
|
-
# arrived with (typically `?to=...` off a record's own detail page) —
|
|
42
|
-
# kept separate from `values` because a prefill is not an error retry
|
|
43
|
-
# and should not be treated as one by a future reader of this code.
|
|
32
|
+
# `registry` populates `:reference` selects. `values` and `error` re-render after a
|
|
33
|
+
# refusal; `prefill` carries values the caller arrived with (`?to=...`), not a retry.
|
|
44
34
|
#
|
|
45
35
|
# @param registry [Runtime::Registry] the booted registry, read for reference options
|
|
46
|
-
# @param domain [String] name of the domain (chapter) the aggregate belongs to
|
|
47
|
-
# @param aggregate [Bluebook::Aggregate] the aggregate that declares the command
|
|
48
|
-
# @param command [Bluebook::Command] the command the form submits
|
|
49
36
|
# @param action [String] URL path the form posts to
|
|
50
|
-
# @param values [Hash{String => Object}, nil]
|
|
51
|
-
# refusal, keyed by dotted field path; nil falls back to `prefill`
|
|
37
|
+
# @param values [Hash{String => Object}, nil] raw submission to re-show; nil uses `prefill`
|
|
52
38
|
# @param error [Exception, nil] the refusal to show in the banner; nil for a fresh form
|
|
53
|
-
# @param prefill [Hash{String => String}] values the caller arrived with,
|
|
54
|
-
# dotted field path; ignored when `values` is given
|
|
39
|
+
# @param prefill [Hash{String => String}] values the caller arrived with, by dotted path
|
|
55
40
|
# @return [String] the HTML page body, without the surrounding page chrome
|
|
56
41
|
def self.render(registry:, domain:, aggregate:, command:, action:, values: nil, error: nil, prefill: {})
|
|
57
42
|
all_fields = fields_for(aggregate, command)
|
|
@@ -130,12 +115,8 @@ module Hecks
|
|
|
130
115
|
# Maps a refusal to per-field messages; always empty, so every refusal is shown in
|
|
131
116
|
# the banner rather than beside a field.
|
|
132
117
|
#
|
|
133
|
-
#
|
|
134
|
-
#
|
|
135
|
-
# docs/command-form-and-query-form-bluebook.md's note on
|
|
136
|
-
# `RefusalWording`), so this returns empty rather than guessing which
|
|
137
|
-
# field a message meant; the banner above carries the real text
|
|
138
|
-
# instead of a misattributed hint.
|
|
118
|
+
# A domain refusal carries no field attribution, so the banner shows the message
|
|
119
|
+
# instead of guessing a field.
|
|
139
120
|
#
|
|
140
121
|
# @param _error [Exception, nil] the refusal raised by the submission; ignored
|
|
141
122
|
# @return [Hash] always empty; keys would be dotted field paths
|
|
@@ -4,31 +4,13 @@ require_relative "../naming"
|
|
|
4
4
|
|
|
5
5
|
module Hecks
|
|
6
6
|
module Forms
|
|
7
|
-
#
|
|
8
|
-
#
|
|
9
|
-
# recursively for a group's children, shared by CommandFormRenderer
|
|
10
|
-
# (POST) and QueryFormRenderer (GET) — the same attribute shape asks
|
|
11
|
-
# for the same input either way; only the surrounding `<form>`'s
|
|
12
|
-
# method differs.
|
|
7
|
+
# Renders a Field (field_shape.rb) as form markup, recursing into a group's children.
|
|
8
|
+
# Shared by CommandFormRenderer (POST) and QueryFormRenderer (GET).
|
|
13
9
|
module FieldRenderer
|
|
14
|
-
# Renders one field,
|
|
15
|
-
# value filled back in.
|
|
10
|
+
# Renders one field, filling any held value back in.
|
|
16
11
|
#
|
|
17
|
-
# `
|
|
18
|
-
#
|
|
19
|
-
# Field already carries, via `dig`. `reference_options` maps a
|
|
20
|
-
# `:reference` field's own path to `[[id, label], ...]`, built by the
|
|
21
|
-
# caller (it needs a repository; this module stays pure markup).
|
|
22
|
-
#
|
|
23
|
-
# @param field [Forms::Field] the field to render
|
|
24
|
-
# @param values [Hash{String, Symbol => Object}] held values, either flat and keyed by
|
|
25
|
-
# dotted path or nested by path segment; see `dig`
|
|
26
|
-
# @param errors [Hash{String => String}, nil] message per dotted field path; nil for none
|
|
27
|
-
# @param reference_options [Hash{String => Array<Array>, nil}] `[id, label]` pairs per
|
|
28
|
-
# `:reference` field path, as `ReferenceOptions.collect` builds them; a nil or empty
|
|
29
|
-
# entry renders a plain text input
|
|
30
|
-
# @return [String] HTML for the field: a `<fieldset>` for `:group` and `:money`, a
|
|
31
|
-
# `<div class="field">` otherwise
|
|
12
|
+
# `reference_options` is built by the caller, since it needs a repository and
|
|
13
|
+
# this module stays pure markup.
|
|
32
14
|
def self.render(field, values: {}, errors: nil, reference_options: {})
|
|
33
15
|
case field.kind
|
|
34
16
|
when :group then group(field, values, errors, reference_options, tag: "fieldset")
|
|
@@ -38,17 +20,6 @@ module Hecks
|
|
|
38
20
|
end
|
|
39
21
|
end
|
|
40
22
|
|
|
41
|
-
# Renders a field's children inside one enclosing element, with the field's label as
|
|
42
|
-
# its `<legend>`.
|
|
43
|
-
#
|
|
44
|
-
# @param field [Forms::Field] a `:group` or `:money` field carrying `children`
|
|
45
|
-
# @param values [Hash{String, Symbol => Object}] held values; see `dig`
|
|
46
|
-
# @param errors [Hash{String => String}, nil] message per dotted field path
|
|
47
|
-
# @param reference_options [Hash{String => Array<Array>, nil}] `[id, label]` pairs per
|
|
48
|
-
# `:reference` field path
|
|
49
|
-
# @param tag [String] name of the enclosing element, such as `"fieldset"`
|
|
50
|
-
# @param css [String, nil] class attribute for the enclosing element; nil for none
|
|
51
|
-
# @return [String] HTML for the enclosing element and every child
|
|
52
23
|
def self.group(field, values, errors, reference_options, tag:, css: nil)
|
|
53
24
|
inner = field.children.map { |child| render(child, values: values, errors: errors, reference_options: reference_options) }
|
|
54
25
|
<<~HTML
|
|
@@ -59,14 +30,7 @@ module Hecks
|
|
|
59
30
|
HTML
|
|
60
31
|
end
|
|
61
32
|
|
|
62
|
-
#
|
|
63
|
-
# `Params.extract_list` reads back.
|
|
64
|
-
#
|
|
65
|
-
# @param field [Forms::Field] a `:list` field whose first child describes one element
|
|
66
|
-
# @param values [Hash{String, Symbol => Object}] held values; the list's entry may be an
|
|
67
|
-
# Array, a newline-joined String, or absent
|
|
68
|
-
# @param _errors [Hash{String => String}, nil] ignored; a list shows no per-field message
|
|
69
|
-
# @return [String] HTML for the labelled textarea and its help line
|
|
33
|
+
# One textarea, an element per line: the shape `Params.extract_list` reads back.
|
|
70
34
|
def self.list(field, values, _errors)
|
|
71
35
|
item = field.children.first
|
|
72
36
|
current = Array(dig(values, field.path)).join("\n")
|
|
@@ -80,15 +44,6 @@ module Hecks
|
|
|
80
44
|
HTML
|
|
81
45
|
end
|
|
82
46
|
|
|
83
|
-
# Renders a single-value field with the control its `kind` calls for, wrapped with its
|
|
84
|
-
# label, help text and error.
|
|
85
|
-
#
|
|
86
|
-
# @param field [Forms::Field] a leaf field
|
|
87
|
-
# @param values [Hash{String, Symbol => Object}] held values; see `dig`
|
|
88
|
-
# @param errors [Hash{String => String}, nil] message per dotted field path
|
|
89
|
-
# @param reference_options [Hash{String => Array<Array>, nil}] `[id, label]` pairs per
|
|
90
|
-
# `:reference` field path
|
|
91
|
-
# @return [String] HTML for the `<div class="field">` block
|
|
92
47
|
def self.leaf(field, values, errors, reference_options)
|
|
93
48
|
value = dig(values, field.path)
|
|
94
49
|
error = errors && errors[field.path]
|
|
@@ -103,14 +58,7 @@ module Hecks
|
|
|
103
58
|
wrap(field, body, error)
|
|
104
59
|
end
|
|
105
60
|
|
|
106
|
-
#
|
|
107
|
-
# gets no label here because `checkbox` renders its own beside the box.
|
|
108
|
-
#
|
|
109
|
-
# @param field [Forms::Field] the field the control belongs to
|
|
110
|
-
# @param body [String] HTML of the control itself
|
|
111
|
-
# @param error [String, nil] message shown as an alert; nil for none
|
|
112
|
-
# @return [String] HTML for the `<div class="field">` block, classed `has-error` when
|
|
113
|
-
# `error` is given
|
|
61
|
+
# A :boolean gets no label here because `checkbox` renders its own beside the box.
|
|
114
62
|
def self.wrap(field, body, error)
|
|
115
63
|
<<~HTML
|
|
116
64
|
<div class="field#{' has-error' if error}">
|
|
@@ -122,13 +70,6 @@ module Hecks
|
|
|
122
70
|
HTML
|
|
123
71
|
end
|
|
124
72
|
|
|
125
|
-
# Renders an `<input>` of the field's `html_type`, falling back to the field's default
|
|
126
|
-
# for a missing value; a whole-cents number also gets a live preview span.
|
|
127
|
-
#
|
|
128
|
-
# @param field [Forms::Field] a leaf field
|
|
129
|
-
# @param value [Object, nil] the held value, rendered with `to_s`; nil shows the default
|
|
130
|
-
# @return [String] HTML for the input, followed by the preview `<span>` when the field
|
|
131
|
-
# is a `:number` whose help text mentions cents
|
|
132
73
|
def self.input(field, value)
|
|
133
74
|
money = field.kind == :number && field.help.to_s.include?("cents")
|
|
134
75
|
tag = Tag.void("input", id: dom_id(field.path), name: field.path, type: field.html_type,
|
|
@@ -140,23 +81,11 @@ module Hecks
|
|
|
140
81
|
%(#{tag} <span id="#{dom_id(field.path)}-preview" class="mono help" aria-live="polite"></span>)
|
|
141
82
|
end
|
|
142
83
|
|
|
143
|
-
# Renders a `<textarea>` holding the value as escaped text; unlike `input`, the field's
|
|
144
|
-
# default is not filled in.
|
|
145
|
-
#
|
|
146
|
-
# @param field [Forms::Field] a `:textarea` field
|
|
147
|
-
# @param value [Object, nil] the held value, rendered with `to_s`; nil renders empty
|
|
148
|
-
# @return [String] HTML for the textarea
|
|
149
84
|
def self.textarea(field, value)
|
|
150
85
|
%(<textarea id="#{dom_id(field.path)}" name="#{Escape.attr(field.path)}" #{aria(field)}>#{Escape.html(value)}</textarea>)
|
|
151
86
|
end
|
|
152
87
|
|
|
153
|
-
#
|
|
154
|
-
# box still submits a value, with the field's label beside it.
|
|
155
|
-
#
|
|
156
|
-
# @param field [Forms::Field] a `:boolean` field
|
|
157
|
-
# @param value [Boolean, String, nil] the held value; `true`, `"true"`, `"on"` and `"1"`
|
|
158
|
-
# tick the box, and nil falls back to a default of exactly `true`
|
|
159
|
-
# @return [String] HTML for the checkbox row
|
|
88
|
+
# The hidden "0" input makes an unticked box still submit a value.
|
|
160
89
|
def self.checkbox(field, value)
|
|
161
90
|
checked = value.nil? ? field.default == true : [true, "true", "on", "1"].include?(value)
|
|
162
91
|
<<~HTML
|
|
@@ -168,13 +97,6 @@ module Hecks
|
|
|
168
97
|
HTML
|
|
169
98
|
end
|
|
170
99
|
|
|
171
|
-
# Renders one radio button per option, pre-checking the one equal to the held value or,
|
|
172
|
-
# failing that, to the field's default.
|
|
173
|
-
#
|
|
174
|
-
# @param field [Forms::Field] a `:radio` field whose `options` are `[value, label]` pairs
|
|
175
|
-
# @param value [Object, nil] the held value, compared with `to_s`; nil falls back to the
|
|
176
|
-
# default
|
|
177
|
-
# @return [String] HTML for the `<div role="radiogroup">` block
|
|
178
100
|
def self.radio_group(field, value)
|
|
179
101
|
selected = value || field.default
|
|
180
102
|
options = field.options.map do |option_value, option_label|
|
|
@@ -187,13 +109,6 @@ module Hecks
|
|
|
187
109
|
%(<div class="radio-group" role="radiogroup">#{options.join}</div>)
|
|
188
110
|
end
|
|
189
111
|
|
|
190
|
-
# Renders a `<select>` over the field's fixed options, with a blank "—" entry first when
|
|
191
|
-
# the field is optional.
|
|
192
|
-
#
|
|
193
|
-
# @param field [Forms::Field] a `:select` field whose `options` are `[value, label]` pairs
|
|
194
|
-
# @param value [Object, nil] the held value, compared with `to_s`; nil falls back to the
|
|
195
|
-
# default
|
|
196
|
-
# @return [String] HTML for the select
|
|
197
112
|
def self.select(field, value)
|
|
198
113
|
selected = value || field.default
|
|
199
114
|
options = field.options.map do |option_value, option_label|
|
|
@@ -204,16 +119,7 @@ module Hecks
|
|
|
204
119
|
%(<select id="#{dom_id(field.path)}" name="#{Escape.attr(field.path)}" #{aria(field)}>#{blank}#{options.join}</select>)
|
|
205
120
|
end
|
|
206
121
|
|
|
207
|
-
#
|
|
208
|
-
# text id input when no records are on offer.
|
|
209
|
-
#
|
|
210
|
-
# @param field [Forms::Field] a `:reference` field; its `html_type` is set to `"text"`
|
|
211
|
-
# in place when the text fallback is taken
|
|
212
|
-
# @param value [Object, nil] the held id, compared with `to_s`; nil preselects the
|
|
213
|
-
# disabled "choose one…" entry of a required field
|
|
214
|
-
# @param options [Array<Array>, nil] `[id, label]` pairs to offer; nil or empty takes the
|
|
215
|
-
# text fallback
|
|
216
|
-
# @return [String] HTML for the select, or for the fallback `<input>`
|
|
122
|
+
# Falls back to a plain text id input when no records are on offer.
|
|
217
123
|
def self.reference_select(field, value, options)
|
|
218
124
|
return input(field.tap { |f| f.html_type = "text" }, value) unless options && !options.empty?
|
|
219
125
|
|
|
@@ -228,78 +134,33 @@ module Hecks
|
|
|
228
134
|
%(<select id="#{dom_id(field.path)}" name="#{Escape.attr(field.path)}" #{aria(field)}>#{blank}#{rendered.join}</select>)
|
|
229
135
|
end
|
|
230
136
|
|
|
231
|
-
# Renders the asterisk that marks a required field's label or legend.
|
|
232
|
-
#
|
|
233
|
-
# @param field [Forms::Field] the field being labelled
|
|
234
|
-
# @return [String] HTML for the mark, or `""` when the field is optional
|
|
235
137
|
def self.required_mark(field) = field.required? ? %(<span class="required-mark" title="required">*</span>) : ""
|
|
236
138
|
|
|
237
|
-
#
|
|
238
|
-
# `"f-amount-cents"` for `"amount.cents"`.
|
|
239
|
-
#
|
|
240
|
-
# @param path [String, Symbol] the field's dotted path
|
|
241
|
-
# @return [String] the id, `"f-"` followed by the path with dots turned to hyphens
|
|
139
|
+
# "amount.cents" -> "f-amount-cents".
|
|
242
140
|
def self.dom_id(path) = "f-#{path.to_s.tr('.', '-')}"
|
|
243
141
|
|
|
244
|
-
#
|
|
245
|
-
# field, whose input takes a record id rather than the attribute's own value.
|
|
246
|
-
#
|
|
247
|
-
# @param field [Forms::Field] a leaf field
|
|
248
|
-
# @return [String, nil] the regex source the attribute declares as `pattern:`; nil for a
|
|
249
|
-
# `:reference` field or when none is declared
|
|
142
|
+
# A :reference input takes a record id, so the attribute's own pattern must not apply.
|
|
250
143
|
def self.leaf_pattern(field) = field.kind == :reference ? nil : field.pattern
|
|
251
144
|
|
|
252
|
-
# Names the preview span a whole-cents input's `data-money-cents` attribute points at.
|
|
253
|
-
#
|
|
254
|
-
# @param field [Forms::Field] the cents field
|
|
255
|
-
# @return [String] a CSS id selector, such as `"#f-amount-cents-preview"`
|
|
256
145
|
def self.money_preview_target(field) = "##{dom_id(field.path)}-preview"
|
|
257
146
|
|
|
258
|
-
#
|
|
259
|
-
# attribute string, for the controls assembled by hand rather than through `Tag.void`.
|
|
260
|
-
#
|
|
261
|
-
# @param field [Forms::Field] the field the control belongs to
|
|
262
|
-
# @return [String] the rendered attributes, or `""` when the field is optional and has
|
|
263
|
-
# no help text
|
|
147
|
+
# String form, for controls assembled by hand rather than through `Tag.void`.
|
|
264
148
|
def self.aria(field)
|
|
265
149
|
Tag.attrs(required: field.required?, aria_describedby: field.help ? "#{dom_id(field.path)}-help" : nil)
|
|
266
150
|
end
|
|
267
151
|
|
|
268
|
-
#
|
|
269
|
-
# splat into `Tag.void`.
|
|
270
|
-
#
|
|
271
|
-
# @param field [Forms::Field] the field the control belongs to
|
|
272
|
-
# @return [Hash{Symbol => Boolean, String, nil}] `:required` and `:aria_describedby`;
|
|
273
|
-
# the latter is the help span's element id, or nil when the field has no help text
|
|
152
|
+
# Hash form of `aria`, to splat into `Tag.void`.
|
|
274
153
|
def self.aria_attrs(field)
|
|
275
154
|
{ required: field.required?, aria_describedby: field.help ? "#{dom_id(field.path)}-help" : nil }
|
|
276
155
|
end
|
|
277
156
|
|
|
278
|
-
# Reads the value held for a dotted
|
|
279
|
-
# arrive in, flat or nested, without losing a stored `false`.
|
|
280
|
-
#
|
|
281
|
-
# `values` is a nested hash; `path` a dotted string using the same
|
|
282
|
-
# segment spelling the hash keys are built from (`Params.nest` in
|
|
283
|
-
# params.rb) — symbols one level down from a group, strings at the
|
|
284
|
-
# flat top when a sticky POST re-render hands raw params back untouched.
|
|
285
|
-
#
|
|
286
|
-
# @param values [Hash{String, Symbol => Object}, Object] held values; anything that is
|
|
287
|
-
# not a Hash, nil included, reads as nil
|
|
288
|
-
# @param path [String, Symbol] the field's dotted path, such as `"amount.cents"`
|
|
289
|
-
# @return [Object, nil] the held value exactly as stored (a raw form String, or a typed
|
|
290
|
-
# value from a record's state); nil when no key on the path answers
|
|
157
|
+
# Reads the value held for a dotted path from either a flat or a nested values hash.
|
|
291
158
|
def self.dig(values, path)
|
|
292
159
|
return nil unless values.is_a?(Hash)
|
|
293
160
|
|
|
294
|
-
# A sticky re-render
|
|
295
|
-
#
|
|
296
|
-
#
|
|
297
|
-
# an existing record's own state hands back a nested hash instead
|
|
298
|
-
# (`{amount: {cents: 1050}}`). Flat wins when both would answer,
|
|
299
|
-
# since only the raw form is ever what the caller actually typed.
|
|
300
|
-
# `key?` decides which spelling answers, at every step below —
|
|
301
|
-
# never `||`, which would treat a genuinely-held `false` the
|
|
302
|
-
# same as an absent key and fall through to `nil`.
|
|
161
|
+
# A sticky re-render hands back raw flat params ({"amount.cents"=>"1050"}); a prefill
|
|
162
|
+
# from a record's state is nested ({amount: {cents: 1050}}). Flat wins when both answer.
|
|
163
|
+
# Test with `key?`, never `||`, so a held `false` is not mistaken for an absent key.
|
|
303
164
|
str = path.to_s
|
|
304
165
|
return values[str] if values.key?(str)
|
|
305
166
|
|