@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,746 @@
|
|
|
1
|
+
import { useState } from "react";
|
|
2
|
+
import { TabGroup, TabList, TabPanel, TabPanels } from "@headlessui/react";
|
|
3
|
+
import { Link, useParams, useSearchParams } from "react-router";
|
|
4
|
+
import { catalog } from "../data";
|
|
5
|
+
import {
|
|
6
|
+
allRepos,
|
|
7
|
+
commandsOf,
|
|
8
|
+
componentKind,
|
|
9
|
+
ownersOf,
|
|
10
|
+
technologiesOf,
|
|
11
|
+
} from "../catalog";
|
|
12
|
+
import { flowRoles } from "../lib/derive";
|
|
13
|
+
import { treeHref } from "../lib/source-link";
|
|
14
|
+
import { flowHealth } from "../lib/flow-tree";
|
|
15
|
+
import { adrsForService, isCurrent } from "../lib/adr";
|
|
16
|
+
import { ADR_ROW_COLUMNS, AdrRow } from "../components/AdrRow";
|
|
17
|
+
import { EVENT_ANCHOR, SERVICE_ANCHOR, aggregatePath, paths } from "../routes";
|
|
18
|
+
import { Markdown } from "../components/Markdown";
|
|
19
|
+
import { middleTruncate, plural } from "../lib/format";
|
|
20
|
+
import { Empty, PageHeader, SectionTitle } from "../components/PageHeader";
|
|
21
|
+
import { Ident } from "../components/Ident";
|
|
22
|
+
import { TabButton, TabCount, TabRow } from "../components/TabRow";
|
|
23
|
+
import { MessageList, MethodRows } from "../components/MethodRows";
|
|
24
|
+
import { docPathOf, pickSpec } from "../lib/source-doc";
|
|
25
|
+
import { ApiReference, hasSpec } from "../components/ApiReference";
|
|
26
|
+
import { WsdlReference } from "../components/WsdlReference";
|
|
27
|
+
import { Integrations } from "../components/Integrations";
|
|
28
|
+
import { integrationsFor } from "../lib/integrations";
|
|
29
|
+
import {
|
|
30
|
+
AsyncApiReference,
|
|
31
|
+
hasAsyncSpec,
|
|
32
|
+
} from "../components/AsyncApiReference";
|
|
33
|
+
import { ChannelRows } from "../components/ChannelRows";
|
|
34
|
+
import { CommandRows } from "../components/CommandRows";
|
|
35
|
+
import { ModuleSpec } from "../components/SourceDoc";
|
|
36
|
+
import { hasSchema, SchemaDocument } from "../components/SchemaDocument";
|
|
37
|
+
import { methodCount, operationsExposedBy } from "../lib/api";
|
|
38
|
+
import { KindIcon } from "../components/kind";
|
|
39
|
+
import { TechIcon } from "../components/TechIcon";
|
|
40
|
+
import { techGlyph } from "../lib/tech";
|
|
41
|
+
import { RowActions } from "../components/RowActions";
|
|
42
|
+
import { ContextPill, StatusChip } from "../components/primitives";
|
|
43
|
+
import { WhatLinksHere } from "../components/WhatLinksHere";
|
|
44
|
+
import { NotFound } from "./NotFound";
|
|
45
|
+
import { C4View } from "../likec4/C4View";
|
|
46
|
+
import { LevelSwitch } from "../likec4/levels";
|
|
47
|
+
import type { C4Level } from "../likec4/levels";
|
|
48
|
+
import { serviceInsideViewId, serviceViewId } from "../likec4/ids";
|
|
49
|
+
import { index } from "../data";
|
|
50
|
+
import { storesOfService } from "../lib/data-model";
|
|
51
|
+
import { ErCanvas } from "../er/ErCanvas";
|
|
52
|
+
import { StoreHeader } from "../er/StoreHeader";
|
|
53
|
+
import { RedisSchema } from "../er/RedisSchema";
|
|
54
|
+
|
|
55
|
+
const TABS = [
|
|
56
|
+
"overview",
|
|
57
|
+
"provides",
|
|
58
|
+
// The document beside the facts drawn from it. Always present rather than
|
|
59
|
+
// appearing only for services that have one, because every other tab on this
|
|
60
|
+
// page is too - a tab that comes and goes makes the page a different shape
|
|
61
|
+
// per service and the url stop meaning the same thing.
|
|
62
|
+
"spec",
|
|
63
|
+
"consumes",
|
|
64
|
+
// What the service says on the bus: the channels it declares, and the
|
|
65
|
+
// document they were read out of. Beside `provides` and `spec` rather than
|
|
66
|
+
// inside them, because a call and a message are answered differently and a
|
|
67
|
+
// reader is asking one question or the other.
|
|
68
|
+
"bus",
|
|
69
|
+
"data",
|
|
70
|
+
"flows",
|
|
71
|
+
"decisions",
|
|
72
|
+
] as const;
|
|
73
|
+
type Tab = (typeof TABS)[number];
|
|
74
|
+
|
|
75
|
+
function isTab(value: string | null): value is Tab {
|
|
76
|
+
return value !== null && (TABS as readonly string[]).includes(value);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export function ServicePage() {
|
|
80
|
+
const { context: contextId, service: serviceSlug } = useParams();
|
|
81
|
+
const [params, setParams] = useSearchParams();
|
|
82
|
+
const [showRetired, setShowRetired] = useState(false);
|
|
83
|
+
/** Which C4 level the model canvas is drawn at: the service, or its parts. */
|
|
84
|
+
const [level, setLevel] = useState<C4Level>(2);
|
|
85
|
+
// Read-only stores are off by default: they belong to someone else, and the
|
|
86
|
+
// question this tab opens with is what THIS service is responsible for.
|
|
87
|
+
const [showReadOnly, setShowReadOnly] = useState(false);
|
|
88
|
+
|
|
89
|
+
// Which request and response shapes are open. Collapsed by default: the
|
|
90
|
+
// question the provides tab answers first is "what can I call", and a page
|
|
91
|
+
// that opens with six schemas answers a question nobody asked yet.
|
|
92
|
+
const [openShapes, setOpenShapes] = useState<ReadonlySet<string>>(new Set());
|
|
93
|
+
const toggleShape = (id: string) =>
|
|
94
|
+
setOpenShapes((open) => {
|
|
95
|
+
const next = new Set(open);
|
|
96
|
+
if (!next.delete(id)) next.add(id);
|
|
97
|
+
|
|
98
|
+
return next;
|
|
99
|
+
});
|
|
100
|
+
const context = catalog.contexts.find((c) => c.id === contextId);
|
|
101
|
+
const service = context?.services.find((s) => s.slug === serviceSlug);
|
|
102
|
+
|
|
103
|
+
const raw = params.get("tab");
|
|
104
|
+
const tab: Tab = isTab(raw) ? raw : "overview";
|
|
105
|
+
|
|
106
|
+
if (!context || !service) return <NotFound kind="Service" id={serviceSlug} />;
|
|
107
|
+
|
|
108
|
+
const events = service.aggregates.flatMap((aggregate) =>
|
|
109
|
+
aggregate.events.map((event) => ({ aggregate, event })),
|
|
110
|
+
);
|
|
111
|
+
const stores = storesOfService(index, service.id);
|
|
112
|
+
const flows = flowRoles(catalog, service.id);
|
|
113
|
+
const tree = treeHref(service.path, service, allRepos(catalog));
|
|
114
|
+
const owners = ownersOf(service);
|
|
115
|
+
const adrs = adrsForService(catalog, service.id, context.id);
|
|
116
|
+
const current = adrs.filter(isCurrent);
|
|
117
|
+
const retired = adrs.filter((a) => !isCurrent(a));
|
|
118
|
+
// What the spec tab has to show: a document this repository holds, else the
|
|
119
|
+
// schema module the interfaces were declared in, else nothing.
|
|
120
|
+
const spec = pickSpec(
|
|
121
|
+
service,
|
|
122
|
+
(source) => hasSpec(source) || hasSchema(source),
|
|
123
|
+
);
|
|
124
|
+
// The channels the service declares, and the document behind them when this
|
|
125
|
+
// repository holds it. A channel names its own source, so the tab does not
|
|
126
|
+
// have to be told where to look.
|
|
127
|
+
const channels = service.channels ?? [];
|
|
128
|
+
const busDoc = channels
|
|
129
|
+
.map((channel) => channel.source)
|
|
130
|
+
.find((source) => source !== undefined && hasAsyncSpec(source));
|
|
131
|
+
const showDomain =
|
|
132
|
+
componentKind(service) === "service" || service.aggregates.length > 0;
|
|
133
|
+
const integrations = integrationsFor(service, catalog);
|
|
134
|
+
|
|
135
|
+
const counts: Record<Tab, number | null> = {
|
|
136
|
+
overview: null,
|
|
137
|
+
provides: methodCount(service),
|
|
138
|
+
spec: null,
|
|
139
|
+
consumes: integrations.length,
|
|
140
|
+
bus: channels.length,
|
|
141
|
+
data: stores.length,
|
|
142
|
+
flows: flows.length,
|
|
143
|
+
decisions: adrs.length,
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
return (
|
|
147
|
+
/* `manual`: the arrow keys move focus and ⏎ commits, rather than switching
|
|
148
|
+
the panel on every keypress. Each tab here is a page - one of them draws
|
|
149
|
+
a C4 view - and automatic activation would render four of them on the
|
|
150
|
+
way to the fifth, writing four URLs behind it. */
|
|
151
|
+
<TabGroup
|
|
152
|
+
manual
|
|
153
|
+
as="div"
|
|
154
|
+
className="h-full overflow-y-auto"
|
|
155
|
+
selectedIndex={TABS.indexOf(tab)}
|
|
156
|
+
onChange={(at) => {
|
|
157
|
+
const next = TABS[at] ?? "overview";
|
|
158
|
+
setParams(next === "overview" ? {} : { tab: next }, { replace: true });
|
|
159
|
+
}}
|
|
160
|
+
>
|
|
161
|
+
<PageHeader
|
|
162
|
+
kind="service"
|
|
163
|
+
name={service.name}
|
|
164
|
+
id={service.id}
|
|
165
|
+
contextId={context.id}
|
|
166
|
+
pin={{ kind: "service", id: service.id }}
|
|
167
|
+
right={
|
|
168
|
+
<>
|
|
169
|
+
<span className="chip-lg">{componentKind(service)}</span>
|
|
170
|
+
<ContextPill id={context.id} name={context.name} />
|
|
171
|
+
</>
|
|
172
|
+
}
|
|
173
|
+
>
|
|
174
|
+
<div className="mono mt-2 flex flex-wrap items-center gap-x-4 gap-y-1 text-muted">
|
|
175
|
+
<Ident value={service.repo}>{middleTruncate(service.repo, 32)}</Ident>
|
|
176
|
+
<Ident value={service.path}>{middleTruncate(service.path, 32)}</Ident>
|
|
177
|
+
{tree ? (
|
|
178
|
+
<a
|
|
179
|
+
href={tree}
|
|
180
|
+
target="_blank"
|
|
181
|
+
rel="noreferrer"
|
|
182
|
+
className="rounded-control text-accent hover:underline"
|
|
183
|
+
title="Open the service's directory on the forge, at the built commit"
|
|
184
|
+
>
|
|
185
|
+
open ↗
|
|
186
|
+
</a>
|
|
187
|
+
) : null}
|
|
188
|
+
{/* Who to ask, read out of CODEOWNERS. A handle is copied rather
|
|
189
|
+
than linked: it is what a reviewer types into a request, and a
|
|
190
|
+
link to a team page is a page most readers cannot open. */}
|
|
191
|
+
{owners.length > 0 ? (
|
|
192
|
+
<span className="flex flex-wrap items-center gap-x-2 gap-y-1">
|
|
193
|
+
<span className="text-muted">owned by</span>
|
|
194
|
+
{owners.map((handle) => (
|
|
195
|
+
<Ident key={handle} value={handle}>
|
|
196
|
+
{middleTruncate(handle, 28)}
|
|
197
|
+
</Ident>
|
|
198
|
+
))}
|
|
199
|
+
</span>
|
|
200
|
+
) : null}
|
|
201
|
+
{/* What it is built with, read off its manifests. A brand that has
|
|
202
|
+
a mark shows it beside the name; one that does not is the name
|
|
203
|
+
alone, which is what every chip was before. */}
|
|
204
|
+
{technologiesOf(service).map((technology) => {
|
|
205
|
+
const glyph = techGlyph(technology);
|
|
206
|
+
return (
|
|
207
|
+
<span key={technology} className="chip">
|
|
208
|
+
{glyph ? <TechIcon glyph={glyph} /> : null}
|
|
209
|
+
{technology}
|
|
210
|
+
</span>
|
|
211
|
+
);
|
|
212
|
+
})}
|
|
213
|
+
<span aria-hidden className="h-4 w-px bg-line-strong" />
|
|
214
|
+
{/* Both counts land in the section that lists what they counted;
|
|
215
|
+
the tabs above do the same job for the other four. */}
|
|
216
|
+
{showDomain ? (
|
|
217
|
+
<a
|
|
218
|
+
href={`#${SERVICE_ANCHOR.aggregates}`}
|
|
219
|
+
className="rounded-control hover:text-ink"
|
|
220
|
+
>
|
|
221
|
+
<span className="tnum">{service.aggregates.length}</span>{" "}
|
|
222
|
+
{plural(service.aggregates.length, "aggregate")}
|
|
223
|
+
</a>
|
|
224
|
+
) : null}
|
|
225
|
+
{showDomain ? (
|
|
226
|
+
<a
|
|
227
|
+
href={`#${SERVICE_ANCHOR.events}`}
|
|
228
|
+
className="rounded-control hover:text-ink"
|
|
229
|
+
>
|
|
230
|
+
<span className="tnum">{events.length}</span>{" "}
|
|
231
|
+
{plural(events.length, "event")}
|
|
232
|
+
</a>
|
|
233
|
+
) : null}
|
|
234
|
+
</div>
|
|
235
|
+
|
|
236
|
+
{/* Tabs keep the underline rather than becoming a segmented box: they
|
|
237
|
+
switch the page under them, they do not filter a list beside them.
|
|
238
|
+
The 2px rule is always drawn, transparent when idle, so selecting a
|
|
239
|
+
tab never lifts the row.
|
|
240
|
+
|
|
241
|
+
Eight of them do not fit a narrow window, so the row scrolls inside
|
|
242
|
+
`TabRow` and says at its edge that it does. */}
|
|
243
|
+
<div className="mt-4">
|
|
244
|
+
<TabRow active={tab}>
|
|
245
|
+
<TabList className="flex w-max gap-0">
|
|
246
|
+
{TABS.map((t) => (
|
|
247
|
+
<TabButton key={t}>
|
|
248
|
+
{t === "consumes" ? "integrations" : t}
|
|
249
|
+
{counts[t] !== null ? <TabCount>{counts[t]}</TabCount> : null}
|
|
250
|
+
</TabButton>
|
|
251
|
+
))}
|
|
252
|
+
</TabList>
|
|
253
|
+
</TabRow>
|
|
254
|
+
</div>
|
|
255
|
+
</PageHeader>
|
|
256
|
+
|
|
257
|
+
<TabPanels className="p-gutter">
|
|
258
|
+
<TabPanel>
|
|
259
|
+
<>
|
|
260
|
+
{/* Two scopes of the same service: the box among the ones it
|
|
261
|
+
touches, and the box opened up. The page already lists the
|
|
262
|
+
aggregates below, so it opens on the level the list cannot
|
|
263
|
+
give — who is on the other end. */}
|
|
264
|
+
<SectionTitle
|
|
265
|
+
right={
|
|
266
|
+
<LevelSwitch
|
|
267
|
+
level={level}
|
|
268
|
+
onLevel={setLevel}
|
|
269
|
+
levels={[
|
|
270
|
+
{ level: 2, label: "neighbours" },
|
|
271
|
+
{ level: 3, label: "inside" },
|
|
272
|
+
]}
|
|
273
|
+
/>
|
|
274
|
+
}
|
|
275
|
+
>
|
|
276
|
+
Model
|
|
277
|
+
</SectionTitle>
|
|
278
|
+
<C4View
|
|
279
|
+
viewId={
|
|
280
|
+
level === 3
|
|
281
|
+
? serviceInsideViewId(service)
|
|
282
|
+
: serviceViewId(service)
|
|
283
|
+
}
|
|
284
|
+
height={300}
|
|
285
|
+
/>
|
|
286
|
+
<div className="mt-section" />
|
|
287
|
+
<Markdown mermaid>{service.readme}</Markdown>
|
|
288
|
+
{/* What to type to build, test and run it. Under the README
|
|
289
|
+
rather than in a tab of its own: the list is short, it is the
|
|
290
|
+
first thing a reader new to the checkout wants, and the README
|
|
291
|
+
above is where it would have been written by hand. Absent
|
|
292
|
+
entirely when no runner file declares one - a heading over an
|
|
293
|
+
empty list would be a claim that the service cannot be built,
|
|
294
|
+
and nobody made it. */}
|
|
295
|
+
{commandsOf(service).length > 0 ? (
|
|
296
|
+
<section
|
|
297
|
+
id={SERVICE_ANCHOR.commands}
|
|
298
|
+
className="mt-section max-w-table"
|
|
299
|
+
>
|
|
300
|
+
<SectionTitle anchor={SERVICE_ANCHOR.commands}>
|
|
301
|
+
Commands
|
|
302
|
+
</SectionTitle>
|
|
303
|
+
<CommandRows
|
|
304
|
+
commands={commandsOf(service)}
|
|
305
|
+
service={service}
|
|
306
|
+
/>
|
|
307
|
+
</section>
|
|
308
|
+
) : null}
|
|
309
|
+
{showDomain ? (
|
|
310
|
+
<section
|
|
311
|
+
id={SERVICE_ANCHOR.aggregates}
|
|
312
|
+
className="mt-section max-w-table"
|
|
313
|
+
>
|
|
314
|
+
<SectionTitle anchor={SERVICE_ANCHOR.aggregates}>
|
|
315
|
+
Aggregates
|
|
316
|
+
</SectionTitle>
|
|
317
|
+
{/* icon, slug, name, event count, actions - one column each,
|
|
318
|
+
so the counts stack up instead of drifting with the name. */}
|
|
319
|
+
<div
|
|
320
|
+
className="rows grid-cols-[auto_auto_1fr_auto_auto]"
|
|
321
|
+
data-nav-list
|
|
322
|
+
>
|
|
323
|
+
{service.aggregates.map((aggregate) => {
|
|
324
|
+
const to = paths.aggregate(
|
|
325
|
+
context.id,
|
|
326
|
+
service.slug,
|
|
327
|
+
aggregate.slug,
|
|
328
|
+
);
|
|
329
|
+
return (
|
|
330
|
+
<div key={aggregate.id} className="row px-2 py-1.5">
|
|
331
|
+
<KindIcon kind="aggregate" />
|
|
332
|
+
<Link
|
|
333
|
+
to={to}
|
|
334
|
+
data-nav-item
|
|
335
|
+
className="mono rounded-control"
|
|
336
|
+
>
|
|
337
|
+
{aggregate.slug}
|
|
338
|
+
</Link>
|
|
339
|
+
<span className="meta">{aggregate.name}</span>
|
|
340
|
+
<Link
|
|
341
|
+
to={`${to}#bb-events`}
|
|
342
|
+
className="mono rounded-control hover:underline"
|
|
343
|
+
style={{
|
|
344
|
+
color:
|
|
345
|
+
aggregate.events.length === 0
|
|
346
|
+
? "var(--status-declared)"
|
|
347
|
+
: "var(--fg-muted)",
|
|
348
|
+
}}
|
|
349
|
+
>
|
|
350
|
+
<span className="tnum">
|
|
351
|
+
{aggregate.events.length}
|
|
352
|
+
</span>{" "}
|
|
353
|
+
events
|
|
354
|
+
</Link>
|
|
355
|
+
<RowActions
|
|
356
|
+
copy={aggregate.id}
|
|
357
|
+
reveal={aggregate.id}
|
|
358
|
+
label={aggregate.name}
|
|
359
|
+
/>
|
|
360
|
+
</div>
|
|
361
|
+
);
|
|
362
|
+
})}
|
|
363
|
+
</div>
|
|
364
|
+
</section>
|
|
365
|
+
) : null}
|
|
366
|
+
|
|
367
|
+
<section
|
|
368
|
+
id={SERVICE_ANCHOR.events}
|
|
369
|
+
className="mt-section max-w-table"
|
|
370
|
+
>
|
|
371
|
+
<SectionTitle
|
|
372
|
+
anchor={SERVICE_ANCHOR.events}
|
|
373
|
+
right={<span>everything this service announces</span>}
|
|
374
|
+
>
|
|
375
|
+
Events
|
|
376
|
+
</SectionTitle>
|
|
377
|
+
{events.length === 0 ? (
|
|
378
|
+
<Empty>this service announces nothing — it only answers</Empty>
|
|
379
|
+
) : (
|
|
380
|
+
<div
|
|
381
|
+
className="rows grid-cols-[auto_auto_1fr_auto_auto]"
|
|
382
|
+
data-nav-list
|
|
383
|
+
>
|
|
384
|
+
{events.map(({ aggregate, event }) => {
|
|
385
|
+
const to = paths.event(
|
|
386
|
+
context.id,
|
|
387
|
+
service.slug,
|
|
388
|
+
aggregate.slug,
|
|
389
|
+
event.slug,
|
|
390
|
+
);
|
|
391
|
+
return (
|
|
392
|
+
<div key={event.id} className="row gap-2">
|
|
393
|
+
<KindIcon kind="event" />
|
|
394
|
+
<Link
|
|
395
|
+
to={to}
|
|
396
|
+
data-nav-item
|
|
397
|
+
className="mono rounded-control"
|
|
398
|
+
style={{ color: "var(--kind-event)" }}
|
|
399
|
+
>
|
|
400
|
+
{event.name}
|
|
401
|
+
</Link>
|
|
402
|
+
<span className="mono text-muted">
|
|
403
|
+
{aggregate.slug}
|
|
404
|
+
</span>
|
|
405
|
+
<Link
|
|
406
|
+
to={`${to}#${EVENT_ANCHOR.consumers}`}
|
|
407
|
+
className="mono rounded-control text-muted hover:text-ink"
|
|
408
|
+
>
|
|
409
|
+
<span className="tnum">{event.consumers.length}</span>{" "}
|
|
410
|
+
{event.consumers.length === 1
|
|
411
|
+
? "consumer"
|
|
412
|
+
: "consumers"}
|
|
413
|
+
</Link>
|
|
414
|
+
<RowActions
|
|
415
|
+
copy={event.id}
|
|
416
|
+
reveal={event.id}
|
|
417
|
+
label={event.name}
|
|
418
|
+
/>
|
|
419
|
+
</div>
|
|
420
|
+
);
|
|
421
|
+
})}
|
|
422
|
+
</div>
|
|
423
|
+
)}
|
|
424
|
+
</section>
|
|
425
|
+
|
|
426
|
+
{/* Who calls this service is nowhere else on the page: `provides`
|
|
427
|
+
and `consumes` both point outwards. Flows and decisions have
|
|
428
|
+
tabs of their own, so they are counted here, not repeated. */}
|
|
429
|
+
<WhatLinksHere
|
|
430
|
+
target={{ kind: "service", id: service.id }}
|
|
431
|
+
elsewhere={{
|
|
432
|
+
flow: { href: "?tab=flows", label: "the flows tab" },
|
|
433
|
+
adr: { href: "?tab=decisions", label: "the decisions tab" },
|
|
434
|
+
}}
|
|
435
|
+
empty="nothing in the catalog calls this service or listens to it"
|
|
436
|
+
/>
|
|
437
|
+
</>
|
|
438
|
+
</TabPanel>
|
|
439
|
+
|
|
440
|
+
<TabPanel>
|
|
441
|
+
<div className="flex flex-col gap-4">
|
|
442
|
+
{service.provides.length === 0 ? (
|
|
443
|
+
<Empty>this service answers nothing — it only listens</Empty>
|
|
444
|
+
) : null}
|
|
445
|
+
{service.provides.map((provided) => {
|
|
446
|
+
const module = provided.module
|
|
447
|
+
? index.moduleById.get(provided.module)
|
|
448
|
+
: undefined;
|
|
449
|
+
|
|
450
|
+
return (
|
|
451
|
+
<div
|
|
452
|
+
key={provided.id}
|
|
453
|
+
className="rounded-card border border-line"
|
|
454
|
+
>
|
|
455
|
+
<div className="mono flex flex-wrap items-center gap-x-3 border-b px-3 py-1.5 border-line bg-surface">
|
|
456
|
+
<Ident value={provided.id} className="text-ink" />
|
|
457
|
+
{/* The schema this interface was declared in. A link
|
|
458
|
+
rather than a chip that only names it: the module page
|
|
459
|
+
is where "who else reads this" is answered. */}
|
|
460
|
+
{module ? (
|
|
461
|
+
<Link
|
|
462
|
+
to={paths.module(module.slug)}
|
|
463
|
+
className="chip hover:text-ink"
|
|
464
|
+
title={module.id}
|
|
465
|
+
>
|
|
466
|
+
<KindIcon kind="module" />
|
|
467
|
+
{module.name}
|
|
468
|
+
</Link>
|
|
469
|
+
) : null}
|
|
470
|
+
<Ident
|
|
471
|
+
value={docPathOf(provided.source)}
|
|
472
|
+
className="ml-auto"
|
|
473
|
+
title={provided.source}
|
|
474
|
+
/>
|
|
475
|
+
</div>
|
|
476
|
+
{/* Drawn by the same component the module page uses, so a
|
|
477
|
+
method reads identically in both places. */}
|
|
478
|
+
<MethodRows
|
|
479
|
+
provided={provided}
|
|
480
|
+
open={openShapes}
|
|
481
|
+
onToggle={toggleShape}
|
|
482
|
+
runs={(method) => {
|
|
483
|
+
// What the endpoint actually runs. More than one is
|
|
484
|
+
// normal: a handler that resolves a token before changing
|
|
485
|
+
// a password has run two use cases, in two aggregates.
|
|
486
|
+
const runs = operationsExposedBy(service, method.name);
|
|
487
|
+
if (runs.length === 0) return null;
|
|
488
|
+
|
|
489
|
+
return (
|
|
490
|
+
<p className="mono mt-0.5 flex flex-wrap items-center gap-x-2 text-muted">
|
|
491
|
+
<span>runs</span>
|
|
492
|
+
{runs.map(({ aggregate, operation }) => {
|
|
493
|
+
const to = aggregatePath(aggregate.id);
|
|
494
|
+
const label = `${aggregate.slug}.${operation.id}`;
|
|
495
|
+
|
|
496
|
+
return to ? (
|
|
497
|
+
<Link
|
|
498
|
+
key={label}
|
|
499
|
+
to={to}
|
|
500
|
+
className="rounded-control hover:text-ink"
|
|
501
|
+
title={`${operation.kind} of ${aggregate.name}`}
|
|
502
|
+
>
|
|
503
|
+
{label}
|
|
504
|
+
</Link>
|
|
505
|
+
) : (
|
|
506
|
+
<span key={label}>{label}</span>
|
|
507
|
+
);
|
|
508
|
+
})}
|
|
509
|
+
</p>
|
|
510
|
+
);
|
|
511
|
+
}}
|
|
512
|
+
/>
|
|
513
|
+
<MessageList
|
|
514
|
+
provided={provided}
|
|
515
|
+
open={openShapes}
|
|
516
|
+
onToggle={toggleShape}
|
|
517
|
+
/>
|
|
518
|
+
</div>
|
|
519
|
+
);
|
|
520
|
+
})}
|
|
521
|
+
</div>
|
|
522
|
+
</TabPanel>
|
|
523
|
+
|
|
524
|
+
<TabPanel>
|
|
525
|
+
{spec === null ? (
|
|
526
|
+
<Empty>
|
|
527
|
+
no api document in this catalog — nothing under this service names
|
|
528
|
+
one
|
|
529
|
+
</Empty>
|
|
530
|
+
) : spec.kind === "openapi" ? (
|
|
531
|
+
<ApiReference source={spec.source} />
|
|
532
|
+
) : spec.kind === "graphql" ? (
|
|
533
|
+
<SchemaDocument source={spec.source} />
|
|
534
|
+
) : spec.kind === "wsdl" ? (
|
|
535
|
+
<WsdlReference source={spec.source} provided={service.provides} />
|
|
536
|
+
) : spec.kind === "inferred-http" ? (
|
|
537
|
+
<div className="flex flex-col gap-4">
|
|
538
|
+
<div className="rounded-card border border-line bg-surface px-4 py-3">
|
|
539
|
+
<p className="font-medium text-ink">HTTP contract inferred from Django</p>
|
|
540
|
+
<p className="mt-1 text-muted">
|
|
541
|
+
No OpenAPI document is checked into this repository. These routes were read
|
|
542
|
+
statically from Django URLConf and DRF views; request and response schemas stay
|
|
543
|
+
unknown until the generated Swagger document is exported into the repository.
|
|
544
|
+
</p>
|
|
545
|
+
</div>
|
|
546
|
+
{service.provides
|
|
547
|
+
.filter((provided) => provided.methods.some((method) => method.http))
|
|
548
|
+
.map((provided) => (
|
|
549
|
+
<div key={provided.id} className="rounded-card border border-line">
|
|
550
|
+
<div className="mono flex flex-wrap items-center gap-x-3 border-b border-line bg-surface px-3 py-1.5">
|
|
551
|
+
<Ident value={provided.id} className="text-ink" />
|
|
552
|
+
<Ident value={docPathOf(provided.source)} className="ml-auto" title={provided.source} />
|
|
553
|
+
</div>
|
|
554
|
+
<MethodRows provided={provided} open={openShapes} onToggle={toggleShape} />
|
|
555
|
+
</div>
|
|
556
|
+
))}
|
|
557
|
+
</div>
|
|
558
|
+
) : (
|
|
559
|
+
/* A proto is drawn from the catalog rather than as raw text. The
|
|
560
|
+
rule ApiReference states - draw the document because the catalog
|
|
561
|
+
cannot carry its shape - does not hold here: the extractor read
|
|
562
|
+
exactly that shape, and a <pre> could not link a field to the
|
|
563
|
+
shared type it refs. */
|
|
564
|
+
<ModuleSpec moduleId={spec.moduleId} />
|
|
565
|
+
)}
|
|
566
|
+
</TabPanel>
|
|
567
|
+
|
|
568
|
+
<TabPanel>
|
|
569
|
+
<Integrations groups={integrations} />
|
|
570
|
+
</TabPanel>
|
|
571
|
+
|
|
572
|
+
<TabPanel>
|
|
573
|
+
{channels.length === 0 ? (
|
|
574
|
+
<Empty>
|
|
575
|
+
nothing says what this service puts on the bus — channels are read
|
|
576
|
+
from an AsyncAPI document, and none was found for this repository
|
|
577
|
+
</Empty>
|
|
578
|
+
) : (
|
|
579
|
+
<ChannelRows channels={channels} service={service.id} />
|
|
580
|
+
)}
|
|
581
|
+
|
|
582
|
+
{busDoc ? (
|
|
583
|
+
<>
|
|
584
|
+
<div className="mt-section" />
|
|
585
|
+
<SectionTitle>Document</SectionTitle>
|
|
586
|
+
<AsyncApiReference source={busDoc} />
|
|
587
|
+
</>
|
|
588
|
+
) : null}
|
|
589
|
+
</TabPanel>
|
|
590
|
+
|
|
591
|
+
<TabPanel>
|
|
592
|
+
{stores.length === 0 ? (
|
|
593
|
+
<Empty>
|
|
594
|
+
nothing says where this service keeps its state — no database
|
|
595
|
+
schema or statically readable ORM configuration was found for this repository
|
|
596
|
+
</Empty>
|
|
597
|
+
) : null}
|
|
598
|
+
|
|
599
|
+
{stores.some((s) => s.access === "reads") ? (
|
|
600
|
+
<button
|
|
601
|
+
type="button"
|
|
602
|
+
onClick={() => setShowReadOnly((v) => !v)}
|
|
603
|
+
aria-pressed={showReadOnly}
|
|
604
|
+
className="mono mb-4 rounded-control border border-dashed px-2 py-1 border-line-strong text-muted hover:bg-surface"
|
|
605
|
+
>
|
|
606
|
+
{showReadOnly ? "hide" : "show"}{" "}
|
|
607
|
+
{stores.filter((s) => s.access === "reads").length} read-only{" "}
|
|
608
|
+
{plural(
|
|
609
|
+
stores.filter((s) => s.access === "reads").length,
|
|
610
|
+
"store",
|
|
611
|
+
)}
|
|
612
|
+
</button>
|
|
613
|
+
) : null}
|
|
614
|
+
|
|
615
|
+
<div className="flex flex-col gap-8">
|
|
616
|
+
{stores
|
|
617
|
+
.filter((s) => showReadOnly || s.access === "owns")
|
|
618
|
+
.map(({ store, access }) => (
|
|
619
|
+
<section key={store.id}>
|
|
620
|
+
<StoreHeader store={store} access={access} />
|
|
621
|
+
<div className="mt-3">
|
|
622
|
+
{(store.keyspaces ?? []).length > 0 ? (
|
|
623
|
+
<RedisSchema store={store} />
|
|
624
|
+
) : store.tables.length === 0 ? (
|
|
625
|
+
/* A store whose schema nobody has read is still a fact
|
|
626
|
+
worth drawing — a cache IS part of the picture — but an
|
|
627
|
+
empty canvas would say the opposite. */
|
|
628
|
+
<Empty>
|
|
629
|
+
no schema extracted — {store.name} is in the catalog by
|
|
630
|
+
kind and owner only
|
|
631
|
+
</Empty>
|
|
632
|
+
) : (
|
|
633
|
+
<ErCanvas store={store} ghost={access === "reads"} />
|
|
634
|
+
)}
|
|
635
|
+
</div>
|
|
636
|
+
</section>
|
|
637
|
+
))}
|
|
638
|
+
</div>
|
|
639
|
+
</TabPanel>
|
|
640
|
+
|
|
641
|
+
<TabPanel>
|
|
642
|
+
<div className="flex flex-col gap-1" data-nav-list>
|
|
643
|
+
{flows.length === 0 ? (
|
|
644
|
+
<Empty>no chart runs through here yet</Empty>
|
|
645
|
+
) : null}
|
|
646
|
+
{flows.map(
|
|
647
|
+
({
|
|
648
|
+
flow,
|
|
649
|
+
role,
|
|
650
|
+
trigger,
|
|
651
|
+
firstStepId,
|
|
652
|
+
steps,
|
|
653
|
+
publishes,
|
|
654
|
+
consumes,
|
|
655
|
+
}) => {
|
|
656
|
+
// What this service does in the flow, in one phrase, and the
|
|
657
|
+
// counts behind it. The link lands on the first step the
|
|
658
|
+
// service is on rather than the top of the rail.
|
|
659
|
+
const does =
|
|
660
|
+
role === "initiates"
|
|
661
|
+
? `answers ${trigger ?? "the call in"}`
|
|
662
|
+
: role === "reacts"
|
|
663
|
+
? `reacts to ${trigger ?? "an event"}`
|
|
664
|
+
: "on the way";
|
|
665
|
+
return (
|
|
666
|
+
<Link
|
|
667
|
+
key={flow.slug}
|
|
668
|
+
to={
|
|
669
|
+
firstStepId
|
|
670
|
+
? paths.flowStep(flow.slug, firstStepId)
|
|
671
|
+
: paths.flow(flow.slug)
|
|
672
|
+
}
|
|
673
|
+
data-nav-item
|
|
674
|
+
className="row flex-wrap items-baseline gap-x-3"
|
|
675
|
+
>
|
|
676
|
+
<span className="font-semibold">{flow.name}</span>
|
|
677
|
+
<span className="mono text-muted">{flow.slug}</span>
|
|
678
|
+
<span className="mono text-muted">{does}</span>
|
|
679
|
+
<span className="mono ml-auto flex shrink-0 items-center gap-3 text-muted">
|
|
680
|
+
{publishes.length > 0 ? (
|
|
681
|
+
<span title={`publishes ${publishes.join(", ")}`}>
|
|
682
|
+
↑ <span className="tnum">{publishes.length}</span>
|
|
683
|
+
</span>
|
|
684
|
+
) : null}
|
|
685
|
+
{consumes.length > 0 ? (
|
|
686
|
+
<span title={`consumes ${consumes.join(", ")}`}>
|
|
687
|
+
↓ <span className="tnum">{consumes.length}</span>
|
|
688
|
+
</span>
|
|
689
|
+
) : null}
|
|
690
|
+
<span title="steps this service is on">
|
|
691
|
+
<span className="tnum">{steps}</span> step
|
|
692
|
+
{steps === 1 ? "" : "s"}
|
|
693
|
+
</span>
|
|
694
|
+
<StatusChip status={flowHealth(flow)} />
|
|
695
|
+
</span>
|
|
696
|
+
</Link>
|
|
697
|
+
);
|
|
698
|
+
},
|
|
699
|
+
)}
|
|
700
|
+
</div>
|
|
701
|
+
</TabPanel>
|
|
702
|
+
|
|
703
|
+
<TabPanel>
|
|
704
|
+
{adrs.length === 0 ? (
|
|
705
|
+
<Empty>nothing on the record names this service</Empty>
|
|
706
|
+
) : (
|
|
707
|
+
/* number, title, status, scope, date - one column each, shared by
|
|
708
|
+
the rows in force and the retired ones below them, so a chip
|
|
709
|
+
sits under the chip above it rather than wherever the title
|
|
710
|
+
before it happened to end. */
|
|
711
|
+
<div
|
|
712
|
+
className={`rows max-w-table ${ADR_ROW_COLUMNS}`}
|
|
713
|
+
data-nav-list
|
|
714
|
+
>
|
|
715
|
+
{current.map((adr) => (
|
|
716
|
+
<AdrRow key={adr.id} adr={adr} />
|
|
717
|
+
))}
|
|
718
|
+
{retired.length > 0 ? (
|
|
719
|
+
<>
|
|
720
|
+
{/* A row of its own, so the button sits in the list's grid
|
|
721
|
+
without being a grid itself. */}
|
|
722
|
+
<div>
|
|
723
|
+
<button
|
|
724
|
+
type="button"
|
|
725
|
+
onClick={() => setShowRetired((v) => !v)}
|
|
726
|
+
aria-expanded={showRetired}
|
|
727
|
+
className="mono col-span-full mt-1 justify-self-start border border-dashed px-2 py-1 border-line-strong text-muted hover:bg-surface"
|
|
728
|
+
>
|
|
729
|
+
{showRetired ? "hide" : "show"} {retired.length}{" "}
|
|
730
|
+
{retired.every((a) => a.status === "superseded")
|
|
731
|
+
? "superseded"
|
|
732
|
+
: "no longer in force"}
|
|
733
|
+
</button>
|
|
734
|
+
</div>
|
|
735
|
+
{showRetired
|
|
736
|
+
? retired.map((adr) => <AdrRow key={adr.id} adr={adr} />)
|
|
737
|
+
: null}
|
|
738
|
+
</>
|
|
739
|
+
) : null}
|
|
740
|
+
</div>
|
|
741
|
+
)}
|
|
742
|
+
</TabPanel>
|
|
743
|
+
</TabPanels>
|
|
744
|
+
</TabGroup>
|
|
745
|
+
);
|
|
746
|
+
}
|