@sentry/node 9.16.1 → 9.18.0

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 (80) hide show
  1. package/build/cjs/index.js +18 -18
  2. package/build/cjs/integrations/anr/index.js +1 -1
  3. package/build/cjs/integrations/http/SentryHttpInstrumentation.js +61 -0
  4. package/build/cjs/integrations/http/SentryHttpInstrumentation.js.map +1 -1
  5. package/build/cjs/integrations/http/index.js +3 -0
  6. package/build/cjs/integrations/http/index.js.map +1 -1
  7. package/build/cjs/integrations/local-variables/local-variables-async.js +1 -1
  8. package/build/cjs/integrations/tracing/fastify/index.js +187 -0
  9. package/build/cjs/integrations/tracing/fastify/index.js.map +1 -0
  10. package/build/cjs/integrations/tracing/fastify/v3/constants.js +23 -0
  11. package/build/cjs/integrations/tracing/fastify/v3/constants.js.map +1 -0
  12. package/build/cjs/integrations/tracing/fastify/v3/enums/AttributeNames.js +37 -0
  13. package/build/cjs/integrations/tracing/fastify/v3/enums/AttributeNames.js.map +1 -0
  14. package/build/cjs/integrations/tracing/fastify/v3/instrumentation.js +303 -0
  15. package/build/cjs/integrations/tracing/fastify/v3/instrumentation.js.map +1 -0
  16. package/build/cjs/integrations/tracing/fastify/v3/utils.js +135 -0
  17. package/build/cjs/integrations/tracing/fastify/v3/utils.js.map +1 -0
  18. package/build/cjs/integrations/tracing/index.js +11 -10
  19. package/build/cjs/integrations/tracing/index.js.map +1 -1
  20. package/build/cjs/sdk/initOtel.js +1 -1
  21. package/build/cjs/sdk/initOtel.js.map +1 -1
  22. package/build/esm/index.js +1 -1
  23. package/build/esm/integrations/anr/index.js +1 -1
  24. package/build/esm/integrations/anr/worker-script.js +2 -2
  25. package/build/esm/integrations/http/SentryHttpInstrumentation.js +62 -1
  26. package/build/esm/integrations/http/SentryHttpInstrumentation.js.map +1 -1
  27. package/build/esm/integrations/http/index.js +3 -0
  28. package/build/esm/integrations/http/index.js.map +1 -1
  29. package/build/esm/integrations/local-variables/local-variables-async.js +1 -1
  30. package/build/esm/integrations/local-variables/worker-script.js +2 -2
  31. package/build/esm/integrations/tracing/fastify/index.js +182 -0
  32. package/build/esm/integrations/tracing/fastify/index.js.map +1 -0
  33. package/build/esm/integrations/tracing/fastify/v3/constants.js +21 -0
  34. package/build/esm/integrations/tracing/fastify/v3/constants.js.map +1 -0
  35. package/build/esm/integrations/tracing/fastify/v3/enums/AttributeNames.js +37 -0
  36. package/build/esm/integrations/tracing/fastify/v3/enums/AttributeNames.js.map +1 -0
  37. package/build/esm/integrations/tracing/fastify/v3/instrumentation.js +301 -0
  38. package/build/esm/integrations/tracing/fastify/v3/instrumentation.js.map +1 -0
  39. package/build/esm/integrations/tracing/fastify/v3/utils.js +131 -0
  40. package/build/esm/integrations/tracing/fastify/v3/utils.js.map +1 -0
  41. package/build/esm/integrations/tracing/index.js +2 -1
  42. package/build/esm/integrations/tracing/index.js.map +1 -1
  43. package/build/esm/package.json +1 -1
  44. package/build/esm/sdk/initOtel.js +1 -1
  45. package/build/esm/sdk/initOtel.js.map +1 -1
  46. package/build/types/integrations/http/SentryHttpInstrumentation.d.ts +14 -0
  47. package/build/types/integrations/http/SentryHttpInstrumentation.d.ts.map +1 -1
  48. package/build/types/integrations/http/index.d.ts.map +1 -1
  49. package/build/{types-ts3.8/integrations/tracing/fastify.d.ts → types/integrations/tracing/fastify/index.d.ts} +83 -103
  50. package/build/types/integrations/tracing/fastify/index.d.ts.map +1 -0
  51. package/build/types/integrations/tracing/fastify/types.d.ts +25 -0
  52. package/build/types/integrations/tracing/fastify/types.d.ts.map +1 -0
  53. package/build/types/integrations/tracing/fastify/v3/constants.d.ts +3 -0
  54. package/build/types/integrations/tracing/fastify/v3/constants.d.ts.map +1 -0
  55. package/build/types/integrations/tracing/fastify/v3/enums/AttributeNames.d.ts +15 -0
  56. package/build/types/integrations/tracing/fastify/v3/enums/AttributeNames.d.ts.map +1 -0
  57. package/build/types/integrations/tracing/fastify/v3/instrumentation.d.ts +16 -0
  58. package/build/types/integrations/tracing/fastify/v3/instrumentation.d.ts.map +1 -0
  59. package/build/types/integrations/tracing/fastify/v3/internal-types.d.ts +7 -0
  60. package/build/types/integrations/tracing/fastify/v3/internal-types.d.ts.map +1 -0
  61. package/build/types/integrations/tracing/fastify/v3/types.d.ts +21 -0
  62. package/build/types/integrations/tracing/fastify/v3/types.d.ts.map +1 -0
  63. package/build/types/integrations/tracing/fastify/v3/utils.d.ts +28 -0
  64. package/build/types/integrations/tracing/fastify/v3/utils.d.ts.map +1 -0
  65. package/build/types/integrations/tracing/index.d.ts.map +1 -1
  66. package/build/types-ts3.8/integrations/http/SentryHttpInstrumentation.d.ts +14 -0
  67. package/build/{types/integrations/tracing/fastify.d.ts → types-ts3.8/integrations/tracing/fastify/index.d.ts} +83 -103
  68. package/build/types-ts3.8/integrations/tracing/fastify/types.d.ts +25 -0
  69. package/build/types-ts3.8/integrations/tracing/fastify/v3/constants.d.ts +3 -0
  70. package/build/types-ts3.8/integrations/tracing/fastify/v3/enums/AttributeNames.d.ts +15 -0
  71. package/build/types-ts3.8/integrations/tracing/fastify/v3/instrumentation.d.ts +16 -0
  72. package/build/types-ts3.8/integrations/tracing/fastify/v3/internal-types.d.ts +7 -0
  73. package/build/types-ts3.8/integrations/tracing/fastify/v3/types.d.ts +21 -0
  74. package/build/types-ts3.8/integrations/tracing/fastify/v3/utils.d.ts +28 -0
  75. package/package.json +5 -5
  76. package/build/cjs/integrations/tracing/fastify.js +0 -160
  77. package/build/cjs/integrations/tracing/fastify.js.map +0 -1
  78. package/build/esm/integrations/tracing/fastify.js +0 -156
  79. package/build/esm/integrations/tracing/fastify.js.map +0 -1
  80. package/build/types/integrations/tracing/fastify.d.ts.map +0 -1
@@ -12,7 +12,7 @@ const onuncaughtexception = require('./integrations/onuncaughtexception.js');
12
12
  const onunhandledrejection = require('./integrations/onunhandledrejection.js');
13
13
  const index$3 = require('./integrations/anr/index.js');
14
14
  const express = require('./integrations/tracing/express.js');
15
- const fastify = require('./integrations/tracing/fastify.js');
15
+ const index$4 = require('./integrations/tracing/fastify/index.js');
16
16
  const graphql = require('./integrations/tracing/graphql.js');
17
17
  const kafka = require('./integrations/tracing/kafka.js');
18
18
  const lrumemoizer = require('./integrations/tracing/lrumemoizer.js');
@@ -23,7 +23,7 @@ const mysql2 = require('./integrations/tracing/mysql2.js');
23
23
  const redis = require('./integrations/tracing/redis.js');
24
24
  const postgres = require('./integrations/tracing/postgres.js');
25
25
  const prisma = require('./integrations/tracing/prisma.js');
26
- const index$4 = require('./integrations/tracing/hapi/index.js');
26
+ const index$5 = require('./integrations/tracing/hapi/index.js');
27
27
  const koa = require('./integrations/tracing/koa.js');
28
28
  const connect = require('./integrations/tracing/connect.js');
29
29
  const spotlight = require('./integrations/spotlight.js');
@@ -32,19 +32,19 @@ const tedious = require('./integrations/tracing/tedious.js');
32
32
  const genericPool = require('./integrations/tracing/genericPool.js');
33
33
  const dataloader = require('./integrations/tracing/dataloader.js');
34
34
  const amqplib = require('./integrations/tracing/amqplib.js');
35
- const index$5 = require('./integrations/tracing/vercelai/index.js');
35
+ const index$6 = require('./integrations/tracing/vercelai/index.js');
36
36
  const childProcess = require('./integrations/childProcess.js');
37
37
  const winston = require('./integrations/winston.js');
38
38
  const contextManager = require('./otel/contextManager.js');
39
39
  const instrument = require('./otel/instrument.js');
40
- const index$6 = require('./sdk/index.js');
40
+ const index$7 = require('./sdk/index.js');
41
41
  const initOtel = require('./sdk/initOtel.js');
42
- const index$7 = require('./integrations/tracing/index.js');
42
+ const index$8 = require('./integrations/tracing/index.js');
43
43
  const api = require('./sdk/api.js');
44
44
  const module$1 = require('./utils/module.js');
45
45
  const http = require('./transports/http.js');
46
46
  const client = require('./sdk/client.js');
47
- const index$8 = require('./cron/index.js');
47
+ const index$9 = require('./cron/index.js');
48
48
  const opentelemetry = require('@sentry/opentelemetry');
49
49
  const core = require('@sentry/core');
50
50
 
@@ -65,8 +65,8 @@ exports.disableAnrDetectionForCallback = index$3.disableAnrDetectionForCallback;
65
65
  exports.expressErrorHandler = express.expressErrorHandler;
66
66
  exports.expressIntegration = express.expressIntegration;
67
67
  exports.setupExpressErrorHandler = express.setupExpressErrorHandler;
68
- exports.fastifyIntegration = fastify.fastifyIntegration;
69
- exports.setupFastifyErrorHandler = fastify.setupFastifyErrorHandler;
68
+ exports.fastifyIntegration = index$4.fastifyIntegration;
69
+ exports.setupFastifyErrorHandler = index$4.setupFastifyErrorHandler;
70
70
  exports.graphqlIntegration = graphql.graphqlIntegration;
71
71
  exports.kafkaIntegration = kafka.kafkaIntegration;
72
72
  exports.lruMemoizerIntegration = lrumemoizer.lruMemoizerIntegration;
@@ -77,8 +77,8 @@ exports.mysql2Integration = mysql2.mysql2Integration;
77
77
  exports.redisIntegration = redis.redisIntegration;
78
78
  exports.postgresIntegration = postgres.postgresIntegration;
79
79
  exports.prismaIntegration = prisma.prismaIntegration;
80
- exports.hapiIntegration = index$4.hapiIntegration;
81
- exports.setupHapiErrorHandler = index$4.setupHapiErrorHandler;
80
+ exports.hapiIntegration = index$5.hapiIntegration;
81
+ exports.setupHapiErrorHandler = index$5.setupHapiErrorHandler;
82
82
  exports.koaIntegration = koa.koaIntegration;
83
83
  exports.setupKoaErrorHandler = koa.setupKoaErrorHandler;
84
84
  exports.connectIntegration = connect.connectIntegration;
@@ -89,25 +89,25 @@ exports.tediousIntegration = tedious.tediousIntegration;
89
89
  exports.genericPoolIntegration = genericPool.genericPoolIntegration;
90
90
  exports.dataloaderIntegration = dataloader.dataloaderIntegration;
91
91
  exports.amqplibIntegration = amqplib.amqplibIntegration;
92
- exports.vercelAIIntegration = index$5.vercelAIIntegration;
92
+ exports.vercelAIIntegration = index$6.vercelAIIntegration;
93
93
  exports.childProcessIntegration = childProcess.childProcessIntegration;
94
94
  exports.createSentryWinstonTransport = winston.createSentryWinstonTransport;
95
95
  exports.SentryContextManager = contextManager.SentryContextManager;
96
96
  exports.generateInstrumentOnce = instrument.generateInstrumentOnce;
97
- exports.getDefaultIntegrations = index$6.getDefaultIntegrations;
98
- exports.getDefaultIntegrationsWithoutPerformance = index$6.getDefaultIntegrationsWithoutPerformance;
99
- exports.init = index$6.init;
100
- exports.initWithoutDefaultIntegrations = index$6.initWithoutDefaultIntegrations;
101
- exports.validateOpenTelemetrySetup = index$6.validateOpenTelemetrySetup;
97
+ exports.getDefaultIntegrations = index$7.getDefaultIntegrations;
98
+ exports.getDefaultIntegrationsWithoutPerformance = index$7.getDefaultIntegrationsWithoutPerformance;
99
+ exports.init = index$7.init;
100
+ exports.initWithoutDefaultIntegrations = index$7.initWithoutDefaultIntegrations;
101
+ exports.validateOpenTelemetrySetup = index$7.validateOpenTelemetrySetup;
102
102
  exports.initOpenTelemetry = initOtel.initOpenTelemetry;
103
103
  exports.preloadOpenTelemetry = initOtel.preloadOpenTelemetry;
104
- exports.getAutoPerformanceIntegrations = index$7.getAutoPerformanceIntegrations;
104
+ exports.getAutoPerformanceIntegrations = index$8.getAutoPerformanceIntegrations;
105
105
  exports.defaultStackParser = api.defaultStackParser;
106
106
  exports.getSentryRelease = api.getSentryRelease;
107
107
  exports.createGetModuleFromFilename = module$1.createGetModuleFromFilename;
108
108
  exports.makeNodeTransport = http.makeNodeTransport;
109
109
  exports.NodeClient = client.NodeClient;
110
- exports.cron = index$8.cron;
110
+ exports.cron = index$9.cron;
111
111
  exports.setNodeAsyncContextStrategy = opentelemetry.setOpenTelemetryContextAsyncContextStrategy;
112
112
  exports.SDK_VERSION = core.SDK_VERSION;
113
113
  exports.SEMANTIC_ATTRIBUTE_SENTRY_OP = core.SEMANTIC_ATTRIBUTE_SENTRY_OP;
@@ -9,7 +9,7 @@ const debug = require('../../utils/debug.js');
9
9
  const { isPromise } = node_util.types;
10
10
 
11
11
  // This string is a placeholder that gets overwritten with the worker code.
