@sentry/node 9.0.0-alpha.1 → 9.0.0-alpha.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.
Files changed (30) hide show
  1. package/build/cjs/integrations/anr/index.js +1 -1
  2. package/build/cjs/integrations/http/SentryHttpInstrumentation.js +15 -4
  3. package/build/cjs/integrations/http/SentryHttpInstrumentation.js.map +1 -1
  4. package/build/cjs/integrations/local-variables/local-variables-async.js +1 -1
  5. package/build/cjs/integrations/node-fetch.js +2 -2
  6. package/build/cjs/integrations/node-fetch.js.map +1 -1
  7. package/build/cjs/integrations/tracing/vercelai/index.js +4 -2
  8. package/build/cjs/integrations/tracing/vercelai/index.js.map +1 -1
  9. package/build/cjs/sdk/index.js +2 -2
  10. package/build/cjs/sdk/index.js.map +1 -1
  11. package/build/cjs/utils/ensureIsWrapped.js +3 -3
  12. package/build/cjs/utils/ensureIsWrapped.js.map +1 -1
  13. package/build/esm/integrations/anr/index.js +1 -1
  14. package/build/esm/integrations/anr/worker-script.js +2 -2
  15. package/build/esm/integrations/http/SentryHttpInstrumentation.js +15 -4
  16. package/build/esm/integrations/http/SentryHttpInstrumentation.js.map +1 -1
  17. package/build/esm/integrations/local-variables/local-variables-async.js +1 -1
  18. package/build/esm/integrations/local-variables/worker-script.js +2 -2
  19. package/build/esm/integrations/node-fetch.js +3 -3
  20. package/build/esm/integrations/node-fetch.js.map +1 -1
  21. package/build/esm/integrations/tracing/vercelai/index.js +4 -2
  22. package/build/esm/integrations/tracing/vercelai/index.js.map +1 -1
  23. package/build/esm/package.json +1 -1
  24. package/build/esm/sdk/index.js +3 -3
  25. package/build/esm/sdk/index.js.map +1 -1
  26. package/build/esm/utils/ensureIsWrapped.js +4 -4
  27. package/build/esm/utils/ensureIsWrapped.js.map +1 -1
  28. package/build/types/integrations/http/SentryHttpInstrumentation.d.ts.map +1 -1
  29. package/build/types/integrations/tracing/vercelai/index.d.ts.map +1 -1
  30. package/package.json +3 -3
@@ -9,7 +9,7 @@ const debug = require('../../utils/debug.js');
9
9
  const { isPromise } = util.types;
10
10
 
11
11
  // This string is a placeholder that gets overwritten with the worker code.
