@shortlink-org/portolan 0.2.3 → 0.3.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.
Files changed (184) hide show
  1. package/README.md +23 -0
  2. package/catalog/enum_test.go +46 -0
  3. package/catalog/evidence_test.go +35 -0
  4. package/catalog/model.go +1066 -0
  5. package/catalog/roundtrip_test.go +203 -0
  6. package/catalog/via_test.go +38 -0
  7. package/cli/init.test.mjs +6 -1
  8. package/cli/portolan.mjs +8 -0
  9. package/cli/portolan.test.mjs +49 -0
  10. package/go.mod +14 -0
  11. package/go.sum +20 -0
  12. package/internal/gocall/README.md +19 -0
  13. package/internal/gocall/analyze.go +189 -0
  14. package/internal/gocall/analyze_test.go +107 -0
  15. package/internal/gohttp/analyze.go +2562 -0
  16. package/internal/gohttp/destination.go +373 -0
  17. package/internal/gohttp/endpoints.go +1067 -0
  18. package/internal/gohttp/roots.go +320 -0
  19. package/internal/gohttp/typed.go +96 -0
  20. package/internal/goscan/constants.go +85 -0
  21. package/internal/goscan/goscan_test.go +227 -0
  22. package/internal/goscan/index.go +629 -0
  23. package/internal/goscan/index_test.go +66 -0
  24. package/internal/goscan/names.go +52 -0
  25. package/internal/goscan/parse_test.go +11 -0
  26. package/internal/goscan/source.go +37 -0
  27. package/internal/goscan/tree.go +284 -0
  28. package/internal/goscan/types.go +99 -0
  29. package/internal/wsdl/ids.go +127 -0
  30. package/internal/wsdl/ids_test.go +21 -0
  31. package/internal/wsdl/model.go +70 -0
  32. package/internal/wsdl/parse.go +949 -0
  33. package/internal/wsdl/parse_test.go +170 -0
  34. package/package.json +22 -10
  35. package/plugin/describe.go +118 -0
  36. package/plugin/describe_test.go +114 -0
  37. package/plugin/protocol.go +141 -0
  38. package/plugin/schematest/schematest.go +126 -0
  39. package/plugins/README.md +114 -46
  40. package/plugins/cmd/portolan-http-clients/main.go +19 -0
  41. package/plugins/extract-celery/extract.py +0 -2
  42. package/plugins/extract-celery/extract_test.py +1 -1
  43. package/plugins/extract-django/README.md +39 -17
  44. package/plugins/extract-django/domain.py +28 -17
  45. package/plugins/extract-django/extract.py +21 -7
  46. package/plugins/extract-django/extract_test.py +55 -2
  47. package/plugins/extract-django/lifecycle.py +2 -0
  48. package/plugins/extract-django/operations.py +1 -1
  49. package/plugins/extract-django/routing_test.py +109 -1
  50. package/plugins/extract-django/store.py +1 -1
  51. package/plugins/extract-django/transport.py +101 -55
  52. package/plugins/extract-django/verbs.py +241 -0
  53. package/plugins/extract-go/README.md +47 -0
  54. package/plugins/extract-http-clients/describe.go +19 -0
  55. package/plugins/extract-http-clients/describe_test.go +11 -0
  56. package/plugins/extract-http-clients/extract.go +740 -0
  57. package/plugins/extract-http-clients/extract_test.go +1561 -0
  58. package/plugins/extract-http-clients/main.go +41 -0
  59. package/plugins/extract-java/build/org/portolan/extract/Extract.class +0 -0
  60. package/plugins/extract-java/build/org/portolan/extract/Protocol$Builder.class +0 -0
  61. package/plugins/extract-java/build/org/portolan/extract/Protocol$Input.class +0 -0
  62. package/plugins/extract-java/build/org/portolan/extract/Protocol$Options.class +0 -0
  63. package/plugins/extract-python-kafka/README.md +6 -0
  64. package/plugins/extract-python-kafka/extract.py +2 -4
  65. package/plugins/extract-python-kafka/extract_test.py +18 -2
  66. package/plugins/extract-ts/extract.test.ts +2 -2
  67. package/plugins/extract-ts/extract.ts +4 -5
  68. package/plugins/extract-ts/graphql.test.ts +1 -1
  69. package/plugins/openapi/ids.go +261 -0
  70. package/plugins/openapi/ids_test.go +98 -0
  71. package/plugins/portolan-go.wasm +0 -0
  72. package/plugins/pyplugin/catalog.py +12 -1
  73. package/plugins/pyplugin/kafka.py +74 -3
  74. package/plugins/pyplugin/protocol.py +1 -5
  75. package/portolan.json +3 -2
  76. package/schema/portolan.schema.json +34 -0
  77. package/scripts/README.md +18 -12
  78. package/scripts/catalog-sources.mjs +6 -0
  79. package/scripts/delivery-presets.mjs +21 -11
  80. package/scripts/diff.mjs +5 -1
  81. package/scripts/django-aggregates.test.mjs +58 -0
  82. package/scripts/gen-likec4.mjs +79 -21
  83. package/scripts/gen-likec4.test.mjs +25 -2
  84. package/scripts/gen.mjs +118 -115
  85. package/scripts/go-discovery.test.mjs +30 -0
  86. package/scripts/history.mjs +186 -3
  87. package/scripts/history.test.mjs +1 -1
  88. package/scripts/host-plugins/fetch-git.mjs +77 -21
  89. package/scripts/host-plugins/fetch-git.test.mjs +62 -8
  90. package/scripts/local-api.mjs +71 -4
  91. package/scripts/local-api.test.mjs +63 -4
  92. package/scripts/local-discovery.mjs +82 -9
  93. package/scripts/manifest.mjs +5 -3
  94. package/scripts/manifest.test.mjs +24 -0
  95. package/scripts/output-diff.mjs +94 -0
  96. package/scripts/output-diff.test.mjs +36 -0
  97. package/scripts/package-smoke.mjs +62 -4
  98. package/scripts/plugin-host.mjs +22 -2
  99. package/scripts/plugin-host.test.mjs +9 -0
  100. package/scripts/plugin-wasm-worker.mjs +4 -1
  101. package/scripts/provenance.mjs +72 -0
  102. package/scripts/provenance.test.mjs +149 -0
  103. package/scripts/run-builtin.mjs +39 -5
  104. package/scripts/schema.mjs +29 -0
  105. package/scripts/warning-policy.mjs +161 -0
  106. package/scripts/warning-policy.test.mjs +56 -0
  107. package/src/app/Breadcrumbs.test.ts +4 -0
  108. package/src/app/Breadcrumbs.tsx +1 -0
  109. package/src/app/Sidebar.tsx +3 -3
  110. package/src/catalog-docs.test.ts +64 -0
  111. package/src/catalog-docs.ts +35 -0
  112. package/src/catalog-error.test.ts +15 -0
  113. package/src/catalog-model.ts +70 -6
  114. package/src/catalog-stores.test.ts +17 -0
  115. package/src/catalog-validation.ts +52 -2
  116. package/src/catalog.test.ts +13 -2
  117. package/src/chat/Starter.tsx +5 -11
  118. package/src/chat/tools.test.ts +27 -0
  119. package/src/chat/tools.ts +5 -9
  120. package/src/components/CatalogStamp.tsx +10 -8
  121. package/src/components/ChannelRows.messagepack.test.tsx +28 -0
  122. package/src/components/ChannelRows.test.tsx +54 -0
  123. package/src/components/ChannelRows.tsx +57 -10
  124. package/src/components/HTTPDestinationEvidence.test.tsx +23 -0
  125. package/src/components/HTTPDestinationEvidence.tsx +31 -0
  126. package/src/components/Integrations.tsx +1 -1
  127. package/src/components/LifecycleDiagram.tsx +28 -12
  128. package/src/components/MachineDocs.tsx +6 -5
  129. package/src/components/MethodRows.tsx +9 -2
  130. package/src/components/ProblemRow.tsx +4 -0
  131. package/src/components/RelationEvidence.test.tsx +14 -0
  132. package/src/components/RelationEvidence.tsx +53 -0
  133. package/src/components/WhatLinksHere.tsx +6 -4
  134. package/src/data.ts +25 -7
  135. package/src/enrich.test.ts +336 -6
  136. package/src/enrich.ts +206 -3
  137. package/src/flow/StepDetail.tsx +104 -54
  138. package/src/flow/answers.test.ts +18 -1
  139. package/src/flow/answers.ts +37 -8
  140. package/src/flow/evidence.test.ts +16 -0
  141. package/src/flow/evidence.ts +34 -0
  142. package/src/index.css +44 -0
  143. package/src/landing/DraggableReveal.tsx +3 -2
  144. package/src/landing/EvidencePipeline.tsx +105 -0
  145. package/src/landing/LandingPage.tsx +2 -59
  146. package/src/lib/backlinks.test.ts +16 -1
  147. package/src/lib/backlinks.ts +20 -0
  148. package/src/lib/catalog-diff.test.ts +18 -0
  149. package/src/lib/catalog-diff.ts +20 -2
  150. package/src/lib/derive.ts +1 -0
  151. package/src/lib/django-aggregates.d.mts +9 -0
  152. package/src/lib/django-aggregates.mjs +36 -0
  153. package/src/lib/django-aggregates.test.ts +29 -0
  154. package/src/lib/django-aggregates.ts +5 -0
  155. package/src/lib/kafka-ui.test.ts +87 -0
  156. package/src/lib/kafka-ui.ts +105 -0
  157. package/src/lib/local-api.ts +20 -2
  158. package/src/lib/setup-info.test.ts +17 -0
  159. package/src/lib/setup-info.ts +58 -0
  160. package/src/lib/warnings.test.ts +54 -0
  161. package/src/lib/warnings.ts +260 -0
  162. package/src/lib/wire-problems.test.ts +21 -0
  163. package/src/lib/wire-problems.ts +62 -1
  164. package/src/likec4/FlowView.tsx +2 -6
  165. package/src/likec4/flow-edges.test.ts +64 -1
  166. package/src/likec4/flow-edges.ts +43 -7
  167. package/src/likec4/view-index.ts +8 -2
  168. package/src/map/ContextMapGraph.tsx +76 -32
  169. package/src/merge.test.ts +23 -0
  170. package/src/merge.ts +33 -10
  171. package/src/pages/AggregatePage.tsx +8 -7
  172. package/src/pages/CatalogFailure.tsx +2 -2
  173. package/src/pages/ContextPage.tsx +6 -5
  174. package/src/pages/ServicePage.tsx +4 -3
  175. package/src/pages/Settings.tsx +200 -44
  176. package/src/pages/settings/DjangoAggregateChoices.tsx +79 -0
  177. package/src/pages/settings/IntegrationsSettings.tsx +117 -0
  178. package/src/routes.test.ts +2 -0
  179. package/src/routes.ts +2 -1
  180. package/src/selection/DetailPanel.tsx +61 -1
  181. package/src/virtual-provenance.d.ts +11 -0
  182. package/vite.config.ts +5 -0
  183. package/scripts/vendor-lock.mjs +0 -58
  184. package/scripts/vendor-lock.test.mjs +0 -69