12
- const base64WorkerScript = 'LyohIEBzZW50cnkvbm9kZSA5LjE2LjEgKDE2MDM4NjYpIHwgaHR0cHM6Ly9naXRodWIuY29tL2dldHNlbnRyeS9zZW50cnktamF2YXNjcmlwdCAqLwppbXBvcnR7U2Vzc2lvbiBhcyB0fWZyb20ibm9kZTppbnNwZWN0b3IiO2ltcG9ydHt3b3JrZXJEYXRhIGFzIG4scGFyZW50UG9ydCBhcyBlfWZyb20ibm9kZTp3b3JrZXJfdGhyZWFkcyI7aW1wb3J0e3Bvc2l4IGFzIHIsc2VwIGFzIG99ZnJvbSJub2RlOnBhdGgiO2ltcG9ydCphcyBzIGZyb20ibm9kZTpodHRwIjtpbXBvcnQqYXMgaSBmcm9tIm5vZGU6aHR0cHMiO2ltcG9ydHtSZWFkYWJsZSBhcyBjfWZyb20ibm9kZTpzdHJlYW0iO2ltcG9ydHtjcmVhdGVHemlwIGFzIHV9ZnJvbSJub2RlOnpsaWIiO2ltcG9ydCphcyBhIGZyb20ibm9kZTpuZXQiO2ltcG9ydCphcyBmIGZyb20ibm9kZTp0bHMiO2NvbnN0IGg9InVuZGVmaW5lZCI9PXR5cGVvZiBfX1NFTlRSWV9ERUJVR19ffHxfX1NFTlRSWV9ERUJVR19fLHA9IjkuMTYuMSIsbD1nbG9iYWxUaGlzO2Z1bmN0aW9uIGQoKXtyZXR1cm4gbShsKSxsfWZ1bmN0aW9uIG0odCl7Y29uc3Qgbj10Ll9fU0VOVFJZX189dC5fX1NFTlRSWV9ffHx7fTtyZXR1cm4gbi52ZXJzaW9uPW4udmVyc2lvbnx8cCxuW3BdPW5bcF18fHt9fWZ1bmN0aW9uIGcodCxuLGU9bCl7Y29uc3Qgcj1lLl9fU0VOVFJZX189ZS5fX1NFTlRSWV9ffHx7fSxvPXJbcF09cltwXXx8e307cmV0dXJuIG9bdF18fChvW3RdPW4oKSl9Y29uc3QgeT1PYmplY3QucHJvdG90eXBlLnRvU3RyaW5nO2Z1bmN0aW9uIGIodCxuKXtyZXR1cm4geS5jYWxsKHQpPT09YFtvYmplY3QgJHtufV1gfWZ1bmN0aW9uIF8odCl7cmV0dXJuIGIodCwiU3RyaW5nIil9ZnVuY3Rpb24gdih0KXtyZXR1cm4gYih0LCJPYmplY3QiKX1mdW5jdGlvbiB3KHQpe3JldHVybiBCb29sZWFuKHQ/LnRoZW4mJiJmdW5jdGlvbiI9PXR5cGVvZiB0LnRoZW4pfWZ1bmN0aW9uIFModCxuKXt0cnl7cmV0dXJuIHQgaW5zdGFuY2VvZiBufWNhdGNoKHQpe3JldHVybiExfX1jb25zdCAkPWwsRT04MDtmdW5jdGlvbiB4KHQsbil7Y29uc3QgZT10LHI9W107aWYoIWU/LnRhZ05hbWUpcmV0dXJuIiI7aWYoJC5IVE1MRWxlbWVudCYmZSBpbnN0YW5jZW9mIEhUTUxFbGVtZW50JiZlLmRhdGFzZXQpe2lmKGUuZGF0YXNldC5zZW50cnlDb21wb25lbnQpcmV0dXJuIGUuZGF0YXNldC5zZW50cnlDb21wb25lbnQ7aWYoZS5kYXRhc2V0LnNlbnRyeUVsZW1lbnQpcmV0dXJuIGUuZGF0YXNldC5zZW50cnlFbGVtZW50fXIucHVzaChlLnRhZ05hbWUudG9Mb3dlckNhc2UoKSk7Y29uc3Qgbz1uPy5sZW5ndGg/bi5maWx0ZXIoKHQ9PmUuZ2V0QXR0cmlidXRlKHQpKSkubWFwKCh0PT5bdCxlLmdldEF0dHJpYnV0ZSh0KV0pKTpudWxsO2lmKG8/Lmxlbmd0aClvLmZvckVhY2goKHQ9PntyLnB1c2goYFske3RbMF19PSIke3RbMV19Il1gKX0pKTtlbHNle2UuaWQmJnIucHVzaChgIyR7ZS5pZH1gKTtjb25zdCB0PWUuY2xhc3NOYW1lO2lmKHQmJl8odCkpe2NvbnN0IG49dC5zcGxpdCgvXHMrLyk7Zm9yKGNvbnN0IHQgb2YgbilyLnB1c2goYC4ke3R9YCl9fWNvbnN0IHM9WyJhcmlhLWxhYmVsIiwidHlwZSIsIm5hbWUiLCJ0aXRsZSIsImFsdCJdO2Zvcihjb25zdCB0IG9mIHMpe2NvbnN0IG49ZS5nZXRBdHRyaWJ1dGUodCk7biYmci5wdXNoKGBbJHt0fT0iJHtufSJdYCl9cmV0dXJuIHIuam9pbigiIil9Y29uc3QgTj0idW5kZWZpbmVkIj09dHlwZW9mIF9fU0VOVFJZX0RFQlVHX198fF9fU0VOVFJZX0RFQlVHX18sVD1bImRlYnVnIiwiaW5mbyIsIndhcm4iLCJlcnJvciIsImxvZyIsImFzc2VydCIsInRyYWNlIl0sQz17fTtmdW5jdGlvbiBSKHQpe2lmKCEoImNvbnNvbGUiaW4gbCkpcmV0dXJuIHQoKTtjb25zdCBuPWwuY29uc29sZSxlPXt9LHI9T2JqZWN0LmtleXMoQyk7ci5mb3JFYWNoKCh0PT57Y29uc3Qgcj1DW3RdO2VbdF09blt0XSxuW3RdPXJ9KSk7dHJ5e3JldHVybiB0KCl9ZmluYWxseXtyLmZvckVhY2goKHQ9PntuW3RdPWVbdF19KSl9fWNvbnN0IGs9ZygibG9nZ2VyIiwoZnVuY3Rpb24oKXtsZXQgdD0hMTtjb25zdCBuPXtlbmFibGU6KCk9Pnt0PSEwfSxkaXNhYmxlOigpPT57dD0hMX0saXNFbmFibGVkOigpPT50fTtyZXR1cm4gTj9ULmZvckVhY2goKGU9PntuW2VdPSguLi5uKT0+e3QmJlIoKCgpPT57bC5jb25zb2xlW2VdKGBTZW50cnkgTG9nZ2VyIFske2V9XTpgLC4uLm4pfSkpfX0pKTpULmZvckVhY2goKHQ9PntuW3RdPSgpPT57fX0pKSxufSkpO2Z1bmN0aW9uIGoodCxuPTApe3JldHVybiJzdHJpbmciIT10eXBlb2YgdHx8MD09PW58fHQubGVuZ3RoPD1uP3Q6YCR7dC5zbGljZSgwLG4pfS4uLmB9ZnVuY3Rpb24gRCh0KXtpZihmdW5jdGlvbih0KXtzd2l0Y2goeS5jYWxsKHQpKXtjYXNlIltvYmplY3QgRXJyb3JdIjpjYXNlIltvYmplY3QgRXhjZXB0aW9uXSI6Y2FzZSJbb2JqZWN0IERPTUV4Y2VwdGlvbl0iOmNhc2UiW29iamVjdCBXZWJBc3NlbWJseS5FeGNlcHRpb25dIjpyZXR1cm4hMDtkZWZhdWx0OnJldHVybiBTKHQsRXJyb3IpfX0odCkpcmV0dXJue21lc3NhZ2U6dC5tZXNzYWdlLG5hbWU6dC5uYW1lLHN0YWNrOnQuc3RhY2ssLi4uTyh0KX07aWYobj10LCJ1bmRlZmluZWQiIT10eXBlb2YgRXZlbnQmJlMobixFdmVudCkpe2NvbnN0IG49e3R5cGU6dC50eXBlLHRhcmdldDpJKHQudGFyZ2V0KSxjdXJyZW50VGFyZ2V0OkkodC5jdXJyZW50VGFyZ2V0KSwuLi5PKHQpfTtyZXR1cm4idW5kZWZpbmVkIiE9dHlwZW9mIEN1c3RvbUV2ZW50JiZTKHQsQ3VzdG9tRXZlbnQpJiYobi5kZXRhaWw9dC5kZXRhaWwpLG59cmV0dXJuIHQ7dmFyIG59ZnVuY3Rpb24gSSh0KXt0cnl7cmV0dXJuIG49dCwidW5kZWZpbmVkIiE9dHlwZW9mIEVsZW1lbnQmJlMobixFbGVtZW50KT9mdW5jdGlvbih0LG49e30pe2lmKCF0KXJldHVybiI8dW5rbm93bj4iO3RyeXtsZXQgZT10O2NvbnN0IHI9NSxvPVtdO2xldCBzPTAsaT0wO2NvbnN0IGM9IiA+ICIsdT1jLmxlbmd0aDtsZXQgYTtjb25zdCBmPUFycmF5LmlzQXJyYXkobik/bjpuLmtleUF0dHJzLGg9IUFycmF5LmlzQXJyYXkobikmJm4ubWF4U3RyaW5nTGVuZ3RofHxFO2Zvcig7ZSYmcysrPHImJihhPXgoZSxmKSwhKCJodG1sIj09PWF8fHM+MSYmaStvLmxlbmd0aCp1K2EubGVuZ3RoPj1oKSk7KW8ucHVzaChhKSxpKz1hLmxlbmd0aCxlPWUucGFyZW50Tm9kZTtyZXR1cm4gby5yZXZlcnNlKCkuam9pbihjKX1jYXRjaCh0KXtyZXR1cm4iPHVua25vd24+In19KHQpOk9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbCh0KX1jYXRjaCh0KXtyZXR1cm4iPHVua25vd24+In12YXIgbn1mdW5jdGlvbiBPKHQpe2lmKCJvYmplY3QiPT10eXBlb2YgdCYmbnVsbCE9PXQpe2NvbnN0IG49e307Zm9yKGNvbnN0IGUgaW4gdClPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwodCxlKSYmKG5bZV09dFtlXSk7cmV0dXJuIG59cmV0dXJue319ZnVuY3Rpb24gQSh0PWZ1bmN0aW9uKCl7Y29uc3QgdD1sO3JldHVybiB0LmNyeXB0b3x8dC5tc0NyeXB0b30oKSl7bGV0IG49KCk9PjE2Kk1hdGgucmFuZG9tKCk7dHJ5e2lmKHQ/LnJhbmRvbVVVSUQpcmV0dXJuIHQucmFuZG9tVVVJRCgpLnJlcGxhY2UoLy0vZywiIik7dD8uZ2V0UmFuZG9tVmFsdWVzJiYobj0oKT0+e2NvbnN0IG49bmV3IFVpbnQ4QXJyYXkoMSk7cmV0dXJuIHQuZ2V0UmFuZG9tVmFsdWVzKG4pLG5bMF19KX1jYXRjaCh0KXt9cmV0dXJuKFsxZTddKzFlMys0ZTMrOGUzKzFlMTEpLnJlcGxhY2UoL1swMThdL2csKHQ9Pih0XigxNSZuKCkpPj50LzQpLnRvU3RyaW5nKDE2KSkpfWNvbnN0IFA9MWUzO2Z1bmN0aW9uIFUoKXtyZXR1cm4gRGF0ZS5ub3coKS9QfWNvbnN0IE09ZnVuY3Rpb24oKXtjb25zdHtwZXJmb3JtYW5jZTp0fT1sO2lmKCF0Py5ub3cpcmV0dXJuIFU7Y29uc3Qgbj1EYXRlLm5vdygpLXQubm93KCksZT1udWxsPT10LnRpbWVPcmlnaW4/bjp0LnRpbWVPcmlnaW47cmV0dXJuKCk9PihlK3Qubm93KCkpL1B9KCk7ZnVuY3Rpb24gTCh0KXtjb25zdCBuPU0oKSxlPXtzaWQ6QSgpLGluaXQ6ITAsdGltZXN0YW1wOm4sc3RhcnRlZDpuLGR1cmF0aW9uOjAsc3RhdHVzOiJvayIsZXJyb3JzOjAsaWdub3JlRHVyYXRpb246ITEsdG9KU09OOigpPT5mdW5jdGlvbih0KXtyZXR1cm57c2lkOmAke3Quc2lkfWAsaW5pdDp0LmluaXQsc3RhcnRlZDpuZXcgRGF0ZSgxZTMqdC5zdGFydGVkKS50b0lTT1N0cmluZygpLHRpbWVzdGFtcDpuZXcgRGF0ZSgxZTMqdC50aW1lc3RhbXApLnRvSVNPU3RyaW5nKCksc3RhdHVzOnQuc3RhdHVzLGVycm9yczp0LmVycm9ycyxkaWQ6Im51bWJlciI9PXR5cGVvZiB0LmRpZHx8InN0cmluZyI9PXR5cGVvZiB0LmRpZD9gJHt0LmRpZH1gOnZvaWQgMCxkdXJhdGlvbjp0LmR1cmF0aW9uLGFibm9ybWFsX21lY2hhbmlzbTp0LmFibm9ybWFsX21lY2hhbmlzbSxhdHRyczp7cmVsZWFzZTp0LnJlbGVhc2UsZW52aXJvbm1lbnQ6dC5lbnZpcm9ubWVudCxpcF9hZGRyZXNzOnQuaXBBZGRyZXNzLHVzZXJfYWdlbnQ6dC51c2VyQWdlbnR9fX0oZSl9O3JldHVybiB0JiZCKGUsdCksZX1mdW5jdGlvbiBCKHQsbj17fSl7aWYobi51c2VyJiYoIXQuaXBBZGRyZXNzJiZuLnVzZXIuaXBfYWRkcmVzcyYmKHQuaXBBZGRyZXNzPW4udXNlci5pcF9hZGRyZXNzKSx0LmRpZHx8bi5kaWR8fCh0LmRpZD1uLnVzZXIuaWR8fG4udXNlci5lbWFpbHx8bi51c2VyLnVzZXJuYW1lKSksdC50aW1lc3RhbXA9bi50aW1lc3RhbXB8fE0oKSxuLmFibm9ybWFsX21lY2hhbmlzbSYmKHQuYWJub3JtYWxfbWVjaGFuaXNtPW4uYWJub3JtYWxfbWVjaGFuaXNtKSxuLmlnbm9yZUR1cmF0aW9uJiYodC5pZ25vcmVEdXJhdGlvbj1uLmlnbm9yZUR1cmF0aW9uKSxuLnNpZCYmKHQuc2lkPTMyPT09bi5zaWQubGVuZ3RoP24uc2lkOkEoKSksdm9pZCAwIT09bi5pbml0JiYodC5pbml0PW4uaW5pdCksIXQuZGlkJiZuLmRpZCYmKHQuZGlkPWAke24uZGlkfWApLCJudW1iZXIiPT10eXBlb2Ygbi5zdGFydGVkJiYodC5zdGFydGVkPW4uc3RhcnRlZCksdC5pZ25vcmVEdXJhdGlvbil0LmR1cmF0aW9uPXZvaWQgMDtlbHNlIGlmKCJudW1iZXIiPT10eXBlb2Ygbi5kdXJhdGlvbil0LmR1cmF0aW9uPW4uZHVyYXRpb247ZWxzZXtjb25zdCBuPXQudGltZXN0YW1wLXQuc3RhcnRlZDt0LmR1cmF0aW9uPW4+PTA/bjowfW4ucmVsZWFzZSYmKHQucmVsZWFzZT1uLnJlbGVhc2UpLG4uZW52aXJvbm1lbnQmJih0LmVudmlyb25tZW50PW4uZW52aXJvbm1lbnQpLCF0LmlwQWRkcmVzcyYmbi5pcEFkZHJlc3MmJih0LmlwQWRkcmVzcz1uLmlwQWRkcmVzcyksIXQudXNlckFnZW50JiZuLnVzZXJBZ2VudCYmKHQudXNlckFnZW50PW4udXNlckFnZW50KSwibnVtYmVyIj09dHlwZW9mIG4uZXJyb3JzJiYodC5lcnJvcnM9bi5lcnJvcnMpLG4uc3RhdHVzJiYodC5zdGF0dXM9bi5zdGF0dXMpfWZ1bmN0aW9uIEcodCxuLGU9Mil7aWYoIW58fCJvYmplY3QiIT10eXBlb2Ygbnx8ZTw9MClyZXR1cm4gbjtpZih0JiYwPT09T2JqZWN0LmtleXMobikubGVuZ3RoKXJldHVybiB0O2NvbnN0IHI9ey4uLnR9O2Zvcihjb25zdCB0IGluIG4pT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKG4sdCkmJihyW3RdPUcoclt0XSxuW3RdLGUtMSkpO3JldHVybiByfWNvbnN0IEo9Il9zZW50cnlTcGFuIjtmdW5jdGlvbiBZKHQsbil7bj9mdW5jdGlvbih0LG4sZSl7dHJ5e09iamVjdC5kZWZpbmVQcm9wZXJ0eSh0LG4se3ZhbHVlOmUsd3JpdGFibGU6ITAsY29uZmlndXJhYmxlOiEwfSl9Y2F0Y2goZSl7TiYmay5sb2coYEZhaWxlZCB0byBhZGQgbm9uLWVudW1lcmFibGUgcHJvcGVydHkgIiR7bn0iIHRvIG9iamVjdGAsdCl9fSh0LEosbik6ZGVsZXRlIHRbSl19ZnVuY3Rpb24geih0KXtyZXR1cm4gdFtKXX1mdW5jdGlvbiBIKCl7cmV0dXJuIEEoKX1mdW5jdGlvbiBGKCl7cmV0dXJuIEEoKS5zdWJzdHJpbmcoMTYpfWNsYXNzIFd7Y29uc3RydWN0b3IoKXt0aGlzLnQ9ITEsdGhpcy5vPVtdLHRoaXMuaT1bXSx0aGlzLnU9W10sdGhpcy5oPVtdLHRoaXMucD17fSx0aGlzLmw9e30sdGhpcy5tPXt9LHRoaXMuXz17fSx0aGlzLnY9e30sdGhpcy5TPXt0cmFjZUlkOkgoKSxzYW1wbGVSYW5kOk1hdGgucmFuZG9tKCl9fWNsb25lKCl7Y29uc3QgdD1uZXcgVztyZXR1cm4gdC51PVsuLi50aGlzLnVdLHQubD17Li4udGhpcy5sfSx0Lm09ey4uLnRoaXMubX0sdC5fPXsuLi50aGlzLl99LHRoaXMuXy5mbGFncyYmKHQuXy5mbGFncz17dmFsdWVzOlsuLi50aGlzLl8uZmxhZ3MudmFsdWVzXX0pLHQucD10aGlzLnAsdC5OPXRoaXMuTix0LlQ9dGhpcy5ULHQuQz10aGlzLkMsdC5SPXRoaXMuUix0Lmk9Wy4uLnRoaXMuaV0sdC5oPVsuLi50aGlzLmhdLHQudj17Li4udGhpcy52fSx0LlM9ey4uLnRoaXMuU30sdC5rPXRoaXMuayx0Lmo9dGhpcy5qLFkodCx6KHRoaXMpKSx0fXNldENsaWVudCh0KXt0aGlzLms9dH1zZXRMYXN0RXZlbnRJZCh0KXt0aGlzLmo9dH1nZXRDbGllbnQoKXtyZXR1cm4gdGhpcy5rfWxhc3RFdmVudElkKCl7cmV0dXJuIHRoaXMuan1hZGRTY29wZUxpc3RlbmVyKHQpe3RoaXMuby5wdXNoKHQpfWFkZEV2ZW50UHJvY2Vzc29yKHQpe3JldHVybiB0aGlzLmkucHVzaCh0KSx0aGlzfXNldFVzZXIodCl7cmV0dXJuIHRoaXMucD10fHx7ZW1haWw6dm9pZCAwLGlkOnZvaWQgMCxpcF9hZGRyZXNzOnZvaWQgMCx1c2VybmFtZTp2b2lkIDB9LHRoaXMuVCYmQih0aGlzLlQse3VzZXI6dH0pLHRoaXMuRCgpLHRoaXN9Z2V0VXNlcigpe3JldHVybiB0aGlzLnB9c2V0VGFncyh0KXtyZXR1cm4gdGhpcy5sPXsuLi50aGlzLmwsLi4udH0sdGhpcy5EKCksdGhpc31zZXRUYWcodCxuKXtyZXR1cm4gdGhpcy5sPXsuLi50aGlzLmwsW3RdOm59LHRoaXMuRCgpLHRoaXN9c2V0RXh0cmFzKHQpe3JldHVybiB0aGlzLm09ey4uLnRoaXMubSwuLi50fSx0aGlzLkQoKSx0aGlzfXNldEV4dHJhKHQsbil7cmV0dXJuIHRoaXMubT17Li4udGhpcy5tLFt0XTpufSx0aGlzLkQoKSx0aGlzfXNldEZpbmdlcnByaW50KHQpe3JldHVybiB0aGlzLlI9dCx0aGlzLkQoKSx0aGlzfXNldExldmVsKHQpe3JldHVybiB0aGlzLk49dCx0aGlzLkQoKSx0aGlzfXNldFRyYW5zYWN0aW9uTmFtZSh0KXtyZXR1cm4gdGhpcy5DPXQsdGhpcy5EKCksdGhpc31zZXRDb250ZXh0KHQsbil7cmV0dXJuIG51bGw9PT1uP2RlbGV0ZSB0aGlzLl9bdF06dGhpcy5fW3RdPW4sdGhpcy5EKCksdGhpc31zZXRTZXNzaW9uKHQpe3JldHVybiB0P3RoaXMuVD10OmRlbGV0ZSB0aGlzLlQsdGhpcy5EKCksdGhpc31nZXRTZXNzaW9uKCl7cmV0dXJuIHRoaXMuVH11cGRhdGUodCl7aWYoIXQpcmV0dXJuIHRoaXM7Y29uc3Qgbj0iZnVuY3Rpb24iPT10eXBlb2YgdD90KHRoaXMpOnQsZT1uIGluc3RhbmNlb2YgVz9uLmdldFNjb3BlRGF0YSgpOnYobik/dDp2b2lkIDAse3RhZ3M6cixleHRyYTpvLHVzZXI6cyxjb250ZXh0czppLGxldmVsOmMsZmluZ2VycHJpbnQ6dT1bXSxwcm9wYWdhdGlvbkNvbnRleHQ6YX09ZXx8e307cmV0dXJuIHRoaXMubD17Li4udGhpcy5sLC4uLnJ9LHRoaXMubT17Li4udGhpcy5tLC4uLm99LHRoaXMuXz17Li4udGhpcy5fLC4uLml9LHMmJk9iamVjdC5rZXlzKHMpLmxlbmd0aCYmKHRoaXMucD1zKSxjJiYodGhpcy5OPWMpLHUubGVuZ3RoJiYodGhpcy5SPXUpLGEmJih0aGlzLlM9YSksdGhpc31jbGVhcigpe3JldHVybiB0aGlzLnU9W10sdGhpcy5sPXt9LHRoaXMubT17fSx0aGlzLnA9e30sdGhpcy5fPXt9LHRoaXMuTj12b2lkIDAsdGhpcy5DPXZvaWQgMCx0aGlzLlI9dm9pZCAwLHRoaXMuVD12b2lkIDAsWSh0aGlzLHZvaWQgMCksdGhpcy5oPVtdLHRoaXMuc2V0UHJvcGFnYXRpb25Db250ZXh0KHt0cmFjZUlkOkgoKSxzYW1wbGVSYW5kOk1hdGgucmFuZG9tKCl9KSx0aGlzLkQoKSx0aGlzfWFkZEJyZWFkY3J1bWIodCxuKXtjb25zdCBlPSJudW1iZXIiPT10eXBlb2Ygbj9uOjEwMDtpZihlPD0wKXJldHVybiB0aGlzO2NvbnN0IHI9e3RpbWVzdGFtcDpVKCksLi4udCxtZXNzYWdlOnQubWVzc2FnZT9qKHQubWVzc2FnZSwyMDQ4KTp0Lm1lc3NhZ2V9O3JldHVybiB0aGlzLnUucHVzaChyKSx0aGlzLnUubGVuZ3RoPmUmJih0aGlzLnU9dGhpcy51LnNsaWNlKC1lKSx0aGlzLms/LnJlY29yZERyb3BwZWRFdmVudCgiYnVmZmVyX292ZXJmbG93IiwibG9nX2l0ZW0iKSksdGhpcy5EKCksdGhpc31nZXRMYXN0QnJlYWRjcnVtYigpe3JldHVybiB0aGlzLnVbdGhpcy51Lmxlbmd0aC0xXX1jbGVhckJyZWFkY3J1bWJzKCl7cmV0dXJuIHRoaXMudT1bXSx0aGlzLkQoKSx0aGlzfWFkZEF0dGFjaG1lbnQodCl7cmV0dXJuIHRoaXMuaC5wdXNoKHQpLHRoaXN9Y2xlYXJBdHRhY2htZW50cygpe3JldHVybiB0aGlzLmg9W10sdGhpc31nZXRTY29wZURhdGEoKXtyZXR1cm57YnJlYWRjcnVtYnM6dGhpcy51LGF0dGFjaG1lbnRzOnRoaXMuaCxjb250ZXh0czp0aGlzLl8sdGFnczp0aGlzLmwsZXh0cmE6dGhpcy5tLHVzZXI6dGhpcy5wLGxldmVsOnRoaXMuTixmaW5nZXJwcmludDp0aGlzLlJ8fFtdLGV2ZW50UHJvY2Vzc29yczp0aGlzLmkscHJvcGFnYXRpb25Db250ZXh0OnRoaXMuUyxzZGtQcm9jZXNzaW5nTWV0YWRhdGE6dGhpcy52LHRyYW5zYWN0aW9uTmFtZTp0aGlzLkMsc3Bhbjp6KHRoaXMpfX1zZXRTREtQcm9jZXNzaW5nTWV0YWRhdGEodCl7cmV0dXJuIHRoaXMudj1HKHRoaXMudix0LDIpLHRoaXN9c2V0UHJvcGFnYXRpb25Db250ZXh0KHQpe3JldHVybiB0aGlzLlM9dCx0aGlzfWdldFByb3BhZ2F0aW9uQ29udGV4dCgpe3JldHVybiB0aGlzLlN9Y2FwdHVyZUV4Y2VwdGlvbih0LG4pe2NvbnN0IGU9bj8uZXZlbnRfaWR8fEEoKTtpZighdGhpcy5rKXJldHVybiBrLndhcm4oIk5vIGNsaWVudCBjb25maWd1cmVkIG9uIHNjb3BlIC0gd2lsbCBub3QgY2FwdHVyZSBleGNlcHRpb24hIiksZTtjb25zdCByPW5ldyBFcnJvcigiU2VudHJ5IHN5bnRoZXRpY0V4Y2VwdGlvbiIpO3JldHVybiB0aGlzLmsuY2FwdHVyZUV4Y2VwdGlvbih0LHtvcmlnaW5hbEV4Y2VwdGlvbjp0LHN5bnRoZXRpY0V4Y2VwdGlvbjpyLC4uLm4sZXZlbnRfaWQ6ZX0sdGhpcyksZX1jYXB0dXJlTWVzc2FnZSh0LG4sZSl7Y29uc3Qgcj1lPy5ldmVudF9pZHx8QSgpO2lmKCF0aGlzLmspcmV0dXJuIGsud2FybigiTm8gY2xpZW50IGNvbmZpZ3VyZWQgb24gc2NvcGUgLSB3aWxsIG5vdCBjYXB0dXJlIG1lc3NhZ2UhIikscjtjb25zdCBvPW5ldyBFcnJvcih0KTtyZXR1cm4gdGhpcy5rLmNhcHR1cmVNZXNzYWdlKHQsbix7b3JpZ2luYWxFeGNlcHRpb246dCxzeW50aGV0aWNFeGNlcHRpb246bywuLi5lLGV2ZW50X2lkOnJ9LHRoaXMpLHJ9Y2FwdHVyZUV2ZW50KHQsbil7Y29uc3QgZT1uPy5ldmVudF9pZHx8QSgpO3JldHVybiB0aGlzLms/KHRoaXMuay5jYXB0dXJlRXZlbnQodCx7Li4ubixldmVudF9pZDplfSx0aGlzKSxlKTooay53YXJuKCJObyBjbGllbnQgY29uZmlndXJlZCBvbiBzY29wZSAtIHdpbGwgbm90IGNhcHR1cmUgZXZlbnQhIiksZSl9RCgpe3RoaXMudHx8KHRoaXMudD0hMCx0aGlzLm8uZm9yRWFjaCgodD0+e3QodGhpcyl9KSksdGhpcy50PSExKX19Y2xhc3MgS3tjb25zdHJ1Y3Rvcih0LG4pe2xldCBlLHI7ZT10fHxuZXcgVyxyPW58fG5ldyBXLHRoaXMuST1be3Njb3BlOmV9XSx0aGlzLk89cn13aXRoU2NvcGUodCl7Y29uc3Qgbj10aGlzLkEoKTtsZXQgZTt0cnl7ZT10KG4pfWNhdGNoKHQpe3Rocm93IHRoaXMuUCgpLHR9cmV0dXJuIHcoZSk/ZS50aGVuKCh0PT4odGhpcy5QKCksdCkpLCh0PT57dGhyb3cgdGhpcy5QKCksdH0pKToodGhpcy5QKCksZSl9Z2V0Q2xpZW50KCl7cmV0dXJuIHRoaXMuZ2V0U3RhY2tUb3AoKS5jbGllbnR9Z2V0U2NvcGUoKXtyZXR1cm4gdGhpcy5nZXRTdGFja1RvcCgpLnNjb3BlfWdldElzb2xhdGlvblNjb3BlKCl7cmV0dXJuIHRoaXMuT31nZXRTdGFja1RvcCgpe3JldHVybiB0aGlzLklbdGhpcy5JLmxlbmd0aC0xXX1BKCl7Y29uc3QgdD10aGlzLmdldFNjb3BlKCkuY2xvbmUoKTtyZXR1cm4gdGhpcy5JLnB1c2goe2NsaWVudDp0aGlzLmdldENsaWVudCgpLHNjb3BlOnR9KSx0fVAoKXtyZXR1cm4hKHRoaXMuSS5sZW5ndGg8PTEpJiYhIXRoaXMuSS5wb3AoKX19ZnVuY3Rpb24gVigpe2NvbnN0IHQ9bShkKCkpO3JldHVybiB0LnN0YWNrPXQuc3RhY2t8fG5ldyBLKGcoImRlZmF1bHRDdXJyZW50U2NvcGUiLCgoKT0+bmV3IFcpKSxnKCJkZWZhdWx0SXNvbGF0aW9uU2NvcGUiLCgoKT0+bmV3IFcpKSl9ZnVuY3Rpb24gWih0KXtyZXR1cm4gVigpLndpdGhTY29wZSh0KX1mdW5jdGlvbiBxKHQsbil7Y29uc3QgZT1WKCk7cmV0dXJuIGUud2l0aFNjb3BlKCgoKT0+KGUuZ2V0U3RhY2tUb3AoKS5zY29wZT10LG4odCkpKSl9ZnVuY3Rpb24gUSh0KXtyZXR1cm4gVigpLndpdGhTY29wZSgoKCk9PnQoVigpLmdldElzb2xhdGlvblNjb3BlKCkpKSl9ZnVuY3Rpb24gWCh0KXtjb25zdCBuPW0odCk7cmV0dXJuIG4uYWNzP24uYWNzOnt3aXRoSXNvbGF0aW9uU2NvcGU6USx3aXRoU2NvcGU6Wix3aXRoU2V0U2NvcGU6cSx3aXRoU2V0SXNvbGF0aW9uU2NvcGU6KHQsbik9PlEobiksZ2V0Q3VycmVudFNjb3BlOigpPT5WKCkuZ2V0U2NvcGUoKSxnZXRJc29sYXRpb25TY29wZTooKT0+VigpLmdldElzb2xhdGlvblNjb3BlKCl9fWZ1bmN0aW9uIHR0KCl7cmV0dXJuIFgoZCgpKS5nZXRDdXJyZW50U2NvcGUoKS5nZXRDbGllbnQoKX1jb25zdCBudD0ic2VudHJ5LnNvdXJjZSIsZXQ9InNlbnRyeS5zYW1wbGVfcmF0ZSIscnQ9InNlbnRyeS5wcmV2aW91c190cmFjZV9zYW1wbGVfcmF0ZSIsb3Q9InNlbnRyeS5vcCIsc3Q9InNlbnRyeS5vcmlnaW4iLGl0PTAsY3Q9MSx1dD0iX3NlbnRyeVNjb3BlIixhdD0iX3NlbnRyeUlzb2xhdGlvblNjb3BlIjtmdW5jdGlvbiBmdCh0KXtyZXR1cm57c2NvcGU6dFt1dF0saXNvbGF0aW9uU2NvcGU6dFthdF19fWNvbnN0IGh0PSJzZW50cnktIixwdD0vXnNlbnRyeS0vO2Z1bmN0aW9uIGx0KHQpe2NvbnN0IG49ZnVuY3Rpb24odCl7aWYoIXR8fCFfKHQpJiYhQXJyYXkuaXNBcnJheSh0KSlyZXR1cm47aWYoQXJyYXkuaXNBcnJheSh0KSlyZXR1cm4gdC5yZWR1Y2UoKCh0LG4pPT57Y29uc3QgZT1kdChuKTtyZXR1cm4gT2JqZWN0LmVudHJpZXMoZSkuZm9yRWFjaCgoKFtuLGVdKT0+e3Rbbl09ZX0pKSx0fSkse30pO3JldHVybiBkdCh0KX0odCk7aWYoIW4pcmV0dXJuO2NvbnN0IGU9T2JqZWN0LmVudHJpZXMobikucmVkdWNlKCgodCxbbixlXSk9PntpZihuLm1hdGNoKHB0KSl7dFtuLnNsaWNlKGh0Lmxlbmd0aCldPWV9cmV0dXJuIHR9KSx7fSk7cmV0dXJuIE9iamVjdC5rZXlzKGUpLmxlbmd0aD4wP2U6dm9pZCAwfWZ1bmN0aW9uIGR0KHQpe3JldHVybiB0LnNwbGl0KCIsIikubWFwKCh0PT50LnNwbGl0KCI9IikubWFwKCh0PT5kZWNvZGVVUklDb21wb25lbnQodC50cmltKCkpKSkpKS5yZWR1Y2UoKCh0LFtuLGVdKT0+KG4mJmUmJih0W25dPWUpLHQpKSx7fSl9Y29uc3QgbXQ9MTtmdW5jdGlvbiBndCh0KXtjb25zdHtzcGFuSWQ6bix0cmFjZUlkOmUsaXNSZW1vdGU6cn09dC5zcGFuQ29udGV4dCgpLG89cj9uOnZ0KHQpLnBhcmVudF9zcGFuX2lkLHM9ZnQodCkuc2NvcGU7cmV0dXJue3BhcmVudF9zcGFuX2lkOm8sc3Bhbl9pZDpyP3M/LmdldFByb3BhZ2F0aW9uQ29udGV4dCgpLnByb3BhZ2F0aW9uU3BhbklkfHxGKCk6bix0cmFjZV9pZDplfX1mdW5jdGlvbiB5dCh0KXtyZXR1cm4gdCYmdC5sZW5ndGg+MD90Lm1hcCgoKHtjb250ZXh0OntzcGFuSWQ6dCx0cmFjZUlkOm4sdHJhY2VGbGFnczplLC4uLnJ9LGF0dHJpYnV0ZXM6b30pPT4oe3NwYW5faWQ6dCx0cmFjZV9pZDpuLHNhbXBsZWQ6ZT09PW10LGF0dHJpYnV0ZXM6bywuLi5yfSkpKTp2b2lkIDB9ZnVuY3Rpb24gYnQodCl7cmV0dXJuIm51bWJlciI9PXR5cGVvZiB0P190KHQpOkFycmF5LmlzQXJyYXkodCk/dFswXSt0WzFdLzFlOTp0IGluc3RhbmNlb2YgRGF0ZT9fdCh0LmdldFRpbWUoKSk6TSgpfWZ1bmN0aW9uIF90KHQpe3JldHVybiB0Pjk5OTk5OTk5OTk/dC8xZTM6dH1mdW5jdGlvbiB2dCh0KXtpZihmdW5jdGlvbih0KXtyZXR1cm4iZnVuY3Rpb24iPT10eXBlb2YgdC5nZXRTcGFuSlNPTn0odCkpcmV0dXJuIHQuZ2V0U3BhbkpTT04oKTtjb25zdHtzcGFuSWQ6bix0cmFjZUlkOmV9PXQuc3BhbkNvbnRleHQoKTtpZihmdW5jdGlvbih0KXtjb25zdCBuPXQ7cmV0dXJuISEobi5hdHRyaWJ1dGVzJiZuLnN0YXJ0VGltZSYmbi5uYW1lJiZuLmVuZFRpbWUmJm4uc3RhdHVzKX0odCkpe2NvbnN0e2F0dHJpYnV0ZXM6cixzdGFydFRpbWU6byxuYW1lOnMsZW5kVGltZTppLHBhcmVudFNwYW5JZDpjLHN0YXR1czp1LGxpbmtzOmF9PXQ7cmV0dXJue3NwYW5faWQ6bix0cmFjZV9pZDplLGRhdGE6cixkZXNjcmlwdGlvbjpzLHBhcmVudF9zcGFuX2lkOmMsc3RhcnRfdGltZXN0YW1wOmJ0KG8pLHRpbWVzdGFtcDpidChpKXx8dm9pZCAwLHN0YXR1czp3dCh1KSxvcDpyW290XSxvcmlnaW46cltzdF0sbGlua3M6eXQoYSl9fXJldHVybntzcGFuX2lkOm4sdHJhY2VfaWQ6ZSxzdGFydF90aW1lc3RhbXA6MCxkYXRhOnt9fX1mdW5jdGlvbiB3dCh0KXtpZih0JiZ0LmNvZGUhPT1pdClyZXR1cm4gdC5jb2RlPT09Y3Q/Im9rIjp0Lm1lc3NhZ2V8fCJ1bmtub3duX2Vycm9yIn1jb25zdCBTdD0iX3NlbnRyeVJvb3RTcGFuIjtmdW5jdGlvbiAkdCh0KXtyZXR1cm4gdFtTdF18fHR9Y29uc3QgRXQ9NTAseHQ9Ij8iLE50PS9jYXB0dXJlTWVzc2FnZXxjYXB0dXJlRXhjZXB0aW9uLztmdW5jdGlvbiBUdCh0KXtyZXR1cm4gdFt0Lmxlbmd0aC0xXXx8e319Y29uc3QgQ3Q9Ijxhbm9ueW1vdXM+Ijtjb25zdCBSdD0icHJvZHVjdGlvbiIsa3Q9Il9mcm96ZW5Ec2MiO2Z1bmN0aW9uIGp0KHQpe2NvbnN0IG49dHQoKTtpZighbilyZXR1cm57fTtjb25zdCBlPSR0KHQpLHI9dnQoZSksbz1yLmRhdGEscz1lLnNwYW5Db250ZXh0KCkudHJhY2VTdGF0ZSxpPXM/LmdldCgic2VudHJ5LnNhbXBsZV9yYXRlIik/P29bZXRdPz9vW3J0XTtmdW5jdGlvbiBjKHQpe3JldHVybiJudW1iZXIiIT10eXBlb2YgaSYmInN0cmluZyIhPXR5cGVvZiBpfHwodC5zYW1wbGVfcmF0ZT1gJHtpfWApLHR9Y29uc3QgdT1lW2t0XTtpZih1KXJldHVybiBjKHUpO2NvbnN0IGE9cz8uZ2V0KCJzZW50cnkuZHNjIiksZj1hJiZsdChhKTtpZihmKXJldHVybiBjKGYpO2NvbnN0IGg9ZnVuY3Rpb24odCxuKXtjb25zdCBlPW4uZ2V0T3B0aW9ucygpLHtwdWJsaWNLZXk6cn09bi5nZXREc24oKXx8e30sbz17ZW52aXJvbm1lbnQ6ZS5lbnZpcm9ubWVudHx8UnQscmVsZWFzZTplLnJlbGVhc2UscHVibGljX2tleTpyLHRyYWNlX2lkOnR9O3JldHVybiBuLmVtaXQoImNyZWF0ZURzYyIsbyksb30odC5zcGFuQ29udGV4dCgpLnRyYWNlSWQsbikscD1vW250XSxsPXIuZGVzY3JpcHRpb247cmV0dXJuInVybCIhPT1wJiZsJiYoaC50cmFuc2FjdGlvbj1sKSxmdW5jdGlvbih0KXtpZigiYm9vbGVhbiI9PXR5cGVvZiBfX1NFTlRSWV9UUkFDSU5HX18mJiFfX1NFTlRSWV9UUkFDSU5HX18pcmV0dXJuITE7Y29uc3Qgbj10fHx0dCgpPy5nZXRPcHRpb25zKCk7cmV0dXJuISghbnx8bnVsbD09bi50cmFjZXNTYW1wbGVSYXRlJiYhbi50cmFjZXNTYW1wbGVyKX0oKSYmKGguc2FtcGxlZD1TdHJpbmcoZnVuY3Rpb24odCl7Y29uc3R7dHJhY2VGbGFnczpufT10LnNwYW5Db250ZXh0KCk7cmV0dXJuIG49PT1tdH0oZSkpLGguc2FtcGxlX3JhbmQ9cz8uZ2V0KCJzZW50cnkuc2FtcGxlX3JhbmQiKT8/ZnQoZSkuc2NvcGU/LmdldFByb3BhZ2F0aW9uQ29udGV4dCgpLnNhbXBsZVJhbmQudG9TdHJpbmcoKSksYyhoKSxuLmVtaXQoImNyZWF0ZURzYyIsaCxlKSxofWZ1bmN0aW9uIER0KHQsbj0hMSl7Y29uc3R7aG9zdDplLHBhdGg6cixwYXNzOm8scG9ydDpzLHByb2plY3RJZDppLHByb3RvY29sOmMscHVibGljS2V5OnV9PXQ7cmV0dXJuYCR7Y306Ly8ke3V9JHtuJiZvP2A6JHtvfWA6IiJ9QCR7ZX0ke3M/YDoke3N9YDoiIn0vJHtyP2Ake3J9L2A6cn0ke2l9YH1mdW5jdGlvbiBJdCh0LG49MTAwLGU9MS8wKXt0cnl7cmV0dXJuIE90KCIiLHQsbixlKX1jYXRjaCh0KXtyZXR1cm57RVJST1I6YCoqbm9uLXNlcmlhbGl6YWJsZSoqICgke3R9KWB9fX1mdW5jdGlvbiBPdCh0LG4sZT0xLzAscj0xLzAsbz1mdW5jdGlvbigpe2NvbnN0IHQ9bmV3IFdlYWtTZXQ7ZnVuY3Rpb24gbihuKXtyZXR1cm4hIXQuaGFzKG4pfHwodC5hZGQobiksITEpfWZ1bmN0aW9uIGUobil7dC5kZWxldGUobil9cmV0dXJuW24sZV19KCkpe2NvbnN0W3MsaV09bztpZihudWxsPT1ufHxbImJvb2xlYW4iLCJzdHJpbmciXS5pbmNsdWRlcyh0eXBlb2Ygbil8fCJudW1iZXIiPT10eXBlb2YgbiYmTnVtYmVyLmlzRmluaXRlKG4pKXJldHVybiBuO2NvbnN0IGM9ZnVuY3Rpb24odCxuKXt0cnl7aWYoImRvbWFpbiI9PT10JiZuJiYib2JqZWN0Ij09dHlwZW9mIG4mJm4uVSlyZXR1cm4iW0RvbWFpbl0iO2lmKCJkb21haW5FbWl0dGVyIj09PXQpcmV0dXJuIltEb21haW5FbWl0dGVyXSI7aWYoInVuZGVmaW5lZCIhPXR5cGVvZiBnbG9iYWwmJm49PT1nbG9iYWwpcmV0dXJuIltHbG9iYWxdIjtpZigidW5kZWZpbmVkIiE9dHlwZW9mIHdpbmRvdyYmbj09PXdpbmRvdylyZXR1cm4iW1dpbmRvd10iO2lmKCJ1bmRlZmluZWQiIT10eXBlb2YgZG9jdW1lbnQmJm49PT1kb2N1bWVudClyZXR1cm4iW0RvY3VtZW50XSI7aWYoIm9iamVjdCI9PXR5cGVvZihlPW4pJiZudWxsIT09ZSYmKGUuX19pc1Z1ZXx8ZS5NKSlyZXR1cm4iW1Z1ZVZpZXdNb2RlbF0iO2lmKGZ1bmN0aW9uKHQpe3JldHVybiB2KHQpJiYibmF0aXZlRXZlbnQiaW4gdCYmInByZXZlbnREZWZhdWx0ImluIHQmJiJzdG9wUHJvcGFnYXRpb24iaW4gdH0obikpcmV0dXJuIltTeW50aGV0aWNFdmVudF0iO2lmKCJudW1iZXIiPT10eXBlb2YgbiYmIU51bWJlci5pc0Zpbml0ZShuKSlyZXR1cm5gWyR7bn1dYDtpZigiZnVuY3Rpb24iPT10eXBlb2YgbilyZXR1cm5gW0Z1bmN0aW9uOiAke2Z1bmN0aW9uKHQpe3RyeXtyZXR1cm4gdCYmImZ1bmN0aW9uIj09dHlwZW9mIHQmJnQubmFtZXx8Q3R9Y2F0Y2godCl7cmV0dXJuIEN0fX0obil9XWA7aWYoInN5bWJvbCI9PXR5cGVvZiBuKXJldHVybmBbJHtTdHJpbmcobil9XWA7aWYoImJpZ2ludCI9PXR5cGVvZiBuKXJldHVybmBbQmlnSW50OiAke1N0cmluZyhuKX1dYDtjb25zdCByPWZ1bmN0aW9uKHQpe2NvbnN0IG49T2JqZWN0LmdldFByb3RvdHlwZU9mKHQpO3JldHVybiBuPy5jb25zdHJ1Y3Rvcj9uLmNvbnN0cnVjdG9yLm5hbWU6Im51bGwgcHJvdG90eXBlIn0obik7cmV0dXJuL15IVE1MKFx3KilFbGVtZW50JC8udGVzdChyKT9gW0hUTUxFbGVtZW50OiAke3J9XWA6YFtvYmplY3QgJHtyfV1gfWNhdGNoKHQpe3JldHVybmAqKm5vbi1zZXJpYWxpemFibGUqKiAoJHt0fSlgfXZhciBlfSh0LG4pO2lmKCFjLnN0YXJ0c1dpdGgoIltvYmplY3QgIikpcmV0dXJuIGM7aWYobi5fX3NlbnRyeV9za2lwX25vcm1hbGl6YXRpb25fXylyZXR1cm4gbjtjb25zdCB1PSJudW1iZXIiPT10eXBlb2Ygbi5fX3NlbnRyeV9vdmVycmlkZV9ub3JtYWxpemF0aW9uX2RlcHRoX18/bi5fX3NlbnRyeV9vdmVycmlkZV9ub3JtYWxpemF0aW9uX2RlcHRoX186ZTtpZigwPT09dSlyZXR1cm4gYy5yZXBsYWNlKCJvYmplY3QgIiwiIik7aWYocyhuKSlyZXR1cm4iW0NpcmN1bGFyIH5dIjtjb25zdCBhPW47aWYoYSYmImZ1bmN0aW9uIj09dHlwZW9mIGEudG9KU09OKXRyeXtyZXR1cm4gT3QoIiIsYS50b0pTT04oKSx1LTEscixvKX1jYXRjaCh0KXt9Y29uc3QgZj1BcnJheS5pc0FycmF5KG4pP1tdOnt9O2xldCBoPTA7Y29uc3QgcD1EKG4pO2Zvcihjb25zdCB0IGluIHApe2lmKCFPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwocCx0KSljb250aW51ZTtpZihoPj1yKXtmW3RdPSJbTWF4UHJvcGVydGllcyB+XSI7YnJlYWt9Y29uc3Qgbj1wW3RdO2ZbdF09T3QodCxuLHUtMSxyLG8pLGgrK31yZXR1cm4gaShuKSxmfWZ1bmN0aW9uIEF0KHQsbil7Y29uc3QgZT1uLnJlcGxhY2UoL1xcL2csIi8iKS5yZXBsYWNlKC9bfFxce30oKVtcXV4kKyo/Ll0vZywiXFwkJiIpO2xldCByPXQ7dHJ5e3I9ZGVjb2RlVVJJKHQpfWNhdGNoKHQpe31yZXR1cm4gci5yZXBsYWNlKC9cXC9nLCIvIikucmVwbGFjZSgvd2VicGFjazpcLz8vZywiIikucmVwbGFjZShuZXcgUmVnRXhwKGAoZmlsZTovLyk/Lyoke2V9LypgLCJpZyIpLCJhcHA6Ly8vIil9ZnVuY3Rpb24gUHQodCxuPVtdKXtyZXR1cm5bdCxuXX1mdW5jdGlvbiBVdCh0LG4pe2NvbnN0IGU9dFsxXTtmb3IoY29uc3QgdCBvZiBlKXtpZihuKHQsdFswXS50eXBlKSlyZXR1cm4hMH1yZXR1cm4hMX1mdW5jdGlvbiBNdCh0KXtjb25zdCBuPW0obCk7cmV0dXJuIG4uZW5jb2RlUG9seWZpbGw/bi5lbmNvZGVQb2x5ZmlsbCh0KToobmV3IFRleHRFbmNvZGVyKS5lbmNvZGUodCl9ZnVuY3Rpb24gTHQodCl7Y29uc3RbbixlXT10O2xldCByPUpTT04uc3RyaW5naWZ5KG4pO2Z1bmN0aW9uIG8odCl7InN0cmluZyI9PXR5cGVvZiByP3I9InN0cmluZyI9PXR5cGVvZiB0P3IrdDpbTXQociksdF06ci5wdXNoKCJzdHJpbmciPT10eXBlb2YgdD9NdCh0KTp0KX1mb3IoY29uc3QgdCBvZiBlKXtjb25zdFtuLGVdPXQ7aWYobyhgXG4ke0pTT04uc3RyaW5naWZ5KG4pfVxuYCksInN0cmluZyI9PXR5cGVvZiBlfHxlIGluc3RhbmNlb2YgVWludDhBcnJheSlvKGUpO2Vsc2V7bGV0IHQ7dHJ5e3Q9SlNPTi5zdHJpbmdpZnkoZSl9Y2F0Y2gobil7dD1KU09OLnN0cmluZ2lmeShJdChlKSl9byh0KX19cmV0dXJuInN0cmluZyI9PXR5cGVvZiByP3I6ZnVuY3Rpb24odCl7Y29uc3Qgbj10LnJlZHVjZSgoKHQsbik9PnQrbi5sZW5ndGgpLDApLGU9bmV3IFVpbnQ4QXJyYXkobik7bGV0IHI9MDtmb3IoY29uc3QgbiBvZiB0KWUuc2V0KG4scikscis9bi5sZW5ndGg7cmV0dXJuIGV9KHIpfWNvbnN0IEJ0PXtzZXNzaW9uOiJzZXNzaW9uIixzZXNzaW9uczoic2Vzc2lvbiIsYXR0YWNobWVudDoiYXR0YWNobWVudCIsdHJhbnNhY3Rpb246InRyYW5zYWN0aW9uIixldmVudDoiZXJyb3IiLGNsaWVudF9yZXBvcnQ6ImludGVybmFsIix1c2VyX3JlcG9ydDoiZGVmYXVsdCIscHJvZmlsZToicHJvZmlsZSIscHJvZmlsZV9jaHVuazoicHJvZmlsZSIscmVwbGF5X2V2ZW50OiJyZXBsYXkiLHJlcGxheV9yZWNvcmRpbmc6InJlcGxheSIsY2hlY2tfaW46Im1vbml0b3IiLGZlZWRiYWNrOiJmZWVkYmFjayIsc3Bhbjoic3BhbiIscmF3X3NlY3VyaXR5OiJzZWN1cml0eSIsbG9nOiJsb2dfaXRlbSJ9O2Z1bmN0aW9uIEd0KHQpe2lmKCF0Py5zZGspcmV0dXJuO2NvbnN0e25hbWU6bix2ZXJzaW9uOmV9PXQuc2RrO3JldHVybntuYW1lOm4sdmVyc2lvbjplfX1mdW5jdGlvbiBKdCh0LG4sZSxyKXtjb25zdCBvPUd0KGUpLHM9dC50eXBlJiYicmVwbGF5X2V2ZW50IiE9PXQudHlwZT90LnR5cGU6ImV2ZW50IjshZnVuY3Rpb24odCxuKXtuJiYodC5zZGs9dC5zZGt8fHt9LHQuc2RrLm5hbWU9dC5zZGsubmFtZXx8bi5uYW1lLHQuc2RrLnZlcnNpb249dC5zZGsudmVyc2lvbnx8bi52ZXJzaW9uLHQuc2RrLmludGVncmF0aW9ucz1bLi4udC5zZGsuaW50ZWdyYXRpb25zfHxbXSwuLi5uLmludGVncmF0aW9uc3x8W11dLHQuc2RrLnBhY2thZ2VzPVsuLi50LnNkay5wYWNrYWdlc3x8W10sLi4ubi5wYWNrYWdlc3x8W11dKX0odCxlPy5zZGspO2NvbnN0IGk9ZnVuY3Rpb24odCxuLGUscil7Y29uc3Qgbz10LnNka1Byb2Nlc3NpbmdNZXRhZGF0YT8uZHluYW1pY1NhbXBsaW5nQ29udGV4dDtyZXR1cm57ZXZlbnRfaWQ6dC5ldmVudF9pZCxzZW50X2F0OihuZXcgRGF0ZSkudG9JU09TdHJpbmcoKSwuLi5uJiZ7c2RrOm59LC4uLiEhZSYmciYme2RzbjpEdChyKX0sLi4ubyYme3RyYWNlOm99fX0odCxvLHIsbik7ZGVsZXRlIHQuc2RrUHJvY2Vzc2luZ01ldGFkYXRhO3JldHVybiBQdChpLFtbe3R5cGU6c30sdF1dKX1jb25zdCBZdD0iX19TRU5UUllfU1VQUFJFU1NfVFJBQ0lOR19fIjtmdW5jdGlvbiB6dCh0KXtjb25zdCBuPVgoZCgpKTtyZXR1cm4gbi5zdXBwcmVzc1RyYWNpbmc/bi5zdXBwcmVzc1RyYWNpbmcodCk6ZnVuY3Rpb24oLi4udCl7Y29uc3Qgbj1YKGQoKSk7aWYoMj09PXQubGVuZ3RoKXtjb25zdFtlLHJdPXQ7cmV0dXJuIGU/bi53aXRoU2V0U2NvcGUoZSxyKTpuLndpdGhTY29wZShyKX1yZXR1cm4gbi53aXRoU2NvcGUodFswXSl9KChuPT4obi5zZXRTREtQcm9jZXNzaW5nTWV0YWRhdGEoe1tZdF06ITB9KSx0KCkpKSl9dmFyIEh0O2Z1bmN0aW9uIEZ0KHQpe3JldHVybiBuZXcgV3QoKG49PntuKHQpfSkpfSFmdW5jdGlvbih0KXt0W3QuUEVORElORz0wXT0iUEVORElORyI7dFt0LlJFU09MVkVEPTFdPSJSRVNPTFZFRCI7dFt0LlJFSkVDVEVEPTJdPSJSRUpFQ1RFRCJ9KEh0fHwoSHQ9e30pKTtjbGFzcyBXdHtjb25zdHJ1Y3Rvcih0KXt0aGlzLkw9SHQuUEVORElORyx0aGlzLkI9W10sdGhpcy5HKHQpfXRoZW4odCxuKXtyZXR1cm4gbmV3IFd0KCgoZSxyKT0+e3RoaXMuQi5wdXNoKFshMSxuPT57aWYodCl0cnl7ZSh0KG4pKX1jYXRjaCh0KXtyKHQpfWVsc2UgZShuKX0sdD0+e2lmKG4pdHJ5e2Uobih0KSl9Y2F0Y2godCl7cih0KX1lbHNlIHIodCl9XSksdGhpcy5KKCl9KSl9Y2F0Y2godCl7cmV0dXJuIHRoaXMudGhlbigodD0+dCksdCl9ZmluYWxseSh0KXtyZXR1cm4gbmV3IFd0KCgobixlKT0+e2xldCByLG87cmV0dXJuIHRoaXMudGhlbigobj0+e289ITEscj1uLHQmJnQoKX0pLChuPT57bz0hMCxyPW4sdCYmdCgpfSkpLnRoZW4oKCgpPT57bz9lKHIpOm4ocil9KSl9KSl9Sigpe2lmKHRoaXMuTD09PUh0LlBFTkRJTkcpcmV0dXJuO2NvbnN0IHQ9dGhpcy5CLnNsaWNlKCk7dGhpcy5CPVtdLHQuZm9yRWFjaCgodD0+e3RbMF18fCh0aGlzLkw9PT1IdC5SRVNPTFZFRCYmdFsxXSh0aGlzLlkpLHRoaXMuTD09PUh0LlJFSkVDVEVEJiZ0WzJdKHRoaXMuWSksdFswXT0hMCl9KSl9Ryh0KXtjb25zdCBuPSh0LG4pPT57dGhpcy5MPT09SHQuUEVORElORyYmKHcobik/bi50aGVuKGUscik6KHRoaXMuTD10LHRoaXMuWT1uLHRoaXMuSigpKSl9LGU9dD0+e24oSHQuUkVTT0xWRUQsdCl9LHI9dD0+e24oSHQuUkVKRUNURUQsdCl9O3RyeXt0KGUscil9Y2F0Y2godCl7cih0KX19fWZ1bmN0aW9uIEt0KHQsbil7Y29uc3R7ZmluZ2VycHJpbnQ6ZSxzcGFuOnIsYnJlYWRjcnVtYnM6byxzZGtQcm9jZXNzaW5nTWV0YWRhdGE6c309bjshZnVuY3Rpb24odCxuKXtjb25zdHtleHRyYTplLHRhZ3M6cix1c2VyOm8sY29udGV4dHM6cyxsZXZlbDppLHRyYW5zYWN0aW9uTmFtZTpjfT1uO09iamVjdC5rZXlzKGUpLmxlbmd0aCYmKHQuZXh0cmE9ey4uLmUsLi4udC5leHRyYX0pO09iamVjdC5rZXlzKHIpLmxlbmd0aCYmKHQudGFncz17Li4uciwuLi50LnRhZ3N9KTtPYmplY3Qua2V5cyhvKS5sZW5ndGgmJih0LnVzZXI9ey4uLm8sLi4udC51c2VyfSk7T2JqZWN0LmtleXMocykubGVuZ3RoJiYodC5jb250ZXh0cz17Li4ucywuLi50LmNvbnRleHRzfSk7aSYmKHQubGV2ZWw9aSk7YyYmInRyYW5zYWN0aW9uIiE9PXQudHlwZSYmKHQudHJhbnNhY3Rpb249Yyl9KHQsbiksciYmZnVuY3Rpb24odCxuKXt0LmNvbnRleHRzPXt0cmFjZTpndChuKSwuLi50LmNvbnRleHRzfSx0LnNka1Byb2Nlc3NpbmdNZXRhZGF0YT17ZHluYW1pY1NhbXBsaW5nQ29udGV4dDpqdChuKSwuLi50LnNka1Byb2Nlc3NpbmdNZXRhZGF0YX07Y29uc3QgZT0kdChuKSxyPXZ0KGUpLmRlc2NyaXB0aW9uO3ImJiF0LnRyYW5zYWN0aW9uJiYidHJhbnNhY3Rpb24iPT09dC50eXBlJiYodC50cmFuc2FjdGlvbj1yKX0odCxyKSxmdW5jdGlvbih0LG4pe3QuZmluZ2VycHJpbnQ9dC5maW5nZXJwcmludD9BcnJheS5pc0FycmF5KHQuZmluZ2VycHJpbnQpP3QuZmluZ2VycHJpbnQ6W3QuZmluZ2VycHJpbnRdOltdLG4mJih0LmZpbmdlcnByaW50PXQuZmluZ2VycHJpbnQuY29uY2F0KG4pKTt0LmZpbmdlcnByaW50Lmxlbmd0aHx8ZGVsZXRlIHQuZmluZ2VycHJpbnR9KHQsZSksZnVuY3Rpb24odCxuKXtjb25zdCBlPVsuLi50LmJyZWFkY3J1bWJzfHxbXSwuLi5uXTt0LmJyZWFkY3J1bWJzPWUubGVuZ3RoP2U6dm9pZCAwfSh0LG8pLGZ1bmN0aW9uKHQsbil7dC5zZGtQcm9jZXNzaW5nTWV0YWRhdGE9ey4uLnQuc2RrUHJvY2Vzc2luZ01ldGFkYXRhLC4uLm59fSh0LHMpfWNvbnN0IFZ0PSI3Ijtjb25zdCBadD1TeW1ib2wuZm9yKCJTZW50cnlCdWZmZXJGdWxsRXJyb3IiKTtmdW5jdGlvbiBxdCh0KXtjb25zdCBuPVtdO2Z1bmN0aW9uIGUodCl7cmV0dXJuIG4uc3BsaWNlKG4uaW5kZXhPZih0KSwxKVswXXx8UHJvbWlzZS5yZXNvbHZlKHZvaWQgMCl9cmV0dXJueyQ6bixhZGQ6ZnVuY3Rpb24ocil7aWYoISh2b2lkIDA9PT10fHxuLmxlbmd0aDx0KSlyZXR1cm4gbz1adCxuZXcgV3QoKCh0LG4pPT57bihvKX0pKTt2YXIgbztjb25zdCBzPXIoKTtyZXR1cm4tMT09PW4uaW5kZXhPZihzKSYmbi5wdXNoKHMpLHMudGhlbigoKCk9PmUocykpKS50aGVuKG51bGwsKCgpPT5lKHMpLnRoZW4obnVsbCwoKCk9Pnt9KSkpKSxzfSxkcmFpbjpmdW5jdGlvbih0KXtyZXR1cm4gbmV3IFd0KCgoZSxyKT0+e2xldCBvPW4ubGVuZ3RoO2lmKCFvKXJldHVybiBlKCEwKTtjb25zdCBzPXNldFRpbWVvdXQoKCgpPT57dCYmdD4wJiZlKCExKX0pLHQpO24uZm9yRWFjaCgodD0+e0Z0KHQpLnRoZW4oKCgpPT57LS1vfHwoY2xlYXJUaW1lb3V0KHMpLGUoITApKX0pLHIpfSkpfSkpfX19Y29uc3QgUXQ9NmU0O2Z1bmN0aW9uIFh0KHQse3N0YXR1c0NvZGU6bixoZWFkZXJzOmV9LHI9RGF0ZS5ub3coKSl7Y29uc3Qgbz17Li4udH0scz1lPy5bIngtc2VudHJ5LXJhdGUtbGltaXRzIl0saT1lPy5bInJldHJ5LWFmdGVyIl07aWYocylmb3IoY29uc3QgdCBvZiBzLnRyaW0oKS5zcGxpdCgiLCIpKXtjb25zdFtuLGUsLCxzXT10LnNwbGl0KCI6Iiw1KSxpPXBhcnNlSW50KG4sMTApLGM9MWUzKihpc05hTihpKT82MDppKTtpZihlKWZvcihjb25zdCB0IG9mIGUuc3BsaXQoIjsiKSkibWV0cmljX2J1Y2tldCI9PT10JiZzJiYhcy5zcGxpdCgiOyIpLmluY2x1ZGVzKCJjdXN0b20iKXx8KG9bdF09citjKTtlbHNlIG8uYWxsPXIrY31lbHNlIGk/by5hbGw9citmdW5jdGlvbih0LG49RGF0ZS5ub3coKSl7Y29uc3QgZT1wYXJzZUludChgJHt0fWAsMTApO2lmKCFpc05hTihlKSlyZXR1cm4gMWUzKmU7Y29uc3Qgcj1EYXRlLnBhcnNlKGAke3R9YCk7cmV0dXJuIGlzTmFOKHIpP1F0OnItbn0oaSxyKTo0Mjk9PT1uJiYoby5hbGw9cis2ZTQpO3JldHVybiBvfWNvbnN0IHRuPTY0O2Z1bmN0aW9uIG5uKHQsbixlPXF0KHQuYnVmZmVyU2l6ZXx8dG4pKXtsZXQgcj17fTtyZXR1cm57c2VuZDpmdW5jdGlvbih0KXtjb25zdCBvPVtdO2lmKFV0KHQsKCh0LG4pPT57Y29uc3QgZT1mdW5jdGlvbih0KXtyZXR1cm4gQnRbdF19KG4pOyhmdW5jdGlvbih0LG4sZT1EYXRlLm5vdygpKXtyZXR1cm4gZnVuY3Rpb24odCxuKXtyZXR1cm4gdFtuXXx8dC5hbGx8fDB9KHQsbik+ZX0pKHIsZSl8fG8ucHVzaCh0KX0pKSwwPT09by5sZW5ndGgpcmV0dXJuIEZ0KHt9KTtjb25zdCBzPVB0KHRbMF0sbyksaT10PT57VXQocywoKHQsbik9Pnt9KSl9O3JldHVybiBlLmFkZCgoKCk9Pm4oe2JvZHk6THQocyl9KS50aGVuKCh0PT4odm9pZCAwIT09dC5zdGF0dXNDb2RlJiYodC5zdGF0dXNDb2RlPDIwMHx8dC5zdGF0dXNDb2RlPj0zMDApJiZoJiZrLndhcm4oYFNlbnRyeSByZXNwb25kZWQgd2l0aCBzdGF0dXMgY29kZSAke3Quc3RhdHVzQ29kZX0gdG8gc2VudCBldmVudC5gKSxyPVh0KHIsdCksdCkpLCh0PT57dGhyb3cgaSgpLGgmJmsuZXJyb3IoIkVuY291bnRlcmVkIGVycm9yIHJ1bm5pbmcgdHJhbnNwb3J0IHJlcXVlc3Q6Iix0KSx0fSkpKSkudGhlbigodD0+dCksKHQ9PntpZih0PT09WnQpcmV0dXJuIGgmJmsuZXJyb3IoIlNraXBwZWQgc2VuZGluZyBldmVudCBiZWNhdXNlIGJ1ZmZlciBpcyBmdWxsLiIpLGkoKSxGdCh7fSk7dGhyb3cgdH0pKX0sZmx1c2g6dD0+ZS5kcmFpbih0KX19Y29uc3QgZW49L14oXFMrOlxcfFwvPykoW1xzXFNdKj8pKCg/OlwuezEsMn18W14vXFxdKz98KShcLlteLi9cXF0qfCkpKD86Wy9cXF0qKSQvO2Z1bmN0aW9uIHJuKHQpe2NvbnN0IG49ZnVuY3Rpb24odCl7Y29uc3Qgbj10Lmxlbmd0aD4xMDI0P2A8dHJ1bmNhdGVkPiR7dC5zbGljZSgtMTAyNCl9YDp0LGU9ZW4uZXhlYyhuKTtyZXR1cm4gZT9lLnNsaWNlKDEpOltdfSh0KSxlPW5bMF18fCIiO2xldCByPW5bMV07cmV0dXJuIGV8fHI/KHImJihyPXIuc2xpY2UoMCxyLmxlbmd0aC0xKSksZStyKToiLiJ9ZnVuY3Rpb24gb24odCxuPSExKXtyZXR1cm4hKG58fHQmJiF0LnN0YXJ0c1dpdGgoIi8iKSYmIXQubWF0Y2goL15bQS1aXTovKSYmIXQuc3RhcnRzV2l0aCgiLiIpJiYhdC5tYXRjaCgvXlthLXpBLVpdKFthLXpBLVowLTkuXC0rXSkqOlwvXC8vKSkmJnZvaWQgMCE9PXQmJiF0LmluY2x1ZGVzKCJub2RlX21vZHVsZXMvIil9Y29uc3Qgc249U3ltYm9sKCJBZ2VudEJhc2VJbnRlcm5hbFN0YXRlIik7Y2xhc3MgY24gZXh0ZW5kcyBzLkFnZW50e2NvbnN0cnVjdG9yKHQpe3N1cGVyKHQpLHRoaXNbc25dPXt9fWlzU2VjdXJlRW5kcG9pbnQodCl7aWYodCl7aWYoImJvb2xlYW4iPT10eXBlb2YgdC5zZWN1cmVFbmRwb2ludClyZXR1cm4gdC5zZWN1cmVFbmRwb2ludDtpZigic3RyaW5nIj09dHlwZW9mIHQucHJvdG9jb2wpcmV0dXJuImh0dHBzOiI9PT10LnByb3RvY29sfWNvbnN0e3N0YWNrOm59PW5ldyBFcnJvcjtyZXR1cm4ic3RyaW5nIj09dHlwZW9mIG4mJm4uc3BsaXQoIlxuIikuc29tZSgodD0+LTEhPT10LmluZGV4T2YoIihodHRwcy5qczoiKXx8LTEhPT10LmluZGV4T2YoIm5vZGU6aHR0cHM6IikpKX1jcmVhdGVTb2NrZXQodCxuLGUpe2NvbnN0IHI9ey4uLm4sc2VjdXJlRW5kcG9pbnQ6dGhpcy5pc1NlY3VyZUVuZHBvaW50KG4pfTtQcm9taXNlLnJlc29sdmUoKS50aGVuKCgoKT0+dGhpcy5jb25uZWN0KHQscikpKS50aGVuKChvPT57aWYobyBpbnN0YW5jZW9mIHMuQWdlbnQpcmV0dXJuIG8uYWRkUmVxdWVzdCh0LHIpO3RoaXNbc25dLmN1cnJlbnRTb2NrZXQ9byxzdXBlci5jcmVhdGVTb2NrZXQodCxuLGUpfSksZSl9Y3JlYXRlQ29ubmVjdGlvbigpe2NvbnN0IHQ9dGhpc1tzbl0uY3VycmVudFNvY2tldDtpZih0aGlzW3NuXS5jdXJyZW50U29ja2V0PXZvaWQgMCwhdCl0aHJvdyBuZXcgRXJyb3IoIk5vIHNvY2tldCB3YXMgcmV0dXJuZWQgaW4gdGhlIGBjb25uZWN0KClgIGZ1bmN0aW9uIik7cmV0dXJuIHR9Z2V0IGRlZmF1bHRQb3J0KCl7cmV0dXJuIHRoaXNbc25dLmRlZmF1bHRQb3J0Pz8oImh0dHBzOiI9PT10aGlzLnByb3RvY29sPzQ0Mzo4MCl9c2V0IGRlZmF1bHRQb3J0KHQpe3RoaXNbc25dJiYodGhpc1tzbl0uZGVmYXVsdFBvcnQ9dCl9Z2V0IHByb3RvY29sKCl7cmV0dXJuIHRoaXNbc25dLnByb3RvY29sPz8odGhpcy5pc1NlY3VyZUVuZHBvaW50KCk/Imh0dHBzOiI6Imh0dHA6Iil9c2V0IHByb3RvY29sKHQpe3RoaXNbc25dJiYodGhpc1tzbl0ucHJvdG9jb2w9dCl9fWZ1bmN0aW9uIHVuKC4uLnQpe2subG9nKCJbaHR0cHMtcHJveHktYWdlbnQ6cGFyc2UtcHJveHktcmVzcG9uc2VdIiwuLi50KX1mdW5jdGlvbiBhbih0KXtyZXR1cm4gbmV3IFByb21pc2UoKChuLGUpPT57bGV0IHI9MDtjb25zdCBvPVtdO2Z1bmN0aW9uIHMoKXtjb25zdCBjPXQucmVhZCgpO2M/ZnVuY3Rpb24oYyl7by5wdXNoKGMpLHIrPWMubGVuZ3RoO2NvbnN0IHU9QnVmZmVyLmNvbmNhdChvLHIpLGE9dS5pbmRleE9mKCJcclxuXHJcbiIpO2lmKC0xPT09YSlyZXR1cm4gdW4oImhhdmUgbm90IHJlY2VpdmVkIGVuZCBvZiBIVFRQIGhlYWRlcnMgeWV0Li4uIiksdm9pZCBzKCk7Y29uc3QgZj11LnN1YmFycmF5KDAsYSkudG9TdHJpbmcoImFzY2lpIikuc3BsaXQoIlxyXG4iKSxoPWYuc2hpZnQoKTtpZighaClyZXR1cm4gdC5kZXN0cm95KCksZShuZXcgRXJyb3IoIk5vIGhlYWRlciByZWNlaXZlZCBmcm9tIHByb3h5IENPTk5FQ1QgcmVzcG9uc2UiKSk7Y29uc3QgcD1oLnNwbGl0KCIgIiksbD0rKHBbMV18fDApLGQ9cC5zbGljZSgyKS5qb2luKCIgIiksbT17fTtmb3IoY29uc3QgbiBvZiBmKXtpZighbiljb250aW51ZTtjb25zdCByPW4uaW5kZXhPZigiOiIpO2lmKC0xPT09cilyZXR1cm4gdC5kZXN0cm95KCksZShuZXcgRXJyb3IoYEludmFsaWQgaGVhZGVyIGZyb20gcHJveHkgQ09OTkVDVCByZXNwb25zZTogIiR7bn0iYCkpO2NvbnN0IG89bi5zbGljZSgwLHIpLnRvTG93ZXJDYXNlKCkscz1uLnNsaWNlKHIrMSkudHJpbVN0YXJ0KCksaT1tW29dOyJzdHJpbmciPT10eXBlb2YgaT9tW29dPVtpLHNdOkFycmF5LmlzQXJyYXkoaSk/aS5wdXNoKHMpOm1bb109c311bigiZ290IHByb3h5IHNlcnZlciByZXNwb25zZTogJW8gJW8iLGgsbSksaSgpLG4oe2Nvbm5lY3Q6e3N0YXR1c0NvZGU6bCxzdGF0dXNUZXh0OmQsaGVhZGVyczptfSxidWZmZXJlZDp1fSl9KGMpOnQub25jZSgicmVhZGFibGUiLHMpfWZ1bmN0aW9uIGkoKXt0LnJlbW92ZUxpc3RlbmVyKCJlbmQiLGMpLHQucmVtb3ZlTGlzdGVuZXIoImVycm9yIix1KSx0LnJlbW92ZUxpc3RlbmVyKCJyZWFkYWJsZSIscyl9ZnVuY3Rpb24gYygpe2koKSx1bigib25lbmQiKSxlKG5ldyBFcnJvcigiUHJveHkgY29ubmVjdGlvbiBlbmRlZCBiZWZvcmUgcmVjZWl2aW5nIENPTk5FQ1QgcmVzcG9uc2UiKSl9ZnVuY3Rpb24gdSh0KXtpKCksdW4oIm9uZXJyb3IgJW8iLHQpLGUodCl9dC5vbigiZXJyb3IiLHUpLHQub24oImVuZCIsYykscygpfSkpfWZ1bmN0aW9uIGZuKC4uLnQpe2subG9nKCJbaHR0cHMtcHJveHktYWdlbnRdIiwuLi50KX1jbGFzcyBobiBleHRlbmRzIGNue3N0YXRpYyBfX2luaXRTdGF0aWMoKXt0aGlzLnByb3RvY29scz1bImh0dHAiLCJodHRwcyJdfWNvbnN0cnVjdG9yKHQsbil7c3VwZXIobiksdGhpcy5vcHRpb25zPXt9LHRoaXMucHJveHk9InN0cmluZyI9PXR5cGVvZiB0P25ldyBVUkwodCk6dCx0aGlzLnByb3h5SGVhZGVycz1uPy5oZWFkZXJzPz97fSxmbigiQ3JlYXRpbmcgbmV3IEh0dHBzUHJveHlBZ2VudCBpbnN0YW5jZTogJW8iLHRoaXMucHJveHkuaHJlZik7Y29uc3QgZT0odGhpcy5wcm94eS5ob3N0bmFtZXx8dGhpcy5wcm94eS5ob3N0KS5yZXBsYWNlKC9eXFt8XF0kL2csIiIpLHI9dGhpcy5wcm94eS5wb3J0P3BhcnNlSW50KHRoaXMucHJveHkucG9ydCwxMCk6Imh0dHBzOiI9PT10aGlzLnByb3h5LnByb3RvY29sPzQ0Mzo4MDt0aGlzLmNvbm5lY3RPcHRzPXtBTFBOUHJvdG9jb2xzOlsiaHR0cC8xLjEiXSwuLi5uP2xuKG4sImhlYWRlcnMiKTpudWxsLGhvc3Q6ZSxwb3J0OnJ9fWFzeW5jIGNvbm5lY3QodCxuKXtjb25zdHtwcm94eTplfT10aGlzO2lmKCFuLmhvc3QpdGhyb3cgbmV3IFR5cGVFcnJvcignTm8gImhvc3QiIHByb3ZpZGVkJyk7bGV0IHI7aWYoImh0dHBzOiI9PT1lLnByb3RvY29sKXtmbigiQ3JlYXRpbmcgYHRscy5Tb2NrZXRgOiAlbyIsdGhpcy5jb25uZWN0T3B0cyk7Y29uc3QgdD10aGlzLmNvbm5lY3RPcHRzLnNlcnZlcm5hbWV8fHRoaXMuY29ubmVjdE9wdHMuaG9zdDtyPWYuY29ubmVjdCh7Li4udGhpcy5jb25uZWN0T3B0cyxzZXJ2ZXJuYW1lOnQmJmEuaXNJUCh0KT92b2lkIDA6dH0pfWVsc2UgZm4oIkNyZWF0aW5nIGBuZXQuU29ja2V0YDogJW8iLHRoaXMuY29ubmVjdE9wdHMpLHI9YS5jb25uZWN0KHRoaXMuY29ubmVjdE9wdHMpO2NvbnN0IG89ImZ1bmN0aW9uIj09dHlwZW9mIHRoaXMucHJveHlIZWFkZXJzP3RoaXMucHJveHlIZWFkZXJzKCk6ey4uLnRoaXMucHJveHlIZWFkZXJzfSxzPWEuaXNJUHY2KG4uaG9zdCk/YFske24uaG9zdH1dYDpuLmhvc3Q7bGV0IGk9YENPTk5FQ1QgJHtzfToke24ucG9ydH0gSFRUUC8xLjFcclxuYDtpZihlLnVzZXJuYW1lfHxlLnBhc3N3b3JkKXtjb25zdCB0PWAke2RlY29kZVVSSUNvbXBvbmVudChlLnVzZXJuYW1lKX06JHtkZWNvZGVVUklDb21wb25lbnQoZS5wYXNzd29yZCl9YDtvWyJQcm94eS1BdXRob3JpemF0aW9uIl09YEJhc2ljICR7QnVmZmVyLmZyb20odCkudG9TdHJpbmcoImJhc2U2NCIpfWB9by5Ib3N0PWAke3N9OiR7bi5wb3J0fWAsb1siUHJveHktQ29ubmVjdGlvbiJdfHwob1siUHJveHktQ29ubmVjdGlvbiJdPXRoaXMua2VlcEFsaXZlPyJLZWVwLUFsaXZlIjoiY2xvc2UiKTtmb3IoY29uc3QgdCBvZiBPYmplY3Qua2V5cyhvKSlpKz1gJHt0fTogJHtvW3RdfVxyXG5gO2NvbnN0IGM9YW4ocik7ci53cml0ZShgJHtpfVxyXG5gKTtjb25zdHtjb25uZWN0OnUsYnVmZmVyZWQ6aH09YXdhaXQgYztpZih0LmVtaXQoInByb3h5Q29ubmVjdCIsdSksdGhpcy5lbWl0KCJwcm94eUNvbm5lY3QiLHUsdCksMjAwPT09dS5zdGF0dXNDb2RlKXtpZih0Lm9uY2UoInNvY2tldCIscG4pLG4uc2VjdXJlRW5kcG9pbnQpe2ZuKCJVcGdyYWRpbmcgc29ja2V0IGNvbm5lY3Rpb24gdG8gVExTIik7Y29uc3QgdD1uLnNlcnZlcm5hbWV8fG4uaG9zdDtyZXR1cm4gZi5jb25uZWN0KHsuLi5sbihuLCJob3N0IiwicGF0aCIsInBvcnQiKSxzb2NrZXQ6cixzZXJ2ZXJuYW1lOmEuaXNJUCh0KT92b2lkIDA6dH0pfXJldHVybiByfXIuZGVzdHJveSgpO2NvbnN0IHA9bmV3IGEuU29ja2V0KHt3cml0YWJsZTohMX0pO3JldHVybiBwLnJlYWRhYmxlPSEwLHQub25jZSgic29ja2V0IiwodD0+e2ZuKCJSZXBsYXlpbmcgcHJveHkgYnVmZmVyIGZvciBmYWlsZWQgcmVxdWVzdCIpLHQucHVzaChoKSx0LnB1c2gobnVsbCl9KSkscH19ZnVuY3Rpb24gcG4odCl7dC5yZXN1bWUoKX1mdW5jdGlvbiBsbih0LC4uLm4pe2NvbnN0IGU9e307bGV0IHI7Zm9yKHIgaW4gdCluLmluY2x1ZGVzKHIpfHwoZVtyXT10W3JdKTtyZXR1cm4gZX1obi5fX2luaXRTdGF0aWMoKTtjb25zdCBkbj0zMjc2ODtmdW5jdGlvbiBtbih0KXtyZXR1cm4gdC5yZXBsYWNlKC9eW0EtWl06LywiIikucmVwbGFjZSgvXFwvZywiLyIpfWNvbnN0IGduPW47bGV0IHluLGJuPTAsX249e307ZnVuY3Rpb24gdm4odCl7Z24uZGVidWcmJmNvbnNvbGUubG9nKGBbQU5SIFdvcmtlcl0gJHt0fWApfXZhciB3bixTbiwkbjtjb25zdCBFbj1mdW5jdGlvbih0KXtsZXQgbjt0cnl7bj1uZXcgVVJMKHQudXJsKX1jYXRjaChuKXtyZXR1cm4gUigoKCk9Pntjb25zb2xlLndhcm4oIltAc2VudHJ5L25vZGVdOiBJbnZhbGlkIGRzbiBvciB0dW5uZWwgb3B0aW9uLCB3aWxsIG5vdCBzZW5kIGFueSBldmVudHMuIFRoZSB0dW5uZWwgb3B0aW9uIG11c3QgYmUgYSBmdWxsIFVSTCB3aGVuIHVzZWQuIil9KSksbm4odCwoKCk9PlByb21pc2UucmVzb2x2ZSh7fSkpKX1jb25zdCBlPSJodHRwczoiPT09bi5wcm90b2NvbCxyPWZ1bmN0aW9uKHQsbil7Y29uc3R7bm9fcHJveHk6ZX09cHJvY2Vzcy5lbnYscj1lPy5zcGxpdCgiLCIpLnNvbWUoKG49PnQuaG9zdC5lbmRzV2l0aChuKXx8dC5ob3N0bmFtZS5lbmRzV2l0aChuKSkpO3JldHVybiByP3ZvaWQgMDpufShuLHQucHJveHl8fChlP3Byb2Nlc3MuZW52Lmh0dHBzX3Byb3h5OnZvaWQgMCl8fHByb2Nlc3MuZW52Lmh0dHBfcHJveHkpLG89ZT9pOnMsYT12b2lkIDAhPT10LmtlZXBBbGl2ZSYmdC5rZWVwQWxpdmUsZj1yP25ldyBobihyKTpuZXcgby5BZ2VudCh7a2VlcEFsaXZlOmEsbWF4U29ja2V0czozMCx0aW1lb3V0OjJlM30pLGg9ZnVuY3Rpb24odCxuLGUpe2NvbnN0e2hvc3RuYW1lOnIscGF0aG5hbWU6byxwb3J0OnMscHJvdG9jb2w6aSxzZWFyY2g6YX09bmV3IFVSTCh0LnVybCk7cmV0dXJuIGZ1bmN0aW9uKGYpe3JldHVybiBuZXcgUHJvbWlzZSgoKGgscCk9Pnt6dCgoKCk9PntsZXQgbD1mdW5jdGlvbih0KXtyZXR1cm4gbmV3IGMoe3JlYWQoKXt0aGlzLnB1c2godCksdGhpcy5wdXNoKG51bGwpfX0pfShmLmJvZHkpO2NvbnN0IGQ9ey4uLnQuaGVhZGVyc307Zi5ib2R5Lmxlbmd0aD5kbiYmKGRbImNvbnRlbnQtZW5jb2RpbmciXT0iZ3ppcCIsbD1sLnBpcGUodSgpKSk7Y29uc3QgbT1uLnJlcXVlc3Qoe21ldGhvZDoiUE9TVCIsYWdlbnQ6ZSxoZWFkZXJzOmQsaG9zdG5hbWU6cixwYXRoOmAke299JHthfWAscG9ydDpzLHByb3RvY29sOmksY2E6dC5jYUNlcnRzfSwodD0+e3Qub24oImRhdGEiLCgoKT0+e30pKSx0Lm9uKCJlbmQiLCgoKT0+e30pKSx0LnNldEVuY29kaW5nKCJ1dGY4Iik7Y29uc3Qgbj10LmhlYWRlcnNbInJldHJ5LWFmdGVyIl0/P251bGwsZT10LmhlYWRlcnNbIngtc2VudHJ5LXJhdGUtbGltaXRzIl0/P251bGw7aCh7c3RhdHVzQ29kZTp0LnN0YXR1c0NvZGUsaGVhZGVyczp7InJldHJ5LWFmdGVyIjpuLCJ4LXNlbnRyeS1yYXRlLWxpbWl0cyI6QXJyYXkuaXNBcnJheShlKT9lWzBdfHxudWxsOmV9fSl9KSk7bS5vbigiZXJyb3IiLHApLGwucGlwZShtKX0pKX0pKX19KHQsdC5odHRwTW9kdWxlPz9vLGYpO3JldHVybiBubih0LGgpfSh7dXJsOih3bj1nbi5kc24sU249Z24udHVubmVsLCRuPWduLnNka01ldGFkYXRhLnNkayxTbnx8YCR7ZnVuY3Rpb24odCl7cmV0dXJuYCR7ZnVuY3Rpb24odCl7Y29uc3Qgbj10LnByb3RvY29sP2Ake3QucHJvdG9jb2x9OmA6IiIsZT10LnBvcnQ/YDoke3QucG9ydH1gOiIiO3JldHVybmAke259Ly8ke3QuaG9zdH0ke2V9JHt0LnBhdGg/YC8ke3QucGF0aH1gOiIifS9hcGkvYH0odCl9JHt0LnByb2plY3RJZH0vZW52ZWxvcGUvYH0od24pfT8ke2Z1bmN0aW9uKHQsbil7Y29uc3QgZT17c2VudHJ5X3ZlcnNpb246VnR9O3JldHVybiB0LnB1YmxpY0tleSYmKGUuc2VudHJ5X2tleT10LnB1YmxpY0tleSksbiYmKGUuc2VudHJ5X2NsaWVudD1gJHtuLm5hbWV9LyR7bi52ZXJzaW9ufWApLG5ldyBVUkxTZWFyY2hQYXJhbXMoZSkudG9TdHJpbmcoKX0od24sJG4pfWApfSk7YXN5bmMgZnVuY3Rpb24geG4oKXtpZih5bil7dm4oIlNlbmRpbmcgYWJub3JtYWwgc2Vzc2lvbiIpLEIoeW4se3N0YXR1czoiYWJub3JtYWwiLGFibm9ybWFsX21lY2hhbmlzbToiYW5yX2ZvcmVncm91bmQiLHJlbGVhc2U6Z24ucmVsZWFzZSxlbnZpcm9ubWVudDpnbi5lbnZpcm9ubWVudH0pO2NvbnN0IHQ9ZnVuY3Rpb24odCxuLGUscil7Y29uc3Qgbz1HdChlKTtyZXR1cm4gUHQoe3NlbnRfYXQ6KG5ldyBEYXRlKS50b0lTT1N0cmluZygpLC4uLm8mJntzZGs6b30sLi4uISFyJiZuJiZ7ZHNuOkR0KG4pfX0sWyJhZ2dyZWdhdGVzImluIHQ/W3t0eXBlOiJzZXNzaW9ucyJ9LHRdOlt7dHlwZToic2Vzc2lvbiJ9LHQudG9KU09OKCldXSl9KHluLGduLmRzbixnbi5zZGtNZXRhZGF0YSxnbi50dW5uZWwpO3ZuKEpTT04uc3RyaW5naWZ5KHQpKSxhd2FpdCBFbi5zZW5kKHQpO3RyeXtlPy5wb3N0TWVzc2FnZSgic2Vzc2lvbi1lbmRlZCIpfWNhdGNoKHQpe319fWZ1bmN0aW9uIE5uKHQpe2lmKCF0KXJldHVybjtjb25zdCBuPWZ1bmN0aW9uKHQpe2lmKCF0Lmxlbmd0aClyZXR1cm5bXTtjb25zdCBuPUFycmF5LmZyb20odCk7cmV0dXJuL3NlbnRyeVdyYXBwZWQvLnRlc3QoVHQobikuZnVuY3Rpb258fCIiKSYmbi5wb3AoKSxuLnJldmVyc2UoKSxOdC50ZXN0KFR0KG4pLmZ1bmN0aW9ufHwiIikmJihuLnBvcCgpLE50LnRlc3QoVHQobikuZnVuY3Rpb258fCIiKSYmbi5wb3AoKSksbi5zbGljZSgwLEV0KS5tYXAoKHQ9Pih7Li4udCxmaWxlbmFtZTp0LmZpbGVuYW1lfHxUdChuKS5maWxlbmFtZSxmdW5jdGlvbjp0LmZ1bmN0aW9ufHx4dH0pKSl9KHQpO2lmKGduLmFwcFJvb3RQYXRoKWZvcihjb25zdCB0IG9mIG4pdC5maWxlbmFtZSYmKHQuZmlsZW5hbWU9QXQodC5maWxlbmFtZSxnbi5hcHBSb290UGF0aCkpO3JldHVybiBufWFzeW5jIGZ1bmN0aW9uIFRuKHQsbil7aWYoYm4+PWduLm1heEFuckV2ZW50cylyZXR1cm47Ym4rPTEsYXdhaXQgeG4oKSx2bigiU2VuZGluZyBldmVudCIpO2NvbnN0IGU9e2V2ZW50X2lkOkEoKSxjb250ZXh0czpnbi5jb250ZXh0cyxyZWxlYXNlOmduLnJlbGVhc2UsZW52aXJvbm1lbnQ6Z24uZW52aXJvbm1lbnQsZGlzdDpnbi5kaXN0LHBsYXRmb3JtOiJub2RlIixsZXZlbDoiZXJyb3IiLGV4Y2VwdGlvbjp7dmFsdWVzOlt7dHlwZToiQXBwbGljYXRpb25Ob3RSZXNwb25kaW5nIix2YWx1ZTpgQXBwbGljYXRpb24gTm90IFJlc3BvbmRpbmcgZm9yIGF0IGxlYXN0ICR7Z24uYW5yVGhyZXNob2xkfSBtc2Asc3RhY2t0cmFjZTp7ZnJhbWVzOk5uKHQpfSxtZWNoYW5pc206e3R5cGU6IkFOUiJ9fV19LHRhZ3M6Z24uc3RhdGljVGFnc307biYmZnVuY3Rpb24odCxuKXtpZihLdCh0LG4pLCF0LmNvbnRleHRzPy50cmFjZSl7Y29uc3R7dHJhY2VJZDplLHBhcmVudFNwYW5JZDpyLHByb3BhZ2F0aW9uU3BhbklkOm99PW4ucHJvcGFnYXRpb25Db250ZXh0O3QuY29udGV4dHM9e3RyYWNlOnt0cmFjZV9pZDplLHNwYW5faWQ6b3x8RigpLHBhcmVudF9zcGFuX2lkOnJ9LC4uLnQuY29udGV4dHN9fX0oZSxuKSxmdW5jdGlvbih0KXtpZigwPT09T2JqZWN0LmtleXMoX24pLmxlbmd0aClyZXR1cm47Y29uc3Qgbj1nbi5hcHBSb290UGF0aD97fTpfbjtpZihnbi5hcHBSb290UGF0aClmb3IoY29uc3RbdCxlXW9mIE9iamVjdC5lbnRyaWVzKF9uKSluW0F0KHQsZ24uYXBwUm9vdFBhdGgpXT1lO2NvbnN0IGU9bmV3IE1hcDtmb3IoY29uc3QgciBvZiB0LmV4Y2VwdGlvbj8udmFsdWVzfHxbXSlmb3IoY29uc3QgdCBvZiByLnN0YWNrdHJhY2U/LmZyYW1lc3x8W10pe2NvbnN0IHI9dC5hYnNfcGF0aHx8dC5maWxlbmFtZTtyJiZuW3JdJiZlLnNldChyLG5bcl0pfWlmKGUuc2l6ZT4wKXtjb25zdCBuPVtdO2Zvcihjb25zdFt0LHJdb2YgZS5lbnRyaWVzKCkpbi5wdXNoKHt0eXBlOiJzb3VyY2VtYXAiLGNvZGVfZmlsZTp0LGRlYnVnX2lkOnJ9KTt0LmRlYnVnX21ldGE9e2ltYWdlczpufX19KGUpO2NvbnN0IHI9SnQoZSxnbi5kc24sZ24uc2RrTWV0YWRhdGEsZ24udHVubmVsKTt2bihKU09OLnN0cmluZ2lmeShyKSksYXdhaXQgRW4uc2VuZChyKSxhd2FpdCBFbi5mbHVzaCgyZTMpLGJuPj1nbi5tYXhBbnJFdmVudHMmJnNldFRpbWVvdXQoKCgpPT57cHJvY2Vzcy5leGl0KDApfSksNWUzKX1sZXQgQ247aWYodm4oIlN0YXJ0ZWQiKSxnbi5jYXB0dXJlU3RhY2tUcmFjZSl7dm4oIkNvbm5lY3RpbmcgdG8gZGVidWdnZXIiKTtjb25zdCBuPW5ldyB0O24uY29ubmVjdFRvTWFpblRocmVhZCgpLHZuKCJDb25uZWN0ZWQgdG8gZGVidWdnZXIiKTtjb25zdCBlPW5ldyBNYXA7bi5vbigiRGVidWdnZXIuc2NyaXB0UGFyc2VkIiwodD0+e2Uuc2V0KHQucGFyYW1zLnNjcmlwdElkLHQucGFyYW1zLnVybCl9KSksbi5vbigiRGVidWdnZXIucGF1c2VkIiwodD0+e2lmKCJvdGhlciI9PT10LnBhcmFtcy5yZWFzb24pdHJ5e3ZuKCJEZWJ1Z2dlciBwYXVzZWQiKTtjb25zdCBzPVsuLi50LnBhcmFtcy5jYWxsRnJhbWVzXSxpPWduLmFwcFJvb3RQYXRoP2Z1bmN0aW9uKHQ9KHByb2Nlc3MuYXJndlsxXT9ybihwcm9jZXNzLmFyZ3ZbMV0pOnByb2Nlc3MuY3dkKCkpLG49IlxcIj09PW8pe2NvbnN0IGU9bj9tbih0KTp0O3JldHVybiB0PT57aWYoIXQpcmV0dXJuO2NvbnN0IG89bj9tbih0KTp0O2xldHtkaXI6cyxiYXNlOmksZXh0OmN9PXIucGFyc2Uobyk7Ii5qcyIhPT1jJiYiLm1qcyIhPT1jJiYiLmNqcyIhPT1jfHwoaT1pLnNsaWNlKDAsLTEqYy5sZW5ndGgpKTtjb25zdCB1PWRlY29kZVVSSUNvbXBvbmVudChpKTtzfHwocz0iLiIpO2NvbnN0IGE9cy5sYXN0SW5kZXhPZigiL25vZGVfbW9kdWxlcyIpO2lmKGE+LTEpcmV0dXJuYCR7cy5zbGljZShhKzE0KS5yZXBsYWNlKC9cLy9nLCIuIil9OiR7dX1gO2lmKHMuc3RhcnRzV2l0aChlKSl7Y29uc3QgdD1zLnNsaWNlKGUubGVuZ3RoKzEpLnJlcGxhY2UoL1wvL2csIi4iKTtyZXR1cm4gdD9gJHt0fToke3V9YDp1fXJldHVybiB1fX0oZ24uYXBwUm9vdFBhdGgpOigpPT57fSxjPXMubWFwKCh0PT5mdW5jdGlvbih0LG4sZSl7Y29uc3Qgcj1uP24ucmVwbGFjZSgvXmZpbGU6XC9cLy8sIiIpOnZvaWQgMCxvPXQubG9jYXRpb24uY29sdW1uTnVtYmVyP3QubG9jYXRpb24uY29sdW1uTnVtYmVyKzE6dm9pZCAwLHM9dC5sb2NhdGlvbi5saW5lTnVtYmVyP3QubG9jYXRpb24ubGluZU51bWJlcisxOnZvaWQgMDtyZXR1cm57ZmlsZW5hbWU6cixtb2R1bGU6ZShyKSxmdW5jdGlvbjp0LmZ1bmN0aW9uTmFtZXx8eHQsY29sbm86byxsaW5lbm86cyxpbl9hcHA6cj9vbihyKTp2b2lkIDB9fSh0LGUuZ2V0KHQubG9jYXRpb24uc2NyaXB0SWQpLGkpKSksdT1zZXRUaW1lb3V0KCgoKT0+e1RuKGMpLnRoZW4obnVsbCwoKCk9Pnt2bigiU2VuZGluZyBBTlIgZXZlbnQgZmFpbGVkLiIpfSkpfSksNWUzKTtuLnBvc3QoIlJ1bnRpbWUuZXZhbHVhdGUiLHtleHByZXNzaW9uOiJnbG9iYWwuX19TRU5UUllfR0VUX1NDT1BFU19fKCk7IixzaWxlbnQ6ITAscmV0dXJuQnlWYWx1ZTohMH0sKCh0LGUpPT57dCYmdm4oYEVycm9yIGV4ZWN1dGluZyBzY3JpcHQ6ICcke3QubWVzc2FnZX0nYCksY2xlYXJUaW1lb3V0KHUpO2NvbnN0IHI9ZT8ucmVzdWx0P2UucmVzdWx0LnZhbHVlOnZvaWQgMDtuLnBvc3QoIkRlYnVnZ2VyLnJlc3VtZSIpLG4ucG9zdCgiRGVidWdnZXIuZGlzYWJsZSIpLFRuKGMscikudGhlbihudWxsLCgoKT0+e3ZuKCJTZW5kaW5nIEFOUiBldmVudCBmYWlsZWQuIil9KSl9KSl9Y2F0Y2godCl7dGhyb3cgbi5wb3N0KCJEZWJ1Z2dlci5yZXN1bWUiKSxuLnBvc3QoIkRlYnVnZ2VyLmRpc2FibGUiKSx0fX0pKSxDbj0oKT0+e3RyeXtuLnBvc3QoIkRlYnVnZ2VyLmVuYWJsZSIsKCgpPT57bi5wb3N0KCJEZWJ1Z2dlci5wYXVzZSIpfSkpfWNhdGNoKHQpe319fWNvbnN0e3BvbGw6Um59PWZ1bmN0aW9uKHQsbixlLHIpe2NvbnN0IG89dCgpO2xldCBzPSExLGk9ITA7cmV0dXJuIHNldEludGVydmFsKCgoKT0+e2NvbnN0IHQ9by5nZXRUaW1lTXMoKTshMT09PXMmJnQ+bitlJiYocz0hMCxpJiZyKCkpLHQ8bitlJiYocz0hMSl9KSwyMCkse3BvbGw6KCk9PntvLnJlc2V0KCl9LGVuYWJsZWQ6dD0+e2k9dH19fSgoZnVuY3Rpb24oKXtsZXQgdD1wcm9jZXNzLmhydGltZSgpO3JldHVybntnZXRUaW1lTXM6KCk9Pntjb25zdFtuLGVdPXByb2Nlc3MuaHJ0aW1lKHQpO3JldHVybiBNYXRoLmZsb29yKDFlMypuK2UvMWU2KX0scmVzZXQ6KCk9Pnt0PXByb2Nlc3MuaHJ0aW1lKCl9fX0pLGduLnBvbGxJbnRlcnZhbCxnbi5hbnJUaHJlc2hvbGQsKGZ1bmN0aW9uKCl7dm4oIldhdGNoZG9nIHRpbWVvdXQiKSxDbj8odm4oIlBhdXNpbmcgZGVidWdnZXIgdG8gY2FwdHVyZSBzdGFjayB0cmFjZSIpLENuKCkpOih2bigiQ2FwdHVyaW5nIGV2ZW50IHdpdGhvdXQgYSBzdGFjayB0cmFjZSIpLFRuKCkudGhlbihudWxsLCgoKT0+e3ZuKCJTZW5kaW5nIEFOUiBldmVudCBmYWlsZWQgb24gd2F0Y2hkb2cgdGltZW91dC4iKX0pKSl9KSk7ZT8ub24oIm1lc3NhZ2UiLCh0PT57dC5zZXNzaW9uJiYoeW49TCh0LnNlc3Npb24pKSx0LmRlYnVnSW1hZ2VzJiYoX249dC5kZWJ1Z0ltYWdlcyksUm4oKX0pKTs=';
12
+ const base64WorkerScript = 'LyohIEBzZW50cnkvbm9kZSA5LjE4LjAgKGNiMDdhMzIpIHwgaHR0cHM6Ly9naXRodWIuY29tL2dldHNlbnRyeS9zZW50cnktamF2YXNjcmlwdCAqLwppbXBvcnR7U2Vzc2lvbiBhcyB0fWZyb20ibm9kZTppbnNwZWN0b3IiO2ltcG9ydHt3b3JrZXJEYXRhIGFzIG4scGFyZW50UG9ydCBhcyBlfWZyb20ibm9kZTp3b3JrZXJfdGhyZWFkcyI7aW1wb3J0e3Bvc2l4IGFzIHIsc2VwIGFzIG99ZnJvbSJub2RlOnBhdGgiO2ltcG9ydCphcyBzIGZyb20ibm9kZTpodHRwIjtpbXBvcnQqYXMgaSBmcm9tIm5vZGU6aHR0cHMiO2ltcG9ydHtSZWFkYWJsZSBhcyBjfWZyb20ibm9kZTpzdHJlYW0iO2ltcG9ydHtjcmVhdGVHemlwIGFzIHV9ZnJvbSJub2RlOnpsaWIiO2ltcG9ydCphcyBhIGZyb20ibm9kZTpuZXQiO2ltcG9ydCphcyBmIGZyb20ibm9kZTp0bHMiO2NvbnN0IGg9InVuZGVmaW5lZCI9PXR5cGVvZiBfX1NFTlRSWV9ERUJVR19ffHxfX1NFTlRSWV9ERUJVR19fLHA9IjkuMTguMCIsbD1nbG9iYWxUaGlzO2Z1bmN0aW9uIGQoKXtyZXR1cm4gbShsKSxsfWZ1bmN0aW9uIG0odCl7Y29uc3Qgbj10Ll9fU0VOVFJZX189dC5fX1NFTlRSWV9ffHx7fTtyZXR1cm4gbi52ZXJzaW9uPW4udmVyc2lvbnx8cCxuW3BdPW5bcF18fHt9fWZ1bmN0aW9uIGcodCxuLGU9bCl7Y29uc3Qgcj1lLl9fU0VOVFJZX189ZS5fX1NFTlRSWV9ffHx7fSxvPXJbcF09cltwXXx8e307cmV0dXJuIG9bdF18fChvW3RdPW4oKSl9Y29uc3QgeT1PYmplY3QucHJvdG90eXBlLnRvU3RyaW5nO2Z1bmN0aW9uIGIodCxuKXtyZXR1cm4geS5jYWxsKHQpPT09YFtvYmplY3QgJHtufV1gfWZ1bmN0aW9uIHYodCl7cmV0dXJuIGIodCwiU3RyaW5nIil9ZnVuY3Rpb24gXyh0KXtyZXR1cm4gYih0LCJPYmplY3QiKX1mdW5jdGlvbiB3KHQpe3JldHVybiBCb29sZWFuKHQ/LnRoZW4mJiJmdW5jdGlvbiI9PXR5cGVvZiB0LnRoZW4pfWZ1bmN0aW9uIFModCxuKXt0cnl7cmV0dXJuIHQgaW5zdGFuY2VvZiBufWNhdGNoKHQpe3JldHVybiExfX1jb25zdCAkPWwsRT04MDtmdW5jdGlvbiB4KHQsbil7Y29uc3QgZT10LHI9W107aWYoIWU/LnRhZ05hbWUpcmV0dXJuIiI7aWYoJC5IVE1MRWxlbWVudCYmZSBpbnN0YW5jZW9mIEhUTUxFbGVtZW50JiZlLmRhdGFzZXQpe2lmKGUuZGF0YXNldC5zZW50cnlDb21wb25lbnQpcmV0dXJuIGUuZGF0YXNldC5zZW50cnlDb21wb25lbnQ7aWYoZS5kYXRhc2V0LnNlbnRyeUVsZW1lbnQpcmV0dXJuIGUuZGF0YXNldC5zZW50cnlFbGVtZW50fXIucHVzaChlLnRhZ05hbWUudG9Mb3dlckNhc2UoKSk7Y29uc3Qgbz1uPy5sZW5ndGg/bi5maWx0ZXIoKHQ9PmUuZ2V0QXR0cmlidXRlKHQpKSkubWFwKCh0PT5bdCxlLmdldEF0dHJpYnV0ZSh0KV0pKTpudWxsO2lmKG8/Lmxlbmd0aClvLmZvckVhY2goKHQ9PntyLnB1c2goYFske3RbMF19PSIke3RbMV19Il1gKX0pKTtlbHNle2UuaWQmJnIucHVzaChgIyR7ZS5pZH1gKTtjb25zdCB0PWUuY2xhc3NOYW1lO2lmKHQmJnYodCkpe2NvbnN0IG49dC5zcGxpdCgvXHMrLyk7Zm9yKGNvbnN0IHQgb2YgbilyLnB1c2goYC4ke3R9YCl9fWNvbnN0IHM9WyJhcmlhLWxhYmVsIiwidHlwZSIsIm5hbWUiLCJ0aXRsZSIsImFsdCJdO2Zvcihjb25zdCB0IG9mIHMpe2NvbnN0IG49ZS5nZXRBdHRyaWJ1dGUodCk7biYmci5wdXNoKGBbJHt0fT0iJHtufSJdYCl9cmV0dXJuIHIuam9pbigiIil9Y29uc3QgTj1bImRlYnVnIiwiaW5mbyIsIndhcm4iLCJlcnJvciIsImxvZyIsImFzc2VydCIsInRyYWNlIl0sQz17fTtmdW5jdGlvbiBUKHQpe2lmKCEoImNvbnNvbGUiaW4gbCkpcmV0dXJuIHQoKTtjb25zdCBuPWwuY29uc29sZSxlPXt9LHI9T2JqZWN0LmtleXMoQyk7ci5mb3JFYWNoKCh0PT57Y29uc3Qgcj1DW3RdO2VbdF09blt0XSxuW3RdPXJ9KSk7dHJ5e3JldHVybiB0KCl9ZmluYWxseXtyLmZvckVhY2goKHQ9PntuW3RdPWVbdF19KSl9fWNvbnN0IGs9ZygibG9nZ2VyIiwoZnVuY3Rpb24oKXtsZXQgdD0hMTtjb25zdCBuPXtlbmFibGU6KCk9Pnt0PSEwfSxkaXNhYmxlOigpPT57dD0hMX0saXNFbmFibGVkOigpPT50fTtyZXR1cm4gaD9OLmZvckVhY2goKGU9PntuW2VdPSguLi5uKT0+e3QmJlQoKCgpPT57bC5jb25zb2xlW2VdKGBTZW50cnkgTG9nZ2VyIFske2V9XTpgLC4uLm4pfSkpfX0pKTpOLmZvckVhY2goKHQ9PntuW3RdPSgpPT57fX0pKSxufSkpO2Z1bmN0aW9uIGoodCxuPTApe3JldHVybiJzdHJpbmciIT10eXBlb2YgdHx8MD09PW58fHQubGVuZ3RoPD1uP3Q6YCR7dC5zbGljZSgwLG4pfS4uLmB9ZnVuY3Rpb24gUih0KXtpZihmdW5jdGlvbih0KXtzd2l0Y2goeS5jYWxsKHQpKXtjYXNlIltvYmplY3QgRXJyb3JdIjpjYXNlIltvYmplY3QgRXhjZXB0aW9uXSI6Y2FzZSJbb2JqZWN0IERPTUV4Y2VwdGlvbl0iOmNhc2UiW29iamVjdCBXZWJBc3NlbWJseS5FeGNlcHRpb25dIjpyZXR1cm4hMDtkZWZhdWx0OnJldHVybiBTKHQsRXJyb3IpfX0odCkpcmV0dXJue21lc3NhZ2U6dC5tZXNzYWdlLG5hbWU6dC5uYW1lLHN0YWNrOnQuc3RhY2ssLi4uTyh0KX07aWYobj10LCJ1bmRlZmluZWQiIT10eXBlb2YgRXZlbnQmJlMobixFdmVudCkpe2NvbnN0IG49e3R5cGU6dC50eXBlLHRhcmdldDpJKHQudGFyZ2V0KSxjdXJyZW50VGFyZ2V0OkkodC5jdXJyZW50VGFyZ2V0KSwuLi5PKHQpfTtyZXR1cm4idW5kZWZpbmVkIiE9dHlwZW9mIEN1c3RvbUV2ZW50JiZTKHQsQ3VzdG9tRXZlbnQpJiYobi5kZXRhaWw9dC5kZXRhaWwpLG59cmV0dXJuIHQ7dmFyIG59ZnVuY3Rpb24gSSh0KXt0cnl7cmV0dXJuIG49dCwidW5kZWZpbmVkIiE9dHlwZW9mIEVsZW1lbnQmJlMobixFbGVtZW50KT9mdW5jdGlvbih0LG49e30pe2lmKCF0KXJldHVybiI8dW5rbm93bj4iO3RyeXtsZXQgZT10O2NvbnN0IHI9NSxvPVtdO2xldCBzPTAsaT0wO2NvbnN0IGM9IiA+ICIsdT1jLmxlbmd0aDtsZXQgYTtjb25zdCBmPUFycmF5LmlzQXJyYXkobik/bjpuLmtleUF0dHJzLGg9IUFycmF5LmlzQXJyYXkobikmJm4ubWF4U3RyaW5nTGVuZ3RofHxFO2Zvcig7ZSYmcysrPHImJihhPXgoZSxmKSwhKCJodG1sIj09PWF8fHM+MSYmaStvLmxlbmd0aCp1K2EubGVuZ3RoPj1oKSk7KW8ucHVzaChhKSxpKz1hLmxlbmd0aCxlPWUucGFyZW50Tm9kZTtyZXR1cm4gby5yZXZlcnNlKCkuam9pbihjKX1jYXRjaCh0KXtyZXR1cm4iPHVua25vd24+In19KHQpOk9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbCh0KX1jYXRjaCh0KXtyZXR1cm4iPHVua25vd24+In12YXIgbn1mdW5jdGlvbiBPKHQpe2lmKCJvYmplY3QiPT10eXBlb2YgdCYmbnVsbCE9PXQpe2NvbnN0IG49e307Zm9yKGNvbnN0IGUgaW4gdClPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwodCxlKSYmKG5bZV09dFtlXSk7cmV0dXJuIG59cmV0dXJue319ZnVuY3Rpb24gRCh0PWZ1bmN0aW9uKCl7Y29uc3QgdD1sO3JldHVybiB0LmNyeXB0b3x8dC5tc0NyeXB0b30oKSl7bGV0IG49KCk9PjE2Kk1hdGgucmFuZG9tKCk7dHJ5e2lmKHQ/LnJhbmRvbVVVSUQpcmV0dXJuIHQucmFuZG9tVVVJRCgpLnJlcGxhY2UoLy0vZywiIik7dD8uZ2V0UmFuZG9tVmFsdWVzJiYobj0oKT0+e2NvbnN0IG49bmV3IFVpbnQ4QXJyYXkoMSk7cmV0dXJuIHQuZ2V0UmFuZG9tVmFsdWVzKG4pLG5bMF19KX1jYXRjaCh0KXt9cmV0dXJuKFsxZTddKzFlMys0ZTMrOGUzKzFlMTEpLnJlcGxhY2UoL1swMThdL2csKHQ9Pih0XigxNSZuKCkpPj50LzQpLnRvU3RyaW5nKDE2KSkpfWNvbnN0IEE9MWUzO2Z1bmN0aW9uIFAoKXtyZXR1cm4gRGF0ZS5ub3coKS9BfWNvbnN0IFU9ZnVuY3Rpb24oKXtjb25zdHtwZXJmb3JtYW5jZTp0fT1sO2lmKCF0Py5ub3cpcmV0dXJuIFA7Y29uc3Qgbj1EYXRlLm5vdygpLXQubm93KCksZT1udWxsPT10LnRpbWVPcmlnaW4/bjp0LnRpbWVPcmlnaW47cmV0dXJuKCk9PihlK3Qubm93KCkpL0F9KCk7ZnVuY3Rpb24gTSh0KXtjb25zdCBuPVUoKSxlPXtzaWQ6RCgpLGluaXQ6ITAsdGltZXN0YW1wOm4sc3RhcnRlZDpuLGR1cmF0aW9uOjAsc3RhdHVzOiJvayIsZXJyb3JzOjAsaWdub3JlRHVyYXRpb246ITEsdG9KU09OOigpPT5mdW5jdGlvbih0KXtyZXR1cm57c2lkOmAke3Quc2lkfWAsaW5pdDp0LmluaXQsc3RhcnRlZDpuZXcgRGF0ZSgxZTMqdC5zdGFydGVkKS50b0lTT1N0cmluZygpLHRpbWVzdGFtcDpuZXcgRGF0ZSgxZTMqdC50aW1lc3RhbXApLnRvSVNPU3RyaW5nKCksc3RhdHVzOnQuc3RhdHVzLGVycm9yczp0LmVycm9ycyxkaWQ6Im51bWJlciI9PXR5cGVvZiB0LmRpZHx8InN0cmluZyI9PXR5cGVvZiB0LmRpZD9gJHt0LmRpZH1gOnZvaWQgMCxkdXJhdGlvbjp0LmR1cmF0aW9uLGFibm9ybWFsX21lY2hhbmlzbTp0LmFibm9ybWFsX21lY2hhbmlzbSxhdHRyczp7cmVsZWFzZTp0LnJlbGVhc2UsZW52aXJvbm1lbnQ6dC5lbnZpcm9ubWVudCxpcF9hZGRyZXNzOnQuaXBBZGRyZXNzLHVzZXJfYWdlbnQ6dC51c2VyQWdlbnR9fX0oZSl9O3JldHVybiB0JiZMKGUsdCksZX1mdW5jdGlvbiBMKHQsbj17fSl7aWYobi51c2VyJiYoIXQuaXBBZGRyZXNzJiZuLnVzZXIuaXBfYWRkcmVzcyYmKHQuaXBBZGRyZXNzPW4udXNlci5pcF9hZGRyZXNzKSx0LmRpZHx8bi5kaWR8fCh0LmRpZD1uLnVzZXIuaWR8fG4udXNlci5lbWFpbHx8bi51c2VyLnVzZXJuYW1lKSksdC50aW1lc3RhbXA9bi50aW1lc3RhbXB8fFUoKSxuLmFibm9ybWFsX21lY2hhbmlzbSYmKHQuYWJub3JtYWxfbWVjaGFuaXNtPW4uYWJub3JtYWxfbWVjaGFuaXNtKSxuLmlnbm9yZUR1cmF0aW9uJiYodC5pZ25vcmVEdXJhdGlvbj1uLmlnbm9yZUR1cmF0aW9uKSxuLnNpZCYmKHQuc2lkPTMyPT09bi5zaWQubGVuZ3RoP24uc2lkOkQoKSksdm9pZCAwIT09bi5pbml0JiYodC5pbml0PW4uaW5pdCksIXQuZGlkJiZuLmRpZCYmKHQuZGlkPWAke24uZGlkfWApLCJudW1iZXIiPT10eXBlb2Ygbi5zdGFydGVkJiYodC5zdGFydGVkPW4uc3RhcnRlZCksdC5pZ25vcmVEdXJhdGlvbil0LmR1cmF0aW9uPXZvaWQgMDtlbHNlIGlmKCJudW1iZXIiPT10eXBlb2Ygbi5kdXJhdGlvbil0LmR1cmF0aW9uPW4uZHVyYXRpb247ZWxzZXtjb25zdCBuPXQudGltZXN0YW1wLXQuc3RhcnRlZDt0LmR1cmF0aW9uPW4+PTA/bjowfW4ucmVsZWFzZSYmKHQucmVsZWFzZT1uLnJlbGVhc2UpLG4uZW52aXJvbm1lbnQmJih0LmVudmlyb25tZW50PW4uZW52aXJvbm1lbnQpLCF0LmlwQWRkcmVzcyYmbi5pcEFkZHJlc3MmJih0LmlwQWRkcmVzcz1uLmlwQWRkcmVzcyksIXQudXNlckFnZW50JiZuLnVzZXJBZ2VudCYmKHQudXNlckFnZW50PW4udXNlckFnZW50KSwibnVtYmVyIj09dHlwZW9mIG4uZXJyb3JzJiYodC5lcnJvcnM9bi5lcnJvcnMpLG4uc3RhdHVzJiYodC5zdGF0dXM9bi5zdGF0dXMpfWZ1bmN0aW9uIEIodCxuLGU9Mil7aWYoIW58fCJvYmplY3QiIT10eXBlb2Ygbnx8ZTw9MClyZXR1cm4gbjtpZih0JiYwPT09T2JqZWN0LmtleXMobikubGVuZ3RoKXJldHVybiB0O2NvbnN0IHI9ey4uLnR9O2Zvcihjb25zdCB0IGluIG4pT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKG4sdCkmJihyW3RdPUIoclt0XSxuW3RdLGUtMSkpO3JldHVybiByfWNvbnN0IEc9Il9zZW50cnlTcGFuIjtmdW5jdGlvbiBKKHQsbil7bj9mdW5jdGlvbih0LG4sZSl7dHJ5e09iamVjdC5kZWZpbmVQcm9wZXJ0eSh0LG4se3ZhbHVlOmUsd3JpdGFibGU6ITAsY29uZmlndXJhYmxlOiEwfSl9Y2F0Y2goZSl7aCYmay5sb2coYEZhaWxlZCB0byBhZGQgbm9uLWVudW1lcmFibGUgcHJvcGVydHkgIiR7bn0iIHRvIG9iamVjdGAsdCl9fSh0LEcsbik6ZGVsZXRlIHRbR119ZnVuY3Rpb24geih0KXtyZXR1cm4gdFtHXX1mdW5jdGlvbiBIKCl7cmV0dXJuIEQoKX1mdW5jdGlvbiBGKCl7cmV0dXJuIEQoKS5zdWJzdHJpbmcoMTYpfWNsYXNzIFd7Y29uc3RydWN0b3IoKXt0aGlzLnQ9ITEsdGhpcy5vPVtdLHRoaXMuaT1bXSx0aGlzLnU9W10sdGhpcy5oPVtdLHRoaXMucD17fSx0aGlzLmw9e30sdGhpcy5tPXt9LHRoaXMudj17fSx0aGlzLl89e30sdGhpcy5TPXt0cmFjZUlkOkgoKSxzYW1wbGVSYW5kOk1hdGgucmFuZG9tKCl9fWNsb25lKCl7Y29uc3QgdD1uZXcgVztyZXR1cm4gdC51PVsuLi50aGlzLnVdLHQubD17Li4udGhpcy5sfSx0Lm09ey4uLnRoaXMubX0sdC52PXsuLi50aGlzLnZ9LHRoaXMudi5mbGFncyYmKHQudi5mbGFncz17dmFsdWVzOlsuLi50aGlzLnYuZmxhZ3MudmFsdWVzXX0pLHQucD10aGlzLnAsdC5OPXRoaXMuTix0LkM9dGhpcy5DLHQuVD10aGlzLlQsdC5rPXRoaXMuayx0Lmk9Wy4uLnRoaXMuaV0sdC5oPVsuLi50aGlzLmhdLHQuXz17Li4udGhpcy5ffSx0LlM9ey4uLnRoaXMuU30sdC5qPXRoaXMuaix0LlI9dGhpcy5SLEoodCx6KHRoaXMpKSx0fXNldENsaWVudCh0KXt0aGlzLmo9dH1zZXRMYXN0RXZlbnRJZCh0KXt0aGlzLlI9dH1nZXRDbGllbnQoKXtyZXR1cm4gdGhpcy5qfWxhc3RFdmVudElkKCl7cmV0dXJuIHRoaXMuUn1hZGRTY29wZUxpc3RlbmVyKHQpe3RoaXMuby5wdXNoKHQpfWFkZEV2ZW50UHJvY2Vzc29yKHQpe3JldHVybiB0aGlzLmkucHVzaCh0KSx0aGlzfXNldFVzZXIodCl7cmV0dXJuIHRoaXMucD10fHx7ZW1haWw6dm9pZCAwLGlkOnZvaWQgMCxpcF9hZGRyZXNzOnZvaWQgMCx1c2VybmFtZTp2b2lkIDB9LHRoaXMuQyYmTCh0aGlzLkMse3VzZXI6dH0pLHRoaXMuSSgpLHRoaXN9Z2V0VXNlcigpe3JldHVybiB0aGlzLnB9c2V0VGFncyh0KXtyZXR1cm4gdGhpcy5sPXsuLi50aGlzLmwsLi4udH0sdGhpcy5JKCksdGhpc31zZXRUYWcodCxuKXtyZXR1cm4gdGhpcy5sPXsuLi50aGlzLmwsW3RdOm59LHRoaXMuSSgpLHRoaXN9c2V0RXh0cmFzKHQpe3JldHVybiB0aGlzLm09ey4uLnRoaXMubSwuLi50fSx0aGlzLkkoKSx0aGlzfXNldEV4dHJhKHQsbil7cmV0dXJuIHRoaXMubT17Li4udGhpcy5tLFt0XTpufSx0aGlzLkkoKSx0aGlzfXNldEZpbmdlcnByaW50KHQpe3JldHVybiB0aGlzLms9dCx0aGlzLkkoKSx0aGlzfXNldExldmVsKHQpe3JldHVybiB0aGlzLk49dCx0aGlzLkkoKSx0aGlzfXNldFRyYW5zYWN0aW9uTmFtZSh0KXtyZXR1cm4gdGhpcy5UPXQsdGhpcy5JKCksdGhpc31zZXRDb250ZXh0KHQsbil7cmV0dXJuIG51bGw9PT1uP2RlbGV0ZSB0aGlzLnZbdF06dGhpcy52W3RdPW4sdGhpcy5JKCksdGhpc31zZXRTZXNzaW9uKHQpe3JldHVybiB0P3RoaXMuQz10OmRlbGV0ZSB0aGlzLkMsdGhpcy5JKCksdGhpc31nZXRTZXNzaW9uKCl7cmV0dXJuIHRoaXMuQ311cGRhdGUodCl7aWYoIXQpcmV0dXJuIHRoaXM7Y29uc3Qgbj0iZnVuY3Rpb24iPT10eXBlb2YgdD90KHRoaXMpOnQsZT1uIGluc3RhbmNlb2YgVz9uLmdldFNjb3BlRGF0YSgpOl8obik/dDp2b2lkIDAse3RhZ3M6cixleHRyYTpvLHVzZXI6cyxjb250ZXh0czppLGxldmVsOmMsZmluZ2VycHJpbnQ6dT1bXSxwcm9wYWdhdGlvbkNvbnRleHQ6YX09ZXx8e307cmV0dXJuIHRoaXMubD17Li4udGhpcy5sLC4uLnJ9LHRoaXMubT17Li4udGhpcy5tLC4uLm99LHRoaXMudj17Li4udGhpcy52LC4uLml9LHMmJk9iamVjdC5rZXlzKHMpLmxlbmd0aCYmKHRoaXMucD1zKSxjJiYodGhpcy5OPWMpLHUubGVuZ3RoJiYodGhpcy5rPXUpLGEmJih0aGlzLlM9YSksdGhpc31jbGVhcigpe3JldHVybiB0aGlzLnU9W10sdGhpcy5sPXt9LHRoaXMubT17fSx0aGlzLnA9e30sdGhpcy52PXt9LHRoaXMuTj12b2lkIDAsdGhpcy5UPXZvaWQgMCx0aGlzLms9dm9pZCAwLHRoaXMuQz12b2lkIDAsSih0aGlzLHZvaWQgMCksdGhpcy5oPVtdLHRoaXMuc2V0UHJvcGFnYXRpb25Db250ZXh0KHt0cmFjZUlkOkgoKSxzYW1wbGVSYW5kOk1hdGgucmFuZG9tKCl9KSx0aGlzLkkoKSx0aGlzfWFkZEJyZWFkY3J1bWIodCxuKXtjb25zdCBlPSJudW1iZXIiPT10eXBlb2Ygbj9uOjEwMDtpZihlPD0wKXJldHVybiB0aGlzO2NvbnN0IHI9e3RpbWVzdGFtcDpQKCksLi4udCxtZXNzYWdlOnQubWVzc2FnZT9qKHQubWVzc2FnZSwyMDQ4KTp0Lm1lc3NhZ2V9O3JldHVybiB0aGlzLnUucHVzaChyKSx0aGlzLnUubGVuZ3RoPmUmJih0aGlzLnU9dGhpcy51LnNsaWNlKC1lKSx0aGlzLmo/LnJlY29yZERyb3BwZWRFdmVudCgiYnVmZmVyX292ZXJmbG93IiwibG9nX2l0ZW0iKSksdGhpcy5JKCksdGhpc31nZXRMYXN0QnJlYWRjcnVtYigpe3JldHVybiB0aGlzLnVbdGhpcy51Lmxlbmd0aC0xXX1jbGVhckJyZWFkY3J1bWJzKCl7cmV0dXJuIHRoaXMudT1bXSx0aGlzLkkoKSx0aGlzfWFkZEF0dGFjaG1lbnQodCl7cmV0dXJuIHRoaXMuaC5wdXNoKHQpLHRoaXN9Y2xlYXJBdHRhY2htZW50cygpe3JldHVybiB0aGlzLmg9W10sdGhpc31nZXRTY29wZURhdGEoKXtyZXR1cm57YnJlYWRjcnVtYnM6dGhpcy51LGF0dGFjaG1lbnRzOnRoaXMuaCxjb250ZXh0czp0aGlzLnYsdGFnczp0aGlzLmwsZXh0cmE6dGhpcy5tLHVzZXI6dGhpcy5wLGxldmVsOnRoaXMuTixmaW5nZXJwcmludDp0aGlzLmt8fFtdLGV2ZW50UHJvY2Vzc29yczp0aGlzLmkscHJvcGFnYXRpb25Db250ZXh0OnRoaXMuUyxzZGtQcm9jZXNzaW5nTWV0YWRhdGE6dGhpcy5fLHRyYW5zYWN0aW9uTmFtZTp0aGlzLlQsc3Bhbjp6KHRoaXMpfX1zZXRTREtQcm9jZXNzaW5nTWV0YWRhdGEodCl7cmV0dXJuIHRoaXMuXz1CKHRoaXMuXyx0LDIpLHRoaXN9c2V0UHJvcGFnYXRpb25Db250ZXh0KHQpe3JldHVybiB0aGlzLlM9dCx0aGlzfWdldFByb3BhZ2F0aW9uQ29udGV4dCgpe3JldHVybiB0aGlzLlN9Y2FwdHVyZUV4Y2VwdGlvbih0LG4pe2NvbnN0IGU9bj8uZXZlbnRfaWR8fEQoKTtpZighdGhpcy5qKXJldHVybiBrLndhcm4oIk5vIGNsaWVudCBjb25maWd1cmVkIG9uIHNjb3BlIC0gd2lsbCBub3QgY2FwdHVyZSBleGNlcHRpb24hIiksZTtjb25zdCByPW5ldyBFcnJvcigiU2VudHJ5IHN5bnRoZXRpY0V4Y2VwdGlvbiIpO3JldHVybiB0aGlzLmouY2FwdHVyZUV4Y2VwdGlvbih0LHtvcmlnaW5hbEV4Y2VwdGlvbjp0LHN5bnRoZXRpY0V4Y2VwdGlvbjpyLC4uLm4sZXZlbnRfaWQ6ZX0sdGhpcyksZX1jYXB0dXJlTWVzc2FnZSh0LG4sZSl7Y29uc3Qgcj1lPy5ldmVudF9pZHx8RCgpO2lmKCF0aGlzLmopcmV0dXJuIGsud2FybigiTm8gY2xpZW50IGNvbmZpZ3VyZWQgb24gc2NvcGUgLSB3aWxsIG5vdCBjYXB0dXJlIG1lc3NhZ2UhIikscjtjb25zdCBvPW5ldyBFcnJvcih0KTtyZXR1cm4gdGhpcy5qLmNhcHR1cmVNZXNzYWdlKHQsbix7b3JpZ2luYWxFeGNlcHRpb246dCxzeW50aGV0aWNFeGNlcHRpb246bywuLi5lLGV2ZW50X2lkOnJ9LHRoaXMpLHJ9Y2FwdHVyZUV2ZW50KHQsbil7Y29uc3QgZT1uPy5ldmVudF9pZHx8RCgpO3JldHVybiB0aGlzLmo/KHRoaXMuai5jYXB0dXJlRXZlbnQodCx7Li4ubixldmVudF9pZDplfSx0aGlzKSxlKTooay53YXJuKCJObyBjbGllbnQgY29uZmlndXJlZCBvbiBzY29wZSAtIHdpbGwgbm90IGNhcHR1cmUgZXZlbnQhIiksZSl9SSgpe3RoaXMudHx8KHRoaXMudD0hMCx0aGlzLm8uZm9yRWFjaCgodD0+e3QodGhpcyl9KSksdGhpcy50PSExKX19Y2xhc3MgWXtjb25zdHJ1Y3Rvcih0LG4pe2xldCBlLHI7ZT10fHxuZXcgVyxyPW58fG5ldyBXLHRoaXMuTz1be3Njb3BlOmV9XSx0aGlzLkQ9cn13aXRoU2NvcGUodCl7Y29uc3Qgbj10aGlzLkEoKTtsZXQgZTt0cnl7ZT10KG4pfWNhdGNoKHQpe3Rocm93IHRoaXMuUCgpLHR9cmV0dXJuIHcoZSk/ZS50aGVuKCh0PT4odGhpcy5QKCksdCkpLCh0PT57dGhyb3cgdGhpcy5QKCksdH0pKToodGhpcy5QKCksZSl9Z2V0Q2xpZW50KCl7cmV0dXJuIHRoaXMuZ2V0U3RhY2tUb3AoKS5jbGllbnR9Z2V0U2NvcGUoKXtyZXR1cm4gdGhpcy5nZXRTdGFja1RvcCgpLnNjb3BlfWdldElzb2xhdGlvblNjb3BlKCl7cmV0dXJuIHRoaXMuRH1nZXRTdGFja1RvcCgpe3JldHVybiB0aGlzLk9bdGhpcy5PLmxlbmd0aC0xXX1BKCl7Y29uc3QgdD10aGlzLmdldFNjb3BlKCkuY2xvbmUoKTtyZXR1cm4gdGhpcy5PLnB1c2goe2NsaWVudDp0aGlzLmdldENsaWVudCgpLHNjb3BlOnR9KSx0fVAoKXtyZXR1cm4hKHRoaXMuTy5sZW5ndGg8PTEpJiYhIXRoaXMuTy5wb3AoKX19ZnVuY3Rpb24gSygpe2NvbnN0IHQ9bShkKCkpO3JldHVybiB0LnN0YWNrPXQuc3RhY2t8fG5ldyBZKGcoImRlZmF1bHRDdXJyZW50U2NvcGUiLCgoKT0+bmV3IFcpKSxnKCJkZWZhdWx0SXNvbGF0aW9uU2NvcGUiLCgoKT0+bmV3IFcpKSl9ZnVuY3Rpb24gVih0KXtyZXR1cm4gSygpLndpdGhTY29wZSh0KX1mdW5jdGlvbiBaKHQsbil7Y29uc3QgZT1LKCk7cmV0dXJuIGUud2l0aFNjb3BlKCgoKT0+KGUuZ2V0U3RhY2tUb3AoKS5zY29wZT10LG4odCkpKSl9ZnVuY3Rpb24gcSh0KXtyZXR1cm4gSygpLndpdGhTY29wZSgoKCk9PnQoSygpLmdldElzb2xhdGlvblNjb3BlKCkpKSl9ZnVuY3Rpb24gUSh0KXtjb25zdCBuPW0odCk7cmV0dXJuIG4uYWNzP24uYWNzOnt3aXRoSXNvbGF0aW9uU2NvcGU6cSx3aXRoU2NvcGU6Vix3aXRoU2V0U2NvcGU6Wix3aXRoU2V0SXNvbGF0aW9uU2NvcGU6KHQsbik9PnEobiksZ2V0Q3VycmVudFNjb3BlOigpPT5LKCkuZ2V0U2NvcGUoKSxnZXRJc29sYXRpb25TY29wZTooKT0+SygpLmdldElzb2xhdGlvblNjb3BlKCl9fWZ1bmN0aW9uIFgoKXtyZXR1cm4gUShkKCkpLmdldEN1cnJlbnRTY29wZSgpLmdldENsaWVudCgpfWNvbnN0IHR0PSJzZW50cnkuc291cmNlIixudD0ic2VudHJ5LnNhbXBsZV9yYXRlIixldD0ic2VudHJ5LnByZXZpb3VzX3RyYWNlX3NhbXBsZV9yYXRlIixydD0ic2VudHJ5Lm9wIixvdD0ic2VudHJ5Lm9yaWdpbiIsc3Q9MCxpdD0xLGN0PSJfc2VudHJ5U2NvcGUiLHV0PSJfc2VudHJ5SXNvbGF0aW9uU2NvcGUiO2Z1bmN0aW9uIGF0KHQpe3JldHVybntzY29wZTp0W2N0XSxpc29sYXRpb25TY29wZTp0W3V0XX19Y29uc3QgZnQ9InNlbnRyeS0iLGh0PS9ec2VudHJ5LS87ZnVuY3Rpb24gcHQodCl7Y29uc3Qgbj1mdW5jdGlvbih0KXtpZighdHx8IXYodCkmJiFBcnJheS5pc0FycmF5KHQpKXJldHVybjtpZihBcnJheS5pc0FycmF5KHQpKXJldHVybiB0LnJlZHVjZSgoKHQsbik9Pntjb25zdCBlPWx0KG4pO3JldHVybiBPYmplY3QuZW50cmllcyhlKS5mb3JFYWNoKCgoW24sZV0pPT57dFtuXT1lfSkpLHR9KSx7fSk7cmV0dXJuIGx0KHQpfSh0KTtpZighbilyZXR1cm47Y29uc3QgZT1PYmplY3QuZW50cmllcyhuKS5yZWR1Y2UoKCh0LFtuLGVdKT0+e2lmKG4ubWF0Y2goaHQpKXt0W24uc2xpY2UoZnQubGVuZ3RoKV09ZX1yZXR1cm4gdH0pLHt9KTtyZXR1cm4gT2JqZWN0LmtleXMoZSkubGVuZ3RoPjA/ZTp2b2lkIDB9ZnVuY3Rpb24gbHQodCl7cmV0dXJuIHQuc3BsaXQoIiwiKS5tYXAoKHQ9PnQuc3BsaXQoIj0iKS5tYXAoKHQ9Pnt0cnl7cmV0dXJuIGRlY29kZVVSSUNvbXBvbmVudCh0LnRyaW0oKSl9Y2F0Y2h7cmV0dXJufX0pKSkpLnJlZHVjZSgoKHQsW24sZV0pPT4obiYmZSYmKHRbbl09ZSksdCkpLHt9KX1jb25zdCBkdD0xO2Z1bmN0aW9uIG10KHQpe2NvbnN0e3NwYW5JZDpuLHRyYWNlSWQ6ZSxpc1JlbW90ZTpyfT10LnNwYW5Db250ZXh0KCksbz1yP246dnQodCkucGFyZW50X3NwYW5faWQscz1hdCh0KS5zY29wZTtyZXR1cm57cGFyZW50X3NwYW5faWQ6byxzcGFuX2lkOnI/cz8uZ2V0UHJvcGFnYXRpb25Db250ZXh0KCkucHJvcGFnYXRpb25TcGFuSWR8fEYoKTpuLHRyYWNlX2lkOmV9fWZ1bmN0aW9uIGd0KHQpe3JldHVybiB0JiZ0Lmxlbmd0aD4wP3QubWFwKCgoe2NvbnRleHQ6e3NwYW5JZDp0LHRyYWNlSWQ6bix0cmFjZUZsYWdzOmUsLi4ucn0sYXR0cmlidXRlczpvfSk9Pih7c3Bhbl9pZDp0LHRyYWNlX2lkOm4sc2FtcGxlZDplPT09ZHQsYXR0cmlidXRlczpvLC4uLnJ9KSkpOnZvaWQgMH1mdW5jdGlvbiB5dCh0KXtyZXR1cm4ibnVtYmVyIj09dHlwZW9mIHQ/YnQodCk6QXJyYXkuaXNBcnJheSh0KT90WzBdK3RbMV0vMWU5OnQgaW5zdGFuY2VvZiBEYXRlP2J0KHQuZ2V0VGltZSgpKTpVKCl9ZnVuY3Rpb24gYnQodCl7cmV0dXJuIHQ+OTk5OTk5OTk5OT90LzFlMzp0fWZ1bmN0aW9uIHZ0KHQpe2lmKGZ1bmN0aW9uKHQpe3JldHVybiJmdW5jdGlvbiI9PXR5cGVvZiB0LmdldFNwYW5KU09OfSh0KSlyZXR1cm4gdC5nZXRTcGFuSlNPTigpO2NvbnN0e3NwYW5JZDpuLHRyYWNlSWQ6ZX09dC5zcGFuQ29udGV4dCgpO2lmKGZ1bmN0aW9uKHQpe2NvbnN0IG49dDtyZXR1cm4hIShuLmF0dHJpYnV0ZXMmJm4uc3RhcnRUaW1lJiZuLm5hbWUmJm4uZW5kVGltZSYmbi5zdGF0dXMpfSh0KSl7Y29uc3R7YXR0cmlidXRlczpyLHN0YXJ0VGltZTpvLG5hbWU6cyxlbmRUaW1lOmksc3RhdHVzOmMsbGlua3M6dX09dDtyZXR1cm57c3Bhbl9pZDpuLHRyYWNlX2lkOmUsZGF0YTpyLGRlc2NyaXB0aW9uOnMscGFyZW50X3NwYW5faWQ6InBhcmVudFNwYW5JZCJpbiB0P3QucGFyZW50U3BhbklkOiJwYXJlbnRTcGFuQ29udGV4dCJpbiB0P3QucGFyZW50U3BhbkNvbnRleHQ/LnNwYW5JZDp2b2lkIDAsc3RhcnRfdGltZXN0YW1wOnl0KG8pLHRpbWVzdGFtcDp5dChpKXx8dm9pZCAwLHN0YXR1czpfdChjKSxvcDpyW3J0XSxvcmlnaW46cltvdF0sbGlua3M6Z3QodSl9fXJldHVybntzcGFuX2lkOm4sdHJhY2VfaWQ6ZSxzdGFydF90aW1lc3RhbXA6MCxkYXRhOnt9fX1mdW5jdGlvbiBfdCh0KXtpZih0JiZ0LmNvZGUhPT1zdClyZXR1cm4gdC5jb2RlPT09aXQ/Im9rIjp0Lm1lc3NhZ2V8fCJ1bmtub3duX2Vycm9yIn1jb25zdCB3dD0iX3NlbnRyeVJvb3RTcGFuIjtmdW5jdGlvbiBTdCh0KXtyZXR1cm4gdFt3dF18fHR9Y29uc3QgJHQ9NTAsRXQ9Ij8iLHh0PS9jYXB0dXJlTWVzc2FnZXxjYXB0dXJlRXhjZXB0aW9uLztmdW5jdGlvbiBOdCh0KXtyZXR1cm4gdFt0Lmxlbmd0aC0xXXx8e319Y29uc3QgQ3Q9Ijxhbm9ueW1vdXM+Ijtjb25zdCBUdD0icHJvZHVjdGlvbiIsa3Q9Il9mcm96ZW5Ec2MiO2Z1bmN0aW9uIGp0KHQpe2NvbnN0IG49WCgpO2lmKCFuKXJldHVybnt9O2NvbnN0IGU9U3QodCkscj12dChlKSxvPXIuZGF0YSxzPWUuc3BhbkNvbnRleHQoKS50cmFjZVN0YXRlLGk9cz8uZ2V0KCJzZW50cnkuc2FtcGxlX3JhdGUiKT8/b1tudF0/P29bZXRdO2Z1bmN0aW9uIGModCl7cmV0dXJuIm51bWJlciIhPXR5cGVvZiBpJiYic3RyaW5nIiE9dHlwZW9mIGl8fCh0LnNhbXBsZV9yYXRlPWAke2l9YCksdH1jb25zdCB1PWVba3RdO2lmKHUpcmV0dXJuIGModSk7Y29uc3QgYT1zPy5nZXQoInNlbnRyeS5kc2MiKSxmPWEmJnB0KGEpO2lmKGYpcmV0dXJuIGMoZik7Y29uc3QgaD1mdW5jdGlvbih0LG4pe2NvbnN0IGU9bi5nZXRPcHRpb25zKCkse3B1YmxpY0tleTpyfT1uLmdldERzbigpfHx7fSxvPXtlbnZpcm9ubWVudDplLmVudmlyb25tZW50fHxUdCxyZWxlYXNlOmUucmVsZWFzZSxwdWJsaWNfa2V5OnIsdHJhY2VfaWQ6dH07cmV0dXJuIG4uZW1pdCgiY3JlYXRlRHNjIixvKSxvfSh0LnNwYW5Db250ZXh0KCkudHJhY2VJZCxuKSxwPW9bdHRdLGw9ci5kZXNjcmlwdGlvbjtyZXR1cm4idXJsIiE9PXAmJmwmJihoLnRyYW5zYWN0aW9uPWwpLGZ1bmN0aW9uKHQpe2lmKCJib29sZWFuIj09dHlwZW9mIF9fU0VOVFJZX1RSQUNJTkdfXyYmIV9fU0VOVFJZX1RSQUNJTkdfXylyZXR1cm4hMTtjb25zdCBuPXR8fFgoKT8uZ2V0T3B0aW9ucygpO3JldHVybiEoIW58fG51bGw9PW4udHJhY2VzU2FtcGxlUmF0ZSYmIW4udHJhY2VzU2FtcGxlcil9KCkmJihoLnNhbXBsZWQ9U3RyaW5nKGZ1bmN0aW9uKHQpe2NvbnN0e3RyYWNlRmxhZ3M6bn09dC5zcGFuQ29udGV4dCgpO3JldHVybiBuPT09ZHR9KGUpKSxoLnNhbXBsZV9yYW5kPXM/LmdldCgic2VudHJ5LnNhbXBsZV9yYW5kIik/P2F0KGUpLnNjb3BlPy5nZXRQcm9wYWdhdGlvbkNvbnRleHQoKS5zYW1wbGVSYW5kLnRvU3RyaW5nKCkpLGMoaCksbi5lbWl0KCJjcmVhdGVEc2MiLGgsZSksaH1mdW5jdGlvbiBSdCh0LG49ITEpe2NvbnN0e2hvc3Q6ZSxwYXRoOnIscGFzczpvLHBvcnQ6cyxwcm9qZWN0SWQ6aSxwcm90b2NvbDpjLHB1YmxpY0tleTp1fT10O3JldHVybmAke2N9Oi8vJHt1fSR7biYmbz9gOiR7b31gOiIifUAke2V9JHtzP2A6JHtzfWA6IiJ9LyR7cj9gJHtyfS9gOnJ9JHtpfWB9ZnVuY3Rpb24gSXQodCxuPTEwMCxlPTEvMCl7dHJ5e3JldHVybiBPdCgiIix0LG4sZSl9Y2F0Y2godCl7cmV0dXJue0VSUk9SOmAqKm5vbi1zZXJpYWxpemFibGUqKiAoJHt0fSlgfX19ZnVuY3Rpb24gT3QodCxuLGU9MS8wLHI9MS8wLG89ZnVuY3Rpb24oKXtjb25zdCB0PW5ldyBXZWFrU2V0O2Z1bmN0aW9uIG4obil7cmV0dXJuISF0LmhhcyhuKXx8KHQuYWRkKG4pLCExKX1mdW5jdGlvbiBlKG4pe3QuZGVsZXRlKG4pfXJldHVybltuLGVdfSgpKXtjb25zdFtzLGldPW87aWYobnVsbD09bnx8WyJib29sZWFuIiwic3RyaW5nIl0uaW5jbHVkZXModHlwZW9mIG4pfHwibnVtYmVyIj09dHlwZW9mIG4mJk51bWJlci5pc0Zpbml0ZShuKSlyZXR1cm4gbjtjb25zdCBjPWZ1bmN0aW9uKHQsbil7dHJ5e2lmKCJkb21haW4iPT09dCYmbiYmIm9iamVjdCI9PXR5cGVvZiBuJiZuLlUpcmV0dXJuIltEb21haW5dIjtpZigiZG9tYWluRW1pdHRlciI9PT10KXJldHVybiJbRG9tYWluRW1pdHRlcl0iO2lmKCJ1bmRlZmluZWQiIT10eXBlb2YgZ2xvYmFsJiZuPT09Z2xvYmFsKXJldHVybiJbR2xvYmFsXSI7aWYoInVuZGVmaW5lZCIhPXR5cGVvZiB3aW5kb3cmJm49PT13aW5kb3cpcmV0dXJuIltXaW5kb3ddIjtpZigidW5kZWZpbmVkIiE9dHlwZW9mIGRvY3VtZW50JiZuPT09ZG9jdW1lbnQpcmV0dXJuIltEb2N1bWVudF0iO2lmKCJvYmplY3QiPT10eXBlb2YoZT1uKSYmbnVsbCE9PWUmJihlLl9faXNWdWV8fGUuTSkpcmV0dXJuIltWdWVWaWV3TW9kZWxdIjtpZihmdW5jdGlvbih0KXtyZXR1cm4gXyh0KSYmIm5hdGl2ZUV2ZW50ImluIHQmJiJwcmV2ZW50RGVmYXVsdCJpbiB0JiYic3RvcFByb3BhZ2F0aW9uImluIHR9KG4pKXJldHVybiJbU3ludGhldGljRXZlbnRdIjtpZigibnVtYmVyIj09dHlwZW9mIG4mJiFOdW1iZXIuaXNGaW5pdGUobikpcmV0dXJuYFske259XWA7aWYoImZ1bmN0aW9uIj09dHlwZW9mIG4pcmV0dXJuYFtGdW5jdGlvbjogJHtmdW5jdGlvbih0KXt0cnl7cmV0dXJuIHQmJiJmdW5jdGlvbiI9PXR5cGVvZiB0JiZ0Lm5hbWV8fEN0fWNhdGNoKHQpe3JldHVybiBDdH19KG4pfV1gO2lmKCJzeW1ib2wiPT10eXBlb2YgbilyZXR1cm5gWyR7U3RyaW5nKG4pfV1gO2lmKCJiaWdpbnQiPT10eXBlb2YgbilyZXR1cm5gW0JpZ0ludDogJHtTdHJpbmcobil9XWA7Y29uc3Qgcj1mdW5jdGlvbih0KXtjb25zdCBuPU9iamVjdC5nZXRQcm90b3R5cGVPZih0KTtyZXR1cm4gbj8uY29uc3RydWN0b3I/bi5jb25zdHJ1Y3Rvci5uYW1lOiJudWxsIHByb3RvdHlwZSJ9KG4pO3JldHVybi9eSFRNTChcdyopRWxlbWVudCQvLnRlc3Qocik/YFtIVE1MRWxlbWVudDogJHtyfV1gOmBbb2JqZWN0ICR7cn1dYH1jYXRjaCh0KXtyZXR1cm5gKipub24tc2VyaWFsaXphYmxlKiogKCR7dH0pYH12YXIgZX0odCxuKTtpZighYy5zdGFydHNXaXRoKCJbb2JqZWN0ICIpKXJldHVybiBjO2lmKG4uX19zZW50cnlfc2tpcF9ub3JtYWxpemF0aW9uX18pcmV0dXJuIG47Y29uc3QgdT0ibnVtYmVyIj09dHlwZW9mIG4uX19zZW50cnlfb3ZlcnJpZGVfbm9ybWFsaXphdGlvbl9kZXB0aF9fP24uX19zZW50cnlfb3ZlcnJpZGVfbm9ybWFsaXphdGlvbl9kZXB0aF9fOmU7aWYoMD09PXUpcmV0dXJuIGMucmVwbGFjZSgib2JqZWN0ICIsIiIpO2lmKHMobikpcmV0dXJuIltDaXJjdWxhciB+XSI7Y29uc3QgYT1uO2lmKGEmJiJmdW5jdGlvbiI9PXR5cGVvZiBhLnRvSlNPTil0cnl7cmV0dXJuIE90KCIiLGEudG9KU09OKCksdS0xLHIsbyl9Y2F0Y2godCl7fWNvbnN0IGY9QXJyYXkuaXNBcnJheShuKT9bXTp7fTtsZXQgaD0wO2NvbnN0IHA9UihuKTtmb3IoY29uc3QgdCBpbiBwKXtpZighT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKHAsdCkpY29udGludWU7aWYoaD49cil7Zlt0XT0iW01heFByb3BlcnRpZXMgfl0iO2JyZWFrfWNvbnN0IG49cFt0XTtmW3RdPU90KHQsbix1LTEscixvKSxoKyt9cmV0dXJuIGkobiksZn1mdW5jdGlvbiBEdCh0LG4pe2NvbnN0IGU9bi5yZXBsYWNlKC9cXC9nLCIvIikucmVwbGFjZSgvW3xcXHt9KClbXF1eJCsqPy5dL2csIlxcJCYiKTtsZXQgcj10O3RyeXtyPWRlY29kZVVSSSh0KX1jYXRjaCh0KXt9cmV0dXJuIHIucmVwbGFjZSgvXFwvZywiLyIpLnJlcGxhY2UoL3dlYnBhY2s6XC8/L2csIiIpLnJlcGxhY2UobmV3IFJlZ0V4cChgKGZpbGU6Ly8pPy8qJHtlfS8qYCwiaWciKSwiYXBwOi8vLyIpfWZ1bmN0aW9uIEF0KHQsbj1bXSl7cmV0dXJuW3Qsbl19ZnVuY3Rpb24gUHQodCxuKXtjb25zdCBlPXRbMV07Zm9yKGNvbnN0IHQgb2YgZSl7aWYobih0LHRbMF0udHlwZSkpcmV0dXJuITB9cmV0dXJuITF9ZnVuY3Rpb24gVXQodCl7Y29uc3Qgbj1tKGwpO3JldHVybiBuLmVuY29kZVBvbHlmaWxsP24uZW5jb2RlUG9seWZpbGwodCk6KG5ldyBUZXh0RW5jb2RlcikuZW5jb2RlKHQpfWZ1bmN0aW9uIE10KHQpe2NvbnN0W24sZV09dDtsZXQgcj1KU09OLnN0cmluZ2lmeShuKTtmdW5jdGlvbiBvKHQpeyJzdHJpbmciPT10eXBlb2Ygcj9yPSJzdHJpbmciPT10eXBlb2YgdD9yK3Q6W1V0KHIpLHRdOnIucHVzaCgic3RyaW5nIj09dHlwZW9mIHQ/VXQodCk6dCl9Zm9yKGNvbnN0IHQgb2YgZSl7Y29uc3RbbixlXT10O2lmKG8oYFxuJHtKU09OLnN0cmluZ2lmeShuKX1cbmApLCJzdHJpbmciPT10eXBlb2YgZXx8ZSBpbnN0YW5jZW9mIFVpbnQ4QXJyYXkpbyhlKTtlbHNle2xldCB0O3RyeXt0PUpTT04uc3RyaW5naWZ5KGUpfWNhdGNoKG4pe3Q9SlNPTi5zdHJpbmdpZnkoSXQoZSkpfW8odCl9fXJldHVybiJzdHJpbmciPT10eXBlb2Ygcj9yOmZ1bmN0aW9uKHQpe2NvbnN0IG49dC5yZWR1Y2UoKCh0LG4pPT50K24ubGVuZ3RoKSwwKSxlPW5ldyBVaW50OEFycmF5KG4pO2xldCByPTA7Zm9yKGNvbnN0IG4gb2YgdCllLnNldChuLHIpLHIrPW4ubGVuZ3RoO3JldHVybiBlfShyKX1jb25zdCBMdD17c2Vzc2lvbjoic2Vzc2lvbiIsc2Vzc2lvbnM6InNlc3Npb24iLGF0dGFjaG1lbnQ6ImF0dGFjaG1lbnQiLHRyYW5zYWN0aW9uOiJ0cmFuc2FjdGlvbiIsZXZlbnQ6ImVycm9yIixjbGllbnRfcmVwb3J0OiJpbnRlcm5hbCIsdXNlcl9yZXBvcnQ6ImRlZmF1bHQiLHByb2ZpbGU6InByb2ZpbGUiLHByb2ZpbGVfY2h1bms6InByb2ZpbGUiLHJlcGxheV9ldmVudDoicmVwbGF5IixyZXBsYXlfcmVjb3JkaW5nOiJyZXBsYXkiLGNoZWNrX2luOiJtb25pdG9yIixmZWVkYmFjazoiZmVlZGJhY2siLHNwYW46InNwYW4iLHJhd19zZWN1cml0eToic2VjdXJpdHkiLGxvZzoibG9nX2l0ZW0ifTtmdW5jdGlvbiBCdCh0KXtpZighdD8uc2RrKXJldHVybjtjb25zdHtuYW1lOm4sdmVyc2lvbjplfT10LnNkaztyZXR1cm57bmFtZTpuLHZlcnNpb246ZX19ZnVuY3Rpb24gR3QodCxuLGUscil7Y29uc3Qgbz1CdChlKSxzPXQudHlwZSYmInJlcGxheV9ldmVudCIhPT10LnR5cGU/dC50eXBlOiJldmVudCI7IWZ1bmN0aW9uKHQsbil7biYmKHQuc2RrPXQuc2RrfHx7fSx0LnNkay5uYW1lPXQuc2RrLm5hbWV8fG4ubmFtZSx0LnNkay52ZXJzaW9uPXQuc2RrLnZlcnNpb258fG4udmVyc2lvbix0LnNkay5pbnRlZ3JhdGlvbnM9Wy4uLnQuc2RrLmludGVncmF0aW9uc3x8W10sLi4ubi5pbnRlZ3JhdGlvbnN8fFtdXSx0LnNkay5wYWNrYWdlcz1bLi4udC5zZGsucGFja2FnZXN8fFtdLC4uLm4ucGFja2FnZXN8fFtdXSl9KHQsZT8uc2RrKTtjb25zdCBpPWZ1bmN0aW9uKHQsbixlLHIpe2NvbnN0IG89dC5zZGtQcm9jZXNzaW5nTWV0YWRhdGE/LmR5bmFtaWNTYW1wbGluZ0NvbnRleHQ7cmV0dXJue2V2ZW50X2lkOnQuZXZlbnRfaWQsc2VudF9hdDoobmV3IERhdGUpLnRvSVNPU3RyaW5nKCksLi4ubiYme3NkazpufSwuLi4hIWUmJnImJntkc246UnQocil9LC4uLm8mJnt0cmFjZTpvfX19KHQsbyxyLG4pO2RlbGV0ZSB0LnNka1Byb2Nlc3NpbmdNZXRhZGF0YTtyZXR1cm4gQXQoaSxbW3t0eXBlOnN9LHRdXSl9Y29uc3QgSnQ9Il9fU0VOVFJZX1NVUFBSRVNTX1RSQUNJTkdfXyI7ZnVuY3Rpb24genQodCl7Y29uc3Qgbj1RKGQoKSk7cmV0dXJuIG4uc3VwcHJlc3NUcmFjaW5nP24uc3VwcHJlc3NUcmFjaW5nKHQpOmZ1bmN0aW9uKC4uLnQpe2NvbnN0IG49UShkKCkpO2lmKDI9PT10Lmxlbmd0aCl7Y29uc3RbZSxyXT10O3JldHVybiBlP24ud2l0aFNldFNjb3BlKGUscik6bi53aXRoU2NvcGUocil9cmV0dXJuIG4ud2l0aFNjb3BlKHRbMF0pfSgobj0+KG4uc2V0U0RLUHJvY2Vzc2luZ01ldGFkYXRhKHtbSnRdOiEwfSksdCgpKSkpfXZhciBIdDtmdW5jdGlvbiBGdCh0KXtyZXR1cm4gbmV3IFd0KChuPT57bih0KX0pKX0hZnVuY3Rpb24odCl7dFt0LlBFTkRJTkc9MF09IlBFTkRJTkciO3RbdC5SRVNPTFZFRD0xXT0iUkVTT0xWRUQiO3RbdC5SRUpFQ1RFRD0yXT0iUkVKRUNURUQifShIdHx8KEh0PXt9KSk7Y2xhc3MgV3R7Y29uc3RydWN0b3IodCl7dGhpcy5MPUh0LlBFTkRJTkcsdGhpcy5CPVtdLHRoaXMuRyh0KX10aGVuKHQsbil7cmV0dXJuIG5ldyBXdCgoKGUscik9Pnt0aGlzLkIucHVzaChbITEsbj0+e2lmKHQpdHJ5e2UodChuKSl9Y2F0Y2godCl7cih0KX1lbHNlIGUobil9LHQ9PntpZihuKXRyeXtlKG4odCkpfWNhdGNoKHQpe3IodCl9ZWxzZSByKHQpfV0pLHRoaXMuSigpfSkpfWNhdGNoKHQpe3JldHVybiB0aGlzLnRoZW4oKHQ9PnQpLHQpfWZpbmFsbHkodCl7cmV0dXJuIG5ldyBXdCgoKG4sZSk9PntsZXQgcixvO3JldHVybiB0aGlzLnRoZW4oKG49PntvPSExLHI9bix0JiZ0KCl9KSwobj0+e289ITAscj1uLHQmJnQoKX0pKS50aGVuKCgoKT0+e28/ZShyKTpuKHIpfSkpfSkpfUooKXtpZih0aGlzLkw9PT1IdC5QRU5ESU5HKXJldHVybjtjb25zdCB0PXRoaXMuQi5zbGljZSgpO3RoaXMuQj1bXSx0LmZvckVhY2goKHQ9Pnt0WzBdfHwodGhpcy5MPT09SHQuUkVTT0xWRUQmJnRbMV0odGhpcy5IKSx0aGlzLkw9PT1IdC5SRUpFQ1RFRCYmdFsyXSh0aGlzLkgpLHRbMF09ITApfSkpfUcodCl7Y29uc3Qgbj0odCxuKT0+e3RoaXMuTD09PUh0LlBFTkRJTkcmJih3KG4pP24udGhlbihlLHIpOih0aGlzLkw9dCx0aGlzLkg9bix0aGlzLkooKSkpfSxlPXQ9PntuKEh0LlJFU09MVkVELHQpfSxyPXQ9PntuKEh0LlJFSkVDVEVELHQpfTt0cnl7dChlLHIpfWNhdGNoKHQpe3IodCl9fX1mdW5jdGlvbiBZdCh0LG4pe2NvbnN0e2ZpbmdlcnByaW50OmUsc3BhbjpyLGJyZWFkY3J1bWJzOm8sc2RrUHJvY2Vzc2luZ01ldGFkYXRhOnN9PW47IWZ1bmN0aW9uKHQsbil7Y29uc3R7ZXh0cmE6ZSx0YWdzOnIsdXNlcjpvLGNvbnRleHRzOnMsbGV2ZWw6aSx0cmFuc2FjdGlvbk5hbWU6Y309bjtPYmplY3Qua2V5cyhlKS5sZW5ndGgmJih0LmV4dHJhPXsuLi5lLC4uLnQuZXh0cmF9KTtPYmplY3Qua2V5cyhyKS5sZW5ndGgmJih0LnRhZ3M9ey4uLnIsLi4udC50YWdzfSk7T2JqZWN0LmtleXMobykubGVuZ3RoJiYodC51c2VyPXsuLi5vLC4uLnQudXNlcn0pO09iamVjdC5rZXlzKHMpLmxlbmd0aCYmKHQuY29udGV4dHM9ey4uLnMsLi4udC5jb250ZXh0c30pO2kmJih0LmxldmVsPWkpO2MmJiJ0cmFuc2FjdGlvbiIhPT10LnR5cGUmJih0LnRyYW5zYWN0aW9uPWMpfSh0LG4pLHImJmZ1bmN0aW9uKHQsbil7dC5jb250ZXh0cz17dHJhY2U6bXQobiksLi4udC5jb250ZXh0c30sdC5zZGtQcm9jZXNzaW5nTWV0YWRhdGE9e2R5bmFtaWNTYW1wbGluZ0NvbnRleHQ6anQobiksLi4udC5zZGtQcm9jZXNzaW5nTWV0YWRhdGF9O2NvbnN0IGU9U3Qobikscj12dChlKS5kZXNjcmlwdGlvbjtyJiYhdC50cmFuc2FjdGlvbiYmInRyYW5zYWN0aW9uIj09PXQudHlwZSYmKHQudHJhbnNhY3Rpb249cil9KHQsciksZnVuY3Rpb24odCxuKXt0LmZpbmdlcnByaW50PXQuZmluZ2VycHJpbnQ/QXJyYXkuaXNBcnJheSh0LmZpbmdlcnByaW50KT90LmZpbmdlcnByaW50Olt0LmZpbmdlcnByaW50XTpbXSxuJiYodC5maW5nZXJwcmludD10LmZpbmdlcnByaW50LmNvbmNhdChuKSk7dC5maW5nZXJwcmludC5sZW5ndGh8fGRlbGV0ZSB0LmZpbmdlcnByaW50fSh0LGUpLGZ1bmN0aW9uKHQsbil7Y29uc3QgZT1bLi4udC5icmVhZGNydW1ic3x8W10sLi4ubl07dC5icmVhZGNydW1icz1lLmxlbmd0aD9lOnZvaWQgMH0odCxvKSxmdW5jdGlvbih0LG4pe3Quc2RrUHJvY2Vzc2luZ01ldGFkYXRhPXsuLi50LnNka1Byb2Nlc3NpbmdNZXRhZGF0YSwuLi5ufX0odCxzKX1jb25zdCBLdD0iNyI7Y29uc3QgVnQ9U3ltYm9sLmZvcigiU2VudHJ5QnVmZmVyRnVsbEVycm9yIik7ZnVuY3Rpb24gWnQodCl7Y29uc3Qgbj1bXTtmdW5jdGlvbiBlKHQpe3JldHVybiBuLnNwbGljZShuLmluZGV4T2YodCksMSlbMF18fFByb21pc2UucmVzb2x2ZSh2b2lkIDApfXJldHVybnskOm4sYWRkOmZ1bmN0aW9uKHIpe2lmKCEodm9pZCAwPT09dHx8bi5sZW5ndGg8dCkpcmV0dXJuIG89VnQsbmV3IFd0KCgodCxuKT0+e24obyl9KSk7dmFyIG87Y29uc3Qgcz1yKCk7cmV0dXJuLTE9PT1uLmluZGV4T2YocykmJm4ucHVzaChzKSxzLnRoZW4oKCgpPT5lKHMpKSkudGhlbihudWxsLCgoKT0+ZShzKS50aGVuKG51bGwsKCgpPT57fSkpKSksc30sZHJhaW46ZnVuY3Rpb24odCl7cmV0dXJuIG5ldyBXdCgoKGUscik9PntsZXQgbz1uLmxlbmd0aDtpZighbylyZXR1cm4gZSghMCk7Y29uc3Qgcz1zZXRUaW1lb3V0KCgoKT0+e3QmJnQ+MCYmZSghMSl9KSx0KTtuLmZvckVhY2goKHQ9PntGdCh0KS50aGVuKCgoKT0+ey0tb3x8KGNsZWFyVGltZW91dChzKSxlKCEwKSl9KSxyKX0pKX0pKX19fWNvbnN0IHF0PTZlNDtmdW5jdGlvbiBRdCh0LHtzdGF0dXNDb2RlOm4saGVhZGVyczplfSxyPURhdGUubm93KCkpe2NvbnN0IG89ey4uLnR9LHM9ZT8uWyJ4LXNlbnRyeS1yYXRlLWxpbWl0cyJdLGk9ZT8uWyJyZXRyeS1hZnRlciJdO2lmKHMpZm9yKGNvbnN0IHQgb2Ygcy50cmltKCkuc3BsaXQoIiwiKSl7Y29uc3RbbixlLCwsc109dC5zcGxpdCgiOiIsNSksaT1wYXJzZUludChuLDEwKSxjPTFlMyooaXNOYU4oaSk/NjA6aSk7aWYoZSlmb3IoY29uc3QgdCBvZiBlLnNwbGl0KCI7IikpIm1ldHJpY19idWNrZXQiPT09dCYmcyYmIXMuc3BsaXQoIjsiKS5pbmNsdWRlcygiY3VzdG9tIil8fChvW3RdPXIrYyk7ZWxzZSBvLmFsbD1yK2N9ZWxzZSBpP28uYWxsPXIrZnVuY3Rpb24odCxuPURhdGUubm93KCkpe2NvbnN0IGU9cGFyc2VJbnQoYCR7dH1gLDEwKTtpZighaXNOYU4oZSkpcmV0dXJuIDFlMyplO2NvbnN0IHI9RGF0ZS5wYXJzZShgJHt0fWApO3JldHVybiBpc05hTihyKT9xdDpyLW59KGkscik6NDI5PT09biYmKG8uYWxsPXIrNmU0KTtyZXR1cm4gb31jb25zdCBYdD02NDtmdW5jdGlvbiB0bih0LG4sZT1adCh0LmJ1ZmZlclNpemV8fFh0KSl7bGV0IHI9e307cmV0dXJue3NlbmQ6ZnVuY3Rpb24odCl7Y29uc3Qgbz1bXTtpZihQdCh0LCgodCxuKT0+e2NvbnN0IGU9ZnVuY3Rpb24odCl7cmV0dXJuIEx0W3RdfShuKTsoZnVuY3Rpb24odCxuLGU9RGF0ZS5ub3coKSl7cmV0dXJuIGZ1bmN0aW9uKHQsbil7cmV0dXJuIHRbbl18fHQuYWxsfHwwfSh0LG4pPmV9KShyLGUpfHxvLnB1c2godCl9KSksMD09PW8ubGVuZ3RoKXJldHVybiBGdCh7fSk7Y29uc3Qgcz1BdCh0WzBdLG8pLGk9dD0+e1B0KHMsKCh0LG4pPT57fSkpfTtyZXR1cm4gZS5hZGQoKCgpPT5uKHtib2R5Ok10KHMpfSkudGhlbigodD0+KHZvaWQgMCE9PXQuc3RhdHVzQ29kZSYmKHQuc3RhdHVzQ29kZTwyMDB8fHQuc3RhdHVzQ29kZT49MzAwKSYmaCYmay53YXJuKGBTZW50cnkgcmVzcG9uZGVkIHdpdGggc3RhdHVzIGNvZGUgJHt0LnN0YXR1c0NvZGV9IHRvIHNlbnQgZXZlbnQuYCkscj1RdChyLHQpLHQpKSwodD0+e3Rocm93IGkoKSxoJiZrLmVycm9yKCJFbmNvdW50ZXJlZCBlcnJvciBydW5uaW5nIHRyYW5zcG9ydCByZXF1ZXN0OiIsdCksdH0pKSkpLnRoZW4oKHQ9PnQpLCh0PT57aWYodD09PVZ0KXJldHVybiBoJiZrLmVycm9yKCJTa2lwcGVkIHNlbmRpbmcgZXZlbnQgYmVjYXVzZSBidWZmZXIgaXMgZnVsbC4iKSxpKCksRnQoe30pO3Rocm93IHR9KSl9LGZsdXNoOnQ9PmUuZHJhaW4odCl9fWNvbnN0IG5uPS9eKFxTKzpcXHxcLz8pKFtcc1xTXSo/KSgoPzpcLnsxLDJ9fFteL1xcXSs/fCkoXC5bXi4vXFxdKnwpKSg/OlsvXFxdKikkLztmdW5jdGlvbiBlbih0KXtjb25zdCBuPWZ1bmN0aW9uKHQpe2NvbnN0IG49dC5sZW5ndGg+MTAyND9gPHRydW5jYXRlZD4ke3Quc2xpY2UoLTEwMjQpfWA6dCxlPW5uLmV4ZWMobik7cmV0dXJuIGU/ZS5zbGljZSgxKTpbXX0odCksZT1uWzBdfHwiIjtsZXQgcj1uWzFdO3JldHVybiBlfHxyPyhyJiYocj1yLnNsaWNlKDAsci5sZW5ndGgtMSkpLGUrcik6Ii4ifWZ1bmN0aW9uIHJuKHQsbj0hMSl7cmV0dXJuIShufHx0JiYhdC5zdGFydHNXaXRoKCIvIikmJiF0Lm1hdGNoKC9eW0EtWl06LykmJiF0LnN0YXJ0c1dpdGgoIi4iKSYmIXQubWF0Y2goL15bYS16QS1aXShbYS16QS1aMC05LlwtK10pKjpcL1wvLykpJiZ2b2lkIDAhPT10JiYhdC5pbmNsdWRlcygibm9kZV9tb2R1bGVzLyIpfWNvbnN0IG9uPVN5bWJvbCgiQWdlbnRCYXNlSW50ZXJuYWxTdGF0ZSIpO2NsYXNzIHNuIGV4dGVuZHMgcy5BZ2VudHtjb25zdHJ1Y3Rvcih0KXtzdXBlcih0KSx0aGlzW29uXT17fX1pc1NlY3VyZUVuZHBvaW50KHQpe2lmKHQpe2lmKCJib29sZWFuIj09dHlwZW9mIHQuc2VjdXJlRW5kcG9pbnQpcmV0dXJuIHQuc2VjdXJlRW5kcG9pbnQ7aWYoInN0cmluZyI9PXR5cGVvZiB0LnByb3RvY29sKXJldHVybiJodHRwczoiPT09dC5wcm90b2NvbH1jb25zdHtzdGFjazpufT1uZXcgRXJyb3I7cmV0dXJuInN0cmluZyI9PXR5cGVvZiBuJiZuLnNwbGl0KCJcbiIpLnNvbWUoKHQ9Pi0xIT09dC5pbmRleE9mKCIoaHR0cHMuanM6Iil8fC0xIT09dC5pbmRleE9mKCJub2RlOmh0dHBzOiIpKSl9Y3JlYXRlU29ja2V0KHQsbixlKXtjb25zdCByPXsuLi5uLHNlY3VyZUVuZHBvaW50OnRoaXMuaXNTZWN1cmVFbmRwb2ludChuKX07UHJvbWlzZS5yZXNvbHZlKCkudGhlbigoKCk9PnRoaXMuY29ubmVjdCh0LHIpKSkudGhlbigobz0+e2lmKG8gaW5zdGFuY2VvZiBzLkFnZW50KXJldHVybiBvLmFkZFJlcXVlc3QodCxyKTt0aGlzW29uXS5jdXJyZW50U29ja2V0PW8sc3VwZXIuY3JlYXRlU29ja2V0KHQsbixlKX0pLGUpfWNyZWF0ZUNvbm5lY3Rpb24oKXtjb25zdCB0PXRoaXNbb25dLmN1cnJlbnRTb2NrZXQ7aWYodGhpc1tvbl0uY3VycmVudFNvY2tldD12b2lkIDAsIXQpdGhyb3cgbmV3IEVycm9yKCJObyBzb2NrZXQgd2FzIHJldHVybmVkIGluIHRoZSBgY29ubmVjdCgpYCBmdW5jdGlvbiIpO3JldHVybiB0fWdldCBkZWZhdWx0UG9ydCgpe3JldHVybiB0aGlzW29uXS5kZWZhdWx0UG9ydD8/KCJodHRwczoiPT09dGhpcy5wcm90b2NvbD80NDM6ODApfXNldCBkZWZhdWx0UG9ydCh0KXt0aGlzW29uXSYmKHRoaXNbb25dLmRlZmF1bHRQb3J0PXQpfWdldCBwcm90b2NvbCgpe3JldHVybiB0aGlzW29uXS5wcm90b2NvbD8/KHRoaXMuaXNTZWN1cmVFbmRwb2ludCgpPyJodHRwczoiOiJodHRwOiIpfXNldCBwcm90b2NvbCh0KXt0aGlzW29uXSYmKHRoaXNbb25dLnByb3RvY29sPXQpfX1mdW5jdGlvbiBjbiguLi50KXtrLmxvZygiW2h0dHBzLXByb3h5LWFnZW50OnBhcnNlLXByb3h5LXJlc3BvbnNlXSIsLi4udCl9ZnVuY3Rpb24gdW4odCl7cmV0dXJuIG5ldyBQcm9taXNlKCgobixlKT0+e2xldCByPTA7Y29uc3Qgbz1bXTtmdW5jdGlvbiBzKCl7Y29uc3QgYz10LnJlYWQoKTtjP2Z1bmN0aW9uKGMpe28ucHVzaChjKSxyKz1jLmxlbmd0aDtjb25zdCB1PUJ1ZmZlci5jb25jYXQobyxyKSxhPXUuaW5kZXhPZigiXHJcblxyXG4iKTtpZigtMT09PWEpcmV0dXJuIGNuKCJoYXZlIG5vdCByZWNlaXZlZCBlbmQgb2YgSFRUUCBoZWFkZXJzIHlldC4uLiIpLHZvaWQgcygpO2NvbnN0IGY9dS5zdWJhcnJheSgwLGEpLnRvU3RyaW5nKCJhc2NpaSIpLnNwbGl0KCJcclxuIiksaD1mLnNoaWZ0KCk7aWYoIWgpcmV0dXJuIHQuZGVzdHJveSgpLGUobmV3IEVycm9yKCJObyBoZWFkZXIgcmVjZWl2ZWQgZnJvbSBwcm94eSBDT05ORUNUIHJlc3BvbnNlIikpO2NvbnN0IHA9aC5zcGxpdCgiICIpLGw9KyhwWzFdfHwwKSxkPXAuc2xpY2UoMikuam9pbigiICIpLG09e307Zm9yKGNvbnN0IG4gb2YgZil7aWYoIW4pY29udGludWU7Y29uc3Qgcj1uLmluZGV4T2YoIjoiKTtpZigtMT09PXIpcmV0dXJuIHQuZGVzdHJveSgpLGUobmV3IEVycm9yKGBJbnZhbGlkIGhlYWRlciBmcm9tIHByb3h5IENPTk5FQ1QgcmVzcG9uc2U6ICIke259ImApKTtjb25zdCBvPW4uc2xpY2UoMCxyKS50b0xvd2VyQ2FzZSgpLHM9bi5zbGljZShyKzEpLnRyaW1TdGFydCgpLGk9bVtvXTsic3RyaW5nIj09dHlwZW9mIGk/bVtvXT1baSxzXTpBcnJheS5pc0FycmF5KGkpP2kucHVzaChzKTptW29dPXN9Y24oImdvdCBwcm94eSBzZXJ2ZXIgcmVzcG9uc2U6ICVvICVvIixoLG0pLGkoKSxuKHtjb25uZWN0OntzdGF0dXNDb2RlOmwsc3RhdHVzVGV4dDpkLGhlYWRlcnM6bX0sYnVmZmVyZWQ6dX0pfShjKTp0Lm9uY2UoInJlYWRhYmxlIixzKX1mdW5jdGlvbiBpKCl7dC5yZW1vdmVMaXN0ZW5lcigiZW5kIixjKSx0LnJlbW92ZUxpc3RlbmVyKCJlcnJvciIsdSksdC5yZW1vdmVMaXN0ZW5lcigicmVhZGFibGUiLHMpfWZ1bmN0aW9uIGMoKXtpKCksY24oIm9uZW5kIiksZShuZXcgRXJyb3IoIlByb3h5IGNvbm5lY3Rpb24gZW5kZWQgYmVmb3JlIHJlY2VpdmluZyBDT05ORUNUIHJlc3BvbnNlIikpfWZ1bmN0aW9uIHUodCl7aSgpLGNuKCJvbmVycm9yICVvIix0KSxlKHQpfXQub24oImVycm9yIix1KSx0Lm9uKCJlbmQiLGMpLHMoKX0pKX1mdW5jdGlvbiBhbiguLi50KXtrLmxvZygiW2h0dHBzLXByb3h5LWFnZW50XSIsLi4udCl9Y2xhc3MgZm4gZXh0ZW5kcyBzbntzdGF0aWMgX19pbml0U3RhdGljKCl7dGhpcy5wcm90b2NvbHM9WyJodHRwIiwiaHR0cHMiXX1jb25zdHJ1Y3Rvcih0LG4pe3N1cGVyKG4pLHRoaXMub3B0aW9ucz17fSx0aGlzLnByb3h5PSJzdHJpbmciPT10eXBlb2YgdD9uZXcgVVJMKHQpOnQsdGhpcy5wcm94eUhlYWRlcnM9bj8uaGVhZGVycz8/e30sYW4oIkNyZWF0aW5nIG5ldyBIdHRwc1Byb3h5QWdlbnQgaW5zdGFuY2U6ICVvIix0aGlzLnByb3h5LmhyZWYpO2NvbnN0IGU9KHRoaXMucHJveHkuaG9zdG5hbWV8fHRoaXMucHJveHkuaG9zdCkucmVwbGFjZSgvXlxbfFxdJC9nLCIiKSxyPXRoaXMucHJveHkucG9ydD9wYXJzZUludCh0aGlzLnByb3h5LnBvcnQsMTApOiJodHRwczoiPT09dGhpcy5wcm94eS5wcm90b2NvbD80NDM6ODA7dGhpcy5jb25uZWN0T3B0cz17QUxQTlByb3RvY29sczpbImh0dHAvMS4xIl0sLi4ubj9wbihuLCJoZWFkZXJzIik6bnVsbCxob3N0OmUscG9ydDpyfX1hc3luYyBjb25uZWN0KHQsbil7Y29uc3R7cHJveHk6ZX09dGhpcztpZighbi5ob3N0KXRocm93IG5ldyBUeXBlRXJyb3IoJ05vICJob3N0IiBwcm92aWRlZCcpO2xldCByO2lmKCJodHRwczoiPT09ZS5wcm90b2NvbCl7YW4oIkNyZWF0aW5nIGB0bHMuU29ja2V0YDogJW8iLHRoaXMuY29ubmVjdE9wdHMpO2NvbnN0IHQ9dGhpcy5jb25uZWN0T3B0cy5zZXJ2ZXJuYW1lfHx0aGlzLmNvbm5lY3RPcHRzLmhvc3Q7cj1mLmNvbm5lY3Qoey4uLnRoaXMuY29ubmVjdE9wdHMsc2VydmVybmFtZTp0JiZhLmlzSVAodCk/dm9pZCAwOnR9KX1lbHNlIGFuKCJDcmVhdGluZyBgbmV0LlNvY2tldGA6ICVvIix0aGlzLmNvbm5lY3RPcHRzKSxyPWEuY29ubmVjdCh0aGlzLmNvbm5lY3RPcHRzKTtjb25zdCBvPSJmdW5jdGlvbiI9PXR5cGVvZiB0aGlzLnByb3h5SGVhZGVycz90aGlzLnByb3h5SGVhZGVycygpOnsuLi50aGlzLnByb3h5SGVhZGVyc30scz1hLmlzSVB2NihuLmhvc3QpP2BbJHtuLmhvc3R9XWA6bi5ob3N0O2xldCBpPWBDT05ORUNUICR7c306JHtuLnBvcnR9IEhUVFAvMS4xXHJcbmA7aWYoZS51c2VybmFtZXx8ZS5wYXNzd29yZCl7Y29uc3QgdD1gJHtkZWNvZGVVUklDb21wb25lbnQoZS51c2VybmFtZSl9OiR7ZGVjb2RlVVJJQ29tcG9uZW50KGUucGFzc3dvcmQpfWA7b1siUHJveHktQXV0aG9yaXphdGlvbiJdPWBCYXNpYyAke0J1ZmZlci5mcm9tKHQpLnRvU3RyaW5nKCJiYXNlNjQiKX1gfW8uSG9zdD1gJHtzfToke24ucG9ydH1gLG9bIlByb3h5LUNvbm5lY3Rpb24iXXx8KG9bIlByb3h5LUNvbm5lY3Rpb24iXT10aGlzLmtlZXBBbGl2ZT8iS2VlcC1BbGl2ZSI6ImNsb3NlIik7Zm9yKGNvbnN0IHQgb2YgT2JqZWN0LmtleXMobykpaSs9YCR7dH06ICR7b1t0XX1cclxuYDtjb25zdCBjPXVuKHIpO3Iud3JpdGUoYCR7aX1cclxuYCk7Y29uc3R7Y29ubmVjdDp1LGJ1ZmZlcmVkOmh9PWF3YWl0IGM7aWYodC5lbWl0KCJwcm94eUNvbm5lY3QiLHUpLHRoaXMuZW1pdCgicHJveHlDb25uZWN0Iix1LHQpLDIwMD09PXUuc3RhdHVzQ29kZSl7aWYodC5vbmNlKCJzb2NrZXQiLGhuKSxuLnNlY3VyZUVuZHBvaW50KXthbigiVXBncmFkaW5nIHNvY2tldCBjb25uZWN0aW9uIHRvIFRMUyIpO2NvbnN0IHQ9bi5zZXJ2ZXJuYW1lfHxuLmhvc3Q7cmV0dXJuIGYuY29ubmVjdCh7Li4ucG4obiwiaG9zdCIsInBhdGgiLCJwb3J0Iiksc29ja2V0OnIsc2VydmVybmFtZTphLmlzSVAodCk/dm9pZCAwOnR9KX1yZXR1cm4gcn1yLmRlc3Ryb3koKTtjb25zdCBwPW5ldyBhLlNvY2tldCh7d3JpdGFibGU6ITF9KTtyZXR1cm4gcC5yZWFkYWJsZT0hMCx0Lm9uY2UoInNvY2tldCIsKHQ9PnthbigiUmVwbGF5aW5nIHByb3h5IGJ1ZmZlciBmb3IgZmFpbGVkIHJlcXVlc3QiKSx0LnB1c2goaCksdC5wdXNoKG51bGwpfSkpLHB9fWZ1bmN0aW9uIGhuKHQpe3QucmVzdW1lKCl9ZnVuY3Rpb24gcG4odCwuLi5uKXtjb25zdCBlPXt9O2xldCByO2ZvcihyIGluIHQpbi5pbmNsdWRlcyhyKXx8KGVbcl09dFtyXSk7cmV0dXJuIGV9Zm4uX19pbml0U3RhdGljKCk7Y29uc3QgbG49MzI3Njg7ZnVuY3Rpb24gZG4odCl7cmV0dXJuIHQucmVwbGFjZSgvXltBLVpdOi8sIiIpLnJlcGxhY2UoL1xcL2csIi8iKX1jb25zdCBtbj1uO2xldCBnbix5bj0wLGJuPXt9O2Z1bmN0aW9uIHZuKHQpe21uLmRlYnVnJiZjb25zb2xlLmxvZyhgW0FOUiBXb3JrZXJdICR7dH1gKX12YXIgX24sd24sU247Y29uc3QgJG49ZnVuY3Rpb24odCl7bGV0IG47dHJ5e249bmV3IFVSTCh0LnVybCl9Y2F0Y2gobil7cmV0dXJuIFQoKCgpPT57Y29uc29sZS53YXJuKCJbQHNlbnRyeS9ub2RlXTogSW52YWxpZCBkc24gb3IgdHVubmVsIG9wdGlvbiwgd2lsbCBub3Qgc2VuZCBhbnkgZXZlbnRzLiBUaGUgdHVubmVsIG9wdGlvbiBtdXN0IGJlIGEgZnVsbCBVUkwgd2hlbiB1c2VkLiIpfSkpLHRuKHQsKCgpPT5Qcm9taXNlLnJlc29sdmUoe30pKSl9Y29uc3QgZT0iaHR0cHM6Ij09PW4ucHJvdG9jb2wscj1mdW5jdGlvbih0LG4pe2NvbnN0e25vX3Byb3h5OmV9PXByb2Nlc3MuZW52LHI9ZT8uc3BsaXQoIiwiKS5zb21lKChuPT50Lmhvc3QuZW5kc1dpdGgobil8fHQuaG9zdG5hbWUuZW5kc1dpdGgobikpKTtyZXR1cm4gcj92b2lkIDA6bn0obix0LnByb3h5fHwoZT9wcm9jZXNzLmVudi5odHRwc19wcm94eTp2b2lkIDApfHxwcm9jZXNzLmVudi5odHRwX3Byb3h5KSxvPWU/aTpzLGE9dm9pZCAwIT09dC5rZWVwQWxpdmUmJnQua2VlcEFsaXZlLGY9cj9uZXcgZm4ocik6bmV3IG8uQWdlbnQoe2tlZXBBbGl2ZTphLG1heFNvY2tldHM6MzAsdGltZW91dDoyZTN9KSxoPWZ1bmN0aW9uKHQsbixlKXtjb25zdHtob3N0bmFtZTpyLHBhdGhuYW1lOm8scG9ydDpzLHByb3RvY29sOmksc2VhcmNoOmF9PW5ldyBVUkwodC51cmwpO3JldHVybiBmdW5jdGlvbihmKXtyZXR1cm4gbmV3IFByb21pc2UoKChoLHApPT57enQoKCgpPT57bGV0IGw9ZnVuY3Rpb24odCl7cmV0dXJuIG5ldyBjKHtyZWFkKCl7dGhpcy5wdXNoKHQpLHRoaXMucHVzaChudWxsKX19KX0oZi5ib2R5KTtjb25zdCBkPXsuLi50LmhlYWRlcnN9O2YuYm9keS5sZW5ndGg+bG4mJihkWyJjb250ZW50LWVuY29kaW5nIl09Imd6aXAiLGw9bC5waXBlKHUoKSkpO2NvbnN0IG09bi5yZXF1ZXN0KHttZXRob2Q6IlBPU1QiLGFnZW50OmUsaGVhZGVyczpkLGhvc3RuYW1lOnIscGF0aDpgJHtvfSR7YX1gLHBvcnQ6cyxwcm90b2NvbDppLGNhOnQuY2FDZXJ0c30sKHQ9Pnt0Lm9uKCJkYXRhIiwoKCk9Pnt9KSksdC5vbigiZW5kIiwoKCk9Pnt9KSksdC5zZXRFbmNvZGluZygidXRmOCIpO2NvbnN0IG49dC5oZWFkZXJzWyJyZXRyeS1hZnRlciJdPz9udWxsLGU9dC5oZWFkZXJzWyJ4LXNlbnRyeS1yYXRlLWxpbWl0cyJdPz9udWxsO2goe3N0YXR1c0NvZGU6dC5zdGF0dXNDb2RlLGhlYWRlcnM6eyJyZXRyeS1hZnRlciI6biwieC1zZW50cnktcmF0ZS1saW1pdHMiOkFycmF5LmlzQXJyYXkoZSk/ZVswXXx8bnVsbDplfX0pfSkpO20ub24oImVycm9yIixwKSxsLnBpcGUobSl9KSl9KSl9fSh0LHQuaHR0cE1vZHVsZT8/byxmKTtyZXR1cm4gdG4odCxoKX0oe3VybDooX249bW4uZHNuLHduPW1uLnR1bm5lbCxTbj1tbi5zZGtNZXRhZGF0YS5zZGssd258fGAke2Z1bmN0aW9uKHQpe3JldHVybmAke2Z1bmN0aW9uKHQpe2NvbnN0IG49dC5wcm90b2NvbD9gJHt0LnByb3RvY29sfTpgOiIiLGU9dC5wb3J0P2A6JHt0LnBvcnR9YDoiIjtyZXR1cm5gJHtufS8vJHt0Lmhvc3R9JHtlfSR7dC5wYXRoP2AvJHt0LnBhdGh9YDoiIn0vYXBpL2B9KHQpfSR7dC5wcm9qZWN0SWR9L2VudmVsb3BlL2B9KF9uKX0/JHtmdW5jdGlvbih0LG4pe2NvbnN0IGU9e3NlbnRyeV92ZXJzaW9uOkt0fTtyZXR1cm4gdC5wdWJsaWNLZXkmJihlLnNlbnRyeV9rZXk9dC5wdWJsaWNLZXkpLG4mJihlLnNlbnRyeV9jbGllbnQ9YCR7bi5uYW1lfS8ke24udmVyc2lvbn1gKSxuZXcgVVJMU2VhcmNoUGFyYW1zKGUpLnRvU3RyaW5nKCl9KF9uLFNuKX1gKX0pO2FzeW5jIGZ1bmN0aW9uIEVuKCl7aWYoZ24pe3ZuKCJTZW5kaW5nIGFibm9ybWFsIHNlc3Npb24iKSxMKGduLHtzdGF0dXM6ImFibm9ybWFsIixhYm5vcm1hbF9tZWNoYW5pc206ImFucl9mb3JlZ3JvdW5kIixyZWxlYXNlOm1uLnJlbGVhc2UsZW52aXJvbm1lbnQ6bW4uZW52aXJvbm1lbnR9KTtjb25zdCB0PWZ1bmN0aW9uKHQsbixlLHIpe2NvbnN0IG89QnQoZSk7cmV0dXJuIEF0KHtzZW50X2F0OihuZXcgRGF0ZSkudG9JU09TdHJpbmcoKSwuLi5vJiZ7c2RrOm99LC4uLiEhciYmbiYme2RzbjpSdChuKX19LFsiYWdncmVnYXRlcyJpbiB0P1t7dHlwZToic2Vzc2lvbnMifSx0XTpbe3R5cGU6InNlc3Npb24ifSx0LnRvSlNPTigpXV0pfShnbixtbi5kc24sbW4uc2RrTWV0YWRhdGEsbW4udHVubmVsKTt2bihKU09OLnN0cmluZ2lmeSh0KSksYXdhaXQgJG4uc2VuZCh0KTt0cnl7ZT8ucG9zdE1lc3NhZ2UoInNlc3Npb24tZW5kZWQiKX1jYXRjaCh0KXt9fX1mdW5jdGlvbiB4bih0KXtpZighdClyZXR1cm47Y29uc3Qgbj1mdW5jdGlvbih0KXtpZighdC5sZW5ndGgpcmV0dXJuW107Y29uc3Qgbj1BcnJheS5mcm9tKHQpO3JldHVybi9zZW50cnlXcmFwcGVkLy50ZXN0KE50KG4pLmZ1bmN0aW9ufHwiIikmJm4ucG9wKCksbi5yZXZlcnNlKCkseHQudGVzdChOdChuKS5mdW5jdGlvbnx8IiIpJiYobi5wb3AoKSx4dC50ZXN0KE50KG4pLmZ1bmN0aW9ufHwiIikmJm4ucG9wKCkpLG4uc2xpY2UoMCwkdCkubWFwKCh0PT4oey4uLnQsZmlsZW5hbWU6dC5maWxlbmFtZXx8TnQobikuZmlsZW5hbWUsZnVuY3Rpb246dC5mdW5jdGlvbnx8RXR9KSkpfSh0KTtpZihtbi5hcHBSb290UGF0aClmb3IoY29uc3QgdCBvZiBuKXQuZmlsZW5hbWUmJih0LmZpbGVuYW1lPUR0KHQuZmlsZW5hbWUsbW4uYXBwUm9vdFBhdGgpKTtyZXR1cm4gbn1hc3luYyBmdW5jdGlvbiBObih0LG4pe2lmKHluPj1tbi5tYXhBbnJFdmVudHMpcmV0dXJuO3luKz0xLGF3YWl0IEVuKCksdm4oIlNlbmRpbmcgZXZlbnQiKTtjb25zdCBlPXtldmVudF9pZDpEKCksY29udGV4dHM6bW4uY29udGV4dHMscmVsZWFzZTptbi5yZWxlYXNlLGVudmlyb25tZW50Om1uLmVudmlyb25tZW50LGRpc3Q6bW4uZGlzdCxwbGF0Zm9ybToibm9kZSIsbGV2ZWw6ImVycm9yIixleGNlcHRpb246e3ZhbHVlczpbe3R5cGU6IkFwcGxpY2F0aW9uTm90UmVzcG9uZGluZyIsdmFsdWU6YEFwcGxpY2F0aW9uIE5vdCBSZXNwb25kaW5nIGZvciBhdCBsZWFzdCAke21uLmFuclRocmVzaG9sZH0gbXNgLHN0YWNrdHJhY2U6e2ZyYW1lczp4bih0KX0sbWVjaGFuaXNtOnt0eXBlOiJBTlIifX1dfSx0YWdzOm1uLnN0YXRpY1RhZ3N9O24mJmZ1bmN0aW9uKHQsbil7aWYoWXQodCxuKSwhdC5jb250ZXh0cz8udHJhY2Upe2NvbnN0e3RyYWNlSWQ6ZSxwYXJlbnRTcGFuSWQ6cixwcm9wYWdhdGlvblNwYW5JZDpvfT1uLnByb3BhZ2F0aW9uQ29udGV4dDt0LmNvbnRleHRzPXt0cmFjZTp7dHJhY2VfaWQ6ZSxzcGFuX2lkOm98fEYoKSxwYXJlbnRfc3Bhbl9pZDpyfSwuLi50LmNvbnRleHRzfX19KGUsbiksZnVuY3Rpb24odCl7aWYoMD09PU9iamVjdC5rZXlzKGJuKS5sZW5ndGgpcmV0dXJuO2NvbnN0IG49bW4uYXBwUm9vdFBhdGg/e306Ym47aWYobW4uYXBwUm9vdFBhdGgpZm9yKGNvbnN0W3QsZV1vZiBPYmplY3QuZW50cmllcyhibikpbltEdCh0LG1uLmFwcFJvb3RQYXRoKV09ZTtjb25zdCBlPW5ldyBNYXA7Zm9yKGNvbnN0IHIgb2YgdC5leGNlcHRpb24/LnZhbHVlc3x8W10pZm9yKGNvbnN0IHQgb2Ygci5zdGFja3RyYWNlPy5mcmFtZXN8fFtdKXtjb25zdCByPXQuYWJzX3BhdGh8fHQuZmlsZW5hbWU7ciYmbltyXSYmZS5zZXQocixuW3JdKX1pZihlLnNpemU+MCl7Y29uc3Qgbj1bXTtmb3IoY29uc3RbdCxyXW9mIGUuZW50cmllcygpKW4ucHVzaCh7dHlwZToic291cmNlbWFwIixjb2RlX2ZpbGU6dCxkZWJ1Z19pZDpyfSk7dC5kZWJ1Z19tZXRhPXtpbWFnZXM6bn19fShlKTtjb25zdCByPUd0KGUsbW4uZHNuLG1uLnNka01ldGFkYXRhLG1uLnR1bm5lbCk7dm4oSlNPTi5zdHJpbmdpZnkocikpLGF3YWl0ICRuLnNlbmQociksYXdhaXQgJG4uZmx1c2goMmUzKSx5bj49bW4ubWF4QW5yRXZlbnRzJiZzZXRUaW1lb3V0KCgoKT0+e3Byb2Nlc3MuZXhpdCgwKX0pLDVlMyl9bGV0IENuO2lmKHZuKCJTdGFydGVkIiksbW4uY2FwdHVyZVN0YWNrVHJhY2Upe3ZuKCJDb25uZWN0aW5nIHRvIGRlYnVnZ2VyIik7Y29uc3Qgbj1uZXcgdDtuLmNvbm5lY3RUb01haW5UaHJlYWQoKSx2bigiQ29ubmVjdGVkIHRvIGRlYnVnZ2VyIik7Y29uc3QgZT1uZXcgTWFwO24ub24oIkRlYnVnZ2VyLnNjcmlwdFBhcnNlZCIsKHQ9PntlLnNldCh0LnBhcmFtcy5zY3JpcHRJZCx0LnBhcmFtcy51cmwpfSkpLG4ub24oIkRlYnVnZ2VyLnBhdXNlZCIsKHQ9PntpZigib3RoZXIiPT09dC5wYXJhbXMucmVhc29uKXRyeXt2bigiRGVidWdnZXIgcGF1c2VkIik7Y29uc3Qgcz1bLi4udC5wYXJhbXMuY2FsbEZyYW1lc10saT1tbi5hcHBSb290UGF0aD9mdW5jdGlvbih0PShwcm9jZXNzLmFyZ3ZbMV0/ZW4ocHJvY2Vzcy5hcmd2WzFdKTpwcm9jZXNzLmN3ZCgpKSxuPSJcXCI9PT1vKXtjb25zdCBlPW4/ZG4odCk6dDtyZXR1cm4gdD0+e2lmKCF0KXJldHVybjtjb25zdCBvPW4/ZG4odCk6dDtsZXR7ZGlyOnMsYmFzZTppLGV4dDpjfT1yLnBhcnNlKG8pOyIuanMiIT09YyYmIi5tanMiIT09YyYmIi5janMiIT09Y3x8KGk9aS5zbGljZSgwLC0xKmMubGVuZ3RoKSk7Y29uc3QgdT1kZWNvZGVVUklDb21wb25lbnQoaSk7c3x8KHM9Ii4iKTtjb25zdCBhPXMubGFzdEluZGV4T2YoIi9ub2RlX21vZHVsZXMiKTtpZihhPi0xKXJldHVybmAke3Muc2xpY2UoYSsxNCkucmVwbGFjZSgvXC8vZywiLiIpfToke3V9YDtpZihzLnN0YXJ0c1dpdGgoZSkpe2NvbnN0IHQ9cy5zbGljZShlLmxlbmd0aCsxKS5yZXBsYWNlKC9cLy9nLCIuIik7cmV0dXJuIHQ/YCR7dH06JHt1fWA6dX1yZXR1cm4gdX19KG1uLmFwcFJvb3RQYXRoKTooKT0+e30sYz1zLm1hcCgodD0+ZnVuY3Rpb24odCxuLGUpe2NvbnN0IHI9bj9uLnJlcGxhY2UoL15maWxlOlwvXC8vLCIiKTp2b2lkIDAsbz10LmxvY2F0aW9uLmNvbHVtbk51bWJlcj90LmxvY2F0aW9uLmNvbHVtbk51bWJlcisxOnZvaWQgMCxzPXQubG9jYXRpb24ubGluZU51bWJlcj90LmxvY2F0aW9uLmxpbmVOdW1iZXIrMTp2b2lkIDA7cmV0dXJue2ZpbGVuYW1lOnIsbW9kdWxlOmUociksZnVuY3Rpb246dC5mdW5jdGlvbk5hbWV8fEV0LGNvbG5vOm8sbGluZW5vOnMsaW5fYXBwOnI/cm4ocik6dm9pZCAwfX0odCxlLmdldCh0LmxvY2F0aW9uLnNjcmlwdElkKSxpKSkpLHU9c2V0VGltZW91dCgoKCk9PntObihjKS50aGVuKG51bGwsKCgpPT57dm4oIlNlbmRpbmcgQU5SIGV2ZW50IGZhaWxlZC4iKX0pKX0pLDVlMyk7bi5wb3N0KCJSdW50aW1lLmV2YWx1YXRlIix7ZXhwcmVzc2lvbjoiZ2xvYmFsLl9fU0VOVFJZX0dFVF9TQ09QRVNfXygpOyIsc2lsZW50OiEwLHJldHVybkJ5VmFsdWU6ITB9LCgodCxlKT0+e3QmJnZuKGBFcnJvciBleGVjdXRpbmcgc2NyaXB0OiAnJHt0Lm1lc3NhZ2V9J2ApLGNsZWFyVGltZW91dCh1KTtjb25zdCByPWU/LnJlc3VsdD9lLnJlc3VsdC52YWx1ZTp2b2lkIDA7bi5wb3N0KCJEZWJ1Z2dlci5yZXN1bWUiKSxuLnBvc3QoIkRlYnVnZ2VyLmRpc2FibGUiKSxObihjLHIpLnRoZW4obnVsbCwoKCk9Pnt2bigiU2VuZGluZyBBTlIgZXZlbnQgZmFpbGVkLiIpfSkpfSkpfWNhdGNoKHQpe3Rocm93IG4ucG9zdCgiRGVidWdnZXIucmVzdW1lIiksbi5wb3N0KCJEZWJ1Z2dlci5kaXNhYmxlIiksdH19KSksQ249KCk9Pnt0cnl7bi5wb3N0KCJEZWJ1Z2dlci5lbmFibGUiLCgoKT0+e24ucG9zdCgiRGVidWdnZXIucGF1c2UiKX0pKX1jYXRjaCh0KXt9fX1jb25zdHtwb2xsOlRufT1mdW5jdGlvbih0LG4sZSxyKXtjb25zdCBvPXQoKTtsZXQgcz0hMSxpPSEwO3JldHVybiBzZXRJbnRlcnZhbCgoKCk9Pntjb25zdCB0PW8uZ2V0VGltZU1zKCk7ITE9PT1zJiZ0Pm4rZSYmKHM9ITAsaSYmcigpKSx0PG4rZSYmKHM9ITEpfSksMjApLHtwb2xsOigpPT57by5yZXNldCgpfSxlbmFibGVkOnQ9PntpPXR9fX0oKGZ1bmN0aW9uKCl7bGV0IHQ9cHJvY2Vzcy5ocnRpbWUoKTtyZXR1cm57Z2V0VGltZU1zOigpPT57Y29uc3RbbixlXT1wcm9jZXNzLmhydGltZSh0KTtyZXR1cm4gTWF0aC5mbG9vcigxZTMqbitlLzFlNil9LHJlc2V0OigpPT57dD1wcm9jZXNzLmhydGltZSgpfX19KSxtbi5wb2xsSW50ZXJ2YWwsbW4uYW5yVGhyZXNob2xkLChmdW5jdGlvbigpe3ZuKCJXYXRjaGRvZyB0aW1lb3V0IiksQ24/KHZuKCJQYXVzaW5nIGRlYnVnZ2VyIHRvIGNhcHR1cmUgc3RhY2sgdHJhY2UiKSxDbigpKToodm4oIkNhcHR1cmluZyBldmVudCB3aXRob3V0IGEgc3RhY2sgdHJhY2UiKSxObigpLnRoZW4obnVsbCwoKCk9Pnt2bigiU2VuZGluZyBBTlIgZXZlbnQgZmFpbGVkIG9uIHdhdGNoZG9nIHRpbWVvdXQuIil9KSkpfSkpO2U/Lm9uKCJtZXNzYWdlIiwodD0+e3Quc2Vzc2lvbiYmKGduPU0odC5zZXNzaW9uKSksdC5kZWJ1Z0ltYWdlcyYmKGJuPXQuZGVidWdJbWFnZXMpLFRuKCl9KSk7';
13
13
 
