@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,89 @@
|
|
|
1
|
+
package main
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"reflect"
|
|
5
|
+
"sort"
|
|
6
|
+
"strings"
|
|
7
|
+
"testing"
|
|
8
|
+
|
|
9
|
+
"github.com/shortlink-org/portolan/catalog"
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
// Every catalog field must be acknowledged when the mirror grows. Some are
|
|
13
|
+
// printed, others are structural (ids, slugs and union discriminators), but a
|
|
14
|
+
// new field may not disappear from generated documentation by default.
|
|
15
|
+
var catalogCoverage = map[reflect.Type]string{
|
|
16
|
+
reflect.TypeOf(catalog.Catalog{}): "generatedAt commit contexts defs flows adrs stores modules terms repos externals",
|
|
17
|
+
reflect.TypeOf(catalog.External{}): "id slug name summary url provides",
|
|
18
|
+
reflect.TypeOf(catalog.RepoPin{}): "repo commit",
|
|
19
|
+
reflect.TypeOf(catalog.BoundedContext{}): "id slug name summary kind classification viewId services",
|
|
20
|
+
reflect.TypeOf(catalog.Service{}): "id slug name repo path readme kind technologies provides consumes aggregates stores modules channels owners commands",
|
|
21
|
+
reflect.TypeOf(catalog.Command{}): "runner name run doc body source",
|
|
22
|
+
reflect.TypeOf(catalog.RpcService{}): "id methods source messages enums module",
|
|
23
|
+
reflect.TypeOf(catalog.RpcEnum{}): "name doc values",
|
|
24
|
+
reflect.TypeOf(catalog.RpcEnumValue{}): "name number doc",
|
|
25
|
+
reflect.TypeOf(catalog.RpcMethod{}): "name doc request requestRef response responseRef streaming deprecated http soap",
|
|
26
|
+
reflect.TypeOf(catalog.HttpRoute{}): "method path",
|
|
27
|
+
reflect.TypeOf(catalog.SoapRoute{}): "action version style endpoint binding faults headers",
|
|
28
|
+
reflect.TypeOf(catalog.RpcMessage{}): "name fields discriminator",
|
|
29
|
+
reflect.TypeOf(catalog.RpcDiscriminator{}): "property variants",
|
|
30
|
+
reflect.TypeOf(catalog.RpcVariant{}): "value message",
|
|
31
|
+
reflect.TypeOf(catalog.RpcCall{}): "id peer status source note module via",
|
|
32
|
+
reflect.TypeOf(catalog.EdgeVia{}): "flow step",
|
|
33
|
+
reflect.TypeOf(catalog.ProtoModule{}): "id slug name registry owner commit digest packages files deps source",
|
|
34
|
+
reflect.TypeOf(catalog.Aggregate{}): "id slug name readme root entities valueObjects operations events enums lifecycle",
|
|
35
|
+
reflect.TypeOf(catalog.Enum{}): "id slug name doc deprecated values",
|
|
36
|
+
reflect.TypeOf(catalog.EnumValue{}): "name doc deprecated",
|
|
37
|
+
reflect.TypeOf(catalog.Lifecycle{}): "states transitions",
|
|
38
|
+
reflect.TypeOf(catalog.Transition{}): "from to on emits source",
|
|
39
|
+
reflect.TypeOf(catalog.Operation{}): "id kind doc exposedBy",
|
|
40
|
+
reflect.TypeOf(catalog.Block{}): "id slug name doc ref fields",
|
|
41
|
+
reflect.TypeOf(catalog.Event{}): "id slug name versions consumers wire",
|
|
42
|
+
reflect.TypeOf(catalog.EventWire{}): "name channel",
|
|
43
|
+
reflect.TypeOf(catalog.Channel{}): "address kind title doc messages source",
|
|
44
|
+
reflect.TypeOf(catalog.ChannelMessage{}): "name title doc direction",
|
|
45
|
+
reflect.TypeOf(catalog.EventConsumer{}): "service status note via",
|
|
46
|
+
reflect.TypeOf(catalog.EventVersion{}): "version doc source fields",
|
|
47
|
+
reflect.TypeOf(catalog.Field{}): "name type doc ref",
|
|
48
|
+
reflect.TypeOf(catalog.TypeDef{}): "fields",
|
|
49
|
+
reflect.TypeOf(catalog.Store{}): "id slug name kind owner tables views keyspaces source",
|
|
50
|
+
reflect.TypeOf(catalog.RedisKeyspace{}): "pattern operations ttl value source",
|
|
51
|
+
reflect.TypeOf(catalog.Table{}): "id name doc columns indexes persists role",
|
|
52
|
+
reflect.TypeOf(catalog.Persists{}): "aggregate block",
|
|
53
|
+
reflect.TypeOf(catalog.TableIndex{}): "name columns unique",
|
|
54
|
+
reflect.TypeOf(catalog.Column{}): "name type nullable pk fk from maps doc",
|
|
55
|
+
reflect.TypeOf(catalog.FK{}): "table column onDelete",
|
|
56
|
+
reflect.TypeOf(catalog.View{}): "id name doc materialized columns reads definition persists source",
|
|
57
|
+
reflect.TypeOf(catalog.Flow{}): "id slug name summary source trigger entrypoint includes owner participants steps",
|
|
58
|
+
reflect.TypeOf(catalog.FlowTrigger{}): "kind label confidence",
|
|
59
|
+
reflect.TypeOf(catalog.Participant{}): "id kind context label",
|
|
60
|
+
reflect.TypeOf(catalog.Step{}): "type id from to kind ref label status note line continuesAt reaches handoff",
|
|
61
|
+
reflect.TypeOf(catalog.FlowHandoff{}): "kind transport channel message direction",
|
|
62
|
+
reflect.TypeOf(catalog.Parallel{}): "type id title branches",
|
|
63
|
+
reflect.TypeOf(catalog.Alt{}): "type id branches",
|
|
64
|
+
reflect.TypeOf(catalog.AltBranch{}): "title steps terminal",
|
|
65
|
+
reflect.TypeOf(catalog.Loop{}): "type id title steps",
|
|
66
|
+
reflect.TypeOf(catalog.AdrScope{}): "kind context service",
|
|
67
|
+
reflect.TypeOf(catalog.Adr{}): "id slug number title status date scope body note supersededBy supersedes relates source created revised",
|
|
68
|
+
reflect.TypeOf(catalog.AdrCommit{}): "commit author date",
|
|
69
|
+
reflect.TypeOf(catalog.AdrRelates{}): "services events flows",
|
|
70
|
+
reflect.TypeOf(catalog.Term{}): "id slug context name definition source",
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
func TestCatalogFieldCoverageIsExplicit(t *testing.T) {
|
|
74
|
+
for typ, declared := range catalogCoverage {
|
|
75
|
+
want := strings.Fields(declared)
|
|
76
|
+
got := make([]string, 0, typ.NumField())
|
|
77
|
+
for i := 0; i < typ.NumField(); i++ {
|
|
78
|
+
name := strings.Split(typ.Field(i).Tag.Get("json"), ",")[0]
|
|
79
|
+
if name != "" && name != "-" {
|
|
80
|
+
got = append(got, name)
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
sort.Strings(want)
|
|
84
|
+
sort.Strings(got)
|
|
85
|
+
if strings.Join(want, " ") != strings.Join(got, " ") {
|
|
86
|
+
t.Errorf("%s coverage changed\nfields: %s\ncovered: %s", typ.Name(), strings.Join(got, " "), strings.Join(want, " "))
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
package main
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
_ "embed"
|
|
5
|
+
|
|
6
|
+
"github.com/shortlink-org/portolan/plugin"
|
|
7
|
+
)
|
|
8
|
+
|
|
9
|
+
//go:embed options.schema.json
|
|
10
|
+
var optionsSchema []byte
|
|
11
|
+
|
|
12
|
+
func descriptor() plugin.Descriptor {
|
|
13
|
+
return plugin.Descriptor{
|
|
14
|
+
Name: "gen-markdown",
|
|
15
|
+
Summary: "Renders the merged catalog as a directory of markdown: a page per context, service, aggregate, store and flow.",
|
|
16
|
+
Phases: []string{plugin.PhaseGenerate},
|
|
17
|
+
Options: optionsSchema,
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
package main
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"strings"
|
|
5
|
+
|
|
6
|
+
"github.com/shortlink-org/portolan/catalog"
|
|
7
|
+
)
|
|
8
|
+
|
|
9
|
+
// renderExternals writes one page per system outside the estate. The page
|
|
10
|
+
// says what the catalog may claim about it - what it answers on, read from
|
|
11
|
+
// the vendored copy of its document, and who of ours calls it - and nothing
|
|
12
|
+
// the estate would have to own the far end to know.
|
|
13
|
+
func (s *site) renderExternals() {
|
|
14
|
+
for i := range s.cat.Externals {
|
|
15
|
+
s.renderExternal(&s.cat.Externals[i])
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
func (s *site) renderExternal(ext *catalog.External) {
|
|
20
|
+
self := s.pathOf[ext.ID]
|
|
21
|
+
|
|
22
|
+
var b strings.Builder
|
|
23
|
+
b.WriteString("# " + orDefault(ext.Name, ext.ID) + "\n\n")
|
|
24
|
+
b.WriteString(s.stamp() + "\n")
|
|
25
|
+
|
|
26
|
+
rows := [][]string{
|
|
27
|
+
{"Id", code(ext.ID)},
|
|
28
|
+
{"Where", "outside the estate"},
|
|
29
|
+
}
|
|
30
|
+
if ext.URL != "" {
|
|
31
|
+
rows = append(rows, []string{"Documented at", "<" + ext.URL + ">"})
|
|
32
|
+
}
|
|
33
|
+
b.WriteString(defList(rows))
|
|
34
|
+
|
|
35
|
+
if ext.Summary != "" {
|
|
36
|
+
b.WriteString("\n" + ext.Summary + "\n")
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
section(&b, "Provides", s.providesBlock(self, ext.Provides, nil))
|
|
40
|
+
section(&b, "Called by", s.calledByTable(self, ext.ID))
|
|
41
|
+
|
|
42
|
+
s.b.file(self, b.String())
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// calledByTable is every call in the catalog that lands on the external. The
|
|
46
|
+
// service pages list their own calls outward; this is the one place the
|
|
47
|
+
// callers of a third party stand together.
|
|
48
|
+
func (s *site) calledByTable(from, externalID string) string {
|
|
49
|
+
var rows [][]string
|
|
50
|
+
for i := range s.cat.Contexts {
|
|
51
|
+
ctx := &s.cat.Contexts[i]
|
|
52
|
+
for j := range ctx.Services {
|
|
53
|
+
svc := &ctx.Services[j]
|
|
54
|
+
for k := range svc.Consumes {
|
|
55
|
+
call := &svc.Consumes[k]
|
|
56
|
+
if call.Peer != externalID {
|
|
57
|
+
continue
|
|
58
|
+
}
|
|
59
|
+
rows = append(rows, []string{
|
|
60
|
+
s.ref(from, svc.ID, svc.Name),
|
|
61
|
+
code(call.ID),
|
|
62
|
+
string(call.Status),
|
|
63
|
+
s.source(from, call.Source, svc),
|
|
64
|
+
s.viaRef(from, call.Via),
|
|
65
|
+
})
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return table([]string{"Service", "Call", "Status", "Source", "Via"}, rows)
|
|
71
|
+
}
|
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
package main
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"path"
|
|
5
|
+
"strconv"
|
|
6
|
+
"strings"
|
|
7
|
+
|
|
8
|
+
"github.com/shortlink-org/portolan/catalog"
|
|
9
|
+
flowmermaid "github.com/shortlink-org/portolan/render/mermaid"
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
func (s *site) renderFlows() {
|
|
13
|
+
if len(s.cat.Flows) == 0 {
|
|
14
|
+
return
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const self = "flows/README.md"
|
|
18
|
+
|
|
19
|
+
var b strings.Builder
|
|
20
|
+
b.WriteString("# Flows\n\n")
|
|
21
|
+
b.WriteString(s.stamp() + "\n")
|
|
22
|
+
|
|
23
|
+
rows := make([][]string, 0, len(s.cat.Flows))
|
|
24
|
+
for i := range s.cat.Flows {
|
|
25
|
+
flow := &s.cat.Flows[i]
|
|
26
|
+
owner := "—"
|
|
27
|
+
if flow.Owner != "" {
|
|
28
|
+
owner = s.ref(self, flow.Owner, flow.Owner)
|
|
29
|
+
}
|
|
30
|
+
rows = append(rows, []string{
|
|
31
|
+
s.ref(self, flow.ID, flow.Name),
|
|
32
|
+
owner,
|
|
33
|
+
firstLine(flow.Summary),
|
|
34
|
+
})
|
|
35
|
+
}
|
|
36
|
+
b.WriteString(table([]string{"Flow", "Owner", "Summary"}, rows))
|
|
37
|
+
|
|
38
|
+
s.b.file(self, b.String())
|
|
39
|
+
|
|
40
|
+
for i := range s.cat.Flows {
|
|
41
|
+
s.renderFlow(&s.cat.Flows[i])
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
func (s *site) renderFlow(flow *catalog.Flow) {
|
|
46
|
+
self := s.pathOf[flow.ID]
|
|
47
|
+
|
|
48
|
+
var b strings.Builder
|
|
49
|
+
b.WriteString("# " + flow.Name + "\n\n")
|
|
50
|
+
b.WriteString(s.stamp() + "\n")
|
|
51
|
+
|
|
52
|
+
meta := [][]string{
|
|
53
|
+
{"Id", code(flow.ID)},
|
|
54
|
+
}
|
|
55
|
+
if flow.Owner != "" {
|
|
56
|
+
meta = append(meta, []string{"Owner", s.ref(self, flow.Owner, flow.Owner)})
|
|
57
|
+
}
|
|
58
|
+
if flow.Trigger != nil {
|
|
59
|
+
trigger := code(flow.Trigger.Kind)
|
|
60
|
+
if flow.Trigger.Label != "" {
|
|
61
|
+
trigger += " · " + flow.Trigger.Label
|
|
62
|
+
}
|
|
63
|
+
meta = append(meta,
|
|
64
|
+
[]string{"Trigger", trigger},
|
|
65
|
+
[]string{"Root confidence", flow.Trigger.Confidence},
|
|
66
|
+
)
|
|
67
|
+
}
|
|
68
|
+
// Source is the file the flow was read out of, which is the only thing a
|
|
69
|
+
// reader can go and check for themselves.
|
|
70
|
+
if flow.Source != "" {
|
|
71
|
+
meta = append(meta, []string{"Source", s.source(self, flow.Source, s.serviceForSource(flow.Source))})
|
|
72
|
+
}
|
|
73
|
+
b.WriteString(defList(meta))
|
|
74
|
+
|
|
75
|
+
if flow.Summary != "" {
|
|
76
|
+
b.WriteString("\n" + flow.Summary + "\n")
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
participants := make([][]string, 0, len(flow.Participants))
|
|
80
|
+
for i := range flow.Participants {
|
|
81
|
+
p := &flow.Participants[i]
|
|
82
|
+
context := "—"
|
|
83
|
+
if p.Context != nil {
|
|
84
|
+
context = s.ref(self, *p.Context, *p.Context)
|
|
85
|
+
}
|
|
86
|
+
participants = append(participants, []string{code(p.ID), string(p.Kind), context, p.Label})
|
|
87
|
+
}
|
|
88
|
+
section(&b, "Participants", table([]string{"Participant", "Kind", "Context", "Label"}, participants))
|
|
89
|
+
|
|
90
|
+
section(&b, "Sequence", fence("mermaid", flowmermaid.Sequence(flow, s.labelWithAnswer)))
|
|
91
|
+
|
|
92
|
+
counter := 0
|
|
93
|
+
section(&b, "Steps", s.stepList(self, flow, flow.Steps, &counter))
|
|
94
|
+
|
|
95
|
+
s.b.file(self, b.String())
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// stepList is the same walk again, in prose. The diagram shows the shape and
|
|
99
|
+
// the list carries what will not fit on an arrow: where the step was read
|
|
100
|
+
// from, how far it is trusted, and what it refers to.
|
|
101
|
+
//
|
|
102
|
+
// Branches are wrapped in block quotes rather than indented. Four spaces of
|
|
103
|
+
// indentation is a code block in markdown, and three is a continuation of
|
|
104
|
+
// whatever list came before - a quote is the one nesting that means nesting.
|
|
105
|
+
func (s *site) stepList(self string, flow *catalog.Flow, nodes catalog.FlowNodes, counter *int) string {
|
|
106
|
+
var b strings.Builder
|
|
107
|
+
|
|
108
|
+
for _, node := range nodes {
|
|
109
|
+
switch n := node.(type) {
|
|
110
|
+
case *catalog.Step:
|
|
111
|
+
*counter++
|
|
112
|
+
b.WriteString("<a id=\"step-" + anchorID(n.ID) + "\"></a>\n")
|
|
113
|
+
|
|
114
|
+
arrow := " → "
|
|
115
|
+
if n.From == n.To {
|
|
116
|
+
arrow = " ↺ "
|
|
117
|
+
}
|
|
118
|
+
b.WriteString(strconv.Itoa(*counter) + ". **" + n.From + "**" + arrow + "**" + n.To + "** — " + s.labelWithAnswer(n) + "\n")
|
|
119
|
+
|
|
120
|
+
var notes []string
|
|
121
|
+
if n.Ref != "" {
|
|
122
|
+
notes = append(notes, s.stepRef(self, n))
|
|
123
|
+
}
|
|
124
|
+
if n.Status != catalog.StatusVerified {
|
|
125
|
+
notes = append(notes, "status: "+string(n.Status))
|
|
126
|
+
}
|
|
127
|
+
if n.Line != "" {
|
|
128
|
+
location := n.Line
|
|
129
|
+
if flow.Source != "" && path.Dir(sourceFile(n.Line)) == "." {
|
|
130
|
+
location = path.Join(path.Dir(sourceFile(flow.Source)), n.Line)
|
|
131
|
+
}
|
|
132
|
+
notes = append(notes, s.source(self, location, s.serviceForSource(flow.Source)))
|
|
133
|
+
}
|
|
134
|
+
if n.Note != "" {
|
|
135
|
+
notes = append(notes, n.Note)
|
|
136
|
+
}
|
|
137
|
+
if len(notes) > 0 {
|
|
138
|
+
// Three spaces line the continuation up under the "1. " marker.
|
|
139
|
+
b.WriteString(" " + strings.Join(notes, " · ") + "\n")
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
if n.Status == catalog.StatusUnresolved {
|
|
143
|
+
s.b.warn(flow.ID, "%s step %q is unresolved: %s", flow.ID, n.ID, stepLabel(n))
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
case *catalog.Parallel:
|
|
147
|
+
var inner strings.Builder
|
|
148
|
+
inner.WriteString("**In parallel** — " + orDefault(n.Title, "branches that do not wait for each other") + "\n")
|
|
149
|
+
for i, branch := range n.Branches {
|
|
150
|
+
inner.WriteString("\n*Branch " + strconv.Itoa(i+1) + "*\n\n")
|
|
151
|
+
inner.WriteString(s.stepList(self, flow, branch, counter))
|
|
152
|
+
}
|
|
153
|
+
b.WriteString("\n" + quote(inner.String()) + "\n")
|
|
154
|
+
|
|
155
|
+
case *catalog.Alt:
|
|
156
|
+
var inner strings.Builder
|
|
157
|
+
// "One of" rather than "if": exactly one branch runs, and a reader
|
|
158
|
+
// who takes the branches for a sequence reads the flow backwards.
|
|
159
|
+
inner.WriteString("**One of**\n")
|
|
160
|
+
for _, branch := range n.Branches {
|
|
161
|
+
title := branch.Title
|
|
162
|
+
if branch.Terminal {
|
|
163
|
+
title += " — *ends the flow*"
|
|
164
|
+
}
|
|
165
|
+
inner.WriteString("\n*" + title + "*\n\n")
|
|
166
|
+
inner.WriteString(s.stepList(self, flow, branch.Steps, counter))
|
|
167
|
+
}
|
|
168
|
+
b.WriteString("\n" + quote(inner.String()) + "\n")
|
|
169
|
+
|
|
170
|
+
case *catalog.Loop:
|
|
171
|
+
var inner strings.Builder
|
|
172
|
+
inner.WriteString("**Repeats** — " + n.Title + "\n\n")
|
|
173
|
+
inner.WriteString(s.stepList(self, flow, n.Steps, counter))
|
|
174
|
+
b.WriteString("\n" + quote(inner.String()) + "\n")
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
return b.String()
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// quote wraps a block so it nests visibly, at any depth, without markdown
|
|
182
|
+
// mistaking the indentation for something else.
|
|
183
|
+
func quote(block string) string {
|
|
184
|
+
lines := strings.Split(strings.TrimRight(block, "\n"), "\n")
|
|
185
|
+
for i, line := range lines {
|
|
186
|
+
if line == "" {
|
|
187
|
+
lines[i] = ">"
|
|
188
|
+
|
|
189
|
+
continue
|
|
190
|
+
}
|
|
191
|
+
lines[i] = "> " + line
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
return strings.Join(lines, "\n") + "\n"
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// stepRef links a step to what it refers to. An event id resolves to the
|
|
198
|
+
// aggregate page that publishes it; anything else is shown as written.
|
|
199
|
+
func (s *site) stepRef(self string, step *catalog.Step) string {
|
|
200
|
+
if step.Kind == catalog.StepEvent {
|
|
201
|
+
if _, ok := s.eventPage[step.Ref]; ok {
|
|
202
|
+
return s.eventRef(self, step.Ref, step.Ref)
|
|
203
|
+
}
|
|
204
|
+
if step.Status != catalog.StatusUnresolved {
|
|
205
|
+
s.b.warn(step.Ref, "step %q refers to event %q, which no service in this catalog publishes", step.ID, step.Ref)
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
return code(step.Ref)
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
func stepLabel(step *catalog.Step) string {
|
|
213
|
+
switch {
|
|
214
|
+
case step.Label != "":
|
|
215
|
+
return step.Label
|
|
216
|
+
case step.Ref != "":
|
|
217
|
+
return step.Ref
|
|
218
|
+
default:
|
|
219
|
+
return string(step.Kind)
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// mermaidText makes a label safe on a mermaid line. A newline ends the
|
|
224
|
+
// statement, a semicolon ends it too, and a bare # opens an entity code.
|
|
225
|
+
func mermaidText(s string) string {
|
|
226
|
+
return flowmermaid.Text(s)
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
func orDefault(s, fallback string) string {
|
|
230
|
+
if strings.TrimSpace(s) == "" {
|
|
231
|
+
return fallback
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
return s
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
// labelWithAnswer is the step's label, and what comes back when a contract
|
|
238
|
+
// says so.
|
|
239
|
+
func (s *site) labelWithAnswer(step *catalog.Step) string {
|
|
240
|
+
if answer := s.answer(step); answer != "" {
|
|
241
|
+
return stepLabel(step) + " → " + answer
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
return stepLabel(step)
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
// answer is what the far end of an rpc hands back, as the contract names it.
|
|
248
|
+
// The mirror of src/flow/answers.ts, and the prose is there.
|
|
249
|
+
//
|
|
250
|
+
// Only an rpc has one: a call lands inside a service, which no interface
|
|
251
|
+
// describes, and an event is a publication - a reply drawn to one would be a
|
|
252
|
+
// lie about the bus.
|
|
253
|
+
func (s *site) answer(step *catalog.Step) string {
|
|
254
|
+
if step.Kind != catalog.StepRPC {
|
|
255
|
+
return ""
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
// Outgoing: the step names the call, and a call id is "<interface>/<method>".
|
|
259
|
+
if step.Ref != "" {
|
|
260
|
+
return s.methodOf[step.Ref].Response
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
// Incoming: somebody called this service, and the label is the operation.
|
|
264
|
+
service, ok := s.services[step.To]
|
|
265
|
+
if !ok || step.Label == "" {
|
|
266
|
+
return ""
|
|
267
|
+
}
|
|
268
|
+
for i := range service.Provides {
|
|
269
|
+
for j := range service.Provides[i].Methods {
|
|
270
|
+
if service.Provides[i].Methods[j].Name == step.Label {
|
|
271
|
+
return service.Provides[i].Methods[j].Response
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
return ""
|
|
277
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
package main
|
|
2
|
+
|
|
3
|
+
// The vocabulary of one context, as a page of its own.
|
|
4
|
+
//
|
|
5
|
+
// It is not folded into the context's README for the same reason the source
|
|
6
|
+
// is its own file: the README says what the services do, the glossary says
|
|
7
|
+
// what the words in that sentence mean, and a reader consults them at
|
|
8
|
+
// different moments. It is also the page a model reading this estate wants
|
|
9
|
+
// FIRST - every other page is written in these words.
|
|
10
|
+
//
|
|
11
|
+
// Nothing here is derived. A definition is the author's sentence, carried
|
|
12
|
+
// through as written, and the only thing this file decides is the order it is
|
|
13
|
+
// read in and where the words came from.
|
|
14
|
+
|
|
15
|
+
import (
|
|
16
|
+
"sort"
|
|
17
|
+
"strconv"
|
|
18
|
+
"strings"
|
|
19
|
+
|
|
20
|
+
"github.com/shortlink-org/portolan/catalog"
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
const glossaryFile = "glossary.md"
|
|
24
|
+
|
|
25
|
+
// glossaryPath is where a context's vocabulary is documented: beside its
|
|
26
|
+
// README, so the two sit together in the tree the way they sit together in
|
|
27
|
+
// the repository the terms were read from.
|
|
28
|
+
func (s *site) glossaryPath(ctx *catalog.BoundedContext) string {
|
|
29
|
+
return ctx.Slug + "/" + glossaryFile
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
func (s *site) renderGlossary(ctx *catalog.BoundedContext) {
|
|
33
|
+
terms := s.termsOf[ctx.ID]
|
|
34
|
+
if len(terms) == 0 {
|
|
35
|
+
return
|
|
36
|
+
}
|
|
37
|
+
self := s.glossaryPath(ctx)
|
|
38
|
+
|
|
39
|
+
var b strings.Builder
|
|
40
|
+
b.WriteString("# Glossary — " + ctx.Name + "\n\n")
|
|
41
|
+
b.WriteString(s.stamp() + "\n")
|
|
42
|
+
b.WriteString(defList([][]string{
|
|
43
|
+
{"Context", s.ref(self, ctx.ID, ctx.Name)},
|
|
44
|
+
{"Terms", strconv.Itoa(len(terms))},
|
|
45
|
+
{"Read from", strings.Join(s.termSources(self, terms), ", ")},
|
|
46
|
+
}))
|
|
47
|
+
|
|
48
|
+
b.WriteString("\nOne meaning per word inside this context, as the glossary" +
|
|
49
|
+
" beside the code states it.\n")
|
|
50
|
+
|
|
51
|
+
// A list rather than a table. A definition is a sentence or two of prose,
|
|
52
|
+
// and a table cell is where a sentence goes to be truncated - the same
|
|
53
|
+
// reason the source file is prose. A list also diffs by the term.
|
|
54
|
+
var out strings.Builder
|
|
55
|
+
for _, term := range terms {
|
|
56
|
+
out.WriteString("- **" + term.Name + "** — " + term.Definition + "\n")
|
|
57
|
+
}
|
|
58
|
+
section(&b, "Terms", out.String())
|
|
59
|
+
|
|
60
|
+
s.b.file(self, b.String())
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
func (s *site) termSources(from string, terms []*catalog.Term) []string {
|
|
64
|
+
seen := map[string]bool{}
|
|
65
|
+
var out []string
|
|
66
|
+
for _, term := range terms {
|
|
67
|
+
file := sourceFile(term.Source)
|
|
68
|
+
if file == "" || seen[file] {
|
|
69
|
+
continue
|
|
70
|
+
}
|
|
71
|
+
seen[file] = true
|
|
72
|
+
out = append(out, s.source(from, file, s.serviceForSource(file)))
|
|
73
|
+
}
|
|
74
|
+
sort.Strings(out)
|
|
75
|
+
return out
|
|
76
|
+
}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
package main
|
|
2
|
+
|
|
3
|
+
// What the glossary page promises, said once here rather than read out of the
|
|
4
|
+
// golden tree: the golden proves the bytes, these prove the intent.
|
|
5
|
+
|
|
6
|
+
import (
|
|
7
|
+
"encoding/json"
|
|
8
|
+
"os"
|
|
9
|
+
"strings"
|
|
10
|
+
"testing"
|
|
11
|
+
|
|
12
|
+
"github.com/shortlink-org/portolan/catalog"
|
|
13
|
+
"github.com/shortlink-org/portolan/plugin"
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
func rendered(t *testing.T) map[string]string {
|
|
17
|
+
t.Helper()
|
|
18
|
+
|
|
19
|
+
raw, err := os.ReadFile("testdata/catalog.json")
|
|
20
|
+
if err != nil {
|
|
21
|
+
t.Fatal(err)
|
|
22
|
+
}
|
|
23
|
+
var cat catalog.Catalog
|
|
24
|
+
if err := json.Unmarshal(raw, &cat); err != nil {
|
|
25
|
+
t.Fatal(err)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
out := map[string]string{}
|
|
29
|
+
for _, file := range render(plugin.Request{Catalog: cat}, Options{Title: "Golden estate"}).Files {
|
|
30
|
+
out[file.Name] = file.Contents
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return out
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
func page(t *testing.T, name string) string {
|
|
37
|
+
t.Helper()
|
|
38
|
+
|
|
39
|
+
pages := rendered(t)
|
|
40
|
+
body, ok := pages[name]
|
|
41
|
+
if !ok {
|
|
42
|
+
t.Fatalf("no page %s", name)
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return body
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// A page of its own, beside the context's README: the README says what the
|
|
49
|
+
// services do, the glossary says what the words in that sentence mean.
|
|
50
|
+
func TestGlossaryIsItsOwnPage(t *testing.T) {
|
|
51
|
+
body := page(t, "billing/glossary.md")
|
|
52
|
+
|
|
53
|
+
if !strings.HasPrefix(body, "# Glossary — Billing\n") {
|
|
54
|
+
t.Errorf("the page opens with %q", strings.SplitN(body, "\n", 2)[0])
|
|
55
|
+
}
|
|
56
|
+
for _, want := range []string{
|
|
57
|
+
"**Invoice** — What a customer is asked to pay",
|
|
58
|
+
"**Dunning** — Asking again, on a schedule",
|
|
59
|
+
} {
|
|
60
|
+
if !strings.Contains(body, want) {
|
|
61
|
+
t.Errorf("no %q in:\n%s", want, body)
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Alphabetical, whatever order the sources merged in. A glossary is looked up,
|
|
67
|
+
// not read through, and catalog order is nobody's index.
|
|
68
|
+
func TestTermsAreAlphabetical(t *testing.T) {
|
|
69
|
+
body := page(t, "billing/glossary.md")
|
|
70
|
+
|
|
71
|
+
dunning := strings.Index(body, "**Dunning**")
|
|
72
|
+
invoice := strings.Index(body, "**Invoice**")
|
|
73
|
+
if dunning < 0 || invoice < 0 || dunning > invoice {
|
|
74
|
+
t.Errorf("Dunning at %d, Invoice at %d", dunning, invoice)
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// The file the words were read from, named once on the page rather than once
|
|
79
|
+
// per term: the reader who disagrees with a definition edits that file.
|
|
80
|
+
func TestThePageNamesWhereTheWordsWereWritten(t *testing.T) {
|
|
81
|
+
if body := page(t, "billing/glossary.md"); !strings.Contains(body, "examples/billing/GLOSSARY.md") {
|
|
82
|
+
t.Errorf("the page does not say where it was read from:\n%s", body)
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
func TestTheContextPageLinksItsGlossary(t *testing.T) {
|
|
87
|
+
if body := page(t, "billing/README.md"); !strings.Contains(body, "[Glossary](glossary.md)") {
|
|
88
|
+
t.Errorf("the context page does not link the glossary:\n%s", body)
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
func TestServiceReadmeLinksUseGeneratedAdrAndGlossaryPages(t *testing.T) {
|
|
93
|
+
body := page(t, "billing/invoices/README.md")
|
|
94
|
+
|
|
95
|
+
for _, want := range []string{
|
|
96
|
+
"[GLOSSARY.md](../glossary.md)",
|
|
97
|
+
"[billing.0001](../../adr/billing.0001.md)",
|
|
98
|
+
} {
|
|
99
|
+
if !strings.Contains(body, want) {
|
|
100
|
+
t.Errorf("the service README does not rewrite %q:\n%s", want, body)
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
if strings.Contains(body, "](GLOSSARY.md)") || strings.Contains(body, "](../../docs/adr/0001.md)") {
|
|
104
|
+
t.Errorf("the copied source links survived unchanged:\n%s", body)
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// Straight after the contexts, before the pages that are written in these
|
|
109
|
+
// words. A model reading the estate cold has the same problem a person has.
|
|
110
|
+
func TestLlmsListsTheGlossaries(t *testing.T) {
|
|
111
|
+
body := page(t, "llms.txt")
|
|
112
|
+
|
|
113
|
+
if !strings.Contains(body, "## Glossaries") {
|
|
114
|
+
t.Fatalf("no Glossaries section:\n%s", body)
|
|
115
|
+
}
|
|
116
|
+
if !strings.Contains(body, "[Glossary of Billing](billing/glossary.md): 2 terms. Dunning, Invoice") {
|
|
117
|
+
t.Errorf("the entry is not what it should be:\n%s", body)
|
|
118
|
+
}
|
|
119
|
+
if strings.Index(body, "## Glossaries") > strings.Index(body, "## Services") {
|
|
120
|
+
t.Error("the glossaries sit after the services")
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// An estate that has written no glossary renders exactly as it did before
|
|
125
|
+
// there was one to write.
|
|
126
|
+
func TestAContextWithNoGlossaryGetsNoPage(t *testing.T) {
|
|
127
|
+
raw, err := os.ReadFile("testdata/catalog.json")
|
|
128
|
+
if err != nil {
|
|
129
|
+
t.Fatal(err)
|
|
130
|
+
}
|
|
131
|
+
var cat catalog.Catalog
|
|
132
|
+
if err := json.Unmarshal(raw, &cat); err != nil {
|
|
133
|
+
t.Fatal(err)
|
|
134
|
+
}
|
|
135
|
+
cat.Terms = nil
|
|
136
|
+
|
|
137
|
+
for _, file := range render(plugin.Request{Catalog: cat}, Options{}).Files {
|
|
138
|
+
if strings.HasSuffix(file.Name, glossaryFile) {
|
|
139
|
+
t.Errorf("rendered %s for a catalog with no terms", file.Name)
|
|
140
|
+
}
|
|
141
|
+
if file.Name == "llms.txt" && strings.Contains(file.Contents, "Glossaries") {
|
|
142
|
+
t.Error("llms.txt has a Glossaries section with no glossaries")
|
|
143
|
+
}
|
|
144
|
+
if file.Name == "billing/README.md" && strings.Contains(file.Contents, "## Language") {
|
|
145
|
+
t.Error("the context page has a Language section with no terms")
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|