@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,157 @@
|
|
|
1
|
+
// The visual half of the taxonomy in src/lib/kinds.ts. One icon per kind,
|
|
2
|
+
// painted from a token, so nothing downstream picks its own glyph or colour.
|
|
3
|
+
|
|
4
|
+
import {
|
|
5
|
+
Database,
|
|
6
|
+
Eye,
|
|
7
|
+
Globe,
|
|
8
|
+
Hexagon,
|
|
9
|
+
ListChecks,
|
|
10
|
+
Package,
|
|
11
|
+
Route,
|
|
12
|
+
ScrollText,
|
|
13
|
+
Server,
|
|
14
|
+
Shapes,
|
|
15
|
+
Table2,
|
|
16
|
+
Webhook,
|
|
17
|
+
WholeWord,
|
|
18
|
+
} from "lucide-react";
|
|
19
|
+
import type { Kind } from "../lib/kinds";
|
|
20
|
+
import { ctxStyle } from "../lib/context-color";
|
|
21
|
+
import {
|
|
22
|
+
CommandIcon,
|
|
23
|
+
EntityIcon,
|
|
24
|
+
EventIcon,
|
|
25
|
+
QueryIcon,
|
|
26
|
+
ValueObjectIcon,
|
|
27
|
+
} from "./ddd-icons";
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Anything that takes `size` and paints itself from `currentColor` - lucide's
|
|
31
|
+
* icons and portolan's own five, which are drawn on lucide's grid precisely so
|
|
32
|
+
* this type can cover both.
|
|
33
|
+
*/
|
|
34
|
+
type IconComponent = (props: {
|
|
35
|
+
size?: number;
|
|
36
|
+
className?: string;
|
|
37
|
+
style?: React.CSSProperties;
|
|
38
|
+
"aria-hidden"?: boolean;
|
|
39
|
+
}) => React.ReactNode;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* The five DDD building blocks are drawn in ./ddd-icons; everything else is
|
|
43
|
+
* app chrome and stays lucide. That split is the rule, not a coincidence: a
|
|
44
|
+
* domain concept gets a mark that says what it is, a piece of furniture gets
|
|
45
|
+
* the furniture library.
|
|
46
|
+
*/
|
|
47
|
+
const KIND_ICON: Record<Kind, IconComponent> = {
|
|
48
|
+
context: Hexagon, // unused: contexts draw a coloured dot instead
|
|
49
|
+
// Outside the estate, so the one mark that says "the rest of the world".
|
|
50
|
+
external: Globe,
|
|
51
|
+
service: Server,
|
|
52
|
+
aggregate: Hexagon,
|
|
53
|
+
// A store and a table are infrastructure, not domain objects, so they take
|
|
54
|
+
// lucide's furniture rather than one of portolan's five domain marks.
|
|
55
|
+
store: Database,
|
|
56
|
+
table: Table2,
|
|
57
|
+
// A view is drawn as an eye rather than a second grid: what separates it
|
|
58
|
+
// from a table is that it is a way of LOOKING at rows, not a place they are.
|
|
59
|
+
view: Eye,
|
|
60
|
+
event: EventIcon,
|
|
61
|
+
vo: ValueObjectIcon,
|
|
62
|
+
entity: EntityIcon,
|
|
63
|
+
// An enum is a list a consumer ticks through - one of these, and no other.
|
|
64
|
+
// Furniture rather than a sixth domain mark: the five say what a block IS,
|
|
65
|
+
// and a set of values is what a field HOLDS.
|
|
66
|
+
enum: ListChecks,
|
|
67
|
+
command: CommandIcon,
|
|
68
|
+
query: QueryIcon,
|
|
69
|
+
// An endpoint is a door in the wall of a service, not a domain object, so it
|
|
70
|
+
// takes furniture like the store and the table do.
|
|
71
|
+
endpoint: Webhook,
|
|
72
|
+
// A module is a package of schema someone published - infrastructure again,
|
|
73
|
+
// and a box is what a registry hands you.
|
|
74
|
+
module: Package,
|
|
75
|
+
def: Shapes,
|
|
76
|
+
flow: Route,
|
|
77
|
+
adr: ScrollText,
|
|
78
|
+
// A term is a word, and the mark says so. It is deliberately NOT one of the
|
|
79
|
+
// five domain marks: the glossary names the building blocks, it is not one
|
|
80
|
+
// of them, and a term wearing an aggregate's hexagon would say it was.
|
|
81
|
+
term: WholeWord,
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Colour by kind. Domain events are the loudest leaf in the tree because they
|
|
86
|
+
* are the thing other contexts actually depend on; structural blocks stay grey
|
|
87
|
+
* so they read as detail inside the aggregate that owns them.
|
|
88
|
+
*/
|
|
89
|
+
export const KIND_COLOR: Record<Kind, string> = {
|
|
90
|
+
context: "var(--ctx)",
|
|
91
|
+
external: "var(--fg-muted)",
|
|
92
|
+
service: "var(--fg-muted)",
|
|
93
|
+
aggregate: "var(--fg)",
|
|
94
|
+
store: "var(--fg-muted)",
|
|
95
|
+
table: "var(--fg-muted)",
|
|
96
|
+
view: "var(--fg-muted)",
|
|
97
|
+
event: "var(--kind-event)",
|
|
98
|
+
vo: "var(--fg-muted)",
|
|
99
|
+
entity: "var(--fg-muted)",
|
|
100
|
+
enum: "var(--fg-muted)",
|
|
101
|
+
command: "var(--fg-muted)",
|
|
102
|
+
query: "var(--fg-muted)",
|
|
103
|
+
endpoint: "var(--fg-muted)",
|
|
104
|
+
module: "var(--fg-muted)",
|
|
105
|
+
def: "var(--fg-muted)",
|
|
106
|
+
flow: "var(--fg-muted)",
|
|
107
|
+
adr: "var(--fg-muted)",
|
|
108
|
+
// A term is painted by the context that means it, like a context row: which
|
|
109
|
+
// vocabulary a word belongs to is the whole of what distinguishes two
|
|
110
|
+
// entries that spell the same word.
|
|
111
|
+
term: "var(--ctx)",
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Icons are 16px wherever one stands on its own - a toolbar button, a page
|
|
116
|
+
* header, the panel's close. Inside a 12px mono row or chip the default drops
|
|
117
|
+
* to 14: the icon labels the identifier next to it, and a 16px glyph beside
|
|
118
|
+
* 12px type reads as the subject rather than the label.
|
|
119
|
+
*/
|
|
120
|
+
export function KindIcon({
|
|
121
|
+
kind,
|
|
122
|
+
contextId,
|
|
123
|
+
size = 14,
|
|
124
|
+
className = "",
|
|
125
|
+
}: {
|
|
126
|
+
kind: Kind;
|
|
127
|
+
/** Required for `context`, which is painted in that context's own colour. */
|
|
128
|
+
contextId?: string;
|
|
129
|
+
size?: number;
|
|
130
|
+
className?: string;
|
|
131
|
+
}) {
|
|
132
|
+
if (kind === "context") {
|
|
133
|
+
return (
|
|
134
|
+
<span
|
|
135
|
+
aria-hidden
|
|
136
|
+
className={`inline-block shrink-0 rounded-full ${className}`}
|
|
137
|
+
style={{
|
|
138
|
+
width: size - 3,
|
|
139
|
+
height: size - 3,
|
|
140
|
+
background: "var(--ctx)",
|
|
141
|
+
...ctxStyle(contextId),
|
|
142
|
+
}}
|
|
143
|
+
/>
|
|
144
|
+
);
|
|
145
|
+
}
|
|
146
|
+
const Icon = KIND_ICON[kind];
|
|
147
|
+
return (
|
|
148
|
+
<Icon
|
|
149
|
+
size={size}
|
|
150
|
+
aria-hidden
|
|
151
|
+
/* `block` drops the inline baseline gap so the glyph centres on the
|
|
152
|
+
cap-height of the text beside it rather than sitting on its baseline. */
|
|
153
|
+
className={`block shrink-0 ${className}`}
|
|
154
|
+
style={{ color: KIND_COLOR[kind] }}
|
|
155
|
+
/>
|
|
156
|
+
);
|
|
157
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
// The mark.
|
|
2
|
+
//
|
|
3
|
+
// A portolan chart is drawn around wind roses: a circle with the rhumb lines
|
|
4
|
+
// radiating out of it, one long point for each cardinal direction and a shorter
|
|
5
|
+
// one between. That is the whole logo - no gradient, no second colour, nothing
|
|
6
|
+
// that stops being a logo at 16px.
|
|
7
|
+
//
|
|
8
|
+
// The star is filled and the ring is stroked, which is the only reason the
|
|
9
|
+
// points still read as points at favicon size: eight hairlines crossing inside
|
|
10
|
+
// a 16px box turn into a grey smudge, eight solid wedges do not.
|
|
11
|
+
|
|
12
|
+
import type { SVGProps } from "react";
|
|
13
|
+
|
|
14
|
+
/** The 8-point rose, tips crossing a ring, drawn on the same 24 grid as the icons. */
|
|
15
|
+
export const ROSE_STAR =
|
|
16
|
+
"M 12 1.4 L 12.96 9.69 L 16.38 7.62 L 14.31 11.04 L 22.6 12 L 14.31 12.96 L 16.38 16.38 L 12.96 14.31 L 12 22.6 L 11.04 14.31 L 7.62 16.38 L 9.69 12.96 L 1.4 12 L 9.69 11.04 L 7.62 7.62 L 11.04 9.69 Z";
|
|
17
|
+
|
|
18
|
+
export function CompassRose({
|
|
19
|
+
size = 16,
|
|
20
|
+
...rest
|
|
21
|
+
}: Omit<SVGProps<SVGSVGElement>, "ref"> & { size?: number }) {
|
|
22
|
+
return (
|
|
23
|
+
<svg
|
|
24
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
25
|
+
width={size}
|
|
26
|
+
height={size}
|
|
27
|
+
viewBox="0 0 24 24"
|
|
28
|
+
fill="none"
|
|
29
|
+
aria-hidden
|
|
30
|
+
{...rest}
|
|
31
|
+
>
|
|
32
|
+
<circle
|
|
33
|
+
cx={12}
|
|
34
|
+
cy={12}
|
|
35
|
+
r={7.1}
|
|
36
|
+
stroke="currentColor"
|
|
37
|
+
strokeWidth={1.4}
|
|
38
|
+
opacity={0.55}
|
|
39
|
+
/>
|
|
40
|
+
<path d={ROSE_STAR} fill="currentColor" />
|
|
41
|
+
</svg>
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Mark plus wordmark, for the sidebar header. Lowercase and set in the mono
|
|
47
|
+
* face: the name is an identifier like everything else this app names.
|
|
48
|
+
*/
|
|
49
|
+
export function Wordmark({ size = 16 }: { size?: number }) {
|
|
50
|
+
return (
|
|
51
|
+
<span className="flex items-center gap-2 text-ink">
|
|
52
|
+
<CompassRose size={size} className="shrink-0" />
|
|
53
|
+
<span
|
|
54
|
+
className="text-sm font-semibold lowercase"
|
|
55
|
+
style={{ letterSpacing: "-0.01em" }}
|
|
56
|
+
>
|
|
57
|
+
portolan
|
|
58
|
+
</span>
|
|
59
|
+
</span>
|
|
60
|
+
);
|
|
61
|
+
}
|
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
import { Link } from "react-router";
|
|
2
|
+
import type { ReactNode } from "react";
|
|
3
|
+
import type {
|
|
4
|
+
Adr,
|
|
5
|
+
AdrScope,
|
|
6
|
+
AdrStatus,
|
|
7
|
+
Classification,
|
|
8
|
+
Status,
|
|
9
|
+
} from "../catalog";
|
|
10
|
+
import { index } from "../data";
|
|
11
|
+
import { adrNumber } from "../lib/adr";
|
|
12
|
+
import { ctxStyle } from "../lib/context-color";
|
|
13
|
+
import { paths } from "../routes";
|
|
14
|
+
|
|
15
|
+
const STATUS_LABEL: Record<Status, string> = {
|
|
16
|
+
verified: "verified",
|
|
17
|
+
declared: "declared",
|
|
18
|
+
unresolved: "unresolved",
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
/** Component class that paints text and border for a status. */
|
|
22
|
+
const STATUS_CLASS: Record<Status, string> = {
|
|
23
|
+
verified: "status-verified",
|
|
24
|
+
declared: "status-declared",
|
|
25
|
+
unresolved: "status-unresolved",
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
/** Raw value, for SVG strokes and React Flow edges that cannot take a class. */
|
|
29
|
+
export function statusVar(status: Status): string {
|
|
30
|
+
return `var(--status-${status})`;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function StatusChip({
|
|
34
|
+
status,
|
|
35
|
+
title,
|
|
36
|
+
}: {
|
|
37
|
+
status: Status;
|
|
38
|
+
title?: string;
|
|
39
|
+
}) {
|
|
40
|
+
return (
|
|
41
|
+
<span
|
|
42
|
+
title={title ?? `status: ${status}`}
|
|
43
|
+
className={`chip ${STATUS_CLASS[status]}`}
|
|
44
|
+
>
|
|
45
|
+
<span aria-hidden className="dot" />
|
|
46
|
+
{STATUS_LABEL[status]}
|
|
47
|
+
</span>
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export function ContextPill({ id, name }: { id: string; name?: string }) {
|
|
52
|
+
return (
|
|
53
|
+
<span className="chip ctx" style={ctxStyle(id)}>
|
|
54
|
+
<span aria-hidden className="dot" />
|
|
55
|
+
{name ?? id}
|
|
56
|
+
</span>
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* How strategically a bounded context is rated, said in one word. Core is the
|
|
62
|
+
* only one worth the accent - "supporting" and "generic" are the answer "not
|
|
63
|
+
* where the value is", and a row full of loud badges says nothing at all.
|
|
64
|
+
*/
|
|
65
|
+
const CLASSIFICATION_META: Record<
|
|
66
|
+
Classification,
|
|
67
|
+
{ className: string; title: string }
|
|
68
|
+
> = {
|
|
69
|
+
core: {
|
|
70
|
+
className: "border-accent text-accent",
|
|
71
|
+
title: "core domain - where this estate competes",
|
|
72
|
+
},
|
|
73
|
+
supporting: {
|
|
74
|
+
className: "border-line-strong text-muted",
|
|
75
|
+
title: "supporting domain - needed here, but not a differentiator",
|
|
76
|
+
},
|
|
77
|
+
generic: {
|
|
78
|
+
className: "border-line-strong text-muted",
|
|
79
|
+
title: "generic domain - a solved problem, bought or borrowed",
|
|
80
|
+
},
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* The classification badge, and the only place it is drawn. A context with no
|
|
85
|
+
* classification renders nothing: an unrated domain is not a "generic" one, and
|
|
86
|
+
* a placeholder would state a call the estate has not made.
|
|
87
|
+
*
|
|
88
|
+
* `tiny` is the sidebar's 10px variant, where the badge rides at the end of a
|
|
89
|
+
* tree row and must not compete with the context name it annotates.
|
|
90
|
+
*/
|
|
91
|
+
export function ClassificationBadge({
|
|
92
|
+
classification,
|
|
93
|
+
tiny = false,
|
|
94
|
+
}: {
|
|
95
|
+
classification?: Classification;
|
|
96
|
+
tiny?: boolean;
|
|
97
|
+
}) {
|
|
98
|
+
if (!classification) return null;
|
|
99
|
+
const meta = CLASSIFICATION_META[classification];
|
|
100
|
+
return (
|
|
101
|
+
<span
|
|
102
|
+
className={`chip shrink-0 ${meta.className}`}
|
|
103
|
+
style={tiny ? { fontSize: 10, lineHeight: "14px" } : undefined}
|
|
104
|
+
title={meta.title}
|
|
105
|
+
>
|
|
106
|
+
{classification}
|
|
107
|
+
</span>
|
|
108
|
+
);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// ---------------------------------------------------------------------------
|
|
112
|
+
// Decision records
|
|
113
|
+
// ---------------------------------------------------------------------------
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Green for what holds, amber for what is still being argued, grey for what is
|
|
117
|
+
* only history. Grey covers three different endings, so the badge says which.
|
|
118
|
+
*/
|
|
119
|
+
const ADR_STATUS_CLASS: Record<AdrStatus, string> = {
|
|
120
|
+
accepted: "status-verified",
|
|
121
|
+
proposed: "status-declared",
|
|
122
|
+
superseded: "border-line-strong text-muted",
|
|
123
|
+
deprecated: "border-line-strong text-muted",
|
|
124
|
+
rejected: "border-line-strong text-muted",
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
/** True for records that are no longer in force; their number is struck out. */
|
|
128
|
+
export function isStruck(status: AdrStatus): boolean {
|
|
129
|
+
return status === "superseded" || status === "deprecated";
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
export function AdrStatusChip({ status }: { status: AdrStatus }) {
|
|
133
|
+
return (
|
|
134
|
+
<span
|
|
135
|
+
title={`status: ${status}`}
|
|
136
|
+
className={`chip ${ADR_STATUS_CLASS[status]}`}
|
|
137
|
+
>
|
|
138
|
+
<span aria-hidden className="dot" />
|
|
139
|
+
{status}
|
|
140
|
+
</span>
|
|
141
|
+
);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/** "ADR-0007", struck through once the decision no longer holds. */
|
|
145
|
+
export function AdrNumber({
|
|
146
|
+
adr,
|
|
147
|
+
className = "",
|
|
148
|
+
}: {
|
|
149
|
+
adr: Adr;
|
|
150
|
+
className?: string;
|
|
151
|
+
}) {
|
|
152
|
+
const struck = isStruck(adr.status);
|
|
153
|
+
return (
|
|
154
|
+
<span
|
|
155
|
+
className={`mono ${struck ? "line-through text-muted" : ""} ${className}`}
|
|
156
|
+
title={struck ? `${adr.id} - no longer in force` : adr.id}
|
|
157
|
+
>
|
|
158
|
+
{adrNumber(adr)}
|
|
159
|
+
</span>
|
|
160
|
+
);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* The scope a decision was taken at, linking to the page it governs. Pass
|
|
165
|
+
* `link={false}` inside a row that is itself a link: an anchor cannot contain
|
|
166
|
+
* another one.
|
|
167
|
+
*/
|
|
168
|
+
export function AdrScopePill({
|
|
169
|
+
scope,
|
|
170
|
+
link = true,
|
|
171
|
+
}: {
|
|
172
|
+
scope: AdrScope;
|
|
173
|
+
link?: boolean;
|
|
174
|
+
}) {
|
|
175
|
+
if (scope.kind === "org") {
|
|
176
|
+
return (
|
|
177
|
+
<span className="chip border-line-strong text-muted" title="org-wide">
|
|
178
|
+
<span aria-hidden className="dot" />
|
|
179
|
+
org
|
|
180
|
+
</span>
|
|
181
|
+
);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
if (scope.kind === "context") {
|
|
185
|
+
const body = (
|
|
186
|
+
<>
|
|
187
|
+
<span aria-hidden className="dot" />
|
|
188
|
+
{scope.context}
|
|
189
|
+
</>
|
|
190
|
+
);
|
|
191
|
+
const props = {
|
|
192
|
+
className: "chip ctx",
|
|
193
|
+
style: ctxStyle(scope.context),
|
|
194
|
+
title: `context ${scope.context}`,
|
|
195
|
+
};
|
|
196
|
+
return link ? (
|
|
197
|
+
<Link to={paths.context(scope.context)} {...props}>
|
|
198
|
+
{body}
|
|
199
|
+
</Link>
|
|
200
|
+
) : (
|
|
201
|
+
<span {...props}>{body}</span>
|
|
202
|
+
);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
const context = index.serviceContext.get(scope.service);
|
|
206
|
+
const service = index.serviceById.get(scope.service);
|
|
207
|
+
if (!context || !service) {
|
|
208
|
+
return (
|
|
209
|
+
<span className="chip status-unresolved">
|
|
210
|
+
<span aria-hidden className="dot" />
|
|
211
|
+
{scope.service}
|
|
212
|
+
</span>
|
|
213
|
+
);
|
|
214
|
+
}
|
|
215
|
+
const body = (
|
|
216
|
+
<>
|
|
217
|
+
<span aria-hidden className="dot" />
|
|
218
|
+
{scope.service}
|
|
219
|
+
</>
|
|
220
|
+
);
|
|
221
|
+
const props = {
|
|
222
|
+
className: "chip ctx",
|
|
223
|
+
style: ctxStyle(context.id),
|
|
224
|
+
title: `service ${scope.service}`,
|
|
225
|
+
};
|
|
226
|
+
return link ? (
|
|
227
|
+
<Link to={paths.service(context.id, service.slug)} {...props}>
|
|
228
|
+
{body}
|
|
229
|
+
</Link>
|
|
230
|
+
) : (
|
|
231
|
+
<span {...props}>{body}</span>
|
|
232
|
+
);
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
export function Panel({
|
|
236
|
+
title,
|
|
237
|
+
children,
|
|
238
|
+
}: {
|
|
239
|
+
title: string;
|
|
240
|
+
children: ReactNode;
|
|
241
|
+
}) {
|
|
242
|
+
return (
|
|
243
|
+
<section className="overflow-hidden rounded-card border border-line shadow-xs">
|
|
244
|
+
<h2 className="label border-b border-line bg-surface px-4 py-2">
|
|
245
|
+
{title}
|
|
246
|
+
</h2>
|
|
247
|
+
<div className="p-4">{children}</div>
|
|
248
|
+
</section>
|
|
249
|
+
);
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
export function ExternalLink({
|
|
253
|
+
to,
|
|
254
|
+
children,
|
|
255
|
+
}: {
|
|
256
|
+
to: string;
|
|
257
|
+
children: ReactNode;
|
|
258
|
+
}) {
|
|
259
|
+
return (
|
|
260
|
+
<Link to={to} className="mono rounded-control text-accent hover:underline">
|
|
261
|
+
{children}
|
|
262
|
+
</Link>
|
|
263
|
+
);
|
|
264
|
+
}
|
package/src/data.test.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
import { describe, expect, it } from "vitest";
|
|
3
|
+
|
|
4
|
+
import { SOURCE_GLOBS } from "./data";
|
|
5
|
+
|
|
6
|
+
// The site cannot read the manifest: import.meta.glob resolves at build time
|
|
7
|
+
// and needs literals, so the patterns are written out twice - once in
|
|
8
|
+
// portolan.json for the host, once in data.ts for the site. This is what keeps
|
|
9
|
+
// the two copies one list: a source the host merges and the site never loads
|
|
10
|
+
// is a page that exists in docs/ and nowhere on the site.
|
|
11
|
+
describe("the site's source globs", () => {
|
|
12
|
+
it("are the manifest's sources, in the manifest's order", () => {
|
|
13
|
+
const manifest = JSON.parse(
|
|
14
|
+
readFileSync(new URL("../portolan.json", import.meta.url), "utf8"),
|
|
15
|
+
) as { sources: string[] };
|
|
16
|
+
expect([...SOURCE_GLOBS]).toEqual(manifest.sources);
|
|
17
|
+
});
|
|
18
|
+
});
|
package/src/data.ts
ADDED
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
// Single entry point for catalog data.
|
|
2
|
+
//
|
|
3
|
+
// There is no master catalog. The app reads every source it can find, merges
|
|
4
|
+
// them, and validates the union - in that order, because referential integrity
|
|
5
|
+
// is a property of the whole estate and not of any one file. A service that
|
|
6
|
+
// publishes facts about itself next to its own code is a source; so is a
|
|
7
|
+
// hand-written file carrying the prose nobody can generate.
|
|
8
|
+
//
|
|
9
|
+
// Validation happens here, at startup, so a bad generator run is caught before
|
|
10
|
+
// anything is drawn. It is caught, not thrown: a validator that throws out of a
|
|
11
|
+
// module's top level takes the whole bundle down and the reader gets a blank
|
|
12
|
+
// page and a line in a console they are not looking at. So the failure is
|
|
13
|
+
// turned into a value, the app falls back to an empty catalog so every module
|
|
14
|
+
// below still imports, and the shell renders the error instead of the routes.
|
|
15
|
+
|
|
16
|
+
import { buildIndex, CatalogError, validateCatalog } from "./catalog";
|
|
17
|
+
import type { Catalog, CatalogIndex } from "./catalog";
|
|
18
|
+
import {
|
|
19
|
+
catalogProfileNamed,
|
|
20
|
+
catalogProfiles as profilesFromManifest,
|
|
21
|
+
filterCatalogForProfile,
|
|
22
|
+
profileIncludesSource,
|
|
23
|
+
} from "./catalog-profile";
|
|
24
|
+
import type { CatalogProfile, CatalogProfileManifest } from "./catalog-profile";
|
|
25
|
+
import { enrichCatalog } from "./enrich";
|
|
26
|
+
import type { DerivedEdge } from "./enrich";
|
|
27
|
+
import { mergeCatalogs } from "./merge";
|
|
28
|
+
import type {
|
|
29
|
+
CatalogSource,
|
|
30
|
+
MergeConflict,
|
|
31
|
+
SourceCatalog,
|
|
32
|
+
SourceStamp,
|
|
33
|
+
} from "./merge";
|
|
34
|
+
import manifestJson from "../portolan.json";
|
|
35
|
+
|
|
36
|
+
const manifest = manifestJson as CatalogProfileManifest & { sources: string[] };
|
|
37
|
+
export const catalogProfiles: CatalogProfile[] = profilesFromManifest(manifest);
|
|
38
|
+
const requestedProfile =
|
|
39
|
+
typeof window === "undefined"
|
|
40
|
+
? null
|
|
41
|
+
: new URLSearchParams(window.location.search).get("catalog");
|
|
42
|
+
export const activeCatalogProfile = catalogProfileNamed(manifest, requestedProfile);
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Where sources are looked for. The patterns are written out because
|
|
46
|
+
* import.meta.glob resolves at build time and needs literals - and because
|
|
47
|
+
* they are worth reading: the first is the estate's own files, the second is
|
|
48
|
+
* what each service publishes beside its code - one level down for a context
|
|
49
|
+
* of one service, two for a context that holds several.
|
|
50
|
+
*/
|
|
51
|
+
export const SOURCE_GLOBS = [
|
|
52
|
+
"data/*.json",
|
|
53
|
+
"portolan/*.json",
|
|
54
|
+
"examples/*/portolan/*.json",
|
|
55
|
+
"examples/*/*/portolan/*.json",
|
|
56
|
+
"examples/*/*/*/portolan/*.json",
|
|
57
|
+
"vendor/repos/*/*/git.repo.json",
|
|
58
|
+
"vendor/repos/**/portolan/*.json",
|
|
59
|
+
] as const;
|
|
60
|
+
|
|
61
|
+
const modules: Record<string, unknown> = {
|
|
62
|
+
...import.meta.glob("../data/*.json", { eager: true, import: "default" }),
|
|
63
|
+
...import.meta.glob("../portolan/*.json", { eager: true, import: "default" }),
|
|
64
|
+
...import.meta.glob("../examples/*/portolan/*.json", {
|
|
65
|
+
eager: true,
|
|
66
|
+
import: "default",
|
|
67
|
+
}),
|
|
68
|
+
...import.meta.glob("../examples/*/*/portolan/*.json", {
|
|
69
|
+
eager: true,
|
|
70
|
+
import: "default",
|
|
71
|
+
}),
|
|
72
|
+
...import.meta.glob("../examples/*/*/*/portolan/*.json", {
|
|
73
|
+
eager: true,
|
|
74
|
+
import: "default",
|
|
75
|
+
}),
|
|
76
|
+
...import.meta.glob("../vendor/repos/*/*/git.repo.json", {
|
|
77
|
+
eager: true,
|
|
78
|
+
import: "default",
|
|
79
|
+
}),
|
|
80
|
+
...import.meta.glob("../vendor/repos/**/portolan/*.json", {
|
|
81
|
+
eager: true,
|
|
82
|
+
import: "default",
|
|
83
|
+
}),
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
/** What the app draws when the catalog cannot be trusted: nothing. */
|
|
87
|
+
const EMPTY: Catalog = {
|
|
88
|
+
generatedAt: "",
|
|
89
|
+
commit: "",
|
|
90
|
+
contexts: [],
|
|
91
|
+
defs: {},
|
|
92
|
+
flows: [],
|
|
93
|
+
adrs: [],
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
interface Loaded {
|
|
97
|
+
catalog: Catalog;
|
|
98
|
+
sources: SourceStamp[];
|
|
99
|
+
conflicts: MergeConflict[];
|
|
100
|
+
derived: DerivedEdge[];
|
|
101
|
+
error: CatalogError | null;
|
|
102
|
+
/** The sources as merged, before anything was derived or checked. */
|
|
103
|
+
raw: Catalog;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function load(): Loaded {
|
|
107
|
+
const sources: CatalogSource[] = Object.entries(modules)
|
|
108
|
+
.map(([path, catalog]) => ({
|
|
109
|
+
// Vite keys a glob by its pattern-relative path; the leading ../ is an
|
|
110
|
+
// artefact of this file's location, not part of where anything lives.
|
|
111
|
+
path: path.replace(/^\.\.\//, ""),
|
|
112
|
+
// A SOURCE, not a catalog: the two stamps are optional in a file, and
|
|
113
|
+
// the estate's authored facts carry neither.
|
|
114
|
+
catalog: catalog as SourceCatalog,
|
|
115
|
+
}))
|
|
116
|
+
.filter((source) => profileIncludesSource(activeCatalogProfile, source.path));
|
|
117
|
+
|
|
118
|
+
const merged = mergeCatalogs(sources);
|
|
119
|
+
// Enriched before it is validated: the edges the flows imply are part of
|
|
120
|
+
// the union the way a peer named by another source is, and the validator
|
|
121
|
+
// resolves a step's call against them.
|
|
122
|
+
const scoped = filterCatalogForProfile(merged.catalog, activeCatalogProfile);
|
|
123
|
+
const enriched = enrichCatalog(scoped);
|
|
124
|
+
|
|
125
|
+
try {
|
|
126
|
+
return {
|
|
127
|
+
catalog: validateCatalog(enriched.catalog),
|
|
128
|
+
sources: merged.sources,
|
|
129
|
+
conflicts: merged.conflicts,
|
|
130
|
+
derived: enriched.derived,
|
|
131
|
+
error: null,
|
|
132
|
+
raw: merged.catalog,
|
|
133
|
+
};
|
|
134
|
+
} catch (cause) {
|
|
135
|
+
const error =
|
|
136
|
+
cause instanceof CatalogError
|
|
137
|
+
? cause
|
|
138
|
+
: // Anything else is a shape the validator never got far enough to
|
|
139
|
+
// name - a truncated file, a null where a list was expected. Same
|
|
140
|
+
// treatment.
|
|
141
|
+
new CatalogError(
|
|
142
|
+
cause instanceof Error ? cause.message : String(cause),
|
|
143
|
+
);
|
|
144
|
+
|
|
145
|
+
return {
|
|
146
|
+
catalog: EMPTY,
|
|
147
|
+
sources: merged.sources,
|
|
148
|
+
conflicts: merged.conflicts,
|
|
149
|
+
derived: [],
|
|
150
|
+
error,
|
|
151
|
+
raw: merged.catalog,
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
const loaded = load();
|
|
157
|
+
|
|
158
|
+
export const catalog: Catalog = loaded.catalog;
|
|
159
|
+
export const index: CatalogIndex = buildIndex(catalog);
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* The sources the catalog was built from, newest first by nothing at all -
|
|
163
|
+
* they are in path order, which is the order the merge used.
|
|
164
|
+
*
|
|
165
|
+
* This is what the merged stamp is a summary of, and the summary is lossy in
|
|
166
|
+
* both halves: one date stands for the oldest of many, and "6 sources" stands
|
|
167
|
+
* for six shas the header has no room to print. The Overview stamp opens onto
|
|
168
|
+
* this list, so a reader who wants to know WHICH part is a week old can find
|
|
169
|
+
* out instead of being told a number and left with it. A source with an empty
|
|
170
|
+
* stamp is one nobody generated.
|
|
171
|
+
*/
|
|
172
|
+
export const catalogSources: SourceStamp[] = loaded.sources;
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Sources disagreeing with each other. Not an error: two files both naming a
|
|
176
|
+
* context is normal, and both naming it differently is a fact about the estate
|
|
177
|
+
* that belongs on the Problems page rather than on a crash screen.
|
|
178
|
+
*/
|
|
179
|
+
export const catalogConflicts: MergeConflict[] = loaded.conflicts;
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Consumers and calls no source declared: what the flows said, written onto
|
|
183
|
+
* the events and services after the merge. Each one names the step it was
|
|
184
|
+
* read from, and the catalog above already contains it.
|
|
185
|
+
*/
|
|
186
|
+
export const derivedEdges: DerivedEdge[] = loaded.derived;
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Where the catalog is read from, as a reader would type it. Empty states name
|
|
190
|
+
* it, so it is written once here rather than spelled out on five pages.
|
|
191
|
+
*/
|
|
192
|
+
export const CATALOG_PATH = activeCatalogProfile.sources.join(" · ");
|
|
193
|
+
|
|
194
|
+
/** Non-null when the catalog failed validation; the shell renders it instead. */
|
|
195
|
+
export const catalogError: CatalogError | null = loaded.error;
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* The merge before enrichment and validation: what the sources said, with
|
|
199
|
+
* nothing derived onto it yet. Tests that check the validator, or that want
|
|
200
|
+
* to see the estate the way a source wrote it, start from here.
|
|
201
|
+
*/
|
|
202
|
+
export const rawCatalog: Catalog = loaded.raw;
|