@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,593 @@
|
|
|
1
|
+
// The command palette's index and its ranking. Pure: given a catalog and a
|
|
2
|
+
// query string it returns the rows to draw, so the ordering can be asserted in
|
|
3
|
+
// a test rather than eyeballed.
|
|
4
|
+
//
|
|
5
|
+
// Every row also carries the PROSE that belongs to it - a context's summary, a
|
|
6
|
+
// readme and the invariants written in it, an event's version notes, a field's
|
|
7
|
+
// doc line, the body of a decision. Names and ids are how you find a thing you
|
|
8
|
+
// can already name; prose is how you find the thing you can only describe
|
|
9
|
+
// ("the rule about two currencies in one order"). It is the last tier the
|
|
10
|
+
// scorer tries, so a prose hit never displaces a name, and a hit brings its
|
|
11
|
+
// own line of context back with it - a row that matched on something the
|
|
12
|
+
// reader cannot see is a row they have to open to understand.
|
|
13
|
+
|
|
14
|
+
import type { Block, Catalog, Event, Field } from "../catalog";
|
|
15
|
+
import { allTerms, enumsOf, walkSteps } from "../catalog";
|
|
16
|
+
import { flowHealth } from "./flow-tree";
|
|
17
|
+
import { parseQuery } from "./kinds";
|
|
18
|
+
import type { Kind, ParsedQuery } from "./kinds";
|
|
19
|
+
import { paths, storePath, tablePath, viewPath } from "../routes";
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Markdown, flattened to one line of searchable prose.
|
|
23
|
+
*
|
|
24
|
+
* Fenced code is dropped whole: a readme's Go snippet would match half the
|
|
25
|
+
* catalog's identifiers and answer nothing. The remaining marks are stripped
|
|
26
|
+
* rather than parsed - `**never**` must be found by typing "never", and an
|
|
27
|
+
* excerpt is a sentence, not a rendering.
|
|
28
|
+
*/
|
|
29
|
+
export function flattenProse(markdown: string): string {
|
|
30
|
+
return markdown
|
|
31
|
+
.replace(/```[\s\S]*?```/g, " ")
|
|
32
|
+
.replace(/[`*_#>|[\]]/g, "")
|
|
33
|
+
.replace(/\s+/g, " ")
|
|
34
|
+
.trim();
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/** Everything a field says about itself, for the row that owns the field. */
|
|
38
|
+
function fieldProse(fields: readonly Field[] | undefined): string {
|
|
39
|
+
return (fields ?? []).map((f) => `${f.name} ${f.doc}`).join(" ");
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function eventProse(event: Event): string {
|
|
43
|
+
return event.versions
|
|
44
|
+
.map((v) => `${v.doc} ${fieldProse(v.fields)}`)
|
|
45
|
+
.join(" ");
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function blockProse(block: Block): string {
|
|
49
|
+
return `${block.doc} ${fieldProse(block.fields)}`;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export interface PaletteItem {
|
|
53
|
+
kind: Kind;
|
|
54
|
+
/**
|
|
55
|
+
* The catalog id of the thing. Rows are keyed by kind AND id downstream: a
|
|
56
|
+
* term's id has the same shape as a service's - `<context>.<name>` - so a
|
|
57
|
+
* context with a service called `billing` and a word called Billing would
|
|
58
|
+
* otherwise be two rows fighting over one key.
|
|
59
|
+
*/
|
|
60
|
+
id: string;
|
|
61
|
+
/**
|
|
62
|
+
* The catalog id to SELECT when picking this row, for the kinds the
|
|
63
|
+
* selection model knows. Rows without one only navigate: a value object,
|
|
64
|
+
* a command and a decision have pages but are not selectable entities.
|
|
65
|
+
*/
|
|
66
|
+
selectId?: string;
|
|
67
|
+
/** What is matched and shown first. */
|
|
68
|
+
name: string;
|
|
69
|
+
/** Where it lives - owner id, or the summary for flows and decisions. */
|
|
70
|
+
detail: string;
|
|
71
|
+
/** The page that owns the row, or null when it has none (shared types). */
|
|
72
|
+
path: string | null;
|
|
73
|
+
/** Context colour to paint with, or null for org-wide rows. */
|
|
74
|
+
context: string | null;
|
|
75
|
+
/** Right-aligned extra, e.g. an event's latest version. */
|
|
76
|
+
badge?: string;
|
|
77
|
+
/**
|
|
78
|
+
* Names the row is also known by, searched after its own and before its
|
|
79
|
+
* prose: for a flow, the lanes it runs through and the labels and refs of
|
|
80
|
+
* its steps, so "GetQuote" finds the flow that makes that call.
|
|
81
|
+
*/
|
|
82
|
+
keywords?: string[];
|
|
83
|
+
/**
|
|
84
|
+
* The row's own prose, flattened to one line. Searched last, and only for
|
|
85
|
+
* terms long enough to mean something; a row with nothing written about it
|
|
86
|
+
* simply leaves it out.
|
|
87
|
+
*/
|
|
88
|
+
text?: string;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/** Every navigable thing in the catalog, built once at module load. */
|
|
92
|
+
export function paletteItems(catalog: Catalog): PaletteItem[] {
|
|
93
|
+
const items: PaletteItem[] = [];
|
|
94
|
+
|
|
95
|
+
for (const context of catalog.contexts) {
|
|
96
|
+
items.push({
|
|
97
|
+
kind: "context",
|
|
98
|
+
id: context.id,
|
|
99
|
+
selectId: context.id,
|
|
100
|
+
name: context.id,
|
|
101
|
+
detail: context.name,
|
|
102
|
+
path: paths.context(context.id),
|
|
103
|
+
context: context.id,
|
|
104
|
+
text: flattenProse(`${context.name} ${context.summary}`),
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
for (const service of context.services) {
|
|
108
|
+
items.push({
|
|
109
|
+
kind: "service",
|
|
110
|
+
id: service.id,
|
|
111
|
+
selectId: service.id,
|
|
112
|
+
name: service.slug,
|
|
113
|
+
detail: service.id,
|
|
114
|
+
path: paths.service(context.id, service.slug),
|
|
115
|
+
context: context.id,
|
|
116
|
+
text: flattenProse(`${service.name} ${service.readme}`),
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
for (const aggregate of service.aggregates) {
|
|
120
|
+
items.push({
|
|
121
|
+
kind: "aggregate",
|
|
122
|
+
id: aggregate.id,
|
|
123
|
+
selectId: aggregate.id,
|
|
124
|
+
name: aggregate.name,
|
|
125
|
+
detail: service.id,
|
|
126
|
+
path: paths.aggregate(context.id, service.slug, aggregate.slug),
|
|
127
|
+
context: context.id,
|
|
128
|
+
badge: `root: ${aggregate.root}`,
|
|
129
|
+
// The readme is where the invariants live, and an invariant is the
|
|
130
|
+
// one fact about an aggregate nobody can guess the name of.
|
|
131
|
+
text: flattenProse(`${aggregate.name} ${aggregate.readme}`),
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
for (const event of aggregate.events) {
|
|
135
|
+
const latest = event.versions[event.versions.length - 1];
|
|
136
|
+
items.push({
|
|
137
|
+
kind: "event",
|
|
138
|
+
id: event.id,
|
|
139
|
+
selectId: event.id,
|
|
140
|
+
name: event.name,
|
|
141
|
+
detail: aggregate.id,
|
|
142
|
+
path: paths.event(
|
|
143
|
+
context.id,
|
|
144
|
+
service.slug,
|
|
145
|
+
aggregate.slug,
|
|
146
|
+
event.slug,
|
|
147
|
+
),
|
|
148
|
+
context: context.id,
|
|
149
|
+
...(latest ? { badge: latest.version } : {}),
|
|
150
|
+
text: flattenProse(eventProse(event)),
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
for (const vo of aggregate.valueObjects) {
|
|
155
|
+
items.push({
|
|
156
|
+
kind: "vo",
|
|
157
|
+
id: vo.id,
|
|
158
|
+
name: vo.name,
|
|
159
|
+
detail: aggregate.id,
|
|
160
|
+
path: paths.valueObject(
|
|
161
|
+
context.id,
|
|
162
|
+
service.slug,
|
|
163
|
+
aggregate.slug,
|
|
164
|
+
vo.slug,
|
|
165
|
+
),
|
|
166
|
+
context: context.id,
|
|
167
|
+
text: flattenProse(blockProse(vo)),
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
for (const item of enumsOf(aggregate)) {
|
|
172
|
+
items.push({
|
|
173
|
+
kind: "enum",
|
|
174
|
+
id: item.id,
|
|
175
|
+
name: item.name,
|
|
176
|
+
detail: aggregate.id,
|
|
177
|
+
path: paths.enum(
|
|
178
|
+
context.id,
|
|
179
|
+
service.slug,
|
|
180
|
+
aggregate.slug,
|
|
181
|
+
item.slug,
|
|
182
|
+
),
|
|
183
|
+
context: context.id,
|
|
184
|
+
// The values are what a reader remembers - "the one with
|
|
185
|
+
// CARD_REFUSED" - so they are searchable, docs and all.
|
|
186
|
+
text: flattenProse(
|
|
187
|
+
`${item.doc} ${item.values.map((v) => `${v.name} ${v.doc}`).join(" ")}`,
|
|
188
|
+
),
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
for (const entity of aggregate.entities) {
|
|
193
|
+
items.push({
|
|
194
|
+
kind: "entity",
|
|
195
|
+
id: entity.id,
|
|
196
|
+
name: entity.name,
|
|
197
|
+
detail: aggregate.id,
|
|
198
|
+
path: paths.entity(
|
|
199
|
+
context.id,
|
|
200
|
+
service.slug,
|
|
201
|
+
aggregate.slug,
|
|
202
|
+
entity.slug,
|
|
203
|
+
),
|
|
204
|
+
context: context.id,
|
|
205
|
+
...(entity.name === aggregate.root ? { badge: "root" } : {}),
|
|
206
|
+
text: flattenProse(blockProse(entity)),
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// Commands and queries have no page of their own; they land on the
|
|
211
|
+
// aggregate that handles them, at the right section.
|
|
212
|
+
for (const op of aggregate.operations) {
|
|
213
|
+
items.push({
|
|
214
|
+
kind: op.kind,
|
|
215
|
+
id: `${aggregate.id}#${op.id}`,
|
|
216
|
+
name: op.id,
|
|
217
|
+
detail: aggregate.id,
|
|
218
|
+
path: `${paths.aggregate(context.id, service.slug, aggregate.slug)}#bb-${op.kind === "command" ? "commands" : "queries"}`,
|
|
219
|
+
context: context.id,
|
|
220
|
+
...(op.doc ? { text: flattenProse(op.doc) } : {}),
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// Endpoints hang off the service rather than an aggregate: one of them
|
|
226
|
+
// can run use cases from two of them. They have no page of their own
|
|
227
|
+
// either, so they land on the tab that lists them.
|
|
228
|
+
for (const provided of service.provides) {
|
|
229
|
+
for (const method of provided.methods) {
|
|
230
|
+
items.push({
|
|
231
|
+
kind: "endpoint",
|
|
232
|
+
id: `${provided.id}/${method.name}`,
|
|
233
|
+
name: method.name,
|
|
234
|
+
detail: provided.id,
|
|
235
|
+
path: `${paths.service(context.id, service.slug)}?tab=provides`,
|
|
236
|
+
context: context.id,
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
// Shared types have no page: picking one opens the detail panel where it is.
|
|
244
|
+
// They are listed all the same, because "which events carry a Money?" is a
|
|
245
|
+
// question people arrive with.
|
|
246
|
+
for (const [id, def] of Object.entries(catalog.defs)) {
|
|
247
|
+
items.push({
|
|
248
|
+
kind: "def",
|
|
249
|
+
id: `def:${id}`,
|
|
250
|
+
selectId: id,
|
|
251
|
+
name: id,
|
|
252
|
+
detail: "shared type",
|
|
253
|
+
path: null,
|
|
254
|
+
context: null,
|
|
255
|
+
badge: `${def.fields.length}f`,
|
|
256
|
+
text: flattenProse(fieldProse(def.fields)),
|
|
257
|
+
});
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
// Schema modules. Found by the name a reader pastes into a buf.yaml, and by
|
|
261
|
+
// the packages inside them — "which module declares shop.v1?" is a question
|
|
262
|
+
// people arrive with, and the module page is the only thing that answers it.
|
|
263
|
+
for (const module of catalog.modules ?? []) {
|
|
264
|
+
items.push({
|
|
265
|
+
kind: "module",
|
|
266
|
+
id: module.id,
|
|
267
|
+
selectId: module.id,
|
|
268
|
+
name: module.name,
|
|
269
|
+
detail: module.registry ?? "not published",
|
|
270
|
+
path: paths.module(module.slug),
|
|
271
|
+
context: null,
|
|
272
|
+
badge: module.commit ? module.commit.slice(0, 7) : undefined,
|
|
273
|
+
text: flattenProse(module.packages.join(" ")),
|
|
274
|
+
});
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
// Stores and tables. A table is the one row here whose name a reader is
|
|
278
|
+
// likely to know exactly — they have just read it in a migration or a stack
|
|
279
|
+
// trace — so it is worth finding by name alone, without the store.
|
|
280
|
+
for (const store of catalog.stores ?? []) {
|
|
281
|
+
const to = storePath(store.id);
|
|
282
|
+
const context = store.owner.split(".")[0] ?? null;
|
|
283
|
+
items.push({
|
|
284
|
+
kind: "store",
|
|
285
|
+
id: store.id,
|
|
286
|
+
selectId: store.id,
|
|
287
|
+
name: store.slug,
|
|
288
|
+
detail: store.owner,
|
|
289
|
+
path: to,
|
|
290
|
+
context,
|
|
291
|
+
badge: store.kind,
|
|
292
|
+
text: flattenProse(`${store.name} ${store.source ?? ""}`),
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
for (const table of store.tables) {
|
|
296
|
+
items.push({
|
|
297
|
+
kind: "table",
|
|
298
|
+
id: table.id,
|
|
299
|
+
selectId: table.id,
|
|
300
|
+
name: table.name,
|
|
301
|
+
detail: store.id,
|
|
302
|
+
path: tablePath(table.id),
|
|
303
|
+
context,
|
|
304
|
+
...(table.role ? { badge: table.role } : {}),
|
|
305
|
+
text: flattenProse(
|
|
306
|
+
`${table.doc ?? ""} ${table.columns.map((c) => c.name).join(" ")}`,
|
|
307
|
+
),
|
|
308
|
+
});
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
// A view is searched by its SQL as well as by its columns: half the time
|
|
312
|
+
// the reader remembers the join, not the name the migration gave it.
|
|
313
|
+
for (const view of store.views ?? []) {
|
|
314
|
+
items.push({
|
|
315
|
+
kind: "view",
|
|
316
|
+
id: view.id,
|
|
317
|
+
selectId: view.id,
|
|
318
|
+
name: view.name,
|
|
319
|
+
detail: store.id,
|
|
320
|
+
path: viewPath(view.id),
|
|
321
|
+
context,
|
|
322
|
+
badge: view.materialized ? "matview" : "view",
|
|
323
|
+
text: flattenProse(
|
|
324
|
+
`${view.doc ?? ""} ${view.definition ?? ""} ${view.columns
|
|
325
|
+
.map((c) => c.name)
|
|
326
|
+
.join(" ")}`,
|
|
327
|
+
),
|
|
328
|
+
});
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
// A third party has no context and no tree row: the palette is the one way
|
|
333
|
+
// to its page besides a call that names it.
|
|
334
|
+
for (const external of catalog.externals ?? []) {
|
|
335
|
+
items.push({
|
|
336
|
+
kind: "external",
|
|
337
|
+
id: external.id,
|
|
338
|
+
name: external.name,
|
|
339
|
+
detail: "outside the estate",
|
|
340
|
+
path: paths.external(external.slug),
|
|
341
|
+
context: null,
|
|
342
|
+
keywords: external.provides.map((provided) => provided.id),
|
|
343
|
+
text: flattenProse(external.summary),
|
|
344
|
+
});
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
for (const flow of catalog.flows) {
|
|
348
|
+
const keywords = new Set<string>();
|
|
349
|
+
for (const p of flow.participants) keywords.add(p.id);
|
|
350
|
+
for (const step of walkSteps(flow.steps)) {
|
|
351
|
+
if (step.label) keywords.add(step.label);
|
|
352
|
+
if (step.ref) keywords.add(step.ref);
|
|
353
|
+
}
|
|
354
|
+
items.push({
|
|
355
|
+
kind: "flow",
|
|
356
|
+
id: flow.id,
|
|
357
|
+
name: flow.slug,
|
|
358
|
+
detail: flow.name,
|
|
359
|
+
path: paths.flow(flow.slug),
|
|
360
|
+
context: null,
|
|
361
|
+
badge: flowHealth(flow),
|
|
362
|
+
keywords: [...keywords],
|
|
363
|
+
text: flattenProse(`${flow.name} ${flow.summary}`),
|
|
364
|
+
});
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
// Last, because a term is what everything above is CALLED rather than a
|
|
368
|
+
// thing to open. A reader who typed a word and got the sentence explaining
|
|
369
|
+
// it before the aggregate named after it would have to scroll past the
|
|
370
|
+
// dictionary to reach the model.
|
|
371
|
+
for (const term of allTerms(catalog)) {
|
|
372
|
+
items.push({
|
|
373
|
+
kind: "term",
|
|
374
|
+
id: term.id,
|
|
375
|
+
name: term.name,
|
|
376
|
+
detail: term.context,
|
|
377
|
+
// The page, showing this word. A term has no page of its own - it is one
|
|
378
|
+
// paragraph, and a route per paragraph is a route nobody can hold in
|
|
379
|
+
// their head.
|
|
380
|
+
path: paths.term(term.id),
|
|
381
|
+
context: term.context,
|
|
382
|
+
text: flattenProse(term.definition),
|
|
383
|
+
});
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
for (const adr of catalog.adrs) {
|
|
387
|
+
items.push({
|
|
388
|
+
kind: "adr",
|
|
389
|
+
id: adr.id,
|
|
390
|
+
name: adr.id,
|
|
391
|
+
detail: adr.title,
|
|
392
|
+
path: paths.adr(adr.slug),
|
|
393
|
+
context: adr.scope.kind === "context" ? adr.scope.context : null,
|
|
394
|
+
badge: adr.status,
|
|
395
|
+
text: flattenProse(`${adr.title} ${adr.body}`),
|
|
396
|
+
});
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
return items;
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
/**
|
|
403
|
+
* Lower is better. Exact beats prefix beats a match at a word boundary beats
|
|
404
|
+
* anything else, and the id is only consulted once the name has failed, so
|
|
405
|
+
* typing "money" puts the value objects called Money above the events that
|
|
406
|
+
* merely carry one.
|
|
407
|
+
*/
|
|
408
|
+
export function score(item: PaletteItem, term: string): number | null {
|
|
409
|
+
if (!term) return 0;
|
|
410
|
+
const needle = term.toLowerCase();
|
|
411
|
+
const name = item.name.toLowerCase();
|
|
412
|
+
if (name === needle) return 0;
|
|
413
|
+
if (name.startsWith(needle)) return 1;
|
|
414
|
+
// A word boundary is a case change or one of . / - _ ; "item" should hit
|
|
415
|
+
// "AddItem" and "line-item" but not rank with a mid-word accident.
|
|
416
|
+
if (new RegExp(`(^|[.\\-_/ ])${escapeRegex(needle)}`).test(name)) return 2;
|
|
417
|
+
if (
|
|
418
|
+
/[a-z]/.test(item.name) &&
|
|
419
|
+
new RegExp(`[a-z]${escapeRegex(term)}`).test(item.name)
|
|
420
|
+
)
|
|
421
|
+
return 2;
|
|
422
|
+
if (name.includes(needle)) return 3;
|
|
423
|
+
if (item.id.toLowerCase().includes(needle)) return 4;
|
|
424
|
+
if (item.detail.toLowerCase().includes(needle)) return 5;
|
|
425
|
+
if (keywordHit(item, needle)) return KEYWORD_SCORE;
|
|
426
|
+
// Last, and only for a term with something to say. Two characters match
|
|
427
|
+
// prose everywhere and rank nothing; the floor is what stops "or" from
|
|
428
|
+
// returning the whole estate under the rows that actually answered.
|
|
429
|
+
if (
|
|
430
|
+
term.length >= PROSE_MIN &&
|
|
431
|
+
item.text &&
|
|
432
|
+
item.text.toLowerCase().includes(needle)
|
|
433
|
+
)
|
|
434
|
+
return PROSE_SCORE;
|
|
435
|
+
return null;
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
/** The first keyword the term is found in, or undefined. */
|
|
439
|
+
function keywordHit(item: PaletteItem, needle: string): string | undefined {
|
|
440
|
+
if (needle.length < PROSE_MIN) return undefined;
|
|
441
|
+
return item.keywords?.find((k) => k.toLowerCase().includes(needle));
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
/** The score a keyword hit returns; it owes an excerpt naming the keyword. */
|
|
445
|
+
const KEYWORD_SCORE = 6;
|
|
446
|
+
|
|
447
|
+
/** Shortest term the prose tier will answer. Below it, names only. */
|
|
448
|
+
const PROSE_MIN = 3;
|
|
449
|
+
|
|
450
|
+
/** How much of the sentence around a hit comes back with it. */
|
|
451
|
+
const LEAD = 32;
|
|
452
|
+
const TRAIL = 56;
|
|
453
|
+
|
|
454
|
+
/**
|
|
455
|
+
* The words around a prose hit, cut to fit one row.
|
|
456
|
+
*
|
|
457
|
+
* Returned as three parts rather than one string so the caller can mark the
|
|
458
|
+
* match without parsing its own output back apart - and so a term containing
|
|
459
|
+
* regex punctuation is never a regex.
|
|
460
|
+
*/
|
|
461
|
+
export interface Excerpt {
|
|
462
|
+
before: string;
|
|
463
|
+
match: string;
|
|
464
|
+
after: string;
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
export function excerptOf(text: string, term: string): Excerpt | null {
|
|
468
|
+
if (!term) return null;
|
|
469
|
+
const at = text.toLowerCase().indexOf(term.toLowerCase());
|
|
470
|
+
if (at < 0) return null;
|
|
471
|
+
|
|
472
|
+
const end = at + term.length;
|
|
473
|
+
// Cut at a space where there is one nearby, so an excerpt starts on a word
|
|
474
|
+
// rather than in the middle of one.
|
|
475
|
+
let from = Math.max(0, at - LEAD);
|
|
476
|
+
if (from > 0) {
|
|
477
|
+
const space = text.indexOf(" ", from);
|
|
478
|
+
if (space >= 0 && space < at) from = space + 1;
|
|
479
|
+
}
|
|
480
|
+
let to = Math.min(text.length, end + TRAIL);
|
|
481
|
+
if (to < text.length) {
|
|
482
|
+
const space = text.lastIndexOf(" ", to);
|
|
483
|
+
if (space > end) to = space;
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
return {
|
|
487
|
+
before: (from > 0 ? "…" : "") + text.slice(from, at),
|
|
488
|
+
match: text.slice(at, end),
|
|
489
|
+
after: text.slice(end, to) + (to < text.length ? "…" : ""),
|
|
490
|
+
};
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
function escapeRegex(raw: string): string {
|
|
494
|
+
return raw.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
/** Kinds first in this order when scores tie: the model before the paperwork. */
|
|
498
|
+
const KIND_RANK: Record<Kind, number> = {
|
|
499
|
+
event: 0,
|
|
500
|
+
aggregate: 1,
|
|
501
|
+
vo: 2,
|
|
502
|
+
entity: 3,
|
|
503
|
+
service: 4,
|
|
504
|
+
context: 5,
|
|
505
|
+
external: 5,
|
|
506
|
+
command: 6,
|
|
507
|
+
query: 7,
|
|
508
|
+
// After the operation it exposes: a reader searching for "register" wants
|
|
509
|
+
// the command first and the door to it second.
|
|
510
|
+
endpoint: 8,
|
|
511
|
+
// A set of values after the shapes that hold it and the calls that move
|
|
512
|
+
// it: "status" wants the lifecycle's aggregate before the enum's list.
|
|
513
|
+
enum: 9,
|
|
514
|
+
def: 9,
|
|
515
|
+
// A module is a contract, so it sits with the shared types rather than with
|
|
516
|
+
// the infrastructure: what it holds is shapes other services are promised.
|
|
517
|
+
module: 10,
|
|
518
|
+
// Where the model is kept comes after the model itself: a reader looking for
|
|
519
|
+
// "orders" wants the aggregate first and the table that holds it second.
|
|
520
|
+
store: 11,
|
|
521
|
+
table: 12,
|
|
522
|
+
// A view after the tables it is computed from, for the same reason.
|
|
523
|
+
view: 13,
|
|
524
|
+
flow: 14,
|
|
525
|
+
adr: 15,
|
|
526
|
+
// Last, and on purpose. A reader typing "session" wants the aggregate they
|
|
527
|
+
// can open, not the sentence about what the word means; the term is what
|
|
528
|
+
// they fall back to when nothing they clicked explained it.
|
|
529
|
+
term: 16,
|
|
530
|
+
};
|
|
531
|
+
|
|
532
|
+
/**
|
|
533
|
+
* One row of the result list. A hit is not the same thing as an index row: it
|
|
534
|
+
* knows WHY it is here, which is the whole difference between a name match and
|
|
535
|
+
* a match on something written three paragraphs into a readme.
|
|
536
|
+
*/
|
|
537
|
+
export interface PaletteHit {
|
|
538
|
+
item: PaletteItem;
|
|
539
|
+
/** Set only when the term was found in prose and nowhere shorter. */
|
|
540
|
+
excerpt?: Excerpt;
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
export interface PaletteResult extends ParsedQuery {
|
|
544
|
+
hits: PaletteHit[];
|
|
545
|
+
/** Matches dropped by the limit, so the palette can say so. */
|
|
546
|
+
truncated: number;
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
/** The score the prose tier returns; the other tier that owes an excerpt. */
|
|
550
|
+
const PROSE_SCORE = 7;
|
|
551
|
+
|
|
552
|
+
export function search(
|
|
553
|
+
items: PaletteItem[],
|
|
554
|
+
raw: string,
|
|
555
|
+
limit = 40,
|
|
556
|
+
): PaletteResult {
|
|
557
|
+
const parsed = parseQuery(raw);
|
|
558
|
+
const scored: { item: PaletteItem; score: number }[] = [];
|
|
559
|
+
|
|
560
|
+
for (const item of items) {
|
|
561
|
+
if (parsed.kind && item.kind !== parsed.kind) continue;
|
|
562
|
+
const s = score(item, parsed.term);
|
|
563
|
+
if (s === null) continue;
|
|
564
|
+
scored.push({ item, score: s });
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
scored.sort(
|
|
568
|
+
(a, b) =>
|
|
569
|
+
a.score - b.score ||
|
|
570
|
+
KIND_RANK[a.item.kind] - KIND_RANK[b.item.kind] ||
|
|
571
|
+
a.item.name.length - b.item.name.length ||
|
|
572
|
+
a.item.name.localeCompare(b.item.name) ||
|
|
573
|
+
a.item.id.localeCompare(b.item.id),
|
|
574
|
+
);
|
|
575
|
+
|
|
576
|
+
const hits = scored.slice(0, limit).map(({ item, score: s }) => {
|
|
577
|
+
if (s === KEYWORD_SCORE) {
|
|
578
|
+
const keyword = keywordHit(item, parsed.term.toLowerCase());
|
|
579
|
+
return keyword
|
|
580
|
+
? { item, excerpt: { before: "runs through ", match: keyword, after: "" } }
|
|
581
|
+
: { item };
|
|
582
|
+
}
|
|
583
|
+
if (s !== PROSE_SCORE || !item.text) return { item };
|
|
584
|
+
const excerpt = excerptOf(item.text, parsed.term);
|
|
585
|
+
return excerpt ? { item, excerpt } : { item };
|
|
586
|
+
});
|
|
587
|
+
|
|
588
|
+
return {
|
|
589
|
+
...parsed,
|
|
590
|
+
hits,
|
|
591
|
+
truncated: Math.max(0, scored.length - limit),
|
|
592
|
+
};
|
|
593
|
+
}
|