@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,316 @@
|
|
|
1
|
+
package main
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"go/ast"
|
|
5
|
+
"go/parser"
|
|
6
|
+
"go/token"
|
|
7
|
+
"go/types"
|
|
8
|
+
"os"
|
|
9
|
+
"path"
|
|
10
|
+
"path/filepath"
|
|
11
|
+
"strings"
|
|
12
|
+
|
|
13
|
+
"github.com/shortlink-org/portolan/catalog"
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
// A parsed package: the files that make it up, and where they came from.
|
|
17
|
+
//
|
|
18
|
+
// Tests are left out. A _test.go file is about how the code is exercised, and
|
|
19
|
+
// a helper struct in one is not part of the domain however much it looks like
|
|
20
|
+
// it.
|
|
21
|
+
type pkg struct {
|
|
22
|
+
dir string // as a reader would open it, relative to the repository
|
|
23
|
+
name string
|
|
24
|
+
files []*ast.File
|
|
25
|
+
fset *token.FileSet
|
|
26
|
+
paths map[*ast.File]string
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
func parsePkg(root, rel string) (*pkg, error) {
|
|
30
|
+
dir := filepath.Join(root, rel)
|
|
31
|
+
|
|
32
|
+
entries, err := os.ReadDir(dir)
|
|
33
|
+
if err != nil {
|
|
34
|
+
return nil, err
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
p := &pkg{
|
|
38
|
+
dir: path.Join(filepath.ToSlash(root), rel),
|
|
39
|
+
fset: token.NewFileSet(),
|
|
40
|
+
paths: map[*ast.File]string{},
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
for _, entry := range entries {
|
|
44
|
+
name := entry.Name()
|
|
45
|
+
if entry.IsDir() || !strings.HasSuffix(name, ".go") || strings.HasSuffix(name, "_test.go") {
|
|
46
|
+
continue
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
file, err := parser.ParseFile(p.fset, filepath.Join(dir, name), nil, parser.ParseComments)
|
|
50
|
+
if err != nil {
|
|
51
|
+
return nil, err
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
p.name = file.Name.Name
|
|
55
|
+
p.files = append(p.files, file)
|
|
56
|
+
p.paths[file] = path.Join(p.dir, name)
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if len(p.files) == 0 {
|
|
60
|
+
return nil, os.ErrNotExist
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return p, nil
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// doc is the package comment: the block immediately above `package x`, in
|
|
67
|
+
// whichever file carries it.
|
|
68
|
+
//
|
|
69
|
+
// It is the aggregate's readme, and it is worth saying why that is not a
|
|
70
|
+
// fallback. A package comment is where a Go author already writes down what the
|
|
71
|
+
// package is for and what it refuses to do; asking them to write it a second
|
|
72
|
+
// time somewhere a generator can find it is how documentation goes stale.
|
|
73
|
+
func (p *pkg) doc() string {
|
|
74
|
+
for _, file := range p.files {
|
|
75
|
+
if file.Doc == nil {
|
|
76
|
+
continue
|
|
77
|
+
}
|
|
78
|
+
if text := strings.TrimSpace(file.Doc.Text()); text != "" {
|
|
79
|
+
return text
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return ""
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// position is where a node sits, as a reader would write it down: the file
|
|
87
|
+
// path relative to the repository, and the line. It is what a flow step points
|
|
88
|
+
// at, and it is read from the file set rather than remembered per declaration.
|
|
89
|
+
func (p *pkg) position(pos token.Pos) (string, int) {
|
|
90
|
+
at := p.fset.Position(pos)
|
|
91
|
+
|
|
92
|
+
return filepath.ToSlash(at.Filename), at.Line
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// structDecl is a named struct type with the comment above it.
|
|
96
|
+
type structDecl struct {
|
|
97
|
+
name string
|
|
98
|
+
doc string
|
|
99
|
+
fields *ast.StructType
|
|
100
|
+
source string
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
func (p *pkg) structs() []structDecl {
|
|
104
|
+
var out []structDecl
|
|
105
|
+
|
|
106
|
+
for _, file := range p.files {
|
|
107
|
+
for _, decl := range file.Decls {
|
|
108
|
+
gen, ok := decl.(*ast.GenDecl)
|
|
109
|
+
if !ok || gen.Tok != token.TYPE {
|
|
110
|
+
continue
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
for _, spec := range gen.Specs {
|
|
114
|
+
typeSpec, ok := spec.(*ast.TypeSpec)
|
|
115
|
+
if !ok {
|
|
116
|
+
continue
|
|
117
|
+
}
|
|
118
|
+
structType, ok := typeSpec.Type.(*ast.StructType)
|
|
119
|
+
if !ok {
|
|
120
|
+
continue
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// A single-spec declaration carries its comment on the
|
|
124
|
+
// GenDecl; one inside a `type (...)` block carries its own.
|
|
125
|
+
comment := typeSpec.Doc
|
|
126
|
+
if comment == nil && len(gen.Specs) == 1 {
|
|
127
|
+
comment = gen.Doc
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
out = append(out, structDecl{
|
|
131
|
+
name: typeSpec.Name.Name,
|
|
132
|
+
doc: firstSentenceOrAll(comment.Text()),
|
|
133
|
+
fields: structType,
|
|
134
|
+
source: p.paths[file],
|
|
135
|
+
})
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
return out
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// methods returns the methods declared on a receiver type, by name.
|
|
144
|
+
func (p *pkg) methods(recv string) map[string]*ast.FuncDecl {
|
|
145
|
+
out := map[string]*ast.FuncDecl{}
|
|
146
|
+
|
|
147
|
+
for _, file := range p.files {
|
|
148
|
+
for _, decl := range file.Decls {
|
|
149
|
+
fn, ok := decl.(*ast.FuncDecl)
|
|
150
|
+
if !ok || fn.Recv == nil || len(fn.Recv.List) == 0 {
|
|
151
|
+
continue
|
|
152
|
+
}
|
|
153
|
+
if receiverName(fn.Recv.List[0].Type) == recv {
|
|
154
|
+
out[fn.Name.Name] = fn
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
return out
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
func receiverName(expr ast.Expr) string {
|
|
163
|
+
if star, ok := expr.(*ast.StarExpr); ok {
|
|
164
|
+
expr = star.X
|
|
165
|
+
}
|
|
166
|
+
if ident, ok := expr.(*ast.Ident); ok {
|
|
167
|
+
return ident.Name
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
return ""
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// fields turns a struct's members into catalog fields.
|
|
174
|
+
//
|
|
175
|
+
// The type is rendered from the syntax rather than resolved: `email.Address`
|
|
176
|
+
// is written down as `email.Address`, which is what a reader of the catalog
|
|
177
|
+
// wants to see and what the shape of the schema asks for. Resolving it would
|
|
178
|
+
// need the whole module built, and would answer a question nobody asked.
|
|
179
|
+
func fields(st *ast.StructType) []catalog.Field {
|
|
180
|
+
if st == nil || st.Fields == nil {
|
|
181
|
+
return nil
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
var out []catalog.Field
|
|
185
|
+
for _, field := range st.Fields.List {
|
|
186
|
+
typeName := types.ExprString(field.Type)
|
|
187
|
+
|
|
188
|
+
doc := strings.TrimSpace(field.Doc.Text())
|
|
189
|
+
if doc == "" {
|
|
190
|
+
doc = strings.TrimSpace(field.Comment.Text())
|
|
191
|
+
}
|
|
192
|
+
doc = firstSentenceOrAll(doc)
|
|
193
|
+
|
|
194
|
+
if len(field.Names) == 0 {
|
|
195
|
+
// An embedded field: named by its type.
|
|
196
|
+
out = append(out, catalog.Field{Name: typeName, Type: typeName, Doc: doc})
|
|
197
|
+
|
|
198
|
+
continue
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
for _, name := range field.Names {
|
|
202
|
+
out = append(out, catalog.Field{Name: name.Name, Type: typeName, Doc: doc})
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
return out
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// returnedString is the string a one-line method returns, which is how an
|
|
210
|
+
// event's name on the bus is read out of `func (E) Name() string`: a literal,
|
|
211
|
+
// or a constant the package declares - `return TopicAccountLocked` - since a
|
|
212
|
+
// topic is routinely named once and returned by name.
|
|
213
|
+
func returnedString(p *pkg, fn *ast.FuncDecl) (string, bool) {
|
|
214
|
+
if fn == nil || fn.Body == nil {
|
|
215
|
+
return "", false
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
for _, stmt := range fn.Body.List {
|
|
219
|
+
ret, ok := stmt.(*ast.ReturnStmt)
|
|
220
|
+
if !ok || len(ret.Results) != 1 {
|
|
221
|
+
continue
|
|
222
|
+
}
|
|
223
|
+
if value, ok := constString(ret.Results[0], stringConsts(p)); ok {
|
|
224
|
+
return value, true
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
return "", false
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// calls reports whether a function's body calls a method with one of these
|
|
232
|
+
// names on anything at all.
|
|
233
|
+
func calls(fn *ast.FuncDecl, names ...string) bool {
|
|
234
|
+
if fn == nil || fn.Body == nil {
|
|
235
|
+
return false
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
wanted := map[string]bool{}
|
|
239
|
+
for _, name := range names {
|
|
240
|
+
wanted[name] = true
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
found := false
|
|
244
|
+
ast.Inspect(fn.Body, func(node ast.Node) bool {
|
|
245
|
+
call, ok := node.(*ast.CallExpr)
|
|
246
|
+
if !ok {
|
|
247
|
+
return true
|
|
248
|
+
}
|
|
249
|
+
if selector, ok := call.Fun.(*ast.SelectorExpr); ok && wanted[selector.Sel.Name] {
|
|
250
|
+
found = true
|
|
251
|
+
|
|
252
|
+
return false
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
return true
|
|
256
|
+
})
|
|
257
|
+
|
|
258
|
+
return found
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
// subdirs lists the immediate subdirectories of a path, sorted by os.ReadDir,
|
|
262
|
+
// which reads them in filename order - so the fragment comes out the same way
|
|
263
|
+
// every time.
|
|
264
|
+
func subdirs(root, rel string) []string {
|
|
265
|
+
entries, err := os.ReadDir(filepath.Join(root, rel))
|
|
266
|
+
if err != nil {
|
|
267
|
+
return nil
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
var out []string
|
|
271
|
+
for _, entry := range entries {
|
|
272
|
+
if entry.IsDir() {
|
|
273
|
+
out = append(out, entry.Name())
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
return out
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
// firstSentenceOrAll trims a doc comment down to something that fits in a
|
|
281
|
+
// table cell, and leaves it alone when it is already short.
|
|
282
|
+
//
|
|
283
|
+
// Go doc comments open with a sentence naming the thing, then explain. The
|
|
284
|
+
// first sentence is the label; the rest belongs on the page, not in a column.
|
|
285
|
+
func firstSentenceOrAll(doc string) string {
|
|
286
|
+
doc = strings.TrimSpace(doc)
|
|
287
|
+
if doc == "" {
|
|
288
|
+
return ""
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
// Everything up to the first blank line is the opening paragraph.
|
|
292
|
+
if i := strings.Index(doc, "\n\n"); i >= 0 {
|
|
293
|
+
doc = doc[:i]
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
return strings.Join(strings.Fields(doc), " ")
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
// parseSource builds a package out of one file of source. It exists for tests:
|
|
300
|
+
// every other caller has a directory.
|
|
301
|
+
func parseSource(name, src string) (*pkg, error) {
|
|
302
|
+
fset := token.NewFileSet()
|
|
303
|
+
|
|
304
|
+
file, err := parser.ParseFile(fset, name, src, parser.ParseComments)
|
|
305
|
+
if err != nil {
|
|
306
|
+
return nil, err
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
return &pkg{
|
|
310
|
+
dir: ".",
|
|
311
|
+
name: file.Name.Name,
|
|
312
|
+
files: []*ast.File{file},
|
|
313
|
+
fset: fset,
|
|
314
|
+
paths: map[*ast.File]string{file: name},
|
|
315
|
+
}, nil
|
|
316
|
+
}
|
|
@@ -0,0 +1,321 @@
|
|
|
1
|
+
package main
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"go/ast"
|
|
5
|
+
"go/types"
|
|
6
|
+
"sort"
|
|
7
|
+
"strings"
|
|
8
|
+
|
|
9
|
+
"github.com/shortlink-org/portolan/plugin"
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
// extractTransport reads the http layer and answers with which endpoints run
|
|
13
|
+
// which use case, keyed by "<aggregate>/<use case>".
|
|
14
|
+
//
|
|
15
|
+
// Three things in a handler say it, and they agree:
|
|
16
|
+
//
|
|
17
|
+
// // RegisterUser implements POST /v1/users.
|
|
18
|
+
// func (h *Users) RegisterUser(ctx context.Context, request gen.RegisterUserRequestObject) ... {
|
|
19
|
+
// out, err := h.register.Handle(ctx, dto.Input{...})
|
|
20
|
+
//
|
|
21
|
+
// The method name is the generated server's, which is the document's
|
|
22
|
+
// operationId with a capital letter; `register` is a field of the handler
|
|
23
|
+
// struct, declared as *register.UseCase; and the import that names it says
|
|
24
|
+
// which aggregate's use case that is. None of it needs a type checker, and
|
|
25
|
+
// none of it needs the OpenAPI document - which is the point, because the
|
|
26
|
+
// document is read by a different extractor that knows nothing about Go.
|
|
27
|
+
func extractTransport(root string, layout sourceLayout, b *plugin.Builder) (map[string][]string, []endpointDecl) {
|
|
28
|
+
out := map[string][]string{}
|
|
29
|
+
var endpoints []endpointDecl
|
|
30
|
+
|
|
31
|
+
for _, dir := range layout.http {
|
|
32
|
+
for _, endpoint := range readTransportPackage(root, dir, layout, isHandler, lowerFirst, b) {
|
|
33
|
+
endpoints = append(endpoints, endpoint)
|
|
34
|
+
for _, useCase := range endpoint.useCases {
|
|
35
|
+
out[useCase] = appendOnce(out[useCase], endpoint.id)
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// A gRPC handler is read the same way, and differs in two things: what
|
|
41
|
+
// marks a method as one of the contract's, and what the endpoint is called.
|
|
42
|
+
// An rpc is named the same on both sides - GetQuote is GetQuote - so the
|
|
43
|
+
// method name is the id, and it is the id extract-proto puts in `provides`.
|
|
44
|
+
for _, dir := range layout.grpc {
|
|
45
|
+
for _, endpoint := range readTransportPackage(root, dir, layout, isRpcHandler, sameName, b) {
|
|
46
|
+
endpoints = append(endpoints, endpoint)
|
|
47
|
+
for _, useCase := range endpoint.useCases {
|
|
48
|
+
out[useCase] = appendOnce(out[useCase], endpoint.id)
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Both the struct set and the method set are walked as maps, so the order
|
|
54
|
+
// operations arrive in is not the order they were written in. Sorting here
|
|
55
|
+
// is what keeps the fragment byte-identical between runs.
|
|
56
|
+
for useCase := range out {
|
|
57
|
+
sort.Strings(out[useCase])
|
|
58
|
+
}
|
|
59
|
+
sort.Slice(endpoints, func(i, j int) bool { return endpoints[i].id < endpoints[j].id })
|
|
60
|
+
|
|
61
|
+
return out, endpoints
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// readTransportPackage reads one discovered handler package: a struct per
|
|
65
|
+
// server, and the methods of it that answer something.
|
|
66
|
+
func readTransportPackage(root, dir string, layout sourceLayout, handler func(*ast.FuncDecl) bool, id func(string) string, b *plugin.Builder) []endpointDecl {
|
|
67
|
+
var endpoints []endpointDecl
|
|
68
|
+
|
|
69
|
+
pkg, err := parsePkg(root, dir)
|
|
70
|
+
if err != nil {
|
|
71
|
+
return endpoints
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
for name, useCase := range handlerFields(pkg, layout) {
|
|
75
|
+
endpoints = append(endpoints, operationsRunning(pkg, name, useCase, handler, id, b)...)
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return endpoints
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// handlerFields maps each handler struct to the use case behind each of its
|
|
82
|
+
// fields: Users{register: *register.UseCase} gives {"Users": {"register":
|
|
83
|
+
// "user/register"}}.
|
|
84
|
+
func handlerFields(pkg *pkg, layouts ...sourceLayout) map[string]map[string]string {
|
|
85
|
+
out := map[string]map[string]string{}
|
|
86
|
+
|
|
87
|
+
for _, file := range pkg.files {
|
|
88
|
+
useCases := useCaseImports(file, layouts...)
|
|
89
|
+
if len(useCases) == 0 {
|
|
90
|
+
continue
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
for _, decl := range file.Decls {
|
|
94
|
+
gen, ok := decl.(*ast.GenDecl)
|
|
95
|
+
if !ok {
|
|
96
|
+
continue
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
for _, spec := range gen.Specs {
|
|
100
|
+
typeSpec, ok := spec.(*ast.TypeSpec)
|
|
101
|
+
if !ok {
|
|
102
|
+
continue
|
|
103
|
+
}
|
|
104
|
+
structType, ok := typeSpec.Type.(*ast.StructType)
|
|
105
|
+
if !ok || structType.Fields == nil {
|
|
106
|
+
continue
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
fields := map[string]string{}
|
|
110
|
+
for _, field := range structType.Fields.List {
|
|
111
|
+
// The field is what a use case is held in, and its type is
|
|
112
|
+
// what says which one: *register.UseCase.
|
|
113
|
+
selector, _, found := strings.Cut(strings.TrimPrefix(types.ExprString(field.Type), "*"), ".")
|
|
114
|
+
if !found {
|
|
115
|
+
continue
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
useCase, known := useCases[selector]
|
|
119
|
+
if !known {
|
|
120
|
+
continue
|
|
121
|
+
}
|
|
122
|
+
for _, name := range field.Names {
|
|
123
|
+
fields[name.Name] = useCase
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
if len(fields) > 0 {
|
|
128
|
+
out[typeSpec.Name.Name] = fields
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
return out
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// useCaseImports maps the name a file refers to a use case package by - its
|
|
138
|
+
// alias, or the last segment of its path - to "<aggregate>/<use case>".
|
|
139
|
+
//
|
|
140
|
+
// The aggregate is carried because a use case directory name is only unique
|
|
141
|
+
// within one: two aggregates may each have a `get`, and pairing an endpoint
|
|
142
|
+
// with the wrong one would be worse than pairing it with nothing.
|
|
143
|
+
func useCaseImports(file *ast.File, layouts ...sourceLayout) map[string]string {
|
|
144
|
+
out := map[string]string{}
|
|
145
|
+
|
|
146
|
+
for _, spec := range file.Imports {
|
|
147
|
+
importPath := strings.Trim(spec.Path.Value, `"`)
|
|
148
|
+
|
|
149
|
+
aggregate, useCaseName, found := useCaseImport(importPath)
|
|
150
|
+
if !found {
|
|
151
|
+
continue
|
|
152
|
+
}
|
|
153
|
+
key := aggregate + "/" + useCaseName
|
|
154
|
+
if len(layouts) > 0 {
|
|
155
|
+
if _, discovered := layouts[0].useCases[key]; !discovered {
|
|
156
|
+
continue
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
name := useCaseName
|
|
161
|
+
if spec.Name != nil {
|
|
162
|
+
name = spec.Name.Name
|
|
163
|
+
}
|
|
164
|
+
out[name] = key
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
return out
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// endpointDecl is one operation of the generated server: what it is called in
|
|
171
|
+
// the document, the use cases it runs in the order it runs them, and where the
|
|
172
|
+
// method that does it can be read.
|
|
173
|
+
//
|
|
174
|
+
// The order matters twice over. It is what pairs an operation with the use
|
|
175
|
+
// cases the catalog says it exposes, and it is the opening of a flow: an
|
|
176
|
+
// endpoint that validates a token and then changes a password does those two
|
|
177
|
+
// things in that order, and a picture that swapped them would be wrong.
|
|
178
|
+
type endpointDecl struct {
|
|
179
|
+
id string
|
|
180
|
+
useCases []string
|
|
181
|
+
source string
|
|
182
|
+
line int
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// operationsRunning finds the handler methods on a struct and the use cases
|
|
186
|
+
// each one reaches.
|
|
187
|
+
func operationsRunning(pkg *pkg, structName string, fields map[string]string, handler func(*ast.FuncDecl) bool, id func(string) string, b *plugin.Builder) []endpointDecl {
|
|
188
|
+
var out []endpointDecl
|
|
189
|
+
|
|
190
|
+
for name, fn := range pkg.methods(structName) {
|
|
191
|
+
if !handler(fn) {
|
|
192
|
+
continue
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
operation := id(name)
|
|
196
|
+
used := useCasesTouched(fn, fields)
|
|
197
|
+
|
|
198
|
+
if len(used) == 0 {
|
|
199
|
+
// An endpoint that reaches no use case is doing the work itself, or
|
|
200
|
+
// doing nothing. Either is worth saying out loud.
|
|
201
|
+
b.Warn(operation, pkg.dir+": "+name+" runs no use case; the operation is not paired with anything")
|
|
202
|
+
|
|
203
|
+
continue
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
source, line := pkg.position(fn.Pos())
|
|
207
|
+
out = append(out, endpointDecl{id: operation, useCases: used, source: source, line: line})
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
return out
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// isHandler tells a generated-server method from a helper beside it. The
|
|
214
|
+
// generated interface takes a `gen.XxxRequestObject`, and nothing else in these
|
|
215
|
+
// packages does.
|
|
216
|
+
func isHandler(fn *ast.FuncDecl) bool {
|
|
217
|
+
if fn.Type.Params == nil {
|
|
218
|
+
return false
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
for _, param := range fn.Type.Params.List {
|
|
222
|
+
if strings.HasSuffix(types.ExprString(param.Type), "RequestObject") {
|
|
223
|
+
return true
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
return false
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
// isRpcHandler tells a generated-server method from a helper beside it. A
|
|
231
|
+
// protoc-gen-go-grpc server takes a context and a pointer to the request
|
|
232
|
+
// message and answers with a pointer and an error, and the generated
|
|
233
|
+
// Unimplemented embed is what says the struct is one of those servers at all.
|
|
234
|
+
func isRpcHandler(fn *ast.FuncDecl) bool {
|
|
235
|
+
if fn.Type.Params == nil || fn.Type.Results == nil {
|
|
236
|
+
return false
|
|
237
|
+
}
|
|
238
|
+
if len(fn.Type.Params.List) != 2 || len(fn.Type.Results.List) != 2 {
|
|
239
|
+
return false
|
|
240
|
+
}
|
|
241
|
+
if types.ExprString(fn.Type.Params.List[0].Type) != "context.Context" {
|
|
242
|
+
return false
|
|
243
|
+
}
|
|
244
|
+
if !strings.HasPrefix(types.ExprString(fn.Type.Params.List[1].Type), "*") {
|
|
245
|
+
return false
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
return types.ExprString(fn.Type.Results.List[1].Type) == "error" &&
|
|
249
|
+
strings.HasPrefix(types.ExprString(fn.Type.Results.List[0].Type), "*")
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
// sameName is the id of an rpc: the method's own name, because the contract
|
|
253
|
+
// spells it the same and extract-proto puts that spelling in `provides`.
|
|
254
|
+
func sameName(name string) string { return name }
|
|
255
|
+
|
|
256
|
+
// useCasesTouched collects the receiver's use case fields a body reaches, in a
|
|
257
|
+
// stable order.
|
|
258
|
+
//
|
|
259
|
+
// Any mention counts, not only a call: a handler that resolves a bearer token
|
|
260
|
+
// through one use case before running another has been served by both, and
|
|
261
|
+
// which of them it happens to call through a helper is not a fact about the
|
|
262
|
+
// endpoint.
|
|
263
|
+
func useCasesTouched(fn *ast.FuncDecl, fields map[string]string) []string {
|
|
264
|
+
receiver := receiverIdent(fn)
|
|
265
|
+
if receiver == "" || fn.Body == nil {
|
|
266
|
+
return nil
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
var out []string
|
|
270
|
+
ast.Inspect(fn.Body, func(node ast.Node) bool {
|
|
271
|
+
selector, ok := node.(*ast.SelectorExpr)
|
|
272
|
+
if !ok {
|
|
273
|
+
return true
|
|
274
|
+
}
|
|
275
|
+
ident, ok := selector.X.(*ast.Ident)
|
|
276
|
+
if !ok || ident.Name != receiver {
|
|
277
|
+
return true
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
if useCase, known := fields[selector.Sel.Name]; known {
|
|
281
|
+
out = appendOnce(out, useCase)
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
return true
|
|
285
|
+
})
|
|
286
|
+
|
|
287
|
+
return out
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
func receiverIdent(fn *ast.FuncDecl) string {
|
|
291
|
+
if fn.Recv == nil || len(fn.Recv.List) == 0 || len(fn.Recv.List[0].Names) == 0 {
|
|
292
|
+
return ""
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
return fn.Recv.List[0].Names[0].Name
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
func appendOnce(list []string, value string) []string {
|
|
299
|
+
for _, existing := range list {
|
|
300
|
+
if existing == value {
|
|
301
|
+
return list
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
return append(list, value)
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
// lowerFirst turns a generated method name back into the operationId it was
|
|
309
|
+
// built from: RegisterUser was registerUser in the document.
|
|
310
|
+
func lowerFirst(name string) string {
|
|
311
|
+
if name == "" {
|
|
312
|
+
return name
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
runes := []rune(name)
|
|
316
|
+
if runes[0] >= 'A' && runes[0] <= 'Z' {
|
|
317
|
+
runes[0] = runes[0] - 'A' + 'a'
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
return string(runes)
|
|
321
|
+
}
|