@shortlink-org/portolan 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (381) hide show
  1. package/README.md +69 -205
  2. package/cli/init.mjs +285 -0
  3. package/cli/init.test.mjs +158 -0
  4. package/cli/portolan.mjs +37 -73
  5. package/index.html +19 -0
  6. package/package.json +5 -10
  7. package/plugins/README.md +66 -27
  8. package/plugins/portolan-go.wasm +0 -0
  9. package/portolan.json +52 -73
  10. package/public/landing/cats/bug-hunter.webp +0 -0
  11. package/public/landing/cats/compass-nap.webp +0 -0
  12. package/public/landing/cats/diagrammer.webp +0 -0
  13. package/public/landing/cats/docs-reader.webp +0 -0
  14. package/public/landing/cats/laptop.webp +0 -0
  15. package/public/landing/cats/map-inspector.webp +0 -0
  16. package/public/landing/cats/server-break.webp +0 -0
  17. package/public/landing/cats/star-mapper.webp +0 -0
  18. package/public/landing/cats/system-builder.webp +0 -0
  19. package/public/landing/cats/thread-tangle.webp +0 -0
  20. package/public/og.png +0 -0
  21. package/public/readme-header.webp +0 -0
  22. package/schema/portolan.schema.json +180 -0
  23. package/scripts/builtin-plugins.mjs +14 -0
  24. package/scripts/delivery-presets.mjs +353 -0
  25. package/scripts/gen.mjs +37 -4
  26. package/scripts/history.mjs +126 -0
  27. package/scripts/history.test.mjs +110 -0
  28. package/scripts/host-plugins/fetch-bsr.mjs +351 -0
  29. package/{plugins/fetch-bsr/options.schema.json → scripts/host-plugins/fetch-bsr.options.json} +4 -0
  30. package/scripts/host-plugins/fetch-bsr.test.mjs +212 -0
  31. package/scripts/host-plugins/fetch-csr.mjs +386 -0
  32. package/scripts/host-plugins/fetch-csr.test.mjs +178 -0
  33. package/scripts/host-plugins/fetch-git.mjs +379 -0
  34. package/scripts/host-plugins/fetch-git.test.mjs +210 -0
  35. package/scripts/local-api.mjs +22 -4
  36. package/scripts/local-api.test.mjs +84 -2
  37. package/scripts/manifest.mjs +3 -2
  38. package/scripts/package-smoke.mjs +6 -2
  39. package/scripts/plugin-host.mjs +77 -18
  40. package/scripts/plugin-host.test.mjs +50 -1
  41. package/scripts/plugin-wasm-worker.mjs +6 -3
  42. package/scripts/run-builtin.mjs +6 -26
  43. package/scripts/schema.mjs +6 -1
  44. package/src/app/App.tsx +24 -429
  45. package/src/app/Breadcrumbs.test.ts +7 -0
  46. package/src/app/Breadcrumbs.tsx +15 -2
  47. package/src/app/CatalogApp.tsx +436 -0
  48. package/src/app/Sidebar.tsx +0 -1
  49. package/src/chat/ChatPanel.tsx +98 -41
  50. package/src/chat/Composer.tsx +4 -2
  51. package/src/chat/Conversation.tsx +79 -15
  52. package/src/chat/Header.tsx +43 -9
  53. package/src/chat/Starter.tsx +64 -3
  54. package/src/chat/Steps.tsx +1 -1
  55. package/src/chat/flags.test.ts +51 -14
  56. package/src/chat/flags.ts +8 -2
  57. package/src/chat/page-context.test.ts +51 -0
  58. package/src/chat/page-context.ts +128 -0
  59. package/src/chat/prompt.test.ts +49 -1
  60. package/src/chat/prompt.ts +42 -1
  61. package/src/chat/tools.ts +7 -2
  62. package/src/chat/transport.ts +16 -4
  63. package/src/components/ProblemRow.tsx +182 -0
  64. package/src/data.ts +20 -5
  65. package/src/er/ErCanvas.tsx +1 -1
  66. package/src/graph/DependencyGraph.tsx +10 -1
  67. package/src/graph/FocusedEventGraph.tsx +1 -1
  68. package/src/graph/GraphToolbar.tsx +2 -4
  69. package/src/index.css +220 -2
  70. package/src/landing/DraggableReveal.tsx +168 -0
  71. package/src/landing/EstateGraph.tsx +28 -0
  72. package/src/landing/FlowPlayback.tsx +282 -0
  73. package/src/landing/HeroMap.tsx +128 -0
  74. package/src/landing/LandingPage.tsx +757 -0
  75. package/src/landing/ProductFrame.tsx +68 -0
  76. package/src/landing/ProductTour.tsx +371 -0
  77. package/src/landing/catalog.ts +25 -0
  78. package/src/landing/motion.tsx +52 -0
  79. package/src/lib/all-problems.ts +28 -0
  80. package/src/lib/local-api.ts +35 -1
  81. package/src/lib/setup-info.test.ts +8 -0
  82. package/src/lib/setup-info.ts +3 -2
  83. package/src/lib/source-code.ts +2 -1
  84. package/src/likec4/C4View.tsx +5 -0
  85. package/src/likec4/InteractiveView.tsx +5 -1
  86. package/src/map/ContextMapGraph.tsx +47 -20
  87. package/src/pages/ContextMap.tsx +5 -1
  88. package/src/pages/FlowDetail.tsx +24 -7
  89. package/src/pages/Overview.tsx +68 -12
  90. package/src/pages/Problems.tsx +6 -193
  91. package/src/pages/Settings.tsx +133 -108
  92. package/src/pages/settings/DeliverySettings.tsx +229 -0
  93. package/src/pages/settings/PreferencesSettings.tsx +101 -0
  94. package/src/routes.test.ts +20 -0
  95. package/src/routes.ts +13 -1
  96. package/vite.config.ts +12 -8
  97. package/catalog/enum_test.go +0 -46
  98. package/catalog/model.go +0 -932
  99. package/catalog/roundtrip_test.go +0 -185
  100. package/catalog/via_test.go +0 -38
  101. package/go.mod +0 -14
  102. package/go.sum +0 -14
  103. package/internal/commands/cargo.go +0 -154
  104. package/internal/commands/commands.go +0 -143
  105. package/internal/commands/commands_test.go +0 -323
  106. package/internal/commands/gradle.go +0 -77
  107. package/internal/commands/justfile.go +0 -82
  108. package/internal/commands/makefile.go +0 -106
  109. package/internal/commands/maven.go +0 -93
  110. package/internal/commands/packagejson.go +0 -159
  111. package/internal/commands/pyproject.go +0 -169
  112. package/internal/commands/taskfile.go +0 -101
  113. package/internal/commands/testdata/estate/.cargo/config.toml +0 -7
  114. package/internal/commands/testdata/estate/Makefile +0 -33
  115. package/internal/commands/testdata/estate/Taskfile.yml +0 -21
  116. package/internal/commands/testdata/estate/build.gradle.kts +0 -21
  117. package/internal/commands/testdata/estate/justfile +0 -20
  118. package/internal/commands/testdata/estate/package.json +0 -13
  119. package/internal/commands/testdata/estate/pom.xml +0 -29
  120. package/internal/commands/testdata/estate/pyproject.toml +0 -27
  121. package/internal/commands/testdata/estate/xtask/src/main.rs +0 -27
  122. package/internal/commands/testdata/golden/commands.json +0 -305
  123. package/internal/gohttp/analyze.go +0 -2500
  124. package/internal/gohttp/endpoints.go +0 -1067
  125. package/internal/gohttp/roots.go +0 -320
  126. package/internal/gohttp/typed.go +0 -143
  127. package/internal/goscan/constants.go +0 -85
  128. package/internal/goscan/goscan_test.go +0 -227
  129. package/internal/goscan/names.go +0 -52
  130. package/internal/goscan/parse_test.go +0 -11
  131. package/internal/goscan/source.go +0 -36
  132. package/internal/goscan/tree.go +0 -155
  133. package/internal/goscan/types.go +0 -99
  134. package/internal/wsdl/ids.go +0 -127
  135. package/internal/wsdl/ids_test.go +0 -21
  136. package/internal/wsdl/model.go +0 -62
  137. package/internal/wsdl/parse.go +0 -920
  138. package/internal/wsdl/parse_test.go +0 -133
  139. package/plugin/describe.go +0 -107
  140. package/plugin/describe_test.go +0 -114
  141. package/plugin/protocol.go +0 -117
  142. package/plugin/schematest/schematest.go +0 -126
  143. package/plugins/extract-adr/describe.go +0 -19
  144. package/plugins/extract-adr/describe_test.go +0 -11
  145. package/plugins/extract-adr/extract.go +0 -153
  146. package/plugins/extract-adr/extract_test.go +0 -350
  147. package/plugins/extract-adr/history.go +0 -99
  148. package/plugins/extract-adr/main.go +0 -65
  149. package/plugins/extract-adr/parse.go +0 -642
  150. package/plugins/extract-adr/parse_test.go +0 -405
  151. package/plugins/extract-asyncapi/describe.go +0 -19
  152. package/plugins/extract-asyncapi/describe_test.go +0 -11
  153. package/plugins/extract-asyncapi/extract.go +0 -315
  154. package/plugins/extract-asyncapi/extract_test.go +0 -197
  155. package/plugins/extract-asyncapi/main.go +0 -48
  156. package/plugins/extract-asyncapi/spec.go +0 -151
  157. package/plugins/extract-commands/describe.go +0 -19
  158. package/plugins/extract-commands/describe_test.go +0 -11
  159. package/plugins/extract-commands/extract.go +0 -79
  160. package/plugins/extract-commands/extract_test.go +0 -92
  161. package/plugins/extract-commands/main.go +0 -55
  162. package/plugins/extract-csr/avro.go +0 -258
  163. package/plugins/extract-csr/describe.go +0 -19
  164. package/plugins/extract-csr/describe_test.go +0 -11
  165. package/plugins/extract-csr/extract.go +0 -338
  166. package/plugins/extract-csr/extract_test.go +0 -374
  167. package/plugins/extract-csr/jsonschema.go +0 -343
  168. package/plugins/extract-csr/lock.go +0 -25
  169. package/plugins/extract-csr/main.go +0 -84
  170. package/plugins/extract-csr/subject.go +0 -102
  171. package/plugins/extract-flows/describe.go +0 -19
  172. package/plugins/extract-flows/describe_test.go +0 -11
  173. package/plugins/extract-flows/extract.go +0 -91
  174. package/plugins/extract-flows/main.go +0 -45
  175. package/plugins/extract-flows/parse.go +0 -593
  176. package/plugins/extract-flows/parse_test.go +0 -204
  177. package/plugins/extract-glossary/describe.go +0 -19
  178. package/plugins/extract-glossary/describe_test.go +0 -11
  179. package/plugins/extract-glossary/extract.go +0 -115
  180. package/plugins/extract-glossary/extract_test.go +0 -220
  181. package/plugins/extract-glossary/main.go +0 -59
  182. package/plugins/extract-glossary/parse.go +0 -214
  183. package/plugins/extract-glossary/parse_test.go +0 -203
  184. package/plugins/extract-go/aggregate.go +0 -214
  185. package/plugins/extract-go/client.go +0 -409
  186. package/plugins/extract-go/client_test.go +0 -266
  187. package/plugins/extract-go/describe.go +0 -19
  188. package/plugins/extract-go/describe_test.go +0 -11
  189. package/plugins/extract-go/enum.go +0 -195
  190. package/plugins/extract-go/enum_test.go +0 -82
  191. package/plugins/extract-go/event.go +0 -99
  192. package/plugins/extract-go/extract.go +0 -191
  193. package/plugins/extract-go/extract_test.go +0 -261
  194. package/plugins/extract-go/flow.go +0 -1441
  195. package/plugins/extract-go/flow_test.go +0 -609
  196. package/plugins/extract-go/httpclient.go +0 -174
  197. package/plugins/extract-go/httpclient_test.go +0 -296
  198. package/plugins/extract-go/ids.go +0 -92
  199. package/plugins/extract-go/layout.go +0 -225
  200. package/plugins/extract-go/layout_test.go +0 -125
  201. package/plugins/extract-go/lifecycle.go +0 -324
  202. package/plugins/extract-go/lifecycle_test.go +0 -108
  203. package/plugins/extract-go/main.go +0 -79
  204. package/plugins/extract-go/operation.go +0 -157
  205. package/plugins/extract-go/source.go +0 -316
  206. package/plugins/extract-go/transport.go +0 -321
  207. package/plugins/extract-go/transport_test.go +0 -145
  208. package/plugins/extract-go/wiring.go +0 -434
  209. package/plugins/extract-go-nats/describe.go +0 -19
  210. package/plugins/extract-go-nats/describe_test.go +0 -11
  211. package/plugins/extract-go-nats/extract.go +0 -177
  212. package/plugins/extract-go-nats/extract_test.go +0 -389
  213. package/plugins/extract-go-nats/index.go +0 -379
  214. package/plugins/extract-go-nats/main.go +0 -42
  215. package/plugins/extract-go-nats/resolve.go +0 -161
  216. package/plugins/extract-go-nats/sites.go +0 -224
  217. package/plugins/extract-graphql/describe.go +0 -19
  218. package/plugins/extract-graphql/describe_test.go +0 -11
  219. package/plugins/extract-graphql/extract.go +0 -433
  220. package/plugins/extract-graphql/extract_test.go +0 -256
  221. package/plugins/extract-graphql/ids.go +0 -49
  222. package/plugins/extract-graphql/lex.go +0 -237
  223. package/plugins/extract-graphql/main.go +0 -51
  224. package/plugins/extract-graphql/parse.go +0 -621
  225. package/plugins/extract-graphql/parse_test.go +0 -122
  226. package/plugins/extract-http-clients/describe.go +0 -19
  227. package/plugins/extract-http-clients/describe_test.go +0 -11
  228. package/plugins/extract-http-clients/extract.go +0 -705
  229. package/plugins/extract-http-clients/extract_test.go +0 -1263
  230. package/plugins/extract-http-clients/main.go +0 -42
  231. package/plugins/extract-openapi/describe.go +0 -19
  232. package/plugins/extract-openapi/describe_test.go +0 -11
  233. package/plugins/extract-openapi/discover.go +0 -243
  234. package/plugins/extract-openapi/extract.go +0 -526
  235. package/plugins/extract-openapi/extract_test.go +0 -545
  236. package/plugins/extract-openapi/main.go +0 -75
  237. package/plugins/extract-openapi/spec.go +0 -350
  238. package/plugins/extract-project/describe.go +0 -19
  239. package/plugins/extract-project/describe_test.go +0 -11
  240. package/plugins/extract-project/extract.go +0 -221
  241. package/plugins/extract-project/extract_test.go +0 -109
  242. package/plugins/extract-project/main.go +0 -41
  243. package/plugins/extract-proto/ast.go +0 -125
  244. package/plugins/extract-proto/consumes.go +0 -77
  245. package/plugins/extract-proto/describe.go +0 -19
  246. package/plugins/extract-proto/extract.go +0 -293
  247. package/plugins/extract-proto/extract_test.go +0 -459
  248. package/plugins/extract-proto/ids.go +0 -89
  249. package/plugins/extract-proto/ids_test.go +0 -57
  250. package/plugins/extract-proto/lex.go +0 -285
  251. package/plugins/extract-proto/main.go +0 -100
  252. package/plugins/extract-proto/module.go +0 -120
  253. package/plugins/extract-proto/parse.go +0 -720
  254. package/plugins/extract-proto/parse_test.go +0 -307
  255. package/plugins/extract-proto/provides.go +0 -236
  256. package/plugins/extract-proto/resolve.go +0 -222
  257. package/plugins/extract-proto/resolve_test.go +0 -119
  258. package/plugins/extract-redis/describe.go +0 -19
  259. package/plugins/extract-redis/describe_test.go +0 -11
  260. package/plugins/extract-redis/extract.go +0 -183
  261. package/plugins/extract-redis/extract_test.go +0 -168
  262. package/plugins/extract-redis/keyspaces.go +0 -469
  263. package/plugins/extract-redis/main.go +0 -44
  264. package/plugins/extract-river/describe.go +0 -19
  265. package/plugins/extract-river/describe_test.go +0 -11
  266. package/plugins/extract-river/extract.go +0 -507
  267. package/plugins/extract-river/extract_test.go +0 -132
  268. package/plugins/extract-river/main.go +0 -42
  269. package/plugins/extract-sql/ddl.go +0 -893
  270. package/plugins/extract-sql/ddl_test.go +0 -401
  271. package/plugins/extract-sql/describe.go +0 -19
  272. package/plugins/extract-sql/describe_test.go +0 -11
  273. package/plugins/extract-sql/layout.go +0 -221
  274. package/plugins/extract-sql/layout_test.go +0 -55
  275. package/plugins/extract-sql/lineage.go +0 -107
  276. package/plugins/extract-sql/main.go +0 -141
  277. package/plugins/extract-sql/maps.go +0 -564
  278. package/plugins/extract-sql/maps_java.go +0 -117
  279. package/plugins/extract-sql/maps_rust.go +0 -333
  280. package/plugins/extract-sql/maps_rust_test.go +0 -70
  281. package/plugins/extract-sql/maps_test.go +0 -204
  282. package/plugins/extract-sql/maps_ts.go +0 -398
  283. package/plugins/extract-sql/maps_ts_test.go +0 -136
  284. package/plugins/extract-sql/projection.go +0 -70
  285. package/plugins/extract-sql/projection_test.go +0 -50
  286. package/plugins/extract-sql/store.go +0 -420
  287. package/plugins/extract-sql/store_test.go +0 -233
  288. package/plugins/extract-sql/view.go +0 -295
  289. package/plugins/extract-watermill/describe.go +0 -19
  290. package/plugins/extract-watermill/describe_test.go +0 -11
  291. package/plugins/extract-watermill/extract.go +0 -1228
  292. package/plugins/extract-watermill/extract_test.go +0 -234
  293. package/plugins/extract-watermill/main.go +0 -41
  294. package/plugins/extract-wsdl/describe.go +0 -19
  295. package/plugins/extract-wsdl/describe_test.go +0 -11
  296. package/plugins/extract-wsdl/extract.go +0 -148
  297. package/plugins/extract-wsdl/extract_test.go +0 -45
  298. package/plugins/extract-wsdl/main.go +0 -53
  299. package/plugins/fetch-bsr/auth.go +0 -114
  300. package/plugins/fetch-bsr/bsr.go +0 -240
  301. package/plugins/fetch-bsr/cache.go +0 -66
  302. package/plugins/fetch-bsr/describe.go +0 -19
  303. package/plugins/fetch-bsr/fetch.go +0 -192
  304. package/plugins/fetch-bsr/fetch_test.go +0 -465
  305. package/plugins/fetch-bsr/lock.go +0 -71
  306. package/plugins/fetch-bsr/main.go +0 -117
  307. package/plugins/fetch-csr/auth.go +0 -95
  308. package/plugins/fetch-csr/cache.go +0 -69
  309. package/plugins/fetch-csr/describe.go +0 -19
  310. package/plugins/fetch-csr/describe_test.go +0 -11
  311. package/plugins/fetch-csr/fetch.go +0 -254
  312. package/plugins/fetch-csr/fetch_test.go +0 -494
  313. package/plugins/fetch-csr/lock.go +0 -95
  314. package/plugins/fetch-csr/main.go +0 -122
  315. package/plugins/fetch-csr/registry.go +0 -209
  316. package/plugins/fetch-git/cache.go +0 -65
  317. package/plugins/fetch-git/describe.go +0 -19
  318. package/plugins/fetch-git/describe_test.go +0 -11
  319. package/plugins/fetch-git/fetch.go +0 -181
  320. package/plugins/fetch-git/fetch_test.go +0 -332
  321. package/plugins/fetch-git/git.go +0 -169
  322. package/plugins/fetch-git/lock.go +0 -72
  323. package/plugins/fetch-git/main.go +0 -127
  324. package/plugins/fetch-git/offline.go +0 -39
  325. package/plugins/fetch-git/pin.go +0 -90
  326. package/plugins/fetch-git/pin_test.go +0 -74
  327. package/plugins/gen-backstage/describe.go +0 -17
  328. package/plugins/gen-backstage/main.go +0 -22
  329. package/plugins/gen-backstage/plugin.go +0 -473
  330. package/plugins/gen-backstage/plugin_test.go +0 -145
  331. package/plugins/gen-backstage.wasm +0 -0
  332. package/plugins/gen-markdown/adr.go +0 -162
  333. package/plugins/gen-markdown/aggregate.go +0 -362
  334. package/plugins/gen-markdown/canonical.go +0 -93
  335. package/plugins/gen-markdown/context.go +0 -90
  336. package/plugins/gen-markdown/coverage_test.go +0 -89
  337. package/plugins/gen-markdown/describe.go +0 -19
  338. package/plugins/gen-markdown/describe_test.go +0 -11
  339. package/plugins/gen-markdown/external.go +0 -71
  340. package/plugins/gen-markdown/flow.go +0 -277
  341. package/plugins/gen-markdown/glossary.go +0 -76
  342. package/plugins/gen-markdown/glossary_test.go +0 -148
  343. package/plugins/gen-markdown/llms.go +0 -302
  344. package/plugins/gen-markdown/main.go +0 -22
  345. package/plugins/gen-markdown/markdown.go +0 -254
  346. package/plugins/gen-markdown/markdown_test.go +0 -100
  347. package/plugins/gen-markdown/module.go +0 -107
  348. package/plugins/gen-markdown/plugin.go +0 -39
  349. package/plugins/gen-markdown/quality_test.go +0 -176
  350. package/plugins/gen-markdown/redis_test.go +0 -38
  351. package/plugins/gen-markdown/render.go +0 -344
  352. package/plugins/gen-markdown/render_test.go +0 -186
  353. package/plugins/gen-markdown/service.go +0 -456
  354. package/plugins/gen-markdown/source.go +0 -177
  355. package/plugins/gen-markdown/store.go +0 -201
  356. package/plugins/gen-markdown.wasm +0 -0
  357. package/plugins/gen-mermaid/describe.go +0 -17
  358. package/plugins/gen-mermaid/main.go +0 -22
  359. package/plugins/gen-mermaid/plugin.go +0 -104
  360. package/plugins/gen-mermaid/plugin_test.go +0 -33
  361. package/plugins/gen-mermaid.wasm +0 -0
  362. package/plugins/openapi/ids.go +0 -261
  363. package/plugins/openapi/ids_test.go +0 -98
  364. package/plugins/verify-codeowners/describe.go +0 -19
  365. package/plugins/verify-codeowners/describe_test.go +0 -11
  366. package/plugins/verify-codeowners/main.go +0 -75
  367. package/plugins/verify-codeowners/match.go +0 -85
  368. package/plugins/verify-codeowners/match_test.go +0 -47
  369. package/plugins/verify-codeowners/owners.go +0 -164
  370. package/plugins/verify-codeowners/owners_test.go +0 -225
  371. package/plugins/verify-codeowners/parse.go +0 -90
  372. package/plugins/verify-codeowners/parse_test.go +0 -62
  373. package/plugins/verify-otel/describe.go +0 -19
  374. package/plugins/verify-otel/describe_test.go +0 -11
  375. package/plugins/verify-otel/main.go +0 -53
  376. package/plugins/verify-otel/match.go +0 -336
  377. package/plugins/verify-otel/otlp.go +0 -200
  378. package/plugins/verify-otel/verify.go +0 -734
  379. package/plugins/verify-otel/verify_test.go +0 -460
  380. /package/{plugins/fetch-csr/options.schema.json → scripts/host-plugins/fetch-csr.options.json} +0 -0
  381. /package/{plugins/fetch-git/options.schema.json → scripts/host-plugins/fetch-git.options.json} +0 -0
