@sentry/node 11.0.0-alpha.1 → 11.0.0-beta.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.
- package/README.md +19 -0
- package/build/cjs/bundler-plugin/esbuild.js.map +1 -1
- package/build/cjs/bundler-plugin/rollup.js.map +1 -1
- package/build/cjs/bundler-plugin/vite.js.map +1 -1
- package/build/cjs/bundler-plugin/webpack.js.map +1 -1
- package/build/cjs/index.js +56 -56
- package/build/cjs/integrations/anr/index.js +1 -1
- package/build/cjs/integrations/childProcess.js +0 -24
- package/build/cjs/integrations/childProcess.js.map +1 -1
- package/build/cjs/integrations/fs/vendored/instrumentation.js +4 -2
- package/build/cjs/integrations/fs/vendored/instrumentation.js.map +1 -1
- package/build/cjs/integrations/http/SentryHttpInstrumentation.js +7 -12
- package/build/cjs/integrations/http/SentryHttpInstrumentation.js.map +1 -1
- package/build/cjs/integrations/http/httpServerIntegration.js +4 -3
- package/build/cjs/integrations/http/httpServerIntegration.js.map +1 -1
- package/build/cjs/integrations/http/httpServerSpansIntegration.js +38 -92
- package/build/cjs/integrations/http/httpServerSpansIntegration.js.map +1 -1
- package/build/cjs/integrations/http/index.js +16 -30
- package/build/cjs/integrations/http/index.js.map +1 -1
- package/build/cjs/integrations/local-variables/local-variables-async.js +1 -1
- package/build/cjs/integrations/node-fetch/undici-instrumentation.js +15 -7
- package/build/cjs/integrations/node-fetch/undici-instrumentation.js.map +1 -1
- package/build/cjs/integrations/nodeRuntimeMetrics.js +2 -1
- package/build/cjs/integrations/nodeRuntimeMetrics.js.map +1 -1
- package/build/cjs/integrations/onunhandledrejection.js +5 -3
- package/build/cjs/integrations/onunhandledrejection.js.map +1 -1
- package/build/cjs/integrations/pino.js +2 -3
- package/build/cjs/integrations/pino.js.map +1 -1
- package/build/cjs/integrations/processSession.js +1 -1
- package/build/cjs/integrations/processSession.js.map +1 -1
- package/build/cjs/integrations/tracing/hapi.js +10 -0
- package/build/cjs/integrations/tracing/hapi.js.map +1 -0
- package/build/cjs/integrations/tracing/index.js +1 -34
- package/build/cjs/integrations/tracing/index.js.map +1 -1
- package/build/cjs/integrations/tracing/koa.js +10 -0
- package/build/cjs/integrations/tracing/koa.js.map +1 -0
- package/build/cjs/integrations/workerThreads.js +35 -0
- package/build/cjs/integrations/workerThreads.js.map +1 -0
- package/build/cjs/sdk/api.js +2 -1
- package/build/cjs/sdk/api.js.map +1 -1
- package/build/cjs/sdk/client.js +25 -14
- package/build/cjs/sdk/client.js.map +1 -1
- package/build/cjs/sdk/index.js +17 -30
- package/build/cjs/sdk/index.js.map +1 -1
- package/build/cjs/transports/http.js +10 -3
- package/build/cjs/transports/http.js.map +1 -1
- package/build/cjs/utils/outgoingFetchRequest.js +1 -1
- package/build/cjs/utils/outgoingFetchRequest.js.map +1 -1
- package/build/esm/bundler-plugin/esbuild.js.map +1 -1
- package/build/esm/bundler-plugin/rollup.js.map +1 -1
- package/build/esm/bundler-plugin/vite.js.map +1 -1
- package/build/esm/bundler-plugin/webpack.js.map +1 -1
- package/build/esm/index.js +7 -8
- package/build/esm/index.js.map +1 -1
- package/build/esm/integrations/anr/index.js +1 -1
- package/build/esm/integrations/anr/worker-script.js +2 -2
- package/build/esm/integrations/childProcess.js +1 -25
- package/build/esm/integrations/childProcess.js.map +1 -1
- package/build/esm/integrations/fs/vendored/instrumentation.js +4 -2
- package/build/esm/integrations/fs/vendored/instrumentation.js.map +1 -1
- package/build/esm/integrations/http/SentryHttpInstrumentation.js +5 -10
- package/build/esm/integrations/http/SentryHttpInstrumentation.js.map +1 -1
- package/build/esm/integrations/http/httpServerIntegration.js +3 -2
- package/build/esm/integrations/http/httpServerIntegration.js.map +1 -1
- package/build/esm/integrations/http/httpServerSpansIntegration.js +40 -94
- package/build/esm/integrations/http/httpServerSpansIntegration.js.map +1 -1
- package/build/esm/integrations/http/index.js +15 -29
- package/build/esm/integrations/http/index.js.map +1 -1
- package/build/esm/integrations/local-variables/local-variables-async.js +1 -1
- package/build/esm/integrations/local-variables/worker-script.js +1 -1
- package/build/esm/integrations/node-fetch/undici-instrumentation.js +17 -9
- package/build/esm/integrations/node-fetch/undici-instrumentation.js.map +1 -1
- package/build/esm/integrations/nodeRuntimeMetrics.js +2 -1
- package/build/esm/integrations/nodeRuntimeMetrics.js.map +1 -1
- package/build/esm/integrations/onunhandledrejection.js +5 -3
- package/build/esm/integrations/onunhandledrejection.js.map +1 -1
- package/build/esm/integrations/pino.js +2 -3
- package/build/esm/integrations/pino.js.map +1 -1
- package/build/esm/integrations/processSession.js +1 -1
- package/build/esm/integrations/processSession.js.map +1 -1
- package/build/esm/integrations/tracing/hapi.js +8 -0
- package/build/esm/integrations/tracing/hapi.js.map +1 -0
- package/build/esm/integrations/tracing/index.js +2 -35
- package/build/esm/integrations/tracing/index.js.map +1 -1
- package/build/esm/integrations/tracing/koa.js +8 -0
- package/build/esm/integrations/tracing/koa.js.map +1 -0
- package/build/esm/integrations/workerThreads.js +33 -0
- package/build/esm/integrations/workerThreads.js.map +1 -0
- package/build/esm/package.json +1 -1
- package/build/esm/sdk/api.js +2 -1
- package/build/esm/sdk/api.js.map +1 -1
- package/build/esm/sdk/client.js +25 -14
- package/build/esm/sdk/client.js.map +1 -1
- package/build/esm/sdk/index.js +11 -24
- package/build/esm/sdk/index.js.map +1 -1
- package/build/esm/transports/http.js +10 -3
- package/build/esm/transports/http.js.map +1 -1
- package/build/esm/utils/outgoingFetchRequest.js +2 -2
- package/build/esm/utils/outgoingFetchRequest.js.map +1 -1
- package/build/import-hook.mjs +1 -1
- package/build/types/bundler-plugin/esbuild.d.ts +3 -4
- package/build/types/bundler-plugin/esbuild.d.ts.map +1 -1
- package/build/types/bundler-plugin/rollup.d.ts +3 -4
- package/build/types/bundler-plugin/rollup.d.ts.map +1 -1
- package/build/types/bundler-plugin/vite.d.ts +3 -4
- package/build/types/bundler-plugin/vite.d.ts.map +1 -1
- package/build/types/bundler-plugin/webpack.d.ts +2 -2
- package/build/types/bundler-plugin/webpack.d.ts.map +1 -1
- package/build/types/index.d.ts +7 -6
- package/build/types/index.d.ts.map +1 -1
- package/build/types/integrations/childProcess.d.ts +2 -7
- package/build/types/integrations/childProcess.d.ts.map +1 -1
- package/build/types/integrations/fs/vendored/instrumentation.d.ts.map +1 -1
- package/build/types/integrations/http/SentryHttpInstrumentation.d.ts +8 -62
- package/build/types/integrations/http/SentryHttpInstrumentation.d.ts.map +1 -1
- package/build/types/integrations/http/httpServerIntegration.d.ts +4 -3
- package/build/types/integrations/http/httpServerIntegration.d.ts.map +1 -1
- package/build/types/integrations/http/httpServerSpansIntegration.d.ts +2 -9
- package/build/types/integrations/http/httpServerSpansIntegration.d.ts.map +1 -1
- package/build/types/integrations/http/index.d.ts +16 -74
- package/build/types/integrations/http/index.d.ts.map +1 -1
- package/build/types/integrations/node-fetch/undici-instrumentation.d.ts.map +1 -1
- package/build/types/integrations/nodeRuntimeMetrics.d.ts.map +1 -1
- package/build/types/integrations/pino.d.ts.map +1 -1
- package/build/types/integrations/tracing/hapi.d.ts +13 -0
- package/build/types/integrations/tracing/hapi.d.ts.map +1 -0
- package/build/types/integrations/tracing/index.d.ts.map +1 -1
- package/build/types/integrations/tracing/koa.d.ts +27 -0
- package/build/types/integrations/tracing/koa.d.ts.map +1 -0
- package/build/types/integrations/workerThreads.d.ts +8 -0
- package/build/types/integrations/workerThreads.d.ts.map +1 -0
- package/build/types/sdk/api.d.ts.map +1 -1
- package/build/types/sdk/client.d.ts +3 -1
- package/build/types/sdk/client.d.ts.map +1 -1
- package/build/types/sdk/index.d.ts.map +1 -1
- package/build/types/transports/http.d.ts +1 -1
- package/build/types/transports/http.d.ts.map +1 -1
- package/build/types/types.d.ts +13 -1
- package/build/types/types.d.ts.map +1 -1
- package/package.json +8 -6
- package/build/cjs/integrations/tracing/express.js +0 -11
- package/build/cjs/integrations/tracing/express.js.map +0 -1
- package/build/cjs/integrations/tracing/fastify/index.js +0 -40
- package/build/cjs/integrations/tracing/fastify/index.js.map +0 -1
- package/build/cjs/integrations/tracing/hapi/index.js +0 -44
- package/build/cjs/integrations/tracing/hapi/index.js.map +0 -1
- package/build/cjs/integrations/tracing/koa/index.js +0 -22
- package/build/cjs/integrations/tracing/koa/index.js.map +0 -1
- package/build/cjs/integrations/tracing/redis/cache.js +0 -43
- package/build/cjs/integrations/tracing/redis/cache.js.map +0 -1
- package/build/cjs/integrations/tracing/redis/index.js +0 -34
- package/build/cjs/integrations/tracing/redis/index.js.map +0 -1
- package/build/cjs/utils/redisCache.js +0 -98
- package/build/cjs/utils/redisCache.js.map +0 -1
- package/build/esm/integrations/tracing/express.js +0 -9
- package/build/esm/integrations/tracing/express.js.map +0 -1
- package/build/esm/integrations/tracing/fastify/index.js +0 -37
- package/build/esm/integrations/tracing/fastify/index.js.map +0 -1
- package/build/esm/integrations/tracing/hapi/index.js +0 -41
- package/build/esm/integrations/tracing/hapi/index.js.map +0 -1
- package/build/esm/integrations/tracing/koa/index.js +0 -20
- package/build/esm/integrations/tracing/koa/index.js.map +0 -1
- package/build/esm/integrations/tracing/redis/cache.js +0 -40
- package/build/esm/integrations/tracing/redis/cache.js.map +0 -1
- package/build/esm/integrations/tracing/redis/index.js +0 -28
- package/build/esm/integrations/tracing/redis/index.js.map +0 -1
- package/build/esm/utils/redisCache.js +0 -89
- package/build/esm/utils/redisCache.js.map +0 -1
- package/build/types/integrations/tracing/express.d.ts +0 -6
- package/build/types/integrations/tracing/express.d.ts.map +0 -1
- package/build/types/integrations/tracing/fastify/index.d.ts +0 -115
- package/build/types/integrations/tracing/fastify/index.d.ts.map +0 -1
- package/build/types/integrations/tracing/fastify/types.d.ts +0 -33
- package/build/types/integrations/tracing/fastify/types.d.ts.map +0 -1
- package/build/types/integrations/tracing/hapi/index.d.ts +0 -29
- package/build/types/integrations/tracing/hapi/index.d.ts.map +0 -1
- package/build/types/integrations/tracing/hapi/types.d.ts +0 -166
- package/build/types/integrations/tracing/hapi/types.d.ts.map +0 -1
- package/build/types/integrations/tracing/koa/index.d.ts +0 -26
- package/build/types/integrations/tracing/koa/index.d.ts.map +0 -1
- package/build/types/integrations/tracing/redis/cache.d.ts +0 -22
- package/build/types/integrations/tracing/redis/cache.d.ts.map +0 -1
- package/build/types/integrations/tracing/redis/index.d.ts +0 -21
- package/build/types/integrations/tracing/redis/index.d.ts.map +0 -1
- package/build/types/integrations/tracing/redis/vendored/types.d.ts +0 -9
- package/build/types/integrations/tracing/redis/vendored/types.d.ts.map +0 -1
- package/build/types/utils/redisCache.d.ts +0 -17
- package/build/types/utils/redisCache.d.ts.map +0 -1
package/README.md
CHANGED
|
@@ -72,6 +72,25 @@ If it is not possible for you to pass the `--import` flag to the Node.js binary,
|
|
|
72
72
|
NODE_OPTIONS="--import ./instrument.mjs" npm run start
|
|
73
73
|
```
|
|
74
74
|
|
|
75
|
+
### Bundling your server
|
|
76
|
+
|
|
77
|
+
`@sentry/node` installs its automatic (diagnostics-channel) instrumentation through a runtime module
|
|
78
|
+
hook that ships in `@sentry/server-runtime-injection` and is designed to run from `node_modules`. There are two
|
|
79
|
+
supported ways to keep auto-instrumentation working when you bundle your server:
|
|
80
|
+
|
|
81
|
+
1. **Keep `@sentry/server-runtime-injection` external** (do not inline it into the bundle) so the runtime hook
|
|
82
|
+
loads from `node_modules`. Most bundlers externalize `node_modules` for a Node target by default;
|
|
83
|
+
if yours inlines everything, mark `@sentry/server-runtime-injection` as external explicitly.
|
|
84
|
+
2. **Instrument at build time** with the Sentry bundler plugins (`@sentry/node/esbuild`,
|
|
85
|
+
`@sentry/node/webpack`, `@sentry/node/vite`, `@sentry/node/rollup`), which inject the
|
|
86
|
+
instrumentation into your bundled dependencies during the build. In this mode the runtime hook is
|
|
87
|
+
not needed.
|
|
88
|
+
|
|
89
|
+
If you bundle `@sentry/server-runtime-injection` **and** don't use the build-time plugin, its internal code
|
|
90
|
+
transformer is stripped and runtime auto-instrumentation is disabled. `@sentry/node` warns the
|
|
91
|
+
first time an instrumented dependency loads uninstrumented, so a build-time-instrumented app never
|
|
92
|
+
sees the warning.
|
|
93
|
+
|
|
75
94
|
## Links
|
|
76
95
|
|
|
77
96
|
- [Official SDK Docs](https://docs.sentry.io/quickstart/)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"esbuild.js","sources":["../../../src/bundler-plugin/esbuild.ts"],"sourcesContent":["import { sentryEsbuildPlugin as sentryEsbuildBundlerPlugin } from '@sentry/bundler-plugins/esbuild';\nimport type { SentryEsbuildPluginOptions as SentryEsbuildPluginOptionsBase } from '@sentry/bundler-plugins/esbuild';\nimport { sentryOrchestrionPlugin } from '@sentry/server-utils/orchestrion/esbuild';\n\nexport type SentryEsbuildPluginOptions = SentryEsbuildPluginOptionsBase & {\n /**\n * @ignore This is for internal use only when this plugin is consumed by a framework SDK\n */\n instrumentations?:
|
|
1
|
+
{"version":3,"file":"esbuild.js","sources":["../../../src/bundler-plugin/esbuild.ts"],"sourcesContent":["import { sentryEsbuildPlugin as sentryEsbuildBundlerPlugin } from '@sentry/bundler-plugins/esbuild';\nimport type { SentryEsbuildPluginOptions as SentryEsbuildPluginOptionsBase } from '@sentry/bundler-plugins/esbuild';\nimport type { InstrumentationConfig } from '@sentry/server-utils';\nimport { sentryOrchestrionPlugin } from '@sentry/server-utils/orchestrion/esbuild';\nimport type { EsbuildPlugin } from '@sentry/server-utils/orchestrion/esbuild';\n\nexport type SentryEsbuildPluginOptions = SentryEsbuildPluginOptionsBase & {\n /**\n * @ignore This is for internal use only when this plugin is consumed by a framework SDK\n */\n instrumentations?: InstrumentationConfig[];\n\n /**\n * Automatic instrumentation of server-side dependencies at build time.\n *\n * Set to `false` to turn it off.\n *\n * @default true\n */\n buildTimeInstrumentation?: boolean;\n};\n\n/**\n * esbuild plugin that bundles the Sentry esbuild bundler plugin (source maps,\n * release injection, …) together with the code transformer\n * (build-time `diagnostics_channel` instrumentation for Node libraries).\n *\n * It is a drop-in replacement for `@sentry/bundler-plugins/esbuild` and accepts\n * the same options.\n * @example\n * ```ts\n * // build.mjs\n * import { sentryEsbuildPlugin } from '@sentry/node/esbuild';\n * await esbuild.build({ plugins: [sentryEsbuildPlugin({ org: '…', project: '…' })] });\n * ```\n */\nexport function sentryEsbuildPlugin(options?: SentryEsbuildPluginOptions): EsbuildPlugin {\n const bundlerPlugin = sentryEsbuildBundlerPlugin(options) as EsbuildPlugin;\n const orchestrionPlugin = sentryOrchestrionPlugin(options);\n\n return {\n name: 'sentry-node-esbuild',\n async setup(build): Promise<void> {\n await bundlerPlugin.setup(build);\n await orchestrionPlugin.setup(build);\n },\n };\n}\n"],"names":["sentryEsbuildBundlerPlugin","sentryOrchestrionPlugin"],"mappings":";;;;;AAoCO,SAAS,oBAAoB,OAAA,EAAqD;AACvF,EAAA,MAAM,aAAA,GAAgBA,4BAA2B,OAAO,CAAA;AACxD,EAAA,MAAM,iBAAA,GAAoBC,kCAAwB,OAAO,CAAA;AAEzD,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,qBAAA;AAAA,IACN,MAAM,MAAM,KAAA,EAAsB;AAChC,MAAA,MAAM,aAAA,CAAc,MAAM,KAAK,CAAA;AAC/B,MAAA,MAAM,iBAAA,CAAkB,MAAM,KAAK,CAAA;AAAA,IACrC;AAAA,GACF;AACF;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rollup.js","sources":["../../../src/bundler-plugin/rollup.ts"],"sourcesContent":["import { sentryRollupPlugin as sentryRollupBundlerPlugin } from '@sentry/bundler-plugins/rollup';\nimport type { SentryRollupPluginOptions as SentryRollupPluginOptionsBase } from '@sentry/bundler-plugins/rollup';\nimport { sentryOrchestrionPlugin } from '@sentry/server-utils/orchestrion/rollup';\n\nexport type SentryRollupPluginOptions = SentryRollupPluginOptionsBase & {\n /**\n * @ignore This is for internal use only when this plugin is consumed by a framework SDK\n */\n instrumentations?:
|
|
1
|
+
{"version":3,"file":"rollup.js","sources":["../../../src/bundler-plugin/rollup.ts"],"sourcesContent":["import { sentryRollupPlugin as sentryRollupBundlerPlugin } from '@sentry/bundler-plugins/rollup';\nimport type { SentryRollupPluginOptions as SentryRollupPluginOptionsBase } from '@sentry/bundler-plugins/rollup';\nimport type { InstrumentationConfig } from '@sentry/server-utils';\nimport { sentryOrchestrionPlugin } from '@sentry/server-utils/orchestrion/rollup';\nimport type { RollupPlugin } from '@sentry/server-utils/orchestrion/rollup';\n\nexport type SentryRollupPluginOptions = SentryRollupPluginOptionsBase & {\n /**\n * @ignore This is for internal use only when this plugin is consumed by a framework SDK\n */\n instrumentations?: InstrumentationConfig[];\n\n /**\n * Automatic instrumentation of server-side dependencies at build time.\n *\n * Set to `false` to turn it off.\n *\n * @default true\n */\n buildTimeInstrumentation?: boolean;\n};\n\n/**\n * Rollup plugin that bundles the Sentry Rollup bundler plugin (source maps,\n * release injection, bundle size optimizations, …) together with the\n * code transformer (build-time `diagnostics_channel` instrumentation\n * for Node libraries).\n *\n * It is a drop-in replacement for `@sentry/bundler-plugins/rollup` and accepts\n * the same options.\n * @example\n * ```ts\n * // rollup.config.js\n * import { sentryRollupPlugin } from '@sentry/node/rollup';\n * export default { plugins: [sentryRollupPlugin({ org: '…', project: '…' })] };\n * ```\n */\nexport function sentryRollupPlugin(options?: SentryRollupPluginOptions): RollupPlugin[] {\n const bundlerPlugins = sentryRollupBundlerPlugin(options);\n return [...bundlerPlugins, sentryOrchestrionPlugin(options)];\n}\n"],"names":["sentryRollupBundlerPlugin","sentryOrchestrionPlugin"],"mappings":";;;;;AAqCO,SAAS,mBAAmB,OAAA,EAAqD;AACtF,EAAA,MAAM,cAAA,GAAiBA,0BAA0B,OAAO,CAAA;AACxD,EAAA,OAAO,CAAC,GAAG,cAAA,EAAgBC,gCAAA,CAAwB,OAAO,CAAC,CAAA;AAC7D;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vite.js","sources":["../../../src/bundler-plugin/vite.ts"],"sourcesContent":["import { sentryVitePlugin as sentryViteBundlerPlugin } from '@sentry/bundler-plugins/vite';\nimport type { SentryVitePluginOptions as SentryVitePluginOptionsBase } from '@sentry/bundler-plugins/vite';\nimport { sentryOrchestrionPlugin } from '@sentry/server-utils/orchestrion/vite';\n\nexport type SentryVitePluginOptions = SentryVitePluginOptionsBase & {\n /**\n * @ignore This is for internal use only when this plugin is consumed by a framework SDK\n */\n instrumentations?:
|
|
1
|
+
{"version":3,"file":"vite.js","sources":["../../../src/bundler-plugin/vite.ts"],"sourcesContent":["import { sentryVitePlugin as sentryViteBundlerPlugin } from '@sentry/bundler-plugins/vite';\nimport type { SentryVitePluginOptions as SentryVitePluginOptionsBase } from '@sentry/bundler-plugins/vite';\nimport type { InstrumentationConfig } from '@sentry/server-utils';\nimport { sentryOrchestrionPlugin } from '@sentry/server-utils/orchestrion/vite';\nimport type { VitePlugin } from '@sentry/server-utils/orchestrion/vite';\n\nexport type SentryVitePluginOptions = SentryVitePluginOptionsBase & {\n /**\n * @ignore This is for internal use only when this plugin is consumed by a framework SDK\n */\n instrumentations?: InstrumentationConfig[];\n\n /**\n * Automatic instrumentation of server-side dependencies at build time.\n *\n * Set to `false` to turn it off.\n *\n * @default true\n */\n buildTimeInstrumentation?: boolean;\n};\n\n/**\n * Vite plugin that bundles the Sentry Vite bundler plugin (source maps, release\n * injection, bundle size optimizations, …) together with the code\n * transformer (build-time `diagnostics_channel` instrumentation for Node\n * libraries).\n *\n * It is a drop-in replacement for `@sentry/bundler-plugins/vite` and accepts the\n * same options.\n *\n * @example\n * ```ts\n * // vite.config.ts\n * import { sentryVitePlugin } from '@sentry/node/vite';\n * export default { plugins: [sentryVitePlugin({ org: '…', project: '…' })] };\n * ```\n */\nexport function sentryVitePlugin(options?: SentryVitePluginOptions): VitePlugin[] {\n const bundlerPlugins = sentryViteBundlerPlugin(options);\n return [...bundlerPlugins, sentryOrchestrionPlugin(options)];\n}\n"],"names":["sentryViteBundlerPlugin","sentryOrchestrionPlugin"],"mappings":";;;;;AAsCO,SAAS,iBAAiB,OAAA,EAAiD;AAChF,EAAA,MAAM,cAAA,GAAiBA,sBAAwB,OAAO,CAAA;AACtD,EAAA,OAAO,CAAC,GAAG,cAAA,EAAgBC,8BAAA,CAAwB,OAAO,CAAC,CAAA;AAC7D;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"webpack.js","sources":["../../../src/bundler-plugin/webpack.ts"],"sourcesContent":["import { sentryWebpackPlugin as sentryWebpackBundlerPlugin } from '@sentry/bundler-plugins/webpack';\nimport type { SentryWebpackPluginOptions as SentryWebpackPluginOptionsBase } from '@sentry/bundler-plugins/webpack';\nimport { sentryOrchestrionWebpackPlugin } from '@sentry/server-utils/orchestrion/webpack';\n\nexport type SentryWebpackPluginOptions = SentryWebpackPluginOptionsBase & {\n /**\n * @ignore This is for internal use only when this plugin is consumed by a framework SDK\n */\n instrumentations?:
|
|
1
|
+
{"version":3,"file":"webpack.js","sources":["../../../src/bundler-plugin/webpack.ts"],"sourcesContent":["import { sentryWebpackPlugin as sentryWebpackBundlerPlugin } from '@sentry/bundler-plugins/webpack';\nimport type { SentryWebpackPluginOptions as SentryWebpackPluginOptionsBase } from '@sentry/bundler-plugins/webpack';\nimport type { InstrumentationConfig } from '@sentry/server-utils';\nimport { sentryOrchestrionWebpackPlugin } from '@sentry/server-utils/orchestrion/webpack';\n\nexport type SentryWebpackPluginOptions = SentryWebpackPluginOptionsBase & {\n /**\n * @ignore This is for internal use only when this plugin is consumed by a framework SDK\n */\n instrumentations?: InstrumentationConfig[];\n\n /**\n * Automatic instrumentation of server-side dependencies at build time.\n *\n * Set to `false` to turn it off.\n *\n * @default true\n */\n buildTimeInstrumentation?: boolean;\n};\n\ntype WebpackCompiler = Parameters<ReturnType<typeof sentryWebpackBundlerPlugin>['apply']>[0];\n\n/**\n * webpack plugin that bundles the Sentry webpack bundler plugin (source maps,\n * release injection, …) together with the code transformer\n * (build-time `diagnostics_channel` instrumentation for Node libraries).\n *\n * It is a drop-in replacement for `@sentry/bundler-plugins/webpack` and accepts\n * the same options.\n * @example\n * ```ts\n * // webpack.config.mjs\n * import { sentryWebpackPlugin } from '@sentry/node/webpack';\n * export default { plugins: [sentryWebpackPlugin({ org: '…', project: '…' })] };\n * ```\n */\nexport function sentryWebpackPlugin(options?: SentryWebpackPluginOptions): {\n apply: (compiler: WebpackCompiler) => void;\n} {\n const bundlerPlugin = sentryWebpackBundlerPlugin(options) as { apply: (compiler: WebpackCompiler) => void };\n const orchestrionPlugin = sentryOrchestrionWebpackPlugin(options) as { apply: (compiler: WebpackCompiler) => void };\n\n return {\n apply(compiler: WebpackCompiler): void {\n bundlerPlugin.apply(compiler);\n orchestrionPlugin.apply(compiler);\n },\n };\n}\n"],"names":["sentryWebpackBundlerPlugin","sentryOrchestrionWebpackPlugin"],"mappings":";;;;;AAqCO,SAAS,oBAAoB,OAAA,EAElC;AACA,EAAA,MAAM,aAAA,GAAgBA,4BAA2B,OAAO,CAAA;AACxD,EAAA,MAAM,iBAAA,GAAoBC,yCAA+B,OAAO,CAAA;AAEhE,EAAA,OAAO;AAAA,IACL,MAAM,QAAA,EAAiC;AACrC,MAAA,aAAA,CAAc,MAAM,QAAQ,CAAA;AAC5B,MAAA,iBAAA,CAAkB,MAAM,QAAQ,CAAA;AAAA,IAClC;AAAA,GACF;AACF;;;;"}
|
package/build/cjs/index.js
CHANGED
|
@@ -1,31 +1,28 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
2
|
|
|
3
|
-
const index$
|
|
4
|
-
const index$
|
|
5
|
-
const index$
|
|
6
|
-
const express = require('./integrations/tracing/express.js');
|
|
7
|
-
const index$2 = require('./integrations/tracing/fastify/index.js');
|
|
8
|
-
const orchestrion = require('@sentry/server-utils/orchestrion');
|
|
9
|
-
const index$9 = require('./integrations/tracing/redis/index.js');
|
|
3
|
+
const index$5 = require('./integrations/http/index.js');
|
|
4
|
+
const index$7 = require('./integrations/node-fetch/index.js');
|
|
5
|
+
const index$2 = require('./integrations/fs/index.js');
|
|
10
6
|
const serverUtils = require('@sentry/server-utils');
|
|
11
|
-
const
|
|
12
|
-
const
|
|
7
|
+
const hapi = require('./integrations/tracing/hapi.js');
|
|
8
|
+
const koa = require('./integrations/tracing/koa.js');
|
|
13
9
|
const launchDarkly = require('./integrations/featureFlagShims/launchDarkly.js');
|
|
14
10
|
const openFeature = require('./integrations/featureFlagShims/openFeature.js');
|
|
15
11
|
const statsig = require('./integrations/featureFlagShims/statsig.js');
|
|
16
12
|
const unleash = require('./integrations/featureFlagShims/unleash.js');
|
|
17
13
|
const growthbook = require('./integrations/featureFlagShims/growthbook.js');
|
|
18
|
-
const index$
|
|
14
|
+
const index$4 = require('./sdk/index.js');
|
|
19
15
|
const initOtel = require('./sdk/initOtel.js');
|
|
20
|
-
const index$
|
|
16
|
+
const index$3 = require('./integrations/tracing/index.js');
|
|
21
17
|
const opentelemetry = require('@sentry/opentelemetry');
|
|
22
18
|
const core = require('@sentry/core');
|
|
19
|
+
const server = require('@sentry/core/server');
|
|
23
20
|
const exports$1 = require('./logs/exports.js');
|
|
24
21
|
const childProcess = require('./integrations/childProcess.js');
|
|
25
22
|
const console = require('./integrations/console.js');
|
|
26
23
|
const context = require('./integrations/context.js');
|
|
27
24
|
const contextlines = require('./integrations/contextlines.js');
|
|
28
|
-
const index$
|
|
25
|
+
const index$6 = require('./integrations/local-variables/index.js');
|
|
29
26
|
const modules = require('./integrations/modules.js');
|
|
30
27
|
const nodeRuntimeMetrics = require('./integrations/nodeRuntimeMetrics.js');
|
|
31
28
|
const onuncaughtexception = require('./integrations/onuncaughtexception.js');
|
|
@@ -34,11 +31,13 @@ const pino = require('./integrations/pino.js');
|
|
|
34
31
|
const spotlight = require('./integrations/spotlight.js');
|
|
35
32
|
const systemError = require('./integrations/systemError.js');
|
|
36
33
|
const winston = require('./integrations/winston.js');
|
|
34
|
+
const workerThreads = require('./integrations/workerThreads.js');
|
|
37
35
|
const index$1 = require('./cron/index.js');
|
|
38
36
|
const nodeVersion = require('./nodeVersion.js');
|
|
39
37
|
const api = require('./sdk/api.js');
|
|
40
38
|
const http = require('./transports/http.js');
|
|
41
39
|
const module$1 = require('./utils/module.js');
|
|
40
|
+
const attributes = require('@sentry/conventions/attributes');
|
|
42
41
|
const httpServerIntegration = require('./integrations/http/httpServerIntegration.js');
|
|
43
42
|
const httpServerSpansIntegration = require('./integrations/http/httpServerSpansIntegration.js');
|
|
44
43
|
const processSession = require('./integrations/processSession.js');
|
|
@@ -47,49 +46,50 @@ const index = require('./integrations/anr/index.js');
|
|
|
47
46
|
|
|
48
47
|
|
|
49
48
|
|
|
50
|
-
exports.httpIntegration = index$
|
|
51
|
-
exports.nativeNodeFetchIntegration = index$
|
|
52
|
-
exports.fsIntegration = index$
|
|
53
|
-
exports.
|
|
54
|
-
exports.
|
|
55
|
-
exports.setupFastifyErrorHandler = index$2.setupFastifyErrorHandler;
|
|
56
|
-
exports.amqplibIntegration = orchestrion.amqplibIntegration;
|
|
57
|
-
exports.anthropicAIIntegration = orchestrion.anthropicIntegration;
|
|
58
|
-
exports.dataloaderIntegration = orchestrion.dataloaderIntegration;
|
|
59
|
-
exports.expressIntegration = orchestrion.expressIntegration;
|
|
60
|
-
exports.firebaseIntegration = orchestrion.firebaseIntegration;
|
|
61
|
-
exports.genericPoolIntegration = orchestrion.genericPoolIntegration;
|
|
62
|
-
exports.googleGenAIIntegration = orchestrion.googleGenAIIntegration;
|
|
63
|
-
exports.graphqlIntegration = orchestrion.graphqlDiagnosticsIntegration;
|
|
64
|
-
exports.hapiIntegration = orchestrion.hapiIntegration;
|
|
65
|
-
exports.kafkaIntegration = orchestrion.kafkajsIntegration;
|
|
66
|
-
exports.knexIntegration = orchestrion.knexIntegration;
|
|
67
|
-
exports.koaIntegration = orchestrion.koaIntegration;
|
|
68
|
-
exports.langChainIntegration = orchestrion.langChainIntegration;
|
|
69
|
-
exports.langGraphIntegration = orchestrion.langGraphIntegration;
|
|
70
|
-
exports.lruMemoizerIntegration = orchestrion.lruMemoizerIntegration;
|
|
71
|
-
exports.mongoIntegration = orchestrion.mongodbIntegration;
|
|
72
|
-
exports.mongooseIntegration = orchestrion.mongooseIntegration;
|
|
73
|
-
exports.mysql2Integration = orchestrion.mysql2Integration;
|
|
74
|
-
exports.mysqlIntegration = orchestrion.mysqlIntegration;
|
|
75
|
-
exports.openAIIntegration = orchestrion.openaiIntegration;
|
|
76
|
-
exports.postgresIntegration = orchestrion.postgresIntegration;
|
|
77
|
-
exports.postgresJsIntegration = orchestrion.postgresJsIntegration;
|
|
78
|
-
exports.tediousIntegration = orchestrion.tediousIntegration;
|
|
79
|
-
exports.vercelAIIntegration = orchestrion.vercelAiIntegration;
|
|
80
|
-
exports.redisIntegration = index$9.redisIntegration;
|
|
49
|
+
exports.httpIntegration = index$5.httpIntegration;
|
|
50
|
+
exports.nativeNodeFetchIntegration = index$7.nativeNodeFetchIntegration;
|
|
51
|
+
exports.fsIntegration = index$2.fsIntegration;
|
|
52
|
+
exports.amqplibIntegration = serverUtils.amqplibIntegration;
|
|
53
|
+
exports.anthropicAIIntegration = serverUtils.anthropicAIIntegration;
|
|
81
54
|
exports.createLangChainCallbackHandler = serverUtils.createLangChainCallbackHandler;
|
|
55
|
+
exports.dataloaderIntegration = serverUtils.dataloaderIntegration;
|
|
56
|
+
exports.expressErrorHandler = serverUtils.expressErrorHandler;
|
|
57
|
+
exports.expressIntegration = serverUtils.expressIntegration;
|
|
58
|
+
exports.fastifyIntegration = serverUtils.fastifyIntegration;
|
|
59
|
+
exports.firebaseIntegration = serverUtils.firebaseIntegration;
|
|
60
|
+
exports.genericPoolIntegration = serverUtils.genericPoolIntegration;
|
|
82
61
|
exports.getOtlpTracesEndpoint = serverUtils.getOtlpTracesEndpoint;
|
|
62
|
+
exports.googleGenAIIntegration = serverUtils.googleGenAIIntegration;
|
|
63
|
+
exports.graphqlIntegration = serverUtils.graphqlIntegration;
|
|
64
|
+
exports.hapiIntegration = serverUtils.hapiIntegration;
|
|
83
65
|
exports.instrumentAnthropicAiClient = serverUtils.instrumentAnthropicAiClient;
|
|
84
66
|
exports.instrumentGoogleGenAIClient = serverUtils.instrumentGoogleGenAIClient;
|
|
85
67
|
exports.instrumentLangChainEmbeddings = serverUtils.instrumentLangChainEmbeddings;
|
|
86
68
|
exports.instrumentOpenAiClient = serverUtils.instrumentOpenAiClient;
|
|
87
69
|
exports.instrumentStateGraph = serverUtils.instrumentStateGraph;
|
|
88
70
|
exports.instrumentStateGraphCompile = serverUtils.instrumentStateGraphCompile;
|
|
89
|
-
exports.
|
|
71
|
+
exports.kafkaIntegration = serverUtils.kafkaIntegration;
|
|
72
|
+
exports.knexIntegration = serverUtils.knexIntegration;
|
|
73
|
+
exports.koaIntegration = serverUtils.koaIntegration;
|
|
74
|
+
exports.langChainIntegration = serverUtils.langChainIntegration;
|
|
75
|
+
exports.langGraphIntegration = serverUtils.langGraphIntegration;
|
|
76
|
+
exports.lruMemoizerIntegration = serverUtils.lruMemoizerIntegration;
|
|
77
|
+
exports.mongoIntegration = serverUtils.mongoIntegration;
|
|
78
|
+
exports.mongooseIntegration = serverUtils.mongooseIntegration;
|
|
79
|
+
exports.mysql2Integration = serverUtils.mysql2Integration;
|
|
80
|
+
exports.mysqlIntegration = serverUtils.mysqlIntegration;
|
|
81
|
+
exports.openAIIntegration = serverUtils.openAIIntegration;
|
|
82
|
+
exports.openTelemetryIntegration = serverUtils.openTelemetryIntegration;
|
|
83
|
+
exports.postgresIntegration = serverUtils.postgresIntegration;
|
|
84
|
+
exports.postgresJsIntegration = serverUtils.postgresJsIntegration;
|
|
90
85
|
exports.prismaIntegration = serverUtils.prismaIntegration;
|
|
91
|
-
exports.
|
|
92
|
-
exports.
|
|
86
|
+
exports.redisIntegration = serverUtils.redisIntegration;
|
|
87
|
+
exports.setupExpressErrorHandler = serverUtils.setupExpressErrorHandler;
|
|
88
|
+
exports.setupFastifyErrorHandler = serverUtils.setupFastifyErrorHandler;
|
|
89
|
+
exports.tediousIntegration = serverUtils.tediousIntegration;
|
|
90
|
+
exports.vercelAIIntegration = serverUtils.vercelAIIntegration;
|
|
91
|
+
exports.setupHapiErrorHandler = hapi.setupHapiErrorHandler;
|
|
92
|
+
exports.setupKoaErrorHandler = koa.setupKoaErrorHandler;
|
|
93
93
|
exports.buildLaunchDarklyFlagUsedHandler = launchDarkly.buildLaunchDarklyFlagUsedHandlerShim;
|
|
94
94
|
exports.launchDarklyIntegration = launchDarkly.launchDarklyIntegrationShim;
|
|
95
95
|
exports.OpenFeatureIntegrationHook = openFeature.OpenFeatureIntegrationHookShim;
|
|
@@ -97,18 +97,17 @@ exports.openFeatureIntegration = openFeature.openFeatureIntegrationShim;
|
|
|
97
97
|
exports.statsigIntegration = statsig.statsigIntegrationShim;
|
|
98
98
|
exports.unleashIntegration = unleash.unleashIntegrationShim;
|
|
99
99
|
exports.growthbookIntegration = growthbook.growthbookIntegrationShim;
|
|
100
|
-
exports.getDefaultIntegrations = index$
|
|
101
|
-
exports.getDefaultIntegrationsWithoutPerformance = index$
|
|
102
|
-
exports.init = index$
|
|
103
|
-
exports.initWithoutDefaultIntegrations = index$
|
|
100
|
+
exports.getDefaultIntegrations = index$4.getDefaultIntegrations;
|
|
101
|
+
exports.getDefaultIntegrationsWithoutPerformance = index$4.getDefaultIntegrationsWithoutPerformance;
|
|
102
|
+
exports.init = index$4.init;
|
|
103
|
+
exports.initWithoutDefaultIntegrations = index$4.initWithoutDefaultIntegrations;
|
|
104
104
|
exports.initOpenTelemetry = initOtel.initOpenTelemetry;
|
|
105
|
-
exports.getAutoPerformanceIntegrations = index$
|
|
105
|
+
exports.getAutoPerformanceIntegrations = index$3.getAutoPerformanceIntegrations;
|
|
106
106
|
exports.setOpenTelemetryContextAsyncContextStrategy = opentelemetry.setOpenTelemetryContextAsyncContextStrategy;
|
|
107
107
|
exports.SDK_VERSION = core.SDK_VERSION;
|
|
108
108
|
exports.SEMANTIC_ATTRIBUTE_SENTRY_OP = core.SEMANTIC_ATTRIBUTE_SENTRY_OP;
|
|
109
109
|
exports.SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN = core.SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN;
|
|
110
110
|
exports.SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE = core.SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE;
|
|
111
|
-
exports.SEMANTIC_ATTRIBUTE_SENTRY_SOURCE = core.SEMANTIC_ATTRIBUTE_SENTRY_SOURCE;
|
|
112
111
|
exports.Scope = core.Scope;
|
|
113
112
|
exports.addBreadcrumb = core.addBreadcrumb;
|
|
114
113
|
exports.addEventProcessor = core.addEventProcessor;
|
|
@@ -129,7 +128,6 @@ exports.createTransport = core.createTransport;
|
|
|
129
128
|
exports.dedupeIntegration = core.dedupeIntegration;
|
|
130
129
|
exports.endSession = core.endSession;
|
|
131
130
|
exports.eventFiltersIntegration = core.eventFiltersIntegration;
|
|
132
|
-
exports.expressErrorHandler = core.expressErrorHandler;
|
|
133
131
|
exports.extraErrorDataIntegration = core.extraErrorDataIntegration;
|
|
134
132
|
exports.featureFlagsIntegration = core.featureFlagsIntegration;
|
|
135
133
|
exports.flush = core.flush;
|
|
@@ -179,7 +177,6 @@ exports.startSpan = core.startSpan;
|
|
|
179
177
|
exports.startSpanManual = core.startSpanManual;
|
|
180
178
|
exports.supabaseIntegration = core.supabaseIntegration;
|
|
181
179
|
exports.suppressTracing = core.suppressTracing;
|
|
182
|
-
exports.trpcMiddleware = core.trpcMiddleware;
|
|
183
180
|
exports.updateSpanName = core.updateSpanName;
|
|
184
181
|
exports.winterCGHeadersToDict = core.winterCGHeadersToDict;
|
|
185
182
|
exports.withActiveSpan = core.withActiveSpan;
|
|
@@ -188,14 +185,15 @@ exports.withMonitor = core.withMonitor;
|
|
|
188
185
|
exports.withScope = core.withScope;
|
|
189
186
|
exports.withStaticSpan = core.withStaticSpan;
|
|
190
187
|
exports.withStreamedSpan = core.withStreamedSpan;
|
|
191
|
-
exports.wrapMcpServerWithSentry = core.wrapMcpServerWithSentry;
|
|
192
188
|
exports.zodErrorsIntegration = core.zodErrorsIntegration;
|
|
189
|
+
exports.trpcMiddleware = server.trpcMiddleware;
|
|
190
|
+
exports.wrapMcpServerWithSentry = server.wrapMcpServerWithSentry;
|
|
193
191
|
exports.logger = exports$1;
|
|
194
192
|
exports.childProcessIntegration = childProcess.childProcessIntegration;
|
|
195
193
|
exports.consoleIntegration = console.consoleIntegration;
|
|
196
194
|
exports.nodeContextIntegration = context.nodeContextIntegration;
|
|
197
195
|
exports.contextLinesIntegration = contextlines.contextLinesIntegration;
|
|
198
|
-
exports.localVariablesIntegration = index$
|
|
196
|
+
exports.localVariablesIntegration = index$6.localVariablesIntegration;
|
|
199
197
|
exports.modulesIntegration = modules.modulesIntegration;
|
|
200
198
|
exports._INTERNAL_normalizeCollectionInterval = nodeRuntimeMetrics._INTERNAL_normalizeCollectionInterval;
|
|
201
199
|
exports.nodeRuntimeMetricsIntegration = nodeRuntimeMetrics.nodeRuntimeMetricsIntegration;
|
|
@@ -205,12 +203,14 @@ exports.pinoIntegration = pino.pinoIntegration;
|
|
|
205
203
|
exports.spotlightIntegration = spotlight.spotlightIntegration;
|
|
206
204
|
exports.systemErrorIntegration = systemError.systemErrorIntegration;
|
|
207
205
|
exports.createSentryWinstonTransport = winston.createSentryWinstonTransport;
|
|
206
|
+
exports.workerThreadsIntegration = workerThreads.workerThreadsIntegration;
|
|
208
207
|
exports.cron = index$1.cron;
|
|
209
208
|
exports.NODE_VERSION = nodeVersion.NODE_VERSION;
|
|
210
209
|
exports.defaultStackParser = api.defaultStackParser;
|
|
211
210
|
exports.getSentryRelease = api.getSentryRelease;
|
|
212
211
|
exports.makeNodeTransport = http.makeNodeTransport;
|
|
213
212
|
exports.createGetModuleFromFilename = module$1.createGetModuleFromFilename;
|
|
213
|
+
exports.SENTRY_SEGMENT_NAME_SOURCE = attributes.SENTRY_SEGMENT_NAME_SOURCE;
|
|
214
214
|
exports.httpServerIntegration = httpServerIntegration.httpServerIntegration;
|
|
215
215
|
exports.httpServerSpansIntegration = httpServerSpansIntegration.httpServerSpansIntegration;
|
|
216
216
|
exports.processSessionIntegration = processSession.processSessionIntegration;
|
|
@@ -6,7 +6,7 @@ const core = require('@sentry/core');
|
|
|
6
6
|
const debug = require('../../utils/debug.js');
|
|
7
7
|
|
|
8
8
|
const { isPromise } = util.types;
|
|
9
|
-
const base64WorkerScript = "LyohIEBzZW50cnkvbm9kZSAxMS4wLjAtYWxwaGEuMSAoNmFiN2VmZCkgfCBodHRwczovL2dpdGh1Yi5jb20vZ2V0c2VudHJ5L3NlbnRyeS1qYXZhc2NyaXB0ICovCmltcG9ydHtTZXNzaW9uIGFzIHR9ZnJvbSJub2RlOmluc3BlY3RvciI7aW1wb3J0e3dvcmtlckRhdGEgYXMgZSxwYXJlbnRQb3J0IGFzIG59ZnJvbSJub2RlOndvcmtlcl90aHJlYWRzIjtpbXBvcnR7cG9zaXggYXMgcixzZXAgYXMgb31mcm9tIm5vZGU6cGF0aCI7aW1wb3J0KmFzIHMgZnJvbSJub2RlOmh0dHAiO2ltcG9ydCphcyBpIGZyb20ibm9kZTpodHRwcyI7aW1wb3J0e1JlYWRhYmxlIGFzIGN9ZnJvbSJub2RlOnN0cmVhbSI7aW1wb3J0e2NyZWF0ZUd6aXAgYXMgdX1mcm9tIm5vZGU6emxpYiI7aW1wb3J0KmFzIGEgZnJvbSJub2RlOm5ldCI7aW1wb3J0KmFzIGYgZnJvbSJub2RlOnRscyI7Y29uc3QgaD0idW5kZWZpbmVkIj09dHlwZW9mIF9fU0VOVFJZX0RFQlVHX198fF9fU0VOVFJZX0RFQlVHX18scD1nbG9iYWxUaGlzLGw9IjExLjAuMC1hbHBoYS4xIjtmdW5jdGlvbiBkKCl7cmV0dXJuIGcocCkscH1mdW5jdGlvbiBnKHQpe2NvbnN0IGU9dC5fX1NFTlRSWV9fPXQuX19TRU5UUllfX3x8e307cmV0dXJuIGUudmVyc2lvbj1lLnZlcnNpb258fGwsZVtsXT1lW2xdfHx7fX1mdW5jdGlvbiBtKHQsZSxuPXApe2NvbnN0IHI9bi5fX1NFTlRSWV9fPW4uX19TRU5UUllfX3x8e30sbz1yW2xdPXJbbF18fHt9O3JldHVybiBvW3RdfHwob1t0XT1lKCkpfWNvbnN0IHk9e307ZnVuY3Rpb24gYih0KXtpZighKCJjb25zb2xlImluIHApKXJldHVybiB0KCk7Y29uc3QgZT1wLmNvbnNvbGUsbj17fSxyPU9iamVjdC5rZXlzKHkpO3IuZm9yRWFjaCh0PT57Y29uc3Qgcj15W3RdO25bdF09ZVt0XSxlW3RdPXJ9KTt0cnl7cmV0dXJuIHQoKX1maW5hbGx5e3IuZm9yRWFjaCh0PT57ZVt0XT1uW3RdfSl9fWZ1bmN0aW9uIHYoKXtyZXR1cm4gUygpLmVuYWJsZWR9ZnVuY3Rpb24gdyh0LC4uLmUpe2gmJnYoKSYmYigoKT0+e3AuY29uc29sZVt0XShgU2VudHJ5IExvZ2dlciBbJHt0fV06YCwuLi5lKX0pfWZ1bmN0aW9uIFMoKXtyZXR1cm4gaD9tKCJsb2dnZXJTZXR0aW5ncyIsKCk9Pih7ZW5hYmxlZDohMX0pKTp7ZW5hYmxlZDohMX19Y29uc3QgXz17ZW5hYmxlOmZ1bmN0aW9uKCl7UygpLmVuYWJsZWQ9ITB9LGRpc2FibGU6ZnVuY3Rpb24oKXtTKCkuZW5hYmxlZD0hMX0saXNFbmFibGVkOnYsbG9nOmZ1bmN0aW9uKC4uLnQpe3coImxvZyIsLi4udCl9LHdhcm46ZnVuY3Rpb24oLi4udCl7dygid2FybiIsLi4udCl9LGVycm9yOmZ1bmN0aW9uKC4uLnQpe3coImVycm9yIiwuLi50KX19LCQ9L2NhcHR1cmVNZXNzYWdlfGNhcHR1cmVFeGNlcHRpb24vO2Z1bmN0aW9uIEUodCl7cmV0dXJuIHRbdC5sZW5ndGgtMV18fHt9fWNvbnN0IHg9Ijxhbm9ueW1vdXM+Ijtjb25zdCBOPU9iamVjdC5wcm90b3R5cGUudG9TdHJpbmc7ZnVuY3Rpb24gaih0KXtyZXR1cm4gZnVuY3Rpb24odCxlKXtyZXR1cm4gTi5jYWxsKHQpPT09YFtvYmplY3QgJHtlfV1gfSh0LCJPYmplY3QiKX1mdW5jdGlvbiBDKHQpe3JldHVybiBCb29sZWFuKHQ/LnRoZW4mJiJmdW5jdGlvbiI9PXR5cGVvZiB0LnRoZW4pfWZ1bmN0aW9uIE8odCxlKXt0cnl7cmV0dXJuIHQgaW5zdGFuY2VvZiBlfWNhdGNoe3JldHVybiExfX1mdW5jdGlvbiBQKHQpe2lmKGZ1bmN0aW9uKHQpe3N3aXRjaChOLmNhbGwodCkpe2Nhc2UiW29iamVjdCBFcnJvcl0iOmNhc2UiW29iamVjdCBFeGNlcHRpb25dIjpjYXNlIltvYmplY3QgRE9NRXhjZXB0aW9uXSI6Y2FzZSJbb2JqZWN0IFdlYkFzc2VtYmx5LkV4Y2VwdGlvbl0iOnJldHVybiEwO2RlZmF1bHQ6cmV0dXJuIE8odCxFcnJvcil9fSh0KSlyZXR1cm57bWVzc2FnZTp0Lm1lc3NhZ2UsbmFtZTp0Lm5hbWUsc3RhY2s6dC5zdGFjaywuLi5BKHQpfTtpZihlPXQsInVuZGVmaW5lZCIhPXR5cGVvZiBFdmVudCYmTyhlLEV2ZW50KSl7Y29uc3R7dHlwZTplLHRhcmdldDpuLGN1cnJlbnRUYXJnZXQ6cixkZXRhaWw6b309dDtyZXR1cm57dHlwZTplLHRhcmdldDpuLGN1cnJlbnRUYXJnZXQ6ciwuLi5vP3tkZXRhaWw6b306e30sLi4uQSh0KX19dmFyIGU7cmV0dXJuIHR9ZnVuY3Rpb24gQSh0KXtyZXR1cm4ib2JqZWN0Ij09dHlwZW9mKGU9dCkmJm51bGwhPT1lP09iamVjdC5mcm9tRW50cmllcyhPYmplY3QuZW50cmllcyh0KSk6e307dmFyIGV9bGV0IGs7ZnVuY3Rpb24gVCh0KXtpZih2b2lkIDAhPT1rKXJldHVybiBrP2sodCk6dCgpO2NvbnN0IGU9U3ltYm9sLmZvcigiX19TRU5UUllfU0FGRV9SQU5ET01fSURfV1JBUFBFUl9fIiksbj1wO3JldHVybiBlIGluIG4mJiJmdW5jdGlvbiI9PXR5cGVvZiBuW2VdPyhrPW5bZV0sayh0KSk6KGs9bnVsbCx0KCkpfWZ1bmN0aW9uIFIoKXtyZXR1cm4gVCgoKT0+TWF0aC5yYW5kb20oKSl9ZnVuY3Rpb24gSSgpe3JldHVybiBUKCgpPT5EYXRlLm5vdygpKX1jb25zdCBEPVN5bWJvbC5mb3IoInNlbnRyeS5za2lwTm9ybWFsaXphdGlvbiIpLFU9U3ltYm9sLmZvcigic2VudHJ5Lm92ZXJyaWRlTm9ybWFsaXphdGlvbkRlcHRoIik7ZnVuY3Rpb24gQih0LGU9MTAwLG49MS8wKXt0cnl7cmV0dXJuIEwoIiIsdCxlLG4pfWNhdGNoKHQpe3JldHVybntFUlJPUjpgKipub24tc2VyaWFsaXphYmxlKiogKCR7dH0pYH19fWZ1bmN0aW9uIEwodCxlLG49MS8wLHI9MS8wLG89ZnVuY3Rpb24oKXtjb25zdCB0PW5ldyBXZWFrU2V0O2Z1bmN0aW9uIGUoZSl7cmV0dXJuISF0LmhhcyhlKXx8KHQuYWRkKGUpLCExKX1mdW5jdGlvbiBuKGUpe3QuZGVsZXRlKGUpfXJldHVybltlLG5dfSgpKXtjb25zdFtzLGldPW87aWYobnVsbD09ZXx8WyJib29sZWFuIiwic3RyaW5nIl0uaW5jbHVkZXModHlwZW9mIGUpfHwibnVtYmVyIj09dHlwZW9mIGUmJk51bWJlci5pc0Zpbml0ZShlKSlyZXR1cm4gZTtjb25zdCBjPWZ1bmN0aW9uKHQsZSl7dHJ5e2lmKCJ1bmRlZmluZWQiIT10eXBlb2YgZ2xvYmFsJiZlPT09Z2xvYmFsKXJldHVybiJbR2xvYmFsXSI7aWYoIm51bWJlciI9PXR5cGVvZiBlJiYhTnVtYmVyLmlzRmluaXRlKGUpKXJldHVybmBbJHtlfV1gO2lmKCJmdW5jdGlvbiI9PXR5cGVvZiBlKXJldHVybmBbRnVuY3Rpb246ICR7ZnVuY3Rpb24odCl7dHJ5e3JldHVybiB0JiYiZnVuY3Rpb24iPT10eXBlb2YgdCYmdC5uYW1lfHx4fWNhdGNoe3JldHVybiB4fX0oZSl9XWA7aWYoInN5bWJvbCI9PXR5cGVvZiBlKXJldHVybmBbJHtTdHJpbmcoZSl9XWA7aWYoImJpZ2ludCI9PXR5cGVvZiBlKXJldHVybmBbQmlnSW50OiAke1N0cmluZyhlKX1dYDtjb25zdCB0PWZ1bmN0aW9uKHQpe2NvbnN0IGU9T2JqZWN0LmdldFByb3RvdHlwZU9mKHQpO3JldHVybiBlPy5jb25zdHJ1Y3Rvcj9lLmNvbnN0cnVjdG9yLm5hbWU6Im51bGwgcHJvdG90eXBlIn0oZSk7cmV0dXJuYFtvYmplY3QgJHt0fV1gfWNhdGNoKHQpe3JldHVybmAqKm5vbi1zZXJpYWxpemFibGUqKiAoJHt0fSlgfX0oMCxlKTtpZighYy5zdGFydHNXaXRoKCJbb2JqZWN0ICIpKXJldHVybiBjO2lmKGZ1bmN0aW9uKHQpe3JldHVybiBCb29sZWFuKHRbRF0pfShlKSlyZXR1cm4gZTtjb25zdCB1PWZ1bmN0aW9uKHQpe2NvbnN0IGU9dFtVXTtyZXR1cm4ibnVtYmVyIj09dHlwZW9mIGU/ZTp2b2lkIDB9KGUpLGE9dm9pZCAwIT09dT91Om47aWYoMD09PWEpcmV0dXJuIGMucmVwbGFjZSgib2JqZWN0ICIsIiIpO2lmKHMoZSkpcmV0dXJuIltDaXJjdWxhciB+XSI7Y29uc3QgZj1lO2lmKGYmJiJmdW5jdGlvbiI9PXR5cGVvZiBmLnRvSlNPTil0cnl7cmV0dXJuIEwoIiIsZi50b0pTT04oKSxhLTEscixvKX1jYXRjaHt9Y29uc3QgaD1BcnJheS5pc0FycmF5KGUpP1tdOnt9O2xldCBwPTA7Y29uc3QgbD1QKGUpO2Zvcihjb25zdCB0IGluIGwpe2lmKCFPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwobCx0KSljb250aW51ZTtpZihwPj1yKXtoW3RdPSJbTWF4UHJvcGVydGllcyB+XSI7YnJlYWt9Y29uc3QgZT1sW3RdO2hbdF09TCh0LGUsYS0xLHIsbykscCsrfXJldHVybiBpKGUpLGh9ZnVuY3Rpb24gTSh0LGUpe2NvbnN0IG49ZS5yZXBsYWNlKC9cXC9nLCIvIikucmVwbGFjZSgvW3xcXHt9KClbXF1eJCsqPy5dL2csIlxcJCYiKTtsZXQgcj10O3RyeXtyPWRlY29kZVVSSSh0KX1jYXRjaHt9cmV0dXJuIHIucmVwbGFjZSgvXFwvZywiLyIpLnJlcGxhY2UoL3dlYnBhY2s6XC8/L2csIiIpLnJlcGxhY2UobmV3IFJlZ0V4cChgKGZpbGU6Ly8pPy8qJHtufS8qYCwiaWciKSwiYXBwOi8vLyIpfWZ1bmN0aW9uIHoodCxlPTApe3JldHVybiJzdHJpbmciIT10eXBlb2YgdHx8MD09PWV8fHQubGVuZ3RoPD1lP3Q6YCR7dC5zbGljZSgwLGUpfS4uLmB9bGV0IEo7ZnVuY3Rpb24gVyh0PWZ1bmN0aW9uKCl7Y29uc3QgdD1wO3JldHVybiB0LmNyeXB0b3x8dC5tc0NyeXB0b30oKSl7dHJ5e2lmKHQ/LnJhbmRvbVVVSUQpcmV0dXJuIFQoKCk9PnQucmFuZG9tVVVJRCgpKS5yZXBsYWNlKC8tL2csIiIpfWNhdGNoe31yZXR1cm4gSnx8KEo9IjEwMDAwMDAwMTAwMDQwMDA4MDAwMTAwMDAwMDAwMDAwIiksSi5yZXBsYWNlKC9bMDE4XS9nLHQ9Pih0XigxNipSKCkmMTUpPj50LzQpLnRvU3RyaW5nKDE2KSl9ZnVuY3Rpb24gRigpe3JldHVybiBJKCkvMWUzfWxldCBHO2Z1bmN0aW9uIFkoKXtyZXR1cm4oRz8/KEc9ZnVuY3Rpb24oKXtjb25zdHtwZXJmb3JtYW5jZTp0fT1wO2lmKCF0Py5ub3d8fCF0LnRpbWVPcmlnaW4pcmV0dXJuIEY7Y29uc3QgZT10LnRpbWVPcmlnaW47cmV0dXJuKCk9PihlK1QoKCk9PnQubm93KCkpKS8xZTN9KCkpKSgpfWZ1bmN0aW9uIEgodCl7Y29uc3QgZT1ZKCksbj17c2lkOlcoKSxpbml0OiEwLHRpbWVzdGFtcDplLHN0YXJ0ZWQ6ZSxkdXJhdGlvbjowLHN0YXR1czoib2siLGVycm9yczowLGlnbm9yZUR1cmF0aW9uOiExLHRvSlNPTjooKT0+ZnVuY3Rpb24odCl7cmV0dXJue3NpZDpgJHt0LnNpZH1gLGluaXQ6dC5pbml0LHN0YXJ0ZWQ6bmV3IERhdGUoMWUzKnQuc3RhcnRlZCkudG9JU09TdHJpbmcoKSx0aW1lc3RhbXA6bmV3IERhdGUoMWUzKnQudGltZXN0YW1wKS50b0lTT1N0cmluZygpLHN0YXR1czp0LnN0YXR1cyxlcnJvcnM6dC5lcnJvcnMsZGlkOiJudW1iZXIiPT10eXBlb2YgdC5kaWR8fCJzdHJpbmciPT10eXBlb2YgdC5kaWQ/YCR7dC5kaWR9YDp2b2lkIDAsZHVyYXRpb246dC5kdXJhdGlvbixhYm5vcm1hbF9tZWNoYW5pc206dC5hYm5vcm1hbF9tZWNoYW5pc20sYXR0cnM6e3JlbGVhc2U6dC5yZWxlYXNlLGVudmlyb25tZW50OnQuZW52aXJvbm1lbnQsaXBfYWRkcmVzczp0LmlwQWRkcmVzcyx1c2VyX2FnZW50OnQudXNlckFnZW50fX19KG4pfTtyZXR1cm4gdCYmWihuLHQpLG59ZnVuY3Rpb24gWih0LGU9e30pe2lmKGUudXNlciYmKCF0LmlwQWRkcmVzcyYmZS51c2VyLmlwX2FkZHJlc3MmJih0LmlwQWRkcmVzcz1lLnVzZXIuaXBfYWRkcmVzcyksdC5kaWR8fGUuZGlkfHwodC5kaWQ9ZS51c2VyLmlkfHxlLnVzZXIuZW1haWx8fGUudXNlci51c2VybmFtZSkpLHQudGltZXN0YW1wPWUudGltZXN0YW1wfHxZKCksZS5hYm5vcm1hbF9tZWNoYW5pc20mJih0LmFibm9ybWFsX21lY2hhbmlzbT1lLmFibm9ybWFsX21lY2hhbmlzbSksZS5pZ25vcmVEdXJhdGlvbiYmKHQuaWdub3JlRHVyYXRpb249ZS5pZ25vcmVEdXJhdGlvbiksZS5zaWQmJih0LnNpZD0zMj09PWUuc2lkLmxlbmd0aD9lLnNpZDpXKCkpLHZvaWQgMCE9PWUuaW5pdCYmKHQuaW5pdD1lLmluaXQpLCF0LmRpZCYmZS5kaWQmJih0LmRpZD1gJHtlLmRpZH1gKSwibnVtYmVyIj09dHlwZW9mIGUuc3RhcnRlZCYmKHQuc3RhcnRlZD1lLnN0YXJ0ZWQpLHQuaWdub3JlRHVyYXRpb24pdC5kdXJhdGlvbj12b2lkIDA7ZWxzZSBpZigibnVtYmVyIj09dHlwZW9mIGUuZHVyYXRpb24pdC5kdXJhdGlvbj1lLmR1cmF0aW9uO2Vsc2V7Y29uc3QgZT10LnRpbWVzdGFtcC10LnN0YXJ0ZWQ7dC5kdXJhdGlvbj1lPj0wP2U6MH1lLnJlbGVhc2UmJih0LnJlbGVhc2U9ZS5yZWxlYXNlKSxlLmVudmlyb25tZW50JiYodC5lbnZpcm9ubWVudD1lLmVudmlyb25tZW50KSwhdC5pcEFkZHJlc3MmJmUuaXBBZGRyZXNzJiYodC5pcEFkZHJlc3M9ZS5pcEFkZHJlc3MpLCF0LnVzZXJBZ2VudCYmZS51c2VyQWdlbnQmJih0LnVzZXJBZ2VudD1lLnVzZXJBZ2VudCksIm51bWJlciI9PXR5cGVvZiBlLmVycm9ycyYmKHQuZXJyb3JzPWUuZXJyb3JzKSxlLnN0YXR1cyYmKHQuc3RhdHVzPWUuc3RhdHVzKX1mdW5jdGlvbiBxKHQsZSxuPTIpe2lmKCFlfHwib2JqZWN0IiE9dHlwZW9mIGV8fG48PTApcmV0dXJuIGU7aWYodCYmMD09PU9iamVjdC5rZXlzKGUpLmxlbmd0aClyZXR1cm4gdDtjb25zdCByPXsuLi50fTtmb3IoY29uc3QgdCBpbiBlKU9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChlLHQpJiYoclt0XT1xKHJbdF0sZVt0XSxuLTEpKTtyZXR1cm4gcn1jbGFzcyBLe2NvbnN0cnVjdG9yKCl7dGhpcy50PSExLHRoaXMubz1bXSx0aGlzLmk9W10sdGhpcy51PVtdLHRoaXMuaD1bXSx0aGlzLnA9e30sdGhpcy5sPXt9LHRoaXMubT17fSx0aGlzLnY9e30sdGhpcy5TPXt9LHRoaXMuXz17fSxmdW5jdGlvbih0LGUsbil7dHJ5e09iamVjdC5kZWZpbmVQcm9wZXJ0eSh0LGUse3ZhbHVlOm4sd3JpdGFibGU6ITAsY29uZmlndXJhYmxlOiEwfSl9Y2F0Y2h7aCYmXy5sb2coYEZhaWxlZCB0byBhZGQgbm9uLWVudW1lcmFibGUgcHJvcGVydHkgIiR7U3RyaW5nKGUpfSIgdG8gb2JqZWN0YCx0KX19KHRoaXMsInJlZnMiLHt9KSx0aGlzLk49e3RyYWNlSWQ6VygpLHNhbXBsZVJhbmQ6UigpfX1jbG9uZSgpe2NvbnN0IHQ9bmV3IEs7cmV0dXJuIHQudT1bLi4udGhpcy51XSx0Lmw9ey4uLnRoaXMubH0sdC5tPXsuLi50aGlzLm19LHQudj17Li4udGhpcy52fSx0LlM9ey4uLnRoaXMuU30sdGhpcy5TLmZsYWdzJiYodC5TLmZsYWdzPXt2YWx1ZXM6Wy4uLnRoaXMuUy5mbGFncy52YWx1ZXNdfSksdC5wPXRoaXMucCx0Lmo9dGhpcy5qLHQuQz10aGlzLkMsdC5PPXRoaXMuTyx0LlA9dGhpcy5QLHQuaT1bLi4udGhpcy5pXSx0Lmg9Wy4uLnRoaXMuaF0sdC5fPXsuLi50aGlzLl99LHQuTj17Li4udGhpcy5OfSx0LkE9dGhpcy5BLHQuaz10aGlzLmssdC5UPXRoaXMuVCx0LnJlZnM9ey4uLnRoaXMucmVmc30sdH1zZXRDbGllbnQodCl7dGhpcy5BPXR9c2V0TGFzdEV2ZW50SWQodCl7dGhpcy5rPXR9Z2V0Q2xpZW50KCl7cmV0dXJuIHRoaXMuQX1sYXN0RXZlbnRJZCgpe3JldHVybiB0aGlzLmt9YWRkU2NvcGVMaXN0ZW5lcih0KXt0aGlzLm8ucHVzaCh0KX1hZGRFdmVudFByb2Nlc3Nvcih0KXtyZXR1cm4gdGhpcy5pLnB1c2godCksdGhpc31zZXRVc2VyKHQpe3JldHVybiB0aGlzLnA9dHx8e2VtYWlsOnZvaWQgMCxpZDp2b2lkIDAsaXBfYWRkcmVzczp2b2lkIDAsdXNlcm5hbWU6dm9pZCAwfSx0aGlzLkMmJloodGhpcy5DLHt1c2VyOnR9KSx0aGlzLlIoKSx0aGlzfWdldFVzZXIoKXtyZXR1cm4gdGhpcy5wfXNldENvbnZlcnNhdGlvbklkKHQpe3JldHVybiB0aGlzLlQ9dHx8dm9pZCAwLHRoaXMuUigpLHRoaXN9c2V0VGFncyh0KXtyZXR1cm4gdGhpcy5sPXsuLi50aGlzLmwsLi4udH0sdGhpcy5SKCksdGhpc31zZXRUYWcodCxlKXtyZXR1cm4gdGhpcy5zZXRUYWdzKHtbdF06ZX0pfXNldEF0dHJpYnV0ZXModCl7cmV0dXJuIHRoaXMubT17Li4udGhpcy5tLC4uLnR9LHRoaXMuUigpLHRoaXN9c2V0QXR0cmlidXRlKHQsZSl7cmV0dXJuIHRoaXMuc2V0QXR0cmlidXRlcyh7W3RdOmV9KX1yZW1vdmVBdHRyaWJ1dGUodCl7cmV0dXJuIHQgaW4gdGhpcy5tJiYoZGVsZXRlIHRoaXMubVt0XSx0aGlzLlIoKSksdGhpc31zZXRFeHRyYXModCl7cmV0dXJuIHRoaXMudj17Li4udGhpcy52LC4uLnR9LHRoaXMuUigpLHRoaXN9c2V0RXh0cmEodCxlKXtyZXR1cm4gdGhpcy52PXsuLi50aGlzLnYsW3RdOmV9LHRoaXMuUigpLHRoaXN9c2V0RmluZ2VycHJpbnQodCl7cmV0dXJuIHRoaXMuUD10LHRoaXMuUigpLHRoaXN9c2V0TGV2ZWwodCl7cmV0dXJuIHRoaXMuaj10LHRoaXMuUigpLHRoaXN9c2V0VHJhbnNhY3Rpb25OYW1lKHQpe3JldHVybiB0aGlzLk89dCx0aGlzLlIoKSx0aGlzfXNldENvbnRleHQodCxlKXtyZXR1cm4gbnVsbD09PWU/ZGVsZXRlIHRoaXMuU1t0XTp0aGlzLlNbdF09ZSx0aGlzLlIoKSx0aGlzfXNldFNlc3Npb24odCl7cmV0dXJuIHQ/dGhpcy5DPXQ6ZGVsZXRlIHRoaXMuQyx0aGlzLlIoKSx0aGlzfWdldFNlc3Npb24oKXtyZXR1cm4gdGhpcy5DfXVwZGF0ZSh0KXtpZighdClyZXR1cm4gdGhpcztjb25zdCBlPSJmdW5jdGlvbiI9PXR5cGVvZiB0P3QodGhpcyk6dCxuPWUgaW5zdGFuY2VvZiBLP2UuZ2V0U2NvcGVEYXRhKCk6aihlKT90OnZvaWQgMCx7dGFnczpyLGF0dHJpYnV0ZXM6byxleHRyYTpzLHVzZXI6aSxjb250ZXh0czpjLGxldmVsOnUsZmluZ2VycHJpbnQ6YT1bXSxwcm9wYWdhdGlvbkNvbnRleHQ6Zixjb252ZXJzYXRpb25JZDpofT1ufHx7fTtyZXR1cm4gdGhpcy5sPXsuLi50aGlzLmwsLi4ucn0sdGhpcy5tPXsuLi50aGlzLm0sLi4ub30sdGhpcy52PXsuLi50aGlzLnYsLi4uc30sdGhpcy5TPXsuLi50aGlzLlMsLi4uY30saSYmT2JqZWN0LmtleXMoaSkubGVuZ3RoJiYodGhpcy5wPWkpLHUmJih0aGlzLmo9dSksYS5sZW5ndGgmJih0aGlzLlA9YSksZiYmKHRoaXMuTj1mKSxoJiYodGhpcy5UPWgpLHRoaXN9YWRkQnJlYWRjcnVtYih0LGUpe2NvbnN0IG49Im51bWJlciI9PXR5cGVvZiBlP2U6MTAwO2lmKG48PTApcmV0dXJuIHRoaXM7Y29uc3Qgcj17dGltZXN0YW1wOkYoKSwuLi50LG1lc3NhZ2U6dC5tZXNzYWdlP3oodC5tZXNzYWdlLDIwNDgpOnQubWVzc2FnZX07cmV0dXJuIHRoaXMudS5wdXNoKHIpLHRoaXMudS5sZW5ndGg+biYmKHRoaXMudT10aGlzLnUuc2xpY2UoLW4pLHRoaXMuQT8ucmVjb3JkRHJvcHBlZEV2ZW50KCJidWZmZXJfb3ZlcmZsb3ciLCJsb2dfaXRlbSIpKSx0aGlzLlIoKSx0aGlzfWdldExhc3RCcmVhZGNydW1iKCl7cmV0dXJuIHRoaXMudVt0aGlzLnUubGVuZ3RoLTFdfWNsZWFyQnJlYWRjcnVtYnMoKXtyZXR1cm4gdGhpcy51PVtdLHRoaXMuUigpLHRoaXN9YWRkQXR0YWNobWVudCh0KXtyZXR1cm4gdGhpcy5oLnB1c2godCksdGhpc31jbGVhckF0dGFjaG1lbnRzKCl7cmV0dXJuIHRoaXMuaD1bXSx0aGlzfWdldFNjb3BlRGF0YSgpe3JldHVybnticmVhZGNydW1iczp0aGlzLnUsYXR0YWNobWVudHM6dGhpcy5oLGNvbnRleHRzOnRoaXMuUyx0YWdzOnRoaXMubCxhdHRyaWJ1dGVzOnRoaXMubSxleHRyYTp0aGlzLnYsdXNlcjp0aGlzLnAsbGV2ZWw6dGhpcy5qLGZpbmdlcnByaW50OnRoaXMuUHx8W10sZXZlbnRQcm9jZXNzb3JzOnRoaXMuaSxwcm9wYWdhdGlvbkNvbnRleHQ6dGhpcy5OLHNka1Byb2Nlc3NpbmdNZXRhZGF0YTp0aGlzLl8sdHJhbnNhY3Rpb25OYW1lOnRoaXMuTyxjb252ZXJzYXRpb25JZDp0aGlzLlR9fXNldFNES1Byb2Nlc3NpbmdNZXRhZGF0YSh0KXtyZXR1cm4gdGhpcy5fPXEodGhpcy5fLHQsMiksdGhpc31zZXRQcm9wYWdhdGlvbkNvbnRleHQodCl7cmV0dXJuIHRoaXMuTj10LHRoaXN9Z2V0UHJvcGFnYXRpb25Db250ZXh0KCl7cmV0dXJuIHRoaXMuTn1jYXB0dXJlRXhjZXB0aW9uKHQsZSl7Y29uc3Qgbj1lPy5ldmVudF9pZHx8VygpO2lmKCF0aGlzLkEpcmV0dXJuIGgmJl8ud2FybigiTm8gY2xpZW50IGNvbmZpZ3VyZWQgb24gc2NvcGUgLSB3aWxsIG5vdCBjYXB0dXJlIGV4Y2VwdGlvbiEiKSxuO2NvbnN0IHI9bmV3IEVycm9yKCJTZW50cnkgc3ludGhldGljRXhjZXB0aW9uIik7cmV0dXJuIHRoaXMuQS5jYXB0dXJlRXhjZXB0aW9uKHQse29yaWdpbmFsRXhjZXB0aW9uOnQsc3ludGhldGljRXhjZXB0aW9uOnIsLi4uZSxldmVudF9pZDpufSx0aGlzKSxufWNhcHR1cmVNZXNzYWdlKHQsZSxuKXtjb25zdCByPW4/LmV2ZW50X2lkfHxXKCk7aWYoIXRoaXMuQSlyZXR1cm4gaCYmXy53YXJuKCJObyBjbGllbnQgY29uZmlndXJlZCBvbiBzY29wZSAtIHdpbGwgbm90IGNhcHR1cmUgbWVzc2FnZSEiKSxyO2NvbnN0IG89bj8uc3ludGhldGljRXhjZXB0aW9uPz9uZXcgRXJyb3IodCk7cmV0dXJuIHRoaXMuQS5jYXB0dXJlTWVzc2FnZSh0LGUse29yaWdpbmFsRXhjZXB0aW9uOnQsc3ludGhldGljRXhjZXB0aW9uOm8sLi4ubixldmVudF9pZDpyfSx0aGlzKSxyfWNhcHR1cmVFdmVudCh0LGUpe2NvbnN0IG49dC5ldmVudF9pZHx8ZT8uZXZlbnRfaWR8fFcoKTtyZXR1cm4gdGhpcy5BPyh0aGlzLkEuY2FwdHVyZUV2ZW50KHQsey4uLmUsZXZlbnRfaWQ6bn0sdGhpcyksbik6KGgmJl8ud2FybigiTm8gY2xpZW50IGNvbmZpZ3VyZWQgb24gc2NvcGUgLSB3aWxsIG5vdCBjYXB0dXJlIGV2ZW50ISIpLG4pfVIoKXt0aGlzLnR8fCh0aGlzLnQ9ITAsdGhpcy5vLmZvckVhY2godD0+e3QodGhpcyl9KSx0aGlzLnQ9ITEpfX1jb25zdCBWPSJfX1NFTlRSWV9TVVBQUkVTU19UUkFDSU5HX18iLFE9dD0+dCBpbnN0YW5jZW9mIFByb21pc2UmJiF0W1hdLFg9U3ltYm9sKCJjaGFpbmVkIFByb21pc2VMaWtlIiksdHQ9KHQsZSk9PntpZighZSlyZXR1cm4gdDtsZXQgbj0hMTtmb3IoY29uc3QgciBpbiB0KXtpZihyIGluIGUpY29udGludWU7bj0hMDtjb25zdCBvPXRbcl07ImZ1bmN0aW9uIj09dHlwZW9mIG8/T2JqZWN0LmRlZmluZVByb3BlcnR5KGUscix7dmFsdWU6KC4uLmUpPT5vLmFwcGx5KHQsZSksZW51bWVyYWJsZTohMCxjb25maWd1cmFibGU6ITAsd3JpdGFibGU6ITB9KTplW3JdPW99cmV0dXJuIG4mJk9iamVjdC5hc3NpZ24oZSx7W1hdOiEwfSksZX07Y2xhc3MgZXR7Y29uc3RydWN0b3IodCxlKXtsZXQgbixyO249dHx8bmV3IEsscj1lfHxuZXcgSyx0aGlzLkk9W3tzY29wZTpufV0sdGhpcy5EPXJ9d2l0aFNjb3BlKHQpe2NvbnN0IGU9dGhpcy5VKCk7bGV0IG47dHJ5e249dChlKX1jYXRjaCh0KXt0aHJvdyB0aGlzLkIoKSx0fXJldHVybiBDKG4pPygodCxlLG4pPT57Y29uc3Qgcj10LnRoZW4odD0+KGUodCksdCksdD0+e3Rocm93IG4odCksdH0pO3JldHVybiBRKHIpJiZRKHQpP3I6dHQodCxyKX0pKG4sKCk9PnRoaXMuQigpLCgpPT50aGlzLkIoKSk6KHRoaXMuQigpLG4pfWdldENsaWVudCgpe3JldHVybiB0aGlzLmdldFN0YWNrVG9wKCkuY2xpZW50fWdldFNjb3BlKCl7cmV0dXJuIHRoaXMuZ2V0U3RhY2tUb3AoKS5zY29wZX1nZXRJc29sYXRpb25TY29wZSgpe3JldHVybiB0aGlzLkR9Z2V0U3RhY2tUb3AoKXtyZXR1cm4gdGhpcy5JW3RoaXMuSS5sZW5ndGgtMV19VSgpe2NvbnN0IHQ9dGhpcy5nZXRTY29wZSgpLmNsb25lKCk7cmV0dXJuIHRoaXMuSS5wdXNoKHtjbGllbnQ6dGhpcy5nZXRDbGllbnQoKSxzY29wZTp0fSksdH1CKCl7cmV0dXJuISh0aGlzLkkubGVuZ3RoPD0xKSYmISF0aGlzLkkucG9wKCl9fWZ1bmN0aW9uIG50KCl7Y29uc3QgdD1nKGQoKSk7cmV0dXJuIHQuc3RhY2s9dC5zdGFja3x8bmV3IGV0KG0oImRlZmF1bHRDdXJyZW50U2NvcGUiLCgpPT5uZXcgSyksbSgiZGVmYXVsdElzb2xhdGlvblNjb3BlIiwoKT0+bmV3IEspKX1mdW5jdGlvbiBydCh0KXtyZXR1cm4gbnQoKS53aXRoU2NvcGUodCl9ZnVuY3Rpb24gb3QodCxlKXtjb25zdCBuPW50KCk7cmV0dXJuIG4ud2l0aFNjb3BlKCgpPT4obi5nZXRTdGFja1RvcCgpLnNjb3BlPXQsZSh0KSkpfWZ1bmN0aW9uIHN0KHQpe3JldHVybiBudCgpLndpdGhTY29wZSgoKT0+dChudCgpLmdldElzb2xhdGlvblNjb3BlKCkpKX1mdW5jdGlvbiBpdCh0KXtyZXR1cm4gcnQoZT0+e2Uuc2V0U0RLUHJvY2Vzc2luZ01ldGFkYXRhKHtbVl06ITB9KTtjb25zdCBuPXQoKTtyZXR1cm4gZS5zZXRTREtQcm9jZXNzaW5nTWV0YWRhdGEoe1tWXTp2b2lkIDB9KSxufSl9ZnVuY3Rpb24gY3QodCl7Y29uc3QgZT1nKHQpO3JldHVybiBlLmFjcz9lLmFjczp7c3VwcHJlc3NUcmFjaW5nOml0LHdpdGhJc29sYXRpb25TY29wZTpzdCx3aXRoU2NvcGU6cnQsd2l0aFNldFNjb3BlOm90LHdpdGhTZXRJc29sYXRpb25TY29wZToodCxlKT0+c3QoZSksZ2V0Q3VycmVudFNjb3BlOigpPT5udCgpLmdldFNjb3BlKCksZ2V0SXNvbGF0aW9uU2NvcGU6KCk9Pm50KCkuZ2V0SXNvbGF0aW9uU2NvcGUoKX19ZnVuY3Rpb24gdXQodCxlPSExKXtjb25zdHtob3N0Om4scGF0aDpyLHBhc3M6byxwb3J0OnMscHJvamVjdElkOmkscHJvdG9jb2w6YyxwdWJsaWNLZXk6dX09dDtyZXR1cm5gJHtjfTovLyR7dX0ke2UmJm8/YDoke299YDoiIn1AJHtufSR7cz9gOiR7c31gOiIifS8ke3I/YCR7cn0vYDpyfSR7aX1gfWZ1bmN0aW9uIGF0KHQsZSl7Y29uc3R7ZmluZ2VycHJpbnQ6bixicmVhZGNydW1iczpyLHNka1Byb2Nlc3NpbmdNZXRhZGF0YTpvfT1lOyFmdW5jdGlvbih0LGUpe2NvbnN0e2V4dHJhOm4sdGFnczpyLHVzZXI6byxjb250ZXh0czpzLGxldmVsOmksdHJhbnNhY3Rpb25OYW1lOmN9PWU7T2JqZWN0LmtleXMobikubGVuZ3RoJiYodC5leHRyYT17Li4ubiwuLi50LmV4dHJhfSk7T2JqZWN0LmtleXMocikubGVuZ3RoJiYodC50YWdzPXsuLi5yLC4uLnQudGFnc30pO09iamVjdC5rZXlzKG8pLmxlbmd0aCYmKHQudXNlcj17Li4ubywuLi50LnVzZXJ9KTtPYmplY3Qua2V5cyhzKS5sZW5ndGgmJih0LmNvbnRleHRzPXsuLi5zLC4uLnQuY29udGV4dHN9KTtpJiYodC5sZXZlbD1pKTtjJiYidHJhbnNhY3Rpb24iIT09dC50eXBlJiYodC50cmFuc2FjdGlvbj1jKX0odCxlKSxmdW5jdGlvbih0LGUpe3QuZmluZ2VycHJpbnQ9dC5maW5nZXJwcmludD9BcnJheS5pc0FycmF5KHQuZmluZ2VycHJpbnQpP3QuZmluZ2VycHJpbnQ6W3QuZmluZ2VycHJpbnRdOltdLGUmJih0LmZpbmdlcnByaW50PXQuZmluZ2VycHJpbnQuY29uY2F0KGUpKTt0LmZpbmdlcnByaW50Lmxlbmd0aHx8ZGVsZXRlIHQuZmluZ2VycHJpbnR9KHQsbiksZnVuY3Rpb24odCxlKXtjb25zdCBuPVsuLi50LmJyZWFkY3J1bWJzfHxbXSwuLi5lXTt0LmJyZWFkY3J1bWJzPW4ubGVuZ3RoP246dm9pZCAwfSh0LHIpLGZ1bmN0aW9uKHQsZSl7dC5zZGtQcm9jZXNzaW5nTWV0YWRhdGE9ey4uLnQuc2RrUHJvY2Vzc2luZ01ldGFkYXRhLC4uLmV9fSh0LG8pfWZ1bmN0aW9uIGZ0KHQsZT1bXSl7cmV0dXJuW3QsZV19ZnVuY3Rpb24gaHQodCxlKXtjb25zdCBuPXRbMV07Zm9yKGNvbnN0IHQgb2Ygbil7aWYoZSh0LHRbMF0udHlwZSkpcmV0dXJuITB9cmV0dXJuITF9ZnVuY3Rpb24gcHQodCl7Y29uc3QgZT1nKHApO3JldHVybiBlLmVuY29kZVBvbHlmaWxsP2UuZW5jb2RlUG9seWZpbGwodCk6KG5ldyBUZXh0RW5jb2RlcikuZW5jb2RlKHQpfWZ1bmN0aW9uIGx0KHQpe2NvbnN0W2Usbl09dDtsZXQgcj1KU09OLnN0cmluZ2lmeShlKTtmdW5jdGlvbiBvKHQpeyJzdHJpbmciPT10eXBlb2Ygcj9yPSJzdHJpbmciPT10eXBlb2YgdD9yK3Q6W3B0KHIpLHRdOnIucHVzaCgic3RyaW5nIj09dHlwZW9mIHQ/cHQodCk6dCl9Zm9yKGNvbnN0IHQgb2Ygbil7Y29uc3RbZSxuXT10O2lmKG8oYFxuJHtKU09OLnN0cmluZ2lmeShlKX1cbmApLCJzdHJpbmciPT10eXBlb2Ygbnx8biBpbnN0YW5jZW9mIFVpbnQ4QXJyYXkpbyhuKTtlbHNle2xldCB0O3RyeXt0PUpTT04uc3RyaW5naWZ5KG4pfWNhdGNoe3Q9SlNPTi5zdHJpbmdpZnkoQihuKSl9byh0KX19cmV0dXJuInN0cmluZyI9PXR5cGVvZiByP3I6ZnVuY3Rpb24odCl7Y29uc3QgZT10LnJlZHVjZSgodCxlKT0+dCtlLmxlbmd0aCwwKSxuPW5ldyBVaW50OEFycmF5KGUpO2xldCByPTA7Zm9yKGNvbnN0IGUgb2YgdCluLnNldChlLHIpLHIrPWUubGVuZ3RoO3JldHVybiBufShyKX1jb25zdCBkdD17c2Vzc2lvbnM6InNlc3Npb24iLGV2ZW50OiJlcnJvciIsY2xpZW50X3JlcG9ydDoiaW50ZXJuYWwiLHVzZXJfcmVwb3J0OiJkZWZhdWx0Iixwcm9maWxlX2NodW5rOiJwcm9maWxlIixyZXBsYXlfZXZlbnQ6InJlcGxheSIscmVwbGF5X3JlY29yZGluZzoicmVwbGF5IixjaGVja19pbjoibW9uaXRvciIscmF3X3NlY3VyaXR5OiJzZWN1cml0eSIsbG9nOiJsb2dfaXRlbSIsdHJhY2VfbWV0cmljOiJtZXRyaWMifTtmdW5jdGlvbiBndCh0KXtyZXR1cm4gZnVuY3Rpb24odCl7cmV0dXJuIHQgaW4gZHR9KHQpP2R0W3RdOnR9ZnVuY3Rpb24gbXQodCl7aWYoIXQ/LnNkaylyZXR1cm47Y29uc3R7bmFtZTplLHZlcnNpb246bn09dC5zZGs7cmV0dXJue25hbWU6ZSx2ZXJzaW9uOm59fWZ1bmN0aW9uIHl0KHQpe2NvbnN0IGU9Y3QoZCgpKTtyZXR1cm4gZS5zdXBwcmVzc1RyYWNpbmc/ZS5zdXBwcmVzc1RyYWNpbmcodCk6ZnVuY3Rpb24oLi4udCl7Y29uc3QgZT1jdChkKCkpO2lmKDI9PT10Lmxlbmd0aCl7Y29uc3RbbixyXT10O3JldHVybiBuP2Uud2l0aFNldFNjb3BlKG4scik6ZS53aXRoU2NvcGUocil9cmV0dXJuIGUud2l0aFNjb3BlKHRbMF0pfShlPT4oZS5zZXRTREtQcm9jZXNzaW5nTWV0YWRhdGEoe1tWXTohMH0pLHQoKSkpfWZ1bmN0aW9uIGJ0KHQsZSxuLHIpe2NvbnN0IG89bXQobikscz10LnR5cGUmJiJyZXBsYXlfZXZlbnQiIT09dC50eXBlP3QudHlwZToiZXZlbnQiOyFmdW5jdGlvbih0LGUpe2lmKCFlKXJldHVybiB0O2NvbnN0IG49dC5zZGt8fHt9O3Quc2RrPXsuLi5uLG5hbWU6bi5uYW1lfHxlLm5hbWUsdmVyc2lvbjpuLnZlcnNpb258fGUudmVyc2lvbixpbnRlZ3JhdGlvbnM6Wy4uLnQuc2RrPy5pbnRlZ3JhdGlvbnN8fFtdLC4uLmUuaW50ZWdyYXRpb25zfHxbXV0scGFja2FnZXM6Wy4uLnQuc2RrPy5wYWNrYWdlc3x8W10sLi4uZS5wYWNrYWdlc3x8W11dLHNldHRpbmdzOnQuc2RrPy5zZXR0aW5nc3x8ZS5zZXR0aW5ncz97Li4udC5zZGs/LnNldHRpbmdzLC4uLmUuc2V0dGluZ3N9OnZvaWQgMH19KHQsbj8uc2RrKTtjb25zdCBpPWZ1bmN0aW9uKHQsZSxuLHIpe2NvbnN0IG89dC5zZGtQcm9jZXNzaW5nTWV0YWRhdGE/LmR5bmFtaWNTYW1wbGluZ0NvbnRleHQ7cmV0dXJue2V2ZW50X2lkOnQuZXZlbnRfaWQsc2VudF9hdDpuZXcgRGF0ZShJKCkpLnRvSVNPU3RyaW5nKCksLi4uZSYme3NkazplfSwuLi4hIW4mJnImJntkc246dXQocil9LC4uLm8mJnt0cmFjZTpvfX19KHQsbyxyLGUpO2RlbGV0ZSB0LnNka1Byb2Nlc3NpbmdNZXRhZGF0YTtyZXR1cm4gZnQoaSxbW3t0eXBlOnN9LHRdXSl9Y2xhc3MgdnR7Y29uc3RydWN0b3IodCl7dGhpcy5MPTAsdGhpcy5NPVtdLHRoaXMuSih0KX10aGVuKHQsZSl7cmV0dXJuIG5ldyB2dCgobixyKT0+e3RoaXMuTS5wdXNoKFshMSxlPT57aWYodCl0cnl7bih0KGUpKX1jYXRjaCh0KXtyKHQpfWVsc2UgbihlKX0sdD0+e2lmKGUpdHJ5e24oZSh0KSl9Y2F0Y2godCl7cih0KX1lbHNlIHIodCl9XSksdGhpcy5XKCl9KX1jYXRjaCh0KXtyZXR1cm4gdGhpcy50aGVuKHQ9PnQsdCl9ZmluYWxseSh0KXtyZXR1cm4gbmV3IHZ0KChlLG4pPT57bGV0IHIsbztyZXR1cm4gdGhpcy50aGVuKGU9PntvPSExLHI9ZSx0JiZ0KCl9LGU9PntvPSEwLHI9ZSx0JiZ0KCl9KS50aGVuKCgpPT57bz9uKHIpOmUocil9KX0pfVcoKXtpZigwPT09dGhpcy5MKXJldHVybjtjb25zdCB0PXRoaXMuTS5zbGljZSgpO3RoaXMuTT1bXSx0LmZvckVhY2godD0+e3RbMF18fCgxPT09dGhpcy5MJiZ0WzFdKHRoaXMuRiksMj09PXRoaXMuTCYmdFsyXSh0aGlzLkYpLHRbMF09ITApfSl9Sih0KXtjb25zdCBlPSh0LGUpPT57MD09PXRoaXMuTCYmKEMoZSk/ZS50aGVuKG4scik6KHRoaXMuTD10LHRoaXMuRj1lLHRoaXMuVygpKSl9LG49dD0+e2UoMSx0KX0scj10PT57ZSgyLHQpfTt0cnl7dChuLHIpfWNhdGNoKHQpe3IodCl9fX1jb25zdCB3dD1TeW1ib2wuZm9yKCJTZW50cnlCdWZmZXJGdWxsRXJyb3IiKTtmdW5jdGlvbiBTdCh0PTEwMCl7Y29uc3QgZT1uZXcgU2V0O2Z1bmN0aW9uIG4odCl7ZS5kZWxldGUodCl9cmV0dXJue2dldCAkKCl7cmV0dXJuIEFycmF5LmZyb20oZSl9LGFkZDpmdW5jdGlvbihyKXtpZighKGUuc2l6ZTx0KSlyZXR1cm4gbz13dCxuZXcgdnQoKHQsZSk9PntlKG8pfSk7dmFyIG87Y29uc3Qgcz1yKCk7cmV0dXJuIGUuYWRkKHMpLHMudGhlbigoKT0+bihzKSwoKT0+bihzKSksc30sZHJhaW46ZnVuY3Rpb24odCl7aWYoIWUuc2l6ZSlyZXR1cm4gbj0hMCxuZXcgdnQodD0+e3Qobil9KTt2YXIgbjtjb25zdCByPVByb21pc2UuYWxsU2V0dGxlZChBcnJheS5mcm9tKGUpKS50aGVuKCgpPT4hMCk7aWYoIXQpcmV0dXJuIHI7Y29uc3Qgbz1bcixuZXcgUHJvbWlzZShlPT57cmV0dXJuIm9iamVjdCI9PXR5cGVvZihuPXNldFRpbWVvdXQoKCk9PmUoITEpLHQpKSYmImZ1bmN0aW9uIj09dHlwZW9mIG4udW5yZWYmJm4udW5yZWYoKSxuO3ZhciBufSldO3JldHVybiBQcm9taXNlLnJhY2Uobyl9fX1mdW5jdGlvbiBfdCh0LHtzdGF0dXNDb2RlOmUsaGVhZGVyczpufSxyPUkoKSl7Y29uc3Qgbz17Li4udH0scz1uPy5bIngtc2VudHJ5LXJhdGUtbGltaXRzIl0saT1uPy5bInJldHJ5LWFmdGVyIl07aWYocylmb3IoY29uc3QgdCBvZiBzLnRyaW0oKS5zcGxpdCgiLCIpKXtjb25zdFtlLG4sLCxzXT10LnNwbGl0KCI6Iiw1KSxpPXBhcnNlSW50KGUsMTApLGM9MWUzKihpc05hTihpKT82MDppKTtpZihuKWZvcihjb25zdCB0IG9mIG4uc3BsaXQoIjsiKSkibWV0cmljX2J1Y2tldCI9PT10JiZzJiYhcy5zcGxpdCgiOyIpLmluY2x1ZGVzKCJjdXN0b20iKXx8KG9bdF09citjKTtlbHNlIG8uYWxsPXIrY31lbHNlIGk/by5hbGw9citmdW5jdGlvbih0LGU9SSgpKXtjb25zdCBuPXBhcnNlSW50KGAke3R9YCwxMCk7aWYoIWlzTmFOKG4pKXJldHVybiAxZTMqbjtjb25zdCByPURhdGUucGFyc2UoYCR7dH1gKTtyZXR1cm4gaXNOYU4ocik/NmU0OnItZX0oaSxyKTo0Mjk9PT1lJiYoby5hbGw9cis2ZTQpO3JldHVybiBvfWZ1bmN0aW9uICR0KHQsZSxuPVN0KHQuYnVmZmVyU2l6ZXx8NjQpKXtsZXQgcj17fTtyZXR1cm57c2VuZDpmdW5jdGlvbih0KXtjb25zdCBvPVtdO2lmKGh0KHQsKHQsZSk9Pntjb25zdCBuPWd0KGUpOyhmdW5jdGlvbih0LGUsbj1JKCkpe3JldHVybiBmdW5jdGlvbih0LGUpe3JldHVybiB0W2VdfHx0LmFsbHx8MH0odCxlKT5ufSkocixuKXx8by5wdXNoKHQpfSksMD09PW8ubGVuZ3RoKXJldHVybiBQcm9taXNlLnJlc29sdmUoe30pO2NvbnN0IHM9ZnQodFswXSxvKSxpPXQ9PnshZnVuY3Rpb24odCxlKXtyZXR1cm4gaHQodCwodCxuKT0+ZS5pbmNsdWRlcyhuKSl9KHMsWyJjbGllbnRfcmVwb3J0Il0pP2h0KHMsKHQsZSk9Pnt9KTpoJiZfLndhcm4oYERyb3BwaW5nIGNsaWVudCByZXBvcnQuIFdpbGwgbm90IHNlbmQgb3V0Y29tZXMgKHJlYXNvbjogJHt0fSkuYCl9O3JldHVybiBuLmFkZCgoKT0+ZSh7Ym9keTpsdChzKX0pLnRoZW4odD0+NDEzPT09dC5zdGF0dXNDb2RlPyhoJiZfLmVycm9yKCJTZW50cnkgcmVzcG9uZGVkIHdpdGggc3RhdHVzIGNvZGUgNDEzLiBFbnZlbG9wZSB3YXMgZGlzY2FyZGVkIGR1ZSB0byBleGNlZWRpbmcgc2l6ZSBsaW1pdHMuIiksaSgic2VuZF9lcnJvciIpLHQpOihoJiZ2b2lkIDAhPT10LnN0YXR1c0NvZGUmJih0LnN0YXR1c0NvZGU8MjAwfHx0LnN0YXR1c0NvZGU+PTMwMCkmJl8ud2FybihgU2VudHJ5IHJlc3BvbmRlZCB3aXRoIHN0YXR1cyBjb2RlICR7dC5zdGF0dXNDb2RlfSB0byBzZW50IGV2ZW50LmApLHI9X3Qocix0KSx0KSx0PT57dGhyb3cgaSgibmV0d29ya19lcnJvciIpLGgmJl8uZXJyb3IoIkVuY291bnRlcmVkIGVycm9yIHJ1bm5pbmcgdHJhbnNwb3J0IHJlcXVlc3Q6Iix0KSx0fSkpLnRoZW4odD0+dCx0PT57aWYodD09PXd0KXJldHVybiBoJiZfLmVycm9yKCJTa2lwcGVkIHNlbmRpbmcgZXZlbnQgYmVjYXVzZSBidWZmZXIgaXMgZnVsbC4iKSxpKCJxdWV1ZV9vdmVyZmxvdyIpLFByb21pc2UucmVzb2x2ZSh7fSk7dGhyb3cgdH0pfSxmbHVzaDp0PT5uLmRyYWluKHQpfX1jb25zdCBFdD0vXihcUys6XFx8XC8/KShbXHNcU10qPykoKD86XC57MSwyfXxbXi9cXF0rP3wpKFwuW14uL1xcXSp8KSkoPzpbL1xcXSopJC87ZnVuY3Rpb24geHQodCl7Y29uc3QgZT1mdW5jdGlvbih0KXtjb25zdCBlPXQubGVuZ3RoPjEwMjQ/YDx0cnVuY2F0ZWQ+JHt0LnNsaWNlKC0xMDI0KX1gOnQsbj1FdC5leGVjKGUpO3JldHVybiBuP24uc2xpY2UoMSk6W119KHQpLG49ZVswXXx8IiI7bGV0IHI9ZVsxXTtyZXR1cm4gbnx8cj8ociYmKHI9ci5zbGljZSgwLHIubGVuZ3RoLTEpKSxuK3IpOiIuIn1mdW5jdGlvbiBOdCh0LGU9ITEpe3JldHVybiEoZXx8dCYmIXQuc3RhcnRzV2l0aCgiLyIpJiYhdC5tYXRjaCgvXltBLVpdOi8pJiYhdC5zdGFydHNXaXRoKCIuIikmJiF0Lm1hdGNoKC9eW2EtekEtWl0oW2EtekEtWjAtOS5cLStdKSo6XC9cLy8pKSYmdm9pZCAwIT09dCYmIXQuaW5jbHVkZXMoIm5vZGVfbW9kdWxlcy8iKX12YXIganQ7Y29uc3QgQ3Q9U3ltYm9sKCJBZ2VudEJhc2VJbnRlcm5hbFN0YXRlIik7Y2xhc3MgT3QgZXh0ZW5kcyhqdD1zLkFnZW50LGp0KXtjb25zdHJ1Y3Rvcih0KXtzdXBlcih0KSx0aGlzW0N0XT17fX1pc1NlY3VyZUVuZHBvaW50KHQpe2lmKHQpe2lmKCJib29sZWFuIj09dHlwZW9mIHQuc2VjdXJlRW5kcG9pbnQpcmV0dXJuIHQuc2VjdXJlRW5kcG9pbnQ7aWYoInN0cmluZyI9PXR5cGVvZiB0LnByb3RvY29sKXJldHVybiJodHRwczoiPT09dC5wcm90b2NvbH1jb25zdHtzdGFjazplfT1uZXcgRXJyb3I7cmV0dXJuInN0cmluZyI9PXR5cGVvZiBlJiZlLnNwbGl0KCJcbiIpLnNvbWUodD0+LTEhPT10LmluZGV4T2YoIihodHRwcy5qczoiKXx8LTEhPT10LmluZGV4T2YoIm5vZGU6aHR0cHM6IikpfWNyZWF0ZVNvY2tldCh0LGUsbil7Y29uc3Qgcj17Li4uZSxzZWN1cmVFbmRwb2ludDp0aGlzLmlzU2VjdXJlRW5kcG9pbnQoZSl9O1Byb21pc2UucmVzb2x2ZSgpLnRoZW4oKCk9PnRoaXMuY29ubmVjdCh0LHIpKS50aGVuKG89PntpZihvIGluc3RhbmNlb2Ygcy5BZ2VudClyZXR1cm4gby5hZGRSZXF1ZXN0KHQscik7dGhpc1tDdF0uY3VycmVudFNvY2tldD1vLHN1cGVyLmNyZWF0ZVNvY2tldCh0LGUsbil9LG4pfWNyZWF0ZUNvbm5lY3Rpb24oKXtjb25zdCB0PXRoaXNbQ3RdLmN1cnJlbnRTb2NrZXQ7aWYodGhpc1tDdF0uY3VycmVudFNvY2tldD12b2lkIDAsIXQpdGhyb3cgbmV3IEVycm9yKCJObyBzb2NrZXQgd2FzIHJldHVybmVkIGluIHRoZSBgY29ubmVjdCgpYCBmdW5jdGlvbiIpO3JldHVybiB0fWdldCBkZWZhdWx0UG9ydCgpe3JldHVybiB0aGlzW0N0XS5kZWZhdWx0UG9ydD8/KCJodHRwczoiPT09dGhpcy5wcm90b2NvbD80NDM6ODApfXNldCBkZWZhdWx0UG9ydCh0KXt0aGlzW0N0XSYmKHRoaXNbQ3RdLmRlZmF1bHRQb3J0PXQpfWdldCBwcm90b2NvbCgpe3JldHVybiB0aGlzW0N0XS5wcm90b2NvbD8/KHRoaXMuaXNTZWN1cmVFbmRwb2ludCgpPyJodHRwczoiOiJodHRwOiIpfXNldCBwcm90b2NvbCh0KXt0aGlzW0N0XSYmKHRoaXNbQ3RdLnByb3RvY29sPXQpfX1mdW5jdGlvbiBQdCguLi50KXtfLmxvZygiW2h0dHBzLXByb3h5LWFnZW50OnBhcnNlLXByb3h5LXJlc3BvbnNlXSIsLi4udCl9ZnVuY3Rpb24gQXQodCl7cmV0dXJuIG5ldyBQcm9taXNlKChlLG4pPT57bGV0IHI9MDtjb25zdCBvPVtdO2Z1bmN0aW9uIHMoKXtjb25zdCBjPXQucmVhZCgpO2M/ZnVuY3Rpb24oYyl7by5wdXNoKGMpLHIrPWMubGVuZ3RoO2NvbnN0IHU9QnVmZmVyLmNvbmNhdChvLHIpLGE9dS5pbmRleE9mKCJcclxuXHJcbiIpO2lmKC0xPT09YSlyZXR1cm4gUHQoImhhdmUgbm90IHJlY2VpdmVkIGVuZCBvZiBIVFRQIGhlYWRlcnMgeWV0Li4uIiksdm9pZCBzKCk7Y29uc3QgZj11LnN1YmFycmF5KDAsYSkudG9TdHJpbmcoImFzY2lpIikuc3BsaXQoIlxyXG4iKSxoPWYuc2hpZnQoKTtpZighaClyZXR1cm4gdC5kZXN0cm95KCksbihuZXcgRXJyb3IoIk5vIGhlYWRlciByZWNlaXZlZCBmcm9tIHByb3h5IENPTk5FQ1QgcmVzcG9uc2UiKSk7Y29uc3QgcD1oLnNwbGl0KCIgIiksbD0rKHBbMV18fDApLGQ9cC5zbGljZSgyKS5qb2luKCIgIiksZz17fTtmb3IoY29uc3QgZSBvZiBmKXtpZighZSljb250aW51ZTtjb25zdCByPWUuaW5kZXhPZigiOiIpO2lmKC0xPT09cilyZXR1cm4gdC5kZXN0cm95KCksbihuZXcgRXJyb3IoYEludmFsaWQgaGVhZGVyIGZyb20gcHJveHkgQ09OTkVDVCByZXNwb25zZTogIiR7ZX0iYCkpO2NvbnN0IG89ZS5zbGljZSgwLHIpLnRvTG93ZXJDYXNlKCkscz1lLnNsaWNlKHIrMSkudHJpbVN0YXJ0KCksaT1nW29dOyJzdHJpbmciPT10eXBlb2YgaT9nW29dPVtpLHNdOkFycmF5LmlzQXJyYXkoaSk/aS5wdXNoKHMpOmdbb109c31QdCgiZ290IHByb3h5IHNlcnZlciByZXNwb25zZTogJW8gJW8iLGgsZyksaSgpLGUoe2Nvbm5lY3Q6e3N0YXR1c0NvZGU6bCxzdGF0dXNUZXh0OmQsaGVhZGVyczpnfSxidWZmZXJlZDp1fSl9KGMpOnQub25jZSgicmVhZGFibGUiLHMpfWZ1bmN0aW9uIGkoKXt0LnJlbW92ZUxpc3RlbmVyKCJlbmQiLGMpLHQucmVtb3ZlTGlzdGVuZXIoImVycm9yIix1KSx0LnJlbW92ZUxpc3RlbmVyKCJyZWFkYWJsZSIscyl9ZnVuY3Rpb24gYygpe2koKSxQdCgib25lbmQiKSxuKG5ldyBFcnJvcigiUHJveHkgY29ubmVjdGlvbiBlbmRlZCBiZWZvcmUgcmVjZWl2aW5nIENPTk5FQ1QgcmVzcG9uc2UiKSl9ZnVuY3Rpb24gdSh0KXtpKCksUHQoIm9uZXJyb3IgJW8iLHQpLG4odCl9dC5vbigiZXJyb3IiLHUpLHQub24oImVuZCIsYykscygpfSl9ZnVuY3Rpb24ga3QoLi4udCl7Xy5sb2coIltodHRwcy1wcm94eS1hZ2VudF0iLC4uLnQpfWNsYXNzIFR0IGV4dGVuZHMgT3R7Y29uc3RydWN0b3IodCxlKXtzdXBlcihlKSx0aGlzLm9wdGlvbnM9e30sdGhpcy5wcm94eT0ic3RyaW5nIj09dHlwZW9mIHQ/bmV3IFVSTCh0KTp0LHRoaXMucHJveHlIZWFkZXJzPWU/LmhlYWRlcnM/P3t9LGt0KCJDcmVhdGluZyBuZXcgSHR0cHNQcm94eUFnZW50IGluc3RhbmNlOiAlbyIsdGhpcy5wcm94eS5ocmVmKTtjb25zdCBuPSh0aGlzLnByb3h5Lmhvc3RuYW1lfHx0aGlzLnByb3h5Lmhvc3QpLnJlcGxhY2UoL15cW3xcXSQvZywiIikscj10aGlzLnByb3h5LnBvcnQ/cGFyc2VJbnQodGhpcy5wcm94eS5wb3J0LDEwKToiaHR0cHM6Ij09PXRoaXMucHJveHkucHJvdG9jb2w/NDQzOjgwO3RoaXMuY29ubmVjdE9wdHM9e0FMUE5Qcm90b2NvbHM6WyJodHRwLzEuMSJdLC4uLmU/SXQoZSwiaGVhZGVycyIpOm51bGwsaG9zdDpuLHBvcnQ6cn19YXN5bmMgY29ubmVjdCh0LGUpe2NvbnN0e3Byb3h5Om59PXRoaXM7aWYoIWUuaG9zdCl0aHJvdyBuZXcgVHlwZUVycm9yKCdObyAiaG9zdCIgcHJvdmlkZWQnKTtsZXQgcjtpZigiaHR0cHM6Ij09PW4ucHJvdG9jb2wpe2t0KCJDcmVhdGluZyBgdGxzLlNvY2tldGA6ICVvIix0aGlzLmNvbm5lY3RPcHRzKTtjb25zdCB0PXRoaXMuY29ubmVjdE9wdHMuc2VydmVybmFtZXx8dGhpcy5jb25uZWN0T3B0cy5ob3N0O3I9Zi5jb25uZWN0KHsuLi50aGlzLmNvbm5lY3RPcHRzLHNlcnZlcm5hbWU6dCYmYS5pc0lQKHQpP3ZvaWQgMDp0fSl9ZWxzZSBrdCgiQ3JlYXRpbmcgYG5ldC5Tb2NrZXRgOiAlbyIsdGhpcy5jb25uZWN0T3B0cykscj1hLmNvbm5lY3QodGhpcy5jb25uZWN0T3B0cyk7Y29uc3Qgbz0iZnVuY3Rpb24iPT10eXBlb2YgdGhpcy5wcm94eUhlYWRlcnM/dGhpcy5wcm94eUhlYWRlcnMoKTp7Li4udGhpcy5wcm94eUhlYWRlcnN9LHM9YS5pc0lQdjYoZS5ob3N0KT9gWyR7ZS5ob3N0fV1gOmUuaG9zdDtsZXQgaT1gQ09OTkVDVCAke3N9OiR7ZS5wb3J0fSBIVFRQLzEuMVxyXG5gO2lmKG4udXNlcm5hbWV8fG4ucGFzc3dvcmQpe2NvbnN0IHQ9YCR7ZGVjb2RlVVJJQ29tcG9uZW50KG4udXNlcm5hbWUpfToke2RlY29kZVVSSUNvbXBvbmVudChuLnBhc3N3b3JkKX1gO29bIlByb3h5LUF1dGhvcml6YXRpb24iXT1gQmFzaWMgJHtCdWZmZXIuZnJvbSh0KS50b1N0cmluZygiYmFzZTY0Iil9YH1vLkhvc3Q9YCR7c306JHtlLnBvcnR9YCxvWyJQcm94eS1Db25uZWN0aW9uIl18fChvWyJQcm94eS1Db25uZWN0aW9uIl09dGhpcy5rZWVwQWxpdmU/IktlZXAtQWxpdmUiOiJjbG9zZSIpO2Zvcihjb25zdCB0IG9mIE9iamVjdC5rZXlzKG8pKWkrPWAke3R9OiAke29bdF19XHJcbmA7Y29uc3QgYz1BdChyKTtyLndyaXRlKGAke2l9XHJcbmApO2NvbnN0e2Nvbm5lY3Q6dSxidWZmZXJlZDpofT1hd2FpdCBjO2lmKHQuZW1pdCgicHJveHlDb25uZWN0Iix1KSx0aGlzLmVtaXQoInByb3h5Q29ubmVjdCIsdSx0KSwyMDA9PT11LnN0YXR1c0NvZGUpe2lmKHQub25jZSgic29ja2V0IixSdCksZS5zZWN1cmVFbmRwb2ludCl7a3QoIlVwZ3JhZGluZyBzb2NrZXQgY29ubmVjdGlvbiB0byBUTFMiKTtjb25zdCB0PWUuc2VydmVybmFtZXx8ZS5ob3N0O3JldHVybiBmLmNvbm5lY3Qoey4uLkl0KGUsImhvc3QiLCJwYXRoIiwicG9ydCIpLHNvY2tldDpyLHNlcnZlcm5hbWU6YS5pc0lQKHQpP3ZvaWQgMDp0fSl9cmV0dXJuIHJ9ci5kZXN0cm95KCk7Y29uc3QgcD1uZXcgYS5Tb2NrZXQoe3dyaXRhYmxlOiExfSk7cmV0dXJuIHAucmVhZGFibGU9ITAsdC5vbmNlKCJzb2NrZXQiLHQ9PntrdCgiUmVwbGF5aW5nIHByb3h5IGJ1ZmZlciBmb3IgZmFpbGVkIHJlcXVlc3QiKSx0LnB1c2goaCksdC5wdXNoKG51bGwpfSkscH19ZnVuY3Rpb24gUnQodCl7dC5yZXN1bWUoKX1mdW5jdGlvbiBJdCh0LC4uLmUpe2NvbnN0IG49e307bGV0IHI7Zm9yKHIgaW4gdCllLmluY2x1ZGVzKHIpfHwobltyXT10W3JdKTtyZXR1cm4gbn1UdC5wcm90b2NvbHM9WyJodHRwIiwiaHR0cHMiXTtmdW5jdGlvbiBEdCh0KXtyZXR1cm4gdC5yZXBsYWNlKC9eW0EtWl06LywiIikucmVwbGFjZSgvXFwvZywiLyIpfWNvbnN0IFV0PWU7bGV0IEJ0LEx0PTAsTXQ9e307ZnVuY3Rpb24genQodCl7VXQuZGVidWcmJmNvbnNvbGUubG9nKGBbQU5SIFdvcmtlcl0gJHt0fWApfXZhciBKdCxXdCxGdDtjb25zdCBHdD1mdW5jdGlvbih0KXtsZXQgZTt0cnl7ZT1uZXcgVVJMKHQudXJsKX1jYXRjaHtyZXR1cm4gYigoKT0+e2NvbnNvbGUud2FybigiW0BzZW50cnkvbm9kZV06IEludmFsaWQgZHNuIG9yIHR1bm5lbCBvcHRpb24sIHdpbGwgbm90IHNlbmQgYW55IGV2ZW50cy4gVGhlIHR1bm5lbCBvcHRpb24gbXVzdCBiZSBhIGZ1bGwgVVJMIHdoZW4gdXNlZC4iKX0pLCR0KHQsKCk9PlByb21pc2UucmVzb2x2ZSh7fSkpfWNvbnN0IG49Imh0dHBzOiI9PT1lLnByb3RvY29sLHI9ZnVuY3Rpb24odCxlKXtjb25zdHtub19wcm94eTpufT1wcm9jZXNzLmVudixyPW4/LnNwbGl0KCIsIikuc29tZShlPT50Lmhvc3QuZW5kc1dpdGgoZSl8fHQuaG9zdG5hbWUuZW5kc1dpdGgoZSkpO3JldHVybiByP3ZvaWQgMDplfShlLHQucHJveHl8fChuP3Byb2Nlc3MuZW52Lmh0dHBzX3Byb3h5OnZvaWQgMCl8fHByb2Nlc3MuZW52Lmh0dHBfcHJveHkpLG89bj9pOnMsYT12b2lkIDAhPT10LmtlZXBBbGl2ZSYmdC5rZWVwQWxpdmUsZj1yP25ldyBUdChyKTpuZXcgby5BZ2VudCh7a2VlcEFsaXZlOmEsbWF4U29ja2V0czozMCx0aW1lb3V0OjJlM30pLGg9ZnVuY3Rpb24odCxlLG4pe2NvbnN0e2hvc3RuYW1lOnIscGF0aG5hbWU6byxwb3J0OnMscHJvdG9jb2w6aSxzZWFyY2g6YX09bmV3IFVSTCh0LnVybCk7cmV0dXJuIGZ1bmN0aW9uKGYpe3JldHVybiBuZXcgUHJvbWlzZSgoaCxwKT0+e3l0KCgpPT57bGV0IGw9ZnVuY3Rpb24odCl7cmV0dXJuIG5ldyBjKHtyZWFkKCl7dGhpcy5wdXNoKHQpLHRoaXMucHVzaChudWxsKX19KX0oZi5ib2R5KTtjb25zdCBkPXsuLi50LmhlYWRlcnN9O2YuYm9keS5sZW5ndGg+MzI3NjgmJihkWyJjb250ZW50LWVuY29kaW5nIl09Imd6aXAiLGw9bC5waXBlKHUoKSkpO2NvbnN0IGc9ci5zdGFydHNXaXRoKCJbIiksbT1lLnJlcXVlc3Qoe21ldGhvZDoiUE9TVCIsYWdlbnQ6bixoZWFkZXJzOmQsaG9zdG5hbWU6Zz9yLnNsaWNlKDEsLTEpOnIscGF0aDpgJHtvfSR7YX1gLHBvcnQ6cyxwcm90b2NvbDppLGNhOnQuY2FDZXJ0c30sdD0+e3Qub24oImRhdGEiLCgpPT57fSksdC5vbigiZW5kIiwoKT0+e30pLHQuc2V0RW5jb2RpbmcoInV0ZjgiKTtjb25zdCBlPXQuaGVhZGVyc1sicmV0cnktYWZ0ZXIiXT8/bnVsbCxuPXQuaGVhZGVyc1sieC1zZW50cnktcmF0ZS1saW1pdHMiXT8/bnVsbDtoKHtzdGF0dXNDb2RlOnQuc3RhdHVzQ29kZSxoZWFkZXJzOnsicmV0cnktYWZ0ZXIiOmUsIngtc2VudHJ5LXJhdGUtbGltaXRzIjpBcnJheS5pc0FycmF5KG4pP25bMF18fG51bGw6bn19KX0pO20ub24oImVycm9yIixwKSxsLnBpcGUobSl9KX0pfX0odCx0Lmh0dHBNb2R1bGU/P28sZik7cmV0dXJuICR0KHQsaCl9KHt1cmw6KEp0PVV0LmRzbixXdD1VdC50dW5uZWwsRnQ9VXQuc2RrTWV0YWRhdGEuc2RrLFd0fHxgJHtmdW5jdGlvbih0KXtyZXR1cm5gJHtmdW5jdGlvbih0KXtjb25zdCBlPXQucHJvdG9jb2w/YCR7dC5wcm90b2NvbH06YDoiIixuPXQucG9ydD9gOiR7dC5wb3J0fWA6IiI7cmV0dXJuYCR7ZX0vLyR7dC5ob3N0fSR7bn0ke3QucGF0aD9gLyR7dC5wYXRofWA6IiJ9L2FwaS9gfSh0KX0ke3QucHJvamVjdElkfS9lbnZlbG9wZS9gfShKdCl9PyR7ZnVuY3Rpb24odCxlKXtjb25zdCBuPXtzZW50cnlfdmVyc2lvbjoiNyJ9O3JldHVybiB0LnB1YmxpY0tleSYmKG4uc2VudHJ5X2tleT10LnB1YmxpY0tleSksZSYmKG4uc2VudHJ5X2NsaWVudD1gJHtlLm5hbWV9LyR7ZS52ZXJzaW9ufWApLG5ldyBVUkxTZWFyY2hQYXJhbXMobikudG9TdHJpbmcoKX0oSnQsRnQpfWApfSk7YXN5bmMgZnVuY3Rpb24gWXQoKXtpZihCdCl7enQoIlNlbmRpbmcgYWJub3JtYWwgc2Vzc2lvbiIpLFooQnQse3N0YXR1czoiYWJub3JtYWwiLGFibm9ybWFsX21lY2hhbmlzbToiYW5yX2ZvcmVncm91bmQiLHJlbGVhc2U6VXQucmVsZWFzZSxlbnZpcm9ubWVudDpVdC5lbnZpcm9ubWVudH0pO2NvbnN0IHQ9ZnVuY3Rpb24odCxlLG4scil7Y29uc3Qgbz1tdChuKTtyZXR1cm4gZnQoe3NlbnRfYXQ6bmV3IERhdGUoSSgpKS50b0lTT1N0cmluZygpLC4uLm8mJntzZGs6b30sLi4uISFyJiZlJiZ7ZHNuOnV0KGUpfX0sWyJhZ2dyZWdhdGVzImluIHQ/W3t0eXBlOiJzZXNzaW9ucyJ9LHRdOlt7dHlwZToic2Vzc2lvbiJ9LHQudG9KU09OKCldXSl9KEJ0LFV0LmRzbixVdC5zZGtNZXRhZGF0YSxVdC50dW5uZWwpO3p0KEpTT04uc3RyaW5naWZ5KHQpKSxhd2FpdCBHdC5zZW5kKHQpO3RyeXtuPy5wb3N0TWVzc2FnZSgic2Vzc2lvbi1lbmRlZCIpfWNhdGNoe319fWZ1bmN0aW9uIEh0KHQpe2lmKCF0KXJldHVybjtjb25zdCBlPWZ1bmN0aW9uKHQpe2lmKCF0Lmxlbmd0aClyZXR1cm5bXTtjb25zdCBlPUFycmF5LmZyb20odCk7cmV0dXJuL3NlbnRyeVdyYXBwZWQvLnRlc3QoRShlKS5mdW5jdGlvbnx8IiIpJiZlLnBvcCgpLGUucmV2ZXJzZSgpLCQudGVzdChFKGUpLmZ1bmN0aW9ufHwiIikmJihlLnBvcCgpLCQudGVzdChFKGUpLmZ1bmN0aW9ufHwiIikmJmUucG9wKCkpLGUuc2xpY2UoMCw1MCkubWFwKHQ9Pih7Li4udCxmaWxlbmFtZTp0LmZpbGVuYW1lfHxFKGUpLmZpbGVuYW1lLGZ1bmN0aW9uOnQuZnVuY3Rpb258fCI/In0pKX0odCk7aWYoVXQuYXBwUm9vdFBhdGgpZm9yKGNvbnN0IHQgb2YgZSl0LmZpbGVuYW1lJiYodC5maWxlbmFtZT1NKHQuZmlsZW5hbWUsVXQuYXBwUm9vdFBhdGgpKTtyZXR1cm4gZX1hc3luYyBmdW5jdGlvbiBadCh0LGUpe2lmKEx0Pj1VdC5tYXhBbnJFdmVudHMpcmV0dXJuO0x0Kz0xLGF3YWl0IFl0KCksenQoIlNlbmRpbmcgZXZlbnQiKTtjb25zdCBuPXtldmVudF9pZDpXKCksY29udGV4dHM6VXQuY29udGV4dHMscmVsZWFzZTpVdC5yZWxlYXNlLGVudmlyb25tZW50OlV0LmVudmlyb25tZW50LGRpc3Q6VXQuZGlzdCxwbGF0Zm9ybToibm9kZSIsbGV2ZWw6ImVycm9yIixleGNlcHRpb246e3ZhbHVlczpbe3R5cGU6IkFwcGxpY2F0aW9uTm90UmVzcG9uZGluZyIsdmFsdWU6YEFwcGxpY2F0aW9uIE5vdCBSZXNwb25kaW5nIGZvciBhdCBsZWFzdCAke1V0LmFuclRocmVzaG9sZH0gbXNgLHN0YWNrdHJhY2U6e2ZyYW1lczpIdCh0KX0sbWVjaGFuaXNtOnt0eXBlOiJBTlIifX1dfSx0YWdzOlV0LnN0YXRpY1RhZ3N9O2UmJmZ1bmN0aW9uKHQsZSl7aWYoYXQodCxlKSwhdC5jb250ZXh0cz8udHJhY2Upe2NvbnN0e3RyYWNlSWQ6bixwYXJlbnRTcGFuSWQ6cixwcm9wYWdhdGlvblNwYW5JZDpvfT1lLnByb3BhZ2F0aW9uQ29udGV4dDt0LmNvbnRleHRzPXt0cmFjZTp7dHJhY2VfaWQ6bixzcGFuX2lkOm98fFcoKS5zdWJzdHJpbmcoMTYpLHBhcmVudF9zcGFuX2lkOnJ9LC4uLnQuY29udGV4dHN9fX0obixlKSxmdW5jdGlvbih0KXtpZigwPT09T2JqZWN0LmtleXMoTXQpLmxlbmd0aClyZXR1cm47Y29uc3QgZT1VdC5hcHBSb290UGF0aD97fTpNdDtpZihVdC5hcHBSb290UGF0aClmb3IoY29uc3RbdCxuXW9mIE9iamVjdC5lbnRyaWVzKE10KSllW00odCxVdC5hcHBSb290UGF0aCldPW47Y29uc3Qgbj1uZXcgTWFwO2Zvcihjb25zdCByIG9mIHQuZXhjZXB0aW9uPy52YWx1ZXN8fFtdKWZvcihjb25zdCB0IG9mIHIuc3RhY2t0cmFjZT8uZnJhbWVzfHxbXSl7Y29uc3Qgcj10LmFic19wYXRofHx0LmZpbGVuYW1lO3ImJmVbcl0mJm4uc2V0KHIsZVtyXSl9aWYobi5zaXplPjApe2NvbnN0IGU9W107Zm9yKGNvbnN0W3Qscl1vZiBuLmVudHJpZXMoKSllLnB1c2goe3R5cGU6InNvdXJjZW1hcCIsY29kZV9maWxlOnQsZGVidWdfaWQ6cn0pO3QuZGVidWdfbWV0YT17aW1hZ2VzOmV9fX0obik7Y29uc3Qgcj1idChuLFV0LmRzbixVdC5zZGtNZXRhZGF0YSxVdC50dW5uZWwpO3p0KEpTT04uc3RyaW5naWZ5KHIpKSxhd2FpdCBHdC5zZW5kKHIpLGF3YWl0IEd0LmZsdXNoKDJlMyksTHQ+PVV0Lm1heEFuckV2ZW50cyYmc2V0VGltZW91dCgoKT0+e3Byb2Nlc3MuZXhpdCgwKX0sNWUzKX1sZXQgcXQ7aWYoenQoIlN0YXJ0ZWQiKSxVdC5jYXB0dXJlU3RhY2tUcmFjZSl7enQoIkNvbm5lY3RpbmcgdG8gZGVidWdnZXIiKTtjb25zdCBlPW5ldyB0O2UuY29ubmVjdFRvTWFpblRocmVhZCgpLHp0KCJDb25uZWN0ZWQgdG8gZGVidWdnZXIiKTtjb25zdCBuPW5ldyBNYXA7ZS5vbigiRGVidWdnZXIuc2NyaXB0UGFyc2VkIix0PT57bi5zZXQodC5wYXJhbXMuc2NyaXB0SWQsdC5wYXJhbXMudXJsKX0pLGUub24oIkRlYnVnZ2VyLnBhdXNlZCIsdD0+e2lmKCJvdGhlciI9PT10LnBhcmFtcy5yZWFzb24pdHJ5e3p0KCJEZWJ1Z2dlciBwYXVzZWQiKTtjb25zdCBzPVsuLi50LnBhcmFtcy5jYWxsRnJhbWVzXSxpPVV0LmFwcFJvb3RQYXRoP2Z1bmN0aW9uKHQ9KHByb2Nlc3MuYXJndlsxXT94dChwcm9jZXNzLmFyZ3ZbMV0pOnByb2Nlc3MuY3dkKCkpLGU9IlxcIj09PW8pe2NvbnN0IG49ZT9EdCh0KTp0O3JldHVybiB0PT57aWYoIXQpcmV0dXJuO2NvbnN0IG89ZT9EdCh0KTp0O2xldHtkaXI6cyxiYXNlOmksZXh0OmN9PXIucGFyc2Uobyk7Ii5qcyIhPT1jJiYiLm1qcyIhPT1jJiYiLmNqcyIhPT1jfHwoaT1pLnNsaWNlKDAsLTEqYy5sZW5ndGgpKTtjb25zdCB1PWRlY29kZVVSSUNvbXBvbmVudChpKTtzfHwocz0iLiIpO2NvbnN0IGE9cy5sYXN0SW5kZXhPZigiL25vZGVfbW9kdWxlcyIpO2lmKGE+LTEpcmV0dXJuYCR7cy5zbGljZShhKzE0KS5yZXBsYWNlKC9cLy9nLCIuIil9OiR7dX1gO2lmKHMuc3RhcnRzV2l0aChuKSl7Y29uc3QgdD1zLnNsaWNlKG4ubGVuZ3RoKzEpLnJlcGxhY2UoL1wvL2csIi4iKTtyZXR1cm4gdD9gJHt0fToke3V9YDp1fXJldHVybiB1fX0oVXQuYXBwUm9vdFBhdGgpOigpPT57fSxjPXMubWFwKHQ9PmZ1bmN0aW9uKHQsZSxuKXtjb25zdCByPWU/ZS5yZXBsYWNlKC9eZmlsZTpcL1wvLywiIik6dm9pZCAwLG89dC5sb2NhdGlvbi5jb2x1bW5OdW1iZXI/dC5sb2NhdGlvbi5jb2x1bW5OdW1iZXIrMTp2b2lkIDAscz10LmxvY2F0aW9uLmxpbmVOdW1iZXI/dC5sb2NhdGlvbi5saW5lTnVtYmVyKzE6dm9pZCAwO3JldHVybntmaWxlbmFtZTpyLG1vZHVsZTpuKHIpLGZ1bmN0aW9uOnQuZnVuY3Rpb25OYW1lfHwiPyIsY29sbm86byxsaW5lbm86cyxpbl9hcHA6cj9OdChyKTp2b2lkIDB9fSh0LG4uZ2V0KHQubG9jYXRpb24uc2NyaXB0SWQpLGkpKSx1PXNldFRpbWVvdXQoKCk9PntadChjKS50aGVuKG51bGwsKCk9Pnt6dCgiU2VuZGluZyBBTlIgZXZlbnQgZmFpbGVkLiIpfSl9LDVlMyk7ZS5wb3N0KCJSdW50aW1lLmV2YWx1YXRlIix7ZXhwcmVzc2lvbjoiZ2xvYmFsLl9fU0VOVFJZX0dFVF9TQ09QRVNfXygpOyIsc2lsZW50OiEwLHJldHVybkJ5VmFsdWU6ITB9LCh0LG4pPT57dCYmenQoYEVycm9yIGV4ZWN1dGluZyBzY3JpcHQ6ICcke3QubWVzc2FnZX0nYCksY2xlYXJUaW1lb3V0KHUpO2NvbnN0IHI9bj8ucmVzdWx0P24ucmVzdWx0LnZhbHVlOnZvaWQgMDtlLnBvc3QoIkRlYnVnZ2VyLnJlc3VtZSIpLGUucG9zdCgiRGVidWdnZXIuZGlzYWJsZSIpLFp0KGMscikudGhlbihudWxsLCgpPT57enQoIlNlbmRpbmcgQU5SIGV2ZW50IGZhaWxlZC4iKX0pfSl9Y2F0Y2godCl7dGhyb3cgZS5wb3N0KCJEZWJ1Z2dlci5yZXN1bWUiKSxlLnBvc3QoIkRlYnVnZ2VyLmRpc2FibGUiKSx0fX0pLHF0PSgpPT57dHJ5e2UucG9zdCgiRGVidWdnZXIuZW5hYmxlIiwoKT0+e2UucG9zdCgiRGVidWdnZXIucGF1c2UiKX0pfWNhdGNoe319fWNvbnN0e3BvbGw6S3R9PWZ1bmN0aW9uKHQsZSxuLHIpe2NvbnN0IG89dCgpO2xldCBzPSExLGk9ITA7cmV0dXJuIHNldEludGVydmFsKCgpPT57Y29uc3QgdD1vLmdldFRpbWVNcygpOyExPT09cyYmdD5lK24mJihzPSEwLGkmJnIoKSksdDxlK24mJihzPSExKX0sMjApLHtwb2xsOigpPT57by5yZXNldCgpfSxlbmFibGVkOnQ9PntpPXR9fX0oZnVuY3Rpb24oKXtsZXQgdD1wcm9jZXNzLmhydGltZSgpO3JldHVybntnZXRUaW1lTXM6KCk9Pntjb25zdFtlLG5dPXByb2Nlc3MuaHJ0aW1lKHQpO3JldHVybiBNYXRoLmZsb29yKDFlMyplK24vMWU2KX0scmVzZXQ6KCk9Pnt0PXByb2Nlc3MuaHJ0aW1lKCl9fX0sVXQucG9sbEludGVydmFsLFV0LmFuclRocmVzaG9sZCxmdW5jdGlvbigpe3p0KCJXYXRjaGRvZyB0aW1lb3V0IikscXQ/KHp0KCJQYXVzaW5nIGRlYnVnZ2VyIHRvIGNhcHR1cmUgc3RhY2sgdHJhY2UiKSxxdCgpKTooenQoIkNhcHR1cmluZyBldmVudCB3aXRob3V0IGEgc3RhY2sgdHJhY2UiKSxadCgpLnRoZW4obnVsbCwoKT0+e3p0KCJTZW5kaW5nIEFOUiBldmVudCBmYWlsZWQgb24gd2F0Y2hkb2cgdGltZW91dC4iKX0pKX0pO24/Lm9uKCJtZXNzYWdlIix0PT57dC5zZXNzaW9uJiYoQnQ9SCh0LnNlc3Npb24pKSx0LmRlYnVnSW1hZ2VzJiYoTXQ9dC5kZWJ1Z0ltYWdlcyksS3QoKX0pOw==";
|
|
9
|
+
const base64WorkerScript = "LyohIEBzZW50cnkvbm9kZSAxMS4wLjAtYmV0YS4wICg1NGJiYWU5KSB8IGh0dHBzOi8vZ2l0aHViLmNvbS9nZXRzZW50cnkvc2VudHJ5LWphdmFzY3JpcHQgKi8KaW1wb3J0e1Nlc3Npb24gYXMgdH1mcm9tIm5vZGU6aW5zcGVjdG9yIjtpbXBvcnR7d29ya2VyRGF0YSBhcyBlLHBhcmVudFBvcnQgYXMgbn1mcm9tIm5vZGU6d29ya2VyX3RocmVhZHMiO2ltcG9ydHtwb3NpeCBhcyByLHNlcCBhcyBvfWZyb20ibm9kZTpwYXRoIjtpbXBvcnQqYXMgcyBmcm9tIm5vZGU6aHR0cCI7aW1wb3J0KmFzIGkgZnJvbSJub2RlOmh0dHBzIjtpbXBvcnR7UmVhZGFibGUgYXMgY31mcm9tIm5vZGU6c3RyZWFtIjtpbXBvcnR7Y3JlYXRlR3ppcCBhcyB1fWZyb20ibm9kZTp6bGliIjtpbXBvcnQqYXMgYSBmcm9tIm5vZGU6bmV0IjtpbXBvcnQqYXMgZiBmcm9tIm5vZGU6dGxzIjtjb25zdCBoPSJ1bmRlZmluZWQiPT10eXBlb2YgX19TRU5UUllfREVCVUdfX3x8X19TRU5UUllfREVCVUdfXyxwPWdsb2JhbFRoaXMsbD0iMTEuMC4wLWJldGEuMCI7ZnVuY3Rpb24gZCgpe3JldHVybiBnKHApLHB9ZnVuY3Rpb24gZyh0KXtjb25zdCBlPXQuX19TRU5UUllfXz10Ll9fU0VOVFJZX198fHt9O3JldHVybiBlLnZlcnNpb249ZS52ZXJzaW9ufHxsLGVbbF09ZVtsXXx8e319ZnVuY3Rpb24gbSh0LGUsbj1wKXtjb25zdCByPW4uX19TRU5UUllfXz1uLl9fU0VOVFJZX198fHt9LG89cltsXT1yW2xdfHx7fTtyZXR1cm4gb1t0XXx8KG9bdF09ZSgpKX1jb25zdCB5PXt9O2Z1bmN0aW9uIGIodCl7aWYoISgiY29uc29sZSJpbiBwKSlyZXR1cm4gdCgpO2NvbnN0IGU9cC5jb25zb2xlLG49e30scj1PYmplY3Qua2V5cyh5KTtyLmZvckVhY2godD0+e2NvbnN0IHI9eVt0XTtuW3RdPWVbdF0sZVt0XT1yfSk7dHJ5e3JldHVybiB0KCl9ZmluYWxseXtyLmZvckVhY2godD0+e2VbdF09blt0XX0pfX1mdW5jdGlvbiB2KCl7cmV0dXJuIFMoKS5lbmFibGVkfWZ1bmN0aW9uIHcodCwuLi5lKXtoJiZ2KCkmJmIoKCk9PntwLmNvbnNvbGVbdF0oYFNlbnRyeSBMb2dnZXIgWyR7dH1dOmAsLi4uZSl9KX1mdW5jdGlvbiBTKCl7cmV0dXJuIGg/bSgibG9nZ2VyU2V0dGluZ3MiLCgpPT4oe2VuYWJsZWQ6ITF9KSk6e2VuYWJsZWQ6ITF9fWNvbnN0IF89e2VuYWJsZTpmdW5jdGlvbigpe1MoKS5lbmFibGVkPSEwfSxkaXNhYmxlOmZ1bmN0aW9uKCl7UygpLmVuYWJsZWQ9ITF9LGlzRW5hYmxlZDp2LGxvZzpmdW5jdGlvbiguLi50KXt3KCJsb2ciLC4uLnQpfSx3YXJuOmZ1bmN0aW9uKC4uLnQpe3coIndhcm4iLC4uLnQpfSxlcnJvcjpmdW5jdGlvbiguLi50KXt3KCJlcnJvciIsLi4udCl9fSwkPS9jYXB0dXJlTWVzc2FnZXxjYXB0dXJlRXhjZXB0aW9uLztmdW5jdGlvbiBFKHQpe3JldHVybiB0W3QubGVuZ3RoLTFdfHx7fX1jb25zdCB4PSI8YW5vbnltb3VzPiI7Y29uc3QgTj1PYmplY3QucHJvdG90eXBlLnRvU3RyaW5nO2Z1bmN0aW9uIEModCl7cmV0dXJuIGZ1bmN0aW9uKHQsZSl7cmV0dXJuIE4uY2FsbCh0KT09PWBbb2JqZWN0ICR7ZX1dYH0odCwiT2JqZWN0Iil9ZnVuY3Rpb24gaih0KXtyZXR1cm4gQm9vbGVhbih0Py50aGVuJiYiZnVuY3Rpb24iPT10eXBlb2YgdC50aGVuKX1mdW5jdGlvbiBPKHQsZSl7dHJ5e3JldHVybiB0IGluc3RhbmNlb2YgZX1jYXRjaHtyZXR1cm4hMX19ZnVuY3Rpb24gUCh0KXtpZihmdW5jdGlvbih0KXtzd2l0Y2goTi5jYWxsKHQpKXtjYXNlIltvYmplY3QgRXJyb3JdIjpjYXNlIltvYmplY3QgRXhjZXB0aW9uXSI6Y2FzZSJbb2JqZWN0IERPTUV4Y2VwdGlvbl0iOmNhc2UiW29iamVjdCBXZWJBc3NlbWJseS5FeGNlcHRpb25dIjpyZXR1cm4hMDtkZWZhdWx0OnJldHVybiBPKHQsRXJyb3IpfX0odCkpcmV0dXJue21lc3NhZ2U6dC5tZXNzYWdlLG5hbWU6dC5uYW1lLHN0YWNrOnQuc3RhY2ssLi4uQSh0KX07aWYoZT10LCJ1bmRlZmluZWQiIT10eXBlb2YgRXZlbnQmJk8oZSxFdmVudCkpe2NvbnN0e3R5cGU6ZSx0YXJnZXQ6bixjdXJyZW50VGFyZ2V0OnIsZGV0YWlsOm99PXQ7cmV0dXJue3R5cGU6ZSx0YXJnZXQ6bixjdXJyZW50VGFyZ2V0OnIsLi4ubz97ZGV0YWlsOm99Ont9LC4uLkEodCl9fXZhciBlO3JldHVybiB0fWZ1bmN0aW9uIEEodCl7cmV0dXJuIm9iamVjdCI9PXR5cGVvZihlPXQpJiZudWxsIT09ZT9PYmplY3QuZnJvbUVudHJpZXMoT2JqZWN0LmVudHJpZXModCkpOnt9O3ZhciBlfWxldCBUO2Z1bmN0aW9uIGsodCl7aWYodm9pZCAwIT09VClyZXR1cm4gVD9UKHQpOnQoKTtjb25zdCBlPVN5bWJvbC5mb3IoIl9fU0VOVFJZX1NBRkVfUkFORE9NX0lEX1dSQVBQRVJfXyIpLG49cDtyZXR1cm4gZSBpbiBuJiYiZnVuY3Rpb24iPT10eXBlb2YgbltlXT8oVD1uW2VdLFQodCkpOihUPW51bGwsdCgpKX1mdW5jdGlvbiBSKCl7cmV0dXJuIGsoKCk9Pk1hdGgucmFuZG9tKCkpfWZ1bmN0aW9uIEkoKXtyZXR1cm4gaygoKT0+RGF0ZS5ub3coKSl9Y29uc3QgRD1TeW1ib2wuZm9yKCJzZW50cnkuc2tpcE5vcm1hbGl6YXRpb24iKSxVPVN5bWJvbC5mb3IoInNlbnRyeS5vdmVycmlkZU5vcm1hbGl6YXRpb25EZXB0aCIpO2Z1bmN0aW9uIEIodCxlPTEwMCxuPTEvMCl7dHJ5e3JldHVybiBMKCIiLHQsZSxuKX1jYXRjaCh0KXtyZXR1cm57RVJST1I6YCoqbm9uLXNlcmlhbGl6YWJsZSoqICgke3R9KWB9fX1mdW5jdGlvbiBMKHQsZSxuPTEvMCxyPTEvMCxvPWZ1bmN0aW9uKCl7Y29uc3QgdD1uZXcgV2Vha1NldDtmdW5jdGlvbiBlKGUpe3JldHVybiEhdC5oYXMoZSl8fCh0LmFkZChlKSwhMSl9ZnVuY3Rpb24gbihlKXt0LmRlbGV0ZShlKX1yZXR1cm5bZSxuXX0oKSl7Y29uc3RbcyxpXT1vO2lmKG51bGw9PWV8fFsiYm9vbGVhbiIsInN0cmluZyJdLmluY2x1ZGVzKHR5cGVvZiBlKXx8Im51bWJlciI9PXR5cGVvZiBlJiZOdW1iZXIuaXNGaW5pdGUoZSkpcmV0dXJuIGU7Y29uc3QgYz1mdW5jdGlvbih0LGUpe3RyeXtpZigidW5kZWZpbmVkIiE9dHlwZW9mIGdsb2JhbCYmZT09PWdsb2JhbClyZXR1cm4iW0dsb2JhbF0iO2lmKCJudW1iZXIiPT10eXBlb2YgZSYmIU51bWJlci5pc0Zpbml0ZShlKSlyZXR1cm5gWyR7ZX1dYDtpZigiZnVuY3Rpb24iPT10eXBlb2YgZSlyZXR1cm5gW0Z1bmN0aW9uOiAke2Z1bmN0aW9uKHQpe3RyeXtyZXR1cm4gdCYmImZ1bmN0aW9uIj09dHlwZW9mIHQmJnQubmFtZXx8eH1jYXRjaHtyZXR1cm4geH19KGUpfV1gO2lmKCJzeW1ib2wiPT10eXBlb2YgZSlyZXR1cm5gWyR7U3RyaW5nKGUpfV1gO2lmKCJiaWdpbnQiPT10eXBlb2YgZSlyZXR1cm5gW0JpZ0ludDogJHtTdHJpbmcoZSl9XWA7Y29uc3QgdD1mdW5jdGlvbih0KXtjb25zdCBlPU9iamVjdC5nZXRQcm90b3R5cGVPZih0KTtyZXR1cm4gZT8uY29uc3RydWN0b3I/ZS5jb25zdHJ1Y3Rvci5uYW1lOiJudWxsIHByb3RvdHlwZSJ9KGUpO3JldHVybmBbb2JqZWN0ICR7dH1dYH1jYXRjaCh0KXtyZXR1cm5gKipub24tc2VyaWFsaXphYmxlKiogKCR7dH0pYH19KDAsZSk7aWYoIWMuc3RhcnRzV2l0aCgiW29iamVjdCAiKSlyZXR1cm4gYztpZihmdW5jdGlvbih0KXtyZXR1cm4gQm9vbGVhbih0W0RdKX0oZSkpcmV0dXJuIGU7Y29uc3QgdT1mdW5jdGlvbih0KXtjb25zdCBlPXRbVV07cmV0dXJuIm51bWJlciI9PXR5cGVvZiBlP2U6dm9pZCAwfShlKSxhPXZvaWQgMCE9PXU/dTpuO2lmKDA9PT1hKXJldHVybiBjLnJlcGxhY2UoIm9iamVjdCAiLCIiKTtpZihzKGUpKXJldHVybiJbQ2lyY3VsYXIgfl0iO2NvbnN0IGY9ZTtpZihmJiYiZnVuY3Rpb24iPT10eXBlb2YgZi50b0pTT04pdHJ5e3JldHVybiBMKCIiLGYudG9KU09OKCksYS0xLHIsbyl9Y2F0Y2h7fWNvbnN0IGg9QXJyYXkuaXNBcnJheShlKT9bXTp7fTtsZXQgcD0wO2NvbnN0IGw9UChlKTtmb3IoY29uc3QgdCBpbiBsKXtpZighT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGwsdCkpY29udGludWU7aWYocD49cil7aFt0XT0iW01heFByb3BlcnRpZXMgfl0iO2JyZWFrfWNvbnN0IGU9bFt0XTtoW3RdPUwodCxlLGEtMSxyLG8pLHArK31yZXR1cm4gaShlKSxofWZ1bmN0aW9uIE0odCxlKXtjb25zdCBuPWUucmVwbGFjZSgvXFwvZywiLyIpLnJlcGxhY2UoL1t8XFx7fSgpW1xdXiQrKj8uXS9nLCJcXCQmIik7bGV0IHI9dDt0cnl7cj1kZWNvZGVVUkkodCl9Y2F0Y2h7fXJldHVybiByLnJlcGxhY2UoL1xcL2csIi8iKS5yZXBsYWNlKC93ZWJwYWNrOlwvPy9nLCIiKS5yZXBsYWNlKG5ldyBSZWdFeHAoYChmaWxlOi8vKT8vKiR7bn0vKmAsImlnIiksImFwcDovLy8iKX1mdW5jdGlvbiB6KHQsZT0wKXtyZXR1cm4ic3RyaW5nIiE9dHlwZW9mIHR8fDA9PT1lfHx0Lmxlbmd0aDw9ZT90OmAke3Quc2xpY2UoMCxlKX0uLi5gfWxldCBKO2Z1bmN0aW9uIFcodD1mdW5jdGlvbigpe2NvbnN0IHQ9cDtyZXR1cm4gdC5jcnlwdG98fHQubXNDcnlwdG99KCkpe3RyeXtpZih0Py5yYW5kb21VVUlEKXJldHVybiBrKCgpPT50LnJhbmRvbVVVSUQoKSkucmVwbGFjZSgvLS9nLCIiKX1jYXRjaHt9cmV0dXJuIEp8fChKPSIxMDAwMDAwMDEwMDA0MDAwODAwMDEwMDAwMDAwMDAwMCIpLEoucmVwbGFjZSgvWzAxOF0vZyx0PT4odF4oMTYqUigpJjE1KT4+dC80KS50b1N0cmluZygxNikpfWZ1bmN0aW9uIEYoKXtyZXR1cm4gSSgpLzFlM31sZXQgRztmdW5jdGlvbiBZKCl7cmV0dXJuKEc/PyhHPWZ1bmN0aW9uKCl7Y29uc3R7cGVyZm9ybWFuY2U6dH09cDtpZighdD8ubm93fHwhdC50aW1lT3JpZ2luKXJldHVybiBGO2NvbnN0IGU9dC50aW1lT3JpZ2luO3JldHVybigpPT4oZStrKCgpPT50Lm5vdygpKSkvMWUzfSgpKSkoKX1mdW5jdGlvbiBIKHQpe2NvbnN0IGU9WSgpLG49e3NpZDpXKCksaW5pdDohMCx0aW1lc3RhbXA6ZSxzdGFydGVkOmUsZHVyYXRpb246MCxzdGF0dXM6Im9rIixlcnJvcnM6MCxpZ25vcmVEdXJhdGlvbjohMSx0b0pTT046KCk9PmZ1bmN0aW9uKHQpe3JldHVybntzaWQ6YCR7dC5zaWR9YCxpbml0OnQuaW5pdCxzdGFydGVkOm5ldyBEYXRlKDFlMyp0LnN0YXJ0ZWQpLnRvSVNPU3RyaW5nKCksdGltZXN0YW1wOm5ldyBEYXRlKDFlMyp0LnRpbWVzdGFtcCkudG9JU09TdHJpbmcoKSxzdGF0dXM6dC5zdGF0dXMsZXJyb3JzOnQuZXJyb3JzLGRpZDoibnVtYmVyIj09dHlwZW9mIHQuZGlkfHwic3RyaW5nIj09dHlwZW9mIHQuZGlkP2Ake3QuZGlkfWA6dm9pZCAwLGR1cmF0aW9uOnQuZHVyYXRpb24sYWJub3JtYWxfbWVjaGFuaXNtOnQuYWJub3JtYWxfbWVjaGFuaXNtLGF0dHJzOntyZWxlYXNlOnQucmVsZWFzZSxlbnZpcm9ubWVudDp0LmVudmlyb25tZW50LGlwX2FkZHJlc3M6dC5pcEFkZHJlc3MsdXNlcl9hZ2VudDp0LnVzZXJBZ2VudH19fShuKX07cmV0dXJuIHQmJloobix0KSxufWZ1bmN0aW9uIFoodCxlPXt9KXtpZihlLnVzZXImJighdC5pcEFkZHJlc3MmJmUudXNlci5pcF9hZGRyZXNzJiYodC5pcEFkZHJlc3M9ZS51c2VyLmlwX2FkZHJlc3MpLHQuZGlkfHxlLmRpZHx8KHQuZGlkPWUudXNlci5pZHx8ZS51c2VyLmVtYWlsfHxlLnVzZXIudXNlcm5hbWUpKSx0LnRpbWVzdGFtcD1lLnRpbWVzdGFtcHx8WSgpLGUuYWJub3JtYWxfbWVjaGFuaXNtJiYodC5hYm5vcm1hbF9tZWNoYW5pc209ZS5hYm5vcm1hbF9tZWNoYW5pc20pLGUuaWdub3JlRHVyYXRpb24mJih0Lmlnbm9yZUR1cmF0aW9uPWUuaWdub3JlRHVyYXRpb24pLGUuc2lkJiYodC5zaWQ9MzI9PT1lLnNpZC5sZW5ndGg/ZS5zaWQ6VygpKSx2b2lkIDAhPT1lLmluaXQmJih0LmluaXQ9ZS5pbml0KSwhdC5kaWQmJmUuZGlkJiYodC5kaWQ9YCR7ZS5kaWR9YCksIm51bWJlciI9PXR5cGVvZiBlLnN0YXJ0ZWQmJih0LnN0YXJ0ZWQ9ZS5zdGFydGVkKSx0Lmlnbm9yZUR1cmF0aW9uKXQuZHVyYXRpb249dm9pZCAwO2Vsc2UgaWYoIm51bWJlciI9PXR5cGVvZiBlLmR1cmF0aW9uKXQuZHVyYXRpb249ZS5kdXJhdGlvbjtlbHNle2NvbnN0IGU9dC50aW1lc3RhbXAtdC5zdGFydGVkO3QuZHVyYXRpb249ZT49MD9lOjB9ZS5yZWxlYXNlJiYodC5yZWxlYXNlPWUucmVsZWFzZSksZS5lbnZpcm9ubWVudCYmKHQuZW52aXJvbm1lbnQ9ZS5lbnZpcm9ubWVudCksIXQuaXBBZGRyZXNzJiZlLmlwQWRkcmVzcyYmKHQuaXBBZGRyZXNzPWUuaXBBZGRyZXNzKSwhdC51c2VyQWdlbnQmJmUudXNlckFnZW50JiYodC51c2VyQWdlbnQ9ZS51c2VyQWdlbnQpLCJudW1iZXIiPT10eXBlb2YgZS5lcnJvcnMmJih0LmVycm9ycz1lLmVycm9ycyksZS5zdGF0dXMmJih0LnN0YXR1cz1lLnN0YXR1cyl9ZnVuY3Rpb24gcSh0LGUsbj0yKXtpZighZXx8Im9iamVjdCIhPXR5cGVvZiBlfHxuPD0wKXJldHVybiBlO2lmKHQmJjA9PT1PYmplY3Qua2V5cyhlKS5sZW5ndGgpcmV0dXJuIHQ7Y29uc3Qgcj17Li4udH07Zm9yKGNvbnN0IHQgaW4gZSlPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoZSx0KSYmKHJbdF09cShyW3RdLGVbdF0sbi0xKSk7cmV0dXJuIHJ9Y2xhc3MgS3tjb25zdHJ1Y3Rvcigpe3RoaXMudD0hMSx0aGlzLm89W10sdGhpcy5pPVtdLHRoaXMudT1bXSx0aGlzLmg9W10sdGhpcy5wPXt9LHRoaXMubD17fSx0aGlzLm09e30sdGhpcy52PXt9LHRoaXMuUz17fSx0aGlzLl89e30sZnVuY3Rpb24odCxlLG4pe3RyeXtPYmplY3QuZGVmaW5lUHJvcGVydHkodCxlLHt2YWx1ZTpuLHdyaXRhYmxlOiEwLGNvbmZpZ3VyYWJsZTohMH0pfWNhdGNoe2gmJl8ubG9nKGBGYWlsZWQgdG8gYWRkIG5vbi1lbnVtZXJhYmxlIHByb3BlcnR5ICIke1N0cmluZyhlKX0iIHRvIG9iamVjdGAsdCl9fSh0aGlzLCJyZWZzIix7fSksdGhpcy5OPXt0cmFjZUlkOlcoKSxzYW1wbGVSYW5kOlIoKX19Y2xvbmUoKXtjb25zdCB0PW5ldyBLO3JldHVybiB0LnU9Wy4uLnRoaXMudV0sdC5sPXsuLi50aGlzLmx9LHQubT17Li4udGhpcy5tfSx0LnY9ey4uLnRoaXMudn0sdC5TPXsuLi50aGlzLlN9LHRoaXMuUy5mbGFncyYmKHQuUy5mbGFncz17dmFsdWVzOlsuLi50aGlzLlMuZmxhZ3MudmFsdWVzXX0pLHQucD10aGlzLnAsdC5DPXRoaXMuQyx0Lmo9dGhpcy5qLHQuTz10aGlzLk8sdC5QPXRoaXMuUCx0Lmk9Wy4uLnRoaXMuaV0sdC5oPVsuLi50aGlzLmhdLHQuXz17Li4udGhpcy5ffSx0Lk49ey4uLnRoaXMuTn0sdC5BPXRoaXMuQSx0LlQ9dGhpcy5ULHQuaz10aGlzLmssdC5yZWZzPXsuLi50aGlzLnJlZnN9LHR9c2V0Q2xpZW50KHQpe3RoaXMuQT10fXNldExhc3RFdmVudElkKHQpe3RoaXMuVD10fWdldENsaWVudCgpe3JldHVybiB0aGlzLkF9bGFzdEV2ZW50SWQoKXtyZXR1cm4gdGhpcy5UfWFkZFNjb3BlTGlzdGVuZXIodCl7dGhpcy5vLnB1c2godCl9YWRkRXZlbnRQcm9jZXNzb3IodCl7cmV0dXJuIHRoaXMuaS5wdXNoKHQpLHRoaXN9c2V0VXNlcih0KXtyZXR1cm4gdGhpcy5wPXR8fHtlbWFpbDp2b2lkIDAsaWQ6dm9pZCAwLGlwX2FkZHJlc3M6dm9pZCAwLHVzZXJuYW1lOnZvaWQgMH0sdGhpcy5qJiZaKHRoaXMuaix7dXNlcjp0fSksdGhpcy5SKCksdGhpc31nZXRVc2VyKCl7cmV0dXJuIHRoaXMucH1zZXRDb252ZXJzYXRpb25JZCh0KXtyZXR1cm4gdGhpcy5rPXR8fHZvaWQgMCx0aGlzLlIoKSx0aGlzfXNldFRhZ3ModCl7cmV0dXJuIHRoaXMubD17Li4udGhpcy5sLC4uLnR9LHRoaXMuUigpLHRoaXN9c2V0VGFnKHQsZSl7cmV0dXJuIHRoaXMuc2V0VGFncyh7W3RdOmV9KX1zZXRBdHRyaWJ1dGVzKHQpe3JldHVybiB0aGlzLm09ey4uLnRoaXMubSwuLi50fSx0aGlzLlIoKSx0aGlzfXNldEF0dHJpYnV0ZSh0LGUpe3JldHVybiB0aGlzLnNldEF0dHJpYnV0ZXMoe1t0XTplfSl9cmVtb3ZlQXR0cmlidXRlKHQpe3JldHVybiB0IGluIHRoaXMubSYmKGRlbGV0ZSB0aGlzLm1bdF0sdGhpcy5SKCkpLHRoaXN9c2V0RXh0cmFzKHQpe3JldHVybiB0aGlzLnY9ey4uLnRoaXMudiwuLi50fSx0aGlzLlIoKSx0aGlzfXNldEV4dHJhKHQsZSl7cmV0dXJuIHRoaXMudj17Li4udGhpcy52LFt0XTplfSx0aGlzLlIoKSx0aGlzfXNldEZpbmdlcnByaW50KHQpe3JldHVybiB0aGlzLlA9dCx0aGlzLlIoKSx0aGlzfXNldExldmVsKHQpe3JldHVybiB0aGlzLkM9dCx0aGlzLlIoKSx0aGlzfXNldFRyYW5zYWN0aW9uTmFtZSh0KXtyZXR1cm4gdGhpcy5PPXQsdGhpcy5SKCksdGhpc31zZXRDb250ZXh0KHQsZSl7cmV0dXJuIG51bGw9PT1lP2RlbGV0ZSB0aGlzLlNbdF06dGhpcy5TW3RdPWUsdGhpcy5SKCksdGhpc31zZXRTZXNzaW9uKHQpe3JldHVybiB0P3RoaXMuaj10OmRlbGV0ZSB0aGlzLmosdGhpcy5SKCksdGhpc31nZXRTZXNzaW9uKCl7cmV0dXJuIHRoaXMuan11cGRhdGUodCl7aWYoIXQpcmV0dXJuIHRoaXM7Y29uc3QgZT0iZnVuY3Rpb24iPT10eXBlb2YgdD90KHRoaXMpOnQsbj1lIGluc3RhbmNlb2YgSz9lLmdldFNjb3BlRGF0YSgpOkMoZSk/dDp2b2lkIDAse3RhZ3M6cixhdHRyaWJ1dGVzOm8sZXh0cmE6cyx1c2VyOmksY29udGV4dHM6YyxsZXZlbDp1LGZpbmdlcnByaW50OmE9W10scHJvcGFnYXRpb25Db250ZXh0OmYsY29udmVyc2F0aW9uSWQ6aH09bnx8e307cmV0dXJuIHRoaXMubD17Li4udGhpcy5sLC4uLnJ9LHRoaXMubT17Li4udGhpcy5tLC4uLm99LHRoaXMudj17Li4udGhpcy52LC4uLnN9LHRoaXMuUz17Li4udGhpcy5TLC4uLmN9LGkmJk9iamVjdC5rZXlzKGkpLmxlbmd0aCYmKHRoaXMucD1pKSx1JiYodGhpcy5DPXUpLGEubGVuZ3RoJiYodGhpcy5QPWEpLGYmJih0aGlzLk49ZiksaCYmKHRoaXMuaz1oKSx0aGlzfWFkZEJyZWFkY3J1bWIodCxlKXtjb25zdCBuPSJudW1iZXIiPT10eXBlb2YgZT9lOjEwMDtpZihuPD0wKXJldHVybiB0aGlzO2NvbnN0IHI9e3RpbWVzdGFtcDpGKCksLi4udCxtZXNzYWdlOnQubWVzc2FnZT96KHQubWVzc2FnZSwyMDQ4KTp0Lm1lc3NhZ2V9O3JldHVybiB0aGlzLnUucHVzaChyKSx0aGlzLnUubGVuZ3RoPm4mJih0aGlzLnU9dGhpcy51LnNsaWNlKC1uKSx0aGlzLkE/LnJlY29yZERyb3BwZWRFdmVudCgiYnVmZmVyX292ZXJmbG93IiwibG9nX2l0ZW0iKSksdGhpcy5SKCksdGhpc31nZXRMYXN0QnJlYWRjcnVtYigpe3JldHVybiB0aGlzLnVbdGhpcy51Lmxlbmd0aC0xXX1jbGVhckJyZWFkY3J1bWJzKCl7cmV0dXJuIHRoaXMudT1bXSx0aGlzLlIoKSx0aGlzfWFkZEF0dGFjaG1lbnQodCl7cmV0dXJuIHRoaXMuaC5wdXNoKHQpLHRoaXN9Y2xlYXJBdHRhY2htZW50cygpe3JldHVybiB0aGlzLmg9W10sdGhpc31nZXRTY29wZURhdGEoKXtyZXR1cm57YnJlYWRjcnVtYnM6dGhpcy51LGF0dGFjaG1lbnRzOnRoaXMuaCxjb250ZXh0czp0aGlzLlMsdGFnczp0aGlzLmwsYXR0cmlidXRlczp0aGlzLm0sZXh0cmE6dGhpcy52LHVzZXI6dGhpcy5wLGxldmVsOnRoaXMuQyxmaW5nZXJwcmludDp0aGlzLlB8fFtdLGV2ZW50UHJvY2Vzc29yczp0aGlzLmkscHJvcGFnYXRpb25Db250ZXh0OnRoaXMuTixzZGtQcm9jZXNzaW5nTWV0YWRhdGE6dGhpcy5fLHRyYW5zYWN0aW9uTmFtZTp0aGlzLk8sY29udmVyc2F0aW9uSWQ6dGhpcy5rfX1zZXRTREtQcm9jZXNzaW5nTWV0YWRhdGEodCl7cmV0dXJuIHRoaXMuXz1xKHRoaXMuXyx0LDIpLHRoaXN9c2V0UHJvcGFnYXRpb25Db250ZXh0KHQpe3JldHVybiB0aGlzLk49dCx0aGlzfWdldFByb3BhZ2F0aW9uQ29udGV4dCgpe3JldHVybiB0aGlzLk59Y2FwdHVyZUV4Y2VwdGlvbih0LGUpe2NvbnN0IG49ZT8uZXZlbnRfaWR8fFcoKTtpZighdGhpcy5BKXJldHVybiBoJiZfLndhcm4oIk5vIGNsaWVudCBjb25maWd1cmVkIG9uIHNjb3BlIC0gd2lsbCBub3QgY2FwdHVyZSBleGNlcHRpb24hIiksbjtjb25zdCByPW5ldyBFcnJvcigiU2VudHJ5IHN5bnRoZXRpY0V4Y2VwdGlvbiIpO3JldHVybiB0aGlzLkEuY2FwdHVyZUV4Y2VwdGlvbih0LHtvcmlnaW5hbEV4Y2VwdGlvbjp0LHN5bnRoZXRpY0V4Y2VwdGlvbjpyLC4uLmUsZXZlbnRfaWQ6bn0sdGhpcyksbn1jYXB0dXJlTWVzc2FnZSh0LGUsbil7Y29uc3Qgcj1uPy5ldmVudF9pZHx8VygpO2lmKCF0aGlzLkEpcmV0dXJuIGgmJl8ud2FybigiTm8gY2xpZW50IGNvbmZpZ3VyZWQgb24gc2NvcGUgLSB3aWxsIG5vdCBjYXB0dXJlIG1lc3NhZ2UhIikscjtjb25zdCBvPW4/LnN5bnRoZXRpY0V4Y2VwdGlvbj8/bmV3IEVycm9yKHQpO3JldHVybiB0aGlzLkEuY2FwdHVyZU1lc3NhZ2UodCxlLHtvcmlnaW5hbEV4Y2VwdGlvbjp0LHN5bnRoZXRpY0V4Y2VwdGlvbjpvLC4uLm4sZXZlbnRfaWQ6cn0sdGhpcykscn1jYXB0dXJlRXZlbnQodCxlKXtjb25zdCBuPXQuZXZlbnRfaWR8fGU/LmV2ZW50X2lkfHxXKCk7cmV0dXJuIHRoaXMuQT8odGhpcy5BLmNhcHR1cmVFdmVudCh0LHsuLi5lLGV2ZW50X2lkOm59LHRoaXMpLG4pOihoJiZfLndhcm4oIk5vIGNsaWVudCBjb25maWd1cmVkIG9uIHNjb3BlIC0gd2lsbCBub3QgY2FwdHVyZSBldmVudCEiKSxuKX1SKCl7dGhpcy50fHwodGhpcy50PSEwLHRoaXMuby5mb3JFYWNoKHQ9Pnt0KHRoaXMpfSksdGhpcy50PSExKX19Y29uc3QgVj0iX19TRU5UUllfU1VQUFJFU1NfVFJBQ0lOR19fIixRPXQ9PnQgaW5zdGFuY2VvZiBQcm9taXNlJiYhdFtYXSxYPVN5bWJvbCgiY2hhaW5lZCBQcm9taXNlTGlrZSIpLHR0PSh0LGUpPT57aWYoIWUpcmV0dXJuIHQ7bGV0IG49ITE7Zm9yKGNvbnN0IHIgaW4gdCl7aWYociBpbiBlKWNvbnRpbnVlO249ITA7Y29uc3Qgbz10W3JdOyJmdW5jdGlvbiI9PXR5cGVvZiBvP09iamVjdC5kZWZpbmVQcm9wZXJ0eShlLHIse3ZhbHVlOiguLi5lKT0+by5hcHBseSh0LGUpLGVudW1lcmFibGU6ITAsY29uZmlndXJhYmxlOiEwLHdyaXRhYmxlOiEwfSk6ZVtyXT1vfXJldHVybiBuJiZPYmplY3QuYXNzaWduKGUse1tYXTohMH0pLGV9O2NsYXNzIGV0e2NvbnN0cnVjdG9yKHQsZSl7bGV0IG4scjtuPXR8fG5ldyBLLHI9ZXx8bmV3IEssdGhpcy5JPVt7c2NvcGU6bn1dLHRoaXMuRD1yfXdpdGhTY29wZSh0KXtjb25zdCBlPXRoaXMuVSgpO2xldCBuO3RyeXtuPXQoZSl9Y2F0Y2godCl7dGhyb3cgdGhpcy5CKCksdH1yZXR1cm4gaihuKT8oKHQsZSxuKT0+e2NvbnN0IHI9dC50aGVuKHQ9PihlKHQpLHQpLHQ9Pnt0aHJvdyBuKHQpLHR9KTtyZXR1cm4gUShyKSYmUSh0KT9yOnR0KHQscil9KShuLCgpPT50aGlzLkIoKSwoKT0+dGhpcy5CKCkpOih0aGlzLkIoKSxuKX1nZXRDbGllbnQoKXtyZXR1cm4gdGhpcy5nZXRTdGFja1RvcCgpLmNsaWVudH1nZXRTY29wZSgpe3JldHVybiB0aGlzLmdldFN0YWNrVG9wKCkuc2NvcGV9Z2V0SXNvbGF0aW9uU2NvcGUoKXtyZXR1cm4gdGhpcy5EfWdldFN0YWNrVG9wKCl7cmV0dXJuIHRoaXMuSVt0aGlzLkkubGVuZ3RoLTFdfVUoKXtjb25zdCB0PXRoaXMuZ2V0U2NvcGUoKS5jbG9uZSgpO3JldHVybiB0aGlzLkkucHVzaCh7Y2xpZW50OnRoaXMuZ2V0Q2xpZW50KCksc2NvcGU6dH0pLHR9Qigpe3JldHVybiEodGhpcy5JLmxlbmd0aDw9MSkmJiEhdGhpcy5JLnBvcCgpfX1mdW5jdGlvbiBudCgpe2NvbnN0IHQ9ZyhkKCkpO3JldHVybiB0LnN0YWNrPXQuc3RhY2t8fG5ldyBldChtKCJkZWZhdWx0Q3VycmVudFNjb3BlIiwoKT0+bmV3IEspLG0oImRlZmF1bHRJc29sYXRpb25TY29wZSIsKCk9Pm5ldyBLKSl9ZnVuY3Rpb24gcnQodCl7cmV0dXJuIG50KCkud2l0aFNjb3BlKHQpfWZ1bmN0aW9uIG90KHQsZSl7Y29uc3Qgbj1udCgpO3JldHVybiBuLndpdGhTY29wZSgoKT0+KG4uZ2V0U3RhY2tUb3AoKS5zY29wZT10LGUodCkpKX1mdW5jdGlvbiBzdCh0KXtyZXR1cm4gbnQoKS53aXRoU2NvcGUoKCk9PnQobnQoKS5nZXRJc29sYXRpb25TY29wZSgpKSl9ZnVuY3Rpb24gaXQodCl7cmV0dXJuIHJ0KGU9PntlLnNldFNES1Byb2Nlc3NpbmdNZXRhZGF0YSh7W1ZdOiEwfSk7Y29uc3Qgbj10KCk7cmV0dXJuIGUuc2V0U0RLUHJvY2Vzc2luZ01ldGFkYXRhKHtbVl06dm9pZCAwfSksbn0pfWZ1bmN0aW9uIGN0KHQpe2NvbnN0IGU9Zyh0KTtyZXR1cm4gZS5hY3M/ZS5hY3M6e3N1cHByZXNzVHJhY2luZzppdCx3aXRoSXNvbGF0aW9uU2NvcGU6c3Qsd2l0aFNjb3BlOnJ0LHdpdGhTZXRTY29wZTpvdCx3aXRoU2V0SXNvbGF0aW9uU2NvcGU6KHQsZSk9PnN0KGUpLGdldEN1cnJlbnRTY29wZTooKT0+bnQoKS5nZXRTY29wZSgpLGdldElzb2xhdGlvblNjb3BlOigpPT5udCgpLmdldElzb2xhdGlvblNjb3BlKCl9fWZ1bmN0aW9uIHV0KHQsZT0hMSl7Y29uc3R7aG9zdDpuLHBhdGg6cixwYXNzOm8scG9ydDpzLHByb2plY3RJZDppLHByb3RvY29sOmMscHVibGljS2V5OnV9PXQ7cmV0dXJuYCR7Y306Ly8ke3V9JHtlJiZvP2A6JHtvfWA6IiJ9QCR7bn0ke3M/YDoke3N9YDoiIn0vJHtyP2Ake3J9L2A6cn0ke2l9YH1mdW5jdGlvbiBhdCh0LGUpe2NvbnN0e2ZpbmdlcnByaW50Om4sYnJlYWRjcnVtYnM6cixzZGtQcm9jZXNzaW5nTWV0YWRhdGE6b309ZTshZnVuY3Rpb24odCxlKXtjb25zdHtleHRyYTpuLHRhZ3M6cix1c2VyOm8sY29udGV4dHM6cyxsZXZlbDppLHRyYW5zYWN0aW9uTmFtZTpjfT1lO09iamVjdC5rZXlzKG4pLmxlbmd0aCYmKHQuZXh0cmE9ey4uLm4sLi4udC5leHRyYX0pO09iamVjdC5rZXlzKHIpLmxlbmd0aCYmKHQudGFncz17Li4uciwuLi50LnRhZ3N9KTtPYmplY3Qua2V5cyhvKS5sZW5ndGgmJih0LnVzZXI9ey4uLm8sLi4udC51c2VyfSk7T2JqZWN0LmtleXMocykubGVuZ3RoJiYodC5jb250ZXh0cz17Li4ucywuLi50LmNvbnRleHRzfSk7aSYmKHQubGV2ZWw9aSk7YyYmInRyYW5zYWN0aW9uIiE9PXQudHlwZSYmKHQudHJhbnNhY3Rpb249Yyl9KHQsZSksZnVuY3Rpb24odCxlKXt0LmZpbmdlcnByaW50PXQuZmluZ2VycHJpbnQ/QXJyYXkuaXNBcnJheSh0LmZpbmdlcnByaW50KT90LmZpbmdlcnByaW50Olt0LmZpbmdlcnByaW50XTpbXSxlJiYodC5maW5nZXJwcmludD10LmZpbmdlcnByaW50LmNvbmNhdChlKSk7dC5maW5nZXJwcmludC5sZW5ndGh8fGRlbGV0ZSB0LmZpbmdlcnByaW50fSh0LG4pLGZ1bmN0aW9uKHQsZSl7Y29uc3Qgbj1bLi4udC5icmVhZGNydW1ic3x8W10sLi4uZV07dC5icmVhZGNydW1icz1uLmxlbmd0aD9uOnZvaWQgMH0odCxyKSxmdW5jdGlvbih0LGUpe3Quc2RrUHJvY2Vzc2luZ01ldGFkYXRhPXsuLi50LnNka1Byb2Nlc3NpbmdNZXRhZGF0YSwuLi5lfX0odCxvKX1mdW5jdGlvbiBmdCh0LGU9W10pe3JldHVyblt0LGVdfWZ1bmN0aW9uIGh0KHQsZSl7Y29uc3Qgbj10WzFdO2Zvcihjb25zdCB0IG9mIG4pe2lmKGUodCx0WzBdLnR5cGUpKXJldHVybiEwfXJldHVybiExfWZ1bmN0aW9uIHB0KHQpe2NvbnN0IGU9ZyhwKTtyZXR1cm4gZS5lbmNvZGVQb2x5ZmlsbD9lLmVuY29kZVBvbHlmaWxsKHQpOihuZXcgVGV4dEVuY29kZXIpLmVuY29kZSh0KX1mdW5jdGlvbiBsdCh0KXtjb25zdFtlLG5dPXQ7bGV0IHI9SlNPTi5zdHJpbmdpZnkoZSk7ZnVuY3Rpb24gbyh0KXsic3RyaW5nIj09dHlwZW9mIHI/cj0ic3RyaW5nIj09dHlwZW9mIHQ/cit0OltwdChyKSx0XTpyLnB1c2goInN0cmluZyI9PXR5cGVvZiB0P3B0KHQpOnQpfWZvcihjb25zdCB0IG9mIG4pe2NvbnN0W2Usbl09dDtpZihvKGBcbiR7SlNPTi5zdHJpbmdpZnkoZSl9XG5gKSwic3RyaW5nIj09dHlwZW9mIG58fG4gaW5zdGFuY2VvZiBVaW50OEFycmF5KW8obik7ZWxzZXtsZXQgdDt0cnl7dD1KU09OLnN0cmluZ2lmeShuKX1jYXRjaHt0PUpTT04uc3RyaW5naWZ5KEIobikpfW8odCl9fXJldHVybiJzdHJpbmciPT10eXBlb2Ygcj9yOmZ1bmN0aW9uKHQpe2NvbnN0IGU9dC5yZWR1Y2UoKHQsZSk9PnQrZS5sZW5ndGgsMCksbj1uZXcgVWludDhBcnJheShlKTtsZXQgcj0wO2Zvcihjb25zdCBlIG9mIHQpbi5zZXQoZSxyKSxyKz1lLmxlbmd0aDtyZXR1cm4gbn0ocil9Y29uc3QgZHQ9e3Nlc3Npb25zOiJzZXNzaW9uIixldmVudDoiZXJyb3IiLGNsaWVudF9yZXBvcnQ6ImludGVybmFsIix1c2VyX3JlcG9ydDoiZGVmYXVsdCIscHJvZmlsZV9jaHVuazoicHJvZmlsZSIscmVwbGF5X2V2ZW50OiJyZXBsYXkiLHJlcGxheV9yZWNvcmRpbmc6InJlcGxheSIsY2hlY2tfaW46Im1vbml0b3IiLHJhd19zZWN1cml0eToic2VjdXJpdHkiLGxvZzoibG9nX2l0ZW0iLHRyYWNlX21ldHJpYzoibWV0cmljIn07ZnVuY3Rpb24gZ3QodCl7cmV0dXJuIGZ1bmN0aW9uKHQpe3JldHVybiB0IGluIGR0fSh0KT9kdFt0XTp0fWZ1bmN0aW9uIG10KHQpe2lmKCF0Py5zZGspcmV0dXJuO2NvbnN0e25hbWU6ZSx2ZXJzaW9uOm59PXQuc2RrO3JldHVybntuYW1lOmUsdmVyc2lvbjpufX1mdW5jdGlvbiB5dCh0KXtjb25zdCBlPWN0KGQoKSk7cmV0dXJuIGUuc3VwcHJlc3NUcmFjaW5nP2Uuc3VwcHJlc3NUcmFjaW5nKHQpOmZ1bmN0aW9uKC4uLnQpe2NvbnN0IGU9Y3QoZCgpKTtpZigyPT09dC5sZW5ndGgpe2NvbnN0W24scl09dDtyZXR1cm4gbj9lLndpdGhTZXRTY29wZShuLHIpOmUud2l0aFNjb3BlKHIpfXJldHVybiBlLndpdGhTY29wZSh0WzBdKX0oZT0+KGUuc2V0U0RLUHJvY2Vzc2luZ01ldGFkYXRhKHtbVl06ITB9KSx0KCkpKX1mdW5jdGlvbiBidCh0LGUsbixyKXtjb25zdCBvPW10KG4pLHM9dC50eXBlJiYicmVwbGF5X2V2ZW50IiE9PXQudHlwZT90LnR5cGU6ImV2ZW50IjshZnVuY3Rpb24odCxlKXtpZighZSlyZXR1cm4gdDtjb25zdCBuPXQuc2RrfHx7fTt0LnNkaz17Li4ubixuYW1lOm4ubmFtZXx8ZS5uYW1lLHZlcnNpb246bi52ZXJzaW9ufHxlLnZlcnNpb24saW50ZWdyYXRpb25zOlsuLi50LnNkaz8uaW50ZWdyYXRpb25zfHxbXSwuLi5lLmludGVncmF0aW9uc3x8W11dLHBhY2thZ2VzOlsuLi50LnNkaz8ucGFja2FnZXN8fFtdLC4uLmUucGFja2FnZXN8fFtdXSxzZXR0aW5nczp0LnNkaz8uc2V0dGluZ3N8fGUuc2V0dGluZ3M/ey4uLnQuc2RrPy5zZXR0aW5ncywuLi5lLnNldHRpbmdzfTp2b2lkIDB9fSh0LG4/LnNkayk7Y29uc3QgaT1mdW5jdGlvbih0LGUsbixyKXtjb25zdCBvPXQuc2RrUHJvY2Vzc2luZ01ldGFkYXRhPy5keW5hbWljU2FtcGxpbmdDb250ZXh0O3JldHVybntldmVudF9pZDp0LmV2ZW50X2lkLHNlbnRfYXQ6bmV3IERhdGUoSSgpKS50b0lTT1N0cmluZygpLC4uLmUmJntzZGs6ZX0sLi4uISFuJiZyJiZ7ZHNuOnV0KHIpfSwuLi5vJiZ7dHJhY2U6b319fSh0LG8scixlKTtkZWxldGUgdC5zZGtQcm9jZXNzaW5nTWV0YWRhdGE7cmV0dXJuIGZ0KGksW1t7dHlwZTpzfSx0XV0pfWNsYXNzIHZ0e2NvbnN0cnVjdG9yKHQpe3RoaXMuTD0wLHRoaXMuTT1bXSx0aGlzLkoodCl9dGhlbih0LGUpe3JldHVybiBuZXcgdnQoKG4scik9Pnt0aGlzLk0ucHVzaChbITEsZT0+e2lmKHQpdHJ5e24odChlKSl9Y2F0Y2godCl7cih0KX1lbHNlIG4oZSl9LHQ9PntpZihlKXRyeXtuKGUodCkpfWNhdGNoKHQpe3IodCl9ZWxzZSByKHQpfV0pLHRoaXMuVygpfSl9Y2F0Y2godCl7cmV0dXJuIHRoaXMudGhlbih0PT50LHQpfWZpbmFsbHkodCl7cmV0dXJuIG5ldyB2dCgoZSxuKT0+e2xldCByLG87cmV0dXJuIHRoaXMudGhlbihlPT57bz0hMSxyPWUsdCYmdCgpfSxlPT57bz0hMCxyPWUsdCYmdCgpfSkudGhlbigoKT0+e28/bihyKTplKHIpfSl9KX1XKCl7aWYoMD09PXRoaXMuTClyZXR1cm47Y29uc3QgdD10aGlzLk0uc2xpY2UoKTt0aGlzLk09W10sdC5mb3JFYWNoKHQ9Pnt0WzBdfHwoMT09PXRoaXMuTCYmdFsxXSh0aGlzLkYpLDI9PT10aGlzLkwmJnRbMl0odGhpcy5GKSx0WzBdPSEwKX0pfUoodCl7Y29uc3QgZT0odCxlKT0+ezA9PT10aGlzLkwmJihqKGUpP2UudGhlbihuLHIpOih0aGlzLkw9dCx0aGlzLkY9ZSx0aGlzLlcoKSkpfSxuPXQ9PntlKDEsdCl9LHI9dD0+e2UoMix0KX07dHJ5e3QobixyKX1jYXRjaCh0KXtyKHQpfX19Y29uc3Qgd3Q9U3ltYm9sLmZvcigiU2VudHJ5QnVmZmVyRnVsbEVycm9yIik7ZnVuY3Rpb24gU3QodD0xMDApe2NvbnN0IGU9bmV3IFNldDtmdW5jdGlvbiBuKHQpe2UuZGVsZXRlKHQpfXJldHVybntnZXQgJCgpe3JldHVybiBBcnJheS5mcm9tKGUpfSxhZGQ6ZnVuY3Rpb24ocil7aWYoIShlLnNpemU8dCkpcmV0dXJuIG89d3QsbmV3IHZ0KCh0LGUpPT57ZShvKX0pO3ZhciBvO2NvbnN0IHM9cigpO3JldHVybiBlLmFkZChzKSxzLnRoZW4oKCk9Pm4ocyksKCk9Pm4ocykpLHN9LGRyYWluOmZ1bmN0aW9uKHQpe2lmKCFlLnNpemUpcmV0dXJuIG49ITAsbmV3IHZ0KHQ9Pnt0KG4pfSk7dmFyIG47Y29uc3Qgcj1Qcm9taXNlLmFsbFNldHRsZWQoQXJyYXkuZnJvbShlKSkudGhlbigoKT0+ITApO2lmKCF0KXJldHVybiByO2NvbnN0IG89W3IsbmV3IFByb21pc2UoZT0+e3JldHVybiJvYmplY3QiPT10eXBlb2Yobj1zZXRUaW1lb3V0KCgpPT5lKCExKSx0KSkmJiJmdW5jdGlvbiI9PXR5cGVvZiBuLnVucmVmJiZuLnVucmVmKCksbjt2YXIgbn0pXTtyZXR1cm4gUHJvbWlzZS5yYWNlKG8pfX19ZnVuY3Rpb24gX3QodCx7c3RhdHVzQ29kZTplLGhlYWRlcnM6bn0scj1JKCkpe2NvbnN0IG89ey4uLnR9LHM9bj8uWyJ4LXNlbnRyeS1yYXRlLWxpbWl0cyJdLGk9bj8uWyJyZXRyeS1hZnRlciJdO2lmKHMpZm9yKGNvbnN0IHQgb2Ygcy50cmltKCkuc3BsaXQoIiwiKSl7Y29uc3RbZSxuLCwsc109dC5zcGxpdCgiOiIsNSksaT1wYXJzZUludChlLDEwKSxjPTFlMyooaXNOYU4oaSk/NjA6aSk7aWYobilmb3IoY29uc3QgdCBvZiBuLnNwbGl0KCI7IikpIm1ldHJpY19idWNrZXQiPT09dCYmcyYmIXMuc3BsaXQoIjsiKS5pbmNsdWRlcygiY3VzdG9tIil8fChvW3RdPXIrYyk7ZWxzZSBvLmFsbD1yK2N9ZWxzZSBpP28uYWxsPXIrZnVuY3Rpb24odCxlPUkoKSl7Y29uc3Qgbj1wYXJzZUludChgJHt0fWAsMTApO2lmKCFpc05hTihuKSlyZXR1cm4gMWUzKm47Y29uc3Qgcj1EYXRlLnBhcnNlKGAke3R9YCk7cmV0dXJuIGlzTmFOKHIpPzZlNDpyLWV9KGkscik6NDI5PT09ZSYmKG8uYWxsPXIrNmU0KTtyZXR1cm4gb31mdW5jdGlvbiAkdCh0LGUsbj1TdCh0LmJ1ZmZlclNpemV8fDY0KSl7bGV0IHI9e307cmV0dXJue3NlbmQ6ZnVuY3Rpb24odCl7Y29uc3Qgbz1bXTtpZihodCh0LCh0LGUpPT57Y29uc3Qgbj1ndChlKTsoZnVuY3Rpb24odCxlLG49SSgpKXtyZXR1cm4gZnVuY3Rpb24odCxlKXtyZXR1cm4gdFtlXXx8dC5hbGx8fDB9KHQsZSk+bn0pKHIsbil8fG8ucHVzaCh0KX0pLDA9PT1vLmxlbmd0aClyZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHt9KTtjb25zdCBzPWZ0KHRbMF0sbyksaT10PT57IWZ1bmN0aW9uKHQsZSl7cmV0dXJuIGh0KHQsKHQsbik9PmUuaW5jbHVkZXMobikpfShzLFsiY2xpZW50X3JlcG9ydCJdKT9odChzLCh0LGUpPT57fSk6aCYmXy53YXJuKGBEcm9wcGluZyBjbGllbnQgcmVwb3J0LiBXaWxsIG5vdCBzZW5kIG91dGNvbWVzIChyZWFzb246ICR7dH0pLmApfTtyZXR1cm4gbi5hZGQoKCk9PmUoe2JvZHk6bHQocyl9KS50aGVuKHQ9PjQxMz09PXQuc3RhdHVzQ29kZT8oaCYmXy5lcnJvcigiU2VudHJ5IHJlc3BvbmRlZCB3aXRoIHN0YXR1cyBjb2RlIDQxMy4gRW52ZWxvcGUgd2FzIGRpc2NhcmRlZCBkdWUgdG8gZXhjZWVkaW5nIHNpemUgbGltaXRzLiIpLGkoInNlbmRfZXJyb3IiKSx0KTooaCYmdm9pZCAwIT09dC5zdGF0dXNDb2RlJiYodC5zdGF0dXNDb2RlPDIwMHx8dC5zdGF0dXNDb2RlPj0zMDApJiZfLndhcm4oYFNlbnRyeSByZXNwb25kZWQgd2l0aCBzdGF0dXMgY29kZSAke3Quc3RhdHVzQ29kZX0gdG8gc2VudCBldmVudC5gKSxyPV90KHIsdCksdCksdD0+e3Rocm93IGkoIm5ldHdvcmtfZXJyb3IiKSxoJiZfLmVycm9yKCJFbmNvdW50ZXJlZCBlcnJvciBydW5uaW5nIHRyYW5zcG9ydCByZXF1ZXN0OiIsdCksdH0pKS50aGVuKHQ9PnQsdD0+e2lmKHQ9PT13dClyZXR1cm4gaCYmXy5lcnJvcigiU2tpcHBlZCBzZW5kaW5nIGV2ZW50IGJlY2F1c2UgYnVmZmVyIGlzIGZ1bGwuIiksaSgicXVldWVfb3ZlcmZsb3ciKSxQcm9taXNlLnJlc29sdmUoe30pO3Rocm93IHR9KX0sZmx1c2g6dD0+bi5kcmFpbih0KX19Y29uc3QgRXQ9L14oXFMrOlxcfFwvPykoW1xzXFNdKj8pKCg/OlwuezEsMn18W14vXFxdKz98KShcLlteLi9cXF0qfCkpKD86Wy9cXF0qKSQvO2Z1bmN0aW9uIHh0KHQpe2NvbnN0IGU9ZnVuY3Rpb24odCl7Y29uc3QgZT10Lmxlbmd0aD4xMDI0P2A8dHJ1bmNhdGVkPiR7dC5zbGljZSgtMTAyNCl9YDp0LG49RXQuZXhlYyhlKTtyZXR1cm4gbj9uLnNsaWNlKDEpOltdfSh0KSxuPWVbMF18fCIiO2xldCByPWVbMV07cmV0dXJuIG58fHI/KHImJihyPXIuc2xpY2UoMCxyLmxlbmd0aC0xKSksbityKToiLiJ9ZnVuY3Rpb24gTnQodCxlPSExKXtyZXR1cm4hKGV8fHQmJiF0LnN0YXJ0c1dpdGgoIi8iKSYmIXQubWF0Y2goL15bQS1aXTovKSYmIXQuc3RhcnRzV2l0aCgiLiIpJiYhdC5tYXRjaCgvXlthLXpBLVpdKFthLXpBLVowLTkuXC0rXSkqOlwvXC8vKSkmJnZvaWQgMCE9PXQmJiF0LmluY2x1ZGVzKCJub2RlX21vZHVsZXMvIil9dmFyIEN0O2NvbnN0IGp0PVN5bWJvbCgiQWdlbnRCYXNlSW50ZXJuYWxTdGF0ZSIpO2NsYXNzIE90IGV4dGVuZHMoQ3Q9cy5BZ2VudCxDdCl7Y29uc3RydWN0b3IodCl7c3VwZXIodCksdGhpc1tqdF09e319aXNTZWN1cmVFbmRwb2ludCh0KXtpZih0KXtpZigiYm9vbGVhbiI9PXR5cGVvZiB0LnNlY3VyZUVuZHBvaW50KXJldHVybiB0LnNlY3VyZUVuZHBvaW50O2lmKCJzdHJpbmciPT10eXBlb2YgdC5wcm90b2NvbClyZXR1cm4iaHR0cHM6Ij09PXQucHJvdG9jb2x9Y29uc3R7c3RhY2s6ZX09bmV3IEVycm9yO3JldHVybiJzdHJpbmciPT10eXBlb2YgZSYmZS5zcGxpdCgiXG4iKS5zb21lKHQ9Pi0xIT09dC5pbmRleE9mKCIoaHR0cHMuanM6Iil8fC0xIT09dC5pbmRleE9mKCJub2RlOmh0dHBzOiIpKX1jcmVhdGVTb2NrZXQodCxlLG4pe2NvbnN0IHI9ey4uLmUsc2VjdXJlRW5kcG9pbnQ6dGhpcy5pc1NlY3VyZUVuZHBvaW50KGUpfTtQcm9taXNlLnJlc29sdmUoKS50aGVuKCgpPT50aGlzLmNvbm5lY3QodCxyKSkudGhlbihvPT57aWYobyBpbnN0YW5jZW9mIHMuQWdlbnQpcmV0dXJuIG8uYWRkUmVxdWVzdCh0LHIpO3RoaXNbanRdLmN1cnJlbnRTb2NrZXQ9byxzdXBlci5jcmVhdGVTb2NrZXQodCxlLG4pfSxuKX1jcmVhdGVDb25uZWN0aW9uKCl7Y29uc3QgdD10aGlzW2p0XS5jdXJyZW50U29ja2V0O2lmKHRoaXNbanRdLmN1cnJlbnRTb2NrZXQ9dm9pZCAwLCF0KXRocm93IG5ldyBFcnJvcigiTm8gc29ja2V0IHdhcyByZXR1cm5lZCBpbiB0aGUgYGNvbm5lY3QoKWAgZnVuY3Rpb24iKTtyZXR1cm4gdH1nZXQgZGVmYXVsdFBvcnQoKXtyZXR1cm4gdGhpc1tqdF0uZGVmYXVsdFBvcnQ/PygiaHR0cHM6Ij09PXRoaXMucHJvdG9jb2w/NDQzOjgwKX1zZXQgZGVmYXVsdFBvcnQodCl7dGhpc1tqdF0mJih0aGlzW2p0XS5kZWZhdWx0UG9ydD10KX1nZXQgcHJvdG9jb2woKXtyZXR1cm4gdGhpc1tqdF0ucHJvdG9jb2w/Pyh0aGlzLmlzU2VjdXJlRW5kcG9pbnQoKT8iaHR0cHM6IjoiaHR0cDoiKX1zZXQgcHJvdG9jb2wodCl7dGhpc1tqdF0mJih0aGlzW2p0XS5wcm90b2NvbD10KX19ZnVuY3Rpb24gUHQoLi4udCl7Xy5sb2coIltodHRwcy1wcm94eS1hZ2VudDpwYXJzZS1wcm94eS1yZXNwb25zZV0iLC4uLnQpfWZ1bmN0aW9uIEF0KHQpe3JldHVybiBuZXcgUHJvbWlzZSgoZSxuKT0+e2xldCByPTA7Y29uc3Qgbz1bXTtmdW5jdGlvbiBzKCl7Y29uc3QgYz10LnJlYWQoKTtjP2Z1bmN0aW9uKGMpe28ucHVzaChjKSxyKz1jLmxlbmd0aDtjb25zdCB1PUJ1ZmZlci5jb25jYXQobyxyKSxhPXUuaW5kZXhPZigiXHJcblxyXG4iKTtpZigtMT09PWEpcmV0dXJuIFB0KCJoYXZlIG5vdCByZWNlaXZlZCBlbmQgb2YgSFRUUCBoZWFkZXJzIHlldC4uLiIpLHZvaWQgcygpO2NvbnN0IGY9dS5zdWJhcnJheSgwLGEpLnRvU3RyaW5nKCJhc2NpaSIpLnNwbGl0KCJcclxuIiksaD1mLnNoaWZ0KCk7aWYoIWgpcmV0dXJuIHQuZGVzdHJveSgpLG4obmV3IEVycm9yKCJObyBoZWFkZXIgcmVjZWl2ZWQgZnJvbSBwcm94eSBDT05ORUNUIHJlc3BvbnNlIikpO2NvbnN0IHA9aC5zcGxpdCgiICIpLGw9KyhwWzFdfHwwKSxkPXAuc2xpY2UoMikuam9pbigiICIpLGc9e307Zm9yKGNvbnN0IGUgb2YgZil7aWYoIWUpY29udGludWU7Y29uc3Qgcj1lLmluZGV4T2YoIjoiKTtpZigtMT09PXIpcmV0dXJuIHQuZGVzdHJveSgpLG4obmV3IEVycm9yKGBJbnZhbGlkIGhlYWRlciBmcm9tIHByb3h5IENPTk5FQ1QgcmVzcG9uc2U6ICIke2V9ImApKTtjb25zdCBvPWUuc2xpY2UoMCxyKS50b0xvd2VyQ2FzZSgpLHM9ZS5zbGljZShyKzEpLnRyaW1TdGFydCgpLGk9Z1tvXTsic3RyaW5nIj09dHlwZW9mIGk/Z1tvXT1baSxzXTpBcnJheS5pc0FycmF5KGkpP2kucHVzaChzKTpnW29dPXN9UHQoImdvdCBwcm94eSBzZXJ2ZXIgcmVzcG9uc2U6ICVvICVvIixoLGcpLGkoKSxlKHtjb25uZWN0OntzdGF0dXNDb2RlOmwsc3RhdHVzVGV4dDpkLGhlYWRlcnM6Z30sYnVmZmVyZWQ6dX0pfShjKTp0Lm9uY2UoInJlYWRhYmxlIixzKX1mdW5jdGlvbiBpKCl7dC5yZW1vdmVMaXN0ZW5lcigiZW5kIixjKSx0LnJlbW92ZUxpc3RlbmVyKCJlcnJvciIsdSksdC5yZW1vdmVMaXN0ZW5lcigicmVhZGFibGUiLHMpfWZ1bmN0aW9uIGMoKXtpKCksUHQoIm9uZW5kIiksbihuZXcgRXJyb3IoIlByb3h5IGNvbm5lY3Rpb24gZW5kZWQgYmVmb3JlIHJlY2VpdmluZyBDT05ORUNUIHJlc3BvbnNlIikpfWZ1bmN0aW9uIHUodCl7aSgpLFB0KCJvbmVycm9yICVvIix0KSxuKHQpfXQub24oImVycm9yIix1KSx0Lm9uKCJlbmQiLGMpLHMoKX0pfWZ1bmN0aW9uIFR0KC4uLnQpe18ubG9nKCJbaHR0cHMtcHJveHktYWdlbnRdIiwuLi50KX1jbGFzcyBrdCBleHRlbmRzIE90e2NvbnN0cnVjdG9yKHQsZSl7c3VwZXIoZSksdGhpcy5vcHRpb25zPXt9LHRoaXMucHJveHk9InN0cmluZyI9PXR5cGVvZiB0P25ldyBVUkwodCk6dCx0aGlzLnByb3h5SGVhZGVycz1lPy5oZWFkZXJzPz97fSxUdCgiQ3JlYXRpbmcgbmV3IEh0dHBzUHJveHlBZ2VudCBpbnN0YW5jZTogJW8iLHRoaXMucHJveHkuaHJlZik7Y29uc3Qgbj0odGhpcy5wcm94eS5ob3N0bmFtZXx8dGhpcy5wcm94eS5ob3N0KS5yZXBsYWNlKC9eXFt8XF0kL2csIiIpLHI9dGhpcy5wcm94eS5wb3J0P3BhcnNlSW50KHRoaXMucHJveHkucG9ydCwxMCk6Imh0dHBzOiI9PT10aGlzLnByb3h5LnByb3RvY29sPzQ0Mzo4MDt0aGlzLmNvbm5lY3RPcHRzPXtBTFBOUHJvdG9jb2xzOlsiaHR0cC8xLjEiXSwuLi5lP0l0KGUsImhlYWRlcnMiKTpudWxsLGhvc3Q6bixwb3J0OnJ9fWFzeW5jIGNvbm5lY3QodCxlKXtjb25zdHtwcm94eTpufT10aGlzO2lmKCFlLmhvc3QpdGhyb3cgbmV3IFR5cGVFcnJvcignTm8gImhvc3QiIHByb3ZpZGVkJyk7bGV0IHI7aWYoImh0dHBzOiI9PT1uLnByb3RvY29sKXtUdCgiQ3JlYXRpbmcgYHRscy5Tb2NrZXRgOiAlbyIsdGhpcy5jb25uZWN0T3B0cyk7Y29uc3QgdD10aGlzLmNvbm5lY3RPcHRzLnNlcnZlcm5hbWV8fHRoaXMuY29ubmVjdE9wdHMuaG9zdDtyPWYuY29ubmVjdCh7Li4udGhpcy5jb25uZWN0T3B0cyxzZXJ2ZXJuYW1lOnQmJmEuaXNJUCh0KT92b2lkIDA6dH0pfWVsc2UgVHQoIkNyZWF0aW5nIGBuZXQuU29ja2V0YDogJW8iLHRoaXMuY29ubmVjdE9wdHMpLHI9YS5jb25uZWN0KHRoaXMuY29ubmVjdE9wdHMpO2NvbnN0IG89ImZ1bmN0aW9uIj09dHlwZW9mIHRoaXMucHJveHlIZWFkZXJzP3RoaXMucHJveHlIZWFkZXJzKCk6ey4uLnRoaXMucHJveHlIZWFkZXJzfSxzPWEuaXNJUHY2KGUuaG9zdCk/YFske2UuaG9zdH1dYDplLmhvc3Q7bGV0IGk9YENPTk5FQ1QgJHtzfToke2UucG9ydH0gSFRUUC8xLjFcclxuYDtpZihuLnVzZXJuYW1lfHxuLnBhc3N3b3JkKXtjb25zdCB0PWAke2RlY29kZVVSSUNvbXBvbmVudChuLnVzZXJuYW1lKX06JHtkZWNvZGVVUklDb21wb25lbnQobi5wYXNzd29yZCl9YDtvWyJQcm94eS1BdXRob3JpemF0aW9uIl09YEJhc2ljICR7QnVmZmVyLmZyb20odCkudG9TdHJpbmcoImJhc2U2NCIpfWB9by5Ib3N0PWAke3N9OiR7ZS5wb3J0fWAsb1siUHJveHktQ29ubmVjdGlvbiJdfHwob1siUHJveHktQ29ubmVjdGlvbiJdPXRoaXMua2VlcEFsaXZlPyJLZWVwLUFsaXZlIjoiY2xvc2UiKTtmb3IoY29uc3QgdCBvZiBPYmplY3Qua2V5cyhvKSlpKz1gJHt0fTogJHtvW3RdfVxyXG5gO2NvbnN0IGM9QXQocik7ci53cml0ZShgJHtpfVxyXG5gKTtjb25zdHtjb25uZWN0OnUsYnVmZmVyZWQ6aH09YXdhaXQgYztpZih0LmVtaXQoInByb3h5Q29ubmVjdCIsdSksdGhpcy5lbWl0KCJwcm94eUNvbm5lY3QiLHUsdCksMjAwPT09dS5zdGF0dXNDb2RlKXtpZih0Lm9uY2UoInNvY2tldCIsUnQpLGUuc2VjdXJlRW5kcG9pbnQpe1R0KCJVcGdyYWRpbmcgc29ja2V0IGNvbm5lY3Rpb24gdG8gVExTIik7Y29uc3QgdD1lLnNlcnZlcm5hbWV8fGUuaG9zdDtyZXR1cm4gZi5jb25uZWN0KHsuLi5JdChlLCJob3N0IiwicGF0aCIsInBvcnQiKSxzb2NrZXQ6cixzZXJ2ZXJuYW1lOmEuaXNJUCh0KT92b2lkIDA6dH0pfXJldHVybiByfXIuZGVzdHJveSgpO2NvbnN0IHA9bmV3IGEuU29ja2V0KHt3cml0YWJsZTohMX0pO3JldHVybiBwLnJlYWRhYmxlPSEwLHQub25jZSgic29ja2V0Iix0PT57VHQoIlJlcGxheWluZyBwcm94eSBidWZmZXIgZm9yIGZhaWxlZCByZXF1ZXN0IiksdC5wdXNoKGgpLHQucHVzaChudWxsKX0pLHB9fWZ1bmN0aW9uIFJ0KHQpe3QucmVzdW1lKCl9ZnVuY3Rpb24gSXQodCwuLi5lKXtjb25zdCBuPXt9O2xldCByO2ZvcihyIGluIHQpZS5pbmNsdWRlcyhyKXx8KG5bcl09dFtyXSk7cmV0dXJuIG59a3QucHJvdG9jb2xzPVsiaHR0cCIsImh0dHBzIl07ZnVuY3Rpb24gRHQodCl7cmV0dXJuIHQucmVwbGFjZSgvXltBLVpdOi8sIiIpLnJlcGxhY2UoL1xcL2csIi8iKX1jb25zdCBVdD1lO2xldCBCdCxMdD0wLE10PXt9O2Z1bmN0aW9uIHp0KHQpe1V0LmRlYnVnJiZjb25zb2xlLmxvZyhgW0FOUiBXb3JrZXJdICR7dH1gKX12YXIgSnQsV3QsRnQ7Y29uc3QgR3Q9ZnVuY3Rpb24odCl7bGV0IGU7dHJ5e2U9bmV3IFVSTCh0LnVybCl9Y2F0Y2h7cmV0dXJuIGIoKCk9Pntjb25zb2xlLndhcm4oIltAc2VudHJ5L25vZGVdOiBJbnZhbGlkIGRzbiBvciB0dW5uZWwgb3B0aW9uLCB3aWxsIG5vdCBzZW5kIGFueSBldmVudHMuIFRoZSB0dW5uZWwgb3B0aW9uIG11c3QgYmUgYSBmdWxsIFVSTCB3aGVuIHVzZWQuIil9KSwkdCh0LCgpPT5Qcm9taXNlLnJlc29sdmUoe30pKX1jb25zdCBuPSJodHRwczoiPT09ZS5wcm90b2NvbCxyPWZ1bmN0aW9uKHQsZSl7Y29uc3R7bm9fcHJveHk6bn09cHJvY2Vzcy5lbnYscj1uPy5zcGxpdCgiLCIpLnNvbWUoZT0+dC5ob3N0LmVuZHNXaXRoKGUpfHx0Lmhvc3RuYW1lLmVuZHNXaXRoKGUpKTtyZXR1cm4gcj92b2lkIDA6ZX0oZSx0LnByb3h5fHwobj9wcm9jZXNzLmVudi5odHRwc19wcm94eTp2b2lkIDApfHxwcm9jZXNzLmVudi5odHRwX3Byb3h5KSxvPW4/aTpzLGE9dC5rZWVwQWxpdmU/PyEwLGY9cj9uZXcga3Qocik6bmV3IG8uQWdlbnQoe2tlZXBBbGl2ZTphLG1heFNvY2tldHM6MzAsdGltZW91dDoyZTN9KSxoPWZ1bmN0aW9uKHQsZSxuKXtjb25zdHtob3N0bmFtZTpyLHBhdGhuYW1lOm8scG9ydDpzLHByb3RvY29sOmksc2VhcmNoOmF9PW5ldyBVUkwodC51cmwpO3JldHVybiBmdW5jdGlvbihmKXtjb25zdCBoPXA9Pm5ldyBQcm9taXNlKChsLGQpPT57eXQoKCk9PntsZXQgZz1mdW5jdGlvbih0KXtyZXR1cm4gbmV3IGMoe3JlYWQoKXt0aGlzLnB1c2godCksdGhpcy5wdXNoKG51bGwpfX0pfShmLmJvZHkpO2NvbnN0IG09ey4uLnQuaGVhZGVyc307Zi5ib2R5Lmxlbmd0aD4zMjc2OCYmKG1bImNvbnRlbnQtZW5jb2RpbmciXT0iZ3ppcCIsZz1nLnBpcGUodSgpKSk7Y29uc3QgeT1yLnN0YXJ0c1dpdGgoIlsiKSxiPWUucmVxdWVzdCh7bWV0aG9kOiJQT1NUIixhZ2VudDpuLGhlYWRlcnM6bSxob3N0bmFtZTp5P3Iuc2xpY2UoMSwtMSk6cixwYXRoOmAke299JHthfWAscG9ydDpzLHByb3RvY29sOmksY2E6dC5jYUNlcnRzfSx0PT57dC5vbigiZGF0YSIsKCk9Pnt9KSx0Lm9uKCJlbmQiLCgpPT57fSksdC5zZXRFbmNvZGluZygidXRmOCIpO2NvbnN0IGU9dC5oZWFkZXJzWyJyZXRyeS1hZnRlciJdPz9udWxsLG49dC5oZWFkZXJzWyJ4LXNlbnRyeS1yYXRlLWxpbWl0cyJdPz9udWxsO2woe3N0YXR1c0NvZGU6dC5zdGF0dXNDb2RlLGhlYWRlcnM6eyJyZXRyeS1hZnRlciI6ZSwieC1zZW50cnktcmF0ZS1saW1pdHMiOkFycmF5LmlzQXJyYXkobik/blswXXx8bnVsbDpufX0pfSk7Yi5vbigiZXJyb3IiLHQ9PntwJiZiLnJldXNlZFNvY2tldCYmIkVDT05OUkVTRVQiPT09dC5jb2RlP2woaCghMSkpOmQodCl9KSxnLnBpcGUoYil9KX0pO3JldHVybiBoKCEwKX19KHQsdC5odHRwTW9kdWxlPz9vLGYpO3JldHVybiAkdCh0LGgpfSh7dXJsOihKdD1VdC5kc24sV3Q9VXQudHVubmVsLEZ0PVV0LnNka01ldGFkYXRhLnNkayxXdHx8YCR7ZnVuY3Rpb24odCl7cmV0dXJuYCR7ZnVuY3Rpb24odCl7Y29uc3QgZT10LnByb3RvY29sP2Ake3QucHJvdG9jb2x9OmA6IiIsbj10LnBvcnQ/YDoke3QucG9ydH1gOiIiO3JldHVybmAke2V9Ly8ke3QuaG9zdH0ke259JHt0LnBhdGg/YC8ke3QucGF0aH1gOiIifS9hcGkvYH0odCl9JHt0LnByb2plY3RJZH0vZW52ZWxvcGUvYH0oSnQpfT8ke2Z1bmN0aW9uKHQsZSl7Y29uc3Qgbj17c2VudHJ5X3ZlcnNpb246IjcifTtyZXR1cm4gdC5wdWJsaWNLZXkmJihuLnNlbnRyeV9rZXk9dC5wdWJsaWNLZXkpLGUmJihuLnNlbnRyeV9jbGllbnQ9YCR7ZS5uYW1lfS8ke2UudmVyc2lvbn1gKSxuZXcgVVJMU2VhcmNoUGFyYW1zKG4pLnRvU3RyaW5nKCl9KEp0LEZ0KX1gKX0pO2FzeW5jIGZ1bmN0aW9uIFl0KCl7aWYoQnQpe3p0KCJTZW5kaW5nIGFibm9ybWFsIHNlc3Npb24iKSxaKEJ0LHtzdGF0dXM6ImFibm9ybWFsIixhYm5vcm1hbF9tZWNoYW5pc206ImFucl9mb3JlZ3JvdW5kIixyZWxlYXNlOlV0LnJlbGVhc2UsZW52aXJvbm1lbnQ6VXQuZW52aXJvbm1lbnR9KTtjb25zdCB0PWZ1bmN0aW9uKHQsZSxuLHIpe2NvbnN0IG89bXQobik7cmV0dXJuIGZ0KHtzZW50X2F0Om5ldyBEYXRlKEkoKSkudG9JU09TdHJpbmcoKSwuLi5vJiZ7c2RrOm99LC4uLiEhciYmZSYme2Rzbjp1dChlKX19LFsiYWdncmVnYXRlcyJpbiB0P1t7dHlwZToic2Vzc2lvbnMifSx0XTpbe3R5cGU6InNlc3Npb24ifSx0LnRvSlNPTigpXV0pfShCdCxVdC5kc24sVXQuc2RrTWV0YWRhdGEsVXQudHVubmVsKTt6dChKU09OLnN0cmluZ2lmeSh0KSksYXdhaXQgR3Quc2VuZCh0KTt0cnl7bj8ucG9zdE1lc3NhZ2UoInNlc3Npb24tZW5kZWQiKX1jYXRjaHt9fX1mdW5jdGlvbiBIdCh0KXtpZighdClyZXR1cm47Y29uc3QgZT1mdW5jdGlvbih0KXtpZighdC5sZW5ndGgpcmV0dXJuW107Y29uc3QgZT1BcnJheS5mcm9tKHQpO3JldHVybi9zZW50cnlXcmFwcGVkLy50ZXN0KEUoZSkuZnVuY3Rpb258fCIiKSYmZS5wb3AoKSxlLnJldmVyc2UoKSwkLnRlc3QoRShlKS5mdW5jdGlvbnx8IiIpJiYoZS5wb3AoKSwkLnRlc3QoRShlKS5mdW5jdGlvbnx8IiIpJiZlLnBvcCgpKSxlLnNsaWNlKDAsNTApLm1hcCh0PT4oey4uLnQsZmlsZW5hbWU6dC5maWxlbmFtZXx8RShlKS5maWxlbmFtZSxmdW5jdGlvbjp0LmZ1bmN0aW9ufHwiPyJ9KSl9KHQpO2lmKFV0LmFwcFJvb3RQYXRoKWZvcihjb25zdCB0IG9mIGUpdC5maWxlbmFtZSYmKHQuZmlsZW5hbWU9TSh0LmZpbGVuYW1lLFV0LmFwcFJvb3RQYXRoKSk7cmV0dXJuIGV9YXN5bmMgZnVuY3Rpb24gWnQodCxlKXtpZihMdD49VXQubWF4QW5yRXZlbnRzKXJldHVybjtMdCs9MSxhd2FpdCBZdCgpLHp0KCJTZW5kaW5nIGV2ZW50Iik7Y29uc3Qgbj17ZXZlbnRfaWQ6VygpLGNvbnRleHRzOlV0LmNvbnRleHRzLHJlbGVhc2U6VXQucmVsZWFzZSxlbnZpcm9ubWVudDpVdC5lbnZpcm9ubWVudCxkaXN0OlV0LmRpc3QscGxhdGZvcm06Im5vZGUiLGxldmVsOiJlcnJvciIsZXhjZXB0aW9uOnt2YWx1ZXM6W3t0eXBlOiJBcHBsaWNhdGlvbk5vdFJlc3BvbmRpbmciLHZhbHVlOmBBcHBsaWNhdGlvbiBOb3QgUmVzcG9uZGluZyBmb3IgYXQgbGVhc3QgJHtVdC5hbnJUaHJlc2hvbGR9IG1zYCxzdGFja3RyYWNlOntmcmFtZXM6SHQodCl9LG1lY2hhbmlzbTp7dHlwZToiQU5SIn19XX0sdGFnczpVdC5zdGF0aWNUYWdzfTtlJiZmdW5jdGlvbih0LGUpe2lmKGF0KHQsZSksIXQuY29udGV4dHM/LnRyYWNlKXtjb25zdHt0cmFjZUlkOm4scGFyZW50U3BhbklkOnIscHJvcGFnYXRpb25TcGFuSWQ6b309ZS5wcm9wYWdhdGlvbkNvbnRleHQ7dC5jb250ZXh0cz17dHJhY2U6e3RyYWNlX2lkOm4sc3Bhbl9pZDpvfHxXKCkuc3Vic3RyaW5nKDE2KSxwYXJlbnRfc3Bhbl9pZDpyfSwuLi50LmNvbnRleHRzfX19KG4sZSksZnVuY3Rpb24odCl7aWYoMD09PU9iamVjdC5rZXlzKE10KS5sZW5ndGgpcmV0dXJuO2NvbnN0IGU9VXQuYXBwUm9vdFBhdGg/e306TXQ7aWYoVXQuYXBwUm9vdFBhdGgpZm9yKGNvbnN0W3Qsbl1vZiBPYmplY3QuZW50cmllcyhNdCkpZVtNKHQsVXQuYXBwUm9vdFBhdGgpXT1uO2NvbnN0IG49bmV3IE1hcDtmb3IoY29uc3QgciBvZiB0LmV4Y2VwdGlvbj8udmFsdWVzfHxbXSlmb3IoY29uc3QgdCBvZiByLnN0YWNrdHJhY2U/LmZyYW1lc3x8W10pe2NvbnN0IHI9dC5hYnNfcGF0aHx8dC5maWxlbmFtZTtyJiZlW3JdJiZuLnNldChyLGVbcl0pfWlmKG4uc2l6ZT4wKXtjb25zdCBlPVtdO2Zvcihjb25zdFt0LHJdb2Ygbi5lbnRyaWVzKCkpZS5wdXNoKHt0eXBlOiJzb3VyY2VtYXAiLGNvZGVfZmlsZTp0LGRlYnVnX2lkOnJ9KTt0LmRlYnVnX21ldGE9e2ltYWdlczplfX19KG4pO2NvbnN0IHI9YnQobixVdC5kc24sVXQuc2RrTWV0YWRhdGEsVXQudHVubmVsKTt6dChKU09OLnN0cmluZ2lmeShyKSksYXdhaXQgR3Quc2VuZChyKSxhd2FpdCBHdC5mbHVzaCgyZTMpLEx0Pj1VdC5tYXhBbnJFdmVudHMmJnNldFRpbWVvdXQoKCk9Pntwcm9jZXNzLmV4aXQoMCl9LDVlMyl9bGV0IHF0O2lmKHp0KCJTdGFydGVkIiksVXQuY2FwdHVyZVN0YWNrVHJhY2Upe3p0KCJDb25uZWN0aW5nIHRvIGRlYnVnZ2VyIik7Y29uc3QgZT1uZXcgdDtlLmNvbm5lY3RUb01haW5UaHJlYWQoKSx6dCgiQ29ubmVjdGVkIHRvIGRlYnVnZ2VyIik7Y29uc3Qgbj1uZXcgTWFwO2Uub24oIkRlYnVnZ2VyLnNjcmlwdFBhcnNlZCIsdD0+e24uc2V0KHQucGFyYW1zLnNjcmlwdElkLHQucGFyYW1zLnVybCl9KSxlLm9uKCJEZWJ1Z2dlci5wYXVzZWQiLHQ9PntpZigib3RoZXIiPT09dC5wYXJhbXMucmVhc29uKXRyeXt6dCgiRGVidWdnZXIgcGF1c2VkIik7Y29uc3Qgcz1bLi4udC5wYXJhbXMuY2FsbEZyYW1lc10saT1VdC5hcHBSb290UGF0aD9mdW5jdGlvbih0PShwcm9jZXNzLmFyZ3ZbMV0/eHQocHJvY2Vzcy5hcmd2WzFdKTpwcm9jZXNzLmN3ZCgpKSxlPSJcXCI9PT1vKXtjb25zdCBuPWU/RHQodCk6dDtyZXR1cm4gdD0+e2lmKCF0KXJldHVybjtjb25zdCBvPWU/RHQodCk6dDtsZXR7ZGlyOnMsYmFzZTppLGV4dDpjfT1yLnBhcnNlKG8pOyIuanMiIT09YyYmIi5tanMiIT09YyYmIi5janMiIT09Y3x8KGk9aS5zbGljZSgwLC0xKmMubGVuZ3RoKSk7Y29uc3QgdT1kZWNvZGVVUklDb21wb25lbnQoaSk7c3x8KHM9Ii4iKTtjb25zdCBhPXMubGFzdEluZGV4T2YoIi9ub2RlX21vZHVsZXMiKTtpZihhPi0xKXJldHVybmAke3Muc2xpY2UoYSsxNCkucmVwbGFjZSgvXC8vZywiLiIpfToke3V9YDtpZihzLnN0YXJ0c1dpdGgobikpe2NvbnN0IHQ9cy5zbGljZShuLmxlbmd0aCsxKS5yZXBsYWNlKC9cLy9nLCIuIik7cmV0dXJuIHQ/YCR7dH06JHt1fWA6dX1yZXR1cm4gdX19KFV0LmFwcFJvb3RQYXRoKTooKT0+e30sYz1zLm1hcCh0PT5mdW5jdGlvbih0LGUsbil7Y29uc3Qgcj1lP2UucmVwbGFjZSgvXmZpbGU6XC9cLy8sIiIpOnZvaWQgMCxvPXQubG9jYXRpb24uY29sdW1uTnVtYmVyP3QubG9jYXRpb24uY29sdW1uTnVtYmVyKzE6dm9pZCAwLHM9dC5sb2NhdGlvbi5saW5lTnVtYmVyP3QubG9jYXRpb24ubGluZU51bWJlcisxOnZvaWQgMDtyZXR1cm57ZmlsZW5hbWU6cixtb2R1bGU6bihyKSxmdW5jdGlvbjp0LmZ1bmN0aW9uTmFtZXx8Ij8iLGNvbG5vOm8sbGluZW5vOnMsaW5fYXBwOnI/TnQocik6dm9pZCAwfX0odCxuLmdldCh0LmxvY2F0aW9uLnNjcmlwdElkKSxpKSksdT1zZXRUaW1lb3V0KCgpPT57WnQoYykudGhlbihudWxsLCgpPT57enQoIlNlbmRpbmcgQU5SIGV2ZW50IGZhaWxlZC4iKX0pfSw1ZTMpO2UucG9zdCgiUnVudGltZS5ldmFsdWF0ZSIse2V4cHJlc3Npb246Imdsb2JhbC5fX1NFTlRSWV9HRVRfU0NPUEVTX18oKTsiLHNpbGVudDohMCxyZXR1cm5CeVZhbHVlOiEwfSwodCxuKT0+e3QmJnp0KGBFcnJvciBleGVjdXRpbmcgc2NyaXB0OiAnJHt0Lm1lc3NhZ2V9J2ApLGNsZWFyVGltZW91dCh1KTtjb25zdCByPW4/LnJlc3VsdD9uLnJlc3VsdC52YWx1ZTp2b2lkIDA7ZS5wb3N0KCJEZWJ1Z2dlci5yZXN1bWUiKSxlLnBvc3QoIkRlYnVnZ2VyLmRpc2FibGUiKSxadChjLHIpLnRoZW4obnVsbCwoKT0+e3p0KCJTZW5kaW5nIEFOUiBldmVudCBmYWlsZWQuIil9KX0pfWNhdGNoKHQpe3Rocm93IGUucG9zdCgiRGVidWdnZXIucmVzdW1lIiksZS5wb3N0KCJEZWJ1Z2dlci5kaXNhYmxlIiksdH19KSxxdD0oKT0+e3RyeXtlLnBvc3QoIkRlYnVnZ2VyLmVuYWJsZSIsKCk9PntlLnBvc3QoIkRlYnVnZ2VyLnBhdXNlIil9KX1jYXRjaHt9fX1jb25zdHtwb2xsOkt0fT1mdW5jdGlvbih0LGUsbixyKXtjb25zdCBvPXQoKTtsZXQgcz0hMSxpPSEwO3JldHVybiBzZXRJbnRlcnZhbCgoKT0+e2NvbnN0IHQ9by5nZXRUaW1lTXMoKTshMT09PXMmJnQ+ZStuJiYocz0hMCxpJiZyKCkpLHQ8ZStuJiYocz0hMSl9LDIwKSx7cG9sbDooKT0+e28ucmVzZXQoKX0sZW5hYmxlZDp0PT57aT10fX19KGZ1bmN0aW9uKCl7bGV0IHQ9cHJvY2Vzcy5ocnRpbWUoKTtyZXR1cm57Z2V0VGltZU1zOigpPT57Y29uc3RbZSxuXT1wcm9jZXNzLmhydGltZSh0KTtyZXR1cm4gTWF0aC5mbG9vcigxZTMqZStuLzFlNil9LHJlc2V0OigpPT57dD1wcm9jZXNzLmhydGltZSgpfX19LFV0LnBvbGxJbnRlcnZhbCxVdC5hbnJUaHJlc2hvbGQsZnVuY3Rpb24oKXt6dCgiV2F0Y2hkb2cgdGltZW91dCIpLHF0Pyh6dCgiUGF1c2luZyBkZWJ1Z2dlciB0byBjYXB0dXJlIHN0YWNrIHRyYWNlIikscXQoKSk6KHp0KCJDYXB0dXJpbmcgZXZlbnQgd2l0aG91dCBhIHN0YWNrIHRyYWNlIiksWnQoKS50aGVuKG51bGwsKCk9Pnt6dCgiU2VuZGluZyBBTlIgZXZlbnQgZmFpbGVkIG9uIHdhdGNoZG9nIHRpbWVvdXQuIil9KSl9KTtuPy5vbigibWVzc2FnZSIsdD0+e3Quc2Vzc2lvbiYmKEJ0PUgodC5zZXNzaW9uKSksdC5kZWJ1Z0ltYWdlcyYmKE10PXQuZGVidWdJbWFnZXMpLEt0KCl9KTs=";
|
|
10
10
|
const DEFAULT_INTERVAL = 50;
|
|
11
11
|
const DEFAULT_HANG_THRESHOLD = 5e3;
|
|
12
12
|
function log(message, ...args) {
|
|
@@ -13,11 +13,6 @@ const childProcessIntegration = core.defineIntegration((options = {}) => {
|
|
|
13
13
|
captureChildProcessEvents(event.process, options);
|
|
14
14
|
}
|
|
15
15
|
});
|
|
16
|
-
diagnosticsChannel.channel("worker_threads").subscribe((event) => {
|
|
17
|
-
if (core.isObjectLike(event) && "worker" in event) {
|
|
18
|
-
captureWorkerThreadEvents(event.worker, options);
|
|
19
|
-
}
|
|
20
|
-
});
|
|
21
16
|
}
|
|
22
17
|
};
|
|
23
18
|
});
|
|
@@ -57,25 +52,6 @@ function captureChildProcessEvents(child, options) {
|
|
|
57
52
|
}
|
|
58
53
|
});
|
|
59
54
|
}
|
|
60
|
-
function captureWorkerThreadEvents(worker, options) {
|
|
61
|
-
let threadId;
|
|
62
|
-
worker.on("online", () => {
|
|
63
|
-
threadId = worker.threadId;
|
|
64
|
-
}).on("error", (error) => {
|
|
65
|
-
if (options.captureWorkerErrors !== false) {
|
|
66
|
-
core.captureException(error, {
|
|
67
|
-
mechanism: { type: "auto.child_process.worker_thread", handled: false, data: { threadId: String(threadId) } }
|
|
68
|
-
});
|
|
69
|
-
} else {
|
|
70
|
-
core.addBreadcrumb({
|
|
71
|
-
category: "worker_thread",
|
|
72
|
-
message: `Worker thread errored with '${error.message}'`,
|
|
73
|
-
level: "error",
|
|
74
|
-
data: { threadId }
|
|
75
|
-
});
|
|
76
|
-
}
|
|
77
|
-
});
|
|
78
|
-
}
|
|
79
55
|
|
|
80
56
|
exports.childProcessIntegration = childProcessIntegration;
|
|
81
57
|
//# sourceMappingURL=childProcess.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"childProcess.js","sources":["../../../src/integrations/childProcess.ts"],"sourcesContent":["import type { ChildProcess } from 'node:child_process';\nimport * as diagnosticsChannel from 'node:diagnostics_channel';\nimport
|
|
1
|
+
{"version":3,"file":"childProcess.js","sources":["../../../src/integrations/childProcess.ts"],"sourcesContent":["import type { ChildProcess } from 'node:child_process';\nimport * as diagnosticsChannel from 'node:diagnostics_channel';\nimport { addBreadcrumb, defineIntegration, isObjectLike } from '@sentry/core';\n\ninterface Options {\n /**\n * Whether to include child process arguments in breadcrumbs data.\n *\n * @default false\n */\n includeChildProcessArgs?: boolean;\n}\n\nconst INTEGRATION_NAME = 'ChildProcess' as const;\n\n/**\n * Capture breadcrumbs and events for child processes.\n * For worker thread events, use `workerThreadsIntegration()` instead.\n */\nexport const childProcessIntegration = defineIntegration((options: Options = {}) => {\n return {\n name: INTEGRATION_NAME,\n setup() {\n diagnosticsChannel.channel('child_process').subscribe((event: unknown) => {\n if (isObjectLike(event) && 'process' in event) {\n captureChildProcessEvents(event.process as ChildProcess, options);\n }\n });\n },\n };\n});\n\nfunction captureChildProcessEvents(child: ChildProcess, options: Options): void {\n let hasExited = false;\n let data: Record<string, unknown> | undefined;\n\n child\n .on('spawn', () => {\n // This is Sentry getting macOS OS context\n if (child.spawnfile === '/usr/bin/sw_vers') {\n hasExited = true;\n return;\n }\n\n data = { spawnfile: child.spawnfile };\n if (options.includeChildProcessArgs) {\n data.spawnargs = child.spawnargs;\n }\n })\n .on('exit', code => {\n if (!hasExited) {\n hasExited = true;\n\n // Only log for non-zero exit codes\n if (code !== null && code !== 0) {\n addBreadcrumb({\n category: 'child_process',\n message: `Child process exited with code '${code}'`,\n level: code === 0 ? 'info' : 'warning',\n data,\n });\n }\n }\n })\n .on('error', error => {\n if (!hasExited) {\n hasExited = true;\n\n addBreadcrumb({\n category: 'child_process',\n message: `Child process errored with '${error.message}'`,\n level: 'error',\n data,\n });\n }\n });\n}\n"],"names":["defineIntegration","isObjectLike","addBreadcrumb"],"mappings":";;;;;AAaA,MAAM,gBAAA,GAAmB,cAAA;AAMlB,MAAM,uBAAA,GAA0BA,sBAAA,CAAkB,CAAC,OAAA,GAAmB,EAAC,KAAM;AAClF,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,gBAAA;AAAA,IACN,KAAA,GAAQ;AACN,MAAA,kBAAA,CAAmB,OAAA,CAAQ,eAAe,CAAA,CAAE,SAAA,CAAU,CAAC,KAAA,KAAmB;AACxE,QAAA,IAAIC,iBAAA,CAAa,KAAK,CAAA,IAAK,SAAA,IAAa,KAAA,EAAO;AAC7C,UAAA,yBAAA,CAA0B,KAAA,CAAM,SAAyB,OAAO,CAAA;AAAA,QAClE;AAAA,MACF,CAAC,CAAA;AAAA,IACH;AAAA,GACF;AACF,CAAC;AAED,SAAS,yBAAA,CAA0B,OAAqB,OAAA,EAAwB;AAC9E,EAAA,IAAI,SAAA,GAAY,KAAA;AAChB,EAAA,IAAI,IAAA;AAEJ,EAAA,KAAA,CACG,EAAA,CAAG,SAAS,MAAM;AAEjB,IAAA,IAAI,KAAA,CAAM,cAAc,kBAAA,EAAoB;AAC1C,MAAA,SAAA,GAAY,IAAA;AACZ,MAAA;AAAA,IACF;AAEA,IAAA,IAAA,GAAO,EAAE,SAAA,EAAW,KAAA,CAAM,SAAA,EAAU;AACpC,IAAA,IAAI,QAAQ,uBAAA,EAAyB;AACnC,MAAA,IAAA,CAAK,YAAY,KAAA,CAAM,SAAA;AAAA,IACzB;AAAA,EACF,CAAC,CAAA,CACA,EAAA,CAAG,MAAA,EAAQ,CAAA,IAAA,KAAQ;AAClB,IAAA,IAAI,CAAC,SAAA,EAAW;AACd,MAAA,SAAA,GAAY,IAAA;AAGZ,MAAA,IAAI,IAAA,KAAS,IAAA,IAAQ,IAAA,KAAS,CAAA,EAAG;AAC/B,QAAAC,kBAAA,CAAc;AAAA,UACZ,QAAA,EAAU,eAAA;AAAA,UACV,OAAA,EAAS,mCAAmC,IAAI,CAAA,CAAA,CAAA;AAAA,UAChD,KAAA,EAAO,IAAA,KAAS,CAAA,GAAI,MAAA,GAAS,SAAA;AAAA,UAC7B;AAAA,SACD,CAAA;AAAA,MACH;AAAA,IACF;AAAA,EACF,CAAC,CAAA,CACA,EAAA,CAAG,OAAA,EAAS,CAAA,KAAA,KAAS;AACpB,IAAA,IAAI,CAAC,SAAA,EAAW;AACd,MAAA,SAAA,GAAY,IAAA;AAEZ,MAAAA,kBAAA,CAAc;AAAA,QACZ,QAAA,EAAU,eAAA;AAAA,QACV,OAAA,EAAS,CAAA,4BAAA,EAA+B,KAAA,CAAM,OAAO,CAAA,CAAA,CAAA;AAAA,QACrD,KAAA,EAAO,OAAA;AAAA,QACP;AAAA,OACD,CAAA;AAAA,IACH;AAAA,EACF,CAAC,CAAA;AACL;;;;"}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
2
|
|
|
3
|
+
const attributes = require('@sentry/conventions/attributes');
|
|
4
|
+
const op = require('@sentry/conventions/op');
|
|
3
5
|
const core = require('@sentry/core');
|
|
4
6
|
const fs = require('fs');
|
|
5
7
|
const util = require('util');
|
|
@@ -7,7 +9,7 @@ const constants = require('./constants.js');
|
|
|
7
9
|
const utils = require('./utils.js');
|
|
8
10
|
|
|
9
11
|
const SPAN_ORIGIN = "auto.file.fs";
|
|
10
|
-
const SPAN_OP =
|
|
12
|
+
const SPAN_OP = op.FILE;
|
|
11
13
|
const FS_OPERATIONS_WITH_OLD_PATH_NEW_PATH = ["rename", "renameSync"];
|
|
12
14
|
const FS_OPERATIONS_WITH_SRC_DEST = ["copyFile", "cp", "copyFileSync", "cpSync"];
|
|
13
15
|
const FS_OPERATIONS_WITH_EXISTING_PATH_NEW_PATH = ["link", "linkSync"];
|
|
@@ -222,7 +224,7 @@ function enableFsInstrumentation(config = {}) {
|
|
|
222
224
|
function recordError(span, error, config) {
|
|
223
225
|
span.setStatus({ code: core.SPAN_STATUS_ERROR, message: "internal_error" });
|
|
224
226
|
if (config.recordErrorMessagesAsSpanAttributes && error instanceof Error) {
|
|
225
|
-
span.setAttribute(
|
|
227
|
+
span.setAttribute(attributes.ERROR_TYPE, error.code ?? error.name);
|
|
226
228
|
}
|
|
227
229
|
}
|
|
228
230
|
|