trickle-observe 0.2.67 → 0.2.68
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/observe-esm-hooks.mjs +66 -16
- package/package.json +1 -1
package/observe-esm-hooks.mjs
CHANGED
|
@@ -523,7 +523,21 @@ function transformSource(source, url, originalSource) {
|
|
|
523
523
|
const paramNames = parenPos >= 0 ? extractParamNamesFromSource(source, parenPos) : [];
|
|
524
524
|
// Remove 'export ' prefix, keep the function
|
|
525
525
|
result.push(line.replace(/^(\s*)export\s+/, '$1'));
|
|
526
|
-
exportedFunctions.push({ name, paramNames });
|
|
526
|
+
exportedFunctions.push({ name, paramNames, wrapInPlace: true });
|
|
527
|
+
continue;
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
// Non-exported function declarations — wrap them too for entry module coverage
|
|
531
|
+
const plainFuncMatch = trimmed.match(/^(async\s+)?function\s+(\w+)\s*(?:<[^>]*>)?\s*\(/);
|
|
532
|
+
if (plainFuncMatch && !trimmed.startsWith('export')) {
|
|
533
|
+
const name = plainFuncMatch[2];
|
|
534
|
+
if (name !== 'require' && name !== 'exports' && name !== 'module' && !name.startsWith('__trickle')) {
|
|
535
|
+
const srcOffset = lineOffset(source, i) + (line.length - trimmed.length);
|
|
536
|
+
const parenPos = source.indexOf('(', srcOffset + plainFuncMatch[0].indexOf('('));
|
|
537
|
+
const paramNames = parenPos >= 0 ? extractParamNamesFromSource(source, parenPos) : [];
|
|
538
|
+
exportedFunctions.push({ name, paramNames, wrapInPlace: true, noExport: true });
|
|
539
|
+
}
|
|
540
|
+
result.push(line);
|
|
527
541
|
continue;
|
|
528
542
|
}
|
|
529
543
|
|
|
@@ -607,23 +621,58 @@ function transformSource(source, url, originalSource) {
|
|
|
607
621
|
return source;
|
|
608
622
|
}
|
|
609
623
|
|
|
610
|
-
// Add wrapper import and wrapping code
|
|
624
|
+
// Add wrapper import and wrapping code
|
|
611
625
|
const wrapperPathEscaped = config.wrapperPath.replace(/\\/g, '\\\\');
|
|
612
626
|
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
627
|
+
// Insert wrapper setup at the top (after imports, before user code)
|
|
628
|
+
// Using import + createRequire to load CJS wrapper from ESM context
|
|
629
|
+
const wrapSetup = [
|
|
630
|
+
'',
|
|
631
|
+
'// [trickle] Auto-observation wrappers',
|
|
632
|
+
`import { createRequire as __cr } from 'node:module';`,
|
|
633
|
+
`const __require = __cr(import.meta.url);`,
|
|
634
|
+
`const { wrapFunction: __tw } = __require('${wrapperPathEscaped}');`,
|
|
635
|
+
`const __twOpts = (name, paramNames) => { const o = { functionName: name, module: '${moduleName}', trackArgs: true, trackReturn: true, sampleRate: 1, maxDepth: 5, environment: process.env.TRICKLE_ENV || 'development', enabled: true }; if (paramNames && paramNames.length) o.paramNames = paramNames; return o; };`,
|
|
636
|
+
];
|
|
637
|
+
|
|
638
|
+
// For in-place wrapping: insert wrapper calls right after each function declaration
|
|
639
|
+
// This ensures functions are wrapped BEFORE any top-level code calls them
|
|
640
|
+
const inPlaceWraps = [];
|
|
641
|
+
for (const fn of exportedFunctions) {
|
|
642
|
+
if (fn.wrapInPlace) {
|
|
643
|
+
const pn = fn.paramNames.length > 0 ? JSON.stringify(fn.paramNames) : 'null';
|
|
644
|
+
inPlaceWraps.push(`try{${fn.name}=__tw(${fn.name},__twOpts('${fn.name}',${pn}))}catch(__e){}`);
|
|
645
|
+
}
|
|
646
|
+
}
|
|
619
647
|
|
|
620
|
-
//
|
|
648
|
+
// Find the right position to insert the wrap setup + in-place wraps
|
|
649
|
+
// Insert after the last import/function-declaration block, before top-level code
|
|
650
|
+
let insertIdx = 0;
|
|
651
|
+
for (let j = 0; j < result.length; j++) {
|
|
652
|
+
const t = result[j].trimStart();
|
|
653
|
+
if (t.startsWith('import ') || t.startsWith('// [trickle]') || t === '' ||
|
|
654
|
+
t.startsWith('function ') || t.startsWith('async function ') ||
|
|
655
|
+
t.startsWith('const __trickle_tv') || t.startsWith('const __require_tv') ||
|
|
656
|
+
t.startsWith('const __tv_mod') || t.startsWith('if (typeof __tv_mod')) {
|
|
657
|
+
insertIdx = j + 1;
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
// But make sure we're after any function body closing braces too
|
|
661
|
+
// Simple heuristic: find the last line that's just '}' before any assignment/call
|
|
662
|
+
for (let j = insertIdx; j < result.length; j++) {
|
|
663
|
+
const t = result[j].trim();
|
|
664
|
+
if (t === '}') insertIdx = j + 1;
|
|
665
|
+
else if (t && !t.startsWith('//') && !t.startsWith('function') && !t.startsWith('async function')) break;
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
result.splice(insertIdx, 0, ...wrapSetup, ...inPlaceWraps, '');
|
|
669
|
+
|
|
670
|
+
// Re-export wrapped functions (for importers of this module)
|
|
621
671
|
const reExports = [];
|
|
622
|
-
for (const
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
reExports.push(`${wrappedName} as ${name}`);
|
|
672
|
+
for (const fn of exportedFunctions) {
|
|
673
|
+
if (!fn.noExport) {
|
|
674
|
+
reExports.push(`${fn.name}`);
|
|
675
|
+
}
|
|
627
676
|
}
|
|
628
677
|
|
|
629
678
|
// Handle named exports from export { } statements
|
|
@@ -703,10 +752,11 @@ export async function load(url, context, nextLoad) {
|
|
|
703
752
|
? source
|
|
704
753
|
: Buffer.from(source).toString('utf-8');
|
|
705
754
|
|
|
706
|
-
// Only transform if the module has exports or variable declarations to trace
|
|
755
|
+
// Only transform if the module has exports, function declarations, or variable declarations to trace
|
|
707
756
|
const varTraceEnabled = process.env.TRICKLE_TRACE_VARS !== '0' && config.traceVarPath;
|
|
708
757
|
const hasVarDecls = varTraceEnabled && /^[ \t]*(?:export\s+)?(?:const|let|var)\s+[a-zA-Z_$]/m.test(sourceStr);
|
|
709
|
-
|
|
758
|
+
const hasFuncDecls = /^[ \t]*(?:export\s+)?(?:async\s+)?function\s+\w/m.test(sourceStr);
|
|
759
|
+
if (!sourceStr.includes('export ') && !hasVarDecls && !hasFuncDecls) return result;
|
|
710
760
|
|
|
711
761
|
try {
|
|
712
762
|
const transformed = transformSource(sourceStr, url);
|