@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,256 @@
|
|
|
1
|
+
package main
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"encoding/json"
|
|
5
|
+
"strings"
|
|
6
|
+
"testing"
|
|
7
|
+
|
|
8
|
+
"github.com/shortlink-org/portolan/catalog"
|
|
9
|
+
"github.com/shortlink-org/portolan/plugin"
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
func fragment(t *testing.T) catalog.Catalog {
|
|
13
|
+
t.Helper()
|
|
14
|
+
|
|
15
|
+
resp, err := extract(
|
|
16
|
+
plugin.Input{Root: "testdata", Commit: "abc1234", GeneratedAt: "2026-01-01T00:00:00Z"},
|
|
17
|
+
Options{Context: "storefront", Service: "bff", Schema: "schema", API: "storefront.v1"},
|
|
18
|
+
)
|
|
19
|
+
if err != nil {
|
|
20
|
+
t.Fatal(err)
|
|
21
|
+
}
|
|
22
|
+
if len(resp.Files) != 1 {
|
|
23
|
+
t.Fatalf("expected one fragment, got %d files", len(resp.Files))
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
var out catalog.Catalog
|
|
27
|
+
if err := json.Unmarshal([]byte(resp.Files[0].Contents), &out); err != nil {
|
|
28
|
+
t.Fatal(err)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return out
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
func provided(t *testing.T) []catalog.RpcService {
|
|
35
|
+
t.Helper()
|
|
36
|
+
|
|
37
|
+
return fragment(t).Contexts[0].Services[0].Provides
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
func interfaceNamed(t *testing.T, id string) catalog.RpcService {
|
|
41
|
+
t.Helper()
|
|
42
|
+
|
|
43
|
+
for _, p := range provided(t) {
|
|
44
|
+
if p.ID == id {
|
|
45
|
+
return p
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
t.Fatalf("no interface %q in the fragment", id)
|
|
49
|
+
|
|
50
|
+
return catalog.RpcService{}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
func method(t *testing.T, id, name string) catalog.RpcMethod {
|
|
54
|
+
t.Helper()
|
|
55
|
+
|
|
56
|
+
for _, m := range interfaceNamed(t, id).Methods {
|
|
57
|
+
if m.Name == name {
|
|
58
|
+
return m
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
t.Fatalf("no method %q on %q", name, id)
|
|
62
|
+
|
|
63
|
+
return catalog.RpcMethod{}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
func message(t *testing.T, id, name string) catalog.RpcMessage {
|
|
67
|
+
t.Helper()
|
|
68
|
+
|
|
69
|
+
for _, m := range interfaceNamed(t, id).Messages {
|
|
70
|
+
if m.Name == name {
|
|
71
|
+
return m
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
t.Fatalf("no message %q on %q", name, id)
|
|
75
|
+
|
|
76
|
+
return catalog.RpcMessage{}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// A module is how a schema's author says "these fields belong together", the
|
|
80
|
+
// way a tag is in an OpenAPI document - and unlike a tag it is a file, so the
|
|
81
|
+
// interface can point at something a reader can open.
|
|
82
|
+
func TestModulesBecomeInterfaces(t *testing.T) {
|
|
83
|
+
got := map[string]string{}
|
|
84
|
+
for _, p := range provided(t) {
|
|
85
|
+
got[p.ID] = p.Source
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
want := map[string]string{
|
|
89
|
+
"storefront.v1.Basket": "testdata/schema/basket/schema.graphql",
|
|
90
|
+
"storefront.v1.Order": "testdata/schema/order/schema.graphql",
|
|
91
|
+
}
|
|
92
|
+
for id, source := range want {
|
|
93
|
+
if got[id] != source {
|
|
94
|
+
t.Errorf("%s reads %q, want %q", id, got[id], source)
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
if len(got) != len(want) {
|
|
98
|
+
t.Errorf("declared %d interfaces, want %d: %v", len(got), len(want), got)
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// The generator writes the whole schema out again beside the modules it read.
|
|
103
|
+
// Reading that copy would give the estate a module nobody wrote, holding every
|
|
104
|
+
// field a second time.
|
|
105
|
+
func TestTheGeneratedCopyIsNotAModule(t *testing.T) {
|
|
106
|
+
for _, p := range provided(t) {
|
|
107
|
+
if strings.Contains(p.Source, ".generated.") {
|
|
108
|
+
t.Errorf("%s was read out of the generated copy %s", p.ID, p.Source)
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// A field is named by the operation it belongs to. Two operations may each
|
|
114
|
+
// have a `basket` field and they are not the same endpoint.
|
|
115
|
+
func TestMethodsAreNamedByOperation(t *testing.T) {
|
|
116
|
+
var names []string
|
|
117
|
+
for _, m := range interfaceNamed(t, "storefront.v1.Basket").Methods {
|
|
118
|
+
names = append(names, m.Name)
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
want := []string{"Query.basket", "Query.legacyBasket", "Mutation.addItem"}
|
|
122
|
+
if len(names) != len(want) {
|
|
123
|
+
t.Fatalf("methods are %v, want %v", names, want)
|
|
124
|
+
}
|
|
125
|
+
for i := range want {
|
|
126
|
+
if names[i] != want[i] {
|
|
127
|
+
t.Errorf("method %d is %q, want %q", i, names[i], want[i])
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// A subscription keeps answering. Drawn as a call it would be a lie about how
|
|
133
|
+
// the two ends are coupled, which is what Streaming exists to prevent.
|
|
134
|
+
func TestSubscriptionsAreServerStreams(t *testing.T) {
|
|
135
|
+
if got := method(t, "storefront.v1.Order", "Subscription.orderStatus").Streaming; got != catalog.StreamingServer {
|
|
136
|
+
t.Errorf("streaming is %q, want %q", got, catalog.StreamingServer)
|
|
137
|
+
}
|
|
138
|
+
if got := method(t, "storefront.v1.Basket", "Query.basket").Streaming; got != "" {
|
|
139
|
+
t.Errorf("a query is streaming %q, want unary", got)
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// A field whose whole input is one input object is already named by the
|
|
144
|
+
// schema; a field with loose arguments is not, so a name is made and the
|
|
145
|
+
// arguments become its fields.
|
|
146
|
+
func TestArgumentsAreNamedOnceAndInventedOtherwise(t *testing.T) {
|
|
147
|
+
if got := method(t, "storefront.v1.Basket", "Mutation.addItem").Request; got != "AddItemInput" {
|
|
148
|
+
t.Errorf("request is %q, want the input object AddItemInput", got)
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
if got := method(t, "storefront.v1.Order", "Query.order").Request; got != "QueryOrderArgs" {
|
|
152
|
+
t.Errorf("request is %q, want QueryOrderArgs", got)
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
args := message(t, "storefront.v1.Order", "QueryOrderArgs")
|
|
156
|
+
if len(args.Fields) != 2 || args.Fields[0].Name != "id" || args.Fields[1].Name != "at" {
|
|
157
|
+
t.Fatalf("QueryOrderArgs holds %+v, want id and at", args.Fields)
|
|
158
|
+
}
|
|
159
|
+
// `at` is nullable, and the rest of the catalog says that in prose.
|
|
160
|
+
if args.Fields[1].Doc != "Optional." {
|
|
161
|
+
t.Errorf("the nullable argument reads %q, want it marked optional", args.Fields[1].Doc)
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// A response names a shape, and the shapes it names are walked until nothing
|
|
166
|
+
// new is reached: a reader who has to open the schema to find out what a Line
|
|
167
|
+
// holds has been given a worse document than the schema.
|
|
168
|
+
func TestMessagesFollowWhatTheyReach(t *testing.T) {
|
|
169
|
+
var names []string
|
|
170
|
+
for _, m := range interfaceNamed(t, "storefront.v1.Basket").Messages {
|
|
171
|
+
names = append(names, m.Name)
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
for _, want := range []string{"Basket", "Line", "Money", "AddItemInput"} {
|
|
175
|
+
found := false
|
|
176
|
+
for _, name := range names {
|
|
177
|
+
found = found || name == want
|
|
178
|
+
}
|
|
179
|
+
if !found {
|
|
180
|
+
t.Errorf("%s is reachable from the basket module and is not in %v", want, names)
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// A list is spelled the way every other extractor here spells one, and an enum
|
|
186
|
+
// carries its values: a status whose values are three clicks away is a status
|
|
187
|
+
// nobody reads.
|
|
188
|
+
func TestTypesAreSpelledLikeTheRestOfTheCatalog(t *testing.T) {
|
|
189
|
+
basket := message(t, "storefront.v1.Basket", "Basket")
|
|
190
|
+
byName := map[string]catalog.Field{}
|
|
191
|
+
for _, f := range basket.Fields {
|
|
192
|
+
byName[f.Name] = f
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
if got := byName["lines"].Type; got != "[]Line" {
|
|
196
|
+
t.Errorf("lines is %q, want []Line", got)
|
|
197
|
+
}
|
|
198
|
+
if got := byName["quote"].Doc; got != "Optional. Nothing has been priced yet when the basket is empty." {
|
|
199
|
+
t.Errorf("the nullable field reads %q", got)
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
order := message(t, "storefront.v1.Order", "Order")
|
|
203
|
+
for _, f := range order.Fields {
|
|
204
|
+
if f.Name == "status" && f.Type != "OrderStatus enum(PLACED | CONFIRMED | CANCELLED)" {
|
|
205
|
+
t.Errorf("status is %q, want the enum and its values", f.Type)
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// GraphQL is polymorphic in two ways and answers both of them with the same
|
|
211
|
+
// field, which is the one a client would select.
|
|
212
|
+
func TestUnionsDiscriminateOnTypename(t *testing.T) {
|
|
213
|
+
result := message(t, "storefront.v1.Order", "OrderResult")
|
|
214
|
+
if result.Discriminator == nil {
|
|
215
|
+
t.Fatal("a union came back with no discriminator")
|
|
216
|
+
}
|
|
217
|
+
if result.Discriminator.Property != "__typename" {
|
|
218
|
+
t.Errorf("discriminates on %q, want __typename", result.Discriminator.Property)
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
var variants []string
|
|
222
|
+
for _, v := range result.Discriminator.Variants {
|
|
223
|
+
variants = append(variants, v.Message)
|
|
224
|
+
}
|
|
225
|
+
if len(variants) != 2 || variants[0] != "Order" || variants[1] != "OrderNotFound" {
|
|
226
|
+
t.Errorf("variants are %v, want Order and OrderNotFound", variants)
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
// A deprecated field is reported deprecated, and its reason is prose the
|
|
231
|
+
// reader gets to see.
|
|
232
|
+
func TestDeprecationSurvives(t *testing.T) {
|
|
233
|
+
m := method(t, "storefront.v1.Basket", "Query.legacyBasket")
|
|
234
|
+
if !m.Deprecated {
|
|
235
|
+
t.Error("the deprecated field is not marked deprecated")
|
|
236
|
+
}
|
|
237
|
+
if m.Doc != "Deprecated: Ask for `basket` instead." {
|
|
238
|
+
t.Errorf("doc is %q, want the deprecation reason", m.Doc)
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
// The same schema read twice is the same fragment. Everything that came out of
|
|
243
|
+
// a map is sorted, and nothing reads a clock.
|
|
244
|
+
func TestExtractionIsDeterministic(t *testing.T) {
|
|
245
|
+
first, err := json.Marshal(fragment(t))
|
|
246
|
+
if err != nil {
|
|
247
|
+
t.Fatal(err)
|
|
248
|
+
}
|
|
249
|
+
second, err := json.Marshal(fragment(t))
|
|
250
|
+
if err != nil {
|
|
251
|
+
t.Fatal(err)
|
|
252
|
+
}
|
|
253
|
+
if string(first) != string(second) {
|
|
254
|
+
t.Error("two runs over the same schema produced different fragments")
|
|
255
|
+
}
|
|
256
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
package main
|
|
2
|
+
|
|
3
|
+
// What a schema's parts are called in the catalog.
|
|
4
|
+
//
|
|
5
|
+
// Two readers have to agree on these. This one reads the SDL and says what a
|
|
6
|
+
// service provides; `extract-ts` reads the resolvers beside it and says what
|
|
7
|
+
// each field goes on to call, and a flow step that named a field differently
|
|
8
|
+
// from the method it lands on would never meet it. The spelling is written
|
|
9
|
+
// out twice because the two are in different languages; `extract-ts/graphql.ts`
|
|
10
|
+
// is the other copy.
|
|
11
|
+
|
|
12
|
+
import "strings"
|
|
13
|
+
|
|
14
|
+
// interfaceID is the interface a module's root fields land in: the api and the
|
|
15
|
+
// module, `storefront.v1.Basket`. A schema in one file has no module to name,
|
|
16
|
+
// and its fields land on the api itself.
|
|
17
|
+
func interfaceID(api, module string) string {
|
|
18
|
+
if module == "" {
|
|
19
|
+
return api
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
return api + "." + title(module)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// methodName is a root field by the operation it belongs to: `Query.basket`.
|
|
26
|
+
// GraphQL has no other name for it - two operations may each have a `basket`
|
|
27
|
+
// field, and they are not the same endpoint.
|
|
28
|
+
func methodName(root, field string) string { return root + "." + field }
|
|
29
|
+
|
|
30
|
+
// argsMessage names the shape a field's arguments make when they are not
|
|
31
|
+
// already one input object: `Query.basket(id: ID!)` gives `QueryBasketArgs`.
|
|
32
|
+
// The name is the one graphql-codegen generates for the same thing, so a
|
|
33
|
+
// reader who has the generated types open recognises it.
|
|
34
|
+
func argsMessage(root, field string) string { return root + title(field) + "Args" }
|
|
35
|
+
|
|
36
|
+
// title is the human form of a module name: `basket` becomes Basket,
|
|
37
|
+
// `order_status` becomes OrderStatus.
|
|
38
|
+
func title(name string) string {
|
|
39
|
+
var b strings.Builder
|
|
40
|
+
for _, word := range strings.FieldsFunc(name, func(r rune) bool { return r == '_' || r == '-' || r == ' ' || r == '.' }) {
|
|
41
|
+
runes := []rune(word)
|
|
42
|
+
if runes[0] >= 'a' && runes[0] <= 'z' {
|
|
43
|
+
runes[0] = runes[0] - 'a' + 'A'
|
|
44
|
+
}
|
|
45
|
+
b.WriteString(string(runes))
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return b.String()
|
|
49
|
+
}
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
package main
|
|
2
|
+
|
|
3
|
+
// The tokens of a GraphQL SDL document, and the descriptions attached to them.
|
|
4
|
+
//
|
|
5
|
+
// A schema documents itself in strings rather than in comments: `# ...` is
|
|
6
|
+
// thrown away by every reader, and the prose a client is meant to see sits in
|
|
7
|
+
// a string literal directly above the thing it describes. So the lexer keeps
|
|
8
|
+
// string tokens as tokens - the parser decides which of them are descriptions -
|
|
9
|
+
// and drops comments on the floor, which is the opposite of what the proto
|
|
10
|
+
// lexer beside it has to do.
|
|
11
|
+
|
|
12
|
+
import (
|
|
13
|
+
"fmt"
|
|
14
|
+
"strings"
|
|
15
|
+
"unicode"
|
|
16
|
+
"unicode/utf8"
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
type kind int
|
|
20
|
+
|
|
21
|
+
const (
|
|
22
|
+
tokEOF kind = iota
|
|
23
|
+
tokName
|
|
24
|
+
tokString
|
|
25
|
+
tokNumber
|
|
26
|
+
tokPunct
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
type token struct {
|
|
30
|
+
kind kind
|
|
31
|
+
text string
|
|
32
|
+
line int
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
func (t token) is(text string) bool {
|
|
36
|
+
return (t.kind == tokPunct || t.kind == tokName) && t.text == text
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
type lexer struct {
|
|
40
|
+
src string
|
|
41
|
+
pos int
|
|
42
|
+
line int
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
func lex(src string) ([]token, error) {
|
|
46
|
+
l := &lexer{src: strings.TrimPrefix(src, "\ufeff"), line: 1}
|
|
47
|
+
|
|
48
|
+
var out []token
|
|
49
|
+
for {
|
|
50
|
+
tok, err := l.next()
|
|
51
|
+
if err != nil {
|
|
52
|
+
return nil, err
|
|
53
|
+
}
|
|
54
|
+
out = append(out, tok)
|
|
55
|
+
if tok.kind == tokEOF {
|
|
56
|
+
return out, nil
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
func (l *lexer) next() (token, error) {
|
|
62
|
+
for {
|
|
63
|
+
l.skipIgnored()
|
|
64
|
+
if l.pos >= len(l.src) {
|
|
65
|
+
return token{kind: tokEOF, line: l.line}, nil
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
c := l.src[l.pos]
|
|
69
|
+
switch {
|
|
70
|
+
case c == '#':
|
|
71
|
+
l.lineComment()
|
|
72
|
+
continue
|
|
73
|
+
case c == '"':
|
|
74
|
+
return l.stringLiteral()
|
|
75
|
+
case c == '_' || isLetter(c):
|
|
76
|
+
return l.name(), nil
|
|
77
|
+
case c == '-' || isDigit(c):
|
|
78
|
+
return l.number(), nil
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// `...` is one token; every other punctuator is one byte. Nothing else
|
|
82
|
+
// is legal, and a document that reaches here is one no server would
|
|
83
|
+
// serve either.
|
|
84
|
+
if strings.HasPrefix(l.src[l.pos:], "...") {
|
|
85
|
+
tok := token{kind: tokPunct, text: "...", line: l.line}
|
|
86
|
+
l.pos += 3
|
|
87
|
+
return tok, nil
|
|
88
|
+
}
|
|
89
|
+
if strings.ContainsRune("!$&()::=@[]{|}", rune(c)) {
|
|
90
|
+
tok := token{kind: tokPunct, text: string(c), line: l.line}
|
|
91
|
+
l.pos++
|
|
92
|
+
return tok, nil
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
return token{}, fmt.Errorf("line %d: %q is not a graphql token", l.line, string(c))
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// skipIgnored eats whitespace and the commas GraphQL treats as whitespace.
|
|
100
|
+
func (l *lexer) skipIgnored() {
|
|
101
|
+
for l.pos < len(l.src) {
|
|
102
|
+
switch l.src[l.pos] {
|
|
103
|
+
case '\n':
|
|
104
|
+
l.line++
|
|
105
|
+
l.pos++
|
|
106
|
+
case ' ', '\t', '\r', ',':
|
|
107
|
+
l.pos++
|
|
108
|
+
default:
|
|
109
|
+
return
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
func (l *lexer) lineComment() {
|
|
115
|
+
for l.pos < len(l.src) && l.src[l.pos] != '\n' {
|
|
116
|
+
l.pos++
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
func (l *lexer) name() token {
|
|
121
|
+
start := l.pos
|
|
122
|
+
for l.pos < len(l.src) && (isLetter(l.src[l.pos]) || isDigit(l.src[l.pos]) || l.src[l.pos] == '_') {
|
|
123
|
+
l.pos++
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
return token{kind: tokName, text: l.src[start:l.pos], line: l.line}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// number is lexed only so a default value can be stepped over. Nothing in the
|
|
130
|
+
// catalog is interested in what it says.
|
|
131
|
+
func (l *lexer) number() token {
|
|
132
|
+
start := l.pos
|
|
133
|
+
l.pos++
|
|
134
|
+
for l.pos < len(l.src) && (isDigit(l.src[l.pos]) || strings.ContainsRune(".eE+-", rune(l.src[l.pos]))) {
|
|
135
|
+
l.pos++
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
return token{kind: tokNumber, text: l.src[start:l.pos], line: l.line}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
func (l *lexer) stringLiteral() (token, error) {
|
|
142
|
+
line := l.line
|
|
143
|
+
if strings.HasPrefix(l.src[l.pos:], `"""`) {
|
|
144
|
+
l.pos += 3
|
|
145
|
+
start := l.pos
|
|
146
|
+
for {
|
|
147
|
+
if l.pos >= len(l.src) {
|
|
148
|
+
return token{}, fmt.Errorf("line %d: a block string is never closed", line)
|
|
149
|
+
}
|
|
150
|
+
if strings.HasPrefix(l.src[l.pos:], `"""`) && (l.pos == start || l.src[l.pos-1] != '\\') {
|
|
151
|
+
text := l.src[start:l.pos]
|
|
152
|
+
l.line += strings.Count(text, "\n")
|
|
153
|
+
l.pos += 3
|
|
154
|
+
return token{kind: tokString, text: blockString(text), line: line}, nil
|
|
155
|
+
}
|
|
156
|
+
l.pos++
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
l.pos++
|
|
161
|
+
var b strings.Builder
|
|
162
|
+
for {
|
|
163
|
+
if l.pos >= len(l.src) || l.src[l.pos] == '\n' {
|
|
164
|
+
return token{}, fmt.Errorf("line %d: a string is never closed", line)
|
|
165
|
+
}
|
|
166
|
+
c := l.src[l.pos]
|
|
167
|
+
if c == '"' {
|
|
168
|
+
l.pos++
|
|
169
|
+
return token{kind: tokString, text: b.String(), line: line}, nil
|
|
170
|
+
}
|
|
171
|
+
if c == '\\' && l.pos+1 < len(l.src) {
|
|
172
|
+
l.pos++
|
|
173
|
+
switch l.src[l.pos] {
|
|
174
|
+
case 'n':
|
|
175
|
+
b.WriteByte('\n')
|
|
176
|
+
case 't':
|
|
177
|
+
b.WriteByte('\t')
|
|
178
|
+
case 'u':
|
|
179
|
+
if l.pos+4 < len(l.src) {
|
|
180
|
+
var r rune
|
|
181
|
+
if _, err := fmt.Sscanf(l.src[l.pos+1:l.pos+5], "%04x", &r); err == nil {
|
|
182
|
+
b.WriteRune(r)
|
|
183
|
+
l.pos += 4
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
default:
|
|
187
|
+
b.WriteByte(l.src[l.pos])
|
|
188
|
+
}
|
|
189
|
+
l.pos++
|
|
190
|
+
continue
|
|
191
|
+
}
|
|
192
|
+
r, size := utf8.DecodeRuneInString(l.src[l.pos:])
|
|
193
|
+
b.WriteRune(r)
|
|
194
|
+
l.pos += size
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// blockString applies the indentation rules the spec gives for `"""` strings:
|
|
199
|
+
// the common indent of every line after the first is removed, and blank lines
|
|
200
|
+
// at either end go with it. Without this every description in the catalog
|
|
201
|
+
// would carry the indentation of the schema file it was written in.
|
|
202
|
+
func blockString(raw string) string {
|
|
203
|
+
lines := strings.Split(strings.ReplaceAll(raw, "\r\n", "\n"), "\n")
|
|
204
|
+
|
|
205
|
+
indent := -1
|
|
206
|
+
for _, line := range lines[1:] {
|
|
207
|
+
trimmed := strings.TrimLeft(line, " \t")
|
|
208
|
+
if trimmed == "" {
|
|
209
|
+
continue
|
|
210
|
+
}
|
|
211
|
+
if width := len(line) - len(trimmed); indent < 0 || width < indent {
|
|
212
|
+
indent = width
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
if indent > 0 {
|
|
216
|
+
for i, line := range lines[1:] {
|
|
217
|
+
if len(line) >= indent {
|
|
218
|
+
lines[i+1] = line[indent:]
|
|
219
|
+
} else {
|
|
220
|
+
lines[i+1] = strings.TrimLeft(line, " \t")
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
for len(lines) > 0 && strings.TrimSpace(lines[0]) == "" {
|
|
226
|
+
lines = lines[1:]
|
|
227
|
+
}
|
|
228
|
+
for len(lines) > 0 && strings.TrimSpace(lines[len(lines)-1]) == "" {
|
|
229
|
+
lines = lines[:len(lines)-1]
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
return strings.Join(lines, "\n")
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
func isLetter(c byte) bool { return unicode.IsLetter(rune(c)) && c < utf8.RuneSelf }
|
|
236
|
+
|
|
237
|
+
func isDigit(c byte) bool { return c >= '0' && c <= '9' }
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
// Package main is portolan-extract-graphql: a GraphQL schema in, a catalog
|
|
2
|
+
// fragment out.
|
|
3
|
+
//
|
|
4
|
+
// It describes one aspect of a service - what a client may ask it for - and
|
|
5
|
+
// nothing else. Who answers underneath is a different fact, read by whichever
|
|
6
|
+
// extractor reads the resolvers, and the two meet in the merge. Neither knows
|
|
7
|
+
// the other exists, which is the whole reason each of them stays small.
|
|
8
|
+
package main
|
|
9
|
+
|
|
10
|
+
import (
|
|
11
|
+
"fmt"
|
|
12
|
+
"io"
|
|
13
|
+
"os"
|
|
14
|
+
|
|
15
|
+
"github.com/shortlink-org/portolan/plugin"
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
// Options are what the manifest tells the extractor: the things a schema does
|
|
19
|
+
// not say about the estate it belongs to.
|
|
20
|
+
type Options struct {
|
|
21
|
+
Context string `json:"context"`
|
|
22
|
+
Service string `json:"service"`
|
|
23
|
+
|
|
24
|
+
// Schema is the document or the directory of documents, relative to the
|
|
25
|
+
// input root. Left out, the extractor looks for them.
|
|
26
|
+
Schema string `json:"schema,omitempty"`
|
|
27
|
+
|
|
28
|
+
// API prefixes the ids of the interfaces this produces. Left out, it is
|
|
29
|
+
// the service and a major version - `bff` gives `bff.v1`, and a module
|
|
30
|
+
// called `basket` gives `bff.v1.Basket`.
|
|
31
|
+
API string `json:"api,omitempty"`
|
|
32
|
+
|
|
33
|
+
Out string `json:"out,omitempty"`
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
func main() {
|
|
37
|
+
if err := run(os.Stdin, os.Stdout); err != nil {
|
|
38
|
+
fmt.Fprintln(os.Stderr, "portolan-extract-graphql:", err)
|
|
39
|
+
os.Exit(1)
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
func run(stdin io.Reader, stdout io.Writer) error {
|
|
44
|
+
return plugin.Serve(stdin, stdout, descriptor(), func(req plugin.Request, opts Options) (plugin.Response, error) {
|
|
45
|
+
if req.Input.Root == "" {
|
|
46
|
+
return plugin.Response{}, fmt.Errorf("no input root: an extractor has nothing to read")
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return extract(req.Input, opts)
|
|
50
|
+
})
|
|
51
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"type": "object",
|
|
3
|
+
"additionalProperties": false,
|
|
4
|
+
"properties": {
|
|
5
|
+
"context": {
|
|
6
|
+
"type": "string",
|
|
7
|
+
"description": "Slug of the bounded context that owns the service this schema belongs to. Defaults to the name of the input directory.",
|
|
8
|
+
"examples": ["storefront"]
|
|
9
|
+
},
|
|
10
|
+
"service": {
|
|
11
|
+
"type": "string",
|
|
12
|
+
"description": "Slug of the service the schema describes. Defaults to the name of the input directory.",
|
|
13
|
+
"examples": ["bff"]
|
|
14
|
+
},
|
|
15
|
+
"schema": {
|
|
16
|
+
"type": "string",
|
|
17
|
+
"description": "The schema, relative to the input root: one .graphql document, or a directory of them read together. Left out, the extractor looks for them.",
|
|
18
|
+
"examples": ["src/schema"]
|
|
19
|
+
},
|
|
20
|
+
"api": {
|
|
21
|
+
"type": "string",
|
|
22
|
+
"description": "Prefix for the ids of the interfaces this produces. Left out, it is the service and a major version: bff gives bff.v1, and a module called basket gives bff.v1.Basket.",
|
|
23
|
+
"examples": ["storefront.v1"]
|
|
24
|
+
},
|
|
25
|
+
"out": {
|
|
26
|
+
"type": "string",
|
|
27
|
+
"description": "Name of the fragment file, inside the step's output directory.",
|
|
28
|
+
"default": "graphql.json"
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|