@@ -0,0 +1,101 @@
1
+ import { Moon, Rows2, Rows4, Sun } from "lucide-react";
2
+ import { useDensity } from "../../app/density";
3
+ import { useTheme } from "../../app/theme";
4
+ import { ChatSection } from "../../chat/ChatSettings";
5
+ import { BUILD as CHAT_BUILD } from "../../chat/flags";
6
+ import { useEditorStore } from "../../components/EditorLink";
7
+ import { Select } from "../../components/Select";
8
+ import { EDITORS } from "../../lib/editor-link";
9
+ import { parseEditor } from "../../lib/editor-prefs";
10
+ import { SectionTitle } from "../../components/PageHeader";
11
+
12
+ function EditorChoice() {
13
+ const editor = useEditorStore((state) => state.editor);
14
+ const setEditor = useEditorStore((state) => state.set);
15
+ const options = EDITORS.map((item) => ({
16
+ value: item.id,
17
+ label: item.name,
18
+ }));
19
+ return (
20
+ <div className="rounded-card border border-line p-card shadow-xs">
21
+ <div className="label mb-3">open source in</div>
22
+ <Select
23
+ value={editor}
24
+ options={options}
25
+ onChange={(value) => setEditor(parseEditor(value))}
26
+ label="Editor for source links"
27
+ menuWidth={200}
28
+ />
29
+ <p className="mono mt-2 text-muted">Used by the edit links in local mode.</p>
30
+ </div>
31
+ );
32
+ }
33
+
34
+ function Appearance() {
35
+ const { theme, toggle: toggleTheme } = useTheme();
36
+ const { density, toggle: toggleDensity } = useDensity();
37
+ return (
38
+ <div className="grid gap-grid sm:grid-cols-2 xl:grid-cols-3">
39
+ <div className="rounded-card border border-line p-card shadow-xs">
40
+ <div className="label mb-3">theme</div>
41
+ <div className="seg inline-flex" role="group" aria-label="Theme">
42
+ <button
43
+ type="button"
44
+ aria-pressed={theme === "dark"}
45
+ onClick={() => theme !== "dark" && toggleTheme()}
46
+ className={`flex items-center gap-1.5 ${theme === "dark" ? "is-on" : ""}`}
47
+ >
48
+ <Moon size={15} aria-hidden /> dark
49
+ </button>
50
+ <button
51
+ type="button"
52
+ aria-pressed={theme === "light"}
53
+ onClick={() => theme !== "light" && toggleTheme()}
54
+ className={`flex items-center gap-1.5 ${theme === "light" ? "is-on" : ""}`}
55
+ >
56
+ <Sun size={15} aria-hidden /> light
57
+ </button>
58
+ </div>
59
+ </div>
60
+ <div className="rounded-card border border-line p-card shadow-xs">
61
+ <div className="label mb-3">row density</div>
62
+ <div className="seg inline-flex" role="group" aria-label="Row density">
63
+ <button
64
+ type="button"
65
+ aria-pressed={density === "comfortable"}
66
+ onClick={() => density !== "comfortable" && toggleDensity()}
67
+ className={`flex items-center gap-1.5 ${density === "comfortable" ? "is-on" : ""}`}
68
+ >
69
+ <Rows4 size={15} aria-hidden /> comfortable
70
+ </button>
71
+ <button
72
+ type="button"
73
+ aria-pressed={density === "compact"}
74
+ onClick={() => density !== "compact" && toggleDensity()}
75
+ className={`flex items-center gap-1.5 ${density === "compact" ? "is-on" : ""}`}
76
+ >
77
+ <Rows2 size={15} aria-hidden /> compact
78
+ </button>
79
+ </div>
80
+ </div>
81
+ <EditorChoice />
82
+ </div>
83
+ );
84
+ }
85
+
86
+ export function PreferencesSettings() {
87
+ return (
88
+ <div className="space-y-section">
89
+ <section>
90
+ <SectionTitle right="stored in this browser">Appearance</SectionTitle>
91
+ <Appearance />
92
+ </section>
93
+ {CHAT_BUILD.built ? (
94
+ <section>
95
+ <SectionTitle right="stored in this browser">Ask the catalog</SectionTitle>
96
+ <ChatSection />
97
+ </section>
98
+ ) : null}
99
+ </div>
100
+ );
101
+ }
@@ -6,6 +6,7 @@ import {
6
6
  allCatalogPaths,
7
7
  blockPath,
8
8
  eventPath,
9
+ isLandingPath,
9
10
  isRoutable,
10
11
  paths,
11
12
  servicePath,
@@ -18,6 +19,14 @@ import { allAggregates, allStores, allViews, enumsOf } from "./catalog";
18
19
  import { registryCatalog } from "./lib/scenarios";
19
20
 
20
21
  describe("routes", () => {
22
+ it("routes the public landing page", () => {
23
+ expect(paths.landing()).toBe("/landing");
24
+ expect(isLandingPath("/landing")).toBe(true);
25
+ expect(isLandingPath("/landing/")).toBe(true);
26
+ expect(isRoutable(paths.landing())).toBe(true);
27
+ expect(isRoutable("/landing/")).toBe(true);
28
+ });
29
+
21
30
  it("routes every URL the catalog can produce", () => {
22
31
  const unroutable = allCatalogPaths(catalog).filter((p) => !isRoutable(p));
23
32
  expect(unroutable).toEqual([]);
@@ -157,6 +166,17 @@ describe("routes", () => {
157
166
  it("routes the build settings page", () => {
158
167
  expect(paths.settings()).toBe("/settings");
159
168
  expect(isRoutable(paths.settings())).toBe(true);
169
+ expect(paths.settingsProjects()).toBe("/settings/projects");
170
+ expect(paths.settingsPipeline()).toBe("/settings/pipeline");
171
+ expect(paths.settingsDelivery()).toBe("/settings/delivery");
172
+ expect(paths.settingsPreferences()).toBe("/settings/preferences");
173
+ for (const path of [
174
+ paths.settingsProjects(),
175
+ paths.settingsPipeline(),
176
+ paths.settingsDelivery(),
177
+ paths.settingsPreferences(),
178
+ ]) expect(isRoutable(path)).toBe(true);
179
+ expect(isRoutable("/settings/nope")).toBe(false);
160
180
  expect(allCatalogPaths(catalog)).toContain(paths.settings());
161
181
  });
162
182
 
package/src/routes.ts CHANGED
@@ -8,6 +8,7 @@ import { selectionHash } from "./selection/hash";
8
8
  import { flowStepId } from "./selection/model";
9
9
 
10
10
  export const paths = {
11
+ landing: () => "/landing",
11
12
  overview: () => "/",
12
13
  flows: () => "/flows",
13
14
  flow: (slug: string) => `/flows/${slug}`,
@@ -41,6 +42,10 @@ export const paths = {
41
42
  problems: () => "/problems",
42
43
  changes: () => "/changes",
43
44
  settings: () => "/settings",
45
+ settingsProjects: () => "/settings/projects",
46
+ settingsPipeline: () => "/settings/pipeline",
47
+ settingsDelivery: () => "/settings/delivery",
48
+ settingsPreferences: () => "/settings/preferences",
44
49
  external: (slug: string) => `/externals/${slug}`,
45
50
  registry: () => "/registry",
46
51
  /**
@@ -103,6 +108,11 @@ export const paths = {
103
108
  `/c/${contextId}/${serviceSlug}/data/${storeSlug}`,
104
109
  } as const;
105
110
 
111
+ /** GitHub Pages canonicalizes extensionless routes with a trailing slash. */
112
+ export function isLandingPath(pathname: string): boolean {
113
+ return /^\/landing\/?$/.test(pathname);
114
+ }
115
+
106
116
  /** The section anchors on an aggregate page, as used by the building-blocks strip. */
107
117
  export const AGGREGATE_ANCHOR = {
108
118
  entities: "bb-entities",
@@ -201,6 +211,7 @@ export const OVERVIEW_ANCHOR = {
201
211
  landscape: "landscape",
202
212
  contexts: "contexts",
203
213
  flows: "flows-by-reach",
214
+ problems: "problems",
204
215
  } as const;
205
216
 
206
217
  /** Path to the page that owns an event, or null if the event is not in the catalog. */
@@ -355,6 +366,7 @@ export function backlinkPath(link: Backlink): string | null {
355
366
 
356
367
  /** Route patterns declared in App.tsx, in the same order. */
357
368
  const ROUTES: RegExp[] = [
369
+ /^\/landing\/?$/,
358
370
  /^\/$/,
359
371
  /^\/flows$/,
360
372
  /^\/flows\/[^/]+$/,
@@ -362,7 +374,7 @@ const ROUTES: RegExp[] = [
362
374
  /^\/language$/,
363
375
  /^\/problems$/,
364
376
  /^\/changes$/,
365
- /^\/settings$/,
377
+ /^\/settings(?:\/(?:projects|pipeline|delivery|preferences))?$/,
366
378
  /^\/externals\/[^/]+$/,
367
379
  /^\/map$/,
368
380
  /^\/adrs\/[^/]+$/,
package/vite.config.ts CHANGED
@@ -111,17 +111,11 @@ const buildInfo = {
111
111
  // the executable commands or arbitrary options in portolan.json. Reduce the
112
112
  // manifest here, while building, and expose only the read-only inventory the
113
113
  // Settings page needs.
114
- const manifestText = readFileSync(
115
- resolve(workspace, "portolan.json"),
116
- "utf8",
117
- );
114
+ const manifestText = readFileSync(resolve(workspace, "portolan.json"), "utf8");
118
115
  let buildReport: unknown;
119
116
  try {
120
117
  buildReport = JSON.parse(
121
- readFileSync(
122
- resolve(workspace, ".portolan/build-report.json"),
123
- "utf8",
124
- ),
118
+ readFileSync(resolve(workspace, ".portolan/build-report.json"), "utf8"),
125
119
  ) as unknown;
126
120
  } catch {
127
121
  // A clean checkout has no run to report yet. Settings says so explicitly.
@@ -141,6 +135,16 @@ export default defineConfig({
141
135
  // .portolan. Their tsconfig files and generated output are inputs to the
142
136
  // local control plane, not another Vite application to hot-reload.
143
137
  watch: { ignored: ["**/.portolan/**"] },
138
+ proxy: {
139
+ "/api/portolan-chat": {
140
+ target: "https://portolan-chat.batazor.workers.dev",
141
+ changeOrigin: true,
142
+ rewrite: () => "/chat",
143
+ // The browser talks to Vite on the same origin. Vite talks to the
144
+ // worker as the public demo, whose origin is deliberately allowlisted.
145
+ headers: { Origin: "https://shortlink-org.github.io" },
146
+ },
147
+ },
144
148
  },
145
149
  define: {
146
150
  __BUILD_INFO__: JSON.stringify(buildInfo),
@@ -1,46 +0,0 @@
1
- package catalog
2
-
3
- import (
4
- "encoding/json"
5
- "testing"
6
- )
7
-
8
- // An enum round-trips whole: the aggregate's list, the values with their
9
- // docs, the deprecation marks - and the proto side's numbers. The fixture is
10
- // literal rather than read from a catalog so that the test says exactly what
11
- // the mirror is expected to keep.
12
- func TestEnumRoundTrip(t *testing.T) {
13
- raw := `{"id":"a","slug":"a","name":"A","readme":"","root":"A","entities":[],"valueObjects":[],"operations":[],"events":[],
14
- "enums":[{"id":"shop.oms.order.status","slug":"status","name":"Status","doc":"Where an order is.","deprecated":true,
15
- "values":[{"name":"placed","doc":"just in"},{"name":"legacy","doc":"","deprecated":true}]}]}`
16
-
17
- var agg Aggregate
18
- if err := json.Unmarshal([]byte(raw), &agg); err != nil {
19
- t.Fatal(err)
20
- }
21
- if len(agg.Enums) != 1 || agg.Enums[0].ID != "shop.oms.order.status" || !agg.Enums[0].Deprecated {
22
- t.Fatalf("enum not read: %+v", agg.Enums)
23
- }
24
- if got := agg.Enums[0].Values; len(got) != 2 || got[0].Name != "placed" || !got[1].Deprecated {
25
- t.Fatalf("values not read: %+v", got)
26
- }
27
-
28
- out, err := json.Marshal(agg)
29
- if err != nil {
30
- t.Fatal(err)
31
- }
32
- var before, after any
33
- _ = json.Unmarshal([]byte(raw), &before)
34
- _ = json.Unmarshal(out, &after)
35
- if diffs := compare("aggregate", normalize(before), normalize(after)); len(diffs) != 0 {
36
- t.Fatalf("round trip lost something: %v", diffs)
37
- }
38
-
39
- var svc RpcService
40
- if err := json.Unmarshal([]byte(`{"id":"shop.v1.OrderService","methods":[],"source":"","enums":[{"name":"Status","values":[{"name":"STATUS_UNSPECIFIED","number":0},{"name":"PLACED","number":1,"doc":"in"}]}]}`), &svc); err != nil {
41
- t.Fatal(err)
42
- }
43
- if len(svc.Enums) != 1 || svc.Enums[0].Values[1].Number != 1 || svc.Enums[0].Values[0].Number != 0 {
44
- t.Fatalf("proto enum not read: %+v", svc.Enums)
45
- }
46
- }