14
14
  const DEFAULT_INTERVAL = 50;
15
15
  const DEFAULT_HANG_THRESHOLD = 5000;
@@ -5,7 +5,9 @@ const api = require('@opentelemetry/api');
5
5
  const core = require('@opentelemetry/core');
6
6
  const instrumentation = require('@opentelemetry/instrumentation');
7
7
  const core$1 = require('@sentry/core');
8
+ const opentelemetry = require('@sentry/opentelemetry');
8
9
  const debugBuild = require('../../debug-build.js');
10
+ const baggage = require('../../utils/baggage.js');
9
11
  const getRequestUrl = require('../../utils/getRequestUrl.js');
10
12
 
11
13
  const INSTRUMENTATION_NAME = '@sentry/instrumentation-http';
@@ -27,8 +29,11 @@ const MAX_BODY_BYTE_LENGTH = 1024 * 1024;
27
29
  * https://github.com/open-telemetry/opentelemetry-js/blob/f8ab5592ddea5cba0a3b33bf8d74f27872c0367f/experimental/packages/opentelemetry-instrumentation-http/src/http.ts
28
30
  */
29
31
  class SentryHttpInstrumentation extends instrumentation.InstrumentationBase {
32
+
30
33
  constructor(config = {}) {
31
34
  super(INSTRUMENTATION_NAME, core.VERSION, config);
35
+
36
+ this._propagationDecisionMap = new core$1.LRUMap(100);
32
37
  }
33
38
 
34
39
  /** @inheritdoc */
@@ -52,6 +57,11 @@ class SentryHttpInstrumentation extends instrumentation.InstrumentationBase {
52
57
  this._onOutgoingRequestFinish(data.request, undefined);
53
58
  }) ;
