@senzops/apm-node 1.2.0 → 1.2.2
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/.claude/worktrees/infallible-chatelet-f3fb36/.claude/settings.local.json +9 -0
- package/.claude/worktrees/infallible-chatelet-f3fb36/CHANGELOG.md +49 -0
- package/.claude/worktrees/infallible-chatelet-f3fb36/README.md +398 -0
- package/.claude/worktrees/infallible-chatelet-f3fb36/package-lock.json +1494 -0
- package/.claude/worktrees/infallible-chatelet-f3fb36/package.json +42 -0
- package/.claude/worktrees/infallible-chatelet-f3fb36/src/core/client.ts +451 -0
- package/.claude/worktrees/infallible-chatelet-f3fb36/src/core/context.ts +48 -0
- package/.claude/worktrees/infallible-chatelet-f3fb36/src/core/normalizer.ts +44 -0
- package/.claude/worktrees/infallible-chatelet-f3fb36/src/core/sanitizer.ts +203 -0
- package/.claude/worktrees/infallible-chatelet-f3fb36/src/core/transport.ts +273 -0
- package/.claude/worktrees/infallible-chatelet-f3fb36/src/core/types.ts +106 -0
- package/.claude/worktrees/infallible-chatelet-f3fb36/src/index.ts +36 -0
- package/.claude/worktrees/infallible-chatelet-f3fb36/src/instrumentation/bullmq.ts +195 -0
- package/.claude/worktrees/infallible-chatelet-f3fb36/src/instrumentation/cron.ts +204 -0
- package/.claude/worktrees/infallible-chatelet-f3fb36/src/instrumentation/express.ts +338 -0
- package/.claude/worktrees/infallible-chatelet-f3fb36/src/instrumentation/fastify.ts +296 -0
- package/.claude/worktrees/infallible-chatelet-f3fb36/src/instrumentation/framework.ts +301 -0
- package/.claude/worktrees/infallible-chatelet-f3fb36/src/instrumentation/hook.ts +134 -0
- package/.claude/worktrees/infallible-chatelet-f3fb36/src/instrumentation/http.ts +530 -0
- package/.claude/worktrees/infallible-chatelet-f3fb36/src/instrumentation/koa.ts +173 -0
- package/.claude/worktrees/infallible-chatelet-f3fb36/src/instrumentation/mongo.ts +202 -0
- package/.claude/worktrees/infallible-chatelet-f3fb36/src/instrumentation/mongoose.ts +156 -0
- package/.claude/worktrees/infallible-chatelet-f3fb36/src/instrumentation/mysql.ts +169 -0
- package/.claude/worktrees/infallible-chatelet-f3fb36/src/instrumentation/patch.ts +56 -0
- package/.claude/worktrees/infallible-chatelet-f3fb36/src/instrumentation/pg.ts +131 -0
- package/.claude/worktrees/infallible-chatelet-f3fb36/src/instrumentation/redis.ts +109 -0
- package/.claude/worktrees/infallible-chatelet-f3fb36/src/instrumentation/span.ts +73 -0
- package/.claude/worktrees/infallible-chatelet-f3fb36/src/instrumentation/undici.ts +189 -0
- package/.claude/worktrees/infallible-chatelet-f3fb36/src/middleware/express.ts +48 -0
- package/.claude/worktrees/infallible-chatelet-f3fb36/src/register.ts +58 -0
- package/.claude/worktrees/infallible-chatelet-f3fb36/src/utils/getClientIp.ts +175 -0
- package/.claude/worktrees/infallible-chatelet-f3fb36/src/utils/ids.ts +7 -0
- package/.claude/worktrees/infallible-chatelet-f3fb36/src/utils/internal.ts +1 -0
- package/.claude/worktrees/infallible-chatelet-f3fb36/src/utils/sdkMeta.ts +6 -0
- package/.claude/worktrees/infallible-chatelet-f3fb36/src/utils/traceContext.ts +44 -0
- package/.claude/worktrees/infallible-chatelet-f3fb36/src/wrappers/fastify.ts +35 -0
- package/.claude/worktrees/infallible-chatelet-f3fb36/src/wrappers/h3.ts +59 -0
- package/.claude/worktrees/infallible-chatelet-f3fb36/src/wrappers/next.ts +131 -0
- package/.claude/worktrees/infallible-chatelet-f3fb36/tsconfig.json +15 -0
- package/.claude/worktrees/infallible-chatelet-f3fb36/tsup.config.ts +21 -0
- package/.claude/worktrees/infallible-chatelet-f3fb36/wiki.md +852 -0
- package/CHANGELOG.md +8 -0
- package/README.md +12 -0
- package/dist/index.d.mts +5 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.global.js +1 -1
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/index.mjs.map +1 -1
- package/dist/register.js +1 -1
- package/dist/register.js.map +1 -1
- package/dist/register.mjs +1 -1
- package/dist/register.mjs.map +1 -1
- package/package.json +1 -1
- package/src/core/client.ts +8 -2
- package/src/core/types.ts +5 -0
- package/src/instrumentation/express.ts +338 -0
- package/src/instrumentation/fastify.ts +296 -0
- package/src/instrumentation/framework.ts +301 -0
- package/src/instrumentation/hook.ts +79 -192
- package/src/instrumentation/koa.ts +173 -0
- package/src/register.ts +16 -0
- package/src/wrappers/fastify.ts +10 -7
- package/src/wrappers/h3.ts +40 -16
- package/src/wrappers/next.ts +68 -21
- package/wiki.md +8 -0
|
@@ -0,0 +1,301 @@
|
|
|
1
|
+
import { Context } from '../core/context';
|
|
2
|
+
import { SenzorOptions } from '../core/types';
|
|
3
|
+
import { CapturedSpan, runWithCapturedSpan, startCapturedSpan } from './span';
|
|
4
|
+
|
|
5
|
+
export type FrameworkSpanType =
|
|
6
|
+
| 'middleware'
|
|
7
|
+
| 'router'
|
|
8
|
+
| 'request_handler'
|
|
9
|
+
| 'route_handler'
|
|
10
|
+
| 'controller_handler'
|
|
11
|
+
| 'lifecycle_hook'
|
|
12
|
+
| 'error_handler'
|
|
13
|
+
| 'event_handler';
|
|
14
|
+
|
|
15
|
+
export interface FrameworkSpanInfo {
|
|
16
|
+
framework: string;
|
|
17
|
+
type: FrameworkSpanType;
|
|
18
|
+
name: string;
|
|
19
|
+
route?: string;
|
|
20
|
+
method?: string;
|
|
21
|
+
layerPath?: string;
|
|
22
|
+
handlerName?: string;
|
|
23
|
+
request?: any;
|
|
24
|
+
response?: any;
|
|
25
|
+
attributes?: Record<string, unknown>;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
interface InvokeOptions {
|
|
29
|
+
callbackIndex?: number;
|
|
30
|
+
callbackCompletesSpan?: boolean;
|
|
31
|
+
responseEndsSpan?: boolean;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const ignoredNextValues = new Set([undefined, null, 'route', 'router']);
|
|
35
|
+
|
|
36
|
+
export const shouldCaptureFrameworkSpan = (
|
|
37
|
+
type: FrameworkSpanType,
|
|
38
|
+
options?: SenzorOptions
|
|
39
|
+
): boolean => {
|
|
40
|
+
if (options?.frameworkSpans === false) return false;
|
|
41
|
+
if (type === 'middleware' && options?.captureMiddlewareSpans === false) return false;
|
|
42
|
+
if (type === 'router' && options?.captureRouterSpans === false) return false;
|
|
43
|
+
if (type === 'lifecycle_hook' && options?.captureLifecycleHookSpans === false) return false;
|
|
44
|
+
if (options?.ignoreFrameworkSpanTypes?.includes(type)) return false;
|
|
45
|
+
return true;
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
const statusFrom = (
|
|
49
|
+
info: FrameworkSpanInfo,
|
|
50
|
+
fallback = 0
|
|
51
|
+
): number => {
|
|
52
|
+
const res = info.response;
|
|
53
|
+
return (
|
|
54
|
+
res?.statusCode ||
|
|
55
|
+
res?.status ||
|
|
56
|
+
res?.raw?.statusCode ||
|
|
57
|
+
res?.status_code ||
|
|
58
|
+
fallback
|
|
59
|
+
);
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
const isPromiseLike = (value: unknown): value is Promise<unknown> =>
|
|
63
|
+
Boolean(value && typeof (value as any).then === 'function');
|
|
64
|
+
|
|
65
|
+
const runWithParentOf = <T>(
|
|
66
|
+
span: CapturedSpan,
|
|
67
|
+
fn: () => T
|
|
68
|
+
): T => {
|
|
69
|
+
if (!span.parentSpanId) return fn();
|
|
70
|
+
return Context.withActiveSpan(span.parentSpanId, fn);
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
const copyFunctionProperties = (
|
|
74
|
+
source: Function,
|
|
75
|
+
target: Function
|
|
76
|
+
) => {
|
|
77
|
+
for (const key in source as any) {
|
|
78
|
+
try {
|
|
79
|
+
Object.defineProperty(target, key, {
|
|
80
|
+
configurable: true,
|
|
81
|
+
enumerable: true,
|
|
82
|
+
get() {
|
|
83
|
+
return (source as any)[key];
|
|
84
|
+
},
|
|
85
|
+
set(value) {
|
|
86
|
+
(source as any)[key] = value;
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
} catch { }
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
export const invokeWithFrameworkSpan = (
|
|
94
|
+
handler: Function,
|
|
95
|
+
thisArg: unknown,
|
|
96
|
+
args: any[],
|
|
97
|
+
info: FrameworkSpanInfo,
|
|
98
|
+
options?: SenzorOptions,
|
|
99
|
+
invokeOptions: InvokeOptions = {}
|
|
100
|
+
) => {
|
|
101
|
+
if (!shouldCaptureFrameworkSpan(info.type, options) || !Context.current()) {
|
|
102
|
+
return handler.apply(thisArg, args);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
const span = startCapturedSpan(
|
|
106
|
+
info.name,
|
|
107
|
+
'function',
|
|
108
|
+
{
|
|
109
|
+
framework: info.framework,
|
|
110
|
+
'senzor.framework': info.framework,
|
|
111
|
+
'senzor.framework.type': info.type,
|
|
112
|
+
'http.route': info.route,
|
|
113
|
+
route: info.route,
|
|
114
|
+
method: info.method,
|
|
115
|
+
layerPath: info.layerPath,
|
|
116
|
+
handlerName: info.handlerName,
|
|
117
|
+
...info.attributes
|
|
118
|
+
},
|
|
119
|
+
options
|
|
120
|
+
);
|
|
121
|
+
|
|
122
|
+
if (!span) return handler.apply(thisArg, args);
|
|
123
|
+
|
|
124
|
+
let ended = false;
|
|
125
|
+
const cleanup: Array<() => void> = [];
|
|
126
|
+
|
|
127
|
+
const endSpan = (
|
|
128
|
+
status = statusFrom(info),
|
|
129
|
+
meta: Record<string, unknown> = {}
|
|
130
|
+
) => {
|
|
131
|
+
if (ended) return;
|
|
132
|
+
ended = true;
|
|
133
|
+
|
|
134
|
+
for (const clean of cleanup) {
|
|
135
|
+
try { clean(); } catch { }
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
span.end(status, meta);
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
const res = info.response;
|
|
142
|
+
if (invokeOptions.responseEndsSpan !== false && res?.once) {
|
|
143
|
+
const onFinish = () =>
|
|
144
|
+
endSpan(statusFrom(info), { completion: 'response.finish' });
|
|
145
|
+
const onClose = () =>
|
|
146
|
+
endSpan(statusFrom(info), { completion: 'response.close' });
|
|
147
|
+
|
|
148
|
+
res.once('finish', onFinish);
|
|
149
|
+
res.once('close', onClose);
|
|
150
|
+
|
|
151
|
+
cleanup.push(() => {
|
|
152
|
+
try { res.removeListener?.('finish', onFinish); } catch { }
|
|
153
|
+
try { res.removeListener?.('close', onClose); } catch { }
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
const callbackIndex =
|
|
158
|
+
invokeOptions.callbackIndex ??
|
|
159
|
+
args.findIndex((arg) => typeof arg === 'function');
|
|
160
|
+
|
|
161
|
+
if (
|
|
162
|
+
invokeOptions.callbackCompletesSpan !== false &&
|
|
163
|
+
callbackIndex >= 0 &&
|
|
164
|
+
typeof args[callbackIndex] === 'function'
|
|
165
|
+
) {
|
|
166
|
+
const originalCallback = args[callbackIndex];
|
|
167
|
+
args[callbackIndex] = function wrappedFrameworkCallback(
|
|
168
|
+
this: unknown,
|
|
169
|
+
...callbackArgs: any[]
|
|
170
|
+
) {
|
|
171
|
+
const maybeError = callbackArgs[0];
|
|
172
|
+
const hasError = !ignoredNextValues.has(maybeError);
|
|
173
|
+
|
|
174
|
+
endSpan(hasError ? 500 : statusFrom(info), {
|
|
175
|
+
completion: 'callback',
|
|
176
|
+
error: hasError ? String(maybeError?.message || maybeError) : undefined,
|
|
177
|
+
'error.type': hasError
|
|
178
|
+
? maybeError?.name || typeof maybeError
|
|
179
|
+
: undefined
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
return runWithParentOf(span, () =>
|
|
183
|
+
originalCallback.apply(this, callbackArgs)
|
|
184
|
+
);
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
return runWithCapturedSpan(span, () => {
|
|
189
|
+
try {
|
|
190
|
+
const result = handler.apply(thisArg, args);
|
|
191
|
+
|
|
192
|
+
if (isPromiseLike(result)) {
|
|
193
|
+
return result.then(
|
|
194
|
+
(value) => {
|
|
195
|
+
endSpan(statusFrom(info), { completion: 'promise.resolve' });
|
|
196
|
+
return value;
|
|
197
|
+
},
|
|
198
|
+
(error) => {
|
|
199
|
+
endSpan(500, {
|
|
200
|
+
completion: 'promise.reject',
|
|
201
|
+
error: error?.message,
|
|
202
|
+
'error.type': error?.name || 'Error'
|
|
203
|
+
});
|
|
204
|
+
throw error;
|
|
205
|
+
}
|
|
206
|
+
);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
if (callbackIndex < 0 && invokeOptions.responseEndsSpan === false) {
|
|
210
|
+
endSpan(statusFrom(info), { completion: 'sync.return' });
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
return result;
|
|
214
|
+
} catch (error: any) {
|
|
215
|
+
endSpan(500, {
|
|
216
|
+
completion: 'throw',
|
|
217
|
+
error: error?.message,
|
|
218
|
+
'error.type': error?.name || 'Error'
|
|
219
|
+
});
|
|
220
|
+
throw error;
|
|
221
|
+
}
|
|
222
|
+
});
|
|
223
|
+
};
|
|
224
|
+
|
|
225
|
+
export const wrapFrameworkHandler = <T extends Function>(
|
|
226
|
+
handler: T,
|
|
227
|
+
getInfo: (thisArg: unknown, args: any[]) => FrameworkSpanInfo,
|
|
228
|
+
options?: SenzorOptions,
|
|
229
|
+
invokeOptions: InvokeOptions = {}
|
|
230
|
+
): T => {
|
|
231
|
+
if (typeof handler !== 'function') return handler;
|
|
232
|
+
|
|
233
|
+
const wrapped = function wrappedFrameworkHandler(
|
|
234
|
+
this: unknown,
|
|
235
|
+
...args: any[]
|
|
236
|
+
) {
|
|
237
|
+
return invokeWithFrameworkSpan(
|
|
238
|
+
handler,
|
|
239
|
+
this,
|
|
240
|
+
args,
|
|
241
|
+
getInfo(this, args),
|
|
242
|
+
options,
|
|
243
|
+
invokeOptions
|
|
244
|
+
);
|
|
245
|
+
};
|
|
246
|
+
|
|
247
|
+
copyFunctionProperties(handler, wrapped);
|
|
248
|
+
return wrapped as unknown as T;
|
|
249
|
+
};
|
|
250
|
+
|
|
251
|
+
export const wrapFrameworkHandlerWithArity = <T extends Function>(
|
|
252
|
+
handler: T,
|
|
253
|
+
getInfo: (thisArg: unknown, args: any[]) => FrameworkSpanInfo,
|
|
254
|
+
options?: SenzorOptions,
|
|
255
|
+
invokeOptions: InvokeOptions = {}
|
|
256
|
+
): T => {
|
|
257
|
+
if (typeof handler !== 'function') return handler;
|
|
258
|
+
|
|
259
|
+
const invoke = (thisArg: unknown, args: any[]) =>
|
|
260
|
+
invokeWithFrameworkSpan(
|
|
261
|
+
handler,
|
|
262
|
+
thisArg,
|
|
263
|
+
args,
|
|
264
|
+
getInfo(thisArg, args),
|
|
265
|
+
options,
|
|
266
|
+
invokeOptions
|
|
267
|
+
);
|
|
268
|
+
|
|
269
|
+
let wrapped: Function;
|
|
270
|
+
|
|
271
|
+
switch (handler.length) {
|
|
272
|
+
case 4:
|
|
273
|
+
wrapped = function wrapped4(this: unknown, a: any, b: any, c: any, d: any) {
|
|
274
|
+
return invoke(this, [a, b, c, d]);
|
|
275
|
+
};
|
|
276
|
+
break;
|
|
277
|
+
case 3:
|
|
278
|
+
wrapped = function wrapped3(this: unknown, a: any, b: any, c: any) {
|
|
279
|
+
return invoke(this, [a, b, c]);
|
|
280
|
+
};
|
|
281
|
+
break;
|
|
282
|
+
case 2:
|
|
283
|
+
wrapped = function wrapped2(this: unknown, a: any, b: any) {
|
|
284
|
+
return invoke(this, [a, b]);
|
|
285
|
+
};
|
|
286
|
+
break;
|
|
287
|
+
case 1:
|
|
288
|
+
wrapped = function wrapped1(this: unknown, a: any) {
|
|
289
|
+
return invoke(this, [a]);
|
|
290
|
+
};
|
|
291
|
+
break;
|
|
292
|
+
default:
|
|
293
|
+
wrapped = function wrapped0(this: unknown) {
|
|
294
|
+
return invoke(this, Array.from(arguments));
|
|
295
|
+
};
|
|
296
|
+
break;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
copyFunctionProperties(handler, wrapped);
|
|
300
|
+
return wrapped as unknown as T;
|
|
301
|
+
};
|
|
@@ -1,247 +1,134 @@
|
|
|
1
1
|
import Module from 'module';
|
|
2
2
|
|
|
3
|
-
const SENZOR_PATCHED =
|
|
4
|
-
|
|
3
|
+
const SENZOR_PATCHED = Symbol.for('senzor.require.patched');
|
|
4
|
+
const SENZOR_HOOKS = Symbol.for('senzor.require.hooks');
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
type HookFn = (exports: unknown) => unknown | void;
|
|
7
|
+
type HookMap = Map<string, HookFn[]>;
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
9
|
+
// Module.createRequire works in both CJS and ESM contexts,
|
|
10
|
+
// unlike bare `require` which is unavailable in ESM builds.
|
|
11
|
+
const safeRequire: NodeRequire = Module.createRequire(
|
|
12
|
+
typeof __filename !== 'undefined'
|
|
13
|
+
? __filename
|
|
14
|
+
: process.cwd() + '/'
|
|
15
|
+
);
|
|
14
16
|
|
|
15
17
|
function getHookRegistry(): HookMap {
|
|
16
|
-
|
|
17
|
-
const mod =
|
|
18
|
-
Module as unknown as Record<
|
|
19
|
-
symbol,
|
|
20
|
-
HookMap
|
|
21
|
-
>;
|
|
18
|
+
const mod = Module as unknown as Record<symbol, HookMap>;
|
|
22
19
|
|
|
23
20
|
if (!mod[SENZOR_HOOKS]) {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
{
|
|
29
|
-
value: new Map(),
|
|
30
|
-
enumerable: false
|
|
31
|
-
}
|
|
32
|
-
);
|
|
33
|
-
|
|
21
|
+
Object.defineProperty(mod, SENZOR_HOOKS, {
|
|
22
|
+
value: new Map(),
|
|
23
|
+
enumerable: false
|
|
24
|
+
});
|
|
34
25
|
}
|
|
35
26
|
|
|
36
27
|
return mod[SENZOR_HOOKS];
|
|
37
|
-
|
|
38
28
|
}
|
|
39
29
|
|
|
40
|
-
function runHooks(
|
|
41
|
-
|
|
42
|
-
exports
|
|
43
|
-
) {
|
|
44
|
-
|
|
45
|
-
const registry =
|
|
46
|
-
(Module as unknown as Record<
|
|
47
|
-
symbol,
|
|
48
|
-
HookMap
|
|
49
|
-
>)[SENZOR_HOOKS];
|
|
30
|
+
function runHooks(moduleName: string, exports: unknown) {
|
|
31
|
+
const registry = (Module as unknown as Record<symbol, HookMap>)[SENZOR_HOOKS];
|
|
32
|
+
if (!registry) return exports;
|
|
50
33
|
|
|
51
|
-
|
|
34
|
+
const hooks = registry.get(moduleName);
|
|
35
|
+
if (!hooks?.length) return exports;
|
|
52
36
|
|
|
53
|
-
|
|
54
|
-
registry.get(moduleName);
|
|
55
|
-
|
|
56
|
-
if (!hooks?.length) return;
|
|
37
|
+
let currentExports = exports;
|
|
57
38
|
|
|
58
39
|
for (const hook of hooks) {
|
|
59
|
-
|
|
60
40
|
try {
|
|
61
|
-
hook(
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
err
|
|
68
|
-
);
|
|
69
|
-
|
|
41
|
+
const nextExports = hook(currentExports);
|
|
42
|
+
if (nextExports !== undefined) {
|
|
43
|
+
currentExports = nextExports;
|
|
44
|
+
}
|
|
45
|
+
} catch (err) {
|
|
46
|
+
console.error(`[Senzor] instrumentation failed for ${moduleName}`, err);
|
|
70
47
|
}
|
|
71
|
-
|
|
72
48
|
}
|
|
73
49
|
|
|
50
|
+
return currentExports;
|
|
74
51
|
}
|
|
75
52
|
|
|
76
53
|
function patchLoaderOnce() {
|
|
54
|
+
const mod = Module as unknown as any;
|
|
77
55
|
|
|
78
|
-
|
|
79
|
-
Module as unknown as any;
|
|
56
|
+
if (mod[SENZOR_PATCHED]) return;
|
|
80
57
|
|
|
81
|
-
|
|
82
|
-
return;
|
|
83
|
-
}
|
|
58
|
+
const previousLoad = mod._load;
|
|
84
59
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
) {
|
|
94
|
-
|
|
95
|
-
const exports =
|
|
96
|
-
previousLoad.apply(
|
|
97
|
-
this,
|
|
98
|
-
arguments
|
|
99
|
-
);
|
|
100
|
-
|
|
101
|
-
runHooks(
|
|
102
|
-
request,
|
|
103
|
-
exports
|
|
104
|
-
);
|
|
105
|
-
|
|
106
|
-
return exports;
|
|
107
|
-
|
|
108
|
-
};
|
|
109
|
-
|
|
110
|
-
Object.defineProperty(
|
|
111
|
-
mod,
|
|
112
|
-
SENZOR_PATCHED,
|
|
113
|
-
{
|
|
114
|
-
value: true,
|
|
115
|
-
enumerable: false
|
|
116
|
-
}
|
|
117
|
-
);
|
|
60
|
+
mod._load = function patchedLoad(
|
|
61
|
+
request: string,
|
|
62
|
+
parent: unknown,
|
|
63
|
+
isMain: boolean
|
|
64
|
+
) {
|
|
65
|
+
const exports = previousLoad.apply(this, arguments);
|
|
66
|
+
return runHooks(request, exports);
|
|
67
|
+
};
|
|
118
68
|
|
|
69
|
+
Object.defineProperty(mod, SENZOR_PATCHED, {
|
|
70
|
+
value: true,
|
|
71
|
+
enumerable: false
|
|
72
|
+
});
|
|
119
73
|
}
|
|
120
74
|
|
|
121
|
-
function patchCached(
|
|
122
|
-
moduleName: string,
|
|
123
|
-
hook: HookFn
|
|
124
|
-
) {
|
|
125
|
-
|
|
75
|
+
function patchCached(moduleName: string, hook: HookFn) {
|
|
126
76
|
try {
|
|
127
|
-
|
|
128
|
-
const
|
|
129
|
-
require.resolve(
|
|
130
|
-
moduleName
|
|
131
|
-
);
|
|
132
|
-
|
|
133
|
-
const cached =
|
|
134
|
-
require.cache?.[
|
|
135
|
-
resolved
|
|
136
|
-
];
|
|
77
|
+
const resolved = safeRequire.resolve(moduleName);
|
|
78
|
+
const cached = safeRequire.cache?.[resolved];
|
|
137
79
|
|
|
138
80
|
if (cached?.exports) {
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
cached.exports
|
|
142
|
-
|
|
143
|
-
|
|
81
|
+
const replacement = hook(cached.exports);
|
|
82
|
+
if (replacement !== undefined) {
|
|
83
|
+
cached.exports = replacement;
|
|
84
|
+
}
|
|
144
85
|
}
|
|
145
|
-
|
|
146
|
-
}
|
|
147
|
-
catch { }
|
|
148
|
-
|
|
86
|
+
} catch { }
|
|
149
87
|
}
|
|
150
88
|
|
|
151
|
-
function tryRequire(
|
|
152
|
-
moduleName: string,
|
|
153
|
-
hook: HookFn
|
|
154
|
-
) {
|
|
155
|
-
|
|
89
|
+
function tryRequire(moduleName: string, hook: HookFn) {
|
|
156
90
|
try {
|
|
157
|
-
|
|
158
|
-
const mod =
|
|
159
|
-
require(moduleName);
|
|
160
|
-
|
|
91
|
+
const mod = safeRequire(moduleName);
|
|
161
92
|
if (mod) {
|
|
162
93
|
hook(mod);
|
|
163
94
|
}
|
|
164
|
-
|
|
165
|
-
}
|
|
166
|
-
catch { }
|
|
167
|
-
|
|
95
|
+
} catch { }
|
|
168
96
|
}
|
|
169
97
|
|
|
170
|
-
function retryPatch(
|
|
171
|
-
moduleName: string,
|
|
172
|
-
hook: HookFn
|
|
173
|
-
) {
|
|
174
|
-
|
|
98
|
+
function retryPatch(moduleName: string, hook: HookFn) {
|
|
175
99
|
let attempts = 0;
|
|
176
|
-
|
|
177
100
|
const max = 5;
|
|
178
101
|
|
|
179
|
-
const timer =
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
attempts++;
|
|
183
|
-
|
|
184
|
-
try {
|
|
185
|
-
|
|
186
|
-
const mod =
|
|
187
|
-
require(moduleName);
|
|
188
|
-
|
|
189
|
-
if (mod) {
|
|
190
|
-
|
|
191
|
-
hook(mod);
|
|
102
|
+
const timer = setInterval(() => {
|
|
103
|
+
attempts++;
|
|
192
104
|
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
}
|
|
198
|
-
catch { }
|
|
199
|
-
|
|
200
|
-
if (attempts >= max) {
|
|
105
|
+
try {
|
|
106
|
+
const mod = safeRequire(moduleName);
|
|
107
|
+
if (mod) {
|
|
108
|
+
hook(mod);
|
|
201
109
|
clearInterval(timer);
|
|
202
110
|
}
|
|
111
|
+
} catch { }
|
|
203
112
|
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
export const hookRequire =
|
|
209
|
-
(
|
|
210
|
-
moduleName: string,
|
|
211
|
-
onRequire: HookFn
|
|
212
|
-
) => {
|
|
213
|
-
|
|
214
|
-
const registry =
|
|
215
|
-
getHookRegistry();
|
|
216
|
-
|
|
217
|
-
if (!registry.has(moduleName)) {
|
|
218
|
-
|
|
219
|
-
registry.set(
|
|
220
|
-
moduleName,
|
|
221
|
-
[]
|
|
222
|
-
);
|
|
223
|
-
|
|
113
|
+
if (attempts >= max) {
|
|
114
|
+
clearInterval(timer);
|
|
224
115
|
}
|
|
116
|
+
}, 200);
|
|
225
117
|
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
.push(onRequire);
|
|
229
|
-
|
|
230
|
-
patchLoaderOnce();
|
|
118
|
+
if (typeof timer.unref === 'function') timer.unref();
|
|
119
|
+
}
|
|
231
120
|
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
onRequire
|
|
235
|
-
);
|
|
121
|
+
export const hookRequire = (moduleName: string, onRequire: HookFn) => {
|
|
122
|
+
const registry = getHookRegistry();
|
|
236
123
|
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
);
|
|
124
|
+
if (!registry.has(moduleName)) {
|
|
125
|
+
registry.set(moduleName, []);
|
|
126
|
+
}
|
|
241
127
|
|
|
242
|
-
|
|
243
|
-
moduleName,
|
|
244
|
-
onRequire
|
|
245
|
-
);
|
|
128
|
+
registry.get(moduleName)!.push(onRequire);
|
|
246
129
|
|
|
247
|
-
|
|
130
|
+
patchLoaderOnce();
|
|
131
|
+
patchCached(moduleName, onRequire);
|
|
132
|
+
tryRequire(moduleName, onRequire);
|
|
133
|
+
retryPatch(moduleName, onRequire);
|
|
134
|
+
};
|