@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,141 @@
|
|
|
1
|
+
// Resizable layout, in one place.
|
|
2
|
+
//
|
|
3
|
+
// react-resizable-panels v4 calls them Group / Panel / Separator. Everything
|
|
4
|
+
// portolan needs on top of that is here: a persisted layout keyed by page, a
|
|
5
|
+
// separator that reads as a hairline until you reach for it, and a hook that
|
|
6
|
+
// tells a canvas its box changed.
|
|
7
|
+
|
|
8
|
+
import { useCallback, useEffect, useRef } from "react";
|
|
9
|
+
import { Group, Separator, useDefaultLayout } from "react-resizable-panels";
|
|
10
|
+
import type { GroupProps } from "react-resizable-panels";
|
|
11
|
+
|
|
12
|
+
export { Panel, usePanelRef } from "react-resizable-panels";
|
|
13
|
+
export type { PanelImperativeHandle } from "react-resizable-panels";
|
|
14
|
+
|
|
15
|
+
/** The 100ms every canvas in the app waits before it re-measures. */
|
|
16
|
+
const RESIZE_SETTLE_MS = 100;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* localStorage, but a private-mode failure is not worth a crash: a layout that
|
|
20
|
+
* cannot be remembered is a layout that starts at its defaults.
|
|
21
|
+
*/
|
|
22
|
+
const storage = {
|
|
23
|
+
getItem(key: string): string | null {
|
|
24
|
+
try {
|
|
25
|
+
return localStorage.getItem(key);
|
|
26
|
+
} catch {
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
setItem(key: string, value: string): void {
|
|
31
|
+
try {
|
|
32
|
+
localStorage.setItem(key, value);
|
|
33
|
+
} catch {
|
|
34
|
+
/* private mode: this session still resizes, it just does not persist */
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* A Group whose layout survives a reload. `id` is the storage key and is
|
|
41
|
+
* spelled "portolan:<page>" at every call site, so one glance at localStorage
|
|
42
|
+
* says which page a layout belongs to.
|
|
43
|
+
*
|
|
44
|
+
* `panelIds` matters when a Group holds a Panel that is not always rendered -
|
|
45
|
+
* without it the restored layout is applied to the wrong panels.
|
|
46
|
+
*/
|
|
47
|
+
export function SavedGroup({
|
|
48
|
+
id,
|
|
49
|
+
panelIds,
|
|
50
|
+
children,
|
|
51
|
+
...rest
|
|
52
|
+
}: Omit<GroupProps, "id" | "defaultLayout" | "onLayoutChanged"> & {
|
|
53
|
+
id: string;
|
|
54
|
+
panelIds?: string[];
|
|
55
|
+
}) {
|
|
56
|
+
const { defaultLayout, onLayoutChanged } = useDefaultLayout({
|
|
57
|
+
id,
|
|
58
|
+
storage,
|
|
59
|
+
...(panelIds ? { panelIds } : {}),
|
|
60
|
+
});
|
|
61
|
+
return (
|
|
62
|
+
<Group
|
|
63
|
+
id={id}
|
|
64
|
+
defaultLayout={defaultLayout}
|
|
65
|
+
onLayoutChanged={onLayoutChanged}
|
|
66
|
+
{...rest}
|
|
67
|
+
>
|
|
68
|
+
{children}
|
|
69
|
+
</Group>
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* The divider. A 1px hairline that thickens to a 3px accent rule under the
|
|
75
|
+
* pointer or the keyboard, drawn by a child rather than by the separator's own
|
|
76
|
+
* border, so the 8px hit area never becomes 8px of visible gutter and nothing
|
|
77
|
+
* around it reflows when the rule thickens.
|
|
78
|
+
*
|
|
79
|
+
* Double-click resets the neighbouring panel to its default size; that is the
|
|
80
|
+
* library's own behaviour and is left on deliberately.
|
|
81
|
+
*/
|
|
82
|
+
export function ResizeHandle({
|
|
83
|
+
orientation = "horizontal",
|
|
84
|
+
id,
|
|
85
|
+
}: {
|
|
86
|
+
/** Matches the parent Group. Horizontal groups get a vertical divider. */
|
|
87
|
+
orientation?: "horizontal" | "vertical";
|
|
88
|
+
id?: string;
|
|
89
|
+
}) {
|
|
90
|
+
const vertical = orientation === "horizontal";
|
|
91
|
+
return (
|
|
92
|
+
<Separator
|
|
93
|
+
{...(id ? { id } : {})}
|
|
94
|
+
className={`group relative z-20 flex shrink-0 items-center justify-center ${
|
|
95
|
+
vertical ? "w-2 cursor-col-resize" : "h-2 cursor-row-resize"
|
|
96
|
+
}`}
|
|
97
|
+
title="Drag to resize · double-click to reset"
|
|
98
|
+
>
|
|
99
|
+
{/* The library puts data-separator="inactive|hover|focus|active" on the
|
|
100
|
+
separator itself, and its "hover" accounts for the full 8px target -
|
|
101
|
+
wider than the 1px rule the reader can actually see. Keying off that
|
|
102
|
+
rather than :hover is what makes the rule thicken as soon as the
|
|
103
|
+
pointer is in the hit area, and it covers the keyboard the same way. */}
|
|
104
|
+
<span
|
|
105
|
+
aria-hidden
|
|
106
|
+
className={`bg-line t-micro transition-[background-color,width,height] group-data-[separator=hover]:bg-accent group-data-[separator=focus]:bg-accent group-data-[separator=active]:bg-accent ${
|
|
107
|
+
vertical
|
|
108
|
+
? "h-full w-px group-data-[separator=hover]:w-[3px] group-data-[separator=focus]:w-[3px] group-data-[separator=active]:w-[3px]"
|
|
109
|
+
: "h-px w-full group-data-[separator=hover]:h-[3px] group-data-[separator=focus]:h-[3px] group-data-[separator=active]:h-[3px]"
|
|
110
|
+
}`}
|
|
111
|
+
/>
|
|
112
|
+
</Separator>
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Tells a canvas its box changed, once the dragging has stopped.
|
|
118
|
+
*
|
|
119
|
+
* LikeC4 and React Flow both re-measure on the window's resize event, and both
|
|
120
|
+
* are expensive enough that doing it on every frame of a drag is visible. The
|
|
121
|
+
* trailing 100ms edge is the whole point: the reader drags, the picture
|
|
122
|
+
* re-lays-out once, when they let go.
|
|
123
|
+
*/
|
|
124
|
+
export function useCanvasResize(): () => void {
|
|
125
|
+
const timer = useRef<ReturnType<typeof setTimeout> | null>(null);
|
|
126
|
+
|
|
127
|
+
useEffect(
|
|
128
|
+
() => () => {
|
|
129
|
+
if (timer.current) clearTimeout(timer.current);
|
|
130
|
+
},
|
|
131
|
+
[],
|
|
132
|
+
);
|
|
133
|
+
|
|
134
|
+
return useCallback(() => {
|
|
135
|
+
if (timer.current) clearTimeout(timer.current);
|
|
136
|
+
timer.current = setTimeout(() => {
|
|
137
|
+
timer.current = null;
|
|
138
|
+
window.dispatchEvent(new Event("resize"));
|
|
139
|
+
}, RESIZE_SETTLE_MS);
|
|
140
|
+
}, []);
|
|
141
|
+
}
|
package/src/app/pins.tsx
ADDED
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
// Pinning, everywhere it is offered.
|
|
2
|
+
//
|
|
3
|
+
// The store holds kinds and ids; `resolvePin` turns one back into a row the
|
|
4
|
+
// tree can draw. Resolution happening at render rather than at pin time is the
|
|
5
|
+
// whole point: a pin survives a rebuild that renamed the event, and quietly
|
|
6
|
+
// stops resolving when the event is gone, rather than pointing at a page the
|
|
7
|
+
// catalog no longer has.
|
|
8
|
+
|
|
9
|
+
import { Pin as PinIcon, PinOff } from "lucide-react";
|
|
10
|
+
import { create } from "zustand";
|
|
11
|
+
import { catalog, index } from "../data";
|
|
12
|
+
import { adrNumber } from "../lib/adr";
|
|
13
|
+
import { flowOwner } from "../lib/flow-tree";
|
|
14
|
+
import { addPin, isPinned, movePin, removePin } from "../lib/pins";
|
|
15
|
+
import type { Pin, PinKind } from "../lib/pins";
|
|
16
|
+
import { readPins, writePins } from "../lib/sidebar-prefs";
|
|
17
|
+
import type { Kind } from "../lib/kinds";
|
|
18
|
+
import {
|
|
19
|
+
adrPath,
|
|
20
|
+
aggregatePath,
|
|
21
|
+
eventPath,
|
|
22
|
+
modulePath,
|
|
23
|
+
paths,
|
|
24
|
+
servicePath,
|
|
25
|
+
storePath,
|
|
26
|
+
tablePath,
|
|
27
|
+
} from "../routes";
|
|
28
|
+
import { useToastStore } from "./toast";
|
|
29
|
+
|
|
30
|
+
interface PinsState {
|
|
31
|
+
pins: Pin[];
|
|
32
|
+
toggle: (pin: Pin) => void;
|
|
33
|
+
reorder: (from: number, to: number) => void;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export const usePinsStore = create<PinsState>()((set, get) => ({
|
|
37
|
+
pins: readPins(),
|
|
38
|
+
toggle: (pin) => {
|
|
39
|
+
const current = get().pins;
|
|
40
|
+
if (isPinned(current, pin)) {
|
|
41
|
+
const next = removePin(current, pin);
|
|
42
|
+
writePins(next);
|
|
43
|
+
set({ pins: next });
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
const { pins: next, evicted } = addPin(current, pin);
|
|
47
|
+
writePins(next);
|
|
48
|
+
set({ pins: next });
|
|
49
|
+
if (evicted) {
|
|
50
|
+
const gone = resolvePin(evicted);
|
|
51
|
+
useToastStore
|
|
52
|
+
.getState()
|
|
53
|
+
.say(`pinned — ${gone?.name ?? evicted.id} was unpinned to make room`);
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
reorder: (from, to) => {
|
|
57
|
+
const next = movePin(get().pins, from, to);
|
|
58
|
+
writePins(next);
|
|
59
|
+
set({ pins: next });
|
|
60
|
+
},
|
|
61
|
+
}));
|
|
62
|
+
|
|
63
|
+
/** True while this exact thing is on the list. Re-renders only when it flips. */
|
|
64
|
+
function useIsPinned(pin: Pin | null): boolean {
|
|
65
|
+
return usePinsStore((s) => (pin ? isPinned(s.pins, pin) : false));
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export interface ResolvedPin {
|
|
69
|
+
pin: Pin;
|
|
70
|
+
/** The kind's icon in the shared taxonomy, which is not always the pin kind. */
|
|
71
|
+
kind: Kind;
|
|
72
|
+
name: string;
|
|
73
|
+
/** What the row is titled with - the catalog id, as it is spelled. */
|
|
74
|
+
title: string;
|
|
75
|
+
path: string;
|
|
76
|
+
contextId: string | null;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* A pin, as a row. Null when the catalog no longer has what was pinned: the
|
|
81
|
+
* tree drops the row rather than drawing a name with nowhere to go.
|
|
82
|
+
*/
|
|
83
|
+
export function resolvePin(pin: Pin): ResolvedPin | null {
|
|
84
|
+
const base = { pin, title: pin.id };
|
|
85
|
+
switch (pin.kind) {
|
|
86
|
+
case "context": {
|
|
87
|
+
const context = catalog.contexts.find((c) => c.id === pin.id);
|
|
88
|
+
if (!context) return null;
|
|
89
|
+
return {
|
|
90
|
+
...base,
|
|
91
|
+
kind: "context",
|
|
92
|
+
name: context.name,
|
|
93
|
+
path: paths.context(context.id),
|
|
94
|
+
contextId: context.id,
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
case "store": {
|
|
98
|
+
const store = index.storeById.get(pin.id);
|
|
99
|
+
const to = storePath(pin.id);
|
|
100
|
+
if (!store || !to) return null;
|
|
101
|
+
return {
|
|
102
|
+
...base,
|
|
103
|
+
kind: "store",
|
|
104
|
+
name: store.name,
|
|
105
|
+
path: to,
|
|
106
|
+
contextId: index.serviceContext.get(store.owner)?.id ?? null,
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
case "flow": {
|
|
110
|
+
const flow = catalog.flows.find((f) => f.id === pin.id);
|
|
111
|
+
if (!flow) return null;
|
|
112
|
+
return {
|
|
113
|
+
...base,
|
|
114
|
+
kind: "flow",
|
|
115
|
+
name: flow.name,
|
|
116
|
+
title: flow.slug,
|
|
117
|
+
path: paths.flow(flow.slug),
|
|
118
|
+
contextId: flowOwner(flow),
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
case "event": {
|
|
122
|
+
const event = index.eventById.get(pin.id);
|
|
123
|
+
const owner = index.eventOwner.get(pin.id);
|
|
124
|
+
const to = eventPath(pin.id);
|
|
125
|
+
if (!event || !owner || !to) return null;
|
|
126
|
+
return {
|
|
127
|
+
...base,
|
|
128
|
+
kind: "event",
|
|
129
|
+
name: event.name,
|
|
130
|
+
path: to,
|
|
131
|
+
contextId: index.serviceContext.get(owner.service.id)?.id ?? null,
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
case "adr": {
|
|
135
|
+
const adr = index.adrById.get(pin.id);
|
|
136
|
+
const to = adrPath(pin.id);
|
|
137
|
+
if (!adr || !to) return null;
|
|
138
|
+
return {
|
|
139
|
+
...base,
|
|
140
|
+
kind: "adr",
|
|
141
|
+
name: `${adrNumber(adr).replace(/^ADR-/, "")} ${adr.title}`,
|
|
142
|
+
path: to,
|
|
143
|
+
contextId: adr.scope.kind === "context" ? adr.scope.context : null,
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
case "module": {
|
|
147
|
+
const module = index.moduleById.get(pin.id);
|
|
148
|
+
const to = modulePath(pin.id);
|
|
149
|
+
if (!module || !to) return null;
|
|
150
|
+
return {
|
|
151
|
+
...base,
|
|
152
|
+
kind: "module",
|
|
153
|
+
name: module.name,
|
|
154
|
+
path: to,
|
|
155
|
+
// A module belongs to no single context: it is published by one
|
|
156
|
+
// service and read by four, which is why it has no context colour.
|
|
157
|
+
contextId: null,
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
case "service": {
|
|
161
|
+
const service = index.serviceById.get(pin.id);
|
|
162
|
+
const to = servicePath(pin.id);
|
|
163
|
+
if (!service || !to) return null;
|
|
164
|
+
return {
|
|
165
|
+
...base,
|
|
166
|
+
kind: "service",
|
|
167
|
+
name: service.name,
|
|
168
|
+
path: to,
|
|
169
|
+
contextId: index.serviceContext.get(pin.id)?.id ?? null,
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
case "aggregate": {
|
|
173
|
+
const aggregate = index.aggregateById.get(pin.id);
|
|
174
|
+
const owner = index.aggregateOwner.get(pin.id);
|
|
175
|
+
const to = aggregatePath(pin.id);
|
|
176
|
+
if (!aggregate || !owner || !to) return null;
|
|
177
|
+
return {
|
|
178
|
+
...base,
|
|
179
|
+
kind: "aggregate",
|
|
180
|
+
name: aggregate.name,
|
|
181
|
+
path: to,
|
|
182
|
+
contextId: index.serviceContext.get(owner.id)?.id ?? null,
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
case "table": {
|
|
186
|
+
const held = index.tableById.get(pin.id);
|
|
187
|
+
const to = tablePath(pin.id);
|
|
188
|
+
if (!held || !to) return null;
|
|
189
|
+
return {
|
|
190
|
+
...base,
|
|
191
|
+
kind: "table",
|
|
192
|
+
name: held.table.name,
|
|
193
|
+
path: to,
|
|
194
|
+
contextId: index.serviceContext.get(held.store.owner)?.id ?? null,
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* The pin control, and the only one. It says what it will do rather than what
|
|
202
|
+
* the state is - "Pin" / "Unpin" - because a filled pin icon on its own reads
|
|
203
|
+
* as decoration on a page a reader has never pinned.
|
|
204
|
+
*/
|
|
205
|
+
export function PinButton({
|
|
206
|
+
kind,
|
|
207
|
+
id,
|
|
208
|
+
label,
|
|
209
|
+
size = 16,
|
|
210
|
+
}: {
|
|
211
|
+
kind: PinKind;
|
|
212
|
+
id: string;
|
|
213
|
+
/** What the tooltip names, when the catalog id is not what a reader calls it. */
|
|
214
|
+
label?: string;
|
|
215
|
+
size?: number;
|
|
216
|
+
}) {
|
|
217
|
+
const pin: Pin = { kind, id };
|
|
218
|
+
const pinned = useIsPinned(pin);
|
|
219
|
+
const toggle = usePinsStore((s) => s.toggle);
|
|
220
|
+
const what = label ?? id;
|
|
221
|
+
const title = pinned
|
|
222
|
+
? `Unpin ${what}`
|
|
223
|
+
: `Pin ${what} to the top of the catalog`;
|
|
224
|
+
return (
|
|
225
|
+
<button
|
|
226
|
+
type="button"
|
|
227
|
+
onClick={() => toggle(pin)}
|
|
228
|
+
aria-pressed={pinned}
|
|
229
|
+
aria-label={title}
|
|
230
|
+
title={title}
|
|
231
|
+
className={`flex size-7 shrink-0 items-center justify-center rounded-control t-micro transition-colors hover:bg-surface ${
|
|
232
|
+
pinned ? "text-accent" : "text-muted hover:text-ink"
|
|
233
|
+
}`}
|
|
234
|
+
>
|
|
235
|
+
{pinned ? (
|
|
236
|
+
<PinOff size={size} aria-hidden />
|
|
237
|
+
) : (
|
|
238
|
+
<PinIcon size={size} aria-hidden />
|
|
239
|
+
)}
|
|
240
|
+
</button>
|
|
241
|
+
);
|
|
242
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { QueryClient } from "@tanstack/react-query";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* One client for everything the app reads over the network at runtime: forge
|
|
5
|
+
* branches and catalogs, source previews, the local API's status.
|
|
6
|
+
*
|
|
7
|
+
* The defaults are deliberately quiet. A forge answers 401, 404 or a rate
|
|
8
|
+
* limit, and repeating those only hides the message and spends the limit, so
|
|
9
|
+
* nothing retries. Nothing refetches on focus or reconnect either: a reader
|
|
10
|
+
* flipping between tabs must not spend GitHub requests. Data stays fresh for
|
|
11
|
+
* the session, which is what the hand-written promise caches did before; the
|
|
12
|
+
* comparison page's "Try again" resets the forge queries explicitly.
|
|
13
|
+
*/
|
|
14
|
+
export const queryClient = new QueryClient({
|
|
15
|
+
defaultOptions: {
|
|
16
|
+
queries: {
|
|
17
|
+
retry: false,
|
|
18
|
+
refetchOnWindowFocus: false,
|
|
19
|
+
refetchOnReconnect: false,
|
|
20
|
+
staleTime: Infinity,
|
|
21
|
+
gcTime: 30 * 60 * 1000,
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
});
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
// Two breakpoints, named once.
|
|
2
|
+
//
|
|
3
|
+
// 1100px is not a phone. It is the width a 13" laptop has left after the reader
|
|
4
|
+
// has put something else beside portolan, and below it the three-pane shell
|
|
5
|
+
// stops being three panes: the tree becomes a drawer and the detail rail
|
|
6
|
+
// becomes a sheet. That is graceful degradation of a desktop tool, not a mobile
|
|
7
|
+
// design, and nothing below this line pretends otherwise.
|
|
8
|
+
//
|
|
9
|
+
// 640px is a phone held upright, and it is a second thing entirely. The shell
|
|
10
|
+
// has already degraded by then; what runs out at this width is the top bar's
|
|
11
|
+
// own row, which carries a search box, five controls and a build stamp beside
|
|
12
|
+
// the breadcrumbs. Wrapping turned that into three rows of chrome above a page
|
|
13
|
+
// that had four rows of its own, so below this width the bar keeps one row and
|
|
14
|
+
// puts what does not fit behind an icon.
|
|
15
|
+
|
|
16
|
+
import { useEffect, useState } from "react";
|
|
17
|
+
|
|
18
|
+
const NARROW_QUERY = "(max-width: 1099px)";
|
|
19
|
+
const PHONE_QUERY = "(max-width: 639px)";
|
|
20
|
+
|
|
21
|
+
function match(query: string): boolean {
|
|
22
|
+
if (typeof window === "undefined" || !window.matchMedia) return false;
|
|
23
|
+
return window.matchMedia(query).matches;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function useMediaQuery(query: string): boolean {
|
|
27
|
+
const [on, setOn] = useState(() => match(query));
|
|
28
|
+
useEffect(() => {
|
|
29
|
+
if (typeof window === "undefined" || !window.matchMedia) return;
|
|
30
|
+
const mq = window.matchMedia(query);
|
|
31
|
+
const onChange = () => setOn(mq.matches);
|
|
32
|
+
mq.addEventListener("change", onChange);
|
|
33
|
+
// The resize listener is the belt to matchMedia's braces. Under a viewport
|
|
34
|
+
// that is emulated rather than dragged - devtools, a screenshot harness -
|
|
35
|
+
// the media query updates but its change event never fires, and the shell
|
|
36
|
+
// would sit in the wrong layout until the next reload.
|
|
37
|
+
window.addEventListener("resize", onChange);
|
|
38
|
+
onChange();
|
|
39
|
+
return () => {
|
|
40
|
+
mq.removeEventListener("change", onChange);
|
|
41
|
+
window.removeEventListener("resize", onChange);
|
|
42
|
+
};
|
|
43
|
+
}, [query]);
|
|
44
|
+
return on;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/** True while the viewport is too narrow to hold the panes side by side. */
|
|
48
|
+
export function useNarrow(): boolean {
|
|
49
|
+
return useMediaQuery(NARROW_QUERY);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/** True while the viewport is too narrow to hold the top bar on one row. */
|
|
53
|
+
export function usePhone(): boolean {
|
|
54
|
+
return useMediaQuery(PHONE_QUERY);
|
|
55
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
// The "?" sheet is only useful if it is true. These are the two ways it could
|
|
2
|
+
// stop being true: a chord that goes nowhere, and a key bound twice.
|
|
3
|
+
|
|
4
|
+
import { describe, expect, it } from "vitest";
|
|
5
|
+
import { GO_TO, SHORTCUT_GROUPS } from "./shortcuts";
|
|
6
|
+
import { isRoutable } from "../routes";
|
|
7
|
+
|
|
8
|
+
describe("go-to chords", () => {
|
|
9
|
+
it("every destination is a route this app actually serves", () => {
|
|
10
|
+
for (const target of GO_TO) {
|
|
11
|
+
expect(isRoutable(target.to), `g ${target.key} -> ${target.to}`).toBe(
|
|
12
|
+
true,
|
|
13
|
+
);
|
|
14
|
+
}
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
it("binds each second key once", () => {
|
|
18
|
+
const keys = GO_TO.map((g) => g.key);
|
|
19
|
+
expect(new Set(keys).size).toBe(keys.length);
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
it("is what the sheet prints", () => {
|
|
23
|
+
const listed =
|
|
24
|
+
SHORTCUT_GROUPS.find((g) => g.group === "Go to")?.items ?? [];
|
|
25
|
+
expect(listed.map((i) => i.keys)).toEqual(GO_TO.map((g) => ["g", g.key]));
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
describe("the sheet", () => {
|
|
30
|
+
it("names every key the handler implements", () => {
|
|
31
|
+
const printed = SHORTCUT_GROUPS.flatMap((g) => g.items).flatMap(
|
|
32
|
+
(i) => i.keys,
|
|
33
|
+
);
|
|
34
|
+
// Everything useShortcuts binds outside the go-to chord.
|
|
35
|
+
for (const key of ["[", "]", "j", "k", "?", "⌘", "K", "Esc", "⏎"]) {
|
|
36
|
+
expect(printed, `"${key}" is bound but not listed`).toContain(key);
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
});
|