12
- const base64WorkerScript = 'LyohIEBzZW50cnkvbm9kZSA5LjAuMC1hbHBoYS4xIChiZTkxZjllKSB8IGh0dHBzOi8vZ2l0aHViLmNvbS9nZXRzZW50cnkvc2VudHJ5LWphdmFzY3JpcHQgKi8KaW1wb3J0e1Nlc3Npb24gYXMgdH1mcm9tIm5vZGU6aW5zcGVjdG9yIjtpbXBvcnR7cGFyZW50UG9ydCBhcyBuLHdvcmtlckRhdGEgYXMgZX1mcm9tIm5vZGU6d29ya2VyX3RocmVhZHMiO2ltcG9ydHtwb3NpeCBhcyByLHNlcCBhcyBvfWZyb20ibm9kZTpwYXRoIjtpbXBvcnQqYXMgcyBmcm9tIm5vZGU6aHR0cCI7aW1wb3J0KmFzIGkgZnJvbSJub2RlOmh0dHBzIjtpbXBvcnR7UmVhZGFibGUgYXMgY31mcm9tIm5vZGU6c3RyZWFtIjtpbXBvcnR7Y3JlYXRlR3ppcCBhcyB1fWZyb20ibm9kZTp6bGliIjtpbXBvcnQqYXMgYSBmcm9tIm5vZGU6bmV0IjtpbXBvcnQqYXMgZiBmcm9tIm5vZGU6dGxzIjtjb25zdCBoPSJ1bmRlZmluZWQiPT10eXBlb2YgX19TRU5UUllfREVCVUdfX3x8X19TRU5UUllfREVCVUdfXyxwPWdsb2JhbFRoaXMsbD0idW5kZWZpbmVkIj09dHlwZW9mIF9fU0VOVFJZX0RFQlVHX198fF9fU0VOVFJZX0RFQlVHX18sZD0iOS4wLjAtYWxwaGEuMSI7ZnVuY3Rpb24gbSgpe3JldHVybiB5KHApLHB9ZnVuY3Rpb24geSh0KXtjb25zdCBuPXQuX19TRU5UUllfXz10Ll9fU0VOVFJZX198fHt9O3JldHVybiBuLnZlcnNpb249bi52ZXJzaW9ufHxkLG5bZF09bltkXXx8e319ZnVuY3Rpb24gZyh0LG4sZT1wKXtjb25zdCByPWUuX19TRU5UUllfXz1lLl9fU0VOVFJZX198fHt9LG89cltkXT1yW2RdfHx7fTtyZXR1cm4gb1t0XXx8KG9bdF09bigpKX1jb25zdCBiPVsiZGVidWciLCJpbmZvIiwid2FybiIsImVycm9yIiwibG9nIiwiYXNzZXJ0IiwidHJhY2UiXSxfPXt9O2Z1bmN0aW9uIHYodCl7aWYoISgiY29uc29sZSJpbiBwKSlyZXR1cm4gdCgpO2NvbnN0IG49cC5jb25zb2xlLGU9e30scj1PYmplY3Qua2V5cyhfKTtyLmZvckVhY2goKHQ9Pntjb25zdCByPV9bdF07ZVt0XT1uW3RdLG5bdF09cn0pKTt0cnl7cmV0dXJuIHQoKX1maW5hbGx5e3IuZm9yRWFjaCgodD0+e25bdF09ZVt0XX0pKX19Y29uc3Qgdz1nKCJsb2dnZXIiLChmdW5jdGlvbigpe2xldCB0PSExO2NvbnN0IG49e2VuYWJsZTooKT0+e3Q9ITB9LGRpc2FibGU6KCk9Pnt0PSExfSxpc0VuYWJsZWQ6KCk9PnR9O3JldHVybiBsP2IuZm9yRWFjaCgoZT0+e25bZV09KC4uLm4pPT57dCYmdigoKCk9PntwLmNvbnNvbGVbZV0oYFNlbnRyeSBMb2dnZXIgWyR7ZX1dOmAsLi4ubil9KSl9fSkpOmIuZm9yRWFjaCgodD0+e25bdF09KCk9Pnt9fSkpLG59KSksUz01MCwkPSI/IixFPS9jYXB0dXJlTWVzc2FnZXxjYXB0dXJlRXhjZXB0aW9uLztmdW5jdGlvbiB4KHQpe3JldHVybiB0W3QubGVuZ3RoLTFdfHx7fX1jb25zdCBOPSI8YW5vbnltb3VzPiI7Y29uc3QgVD1PYmplY3QucHJvdG90eXBlLnRvU3RyaW5nO2Z1bmN0aW9uIEModCxuKXtyZXR1cm4gVC5jYWxsKHQpPT09YFtvYmplY3QgJHtufV1gfWZ1bmN0aW9uIGoodCl7cmV0dXJuIEModCwiU3RyaW5nIil9ZnVuY3Rpb24gUih0KXtyZXR1cm4gQyh0LCJPYmplY3QiKX1mdW5jdGlvbiBPKHQpe3JldHVybiBCb29sZWFuKHQ/LnRoZW4mJiJmdW5jdGlvbiI9PXR5cGVvZiB0LnRoZW4pfWZ1bmN0aW9uIEQodCxuKXt0cnl7cmV0dXJuIHQgaW5zdGFuY2VvZiBufWNhdGNoKHQpe3JldHVybiExfX1jb25zdCBrPXAsQT04MDtmdW5jdGlvbiBJKHQsbil7Y29uc3QgZT10LHI9W107aWYoIWU/LnRhZ05hbWUpcmV0dXJuIiI7aWYoay5IVE1MRWxlbWVudCYmZSBpbnN0YW5jZW9mIEhUTUxFbGVtZW50JiZlLmRhdGFzZXQpe2lmKGUuZGF0YXNldC5zZW50cnlDb21wb25lbnQpcmV0dXJuIGUuZGF0YXNldC5zZW50cnlDb21wb25lbnQ7aWYoZS5kYXRhc2V0LnNlbnRyeUVsZW1lbnQpcmV0dXJuIGUuZGF0YXNldC5zZW50cnlFbGVtZW50fXIucHVzaChlLnRhZ05hbWUudG9Mb3dlckNhc2UoKSk7Y29uc3Qgbz1uPy5sZW5ndGg/bi5maWx0ZXIoKHQ9PmUuZ2V0QXR0cmlidXRlKHQpKSkubWFwKCh0PT5bdCxlLmdldEF0dHJpYnV0ZSh0KV0pKTpudWxsO2lmKG8/Lmxlbmd0aClvLmZvckVhY2goKHQ9PntyLnB1c2goYFske3RbMF19PSIke3RbMV19Il1gKX0pKTtlbHNle2UuaWQmJnIucHVzaChgIyR7ZS5pZH1gKTtjb25zdCB0PWUuY2xhc3NOYW1lO2lmKHQmJmoodCkpe2NvbnN0IG49dC5zcGxpdCgvXHMrLyk7Zm9yKGNvbnN0IHQgb2YgbilyLnB1c2goYC4ke3R9YCl9fWNvbnN0IHM9WyJhcmlhLWxhYmVsIiwidHlwZSIsIm5hbWUiLCJ0aXRsZSIsImFsdCJdO2Zvcihjb25zdCB0IG9mIHMpe2NvbnN0IG49ZS5nZXRBdHRyaWJ1dGUodCk7biYmci5wdXNoKGBbJHt0fT0iJHtufSJdYCl9cmV0dXJuIHIuam9pbigiIil9ZnVuY3Rpb24gUCh0KXtpZihmdW5jdGlvbih0KXtzd2l0Y2goVC5jYWxsKHQpKXtjYXNlIltvYmplY3QgRXJyb3JdIjpjYXNlIltvYmplY3QgRXhjZXB0aW9uXSI6Y2FzZSJbb2JqZWN0IERPTUV4Y2VwdGlvbl0iOmNhc2UiW29iamVjdCBXZWJBc3NlbWJseS5FeGNlcHRpb25dIjpyZXR1cm4hMDtkZWZhdWx0OnJldHVybiBEKHQsRXJyb3IpfX0odCkpcmV0dXJue21lc3NhZ2U6dC5tZXNzYWdlLG5hbWU6dC5uYW1lLHN0YWNrOnQuc3RhY2ssLi4uTSh0KX07aWYobj10LCJ1bmRlZmluZWQiIT10eXBlb2YgRXZlbnQmJkQobixFdmVudCkpe2NvbnN0IG49e3R5cGU6dC50eXBlLHRhcmdldDpVKHQudGFyZ2V0KSxjdXJyZW50VGFyZ2V0OlUodC5jdXJyZW50VGFyZ2V0KSwuLi5NKHQpfTtyZXR1cm4idW5kZWZpbmVkIiE9dHlwZW9mIEN1c3RvbUV2ZW50JiZEKHQsQ3VzdG9tRXZlbnQpJiYobi5kZXRhaWw9dC5kZXRhaWwpLG59cmV0dXJuIHQ7dmFyIG59ZnVuY3Rpb24gVSh0KXt0cnl7cmV0dXJuIG49dCwidW5kZWZpbmVkIiE9dHlwZW9mIEVsZW1lbnQmJkQobixFbGVtZW50KT9mdW5jdGlvbih0LG49e30pe2lmKCF0KXJldHVybiI8dW5rbm93bj4iO3RyeXtsZXQgZT10O2NvbnN0IHI9NSxvPVtdO2xldCBzPTAsaT0wO2NvbnN0IGM9IiA+ICIsdT1jLmxlbmd0aDtsZXQgYTtjb25zdCBmPUFycmF5LmlzQXJyYXkobik/bjpuLmtleUF0dHJzLGg9IUFycmF5LmlzQXJyYXkobikmJm4ubWF4U3RyaW5nTGVuZ3RofHxBO2Zvcig7ZSYmcysrPHImJihhPUkoZSxmKSwhKCJodG1sIj09PWF8fHM+MSYmaStvLmxlbmd0aCp1K2EubGVuZ3RoPj1oKSk7KW8ucHVzaChhKSxpKz1hLmxlbmd0aCxlPWUucGFyZW50Tm9kZTtyZXR1cm4gby5yZXZlcnNlKCkuam9pbihjKX1jYXRjaCh0KXtyZXR1cm4iPHVua25vd24+In19KHQpOk9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbCh0KX1jYXRjaCh0KXtyZXR1cm4iPHVua25vd24+In12YXIgbn1mdW5jdGlvbiBNKHQpe2lmKCJvYmplY3QiPT10eXBlb2YgdCYmbnVsbCE9PXQpe2NvbnN0IG49e307Zm9yKGNvbnN0IGUgaW4gdClPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwodCxlKSYmKG5bZV09dFtlXSk7cmV0dXJuIG59cmV0dXJue319ZnVuY3Rpb24gTCh0KXtyZXR1cm4gQih0LG5ldyBNYXApfWZ1bmN0aW9uIEIodCxuKXtpZihmdW5jdGlvbih0KXtpZighUih0KSlyZXR1cm4hMTt0cnl7Y29uc3Qgbj1PYmplY3QuZ2V0UHJvdG90eXBlT2YodCkuY29uc3RydWN0b3IubmFtZTtyZXR1cm4hbnx8Ik9iamVjdCI9PT1ufWNhdGNoe3JldHVybiEwfX0odCkpe2NvbnN0IGU9bi5nZXQodCk7aWYodm9pZCAwIT09ZSlyZXR1cm4gZTtjb25zdCByPXt9O24uc2V0KHQscik7Zm9yKGNvbnN0IGUgb2YgT2JqZWN0LmdldE93blByb3BlcnR5TmFtZXModCkpdm9pZCAwIT09dFtlXSYmKHJbZV09Qih0W2VdLG4pKTtyZXR1cm4gcn1pZihBcnJheS5pc0FycmF5KHQpKXtjb25zdCBlPW4uZ2V0KHQpO2lmKHZvaWQgMCE9PWUpcmV0dXJuIGU7Y29uc3Qgcj1bXTtyZXR1cm4gbi5zZXQodCxyKSx0LmZvckVhY2goKHQ9PntyLnB1c2goQih0LG4pKX0pKSxyfXJldHVybiB0fWNvbnN0IEc9MWUzO2Z1bmN0aW9uIEooKXtyZXR1cm4gRGF0ZS5ub3coKS9HfWNvbnN0IFk9ZnVuY3Rpb24oKXtjb25zdHtwZXJmb3JtYW5jZTp0fT1wO2lmKCF0Py5ub3cpcmV0dXJuIEo7Y29uc3Qgbj1EYXRlLm5vdygpLXQubm93KCksZT1udWxsPT10LnRpbWVPcmlnaW4/bjp0LnRpbWVPcmlnaW47cmV0dXJuKCk9PihlK3Qubm93KCkpL0d9KCk7ZnVuY3Rpb24geigpe2NvbnN0IHQ9cCxuPXQuY3J5cHRvfHx0Lm1zQ3J5cHRvO2xldCBlPSgpPT4xNipNYXRoLnJhbmRvbSgpO3RyeXtpZihuPy5yYW5kb21VVUlEKXJldHVybiBuLnJhbmRvbVVVSUQoKS5yZXBsYWNlKC8tL2csIiIpO24/LmdldFJhbmRvbVZhbHVlcyYmKGU9KCk9Pntjb25zdCB0PW5ldyBVaW50OEFycmF5KDEpO3JldHVybiBuLmdldFJhbmRvbVZhbHVlcyh0KSx0WzBdfSl9Y2F0Y2godCl7fXJldHVybihbMWU3XSsxZTMrNGUzKzhlMysxZTExKS5yZXBsYWNlKC9bMDE4XS9nLCh0PT4odF4oMTUmZSgpKT4+dC80KS50b1N0cmluZygxNikpKX12YXIgSDtmdW5jdGlvbiBXKHQpe3JldHVybiBuZXcgRigobj0+e24odCl9KSl9IWZ1bmN0aW9uKHQpe3RbdC5QRU5ESU5HPTBdPSJQRU5ESU5HIjt0W3QuUkVTT0xWRUQ9MV09IlJFU09MVkVEIjt0W3QuUkVKRUNURUQ9Ml09IlJFSkVDVEVEIn0oSHx8KEg9e30pKTtjbGFzcyBGe2NvbnN0cnVjdG9yKHQpe3RoaXMudD1ILlBFTkRJTkcsdGhpcy5vPVtdLHRoaXMuaSh0KX10aGVuKHQsbil7cmV0dXJuIG5ldyBGKCgoZSxyKT0+e3RoaXMuby5wdXNoKFshMSxuPT57aWYodCl0cnl7ZSh0KG4pKX1jYXRjaCh0KXtyKHQpfWVsc2UgZShuKX0sdD0+e2lmKG4pdHJ5e2Uobih0KSl9Y2F0Y2godCl7cih0KX1lbHNlIHIodCl9XSksdGhpcy51KCl9KSl9Y2F0Y2godCl7cmV0dXJuIHRoaXMudGhlbigodD0+dCksdCl9ZmluYWxseSh0KXtyZXR1cm4gbmV3IEYoKChuLGUpPT57bGV0IHIsbztyZXR1cm4gdGhpcy50aGVuKChuPT57bz0hMSxyPW4sdCYmdCgpfSksKG49PntvPSEwLHI9bix0JiZ0KCl9KSkudGhlbigoKCk9PntvP2Uocik6bihyKX0pKX0pKX11KCl7aWYodGhpcy50PT09SC5QRU5ESU5HKXJldHVybjtjb25zdCB0PXRoaXMuby5zbGljZSgpO3RoaXMubz1bXSx0LmZvckVhY2goKHQ9Pnt0WzBdfHwodGhpcy50PT09SC5SRVNPTFZFRCYmdFsxXSh0aGlzLmgpLHRoaXMudD09PUguUkVKRUNURUQmJnRbMl0odGhpcy5oKSx0WzBdPSEwKX0pKX1pKHQpe2NvbnN0IG49KHQsbik9Pnt0aGlzLnQ9PT1ILlBFTkRJTkcmJihPKG4pP24udGhlbihlLHIpOih0aGlzLnQ9dCx0aGlzLmg9bix0aGlzLnUoKSkpfSxlPXQ9PntuKEguUkVTT0xWRUQsdCl9LHI9dD0+e24oSC5SRUpFQ1RFRCx0KX07dHJ5e3QoZSxyKX1jYXRjaCh0KXtyKHQpfX19ZnVuY3Rpb24gSyh0KXtjb25zdCBuPVkoKSxlPXtzaWQ6eigpLGluaXQ6ITAsdGltZXN0YW1wOm4sc3RhcnRlZDpuLGR1cmF0aW9uOjAsc3RhdHVzOiJvayIsZXJyb3JzOjAsaWdub3JlRHVyYXRpb246ITEsdG9KU09OOigpPT5mdW5jdGlvbih0KXtyZXR1cm4gTCh7c2lkOmAke3Quc2lkfWAsaW5pdDp0LmluaXQsc3RhcnRlZDpuZXcgRGF0ZSgxZTMqdC5zdGFydGVkKS50b0lTT1N0cmluZygpLHRpbWVzdGFtcDpuZXcgRGF0ZSgxZTMqdC50aW1lc3RhbXApLnRvSVNPU3RyaW5nKCksc3RhdHVzOnQuc3RhdHVzLGVycm9yczp0LmVycm9ycyxkaWQ6Im51bWJlciI9PXR5cGVvZiB0LmRpZHx8InN0cmluZyI9PXR5cGVvZiB0LmRpZD9gJHt0LmRpZH1gOnZvaWQgMCxkdXJhdGlvbjp0LmR1cmF0aW9uLGFibm9ybWFsX21lY2hhbmlzbTp0LmFibm9ybWFsX21lY2hhbmlzbSxhdHRyczp7cmVsZWFzZTp0LnJlbGVhc2UsZW52aXJvbm1lbnQ6dC5lbnZpcm9ubWVudCxpcF9hZGRyZXNzOnQuaXBBZGRyZXNzLHVzZXJfYWdlbnQ6dC51c2VyQWdlbnR9fSl9KGUpfTtyZXR1cm4gdCYmVihlLHQpLGV9ZnVuY3Rpb24gVih0LG49e30pe2lmKG4udXNlciYmKCF0LmlwQWRkcmVzcyYmbi51c2VyLmlwX2FkZHJlc3MmJih0LmlwQWRkcmVzcz1uLnVzZXIuaXBfYWRkcmVzcyksdC5kaWR8fG4uZGlkfHwodC5kaWQ9bi51c2VyLmlkfHxuLnVzZXIuZW1haWx8fG4udXNlci51c2VybmFtZSkpLHQudGltZXN0YW1wPW4udGltZXN0YW1wfHxZKCksbi5hYm5vcm1hbF9tZWNoYW5pc20mJih0LmFibm9ybWFsX21lY2hhbmlzbT1uLmFibm9ybWFsX21lY2hhbmlzbSksbi5pZ25vcmVEdXJhdGlvbiYmKHQuaWdub3JlRHVyYXRpb249bi5pZ25vcmVEdXJhdGlvbiksbi5zaWQmJih0LnNpZD0zMj09PW4uc2lkLmxlbmd0aD9uLnNpZDp6KCkpLHZvaWQgMCE9PW4uaW5pdCYmKHQuaW5pdD1uLmluaXQpLCF0LmRpZCYmbi5kaWQmJih0LmRpZD1gJHtuLmRpZH1gKSwibnVtYmVyIj09dHlwZW9mIG4uc3RhcnRlZCYmKHQuc3RhcnRlZD1uLnN0YXJ0ZWQpLHQuaWdub3JlRHVyYXRpb24pdC5kdXJhdGlvbj12b2lkIDA7ZWxzZSBpZigibnVtYmVyIj09dHlwZW9mIG4uZHVyYXRpb24pdC5kdXJhdGlvbj1uLmR1cmF0aW9uO2Vsc2V7Y29uc3Qgbj10LnRpbWVzdGFtcC10LnN0YXJ0ZWQ7dC5kdXJhdGlvbj1uPj0wP246MH1uLnJlbGVhc2UmJih0LnJlbGVhc2U9bi5yZWxlYXNlKSxuLmVudmlyb25tZW50JiYodC5lbnZpcm9ubWVudD1uLmVudmlyb25tZW50KSwhdC5pcEFkZHJlc3MmJm4uaXBBZGRyZXNzJiYodC5pcEFkZHJlc3M9bi5pcEFkZHJlc3MpLCF0LnVzZXJBZ2VudCYmbi51c2VyQWdlbnQmJih0LnVzZXJBZ2VudD1uLnVzZXJBZ2VudCksIm51bWJlciI9PXR5cGVvZiBuLmVycm9ycyYmKHQuZXJyb3JzPW4uZXJyb3JzKSxuLnN0YXR1cyYmKHQuc3RhdHVzPW4uc3RhdHVzKX1mdW5jdGlvbiBaKCl7cmV0dXJuIHooKX1mdW5jdGlvbiBxKCl7cmV0dXJuIHooKS5zdWJzdHJpbmcoMTYpfWZ1bmN0aW9uIFEodCxuLGU9Mil7aWYoIW58fCJvYmplY3QiIT10eXBlb2Ygbnx8ZTw9MClyZXR1cm4gbjtpZih0JiYwPT09T2JqZWN0LmtleXMobikubGVuZ3RoKXJldHVybiB0O2NvbnN0IHI9ey4uLnR9O2Zvcihjb25zdCB0IGluIG4pT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKG4sdCkmJihyW3RdPVEoclt0XSxuW3RdLGUtMSkpO3JldHVybiByfWNvbnN0IFg9Il9zZW50cnlTcGFuIjtmdW5jdGlvbiB0dCh0LG4pe24/ZnVuY3Rpb24odCxuLGUpe3RyeXtPYmplY3QuZGVmaW5lUHJvcGVydHkodCxuLHt2YWx1ZTplLHdyaXRhYmxlOiEwLGNvbmZpZ3VyYWJsZTohMH0pfWNhdGNoKGUpe2wmJncubG9nKGBGYWlsZWQgdG8gYWRkIG5vbi1lbnVtZXJhYmxlIHByb3BlcnR5ICIke259IiB0byBvYmplY3RgLHQpfX0odCxYLG4pOmRlbGV0ZSB0W1hdfWZ1bmN0aW9uIG50KHQpe3JldHVybiB0W1hdfWNsYXNzIGV0e2NvbnN0cnVjdG9yKCl7dGhpcy5wPSExLHRoaXMubD1bXSx0aGlzLm09W10sdGhpcy5fPVtdLHRoaXMudj1bXSx0aGlzLlM9e30sdGhpcy5OPXt9LHRoaXMuVD17fSx0aGlzLkM9e30sdGhpcy5qPXt9LHRoaXMuUj17dHJhY2VJZDpaKCksc2FtcGxlUmFuZDpNYXRoLnJhbmRvbSgpfX1jbG9uZSgpe2NvbnN0IHQ9bmV3IGV0O3JldHVybiB0Ll89Wy4uLnRoaXMuX10sdC5OPXsuLi50aGlzLk59LHQuVD17Li4udGhpcy5UfSx0LkM9ey4uLnRoaXMuQ30sdGhpcy5DLmZsYWdzJiYodC5DLmZsYWdzPXt2YWx1ZXM6Wy4uLnRoaXMuQy5mbGFncy52YWx1ZXNdfSksdC5TPXRoaXMuUyx0Lk89dGhpcy5PLHQuRD10aGlzLkQsdC5rPXRoaXMuayx0LkE9dGhpcy5BLHQubT1bLi4udGhpcy5tXSx0LnY9Wy4uLnRoaXMudl0sdC5qPXsuLi50aGlzLmp9LHQuUj17Li4udGhpcy5SfSx0Lkk9dGhpcy5JLHQuUD10aGlzLlAsdHQodCxudCh0aGlzKSksdH1zZXRDbGllbnQodCl7dGhpcy5JPXR9c2V0TGFzdEV2ZW50SWQodCl7dGhpcy5QPXR9Z2V0Q2xpZW50KCl7cmV0dXJuIHRoaXMuSX1sYXN0RXZlbnRJZCgpe3JldHVybiB0aGlzLlB9YWRkU2NvcGVMaXN0ZW5lcih0KXt0aGlzLmwucHVzaCh0KX1hZGRFdmVudFByb2Nlc3Nvcih0KXtyZXR1cm4gdGhpcy5tLnB1c2godCksdGhpc31zZXRVc2VyKHQpe3JldHVybiB0aGlzLlM9dHx8e2VtYWlsOnZvaWQgMCxpZDp2b2lkIDAsaXBfYWRkcmVzczp2b2lkIDAsdXNlcm5hbWU6dm9pZCAwfSx0aGlzLkQmJlYodGhpcy5ELHt1c2VyOnR9KSx0aGlzLlUoKSx0aGlzfWdldFVzZXIoKXtyZXR1cm4gdGhpcy5TfXNldFRhZ3ModCl7cmV0dXJuIHRoaXMuTj17Li4udGhpcy5OLC4uLnR9LHRoaXMuVSgpLHRoaXN9c2V0VGFnKHQsbil7cmV0dXJuIHRoaXMuTj17Li4udGhpcy5OLFt0XTpufSx0aGlzLlUoKSx0aGlzfXNldEV4dHJhcyh0KXtyZXR1cm4gdGhpcy5UPXsuLi50aGlzLlQsLi4udH0sdGhpcy5VKCksdGhpc31zZXRFeHRyYSh0LG4pe3JldHVybiB0aGlzLlQ9ey4uLnRoaXMuVCxbdF06bn0sdGhpcy5VKCksdGhpc31zZXRGaW5nZXJwcmludCh0KXtyZXR1cm4gdGhpcy5BPXQsdGhpcy5VKCksdGhpc31zZXRMZXZlbCh0KXtyZXR1cm4gdGhpcy5PPXQsdGhpcy5VKCksdGhpc31zZXRUcmFuc2FjdGlvbk5hbWUodCl7cmV0dXJuIHRoaXMuaz10LHRoaXMuVSgpLHRoaXN9c2V0Q29udGV4dCh0LG4pe3JldHVybiBudWxsPT09bj9kZWxldGUgdGhpcy5DW3RdOnRoaXMuQ1t0XT1uLHRoaXMuVSgpLHRoaXN9c2V0U2Vzc2lvbih0KXtyZXR1cm4gdD90aGlzLkQ9dDpkZWxldGUgdGhpcy5ELHRoaXMuVSgpLHRoaXN9Z2V0U2Vzc2lvbigpe3JldHVybiB0aGlzLkR9dXBkYXRlKHQpe2lmKCF0KXJldHVybiB0aGlzO2NvbnN0IG49ImZ1bmN0aW9uIj09dHlwZW9mIHQ/dCh0aGlzKTp0LGU9biBpbnN0YW5jZW9mIGV0P24uZ2V0U2NvcGVEYXRhKCk6UihuKT90OnZvaWQgMCx7dGFnczpyLGV4dHJhOm8sdXNlcjpzLGNvbnRleHRzOmksbGV2ZWw6YyxmaW5nZXJwcmludDp1PVtdLHByb3BhZ2F0aW9uQ29udGV4dDphfT1lfHx7fTtyZXR1cm4gdGhpcy5OPXsuLi50aGlzLk4sLi4ucn0sdGhpcy5UPXsuLi50aGlzLlQsLi4ub30sdGhpcy5DPXsuLi50aGlzLkMsLi4uaX0scyYmT2JqZWN0LmtleXMocykubGVuZ3RoJiYodGhpcy5TPXMpLGMmJih0aGlzLk89YyksdS5sZW5ndGgmJih0aGlzLkE9dSksYSYmKHRoaXMuUj1hKSx0aGlzfWNsZWFyKCl7cmV0dXJuIHRoaXMuXz1bXSx0aGlzLk49e30sdGhpcy5UPXt9LHRoaXMuUz17fSx0aGlzLkM9e30sdGhpcy5PPXZvaWQgMCx0aGlzLms9dm9pZCAwLHRoaXMuQT12b2lkIDAsdGhpcy5EPXZvaWQgMCx0dCh0aGlzLHZvaWQgMCksdGhpcy52PVtdLHRoaXMuc2V0UHJvcGFnYXRpb25Db250ZXh0KHt0cmFjZUlkOlooKSxzYW1wbGVSYW5kOk1hdGgucmFuZG9tKCl9KSx0aGlzLlUoKSx0aGlzfWFkZEJyZWFkY3J1bWIodCxuKXtjb25zdCBlPSJudW1iZXIiPT10eXBlb2Ygbj9uOjEwMDtpZihlPD0wKXJldHVybiB0aGlzO2NvbnN0IHI9e3RpbWVzdGFtcDpKKCksLi4udH07cmV0dXJuIHRoaXMuXy5wdXNoKHIpLHRoaXMuXy5sZW5ndGg+ZSYmKHRoaXMuXz10aGlzLl8uc2xpY2UoLWUpLHRoaXMuST8ucmVjb3JkRHJvcHBlZEV2ZW50KCJidWZmZXJfb3ZlcmZsb3ciLCJsb2dfaXRlbSIpKSx0aGlzLlUoKSx0aGlzfWdldExhc3RCcmVhZGNydW1iKCl7cmV0dXJuIHRoaXMuX1t0aGlzLl8ubGVuZ3RoLTFdfWNsZWFyQnJlYWRjcnVtYnMoKXtyZXR1cm4gdGhpcy5fPVtdLHRoaXMuVSgpLHRoaXN9YWRkQXR0YWNobWVudCh0KXtyZXR1cm4gdGhpcy52LnB1c2godCksdGhpc31jbGVhckF0dGFjaG1lbnRzKCl7cmV0dXJuIHRoaXMudj1bXSx0aGlzfWdldFNjb3BlRGF0YSgpe3JldHVybnticmVhZGNydW1iczp0aGlzLl8sYXR0YWNobWVudHM6dGhpcy52LGNvbnRleHRzOnRoaXMuQyx0YWdzOnRoaXMuTixleHRyYTp0aGlzLlQsdXNlcjp0aGlzLlMsbGV2ZWw6dGhpcy5PLGZpbmdlcnByaW50OnRoaXMuQXx8W10sZXZlbnRQcm9jZXNzb3JzOnRoaXMubSxwcm9wYWdhdGlvbkNvbnRleHQ6dGhpcy5SLHNka1Byb2Nlc3NpbmdNZXRhZGF0YTp0aGlzLmosdHJhbnNhY3Rpb25OYW1lOnRoaXMuayxzcGFuOm50KHRoaXMpfX1zZXRTREtQcm9jZXNzaW5nTWV0YWRhdGEodCl7cmV0dXJuIHRoaXMuaj1RKHRoaXMuaix0LDIpLHRoaXN9c2V0UHJvcGFnYXRpb25Db250ZXh0KHQpe3JldHVybiB0aGlzLlI9dCx0aGlzfWdldFByb3BhZ2F0aW9uQ29udGV4dCgpe3JldHVybiB0aGlzLlJ9Y2FwdHVyZUV4Y2VwdGlvbih0LG4pe2NvbnN0IGU9bj8uZXZlbnRfaWR8fHooKTtpZighdGhpcy5JKXJldHVybiB3Lndhcm4oIk5vIGNsaWVudCBjb25maWd1cmVkIG9uIHNjb3BlIC0gd2lsbCBub3QgY2FwdHVyZSBleGNlcHRpb24hIiksZTtjb25zdCByPW5ldyBFcnJvcigiU2VudHJ5IHN5bnRoZXRpY0V4Y2VwdGlvbiIpO3JldHVybiB0aGlzLkkuY2FwdHVyZUV4Y2VwdGlvbih0LHtvcmlnaW5hbEV4Y2VwdGlvbjp0LHN5bnRoZXRpY0V4Y2VwdGlvbjpyLC4uLm4sZXZlbnRfaWQ6ZX0sdGhpcyksZX1jYXB0dXJlTWVzc2FnZSh0LG4sZSl7Y29uc3Qgcj1lPy5ldmVudF9pZHx8eigpO2lmKCF0aGlzLkkpcmV0dXJuIHcud2FybigiTm8gY2xpZW50IGNvbmZpZ3VyZWQgb24gc2NvcGUgLSB3aWxsIG5vdCBjYXB0dXJlIG1lc3NhZ2UhIikscjtjb25zdCBvPW5ldyBFcnJvcih0KTtyZXR1cm4gdGhpcy5JLmNhcHR1cmVNZXNzYWdlKHQsbix7b3JpZ2luYWxFeGNlcHRpb246dCxzeW50aGV0aWNFeGNlcHRpb246bywuLi5lLGV2ZW50X2lkOnJ9LHRoaXMpLHJ9Y2FwdHVyZUV2ZW50KHQsbil7Y29uc3QgZT1uPy5ldmVudF9pZHx8eigpO3JldHVybiB0aGlzLkk/KHRoaXMuSS5jYXB0dXJlRXZlbnQodCx7Li4ubixldmVudF9pZDplfSx0aGlzKSxlKToody53YXJuKCJObyBjbGllbnQgY29uZmlndXJlZCBvbiBzY29wZSAtIHdpbGwgbm90IGNhcHR1cmUgZXZlbnQhIiksZSl9VSgpe3RoaXMucHx8KHRoaXMucD0hMCx0aGlzLmwuZm9yRWFjaCgodD0+e3QodGhpcyl9KSksdGhpcy5wPSExKX19Y2xhc3MgcnR7Y29uc3RydWN0b3IodCxuKXtsZXQgZSxyO2U9dHx8bmV3IGV0LHI9bnx8bmV3IGV0LHRoaXMuTT1be3Njb3BlOmV9XSx0aGlzLkw9cn13aXRoU2NvcGUodCl7Y29uc3Qgbj10aGlzLkIoKTtsZXQgZTt0cnl7ZT10KG4pfWNhdGNoKHQpe3Rocm93IHRoaXMuRygpLHR9cmV0dXJuIE8oZSk/ZS50aGVuKCh0PT4odGhpcy5HKCksdCkpLCh0PT57dGhyb3cgdGhpcy5HKCksdH0pKToodGhpcy5HKCksZSl9Z2V0Q2xpZW50KCl7cmV0dXJuIHRoaXMuZ2V0U3RhY2tUb3AoKS5jbGllbnR9Z2V0U2NvcGUoKXtyZXR1cm4gdGhpcy5nZXRTdGFja1RvcCgpLnNjb3BlfWdldElzb2xhdGlvblNjb3BlKCl7cmV0dXJuIHRoaXMuTH1nZXRTdGFja1RvcCgpe3JldHVybiB0aGlzLk1bdGhpcy5NLmxlbmd0aC0xXX1CKCl7Y29uc3QgdD10aGlzLmdldFNjb3BlKCkuY2xvbmUoKTtyZXR1cm4gdGhpcy5NLnB1c2goe2NsaWVudDp0aGlzLmdldENsaWVudCgpLHNjb3BlOnR9KSx0fUcoKXtyZXR1cm4hKHRoaXMuTS5sZW5ndGg8PTEpJiYhIXRoaXMuTS5wb3AoKX19ZnVuY3Rpb24gb3QoKXtjb25zdCB0PXkobSgpKTtyZXR1cm4gdC5zdGFjaz10LnN0YWNrfHxuZXcgcnQoZygiZGVmYXVsdEN1cnJlbnRTY29wZSIsKCgpPT5uZXcgZXQpKSxnKCJkZWZhdWx0SXNvbGF0aW9uU2NvcGUiLCgoKT0+bmV3IGV0KSkpfWZ1bmN0aW9uIHN0KHQpe3JldHVybiBvdCgpLndpdGhTY29wZSh0KX1mdW5jdGlvbiBpdCh0LG4pe2NvbnN0IGU9b3QoKTtyZXR1cm4gZS53aXRoU2NvcGUoKCgpPT4oZS5nZXRTdGFja1RvcCgpLnNjb3BlPXQsbih0KSkpKX1mdW5jdGlvbiBjdCh0KXtyZXR1cm4gb3QoKS53aXRoU2NvcGUoKCgpPT50KG90KCkuZ2V0SXNvbGF0aW9uU2NvcGUoKSkpKX1mdW5jdGlvbiB1dCh0KXtjb25zdCBuPXkodCk7cmV0dXJuIG4uYWNzP24uYWNzOnt3aXRoSXNvbGF0aW9uU2NvcGU6Y3Qsd2l0aFNjb3BlOnN0LHdpdGhTZXRTY29wZTppdCx3aXRoU2V0SXNvbGF0aW9uU2NvcGU6KHQsbik9PmN0KG4pLGdldEN1cnJlbnRTY29wZTooKT0+b3QoKS5nZXRTY29wZSgpLGdldElzb2xhdGlvblNjb3BlOigpPT5vdCgpLmdldElzb2xhdGlvblNjb3BlKCl9fWZ1bmN0aW9uIGF0KCl7cmV0dXJuIHV0KG0oKSkuZ2V0Q3VycmVudFNjb3BlKCkuZ2V0Q2xpZW50KCl9Y29uc3QgZnQ9InNlbnRyeS5zb3VyY2UiLGh0PSJzZW50cnkuc2FtcGxlX3JhdGUiLHB0PSJzZW50cnkub3AiLGx0PSJzZW50cnkub3JpZ2luIixkdD0wLG10PTEseXQ9Il9zZW50cnlTY29wZSIsZ3Q9Il9zZW50cnlJc29sYXRpb25TY29wZSI7ZnVuY3Rpb24gYnQodCl7cmV0dXJue3Njb3BlOnRbeXRdLGlzb2xhdGlvblNjb3BlOnRbZ3RdfX1jb25zdCBfdD0ic2VudHJ5LSIsdnQ9L15zZW50cnktLztmdW5jdGlvbiB3dCh0KXtjb25zdCBuPWZ1bmN0aW9uKHQpe2lmKCF0fHwhaih0KSYmIUFycmF5LmlzQXJyYXkodCkpcmV0dXJuO2lmKEFycmF5LmlzQXJyYXkodCkpcmV0dXJuIHQucmVkdWNlKCgodCxuKT0+e2NvbnN0IGU9U3Qobik7cmV0dXJuIE9iamVjdC5lbnRyaWVzKGUpLmZvckVhY2goKChbbixlXSk9Pnt0W25dPWV9KSksdH0pLHt9KTtyZXR1cm4gU3QodCl9KHQpO2lmKCFuKXJldHVybjtjb25zdCBlPU9iamVjdC5lbnRyaWVzKG4pLnJlZHVjZSgoKHQsW24sZV0pPT57aWYobi5tYXRjaCh2dCkpe3Rbbi5zbGljZShfdC5sZW5ndGgpXT1lfXJldHVybiB0fSkse30pO3JldHVybiBPYmplY3Qua2V5cyhlKS5sZW5ndGg+MD9lOnZvaWQgMH1mdW5jdGlvbiBTdCh0KXtyZXR1cm4gdC5zcGxpdCgiLCIpLm1hcCgodD0+dC5zcGxpdCgiPSIpLm1hcCgodD0+ZGVjb2RlVVJJQ29tcG9uZW50KHQudHJpbSgpKSkpKSkucmVkdWNlKCgodCxbbixlXSk9PihuJiZlJiYodFtuXT1lKSx0KSkse30pfWNvbnN0ICR0PTE7ZnVuY3Rpb24gRXQodCl7Y29uc3R7c3BhbklkOm4sdHJhY2VJZDplLGlzUmVtb3RlOnJ9PXQuc3BhbkNvbnRleHQoKSxvPXI/bjpUdCh0KS5wYXJlbnRfc3Bhbl9pZCxzPWJ0KHQpLnNjb3BlO3JldHVybiBMKHtwYXJlbnRfc3Bhbl9pZDpvLHNwYW5faWQ6cj9zPy5nZXRQcm9wYWdhdGlvbkNvbnRleHQoKS5wcm9wYWdhdGlvblNwYW5JZHx8cSgpOm4sdHJhY2VfaWQ6ZX0pfWZ1bmN0aW9uIHh0KHQpe3JldHVybiJudW1iZXIiPT10eXBlb2YgdD9OdCh0KTpBcnJheS5pc0FycmF5KHQpP3RbMF0rdFsxXS8xZTk6dCBpbnN0YW5jZW9mIERhdGU/TnQodC5nZXRUaW1lKCkpOlkoKX1mdW5jdGlvbiBOdCh0KXtyZXR1cm4gdD45OTk5OTk5OTk5P3QvMWUzOnR9ZnVuY3Rpb24gVHQodCl7aWYoZnVuY3Rpb24odCl7cmV0dXJuImZ1bmN0aW9uIj09dHlwZW9mIHQuZ2V0U3BhbkpTT059KHQpKXJldHVybiB0LmdldFNwYW5KU09OKCk7Y29uc3R7c3BhbklkOm4sdHJhY2VJZDplfT10LnNwYW5Db250ZXh0KCk7aWYoZnVuY3Rpb24odCl7Y29uc3Qgbj10O3JldHVybiEhKG4uYXR0cmlidXRlcyYmbi5zdGFydFRpbWUmJm4ubmFtZSYmbi5lbmRUaW1lJiZuLnN0YXR1cyl9KHQpKXtjb25zdHthdHRyaWJ1dGVzOnIsc3RhcnRUaW1lOm8sbmFtZTpzLGVuZFRpbWU6aSxwYXJlbnRTcGFuSWQ6YyxzdGF0dXM6dX09dDtyZXR1cm4gTCh7c3Bhbl9pZDpuLHRyYWNlX2lkOmUsZGF0YTpyLGRlc2NyaXB0aW9uOnMscGFyZW50X3NwYW5faWQ6YyxzdGFydF90aW1lc3RhbXA6eHQobyksdGltZXN0YW1wOnh0KGkpfHx2b2lkIDAsc3RhdHVzOkN0KHUpLG9wOnJbcHRdLG9yaWdpbjpyW2x0XX0pfXJldHVybntzcGFuX2lkOm4sdHJhY2VfaWQ6ZSxzdGFydF90aW1lc3RhbXA6MCxkYXRhOnt9fX1mdW5jdGlvbiBDdCh0KXtpZih0JiZ0LmNvZGUhPT1kdClyZXR1cm4gdC5jb2RlPT09bXQ/Im9rIjp0Lm1lc3NhZ2V8fCJ1bmtub3duX2Vycm9yIn1jb25zdCBqdD0iX3NlbnRyeVJvb3RTcGFuIjtmdW5jdGlvbiBSdCh0KXtyZXR1cm4gdFtqdF18fHR9Y29uc3QgT3Q9InByb2R1Y3Rpb24iLER0PSJfZnJvemVuRHNjIjtmdW5jdGlvbiBrdCh0KXtjb25zdCBuPWF0KCk7aWYoIW4pcmV0dXJue307Y29uc3QgZT1SdCh0KSxyPVR0KGUpLG89ci5kYXRhLHM9ZS5zcGFuQ29udGV4dCgpLnRyYWNlU3RhdGUsaT1zPy5nZXQoInNlbnRyeS5zYW1wbGVfcmF0ZSIpPz9vW2h0XTtmdW5jdGlvbiBjKHQpe3JldHVybiJudW1iZXIiIT10eXBlb2YgaSYmInN0cmluZyIhPXR5cGVvZiBpfHwodC5zYW1wbGVfcmF0ZT1gJHtpfWApLHR9Y29uc3QgdT1lW0R0XTtpZih1KXJldHVybiBjKHUpO2NvbnN0IGE9cz8uZ2V0KCJzZW50cnkuZHNjIiksZj1hJiZ3dChhKTtpZihmKXJldHVybiBjKGYpO2NvbnN0IGg9ZnVuY3Rpb24odCxuKXtjb25zdCBlPW4uZ2V0T3B0aW9ucygpLHtwdWJsaWNLZXk6cn09bi5nZXREc24oKXx8e30sbz1MKHtlbnZpcm9ubWVudDplLmVudmlyb25tZW50fHxPdCxyZWxlYXNlOmUucmVsZWFzZSxwdWJsaWNfa2V5OnIsdHJhY2VfaWQ6dH0pO3JldHVybiBuLmVtaXQoImNyZWF0ZURzYyIsbyksb30odC5zcGFuQ29udGV4dCgpLnRyYWNlSWQsbikscD1vW2Z0XSxsPXIuZGVzY3JpcHRpb247cmV0dXJuInVybCIhPT1wJiZsJiYoaC50cmFuc2FjdGlvbj1sKSxmdW5jdGlvbih0KXtpZigiYm9vbGVhbiI9PXR5cGVvZiBfX1NFTlRSWV9UUkFDSU5HX18mJiFfX1NFTlRSWV9UUkFDSU5HX18pcmV0dXJuITE7Y29uc3Qgbj1hdCgpLGU9bj8uZ2V0T3B0aW9ucygpO3JldHVybiEoIWV8fG51bGw9PWUudHJhY2VzU2FtcGxlUmF0ZSYmIWUudHJhY2VzU2FtcGxlcil9KCkmJihoLnNhbXBsZWQ9U3RyaW5nKGZ1bmN0aW9uKHQpe2NvbnN0e3RyYWNlRmxhZ3M6bn09dC5zcGFuQ29udGV4dCgpO3JldHVybiBuPT09JHR9KGUpKSxoLnNhbXBsZV9yYW5kPXM/LmdldCgic2VudHJ5LnNhbXBsZV9yYW5kIik/P2J0KGUpLnNjb3BlPy5nZXRQcm9wYWdhdGlvbkNvbnRleHQoKS5zYW1wbGVSYW5kLnRvU3RyaW5nKCkpLGMoaCksbi5lbWl0KCJjcmVhdGVEc2MiLGgsZSksaH1mdW5jdGlvbiBBdCh0LG49ITEpe2NvbnN0e2hvc3Q6ZSxwYXRoOnIscGFzczpvLHBvcnQ6cyxwcm9qZWN0SWQ6aSxwcm90b2NvbDpjLHB1YmxpY0tleTp1fT10O3JldHVybmAke2N9Oi8vJHt1fSR7biYmbz9gOiR7b31gOiIifUAke2V9JHtzP2A6JHtzfWA6IiJ9LyR7cj9gJHtyfS9gOnJ9JHtpfWB9ZnVuY3Rpb24gSXQodCxuPTEwMCxlPTEvMCl7dHJ5e3JldHVybiBQdCgiIix0LG4sZSl9Y2F0Y2godCl7cmV0dXJue0VSUk9SOmAqKm5vbi1zZXJpYWxpemFibGUqKiAoJHt0fSlgfX19ZnVuY3Rpb24gUHQodCxuLGU9MS8wLHI9MS8wLG89ZnVuY3Rpb24oKXtjb25zdCB0PW5ldyBXZWFrU2V0O2Z1bmN0aW9uIG4obil7cmV0dXJuISF0LmhhcyhuKXx8KHQuYWRkKG4pLCExKX1mdW5jdGlvbiBlKG4pe3QuZGVsZXRlKG4pfXJldHVybltuLGVdfSgpKXtjb25zdFtzLGldPW87aWYobnVsbD09bnx8WyJib29sZWFuIiwic3RyaW5nIl0uaW5jbHVkZXModHlwZW9mIG4pfHwibnVtYmVyIj09dHlwZW9mIG4mJk51bWJlci5pc0Zpbml0ZShuKSlyZXR1cm4gbjtjb25zdCBjPWZ1bmN0aW9uKHQsbil7dHJ5e2lmKCJkb21haW4iPT09dCYmbiYmIm9iamVjdCI9PXR5cGVvZiBuJiZuLkopcmV0dXJuIltEb21haW5dIjtpZigiZG9tYWluRW1pdHRlciI9PT10KXJldHVybiJbRG9tYWluRW1pdHRlcl0iO2lmKCJ1bmRlZmluZWQiIT10eXBlb2YgZ2xvYmFsJiZuPT09Z2xvYmFsKXJldHVybiJbR2xvYmFsXSI7aWYoInVuZGVmaW5lZCIhPXR5cGVvZiB3aW5kb3cmJm49PT13aW5kb3cpcmV0dXJuIltXaW5kb3ddIjtpZigidW5kZWZpbmVkIiE9dHlwZW9mIGRvY3VtZW50JiZuPT09ZG9jdW1lbnQpcmV0dXJuIltEb2N1bWVudF0iO2lmKCJvYmplY3QiPT10eXBlb2YoZT1uKSYmbnVsbCE9PWUmJihlLl9faXNWdWV8fGUuWSkpcmV0dXJuIltWdWVWaWV3TW9kZWxdIjtpZihmdW5jdGlvbih0KXtyZXR1cm4gUih0KSYmIm5hdGl2ZUV2ZW50ImluIHQmJiJwcmV2ZW50RGVmYXVsdCJpbiB0JiYic3RvcFByb3BhZ2F0aW9uImluIHR9KG4pKXJldHVybiJbU3ludGhldGljRXZlbnRdIjtpZigibnVtYmVyIj09dHlwZW9mIG4mJiFOdW1iZXIuaXNGaW5pdGUobikpcmV0dXJuYFske259XWA7aWYoImZ1bmN0aW9uIj09dHlwZW9mIG4pcmV0dXJuYFtGdW5jdGlvbjogJHtmdW5jdGlvbih0KXt0cnl7cmV0dXJuIHQmJiJmdW5jdGlvbiI9PXR5cGVvZiB0JiZ0Lm5hbWV8fE59Y2F0Y2godCl7cmV0dXJuIE59fShuKX1dYDtpZigic3ltYm9sIj09dHlwZW9mIG4pcmV0dXJuYFske1N0cmluZyhuKX1dYDtpZigiYmlnaW50Ij09dHlwZW9mIG4pcmV0dXJuYFtCaWdJbnQ6ICR7U3RyaW5nKG4pfV1gO2NvbnN0IHI9ZnVuY3Rpb24odCl7Y29uc3Qgbj1PYmplY3QuZ2V0UHJvdG90eXBlT2YodCk7cmV0dXJuIG4/bi5jb25zdHJ1Y3Rvci5uYW1lOiJudWxsIHByb3RvdHlwZSJ9KG4pO3JldHVybi9eSFRNTChcdyopRWxlbWVudCQvLnRlc3Qocik/YFtIVE1MRWxlbWVudDogJHtyfV1gOmBbb2JqZWN0ICR7cn1dYH1jYXRjaCh0KXtyZXR1cm5gKipub24tc2VyaWFsaXphYmxlKiogKCR7dH0pYH12YXIgZX0odCxuKTtpZighYy5zdGFydHNXaXRoKCJbb2JqZWN0ICIpKXJldHVybiBjO2lmKG4uX19zZW50cnlfc2tpcF9ub3JtYWxpemF0aW9uX18pcmV0dXJuIG47Y29uc3QgdT0ibnVtYmVyIj09dHlwZW9mIG4uX19zZW50cnlfb3ZlcnJpZGVfbm9ybWFsaXphdGlvbl9kZXB0aF9fP24uX19zZW50cnlfb3ZlcnJpZGVfbm9ybWFsaXphdGlvbl9kZXB0aF9fOmU7aWYoMD09PXUpcmV0dXJuIGMucmVwbGFjZSgib2JqZWN0ICIsIiIpO2lmKHMobikpcmV0dXJuIltDaXJjdWxhciB+XSI7Y29uc3QgYT1uO2lmKGEmJiJmdW5jdGlvbiI9PXR5cGVvZiBhLnRvSlNPTil0cnl7cmV0dXJuIFB0KCIiLGEudG9KU09OKCksdS0xLHIsbyl9Y2F0Y2godCl7fWNvbnN0IGY9QXJyYXkuaXNBcnJheShuKT9bXTp7fTtsZXQgaD0wO2NvbnN0IHA9UChuKTtmb3IoY29uc3QgdCBpbiBwKXtpZighT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKHAsdCkpY29udGludWU7aWYoaD49cil7Zlt0XT0iW01heFByb3BlcnRpZXMgfl0iO2JyZWFrfWNvbnN0IG49cFt0XTtmW3RdPVB0KHQsbix1LTEscixvKSxoKyt9cmV0dXJuIGkobiksZn1mdW5jdGlvbiBVdCh0LG4pe2NvbnN0IGU9bi5yZXBsYWNlKC9cXC9nLCIvIikucmVwbGFjZSgvW3xcXHt9KClbXF1eJCsqPy5dL2csIlxcJCYiKTtsZXQgcj10O3RyeXtyPWRlY29kZVVSSSh0KX1jYXRjaCh0KXt9cmV0dXJuIHIucmVwbGFjZSgvXFwvZywiLyIpLnJlcGxhY2UoL3dlYnBhY2s6XC8/L2csIiIpLnJlcGxhY2UobmV3IFJlZ0V4cChgKGZpbGU6Ly8pPy8qJHtlfS8qYCwiaWciKSwiYXBwOi8vLyIpfWZ1bmN0aW9uIE10KHQsbj1bXSl7cmV0dXJuW3Qsbl19ZnVuY3Rpb24gTHQodCxuKXtjb25zdCBlPXRbMV07Zm9yKGNvbnN0IHQgb2YgZSl7aWYobih0LHRbMF0udHlwZSkpcmV0dXJuITB9cmV0dXJuITF9ZnVuY3Rpb24gQnQodCl7Y29uc3Qgbj15KHApO3JldHVybiBuLmVuY29kZVBvbHlmaWxsP24uZW5jb2RlUG9seWZpbGwodCk6KG5ldyBUZXh0RW5jb2RlcikuZW5jb2RlKHQpfWZ1bmN0aW9uIEd0KHQpe2NvbnN0W24sZV09dDtsZXQgcj1KU09OLnN0cmluZ2lmeShuKTtmdW5jdGlvbiBvKHQpeyJzdHJpbmciPT10eXBlb2Ygcj9yPSJzdHJpbmciPT10eXBlb2YgdD9yK3Q6W0J0KHIpLHRdOnIucHVzaCgic3RyaW5nIj09dHlwZW9mIHQ/QnQodCk6dCl9Zm9yKGNvbnN0IHQgb2YgZSl7Y29uc3RbbixlXT10O2lmKG8oYFxuJHtKU09OLnN0cmluZ2lmeShuKX1cbmApLCJzdHJpbmciPT10eXBlb2YgZXx8ZSBpbnN0YW5jZW9mIFVpbnQ4QXJyYXkpbyhlKTtlbHNle2xldCB0O3RyeXt0PUpTT04uc3RyaW5naWZ5KGUpfWNhdGNoKG4pe3Q9SlNPTi5zdHJpbmdpZnkoSXQoZSkpfW8odCl9fXJldHVybiJzdHJpbmciPT10eXBlb2Ygcj9yOmZ1bmN0aW9uKHQpe2NvbnN0IG49dC5yZWR1Y2UoKCh0LG4pPT50K24ubGVuZ3RoKSwwKSxlPW5ldyBVaW50OEFycmF5KG4pO2xldCByPTA7Zm9yKGNvbnN0IG4gb2YgdCllLnNldChuLHIpLHIrPW4ubGVuZ3RoO3JldHVybiBlfShyKX1jb25zdCBKdD17c2Vzc2lvbjoic2Vzc2lvbiIsc2Vzc2lvbnM6InNlc3Npb24iLGF0dGFjaG1lbnQ6ImF0dGFjaG1lbnQiLHRyYW5zYWN0aW9uOiJ0cmFuc2FjdGlvbiIsZXZlbnQ6ImVycm9yIixjbGllbnRfcmVwb3J0OiJpbnRlcm5hbCIsdXNlcl9yZXBvcnQ6ImRlZmF1bHQiLHByb2ZpbGU6InByb2ZpbGUiLHByb2ZpbGVfY2h1bms6InByb2ZpbGUiLHJlcGxheV9ldmVudDoicmVwbGF5IixyZXBsYXlfcmVjb3JkaW5nOiJyZXBsYXkiLGNoZWNrX2luOiJtb25pdG9yIixmZWVkYmFjazoiZmVlZGJhY2siLHNwYW46InNwYW4iLHJhd19zZWN1cml0eToic2VjdXJpdHkifTtmdW5jdGlvbiBZdCh0KXtpZighdD8uc2RrKXJldHVybjtjb25zdHtuYW1lOm4sdmVyc2lvbjplfT10LnNkaztyZXR1cm57bmFtZTpuLHZlcnNpb246ZX19ZnVuY3Rpb24genQodCxuLGUscil7Y29uc3Qgbz1ZdChlKSxzPXQudHlwZSYmInJlcGxheV9ldmVudCIhPT10LnR5cGU/dC50eXBlOiJldmVudCI7IWZ1bmN0aW9uKHQsbil7biYmKHQuc2RrPXQuc2RrfHx7fSx0LnNkay5uYW1lPXQuc2RrLm5hbWV8fG4ubmFtZSx0LnNkay52ZXJzaW9uPXQuc2RrLnZlcnNpb258fG4udmVyc2lvbix0LnNkay5pbnRlZ3JhdGlvbnM9Wy4uLnQuc2RrLmludGVncmF0aW9uc3x8W10sLi4ubi5pbnRlZ3JhdGlvbnN8fFtdXSx0LnNkay5wYWNrYWdlcz1bLi4udC5zZGsucGFja2FnZXN8fFtdLC4uLm4ucGFja2FnZXN8fFtdXSl9KHQsZT8uc2RrKTtjb25zdCBpPWZ1bmN0aW9uKHQsbixlLHIpe2NvbnN0IG89dC5zZGtQcm9jZXNzaW5nTWV0YWRhdGE/LmR5bmFtaWNTYW1wbGluZ0NvbnRleHQ7cmV0dXJue2V2ZW50X2lkOnQuZXZlbnRfaWQsc2VudF9hdDoobmV3IERhdGUpLnRvSVNPU3RyaW5nKCksLi4ubiYme3NkazpufSwuLi4hIWUmJnImJntkc246QXQocil9LC4uLm8mJnt0cmFjZTpMKHsuLi5vfSl9fX0odCxvLHIsbik7ZGVsZXRlIHQuc2RrUHJvY2Vzc2luZ01ldGFkYXRhO3JldHVybiBNdChpLFtbe3R5cGU6c30sdF1dKX1jb25zdCBIdD0iX19TRU5UUllfU1VQUFJFU1NfVFJBQ0lOR19fIjtmdW5jdGlvbiBXdCh0KXtjb25zdCBuPXV0KG0oKSk7cmV0dXJuIG4uc3VwcHJlc3NUcmFjaW5nP24uc3VwcHJlc3NUcmFjaW5nKHQpOmZ1bmN0aW9uKC4uLnQpe2NvbnN0IG49dXQobSgpKTtpZigyPT09dC5sZW5ndGgpe2NvbnN0W2Uscl09dDtyZXR1cm4gZT9uLndpdGhTZXRTY29wZShlLHIpOm4ud2l0aFNjb3BlKHIpfXJldHVybiBuLndpdGhTY29wZSh0WzBdKX0oKG49PihuLnNldFNES1Byb2Nlc3NpbmdNZXRhZGF0YSh7W0h0XTohMH0pLHQoKSkpKX1mdW5jdGlvbiBGdCh0LG4pe2NvbnN0e2ZpbmdlcnByaW50OmUsc3BhbjpyLGJyZWFkY3J1bWJzOm8sc2RrUHJvY2Vzc2luZ01ldGFkYXRhOnN9PW47IWZ1bmN0aW9uKHQsbil7Y29uc3R7ZXh0cmE6ZSx0YWdzOnIsdXNlcjpvLGNvbnRleHRzOnMsbGV2ZWw6aSx0cmFuc2FjdGlvbk5hbWU6Y309bix1PUwoZSk7T2JqZWN0LmtleXModSkubGVuZ3RoJiYodC5leHRyYT17Li4udSwuLi50LmV4dHJhfSk7Y29uc3QgYT1MKHIpO09iamVjdC5rZXlzKGEpLmxlbmd0aCYmKHQudGFncz17Li4uYSwuLi50LnRhZ3N9KTtjb25zdCBmPUwobyk7T2JqZWN0LmtleXMoZikubGVuZ3RoJiYodC51c2VyPXsuLi5mLC4uLnQudXNlcn0pO2NvbnN0IGg9TChzKTtPYmplY3Qua2V5cyhoKS5sZW5ndGgmJih0LmNvbnRleHRzPXsuLi5oLC4uLnQuY29udGV4dHN9KTtpJiYodC5sZXZlbD1pKTtjJiYidHJhbnNhY3Rpb24iIT09dC50eXBlJiYodC50cmFuc2FjdGlvbj1jKX0odCxuKSxyJiZmdW5jdGlvbih0LG4pe3QuY29udGV4dHM9e3RyYWNlOkV0KG4pLC4uLnQuY29udGV4dHN9LHQuc2RrUHJvY2Vzc2luZ01ldGFkYXRhPXtkeW5hbWljU2FtcGxpbmdDb250ZXh0Omt0KG4pLC4uLnQuc2RrUHJvY2Vzc2luZ01ldGFkYXRhfTtjb25zdCBlPVJ0KG4pLHI9VHQoZSkuZGVzY3JpcHRpb247ciYmIXQudHJhbnNhY3Rpb24mJiJ0cmFuc2FjdGlvbiI9PT10LnR5cGUmJih0LnRyYW5zYWN0aW9uPXIpfSh0LHIpLGZ1bmN0aW9uKHQsbil7dC5maW5nZXJwcmludD10LmZpbmdlcnByaW50P0FycmF5LmlzQXJyYXkodC5maW5nZXJwcmludCk/dC5maW5nZXJwcmludDpbdC5maW5nZXJwcmludF06W10sbiYmKHQuZmluZ2VycHJpbnQ9dC5maW5nZXJwcmludC5jb25jYXQobikpO3QuZmluZ2VycHJpbnQubGVuZ3RofHxkZWxldGUgdC5maW5nZXJwcmludH0odCxlKSxmdW5jdGlvbih0LG4pe2NvbnN0IGU9Wy4uLnQuYnJlYWRjcnVtYnN8fFtdLC4uLm5dO3QuYnJlYWRjcnVtYnM9ZS5sZW5ndGg/ZTp2b2lkIDB9KHQsbyksZnVuY3Rpb24odCxuKXt0LnNka1Byb2Nlc3NpbmdNZXRhZGF0YT17Li4udC5zZGtQcm9jZXNzaW5nTWV0YWRhdGEsLi4ubn19KHQscyl9Y29uc3QgS3Q9IjciO2NsYXNzIFZ0IGV4dGVuZHMgRXJyb3J7Y29uc3RydWN0b3IodCxuPSJ3YXJuIil7c3VwZXIodCksdGhpcy5tZXNzYWdlPXQsdGhpcy5sb2dMZXZlbD1ufX1mdW5jdGlvbiBadCh0KXtjb25zdCBuPVtdO2Z1bmN0aW9uIGUodCl7cmV0dXJuIG4uc3BsaWNlKG4uaW5kZXhPZih0KSwxKVswXXx8UHJvbWlzZS5yZXNvbHZlKHZvaWQgMCl9cmV0dXJueyQ6bixhZGQ6ZnVuY3Rpb24ocil7aWYoISh2b2lkIDA9PT10fHxuLmxlbmd0aDx0KSlyZXR1cm4gbz1uZXcgVnQoIk5vdCBhZGRpbmcgUHJvbWlzZSBiZWNhdXNlIGJ1ZmZlciBsaW1pdCB3YXMgcmVhY2hlZC4iKSxuZXcgRigoKHQsbik9PntuKG8pfSkpO3ZhciBvO2NvbnN0IHM9cigpO3JldHVybi0xPT09bi5pbmRleE9mKHMpJiZuLnB1c2gocykscy50aGVuKCgoKT0+ZShzKSkpLnRoZW4obnVsbCwoKCk9PmUocykudGhlbihudWxsLCgoKT0+e30pKSkpLHN9LGRyYWluOmZ1bmN0aW9uKHQpe3JldHVybiBuZXcgRigoKGUscik9PntsZXQgbz1uLmxlbmd0aDtpZighbylyZXR1cm4gZSghMCk7Y29uc3Qgcz1zZXRUaW1lb3V0KCgoKT0+e3QmJnQ+MCYmZSghMSl9KSx0KTtuLmZvckVhY2goKHQ9PntXKHQpLnRoZW4oKCgpPT57LS1vfHwoY2xlYXJUaW1lb3V0KHMpLGUoITApKX0pLHIpfSkpfSkpfX19Y29uc3QgcXQ9NmU0O2Z1bmN0aW9uIFF0KHQse3N0YXR1c0NvZGU6bixoZWFkZXJzOmV9LHI9RGF0ZS5ub3coKSl7Y29uc3Qgbz17Li4udH0scz1lPy5bIngtc2VudHJ5LXJhdGUtbGltaXRzIl0saT1lPy5bInJldHJ5LWFmdGVyIl07aWYocylmb3IoY29uc3QgdCBvZiBzLnRyaW0oKS5zcGxpdCgiLCIpKXtjb25zdFtuLGUsLCxzXT10LnNwbGl0KCI6Iiw1KSxpPXBhcnNlSW50KG4sMTApLGM9MWUzKihpc05hTihpKT82MDppKTtpZihlKWZvcihjb25zdCB0IG9mIGUuc3BsaXQoIjsiKSkibWV0cmljX2J1Y2tldCI9PT10JiZzJiYhcy5zcGxpdCgiOyIpLmluY2x1ZGVzKCJjdXN0b20iKXx8KG9bdF09citjKTtlbHNlIG8uYWxsPXIrY31lbHNlIGk/by5hbGw9citmdW5jdGlvbih0LG49RGF0ZS5ub3coKSl7Y29uc3QgZT1wYXJzZUludChgJHt0fWAsMTApO2lmKCFpc05hTihlKSlyZXR1cm4gMWUzKmU7Y29uc3Qgcj1EYXRlLnBhcnNlKGAke3R9YCk7cmV0dXJuIGlzTmFOKHIpP3F0OnItbn0oaSxyKTo0Mjk9PT1uJiYoby5hbGw9cis2ZTQpO3JldHVybiBvfWNvbnN0IFh0PTY0O2Z1bmN0aW9uIHRuKHQsbixlPVp0KHQuYnVmZmVyU2l6ZXx8WHQpKXtsZXQgcj17fTtyZXR1cm57c2VuZDpmdW5jdGlvbih0KXtjb25zdCBvPVtdO2lmKEx0KHQsKCh0LG4pPT57Y29uc3QgZT1mdW5jdGlvbih0KXtyZXR1cm4gSnRbdF19KG4pOyhmdW5jdGlvbih0LG4sZT1EYXRlLm5vdygpKXtyZXR1cm4gZnVuY3Rpb24odCxuKXtyZXR1cm4gdFtuXXx8dC5hbGx8fDB9KHQsbik+ZX0pKHIsZSl8fG8ucHVzaCh0KX0pKSwwPT09by5sZW5ndGgpcmV0dXJuIFcoe30pO2NvbnN0IHM9TXQodFswXSxvKSxpPXQ9PntMdChzLCgodCxuKT0+e30pKX07cmV0dXJuIGUuYWRkKCgoKT0+bih7Ym9keTpHdChzKX0pLnRoZW4oKHQ9Pih2b2lkIDAhPT10LnN0YXR1c0NvZGUmJih0LnN0YXR1c0NvZGU8MjAwfHx0LnN0YXR1c0NvZGU+PTMwMCkmJmgmJncud2FybihgU2VudHJ5IHJlc3BvbmRlZCB3aXRoIHN0YXR1cyBjb2RlICR7dC5zdGF0dXNDb2RlfSB0byBzZW50IGV2ZW50LmApLHI9UXQocix0KSx0KSksKHQ9Pnt0aHJvdyBpKCksdH0pKSkpLnRoZW4oKHQ9PnQpLCh0PT57aWYodCBpbnN0YW5jZW9mIFZ0KXJldHVybiBoJiZ3LmVycm9yKCJTa2lwcGVkIHNlbmRpbmcgZXZlbnQgYmVjYXVzZSBidWZmZXIgaXMgZnVsbC4iKSxpKCksVyh7fSk7dGhyb3cgdH0pKX0sZmx1c2g6dD0+ZS5kcmFpbih0KX19Y29uc3Qgbm49L14oXFMrOlxcfFwvPykoW1xzXFNdKj8pKCg/OlwuezEsMn18W14vXFxdKz98KShcLlteLi9cXF0qfCkpKD86Wy9cXF0qKSQvO2Z1bmN0aW9uIGVuKHQpe2NvbnN0IG49ZnVuY3Rpb24odCl7Y29uc3Qgbj10Lmxlbmd0aD4xMDI0P2A8dHJ1bmNhdGVkPiR7dC5zbGljZSgtMTAyNCl9YDp0LGU9bm4uZXhlYyhuKTtyZXR1cm4gZT9lLnNsaWNlKDEpOltdfSh0KSxlPW5bMF18fCIiO2xldCByPW5bMV07cmV0dXJuIGV8fHI/KHImJihyPXIuc2xpY2UoMCxyLmxlbmd0aC0xKSksZStyKToiLiJ9ZnVuY3Rpb24gcm4odCxuPSExKXtyZXR1cm4hKG58fHQmJiF0LnN0YXJ0c1dpdGgoIi8iKSYmIXQubWF0Y2goL15bQS1aXTovKSYmIXQuc3RhcnRzV2l0aCgiLiIpJiYhdC5tYXRjaCgvXlthLXpBLVpdKFthLXpBLVowLTkuXC0rXSkqOlwvXC8vKSkmJnZvaWQgMCE9PXQmJiF0LmluY2x1ZGVzKCJub2RlX21vZHVsZXMvIil9Y29uc3Qgb249U3ltYm9sKCJBZ2VudEJhc2VJbnRlcm5hbFN0YXRlIik7Y2xhc3Mgc24gZXh0ZW5kcyBzLkFnZW50e2NvbnN0cnVjdG9yKHQpe3N1cGVyKHQpLHRoaXNbb25dPXt9fWlzU2VjdXJlRW5kcG9pbnQodCl7aWYodCl7aWYoImJvb2xlYW4iPT10eXBlb2YgdC5zZWN1cmVFbmRwb2ludClyZXR1cm4gdC5zZWN1cmVFbmRwb2ludDtpZigic3RyaW5nIj09dHlwZW9mIHQucHJvdG9jb2wpcmV0dXJuImh0dHBzOiI9PT10LnByb3RvY29sfWNvbnN0e3N0YWNrOm59PW5ldyBFcnJvcjtyZXR1cm4ic3RyaW5nIj09dHlwZW9mIG4mJm4uc3BsaXQoIlxuIikuc29tZSgodD0+LTEhPT10LmluZGV4T2YoIihodHRwcy5qczoiKXx8LTEhPT10LmluZGV4T2YoIm5vZGU6aHR0cHM6IikpKX1jcmVhdGVTb2NrZXQodCxuLGUpe2NvbnN0IHI9ey4uLm4sc2VjdXJlRW5kcG9pbnQ6dGhpcy5pc1NlY3VyZUVuZHBvaW50KG4pfTtQcm9taXNlLnJlc29sdmUoKS50aGVuKCgoKT0+dGhpcy5jb25uZWN0KHQscikpKS50aGVuKChvPT57aWYobyBpbnN0YW5jZW9mIHMuQWdlbnQpcmV0dXJuIG8uYWRkUmVxdWVzdCh0LHIpO3RoaXNbb25dLmN1cnJlbnRTb2NrZXQ9byxzdXBlci5jcmVhdGVTb2NrZXQodCxuLGUpfSksZSl9Y3JlYXRlQ29ubmVjdGlvbigpe2NvbnN0IHQ9dGhpc1tvbl0uY3VycmVudFNvY2tldDtpZih0aGlzW29uXS5jdXJyZW50U29ja2V0PXZvaWQgMCwhdCl0aHJvdyBuZXcgRXJyb3IoIk5vIHNvY2tldCB3YXMgcmV0dXJuZWQgaW4gdGhlIGBjb25uZWN0KClgIGZ1bmN0aW9uIik7cmV0dXJuIHR9Z2V0IGRlZmF1bHRQb3J0KCl7cmV0dXJuIHRoaXNbb25dLmRlZmF1bHRQb3J0Pz8oImh0dHBzOiI9PT10aGlzLnByb3RvY29sPzQ0Mzo4MCl9c2V0IGRlZmF1bHRQb3J0KHQpe3RoaXNbb25dJiYodGhpc1tvbl0uZGVmYXVsdFBvcnQ9dCl9Z2V0IHByb3RvY29sKCl7cmV0dXJuIHRoaXNbb25dLnByb3RvY29sPz8odGhpcy5pc1NlY3VyZUVuZHBvaW50KCk/Imh0dHBzOiI6Imh0dHA6Iil9c2V0IHByb3RvY29sKHQpe3RoaXNbb25dJiYodGhpc1tvbl0ucHJvdG9jb2w9dCl9fWZ1bmN0aW9uIGNuKC4uLnQpe3cubG9nKCJbaHR0cHMtcHJveHktYWdlbnQ6cGFyc2UtcHJveHktcmVzcG9uc2VdIiwuLi50KX1mdW5jdGlvbiB1bih0KXtyZXR1cm4gbmV3IFByb21pc2UoKChuLGUpPT57bGV0IHI9MDtjb25zdCBvPVtdO2Z1bmN0aW9uIHMoKXtjb25zdCBjPXQucmVhZCgpO2M/ZnVuY3Rpb24oYyl7by5wdXNoKGMpLHIrPWMubGVuZ3RoO2NvbnN0IHU9QnVmZmVyLmNvbmNhdChvLHIpLGE9dS5pbmRleE9mKCJcclxuXHJcbiIpO2lmKC0xPT09YSlyZXR1cm4gY24oImhhdmUgbm90IHJlY2VpdmVkIGVuZCBvZiBIVFRQIGhlYWRlcnMgeWV0Li4uIiksdm9pZCBzKCk7Y29uc3QgZj11LnN1YmFycmF5KDAsYSkudG9TdHJpbmcoImFzY2lpIikuc3BsaXQoIlxyXG4iKSxoPWYuc2hpZnQoKTtpZighaClyZXR1cm4gdC5kZXN0cm95KCksZShuZXcgRXJyb3IoIk5vIGhlYWRlciByZWNlaXZlZCBmcm9tIHByb3h5IENPTk5FQ1QgcmVzcG9uc2UiKSk7Y29uc3QgcD1oLnNwbGl0KCIgIiksbD0rKHBbMV18fDApLGQ9cC5zbGljZSgyKS5qb2luKCIgIiksbT17fTtmb3IoY29uc3QgbiBvZiBmKXtpZighbiljb250aW51ZTtjb25zdCByPW4uaW5kZXhPZigiOiIpO2lmKC0xPT09cilyZXR1cm4gdC5kZXN0cm95KCksZShuZXcgRXJyb3IoYEludmFsaWQgaGVhZGVyIGZyb20gcHJveHkgQ09OTkVDVCByZXNwb25zZTogIiR7bn0iYCkpO2NvbnN0IG89bi5zbGljZSgwLHIpLnRvTG93ZXJDYXNlKCkscz1uLnNsaWNlKHIrMSkudHJpbVN0YXJ0KCksaT1tW29dOyJzdHJpbmciPT10eXBlb2YgaT9tW29dPVtpLHNdOkFycmF5LmlzQXJyYXkoaSk/aS5wdXNoKHMpOm1bb109c31jbigiZ290IHByb3h5IHNlcnZlciByZXNwb25zZTogJW8gJW8iLGgsbSksaSgpLG4oe2Nvbm5lY3Q6e3N0YXR1c0NvZGU6bCxzdGF0dXNUZXh0OmQsaGVhZGVyczptfSxidWZmZXJlZDp1fSl9KGMpOnQub25jZSgicmVhZGFibGUiLHMpfWZ1bmN0aW9uIGkoKXt0LnJlbW92ZUxpc3RlbmVyKCJlbmQiLGMpLHQucmVtb3ZlTGlzdGVuZXIoImVycm9yIix1KSx0LnJlbW92ZUxpc3RlbmVyKCJyZWFkYWJsZSIscyl9ZnVuY3Rpb24gYygpe2koKSxjbigib25lbmQiKSxlKG5ldyBFcnJvcigiUHJveHkgY29ubmVjdGlvbiBlbmRlZCBiZWZvcmUgcmVjZWl2aW5nIENPTk5FQ1QgcmVzcG9uc2UiKSl9ZnVuY3Rpb24gdSh0KXtpKCksY24oIm9uZXJyb3IgJW8iLHQpLGUodCl9dC5vbigiZXJyb3IiLHUpLHQub24oImVuZCIsYykscygpfSkpfWZ1bmN0aW9uIGFuKC4uLnQpe3cubG9nKCJbaHR0cHMtcHJveHktYWdlbnRdIiwuLi50KX1jbGFzcyBmbiBleHRlbmRzIHNue3N0YXRpYyBfX2luaXRTdGF0aWMoKXt0aGlzLnByb3RvY29scz1bImh0dHAiLCJodHRwcyJdfWNvbnN0cnVjdG9yKHQsbil7c3VwZXIobiksdGhpcy5vcHRpb25zPXt9LHRoaXMucHJveHk9InN0cmluZyI9PXR5cGVvZiB0P25ldyBVUkwodCk6dCx0aGlzLnByb3h5SGVhZGVycz1uPy5oZWFkZXJzPz97fSxhbigiQ3JlYXRpbmcgbmV3IEh0dHBzUHJveHlBZ2VudCBpbnN0YW5jZTogJW8iLHRoaXMucHJveHkuaHJlZik7Y29uc3QgZT0odGhpcy5wcm94eS5ob3N0bmFtZXx8dGhpcy5wcm94eS5ob3N0KS5yZXBsYWNlKC9eXFt8XF0kL2csIiIpLHI9dGhpcy5wcm94eS5wb3J0P3BhcnNlSW50KHRoaXMucHJveHkucG9ydCwxMCk6Imh0dHBzOiI9PT10aGlzLnByb3h5LnByb3RvY29sPzQ0Mzo4MDt0aGlzLmNvbm5lY3RPcHRzPXtBTFBOUHJvdG9jb2xzOlsiaHR0cC8xLjEiXSwuLi5uP3BuKG4sImhlYWRlcnMiKTpudWxsLGhvc3Q6ZSxwb3J0OnJ9fWFzeW5jIGNvbm5lY3QodCxuKXtjb25zdHtwcm94eTplfT10aGlzO2lmKCFuLmhvc3QpdGhyb3cgbmV3IFR5cGVFcnJvcignTm8gImhvc3QiIHByb3ZpZGVkJyk7bGV0IHI7aWYoImh0dHBzOiI9PT1lLnByb3RvY29sKXthbigiQ3JlYXRpbmcgYHRscy5Tb2NrZXRgOiAlbyIsdGhpcy5jb25uZWN0T3B0cyk7Y29uc3QgdD10aGlzLmNvbm5lY3RPcHRzLnNlcnZlcm5hbWV8fHRoaXMuY29ubmVjdE9wdHMuaG9zdDtyPWYuY29ubmVjdCh7Li4udGhpcy5jb25uZWN0T3B0cyxzZXJ2ZXJuYW1lOnQmJmEuaXNJUCh0KT92b2lkIDA6dH0pfWVsc2UgYW4oIkNyZWF0aW5nIGBuZXQuU29ja2V0YDogJW8iLHRoaXMuY29ubmVjdE9wdHMpLHI9YS5jb25uZWN0KHRoaXMuY29ubmVjdE9wdHMpO2NvbnN0IG89ImZ1bmN0aW9uIj09dHlwZW9mIHRoaXMucHJveHlIZWFkZXJzP3RoaXMucHJveHlIZWFkZXJzKCk6ey4uLnRoaXMucHJveHlIZWFkZXJzfSxzPWEuaXNJUHY2KG4uaG9zdCk/YFske24uaG9zdH1dYDpuLmhvc3Q7bGV0IGk9YENPTk5FQ1QgJHtzfToke24ucG9ydH0gSFRUUC8xLjFcclxuYDtpZihlLnVzZXJuYW1lfHxlLnBhc3N3b3JkKXtjb25zdCB0PWAke2RlY29kZVVSSUNvbXBvbmVudChlLnVzZXJuYW1lKX06JHtkZWNvZGVVUklDb21wb25lbnQoZS5wYXNzd29yZCl9YDtvWyJQcm94eS1BdXRob3JpemF0aW9uIl09YEJhc2ljICR7QnVmZmVyLmZyb20odCkudG9TdHJpbmcoImJhc2U2NCIpfWB9by5Ib3N0PWAke3N9OiR7bi5wb3J0fWAsb1siUHJveHktQ29ubmVjdGlvbiJdfHwob1siUHJveHktQ29ubmVjdGlvbiJdPXRoaXMua2VlcEFsaXZlPyJLZWVwLUFsaXZlIjoiY2xvc2UiKTtmb3IoY29uc3QgdCBvZiBPYmplY3Qua2V5cyhvKSlpKz1gJHt0fTogJHtvW3RdfVxyXG5gO2NvbnN0IGM9dW4ocik7ci53cml0ZShgJHtpfVxyXG5gKTtjb25zdHtjb25uZWN0OnUsYnVmZmVyZWQ6aH09YXdhaXQgYztpZih0LmVtaXQoInByb3h5Q29ubmVjdCIsdSksdGhpcy5lbWl0KCJwcm94eUNvbm5lY3QiLHUsdCksMjAwPT09dS5zdGF0dXNDb2RlKXtpZih0Lm9uY2UoInNvY2tldCIsaG4pLG4uc2VjdXJlRW5kcG9pbnQpe2FuKCJVcGdyYWRpbmcgc29ja2V0IGNvbm5lY3Rpb24gdG8gVExTIik7Y29uc3QgdD1uLnNlcnZlcm5hbWV8fG4uaG9zdDtyZXR1cm4gZi5jb25uZWN0KHsuLi5wbihuLCJob3N0IiwicGF0aCIsInBvcnQiKSxzb2NrZXQ6cixzZXJ2ZXJuYW1lOmEuaXNJUCh0KT92b2lkIDA6dH0pfXJldHVybiByfXIuZGVzdHJveSgpO2NvbnN0IHA9bmV3IGEuU29ja2V0KHt3cml0YWJsZTohMX0pO3JldHVybiBwLnJlYWRhYmxlPSEwLHQub25jZSgic29ja2V0IiwodD0+e2FuKCJSZXBsYXlpbmcgcHJveHkgYnVmZmVyIGZvciBmYWlsZWQgcmVxdWVzdCIpLHQucHVzaChoKSx0LnB1c2gobnVsbCl9KSkscH19ZnVuY3Rpb24gaG4odCl7dC5yZXN1bWUoKX1mdW5jdGlvbiBwbih0LC4uLm4pe2NvbnN0IGU9e307bGV0IHI7Zm9yKHIgaW4gdCluLmluY2x1ZGVzKHIpfHwoZVtyXT10W3JdKTtyZXR1cm4gZX1mbi5fX2luaXRTdGF0aWMoKTtjb25zdCBsbj0zMjc2ODtmdW5jdGlvbiBkbih0KXtyZXR1cm4gdC5yZXBsYWNlKC9eW0EtWl06LywiIikucmVwbGFjZSgvXFwvZywiLyIpfWNvbnN0IG1uPWU7bGV0IHluLGduPTAsYm49e307ZnVuY3Rpb24gX24odCl7bW4uZGVidWcmJmNvbnNvbGUubG9nKGBbQU5SIFdvcmtlcl0gJHt0fWApfXZhciB2bix3bixTbjtjb25zdCAkbj1mdW5jdGlvbih0KXtsZXQgbjt0cnl7bj1uZXcgVVJMKHQudXJsKX1jYXRjaChuKXtyZXR1cm4gdigoKCk9Pntjb25zb2xlLndhcm4oIltAc2VudHJ5L25vZGVdOiBJbnZhbGlkIGRzbiBvciB0dW5uZWwgb3B0aW9uLCB3aWxsIG5vdCBzZW5kIGFueSBldmVudHMuIFRoZSB0dW5uZWwgb3B0aW9uIG11c3QgYmUgYSBmdWxsIFVSTCB3aGVuIHVzZWQuIil9KSksdG4odCwoKCk9PlByb21pc2UucmVzb2x2ZSh7fSkpKX1jb25zdCBlPSJodHRwczoiPT09bi5wcm90b2NvbCxyPWZ1bmN0aW9uKHQsbil7Y29uc3R7bm9fcHJveHk6ZX09cHJvY2Vzcy5lbnYscj1lPy5zcGxpdCgiLCIpLnNvbWUoKG49PnQuaG9zdC5lbmRzV2l0aChuKXx8dC5ob3N0bmFtZS5lbmRzV2l0aChuKSkpO3JldHVybiByP3ZvaWQgMDpufShuLHQucHJveHl8fChlP3Byb2Nlc3MuZW52Lmh0dHBzX3Byb3h5OnZvaWQgMCl8fHByb2Nlc3MuZW52Lmh0dHBfcHJveHkpLG89ZT9pOnMsYT12b2lkIDAhPT10LmtlZXBBbGl2ZSYmdC5rZWVwQWxpdmUsZj1yP25ldyBmbihyKTpuZXcgby5BZ2VudCh7a2VlcEFsaXZlOmEsbWF4U29ja2V0czozMCx0aW1lb3V0OjJlM30pLGg9ZnVuY3Rpb24odCxuLGUpe2NvbnN0e2hvc3RuYW1lOnIscGF0aG5hbWU6byxwb3J0OnMscHJvdG9jb2w6aSxzZWFyY2g6YX09bmV3IFVSTCh0LnVybCk7cmV0dXJuIGZ1bmN0aW9uKGYpe3JldHVybiBuZXcgUHJvbWlzZSgoKGgscCk9PntXdCgoKCk9PntsZXQgbD1mdW5jdGlvbih0KXtyZXR1cm4gbmV3IGMoe3JlYWQoKXt0aGlzLnB1c2godCksdGhpcy5wdXNoKG51bGwpfX0pfShmLmJvZHkpO2NvbnN0IGQ9ey4uLnQuaGVhZGVyc307Zi5ib2R5Lmxlbmd0aD5sbiYmKGRbImNvbnRlbnQtZW5jb2RpbmciXT0iZ3ppcCIsbD1sLnBpcGUodSgpKSk7Y29uc3QgbT1uLnJlcXVlc3Qoe21ldGhvZDoiUE9TVCIsYWdlbnQ6ZSxoZWFkZXJzOmQsaG9zdG5hbWU6cixwYXRoOmAke299JHthfWAscG9ydDpzLHByb3RvY29sOmksY2E6dC5jYUNlcnRzfSwodD0+e3Qub24oImRhdGEiLCgoKT0+e30pKSx0Lm9uKCJlbmQiLCgoKT0+e30pKSx0LnNldEVuY29kaW5nKCJ1dGY4Iik7Y29uc3Qgbj10LmhlYWRlcnNbInJldHJ5LWFmdGVyIl0/P251bGwsZT10LmhlYWRlcnNbIngtc2VudHJ5LXJhdGUtbGltaXRzIl0/P251bGw7aCh7c3RhdHVzQ29kZTp0LnN0YXR1c0NvZGUsaGVhZGVyczp7InJldHJ5LWFmdGVyIjpuLCJ4LXNlbnRyeS1yYXRlLWxpbWl0cyI6QXJyYXkuaXNBcnJheShlKT9lWzBdfHxudWxsOmV9fSl9KSk7bS5vbigiZXJyb3IiLHApLGwucGlwZShtKX0pKX0pKX19KHQsdC5odHRwTW9kdWxlPz9vLGYpO3JldHVybiB0bih0LGgpfSh7dXJsOih2bj1tbi5kc24sd249bW4udHVubmVsLFNuPW1uLnNka01ldGFkYXRhLnNkayx3bnx8YCR7ZnVuY3Rpb24odCl7cmV0dXJuYCR7ZnVuY3Rpb24odCl7Y29uc3Qgbj10LnByb3RvY29sP2Ake3QucHJvdG9jb2x9OmA6IiIsZT10LnBvcnQ/YDoke3QucG9ydH1gOiIiO3JldHVybmAke259Ly8ke3QuaG9zdH0ke2V9JHt0LnBhdGg/YC8ke3QucGF0aH1gOiIifS9hcGkvYH0odCl9JHt0LnByb2plY3RJZH0vZW52ZWxvcGUvYH0odm4pfT8ke2Z1bmN0aW9uKHQsbil7Y29uc3QgZT17c2VudHJ5X3ZlcnNpb246S3R9O3JldHVybiB0LnB1YmxpY0tleSYmKGUuc2VudHJ5X2tleT10LnB1YmxpY0tleSksbiYmKGUuc2VudHJ5X2NsaWVudD1gJHtuLm5hbWV9LyR7bi52ZXJzaW9ufWApLG5ldyBVUkxTZWFyY2hQYXJhbXMoZSkudG9TdHJpbmcoKX0odm4sU24pfWApLHJlY29yZERyb3BwZWRFdmVudDooKT0+e319KTthc3luYyBmdW5jdGlvbiBFbigpe2lmKHluKXtfbigiU2VuZGluZyBhYm5vcm1hbCBzZXNzaW9uIiksVih5bix7c3RhdHVzOiJhYm5vcm1hbCIsYWJub3JtYWxfbWVjaGFuaXNtOiJhbnJfZm9yZWdyb3VuZCIscmVsZWFzZTptbi5yZWxlYXNlLGVudmlyb25tZW50Om1uLmVudmlyb25tZW50fSk7Y29uc3QgdD1mdW5jdGlvbih0LG4sZSxyKXtjb25zdCBvPVl0KGUpO3JldHVybiBNdCh7c2VudF9hdDoobmV3IERhdGUpLnRvSVNPU3RyaW5nKCksLi4ubyYme3NkazpvfSwuLi4hIXImJm4mJntkc246QXQobil9fSxbImFnZ3JlZ2F0ZXMiaW4gdD9be3R5cGU6InNlc3Npb25zIn0sdF06W3t0eXBlOiJzZXNzaW9uIn0sdC50b0pTT04oKV1dKX0oeW4sbW4uZHNuLG1uLnNka01ldGFkYXRhLG1uLnR1bm5lbCk7X24oSlNPTi5zdHJpbmdpZnkodCkpLGF3YWl0ICRuLnNlbmQodCk7dHJ5e24/LnBvc3RNZXNzYWdlKCJzZXNzaW9uLWVuZGVkIil9Y2F0Y2godCl7fX19ZnVuY3Rpb24geG4odCl7aWYoIXQpcmV0dXJuO2NvbnN0IG49ZnVuY3Rpb24odCl7aWYoIXQubGVuZ3RoKXJldHVybltdO2NvbnN0IG49QXJyYXkuZnJvbSh0KTtyZXR1cm4vc2VudHJ5V3JhcHBlZC8udGVzdCh4KG4pLmZ1bmN0aW9ufHwiIikmJm4ucG9wKCksbi5yZXZlcnNlKCksRS50ZXN0KHgobikuZnVuY3Rpb258fCIiKSYmKG4ucG9wKCksRS50ZXN0KHgobikuZnVuY3Rpb258fCIiKSYmbi5wb3AoKSksbi5zbGljZSgwLFMpLm1hcCgodD0+KHsuLi50LGZpbGVuYW1lOnQuZmlsZW5hbWV8fHgobikuZmlsZW5hbWUsZnVuY3Rpb246dC5mdW5jdGlvbnx8JH0pKSl9KHQpO2lmKG1uLmFwcFJvb3RQYXRoKWZvcihjb25zdCB0IG9mIG4pdC5maWxlbmFtZSYmKHQuZmlsZW5hbWU9VXQodC5maWxlbmFtZSxtbi5hcHBSb290UGF0aCkpO3JldHVybiBufWFzeW5jIGZ1bmN0aW9uIE5uKHQsbil7aWYoZ24+PW1uLm1heEFuckV2ZW50cylyZXR1cm47Z24rPTEsYXdhaXQgRW4oKSxfbigiU2VuZGluZyBldmVudCIpO2NvbnN0IGU9e2V2ZW50X2lkOnooKSxjb250ZXh0czptbi5jb250ZXh0cyxyZWxlYXNlOm1uLnJlbGVhc2UsZW52aXJvbm1lbnQ6bW4uZW52aXJvbm1lbnQsZGlzdDptbi5kaXN0LHBsYXRmb3JtOiJub2RlIixsZXZlbDoiZXJyb3IiLGV4Y2VwdGlvbjp7dmFsdWVzOlt7dHlwZToiQXBwbGljYXRpb25Ob3RSZXNwb25kaW5nIix2YWx1ZTpgQXBwbGljYXRpb24gTm90IFJlc3BvbmRpbmcgZm9yIGF0IGxlYXN0ICR7bW4uYW5yVGhyZXNob2xkfSBtc2Asc3RhY2t0cmFjZTp7ZnJhbWVzOnhuKHQpfSxtZWNoYW5pc206e3R5cGU6IkFOUiJ9fV19LHRhZ3M6bW4uc3RhdGljVGFnc307biYmZnVuY3Rpb24odCxuKXtpZihGdCh0LG4pLCF0LmNvbnRleHRzPy50cmFjZSl7Y29uc3R7dHJhY2VJZDplLHBhcmVudFNwYW5JZDpyLHByb3BhZ2F0aW9uU3BhbklkOm99PW4ucHJvcGFnYXRpb25Db250ZXh0O3QuY29udGV4dHM9e3RyYWNlOnt0cmFjZV9pZDplLHNwYW5faWQ6b3x8cSgpLHBhcmVudF9zcGFuX2lkOnJ9LC4uLnQuY29udGV4dHN9fX0oZSxuKSxmdW5jdGlvbih0KXtpZigwPT09T2JqZWN0LmtleXMoYm4pLmxlbmd0aClyZXR1cm47Y29uc3Qgbj1tbi5hcHBSb290UGF0aD97fTpibjtpZihtbi5hcHBSb290UGF0aClmb3IoY29uc3RbdCxlXW9mIE9iamVjdC5lbnRyaWVzKGJuKSluW1V0KHQsbW4uYXBwUm9vdFBhdGgpXT1lO2NvbnN0IGU9bmV3IE1hcDtmb3IoY29uc3QgciBvZiB0LmV4Y2VwdGlvbj8udmFsdWVzfHxbXSlmb3IoY29uc3QgdCBvZiByLnN0YWNrdHJhY2U/LmZyYW1lc3x8W10pe2NvbnN0IHI9dC5hYnNfcGF0aHx8dC5maWxlbmFtZTtyJiZuW3JdJiZlLnNldChyLG5bcl0pfWlmKGUuc2l6ZT4wKXtjb25zdCBuPVtdO2Zvcihjb25zdFt0LHJdb2YgZS5lbnRyaWVzKCkpbi5wdXNoKHt0eXBlOiJzb3VyY2VtYXAiLGNvZGVfZmlsZTp0LGRlYnVnX2lkOnJ9KTt0LmRlYnVnX21ldGE9e2ltYWdlczpufX19KGUpO2NvbnN0IHI9enQoZSxtbi5kc24sbW4uc2RrTWV0YWRhdGEsbW4udHVubmVsKTtfbihKU09OLnN0cmluZ2lmeShyKSksYXdhaXQgJG4uc2VuZChyKSxhd2FpdCAkbi5mbHVzaCgyZTMpLGduPj1tbi5tYXhBbnJFdmVudHMmJnNldFRpbWVvdXQoKCgpPT57cHJvY2Vzcy5leGl0KDApfSksNWUzKX1sZXQgVG47aWYoX24oIlN0YXJ0ZWQiKSxtbi5jYXB0dXJlU3RhY2tUcmFjZSl7X24oIkNvbm5lY3RpbmcgdG8gZGVidWdnZXIiKTtjb25zdCBuPW5ldyB0O24uY29ubmVjdFRvTWFpblRocmVhZCgpLF9uKCJDb25uZWN0ZWQgdG8gZGVidWdnZXIiKTtjb25zdCBlPW5ldyBNYXA7bi5vbigiRGVidWdnZXIuc2NyaXB0UGFyc2VkIiwodD0+e2Uuc2V0KHQucGFyYW1zLnNjcmlwdElkLHQucGFyYW1zLnVybCl9KSksbi5vbigiRGVidWdnZXIucGF1c2VkIiwodD0+e2lmKCJvdGhlciI9PT10LnBhcmFtcy5yZWFzb24pdHJ5e19uKCJEZWJ1Z2dlciBwYXVzZWQiKTtjb25zdCBzPVsuLi50LnBhcmFtcy5jYWxsRnJhbWVzXSxpPW1uLmFwcFJvb3RQYXRoP2Z1bmN0aW9uKHQ9KHByb2Nlc3MuYXJndlsxXT9lbihwcm9jZXNzLmFyZ3ZbMV0pOnByb2Nlc3MuY3dkKCkpLG49IlxcIj09PW8pe2NvbnN0IGU9bj9kbih0KTp0O3JldHVybiB0PT57aWYoIXQpcmV0dXJuO2NvbnN0IG89bj9kbih0KTp0O2xldHtkaXI6cyxiYXNlOmksZXh0OmN9PXIucGFyc2Uobyk7Ii5qcyIhPT1jJiYiLm1qcyIhPT1jJiYiLmNqcyIhPT1jfHwoaT1pLnNsaWNlKDAsLTEqYy5sZW5ndGgpKTtjb25zdCB1PWRlY29kZVVSSUNvbXBvbmVudChpKTtzfHwocz0iLiIpO2NvbnN0IGE9cy5sYXN0SW5kZXhPZigiL25vZGVfbW9kdWxlcyIpO2lmKGE+LTEpcmV0dXJuYCR7cy5zbGljZShhKzE0KS5yZXBsYWNlKC9cLy9nLCIuIil9OiR7dX1gO2lmKHMuc3RhcnRzV2l0aChlKSl7Y29uc3QgdD1zLnNsaWNlKGUubGVuZ3RoKzEpLnJlcGxhY2UoL1wvL2csIi4iKTtyZXR1cm4gdD9gJHt0fToke3V9YDp1fXJldHVybiB1fX0obW4uYXBwUm9vdFBhdGgpOigpPT57fSxjPXMubWFwKCh0PT5mdW5jdGlvbih0LG4sZSl7Y29uc3Qgcj1uP24ucmVwbGFjZSgvXmZpbGU6XC9cLy8sIiIpOnZvaWQgMCxvPXQubG9jYXRpb24uY29sdW1uTnVtYmVyP3QubG9jYXRpb24uY29sdW1uTnVtYmVyKzE6dm9pZCAwLHM9dC5sb2NhdGlvbi5saW5lTnVtYmVyP3QubG9jYXRpb24ubGluZU51bWJlcisxOnZvaWQgMDtyZXR1cm4gTCh7ZmlsZW5hbWU6cixtb2R1bGU6ZShyKSxmdW5jdGlvbjp0LmZ1bmN0aW9uTmFtZXx8JCxjb2xubzpvLGxpbmVubzpzLGluX2FwcDpyP3JuKHIpOnZvaWQgMH0pfSh0LGUuZ2V0KHQubG9jYXRpb24uc2NyaXB0SWQpLGkpKSksdT1zZXRUaW1lb3V0KCgoKT0+e05uKGMpLnRoZW4obnVsbCwoKCk9PntfbigiU2VuZGluZyBBTlIgZXZlbnQgZmFpbGVkLiIpfSkpfSksNWUzKTtuLnBvc3QoIlJ1bnRpbWUuZXZhbHVhdGUiLHtleHByZXNzaW9uOiJnbG9iYWwuX19TRU5UUllfR0VUX1NDT1BFU19fKCk7IixzaWxlbnQ6ITAscmV0dXJuQnlWYWx1ZTohMH0sKCh0LGUpPT57dCYmX24oYEVycm9yIGV4ZWN1dGluZyBzY3JpcHQ6ICcke3QubWVzc2FnZX0nYCksY2xlYXJUaW1lb3V0KHUpO2NvbnN0IHI9ZT8ucmVzdWx0P2UucmVzdWx0LnZhbHVlOnZvaWQgMDtuLnBvc3QoIkRlYnVnZ2VyLnJlc3VtZSIpLG4ucG9zdCgiRGVidWdnZXIuZGlzYWJsZSIpLE5uKGMscikudGhlbihudWxsLCgoKT0+e19uKCJTZW5kaW5nIEFOUiBldmVudCBmYWlsZWQuIil9KSl9KSl9Y2F0Y2godCl7dGhyb3cgbi5wb3N0KCJEZWJ1Z2dlci5yZXN1bWUiKSxuLnBvc3QoIkRlYnVnZ2VyLmRpc2FibGUiKSx0fX0pKSxUbj0oKT0+e3RyeXtuLnBvc3QoIkRlYnVnZ2VyLmVuYWJsZSIsKCgpPT57bi5wb3N0KCJEZWJ1Z2dlci5wYXVzZSIpfSkpfWNhdGNoKHQpe319fWNvbnN0e3BvbGw6Q259PWZ1bmN0aW9uKHQsbixlLHIpe2NvbnN0IG89dCgpO2xldCBzPSExLGk9ITA7cmV0dXJuIHNldEludGVydmFsKCgoKT0+e2NvbnN0IHQ9by5nZXRUaW1lTXMoKTshMT09PXMmJnQ+bitlJiYocz0hMCxpJiZyKCkpLHQ8bitlJiYocz0hMSl9KSwyMCkse3BvbGw6KCk9PntvLnJlc2V0KCl9LGVuYWJsZWQ6dD0+e2k9dH19fSgoZnVuY3Rpb24oKXtsZXQgdD1wcm9jZXNzLmhydGltZSgpO3JldHVybntnZXRUaW1lTXM6KCk9Pntjb25zdFtuLGVdPXByb2Nlc3MuaHJ0aW1lKHQpO3JldHVybiBNYXRoLmZsb29yKDFlMypuK2UvMWU2KX0scmVzZXQ6KCk9Pnt0PXByb2Nlc3MuaHJ0aW1lKCl9fX0pLG1uLnBvbGxJbnRlcnZhbCxtbi5hbnJUaHJlc2hvbGQsKGZ1bmN0aW9uKCl7X24oIldhdGNoZG9nIHRpbWVvdXQiKSxUbj8oX24oIlBhdXNpbmcgZGVidWdnZXIgdG8gY2FwdHVyZSBzdGFjayB0cmFjZSIpLFRuKCkpOihfbigiQ2FwdHVyaW5nIGV2ZW50IHdpdGhvdXQgYSBzdGFjayB0cmFjZSIpLE5uKCkudGhlbihudWxsLCgoKT0+e19uKCJTZW5kaW5nIEFOUiBldmVudCBmYWlsZWQgb24gd2F0Y2hkb2cgdGltZW91dC4iKX0pKSl9KSk7bj8ub24oIm1lc3NhZ2UiLCh0PT57dC5zZXNzaW9uJiYoeW49Syh0LnNlc3Npb24pKSx0LmRlYnVnSW1hZ2VzJiYoYm49dC5kZWJ1Z0ltYWdlcyksQ24oKX0pKTs=';
12
+ const base64WorkerScript = 'LyohIEBzZW50cnkvbm9kZSA5LjAuMC1hbHBoYS4yICg3YTY4MTliKSB8IGh0dHBzOi8vZ2l0aHViLmNvbS9nZXRzZW50cnkvc2VudHJ5LWphdmFzY3JpcHQgKi8KaW1wb3J0e1Nlc3Npb24gYXMgdH1mcm9tIm5vZGU6aW5zcGVjdG9yIjtpbXBvcnR7cGFyZW50UG9ydCBhcyBuLHdvcmtlckRhdGEgYXMgZX1mcm9tIm5vZGU6d29ya2VyX3RocmVhZHMiO2ltcG9ydHtwb3NpeCBhcyByLHNlcCBhcyBvfWZyb20ibm9kZTpwYXRoIjtpbXBvcnQqYXMgcyBmcm9tIm5vZGU6aHR0cCI7aW1wb3J0KmFzIGkgZnJvbSJub2RlOmh0dHBzIjtpbXBvcnR7UmVhZGFibGUgYXMgY31mcm9tIm5vZGU6c3RyZWFtIjtpbXBvcnR7Y3JlYXRlR3ppcCBhcyB1fWZyb20ibm9kZTp6bGliIjtpbXBvcnQqYXMgYSBmcm9tIm5vZGU6bmV0IjtpbXBvcnQqYXMgZiBmcm9tIm5vZGU6dGxzIjtjb25zdCBoPSJ1bmRlZmluZWQiPT10eXBlb2YgX19TRU5UUllfREVCVUdfX3x8X19TRU5UUllfREVCVUdfXyxwPWdsb2JhbFRoaXMsbD0idW5kZWZpbmVkIj09dHlwZW9mIF9fU0VOVFJZX0RFQlVHX198fF9fU0VOVFJZX0RFQlVHX18sZD0iOS4wLjAtYWxwaGEuMiI7ZnVuY3Rpb24gbSgpe3JldHVybiB5KHApLHB9ZnVuY3Rpb24geSh0KXtjb25zdCBuPXQuX19TRU5UUllfXz10Ll9fU0VOVFJZX198fHt9O3JldHVybiBuLnZlcnNpb249bi52ZXJzaW9ufHxkLG5bZF09bltkXXx8e319ZnVuY3Rpb24gZyh0LG4sZT1wKXtjb25zdCByPWUuX19TRU5UUllfXz1lLl9fU0VOVFJZX198fHt9LG89cltkXT1yW2RdfHx7fTtyZXR1cm4gb1t0XXx8KG9bdF09bigpKX1jb25zdCBiPVsiZGVidWciLCJpbmZvIiwid2FybiIsImVycm9yIiwibG9nIiwiYXNzZXJ0IiwidHJhY2UiXSxfPXt9O2Z1bmN0aW9uIHYodCl7aWYoISgiY29uc29sZSJpbiBwKSlyZXR1cm4gdCgpO2NvbnN0IG49cC5jb25zb2xlLGU9e30scj1PYmplY3Qua2V5cyhfKTtyLmZvckVhY2goKHQ9Pntjb25zdCByPV9bdF07ZVt0XT1uW3RdLG5bdF09cn0pKTt0cnl7cmV0dXJuIHQoKX1maW5hbGx5e3IuZm9yRWFjaCgodD0+e25bdF09ZVt0XX0pKX19Y29uc3Qgdz1nKCJsb2dnZXIiLChmdW5jdGlvbigpe2xldCB0PSExO2NvbnN0IG49e2VuYWJsZTooKT0+e3Q9ITB9LGRpc2FibGU6KCk9Pnt0PSExfSxpc0VuYWJsZWQ6KCk9PnR9O3JldHVybiBsP2IuZm9yRWFjaCgoZT0+e25bZV09KC4uLm4pPT57dCYmdigoKCk9PntwLmNvbnNvbGVbZV0oYFNlbnRyeSBMb2dnZXIgWyR7ZX1dOmAsLi4ubil9KSl9fSkpOmIuZm9yRWFjaCgodD0+e25bdF09KCk9Pnt9fSkpLG59KSksUz01MCwkPSI/IixFPS9jYXB0dXJlTWVzc2FnZXxjYXB0dXJlRXhjZXB0aW9uLztmdW5jdGlvbiB4KHQpe3JldHVybiB0W3QubGVuZ3RoLTFdfHx7fX1jb25zdCBOPSI8YW5vbnltb3VzPiI7Y29uc3QgVD1PYmplY3QucHJvdG90eXBlLnRvU3RyaW5nO2Z1bmN0aW9uIEModCxuKXtyZXR1cm4gVC5jYWxsKHQpPT09YFtvYmplY3QgJHtufV1gfWZ1bmN0aW9uIGoodCl7cmV0dXJuIEModCwiU3RyaW5nIil9ZnVuY3Rpb24gUih0KXtyZXR1cm4gQyh0LCJPYmplY3QiKX1mdW5jdGlvbiBPKHQpe3JldHVybiBCb29sZWFuKHQ/LnRoZW4mJiJmdW5jdGlvbiI9PXR5cGVvZiB0LnRoZW4pfWZ1bmN0aW9uIEQodCxuKXt0cnl7cmV0dXJuIHQgaW5zdGFuY2VvZiBufWNhdGNoKHQpe3JldHVybiExfX1jb25zdCBrPXAsQT04MDtmdW5jdGlvbiBJKHQsbil7Y29uc3QgZT10LHI9W107aWYoIWU/LnRhZ05hbWUpcmV0dXJuIiI7aWYoay5IVE1MRWxlbWVudCYmZSBpbnN0YW5jZW9mIEhUTUxFbGVtZW50JiZlLmRhdGFzZXQpe2lmKGUuZGF0YXNldC5zZW50cnlDb21wb25lbnQpcmV0dXJuIGUuZGF0YXNldC5zZW50cnlDb21wb25lbnQ7aWYoZS5kYXRhc2V0LnNlbnRyeUVsZW1lbnQpcmV0dXJuIGUuZGF0YXNldC5zZW50cnlFbGVtZW50fXIucHVzaChlLnRhZ05hbWUudG9Mb3dlckNhc2UoKSk7Y29uc3Qgbz1uPy5sZW5ndGg/bi5maWx0ZXIoKHQ9PmUuZ2V0QXR0cmlidXRlKHQpKSkubWFwKCh0PT5bdCxlLmdldEF0dHJpYnV0ZSh0KV0pKTpudWxsO2lmKG8/Lmxlbmd0aClvLmZvckVhY2goKHQ9PntyLnB1c2goYFske3RbMF19PSIke3RbMV19Il1gKX0pKTtlbHNle2UuaWQmJnIucHVzaChgIyR7ZS5pZH1gKTtjb25zdCB0PWUuY2xhc3NOYW1lO2lmKHQmJmoodCkpe2NvbnN0IG49dC5zcGxpdCgvXHMrLyk7Zm9yKGNvbnN0IHQgb2YgbilyLnB1c2goYC4ke3R9YCl9fWNvbnN0IHM9WyJhcmlhLWxhYmVsIiwidHlwZSIsIm5hbWUiLCJ0aXRsZSIsImFsdCJdO2Zvcihjb25zdCB0IG9mIHMpe2NvbnN0IG49ZS5nZXRBdHRyaWJ1dGUodCk7biYmci5wdXNoKGBbJHt0fT0iJHtufSJdYCl9cmV0dXJuIHIuam9pbigiIil9ZnVuY3Rpb24gUCh0KXtpZihmdW5jdGlvbih0KXtzd2l0Y2goVC5jYWxsKHQpKXtjYXNlIltvYmplY3QgRXJyb3JdIjpjYXNlIltvYmplY3QgRXhjZXB0aW9uXSI6Y2FzZSJbb2JqZWN0IERPTUV4Y2VwdGlvbl0iOmNhc2UiW29iamVjdCBXZWJBc3NlbWJseS5FeGNlcHRpb25dIjpyZXR1cm4hMDtkZWZhdWx0OnJldHVybiBEKHQsRXJyb3IpfX0odCkpcmV0dXJue21lc3NhZ2U6dC5tZXNzYWdlLG5hbWU6dC5uYW1lLHN0YWNrOnQuc3RhY2ssLi4uTSh0KX07aWYobj10LCJ1bmRlZmluZWQiIT10eXBlb2YgRXZlbnQmJkQobixFdmVudCkpe2NvbnN0IG49e3R5cGU6dC50eXBlLHRhcmdldDpVKHQudGFyZ2V0KSxjdXJyZW50VGFyZ2V0OlUodC5jdXJyZW50VGFyZ2V0KSwuLi5NKHQpfTtyZXR1cm4idW5kZWZpbmVkIiE9dHlwZW9mIEN1c3RvbUV2ZW50JiZEKHQsQ3VzdG9tRXZlbnQpJiYobi5kZXRhaWw9dC5kZXRhaWwpLG59cmV0dXJuIHQ7dmFyIG59ZnVuY3Rpb24gVSh0KXt0cnl7cmV0dXJuIG49dCwidW5kZWZpbmVkIiE9dHlwZW9mIEVsZW1lbnQmJkQobixFbGVtZW50KT9mdW5jdGlvbih0LG49e30pe2lmKCF0KXJldHVybiI8dW5rbm93bj4iO3RyeXtsZXQgZT10O2NvbnN0IHI9NSxvPVtdO2xldCBzPTAsaT0wO2NvbnN0IGM9IiA+ICIsdT1jLmxlbmd0aDtsZXQgYTtjb25zdCBmPUFycmF5LmlzQXJyYXkobik/bjpuLmtleUF0dHJzLGg9IUFycmF5LmlzQXJyYXkobikmJm4ubWF4U3RyaW5nTGVuZ3RofHxBO2Zvcig7ZSYmcysrPHImJihhPUkoZSxmKSwhKCJodG1sIj09PWF8fHM+MSYmaStvLmxlbmd0aCp1K2EubGVuZ3RoPj1oKSk7KW8ucHVzaChhKSxpKz1hLmxlbmd0aCxlPWUucGFyZW50Tm9kZTtyZXR1cm4gby5yZXZlcnNlKCkuam9pbihjKX1jYXRjaCh0KXtyZXR1cm4iPHVua25vd24+In19KHQpOk9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbCh0KX1jYXRjaCh0KXtyZXR1cm4iPHVua25vd24+In12YXIgbn1mdW5jdGlvbiBNKHQpe2lmKCJvYmplY3QiPT10eXBlb2YgdCYmbnVsbCE9PXQpe2NvbnN0IG49e307Zm9yKGNvbnN0IGUgaW4gdClPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwodCxlKSYmKG5bZV09dFtlXSk7cmV0dXJuIG59cmV0dXJue319ZnVuY3Rpb24gTCh0KXtyZXR1cm4gQih0LG5ldyBNYXApfWZ1bmN0aW9uIEIodCxuKXtpZihmdW5jdGlvbih0KXtpZighUih0KSlyZXR1cm4hMTt0cnl7Y29uc3Qgbj1PYmplY3QuZ2V0UHJvdG90eXBlT2YodCkuY29uc3RydWN0b3IubmFtZTtyZXR1cm4hbnx8Ik9iamVjdCI9PT1ufWNhdGNoe3JldHVybiEwfX0odCkpe2NvbnN0IGU9bi5nZXQodCk7aWYodm9pZCAwIT09ZSlyZXR1cm4gZTtjb25zdCByPXt9O24uc2V0KHQscik7Zm9yKGNvbnN0IGUgb2YgT2JqZWN0LmdldE93blByb3BlcnR5TmFtZXModCkpdm9pZCAwIT09dFtlXSYmKHJbZV09Qih0W2VdLG4pKTtyZXR1cm4gcn1pZihBcnJheS5pc0FycmF5KHQpKXtjb25zdCBlPW4uZ2V0KHQpO2lmKHZvaWQgMCE9PWUpcmV0dXJuIGU7Y29uc3Qgcj1bXTtyZXR1cm4gbi5zZXQodCxyKSx0LmZvckVhY2goKHQ9PntyLnB1c2goQih0LG4pKX0pKSxyfXJldHVybiB0fWNvbnN0IEc9MWUzO2Z1bmN0aW9uIEooKXtyZXR1cm4gRGF0ZS5ub3coKS9HfWNvbnN0IFk9ZnVuY3Rpb24oKXtjb25zdHtwZXJmb3JtYW5jZTp0fT1wO2lmKCF0Py5ub3cpcmV0dXJuIEo7Y29uc3Qgbj1EYXRlLm5vdygpLXQubm93KCksZT1udWxsPT10LnRpbWVPcmlnaW4/bjp0LnRpbWVPcmlnaW47cmV0dXJuKCk9PihlK3Qubm93KCkpL0d9KCk7ZnVuY3Rpb24geigpe2NvbnN0IHQ9cCxuPXQuY3J5cHRvfHx0Lm1zQ3J5cHRvO2xldCBlPSgpPT4xNipNYXRoLnJhbmRvbSgpO3RyeXtpZihuPy5yYW5kb21VVUlEKXJldHVybiBuLnJhbmRvbVVVSUQoKS5yZXBsYWNlKC8tL2csIiIpO24/LmdldFJhbmRvbVZhbHVlcyYmKGU9KCk9Pntjb25zdCB0PW5ldyBVaW50OEFycmF5KDEpO3JldHVybiBuLmdldFJhbmRvbVZhbHVlcyh0KSx0WzBdfSl9Y2F0Y2godCl7fXJldHVybihbMWU3XSsxZTMrNGUzKzhlMysxZTExKS5yZXBsYWNlKC9bMDE4XS9nLCh0PT4odF4oMTUmZSgpKT4+dC80KS50b1N0cmluZygxNikpKX12YXIgSDtmdW5jdGlvbiBXKHQpe3JldHVybiBuZXcgRigobj0+e24odCl9KSl9IWZ1bmN0aW9uKHQpe3RbdC5QRU5ESU5HPTBdPSJQRU5ESU5HIjt0W3QuUkVTT0xWRUQ9MV09IlJFU09MVkVEIjt0W3QuUkVKRUNURUQ9Ml09IlJFSkVDVEVEIn0oSHx8KEg9e30pKTtjbGFzcyBGe2NvbnN0cnVjdG9yKHQpe3RoaXMudD1ILlBFTkRJTkcsdGhpcy5vPVtdLHRoaXMuaSh0KX10aGVuKHQsbil7cmV0dXJuIG5ldyBGKCgoZSxyKT0+e3RoaXMuby5wdXNoKFshMSxuPT57aWYodCl0cnl7ZSh0KG4pKX1jYXRjaCh0KXtyKHQpfWVsc2UgZShuKX0sdD0+e2lmKG4pdHJ5e2Uobih0KSl9Y2F0Y2godCl7cih0KX1lbHNlIHIodCl9XSksdGhpcy51KCl9KSl9Y2F0Y2godCl7cmV0dXJuIHRoaXMudGhlbigodD0+dCksdCl9ZmluYWxseSh0KXtyZXR1cm4gbmV3IEYoKChuLGUpPT57bGV0IHIsbztyZXR1cm4gdGhpcy50aGVuKChuPT57bz0hMSxyPW4sdCYmdCgpfSksKG49PntvPSEwLHI9bix0JiZ0KCl9KSkudGhlbigoKCk9PntvP2Uocik6bihyKX0pKX0pKX11KCl7aWYodGhpcy50PT09SC5QRU5ESU5HKXJldHVybjtjb25zdCB0PXRoaXMuby5zbGljZSgpO3RoaXMubz1bXSx0LmZvckVhY2goKHQ9Pnt0WzBdfHwodGhpcy50PT09SC5SRVNPTFZFRCYmdFsxXSh0aGlzLmgpLHRoaXMudD09PUguUkVKRUNURUQmJnRbMl0odGhpcy5oKSx0WzBdPSEwKX0pKX1pKHQpe2NvbnN0IG49KHQsbik9Pnt0aGlzLnQ9PT1ILlBFTkRJTkcmJihPKG4pP24udGhlbihlLHIpOih0aGlzLnQ9dCx0aGlzLmg9bix0aGlzLnUoKSkpfSxlPXQ9PntuKEguUkVTT0xWRUQsdCl9LHI9dD0+e24oSC5SRUpFQ1RFRCx0KX07dHJ5e3QoZSxyKX1jYXRjaCh0KXtyKHQpfX19ZnVuY3Rpb24gSyh0KXtjb25zdCBuPVkoKSxlPXtzaWQ6eigpLGluaXQ6ITAsdGltZXN0YW1wOm4sc3RhcnRlZDpuLGR1cmF0aW9uOjAsc3RhdHVzOiJvayIsZXJyb3JzOjAsaWdub3JlRHVyYXRpb246ITEsdG9KU09OOigpPT5mdW5jdGlvbih0KXtyZXR1cm4gTCh7c2lkOmAke3Quc2lkfWAsaW5pdDp0LmluaXQsc3RhcnRlZDpuZXcgRGF0ZSgxZTMqdC5zdGFydGVkKS50b0lTT1N0cmluZygpLHRpbWVzdGFtcDpuZXcgRGF0ZSgxZTMqdC50aW1lc3RhbXApLnRvSVNPU3RyaW5nKCksc3RhdHVzOnQuc3RhdHVzLGVycm9yczp0LmVycm9ycyxkaWQ6Im51bWJlciI9PXR5cGVvZiB0LmRpZHx8InN0cmluZyI9PXR5cGVvZiB0LmRpZD9gJHt0LmRpZH1gOnZvaWQgMCxkdXJhdGlvbjp0LmR1cmF0aW9uLGFibm9ybWFsX21lY2hhbmlzbTp0LmFibm9ybWFsX21lY2hhbmlzbSxhdHRyczp7cmVsZWFzZTp0LnJlbGVhc2UsZW52aXJvbm1lbnQ6dC5lbnZpcm9ubWVudCxpcF9hZGRyZXNzOnQuaXBBZGRyZXNzLHVzZXJfYWdlbnQ6dC51c2VyQWdlbnR9fSl9KGUpfTtyZXR1cm4gdCYmVihlLHQpLGV9ZnVuY3Rpb24gVih0LG49e30pe2lmKG4udXNlciYmKCF0LmlwQWRkcmVzcyYmbi51c2VyLmlwX2FkZHJlc3MmJih0LmlwQWRkcmVzcz1uLnVzZXIuaXBfYWRkcmVzcyksdC5kaWR8fG4uZGlkfHwodC5kaWQ9bi51c2VyLmlkfHxuLnVzZXIuZW1haWx8fG4udXNlci51c2VybmFtZSkpLHQudGltZXN0YW1wPW4udGltZXN0YW1wfHxZKCksbi5hYm5vcm1hbF9tZWNoYW5pc20mJih0LmFibm9ybWFsX21lY2hhbmlzbT1uLmFibm9ybWFsX21lY2hhbmlzbSksbi5pZ25vcmVEdXJhdGlvbiYmKHQuaWdub3JlRHVyYXRpb249bi5pZ25vcmVEdXJhdGlvbiksbi5zaWQmJih0LnNpZD0zMj09PW4uc2lkLmxlbmd0aD9uLnNpZDp6KCkpLHZvaWQgMCE9PW4uaW5pdCYmKHQuaW5pdD1uLmluaXQpLCF0LmRpZCYmbi5kaWQmJih0LmRpZD1gJHtuLmRpZH1gKSwibnVtYmVyIj09dHlwZW9mIG4uc3RhcnRlZCYmKHQuc3RhcnRlZD1uLnN0YXJ0ZWQpLHQuaWdub3JlRHVyYXRpb24pdC5kdXJhdGlvbj12b2lkIDA7ZWxzZSBpZigibnVtYmVyIj09dHlwZW9mIG4uZHVyYXRpb24pdC5kdXJhdGlvbj1uLmR1cmF0aW9uO2Vsc2V7Y29uc3Qgbj10LnRpbWVzdGFtcC10LnN0YXJ0ZWQ7dC5kdXJhdGlvbj1uPj0wP246MH1uLnJlbGVhc2UmJih0LnJlbGVhc2U9bi5yZWxlYXNlKSxuLmVudmlyb25tZW50JiYodC5lbnZpcm9ubWVudD1uLmVudmlyb25tZW50KSwhdC5pcEFkZHJlc3MmJm4uaXBBZGRyZXNzJiYodC5pcEFkZHJlc3M9bi5pcEFkZHJlc3MpLCF0LnVzZXJBZ2VudCYmbi51c2VyQWdlbnQmJih0LnVzZXJBZ2VudD1uLnVzZXJBZ2VudCksIm51bWJlciI9PXR5cGVvZiBuLmVycm9ycyYmKHQuZXJyb3JzPW4uZXJyb3JzKSxuLnN0YXR1cyYmKHQuc3RhdHVzPW4uc3RhdHVzKX1mdW5jdGlvbiBaKCl7cmV0dXJuIHooKX1mdW5jdGlvbiBxKCl7cmV0dXJuIHooKS5zdWJzdHJpbmcoMTYpfWZ1bmN0aW9uIFEodCxuLGU9Mil7aWYoIW58fCJvYmplY3QiIT10eXBlb2Ygbnx8ZTw9MClyZXR1cm4gbjtpZih0JiYwPT09T2JqZWN0LmtleXMobikubGVuZ3RoKXJldHVybiB0O2NvbnN0IHI9ey4uLnR9O2Zvcihjb25zdCB0IGluIG4pT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKG4sdCkmJihyW3RdPVEoclt0XSxuW3RdLGUtMSkpO3JldHVybiByfWNvbnN0IFg9Il9zZW50cnlTcGFuIjtmdW5jdGlvbiB0dCh0LG4pe24/ZnVuY3Rpb24odCxuLGUpe3RyeXtPYmplY3QuZGVmaW5lUHJvcGVydHkodCxuLHt2YWx1ZTplLHdyaXRhYmxlOiEwLGNvbmZpZ3VyYWJsZTohMH0pfWNhdGNoKGUpe2wmJncubG9nKGBGYWlsZWQgdG8gYWRkIG5vbi1lbnVtZXJhYmxlIHByb3BlcnR5ICIke259IiB0byBvYmplY3RgLHQpfX0odCxYLG4pOmRlbGV0ZSB0W1hdfWZ1bmN0aW9uIG50KHQpe3JldHVybiB0W1hdfWNsYXNzIGV0e2NvbnN0cnVjdG9yKCl7dGhpcy5wPSExLHRoaXMubD1bXSx0aGlzLm09W10sdGhpcy5fPVtdLHRoaXMudj1bXSx0aGlzLlM9e30sdGhpcy5OPXt9LHRoaXMuVD17fSx0aGlzLkM9e30sdGhpcy5qPXt9LHRoaXMuUj17dHJhY2VJZDpaKCksc2FtcGxlUmFuZDpNYXRoLnJhbmRvbSgpfX1jbG9uZSgpe2NvbnN0IHQ9bmV3IGV0O3JldHVybiB0Ll89Wy4uLnRoaXMuX10sdC5OPXsuLi50aGlzLk59LHQuVD17Li4udGhpcy5UfSx0LkM9ey4uLnRoaXMuQ30sdGhpcy5DLmZsYWdzJiYodC5DLmZsYWdzPXt2YWx1ZXM6Wy4uLnRoaXMuQy5mbGFncy52YWx1ZXNdfSksdC5TPXRoaXMuUyx0Lk89dGhpcy5PLHQuRD10aGlzLkQsdC5rPXRoaXMuayx0LkE9dGhpcy5BLHQubT1bLi4udGhpcy5tXSx0LnY9Wy4uLnRoaXMudl0sdC5qPXsuLi50aGlzLmp9LHQuUj17Li4udGhpcy5SfSx0Lkk9dGhpcy5JLHQuUD10aGlzLlAsdHQodCxudCh0aGlzKSksdH1zZXRDbGllbnQodCl7dGhpcy5JPXR9c2V0TGFzdEV2ZW50SWQodCl7dGhpcy5QPXR9Z2V0Q2xpZW50KCl7cmV0dXJuIHRoaXMuSX1sYXN0RXZlbnRJZCgpe3JldHVybiB0aGlzLlB9YWRkU2NvcGVMaXN0ZW5lcih0KXt0aGlzLmwucHVzaCh0KX1hZGRFdmVudFByb2Nlc3Nvcih0KXtyZXR1cm4gdGhpcy5tLnB1c2godCksdGhpc31zZXRVc2VyKHQpe3JldHVybiB0aGlzLlM9dHx8e2VtYWlsOnZvaWQgMCxpZDp2b2lkIDAsaXBfYWRkcmVzczp2b2lkIDAsdXNlcm5hbWU6dm9pZCAwfSx0aGlzLkQmJlYodGhpcy5ELHt1c2VyOnR9KSx0aGlzLlUoKSx0aGlzfWdldFVzZXIoKXtyZXR1cm4gdGhpcy5TfXNldFRhZ3ModCl7cmV0dXJuIHRoaXMuTj17Li4udGhpcy5OLC4uLnR9LHRoaXMuVSgpLHRoaXN9c2V0VGFnKHQsbil7cmV0dXJuIHRoaXMuTj17Li4udGhpcy5OLFt0XTpufSx0aGlzLlUoKSx0aGlzfXNldEV4dHJhcyh0KXtyZXR1cm4gdGhpcy5UPXsuLi50aGlzLlQsLi4udH0sdGhpcy5VKCksdGhpc31zZXRFeHRyYSh0LG4pe3JldHVybiB0aGlzLlQ9ey4uLnRoaXMuVCxbdF06bn0sdGhpcy5VKCksdGhpc31zZXRGaW5nZXJwcmludCh0KXtyZXR1cm4gdGhpcy5BPXQsdGhpcy5VKCksdGhpc31zZXRMZXZlbCh0KXtyZXR1cm4gdGhpcy5PPXQsdGhpcy5VKCksdGhpc31zZXRUcmFuc2FjdGlvbk5hbWUodCl7cmV0dXJuIHRoaXMuaz10LHRoaXMuVSgpLHRoaXN9c2V0Q29udGV4dCh0LG4pe3JldHVybiBudWxsPT09bj9kZWxldGUgdGhpcy5DW3RdOnRoaXMuQ1t0XT1uLHRoaXMuVSgpLHRoaXN9c2V0U2Vzc2lvbih0KXtyZXR1cm4gdD90aGlzLkQ9dDpkZWxldGUgdGhpcy5ELHRoaXMuVSgpLHRoaXN9Z2V0U2Vzc2lvbigpe3JldHVybiB0aGlzLkR9dXBkYXRlKHQpe2lmKCF0KXJldHVybiB0aGlzO2NvbnN0IG49ImZ1bmN0aW9uIj09dHlwZW9mIHQ/dCh0aGlzKTp0LGU9biBpbnN0YW5jZW9mIGV0P24uZ2V0U2NvcGVEYXRhKCk6UihuKT90OnZvaWQgMCx7dGFnczpyLGV4dHJhOm8sdXNlcjpzLGNvbnRleHRzOmksbGV2ZWw6YyxmaW5nZXJwcmludDp1PVtdLHByb3BhZ2F0aW9uQ29udGV4dDphfT1lfHx7fTtyZXR1cm4gdGhpcy5OPXsuLi50aGlzLk4sLi4ucn0sdGhpcy5UPXsuLi50aGlzLlQsLi4ub30sdGhpcy5DPXsuLi50aGlzLkMsLi4uaX0scyYmT2JqZWN0LmtleXMocykubGVuZ3RoJiYodGhpcy5TPXMpLGMmJih0aGlzLk89YyksdS5sZW5ndGgmJih0aGlzLkE9dSksYSYmKHRoaXMuUj1hKSx0aGlzfWNsZWFyKCl7cmV0dXJuIHRoaXMuXz1bXSx0aGlzLk49e30sdGhpcy5UPXt9LHRoaXMuUz17fSx0aGlzLkM9e30sdGhpcy5PPXZvaWQgMCx0aGlzLms9dm9pZCAwLHRoaXMuQT12b2lkIDAsdGhpcy5EPXZvaWQgMCx0dCh0aGlzLHZvaWQgMCksdGhpcy52PVtdLHRoaXMuc2V0UHJvcGFnYXRpb25Db250ZXh0KHt0cmFjZUlkOlooKSxzYW1wbGVSYW5kOk1hdGgucmFuZG9tKCl9KSx0aGlzLlUoKSx0aGlzfWFkZEJyZWFkY3J1bWIodCxuKXtjb25zdCBlPSJudW1iZXIiPT10eXBlb2Ygbj9uOjEwMDtpZihlPD0wKXJldHVybiB0aGlzO2NvbnN0IHI9e3RpbWVzdGFtcDpKKCksLi4udH07cmV0dXJuIHRoaXMuXy5wdXNoKHIpLHRoaXMuXy5sZW5ndGg+ZSYmKHRoaXMuXz10aGlzLl8uc2xpY2UoLWUpLHRoaXMuST8ucmVjb3JkRHJvcHBlZEV2ZW50KCJidWZmZXJfb3ZlcmZsb3ciLCJsb2dfaXRlbSIpKSx0aGlzLlUoKSx0aGlzfWdldExhc3RCcmVhZGNydW1iKCl7cmV0dXJuIHRoaXMuX1t0aGlzLl8ubGVuZ3RoLTFdfWNsZWFyQnJlYWRjcnVtYnMoKXtyZXR1cm4gdGhpcy5fPVtdLHRoaXMuVSgpLHRoaXN9YWRkQXR0YWNobWVudCh0KXtyZXR1cm4gdGhpcy52LnB1c2godCksdGhpc31jbGVhckF0dGFjaG1lbnRzKCl7cmV0dXJuIHRoaXMudj1bXSx0aGlzfWdldFNjb3BlRGF0YSgpe3JldHVybnticmVhZGNydW1iczp0aGlzLl8sYXR0YWNobWVudHM6dGhpcy52LGNvbnRleHRzOnRoaXMuQyx0YWdzOnRoaXMuTixleHRyYTp0aGlzLlQsdXNlcjp0aGlzLlMsbGV2ZWw6dGhpcy5PLGZpbmdlcnByaW50OnRoaXMuQXx8W10sZXZlbnRQcm9jZXNzb3JzOnRoaXMubSxwcm9wYWdhdGlvbkNvbnRleHQ6dGhpcy5SLHNka1Byb2Nlc3NpbmdNZXRhZGF0YTp0aGlzLmosdHJhbnNhY3Rpb25OYW1lOnRoaXMuayxzcGFuOm50KHRoaXMpfX1zZXRTREtQcm9jZXNzaW5nTWV0YWRhdGEodCl7cmV0dXJuIHRoaXMuaj1RKHRoaXMuaix0LDIpLHRoaXN9c2V0UHJvcGFnYXRpb25Db250ZXh0KHQpe3JldHVybiB0aGlzLlI9dCx0aGlzfWdldFByb3BhZ2F0aW9uQ29udGV4dCgpe3JldHVybiB0aGlzLlJ9Y2FwdHVyZUV4Y2VwdGlvbih0LG4pe2NvbnN0IGU9bj8uZXZlbnRfaWR8fHooKTtpZighdGhpcy5JKXJldHVybiB3Lndhcm4oIk5vIGNsaWVudCBjb25maWd1cmVkIG9uIHNjb3BlIC0gd2lsbCBub3QgY2FwdHVyZSBleGNlcHRpb24hIiksZTtjb25zdCByPW5ldyBFcnJvcigiU2VudHJ5IHN5bnRoZXRpY0V4Y2VwdGlvbiIpO3JldHVybiB0aGlzLkkuY2FwdHVyZUV4Y2VwdGlvbih0LHtvcmlnaW5hbEV4Y2VwdGlvbjp0LHN5bnRoZXRpY0V4Y2VwdGlvbjpyLC4uLm4sZXZlbnRfaWQ6ZX0sdGhpcyksZX1jYXB0dXJlTWVzc2FnZSh0LG4sZSl7Y29uc3Qgcj1lPy5ldmVudF9pZHx8eigpO2lmKCF0aGlzLkkpcmV0dXJuIHcud2FybigiTm8gY2xpZW50IGNvbmZpZ3VyZWQgb24gc2NvcGUgLSB3aWxsIG5vdCBjYXB0dXJlIG1lc3NhZ2UhIikscjtjb25zdCBvPW5ldyBFcnJvcih0KTtyZXR1cm4gdGhpcy5JLmNhcHR1cmVNZXNzYWdlKHQsbix7b3JpZ2luYWxFeGNlcHRpb246dCxzeW50aGV0aWNFeGNlcHRpb246bywuLi5lLGV2ZW50X2lkOnJ9LHRoaXMpLHJ9Y2FwdHVyZUV2ZW50KHQsbil7Y29uc3QgZT1uPy5ldmVudF9pZHx8eigpO3JldHVybiB0aGlzLkk/KHRoaXMuSS5jYXB0dXJlRXZlbnQodCx7Li4ubixldmVudF9pZDplfSx0aGlzKSxlKToody53YXJuKCJObyBjbGllbnQgY29uZmlndXJlZCBvbiBzY29wZSAtIHdpbGwgbm90IGNhcHR1cmUgZXZlbnQhIiksZSl9VSgpe3RoaXMucHx8KHRoaXMucD0hMCx0aGlzLmwuZm9yRWFjaCgodD0+e3QodGhpcyl9KSksdGhpcy5wPSExKX19Y2xhc3MgcnR7Y29uc3RydWN0b3IodCxuKXtsZXQgZSxyO2U9dHx8bmV3IGV0LHI9bnx8bmV3IGV0LHRoaXMuTT1be3Njb3BlOmV9XSx0aGlzLkw9cn13aXRoU2NvcGUodCl7Y29uc3Qgbj10aGlzLkIoKTtsZXQgZTt0cnl7ZT10KG4pfWNhdGNoKHQpe3Rocm93IHRoaXMuRygpLHR9cmV0dXJuIE8oZSk/ZS50aGVuKCh0PT4odGhpcy5HKCksdCkpLCh0PT57dGhyb3cgdGhpcy5HKCksdH0pKToodGhpcy5HKCksZSl9Z2V0Q2xpZW50KCl7cmV0dXJuIHRoaXMuZ2V0U3RhY2tUb3AoKS5jbGllbnR9Z2V0U2NvcGUoKXtyZXR1cm4gdGhpcy5nZXRTdGFja1RvcCgpLnNjb3BlfWdldElzb2xhdGlvblNjb3BlKCl7cmV0dXJuIHRoaXMuTH1nZXRTdGFja1RvcCgpe3JldHVybiB0aGlzLk1bdGhpcy5NLmxlbmd0aC0xXX1CKCl7Y29uc3QgdD10aGlzLmdldFNjb3BlKCkuY2xvbmUoKTtyZXR1cm4gdGhpcy5NLnB1c2goe2NsaWVudDp0aGlzLmdldENsaWVudCgpLHNjb3BlOnR9KSx0fUcoKXtyZXR1cm4hKHRoaXMuTS5sZW5ndGg8PTEpJiYhIXRoaXMuTS5wb3AoKX19ZnVuY3Rpb24gb3QoKXtjb25zdCB0PXkobSgpKTtyZXR1cm4gdC5zdGFjaz10LnN0YWNrfHxuZXcgcnQoZygiZGVmYXVsdEN1cnJlbnRTY29wZSIsKCgpPT5uZXcgZXQpKSxnKCJkZWZhdWx0SXNvbGF0aW9uU2NvcGUiLCgoKT0+bmV3IGV0KSkpfWZ1bmN0aW9uIHN0KHQpe3JldHVybiBvdCgpLndpdGhTY29wZSh0KX1mdW5jdGlvbiBpdCh0LG4pe2NvbnN0IGU9b3QoKTtyZXR1cm4gZS53aXRoU2NvcGUoKCgpPT4oZS5nZXRTdGFja1RvcCgpLnNjb3BlPXQsbih0KSkpKX1mdW5jdGlvbiBjdCh0KXtyZXR1cm4gb3QoKS53aXRoU2NvcGUoKCgpPT50KG90KCkuZ2V0SXNvbGF0aW9uU2NvcGUoKSkpKX1mdW5jdGlvbiB1dCh0KXtjb25zdCBuPXkodCk7cmV0dXJuIG4uYWNzP24uYWNzOnt3aXRoSXNvbGF0aW9uU2NvcGU6Y3Qsd2l0aFNjb3BlOnN0LHdpdGhTZXRTY29wZTppdCx3aXRoU2V0SXNvbGF0aW9uU2NvcGU6KHQsbik9PmN0KG4pLGdldEN1cnJlbnRTY29wZTooKT0+b3QoKS5nZXRTY29wZSgpLGdldElzb2xhdGlvblNjb3BlOigpPT5vdCgpLmdldElzb2xhdGlvblNjb3BlKCl9fWZ1bmN0aW9uIGF0KCl7cmV0dXJuIHV0KG0oKSkuZ2V0Q3VycmVudFNjb3BlKCkuZ2V0Q2xpZW50KCl9Y29uc3QgZnQ9InNlbnRyeS5zb3VyY2UiLGh0PSJzZW50cnkuc2FtcGxlX3JhdGUiLHB0PSJzZW50cnkub3AiLGx0PSJzZW50cnkub3JpZ2luIixkdD0wLG10PTEseXQ9Il9zZW50cnlTY29wZSIsZ3Q9Il9zZW50cnlJc29sYXRpb25TY29wZSI7ZnVuY3Rpb24gYnQodCl7cmV0dXJue3Njb3BlOnRbeXRdLGlzb2xhdGlvblNjb3BlOnRbZ3RdfX1jb25zdCBfdD0ic2VudHJ5LSIsdnQ9L15zZW50cnktLztmdW5jdGlvbiB3dCh0KXtjb25zdCBuPWZ1bmN0aW9uKHQpe2lmKCF0fHwhaih0KSYmIUFycmF5LmlzQXJyYXkodCkpcmV0dXJuO2lmKEFycmF5LmlzQXJyYXkodCkpcmV0dXJuIHQucmVkdWNlKCgodCxuKT0+e2NvbnN0IGU9U3Qobik7cmV0dXJuIE9iamVjdC5lbnRyaWVzKGUpLmZvckVhY2goKChbbixlXSk9Pnt0W25dPWV9KSksdH0pLHt9KTtyZXR1cm4gU3QodCl9KHQpO2lmKCFuKXJldHVybjtjb25zdCBlPU9iamVjdC5lbnRyaWVzKG4pLnJlZHVjZSgoKHQsW24sZV0pPT57aWYobi5tYXRjaCh2dCkpe3Rbbi5zbGljZShfdC5sZW5ndGgpXT1lfXJldHVybiB0fSkse30pO3JldHVybiBPYmplY3Qua2V5cyhlKS5sZW5ndGg+MD9lOnZvaWQgMH1mdW5jdGlvbiBTdCh0KXtyZXR1cm4gdC5zcGxpdCgiLCIpLm1hcCgodD0+dC5zcGxpdCgiPSIpLm1hcCgodD0+ZGVjb2RlVVJJQ29tcG9uZW50KHQudHJpbSgpKSkpKSkucmVkdWNlKCgodCxbbixlXSk9PihuJiZlJiYodFtuXT1lKSx0KSkse30pfWNvbnN0ICR0PTE7ZnVuY3Rpb24gRXQodCl7Y29uc3R7c3BhbklkOm4sdHJhY2VJZDplLGlzUmVtb3RlOnJ9PXQuc3BhbkNvbnRleHQoKSxvPXI/bjpUdCh0KS5wYXJlbnRfc3Bhbl9pZCxzPWJ0KHQpLnNjb3BlO3JldHVybiBMKHtwYXJlbnRfc3Bhbl9pZDpvLHNwYW5faWQ6cj9zPy5nZXRQcm9wYWdhdGlvbkNvbnRleHQoKS5wcm9wYWdhdGlvblNwYW5JZHx8cSgpOm4sdHJhY2VfaWQ6ZX0pfWZ1bmN0aW9uIHh0KHQpe3JldHVybiJudW1iZXIiPT10eXBlb2YgdD9OdCh0KTpBcnJheS5pc0FycmF5KHQpP3RbMF0rdFsxXS8xZTk6dCBpbnN0YW5jZW9mIERhdGU/TnQodC5nZXRUaW1lKCkpOlkoKX1mdW5jdGlvbiBOdCh0KXtyZXR1cm4gdD45OTk5OTk5OTk5P3QvMWUzOnR9ZnVuY3Rpb24gVHQodCl7aWYoZnVuY3Rpb24odCl7cmV0dXJuImZ1bmN0aW9uIj09dHlwZW9mIHQuZ2V0U3BhbkpTT059KHQpKXJldHVybiB0LmdldFNwYW5KU09OKCk7Y29uc3R7c3BhbklkOm4sdHJhY2VJZDplfT10LnNwYW5Db250ZXh0KCk7aWYoZnVuY3Rpb24odCl7Y29uc3Qgbj10O3JldHVybiEhKG4uYXR0cmlidXRlcyYmbi5zdGFydFRpbWUmJm4ubmFtZSYmbi5lbmRUaW1lJiZuLnN0YXR1cyl9KHQpKXtjb25zdHthdHRyaWJ1dGVzOnIsc3RhcnRUaW1lOm8sbmFtZTpzLGVuZFRpbWU6aSxwYXJlbnRTcGFuSWQ6YyxzdGF0dXM6dX09dDtyZXR1cm4gTCh7c3Bhbl9pZDpuLHRyYWNlX2lkOmUsZGF0YTpyLGRlc2NyaXB0aW9uOnMscGFyZW50X3NwYW5faWQ6YyxzdGFydF90aW1lc3RhbXA6eHQobyksdGltZXN0YW1wOnh0KGkpfHx2b2lkIDAsc3RhdHVzOkN0KHUpLG9wOnJbcHRdLG9yaWdpbjpyW2x0XX0pfXJldHVybntzcGFuX2lkOm4sdHJhY2VfaWQ6ZSxzdGFydF90aW1lc3RhbXA6MCxkYXRhOnt9fX1mdW5jdGlvbiBDdCh0KXtpZih0JiZ0LmNvZGUhPT1kdClyZXR1cm4gdC5jb2RlPT09bXQ/Im9rIjp0Lm1lc3NhZ2V8fCJ1bmtub3duX2Vycm9yIn1jb25zdCBqdD0iX3NlbnRyeVJvb3RTcGFuIjtmdW5jdGlvbiBSdCh0KXtyZXR1cm4gdFtqdF18fHR9Y29uc3QgT3Q9InByb2R1Y3Rpb24iLER0PSJfZnJvemVuRHNjIjtmdW5jdGlvbiBrdCh0KXtjb25zdCBuPWF0KCk7aWYoIW4pcmV0dXJue307Y29uc3QgZT1SdCh0KSxyPVR0KGUpLG89ci5kYXRhLHM9ZS5zcGFuQ29udGV4dCgpLnRyYWNlU3RhdGUsaT1zPy5nZXQoInNlbnRyeS5zYW1wbGVfcmF0ZSIpPz9vW2h0XTtmdW5jdGlvbiBjKHQpe3JldHVybiJudW1iZXIiIT10eXBlb2YgaSYmInN0cmluZyIhPXR5cGVvZiBpfHwodC5zYW1wbGVfcmF0ZT1gJHtpfWApLHR9Y29uc3QgdT1lW0R0XTtpZih1KXJldHVybiBjKHUpO2NvbnN0IGE9cz8uZ2V0KCJzZW50cnkuZHNjIiksZj1hJiZ3dChhKTtpZihmKXJldHVybiBjKGYpO2NvbnN0IGg9ZnVuY3Rpb24odCxuKXtjb25zdCBlPW4uZ2V0T3B0aW9ucygpLHtwdWJsaWNLZXk6cn09bi5nZXREc24oKXx8e30sbz1MKHtlbnZpcm9ubWVudDplLmVudmlyb25tZW50fHxPdCxyZWxlYXNlOmUucmVsZWFzZSxwdWJsaWNfa2V5OnIsdHJhY2VfaWQ6dH0pO3JldHVybiBuLmVtaXQoImNyZWF0ZURzYyIsbyksb30odC5zcGFuQ29udGV4dCgpLnRyYWNlSWQsbikscD1vW2Z0XSxsPXIuZGVzY3JpcHRpb247cmV0dXJuInVybCIhPT1wJiZsJiYoaC50cmFuc2FjdGlvbj1sKSxmdW5jdGlvbih0KXtpZigiYm9vbGVhbiI9PXR5cGVvZiBfX1NFTlRSWV9UUkFDSU5HX18mJiFfX1NFTlRSWV9UUkFDSU5HX18pcmV0dXJuITE7Y29uc3Qgbj10fHxhdCgpPy5nZXRPcHRpb25zKCk7cmV0dXJuISghbnx8bnVsbD09bi50cmFjZXNTYW1wbGVSYXRlJiYhbi50cmFjZXNTYW1wbGVyKX0oKSYmKGguc2FtcGxlZD1TdHJpbmcoZnVuY3Rpb24odCl7Y29uc3R7dHJhY2VGbGFnczpufT10LnNwYW5Db250ZXh0KCk7cmV0dXJuIG49PT0kdH0oZSkpLGguc2FtcGxlX3JhbmQ9cz8uZ2V0KCJzZW50cnkuc2FtcGxlX3JhbmQiKT8/YnQoZSkuc2NvcGU/LmdldFByb3BhZ2F0aW9uQ29udGV4dCgpLnNhbXBsZVJhbmQudG9TdHJpbmcoKSksYyhoKSxuLmVtaXQoImNyZWF0ZURzYyIsaCxlKSxofWZ1bmN0aW9uIEF0KHQsbj0hMSl7Y29uc3R7aG9zdDplLHBhdGg6cixwYXNzOm8scG9ydDpzLHByb2plY3RJZDppLHByb3RvY29sOmMscHVibGljS2V5OnV9PXQ7cmV0dXJuYCR7Y306Ly8ke3V9JHtuJiZvP2A6JHtvfWA6IiJ9QCR7ZX0ke3M/YDoke3N9YDoiIn0vJHtyP2Ake3J9L2A6cn0ke2l9YH1mdW5jdGlvbiBJdCh0LG49MTAwLGU9MS8wKXt0cnl7cmV0dXJuIFB0KCIiLHQsbixlKX1jYXRjaCh0KXtyZXR1cm57RVJST1I6YCoqbm9uLXNlcmlhbGl6YWJsZSoqICgke3R9KWB9fX1mdW5jdGlvbiBQdCh0LG4sZT0xLzAscj0xLzAsbz1mdW5jdGlvbigpe2NvbnN0IHQ9bmV3IFdlYWtTZXQ7ZnVuY3Rpb24gbihuKXtyZXR1cm4hIXQuaGFzKG4pfHwodC5hZGQobiksITEpfWZ1bmN0aW9uIGUobil7dC5kZWxldGUobil9cmV0dXJuW24sZV19KCkpe2NvbnN0W3MsaV09bztpZihudWxsPT1ufHxbImJvb2xlYW4iLCJzdHJpbmciXS5pbmNsdWRlcyh0eXBlb2Ygbil8fCJudW1iZXIiPT10eXBlb2YgbiYmTnVtYmVyLmlzRmluaXRlKG4pKXJldHVybiBuO2NvbnN0IGM9ZnVuY3Rpb24odCxuKXt0cnl7aWYoImRvbWFpbiI9PT10JiZuJiYib2JqZWN0Ij09dHlwZW9mIG4mJm4uSilyZXR1cm4iW0RvbWFpbl0iO2lmKCJkb21haW5FbWl0dGVyIj09PXQpcmV0dXJuIltEb21haW5FbWl0dGVyXSI7aWYoInVuZGVmaW5lZCIhPXR5cGVvZiBnbG9iYWwmJm49PT1nbG9iYWwpcmV0dXJuIltHbG9iYWxdIjtpZigidW5kZWZpbmVkIiE9dHlwZW9mIHdpbmRvdyYmbj09PXdpbmRvdylyZXR1cm4iW1dpbmRvd10iO2lmKCJ1bmRlZmluZWQiIT10eXBlb2YgZG9jdW1lbnQmJm49PT1kb2N1bWVudClyZXR1cm4iW0RvY3VtZW50XSI7aWYoIm9iamVjdCI9PXR5cGVvZihlPW4pJiZudWxsIT09ZSYmKGUuX19pc1Z1ZXx8ZS5ZKSlyZXR1cm4iW1Z1ZVZpZXdNb2RlbF0iO2lmKGZ1bmN0aW9uKHQpe3JldHVybiBSKHQpJiYibmF0aXZlRXZlbnQiaW4gdCYmInByZXZlbnREZWZhdWx0ImluIHQmJiJzdG9wUHJvcGFnYXRpb24iaW4gdH0obikpcmV0dXJuIltTeW50aGV0aWNFdmVudF0iO2lmKCJudW1iZXIiPT10eXBlb2YgbiYmIU51bWJlci5pc0Zpbml0ZShuKSlyZXR1cm5gWyR7bn1dYDtpZigiZnVuY3Rpb24iPT10eXBlb2YgbilyZXR1cm5gW0Z1bmN0aW9uOiAke2Z1bmN0aW9uKHQpe3RyeXtyZXR1cm4gdCYmImZ1bmN0aW9uIj09dHlwZW9mIHQmJnQubmFtZXx8Tn1jYXRjaCh0KXtyZXR1cm4gTn19KG4pfV1gO2lmKCJzeW1ib2wiPT10eXBlb2YgbilyZXR1cm5gWyR7U3RyaW5nKG4pfV1gO2lmKCJiaWdpbnQiPT10eXBlb2YgbilyZXR1cm5gW0JpZ0ludDogJHtTdHJpbmcobil9XWA7Y29uc3Qgcj1mdW5jdGlvbih0KXtjb25zdCBuPU9iamVjdC5nZXRQcm90b3R5cGVPZih0KTtyZXR1cm4gbj9uLmNvbnN0cnVjdG9yLm5hbWU6Im51bGwgcHJvdG90eXBlIn0obik7cmV0dXJuL15IVE1MKFx3KilFbGVtZW50JC8udGVzdChyKT9gW0hUTUxFbGVtZW50OiAke3J9XWA6YFtvYmplY3QgJHtyfV1gfWNhdGNoKHQpe3JldHVybmAqKm5vbi1zZXJpYWxpemFibGUqKiAoJHt0fSlgfXZhciBlfSh0LG4pO2lmKCFjLnN0YXJ0c1dpdGgoIltvYmplY3QgIikpcmV0dXJuIGM7aWYobi5fX3NlbnRyeV9za2lwX25vcm1hbGl6YXRpb25fXylyZXR1cm4gbjtjb25zdCB1PSJudW1iZXIiPT10eXBlb2Ygbi5fX3NlbnRyeV9vdmVycmlkZV9ub3JtYWxpemF0aW9uX2RlcHRoX18/bi5fX3NlbnRyeV9vdmVycmlkZV9ub3JtYWxpemF0aW9uX2RlcHRoX186ZTtpZigwPT09dSlyZXR1cm4gYy5yZXBsYWNlKCJvYmplY3QgIiwiIik7aWYocyhuKSlyZXR1cm4iW0NpcmN1bGFyIH5dIjtjb25zdCBhPW47aWYoYSYmImZ1bmN0aW9uIj09dHlwZW9mIGEudG9KU09OKXRyeXtyZXR1cm4gUHQoIiIsYS50b0pTT04oKSx1LTEscixvKX1jYXRjaCh0KXt9Y29uc3QgZj1BcnJheS5pc0FycmF5KG4pP1tdOnt9O2xldCBoPTA7Y29uc3QgcD1QKG4pO2Zvcihjb25zdCB0IGluIHApe2lmKCFPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwocCx0KSljb250aW51ZTtpZihoPj1yKXtmW3RdPSJbTWF4UHJvcGVydGllcyB+XSI7YnJlYWt9Y29uc3Qgbj1wW3RdO2ZbdF09UHQodCxuLHUtMSxyLG8pLGgrK31yZXR1cm4gaShuKSxmfWZ1bmN0aW9uIFV0KHQsbil7Y29uc3QgZT1uLnJlcGxhY2UoL1xcL2csIi8iKS5yZXBsYWNlKC9bfFxce30oKVtcXV4kKyo/Ll0vZywiXFwkJiIpO2xldCByPXQ7dHJ5e3I9ZGVjb2RlVVJJKHQpfWNhdGNoKHQpe31yZXR1cm4gci5yZXBsYWNlKC9cXC9nLCIvIikucmVwbGFjZSgvd2VicGFjazpcLz8vZywiIikucmVwbGFjZShuZXcgUmVnRXhwKGAoZmlsZTovLyk/Lyoke2V9LypgLCJpZyIpLCJhcHA6Ly8vIil9ZnVuY3Rpb24gTXQodCxuPVtdKXtyZXR1cm5bdCxuXX1mdW5jdGlvbiBMdCh0LG4pe2NvbnN0IGU9dFsxXTtmb3IoY29uc3QgdCBvZiBlKXtpZihuKHQsdFswXS50eXBlKSlyZXR1cm4hMH1yZXR1cm4hMX1mdW5jdGlvbiBCdCh0KXtjb25zdCBuPXkocCk7cmV0dXJuIG4uZW5jb2RlUG9seWZpbGw/bi5lbmNvZGVQb2x5ZmlsbCh0KToobmV3IFRleHRFbmNvZGVyKS5lbmNvZGUodCl9ZnVuY3Rpb24gR3QodCl7Y29uc3RbbixlXT10O2xldCByPUpTT04uc3RyaW5naWZ5KG4pO2Z1bmN0aW9uIG8odCl7InN0cmluZyI9PXR5cGVvZiByP3I9InN0cmluZyI9PXR5cGVvZiB0P3IrdDpbQnQociksdF06ci5wdXNoKCJzdHJpbmciPT10eXBlb2YgdD9CdCh0KTp0KX1mb3IoY29uc3QgdCBvZiBlKXtjb25zdFtuLGVdPXQ7aWYobyhgXG4ke0pTT04uc3RyaW5naWZ5KG4pfVxuYCksInN0cmluZyI9PXR5cGVvZiBlfHxlIGluc3RhbmNlb2YgVWludDhBcnJheSlvKGUpO2Vsc2V7bGV0IHQ7dHJ5e3Q9SlNPTi5zdHJpbmdpZnkoZSl9Y2F0Y2gobil7dD1KU09OLnN0cmluZ2lmeShJdChlKSl9byh0KX19cmV0dXJuInN0cmluZyI9PXR5cGVvZiByP3I6ZnVuY3Rpb24odCl7Y29uc3Qgbj10LnJlZHVjZSgoKHQsbik9PnQrbi5sZW5ndGgpLDApLGU9bmV3IFVpbnQ4QXJyYXkobik7bGV0IHI9MDtmb3IoY29uc3QgbiBvZiB0KWUuc2V0KG4scikscis9bi5sZW5ndGg7cmV0dXJuIGV9KHIpfWNvbnN0IEp0PXtzZXNzaW9uOiJzZXNzaW9uIixzZXNzaW9uczoic2Vzc2lvbiIsYXR0YWNobWVudDoiYXR0YWNobWVudCIsdHJhbnNhY3Rpb246InRyYW5zYWN0aW9uIixldmVudDoiZXJyb3IiLGNsaWVudF9yZXBvcnQ6ImludGVybmFsIix1c2VyX3JlcG9ydDoiZGVmYXVsdCIscHJvZmlsZToicHJvZmlsZSIscHJvZmlsZV9jaHVuazoicHJvZmlsZSIscmVwbGF5X2V2ZW50OiJyZXBsYXkiLHJlcGxheV9yZWNvcmRpbmc6InJlcGxheSIsY2hlY2tfaW46Im1vbml0b3IiLGZlZWRiYWNrOiJmZWVkYmFjayIsc3Bhbjoic3BhbiIscmF3X3NlY3VyaXR5OiJzZWN1cml0eSJ9O2Z1bmN0aW9uIFl0KHQpe2lmKCF0Py5zZGspcmV0dXJuO2NvbnN0e25hbWU6bix2ZXJzaW9uOmV9PXQuc2RrO3JldHVybntuYW1lOm4sdmVyc2lvbjplfX1mdW5jdGlvbiB6dCh0LG4sZSxyKXtjb25zdCBvPVl0KGUpLHM9dC50eXBlJiYicmVwbGF5X2V2ZW50IiE9PXQudHlwZT90LnR5cGU6ImV2ZW50IjshZnVuY3Rpb24odCxuKXtuJiYodC5zZGs9dC5zZGt8fHt9LHQuc2RrLm5hbWU9dC5zZGsubmFtZXx8bi5uYW1lLHQuc2RrLnZlcnNpb249dC5zZGsudmVyc2lvbnx8bi52ZXJzaW9uLHQuc2RrLmludGVncmF0aW9ucz1bLi4udC5zZGsuaW50ZWdyYXRpb25zfHxbXSwuLi5uLmludGVncmF0aW9uc3x8W11dLHQuc2RrLnBhY2thZ2VzPVsuLi50LnNkay5wYWNrYWdlc3x8W10sLi4ubi5wYWNrYWdlc3x8W11dKX0odCxlPy5zZGspO2NvbnN0IGk9ZnVuY3Rpb24odCxuLGUscil7Y29uc3Qgbz10LnNka1Byb2Nlc3NpbmdNZXRhZGF0YT8uZHluYW1pY1NhbXBsaW5nQ29udGV4dDtyZXR1cm57ZXZlbnRfaWQ6dC5ldmVudF9pZCxzZW50X2F0OihuZXcgRGF0ZSkudG9JU09TdHJpbmcoKSwuLi5uJiZ7c2RrOm59LC4uLiEhZSYmciYme2RzbjpBdChyKX0sLi4ubyYme3RyYWNlOkwoey4uLm99KX19fSh0LG8scixuKTtkZWxldGUgdC5zZGtQcm9jZXNzaW5nTWV0YWRhdGE7cmV0dXJuIE10KGksW1t7dHlwZTpzfSx0XV0pfWNvbnN0IEh0PSJfX1NFTlRSWV9TVVBQUkVTU19UUkFDSU5HX18iO2Z1bmN0aW9uIFd0KHQpe2NvbnN0IG49dXQobSgpKTtyZXR1cm4gbi5zdXBwcmVzc1RyYWNpbmc/bi5zdXBwcmVzc1RyYWNpbmcodCk6ZnVuY3Rpb24oLi4udCl7Y29uc3Qgbj11dChtKCkpO2lmKDI9PT10Lmxlbmd0aCl7Y29uc3RbZSxyXT10O3JldHVybiBlP24ud2l0aFNldFNjb3BlKGUscik6bi53aXRoU2NvcGUocil9cmV0dXJuIG4ud2l0aFNjb3BlKHRbMF0pfSgobj0+KG4uc2V0U0RLUHJvY2Vzc2luZ01ldGFkYXRhKHtbSHRdOiEwfSksdCgpKSkpfWZ1bmN0aW9uIEZ0KHQsbil7Y29uc3R7ZmluZ2VycHJpbnQ6ZSxzcGFuOnIsYnJlYWRjcnVtYnM6byxzZGtQcm9jZXNzaW5nTWV0YWRhdGE6c309bjshZnVuY3Rpb24odCxuKXtjb25zdHtleHRyYTplLHRhZ3M6cix1c2VyOm8sY29udGV4dHM6cyxsZXZlbDppLHRyYW5zYWN0aW9uTmFtZTpjfT1uLHU9TChlKTtPYmplY3Qua2V5cyh1KS5sZW5ndGgmJih0LmV4dHJhPXsuLi51LC4uLnQuZXh0cmF9KTtjb25zdCBhPUwocik7T2JqZWN0LmtleXMoYSkubGVuZ3RoJiYodC50YWdzPXsuLi5hLC4uLnQudGFnc30pO2NvbnN0IGY9TChvKTtPYmplY3Qua2V5cyhmKS5sZW5ndGgmJih0LnVzZXI9ey4uLmYsLi4udC51c2VyfSk7Y29uc3QgaD1MKHMpO09iamVjdC5rZXlzKGgpLmxlbmd0aCYmKHQuY29udGV4dHM9ey4uLmgsLi4udC5jb250ZXh0c30pO2kmJih0LmxldmVsPWkpO2MmJiJ0cmFuc2FjdGlvbiIhPT10LnR5cGUmJih0LnRyYW5zYWN0aW9uPWMpfSh0LG4pLHImJmZ1bmN0aW9uKHQsbil7dC5jb250ZXh0cz17dHJhY2U6RXQobiksLi4udC5jb250ZXh0c30sdC5zZGtQcm9jZXNzaW5nTWV0YWRhdGE9e2R5bmFtaWNTYW1wbGluZ0NvbnRleHQ6a3QobiksLi4udC5zZGtQcm9jZXNzaW5nTWV0YWRhdGF9O2NvbnN0IGU9UnQobikscj1UdChlKS5kZXNjcmlwdGlvbjtyJiYhdC50cmFuc2FjdGlvbiYmInRyYW5zYWN0aW9uIj09PXQudHlwZSYmKHQudHJhbnNhY3Rpb249cil9KHQsciksZnVuY3Rpb24odCxuKXt0LmZpbmdlcnByaW50PXQuZmluZ2VycHJpbnQ/QXJyYXkuaXNBcnJheSh0LmZpbmdlcnByaW50KT90LmZpbmdlcnByaW50Olt0LmZpbmdlcnByaW50XTpbXSxuJiYodC5maW5nZXJwcmludD10LmZpbmdlcnByaW50LmNvbmNhdChuKSk7dC5maW5nZXJwcmludC5sZW5ndGh8fGRlbGV0ZSB0LmZpbmdlcnByaW50fSh0LGUpLGZ1bmN0aW9uKHQsbil7Y29uc3QgZT1bLi4udC5icmVhZGNydW1ic3x8W10sLi4ubl07dC5icmVhZGNydW1icz1lLmxlbmd0aD9lOnZvaWQgMH0odCxvKSxmdW5jdGlvbih0LG4pe3Quc2RrUHJvY2Vzc2luZ01ldGFkYXRhPXsuLi50LnNka1Byb2Nlc3NpbmdNZXRhZGF0YSwuLi5ufX0odCxzKX1jb25zdCBLdD0iNyI7Y2xhc3MgVnQgZXh0ZW5kcyBFcnJvcntjb25zdHJ1Y3Rvcih0LG49Indhcm4iKXtzdXBlcih0KSx0aGlzLm1lc3NhZ2U9dCx0aGlzLmxvZ0xldmVsPW59fWZ1bmN0aW9uIFp0KHQpe2NvbnN0IG49W107ZnVuY3Rpb24gZSh0KXtyZXR1cm4gbi5zcGxpY2Uobi5pbmRleE9mKHQpLDEpWzBdfHxQcm9taXNlLnJlc29sdmUodm9pZCAwKX1yZXR1cm57JDpuLGFkZDpmdW5jdGlvbihyKXtpZighKHZvaWQgMD09PXR8fG4ubGVuZ3RoPHQpKXJldHVybiBvPW5ldyBWdCgiTm90IGFkZGluZyBQcm9taXNlIGJlY2F1c2UgYnVmZmVyIGxpbWl0IHdhcyByZWFjaGVkLiIpLG5ldyBGKCgodCxuKT0+e24obyl9KSk7dmFyIG87Y29uc3Qgcz1yKCk7cmV0dXJuLTE9PT1uLmluZGV4T2YocykmJm4ucHVzaChzKSxzLnRoZW4oKCgpPT5lKHMpKSkudGhlbihudWxsLCgoKT0+ZShzKS50aGVuKG51bGwsKCgpPT57fSkpKSksc30sZHJhaW46ZnVuY3Rpb24odCl7cmV0dXJuIG5ldyBGKCgoZSxyKT0+e2xldCBvPW4ubGVuZ3RoO2lmKCFvKXJldHVybiBlKCEwKTtjb25zdCBzPXNldFRpbWVvdXQoKCgpPT57dCYmdD4wJiZlKCExKX0pLHQpO24uZm9yRWFjaCgodD0+e1codCkudGhlbigoKCk9PnstLW98fChjbGVhclRpbWVvdXQocyksZSghMCkpfSkscil9KSl9KSl9fX1jb25zdCBxdD02ZTQ7ZnVuY3Rpb24gUXQodCx7c3RhdHVzQ29kZTpuLGhlYWRlcnM6ZX0scj1EYXRlLm5vdygpKXtjb25zdCBvPXsuLi50fSxzPWU/LlsieC1zZW50cnktcmF0ZS1saW1pdHMiXSxpPWU/LlsicmV0cnktYWZ0ZXIiXTtpZihzKWZvcihjb25zdCB0IG9mIHMudHJpbSgpLnNwbGl0KCIsIikpe2NvbnN0W24sZSwsLHNdPXQuc3BsaXQoIjoiLDUpLGk9cGFyc2VJbnQobiwxMCksYz0xZTMqKGlzTmFOKGkpPzYwOmkpO2lmKGUpZm9yKGNvbnN0IHQgb2YgZS5zcGxpdCgiOyIpKSJtZXRyaWNfYnVja2V0Ij09PXQmJnMmJiFzLnNwbGl0KCI7IikuaW5jbHVkZXMoImN1c3RvbSIpfHwob1t0XT1yK2MpO2Vsc2Ugby5hbGw9citjfWVsc2UgaT9vLmFsbD1yK2Z1bmN0aW9uKHQsbj1EYXRlLm5vdygpKXtjb25zdCBlPXBhcnNlSW50KGAke3R9YCwxMCk7aWYoIWlzTmFOKGUpKXJldHVybiAxZTMqZTtjb25zdCByPURhdGUucGFyc2UoYCR7dH1gKTtyZXR1cm4gaXNOYU4ocik/cXQ6ci1ufShpLHIpOjQyOT09PW4mJihvLmFsbD1yKzZlNCk7cmV0dXJuIG99Y29uc3QgWHQ9NjQ7ZnVuY3Rpb24gdG4odCxuLGU9WnQodC5idWZmZXJTaXplfHxYdCkpe2xldCByPXt9O3JldHVybntzZW5kOmZ1bmN0aW9uKHQpe2NvbnN0IG89W107aWYoTHQodCwoKHQsbik9Pntjb25zdCBlPWZ1bmN0aW9uKHQpe3JldHVybiBKdFt0XX0obik7KGZ1bmN0aW9uKHQsbixlPURhdGUubm93KCkpe3JldHVybiBmdW5jdGlvbih0LG4pe3JldHVybiB0W25dfHx0LmFsbHx8MH0odCxuKT5lfSkocixlKXx8by5wdXNoKHQpfSkpLDA9PT1vLmxlbmd0aClyZXR1cm4gVyh7fSk7Y29uc3Qgcz1NdCh0WzBdLG8pLGk9dD0+e0x0KHMsKCh0LG4pPT57fSkpfTtyZXR1cm4gZS5hZGQoKCgpPT5uKHtib2R5Okd0KHMpfSkudGhlbigodD0+KHZvaWQgMCE9PXQuc3RhdHVzQ29kZSYmKHQuc3RhdHVzQ29kZTwyMDB8fHQuc3RhdHVzQ29kZT49MzAwKSYmaCYmdy53YXJuKGBTZW50cnkgcmVzcG9uZGVkIHdpdGggc3RhdHVzIGNvZGUgJHt0LnN0YXR1c0NvZGV9IHRvIHNlbnQgZXZlbnQuYCkscj1RdChyLHQpLHQpKSwodD0+e3Rocm93IGkoKSx0fSkpKSkudGhlbigodD0+dCksKHQ9PntpZih0IGluc3RhbmNlb2YgVnQpcmV0dXJuIGgmJncuZXJyb3IoIlNraXBwZWQgc2VuZGluZyBldmVudCBiZWNhdXNlIGJ1ZmZlciBpcyBmdWxsLiIpLGkoKSxXKHt9KTt0aHJvdyB0fSkpfSxmbHVzaDp0PT5lLmRyYWluKHQpfX1jb25zdCBubj0vXihcUys6XFx8XC8/KShbXHNcU10qPykoKD86XC57MSwyfXxbXi9cXF0rP3wpKFwuW14uL1xcXSp8KSkoPzpbL1xcXSopJC87ZnVuY3Rpb24gZW4odCl7Y29uc3Qgbj1mdW5jdGlvbih0KXtjb25zdCBuPXQubGVuZ3RoPjEwMjQ/YDx0cnVuY2F0ZWQ+JHt0LnNsaWNlKC0xMDI0KX1gOnQsZT1ubi5leGVjKG4pO3JldHVybiBlP2Uuc2xpY2UoMSk6W119KHQpLGU9blswXXx8IiI7bGV0IHI9blsxXTtyZXR1cm4gZXx8cj8ociYmKHI9ci5zbGljZSgwLHIubGVuZ3RoLTEpKSxlK3IpOiIuIn1mdW5jdGlvbiBybih0LG49ITEpe3JldHVybiEobnx8dCYmIXQuc3RhcnRzV2l0aCgiLyIpJiYhdC5tYXRjaCgvXltBLVpdOi8pJiYhdC5zdGFydHNXaXRoKCIuIikmJiF0Lm1hdGNoKC9eW2EtekEtWl0oW2EtekEtWjAtOS5cLStdKSo6XC9cLy8pKSYmdm9pZCAwIT09dCYmIXQuaW5jbHVkZXMoIm5vZGVfbW9kdWxlcy8iKX1jb25zdCBvbj1TeW1ib2woIkFnZW50QmFzZUludGVybmFsU3RhdGUiKTtjbGFzcyBzbiBleHRlbmRzIHMuQWdlbnR7Y29uc3RydWN0b3IodCl7c3VwZXIodCksdGhpc1tvbl09e319aXNTZWN1cmVFbmRwb2ludCh0KXtpZih0KXtpZigiYm9vbGVhbiI9PXR5cGVvZiB0LnNlY3VyZUVuZHBvaW50KXJldHVybiB0LnNlY3VyZUVuZHBvaW50O2lmKCJzdHJpbmciPT10eXBlb2YgdC5wcm90b2NvbClyZXR1cm4iaHR0cHM6Ij09PXQucHJvdG9jb2x9Y29uc3R7c3RhY2s6bn09bmV3IEVycm9yO3JldHVybiJzdHJpbmciPT10eXBlb2YgbiYmbi5zcGxpdCgiXG4iKS5zb21lKCh0PT4tMSE9PXQuaW5kZXhPZigiKGh0dHBzLmpzOiIpfHwtMSE9PXQuaW5kZXhPZigibm9kZTpodHRwczoiKSkpfWNyZWF0ZVNvY2tldCh0LG4sZSl7Y29uc3Qgcj17Li4ubixzZWN1cmVFbmRwb2ludDp0aGlzLmlzU2VjdXJlRW5kcG9pbnQobil9O1Byb21pc2UucmVzb2x2ZSgpLnRoZW4oKCgpPT50aGlzLmNvbm5lY3QodCxyKSkpLnRoZW4oKG89PntpZihvIGluc3RhbmNlb2Ygcy5BZ2VudClyZXR1cm4gby5hZGRSZXF1ZXN0KHQscik7dGhpc1tvbl0uY3VycmVudFNvY2tldD1vLHN1cGVyLmNyZWF0ZVNvY2tldCh0LG4sZSl9KSxlKX1jcmVhdGVDb25uZWN0aW9uKCl7Y29uc3QgdD10aGlzW29uXS5jdXJyZW50U29ja2V0O2lmKHRoaXNbb25dLmN1cnJlbnRTb2NrZXQ9dm9pZCAwLCF0KXRocm93IG5ldyBFcnJvcigiTm8gc29ja2V0IHdhcyByZXR1cm5lZCBpbiB0aGUgYGNvbm5lY3QoKWAgZnVuY3Rpb24iKTtyZXR1cm4gdH1nZXQgZGVmYXVsdFBvcnQoKXtyZXR1cm4gdGhpc1tvbl0uZGVmYXVsdFBvcnQ/PygiaHR0cHM6Ij09PXRoaXMucHJvdG9jb2w/NDQzOjgwKX1zZXQgZGVmYXVsdFBvcnQodCl7dGhpc1tvbl0mJih0aGlzW29uXS5kZWZhdWx0UG9ydD10KX1nZXQgcHJvdG9jb2woKXtyZXR1cm4gdGhpc1tvbl0ucHJvdG9jb2w/Pyh0aGlzLmlzU2VjdXJlRW5kcG9pbnQoKT8iaHR0cHM6IjoiaHR0cDoiKX1zZXQgcHJvdG9jb2wodCl7dGhpc1tvbl0mJih0aGlzW29uXS5wcm90b2NvbD10KX19ZnVuY3Rpb24gY24oLi4udCl7dy5sb2coIltodHRwcy1wcm94eS1hZ2VudDpwYXJzZS1wcm94eS1yZXNwb25zZV0iLC4uLnQpfWZ1bmN0aW9uIHVuKHQpe3JldHVybiBuZXcgUHJvbWlzZSgoKG4sZSk9PntsZXQgcj0wO2NvbnN0IG89W107ZnVuY3Rpb24gcygpe2NvbnN0IGM9dC5yZWFkKCk7Yz9mdW5jdGlvbihjKXtvLnB1c2goYykscis9Yy5sZW5ndGg7Y29uc3QgdT1CdWZmZXIuY29uY2F0KG8sciksYT11LmluZGV4T2YoIlxyXG5cclxuIik7aWYoLTE9PT1hKXJldHVybiBjbigiaGF2ZSBub3QgcmVjZWl2ZWQgZW5kIG9mIEhUVFAgaGVhZGVycyB5ZXQuLi4iKSx2b2lkIHMoKTtjb25zdCBmPXUuc3ViYXJyYXkoMCxhKS50b1N0cmluZygiYXNjaWkiKS5zcGxpdCgiXHJcbiIpLGg9Zi5zaGlmdCgpO2lmKCFoKXJldHVybiB0LmRlc3Ryb3koKSxlKG5ldyBFcnJvcigiTm8gaGVhZGVyIHJlY2VpdmVkIGZyb20gcHJveHkgQ09OTkVDVCByZXNwb25zZSIpKTtjb25zdCBwPWguc3BsaXQoIiAiKSxsPSsocFsxXXx8MCksZD1wLnNsaWNlKDIpLmpvaW4oIiAiKSxtPXt9O2Zvcihjb25zdCBuIG9mIGYpe2lmKCFuKWNvbnRpbnVlO2NvbnN0IHI9bi5pbmRleE9mKCI6Iik7aWYoLTE9PT1yKXJldHVybiB0LmRlc3Ryb3koKSxlKG5ldyBFcnJvcihgSW52YWxpZCBoZWFkZXIgZnJvbSBwcm94eSBDT05ORUNUIHJlc3BvbnNlOiAiJHtufSJgKSk7Y29uc3Qgbz1uLnNsaWNlKDAscikudG9Mb3dlckNhc2UoKSxzPW4uc2xpY2UocisxKS50cmltU3RhcnQoKSxpPW1bb107InN0cmluZyI9PXR5cGVvZiBpP21bb109W2ksc106QXJyYXkuaXNBcnJheShpKT9pLnB1c2gocyk6bVtvXT1zfWNuKCJnb3QgcHJveHkgc2VydmVyIHJlc3BvbnNlOiAlbyAlbyIsaCxtKSxpKCksbih7Y29ubmVjdDp7c3RhdHVzQ29kZTpsLHN0YXR1c1RleHQ6ZCxoZWFkZXJzOm19LGJ1ZmZlcmVkOnV9KX0oYyk6dC5vbmNlKCJyZWFkYWJsZSIscyl9ZnVuY3Rpb24gaSgpe3QucmVtb3ZlTGlzdGVuZXIoImVuZCIsYyksdC5yZW1vdmVMaXN0ZW5lcigiZXJyb3IiLHUpLHQucmVtb3ZlTGlzdGVuZXIoInJlYWRhYmxlIixzKX1mdW5jdGlvbiBjKCl7aSgpLGNuKCJvbmVuZCIpLGUobmV3IEVycm9yKCJQcm94eSBjb25uZWN0aW9uIGVuZGVkIGJlZm9yZSByZWNlaXZpbmcgQ09OTkVDVCByZXNwb25zZSIpKX1mdW5jdGlvbiB1KHQpe2koKSxjbigib25lcnJvciAlbyIsdCksZSh0KX10Lm9uKCJlcnJvciIsdSksdC5vbigiZW5kIixjKSxzKCl9KSl9ZnVuY3Rpb24gYW4oLi4udCl7dy5sb2coIltodHRwcy1wcm94eS1hZ2VudF0iLC4uLnQpfWNsYXNzIGZuIGV4dGVuZHMgc257c3RhdGljIF9faW5pdFN0YXRpYygpe3RoaXMucHJvdG9jb2xzPVsiaHR0cCIsImh0dHBzIl19Y29uc3RydWN0b3IodCxuKXtzdXBlcihuKSx0aGlzLm9wdGlvbnM9e30sdGhpcy5wcm94eT0ic3RyaW5nIj09dHlwZW9mIHQ/bmV3IFVSTCh0KTp0LHRoaXMucHJveHlIZWFkZXJzPW4/LmhlYWRlcnM/P3t9LGFuKCJDcmVhdGluZyBuZXcgSHR0cHNQcm94eUFnZW50IGluc3RhbmNlOiAlbyIsdGhpcy5wcm94eS5ocmVmKTtjb25zdCBlPSh0aGlzLnByb3h5Lmhvc3RuYW1lfHx0aGlzLnByb3h5Lmhvc3QpLnJlcGxhY2UoL15cW3xcXSQvZywiIikscj10aGlzLnByb3h5LnBvcnQ/cGFyc2VJbnQodGhpcy5wcm94eS5wb3J0LDEwKToiaHR0cHM6Ij09PXRoaXMucHJveHkucHJvdG9jb2w/NDQzOjgwO3RoaXMuY29ubmVjdE9wdHM9e0FMUE5Qcm90b2NvbHM6WyJodHRwLzEuMSJdLC4uLm4/cG4obiwiaGVhZGVycyIpOm51bGwsaG9zdDplLHBvcnQ6cn19YXN5bmMgY29ubmVjdCh0LG4pe2NvbnN0e3Byb3h5OmV9PXRoaXM7aWYoIW4uaG9zdCl0aHJvdyBuZXcgVHlwZUVycm9yKCdObyAiaG9zdCIgcHJvdmlkZWQnKTtsZXQgcjtpZigiaHR0cHM6Ij09PWUucHJvdG9jb2wpe2FuKCJDcmVhdGluZyBgdGxzLlNvY2tldGA6ICVvIix0aGlzLmNvbm5lY3RPcHRzKTtjb25zdCB0PXRoaXMuY29ubmVjdE9wdHMuc2VydmVybmFtZXx8dGhpcy5jb25uZWN0T3B0cy5ob3N0O3I9Zi5jb25uZWN0KHsuLi50aGlzLmNvbm5lY3RPcHRzLHNlcnZlcm5hbWU6dCYmYS5pc0lQKHQpP3ZvaWQgMDp0fSl9ZWxzZSBhbigiQ3JlYXRpbmcgYG5ldC5Tb2NrZXRgOiAlbyIsdGhpcy5jb25uZWN0T3B0cykscj1hLmNvbm5lY3QodGhpcy5jb25uZWN0T3B0cyk7Y29uc3Qgbz0iZnVuY3Rpb24iPT10eXBlb2YgdGhpcy5wcm94eUhlYWRlcnM/dGhpcy5wcm94eUhlYWRlcnMoKTp7Li4udGhpcy5wcm94eUhlYWRlcnN9LHM9YS5pc0lQdjYobi5ob3N0KT9gWyR7bi5ob3N0fV1gOm4uaG9zdDtsZXQgaT1gQ09OTkVDVCAke3N9OiR7bi5wb3J0fSBIVFRQLzEuMVxyXG5gO2lmKGUudXNlcm5hbWV8fGUucGFzc3dvcmQpe2NvbnN0IHQ9YCR7ZGVjb2RlVVJJQ29tcG9uZW50KGUudXNlcm5hbWUpfToke2RlY29kZVVSSUNvbXBvbmVudChlLnBhc3N3b3JkKX1gO29bIlByb3h5LUF1dGhvcml6YXRpb24iXT1gQmFzaWMgJHtCdWZmZXIuZnJvbSh0KS50b1N0cmluZygiYmFzZTY0Iil9YH1vLkhvc3Q9YCR7c306JHtuLnBvcnR9YCxvWyJQcm94eS1Db25uZWN0aW9uIl18fChvWyJQcm94eS1Db25uZWN0aW9uIl09dGhpcy5rZWVwQWxpdmU/IktlZXAtQWxpdmUiOiJjbG9zZSIpO2Zvcihjb25zdCB0IG9mIE9iamVjdC5rZXlzKG8pKWkrPWAke3R9OiAke29bdF19XHJcbmA7Y29uc3QgYz11bihyKTtyLndyaXRlKGAke2l9XHJcbmApO2NvbnN0e2Nvbm5lY3Q6dSxidWZmZXJlZDpofT1hd2FpdCBjO2lmKHQuZW1pdCgicHJveHlDb25uZWN0Iix1KSx0aGlzLmVtaXQoInByb3h5Q29ubmVjdCIsdSx0KSwyMDA9PT11LnN0YXR1c0NvZGUpe2lmKHQub25jZSgic29ja2V0Iixobiksbi5zZWN1cmVFbmRwb2ludCl7YW4oIlVwZ3JhZGluZyBzb2NrZXQgY29ubmVjdGlvbiB0byBUTFMiKTtjb25zdCB0PW4uc2VydmVybmFtZXx8bi5ob3N0O3JldHVybiBmLmNvbm5lY3Qoey4uLnBuKG4sImhvc3QiLCJwYXRoIiwicG9ydCIpLHNvY2tldDpyLHNlcnZlcm5hbWU6YS5pc0lQKHQpP3ZvaWQgMDp0fSl9cmV0dXJuIHJ9ci5kZXN0cm95KCk7Y29uc3QgcD1uZXcgYS5Tb2NrZXQoe3dyaXRhYmxlOiExfSk7cmV0dXJuIHAucmVhZGFibGU9ITAsdC5vbmNlKCJzb2NrZXQiLCh0PT57YW4oIlJlcGxheWluZyBwcm94eSBidWZmZXIgZm9yIGZhaWxlZCByZXF1ZXN0IiksdC5wdXNoKGgpLHQucHVzaChudWxsKX0pKSxwfX1mdW5jdGlvbiBobih0KXt0LnJlc3VtZSgpfWZ1bmN0aW9uIHBuKHQsLi4ubil7Y29uc3QgZT17fTtsZXQgcjtmb3IociBpbiB0KW4uaW5jbHVkZXMocil8fChlW3JdPXRbcl0pO3JldHVybiBlfWZuLl9faW5pdFN0YXRpYygpO2NvbnN0IGxuPTMyNzY4O2Z1bmN0aW9uIGRuKHQpe3JldHVybiB0LnJlcGxhY2UoL15bQS1aXTovLCIiKS5yZXBsYWNlKC9cXC9nLCIvIil9Y29uc3QgbW49ZTtsZXQgeW4sZ249MCxibj17fTtmdW5jdGlvbiBfbih0KXttbi5kZWJ1ZyYmY29uc29sZS5sb2coYFtBTlIgV29ya2VyXSAke3R9YCl9dmFyIHZuLHduLFNuO2NvbnN0ICRuPWZ1bmN0aW9uKHQpe2xldCBuO3RyeXtuPW5ldyBVUkwodC51cmwpfWNhdGNoKG4pe3JldHVybiB2KCgoKT0+e2NvbnNvbGUud2FybigiW0BzZW50cnkvbm9kZV06IEludmFsaWQgZHNuIG9yIHR1bm5lbCBvcHRpb24sIHdpbGwgbm90IHNlbmQgYW55IGV2ZW50cy4gVGhlIHR1bm5lbCBvcHRpb24gbXVzdCBiZSBhIGZ1bGwgVVJMIHdoZW4gdXNlZC4iKX0pKSx0bih0LCgoKT0+UHJvbWlzZS5yZXNvbHZlKHt9KSkpfWNvbnN0IGU9Imh0dHBzOiI9PT1uLnByb3RvY29sLHI9ZnVuY3Rpb24odCxuKXtjb25zdHtub19wcm94eTplfT1wcm9jZXNzLmVudixyPWU/LnNwbGl0KCIsIikuc29tZSgobj0+dC5ob3N0LmVuZHNXaXRoKG4pfHx0Lmhvc3RuYW1lLmVuZHNXaXRoKG4pKSk7cmV0dXJuIHI/dm9pZCAwOm59KG4sdC5wcm94eXx8KGU/cHJvY2Vzcy5lbnYuaHR0cHNfcHJveHk6dm9pZCAwKXx8cHJvY2Vzcy5lbnYuaHR0cF9wcm94eSksbz1lP2k6cyxhPXZvaWQgMCE9PXQua2VlcEFsaXZlJiZ0LmtlZXBBbGl2ZSxmPXI/bmV3IGZuKHIpOm5ldyBvLkFnZW50KHtrZWVwQWxpdmU6YSxtYXhTb2NrZXRzOjMwLHRpbWVvdXQ6MmUzfSksaD1mdW5jdGlvbih0LG4sZSl7Y29uc3R7aG9zdG5hbWU6cixwYXRobmFtZTpvLHBvcnQ6cyxwcm90b2NvbDppLHNlYXJjaDphfT1uZXcgVVJMKHQudXJsKTtyZXR1cm4gZnVuY3Rpb24oZil7cmV0dXJuIG5ldyBQcm9taXNlKCgoaCxwKT0+e1d0KCgoKT0+e2xldCBsPWZ1bmN0aW9uKHQpe3JldHVybiBuZXcgYyh7cmVhZCgpe3RoaXMucHVzaCh0KSx0aGlzLnB1c2gobnVsbCl9fSl9KGYuYm9keSk7Y29uc3QgZD17Li4udC5oZWFkZXJzfTtmLmJvZHkubGVuZ3RoPmxuJiYoZFsiY29udGVudC1lbmNvZGluZyJdPSJnemlwIixsPWwucGlwZSh1KCkpKTtjb25zdCBtPW4ucmVxdWVzdCh7bWV0aG9kOiJQT1NUIixhZ2VudDplLGhlYWRlcnM6ZCxob3N0bmFtZTpyLHBhdGg6YCR7b30ke2F9YCxwb3J0OnMscHJvdG9jb2w6aSxjYTp0LmNhQ2VydHN9LCh0PT57dC5vbigiZGF0YSIsKCgpPT57fSkpLHQub24oImVuZCIsKCgpPT57fSkpLHQuc2V0RW5jb2RpbmcoInV0ZjgiKTtjb25zdCBuPXQuaGVhZGVyc1sicmV0cnktYWZ0ZXIiXT8/bnVsbCxlPXQuaGVhZGVyc1sieC1zZW50cnktcmF0ZS1saW1pdHMiXT8/bnVsbDtoKHtzdGF0dXNDb2RlOnQuc3RhdHVzQ29kZSxoZWFkZXJzOnsicmV0cnktYWZ0ZXIiOm4sIngtc2VudHJ5LXJhdGUtbGltaXRzIjpBcnJheS5pc0FycmF5KGUpP2VbMF18fG51bGw6ZX19KX0pKTttLm9uKCJlcnJvciIscCksbC5waXBlKG0pfSkpfSkpfX0odCx0Lmh0dHBNb2R1bGU/P28sZik7cmV0dXJuIHRuKHQsaCl9KHt1cmw6KHZuPW1uLmRzbix3bj1tbi50dW5uZWwsU249bW4uc2RrTWV0YWRhdGEuc2RrLHdufHxgJHtmdW5jdGlvbih0KXtyZXR1cm5gJHtmdW5jdGlvbih0KXtjb25zdCBuPXQucHJvdG9jb2w/YCR7dC5wcm90b2NvbH06YDoiIixlPXQucG9ydD9gOiR7dC5wb3J0fWA6IiI7cmV0dXJuYCR7bn0vLyR7dC5ob3N0fSR7ZX0ke3QucGF0aD9gLyR7dC5wYXRofWA6IiJ9L2FwaS9gfSh0KX0ke3QucHJvamVjdElkfS9lbnZlbG9wZS9gfSh2bil9PyR7ZnVuY3Rpb24odCxuKXtjb25zdCBlPXtzZW50cnlfdmVyc2lvbjpLdH07cmV0dXJuIHQucHVibGljS2V5JiYoZS5zZW50cnlfa2V5PXQucHVibGljS2V5KSxuJiYoZS5zZW50cnlfY2xpZW50PWAke24ubmFtZX0vJHtuLnZlcnNpb259YCksbmV3IFVSTFNlYXJjaFBhcmFtcyhlKS50b1N0cmluZygpfSh2bixTbil9YCkscmVjb3JkRHJvcHBlZEV2ZW50OigpPT57fX0pO2FzeW5jIGZ1bmN0aW9uIEVuKCl7aWYoeW4pe19uKCJTZW5kaW5nIGFibm9ybWFsIHNlc3Npb24iKSxWKHluLHtzdGF0dXM6ImFibm9ybWFsIixhYm5vcm1hbF9tZWNoYW5pc206ImFucl9mb3JlZ3JvdW5kIixyZWxlYXNlOm1uLnJlbGVhc2UsZW52aXJvbm1lbnQ6bW4uZW52aXJvbm1lbnR9KTtjb25zdCB0PWZ1bmN0aW9uKHQsbixlLHIpe2NvbnN0IG89WXQoZSk7cmV0dXJuIE10KHtzZW50X2F0OihuZXcgRGF0ZSkudG9JU09TdHJpbmcoKSwuLi5vJiZ7c2RrOm99LC4uLiEhciYmbiYme2RzbjpBdChuKX19LFsiYWdncmVnYXRlcyJpbiB0P1t7dHlwZToic2Vzc2lvbnMifSx0XTpbe3R5cGU6InNlc3Npb24ifSx0LnRvSlNPTigpXV0pfSh5bixtbi5kc24sbW4uc2RrTWV0YWRhdGEsbW4udHVubmVsKTtfbihKU09OLnN0cmluZ2lmeSh0KSksYXdhaXQgJG4uc2VuZCh0KTt0cnl7bj8ucG9zdE1lc3NhZ2UoInNlc3Npb24tZW5kZWQiKX1jYXRjaCh0KXt9fX1mdW5jdGlvbiB4bih0KXtpZighdClyZXR1cm47Y29uc3Qgbj1mdW5jdGlvbih0KXtpZighdC5sZW5ndGgpcmV0dXJuW107Y29uc3Qgbj1BcnJheS5mcm9tKHQpO3JldHVybi9zZW50cnlXcmFwcGVkLy50ZXN0KHgobikuZnVuY3Rpb258fCIiKSYmbi5wb3AoKSxuLnJldmVyc2UoKSxFLnRlc3QoeChuKS5mdW5jdGlvbnx8IiIpJiYobi5wb3AoKSxFLnRlc3QoeChuKS5mdW5jdGlvbnx8IiIpJiZuLnBvcCgpKSxuLnNsaWNlKDAsUykubWFwKCh0PT4oey4uLnQsZmlsZW5hbWU6dC5maWxlbmFtZXx8eChuKS5maWxlbmFtZSxmdW5jdGlvbjp0LmZ1bmN0aW9ufHwkfSkpKX0odCk7aWYobW4uYXBwUm9vdFBhdGgpZm9yKGNvbnN0IHQgb2Ygbil0LmZpbGVuYW1lJiYodC5maWxlbmFtZT1VdCh0LmZpbGVuYW1lLG1uLmFwcFJvb3RQYXRoKSk7cmV0dXJuIG59YXN5bmMgZnVuY3Rpb24gTm4odCxuKXtpZihnbj49bW4ubWF4QW5yRXZlbnRzKXJldHVybjtnbis9MSxhd2FpdCBFbigpLF9uKCJTZW5kaW5nIGV2ZW50Iik7Y29uc3QgZT17ZXZlbnRfaWQ6eigpLGNvbnRleHRzOm1uLmNvbnRleHRzLHJlbGVhc2U6bW4ucmVsZWFzZSxlbnZpcm9ubWVudDptbi5lbnZpcm9ubWVudCxkaXN0Om1uLmRpc3QscGxhdGZvcm06Im5vZGUiLGxldmVsOiJlcnJvciIsZXhjZXB0aW9uOnt2YWx1ZXM6W3t0eXBlOiJBcHBsaWNhdGlvbk5vdFJlc3BvbmRpbmciLHZhbHVlOmBBcHBsaWNhdGlvbiBOb3QgUmVzcG9uZGluZyBmb3IgYXQgbGVhc3QgJHttbi5hbnJUaHJlc2hvbGR9IG1zYCxzdGFja3RyYWNlOntmcmFtZXM6eG4odCl9LG1lY2hhbmlzbTp7dHlwZToiQU5SIn19XX0sdGFnczptbi5zdGF0aWNUYWdzfTtuJiZmdW5jdGlvbih0LG4pe2lmKEZ0KHQsbiksIXQuY29udGV4dHM/LnRyYWNlKXtjb25zdHt0cmFjZUlkOmUscGFyZW50U3BhbklkOnIscHJvcGFnYXRpb25TcGFuSWQ6b309bi5wcm9wYWdhdGlvbkNvbnRleHQ7dC5jb250ZXh0cz17dHJhY2U6e3RyYWNlX2lkOmUsc3Bhbl9pZDpvfHxxKCkscGFyZW50X3NwYW5faWQ6cn0sLi4udC5jb250ZXh0c319fShlLG4pLGZ1bmN0aW9uKHQpe2lmKDA9PT1PYmplY3Qua2V5cyhibikubGVuZ3RoKXJldHVybjtjb25zdCBuPW1uLmFwcFJvb3RQYXRoP3t9OmJuO2lmKG1uLmFwcFJvb3RQYXRoKWZvcihjb25zdFt0LGVdb2YgT2JqZWN0LmVudHJpZXMoYm4pKW5bVXQodCxtbi5hcHBSb290UGF0aCldPWU7Y29uc3QgZT1uZXcgTWFwO2Zvcihjb25zdCByIG9mIHQuZXhjZXB0aW9uPy52YWx1ZXN8fFtdKWZvcihjb25zdCB0IG9mIHIuc3RhY2t0cmFjZT8uZnJhbWVzfHxbXSl7Y29uc3Qgcj10LmFic19wYXRofHx0LmZpbGVuYW1lO3ImJm5bcl0mJmUuc2V0KHIsbltyXSl9aWYoZS5zaXplPjApe2NvbnN0IG49W107Zm9yKGNvbnN0W3Qscl1vZiBlLmVudHJpZXMoKSluLnB1c2goe3R5cGU6InNvdXJjZW1hcCIsY29kZV9maWxlOnQsZGVidWdfaWQ6cn0pO3QuZGVidWdfbWV0YT17aW1hZ2VzOm59fX0oZSk7Y29uc3Qgcj16dChlLG1uLmRzbixtbi5zZGtNZXRhZGF0YSxtbi50dW5uZWwpO19uKEpTT04uc3RyaW5naWZ5KHIpKSxhd2FpdCAkbi5zZW5kKHIpLGF3YWl0ICRuLmZsdXNoKDJlMyksZ24+PW1uLm1heEFuckV2ZW50cyYmc2V0VGltZW91dCgoKCk9Pntwcm9jZXNzLmV4aXQoMCl9KSw1ZTMpfWxldCBUbjtpZihfbigiU3RhcnRlZCIpLG1uLmNhcHR1cmVTdGFja1RyYWNlKXtfbigiQ29ubmVjdGluZyB0byBkZWJ1Z2dlciIpO2NvbnN0IG49bmV3IHQ7bi5jb25uZWN0VG9NYWluVGhyZWFkKCksX24oIkNvbm5lY3RlZCB0byBkZWJ1Z2dlciIpO2NvbnN0IGU9bmV3IE1hcDtuLm9uKCJEZWJ1Z2dlci5zY3JpcHRQYXJzZWQiLCh0PT57ZS5zZXQodC5wYXJhbXMuc2NyaXB0SWQsdC5wYXJhbXMudXJsKX0pKSxuLm9uKCJEZWJ1Z2dlci5wYXVzZWQiLCh0PT57aWYoIm90aGVyIj09PXQucGFyYW1zLnJlYXNvbil0cnl7X24oIkRlYnVnZ2VyIHBhdXNlZCIpO2NvbnN0IHM9Wy4uLnQucGFyYW1zLmNhbGxGcmFtZXNdLGk9bW4uYXBwUm9vdFBhdGg/ZnVuY3Rpb24odD0ocHJvY2Vzcy5hcmd2WzFdP2VuKHByb2Nlc3MuYXJndlsxXSk6cHJvY2Vzcy5jd2QoKSksbj0iXFwiPT09byl7Y29uc3QgZT1uP2RuKHQpOnQ7cmV0dXJuIHQ9PntpZighdClyZXR1cm47Y29uc3Qgbz1uP2RuKHQpOnQ7bGV0e2RpcjpzLGJhc2U6aSxleHQ6Y309ci5wYXJzZShvKTsiLmpzIiE9PWMmJiIubWpzIiE9PWMmJiIuY2pzIiE9PWN8fChpPWkuc2xpY2UoMCwtMSpjLmxlbmd0aCkpO2NvbnN0IHU9ZGVjb2RlVVJJQ29tcG9uZW50KGkpO3N8fChzPSIuIik7Y29uc3QgYT1zLmxhc3RJbmRleE9mKCIvbm9kZV9tb2R1bGVzIik7aWYoYT4tMSlyZXR1cm5gJHtzLnNsaWNlKGErMTQpLnJlcGxhY2UoL1wvL2csIi4iKX06JHt1fWA7aWYocy5zdGFydHNXaXRoKGUpKXtjb25zdCB0PXMuc2xpY2UoZS5sZW5ndGgrMSkucmVwbGFjZSgvXC8vZywiLiIpO3JldHVybiB0P2Ake3R9OiR7dX1gOnV9cmV0dXJuIHV9fShtbi5hcHBSb290UGF0aCk6KCk9Pnt9LGM9cy5tYXAoKHQ9PmZ1bmN0aW9uKHQsbixlKXtjb25zdCByPW4/bi5yZXBsYWNlKC9eZmlsZTpcL1wvLywiIik6dm9pZCAwLG89dC5sb2NhdGlvbi5jb2x1bW5OdW1iZXI/dC5sb2NhdGlvbi5jb2x1bW5OdW1iZXIrMTp2b2lkIDAscz10LmxvY2F0aW9uLmxpbmVOdW1iZXI/dC5sb2NhdGlvbi5saW5lTnVtYmVyKzE6dm9pZCAwO3JldHVybiBMKHtmaWxlbmFtZTpyLG1vZHVsZTplKHIpLGZ1bmN0aW9uOnQuZnVuY3Rpb25OYW1lfHwkLGNvbG5vOm8sbGluZW5vOnMsaW5fYXBwOnI/cm4ocik6dm9pZCAwfSl9KHQsZS5nZXQodC5sb2NhdGlvbi5zY3JpcHRJZCksaSkpKSx1PXNldFRpbWVvdXQoKCgpPT57Tm4oYykudGhlbihudWxsLCgoKT0+e19uKCJTZW5kaW5nIEFOUiBldmVudCBmYWlsZWQuIil9KSl9KSw1ZTMpO24ucG9zdCgiUnVudGltZS5ldmFsdWF0ZSIse2V4cHJlc3Npb246Imdsb2JhbC5fX1NFTlRSWV9HRVRfU0NPUEVTX18oKTsiLHNpbGVudDohMCxyZXR1cm5CeVZhbHVlOiEwfSwoKHQsZSk9Pnt0JiZfbihgRXJyb3IgZXhlY3V0aW5nIHNjcmlwdDogJyR7dC5tZXNzYWdlfSdgKSxjbGVhclRpbWVvdXQodSk7Y29uc3Qgcj1lPy5yZXN1bHQ/ZS5yZXN1bHQudmFsdWU6dm9pZCAwO24ucG9zdCgiRGVidWdnZXIucmVzdW1lIiksbi5wb3N0KCJEZWJ1Z2dlci5kaXNhYmxlIiksTm4oYyxyKS50aGVuKG51bGwsKCgpPT57X24oIlNlbmRpbmcgQU5SIGV2ZW50IGZhaWxlZC4iKX0pKX0pKX1jYXRjaCh0KXt0aHJvdyBuLnBvc3QoIkRlYnVnZ2VyLnJlc3VtZSIpLG4ucG9zdCgiRGVidWdnZXIuZGlzYWJsZSIpLHR9fSkpLFRuPSgpPT57dHJ5e24ucG9zdCgiRGVidWdnZXIuZW5hYmxlIiwoKCk9PntuLnBvc3QoIkRlYnVnZ2VyLnBhdXNlIil9KSl9Y2F0Y2godCl7fX19Y29uc3R7cG9sbDpDbn09ZnVuY3Rpb24odCxuLGUscil7Y29uc3Qgbz10KCk7bGV0IHM9ITEsaT0hMDtyZXR1cm4gc2V0SW50ZXJ2YWwoKCgpPT57Y29uc3QgdD1vLmdldFRpbWVNcygpOyExPT09cyYmdD5uK2UmJihzPSEwLGkmJnIoKSksdDxuK2UmJihzPSExKX0pLDIwKSx7cG9sbDooKT0+e28ucmVzZXQoKX0sZW5hYmxlZDp0PT57aT10fX19KChmdW5jdGlvbigpe2xldCB0PXByb2Nlc3MuaHJ0aW1lKCk7cmV0dXJue2dldFRpbWVNczooKT0+e2NvbnN0W24sZV09cHJvY2Vzcy5ocnRpbWUodCk7cmV0dXJuIE1hdGguZmxvb3IoMWUzKm4rZS8xZTYpfSxyZXNldDooKT0+e3Q9cHJvY2Vzcy5ocnRpbWUoKX19fSksbW4ucG9sbEludGVydmFsLG1uLmFuclRocmVzaG9sZCwoZnVuY3Rpb24oKXtfbigiV2F0Y2hkb2cgdGltZW91dCIpLFRuPyhfbigiUGF1c2luZyBkZWJ1Z2dlciB0byBjYXB0dXJlIHN0YWNrIHRyYWNlIiksVG4oKSk6KF9uKCJDYXB0dXJpbmcgZXZlbnQgd2l0aG91dCBhIHN0YWNrIHRyYWNlIiksTm4oKS50aGVuKG51bGwsKCgpPT57X24oIlNlbmRpbmcgQU5SIGV2ZW50IGZhaWxlZCBvbiB3YXRjaGRvZyB0aW1lb3V0LiIpfSkpKX0pKTtuPy5vbigibWVzc2FnZSIsKHQ9Pnt0LnNlc3Npb24mJih5bj1LKHQuc2Vzc2lvbikpLHQuZGVidWdJbWFnZXMmJihibj10LmRlYnVnSW1hZ2VzKSxDbigpfSkpOw==';
13
13
 
