@sentry/node 11.0.0-alpha.2 → 11.0.0-beta.1
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/index.js +4 -3
- package/build/cjs/index.js.map +1 -1
- package/build/cjs/integrations/anr/index.js +1 -1
- package/build/cjs/integrations/fs/vendored/instrumentation.js +2 -1
- package/build/cjs/integrations/fs/vendored/instrumentation.js.map +1 -1
- package/build/cjs/integrations/http/SentryHttpInstrumentation.js +5 -4
- 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 +5 -33
- package/build/cjs/integrations/http/httpServerSpansIntegration.js.map +1 -1
- package/build/cjs/integrations/http/index.js +8 -4
- 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 +22 -16
- 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/sdk/api.js +2 -1
- package/build/cjs/sdk/api.js.map +1 -1
- package/build/cjs/sdk/client.js +2 -1
- package/build/cjs/sdk/client.js.map +1 -1
- package/build/cjs/sdk/index.js +1 -1
- package/build/cjs/sdk/index.js.map +1 -1
- package/build/esm/index.js +3 -2
- 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/fs/vendored/instrumentation.js +2 -1
- package/build/esm/integrations/fs/vendored/instrumentation.js.map +1 -1
- package/build/esm/integrations/http/SentryHttpInstrumentation.js +2 -1
- 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 +7 -35
- package/build/esm/integrations/http/httpServerSpansIntegration.js.map +1 -1
- package/build/esm/integrations/http/index.js +6 -2
- 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 +24 -18
- 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/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 +2 -1
- package/build/esm/sdk/client.js.map +1 -1
- package/build/esm/sdk/index.js +1 -1
- package/build/esm/sdk/index.js.map +1 -1
- package/build/import-hook.mjs +1 -1
- package/build/types/index.d.ts +4 -3
- package/build/types/index.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 +2 -1
- package/build/types/integrations/http/SentryHttpInstrumentation.d.ts.map +1 -1
- package/build/types/integrations/http/httpServerIntegration.d.ts +3 -2
- package/build/types/integrations/http/httpServerIntegration.d.ts.map +1 -1
- package/build/types/integrations/http/httpServerSpansIntegration.d.ts +9 -1
- package/build/types/integrations/http/httpServerSpansIntegration.d.ts.map +1 -1
- 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/sdk/api.d.ts.map +1 -1
- package/build/types/sdk/client.d.ts +1 -1
- package/build/types/sdk/client.d.ts.map +1 -1
- package/build/types/types.d.ts +2 -1
- package/build/types/types.d.ts.map +1 -1
- package/package.json +6 -5
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"onunhandledrejection.js","sources":["../../../src/integrations/onunhandledrejection.ts"],"sourcesContent":["import type { Client, IntegrationFn, SeverityLevel, Span } from '@sentry/core';\nimport {\n captureException,\n consoleSandbox,\n defineIntegration,\n getClient,\n isMatchingPattern,\n isObjectLike,\n withActiveSpan,\n} from '@sentry/core';\nimport { logAndExitProcess } from '../utils/errorhandling';\n\ntype UnhandledRejectionMode = 'none' | 'warn' | 'strict';\n\ntype IgnoreMatcher = { name?: string | RegExp; message?: string | RegExp };\n\ninterface OnUnhandledRejectionOptions {\n /**\n * Option deciding what to do after capturing unhandledRejection,\n * that mimicks behavior of node's --unhandled-rejection flag.\n */\n mode: UnhandledRejectionMode;\n /** Rejection Errors to ignore (don't capture or warn). */\n ignore?: IgnoreMatcher[];\n}\n\nconst INTEGRATION_NAME = 'OnUnhandledRejection';\n\nconst DEFAULT_IGNORES: IgnoreMatcher[] = [\n {\n name: 'AI_NoOutputGeneratedError', // When stream aborts in Vercel AI SDK V5, Vercel flush() fails with an error\n },\n {\n name: 'AbortError', // When stream aborts in Vercel AI SDK V6\n },\n];\n\nconst _onUnhandledRejectionIntegration = ((options: Partial<OnUnhandledRejectionOptions> = {}) => {\n const opts: OnUnhandledRejectionOptions = {\n mode: options.mode ?? 'warn',\n ignore: [...DEFAULT_IGNORES, ...(options.ignore ?? [])],\n };\n\n return {\n name: INTEGRATION_NAME,\n setup(client) {\n global.process.on('unhandledRejection', makeUnhandledPromiseHandler(client, opts));\n },\n };\n}) satisfies IntegrationFn;\n\nexport const onUnhandledRejectionIntegration = defineIntegration(_onUnhandledRejectionIntegration);\n\n/** Extract error info safely */\nfunction extractErrorInfo(reason: unknown): { name: string; message: string } {\n // Check if reason is an object (including Error instances, not just plain objects)\n if (!isObjectLike(reason)) {\n return { name: '', message: String(reason ?? '') };\n }\n\n const errorLike = reason as Record<string, unknown>;\n const name = typeof errorLike.name === 'string' ? errorLike.name : '';\n const message = typeof errorLike.message === 'string' ? errorLike.message : String(reason);\n\n return { name, message };\n}\n\n/** Check if a matcher matches the reason */\nfunction isMatchingReason(matcher: IgnoreMatcher, errorInfo: ReturnType<typeof extractErrorInfo>): boolean {\n // name/message matcher\n const nameMatches = matcher.name === undefined || isMatchingPattern(errorInfo.name, matcher.name, true);\n\n const messageMatches = matcher.message === undefined || isMatchingPattern(errorInfo.message, matcher.message);\n\n return nameMatches && messageMatches;\n}\n\n/** Match helper */\nfunction matchesIgnore(list: IgnoreMatcher[], reason: unknown): boolean {\n const errorInfo = extractErrorInfo(reason);\n return list.some(matcher => isMatchingReason(matcher, errorInfo));\n}\n\n/** Core handler */\nexport function makeUnhandledPromiseHandler(\n client: Client,\n options: OnUnhandledRejectionOptions,\n): (reason: unknown, promise: unknown) => void {\n return function sendUnhandledPromise(reason: unknown, _promise: unknown): void {\n // Only handle for the active client\n if (getClient() !== client) {\n return;\n }\n\n // Skip if configured to ignore\n if (matchesIgnore(options.ignore ?? [], reason)) {\n return;\n }\n\n const level: SeverityLevel = options.mode === 'strict' ? 'fatal' : 'error';\n\n // this can be set in places where we cannot reliably get access to the active span/error\n // when the error bubbles up to this handler, we can use this to set the active span\n const activeSpanForError = isObjectLike(reason)\n ? (reason as { _sentry_active_span?: Span })._sentry_active_span\n : undefined;\n\n const activeSpanWrapper = activeSpanForError\n ? (fn: () => void) => withActiveSpan(activeSpanForError, fn)\n : (fn: () => void) => fn();\n\n activeSpanWrapper(() => {\n captureException(reason, {\n originalException: reason,\n captureContext: {\n extra: { unhandledPromiseRejection: true },\n level,\n },\n mechanism: {\n handled: false,\n type: 'auto.node.onunhandledrejection',\n },\n });\n });\n\n handleRejection(reason, options.mode);\n };\n}\n\n/**\n * Handler for `mode` option\n */\nfunction handleRejection(reason: unknown, mode: UnhandledRejectionMode): void {\n // https://github.com/nodejs/node/blob/7cf6f9e964aa00772965391c23acda6d71972a9a/lib/internal/process/promises.js#L234-L240\n const rejectionWarning =\n 'This error originated either by ' +\n 'throwing inside of an async function without a catch block, ' +\n 'or by rejecting a promise which was not handled with .catch().' +\n ' The promise rejected with the reason:';\n\n /* eslint-disable no-console */\n if (mode === 'warn') {\n consoleSandbox(() => {\n console.warn(rejectionWarning);\n console.error(isObjectLike(reason) && 'stack' in reason ? reason.stack : reason);\n });\n } else if (mode === 'strict') {\n consoleSandbox(() => {\n
|
|
1
|
+
{"version":3,"file":"onunhandledrejection.js","sources":["../../../src/integrations/onunhandledrejection.ts"],"sourcesContent":["import type { Client, IntegrationFn, SeverityLevel, Span } from '@sentry/core';\nimport {\n captureException,\n consoleSandbox,\n defineIntegration,\n getClient,\n isMatchingPattern,\n isObjectLike,\n withActiveSpan,\n} from '@sentry/core';\nimport { logAndExitProcess } from '../utils/errorhandling';\n\ntype UnhandledRejectionMode = 'none' | 'warn' | 'strict';\n\ntype IgnoreMatcher = { name?: string | RegExp; message?: string | RegExp };\n\ninterface OnUnhandledRejectionOptions {\n /**\n * Option deciding what to do after capturing unhandledRejection,\n * that mimicks behavior of node's --unhandled-rejection flag.\n */\n mode: UnhandledRejectionMode;\n /** Rejection Errors to ignore (don't capture or warn). */\n ignore?: IgnoreMatcher[];\n}\n\nconst INTEGRATION_NAME = 'OnUnhandledRejection';\n\nconst DEFAULT_IGNORES: IgnoreMatcher[] = [\n {\n name: 'AI_NoOutputGeneratedError', // When stream aborts in Vercel AI SDK V5, Vercel flush() fails with an error\n },\n {\n name: 'AbortError', // When stream aborts in Vercel AI SDK V6\n },\n];\n\nconst _onUnhandledRejectionIntegration = ((options: Partial<OnUnhandledRejectionOptions> = {}) => {\n const opts: OnUnhandledRejectionOptions = {\n mode: options.mode ?? 'warn',\n ignore: [...DEFAULT_IGNORES, ...(options.ignore ?? [])],\n };\n\n return {\n name: INTEGRATION_NAME,\n setup(client) {\n global.process.on('unhandledRejection', makeUnhandledPromiseHandler(client, opts));\n },\n };\n}) satisfies IntegrationFn;\n\nexport const onUnhandledRejectionIntegration = defineIntegration(_onUnhandledRejectionIntegration);\n\n/** Extract error info safely */\nfunction extractErrorInfo(reason: unknown): { name: string; message: string } {\n // Check if reason is an object (including Error instances, not just plain objects)\n if (!isObjectLike(reason)) {\n return { name: '', message: String(reason ?? '') };\n }\n\n const errorLike = reason as Record<string, unknown>;\n const name = typeof errorLike.name === 'string' ? errorLike.name : '';\n const message = typeof errorLike.message === 'string' ? errorLike.message : String(reason);\n\n return { name, message };\n}\n\n/** Check if a matcher matches the reason */\nfunction isMatchingReason(matcher: IgnoreMatcher, errorInfo: ReturnType<typeof extractErrorInfo>): boolean {\n // name/message matcher\n const nameMatches = matcher.name === undefined || isMatchingPattern(errorInfo.name, matcher.name, true);\n\n const messageMatches = matcher.message === undefined || isMatchingPattern(errorInfo.message, matcher.message);\n\n return nameMatches && messageMatches;\n}\n\n/** Match helper */\nfunction matchesIgnore(list: IgnoreMatcher[], reason: unknown): boolean {\n const errorInfo = extractErrorInfo(reason);\n return list.some(matcher => isMatchingReason(matcher, errorInfo));\n}\n\n/** Core handler */\nexport function makeUnhandledPromiseHandler(\n client: Client,\n options: OnUnhandledRejectionOptions,\n): (reason: unknown, promise: unknown) => void {\n return function sendUnhandledPromise(reason: unknown, _promise: unknown): void {\n // Only handle for the active client\n if (getClient() !== client) {\n return;\n }\n\n // Skip if configured to ignore\n if (matchesIgnore(options.ignore ?? [], reason)) {\n return;\n }\n\n const level: SeverityLevel = options.mode === 'strict' ? 'fatal' : 'error';\n\n // this can be set in places where we cannot reliably get access to the active span/error\n // when the error bubbles up to this handler, we can use this to set the active span\n const activeSpanForError = isObjectLike(reason)\n ? (reason as { _sentry_active_span?: Span })._sentry_active_span\n : undefined;\n\n const activeSpanWrapper = activeSpanForError\n ? (fn: () => void) => withActiveSpan(activeSpanForError, fn)\n : (fn: () => void) => fn();\n\n activeSpanWrapper(() => {\n captureException(reason, {\n originalException: reason,\n captureContext: {\n extra: { unhandledPromiseRejection: true },\n level,\n },\n mechanism: {\n handled: false,\n type: 'auto.node.onunhandledrejection',\n },\n });\n });\n\n handleRejection(reason, options.mode);\n };\n}\n\n/**\n * Handler for `mode` option\n */\nfunction handleRejection(reason: unknown, mode: UnhandledRejectionMode): void {\n // https://github.com/nodejs/node/blob/7cf6f9e964aa00772965391c23acda6d71972a9a/lib/internal/process/promises.js#L234-L240\n const rejectionWarning =\n 'This error originated either by ' +\n 'throwing inside of an async function without a catch block, ' +\n 'or by rejecting a promise which was not handled with .catch().' +\n ' The promise rejected with the reason:';\n\n /* eslint-disable no-console */\n if (mode === 'warn') {\n consoleSandbox(() => {\n console.warn(rejectionWarning);\n console.error(isObjectLike(reason) && 'stack' in reason ? reason.stack : reason);\n });\n } else if (mode === 'strict') {\n if (!(isObjectLike(reason) && 'stack' in reason)) {\n consoleSandbox(() => {\n console.warn(rejectionWarning);\n });\n }\n logAndExitProcess(reason);\n }\n /* eslint-enable no-console */\n}\n"],"names":["defineIntegration","isObjectLike","isMatchingPattern","getClient","withActiveSpan","captureException","consoleSandbox","logAndExitProcess"],"mappings":"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"}
|
package/build/cjs/sdk/api.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
2
|
|
|
3
3
|
const core = require('@sentry/core');
|
|
4
|
+
const server = require('@sentry/core/server');
|
|
4
5
|
const module$1 = require('../utils/module.js');
|
|
5
6
|
|
|
6
7
|
function getSentryRelease(fallback) {
|
|
@@ -54,7 +55,7 @@ function getSentryRelease(fallback) {
|
|
|
54
55
|
);
|
|
55
56
|
return possibleReleaseNameOfGitProvider || possibleReleaseNameOfCiProvidersWithSpecificEnvVar || possibleReleaseNameOfCiProvidersWithGenericEnvVar || fallback;
|
|
56
57
|
}
|
|
57
|
-
const defaultStackParser = core.createStackParser(
|
|
58
|
+
const defaultStackParser = core.createStackParser(server.nodeStackLineParser(module$1.createGetModuleFromFilename()));
|
|
58
59
|
|
|
59
60
|
exports.defaultStackParser = defaultStackParser;
|
|
60
61
|
exports.getSentryRelease = getSentryRelease;
|
package/build/cjs/sdk/api.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api.js","sources":["../../../src/sdk/api.ts"],"sourcesContent":["// PUBLIC APIS\n\nimport type { StackParser } from '@sentry/core';\nimport { createStackParser, GLOBAL_OBJ
|
|
1
|
+
{"version":3,"file":"api.js","sources":["../../../src/sdk/api.ts"],"sourcesContent":["// PUBLIC APIS\n\nimport type { StackParser } from '@sentry/core';\nimport { createStackParser, GLOBAL_OBJ } from '@sentry/core';\nimport { nodeStackLineParser } from '@sentry/core/server';\nimport { createGetModuleFromFilename } from '../utils/module';\n\n/**\n * Returns a release dynamically from environment variables.\n */\n// eslint-disable-next-line complexity\nexport function getSentryRelease(fallback?: string): string | undefined {\n // Always read first as Sentry takes this as precedence\n if (process.env.SENTRY_RELEASE) {\n return process.env.SENTRY_RELEASE;\n }\n\n // This supports the variable that sentry-webpack-plugin injects\n if (GLOBAL_OBJ.SENTRY_RELEASE?.id) {\n return GLOBAL_OBJ.SENTRY_RELEASE.id;\n }\n\n // This list is in approximate alpha order, separated into 3 categories:\n // 1. Git providers\n // 2. CI providers with specific environment variables (has the provider name in the variable name)\n // 3. CI providers with generic environment variables (checked for last to prevent possible false positives)\n\n const possibleReleaseNameOfGitProvider =\n // GitHub Actions - https://help.github.com/en/actions/configuring-and-managing-workflows/using-environment-variables#default-environment-variables\n process.env['GITHUB_SHA'] ||\n // GitLab CI - https://docs.gitlab.com/ee/ci/variables/predefined_variables.html\n process.env['CI_MERGE_REQUEST_SOURCE_BRANCH_SHA'] ||\n process.env['CI_BUILD_REF'] ||\n process.env['CI_COMMIT_SHA'] ||\n // Bitbucket - https://support.atlassian.com/bitbucket-cloud/docs/variables-and-secrets/\n process.env['BITBUCKET_COMMIT'];\n\n const possibleReleaseNameOfCiProvidersWithSpecificEnvVar =\n // AppVeyor - https://www.appveyor.com/docs/environment-variables/\n process.env['APPVEYOR_PULL_REQUEST_HEAD_COMMIT'] ||\n process.env['APPVEYOR_REPO_COMMIT'] ||\n // AWS CodeBuild - https://docs.aws.amazon.com/codebuild/latest/userguide/build-env-ref-env-vars.html\n process.env['CODEBUILD_RESOLVED_SOURCE_VERSION'] ||\n // AWS Amplify - https://docs.aws.amazon.com/amplify/latest/userguide/environment-variables.html\n process.env['AWS_COMMIT_ID'] ||\n // Azure Pipelines - https://docs.microsoft.com/en-us/azure/devops/pipelines/build/variables?view=azure-devops&tabs=yaml\n process.env['BUILD_SOURCEVERSION'] ||\n // Bitrise - https://devcenter.bitrise.io/builds/available-environment-variables/\n process.env['GIT_CLONE_COMMIT_HASH'] ||\n // Buddy CI - https://buddy.works/docs/pipelines/environment-variables#default-environment-variables\n process.env['BUDDY_EXECUTION_REVISION'] ||\n // Builtkite - https://buildkite.com/docs/pipelines/environment-variables\n process.env['BUILDKITE_COMMIT'] ||\n // CircleCI - https://circleci.com/docs/variables/\n process.env['CIRCLE_SHA1'] ||\n // Cirrus CI - https://cirrus-ci.org/guide/writing-tasks/#environment-variables\n process.env['CIRRUS_CHANGE_IN_REPO'] ||\n // Codefresh - https://codefresh.io/docs/docs/codefresh-yaml/variables/\n process.env['CF_REVISION'] ||\n // Codemagic - https://docs.codemagic.io/yaml-basic-configuration/environment-variables/\n process.env['CM_COMMIT'] ||\n // Cloudflare Pages - https://developers.cloudflare.com/pages/platform/build-configuration/#environment-variables\n process.env['CF_PAGES_COMMIT_SHA'] ||\n // Drone - https://docs.drone.io/pipeline/environment/reference/\n process.env['DRONE_COMMIT_SHA'] ||\n // Flightcontrol - https://www.flightcontrol.dev/docs/guides/flightcontrol/environment-variables#built-in-environment-variables\n process.env['FC_GIT_COMMIT_SHA'] ||\n // Heroku #1 https://devcenter.heroku.com/articles/heroku-ci\n process.env['HEROKU_TEST_RUN_COMMIT_VERSION'] ||\n // Heroku #2 https://devcenter.heroku.com/articles/dyno-metadata#dyno-metadata\n process.env['HEROKU_BUILD_COMMIT'] ||\n // Heroku #3 (deprecated by Heroku, kept for backward compatibility)\n process.env['HEROKU_SLUG_COMMIT'] ||\n // Railway - https://docs.railway.app/reference/variables#git-variables\n process.env['RAILWAY_GIT_COMMIT_SHA'] ||\n // Render - https://render.com/docs/environment-variables\n process.env['RENDER_GIT_COMMIT'] ||\n // Semaphore CI - https://docs.semaphoreci.com/ci-cd-environment/environment-variables\n process.env['SEMAPHORE_GIT_SHA'] ||\n // TravisCI - https://docs.travis-ci.com/user/environment-variables/#default-environment-variables\n process.env['TRAVIS_PULL_REQUEST_SHA'] ||\n // Vercel - https://vercel.com/docs/v2/build-step#system-environment-variables\n process.env['VERCEL_GIT_COMMIT_SHA'] ||\n process.env['VERCEL_GITHUB_COMMIT_SHA'] ||\n process.env['VERCEL_GITLAB_COMMIT_SHA'] ||\n process.env['VERCEL_BITBUCKET_COMMIT_SHA'] ||\n // Zeit (now known as Vercel)\n process.env['ZEIT_GITHUB_COMMIT_SHA'] ||\n process.env['ZEIT_GITLAB_COMMIT_SHA'] ||\n process.env['ZEIT_BITBUCKET_COMMIT_SHA'];\n\n const possibleReleaseNameOfCiProvidersWithGenericEnvVar =\n // CloudBees CodeShip - https://docs.cloudbees.com/docs/cloudbees-codeship/latest/pro-builds-and-configuration/environment-variables\n process.env['CI_COMMIT_ID'] ||\n // Coolify - https://coolify.io/docs/knowledge-base/environment-variables\n process.env['SOURCE_COMMIT'] ||\n // Heroku #3 https://devcenter.heroku.com/changelog-items/630\n process.env['SOURCE_VERSION'] ||\n // Jenkins - https://plugins.jenkins.io/git/#environment-variables\n process.env['GIT_COMMIT'] ||\n // Netlify - https://docs.netlify.com/configure-builds/environment-variables/#build-metadata\n process.env['COMMIT_REF'] ||\n // TeamCity - https://www.jetbrains.com/help/teamcity/predefined-build-parameters.html\n process.env['BUILD_VCS_NUMBER'] ||\n // Woodpecker CI - https://woodpecker-ci.org/docs/usage/environment\n process.env['CI_COMMIT_SHA'];\n\n return (\n possibleReleaseNameOfGitProvider ||\n possibleReleaseNameOfCiProvidersWithSpecificEnvVar ||\n possibleReleaseNameOfCiProvidersWithGenericEnvVar ||\n fallback\n );\n}\n\n/** Node.js stack parser */\nexport const defaultStackParser: StackParser = createStackParser(nodeStackLineParser(createGetModuleFromFilename()));\n"],"names":["GLOBAL_OBJ","createStackParser","nodeStackLineParser","createGetModuleFromFilename"],"mappings":";;;;;;AAWO,SAAS,iBAAiB,QAAA,EAAuC;AAEtE,EAAA,IAAI,OAAA,CAAQ,IAAI,cAAA,EAAgB;AAC9B,IAAA,OAAO,QAAQ,GAAA,CAAI,cAAA;AAAA,EACrB;AAGA,EAAA,IAAIA,eAAA,CAAW,gBAAgB,EAAA,EAAI;AACjC,IAAA,OAAOA,gBAAW,cAAA,CAAe,EAAA;AAAA,EACnC;AAOA,EAAA,MAAM,gCAAA;AAAA;AAAA,IAEJ,OAAA,CAAQ,IAAI,YAAY,CAAA;AAAA,IAExB,OAAA,CAAQ,GAAA,CAAI,oCAAoC,CAAA,IAChD,OAAA,CAAQ,IAAI,cAAc,CAAA,IAC1B,OAAA,CAAQ,GAAA,CAAI,eAAe,CAAA;AAAA,IAE3B,OAAA,CAAQ,IAAI,kBAAkB;AAAA,GAAA;AAEhC,EAAA,MAAM,kDAAA;AAAA;AAAA,IAEJ,QAAQ,GAAA,CAAI,mCAAmC,CAAA,IAC/C,OAAA,CAAQ,IAAI,sBAAsB,CAAA;AAAA,IAElC,OAAA,CAAQ,IAAI,mCAAmC,CAAA;AAAA,IAE/C,OAAA,CAAQ,IAAI,eAAe,CAAA;AAAA,IAE3B,OAAA,CAAQ,IAAI,qBAAqB,CAAA;AAAA,IAEjC,OAAA,CAAQ,IAAI,uBAAuB,CAAA;AAAA,IAEnC,OAAA,CAAQ,IAAI,0BAA0B,CAAA;AAAA,IAEtC,OAAA,CAAQ,IAAI,kBAAkB,CAAA;AAAA,IAE9B,OAAA,CAAQ,IAAI,aAAa,CAAA;AAAA,IAEzB,OAAA,CAAQ,IAAI,uBAAuB,CAAA;AAAA,IAEnC,OAAA,CAAQ,IAAI,aAAa,CAAA;AAAA,IAEzB,OAAA,CAAQ,IAAI,WAAW,CAAA;AAAA,IAEvB,OAAA,CAAQ,IAAI,qBAAqB,CAAA;AAAA,IAEjC,OAAA,CAAQ,IAAI,kBAAkB,CAAA;AAAA,IAE9B,OAAA,CAAQ,IAAI,mBAAmB,CAAA;AAAA,IAE/B,OAAA,CAAQ,IAAI,gCAAgC,CAAA;AAAA,IAE5C,OAAA,CAAQ,IAAI,qBAAqB,CAAA;AAAA,IAEjC,OAAA,CAAQ,IAAI,oBAAoB,CAAA;AAAA,IAEhC,OAAA,CAAQ,IAAI,wBAAwB,CAAA;AAAA,IAEpC,OAAA,CAAQ,IAAI,mBAAmB,CAAA;AAAA,IAE/B,OAAA,CAAQ,IAAI,mBAAmB,CAAA;AAAA,IAE/B,OAAA,CAAQ,IAAI,yBAAyB,CAAA;AAAA,IAErC,OAAA,CAAQ,GAAA,CAAI,uBAAuB,CAAA,IACnC,QAAQ,GAAA,CAAI,0BAA0B,CAAA,IACtC,OAAA,CAAQ,GAAA,CAAI,0BAA0B,CAAA,IACtC,OAAA,CAAQ,IAAI,6BAA6B,CAAA;AAAA,IAEzC,OAAA,CAAQ,GAAA,CAAI,wBAAwB,CAAA,IACpC,OAAA,CAAQ,IAAI,wBAAwB,CAAA,IACpC,OAAA,CAAQ,GAAA,CAAI,2BAA2B;AAAA,GAAA;AAEzC,EAAA,MAAM,iDAAA;AAAA;AAAA,IAEJ,OAAA,CAAQ,IAAI,cAAc,CAAA;AAAA,IAE1B,OAAA,CAAQ,IAAI,eAAe,CAAA;AAAA,IAE3B,OAAA,CAAQ,IAAI,gBAAgB,CAAA;AAAA,IAE5B,OAAA,CAAQ,IAAI,YAAY,CAAA;AAAA,IAExB,OAAA,CAAQ,IAAI,YAAY,CAAA;AAAA,IAExB,OAAA,CAAQ,IAAI,kBAAkB,CAAA;AAAA,IAE9B,OAAA,CAAQ,IAAI,eAAe;AAAA,GAAA;AAE7B,EAAA,OACE,gCAAA,IACA,sDACA,iDAAA,IACA,QAAA;AAEJ;AAGO,MAAM,kBAAA,GAAkCC,sBAAA,CAAkBC,0BAAA,CAAoBC,oCAAA,EAA6B,CAAC;;;;;"}
|
package/build/cjs/sdk/client.js
CHANGED
|
@@ -3,13 +3,14 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
3
3
|
const os = require('node:os');
|
|
4
4
|
const api = require('@opentelemetry/api');
|
|
5
5
|
const core = require('@sentry/core');
|
|
6
|
+
const server = require('@sentry/core/server');
|
|
6
7
|
const opentelemetry = require('@sentry/opentelemetry');
|
|
7
8
|
const serverUtils = require('@sentry/server-utils');
|
|
8
9
|
const worker_threads = require('worker_threads');
|
|
9
10
|
const debugBuild = require('../debug-build.js');
|
|
10
11
|
|
|
11
12
|
const DEFAULT_CLIENT_REPORT_FLUSH_INTERVAL_MS = 6e4;
|
|
12
|
-
class NodeClient extends
|
|
13
|
+
class NodeClient extends server.ServerRuntimeClient {
|
|
13
14
|
constructor(options) {
|
|
14
15
|
const serverName = options.includeServerName === false ? void 0 : options.serverName || global.process.env.SENTRY_NAME || os.hostname();
|
|
15
16
|
const clientOptions = {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","sources":["../../../src/sdk/client.ts"],"sourcesContent":["import * as os from 'node:os';\nimport type { Tracer } from '@opentelemetry/api';\nimport { trace } from '@opentelemetry/api';\nimport type { ServerRuntimeClientOptions } from '@sentry/core';\nimport {\n _INTERNAL_clearAiProviderSkips,\n _INTERNAL_flushLogsBuffer,\n _INTERNAL_setDeferSegmentSpanCapture,\n applySdkMetadata,\n debug,\n SDK_VERSION,\n ServerRuntimeClient,\n} from '@sentry/core';\nimport {\n type AsyncLocalStorageLookup,\n registerPrepareSpanScope,\n type SentryTracerProvider,\n setOpenTelemetryContextAsyncContextStrategy,\n} from '@sentry/opentelemetry';\nimport { setAsyncLocalStorageAsyncContextStrategy } from '@sentry/server-utils';\nimport { isMainThread, threadId } from 'worker_threads';\nimport { DEBUG_BUILD } from '../debug-build';\nimport type { NodeClientOptions } from '../types';\n\nconst DEFAULT_CLIENT_REPORT_FLUSH_INTERVAL_MS = 60_000; // 60s was chosen arbitrarily\n\n/** A client for using Sentry with Node & OpenTelemetry. */\nexport class NodeClient extends ServerRuntimeClient<NodeClientOptions> {\n public traceProvider: SentryTracerProvider | undefined;\n public asyncLocalStorageLookup: AsyncLocalStorageLookup | undefined;\n\n private _tracer: Tracer | undefined;\n private _clientReportInterval: NodeJS.Timeout | undefined;\n private _clientReportOnExitFlushListener: (() => void) | undefined;\n private _logOnExitFlushListener: (() => void) | undefined;\n\n public constructor(options: NodeClientOptions) {\n const serverName =\n options.includeServerName === false\n ? undefined\n : options.serverName || global.process.env.SENTRY_NAME || os.hostname();\n\n const clientOptions: ServerRuntimeClientOptions = {\n ...options,\n platform: 'node',\n // Use provided runtime or default to 'node' with current process version\n runtime: options.runtime || { name: 'node', version: global.process.version },\n serverName,\n };\n\n applySdkMetadata(clientOptions, 'node');\n\n debug.log(`Initializing Sentry: process: ${process.pid}, thread: ${isMainThread ? 'main' : `worker-${threadId}`}.`);\n\n super(clientOptions);\n\n this._logOnExitFlushListener = () => {\n _INTERNAL_flushLogsBuffer(this);\n };\n\n if (serverName) {\n this.on('beforeCaptureLog', log => {\n log.attributes = {\n ...log.attributes,\n 'server.address': serverName,\n };\n });\n }\n\n process.on('beforeExit', this._logOnExitFlushListener);\n\n // Enable deferred segment-span transaction capture here, in the constructor, rather than in\n // `initOtel`. Every client runs its constructor exactly once, whereas `initOtel` only runs on\n // `Sentry.init()` and only fully wires up the first client (a second `init` loses the\n // `setGlobalTracerProvider` race and bails early, and a manually constructed `NodeClient` never\n // runs `initOtel` at all). Anchoring on the constructor means every client — first, second, or\n // manual — defers correctly. It's unconditional and cheap: clients on the OpenTelemetry SDK\n // provider path produce OTel spans that never reach `SentrySpan`, so the strategy is simply never\n // consulted for them.\n _INTERNAL_setDeferSegmentSpanCapture(this);\n\n // Same constructor anchoring as above: every client must continue incoming (remote) traces,\n // also manually constructed ones that never run `initOtel`.\n registerPrepareSpanScope(this);\n }\n\n /** @inheritDoc */\n public init(): void {\n // Must run before `super.init()`: channel-based integrations capture the strategy's\n // AsyncLocalStorage via `getTracingChannelBinding()` during integration setup.\n if (this.getOptions().enableOpenTelemetrySetup) {\n this.asyncLocalStorageLookup = setOpenTelemetryContextAsyncContextStrategy();\n } else {\n this.asyncLocalStorageLookup = { asyncLocalStorage: setAsyncLocalStorageAsyncContextStrategy() };\n }\n\n super.init();\n }\n\n /** Get the OTEL tracer. */\n public get tracer(): Tracer {\n if (this._tracer) {\n return this._tracer;\n }\n\n const name = '@sentry/node';\n const version = SDK_VERSION;\n const tracer = trace.getTracer(name, version);\n this._tracer = tracer;\n\n return tracer;\n }\n\n /** @inheritDoc */\n // @ts-expect-error - PromiseLike is a subset of Promise\n public async flush(timeout?: number): PromiseLike<boolean> {\n await this.traceProvider?.forceFlush();\n\n if (this.getOptions().sendClientReports) {\n this._flushOutcomes();\n }\n\n return super.flush(timeout);\n }\n\n /** @inheritDoc */\n // @ts-expect-error - PromiseLike is a subset of Promise\n public async close(timeout?: number | undefined): PromiseLike<boolean> {\n if (this._clientReportInterval) {\n clearInterval(this._clientReportInterval);\n }\n\n if (this._clientReportOnExitFlushListener) {\n process.off('beforeExit', this._clientReportOnExitFlushListener);\n }\n\n if (this._logOnExitFlushListener) {\n process.off('beforeExit', this._logOnExitFlushListener);\n }\n\n const allEventsSent = await super.close(timeout);\n if (this.traceProvider) {\n await this.traceProvider.shutdown();\n }\n\n return allEventsSent;\n }\n\n /**\n * Will start tracking client reports for this client.\n *\n * NOTICE: This method will create an interval that is periodically called and attach a `process.on('beforeExit')`\n * hook. To clean up these resources, call `.close()` when you no longer intend to use the client. Not doing so will\n * result in a memory leak.\n */\n // The reason client reports need to be manually activated with this method instead of just enabling them in a\n // constructor, is that if users periodically and unboundedly create new clients, we will create more and more\n // intervals and beforeExit listeners, thus leaking memory. In these situations, users are required to call\n // `client.close()` in order to dispose of the acquired resources.\n // We assume that calling this method in Sentry.init() is a sensible default, because calling Sentry.init() over and\n // over again would also result in memory leaks.\n // Note: We have experimented with using `FinalizationRegisty` to clear the interval when the client is garbage\n // collected, but it did not work, because the cleanup function never got called.\n public startClientReportTracking(): void {\n const clientOptions = this.getOptions();\n if (clientOptions.sendClientReports) {\n this._clientReportOnExitFlushListener = () => {\n this._flushOutcomes();\n };\n\n this._clientReportInterval = setInterval(() => {\n DEBUG_BUILD && debug.log('Flushing client reports based on interval.');\n this._flushOutcomes();\n }, clientOptions.clientReportFlushInterval ?? DEFAULT_CLIENT_REPORT_FLUSH_INTERVAL_MS)\n // Unref is critical for not preventing the process from exiting because the interval is active.\n .unref();\n\n process.on('beforeExit', this._clientReportOnExitFlushListener);\n }\n }\n\n /** @inheritDoc */\n protected _setupIntegrations(): void {\n // Clear AI provider skip registrations before setting up integrations\n // This ensures a clean state between different client initializations\n // (e.g., when LangChain skips OpenAI in one client, but a subsequent client uses OpenAI standalone)\n _INTERNAL_clearAiProviderSkips();\n super._setupIntegrations();\n }\n}\n"],"names":["ServerRuntimeClient","applySdkMetadata","debug","isMainThread","threadId","_INTERNAL_flushLogsBuffer","_INTERNAL_setDeferSegmentSpanCapture","registerPrepareSpanScope","setOpenTelemetryContextAsyncContextStrategy","setAsyncLocalStorageAsyncContextStrategy","SDK_VERSION","trace","DEBUG_BUILD","_INTERNAL_clearAiProviderSkips"],"mappings":";;;;;;;;;;AAwBA,MAAM,uCAAA,GAA0C,GAAA;AAGzC,MAAM,mBAAmBA,wBAAA,CAAuC;AAAA,EAS9D,YAAY,OAAA,EAA4B;AAC7C,IAAA,MAAM,UAAA,GACJ,OAAA,CAAQ,iBAAA,KAAsB,KAAA,GAC1B,MAAA,GACA,OAAA,CAAQ,UAAA,IAAc,MAAA,CAAO,OAAA,CAAQ,GAAA,CAAI,WAAA,IAAe,EAAA,CAAG,QAAA,EAAS;AAE1E,IAAA,MAAM,aAAA,GAA4C;AAAA,MAChD,GAAG,OAAA;AAAA,MACH,QAAA,EAAU,MAAA;AAAA;AAAA,MAEV,OAAA,EAAS,QAAQ,OAAA,IAAW,EAAE,MAAM,MAAA,EAAQ,OAAA,EAAS,MAAA,CAAO,OAAA,CAAQ,OAAA,EAAQ;AAAA,MAC5E;AAAA,KACF;AAEA,IAAAC,qBAAA,CAAiB,eAAe,MAAM,CAAA;AAEtC,IAAAC,UAAA,CAAM,GAAA,CAAI,CAAA,8BAAA,EAAiC,OAAA,CAAQ,GAAG,CAAA,UAAA,EAAaC,8BAAe,MAAA,GAAS,CAAA,OAAA,EAAUC,uBAAQ,CAAA,CAAE,CAAA,CAAA,CAAG,CAAA;AAElH,IAAA,KAAA,CAAM,aAAa,CAAA;AAEnB,IAAA,IAAA,CAAK,0BAA0B,MAAM;AACnC,MAAAC,8BAAA,CAA0B,IAAI,CAAA;AAAA,IAChC,CAAA;AAEA,IAAA,IAAI,UAAA,EAAY;AACd,MAAA,IAAA,CAAK,EAAA,CAAG,oBAAoB,CAAA,GAAA,KAAO;AACjC,QAAA,GAAA,CAAI,UAAA,GAAa;AAAA,UACf,GAAG,GAAA,CAAI,UAAA;AAAA,UACP,gBAAA,EAAkB;AAAA,SACpB;AAAA,MACF,CAAC,CAAA;AAAA,IACH;AAEA,IAAA,OAAA,CAAQ,EAAA,CAAG,YAAA,EAAc,IAAA,CAAK,uBAAuB,CAAA;AAUrD,IAAAC,yCAAA,CAAqC,IAAI,CAAA;AAIzC,IAAAC,sCAAA,CAAyB,IAAI,CAAA;AAAA,EAC/B;AAAA;AAAA,EAGO,IAAA,GAAa;AAGlB,IAAA,IAAI,IAAA,CAAK,UAAA,EAAW,CAAE,wBAAA,EAA0B;AAC9C,MAAA,IAAA,CAAK,0BAA0BC,yDAAA,EAA4C;AAAA,IAC7E,CAAA,MAAO;AACL,MAAA,IAAA,CAAK,uBAAA,GAA0B,EAAE,iBAAA,EAAmBC,oDAAA,EAAyC,EAAE;AAAA,IACjG;AAEA,IAAA,KAAA,CAAM,IAAA,EAAK;AAAA,EACb;AAAA;AAAA,EAGA,IAAW,MAAA,GAAiB;AAC1B,IAAA,IAAI,KAAK,OAAA,EAAS;AAChB,MAAA,OAAO,IAAA,CAAK,OAAA;AAAA,IACd;AAEA,IAAA,MAAM,IAAA,GAAO,cAAA;AACb,IAAA,MAAM,OAAA,GAAUC,gBAAA;AAChB,IAAA,MAAM,MAAA,GAASC,SAAA,CAAM,SAAA,CAAU,IAAA,EAAM,OAAO,CAAA;AAC5C,IAAA,IAAA,CAAK,OAAA,GAAU,MAAA;AAEf,IAAA,OAAO,MAAA;AAAA,EACT;AAAA;AAAA;AAAA,EAIA,MAAa,MAAM,OAAA,EAAwC;AACzD,IAAA,MAAM,IAAA,CAAK,eAAe,UAAA,EAAW;AAErC,IAAA,IAAI,IAAA,CAAK,UAAA,EAAW,CAAE,iBAAA,EAAmB;AACvC,MAAA,IAAA,CAAK,cAAA,EAAe;AAAA,IACtB;AAEA,IAAA,OAAO,KAAA,CAAM,MAAM,OAAO,CAAA;AAAA,EAC5B;AAAA;AAAA;AAAA,EAIA,MAAa,MAAM,OAAA,EAAoD;AACrE,IAAA,IAAI,KAAK,qBAAA,EAAuB;AAC9B,MAAA,aAAA,CAAc,KAAK,qBAAqB,CAAA;AAAA,IAC1C;AAEA,IAAA,IAAI,KAAK,gCAAA,EAAkC;AACzC,MAAA,OAAA,CAAQ,GAAA,CAAI,YAAA,EAAc,IAAA,CAAK,gCAAgC,CAAA;AAAA,IACjE;AAEA,IAAA,IAAI,KAAK,uBAAA,EAAyB;AAChC,MAAA,OAAA,CAAQ,GAAA,CAAI,YAAA,EAAc,IAAA,CAAK,uBAAuB,CAAA;AAAA,IACxD;AAEA,IAAA,MAAM,aAAA,GAAgB,MAAM,KAAA,CAAM,KAAA,CAAM,OAAO,CAAA;AAC/C,IAAA,IAAI,KAAK,aAAA,EAAe;AACtB,MAAA,MAAM,IAAA,CAAK,cAAc,QAAA,EAAS;AAAA,IACpC;AAEA,IAAA,OAAO,aAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAiBO,yBAAA,GAAkC;AACvC,IAAA,MAAM,aAAA,GAAgB,KAAK,UAAA,EAAW;AACtC,IAAA,IAAI,cAAc,iBAAA,EAAmB;AACnC,MAAA,IAAA,CAAK,mCAAmC,MAAM;AAC5C,QAAA,IAAA,CAAK,cAAA,EAAe;AAAA,MACtB,CAAA;AAEA,MAAA,IAAA,CAAK,qBAAA,GAAwB,YAAY,MAAM;AAC7C,QAAAC,sBAAA,IAAeV,UAAA,CAAM,IAAI,4CAA4C,CAAA;AACrE,QAAA,IAAA,CAAK,cAAA,EAAe;AAAA,MACtB,CAAA,EAAG,aAAA,CAAc,yBAAA,IAA6B,uCAAuC,EAElF,KAAA,EAAM;AAET,MAAA,OAAA,CAAQ,EAAA,CAAG,YAAA,EAAc,IAAA,CAAK,gCAAgC,CAAA;AAAA,IAChE;AAAA,EACF;AAAA;AAAA,EAGU,kBAAA,GAA2B;AAInC,IAAAW,mCAAA,EAA+B;AAC/B,IAAA,KAAA,CAAM,kBAAA,EAAmB;AAAA,EAC3B;AACF;;;;"}
|
|
1
|
+
{"version":3,"file":"client.js","sources":["../../../src/sdk/client.ts"],"sourcesContent":["import * as os from 'node:os';\nimport type { Tracer } from '@opentelemetry/api';\nimport { trace } from '@opentelemetry/api';\nimport type { ServerRuntimeClientOptions } from '@sentry/core/server';\nimport {\n _INTERNAL_clearAiProviderSkips,\n _INTERNAL_flushLogsBuffer,\n _INTERNAL_setDeferSegmentSpanCapture,\n applySdkMetadata,\n debug,\n SDK_VERSION,\n} from '@sentry/core';\nimport { ServerRuntimeClient } from '@sentry/core/server';\nimport {\n type AsyncLocalStorageLookup,\n registerPrepareSpanScope,\n type SentryTracerProvider,\n setOpenTelemetryContextAsyncContextStrategy,\n} from '@sentry/opentelemetry';\nimport { setAsyncLocalStorageAsyncContextStrategy } from '@sentry/server-utils';\nimport { isMainThread, threadId } from 'worker_threads';\nimport { DEBUG_BUILD } from '../debug-build';\nimport type { NodeClientOptions } from '../types';\n\nconst DEFAULT_CLIENT_REPORT_FLUSH_INTERVAL_MS = 60_000; // 60s was chosen arbitrarily\n\n/** A client for using Sentry with Node & OpenTelemetry. */\nexport class NodeClient extends ServerRuntimeClient<NodeClientOptions> {\n public traceProvider: SentryTracerProvider | undefined;\n public asyncLocalStorageLookup: AsyncLocalStorageLookup | undefined;\n\n private _tracer: Tracer | undefined;\n private _clientReportInterval: NodeJS.Timeout | undefined;\n private _clientReportOnExitFlushListener: (() => void) | undefined;\n private _logOnExitFlushListener: (() => void) | undefined;\n\n public constructor(options: NodeClientOptions) {\n const serverName =\n options.includeServerName === false\n ? undefined\n : options.serverName || global.process.env.SENTRY_NAME || os.hostname();\n\n const clientOptions: ServerRuntimeClientOptions = {\n ...options,\n platform: 'node',\n // Use provided runtime or default to 'node' with current process version\n runtime: options.runtime || { name: 'node', version: global.process.version },\n serverName,\n };\n\n applySdkMetadata(clientOptions, 'node');\n\n debug.log(`Initializing Sentry: process: ${process.pid}, thread: ${isMainThread ? 'main' : `worker-${threadId}`}.`);\n\n super(clientOptions);\n\n this._logOnExitFlushListener = () => {\n _INTERNAL_flushLogsBuffer(this);\n };\n\n if (serverName) {\n this.on('beforeCaptureLog', log => {\n log.attributes = {\n ...log.attributes,\n 'server.address': serverName,\n };\n });\n }\n\n process.on('beforeExit', this._logOnExitFlushListener);\n\n // Enable deferred segment-span transaction capture here, in the constructor, rather than in\n // `initOtel`. Every client runs its constructor exactly once, whereas `initOtel` only runs on\n // `Sentry.init()` and only fully wires up the first client (a second `init` loses the\n // `setGlobalTracerProvider` race and bails early, and a manually constructed `NodeClient` never\n // runs `initOtel` at all). Anchoring on the constructor means every client — first, second, or\n // manual — defers correctly. It's unconditional and cheap: clients on the OpenTelemetry SDK\n // provider path produce OTel spans that never reach `SentrySpan`, so the strategy is simply never\n // consulted for them.\n _INTERNAL_setDeferSegmentSpanCapture(this);\n\n // Same constructor anchoring as above: every client must continue incoming (remote) traces,\n // also manually constructed ones that never run `initOtel`.\n registerPrepareSpanScope(this);\n }\n\n /** @inheritDoc */\n public init(): void {\n // Must run before `super.init()`: channel-based integrations capture the strategy's\n // AsyncLocalStorage via `getTracingChannelBinding()` during integration setup.\n if (this.getOptions().enableOpenTelemetrySetup) {\n this.asyncLocalStorageLookup = setOpenTelemetryContextAsyncContextStrategy();\n } else {\n this.asyncLocalStorageLookup = { asyncLocalStorage: setAsyncLocalStorageAsyncContextStrategy() };\n }\n\n super.init();\n }\n\n /** Get the OTEL tracer. */\n public get tracer(): Tracer {\n if (this._tracer) {\n return this._tracer;\n }\n\n const name = '@sentry/node';\n const version = SDK_VERSION;\n const tracer = trace.getTracer(name, version);\n this._tracer = tracer;\n\n return tracer;\n }\n\n /** @inheritDoc */\n // @ts-expect-error - PromiseLike is a subset of Promise\n public async flush(timeout?: number): PromiseLike<boolean> {\n await this.traceProvider?.forceFlush();\n\n if (this.getOptions().sendClientReports) {\n this._flushOutcomes();\n }\n\n return super.flush(timeout);\n }\n\n /** @inheritDoc */\n // @ts-expect-error - PromiseLike is a subset of Promise\n public async close(timeout?: number | undefined): PromiseLike<boolean> {\n if (this._clientReportInterval) {\n clearInterval(this._clientReportInterval);\n }\n\n if (this._clientReportOnExitFlushListener) {\n process.off('beforeExit', this._clientReportOnExitFlushListener);\n }\n\n if (this._logOnExitFlushListener) {\n process.off('beforeExit', this._logOnExitFlushListener);\n }\n\n const allEventsSent = await super.close(timeout);\n if (this.traceProvider) {\n await this.traceProvider.shutdown();\n }\n\n return allEventsSent;\n }\n\n /**\n * Will start tracking client reports for this client.\n *\n * NOTICE: This method will create an interval that is periodically called and attach a `process.on('beforeExit')`\n * hook. To clean up these resources, call `.close()` when you no longer intend to use the client. Not doing so will\n * result in a memory leak.\n */\n // The reason client reports need to be manually activated with this method instead of just enabling them in a\n // constructor, is that if users periodically and unboundedly create new clients, we will create more and more\n // intervals and beforeExit listeners, thus leaking memory. In these situations, users are required to call\n // `client.close()` in order to dispose of the acquired resources.\n // We assume that calling this method in Sentry.init() is a sensible default, because calling Sentry.init() over and\n // over again would also result in memory leaks.\n // Note: We have experimented with using `FinalizationRegisty` to clear the interval when the client is garbage\n // collected, but it did not work, because the cleanup function never got called.\n public startClientReportTracking(): void {\n const clientOptions = this.getOptions();\n if (clientOptions.sendClientReports) {\n this._clientReportOnExitFlushListener = () => {\n this._flushOutcomes();\n };\n\n this._clientReportInterval = setInterval(() => {\n DEBUG_BUILD && debug.log('Flushing client reports based on interval.');\n this._flushOutcomes();\n }, clientOptions.clientReportFlushInterval ?? DEFAULT_CLIENT_REPORT_FLUSH_INTERVAL_MS)\n // Unref is critical for not preventing the process from exiting because the interval is active.\n .unref();\n\n process.on('beforeExit', this._clientReportOnExitFlushListener);\n }\n }\n\n /** @inheritDoc */\n protected _setupIntegrations(): void {\n // Clear AI provider skip registrations before setting up integrations\n // This ensures a clean state between different client initializations\n // (e.g., when LangChain skips OpenAI in one client, but a subsequent client uses OpenAI standalone)\n _INTERNAL_clearAiProviderSkips();\n super._setupIntegrations();\n }\n}\n"],"names":["ServerRuntimeClient","applySdkMetadata","debug","isMainThread","threadId","_INTERNAL_flushLogsBuffer","_INTERNAL_setDeferSegmentSpanCapture","registerPrepareSpanScope","setOpenTelemetryContextAsyncContextStrategy","setAsyncLocalStorageAsyncContextStrategy","SDK_VERSION","trace","DEBUG_BUILD","_INTERNAL_clearAiProviderSkips"],"mappings":"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"}
|
package/build/cjs/sdk/index.js
CHANGED
|
@@ -3,7 +3,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
3
3
|
const core = require('@sentry/core');
|
|
4
4
|
const node_worker_threads = require('node:worker_threads');
|
|
5
5
|
const serverUtils = require('@sentry/server-utils');
|
|
6
|
-
const register = require('@sentry/server-
|
|
6
|
+
const register = require('@sentry/server-runtime-injection/register');
|
|
7
7
|
const debugBuild = require('../debug-build.js');
|
|
8
8
|
const childProcess = require('../integrations/childProcess.js');
|
|
9
9
|
const console$1 = require('../integrations/console.js');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../../src/sdk/index.ts"],"sourcesContent":["import type { Integration, Options } from '@sentry/core';\nimport {\n applySdkMetadata,\n consoleSandbox,\n conversationIdIntegration,\n debug,\n envToBool,\n eventFiltersIntegration,\n functionToStringIntegration,\n getCurrentScope,\n getIntegrationsToSetup,\n hasSpansEnabled,\n linkedErrorsIntegration,\n propagationContextFromHeaders,\n requestDataIntegration,\n stackParserFromStackParserOptions,\n} from '@sentry/core';\nimport { isMainThread, parentPort } from 'node:worker_threads';\nimport { detectOrchestrionSetup, getErrorIntegrations, getTracingIntegrations } from '@sentry/server-utils';\nimport { registerDiagnosticsChannelInjection } from '@sentry/server-utils/orchestrion/register';\nimport { DEBUG_BUILD } from '../debug-build';\nimport { childProcessIntegration } from '../integrations/childProcess';\nimport { consoleIntegration } from '../integrations/console';\nimport { nodeContextIntegration } from '../integrations/context';\nimport { contextLinesIntegration } from '../integrations/contextlines';\nimport { httpIntegration } from '../integrations/http';\nimport { localVariablesIntegration } from '../integrations/local-variables';\nimport { modulesIntegration } from '../integrations/modules';\nimport { nativeNodeFetchIntegration } from '../integrations/node-fetch';\nimport { onUncaughtExceptionIntegration } from '../integrations/onuncaughtexception';\nimport { onUnhandledRejectionIntegration } from '../integrations/onunhandledrejection';\nimport { processSessionIntegration } from '../integrations/processSession';\nimport { INTEGRATION_NAME as SPOTLIGHT_INTEGRATION_NAME, spotlightIntegration } from '../integrations/spotlight';\nimport { systemErrorIntegration } from '../integrations/systemError';\nimport { workerThreadsIntegration } from '../integrations/workerThreads';\nimport { makeNodeTransport } from '../transports';\nimport type { NodeClientOptions, NodeOptions } from '../types';\nimport { getEntryPointType } from '../utils/entry-point';\nimport { getSpotlightConfig } from '../utils/spotlight';\nimport { defaultStackParser, getSentryRelease } from './api';\nimport { NodeClient } from './client';\nimport { initOpenTelemetry } from './initOtel';\n\n// Treeshakable guard to remove all code related to runtime diagnostics-channel injection. Set to\n// `false` at build time by the Sentry bundler plugins' `bundleSizeOptimizations.excludeChannelInjection`.\ndeclare const __SENTRY_CHANNEL_INJECTION__: boolean | undefined;\n\n/**\n * Get the base default integrations shared by all Node SDK default-integration sets.\n */\nfunction getBaseDefaultIntegrations(): Integration[] {\n return [\n // Common\n eventFiltersIntegration(),\n functionToStringIntegration(),\n linkedErrorsIntegration(),\n requestDataIntegration(),\n systemErrorIntegration(),\n conversationIdIntegration(),\n // Native Wrappers\n consoleIntegration(),\n httpIntegration(),\n nativeNodeFetchIntegration(),\n // Global Handlers\n onUncaughtExceptionIntegration(),\n onUnhandledRejectionIntegration(),\n // Event Info\n contextLinesIntegration(),\n localVariablesIntegration(),\n nodeContextIntegration(),\n childProcessIntegration(),\n workerThreadsIntegration(),\n processSessionIntegration(),\n modulesIntegration(),\n // Framework-level integrations\n ...getErrorIntegrations(),\n ];\n}\n\n/**\n * Get default integrations, excluding performance.\n */\nexport function getDefaultIntegrationsWithoutPerformance(): Integration[] {\n return getBaseDefaultIntegrations();\n}\n\n/** Get the default integrations for the Node SDK. */\nexport function getDefaultIntegrations(options: Options): Integration[] {\n return [\n ...getDefaultIntegrationsWithoutPerformance(),\n // We only add tracing-only integrations if tracing is enabled\n ...(hasSpansEnabled(options) ? getTracingIntegrations() : []),\n ];\n}\n\n/**\n * Initialize Sentry for Node.\n */\nexport function init(options: NodeOptions | undefined = {}): NodeClient | undefined {\n return _init(options, getDefaultIntegrations);\n}\n\n/**\n * Initialize Sentry for Node, without any integrations added by default.\n */\nexport function initWithoutDefaultIntegrations(options: NodeOptions | undefined = {}): NodeClient | undefined {\n return _init(options, () => []);\n}\n\n/**\n * Internal initialization function.\n */\nfunction _init(\n options: NodeOptions | undefined = {},\n getDefaultIntegrationsImpl: (options: Options) => Integration[],\n): NodeClient | undefined {\n // Node re-runs `--require` preloads (though not `--import` ones) on the module loader thread it\n // spawns for `Module.register()`, which `init()` itself triggers (channel injection, the ESM\n // loader hook). So a `--require`d instrument file re-enters `init()` there, on a thread that\n // never runs app code. It is recognizable as the only thread without a `parentPort`:\n // user-created workers always have one and are legitimately instrumented.\n if (!isMainThread && !parentPort) {\n return undefined;\n }\n\n if (getEntryPointType() === 'require') {\n consoleSandbox(() => {\n // eslint-disable-next-line no-console\n console.warn(\n '[Sentry] Initializing the SDK via the Node `--require` flag is no longer supported, because Node re-runs `--require` preloads on its module loader thread. Use `--import` instead: `node --import ./instrument.js app.js`',\n );\n });\n }\n\n applySdkMetadata(options, 'node');\n\n // Enable debug logging before channel-injection registration below, so its failure modes (e.g. no\n // available Node hook API, dep-resolution errors) actually surface. `getClientOptions` resolves\n // `debug` the same way for the client; resolving it here as well keeps the two in agreement.\n if (envToBool(options.debug ?? process.env.SENTRY_DEBUG)) {\n if (DEBUG_BUILD) {\n debug.enable();\n } else {\n // use `console.warn` rather than `debug.warn` since non-debug bundles have all `debug.x` statements stripped\n consoleSandbox(() => {\n // eslint-disable-next-line no-console\n console.warn('[Sentry] Cannot initialize SDK with `debug` option using a non-debug bundle.');\n });\n }\n }\n\n // Resolve the tracing-affecting options (e.g. `SENTRY_TRACES_SAMPLE_RATE`) up front so that\n // default-integration selection sees the final values. Without this, enabling tracing purely via\n // env would leave `hasSpansEnabled` false at this point and skip the performance integrations.\n // `getClientOptions` resolves the remaining options later.\n const optionsWithResolvedTracing = {\n ...options,\n tracesSampleRate: getTracesSampleRate(options.tracesSampleRate),\n };\n\n // Install the channel-based (orchestrion diagnostics-channel) instrumentation hooks by default,\n // independent of tracing — the channel integrations also capture errors, not just spans. Opt out at\n // runtime with `enableRuntimeChannelInjection: false`, or at build time via the bundler plugins'\n // `bundleSizeOptimizations.excludeChannelInjection` (which tree-shakes this whole block away).\n // Install as early as possible, before the app imports its instrumented modules.\n if (\n (typeof __SENTRY_CHANNEL_INJECTION__ === 'undefined' || __SENTRY_CHANNEL_INJECTION__) &&\n options.enableRuntimeChannelInjection !== false\n ) {\n registerDiagnosticsChannelInjection();\n }\n\n // Only use Node SDK defaults if none provided.\n const defaultIntegrations = options.defaultIntegrations ?? getDefaultIntegrationsImpl(optionsWithResolvedTracing);\n\n const clientOptions = getClientOptions({ ...options, defaultIntegrations }, getDefaultIntegrationsImpl);\n\n const scope = getCurrentScope();\n scope.update(clientOptions.initialScope);\n\n if (clientOptions.spotlight && !clientOptions.integrations.some(({ name }) => name === SPOTLIGHT_INTEGRATION_NAME)) {\n clientOptions.integrations.push(\n spotlightIntegration({\n sidecarUrl: typeof clientOptions.spotlight === 'string' ? clientOptions.spotlight : undefined,\n }),\n );\n }\n\n const client = new NodeClient(clientOptions);\n // The client is on the current scope, from where it generally is inherited\n getCurrentScope().setClient(client);\n\n client.init();\n\n /*! rollup-include-cjs-only */\n debug.log(`SDK initialized from CommonJS`);\n /*! rollup-include-cjs-only-end */\n /*! rollup-include-esm-only */\n debug.log(`SDK initialized from ESM`);\n /*! rollup-include-esm-only-end */\n\n client.startClientReportTracking();\n\n updateScopeFromEnvVariables();\n\n // Ensure we flush events when vercel functions are ended\n // See: https://vercel.com/docs/functions/functions-api-reference#sigterm-signal\n if (process.env.VERCEL) {\n process.on('SIGTERM', async () => {\n // We have 500ms for processing here, so we try to make sure to have enough time to send the events\n await client.flush(200);\n });\n }\n\n // Add Node SDK specific OpenTelemetry setup. `setupEventContextTrace` reads the active span from the\n // OpenTelemetry context, so it only belongs here: without a Sentry tracer provider a foreign OTel\n // span could otherwise override the Sentry trace on error events.\n if (clientOptions.enableOpenTelemetrySetup) {\n initOpenTelemetry(client);\n }\n\n // Warn about missing or doubled channel injection. Runs after the client\n // is created so the debug logger is enabled and the warning is emitted.\n detectOrchestrionSetup();\n\n return client;\n}\n\nfunction getClientOptions(\n options: NodeOptions,\n getDefaultIntegrationsImpl: (options: Options) => Integration[],\n): NodeClientOptions {\n const release = getRelease(options.release);\n\n const spotlight = getSpotlightConfig(options.spotlight);\n\n const tracesSampleRate = getTracesSampleRate(options.tracesSampleRate);\n const traceLifecycle = getTraceLifecycle(options.traceLifecycle);\n\n const mergedOptions = {\n ...options,\n dsn: options.dsn ?? process.env.SENTRY_DSN,\n environment: options.environment ?? process.env.SENTRY_ENVIRONMENT,\n sendClientReports: options.sendClientReports ?? true,\n transport: options.transport ?? makeNodeTransport,\n stackParser: stackParserFromStackParserOptions(options.stackParser || defaultStackParser),\n release,\n tracesSampleRate,\n spotlight,\n traceLifecycle,\n // Most Node-based SDKs default to running without a Sentry OpenTelemetry tracer provider. SDKs\n // that need OTel spans surfaced in Sentry (nextjs, sveltekit) opt back in by passing `true`.\n enableOpenTelemetrySetup: options.enableOpenTelemetrySetup ?? false,\n debug: envToBool(options.debug ?? process.env.SENTRY_DEBUG),\n };\n\n const integrations = options.integrations;\n const defaultIntegrations = options.defaultIntegrations ?? getDefaultIntegrationsImpl(mergedOptions);\n\n const resolvedIntegrations = getIntegrationsToSetup({\n defaultIntegrations,\n integrations,\n });\n\n return {\n ...mergedOptions,\n integrations: resolvedIntegrations,\n };\n}\n\nfunction getRelease(release: NodeOptions['release']): string | undefined {\n if (release !== undefined) {\n return release;\n }\n\n const detectedRelease = getSentryRelease();\n if (detectedRelease !== undefined) {\n return detectedRelease;\n }\n\n return undefined;\n}\n\nfunction getTracesSampleRate(tracesSampleRate: NodeOptions['tracesSampleRate']): number | undefined {\n if (tracesSampleRate !== undefined) {\n return tracesSampleRate;\n }\n\n const sampleRateFromEnv = process.env.SENTRY_TRACES_SAMPLE_RATE;\n if (!sampleRateFromEnv) {\n return undefined;\n }\n\n const parsed = parseFloat(sampleRateFromEnv);\n return isFinite(parsed) ? parsed : undefined;\n}\n\nfunction getTraceLifecycle(traceLifecycle: NodeOptions['traceLifecycle']): 'stream' | 'static' {\n if (traceLifecycle !== undefined) {\n return traceLifecycle;\n }\n\n const lifecycleFromEnv = process.env.SENTRY_TRACE_LIFECYCLE;\n\n if (lifecycleFromEnv === 'stream' || lifecycleFromEnv === 'static') {\n return lifecycleFromEnv;\n }\n\n return 'stream';\n}\n\n/**\n * Update scope and propagation context based on environmental variables.\n *\n * See https://github.com/getsentry/rfcs/blob/main/text/0071-continue-trace-over-process-boundaries.md\n * for more details.\n */\nfunction updateScopeFromEnvVariables(): void {\n if (envToBool(process.env.SENTRY_USE_ENVIRONMENT) !== false) {\n const sentryTraceEnv = process.env.SENTRY_TRACE;\n const baggageEnv = process.env.SENTRY_BAGGAGE;\n const propagationContext = propagationContextFromHeaders(sentryTraceEnv, baggageEnv);\n getCurrentScope().setPropagationContext(propagationContext);\n }\n}\n"],"names":["eventFiltersIntegration","functionToStringIntegration","linkedErrorsIntegration","requestDataIntegration","systemErrorIntegration","conversationIdIntegration","consoleIntegration","httpIntegration","nativeNodeFetchIntegration","onUncaughtExceptionIntegration","onUnhandledRejectionIntegration","contextLinesIntegration","localVariablesIntegration","nodeContextIntegration","childProcessIntegration","workerThreadsIntegration","processSessionIntegration","modulesIntegration","getErrorIntegrations","hasSpansEnabled","getTracingIntegrations","isMainThread","parentPort","getEntryPointType","consoleSandbox","applySdkMetadata","envToBool","DEBUG_BUILD","debug","registerDiagnosticsChannelInjection","getCurrentScope","SPOTLIGHT_INTEGRATION_NAME","spotlightIntegration","client","NodeClient","initOpenTelemetry","detectOrchestrionSetup","getSpotlightConfig","makeNodeTransport","stackParserFromStackParserOptions","defaultStackParser","getSentryRelease","propagationContextFromHeaders"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../../src/sdk/index.ts"],"sourcesContent":["import type { Integration, Options } from '@sentry/core';\nimport {\n applySdkMetadata,\n consoleSandbox,\n conversationIdIntegration,\n debug,\n envToBool,\n eventFiltersIntegration,\n functionToStringIntegration,\n getCurrentScope,\n getIntegrationsToSetup,\n hasSpansEnabled,\n linkedErrorsIntegration,\n propagationContextFromHeaders,\n requestDataIntegration,\n stackParserFromStackParserOptions,\n} from '@sentry/core';\nimport { isMainThread, parentPort } from 'node:worker_threads';\nimport { detectOrchestrionSetup, getErrorIntegrations, getTracingIntegrations } from '@sentry/server-utils';\nimport { registerDiagnosticsChannelInjection } from '@sentry/server-runtime-injection/register';\nimport { DEBUG_BUILD } from '../debug-build';\nimport { childProcessIntegration } from '../integrations/childProcess';\nimport { consoleIntegration } from '../integrations/console';\nimport { nodeContextIntegration } from '../integrations/context';\nimport { contextLinesIntegration } from '../integrations/contextlines';\nimport { httpIntegration } from '../integrations/http';\nimport { localVariablesIntegration } from '../integrations/local-variables';\nimport { modulesIntegration } from '../integrations/modules';\nimport { nativeNodeFetchIntegration } from '../integrations/node-fetch';\nimport { onUncaughtExceptionIntegration } from '../integrations/onuncaughtexception';\nimport { onUnhandledRejectionIntegration } from '../integrations/onunhandledrejection';\nimport { processSessionIntegration } from '../integrations/processSession';\nimport { INTEGRATION_NAME as SPOTLIGHT_INTEGRATION_NAME, spotlightIntegration } from '../integrations/spotlight';\nimport { systemErrorIntegration } from '../integrations/systemError';\nimport { workerThreadsIntegration } from '../integrations/workerThreads';\nimport { makeNodeTransport } from '../transports';\nimport type { NodeClientOptions, NodeOptions } from '../types';\nimport { getEntryPointType } from '../utils/entry-point';\nimport { getSpotlightConfig } from '../utils/spotlight';\nimport { defaultStackParser, getSentryRelease } from './api';\nimport { NodeClient } from './client';\nimport { initOpenTelemetry } from './initOtel';\n\n// Treeshakable guard to remove all code related to runtime diagnostics-channel injection. Set to\n// `false` at build time by the Sentry bundler plugins' `bundleSizeOptimizations.excludeChannelInjection`.\ndeclare const __SENTRY_CHANNEL_INJECTION__: boolean | undefined;\n\n/**\n * Get the base default integrations shared by all Node SDK default-integration sets.\n */\nfunction getBaseDefaultIntegrations(): Integration[] {\n return [\n // Common\n eventFiltersIntegration(),\n functionToStringIntegration(),\n linkedErrorsIntegration(),\n requestDataIntegration(),\n systemErrorIntegration(),\n conversationIdIntegration(),\n // Native Wrappers\n consoleIntegration(),\n httpIntegration(),\n nativeNodeFetchIntegration(),\n // Global Handlers\n onUncaughtExceptionIntegration(),\n onUnhandledRejectionIntegration(),\n // Event Info\n contextLinesIntegration(),\n localVariablesIntegration(),\n nodeContextIntegration(),\n childProcessIntegration(),\n workerThreadsIntegration(),\n processSessionIntegration(),\n modulesIntegration(),\n // Framework-level integrations\n ...getErrorIntegrations(),\n ];\n}\n\n/**\n * Get default integrations, excluding performance.\n */\nexport function getDefaultIntegrationsWithoutPerformance(): Integration[] {\n return getBaseDefaultIntegrations();\n}\n\n/** Get the default integrations for the Node SDK. */\nexport function getDefaultIntegrations(options: Options): Integration[] {\n return [\n ...getDefaultIntegrationsWithoutPerformance(),\n // We only add tracing-only integrations if tracing is enabled\n ...(hasSpansEnabled(options) ? getTracingIntegrations() : []),\n ];\n}\n\n/**\n * Initialize Sentry for Node.\n */\nexport function init(options: NodeOptions | undefined = {}): NodeClient | undefined {\n return _init(options, getDefaultIntegrations);\n}\n\n/**\n * Initialize Sentry for Node, without any integrations added by default.\n */\nexport function initWithoutDefaultIntegrations(options: NodeOptions | undefined = {}): NodeClient | undefined {\n return _init(options, () => []);\n}\n\n/**\n * Internal initialization function.\n */\nfunction _init(\n options: NodeOptions | undefined = {},\n getDefaultIntegrationsImpl: (options: Options) => Integration[],\n): NodeClient | undefined {\n // Node re-runs `--require` preloads (though not `--import` ones) on the module loader thread it\n // spawns for `Module.register()`, which `init()` itself triggers (channel injection, the ESM\n // loader hook). So a `--require`d instrument file re-enters `init()` there, on a thread that\n // never runs app code. It is recognizable as the only thread without a `parentPort`:\n // user-created workers always have one and are legitimately instrumented.\n if (!isMainThread && !parentPort) {\n return undefined;\n }\n\n if (getEntryPointType() === 'require') {\n consoleSandbox(() => {\n // eslint-disable-next-line no-console\n console.warn(\n '[Sentry] Initializing the SDK via the Node `--require` flag is no longer supported, because Node re-runs `--require` preloads on its module loader thread. Use `--import` instead: `node --import ./instrument.js app.js`',\n );\n });\n }\n\n applySdkMetadata(options, 'node');\n\n // Enable debug logging before channel-injection registration below, so its failure modes (e.g. no\n // available Node hook API, dep-resolution errors) actually surface. `getClientOptions` resolves\n // `debug` the same way for the client; resolving it here as well keeps the two in agreement.\n if (envToBool(options.debug ?? process.env.SENTRY_DEBUG)) {\n if (DEBUG_BUILD) {\n debug.enable();\n } else {\n // use `console.warn` rather than `debug.warn` since non-debug bundles have all `debug.x` statements stripped\n consoleSandbox(() => {\n // eslint-disable-next-line no-console\n console.warn('[Sentry] Cannot initialize SDK with `debug` option using a non-debug bundle.');\n });\n }\n }\n\n // Resolve the tracing-affecting options (e.g. `SENTRY_TRACES_SAMPLE_RATE`) up front so that\n // default-integration selection sees the final values. Without this, enabling tracing purely via\n // env would leave `hasSpansEnabled` false at this point and skip the performance integrations.\n // `getClientOptions` resolves the remaining options later.\n const optionsWithResolvedTracing = {\n ...options,\n tracesSampleRate: getTracesSampleRate(options.tracesSampleRate),\n };\n\n // Install the channel-based (orchestrion diagnostics-channel) instrumentation hooks by default,\n // independent of tracing — the channel integrations also capture errors, not just spans. Opt out at\n // runtime with `enableRuntimeChannelInjection: false`, or at build time via the bundler plugins'\n // `bundleSizeOptimizations.excludeChannelInjection` (which tree-shakes this whole block away).\n // Install as early as possible, before the app imports its instrumented modules.\n if (\n (typeof __SENTRY_CHANNEL_INJECTION__ === 'undefined' || __SENTRY_CHANNEL_INJECTION__) &&\n options.enableRuntimeChannelInjection !== false\n ) {\n registerDiagnosticsChannelInjection();\n }\n\n // Only use Node SDK defaults if none provided.\n const defaultIntegrations = options.defaultIntegrations ?? getDefaultIntegrationsImpl(optionsWithResolvedTracing);\n\n const clientOptions = getClientOptions({ ...options, defaultIntegrations }, getDefaultIntegrationsImpl);\n\n const scope = getCurrentScope();\n scope.update(clientOptions.initialScope);\n\n if (clientOptions.spotlight && !clientOptions.integrations.some(({ name }) => name === SPOTLIGHT_INTEGRATION_NAME)) {\n clientOptions.integrations.push(\n spotlightIntegration({\n sidecarUrl: typeof clientOptions.spotlight === 'string' ? clientOptions.spotlight : undefined,\n }),\n );\n }\n\n const client = new NodeClient(clientOptions);\n // The client is on the current scope, from where it generally is inherited\n getCurrentScope().setClient(client);\n\n client.init();\n\n /*! rollup-include-cjs-only */\n debug.log(`SDK initialized from CommonJS`);\n /*! rollup-include-cjs-only-end */\n /*! rollup-include-esm-only */\n debug.log(`SDK initialized from ESM`);\n /*! rollup-include-esm-only-end */\n\n client.startClientReportTracking();\n\n updateScopeFromEnvVariables();\n\n // Ensure we flush events when vercel functions are ended\n // See: https://vercel.com/docs/functions/functions-api-reference#sigterm-signal\n if (process.env.VERCEL) {\n process.on('SIGTERM', async () => {\n // We have 500ms for processing here, so we try to make sure to have enough time to send the events\n await client.flush(200);\n });\n }\n\n // Add Node SDK specific OpenTelemetry setup. `setupEventContextTrace` reads the active span from the\n // OpenTelemetry context, so it only belongs here: without a Sentry tracer provider a foreign OTel\n // span could otherwise override the Sentry trace on error events.\n if (clientOptions.enableOpenTelemetrySetup) {\n initOpenTelemetry(client);\n }\n\n // Warn about missing or doubled channel injection. Runs after the client\n // is created so the debug logger is enabled and the warning is emitted.\n detectOrchestrionSetup();\n\n return client;\n}\n\nfunction getClientOptions(\n options: NodeOptions,\n getDefaultIntegrationsImpl: (options: Options) => Integration[],\n): NodeClientOptions {\n const release = getRelease(options.release);\n\n const spotlight = getSpotlightConfig(options.spotlight);\n\n const tracesSampleRate = getTracesSampleRate(options.tracesSampleRate);\n const traceLifecycle = getTraceLifecycle(options.traceLifecycle);\n\n const mergedOptions = {\n ...options,\n dsn: options.dsn ?? process.env.SENTRY_DSN,\n environment: options.environment ?? process.env.SENTRY_ENVIRONMENT,\n sendClientReports: options.sendClientReports ?? true,\n transport: options.transport ?? makeNodeTransport,\n stackParser: stackParserFromStackParserOptions(options.stackParser || defaultStackParser),\n release,\n tracesSampleRate,\n spotlight,\n traceLifecycle,\n // Most Node-based SDKs default to running without a Sentry OpenTelemetry tracer provider. SDKs\n // that need OTel spans surfaced in Sentry (nextjs, sveltekit) opt back in by passing `true`.\n enableOpenTelemetrySetup: options.enableOpenTelemetrySetup ?? false,\n debug: envToBool(options.debug ?? process.env.SENTRY_DEBUG),\n };\n\n const integrations = options.integrations;\n const defaultIntegrations = options.defaultIntegrations ?? getDefaultIntegrationsImpl(mergedOptions);\n\n const resolvedIntegrations = getIntegrationsToSetup({\n defaultIntegrations,\n integrations,\n });\n\n return {\n ...mergedOptions,\n integrations: resolvedIntegrations,\n };\n}\n\nfunction getRelease(release: NodeOptions['release']): string | undefined {\n if (release !== undefined) {\n return release;\n }\n\n const detectedRelease = getSentryRelease();\n if (detectedRelease !== undefined) {\n return detectedRelease;\n }\n\n return undefined;\n}\n\nfunction getTracesSampleRate(tracesSampleRate: NodeOptions['tracesSampleRate']): number | undefined {\n if (tracesSampleRate !== undefined) {\n return tracesSampleRate;\n }\n\n const sampleRateFromEnv = process.env.SENTRY_TRACES_SAMPLE_RATE;\n if (!sampleRateFromEnv) {\n return undefined;\n }\n\n const parsed = parseFloat(sampleRateFromEnv);\n return isFinite(parsed) ? parsed : undefined;\n}\n\nfunction getTraceLifecycle(traceLifecycle: NodeOptions['traceLifecycle']): 'stream' | 'static' {\n if (traceLifecycle !== undefined) {\n return traceLifecycle;\n }\n\n const lifecycleFromEnv = process.env.SENTRY_TRACE_LIFECYCLE;\n\n if (lifecycleFromEnv === 'stream' || lifecycleFromEnv === 'static') {\n return lifecycleFromEnv;\n }\n\n return 'stream';\n}\n\n/**\n * Update scope and propagation context based on environmental variables.\n *\n * See https://github.com/getsentry/rfcs/blob/main/text/0071-continue-trace-over-process-boundaries.md\n * for more details.\n */\nfunction updateScopeFromEnvVariables(): void {\n if (envToBool(process.env.SENTRY_USE_ENVIRONMENT) !== false) {\n const sentryTraceEnv = process.env.SENTRY_TRACE;\n const baggageEnv = process.env.SENTRY_BAGGAGE;\n const propagationContext = propagationContextFromHeaders(sentryTraceEnv, baggageEnv);\n getCurrentScope().setPropagationContext(propagationContext);\n }\n}\n"],"names":["eventFiltersIntegration","functionToStringIntegration","linkedErrorsIntegration","requestDataIntegration","systemErrorIntegration","conversationIdIntegration","consoleIntegration","httpIntegration","nativeNodeFetchIntegration","onUncaughtExceptionIntegration","onUnhandledRejectionIntegration","contextLinesIntegration","localVariablesIntegration","nodeContextIntegration","childProcessIntegration","workerThreadsIntegration","processSessionIntegration","modulesIntegration","getErrorIntegrations","hasSpansEnabled","getTracingIntegrations","isMainThread","parentPort","getEntryPointType","consoleSandbox","applySdkMetadata","envToBool","DEBUG_BUILD","debug","registerDiagnosticsChannelInjection","getCurrentScope","SPOTLIGHT_INTEGRATION_NAME","spotlightIntegration","client","NodeClient","initOpenTelemetry","detectOrchestrionSetup","getSpotlightConfig","makeNodeTransport","stackParserFromStackParserOptions","defaultStackParser","getSentryRelease","propagationContextFromHeaders"],"mappings":"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"}
|
package/build/esm/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export { httpIntegration } from './integrations/http/index.js';
|
|
2
2
|
export { nativeNodeFetchIntegration } from './integrations/node-fetch/index.js';
|
|
3
3
|
export { fsIntegration } from './integrations/fs/index.js';
|
|
4
|
-
export { amqplibIntegration, anthropicAIIntegration, createLangChainCallbackHandler, dataloaderIntegration, expressErrorHandler, expressIntegration, fastifyIntegration, firebaseIntegration, genericPoolIntegration, getOtlpTracesEndpoint, googleGenAIIntegration, graphqlIntegration, hapiIntegration, instrumentAnthropicAiClient, instrumentGoogleGenAIClient, instrumentLangChainEmbeddings, instrumentOpenAiClient, instrumentStateGraph, instrumentStateGraphCompile, kafkaIntegration, knexIntegration, koaIntegration, langChainIntegration, langGraphIntegration, lruMemoizerIntegration, mongoIntegration, mongooseIntegration, mysql2Integration, mysqlIntegration, openAIIntegration,
|
|
4
|
+
export { amqplibIntegration, anthropicAIIntegration, createLangChainCallbackHandler, dataloaderIntegration, expressErrorHandler, expressIntegration, fastifyIntegration, firebaseIntegration, genericPoolIntegration, getOtlpTracesEndpoint, googleGenAIIntegration, graphqlIntegration, hapiIntegration, instrumentAnthropicAiClient, instrumentGoogleGenAIClient, instrumentLangChainEmbeddings, instrumentOpenAiClient, instrumentStateGraph, instrumentStateGraphCompile, kafkaIntegration, knexIntegration, koaIntegration, langChainIntegration, langGraphIntegration, lruMemoizerIntegration, mongoIntegration, mongooseIntegration, mysql2Integration, mysqlIntegration, openAIIntegration, openTelemetryIntegration, postgresIntegration, postgresJsIntegration, prismaIntegration, redisIntegration, setupExpressErrorHandler, setupFastifyErrorHandler, tediousIntegration, vercelAIIntegration } from '@sentry/server-utils';
|
|
5
5
|
export { setupHapiErrorHandler } from './integrations/tracing/hapi.js';
|
|
6
6
|
export { setupKoaErrorHandler } from './integrations/tracing/koa.js';
|
|
7
7
|
export { buildLaunchDarklyFlagUsedHandlerShim as buildLaunchDarklyFlagUsedHandler, launchDarklyIntegrationShim as launchDarklyIntegration } from './integrations/featureFlagShims/launchDarkly.js';
|
|
@@ -13,7 +13,8 @@ export { getDefaultIntegrations, getDefaultIntegrationsWithoutPerformance, init,
|
|
|
13
13
|
export { initOpenTelemetry } from './sdk/initOtel.js';
|
|
14
14
|
export { getAutoPerformanceIntegrations } from './integrations/tracing/index.js';
|
|
15
15
|
export { setOpenTelemetryContextAsyncContextStrategy } from '@sentry/opentelemetry';
|
|
16
|
-
export { SDK_VERSION, SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE, Scope, addBreadcrumb, addEventProcessor, addIntegration, bindScopeToEmitter, captureCheckIn, captureConsoleIntegration, captureEvent, captureException, captureFeedback, captureMessage, captureSession, close, consoleLoggingIntegration, continueTrace, createConsolaReporter, createTransport, dedupeIntegration, endSession, eventFiltersIntegration, extraErrorDataIntegration, featureFlagsIntegration, flush, functionToStringIntegration, getActiveSpan, getClient, getCurrentScope, getGlobalScope, getIsolationScope, getRootSpan, getSpanDescendants, getSpanStatusFromHttpCode, getTraceData, getTraceMetaTags, httpHeadersToSpanAttributes, instrumentSupabaseClient, isEnabled, isInitialized, lastEventId, linkedErrorsIntegration, metrics, parameterize, profiler, requestDataIntegration, rewriteFramesIntegration, setAttribute, setAttributes, setContext, setConversationId, setCurrentClient, setExtra, setExtras, setHttpStatus, setMeasurement, setTag, setTags, setUser, spanStreamingIntegration, spanToBaggageHeader, spanToJSON, spanToStaticSpanJSON, spanToTraceHeader, startInactiveSpan, startNewTrace, startSession, startSpan, startSpanManual, supabaseIntegration, suppressTracing,
|
|
16
|
+
export { SDK_VERSION, SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE, Scope, addBreadcrumb, addEventProcessor, addIntegration, bindScopeToEmitter, captureCheckIn, captureConsoleIntegration, captureEvent, captureException, captureFeedback, captureMessage, captureSession, close, consoleLoggingIntegration, continueTrace, createConsolaReporter, createTransport, dedupeIntegration, endSession, eventFiltersIntegration, extraErrorDataIntegration, featureFlagsIntegration, flush, functionToStringIntegration, getActiveSpan, getClient, getCurrentScope, getGlobalScope, getIsolationScope, getRootSpan, getSpanDescendants, getSpanStatusFromHttpCode, getTraceData, getTraceMetaTags, httpHeadersToSpanAttributes, instrumentSupabaseClient, isEnabled, isInitialized, lastEventId, linkedErrorsIntegration, metrics, parameterize, profiler, requestDataIntegration, rewriteFramesIntegration, setAttribute, setAttributes, setContext, setConversationId, setCurrentClient, setExtra, setExtras, setHttpStatus, setMeasurement, setTag, setTags, setUser, spanStreamingIntegration, spanToBaggageHeader, spanToJSON, spanToStaticSpanJSON, spanToTraceHeader, startInactiveSpan, startNewTrace, startSession, startSpan, startSpanManual, supabaseIntegration, suppressTracing, updateSpanName, winterCGHeadersToDict, withActiveSpan, withIsolationScope, withMonitor, withScope, withStaticSpan, withStreamedSpan, zodErrorsIntegration } from '@sentry/core';
|
|
17
|
+
export { trpcMiddleware, wrapMcpServerWithSentry } from '@sentry/core/server';
|
|
17
18
|
import * as exports$1 from './logs/exports.js';
|
|
18
19
|
export { exports$1 as logger };
|
|
19
20
|
export { childProcessIntegration } from './integrations/childProcess.js';
|
package/build/esm/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -4,7 +4,7 @@ import { defineIntegration, debug, getCombinedScopeData, getIsolationScope, getC
|
|
|
4
4
|
import { isDebuggerEnabled } from '../../utils/debug.js';
|
|
5
5
|
|
|
6
6
|
const { isPromise } = types;
|
|
7
|
-
const base64WorkerScript = "LyohIEBzZW50cnkvbm9kZSAxMS4wLjAtYWxwaGEuMiAoYTcxYTk0MykgfCBodHRwczovL2dpdGh1Yi5jb20vZ2V0c2VudHJ5L3NlbnRyeS1qYXZhc2NyaXB0ICovCmltcG9ydHtTZXNzaW9uIGFzIHR9ZnJvbSJub2RlOmluc3BlY3RvciI7aW1wb3J0e3dvcmtlckRhdGEgYXMgZSxwYXJlbnRQb3J0IGFzIG59ZnJvbSJub2RlOndvcmtlcl90aHJlYWRzIjtpbXBvcnR7cG9zaXggYXMgcixzZXAgYXMgb31mcm9tIm5vZGU6cGF0aCI7aW1wb3J0KmFzIHMgZnJvbSJub2RlOmh0dHAiO2ltcG9ydCphcyBpIGZyb20ibm9kZTpodHRwcyI7aW1wb3J0e1JlYWRhYmxlIGFzIGN9ZnJvbSJub2RlOnN0cmVhbSI7aW1wb3J0e2NyZWF0ZUd6aXAgYXMgdX1mcm9tIm5vZGU6emxpYiI7aW1wb3J0KmFzIGEgZnJvbSJub2RlOm5ldCI7aW1wb3J0KmFzIGYgZnJvbSJub2RlOnRscyI7Y29uc3QgaD0idW5kZWZpbmVkIj09dHlwZW9mIF9fU0VOVFJZX0RFQlVHX198fF9fU0VOVFJZX0RFQlVHX18scD1nbG9iYWxUaGlzLGw9IjExLjAuMC1hbHBoYS4yIjtmdW5jdGlvbiBkKCl7cmV0dXJuIGcocCkscH1mdW5jdGlvbiBnKHQpe2NvbnN0IGU9dC5fX1NFTlRSWV9fPXQuX19TRU5UUllfX3x8e307cmV0dXJuIGUudmVyc2lvbj1lLnZlcnNpb258fGwsZVtsXT1lW2xdfHx7fX1mdW5jdGlvbiBtKHQsZSxuPXApe2NvbnN0IHI9bi5fX1NFTlRSWV9fPW4uX19TRU5UUllfX3x8e30sbz1yW2xdPXJbbF18fHt9O3JldHVybiBvW3RdfHwob1t0XT1lKCkpfWNvbnN0IHk9e307ZnVuY3Rpb24gYih0KXtpZighKCJjb25zb2xlImluIHApKXJldHVybiB0KCk7Y29uc3QgZT1wLmNvbnNvbGUsbj17fSxyPU9iamVjdC5rZXlzKHkpO3IuZm9yRWFjaCh0PT57Y29uc3Qgcj15W3RdO25bdF09ZVt0XSxlW3RdPXJ9KTt0cnl7cmV0dXJuIHQoKX1maW5hbGx5e3IuZm9yRWFjaCh0PT57ZVt0XT1uW3RdfSl9fWZ1bmN0aW9uIHYoKXtyZXR1cm4gUygpLmVuYWJsZWR9ZnVuY3Rpb24gdyh0LC4uLmUpe2gmJnYoKSYmYigoKT0+e3AuY29uc29sZVt0XShgU2VudHJ5IExvZ2dlciBbJHt0fV06YCwuLi5lKX0pfWZ1bmN0aW9uIFMoKXtyZXR1cm4gaD9tKCJsb2dnZXJTZXR0aW5ncyIsKCk9Pih7ZW5hYmxlZDohMX0pKTp7ZW5hYmxlZDohMX19Y29uc3QgXz17ZW5hYmxlOmZ1bmN0aW9uKCl7UygpLmVuYWJsZWQ9ITB9LGRpc2FibGU6ZnVuY3Rpb24oKXtTKCkuZW5hYmxlZD0hMX0saXNFbmFibGVkOnYsbG9nOmZ1bmN0aW9uKC4uLnQpe3coImxvZyIsLi4udCl9LHdhcm46ZnVuY3Rpb24oLi4udCl7dygid2FybiIsLi4udCl9LGVycm9yOmZ1bmN0aW9uKC4uLnQpe3coImVycm9yIiwuLi50KX19LCQ9L2NhcHR1cmVNZXNzYWdlfGNhcHR1cmVFeGNlcHRpb24vO2Z1bmN0aW9uIEUodCl7cmV0dXJuIHRbdC5sZW5ndGgtMV18fHt9fWNvbnN0IHg9Ijxhbm9ueW1vdXM+Ijtjb25zdCBOPU9iamVjdC5wcm90b3R5cGUudG9TdHJpbmc7ZnVuY3Rpb24gQyh0KXtyZXR1cm4gZnVuY3Rpb24odCxlKXtyZXR1cm4gTi5jYWxsKHQpPT09YFtvYmplY3QgJHtlfV1gfSh0LCJPYmplY3QiKX1mdW5jdGlvbiBqKHQpe3JldHVybiBCb29sZWFuKHQ/LnRoZW4mJiJmdW5jdGlvbiI9PXR5cGVvZiB0LnRoZW4pfWZ1bmN0aW9uIE8odCxlKXt0cnl7cmV0dXJuIHQgaW5zdGFuY2VvZiBlfWNhdGNoe3JldHVybiExfX1mdW5jdGlvbiBQKHQpe2lmKGZ1bmN0aW9uKHQpe3N3aXRjaChOLmNhbGwodCkpe2Nhc2UiW29iamVjdCBFcnJvcl0iOmNhc2UiW29iamVjdCBFeGNlcHRpb25dIjpjYXNlIltvYmplY3QgRE9NRXhjZXB0aW9uXSI6Y2FzZSJbb2JqZWN0IFdlYkFzc2VtYmx5LkV4Y2VwdGlvbl0iOnJldHVybiEwO2RlZmF1bHQ6cmV0dXJuIE8odCxFcnJvcil9fSh0KSlyZXR1cm57bWVzc2FnZTp0Lm1lc3NhZ2UsbmFtZTp0Lm5hbWUsc3RhY2s6dC5zdGFjaywuLi5BKHQpfTtpZihlPXQsInVuZGVmaW5lZCIhPXR5cGVvZiBFdmVudCYmTyhlLEV2ZW50KSl7Y29uc3R7dHlwZTplLHRhcmdldDpuLGN1cnJlbnRUYXJnZXQ6cixkZXRhaWw6b309dDtyZXR1cm57dHlwZTplLHRhcmdldDpuLGN1cnJlbnRUYXJnZXQ6ciwuLi5vP3tkZXRhaWw6b306e30sLi4uQSh0KX19dmFyIGU7cmV0dXJuIHR9ZnVuY3Rpb24gQSh0KXtyZXR1cm4ib2JqZWN0Ij09dHlwZW9mKGU9dCkmJm51bGwhPT1lP09iamVjdC5mcm9tRW50cmllcyhPYmplY3QuZW50cmllcyh0KSk6e307dmFyIGV9bGV0IFQ7ZnVuY3Rpb24gayh0KXtpZih2b2lkIDAhPT1UKXJldHVybiBUP1QodCk6dCgpO2NvbnN0IGU9U3ltYm9sLmZvcigiX19TRU5UUllfU0FGRV9SQU5ET01fSURfV1JBUFBFUl9fIiksbj1wO3JldHVybiBlIGluIG4mJiJmdW5jdGlvbiI9PXR5cGVvZiBuW2VdPyhUPW5bZV0sVCh0KSk6KFQ9bnVsbCx0KCkpfWZ1bmN0aW9uIFIoKXtyZXR1cm4gaygoKT0+TWF0aC5yYW5kb20oKSl9ZnVuY3Rpb24gSSgpe3JldHVybiBrKCgpPT5EYXRlLm5vdygpKX1jb25zdCBEPVN5bWJvbC5mb3IoInNlbnRyeS5za2lwTm9ybWFsaXphdGlvbiIpLFU9U3ltYm9sLmZvcigic2VudHJ5Lm92ZXJyaWRlTm9ybWFsaXphdGlvbkRlcHRoIik7ZnVuY3Rpb24gQih0LGU9MTAwLG49MS8wKXt0cnl7cmV0dXJuIEwoIiIsdCxlLG4pfWNhdGNoKHQpe3JldHVybntFUlJPUjpgKipub24tc2VyaWFsaXphYmxlKiogKCR7dH0pYH19fWZ1bmN0aW9uIEwodCxlLG49MS8wLHI9MS8wLG89ZnVuY3Rpb24oKXtjb25zdCB0PW5ldyBXZWFrU2V0O2Z1bmN0aW9uIGUoZSl7cmV0dXJuISF0LmhhcyhlKXx8KHQuYWRkKGUpLCExKX1mdW5jdGlvbiBuKGUpe3QuZGVsZXRlKGUpfXJldHVybltlLG5dfSgpKXtjb25zdFtzLGldPW87aWYobnVsbD09ZXx8WyJib29sZWFuIiwic3RyaW5nIl0uaW5jbHVkZXModHlwZW9mIGUpfHwibnVtYmVyIj09dHlwZW9mIGUmJk51bWJlci5pc0Zpbml0ZShlKSlyZXR1cm4gZTtjb25zdCBjPWZ1bmN0aW9uKHQsZSl7dHJ5e2lmKCJ1bmRlZmluZWQiIT10eXBlb2YgZ2xvYmFsJiZlPT09Z2xvYmFsKXJldHVybiJbR2xvYmFsXSI7aWYoIm51bWJlciI9PXR5cGVvZiBlJiYhTnVtYmVyLmlzRmluaXRlKGUpKXJldHVybmBbJHtlfV1gO2lmKCJmdW5jdGlvbiI9PXR5cGVvZiBlKXJldHVybmBbRnVuY3Rpb246ICR7ZnVuY3Rpb24odCl7dHJ5e3JldHVybiB0JiYiZnVuY3Rpb24iPT10eXBlb2YgdCYmdC5uYW1lfHx4fWNhdGNoe3JldHVybiB4fX0oZSl9XWA7aWYoInN5bWJvbCI9PXR5cGVvZiBlKXJldHVybmBbJHtTdHJpbmcoZSl9XWA7aWYoImJpZ2ludCI9PXR5cGVvZiBlKXJldHVybmBbQmlnSW50OiAke1N0cmluZyhlKX1dYDtjb25zdCB0PWZ1bmN0aW9uKHQpe2NvbnN0IGU9T2JqZWN0LmdldFByb3RvdHlwZU9mKHQpO3JldHVybiBlPy5jb25zdHJ1Y3Rvcj9lLmNvbnN0cnVjdG9yLm5hbWU6Im51bGwgcHJvdG90eXBlIn0oZSk7cmV0dXJuYFtvYmplY3QgJHt0fV1gfWNhdGNoKHQpe3JldHVybmAqKm5vbi1zZXJpYWxpemFibGUqKiAoJHt0fSlgfX0oMCxlKTtpZighYy5zdGFydHNXaXRoKCJbb2JqZWN0ICIpKXJldHVybiBjO2lmKGZ1bmN0aW9uKHQpe3JldHVybiBCb29sZWFuKHRbRF0pfShlKSlyZXR1cm4gZTtjb25zdCB1PWZ1bmN0aW9uKHQpe2NvbnN0IGU9dFtVXTtyZXR1cm4ibnVtYmVyIj09dHlwZW9mIGU/ZTp2b2lkIDB9KGUpLGE9dm9pZCAwIT09dT91Om47aWYoMD09PWEpcmV0dXJuIGMucmVwbGFjZSgib2JqZWN0ICIsIiIpO2lmKHMoZSkpcmV0dXJuIltDaXJjdWxhciB+XSI7Y29uc3QgZj1lO2lmKGYmJiJmdW5jdGlvbiI9PXR5cGVvZiBmLnRvSlNPTil0cnl7cmV0dXJuIEwoIiIsZi50b0pTT04oKSxhLTEscixvKX1jYXRjaHt9Y29uc3QgaD1BcnJheS5pc0FycmF5KGUpP1tdOnt9O2xldCBwPTA7Y29uc3QgbD1QKGUpO2Zvcihjb25zdCB0IGluIGwpe2lmKCFPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwobCx0KSljb250aW51ZTtpZihwPj1yKXtoW3RdPSJbTWF4UHJvcGVydGllcyB+XSI7YnJlYWt9Y29uc3QgZT1sW3RdO2hbdF09TCh0LGUsYS0xLHIsbykscCsrfXJldHVybiBpKGUpLGh9ZnVuY3Rpb24gTSh0LGUpe2NvbnN0IG49ZS5yZXBsYWNlKC9cXC9nLCIvIikucmVwbGFjZSgvW3xcXHt9KClbXF1eJCsqPy5dL2csIlxcJCYiKTtsZXQgcj10O3RyeXtyPWRlY29kZVVSSSh0KX1jYXRjaHt9cmV0dXJuIHIucmVwbGFjZSgvXFwvZywiLyIpLnJlcGxhY2UoL3dlYnBhY2s6XC8/L2csIiIpLnJlcGxhY2UobmV3IFJlZ0V4cChgKGZpbGU6Ly8pPy8qJHtufS8qYCwiaWciKSwiYXBwOi8vLyIpfWZ1bmN0aW9uIHoodCxlPTApe3JldHVybiJzdHJpbmciIT10eXBlb2YgdHx8MD09PWV8fHQubGVuZ3RoPD1lP3Q6YCR7dC5zbGljZSgwLGUpfS4uLmB9bGV0IEo7ZnVuY3Rpb24gVyh0PWZ1bmN0aW9uKCl7Y29uc3QgdD1wO3JldHVybiB0LmNyeXB0b3x8dC5tc0NyeXB0b30oKSl7dHJ5e2lmKHQ/LnJhbmRvbVVVSUQpcmV0dXJuIGsoKCk9PnQucmFuZG9tVVVJRCgpKS5yZXBsYWNlKC8tL2csIiIpfWNhdGNoe31yZXR1cm4gSnx8KEo9IjEwMDAwMDAwMTAwMDQwMDA4MDAwMTAwMDAwMDAwMDAwIiksSi5yZXBsYWNlKC9bMDE4XS9nLHQ9Pih0XigxNipSKCkmMTUpPj50LzQpLnRvU3RyaW5nKDE2KSl9ZnVuY3Rpb24gRigpe3JldHVybiBJKCkvMWUzfWxldCBHO2Z1bmN0aW9uIFkoKXtyZXR1cm4oRz8/KEc9ZnVuY3Rpb24oKXtjb25zdHtwZXJmb3JtYW5jZTp0fT1wO2lmKCF0Py5ub3d8fCF0LnRpbWVPcmlnaW4pcmV0dXJuIEY7Y29uc3QgZT10LnRpbWVPcmlnaW47cmV0dXJuKCk9PihlK2soKCk9PnQubm93KCkpKS8xZTN9KCkpKSgpfWZ1bmN0aW9uIEgodCl7Y29uc3QgZT1ZKCksbj17c2lkOlcoKSxpbml0OiEwLHRpbWVzdGFtcDplLHN0YXJ0ZWQ6ZSxkdXJhdGlvbjowLHN0YXR1czoib2siLGVycm9yczowLGlnbm9yZUR1cmF0aW9uOiExLHRvSlNPTjooKT0+ZnVuY3Rpb24odCl7cmV0dXJue3NpZDpgJHt0LnNpZH1gLGluaXQ6dC5pbml0LHN0YXJ0ZWQ6bmV3IERhdGUoMWUzKnQuc3RhcnRlZCkudG9JU09TdHJpbmcoKSx0aW1lc3RhbXA6bmV3IERhdGUoMWUzKnQudGltZXN0YW1wKS50b0lTT1N0cmluZygpLHN0YXR1czp0LnN0YXR1cyxlcnJvcnM6dC5lcnJvcnMsZGlkOiJudW1iZXIiPT10eXBlb2YgdC5kaWR8fCJzdHJpbmciPT10eXBlb2YgdC5kaWQ/YCR7dC5kaWR9YDp2b2lkIDAsZHVyYXRpb246dC5kdXJhdGlvbixhYm5vcm1hbF9tZWNoYW5pc206dC5hYm5vcm1hbF9tZWNoYW5pc20sYXR0cnM6e3JlbGVhc2U6dC5yZWxlYXNlLGVudmlyb25tZW50OnQuZW52aXJvbm1lbnQsaXBfYWRkcmVzczp0LmlwQWRkcmVzcyx1c2VyX2FnZW50OnQudXNlckFnZW50fX19KG4pfTtyZXR1cm4gdCYmWihuLHQpLG59ZnVuY3Rpb24gWih0LGU9e30pe2lmKGUudXNlciYmKCF0LmlwQWRkcmVzcyYmZS51c2VyLmlwX2FkZHJlc3MmJih0LmlwQWRkcmVzcz1lLnVzZXIuaXBfYWRkcmVzcyksdC5kaWR8fGUuZGlkfHwodC5kaWQ9ZS51c2VyLmlkfHxlLnVzZXIuZW1haWx8fGUudXNlci51c2VybmFtZSkpLHQudGltZXN0YW1wPWUudGltZXN0YW1wfHxZKCksZS5hYm5vcm1hbF9tZWNoYW5pc20mJih0LmFibm9ybWFsX21lY2hhbmlzbT1lLmFibm9ybWFsX21lY2hhbmlzbSksZS5pZ25vcmVEdXJhdGlvbiYmKHQuaWdub3JlRHVyYXRpb249ZS5pZ25vcmVEdXJhdGlvbiksZS5zaWQmJih0LnNpZD0zMj09PWUuc2lkLmxlbmd0aD9lLnNpZDpXKCkpLHZvaWQgMCE9PWUuaW5pdCYmKHQuaW5pdD1lLmluaXQpLCF0LmRpZCYmZS5kaWQmJih0LmRpZD1gJHtlLmRpZH1gKSwibnVtYmVyIj09dHlwZW9mIGUuc3RhcnRlZCYmKHQuc3RhcnRlZD1lLnN0YXJ0ZWQpLHQuaWdub3JlRHVyYXRpb24pdC5kdXJhdGlvbj12b2lkIDA7ZWxzZSBpZigibnVtYmVyIj09dHlwZW9mIGUuZHVyYXRpb24pdC5kdXJhdGlvbj1lLmR1cmF0aW9uO2Vsc2V7Y29uc3QgZT10LnRpbWVzdGFtcC10LnN0YXJ0ZWQ7dC5kdXJhdGlvbj1lPj0wP2U6MH1lLnJlbGVhc2UmJih0LnJlbGVhc2U9ZS5yZWxlYXNlKSxlLmVudmlyb25tZW50JiYodC5lbnZpcm9ubWVudD1lLmVudmlyb25tZW50KSwhdC5pcEFkZHJlc3MmJmUuaXBBZGRyZXNzJiYodC5pcEFkZHJlc3M9ZS5pcEFkZHJlc3MpLCF0LnVzZXJBZ2VudCYmZS51c2VyQWdlbnQmJih0LnVzZXJBZ2VudD1lLnVzZXJBZ2VudCksIm51bWJlciI9PXR5cGVvZiBlLmVycm9ycyYmKHQuZXJyb3JzPWUuZXJyb3JzKSxlLnN0YXR1cyYmKHQuc3RhdHVzPWUuc3RhdHVzKX1mdW5jdGlvbiBxKHQsZSxuPTIpe2lmKCFlfHwib2JqZWN0IiE9dHlwZW9mIGV8fG48PTApcmV0dXJuIGU7aWYodCYmMD09PU9iamVjdC5rZXlzKGUpLmxlbmd0aClyZXR1cm4gdDtjb25zdCByPXsuLi50fTtmb3IoY29uc3QgdCBpbiBlKU9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChlLHQpJiYoclt0XT1xKHJbdF0sZVt0XSxuLTEpKTtyZXR1cm4gcn1jbGFzcyBLe2NvbnN0cnVjdG9yKCl7dGhpcy50PSExLHRoaXMubz1bXSx0aGlzLmk9W10sdGhpcy51PVtdLHRoaXMuaD1bXSx0aGlzLnA9e30sdGhpcy5sPXt9LHRoaXMubT17fSx0aGlzLnY9e30sdGhpcy5TPXt9LHRoaXMuXz17fSxmdW5jdGlvbih0LGUsbil7dHJ5e09iamVjdC5kZWZpbmVQcm9wZXJ0eSh0LGUse3ZhbHVlOm4sd3JpdGFibGU6ITAsY29uZmlndXJhYmxlOiEwfSl9Y2F0Y2h7aCYmXy5sb2coYEZhaWxlZCB0byBhZGQgbm9uLWVudW1lcmFibGUgcHJvcGVydHkgIiR7U3RyaW5nKGUpfSIgdG8gb2JqZWN0YCx0KX19KHRoaXMsInJlZnMiLHt9KSx0aGlzLk49e3RyYWNlSWQ6VygpLHNhbXBsZVJhbmQ6UigpfX1jbG9uZSgpe2NvbnN0IHQ9bmV3IEs7cmV0dXJuIHQudT1bLi4udGhpcy51XSx0Lmw9ey4uLnRoaXMubH0sdC5tPXsuLi50aGlzLm19LHQudj17Li4udGhpcy52fSx0LlM9ey4uLnRoaXMuU30sdGhpcy5TLmZsYWdzJiYodC5TLmZsYWdzPXt2YWx1ZXM6Wy4uLnRoaXMuUy5mbGFncy52YWx1ZXNdfSksdC5wPXRoaXMucCx0LkM9dGhpcy5DLHQuaj10aGlzLmosdC5PPXRoaXMuTyx0LlA9dGhpcy5QLHQuaT1bLi4udGhpcy5pXSx0Lmg9Wy4uLnRoaXMuaF0sdC5fPXsuLi50aGlzLl99LHQuTj17Li4udGhpcy5OfSx0LkE9dGhpcy5BLHQuVD10aGlzLlQsdC5rPXRoaXMuayx0LnJlZnM9ey4uLnRoaXMucmVmc30sdH1zZXRDbGllbnQodCl7dGhpcy5BPXR9c2V0TGFzdEV2ZW50SWQodCl7dGhpcy5UPXR9Z2V0Q2xpZW50KCl7cmV0dXJuIHRoaXMuQX1sYXN0RXZlbnRJZCgpe3JldHVybiB0aGlzLlR9YWRkU2NvcGVMaXN0ZW5lcih0KXt0aGlzLm8ucHVzaCh0KX1hZGRFdmVudFByb2Nlc3Nvcih0KXtyZXR1cm4gdGhpcy5pLnB1c2godCksdGhpc31zZXRVc2VyKHQpe3JldHVybiB0aGlzLnA9dHx8e2VtYWlsOnZvaWQgMCxpZDp2b2lkIDAsaXBfYWRkcmVzczp2b2lkIDAsdXNlcm5hbWU6dm9pZCAwfSx0aGlzLmomJloodGhpcy5qLHt1c2VyOnR9KSx0aGlzLlIoKSx0aGlzfWdldFVzZXIoKXtyZXR1cm4gdGhpcy5wfXNldENvbnZlcnNhdGlvbklkKHQpe3JldHVybiB0aGlzLms9dHx8dm9pZCAwLHRoaXMuUigpLHRoaXN9c2V0VGFncyh0KXtyZXR1cm4gdGhpcy5sPXsuLi50aGlzLmwsLi4udH0sdGhpcy5SKCksdGhpc31zZXRUYWcodCxlKXtyZXR1cm4gdGhpcy5zZXRUYWdzKHtbdF06ZX0pfXNldEF0dHJpYnV0ZXModCl7cmV0dXJuIHRoaXMubT17Li4udGhpcy5tLC4uLnR9LHRoaXMuUigpLHRoaXN9c2V0QXR0cmlidXRlKHQsZSl7cmV0dXJuIHRoaXMuc2V0QXR0cmlidXRlcyh7W3RdOmV9KX1yZW1vdmVBdHRyaWJ1dGUodCl7cmV0dXJuIHQgaW4gdGhpcy5tJiYoZGVsZXRlIHRoaXMubVt0XSx0aGlzLlIoKSksdGhpc31zZXRFeHRyYXModCl7cmV0dXJuIHRoaXMudj17Li4udGhpcy52LC4uLnR9LHRoaXMuUigpLHRoaXN9c2V0RXh0cmEodCxlKXtyZXR1cm4gdGhpcy52PXsuLi50aGlzLnYsW3RdOmV9LHRoaXMuUigpLHRoaXN9c2V0RmluZ2VycHJpbnQodCl7cmV0dXJuIHRoaXMuUD10LHRoaXMuUigpLHRoaXN9c2V0TGV2ZWwodCl7cmV0dXJuIHRoaXMuQz10LHRoaXMuUigpLHRoaXN9c2V0VHJhbnNhY3Rpb25OYW1lKHQpe3JldHVybiB0aGlzLk89dCx0aGlzLlIoKSx0aGlzfXNldENvbnRleHQodCxlKXtyZXR1cm4gbnVsbD09PWU/ZGVsZXRlIHRoaXMuU1t0XTp0aGlzLlNbdF09ZSx0aGlzLlIoKSx0aGlzfXNldFNlc3Npb24odCl7cmV0dXJuIHQ/dGhpcy5qPXQ6ZGVsZXRlIHRoaXMuaix0aGlzLlIoKSx0aGlzfWdldFNlc3Npb24oKXtyZXR1cm4gdGhpcy5qfXVwZGF0ZSh0KXtpZighdClyZXR1cm4gdGhpcztjb25zdCBlPSJmdW5jdGlvbiI9PXR5cGVvZiB0P3QodGhpcyk6dCxuPWUgaW5zdGFuY2VvZiBLP2UuZ2V0U2NvcGVEYXRhKCk6QyhlKT90OnZvaWQgMCx7dGFnczpyLGF0dHJpYnV0ZXM6byxleHRyYTpzLHVzZXI6aSxjb250ZXh0czpjLGxldmVsOnUsZmluZ2VycHJpbnQ6YT1bXSxwcm9wYWdhdGlvbkNvbnRleHQ6Zixjb252ZXJzYXRpb25JZDpofT1ufHx7fTtyZXR1cm4gdGhpcy5sPXsuLi50aGlzLmwsLi4ucn0sdGhpcy5tPXsuLi50aGlzLm0sLi4ub30sdGhpcy52PXsuLi50aGlzLnYsLi4uc30sdGhpcy5TPXsuLi50aGlzLlMsLi4uY30saSYmT2JqZWN0LmtleXMoaSkubGVuZ3RoJiYodGhpcy5wPWkpLHUmJih0aGlzLkM9dSksYS5sZW5ndGgmJih0aGlzLlA9YSksZiYmKHRoaXMuTj1mKSxoJiYodGhpcy5rPWgpLHRoaXN9YWRkQnJlYWRjcnVtYih0LGUpe2NvbnN0IG49Im51bWJlciI9PXR5cGVvZiBlP2U6MTAwO2lmKG48PTApcmV0dXJuIHRoaXM7Y29uc3Qgcj17dGltZXN0YW1wOkYoKSwuLi50LG1lc3NhZ2U6dC5tZXNzYWdlP3oodC5tZXNzYWdlLDIwNDgpOnQubWVzc2FnZX07cmV0dXJuIHRoaXMudS5wdXNoKHIpLHRoaXMudS5sZW5ndGg+biYmKHRoaXMudT10aGlzLnUuc2xpY2UoLW4pLHRoaXMuQT8ucmVjb3JkRHJvcHBlZEV2ZW50KCJidWZmZXJfb3ZlcmZsb3ciLCJsb2dfaXRlbSIpKSx0aGlzLlIoKSx0aGlzfWdldExhc3RCcmVhZGNydW1iKCl7cmV0dXJuIHRoaXMudVt0aGlzLnUubGVuZ3RoLTFdfWNsZWFyQnJlYWRjcnVtYnMoKXtyZXR1cm4gdGhpcy51PVtdLHRoaXMuUigpLHRoaXN9YWRkQXR0YWNobWVudCh0KXtyZXR1cm4gdGhpcy5oLnB1c2godCksdGhpc31jbGVhckF0dGFjaG1lbnRzKCl7cmV0dXJuIHRoaXMuaD1bXSx0aGlzfWdldFNjb3BlRGF0YSgpe3JldHVybnticmVhZGNydW1iczp0aGlzLnUsYXR0YWNobWVudHM6dGhpcy5oLGNvbnRleHRzOnRoaXMuUyx0YWdzOnRoaXMubCxhdHRyaWJ1dGVzOnRoaXMubSxleHRyYTp0aGlzLnYsdXNlcjp0aGlzLnAsbGV2ZWw6dGhpcy5DLGZpbmdlcnByaW50OnRoaXMuUHx8W10sZXZlbnRQcm9jZXNzb3JzOnRoaXMuaSxwcm9wYWdhdGlvbkNvbnRleHQ6dGhpcy5OLHNka1Byb2Nlc3NpbmdNZXRhZGF0YTp0aGlzLl8sdHJhbnNhY3Rpb25OYW1lOnRoaXMuTyxjb252ZXJzYXRpb25JZDp0aGlzLmt9fXNldFNES1Byb2Nlc3NpbmdNZXRhZGF0YSh0KXtyZXR1cm4gdGhpcy5fPXEodGhpcy5fLHQsMiksdGhpc31zZXRQcm9wYWdhdGlvbkNvbnRleHQodCl7cmV0dXJuIHRoaXMuTj10LHRoaXN9Z2V0UHJvcGFnYXRpb25Db250ZXh0KCl7cmV0dXJuIHRoaXMuTn1jYXB0dXJlRXhjZXB0aW9uKHQsZSl7Y29uc3Qgbj1lPy5ldmVudF9pZHx8VygpO2lmKCF0aGlzLkEpcmV0dXJuIGgmJl8ud2FybigiTm8gY2xpZW50IGNvbmZpZ3VyZWQgb24gc2NvcGUgLSB3aWxsIG5vdCBjYXB0dXJlIGV4Y2VwdGlvbiEiKSxuO2NvbnN0IHI9bmV3IEVycm9yKCJTZW50cnkgc3ludGhldGljRXhjZXB0aW9uIik7cmV0dXJuIHRoaXMuQS5jYXB0dXJlRXhjZXB0aW9uKHQse29yaWdpbmFsRXhjZXB0aW9uOnQsc3ludGhldGljRXhjZXB0aW9uOnIsLi4uZSxldmVudF9pZDpufSx0aGlzKSxufWNhcHR1cmVNZXNzYWdlKHQsZSxuKXtjb25zdCByPW4/LmV2ZW50X2lkfHxXKCk7aWYoIXRoaXMuQSlyZXR1cm4gaCYmXy53YXJuKCJObyBjbGllbnQgY29uZmlndXJlZCBvbiBzY29wZSAtIHdpbGwgbm90IGNhcHR1cmUgbWVzc2FnZSEiKSxyO2NvbnN0IG89bj8uc3ludGhldGljRXhjZXB0aW9uPz9uZXcgRXJyb3IodCk7cmV0dXJuIHRoaXMuQS5jYXB0dXJlTWVzc2FnZSh0LGUse29yaWdpbmFsRXhjZXB0aW9uOnQsc3ludGhldGljRXhjZXB0aW9uOm8sLi4ubixldmVudF9pZDpyfSx0aGlzKSxyfWNhcHR1cmVFdmVudCh0LGUpe2NvbnN0IG49dC5ldmVudF9pZHx8ZT8uZXZlbnRfaWR8fFcoKTtyZXR1cm4gdGhpcy5BPyh0aGlzLkEuY2FwdHVyZUV2ZW50KHQsey4uLmUsZXZlbnRfaWQ6bn0sdGhpcyksbik6KGgmJl8ud2FybigiTm8gY2xpZW50IGNvbmZpZ3VyZWQgb24gc2NvcGUgLSB3aWxsIG5vdCBjYXB0dXJlIGV2ZW50ISIpLG4pfVIoKXt0aGlzLnR8fCh0aGlzLnQ9ITAsdGhpcy5vLmZvckVhY2godD0+e3QodGhpcyl9KSx0aGlzLnQ9ITEpfX1jb25zdCBWPSJfX1NFTlRSWV9TVVBQUkVTU19UUkFDSU5HX18iLFE9dD0+dCBpbnN0YW5jZW9mIFByb21pc2UmJiF0W1hdLFg9U3ltYm9sKCJjaGFpbmVkIFByb21pc2VMaWtlIiksdHQ9KHQsZSk9PntpZighZSlyZXR1cm4gdDtsZXQgbj0hMTtmb3IoY29uc3QgciBpbiB0KXtpZihyIGluIGUpY29udGludWU7bj0hMDtjb25zdCBvPXRbcl07ImZ1bmN0aW9uIj09dHlwZW9mIG8/T2JqZWN0LmRlZmluZVByb3BlcnR5KGUscix7dmFsdWU6KC4uLmUpPT5vLmFwcGx5KHQsZSksZW51bWVyYWJsZTohMCxjb25maWd1cmFibGU6ITAsd3JpdGFibGU6ITB9KTplW3JdPW99cmV0dXJuIG4mJk9iamVjdC5hc3NpZ24oZSx7W1hdOiEwfSksZX07Y2xhc3MgZXR7Y29uc3RydWN0b3IodCxlKXtsZXQgbixyO249dHx8bmV3IEsscj1lfHxuZXcgSyx0aGlzLkk9W3tzY29wZTpufV0sdGhpcy5EPXJ9d2l0aFNjb3BlKHQpe2NvbnN0IGU9dGhpcy5VKCk7bGV0IG47dHJ5e249dChlKX1jYXRjaCh0KXt0aHJvdyB0aGlzLkIoKSx0fXJldHVybiBqKG4pPygodCxlLG4pPT57Y29uc3Qgcj10LnRoZW4odD0+KGUodCksdCksdD0+e3Rocm93IG4odCksdH0pO3JldHVybiBRKHIpJiZRKHQpP3I6dHQodCxyKX0pKG4sKCk9PnRoaXMuQigpLCgpPT50aGlzLkIoKSk6KHRoaXMuQigpLG4pfWdldENsaWVudCgpe3JldHVybiB0aGlzLmdldFN0YWNrVG9wKCkuY2xpZW50fWdldFNjb3BlKCl7cmV0dXJuIHRoaXMuZ2V0U3RhY2tUb3AoKS5zY29wZX1nZXRJc29sYXRpb25TY29wZSgpe3JldHVybiB0aGlzLkR9Z2V0U3RhY2tUb3AoKXtyZXR1cm4gdGhpcy5JW3RoaXMuSS5sZW5ndGgtMV19VSgpe2NvbnN0IHQ9dGhpcy5nZXRTY29wZSgpLmNsb25lKCk7cmV0dXJuIHRoaXMuSS5wdXNoKHtjbGllbnQ6dGhpcy5nZXRDbGllbnQoKSxzY29wZTp0fSksdH1CKCl7cmV0dXJuISh0aGlzLkkubGVuZ3RoPD0xKSYmISF0aGlzLkkucG9wKCl9fWZ1bmN0aW9uIG50KCl7Y29uc3QgdD1nKGQoKSk7cmV0dXJuIHQuc3RhY2s9dC5zdGFja3x8bmV3IGV0KG0oImRlZmF1bHRDdXJyZW50U2NvcGUiLCgpPT5uZXcgSyksbSgiZGVmYXVsdElzb2xhdGlvblNjb3BlIiwoKT0+bmV3IEspKX1mdW5jdGlvbiBydCh0KXtyZXR1cm4gbnQoKS53aXRoU2NvcGUodCl9ZnVuY3Rpb24gb3QodCxlKXtjb25zdCBuPW50KCk7cmV0dXJuIG4ud2l0aFNjb3BlKCgpPT4obi5nZXRTdGFja1RvcCgpLnNjb3BlPXQsZSh0KSkpfWZ1bmN0aW9uIHN0KHQpe3JldHVybiBudCgpLndpdGhTY29wZSgoKT0+dChudCgpLmdldElzb2xhdGlvblNjb3BlKCkpKX1mdW5jdGlvbiBpdCh0KXtyZXR1cm4gcnQoZT0+e2Uuc2V0U0RLUHJvY2Vzc2luZ01ldGFkYXRhKHtbVl06ITB9KTtjb25zdCBuPXQoKTtyZXR1cm4gZS5zZXRTREtQcm9jZXNzaW5nTWV0YWRhdGEoe1tWXTp2b2lkIDB9KSxufSl9ZnVuY3Rpb24gY3QodCl7Y29uc3QgZT1nKHQpO3JldHVybiBlLmFjcz9lLmFjczp7c3VwcHJlc3NUcmFjaW5nOml0LHdpdGhJc29sYXRpb25TY29wZTpzdCx3aXRoU2NvcGU6cnQsd2l0aFNldFNjb3BlOm90LHdpdGhTZXRJc29sYXRpb25TY29wZToodCxlKT0+c3QoZSksZ2V0Q3VycmVudFNjb3BlOigpPT5udCgpLmdldFNjb3BlKCksZ2V0SXNvbGF0aW9uU2NvcGU6KCk9Pm50KCkuZ2V0SXNvbGF0aW9uU2NvcGUoKX19ZnVuY3Rpb24gdXQodCxlPSExKXtjb25zdHtob3N0Om4scGF0aDpyLHBhc3M6byxwb3J0OnMscHJvamVjdElkOmkscHJvdG9jb2w6YyxwdWJsaWNLZXk6dX09dDtyZXR1cm5gJHtjfTovLyR7dX0ke2UmJm8/YDoke299YDoiIn1AJHtufSR7cz9gOiR7c31gOiIifS8ke3I/YCR7cn0vYDpyfSR7aX1gfWZ1bmN0aW9uIGF0KHQsZSl7Y29uc3R7ZmluZ2VycHJpbnQ6bixicmVhZGNydW1iczpyLHNka1Byb2Nlc3NpbmdNZXRhZGF0YTpvfT1lOyFmdW5jdGlvbih0LGUpe2NvbnN0e2V4dHJhOm4sdGFnczpyLHVzZXI6byxjb250ZXh0czpzLGxldmVsOmksdHJhbnNhY3Rpb25OYW1lOmN9PWU7T2JqZWN0LmtleXMobikubGVuZ3RoJiYodC5leHRyYT17Li4ubiwuLi50LmV4dHJhfSk7T2JqZWN0LmtleXMocikubGVuZ3RoJiYodC50YWdzPXsuLi5yLC4uLnQudGFnc30pO09iamVjdC5rZXlzKG8pLmxlbmd0aCYmKHQudXNlcj17Li4ubywuLi50LnVzZXJ9KTtPYmplY3Qua2V5cyhzKS5sZW5ndGgmJih0LmNvbnRleHRzPXsuLi5zLC4uLnQuY29udGV4dHN9KTtpJiYodC5sZXZlbD1pKTtjJiYidHJhbnNhY3Rpb24iIT09dC50eXBlJiYodC50cmFuc2FjdGlvbj1jKX0odCxlKSxmdW5jdGlvbih0LGUpe3QuZmluZ2VycHJpbnQ9dC5maW5nZXJwcmludD9BcnJheS5pc0FycmF5KHQuZmluZ2VycHJpbnQpP3QuZmluZ2VycHJpbnQ6W3QuZmluZ2VycHJpbnRdOltdLGUmJih0LmZpbmdlcnByaW50PXQuZmluZ2VycHJpbnQuY29uY2F0KGUpKTt0LmZpbmdlcnByaW50Lmxlbmd0aHx8ZGVsZXRlIHQuZmluZ2VycHJpbnR9KHQsbiksZnVuY3Rpb24odCxlKXtjb25zdCBuPVsuLi50LmJyZWFkY3J1bWJzfHxbXSwuLi5lXTt0LmJyZWFkY3J1bWJzPW4ubGVuZ3RoP246dm9pZCAwfSh0LHIpLGZ1bmN0aW9uKHQsZSl7dC5zZGtQcm9jZXNzaW5nTWV0YWRhdGE9ey4uLnQuc2RrUHJvY2Vzc2luZ01ldGFkYXRhLC4uLmV9fSh0LG8pfWZ1bmN0aW9uIGZ0KHQsZT1bXSl7cmV0dXJuW3QsZV19ZnVuY3Rpb24gaHQodCxlKXtjb25zdCBuPXRbMV07Zm9yKGNvbnN0IHQgb2Ygbil7aWYoZSh0LHRbMF0udHlwZSkpcmV0dXJuITB9cmV0dXJuITF9ZnVuY3Rpb24gcHQodCl7Y29uc3QgZT1nKHApO3JldHVybiBlLmVuY29kZVBvbHlmaWxsP2UuZW5jb2RlUG9seWZpbGwodCk6KG5ldyBUZXh0RW5jb2RlcikuZW5jb2RlKHQpfWZ1bmN0aW9uIGx0KHQpe2NvbnN0W2Usbl09dDtsZXQgcj1KU09OLnN0cmluZ2lmeShlKTtmdW5jdGlvbiBvKHQpeyJzdHJpbmciPT10eXBlb2Ygcj9yPSJzdHJpbmciPT10eXBlb2YgdD9yK3Q6W3B0KHIpLHRdOnIucHVzaCgic3RyaW5nIj09dHlwZW9mIHQ/cHQodCk6dCl9Zm9yKGNvbnN0IHQgb2Ygbil7Y29uc3RbZSxuXT10O2lmKG8oYFxuJHtKU09OLnN0cmluZ2lmeShlKX1cbmApLCJzdHJpbmciPT10eXBlb2Ygbnx8biBpbnN0YW5jZW9mIFVpbnQ4QXJyYXkpbyhuKTtlbHNle2xldCB0O3RyeXt0PUpTT04uc3RyaW5naWZ5KG4pfWNhdGNoe3Q9SlNPTi5zdHJpbmdpZnkoQihuKSl9byh0KX19cmV0dXJuInN0cmluZyI9PXR5cGVvZiByP3I6ZnVuY3Rpb24odCl7Y29uc3QgZT10LnJlZHVjZSgodCxlKT0+dCtlLmxlbmd0aCwwKSxuPW5ldyBVaW50OEFycmF5KGUpO2xldCByPTA7Zm9yKGNvbnN0IGUgb2YgdCluLnNldChlLHIpLHIrPWUubGVuZ3RoO3JldHVybiBufShyKX1jb25zdCBkdD17c2Vzc2lvbnM6InNlc3Npb24iLGV2ZW50OiJlcnJvciIsY2xpZW50X3JlcG9ydDoiaW50ZXJuYWwiLHVzZXJfcmVwb3J0OiJkZWZhdWx0Iixwcm9maWxlX2NodW5rOiJwcm9maWxlIixyZXBsYXlfZXZlbnQ6InJlcGxheSIscmVwbGF5X3JlY29yZGluZzoicmVwbGF5IixjaGVja19pbjoibW9uaXRvciIscmF3X3NlY3VyaXR5OiJzZWN1cml0eSIsbG9nOiJsb2dfaXRlbSIsdHJhY2VfbWV0cmljOiJtZXRyaWMifTtmdW5jdGlvbiBndCh0KXtyZXR1cm4gZnVuY3Rpb24odCl7cmV0dXJuIHQgaW4gZHR9KHQpP2R0W3RdOnR9ZnVuY3Rpb24gbXQodCl7aWYoIXQ/LnNkaylyZXR1cm47Y29uc3R7bmFtZTplLHZlcnNpb246bn09dC5zZGs7cmV0dXJue25hbWU6ZSx2ZXJzaW9uOm59fWZ1bmN0aW9uIHl0KHQpe2NvbnN0IGU9Y3QoZCgpKTtyZXR1cm4gZS5zdXBwcmVzc1RyYWNpbmc/ZS5zdXBwcmVzc1RyYWNpbmcodCk6ZnVuY3Rpb24oLi4udCl7Y29uc3QgZT1jdChkKCkpO2lmKDI9PT10Lmxlbmd0aCl7Y29uc3RbbixyXT10O3JldHVybiBuP2Uud2l0aFNldFNjb3BlKG4scik6ZS53aXRoU2NvcGUocil9cmV0dXJuIGUud2l0aFNjb3BlKHRbMF0pfShlPT4oZS5zZXRTREtQcm9jZXNzaW5nTWV0YWRhdGEoe1tWXTohMH0pLHQoKSkpfWZ1bmN0aW9uIGJ0KHQsZSxuLHIpe2NvbnN0IG89bXQobikscz10LnR5cGUmJiJyZXBsYXlfZXZlbnQiIT09dC50eXBlP3QudHlwZToiZXZlbnQiOyFmdW5jdGlvbih0LGUpe2lmKCFlKXJldHVybiB0O2NvbnN0IG49dC5zZGt8fHt9O3Quc2RrPXsuLi5uLG5hbWU6bi5uYW1lfHxlLm5hbWUsdmVyc2lvbjpuLnZlcnNpb258fGUudmVyc2lvbixpbnRlZ3JhdGlvbnM6Wy4uLnQuc2RrPy5pbnRlZ3JhdGlvbnN8fFtdLC4uLmUuaW50ZWdyYXRpb25zfHxbXV0scGFja2FnZXM6Wy4uLnQuc2RrPy5wYWNrYWdlc3x8W10sLi4uZS5wYWNrYWdlc3x8W11dLHNldHRpbmdzOnQuc2RrPy5zZXR0aW5nc3x8ZS5zZXR0aW5ncz97Li4udC5zZGs/LnNldHRpbmdzLC4uLmUuc2V0dGluZ3N9OnZvaWQgMH19KHQsbj8uc2RrKTtjb25zdCBpPWZ1bmN0aW9uKHQsZSxuLHIpe2NvbnN0IG89dC5zZGtQcm9jZXNzaW5nTWV0YWRhdGE/LmR5bmFtaWNTYW1wbGluZ0NvbnRleHQ7cmV0dXJue2V2ZW50X2lkOnQuZXZlbnRfaWQsc2VudF9hdDpuZXcgRGF0ZShJKCkpLnRvSVNPU3RyaW5nKCksLi4uZSYme3NkazplfSwuLi4hIW4mJnImJntkc246dXQocil9LC4uLm8mJnt0cmFjZTpvfX19KHQsbyxyLGUpO2RlbGV0ZSB0LnNka1Byb2Nlc3NpbmdNZXRhZGF0YTtyZXR1cm4gZnQoaSxbW3t0eXBlOnN9LHRdXSl9Y2xhc3MgdnR7Y29uc3RydWN0b3IodCl7dGhpcy5MPTAsdGhpcy5NPVtdLHRoaXMuSih0KX10aGVuKHQsZSl7cmV0dXJuIG5ldyB2dCgobixyKT0+e3RoaXMuTS5wdXNoKFshMSxlPT57aWYodCl0cnl7bih0KGUpKX1jYXRjaCh0KXtyKHQpfWVsc2UgbihlKX0sdD0+e2lmKGUpdHJ5e24oZSh0KSl9Y2F0Y2godCl7cih0KX1lbHNlIHIodCl9XSksdGhpcy5XKCl9KX1jYXRjaCh0KXtyZXR1cm4gdGhpcy50aGVuKHQ9PnQsdCl9ZmluYWxseSh0KXtyZXR1cm4gbmV3IHZ0KChlLG4pPT57bGV0IHIsbztyZXR1cm4gdGhpcy50aGVuKGU9PntvPSExLHI9ZSx0JiZ0KCl9LGU9PntvPSEwLHI9ZSx0JiZ0KCl9KS50aGVuKCgpPT57bz9uKHIpOmUocil9KX0pfVcoKXtpZigwPT09dGhpcy5MKXJldHVybjtjb25zdCB0PXRoaXMuTS5zbGljZSgpO3RoaXMuTT1bXSx0LmZvckVhY2godD0+e3RbMF18fCgxPT09dGhpcy5MJiZ0WzFdKHRoaXMuRiksMj09PXRoaXMuTCYmdFsyXSh0aGlzLkYpLHRbMF09ITApfSl9Sih0KXtjb25zdCBlPSh0LGUpPT57MD09PXRoaXMuTCYmKGooZSk/ZS50aGVuKG4scik6KHRoaXMuTD10LHRoaXMuRj1lLHRoaXMuVygpKSl9LG49dD0+e2UoMSx0KX0scj10PT57ZSgyLHQpfTt0cnl7dChuLHIpfWNhdGNoKHQpe3IodCl9fX1jb25zdCB3dD1TeW1ib2wuZm9yKCJTZW50cnlCdWZmZXJGdWxsRXJyb3IiKTtmdW5jdGlvbiBTdCh0PTEwMCl7Y29uc3QgZT1uZXcgU2V0O2Z1bmN0aW9uIG4odCl7ZS5kZWxldGUodCl9cmV0dXJue2dldCAkKCl7cmV0dXJuIEFycmF5LmZyb20oZSl9LGFkZDpmdW5jdGlvbihyKXtpZighKGUuc2l6ZTx0KSlyZXR1cm4gbz13dCxuZXcgdnQoKHQsZSk9PntlKG8pfSk7dmFyIG87Y29uc3Qgcz1yKCk7cmV0dXJuIGUuYWRkKHMpLHMudGhlbigoKT0+bihzKSwoKT0+bihzKSksc30sZHJhaW46ZnVuY3Rpb24odCl7aWYoIWUuc2l6ZSlyZXR1cm4gbj0hMCxuZXcgdnQodD0+e3Qobil9KTt2YXIgbjtjb25zdCByPVByb21pc2UuYWxsU2V0dGxlZChBcnJheS5mcm9tKGUpKS50aGVuKCgpPT4hMCk7aWYoIXQpcmV0dXJuIHI7Y29uc3Qgbz1bcixuZXcgUHJvbWlzZShlPT57cmV0dXJuIm9iamVjdCI9PXR5cGVvZihuPXNldFRpbWVvdXQoKCk9PmUoITEpLHQpKSYmImZ1bmN0aW9uIj09dHlwZW9mIG4udW5yZWYmJm4udW5yZWYoKSxuO3ZhciBufSldO3JldHVybiBQcm9taXNlLnJhY2Uobyl9fX1mdW5jdGlvbiBfdCh0LHtzdGF0dXNDb2RlOmUsaGVhZGVyczpufSxyPUkoKSl7Y29uc3Qgbz17Li4udH0scz1uPy5bIngtc2VudHJ5LXJhdGUtbGltaXRzIl0saT1uPy5bInJldHJ5LWFmdGVyIl07aWYocylmb3IoY29uc3QgdCBvZiBzLnRyaW0oKS5zcGxpdCgiLCIpKXtjb25zdFtlLG4sLCxzXT10LnNwbGl0KCI6Iiw1KSxpPXBhcnNlSW50KGUsMTApLGM9MWUzKihpc05hTihpKT82MDppKTtpZihuKWZvcihjb25zdCB0IG9mIG4uc3BsaXQoIjsiKSkibWV0cmljX2J1Y2tldCI9PT10JiZzJiYhcy5zcGxpdCgiOyIpLmluY2x1ZGVzKCJjdXN0b20iKXx8KG9bdF09citjKTtlbHNlIG8uYWxsPXIrY31lbHNlIGk/by5hbGw9citmdW5jdGlvbih0LGU9SSgpKXtjb25zdCBuPXBhcnNlSW50KGAke3R9YCwxMCk7aWYoIWlzTmFOKG4pKXJldHVybiAxZTMqbjtjb25zdCByPURhdGUucGFyc2UoYCR7dH1gKTtyZXR1cm4gaXNOYU4ocik/NmU0OnItZX0oaSxyKTo0Mjk9PT1lJiYoby5hbGw9cis2ZTQpO3JldHVybiBvfWZ1bmN0aW9uICR0KHQsZSxuPVN0KHQuYnVmZmVyU2l6ZXx8NjQpKXtsZXQgcj17fTtyZXR1cm57c2VuZDpmdW5jdGlvbih0KXtjb25zdCBvPVtdO2lmKGh0KHQsKHQsZSk9Pntjb25zdCBuPWd0KGUpOyhmdW5jdGlvbih0LGUsbj1JKCkpe3JldHVybiBmdW5jdGlvbih0LGUpe3JldHVybiB0W2VdfHx0LmFsbHx8MH0odCxlKT5ufSkocixuKXx8by5wdXNoKHQpfSksMD09PW8ubGVuZ3RoKXJldHVybiBQcm9taXNlLnJlc29sdmUoe30pO2NvbnN0IHM9ZnQodFswXSxvKSxpPXQ9PnshZnVuY3Rpb24odCxlKXtyZXR1cm4gaHQodCwodCxuKT0+ZS5pbmNsdWRlcyhuKSl9KHMsWyJjbGllbnRfcmVwb3J0Il0pP2h0KHMsKHQsZSk9Pnt9KTpoJiZfLndhcm4oYERyb3BwaW5nIGNsaWVudCByZXBvcnQuIFdpbGwgbm90IHNlbmQgb3V0Y29tZXMgKHJlYXNvbjogJHt0fSkuYCl9O3JldHVybiBuLmFkZCgoKT0+ZSh7Ym9keTpsdChzKX0pLnRoZW4odD0+NDEzPT09dC5zdGF0dXNDb2RlPyhoJiZfLmVycm9yKCJTZW50cnkgcmVzcG9uZGVkIHdpdGggc3RhdHVzIGNvZGUgNDEzLiBFbnZlbG9wZSB3YXMgZGlzY2FyZGVkIGR1ZSB0byBleGNlZWRpbmcgc2l6ZSBsaW1pdHMuIiksaSgic2VuZF9lcnJvciIpLHQpOihoJiZ2b2lkIDAhPT10LnN0YXR1c0NvZGUmJih0LnN0YXR1c0NvZGU8MjAwfHx0LnN0YXR1c0NvZGU+PTMwMCkmJl8ud2FybihgU2VudHJ5IHJlc3BvbmRlZCB3aXRoIHN0YXR1cyBjb2RlICR7dC5zdGF0dXNDb2RlfSB0byBzZW50IGV2ZW50LmApLHI9X3Qocix0KSx0KSx0PT57dGhyb3cgaSgibmV0d29ya19lcnJvciIpLGgmJl8uZXJyb3IoIkVuY291bnRlcmVkIGVycm9yIHJ1bm5pbmcgdHJhbnNwb3J0IHJlcXVlc3Q6Iix0KSx0fSkpLnRoZW4odD0+dCx0PT57aWYodD09PXd0KXJldHVybiBoJiZfLmVycm9yKCJTa2lwcGVkIHNlbmRpbmcgZXZlbnQgYmVjYXVzZSBidWZmZXIgaXMgZnVsbC4iKSxpKCJxdWV1ZV9vdmVyZmxvdyIpLFByb21pc2UucmVzb2x2ZSh7fSk7dGhyb3cgdH0pfSxmbHVzaDp0PT5uLmRyYWluKHQpfX1jb25zdCBFdD0vXihcUys6XFx8XC8/KShbXHNcU10qPykoKD86XC57MSwyfXxbXi9cXF0rP3wpKFwuW14uL1xcXSp8KSkoPzpbL1xcXSopJC87ZnVuY3Rpb24geHQodCl7Y29uc3QgZT1mdW5jdGlvbih0KXtjb25zdCBlPXQubGVuZ3RoPjEwMjQ/YDx0cnVuY2F0ZWQ+JHt0LnNsaWNlKC0xMDI0KX1gOnQsbj1FdC5leGVjKGUpO3JldHVybiBuP24uc2xpY2UoMSk6W119KHQpLG49ZVswXXx8IiI7bGV0IHI9ZVsxXTtyZXR1cm4gbnx8cj8ociYmKHI9ci5zbGljZSgwLHIubGVuZ3RoLTEpKSxuK3IpOiIuIn1mdW5jdGlvbiBOdCh0LGU9ITEpe3JldHVybiEoZXx8dCYmIXQuc3RhcnRzV2l0aCgiLyIpJiYhdC5tYXRjaCgvXltBLVpdOi8pJiYhdC5zdGFydHNXaXRoKCIuIikmJiF0Lm1hdGNoKC9eW2EtekEtWl0oW2EtekEtWjAtOS5cLStdKSo6XC9cLy8pKSYmdm9pZCAwIT09dCYmIXQuaW5jbHVkZXMoIm5vZGVfbW9kdWxlcy8iKX12YXIgQ3Q7Y29uc3QganQ9U3ltYm9sKCJBZ2VudEJhc2VJbnRlcm5hbFN0YXRlIik7Y2xhc3MgT3QgZXh0ZW5kcyhDdD1zLkFnZW50LEN0KXtjb25zdHJ1Y3Rvcih0KXtzdXBlcih0KSx0aGlzW2p0XT17fX1pc1NlY3VyZUVuZHBvaW50KHQpe2lmKHQpe2lmKCJib29sZWFuIj09dHlwZW9mIHQuc2VjdXJlRW5kcG9pbnQpcmV0dXJuIHQuc2VjdXJlRW5kcG9pbnQ7aWYoInN0cmluZyI9PXR5cGVvZiB0LnByb3RvY29sKXJldHVybiJodHRwczoiPT09dC5wcm90b2NvbH1jb25zdHtzdGFjazplfT1uZXcgRXJyb3I7cmV0dXJuInN0cmluZyI9PXR5cGVvZiBlJiZlLnNwbGl0KCJcbiIpLnNvbWUodD0+LTEhPT10LmluZGV4T2YoIihodHRwcy5qczoiKXx8LTEhPT10LmluZGV4T2YoIm5vZGU6aHR0cHM6IikpfWNyZWF0ZVNvY2tldCh0LGUsbil7Y29uc3Qgcj17Li4uZSxzZWN1cmVFbmRwb2ludDp0aGlzLmlzU2VjdXJlRW5kcG9pbnQoZSl9O1Byb21pc2UucmVzb2x2ZSgpLnRoZW4oKCk9PnRoaXMuY29ubmVjdCh0LHIpKS50aGVuKG89PntpZihvIGluc3RhbmNlb2Ygcy5BZ2VudClyZXR1cm4gby5hZGRSZXF1ZXN0KHQscik7dGhpc1tqdF0uY3VycmVudFNvY2tldD1vLHN1cGVyLmNyZWF0ZVNvY2tldCh0LGUsbil9LG4pfWNyZWF0ZUNvbm5lY3Rpb24oKXtjb25zdCB0PXRoaXNbanRdLmN1cnJlbnRTb2NrZXQ7aWYodGhpc1tqdF0uY3VycmVudFNvY2tldD12b2lkIDAsIXQpdGhyb3cgbmV3IEVycm9yKCJObyBzb2NrZXQgd2FzIHJldHVybmVkIGluIHRoZSBgY29ubmVjdCgpYCBmdW5jdGlvbiIpO3JldHVybiB0fWdldCBkZWZhdWx0UG9ydCgpe3JldHVybiB0aGlzW2p0XS5kZWZhdWx0UG9ydD8/KCJodHRwczoiPT09dGhpcy5wcm90b2NvbD80NDM6ODApfXNldCBkZWZhdWx0UG9ydCh0KXt0aGlzW2p0XSYmKHRoaXNbanRdLmRlZmF1bHRQb3J0PXQpfWdldCBwcm90b2NvbCgpe3JldHVybiB0aGlzW2p0XS5wcm90b2NvbD8/KHRoaXMuaXNTZWN1cmVFbmRwb2ludCgpPyJodHRwczoiOiJodHRwOiIpfXNldCBwcm90b2NvbCh0KXt0aGlzW2p0XSYmKHRoaXNbanRdLnByb3RvY29sPXQpfX1mdW5jdGlvbiBQdCguLi50KXtfLmxvZygiW2h0dHBzLXByb3h5LWFnZW50OnBhcnNlLXByb3h5LXJlc3BvbnNlXSIsLi4udCl9ZnVuY3Rpb24gQXQodCl7cmV0dXJuIG5ldyBQcm9taXNlKChlLG4pPT57bGV0IHI9MDtjb25zdCBvPVtdO2Z1bmN0aW9uIHMoKXtjb25zdCBjPXQucmVhZCgpO2M/ZnVuY3Rpb24oYyl7by5wdXNoKGMpLHIrPWMubGVuZ3RoO2NvbnN0IHU9QnVmZmVyLmNvbmNhdChvLHIpLGE9dS5pbmRleE9mKCJcclxuXHJcbiIpO2lmKC0xPT09YSlyZXR1cm4gUHQoImhhdmUgbm90IHJlY2VpdmVkIGVuZCBvZiBIVFRQIGhlYWRlcnMgeWV0Li4uIiksdm9pZCBzKCk7Y29uc3QgZj11LnN1YmFycmF5KDAsYSkudG9TdHJpbmcoImFzY2lpIikuc3BsaXQoIlxyXG4iKSxoPWYuc2hpZnQoKTtpZighaClyZXR1cm4gdC5kZXN0cm95KCksbihuZXcgRXJyb3IoIk5vIGhlYWRlciByZWNlaXZlZCBmcm9tIHByb3h5IENPTk5FQ1QgcmVzcG9uc2UiKSk7Y29uc3QgcD1oLnNwbGl0KCIgIiksbD0rKHBbMV18fDApLGQ9cC5zbGljZSgyKS5qb2luKCIgIiksZz17fTtmb3IoY29uc3QgZSBvZiBmKXtpZighZSljb250aW51ZTtjb25zdCByPWUuaW5kZXhPZigiOiIpO2lmKC0xPT09cilyZXR1cm4gdC5kZXN0cm95KCksbihuZXcgRXJyb3IoYEludmFsaWQgaGVhZGVyIGZyb20gcHJveHkgQ09OTkVDVCByZXNwb25zZTogIiR7ZX0iYCkpO2NvbnN0IG89ZS5zbGljZSgwLHIpLnRvTG93ZXJDYXNlKCkscz1lLnNsaWNlKHIrMSkudHJpbVN0YXJ0KCksaT1nW29dOyJzdHJpbmciPT10eXBlb2YgaT9nW29dPVtpLHNdOkFycmF5LmlzQXJyYXkoaSk/aS5wdXNoKHMpOmdbb109c31QdCgiZ290IHByb3h5IHNlcnZlciByZXNwb25zZTogJW8gJW8iLGgsZyksaSgpLGUoe2Nvbm5lY3Q6e3N0YXR1c0NvZGU6bCxzdGF0dXNUZXh0OmQsaGVhZGVyczpnfSxidWZmZXJlZDp1fSl9KGMpOnQub25jZSgicmVhZGFibGUiLHMpfWZ1bmN0aW9uIGkoKXt0LnJlbW92ZUxpc3RlbmVyKCJlbmQiLGMpLHQucmVtb3ZlTGlzdGVuZXIoImVycm9yIix1KSx0LnJlbW92ZUxpc3RlbmVyKCJyZWFkYWJsZSIscyl9ZnVuY3Rpb24gYygpe2koKSxQdCgib25lbmQiKSxuKG5ldyBFcnJvcigiUHJveHkgY29ubmVjdGlvbiBlbmRlZCBiZWZvcmUgcmVjZWl2aW5nIENPTk5FQ1QgcmVzcG9uc2UiKSl9ZnVuY3Rpb24gdSh0KXtpKCksUHQoIm9uZXJyb3IgJW8iLHQpLG4odCl9dC5vbigiZXJyb3IiLHUpLHQub24oImVuZCIsYykscygpfSl9ZnVuY3Rpb24gVHQoLi4udCl7Xy5sb2coIltodHRwcy1wcm94eS1hZ2VudF0iLC4uLnQpfWNsYXNzIGt0IGV4dGVuZHMgT3R7Y29uc3RydWN0b3IodCxlKXtzdXBlcihlKSx0aGlzLm9wdGlvbnM9e30sdGhpcy5wcm94eT0ic3RyaW5nIj09dHlwZW9mIHQ/bmV3IFVSTCh0KTp0LHRoaXMucHJveHlIZWFkZXJzPWU/LmhlYWRlcnM/P3t9LFR0KCJDcmVhdGluZyBuZXcgSHR0cHNQcm94eUFnZW50IGluc3RhbmNlOiAlbyIsdGhpcy5wcm94eS5ocmVmKTtjb25zdCBuPSh0aGlzLnByb3h5Lmhvc3RuYW1lfHx0aGlzLnByb3h5Lmhvc3QpLnJlcGxhY2UoL15cW3xcXSQvZywiIikscj10aGlzLnByb3h5LnBvcnQ/cGFyc2VJbnQodGhpcy5wcm94eS5wb3J0LDEwKToiaHR0cHM6Ij09PXRoaXMucHJveHkucHJvdG9jb2w/NDQzOjgwO3RoaXMuY29ubmVjdE9wdHM9e0FMUE5Qcm90b2NvbHM6WyJodHRwLzEuMSJdLC4uLmU/SXQoZSwiaGVhZGVycyIpOm51bGwsaG9zdDpuLHBvcnQ6cn19YXN5bmMgY29ubmVjdCh0LGUpe2NvbnN0e3Byb3h5Om59PXRoaXM7aWYoIWUuaG9zdCl0aHJvdyBuZXcgVHlwZUVycm9yKCdObyAiaG9zdCIgcHJvdmlkZWQnKTtsZXQgcjtpZigiaHR0cHM6Ij09PW4ucHJvdG9jb2wpe1R0KCJDcmVhdGluZyBgdGxzLlNvY2tldGA6ICVvIix0aGlzLmNvbm5lY3RPcHRzKTtjb25zdCB0PXRoaXMuY29ubmVjdE9wdHMuc2VydmVybmFtZXx8dGhpcy5jb25uZWN0T3B0cy5ob3N0O3I9Zi5jb25uZWN0KHsuLi50aGlzLmNvbm5lY3RPcHRzLHNlcnZlcm5hbWU6dCYmYS5pc0lQKHQpP3ZvaWQgMDp0fSl9ZWxzZSBUdCgiQ3JlYXRpbmcgYG5ldC5Tb2NrZXRgOiAlbyIsdGhpcy5jb25uZWN0T3B0cykscj1hLmNvbm5lY3QodGhpcy5jb25uZWN0T3B0cyk7Y29uc3Qgbz0iZnVuY3Rpb24iPT10eXBlb2YgdGhpcy5wcm94eUhlYWRlcnM/dGhpcy5wcm94eUhlYWRlcnMoKTp7Li4udGhpcy5wcm94eUhlYWRlcnN9LHM9YS5pc0lQdjYoZS5ob3N0KT9gWyR7ZS5ob3N0fV1gOmUuaG9zdDtsZXQgaT1gQ09OTkVDVCAke3N9OiR7ZS5wb3J0fSBIVFRQLzEuMVxyXG5gO2lmKG4udXNlcm5hbWV8fG4ucGFzc3dvcmQpe2NvbnN0IHQ9YCR7ZGVjb2RlVVJJQ29tcG9uZW50KG4udXNlcm5hbWUpfToke2RlY29kZVVSSUNvbXBvbmVudChuLnBhc3N3b3JkKX1gO29bIlByb3h5LUF1dGhvcml6YXRpb24iXT1gQmFzaWMgJHtCdWZmZXIuZnJvbSh0KS50b1N0cmluZygiYmFzZTY0Iil9YH1vLkhvc3Q9YCR7c306JHtlLnBvcnR9YCxvWyJQcm94eS1Db25uZWN0aW9uIl18fChvWyJQcm94eS1Db25uZWN0aW9uIl09dGhpcy5rZWVwQWxpdmU/IktlZXAtQWxpdmUiOiJjbG9zZSIpO2Zvcihjb25zdCB0IG9mIE9iamVjdC5rZXlzKG8pKWkrPWAke3R9OiAke29bdF19XHJcbmA7Y29uc3QgYz1BdChyKTtyLndyaXRlKGAke2l9XHJcbmApO2NvbnN0e2Nvbm5lY3Q6dSxidWZmZXJlZDpofT1hd2FpdCBjO2lmKHQuZW1pdCgicHJveHlDb25uZWN0Iix1KSx0aGlzLmVtaXQoInByb3h5Q29ubmVjdCIsdSx0KSwyMDA9PT11LnN0YXR1c0NvZGUpe2lmKHQub25jZSgic29ja2V0IixSdCksZS5zZWN1cmVFbmRwb2ludCl7VHQoIlVwZ3JhZGluZyBzb2NrZXQgY29ubmVjdGlvbiB0byBUTFMiKTtjb25zdCB0PWUuc2VydmVybmFtZXx8ZS5ob3N0O3JldHVybiBmLmNvbm5lY3Qoey4uLkl0KGUsImhvc3QiLCJwYXRoIiwicG9ydCIpLHNvY2tldDpyLHNlcnZlcm5hbWU6YS5pc0lQKHQpP3ZvaWQgMDp0fSl9cmV0dXJuIHJ9ci5kZXN0cm95KCk7Y29uc3QgcD1uZXcgYS5Tb2NrZXQoe3dyaXRhYmxlOiExfSk7cmV0dXJuIHAucmVhZGFibGU9ITAsdC5vbmNlKCJzb2NrZXQiLHQ9PntUdCgiUmVwbGF5aW5nIHByb3h5IGJ1ZmZlciBmb3IgZmFpbGVkIHJlcXVlc3QiKSx0LnB1c2goaCksdC5wdXNoKG51bGwpfSkscH19ZnVuY3Rpb24gUnQodCl7dC5yZXN1bWUoKX1mdW5jdGlvbiBJdCh0LC4uLmUpe2NvbnN0IG49e307bGV0IHI7Zm9yKHIgaW4gdCllLmluY2x1ZGVzKHIpfHwobltyXT10W3JdKTtyZXR1cm4gbn1rdC5wcm90b2NvbHM9WyJodHRwIiwiaHR0cHMiXTtmdW5jdGlvbiBEdCh0KXtyZXR1cm4gdC5yZXBsYWNlKC9eW0EtWl06LywiIikucmVwbGFjZSgvXFwvZywiLyIpfWNvbnN0IFV0PWU7bGV0IEJ0LEx0PTAsTXQ9e307ZnVuY3Rpb24genQodCl7VXQuZGVidWcmJmNvbnNvbGUubG9nKGBbQU5SIFdvcmtlcl0gJHt0fWApfXZhciBKdCxXdCxGdDtjb25zdCBHdD1mdW5jdGlvbih0KXtsZXQgZTt0cnl7ZT1uZXcgVVJMKHQudXJsKX1jYXRjaHtyZXR1cm4gYigoKT0+e2NvbnNvbGUud2FybigiW0BzZW50cnkvbm9kZV06IEludmFsaWQgZHNuIG9yIHR1bm5lbCBvcHRpb24sIHdpbGwgbm90IHNlbmQgYW55IGV2ZW50cy4gVGhlIHR1bm5lbCBvcHRpb24gbXVzdCBiZSBhIGZ1bGwgVVJMIHdoZW4gdXNlZC4iKX0pLCR0KHQsKCk9PlByb21pc2UucmVzb2x2ZSh7fSkpfWNvbnN0IG49Imh0dHBzOiI9PT1lLnByb3RvY29sLHI9ZnVuY3Rpb24odCxlKXtjb25zdHtub19wcm94eTpufT1wcm9jZXNzLmVudixyPW4/LnNwbGl0KCIsIikuc29tZShlPT50Lmhvc3QuZW5kc1dpdGgoZSl8fHQuaG9zdG5hbWUuZW5kc1dpdGgoZSkpO3JldHVybiByP3ZvaWQgMDplfShlLHQucHJveHl8fChuP3Byb2Nlc3MuZW52Lmh0dHBzX3Byb3h5OnZvaWQgMCl8fHByb2Nlc3MuZW52Lmh0dHBfcHJveHkpLG89bj9pOnMsYT10LmtlZXBBbGl2ZT8/ITAsZj1yP25ldyBrdChyKTpuZXcgby5BZ2VudCh7a2VlcEFsaXZlOmEsbWF4U29ja2V0czozMCx0aW1lb3V0OjJlM30pLGg9ZnVuY3Rpb24odCxlLG4pe2NvbnN0e2hvc3RuYW1lOnIscGF0aG5hbWU6byxwb3J0OnMscHJvdG9jb2w6aSxzZWFyY2g6YX09bmV3IFVSTCh0LnVybCk7cmV0dXJuIGZ1bmN0aW9uKGYpe2NvbnN0IGg9cD0+bmV3IFByb21pc2UoKGwsZCk9Pnt5dCgoKT0+e2xldCBnPWZ1bmN0aW9uKHQpe3JldHVybiBuZXcgYyh7cmVhZCgpe3RoaXMucHVzaCh0KSx0aGlzLnB1c2gobnVsbCl9fSl9KGYuYm9keSk7Y29uc3QgbT17Li4udC5oZWFkZXJzfTtmLmJvZHkubGVuZ3RoPjMyNzY4JiYobVsiY29udGVudC1lbmNvZGluZyJdPSJnemlwIixnPWcucGlwZSh1KCkpKTtjb25zdCB5PXIuc3RhcnRzV2l0aCgiWyIpLGI9ZS5yZXF1ZXN0KHttZXRob2Q6IlBPU1QiLGFnZW50Om4saGVhZGVyczptLGhvc3RuYW1lOnk/ci5zbGljZSgxLC0xKTpyLHBhdGg6YCR7b30ke2F9YCxwb3J0OnMscHJvdG9jb2w6aSxjYTp0LmNhQ2VydHN9LHQ9Pnt0Lm9uKCJkYXRhIiwoKT0+e30pLHQub24oImVuZCIsKCk9Pnt9KSx0LnNldEVuY29kaW5nKCJ1dGY4Iik7Y29uc3QgZT10LmhlYWRlcnNbInJldHJ5LWFmdGVyIl0/P251bGwsbj10LmhlYWRlcnNbIngtc2VudHJ5LXJhdGUtbGltaXRzIl0/P251bGw7bCh7c3RhdHVzQ29kZTp0LnN0YXR1c0NvZGUsaGVhZGVyczp7InJldHJ5LWFmdGVyIjplLCJ4LXNlbnRyeS1yYXRlLWxpbWl0cyI6QXJyYXkuaXNBcnJheShuKT9uWzBdfHxudWxsOm59fSl9KTtiLm9uKCJlcnJvciIsdD0+e3AmJmIucmV1c2VkU29ja2V0JiYiRUNPTk5SRVNFVCI9PT10LmNvZGU/bChoKCExKSk6ZCh0KX0pLGcucGlwZShiKX0pfSk7cmV0dXJuIGgoITApfX0odCx0Lmh0dHBNb2R1bGU/P28sZik7cmV0dXJuICR0KHQsaCl9KHt1cmw6KEp0PVV0LmRzbixXdD1VdC50dW5uZWwsRnQ9VXQuc2RrTWV0YWRhdGEuc2RrLFd0fHxgJHtmdW5jdGlvbih0KXtyZXR1cm5gJHtmdW5jdGlvbih0KXtjb25zdCBlPXQucHJvdG9jb2w/YCR7dC5wcm90b2NvbH06YDoiIixuPXQucG9ydD9gOiR7dC5wb3J0fWA6IiI7cmV0dXJuYCR7ZX0vLyR7dC5ob3N0fSR7bn0ke3QucGF0aD9gLyR7dC5wYXRofWA6IiJ9L2FwaS9gfSh0KX0ke3QucHJvamVjdElkfS9lbnZlbG9wZS9gfShKdCl9PyR7ZnVuY3Rpb24odCxlKXtjb25zdCBuPXtzZW50cnlfdmVyc2lvbjoiNyJ9O3JldHVybiB0LnB1YmxpY0tleSYmKG4uc2VudHJ5X2tleT10LnB1YmxpY0tleSksZSYmKG4uc2VudHJ5X2NsaWVudD1gJHtlLm5hbWV9LyR7ZS52ZXJzaW9ufWApLG5ldyBVUkxTZWFyY2hQYXJhbXMobikudG9TdHJpbmcoKX0oSnQsRnQpfWApfSk7YXN5bmMgZnVuY3Rpb24gWXQoKXtpZihCdCl7enQoIlNlbmRpbmcgYWJub3JtYWwgc2Vzc2lvbiIpLFooQnQse3N0YXR1czoiYWJub3JtYWwiLGFibm9ybWFsX21lY2hhbmlzbToiYW5yX2ZvcmVncm91bmQiLHJlbGVhc2U6VXQucmVsZWFzZSxlbnZpcm9ubWVudDpVdC5lbnZpcm9ubWVudH0pO2NvbnN0IHQ9ZnVuY3Rpb24odCxlLG4scil7Y29uc3Qgbz1tdChuKTtyZXR1cm4gZnQoe3NlbnRfYXQ6bmV3IERhdGUoSSgpKS50b0lTT1N0cmluZygpLC4uLm8mJntzZGs6b30sLi4uISFyJiZlJiZ7ZHNuOnV0KGUpfX0sWyJhZ2dyZWdhdGVzImluIHQ/W3t0eXBlOiJzZXNzaW9ucyJ9LHRdOlt7dHlwZToic2Vzc2lvbiJ9LHQudG9KU09OKCldXSl9KEJ0LFV0LmRzbixVdC5zZGtNZXRhZGF0YSxVdC50dW5uZWwpO3p0KEpTT04uc3RyaW5naWZ5KHQpKSxhd2FpdCBHdC5zZW5kKHQpO3RyeXtuPy5wb3N0TWVzc2FnZSgic2Vzc2lvbi1lbmRlZCIpfWNhdGNoe319fWZ1bmN0aW9uIEh0KHQpe2lmKCF0KXJldHVybjtjb25zdCBlPWZ1bmN0aW9uKHQpe2lmKCF0Lmxlbmd0aClyZXR1cm5bXTtjb25zdCBlPUFycmF5LmZyb20odCk7cmV0dXJuL3NlbnRyeVdyYXBwZWQvLnRlc3QoRShlKS5mdW5jdGlvbnx8IiIpJiZlLnBvcCgpLGUucmV2ZXJzZSgpLCQudGVzdChFKGUpLmZ1bmN0aW9ufHwiIikmJihlLnBvcCgpLCQudGVzdChFKGUpLmZ1bmN0aW9ufHwiIikmJmUucG9wKCkpLGUuc2xpY2UoMCw1MCkubWFwKHQ9Pih7Li4udCxmaWxlbmFtZTp0LmZpbGVuYW1lfHxFKGUpLmZpbGVuYW1lLGZ1bmN0aW9uOnQuZnVuY3Rpb258fCI/In0pKX0odCk7aWYoVXQuYXBwUm9vdFBhdGgpZm9yKGNvbnN0IHQgb2YgZSl0LmZpbGVuYW1lJiYodC5maWxlbmFtZT1NKHQuZmlsZW5hbWUsVXQuYXBwUm9vdFBhdGgpKTtyZXR1cm4gZX1hc3luYyBmdW5jdGlvbiBadCh0LGUpe2lmKEx0Pj1VdC5tYXhBbnJFdmVudHMpcmV0dXJuO0x0Kz0xLGF3YWl0IFl0KCksenQoIlNlbmRpbmcgZXZlbnQiKTtjb25zdCBuPXtldmVudF9pZDpXKCksY29udGV4dHM6VXQuY29udGV4dHMscmVsZWFzZTpVdC5yZWxlYXNlLGVudmlyb25tZW50OlV0LmVudmlyb25tZW50LGRpc3Q6VXQuZGlzdCxwbGF0Zm9ybToibm9kZSIsbGV2ZWw6ImVycm9yIixleGNlcHRpb246e3ZhbHVlczpbe3R5cGU6IkFwcGxpY2F0aW9uTm90UmVzcG9uZGluZyIsdmFsdWU6YEFwcGxpY2F0aW9uIE5vdCBSZXNwb25kaW5nIGZvciBhdCBsZWFzdCAke1V0LmFuclRocmVzaG9sZH0gbXNgLHN0YWNrdHJhY2U6e2ZyYW1lczpIdCh0KX0sbWVjaGFuaXNtOnt0eXBlOiJBTlIifX1dfSx0YWdzOlV0LnN0YXRpY1RhZ3N9O2UmJmZ1bmN0aW9uKHQsZSl7aWYoYXQodCxlKSwhdC5jb250ZXh0cz8udHJhY2Upe2NvbnN0e3RyYWNlSWQ6bixwYXJlbnRTcGFuSWQ6cixwcm9wYWdhdGlvblNwYW5JZDpvfT1lLnByb3BhZ2F0aW9uQ29udGV4dDt0LmNvbnRleHRzPXt0cmFjZTp7dHJhY2VfaWQ6bixzcGFuX2lkOm98fFcoKS5zdWJzdHJpbmcoMTYpLHBhcmVudF9zcGFuX2lkOnJ9LC4uLnQuY29udGV4dHN9fX0obixlKSxmdW5jdGlvbih0KXtpZigwPT09T2JqZWN0LmtleXMoTXQpLmxlbmd0aClyZXR1cm47Y29uc3QgZT1VdC5hcHBSb290UGF0aD97fTpNdDtpZihVdC5hcHBSb290UGF0aClmb3IoY29uc3RbdCxuXW9mIE9iamVjdC5lbnRyaWVzKE10KSllW00odCxVdC5hcHBSb290UGF0aCldPW47Y29uc3Qgbj1uZXcgTWFwO2Zvcihjb25zdCByIG9mIHQuZXhjZXB0aW9uPy52YWx1ZXN8fFtdKWZvcihjb25zdCB0IG9mIHIuc3RhY2t0cmFjZT8uZnJhbWVzfHxbXSl7Y29uc3Qgcj10LmFic19wYXRofHx0LmZpbGVuYW1lO3ImJmVbcl0mJm4uc2V0KHIsZVtyXSl9aWYobi5zaXplPjApe2NvbnN0IGU9W107Zm9yKGNvbnN0W3Qscl1vZiBuLmVudHJpZXMoKSllLnB1c2goe3R5cGU6InNvdXJjZW1hcCIsY29kZV9maWxlOnQsZGVidWdfaWQ6cn0pO3QuZGVidWdfbWV0YT17aW1hZ2VzOmV9fX0obik7Y29uc3Qgcj1idChuLFV0LmRzbixVdC5zZGtNZXRhZGF0YSxVdC50dW5uZWwpO3p0KEpTT04uc3RyaW5naWZ5KHIpKSxhd2FpdCBHdC5zZW5kKHIpLGF3YWl0IEd0LmZsdXNoKDJlMyksTHQ+PVV0Lm1heEFuckV2ZW50cyYmc2V0VGltZW91dCgoKT0+e3Byb2Nlc3MuZXhpdCgwKX0sNWUzKX1sZXQgcXQ7aWYoenQoIlN0YXJ0ZWQiKSxVdC5jYXB0dXJlU3RhY2tUcmFjZSl7enQoIkNvbm5lY3RpbmcgdG8gZGVidWdnZXIiKTtjb25zdCBlPW5ldyB0O2UuY29ubmVjdFRvTWFpblRocmVhZCgpLHp0KCJDb25uZWN0ZWQgdG8gZGVidWdnZXIiKTtjb25zdCBuPW5ldyBNYXA7ZS5vbigiRGVidWdnZXIuc2NyaXB0UGFyc2VkIix0PT57bi5zZXQodC5wYXJhbXMuc2NyaXB0SWQsdC5wYXJhbXMudXJsKX0pLGUub24oIkRlYnVnZ2VyLnBhdXNlZCIsdD0+e2lmKCJvdGhlciI9PT10LnBhcmFtcy5yZWFzb24pdHJ5e3p0KCJEZWJ1Z2dlciBwYXVzZWQiKTtjb25zdCBzPVsuLi50LnBhcmFtcy5jYWxsRnJhbWVzXSxpPVV0LmFwcFJvb3RQYXRoP2Z1bmN0aW9uKHQ9KHByb2Nlc3MuYXJndlsxXT94dChwcm9jZXNzLmFyZ3ZbMV0pOnByb2Nlc3MuY3dkKCkpLGU9IlxcIj09PW8pe2NvbnN0IG49ZT9EdCh0KTp0O3JldHVybiB0PT57aWYoIXQpcmV0dXJuO2NvbnN0IG89ZT9EdCh0KTp0O2xldHtkaXI6cyxiYXNlOmksZXh0OmN9PXIucGFyc2Uobyk7Ii5qcyIhPT1jJiYiLm1qcyIhPT1jJiYiLmNqcyIhPT1jfHwoaT1pLnNsaWNlKDAsLTEqYy5sZW5ndGgpKTtjb25zdCB1PWRlY29kZVVSSUNvbXBvbmVudChpKTtzfHwocz0iLiIpO2NvbnN0IGE9cy5sYXN0SW5kZXhPZigiL25vZGVfbW9kdWxlcyIpO2lmKGE+LTEpcmV0dXJuYCR7cy5zbGljZShhKzE0KS5yZXBsYWNlKC9cLy9nLCIuIil9OiR7dX1gO2lmKHMuc3RhcnRzV2l0aChuKSl7Y29uc3QgdD1zLnNsaWNlKG4ubGVuZ3RoKzEpLnJlcGxhY2UoL1wvL2csIi4iKTtyZXR1cm4gdD9gJHt0fToke3V9YDp1fXJldHVybiB1fX0oVXQuYXBwUm9vdFBhdGgpOigpPT57fSxjPXMubWFwKHQ9PmZ1bmN0aW9uKHQsZSxuKXtjb25zdCByPWU/ZS5yZXBsYWNlKC9eZmlsZTpcL1wvLywiIik6dm9pZCAwLG89dC5sb2NhdGlvbi5jb2x1bW5OdW1iZXI/dC5sb2NhdGlvbi5jb2x1bW5OdW1iZXIrMTp2b2lkIDAscz10LmxvY2F0aW9uLmxpbmVOdW1iZXI/dC5sb2NhdGlvbi5saW5lTnVtYmVyKzE6dm9pZCAwO3JldHVybntmaWxlbmFtZTpyLG1vZHVsZTpuKHIpLGZ1bmN0aW9uOnQuZnVuY3Rpb25OYW1lfHwiPyIsY29sbm86byxsaW5lbm86cyxpbl9hcHA6cj9OdChyKTp2b2lkIDB9fSh0LG4uZ2V0KHQubG9jYXRpb24uc2NyaXB0SWQpLGkpKSx1PXNldFRpbWVvdXQoKCk9PntadChjKS50aGVuKG51bGwsKCk9Pnt6dCgiU2VuZGluZyBBTlIgZXZlbnQgZmFpbGVkLiIpfSl9LDVlMyk7ZS5wb3N0KCJSdW50aW1lLmV2YWx1YXRlIix7ZXhwcmVzc2lvbjoiZ2xvYmFsLl9fU0VOVFJZX0dFVF9TQ09QRVNfXygpOyIsc2lsZW50OiEwLHJldHVybkJ5VmFsdWU6ITB9LCh0LG4pPT57dCYmenQoYEVycm9yIGV4ZWN1dGluZyBzY3JpcHQ6ICcke3QubWVzc2FnZX0nYCksY2xlYXJUaW1lb3V0KHUpO2NvbnN0IHI9bj8ucmVzdWx0P24ucmVzdWx0LnZhbHVlOnZvaWQgMDtlLnBvc3QoIkRlYnVnZ2VyLnJlc3VtZSIpLGUucG9zdCgiRGVidWdnZXIuZGlzYWJsZSIpLFp0KGMscikudGhlbihudWxsLCgpPT57enQoIlNlbmRpbmcgQU5SIGV2ZW50IGZhaWxlZC4iKX0pfSl9Y2F0Y2godCl7dGhyb3cgZS5wb3N0KCJEZWJ1Z2dlci5yZXN1bWUiKSxlLnBvc3QoIkRlYnVnZ2VyLmRpc2FibGUiKSx0fX0pLHF0PSgpPT57dHJ5e2UucG9zdCgiRGVidWdnZXIuZW5hYmxlIiwoKT0+e2UucG9zdCgiRGVidWdnZXIucGF1c2UiKX0pfWNhdGNoe319fWNvbnN0e3BvbGw6S3R9PWZ1bmN0aW9uKHQsZSxuLHIpe2NvbnN0IG89dCgpO2xldCBzPSExLGk9ITA7cmV0dXJuIHNldEludGVydmFsKCgpPT57Y29uc3QgdD1vLmdldFRpbWVNcygpOyExPT09cyYmdD5lK24mJihzPSEwLGkmJnIoKSksdDxlK24mJihzPSExKX0sMjApLHtwb2xsOigpPT57by5yZXNldCgpfSxlbmFibGVkOnQ9PntpPXR9fX0oZnVuY3Rpb24oKXtsZXQgdD1wcm9jZXNzLmhydGltZSgpO3JldHVybntnZXRUaW1lTXM6KCk9Pntjb25zdFtlLG5dPXByb2Nlc3MuaHJ0aW1lKHQpO3JldHVybiBNYXRoLmZsb29yKDFlMyplK24vMWU2KX0scmVzZXQ6KCk9Pnt0PXByb2Nlc3MuaHJ0aW1lKCl9fX0sVXQucG9sbEludGVydmFsLFV0LmFuclRocmVzaG9sZCxmdW5jdGlvbigpe3p0KCJXYXRjaGRvZyB0aW1lb3V0IikscXQ/KHp0KCJQYXVzaW5nIGRlYnVnZ2VyIHRvIGNhcHR1cmUgc3RhY2sgdHJhY2UiKSxxdCgpKTooenQoIkNhcHR1cmluZyBldmVudCB3aXRob3V0IGEgc3RhY2sgdHJhY2UiKSxadCgpLnRoZW4obnVsbCwoKT0+e3p0KCJTZW5kaW5nIEFOUiBldmVudCBmYWlsZWQgb24gd2F0Y2hkb2cgdGltZW91dC4iKX0pKX0pO24/Lm9uKCJtZXNzYWdlIix0PT57dC5zZXNzaW9uJiYoQnQ9SCh0LnNlc3Npb24pKSx0LmRlYnVnSW1hZ2VzJiYoTXQ9dC5kZWJ1Z0ltYWdlcyksS3QoKX0pOw==";
|
|
7
|
+
const base64WorkerScript = "LyohIEBzZW50cnkvbm9kZSAxMS4wLjAtYmV0YS4xIChjYjIzOWUwKSB8IGh0dHBzOi8vZ2l0aHViLmNvbS9nZXRzZW50cnkvc2VudHJ5LWphdmFzY3JpcHQgKi8KaW1wb3J0e1Nlc3Npb24gYXMgdH1mcm9tIm5vZGU6aW5zcGVjdG9yIjtpbXBvcnR7d29ya2VyRGF0YSBhcyBlLHBhcmVudFBvcnQgYXMgbn1mcm9tIm5vZGU6d29ya2VyX3RocmVhZHMiO2ltcG9ydHtwb3NpeCBhcyByLHNlcCBhcyBvfWZyb20ibm9kZTpwYXRoIjtpbXBvcnQqYXMgcyBmcm9tIm5vZGU6aHR0cCI7aW1wb3J0KmFzIGkgZnJvbSJub2RlOmh0dHBzIjtpbXBvcnR7UmVhZGFibGUgYXMgY31mcm9tIm5vZGU6c3RyZWFtIjtpbXBvcnR7Y3JlYXRlR3ppcCBhcyB1fWZyb20ibm9kZTp6bGliIjtpbXBvcnQqYXMgYSBmcm9tIm5vZGU6bmV0IjtpbXBvcnQqYXMgZiBmcm9tIm5vZGU6dGxzIjtjb25zdCBoPSJ1bmRlZmluZWQiPT10eXBlb2YgX19TRU5UUllfREVCVUdfX3x8X19TRU5UUllfREVCVUdfXyxwPWdsb2JhbFRoaXMsbD0iMTEuMC4wLWJldGEuMSI7ZnVuY3Rpb24gZCgpe3JldHVybiBnKHApLHB9ZnVuY3Rpb24gZyh0KXtjb25zdCBlPXQuX19TRU5UUllfXz10Ll9fU0VOVFJZX198fHt9O3JldHVybiBlLnZlcnNpb249ZS52ZXJzaW9ufHxsLGVbbF09ZVtsXXx8e319ZnVuY3Rpb24gbSh0LGUsbj1wKXtjb25zdCByPW4uX19TRU5UUllfXz1uLl9fU0VOVFJZX198fHt9LG89cltsXT1yW2xdfHx7fTtyZXR1cm4gb1t0XXx8KG9bdF09ZSgpKX1jb25zdCB5PXt9O2Z1bmN0aW9uIGIodCl7aWYoISgiY29uc29sZSJpbiBwKSlyZXR1cm4gdCgpO2NvbnN0IGU9cC5jb25zb2xlLG49e30scj1PYmplY3Qua2V5cyh5KTtyLmZvckVhY2godD0+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=";
|
|
8
8
|
const DEFAULT_INTERVAL = 50;
|
|
9
9
|
const DEFAULT_HANG_THRESHOLD = 5e3;
|
|
10
10
|
function log(message, ...args) {
|