@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,295 @@
1
+ package main
2
+
3
+ // Reading a view.
4
+ //
5
+ // A view is kept apart from a table rather than folded in behind a flag: it has
6
+ // no key, no constraints and no rows of its own, and what it has instead is
7
+ // what it reads. So this reads the select: which relations it draws from, what
8
+ // each output column is called, and - the part a table cannot say - which
9
+ // column each one was computed from.
10
+ //
11
+ // The type of a column is not in the statement, because a view does not declare
12
+ // one. It is taken from the column it is computed from when there is exactly
13
+ // one; a column summed, coalesced or joined out of several says nothing and is
14
+ // left blank rather than guessed at.
15
+
16
+ import (
17
+ "strings"
18
+
19
+ "github.com/pgplex/pgparser/nodes"
20
+
21
+ "github.com/shortlink-org/portolan/catalog"
22
+ )
23
+
24
+ // view is what one CREATE VIEW says, before the store turns names into ids.
25
+ type view struct {
26
+ name string
27
+ doc string
28
+ // materialized: the database keeps the rows rather than recomputing them,
29
+ // which means they can be stale. A reader has to know that before believing
30
+ // one, so it is carried rather than inferred from the name.
31
+ materialized bool
32
+ // reads names the relations of the FROM clause, in the order written.
33
+ reads []string
34
+ // columns, in the order the select lists them.
35
+ columns []viewColumn
36
+ // definition is the statement as it was written.
37
+ definition string
38
+ }
39
+
40
+ type viewColumn struct {
41
+ name string
42
+ // from is "<relation>.<column>" for every column this one is computed from.
43
+ from []string
44
+ }
45
+
46
+ func readView(stmt *nodes.ViewStmt, sql string) view {
47
+ return selectInto(relationName(stmt.View), stmt.Query, false, sql)
48
+ }
49
+
50
+ // readMaterializedView reads the other spelling. The grammar calls it a CREATE
51
+ // TABLE AS whose object type is a matview, because that is what it is: a query
52
+ // whose rows are kept.
53
+ func readMaterializedView(stmt *nodes.CreateTableAsStmt, sql string) (view, bool) {
54
+ if stmt.Objtype != nodes.OBJECT_MATVIEW || stmt.Into == nil || stmt.Into.Rel == nil {
55
+ return view{}, false
56
+ }
57
+ query := stmt.Query
58
+ if query == nil {
59
+ query = stmt.Into.ViewQuery
60
+ }
61
+
62
+ return selectInto(relationName(stmt.Into.Rel), query, true, sql), true
63
+ }
64
+
65
+ func selectInto(name string, node nodes.Node, materialized bool, sql string) view {
66
+ out := view{name: name, materialized: materialized}
67
+
68
+ query, ok := node.(*nodes.SelectStmt)
69
+ if !ok {
70
+ return out
71
+ }
72
+
73
+ // alias -> relation, so `j.id` can be read as a column of journal_entries.
74
+ relations := map[string]string{}
75
+ readFrom(query.FromClause, relations, &out.reads)
76
+
77
+ for _, item := range items(query.TargetList) {
78
+ target, ok := item.(*nodes.ResTarget)
79
+ if !ok {
80
+ continue
81
+ }
82
+
83
+ var sources []string
84
+ columnRefs(target.Val, relations, &sources)
85
+
86
+ name := target.Name
87
+ if name == "" && len(sources) == 1 {
88
+ // `SELECT j.state` names its column after the column it takes.
89
+ name = sources[0][strings.LastIndex(sources[0], ".")+1:]
90
+ }
91
+ if name == "" {
92
+ continue
93
+ }
94
+ out.columns = append(out.columns, viewColumn{name: name, from: sources})
95
+ }
96
+
97
+ out.definition = definitionOf(sql, out.name, materialized)
98
+
99
+ return out
100
+ }
101
+
102
+ // readFrom walks the FROM clause, which is a tree once anything is joined.
103
+ func readFrom(list *nodes.List, relations map[string]string, reads *[]string) {
104
+ for _, item := range items(list) {
105
+ readFromItem(item, relations, reads)
106
+ }
107
+ }
108
+
109
+ func readFromItem(item nodes.Node, relations map[string]string, reads *[]string) {
110
+ switch node := item.(type) {
111
+ case *nodes.RangeVar:
112
+ name := relationName(node)
113
+ relations[node.Relname] = name
114
+ relations[name] = name
115
+ if node.Alias != nil && node.Alias.Aliasname != "" {
116
+ relations[node.Alias.Aliasname] = name
117
+ }
118
+ *reads = append(*reads, name)
119
+
120
+ case *nodes.JoinExpr:
121
+ readFromItem(node.Larg, relations, reads)
122
+ readFromItem(node.Rarg, relations, reads)
123
+ }
124
+ }
125
+
126
+ // columnRefs collects every column an expression reaches, however deep: a sum
127
+ // of a coalesce of a column is still that column's value arriving here.
128
+ func columnRefs(node nodes.Node, relations map[string]string, into *[]string) {
129
+ switch expression := node.(type) {
130
+ case *nodes.ColumnRef:
131
+ fields := stringList(expression.Fields)
132
+ if len(fields) == 0 {
133
+ return
134
+ }
135
+ column := fields[len(fields)-1]
136
+ relation := ""
137
+ if len(fields) > 1 {
138
+ relation = relations[fields[len(fields)-2]]
139
+ } else {
140
+ // A qualified relation has two lookup keys (base name and full
141
+ // name), but it is still only one FROM source.
142
+ for _, candidate := range relations {
143
+ if relation == "" {
144
+ relation = candidate
145
+ } else if relation != candidate {
146
+ relation = ""
147
+ break
148
+ }
149
+ }
150
+ }
151
+ if relation == "" || column == "*" {
152
+ return
153
+ }
154
+ *into = append(*into, relation+"."+column)
155
+
156
+ case *nodes.FuncCall:
157
+ for _, argument := range items(expression.Args) {
158
+ columnRefs(argument, relations, into)
159
+ }
160
+
161
+ case *nodes.CoalesceExpr:
162
+ for _, argument := range items(expression.Args) {
163
+ columnRefs(argument, relations, into)
164
+ }
165
+
166
+ case *nodes.A_Expr:
167
+ columnRefs(expression.Lexpr, relations, into)
168
+ columnRefs(expression.Rexpr, relations, into)
169
+
170
+ case *nodes.TypeCast:
171
+ columnRefs(expression.Arg, relations, into)
172
+
173
+ case *nodes.CaseExpr:
174
+ columnRefs(expression.Arg, relations, into)
175
+ for _, when := range items(expression.Args) {
176
+ if clause, ok := when.(*nodes.CaseWhen); ok {
177
+ columnRefs(clause.Expr, relations, into)
178
+ columnRefs(clause.Result, relations, into)
179
+ }
180
+ }
181
+ columnRefs(expression.Defresult, relations, into)
182
+ }
183
+ }
184
+
185
+ // definitionOf cuts the statement out of the file it was read from.
186
+ //
187
+ // The parse tree is not printed back: a reader comparing the page to the
188
+ // migration wants the SQL somebody wrote, down to the line breaks they chose.
189
+ func definitionOf(sql, name string, materialized bool) string {
190
+ lower := strings.ToLower(sql)
191
+ opening := "create view "
192
+ if materialized {
193
+ opening = "create materialized view "
194
+ }
195
+ at := strings.Index(lower, opening+strings.ToLower(name))
196
+ if at < 0 {
197
+ at = strings.Index(lower, "create or replace view "+strings.ToLower(name))
198
+ }
199
+ if at < 0 {
200
+ return ""
201
+ }
202
+ end := strings.Index(sql[at:], ";")
203
+ if end < 0 {
204
+ return strings.TrimSpace(sql[at:])
205
+ }
206
+
207
+ return strings.TrimSpace(sql[at : at+end+1])
208
+ }
209
+
210
+ // asCatalog turns the names into ids, and takes what the statement does not
211
+ // say - a column's type, and whether it can be null - from the column it is
212
+ // computed from.
213
+ func (v view) asCatalog(storeID, source string, tables []catalog.Table) catalog.View {
214
+ out := catalog.View{
215
+ ID: storeID + "." + v.name,
216
+ Name: v.name,
217
+ Doc: v.doc,
218
+ Materialized: v.materialized,
219
+ Definition: v.definition,
220
+ Source: source,
221
+ }
222
+ for _, relation := range v.reads {
223
+ out.Reads = append(out.Reads, storeID+"."+relation)
224
+ }
225
+
226
+ for _, column := range v.columns {
227
+ held := catalog.Column{Name: column.name, Nullable: true}
228
+ for _, from := range column.from {
229
+ held.From = append(held.From, storeID+"."+from)
230
+ }
231
+ if len(column.from) == 1 {
232
+ at := strings.LastIndex(column.from[0], ".")
233
+ if at < 0 {
234
+ continue
235
+ }
236
+ relation, name := column.from[0][:at], column.from[0][at+1:]
237
+ if source := columnOf(tables, storeID+"."+relation, name); source != nil {
238
+ held.Type = source.Type
239
+ held.Nullable = source.Nullable
240
+ held.Maps = source.Maps
241
+ }
242
+ }
243
+ out.Columns = append(out.Columns, held)
244
+ }
245
+
246
+ // What it holds is what the relation it is built on holds: a view over one
247
+ // aggregate's tables is another way of reading that aggregate, and a view
248
+ // that draws on several says nothing here rather than picking one.
249
+ persists := ""
250
+ for _, relation := range v.reads {
251
+ table := tableOf(tables, storeID+"."+relation)
252
+ if table == nil || table.Persists == nil {
253
+ continue
254
+ }
255
+ if persists == "" {
256
+ persists = table.Persists.Aggregate
257
+
258
+ continue
259
+ }
260
+ if persists != table.Persists.Aggregate {
261
+ persists = ""
262
+
263
+ break
264
+ }
265
+ }
266
+ if persists != "" {
267
+ out.Persists = &catalog.Persists{Aggregate: persists}
268
+ }
269
+
270
+ return out
271
+ }
272
+
273
+ func tableOf(tables []catalog.Table, id string) *catalog.Table {
274
+ for i := range tables {
275
+ if tables[i].ID == id {
276
+ return &tables[i]
277
+ }
278
+ }
279
+
280
+ return nil
281
+ }
282
+
283
+ func columnOf(tables []catalog.Table, tableID, name string) *catalog.Column {
284
+ table := tableOf(tables, tableID)
285
+ if table == nil {
286
+ return nil
287
+ }
288
+ for i := range table.Columns {
289
+ if table.Columns[i].Name == name {
290
+ return &table.Columns[i]
291
+ }
292
+ }
293
+
294
+ return nil
295
+ }
@@ -0,0 +1,306 @@
1
+ # extract-ts
2
+
3
+ A TypeScript or JavaScript service in, a catalog fragment out. The TypeScript twin of
4
+ `extract-go`: it describes one service - its aggregates, what they publish,
5
+ what runs when somebody calls in, what the service calls - by reading the
6
+ tree, and it reads the tree by its layout. Nothing is annotated for the
7
+ catalog; the layout is the claim.
8
+
9
+ Written in TypeScript and run as a process plugin, `node plugins/extract-ts/main.ts`,
10
+ because the catalog's own types in `src/catalog.ts` are the fragment's types.
11
+ The parser is oxc-parser: native, with no TypeScript inside it, handing back
12
+ an ESTree with the TypeScript nodes typescript-eslint would give. The
13
+ project's TypeScript is the 7 series, a compiler with no syntax tree to offer,
14
+ and holding a second copy of 5 beside it for the parser alone was a workaround
15
+ this replaces. The tree is read through `ast.ts`, a hand-written, minimal set
16
+ of node shapes and predicates, so the reading does not move when the parser's
17
+ own typings do. There is no type checker: everything is resolved by name and by import - the
18
+ resolver is `oxc-resolver`, so a tsconfig `paths` alias and a workspace package
19
+ resolve as they would for Node and TypeScript - which is all a layout that is
20
+ the claim needs.
21
+
22
+ ## The layout it reads
23
+
24
+ ```
25
+ src/
26
+ domain/<aggregate>/
27
+ <aggregate>.ts the root: a class named like the directory, in PascalCase
28
+ *.ts entities: other classes exported from the directory's own files
29
+ vo/*.ts value objects: one class per file
30
+ rules/*.ts specifications; skipped, they are not shapes
31
+ events/*.ts one class per event, `readonly name = "<service>.<Name>"`
32
+ port.ts interfaces a use case holds: repositories, publishers
33
+ status.ts optional: `export const TRANSITIONS = { open: ["checked-out"], … }`, the root's lifecycle
34
+ README.md the aggregate's page, or the doc comment above the root class
35
+ application/<aggregate>/usecases/<name>/
36
+ usecase.ts `export class UseCase` with a `handle(...)` method
37
+ README.md the operation's doc, or the doc comment above the class
38
+ application/policy/*.ts one class per policy, `handle(event)` reacting to one event
39
+ infrastructure/transport/http/
40
+ gen/openapi.yaml the document; operationIds name the handlers
41
+ <pkg>/*.ts handlers: `async <operationId>(...)` methods on a class holding use cases
42
+ schema/<module>/
43
+ schema.graphql the contract, read by extract-graphql rather than here
44
+ resolvers/<Root>/<field>.ts
45
+ one file per field of Query, Mutation or Subscription,
46
+ exporting the field's own name; the third parameter is
47
+ the context, and `ctx.<port>.<method>(...)` is a hop
48
+ <anywhere>/context.ts `export interface GraphQLContext` - the ports every
49
+ resolver may reach, which is what a use case says in
50
+ its constructor
51
+ ports/*.ts ports a service with no use cases declares on their own
52
+ infrastructure/<peer>/
53
+ gen/openapi.yaml + gen/types.ts an HTTP peer: the vendored document and `openapi-typescript` output
54
+ proto/**/*.proto + gen/*_pb.ts a gRPC peer: the vendored contract and Connect-ES output
55
+ client.ts the adapter over the generated client, implementing a use case's port
56
+ infrastructure/repository/<aggregate>/
57
+ migrations/*.sql read by extract-sql, with `repositories` pointed at the directory above
58
+ di/**/*.ts which adapter or use case fills a port: `export function provideX(deps): Port`,
59
+ or an Inversify container's `bind<Port>(TOKENS.X).to(Impl)` or
60
+ `.toConstantValue(new Impl(...))`; a port bound more than once - the adapter
61
+ behind a setting, a stand-in without - shows as the binding that reaches a
62
+ peer; a use case's constructor may carry `@inject(TOKENS.X)`, the type
63
+ beside it is still the port
64
+ ```
65
+
66
+ ## A service whose way in is a graph
67
+
68
+ A BFF has no aggregates, no store and no use cases: it composes what other
69
+ services decided, and there is nothing left for it to decide. Told where the
70
+ schema is - the `graphql` option, `src/schema` by convention - this reader
71
+ opens a flow on each resolver instead of on an HTTP or gRPC endpoint, and does
72
+ not report the missing domain.
73
+
74
+ A resolver's ports do not arrive in a constructor. The signature comes from
75
+ the generated resolver type, so the context parameter is typed by where it
76
+ sits rather than by anything written in the file, and the ports are read once
77
+ from the one exported `GraphQLContext` interface - the name codegen's own
78
+ `contextType` conventionally points at. From there everything is the same as
79
+ inside a use case: `ctx.baskets.byId(...)` is a port call, assembly says what
80
+ fills the port, and the adapter behind it names the peer.
81
+
82
+ The field is called what `extract-graphql` calls it - `Query.basket`,
83
+ `Mutation.checkout` - because the directory a resolver sits in is the root
84
+ type and the file is the field. That is why nothing here parses a schema: the
85
+ layout already says what the SDL would.
86
+
87
+ An adapter over the bus is the one port call that draws no step. It calls
88
+ nobody - it waits - and what it hears is said by the channel the service
89
+ declares in its AsyncAPI document, not by a step in a flow.
90
+
91
+ ## A service written in JavaScript
92
+
93
+ The same layout in `.js` (or `.mjs`, `.jsx`) reads the same way. What the
94
+ syntax cannot say, the doc comments do, in the form `tsc --checkJs` reads:
95
+
96
+ | in TypeScript | in JavaScript |
97
+ | --- | --- |
98
+ | `readonly items: BasketItem[] = []` | `/** @type {BasketItem[]} */ items = [];` |
99
+ | `constructor(readonly id: string)` | `/** @param {string} id */ constructor(id) { this.id = id; }` - a field is what the constructor assigns to `this`, typed by the parameter it takes or by what it is given |
100
+ | `handle(input: Input): Promise<void>` | `/** @param {Input} input @returns {Promise<void>} */ handle(input)` |
101
+ | `export interface Port { save(b: Basket): Promise<void> }` | `/** @typedef {{ save(b: Basket): Promise<void> }} Port */`, or `@typedef {Object} Port` with one `@property {type} name` per member |
102
+ | `import type { Port } from "./port.ts"` | `/** @typedef {import("./port.js").Port} Port */`, or `import("./port.js").Port` written inline in any type |
103
+ | `bind<Port>(TOKENS.Port)` | `bind(TOKENS.Port)` - the token's name is the port's |
104
+ | `function provideX(deps): Port` | `/** @returns {Port} */ function provideX(deps)` |
105
+ | `gen/types.ts`, `gen/**/x_pb.ts` | `gen/types.d.ts`, `gen/**/x_pb.js` |
106
+
107
+ A type expression in a comment is TypeScript's own syntax, so it is parsed
108
+ as one - `let _: <expr>` - and read by the same code that reads an
109
+ annotation. Closure's `?T` and `Array.<T>` are not, and read as nothing.
110
+ `@param`, `@returns` and `@type` are read only where the syntax has no
111
+ annotation, so a TypeScript file that leaves a field untyped and documents it
112
+ instead reads that too. Decorators are not JavaScript; assembly in a
113
+ JavaScript tree is the container's `bind(...)` calls or the `provideX`
114
+ functions, which need none.
115
+
116
+ `testdata/cart-js` is `testdata/cart` written in JavaScript, file for file,
117
+ and the test is that both read to one fragment.
118
+
119
+ ## What a doc comment says
120
+
121
+ The `/** … */` above a class, a field or a constructor parameter property is
122
+ its doc, read the way [JSDoc](https://jsdoc.app/) and TSDoc say to: the prose
123
+ above the first tag, then the tags. Most tags are for a type checker or a site
124
+ generator and are dropped - `@param`, `@returns`, `@see`, `@fires` - because
125
+ the layout and the signature already say what they would, and a tag that
126
+ restates the code is one more place for it to go stale. Three are kept:
127
+
128
+ | tag | becomes |
129
+ | --- | --- |
130
+ | `@remarks` | the paragraphs after the summary, in the same doc: TSDoc's long description is still the description |
131
+ | `@example` | a fenced block in the aggregate's readme when the root has no `README.md`; elsewhere an example is code where a sentence should be, and is left out |
132
+ | `@deprecated` | `deprecated: true` on the entity, value object, field, event version or operation, which the page strikes through and badges; the reason, when one follows the tag, is appended to the doc as "Deprecated: …" - except for an operation, whose doc stays the one paragraph its README or summary gives |
133
+
134
+ An inline `{@link X}` is flattened to `X`, or to its label when it has one
135
+ (`{@link X|label}`, `[label]{@link X}`): the catalog has no way to say from
136
+ inside a sentence that a name is a page, so the name is kept as a word rather
137
+ than left as a tag nobody renders.
138
+
139
+ ## What becomes what
140
+
141
+ **Aggregate.** Every directory under `src/domain/` whose name has a root class
142
+ in it. The root is the class whose name is the directory's in PascalCase
143
+ (`basket` → `Basket`); a directory without one is reported and skipped. Its
144
+ fields are the class's property declarations and constructor parameter
145
+ properties, `readonly id: string` and `constructor(readonly id: string)` alike,
146
+ with the type as written. Other classes exported from the directory's top-level
147
+ files are entities; classes in `vo/` are value objects; `rules/` is skipped.
148
+ The readme is `README.md` in the directory, or the doc comment above the root,
149
+ its `@example`s fenced as code.
150
+
151
+ **Event.** Each class in `events/` with a `name` property initialised to a
152
+ string literal - `readonly name = "cart.BasketCheckedOut"` or `static readonly
153
+ name` - is an event of the aggregate, its id `<service>.<aggregate>.<Class>`.
154
+ Fields as for a root; doc from JSDoc; one version, `v1`; `consumers` empty,
155
+ because a service does not know who listens - the merge is where the other end
156
+ arrives, and the flows imply the rest.
157
+
158
+ **Operation.** Each `application/<aggregate>/usecases/<name>/usecase.ts`
159
+ exporting a class `UseCase` with a method `handle`. The id is the directory's
160
+ name in PascalCase (`add_item` → `AddItem`). It is a command when `handle` -
161
+ or a private method it calls - calls `save`, `delete`, `create`, `update` or
162
+ `publish` on a port, else a query. The doc is the directory's `README.md`
163
+ first paragraph, or the JSDoc above the class. `exposedBy` names the HTTP
164
+ operations that run it, read from the handlers.
165
+
166
+ **Port.** A constructor parameter of `UseCase` typed with an interface or a
167
+ class. What it is decides what a call on it becomes:
168
+
169
+ | the type is | a call on it is |
170
+ | --- | --- |
171
+ | an interface from `domain/<aggregate>/port.ts` | a `call` into the store lane, named by the method; an argument that holds an event is the event leaving for the bus |
172
+ | another `UseCase` | a `call` to the service itself, and that use case's own steps, inlined two deep at most |
173
+ | an interface bound in `di/` to a use case | the same |
174
+ | an interface bound in `di/` to an adapter over a generated client | an `rpc` to the peer, read through the adapter's method to the client's call |
175
+ | an interface another use case declares, imported from its `usecase.ts` | whatever that use case's binding says: the port is looked up under the use case that declares it |
176
+ | the generated client itself | an `rpc` to the peer |
177
+ | a function type, `() => Date` | nothing: a clock is a port with nobody at the other end |
178
+
179
+ **Lifecycle.** An aggregate whose directory exports a `TRANSITIONS` table -
180
+ an object literal, each state to the states it may become - gets a
181
+ `lifecycle`: the states in the table's order, the first being where a new
182
+ root starts, and one move per edge. The method of the root that assigns
183
+ `this.status` is the mover; every public method that calls it with a literal
184
+ (`this.moveTo("checked-out", now)`) makes the edges into that state, and
185
+ `emits` is the event its return type names. A status assigned anywhere else,
186
+ a move into a state the table lacks, and an edge in the table no method makes
187
+ are each reported. A state nothing leads out of is terminal; that is derived
188
+ on the page, never written down.
189
+
190
+ **Flow, from an endpoint.** Each handler method named by an `operationId` in
191
+ `transport/http/gen/openapi.yaml` opens a flow: `client → service : rpc
192
+ <operationId>`, then the steps of every use case the handler runs, in the order
193
+ it runs them. **Flow, from a policy.** Each class in `application/policy/` with
194
+ a `handle` opens a flow on the bus: `bus → service : event <ref>`, where the
195
+ event is what the body tests for - `event instanceof BasketCheckedOut`, `event
196
+ .name === "cart.BasketCheckedOut"`, or a `switch` on `event.name`. An event
197
+ imported from outside `src/domain` is another service's; with a line in the
198
+ `events` option mapping the import to an aggregate id it resolves, without one
199
+ the step names the type and is unresolved.
200
+
201
+ **Inside a body.** Statements are read in source order. A call on a port is a
202
+ hop; a call on `this.<method>` is followed into the method; `if` and `switch`
203
+ become an `alt` when some arm holds a hop, an arm that `return`s or `throw`s
204
+ is terminal; `for`, `for … of`, `while` become a note on the steps inside;
205
+ `await` is transparent; a `.then(...)` chain is followed as a call. Every step
206
+ is `declared`: this reads code, and code is a claim about behaviour, not a
207
+ record of it. A call whose peer the manifest does not name is `unresolved`.
208
+
209
+ **What a name holds.** A value is followed back to its type by name, without a
210
+ checker: what a domain constructor, a domain method or a port method hands
211
+ back, as its return type is written - `Promise<[Basket, BasketCreated]>` binds
212
+ both by position - and what a helper function anywhere under `src/` returns
213
+ when its return type names something of an aggregate (`holderOf(repo, id,
214
+ token): Promise<Basket>`). `for (const basket of idle)` holds one of what
215
+ `idle` holds; `into = created` holds what `created` held; `events.push(x)`
216
+ collects what `x` holds, and `...events` handed to a port is each event
217
+ collected, once. An event handed to a domain port is the event leaving for the
218
+ bus; a field read off one is not.
219
+
220
+ **HTTP peer.** A generated `openapi-fetch` client is called with the verb and
221
+ the path in the code - `client.GET("/v1/sessions/current", …)` - and the
222
+ document vendored beside `gen/types.ts` says which operation answers on that
223
+ route and which interface it belongs to, spelled by `plugins/openapi` so the
224
+ call and the method on the other side share one id: `auth.v1.Sessions/validateSession`.
225
+ **gRPC peer.** A Connect-ES client is created from a service descriptor whose
226
+ `typeName` is the proto service, `shop.v1.Pricing`, and a call on it is the
227
+ method in the descriptor's own case: `client.getQuote(…)` is
228
+ `shop.v1.Pricing/GetQuote`. The descriptor is imported from under `gen/`,
229
+ however deep its package path put it, and the service is looked up in the
230
+ `.proto` files vendored under `proto/` beside that `gen/`. Either way the peer is the manifest's `peers`
231
+ entry for the api id or the proto package; without one the lane is `unknown`
232
+ and the step unresolved, and the call is recorded on the service's `consumes`
233
+ with the vendored document as its source.
234
+
235
+ ## Options
236
+
237
+ ```json
238
+ {
239
+ "context": "shop",
240
+ "contextName": "Shop",
241
+ "service": "cart",
242
+ "store": "pg",
243
+ "peers": { "auth.v1": "auth.auth", "shop.v1": "shop.pricing" },
244
+ "events": { "@acme/payments-events": "payments.ledger.payment" },
245
+ "source": "src",
246
+ "out": "domain.json"
247
+ }
248
+ ```
249
+
250
+ `source` is the directory the layout starts in, `src` unless said otherwise.
251
+ Everything else means what it means for `extract-go`.
252
+
253
+ ## Extraction limits
254
+
255
+ These cases do not become facts in the fragment:
256
+
257
+ - a domain directory with no root class of its name;
258
+ - a use case directory with no `UseCase`, or a `UseCase` with no `handle`;
259
+ - a port whose type is neither a domain port, a use case, nor a client, whose
260
+ calls are therefore left out;
261
+ - a handler named by no `operationId`, and an `operationId` with no handler;
262
+ - a policy whose `handle` tests for no event;
263
+ - a peer package with no document beside it, or a route the document does not
264
+ declare;
265
+ - an event no flow reaches;
266
+ - a proto package or api id the manifest names no peer for.
267
+ - an import of a dependency: what lands in `node_modules` is not read, so a
268
+ port declared by a published package is a name with nothing behind it. A
269
+ tsconfig `paths` alias and a workspace package are followed, because they
270
+ resolve to the repository's own files.
271
+ - a file with a syntax error, past the error: the tree up to it is read, the
272
+ rest is not, and the warning says where.
273
+
274
+ ## Manifest
275
+
276
+ ```json
277
+ {
278
+ "plugins": [{ "name": "ts-domain", "process": { "command": "node", "args": ["plugins/extract-ts/main.ts"] } }],
279
+ "extract": [
280
+ { "plugin": "ts-domain", "in": "examples/shop/cart", "out": "examples/shop/cart/portolan",
281
+ "options": { "context": "shop", "service": "cart", "store": "pg",
282
+ "peers": { "auth.v1": "auth.auth", "shop.v1": "shop.pricing" }, "out": "domain.json" } },
283
+ { "plugin": "openapi", "in": "examples/shop/cart", "out": "examples/shop/cart/portolan",
284
+ "options": { "context": "shop", "service": "cart",
285
+ "spec": "src/infrastructure/transport/http/gen/openapi.yaml", "out": "api.json" } },
286
+ { "plugin": "sql", "in": "examples/shop/cart", "out": "examples/shop/cart/portolan",
287
+ "options": { "context": "shop", "service": "cart", "store": "pg", "name": "Cart database",
288
+ "repositories": "src/infrastructure/repository", "out": "stores.json" } }
289
+ ],
290
+ "verify": [
291
+ { "plugin": "otel", "in": "examples/shop/cart", "out": "examples/shop/cart/portolan",
292
+ "options": { "traces": ["telemetry/traces.jsonl"], "out": "observed.json" } }
293
+ ]
294
+ }
295
+ ```
296
+
297
+ `extract-sql`'s `repositories` points it at the adapters: its default is the
298
+ Go layout, `internal/infrastructure/repository`, and a TypeScript service
299
+ keeps the same shape one directory over, `<aggregate>/migrations` under it.
300
+
301
+ ## Tests
302
+
303
+ The reader is held to fixtures under `testdata/`: a small service in the
304
+ layout above, each shape it claims to read present once, and a golden
305
+ fragment. `examples/shop/cart/portolan/domain.json` is the second golden, held
306
+ by `gen:check` like every other fragment.