@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,157 @@
1
+ // The visual half of the taxonomy in src/lib/kinds.ts. One icon per kind,
2
+ // painted from a token, so nothing downstream picks its own glyph or colour.
3
+
4
+ import {
5
+ Database,
6
+ Eye,
7
+ Globe,
8
+ Hexagon,
9
+ ListChecks,
10
+ Package,
11
+ Route,
12
+ ScrollText,
13
+ Server,
14
+ Shapes,
15
+ Table2,
16
+ Webhook,
17
+ WholeWord,
18
+ } from "lucide-react";
19
+ import type { Kind } from "../lib/kinds";
20
+ import { ctxStyle } from "../lib/context-color";
21
+ import {
22
+ CommandIcon,
23
+ EntityIcon,
24
+ EventIcon,
25
+ QueryIcon,
26
+ ValueObjectIcon,
27
+ } from "./ddd-icons";
28
+
29
+ /**
30
+ * Anything that takes `size` and paints itself from `currentColor` - lucide's
31
+ * icons and portolan's own five, which are drawn on lucide's grid precisely so
32
+ * this type can cover both.
33
+ */
34
+ type IconComponent = (props: {
35
+ size?: number;
36
+ className?: string;
37
+ style?: React.CSSProperties;
38
+ "aria-hidden"?: boolean;
39
+ }) => React.ReactNode;
40
+
41
+ /**
42
+ * The five DDD building blocks are drawn in ./ddd-icons; everything else is
43
+ * app chrome and stays lucide. That split is the rule, not a coincidence: a
44
+ * domain concept gets a mark that says what it is, a piece of furniture gets
45
+ * the furniture library.
46
+ */
47
+ const KIND_ICON: Record<Kind, IconComponent> = {
48
+ context: Hexagon, // unused: contexts draw a coloured dot instead
49
+ // Outside the estate, so the one mark that says "the rest of the world".
50
+ external: Globe,
51
+ service: Server,
52
+ aggregate: Hexagon,
53
+ // A store and a table are infrastructure, not domain objects, so they take
54
+ // lucide's furniture rather than one of portolan's five domain marks.
55
+ store: Database,
56
+ table: Table2,
57
+ // A view is drawn as an eye rather than a second grid: what separates it
58
+ // from a table is that it is a way of LOOKING at rows, not a place they are.
59
+ view: Eye,
60
+ event: EventIcon,
61
+ vo: ValueObjectIcon,
62
+ entity: EntityIcon,
63
+ // An enum is a list a consumer ticks through - one of these, and no other.
64
+ // Furniture rather than a sixth domain mark: the five say what a block IS,
65
+ // and a set of values is what a field HOLDS.
66
+ enum: ListChecks,
67
+ command: CommandIcon,
68
+ query: QueryIcon,
69
+ // An endpoint is a door in the wall of a service, not a domain object, so it
70
+ // takes furniture like the store and the table do.
71
+ endpoint: Webhook,
72
+ // A module is a package of schema someone published - infrastructure again,
73
+ // and a box is what a registry hands you.
74
+ module: Package,
75
+ def: Shapes,
76
+ flow: Route,
77
+ adr: ScrollText,
78
+ // A term is a word, and the mark says so. It is deliberately NOT one of the
79
+ // five domain marks: the glossary names the building blocks, it is not one
80
+ // of them, and a term wearing an aggregate's hexagon would say it was.
81
+ term: WholeWord,
82
+ };
83
+
84
+ /**
85
+ * Colour by kind. Domain events are the loudest leaf in the tree because they
86
+ * are the thing other contexts actually depend on; structural blocks stay grey
87
+ * so they read as detail inside the aggregate that owns them.
88
+ */
89
+ export const KIND_COLOR: Record<Kind, string> = {
90
+ context: "var(--ctx)",
91
+ external: "var(--fg-muted)",
92
+ service: "var(--fg-muted)",
93
+ aggregate: "var(--fg)",
94
+ store: "var(--fg-muted)",
95
+ table: "var(--fg-muted)",
96
+ view: "var(--fg-muted)",
97
+ event: "var(--kind-event)",
98
+ vo: "var(--fg-muted)",
99
+ entity: "var(--fg-muted)",
100
+ enum: "var(--fg-muted)",
101
+ command: "var(--fg-muted)",
102
+ query: "var(--fg-muted)",
103
+ endpoint: "var(--fg-muted)",
104
+ module: "var(--fg-muted)",
105
+ def: "var(--fg-muted)",
106
+ flow: "var(--fg-muted)",
107
+ adr: "var(--fg-muted)",
108
+ // A term is painted by the context that means it, like a context row: which
109
+ // vocabulary a word belongs to is the whole of what distinguishes two
110
+ // entries that spell the same word.
111
+ term: "var(--ctx)",
112
+ };
113
+
114
+ /**
115
+ * Icons are 16px wherever one stands on its own - a toolbar button, a page
116
+ * header, the panel's close. Inside a 12px mono row or chip the default drops
117
+ * to 14: the icon labels the identifier next to it, and a 16px glyph beside
118
+ * 12px type reads as the subject rather than the label.
119
+ */
120
+ export function KindIcon({
121
+ kind,
122
+ contextId,
123
+ size = 14,
124
+ className = "",
125
+ }: {
126
+ kind: Kind;
127
+ /** Required for `context`, which is painted in that context's own colour. */
128
+ contextId?: string;
129
+ size?: number;
130
+ className?: string;
131
+ }) {
132
+ if (kind === "context") {
133
+ return (
134
+ <span
135
+ aria-hidden
136
+ className={`inline-block shrink-0 rounded-full ${className}`}
137
+ style={{
138
+ width: size - 3,
139
+ height: size - 3,
140
+ background: "var(--ctx)",
141
+ ...ctxStyle(contextId),
142
+ }}
143
+ />
144
+ );
145
+ }
146
+ const Icon = KIND_ICON[kind];
147
+ return (
148
+ <Icon
149
+ size={size}
150
+ aria-hidden
151
+ /* `block` drops the inline baseline gap so the glyph centres on the
152
+ cap-height of the text beside it rather than sitting on its baseline. */
153
+ className={`block shrink-0 ${className}`}
154
+ style={{ color: KIND_COLOR[kind] }}
155
+ />
156
+ );
157
+ }
@@ -0,0 +1,61 @@
1
+ // The mark.
2
+ //
3
+ // A portolan chart is drawn around wind roses: a circle with the rhumb lines
4
+ // radiating out of it, one long point for each cardinal direction and a shorter
5
+ // one between. That is the whole logo - no gradient, no second colour, nothing
6
+ // that stops being a logo at 16px.
7
+ //
8
+ // The star is filled and the ring is stroked, which is the only reason the
9
+ // points still read as points at favicon size: eight hairlines crossing inside
10
+ // a 16px box turn into a grey smudge, eight solid wedges do not.
11
+
12
+ import type { SVGProps } from "react";
13
+
14
+ /** The 8-point rose, tips crossing a ring, drawn on the same 24 grid as the icons. */
15
+ export const ROSE_STAR =
16
+ "M 12 1.4 L 12.96 9.69 L 16.38 7.62 L 14.31 11.04 L 22.6 12 L 14.31 12.96 L 16.38 16.38 L 12.96 14.31 L 12 22.6 L 11.04 14.31 L 7.62 16.38 L 9.69 12.96 L 1.4 12 L 9.69 11.04 L 7.62 7.62 L 11.04 9.69 Z";
17
+
18
+ export function CompassRose({
19
+ size = 16,
20
+ ...rest
21
+ }: Omit<SVGProps<SVGSVGElement>, "ref"> & { size?: number }) {
22
+ return (
23
+ <svg
24
+ xmlns="http://www.w3.org/2000/svg"
25
+ width={size}
26
+ height={size}
27
+ viewBox="0 0 24 24"
28
+ fill="none"
29
+ aria-hidden
30
+ {...rest}
31
+ >
32
+ <circle
33
+ cx={12}
34
+ cy={12}
35
+ r={7.1}
36
+ stroke="currentColor"
37
+ strokeWidth={1.4}
38
+ opacity={0.55}
39
+ />
40
+ <path d={ROSE_STAR} fill="currentColor" />
41
+ </svg>
42
+ );
43
+ }
44
+
45
+ /**
46
+ * Mark plus wordmark, for the sidebar header. Lowercase and set in the mono
47
+ * face: the name is an identifier like everything else this app names.
48
+ */
49
+ export function Wordmark({ size = 16 }: { size?: number }) {
50
+ return (
51
+ <span className="flex items-center gap-2 text-ink">
52
+ <CompassRose size={size} className="shrink-0" />
53
+ <span
54
+ className="text-sm font-semibold lowercase"
55
+ style={{ letterSpacing: "-0.01em" }}
56
+ >
57
+ portolan
58
+ </span>
59
+ </span>
60
+ );
61
+ }
@@ -0,0 +1,264 @@
1
+ import { Link } from "react-router";
2
+ import type { ReactNode } from "react";
3
+ import type {
4
+ Adr,
5
+ AdrScope,
6
+ AdrStatus,
7
+ Classification,
8
+ Status,
9
+ } from "../catalog";
10
+ import { index } from "../data";
11
+ import { adrNumber } from "../lib/adr";
12
+ import { ctxStyle } from "../lib/context-color";
13
+ import { paths } from "../routes";
14
+
15
+ const STATUS_LABEL: Record<Status, string> = {
16
+ verified: "verified",
17
+ declared: "declared",
18
+ unresolved: "unresolved",
19
+ };
20
+
21
+ /** Component class that paints text and border for a status. */
22
+ const STATUS_CLASS: Record<Status, string> = {
23
+ verified: "status-verified",
24
+ declared: "status-declared",
25
+ unresolved: "status-unresolved",
26
+ };
27
+
28
+ /** Raw value, for SVG strokes and React Flow edges that cannot take a class. */
29
+ export function statusVar(status: Status): string {
30
+ return `var(--status-${status})`;
31
+ }
32
+
33
+ export function StatusChip({
34
+ status,
35
+ title,
36
+ }: {
37
+ status: Status;
38
+ title?: string;
39
+ }) {
40
+ return (
41
+ <span
42
+ title={title ?? `status: ${status}`}
43
+ className={`chip ${STATUS_CLASS[status]}`}
44
+ >
45
+ <span aria-hidden className="dot" />
46
+ {STATUS_LABEL[status]}
47
+ </span>
48
+ );
49
+ }
50
+
51
+ export function ContextPill({ id, name }: { id: string; name?: string }) {
52
+ return (
53
+ <span className="chip ctx" style={ctxStyle(id)}>
54
+ <span aria-hidden className="dot" />
55
+ {name ?? id}
56
+ </span>
57
+ );
58
+ }
59
+
60
+ /**
61
+ * How strategically a bounded context is rated, said in one word. Core is the
62
+ * only one worth the accent - "supporting" and "generic" are the answer "not
63
+ * where the value is", and a row full of loud badges says nothing at all.
64
+ */
65
+ const CLASSIFICATION_META: Record<
66
+ Classification,
67
+ { className: string; title: string }
68
+ > = {
69
+ core: {
70
+ className: "border-accent text-accent",
71
+ title: "core domain - where this estate competes",
72
+ },
73
+ supporting: {
74
+ className: "border-line-strong text-muted",
75
+ title: "supporting domain - needed here, but not a differentiator",
76
+ },
77
+ generic: {
78
+ className: "border-line-strong text-muted",
79
+ title: "generic domain - a solved problem, bought or borrowed",
80
+ },
81
+ };
82
+
83
+ /**
84
+ * The classification badge, and the only place it is drawn. A context with no
85
+ * classification renders nothing: an unrated domain is not a "generic" one, and
86
+ * a placeholder would state a call the estate has not made.
87
+ *
88
+ * `tiny` is the sidebar's 10px variant, where the badge rides at the end of a
89
+ * tree row and must not compete with the context name it annotates.
90
+ */
91
+ export function ClassificationBadge({
92
+ classification,
93
+ tiny = false,
94
+ }: {
95
+ classification?: Classification;
96
+ tiny?: boolean;
97
+ }) {
98
+ if (!classification) return null;
99
+ const meta = CLASSIFICATION_META[classification];
100
+ return (
101
+ <span
102
+ className={`chip shrink-0 ${meta.className}`}
103
+ style={tiny ? { fontSize: 10, lineHeight: "14px" } : undefined}
104
+ title={meta.title}
105
+ >
106
+ {classification}
107
+ </span>
108
+ );
109
+ }
110
+
111
+ // ---------------------------------------------------------------------------
112
+ // Decision records
113
+ // ---------------------------------------------------------------------------
114
+
115
+ /**
116
+ * Green for what holds, amber for what is still being argued, grey for what is
117
+ * only history. Grey covers three different endings, so the badge says which.
118
+ */
119
+ const ADR_STATUS_CLASS: Record<AdrStatus, string> = {
120
+ accepted: "status-verified",
121
+ proposed: "status-declared",
122
+ superseded: "border-line-strong text-muted",
123
+ deprecated: "border-line-strong text-muted",
124
+ rejected: "border-line-strong text-muted",
125
+ };
126
+
127
+ /** True for records that are no longer in force; their number is struck out. */
128
+ export function isStruck(status: AdrStatus): boolean {
129
+ return status === "superseded" || status === "deprecated";
130
+ }
131
+
132
+ export function AdrStatusChip({ status }: { status: AdrStatus }) {
133
+ return (
134
+ <span
135
+ title={`status: ${status}`}
136
+ className={`chip ${ADR_STATUS_CLASS[status]}`}
137
+ >
138
+ <span aria-hidden className="dot" />
139
+ {status}
140
+ </span>
141
+ );
142
+ }
143
+
144
+ /** "ADR-0007", struck through once the decision no longer holds. */
145
+ export function AdrNumber({
146
+ adr,
147
+ className = "",
148
+ }: {
149
+ adr: Adr;
150
+ className?: string;
151
+ }) {
152
+ const struck = isStruck(adr.status);
153
+ return (
154
+ <span
155
+ className={`mono ${struck ? "line-through text-muted" : ""} ${className}`}
156
+ title={struck ? `${adr.id} - no longer in force` : adr.id}
157
+ >
158
+ {adrNumber(adr)}
159
+ </span>
160
+ );
161
+ }
162
+
163
+ /**
164
+ * The scope a decision was taken at, linking to the page it governs. Pass
165
+ * `link={false}` inside a row that is itself a link: an anchor cannot contain
166
+ * another one.
167
+ */
168
+ export function AdrScopePill({
169
+ scope,
170
+ link = true,
171
+ }: {
172
+ scope: AdrScope;
173
+ link?: boolean;
174
+ }) {
175
+ if (scope.kind === "org") {
176
+ return (
177
+ <span className="chip border-line-strong text-muted" title="org-wide">
178
+ <span aria-hidden className="dot" />
179
+ org
180
+ </span>
181
+ );
182
+ }
183
+
184
+ if (scope.kind === "context") {
185
+ const body = (
186
+ <>
187
+ <span aria-hidden className="dot" />
188
+ {scope.context}
189
+ </>
190
+ );
191
+ const props = {
192
+ className: "chip ctx",
193
+ style: ctxStyle(scope.context),
194
+ title: `context ${scope.context}`,
195
+ };
196
+ return link ? (
197
+ <Link to={paths.context(scope.context)} {...props}>
198
+ {body}
199
+ </Link>
200
+ ) : (
201
+ <span {...props}>{body}</span>
202
+ );
203
+ }
204
+
205
+ const context = index.serviceContext.get(scope.service);
206
+ const service = index.serviceById.get(scope.service);
207
+ if (!context || !service) {
208
+ return (
209
+ <span className="chip status-unresolved">
210
+ <span aria-hidden className="dot" />
211
+ {scope.service}
212
+ </span>
213
+ );
214
+ }
215
+ const body = (
216
+ <>
217
+ <span aria-hidden className="dot" />
218
+ {scope.service}
219
+ </>
220
+ );
221
+ const props = {
222
+ className: "chip ctx",
223
+ style: ctxStyle(context.id),
224
+ title: `service ${scope.service}`,
225
+ };
226
+ return link ? (
227
+ <Link to={paths.service(context.id, service.slug)} {...props}>
228
+ {body}
229
+ </Link>
230
+ ) : (
231
+ <span {...props}>{body}</span>
232
+ );
233
+ }
234
+
235
+ export function Panel({
236
+ title,
237
+ children,
238
+ }: {
239
+ title: string;
240
+ children: ReactNode;
241
+ }) {
242
+ return (
243
+ <section className="overflow-hidden rounded-card border border-line shadow-xs">
244
+ <h2 className="label border-b border-line bg-surface px-4 py-2">
245
+ {title}
246
+ </h2>
247
+ <div className="p-4">{children}</div>
248
+ </section>
249
+ );
250
+ }
251
+
252
+ export function ExternalLink({
253
+ to,
254
+ children,
255
+ }: {
256
+ to: string;
257
+ children: ReactNode;
258
+ }) {
259
+ return (
260
+ <Link to={to} className="mono rounded-control text-accent hover:underline">
261
+ {children}
262
+ </Link>
263
+ );
264
+ }
@@ -0,0 +1,18 @@
1
+ import { readFileSync } from "node:fs";
2
+ import { describe, expect, it } from "vitest";
3
+
4
+ import { SOURCE_GLOBS } from "./data";
5
+
6
+ // The site cannot read the manifest: import.meta.glob resolves at build time
7
+ // and needs literals, so the patterns are written out twice - once in
8
+ // portolan.json for the host, once in data.ts for the site. This is what keeps
9
+ // the two copies one list: a source the host merges and the site never loads
10
+ // is a page that exists in docs/ and nowhere on the site.
11
+ describe("the site's source globs", () => {
12
+ it("are the manifest's sources, in the manifest's order", () => {
13
+ const manifest = JSON.parse(
14
+ readFileSync(new URL("../portolan.json", import.meta.url), "utf8"),
15
+ ) as { sources: string[] };
16
+ expect([...SOURCE_GLOBS]).toEqual(manifest.sources);
17
+ });
18
+ });
package/src/data.ts ADDED
@@ -0,0 +1,202 @@
1
+ // Single entry point for catalog data.
2
+ //
3
+ // There is no master catalog. The app reads every source it can find, merges
4
+ // them, and validates the union - in that order, because referential integrity
5
+ // is a property of the whole estate and not of any one file. A service that
6
+ // publishes facts about itself next to its own code is a source; so is a
7
+ // hand-written file carrying the prose nobody can generate.
8
+ //
9
+ // Validation happens here, at startup, so a bad generator run is caught before
10
+ // anything is drawn. It is caught, not thrown: a validator that throws out of a
11
+ // module's top level takes the whole bundle down and the reader gets a blank
12
+ // page and a line in a console they are not looking at. So the failure is
13
+ // turned into a value, the app falls back to an empty catalog so every module
14
+ // below still imports, and the shell renders the error instead of the routes.
15
+
16
+ import { buildIndex, CatalogError, validateCatalog } from "./catalog";
17
+ import type { Catalog, CatalogIndex } from "./catalog";
18
+ import {
19
+ catalogProfileNamed,
20
+ catalogProfiles as profilesFromManifest,
21
+ filterCatalogForProfile,
22
+ profileIncludesSource,
23
+ } from "./catalog-profile";
24
+ import type { CatalogProfile, CatalogProfileManifest } from "./catalog-profile";
25
+ import { enrichCatalog } from "./enrich";
26
+ import type { DerivedEdge } from "./enrich";
27
+ import { mergeCatalogs } from "./merge";
28
+ import type {
29
+ CatalogSource,
30
+ MergeConflict,
31
+ SourceCatalog,
32
+ SourceStamp,
33
+ } from "./merge";
34
+ import manifestJson from "../portolan.json";
35
+
36
+ const manifest = manifestJson as CatalogProfileManifest & { sources: string[] };
37
+ export const catalogProfiles: CatalogProfile[] = profilesFromManifest(manifest);
38
+ const requestedProfile =
39
+ typeof window === "undefined"
40
+ ? null
41
+ : new URLSearchParams(window.location.search).get("catalog");
42
+ export const activeCatalogProfile = catalogProfileNamed(manifest, requestedProfile);
43
+
44
+ /**
45
+ * Where sources are looked for. The patterns are written out because
46
+ * import.meta.glob resolves at build time and needs literals - and because
47
+ * they are worth reading: the first is the estate's own files, the second is
48
+ * what each service publishes beside its code - one level down for a context
49
+ * of one service, two for a context that holds several.
50
+ */
51
+ export const SOURCE_GLOBS = [
52
+ "data/*.json",
53
+ "portolan/*.json",
54
+ "examples/*/portolan/*.json",
55
+ "examples/*/*/portolan/*.json",
56
+ "examples/*/*/*/portolan/*.json",
57
+ "vendor/repos/*/*/git.repo.json",
58
+ "vendor/repos/**/portolan/*.json",
59
+ ] as const;
60
+
61
+ const modules: Record<string, unknown> = {
62
+ ...import.meta.glob("../data/*.json", { eager: true, import: "default" }),
63
+ ...import.meta.glob("../portolan/*.json", { eager: true, import: "default" }),
64
+ ...import.meta.glob("../examples/*/portolan/*.json", {
65
+ eager: true,
66
+ import: "default",
67
+ }),
68
+ ...import.meta.glob("../examples/*/*/portolan/*.json", {
69
+ eager: true,
70
+ import: "default",
71
+ }),
72
+ ...import.meta.glob("../examples/*/*/*/portolan/*.json", {
73
+ eager: true,
74
+ import: "default",
75
+ }),
76
+ ...import.meta.glob("../vendor/repos/*/*/git.repo.json", {
77
+ eager: true,
78
+ import: "default",
79
+ }),
80
+ ...import.meta.glob("../vendor/repos/**/portolan/*.json", {
81
+ eager: true,
82
+ import: "default",
83
+ }),
84
+ };
85
+
86
+ /** What the app draws when the catalog cannot be trusted: nothing. */
87
+ const EMPTY: Catalog = {
88
+ generatedAt: "",
89
+ commit: "",
90
+ contexts: [],
91
+ defs: {},
92
+ flows: [],
93
+ adrs: [],
94
+ };
95
+
96
+ interface Loaded {
97
+ catalog: Catalog;
98
+ sources: SourceStamp[];
99
+ conflicts: MergeConflict[];
100
+ derived: DerivedEdge[];
101
+ error: CatalogError | null;
102
+ /** The sources as merged, before anything was derived or checked. */
103
+ raw: Catalog;
104
+ }
105
+
106
+ function load(): Loaded {
107
+ const sources: CatalogSource[] = Object.entries(modules)
108
+ .map(([path, catalog]) => ({
109
+ // Vite keys a glob by its pattern-relative path; the leading ../ is an
110
+ // artefact of this file's location, not part of where anything lives.
111
+ path: path.replace(/^\.\.\//, ""),
112
+ // A SOURCE, not a catalog: the two stamps are optional in a file, and
113
+ // the estate's authored facts carry neither.
114
+ catalog: catalog as SourceCatalog,
115
+ }))
116
+ .filter((source) => profileIncludesSource(activeCatalogProfile, source.path));
117
+
118
+ const merged = mergeCatalogs(sources);
119
+ // Enriched before it is validated: the edges the flows imply are part of
120
+ // the union the way a peer named by another source is, and the validator
121
+ // resolves a step's call against them.
122
+ const scoped = filterCatalogForProfile(merged.catalog, activeCatalogProfile);
123
+ const enriched = enrichCatalog(scoped);
124
+
125
+ try {
126
+ return {
127
+ catalog: validateCatalog(enriched.catalog),
128
+ sources: merged.sources,
129
+ conflicts: merged.conflicts,
130
+ derived: enriched.derived,
131
+ error: null,
132
+ raw: merged.catalog,
133
+ };
134
+ } catch (cause) {
135
+ const error =
136
+ cause instanceof CatalogError
137
+ ? cause
138
+ : // Anything else is a shape the validator never got far enough to
139
+ // name - a truncated file, a null where a list was expected. Same
140
+ // treatment.
141
+ new CatalogError(
142
+ cause instanceof Error ? cause.message : String(cause),
143
+ );
144
+
145
+ return {
146
+ catalog: EMPTY,
147
+ sources: merged.sources,
148
+ conflicts: merged.conflicts,
149
+ derived: [],
150
+ error,
151
+ raw: merged.catalog,
152
+ };
153
+ }
154
+ }
155
+
156
+ const loaded = load();
157
+
158
+ export const catalog: Catalog = loaded.catalog;
159
+ export const index: CatalogIndex = buildIndex(catalog);
160
+
161
+ /**
162
+ * The sources the catalog was built from, newest first by nothing at all -
163
+ * they are in path order, which is the order the merge used.
164
+ *
165
+ * This is what the merged stamp is a summary of, and the summary is lossy in
166
+ * both halves: one date stands for the oldest of many, and "6 sources" stands
167
+ * for six shas the header has no room to print. The Overview stamp opens onto
168
+ * this list, so a reader who wants to know WHICH part is a week old can find
169
+ * out instead of being told a number and left with it. A source with an empty
170
+ * stamp is one nobody generated.
171
+ */
172
+ export const catalogSources: SourceStamp[] = loaded.sources;
173
+
174
+ /**
175
+ * Sources disagreeing with each other. Not an error: two files both naming a
176
+ * context is normal, and both naming it differently is a fact about the estate
177
+ * that belongs on the Problems page rather than on a crash screen.
178
+ */
179
+ export const catalogConflicts: MergeConflict[] = loaded.conflicts;
180
+
181
+ /**
182
+ * Consumers and calls no source declared: what the flows said, written onto
183
+ * the events and services after the merge. Each one names the step it was
184
+ * read from, and the catalog above already contains it.
185
+ */
186
+ export const derivedEdges: DerivedEdge[] = loaded.derived;
187
+
188
+ /**
189
+ * Where the catalog is read from, as a reader would type it. Empty states name
190
+ * it, so it is written once here rather than spelled out on five pages.
191
+ */
192
+ export const CATALOG_PATH = activeCatalogProfile.sources.join(" · ");
193
+
194
+ /** Non-null when the catalog failed validation; the shell renders it instead. */
195
+ export const catalogError: CatalogError | null = loaded.error;
196
+
197
+ /**
198
+ * The merge before enrichment and validation: what the sources said, with
199
+ * nothing derived onto it yet. Tests that check the validator, or that want
200
+ * to see the estate the way a source wrote it, start from here.
201
+ */
202
+ export const rawCatalog: Catalog = loaded.raw;