54
59
 
60
+ const onHttpClientRequestCreated = ((_data) => {
61
+ const data = _data ;
62
+ this._onOutgoingRequestCreated(data.request);
63
+ }) ;
64
+
55
65
  /**
56
66
  * You may be wondering why we register these diagnostics-channel listeners
57
67
  * in such a convoluted way (as InstrumentationNodeModuleDefinition...)˝,
@@ -78,12 +88,20 @@ class SentryHttpInstrumentation extends instrumentation.InstrumentationBase {
78
88
  // In this case, `http.client.response.finish` is not triggered
79
89
  diagnosticsChannel.subscribe('http.client.request.error', onHttpClientRequestError);
80
90
 
91
+ // NOTE: This channel only exist since Node 23
92
+ // Before that, outgoing requests are not patched
93
+ // and trace headers are not propagated, sadly.
94
+ if (this.getConfig().propagateTraceInOutgoingRequests) {
95
+ diagnosticsChannel.subscribe('http.client.request.created', onHttpClientRequestCreated);
96
+ }
97
+
81
98
  return moduleExports;
82
99
  },
83
100
  () => {
84
101
  diagnosticsChannel.unsubscribe('http.server.request.start', onHttpServerRequestStart);
85
102
  diagnosticsChannel.unsubscribe('http.client.response.finish', onHttpClientResponseFinish);
86
103
  diagnosticsChannel.unsubscribe('http.client.request.error', onHttpClientRequestError);
104
+ diagnosticsChannel.unsubscribe('http.client.request.created', onHttpClientRequestCreated);
87
105
  },
88
106
  ),
89
107
  new instrumentation.InstrumentationNodeModuleDefinition(
@@ -134,6 +152,49 @@ class SentryHttpInstrumentation extends instrumentation.InstrumentationBase {
134
152
  }
135
153
  }
136
154
 
155
+ /**
156
+ * This is triggered when an outgoing request is created.
157
+ * It has access to the request object, and can mutate it before the request is sent.
158
+ */
159
+ _onOutgoingRequestCreated(request) {
160
+ const url = getRequestUrl.getRequestUrl(request);
161
+ const ignoreOutgoingRequests = this.getConfig().ignoreOutgoingRequests;
162
+ const shouldPropagate =
163
+ typeof ignoreOutgoingRequests === 'function' ? !ignoreOutgoingRequests(url, getRequestOptions(request)) : true;
164
+
165
+ if (!shouldPropagate) {
166
+ return;
167
+ }
168
+
169
+ // Manually add the trace headers, if it applies
170
+ // Note: We do not use `propagation.inject()` here, because our propagator relies on an active span
171
+ // Which we do not have in this case
172
+ const tracePropagationTargets = core$1.getClient()?.getOptions().tracePropagationTargets;
173
+ const addedHeaders = opentelemetry.shouldPropagateTraceForUrl(url, tracePropagationTargets, this._propagationDecisionMap)
174
+ ? core$1.getTraceData()
175
+ : undefined;
176
+
177
+ if (!addedHeaders) {
178
+ return;
179
+ }
180
+
181
+ const { 'sentry-trace': sentryTrace, baggage: baggage$1 } = addedHeaders;
182
+
183
+ // We do not want to overwrite existing header here, if it was already set
184
+ if (sentryTrace && !request.getHeader('sentry-trace')) {
185
+ request.setHeader('sentry-trace', sentryTrace);
186
+ core$1.logger.log(INSTRUMENTATION_NAME, 'Added sentry-trace header to outgoing request');
187
+ }
188
+
189
+ if (baggage$1) {
190
+ // For baggage, we make sure to merge this into a possibly existing header
191
+ const newBaggage = baggage.mergeBaggageHeaders(request.getHeader('baggage'), baggage$1);
192
+ if (newBaggage) {
193
+ request.setHeader('baggage', newBaggage);
194
+ }
195
+ }
196
+ }
197
+
137
198
  /**
138
199
  * Patch a server.emit function to handle process isolation for incoming requests.
139
200
  * This will only patch the emit function if it was not already patched.
@@ -1 +1 @@
1
- {"version":3,"file":"SentryHttpInstrumentation.js","sources":["../../../../src/integrations/http/SentryHttpInstrumentation.ts"],"sourcesContent":["/* eslint-disable max-lines */\nimport type { ChannelListener } from 'node:diagnostics_channel';\nimport { subscribe, unsubscribe } from 'node:diagnostics_channel';\nimport type * as http from 'node:http';\nimport type * as https from 'node:https';\nimport type { EventEmitter } from 'node:stream';\nimport { context, propagation } from '@opentelemetry/api';\nimport { VERSION } from '@opentelemetry/core';\nimport type { InstrumentationConfig } from '@opentelemetry/instrumentation';\nimport { InstrumentationBase, InstrumentationNodeModuleDefinition } from '@opentelemetry/instrumentation';\nimport type { AggregationCounts, Client, SanitizedRequestData, Scope } from '@sentry/core';\nimport {\n addBreadcrumb,\n addNonEnumerableProperty,\n generateSpanId,\n getBreadcrumbLogLevelFromHttpStatusCode,\n getClient,\n getCurrentScope,\n getIsolationScope,\n getSanitizedUrlString,\n httpRequestToRequestData,\n logger,\n parseUrl,\n stripUrlQueryAndFragment,\n withIsolationScope,\n} from '@sentry/core';\nimport { DEBUG_BUILD } from '../../debug-build';\nimport { getRequestUrl } from '../../utils/getRequestUrl';\n\nconst INSTRUMENTATION_NAME = '@sentry/instrumentation-http';\n\ntype Http = typeof http;\ntype Https = typeof https;\n\nexport type SentryHttpInstrumentationOptions = InstrumentationConfig & {\n /**\n * Whether breadcrumbs should be recorded for requests.\n *\n * @default `true`\n */\n breadcrumbs?: boolean;\n\n /**\n * Whether to extract the trace ID from the `sentry-trace` header for incoming requests.\n * By default this is done by the HttpInstrumentation, but if that is not added (e.g. because tracing is disabled, ...)\n * then this instrumentation can take over.\n *\n * @default `false`\n */\n extractIncomingTraceFromHeader?: 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: http.RequestOptions) => boolean;\n\n /**\n * Do not capture the request body for incoming HTTP requests to URLs where the given callback returns `true`.\n * This can be useful for long running requests where the body is not needed and we want to avoid capturing it.\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 ignoreIncomingRequestBody?: (url: string, request: http.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 public constructor(config: SentryHttpInstrumentationOptions = {}) {\n super(INSTRUMENTATION_NAME, VERSION, config);\n }\n\n /** @inheritdoc */\n public init(): [InstrumentationNodeModuleDefinition, InstrumentationNodeModuleDefinition] {\n // We register handlers when either http or https is instrumented\n // but we only want to register them once, whichever is loaded first\n let hasRegisteredHandlers = false;\n\n const onHttpServerRequestStart = ((_data: unknown) => {\n const data = _data as { server: http.Server };\n this._patchServerEmitOnce(data.server);\n }) satisfies ChannelListener;\n\n const onHttpClientResponseFinish = ((_data: unknown) => {\n const data = _data as { request: http.ClientRequest; response: http.IncomingMessage };\n this._onOutgoingRequestFinish(data.request, data.response);\n }) satisfies ChannelListener;\n\n const onHttpClientRequestError = ((_data: unknown) => {\n const data = _data as { request: http.ClientRequest };\n this._onOutgoingRequestFinish(data.request, undefined);\n }) satisfies ChannelListener;\n\n /**\n * You may be wondering why we register these diagnostics-channel listeners\n * in such a convoluted way (as InstrumentationNodeModuleDefinition...)˝,\n * instead of simply subscribing to the events once in here.\n * The reason for this is timing semantics: These functions are called once the http or https module is loaded.\n * If we'd subscribe before that, there seem to be conflicts with the OTEL native instrumentation in some scenarios,\n * especially the \"import-on-top\" pattern of setting up ESM applications.\n */\n return [\n new InstrumentationNodeModuleDefinition(\n 'http',\n ['*'],\n (moduleExports: Http): Http => {\n if (hasRegisteredHandlers) {\n return moduleExports;\n }\n\n hasRegisteredHandlers = true;\n\n subscribe('http.server.request.start', onHttpServerRequestStart);\n subscribe('http.client.response.finish', onHttpClientResponseFinish);\n\n // When an error happens, we still want to have a breadcrumb\n // In this case, `http.client.response.finish` is not triggered\n subscribe('http.client.request.error', onHttpClientRequestError);\n\n return moduleExports;\n },\n () => {\n unsubscribe('http.server.request.start', onHttpServerRequestStart);\n unsubscribe('http.client.response.finish', onHttpClientResponseFinish);\n unsubscribe('http.client.request.error', onHttpClientRequestError);\n },\n ),\n new InstrumentationNodeModuleDefinition(\n 'https',\n ['*'],\n (moduleExports: Https): Https => {\n if (hasRegisteredHandlers) {\n return moduleExports;\n }\n\n hasRegisteredHandlers = true;\n\n subscribe('http.server.request.start', onHttpServerRequestStart);\n subscribe('http.client.response.finish', onHttpClientResponseFinish);\n\n // When an error happens, we still want to have a breadcrumb\n // In this case, `http.client.response.finish` is not triggered\n subscribe('http.client.request.error', onHttpClientRequestError);\n\n return moduleExports;\n },\n () => {\n unsubscribe('http.server.request.start', onHttpServerRequestStart);\n unsubscribe('http.client.response.finish', onHttpClientResponseFinish);\n unsubscribe('http.client.request.error', onHttpClientRequestError);\n },\n ),\n ];\n }\n\n /**\n * This is triggered when an outgoing request finishes.\n * It has access to the final request and response objects.\n */\n private _onOutgoingRequestFinish(request: http.ClientRequest, response?: http.IncomingMessage): void {\n DEBUG_BUILD && logger.log(INSTRUMENTATION_NAME, 'Handling finished outgoing request');\n\n const _breadcrumbs = this.getConfig().breadcrumbs;\n const breadCrumbsEnabled = typeof _breadcrumbs === 'undefined' ? true : _breadcrumbs;\n const options = getRequestOptions(request);\n\n const _ignoreOutgoingRequests = this.getConfig().ignoreOutgoingRequests;\n const shouldCreateBreadcrumb =\n typeof _ignoreOutgoingRequests === 'function' ? !_ignoreOutgoingRequests(getRequestUrl(request), options) : true;\n\n if (breadCrumbsEnabled && shouldCreateBreadcrumb) {\n addRequestBreadcrumb(request, response);\n }\n }\n\n /**\n * Patch a server.emit function to handle process isolation for incoming requests.\n * This will only patch the emit function if it was not already patched.\n */\n private _patchServerEmitOnce(server: http.Server): void {\n // eslint-disable-next-line @typescript-eslint/unbound-method\n const originalEmit = server.emit;\n\n // This means it was already patched, do nothing\n if ((originalEmit as { __sentry_patched__?: boolean }).__sentry_patched__) {\n return;\n }\n\n DEBUG_BUILD && logger.log(INSTRUMENTATION_NAME, 'Patching server.emit');\n\n // eslint-disable-next-line @typescript-eslint/no-this-alias\n const instrumentation = this;\n const { ignoreIncomingRequestBody } = instrumentation.getConfig();\n\n const newEmit = new Proxy(originalEmit, {\n apply(target, thisArg, args: [event: string, ...args: unknown[]]) {\n // Only traces request events\n if (args[0] !== 'request') {\n return target.apply(thisArg, args);\n }\n\n DEBUG_BUILD && logger.log(INSTRUMENTATION_NAME, 'Handling incoming request');\n\n const isolationScope = getIsolationScope().clone();\n const request = args[1] as http.IncomingMessage;\n const response = args[2] 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 const url = request.url || '/';\n if (!ignoreIncomingRequestBody?.(url, request)) {\n patchRequestToCaptureBody(request, isolationScope);\n }\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(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 // Set a new propagationSpanId for this request\n // We rely on the fact that `withIsolationScope()` will implicitly also fork the current scope\n // This way we can save an \"unnecessary\" `withScope()` invocation\n getCurrentScope().getPropagationContext().propagationSpanId = generateSpanId();\n\n // If we don't want to extract the trace from the header, we can skip this\n if (!instrumentation.getConfig().extractIncomingTraceFromHeader) {\n return target.apply(thisArg, args);\n }\n\n const ctx = propagation.extract(context.active(), normalizedRequest.headers);\n return context.with(ctx, () => {\n return target.apply(thisArg, args);\n });\n });\n },\n });\n\n addNonEnumerableProperty(newEmit, '__sentry_patched__', true);\n\n server.emit = newEmit;\n }\n}\n\n/** Add a breadcrumb for outgoing requests. */\nfunction addRequestBreadcrumb(request: http.ClientRequest, response: http.IncomingMessage | undefined): 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: http.IncomingMessage, isolationScope: Scope): void {\n let bodyByteLength = 0;\n const chunks: Buffer[] = [];\n\n DEBUG_BUILD && logger.log(INSTRUMENTATION_NAME, 'Patching request.on');\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 DEBUG_BUILD && logger.log(INSTRUMENTATION_NAME, 'Handling request.on(\"data\")');\n const callback = new Proxy(listener, {\n apply: (target, thisArg, args: Parameters<typeof listener>) => {\n try {\n const chunk = args[0] as Buffer | string;\n const bufferifiedChunk = Buffer.from(chunk);\n\n if (bodyByteLength < MAX_BODY_BYTE_LENGTH) {\n chunks.push(bufferifiedChunk);\n bodyByteLength += bufferifiedChunk.byteLength;\n } else if (DEBUG_BUILD) {\n logger.log(\n INSTRUMENTATION_NAME,\n `Dropping request body chunk because maximum body length of ${MAX_BODY_BYTE_LENGTH}b is exceeded.`,\n );\n }\n } catch (err) {\n DEBUG_BUILD && logger.error(INSTRUMENTATION_NAME, 'Encountered error while storing body chunk.');\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\n req.on('end', () => {\n try {\n const body = Buffer.concat(chunks).toString('utf-8');\n if (body) {\n isolationScope.setSDKProcessingMetadata({ normalizedRequest: { data: body } });\n }\n } catch (error) {\n if (DEBUG_BUILD) {\n logger.error(INSTRUMENTATION_NAME, 'Error building captured request body', error);\n }\n }\n });\n } catch (error) {\n if (DEBUG_BUILD) {\n logger.error(INSTRUMENTATION_NAME, 'Error patching request to capture body', error);\n }\n }\n}\n\nfunction getRequestOptions(request: http.ClientRequest): http.RequestOptions {\n return {\n method: request.method,\n protocol: request.protocol,\n host: request.host,\n hostname: request.host,\n path: request.path,\n headers: request.getHeaders(),\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}: {\n requestIsolationScope: Scope;\n response: EventEmitter;\n sessionFlushingDelayMS?: number;\n}): 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"],"names":["InstrumentationBase","VERSION","InstrumentationNodeModuleDefinition","subscribe","unsubscribe","DEBUG_BUILD","logger","getRequestUrl","getIsolationScope","httpRequestToRequestData","stripUrlQueryAndFragment","withIsolationScope","getCurrentScope","generateSpanId","propagation","context","addNonEnumerableProperty","getBreadcrumbLogLevelFromHttpStatusCode","addBreadcrumb","parseUrl","getSanitizedUrlString","getClient"],"mappings":"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"}
1
+ {"version":3,"file":"SentryHttpInstrumentation.js","sources":["../../../../src/integrations/http/SentryHttpInstrumentation.ts"],"sourcesContent":["/* eslint-disable max-lines */\nimport type { ChannelListener } from 'node:diagnostics_channel';\nimport { subscribe, unsubscribe } from 'node:diagnostics_channel';\nimport type * as http from 'node:http';\nimport type * as https from 'node:https';\nimport type { EventEmitter } from 'node:stream';\nimport { context, propagation } from '@opentelemetry/api';\nimport { VERSION } from '@opentelemetry/core';\nimport type { InstrumentationConfig } from '@opentelemetry/instrumentation';\nimport { InstrumentationBase, InstrumentationNodeModuleDefinition } from '@opentelemetry/instrumentation';\nimport type { AggregationCounts, Client, SanitizedRequestData, Scope } from '@sentry/core';\nimport {\n addBreadcrumb,\n addNonEnumerableProperty,\n generateSpanId,\n getBreadcrumbLogLevelFromHttpStatusCode,\n getClient,\n getCurrentScope,\n getIsolationScope,\n getSanitizedUrlString,\n getTraceData,\n httpRequestToRequestData,\n logger,\n LRUMap,\n parseUrl,\n stripUrlQueryAndFragment,\n withIsolationScope,\n} from '@sentry/core';\nimport { shouldPropagateTraceForUrl } from '@sentry/opentelemetry';\nimport { DEBUG_BUILD } from '../../debug-build';\nimport { mergeBaggageHeaders } from '../../utils/baggage';\nimport { getRequestUrl } from '../../utils/getRequestUrl';\n\nconst INSTRUMENTATION_NAME = '@sentry/instrumentation-http';\n\ntype Http = typeof http;\ntype Https = typeof https;\n\nexport type SentryHttpInstrumentationOptions = InstrumentationConfig & {\n /**\n * Whether breadcrumbs should be recorded for requests.\n *\n * @default `true`\n */\n breadcrumbs?: boolean;\n\n /**\n * Whether to extract the trace ID from the `sentry-trace` header for incoming requests.\n * By default this is done by the HttpInstrumentation, but if that is not added (e.g. because tracing is disabled, ...)\n * then this instrumentation can take over.\n *\n * @default `false`\n */\n extractIncomingTraceFromHeader?: boolean;\n\n /**\n * Whether to propagate Sentry trace headers in outgoing requests.\n * By default this is done by the HttpInstrumentation, but if that is not added (e.g. because tracing is disabled)\n * then this instrumentation can take over.\n *\n * @default `false`\n */\n propagateTraceInOutgoingRequests?: 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: http.RequestOptions) => boolean;\n\n /**\n * Do not capture the request body for incoming HTTP requests to URLs where the given callback returns `true`.\n * This can be useful for long running requests where the body is not needed and we want to avoid capturing it.\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 ignoreIncomingRequestBody?: (url: string, request: http.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(INSTRUMENTATION_NAME, VERSION, config);\n\n this._propagationDecisionMap = new LRUMap<string, boolean>(100);\n }\n\n /** @inheritdoc */\n public init(): [InstrumentationNodeModuleDefinition, InstrumentationNodeModuleDefinition] {\n // We register handlers when either http or https is instrumented\n // but we only want to register them once, whichever is loaded first\n let hasRegisteredHandlers = false;\n\n const onHttpServerRequestStart = ((_data: unknown) => {\n const data = _data as { server: http.Server };\n this._patchServerEmitOnce(data.server);\n }) satisfies ChannelListener;\n\n const onHttpClientResponseFinish = ((_data: unknown) => {\n const data = _data as { request: http.ClientRequest; response: http.IncomingMessage };\n this._onOutgoingRequestFinish(data.request, data.response);\n }) satisfies ChannelListener;\n\n const onHttpClientRequestError = ((_data: unknown) => {\n const data = _data as { request: http.ClientRequest };\n this._onOutgoingRequestFinish(data.request, undefined);\n }) satisfies ChannelListener;\n\n const onHttpClientRequestCreated = ((_data: unknown) => {\n const data = _data as { request: http.ClientRequest };\n this._onOutgoingRequestCreated(data.request);\n }) satisfies ChannelListener;\n\n /**\n * You may be wondering why we register these diagnostics-channel listeners\n * in such a convoluted way (as InstrumentationNodeModuleDefinition...)˝,\n * instead of simply subscribing to the events once in here.\n * The reason for this is timing semantics: These functions are called once the http or https module is loaded.\n * If we'd subscribe before that, there seem to be conflicts with the OTEL native instrumentation in some scenarios,\n * especially the \"import-on-top\" pattern of setting up ESM applications.\n */\n return [\n new InstrumentationNodeModuleDefinition(\n 'http',\n ['*'],\n (moduleExports: Http): Http => {\n if (hasRegisteredHandlers) {\n return moduleExports;\n }\n\n hasRegisteredHandlers = true;\n\n subscribe('http.server.request.start', onHttpServerRequestStart);\n subscribe('http.client.response.finish', onHttpClientResponseFinish);\n\n // When an error happens, we still want to have a breadcrumb\n // In this case, `http.client.response.finish` is not triggered\n subscribe('http.client.request.error', onHttpClientRequestError);\n\n // NOTE: This channel only exist since Node 23\n // Before that, outgoing requests are not patched\n // and trace headers are not propagated, sadly.\n if (this.getConfig().propagateTraceInOutgoingRequests) {\n subscribe('http.client.request.created', onHttpClientRequestCreated);\n }\n\n return moduleExports;\n },\n () => {\n unsubscribe('http.server.request.start', onHttpServerRequestStart);\n unsubscribe('http.client.response.finish', onHttpClientResponseFinish);\n unsubscribe('http.client.request.error', onHttpClientRequestError);\n unsubscribe('http.client.request.created', onHttpClientRequestCreated);\n },\n ),\n new InstrumentationNodeModuleDefinition(\n 'https',\n ['*'],\n (moduleExports: Https): Https => {\n if (hasRegisteredHandlers) {\n return moduleExports;\n }\n\n hasRegisteredHandlers = true;\n\n subscribe('http.server.request.start', onHttpServerRequestStart);\n subscribe('http.client.response.finish', onHttpClientResponseFinish);\n\n // When an error happens, we still want to have a breadcrumb\n // In this case, `http.client.response.finish` is not triggered\n subscribe('http.client.request.error', onHttpClientRequestError);\n\n return moduleExports;\n },\n () => {\n unsubscribe('http.server.request.start', onHttpServerRequestStart);\n unsubscribe('http.client.response.finish', onHttpClientResponseFinish);\n unsubscribe('http.client.request.error', onHttpClientRequestError);\n },\n ),\n ];\n }\n\n /**\n * This is triggered when an outgoing request finishes.\n * It has access to the final request and response objects.\n */\n private _onOutgoingRequestFinish(request: http.ClientRequest, response?: http.IncomingMessage): void {\n DEBUG_BUILD && logger.log(INSTRUMENTATION_NAME, 'Handling finished outgoing request');\n\n const _breadcrumbs = this.getConfig().breadcrumbs;\n const breadCrumbsEnabled = typeof _breadcrumbs === 'undefined' ? true : _breadcrumbs;\n const options = getRequestOptions(request);\n\n const _ignoreOutgoingRequests = this.getConfig().ignoreOutgoingRequests;\n const shouldCreateBreadcrumb =\n typeof _ignoreOutgoingRequests === 'function' ? !_ignoreOutgoingRequests(getRequestUrl(request), options) : true;\n\n if (breadCrumbsEnabled && shouldCreateBreadcrumb) {\n addRequestBreadcrumb(request, response);\n }\n }\n\n /**\n * This is triggered when an outgoing request is created.\n * It has access to the request object, and can mutate it before the request is sent.\n */\n private _onOutgoingRequestCreated(request: http.ClientRequest): void {\n const url = getRequestUrl(request);\n const ignoreOutgoingRequests = this.getConfig().ignoreOutgoingRequests;\n const shouldPropagate =\n typeof ignoreOutgoingRequests === 'function' ? !ignoreOutgoingRequests(url, getRequestOptions(request)) : true;\n\n if (!shouldPropagate) {\n return;\n }\n\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, this._propagationDecisionMap)\n ? getTraceData()\n : undefined;\n\n if (!addedHeaders) {\n return;\n }\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 && !request.getHeader('sentry-trace')) {\n request.setHeader('sentry-trace', sentryTrace);\n logger.log(INSTRUMENTATION_NAME, 'Added sentry-trace header to outgoing request');\n }\n\n if (baggage) {\n // For baggage, we make sure to merge this into a possibly existing header\n const newBaggage = mergeBaggageHeaders(request.getHeader('baggage'), baggage);\n if (newBaggage) {\n request.setHeader('baggage', newBaggage);\n }\n }\n }\n\n /**\n * Patch a server.emit function to handle process isolation for incoming requests.\n * This will only patch the emit function if it was not already patched.\n */\n private _patchServerEmitOnce(server: http.Server): void {\n // eslint-disable-next-line @typescript-eslint/unbound-method\n const originalEmit = server.emit;\n\n // This means it was already patched, do nothing\n if ((originalEmit as { __sentry_patched__?: boolean }).__sentry_patched__) {\n return;\n }\n\n DEBUG_BUILD && logger.log(INSTRUMENTATION_NAME, 'Patching server.emit');\n\n // eslint-disable-next-line @typescript-eslint/no-this-alias\n const instrumentation = this;\n const { ignoreIncomingRequestBody } = instrumentation.getConfig();\n\n const newEmit = new Proxy(originalEmit, {\n apply(target, thisArg, args: [event: string, ...args: unknown[]]) {\n // Only traces request events\n if (args[0] !== 'request') {\n return target.apply(thisArg, args);\n }\n\n DEBUG_BUILD && logger.log(INSTRUMENTATION_NAME, 'Handling incoming request');\n\n const isolationScope = getIsolationScope().clone();\n const request = args[1] as http.IncomingMessage;\n const response = args[2] 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 const url = request.url || '/';\n if (!ignoreIncomingRequestBody?.(url, request)) {\n patchRequestToCaptureBody(request, isolationScope);\n }\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(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 // Set a new propagationSpanId for this request\n // We rely on the fact that `withIsolationScope()` will implicitly also fork the current scope\n // This way we can save an \"unnecessary\" `withScope()` invocation\n getCurrentScope().getPropagationContext().propagationSpanId = generateSpanId();\n\n // If we don't want to extract the trace from the header, we can skip this\n if (!instrumentation.getConfig().extractIncomingTraceFromHeader) {\n return target.apply(thisArg, args);\n }\n\n const ctx = propagation.extract(context.active(), normalizedRequest.headers);\n return context.with(ctx, () => {\n return target.apply(thisArg, args);\n });\n });\n },\n });\n\n addNonEnumerableProperty(newEmit, '__sentry_patched__', true);\n\n server.emit = newEmit;\n }\n}\n\n/** Add a breadcrumb for outgoing requests. */\nfunction addRequestBreadcrumb(request: http.ClientRequest, response: http.IncomingMessage | undefined): 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: http.IncomingMessage, isolationScope: Scope): void {\n let bodyByteLength = 0;\n const chunks: Buffer[] = [];\n\n DEBUG_BUILD && logger.log(INSTRUMENTATION_NAME, 'Patching request.on');\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 DEBUG_BUILD && logger.log(INSTRUMENTATION_NAME, 'Handling request.on(\"data\")');\n const callback = new Proxy(listener, {\n apply: (target, thisArg, args: Parameters<typeof listener>) => {\n try {\n const chunk = args[0] as Buffer | string;\n const bufferifiedChunk = Buffer.from(chunk);\n\n if (bodyByteLength < MAX_BODY_BYTE_LENGTH) {\n chunks.push(bufferifiedChunk);\n bodyByteLength += bufferifiedChunk.byteLength;\n } else if (DEBUG_BUILD) {\n logger.log(\n INSTRUMENTATION_NAME,\n `Dropping request body chunk because maximum body length of ${MAX_BODY_BYTE_LENGTH}b is exceeded.`,\n );\n }\n } catch (err) {\n DEBUG_BUILD && logger.error(INSTRUMENTATION_NAME, 'Encountered error while storing body chunk.');\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\n req.on('end', () => {\n try {\n const body = Buffer.concat(chunks).toString('utf-8');\n if (body) {\n isolationScope.setSDKProcessingMetadata({ normalizedRequest: { data: body } });\n }\n } catch (error) {\n if (DEBUG_BUILD) {\n logger.error(INSTRUMENTATION_NAME, 'Error building captured request body', error);\n }\n }\n });\n } catch (error) {\n if (DEBUG_BUILD) {\n logger.error(INSTRUMENTATION_NAME, 'Error patching request to capture body', error);\n }\n }\n}\n\nfunction getRequestOptions(request: http.ClientRequest): http.RequestOptions {\n return {\n method: request.method,\n protocol: request.protocol,\n host: request.host,\n hostname: request.host,\n path: request.path,\n headers: request.getHeaders(),\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}: {\n requestIsolationScope: Scope;\n response: EventEmitter;\n sessionFlushingDelayMS?: number;\n}): 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"],"names":["InstrumentationBase","VERSION","LRUMap","InstrumentationNodeModuleDefinition","subscribe","unsubscribe","DEBUG_BUILD","logger","getRequestUrl","getClient","shouldPropagateTraceForUrl","getTraceData","baggage","mergeBaggageHeaders","getIsolationScope","httpRequestToRequestData","stripUrlQueryAndFragment","withIsolationScope","getCurrentScope","generateSpanId","propagation","context","addNonEnumerableProperty","getBreadcrumbLogLevelFromHttpStatusCode","addBreadcrumb","parseUrl","getSanitizedUrlString"],"mappings":"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"}
@@ -61,6 +61,9 @@ const httpIntegration = core.defineIntegration((options = {}) => {
61
61
  // If spans are not instrumented, it means the HttpInstrumentation has not been added
62
62
  // In that case, we want to handle incoming trace extraction ourselves
63
63
  extractIncomingTraceFromHeader: !instrumentSpans,
64
+ // If spans are not instrumented, it means the HttpInstrumentation has not been added
65
+ // In that case, we want to handle trace propagation ourselves
66
+ propagateTraceInOutgoingRequests: !instrumentSpans,
64
67
  });
65
68
 
66
69
  // This is the "regular" OTEL instrumentation that emits spans