|
1 | 1 | import type { H3Event } from "./event.ts"; |
2 | | -import type { H3 } from "./h3.ts"; |
| 2 | +import type { H3, H3Core } from "./h3.ts"; |
3 | 3 | import { |
4 | 4 | type H3Plugin, |
5 | 5 | type H3Route, |
@@ -36,8 +36,7 @@ export interface TracingPluginOptions { |
36 | 36 | * Enables tracing for H3 apps. |
37 | 37 | */ |
38 | 38 | export function tracingPlugin(traceOpts?: TracingPluginOptions): H3Plugin { |
39 | | - // TODO: Support H3Core (Nitro) |
40 | | - return (h3: H3) => { |
| 39 | + return (h3: H3 | H3Core) => { |
41 | 40 | const { tracingChannel } = |
42 | 41 | globalThis.process.getBuiltinModule?.("diagnostics_channel") ?? {}; |
43 | 42 |
|
@@ -97,57 +96,63 @@ export function tracingPlugin(traceOpts?: TracingPluginOptions): H3Plugin { |
97 | 96 | } satisfies H3Route; |
98 | 97 | }); |
99 | 98 |
|
100 | | - const originalOn = h3.on; |
101 | | - |
102 | | - h3.on = (...args) => { |
103 | | - const instance = originalOn.apply(h3, args); |
104 | | - // Since it uses route push, we can wrap the last route handler added |
105 | | - // Wrapping the handler at the arg level is problematic because we need the `event` to be passed to the tracePromise. |
106 | | - // Which is only available with `toEventHandler` and it is already called in the `on` method. |
107 | | - // eslint-disable-next-line unicorn/prefer-at |
108 | | - const lastRoute = instance["~routes"][instance["~routes"].length - 1]; |
109 | | - if (lastRoute) { |
110 | | - lastRoute.handler = wrapEventHandler(lastRoute.handler); |
111 | | - lastRoute.middleware = lastRoute.middleware?.map((m) => |
112 | | - wrapMiddleware(m), |
113 | | - ); |
114 | | - } |
115 | | - |
116 | | - return instance; |
117 | | - }; |
| 99 | + if ("on" in h3 && typeof h3.on === "function") { |
| 100 | + const originalOn = h3.on; |
| 101 | + |
| 102 | + h3.on = (...args) => { |
| 103 | + const instance = originalOn.apply(h3, args); |
| 104 | + // Since it uses route push, we can wrap the last route handler added |
| 105 | + // Wrapping the handler at the arg level is problematic because we need the `event` to be passed to the tracePromise. |
| 106 | + // Which is only available with `toEventHandler` and it is already called in the `on` method. |
| 107 | + // eslint-disable-next-line unicorn/prefer-at |
| 108 | + const lastRoute = instance["~routes"][instance["~routes"].length - 1]; |
| 109 | + if (lastRoute) { |
| 110 | + lastRoute.handler = wrapEventHandler(lastRoute.handler); |
| 111 | + lastRoute.middleware = lastRoute.middleware?.map((m) => |
| 112 | + wrapMiddleware(m), |
| 113 | + ); |
| 114 | + } |
| 115 | + |
| 116 | + return instance; |
| 117 | + }; |
| 118 | + } |
118 | 119 |
|
119 | | - const originalUse = h3.use; |
120 | | - h3.use = (arg1: unknown, arg2?: unknown, arg3?: unknown) => { |
121 | | - // Middlewares should be wrapped at the arg level to avoid creating trace events for skipped wrappers added by h3 |
122 | | - let route: string | undefined; |
123 | | - let fn: Middleware; |
124 | | - let opts: MiddlewareOptions | undefined; |
| 120 | + if ("use" in h3 && typeof h3.use === "function") { |
| 121 | + const originalUse = h3.use; |
| 122 | + h3.use = (arg1: unknown, arg2?: unknown, arg3?: unknown) => { |
| 123 | + // Middlewares should be wrapped at the arg level to avoid creating trace events for skipped wrappers added by h3 |
| 124 | + let route: string | undefined; |
| 125 | + let fn: Middleware; |
| 126 | + let opts: MiddlewareOptions | undefined; |
125 | 127 |
|
126 | | - if (typeof arg1 === "string") { |
127 | | - route = arg1 as string; |
128 | | - fn = arg2 as Middleware; |
129 | | - opts = arg3 as MiddlewareOptions; |
| 128 | + if (typeof arg1 === "string") { |
| 129 | + route = arg1 as string; |
| 130 | + fn = arg2 as Middleware; |
| 131 | + opts = arg3 as MiddlewareOptions; |
130 | 132 |
|
131 | | - // @ts-expect-error - call not accepting the route signature |
132 | | - return originalUse.call(h3, route, wrapMiddleware(fn), opts); |
133 | | - } |
| 133 | + // @ts-expect-error - call not accepting the route signature |
| 134 | + return originalUse.call(h3, route, wrapMiddleware(fn), opts); |
| 135 | + } |
134 | 136 |
|
135 | | - fn = arg1 as Middleware; |
136 | | - opts = arg2 as MiddlewareOptions; |
| 137 | + fn = arg1 as Middleware; |
| 138 | + opts = arg2 as MiddlewareOptions; |
137 | 139 |
|
138 | | - return originalUse.call(h3, wrapMiddleware(fn), opts); |
139 | | - }; |
| 140 | + return originalUse.call(h3, wrapMiddleware(fn), opts); |
| 141 | + }; |
| 142 | + } |
140 | 143 |
|
141 | | - const originalMount = h3.mount; |
142 | | - h3.mount = (base, input) => { |
143 | | - // If the input is an H3 instance |
144 | | - // then we can register the tracing plugin on it to propagate the tracing to the nested app |
145 | | - if ("register" in input) { |
146 | | - input.register(tracingPlugin(traceOpts)); |
147 | | - } |
| 144 | + if ("mount" in h3 && typeof h3.mount === "function") { |
| 145 | + const originalMount = h3.mount; |
| 146 | + h3.mount = (base, input) => { |
| 147 | + // If the input is an H3 instance |
| 148 | + // then we can register the tracing plugin on it to propagate the tracing to the nested app |
| 149 | + if ("register" in input) { |
| 150 | + input.register(tracingPlugin(traceOpts)); |
| 151 | + } |
148 | 152 |
|
149 | | - return originalMount.call(h3, base, input); |
150 | | - }; |
| 153 | + return originalMount.call(h3, base, input); |
| 154 | + }; |
| 155 | + } |
151 | 156 |
|
152 | 157 | return h3; |
153 | 158 | }; |
|
0 commit comments