@@ -0,0 +1,227 @@
1
+ package goscan
2
+
3
+ import (
4
+ "go/ast"
5
+ "os"
6
+ "path/filepath"
7
+ "reflect"
8
+ "strings"
9
+ "testing"
10
+ )
11
+
12
+ func write(t *testing.T, root, name, contents string) {
13
+ t.Helper()
14
+ full := filepath.Join(root, name)
15
+ if err := os.MkdirAll(filepath.Dir(full), 0o755); err != nil {
16
+ t.Fatal(err)
17
+ }
18
+ if err := os.WriteFile(full, []byte(contents), 0o644); err != nil {
19
+ t.Fatal(err)
20
+ }
21
+ }
22
+
23
+ func tree(t *testing.T) *Tree {
24
+ t.Helper()
25
+ root := t.TempDir()
26
+ write(t, root, "go.mod", "module example.com/m\n\ngo 1.22\n")
27
+ write(t, root, "main.go", `package main
28
+
29
+ import (
30
+ other "example.com/m/sub"
31
+ "example.com/m/vendor/lib"
32
+ )
33
+
34
+ const (
35
+ A = "a"
36
+ B = A
37
+ C = other.D
38
+ Inherited
39
+ Self1 = Self2
40
+ Self2 = Self1
41
+ Foreign = lib.Default
42
+ Number = 3
43
+ )
44
+
45
+ type Args struct {
46
+ ID string `+"`json:\"id\"`"+`
47
+ Secret string `+"`json:\"-\"`"+`
48
+ Plain int
49
+ hidden bool
50
+ }
51
+ `)
52
+ write(t, root, "sub/b.go", "package sub\n\nconst D = \"d\"\n")
53
+ write(t, root, "sub/b_test.go", "package sub\n\nconst Test = \"never\"\n")
54
+ write(t, root, "sub/gen.gen.go", "package sub\n\nconst Generated = \"never\"\n")
55
+ write(t, root, "vendor/lib/lib.go", "package lib\n\nconst Default = \"never\"\n")
56
+ write(t, root, ".hidden/h.go", "package hidden\n\nconst Hidden = \"never\"\n")
57
+ write(t, root, "node_modules/x/x.go", "package x\n\nconst X = \"never\"\n")
58
+
59
+ out, err := Read(root)
60
+ if err != nil {
61
+ t.Fatal(err)
62
+ }
63
+ return out
64
+ }
65
+
66
+ func TestReadKeepsTheSourceAndLeavesTheRest(t *testing.T) {
67
+ out := tree(t)
68
+
69
+ var names []string
70
+ for _, file := range out.Files {
71
+ names = append(names, file.Name+" "+file.Pkg)
72
+ }
73
+ want := []string{"main.go example.com/m", "sub/b.go example.com/m/sub"}
74
+ if !reflect.DeepEqual(names, want) {
75
+ t.Errorf("files: got %v, want %v", names, want)
76
+ }
77
+ if out.Module != "example.com/m" {
78
+ t.Errorf("module: got %q", out.Module)
79
+ }
80
+ for _, key := range []string{"example.com/m/sub.Test", "example.com/m/sub.Generated", "example.com/m/vendor/lib.Default", "example.com/m/.hidden.Hidden"} {
81
+ if _, found := out.Constants[key]; found {
82
+ t.Errorf("%s was read", key)
83
+ }
84
+ }
85
+ }
86
+
87
+ func TestImportsAreByLocalName(t *testing.T) {
88
+ out := tree(t)
89
+ got := out.Files[0].Imports
90
+ want := map[string]string{"other": "example.com/m/sub", "lib": "example.com/m/vendor/lib"}
91
+ if !reflect.DeepEqual(got, want) {
92
+ t.Errorf("imports: got %v, want %v", got, want)
93
+ }
94
+ }
95
+
96
+ func TestADottedImportSegmentIsKnownByItsPackageName(t *testing.T) {
97
+ root := t.TempDir()
98
+ write(t, root, "go.mod", "module example.com/m\n")
99
+ write(t, root, "main.go", "package main\n\nimport (\n\t\"github.com/nats-io/nats.go\"\n\t\"gopkg.in/yaml.v3\"\n\t\"github.com/nats-io/nats.go/jetstream\"\n)\n")
100
+ out, err := Read(root)
101
+ if err != nil {
102
+ t.Fatal(err)
103
+ }
104
+ got := out.Files[0].Imports
105
+ want := map[string]string{
106
+ "nats.go": "github.com/nats-io/nats.go",
107
+ "nats": "github.com/nats-io/nats.go",
108
+ "yaml.v3": "gopkg.in/yaml.v3",
109
+ "yaml": "gopkg.in/yaml.v3",
110
+ "jetstream": "github.com/nats-io/nats.go/jetstream",
111
+ }
112
+ if !reflect.DeepEqual(got, want) {
113
+ t.Errorf("imports: got %v, want %v", got, want)
114
+ }
115
+ }
116
+
117
+ func TestConstantsResolveThroughEachOther(t *testing.T) {
118
+ out := tree(t)
119
+ cases := map[string]string{
120
+ "example.com/m.A": "a",
121
+ "example.com/m.B": "a",
122
+ "example.com/m.C": "d",
123
+ "example.com/m.Inherited": "d",
124
+ "example.com/m.Self1": "",
125
+ "example.com/m.Foreign": "",
126
+ "example.com/m.Number": "",
127
+ "example.com/m.Missing": "",
128
+ }
129
+ for key, want := range cases {
130
+ if got := out.ConstantString(key, nil); got != want {
131
+ t.Errorf("%s: got %q, want %q", key, got, want)
132
+ }
133
+ }
134
+ }
135
+
136
+ func TestForeignAnswersWhatTheTreeCannot(t *testing.T) {
137
+ out := tree(t)
138
+ out.Foreign = func(importPath, name string) (string, bool) {
139
+ if importPath == "example.com/m/vendor/lib" && name == "Default" {
140
+ return "default", true
141
+ }
142
+ return "", false
143
+ }
144
+ if got := out.ConstantString("example.com/m.Foreign", nil); got != "default" {
145
+ t.Errorf("got %q, want %q", got, "default")
146
+ }
147
+ }
148
+
149
+ func TestTypeKey(t *testing.T) {
150
+ out := tree(t)
151
+ file := out.Files[0]
152
+ parse := func(src string) ast.Expr {
153
+ expr, err := parseExpr(src)
154
+ if err != nil {
155
+ t.Fatal(err)
156
+ }
157
+ return expr
158
+ }
159
+ cases := map[string]string{
160
+ "Args": "example.com/m.Args",
161
+ "*Args": "example.com/m.Args",
162
+ "string": "string",
163
+ "other.Thing": "example.com/m/sub.Thing",
164
+ "[]other.Thing": "[]example.com/m/sub.Thing",
165
+ "map[string]Args": "map[string]example.com/m.Args",
166
+ "interface{ M() }": "interface",
167
+ "func()": "",
168
+ "a.b.C": "",
169
+ }
170
+ for src, want := range cases {
171
+ if got := out.TypeKey(parse(src), file); got != want {
172
+ t.Errorf("%s: got %q, want %q", src, got, want)
173
+ }
174
+ }
175
+ if got := out.TypeKey(nil, file); got != "" {
176
+ t.Errorf("nil: got %q", got)
177
+ }
178
+ }
179
+
180
+ func TestFieldsOfFollowTheJSONTag(t *testing.T) {
181
+ out := tree(t)
182
+ var body *ast.StructType
183
+ ast.Inspect(out.Files[0].Node, func(node ast.Node) bool {
184
+ if spec, ok := node.(*ast.TypeSpec); ok && spec.Name.Name == "Args" {
185
+ body = spec.Type.(*ast.StructType)
186
+ }
187
+ return body == nil
188
+ })
189
+ got := out.FieldsOf(body)
190
+ want := []string{"id string", "Plain int", "hidden bool"}
191
+ if !reflect.DeepEqual(got, want) {
192
+ t.Errorf("got %v, want %v", got, want)
193
+ }
194
+ }
195
+
196
+ func TestAtIsRelativeToTheRoot(t *testing.T) {
197
+ out := tree(t)
198
+ file := out.Files[1]
199
+ at := out.At(file.Node.Decls[0].Pos())
200
+ if at.String() != "sub/b.go:3" {
201
+ t.Errorf("got %q", at.String())
202
+ }
203
+ if (Source{File: "x.go"}).String() != "x.go" {
204
+ t.Error("a source with no line prints its line")
205
+ }
206
+ }
207
+
208
+ func TestNames(t *testing.T) {
209
+ if got := LastSegment("example.com/m.Args"); got != "Args" {
210
+ t.Errorf("LastSegment: %q", got)
211
+ }
212
+ if got := LastSegment("plain"); got != "plain" {
213
+ t.Errorf("LastSegment plain: %q", got)
214
+ }
215
+ if got := Slug(" Send Welcome_Mail!! "); got != "send-welcome-mail" {
216
+ t.Errorf("Slug: %q", got)
217
+ }
218
+ if got := Title("send-welcome_mail.v1"); got != "Send Welcome Mail V1" {
219
+ t.Errorf("Title: %q", got)
220
+ }
221
+ if got := FirstNonEmpty(" ", "", "x", "y"); got != "x" {
222
+ t.Errorf("FirstNonEmpty: %q", got)
223
+ }
224
+ if got := strings.TrimSpace(FirstNonEmpty(" ", "")); got != "" {
225
+ t.Errorf("FirstNonEmpty empty: %q", got)
226
+ }
227
+ }