@shortlink-org/portolan 0.1.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.
- package/LICENSE +21 -0
- package/README.md +387 -0
- package/catalog/enum_test.go +46 -0
- package/catalog/model.go +932 -0
- package/catalog/roundtrip_test.go +185 -0
- package/catalog/via_test.go +38 -0
- package/cli/portolan.mjs +368 -0
- package/go.mod +14 -0
- package/go.sum +14 -0
- package/index.html +13 -0
- package/internal/commands/cargo.go +154 -0
- package/internal/commands/commands.go +143 -0
- package/internal/commands/commands_test.go +323 -0
- package/internal/commands/gradle.go +77 -0
- package/internal/commands/justfile.go +82 -0
- package/internal/commands/makefile.go +106 -0
- package/internal/commands/maven.go +93 -0
- package/internal/commands/packagejson.go +159 -0
- package/internal/commands/pyproject.go +169 -0
- package/internal/commands/taskfile.go +101 -0
- package/internal/commands/testdata/estate/.cargo/config.toml +7 -0
- package/internal/commands/testdata/estate/Makefile +33 -0
- package/internal/commands/testdata/estate/Taskfile.yml +21 -0
- package/internal/commands/testdata/estate/build.gradle.kts +21 -0
- package/internal/commands/testdata/estate/justfile +20 -0
- package/internal/commands/testdata/estate/package.json +13 -0
- package/internal/commands/testdata/estate/pom.xml +29 -0
- package/internal/commands/testdata/estate/pyproject.toml +27 -0
- package/internal/commands/testdata/estate/xtask/src/main.rs +27 -0
- package/internal/commands/testdata/golden/commands.json +305 -0
- package/internal/gohttp/analyze.go +2500 -0
- package/internal/gohttp/endpoints.go +1067 -0
- package/internal/gohttp/roots.go +320 -0
- package/internal/gohttp/typed.go +143 -0
- package/internal/goscan/constants.go +85 -0
- package/internal/goscan/goscan_test.go +227 -0
- package/internal/goscan/names.go +52 -0
- package/internal/goscan/parse_test.go +11 -0
- package/internal/goscan/source.go +36 -0
- package/internal/goscan/tree.go +155 -0
- package/internal/goscan/types.go +99 -0
- package/internal/wsdl/ids.go +127 -0
- package/internal/wsdl/ids_test.go +21 -0
- package/internal/wsdl/model.go +62 -0
- package/internal/wsdl/parse.go +920 -0
- package/internal/wsdl/parse_test.go +133 -0
- package/package.json +117 -0
- package/plugin/describe.go +107 -0
- package/plugin/describe_test.go +114 -0
- package/plugin/protocol.go +117 -0
- package/plugin/schematest/schematest.go +126 -0
- package/plugins/README.md +1160 -0
- package/plugins/extract-adr/describe.go +19 -0
- package/plugins/extract-adr/describe_test.go +11 -0
- package/plugins/extract-adr/extract.go +153 -0
- package/plugins/extract-adr/extract_test.go +350 -0
- package/plugins/extract-adr/history.go +99 -0
- package/plugins/extract-adr/main.go +65 -0
- package/plugins/extract-adr/options.schema.json +26 -0
- package/plugins/extract-adr/parse.go +642 -0
- package/plugins/extract-adr/parse_test.go +405 -0
- package/plugins/extract-asyncapi/describe.go +19 -0
- package/plugins/extract-asyncapi/describe_test.go +11 -0
- package/plugins/extract-asyncapi/extract.go +315 -0
- package/plugins/extract-asyncapi/extract_test.go +197 -0
- package/plugins/extract-asyncapi/main.go +48 -0
- package/plugins/extract-asyncapi/options.schema.json +26 -0
- package/plugins/extract-asyncapi/spec.go +151 -0
- package/plugins/extract-celery/README.md +169 -0
- package/plugins/extract-celery/extract.py +346 -0
- package/plugins/extract-celery/extract_test.py +192 -0
- package/plugins/extract-celery/main.py +66 -0
- package/plugins/extract-celery/options.py +31 -0
- package/plugins/extract-celery/options.schema.json +31 -0
- package/plugins/extract-celery/producers.py +156 -0
- package/plugins/extract-celery/routes_test.py +106 -0
- package/plugins/extract-commands/describe.go +19 -0
- package/plugins/extract-commands/describe_test.go +11 -0
- package/plugins/extract-commands/extract.go +79 -0
- package/plugins/extract-commands/extract_test.go +92 -0
- package/plugins/extract-commands/main.go +55 -0
- package/plugins/extract-commands/options.schema.json +20 -0
- package/plugins/extract-csr/avro.go +258 -0
- package/plugins/extract-csr/describe.go +19 -0
- package/plugins/extract-csr/describe_test.go +11 -0
- package/plugins/extract-csr/extract.go +338 -0
- package/plugins/extract-csr/extract_test.go +374 -0
- package/plugins/extract-csr/jsonschema.go +343 -0
- package/plugins/extract-csr/lock.go +25 -0
- package/plugins/extract-csr/main.go +84 -0
- package/plugins/extract-csr/options.schema.json +43 -0
- package/plugins/extract-csr/subject.go +102 -0
- package/plugins/extract-django/README.md +386 -0
- package/plugins/extract-django/apps.py +100 -0
- package/plugins/extract-django/auth.py +302 -0
- package/plugins/extract-django/auth_test.py +188 -0
- package/plugins/extract-django/clients.py +121 -0
- package/plugins/extract-django/contracts.py +458 -0
- package/plugins/extract-django/database.py +119 -0
- package/plugins/extract-django/domain.py +318 -0
- package/plugins/extract-django/events.py +86 -0
- package/plugins/extract-django/extract.py +601 -0
- package/plugins/extract-django/extract_test.py +397 -0
- package/plugins/extract-django/flows.py +1278 -0
- package/plugins/extract-django/flows_test.py +338 -0
- package/plugins/extract-django/ids.py +42 -0
- package/plugins/extract-django/ids_test.py +30 -0
- package/plugins/extract-django/lifecycle.py +222 -0
- package/plugins/extract-django/lifecycle_test.py +76 -0
- package/plugins/extract-django/main.py +66 -0
- package/plugins/extract-django/openapi.py +229 -0
- package/plugins/extract-django/openapi_test.py +60 -0
- package/plugins/extract-django/operations.py +96 -0
- package/plugins/extract-django/options.py +61 -0
- package/plugins/extract-django/options.schema.json +126 -0
- package/plugins/extract-django/routing.py +214 -0
- package/plugins/extract-django/routing_test.py +198 -0
- package/plugins/extract-django/serializers.py +558 -0
- package/plugins/extract-django/store.py +434 -0
- package/plugins/extract-django/transport.py +242 -0
- package/plugins/extract-flows/describe.go +19 -0
- package/plugins/extract-flows/describe_test.go +11 -0
- package/plugins/extract-flows/extract.go +91 -0
- package/plugins/extract-flows/main.go +45 -0
- package/plugins/extract-flows/options.schema.json +16 -0
- package/plugins/extract-flows/parse.go +593 -0
- package/plugins/extract-flows/parse_test.go +204 -0
- package/plugins/extract-glossary/describe.go +19 -0
- package/plugins/extract-glossary/describe_test.go +11 -0
- package/plugins/extract-glossary/extract.go +115 -0
- package/plugins/extract-glossary/extract_test.go +220 -0
- package/plugins/extract-glossary/main.go +59 -0
- package/plugins/extract-glossary/options.schema.json +21 -0
- package/plugins/extract-glossary/parse.go +214 -0
- package/plugins/extract-glossary/parse_test.go +203 -0
- package/plugins/extract-go/aggregate.go +214 -0
- package/plugins/extract-go/client.go +409 -0
- package/plugins/extract-go/client_test.go +266 -0
- package/plugins/extract-go/describe.go +19 -0
- package/plugins/extract-go/describe_test.go +11 -0
- package/plugins/extract-go/enum.go +195 -0
- package/plugins/extract-go/enum_test.go +82 -0
- package/plugins/extract-go/event.go +99 -0
- package/plugins/extract-go/extract.go +191 -0
- package/plugins/extract-go/extract_test.go +261 -0
- package/plugins/extract-go/flow.go +1441 -0
- package/plugins/extract-go/flow_test.go +609 -0
- package/plugins/extract-go/httpclient.go +174 -0
- package/plugins/extract-go/httpclient_test.go +296 -0
- package/plugins/extract-go/ids.go +92 -0
- package/plugins/extract-go/layout.go +225 -0
- package/plugins/extract-go/layout_test.go +125 -0
- package/plugins/extract-go/lifecycle.go +324 -0
- package/plugins/extract-go/lifecycle_test.go +108 -0
- package/plugins/extract-go/main.go +79 -0
- package/plugins/extract-go/operation.go +157 -0
- package/plugins/extract-go/options.schema.json +66 -0
- package/plugins/extract-go/source.go +316 -0
- package/plugins/extract-go/transport.go +321 -0
- package/plugins/extract-go/transport_test.go +145 -0
- package/plugins/extract-go/wiring.go +434 -0
- package/plugins/extract-go-nats/describe.go +19 -0
- package/plugins/extract-go-nats/describe_test.go +11 -0
- package/plugins/extract-go-nats/extract.go +177 -0
- package/plugins/extract-go-nats/extract_test.go +389 -0
- package/plugins/extract-go-nats/index.go +379 -0
- package/plugins/extract-go-nats/main.go +42 -0
- package/plugins/extract-go-nats/options.schema.json +21 -0
- package/plugins/extract-go-nats/resolve.go +161 -0
- package/plugins/extract-go-nats/sites.go +224 -0
- package/plugins/extract-graphql/describe.go +19 -0
- package/plugins/extract-graphql/describe_test.go +11 -0
- package/plugins/extract-graphql/extract.go +433 -0
- package/plugins/extract-graphql/extract_test.go +256 -0
- package/plugins/extract-graphql/ids.go +49 -0
- package/plugins/extract-graphql/lex.go +237 -0
- package/plugins/extract-graphql/main.go +51 -0
- package/plugins/extract-graphql/options.schema.json +31 -0
- package/plugins/extract-graphql/parse.go +621 -0
- package/plugins/extract-graphql/parse_test.go +122 -0
- package/plugins/extract-http-clients/describe.go +19 -0
- package/plugins/extract-http-clients/describe_test.go +11 -0
- package/plugins/extract-http-clients/extract.go +705 -0
- package/plugins/extract-http-clients/extract_test.go +1263 -0
- package/plugins/extract-http-clients/main.go +42 -0
- package/plugins/extract-http-clients/options.schema.json +33 -0
- package/plugins/extract-java/README.md +190 -0
- package/plugins/extract-java/build/org/portolan/extract/Catalog.class +0 -0
- package/plugins/extract-java/build/org/portolan/extract/Clients$1.class +0 -0
- package/plugins/extract-java/build/org/portolan/extract/Clients$2.class +0 -0
- package/plugins/extract-java/build/org/portolan/extract/Clients$Call.class +0 -0
- package/plugins/extract-java/build/org/portolan/extract/Clients$Client.class +0 -0
- package/plugins/extract-java/build/org/portolan/extract/Clients$Route.class +0 -0
- package/plugins/extract-java/build/org/portolan/extract/Clients.class +0 -0
- package/plugins/extract-java/build/org/portolan/extract/Domain$Aggregate.class +0 -0
- package/plugins/extract-java/build/org/portolan/extract/Domain.class +0 -0
- package/plugins/extract-java/build/org/portolan/extract/Events$Found.class +0 -0
- package/plugins/extract-java/build/org/portolan/extract/Events.class +0 -0
- package/plugins/extract-java/build/org/portolan/extract/Extract.class +0 -0
- package/plugins/extract-java/build/org/portolan/extract/Flows$1.class +0 -0
- package/plugins/extract-java/build/org/portolan/extract/Flows$Binding.class +0 -0
- package/plugins/extract-java/build/org/portolan/extract/Flows$Draft.class +0 -0
- package/plugins/extract-java/build/org/portolan/extract/Flows$Frame.class +0 -0
- package/plugins/extract-java/build/org/portolan/extract/Flows$Options.class +0 -0
- package/plugins/extract-java/build/org/portolan/extract/Flows.class +0 -0
- package/plugins/extract-java/build/org/portolan/extract/Ids.class +0 -0
- package/plugins/extract-java/build/org/portolan/extract/Json$Reader.class +0 -0
- package/plugins/extract-java/build/org/portolan/extract/Json.class +0 -0
- package/plugins/extract-java/build/org/portolan/extract/Lifecycle$1.class +0 -0
- package/plugins/extract-java/build/org/portolan/extract/Lifecycle$Move.class +0 -0
- package/plugins/extract-java/build/org/portolan/extract/Lifecycle.class +0 -0
- package/plugins/extract-java/build/org/portolan/extract/Main.class +0 -0
- package/plugins/extract-java/build/org/portolan/extract/OpenApi$Operation.class +0 -0
- package/plugins/extract-java/build/org/portolan/extract/OpenApi$Spec.class +0 -0
- package/plugins/extract-java/build/org/portolan/extract/OpenApi.class +0 -0
- package/plugins/extract-java/build/org/portolan/extract/Operations$1.class +0 -0
- package/plugins/extract-java/build/org/portolan/extract/Operations$UseCase.class +0 -0
- package/plugins/extract-java/build/org/portolan/extract/Operations.class +0 -0
- package/plugins/extract-java/build/org/portolan/extract/Proto$Rpc.class +0 -0
- package/plugins/extract-java/build/org/portolan/extract/Proto$Service.class +0 -0
- package/plugins/extract-java/build/org/portolan/extract/Proto.class +0 -0
- package/plugins/extract-java/build/org/portolan/extract/Protocol$Builder.class +0 -0
- package/plugins/extract-java/build/org/portolan/extract/Protocol$Input.class +0 -0
- package/plugins/extract-java/build/org/portolan/extract/Protocol$Options.class +0 -0
- package/plugins/extract-java/build/org/portolan/extract/Protocol.class +0 -0
- package/plugins/extract-java/build/org/portolan/extract/Source$Project.class +0 -0
- package/plugins/extract-java/build/org/portolan/extract/Source$Unit.class +0 -0
- package/plugins/extract-java/build/org/portolan/extract/Source.class +0 -0
- package/plugins/extract-java/build/org/portolan/extract/Transport$Endpoint.class +0 -0
- package/plugins/extract-java/build/org/portolan/extract/Transport.class +0 -0
- package/plugins/extract-java/build/org/portolan/extract/Yaml$Line.class +0 -0
- package/plugins/extract-java/build/org/portolan/extract/Yaml$Reader.class +0 -0
- package/plugins/extract-java/build/org/portolan/extract/Yaml.class +0 -0
- package/plugins/extract-java/options.schema.json +70 -0
- package/plugins/extract-openapi/describe.go +19 -0
- package/plugins/extract-openapi/describe_test.go +11 -0
- package/plugins/extract-openapi/discover.go +243 -0
- package/plugins/extract-openapi/extract.go +526 -0
- package/plugins/extract-openapi/extract_test.go +545 -0
- package/plugins/extract-openapi/main.go +75 -0
- package/plugins/extract-openapi/options.schema.json +62 -0
- package/plugins/extract-openapi/spec.go +350 -0
- package/plugins/extract-project/README.md +22 -0
- package/plugins/extract-project/describe.go +19 -0
- package/plugins/extract-project/describe_test.go +11 -0
- package/plugins/extract-project/extract.go +221 -0
- package/plugins/extract-project/extract_test.go +109 -0
- package/plugins/extract-project/main.go +41 -0
- package/plugins/extract-project/options.schema.json +48 -0
- package/plugins/extract-proto/ast.go +125 -0
- package/plugins/extract-proto/consumes.go +77 -0
- package/plugins/extract-proto/describe.go +19 -0
- package/plugins/extract-proto/extract.go +293 -0
- package/plugins/extract-proto/extract_test.go +459 -0
- package/plugins/extract-proto/ids.go +89 -0
- package/plugins/extract-proto/ids_test.go +57 -0
- package/plugins/extract-proto/lex.go +285 -0
- package/plugins/extract-proto/main.go +100 -0
- package/plugins/extract-proto/module.go +120 -0
- package/plugins/extract-proto/options.schema.json +51 -0
- package/plugins/extract-proto/parse.go +720 -0
- package/plugins/extract-proto/parse_test.go +307 -0
- package/plugins/extract-proto/provides.go +236 -0
- package/plugins/extract-proto/resolve.go +222 -0
- package/plugins/extract-proto/resolve_test.go +119 -0
- package/plugins/extract-python-kafka/README.md +36 -0
- package/plugins/extract-python-kafka/extract.py +211 -0
- package/plugins/extract-python-kafka/extract_test.py +68 -0
- package/plugins/extract-python-kafka/main.py +59 -0
- package/plugins/extract-python-kafka/options.py +29 -0
- package/plugins/extract-python-kafka/options.schema.json +31 -0
- package/plugins/extract-redis/README.md +11 -0
- package/plugins/extract-redis/describe.go +19 -0
- package/plugins/extract-redis/describe_test.go +11 -0
- package/plugins/extract-redis/extract.go +183 -0
- package/plugins/extract-redis/extract_test.go +168 -0
- package/plugins/extract-redis/keyspaces.go +469 -0
- package/plugins/extract-redis/main.go +44 -0
- package/plugins/extract-redis/options.schema.json +30 -0
- package/plugins/extract-river/describe.go +19 -0
- package/plugins/extract-river/describe_test.go +11 -0
- package/plugins/extract-river/extract.go +507 -0
- package/plugins/extract-river/extract_test.go +132 -0
- package/plugins/extract-river/main.go +42 -0
- package/plugins/extract-river/options.schema.json +21 -0
- package/plugins/extract-rust/Cargo.lock +133 -0
- package/plugins/extract-rust/Cargo.toml +23 -0
- package/plugins/extract-rust/README.md +204 -0
- package/plugins/extract-rust/options.schema.json +65 -0
- package/plugins/extract-rust/rustfmt.toml +1 -0
- package/plugins/extract-sql/ddl.go +893 -0
- package/plugins/extract-sql/ddl_test.go +401 -0
- package/plugins/extract-sql/describe.go +19 -0
- package/plugins/extract-sql/describe_test.go +11 -0
- package/plugins/extract-sql/layout.go +221 -0
- package/plugins/extract-sql/layout_test.go +55 -0
- package/plugins/extract-sql/lineage.go +107 -0
- package/plugins/extract-sql/main.go +141 -0
- package/plugins/extract-sql/maps.go +564 -0
- package/plugins/extract-sql/maps_java.go +117 -0
- package/plugins/extract-sql/maps_rust.go +333 -0
- package/plugins/extract-sql/maps_rust_test.go +70 -0
- package/plugins/extract-sql/maps_test.go +204 -0
- package/plugins/extract-sql/maps_ts.go +398 -0
- package/plugins/extract-sql/maps_ts_test.go +136 -0
- package/plugins/extract-sql/options.schema.json +53 -0
- package/plugins/extract-sql/projection.go +70 -0
- package/plugins/extract-sql/projection_test.go +50 -0
- package/plugins/extract-sql/store.go +420 -0
- package/plugins/extract-sql/store_test.go +233 -0
- package/plugins/extract-sql/view.go +295 -0
- package/plugins/extract-ts/README.md +306 -0
- package/plugins/extract-ts/ast.test.ts +178 -0
- package/plugins/extract-ts/ast.ts +648 -0
- package/plugins/extract-ts/clients.ts +185 -0
- package/plugins/extract-ts/domain.ts +164 -0
- package/plugins/extract-ts/extract.test.ts +208 -0
- package/plugins/extract-ts/extract.ts +200 -0
- package/plugins/extract-ts/flows.ts +783 -0
- package/plugins/extract-ts/graphql.test.ts +73 -0
- package/plugins/extract-ts/graphql.ts +181 -0
- package/plugins/extract-ts/ids.test.ts +21 -0
- package/plugins/extract-ts/ids.ts +52 -0
- package/plugins/extract-ts/lifecycle.ts +138 -0
- package/plugins/extract-ts/main.ts +48 -0
- package/plugins/extract-ts/openapi.test.ts +64 -0
- package/plugins/extract-ts/openapi.ts +99 -0
- package/plugins/extract-ts/operations.ts +93 -0
- package/plugins/extract-ts/options.schema.json +96 -0
- package/plugins/extract-ts/source.test.ts +174 -0
- package/plugins/extract-ts/source.ts +465 -0
- package/plugins/extract-ts/transport.ts +147 -0
- package/plugins/extract-ts/tsconfig.json +13 -0
- package/plugins/extract-ts/wiring.ts +190 -0
- package/plugins/extract-watermill/describe.go +19 -0
- package/plugins/extract-watermill/describe_test.go +11 -0
- package/plugins/extract-watermill/extract.go +1228 -0
- package/plugins/extract-watermill/extract_test.go +234 -0
- package/plugins/extract-watermill/main.go +41 -0
- package/plugins/extract-watermill/options.schema.json +21 -0
- package/plugins/extract-wsdl/describe.go +19 -0
- package/plugins/extract-wsdl/describe_test.go +11 -0
- package/plugins/extract-wsdl/extract.go +148 -0
- package/plugins/extract-wsdl/extract_test.go +45 -0
- package/plugins/extract-wsdl/main.go +53 -0
- package/plugins/extract-wsdl/options.schema.json +59 -0
- package/plugins/fetch-bsr/auth.go +114 -0
- package/plugins/fetch-bsr/bsr.go +240 -0
- package/plugins/fetch-bsr/cache.go +66 -0
- package/plugins/fetch-bsr/describe.go +19 -0
- package/plugins/fetch-bsr/fetch.go +192 -0
- package/plugins/fetch-bsr/fetch_test.go +465 -0
- package/plugins/fetch-bsr/lock.go +71 -0
- package/plugins/fetch-bsr/main.go +117 -0
- package/plugins/fetch-bsr/options.schema.json +42 -0
- package/plugins/fetch-csr/auth.go +95 -0
- package/plugins/fetch-csr/cache.go +69 -0
- package/plugins/fetch-csr/describe.go +19 -0
- package/plugins/fetch-csr/describe_test.go +11 -0
- package/plugins/fetch-csr/fetch.go +254 -0
- package/plugins/fetch-csr/fetch_test.go +494 -0
- package/plugins/fetch-csr/lock.go +95 -0
- package/plugins/fetch-csr/main.go +122 -0
- package/plugins/fetch-csr/options.schema.json +42 -0
- package/plugins/fetch-csr/registry.go +209 -0
- package/plugins/fetch-git/cache.go +65 -0
- package/plugins/fetch-git/describe.go +19 -0
- package/plugins/fetch-git/describe_test.go +11 -0
- package/plugins/fetch-git/fetch.go +181 -0
- package/plugins/fetch-git/fetch_test.go +332 -0
- package/plugins/fetch-git/git.go +169 -0
- package/plugins/fetch-git/lock.go +72 -0
- package/plugins/fetch-git/main.go +127 -0
- package/plugins/fetch-git/offline.go +39 -0
- package/plugins/fetch-git/options.schema.json +42 -0
- package/plugins/fetch-git/pin.go +90 -0
- package/plugins/fetch-git/pin_test.go +74 -0
- package/plugins/gen-backstage/describe.go +17 -0
- package/plugins/gen-backstage/main.go +22 -0
- package/plugins/gen-backstage/options.schema.json +30 -0
- package/plugins/gen-backstage/plugin.go +473 -0
- package/plugins/gen-backstage/plugin_test.go +145 -0
- package/plugins/gen-backstage.wasm +0 -0
- package/plugins/gen-markdown/adr.go +162 -0
- package/plugins/gen-markdown/aggregate.go +362 -0
- package/plugins/gen-markdown/canonical.go +93 -0
- package/plugins/gen-markdown/context.go +90 -0
- package/plugins/gen-markdown/coverage_test.go +89 -0
- package/plugins/gen-markdown/describe.go +19 -0
- package/plugins/gen-markdown/describe_test.go +11 -0
- package/plugins/gen-markdown/external.go +71 -0
- package/plugins/gen-markdown/flow.go +277 -0
- package/plugins/gen-markdown/glossary.go +76 -0
- package/plugins/gen-markdown/glossary_test.go +148 -0
- package/plugins/gen-markdown/llms.go +302 -0
- package/plugins/gen-markdown/main.go +22 -0
- package/plugins/gen-markdown/markdown.go +254 -0
- package/plugins/gen-markdown/markdown_test.go +100 -0
- package/plugins/gen-markdown/module.go +107 -0
- package/plugins/gen-markdown/options.schema.json +16 -0
- package/plugins/gen-markdown/plugin.go +39 -0
- package/plugins/gen-markdown/quality_test.go +176 -0
- package/plugins/gen-markdown/redis_test.go +38 -0
- package/plugins/gen-markdown/render.go +344 -0
- package/plugins/gen-markdown/render_test.go +186 -0
- package/plugins/gen-markdown/service.go +456 -0
- package/plugins/gen-markdown/source.go +177 -0
- package/plugins/gen-markdown/store.go +201 -0
- package/plugins/gen-markdown.wasm +0 -0
- package/plugins/gen-mermaid/describe.go +17 -0
- package/plugins/gen-mermaid/main.go +22 -0
- package/plugins/gen-mermaid/options.schema.json +10 -0
- package/plugins/gen-mermaid/plugin.go +104 -0
- package/plugins/gen-mermaid/plugin_test.go +33 -0
- package/plugins/gen-mermaid.wasm +0 -0
- package/plugins/openapi/ids.go +261 -0
- package/plugins/openapi/ids_test.go +98 -0
- package/plugins/pyplugin/catalog.py +209 -0
- package/plugins/pyplugin/celery_conf.py +436 -0
- package/plugins/pyplugin/celery_tasks.py +76 -0
- package/plugins/pyplugin/kafka.py +570 -0
- package/plugins/pyplugin/names.py +38 -0
- package/plugins/pyplugin/protocol.py +79 -0
- package/plugins/pyplugin/source.py +285 -0
- package/plugins/verify-codeowners/describe.go +19 -0
- package/plugins/verify-codeowners/describe_test.go +11 -0
- package/plugins/verify-codeowners/main.go +75 -0
- package/plugins/verify-codeowners/match.go +85 -0
- package/plugins/verify-codeowners/match_test.go +47 -0
- package/plugins/verify-codeowners/options.schema.json +15 -0
- package/plugins/verify-codeowners/owners.go +164 -0
- package/plugins/verify-codeowners/owners_test.go +225 -0
- package/plugins/verify-codeowners/parse.go +90 -0
- package/plugins/verify-codeowners/parse_test.go +62 -0
- package/plugins/verify-otel/describe.go +19 -0
- package/plugins/verify-otel/describe_test.go +11 -0
- package/plugins/verify-otel/main.go +53 -0
- package/plugins/verify-otel/match.go +336 -0
- package/plugins/verify-otel/options.schema.json +30 -0
- package/plugins/verify-otel/otlp.go +200 -0
- package/plugins/verify-otel/verify.go +734 -0
- package/plugins/verify-otel/verify_test.go +460 -0
- package/portolan.json +1073 -0
- package/public/favicon.svg +12 -0
- package/schema/portolan.schema.json +2558 -0
- package/scripts/README.md +53 -0
- package/scripts/build-report.mjs +60 -0
- package/scripts/build-report.test.mjs +44 -0
- package/scripts/builtin-plugins.mjs +49 -0
- package/scripts/catalog-sources.mjs +67 -0
- package/scripts/diff.mjs +315 -0
- package/scripts/diff.test.mjs +151 -0
- package/scripts/forge-comment.mjs +144 -0
- package/scripts/forge-comment.test.mjs +151 -0
- package/scripts/forge-release.mjs +138 -0
- package/scripts/forge-release.test.mjs +106 -0
- package/scripts/forge.mjs +61 -0
- package/scripts/gen-likec4.mjs +854 -0
- package/scripts/gen-likec4.test.mjs +258 -0
- package/scripts/gen.mjs +603 -0
- package/scripts/generated-docs.test.mjs +66 -0
- package/scripts/local-api.mjs +1192 -0
- package/scripts/local-api.test.mjs +387 -0
- package/scripts/manifest.mjs +214 -0
- package/scripts/manifest.test.mjs +148 -0
- package/scripts/output-path.mjs +79 -0
- package/scripts/output-path.test.mjs +45 -0
- package/scripts/package-smoke.mjs +37 -0
- package/scripts/plugin-host.mjs +419 -0
- package/scripts/plugin-host.test.mjs +109 -0
- package/scripts/plugin-wasm-worker.mjs +34 -0
- package/scripts/run-builtin.mjs +81 -0
- package/scripts/schema.mjs +357 -0
- package/scripts/site-docs.mjs +295 -0
- package/scripts/site-docs.test.mjs +181 -0
- package/scripts/vendor-lock.mjs +58 -0
- package/scripts/vendor-lock.test.mjs +69 -0
- package/src/README.md +38 -0
- package/src/app/App.tsx +448 -0
- package/src/app/BranchPicker.test.ts +46 -0
- package/src/app/BranchPicker.tsx +153 -0
- package/src/app/Breadcrumbs.test.ts +38 -0
- package/src/app/Breadcrumbs.tsx +223 -0
- package/src/app/BuildStamp.tsx +146 -0
- package/src/app/CommandPalette.tsx +292 -0
- package/src/app/HashScroll.tsx +45 -0
- package/src/app/Sidebar.tsx +1742 -0
- package/src/app/TopBar.tsx +393 -0
- package/src/app/density.tsx +64 -0
- package/src/app/forge-access.test.ts +27 -0
- package/src/app/forge-access.tsx +80 -0
- package/src/app/panels.tsx +141 -0
- package/src/app/pins.tsx +242 -0
- package/src/app/query-client.ts +24 -0
- package/src/app/responsive.ts +55 -0
- package/src/app/shortcuts.test.ts +39 -0
- package/src/app/shortcuts.tsx +282 -0
- package/src/app/theme.tsx +51 -0
- package/src/app/title.test.ts +14 -0
- package/src/app/title.ts +30 -0
- package/src/app/toast.tsx +59 -0
- package/src/app/tree-keys.test.ts +80 -0
- package/src/app/tree-keys.ts +87 -0
- package/src/app/ui-store.ts +52 -0
- package/src/catalog-error.test.ts +105 -0
- package/src/catalog-profile.test.ts +59 -0
- package/src/catalog-profile.ts +101 -0
- package/src/catalog-stores.test.ts +431 -0
- package/src/catalog.test.ts +1215 -0
- package/src/catalog.ts +3125 -0
- package/src/chat/Cards.tsx +408 -0
- package/src/chat/ChatPanel.tsx +79 -0
- package/src/chat/ChatSettings.tsx +219 -0
- package/src/chat/Composer.tsx +99 -0
- package/src/chat/Conversation.tsx +281 -0
- package/src/chat/Header.tsx +46 -0
- package/src/chat/Message.tsx +49 -0
- package/src/chat/Notice.tsx +195 -0
- package/src/chat/Starter.tsx +67 -0
- package/src/chat/Steps.tsx +45 -0
- package/src/chat/Waiting.tsx +87 -0
- package/src/chat/flags.test.ts +59 -0
- package/src/chat/flags.ts +155 -0
- package/src/chat/linkify.test.ts +30 -0
- package/src/chat/linkify.ts +45 -0
- package/src/chat/prefs.ts +56 -0
- package/src/chat/prompt.test.ts +43 -0
- package/src/chat/prompt.ts +157 -0
- package/src/chat/store.ts +35 -0
- package/src/chat/tools.ts +58 -0
- package/src/chat/transport.ts +70 -0
- package/src/components/AdrRow.tsx +29 -0
- package/src/components/AnchorLink.tsx +67 -0
- package/src/components/ApiReference.tsx +134 -0
- package/src/components/AsyncApiReference.tsx +120 -0
- package/src/components/CatalogStamp.tsx +155 -0
- package/src/components/ChannelRows.tsx +132 -0
- package/src/components/CommandRows.tsx +139 -0
- package/src/components/DiagramSkeleton.tsx +71 -0
- package/src/components/EditorLink.tsx +85 -0
- package/src/components/FieldTree.tsx +305 -0
- package/src/components/FlowTrigger.tsx +34 -0
- package/src/components/Ident.tsx +89 -0
- package/src/components/Integrations.tsx +243 -0
- package/src/components/LifecycleDiagram.tsx +110 -0
- package/src/components/MachineDocs.tsx +42 -0
- package/src/components/Markdown.tsx +173 -0
- package/src/components/MarkdownTable.tsx +206 -0
- package/src/components/Mermaid.tsx +211 -0
- package/src/components/MethodRows.tsx +309 -0
- package/src/components/Overlay.tsx +125 -0
- package/src/components/PageHeader.tsx +189 -0
- package/src/components/RowActions.tsx +97 -0
- package/src/components/SchemaDocument.tsx +89 -0
- package/src/components/Select.tsx +126 -0
- package/src/components/ShapeRows.tsx +118 -0
- package/src/components/SourceDoc.tsx +82 -0
- package/src/components/SourcePreview.tsx +441 -0
- package/src/components/TabRow.tsx +182 -0
- package/src/components/TechIcon.tsx +34 -0
- package/src/components/Toc.tsx +132 -0
- package/src/components/WhatLinksHere.tsx +273 -0
- package/src/components/WsdlReference.tsx +84 -0
- package/src/components/ddd-icons.tsx +107 -0
- package/src/components/kind.tsx +157 -0
- package/src/components/logo.tsx +61 -0
- package/src/components/primitives.tsx +264 -0
- package/src/data.test.ts +18 -0
- package/src/data.ts +202 -0
- package/src/enrich.test.ts +1150 -0
- package/src/enrich.ts +672 -0
- package/src/er/ErCanvas.tsx +533 -0
- package/src/er/RedisSchema.tsx +74 -0
- package/src/er/RelationCard.tsx +267 -0
- package/src/er/StoreHeader.tsx +155 -0
- package/src/er/TableNode.tsx +84 -0
- package/src/er/ViewNode.tsx +83 -0
- package/src/er/layout.test.ts +115 -0
- package/src/er/layout.ts +77 -0
- package/src/er/lineage.test.ts +140 -0
- package/src/er/lineage.ts +107 -0
- package/src/er/markers.tsx +79 -0
- package/src/er/spec.test.ts +344 -0
- package/src/er/spec.ts +426 -0
- package/src/flow/ChainList.tsx +162 -0
- package/src/flow/FlowTable.tsx +123 -0
- package/src/flow/FlowToolbar.tsx +372 -0
- package/src/flow/StepDetail.tsx +380 -0
- package/src/flow/StepRail.tsx +428 -0
- package/src/flow/answers.test.ts +50 -0
- package/src/flow/answers.ts +58 -0
- package/src/flow/chain.test.ts +383 -0
- package/src/flow/chain.ts +353 -0
- package/src/flow/chapters.test.ts +185 -0
- package/src/flow/chapters.ts +225 -0
- package/src/flow/continues.test.ts +102 -0
- package/src/flow/continues.ts +65 -0
- package/src/flow/cross-context.test.ts +97 -0
- package/src/flow/cross-context.ts +35 -0
- package/src/flow/mermaid.test.ts +22 -0
- package/src/flow/mermaid.ts +141 -0
- package/src/flow/outline.test.ts +212 -0
- package/src/flow/outline.ts +170 -0
- package/src/flow/paths.test.ts +129 -0
- package/src/flow/paths.ts +147 -0
- package/src/flow/prefs.test.ts +80 -0
- package/src/flow/prefs.ts +104 -0
- package/src/graph/DependencyGraph.tsx +283 -0
- package/src/graph/DependencyNodes.tsx +162 -0
- package/src/graph/EdgeLabel.tsx +61 -0
- package/src/graph/FocusedEventGraph.tsx +211 -0
- package/src/graph/GraphToolbar.tsx +187 -0
- package/src/graph/RoutedEdge.tsx +80 -0
- package/src/graph/dependency-layout.test.ts +360 -0
- package/src/graph/dependency-layout.ts +444 -0
- package/src/graph/elk.test.ts +70 -0
- package/src/graph/elk.ts +287 -0
- package/src/graph/nodes.tsx +97 -0
- package/src/graph/theme.ts +81 -0
- package/src/graph/useElkFlow.ts +125 -0
- package/src/index.css +1547 -0
- package/src/language/InLanguage.tsx +40 -0
- package/src/language/TermCard.tsx +132 -0
- package/src/language/cards.test.ts +114 -0
- package/src/language/cards.ts +111 -0
- package/src/lib/admonition.test.ts +49 -0
- package/src/lib/admonition.ts +48 -0
- package/src/lib/adr.test.ts +131 -0
- package/src/lib/adr.ts +68 -0
- package/src/lib/api.test.ts +122 -0
- package/src/lib/api.ts +135 -0
- package/src/lib/backlinks.test.ts +330 -0
- package/src/lib/backlinks.ts +567 -0
- package/src/lib/branch-compare.ts +16 -0
- package/src/lib/build-info.test.ts +76 -0
- package/src/lib/build-info.ts +80 -0
- package/src/lib/catalog-diff.test.ts +275 -0
- package/src/lib/catalog-diff.ts +655 -0
- package/src/lib/clipboard.ts +43 -0
- package/src/lib/comparison-memory.test.ts +40 -0
- package/src/lib/comparison-memory.ts +39 -0
- package/src/lib/context-color.ts +27 -0
- package/src/lib/context-map.test.ts +148 -0
- package/src/lib/context-map.ts +399 -0
- package/src/lib/data-model.test.ts +245 -0
- package/src/lib/data-model.ts +399 -0
- package/src/lib/data-problems.test.ts +178 -0
- package/src/lib/data-problems.ts +314 -0
- package/src/lib/derive.test.ts +251 -0
- package/src/lib/derive.ts +515 -0
- package/src/lib/editor-link.test.ts +125 -0
- package/src/lib/editor-link.ts +96 -0
- package/src/lib/editor-prefs.ts +27 -0
- package/src/lib/event-graph.test.ts +237 -0
- package/src/lib/event-graph.ts +327 -0
- package/src/lib/export-canvas.ts +37 -0
- package/src/lib/export-file.test.ts +30 -0
- package/src/lib/export-file.ts +20 -0
- package/src/lib/flow-tree.test.ts +177 -0
- package/src/lib/flow-tree.ts +160 -0
- package/src/lib/forge-refs.test.ts +50 -0
- package/src/lib/forge-refs.ts +60 -0
- package/src/lib/format.test.ts +35 -0
- package/src/lib/format.ts +64 -0
- package/src/lib/github-catalog.test.ts +301 -0
- package/src/lib/github-catalog.ts +610 -0
- package/src/lib/integrations.test.ts +119 -0
- package/src/lib/integrations.ts +133 -0
- package/src/lib/kinds.test.ts +91 -0
- package/src/lib/kinds.ts +204 -0
- package/src/lib/lifecycle.test.ts +93 -0
- package/src/lib/lifecycle.ts +165 -0
- package/src/lib/local-api.ts +194 -0
- package/src/lib/motion-features.ts +11 -0
- package/src/lib/motion.test.ts +120 -0
- package/src/lib/motion.tsx +269 -0
- package/src/lib/palette-recent.test.ts +80 -0
- package/src/lib/palette-recent.ts +90 -0
- package/src/lib/palette.test.ts +365 -0
- package/src/lib/palette.ts +593 -0
- package/src/lib/pins.test.ts +139 -0
- package/src/lib/pins.ts +130 -0
- package/src/lib/problems.test.ts +112 -0
- package/src/lib/project-preview.ts +5 -0
- package/src/lib/proto-problems.test.ts +121 -0
- package/src/lib/proto-problems.ts +65 -0
- package/src/lib/queries.test.ts +113 -0
- package/src/lib/queries.ts +131 -0
- package/src/lib/registry.test.ts +219 -0
- package/src/lib/registry.ts +208 -0
- package/src/lib/scenarios.ts +547 -0
- package/src/lib/setup-info.test.ts +199 -0
- package/src/lib/setup-info.ts +415 -0
- package/src/lib/shape.test.ts +289 -0
- package/src/lib/shape.ts +454 -0
- package/src/lib/sidebar-prefs.test.ts +32 -0
- package/src/lib/sidebar-prefs.ts +75 -0
- package/src/lib/source-code.test.ts +159 -0
- package/src/lib/source-code.ts +286 -0
- package/src/lib/source-doc.test.ts +131 -0
- package/src/lib/source-doc.ts +103 -0
- package/src/lib/source-highlight.test.ts +29 -0
- package/src/lib/source-highlight.ts +24 -0
- package/src/lib/source-link.test.ts +153 -0
- package/src/lib/source-link.ts +201 -0
- package/src/lib/spec-files.test.ts +24 -0
- package/src/lib/spec-files.ts +23 -0
- package/src/lib/table-directive.test.ts +139 -0
- package/src/lib/table-directive.ts +106 -0
- package/src/lib/tech.test.ts +120 -0
- package/src/lib/tech.ts +421 -0
- package/src/lib/terms.test.ts +67 -0
- package/src/lib/terms.ts +179 -0
- package/src/lib/wire-problems.test.ts +263 -0
- package/src/lib/wire-problems.ts +281 -0
- package/src/likec4/C4View.tsx +55 -0
- package/src/likec4/CanvasBridge.tsx +187 -0
- package/src/likec4/FlowView.tsx +235 -0
- package/src/likec4/InteractiveView.tsx +144 -0
- package/src/likec4/canvas-viewport.test.ts +149 -0
- package/src/likec4/canvas-viewport.ts +135 -0
- package/src/likec4/flow-edges.test.ts +51 -0
- package/src/likec4/flow-edges.ts +89 -0
- package/src/likec4/frame-theme.test.ts +76 -0
- package/src/likec4/frame-theme.ts +101 -0
- package/src/likec4/highlight-css.test.ts +49 -0
- package/src/likec4/highlight-css.ts +52 -0
- package/src/likec4/ids.test.ts +151 -0
- package/src/likec4/ids.ts +115 -0
- package/src/likec4/levels.tsx +70 -0
- package/src/likec4/mapping.test.ts +66 -0
- package/src/likec4/mapping.ts +54 -0
- package/src/likec4/reserved.json +141 -0
- package/src/likec4/view-index.ts +78 -0
- package/src/main.tsx +13 -0
- package/src/map/ContextMapGraph.tsx +274 -0
- package/src/map/ContextNode.tsx +70 -0
- package/src/map/FloatingEdge.tsx +86 -0
- package/src/merge.test.ts +1038 -0
- package/src/merge.ts +1004 -0
- package/src/pages/AdrDetail.tsx +242 -0
- package/src/pages/AdrIndex.tsx +114 -0
- package/src/pages/AggregatePage.tsx +727 -0
- package/src/pages/BlockPage.tsx +478 -0
- package/src/pages/CatalogFailure.tsx +111 -0
- package/src/pages/Changes.tsx +313 -0
- package/src/pages/ContextMap.tsx +534 -0
- package/src/pages/ContextPage.tsx +346 -0
- package/src/pages/EnumPage.tsx +282 -0
- package/src/pages/EventPage.tsx +686 -0
- package/src/pages/ExternalPage.tsx +204 -0
- package/src/pages/FlowDetail.tsx +663 -0
- package/src/pages/FlowIndex.tsx +303 -0
- package/src/pages/GraphPage.tsx +217 -0
- package/src/pages/Language.tsx +257 -0
- package/src/pages/ModulePage.tsx +366 -0
- package/src/pages/NotFound.tsx +54 -0
- package/src/pages/Overview.tsx +344 -0
- package/src/pages/Problems.tsx +360 -0
- package/src/pages/RegistryIndex.tsx +118 -0
- package/src/pages/ServicePage.tsx +746 -0
- package/src/pages/Settings.tsx +975 -0
- package/src/pages/StorePage.tsx +114 -0
- package/src/peek/PeekCard.test.ts +35 -0
- package/src/peek/PeekCard.tsx +118 -0
- package/src/peek/PeekLayer.tsx +147 -0
- package/src/peek/model.test.ts +156 -0
- package/src/peek/model.ts +253 -0
- package/src/routes.test.ts +222 -0
- package/src/routes.ts +449 -0
- package/src/selection/DetailPanel.tsx +1407 -0
- package/src/selection/hash.test.ts +73 -0
- package/src/selection/hash.ts +58 -0
- package/src/selection/model.test.ts +199 -0
- package/src/selection/model.ts +473 -0
- package/src/selection/pages.test.ts +115 -0
- package/src/selection/pages.ts +268 -0
- package/src/selection/store.test.ts +62 -0
- package/src/selection/store.ts +46 -0
- package/src/selection/sync.tsx +99 -0
- package/src/table/ColumnsMenu.tsx +72 -0
- package/src/table/DataTable.tsx +780 -0
- package/src/table/Facets.tsx +54 -0
- package/src/table/GroupMenu.tsx +69 -0
- package/src/table/Toolbar.tsx +190 -0
- package/src/table/cells.tsx +117 -0
- package/src/table/compare.test.ts +117 -0
- package/src/table/compare.ts +196 -0
- package/src/table/export.test.ts +88 -0
- package/src/table/export.ts +66 -0
- package/src/table/facet-groups.test.ts +74 -0
- package/src/table/facet-groups.ts +56 -0
- package/src/table/grouping.test.ts +84 -0
- package/src/table/grouping.ts +82 -0
- package/src/table/infer.test.ts +57 -0
- package/src/table/infer.ts +50 -0
- package/src/table/persist.test.ts +76 -0
- package/src/table/persist.ts +112 -0
- package/src/table/sort-url.test.ts +75 -0
- package/src/table/sort-url.ts +52 -0
- package/src/table/types.ts +80 -0
- package/src/table/useTableState.ts +220 -0
- package/src/test-catalog.ts +7 -0
- package/src/testing/estate/data__catalog.json +2847 -0
- package/src/testing/estate/data__flows.json +1724 -0
- package/src/testing/estate/examples__auth__portolan__api.json +212 -0
- package/src/testing/estate/examples__auth__portolan__domain.json +1204 -0
- package/src/testing/estate/examples__auth__portolan__glossary.json +226 -0
- package/src/testing/estate/examples__auth__portolan__observed.json +757 -0
- package/src/testing/estate/examples__auth__portolan__stores.json +195 -0
- package/src/testing/estate/examples__shop__cart__portolan__api.json +234 -0
- package/src/testing/estate/examples__shop__cart__portolan__commands.json +86 -0
- package/src/testing/estate/examples__shop__cart__portolan__domain.json +966 -0
- package/src/testing/estate/examples__shop__cart__portolan__observed.json +498 -0
- package/src/testing/estate/examples__shop__cart__portolan__stores.json +208 -0
- package/src/testing/estate/examples__shop__oms__portolan__glossary.json +98 -0
- package/src/testing/estate/examples__shop__oms__portolan__proto.json +186 -0
- package/src/testing/estate.ts +49 -0
- package/src/trail/Trail.tsx +81 -0
- package/src/trail/model.test.ts +157 -0
- package/src/trail/model.ts +189 -0
- package/src/trail/record.tsx +32 -0
- package/src/trail/store.test.ts +66 -0
- package/src/trail/store.ts +102 -0
- package/tsconfig.json +35 -0
- package/vite.config.ts +171 -0
|
@@ -0,0 +1,428 @@
|
|
|
1
|
+
import { useEffect, useId, useRef } from "react";
|
|
2
|
+
import { Link } from "react-router";
|
|
3
|
+
import { LayoutGroup, m, transitions } from "../lib/motion";
|
|
4
|
+
import {
|
|
5
|
+
ArrowRight,
|
|
6
|
+
ChevronDown,
|
|
7
|
+
ChevronRight,
|
|
8
|
+
CornerDownLeft,
|
|
9
|
+
CornerDownRight,
|
|
10
|
+
} from "lucide-react";
|
|
11
|
+
import type { Step } from "../catalog";
|
|
12
|
+
import { STATUSES } from "../catalog";
|
|
13
|
+
import { contextName, ctxStyle } from "../lib/context-color";
|
|
14
|
+
import { paths } from "../routes";
|
|
15
|
+
import { statusVar } from "../components/primitives";
|
|
16
|
+
import { railRows } from "./chapters";
|
|
17
|
+
import type { Chapter, ChapterGroup } from "./chapters";
|
|
18
|
+
import type { Continuation } from "./continues";
|
|
19
|
+
import type { OutlineFrame, OutlineStep } from "./outline";
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* A chapter header. The one row on the rail that is a control rather than a
|
|
25
|
+
* reading: it folds its own steps away and nothing else — the canvas keeps
|
|
26
|
+
* drawing them, because a chapter is how the reader is walking the list, not a
|
|
27
|
+
* claim about what the flow does.
|
|
28
|
+
*/
|
|
29
|
+
function ChapterRow({
|
|
30
|
+
chapter,
|
|
31
|
+
collapsed,
|
|
32
|
+
onToggle,
|
|
33
|
+
}: {
|
|
34
|
+
chapter: Chapter;
|
|
35
|
+
collapsed: boolean;
|
|
36
|
+
onToggle: () => void;
|
|
37
|
+
}) {
|
|
38
|
+
const Chevron = collapsed ? ChevronRight : ChevronDown;
|
|
39
|
+
const range =
|
|
40
|
+
chapter.from === chapter.to
|
|
41
|
+
? `${chapter.from}`
|
|
42
|
+
: `${chapter.from}–${chapter.to}`;
|
|
43
|
+
return (
|
|
44
|
+
<button
|
|
45
|
+
type="button"
|
|
46
|
+
onClick={onToggle}
|
|
47
|
+
aria-expanded={!collapsed}
|
|
48
|
+
className="chapter-row"
|
|
49
|
+
title={
|
|
50
|
+
collapsed
|
|
51
|
+
? `Show steps ${range} — ${chapter.title}`
|
|
52
|
+
: `Hide steps ${range} — ${chapter.title}`
|
|
53
|
+
}
|
|
54
|
+
>
|
|
55
|
+
{/* This header stands in for the frame's own opening row, so the one
|
|
56
|
+
thing that row would have shouted has to be shouted here too. */}
|
|
57
|
+
{chapter.terminal ? (
|
|
58
|
+
<CornerDownRight
|
|
59
|
+
size={10}
|
|
60
|
+
aria-hidden
|
|
61
|
+
className="shrink-0"
|
|
62
|
+
style={{ color: "var(--status-unresolved)" }}
|
|
63
|
+
/>
|
|
64
|
+
) : null}
|
|
65
|
+
<Chevron size={12} aria-hidden className="shrink-0 text-muted" />
|
|
66
|
+
{chapter.kind === "steps" ? null : (
|
|
67
|
+
<span className="mono shrink-0 rounded-[4px] border px-1 uppercase border-line-strong text-muted">
|
|
68
|
+
{chapter.kind}
|
|
69
|
+
</span>
|
|
70
|
+
)}
|
|
71
|
+
<span className="mono min-w-0 flex-1 truncate text-ink" title={chapter.title}>
|
|
72
|
+
{chapter.title}
|
|
73
|
+
</span>
|
|
74
|
+
{/* The contexts this episode touches, as colour and nothing else: the
|
|
75
|
+
rail has no room for three names, and the names are one hover away. */}
|
|
76
|
+
<span className="flex shrink-0 items-center gap-0.5">
|
|
77
|
+
{chapter.contexts.map((id) => (
|
|
78
|
+
<span
|
|
79
|
+
key={id}
|
|
80
|
+
aria-hidden
|
|
81
|
+
className="size-1.5 rounded-[1px] ctx"
|
|
82
|
+
style={{ ...ctxStyle(id), background: "var(--ctx)" }}
|
|
83
|
+
title={contextName(id)}
|
|
84
|
+
/>
|
|
85
|
+
))}
|
|
86
|
+
</span>
|
|
87
|
+
{/* Status as a count per colour rather than one dot per step: a chapter
|
|
88
|
+
of twelve steps would otherwise be a bar chart nobody asked for. */}
|
|
89
|
+
<span className="mono flex shrink-0 items-center gap-1 text-muted">
|
|
90
|
+
{STATUSES.filter((status) => chapter.status[status] > 0).map(
|
|
91
|
+
(status) => (
|
|
92
|
+
<span key={status} className="flex items-center gap-0.5" title={status}>
|
|
93
|
+
<span
|
|
94
|
+
aria-hidden
|
|
95
|
+
className="size-1.5 rounded-[1px]"
|
|
96
|
+
style={{ background: statusVar(status) }}
|
|
97
|
+
/>
|
|
98
|
+
<span className="tnum">{chapter.status[status]}</span>
|
|
99
|
+
</span>
|
|
100
|
+
),
|
|
101
|
+
)}
|
|
102
|
+
</span>
|
|
103
|
+
<span className="mono tnum shrink-0 text-faint">{range}</span>
|
|
104
|
+
</button>
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* A frame header. It is deliberately not a button: the frame is context for the
|
|
110
|
+
* steps under it, not something you can select, and making it clickable would
|
|
111
|
+
* put a second kind of selection on the rail.
|
|
112
|
+
*/
|
|
113
|
+
function FrameRow({ frame }: { frame: OutlineFrame }) {
|
|
114
|
+
const choice = frame.keyword === "alt" || frame.keyword === "else";
|
|
115
|
+
return (
|
|
116
|
+
<div
|
|
117
|
+
className="px-2 py-1"
|
|
118
|
+
style={{
|
|
119
|
+
paddingLeft: 8 + frame.depth * 10,
|
|
120
|
+
background: "color-mix(in srgb, var(--fg) 3%, transparent)",
|
|
121
|
+
opacity: frame.offPath ? 0.35 : 1,
|
|
122
|
+
}}
|
|
123
|
+
>
|
|
124
|
+
<div className="flex items-baseline gap-1.5">
|
|
125
|
+
<span
|
|
126
|
+
className="mono shrink-0 rounded-[4px] border px-1 uppercase"
|
|
127
|
+
style={{
|
|
128
|
+
borderColor: choice ? "var(--border-strong)" : "var(--border)",
|
|
129
|
+
color: choice ? "var(--fg)" : "var(--fg-muted)",
|
|
130
|
+
}}
|
|
131
|
+
>
|
|
132
|
+
{frame.keyword}
|
|
133
|
+
</span>
|
|
134
|
+
{frame.title ? (
|
|
135
|
+
<span
|
|
136
|
+
className="mono min-w-0 flex-1 truncate text-muted"
|
|
137
|
+
title={frame.title}
|
|
138
|
+
>
|
|
139
|
+
{frame.title}
|
|
140
|
+
</span>
|
|
141
|
+
) : null}
|
|
142
|
+
</div>
|
|
143
|
+
{/* On its own line: a branch that ends the flow is the whole reason the
|
|
144
|
+
rail draws frames at all, and it must not be what the title truncates
|
|
145
|
+
away in a narrow rail. */}
|
|
146
|
+
{frame.terminal ? (
|
|
147
|
+
<div
|
|
148
|
+
className="mono mt-0.5 flex items-center gap-1"
|
|
149
|
+
style={{ color: "var(--status-unresolved)" }}
|
|
150
|
+
title="This branch ends the flow — the steps after this alt do not follow it"
|
|
151
|
+
>
|
|
152
|
+
<CornerDownRight size={9} aria-hidden className="shrink-0" />
|
|
153
|
+
ends the flow — nothing below follows it
|
|
154
|
+
</div>
|
|
155
|
+
) : null}
|
|
156
|
+
</div>
|
|
157
|
+
);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Where a step leaves the context it was in. This is the first thing the eye
|
|
162
|
+
* should catch on the rail: every other fact about a step is local to the
|
|
163
|
+
* service that runs it, and this one is the only one that is somebody else's
|
|
164
|
+
* problem.
|
|
165
|
+
*/
|
|
166
|
+
function CrossChip({ step, context }: { step: Step; context: string | null }) {
|
|
167
|
+
const label = context ? contextName(context) : step.to;
|
|
168
|
+
return (
|
|
169
|
+
<span
|
|
170
|
+
className="chip shrink-0 ctx"
|
|
171
|
+
style={context ? ctxStyle(context) : { borderColor: "var(--border-strong)" }}
|
|
172
|
+
title={`crosses into ${label}`}
|
|
173
|
+
>
|
|
174
|
+
→ {label}
|
|
175
|
+
</span>
|
|
176
|
+
);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
function StepRow({
|
|
180
|
+
row,
|
|
181
|
+
answer,
|
|
182
|
+
active,
|
|
183
|
+
dimmed,
|
|
184
|
+
onSelect,
|
|
185
|
+
onHover,
|
|
186
|
+
crossContext,
|
|
187
|
+
continuations,
|
|
188
|
+
full,
|
|
189
|
+
}: {
|
|
190
|
+
row: OutlineStep;
|
|
191
|
+
/** What the callee hands back, when a contract says. */
|
|
192
|
+
answer?: string | undefined;
|
|
193
|
+
active: boolean;
|
|
194
|
+
dimmed: boolean;
|
|
195
|
+
onSelect: (id: string) => void;
|
|
196
|
+
onHover: (id: string | null) => void;
|
|
197
|
+
/** The context this step crosses into, or undefined when it stays home. */
|
|
198
|
+
crossContext?: string | null | undefined;
|
|
199
|
+
continuations: readonly Continuation[];
|
|
200
|
+
full?: boolean;
|
|
201
|
+
}) {
|
|
202
|
+
const { step, number, depth, hidden, offPath, offStatus } = row;
|
|
203
|
+
const self = step.from === step.to;
|
|
204
|
+
const crosses = crossContext !== undefined;
|
|
205
|
+
return (
|
|
206
|
+
<div
|
|
207
|
+
onMouseEnter={() => onHover(step.id)}
|
|
208
|
+
onMouseLeave={() => onHover(null)}
|
|
209
|
+
style={{ opacity: dimmed || offPath || offStatus ? 0.3 : 1 }}
|
|
210
|
+
>
|
|
211
|
+
<button
|
|
212
|
+
type="button"
|
|
213
|
+
data-nav-item
|
|
214
|
+
onClick={() => onSelect(step.id)}
|
|
215
|
+
/* Focus lights the canvas arrow the way hover does: j and k walk the
|
|
216
|
+
rail, and the reader walking it should see where each step goes. */
|
|
217
|
+
onFocus={() => onHover(step.id)}
|
|
218
|
+
onBlur={() => onHover(null)}
|
|
219
|
+
/* Playback dims and undims at the narrative tier - the reader is meant to
|
|
220
|
+
watch the sequence recede, not to be blinked at. The edge is always
|
|
221
|
+
2px and transparent, so lighting a step never nudges the text beside
|
|
222
|
+
it; the light itself is the one element below, which slides from the
|
|
223
|
+
step it was on to this one. `isolate` keeps its -z under the text but
|
|
224
|
+
above the rail. */
|
|
225
|
+
className="relative isolate flex w-full items-start gap-2 px-2 py-1.5 text-left t-narrative hover:bg-surface"
|
|
226
|
+
style={{
|
|
227
|
+
borderLeftWidth: 2,
|
|
228
|
+
borderLeftStyle: "solid",
|
|
229
|
+
borderLeftColor: "transparent",
|
|
230
|
+
paddingLeft: 8 + depth * 10,
|
|
231
|
+
}}
|
|
232
|
+
aria-current={active ? "true" : undefined}
|
|
233
|
+
>
|
|
234
|
+
{active ? (
|
|
235
|
+
<m.span
|
|
236
|
+
layoutId="active-step"
|
|
237
|
+
aria-hidden
|
|
238
|
+
className="pointer-events-none absolute inset-y-0 right-0 -left-0.5 -z-10 border-l-2 border-accent bg-raised"
|
|
239
|
+
transition={transitions.settle}
|
|
240
|
+
/>
|
|
241
|
+
) : null}
|
|
242
|
+
<span
|
|
243
|
+
className={`mono w-5 shrink-0 text-right t-micro transition-colors ${active ? "text-accent" : "text-muted"}`}
|
|
244
|
+
>
|
|
245
|
+
{number}
|
|
246
|
+
</span>
|
|
247
|
+
<span className="min-w-0 flex-1">
|
|
248
|
+
<span className="mono flex items-baseline gap-1">
|
|
249
|
+
{/* No flex-1 here: a basis of zero makes shrinking proportional
|
|
250
|
+
to nothing, and the label collapses before the answer gives up
|
|
251
|
+
a character. Both sit on their content and the answer, weighted
|
|
252
|
+
to give way ten times faster, is the one that loses. */}
|
|
253
|
+
<span
|
|
254
|
+
className="min-w-0 truncate text-ink"
|
|
255
|
+
title={step.label ?? step.ref ?? step.kind}
|
|
256
|
+
>
|
|
257
|
+
{step.label ?? step.ref ?? step.kind}
|
|
258
|
+
</span>
|
|
259
|
+
{/* The reply is not a step of its own - it is the far end of this
|
|
260
|
+
one - so it is read on the same line, and only where a contract
|
|
261
|
+
says what comes back. */}
|
|
262
|
+
{/* Only where there is room for it: two truncated halves read
|
|
263
|
+
worse than one whole label, so on a rail dragged narrow the
|
|
264
|
+
answer steps aside and the step's own panel still says it. */}
|
|
265
|
+
{answer ? (
|
|
266
|
+
<span
|
|
267
|
+
className={`min-w-0 shrink-[10] truncate text-muted ${full ? "" : "hidden @[16rem]:inline"}`}
|
|
268
|
+
title={`answers with ${answer}`}
|
|
269
|
+
>
|
|
270
|
+
→ {answer}
|
|
271
|
+
</span>
|
|
272
|
+
) : null}
|
|
273
|
+
</span>
|
|
274
|
+
{/* Two ids on one line in a rail the reader can drag down to a
|
|
275
|
+
quarter of the pane. Both are cut from the left, so what survives
|
|
276
|
+
is the end that differs. */}
|
|
277
|
+
<span className="mono flex items-center gap-1 text-muted">
|
|
278
|
+
<span className="trunc-tail" title={step.from}>
|
|
279
|
+
<bdi>{step.from}</bdi>
|
|
280
|
+
</span>
|
|
281
|
+
{self ? (
|
|
282
|
+
<CornerDownLeft size={12} aria-hidden className="shrink-0" />
|
|
283
|
+
) : (
|
|
284
|
+
<ArrowRight size={12} aria-hidden className="shrink-0" />
|
|
285
|
+
)}
|
|
286
|
+
<span className="trunc-tail" title={step.to}>
|
|
287
|
+
<bdi>{step.to}</bdi>
|
|
288
|
+
</span>
|
|
289
|
+
</span>
|
|
290
|
+
</span>
|
|
291
|
+
{full ? (
|
|
292
|
+
<span className="mono shrink-0 text-muted">{step.kind}</span>
|
|
293
|
+
) : null}
|
|
294
|
+
{crosses ? <CrossChip step={step} context={crossContext} /> : null}
|
|
295
|
+
{hidden ? (
|
|
296
|
+
<span
|
|
297
|
+
className="mono shrink-0 text-muted"
|
|
298
|
+
title="hidden by the cross-context filter"
|
|
299
|
+
>
|
|
300
|
+
·
|
|
301
|
+
</span>
|
|
302
|
+
) : null}
|
|
303
|
+
{/* Last, and always last: the status dot is the column the eye runs
|
|
304
|
+
down when it is asking one question of forty steps at once. */}
|
|
305
|
+
<span
|
|
306
|
+
aria-hidden
|
|
307
|
+
className="mt-1 size-1.5 shrink-0 rounded-[1px]"
|
|
308
|
+
style={{ background: statusVar(step.status) }}
|
|
309
|
+
title={step.status}
|
|
310
|
+
/>
|
|
311
|
+
</button>
|
|
312
|
+
{/* Where this step hands the story over. Outside the button because it is
|
|
313
|
+
a different destination from the step's own selection, and nesting a
|
|
314
|
+
link inside a button is not a thing the DOM allows. */}
|
|
315
|
+
{continuations.map((next) => (
|
|
316
|
+
<Link
|
|
317
|
+
key={next.slug}
|
|
318
|
+
to={paths.flow(next.slug)}
|
|
319
|
+
className="mono flex items-center gap-1 py-0.5 pr-2 text-accent hover:underline"
|
|
320
|
+
style={{ paddingLeft: 8 + depth * 10 + 28 }}
|
|
321
|
+
title={`this event opens ${next.name}`}
|
|
322
|
+
>
|
|
323
|
+
<CornerDownRight size={9} aria-hidden className="shrink-0" />
|
|
324
|
+
continues in {next.name}
|
|
325
|
+
</Link>
|
|
326
|
+
))}
|
|
327
|
+
</div>
|
|
328
|
+
);
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
export function StepRail({
|
|
332
|
+
groups,
|
|
333
|
+
answers,
|
|
334
|
+
activeId,
|
|
335
|
+
matchIds,
|
|
336
|
+
collapsed,
|
|
337
|
+
onToggleChapter,
|
|
338
|
+
onSelect,
|
|
339
|
+
onHover,
|
|
340
|
+
crossContextOf,
|
|
341
|
+
continuations,
|
|
342
|
+
full,
|
|
343
|
+
}: {
|
|
344
|
+
/** The rail's rows, already cut into chapters. */
|
|
345
|
+
groups: readonly ChapterGroup[];
|
|
346
|
+
/** What each step's callee hands back, by step id; see flow/answers.ts. */
|
|
347
|
+
answers: ReadonlyMap<string, string>;
|
|
348
|
+
/** The step the rail marks and scrolls to. */
|
|
349
|
+
activeId: string | null;
|
|
350
|
+
/**
|
|
351
|
+
* When set, only these steps read at full strength. Used when an event is
|
|
352
|
+
* selected somewhere else: every step that carries it stays lit, and the
|
|
353
|
+
* rest of the sequence recedes.
|
|
354
|
+
*/
|
|
355
|
+
matchIds?: ReadonlySet<string> | null;
|
|
356
|
+
collapsed: ReadonlySet<string>;
|
|
357
|
+
onToggleChapter: (chapterId: string) => void;
|
|
358
|
+
onSelect: (id: string) => void;
|
|
359
|
+
/** Hovering a step lights its arrow on the canvas, and nothing else. */
|
|
360
|
+
onHover: (id: string | null) => void;
|
|
361
|
+
/** The context a step crosses into; undefined for a step that crosses none. */
|
|
362
|
+
crossContextOf: (step: Step) => string | null | undefined;
|
|
363
|
+
continuations: ReadonlyMap<string, Continuation[]>;
|
|
364
|
+
full?: boolean;
|
|
365
|
+
}) {
|
|
366
|
+
const listRef = useRef<HTMLDivElement | null>(null);
|
|
367
|
+
// Namespaces the light's layoutId to this rail, for a screen with two.
|
|
368
|
+
const railId = useId();
|
|
369
|
+
|
|
370
|
+
useEffect(() => {
|
|
371
|
+
if (!activeId || !listRef.current) return;
|
|
372
|
+
const el = listRef.current.querySelector<HTMLElement>(
|
|
373
|
+
`[data-step="${CSS.escape(activeId)}"]`,
|
|
374
|
+
);
|
|
375
|
+
el?.scrollIntoView({ block: "nearest" });
|
|
376
|
+
}, [activeId]);
|
|
377
|
+
|
|
378
|
+
return (
|
|
379
|
+
/* `data-nav-list`: j / k walk the steps and ⏎ selects the one under the
|
|
380
|
+
cursor, the same keys that walk every table. Chapter and frame rows are
|
|
381
|
+
not items - a chapter folds, it is not somewhere to stand. */
|
|
382
|
+
// A container so a row can ask how wide the rail is: the reader drags it,
|
|
383
|
+
// and what fits at half a pane does not fit at a quarter.
|
|
384
|
+
<div ref={listRef} data-nav-list className="@container">
|
|
385
|
+
<LayoutGroup id={railId}>
|
|
386
|
+
{groups.map((group) => {
|
|
387
|
+
const { chapter } = group;
|
|
388
|
+
const rows = railRows(group);
|
|
389
|
+
const folded = collapsed.has(chapter.id);
|
|
390
|
+
return (
|
|
391
|
+
<section key={chapter.id}>
|
|
392
|
+
<ChapterRow
|
|
393
|
+
chapter={chapter}
|
|
394
|
+
collapsed={folded}
|
|
395
|
+
onToggle={() => onToggleChapter(chapter.id)}
|
|
396
|
+
/>
|
|
397
|
+
{folded ? null : (
|
|
398
|
+
<ul className="divide-y divide-line">
|
|
399
|
+
{rows.map((row) =>
|
|
400
|
+
row.type === "frame" ? (
|
|
401
|
+
<li key={row.key}>
|
|
402
|
+
<FrameRow frame={row} />
|
|
403
|
+
</li>
|
|
404
|
+
) : (
|
|
405
|
+
<li key={row.key} data-step={row.step.id}>
|
|
406
|
+
<StepRow
|
|
407
|
+
row={row}
|
|
408
|
+
answer={answers.get(row.step.id)}
|
|
409
|
+
active={activeId === row.step.id}
|
|
410
|
+
dimmed={matchIds ? !matchIds.has(row.step.id) : false}
|
|
411
|
+
onSelect={onSelect}
|
|
412
|
+
onHover={onHover}
|
|
413
|
+
crossContext={crossContextOf(row.step)}
|
|
414
|
+
continuations={continuations.get(row.step.id) ?? []}
|
|
415
|
+
full={full}
|
|
416
|
+
/>
|
|
417
|
+
</li>
|
|
418
|
+
),
|
|
419
|
+
)}
|
|
420
|
+
</ul>
|
|
421
|
+
)}
|
|
422
|
+
</section>
|
|
423
|
+
);
|
|
424
|
+
})}
|
|
425
|
+
</LayoutGroup>
|
|
426
|
+
</div>
|
|
427
|
+
);
|
|
428
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { catalog, index } from "../data";
|
|
3
|
+
import { walkSteps } from "../catalog";
|
|
4
|
+
import { flowAnswers, stepAnswer } from "./answers";
|
|
5
|
+
|
|
6
|
+
const flow = (slug: string) => {
|
|
7
|
+
const found = catalog.flows.find((f) => f.slug === slug);
|
|
8
|
+
if (!found) throw new Error(`no flow ${slug}`);
|
|
9
|
+
return found;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
const step = (slug: string, id: string) => {
|
|
13
|
+
const found = walkSteps(flow(slug).steps).find((s) => s.id === id);
|
|
14
|
+
if (!found) throw new Error(`no step ${id} in ${slug}`);
|
|
15
|
+
return found;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
describe("stepAnswer", () => {
|
|
19
|
+
it("reads the answer of an endpoint off the document that declares it", () => {
|
|
20
|
+
// billing's ViewSet is exposed by billing.v1.Invoices, and the document
|
|
21
|
+
// says a void answers 204 and an issue answers with the invoice's id.
|
|
22
|
+
expect(stepAnswer(index, step("billing-invoice-destroy", "s1"))).toBe("204");
|
|
23
|
+
expect(stepAnswer(index, step("billing-invoice-issue", "s1"))).toBe(
|
|
24
|
+
"InvoiceId",
|
|
25
|
+
);
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
it("reads the answer of a call to another service off the callee's contract", () => {
|
|
29
|
+
expect(stepAnswer(index, step("cart-checkout", "s2"))).toBe("SessionInfo");
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it("has none for a hop no interface describes", () => {
|
|
33
|
+
// A call lands inside a service - a repository, a queryset - and an event
|
|
34
|
+
// is a publication. Neither has a reply to read.
|
|
35
|
+
for (const s of walkSteps(flow("billing-invoice-destroy").steps)) {
|
|
36
|
+
if (s.kind !== "rpc") expect(stepAnswer(index, s), s.id).toBeUndefined();
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it("collects a flow's answers by step id", () => {
|
|
41
|
+
// Three, now that pricing is a service rather than a hand-written entry:
|
|
42
|
+
// its contract says what a quote comes back as.
|
|
43
|
+
const answers = flowAnswers(index, flow("cart-checkout"));
|
|
44
|
+
expect([...answers.entries()].sort()).toEqual([
|
|
45
|
+
["s1", "CheckedOut"],
|
|
46
|
+
["s2", "SessionInfo"],
|
|
47
|
+
["s4", "GetQuoteResponse"],
|
|
48
|
+
]);
|
|
49
|
+
});
|
|
50
|
+
});
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
// What comes back from a call, when a contract says.
|
|
2
|
+
//
|
|
3
|
+
// The catalog records hops - a call was made, an event was published - and
|
|
4
|
+
// never a reply: a reply is not a second thing that happened, it is the far end
|
|
5
|
+
// of the same one. But a reader of a sequence still wants to see what the far
|
|
6
|
+
// end hands over, and for an rpc the answer is already written down twice over:
|
|
7
|
+
// in the proto that declares the method, and in the OpenAPI document that
|
|
8
|
+
// declares the operation. So it is looked up rather than recorded, and a step
|
|
9
|
+
// whose method nobody in the catalog provides simply has no answer to draw.
|
|
10
|
+
//
|
|
11
|
+
// Only an rpc has one. A `call` lands inside a service - a repository, a
|
|
12
|
+
// queryset - which no interface in the catalog describes; an event is a
|
|
13
|
+
// publication, and drawing a reply to it would be a lie about the bus.
|
|
14
|
+
|
|
15
|
+
import type { CatalogIndex, Flow, RpcMethod, Step } from "../catalog";
|
|
16
|
+
import { walkSteps } from "../catalog";
|
|
17
|
+
|
|
18
|
+
/** The method a step reaches, when the catalog has it. */
|
|
19
|
+
function methodOf(index: CatalogIndex, step: Step): RpcMethod | undefined {
|
|
20
|
+
if (step.kind !== "rpc") return undefined;
|
|
21
|
+
|
|
22
|
+
// Outgoing: the step names the call, and the call id is `<interface>/<method>`.
|
|
23
|
+
if (step.ref) {
|
|
24
|
+
const cut = step.ref.lastIndexOf("/");
|
|
25
|
+
if (cut < 0) return undefined;
|
|
26
|
+
const [interfaceId, name] = [step.ref.slice(0, cut), step.ref.slice(cut + 1)];
|
|
27
|
+
// A service of ours, or a system outside the estate whose vendored
|
|
28
|
+
// document names the operation: what comes back is written down either way.
|
|
29
|
+
const provider =
|
|
30
|
+
index.rpcProviderByMethod.get(step.ref) ?? index.externalProviderByMethod.get(step.ref);
|
|
31
|
+
const provided = provider?.provides.find((p) => p.id === interfaceId);
|
|
32
|
+
return provided?.methods.find((m) => m.name === name);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Incoming: somebody called this service, and the label is the operation.
|
|
36
|
+
const service = index.serviceById.get(step.to);
|
|
37
|
+
if (!service || !step.label) return undefined;
|
|
38
|
+
for (const provided of service.provides) {
|
|
39
|
+
const found = provided.methods.find((m) => m.name === step.label);
|
|
40
|
+
if (found) return found;
|
|
41
|
+
}
|
|
42
|
+
return undefined;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/** What the callee hands back, as the contract names it. */
|
|
46
|
+
export function stepAnswer(index: CatalogIndex, step: Step): string | undefined {
|
|
47
|
+
return methodOf(index, step)?.response || undefined;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/** Every step of a flow that has one, by step id. */
|
|
51
|
+
export function flowAnswers(index: CatalogIndex, flow: Flow): Map<string, string> {
|
|
52
|
+
const out = new Map<string, string>();
|
|
53
|
+
for (const step of walkSteps(flow.steps)) {
|
|
54
|
+
const answer = stepAnswer(index, step);
|
|
55
|
+
if (answer) out.set(step.id, answer);
|
|
56
|
+
}
|
|
57
|
+
return out;
|
|
58
|
+
}
|