@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,189 @@
|
|
|
1
|
+
import { useDocumentTitle } from "../app/title";
|
|
2
|
+
import { useLayoutEffect, useRef, useState } from "react";
|
|
3
|
+
import type { ReactNode } from "react";
|
|
4
|
+
import { ctxStyle } from "../lib/context-color";
|
|
5
|
+
import { PinButton } from "../app/pins";
|
|
6
|
+
import type { PinKind } from "../lib/pins";
|
|
7
|
+
import { AnchorLink } from "./AnchorLink";
|
|
8
|
+
import { Ident } from "./Ident";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* The header strip every entity page opens with. `contextId` paints the hero
|
|
12
|
+
* wash - 120px of that context's colour at 6%, fading to nothing. The header's
|
|
13
|
+
* own content sits above it on solid background, so no text is ever read off
|
|
14
|
+
* a gradient.
|
|
15
|
+
*
|
|
16
|
+
* `pin` puts the pin control at the head of the right-hand group, before
|
|
17
|
+
* whatever else the page puts there. It is first because it is the only
|
|
18
|
+
* control on the strip that is about the reader rather than about the entity,
|
|
19
|
+
* and a reader looking for it should find it in the same place on every page.
|
|
20
|
+
*
|
|
21
|
+
* Only the name row is pinned (`.page-bar`): the name, its id, and the
|
|
22
|
+
* controls at its right. The kind label above it and whatever the page puts
|
|
23
|
+
* under it - a meta row, a tab list - scroll away like the rest of the page;
|
|
24
|
+
* they were read on arrival, and a strip that kept them would be a strip that
|
|
25
|
+
* kept a third of a small window. The row is transparent in place and goes
|
|
26
|
+
* opaque once it is pinned, so the text is never read through the page
|
|
27
|
+
* scrolling under it. Rendered as siblings rather than one wrapper, because a
|
|
28
|
+
* sticky row pins inside its parent only, and its parent has to be the box
|
|
29
|
+
* that scrolls.
|
|
30
|
+
*
|
|
31
|
+
* The row publishes its height as `--page-header-h` on that box: the toc dock
|
|
32
|
+
* pins itself under it, and the box's scroll-padding keeps an anchor jump
|
|
33
|
+
* from landing behind it.
|
|
34
|
+
*/
|
|
35
|
+
const HEIGHT_VAR = "--page-header-h";
|
|
36
|
+
|
|
37
|
+
export function PageHeader({
|
|
38
|
+
kind,
|
|
39
|
+
name,
|
|
40
|
+
id,
|
|
41
|
+
contextId,
|
|
42
|
+
pin,
|
|
43
|
+
right,
|
|
44
|
+
children,
|
|
45
|
+
}: {
|
|
46
|
+
/** The kind of thing, and what it belongs to - the latter usually a link. */
|
|
47
|
+
kind: ReactNode;
|
|
48
|
+
name: string;
|
|
49
|
+
id?: string;
|
|
50
|
+
contextId?: string | null;
|
|
51
|
+
/** What pinning this page pins. Omitted on pages that are not pinnable. */
|
|
52
|
+
pin?: { kind: PinKind; id: string };
|
|
53
|
+
right?: ReactNode;
|
|
54
|
+
children?: ReactNode;
|
|
55
|
+
}) {
|
|
56
|
+
const bar = useRef<HTMLDivElement>(null);
|
|
57
|
+
const [stuck, setStuck] = useState(false);
|
|
58
|
+
useDocumentTitle(name);
|
|
59
|
+
|
|
60
|
+
useLayoutEffect(() => {
|
|
61
|
+
const el = bar.current;
|
|
62
|
+
const host = el?.parentElement;
|
|
63
|
+
if (!el || !host) return;
|
|
64
|
+
|
|
65
|
+
const publish = () =>
|
|
66
|
+
host.style.setProperty(HEIGHT_VAR, `${el.offsetHeight}px`);
|
|
67
|
+
publish();
|
|
68
|
+
const observer =
|
|
69
|
+
typeof ResizeObserver === "undefined" ? null : new ResizeObserver(publish);
|
|
70
|
+
observer?.observe(el);
|
|
71
|
+
|
|
72
|
+
// Pinned means the row is at the top of the box and the box has scrolled:
|
|
73
|
+
// the same test the browser applies, read back off the geometry.
|
|
74
|
+
let was = false;
|
|
75
|
+
const onScroll = () => {
|
|
76
|
+
const now =
|
|
77
|
+
host.scrollTop > 0 &&
|
|
78
|
+
el.getBoundingClientRect().top - host.getBoundingClientRect().top < 1;
|
|
79
|
+
if (now !== was) {
|
|
80
|
+
was = now;
|
|
81
|
+
setStuck(now);
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
onScroll();
|
|
85
|
+
host.addEventListener("scroll", onScroll, { passive: true });
|
|
86
|
+
|
|
87
|
+
return () => {
|
|
88
|
+
observer?.disconnect();
|
|
89
|
+
host.removeEventListener("scroll", onScroll);
|
|
90
|
+
host.style.removeProperty(HEIGHT_VAR);
|
|
91
|
+
};
|
|
92
|
+
}, []);
|
|
93
|
+
|
|
94
|
+
return (
|
|
95
|
+
<>
|
|
96
|
+
<div className="hero px-gutter pt-5">
|
|
97
|
+
<div aria-hidden className="hero-wash" style={ctxStyle(contextId)} />
|
|
98
|
+
<div className="label">{kind}</div>
|
|
99
|
+
</div>
|
|
100
|
+
<div
|
|
101
|
+
ref={bar}
|
|
102
|
+
className="page-bar flex flex-wrap items-baseline gap-x-3 gap-y-1 px-gutter py-1.5"
|
|
103
|
+
data-stuck={stuck ? "" : undefined}
|
|
104
|
+
>
|
|
105
|
+
<h1 className="text-md font-semibold" title={name}>
|
|
106
|
+
{name}
|
|
107
|
+
</h1>
|
|
108
|
+
{/* The id under a page's own name is the single most-copied string in
|
|
109
|
+
the app - it is what a reader takes to a grep or a ticket. */}
|
|
110
|
+
{id ? <Ident value={id} className="text-muted" /> : null}
|
|
111
|
+
{pin || right ? (
|
|
112
|
+
<div className="ml-auto flex items-center gap-2">
|
|
113
|
+
{pin ? (
|
|
114
|
+
<PinButton kind={pin.kind} id={pin.id} label={name} />
|
|
115
|
+
) : null}
|
|
116
|
+
{right}
|
|
117
|
+
</div>
|
|
118
|
+
) : null}
|
|
119
|
+
</div>
|
|
120
|
+
<div className="border-b border-line px-gutter pb-3.5">{children}</div>
|
|
121
|
+
</>
|
|
122
|
+
);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
export function SectionTitle({
|
|
126
|
+
children,
|
|
127
|
+
right,
|
|
128
|
+
anchor,
|
|
129
|
+
}: {
|
|
130
|
+
children: ReactNode;
|
|
131
|
+
right?: ReactNode;
|
|
132
|
+
/**
|
|
133
|
+
* The id of the section this titles. Every count in this app already links
|
|
134
|
+
* to one of these; passing it here is what lets a reader link back out.
|
|
135
|
+
*/
|
|
136
|
+
anchor?: string;
|
|
137
|
+
}) {
|
|
138
|
+
return (
|
|
139
|
+
<div
|
|
140
|
+
className={`section-head mb-3 flex items-center gap-2 ${anchor ? "anchored" : ""}`}
|
|
141
|
+
>
|
|
142
|
+
<h2 className="section-title">{children}</h2>
|
|
143
|
+
{anchor ? (
|
|
144
|
+
<AnchorLink
|
|
145
|
+
id={anchor}
|
|
146
|
+
{...(typeof children === "string" ? { label: children } : {})}
|
|
147
|
+
/>
|
|
148
|
+
) : null}
|
|
149
|
+
{right ? <div className="section-aside ml-auto">{right}</div> : null}
|
|
150
|
+
</div>
|
|
151
|
+
);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
export function Empty({ children }: { children: ReactNode }) {
|
|
155
|
+
return <div className="empty">{children}</div>;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* What a page says before the catalog has anything to put on it.
|
|
160
|
+
*
|
|
161
|
+
* `Empty` answers a question the reader asked - a filter, a lookup - with
|
|
162
|
+
* "nothing". This answers one they have not asked yet: the first catalog off a
|
|
163
|
+
* real repository is one context and a handful of events, and the sections it
|
|
164
|
+
* cannot fill must read as the start of something rather than as a dashboard
|
|
165
|
+
* with its wires cut. So it says where the missing facts come from, and names
|
|
166
|
+
* the file they land in - the one thing a reader can act on today.
|
|
167
|
+
*/
|
|
168
|
+
export function Blank({
|
|
169
|
+
children,
|
|
170
|
+
where,
|
|
171
|
+
}: {
|
|
172
|
+
children: ReactNode;
|
|
173
|
+
/** Path in the repository the absent facts are read from. */
|
|
174
|
+
where?: string;
|
|
175
|
+
}) {
|
|
176
|
+
return (
|
|
177
|
+
<div className="empty">
|
|
178
|
+
{/* The box is as wide as the list it stands in for, but a sentence is
|
|
179
|
+
not: capped at prose width and centred, so it does not run the full
|
|
180
|
+
bleed of a wide window. */}
|
|
181
|
+
<div className="mx-auto max-w-prose">{children}</div>
|
|
182
|
+
{where ? (
|
|
183
|
+
<div className="mt-2">
|
|
184
|
+
<Ident value={where} />
|
|
185
|
+
</div>
|
|
186
|
+
) : null}
|
|
187
|
+
</div>
|
|
188
|
+
);
|
|
189
|
+
}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
// What a row offers once the pointer is on it.
|
|
2
|
+
//
|
|
3
|
+
// Two actions, and both answer a question a table cannot: "give me that id" and
|
|
4
|
+
// "where does this sit?". They are hidden at rest because a list of forty rows
|
|
5
|
+
// with eighty buttons in it is a list nobody can read, and they are in the DOM
|
|
6
|
+
// rather than conditionally rendered so keyboard focus can still reach them.
|
|
7
|
+
|
|
8
|
+
import { useCallback, useEffect, useRef, useState } from "react";
|
|
9
|
+
import { Copy, ListTree } from "lucide-react";
|
|
10
|
+
import { toClipboard } from "../lib/clipboard";
|
|
11
|
+
import { useUiStore } from "../app/ui-store";
|
|
12
|
+
import { useSelectionStore } from "../selection/store";
|
|
13
|
+
|
|
14
|
+
const SHOWN_MS = 1000;
|
|
15
|
+
|
|
16
|
+
export function RowActions({
|
|
17
|
+
copy,
|
|
18
|
+
reveal,
|
|
19
|
+
label,
|
|
20
|
+
}: {
|
|
21
|
+
/** The string the copy button puts on the clipboard. */
|
|
22
|
+
copy: string;
|
|
23
|
+
/**
|
|
24
|
+
* A catalog id the sidebar tree draws a row for - a context, a service, an
|
|
25
|
+
* aggregate or an event. Omitted for anything the tree has no row for.
|
|
26
|
+
*/
|
|
27
|
+
reveal?: string;
|
|
28
|
+
/** What the buttons say they are acting on, for the accessible names. */
|
|
29
|
+
label?: string;
|
|
30
|
+
}) {
|
|
31
|
+
const [copied, setCopied] = useState(false);
|
|
32
|
+
const timer = useRef<ReturnType<typeof setTimeout> | null>(null);
|
|
33
|
+
const select = useSelectionStore((s) => s.select);
|
|
34
|
+
const requestReveal = useUiStore((s) => s.requestReveal);
|
|
35
|
+
|
|
36
|
+
useEffect(
|
|
37
|
+
() => () => {
|
|
38
|
+
if (timer.current) clearTimeout(timer.current);
|
|
39
|
+
},
|
|
40
|
+
[],
|
|
41
|
+
);
|
|
42
|
+
|
|
43
|
+
const what = label ?? copy;
|
|
44
|
+
|
|
45
|
+
const onCopy = useCallback(
|
|
46
|
+
(e: React.MouseEvent) => {
|
|
47
|
+
e.preventDefault();
|
|
48
|
+
e.stopPropagation();
|
|
49
|
+
void toClipboard(copy).then((ok) => {
|
|
50
|
+
setCopied(ok);
|
|
51
|
+
if (timer.current) clearTimeout(timer.current);
|
|
52
|
+
timer.current = setTimeout(() => setCopied(false), SHOWN_MS);
|
|
53
|
+
});
|
|
54
|
+
},
|
|
55
|
+
[copy],
|
|
56
|
+
);
|
|
57
|
+
|
|
58
|
+
const onReveal = useCallback(
|
|
59
|
+
(e: React.MouseEvent) => {
|
|
60
|
+
e.preventDefault();
|
|
61
|
+
e.stopPropagation();
|
|
62
|
+
if (!reveal) return;
|
|
63
|
+
// The tree opens its own ancestors and scrolls itself once the selection
|
|
64
|
+
// lands; all this has to do is make sure there is a tree to scroll.
|
|
65
|
+
select(reveal, "page");
|
|
66
|
+
requestReveal();
|
|
67
|
+
},
|
|
68
|
+
[reveal, select, requestReveal],
|
|
69
|
+
);
|
|
70
|
+
|
|
71
|
+
return (
|
|
72
|
+
<span className="row-actions ml-auto shrink-0">
|
|
73
|
+
<button
|
|
74
|
+
type="button"
|
|
75
|
+
onClick={onCopy}
|
|
76
|
+
className="row-action"
|
|
77
|
+
aria-label={`Copy ${what}`}
|
|
78
|
+
title={`Copy ${what}`}
|
|
79
|
+
>
|
|
80
|
+
<Copy size={12} aria-hidden />
|
|
81
|
+
{copied ? "copied" : "copy"}
|
|
82
|
+
</button>
|
|
83
|
+
{reveal ? (
|
|
84
|
+
<button
|
|
85
|
+
type="button"
|
|
86
|
+
onClick={onReveal}
|
|
87
|
+
className="row-action"
|
|
88
|
+
aria-label={`Reveal ${what} in the catalog tree`}
|
|
89
|
+
title="Reveal in tree"
|
|
90
|
+
>
|
|
91
|
+
<ListTree size={12} aria-hidden />
|
|
92
|
+
reveal
|
|
93
|
+
</button>
|
|
94
|
+
) : null}
|
|
95
|
+
</span>
|
|
96
|
+
);
|
|
97
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
// The GraphQL schema itself, as it is written.
|
|
2
|
+
//
|
|
3
|
+
// The rule the OpenAPI reference beside it states - draw the document, because
|
|
4
|
+
// the catalog cannot carry the document's own shape - is not quite the reason
|
|
5
|
+
// here. `extract-graphql` does read the shape: the provides tab lists every
|
|
6
|
+
// field with what it takes and what it answers, linked and searchable, and a
|
|
7
|
+
// second copy of that would be worth nothing.
|
|
8
|
+
//
|
|
9
|
+
// What the SDL carries that the catalog does not is that it is the artifact
|
|
10
|
+
// itself. A client author is given this text and writes queries against it,
|
|
11
|
+
// and a proto's reader has a module page to go to for the same thing while a
|
|
12
|
+
// schema has nowhere else to be. So it is shown as written - no rendering, no
|
|
13
|
+
// second navigation tree - and the facts stay next door.
|
|
14
|
+
|
|
15
|
+
import { useEffect, useState } from "react";
|
|
16
|
+
import { loaderFor as loaderIn } from "../lib/spec-files";
|
|
17
|
+
import { Empty } from "./PageHeader";
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* The schemas in the repository, by path, loaded on demand. A schema that
|
|
21
|
+
* lives in another repository is not here, which is the normal case: the
|
|
22
|
+
* catalog still lists what the service answers, and this tab says plainly that
|
|
23
|
+
* it has nothing to show.
|
|
24
|
+
*/
|
|
25
|
+
const SCHEMAS = import.meta.glob<string>(
|
|
26
|
+
[
|
|
27
|
+
"../../**/*.graphql",
|
|
28
|
+
"../../**/*.graphqls",
|
|
29
|
+
"!../../node_modules/**",
|
|
30
|
+
"!../../dist/**",
|
|
31
|
+
"!../../.portolan/**",
|
|
32
|
+
],
|
|
33
|
+
{ query: "?raw", import: "default" },
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
/** Whether the schema a catalog entry points at is one this site can show. */
|
|
37
|
+
export function hasSchema(source: string): boolean {
|
|
38
|
+
return loaderIn(SCHEMAS, source) !== null;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export function SchemaDocument({ source }: { source: string }) {
|
|
42
|
+
const [schema, setSchema] = useState<string | null>(null);
|
|
43
|
+
const [missing, setMissing] = useState(false);
|
|
44
|
+
|
|
45
|
+
useEffect(() => {
|
|
46
|
+
const load = loaderIn(SCHEMAS, source);
|
|
47
|
+
if (!load) {
|
|
48
|
+
setMissing(true);
|
|
49
|
+
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
let live = true;
|
|
54
|
+
load()
|
|
55
|
+
.then((text) => {
|
|
56
|
+
if (live) setSchema(text);
|
|
57
|
+
})
|
|
58
|
+
.catch(() => {
|
|
59
|
+
if (live) setMissing(true);
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
return () => {
|
|
63
|
+
live = false;
|
|
64
|
+
};
|
|
65
|
+
}, [source]);
|
|
66
|
+
|
|
67
|
+
if (missing) {
|
|
68
|
+
return (
|
|
69
|
+
<Empty>
|
|
70
|
+
this service's schema is not in this repository — only the fields
|
|
71
|
+
the catalog extracted from it are
|
|
72
|
+
</Empty>
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
if (schema === null) return <Empty>reading the schema…</Empty>;
|
|
77
|
+
|
|
78
|
+
return (
|
|
79
|
+
<div className="flex flex-col gap-2">
|
|
80
|
+
<p className="text-muted text-sm">
|
|
81
|
+
The module as it is written, at <code className="mono">{source}</code>.
|
|
82
|
+
What it declares is on the provides tab, where it links.
|
|
83
|
+
</p>
|
|
84
|
+
<pre className="mono overflow-x-auto rounded-card border border-line p-2 text-sm">
|
|
85
|
+
{schema}
|
|
86
|
+
</pre>
|
|
87
|
+
</div>
|
|
88
|
+
);
|
|
89
|
+
}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
// A picker that looks like the rest of the app.
|
|
2
|
+
//
|
|
3
|
+
// A native <select> is a control the operating system draws: a different font,
|
|
4
|
+
// a different radius, a different focus ring and, on macOS, a popup that
|
|
5
|
+
// ignores the dark theme entirely. Two of them sat in the middle of pages
|
|
6
|
+
// otherwise built out of six radii and one border colour, and both were the
|
|
7
|
+
// only place where the app stopped looking like itself.
|
|
8
|
+
//
|
|
9
|
+
// The behaviour is Headless UI's Listbox and the paint is ours. That division
|
|
10
|
+
// is the whole point of the dependency: the ARIA wiring, the focus return, the
|
|
11
|
+
// typeahead, the scroll-into-view and the outside-click are a listbox's boring
|
|
12
|
+
// half and are the half that is easy to get subtly wrong, while the part this
|
|
13
|
+
// app actually cares about - that a control is `.tbtn` and a popup is a
|
|
14
|
+
// hairline on --bg - stays here, in tokens, where every other control keeps it.
|
|
15
|
+
//
|
|
16
|
+
// Positioning comes with it: `anchor` puts the panel under the button and
|
|
17
|
+
// flips it to the other edge when the button is near the side of the window.
|
|
18
|
+
// A picker in a page header's right slot has no room to its right, and a panel
|
|
19
|
+
// that opens off the edge does not clip - it widens the pane and scrolls the
|
|
20
|
+
// whole page sideways.
|
|
21
|
+
|
|
22
|
+
import {
|
|
23
|
+
Listbox,
|
|
24
|
+
ListboxButton,
|
|
25
|
+
ListboxOption,
|
|
26
|
+
ListboxOptions,
|
|
27
|
+
} from "@headlessui/react";
|
|
28
|
+
import { Check, ChevronDown } from "lucide-react";
|
|
29
|
+
|
|
30
|
+
export interface SelectOption {
|
|
31
|
+
value: string;
|
|
32
|
+
label: string;
|
|
33
|
+
/** Second line, for the options that need saying rather than naming. */
|
|
34
|
+
note?: string;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function Select({
|
|
38
|
+
value,
|
|
39
|
+
options,
|
|
40
|
+
onChange,
|
|
41
|
+
label,
|
|
42
|
+
title,
|
|
43
|
+
className = "",
|
|
44
|
+
menuWidth,
|
|
45
|
+
}: {
|
|
46
|
+
value: string;
|
|
47
|
+
options: readonly SelectOption[];
|
|
48
|
+
onChange: (value: string) => void;
|
|
49
|
+
/** Accessible name. Rendered by the caller when it is visible. */
|
|
50
|
+
label: string;
|
|
51
|
+
title?: string;
|
|
52
|
+
className?: string;
|
|
53
|
+
/** Width of the panel. Defaults to "as wide as the button, at least 160px". */
|
|
54
|
+
menuWidth?: number;
|
|
55
|
+
}) {
|
|
56
|
+
const selected = options.find((o) => o.value === value);
|
|
57
|
+
|
|
58
|
+
return (
|
|
59
|
+
<Listbox value={value} onChange={onChange}>
|
|
60
|
+
{/* Open state comes back as a render prop rather than a `data-open:`
|
|
61
|
+
variant: `.tbtn-on` is a component class, and Tailwind variants
|
|
62
|
+
compose utilities, not those. */}
|
|
63
|
+
<ListboxButton
|
|
64
|
+
aria-label={label}
|
|
65
|
+
title={title ?? label}
|
|
66
|
+
className={({ open }) =>
|
|
67
|
+
`tbtn justify-between gap-1.5 ${open ? "tbtn-on" : ""} ${className}`
|
|
68
|
+
}
|
|
69
|
+
>
|
|
70
|
+
{({ open }) => (
|
|
71
|
+
<>
|
|
72
|
+
<span className="min-w-0 truncate">{selected?.label ?? value}</span>
|
|
73
|
+
<ChevronDown
|
|
74
|
+
size={13}
|
|
75
|
+
aria-hidden
|
|
76
|
+
className="shrink-0 t-micro transition-transform"
|
|
77
|
+
style={{ transform: open ? "rotate(180deg)" : "none" }}
|
|
78
|
+
/>
|
|
79
|
+
</>
|
|
80
|
+
)}
|
|
81
|
+
</ListboxButton>
|
|
82
|
+
|
|
83
|
+
<ListboxOptions
|
|
84
|
+
aria-label={label}
|
|
85
|
+
/* `padding` is the gap the panel keeps from the window edge; below it
|
|
86
|
+
Floating UI flips the panel to the button's other side rather than
|
|
87
|
+
letting it hang off the page. */
|
|
88
|
+
anchor={{ to: "bottom start", gap: 4, padding: 8 }}
|
|
89
|
+
className="palette-in z-50 max-h-64 overflow-y-auto rounded-control border bg-canvas py-1 border-line-strong shadow-md focus:outline-none"
|
|
90
|
+
style={menuWidth ? { width: menuWidth } : { minWidth: 160 }}
|
|
91
|
+
>
|
|
92
|
+
{options.map((option) => (
|
|
93
|
+
<ListboxOption
|
|
94
|
+
key={option.value}
|
|
95
|
+
value={option.value}
|
|
96
|
+
className={({ focus }) =>
|
|
97
|
+
`mono flex cursor-pointer items-start gap-2 px-2 py-1 ${focus ? "bg-raised" : ""}`
|
|
98
|
+
}
|
|
99
|
+
>
|
|
100
|
+
{({ selected: on }) => (
|
|
101
|
+
<>
|
|
102
|
+
<Check
|
|
103
|
+
size={12}
|
|
104
|
+
aria-hidden
|
|
105
|
+
className="mt-0.5 shrink-0"
|
|
106
|
+
style={{ opacity: on ? 1 : 0, color: "var(--accent)" }}
|
|
107
|
+
/>
|
|
108
|
+
<span
|
|
109
|
+
className="min-w-0"
|
|
110
|
+
style={on ? { color: "var(--accent)" } : undefined}
|
|
111
|
+
>
|
|
112
|
+
<span className="block truncate">{option.label}</span>
|
|
113
|
+
{option.note ? (
|
|
114
|
+
<span className="block truncate text-muted">
|
|
115
|
+
{option.note}
|
|
116
|
+
</span>
|
|
117
|
+
) : null}
|
|
118
|
+
</span>
|
|
119
|
+
</>
|
|
120
|
+
)}
|
|
121
|
+
</ListboxOption>
|
|
122
|
+
))}
|
|
123
|
+
</ListboxOptions>
|
|
124
|
+
</Listbox>
|
|
125
|
+
);
|
|
126
|
+
}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
// A shape, small enough to sit inside something else.
|
|
2
|
+
//
|
|
3
|
+
// Three columns and no toolbar: this is what a reader wants when the shape is
|
|
4
|
+
// an aside - the fields of a shared type opened from a schema row, the body an
|
|
5
|
+
// endpoint accepts - rather than the subject of the page. When it IS the
|
|
6
|
+
// subject, the sortable, filterable table on the block page is the right
|
|
7
|
+
// instrument and this one would be a worse version of it.
|
|
8
|
+
|
|
9
|
+
import { Fragment, useState } from "react";
|
|
10
|
+
import { ChevronDown, ChevronRight } from "lucide-react";
|
|
11
|
+
import type { Field, RpcEnum } from "../catalog";
|
|
12
|
+
import { parseType } from "../lib/shape";
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* The enum a field's type names, among the ones the interface declares. By
|
|
16
|
+
* bare name: a proto field says `OrderStatus`, and the list holds it as
|
|
17
|
+
* `OrderStatus` too.
|
|
18
|
+
*/
|
|
19
|
+
function enumFor(enums: RpcEnum[] | undefined, field: Field): RpcEnum | null {
|
|
20
|
+
if (!enums?.length) return null;
|
|
21
|
+
const { base } = parseType(field.type);
|
|
22
|
+
return enums.find((e) => e.name === base) ?? null;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/** The values of a proto enum, with the numbers a binary message carries. */
|
|
26
|
+
function EnumRows({ set }: { set: RpcEnum }) {
|
|
27
|
+
return (
|
|
28
|
+
<table className="ml-4 mt-1 mb-1">
|
|
29
|
+
<tbody>
|
|
30
|
+
{set.values.map((value) => (
|
|
31
|
+
<tr key={value.name} className="align-top">
|
|
32
|
+
<td className="mono py-0.5 pr-3 whitespace-nowrap">{value.name}</td>
|
|
33
|
+
<td className="mono tnum py-0.5 pr-3 text-right text-muted">
|
|
34
|
+
{value.number}
|
|
35
|
+
</td>
|
|
36
|
+
<td className="py-0.5 text-muted">{value.doc}</td>
|
|
37
|
+
</tr>
|
|
38
|
+
))}
|
|
39
|
+
</tbody>
|
|
40
|
+
</table>
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export function ShapeRows({
|
|
45
|
+
fields,
|
|
46
|
+
enums,
|
|
47
|
+
}: {
|
|
48
|
+
fields: Field[];
|
|
49
|
+
/** The interface's enums, so a field typed by one can open its values. */
|
|
50
|
+
enums?: RpcEnum[];
|
|
51
|
+
}) {
|
|
52
|
+
const [open, setOpen] = useState<Set<string>>(new Set());
|
|
53
|
+
const toggle = (name: string) =>
|
|
54
|
+
setOpen((prev) => {
|
|
55
|
+
const next = new Set(prev);
|
|
56
|
+
if (next.has(name)) next.delete(name);
|
|
57
|
+
else next.add(name);
|
|
58
|
+
return next;
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
return (
|
|
62
|
+
<table className="w-full">
|
|
63
|
+
<tbody>
|
|
64
|
+
{fields.map((field) => {
|
|
65
|
+
const set = enumFor(enums, field);
|
|
66
|
+
const shown = set !== null && open.has(field.name);
|
|
67
|
+
return (
|
|
68
|
+
<Fragment key={field.name}>
|
|
69
|
+
<tr className="align-top">
|
|
70
|
+
{/* Struck through rather than chipped: an aside has no room for a
|
|
71
|
+
badge, and the doc beside it says why. */}
|
|
72
|
+
<td
|
|
73
|
+
className={`mono py-0.5 pr-3 whitespace-nowrap${field.deprecated ? " line-through" : ""}`}
|
|
74
|
+
title={field.deprecated ? "deprecated" : undefined}
|
|
75
|
+
>
|
|
76
|
+
{field.name}
|
|
77
|
+
</td>
|
|
78
|
+
{/* An arrow marks a type that is a shared definition rather than a
|
|
79
|
+
primitive, so a reader can tell which names are worth following
|
|
80
|
+
without the row becoming a link it is not. */}
|
|
81
|
+
<td className="mono py-0.5 pr-3 whitespace-nowrap text-muted">
|
|
82
|
+
{set ? (
|
|
83
|
+
<button
|
|
84
|
+
type="button"
|
|
85
|
+
onClick={() => toggle(field.name)}
|
|
86
|
+
aria-expanded={shown}
|
|
87
|
+
className="inline-flex items-center gap-1 rounded-control hover:text-ink"
|
|
88
|
+
title={`${set.name}: ${set.values.length} values — click to ${shown ? "hide" : "show"} them`}
|
|
89
|
+
>
|
|
90
|
+
{shown ? (
|
|
91
|
+
<ChevronDown size={11} aria-hidden />
|
|
92
|
+
) : (
|
|
93
|
+
<ChevronRight size={11} aria-hidden />
|
|
94
|
+
)}
|
|
95
|
+
{field.type}
|
|
96
|
+
</button>
|
|
97
|
+
) : field.ref ? (
|
|
98
|
+
`${field.type} →`
|
|
99
|
+
) : (
|
|
100
|
+
field.type
|
|
101
|
+
)}
|
|
102
|
+
</td>
|
|
103
|
+
<td className="py-0.5 text-muted">{field.doc}</td>
|
|
104
|
+
</tr>
|
|
105
|
+
{shown && set ? (
|
|
106
|
+
<tr>
|
|
107
|
+
<td colSpan={3} className="pb-1">
|
|
108
|
+
<EnumRows set={set} />
|
|
109
|
+
</td>
|
|
110
|
+
</tr>
|
|
111
|
+
) : null}
|
|
112
|
+
</Fragment>
|
|
113
|
+
);
|
|
114
|
+
})}
|
|
115
|
+
</tbody>
|
|
116
|
+
</table>
|
|
117
|
+
);
|
|
118
|
+
}
|