hecks 3.14.0 → 5.0.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/examples/pizzas/adapters/fake_processor.rb +34 -0
- data/examples/pizzas/adapters/payment_signature.rb +66 -0
- data/examples/pizzas/adapters/payment_webhook.rb +87 -0
- data/examples/pizzas/bluebook/pizzas.behaviors +33 -0
- data/examples/pizzas/bluebook/pizzas.hecksagon +5 -3
- data/examples/pizzas/config.ru +22 -0
- data/exe/hecks +1 -1
- data/lib/hecks/adapters/driven/prism.rb +0 -2
- data/lib/hecks/adapters/driven.rb +0 -2
- data/lib/hecks/adapters/driving/json.rb +9 -16
- data/lib/hecks/bluebook/dsl/bootstrap_table.rb +2 -2
- data/lib/hecks/bluebook/dsl/derivation_words.rb +58 -0
- data/lib/hecks/bluebook/dsl/translation_builder.rb +6 -37
- data/lib/hecks/bluebook/expression/ast_json.rb +0 -9
- data/lib/hecks/bluebook/hecksagon.rb +1 -1
- data/lib/hecks/bluebook/meta_validator/translation_judge/rules.rb +7 -10
- data/lib/hecks/bluebook/meta_validator/translation_judge.rb +4 -8
- data/lib/hecks/bluebook/meta_validator.rb +0 -11
- data/lib/hecks/bluebook/translation.rb +18 -10
- data/lib/hecks/bluebook/translation_expression/evaluator.rb +63 -0
- data/lib/hecks/bluebook/translation_expression/parser.rb +127 -0
- data/lib/hecks/bluebook/translation_expression.rb +39 -0
- data/lib/hecks/bluebook/translation_plan.rb +70 -0
- data/lib/hecks/bluebook.rb +2 -0
- data/lib/hecks/chapters.rb +3 -3
- data/lib/hecks/cli/project_cli/launcher_source.rb +1 -1
- data/lib/hecks/composer/adapters/claude_composer.adapter +3 -0
- data/lib/hecks/composer/adapters/claude_composer.rb +83 -0
- data/lib/hecks/composer/adapters/fake_agent.adapter +3 -0
- data/lib/hecks/composer/adapters/fake_agent.rb +55 -0
- data/lib/hecks/composer/adapters/jev.adapter +3 -0
- data/lib/hecks/composer/adapters/jev.rb +66 -0
- data/lib/hecks/composer/agent.rb +113 -0
- data/lib/hecks/composer/assistant.rb +110 -0
- data/lib/hecks/composer/behavior_run.rb +53 -0
- data/lib/hecks/composer/bluebook/composer.bluebook +178 -0
- data/lib/hecks/composer/bluebook/composer.hecksagon +16 -0
- data/lib/hecks/composer/board.rb +65 -0
- data/lib/hecks/composer/board_edit/command_text.rb +39 -0
- data/lib/hecks/composer/board_edit/source.rb +84 -0
- data/lib/hecks/composer/board_edit.rb +144 -0
- data/lib/hecks/composer/check.rb +89 -0
- data/lib/hecks/composer/domains.rb +81 -0
- data/lib/hecks/composer/jobs.rb +134 -0
- data/lib/hecks/composer/layout.rb +37 -0
- data/lib/hecks/composer/live.rb +150 -0
- data/lib/hecks/composer/outline.rb +48 -0
- data/lib/hecks/composer/page.html +989 -0
- data/lib/hecks/composer/panels.rb +142 -0
- data/lib/hecks/composer/parse.rb +83 -0
- data/lib/hecks/composer/plain.rb +28 -0
- data/lib/hecks/composer/ports/composer_agent.port +7 -0
- data/lib/hecks/composer/session.rb +141 -0
- data/lib/hecks/composer/toolbox.rb +166 -0
- data/lib/hecks/composer/web.rb +156 -0
- data/lib/hecks/composer/workbench.rb +51 -0
- data/lib/hecks/composer/workspace.rb +81 -0
- data/lib/hecks/composer.rb +17 -0
- data/lib/hecks/corpus/adapters.rb +22 -0
- data/lib/hecks/corpus/rust.rb +1 -1
- data/lib/hecks/corpus/worlds.rb +19 -0
- data/lib/hecks/corpus.rb +5 -0
- data/lib/hecks/forms/app/commands.rb +2 -3
- data/lib/hecks/forms/app/queries.rb +2 -3
- data/lib/hecks/forms/app/records.rb +17 -5
- data/lib/hecks/forms/app/responses.rb +3 -1
- data/lib/hecks/forms/command_form_renderer.rb +42 -16
- data/lib/hecks/forms/field_controls.rb +2 -2
- data/lib/hecks/forms/field_renderer.rb +1 -1
- data/lib/hecks/forms/field_shape.rb +36 -17
- data/lib/hecks/forms/index_renderer.rb +2 -1
- data/lib/hecks/forms/page.rb +1 -1
- data/lib/hecks/forms/params.rb +0 -13
- data/lib/hecks/forms/query_form_renderer.rb +7 -6
- data/lib/hecks/forms/record_renderer.rb +11 -7
- data/lib/hecks/forms/rule_words.rb +100 -0
- data/lib/hecks/forms/value_object_shape.rb +2 -1
- data/lib/hecks/fuzzing/bounded_exhaustive_expressions.rb +0 -3
- data/lib/hecks/fuzzing/isolated_boot/worlds.rb +3 -6
- data/lib/hecks/fuzzing/replay/filters.rb +2 -6
- data/lib/hecks/gate/stages.yml +25 -0
- data/lib/hecks/grammar/evolve/seeds.rb +0 -6
- data/lib/hecks/grammar/evolve.rb +0 -3
- data/lib/hecks/grammar/translation.bluebook +1 -1
- data/lib/hecks/hecks/adapters/codebase/composing.rb +56 -0
- data/lib/hecks/hecks/adapters/codebase/source_tree.rb +3 -1
- data/lib/hecks/hecks/adapters/first_admin.rb +3 -3
- data/lib/hecks/hecks/adapters/journal_store/changes.rb +0 -26
- data/lib/hecks/hecks/adapters/journal_store/examination.rb +2 -23
- data/lib/hecks/hecks/adapters/journal_store/readings.rb +3 -11
- data/lib/hecks/hecks/adapters/journal_store.rb +0 -11
- data/lib/hecks/hecks/adapters/rehearsal/inquiry.rb +4 -11
- data/lib/hecks/hecks/adapters/rehearsal/memory_store.rb +0 -9
- data/lib/hecks/hecks/adapters/rehearsal/postgres_reading.rb +0 -4
- data/lib/hecks/hecks/codebase.behaviors +6 -0
- data/lib/hecks/hecks/codebase.bluebook +21 -0
- data/lib/hecks/hecks/composer.behaviors +68 -0
- data/lib/hecks/hecks/context_map.hecksagon +1 -1
- data/lib/hecks/hecks/custodian.behaviors +0 -6
- data/lib/hecks/hecks/custodian.bluebook +3 -80
- data/lib/hecks/hecks/hecks.hecksagon +2 -2
- data/lib/hecks/hecks/hecks.world +1 -1
- data/lib/hecks/hecks/rehearsal.bluebook +7 -13
- data/lib/hecks/kernel_capabilities/templates.rb +4 -4
- data/lib/hecks/kernel_capabilities.rb +1 -1
- data/lib/hecks/language/bluebook/vocabulary.bluebook +2 -3
- data/lib/hecks/language/translation/translation_aggregate.bluebook +21 -24
- data/lib/hecks/ports/access_control.rb +2 -2
- data/lib/hecks/ports/persistence/plugins/era/era_check.rb +3 -41
- data/lib/hecks/ports/persistence/plugins/era/lineage/coverage.rb +7 -7
- data/lib/hecks/ports/persistence/plugins/era/lineage/rewrite.rb +25 -2
- data/lib/hecks/ports/persistence/plugins/era/lineage/rules.rb +4 -4
- data/lib/hecks/ports/persistence/plugins/era/lineage.rb +17 -25
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/base_sql.rb +0 -12
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/domain_rename.rb +1 -1
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/era_store.rb +2 -22
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/provisioning.rb +0 -1
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage.rb +9 -3
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/minter.rb +3 -29
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/refusals.rb +2 -26
- data/lib/hecks/ports/persistence/plugins/era/translation/audit/layer_two.rb +6 -33
- data/lib/hecks/ports/persistence/plugins/era/translation/audit/unfed_report.rb +3 -3
- data/lib/hecks/ports/persistence/plugins/era/translation/audit.rb +2 -4
- data/lib/hecks/ports/persistence/plugins/era/translation/expression_sql.rb +52 -0
- data/lib/hecks/ports/persistence/plugins/era/translation/rule_compiler.rb +23 -29
- data/lib/hecks/ports/persistence/plugins/era/translation/scaffold.rb +1 -1
- data/lib/hecks/ports/persistence/plugins/era/translation.rb +0 -1
- data/lib/hecks/ports/persistence/plugins/era.rb +3 -6
- data/lib/hecks/ports.rb +0 -1
- data/lib/hecks/projection_files.rb +3 -1
- data/lib/hecks/projections/deploy/templates/lambda/nat_comment_oauth.tmpl +1 -1
- data/lib/hecks/projections/glossary/entries.rb +10 -4
- data/lib/hecks/projections/glossary/groups.rb +42 -0
- data/lib/hecks/projections/glossary/html/page.rb +7 -2
- data/lib/hecks/projections/glossary/html/parser.rb +1 -1
- data/lib/hecks/projections/glossary/html/sections.rb +31 -11
- data/lib/hecks/projections/glossary/html.rb +1 -2
- data/lib/hecks/projections/glossary/markdown.rb +31 -28
- data/lib/hecks/projections/glossary/mermaid.rb +3 -0
- data/lib/hecks/projections/glossary/page.css +143 -153
- data/lib/hecks/projections/glossary/page.js +63 -3
- data/lib/hecks/projections/glossary/sentences/actions.rb +88 -0
- data/lib/hecks/projections/glossary/sentences/paths.rb +77 -0
- data/lib/hecks/projections/glossary/sentences/queries.rb +90 -0
- data/lib/hecks/projections/glossary/sentences/value_objects.rb +32 -5
- data/lib/hecks/projections/glossary/sentences.rb +13 -3
- data/lib/hecks/projections/glossary/slugs.rb +4 -1
- data/lib/hecks/projections/glossary.rb +2 -1
- data/lib/hecks/projections/plain_english.rb +97 -0
- data/lib/hecks/projections/rust_vocabulary/arguments.rb +2 -2
- data/lib/hecks/projections/rust_vocabulary/enum_body.rb +20 -25
- data/lib/hecks/projections/rust_vocabulary/tests.rb +2 -2
- data/lib/hecks/projections/rust_vocabulary.rb +14 -6
- data/lib/hecks/projections/site/cms_editor/color.rb +0 -6
- data/lib/hecks/projections/site/cms_editor/templates/src/host.ts.tmpl +7 -2
- data/lib/hecks/projections/statements/actions.rb +99 -0
- data/lib/hecks/projections/statements/relationships.rb +86 -0
- data/lib/hecks/projections/statements.rb +15 -24
- data/lib/hecks/projector/exporter/adapters.rb +112 -0
- data/lib/hecks/projector/exporter/translations.rb +18 -35
- data/lib/hecks/projector/exporter/worlds.rb +103 -0
- data/lib/hecks/projector/exporter.rb +5 -1
- data/lib/hecks/quality_control/adapters/agent.rb +6 -7
- data/lib/hecks/quality_control/adapters/agent_profile.rb +16 -114
- data/lib/hecks/quality_control/cli/qa_mine_combinations.rb +1 -1
- data/lib/hecks/runtime/loader/boot_steps.rb +0 -20
- data/lib/hecks/runtime/outbox.rb +2 -9
- data/lib/hecks/runtime/port_operation_interpreter.rb +1 -9
- data/lib/hecks/runtime/remote_dispatcher.rb +2 -2
- data/lib/hecks/runtime/value/unwrapping.rb +60 -0
- data/lib/hecks/runtime/value.rb +10 -21
- data/lib/hecks/rust_build/project_rust/target_ir.rb +23 -4
- data/lib/hecks/rust_build/wasm.rb +0 -12
- data/lib/hecks/rust_build/write_if_changed.rb +12 -12
- data/lib/hecks/rust_format.rb +77 -0
- data/lib/hecks/tools/fuzz_sweep/findings.rb +3 -9
- data/lib/hecks/tools/fuzz_sweep.rb +1 -3
- data/lib/hecks/tools/translation_audit/verdicts.rb +3 -28
- data/lib/hecks/tools/translation_audit.rb +8 -10
- data/lib/hecks/tools/translation_scaffold/reporting.rb +1 -1
- data/lib/hecks/version.rb +1 -1
- data/lib/hecks/vocabulary.rb +2 -1
- data/lib/hecks.rb +3 -0
- data/prebuilt/{1a6f596be124228be93eba1d86dbc9d2933190fa389b284331241cb9f27115a0.marshal → ad68f9e06c8068c2a4176b57abf3083d591d5d8980c2b3e897b97331f965b643.marshal} +0 -0
- data/prebuilt/{a883a7e568667aa5ac904c82daff356bdf9e996252a36af6def4a4a43efb967e.marshal → ee22ec8642c4006717ba2b80f46e5efb81de459eef9dfec043e838c0ad4fd720.marshal} +0 -0
- data/prebuilt/{verdicts-872993b1aa26d73fe48f28251374b8585fed145d02aab42be0f00de386b6ff80.json → verdicts-b69f5dcbba79c20daa0493476fa7c317004a30aa2bc3d3dc6a722ea70ae2b43b.json} +1 -1
- data/rust/Cargo.toml +40 -0
- data/rust/build/Cargo.toml +36 -0
- data/rust/build/clippy.toml +4 -0
- data/rust/build/src/adapters_pass.rs +196 -0
- data/rust/build/src/binding_pass.rs +54 -13
- data/rust/build/src/build_artifact.rs +23 -5
- data/rust/build/src/cargo_sync.rs +69 -26
- data/rust/build/src/lineage_pass.rs +101 -87
- data/rust/build/src/main.rs +11 -2
- data/rust/build/src/pipeline.rs +80 -19
- data/rust/build/src/reserved_names.rs +6 -50
- data/rust/build/src/resolve.rs +82 -35
- data/rust/build/src/rustfmt.rs +100 -0
- data/rust/build/src/seams_pass.rs +85 -16
- data/rust/build/src/subprocess.rs +30 -6
- data/rust/build/src/tmp.rs +5 -2
- data/rust/build/src/translation_pass.rs +72 -22
- data/rust/build/src/world_pass.rs +109 -0
- data/rust/clippy.toml +4 -0
- data/rust/codegen/Cargo.toml +36 -0
- data/rust/codegen/clippy.toml +4 -0
- data/rust/codegen/src/asks.rs +40 -14
- data/rust/codegen/src/attr.rs +2 -2
- data/rust/codegen/src/bridging.rs +676 -117
- data/rust/codegen/src/commands.rs +979 -373
- data/rust/codegen/src/constraints.rs +88 -25
- data/rust/codegen/src/dependency_planning.rs +128 -34
- data/rust/codegen/src/domain_generator.rs +306 -170
- data/rust/codegen/src/exemplar.rs +87 -32
- data/rust/codegen/src/expr_emitter.rs +54 -6
- data/rust/codegen/src/fielded.rs +193 -41
- data/rust/codegen/src/hecks_naming.rs +124 -16
- data/rust/codegen/src/hecks_naming_tests.rs +81 -0
- data/rust/codegen/src/json.rs +80 -44
- data/rust/codegen/src/json_codec.rs +585 -149
- data/rust/codegen/src/literal.rs +104 -138
- data/rust/codegen/src/main.rs +151 -52
- data/rust/codegen/src/manifest.rs +76 -14
- data/rust/codegen/src/mutations.rs +1212 -239
- data/rust/codegen/src/naming.rs +111 -60
- data/rust/codegen/src/optional_pass.rs +90 -28
- data/rust/codegen/src/ports.rs +5 -4
- data/rust/codegen/src/prelude.rs +139 -49
- data/rust/codegen/src/presenters.rs +335 -0
- data/rust/codegen/src/queries.rs +601 -226
- data/rust/codegen/src/reactions.rs +268 -74
- data/rust/codegen/src/read_models.rs +574 -229
- data/rust/codegen/src/reference_specs.rs +16 -3
- data/rust/codegen/src/registry.rs +128 -79
- data/rust/codegen/src/reserved_names.rs +6 -50
- data/rust/codegen/src/shared.rs +71 -22
- data/rust/codegen/src/sidecars.rs +15 -5
- data/rust/codegen/src/skip_reason.rs +8 -2
- data/rust/codegen/src/types.rs +306 -108
- data/rust/host/Cargo.lock +1 -0
- data/rust/host/Cargo.toml +40 -4
- data/rust/host/HECKS_RELEASE +1 -1
- data/rust/host/clippy.toml +4 -0
- data/rust/host/src/api.rs +698 -218
- data/rust/host/src/auth.rs +491 -214
- data/rust/host/src/b64.rs +91 -0
- data/rust/host/src/bin/expr_harness.rs +6 -2
- data/rust/host/src/bin/lineage_harness.rs +47 -11
- data/rust/host/src/bin/mint_harness.rs +70 -37
- data/rust/host/src/bin/validate_harness.rs +16 -8
- data/rust/host/src/boot.rs +144 -68
- data/rust/host/src/boundary_fuzz/api.rs +130 -32
- data/rust/host/src/boundary_fuzz/auth.rs +108 -23
- data/rust/host/src/boundary_fuzz/expr_json.rs +85 -11
- data/rust/host/src/boundary_fuzz/ir.rs +164 -12
- data/rust/host/src/boundary_fuzz/server.rs +283 -36
- data/rust/host/src/boundary_fuzz/web.rs +56 -8
- data/rust/host/src/checkout.rs +78 -32
- data/rust/host/src/clock.rs +8 -0
- data/rust/host/src/commerce_ir.rs +333 -95
- data/rust/host/src/crypto.rs +33 -0
- data/rust/host/src/dispatch.rs +1037 -331
- data/rust/host/src/expr_json.rs +1021 -273
- data/rust/host/src/extension.rs +24 -4
- data/rust/host/src/field_hints.rs +11 -7
- data/rust/host/src/fuzz_support.rs +85 -13
- data/rust/host/src/host.rs +100 -0
- data/rust/host/src/http.rs +22 -0
- data/rust/host/src/ir.rs +326 -16
- data/rust/host/src/journal.rs +277 -176
- data/rust/host/src/lambda_client.rs +219 -53
- data/rust/host/src/lib.rs +16 -4
- data/rust/host/src/log.rs +62 -11
- data/rust/host/src/mint.rs +1153 -326
- data/rust/host/src/needs.rs +185 -44
- data/rust/host/src/payments/keystore.rs +197 -45
- data/rust/host/src/payments/roles.rs +39 -7
- data/rust/host/src/payments/tests.rs +1427 -282
- data/rust/host/src/payments.rs +391 -112
- data/rust/host/src/platform_signin/attack_tests.rs +5 -5
- data/rust/host/src/platform_signin/config.rs +11 -11
- data/rust/host/src/platform_signin/cookie.rs +2 -2
- data/rust/host/src/platform_signin/extension.rs +2 -1
- data/rust/host/src/platform_signin/handler.rs +9 -8
- data/rust/host/src/platform_signin/jti.rs +4 -2
- data/rust/host/src/platform_signin/jwks.rs +2 -1
- data/rust/host/src/platform_signin/jws.rs +2 -37
- data/rust/host/src/platform_signin/known_answer_tests.rs +5 -1
- data/rust/host/src/platform_signin/mode_tests.rs +5 -3
- data/rust/host/src/platform_signin/pages.rs +20 -20
- data/rust/host/src/platform_signin/session.rs +8 -1
- data/rust/host/src/platform_signin/settings.rs +6 -6
- data/rust/host/src/platform_signin/strict_json.rs +12 -9
- data/rust/host/src/platform_signin/verify.rs +41 -41
- data/rust/host/src/platform_signin/wiring_support.rs +13 -18
- data/rust/host/src/presentation.rs +207 -63
- data/rust/host/src/presentation_write.rs +502 -187
- data/rust/host/src/query_step.rs +69 -18
- data/rust/host/src/rate_limit.rs +541 -142
- data/rust/host/src/reference_transform.rs +77 -25
- data/rust/host/src/reference_validate.rs +443 -104
- data/rust/host/src/resend.rs +190 -55
- data/rust/host/src/secrets.rs +116 -21
- data/rust/host/src/server.rs +555 -104
- data/rust/host/src/storage_shape.rs +88 -21
- data/rust/host/src/test_pg.rs +17 -7
- data/rust/host/src/ui_schema.rs +495 -207
- data/rust/host/src/wasm_runner.rs +21 -6
- data/rust/host/src/web/commerce.rs +101 -23
- data/rust/host/src/web/newsletter/cooldown.rs +10 -3
- data/rust/host/src/web/newsletter/template.rs +26 -7
- data/rust/host/src/web/newsletter/tests.rs +112 -23
- data/rust/host/src/web/newsletter.rs +209 -59
- data/rust/host/src/web/newsletter_send.rs +251 -79
- data/rust/host/src/web/registration_receipt/tests.rs +16 -4
- data/rust/host/src/web/registration_receipt.rs +100 -24
- data/rust/host/src/web/registrations.rs +1384 -332
- data/rust/host/src/web/resend_webhook.rs +138 -80
- data/rust/host/src/web.rs +2416 -508
- data/rust/lsp/Cargo.toml +36 -0
- data/rust/lsp/clippy.toml +4 -0
- data/rust/lsp/src/json.rs +29 -22
- data/rust/lsp/src/main.rs +81 -31
- data/rust/lsp/src/outline.rs +23 -7
- data/rust/lsp/src/rpc.rs +17 -4
- data/rust/parser/Cargo.toml +36 -0
- data/rust/parser/clippy.toml +4 -0
- data/rust/parser/src/build/closed_sets.rs +6 -1
- data/rust/parser/src/build/identity.rs +4 -3
- data/rust/parser/src/build/mod.rs +1 -1
- data/rust/parser/src/build/named_pattern.rs +4 -1
- data/rust/parser/src/build/naming.rs +2 -80
- data/rust/parser/src/build/pattern_subset.rs +6 -8
- data/rust/parser/src/build/query_derive.rs +3 -1
- data/rust/parser/src/build/query_inference.rs +14 -5
- data/rust/parser/src/build/read_model.rs +4 -1
- data/rust/parser/src/build/references.rs +4 -3
- data/rust/parser/src/canonical.rs +34 -15
- data/rust/parser/src/emit.rs +187 -105
- data/rust/parser/src/expr/ast_json.rs +134 -42
- data/rust/parser/src/expr/evaluator.rs +27 -9
- data/rust/parser/src/expr/mod.rs +54 -13
- data/rust/parser/src/expr/resolver.rs +299 -92
- data/rust/parser/src/ir.rs +35 -3
- data/rust/parser/src/keywords.rs +7168 -516
- data/rust/parser/src/lex.rs +11 -25
- data/rust/parser/src/lib.rs +1 -0
- data/rust/parser/src/main.rs +65 -6
- data/rust/parser/src/parse/adapter.rs +157 -0
- data/rust/parser/src/parse/aggregate.rs +19 -10
- data/rust/parser/src/parse/chapter.rs +16 -17
- data/rust/parser/src/parse/command.rs +35 -16
- data/rust/parser/src/parse/domain_port.rs +4 -7
- data/rust/parser/src/parse/entity.rs +21 -11
- data/rust/parser/src/parse/hecksagon.rs +10 -4
- data/rust/parser/src/parse/lifecycle.rs +9 -5
- data/rust/parser/src/parse/mod.rs +22 -91
- data/rust/parser/src/parse/needs.rs +21 -12
- data/rust/parser/src/parse/policy.rs +2 -2
- data/rust/parser/src/parse/process_manager.rs +9 -11
- data/rust/parser/src/parse/query.rs +8 -4
- data/rust/parser/src/parse/read_model.rs +57 -16
- data/rust/parser/src/parse/value_object.rs +7 -2
- data/rust/parser/src/parse/world.rs +322 -0
- data/rust/parser/src/ruby_value.rs +7 -6
- data/rust/src/exemplar/json.rs +4 -4
- data/rust/src/exemplar/mutations.rs +18 -0
- data/rust/src/exemplar/read_models.rs +1 -10
- data/rust/src/kernel/attribute_shapes/composite.rs +54 -14
- data/rust/src/kernel/attribute_shapes/list.rs +2 -2
- data/rust/src/kernel/attribute_shapes/mod.rs +8 -8
- data/rust/src/kernel/attribute_shapes/scalar.rs +2 -2
- data/rust/src/kernel/cli.rs +244 -114
- data/rust/src/kernel/dispatch.rs +323 -115
- data/rust/src/kernel/dispatch_guard_tests.rs +327 -65
- data/rust/src/kernel/expr.rs +203 -86
- data/rust/src/kernel/expression_operators/arithmetic.rs +138 -25
- data/rust/src/kernel/expression_operators/comparison.rs +87 -2
- data/rust/src/kernel/expression_operators/enumeration.rs +106 -22
- data/rust/src/kernel/expression_operators/logical.rs +9 -3
- data/rust/src/kernel/expression_operators/membership.rs +3 -1
- data/rust/src/kernel/expression_operators/mod.rs +34 -21
- data/rust/src/kernel/expression_operators/pattern_match.rs +46 -11
- data/rust/src/kernel/expression_operators/positional.rs +84 -30
- data/rust/src/kernel/expression_operators/presence.rs +52 -13
- data/rust/src/kernel/expression_operators/sign_test.rs +3 -1
- data/rust/src/kernel/expression_operators/sized.rs +24 -8
- data/rust/src/kernel/expression_operators/text.rs +120 -27
- data/rust/src/kernel/expression_operators/to_string.rs +10 -4
- data/rust/src/kernel/json.rs +244 -148
- data/rust/src/kernel/mod.rs +47 -33
- data/rust/src/kernel/named_query.rs +63 -15
- data/rust/src/kernel/needs.rs +112 -25
- data/rust/src/kernel/orchestrate.rs +980 -581
- data/rust/src/kernel/orchestrate_guard_tests.rs +538 -140
- data/rust/src/kernel/pattern.rs +107 -34
- data/rust/src/kernel/present.rs +261 -0
- data/rust/src/kernel/query_comparators.rs +118 -41
- data/rust/src/kernel/query_ordering.rs +13 -5
- data/rust/src/kernel/read_model.rs +479 -181
- data/rust/src/kernel/reference_lookup.rs +122 -26
- data/rust/src/kernel/repository.rs +293 -66
- data/rust/src/kernel/routing.rs +58 -42
- data/rust/src/kernel/ruby_float.rs +139 -0
- data/rust/src/kernel/vocab/aggregate_dispatch_order.rs +57 -57
- data/rust/src/kernel/vocab/entity_dispatch_order.rs +54 -54
- data/rust/src/kernel/vocab/field_hint.rs +19 -25
- data/rust/src/kernel/vocab/mod.rs +6 -6
- data/rust/src/kernel/vocab/query_comparator.rs +23 -24
- data/rust/src/kernel/vocab/refusal_template.rs +501 -297
- data/rust/src/lib.rs +50 -0
- data/rust/src/main.rs +4 -1
- data/rust/web/Cargo.toml +36 -0
- data/rust/web/clippy.toml +4 -0
- metadata +85 -15
- data/examples/pizzas/bluebook/hecksagon/mock_stripe_payment_adapter.rb +0 -36
- data/lib/hecks/adapters/driven/google_authentication.adapter +0 -3
- data/lib/hecks/adapters/driven/google_authentication.rb +0 -99
- data/lib/hecks/adapters/driven/mock_stripe_adapter.adapter +0 -3
- data/lib/hecks/adapters/driven/mock_stripe_adapter.rb +0 -32
- data/lib/hecks/ports/authentication.port +0 -6
- data/lib/hecks/ports/authentication.rb +0 -67
- data/lib/hecks/ports/persistence/plugins/era/translation/approval_file.rb +0 -255
- data/lib/hecks/ports/persistence/plugins/era/translation/audit/approval_digest.rb +0 -22
- data/rust/host/src/approval.rs +0 -652
data/rust/codegen/src/literal.rs
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
//! `Literal::from_json` covers values embedded raw in ir.json, which were never rendered.
|
|
3
3
|
|
|
4
4
|
use crate::json::{Json, Number};
|
|
5
|
+
use crate::ruby_value::{self, Value};
|
|
6
|
+
use crate::shared::ruby_to_i;
|
|
5
7
|
|
|
6
8
|
#[derive(Debug, Clone, PartialEq)]
|
|
7
9
|
pub enum Literal {
|
|
@@ -12,73 +14,71 @@ pub enum Literal {
|
|
|
12
14
|
/// A Symbol, which JSON cannot represent; only `read` produces one (leading-colon strings).
|
|
13
15
|
Symbol(String),
|
|
14
16
|
Str(String),
|
|
15
|
-
Hash(Vec<(String,
|
|
16
|
-
Array(Vec<
|
|
17
|
+
Hash(Vec<(String, Self)>),
|
|
18
|
+
Array(Vec<Self>),
|
|
17
19
|
}
|
|
18
20
|
|
|
19
21
|
impl Literal {
|
|
20
22
|
/// Converts a raw `Json` value structurally, with no text parsing and no Symbol case.
|
|
21
|
-
pub fn from_json(value: &Json) ->
|
|
23
|
+
pub fn from_json(value: &Json) -> Self {
|
|
22
24
|
match value {
|
|
23
|
-
Json::Null =>
|
|
24
|
-
Json::Bool(b) =>
|
|
25
|
+
Json::Null => Self::Nil,
|
|
26
|
+
Json::Bool(b) => Self::Bool(*b),
|
|
25
27
|
Json::Number(_) => match value.number() {
|
|
26
|
-
Some(Number::Int(n)) =>
|
|
27
|
-
Some(Number::Float(n)) =>
|
|
28
|
-
None =>
|
|
28
|
+
Some(Number::Int(n)) => Self::Int(n),
|
|
29
|
+
Some(Number::Float(n)) => Self::Float(n),
|
|
30
|
+
None => Self::Nil,
|
|
29
31
|
},
|
|
30
|
-
Json::String(s) =>
|
|
31
|
-
Json::Array(items) =>
|
|
32
|
-
Json::Object(pairs) =>
|
|
32
|
+
Json::String(s) => Self::Str(s.clone()),
|
|
33
|
+
Json::Array(items) => Self::Array(items.iter().map(Self::from_json).collect()),
|
|
34
|
+
Json::Object(pairs) => Self::Hash(
|
|
35
|
+
pairs
|
|
36
|
+
.iter()
|
|
37
|
+
.map(|(k, v)| (k.clone(), Self::from_json(v)))
|
|
38
|
+
.collect(),
|
|
39
|
+
),
|
|
33
40
|
}
|
|
34
41
|
}
|
|
35
42
|
|
|
36
|
-
pub fn as_hash(&self) -> Option<&[(String,
|
|
43
|
+
pub const fn as_hash(&self) -> Option<&[(String, Self)]> {
|
|
37
44
|
match self {
|
|
38
|
-
|
|
45
|
+
Self::Hash(pairs) => Some(pairs.as_slice()),
|
|
39
46
|
_ => None,
|
|
40
47
|
}
|
|
41
48
|
}
|
|
42
49
|
|
|
43
|
-
pub fn get(&self, key: &str) -> Option<&
|
|
44
|
-
self.as_hash()
|
|
50
|
+
pub fn get(&self, key: &str) -> Option<&Self> {
|
|
51
|
+
self.as_hash()?
|
|
52
|
+
.iter()
|
|
53
|
+
.find(|(k, _)| k == key)
|
|
54
|
+
.map(|(_, v)| v)
|
|
45
55
|
}
|
|
46
56
|
}
|
|
47
57
|
|
|
48
58
|
/// `Literal.read`: parses a rendered wire string back to a `Literal`.
|
|
49
59
|
///
|
|
50
|
-
///
|
|
60
|
+
/// Reads through the parser's shared `ruby_value::read`. A bare word becomes a `Str`. An integer
|
|
61
|
+
/// too large for `i64` (the shared reader returns it as `Bare`) becomes `Int(0)`, as `ruby_to_i`
|
|
62
|
+
/// always did: no corpus domain holds one, and a stable `0` keeps generation total.
|
|
51
63
|
pub fn read(text: &str) -> Literal {
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
return Literal::Nil;
|
|
55
|
-
}
|
|
56
|
-
if raw == "true" {
|
|
57
|
-
return Literal::Bool(true);
|
|
58
|
-
}
|
|
59
|
-
if raw == "false" {
|
|
60
|
-
return Literal::Bool(false);
|
|
61
|
-
}
|
|
62
|
-
if is_integer(raw) {
|
|
63
|
-
return Literal::Int(ruby_to_i(raw));
|
|
64
|
-
}
|
|
65
|
-
if is_float(raw) {
|
|
66
|
-
return Literal::Float(raw.parse::<f64>().unwrap_or(0.0));
|
|
67
|
-
}
|
|
68
|
-
if let Some(rest) = raw.strip_prefix(':') {
|
|
69
|
-
return Literal::Symbol(rest.to_string());
|
|
70
|
-
}
|
|
71
|
-
if is_quoted(raw) {
|
|
72
|
-
return Literal::Str(unquote(raw));
|
|
73
|
-
}
|
|
74
|
-
if raw.starts_with('{') && raw.ends_with('}') {
|
|
75
|
-
return read_hash(raw);
|
|
76
|
-
}
|
|
77
|
-
if raw.starts_with('[') && raw.ends_with(']') {
|
|
78
|
-
return read_array(raw);
|
|
79
|
-
}
|
|
64
|
+
from_value(ruby_value::read(text))
|
|
65
|
+
}
|
|
80
66
|
|
|
81
|
-
|
|
67
|
+
fn from_value(value: Value) -> Literal {
|
|
68
|
+
match value {
|
|
69
|
+
Value::Nil => Literal::Nil,
|
|
70
|
+
Value::Bool(b) => Literal::Bool(b),
|
|
71
|
+
Value::Int(n) => Literal::Int(n),
|
|
72
|
+
Value::Float(n) => Literal::Float(n),
|
|
73
|
+
Value::Str(s) => Literal::Str(s),
|
|
74
|
+
Value::Symbol(s) => Literal::Symbol(s),
|
|
75
|
+
Value::Hash(pairs) => {
|
|
76
|
+
Literal::Hash(pairs.into_iter().map(|(k, v)| (k, from_value(v))).collect())
|
|
77
|
+
}
|
|
78
|
+
Value::Array(items) => Literal::Array(items.into_iter().map(from_value).collect()),
|
|
79
|
+
Value::Bare(text) if is_integer(&text) => Literal::Int(ruby_to_i(&text)),
|
|
80
|
+
Value::Bare(text) => Literal::Str(text),
|
|
81
|
+
}
|
|
82
82
|
}
|
|
83
83
|
|
|
84
84
|
/// `/\A-?\d+\z/`
|
|
@@ -87,63 +87,11 @@ fn is_integer(raw: &str) -> bool {
|
|
|
87
87
|
!s.is_empty() && s.bytes().all(|b| b.is_ascii_digit())
|
|
88
88
|
}
|
|
89
89
|
|
|
90
|
-
/// `/\A-?\d+\.\d+\z/`
|
|
91
|
-
fn is_float(raw: &str) -> bool {
|
|
92
|
-
let s = raw.strip_prefix('-').unwrap_or(raw);
|
|
93
|
-
let Some((int_part, frac_part)) = s.split_once('.') else { return false };
|
|
94
|
-
!int_part.is_empty() && !frac_part.is_empty() && int_part.bytes().all(|b| b.is_ascii_digit()) && frac_part.bytes().all(|b| b.is_ascii_digit())
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
fn ruby_to_i(raw: &str) -> i64 {
|
|
98
|
-
raw.parse().unwrap_or(0)
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
fn is_quoted(raw: &str) -> bool {
|
|
102
|
-
raw.len() >= 2 && raw.starts_with('"') && raw.ends_with('"')
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
/// Drops the surrounding quotes, then unescapes any backslash-escaped character.
|
|
106
|
-
fn unquote(raw: &str) -> String {
|
|
107
|
-
let inner = &raw[1..raw.len() - 1];
|
|
108
|
-
let mut out = String::with_capacity(inner.len());
|
|
109
|
-
let mut chars = inner.chars().peekable();
|
|
110
|
-
while let Some(c) = chars.next() {
|
|
111
|
-
if c == '\\' {
|
|
112
|
-
if let Some(next) = chars.next() {
|
|
113
|
-
out.push(next);
|
|
114
|
-
continue;
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
out.push(c);
|
|
118
|
-
}
|
|
119
|
-
out
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
fn read_hash(raw: &str) -> Literal {
|
|
123
|
-
let inner = &raw[1..raw.len() - 1];
|
|
124
|
-
let pairs = split_items(inner)
|
|
125
|
-
.into_iter()
|
|
126
|
-
.map(|item| {
|
|
127
|
-
// Splits at the first ":" only, like Ruby's `partition`; field names have none.
|
|
128
|
-
match item.find(':') {
|
|
129
|
-
Some(idx) => {
|
|
130
|
-
let key = item[..idx].trim().to_string();
|
|
131
|
-
let held = &item[idx + 1..];
|
|
132
|
-
(key, read(held))
|
|
133
|
-
}
|
|
134
|
-
None => (item.trim().to_string(), read("")),
|
|
135
|
-
}
|
|
136
|
-
})
|
|
137
|
-
.collect();
|
|
138
|
-
Literal::Hash(pairs)
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
fn read_array(raw: &str) -> Literal {
|
|
142
|
-
let inner = &raw[1..raw.len() - 1];
|
|
143
|
-
Literal::Array(split_items(inner).into_iter().map(|item| read(&item)).collect())
|
|
144
|
-
}
|
|
145
|
-
|
|
146
90
|
/// `naming.rb#literal_rhs` for a `Literal`: String/Integer/Float/Boolean, else panics.
|
|
91
|
+
#[allow(
|
|
92
|
+
clippy::panic,
|
|
93
|
+
reason = "a drifted exemplar or invalid IR aborts generation on purpose"
|
|
94
|
+
)]
|
|
147
95
|
pub fn literal_rhs(literal: &Literal) -> String {
|
|
148
96
|
match literal {
|
|
149
97
|
Literal::Str(s) => format!("{}.to_string()", crate::naming::ruby_inspect_string(s)),
|
|
@@ -168,43 +116,61 @@ fn ruby_float_to_s(literal: &Literal) -> String {
|
|
|
168
116
|
}
|
|
169
117
|
}
|
|
170
118
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
let mut current = String::new();
|
|
175
|
-
let mut depth: i32 = 0;
|
|
176
|
-
let mut quoting = false;
|
|
177
|
-
let mut escaping = false;
|
|
178
|
-
|
|
179
|
-
for ch in body.chars() {
|
|
180
|
-
current.push(ch);
|
|
181
|
-
if escaping {
|
|
182
|
-
escaping = false;
|
|
183
|
-
continue;
|
|
184
|
-
}
|
|
185
|
-
if quoting && ch == '\\' {
|
|
186
|
-
escaping = true;
|
|
187
|
-
continue;
|
|
188
|
-
}
|
|
189
|
-
if ch == '"' {
|
|
190
|
-
quoting = !quoting;
|
|
191
|
-
continue;
|
|
192
|
-
}
|
|
193
|
-
if quoting {
|
|
194
|
-
continue;
|
|
195
|
-
}
|
|
119
|
+
#[cfg(test)]
|
|
120
|
+
mod tests {
|
|
121
|
+
use super::*;
|
|
196
122
|
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
123
|
+
fn s(text: &str) -> Literal {
|
|
124
|
+
Literal::Str(text.to_string())
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
#[test]
|
|
128
|
+
fn reads_scalars() {
|
|
129
|
+
assert_eq!(read(""), Literal::Nil);
|
|
130
|
+
assert_eq!(read("nil"), Literal::Nil);
|
|
131
|
+
assert_eq!(read("true"), Literal::Bool(true));
|
|
132
|
+
assert_eq!(read("-12"), Literal::Int(-12));
|
|
133
|
+
assert_eq!(read("1.5"), Literal::Float(1.5));
|
|
134
|
+
assert_eq!(read(":name"), Literal::Symbol("name".to_string()));
|
|
135
|
+
assert_eq!(read(r#""a\"b""#), s("a\"b"));
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
#[test]
|
|
139
|
+
fn reads_collections() {
|
|
140
|
+
assert_eq!(
|
|
141
|
+
read(r#"[1, "x"]"#),
|
|
142
|
+
Literal::Array(vec![Literal::Int(1), s("x")])
|
|
143
|
+
);
|
|
144
|
+
assert_eq!(
|
|
145
|
+
read("{a: 1, b: :c}"),
|
|
146
|
+
Literal::Hash(vec![
|
|
147
|
+
("a".to_string(), Literal::Int(1)),
|
|
148
|
+
("b".to_string(), Literal::Symbol("c".to_string()))
|
|
149
|
+
])
|
|
150
|
+
);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
#[test]
|
|
154
|
+
fn bare_word_is_a_string() {
|
|
155
|
+
assert_eq!(read("Widget"), s("Widget"));
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
#[test]
|
|
159
|
+
fn overflowing_integer_is_zero_like_ruby_to_i() {
|
|
160
|
+
assert_eq!(read("99999999999999999999"), Literal::Int(0));
|
|
161
|
+
assert_eq!(read("-99999999999999999999"), Literal::Int(0));
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
#[test]
|
|
165
|
+
fn adjacent_and_single_quoted_strings() {
|
|
166
|
+
assert_eq!(read(r#""a" "b""#), s("ab"));
|
|
167
|
+
assert_eq!(read(r"'it\'s'"), s("it's"));
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
#[test]
|
|
171
|
+
fn from_json_and_get() {
|
|
172
|
+
let hash = read("{a: 1}");
|
|
173
|
+
assert_eq!(hash.get("a"), Some(&Literal::Int(1)));
|
|
174
|
+
assert_eq!(Literal::from_json(&Json::Null), Literal::Nil);
|
|
207
175
|
}
|
|
208
|
-
items.push(current);
|
|
209
|
-
items.into_iter().map(|s| s.trim().to_string()).filter(|s| !s.is_empty()).collect()
|
|
210
176
|
}
|
data/rust/codegen/src/main.rs
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
//! `hecks-codegen` — the IR-to-Rust-source generator, the only one (ADR 0086).
|
|
2
2
|
//! Usage: `hecks-codegen <prelude|domain|full> ...`, one subcommand per function below.
|
|
3
|
-
// Some ported `naming.rs` helpers are not called yet.
|
|
4
|
-
#![allow(dead_code)]
|
|
5
3
|
|
|
6
4
|
mod asks;
|
|
7
5
|
mod attr;
|
|
@@ -13,7 +11,12 @@ mod domain_generator;
|
|
|
13
11
|
mod exemplar;
|
|
14
12
|
mod expr_emitter;
|
|
15
13
|
mod fielded;
|
|
14
|
+
// The one `Hecks::Naming` port, compiled by path into the other Cargo projects too; codegen uses
|
|
15
|
+
// only part of it.
|
|
16
|
+
#[allow(dead_code)]
|
|
16
17
|
mod hecks_naming;
|
|
18
|
+
#[cfg(test)]
|
|
19
|
+
mod hecks_naming_tests;
|
|
17
20
|
mod json;
|
|
18
21
|
mod json_codec;
|
|
19
22
|
mod literal;
|
|
@@ -23,18 +26,26 @@ mod naming;
|
|
|
23
26
|
mod optional_pass;
|
|
24
27
|
mod ports;
|
|
25
28
|
mod prelude;
|
|
29
|
+
mod presenters;
|
|
26
30
|
mod queries;
|
|
27
31
|
mod reactions;
|
|
28
32
|
mod read_models;
|
|
29
33
|
mod reference_specs;
|
|
30
34
|
mod registry;
|
|
31
35
|
mod reserved_names;
|
|
36
|
+
#[path = "../../parser/src/ruby_value.rs"]
|
|
37
|
+
#[allow(
|
|
38
|
+
dead_code,
|
|
39
|
+
reason = "shared with the parser, which uses parts codegen does not"
|
|
40
|
+
)]
|
|
41
|
+
mod ruby_value;
|
|
32
42
|
mod shared;
|
|
33
43
|
mod sidecars;
|
|
34
44
|
mod skip_reason;
|
|
35
45
|
mod types;
|
|
36
46
|
|
|
37
47
|
use json::Json;
|
|
48
|
+
use shared::{puts_blank, puts_str};
|
|
38
49
|
use std::process::ExitCode;
|
|
39
50
|
|
|
40
51
|
fn main() -> ExitCode {
|
|
@@ -69,7 +80,7 @@ fn run_prelude(args: &[String]) -> Result<(), String> {
|
|
|
69
80
|
|
|
70
81
|
let ex = exemplar::Exemplar::load();
|
|
71
82
|
|
|
72
|
-
let aggregates = ir.get("aggregates").
|
|
83
|
+
let aggregates = ir.get("aggregates").map_or_default(Json::each);
|
|
73
84
|
for aggregate in aggregates {
|
|
74
85
|
let name = aggregate.get("name").and_then(Json::as_str).unwrap_or("");
|
|
75
86
|
match prelude::aggregate_prelude(&ex, &ir, aggregate, source_label) {
|
|
@@ -92,7 +103,9 @@ fn run_prelude(args: &[String]) -> Result<(), String> {
|
|
|
92
103
|
/// sidecars into `out_dir`.
|
|
93
104
|
fn run_domain(args: &[String]) -> Result<(), String> {
|
|
94
105
|
let [ir_path, source_label, mod_name, out_dir] = args else {
|
|
95
|
-
return Err(
|
|
106
|
+
return Err(
|
|
107
|
+
"usage: hecks-codegen domain <ir.json> <source_label> <mod_name> <out_dir>".to_string(),
|
|
108
|
+
);
|
|
96
109
|
};
|
|
97
110
|
|
|
98
111
|
let ir = read_ir(ir_path)?;
|
|
@@ -123,8 +136,7 @@ fn write_domain(
|
|
|
123
136
|
// Refuse before writing anything, so a name collision is reported before any file exists.
|
|
124
137
|
let aggregate_names: Vec<&str> = ir
|
|
125
138
|
.get("aggregates")
|
|
126
|
-
.
|
|
127
|
-
.unwrap_or(&[])
|
|
139
|
+
.map_or_default(Json::each)
|
|
128
140
|
.iter()
|
|
129
141
|
.map(|a| a.get("name").and_then(Json::as_str).unwrap_or(""))
|
|
130
142
|
.collect();
|
|
@@ -146,7 +158,8 @@ fn write_domain(
|
|
|
146
158
|
}
|
|
147
159
|
|
|
148
160
|
let registry_path = format!("{out_dir}/registry.rs");
|
|
149
|
-
std::fs::write(®istry_path, &generated.registry_rs)
|
|
161
|
+
std::fs::write(®istry_path, &generated.registry_rs)
|
|
162
|
+
.map_err(|e| format!("writing {registry_path}: {e}"))?;
|
|
150
163
|
println!("wrote {registry_path}");
|
|
151
164
|
|
|
152
165
|
let mod_path = format!("{out_dir}/mod.rs");
|
|
@@ -154,34 +167,25 @@ fn write_domain(
|
|
|
154
167
|
println!("wrote {mod_path}");
|
|
155
168
|
|
|
156
169
|
let manifest_path = format!("{out_dir}/manifest.json");
|
|
157
|
-
std::fs::write(&manifest_path, &generated.manifest_json)
|
|
170
|
+
std::fs::write(&manifest_path, &generated.manifest_json)
|
|
171
|
+
.map_err(|e| format!("writing {manifest_path}: {e}"))?;
|
|
158
172
|
println!("wrote {manifest_path}");
|
|
159
173
|
|
|
160
|
-
let (ir_json_path, metadata_path) =
|
|
174
|
+
let (ir_json_path, metadata_path) =
|
|
175
|
+
sidecars::write(std::path::Path::new(out_dir), ir, source_label)?;
|
|
161
176
|
println!("wrote {}", ir_json_path.display());
|
|
162
177
|
println!("wrote {}", metadata_path.display());
|
|
163
178
|
|
|
164
179
|
Ok(generated)
|
|
165
180
|
}
|
|
166
181
|
|
|
167
|
-
fn puts_str(out: &mut String, s: &str) {
|
|
168
|
-
out.push_str(s);
|
|
169
|
-
if !s.ends_with('\n') {
|
|
170
|
-
out.push('\n');
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
fn puts_blank(out: &mut String) {
|
|
175
|
-
out.push('\n');
|
|
176
|
-
}
|
|
177
|
-
|
|
178
182
|
/// `hecks-codegen full <out_root> <target_mod_name> <target_source_label> <target_ir.json>
|
|
179
183
|
/// [<chapter_mod_name> <chapter_source_label> <chapter_ir.json>]...`
|
|
180
184
|
///
|
|
181
185
|
/// Writes the target chapter's directory, each attached chapter's own directory, and the
|
|
182
186
|
/// target's `merged.rs`: one `Store`/`dispatch_by_name` table spanning every chapter given.
|
|
183
187
|
fn run_full(args: &[String]) -> Result<(), String> {
|
|
184
|
-
if args.len() < 4 || (args.len() - 4)
|
|
188
|
+
if args.len() < 4 || !(args.len() - 4).is_multiple_of(3) {
|
|
185
189
|
return Err(
|
|
186
190
|
"usage: hecks-codegen full <out_root> <target_mod_name> <target_source_label> <target_ir.json> [<chapter_mod_name> <chapter_source_label> <chapter_ir.json>]..."
|
|
187
191
|
.to_string(),
|
|
@@ -196,19 +200,38 @@ fn run_full(args: &[String]) -> Result<(), String> {
|
|
|
196
200
|
let ex = exemplar::Exemplar::load();
|
|
197
201
|
|
|
198
202
|
let target_ir = read_ir(target_ir_path)?;
|
|
199
|
-
let target_domain_name = target_ir
|
|
203
|
+
let target_domain_name = target_ir
|
|
204
|
+
.get("name")
|
|
205
|
+
.and_then(Json::as_str)
|
|
206
|
+
.unwrap_or("")
|
|
207
|
+
.to_string();
|
|
200
208
|
|
|
201
209
|
let target_out_dir = format!("{out_root}/{target_mod_name}");
|
|
202
|
-
let target_gen = write_domain(
|
|
210
|
+
let target_gen = write_domain(
|
|
211
|
+
&ex,
|
|
212
|
+
&target_ir,
|
|
213
|
+
target_source_label,
|
|
214
|
+
target_mod_name,
|
|
215
|
+
&target_out_dir,
|
|
216
|
+
)?;
|
|
203
217
|
|
|
204
218
|
// Target first, then each attached chapter in command-line order.
|
|
205
|
-
let mut reference_key_pairs: Vec<(String, Vec<String>)> =
|
|
206
|
-
|
|
219
|
+
let mut reference_key_pairs: Vec<(String, Vec<String>)> = vec![(
|
|
220
|
+
target_domain_name.clone(),
|
|
221
|
+
target_gen
|
|
222
|
+
.registry_aggregates
|
|
223
|
+
.iter()
|
|
224
|
+
.map(|a| a.name.clone())
|
|
225
|
+
.collect(),
|
|
226
|
+
)];
|
|
207
227
|
|
|
208
228
|
let mut merged_aggregates = target_gen.registry_aggregates;
|
|
209
229
|
let mut merged_queries = target_gen.query_defs;
|
|
210
230
|
let mut merged_read_models = target_gen.read_model_defs;
|
|
211
|
-
let mut merged_process_managers: Vec<Json> = target_ir
|
|
231
|
+
let mut merged_process_managers: Vec<Json> = target_ir
|
|
232
|
+
.get("process_managers")
|
|
233
|
+
.map_or_default(Json::each)
|
|
234
|
+
.to_vec();
|
|
212
235
|
|
|
213
236
|
// Policies and process managers merge across chapters; `chapter_irs` keeps each parsed
|
|
214
237
|
// chapter alive so `policy_sources` can borrow from it.
|
|
@@ -223,60 +246,127 @@ fn run_full(args: &[String]) -> Result<(), String> {
|
|
|
223
246
|
i += 3;
|
|
224
247
|
|
|
225
248
|
let chapter_ir = read_ir(chapter_ir_path)?;
|
|
226
|
-
let chapter_domain_name = chapter_ir
|
|
249
|
+
let chapter_domain_name = chapter_ir
|
|
250
|
+
.get("name")
|
|
251
|
+
.and_then(Json::as_str)
|
|
252
|
+
.unwrap_or("")
|
|
253
|
+
.to_string();
|
|
227
254
|
|
|
228
255
|
let chapter_out_dir = format!("{out_root}/{chapter_mod_name}");
|
|
229
|
-
let chapter_gen = write_domain(
|
|
230
|
-
|
|
231
|
-
|
|
256
|
+
let chapter_gen = write_domain(
|
|
257
|
+
&ex,
|
|
258
|
+
&chapter_ir,
|
|
259
|
+
chapter_source_label,
|
|
260
|
+
chapter_mod_name,
|
|
261
|
+
&chapter_out_dir,
|
|
262
|
+
)?;
|
|
263
|
+
|
|
264
|
+
reference_key_pairs.push((
|
|
265
|
+
chapter_domain_name.clone(),
|
|
266
|
+
chapter_gen
|
|
267
|
+
.registry_aggregates
|
|
268
|
+
.iter()
|
|
269
|
+
.map(|a| a.name.clone())
|
|
270
|
+
.collect(),
|
|
271
|
+
));
|
|
232
272
|
merged_aggregates.extend(chapter_gen.registry_aggregates);
|
|
233
273
|
merged_queries.extend(chapter_gen.query_defs);
|
|
234
274
|
merged_read_models.extend(chapter_gen.read_model_defs);
|
|
235
|
-
merged_process_managers.extend(
|
|
275
|
+
merged_process_managers.extend(
|
|
276
|
+
chapter_ir
|
|
277
|
+
.get("process_managers")
|
|
278
|
+
.map_or_default(Json::each)
|
|
279
|
+
.to_vec(),
|
|
280
|
+
);
|
|
236
281
|
|
|
237
282
|
chapter_domain_names.push(chapter_domain_name);
|
|
238
283
|
chapter_irs.push(chapter_ir);
|
|
239
284
|
}
|
|
240
285
|
|
|
241
286
|
// One entry per chapter, so its policies qualify against its own domain and aggregates.
|
|
242
|
-
let policies: Vec<Json> = target_ir
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
287
|
+
let policies: Vec<Json> = target_ir
|
|
288
|
+
.get("policies")
|
|
289
|
+
.map_or_default(Json::each)
|
|
290
|
+
.to_vec();
|
|
291
|
+
let policy_aggregates: Vec<Json> = target_ir
|
|
292
|
+
.get("aggregates")
|
|
293
|
+
.map_or_default(Json::each)
|
|
294
|
+
.to_vec();
|
|
295
|
+
|
|
296
|
+
let mut policy_sources: Vec<reactions::PolicySource> = vec![reactions::PolicySource {
|
|
297
|
+
domain_name: &target_domain_name,
|
|
298
|
+
policies: &policies,
|
|
299
|
+
aggregates: &policy_aggregates,
|
|
300
|
+
}];
|
|
247
301
|
for (name, ir) in chapter_domain_names.iter().zip(chapter_irs.iter()) {
|
|
248
302
|
policy_sources.push(reactions::PolicySource {
|
|
249
303
|
domain_name: name,
|
|
250
|
-
policies: ir.get("policies").
|
|
251
|
-
aggregates: ir.get("aggregates").
|
|
304
|
+
policies: ir.get("policies").map_or_default(Json::each),
|
|
305
|
+
aggregates: ir.get("aggregates").map_or_default(Json::each),
|
|
252
306
|
});
|
|
253
307
|
}
|
|
254
308
|
|
|
255
309
|
let mut merged_rs = String::new();
|
|
256
|
-
puts_str(
|
|
310
|
+
puts_str(
|
|
311
|
+
&mut merged_rs,
|
|
312
|
+
&crate::registry::emit_registry(&ex, &merged_aggregates),
|
|
313
|
+
);
|
|
257
314
|
puts_blank(&mut merged_rs);
|
|
258
|
-
puts_str(
|
|
315
|
+
puts_str(
|
|
316
|
+
&mut merged_rs,
|
|
317
|
+
&crate::registry::emit_reference_lookup(&merged_aggregates),
|
|
318
|
+
);
|
|
259
319
|
puts_blank(&mut merged_rs);
|
|
260
|
-
puts_str(
|
|
320
|
+
puts_str(
|
|
321
|
+
&mut merged_rs,
|
|
322
|
+
&reactions::emit_merged_policy_table(&ex, &policy_sources),
|
|
323
|
+
);
|
|
261
324
|
puts_blank(&mut merged_rs);
|
|
262
|
-
puts_str(
|
|
325
|
+
puts_str(
|
|
326
|
+
&mut merged_rs,
|
|
327
|
+
&reactions::emit_merged_cross_domain_policy_table(&ex, &policy_sources),
|
|
328
|
+
);
|
|
263
329
|
puts_blank(&mut merged_rs);
|
|
264
|
-
puts_str(
|
|
330
|
+
puts_str(
|
|
331
|
+
&mut merged_rs,
|
|
332
|
+
&reactions::emit_process_manager_table(&ex, &merged_process_managers),
|
|
333
|
+
);
|
|
265
334
|
puts_blank(&mut merged_rs);
|
|
266
|
-
puts_str(
|
|
335
|
+
puts_str(
|
|
336
|
+
&mut merged_rs,
|
|
337
|
+
&reactions::emit_reference_key_table(&ex, &reference_key_pairs),
|
|
338
|
+
);
|
|
267
339
|
puts_blank(&mut merged_rs);
|
|
268
|
-
puts_str(
|
|
340
|
+
puts_str(
|
|
341
|
+
&mut merged_rs,
|
|
342
|
+
&reactions::emit_creates_table(&ex, &merged_aggregates),
|
|
343
|
+
);
|
|
269
344
|
puts_blank(&mut merged_rs);
|
|
270
|
-
puts_str(
|
|
345
|
+
puts_str(
|
|
346
|
+
&mut merged_rs,
|
|
347
|
+
&reactions::emit_identity_head_table(&ex, &merged_aggregates),
|
|
348
|
+
);
|
|
271
349
|
puts_blank(&mut merged_rs);
|
|
272
350
|
// Section order is part of the output: `hecks regenerate_corpus --check` diffs this file byte for byte.
|
|
273
|
-
puts_str(
|
|
351
|
+
puts_str(
|
|
352
|
+
&mut merged_rs,
|
|
353
|
+
&reactions::emit_entity_identity_head_table(&ex, &merged_aggregates),
|
|
354
|
+
);
|
|
274
355
|
puts_blank(&mut merged_rs);
|
|
275
|
-
puts_str(
|
|
356
|
+
puts_str(
|
|
357
|
+
&mut merged_rs,
|
|
358
|
+
&reactions::emit_command_attributes_table(&ex, &merged_aggregates),
|
|
359
|
+
);
|
|
276
360
|
puts_blank(&mut merged_rs);
|
|
277
|
-
puts_str(
|
|
361
|
+
puts_str(
|
|
362
|
+
&mut merged_rs,
|
|
363
|
+
&queries::emit_query_table(&ex, &merged_queries),
|
|
364
|
+
);
|
|
278
365
|
puts_blank(&mut merged_rs);
|
|
279
|
-
puts_str(
|
|
366
|
+
puts_str(
|
|
367
|
+
&mut merged_rs,
|
|
368
|
+
&queries::emit_query_arg_check_table(&merged_queries),
|
|
369
|
+
);
|
|
280
370
|
puts_blank(&mut merged_rs);
|
|
281
371
|
for rmd in &merged_read_models {
|
|
282
372
|
if let Some(body) = &rmd.group_by_fn_body {
|
|
@@ -284,7 +374,15 @@ fn run_full(args: &[String]) -> Result<(), String> {
|
|
|
284
374
|
puts_blank(&mut merged_rs);
|
|
285
375
|
}
|
|
286
376
|
}
|
|
287
|
-
puts_str(
|
|
377
|
+
puts_str(
|
|
378
|
+
&mut merged_rs,
|
|
379
|
+
&read_models::emit_read_model_table(&ex, &merged_read_models),
|
|
380
|
+
);
|
|
381
|
+
puts_blank(&mut merged_rs);
|
|
382
|
+
puts_str(
|
|
383
|
+
&mut merged_rs,
|
|
384
|
+
&presenters::emit_present_router(&merged_aggregates),
|
|
385
|
+
);
|
|
288
386
|
|
|
289
387
|
let merged_path = format!("{target_out_dir}/merged.rs");
|
|
290
388
|
std::fs::write(&merged_path, &merged_rs).map_err(|e| format!("writing {merged_path}: {e}"))?;
|
|
@@ -292,7 +390,8 @@ fn run_full(args: &[String]) -> Result<(), String> {
|
|
|
292
390
|
|
|
293
391
|
// `write_domain` already wrote `mod.rs`; only the target directory gets a `merged` module.
|
|
294
392
|
let mod_path = format!("{target_out_dir}/mod.rs");
|
|
295
|
-
let mut mod_rs =
|
|
393
|
+
let mut mod_rs =
|
|
394
|
+
std::fs::read_to_string(&mod_path).map_err(|e| format!("reading {mod_path}: {e}"))?;
|
|
296
395
|
if !mod_rs.ends_with('\n') {
|
|
297
396
|
mod_rs.push('\n');
|
|
298
397
|
}
|