@shortlink-org/portolan 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (826) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +387 -0
  3. package/catalog/enum_test.go +46 -0
  4. package/catalog/model.go +932 -0
  5. package/catalog/roundtrip_test.go +185 -0
  6. package/catalog/via_test.go +38 -0
  7. package/cli/portolan.mjs +368 -0
  8. package/go.mod +14 -0
  9. package/go.sum +14 -0
  10. package/index.html +13 -0
  11. package/internal/commands/cargo.go +154 -0
  12. package/internal/commands/commands.go +143 -0
  13. package/internal/commands/commands_test.go +323 -0
  14. package/internal/commands/gradle.go +77 -0
  15. package/internal/commands/justfile.go +82 -0
  16. package/internal/commands/makefile.go +106 -0
  17. package/internal/commands/maven.go +93 -0
  18. package/internal/commands/packagejson.go +159 -0
  19. package/internal/commands/pyproject.go +169 -0
  20. package/internal/commands/taskfile.go +101 -0
  21. package/internal/commands/testdata/estate/.cargo/config.toml +7 -0
  22. package/internal/commands/testdata/estate/Makefile +33 -0
  23. package/internal/commands/testdata/estate/Taskfile.yml +21 -0
  24. package/internal/commands/testdata/estate/build.gradle.kts +21 -0
  25. package/internal/commands/testdata/estate/justfile +20 -0
  26. package/internal/commands/testdata/estate/package.json +13 -0
  27. package/internal/commands/testdata/estate/pom.xml +29 -0
  28. package/internal/commands/testdata/estate/pyproject.toml +27 -0
  29. package/internal/commands/testdata/estate/xtask/src/main.rs +27 -0
  30. package/internal/commands/testdata/golden/commands.json +305 -0
  31. package/internal/gohttp/analyze.go +2500 -0
  32. package/internal/gohttp/endpoints.go +1067 -0
  33. package/internal/gohttp/roots.go +320 -0
  34. package/internal/gohttp/typed.go +143 -0
  35. package/internal/goscan/constants.go +85 -0
  36. package/internal/goscan/goscan_test.go +227 -0
  37. package/internal/goscan/names.go +52 -0
  38. package/internal/goscan/parse_test.go +11 -0
  39. package/internal/goscan/source.go +36 -0
  40. package/internal/goscan/tree.go +155 -0
  41. package/internal/goscan/types.go +99 -0
  42. package/internal/wsdl/ids.go +127 -0
  43. package/internal/wsdl/ids_test.go +21 -0
  44. package/internal/wsdl/model.go +62 -0
  45. package/internal/wsdl/parse.go +920 -0
  46. package/internal/wsdl/parse_test.go +133 -0
  47. package/package.json +117 -0
  48. package/plugin/describe.go +107 -0
  49. package/plugin/describe_test.go +114 -0
  50. package/plugin/protocol.go +117 -0
  51. package/plugin/schematest/schematest.go +126 -0
  52. package/plugins/README.md +1160 -0
  53. package/plugins/extract-adr/describe.go +19 -0
  54. package/plugins/extract-adr/describe_test.go +11 -0
  55. package/plugins/extract-adr/extract.go +153 -0
  56. package/plugins/extract-adr/extract_test.go +350 -0
  57. package/plugins/extract-adr/history.go +99 -0
  58. package/plugins/extract-adr/main.go +65 -0
  59. package/plugins/extract-adr/options.schema.json +26 -0
  60. package/plugins/extract-adr/parse.go +642 -0
  61. package/plugins/extract-adr/parse_test.go +405 -0
  62. package/plugins/extract-asyncapi/describe.go +19 -0
  63. package/plugins/extract-asyncapi/describe_test.go +11 -0
  64. package/plugins/extract-asyncapi/extract.go +315 -0
  65. package/plugins/extract-asyncapi/extract_test.go +197 -0
  66. package/plugins/extract-asyncapi/main.go +48 -0
  67. package/plugins/extract-asyncapi/options.schema.json +26 -0
  68. package/plugins/extract-asyncapi/spec.go +151 -0
  69. package/plugins/extract-celery/README.md +169 -0
  70. package/plugins/extract-celery/extract.py +346 -0
  71. package/plugins/extract-celery/extract_test.py +192 -0
  72. package/plugins/extract-celery/main.py +66 -0
  73. package/plugins/extract-celery/options.py +31 -0
  74. package/plugins/extract-celery/options.schema.json +31 -0
  75. package/plugins/extract-celery/producers.py +156 -0
  76. package/plugins/extract-celery/routes_test.py +106 -0
  77. package/plugins/extract-commands/describe.go +19 -0
  78. package/plugins/extract-commands/describe_test.go +11 -0
  79. package/plugins/extract-commands/extract.go +79 -0
  80. package/plugins/extract-commands/extract_test.go +92 -0
  81. package/plugins/extract-commands/main.go +55 -0
  82. package/plugins/extract-commands/options.schema.json +20 -0
  83. package/plugins/extract-csr/avro.go +258 -0
  84. package/plugins/extract-csr/describe.go +19 -0
  85. package/plugins/extract-csr/describe_test.go +11 -0
  86. package/plugins/extract-csr/extract.go +338 -0
  87. package/plugins/extract-csr/extract_test.go +374 -0
  88. package/plugins/extract-csr/jsonschema.go +343 -0
  89. package/plugins/extract-csr/lock.go +25 -0
  90. package/plugins/extract-csr/main.go +84 -0
  91. package/plugins/extract-csr/options.schema.json +43 -0
  92. package/plugins/extract-csr/subject.go +102 -0
  93. package/plugins/extract-django/README.md +386 -0
  94. package/plugins/extract-django/apps.py +100 -0
  95. package/plugins/extract-django/auth.py +302 -0
  96. package/plugins/extract-django/auth_test.py +188 -0
  97. package/plugins/extract-django/clients.py +121 -0
  98. package/plugins/extract-django/contracts.py +458 -0
  99. package/plugins/extract-django/database.py +119 -0
  100. package/plugins/extract-django/domain.py +318 -0
  101. package/plugins/extract-django/events.py +86 -0
  102. package/plugins/extract-django/extract.py +601 -0
  103. package/plugins/extract-django/extract_test.py +397 -0
  104. package/plugins/extract-django/flows.py +1278 -0
  105. package/plugins/extract-django/flows_test.py +338 -0
  106. package/plugins/extract-django/ids.py +42 -0
  107. package/plugins/extract-django/ids_test.py +30 -0
  108. package/plugins/extract-django/lifecycle.py +222 -0
  109. package/plugins/extract-django/lifecycle_test.py +76 -0
  110. package/plugins/extract-django/main.py +66 -0
  111. package/plugins/extract-django/openapi.py +229 -0
  112. package/plugins/extract-django/openapi_test.py +60 -0
  113. package/plugins/extract-django/operations.py +96 -0
  114. package/plugins/extract-django/options.py +61 -0
  115. package/plugins/extract-django/options.schema.json +126 -0
  116. package/plugins/extract-django/routing.py +214 -0
  117. package/plugins/extract-django/routing_test.py +198 -0
  118. package/plugins/extract-django/serializers.py +558 -0
  119. package/plugins/extract-django/store.py +434 -0
  120. package/plugins/extract-django/transport.py +242 -0
  121. package/plugins/extract-flows/describe.go +19 -0
  122. package/plugins/extract-flows/describe_test.go +11 -0
  123. package/plugins/extract-flows/extract.go +91 -0
  124. package/plugins/extract-flows/main.go +45 -0
  125. package/plugins/extract-flows/options.schema.json +16 -0
  126. package/plugins/extract-flows/parse.go +593 -0
  127. package/plugins/extract-flows/parse_test.go +204 -0
  128. package/plugins/extract-glossary/describe.go +19 -0
  129. package/plugins/extract-glossary/describe_test.go +11 -0
  130. package/plugins/extract-glossary/extract.go +115 -0
  131. package/plugins/extract-glossary/extract_test.go +220 -0
  132. package/plugins/extract-glossary/main.go +59 -0
  133. package/plugins/extract-glossary/options.schema.json +21 -0
  134. package/plugins/extract-glossary/parse.go +214 -0
  135. package/plugins/extract-glossary/parse_test.go +203 -0
  136. package/plugins/extract-go/aggregate.go +214 -0
  137. package/plugins/extract-go/client.go +409 -0
  138. package/plugins/extract-go/client_test.go +266 -0
  139. package/plugins/extract-go/describe.go +19 -0
  140. package/plugins/extract-go/describe_test.go +11 -0
  141. package/plugins/extract-go/enum.go +195 -0
  142. package/plugins/extract-go/enum_test.go +82 -0
  143. package/plugins/extract-go/event.go +99 -0
  144. package/plugins/extract-go/extract.go +191 -0
  145. package/plugins/extract-go/extract_test.go +261 -0
  146. package/plugins/extract-go/flow.go +1441 -0
  147. package/plugins/extract-go/flow_test.go +609 -0
  148. package/plugins/extract-go/httpclient.go +174 -0
  149. package/plugins/extract-go/httpclient_test.go +296 -0
  150. package/plugins/extract-go/ids.go +92 -0
  151. package/plugins/extract-go/layout.go +225 -0
  152. package/plugins/extract-go/layout_test.go +125 -0
  153. package/plugins/extract-go/lifecycle.go +324 -0
  154. package/plugins/extract-go/lifecycle_test.go +108 -0
  155. package/plugins/extract-go/main.go +79 -0
  156. package/plugins/extract-go/operation.go +157 -0
  157. package/plugins/extract-go/options.schema.json +66 -0
  158. package/plugins/extract-go/source.go +316 -0
  159. package/plugins/extract-go/transport.go +321 -0
  160. package/plugins/extract-go/transport_test.go +145 -0
  161. package/plugins/extract-go/wiring.go +434 -0
  162. package/plugins/extract-go-nats/describe.go +19 -0
  163. package/plugins/extract-go-nats/describe_test.go +11 -0
  164. package/plugins/extract-go-nats/extract.go +177 -0
  165. package/plugins/extract-go-nats/extract_test.go +389 -0
  166. package/plugins/extract-go-nats/index.go +379 -0
  167. package/plugins/extract-go-nats/main.go +42 -0
  168. package/plugins/extract-go-nats/options.schema.json +21 -0
  169. package/plugins/extract-go-nats/resolve.go +161 -0
  170. package/plugins/extract-go-nats/sites.go +224 -0
  171. package/plugins/extract-graphql/describe.go +19 -0
  172. package/plugins/extract-graphql/describe_test.go +11 -0
  173. package/plugins/extract-graphql/extract.go +433 -0
  174. package/plugins/extract-graphql/extract_test.go +256 -0
  175. package/plugins/extract-graphql/ids.go +49 -0
  176. package/plugins/extract-graphql/lex.go +237 -0
  177. package/plugins/extract-graphql/main.go +51 -0
  178. package/plugins/extract-graphql/options.schema.json +31 -0
  179. package/plugins/extract-graphql/parse.go +621 -0
  180. package/plugins/extract-graphql/parse_test.go +122 -0
  181. package/plugins/extract-http-clients/describe.go +19 -0
  182. package/plugins/extract-http-clients/describe_test.go +11 -0
  183. package/plugins/extract-http-clients/extract.go +705 -0
  184. package/plugins/extract-http-clients/extract_test.go +1263 -0
  185. package/plugins/extract-http-clients/main.go +42 -0
  186. package/plugins/extract-http-clients/options.schema.json +33 -0
  187. package/plugins/extract-java/README.md +190 -0
  188. package/plugins/extract-java/build/org/portolan/extract/Catalog.class +0 -0
  189. package/plugins/extract-java/build/org/portolan/extract/Clients$1.class +0 -0
  190. package/plugins/extract-java/build/org/portolan/extract/Clients$2.class +0 -0
  191. package/plugins/extract-java/build/org/portolan/extract/Clients$Call.class +0 -0
  192. package/plugins/extract-java/build/org/portolan/extract/Clients$Client.class +0 -0
  193. package/plugins/extract-java/build/org/portolan/extract/Clients$Route.class +0 -0
  194. package/plugins/extract-java/build/org/portolan/extract/Clients.class +0 -0
  195. package/plugins/extract-java/build/org/portolan/extract/Domain$Aggregate.class +0 -0
  196. package/plugins/extract-java/build/org/portolan/extract/Domain.class +0 -0
  197. package/plugins/extract-java/build/org/portolan/extract/Events$Found.class +0 -0
  198. package/plugins/extract-java/build/org/portolan/extract/Events.class +0 -0
  199. package/plugins/extract-java/build/org/portolan/extract/Extract.class +0 -0
  200. package/plugins/extract-java/build/org/portolan/extract/Flows$1.class +0 -0
  201. package/plugins/extract-java/build/org/portolan/extract/Flows$Binding.class +0 -0
  202. package/plugins/extract-java/build/org/portolan/extract/Flows$Draft.class +0 -0
  203. package/plugins/extract-java/build/org/portolan/extract/Flows$Frame.class +0 -0
  204. package/plugins/extract-java/build/org/portolan/extract/Flows$Options.class +0 -0
  205. package/plugins/extract-java/build/org/portolan/extract/Flows.class +0 -0
  206. package/plugins/extract-java/build/org/portolan/extract/Ids.class +0 -0
  207. package/plugins/extract-java/build/org/portolan/extract/Json$Reader.class +0 -0
  208. package/plugins/extract-java/build/org/portolan/extract/Json.class +0 -0
  209. package/plugins/extract-java/build/org/portolan/extract/Lifecycle$1.class +0 -0
  210. package/plugins/extract-java/build/org/portolan/extract/Lifecycle$Move.class +0 -0
  211. package/plugins/extract-java/build/org/portolan/extract/Lifecycle.class +0 -0
  212. package/plugins/extract-java/build/org/portolan/extract/Main.class +0 -0
  213. package/plugins/extract-java/build/org/portolan/extract/OpenApi$Operation.class +0 -0
  214. package/plugins/extract-java/build/org/portolan/extract/OpenApi$Spec.class +0 -0
  215. package/plugins/extract-java/build/org/portolan/extract/OpenApi.class +0 -0
  216. package/plugins/extract-java/build/org/portolan/extract/Operations$1.class +0 -0
  217. package/plugins/extract-java/build/org/portolan/extract/Operations$UseCase.class +0 -0
  218. package/plugins/extract-java/build/org/portolan/extract/Operations.class +0 -0
  219. package/plugins/extract-java/build/org/portolan/extract/Proto$Rpc.class +0 -0
  220. package/plugins/extract-java/build/org/portolan/extract/Proto$Service.class +0 -0
  221. package/plugins/extract-java/build/org/portolan/extract/Proto.class +0 -0
  222. package/plugins/extract-java/build/org/portolan/extract/Protocol$Builder.class +0 -0
  223. package/plugins/extract-java/build/org/portolan/extract/Protocol$Input.class +0 -0
  224. package/plugins/extract-java/build/org/portolan/extract/Protocol$Options.class +0 -0
  225. package/plugins/extract-java/build/org/portolan/extract/Protocol.class +0 -0
  226. package/plugins/extract-java/build/org/portolan/extract/Source$Project.class +0 -0
  227. package/plugins/extract-java/build/org/portolan/extract/Source$Unit.class +0 -0
  228. package/plugins/extract-java/build/org/portolan/extract/Source.class +0 -0
  229. package/plugins/extract-java/build/org/portolan/extract/Transport$Endpoint.class +0 -0
  230. package/plugins/extract-java/build/org/portolan/extract/Transport.class +0 -0
  231. package/plugins/extract-java/build/org/portolan/extract/Yaml$Line.class +0 -0
  232. package/plugins/extract-java/build/org/portolan/extract/Yaml$Reader.class +0 -0
  233. package/plugins/extract-java/build/org/portolan/extract/Yaml.class +0 -0
  234. package/plugins/extract-java/options.schema.json +70 -0
  235. package/plugins/extract-openapi/describe.go +19 -0
  236. package/plugins/extract-openapi/describe_test.go +11 -0
  237. package/plugins/extract-openapi/discover.go +243 -0
  238. package/plugins/extract-openapi/extract.go +526 -0
  239. package/plugins/extract-openapi/extract_test.go +545 -0
  240. package/plugins/extract-openapi/main.go +75 -0
  241. package/plugins/extract-openapi/options.schema.json +62 -0
  242. package/plugins/extract-openapi/spec.go +350 -0
  243. package/plugins/extract-project/README.md +22 -0
  244. package/plugins/extract-project/describe.go +19 -0
  245. package/plugins/extract-project/describe_test.go +11 -0
  246. package/plugins/extract-project/extract.go +221 -0
  247. package/plugins/extract-project/extract_test.go +109 -0
  248. package/plugins/extract-project/main.go +41 -0
  249. package/plugins/extract-project/options.schema.json +48 -0
  250. package/plugins/extract-proto/ast.go +125 -0
  251. package/plugins/extract-proto/consumes.go +77 -0
  252. package/plugins/extract-proto/describe.go +19 -0
  253. package/plugins/extract-proto/extract.go +293 -0
  254. package/plugins/extract-proto/extract_test.go +459 -0
  255. package/plugins/extract-proto/ids.go +89 -0
  256. package/plugins/extract-proto/ids_test.go +57 -0
  257. package/plugins/extract-proto/lex.go +285 -0
  258. package/plugins/extract-proto/main.go +100 -0
  259. package/plugins/extract-proto/module.go +120 -0
  260. package/plugins/extract-proto/options.schema.json +51 -0
  261. package/plugins/extract-proto/parse.go +720 -0
  262. package/plugins/extract-proto/parse_test.go +307 -0
  263. package/plugins/extract-proto/provides.go +236 -0
  264. package/plugins/extract-proto/resolve.go +222 -0
  265. package/plugins/extract-proto/resolve_test.go +119 -0
  266. package/plugins/extract-python-kafka/README.md +36 -0
  267. package/plugins/extract-python-kafka/extract.py +211 -0
  268. package/plugins/extract-python-kafka/extract_test.py +68 -0
  269. package/plugins/extract-python-kafka/main.py +59 -0
  270. package/plugins/extract-python-kafka/options.py +29 -0
  271. package/plugins/extract-python-kafka/options.schema.json +31 -0
  272. package/plugins/extract-redis/README.md +11 -0
  273. package/plugins/extract-redis/describe.go +19 -0
  274. package/plugins/extract-redis/describe_test.go +11 -0
  275. package/plugins/extract-redis/extract.go +183 -0
  276. package/plugins/extract-redis/extract_test.go +168 -0
  277. package/plugins/extract-redis/keyspaces.go +469 -0
  278. package/plugins/extract-redis/main.go +44 -0
  279. package/plugins/extract-redis/options.schema.json +30 -0
  280. package/plugins/extract-river/describe.go +19 -0
  281. package/plugins/extract-river/describe_test.go +11 -0
  282. package/plugins/extract-river/extract.go +507 -0
  283. package/plugins/extract-river/extract_test.go +132 -0
  284. package/plugins/extract-river/main.go +42 -0
  285. package/plugins/extract-river/options.schema.json +21 -0
  286. package/plugins/extract-rust/Cargo.lock +133 -0
  287. package/plugins/extract-rust/Cargo.toml +23 -0
  288. package/plugins/extract-rust/README.md +204 -0
  289. package/plugins/extract-rust/options.schema.json +65 -0
  290. package/plugins/extract-rust/rustfmt.toml +1 -0
  291. package/plugins/extract-sql/ddl.go +893 -0
  292. package/plugins/extract-sql/ddl_test.go +401 -0
  293. package/plugins/extract-sql/describe.go +19 -0
  294. package/plugins/extract-sql/describe_test.go +11 -0
  295. package/plugins/extract-sql/layout.go +221 -0
  296. package/plugins/extract-sql/layout_test.go +55 -0
  297. package/plugins/extract-sql/lineage.go +107 -0
  298. package/plugins/extract-sql/main.go +141 -0
  299. package/plugins/extract-sql/maps.go +564 -0
  300. package/plugins/extract-sql/maps_java.go +117 -0
  301. package/plugins/extract-sql/maps_rust.go +333 -0
  302. package/plugins/extract-sql/maps_rust_test.go +70 -0
  303. package/plugins/extract-sql/maps_test.go +204 -0
  304. package/plugins/extract-sql/maps_ts.go +398 -0
  305. package/plugins/extract-sql/maps_ts_test.go +136 -0
  306. package/plugins/extract-sql/options.schema.json +53 -0
  307. package/plugins/extract-sql/projection.go +70 -0
  308. package/plugins/extract-sql/projection_test.go +50 -0
  309. package/plugins/extract-sql/store.go +420 -0
  310. package/plugins/extract-sql/store_test.go +233 -0
  311. package/plugins/extract-sql/view.go +295 -0
  312. package/plugins/extract-ts/README.md +306 -0
  313. package/plugins/extract-ts/ast.test.ts +178 -0
  314. package/plugins/extract-ts/ast.ts +648 -0
  315. package/plugins/extract-ts/clients.ts +185 -0
  316. package/plugins/extract-ts/domain.ts +164 -0
  317. package/plugins/extract-ts/extract.test.ts +208 -0
  318. package/plugins/extract-ts/extract.ts +200 -0
  319. package/plugins/extract-ts/flows.ts +783 -0
  320. package/plugins/extract-ts/graphql.test.ts +73 -0
  321. package/plugins/extract-ts/graphql.ts +181 -0
  322. package/plugins/extract-ts/ids.test.ts +21 -0
  323. package/plugins/extract-ts/ids.ts +52 -0
  324. package/plugins/extract-ts/lifecycle.ts +138 -0
  325. package/plugins/extract-ts/main.ts +48 -0
  326. package/plugins/extract-ts/openapi.test.ts +64 -0
  327. package/plugins/extract-ts/openapi.ts +99 -0
  328. package/plugins/extract-ts/operations.ts +93 -0
  329. package/plugins/extract-ts/options.schema.json +96 -0
  330. package/plugins/extract-ts/source.test.ts +174 -0
  331. package/plugins/extract-ts/source.ts +465 -0
  332. package/plugins/extract-ts/transport.ts +147 -0
  333. package/plugins/extract-ts/tsconfig.json +13 -0
  334. package/plugins/extract-ts/wiring.ts +190 -0
  335. package/plugins/extract-watermill/describe.go +19 -0
  336. package/plugins/extract-watermill/describe_test.go +11 -0
  337. package/plugins/extract-watermill/extract.go +1228 -0
  338. package/plugins/extract-watermill/extract_test.go +234 -0
  339. package/plugins/extract-watermill/main.go +41 -0
  340. package/plugins/extract-watermill/options.schema.json +21 -0
  341. package/plugins/extract-wsdl/describe.go +19 -0
  342. package/plugins/extract-wsdl/describe_test.go +11 -0
  343. package/plugins/extract-wsdl/extract.go +148 -0
  344. package/plugins/extract-wsdl/extract_test.go +45 -0
  345. package/plugins/extract-wsdl/main.go +53 -0
  346. package/plugins/extract-wsdl/options.schema.json +59 -0
  347. package/plugins/fetch-bsr/auth.go +114 -0
  348. package/plugins/fetch-bsr/bsr.go +240 -0
  349. package/plugins/fetch-bsr/cache.go +66 -0
  350. package/plugins/fetch-bsr/describe.go +19 -0
  351. package/plugins/fetch-bsr/fetch.go +192 -0
  352. package/plugins/fetch-bsr/fetch_test.go +465 -0
  353. package/plugins/fetch-bsr/lock.go +71 -0
  354. package/plugins/fetch-bsr/main.go +117 -0
  355. package/plugins/fetch-bsr/options.schema.json +42 -0
  356. package/plugins/fetch-csr/auth.go +95 -0
  357. package/plugins/fetch-csr/cache.go +69 -0
  358. package/plugins/fetch-csr/describe.go +19 -0
  359. package/plugins/fetch-csr/describe_test.go +11 -0
  360. package/plugins/fetch-csr/fetch.go +254 -0
  361. package/plugins/fetch-csr/fetch_test.go +494 -0
  362. package/plugins/fetch-csr/lock.go +95 -0
  363. package/plugins/fetch-csr/main.go +122 -0
  364. package/plugins/fetch-csr/options.schema.json +42 -0
  365. package/plugins/fetch-csr/registry.go +209 -0
  366. package/plugins/fetch-git/cache.go +65 -0
  367. package/plugins/fetch-git/describe.go +19 -0
  368. package/plugins/fetch-git/describe_test.go +11 -0
  369. package/plugins/fetch-git/fetch.go +181 -0
  370. package/plugins/fetch-git/fetch_test.go +332 -0
  371. package/plugins/fetch-git/git.go +169 -0
  372. package/plugins/fetch-git/lock.go +72 -0
  373. package/plugins/fetch-git/main.go +127 -0
  374. package/plugins/fetch-git/offline.go +39 -0
  375. package/plugins/fetch-git/options.schema.json +42 -0
  376. package/plugins/fetch-git/pin.go +90 -0
  377. package/plugins/fetch-git/pin_test.go +74 -0
  378. package/plugins/gen-backstage/describe.go +17 -0
  379. package/plugins/gen-backstage/main.go +22 -0
  380. package/plugins/gen-backstage/options.schema.json +30 -0
  381. package/plugins/gen-backstage/plugin.go +473 -0
  382. package/plugins/gen-backstage/plugin_test.go +145 -0
  383. package/plugins/gen-backstage.wasm +0 -0
  384. package/plugins/gen-markdown/adr.go +162 -0
  385. package/plugins/gen-markdown/aggregate.go +362 -0
  386. package/plugins/gen-markdown/canonical.go +93 -0
  387. package/plugins/gen-markdown/context.go +90 -0
  388. package/plugins/gen-markdown/coverage_test.go +89 -0
  389. package/plugins/gen-markdown/describe.go +19 -0
  390. package/plugins/gen-markdown/describe_test.go +11 -0
  391. package/plugins/gen-markdown/external.go +71 -0
  392. package/plugins/gen-markdown/flow.go +277 -0
  393. package/plugins/gen-markdown/glossary.go +76 -0
  394. package/plugins/gen-markdown/glossary_test.go +148 -0
  395. package/plugins/gen-markdown/llms.go +302 -0
  396. package/plugins/gen-markdown/main.go +22 -0
  397. package/plugins/gen-markdown/markdown.go +254 -0
  398. package/plugins/gen-markdown/markdown_test.go +100 -0
  399. package/plugins/gen-markdown/module.go +107 -0
  400. package/plugins/gen-markdown/options.schema.json +16 -0
  401. package/plugins/gen-markdown/plugin.go +39 -0
  402. package/plugins/gen-markdown/quality_test.go +176 -0
  403. package/plugins/gen-markdown/redis_test.go +38 -0
  404. package/plugins/gen-markdown/render.go +344 -0
  405. package/plugins/gen-markdown/render_test.go +186 -0
  406. package/plugins/gen-markdown/service.go +456 -0
  407. package/plugins/gen-markdown/source.go +177 -0
  408. package/plugins/gen-markdown/store.go +201 -0
  409. package/plugins/gen-markdown.wasm +0 -0
  410. package/plugins/gen-mermaid/describe.go +17 -0
  411. package/plugins/gen-mermaid/main.go +22 -0
  412. package/plugins/gen-mermaid/options.schema.json +10 -0
  413. package/plugins/gen-mermaid/plugin.go +104 -0
  414. package/plugins/gen-mermaid/plugin_test.go +33 -0
  415. package/plugins/gen-mermaid.wasm +0 -0
  416. package/plugins/openapi/ids.go +261 -0
  417. package/plugins/openapi/ids_test.go +98 -0
  418. package/plugins/pyplugin/catalog.py +209 -0
  419. package/plugins/pyplugin/celery_conf.py +436 -0
  420. package/plugins/pyplugin/celery_tasks.py +76 -0
  421. package/plugins/pyplugin/kafka.py +570 -0
  422. package/plugins/pyplugin/names.py +38 -0
  423. package/plugins/pyplugin/protocol.py +79 -0
  424. package/plugins/pyplugin/source.py +285 -0
  425. package/plugins/verify-codeowners/describe.go +19 -0
  426. package/plugins/verify-codeowners/describe_test.go +11 -0
  427. package/plugins/verify-codeowners/main.go +75 -0
  428. package/plugins/verify-codeowners/match.go +85 -0
  429. package/plugins/verify-codeowners/match_test.go +47 -0
  430. package/plugins/verify-codeowners/options.schema.json +15 -0
  431. package/plugins/verify-codeowners/owners.go +164 -0
  432. package/plugins/verify-codeowners/owners_test.go +225 -0
  433. package/plugins/verify-codeowners/parse.go +90 -0
  434. package/plugins/verify-codeowners/parse_test.go +62 -0
  435. package/plugins/verify-otel/describe.go +19 -0
  436. package/plugins/verify-otel/describe_test.go +11 -0
  437. package/plugins/verify-otel/main.go +53 -0
  438. package/plugins/verify-otel/match.go +336 -0
  439. package/plugins/verify-otel/options.schema.json +30 -0
  440. package/plugins/verify-otel/otlp.go +200 -0
  441. package/plugins/verify-otel/verify.go +734 -0
  442. package/plugins/verify-otel/verify_test.go +460 -0
  443. package/portolan.json +1073 -0
  444. package/public/favicon.svg +12 -0
  445. package/schema/portolan.schema.json +2558 -0
  446. package/scripts/README.md +53 -0
  447. package/scripts/build-report.mjs +60 -0
  448. package/scripts/build-report.test.mjs +44 -0
  449. package/scripts/builtin-plugins.mjs +49 -0
  450. package/scripts/catalog-sources.mjs +67 -0
  451. package/scripts/diff.mjs +315 -0
  452. package/scripts/diff.test.mjs +151 -0
  453. package/scripts/forge-comment.mjs +144 -0
  454. package/scripts/forge-comment.test.mjs +151 -0
  455. package/scripts/forge-release.mjs +138 -0
  456. package/scripts/forge-release.test.mjs +106 -0
  457. package/scripts/forge.mjs +61 -0
  458. package/scripts/gen-likec4.mjs +854 -0
  459. package/scripts/gen-likec4.test.mjs +258 -0
  460. package/scripts/gen.mjs +603 -0
  461. package/scripts/generated-docs.test.mjs +66 -0
  462. package/scripts/local-api.mjs +1192 -0
  463. package/scripts/local-api.test.mjs +387 -0
  464. package/scripts/manifest.mjs +214 -0
  465. package/scripts/manifest.test.mjs +148 -0
  466. package/scripts/output-path.mjs +79 -0
  467. package/scripts/output-path.test.mjs +45 -0
  468. package/scripts/package-smoke.mjs +37 -0
  469. package/scripts/plugin-host.mjs +419 -0
  470. package/scripts/plugin-host.test.mjs +109 -0
  471. package/scripts/plugin-wasm-worker.mjs +34 -0
  472. package/scripts/run-builtin.mjs +81 -0
  473. package/scripts/schema.mjs +357 -0
  474. package/scripts/site-docs.mjs +295 -0
  475. package/scripts/site-docs.test.mjs +181 -0
  476. package/scripts/vendor-lock.mjs +58 -0
  477. package/scripts/vendor-lock.test.mjs +69 -0
  478. package/src/README.md +38 -0
  479. package/src/app/App.tsx +448 -0
  480. package/src/app/BranchPicker.test.ts +46 -0
  481. package/src/app/BranchPicker.tsx +153 -0
  482. package/src/app/Breadcrumbs.test.ts +38 -0
  483. package/src/app/Breadcrumbs.tsx +223 -0
  484. package/src/app/BuildStamp.tsx +146 -0
  485. package/src/app/CommandPalette.tsx +292 -0
  486. package/src/app/HashScroll.tsx +45 -0
  487. package/src/app/Sidebar.tsx +1742 -0
  488. package/src/app/TopBar.tsx +393 -0
  489. package/src/app/density.tsx +64 -0
  490. package/src/app/forge-access.test.ts +27 -0
  491. package/src/app/forge-access.tsx +80 -0
  492. package/src/app/panels.tsx +141 -0
  493. package/src/app/pins.tsx +242 -0
  494. package/src/app/query-client.ts +24 -0
  495. package/src/app/responsive.ts +55 -0
  496. package/src/app/shortcuts.test.ts +39 -0
  497. package/src/app/shortcuts.tsx +282 -0
  498. package/src/app/theme.tsx +51 -0
  499. package/src/app/title.test.ts +14 -0
  500. package/src/app/title.ts +30 -0
  501. package/src/app/toast.tsx +59 -0
  502. package/src/app/tree-keys.test.ts +80 -0
  503. package/src/app/tree-keys.ts +87 -0
  504. package/src/app/ui-store.ts +52 -0
  505. package/src/catalog-error.test.ts +105 -0
  506. package/src/catalog-profile.test.ts +59 -0
  507. package/src/catalog-profile.ts +101 -0
  508. package/src/catalog-stores.test.ts +431 -0
  509. package/src/catalog.test.ts +1215 -0
  510. package/src/catalog.ts +3125 -0
  511. package/src/chat/Cards.tsx +408 -0
  512. package/src/chat/ChatPanel.tsx +79 -0
  513. package/src/chat/ChatSettings.tsx +219 -0
  514. package/src/chat/Composer.tsx +99 -0
  515. package/src/chat/Conversation.tsx +281 -0
  516. package/src/chat/Header.tsx +46 -0
  517. package/src/chat/Message.tsx +49 -0
  518. package/src/chat/Notice.tsx +195 -0
  519. package/src/chat/Starter.tsx +67 -0
  520. package/src/chat/Steps.tsx +45 -0
  521. package/src/chat/Waiting.tsx +87 -0
  522. package/src/chat/flags.test.ts +59 -0
  523. package/src/chat/flags.ts +155 -0
  524. package/src/chat/linkify.test.ts +30 -0
  525. package/src/chat/linkify.ts +45 -0
  526. package/src/chat/prefs.ts +56 -0
  527. package/src/chat/prompt.test.ts +43 -0
  528. package/src/chat/prompt.ts +157 -0
  529. package/src/chat/store.ts +35 -0
  530. package/src/chat/tools.ts +58 -0
  531. package/src/chat/transport.ts +70 -0
  532. package/src/components/AdrRow.tsx +29 -0
  533. package/src/components/AnchorLink.tsx +67 -0
  534. package/src/components/ApiReference.tsx +134 -0
  535. package/src/components/AsyncApiReference.tsx +120 -0
  536. package/src/components/CatalogStamp.tsx +155 -0
  537. package/src/components/ChannelRows.tsx +132 -0
  538. package/src/components/CommandRows.tsx +139 -0
  539. package/src/components/DiagramSkeleton.tsx +71 -0
  540. package/src/components/EditorLink.tsx +85 -0
  541. package/src/components/FieldTree.tsx +305 -0
  542. package/src/components/FlowTrigger.tsx +34 -0
  543. package/src/components/Ident.tsx +89 -0
  544. package/src/components/Integrations.tsx +243 -0
  545. package/src/components/LifecycleDiagram.tsx +110 -0
  546. package/src/components/MachineDocs.tsx +42 -0
  547. package/src/components/Markdown.tsx +173 -0
  548. package/src/components/MarkdownTable.tsx +206 -0
  549. package/src/components/Mermaid.tsx +211 -0
  550. package/src/components/MethodRows.tsx +309 -0
  551. package/src/components/Overlay.tsx +125 -0
  552. package/src/components/PageHeader.tsx +189 -0
  553. package/src/components/RowActions.tsx +97 -0
  554. package/src/components/SchemaDocument.tsx +89 -0
  555. package/src/components/Select.tsx +126 -0
  556. package/src/components/ShapeRows.tsx +118 -0
  557. package/src/components/SourceDoc.tsx +82 -0
  558. package/src/components/SourcePreview.tsx +441 -0
  559. package/src/components/TabRow.tsx +182 -0
  560. package/src/components/TechIcon.tsx +34 -0
  561. package/src/components/Toc.tsx +132 -0
  562. package/src/components/WhatLinksHere.tsx +273 -0
  563. package/src/components/WsdlReference.tsx +84 -0
  564. package/src/components/ddd-icons.tsx +107 -0
  565. package/src/components/kind.tsx +157 -0
  566. package/src/components/logo.tsx +61 -0
  567. package/src/components/primitives.tsx +264 -0
  568. package/src/data.test.ts +18 -0
  569. package/src/data.ts +202 -0
  570. package/src/enrich.test.ts +1150 -0
  571. package/src/enrich.ts +672 -0
  572. package/src/er/ErCanvas.tsx +533 -0
  573. package/src/er/RedisSchema.tsx +74 -0
  574. package/src/er/RelationCard.tsx +267 -0
  575. package/src/er/StoreHeader.tsx +155 -0
  576. package/src/er/TableNode.tsx +84 -0
  577. package/src/er/ViewNode.tsx +83 -0
  578. package/src/er/layout.test.ts +115 -0
  579. package/src/er/layout.ts +77 -0
  580. package/src/er/lineage.test.ts +140 -0
  581. package/src/er/lineage.ts +107 -0
  582. package/src/er/markers.tsx +79 -0
  583. package/src/er/spec.test.ts +344 -0
  584. package/src/er/spec.ts +426 -0
  585. package/src/flow/ChainList.tsx +162 -0
  586. package/src/flow/FlowTable.tsx +123 -0
  587. package/src/flow/FlowToolbar.tsx +372 -0
  588. package/src/flow/StepDetail.tsx +380 -0
  589. package/src/flow/StepRail.tsx +428 -0
  590. package/src/flow/answers.test.ts +50 -0
  591. package/src/flow/answers.ts +58 -0
  592. package/src/flow/chain.test.ts +383 -0
  593. package/src/flow/chain.ts +353 -0
  594. package/src/flow/chapters.test.ts +185 -0
  595. package/src/flow/chapters.ts +225 -0
  596. package/src/flow/continues.test.ts +102 -0
  597. package/src/flow/continues.ts +65 -0
  598. package/src/flow/cross-context.test.ts +97 -0
  599. package/src/flow/cross-context.ts +35 -0
  600. package/src/flow/mermaid.test.ts +22 -0
  601. package/src/flow/mermaid.ts +141 -0
  602. package/src/flow/outline.test.ts +212 -0
  603. package/src/flow/outline.ts +170 -0
  604. package/src/flow/paths.test.ts +129 -0
  605. package/src/flow/paths.ts +147 -0
  606. package/src/flow/prefs.test.ts +80 -0
  607. package/src/flow/prefs.ts +104 -0
  608. package/src/graph/DependencyGraph.tsx +283 -0
  609. package/src/graph/DependencyNodes.tsx +162 -0
  610. package/src/graph/EdgeLabel.tsx +61 -0
  611. package/src/graph/FocusedEventGraph.tsx +211 -0
  612. package/src/graph/GraphToolbar.tsx +187 -0
  613. package/src/graph/RoutedEdge.tsx +80 -0
  614. package/src/graph/dependency-layout.test.ts +360 -0
  615. package/src/graph/dependency-layout.ts +444 -0
  616. package/src/graph/elk.test.ts +70 -0
  617. package/src/graph/elk.ts +287 -0
  618. package/src/graph/nodes.tsx +97 -0
  619. package/src/graph/theme.ts +81 -0
  620. package/src/graph/useElkFlow.ts +125 -0
  621. package/src/index.css +1547 -0
  622. package/src/language/InLanguage.tsx +40 -0
  623. package/src/language/TermCard.tsx +132 -0
  624. package/src/language/cards.test.ts +114 -0
  625. package/src/language/cards.ts +111 -0
  626. package/src/lib/admonition.test.ts +49 -0
  627. package/src/lib/admonition.ts +48 -0
  628. package/src/lib/adr.test.ts +131 -0
  629. package/src/lib/adr.ts +68 -0
  630. package/src/lib/api.test.ts +122 -0
  631. package/src/lib/api.ts +135 -0
  632. package/src/lib/backlinks.test.ts +330 -0
  633. package/src/lib/backlinks.ts +567 -0
  634. package/src/lib/branch-compare.ts +16 -0
  635. package/src/lib/build-info.test.ts +76 -0
  636. package/src/lib/build-info.ts +80 -0
  637. package/src/lib/catalog-diff.test.ts +275 -0
  638. package/src/lib/catalog-diff.ts +655 -0
  639. package/src/lib/clipboard.ts +43 -0
  640. package/src/lib/comparison-memory.test.ts +40 -0
  641. package/src/lib/comparison-memory.ts +39 -0
  642. package/src/lib/context-color.ts +27 -0
  643. package/src/lib/context-map.test.ts +148 -0
  644. package/src/lib/context-map.ts +399 -0
  645. package/src/lib/data-model.test.ts +245 -0
  646. package/src/lib/data-model.ts +399 -0
  647. package/src/lib/data-problems.test.ts +178 -0
  648. package/src/lib/data-problems.ts +314 -0
  649. package/src/lib/derive.test.ts +251 -0
  650. package/src/lib/derive.ts +515 -0
  651. package/src/lib/editor-link.test.ts +125 -0
  652. package/src/lib/editor-link.ts +96 -0
  653. package/src/lib/editor-prefs.ts +27 -0
  654. package/src/lib/event-graph.test.ts +237 -0
  655. package/src/lib/event-graph.ts +327 -0
  656. package/src/lib/export-canvas.ts +37 -0
  657. package/src/lib/export-file.test.ts +30 -0
  658. package/src/lib/export-file.ts +20 -0
  659. package/src/lib/flow-tree.test.ts +177 -0
  660. package/src/lib/flow-tree.ts +160 -0
  661. package/src/lib/forge-refs.test.ts +50 -0
  662. package/src/lib/forge-refs.ts +60 -0
  663. package/src/lib/format.test.ts +35 -0
  664. package/src/lib/format.ts +64 -0
  665. package/src/lib/github-catalog.test.ts +301 -0
  666. package/src/lib/github-catalog.ts +610 -0
  667. package/src/lib/integrations.test.ts +119 -0
  668. package/src/lib/integrations.ts +133 -0
  669. package/src/lib/kinds.test.ts +91 -0
  670. package/src/lib/kinds.ts +204 -0
  671. package/src/lib/lifecycle.test.ts +93 -0
  672. package/src/lib/lifecycle.ts +165 -0
  673. package/src/lib/local-api.ts +194 -0
  674. package/src/lib/motion-features.ts +11 -0
  675. package/src/lib/motion.test.ts +120 -0
  676. package/src/lib/motion.tsx +269 -0
  677. package/src/lib/palette-recent.test.ts +80 -0
  678. package/src/lib/palette-recent.ts +90 -0
  679. package/src/lib/palette.test.ts +365 -0
  680. package/src/lib/palette.ts +593 -0
  681. package/src/lib/pins.test.ts +139 -0
  682. package/src/lib/pins.ts +130 -0
  683. package/src/lib/problems.test.ts +112 -0
  684. package/src/lib/project-preview.ts +5 -0
  685. package/src/lib/proto-problems.test.ts +121 -0
  686. package/src/lib/proto-problems.ts +65 -0
  687. package/src/lib/queries.test.ts +113 -0
  688. package/src/lib/queries.ts +131 -0
  689. package/src/lib/registry.test.ts +219 -0
  690. package/src/lib/registry.ts +208 -0
  691. package/src/lib/scenarios.ts +547 -0
  692. package/src/lib/setup-info.test.ts +199 -0
  693. package/src/lib/setup-info.ts +415 -0
  694. package/src/lib/shape.test.ts +289 -0
  695. package/src/lib/shape.ts +454 -0
  696. package/src/lib/sidebar-prefs.test.ts +32 -0
  697. package/src/lib/sidebar-prefs.ts +75 -0
  698. package/src/lib/source-code.test.ts +159 -0
  699. package/src/lib/source-code.ts +286 -0
  700. package/src/lib/source-doc.test.ts +131 -0
  701. package/src/lib/source-doc.ts +103 -0
  702. package/src/lib/source-highlight.test.ts +29 -0
  703. package/src/lib/source-highlight.ts +24 -0
  704. package/src/lib/source-link.test.ts +153 -0
  705. package/src/lib/source-link.ts +201 -0
  706. package/src/lib/spec-files.test.ts +24 -0
  707. package/src/lib/spec-files.ts +23 -0
  708. package/src/lib/table-directive.test.ts +139 -0
  709. package/src/lib/table-directive.ts +106 -0
  710. package/src/lib/tech.test.ts +120 -0
  711. package/src/lib/tech.ts +421 -0
  712. package/src/lib/terms.test.ts +67 -0
  713. package/src/lib/terms.ts +179 -0
  714. package/src/lib/wire-problems.test.ts +263 -0
  715. package/src/lib/wire-problems.ts +281 -0
  716. package/src/likec4/C4View.tsx +55 -0
  717. package/src/likec4/CanvasBridge.tsx +187 -0
  718. package/src/likec4/FlowView.tsx +235 -0
  719. package/src/likec4/InteractiveView.tsx +144 -0
  720. package/src/likec4/canvas-viewport.test.ts +149 -0
  721. package/src/likec4/canvas-viewport.ts +135 -0
  722. package/src/likec4/flow-edges.test.ts +51 -0
  723. package/src/likec4/flow-edges.ts +89 -0
  724. package/src/likec4/frame-theme.test.ts +76 -0
  725. package/src/likec4/frame-theme.ts +101 -0
  726. package/src/likec4/highlight-css.test.ts +49 -0
  727. package/src/likec4/highlight-css.ts +52 -0
  728. package/src/likec4/ids.test.ts +151 -0
  729. package/src/likec4/ids.ts +115 -0
  730. package/src/likec4/levels.tsx +70 -0
  731. package/src/likec4/mapping.test.ts +66 -0
  732. package/src/likec4/mapping.ts +54 -0
  733. package/src/likec4/reserved.json +141 -0
  734. package/src/likec4/view-index.ts +78 -0
  735. package/src/main.tsx +13 -0
  736. package/src/map/ContextMapGraph.tsx +274 -0
  737. package/src/map/ContextNode.tsx +70 -0
  738. package/src/map/FloatingEdge.tsx +86 -0
  739. package/src/merge.test.ts +1038 -0
  740. package/src/merge.ts +1004 -0
  741. package/src/pages/AdrDetail.tsx +242 -0
  742. package/src/pages/AdrIndex.tsx +114 -0
  743. package/src/pages/AggregatePage.tsx +727 -0
  744. package/src/pages/BlockPage.tsx +478 -0
  745. package/src/pages/CatalogFailure.tsx +111 -0
  746. package/src/pages/Changes.tsx +313 -0
  747. package/src/pages/ContextMap.tsx +534 -0
  748. package/src/pages/ContextPage.tsx +346 -0
  749. package/src/pages/EnumPage.tsx +282 -0
  750. package/src/pages/EventPage.tsx +686 -0
  751. package/src/pages/ExternalPage.tsx +204 -0
  752. package/src/pages/FlowDetail.tsx +663 -0
  753. package/src/pages/FlowIndex.tsx +303 -0
  754. package/src/pages/GraphPage.tsx +217 -0
  755. package/src/pages/Language.tsx +257 -0
  756. package/src/pages/ModulePage.tsx +366 -0
  757. package/src/pages/NotFound.tsx +54 -0
  758. package/src/pages/Overview.tsx +344 -0
  759. package/src/pages/Problems.tsx +360 -0
  760. package/src/pages/RegistryIndex.tsx +118 -0
  761. package/src/pages/ServicePage.tsx +746 -0
  762. package/src/pages/Settings.tsx +975 -0
  763. package/src/pages/StorePage.tsx +114 -0
  764. package/src/peek/PeekCard.test.ts +35 -0
  765. package/src/peek/PeekCard.tsx +118 -0
  766. package/src/peek/PeekLayer.tsx +147 -0
  767. package/src/peek/model.test.ts +156 -0
  768. package/src/peek/model.ts +253 -0
  769. package/src/routes.test.ts +222 -0
  770. package/src/routes.ts +449 -0
  771. package/src/selection/DetailPanel.tsx +1407 -0
  772. package/src/selection/hash.test.ts +73 -0
  773. package/src/selection/hash.ts +58 -0
  774. package/src/selection/model.test.ts +199 -0
  775. package/src/selection/model.ts +473 -0
  776. package/src/selection/pages.test.ts +115 -0
  777. package/src/selection/pages.ts +268 -0
  778. package/src/selection/store.test.ts +62 -0
  779. package/src/selection/store.ts +46 -0
  780. package/src/selection/sync.tsx +99 -0
  781. package/src/table/ColumnsMenu.tsx +72 -0
  782. package/src/table/DataTable.tsx +780 -0
  783. package/src/table/Facets.tsx +54 -0
  784. package/src/table/GroupMenu.tsx +69 -0
  785. package/src/table/Toolbar.tsx +190 -0
  786. package/src/table/cells.tsx +117 -0
  787. package/src/table/compare.test.ts +117 -0
  788. package/src/table/compare.ts +196 -0
  789. package/src/table/export.test.ts +88 -0
  790. package/src/table/export.ts +66 -0
  791. package/src/table/facet-groups.test.ts +74 -0
  792. package/src/table/facet-groups.ts +56 -0
  793. package/src/table/grouping.test.ts +84 -0
  794. package/src/table/grouping.ts +82 -0
  795. package/src/table/infer.test.ts +57 -0
  796. package/src/table/infer.ts +50 -0
  797. package/src/table/persist.test.ts +76 -0
  798. package/src/table/persist.ts +112 -0
  799. package/src/table/sort-url.test.ts +75 -0
  800. package/src/table/sort-url.ts +52 -0
  801. package/src/table/types.ts +80 -0
  802. package/src/table/useTableState.ts +220 -0
  803. package/src/test-catalog.ts +7 -0
  804. package/src/testing/estate/data__catalog.json +2847 -0
  805. package/src/testing/estate/data__flows.json +1724 -0
  806. package/src/testing/estate/examples__auth__portolan__api.json +212 -0
  807. package/src/testing/estate/examples__auth__portolan__domain.json +1204 -0
  808. package/src/testing/estate/examples__auth__portolan__glossary.json +226 -0
  809. package/src/testing/estate/examples__auth__portolan__observed.json +757 -0
  810. package/src/testing/estate/examples__auth__portolan__stores.json +195 -0
  811. package/src/testing/estate/examples__shop__cart__portolan__api.json +234 -0
  812. package/src/testing/estate/examples__shop__cart__portolan__commands.json +86 -0
  813. package/src/testing/estate/examples__shop__cart__portolan__domain.json +966 -0
  814. package/src/testing/estate/examples__shop__cart__portolan__observed.json +498 -0
  815. package/src/testing/estate/examples__shop__cart__portolan__stores.json +208 -0
  816. package/src/testing/estate/examples__shop__oms__portolan__glossary.json +98 -0
  817. package/src/testing/estate/examples__shop__oms__portolan__proto.json +186 -0
  818. package/src/testing/estate.ts +49 -0
  819. package/src/trail/Trail.tsx +81 -0
  820. package/src/trail/model.test.ts +157 -0
  821. package/src/trail/model.ts +189 -0
  822. package/src/trail/record.tsx +32 -0
  823. package/src/trail/store.test.ts +66 -0
  824. package/src/trail/store.ts +102 -0
  825. package/tsconfig.json +35 -0
  826. package/vite.config.ts +171 -0
