@shortlink-org/portolan 0.1.0 → 0.2.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/README.md +69 -205
- package/cli/init.mjs +285 -0
- package/cli/init.test.mjs +158 -0
- package/cli/portolan.mjs +37 -73
- package/index.html +19 -0
- package/package.json +5 -10
- package/plugins/README.md +66 -27
- package/plugins/portolan-go.wasm +0 -0
- package/portolan.json +52 -73
- package/public/landing/cats/bug-hunter.webp +0 -0
- package/public/landing/cats/compass-nap.webp +0 -0
- package/public/landing/cats/diagrammer.webp +0 -0
- package/public/landing/cats/docs-reader.webp +0 -0
- package/public/landing/cats/laptop.webp +0 -0
- package/public/landing/cats/map-inspector.webp +0 -0
- package/public/landing/cats/server-break.webp +0 -0
- package/public/landing/cats/star-mapper.webp +0 -0
- package/public/landing/cats/system-builder.webp +0 -0
- package/public/landing/cats/thread-tangle.webp +0 -0
- package/public/og.png +0 -0
- package/public/readme-header.webp +0 -0
- package/schema/portolan.schema.json +180 -0
- package/scripts/builtin-plugins.mjs +14 -0
- package/scripts/delivery-presets.mjs +353 -0
- package/scripts/gen.mjs +37 -4
- package/scripts/history.mjs +126 -0
- package/scripts/history.test.mjs +110 -0
- package/scripts/host-plugins/fetch-bsr.mjs +351 -0
- package/{plugins/fetch-bsr/options.schema.json → scripts/host-plugins/fetch-bsr.options.json} +4 -0
- package/scripts/host-plugins/fetch-bsr.test.mjs +212 -0
- package/scripts/host-plugins/fetch-csr.mjs +386 -0
- package/scripts/host-plugins/fetch-csr.test.mjs +178 -0
- package/scripts/host-plugins/fetch-git.mjs +379 -0
- package/scripts/host-plugins/fetch-git.test.mjs +210 -0
- package/scripts/local-api.mjs +22 -4
- package/scripts/local-api.test.mjs +84 -2
- package/scripts/manifest.mjs +3 -2
- package/scripts/package-smoke.mjs +6 -2
- package/scripts/plugin-host.mjs +77 -18
- package/scripts/plugin-host.test.mjs +50 -1
- package/scripts/plugin-wasm-worker.mjs +6 -3
- package/scripts/run-builtin.mjs +6 -26
- package/scripts/schema.mjs +6 -1
- package/src/app/App.tsx +24 -429
- package/src/app/Breadcrumbs.test.ts +7 -0
- package/src/app/Breadcrumbs.tsx +15 -2
- package/src/app/CatalogApp.tsx +436 -0
- package/src/app/Sidebar.tsx +0 -1
- package/src/chat/ChatPanel.tsx +98 -41
- package/src/chat/Composer.tsx +4 -2
- package/src/chat/Conversation.tsx +79 -15
- package/src/chat/Header.tsx +43 -9
- package/src/chat/Starter.tsx +64 -3
- package/src/chat/Steps.tsx +1 -1
- package/src/chat/flags.test.ts +51 -14
- package/src/chat/flags.ts +8 -2
- package/src/chat/page-context.test.ts +51 -0
- package/src/chat/page-context.ts +128 -0
- package/src/chat/prompt.test.ts +49 -1
- package/src/chat/prompt.ts +42 -1
- package/src/chat/tools.ts +7 -2
- package/src/chat/transport.ts +16 -4
- package/src/components/ProblemRow.tsx +182 -0
- package/src/data.ts +20 -5
- package/src/er/ErCanvas.tsx +1 -1
- package/src/graph/DependencyGraph.tsx +10 -1
- package/src/graph/FocusedEventGraph.tsx +1 -1
- package/src/graph/GraphToolbar.tsx +2 -4
- package/src/index.css +220 -2
- package/src/landing/DraggableReveal.tsx +168 -0
- package/src/landing/EstateGraph.tsx +28 -0
- package/src/landing/FlowPlayback.tsx +282 -0
- package/src/landing/HeroMap.tsx +128 -0
- package/src/landing/LandingPage.tsx +757 -0
- package/src/landing/ProductFrame.tsx +68 -0
- package/src/landing/ProductTour.tsx +371 -0
- package/src/landing/catalog.ts +25 -0
- package/src/landing/motion.tsx +52 -0
- package/src/lib/all-problems.ts +28 -0
- package/src/lib/local-api.ts +35 -1
- package/src/lib/setup-info.test.ts +8 -0
- package/src/lib/setup-info.ts +3 -2
- package/src/lib/source-code.ts +2 -1
- package/src/likec4/C4View.tsx +5 -0
- package/src/likec4/InteractiveView.tsx +5 -1
- package/src/map/ContextMapGraph.tsx +47 -20
- package/src/pages/ContextMap.tsx +5 -1
- package/src/pages/FlowDetail.tsx +24 -7
- package/src/pages/Overview.tsx +68 -12
- package/src/pages/Problems.tsx +6 -193
- package/src/pages/Settings.tsx +133 -108
- package/src/pages/settings/DeliverySettings.tsx +229 -0
- package/src/pages/settings/PreferencesSettings.tsx +101 -0
- package/src/routes.test.ts +20 -0
- package/src/routes.ts +13 -1
- package/vite.config.ts +12 -8
- package/catalog/enum_test.go +0 -46
- package/catalog/model.go +0 -932
- package/catalog/roundtrip_test.go +0 -185
- package/catalog/via_test.go +0 -38
- package/go.mod +0 -14
- package/go.sum +0 -14
- package/internal/commands/cargo.go +0 -154
- package/internal/commands/commands.go +0 -143
- package/internal/commands/commands_test.go +0 -323
- package/internal/commands/gradle.go +0 -77
- package/internal/commands/justfile.go +0 -82
- package/internal/commands/makefile.go +0 -106
- package/internal/commands/maven.go +0 -93
- package/internal/commands/packagejson.go +0 -159
- package/internal/commands/pyproject.go +0 -169
- package/internal/commands/taskfile.go +0 -101
- package/internal/commands/testdata/estate/.cargo/config.toml +0 -7
- package/internal/commands/testdata/estate/Makefile +0 -33
- package/internal/commands/testdata/estate/Taskfile.yml +0 -21
- package/internal/commands/testdata/estate/build.gradle.kts +0 -21
- package/internal/commands/testdata/estate/justfile +0 -20
- package/internal/commands/testdata/estate/package.json +0 -13
- package/internal/commands/testdata/estate/pom.xml +0 -29
- package/internal/commands/testdata/estate/pyproject.toml +0 -27
- package/internal/commands/testdata/estate/xtask/src/main.rs +0 -27
- package/internal/commands/testdata/golden/commands.json +0 -305
- package/internal/gohttp/analyze.go +0 -2500
- package/internal/gohttp/endpoints.go +0 -1067
- package/internal/gohttp/roots.go +0 -320
- package/internal/gohttp/typed.go +0 -143
- package/internal/goscan/constants.go +0 -85
- package/internal/goscan/goscan_test.go +0 -227
- package/internal/goscan/names.go +0 -52
- package/internal/goscan/parse_test.go +0 -11
- package/internal/goscan/source.go +0 -36
- package/internal/goscan/tree.go +0 -155
- package/internal/goscan/types.go +0 -99
- package/internal/wsdl/ids.go +0 -127
- package/internal/wsdl/ids_test.go +0 -21
- package/internal/wsdl/model.go +0 -62
- package/internal/wsdl/parse.go +0 -920
- package/internal/wsdl/parse_test.go +0 -133
- package/plugin/describe.go +0 -107
- package/plugin/describe_test.go +0 -114
- package/plugin/protocol.go +0 -117
- package/plugin/schematest/schematest.go +0 -126
- package/plugins/extract-adr/describe.go +0 -19
- package/plugins/extract-adr/describe_test.go +0 -11
- package/plugins/extract-adr/extract.go +0 -153
- package/plugins/extract-adr/extract_test.go +0 -350
- package/plugins/extract-adr/history.go +0 -99
- package/plugins/extract-adr/main.go +0 -65
- package/plugins/extract-adr/parse.go +0 -642
- package/plugins/extract-adr/parse_test.go +0 -405
- package/plugins/extract-asyncapi/describe.go +0 -19
- package/plugins/extract-asyncapi/describe_test.go +0 -11
- package/plugins/extract-asyncapi/extract.go +0 -315
- package/plugins/extract-asyncapi/extract_test.go +0 -197
- package/plugins/extract-asyncapi/main.go +0 -48
- package/plugins/extract-asyncapi/spec.go +0 -151
- package/plugins/extract-commands/describe.go +0 -19
- package/plugins/extract-commands/describe_test.go +0 -11
- package/plugins/extract-commands/extract.go +0 -79
- package/plugins/extract-commands/extract_test.go +0 -92
- package/plugins/extract-commands/main.go +0 -55
- package/plugins/extract-csr/avro.go +0 -258
- package/plugins/extract-csr/describe.go +0 -19
- package/plugins/extract-csr/describe_test.go +0 -11
- package/plugins/extract-csr/extract.go +0 -338
- package/plugins/extract-csr/extract_test.go +0 -374
- package/plugins/extract-csr/jsonschema.go +0 -343
- package/plugins/extract-csr/lock.go +0 -25
- package/plugins/extract-csr/main.go +0 -84
- package/plugins/extract-csr/subject.go +0 -102
- package/plugins/extract-flows/describe.go +0 -19
- package/plugins/extract-flows/describe_test.go +0 -11
- package/plugins/extract-flows/extract.go +0 -91
- package/plugins/extract-flows/main.go +0 -45
- package/plugins/extract-flows/parse.go +0 -593
- package/plugins/extract-flows/parse_test.go +0 -204
- package/plugins/extract-glossary/describe.go +0 -19
- package/plugins/extract-glossary/describe_test.go +0 -11
- package/plugins/extract-glossary/extract.go +0 -115
- package/plugins/extract-glossary/extract_test.go +0 -220
- package/plugins/extract-glossary/main.go +0 -59
- package/plugins/extract-glossary/parse.go +0 -214
- package/plugins/extract-glossary/parse_test.go +0 -203
- package/plugins/extract-go/aggregate.go +0 -214
- package/plugins/extract-go/client.go +0 -409
- package/plugins/extract-go/client_test.go +0 -266
- package/plugins/extract-go/describe.go +0 -19
- package/plugins/extract-go/describe_test.go +0 -11
- package/plugins/extract-go/enum.go +0 -195
- package/plugins/extract-go/enum_test.go +0 -82
- package/plugins/extract-go/event.go +0 -99
- package/plugins/extract-go/extract.go +0 -191
- package/plugins/extract-go/extract_test.go +0 -261
- package/plugins/extract-go/flow.go +0 -1441
- package/plugins/extract-go/flow_test.go +0 -609
- package/plugins/extract-go/httpclient.go +0 -174
- package/plugins/extract-go/httpclient_test.go +0 -296
- package/plugins/extract-go/ids.go +0 -92
- package/plugins/extract-go/layout.go +0 -225
- package/plugins/extract-go/layout_test.go +0 -125
- package/plugins/extract-go/lifecycle.go +0 -324
- package/plugins/extract-go/lifecycle_test.go +0 -108
- package/plugins/extract-go/main.go +0 -79
- package/plugins/extract-go/operation.go +0 -157
- package/plugins/extract-go/source.go +0 -316
- package/plugins/extract-go/transport.go +0 -321
- package/plugins/extract-go/transport_test.go +0 -145
- package/plugins/extract-go/wiring.go +0 -434
- package/plugins/extract-go-nats/describe.go +0 -19
- package/plugins/extract-go-nats/describe_test.go +0 -11
- package/plugins/extract-go-nats/extract.go +0 -177
- package/plugins/extract-go-nats/extract_test.go +0 -389
- package/plugins/extract-go-nats/index.go +0 -379
- package/plugins/extract-go-nats/main.go +0 -42
- package/plugins/extract-go-nats/resolve.go +0 -161
- package/plugins/extract-go-nats/sites.go +0 -224
- package/plugins/extract-graphql/describe.go +0 -19
- package/plugins/extract-graphql/describe_test.go +0 -11
- package/plugins/extract-graphql/extract.go +0 -433
- package/plugins/extract-graphql/extract_test.go +0 -256
- package/plugins/extract-graphql/ids.go +0 -49
- package/plugins/extract-graphql/lex.go +0 -237
- package/plugins/extract-graphql/main.go +0 -51
- package/plugins/extract-graphql/parse.go +0 -621
- package/plugins/extract-graphql/parse_test.go +0 -122
- package/plugins/extract-http-clients/describe.go +0 -19
- package/plugins/extract-http-clients/describe_test.go +0 -11
- package/plugins/extract-http-clients/extract.go +0 -705
- package/plugins/extract-http-clients/extract_test.go +0 -1263
- package/plugins/extract-http-clients/main.go +0 -42
- package/plugins/extract-openapi/describe.go +0 -19
- package/plugins/extract-openapi/describe_test.go +0 -11
- package/plugins/extract-openapi/discover.go +0 -243
- package/plugins/extract-openapi/extract.go +0 -526
- package/plugins/extract-openapi/extract_test.go +0 -545
- package/plugins/extract-openapi/main.go +0 -75
- package/plugins/extract-openapi/spec.go +0 -350
- package/plugins/extract-project/describe.go +0 -19
- package/plugins/extract-project/describe_test.go +0 -11
- package/plugins/extract-project/extract.go +0 -221
- package/plugins/extract-project/extract_test.go +0 -109
- package/plugins/extract-project/main.go +0 -41
- package/plugins/extract-proto/ast.go +0 -125
- package/plugins/extract-proto/consumes.go +0 -77
- package/plugins/extract-proto/describe.go +0 -19
- package/plugins/extract-proto/extract.go +0 -293
- package/plugins/extract-proto/extract_test.go +0 -459
- package/plugins/extract-proto/ids.go +0 -89
- package/plugins/extract-proto/ids_test.go +0 -57
- package/plugins/extract-proto/lex.go +0 -285
- package/plugins/extract-proto/main.go +0 -100
- package/plugins/extract-proto/module.go +0 -120
- package/plugins/extract-proto/parse.go +0 -720
- package/plugins/extract-proto/parse_test.go +0 -307
- package/plugins/extract-proto/provides.go +0 -236
- package/plugins/extract-proto/resolve.go +0 -222
- package/plugins/extract-proto/resolve_test.go +0 -119
- package/plugins/extract-redis/describe.go +0 -19
- package/plugins/extract-redis/describe_test.go +0 -11
- package/plugins/extract-redis/extract.go +0 -183
- package/plugins/extract-redis/extract_test.go +0 -168
- package/plugins/extract-redis/keyspaces.go +0 -469
- package/plugins/extract-redis/main.go +0 -44
- package/plugins/extract-river/describe.go +0 -19
- package/plugins/extract-river/describe_test.go +0 -11
- package/plugins/extract-river/extract.go +0 -507
- package/plugins/extract-river/extract_test.go +0 -132
- package/plugins/extract-river/main.go +0 -42
- package/plugins/extract-sql/ddl.go +0 -893
- package/plugins/extract-sql/ddl_test.go +0 -401
- package/plugins/extract-sql/describe.go +0 -19
- package/plugins/extract-sql/describe_test.go +0 -11
- package/plugins/extract-sql/layout.go +0 -221
- package/plugins/extract-sql/layout_test.go +0 -55
- package/plugins/extract-sql/lineage.go +0 -107
- package/plugins/extract-sql/main.go +0 -141
- package/plugins/extract-sql/maps.go +0 -564
- package/plugins/extract-sql/maps_java.go +0 -117
- package/plugins/extract-sql/maps_rust.go +0 -333
- package/plugins/extract-sql/maps_rust_test.go +0 -70
- package/plugins/extract-sql/maps_test.go +0 -204
- package/plugins/extract-sql/maps_ts.go +0 -398
- package/plugins/extract-sql/maps_ts_test.go +0 -136
- package/plugins/extract-sql/projection.go +0 -70
- package/plugins/extract-sql/projection_test.go +0 -50
- package/plugins/extract-sql/store.go +0 -420
- package/plugins/extract-sql/store_test.go +0 -233
- package/plugins/extract-sql/view.go +0 -295
- package/plugins/extract-watermill/describe.go +0 -19
- package/plugins/extract-watermill/describe_test.go +0 -11
- package/plugins/extract-watermill/extract.go +0 -1228
- package/plugins/extract-watermill/extract_test.go +0 -234
- package/plugins/extract-watermill/main.go +0 -41
- package/plugins/extract-wsdl/describe.go +0 -19
- package/plugins/extract-wsdl/describe_test.go +0 -11
- package/plugins/extract-wsdl/extract.go +0 -148
- package/plugins/extract-wsdl/extract_test.go +0 -45
- package/plugins/extract-wsdl/main.go +0 -53
- package/plugins/fetch-bsr/auth.go +0 -114
- package/plugins/fetch-bsr/bsr.go +0 -240
- package/plugins/fetch-bsr/cache.go +0 -66
- package/plugins/fetch-bsr/describe.go +0 -19
- package/plugins/fetch-bsr/fetch.go +0 -192
- package/plugins/fetch-bsr/fetch_test.go +0 -465
- package/plugins/fetch-bsr/lock.go +0 -71
- package/plugins/fetch-bsr/main.go +0 -117
- package/plugins/fetch-csr/auth.go +0 -95
- package/plugins/fetch-csr/cache.go +0 -69
- package/plugins/fetch-csr/describe.go +0 -19
- package/plugins/fetch-csr/describe_test.go +0 -11
- package/plugins/fetch-csr/fetch.go +0 -254
- package/plugins/fetch-csr/fetch_test.go +0 -494
- package/plugins/fetch-csr/lock.go +0 -95
- package/plugins/fetch-csr/main.go +0 -122
- package/plugins/fetch-csr/registry.go +0 -209
- package/plugins/fetch-git/cache.go +0 -65
- package/plugins/fetch-git/describe.go +0 -19
- package/plugins/fetch-git/describe_test.go +0 -11
- package/plugins/fetch-git/fetch.go +0 -181
- package/plugins/fetch-git/fetch_test.go +0 -332
- package/plugins/fetch-git/git.go +0 -169
- package/plugins/fetch-git/lock.go +0 -72
- package/plugins/fetch-git/main.go +0 -127
- package/plugins/fetch-git/offline.go +0 -39
- package/plugins/fetch-git/pin.go +0 -90
- package/plugins/fetch-git/pin_test.go +0 -74
- package/plugins/gen-backstage/describe.go +0 -17
- package/plugins/gen-backstage/main.go +0 -22
- package/plugins/gen-backstage/plugin.go +0 -473
- package/plugins/gen-backstage/plugin_test.go +0 -145
- package/plugins/gen-backstage.wasm +0 -0
- package/plugins/gen-markdown/adr.go +0 -162
- package/plugins/gen-markdown/aggregate.go +0 -362
- package/plugins/gen-markdown/canonical.go +0 -93
- package/plugins/gen-markdown/context.go +0 -90
- package/plugins/gen-markdown/coverage_test.go +0 -89
- package/plugins/gen-markdown/describe.go +0 -19
- package/plugins/gen-markdown/describe_test.go +0 -11
- package/plugins/gen-markdown/external.go +0 -71
- package/plugins/gen-markdown/flow.go +0 -277
- package/plugins/gen-markdown/glossary.go +0 -76
- package/plugins/gen-markdown/glossary_test.go +0 -148
- package/plugins/gen-markdown/llms.go +0 -302
- package/plugins/gen-markdown/main.go +0 -22
- package/plugins/gen-markdown/markdown.go +0 -254
- package/plugins/gen-markdown/markdown_test.go +0 -100
- package/plugins/gen-markdown/module.go +0 -107
- package/plugins/gen-markdown/plugin.go +0 -39
- package/plugins/gen-markdown/quality_test.go +0 -176
- package/plugins/gen-markdown/redis_test.go +0 -38
- package/plugins/gen-markdown/render.go +0 -344
- package/plugins/gen-markdown/render_test.go +0 -186
- package/plugins/gen-markdown/service.go +0 -456
- package/plugins/gen-markdown/source.go +0 -177
- package/plugins/gen-markdown/store.go +0 -201
- package/plugins/gen-markdown.wasm +0 -0
- package/plugins/gen-mermaid/describe.go +0 -17
- package/plugins/gen-mermaid/main.go +0 -22
- package/plugins/gen-mermaid/plugin.go +0 -104
- package/plugins/gen-mermaid/plugin_test.go +0 -33
- package/plugins/gen-mermaid.wasm +0 -0
- package/plugins/openapi/ids.go +0 -261
- package/plugins/openapi/ids_test.go +0 -98
- package/plugins/verify-codeowners/describe.go +0 -19
- package/plugins/verify-codeowners/describe_test.go +0 -11
- package/plugins/verify-codeowners/main.go +0 -75
- package/plugins/verify-codeowners/match.go +0 -85
- package/plugins/verify-codeowners/match_test.go +0 -47
- package/plugins/verify-codeowners/owners.go +0 -164
- package/plugins/verify-codeowners/owners_test.go +0 -225
- package/plugins/verify-codeowners/parse.go +0 -90
- package/plugins/verify-codeowners/parse_test.go +0 -62
- package/plugins/verify-otel/describe.go +0 -19
- package/plugins/verify-otel/describe_test.go +0 -11
- package/plugins/verify-otel/main.go +0 -53
- package/plugins/verify-otel/match.go +0 -336
- package/plugins/verify-otel/otlp.go +0 -200
- package/plugins/verify-otel/verify.go +0 -734
- package/plugins/verify-otel/verify_test.go +0 -460
- /package/{plugins/fetch-csr/options.schema.json → scripts/host-plugins/fetch-csr.options.json} +0 -0
- /package/{plugins/fetch-git/options.schema.json → scripts/host-plugins/fetch-git.options.json} +0 -0
|
@@ -1,222 +0,0 @@
|
|
|
1
|
-
package main
|
|
2
|
-
|
|
3
|
-
// Turning a name as written into the thing it names.
|
|
4
|
-
//
|
|
5
|
-
// A proto reference is relative to where it was written: `Money` inside
|
|
6
|
-
// `shop.v1.Order` might mean `shop.v1.Order.Money`, `shop.v1.Money`, or
|
|
7
|
-
// `Money` at the root, and proto searches outwards in that order. A leading dot
|
|
8
|
-
// means the search is skipped and the name is already absolute.
|
|
9
|
-
//
|
|
10
|
-
// A name that resolves to nothing is NOT an error here. A narrowed vendored
|
|
11
|
-
// copy importing a file nobody vendored beside it is the normal case - see the
|
|
12
|
-
// header of parse.go - and the answer is to say the type is unresolved and
|
|
13
|
-
// carry on, not to refuse to describe the file.
|
|
14
|
-
|
|
15
|
-
import (
|
|
16
|
-
"sort"
|
|
17
|
-
"strings"
|
|
18
|
-
)
|
|
19
|
-
|
|
20
|
-
// scalars are proto's built-in types, which never resolve to a declaration.
|
|
21
|
-
var scalars = map[string]bool{
|
|
22
|
-
"double": true, "float": true, "int32": true, "int64": true,
|
|
23
|
-
"uint32": true, "uint64": true, "sint32": true, "sint64": true,
|
|
24
|
-
"fixed32": true, "fixed64": true, "sfixed32": true, "sfixed64": true,
|
|
25
|
-
"bool": true, "string": true, "bytes": true,
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
func isScalar(name string) bool { return scalars[name] }
|
|
29
|
-
|
|
30
|
-
// Index is every declaration in a set of files, by fully-qualified name.
|
|
31
|
-
type Index struct {
|
|
32
|
-
files []*File
|
|
33
|
-
|
|
34
|
-
messages map[string]*Message
|
|
35
|
-
enums map[string]*Enum
|
|
36
|
-
fileOf map[string]*File
|
|
37
|
-
fqnOf map[*Message]string
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
// NewIndex walks the files once and records every message and enum in them,
|
|
41
|
-
// nested ones included, under the name the rest of the world would use.
|
|
42
|
-
func NewIndex(files []*File) *Index {
|
|
43
|
-
ix := &Index{
|
|
44
|
-
files: files,
|
|
45
|
-
messages: map[string]*Message{},
|
|
46
|
-
enums: map[string]*Enum{},
|
|
47
|
-
fileOf: map[string]*File{},
|
|
48
|
-
fqnOf: map[*Message]string{},
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
for _, file := range files {
|
|
52
|
-
for _, m := range file.Messages {
|
|
53
|
-
ix.addMessage(file, file.Package, m)
|
|
54
|
-
}
|
|
55
|
-
for _, e := range file.Enums {
|
|
56
|
-
ix.addEnum(file, join(file.Package, e.Name), e)
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
return ix
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
func (ix *Index) addMessage(file *File, scope string, m *Message) {
|
|
64
|
-
fqn := join(scope, m.Name)
|
|
65
|
-
ix.messages[fqn] = m
|
|
66
|
-
ix.fileOf[fqn] = file
|
|
67
|
-
ix.fqnOf[m] = fqn
|
|
68
|
-
|
|
69
|
-
for _, nested := range m.Messages {
|
|
70
|
-
ix.addMessage(file, fqn, nested)
|
|
71
|
-
}
|
|
72
|
-
for _, e := range m.Enums {
|
|
73
|
-
ix.addEnum(file, join(fqn, e.Name), e)
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
func (ix *Index) addEnum(file *File, fqn string, e *Enum) {
|
|
78
|
-
ix.enums[fqn] = e
|
|
79
|
-
ix.fileOf[fqn] = file
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
// Resolve finds what `name`, written inside `scope`, refers to.
|
|
83
|
-
//
|
|
84
|
-
// scope is a fully-qualified name - a package, or a message inside one. The
|
|
85
|
-
// search walks outwards from it, which is what proto itself does.
|
|
86
|
-
func (ix *Index) Resolve(scope, name string) (string, bool) {
|
|
87
|
-
if name == "" || isScalar(name) {
|
|
88
|
-
return "", false
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
if strings.HasPrefix(name, ".") {
|
|
92
|
-
fqn := strings.TrimPrefix(name, ".")
|
|
93
|
-
|
|
94
|
-
return fqn, ix.declared(fqn)
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
parts := strings.Split(scope, ".")
|
|
98
|
-
for i := len(parts); i >= 0; i-- {
|
|
99
|
-
fqn := join(strings.Join(parts[:i], "."), name)
|
|
100
|
-
if ix.declared(fqn) {
|
|
101
|
-
return fqn, true
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
return "", false
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
func (ix *Index) declared(fqn string) bool {
|
|
109
|
-
_, message := ix.messages[fqn]
|
|
110
|
-
_, enum := ix.enums[fqn]
|
|
111
|
-
|
|
112
|
-
return message || enum
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
func (ix *Index) Message(fqn string) *Message { return ix.messages[fqn] }
|
|
116
|
-
func (ix *Index) Enum(fqn string) *Enum { return ix.enums[fqn] }
|
|
117
|
-
func (ix *Index) FileOf(fqn string) *File { return ix.fileOf[fqn] }
|
|
118
|
-
|
|
119
|
-
// FQN is the name a message is known by, once it has been indexed.
|
|
120
|
-
func (ix *Index) FQN(m *Message) string { return ix.fqnOf[m] }
|
|
121
|
-
|
|
122
|
-
// Names is every declared name, sorted. Determinism is not a nicety here: the
|
|
123
|
-
// fragment these end up in is committed and compared by `gen:check`, so a map
|
|
124
|
-
// iterated in Go's order would produce a different file every run.
|
|
125
|
-
func (ix *Index) Names() []string {
|
|
126
|
-
out := make([]string, 0, len(ix.messages)+len(ix.enums))
|
|
127
|
-
for fqn := range ix.messages {
|
|
128
|
-
out = append(out, fqn)
|
|
129
|
-
}
|
|
130
|
-
for fqn := range ix.enums {
|
|
131
|
-
out = append(out, fqn)
|
|
132
|
-
}
|
|
133
|
-
sort.Strings(out)
|
|
134
|
-
|
|
135
|
-
return out
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
// TypeRef is one field's type, resolved as far as it could be.
|
|
139
|
-
type TypeRef struct {
|
|
140
|
-
// Written is the type as the author typed it, rendered the way the catalog
|
|
141
|
-
// renders types: `[]LineItem`, `map[string]Money`, `Money`.
|
|
142
|
-
Written string
|
|
143
|
-
|
|
144
|
-
// FQN is what the named type resolves to, empty for a scalar or for a name
|
|
145
|
-
// nothing in the tree declares.
|
|
146
|
-
FQN string
|
|
147
|
-
|
|
148
|
-
// Unresolved is the name that could not be found, empty when there was
|
|
149
|
-
// nothing to find or the search succeeded. It is a diagnostic, not a
|
|
150
|
-
// failure: a narrowed vendored copy is expected to have some.
|
|
151
|
-
Unresolved string
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
// resolveType renders a field's type and resolves the name inside it.
|
|
155
|
-
//
|
|
156
|
-
// A map is rendered `map[K]V` and resolved on its value: the key of a proto map
|
|
157
|
-
// is always a scalar, and the value is the half that can name a message.
|
|
158
|
-
func (ix *Index) resolveType(scope string, f *Field) TypeRef {
|
|
159
|
-
if key, value, ok := mapParts(f.Type); ok {
|
|
160
|
-
inner := ix.resolveType(scope, &Field{Type: value})
|
|
161
|
-
|
|
162
|
-
return TypeRef{
|
|
163
|
-
Written: "map[" + key + "]" + inner.Written,
|
|
164
|
-
FQN: inner.FQN,
|
|
165
|
-
Unresolved: inner.Unresolved,
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
ref := TypeRef{Written: shortName(f.Type)}
|
|
170
|
-
if f.Label == "repeated" {
|
|
171
|
-
ref.Written = "[]" + ref.Written
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
if isScalar(f.Type) {
|
|
175
|
-
return ref
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
if fqn, ok := ix.Resolve(scope, f.Type); ok {
|
|
179
|
-
ref.FQN = fqn
|
|
180
|
-
} else {
|
|
181
|
-
ref.Unresolved = f.Type
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
return ref
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
// mapParts splits `map<string, Money>` into its two arguments.
|
|
188
|
-
func mapParts(typ string) (string, string, bool) {
|
|
189
|
-
if !strings.HasPrefix(typ, "map<") || !strings.HasSuffix(typ, ">") {
|
|
190
|
-
return "", "", false
|
|
191
|
-
}
|
|
192
|
-
inner := typ[len("map<") : len(typ)-1]
|
|
193
|
-
comma := strings.Index(inner, ",")
|
|
194
|
-
if comma < 0 {
|
|
195
|
-
return "", "", false
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
return strings.TrimSpace(inner[:comma]), strings.TrimSpace(inner[comma+1:]), true
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
// shortName is the last segment of a dotted name.
|
|
202
|
-
//
|
|
203
|
-
// The catalog spells a type the way a reader says it - `Money`, not
|
|
204
|
-
// `shop.v1.Money` - and its `defs` keys are deliberately bare for the same
|
|
205
|
-
// reason: two sources meaning different things by `Money` should collide
|
|
206
|
-
// visibly rather than coexist as two quietly different entries.
|
|
207
|
-
func shortName(name string) string {
|
|
208
|
-
name = strings.TrimPrefix(name, ".")
|
|
209
|
-
if i := strings.LastIndex(name, "."); i >= 0 {
|
|
210
|
-
return name[i+1:]
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
return name
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
func join(scope, name string) string {
|
|
217
|
-
if scope == "" {
|
|
218
|
-
return name
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
return scope + "." + name
|
|
222
|
-
}
|
|
@@ -1,119 +0,0 @@
|
|
|
1
|
-
package main
|
|
2
|
-
|
|
3
|
-
// Name resolution, on its own. A proto reference means whatever the innermost
|
|
4
|
-
// enclosing scope that declares it means, and a name nothing declares is a
|
|
5
|
-
// diagnostic rather than a failure.
|
|
6
|
-
|
|
7
|
-
import "testing"
|
|
8
|
-
|
|
9
|
-
func indexed(t *testing.T) *Index {
|
|
10
|
-
t.Helper()
|
|
11
|
-
|
|
12
|
-
orders, _ := parseFile(t, "orders.proto")
|
|
13
|
-
money, _ := parseFile(t, "money.proto")
|
|
14
|
-
|
|
15
|
-
return NewIndex([]*File{orders, money})
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
func TestResolvesAcrossFiles(t *testing.T) {
|
|
19
|
-
ix := indexed(t)
|
|
20
|
-
|
|
21
|
-
fqn, ok := ix.Resolve("shop.v1", "Money")
|
|
22
|
-
if !ok || fqn != "shop.v1.Money" {
|
|
23
|
-
t.Errorf("Money from shop.v1: %q %v", fqn, ok)
|
|
24
|
-
}
|
|
25
|
-
if ix.Message(fqn) == nil {
|
|
26
|
-
t.Error("the resolved name does not lead back to the message")
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
// Proto searches outwards from where the name was written, so the nested type
|
|
31
|
-
// wins over anything of the same name further out.
|
|
32
|
-
func TestResolvesInnermostFirst(t *testing.T) {
|
|
33
|
-
ix := indexed(t)
|
|
34
|
-
|
|
35
|
-
fqn, ok := ix.Resolve("shop.v1.Order", "Address")
|
|
36
|
-
if !ok || fqn != "shop.v1.Order.Address" {
|
|
37
|
-
t.Errorf("Address from inside Order: %q %v", fqn, ok)
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
// The same name written one scope out finds nothing, which is the point.
|
|
41
|
-
if _, ok := ix.Resolve("shop.v1", "Address"); ok {
|
|
42
|
-
t.Error("a nested type resolved from outside the message that nests it")
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
func TestLeadingDotIsAbsolute(t *testing.T) {
|
|
47
|
-
ix := indexed(t)
|
|
48
|
-
|
|
49
|
-
fqn, ok := ix.Resolve("shop.v1.Order", ".shop.v1.Money")
|
|
50
|
-
if !ok || fqn != "shop.v1.Money" {
|
|
51
|
-
t.Errorf("absolute name: %q %v", fqn, ok)
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
func TestNestedEnumIsIndexed(t *testing.T) {
|
|
56
|
-
ix := indexed(t)
|
|
57
|
-
|
|
58
|
-
fqn, ok := ix.Resolve("shop.v1.Order", "Channel")
|
|
59
|
-
if !ok || fqn != "shop.v1.Order.Channel" {
|
|
60
|
-
t.Errorf("nested enum: %q %v", fqn, ok)
|
|
61
|
-
}
|
|
62
|
-
if ix.Enum(fqn) == nil {
|
|
63
|
-
t.Error("the resolved name does not lead back to the enum")
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
// The whole reason this parser is tolerant: a narrowed vendored copy imports
|
|
68
|
-
// files nobody vendored beside it, and it must still be describable.
|
|
69
|
-
func TestUnresolvedIsReportedNotFatal(t *testing.T) {
|
|
70
|
-
ix := indexed(t)
|
|
71
|
-
|
|
72
|
-
ref := ix.resolveType("shop.v1", &Field{Type: "Nowhere"})
|
|
73
|
-
if ref.Unresolved != "Nowhere" {
|
|
74
|
-
t.Errorf("an unknown type was not reported: %+v", ref)
|
|
75
|
-
}
|
|
76
|
-
if ref.Written != "Nowhere" {
|
|
77
|
-
t.Errorf("an unknown type must still be shown as written: %q", ref.Written)
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
// Types are rendered the way the catalog renders types, and resolved on the
|
|
82
|
-
// half that can name a message.
|
|
83
|
-
func TestTypeRendering(t *testing.T) {
|
|
84
|
-
ix := indexed(t)
|
|
85
|
-
|
|
86
|
-
cases := []struct {
|
|
87
|
-
field Field
|
|
88
|
-
written, fqn string
|
|
89
|
-
}{
|
|
90
|
-
{Field{Type: "string"}, "string", ""},
|
|
91
|
-
{Field{Type: "Money"}, "Money", "shop.v1.Money"},
|
|
92
|
-
{Field{Type: "shop.v1.Money"}, "Money", "shop.v1.Money"},
|
|
93
|
-
{Field{Type: "LineItem", Label: "repeated"}, "[]LineItem", "shop.v1.LineItem"},
|
|
94
|
-
{Field{Type: "map<string, string>"}, "map[string]string", ""},
|
|
95
|
-
{Field{Type: "map<string, Money>"}, "map[string]Money", "shop.v1.Money"},
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
for _, c := range cases {
|
|
99
|
-
got := ix.resolveType("shop.v1", &c.field)
|
|
100
|
-
if got.Written != c.written || got.FQN != c.fqn {
|
|
101
|
-
t.Errorf("%s: %q -> %q (want %q -> %q)", c.field.Type, got.Written, got.FQN, c.written, c.fqn)
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
// The fragment is committed and compared by gen:check, so anything derived from
|
|
107
|
-
// a map has to come out in the same order every run.
|
|
108
|
-
func TestNamesAreSorted(t *testing.T) {
|
|
109
|
-
names := indexed(t).Names()
|
|
110
|
-
|
|
111
|
-
for i := 1; i < len(names); i++ {
|
|
112
|
-
if names[i-1] > names[i] {
|
|
113
|
-
t.Fatalf("names are not sorted: %q before %q", names[i-1], names[i])
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
if len(names) == 0 {
|
|
117
|
-
t.Fatal("nothing was indexed")
|
|
118
|
-
}
|
|
119
|
-
}
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
package main
|
|
2
|
-
|
|
3
|
-
import (
|
|
4
|
-
_ "embed"
|
|
5
|
-
|
|
6
|
-
"github.com/shortlink-org/portolan/plugin"
|
|
7
|
-
)
|
|
8
|
-
|
|
9
|
-
//go:embed options.schema.json
|
|
10
|
-
var optionsSchema []byte
|
|
11
|
-
|
|
12
|
-
func descriptor() plugin.Descriptor {
|
|
13
|
-
return plugin.Descriptor{
|
|
14
|
-
Name: "extract-redis",
|
|
15
|
-
Summary: "Finds runtime construction of supported Go Redis clients and adds the service-owned Redis store to the catalog.",
|
|
16
|
-
Phases: []string{plugin.PhaseExtract},
|
|
17
|
-
Options: optionsSchema,
|
|
18
|
-
}
|
|
19
|
-
}
|
|
@@ -1,183 +0,0 @@
|
|
|
1
|
-
package main
|
|
2
|
-
|
|
3
|
-
import (
|
|
4
|
-
"encoding/json"
|
|
5
|
-
"go/ast"
|
|
6
|
-
"strconv"
|
|
7
|
-
"strings"
|
|
8
|
-
|
|
9
|
-
"github.com/shortlink-org/portolan/catalog"
|
|
10
|
-
"github.com/shortlink-org/portolan/internal/goscan"
|
|
11
|
-
"github.com/shortlink-org/portolan/plugin"
|
|
12
|
-
)
|
|
13
|
-
|
|
14
|
-
type redisConstruction struct {
|
|
15
|
-
at goscan.Source
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
func extract(in plugin.Input, opts Options) (plugin.Response, error) {
|
|
19
|
-
b := &plugin.Builder{}
|
|
20
|
-
tree, err := goscan.Read(in.Root)
|
|
21
|
-
if err != nil {
|
|
22
|
-
return plugin.Response{}, err
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
owner := opts.Context + "." + opts.Service
|
|
26
|
-
service := catalog.Service{
|
|
27
|
-
ID: owner,
|
|
28
|
-
Slug: opts.Service,
|
|
29
|
-
Provides: []catalog.RpcService{},
|
|
30
|
-
Consumes: []catalog.RpcCall{},
|
|
31
|
-
Aggregates: []catalog.Aggregate{},
|
|
32
|
-
}
|
|
33
|
-
stores := []catalog.Store{}
|
|
34
|
-
if found := findRedisConstruction(tree); found != nil {
|
|
35
|
-
keyspaces := scanRedisKeyspaces(tree)
|
|
36
|
-
storeSlug := firstNonEmpty(opts.Store, "redis")
|
|
37
|
-
storeID := owner + "." + storeSlug
|
|
38
|
-
service.Stores = []string{storeID}
|
|
39
|
-
stores = append(stores, catalog.Store{
|
|
40
|
-
ID: storeID,
|
|
41
|
-
Slug: storeSlug,
|
|
42
|
-
Name: firstNonEmpty(opts.Name, opts.Service+" Redis"),
|
|
43
|
-
Kind: catalog.StoreKindRedis,
|
|
44
|
-
Owner: owner,
|
|
45
|
-
Tables: []catalog.Table{},
|
|
46
|
-
Keyspaces: keyspaces,
|
|
47
|
-
Source: found.at.String(),
|
|
48
|
-
})
|
|
49
|
-
} else {
|
|
50
|
-
b.Warn(owner, "no supported Redis client construction was found in non-test Go source")
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
fragment := catalog.Catalog{
|
|
54
|
-
GeneratedAt: in.GeneratedAt,
|
|
55
|
-
Commit: in.Commit,
|
|
56
|
-
Contexts: []catalog.BoundedContext{{
|
|
57
|
-
ID: opts.Context,
|
|
58
|
-
Slug: opts.Context,
|
|
59
|
-
Services: []catalog.Service{service},
|
|
60
|
-
}},
|
|
61
|
-
Defs: map[string]catalog.TypeDef{},
|
|
62
|
-
Flows: []catalog.Flow{},
|
|
63
|
-
Adrs: []catalog.Adr{},
|
|
64
|
-
Stores: stores,
|
|
65
|
-
}
|
|
66
|
-
encoded, err := json.MarshalIndent(fragment, "", " ")
|
|
67
|
-
if err != nil {
|
|
68
|
-
return plugin.Response{}, err
|
|
69
|
-
}
|
|
70
|
-
b.File(firstNonEmpty(opts.Out, "redis.json"), string(encoded)+"\n")
|
|
71
|
-
|
|
72
|
-
return b.Response(), nil
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
func findRedisConstruction(tree *goscan.Tree) *redisConstruction {
|
|
76
|
-
for _, file := range tree.Files {
|
|
77
|
-
var found *redisConstruction
|
|
78
|
-
ast.Inspect(file.Node, func(node ast.Node) bool {
|
|
79
|
-
if found != nil {
|
|
80
|
-
return false
|
|
81
|
-
}
|
|
82
|
-
call, ok := node.(*ast.CallExpr)
|
|
83
|
-
if !ok {
|
|
84
|
-
return true
|
|
85
|
-
}
|
|
86
|
-
sel, ok := call.Fun.(*ast.SelectorExpr)
|
|
87
|
-
if !ok {
|
|
88
|
-
return true
|
|
89
|
-
}
|
|
90
|
-
pkg, ok := sel.X.(*ast.Ident)
|
|
91
|
-
if !ok {
|
|
92
|
-
return true
|
|
93
|
-
}
|
|
94
|
-
importPath := redisImportPath(file, pkg.Name)
|
|
95
|
-
if !isRedisConstructor(importPath, sel.Sel.Name) {
|
|
96
|
-
return true
|
|
97
|
-
}
|
|
98
|
-
found = &redisConstruction{at: tree.At(call.Pos())}
|
|
99
|
-
return false
|
|
100
|
-
})
|
|
101
|
-
if found != nil {
|
|
102
|
-
return found
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
return nil
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
// Versioned Go module paths end in v8/v9, while the packages still call
|
|
110
|
-
// themselves redis. goscan cannot infer an external package clause from the
|
|
111
|
-
// import path, so fill in the stable package names of the clients understood
|
|
112
|
-
// by this extractor. Explicit aliases are already present in file.Imports.
|
|
113
|
-
func redisImportPath(file *goscan.File, packageName string) string {
|
|
114
|
-
for _, spec := range file.Node.Imports {
|
|
115
|
-
importPath, err := strconv.Unquote(spec.Path.Value)
|
|
116
|
-
if err != nil || !isRedisClientImport(importPath) {
|
|
117
|
-
continue
|
|
118
|
-
}
|
|
119
|
-
if spec.Name != nil {
|
|
120
|
-
if spec.Name.Name == packageName {
|
|
121
|
-
return importPath
|
|
122
|
-
}
|
|
123
|
-
continue
|
|
124
|
-
}
|
|
125
|
-
if packageName == defaultRedisPackage(importPath) {
|
|
126
|
-
return importPath
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
return ""
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
func isRedisConstructor(importPath, name string) bool {
|
|
133
|
-
switch {
|
|
134
|
-
case isGoRedisImport(importPath):
|
|
135
|
-
switch name {
|
|
136
|
-
case "NewClient", "NewClusterClient", "NewFailoverClient", "NewFailoverClusterClient":
|
|
137
|
-
return true
|
|
138
|
-
}
|
|
139
|
-
case importPath == "github.com/redis/rueidis" || strings.HasPrefix(importPath, "github.com/redis/rueidis/"):
|
|
140
|
-
return name == "NewClient"
|
|
141
|
-
case importPath == "github.com/gomodule/redigo/redis":
|
|
142
|
-
return name == "Dial" || name == "DialURL"
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
return false
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
func isRedisClientImport(importPath string) bool {
|
|
149
|
-
return isGoRedisImport(importPath) || importPath == "github.com/redis/rueidis" ||
|
|
150
|
-
strings.HasPrefix(importPath, "github.com/redis/rueidis/") || importPath == "github.com/gomodule/redigo/redis"
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
func isGoRedisImport(importPath string) bool {
|
|
154
|
-
for _, base := range []string{"github.com/redis/go-redis", "github.com/go-redis/redis"} {
|
|
155
|
-
if importPath == base {
|
|
156
|
-
return true
|
|
157
|
-
}
|
|
158
|
-
version, ok := strings.CutPrefix(importPath, base+"/v")
|
|
159
|
-
if !ok || version == "" {
|
|
160
|
-
continue
|
|
161
|
-
}
|
|
162
|
-
if _, err := strconv.Atoi(version); err == nil {
|
|
163
|
-
return true
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
return false
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
func defaultRedisPackage(importPath string) string {
|
|
170
|
-
if importPath == "github.com/redis/rueidis" || strings.HasPrefix(importPath, "github.com/redis/rueidis/") {
|
|
171
|
-
return "rueidis"
|
|
172
|
-
}
|
|
173
|
-
return "redis"
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
func firstNonEmpty(values ...string) string {
|
|
177
|
-
for _, value := range values {
|
|
178
|
-
if value != "" {
|
|
179
|
-
return value
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
return ""
|
|
183
|
-
}
|