14
14
  const DEFAULT_INTERVAL = 50;
15
15
  const DEFAULT_HANG_THRESHOLD = 5000;
@@ -46,7 +46,7 @@ class SentryHttpInstrumentation extends instrumentation.InstrumentationBase {
46
46
  stealthWrap(moduleExports.Server.prototype, 'emit', this._getPatchIncomingRequestFunction());
47
47
 
48
48
  // Patch outgoing requests for breadcrumbs
49
- const patchedRequest = stealthWrap(moduleExports, 'request', this._getPatchOutgoingRequestFunction());
49
+ const patchedRequest = stealthWrap(moduleExports, 'request', this._getPatchOutgoingRequestFunction('http'));
50
50
  stealthWrap(moduleExports, 'get', this._getPatchOutgoingGetFunction(patchedRequest));
51
51
 
52
52
  return moduleExports;
@@ -67,7 +67,7 @@ class SentryHttpInstrumentation extends instrumentation.InstrumentationBase {
67
67
  stealthWrap(moduleExports.Server.prototype, 'emit', this._getPatchIncomingRequestFunction());
68
68
 
69
69
  // Patch outgoing requests for breadcrumbs
70
- const patchedRequest = stealthWrap(moduleExports, 'request', this._getPatchOutgoingRequestFunction());
70
+ const patchedRequest = stealthWrap(moduleExports, 'request', this._getPatchOutgoingRequestFunction('https'));
71
71
  stealthWrap(moduleExports, 'get', this._getPatchOutgoingGetFunction(patchedRequest));
72
72
 
73
73
  return moduleExports;
@@ -144,7 +144,7 @@ class SentryHttpInstrumentation extends instrumentation.InstrumentationBase {
144
144
  /**
145
145
  * Patch the outgoing request function for breadcrumbs.
146
146
  */
147
- _getPatchOutgoingRequestFunction()
147
+ _getPatchOutgoingRequestFunction(component)
148
148
 
149
149
  {
150
150
  // eslint-disable-next-line @typescript-eslint/no-this-alias
@@ -158,10 +158,21 @@ class SentryHttpInstrumentation extends instrumentation.InstrumentationBase {
158
158
  // so that it matches what Otel instrumentation passes to `ignoreOutgoingRequestHook`.
159
159
  // @see https://github.com/open-telemetry/opentelemetry-js/blob/7293e69c1e55ca62e15d0724d22605e61bd58952/experimental/packages/opentelemetry-instrumentation-http/src/http.ts#L756-L789
160
160
  const requestArgs = [...args] ;
161
- const options = requestArgs[0];
161
+
162
+ let options = requestArgs[0];
163
+
164
+ // Make sure correct fallback attributes are set on the options object for https before we pass them to the vendored getRequestInfo function.
165
+ // Ref: https://github.com/open-telemetry/opentelemetry-js/blob/887ff1cd6e3f795f703e40a9fbe89b3cba7e88c3/experimental/packages/opentelemetry-instrumentation-http/src/http.ts#L390
166
+ if (component === 'https' && typeof options === 'object' && options?.constructor?.name !== 'URL') {
167
+ options = Object.assign({}, options);
168
+ options.protocol = options.protocol || 'https:';
169
+ options.port = options.port || 443;
170
+ }
171
+
162
172
  const extraOptions = typeof requestArgs[1] === 'object' ? requestArgs[1] : undefined;
163
173
 
164
174
  const { optionsParsed, origin, pathname } = getRequestInfo.getRequestInfo(instrumentation._diag, options, extraOptions);
175
+
165
176
  const url = getAbsoluteUrl(origin, pathname);
166
177
 
167
178
  addSentryHeadersToRequestOptions(url, optionsParsed, instrumentation._propagationDecisionMap);
@@ -1 +1 @@
1
- {"version":3,"file":"SentryHttpInstrumentation.js","sources":["../../../../src/integrations/http/SentryHttpInstrumentation.ts"],"sourcesContent":["import type * as http from 'node:http';\nimport type { IncomingMessage, RequestOptions } from 'node:http';\nimport type * as https from 'node:https';\nimport type { EventEmitter } from 'node:stream';\n/* eslint-disable max-lines */\nimport { VERSION } from '@opentelemetry/core';\nimport type { InstrumentationConfig } from '@opentelemetry/instrumentation';\nimport { InstrumentationBase, InstrumentationNodeModuleDefinition } from '@opentelemetry/instrumentation';\nimport type { AggregationCounts, Client, RequestEventData, SanitizedRequestData, Scope } from '@sentry/core';\nimport {\n LRUMap,\n addBreadcrumb,\n generateSpanId,\n getBreadcrumbLogLevelFromHttpStatusCode,\n getClient,\n getIsolationScope,\n getSanitizedUrlString,\n getTraceData,\n httpRequestToRequestData,\n logger,\n objectToBaggageHeader,\n parseBaggageHeader,\n parseUrl,\n stripUrlQueryAndFragment,\n withIsolationScope,\n withScope,\n} from '@sentry/core';\nimport { shouldPropagateTraceForUrl } from '@sentry/opentelemetry';\nimport { DEBUG_BUILD } from '../../debug-build';\nimport { getRequestUrl } from '../../utils/getRequestUrl';\nimport { getRequestInfo } from './vendor/getRequestInfo';\n\ntype Http = typeof http;\ntype Https = typeof https;\n\ntype RequestArgs =\n // eslint-disable-next-line @typescript-eslint/ban-types\n | [url: string | URL, options?: RequestOptions, callback?: Function]\n // eslint-disable-next-line @typescript-eslint/ban-types\n | [options: RequestOptions, callback?: Function];\n\ntype SentryHttpInstrumentationOptions = InstrumentationConfig & {\n /**\n * Whether breadcrumbs should be recorded for requests.\n *\n * @default `true`\n */\n breadcrumbs?: boolean;\n\n /**\n * Do not capture breadcrumbs for outgoing HTTP requests to URLs where the given callback returns `true`.\n * For the scope of this instrumentation, this callback only controls breadcrumb creation.\n * The same option can be passed to the top-level httpIntegration where it controls both, breadcrumb and\n * span creation.\n *\n * @param url Contains the entire URL, including query string (if any), protocol, host, etc. of the outgoing request.\n * @param request Contains the {@type RequestOptions} object used to make the outgoing request.\n */\n ignoreOutgoingRequests?: (url: string, request: RequestOptions) => boolean;\n\n /**\n * Whether the integration should create [Sessions](https://docs.sentry.io/product/releases/health/#sessions) for incoming requests to track the health and crash-free rate of your releases in Sentry.\n * Read more about Release Health: https://docs.sentry.io/product/releases/health/\n *\n * Defaults to `true`.\n */\n trackIncomingRequestsAsSessions?: boolean;\n\n /**\n * Number of milliseconds until sessions tracked with `trackIncomingRequestsAsSessions` will be flushed as a session aggregate.\n *\n * Defaults to `60000` (60s).\n */\n sessionFlushingDelayMS?: number;\n};\n\n// We only want to capture request bodies up to 1mb.\nconst MAX_BODY_BYTE_LENGTH = 1024 * 1024;\n\n/**\n * This custom HTTP instrumentation is used to isolate incoming requests and annotate them with additional information.\n * It does not emit any spans.\n *\n * The reason this is isolated from the OpenTelemetry instrumentation is that users may overwrite this,\n * which would lead to Sentry not working as expected.\n *\n * Important note: Contrary to other OTEL instrumentation, this one cannot be unwrapped.\n * It only does minimal things though and does not emit any spans.\n *\n * This is heavily inspired & adapted from:\n * https://github.com/open-telemetry/opentelemetry-js/blob/f8ab5592ddea5cba0a3b33bf8d74f27872c0367f/experimental/packages/opentelemetry-instrumentation-http/src/http.ts\n */\nexport class SentryHttpInstrumentation extends InstrumentationBase<SentryHttpInstrumentationOptions> {\n private _propagationDecisionMap: LRUMap<string, boolean>;\n\n public constructor(config: SentryHttpInstrumentationOptions = {}) {\n super('@sentry/instrumentation-http', VERSION, config);\n this._propagationDecisionMap = new LRUMap<string, boolean>(100);\n }\n\n /** @inheritdoc */\n public init(): [InstrumentationNodeModuleDefinition, InstrumentationNodeModuleDefinition] {\n return [this._getHttpsInstrumentation(), this._getHttpInstrumentation()];\n }\n\n /** Get the instrumentation for the http module. */\n private _getHttpInstrumentation(): InstrumentationNodeModuleDefinition {\n return new InstrumentationNodeModuleDefinition(\n 'http',\n ['*'],\n (moduleExports: Http): Http => {\n // Patch incoming requests for request isolation\n stealthWrap(moduleExports.Server.prototype, 'emit', this._getPatchIncomingRequestFunction());\n\n // Patch outgoing requests for breadcrumbs\n const patchedRequest = stealthWrap(moduleExports, 'request', this._getPatchOutgoingRequestFunction());\n stealthWrap(moduleExports, 'get', this._getPatchOutgoingGetFunction(patchedRequest));\n\n return moduleExports;\n },\n () => {\n // no unwrap here\n },\n );\n }\n\n /** Get the instrumentation for the https module. */\n private _getHttpsInstrumentation(): InstrumentationNodeModuleDefinition {\n return new InstrumentationNodeModuleDefinition(\n 'https',\n ['*'],\n (moduleExports: Https): Https => {\n // Patch incoming requests for request isolation\n stealthWrap(moduleExports.Server.prototype, 'emit', this._getPatchIncomingRequestFunction());\n\n // Patch outgoing requests for breadcrumbs\n const patchedRequest = stealthWrap(moduleExports, 'request', this._getPatchOutgoingRequestFunction());\n stealthWrap(moduleExports, 'get', this._getPatchOutgoingGetFunction(patchedRequest));\n\n return moduleExports;\n },\n () => {\n // no unwrap here\n },\n );\n }\n\n /**\n * Patch the incoming request function for request isolation.\n */\n private _getPatchIncomingRequestFunction(): (\n original: (event: string, ...args: unknown[]) => boolean,\n ) => (this: unknown, event: string, ...args: unknown[]) => boolean {\n // eslint-disable-next-line @typescript-eslint/no-this-alias\n const instrumentation = this;\n\n return (\n original: (event: string, ...args: unknown[]) => boolean,\n ): ((this: unknown, event: string, ...args: unknown[]) => boolean) => {\n return function incomingRequest(this: unknown, event: string, ...args: unknown[]): boolean {\n // Only traces request events\n if (event !== 'request') {\n return original.apply(this, [event, ...args]);\n }\n\n instrumentation._diag.debug('http instrumentation for incoming request');\n\n const isolationScope = getIsolationScope().clone();\n const request = args[0] as http.IncomingMessage;\n const response = args[1] as http.OutgoingMessage;\n\n const normalizedRequest = httpRequestToRequestData(request);\n\n // request.ip is non-standard but some frameworks set this\n const ipAddress = (request as { ip?: string }).ip || request.socket?.remoteAddress;\n\n patchRequestToCaptureBody(request, isolationScope);\n\n // Update the isolation scope, isolate this request\n isolationScope.setSDKProcessingMetadata({ normalizedRequest, ipAddress });\n\n // attempt to update the scope's `transactionName` based on the request URL\n // Ideally, framework instrumentations coming after the HttpInstrumentation\n // update the transactionName once we get a parameterized route.\n const httpMethod = (request.method || 'GET').toUpperCase();\n const httpTarget = stripUrlQueryAndFragment(request.url || '/');\n\n const bestEffortTransactionName = `${httpMethod} ${httpTarget}`;\n\n isolationScope.setTransactionName(bestEffortTransactionName);\n\n if (instrumentation.getConfig().trackIncomingRequestsAsSessions !== false) {\n recordRequestSession({\n requestIsolationScope: isolationScope,\n response,\n sessionFlushingDelayMS: instrumentation.getConfig().sessionFlushingDelayMS ?? 60_000,\n });\n }\n\n return withIsolationScope(isolationScope, () => {\n return withScope(scope => {\n // Set a new propagationSpanId for this request\n scope.getPropagationContext().propagationSpanId = generateSpanId();\n return original.apply(this, [event, ...args]);\n });\n });\n };\n };\n }\n\n /**\n * Patch the outgoing request function for breadcrumbs.\n */\n private _getPatchOutgoingRequestFunction(): (\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n original: (...args: any[]) => http.ClientRequest,\n ) => (options: URL | http.RequestOptions | string, ...args: unknown[]) => http.ClientRequest {\n // eslint-disable-next-line @typescript-eslint/no-this-alias\n const instrumentation = this;\n\n return (original: (...args: unknown[]) => http.ClientRequest): ((...args: unknown[]) => http.ClientRequest) => {\n return function outgoingRequest(this: unknown, ...args: unknown[]): http.ClientRequest {\n instrumentation._diag.debug('http instrumentation for outgoing requests');\n\n // We need to access and reconstruct the request options object passed to `ignoreOutgoingRequests`\n // so that it matches what Otel instrumentation passes to `ignoreOutgoingRequestHook`.\n // @see https://github.com/open-telemetry/opentelemetry-js/blob/7293e69c1e55ca62e15d0724d22605e61bd58952/experimental/packages/opentelemetry-instrumentation-http/src/http.ts#L756-L789\n const requestArgs = [...args] as RequestArgs;\n const options = requestArgs[0];\n const extraOptions = typeof requestArgs[1] === 'object' ? requestArgs[1] : undefined;\n\n const { optionsParsed, origin, pathname } = getRequestInfo(instrumentation._diag, options, extraOptions);\n const url = getAbsoluteUrl(origin, pathname);\n\n addSentryHeadersToRequestOptions(url, optionsParsed, instrumentation._propagationDecisionMap);\n\n const request = original.apply(this, [optionsParsed, ...requestArgs.slice(1)]) as ReturnType<\n typeof http.request\n >;\n\n request.prependListener('response', (response: http.IncomingMessage) => {\n const _breadcrumbs = instrumentation.getConfig().breadcrumbs;\n const breadCrumbsEnabled = typeof _breadcrumbs === 'undefined' ? true : _breadcrumbs;\n\n const _ignoreOutgoingRequests = instrumentation.getConfig().ignoreOutgoingRequests;\n const shouldCreateBreadcrumb =\n typeof _ignoreOutgoingRequests === 'function'\n ? !_ignoreOutgoingRequests(getRequestUrl(request), optionsParsed)\n : true;\n\n if (breadCrumbsEnabled && shouldCreateBreadcrumb) {\n addRequestBreadcrumb(request, response);\n }\n });\n\n return request;\n };\n };\n }\n\n /** Path the outgoing get function for breadcrumbs. */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n private _getPatchOutgoingGetFunction(clientRequest: (...args: any[]) => http.ClientRequest) {\n return (_original: unknown): ((...args: unknown[]) => http.ClientRequest) => {\n // Re-implement http.get. This needs to be done (instead of using\n // getPatchOutgoingRequestFunction to patch it) because we need to\n // set the trace context header before the returned http.ClientRequest is\n // ended. The Node.js docs state that the only differences between\n // request and get are that (1) get defaults to the HTTP GET method and\n // (2) the returned request object is ended immediately. The former is\n // already true (at least in supported Node versions up to v10), so we\n // simply follow the latter. Ref:\n // https://nodejs.org/dist/latest/docs/api/http.html#http_http_get_options_callback\n // https://github.com/googleapis/cloud-trace-nodejs/blob/master/src/instrumentations/instrumentation-http.ts#L198\n return function outgoingGetRequest(...args: unknown[]): http.ClientRequest {\n const req = clientRequest(...args);\n req.end();\n return req;\n };\n };\n }\n}\n\n/**\n * This is a minimal version of `wrap` from shimmer:\n * https://github.com/othiym23/shimmer/blob/master/index.js\n *\n * In contrast to the original implementation, this version does not allow to unwrap,\n * and does not make it clear that the method is wrapped.\n * This is necessary because we want to wrap the http module with our own code,\n * while still allowing to use the HttpInstrumentation from OTEL.\n *\n * Without this, if we'd just use `wrap` from shimmer, the OTEL instrumentation would remove our wrapping,\n * because it only allows any module to be wrapped a single time.\n */\nfunction stealthWrap<Nodule extends object, FieldName extends keyof Nodule>(\n nodule: Nodule,\n name: FieldName,\n wrapper: (original: Nodule[FieldName]) => Nodule[FieldName],\n): Nodule[FieldName] {\n const original = nodule[name];\n const wrapped = wrapper(original);\n\n defineProperty(nodule, name, wrapped);\n return wrapped;\n}\n\n// Sets a property on an object, preserving its enumerability.\nfunction defineProperty<Nodule extends object, FieldName extends keyof Nodule>(\n obj: Nodule,\n name: FieldName,\n value: Nodule[FieldName],\n): void {\n const enumerable = !!obj[name] && Object.prototype.propertyIsEnumerable.call(obj, name);\n\n Object.defineProperty(obj, name, {\n configurable: true,\n enumerable: enumerable,\n writable: true,\n value: value,\n });\n}\n\n/** Add a breadcrumb for outgoing requests. */\nfunction addRequestBreadcrumb(request: http.ClientRequest, response: http.IncomingMessage): void {\n const data = getBreadcrumbData(request);\n\n const statusCode = response.statusCode;\n const level = getBreadcrumbLogLevelFromHttpStatusCode(statusCode);\n\n addBreadcrumb(\n {\n category: 'http',\n data: {\n status_code: statusCode,\n ...data,\n },\n type: 'http',\n level,\n },\n {\n event: 'response',\n request,\n response,\n },\n );\n}\n\nfunction getBreadcrumbData(request: http.ClientRequest): Partial<SanitizedRequestData> {\n try {\n // `request.host` does not contain the port, but the host header does\n const host = request.getHeader('host') || request.host;\n const url = new URL(request.path, `${request.protocol}//${host}`);\n const parsedUrl = parseUrl(url.toString());\n\n const data: Partial<SanitizedRequestData> = {\n url: getSanitizedUrlString(parsedUrl),\n 'http.method': request.method || 'GET',\n };\n\n if (parsedUrl.search) {\n data['http.query'] = parsedUrl.search;\n }\n if (parsedUrl.hash) {\n data['http.fragment'] = parsedUrl.hash;\n }\n\n return data;\n } catch {\n return {};\n }\n}\n\n/**\n * This method patches the request object to capture the body.\n * Instead of actually consuming the streamed body ourselves, which has potential side effects,\n * we monkey patch `req.on('data')` to intercept the body chunks.\n * This way, we only read the body if the user also consumes the body, ensuring we do not change any behavior in unexpected ways.\n */\nfunction patchRequestToCaptureBody(req: IncomingMessage, isolationScope: Scope): void {\n const chunks: Buffer[] = [];\n\n function getChunksSize(): number {\n return chunks.reduce((acc, chunk) => acc + chunk.byteLength, 0);\n }\n\n /**\n * We need to keep track of the original callbacks, in order to be able to remove listeners again.\n * Since `off` depends on having the exact same function reference passed in, we need to be able to map\n * original listeners to our wrapped ones.\n */\n const callbackMap = new WeakMap();\n\n try {\n // eslint-disable-next-line @typescript-eslint/unbound-method\n req.on = new Proxy(req.on, {\n apply: (target, thisArg, args: Parameters<typeof req.on>) => {\n const [event, listener, ...restArgs] = args;\n\n if (event === 'data') {\n const callback = new Proxy(listener, {\n apply: (target, thisArg, args: Parameters<typeof listener>) => {\n // If we have already read more than the max body length, we stop adding chunks\n // To avoid growing the memory indefinitely if a response is e.g. streamed\n if (getChunksSize() < MAX_BODY_BYTE_LENGTH) {\n const chunk = args[0] as Buffer;\n chunks.push(chunk);\n } else if (DEBUG_BUILD) {\n logger.log(\n `Dropping request body chunk because it maximum body length of ${MAX_BODY_BYTE_LENGTH}b is exceeded.`,\n );\n }\n\n return Reflect.apply(target, thisArg, args);\n },\n });\n\n callbackMap.set(listener, callback);\n\n return Reflect.apply(target, thisArg, [event, callback, ...restArgs]);\n }\n\n if (event === 'end') {\n const callback = new Proxy(listener, {\n apply: (target, thisArg, args) => {\n try {\n const body = Buffer.concat(chunks).toString('utf-8');\n\n if (body) {\n const normalizedRequest = { data: body } satisfies RequestEventData;\n isolationScope.setSDKProcessingMetadata({ normalizedRequest });\n }\n } catch {\n // ignore errors here\n }\n\n return Reflect.apply(target, thisArg, args);\n },\n });\n\n callbackMap.set(listener, callback);\n\n return Reflect.apply(target, thisArg, [event, callback, ...restArgs]);\n }\n\n return Reflect.apply(target, thisArg, args);\n },\n });\n\n // Ensure we also remove callbacks correctly\n // eslint-disable-next-line @typescript-eslint/unbound-method\n req.off = new Proxy(req.off, {\n apply: (target, thisArg, args: Parameters<typeof req.off>) => {\n const [, listener] = args;\n\n const callback = callbackMap.get(listener);\n if (callback) {\n callbackMap.delete(listener);\n\n const modifiedArgs = args.slice();\n modifiedArgs[1] = callback;\n return Reflect.apply(target, thisArg, modifiedArgs);\n }\n\n return Reflect.apply(target, thisArg, args);\n },\n });\n } catch {\n // ignore errors if we can't patch stuff\n }\n}\n\n/**\n * Mutates the passed in `options` and adds `sentry-trace` / `baggage` headers, if they are not already set.\n */\nfunction addSentryHeadersToRequestOptions(\n url: string,\n options: RequestOptions,\n propagationDecisionMap: LRUMap<string, boolean>,\n): void {\n // Manually add the trace headers, if it applies\n // Note: We do not use `propagation.inject()` here, because our propagator relies on an active span\n // Which we do not have in this case\n const tracePropagationTargets = getClient()?.getOptions().tracePropagationTargets;\n const addedHeaders = shouldPropagateTraceForUrl(url, tracePropagationTargets, propagationDecisionMap)\n ? getTraceData()\n : undefined;\n\n if (!addedHeaders) {\n return;\n }\n\n if (!options.headers) {\n options.headers = {};\n }\n const headers = options.headers;\n\n const { 'sentry-trace': sentryTrace, baggage } = addedHeaders;\n\n // We do not want to overwrite existing header here, if it was already set\n if (sentryTrace && !headers['sentry-trace']) {\n headers['sentry-trace'] = sentryTrace;\n }\n\n // For baggage, we make sure to merge this into a possibly existing header\n if (baggage) {\n headers['baggage'] = mergeBaggageHeaders(headers['baggage'], baggage);\n }\n}\n\n/**\n * Starts a session and tracks it in the context of a given isolation scope.\n * When the passed response is finished, the session is put into a task and is\n * aggregated with other sessions that may happen in a certain time window\n * (sessionFlushingDelayMs).\n *\n * The sessions are always aggregated by the client that is on the current scope\n * at the time of ending the response (if there is one).\n */\n// Exported for unit tests\nexport function recordRequestSession({\n requestIsolationScope,\n response,\n sessionFlushingDelayMS,\n}: { requestIsolationScope: Scope; response: EventEmitter; sessionFlushingDelayMS?: number }): void {\n requestIsolationScope.setSDKProcessingMetadata({\n requestSession: { status: 'ok' },\n });\n response.once('close', () => {\n // We need to grab the client off the current scope instead of the isolation scope because the isolation scope doesn't hold any client out of the box.\n const client = getClient();\n const requestSession = requestIsolationScope.getScopeData().sdkProcessingMetadata.requestSession;\n\n if (client && requestSession) {\n DEBUG_BUILD && logger.debug(`Recorded request session with status: ${requestSession.status}`);\n\n const roundedDate = new Date();\n roundedDate.setSeconds(0, 0);\n const dateBucketKey = roundedDate.toISOString();\n\n const existingClientAggregate = clientToRequestSessionAggregatesMap.get(client);\n const bucket = existingClientAggregate?.[dateBucketKey] || { exited: 0, crashed: 0, errored: 0 };\n bucket[({ ok: 'exited', crashed: 'crashed', errored: 'errored' } as const)[requestSession.status]]++;\n\n if (existingClientAggregate) {\n existingClientAggregate[dateBucketKey] = bucket;\n } else {\n DEBUG_BUILD && logger.debug('Opened new request session aggregate.');\n const newClientAggregate = { [dateBucketKey]: bucket };\n clientToRequestSessionAggregatesMap.set(client, newClientAggregate);\n\n const flushPendingClientAggregates = (): void => {\n clearTimeout(timeout);\n unregisterClientFlushHook();\n clientToRequestSessionAggregatesMap.delete(client);\n\n const aggregatePayload: AggregationCounts[] = Object.entries(newClientAggregate).map(\n ([timestamp, value]) => ({\n started: timestamp,\n exited: value.exited,\n errored: value.errored,\n crashed: value.crashed,\n }),\n );\n client.sendSession({ aggregates: aggregatePayload });\n };\n\n const unregisterClientFlushHook = client.on('flush', () => {\n DEBUG_BUILD && logger.debug('Sending request session aggregate due to client flush');\n flushPendingClientAggregates();\n });\n const timeout = setTimeout(() => {\n DEBUG_BUILD && logger.debug('Sending request session aggregate due to flushing schedule');\n flushPendingClientAggregates();\n }, sessionFlushingDelayMS).unref();\n }\n }\n });\n}\n\nconst clientToRequestSessionAggregatesMap = new Map<\n Client,\n { [timestampRoundedToSeconds: string]: { exited: number; crashed: number; errored: number } }\n>();\n\nfunction getAbsoluteUrl(origin: string, path: string = '/'): string {\n try {\n const url = new URL(path, origin);\n return url.toString();\n } catch {\n // fallback: Construct it on our own\n const url = `${origin}`;\n\n if (url.endsWith('/') && path.startsWith('/')) {\n return `${url}${path.slice(1)}`;\n }\n\n if (!url.endsWith('/') && !path.startsWith('/')) {\n return `${url}/${path.slice(1)}`;\n }\n\n return `${url}${path}`;\n }\n}\n\nfunction mergeBaggageHeaders(\n existing: string | string[] | number | undefined,\n baggage: string,\n): string | string[] | number | undefined {\n if (!existing) {\n return baggage;\n }\n\n const existingBaggageEntries = parseBaggageHeader(existing);\n const newBaggageEntries = parseBaggageHeader(baggage);\n\n if (!newBaggageEntries) {\n return existing;\n }\n\n // Existing entries take precedence, ensuring order remains stable for minimal changes\n const mergedBaggageEntries = { ...existingBaggageEntries };\n Object.entries(newBaggageEntries).forEach(([key, value]) => {\n if (!mergedBaggageEntries[key]) {\n mergedBaggageEntries[key] = value;\n }\n });\n\n return objectToBaggageHeader(mergedBaggageEntries);\n}\n"],"names":["InstrumentationBase","VERSION","LRUMap","InstrumentationNodeModuleDefinition","getIsolationScope","httpRequestToRequestData","stripUrlQueryAndFragment","withIsolationScope","withScope","generateSpanId","getRequestInfo","getRequestUrl","getBreadcrumbLogLevelFromHttpStatusCode","addBreadcrumb","parseUrl","getSanitizedUrlString","DEBUG_BUILD","logger","getClient","shouldPropagateTraceForUrl","getTraceData","parseBaggageHeader","objectToBaggageHeader"],"mappings":"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"}
1
+ {"version":3,"file":"SentryHttpInstrumentation.js","sources":["../../../../src/integrations/http/SentryHttpInstrumentation.ts"],"sourcesContent":["import type * as http from 'node:http';\nimport type { IncomingMessage, RequestOptions } from 'node:http';\nimport type * as https from 'node:https';\nimport type { EventEmitter } from 'node:stream';\n/* eslint-disable max-lines */\nimport { VERSION } from '@opentelemetry/core';\nimport type { InstrumentationConfig } from '@opentelemetry/instrumentation';\nimport { InstrumentationBase, InstrumentationNodeModuleDefinition } from '@opentelemetry/instrumentation';\nimport type { AggregationCounts, Client, RequestEventData, SanitizedRequestData, Scope } from '@sentry/core';\nimport {\n LRUMap,\n addBreadcrumb,\n generateSpanId,\n getBreadcrumbLogLevelFromHttpStatusCode,\n getClient,\n getIsolationScope,\n getSanitizedUrlString,\n getTraceData,\n httpRequestToRequestData,\n logger,\n objectToBaggageHeader,\n parseBaggageHeader,\n parseUrl,\n stripUrlQueryAndFragment,\n withIsolationScope,\n withScope,\n} from '@sentry/core';\nimport { shouldPropagateTraceForUrl } from '@sentry/opentelemetry';\nimport { DEBUG_BUILD } from '../../debug-build';\nimport { getRequestUrl } from '../../utils/getRequestUrl';\nimport { getRequestInfo } from './vendor/getRequestInfo';\n\ntype Http = typeof http;\ntype Https = typeof https;\n\ntype RequestArgs =\n // eslint-disable-next-line @typescript-eslint/ban-types\n | [url: string | URL, options?: RequestOptions, callback?: Function]\n // eslint-disable-next-line @typescript-eslint/ban-types\n | [options: RequestOptions, callback?: Function];\n\ntype SentryHttpInstrumentationOptions = InstrumentationConfig & {\n /**\n * Whether breadcrumbs should be recorded for requests.\n *\n * @default `true`\n */\n breadcrumbs?: boolean;\n\n /**\n * Do not capture breadcrumbs for outgoing HTTP requests to URLs where the given callback returns `true`.\n * For the scope of this instrumentation, this callback only controls breadcrumb creation.\n * The same option can be passed to the top-level httpIntegration where it controls both, breadcrumb and\n * span creation.\n *\n * @param url Contains the entire URL, including query string (if any), protocol, host, etc. of the outgoing request.\n * @param request Contains the {@type RequestOptions} object used to make the outgoing request.\n */\n ignoreOutgoingRequests?: (url: string, request: RequestOptions) => boolean;\n\n /**\n * Whether the integration should create [Sessions](https://docs.sentry.io/product/releases/health/#sessions) for incoming requests to track the health and crash-free rate of your releases in Sentry.\n * Read more about Release Health: https://docs.sentry.io/product/releases/health/\n *\n * Defaults to `true`.\n */\n trackIncomingRequestsAsSessions?: boolean;\n\n /**\n * Number of milliseconds until sessions tracked with `trackIncomingRequestsAsSessions` will be flushed as a session aggregate.\n *\n * Defaults to `60000` (60s).\n */\n sessionFlushingDelayMS?: number;\n};\n\n// We only want to capture request bodies up to 1mb.\nconst MAX_BODY_BYTE_LENGTH = 1024 * 1024;\n\n/**\n * This custom HTTP instrumentation is used to isolate incoming requests and annotate them with additional information.\n * It does not emit any spans.\n *\n * The reason this is isolated from the OpenTelemetry instrumentation is that users may overwrite this,\n * which would lead to Sentry not working as expected.\n *\n * Important note: Contrary to other OTEL instrumentation, this one cannot be unwrapped.\n * It only does minimal things though and does not emit any spans.\n *\n * This is heavily inspired & adapted from:\n * https://github.com/open-telemetry/opentelemetry-js/blob/f8ab5592ddea5cba0a3b33bf8d74f27872c0367f/experimental/packages/opentelemetry-instrumentation-http/src/http.ts\n */\nexport class SentryHttpInstrumentation extends InstrumentationBase<SentryHttpInstrumentationOptions> {\n private _propagationDecisionMap: LRUMap<string, boolean>;\n\n public constructor(config: SentryHttpInstrumentationOptions = {}) {\n super('@sentry/instrumentation-http', VERSION, config);\n this._propagationDecisionMap = new LRUMap<string, boolean>(100);\n }\n\n /** @inheritdoc */\n public init(): [InstrumentationNodeModuleDefinition, InstrumentationNodeModuleDefinition] {\n return [this._getHttpsInstrumentation(), this._getHttpInstrumentation()];\n }\n\n /** Get the instrumentation for the http module. */\n private _getHttpInstrumentation(): InstrumentationNodeModuleDefinition {\n return new InstrumentationNodeModuleDefinition(\n 'http',\n ['*'],\n (moduleExports: Http): Http => {\n // Patch incoming requests for request isolation\n stealthWrap(moduleExports.Server.prototype, 'emit', this._getPatchIncomingRequestFunction());\n\n // Patch outgoing requests for breadcrumbs\n const patchedRequest = stealthWrap(moduleExports, 'request', this._getPatchOutgoingRequestFunction('http'));\n stealthWrap(moduleExports, 'get', this._getPatchOutgoingGetFunction(patchedRequest));\n\n return moduleExports;\n },\n () => {\n // no unwrap here\n },\n );\n }\n\n /** Get the instrumentation for the https module. */\n private _getHttpsInstrumentation(): InstrumentationNodeModuleDefinition {\n return new InstrumentationNodeModuleDefinition(\n 'https',\n ['*'],\n (moduleExports: Https): Https => {\n // Patch incoming requests for request isolation\n stealthWrap(moduleExports.Server.prototype, 'emit', this._getPatchIncomingRequestFunction());\n\n // Patch outgoing requests for breadcrumbs\n const patchedRequest = stealthWrap(moduleExports, 'request', this._getPatchOutgoingRequestFunction('https'));\n stealthWrap(moduleExports, 'get', this._getPatchOutgoingGetFunction(patchedRequest));\n\n return moduleExports;\n },\n () => {\n // no unwrap here\n },\n );\n }\n\n /**\n * Patch the incoming request function for request isolation.\n */\n private _getPatchIncomingRequestFunction(): (\n original: (event: string, ...args: unknown[]) => boolean,\n ) => (this: unknown, event: string, ...args: unknown[]) => boolean {\n // eslint-disable-next-line @typescript-eslint/no-this-alias\n const instrumentation = this;\n\n return (\n original: (event: string, ...args: unknown[]) => boolean,\n ): ((this: unknown, event: string, ...args: unknown[]) => boolean) => {\n return function incomingRequest(this: unknown, event: string, ...args: unknown[]): boolean {\n // Only traces request events\n if (event !== 'request') {\n return original.apply(this, [event, ...args]);\n }\n\n instrumentation._diag.debug('http instrumentation for incoming request');\n\n const isolationScope = getIsolationScope().clone();\n const request = args[0] as http.IncomingMessage;\n const response = args[1] as http.OutgoingMessage;\n\n const normalizedRequest = httpRequestToRequestData(request);\n\n // request.ip is non-standard but some frameworks set this\n const ipAddress = (request as { ip?: string }).ip || request.socket?.remoteAddress;\n\n patchRequestToCaptureBody(request, isolationScope);\n\n // Update the isolation scope, isolate this request\n isolationScope.setSDKProcessingMetadata({ normalizedRequest, ipAddress });\n\n // attempt to update the scope's `transactionName` based on the request URL\n // Ideally, framework instrumentations coming after the HttpInstrumentation\n // update the transactionName once we get a parameterized route.\n const httpMethod = (request.method || 'GET').toUpperCase();\n const httpTarget = stripUrlQueryAndFragment(request.url || '/');\n\n const bestEffortTransactionName = `${httpMethod} ${httpTarget}`;\n\n isolationScope.setTransactionName(bestEffortTransactionName);\n\n if (instrumentation.getConfig().trackIncomingRequestsAsSessions !== false) {\n recordRequestSession({\n requestIsolationScope: isolationScope,\n response,\n sessionFlushingDelayMS: instrumentation.getConfig().sessionFlushingDelayMS ?? 60_000,\n });\n }\n\n return withIsolationScope(isolationScope, () => {\n return withScope(scope => {\n // Set a new propagationSpanId for this request\n scope.getPropagationContext().propagationSpanId = generateSpanId();\n return original.apply(this, [event, ...args]);\n });\n });\n };\n };\n }\n\n /**\n * Patch the outgoing request function for breadcrumbs.\n */\n private _getPatchOutgoingRequestFunction(component: 'http' | 'https'): (\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n original: (...args: any[]) => http.ClientRequest,\n ) => (options: URL | http.RequestOptions | string, ...args: unknown[]) => http.ClientRequest {\n // eslint-disable-next-line @typescript-eslint/no-this-alias\n const instrumentation = this;\n\n return (original: (...args: unknown[]) => http.ClientRequest): ((...args: unknown[]) => http.ClientRequest) => {\n return function outgoingRequest(this: unknown, ...args: unknown[]): http.ClientRequest {\n instrumentation._diag.debug('http instrumentation for outgoing requests');\n\n // We need to access and reconstruct the request options object passed to `ignoreOutgoingRequests`\n // so that it matches what Otel instrumentation passes to `ignoreOutgoingRequestHook`.\n // @see https://github.com/open-telemetry/opentelemetry-js/blob/7293e69c1e55ca62e15d0724d22605e61bd58952/experimental/packages/opentelemetry-instrumentation-http/src/http.ts#L756-L789\n const requestArgs = [...args] as RequestArgs;\n\n let options = requestArgs[0];\n\n // Make sure correct fallback attributes are set on the options object for https before we pass them to the vendored getRequestInfo function.\n // Ref: https://github.com/open-telemetry/opentelemetry-js/blob/887ff1cd6e3f795f703e40a9fbe89b3cba7e88c3/experimental/packages/opentelemetry-instrumentation-http/src/http.ts#L390\n if (component === 'https' && typeof options === 'object' && options?.constructor?.name !== 'URL') {\n options = Object.assign({}, options);\n options.protocol = options.protocol || 'https:';\n options.port = options.port || 443;\n }\n\n const extraOptions = typeof requestArgs[1] === 'object' ? requestArgs[1] : undefined;\n\n const { optionsParsed, origin, pathname } = getRequestInfo(instrumentation._diag, options, extraOptions);\n\n const url = getAbsoluteUrl(origin, pathname);\n\n addSentryHeadersToRequestOptions(url, optionsParsed, instrumentation._propagationDecisionMap);\n\n const request = original.apply(this, [optionsParsed, ...requestArgs.slice(1)]) as ReturnType<\n typeof http.request\n >;\n\n request.prependListener('response', (response: http.IncomingMessage) => {\n const _breadcrumbs = instrumentation.getConfig().breadcrumbs;\n const breadCrumbsEnabled = typeof _breadcrumbs === 'undefined' ? true : _breadcrumbs;\n\n const _ignoreOutgoingRequests = instrumentation.getConfig().ignoreOutgoingRequests;\n const shouldCreateBreadcrumb =\n typeof _ignoreOutgoingRequests === 'function'\n ? !_ignoreOutgoingRequests(getRequestUrl(request), optionsParsed)\n : true;\n\n if (breadCrumbsEnabled && shouldCreateBreadcrumb) {\n addRequestBreadcrumb(request, response);\n }\n });\n\n return request;\n };\n };\n }\n\n /** Path the outgoing get function for breadcrumbs. */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n private _getPatchOutgoingGetFunction(clientRequest: (...args: any[]) => http.ClientRequest) {\n return (_original: unknown): ((...args: unknown[]) => http.ClientRequest) => {\n // Re-implement http.get. This needs to be done (instead of using\n // getPatchOutgoingRequestFunction to patch it) because we need to\n // set the trace context header before the returned http.ClientRequest is\n // ended. The Node.js docs state that the only differences between\n // request and get are that (1) get defaults to the HTTP GET method and\n // (2) the returned request object is ended immediately. The former is\n // already true (at least in supported Node versions up to v10), so we\n // simply follow the latter. Ref:\n // https://nodejs.org/dist/latest/docs/api/http.html#http_http_get_options_callback\n // https://github.com/googleapis/cloud-trace-nodejs/blob/master/src/instrumentations/instrumentation-http.ts#L198\n return function outgoingGetRequest(...args: unknown[]): http.ClientRequest {\n const req = clientRequest(...args);\n req.end();\n return req;\n };\n };\n }\n}\n\n/**\n * This is a minimal version of `wrap` from shimmer:\n * https://github.com/othiym23/shimmer/blob/master/index.js\n *\n * In contrast to the original implementation, this version does not allow to unwrap,\n * and does not make it clear that the method is wrapped.\n * This is necessary because we want to wrap the http module with our own code,\n * while still allowing to use the HttpInstrumentation from OTEL.\n *\n * Without this, if we'd just use `wrap` from shimmer, the OTEL instrumentation would remove our wrapping,\n * because it only allows any module to be wrapped a single time.\n */\nfunction stealthWrap<Nodule extends object, FieldName extends keyof Nodule>(\n nodule: Nodule,\n name: FieldName,\n wrapper: (original: Nodule[FieldName]) => Nodule[FieldName],\n): Nodule[FieldName] {\n const original = nodule[name];\n const wrapped = wrapper(original);\n\n defineProperty(nodule, name, wrapped);\n return wrapped;\n}\n\n// Sets a property on an object, preserving its enumerability.\nfunction defineProperty<Nodule extends object, FieldName extends keyof Nodule>(\n obj: Nodule,\n name: FieldName,\n value: Nodule[FieldName],\n): void {\n const enumerable = !!obj[name] && Object.prototype.propertyIsEnumerable.call(obj, name);\n\n Object.defineProperty(obj, name, {\n configurable: true,\n enumerable: enumerable,\n writable: true,\n value: value,\n });\n}\n\n/** Add a breadcrumb for outgoing requests. */\nfunction addRequestBreadcrumb(request: http.ClientRequest, response: http.IncomingMessage): void {\n const data = getBreadcrumbData(request);\n\n const statusCode = response.statusCode;\n const level = getBreadcrumbLogLevelFromHttpStatusCode(statusCode);\n\n addBreadcrumb(\n {\n category: 'http',\n data: {\n status_code: statusCode,\n ...data,\n },\n type: 'http',\n level,\n },\n {\n event: 'response',\n request,\n response,\n },\n );\n}\n\nfunction getBreadcrumbData(request: http.ClientRequest): Partial<SanitizedRequestData> {\n try {\n // `request.host` does not contain the port, but the host header does\n const host = request.getHeader('host') || request.host;\n const url = new URL(request.path, `${request.protocol}//${host}`);\n const parsedUrl = parseUrl(url.toString());\n\n const data: Partial<SanitizedRequestData> = {\n url: getSanitizedUrlString(parsedUrl),\n 'http.method': request.method || 'GET',\n };\n\n if (parsedUrl.search) {\n data['http.query'] = parsedUrl.search;\n }\n if (parsedUrl.hash) {\n data['http.fragment'] = parsedUrl.hash;\n }\n\n return data;\n } catch {\n return {};\n }\n}\n\n/**\n * This method patches the request object to capture the body.\n * Instead of actually consuming the streamed body ourselves, which has potential side effects,\n * we monkey patch `req.on('data')` to intercept the body chunks.\n * This way, we only read the body if the user also consumes the body, ensuring we do not change any behavior in unexpected ways.\n */\nfunction patchRequestToCaptureBody(req: IncomingMessage, isolationScope: Scope): void {\n const chunks: Buffer[] = [];\n\n function getChunksSize(): number {\n return chunks.reduce((acc, chunk) => acc + chunk.byteLength, 0);\n }\n\n /**\n * We need to keep track of the original callbacks, in order to be able to remove listeners again.\n * Since `off` depends on having the exact same function reference passed in, we need to be able to map\n * original listeners to our wrapped ones.\n */\n const callbackMap = new WeakMap();\n\n try {\n // eslint-disable-next-line @typescript-eslint/unbound-method\n req.on = new Proxy(req.on, {\n apply: (target, thisArg, args: Parameters<typeof req.on>) => {\n const [event, listener, ...restArgs] = args;\n\n if (event === 'data') {\n const callback = new Proxy(listener, {\n apply: (target, thisArg, args: Parameters<typeof listener>) => {\n // If we have already read more than the max body length, we stop adding chunks\n // To avoid growing the memory indefinitely if a response is e.g. streamed\n if (getChunksSize() < MAX_BODY_BYTE_LENGTH) {\n const chunk = args[0] as Buffer;\n chunks.push(chunk);\n } else if (DEBUG_BUILD) {\n logger.log(\n `Dropping request body chunk because it maximum body length of ${MAX_BODY_BYTE_LENGTH}b is exceeded.`,\n );\n }\n\n return Reflect.apply(target, thisArg, args);\n },\n });\n\n callbackMap.set(listener, callback);\n\n return Reflect.apply(target, thisArg, [event, callback, ...restArgs]);\n }\n\n if (event === 'end') {\n const callback = new Proxy(listener, {\n apply: (target, thisArg, args) => {\n try {\n const body = Buffer.concat(chunks).toString('utf-8');\n\n if (body) {\n const normalizedRequest = { data: body } satisfies RequestEventData;\n isolationScope.setSDKProcessingMetadata({ normalizedRequest });\n }\n } catch {\n // ignore errors here\n }\n\n return Reflect.apply(target, thisArg, args);\n },\n });\n\n callbackMap.set(listener, callback);\n\n return Reflect.apply(target, thisArg, [event, callback, ...restArgs]);\n }\n\n return Reflect.apply(target, thisArg, args);\n },\n });\n\n // Ensure we also remove callbacks correctly\n // eslint-disable-next-line @typescript-eslint/unbound-method\n req.off = new Proxy(req.off, {\n apply: (target, thisArg, args: Parameters<typeof req.off>) => {\n const [, listener] = args;\n\n const callback = callbackMap.get(listener);\n if (callback) {\n callbackMap.delete(listener);\n\n const modifiedArgs = args.slice();\n modifiedArgs[1] = callback;\n return Reflect.apply(target, thisArg, modifiedArgs);\n }\n\n return Reflect.apply(target, thisArg, args);\n },\n });\n } catch {\n // ignore errors if we can't patch stuff\n }\n}\n\n/**\n * Mutates the passed in `options` and adds `sentry-trace` / `baggage` headers, if they are not already set.\n */\nfunction addSentryHeadersToRequestOptions(\n url: string,\n options: RequestOptions,\n propagationDecisionMap: LRUMap<string, boolean>,\n): void {\n // Manually add the trace headers, if it applies\n // Note: We do not use `propagation.inject()` here, because our propagator relies on an active span\n // Which we do not have in this case\n const tracePropagationTargets = getClient()?.getOptions().tracePropagationTargets;\n const addedHeaders = shouldPropagateTraceForUrl(url, tracePropagationTargets, propagationDecisionMap)\n ? getTraceData()\n : undefined;\n\n if (!addedHeaders) {\n return;\n }\n\n if (!options.headers) {\n options.headers = {};\n }\n const headers = options.headers;\n\n const { 'sentry-trace': sentryTrace, baggage } = addedHeaders;\n\n // We do not want to overwrite existing header here, if it was already set\n if (sentryTrace && !headers['sentry-trace']) {\n headers['sentry-trace'] = sentryTrace;\n }\n\n // For baggage, we make sure to merge this into a possibly existing header\n if (baggage) {\n headers['baggage'] = mergeBaggageHeaders(headers['baggage'], baggage);\n }\n}\n\n/**\n * Starts a session and tracks it in the context of a given isolation scope.\n * When the passed response is finished, the session is put into a task and is\n * aggregated with other sessions that may happen in a certain time window\n * (sessionFlushingDelayMs).\n *\n * The sessions are always aggregated by the client that is on the current scope\n * at the time of ending the response (if there is one).\n */\n// Exported for unit tests\nexport function recordRequestSession({\n requestIsolationScope,\n response,\n sessionFlushingDelayMS,\n}: { requestIsolationScope: Scope; response: EventEmitter; sessionFlushingDelayMS?: number }): void {\n requestIsolationScope.setSDKProcessingMetadata({\n requestSession: { status: 'ok' },\n });\n response.once('close', () => {\n // We need to grab the client off the current scope instead of the isolation scope because the isolation scope doesn't hold any client out of the box.\n const client = getClient();\n const requestSession = requestIsolationScope.getScopeData().sdkProcessingMetadata.requestSession;\n\n if (client && requestSession) {\n DEBUG_BUILD && logger.debug(`Recorded request session with status: ${requestSession.status}`);\n\n const roundedDate = new Date();\n roundedDate.setSeconds(0, 0);\n const dateBucketKey = roundedDate.toISOString();\n\n const existingClientAggregate = clientToRequestSessionAggregatesMap.get(client);\n const bucket = existingClientAggregate?.[dateBucketKey] || { exited: 0, crashed: 0, errored: 0 };\n bucket[({ ok: 'exited', crashed: 'crashed', errored: 'errored' } as const)[requestSession.status]]++;\n\n if (existingClientAggregate) {\n existingClientAggregate[dateBucketKey] = bucket;\n } else {\n DEBUG_BUILD && logger.debug('Opened new request session aggregate.');\n const newClientAggregate = { [dateBucketKey]: bucket };\n clientToRequestSessionAggregatesMap.set(client, newClientAggregate);\n\n const flushPendingClientAggregates = (): void => {\n clearTimeout(timeout);\n unregisterClientFlushHook();\n clientToRequestSessionAggregatesMap.delete(client);\n\n const aggregatePayload: AggregationCounts[] = Object.entries(newClientAggregate).map(\n ([timestamp, value]) => ({\n started: timestamp,\n exited: value.exited,\n errored: value.errored,\n crashed: value.crashed,\n }),\n );\n client.sendSession({ aggregates: aggregatePayload });\n };\n\n const unregisterClientFlushHook = client.on('flush', () => {\n DEBUG_BUILD && logger.debug('Sending request session aggregate due to client flush');\n flushPendingClientAggregates();\n });\n const timeout = setTimeout(() => {\n DEBUG_BUILD && logger.debug('Sending request session aggregate due to flushing schedule');\n flushPendingClientAggregates();\n }, sessionFlushingDelayMS).unref();\n }\n }\n });\n}\n\nconst clientToRequestSessionAggregatesMap = new Map<\n Client,\n { [timestampRoundedToSeconds: string]: { exited: number; crashed: number; errored: number } }\n>();\n\nfunction getAbsoluteUrl(origin: string, path: string = '/'): string {\n try {\n const url = new URL(path, origin);\n return url.toString();\n } catch {\n // fallback: Construct it on our own\n const url = `${origin}`;\n\n if (url.endsWith('/') && path.startsWith('/')) {\n return `${url}${path.slice(1)}`;\n }\n\n if (!url.endsWith('/') && !path.startsWith('/')) {\n return `${url}/${path.slice(1)}`;\n }\n\n return `${url}${path}`;\n }\n}\n\nfunction mergeBaggageHeaders(\n existing: string | string[] | number | undefined,\n baggage: string,\n): string | string[] | number | undefined {\n if (!existing) {\n return baggage;\n }\n\n const existingBaggageEntries = parseBaggageHeader(existing);\n const newBaggageEntries = parseBaggageHeader(baggage);\n\n if (!newBaggageEntries) {\n return existing;\n }\n\n // Existing entries take precedence, ensuring order remains stable for minimal changes\n const mergedBaggageEntries = { ...existingBaggageEntries };\n Object.entries(newBaggageEntries).forEach(([key, value]) => {\n if (!mergedBaggageEntries[key]) {\n mergedBaggageEntries[key] = value;\n }\n });\n\n return objectToBaggageHeader(mergedBaggageEntries);\n}\n"],"names":["InstrumentationBase","VERSION","LRUMap","InstrumentationNodeModuleDefinition","getIsolationScope","httpRequestToRequestData","stripUrlQueryAndFragment","withIsolationScope","withScope","generateSpanId","getRequestInfo","getRequestUrl","getBreadcrumbLogLevelFromHttpStatusCode","addBreadcrumb","parseUrl","getSanitizedUrlString","DEBUG_BUILD","logger","getClient","shouldPropagateTraceForUrl","getTraceData","parseBaggageHeader","objectToBaggageHeader"],"mappings":"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"}
@@ -6,7 +6,7 @@ const debug = require('../../utils/debug.js');
6
6
  const common = require('./common.js');
7
7
 
8
8
  // This string is a placeholder that gets overwritten with the worker code.
9
- const base64WorkerScript = 'LyohIEBzZW50cnkvbm9kZSA5LjAuMC1hbHBoYS4xIChiZTkxZjllKSB8IGh0dHBzOi8vZ2l0aHViLmNvbS9nZXRzZW50cnkvc2VudHJ5LWphdmFzY3JpcHQgKi8KaW1wb3J0e1Nlc3Npb24gYXMgZX1mcm9tIm5vZGU6aW5zcGVjdG9yL3Byb21pc2VzIjtpbXBvcnR7d29ya2VyRGF0YSBhcyB0fWZyb20ibm9kZTp3b3JrZXJfdGhyZWFkcyI7Y29uc3Qgbj1nbG9iYWxUaGlzLG89InVuZGVmaW5lZCI9PXR5cGVvZiBfX1NFTlRSWV9ERUJVR19ffHxfX1NFTlRSWV9ERUJVR19fLGE9IjkuMC4wLWFscGhhLjEiO2NvbnN0IGk9WyJkZWJ1ZyIsImluZm8iLCJ3YXJuIiwiZXJyb3IiLCJsb2ciLCJhc3NlcnQiLCJ0cmFjZSJdLHM9e307ZnVuY3Rpb24gYyhlKXtpZighKCJjb25zb2xlImluIG4pKXJldHVybiBlKCk7Y29uc3QgdD1uLmNvbnNvbGUsbz17fSxhPU9iamVjdC5rZXlzKHMpO2EuZm9yRWFjaCgoZT0+e2NvbnN0IG49c1tlXTtvW2VdPXRbZV0sdFtlXT1ufSkpO3RyeXtyZXR1cm4gZSgpfWZpbmFsbHl7YS5mb3JFYWNoKChlPT57dFtlXT1vW2VdfSkpfX0hZnVuY3Rpb24oZSx0LG89bil7Y29uc3QgaT1vLl9fU0VOVFJZX189by5fX1NFTlRSWV9ffHx7fSxzPWlbYV09aVthXXx8e307c1tlXXx8KHNbZV09dCgpKX0oImxvZ2dlciIsKGZ1bmN0aW9uKCl7bGV0IGU9ITE7Y29uc3QgdD17ZW5hYmxlOigpPT57ZT0hMH0sZGlzYWJsZTooKT0+e2U9ITF9LGlzRW5hYmxlZDooKT0+ZX07cmV0dXJuIG8/aS5mb3JFYWNoKChvPT57dFtvXT0oLi4udCk9PntlJiZjKCgoKT0+e24uY29uc29sZVtvXShgU2VudHJ5IExvZ2dlciBbJHtvfV06YCwuLi50KX0pKX19KSk6aS5mb3JFYWNoKChlPT57dFtlXT0oKT0+e319KSksdH0pKTtjb25zdCByPSJfX1NFTlRSWV9FUlJPUl9MT0NBTF9WQVJJQUJMRVNfXyI7Y29uc3QgdT10O2Z1bmN0aW9uIGwoLi4uZSl7dS5kZWJ1ZyYmYygoKCk9PmNvbnNvbGUubG9nKCJbTG9jYWxWYXJpYWJsZXMgV29ya2VyXSIsLi4uZSkpKX1hc3luYyBmdW5jdGlvbiBmKGUsdCxuLG8pe2NvbnN0IGE9YXdhaXQgZS5wb3N0KCJSdW50aW1lLmdldFByb3BlcnRpZXMiLHtvYmplY3RJZDp0LG93blByb3BlcnRpZXM6ITB9KTtvW25dPWEucmVzdWx0LmZpbHRlcigoZT0+Imxlbmd0aCIhPT1lLm5hbWUmJiFpc05hTihwYXJzZUludChlLm5hbWUsMTApKSkpLnNvcnQoKChlLHQpPT5wYXJzZUludChlLm5hbWUsMTApLXBhcnNlSW50KHQubmFtZSwxMCkpKS5tYXAoKGU9PmUudmFsdWU/LnZhbHVlKSl9YXN5bmMgZnVuY3Rpb24gZyhlLHQsbixvKXtjb25zdCBhPWF3YWl0IGUucG9zdCgiUnVudGltZS5nZXRQcm9wZXJ0aWVzIix7b2JqZWN0SWQ6dCxvd25Qcm9wZXJ0aWVzOiEwfSk7b1tuXT1hLnJlc3VsdC5tYXAoKGU9PltlLm5hbWUsZS52YWx1ZT8udmFsdWVdKSkucmVkdWNlKCgoZSxbdCxuXSk9PihlW3RdPW4sZSkpLHt9KX1mdW5jdGlvbiBkKGUsdCl7ZS52YWx1ZSYmKCJ2YWx1ZSJpbiBlLnZhbHVlP3ZvaWQgMD09PWUudmFsdWUudmFsdWV8fG51bGw9PT1lLnZhbHVlLnZhbHVlP3RbZS5uYW1lXT1gPCR7ZS52YWx1ZS52YWx1ZX0+YDp0W2UubmFtZV09ZS52YWx1ZS52YWx1ZToiZGVzY3JpcHRpb24iaW4gZS52YWx1ZSYmImZ1bmN0aW9uIiE9PWUudmFsdWUudHlwZT90W2UubmFtZV09YDwke2UudmFsdWUuZGVzY3JpcHRpb259PmA6InVuZGVmaW5lZCI9PT1lLnZhbHVlLnR5cGUmJih0W2UubmFtZV09Ijx1bmRlZmluZWQ+IikpfWFzeW5jIGZ1bmN0aW9uIGIoZSx0KXtjb25zdCBuPWF3YWl0IGUucG9zdCgiUnVudGltZS5nZXRQcm9wZXJ0aWVzIix7b2JqZWN0SWQ6dCxvd25Qcm9wZXJ0aWVzOiEwfSksbz17fTtmb3IoY29uc3QgdCBvZiBuLnJlc3VsdClpZih0LnZhbHVlPy5vYmplY3RJZCYmIkFycmF5Ij09PXQudmFsdWUuY2xhc3NOYW1lKXtjb25zdCBuPXQudmFsdWUub2JqZWN0SWQ7YXdhaXQgZihlLG4sdC5uYW1lLG8pfWVsc2UgaWYodC52YWx1ZT8ub2JqZWN0SWQmJiJPYmplY3QiPT09dC52YWx1ZS5jbGFzc05hbWUpe2NvbnN0IG49dC52YWx1ZS5vYmplY3RJZDthd2FpdCBnKGUsbix0Lm5hbWUsbyl9ZWxzZSB0LnZhbHVlJiZkKHQsbyk7cmV0dXJuIG99bGV0IHA7KGFzeW5jIGZ1bmN0aW9uKCl7Y29uc3QgdD1uZXcgZTt0LmNvbm5lY3RUb01haW5UaHJlYWQoKSxsKCJDb25uZWN0ZWQgdG8gbWFpbiB0aHJlYWQiKTtsZXQgbj0hMTt0Lm9uKCJEZWJ1Z2dlci5yZXN1bWVkIiwoKCk9PntuPSExfSkpLHQub24oIkRlYnVnZ2VyLnBhdXNlZCIsKGU9PntuPSEwLGFzeW5jIGZ1bmN0aW9uKGUse3JlYXNvbjp0LGRhdGE6e29iamVjdElkOm59LGNhbGxGcmFtZXM6b30pe2lmKCJleGNlcHRpb24iIT09dCYmInByb21pc2VSZWplY3Rpb24iIT09dClyZXR1cm47aWYocD8uKCksbnVsbD09bilyZXR1cm47Y29uc3QgYT1bXTtmb3IobGV0IHQ9MDt0PG8ubGVuZ3RoO3QrKyl7Y29uc3R7c2NvcGVDaGFpbjpuLGZ1bmN0aW9uTmFtZTppLHRoaXM6c309b1t0XSxjPW4uZmluZCgoZT0+ImxvY2FsIj09PWUudHlwZSkpLHI9Imdsb2JhbCIhPT1zLmNsYXNzTmFtZSYmcy5jbGFzc05hbWU/YCR7cy5jbGFzc05hbWV9LiR7aX1gOmk7aWYodm9pZCAwPT09Yz8ub2JqZWN0Lm9iamVjdElkKWFbdF09e2Z1bmN0aW9uOnJ9O2Vsc2V7Y29uc3Qgbj1hd2FpdCBiKGUsYy5vYmplY3Qub2JqZWN0SWQpO2FbdF09e2Z1bmN0aW9uOnIsdmFyczpufX19YXdhaXQgZS5wb3N0KCJSdW50aW1lLmNhbGxGdW5jdGlvbk9uIix7ZnVuY3Rpb25EZWNsYXJhdGlvbjpgZnVuY3Rpb24oKSB7IHRoaXMuJHtyfSA9IHRoaXMuJHtyfSB8fCAke0pTT04uc3RyaW5naWZ5KGEpfTsgfWAsc2lsZW50OiEwLG9iamVjdElkOm59KSxhd2FpdCBlLnBvc3QoIlJ1bnRpbWUucmVsZWFzZU9iamVjdCIse29iamVjdElkOm59KX0odCxlLnBhcmFtcykudGhlbigoYXN5bmMoKT0+e24mJmF3YWl0IHQucG9zdCgiRGVidWdnZXIucmVzdW1lIil9KSwoYXN5bmMgZT0+e24mJmF3YWl0IHQucG9zdCgiRGVidWdnZXIucmVzdW1lIil9KSl9KSksYXdhaXQgdC5wb3N0KCJEZWJ1Z2dlci5lbmFibGUiKTtjb25zdCBvPSExIT09dS5jYXB0dXJlQWxsRXhjZXB0aW9ucztpZihhd2FpdCB0LnBvc3QoIkRlYnVnZ2VyLnNldFBhdXNlT25FeGNlcHRpb25zIix7c3RhdGU6bz8iYWxsIjoidW5jYXVnaHQifSksbyl7Y29uc3QgZT11Lm1heEV4Y2VwdGlvbnNQZXJTZWNvbmR8fDUwO3A9ZnVuY3Rpb24oZSx0LG4pe2xldCBvPTAsYT01LGk9MDtyZXR1cm4gc2V0SW50ZXJ2YWwoKCgpPT57MD09PWk/bz5lJiYoYSo9MixuKGEpLGE+ODY0MDAmJihhPTg2NDAwKSxpPWEpOihpLT0xLDA9PT1pJiZ0KCkpLG89MH0pLDFlMykudW5yZWYoKSwoKT0+e28rPTF9fShlLChhc3luYygpPT57bCgiUmF0ZS1saW1pdCBsaWZ0ZWQuIiksYXdhaXQgdC5wb3N0KCJEZWJ1Z2dlci5zZXRQYXVzZU9uRXhjZXB0aW9ucyIse3N0YXRlOiJhbGwifSl9KSwoYXN5bmMgZT0+e2woYFJhdGUtbGltaXQgZXhjZWVkZWQuIERpc2FibGluZyBjYXB0dXJpbmcgb2YgY2F1Z2h0IGV4Y2VwdGlvbnMgZm9yICR7ZX0gc2Vjb25kcy5gKSxhd2FpdCB0LnBvc3QoIkRlYnVnZ2VyLnNldFBhdXNlT25FeGNlcHRpb25zIix7c3RhdGU6InVuY2F1Z2h0In0pfSkpfX0pKCkuY2F0Y2goKGU9PntsKCJGYWlsZWQgdG8gc3RhcnQgZGVidWdnZXIiLGUpfSkpLHNldEludGVydmFsKCgoKT0+e30pLDFlNCk7';
9
+ const base64WorkerScript = 'LyohIEBzZW50cnkvbm9kZSA5LjAuMC1hbHBoYS4yICg3YTY4MTliKSB8IGh0dHBzOi8vZ2l0aHViLmNvbS9nZXRzZW50cnkvc2VudHJ5LWphdmFzY3JpcHQgKi8KaW1wb3J0e1Nlc3Npb24gYXMgZX1mcm9tIm5vZGU6aW5zcGVjdG9yL3Byb21pc2VzIjtpbXBvcnR7d29ya2VyRGF0YSBhcyB0fWZyb20ibm9kZTp3b3JrZXJfdGhyZWFkcyI7Y29uc3Qgbj1nbG9iYWxUaGlzLG89InVuZGVmaW5lZCI9PXR5cGVvZiBfX1NFTlRSWV9ERUJVR19ffHxfX1NFTlRSWV9ERUJVR19fLGE9IjkuMC4wLWFscGhhLjIiO2NvbnN0IGk9WyJkZWJ1ZyIsImluZm8iLCJ3YXJuIiwiZXJyb3IiLCJsb2ciLCJhc3NlcnQiLCJ0cmFjZSJdLHM9e307ZnVuY3Rpb24gYyhlKXtpZighKCJjb25zb2xlImluIG4pKXJldHVybiBlKCk7Y29uc3QgdD1uLmNvbnNvbGUsbz17fSxhPU9iamVjdC5rZXlzKHMpO2EuZm9yRWFjaCgoZT0+e2NvbnN0IG49c1tlXTtvW2VdPXRbZV0sdFtlXT1ufSkpO3RyeXtyZXR1cm4gZSgpfWZpbmFsbHl7YS5mb3JFYWNoKChlPT57dFtlXT1vW2VdfSkpfX0hZnVuY3Rpb24oZSx0LG89bil7Y29uc3QgaT1vLl9fU0VOVFJZX189by5fX1NFTlRSWV9ffHx7fSxzPWlbYV09aVthXXx8e307c1tlXXx8KHNbZV09dCgpKX0oImxvZ2dlciIsKGZ1bmN0aW9uKCl7bGV0IGU9ITE7Y29uc3QgdD17ZW5hYmxlOigpPT57ZT0hMH0sZGlzYWJsZTooKT0+e2U9ITF9LGlzRW5hYmxlZDooKT0+ZX07cmV0dXJuIG8/aS5mb3JFYWNoKChvPT57dFtvXT0oLi4udCk9PntlJiZjKCgoKT0+e24uY29uc29sZVtvXShgU2VudHJ5IExvZ2dlciBbJHtvfV06YCwuLi50KX0pKX19KSk6aS5mb3JFYWNoKChlPT57dFtlXT0oKT0+e319KSksdH0pKTtjb25zdCByPSJfX1NFTlRSWV9FUlJPUl9MT0NBTF9WQVJJQUJMRVNfXyI7Y29uc3QgdT10O2Z1bmN0aW9uIGwoLi4uZSl7dS5kZWJ1ZyYmYygoKCk9PmNvbnNvbGUubG9nKCJbTG9jYWxWYXJpYWJsZXMgV29ya2VyXSIsLi4uZSkpKX1hc3luYyBmdW5jdGlvbiBmKGUsdCxuLG8pe2NvbnN0IGE9YXdhaXQgZS5wb3N0KCJSdW50aW1lLmdldFByb3BlcnRpZXMiLHtvYmplY3RJZDp0LG93blByb3BlcnRpZXM6ITB9KTtvW25dPWEucmVzdWx0LmZpbHRlcigoZT0+Imxlbmd0aCIhPT1lLm5hbWUmJiFpc05hTihwYXJzZUludChlLm5hbWUsMTApKSkpLnNvcnQoKChlLHQpPT5wYXJzZUludChlLm5hbWUsMTApLXBhcnNlSW50KHQubmFtZSwxMCkpKS5tYXAoKGU9PmUudmFsdWU/LnZhbHVlKSl9YXN5bmMgZnVuY3Rpb24gZyhlLHQsbixvKXtjb25zdCBhPWF3YWl0IGUucG9zdCgiUnVudGltZS5nZXRQcm9wZXJ0aWVzIix7b2JqZWN0SWQ6dCxvd25Qcm9wZXJ0aWVzOiEwfSk7b1tuXT1hLnJlc3VsdC5tYXAoKGU9PltlLm5hbWUsZS52YWx1ZT8udmFsdWVdKSkucmVkdWNlKCgoZSxbdCxuXSk9PihlW3RdPW4sZSkpLHt9KX1mdW5jdGlvbiBkKGUsdCl7ZS52YWx1ZSYmKCJ2YWx1ZSJpbiBlLnZhbHVlP3ZvaWQgMD09PWUudmFsdWUudmFsdWV8fG51bGw9PT1lLnZhbHVlLnZhbHVlP3RbZS5uYW1lXT1gPCR7ZS52YWx1ZS52YWx1ZX0+YDp0W2UubmFtZV09ZS52YWx1ZS52YWx1ZToiZGVzY3JpcHRpb24iaW4gZS52YWx1ZSYmImZ1bmN0aW9uIiE9PWUudmFsdWUudHlwZT90W2UubmFtZV09YDwke2UudmFsdWUuZGVzY3JpcHRpb259PmA6InVuZGVmaW5lZCI9PT1lLnZhbHVlLnR5cGUmJih0W2UubmFtZV09Ijx1bmRlZmluZWQ+IikpfWFzeW5jIGZ1bmN0aW9uIGIoZSx0KXtjb25zdCBuPWF3YWl0IGUucG9zdCgiUnVudGltZS5nZXRQcm9wZXJ0aWVzIix7b2JqZWN0SWQ6dCxvd25Qcm9wZXJ0aWVzOiEwfSksbz17fTtmb3IoY29uc3QgdCBvZiBuLnJlc3VsdClpZih0LnZhbHVlPy5vYmplY3RJZCYmIkFycmF5Ij09PXQudmFsdWUuY2xhc3NOYW1lKXtjb25zdCBuPXQudmFsdWUub2JqZWN0SWQ7YXdhaXQgZihlLG4sdC5uYW1lLG8pfWVsc2UgaWYodC52YWx1ZT8ub2JqZWN0SWQmJiJPYmplY3QiPT09dC52YWx1ZS5jbGFzc05hbWUpe2NvbnN0IG49dC52YWx1ZS5vYmplY3RJZDthd2FpdCBnKGUsbix0Lm5hbWUsbyl9ZWxzZSB0LnZhbHVlJiZkKHQsbyk7cmV0dXJuIG99bGV0IHA7KGFzeW5jIGZ1bmN0aW9uKCl7Y29uc3QgdD1uZXcgZTt0LmNvbm5lY3RUb01haW5UaHJlYWQoKSxsKCJDb25uZWN0ZWQgdG8gbWFpbiB0aHJlYWQiKTtsZXQgbj0hMTt0Lm9uKCJEZWJ1Z2dlci5yZXN1bWVkIiwoKCk9PntuPSExfSkpLHQub24oIkRlYnVnZ2VyLnBhdXNlZCIsKGU9PntuPSEwLGFzeW5jIGZ1bmN0aW9uKGUse3JlYXNvbjp0LGRhdGE6e29iamVjdElkOm59LGNhbGxGcmFtZXM6b30pe2lmKCJleGNlcHRpb24iIT09dCYmInByb21pc2VSZWplY3Rpb24iIT09dClyZXR1cm47aWYocD8uKCksbnVsbD09bilyZXR1cm47Y29uc3QgYT1bXTtmb3IobGV0IHQ9MDt0PG8ubGVuZ3RoO3QrKyl7Y29uc3R7c2NvcGVDaGFpbjpuLGZ1bmN0aW9uTmFtZTppLHRoaXM6c309b1t0XSxjPW4uZmluZCgoZT0+ImxvY2FsIj09PWUudHlwZSkpLHI9Imdsb2JhbCIhPT1zLmNsYXNzTmFtZSYmcy5jbGFzc05hbWU/YCR7cy5jbGFzc05hbWV9LiR7aX1gOmk7aWYodm9pZCAwPT09Yz8ub2JqZWN0Lm9iamVjdElkKWFbdF09e2Z1bmN0aW9uOnJ9O2Vsc2V7Y29uc3Qgbj1hd2FpdCBiKGUsYy5vYmplY3Qub2JqZWN0SWQpO2FbdF09e2Z1bmN0aW9uOnIsdmFyczpufX19YXdhaXQgZS5wb3N0KCJSdW50aW1lLmNhbGxGdW5jdGlvbk9uIix7ZnVuY3Rpb25EZWNsYXJhdGlvbjpgZnVuY3Rpb24oKSB7IHRoaXMuJHtyfSA9IHRoaXMuJHtyfSB8fCAke0pTT04uc3RyaW5naWZ5KGEpfTsgfWAsc2lsZW50OiEwLG9iamVjdElkOm59KSxhd2FpdCBlLnBvc3QoIlJ1bnRpbWUucmVsZWFzZU9iamVjdCIse29iamVjdElkOm59KX0odCxlLnBhcmFtcykudGhlbigoYXN5bmMoKT0+e24mJmF3YWl0IHQucG9zdCgiRGVidWdnZXIucmVzdW1lIil9KSwoYXN5bmMgZT0+e24mJmF3YWl0IHQucG9zdCgiRGVidWdnZXIucmVzdW1lIil9KSl9KSksYXdhaXQgdC5wb3N0KCJEZWJ1Z2dlci5lbmFibGUiKTtjb25zdCBvPSExIT09dS5jYXB0dXJlQWxsRXhjZXB0aW9ucztpZihhd2FpdCB0LnBvc3QoIkRlYnVnZ2VyLnNldFBhdXNlT25FeGNlcHRpb25zIix7c3RhdGU6bz8iYWxsIjoidW5jYXVnaHQifSksbyl7Y29uc3QgZT11Lm1heEV4Y2VwdGlvbnNQZXJTZWNvbmR8fDUwO3A9ZnVuY3Rpb24oZSx0LG4pe2xldCBvPTAsYT01LGk9MDtyZXR1cm4gc2V0SW50ZXJ2YWwoKCgpPT57MD09PWk/bz5lJiYoYSo9MixuKGEpLGE+ODY0MDAmJihhPTg2NDAwKSxpPWEpOihpLT0xLDA9PT1pJiZ0KCkpLG89MH0pLDFlMykudW5yZWYoKSwoKT0+e28rPTF9fShlLChhc3luYygpPT57bCgiUmF0ZS1saW1pdCBsaWZ0ZWQuIiksYXdhaXQgdC5wb3N0KCJEZWJ1Z2dlci5zZXRQYXVzZU9uRXhjZXB0aW9ucyIse3N0YXRlOiJhbGwifSl9KSwoYXN5bmMgZT0+e2woYFJhdGUtbGltaXQgZXhjZWVkZWQuIERpc2FibGluZyBjYXB0dXJpbmcgb2YgY2F1Z2h0IGV4Y2VwdGlvbnMgZm9yICR7ZX0gc2Vjb25kcy5gKSxhd2FpdCB0LnBvc3QoIkRlYnVnZ2VyLnNldFBhdXNlT25FeGNlcHRpb25zIix7c3RhdGU6InVuY2F1Z2h0In0pfSkpfX0pKCkuY2F0Y2goKGU9PntsKCJGYWlsZWQgdG8gc3RhcnQgZGVidWdnZXIiLGUpfSkpLHNldEludGVydmFsKCgoKT0+e30pLDFlNCk7';
10
10
 
11
11
  function log(...args) {
12
12
  core.logger.log('[LocalVariables]', ...args);
@@ -24,9 +24,9 @@ const _nativeNodeFetchIntegration = ((options = {}) => {
24
24
  return true;
25
25
  }
26
26
 
27
- // If tracing is disabled, we still want to propagate traces
27
+ // If span recording is disabled, we still want to propagate traces
28
28
  // So we do that manually here, matching what the instrumentation does otherwise
29
- if (!core.hasTracingEnabled()) {
29
+ if (!core.hasSpansEnabled()) {
30
30
  const tracePropagationTargets = core.getClient()?.getOptions().tracePropagationTargets;
31
31
  const addedHeaders = opentelemetry.shouldPropagateTraceForUrl(url, tracePropagationTargets, propagationDecisionMap)
32
32
  ? core.getTraceData()
@@ -1 +1 @@
1
- {"version":3,"file":"node-fetch.js","sources":["../../../src/integrations/node-fetch.ts"],"sourcesContent":["import { registerInstrumentations } from '@opentelemetry/instrumentation';\nimport type { UndiciRequest, UndiciResponse } from '@opentelemetry/instrumentation-undici';\nimport { UndiciInstrumentation } from '@opentelemetry/instrumentation-undici';\nimport type { IntegrationFn, SanitizedRequestData } from '@sentry/core';\nimport {\n LRUMap,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n addBreadcrumb,\n defineIntegration,\n getBreadcrumbLogLevelFromHttpStatusCode,\n getClient,\n getSanitizedUrlString,\n getTraceData,\n hasTracingEnabled,\n parseUrl,\n} from '@sentry/core';\nimport { shouldPropagateTraceForUrl } from '@sentry/opentelemetry';\n\ninterface NodeFetchOptions {\n /**\n * Whether breadcrumbs should be recorded for requests.\n * Defaults to true\n */\n breadcrumbs?: boolean;\n\n /**\n * Do not capture spans or breadcrumbs for outgoing fetch requests to URLs where the given callback returns `true`.\n * This controls both span & breadcrumb creation - spans will be non recording if tracing is disabled.\n */\n ignoreOutgoingRequests?: (url: string) => boolean;\n}\n\nconst _nativeNodeFetchIntegration = ((options: NodeFetchOptions = {}) => {\n const _breadcrumbs = typeof options.breadcrumbs === 'undefined' ? true : options.breadcrumbs;\n const _ignoreOutgoingRequests = options.ignoreOutgoingRequests;\n\n return {\n name: 'NodeFetch',\n setupOnce() {\n const propagationDecisionMap = new LRUMap<string, boolean>(100);\n\n const instrumentation = new UndiciInstrumentation({\n requireParentforSpans: false,\n ignoreRequestHook: request => {\n const url = getAbsoluteUrl(request.origin, request.path);\n const shouldIgnore = _ignoreOutgoingRequests && url && _ignoreOutgoingRequests(url);\n\n if (shouldIgnore) {\n return true;\n }\n\n // If tracing is disabled, we still want to propagate traces\n // So we do that manually here, matching what the instrumentation does otherwise\n if (!hasTracingEnabled()) {\n const tracePropagationTargets = getClient()?.getOptions().tracePropagationTargets;\n const addedHeaders = shouldPropagateTraceForUrl(url, tracePropagationTargets, propagationDecisionMap)\n ? getTraceData()\n : {};\n\n const requestHeaders = request.headers;\n if (Array.isArray(requestHeaders)) {\n Object.entries(addedHeaders).forEach(headers => requestHeaders.push(...headers));\n } else {\n request.headers += Object.entries(addedHeaders)\n .map(([k, v]) => `${k}: ${v}\\r\\n`)\n .join('');\n }\n\n // Prevent starting a span for this request\n return true;\n }\n\n return false;\n },\n startSpanHook: () => {\n return {\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.http.otel.node_fetch',\n };\n },\n responseHook: (_, { request, response }) => {\n if (_breadcrumbs) {\n addRequestBreadcrumb(request, response);\n }\n },\n });\n\n registerInstrumentations({ instrumentations: [instrumentation] });\n },\n };\n}) satisfies IntegrationFn;\n\nexport const nativeNodeFetchIntegration = defineIntegration(_nativeNodeFetchIntegration);\n\n/** Add a breadcrumb for outgoing requests. */\nfunction addRequestBreadcrumb(request: UndiciRequest, response: UndiciResponse): void {\n const data = getBreadcrumbData(request);\n const statusCode = response.statusCode;\n const level = getBreadcrumbLogLevelFromHttpStatusCode(statusCode);\n\n addBreadcrumb(\n {\n category: 'http',\n data: {\n status_code: statusCode,\n ...data,\n },\n type: 'http',\n level,\n },\n {\n event: 'response',\n request,\n response,\n },\n );\n}\n\nfunction getBreadcrumbData(request: UndiciRequest): Partial<SanitizedRequestData> {\n try {\n const url = new URL(request.path, request.origin);\n const parsedUrl = parseUrl(url.toString());\n\n const data: Partial<SanitizedRequestData> = {\n url: getSanitizedUrlString(parsedUrl),\n 'http.method': request.method || 'GET',\n };\n\n if (parsedUrl.search) {\n data['http.query'] = parsedUrl.search;\n }\n if (parsedUrl.hash) {\n data['http.fragment'] = parsedUrl.hash;\n }\n\n return data;\n } catch {\n return {};\n }\n}\n\n// Matching the behavior of the base instrumentation\nfunction getAbsoluteUrl(origin: string, path: string = '/'): string {\n const url = `${origin}`;\n\n if (url.endsWith('/') && path.startsWith('/')) {\n return `${url}${path.slice(1)}`;\n }\n\n if (!url.endsWith('/') && !path.startsWith('/')) {\n return `${url}/${path.slice(1)}`;\n }\n\n return `${url}${path}`;\n}\n"],"names":["LRUMap","instrumentation","UndiciInstrumentation","hasTracingEnabled","getClient","shouldPropagateTraceForUrl","getTraceData","SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN","registerInstrumentations","defineIntegration","getBreadcrumbLogLevelFromHttpStatusCode","addBreadcrumb","parseUrl","getSanitizedUrlString"],"mappings":"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"}
1
+ {"version":3,"file":"node-fetch.js","sources":["../../../src/integrations/node-fetch.ts"],"sourcesContent":["import { registerInstrumentations } from '@opentelemetry/instrumentation';\nimport type { UndiciRequest, UndiciResponse } from '@opentelemetry/instrumentation-undici';\nimport { UndiciInstrumentation } from '@opentelemetry/instrumentation-undici';\nimport type { IntegrationFn, SanitizedRequestData } from '@sentry/core';\nimport {\n LRUMap,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n addBreadcrumb,\n defineIntegration,\n getBreadcrumbLogLevelFromHttpStatusCode,\n getClient,\n getSanitizedUrlString,\n getTraceData,\n hasSpansEnabled,\n parseUrl,\n} from '@sentry/core';\nimport { shouldPropagateTraceForUrl } from '@sentry/opentelemetry';\n\ninterface NodeFetchOptions {\n /**\n * Whether breadcrumbs should be recorded for requests.\n * Defaults to true\n */\n breadcrumbs?: boolean;\n\n /**\n * Do not capture spans or breadcrumbs for outgoing fetch requests to URLs where the given callback returns `true`.\n * This controls both span & breadcrumb creation - spans will be non recording if tracing is disabled.\n */\n ignoreOutgoingRequests?: (url: string) => boolean;\n}\n\nconst _nativeNodeFetchIntegration = ((options: NodeFetchOptions = {}) => {\n const _breadcrumbs = typeof options.breadcrumbs === 'undefined' ? true : options.breadcrumbs;\n const _ignoreOutgoingRequests = options.ignoreOutgoingRequests;\n\n return {\n name: 'NodeFetch',\n setupOnce() {\n const propagationDecisionMap = new LRUMap<string, boolean>(100);\n\n const instrumentation = new UndiciInstrumentation({\n requireParentforSpans: false,\n ignoreRequestHook: request => {\n const url = getAbsoluteUrl(request.origin, request.path);\n const shouldIgnore = _ignoreOutgoingRequests && url && _ignoreOutgoingRequests(url);\n\n if (shouldIgnore) {\n return true;\n }\n\n // If span recording is disabled, we still want to propagate traces\n // So we do that manually here, matching what the instrumentation does otherwise\n if (!hasSpansEnabled()) {\n const tracePropagationTargets = getClient()?.getOptions().tracePropagationTargets;\n const addedHeaders = shouldPropagateTraceForUrl(url, tracePropagationTargets, propagationDecisionMap)\n ? getTraceData()\n : {};\n\n const requestHeaders = request.headers;\n if (Array.isArray(requestHeaders)) {\n Object.entries(addedHeaders).forEach(headers => requestHeaders.push(...headers));\n } else {\n request.headers += Object.entries(addedHeaders)\n .map(([k, v]) => `${k}: ${v}\\r\\n`)\n .join('');\n }\n\n // Prevent starting a span for this request\n return true;\n }\n\n return false;\n },\n startSpanHook: () => {\n return {\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.http.otel.node_fetch',\n };\n },\n responseHook: (_, { request, response }) => {\n if (_breadcrumbs) {\n addRequestBreadcrumb(request, response);\n }\n },\n });\n\n registerInstrumentations({ instrumentations: [instrumentation] });\n },\n };\n}) satisfies IntegrationFn;\n\nexport const nativeNodeFetchIntegration = defineIntegration(_nativeNodeFetchIntegration);\n\n/** Add a breadcrumb for outgoing requests. */\nfunction addRequestBreadcrumb(request: UndiciRequest, response: UndiciResponse): void {\n const data = getBreadcrumbData(request);\n const statusCode = response.statusCode;\n const level = getBreadcrumbLogLevelFromHttpStatusCode(statusCode);\n\n addBreadcrumb(\n {\n category: 'http',\n data: {\n status_code: statusCode,\n ...data,\n },\n type: 'http',\n level,\n },\n {\n event: 'response',\n request,\n response,\n },\n );\n}\n\nfunction getBreadcrumbData(request: UndiciRequest): Partial<SanitizedRequestData> {\n try {\n const url = new URL(request.path, request.origin);\n const parsedUrl = parseUrl(url.toString());\n\n const data: Partial<SanitizedRequestData> = {\n url: getSanitizedUrlString(parsedUrl),\n 'http.method': request.method || 'GET',\n };\n\n if (parsedUrl.search) {\n data['http.query'] = parsedUrl.search;\n }\n if (parsedUrl.hash) {\n data['http.fragment'] = parsedUrl.hash;\n }\n\n return data;\n } catch {\n return {};\n }\n}\n\n// Matching the behavior of the base instrumentation\nfunction getAbsoluteUrl(origin: string, path: string = '/'): string {\n const url = `${origin}`;\n\n if (url.endsWith('/') && path.startsWith('/')) {\n return `${url}${path.slice(1)}`;\n }\n\n if (!url.endsWith('/') && !path.startsWith('/')) {\n return `${url}/${path.slice(1)}`;\n }\n\n return `${url}${path}`;\n}\n"],"names":["LRUMap","instrumentation","UndiciInstrumentation","hasSpansEnabled","getClient","shouldPropagateTraceForUrl","getTraceData","SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN","registerInstrumentations","defineIntegration","getBreadcrumbLogLevelFromHttpStatusCode","addBreadcrumb","parseUrl","getSanitizedUrlString"],"mappings":";;;;;;;AAgCA,MAAM,2BAAA,IAA+B,CAAC,OAAO,GAAqB,EAAE,KAAK;AACzE,EAAE,MAAM,YAAA,GAAe,OAAO,OAAO,CAAC,WAAA,KAAgB,WAAA,GAAc,IAAA,GAAO,OAAO,CAAC,WAAW;AAC9F,EAAE,MAAM,uBAAA,GAA0B,OAAO,CAAC,sBAAsB;;AAEhE,EAAE,OAAO;AACT,IAAI,IAAI,EAAE,WAAW;AACrB,IAAI,SAAS,GAAG;AAChB,MAAM,MAAM,sBAAuB,GAAE,IAAIA,WAAM,CAAkB,GAAG,CAAC;;AAErE,MAAM,MAAMC,iBAAA,GAAkB,IAAIC,2CAAqB,CAAC;AACxD,QAAQ,qBAAqB,EAAE,KAAK;AACpC,QAAQ,iBAAiB,EAAE,OAAA,IAAW;AACtC,UAAU,MAAM,GAAA,GAAM,cAAc,CAAC,OAAO,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,CAAC;AAClE,UAAU,MAAM,YAAa,GAAE,uBAAwB,IAAG,OAAO,uBAAuB,CAAC,GAAG,CAAC;;AAE7F,UAAU,IAAI,YAAY,EAAE;AAC5B,YAAY,OAAO,IAAI;AACvB;;AAEA;AACA;AACA,UAAU,IAAI,CAACC,oBAAe,EAAE,EAAE;AAClC,YAAY,MAAM,uBAAwB,GAAEC,cAAS,EAAE,EAAE,UAAU,EAAE,CAAC,uBAAuB;AAC7F,YAAY,MAAM,eAAeC,wCAA0B,CAAC,GAAG,EAAE,uBAAuB,EAAE,sBAAsB;AAChH,gBAAgBC,iBAAY;AAC5B,gBAAgB,EAAE;;AAElB,YAAY,MAAM,cAAA,GAAiB,OAAO,CAAC,OAAO;AAClD,YAAY,IAAI,KAAK,CAAC,OAAO,CAAC,cAAc,CAAC,EAAE;AAC/C,cAAc,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC,OAAO,CAAC,OAAQ,IAAG,cAAc,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,CAAC;AAC9F,mBAAmB;AACnB,cAAc,OAAO,CAAC,OAAQ,IAAG,MAAM,CAAC,OAAO,CAAC,YAAY;AAC5D,iBAAiB,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,EAAA,CAAA,CAAA,EAAA,EAAA,CAAA,CAAA,IAAA,CAAA;AACA,iBAAA,IAAA,CAAA,EAAA,CAAA;AACA;;AAEA;AACA,YAAA,OAAA,IAAA;AACA;;AAEA,UAAA,OAAA,KAAA;AACA,SAAA;AACA,QAAA,aAAA,EAAA,MAAA;AACA,UAAA,OAAA;AACA,YAAA,CAAAC,qCAAA,GAAA,2BAAA;AACA,WAAA;AACA,SAAA;AACA,QAAA,YAAA,EAAA,CAAA,CAAA,EAAA,EAAA,OAAA,EAAA,QAAA,EAAA,KAAA;AACA,UAAA,IAAA,YAAA,EAAA;AACA,YAAA,oBAAA,CAAA,OAAA,EAAA,QAAA,CAAA;AACA;AACA,SAAA;AACA,OAAA,CAAA;;AAEA,MAAAC,wCAAA,CAAA,EAAA,gBAAA,EAAA,CAAAP,iBAAA,CAAA,EAAA,CAAA;AACA,KAAA;AACA,GAAA;AACA,CAAA,CAAA;;AAEA,MAAA,0BAAA,GAAAQ,sBAAA,CAAA,2BAAA;;AAEA;AACA,SAAA,oBAAA,CAAA,OAAA,EAAA,QAAA,EAAA;AACA,EAAA,MAAA,IAAA,GAAA,iBAAA,CAAA,OAAA,CAAA;AACA,EAAA,MAAA,UAAA,GAAA,QAAA,CAAA,UAAA;AACA,EAAA,MAAA,KAAA,GAAAC,4CAAA,CAAA,UAAA,CAAA;;AAEA,EAAAC,kBAAA;AACA,IAAA;AACA,MAAA,QAAA,EAAA,MAAA;AACA,MAAA,IAAA,EAAA;AACA,QAAA,WAAA,EAAA,UAAA;AACA,QAAA,GAAA,IAAA;AACA,OAAA;AACA,MAAA,IAAA,EAAA,MAAA;AACA,MAAA,KAAA;AACA,KAAA;AACA,IAAA;AACA,MAAA,KAAA,EAAA,UAAA;AACA,MAAA,OAAA;AACA,MAAA,QAAA;AACA,KAAA;AACA,GAAA;AACA;;AAEA,SAAA,iBAAA,CAAA,OAAA,EAAA;AACA,EAAA,IAAA;AACA,IAAA,MAAA,GAAA,GAAA,IAAA,GAAA,CAAA,OAAA,CAAA,IAAA,EAAA,OAAA,CAAA,MAAA,CAAA;AACA,IAAA,MAAA,SAAA,GAAAC,aAAA,CAAA,GAAA,CAAA,QAAA,EAAA,CAAA;;AAEA,IAAA,MAAA,IAAA,GAAA;AACA,MAAA,GAAA,EAAAC,0BAAA,CAAA,SAAA,CAAA;AACA,MAAA,aAAA,EAAA,OAAA,CAAA,MAAA,IAAA,KAAA;AACA,KAAA;;AAEA,IAAA,IAAA,SAAA,CAAA,MAAA,EAAA;AACA,MAAA,IAAA,CAAA,YAAA,CAAA,GAAA,SAAA,CAAA,MAAA;AACA;AACA,IAAA,IAAA,SAAA,CAAA,IAAA,EAAA;AACA,MAAA,IAAA,CAAA,eAAA,CAAA,GAAA,SAAA,CAAA,IAAA;AACA;;AAEA,IAAA,OAAA,IAAA;AACA,GAAA,CAAA,MAAA;AACA,IAAA,OAAA,EAAA;AACA;AACA;;AAEA;AACA,SAAA,cAAA,CAAA,MAAA,EAAA,IAAA,GAAA,GAAA,EAAA;AACA,EAAA,MAAA,GAAA,GAAA,CAAA,EAAA,MAAA,CAAA,CAAA;;AAEA,EAAA,IAAA,GAAA,CAAA,QAAA,CAAA,GAAA,CAAA,IAAA,IAAA,CAAA,UAAA,CAAA,GAAA,CAAA,EAAA;AACA,IAAA,OAAA,CAAA,EAAA,GAAA,CAAA,EAAA,IAAA,CAAA,KAAA,CAAA,CAAA,CAAA,CAAA,CAAA;AACA;;AAEA,EAAA,IAAA,CAAA,GAAA,CAAA,QAAA,CAAA,GAAA,CAAA,IAAA,CAAA,IAAA,CAAA,UAAA,CAAA,GAAA,CAAA,EAAA;AACA,IAAA,OAAA,CAAA,EAAA,GAAA,CAAA,CAAA,EAAA,IAAA,CAAA,KAAA,CAAA,CAAA,CAAA,CAAA,CAAA;AACA;;AAEA,EAAA,OAAA,CAAA,EAAA,GAAA,CAAA,EAAA,IAAA,CAAA,CAAA;AACA;;;;"}
@@ -7,11 +7,13 @@ const instrumentation = require('./instrumentation.js');
7
7
 
8
8
  /* eslint-disable complexity */
9
9
 
10
- const instrumentVercelAi = instrument.generateInstrumentOnce('vercelAI', () => new instrumentation.SentryVercelAiInstrumentation({}));
10
+ const INTEGRATION_NAME = 'VercelAI';
11
+
12
+ const instrumentVercelAi = instrument.generateInstrumentOnce(INTEGRATION_NAME, () => new instrumentation.SentryVercelAiInstrumentation({}));
11
13
 
12
14
  const _vercelAIIntegration = (() => {
13
15
  return {
14
- name: 'vercelAI',
16
+ name: INTEGRATION_NAME,
15
17
  setupOnce() {
16
18
  instrumentVercelAi();
17
19
  },