@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.
- package/README.md +69 -205
- package/cli/init.mjs +285 -0
- package/cli/init.test.mjs +158 -0
- package/cli/portolan.mjs +37 -73
- package/index.html +19 -0
- package/package.json +5 -10
- package/plugins/README.md +66 -27
- package/plugins/portolan-go.wasm +0 -0
- package/portolan.json +52 -73
- package/public/landing/cats/bug-hunter.webp +0 -0
- package/public/landing/cats/compass-nap.webp +0 -0
- package/public/landing/cats/diagrammer.webp +0 -0
- package/public/landing/cats/docs-reader.webp +0 -0
- package/public/landing/cats/laptop.webp +0 -0
- package/public/landing/cats/map-inspector.webp +0 -0
- package/public/landing/cats/server-break.webp +0 -0
- package/public/landing/cats/star-mapper.webp +0 -0
- package/public/landing/cats/system-builder.webp +0 -0
- package/public/landing/cats/thread-tangle.webp +0 -0
- package/public/og.png +0 -0
- package/public/readme-header.webp +0 -0
- package/schema/portolan.schema.json +180 -0
- package/scripts/builtin-plugins.mjs +14 -0
- package/scripts/delivery-presets.mjs +353 -0
- package/scripts/gen.mjs +37 -4
- package/scripts/history.mjs +126 -0
- package/scripts/history.test.mjs +110 -0
- package/scripts/host-plugins/fetch-bsr.mjs +351 -0
- package/{plugins/fetch-bsr/options.schema.json → scripts/host-plugins/fetch-bsr.options.json} +4 -0
- package/scripts/host-plugins/fetch-bsr.test.mjs +212 -0
- package/scripts/host-plugins/fetch-csr.mjs +386 -0
- package/scripts/host-plugins/fetch-csr.test.mjs +178 -0
- package/scripts/host-plugins/fetch-git.mjs +379 -0
- package/scripts/host-plugins/fetch-git.test.mjs +210 -0
- package/scripts/local-api.mjs +22 -4
- package/scripts/local-api.test.mjs +84 -2
- package/scripts/manifest.mjs +3 -2
- package/scripts/package-smoke.mjs +6 -2
- package/scripts/plugin-host.mjs +77 -18
- package/scripts/plugin-host.test.mjs +50 -1
- package/scripts/plugin-wasm-worker.mjs +6 -3
- package/scripts/run-builtin.mjs +6 -26
- package/scripts/schema.mjs +6 -1
- package/src/app/App.tsx +24 -429
- package/src/app/Breadcrumbs.test.ts +7 -0
- package/src/app/Breadcrumbs.tsx +15 -2
- package/src/app/CatalogApp.tsx +436 -0
- package/src/app/Sidebar.tsx +0 -1
- package/src/chat/ChatPanel.tsx +98 -41
- package/src/chat/Composer.tsx +4 -2
- package/src/chat/Conversation.tsx +79 -15
- package/src/chat/Header.tsx +43 -9
- package/src/chat/Starter.tsx +64 -3
- package/src/chat/Steps.tsx +1 -1
- package/src/chat/flags.test.ts +51 -14
- package/src/chat/flags.ts +8 -2
- package/src/chat/page-context.test.ts +51 -0
- package/src/chat/page-context.ts +128 -0
- package/src/chat/prompt.test.ts +49 -1
- package/src/chat/prompt.ts +42 -1
- package/src/chat/tools.ts +7 -2
- package/src/chat/transport.ts +16 -4
- package/src/components/ProblemRow.tsx +182 -0
- package/src/data.ts +20 -5
- package/src/er/ErCanvas.tsx +1 -1
- package/src/graph/DependencyGraph.tsx +10 -1
- package/src/graph/FocusedEventGraph.tsx +1 -1
- package/src/graph/GraphToolbar.tsx +2 -4
- package/src/index.css +220 -2
- package/src/landing/DraggableReveal.tsx +168 -0
- package/src/landing/EstateGraph.tsx +28 -0
- package/src/landing/FlowPlayback.tsx +282 -0
- package/src/landing/HeroMap.tsx +128 -0
- package/src/landing/LandingPage.tsx +757 -0
- package/src/landing/ProductFrame.tsx +68 -0
- package/src/landing/ProductTour.tsx +371 -0
- package/src/landing/catalog.ts +25 -0
- package/src/landing/motion.tsx +52 -0
- package/src/lib/all-problems.ts +28 -0
- package/src/lib/local-api.ts +35 -1
- package/src/lib/setup-info.test.ts +8 -0
- package/src/lib/setup-info.ts +3 -2
- package/src/lib/source-code.ts +2 -1
- package/src/likec4/C4View.tsx +5 -0
- package/src/likec4/InteractiveView.tsx +5 -1
- package/src/map/ContextMapGraph.tsx +47 -20
- package/src/pages/ContextMap.tsx +5 -1
- package/src/pages/FlowDetail.tsx +24 -7
- package/src/pages/Overview.tsx +68 -12
- package/src/pages/Problems.tsx +6 -193
- package/src/pages/Settings.tsx +133 -108
- package/src/pages/settings/DeliverySettings.tsx +229 -0
- package/src/pages/settings/PreferencesSettings.tsx +101 -0
- package/src/routes.test.ts +20 -0
- package/src/routes.ts +13 -1
- package/vite.config.ts +12 -8
- package/catalog/enum_test.go +0 -46
- package/catalog/model.go +0 -932
- package/catalog/roundtrip_test.go +0 -185
- package/catalog/via_test.go +0 -38
- package/go.mod +0 -14
- package/go.sum +0 -14
- package/internal/commands/cargo.go +0 -154
- package/internal/commands/commands.go +0 -143
- package/internal/commands/commands_test.go +0 -323
- package/internal/commands/gradle.go +0 -77
- package/internal/commands/justfile.go +0 -82
- package/internal/commands/makefile.go +0 -106
- package/internal/commands/maven.go +0 -93
- package/internal/commands/packagejson.go +0 -159
- package/internal/commands/pyproject.go +0 -169
- package/internal/commands/taskfile.go +0 -101
- package/internal/commands/testdata/estate/.cargo/config.toml +0 -7
- package/internal/commands/testdata/estate/Makefile +0 -33
- package/internal/commands/testdata/estate/Taskfile.yml +0 -21
- package/internal/commands/testdata/estate/build.gradle.kts +0 -21
- package/internal/commands/testdata/estate/justfile +0 -20
- package/internal/commands/testdata/estate/package.json +0 -13
- package/internal/commands/testdata/estate/pom.xml +0 -29
- package/internal/commands/testdata/estate/pyproject.toml +0 -27
- package/internal/commands/testdata/estate/xtask/src/main.rs +0 -27
- package/internal/commands/testdata/golden/commands.json +0 -305
- package/internal/gohttp/analyze.go +0 -2500
- package/internal/gohttp/endpoints.go +0 -1067
- package/internal/gohttp/roots.go +0 -320
- package/internal/gohttp/typed.go +0 -143
- package/internal/goscan/constants.go +0 -85
- package/internal/goscan/goscan_test.go +0 -227
- package/internal/goscan/names.go +0 -52
- package/internal/goscan/parse_test.go +0 -11
- package/internal/goscan/source.go +0 -36
- package/internal/goscan/tree.go +0 -155
- package/internal/goscan/types.go +0 -99
- package/internal/wsdl/ids.go +0 -127
- package/internal/wsdl/ids_test.go +0 -21
- package/internal/wsdl/model.go +0 -62
- package/internal/wsdl/parse.go +0 -920
- package/internal/wsdl/parse_test.go +0 -133
- package/plugin/describe.go +0 -107
- package/plugin/describe_test.go +0 -114
- package/plugin/protocol.go +0 -117
- package/plugin/schematest/schematest.go +0 -126
- package/plugins/extract-adr/describe.go +0 -19
- package/plugins/extract-adr/describe_test.go +0 -11
- package/plugins/extract-adr/extract.go +0 -153
- package/plugins/extract-adr/extract_test.go +0 -350
- package/plugins/extract-adr/history.go +0 -99
- package/plugins/extract-adr/main.go +0 -65
- package/plugins/extract-adr/parse.go +0 -642
- package/plugins/extract-adr/parse_test.go +0 -405
- package/plugins/extract-asyncapi/describe.go +0 -19
- package/plugins/extract-asyncapi/describe_test.go +0 -11
- package/plugins/extract-asyncapi/extract.go +0 -315
- package/plugins/extract-asyncapi/extract_test.go +0 -197
- package/plugins/extract-asyncapi/main.go +0 -48
- package/plugins/extract-asyncapi/spec.go +0 -151
- package/plugins/extract-commands/describe.go +0 -19
- package/plugins/extract-commands/describe_test.go +0 -11
- package/plugins/extract-commands/extract.go +0 -79
- package/plugins/extract-commands/extract_test.go +0 -92
- package/plugins/extract-commands/main.go +0 -55
- package/plugins/extract-csr/avro.go +0 -258
- package/plugins/extract-csr/describe.go +0 -19
- package/plugins/extract-csr/describe_test.go +0 -11
- package/plugins/extract-csr/extract.go +0 -338
- package/plugins/extract-csr/extract_test.go +0 -374
- package/plugins/extract-csr/jsonschema.go +0 -343
- package/plugins/extract-csr/lock.go +0 -25
- package/plugins/extract-csr/main.go +0 -84
- package/plugins/extract-csr/subject.go +0 -102
- package/plugins/extract-flows/describe.go +0 -19
- package/plugins/extract-flows/describe_test.go +0 -11
- package/plugins/extract-flows/extract.go +0 -91
- package/plugins/extract-flows/main.go +0 -45
- package/plugins/extract-flows/parse.go +0 -593
- package/plugins/extract-flows/parse_test.go +0 -204
- package/plugins/extract-glossary/describe.go +0 -19
- package/plugins/extract-glossary/describe_test.go +0 -11
- package/plugins/extract-glossary/extract.go +0 -115
- package/plugins/extract-glossary/extract_test.go +0 -220
- package/plugins/extract-glossary/main.go +0 -59
- package/plugins/extract-glossary/parse.go +0 -214
- package/plugins/extract-glossary/parse_test.go +0 -203
- package/plugins/extract-go/aggregate.go +0 -214
- package/plugins/extract-go/client.go +0 -409
- package/plugins/extract-go/client_test.go +0 -266
- package/plugins/extract-go/describe.go +0 -19
- package/plugins/extract-go/describe_test.go +0 -11
- package/plugins/extract-go/enum.go +0 -195
- package/plugins/extract-go/enum_test.go +0 -82
- package/plugins/extract-go/event.go +0 -99
- package/plugins/extract-go/extract.go +0 -191
- package/plugins/extract-go/extract_test.go +0 -261
- package/plugins/extract-go/flow.go +0 -1441
- package/plugins/extract-go/flow_test.go +0 -609
- package/plugins/extract-go/httpclient.go +0 -174
- package/plugins/extract-go/httpclient_test.go +0 -296
- package/plugins/extract-go/ids.go +0 -92
- package/plugins/extract-go/layout.go +0 -225
- package/plugins/extract-go/layout_test.go +0 -125
- package/plugins/extract-go/lifecycle.go +0 -324
- package/plugins/extract-go/lifecycle_test.go +0 -108
- package/plugins/extract-go/main.go +0 -79
- package/plugins/extract-go/operation.go +0 -157
- package/plugins/extract-go/source.go +0 -316
- package/plugins/extract-go/transport.go +0 -321
- package/plugins/extract-go/transport_test.go +0 -145
- package/plugins/extract-go/wiring.go +0 -434
- package/plugins/extract-go-nats/describe.go +0 -19
- package/plugins/extract-go-nats/describe_test.go +0 -11
- package/plugins/extract-go-nats/extract.go +0 -177
- package/plugins/extract-go-nats/extract_test.go +0 -389
- package/plugins/extract-go-nats/index.go +0 -379
- package/plugins/extract-go-nats/main.go +0 -42
- package/plugins/extract-go-nats/resolve.go +0 -161
- package/plugins/extract-go-nats/sites.go +0 -224
- package/plugins/extract-graphql/describe.go +0 -19
- package/plugins/extract-graphql/describe_test.go +0 -11
- package/plugins/extract-graphql/extract.go +0 -433
- package/plugins/extract-graphql/extract_test.go +0 -256
- package/plugins/extract-graphql/ids.go +0 -49
- package/plugins/extract-graphql/lex.go +0 -237
- package/plugins/extract-graphql/main.go +0 -51
- package/plugins/extract-graphql/parse.go +0 -621
- package/plugins/extract-graphql/parse_test.go +0 -122
- package/plugins/extract-http-clients/describe.go +0 -19
- package/plugins/extract-http-clients/describe_test.go +0 -11
- package/plugins/extract-http-clients/extract.go +0 -705
- package/plugins/extract-http-clients/extract_test.go +0 -1263
- package/plugins/extract-http-clients/main.go +0 -42
- package/plugins/extract-openapi/describe.go +0 -19
- package/plugins/extract-openapi/describe_test.go +0 -11
- package/plugins/extract-openapi/discover.go +0 -243
- package/plugins/extract-openapi/extract.go +0 -526
- package/plugins/extract-openapi/extract_test.go +0 -545
- package/plugins/extract-openapi/main.go +0 -75
- package/plugins/extract-openapi/spec.go +0 -350
- package/plugins/extract-project/describe.go +0 -19
- package/plugins/extract-project/describe_test.go +0 -11
- package/plugins/extract-project/extract.go +0 -221
- package/plugins/extract-project/extract_test.go +0 -109
- package/plugins/extract-project/main.go +0 -41
- package/plugins/extract-proto/ast.go +0 -125
- package/plugins/extract-proto/consumes.go +0 -77
- package/plugins/extract-proto/describe.go +0 -19
- package/plugins/extract-proto/extract.go +0 -293
- package/plugins/extract-proto/extract_test.go +0 -459
- package/plugins/extract-proto/ids.go +0 -89
- package/plugins/extract-proto/ids_test.go +0 -57
- package/plugins/extract-proto/lex.go +0 -285
- package/plugins/extract-proto/main.go +0 -100
- package/plugins/extract-proto/module.go +0 -120
- package/plugins/extract-proto/parse.go +0 -720
- package/plugins/extract-proto/parse_test.go +0 -307
- package/plugins/extract-proto/provides.go +0 -236
- package/plugins/extract-proto/resolve.go +0 -222
- package/plugins/extract-proto/resolve_test.go +0 -119
- package/plugins/extract-redis/describe.go +0 -19
- package/plugins/extract-redis/describe_test.go +0 -11
- package/plugins/extract-redis/extract.go +0 -183
- package/plugins/extract-redis/extract_test.go +0 -168
- package/plugins/extract-redis/keyspaces.go +0 -469
- package/plugins/extract-redis/main.go +0 -44
- package/plugins/extract-river/describe.go +0 -19
- package/plugins/extract-river/describe_test.go +0 -11
- package/plugins/extract-river/extract.go +0 -507
- package/plugins/extract-river/extract_test.go +0 -132
- package/plugins/extract-river/main.go +0 -42
- package/plugins/extract-sql/ddl.go +0 -893
- package/plugins/extract-sql/ddl_test.go +0 -401
- package/plugins/extract-sql/describe.go +0 -19
- package/plugins/extract-sql/describe_test.go +0 -11
- package/plugins/extract-sql/layout.go +0 -221
- package/plugins/extract-sql/layout_test.go +0 -55
- package/plugins/extract-sql/lineage.go +0 -107
- package/plugins/extract-sql/main.go +0 -141
- package/plugins/extract-sql/maps.go +0 -564
- package/plugins/extract-sql/maps_java.go +0 -117
- package/plugins/extract-sql/maps_rust.go +0 -333
- package/plugins/extract-sql/maps_rust_test.go +0 -70
- package/plugins/extract-sql/maps_test.go +0 -204
- package/plugins/extract-sql/maps_ts.go +0 -398
- package/plugins/extract-sql/maps_ts_test.go +0 -136
- package/plugins/extract-sql/projection.go +0 -70
- package/plugins/extract-sql/projection_test.go +0 -50
- package/plugins/extract-sql/store.go +0 -420
- package/plugins/extract-sql/store_test.go +0 -233
- package/plugins/extract-sql/view.go +0 -295
- package/plugins/extract-watermill/describe.go +0 -19
- package/plugins/extract-watermill/describe_test.go +0 -11
- package/plugins/extract-watermill/extract.go +0 -1228
- package/plugins/extract-watermill/extract_test.go +0 -234
- package/plugins/extract-watermill/main.go +0 -41
- package/plugins/extract-wsdl/describe.go +0 -19
- package/plugins/extract-wsdl/describe_test.go +0 -11
- package/plugins/extract-wsdl/extract.go +0 -148
- package/plugins/extract-wsdl/extract_test.go +0 -45
- package/plugins/extract-wsdl/main.go +0 -53
- package/plugins/fetch-bsr/auth.go +0 -114
- package/plugins/fetch-bsr/bsr.go +0 -240
- package/plugins/fetch-bsr/cache.go +0 -66
- package/plugins/fetch-bsr/describe.go +0 -19
- package/plugins/fetch-bsr/fetch.go +0 -192
- package/plugins/fetch-bsr/fetch_test.go +0 -465
- package/plugins/fetch-bsr/lock.go +0 -71
- package/plugins/fetch-bsr/main.go +0 -117
- package/plugins/fetch-csr/auth.go +0 -95
- package/plugins/fetch-csr/cache.go +0 -69
- package/plugins/fetch-csr/describe.go +0 -19
- package/plugins/fetch-csr/describe_test.go +0 -11
- package/plugins/fetch-csr/fetch.go +0 -254
- package/plugins/fetch-csr/fetch_test.go +0 -494
- package/plugins/fetch-csr/lock.go +0 -95
- package/plugins/fetch-csr/main.go +0 -122
- package/plugins/fetch-csr/registry.go +0 -209
- package/plugins/fetch-git/cache.go +0 -65
- package/plugins/fetch-git/describe.go +0 -19
- package/plugins/fetch-git/describe_test.go +0 -11
- package/plugins/fetch-git/fetch.go +0 -181
- package/plugins/fetch-git/fetch_test.go +0 -332
- package/plugins/fetch-git/git.go +0 -169
- package/plugins/fetch-git/lock.go +0 -72
- package/plugins/fetch-git/main.go +0 -127
- package/plugins/fetch-git/offline.go +0 -39
- package/plugins/fetch-git/pin.go +0 -90
- package/plugins/fetch-git/pin_test.go +0 -74
- package/plugins/gen-backstage/describe.go +0 -17
- package/plugins/gen-backstage/main.go +0 -22
- package/plugins/gen-backstage/plugin.go +0 -473
- package/plugins/gen-backstage/plugin_test.go +0 -145
- package/plugins/gen-backstage.wasm +0 -0
- package/plugins/gen-markdown/adr.go +0 -162
- package/plugins/gen-markdown/aggregate.go +0 -362
- package/plugins/gen-markdown/canonical.go +0 -93
- package/plugins/gen-markdown/context.go +0 -90
- package/plugins/gen-markdown/coverage_test.go +0 -89
- package/plugins/gen-markdown/describe.go +0 -19
- package/plugins/gen-markdown/describe_test.go +0 -11
- package/plugins/gen-markdown/external.go +0 -71
- package/plugins/gen-markdown/flow.go +0 -277
- package/plugins/gen-markdown/glossary.go +0 -76
- package/plugins/gen-markdown/glossary_test.go +0 -148
- package/plugins/gen-markdown/llms.go +0 -302
- package/plugins/gen-markdown/main.go +0 -22
- package/plugins/gen-markdown/markdown.go +0 -254
- package/plugins/gen-markdown/markdown_test.go +0 -100
- package/plugins/gen-markdown/module.go +0 -107
- package/plugins/gen-markdown/plugin.go +0 -39
- package/plugins/gen-markdown/quality_test.go +0 -176
- package/plugins/gen-markdown/redis_test.go +0 -38
- package/plugins/gen-markdown/render.go +0 -344
- package/plugins/gen-markdown/render_test.go +0 -186
- package/plugins/gen-markdown/service.go +0 -456
- package/plugins/gen-markdown/source.go +0 -177
- package/plugins/gen-markdown/store.go +0 -201
- package/plugins/gen-markdown.wasm +0 -0
- package/plugins/gen-mermaid/describe.go +0 -17
- package/plugins/gen-mermaid/main.go +0 -22
- package/plugins/gen-mermaid/plugin.go +0 -104
- package/plugins/gen-mermaid/plugin_test.go +0 -33
- package/plugins/gen-mermaid.wasm +0 -0
- package/plugins/openapi/ids.go +0 -261
- package/plugins/openapi/ids_test.go +0 -98
- package/plugins/verify-codeowners/describe.go +0 -19
- package/plugins/verify-codeowners/describe_test.go +0 -11
- package/plugins/verify-codeowners/main.go +0 -75
- package/plugins/verify-codeowners/match.go +0 -85
- package/plugins/verify-codeowners/match_test.go +0 -47
- package/plugins/verify-codeowners/owners.go +0 -164
- package/plugins/verify-codeowners/owners_test.go +0 -225
- package/plugins/verify-codeowners/parse.go +0 -90
- package/plugins/verify-codeowners/parse_test.go +0 -62
- package/plugins/verify-otel/describe.go +0 -19
- package/plugins/verify-otel/describe_test.go +0 -11
- package/plugins/verify-otel/main.go +0 -53
- package/plugins/verify-otel/match.go +0 -336
- package/plugins/verify-otel/otlp.go +0 -200
- package/plugins/verify-otel/verify.go +0 -734
- package/plugins/verify-otel/verify_test.go +0 -460
- /package/{plugins/fetch-csr/options.schema.json → scripts/host-plugins/fetch-csr.options.json} +0 -0
- /package/{plugins/fetch-git/options.schema.json → scripts/host-plugins/fetch-git.options.json} +0 -0
package/src/app/App.tsx
CHANGED
|
@@ -1,447 +1,42 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
Routes,
|
|
7
|
-
useLocation,
|
|
8
|
-
useNavigate,
|
|
9
|
-
} from "react-router";
|
|
10
|
-
import type { Location } from "react-router";
|
|
11
|
-
import {
|
|
12
|
-
Panel,
|
|
13
|
-
ResizeHandle,
|
|
14
|
-
SavedGroup,
|
|
15
|
-
useCanvasResize,
|
|
16
|
-
usePanelRef,
|
|
17
|
-
} from "./panels";
|
|
18
|
-
import { FlowDetail } from "../pages/FlowDetail";
|
|
19
|
-
import { FlowIndex } from "../pages/FlowIndex";
|
|
20
|
-
import { AdrIndex } from "../pages/AdrIndex";
|
|
21
|
-
import { Language } from "../pages/Language";
|
|
22
|
-
import { AdrDetail } from "../pages/AdrDetail";
|
|
23
|
-
import { Overview } from "../pages/Overview";
|
|
24
|
-
import { ContextMap } from "../pages/ContextMap";
|
|
25
|
-
import { ContextPage } from "../pages/ContextPage";
|
|
26
|
-
import { ServicePage } from "../pages/ServicePage";
|
|
27
|
-
import { AggregatePage } from "../pages/AggregatePage";
|
|
28
|
-
import { BlockPage } from "../pages/BlockPage";
|
|
29
|
-
import { EnumPage } from "../pages/EnumPage";
|
|
30
|
-
import { EventPage } from "../pages/EventPage";
|
|
31
|
-
import { StorePage } from "../pages/StorePage";
|
|
32
|
-
import { GraphPage } from "../pages/GraphPage";
|
|
33
|
-
import { Problems } from "../pages/Problems";
|
|
34
|
-
import { Settings } from "../pages/Settings";
|
|
35
|
-
import { Changes } from "../pages/Changes";
|
|
36
|
-
import { RegistryIndex } from "../pages/RegistryIndex";
|
|
37
|
-
import { ModulePage } from "../pages/ModulePage";
|
|
38
|
-
import { ExternalPage } from "../pages/ExternalPage";
|
|
39
|
-
import { NotFoundPage } from "../pages/NotFound";
|
|
40
|
-
import { CatalogFailure } from "../pages/CatalogFailure";
|
|
41
|
-
import { activeCatalogProfile, catalogError } from "../data";
|
|
42
|
-
import { SidePanel } from "../components/Overlay";
|
|
43
|
-
import { Empty } from "../components/PageHeader";
|
|
44
|
-
import { WithDetail } from "../selection/DetailPanel";
|
|
45
|
-
import { SelectionSync } from "../selection/sync";
|
|
46
|
-
import { Trail } from "../trail/Trail";
|
|
47
|
-
import { TrailRecorder } from "../trail/record";
|
|
48
|
-
import { HashScroll } from "./HashScroll";
|
|
49
|
-
import { CommandPalette } from "./CommandPalette";
|
|
50
|
-
import { Sidebar } from "./Sidebar";
|
|
51
|
-
import { TopBar } from "./TopBar";
|
|
1
|
+
import { lazy, Suspense } from "react";
|
|
2
|
+
import { BrowserRouter, useLocation } from "react-router";
|
|
3
|
+
import { LandingPage } from "../landing/LandingPage";
|
|
4
|
+
import { isLandingPath } from "../routes";
|
|
5
|
+
import { MotionProvider } from "../lib/motion";
|
|
52
6
|
import { ThemeProvider } from "./theme";
|
|
53
|
-
import { DensityProvider } from "./density";
|
|
54
|
-
import { useNarrow, usePhone } from "./responsive";
|
|
55
|
-
import { ShortcutsSheet, useShortcuts } from "./shortcuts";
|
|
56
|
-
import { Toaster } from "./toast";
|
|
57
|
-
import { PeekLayer } from "../peek/PeekLayer";
|
|
58
|
-
import { useUiStore } from "./ui-store";
|
|
59
|
-
import { ForgeAccessProvider } from "./forge-access";
|
|
60
|
-
import { QueryClientProvider } from "@tanstack/react-query";
|
|
61
|
-
import { queryClient } from "./query-client";
|
|
62
|
-
import { AnimatePresence, MotionProvider, m, page } from "../lib/motion";
|
|
63
|
-
import { useChatUi } from "../chat/store";
|
|
64
|
-
import { projectPreview } from "../lib/project-preview";
|
|
65
7
|
|
|
66
|
-
// The
|
|
67
|
-
//
|
|
68
|
-
//
|
|
69
|
-
const
|
|
70
|
-
import.
|
|
71
|
-
|
|
72
|
-
: null;
|
|
8
|
+
// The catalog carries diagram runtimes, API viewers and every generated fact.
|
|
9
|
+
// Keep that weight out of the public page; it is fetched only when a catalog
|
|
10
|
+
// route is opened. The landing page itself stays immediately available.
|
|
11
|
+
const CatalogApp = lazy(() =>
|
|
12
|
+
import("./CatalogApp").then((module) => ({ default: module.CatalogApp })),
|
|
13
|
+
);
|
|
73
14
|
|
|
74
|
-
|
|
75
|
-
* What the click shows while that chunk is on its way: the same sheet, at the
|
|
76
|
-
* same width, with a word in it. A fallback of nothing meant the first "ask"
|
|
77
|
-
* on a slow line did nothing for a second and the reader clicked again.
|
|
78
|
-
*/
|
|
79
|
-
function ChatLoading() {
|
|
80
|
-
const phone = usePhone();
|
|
81
|
-
return (
|
|
82
|
-
<SidePanel
|
|
83
|
-
open
|
|
84
|
-
onClose={() => useChatUi.getState().setOpen(false)}
|
|
85
|
-
side="right"
|
|
86
|
-
label="Ask the catalog"
|
|
87
|
-
width={phone ? "100vw" : "min(560px,92vw)"}
|
|
88
|
-
>
|
|
89
|
-
<div className="h-full bg-canvas p-gutter text-ink">
|
|
90
|
-
<Empty>loading the chat…</Empty>
|
|
91
|
-
</div>
|
|
92
|
-
</SidePanel>
|
|
93
|
-
);
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
/**
|
|
97
|
-
* Every route, once. Rendered inside a pane on wide layouts and alone below.
|
|
98
|
-
*
|
|
99
|
-
* The location is a prop, not read from the router: while a page is on its
|
|
100
|
-
* way out the router already says the next address, and the page leaving
|
|
101
|
-
* must keep drawing the one it was.
|
|
102
|
-
*/
|
|
103
|
-
function AppRoutes({ location }: { location: Location }) {
|
|
104
|
-
return (
|
|
105
|
-
<Routes location={location}>
|
|
106
|
-
<Route path="/" element={<Overview />} />
|
|
107
|
-
<Route path="/flows" element={<FlowIndex />} />
|
|
108
|
-
<Route
|
|
109
|
-
path="/flows/:flow"
|
|
110
|
-
element={
|
|
111
|
-
<WithDetail id="flow">
|
|
112
|
-
<FlowDetail />
|
|
113
|
-
</WithDetail>
|
|
114
|
-
}
|
|
115
|
-
/>
|
|
116
|
-
<Route path="/adrs" element={<AdrIndex />} />
|
|
117
|
-
<Route path="/language" element={<Language />} />
|
|
118
|
-
<Route path="/adrs/:adr" element={<AdrDetail />} />
|
|
119
|
-
<Route path="/problems" element={<Problems />} />
|
|
120
|
-
<Route path="/settings" element={<Settings />} />
|
|
121
|
-
<Route path="/changes" element={<Changes />} />
|
|
122
|
-
<Route path="/externals/:external" element={<ExternalPage />} />
|
|
123
|
-
{/* A module sits at the estate level, not under a service: it is
|
|
124
|
-
published by one and read by four, so hanging it off a service would
|
|
125
|
-
put one entity at four URLs. */}
|
|
126
|
-
<Route path="/registry" element={<RegistryIndex />} />
|
|
127
|
-
<Route
|
|
128
|
-
path="/registry/:module"
|
|
129
|
-
element={
|
|
130
|
-
<WithDetail id="module">
|
|
131
|
-
<ModulePage />
|
|
132
|
-
</WithDetail>
|
|
133
|
-
}
|
|
134
|
-
/>
|
|
135
|
-
<Route
|
|
136
|
-
path="/map"
|
|
137
|
-
element={
|
|
138
|
-
<WithDetail id="map">
|
|
139
|
-
<ContextMap />
|
|
140
|
-
</WithDetail>
|
|
141
|
-
}
|
|
142
|
-
/>
|
|
143
|
-
<Route
|
|
144
|
-
path="/c/:context"
|
|
145
|
-
element={
|
|
146
|
-
<WithDetail id="context">
|
|
147
|
-
<ContextPage />
|
|
148
|
-
</WithDetail>
|
|
149
|
-
}
|
|
150
|
-
/>
|
|
151
|
-
<Route
|
|
152
|
-
path="/c/:context/:service"
|
|
153
|
-
element={
|
|
154
|
-
<WithDetail id="service">
|
|
155
|
-
<ServicePage />
|
|
156
|
-
</WithDetail>
|
|
157
|
-
}
|
|
158
|
-
/>
|
|
159
|
-
{/* Before the aggregate routes: "data" is a literal sitting where an
|
|
160
|
-
aggregate slug would, and "/c/x/y/data/z" would otherwise be read as
|
|
161
|
-
the event "z" of an aggregate called "data". */}
|
|
162
|
-
<Route
|
|
163
|
-
path="/c/:context/:service/data/:store"
|
|
164
|
-
element={
|
|
165
|
-
<WithDetail id="store">
|
|
166
|
-
<StorePage />
|
|
167
|
-
</WithDetail>
|
|
168
|
-
}
|
|
169
|
-
/>
|
|
170
|
-
<Route
|
|
171
|
-
path="/c/:context/:service/:aggregate"
|
|
172
|
-
element={<AggregatePage />}
|
|
173
|
-
/>
|
|
174
|
-
{/* The two literal segments come first: a block page must not be
|
|
175
|
-
read as an event whose slug happens to be "vo". */}
|
|
176
|
-
<Route
|
|
177
|
-
path="/c/:context/:service/:aggregate/vo/:block"
|
|
178
|
-
element={<BlockPage kind="vo" />}
|
|
179
|
-
/>
|
|
180
|
-
<Route
|
|
181
|
-
path="/c/:context/:service/:aggregate/entity/:block"
|
|
182
|
-
element={<BlockPage kind="entity" />}
|
|
183
|
-
/>
|
|
184
|
-
<Route
|
|
185
|
-
path="/c/:context/:service/:aggregate/enum/:enum"
|
|
186
|
-
element={<EnumPage />}
|
|
187
|
-
/>
|
|
188
|
-
<Route
|
|
189
|
-
path="/c/:context/:service/:aggregate/:event"
|
|
190
|
-
element={
|
|
191
|
-
<WithDetail id="event">
|
|
192
|
-
<EventPage />
|
|
193
|
-
</WithDetail>
|
|
194
|
-
}
|
|
195
|
-
/>
|
|
196
|
-
<Route
|
|
197
|
-
path="/graph"
|
|
198
|
-
element={
|
|
199
|
-
<WithDetail id="graph">
|
|
200
|
-
<GraphPage />
|
|
201
|
-
</WithDetail>
|
|
202
|
-
}
|
|
203
|
-
/>
|
|
204
|
-
<Route path="/index.html" element={<Navigate to="/" replace />} />
|
|
205
|
-
<Route path="*" element={<NotFoundPage />} />
|
|
206
|
-
</Routes>
|
|
207
|
-
);
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
/**
|
|
211
|
-
* The catalog tree as an overlay, below the narrow breakpoint. It is the same
|
|
212
|
-
* Sidebar; only the box around it changes, so nothing about the tree has two
|
|
213
|
-
* implementations.
|
|
214
|
-
*/
|
|
215
|
-
function SidebarDrawer() {
|
|
216
|
-
const open = useUiStore((s) => s.drawer);
|
|
217
|
-
const setDrawer = useUiStore((s) => s.setDrawer);
|
|
15
|
+
function RoutedApp() {
|
|
218
16
|
const { pathname } = useLocation();
|
|
219
17
|
|
|
220
|
-
|
|
221
|
-
// the drawer's job. Without this the page they asked for is behind a scrim.
|
|
222
|
-
useEffect(() => setDrawer(false), [pathname, setDrawer]);
|
|
223
|
-
|
|
224
|
-
return (
|
|
225
|
-
<SidePanel
|
|
226
|
-
open={open}
|
|
227
|
-
onClose={() => setDrawer(false)}
|
|
228
|
-
side="left"
|
|
229
|
-
label="Catalog"
|
|
230
|
-
width="min(320px,85vw)"
|
|
231
|
-
>
|
|
232
|
-
<Sidebar />
|
|
233
|
-
</SidePanel>
|
|
234
|
-
);
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
function Shell() {
|
|
238
|
-
const [palette, setPalette] = useState(false);
|
|
239
|
-
const [help, setHelp] = useState(false);
|
|
240
|
-
const chatOpen = useChatUi((s) => s.open);
|
|
241
|
-
const [railed, setRailed] = useState(false);
|
|
242
|
-
const location = useLocation();
|
|
243
|
-
const navigate = useNavigate();
|
|
244
|
-
const { pathname } = location;
|
|
245
|
-
const settle = useCanvasResize();
|
|
246
|
-
const sidebarRef = usePanelRef();
|
|
247
|
-
const narrow = useNarrow();
|
|
248
|
-
const toggleDrawer = useUiStore((s) => s.toggleDrawer);
|
|
249
|
-
const setDrawer = useUiStore((s) => s.setDrawer);
|
|
250
|
-
const toggleDetail = useUiStore((s) => s.toggleDetail);
|
|
251
|
-
const revealNonce = useUiStore((s) => s.revealNonce);
|
|
252
|
-
|
|
253
|
-
// Keep the selected catalog shareable even though most route builders do
|
|
254
|
-
// not know about presentation state. Changing the profile itself reloads
|
|
255
|
-
// the bundle; ordinary navigation only restores its URL marker.
|
|
256
|
-
useEffect(() => {
|
|
257
|
-
const params = new URLSearchParams(location.search);
|
|
258
|
-
if (params.get("catalog") === activeCatalogProfile.id) return;
|
|
259
|
-
params.set("catalog", activeCatalogProfile.id);
|
|
260
|
-
navigate(
|
|
261
|
-
{ pathname: location.pathname, search: `?${params}`, hash: location.hash },
|
|
262
|
-
{ replace: true },
|
|
263
|
-
);
|
|
264
|
-
}, [location.hash, location.pathname, location.search, navigate]);
|
|
265
|
-
|
|
266
|
-
// Collapsed is a fact about pixels, not about who dragged: the rail appears
|
|
267
|
-
// whether the reader dragged past the minimum or pressed a rail button.
|
|
268
|
-
const onSidebarResize = useCallback(
|
|
269
|
-
(size: { inPixels: number }) => setRailed(size.inPixels <= 56),
|
|
270
|
-
[],
|
|
271
|
-
);
|
|
272
|
-
|
|
273
|
-
// The rail's buttons ask the panel to expand; `railed` then follows from the
|
|
274
|
-
// resize that answers, so the flag can never disagree with the layout.
|
|
275
|
-
//
|
|
276
|
-
// `expand()` restores the width the panel had before it collapsed, which
|
|
277
|
-
// after a drag all the way to the edge is the minimum - a tree too narrow to
|
|
278
|
-
// read the names in. Anything at or under the minimum is treated as "no
|
|
279
|
-
// remembered width" and goes back to the default instead.
|
|
280
|
-
const expandSidebar = useCallback(() => {
|
|
281
|
-
const panel = sidebarRef.current;
|
|
282
|
-
if (!panel) return;
|
|
283
|
-
panel.expand();
|
|
284
|
-
if (panel.getSize().asPercentage <= 13) panel.resize("18");
|
|
285
|
-
}, [sidebarRef]);
|
|
286
|
-
|
|
287
|
-
// A layout restored from a previous session can arrive already collapsed,
|
|
288
|
-
// and no resize fires for a size that never changed - so the rail has to be
|
|
289
|
-
// read off the panel once on mount, or the full tree renders into 48px.
|
|
290
|
-
useEffect(() => {
|
|
291
|
-
setRailed(sidebarRef.current?.isCollapsed() ?? false);
|
|
292
|
-
}, [sidebarRef]);
|
|
293
|
-
|
|
294
|
-
// "[" means the same thing at both widths - show me the tree, or stop
|
|
295
|
-
// showing it - and reaches for whichever mechanism is on screen.
|
|
296
|
-
const toggleSidebar = useCallback(() => {
|
|
297
|
-
if (narrow) {
|
|
298
|
-
toggleDrawer();
|
|
299
|
-
return;
|
|
300
|
-
}
|
|
301
|
-
const panel = sidebarRef.current;
|
|
302
|
-
if (!panel) return;
|
|
303
|
-
if (panel.isCollapsed()) expandSidebar();
|
|
304
|
-
else panel.collapse();
|
|
305
|
-
}, [narrow, toggleDrawer, sidebarRef, expandSidebar]);
|
|
306
|
-
|
|
307
|
-
// "Reveal in tree" selects; the tree then opens its own ancestors and scrolls
|
|
308
|
-
// itself. The one thing it cannot do from inside a collapsed pane is become
|
|
309
|
-
// visible, which is this.
|
|
310
|
-
useEffect(() => {
|
|
311
|
-
if (revealNonce === 0) return;
|
|
312
|
-
if (narrow) setDrawer(true);
|
|
313
|
-
else if (sidebarRef.current?.isCollapsed()) expandSidebar();
|
|
314
|
-
}, [revealNonce, narrow, setDrawer, sidebarRef, expandSidebar]);
|
|
315
|
-
|
|
316
|
-
useShortcuts(
|
|
317
|
-
{
|
|
318
|
-
openPalette: () => setPalette(true),
|
|
319
|
-
openHelp: () => setHelp(true),
|
|
320
|
-
toggleSidebar,
|
|
321
|
-
toggleDetail,
|
|
322
|
-
},
|
|
323
|
-
// While a modal owns the keyboard the global bindings stand down; ⌘K and
|
|
324
|
-
// Esc are handled inside the modals themselves.
|
|
325
|
-
!palette && !help && !chatOpen,
|
|
326
|
-
);
|
|
18
|
+
if (isLandingPath(pathname)) return <LandingPage />;
|
|
327
19
|
|
|
328
20
|
return (
|
|
329
|
-
<
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
<TopBar
|
|
334
|
-
onOpenPalette={() => setPalette(true)}
|
|
335
|
-
onOpenHelp={() => setHelp(true)}
|
|
336
|
-
onToggleSidebar={toggleSidebar}
|
|
337
|
-
narrow={narrow}
|
|
338
|
-
/>
|
|
339
|
-
{projectPreview ? (
|
|
340
|
-
<div className="shrink-0 border-b border-declared/40 bg-declared/10 px-gutter py-2 text-center text-sm text-declared">
|
|
341
|
-
Temporary project preview · the repository has not been changed · expires after 15 minutes
|
|
21
|
+
<Suspense
|
|
22
|
+
fallback={
|
|
23
|
+
<div className="flex h-full items-center justify-center bg-canvas text-muted">
|
|
24
|
+
<span className="mono">loading the catalog…</span>
|
|
342
25
|
</div>
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
{narrow ? (
|
|
349
|
-
<>
|
|
350
|
-
{/* `key` on the route content is what makes the page transition
|
|
351
|
-
fire: a new pathname is a new element. The old one leaves first,
|
|
352
|
-
on the micro duration, then the new one rises. */}
|
|
353
|
-
<AnimatePresence mode="wait">
|
|
354
|
-
<m.main
|
|
355
|
-
key={pathname}
|
|
356
|
-
{...page}
|
|
357
|
-
className="min-h-0 flex-1 overflow-hidden"
|
|
358
|
-
>
|
|
359
|
-
<AppRoutes location={location} />
|
|
360
|
-
</m.main>
|
|
361
|
-
</AnimatePresence>
|
|
362
|
-
<SidebarDrawer />
|
|
363
|
-
</>
|
|
364
|
-
) : (
|
|
365
|
-
<SavedGroup
|
|
366
|
-
id="portolan:shell"
|
|
367
|
-
orientation="horizontal"
|
|
368
|
-
className="min-h-0 flex-1"
|
|
369
|
-
>
|
|
370
|
-
<Panel
|
|
371
|
-
id="sidebar"
|
|
372
|
-
defaultSize="18"
|
|
373
|
-
minSize="12"
|
|
374
|
-
maxSize="28"
|
|
375
|
-
collapsible
|
|
376
|
-
collapsedSize="48px"
|
|
377
|
-
className="h-full text-sm"
|
|
378
|
-
panelRef={sidebarRef}
|
|
379
|
-
onResize={onSidebarResize}
|
|
380
|
-
>
|
|
381
|
-
<Sidebar railed={railed} onExpand={expandSidebar} />
|
|
382
|
-
</Panel>
|
|
383
|
-
|
|
384
|
-
<ResizeHandle id="shell" />
|
|
385
|
-
|
|
386
|
-
{/* The main pane owns a canvas on most routes, so a drag here has to
|
|
387
|
-
reach the diagram - debounced, once the reader lets go. */}
|
|
388
|
-
<Panel id="main" className="h-full min-w-0" onResize={settle}>
|
|
389
|
-
{/* The detail rail rides along with every page that draws a
|
|
390
|
-
diagram, so a selection made anywhere has somewhere to be read. */}
|
|
391
|
-
<AnimatePresence mode="wait">
|
|
392
|
-
<m.main
|
|
393
|
-
key={pathname}
|
|
394
|
-
{...page}
|
|
395
|
-
className="h-full overflow-hidden"
|
|
396
|
-
>
|
|
397
|
-
<AppRoutes location={location} />
|
|
398
|
-
</m.main>
|
|
399
|
-
</AnimatePresence>
|
|
400
|
-
</Panel>
|
|
401
|
-
</SavedGroup>
|
|
402
|
-
)}
|
|
403
|
-
|
|
404
|
-
<CommandPalette open={palette} onClose={() => setPalette(false)} />
|
|
405
|
-
<ShortcutsSheet open={help} onClose={() => setHelp(false)} />
|
|
406
|
-
{ChatPanel && chatOpen ? (
|
|
407
|
-
<Suspense fallback={<ChatLoading />}>
|
|
408
|
-
<ChatPanel />
|
|
409
|
-
</Suspense>
|
|
410
|
-
) : null}
|
|
411
|
-
{/* The one thing the app says out loud, and it says it here rather than
|
|
412
|
-
in the sidebar: a pin can be taken from a page whose tree is folded
|
|
413
|
-
away to a 48px rail. */}
|
|
414
|
-
<Toaster />
|
|
415
|
-
{/* A card on hover, for any row that names an entity. Mounted once,
|
|
416
|
-
here, because the rows it answers for are on every page. */}
|
|
417
|
-
<PeekLayer />
|
|
418
|
-
</div>
|
|
26
|
+
}
|
|
27
|
+
>
|
|
28
|
+
<CatalogApp />
|
|
29
|
+
</Suspense>
|
|
419
30
|
);
|
|
420
31
|
}
|
|
421
32
|
|
|
422
33
|
export function App() {
|
|
423
|
-
// A catalog that failed validation is the whole app's answer, so it is
|
|
424
|
-
// decided above the router: there is no route worth reaching.
|
|
425
|
-
if (catalogError) {
|
|
426
|
-
return (
|
|
427
|
-
<ThemeProvider>
|
|
428
|
-
<CatalogFailure error={catalogError} />
|
|
429
|
-
</ThemeProvider>
|
|
430
|
-
);
|
|
431
|
-
}
|
|
432
|
-
|
|
433
34
|
return (
|
|
434
35
|
<ThemeProvider>
|
|
435
36
|
<MotionProvider>
|
|
436
|
-
<
|
|
437
|
-
<
|
|
438
|
-
|
|
439
|
-
<BrowserRouter basename={import.meta.env.BASE_URL}>
|
|
440
|
-
<Shell />
|
|
441
|
-
</BrowserRouter>
|
|
442
|
-
</ForgeAccessProvider>
|
|
443
|
-
</QueryClientProvider>
|
|
444
|
-
</DensityProvider>
|
|
37
|
+
<BrowserRouter basename={import.meta.env.BASE_URL}>
|
|
38
|
+
<RoutedApp />
|
|
39
|
+
</BrowserRouter>
|
|
445
40
|
</MotionProvider>
|
|
446
41
|
</ThemeProvider>
|
|
447
42
|
);
|
|
@@ -26,6 +26,13 @@ describe("crumbsFor", () => {
|
|
|
26
26
|
expect(crumbsFor("/adrs")[0]).toEqual({ label: "decisions", to: "/adrs" });
|
|
27
27
|
});
|
|
28
28
|
|
|
29
|
+
it("keeps the active settings section in the trail", () => {
|
|
30
|
+
expect(crumbsFor("/settings/delivery")).toEqual([
|
|
31
|
+
{ label: "settings", to: "/settings" },
|
|
32
|
+
{ label: "delivery", to: "/settings/delivery" },
|
|
33
|
+
]);
|
|
34
|
+
});
|
|
35
|
+
|
|
29
36
|
it("reads 'data' as a literal, not as an aggregate", () => {
|
|
30
37
|
const crumbs = crumbsFor("/c/ctx/svc/data/pg");
|
|
31
38
|
expect(crumbs.map((c) => c.to)).toEqual([
|
package/src/app/Breadcrumbs.tsx
CHANGED
|
@@ -45,8 +45,21 @@ export function crumbsFor(pathname: string): Crumb[] {
|
|
|
45
45
|
|
|
46
46
|
if (parts[0] === "map") return [{ label: "map", to: "/map" }];
|
|
47
47
|
|
|
48
|
-
if (parts[0] === "settings")
|
|
49
|
-
|
|
48
|
+
if (parts[0] === "settings") {
|
|
49
|
+
const subsection = parts[1];
|
|
50
|
+
const labels: Record<string, string> = {
|
|
51
|
+
projects: "projects",
|
|
52
|
+
pipeline: "pipeline",
|
|
53
|
+
delivery: "delivery",
|
|
54
|
+
preferences: "preferences",
|
|
55
|
+
};
|
|
56
|
+
return [
|
|
57
|
+
{ label: "settings", to: paths.settings() },
|
|
58
|
+
...(subsection && labels[subsection]
|
|
59
|
+
? [{ label: labels[subsection], to: pathname }]
|
|
60
|
+
: []),
|
|
61
|
+
];
|
|
62
|
+
}
|
|
50
63
|
|
|
51
64
|
if (parts[0] === "changes")
|
|
52
65
|
return [{ label: "changes", to: paths.changes() }];
|