@sailfish-ai/sf-veritas 0.2.7 → 0.2.9
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/dist/contextManager-CEPhVu9T.js +197 -0
- package/dist/contextManager-CGINtRN5.cjs +1 -0
- package/dist/funcSpanTransformer-B9WWl-g1.cjs +1 -0
- package/dist/funcSpanTransformer-CWNEWRxq.js +225 -0
- package/dist/plugins/funcspanEsbuildPlugin.cjs +1 -1
- package/dist/plugins/funcspanEsbuildPlugin.mjs +17 -11
- package/dist/plugins/funcspanRollupPlugin.cjs +1 -1
- package/dist/plugins/funcspanRollupPlugin.mjs +13 -8
- package/dist/plugins/funcspanTscPlugin.cjs +1 -1
- package/dist/plugins/funcspanTscPlugin.mjs +19 -14
- package/dist/plugins/funcspanVitePlugin.cjs +1 -1
- package/dist/plugins/funcspanVitePlugin.mjs +15 -10
- package/dist/plugins/funcspanWebpackLoader.cjs +1 -1
- package/dist/plugins/funcspanWebpackLoader.mjs +1 -1
- package/dist/plugins/funcspanWebpackPlugin.cjs +1 -1
- package/dist/plugins/funcspanWebpackPlugin.mjs +22 -17
- package/dist/runtime/funcspanRegister.cjs +276 -0
- package/dist/runtimeConfig-CpQ27dZD.cjs +8 -0
- package/dist/runtimeConfig-emBNO3lJ.js +350 -0
- package/dist/sf-veritas.cjs +18 -18
- package/dist/sf-veritas.mjs +417 -619
- package/dist/source-map-Cr6YkjTd.js +631 -0
- package/dist/source-map-rHHEdpre.cjs +1 -0
- package/dist/types/dataTransmitter.d.ts +1 -0
- package/dist/types/funcSpanConfigLoader.d.ts +10 -0
- package/dist/types/index.d.ts +3 -1
- package/dist/types/logHandler.d.ts +5 -0
- package/dist/types/plugins/funcSpanTransformer.d.ts +13 -0
- package/dist/types/runtime/instrumentationDetector.d.ts +33 -0
- package/dist/types/runtime/runtimeConfig.d.ts +48 -0
- package/dist/types/sourceLocation.d.ts +30 -0
- package/dist/worker-pool-capture.cjs +1 -1
- package/dist/worker-pool-capture.mjs +1 -1
- package/dist/workerPoolSpanCapture-B5KN-q4b.js +528 -0
- package/dist/workerPoolSpanCapture-Dg_WGjmO.cjs +86 -0
- package/package.json +5 -2
- package/dist/funcSpanTransformer-BLhIRZqX.js +0 -765
- package/dist/funcSpanTransformer-BpWuHXKT.cjs +0 -1
- package/dist/workerPoolSpanCapture-D0-0Z0Jw.js +0 -718
- package/dist/workerPoolSpanCapture-DEwlTq0a.cjs +0 -86
|
@@ -1,39 +1,44 @@
|
|
|
1
1
|
import { readFileSync as m, writeFileSync as l } from "fs";
|
|
2
|
-
import { sync as
|
|
2
|
+
import { sync as g } from "glob";
|
|
3
3
|
import { resolve as C } from "path";
|
|
4
|
-
import { t as
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
4
|
+
import { t as _ } from "../funcSpanTransformer-CWNEWRxq.js";
|
|
5
|
+
import { s as N } from "../runtimeConfig-emBNO3lJ.js";
|
|
6
|
+
async function D(n = {}) {
|
|
7
|
+
try {
|
|
8
|
+
if (N()) return void console.warn("[FuncSpan TSC Plugin] Runtime mode active - build plugin DISABLED to prevent double-instrumentation");
|
|
9
|
+
} catch {
|
|
10
|
+
}
|
|
11
|
+
const { outDir: d = "dist", include: S = ["**/*.js"], exclude: f = ["**/*.test.js", "**/*.spec.js", "**/__tests__/**"], projectRoot: t = process.cwd(), includeNodeModules: F = [], debug: c = !1 } = n, i = C(t, d);
|
|
12
|
+
console.log("[FuncSpan TSC] Starting post-build function instrumentation..."), console.log(`[FuncSpan TSC] Output directory: ${i}`), console.log(`[FuncSpan TSC] Project root: ${t}`);
|
|
8
13
|
const r = [];
|
|
9
14
|
for (const o of S) {
|
|
10
|
-
const s =
|
|
15
|
+
const s = g(o, { cwd: i, absolute: !0, ignore: f });
|
|
11
16
|
r.push(...s);
|
|
12
17
|
}
|
|
13
18
|
console.log(`[FuncSpan TSC] Found ${r.length} JavaScript files to process`);
|
|
14
|
-
let u = 0,
|
|
19
|
+
let u = 0, a = 0;
|
|
15
20
|
for (const o of r) try {
|
|
16
|
-
const s = m(o, "utf-8"), e = await
|
|
21
|
+
const s = m(o, "utf-8"), e = await _(s, o, { projectRoot: t, includeNodeModules: F, debug: c });
|
|
17
22
|
if (e.modified) {
|
|
18
23
|
if (l(o, e.code, "utf-8"), e.map) {
|
|
19
|
-
const
|
|
20
|
-
l(
|
|
24
|
+
const p = `${o}.map`;
|
|
25
|
+
l(p, JSON.stringify(e.map), "utf-8"), c && console.log(`[FuncSpan TSC] Generated source map: ${p}`);
|
|
21
26
|
}
|
|
22
|
-
u++,
|
|
27
|
+
u++, a += e.functionsWrapped, c && console.log(`[FuncSpan TSC] Modified: ${o} (${e.functionsWrapped} functions)`);
|
|
23
28
|
}
|
|
24
29
|
} catch (s) {
|
|
25
30
|
console.error(`[FuncSpan TSC] Error processing ${o}:`, s);
|
|
26
31
|
}
|
|
27
|
-
console.log(`[FuncSpan TSC] ✅ Completed: Modified ${u} files, wrapped ${
|
|
32
|
+
console.log(`[FuncSpan TSC] ✅ Completed: Modified ${u} files, wrapped ${a} functions`);
|
|
28
33
|
}
|
|
29
34
|
async function T() {
|
|
30
35
|
const n = { outDir: process.env.SF_FUNCSPAN_OUT_DIR || "dist", debug: process.env.SF_FUNCSPAN_DEBUG === "true", includeNodeModules: process.env.SF_FUNCSPAN_INCLUDE_NODE_MODULES ? process.env.SF_FUNCSPAN_INCLUDE_NODE_MODULES.split(",") : [] };
|
|
31
|
-
await
|
|
36
|
+
await D(n);
|
|
32
37
|
}
|
|
33
38
|
require.main === module && T().catch((n) => {
|
|
34
39
|
console.error("[FuncSpan TSC] Fatal error:", n), process.exit(1);
|
|
35
40
|
});
|
|
36
41
|
export {
|
|
37
42
|
T as cli,
|
|
38
|
-
|
|
43
|
+
D as processTscFiles
|
|
39
44
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const r=require("../funcSpanTransformer-B9WWl-g1.cjs"),l=require("../runtimeConfig-CpQ27dZD.cjs");exports.funcspanVitePlugin=function(s={}){try{if(l.shouldEnableRuntimeHooks())return console.warn("[FuncSpan Vite Plugin] Runtime mode active - build plugin DISABLED to prevent double-instrumentation"),{name:"sailfish-funcspan-vite-disabled"}}catch{}const{enabled:o=!0,includeNodeModules:t=[],debug:i=!1}=s;return{name:"sailfish-funcspan-vite",enforce:"pre",async transform(u,e){if(!o||!e.match(/\.(js|ts|jsx|tsx)$/)||e.startsWith("\0")||e.includes("node_modules")&&!t.some(n=>e.includes(`node_modules/${n}`))||e.includes("@sailfish-ai/sf-veritas")||e.includes("jsts-backend/dist"))return null;try{const n=await r.transformFunctionSpans(u,e,{projectRoot:process.cwd(),includeNodeModules:t,debug:i});if(n.modified)return{code:n.code,map:null}}catch(n){i&&console.error(`[FuncSpan Vite] Error transforming ${e}:`,n)}return null}}};
|
|
@@ -1,17 +1,22 @@
|
|
|
1
|
-
import { t as o } from "../funcSpanTransformer-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
if (
|
|
1
|
+
import { t as o } from "../funcSpanTransformer-CWNEWRxq.js";
|
|
2
|
+
import { s as l } from "../runtimeConfig-emBNO3lJ.js";
|
|
3
|
+
function d(u = {}) {
|
|
4
|
+
try {
|
|
5
|
+
if (l()) return console.warn("[FuncSpan Vite Plugin] Runtime mode active - build plugin DISABLED to prevent double-instrumentation"), { name: "sailfish-funcspan-vite-disabled" };
|
|
6
|
+
} catch {
|
|
7
|
+
}
|
|
8
|
+
const { enabled: r = !0, includeNodeModules: t = [], debug: i = !1 } = u;
|
|
9
|
+
return { name: "sailfish-funcspan-vite", enforce: "pre", async transform(s, n) {
|
|
10
|
+
if (!r || !n.match(/\.(js|ts|jsx|tsx)$/) || n.startsWith("\0") || n.includes("node_modules") && !t.some((e) => n.includes(`node_modules/${e}`)) || n.includes("@sailfish-ai/sf-veritas") || n.includes("jsts-backend/dist")) return null;
|
|
6
11
|
try {
|
|
7
|
-
const
|
|
8
|
-
if (
|
|
9
|
-
} catch (
|
|
10
|
-
|
|
12
|
+
const e = await o(s, n, { projectRoot: process.cwd(), includeNodeModules: t, debug: i });
|
|
13
|
+
if (e.modified) return { code: e.code, map: null };
|
|
14
|
+
} catch (e) {
|
|
15
|
+
i && console.error(`[FuncSpan Vite] Error transforming ${n}:`, e);
|
|
11
16
|
}
|
|
12
17
|
return null;
|
|
13
18
|
} };
|
|
14
19
|
}
|
|
15
20
|
export {
|
|
16
|
-
|
|
21
|
+
d as funcspanVitePlugin
|
|
17
22
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";const I=require("../funcSpanTransformer-
|
|
1
|
+
"use strict";const I=require("../funcSpanTransformer-B9WWl-g1.cjs"),M=require("@babel/parser"),x=require("@babel/traverse"),O=require("@babel/generator"),R=require("@babel/types"),z=require("path");function L(n){const p=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(n){for(const r in n)if(r!=="default"){const l=Object.getOwnPropertyDescriptor(n,r);Object.defineProperty(p,r,l.get?l:{enumerable:!0,get:()=>n[r]})}}return p.default=n,Object.freeze(p)}const e=L(R),C=x.default||x,N=O.default||O,Z=["lookup","lookupService","resolve","resolve4","resolve6","resolveAny","resolveCname","resolveMx","resolveNs","resolvePtr","resolveSoa","resolveSrv","resolveTxt","reverse","setServers","getServers"],A=["readFile","writeFile","appendFile","readdir","stat","lstat","mkdir","rmdir","unlink","rename","copyFile","open","close","read","write","access"],B=["pbkdf2","randomBytes","randomFill","scrypt"],G=["deflate","deflateRaw","gzip","gunzip","inflate","inflateRaw","unzip","brotliCompress","brotliDecompress"];module.exports=function(n){const p=this.async(),r=this.getOptions();(async()=>{try{let l=await I.transformFunctionSpans(n,this.resourcePath,{projectRoot:r.projectRoot||process.cwd(),includeNodeModules:r.includeNodeModules||[],debug:r.debug||!1}),m=l.modified?l.code:n,v=l.map;if(r.enableWorkerPoolTracking){const k=await(async function(g,W,D={}){const{projectRoot:q=process.cwd(),trackDns:h=!1,trackFs:w=!1,trackCrypto:j=!1,trackZlib:T=!1,debug:d=!1}=D;if(!(h||w||j||T))return{code:g,modified:!1,callsWrapped:0};const b=z.relative(q,W).replace(/\\/g,"/");let u;d&&console.log(`[WorkerPool Transform] Processing: ${b}`);try{u=M.parse(g,{sourceType:"module",plugins:["typescript","jsx","decorators-legacy","classProperties","objectRestSpread","asyncGenerators","dynamicImport","optionalCatchBinding","optionalChaining","nullishCoalescingOperator"]})}catch(t){return d&&console.error(`[WorkerPool Transform] Parse error in ${b}:`,t),{code:g,modified:!1,callsWrapped:0}}let F=!1,y=0,S=!1;const P=new Map,c=new Map;if(h&&c.set("dns",Z),w&&c.set("fs",A),j&&c.set("crypto",B),T&&c.set("zlib",G),C(u,{VariableDeclarator(t){const o=t.node.init,i=t.node.id;if(o&&e.isCallExpression(o)&&e.isIdentifier(o.callee,{name:"require"})&&o.arguments.length===1&&e.isStringLiteral(o.arguments[0])){const s=o.arguments[0].value;for(const[a]of c)s!==a&&s!==`node:${a}`||e.isIdentifier(i)&&(P.set(i.name,a),d&&console.log(`[WorkerPool Transform] Found ${a} binding: ${i.name}`))}},ImportDeclaration(t){const o=t.node.source.value;for(const[i]of c)if(o===i||o===`node:${i}`){for(const s of t.node.specifiers)if(e.isImportDefaultSpecifier(s)||e.isImportNamespaceSpecifier(s)){const a=s.local.name;P.set(a,i),d&&console.log(`[WorkerPool Transform] Found ${i} import: ${a}`)}}}}),C(u,{CallExpression(t){const o=t.node.callee;if(e.isMemberExpression(o)&&e.isIdentifier(o.object)){const i=o.object.name,s=P.get(i);if(s&&c.has(s)){const a=c.get(s),f=e.isIdentifier(o.property)?o.property.name:null;if(f&&a.includes(f)){d&&console.log(`[WorkerPool Transform] Wrapping ${s}.${f}()`);const E=e.callExpression(e.identifier("captureWorkerPoolOperation"),[e.stringLiteral(s),e.stringLiteral(f),e.memberExpression(e.identifier(i),e.identifier(f)),e.arrayExpression(t.node.arguments),e.identifier(i)]);t.replaceWith(E),S=!0,y++,F=!0}}}}}),S){const t=e.variableDeclaration("const",[e.variableDeclarator(e.objectPattern([e.objectProperty(e.identifier("captureWorkerPoolOperation"),e.identifier("captureWorkerPoolOperation"),!1,!0)]),e.callExpression(e.identifier("require"),[e.stringLiteral("@sailfish-ai/sf-veritas/worker-pool-capture")]))]);u.program.body.length>0&&u.program.body.unshift(t),d&&console.log("[WorkerPool Transform] Added captureWorkerPoolOperation import")}if(!F)return{code:g,modified:!1,callsWrapped:0};const $=N(u,{sourceMaps:!0,sourceFileName:W});return d&&console.log(`[WorkerPool Transform] Wrapped ${y} calls in ${b}`),{code:$.code,map:$.map,modified:!0,callsWrapped:y}})(m,this.resourcePath,{projectRoot:r.projectRoot||process.cwd(),trackDns:r.workerPoolTrackDns||!1,trackFs:r.workerPoolTrackFs||!1,trackCrypto:r.workerPoolTrackCrypto||!1,trackZlib:r.workerPoolTrackZlib||!1,debug:r.debug||!1});k.modified&&(m=k.code,v=k.map)}m!==n?p(null,m,v):p(null,n)}catch(l){r.debug&&console.error(`[FuncSpan Webpack Loader] Error transforming ${this.resourcePath}:`,l),p(null,n)}})()};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var m=Object.defineProperty;var P=(o,e,r)=>e in o?m(o,e,{enumerable:!0,configurable:!0,writable:!0,value:r}):o[e]=r;var a=(o,e,r)=>P(o,typeof e!="symbol"?e+"":e,r);Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const g=require("../runtimeConfig-CpQ27dZD.cjs"),p=require("path"),T=require("url");var u=typeof document<"u"?document.currentScript:null;function h(o){const e=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(o){for(const r in o)if(r!=="default"){const t=Object.getOwnPropertyDescriptor(o,r);Object.defineProperty(e,r,t.get?t:{enumerable:!0,get:()=>o[r]})}}return e.default=o,Object.freeze(e)}const w=h(p);class d{constructor(e={}){a(this,"options");this.options={enabled:!0,includeNodeModules:[],debug:!1,enableWorkerPoolTracking:!1,workerPoolTrackDns:!1,workerPoolTrackFs:!1,workerPoolTrackCrypto:!1,workerPoolTrackZlib:!1,...e}}apply(e){try{if(g.shouldEnableRuntimeHooks())return void console.warn("[FuncSpan Webpack Plugin] Runtime mode active - build plugin DISABLED to prevent double-instrumentation")}catch{}const{enabled:r,includeNodeModules:t,debug:i}=this.options;if(!r)return;const c="FuncspanWebpackPlugin";e.hooks.compilation.tap(c,l=>{l.hooks.buildModule.tap(c,s=>{s.resource&&s.resource.match(/\.(js|ts|jsx|tsx)$/)&&(!s.resource.includes("node_modules")||t?.some(n=>s.resource.includes(`node_modules/${n}`)))}),e.webpack.NormalModule.getCompilationHooks(l).loader.tap(c,(s,n)=>{if(!n.resource||!n.resource.match(/\.(js|ts|jsx|tsx)$/)||n.resource.includes("node_modules")&&!t?.some(f=>n.resource.includes(`node_modules/${f}`)))return;const k=typeof __dirname<"u"?__dirname:p.dirname(T.fileURLToPath(typeof document>"u"?require("url").pathToFileURL(__filename).href:u&&u.tagName.toUpperCase()==="SCRIPT"&&u.src||new URL("plugins/funcspanWebpackPlugin.cjs",document.baseURI).href)),b=w.join(k,"funcspanWebpackLoader.cjs");n.loaders.push({loader:b,options:{projectRoot:e.context,includeNodeModules:t,debug:i,enableWorkerPoolTracking:this.options.enableWorkerPoolTracking,workerPoolTrackDns:this.options.workerPoolTrackDns,workerPoolTrackFs:this.options.workerPoolTrackFs,workerPoolTrackCrypto:this.options.workerPoolTrackCrypto,workerPoolTrackZlib:this.options.workerPoolTrackZlib}})})}),i&&console.log("[FuncSpan Webpack] Plugin initialized")}}exports.FuncspanWebpackPlugin=d,exports.default=d;
|
|
@@ -1,30 +1,35 @@
|
|
|
1
|
-
var
|
|
2
|
-
var m = (r, o, s) => o in r ?
|
|
3
|
-
var
|
|
1
|
+
var k = Object.defineProperty;
|
|
2
|
+
var m = (r, o, s) => o in r ? k(r, o, { enumerable: !0, configurable: !0, writable: !0, value: s }) : r[o] = s;
|
|
3
|
+
var c = (r, o, s) => m(r, typeof o != "symbol" ? o + "" : o, s);
|
|
4
|
+
import { s as b } from "../runtimeConfig-emBNO3lJ.js";
|
|
4
5
|
import * as P from "path";
|
|
5
|
-
import { dirname as
|
|
6
|
-
import { fileURLToPath as
|
|
7
|
-
class
|
|
6
|
+
import { dirname as T } from "path";
|
|
7
|
+
import { fileURLToPath as f } from "url";
|
|
8
|
+
class _ {
|
|
8
9
|
constructor(o = {}) {
|
|
9
|
-
|
|
10
|
+
c(this, "options");
|
|
10
11
|
this.options = { enabled: !0, includeNodeModules: [], debug: !1, enableWorkerPoolTracking: !1, workerPoolTrackDns: !1, workerPoolTrackFs: !1, workerPoolTrackCrypto: !1, workerPoolTrackZlib: !1, ...o };
|
|
11
12
|
}
|
|
12
13
|
apply(o) {
|
|
13
|
-
|
|
14
|
+
try {
|
|
15
|
+
if (b()) return void console.warn("[FuncSpan Webpack Plugin] Runtime mode active - build plugin DISABLED to prevent double-instrumentation");
|
|
16
|
+
} catch {
|
|
17
|
+
}
|
|
18
|
+
const { enabled: s, includeNodeModules: i, debug: t } = this.options;
|
|
14
19
|
if (!s) return;
|
|
15
20
|
const a = "FuncspanWebpackPlugin";
|
|
16
|
-
o.hooks.compilation.tap(a, (
|
|
17
|
-
|
|
18
|
-
n.resource && n.resource.match(/\.(js|ts|jsx|tsx)$/) && (!n.resource.includes("node_modules") ||
|
|
19
|
-
}), o.webpack.NormalModule.getCompilationHooks(
|
|
20
|
-
if (!e.resource || !e.resource.match(/\.(js|ts|jsx|tsx)$/) || e.resource.includes("node_modules") && !
|
|
21
|
-
const u = typeof __dirname < "u" ? __dirname :
|
|
22
|
-
e.loaders.push({ loader: d, options: { projectRoot: o.context, includeNodeModules:
|
|
21
|
+
o.hooks.compilation.tap(a, (l) => {
|
|
22
|
+
l.hooks.buildModule.tap(a, (n) => {
|
|
23
|
+
n.resource && n.resource.match(/\.(js|ts|jsx|tsx)$/) && (!n.resource.includes("node_modules") || i?.some((e) => n.resource.includes(`node_modules/${e}`)));
|
|
24
|
+
}), o.webpack.NormalModule.getCompilationHooks(l).loader.tap(a, (n, e) => {
|
|
25
|
+
if (!e.resource || !e.resource.match(/\.(js|ts|jsx|tsx)$/) || e.resource.includes("node_modules") && !i?.some((p) => e.resource.includes(`node_modules/${p}`))) return;
|
|
26
|
+
const u = typeof __dirname < "u" ? __dirname : T(f(import.meta.url)), d = P.join(u, "funcspanWebpackLoader.cjs");
|
|
27
|
+
e.loaders.push({ loader: d, options: { projectRoot: o.context, includeNodeModules: i, debug: t, enableWorkerPoolTracking: this.options.enableWorkerPoolTracking, workerPoolTrackDns: this.options.workerPoolTrackDns, workerPoolTrackFs: this.options.workerPoolTrackFs, workerPoolTrackCrypto: this.options.workerPoolTrackCrypto, workerPoolTrackZlib: this.options.workerPoolTrackZlib } });
|
|
23
28
|
});
|
|
24
29
|
}), t && console.log("[FuncSpan Webpack] Plugin initialized");
|
|
25
30
|
}
|
|
26
31
|
}
|
|
27
32
|
export {
|
|
28
|
-
|
|
29
|
-
|
|
33
|
+
_ as FuncspanWebpackPlugin,
|
|
34
|
+
_ as default
|
|
30
35
|
};
|
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CommonJS Require Hook for Function Span Runtime Instrumentation
|
|
3
|
+
*
|
|
4
|
+
* This Node.js module hooks into the require() system to apply function span
|
|
5
|
+
* transformations at runtime for CommonJS modules.
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* node -r @sailfish-ai/sf-veritas/runtime/commonjs-hook app.js
|
|
9
|
+
* node --require @sailfish-ai/sf-veritas/runtime/commonjs-hook app.js
|
|
10
|
+
*
|
|
11
|
+
* With ts-node:
|
|
12
|
+
* node -r ts-node/register -r @sailfish-ai/sf-veritas/runtime/commonjs-hook app.ts
|
|
13
|
+
*
|
|
14
|
+
* Environment Variables:
|
|
15
|
+
* SF_FUNCSPAN_DEBUG=true Enable debug logging
|
|
16
|
+
* SF_FUNCSPAN_SAMPLE_RATE=1.0 Override sampling rate
|
|
17
|
+
* SF_FUNCSPAN_INCLUDE_NODE_MODULES=pkg1,pkg2 Instrument specific packages
|
|
18
|
+
*
|
|
19
|
+
* Requirements: Node 12+
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
const Module = require('module');
|
|
23
|
+
const fs = require('fs');
|
|
24
|
+
const path = require('path');
|
|
25
|
+
|
|
26
|
+
// Configuration from environment variables
|
|
27
|
+
const DEBUG = process.env.SF_FUNCSPAN_DEBUG === 'true';
|
|
28
|
+
const INCLUDE_NODE_MODULES = process.env.SF_FUNCSPAN_INCLUDE_NODE_MODULES
|
|
29
|
+
? process.env.SF_FUNCSPAN_INCLUDE_NODE_MODULES.split(',').map(s => s.trim())
|
|
30
|
+
: [];
|
|
31
|
+
|
|
32
|
+
// CRITICAL: Early exit if runtime hooks should not be enabled
|
|
33
|
+
// This checks environment variables, .sailfish config, and production detection
|
|
34
|
+
try {
|
|
35
|
+
const { shouldEnableRuntimeHooks, isAlreadyInstrumented } = require('@sailfish-ai/sf-veritas');
|
|
36
|
+
|
|
37
|
+
if (!shouldEnableRuntimeHooks()) {
|
|
38
|
+
if (DEBUG) {
|
|
39
|
+
console.log('[FuncSpan CommonJS Hook] Runtime hooks DISABLED (production or not enabled)');
|
|
40
|
+
}
|
|
41
|
+
// Export empty object and exit - no hooks will be registered
|
|
42
|
+
module.exports = {};
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (DEBUG) {
|
|
47
|
+
console.log('[FuncSpan CommonJS Hook] Runtime hooks ENABLED (development mode)');
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Make isAlreadyInstrumented available globally for shouldTransform()
|
|
51
|
+
global._sailfishIsAlreadyInstrumented = isAlreadyInstrumented;
|
|
52
|
+
} catch (error) {
|
|
53
|
+
// If we can't load runtime config, disable hooks as a safety measure
|
|
54
|
+
console.error('[FuncSpan CommonJS Hook] Failed to load runtime config:', error);
|
|
55
|
+
module.exports = {};
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Lazy-loaded SYNCHRONOUS transformer (CRITICAL FIX)
|
|
60
|
+
let transformFunctionSpansSync = null;
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Load the SYNCHRONOUS transformer module (CRITICAL FIX)
|
|
64
|
+
*/
|
|
65
|
+
function getTransformerSync() {
|
|
66
|
+
if (!transformFunctionSpansSync) {
|
|
67
|
+
try {
|
|
68
|
+
const transformer = require('@sailfish-ai/sf-veritas');
|
|
69
|
+
transformFunctionSpansSync = transformer.transformFunctionSpansSync;
|
|
70
|
+
|
|
71
|
+
if (!transformFunctionSpansSync) {
|
|
72
|
+
throw new Error('transformFunctionSpansSync not found in module');
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// CRITICAL: Set global flag to skip TypeScript plugin
|
|
76
|
+
// tsx has already compiled TS -> JS, so we receive JavaScript code
|
|
77
|
+
if (transformer.setSkipTypeScriptPlugin) {
|
|
78
|
+
transformer.setSkipTypeScriptPlugin(true);
|
|
79
|
+
if (DEBUG) {
|
|
80
|
+
console.log('[FuncSpan CommonJS Hook] Set SKIP_TYPESCRIPT_PLUGIN=true for tsx compatibility');
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if (DEBUG) {
|
|
85
|
+
console.log('[FuncSpan CommonJS Hook] Loaded SYNC transformer successfully');
|
|
86
|
+
}
|
|
87
|
+
} catch (error) {
|
|
88
|
+
console.error('[FuncSpan CommonJS Hook] Failed to load sync transformer:', error);
|
|
89
|
+
// Return a no-op transformer
|
|
90
|
+
transformFunctionSpansSync = (source) => ({ code: source, modified: false, functionsWrapped: 0 });
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
return transformFunctionSpansSync;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Check if a file should be transformed
|
|
98
|
+
*/
|
|
99
|
+
function shouldTransform(filename) {
|
|
100
|
+
// Only process JS/TS files
|
|
101
|
+
const ext = path.extname(filename);
|
|
102
|
+
if (!['.js', '.mjs', '.cjs', '.ts', '.tsx', '.jsx'].includes(ext)) {
|
|
103
|
+
return false;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// Skip sf-veritas library itself to avoid recursion
|
|
107
|
+
// Check for veritas package installation (node_modules)
|
|
108
|
+
const isVeritasInstalled = filename.includes('/@sailfish-ai/sf-veritas/dist/') ||
|
|
109
|
+
filename.includes('\\@sailfish-ai\\sf-veritas\\dist\\');
|
|
110
|
+
|
|
111
|
+
// Check for veritas source (development/monorepo)
|
|
112
|
+
const isVeritasSource = filename.includes('/sailfish/veritas/jsts-backend/src/') ||
|
|
113
|
+
filename.includes('\\sailfish\\veritas\\jsts-backend\\src\\') ||
|
|
114
|
+
filename.includes('/sailfish/veritas/jsts-backend/dist/') ||
|
|
115
|
+
filename.includes('\\sailfish\\veritas\\jsts-backend\\dist\\');
|
|
116
|
+
|
|
117
|
+
if (isVeritasInstalled || isVeritasSource) {
|
|
118
|
+
if (DEBUG) {
|
|
119
|
+
console.log(`[FuncSpan CommonJS Hook] Skipping sf-veritas library: ${filename}`);
|
|
120
|
+
}
|
|
121
|
+
return false;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// Skip node_modules unless explicitly included
|
|
125
|
+
if (filename.includes('node_modules')) {
|
|
126
|
+
const shouldInclude = INCLUDE_NODE_MODULES.some(pkg => filename.includes(`node_modules${path.sep}${pkg}`));
|
|
127
|
+
if (!shouldInclude) {
|
|
128
|
+
if (DEBUG) {
|
|
129
|
+
console.log(`[FuncSpan CommonJS Hook] Skipping node_modules: ${filename}`);
|
|
130
|
+
}
|
|
131
|
+
return false;
|
|
132
|
+
}
|
|
133
|
+
if (DEBUG) {
|
|
134
|
+
console.log(`[FuncSpan CommonJS Hook] Including node_modules package: ${filename}`);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
return true;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Cache for transformed modules
|
|
143
|
+
* Key: filename + hash(content)
|
|
144
|
+
* Value: { hash, code }
|
|
145
|
+
*/
|
|
146
|
+
const transformCache = new Map();
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Create a simple hash of the content
|
|
150
|
+
*/
|
|
151
|
+
function createHash(content) {
|
|
152
|
+
const crypto = require('crypto');
|
|
153
|
+
return crypto.createHash('sha1').update(content).digest('hex');
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Check if code is already instrumented (prevent double-wrapping)
|
|
158
|
+
*/
|
|
159
|
+
function isInstrumented(code) {
|
|
160
|
+
return code.includes('/*__SF_FUNCSPAN_INSTRUMENTED__*/');
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Mark code as instrumented
|
|
165
|
+
*/
|
|
166
|
+
function markInstrumented(code) {
|
|
167
|
+
return '/*__SF_FUNCSPAN_INSTRUMENTED__*/\n' + code;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Hook Module.prototype._compile to intercept compiled JavaScript
|
|
172
|
+
* This is the ONE choke point that receives post-transpile JS from tsx
|
|
173
|
+
*/
|
|
174
|
+
// Module is already required at the top of the file
|
|
175
|
+
const originalCompile = Module.prototype._compile;
|
|
176
|
+
|
|
177
|
+
// Check if already patched
|
|
178
|
+
if (originalCompile.__sf_patched) {
|
|
179
|
+
if (DEBUG) {
|
|
180
|
+
console.log('[FuncSpan CommonJS Hook] _compile already patched');
|
|
181
|
+
}
|
|
182
|
+
} else {
|
|
183
|
+
Module.prototype._compile = function (content, filename) {
|
|
184
|
+
// LITMUS TEST: Log ALL files to see what's going through _compile
|
|
185
|
+
if (DEBUG && filename.includes('/src/')) {
|
|
186
|
+
console.log(`[FuncSpan _compile LITMUS] file: ${filename}, len: ${content.length}`);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
try {
|
|
190
|
+
// Check if we should transform this file
|
|
191
|
+
if (!shouldTransform(filename)) {
|
|
192
|
+
return originalCompile.call(this, content, filename);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// Don't instrument Node internals
|
|
196
|
+
if (filename.startsWith('node:') || filename.includes('node:internal') || filename === '<repl>') {
|
|
197
|
+
return originalCompile.call(this, content, filename);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// Check if already instrumented
|
|
201
|
+
if (isInstrumented(content)) {
|
|
202
|
+
if (DEBUG) {
|
|
203
|
+
console.log(`[FuncSpan CommonJS Hook] Already instrumented: ${filename}`);
|
|
204
|
+
}
|
|
205
|
+
return originalCompile.call(this, content, filename);
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
// Check cache (by filename + content hash)
|
|
209
|
+
const hash = createHash(content);
|
|
210
|
+
const cacheKey = `${filename}:${hash}`;
|
|
211
|
+
const cached = transformCache.get(cacheKey);
|
|
212
|
+
|
|
213
|
+
if (cached) {
|
|
214
|
+
if (DEBUG) {
|
|
215
|
+
console.log(`[FuncSpan CommonJS Hook] Using cached transformation: ${filename}`);
|
|
216
|
+
}
|
|
217
|
+
return originalCompile.call(this, cached, filename);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// Get SYNCHRONOUS transformer
|
|
221
|
+
const transformer = getTransformerSync();
|
|
222
|
+
|
|
223
|
+
if (DEBUG) {
|
|
224
|
+
console.log(`[FuncSpan CommonJS Hook] Transforming: ${filename}`);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
// Transform the JavaScript (content is already JS from tsx)
|
|
228
|
+
// Note: Global flag SKIP_TYPESCRIPT_PLUGIN has been set on transformer initialization
|
|
229
|
+
const result = transformer(content, filename, {
|
|
230
|
+
projectRoot: process.cwd(),
|
|
231
|
+
includeNodeModules: INCLUDE_NODE_MODULES,
|
|
232
|
+
debug: DEBUG,
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
if (result.modified) {
|
|
236
|
+
const instrumented = markInstrumented(result.code);
|
|
237
|
+
|
|
238
|
+
// Cache the instrumented code
|
|
239
|
+
transformCache.set(cacheKey, instrumented);
|
|
240
|
+
|
|
241
|
+
if (DEBUG) {
|
|
242
|
+
console.log(`[FuncSpan CommonJS Hook] ✅ Wrapped ${result.functionsWrapped} functions: ${filename}`);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
// Compile and execute INSTRUMENTED code
|
|
246
|
+
return originalCompile.call(this, instrumented, filename);
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
// No modifications needed
|
|
250
|
+
if (DEBUG) {
|
|
251
|
+
console.log(`[FuncSpan CommonJS Hook] No functions to wrap: ${filename}`);
|
|
252
|
+
}
|
|
253
|
+
return originalCompile.call(this, content, filename);
|
|
254
|
+
|
|
255
|
+
} catch (error) {
|
|
256
|
+
if (DEBUG) {
|
|
257
|
+
console.error(`[FuncSpan CommonJS Hook] Error transforming ${filename}:`, error);
|
|
258
|
+
}
|
|
259
|
+
// Fall back to original on error (graceful degradation)
|
|
260
|
+
return originalCompile.call(this, content, filename);
|
|
261
|
+
}
|
|
262
|
+
};
|
|
263
|
+
|
|
264
|
+
// Mark as patched
|
|
265
|
+
Module.prototype._compile.__sf_patched = true;
|
|
266
|
+
|
|
267
|
+
if (DEBUG) {
|
|
268
|
+
console.log('[FuncSpan CommonJS Hook] Patched Module.prototype._compile for tsx compatibility');
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
if (DEBUG) {
|
|
273
|
+
console.log('[FuncSpan CommonJS Hook] Registered successfully with SYNC transformation');
|
|
274
|
+
console.log('[FuncSpan CommonJS Hook] Functions will be instrumented on FIRST execution');
|
|
275
|
+
console.log('[FuncSpan CommonJS Hook] Usage: SF_FUNCSPAN_RUNTIME_ENABLED=true node -r @sailfish-ai/sf-veritas/runtime/commonjs-hook app.js');
|
|
276
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"use strict";var D=Object.defineProperty;var M=(I,g,C)=>g in I?D(I,g,{enumerable:!0,configurable:!0,writable:!0,value:C}):I[g]=C;var y=(I,g,C)=>M(I,typeof g!="symbol"?g+"":g,C);const P=require("fs"),_=require("./source-map-rHHEdpre.cjs"),q=require("worker_threads"),d=require("./contextManager-CGINtRN5.cjs"),$=require("path"),z={};class J{constructor({file:g,line:C,function:c,code:A,locals:i={},offender:n=!1,column:l}){y(this,"file");y(this,"line");y(this,"function");y(this,"code");y(this,"locals");y(this,"offender");y(this,"column");this.file=g,this.line=C,this.function=c,this.code=A,this.locals=i,this.offender=n,this.column=l}toDict(){const g={file:this.file,line:this.line,function:this.function,code:this.code,locals:Object.fromEntries(Object.entries(this.locals).map(([C,c])=>[C,String(c)]))};return this.offender&&(g.offender=this.offender),this.column!==void 0&&(g.column=this.column),g}toJson(){return JSON.stringify(this.toDict())}}class v{static encode(g){return g instanceof J?g.toDict():Array.isArray(g)?g.map(C=>v.encode(C)):typeof g=="object"&&g!==null?JSON.stringify(g):g}static stringify(g){return JSON.stringify(v.encode(g),(C,c)=>c instanceof J?c.toDict():c)}}const gg=["/sf-veritas/","/@sailfish-ai/","/node_modules/","/dist/","/<","/internal/","node:"],p=new Map;function Ig(I){return gg.some(g=>I.includes(g))}function Cg(I){let g=I;g.startsWith("file://")&&(g=g.substring(7)),process.platform==="win32"&&g.startsWith("/")&&g.length>2&&g[2]===":"&&(g=g.substring(1));try{return $.resolve(g)}catch{return I}}function cg(I=0){const g=new Error().stack;if(!g)return[null,null];const C=(function(l,e){const o=2+e;return l.split(`
|
|
2
|
+
`).slice(o,o+5).join(`
|
|
3
|
+
`)})(g,I),c=p.get(C);if(c)return c;const A=(function(l){if(!l)return[];const e=l.split(`
|
|
4
|
+
`).slice(1),o=[];for(const t of e){let Z=/at\s+(.+?)\s+\((.+?):(\d+):(\d+)\)/.exec(t);Z?o.push({functionName:Z[1],file:Z[2],line:parseInt(Z[3],10),column:parseInt(Z[4],10)}):(Z=/at\s+(.+?):(\d+):(\d+)/.exec(t),Z&&o.push({functionName:"<anonymous>",file:Z[1],line:parseInt(Z[2],10),column:parseInt(Z[3],10)}))}return o})(g),i=1+I;for(let l=i;l<Math.min(A.length,i+10);l++){const e=A[l];if(!e||!e.file||Ig(e.file))continue;const o=[Cg(e.file),e.line];if(p.size>=512){const t=p.keys().next().value;t!==void 0&&p.delete(t)}return p.set(C,o),o}const n=[null,null];return p.set(C,n),n}const S=console.log.bind(console),F=console.error.bind(console),R=console.warn.bind(console),k=console.info.bind(console),L=console.debug.bind(console),W=S,K=F;let B=!1,V,N=0;function x(I){return I=(I=(I=I.replace(/^webpack:\/\/[^\/]+\/\.?\//,"")).replace(/^.*\/pages\//,"pages/")).replace(/\.(js|ts)$/,"")}function lg(I,g,C){const c=(function(i){i.startsWith("at ")&&(i=i.slice(3).trim());const n=i.match(/^(.*?)(:\d+)+(\.map)?$/);return n?n[1]:i})(I);if(!c||c==="<unknown>")return null;const A=c+".map";try{const i=P.readFileSync(A,"utf-8");if(i){const n=JSON.parse(i);let l=new _.sourceMapExports.SourceMapConsumer(n).originalPositionFor({line:g,column:C});if(c&&l.source){const e=x(c),o=n.sources.findIndex(t=>x(t)===e);if(o===-1)d.getConfig().sfDebug&&W(`Source file "${c}" not found in the source map.`);else{const t=n.sourcesContent[o],Z=n.names.join(",");if(t)return{content:t.split(`
|
|
5
|
+
`).slice(l.line-1,l.line+20).join(`
|
|
6
|
+
`),name:Z,file:l.source};d.getConfig().sfDebug&&W(`No source content available for file "${c}".`)}}return{content:n.sourcesContent[0],name:n.names[0],file:n.file}}}catch(i){d.getConfig().sfDebug&&W(`Cant read/parse "${A}: Error - ".`,i)}return null}function ng(I){return I?.split("/").pop()||"<unknown>"}function T(I,g){if(!I||typeof I!="object")return!1;for(const C of Object.values(I))if(typeof C=="string"&&C.includes(g)||typeof C=="object"&&T(C,g))return!0;return!1}let X,H,U=!1;function Q(I){if(!I)return;const g=I.toLowerCase().trim();return!!["1","true","yes","on"].includes(g)||!["0","false","no","off"].includes(g)&&void 0}function O(){if(V!==void 0)return V;const I=process.env||{},g=Q(I.SF_IS_LOCAL);if(g!==void 0)return V=g;const C=(I.SF_ENV||I.NODE_ENV||"").toLowerCase();if(["local","dev","development"].includes(C))return V=!0;if(["KUBERNETES_SERVICE_HOST","AWS_EXECUTION_ENV","ECS_CONTAINER_METADATA_URI","ECS_CONTAINER_METADATA_URI_V4","GAE_ENV","K_SERVICE","GOOGLE_CLOUD_PROJECT","WEBSITE_INSTANCE_ID","VERCEL","NETLIFY","DYNO","RENDER","FLY_APP_NAME","RAILWAY_STATIC_URL","CF_PAGES","CLOUDFLARE"].some(A=>!!I[A]))return V=!1;const c=(z.hostname?.()||I.HOSTNAME||"").toLowerCase();return V=!(c!=="localhost"&&!c.endsWith(".local")&&!c.includes("local"))}function f(I,g,C){return new Promise(c=>{try{const A=new URL(I),i=(A.protocol,z).request({method:"GET",hostname:A.hostname,port:A.port||(A.protocol==="https:"?443:80),path:A.pathname+(A.search||""),headers:g},n=>{n.resume(),n.statusCode&&n.statusCode>=200&&n.statusCode<400?c("ok"):c("http_error")});i.on("error",()=>c("error")),i.setTimeout(C,()=>{i.destroy(),c("timeout")}),i.end()}catch{c("error")}})}function E(){if(X!==void 0)return X;const I=process.env.SF_FUNCSPAN_RUNTIME_ENABLED;if(I==="true"||I==="1")return X=!0,!0;if(I==="false"||I==="0")return X=!1,!1;try{const{isRuntimeModeConfigured:g}=require("../funcSpanConfigLoader");if(g&&g())return X=!0,!0}catch{}return X=!1,!1}function j(){return H!==void 0||(H=!O()),H}exports.CustomJSONEncoderForFrameInfo=v,exports.https=z,exports.initializeExceptionInterceptor=function(I){d.getConfig().sfDebug&&W("Initializing Exception Interceptor...");try{const l=O();I?.setSupplementalFields?.({isFromLocalService:l}),(async function(e){if(U)return;U=!0;const o=process.env||{};if(Q(o.SF_IS_LOCAL)===void 0)try{await(async function(t){const Z=f("http://169.254.169.254/latest/meta-data/",{},t),h=f("http://metadata.google.internal/computeMetadata/v1/instance/",{"Metadata-Flavor":"Google"},t),m=f("http://169.254.169.254/metadata/instance?api-version=2021-02-01",{Metadata:"true"},t);return(await Promise.allSettled([Z,h,m])).some(s=>s.status==="fulfilled"&&(s.value==="ok"||s.value==="http_error"))})(150)&&V&&(V=!1,e?.setSupplementalFields?.({isFromLocalService:!1}))}catch{}})(I).catch(()=>{})}catch{}const g=new q.Worker(new URL("data:application/javascript;base64,aW1wb3J0IHsgU2Vzc2lvbiB9IGZyb20gImluc3BlY3Rvci9wcm9taXNlcyI7CmltcG9ydCB7IHBhcmVudFBvcnQsIHdvcmtlckRhdGEgfSBmcm9tICJ3b3JrZXJfdGhyZWFkcyI7CgpnbG9iYWwuc2ZEZWJ1ZyA9IHVuZGVmaW5lZDsKZ2xvYmFsLnN0YWNrRGVwdGhMb2NhbHMgPSB1bmRlZmluZWQ7Cmdsb2JhbC5ub2RlTW9kdWxlc1RvQ29sbGVjdExvY2FsVmFyaWFibGVzT24gPSB1bmRlZmluZWQ7CgovKioKICogUHJvY2Vzc2VzIGNhbGwgZnJhbWVzIGZyb20gYW4gZXhjZXB0aW9uIGFuZCBwb3N0cyB0aGVtIHZpYSB0aGUgV29ya2Vy4oCZcyBwYXJlbnRQb3J0LgogKgogKiBAcGFyYW0gc2Vzc2lvbiAtIFRoZSBEZXZUb29scyBzZXNzaW9uIG9yIHNpbWlsYXIgb2JqZWN0IHlvdSB1c2UgdG8gcXVlcnkgZm9yIHNjcmlwdCBzb3VyY2VzLgogKiBAcGFyYW0gY2FsbEZyYW1lcyAtIEFuIGFycmF5IG9mIGNhbGwgZnJhbWUgb2JqZWN0cy4KICogQHBhcmFtIGRlc2NyaXB0aW9uTGluZXMgLSBBbiBhcnJheSBvZiBsaW5lcyBmcm9tIHRoZSBlcnJvcuKAmXMgZGVzY3JpcHRpb24sIGVhY2ggdHlwaWNhbGx5IGJlZ2lubmluZyB3aXRoICJhdCAiLgogKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn0KICovCmV4cG9ydCBhc3luYyBmdW5jdGlvbiBwcm9jZXNzQ2FsbEZyYW1lcyhzZXNzaW9uLCBjYWxsRnJhbWVzLCBkZXNjcmlwdGlvbkxpbmVzKSB7CiAgLyoqCiAgICogTGltaXQgdGhlIGNhbGwgZnJhbWVzIHRvIHRoZSBtYXhpbXVtIGRlcHRoIHNwZWNpZmllZCBieSBnbG9iYWwuc3RhY2tEZXB0aExvY2Fscy4KICAgKiBUaGlzIGFzc3VtZXMgdGhhdCBnbG9iYWwuc3RhY2tEZXB0aExvY2FscyBpcyBkZWZpbmVkIGFzIGEgbnVtYmVyLgogICAqLwogIGNvbnN0IGxpbWl0ZWRDYWxsRnJhbWVzID0gY2FsbEZyYW1lcy5zbGljZSgwLCBnbG9iYWwuc3RhY2tEZXB0aExvY2Fscyk7CgogIGNvbnN0IGZyYW1lcyA9IGF3YWl0IFByb21pc2UuYWxsKAogICAgbGltaXRlZENhbGxGcmFtZXMubWFwKGFzeW5jIChmcmFtZSwgaW5kZXgpID0+IHsKICAgICAgdHJ5IHsKICAgICAgICBjb25zdCB7IGZ1bmN0aW9uTmFtZSwgbG9jYXRpb24sIHVybCwgc2NvcGVDaGFpbiB9ID0gZnJhbWU7CiAgICAgICAgLy8gRmluZCB0aGUgbG9jYWwgc2NvcGUsIGlmIGFueQogICAgICAgIGNvbnN0IGxvY2FsU2NvcGUgPSBzY29wZUNoYWluLmZpbmQoKHNjb3BlKSA9PiBzY29wZS50eXBlID09PSAibG9jYWwiKTsKCiAgICAgICAgbGV0IGNvZGUgPSAiPG5vdCBjYXB0dXJlZD4iOwogICAgICAgIC8vIFVzZSBlaXRoZXIgdGhlIFVSTCBvciB0aGUgZGVzY3JpcHRpb24gbGluZSBmb3IgZmlsZSByZWZlcmVuY2UKICAgICAgICBsZXQgZmlsZSA9ICIiOwogICAgICAgIGlmICh1cmwgJiYgdXJsLnRyaW0oKSAhPT0gIiIpIHsKICAgICAgICAgIGZpbGUgPSB1cmw7CiAgICAgICAgfSBlbHNlIGlmIChkZXNjcmlwdGlvbkxpbmVzW2luZGV4XSkgewogICAgICAgICAgZmlsZSA9IGRlc2NyaXB0aW9uTGluZXNbaW5kZXhdLnRyaW0oKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgZmlsZSA9ICI8dW5rbm93bj4iOwogICAgICAgIH0KCiAgICAgICAgLy8gSWYgd2UgaGF2ZSBhIHZhbGlkIGxvY2F0aW9uIGFuZCBzY3JpcHRJZCwgZmV0Y2ggdGhlIGNvZGUgbGluZQogICAgICAgIGlmIChsb2NhdGlvbiAmJiBsb2NhdGlvbi5zY3JpcHRJZCkgewogICAgICAgICAgY29uc3Qgc2NyaXB0SWQgPSBsb2NhdGlvbi5zY3JpcHRJZDsKICAgICAgICAgIHRyeSB7CiAgICAgICAgICAgIGNvbnN0IHsgc2NyaXB0U291cmNlIH0gPSBhd2FpdCBzZXNzaW9uLnBvc3QoCiAgICAgICAgICAgICAgIkRlYnVnZ2VyLmdldFNjcmlwdFNvdXJjZSIsCiAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgc2NyaXB0SWQsCiAgICAgICAgICAgICAgfSwKICAgICAgICAgICAgKTsKICAgICAgICAgICAgY29uc3Qgc291cmNlTGluZXMgPSBzY3JpcHRTb3VyY2Uuc3BsaXQoIlxuIik7CiAgICAgICAgICAgIGNvZGUgPSBzb3VyY2VMaW5lc1tsb2NhdGlvbi5saW5lTnVtYmVyXSB8fCAiPG5vdCBjYXB0dXJlZD4iOwogICAgICAgICAgfSBjYXRjaCAoZXJyKSB7CiAgICAgICAgICAgIGlmIChnbG9iYWwuc2ZEZWJ1ZykgewogICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoIltXb3JrZXJdIEZhaWxlZCB0byBmZXRjaCBzY3JpcHQgc291cmNlOiIsIGVycik7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICB9CgogICAgICAgIC8vIEZldGNoIGxvY2FsIHZhcmlhYmxlcyBpZiB0aGVyZSdzIGFuIG9iamVjdElkCiAgICAgICAgY29uc3QgbG9jYWxzID0gbG9jYWxTY29wZT8ub2JqZWN0Py5vYmplY3RJZAogICAgICAgICAgPyBhd2FpdCBmZXRjaExvY2FsVmFyaWFibGVzKHNlc3Npb24sIGxvY2FsU2NvcGUub2JqZWN0Lm9iamVjdElkKQogICAgICAgICAgOiB7fTsKCiAgICAgICAgcmV0dXJuIHsKICAgICAgICAgIGZ1bmN0aW9uOiBmdW5jdGlvbk5hbWUgfHwgIjxhbm9ueW1vdXM+IiwKICAgICAgICAgIGxvY2FscywKICAgICAgICAgIGZpbGUsCiAgICAgICAgICBsaW5lOiBsb2NhdGlvbj8ubGluZU51bWJlciB8fCAwLAogICAgICAgICAgY29kZSwKICAgICAgICB9OwogICAgICB9IGNhdGNoIChlcnJvcikgewogICAgICAgIGlmIChnbG9iYWwuc2ZEZWJ1ZykgewogICAgICAgICAgY29uc29sZS5lcnJvcigiW1dvcmtlcl0gRXJyb3IgcHJvY2Vzc2luZyBjYWxsIGZyYW1lOiIsIGVycm9yKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHsKICAgICAgICAgIGZ1bmN0aW9uOiAiPGVycm9yPiIsCiAgICAgICAgICBsb2NhbHM6IHt9LAogICAgICAgICAgZmlsZTogIjx1bmtub3duPiIsCiAgICAgICAgICBsaW5lOiAwLAogICAgICAgICAgY29kZTogIjxub3QgY2FwdHVyZWQ+IiwKICAgICAgICB9OwogICAgICB9CiAgICB9KSwKICApOwogIC8vIFBvc3QgZXhjZXB0aW9uIGRhdGEKICBwYXJlbnRQb3J0Py5wb3N0TWVzc2FnZSh7IHR5cGU6ICJleGNlcHRpb24iLCBmcmFtZXMgfSk7Cn0KCi8qKgogKiBIYW5kbGVzIHRoZSAicGF1c2VkIiBzdGF0ZSBvZiB0aGUgZGVidWdnZXIgYW5kIHByb2Nlc3NlcyBleGNlcHRpb25zIG9yIHByb21pc2UgcmVqZWN0aW9ucy4KICogQHBhcmFtIHtTZXNzaW9ufSBzZXNzaW9uIC0gVGhlIGRlYnVnZ2luZyBzZXNzaW9uIGluc3RhbmNlLgogKiBAcGFyYW0ge29iamVjdH0gcGFyYW1zIC0gUGFyYW1ldGVycyBmcm9tIHRoZSAicGF1c2VkIiBldmVudC4KICovCmFzeW5jIGZ1bmN0aW9uIGhhbmRsZVBhdXNlZChzZXNzaW9uLCBwYXJhbXMpIHsKICBjb25zdCB7IHJlYXNvbiwgZGF0YSwgY2FsbEZyYW1lcyB9ID0gcGFyYW1zOwoKICBpZiAocmVhc29uICE9PSAiZXhjZXB0aW9uIiAmJiByZWFzb24gIT09ICJwcm9taXNlUmVqZWN0aW9uIikgewogICAgcmV0dXJuOwogIH0KCiAgLy8gRGVmaW5lIHJlZ2V4IHBhdHRlcm5zIHRvIGlkZW50aWZ5IG5vbi1hcHBsaWNhdGlvbiBzb3VyY2UgZXJyb3JzLgogIGNvbnN0IG5vbkFwcFBhdHRlcm5zID0gWwogICAgL25vZGU6aW50ZXJuYWwvLAogICAgL2ludGVybmFsXC8vLAogICAgL25vZGVfbW9kdWxlcy8sCiAgICAvbm9kZTpmcy8sCiAgXTsKCiAgbGV0IGZpcnN0RnJhbWVMaW5lID0gIiI7CiAgbGV0IGRlc2NyaXB0aW9uTGluZXMgPSBbXTsKCiAgaWYgKGRhdGEgJiYgdHlwZW9mIGRhdGEuZGVzY3JpcHRpb24gPT09ICJzdHJpbmciKSB7CiAgICAvLyBTcGxpdCB0aGUgZGVzY3JpcHRpb24gaW50byBsaW5lcyBhbmQgZmlsdGVyIHRvIGtlZXAgb25seSBsaW5lcyB0aGF0IHN0YXJ0IHdpdGggImF0ICIKICAgIGRlc2NyaXB0aW9uTGluZXMgPSBkYXRhLmRlc2NyaXB0aW9uCiAgICAgIC5zcGxpdCgiXG4iKQogICAgICAuZmlsdGVyKChsaW5lKSA9PiBsaW5lLnRyaW0oKS5zdGFydHNXaXRoKCJhdCAiKSk7CgogICAgLy8gVXNlIHRoZSBmaXJzdCBjYWxsIGZyYW1lIGxpbmUgZnJvbSB0aGUgZGVzY3JpcHRpb24gZm9yIGZpbHRlcmluZy4KICAgIGZpcnN0RnJhbWVMaW5lID0gZGVzY3JpcHRpb25MaW5lc1swXSB8fCAiIjsKICAgIGlmICghZmlyc3RGcmFtZUxpbmUpIHsKICAgICAgLy8gSWYsIGZvciBzb21lIHJlYXNvbiwgdGhlcmUncyBubyBmcmFtZSwgYmFpbCBvdXQKICAgICAgcmV0dXJuOwogICAgfQoKICAgIC8vIENoZWNrIGlmIHRoaXMgaXMgYSAibm9uLWFwcCIgZXJyb3IKICAgIGNvbnN0IGVycm9yRnJvbU5vbkFwcCA9IG5vbkFwcFBhdHRlcm5zLnNvbWUoKHBhdHRlcm4pID0+CiAgICAgIHBhdHRlcm4udGVzdChmaXJzdEZyYW1lTGluZS50cmltKCkpLAogICAgKTsKCiAgICAvLyBDb252ZXJ0IGBnbG9iYWwubm9kZU1vZHVsZXNUb0NvbGxlY3RMb2NhbFZhcmlhYmxlc09uYCB0byBhbiBhcnJheSBmb3Igc2FmZXR5CiAgICBjb25zdCBub2RlTW9kdWxlc0xpc3QgPSBBcnJheS5pc0FycmF5KAogICAgICBnbG9iYWwubm9kZU1vZHVsZXNUb0NvbGxlY3RMb2NhbFZhcmlhYmxlc09uLAogICAgKQogICAgICA/IGdsb2JhbC5ub2RlTW9kdWxlc1RvQ29sbGVjdExvY2FsVmFyaWFibGVzT24KICAgICAgOiBbXTsKICAgIGlmIChlcnJvckZyb21Ob25BcHApIHsKICAgICAgLy8gSWYgdGhlIGVycm9yIGlzIGZyb20gYSBub24tYXBwIHNvdXJjZSwgd2UgaGF2ZSBhIGZldyBzY2VuYXJpb3M6CiAgICAgIGlmIChub2RlTW9kdWxlc0xpc3QuaW5jbHVkZXMoIl9fYWxsX18iKSkgewogICAgICAgIC8vIElmIHRoZSBsaXN0IGluY2x1ZGVzIF9fYWxsX18sIGNhcHR1cmUgbG9jYWwgdmFyaWFibGVzIGZyb20gKmFsbCogbm9kZV9tb2R1bGVzCiAgICAgICAgaWYgKGdsb2JhbC5zZkRlYnVnKSB7CiAgICAgICAgICBjb25zb2xlLmxvZygKICAgICAgICAgICAgIltXb3JrZXJdIEVycm9yIGlzIGZyb20gbm9uLWFwcCBzb3VyY2UsIGJ1dCBjYXB0dXJpbmcgZHVlIHRvIF9fYWxsX18gcnVsZS4iLAogICAgICAgICAgKTsKICAgICAgICB9CiAgICAgICAgLy8gQ29udGludWUgKGRvIE5PVCByZXR1cm4pLi4uCiAgICAgIH0gZWxzZSBpZiAobm9kZU1vZHVsZXNMaXN0Lmxlbmd0aCA+IDApIHsKICAgICAgICAvLyBDaGVjayBpZiB0aGUgZmlyc3QgZnJhbWUgcmVmZXJlbmNlcyBvbmUgb2YgdGhlIG1vZHVsZXMgd2UgYWxsb3cgY2FwdHVyaW5nIGZyb20KICAgICAgICBjb25zdCBpc0Zyb21BbGxvd2VkTm9kZU1vZHVsZSA9IG5vZGVNb2R1bGVzTGlzdC5zb21lKChtb2R1bGVOYW1lKSA9PgogICAgICAgICAgZmlyc3RGcmFtZUxpbmUuaW5jbHVkZXMoYCR7bW9kdWxlTmFtZX1gKSwKICAgICAgICApOwoKICAgICAgICBpZiAoIWlzRnJvbUFsbG93ZWROb2RlTW9kdWxlKSB7CiAgICAgICAgICAvLyBOb3QgZnJvbSBhbiBhbGxvd2VkIG5vZGUgbW9kdWxlID0+IHJldHVybiBlYXJseQogICAgICAgICAgaWYgKGdsb2JhbC5zZkRlYnVnKSB7CiAgICAgICAgICAgIGNvbnNvbGUubG9nKAogICAgICAgICAgICAgICJbV29ya2VyXSBFcnJvciBhcHBlYXJzIHRvIGJlIHRyaWdnZXJlZCBmcm9tIG5vbi1hcHBsaWNhdGlvbiBzb3VyY2VzOyBpZ25vcmluZy4iLAogICAgICAgICAgICApOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuOwogICAgICAgIH0KICAgICAgICAvLyBPdGhlcndpc2UsIGl0J3MgZnJvbSBhbiBhbGxvd2VkIG5vZGUgbW9kdWxlLCBzbyBjb250aW51ZQogICAgICB9IGVsc2UgewogICAgICAgIC8vIElmIHRoZSBsaXN0IGlzIGVtcHR5LCBwcmVzZXJ2ZSBleGlzdGluZyBiZWhhdmlvciBhbmQgaWdub3JlIG5vbi1hcHBsaWNhdGlvbiBlcnJvcnMKICAgICAgICBpZiAoZ2xvYmFsLnNmRGVidWcpIHsKICAgICAgICAgIGNvbnNvbGUubG9nKAogICAgICAgICAgICAiW1dvcmtlcl0gRXJyb3IgYXBwZWFycyB0byBiZSB0cmlnZ2VyZWQgZnJvbSBub24tYXBwbGljYXRpb24gc291cmNlczsgaWdub3JpbmcuIiwKICAgICAgICAgICk7CiAgICAgICAgfQogICAgICAgIHJldHVybjsKICAgICAgfQogICAgfQoKICAgIC8vIElmIHdlIHJlYWNoIHRoaXMgcG9pbnQsIHRoZSBlcnJvciBpcyBlaXRoZXIgZnJvbSBhcHAgY29kZSwgb3IgZnJvbSBhIG5vZGUgbW9kdWxlIGFsbG93ZWQgYnkgdGhlIGxpc3QKICAgIC8vID0+IFByb2NlZWQgd2l0aCBjYXB0dXJpbmcgbG9jYWwgdmFyaWFibGVzLCBldGMuCiAgICBhd2FpdCBwcm9jZXNzQ2FsbEZyYW1lcyhzZXNzaW9uLCBjYWxsRnJhbWVzLCBkZXNjcmlwdGlvbkxpbmVzKTsKICB9IGVsc2UgewogICAgLy8gSWYgdGhlcmUgaXMgbm8gZGF0YS5kZXNjcmlwdGlvbiBvciBpdCdzIG5vdCBhIHN0cmluZywganVzdCByZXR1cm4KICAgIHJldHVybjsKICB9Cn0KCi8qKgogKiBJbml0aWFsaXplcyB0aGUgZGVidWdnZXIgYW5kIHNldHMgdXAgZXZlbnQgbGlzdGVuZXJzIGZvciBleGNlcHRpb25zIGFuZCBwcm9taXNlIHJlamVjdGlvbnMuCiAqLwphc3luYyBmdW5jdGlvbiBzdGFydERlYnVnZ2VyKCkgewogIHBhcmVudFBvcnQ/LnBvc3RNZXNzYWdlKHsgdHlwZTogIm1lc3NhZ2UiLCByZWFkeVRvR2V0UGFyYW1ldGVyczogdHJ1ZSB9KTsKCiAgbGV0IHJlc29sdmVNZXNzYWdlUHJvbWlzZTsKICBjb25zdCBtZXNzYWdlUHJvbWlzZSA9IG5ldyBQcm9taXNlKChyZXNvbHZlKSA9PiB7CiAgICByZXNvbHZlTWVzc2FnZVByb21pc2UgPSByZXNvbHZlOwogIH0pOwogIGxldCBpc1BhdXNlZCA9IGZhbHNlOwoKICBwYXJlbnRQb3J0Py5vbigibWVzc2FnZSIsIChtZXNzYWdlKSA9PiB7CiAgICB0cnkgewogICAgICBpZiAobWVzc2FnZT8udHlwZSA9PT0gInByb2Nlc3NFeGNlcHRpb24iKSB7CiAgICAgICAgcmV0dXJuOwogICAgICB9CgogICAgICBpZiAoCiAgICAgICAgbWVzc2FnZT8uc2ZEZWJ1ZyAhPT0gdW5kZWZpbmVkICYmCiAgICAgICAgbWVzc2FnZT8uc3RhY2tEZXB0aExvY2FscyAhPT0gdW5kZWZpbmVkCiAgICAgICkgewogICAgICAgIGlmIChnbG9iYWwuc2ZEZWJ1ZykgewogICAgICAgICAgY29uc29sZS5sb2coIlVwZGF0aW5nIGdsb2JhbCBkZWJ1ZyB2YXJpYWJsZXMuLi4iKTsKICAgICAgICB9CgogICAgICAgIGdsb2JhbC5zZkRlYnVnID0gbWVzc2FnZS5zZkRlYnVnOwogICAgICAgIGdsb2JhbC5zdGFja0RlcHRoTG9jYWxzID0gbWVzc2FnZS5zdGFja0RlcHRoTG9jYWxzOwogICAgICAgIGdsb2JhbC5ub2RlTW9kdWxlc1RvQ29sbGVjdExvY2FsVmFyaWFibGVzT24gPQogICAgICAgICAgbWVzc2FnZS5ub2RlTW9kdWxlc1RvQ29sbGVjdExvY2FsVmFyaWFibGVzT247CgogICAgICAgIHJlc29sdmVNZXNzYWdlUHJvbWlzZSgpOwogICAgICB9CiAgICB9IGNhdGNoIChlcnJvcikgewogICAgICBpZiAoZ2xvYmFsLnNmRGVidWcpIHsKICAgICAgICBjb25zb2xlLmVycm9yKCLinYwgRXJyb3IgaW4gbWVzc2FnZSBoYW5kbGluZzoiLCBlcnJvcik7CiAgICAgIH0KICAgIH0KICB9KTsKCiAgYXdhaXQgbWVzc2FnZVByb21pc2U7CgogIHRyeSB7CiAgICBjb25zdCBzZXNzaW9uID0gbmV3IFNlc3Npb24oKTsKICAgIHNlc3Npb24uY29ubmVjdFRvTWFpblRocmVhZCgpOwoKICAgIHNlc3Npb24ub24oIkRlYnVnZ2VyLnJlc3VtZWQiLCAoKSA9PiB7CiAgICAgIGlzUGF1c2VkID0gZmFsc2U7CiAgICB9KTsKCiAgICBzZXNzaW9uLm9uKCJEZWJ1Z2dlci5wYXVzZWQiLCBhc3luYyAoZXZlbnQpID0+IHsKICAgICAgaXNQYXVzZWQgPSB0cnVlOwogICAgICBoYW5kbGVQYXVzZWQoc2Vzc2lvbiwgZXZlbnQucGFyYW1zKS50aGVuKAogICAgICAgIGFzeW5jICgpID0+IHsKICAgICAgICAgIC8vIEFmdGVyIHRoZSBwYXVzZSB3b3JrIGlzIGNvbXBsZXRlLCByZXN1bWUgZXhlY3V0aW9uIQogICAgICAgICAgaWYgKGlzUGF1c2VkKSB7CiAgICAgICAgICAgIGF3YWl0IHNlc3Npb24ucG9zdCgiRGVidWdnZXIucmVzdW1lIik7CiAgICAgICAgICB9CiAgICAgICAgfSwKICAgICAgICBhc3luYyAoXykgPT4gewogICAgICAgICAgaWYgKGlzUGF1c2VkKSB7CiAgICAgICAgICAgIGF3YWl0IHNlc3Npb24ucG9zdCgiRGVidWdnZXIucmVzdW1lIik7CiAgICAgICAgICB9CiAgICAgICAgfSwKICAgICAgKTsKICAgIH0pOwoKICAgIGF3YWl0IHNlc3Npb24ucG9zdCgiRGVidWdnZXIuZW5hYmxlIik7CgogICAgY29uc3QgY2FwdHVyZUFsbCA9IHdvcmtlckRhdGEuY2FwdHVyZUFsbEV4Y2VwdGlvbnMgIT09IGZhbHNlOwogICAgYXdhaXQgc2Vzc2lvbi5wb3N0KCJEZWJ1Z2dlci5zZXRQYXVzZU9uRXhjZXB0aW9ucyIsIHsKICAgICAgc3RhdGU6IGNhcHR1cmVBbGwgPyAiYWxsIiA6ICJ1bmNhdWdodCIsCiAgICB9KTsKICB9IGNhdGNoIChlcnJvcikgewogICAgaWYgKGdsb2JhbC5zZkRlYnVnKSB7CiAgICAgIGNvbnNvbGUuZXJyb3IoIltXb3JrZXJdIGVycm9yICIsIGVycm9yKTsKICAgIH0KICB9CgogIGlmIChnbG9iYWwuc2ZEZWJ1ZykgewogICAgY29uc29sZS5sb2coIltXb3JrZXJdIERlYnVnZ2VyIHN0YXJ0ZWQgc3VjY2Vzc2Z1bGx5LiIpOwogIH0KfQoKYXN5bmMgZnVuY3Rpb24gdW5yb2xsT2JqZWN0KHNlc3Npb24sIG9iamVjdElkLCBuYW1lLCB2YXJzKSB7CiAgY29uc3QgcHJvcGVydGllcyA9IGF3YWl0IHNlc3Npb24ucG9zdCgiUnVudGltZS5nZXRQcm9wZXJ0aWVzIiwgewogICAgb2JqZWN0SWQsCiAgICBvd25Qcm9wZXJ0aWVzOiB0cnVlLAogIH0pOwoKICB2YXJzW25hbWVdID0gcHJvcGVydGllcy5yZXN1bHQKICAgIC5tYXAoKHYpID0+IFt2Lm5hbWUsIHYudmFsdWU/LnZhbHVlXSkKICAgIC5yZWR1Y2UoKG9iaiwgW2tleSwgdmFsXSkgPT4gewogICAgICBvYmpba2V5XSA9IHZhbDsKICAgICAgcmV0dXJuIG9iajsKICAgIH0sIHt9KTsKfQoKYXN5bmMgZnVuY3Rpb24gdW5yb2xsQXJyYXkoc2Vzc2lvbiwgb2JqZWN0SWQsIG5hbWUsIHZhcnMpIHsKICBjb25zdCBwcm9wZXJ0aWVzID0gYXdhaXQgc2Vzc2lvbi5wb3N0KCJSdW50aW1lLmdldFByb3BlcnRpZXMiLCB7CiAgICBvYmplY3RJZDogb2JqZWN0SWQsCiAgICBvd25Qcm9wZXJ0aWVzOiB0cnVlLAogIH0pOwogIHZhcnNbbmFtZV0gPSBwcm9wZXJ0aWVzLnJlc3VsdAogICAgLmZpbHRlcigodikgPT4gdi5uYW1lICE9PSAibGVuZ3RoIiAmJiAhaXNOYU4ocGFyc2VJbnQodi5uYW1lLCAxMCkpKQogICAgLnNvcnQoKGEsIGIpID0+IHBhcnNlSW50KGEubmFtZSwgMTApIC0gcGFyc2VJbnQoYi5uYW1lLCAxMCkpCiAgICAubWFwKCh2KSA9PiB2LnZhbHVlPy52YWx1ZSk7Cn0KCmZ1bmN0aW9uIHVucm9sbE90aGVyKHByb3AsIHZhcnMpIHsKICBpZiAoIXByb3AudmFsdWUpIHsKICAgIHJldHVybjsKICB9CgogIGlmICgidmFsdWUiIGluIHByb3AudmFsdWUpIHsKICAgIGlmIChwcm9wLnZhbHVlLnZhbHVlID09PSB1bmRlZmluZWQgfHwgcHJvcC52YWx1ZS52YWx1ZSA9PT0gbnVsbCkgewogICAgICB2YXJzW3Byb3AubmFtZV0gPSBgPCR7cHJvcC52YWx1ZS52YWx1ZX0+YDsKICAgICAgcmV0dXJuOwogICAgfQoKICAgIHZhcnNbcHJvcC5uYW1lXSA9IHByb3AudmFsdWUudmFsdWU7CiAgICByZXR1cm47CiAgfQoKICBpZiAoImRlc2NyaXB0aW9uIiBpbiBwcm9wLnZhbHVlICYmIHByb3AudmFsdWUudHlwZSAhPT0gImZ1bmN0aW9uIikgewogICAgdmFyc1twcm9wLm5hbWVdID0gYDwke3Byb3AudmFsdWUuZGVzY3JpcHRpb259PmA7CiAgICByZXR1cm47CiAgfQoKICBpZiAocHJvcC52YWx1ZS50eXBlID09PSAidW5kZWZpbmVkIikgewogICAgdmFyc1twcm9wLm5hbWVdID0gIjx1bmRlZmluZWQ+IjsKICAgIHJldHVybjsKICB9Cn0KCi8qKgogKiBGZXRjaGVzIGxvY2FsIHZhcmlhYmxlcyBmcm9tIHRoZSBnaXZlbiBvYmplY3QgSUQuCiAqIEBwYXJhbSB7U2Vzc2lvbn0gc2Vzc2lvbiAtIFRoZSBkZWJ1Z2dpbmcgc2Vzc2lvbiBpbnN0YW5jZS4KICogQHBhcmFtIHtzdHJpbmd9IG9iamVjdElkIC0gVGhlIG9iamVjdCBJRCByZXByZXNlbnRpbmcgdGhlIGxvY2FsIHNjb3BlLgogKiBAcmV0dXJucyB7b2JqZWN0fSBBIGtleS12YWx1ZSBtYXAgb2YgbG9jYWwgdmFyaWFibGUgbmFtZXMgYW5kIHRoZWlyIHZhbHVlcy4KICovCmFzeW5jIGZ1bmN0aW9uIGZldGNoTG9jYWxWYXJpYWJsZXMoc2Vzc2lvbiwgb2JqZWN0SWQpIHsKICBpZiAoIW9iamVjdElkKSByZXR1cm4ge307CgogIHRyeSB7CiAgICBjb25zdCB7IHJlc3VsdCB9ID0gYXdhaXQgc2Vzc2lvbi5wb3N0KCJSdW50aW1lLmdldFByb3BlcnRpZXMiLCB7CiAgICAgIG9iamVjdElkLAogICAgICBvd25Qcm9wZXJ0aWVzOiB0cnVlLAogICAgfSk7CgogICAgY29uc3QgcHJvcGVydGllcyA9IHJlc3VsdDsKICAgIGlmIChwcm9wZXJ0aWVzKSB7CiAgICAgIGNvbnN0IHZhcmlhYmxlcyA9IHt9OwogICAgICBmb3IgKGNvbnN0IHByb3Agb2YgcHJvcGVydGllcykgewogICAgICAgIGlmIChwcm9wPy52YWx1ZT8ub2JqZWN0SWQgJiYgcHJvcD8udmFsdWUuY2xhc3NOYW1lID09PSAiQXJyYXkiKSB7CiAgICAgICAgICBjb25zdCBpZCA9IHByb3AudmFsdWUub2JqZWN0SWQ7CiAgICAgICAgICBhd2FpdCB1bnJvbGxBcnJheShzZXNzaW9uLCBpZCwgcHJvcC5uYW1lLCB2YXJpYWJsZXMpOwogICAgICAgIH0gZWxzZSBpZiAoCiAgICAgICAgICBwcm9wPy52YWx1ZT8ub2JqZWN0SWQgJiYKICAgICAgICAgIHByb3A/LnZhbHVlPy5jbGFzc05hbWUgPT09ICJPYmplY3QiCiAgICAgICAgKSB7CiAgICAgICAgICBjb25zdCBpZCA9IHByb3AudmFsdWUub2JqZWN0SWQ7CiAgICAgICAgICBhd2FpdCB1bnJvbGxPYmplY3Qoc2Vzc2lvbiwgaWQsIHByb3AubmFtZSwgdmFyaWFibGVzKTsKICAgICAgICB9IGVsc2UgaWYgKHByb3A/LnZhbHVlKSB7CiAgICAgICAgICB1bnJvbGxPdGhlcihwcm9wLCB2YXJpYWJsZXMpOwogICAgICAgIH0KICAgICAgfQogICAgICByZXR1cm4gdmFyaWFibGVzOwogICAgfQogIH0gY2F0Y2ggKGVycikgewogICAgaWYgKGdsb2JhbC5zZkRlYnVnKSB7CiAgICAgIGNvbnNvbGUuZXJyb3IoIltXb3JrZXJdIEZhaWxlZCB0byBmZXRjaCBsb2NhbCB2YXJpYWJsZXM6IiwgZXJyKTsKICAgIH0KICAgIHJldHVybiB7fTsKICB9Cn0KCnN0YXJ0RGVidWdnZXIoKS5jYXRjaCgoZXJyb3IpID0+IHsKICBpZiAoZ2xvYmFsLnNmRGVidWcpIHsKICAgIGNvbnNvbGUuZXJyb3IoIltXb3JrZXJdIEZhaWxlZCB0byBzdGFydCBkZWJ1Z2dlcjoiLCBlcnJvcik7CiAgfQp9KTsKCi8vIEtlZXAgdGhlIHdvcmtlciBhbGl2ZQpzZXRJbnRlcnZhbCgoKSA9PiB7fSwgMTAwMDApOwo="),{workerData:{captureAllExceptions:!0}});let C=null;const c=new WeakMap;g.on("message",l=>{if(typeof l=="string"&&d.getConfig().sfDebug&&W(`[Worker] ${l}`),l.readyToGetParameters&&g.postMessage({sfDebug:d.getConfig().sfDebug,stackDepthLocals:d.getConfig().stackDepthLocals,nodeModulesToCollectLocalVariablesOn:d.getConfig().nodeModulesToCollectLocalVariablesOn}),l.type==="exception"){const{frames:e}=l,o=C;if(!o)return;const t=c.get(o),Z=(function(m){return m?m.split(`
|
|
7
|
+
`).slice(1).map(s=>{const Y=/at (.+?) \((.+):(\d+):(\d+)\)/.exec(s)||/at (.+):(\d+):(\d+)/.exec(s);if(Y){const[,u,r,G,b]=Y;return new J({function:u||"<anonymous>",locals:{},file:r||"<unknown>",line:parseInt(G,10)||0,code:"<not captured>",column:parseInt(b)||0})}return new J({function:"<unknown>",locals:{},file:"<unknown>",line:0,code:"<not captured>",column:0})}):[]})(o.stack),h=(function(m,s){const Y=[];let u=-1,r=-1;for(let G=0;G<m.length;G++){const b=ng(m[G].file);if(r=G,b!=="<unknown>"){for(let a=0;a<s.length;a++){const w=s[a];if(T(w,b)||typeof w.file=="string"&&w.file.includes(b)){u=a,N=0,d.getConfig().sfDebug&&W(`✅ Matched Frame Found: ${b} @ Debugger Frame ${a}`);break}}if(u!==-1)break}}if(u===-1)return N===10?(N=0,m):(++N,d.getConfig().sfDebug&&W(`"❌ No matching frame found. Checking once again, Attempt N ${N}"`),[]);d.getConfig().sfDebug&&W(`🔄 Merging from matched index ${u} onward...`);for(let G=0;G<s.length;G++){const b=m[r+G],a=s[u+G];Y.push(new J({function:a?.function||b?.function||"<anonymous>",locals:a?.locals||b?.locals||{},file:b?.file||a?.file||"<unknown>",line:a?.line||b?.line||0,code:a?.code||b?.code||"<not captured>"}))}return Y})(Z,e||[]);if(h.length!==0){C=null;const m=d.getConfig().stackDepthCodeTraceDepth,s=m===-1?h:h.slice(0,m+1),Y=Math.min(s.length,Z.length);for(let b=0;b<Y;b++)(async()=>{const a=lg(s[b].file,Z[b].line,Z[b].column);a&&(a.content!=null&&(s[b].code=a.content),a.file!=null&&(s[b].file=a.file))})();I.setOperationName("CollectExceptions");const u=o.message?`${o.name}: ${o.message}`:o.name;d.getConfig().sfDebug&&W("error message is : ",u);const r=d.ContextManager.getInstance(),G=c.get(o);G?(r.setTraceIdFor(G,G),r.runWithSession(G,()=>{r.setTraceId(G),I.doSend(u,s)})):I.doSend(u,s),t?d.ContextManager.getInstance().runWithSession(t,()=>{I.doSend(u,s)}):I.doSend(u,s)}}}),g.on("error",l=>{K("[Worker Error]",l)}),g.on("exit",l=>{K(`[Worker] Exited with code ${l}`)}),g.unref();const A=Error,i=new Set;function n(...l){const e=Reflect.construct(A,l);Reflect.setPrototypeOf(e,n.prototype);try{const t=d.ContextManager.getInstance().getTraceId();c.set(e,t)}catch{}A.captureStackTrace&&A.captureStackTrace(e,n);const o=`${e.message}:${e.stack?.split(`
|
|
8
|
+
`)[1]?.trim()}`;if(!i.has(o)){i.add(o),C=e;const t=d.ContextManager.getInstance().getTraceId();c.set(e,t),g.postMessage({type:"processException",error:e.message})}return e}n.prototype=Object.create(A.prototype,{constructor:{value:n,enumerable:!1,writable:!0,configurable:!0}}),Object.setPrototypeOf(n,A),globalThis.Error=n},exports.initializeLogInterceptor=function(I){function g(C,c){const[A,i]=cg(2);I.setOperationName("CollectLogs"),I.doSend([c,C,A,i])}console.log=(...C)=>{if(B)S(...C);else{B=!0;try{g("INFO",C.join(" ")),S(...C)}finally{B=!1}}},console.error=(...C)=>{if(B)F(...C);else{B=!0;try{g("ERROR",C.join(" ")),F(...C)}finally{B=!1}}},console.warn=(...C)=>{if(B)R(...C);else{B=!0;try{g("WARN",C.join(" ")),R(...C)}finally{B=!1}}},console.info=(...C)=>{if(B)k(...C);else{B=!0;try{g("INFO",C.join(" ")),k(...C)}finally{B=!1}}},d.getConfig().logLevel==="DEBUG"&&(console.debug=(...C)=>{if(B)L(...C);else{B=!0;try{g("DEBUG",C.join(" ")),L(...C)}finally{B=!1}}})},exports.internalError=K,exports.internalLog=W,exports.isProductionEnvironment=j,exports.isRuntimeModeEnabled=E,exports.shouldEnableRuntimeHooks=function(){return!!E()&&(!j()||(console.warn("[FuncSpan Runtime] DISABLED in production environment"),!1))};
|