@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,177 +0,0 @@
|
|
|
1
|
-
package main
|
|
2
|
-
|
|
3
|
-
import (
|
|
4
|
-
"net/url"
|
|
5
|
-
"path"
|
|
6
|
-
"regexp"
|
|
7
|
-
"strings"
|
|
8
|
-
"unicode"
|
|
9
|
-
|
|
10
|
-
"github.com/shortlink-org/portolan/catalog"
|
|
11
|
-
)
|
|
12
|
-
|
|
13
|
-
var sourceLine = regexp.MustCompile(`^(.+):(\d+)$`)
|
|
14
|
-
|
|
15
|
-
// source renders a catalog location as a forge link when the generator has a
|
|
16
|
-
// stable source base, or an immutable pin for an external repository.
|
|
17
|
-
func (s *site) source(from, where string, owner *catalog.Service) string {
|
|
18
|
-
if where == "" {
|
|
19
|
-
return ""
|
|
20
|
-
}
|
|
21
|
-
label := code(where)
|
|
22
|
-
file, line := where, ""
|
|
23
|
-
if match := sourceLine.FindStringSubmatch(where); len(match) == 3 {
|
|
24
|
-
file, line = match[1], match[2]
|
|
25
|
-
}
|
|
26
|
-
if strings.ContainsAny(file, " \t\n") || strings.HasPrefix(file, "/") {
|
|
27
|
-
return label
|
|
28
|
-
}
|
|
29
|
-
directory := strings.HasSuffix(file, "/")
|
|
30
|
-
|
|
31
|
-
prefix, ok := s.sourcePrefix(owner, directory)
|
|
32
|
-
if !ok {
|
|
33
|
-
return label
|
|
34
|
-
}
|
|
35
|
-
if owner != nil && owner.Path != "" && !strings.HasPrefix(file, owner.Path+"/") && file != owner.Path {
|
|
36
|
-
file = path.Join(owner.Path, file)
|
|
37
|
-
}
|
|
38
|
-
file = remotePath(file, owner)
|
|
39
|
-
if file == "." || file == "" {
|
|
40
|
-
return label
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
file = strings.TrimSuffix(file, "/")
|
|
44
|
-
href := strings.TrimSuffix(prefix, "/") + "/" + escapePath(file)
|
|
45
|
-
if line != "" {
|
|
46
|
-
href += "#L" + line
|
|
47
|
-
}
|
|
48
|
-
return "[" + label + "](" + href + ")"
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
func (s *site) serviceForSource(where string) *catalog.Service {
|
|
52
|
-
file := sourceFile(where)
|
|
53
|
-
var best *catalog.Service
|
|
54
|
-
for _, svc := range s.services {
|
|
55
|
-
if svc.Path != "" && (file == svc.Path || strings.HasPrefix(file, svc.Path+"/")) &&
|
|
56
|
-
(best == nil || len(svc.Path) > len(best.Path)) {
|
|
57
|
-
best = svc
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
return best
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
func (s *site) sourcePrefix(owner *catalog.Service, directory bool) (string, bool) {
|
|
64
|
-
wanted := ""
|
|
65
|
-
if owner != nil {
|
|
66
|
-
wanted = bareRepo(owner.Repo)
|
|
67
|
-
}
|
|
68
|
-
for i := range s.cat.Repos {
|
|
69
|
-
pin := &s.cat.Repos[i]
|
|
70
|
-
if pin.Commit != "" && bareRepo(pin.Repo) == wanted {
|
|
71
|
-
view := "/blob/"
|
|
72
|
-
if directory {
|
|
73
|
-
view = "/tree/"
|
|
74
|
-
}
|
|
75
|
-
repo := "https://" + bareRepo(pin.Repo)
|
|
76
|
-
if strings.Contains(strings.ToLower(repo), "gitlab") {
|
|
77
|
-
view = "/-/" + strings.Trim(view, "/") + "/"
|
|
78
|
-
}
|
|
79
|
-
return repo + view + url.PathEscape(pin.Commit), true
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
base := strings.TrimSuffix(s.opts.SourceBaseURL, "/")
|
|
83
|
-
if base == "" || (wanted != "" && sourceBaseRepo(base) != wanted) {
|
|
84
|
-
return "", false
|
|
85
|
-
}
|
|
86
|
-
if directory {
|
|
87
|
-
base = strings.Replace(base, "/-/blob/", "/-/tree/", 1)
|
|
88
|
-
base = strings.Replace(base, "/blob/", "/tree/", 1)
|
|
89
|
-
}
|
|
90
|
-
return base, true
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
func sourceBaseRepo(base string) string {
|
|
94
|
-
for _, marker := range []string{"/-/blob/", "/-/tree/", "/blob/", "/tree/"} {
|
|
95
|
-
if at := strings.Index(base, marker); at >= 0 {
|
|
96
|
-
return bareRepo(base[:at])
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
return bareRepo(base)
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
func bareRepo(value string) string {
|
|
103
|
-
return strings.ToLower(strings.TrimSuffix(strings.TrimSuffix(strings.TrimPrefix(strings.TrimPrefix(value, "https://"), "http://"), "/"), ".git"))
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
func repoLink(repo string) string {
|
|
107
|
-
if repo == "" {
|
|
108
|
-
return ""
|
|
109
|
-
}
|
|
110
|
-
href := repo
|
|
111
|
-
if !strings.Contains(repo, "://") {
|
|
112
|
-
href = "https://" + repo
|
|
113
|
-
}
|
|
114
|
-
return "[" + code(repo) + "](" + strings.TrimSuffix(href, ".git") + ")"
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
func remotePath(file string, owner *catalog.Service) string {
|
|
118
|
-
if owner == nil || owner.Repo == "" {
|
|
119
|
-
return file
|
|
120
|
-
}
|
|
121
|
-
parts := strings.Split(bareRepo(owner.Repo), "/")
|
|
122
|
-
if len(parts) < 3 {
|
|
123
|
-
return file
|
|
124
|
-
}
|
|
125
|
-
prefix := "vendor/repos/" + parts[len(parts)-2] + "/" + parts[len(parts)-1] + "/"
|
|
126
|
-
return strings.TrimPrefix(file, prefix)
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
func escapePath(value string) string {
|
|
130
|
-
parts := strings.Split(value, "/")
|
|
131
|
-
for i := range parts {
|
|
132
|
-
parts[i] = url.PathEscape(parts[i])
|
|
133
|
-
}
|
|
134
|
-
return strings.Join(parts, "/")
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
// anchorID is independent of a renderer's heading-slug algorithm. Explicit
|
|
138
|
-
// anchors keep deep links stable when a title changes punctuation or case.
|
|
139
|
-
func anchorID(value string) string {
|
|
140
|
-
var b strings.Builder
|
|
141
|
-
dash := false
|
|
142
|
-
for _, r := range strings.ToLower(value) {
|
|
143
|
-
switch {
|
|
144
|
-
case unicode.IsLetter(r), unicode.IsDigit(r):
|
|
145
|
-
b.WriteRune(r)
|
|
146
|
-
dash = false
|
|
147
|
-
case b.Len() > 0 && !dash:
|
|
148
|
-
b.WriteByte('-')
|
|
149
|
-
dash = true
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
return strings.Trim(b.String(), "-")
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
func (s *site) eventRef(from, eventID, text string) string {
|
|
156
|
-
pageID := s.eventPage[eventID]
|
|
157
|
-
page, ok := s.pathOf[pageID]
|
|
158
|
-
if !ok {
|
|
159
|
-
return code(text)
|
|
160
|
-
}
|
|
161
|
-
return "[" + code(text) + "](" + rel(from, page) + "#event-" + anchorID(eventID) + ")"
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
func (s *site) viaRef(from string, via *catalog.EdgeVia) string {
|
|
165
|
-
if via == nil || via.Flow == "" {
|
|
166
|
-
return ""
|
|
167
|
-
}
|
|
168
|
-
page, ok := s.pathOf[via.Flow]
|
|
169
|
-
if !ok {
|
|
170
|
-
return code(via.Flow + "#" + via.Step)
|
|
171
|
-
}
|
|
172
|
-
suffix := ""
|
|
173
|
-
if via.Step != "" {
|
|
174
|
-
suffix = "#step-" + anchorID(via.Step)
|
|
175
|
-
}
|
|
176
|
-
return "[" + code(via.Flow+"#"+via.Step) + "](" + rel(from, page) + suffix + ")"
|
|
177
|
-
}
|
|
@@ -1,201 +0,0 @@
|
|
|
1
|
-
package main
|
|
2
|
-
|
|
3
|
-
import (
|
|
4
|
-
"strings"
|
|
5
|
-
|
|
6
|
-
"github.com/shortlink-org/portolan/catalog"
|
|
7
|
-
)
|
|
8
|
-
|
|
9
|
-
func (s *site) renderStore(store *catalog.Store) {
|
|
10
|
-
self := s.pathOf[store.ID]
|
|
11
|
-
|
|
12
|
-
var b strings.Builder
|
|
13
|
-
b.WriteString("# " + store.Name + "\n\n")
|
|
14
|
-
b.WriteString(s.stamp() + "\n")
|
|
15
|
-
|
|
16
|
-
meta := [][]string{
|
|
17
|
-
{"Id", code(store.ID)},
|
|
18
|
-
{"Kind", string(store.Kind)},
|
|
19
|
-
{"Owner", s.ref(self, store.Owner, store.Owner)},
|
|
20
|
-
}
|
|
21
|
-
if store.Source != "" {
|
|
22
|
-
meta = append(meta, []string{"Source", s.source(self, store.Source, s.services[store.Owner])})
|
|
23
|
-
}
|
|
24
|
-
b.WriteString(defList(meta))
|
|
25
|
-
|
|
26
|
-
keyspaces := make([][]string, 0, len(store.Keyspaces))
|
|
27
|
-
for i := range store.Keyspaces {
|
|
28
|
-
keyspace := &store.Keyspaces[i]
|
|
29
|
-
source := ""
|
|
30
|
-
if keyspace.Source != "" {
|
|
31
|
-
source = s.source(self, keyspace.Source, s.services[store.Owner])
|
|
32
|
-
}
|
|
33
|
-
operations := make([]string, 0, len(keyspace.Operations))
|
|
34
|
-
for _, operation := range keyspace.Operations {
|
|
35
|
-
operations = append(operations, string(operation))
|
|
36
|
-
}
|
|
37
|
-
keyspaces = append(keyspaces, []string{
|
|
38
|
-
code(keyspace.Pattern), strings.Join(operations, ", "), code(keyspace.Value), code(keyspace.TTL), source,
|
|
39
|
-
})
|
|
40
|
-
}
|
|
41
|
-
section(&b, "Redis key patterns", table([]string{"Pattern", "Operations", "Value", "TTL", "Source"}, keyspaces))
|
|
42
|
-
|
|
43
|
-
var tables strings.Builder
|
|
44
|
-
for i := range store.Tables {
|
|
45
|
-
s.renderTable(&tables, self, store, &store.Tables[i])
|
|
46
|
-
}
|
|
47
|
-
section(&b, "Tables", tables.String())
|
|
48
|
-
|
|
49
|
-
var views strings.Builder
|
|
50
|
-
for i := range store.Views {
|
|
51
|
-
s.renderView(&views, self, store, &store.Views[i])
|
|
52
|
-
}
|
|
53
|
-
section(&b, "Views", views.String())
|
|
54
|
-
|
|
55
|
-
s.b.file(self, b.String())
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
func (s *site) renderTable(b *strings.Builder, self string, store *catalog.Store, tbl *catalog.Table) {
|
|
59
|
-
b.WriteString("<a id=\"relation-" + anchorID(tbl.ID) + "\"></a>\n")
|
|
60
|
-
b.WriteString("### " + tbl.Name + "\n\n")
|
|
61
|
-
|
|
62
|
-
meta := []string{}
|
|
63
|
-
if tbl.Role != "" {
|
|
64
|
-
meta = append(meta, string(tbl.Role))
|
|
65
|
-
}
|
|
66
|
-
if tbl.Persists != nil {
|
|
67
|
-
if tbl.Persists.Aggregate != "" {
|
|
68
|
-
meta = append(meta, "persists "+s.ref(self, tbl.Persists.Aggregate, tbl.Persists.Aggregate))
|
|
69
|
-
}
|
|
70
|
-
if tbl.Persists.Block != "" {
|
|
71
|
-
meta = append(meta, "block "+code(tbl.Persists.Block))
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
if len(meta) > 0 {
|
|
75
|
-
b.WriteString(strings.Join(meta, " · ") + "\n\n")
|
|
76
|
-
}
|
|
77
|
-
if tbl.Doc != "" {
|
|
78
|
-
b.WriteString(tbl.Doc + "\n\n")
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
b.WriteString(s.columnTable(self, store, tbl.Columns))
|
|
82
|
-
|
|
83
|
-
indexes := make([][]string, 0, len(tbl.Indexes))
|
|
84
|
-
for _, idx := range tbl.Indexes {
|
|
85
|
-
kind := "index"
|
|
86
|
-
if idx.Unique {
|
|
87
|
-
kind = "unique"
|
|
88
|
-
}
|
|
89
|
-
indexes = append(indexes, []string{code(idx.Name), strings.Join(idx.Columns, ", "), kind})
|
|
90
|
-
}
|
|
91
|
-
if rendered := table([]string{"Index", "Columns", "Kind"}, indexes); rendered != "" {
|
|
92
|
-
b.WriteString("\n" + rendered)
|
|
93
|
-
}
|
|
94
|
-
b.WriteString("\n")
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
func (s *site) renderView(b *strings.Builder, self string, store *catalog.Store, view *catalog.View) {
|
|
98
|
-
b.WriteString("<a id=\"relation-" + anchorID(view.ID) + "\"></a>\n")
|
|
99
|
-
b.WriteString("### " + view.Name + "\n\n")
|
|
100
|
-
|
|
101
|
-
meta := []string{}
|
|
102
|
-
if view.Materialized {
|
|
103
|
-
// Worth saying first and plainly: a materialised view can be stale, and
|
|
104
|
-
// that is the one thing a reader has to know before believing a row.
|
|
105
|
-
meta = append(meta, "**materialized** — rows are stored, and can be stale")
|
|
106
|
-
} else {
|
|
107
|
-
meta = append(meta, "computed on read")
|
|
108
|
-
}
|
|
109
|
-
if len(view.Reads) > 0 {
|
|
110
|
-
reads := make([]string, 0, len(view.Reads))
|
|
111
|
-
for _, id := range view.Reads {
|
|
112
|
-
reads = append(reads, s.relationRef(self, id))
|
|
113
|
-
}
|
|
114
|
-
meta = append(meta, "reads "+strings.Join(reads, ", "))
|
|
115
|
-
}
|
|
116
|
-
b.WriteString(strings.Join(meta, " · ") + "\n\n")
|
|
117
|
-
|
|
118
|
-
if view.Doc != "" {
|
|
119
|
-
b.WriteString(view.Doc + "\n\n")
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
b.WriteString(s.columnTable(self, store, view.Columns))
|
|
123
|
-
|
|
124
|
-
if view.Definition != "" {
|
|
125
|
-
b.WriteString("\n" + fence("sql", view.Definition))
|
|
126
|
-
}
|
|
127
|
-
if view.Source != "" {
|
|
128
|
-
b.WriteString("\nSource: " + s.source(self, view.Source, s.services[store.Owner]) + "\n")
|
|
129
|
-
}
|
|
130
|
-
b.WriteString("\n")
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
func (s *site) columnTable(self string, store *catalog.Store, columns []catalog.Column) string {
|
|
134
|
-
rows := make([][]string, 0, len(columns))
|
|
135
|
-
for i := range columns {
|
|
136
|
-
col := &columns[i]
|
|
137
|
-
|
|
138
|
-
key := ""
|
|
139
|
-
switch {
|
|
140
|
-
case col.PK:
|
|
141
|
-
key = "PK"
|
|
142
|
-
case col.FK != nil:
|
|
143
|
-
key = "→ " + s.relationRef(self, col.FK.Table) + "." + col.FK.Column
|
|
144
|
-
if col.FK.OnDelete != "" {
|
|
145
|
-
key += " (" + col.FK.OnDelete + ")"
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
null := "not null"
|
|
150
|
-
if col.Nullable {
|
|
151
|
-
null = "null"
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
from := ""
|
|
155
|
-
if len(col.From) > 0 {
|
|
156
|
-
sources := make([]string, 0, len(col.From))
|
|
157
|
-
for _, ref := range col.From {
|
|
158
|
-
sources = append(sources, code(ref))
|
|
159
|
-
|
|
160
|
-
// Lineage that leaves the store is how a service stays out of
|
|
161
|
-
// somebody else's database - and nothing on the far side records
|
|
162
|
-
// that the copy exists.
|
|
163
|
-
if owner, ok := s.relationStore[relationOf(ref)]; ok && owner != store.ID {
|
|
164
|
-
s.b.warn(store.ID, "%s.%s is copied from %q, which lives in store %q", store.ID, col.Name, ref, owner)
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
from = strings.Join(sources, ", ")
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
rows = append(rows, []string{code(col.Name), code(col.Type), null, key, col.Maps, from, col.Doc})
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
return table([]string{"Column", "Type", "Null", "Key", "Maps", "From", "Doc"}, rows)
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
// relationRef links a table or view id to the heading that documents it,
|
|
177
|
-
// wherever that lives - a foreign key routinely points at a table in another
|
|
178
|
-
// store, and the point of the link is to say so.
|
|
179
|
-
func (s *site) relationRef(from, id string) string {
|
|
180
|
-
storeID, known := s.relationStore[id]
|
|
181
|
-
if !known {
|
|
182
|
-
return code(id)
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
page, ok := s.pathOf[storeID]
|
|
186
|
-
if !ok {
|
|
187
|
-
return code(id)
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
return "[" + code(id) + "](" + rel(from, page) + "#relation-" + anchorID(id) + ")"
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
// relationOf strips the trailing column from a lineage reference,
|
|
194
|
-
// "<table or view id>.<column>", leaving the relation.
|
|
195
|
-
func relationOf(ref string) string {
|
|
196
|
-
if i := strings.LastIndex(ref, "."); i >= 0 {
|
|
197
|
-
return ref[:i]
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
return ref
|
|
201
|
-
}
|
|
Binary file
|
|
@@ -1,17 +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: "gen-mermaid", Summary: "Exports every flow as a standalone Mermaid sequence diagram.",
|
|
15
|
-
Phases: []string{plugin.PhaseGenerate}, Options: optionsSchema,
|
|
16
|
-
}
|
|
17
|
-
}
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
package main
|
|
2
|
-
|
|
3
|
-
import (
|
|
4
|
-
"fmt"
|
|
5
|
-
"io"
|
|
6
|
-
"os"
|
|
7
|
-
|
|
8
|
-
"github.com/shortlink-org/portolan/plugin"
|
|
9
|
-
)
|
|
10
|
-
|
|
11
|
-
func main() {
|
|
12
|
-
if err := run(os.Stdin, os.Stdout); err != nil {
|
|
13
|
-
fmt.Fprintln(os.Stderr, "portolan-gen-mermaid:", err)
|
|
14
|
-
os.Exit(1)
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
func run(stdin io.Reader, stdout io.Writer) error {
|
|
19
|
-
return plugin.Serve(stdin, stdout, descriptor(), func(req plugin.Request, opts Options) (plugin.Response, error) {
|
|
20
|
-
return render(req, opts), nil
|
|
21
|
-
})
|
|
22
|
-
}
|
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
package main
|
|
2
|
-
|
|
3
|
-
import (
|
|
4
|
-
"encoding/json"
|
|
5
|
-
"sort"
|
|
6
|
-
"strings"
|
|
7
|
-
|
|
8
|
-
"github.com/shortlink-org/portolan/catalog"
|
|
9
|
-
"github.com/shortlink-org/portolan/plugin"
|
|
10
|
-
flowmermaid "github.com/shortlink-org/portolan/render/mermaid"
|
|
11
|
-
)
|
|
12
|
-
|
|
13
|
-
type Options struct {
|
|
14
|
-
Title string `json:"title,omitempty"`
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
type indexEntry struct {
|
|
18
|
-
ID string `json:"id"`
|
|
19
|
-
Slug string `json:"slug"`
|
|
20
|
-
Name string `json:"name"`
|
|
21
|
-
Owner string `json:"owner,omitempty"`
|
|
22
|
-
Source string `json:"source,omitempty"`
|
|
23
|
-
Diagram string `json:"diagram"`
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
func render(req plugin.Request, opts Options) plugin.Response {
|
|
27
|
-
flows := append([]catalog.Flow(nil), req.Catalog.Flows...)
|
|
28
|
-
sort.Slice(flows, func(i, j int) bool { return flows[i].Slug < flows[j].Slug })
|
|
29
|
-
label := labeler(req.Catalog)
|
|
30
|
-
b := &plugin.Builder{}
|
|
31
|
-
title := opts.Title
|
|
32
|
-
if title == "" {
|
|
33
|
-
title = "Architecture flows"
|
|
34
|
-
}
|
|
35
|
-
var readme strings.Builder
|
|
36
|
-
readme.WriteString("# " + title + "\n\n")
|
|
37
|
-
readme.WriteString("Standalone Mermaid sequence diagrams generated from the portolan catalog.\n\n")
|
|
38
|
-
entries := make([]indexEntry, 0, len(flows))
|
|
39
|
-
for i := range flows {
|
|
40
|
-
flow := &flows[i]
|
|
41
|
-
name := flow.Slug + ".mmd"
|
|
42
|
-
b.File(name, flowmermaid.Sequence(flow, label))
|
|
43
|
-
readme.WriteString("- [" + flow.Name + "](" + name + ") — `" + flow.ID + "`\n")
|
|
44
|
-
entries = append(entries, indexEntry{ID: flow.ID, Slug: flow.Slug, Name: flow.Name, Owner: flow.Owner, Source: flow.Source, Diagram: name})
|
|
45
|
-
}
|
|
46
|
-
encoded, _ := json.MarshalIndent(map[string]any{"version": 1, "flows": entries}, "", " ")
|
|
47
|
-
b.File("README.md", readme.String())
|
|
48
|
-
b.File("index.json", string(encoded)+"\n")
|
|
49
|
-
return b.Response()
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
func labeler(cat catalog.Catalog) func(*catalog.Step) string {
|
|
53
|
-
methods := map[string]catalog.RpcMethod{}
|
|
54
|
-
services := map[string]*catalog.Service{}
|
|
55
|
-
for i := range cat.Contexts {
|
|
56
|
-
for j := range cat.Contexts[i].Services {
|
|
57
|
-
svc := &cat.Contexts[i].Services[j]
|
|
58
|
-
services[svc.ID] = svc
|
|
59
|
-
for k := range svc.Provides {
|
|
60
|
-
provided := &svc.Provides[k]
|
|
61
|
-
for m := range provided.Methods {
|
|
62
|
-
methods[provided.ID+"/"+provided.Methods[m].Name] = provided.Methods[m]
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
for i := range cat.Externals {
|
|
68
|
-
for j := range cat.Externals[i].Provides {
|
|
69
|
-
provided := &cat.Externals[i].Provides[j]
|
|
70
|
-
for m := range provided.Methods {
|
|
71
|
-
methods[provided.ID+"/"+provided.Methods[m].Name] = provided.Methods[m]
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
return func(step *catalog.Step) string {
|
|
76
|
-
text := step.Label
|
|
77
|
-
if text == "" {
|
|
78
|
-
text = step.Ref
|
|
79
|
-
}
|
|
80
|
-
if text == "" {
|
|
81
|
-
text = string(step.Kind)
|
|
82
|
-
}
|
|
83
|
-
if step.Kind != catalog.StepRPC {
|
|
84
|
-
return text
|
|
85
|
-
}
|
|
86
|
-
answer := methods[step.Ref].Response
|
|
87
|
-
if step.Ref == "" && step.Label != "" {
|
|
88
|
-
if svc := services[step.To]; svc != nil {
|
|
89
|
-
for i := range svc.Provides {
|
|
90
|
-
for j := range svc.Provides[i].Methods {
|
|
91
|
-
method := &svc.Provides[i].Methods[j]
|
|
92
|
-
if method.Name == step.Label {
|
|
93
|
-
answer = method.Response
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
if answer != "" {
|
|
100
|
-
return text + " → " + answer
|
|
101
|
-
}
|
|
102
|
-
return text
|
|
103
|
-
}
|
|
104
|
-
}
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
package main
|
|
2
|
-
|
|
3
|
-
import (
|
|
4
|
-
"encoding/json"
|
|
5
|
-
"strings"
|
|
6
|
-
"testing"
|
|
7
|
-
|
|
8
|
-
"github.com/shortlink-org/portolan/catalog"
|
|
9
|
-
"github.com/shortlink-org/portolan/plugin"
|
|
10
|
-
"github.com/shortlink-org/portolan/plugin/schematest"
|
|
11
|
-
)
|
|
12
|
-
|
|
13
|
-
func TestOptionsSchema(t *testing.T) { schematest.Check(t, optionsSchema, Options{}) }
|
|
14
|
-
|
|
15
|
-
func TestRenderIsSortedAndIndexed(t *testing.T) {
|
|
16
|
-
cat := catalog.Catalog{Flows: []catalog.Flow{
|
|
17
|
-
{ID: "flow.z", Slug: "z", Name: "Z", Participants: []catalog.Participant{{ID: "a", Kind: catalog.ParticipantActor}, {ID: "b", Kind: catalog.ParticipantService}}, Steps: catalog.FlowNodes{&catalog.Step{Type: "step", ID: "s1", From: "a", To: "b", Kind: catalog.StepCall, Label: "go"}}},
|
|
18
|
-
{ID: "flow.a", Slug: "a", Name: "A"},
|
|
19
|
-
}}
|
|
20
|
-
resp := render(plugin.Request{Catalog: cat}, Options{})
|
|
21
|
-
if resp.Files[0].Name != "a.mmd" || resp.Files[1].Name != "z.mmd" {
|
|
22
|
-
t.Fatalf("files are not stable: %+v", resp.Files)
|
|
23
|
-
}
|
|
24
|
-
var index struct {
|
|
25
|
-
Flows []indexEntry `json:"flows"`
|
|
26
|
-
}
|
|
27
|
-
if err := json.Unmarshal([]byte(resp.Files[len(resp.Files)-1].Contents), &index); err != nil || len(index.Flows) != 2 {
|
|
28
|
-
t.Fatalf("bad index: %v %+v", err, index)
|
|
29
|
-
}
|
|
30
|
-
if !strings.Contains(resp.Files[1].Contents, "sequenceDiagram") {
|
|
31
|
-
t.Fatalf("not Mermaid: %s", resp.Files[1].Contents)
|
|
32
|
-
}
|
|
33
|
-
}
|
package/plugins/gen-mermaid.wasm
DELETED
|
Binary file
|