@rangojs/router 0.0.0-experimental.10 → 0.0.0-experimental.100
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/AGENTS.md +9 -0
- package/README.md +1037 -4
- package/dist/bin/rango.js +1619 -157
- package/dist/vite/index.js +5762 -2301
- package/dist/vite/plugins/cloudflare-protocol-loader-hook.mjs +76 -0
- package/package.json +71 -63
- package/skills/breadcrumbs/SKILL.md +252 -0
- package/skills/cache-guide/SKILL.md +294 -0
- package/skills/caching/SKILL.md +93 -23
- package/skills/composability/SKILL.md +172 -0
- package/skills/debug-manifest/SKILL.md +12 -8
- package/skills/document-cache/SKILL.md +18 -16
- package/skills/fonts/SKILL.md +6 -4
- package/skills/handler-use/SKILL.md +364 -0
- package/skills/hooks/SKILL.md +367 -71
- package/skills/host-router/SKILL.md +218 -0
- package/skills/i18n/SKILL.md +276 -0
- package/skills/intercept/SKILL.md +176 -8
- package/skills/layout/SKILL.md +124 -3
- package/skills/links/SKILL.md +304 -25
- package/skills/loader/SKILL.md +474 -47
- package/skills/middleware/SKILL.md +207 -37
- package/skills/migrate-nextjs/SKILL.md +562 -0
- package/skills/migrate-react-router/SKILL.md +769 -0
- package/skills/mime-routes/SKILL.md +15 -11
- package/skills/parallel/SKILL.md +272 -1
- package/skills/prerender/SKILL.md +467 -65
- package/skills/rango/SKILL.md +89 -21
- package/skills/response-routes/SKILL.md +152 -91
- package/skills/route/SKILL.md +305 -14
- package/skills/router-setup/SKILL.md +210 -32
- package/skills/server-actions/SKILL.md +739 -0
- package/skills/streams-and-websockets/SKILL.md +283 -0
- package/skills/theme/SKILL.md +9 -8
- package/skills/typesafety/SKILL.md +333 -86
- package/skills/use-cache/SKILL.md +324 -0
- package/skills/view-transitions/SKILL.md +212 -0
- package/src/__internal.ts +102 -4
- package/src/bin/rango.ts +312 -15
- package/src/browser/action-coordinator.ts +97 -0
- package/src/browser/action-response-classifier.ts +99 -0
- package/src/browser/app-shell.ts +52 -0
- package/src/browser/app-version.ts +14 -0
- package/src/browser/event-controller.ts +136 -68
- package/src/browser/history-state.ts +80 -0
- package/src/browser/intercept-utils.ts +52 -0
- package/src/browser/link-interceptor.ts +24 -4
- package/src/browser/logging.ts +55 -0
- package/src/browser/merge-segment-loaders.ts +20 -12
- package/src/browser/navigation-bridge.ts +374 -561
- package/src/browser/navigation-client.ts +228 -70
- package/src/browser/navigation-store.ts +97 -55
- package/src/browser/navigation-transaction.ts +297 -0
- package/src/browser/network-error-handler.ts +61 -0
- package/src/browser/partial-update.ts +376 -315
- package/src/browser/prefetch/cache.ts +314 -0
- package/src/browser/prefetch/fetch.ts +282 -0
- package/src/browser/prefetch/observer.ts +65 -0
- package/src/browser/prefetch/policy.ts +48 -0
- package/src/browser/prefetch/queue.ts +191 -0
- package/src/browser/prefetch/resource-ready.ts +77 -0
- package/src/browser/rango-state.ts +152 -0
- package/src/browser/react/Link.tsx +255 -71
- package/src/browser/react/NavigationProvider.tsx +152 -24
- package/src/browser/react/context.ts +11 -0
- package/src/browser/react/filter-segment-order.ts +55 -0
- package/src/browser/react/index.ts +15 -12
- package/src/browser/react/location-state-shared.ts +95 -53
- package/src/browser/react/location-state.ts +60 -15
- package/src/browser/react/mount-context.ts +6 -1
- package/src/browser/react/nonce-context.ts +23 -0
- package/src/browser/react/shallow-equal.ts +27 -0
- package/src/browser/react/use-action.ts +29 -51
- package/src/browser/react/use-client-cache.ts +5 -3
- package/src/browser/react/use-handle.ts +30 -120
- package/src/browser/react/use-link-status.ts +6 -5
- package/src/browser/react/use-navigation.ts +44 -65
- package/src/browser/react/use-params.ts +78 -0
- package/src/browser/react/use-pathname.ts +47 -0
- package/src/browser/react/use-reverse.ts +99 -0
- package/src/browser/react/use-router.ts +83 -0
- package/src/browser/react/use-search-params.ts +56 -0
- package/src/browser/react/use-segments.ts +85 -99
- package/src/browser/response-adapter.ts +73 -0
- package/src/browser/rsc-router.tsx +246 -64
- package/src/browser/scroll-restoration.ts +127 -52
- package/src/browser/segment-reconciler.ts +243 -0
- package/src/browser/segment-structure-assert.ts +16 -0
- package/src/browser/server-action-bridge.ts +510 -603
- package/src/browser/shallow.ts +6 -1
- package/src/browser/types.ts +158 -48
- package/src/browser/validate-redirect-origin.ts +29 -0
- package/src/build/generate-manifest.ts +84 -23
- package/src/build/generate-route-types.ts +39 -828
- package/src/build/index.ts +4 -5
- package/src/build/route-trie.ts +85 -32
- package/src/build/route-types/ast-helpers.ts +25 -0
- package/src/build/route-types/ast-route-extraction.ts +98 -0
- package/src/build/route-types/codegen.ts +102 -0
- package/src/build/route-types/include-resolution.ts +418 -0
- package/src/build/route-types/param-extraction.ts +48 -0
- package/src/build/route-types/per-module-writer.ts +128 -0
- package/src/build/route-types/router-processing.ts +618 -0
- package/src/build/route-types/scan-filter.ts +85 -0
- package/src/build/runtime-discovery.ts +231 -0
- package/src/cache/background-task.ts +34 -0
- package/src/cache/cache-key-utils.ts +44 -0
- package/src/cache/cache-policy.ts +125 -0
- package/src/cache/cache-runtime.ts +342 -0
- package/src/cache/cache-scope.ts +167 -307
- package/src/cache/cf/cf-cache-store.ts +573 -21
- package/src/cache/cf/index.ts +13 -3
- package/src/cache/document-cache.ts +116 -77
- package/src/cache/handle-capture.ts +81 -0
- package/src/cache/handle-snapshot.ts +41 -0
- package/src/cache/index.ts +1 -15
- package/src/cache/memory-segment-store.ts +191 -13
- package/src/cache/profile-registry.ts +73 -0
- package/src/cache/read-through-swr.ts +134 -0
- package/src/cache/segment-codec.ts +256 -0
- package/src/cache/taint.ts +153 -0
- package/src/cache/types.ts +72 -122
- package/src/client.rsc.tsx +6 -1
- package/src/client.tsx +118 -302
- package/src/component-utils.ts +4 -4
- package/src/components/DefaultDocument.tsx +5 -1
- package/src/context-var.ts +156 -0
- package/src/debug.ts +19 -9
- package/src/errors.ts +77 -7
- package/src/handle.ts +55 -10
- package/src/handles/MetaTags.tsx +73 -20
- package/src/handles/breadcrumbs.ts +66 -0
- package/src/handles/index.ts +1 -0
- package/src/handles/meta.ts +30 -13
- package/src/host/cookie-handler.ts +21 -15
- package/src/host/errors.ts +8 -8
- package/src/host/index.ts +4 -7
- package/src/host/pattern-matcher.ts +27 -27
- package/src/host/router.ts +61 -39
- package/src/host/testing.ts +8 -8
- package/src/host/types.ts +15 -7
- package/src/host/utils.ts +1 -1
- package/src/href-client.ts +65 -45
- package/src/index.rsc.ts +138 -21
- package/src/index.ts +206 -51
- package/src/internal-debug.ts +11 -0
- package/src/loader.rsc.ts +25 -143
- package/src/loader.ts +27 -10
- package/src/network-error-thrower.tsx +3 -1
- package/src/outlet-context.ts +1 -1
- package/src/outlet-provider.tsx +45 -0
- package/src/prerender/param-hash.ts +4 -2
- package/src/prerender/store.ts +159 -13
- package/src/prerender.ts +397 -29
- package/src/response-utils.ts +28 -0
- package/src/reverse.ts +231 -121
- package/src/root-error-boundary.tsx +41 -29
- package/src/route-content-wrapper.tsx +7 -4
- package/src/route-definition/dsl-helpers.ts +1134 -0
- package/src/route-definition/helper-factories.ts +200 -0
- package/src/route-definition/helpers-types.ts +483 -0
- package/src/route-definition/index.ts +55 -0
- package/src/route-definition/redirect.ts +101 -0
- package/src/route-definition/resolve-handler-use.ts +155 -0
- package/src/route-definition.ts +1 -1431
- package/src/route-map-builder.ts +162 -123
- package/src/route-name.ts +53 -0
- package/src/route-types.ts +66 -9
- package/src/router/content-negotiation.ts +215 -0
- package/src/router/debug-manifest.ts +72 -0
- package/src/router/error-handling.ts +9 -9
- package/src/router/find-match.ts +160 -0
- package/src/router/handler-context.ts +418 -86
- package/src/router/intercept-resolution.ts +35 -20
- package/src/router/lazy-includes.ts +237 -0
- package/src/router/loader-resolution.ts +359 -128
- package/src/router/logging.ts +251 -0
- package/src/router/manifest.ts +98 -32
- package/src/router/match-api.ts +196 -261
- package/src/router/match-context.ts +4 -2
- package/src/router/match-handlers.ts +441 -0
- package/src/router/match-middleware/background-revalidation.ts +108 -93
- package/src/router/match-middleware/cache-lookup.ts +415 -86
- package/src/router/match-middleware/cache-store.ts +91 -29
- package/src/router/match-middleware/intercept-resolution.ts +48 -21
- package/src/router/match-middleware/segment-resolution.ts +73 -9
- package/src/router/match-pipelines.ts +10 -45
- package/src/router/match-result.ts +154 -35
- package/src/router/metrics.ts +240 -15
- package/src/router/middleware-cookies.ts +55 -0
- package/src/router/middleware-types.ts +209 -0
- package/src/router/middleware.ts +373 -371
- package/src/router/navigation-snapshot.ts +182 -0
- package/src/router/pattern-matching.ts +292 -52
- package/src/router/prerender-match.ts +502 -0
- package/src/router/preview-match.ts +98 -0
- package/src/router/request-classification.ts +310 -0
- package/src/router/revalidation.ts +152 -39
- package/src/router/route-snapshot.ts +245 -0
- package/src/router/router-context.ts +41 -21
- package/src/router/router-interfaces.ts +484 -0
- package/src/router/router-options.ts +618 -0
- package/src/router/router-registry.ts +24 -0
- package/src/router/segment-resolution/fresh.ts +756 -0
- package/src/router/segment-resolution/helpers.ts +268 -0
- package/src/router/segment-resolution/loader-cache.ts +199 -0
- package/src/router/segment-resolution/revalidation.ts +1407 -0
- package/src/router/segment-resolution/static-store.ts +67 -0
- package/src/router/segment-resolution.ts +21 -1315
- package/src/router/segment-wrappers.ts +291 -0
- package/src/router/substitute-pattern-params.ts +56 -0
- package/src/router/telemetry-otel.ts +299 -0
- package/src/router/telemetry.ts +300 -0
- package/src/router/timeout.ts +148 -0
- package/src/router/trie-matching.ts +111 -39
- package/src/router/types.ts +17 -9
- package/src/router/url-params.ts +49 -0
- package/src/router.ts +642 -2011
- package/src/rsc/handler-context.ts +45 -0
- package/src/rsc/handler.ts +864 -1114
- package/src/rsc/helpers.ts +181 -19
- package/src/rsc/index.ts +0 -20
- package/src/rsc/loader-fetch.ts +229 -0
- package/src/rsc/manifest-init.ts +90 -0
- package/src/rsc/nonce.ts +14 -0
- package/src/rsc/origin-guard.ts +141 -0
- package/src/rsc/progressive-enhancement.ts +395 -0
- package/src/rsc/response-error.ts +37 -0
- package/src/rsc/response-route-handler.ts +360 -0
- package/src/rsc/rsc-rendering.ts +256 -0
- package/src/rsc/runtime-warnings.ts +42 -0
- package/src/rsc/server-action.ts +360 -0
- package/src/rsc/ssr-setup.ts +128 -0
- package/src/rsc/types.ts +52 -11
- package/src/search-params.ts +230 -0
- package/src/segment-content-promise.ts +67 -0
- package/src/segment-loader-promise.ts +122 -0
- package/src/segment-system.tsx +187 -38
- package/src/server/context.ts +333 -59
- package/src/server/cookie-store.ts +190 -0
- package/src/server/fetchable-loader-store.ts +37 -0
- package/src/server/handle-store.ts +113 -15
- package/src/server/loader-registry.ts +24 -64
- package/src/server/request-context.ts +603 -109
- package/src/server.ts +35 -155
- package/src/ssr/index.tsx +107 -30
- package/src/static-handler.ts +126 -0
- package/src/theme/ThemeProvider.tsx +21 -15
- package/src/theme/ThemeScript.tsx +5 -5
- package/src/theme/constants.ts +5 -2
- package/src/theme/index.ts +4 -14
- package/src/theme/theme-context.ts +4 -30
- package/src/theme/theme-script.ts +21 -18
- package/src/types/boundaries.ts +158 -0
- package/src/types/cache-types.ts +198 -0
- package/src/types/error-types.ts +192 -0
- package/src/types/global-namespace.ts +100 -0
- package/src/types/handler-context.ts +764 -0
- package/src/types/index.ts +88 -0
- package/src/types/loader-types.ts +209 -0
- package/src/types/request-scope.ts +126 -0
- package/src/types/route-config.ts +170 -0
- package/src/types/route-entry.ts +120 -0
- package/src/types/segments.ts +167 -0
- package/src/types.ts +1 -1757
- package/src/urls/include-helper.ts +207 -0
- package/src/urls/index.ts +53 -0
- package/src/urls/path-helper-types.ts +372 -0
- package/src/urls/path-helper.ts +364 -0
- package/src/urls/pattern-types.ts +107 -0
- package/src/urls/response-types.ts +108 -0
- package/src/urls/type-extraction.ts +372 -0
- package/src/urls/urls-function.ts +98 -0
- package/src/urls.ts +1 -1282
- package/src/use-loader.tsx +161 -81
- package/src/vite/debug.ts +184 -0
- package/src/vite/discovery/bundle-postprocess.ts +181 -0
- package/src/vite/discovery/discover-routers.ts +376 -0
- package/src/vite/discovery/gate-state.ts +171 -0
- package/src/vite/discovery/prerender-collection.ts +486 -0
- package/src/vite/discovery/route-types-writer.ts +258 -0
- package/src/vite/discovery/self-gen-tracking.ts +73 -0
- package/src/vite/discovery/state.ts +117 -0
- package/src/vite/discovery/virtual-module-codegen.ts +203 -0
- package/src/vite/index.ts +15 -2063
- package/src/vite/plugin-types.ts +103 -0
- package/src/vite/plugins/cjs-to-esm.ts +98 -0
- package/src/vite/plugins/client-ref-dedup.ts +131 -0
- package/src/vite/plugins/client-ref-hashing.ts +117 -0
- package/src/vite/plugins/cloudflare-protocol-loader-hook.d.mts +23 -0
- package/src/vite/plugins/cloudflare-protocol-loader-hook.mjs +76 -0
- package/src/vite/plugins/cloudflare-protocol-stub.ts +214 -0
- package/src/vite/{expose-action-id.ts → plugins/expose-action-id.ts} +107 -64
- package/src/vite/plugins/expose-id-utils.ts +299 -0
- package/src/vite/plugins/expose-ids/export-analysis.ts +296 -0
- package/src/vite/plugins/expose-ids/handler-transform.ts +209 -0
- package/src/vite/plugins/expose-ids/loader-transform.ts +74 -0
- package/src/vite/plugins/expose-ids/router-transform.ts +127 -0
- package/src/vite/plugins/expose-ids/types.ts +45 -0
- package/src/vite/plugins/expose-internal-ids.ts +816 -0
- package/src/vite/plugins/performance-tracks.ts +96 -0
- package/src/vite/plugins/refresh-cmd.ts +127 -0
- package/src/vite/plugins/use-cache-transform.ts +336 -0
- package/src/vite/plugins/version-injector.ts +109 -0
- package/src/vite/plugins/version-plugin.ts +266 -0
- package/src/vite/{virtual-entries.ts → plugins/virtual-entries.ts} +23 -14
- package/src/vite/plugins/virtual-stub-plugin.ts +29 -0
- package/src/vite/rango.ts +497 -0
- package/src/vite/router-discovery.ts +1423 -0
- package/src/vite/utils/ast-handler-extract.ts +517 -0
- package/src/vite/utils/banner.ts +36 -0
- package/src/vite/utils/bundle-analysis.ts +137 -0
- package/src/vite/utils/manifest-utils.ts +70 -0
- package/src/vite/utils/package-resolution.ts +161 -0
- package/src/vite/utils/prerender-utils.ts +222 -0
- package/src/vite/utils/shared-utils.ts +170 -0
- package/CLAUDE.md +0 -43
- package/src/browser/lru-cache.ts +0 -69
- package/src/browser/request-controller.ts +0 -164
- package/src/cache/memory-store.ts +0 -253
- package/src/href-context.ts +0 -33
- package/src/router.gen.ts +0 -6
- package/src/urls.gen.ts +0 -8
- package/src/vite/expose-handle-id.ts +0 -209
- package/src/vite/expose-loader-id.ts +0 -426
- package/src/vite/expose-location-state-id.ts +0 -177
- package/src/vite/expose-prerender-handler-id.ts +0 -429
- package/src/vite/package-resolution.ts +0 -125
- /package/src/vite/{version.d.ts → plugins/version.d.ts} +0 -0
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
import type { EntryData, InterceptEntry } from "../server/context";
|
|
2
|
+
import type {
|
|
3
|
+
HandlerContext,
|
|
4
|
+
ResolvedSegment,
|
|
5
|
+
ShouldRevalidateFn,
|
|
6
|
+
} from "../types";
|
|
7
|
+
import type { SegmentResolutionDeps } from "./types.js";
|
|
8
|
+
|
|
9
|
+
import {
|
|
10
|
+
resolveAllSegments as _resolveAllSegments,
|
|
11
|
+
resolveLoadersOnly as _resolveLoadersOnly,
|
|
12
|
+
resolveLoadersOnlyWithRevalidation as _resolveLoadersOnlyWithRevalidation,
|
|
13
|
+
buildEntryRevalidateMap as _buildEntryRevalidateMap,
|
|
14
|
+
resolveAllSegmentsWithRevalidation as _resolveAllSegmentsWithRevalidation,
|
|
15
|
+
} from "./segment-resolution.js";
|
|
16
|
+
|
|
17
|
+
import {
|
|
18
|
+
findInterceptForRoute as _findInterceptForRoute,
|
|
19
|
+
resolveInterceptEntry as _resolveInterceptEntry,
|
|
20
|
+
resolveInterceptLoadersOnly as _resolveInterceptLoadersOnly,
|
|
21
|
+
} from "./intercept-resolution.js";
|
|
22
|
+
|
|
23
|
+
import type { InterceptSelectorContext } from "../server/context";
|
|
24
|
+
|
|
25
|
+
export interface SegmentWrappers<TEnv = any> {
|
|
26
|
+
resolveAllSegments: (
|
|
27
|
+
entries: EntryData[],
|
|
28
|
+
routeKey: string,
|
|
29
|
+
params: Record<string, string>,
|
|
30
|
+
context: HandlerContext<any, TEnv>,
|
|
31
|
+
loaderPromises: Map<string, Promise<any>>,
|
|
32
|
+
options?: { skipLoaders?: boolean },
|
|
33
|
+
) => Promise<ResolvedSegment[]>;
|
|
34
|
+
resolveLoadersOnly: (
|
|
35
|
+
entries: EntryData[],
|
|
36
|
+
context: HandlerContext<any, TEnv>,
|
|
37
|
+
) => Promise<ResolvedSegment[]>;
|
|
38
|
+
resolveLoadersOnlyWithRevalidation: (
|
|
39
|
+
entries: EntryData[],
|
|
40
|
+
context: HandlerContext<any, TEnv>,
|
|
41
|
+
clientSegmentIds: Set<string>,
|
|
42
|
+
prevParams: Record<string, string>,
|
|
43
|
+
request: Request,
|
|
44
|
+
prevUrl: URL,
|
|
45
|
+
nextUrl: URL,
|
|
46
|
+
routeKey: string,
|
|
47
|
+
actionContext?: {
|
|
48
|
+
actionId?: string;
|
|
49
|
+
actionUrl?: URL;
|
|
50
|
+
actionResult?: any;
|
|
51
|
+
formData?: FormData;
|
|
52
|
+
},
|
|
53
|
+
stale?: boolean,
|
|
54
|
+
) => Promise<{ segments: ResolvedSegment[]; matchedIds: string[] }>;
|
|
55
|
+
buildEntryRevalidateMap: (
|
|
56
|
+
entries: EntryData[],
|
|
57
|
+
) => Map<
|
|
58
|
+
string,
|
|
59
|
+
{ entry: EntryData; revalidate: ShouldRevalidateFn<any, any>[] }
|
|
60
|
+
>;
|
|
61
|
+
resolveAllSegmentsWithRevalidation: (
|
|
62
|
+
entries: EntryData[],
|
|
63
|
+
routeKey: string,
|
|
64
|
+
params: Record<string, string>,
|
|
65
|
+
context: HandlerContext<any, TEnv>,
|
|
66
|
+
clientSegmentSet: Set<string>,
|
|
67
|
+
prevParams: Record<string, string>,
|
|
68
|
+
request: Request,
|
|
69
|
+
prevUrl: URL,
|
|
70
|
+
nextUrl: URL,
|
|
71
|
+
loaderPromises: Map<string, Promise<any>>,
|
|
72
|
+
actionContext:
|
|
73
|
+
| {
|
|
74
|
+
actionId?: string;
|
|
75
|
+
actionUrl?: URL;
|
|
76
|
+
actionResult?: any;
|
|
77
|
+
formData?: FormData;
|
|
78
|
+
}
|
|
79
|
+
| undefined,
|
|
80
|
+
interceptResult: { intercept: InterceptEntry; entry: EntryData } | null,
|
|
81
|
+
localRouteName: string,
|
|
82
|
+
pathname: string,
|
|
83
|
+
) => Promise<{ segments: ResolvedSegment[]; matchedIds: string[] }>;
|
|
84
|
+
findInterceptForRoute: (
|
|
85
|
+
targetRouteKey: string,
|
|
86
|
+
fromEntry: EntryData | null,
|
|
87
|
+
selectorContext?: InterceptSelectorContext | null,
|
|
88
|
+
isAction?: boolean,
|
|
89
|
+
) => { intercept: InterceptEntry; entry: EntryData } | null;
|
|
90
|
+
resolveInterceptEntry: (
|
|
91
|
+
interceptEntry: InterceptEntry,
|
|
92
|
+
parentEntry: EntryData,
|
|
93
|
+
params: Record<string, string>,
|
|
94
|
+
context: HandlerContext<any, TEnv>,
|
|
95
|
+
belongsToRoute?: boolean,
|
|
96
|
+
revalidationContext?: any,
|
|
97
|
+
) => Promise<ResolvedSegment[]>;
|
|
98
|
+
resolveInterceptLoadersOnly: (
|
|
99
|
+
interceptEntry: InterceptEntry,
|
|
100
|
+
parentEntry: EntryData,
|
|
101
|
+
params: Record<string, string>,
|
|
102
|
+
context: HandlerContext<any, TEnv>,
|
|
103
|
+
belongsToRoute?: boolean,
|
|
104
|
+
revalidationContext?: any,
|
|
105
|
+
) => Promise<{
|
|
106
|
+
loaderDataPromise: Promise<any[]> | any[];
|
|
107
|
+
loaderIds: string[];
|
|
108
|
+
} | null>;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Create thin wrapper functions that bind segmentDeps to extracted
|
|
113
|
+
* segment resolution and intercept resolution functions.
|
|
114
|
+
*
|
|
115
|
+
* These maintain the same signatures as the original inline functions
|
|
116
|
+
* so that RouterContext and call sites don't need to change.
|
|
117
|
+
*/
|
|
118
|
+
export function createSegmentWrappers<TEnv = any>(
|
|
119
|
+
segmentDeps: SegmentResolutionDeps<TEnv>,
|
|
120
|
+
): SegmentWrappers<TEnv> {
|
|
121
|
+
function resolveAllSegments(
|
|
122
|
+
entries: EntryData[],
|
|
123
|
+
routeKey: string,
|
|
124
|
+
params: Record<string, string>,
|
|
125
|
+
context: HandlerContext<any, TEnv>,
|
|
126
|
+
loaderPromises: Map<string, Promise<any>>,
|
|
127
|
+
options?: { skipLoaders?: boolean },
|
|
128
|
+
): ReturnType<typeof _resolveAllSegments> {
|
|
129
|
+
return _resolveAllSegments(
|
|
130
|
+
entries,
|
|
131
|
+
routeKey,
|
|
132
|
+
params,
|
|
133
|
+
context,
|
|
134
|
+
loaderPromises,
|
|
135
|
+
segmentDeps,
|
|
136
|
+
options,
|
|
137
|
+
);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
function resolveLoadersOnly(
|
|
141
|
+
entries: EntryData[],
|
|
142
|
+
context: HandlerContext<any, TEnv>,
|
|
143
|
+
): ReturnType<typeof _resolveLoadersOnly> {
|
|
144
|
+
return _resolveLoadersOnly(entries, context, segmentDeps);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
function resolveLoadersOnlyWithRevalidation(
|
|
148
|
+
entries: EntryData[],
|
|
149
|
+
context: HandlerContext<any, TEnv>,
|
|
150
|
+
clientSegmentIds: Set<string>,
|
|
151
|
+
prevParams: Record<string, string>,
|
|
152
|
+
request: Request,
|
|
153
|
+
prevUrl: URL,
|
|
154
|
+
nextUrl: URL,
|
|
155
|
+
routeKey: string,
|
|
156
|
+
actionContext?: {
|
|
157
|
+
actionId?: string;
|
|
158
|
+
actionUrl?: URL;
|
|
159
|
+
actionResult?: any;
|
|
160
|
+
formData?: FormData;
|
|
161
|
+
},
|
|
162
|
+
stale?: boolean,
|
|
163
|
+
): ReturnType<typeof _resolveLoadersOnlyWithRevalidation> {
|
|
164
|
+
return _resolveLoadersOnlyWithRevalidation(
|
|
165
|
+
entries,
|
|
166
|
+
context,
|
|
167
|
+
clientSegmentIds,
|
|
168
|
+
prevParams,
|
|
169
|
+
request,
|
|
170
|
+
prevUrl,
|
|
171
|
+
nextUrl,
|
|
172
|
+
routeKey,
|
|
173
|
+
segmentDeps,
|
|
174
|
+
actionContext,
|
|
175
|
+
stale,
|
|
176
|
+
);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
function buildEntryRevalidateMap(
|
|
180
|
+
entries: EntryData[],
|
|
181
|
+
): ReturnType<typeof _buildEntryRevalidateMap> {
|
|
182
|
+
return _buildEntryRevalidateMap(entries);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
function resolveAllSegmentsWithRevalidation(
|
|
186
|
+
entries: EntryData[],
|
|
187
|
+
routeKey: string,
|
|
188
|
+
params: Record<string, string>,
|
|
189
|
+
context: HandlerContext<any, TEnv>,
|
|
190
|
+
clientSegmentSet: Set<string>,
|
|
191
|
+
prevParams: Record<string, string>,
|
|
192
|
+
request: Request,
|
|
193
|
+
prevUrl: URL,
|
|
194
|
+
nextUrl: URL,
|
|
195
|
+
loaderPromises: Map<string, Promise<any>>,
|
|
196
|
+
actionContext:
|
|
197
|
+
| {
|
|
198
|
+
actionId?: string;
|
|
199
|
+
actionUrl?: URL;
|
|
200
|
+
actionResult?: any;
|
|
201
|
+
formData?: FormData;
|
|
202
|
+
}
|
|
203
|
+
| undefined,
|
|
204
|
+
interceptResult: { intercept: InterceptEntry; entry: EntryData } | null,
|
|
205
|
+
localRouteName: string,
|
|
206
|
+
pathname: string,
|
|
207
|
+
stale?: boolean,
|
|
208
|
+
): ReturnType<typeof _resolveAllSegmentsWithRevalidation> {
|
|
209
|
+
return _resolveAllSegmentsWithRevalidation(
|
|
210
|
+
entries,
|
|
211
|
+
routeKey,
|
|
212
|
+
params,
|
|
213
|
+
context,
|
|
214
|
+
clientSegmentSet,
|
|
215
|
+
prevParams,
|
|
216
|
+
request,
|
|
217
|
+
prevUrl,
|
|
218
|
+
nextUrl,
|
|
219
|
+
loaderPromises,
|
|
220
|
+
actionContext,
|
|
221
|
+
interceptResult,
|
|
222
|
+
localRouteName,
|
|
223
|
+
pathname,
|
|
224
|
+
segmentDeps,
|
|
225
|
+
stale,
|
|
226
|
+
);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
function findInterceptForRoute(
|
|
230
|
+
targetRouteKey: string,
|
|
231
|
+
fromEntry: EntryData | null,
|
|
232
|
+
selectorContext: InterceptSelectorContext | null = null,
|
|
233
|
+
isAction: boolean = false,
|
|
234
|
+
): ReturnType<typeof _findInterceptForRoute> {
|
|
235
|
+
return _findInterceptForRoute(
|
|
236
|
+
targetRouteKey,
|
|
237
|
+
fromEntry,
|
|
238
|
+
selectorContext,
|
|
239
|
+
isAction,
|
|
240
|
+
);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
function resolveInterceptEntry(
|
|
244
|
+
interceptEntry: InterceptEntry,
|
|
245
|
+
parentEntry: EntryData,
|
|
246
|
+
params: Record<string, string>,
|
|
247
|
+
context: HandlerContext<any, TEnv>,
|
|
248
|
+
belongsToRoute: boolean = true,
|
|
249
|
+
revalidationContext?: any,
|
|
250
|
+
): ReturnType<typeof _resolveInterceptEntry> {
|
|
251
|
+
return _resolveInterceptEntry(
|
|
252
|
+
interceptEntry,
|
|
253
|
+
parentEntry,
|
|
254
|
+
params,
|
|
255
|
+
context,
|
|
256
|
+
belongsToRoute,
|
|
257
|
+
segmentDeps,
|
|
258
|
+
revalidationContext,
|
|
259
|
+
);
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
function resolveInterceptLoadersOnly(
|
|
263
|
+
interceptEntry: InterceptEntry,
|
|
264
|
+
parentEntry: EntryData,
|
|
265
|
+
params: Record<string, string>,
|
|
266
|
+
context: HandlerContext<any, TEnv>,
|
|
267
|
+
belongsToRoute: boolean = true,
|
|
268
|
+
revalidationContext: any,
|
|
269
|
+
): ReturnType<typeof _resolveInterceptLoadersOnly> {
|
|
270
|
+
return _resolveInterceptLoadersOnly(
|
|
271
|
+
interceptEntry,
|
|
272
|
+
parentEntry,
|
|
273
|
+
params,
|
|
274
|
+
context,
|
|
275
|
+
belongsToRoute,
|
|
276
|
+
segmentDeps,
|
|
277
|
+
revalidationContext,
|
|
278
|
+
);
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
return {
|
|
282
|
+
resolveAllSegments: resolveAllSegments,
|
|
283
|
+
resolveLoadersOnly: resolveLoadersOnly,
|
|
284
|
+
resolveLoadersOnlyWithRevalidation: resolveLoadersOnlyWithRevalidation,
|
|
285
|
+
buildEntryRevalidateMap: buildEntryRevalidateMap,
|
|
286
|
+
resolveAllSegmentsWithRevalidation: resolveAllSegmentsWithRevalidation,
|
|
287
|
+
findInterceptForRoute: findInterceptForRoute,
|
|
288
|
+
resolveInterceptEntry: resolveInterceptEntry,
|
|
289
|
+
resolveInterceptLoadersOnly: resolveInterceptLoadersOnly,
|
|
290
|
+
};
|
|
291
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { encodePathSegment } from "./url-params.js";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Substitute `:param` placeholders in a route pattern with values from
|
|
5
|
+
* `params`. Two-pass: optional params (`:name?`) first so absent values
|
|
6
|
+
* collapse cleanly, then required params (throws on missing). Constraint
|
|
7
|
+
* syntax (`:name(en|gb)`) is stripped from the result. Trailing-slash
|
|
8
|
+
* patterns like `/blog/` are preserved unless an optional segment was
|
|
9
|
+
* actually omitted.
|
|
10
|
+
*
|
|
11
|
+
* Shared by `ctx.reverse()` (server), `createReverse()` (typed runtime
|
|
12
|
+
* helper), and `useReverse()` (client hook). The behavior must stay
|
|
13
|
+
* identical across all three call sites.
|
|
14
|
+
*/
|
|
15
|
+
export function substitutePatternParams(
|
|
16
|
+
pattern: string,
|
|
17
|
+
params: Record<string, string | undefined>,
|
|
18
|
+
routeName: string,
|
|
19
|
+
): string {
|
|
20
|
+
let result = pattern;
|
|
21
|
+
let hadOmittedOptional = false;
|
|
22
|
+
|
|
23
|
+
result = result.replace(
|
|
24
|
+
/:([a-zA-Z_][a-zA-Z0-9_]*)(\([^)]*\))?(\?)/g,
|
|
25
|
+
(_match, key) => {
|
|
26
|
+
const value = params[key as string];
|
|
27
|
+
// The matcher omits absent optional params (so `value` is `undefined`
|
|
28
|
+
// here), but caller-supplied params or `getParams()` shapes may still
|
|
29
|
+
// pass `""` explicitly. Treat both as the absent form.
|
|
30
|
+
if (value === undefined || value === "") {
|
|
31
|
+
hadOmittedOptional = true;
|
|
32
|
+
return "";
|
|
33
|
+
}
|
|
34
|
+
return encodePathSegment(value);
|
|
35
|
+
},
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
result = result.replace(
|
|
39
|
+
/:([a-zA-Z_][a-zA-Z0-9_]*)(\([^)]*\))?(?!\?)/g,
|
|
40
|
+
(_match, key) => {
|
|
41
|
+
const value = params[key as string];
|
|
42
|
+
if (value === undefined) {
|
|
43
|
+
throw new Error(`Missing param "${key}" for route "${routeName}"`);
|
|
44
|
+
}
|
|
45
|
+
return encodePathSegment(value);
|
|
46
|
+
},
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
if (hadOmittedOptional) {
|
|
50
|
+
const hadTrailingSlash = pattern.length > 1 && pattern.endsWith("/");
|
|
51
|
+
result = result.replace(/\/\/+/g, "/").replace(/\/+$/, "") || "/";
|
|
52
|
+
if (hadTrailingSlash && !result.endsWith("/")) result += "/";
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return result;
|
|
56
|
+
}
|
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenTelemetry Adapter for Router Telemetry
|
|
3
|
+
*
|
|
4
|
+
* Maps internal TelemetrySink events to OTel spans. The core router
|
|
5
|
+
* remains OTel-agnostic — this adapter bridges the gap by accepting
|
|
6
|
+
* a standard OTel Tracer and producing spans/events from it.
|
|
7
|
+
*
|
|
8
|
+
* Usage:
|
|
9
|
+
* import { trace } from "@opentelemetry/api";
|
|
10
|
+
* import { createOTelSink } from "@rangojs/router";
|
|
11
|
+
*
|
|
12
|
+
* const router = createRouter({
|
|
13
|
+
* telemetry: createOTelSink(trace.getTracer("my-app")),
|
|
14
|
+
* });
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import type { TelemetrySink, TelemetryEvent } from "./telemetry.js";
|
|
18
|
+
|
|
19
|
+
// ---------------------------------------------------------------------------
|
|
20
|
+
// Minimal OTel-compatible types (structurally typed, no import needed)
|
|
21
|
+
// ---------------------------------------------------------------------------
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Minimal Span interface compatible with @opentelemetry/api Span.
|
|
25
|
+
* Only the methods used by the adapter are declared.
|
|
26
|
+
*/
|
|
27
|
+
export interface OTelSpan {
|
|
28
|
+
setAttribute(key: string, value: string | number | boolean): OTelSpan | void;
|
|
29
|
+
addEvent(
|
|
30
|
+
name: string,
|
|
31
|
+
attributes?: Record<string, string | number | boolean>,
|
|
32
|
+
): OTelSpan | void;
|
|
33
|
+
setStatus(status: { code: number; message?: string }): OTelSpan | void;
|
|
34
|
+
recordException(exception: Error): void;
|
|
35
|
+
end(): void;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Minimal Tracer interface compatible with @opentelemetry/api Tracer.
|
|
40
|
+
*/
|
|
41
|
+
export interface OTelTracer {
|
|
42
|
+
startSpan(
|
|
43
|
+
name: string,
|
|
44
|
+
options?: {
|
|
45
|
+
attributes?: Record<string, string | number | boolean>;
|
|
46
|
+
},
|
|
47
|
+
): OTelSpan;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// OTel SpanStatusCode constants (mirrors @opentelemetry/api values)
|
|
51
|
+
const STATUS_OK = 1;
|
|
52
|
+
const STATUS_ERROR = 2;
|
|
53
|
+
|
|
54
|
+
// ---------------------------------------------------------------------------
|
|
55
|
+
// Span correlation helpers
|
|
56
|
+
// ---------------------------------------------------------------------------
|
|
57
|
+
|
|
58
|
+
// Build correlation keys using requestId.
|
|
59
|
+
// getRequestId() always returns a value (generated internally when no
|
|
60
|
+
// header is present), so concurrent requests to the same path each get
|
|
61
|
+
// their own correlation key and never mis-correlate.
|
|
62
|
+
|
|
63
|
+
function requestKey(event: {
|
|
64
|
+
requestId?: string;
|
|
65
|
+
pathname: string;
|
|
66
|
+
transaction: string;
|
|
67
|
+
}): string {
|
|
68
|
+
return `${event.requestId ?? ""}:${event.pathname}:${event.transaction}`;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function loaderKey(event: {
|
|
72
|
+
requestId?: string;
|
|
73
|
+
segmentId: string;
|
|
74
|
+
loaderName: string;
|
|
75
|
+
pathname: string;
|
|
76
|
+
}): string {
|
|
77
|
+
return `${event.requestId ?? ""}:${event.segmentId}:${event.loaderName}:${event.pathname}`;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function pushSpan(
|
|
81
|
+
map: Map<string, OTelSpan[]>,
|
|
82
|
+
key: string,
|
|
83
|
+
span: OTelSpan,
|
|
84
|
+
): void {
|
|
85
|
+
let stack = map.get(key);
|
|
86
|
+
if (!stack) {
|
|
87
|
+
stack = [];
|
|
88
|
+
map.set(key, stack);
|
|
89
|
+
}
|
|
90
|
+
stack.push(span);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function popSpan(
|
|
94
|
+
map: Map<string, OTelSpan[]>,
|
|
95
|
+
key: string,
|
|
96
|
+
): OTelSpan | undefined {
|
|
97
|
+
const stack = map.get(key);
|
|
98
|
+
if (!stack || stack.length === 0) return undefined;
|
|
99
|
+
const span = stack.pop()!;
|
|
100
|
+
if (stack.length === 0) map.delete(key);
|
|
101
|
+
return span;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// ---------------------------------------------------------------------------
|
|
105
|
+
// Adapter factory
|
|
106
|
+
// ---------------------------------------------------------------------------
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Create a TelemetrySink that maps router lifecycle events to OTel spans.
|
|
110
|
+
*
|
|
111
|
+
* Span mapping:
|
|
112
|
+
* - request.start / request.end / request.error → "rango.request" span
|
|
113
|
+
* - loader.start / loader.end / loader.error → "rango.loader" span
|
|
114
|
+
* - handler.error → "rango.handler.error" instant span
|
|
115
|
+
* - cache.decision → "rango.cache.decision" instant span
|
|
116
|
+
* - revalidation.decision → "rango.revalidation.decision" instant span
|
|
117
|
+
*
|
|
118
|
+
* Attributes use the `rango.*` namespace for router-specific data and
|
|
119
|
+
* `http.method` / `http.route` for HTTP semantics.
|
|
120
|
+
*/
|
|
121
|
+
export function createOTelSink(tracer: OTelTracer): TelemetrySink {
|
|
122
|
+
const requestSpans = new Map<string, OTelSpan[]>();
|
|
123
|
+
const loaderSpans = new Map<string, OTelSpan[]>();
|
|
124
|
+
|
|
125
|
+
return {
|
|
126
|
+
emit(event: TelemetryEvent): void {
|
|
127
|
+
switch (event.type) {
|
|
128
|
+
// -----------------------------------------------------------------
|
|
129
|
+
// Request lifecycle
|
|
130
|
+
// -----------------------------------------------------------------
|
|
131
|
+
|
|
132
|
+
case "request.start": {
|
|
133
|
+
const span = tracer.startSpan("rango.request", {
|
|
134
|
+
attributes: {
|
|
135
|
+
"http.method": event.method,
|
|
136
|
+
"http.route": event.pathname,
|
|
137
|
+
"rango.transaction": event.transaction,
|
|
138
|
+
"rango.is_partial": event.isPartial,
|
|
139
|
+
},
|
|
140
|
+
});
|
|
141
|
+
pushSpan(requestSpans, requestKey(event), span);
|
|
142
|
+
break;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
case "request.end": {
|
|
146
|
+
const span = popSpan(requestSpans, requestKey(event));
|
|
147
|
+
if (span) {
|
|
148
|
+
span.setAttribute("rango.duration_ms", event.durationMs);
|
|
149
|
+
span.setAttribute("rango.segment_count", event.segmentCount);
|
|
150
|
+
span.setAttribute("rango.cache.hit", event.cacheHit);
|
|
151
|
+
span.setStatus({ code: STATUS_OK });
|
|
152
|
+
span.end();
|
|
153
|
+
}
|
|
154
|
+
break;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
case "request.error": {
|
|
158
|
+
const span = popSpan(requestSpans, requestKey(event));
|
|
159
|
+
if (span) {
|
|
160
|
+
span.setAttribute("rango.duration_ms", event.durationMs);
|
|
161
|
+
span.setAttribute("rango.phase", event.phase);
|
|
162
|
+
span.recordException(event.error);
|
|
163
|
+
span.setStatus({
|
|
164
|
+
code: STATUS_ERROR,
|
|
165
|
+
message: event.error.message,
|
|
166
|
+
});
|
|
167
|
+
span.end();
|
|
168
|
+
}
|
|
169
|
+
break;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// -----------------------------------------------------------------
|
|
173
|
+
// Loader lifecycle
|
|
174
|
+
// -----------------------------------------------------------------
|
|
175
|
+
|
|
176
|
+
case "loader.start": {
|
|
177
|
+
const span = tracer.startSpan("rango.loader", {
|
|
178
|
+
attributes: {
|
|
179
|
+
"rango.segment_id": event.segmentId,
|
|
180
|
+
"rango.loader_name": event.loaderName,
|
|
181
|
+
"http.route": event.pathname,
|
|
182
|
+
},
|
|
183
|
+
});
|
|
184
|
+
pushSpan(loaderSpans, loaderKey(event), span);
|
|
185
|
+
break;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
case "loader.end": {
|
|
189
|
+
const key = loaderKey(event);
|
|
190
|
+
const span = popSpan(loaderSpans, key);
|
|
191
|
+
if (span) {
|
|
192
|
+
span.setAttribute("rango.duration_ms", event.durationMs);
|
|
193
|
+
span.setAttribute("rango.loader.ok", event.ok);
|
|
194
|
+
span.setStatus({ code: event.ok ? STATUS_OK : STATUS_ERROR });
|
|
195
|
+
span.end();
|
|
196
|
+
}
|
|
197
|
+
break;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
case "loader.error": {
|
|
201
|
+
const key = loaderKey(event);
|
|
202
|
+
const span = popSpan(loaderSpans, key);
|
|
203
|
+
if (span) {
|
|
204
|
+
span.setAttribute(
|
|
205
|
+
"rango.handled_by_boundary",
|
|
206
|
+
event.handledByBoundary,
|
|
207
|
+
);
|
|
208
|
+
span.recordException(event.error);
|
|
209
|
+
span.setStatus({
|
|
210
|
+
code: STATUS_ERROR,
|
|
211
|
+
message: event.error.message,
|
|
212
|
+
});
|
|
213
|
+
span.end();
|
|
214
|
+
} else {
|
|
215
|
+
// No matching start — create a standalone error span
|
|
216
|
+
const errorSpan = tracer.startSpan("rango.loader", {
|
|
217
|
+
attributes: {
|
|
218
|
+
"rango.segment_id": event.segmentId,
|
|
219
|
+
"rango.loader_name": event.loaderName,
|
|
220
|
+
"http.route": event.pathname,
|
|
221
|
+
"rango.handled_by_boundary": event.handledByBoundary,
|
|
222
|
+
},
|
|
223
|
+
});
|
|
224
|
+
errorSpan.recordException(event.error);
|
|
225
|
+
errorSpan.setStatus({
|
|
226
|
+
code: STATUS_ERROR,
|
|
227
|
+
message: event.error.message,
|
|
228
|
+
});
|
|
229
|
+
errorSpan.end();
|
|
230
|
+
}
|
|
231
|
+
break;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
// -----------------------------------------------------------------
|
|
235
|
+
// Handler errors (instant span)
|
|
236
|
+
// -----------------------------------------------------------------
|
|
237
|
+
|
|
238
|
+
case "handler.error": {
|
|
239
|
+
const attrs: Record<string, string | number | boolean> = {
|
|
240
|
+
"rango.handled_by_boundary": event.handledByBoundary,
|
|
241
|
+
};
|
|
242
|
+
if (event.segmentId) attrs["rango.segment_id"] = event.segmentId;
|
|
243
|
+
if (event.segmentType)
|
|
244
|
+
attrs["rango.segment_type"] = event.segmentType;
|
|
245
|
+
if (event.pathname) attrs["http.route"] = event.pathname;
|
|
246
|
+
if (event.routeKey) attrs["rango.route_key"] = event.routeKey;
|
|
247
|
+
if (event.params) {
|
|
248
|
+
attrs["rango.params"] = JSON.stringify(event.params);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
const span = tracer.startSpan("rango.handler.error", {
|
|
252
|
+
attributes: attrs,
|
|
253
|
+
});
|
|
254
|
+
span.recordException(event.error);
|
|
255
|
+
span.setStatus({ code: STATUS_ERROR, message: event.error.message });
|
|
256
|
+
span.end();
|
|
257
|
+
break;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
// -----------------------------------------------------------------
|
|
261
|
+
// Cache decision (instant span)
|
|
262
|
+
// -----------------------------------------------------------------
|
|
263
|
+
|
|
264
|
+
case "cache.decision": {
|
|
265
|
+
const attrs: Record<string, string | number | boolean> = {
|
|
266
|
+
"http.route": event.pathname,
|
|
267
|
+
"rango.route_key": event.routeKey,
|
|
268
|
+
"rango.cache.hit": event.hit,
|
|
269
|
+
"rango.cache.should_revalidate": event.shouldRevalidate,
|
|
270
|
+
};
|
|
271
|
+
if (event.source) attrs["rango.cache.source"] = event.source;
|
|
272
|
+
|
|
273
|
+
const span = tracer.startSpan("rango.cache.decision", {
|
|
274
|
+
attributes: attrs,
|
|
275
|
+
});
|
|
276
|
+
span.end();
|
|
277
|
+
break;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
// -----------------------------------------------------------------
|
|
281
|
+
// Revalidation decision (instant span)
|
|
282
|
+
// -----------------------------------------------------------------
|
|
283
|
+
|
|
284
|
+
case "revalidation.decision": {
|
|
285
|
+
const span = tracer.startSpan("rango.revalidation.decision", {
|
|
286
|
+
attributes: {
|
|
287
|
+
"rango.segment_id": event.segmentId,
|
|
288
|
+
"http.route": event.pathname,
|
|
289
|
+
"rango.route_key": event.routeKey,
|
|
290
|
+
"rango.revalidate": event.shouldRevalidate,
|
|
291
|
+
},
|
|
292
|
+
});
|
|
293
|
+
span.end();
|
|
294
|
+
break;
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
},
|
|
298
|
+
};
|
|
299
|
+
}
|