@@ -0,0 +1,287 @@
1
+ // elkjs layout for everything React Flow renders. Async by nature, so callers
2
+ // hold the result in state; nothing here touches React.
3
+ //
4
+ // elk does not just place the boxes. It also ROUTES the lines, and that
5
+ // routing is the reason elk is in the stack at all: a bezier drawn between two
6
+ // node centres knows nothing about the third node it passes through, and on a
7
+ // layered graph it will pass through one. So the sections elk returns come
8
+ // back with the positions, and the canvas draws those rather than a curve of
9
+ // its own invention.
10
+
11
+ import ELK from "elkjs/lib/elk.bundled.js";
12
+ import type { ElkNode, ElkExtendedEdge } from "elkjs/lib/elk-api";
13
+
14
+ const elk = new ELK();
15
+
16
+ export interface Point {
17
+ x: number;
18
+ y: number;
19
+ }
20
+
21
+ export interface LayoutInput {
22
+ nodes: { id: string; width: number; height: number }[];
23
+ edges: { id: string; source: string; target: string; labelWidth?: number }[];
24
+ direction?: "RIGHT" | "DOWN";
25
+ /** extra space between layers; the focused graph wants more than the big one */
26
+ layerSpacing?: number;
27
+ nodeSpacing?: number;
28
+ /**
29
+ * "layered" is a flow: it reads left to right and every edge is a step. The
30
+ * context map is not a flow - it is a map, its edges run both ways, and a
31
+ * layered pass would put a third domain in the middle of the line between
32
+ * the other two. "stress" spreads the nodes in two dimensions instead, and
33
+ * `edgeLength` is how far apart it tries to hold them.
34
+ */
35
+ algorithm?: "layered" | "stress";
36
+ edgeLength?: number;
37
+ /**
38
+ * Give every node one WEST input port and one EAST output port, pinned to
39
+ * those sides. Without it elk is free to attach a line anywhere on the
40
+ * boundary, and a line leaving the top-left corner of a box that is laid out
41
+ * left-to-right reads as a mistake even when the routing is optimal.
42
+ */
43
+ ports?: boolean;
44
+ /**
45
+ * How the lines are drawn. ORTHOGONAL is right angles, which is what a
46
+ * bundled service-to-service edge wants; SPLINES is smooth, which is what a
47
+ * graph with a node between every pair of services wants.
48
+ */
49
+ edgeRouting?: "ORTHOGONAL" | "SPLINES" | "POLYLINE";
50
+ /**
51
+ * How the layers are packed vertically.
52
+ *
53
+ * NETWORK_SIMPLEX is the best answer and by far the most expensive one: it
54
+ * solves for straight edges rather than approximating, and past roughly a
55
+ * hundred nodes-and-edges it goes from milliseconds to seconds. Callers big
56
+ * enough to feel that ask for BRANDES_KOEPF instead, which is the same
57
+ * family of answer computed by heuristic.
58
+ */
59
+ nodePlacement?: "NETWORK_SIMPLEX" | "BRANDES_KOEPF";
60
+ /**
61
+ * How hard elk works at crossing minimisation. elk's own default is 7; the
62
+ * only reason to lower it is a graph too big to afford the default.
63
+ */
64
+ thoroughness?: number;
65
+ /**
66
+ * Break layer ties by the order the caller listed the nodes in. It is what
67
+ * puts an event pill at the height of the service that emits it: the events
68
+ * are listed in publisher order, so within their layer they end up in
69
+ * publisher order too.
70
+ */
71
+ considerModelOrder?: boolean;
72
+ }
73
+
74
+ export interface LayoutResult {
75
+ positions: Record<string, Point>;
76
+ /**
77
+ * Edge id -> the points elk routed it through, start first and end last.
78
+ * Empty for an edge elk chose not to route (it does that for edges it hides
79
+ * inside a self-loop, which this app never asks it to draw).
80
+ */
81
+ routes: Record<string, Point[]>;
82
+ width: number;
83
+ height: number;
84
+ }
85
+
86
+ const IN = (id: string): string => `${id}::in`;
87
+ const OUT = (id: string): string => `${id}::out`;
88
+
89
+ export async function layoutWithElk(input: LayoutInput): Promise<LayoutResult> {
90
+ const children: ElkNode[] = input.nodes.map((n) => ({
91
+ id: n.id,
92
+ width: n.width,
93
+ height: n.height,
94
+ ...(input.ports
95
+ ? {
96
+ layoutOptions: { "elk.portConstraints": "FIXED_SIDE" },
97
+ ports: [
98
+ {
99
+ id: IN(n.id),
100
+ width: 1,
101
+ height: 1,
102
+ layoutOptions: { "elk.port.side": "WEST" },
103
+ },
104
+ {
105
+ id: OUT(n.id),
106
+ width: 1,
107
+ height: 1,
108
+ layoutOptions: { "elk.port.side": "EAST" },
109
+ },
110
+ ],
111
+ }
112
+ : {}),
113
+ }));
114
+
115
+ const edges: ElkExtendedEdge[] = input.edges.map((e) => ({
116
+ id: e.id,
117
+ sources: [input.ports ? OUT(e.source) : e.source],
118
+ targets: [input.ports ? IN(e.target) : e.target],
119
+ ...(e.labelWidth
120
+ ? { labels: [{ text: "", width: e.labelWidth, height: 14 }] }
121
+ : {}),
122
+ }));
123
+
124
+ const stress = input.algorithm === "stress";
125
+ const graph: ElkNode = {
126
+ id: "root",
127
+ layoutOptions: stress
128
+ ? {
129
+ "elk.algorithm": "stress",
130
+ "elk.stress.desiredEdgeLength": String(input.edgeLength ?? 320),
131
+ "elk.spacing.nodeNode": String(input.nodeSpacing ?? 60),
132
+ "elk.padding": "[top=16,left=16,bottom=16,right=16]",
133
+ }
134
+ : {
135
+ "elk.algorithm": "layered",
136
+ "elk.direction": input.direction ?? "RIGHT",
137
+ // Every node is a peer; nothing here nests, so there are no children
138
+ // to lay out inside a parent.
139
+ "elk.hierarchyHandling": "SEPARATE_CHILDREN",
140
+ "elk.layered.spacing.nodeNodeBetweenLayers": String(
141
+ input.layerSpacing ?? 130,
142
+ ),
143
+ "elk.spacing.nodeNode": String(input.nodeSpacing ?? 34),
144
+ "elk.layered.spacing.edgeNodeBetweenLayers": "24",
145
+ "elk.spacing.edgeLabel": "6",
146
+ "elk.layered.nodePlacement.strategy":
147
+ input.nodePlacement ?? "NETWORK_SIMPLEX",
148
+ ...(input.thoroughness
149
+ ? { "elk.layered.thoroughness": String(input.thoroughness) }
150
+ : {}),
151
+ "elk.layered.crossingMinimization.semiInteractive": "true",
152
+ ...(input.considerModelOrder
153
+ ? {
154
+ "elk.layered.considerModelOrder.strategy": "NODES_AND_EDGES",
155
+ }
156
+ : {}),
157
+ ...(input.edgeRouting
158
+ ? { "elk.edgeRouting": input.edgeRouting }
159
+ : {}),
160
+ "elk.padding": "[top=16,left=16,bottom=16,right=16]",
161
+ },
162
+ children,
163
+ edges,
164
+ };
165
+
166
+ const laid = await elk.layout(graph);
167
+ const positions: Record<string, Point> = {};
168
+ for (const child of laid.children ?? []) {
169
+ positions[child.id] = { x: child.x ?? 0, y: child.y ?? 0 };
170
+ }
171
+
172
+ const routes: Record<string, Point[]> = {};
173
+ for (const edge of (laid.edges ?? []) as ElkExtendedEdge[]) {
174
+ const points: Point[] = [];
175
+ for (const section of edge.sections ?? []) {
176
+ // Sections chain: the end of one is the start of the next, so the shared
177
+ // point is written once.
178
+ if (points.length === 0) points.push(section.startPoint);
179
+ for (const bend of section.bendPoints ?? []) points.push(bend);
180
+ points.push(section.endPoint);
181
+ }
182
+ if (points.length > 0) routes[edge.id] = points;
183
+ }
184
+
185
+ return {
186
+ positions,
187
+ routes,
188
+ width: laid.width ?? 0,
189
+ height: laid.height ?? 0,
190
+ };
191
+ }
192
+
193
+ // ---------------------------------------------------------------------------
194
+ // Drawing what elk answered
195
+ // ---------------------------------------------------------------------------
196
+
197
+ /**
198
+ * A polyline through `points` with its corners rounded off.
199
+ *
200
+ * The radius shrinks to fit: a corner between two short segments gets a small
201
+ * arc rather than one that overshoots into the segment after it, which is what
202
+ * turns a tidy orthogonal route into a knot at exactly the places where the
203
+ * route is densest.
204
+ */
205
+ export function roundedPath(points: readonly Point[], radius = 10): string {
206
+ if (points.length === 0) return "";
207
+ const first = points[0];
208
+ if (!first) return "";
209
+ if (points.length === 1) return `M ${first.x},${first.y}`;
210
+
211
+ let d = `M ${first.x},${first.y}`;
212
+ for (let i = 1; i < points.length - 1; i += 1) {
213
+ const prev = points[i - 1];
214
+ const corner = points[i];
215
+ const next = points[i + 1];
216
+ if (!prev || !corner || !next) continue;
217
+
218
+ const inLen = Math.hypot(corner.x - prev.x, corner.y - prev.y);
219
+ const outLen = Math.hypot(next.x - corner.x, next.y - corner.y);
220
+ const r = Math.min(radius, inLen / 2, outLen / 2);
221
+ if (r < 0.5) {
222
+ d += ` L ${corner.x},${corner.y}`;
223
+ continue;
224
+ }
225
+ const start = lerp(corner, prev, r / inLen);
226
+ const end = lerp(corner, next, r / outLen);
227
+ d += ` L ${start.x},${start.y} Q ${corner.x},${corner.y} ${end.x},${end.y}`;
228
+ }
229
+ const last = points[points.length - 1];
230
+ if (last) d += ` L ${last.x},${last.y}`;
231
+ return d;
232
+ }
233
+
234
+ function lerp(from: Point, to: Point, t: number): Point {
235
+ return { x: from.x + (to.x - from.x) * t, y: from.y + (to.y - from.y) * t };
236
+ }
237
+
238
+ /** The point half way along a polyline, where a chip or a label goes. */
239
+ export function midpoint(points: readonly Point[]): Point {
240
+ if (points.length === 0) return { x: 0, y: 0 };
241
+ const head = points[0];
242
+ if (!head) return { x: 0, y: 0 };
243
+ if (points.length === 1) return head;
244
+
245
+ let total = 0;
246
+ for (let i = 1; i < points.length; i += 1) {
247
+ const a = points[i - 1];
248
+ const b = points[i];
249
+ if (a && b) total += Math.hypot(b.x - a.x, b.y - a.y);
250
+ }
251
+ let walked = 0;
252
+ for (let i = 1; i < points.length; i += 1) {
253
+ const a = points[i - 1];
254
+ const b = points[i];
255
+ if (!a || !b) continue;
256
+ const len = Math.hypot(b.x - a.x, b.y - a.y);
257
+ if (walked + len >= total / 2) {
258
+ const t = len === 0 ? 0 : (total / 2 - walked) / len;
259
+ return lerp(a, b, t);
260
+ }
261
+ walked += len;
262
+ }
263
+ return points[points.length - 1] ?? head;
264
+ }
265
+
266
+ /**
267
+ * Moves the interior of a route sideways, leaving its ends on their ports.
268
+ *
269
+ * Two services that publish to each other get two lines through the same
270
+ * corridor. elk routes them apart when it can and on top of each other when it
271
+ * cannot; nudging one up and the other down guarantees the reader sees two
272
+ * lines whichever elk chose, and keeping the endpoints pinned means neither
273
+ * line detaches from the box it belongs to.
274
+ */
275
+ export function offsetInterior(points: readonly Point[], dy: number): Point[] {
276
+ if (points.length <= 2) {
277
+ // A straight run has no interior to move, so it grows one: a single
278
+ // waypoint at the middle, offset, which bows the line clear of its twin.
279
+ const a = points[0];
280
+ const b = points[1];
281
+ if (!a || !b) return [...points];
282
+ return [a, { x: (a.x + b.x) / 2, y: (a.y + b.y) / 2 + dy }, b];
283
+ }
284
+ return points.map((p, i) =>
285
+ i === 0 || i === points.length - 1 ? p : { x: p.x, y: p.y + dy },
286
+ );
287
+ }
@@ -0,0 +1,97 @@
1
+ import { Handle, Position } from "@xyflow/react";
2
+ import type { NodeProps, Node } from "@xyflow/react";
3
+ import { Server } from "lucide-react";
4
+ import { EventIcon } from "../components/ddd-icons";
5
+ import { contextVar } from "../lib/context-color";
6
+
7
+ export type ServiceNodeData = {
8
+ label: string;
9
+ context: string | null;
10
+ ghost: boolean;
11
+ kind: "service" | "event" | "producer" | "context";
12
+ /**
13
+ * What this node is to the graph it is in - "publisher", "consumer". The
14
+ * kind says what an entity IS; the role says why it is on this canvas, and
15
+ * on a picture of one event that is the more useful of the two.
16
+ */
17
+ role?: string;
18
+ /** Second line, on the nodes big enough to hold one. */
19
+ sub?: string;
20
+ /** Right-aligned tag - a context's classification, and nothing else so far. */
21
+ tag?: string;
22
+ };
23
+
24
+ export type PortolanNode = Node<ServiceNodeData, "portolan">;
25
+
26
+ /** Fallback when a graph does not name the role itself. */
27
+ const ROLE: Record<ServiceNodeData["kind"], string> = {
28
+ producer: "publisher",
29
+ event: "event",
30
+ service: "service",
31
+ context: "context",
32
+ };
33
+
34
+ /**
35
+ * The node the focused event graph draws. (The dependency graph and the
36
+ * context map register their own components under the same `portolan` key,
37
+ * so this one is not shared - it used to be, and the comment saying so
38
+ * outlived the split.)
39
+ *
40
+ * A card: an icon in a tinted tile, and beside it two lines. The eyebrow says
41
+ * outright what the box is - publisher, event, consumer - so a reader does
42
+ * not have to work it out from position, and it takes the colour, which
43
+ * leaves the name under it plain and readable. The tile is where the card
44
+ * keeps the colour of the context that owns it; it used to be a bar down the
45
+ * left edge and a wash across the box, and on a canvas of cards a wash is
46
+ * the one thing that stops a card being a card.
47
+ */
48
+ export function PortolanNode({ data }: NodeProps<PortolanNode>) {
49
+ const accent = data.ghost
50
+ ? "var(--status-unresolved)"
51
+ : data.kind === "event"
52
+ ? // An event is amber everywhere else in the app; it was blue here only
53
+ // because blue is what --accent happened to be.
54
+ "var(--kind-event)"
55
+ : contextVar(data.context);
56
+ const Icon = data.kind === "event" ? EventIcon : Server;
57
+ // A node the catalog does not know is not a publisher or a consumer - it is
58
+ // a name someone wrote down, and the eyebrow is where that is said.
59
+ const eyebrow = data.ghost
60
+ ? "not in catalog"
61
+ : (data.role ?? ROLE[data.kind]);
62
+
63
+ return (
64
+ <div
65
+ className={`flex h-full w-full items-center gap-2 px-2.5 ${
66
+ data.ghost ? "flow-card-ghost" : "flow-card"
67
+ }`}
68
+ style={{ color: data.ghost ? "var(--status-unresolved)" : "var(--fg)" }}
69
+ title={data.ghost ? `${data.label} — not in the catalog` : data.label}
70
+ >
71
+ <span className="flow-tile" style={{ color: accent }}>
72
+ <Icon size={12} aria-hidden />
73
+ </span>
74
+ <div className="flex min-w-0 flex-1 flex-col justify-center gap-px">
75
+ <span
76
+ className="truncate uppercase"
77
+ style={{
78
+ color: accent,
79
+ fontSize: 9,
80
+ lineHeight: 1.3,
81
+ letterSpacing: "0.06em",
82
+ fontWeight: 600,
83
+ }}
84
+ >
85
+ {eyebrow}
86
+ </span>
87
+ <span className="mono truncate" style={{ fontSize: 12, lineHeight: 1.3 }}>
88
+ {data.label}
89
+ </span>
90
+ </div>
91
+ <Handle type="target" position={Position.Left} style={{ opacity: 0 }} />
92
+ <Handle type="source" position={Position.Right} style={{ opacity: 0 }} />
93
+ </div>
94
+ );
95
+ }
96
+
97
+ export const nodeTypes = { portolan: PortolanNode };
@@ -0,0 +1,81 @@
1
+ // The shared visual language. Both renderers speak it: these are the same
2
+ // tokens LikeC4 gets baked into its generated spec, so the seam is invisible.
3
+
4
+ import type { Status } from "../catalog";
5
+
6
+ /**
7
+ * Edge weight. One width for a line at rest, one for a line the selection has
8
+ * lit, on every canvas - a reader who has learned that a thick line means
9
+ * "this one" on the dependency graph should not have to relearn it on the
10
+ * context map.
11
+ */
12
+ export const EDGE_W = 1.25;
13
+ export const EDGE_W_LIT = 2;
14
+
15
+ /**
16
+ * The focused event graph's boxes - the only nodes elk sizes from these
17
+ * defaults. Two lines tall: an eyebrow naming the role and the name under it.
18
+ */
19
+ export const NODE_W = 176;
20
+ export const NODE_H = 48;
21
+ export const EVENT_W = 204;
22
+
23
+ // ---------------------------------------------------------------------------
24
+ // The dependency graph's two node kinds.
25
+ // ---------------------------------------------------------------------------
26
+
27
+ /**
28
+ * A service box: icon tile, name, and the two traffic counters under it. Wide
29
+ * enough for the counters to sit beside the tile without a truncated word.
30
+ */
31
+ export const SERVICE_W = 212;
32
+ export const SERVICE_H = 52;
33
+
34
+ /** An event pill. 28px is the height of a chip, which is what it is. */
35
+ export const EVENT_H = 28;
36
+ export const EVENT_MIN_W = 104;
37
+ export const EVENT_MAX_W = 260;
38
+
39
+ /** Width of a pill collapsed to its icon, at fit zooms too small to read. */
40
+ export const EVENT_ICON_W = 28;
41
+
42
+ /**
43
+ * Below this zoom a pill's 11px mono renders under 6px on screen, which is a
44
+ * smudge with a shape rather than a word. Pills collapse to their icon there
45
+ * and give their name back on hover.
46
+ *
47
+ * The threshold is a judgement, and it is set by what the graphs actually fit
48
+ * at. The sample estate fits a full-width pane at about 0.58, so it keeps its
49
+ * names - small, but names; the forty-service estate fits at a third of that,
50
+ * where a row of clean icons beats a row of grey marks. Anything in between
51
+ * lands on the side its own fit zoom puts it.
52
+ */
53
+ export const LEGIBLE_ZOOM = 0.55;
54
+
55
+ /**
56
+ * How wide a pill has to be to hold a name.
57
+ *
58
+ * Measured rather than guessed would mean a canvas pass per label before elk
59
+ * can start; 6.35px is the advance of the app's mono at 11px, and the box is
60
+ * padded to the point where being a pixel out is invisible.
61
+ */
62
+ export function eventWidth(name: string, extras = 0): number {
63
+ const text = name.length * 6.35;
64
+ return Math.min(EVENT_MAX_W, Math.max(EVENT_MIN_W, text + 42 + extras));
65
+ }
66
+
67
+ export function statusColor(status: Status): string {
68
+ return `var(--status-${status})`;
69
+ }
70
+
71
+ /** Same three markers as the LikeC4 spec: solid / dashed / dotted. */
72
+ export function statusDash(status: Status): string | undefined {
73
+ switch (status) {
74
+ case "verified":
75
+ return undefined;
76
+ case "declared":
77
+ return "5 3";
78
+ case "unresolved":
79
+ return "2 3";
80
+ }
81
+ }
@@ -0,0 +1,125 @@
1
+ import { useEffect, useState } from "react";
2
+ import type { Edge } from "@xyflow/react";
3
+ import { MarkerType } from "@xyflow/react";
4
+ import type { Status } from "../catalog";
5
+ import { layoutWithElk } from "./elk";
6
+ import type { PortolanNode, ServiceNodeData } from "./nodes";
7
+ import { EDGE_W, NODE_H, NODE_W, statusColor, statusDash } from "./theme";
8
+
9
+ export interface FlowSpec {
10
+ nodes: {
11
+ id: string;
12
+ data: ServiceNodeData;
13
+ width?: number;
14
+ height?: number;
15
+ }[];
16
+ edges: {
17
+ id: string;
18
+ source: string;
19
+ target: string;
20
+ label: string;
21
+ status: Status;
22
+ eventId?: string;
23
+ }[];
24
+ direction?: "RIGHT" | "DOWN";
25
+ layerSpacing?: number;
26
+ }
27
+
28
+ export interface FlowState {
29
+ nodes: PortolanNode[];
30
+ edges: Edge[];
31
+ ready: boolean;
32
+ }
33
+
34
+ /** Runs elk whenever the spec changes and returns React Flow's nodes and edges. */
35
+ export function useElkFlow(spec: FlowSpec): FlowState {
36
+ const [state, setState] = useState<FlowState>({
37
+ nodes: [],
38
+ edges: [],
39
+ ready: false,
40
+ });
41
+
42
+ useEffect(() => {
43
+ let cancelled = false;
44
+ const run = async (): Promise<void> => {
45
+ const { positions } = await layoutWithElk({
46
+ nodes: spec.nodes.map((n) => ({
47
+ id: n.id,
48
+ width: n.width ?? NODE_W,
49
+ height: n.height ?? NODE_H,
50
+ })),
51
+ edges: spec.edges.map((e) => ({
52
+ id: e.id,
53
+ source: e.source,
54
+ target: e.target,
55
+ labelWidth: Math.max(40, e.label.length * 6),
56
+ })),
57
+ ...(spec.direction ? { direction: spec.direction } : {}),
58
+ ...(spec.layerSpacing ? { layerSpacing: spec.layerSpacing } : {}),
59
+ });
60
+ if (cancelled) return;
61
+
62
+ const nodes: PortolanNode[] = spec.nodes.map((n) => ({
63
+ id: n.id,
64
+ type: "portolan",
65
+ position: positions[n.id] ?? { x: 0, y: 0 },
66
+ data: n.data,
67
+ initialWidth: n.width ?? NODE_W,
68
+ initialHeight: n.height ?? NODE_H,
69
+ width: n.width ?? NODE_W,
70
+ height: n.height ?? NODE_H,
71
+ draggable: false,
72
+ connectable: false,
73
+ }));
74
+
75
+ const edges: Edge[] = spec.edges.map((e) => {
76
+ const color = statusColor(e.status);
77
+ const dash = statusDash(e.status);
78
+ return {
79
+ id: e.id,
80
+ source: e.source,
81
+ target: e.target,
82
+ label: e.label,
83
+ type: "bezier",
84
+ animated: false,
85
+ style: {
86
+ stroke: color,
87
+ strokeWidth: EDGE_W,
88
+ ...(dash ? { strokeDasharray: dash } : {}),
89
+ },
90
+ labelStyle: {
91
+ fill: "var(--fg-muted)",
92
+ fontSize: 10,
93
+ fontFamily: "var(--font-mono)",
94
+ },
95
+ // A word printed straight onto a line is a word with a line through
96
+ // it. The label carries the canvas background and a hairline of its
97
+ // own, which is the same pill the bundled edges wear.
98
+ labelBgStyle: {
99
+ fill: "var(--flow-card)",
100
+ stroke: "var(--border)",
101
+ strokeWidth: 1,
102
+ },
103
+ labelBgPadding: [6, 3] as [number, number],
104
+ labelBgBorderRadius: 8,
105
+ labelShowBg: true,
106
+ markerEnd: {
107
+ type: MarkerType.ArrowClosed,
108
+ color,
109
+ width: 14,
110
+ height: 14,
111
+ },
112
+ data: e.eventId ? { eventId: e.eventId } : {},
113
+ };
114
+ });
115
+
116
+ setState({ nodes, edges, ready: true });
117
+ };
118
+ void run();
119
+ return () => {
120
+ cancelled = true;
121
+ };
122
+ }, [spec]);
123
+
124
+ return state;
125
+ }