@cartanova/qgrid-cli 2.10.9 → 2.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bundle/dist/_virtual/_rolldown/runtime.js +1 -10
- package/bundle/dist/application/monit/log-buffer.js +12 -6
- package/bundle/dist/application/monit/monit.frame.js +11 -3
- package/bundle/dist/application/monit/monit.types.js +1 -1
- package/bundle/dist/application/qgrid/conv-routing.js +9 -6
- package/bundle/dist/application/qgrid/expired-token-reminder.js +2 -2
- package/bundle/dist/application/qgrid/oauth.js +31 -4
- package/bundle/dist/application/qgrid/qgrid-image-generation.js +1 -1
- package/bundle/dist/application/qgrid/qgrid-response-format.js +22 -20
- package/bundle/dist/application/qgrid/qgrid-run-lifecycle.js +43 -34
- package/bundle/dist/application/qgrid/qgrid.dispatcher.js +128 -93
- package/bundle/dist/application/qgrid/qgrid.frame.js +930 -49
- package/bundle/dist/application/qgrid/qgrid.types.js +212 -5
- package/bundle/dist/application/qgrid/schema-prompt.js +75 -48
- package/bundle/dist/application/qgrid/slack-user-map.js +1 -1
- package/bundle/dist/application/qgrid/token-death.js +1 -1
- package/bundle/dist/application/qgrid/token-subscriber.js +83 -30
- package/bundle/dist/application/qgrid/token-trigger-setup.js +1 -1
- package/bundle/dist/application/qgrid/token-window-keepalive.js +8 -6
- package/bundle/dist/application/qgrid/tool-emulation-schema.js +13 -13
- package/bundle/dist/application/qgrid/tool-emulation.js +19 -15
- package/bundle/dist/application/request-log/json-schema-type-text.js +29 -12
- package/bundle/dist/application/request-log/request-log.model.js +83 -69
- package/bundle/dist/application/request-log/request-log.types.js +8 -2
- package/bundle/dist/application/request-log/zod-code-format.js +1 -1
- package/bundle/dist/application/request-log-step/request-log-step.model.js +1 -1
- package/bundle/dist/application/request-log-step/request-log-step.types.js +1 -1
- package/bundle/dist/application/setting/setting.constant.js +1 -1
- package/bundle/dist/application/setting/setting.model.js +2 -2
- package/bundle/dist/application/setting/setting.store.js +2 -2
- package/bundle/dist/application/setting/setting.types.js +1 -1
- package/bundle/dist/application/sonamu.generated.js +40 -16
- package/bundle/dist/application/sonamu.generated.sso.js +2 -1
- package/bundle/dist/application/token/token.model.js +26 -9
- package/bundle/dist/application/token/token.types.js +20 -3
- package/bundle/dist/i18n/en.js +15 -1
- package/bundle/dist/i18n/ko.js +15 -1
- package/bundle/dist/i18n/sd.generated.js +2 -1
- package/bundle/dist/migrations/20260807133553_manual__backfill_request_log_cost.js +8 -6
- package/bundle/dist/migrations/20261018215031_alter_request_logs_add1_alter1.js +15 -0
- package/bundle/dist/server-bootstrap.js +4 -2
- package/bundle/dist/server-error-handler.js +1 -1
- package/bundle/dist/sonamu.config.js +37 -8
- package/bundle/dist/startup-migrations.js +17 -7
- package/bundle/dist/testing/global.js +1 -1
- package/bundle/dist/testing/schema-bench.js +0 -0
- package/bundle/dist/testing/test-database-name.js +1 -1
- package/bundle/dist/utils/providers/anthropic/anthropic-constants.js +1 -1
- package/bundle/dist/utils/providers/anthropic/anthropic-dispatcher.js +11 -5
- package/bundle/dist/utils/providers/anthropic/anthropic-quota.js +4 -4
- package/bundle/dist/utils/providers/anthropic/anthropic-thinking.js +1 -1
- package/bundle/dist/utils/providers/anthropic/claude-session.js +20 -19
- package/bundle/dist/utils/providers/anthropic/fence-strip.js +1 -1
- package/bundle/dist/utils/providers/anthropic/stream-json-adapter.js +49 -23
- package/bundle/dist/utils/providers/common/credentials.js +5 -1
- package/bundle/dist/utils/providers/common/effort.js +3 -3
- package/bundle/dist/utils/providers/common/model-cost.js +69 -14
- package/bundle/dist/utils/providers/common/provider-types.js +29 -1
- package/bundle/dist/utils/providers/common/schema-validation.js +78 -40
- package/bundle/dist/utils/providers/common/smooth-weighted-round-robin.js +1 -1
- package/bundle/dist/utils/providers/common/strictifier.js +62 -43
- package/bundle/dist/utils/providers/common/thinking.js +3 -2
- package/bundle/dist/utils/providers/common/ttft.js +1 -1
- package/bundle/dist/utils/providers/grok/grok-backend-protocol.js +427 -0
- package/bundle/dist/utils/providers/grok/grok-constants.js +55 -0
- package/bundle/dist/utils/providers/grok/grok-direct-client.js +196 -0
- package/bundle/dist/utils/providers/grok/grok-dispatcher.js +1313 -0
- package/bundle/dist/utils/providers/grok/grok-headers.js +118 -0
- package/bundle/dist/utils/providers/grok/grok-media-client.js +420 -0
- package/bundle/dist/utils/providers/grok/grok-models.js +114 -0
- package/bundle/dist/utils/providers/grok/grok-oauth.js +455 -0
- package/bundle/dist/utils/providers/grok/grok-quota.js +119 -0
- package/bundle/dist/utils/providers/grok/grok-refresh.js +192 -0
- package/bundle/dist/utils/providers/grok/grok-types.js +186 -0
- package/bundle/dist/utils/providers/grok/grok-voice-client.js +199 -0
- package/bundle/dist/utils/providers/grok/index.js +11 -0
- package/bundle/dist/utils/providers/openai/openai-backend-protocol.js +111 -83
- package/bundle/dist/utils/providers/openai/openai-callback-relay.js +3 -2
- package/bundle/dist/utils/providers/openai/openai-constants.js +1 -1
- package/bundle/dist/utils/providers/openai/openai-direct-client.js +23 -7
- package/bundle/dist/utils/providers/openai/openai-dispatcher.js +143 -106
- package/bundle/dist/utils/providers/openai/openai-image-generation.js +48 -33
- package/bundle/dist/utils/providers/openai/openai-oauth.js +28 -13
- package/bundle/dist/utils/providers/openai/openai-quota.js +38 -27
- package/bundle/dist/utils/providers/openai/openai-refresh.js +17 -9
- package/bundle/dist/utils/providers/openai/openai-sse.js +1 -1
- package/bundle/dist/utils/providers/openai/openai-transport-config.js +1 -1
- package/bundle/dist/utils/quiet-hours.js +1 -1
- package/bundle/dist/utils/slack-notify.js +14 -8
- package/bundle/dist/utils/subset-loaders.js +4 -5
- package/bundle/src/application/monit/log-buffer.ts +23 -9
- package/bundle/src/application/monit/monit.frame.ts +22 -5
- package/bundle/src/application/monit/monit.types.ts +6 -0
- package/bundle/src/application/qgrid/conv-routing.test.ts +76 -4
- package/bundle/src/application/qgrid/conv-routing.ts +35 -9
- package/bundle/src/application/qgrid/expired-token-reminder.ts +9 -1
- package/bundle/src/application/qgrid/oauth.ts +51 -15
- package/bundle/src/application/qgrid/qgrid-image-generation.ts +9 -0
- package/bundle/src/application/qgrid/qgrid-response-format.ts +50 -25
- package/bundle/src/application/qgrid/qgrid-run-lifecycle.test.ts +33 -0
- package/bundle/src/application/qgrid/qgrid-run-lifecycle.ts +87 -40
- package/bundle/src/application/qgrid/qgrid.dispatcher.test.ts +97 -0
- package/bundle/src/application/qgrid/qgrid.dispatcher.ts +274 -126
- package/bundle/src/application/qgrid/qgrid.frame.test.ts +1013 -3
- package/bundle/src/application/qgrid/qgrid.frame.ts +1415 -60
- package/bundle/src/application/qgrid/qgrid.types.ts +335 -0
- package/bundle/src/application/qgrid/schema-prompt.ts +105 -41
- package/bundle/src/application/qgrid/slack-user-map.ts +5 -0
- package/bundle/src/application/qgrid/token-death.ts +4 -0
- package/bundle/src/application/qgrid/token-subscriber.test.ts +21 -19
- package/bundle/src/application/qgrid/token-subscriber.ts +186 -53
- package/bundle/src/application/qgrid/token-trigger-setup.ts +2 -0
- package/bundle/src/application/qgrid/token-window-keepalive.ts +49 -6
- package/bundle/src/application/qgrid/tool-emulation-schema.ts +33 -29
- package/bundle/src/application/qgrid/tool-emulation.ts +52 -27
- package/bundle/src/application/request-log/json-schema-type-text.test.ts +5 -5
- package/bundle/src/application/request-log/json-schema-type-text.ts +81 -26
- package/bundle/src/application/request-log/request-log.entity.json +8 -0
- package/bundle/src/application/request-log/request-log.model.test.ts +111 -4
- package/bundle/src/application/request-log/request-log.model.ts +279 -145
- package/bundle/src/application/request-log/request-log.types.ts +17 -0
- package/bundle/src/application/request-log/zod-code-format.ts +11 -0
- package/bundle/src/application/request-log-step/request-log-step.model.ts +1 -0
- package/bundle/src/application/request-log-step/request-log-step.types.ts +2 -0
- package/bundle/src/application/setting/setting.constant.ts +9 -0
- package/bundle/src/application/setting/setting.model.ts +12 -2
- package/bundle/src/application/setting/setting.store.ts +5 -1
- package/bundle/src/application/setting/setting.types.ts +8 -0
- package/bundle/src/application/sonamu.generated.http +135 -0
- package/bundle/src/application/sonamu.generated.sso.ts +3 -0
- package/bundle/src/application/sonamu.generated.ts +29 -0
- package/bundle/src/application/token/token.identity.test.ts +20 -0
- package/bundle/src/application/token/token.model.ts +66 -7
- package/bundle/src/application/token/token.types.ts +24 -1
- package/bundle/src/i18n/en.ts +19 -0
- package/bundle/src/i18n/ko.ts +21 -0
- package/bundle/src/i18n/sd.generated.ts +24 -2
- package/bundle/src/migrations/20260807133553_manual__backfill_request_log_cost.ts +16 -8
- package/bundle/src/migrations/20261018215031_alter_request_logs_add1_alter1.ts +15 -0
- package/bundle/src/server-bootstrap.ts +4 -2
- package/bundle/src/server-error-handler.ts +1 -0
- package/bundle/src/sonamu.config.ts +69 -7
- package/bundle/src/startup-migrations.ts +27 -9
- package/bundle/src/testing/global.ts +20 -0
- package/bundle/src/testing/schema-bench.ts +105 -30
- package/bundle/src/testing/test-database-name.ts +2 -0
- package/bundle/src/utils/providers/anthropic/anthropic-constants.ts +8 -0
- package/bundle/src/utils/providers/anthropic/anthropic-dispatcher.ts +41 -6
- package/bundle/src/utils/providers/anthropic/anthropic-quota.ts +7 -3
- package/bundle/src/utils/providers/anthropic/anthropic-thinking.ts +6 -0
- package/bundle/src/utils/providers/anthropic/claude-session.ts +58 -24
- package/bundle/src/utils/providers/anthropic/fence-strip.ts +11 -0
- package/bundle/src/utils/providers/anthropic/stream-json-adapter.ts +110 -45
- package/bundle/src/utils/providers/common/credentials.ts +8 -0
- package/bundle/src/utils/providers/common/effort.ts +9 -2
- package/bundle/src/utils/providers/common/model-cost.test.ts +48 -1
- package/bundle/src/utils/providers/common/model-cost.ts +259 -158
- package/bundle/src/utils/providers/common/provider-dispatcher.ts +98 -2
- package/bundle/src/utils/providers/common/provider-types.ts +46 -3
- package/bundle/src/utils/providers/common/schema-validation.test.ts +5 -1
- package/bundle/src/utils/providers/common/schema-validation.ts +124 -56
- package/bundle/src/utils/providers/common/smooth-weighted-round-robin.ts +4 -0
- package/bundle/src/utils/providers/common/strictifier.ts +185 -59
- package/bundle/src/utils/providers/common/thinking.ts +2 -2
- package/bundle/src/utils/providers/common/ttft.ts +4 -2
- package/bundle/src/utils/providers/grok/__fixtures__/golden-responses-1.0.60.json +164 -0
- package/bundle/src/utils/providers/grok/grok-backend-protocol.test.ts +325 -0
- package/bundle/src/utils/providers/grok/grok-backend-protocol.ts +721 -0
- package/bundle/src/utils/providers/grok/grok-constants.ts +105 -0
- package/bundle/src/utils/providers/grok/grok-direct-client.test.ts +179 -0
- package/bundle/src/utils/providers/grok/grok-direct-client.ts +313 -0
- package/bundle/src/utils/providers/grok/grok-dispatcher.test.ts +1395 -0
- package/bundle/src/utils/providers/grok/grok-dispatcher.ts +2105 -0
- package/bundle/src/utils/providers/grok/grok-headers.test.ts +149 -0
- package/bundle/src/utils/providers/grok/grok-headers.ts +199 -0
- package/bundle/src/utils/providers/grok/grok-media-client.test.ts +446 -0
- package/bundle/src/utils/providers/grok/grok-media-client.ts +703 -0
- package/bundle/src/utils/providers/grok/grok-models.test.ts +96 -0
- package/bundle/src/utils/providers/grok/grok-models.ts +161 -0
- package/bundle/src/utils/providers/grok/grok-oauth.test.ts +406 -0
- package/bundle/src/utils/providers/grok/grok-oauth.ts +771 -0
- package/bundle/src/utils/providers/grok/grok-quota.test.ts +142 -0
- package/bundle/src/utils/providers/grok/grok-quota.ts +198 -0
- package/bundle/src/utils/providers/grok/grok-refresh.test.ts +239 -0
- package/bundle/src/utils/providers/grok/grok-refresh.ts +325 -0
- package/bundle/src/utils/providers/grok/grok-types.test.ts +252 -0
- package/bundle/src/utils/providers/grok/grok-types.ts +374 -0
- package/bundle/src/utils/providers/grok/grok-voice-client.test.ts +321 -0
- package/bundle/src/utils/providers/grok/grok-voice-client.ts +284 -0
- package/bundle/src/utils/providers/grok/index.ts +20 -0
- package/bundle/src/utils/providers/openai/openai-backend-protocol.ts +221 -137
- package/bundle/src/utils/providers/openai/openai-callback-relay.ts +12 -1
- package/bundle/src/utils/providers/openai/openai-constants.ts +2 -0
- package/bundle/src/utils/providers/openai/openai-direct-client.ts +111 -21
- package/bundle/src/utils/providers/openai/openai-dispatcher.ts +322 -169
- package/bundle/src/utils/providers/openai/openai-image-generation.ts +116 -36
- package/bundle/src/utils/providers/openai/openai-oauth.ts +48 -20
- package/bundle/src/utils/providers/openai/openai-quota.ts +77 -46
- package/bundle/src/utils/providers/openai/openai-refresh.ts +42 -18
- package/bundle/src/utils/providers/openai/openai-sse.ts +27 -3
- package/bundle/src/utils/providers/openai/openai-transport-config.ts +2 -0
- package/bundle/src/utils/quiet-hours.ts +12 -1
- package/bundle/src/utils/slack-notify.ts +44 -13
- package/bundle/src/utils/subset-loaders.ts +7 -7
- package/bundle/web-dist/client/assets/clsx-5XM_pHvN.js +1 -0
- package/bundle/web-dist/client/assets/index-BA7uQ-6c.js +31 -0
- package/bundle/web-dist/client/assets/index-Be2qCZmI.css +1 -0
- package/bundle/web-dist/client/assets/logs-C47OJGEI.js +1 -0
- package/bundle/web-dist/client/assets/monit-BS9no0dU.js +4 -0
- package/bundle/web-dist/client/assets/plus-sdACTfH0.js +1 -0
- package/bundle/web-dist/client/assets/refresh-cw-CY8o_1cT.js +1 -0
- package/bundle/web-dist/client/assets/request-model-BRtFuZvj.js +1 -0
- package/bundle/web-dist/client/assets/routes-kqgkUxE8.js +5 -0
- package/bundle/web-dist/client/assets/{services.generated-BsieU37H.js → services.generated-CefiDXEv.js} +5 -5
- package/bundle/web-dist/client/assets/settings-DNDvFGSw.js +1 -0
- package/bundle/web-dist/client/assets/show-u8Np69q3.js +2 -0
- package/bundle/web-dist/client/assets/tokens-QvP410NW.js +1 -0
- package/bundle/web-dist/client/assets/total-cost-MnfKU8IN.js +1 -0
- package/bundle/web-dist/client/assets/use-oauth-login-flow-Bzdh28Ws.js +1 -0
- package/bundle/web-dist/client/assets/use-update-token-mutation-CfJKaxmR.js +1 -0
- package/bundle/web-dist/client/assets/vendor-react-CUFFrVN9.js +244 -0
- package/bundle/web-dist/client/assets/vendor-tanstack-Bf_jag9G.js +1 -0
- package/bundle/web-dist/client/index.html +6 -6
- package/bundle/web-dist/server/assets/clsx-D_N5PN_2.js +16 -0
- package/bundle/web-dist/server/assets/{lazyRouteComponent-Dtd0NR4r.js → lazyRouteComponent-D8iTIHyn.js} +129 -2
- package/bundle/web-dist/server/assets/logs-B3OTd9hy.js +825 -0
- package/bundle/web-dist/server/assets/{monit-DvzribSE.js → monit-B2hqorPe.js} +385 -126
- package/bundle/web-dist/server/assets/plus-DwG7h9kq.js +28 -0
- package/bundle/web-dist/server/assets/{react-dom-B4a6-uuR.js → react-dom-BIYQzBqG.js} +2 -129
- package/bundle/web-dist/server/assets/refresh-cw-mMBkwOq0.js +44 -0
- package/bundle/web-dist/server/assets/{request-model-CbqfnQOJ.js → request-model-I6OdODSH.js} +15 -6
- package/bundle/web-dist/server/assets/{routes-BAPWTizT.js → routes-B95YlUv2.js} +760 -213
- package/bundle/web-dist/server/assets/{services.generated-CEbGjsI0.js → services.generated-DQATJ6qf.js} +12821 -12194
- package/bundle/web-dist/server/assets/settings-C3gbGk0m.js +830 -0
- package/bundle/web-dist/server/assets/{show-CxVZTAdv.js → show-Bxaj3rhH.js} +1355 -419
- package/bundle/web-dist/server/assets/tokens-CZjH3cB7.js +1038 -0
- package/bundle/web-dist/server/assets/total-cost-fTE9Xy82.js +18 -0
- package/bundle/web-dist/server/assets/use-oauth-login-flow-CKDHgc3U.js +2379 -0
- package/bundle/web-dist/server/assets/{use-update-token-mutation-CfYmk_4_.js → use-update-token-mutation-BEbgOzaa.js} +1 -1
- package/bundle/web-dist/server/entry-server.generated.js +4303 -22810
- package/dist/cli.js +9 -9
- package/package.json +4 -11
- package/postinstall.mjs +12 -0
- package/skills/qgrid/SKILL.md +1 -0
- package/skills/qgrid/references/cli-env-and-server-boot.md +4 -1
- package/skills/qgrid/references/decision-rationale.md +24 -1
- package/skills/qgrid/references/grok-runtime.md +89 -0
- package/skills/qgrid/references/provider-runtime-differences.md +30 -29
- package/skills/qgrid/references/repo-map.md +10 -0
- package/skills/qgrid/references/request-log-run-lifecycle.md +1 -1
- package/skills/qgrid/references/sonamu-api-web-flow.md +1 -1
- package/skills/qgrid/references/token-auth-quota-lifecycle.md +56 -3
- package/bundle/dist/node_modules/.pnpm/@jridgewell_sourcemap-codec@1.5.5/node_modules/@jridgewell/sourcemap-codec/dist/sourcemap-codec.js +0 -406
- package/bundle/dist/node_modules/.pnpm/@vitest_expect@4.1.10/node_modules/@vitest/expect/dist/index.js +0 -1507
- package/bundle/dist/node_modules/.pnpm/@vitest_pretty-format@4.1.10/node_modules/@vitest/pretty-format/dist/index.js +0 -887
- package/bundle/dist/node_modules/.pnpm/@vitest_runner@4.1.10/node_modules/@vitest/runner/dist/chunk-artifact.js +0 -2756
- package/bundle/dist/node_modules/.pnpm/@vitest_runner@4.1.10/node_modules/@vitest/runner/dist/index.js +0 -8
- package/bundle/dist/node_modules/.pnpm/@vitest_runner@4.1.10/node_modules/@vitest/runner/dist/utils.js +0 -8
- package/bundle/dist/node_modules/.pnpm/@vitest_snapshot@4.1.10/node_modules/@vitest/snapshot/dist/index.js +0 -922
- package/bundle/dist/node_modules/.pnpm/@vitest_spy@4.1.10/node_modules/@vitest/spy/dist/index.js +0 -386
- package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/chunk-pathe.M-eThtNZ.js +0 -121
- package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/constants.js +0 -51
- package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/diff.js +0 -1317
- package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/display.js +0 -561
- package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/error.js +0 -40
- package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/helpers.js +0 -272
- package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/offset.js +0 -27
- package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/serialize.js +0 -77
- package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/source-map.js +0 -381
- package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/timers.js +0 -51
- package/bundle/dist/node_modules/.pnpm/chai@6.2.2/node_modules/chai/index.js +0 -2986
- package/bundle/dist/node_modules/.pnpm/expect-type@1.3.0/node_modules/expect-type/dist/branding.js +0 -10
- package/bundle/dist/node_modules/.pnpm/expect-type@1.3.0/node_modules/expect-type/dist/index.js +0 -109
- package/bundle/dist/node_modules/.pnpm/expect-type@1.3.0/node_modules/expect-type/dist/messages.js +0 -10
- package/bundle/dist/node_modules/.pnpm/expect-type@1.3.0/node_modules/expect-type/dist/overloads.js +0 -10
- package/bundle/dist/node_modules/.pnpm/expect-type@1.3.0/node_modules/expect-type/dist/utils.js +0 -10
- package/bundle/dist/node_modules/.pnpm/magic-string@0.30.21/node_modules/magic-string/dist/magic-string.es.js +0 -1126
- package/bundle/dist/node_modules/.pnpm/pathe@2.0.3/node_modules/pathe/dist/index.js +0 -21
- package/bundle/dist/node_modules/.pnpm/pathe@2.0.3/node_modules/pathe/dist/shared/pathe.M-eThtNZ.js +0 -432
- package/bundle/dist/node_modules/.pnpm/tinybench@2.9.0/node_modules/tinybench/dist/index.js +0 -517
- package/bundle/dist/node_modules/.pnpm/tinyrainbow@3.1.0/node_modules/tinyrainbow/dist/index.js +0 -101
- package/bundle/dist/node_modules/.pnpm/vite@8.0.3_@emnapi_core@1.11.2_@emnapi_runtime@1.11.2_@types_node@25.0.7_esbuild@0.27.4_5b35fc1fb85d2af4d105e0d74f940f50/node_modules/vite/dist/node/module-runner.js +0 -1265
- package/bundle/dist/node_modules/.pnpm/vitest@4.1.10_@opentelemetry_api@1.9.0_@types_node@25.0.7_@vitest_coverage-v8@4.1.10_vi_a1977b93af7bb69308bcb1dbab39b618/node_modules/vitest/dist/chunks/_commonjsHelpers.D26ty3Ew.js +0 -9
- package/bundle/dist/node_modules/.pnpm/vitest@4.1.10_@opentelemetry_api@1.9.0_@types_node@25.0.7_@vitest_coverage-v8@4.1.10_vi_a1977b93af7bb69308bcb1dbab39b618/node_modules/vitest/dist/chunks/benchmark.CX_oY03V.js +0 -41
- package/bundle/dist/node_modules/.pnpm/vitest@4.1.10_@opentelemetry_api@1.9.0_@types_node@25.0.7_@vitest_coverage-v8@4.1.10_vi_a1977b93af7bb69308bcb1dbab39b618/node_modules/vitest/dist/chunks/evaluatedModules.Dg1zASAC.js +0 -19
- package/bundle/dist/node_modules/.pnpm/vitest@4.1.10_@opentelemetry_api@1.9.0_@types_node@25.0.7_@vitest_coverage-v8@4.1.10_vi_a1977b93af7bb69308bcb1dbab39b618/node_modules/vitest/dist/chunks/index.Chj8NDwU.js +0 -202
- package/bundle/dist/node_modules/.pnpm/vitest@4.1.10_@opentelemetry_api@1.9.0_@types_node@25.0.7_@vitest_coverage-v8@4.1.10_vi_a1977b93af7bb69308bcb1dbab39b618/node_modules/vitest/dist/chunks/index.DdgEv5B1.js +0 -46
- package/bundle/dist/node_modules/.pnpm/vitest@4.1.10_@opentelemetry_api@1.9.0_@types_node@25.0.7_@vitest_coverage-v8@4.1.10_vi_a1977b93af7bb69308bcb1dbab39b618/node_modules/vitest/dist/chunks/rpc.MzXet3jl.js +0 -119
- package/bundle/dist/node_modules/.pnpm/vitest@4.1.10_@opentelemetry_api@1.9.0_@types_node@25.0.7_@vitest_coverage-v8@4.1.10_vi_a1977b93af7bb69308bcb1dbab39b618/node_modules/vitest/dist/chunks/test.DNmyFkvJ.js +0 -3044
- package/bundle/dist/node_modules/.pnpm/vitest@4.1.10_@opentelemetry_api@1.9.0_@types_node@25.0.7_@vitest_coverage-v8@4.1.10_vi_a1977b93af7bb69308bcb1dbab39b618/node_modules/vitest/dist/chunks/utils.BX5Fg8C4.js +0 -59
- package/bundle/dist/node_modules/.pnpm/vitest@4.1.10_@opentelemetry_api@1.9.0_@types_node@25.0.7_@vitest_coverage-v8@4.1.10_vi_a1977b93af7bb69308bcb1dbab39b618/node_modules/vitest/dist/index.js +0 -28
- package/bundle/dist/testing/setup-mocks.js +0 -16
- package/bundle/src/testing/setup-mocks.ts +0 -44
- package/bundle/web-dist/client/assets/index-Bw2s88Ot.css +0 -1
- package/bundle/web-dist/client/assets/index-CrXKu_J8.js +0 -106
- package/bundle/web-dist/client/assets/logs-B2SmWJXA.js +0 -1
- package/bundle/web-dist/client/assets/monit-D-JwXXoA.js +0 -1
- package/bundle/web-dist/client/assets/plus-B62CuqT8.js +0 -1
- package/bundle/web-dist/client/assets/refresh-cw-NNcU0Cmq.js +0 -1
- package/bundle/web-dist/client/assets/request-model-CojtinqK.js +0 -1
- package/bundle/web-dist/client/assets/routes-C5r4gTvY.js +0 -5
- package/bundle/web-dist/client/assets/settings-D3tDSAck.js +0 -1
- package/bundle/web-dist/client/assets/show-Cah_kUKC.js +0 -2
- package/bundle/web-dist/client/assets/tokens-DU2Iyxxd.js +0 -1
- package/bundle/web-dist/client/assets/use-oauth-login-flow-D0UaR9_e.js +0 -1
- package/bundle/web-dist/client/assets/use-update-token-mutation-DAq0F8p-.js +0 -1
- package/bundle/web-dist/client/assets/vendor-react-DH4kUfK2.js +0 -9
- package/bundle/web-dist/client/assets/vendor-tanstack-DJRQAbrY.js +0 -1
- package/bundle/web-dist/server/assets/logs-l91avYif.js +0 -509
- package/bundle/web-dist/server/assets/plus-KZrECewT.js +0 -19
- package/bundle/web-dist/server/assets/refresh-cw-BND93JrF.js +0 -23
- package/bundle/web-dist/server/assets/settings-BZR5HSAL.js +0 -461
- package/bundle/web-dist/server/assets/tokens-D1hb4eKk.js +0 -448
- package/bundle/web-dist/server/assets/use-oauth-login-flow-Cvdy0zF8.js +0 -178
- package/dist/cli.d.ts +0 -10
- /package/bundle/web-dist/client/assets/{cost-DH2jZbrw.js → cost-DB3HbU7T.js} +0 -0
- /package/bundle/web-dist/client/assets/{preload-helper-ca-nBW7U.js → preload-helper-DWTEM3RW.js} +0 -0
- /package/bundle/web-dist/server/assets/{cost-eEHeTRT5.js → cost-BC9yzyA9.js} +0 -0
|
@@ -1,922 +0,0 @@
|
|
|
1
|
-
import { format, plugins } from "../../../../../@vitest_pretty-format@4.1.10/node_modules/@vitest/pretty-format/dist/index.js";
|
|
2
|
-
import { getCallLastIndex, isObject } from "../../../../../@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/helpers.js";
|
|
3
|
-
import { parseErrorStacktrace } from "../../../../../@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/source-map.js";
|
|
4
|
-
import { lineSplitRE, offsetToLineNumber, positionToOffset } from "../../../../../@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/offset.js";
|
|
5
|
-
//#region ../../node_modules/.pnpm/@vitest+snapshot@4.1.10/node_modules/@vitest/snapshot/dist/index.js
|
|
6
|
-
function getDefaultExportFromCjs(x) {
|
|
7
|
-
return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, "default") ? x["default"] : x;
|
|
8
|
-
}
|
|
9
|
-
var naturalCompare$1 = { exports: {} };
|
|
10
|
-
var hasRequiredNaturalCompare;
|
|
11
|
-
function requireNaturalCompare() {
|
|
12
|
-
if (hasRequiredNaturalCompare) return naturalCompare$1.exports;
|
|
13
|
-
hasRequiredNaturalCompare = 1;
|
|
14
|
-
/*
|
|
15
|
-
* @version 1.4.0
|
|
16
|
-
* @date 2015-10-26
|
|
17
|
-
* @stability 3 - Stable
|
|
18
|
-
* @author Lauri Rooden (https://github.com/litejs/natural-compare-lite)
|
|
19
|
-
* @license MIT License
|
|
20
|
-
*/
|
|
21
|
-
var naturalCompare = function(a, b) {
|
|
22
|
-
var i, codeA, codeB = 1, posA = 0, posB = 0, alphabet = String.alphabet;
|
|
23
|
-
function getCode(str, pos, code) {
|
|
24
|
-
if (code) {
|
|
25
|
-
for (i = pos; code = getCode(str, i), code < 76 && code > 65;) ++i;
|
|
26
|
-
return +str.slice(pos - 1, i);
|
|
27
|
-
}
|
|
28
|
-
code = alphabet && alphabet.indexOf(str.charAt(pos));
|
|
29
|
-
return code > -1 ? code + 76 : (code = str.charCodeAt(pos) || 0, code < 45 || code > 127) ? code : code < 46 ? 65 : code < 48 ? code - 1 : code < 58 ? code + 18 : code < 65 ? code - 11 : code < 91 ? code + 11 : code < 97 ? code - 37 : code < 123 ? code + 5 : code - 63;
|
|
30
|
-
}
|
|
31
|
-
if ((a += "") != (b += "")) for (; codeB;) {
|
|
32
|
-
codeA = getCode(a, posA++);
|
|
33
|
-
codeB = getCode(b, posB++);
|
|
34
|
-
if (codeA < 76 && codeB < 76 && codeA > 66 && codeB > 66) {
|
|
35
|
-
codeA = getCode(a, posA, posA);
|
|
36
|
-
codeB = getCode(b, posB, posA = i);
|
|
37
|
-
posB = i;
|
|
38
|
-
}
|
|
39
|
-
if (codeA != codeB) return codeA < codeB ? -1 : 1;
|
|
40
|
-
}
|
|
41
|
-
return 0;
|
|
42
|
-
};
|
|
43
|
-
try {
|
|
44
|
-
naturalCompare$1.exports = naturalCompare;
|
|
45
|
-
} catch (e) {
|
|
46
|
-
String.naturalCompare = naturalCompare;
|
|
47
|
-
}
|
|
48
|
-
return naturalCompare$1.exports;
|
|
49
|
-
}
|
|
50
|
-
var naturalCompare = /*@__PURE__*/ getDefaultExportFromCjs(requireNaturalCompare());
|
|
51
|
-
const serialize$1 = (val, config, indentation, depth, refs, printer) => {
|
|
52
|
-
const name = val.getMockName();
|
|
53
|
-
const nameString = name === "vi.fn()" ? "" : ` ${name}`;
|
|
54
|
-
let callsString = "";
|
|
55
|
-
if (val.mock.calls.length !== 0) {
|
|
56
|
-
const indentationNext = indentation + config.indent;
|
|
57
|
-
callsString = ` {${config.spacingOuter}${indentationNext}"calls": ${printer(val.mock.calls, config, indentationNext, depth, refs)}${config.min ? ", " : ","}${config.spacingOuter}${indentationNext}"results": ${printer(val.mock.results, config, indentationNext, depth, refs)}${config.min ? "" : ","}${config.spacingOuter}${indentation}}`;
|
|
58
|
-
}
|
|
59
|
-
return `[MockFunction${nameString}]${callsString}`;
|
|
60
|
-
};
|
|
61
|
-
const test = (val) => val && !!val._isMockFunction;
|
|
62
|
-
const plugin = {
|
|
63
|
-
serialize: serialize$1,
|
|
64
|
-
test
|
|
65
|
-
};
|
|
66
|
-
const { DOMCollection, DOMElement, Immutable, ReactElement, ReactTestComponent, AsymmetricMatcher } = plugins;
|
|
67
|
-
let PLUGINS = [
|
|
68
|
-
ReactTestComponent,
|
|
69
|
-
ReactElement,
|
|
70
|
-
DOMElement,
|
|
71
|
-
DOMCollection,
|
|
72
|
-
Immutable,
|
|
73
|
-
AsymmetricMatcher,
|
|
74
|
-
plugin
|
|
75
|
-
];
|
|
76
|
-
function addSerializer(plugin) {
|
|
77
|
-
PLUGINS = [plugin].concat(PLUGINS);
|
|
78
|
-
}
|
|
79
|
-
function getSerializers() {
|
|
80
|
-
return PLUGINS;
|
|
81
|
-
}
|
|
82
|
-
function testNameToKey(testName, count) {
|
|
83
|
-
return `${testName} ${count}`;
|
|
84
|
-
}
|
|
85
|
-
function keyToTestName(key) {
|
|
86
|
-
if (!/ \d+$/.test(key)) throw new Error("Snapshot keys must end with a number.");
|
|
87
|
-
return key.replace(/ \d+$/, "");
|
|
88
|
-
}
|
|
89
|
-
function getSnapshotData(content, options) {
|
|
90
|
-
const update = options.updateSnapshot;
|
|
91
|
-
const data = Object.create(null);
|
|
92
|
-
let snapshotContents = "";
|
|
93
|
-
let dirty = false;
|
|
94
|
-
if (content != null) try {
|
|
95
|
-
snapshotContents = content;
|
|
96
|
-
new Function("exports", snapshotContents)(data);
|
|
97
|
-
} catch {}
|
|
98
|
-
if ((update === "all" || update === "new") && snapshotContents) dirty = true;
|
|
99
|
-
return {
|
|
100
|
-
data,
|
|
101
|
-
dirty
|
|
102
|
-
};
|
|
103
|
-
}
|
|
104
|
-
function addExtraLineBreaks(string) {
|
|
105
|
-
return string.includes("\n") ? `\n${string}\n` : string;
|
|
106
|
-
}
|
|
107
|
-
function removeExtraLineBreaks(string) {
|
|
108
|
-
return string.length > 2 && string[0] === "\n" && string.endsWith("\n") ? string.slice(1, -1) : string;
|
|
109
|
-
}
|
|
110
|
-
const escapeRegex = true;
|
|
111
|
-
const printFunctionName = false;
|
|
112
|
-
function serialize(val, indent = 2, formatOverrides = {}) {
|
|
113
|
-
return normalizeNewlines(format(val, {
|
|
114
|
-
escapeRegex,
|
|
115
|
-
indent,
|
|
116
|
-
plugins: getSerializers(),
|
|
117
|
-
printFunctionName,
|
|
118
|
-
...formatOverrides
|
|
119
|
-
}));
|
|
120
|
-
}
|
|
121
|
-
function escapeBacktickString(str) {
|
|
122
|
-
return str.replace(/`|\\|\$\{/g, "\\$&");
|
|
123
|
-
}
|
|
124
|
-
function printBacktickString(str) {
|
|
125
|
-
return `\`${escapeBacktickString(str)}\``;
|
|
126
|
-
}
|
|
127
|
-
function normalizeNewlines(string) {
|
|
128
|
-
return string.replace(/\r\n|\r/g, "\n");
|
|
129
|
-
}
|
|
130
|
-
async function saveSnapshotFile(environment, snapshotData, snapshotPath) {
|
|
131
|
-
const snapshots = Object.keys(snapshotData).sort(naturalCompare).map((key) => `exports[${printBacktickString(key)}] = ${printBacktickString(normalizeNewlines(snapshotData[key]))};`);
|
|
132
|
-
const content = `${environment.getHeader()}\n\n${snapshots.join("\n\n")}\n`;
|
|
133
|
-
const oldContent = await environment.readSnapshotFile(snapshotPath);
|
|
134
|
-
if (oldContent != null && oldContent === content) return;
|
|
135
|
-
await environment.saveSnapshotFile(snapshotPath, content);
|
|
136
|
-
}
|
|
137
|
-
function deepMergeArray(target = [], source = []) {
|
|
138
|
-
const mergedOutput = Array.from(target);
|
|
139
|
-
source.forEach((sourceElement, index) => {
|
|
140
|
-
const targetElement = mergedOutput[index];
|
|
141
|
-
if (Array.isArray(target[index])) mergedOutput[index] = deepMergeArray(target[index], sourceElement);
|
|
142
|
-
else if (isObject(targetElement)) mergedOutput[index] = deepMergeSnapshot(target[index], sourceElement);
|
|
143
|
-
else mergedOutput[index] = sourceElement;
|
|
144
|
-
});
|
|
145
|
-
return mergedOutput;
|
|
146
|
-
}
|
|
147
|
-
/**
|
|
148
|
-
* Deep merge, but considers asymmetric matchers. Unlike base util's deep merge,
|
|
149
|
-
* will merge any object-like instance.
|
|
150
|
-
* Compatible with Jest's snapshot matcher. Should not be used outside of snapshot.
|
|
151
|
-
*
|
|
152
|
-
* @example
|
|
153
|
-
* ```ts
|
|
154
|
-
* toMatchSnapshot({
|
|
155
|
-
* name: expect.stringContaining('text')
|
|
156
|
-
* })
|
|
157
|
-
* ```
|
|
158
|
-
*/
|
|
159
|
-
function deepMergeSnapshot(target, source) {
|
|
160
|
-
if (isObject(target) && isObject(source)) {
|
|
161
|
-
const mergedOutput = { ...target };
|
|
162
|
-
Object.keys(source).forEach((key) => {
|
|
163
|
-
if (isObject(source[key]) && !source[key].$$typeof) if (!(key in target)) Object.assign(mergedOutput, { [key]: source[key] });
|
|
164
|
-
else mergedOutput[key] = deepMergeSnapshot(target[key], source[key]);
|
|
165
|
-
else if (Array.isArray(source[key])) mergedOutput[key] = deepMergeArray(target[key], source[key]);
|
|
166
|
-
else Object.assign(mergedOutput, { [key]: source[key] });
|
|
167
|
-
});
|
|
168
|
-
return mergedOutput;
|
|
169
|
-
} else if (Array.isArray(target) && Array.isArray(source)) return deepMergeArray(target, source);
|
|
170
|
-
return target;
|
|
171
|
-
}
|
|
172
|
-
var DefaultMap = class extends Map {
|
|
173
|
-
constructor(defaultFn, entries) {
|
|
174
|
-
super(entries);
|
|
175
|
-
this.defaultFn = defaultFn;
|
|
176
|
-
}
|
|
177
|
-
get(key) {
|
|
178
|
-
if (!this.has(key)) this.set(key, this.defaultFn(key));
|
|
179
|
-
return super.get(key);
|
|
180
|
-
}
|
|
181
|
-
};
|
|
182
|
-
var CounterMap = class extends DefaultMap {
|
|
183
|
-
constructor() {
|
|
184
|
-
super(() => 0);
|
|
185
|
-
}
|
|
186
|
-
_total;
|
|
187
|
-
valueOf() {
|
|
188
|
-
return this._total = this.total();
|
|
189
|
-
}
|
|
190
|
-
increment(key) {
|
|
191
|
-
if (typeof this._total !== "undefined") this._total++;
|
|
192
|
-
this.set(key, this.get(key) + 1);
|
|
193
|
-
}
|
|
194
|
-
total() {
|
|
195
|
-
if (typeof this._total !== "undefined") return this._total;
|
|
196
|
-
let total = 0;
|
|
197
|
-
for (const x of this.values()) total += x;
|
|
198
|
-
return total;
|
|
199
|
-
}
|
|
200
|
-
};
|
|
201
|
-
/* @__NO_SIDE_EFFECTS__ */
|
|
202
|
-
function memo(fn) {
|
|
203
|
-
const cache = /* @__PURE__ */ new Map();
|
|
204
|
-
return (arg) => {
|
|
205
|
-
if (!cache.has(arg)) cache.set(arg, fn(arg));
|
|
206
|
-
return cache.get(arg);
|
|
207
|
-
};
|
|
208
|
-
}
|
|
209
|
-
async function saveInlineSnapshots(environment, snapshots) {
|
|
210
|
-
const MagicString = (await import("../../../../../magic-string@0.30.21/node_modules/magic-string/dist/magic-string.es.js")).default;
|
|
211
|
-
const files = new Set(snapshots.map((i) => i.file));
|
|
212
|
-
await Promise.all(Array.from(files).map(async (file) => {
|
|
213
|
-
const snaps = snapshots.filter((i) => i.file === file);
|
|
214
|
-
const code = await environment.readSnapshotFile(file);
|
|
215
|
-
if (code == null) throw new Error(`cannot read ${file} when saving inline snapshot`);
|
|
216
|
-
const s = new MagicString(code);
|
|
217
|
-
for (const snap of snaps) replaceInlineSnap(code, s, positionToOffset(code, snap.line, snap.column), snap.snapshot, snap.assertionName);
|
|
218
|
-
const transformed = s.toString();
|
|
219
|
-
if (transformed !== code) await environment.saveSnapshotFile(file, transformed);
|
|
220
|
-
}));
|
|
221
|
-
}
|
|
222
|
-
const defaultStartObjectRegex = /(?:toMatchInlineSnapshot|toThrowErrorMatchingInlineSnapshot)\s*\(\s*(?:\/\*[\s\S]*\*\/\s*|\/\/.*(?:[\n\r\u2028\u2029]\s*|[\t\v\f \xA0\u1680\u2000-\u200A\u202F\u205F\u3000\uFEFF]))*\{/;
|
|
223
|
-
function escapeRegExp(s) {
|
|
224
|
-
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
225
|
-
}
|
|
226
|
-
const buildStartObjectRegex = /* @__PURE__ */ memo((assertionName) => {
|
|
227
|
-
const replaced = defaultStartObjectRegex.source.replace("toMatchInlineSnapshot|toThrowErrorMatchingInlineSnapshot", escapeRegExp(assertionName));
|
|
228
|
-
return new RegExp(replaced);
|
|
229
|
-
});
|
|
230
|
-
function replaceObjectSnap(code, s, index, newSnap, assertionName) {
|
|
231
|
-
let _code = code.slice(index);
|
|
232
|
-
const startMatch = (assertionName ? buildStartObjectRegex(assertionName) : defaultStartObjectRegex).exec(_code);
|
|
233
|
-
if (!startMatch) return false;
|
|
234
|
-
_code = _code.slice(startMatch.index);
|
|
235
|
-
let callEnd = getCallLastIndex(_code);
|
|
236
|
-
if (callEnd === null) return false;
|
|
237
|
-
callEnd += index + startMatch.index;
|
|
238
|
-
const shapeEnd = getObjectShapeEndIndex(code, index + startMatch.index + startMatch[0].length);
|
|
239
|
-
const snap = `, ${prepareSnapString(newSnap, code, index)}`;
|
|
240
|
-
if (shapeEnd === callEnd) s.appendLeft(callEnd, snap);
|
|
241
|
-
else s.overwrite(shapeEnd, callEnd, snap);
|
|
242
|
-
return true;
|
|
243
|
-
}
|
|
244
|
-
function getObjectShapeEndIndex(code, index) {
|
|
245
|
-
let startBraces = 1;
|
|
246
|
-
let endBraces = 0;
|
|
247
|
-
while (startBraces !== endBraces && index < code.length) {
|
|
248
|
-
const s = code[index++];
|
|
249
|
-
if (s === "{") startBraces++;
|
|
250
|
-
else if (s === "}") endBraces++;
|
|
251
|
-
}
|
|
252
|
-
return index;
|
|
253
|
-
}
|
|
254
|
-
function prepareSnapString(snap, source, index) {
|
|
255
|
-
const lineNumber = offsetToLineNumber(source, index);
|
|
256
|
-
const indent = source.split(lineSplitRE)[lineNumber - 1].match(/^\s*/)[0] || "";
|
|
257
|
-
const indentNext = indent.includes(" ") ? `${indent}\t` : `${indent} `;
|
|
258
|
-
const lines = snap.trim().replace(/\\/g, "\\\\").split(/\n/g);
|
|
259
|
-
const isOneline = lines.length <= 1;
|
|
260
|
-
const quote = "`";
|
|
261
|
-
if (isOneline) return `${quote}${lines.join("\n").replace(/`/g, "\\`").replace(/\$\{/g, "\\${")}${quote}`;
|
|
262
|
-
return `${quote}\n${lines.map((i) => i ? indentNext + i : "").join("\n").replace(/`/g, "\\`").replace(/\$\{/g, "\\${")}\n${indent}${quote}`;
|
|
263
|
-
}
|
|
264
|
-
const defaultMethodNames = ["toMatchInlineSnapshot", "toThrowErrorMatchingInlineSnapshot"];
|
|
265
|
-
function getCodeStartingAtIndex(code, index, methodNames) {
|
|
266
|
-
for (const name of methodNames) {
|
|
267
|
-
const adjusted = index - name.length;
|
|
268
|
-
if (adjusted >= 0 && code.slice(adjusted, index) === name) return {
|
|
269
|
-
code: code.slice(adjusted),
|
|
270
|
-
index: adjusted
|
|
271
|
-
};
|
|
272
|
-
}
|
|
273
|
-
return {
|
|
274
|
-
code: code.slice(index),
|
|
275
|
-
index
|
|
276
|
-
};
|
|
277
|
-
}
|
|
278
|
-
const defaultStartRegex = /(?:toMatchInlineSnapshot|toThrowErrorMatchingInlineSnapshot)\s*\(\s*(?:\/\*[\s\S]*\*\/\s*|\/\/.*(?:[\n\r\u2028\u2029]\s*|[\t\v\f \xA0\u1680\u2000-\u200A\u202F\u205F\u3000\uFEFF]))*[\w$]*(['"`)])/;
|
|
279
|
-
const buildStartRegex = /* @__PURE__ */ memo((assertionName) => {
|
|
280
|
-
const replaced = defaultStartRegex.source.replace("toMatchInlineSnapshot|toThrowErrorMatchingInlineSnapshot", escapeRegExp(assertionName));
|
|
281
|
-
return new RegExp(replaced);
|
|
282
|
-
});
|
|
283
|
-
function replaceInlineSnap(code, s, currentIndex, newSnap, assertionName) {
|
|
284
|
-
const { code: codeStartingAtIndex, index } = getCodeStartingAtIndex(code, currentIndex, assertionName ? [assertionName] : defaultMethodNames);
|
|
285
|
-
const startMatch = (assertionName ? buildStartRegex(assertionName) : defaultStartRegex).exec(codeStartingAtIndex);
|
|
286
|
-
const firstKeywordMatch = (assertionName ? new RegExp(escapeRegExp(assertionName)) : /toMatchInlineSnapshot|toThrowErrorMatchingInlineSnapshot/).exec(codeStartingAtIndex);
|
|
287
|
-
if (!startMatch || startMatch.index !== firstKeywordMatch?.index) return replaceObjectSnap(code, s, index, newSnap, assertionName);
|
|
288
|
-
const quote = startMatch[1];
|
|
289
|
-
const startIndex = index + startMatch.index + startMatch[0].length;
|
|
290
|
-
const snapString = prepareSnapString(newSnap, code, index);
|
|
291
|
-
if (quote === ")") {
|
|
292
|
-
s.appendRight(startIndex - 1, snapString);
|
|
293
|
-
return true;
|
|
294
|
-
}
|
|
295
|
-
const endMatch = new RegExp(`(?:^|[^\\\\])${quote}`).exec(code.slice(startIndex));
|
|
296
|
-
if (!endMatch) return false;
|
|
297
|
-
const endIndex = startIndex + endMatch.index + endMatch[0].length;
|
|
298
|
-
s.overwrite(startIndex - 1, endIndex, snapString);
|
|
299
|
-
return true;
|
|
300
|
-
}
|
|
301
|
-
const INDENTATION_REGEX = /^([^\S\n]*)\S/m;
|
|
302
|
-
function stripSnapshotIndentation(inlineSnapshot) {
|
|
303
|
-
const match = inlineSnapshot.match(INDENTATION_REGEX);
|
|
304
|
-
if (!match || !match[1]) return inlineSnapshot;
|
|
305
|
-
const indentation = match[1];
|
|
306
|
-
const lines = inlineSnapshot.split(/\n/g);
|
|
307
|
-
if (lines.length <= 2) return inlineSnapshot;
|
|
308
|
-
if (lines[0].trim() !== "" || lines.at(-1)?.trim() !== "") return inlineSnapshot;
|
|
309
|
-
for (let i = 1; i < lines.length - 1; i++) if (lines[i] !== "") {
|
|
310
|
-
if (lines[i].indexOf(indentation) !== 0) return inlineSnapshot;
|
|
311
|
-
lines[i] = lines[i].substring(indentation.length);
|
|
312
|
-
}
|
|
313
|
-
lines[lines.length - 1] = "";
|
|
314
|
-
inlineSnapshot = lines.join("\n");
|
|
315
|
-
return inlineSnapshot;
|
|
316
|
-
}
|
|
317
|
-
async function saveRawSnapshots(environment, snapshots) {
|
|
318
|
-
await Promise.all(snapshots.map(async (snap) => {
|
|
319
|
-
if (!snap.readonly) await environment.saveSnapshotFile(snap.file, snap.snapshot);
|
|
320
|
-
}));
|
|
321
|
-
}
|
|
322
|
-
function isSameStackPosition(x, y) {
|
|
323
|
-
return x.file === y.file && x.column === y.column && x.line === y.line;
|
|
324
|
-
}
|
|
325
|
-
var SnapshotState = class SnapshotState {
|
|
326
|
-
_counters = new CounterMap();
|
|
327
|
-
_dirty;
|
|
328
|
-
_updateSnapshot;
|
|
329
|
-
_snapshotData;
|
|
330
|
-
_initialData;
|
|
331
|
-
_inlineSnapshots;
|
|
332
|
-
_inlineSnapshotStacks;
|
|
333
|
-
_testIdToKeys = new DefaultMap(() => []);
|
|
334
|
-
_rawSnapshots;
|
|
335
|
-
_uncheckedKeys;
|
|
336
|
-
_snapshotFormat;
|
|
337
|
-
_environment;
|
|
338
|
-
_fileExists;
|
|
339
|
-
expand;
|
|
340
|
-
_added = new CounterMap();
|
|
341
|
-
_matched = new CounterMap();
|
|
342
|
-
_unmatched = new CounterMap();
|
|
343
|
-
_updated = new CounterMap();
|
|
344
|
-
get added() {
|
|
345
|
-
return this._added;
|
|
346
|
-
}
|
|
347
|
-
set added(value) {
|
|
348
|
-
this._added._total = value;
|
|
349
|
-
}
|
|
350
|
-
get matched() {
|
|
351
|
-
return this._matched;
|
|
352
|
-
}
|
|
353
|
-
set matched(value) {
|
|
354
|
-
this._matched._total = value;
|
|
355
|
-
}
|
|
356
|
-
get unmatched() {
|
|
357
|
-
return this._unmatched;
|
|
358
|
-
}
|
|
359
|
-
set unmatched(value) {
|
|
360
|
-
this._unmatched._total = value;
|
|
361
|
-
}
|
|
362
|
-
get updated() {
|
|
363
|
-
return this._updated;
|
|
364
|
-
}
|
|
365
|
-
set updated(value) {
|
|
366
|
-
this._updated._total = value;
|
|
367
|
-
}
|
|
368
|
-
constructor(testFilePath, snapshotPath, snapshotContent, options) {
|
|
369
|
-
this.testFilePath = testFilePath;
|
|
370
|
-
this.snapshotPath = snapshotPath;
|
|
371
|
-
const { data, dirty } = getSnapshotData(snapshotContent, options);
|
|
372
|
-
this._fileExists = snapshotContent != null;
|
|
373
|
-
this._initialData = { ...data };
|
|
374
|
-
this._snapshotData = { ...data };
|
|
375
|
-
this._dirty = dirty;
|
|
376
|
-
this._inlineSnapshots = [];
|
|
377
|
-
this._inlineSnapshotStacks = [];
|
|
378
|
-
this._rawSnapshots = [];
|
|
379
|
-
this._uncheckedKeys = new Set(Object.keys(this._snapshotData));
|
|
380
|
-
this.expand = options.expand || false;
|
|
381
|
-
this._updateSnapshot = options.updateSnapshot;
|
|
382
|
-
this._snapshotFormat = {
|
|
383
|
-
printBasicPrototype: false,
|
|
384
|
-
escapeString: false,
|
|
385
|
-
maxOutputLength: 2 ** 27,
|
|
386
|
-
...options.snapshotFormat
|
|
387
|
-
};
|
|
388
|
-
this._environment = options.snapshotEnvironment;
|
|
389
|
-
}
|
|
390
|
-
static async create(testFilePath, options) {
|
|
391
|
-
const snapshotPath = await options.snapshotEnvironment.resolvePath(testFilePath);
|
|
392
|
-
const content = await options.snapshotEnvironment.readSnapshotFile(snapshotPath);
|
|
393
|
-
return new SnapshotState(testFilePath, snapshotPath, content, options);
|
|
394
|
-
}
|
|
395
|
-
get snapshotUpdateState() {
|
|
396
|
-
return this._updateSnapshot;
|
|
397
|
-
}
|
|
398
|
-
get environment() {
|
|
399
|
-
return this._environment;
|
|
400
|
-
}
|
|
401
|
-
markSnapshotsAsCheckedForTest(testName) {
|
|
402
|
-
this._uncheckedKeys.forEach((uncheckedKey) => {
|
|
403
|
-
if (/ \d+$| > /.test(uncheckedKey.slice(testName.length))) this._uncheckedKeys.delete(uncheckedKey);
|
|
404
|
-
});
|
|
405
|
-
}
|
|
406
|
-
clearTest(testId) {
|
|
407
|
-
this._inlineSnapshots = this._inlineSnapshots.filter((s) => s.testId !== testId);
|
|
408
|
-
this._inlineSnapshotStacks = this._inlineSnapshotStacks.filter((s) => s.testId !== testId);
|
|
409
|
-
for (const key of this._testIdToKeys.get(testId)) {
|
|
410
|
-
const name = keyToTestName(key);
|
|
411
|
-
const count = this._counters.get(name);
|
|
412
|
-
if (count > 0) {
|
|
413
|
-
if (key in this._snapshotData || key in this._initialData) this._snapshotData[key] = this._initialData[key];
|
|
414
|
-
this._counters.set(name, count - 1);
|
|
415
|
-
}
|
|
416
|
-
}
|
|
417
|
-
this._testIdToKeys.delete(testId);
|
|
418
|
-
this.added.delete(testId);
|
|
419
|
-
this.updated.delete(testId);
|
|
420
|
-
this.matched.delete(testId);
|
|
421
|
-
this.unmatched.delete(testId);
|
|
422
|
-
}
|
|
423
|
-
_inferInlineSnapshotStack(stacks) {
|
|
424
|
-
const promiseIndex = stacks.findIndex((i) => i.method.match(/__VITEST_(RESOLVES|REJECTS)__/));
|
|
425
|
-
if (promiseIndex !== -1) return stacks[promiseIndex + 3];
|
|
426
|
-
const pollChainIndex = stacks.findIndex((i) => i.method.match(/__VITEST_POLL_CHAIN__/));
|
|
427
|
-
if (pollChainIndex !== -1) return stacks[pollChainIndex + 1];
|
|
428
|
-
for (let i = 0; i < stacks.length; i++) {
|
|
429
|
-
const match = stacks[i].method.match(/__INLINE_SNAPSHOT_OFFSET_(\d+)__/);
|
|
430
|
-
if (match) return stacks[i + Number(match[1])] ?? null;
|
|
431
|
-
}
|
|
432
|
-
const customMatcherIndex = stacks.findIndex((i) => i.method.includes("__VITEST_EXTEND_ASSERTION__"));
|
|
433
|
-
if (customMatcherIndex !== -1) return stacks[customMatcherIndex + 3] ?? null;
|
|
434
|
-
const stackIndex = stacks.findIndex((i) => i.method.includes("__INLINE_SNAPSHOT__"));
|
|
435
|
-
return stackIndex !== -1 ? stacks[stackIndex + 2] : null;
|
|
436
|
-
}
|
|
437
|
-
_addSnapshot(key, receivedSerialized, options) {
|
|
438
|
-
this._dirty = true;
|
|
439
|
-
if (options.stack) this._inlineSnapshots.push({
|
|
440
|
-
...options.stack,
|
|
441
|
-
snapshot: receivedSerialized,
|
|
442
|
-
testId: options.testId,
|
|
443
|
-
assertionName: options.assertionName
|
|
444
|
-
});
|
|
445
|
-
else if (options.rawSnapshot) this._rawSnapshots.push({
|
|
446
|
-
...options.rawSnapshot,
|
|
447
|
-
snapshot: receivedSerialized
|
|
448
|
-
});
|
|
449
|
-
else this._snapshotData[key] = receivedSerialized;
|
|
450
|
-
}
|
|
451
|
-
_resolveKey(testId, testName, key) {
|
|
452
|
-
this._counters.increment(testName);
|
|
453
|
-
const count = this._counters.get(testName);
|
|
454
|
-
if (!key) key = testNameToKey(testName, count);
|
|
455
|
-
this._testIdToKeys.get(testId).push(key);
|
|
456
|
-
return {
|
|
457
|
-
key,
|
|
458
|
-
count
|
|
459
|
-
};
|
|
460
|
-
}
|
|
461
|
-
_resolveInlineStack(options) {
|
|
462
|
-
const { testId, snapshot, assertionName, error } = options;
|
|
463
|
-
const stacks = parseErrorStacktrace(error, { ignoreStackEntries: [] });
|
|
464
|
-
const _stack = this._inferInlineSnapshotStack(stacks);
|
|
465
|
-
if (!_stack) {
|
|
466
|
-
const message = stacks.map((s) => ` ${s.file}:${s.line}:${s.column}${s.method ? ` (${s.method})` : ""}`).join("\n");
|
|
467
|
-
throw new Error(`@vitest/snapshot: Couldn't infer stack frame for inline snapshot.\n${message}`);
|
|
468
|
-
}
|
|
469
|
-
const stack = this.environment.processStackTrace?.(_stack) || _stack;
|
|
470
|
-
stack.column--;
|
|
471
|
-
const snapshotsWithSameStack = this._inlineSnapshotStacks.filter((s) => isSameStackPosition(s, stack));
|
|
472
|
-
if (snapshotsWithSameStack.length > 0) {
|
|
473
|
-
this._inlineSnapshots = this._inlineSnapshots.filter((s) => !isSameStackPosition(s, stack));
|
|
474
|
-
const differentSnapshot = snapshotsWithSameStack.find((s) => s.snapshot !== snapshot);
|
|
475
|
-
if (differentSnapshot) throw Object.assign(/* @__PURE__ */ new Error(`${assertionName} with different snapshots cannot be called at the same location`), {
|
|
476
|
-
actual: snapshot,
|
|
477
|
-
expected: differentSnapshot.snapshot
|
|
478
|
-
});
|
|
479
|
-
}
|
|
480
|
-
this._inlineSnapshotStacks.push({
|
|
481
|
-
...stack,
|
|
482
|
-
testId,
|
|
483
|
-
snapshot
|
|
484
|
-
});
|
|
485
|
-
return stack;
|
|
486
|
-
}
|
|
487
|
-
_reconcile(opts) {
|
|
488
|
-
if (opts.hasSnapshot && this._updateSnapshot === "all" || (!opts.hasSnapshot || !opts.snapshotIsPersisted) && (this._updateSnapshot === "new" || this._updateSnapshot === "all")) {
|
|
489
|
-
if (this._updateSnapshot === "all") if (!opts.pass) {
|
|
490
|
-
if (opts.hasSnapshot) this.updated.increment(opts.testId);
|
|
491
|
-
else this.added.increment(opts.testId);
|
|
492
|
-
this._addSnapshot(opts.key, opts.addValue, {
|
|
493
|
-
stack: opts.stack,
|
|
494
|
-
testId: opts.testId,
|
|
495
|
-
rawSnapshot: opts.rawSnapshot,
|
|
496
|
-
assertionName: opts.assertionName
|
|
497
|
-
});
|
|
498
|
-
} else this.matched.increment(opts.testId);
|
|
499
|
-
else {
|
|
500
|
-
this._addSnapshot(opts.key, opts.addValue, {
|
|
501
|
-
stack: opts.stack,
|
|
502
|
-
testId: opts.testId,
|
|
503
|
-
rawSnapshot: opts.rawSnapshot,
|
|
504
|
-
assertionName: opts.assertionName
|
|
505
|
-
});
|
|
506
|
-
this.added.increment(opts.testId);
|
|
507
|
-
}
|
|
508
|
-
return {
|
|
509
|
-
actual: "",
|
|
510
|
-
count: opts.count,
|
|
511
|
-
expected: "",
|
|
512
|
-
key: opts.key,
|
|
513
|
-
pass: true
|
|
514
|
-
};
|
|
515
|
-
} else if (!opts.pass) {
|
|
516
|
-
this.unmatched.increment(opts.testId);
|
|
517
|
-
return {
|
|
518
|
-
actual: opts.actualDisplay,
|
|
519
|
-
count: opts.count,
|
|
520
|
-
expected: opts.expectedDisplay,
|
|
521
|
-
key: opts.key,
|
|
522
|
-
pass: false
|
|
523
|
-
};
|
|
524
|
-
} else {
|
|
525
|
-
this.matched.increment(opts.testId);
|
|
526
|
-
return {
|
|
527
|
-
actual: "",
|
|
528
|
-
count: opts.count,
|
|
529
|
-
expected: "",
|
|
530
|
-
key: opts.key,
|
|
531
|
-
pass: true
|
|
532
|
-
};
|
|
533
|
-
}
|
|
534
|
-
}
|
|
535
|
-
async save() {
|
|
536
|
-
const hasExternalSnapshots = Object.keys(this._snapshotData).length;
|
|
537
|
-
const hasInlineSnapshots = this._inlineSnapshots.length;
|
|
538
|
-
const hasRawSnapshots = this._rawSnapshots.length;
|
|
539
|
-
const isEmpty = !hasExternalSnapshots && !hasInlineSnapshots && !hasRawSnapshots;
|
|
540
|
-
const status = {
|
|
541
|
-
deleted: false,
|
|
542
|
-
saved: false
|
|
543
|
-
};
|
|
544
|
-
if ((this._dirty || this._uncheckedKeys.size) && !isEmpty) {
|
|
545
|
-
if (hasExternalSnapshots) {
|
|
546
|
-
await saveSnapshotFile(this._environment, this._snapshotData, this.snapshotPath);
|
|
547
|
-
this._fileExists = true;
|
|
548
|
-
}
|
|
549
|
-
if (hasInlineSnapshots) await saveInlineSnapshots(this._environment, this._inlineSnapshots);
|
|
550
|
-
if (hasRawSnapshots) await saveRawSnapshots(this._environment, this._rawSnapshots);
|
|
551
|
-
status.saved = true;
|
|
552
|
-
} else if (!hasExternalSnapshots && this._fileExists) {
|
|
553
|
-
if (this._updateSnapshot === "all") {
|
|
554
|
-
await this._environment.removeSnapshotFile(this.snapshotPath);
|
|
555
|
-
this._fileExists = false;
|
|
556
|
-
}
|
|
557
|
-
status.deleted = true;
|
|
558
|
-
}
|
|
559
|
-
return status;
|
|
560
|
-
}
|
|
561
|
-
getUncheckedCount() {
|
|
562
|
-
return this._uncheckedKeys.size || 0;
|
|
563
|
-
}
|
|
564
|
-
getUncheckedKeys() {
|
|
565
|
-
return Array.from(this._uncheckedKeys);
|
|
566
|
-
}
|
|
567
|
-
removeUncheckedKeys() {
|
|
568
|
-
if (this._updateSnapshot === "all" && this._uncheckedKeys.size) {
|
|
569
|
-
this._dirty = true;
|
|
570
|
-
this._uncheckedKeys.forEach((key) => delete this._snapshotData[key]);
|
|
571
|
-
this._uncheckedKeys.clear();
|
|
572
|
-
}
|
|
573
|
-
}
|
|
574
|
-
probeExpectedSnapshot(options) {
|
|
575
|
-
const count = this._counters.get(options.testName) + 1;
|
|
576
|
-
const key = testNameToKey(options.testName, count);
|
|
577
|
-
return {
|
|
578
|
-
key,
|
|
579
|
-
count,
|
|
580
|
-
data: options?.isInline ? options.inlineSnapshot : this._snapshotData[key],
|
|
581
|
-
markAsChecked: () => {
|
|
582
|
-
this._counters.increment(options.testName);
|
|
583
|
-
this._testIdToKeys.get(options.testId).push(key);
|
|
584
|
-
this._uncheckedKeys.delete(key);
|
|
585
|
-
}
|
|
586
|
-
};
|
|
587
|
-
}
|
|
588
|
-
match({ testId, testName, received, key, inlineSnapshot, isInline, error, rawSnapshot, assertionName }) {
|
|
589
|
-
const resolved = this._resolveKey(testId, testName, key);
|
|
590
|
-
key = resolved.key;
|
|
591
|
-
const count = resolved.count;
|
|
592
|
-
if (!(isInline && this._snapshotData[key] !== void 0)) this._uncheckedKeys.delete(key);
|
|
593
|
-
let receivedSerialized = rawSnapshot && typeof received === "string" ? received : serialize(received, void 0, this._snapshotFormat);
|
|
594
|
-
if (!rawSnapshot) receivedSerialized = addExtraLineBreaks(receivedSerialized);
|
|
595
|
-
if (rawSnapshot) {
|
|
596
|
-
if (rawSnapshot.content && rawSnapshot.content.match(/\r\n/) && !receivedSerialized.match(/\r\n/)) rawSnapshot.content = normalizeNewlines(rawSnapshot.content);
|
|
597
|
-
}
|
|
598
|
-
const expected = isInline ? inlineSnapshot : rawSnapshot ? rawSnapshot.content : this._snapshotData[key];
|
|
599
|
-
const expectedTrimmed = rawSnapshot ? expected : expected?.trim();
|
|
600
|
-
const pass = expectedTrimmed === (rawSnapshot ? receivedSerialized : receivedSerialized.trim());
|
|
601
|
-
const hasSnapshot = expected !== void 0;
|
|
602
|
-
const snapshotIsPersisted = isInline || this._fileExists || rawSnapshot && rawSnapshot.content != null;
|
|
603
|
-
if (pass && !isInline && !rawSnapshot) this._snapshotData[key] = receivedSerialized;
|
|
604
|
-
const stack = isInline ? this._resolveInlineStack({
|
|
605
|
-
testId,
|
|
606
|
-
snapshot: receivedSerialized,
|
|
607
|
-
assertionName: assertionName || "toMatchInlineSnapshot",
|
|
608
|
-
error: error || /* @__PURE__ */ new Error("snapshot")
|
|
609
|
-
}) : void 0;
|
|
610
|
-
return this._reconcile({
|
|
611
|
-
testId,
|
|
612
|
-
key,
|
|
613
|
-
count,
|
|
614
|
-
pass,
|
|
615
|
-
hasSnapshot,
|
|
616
|
-
snapshotIsPersisted: !!snapshotIsPersisted,
|
|
617
|
-
addValue: receivedSerialized,
|
|
618
|
-
actualDisplay: rawSnapshot ? receivedSerialized : removeExtraLineBreaks(receivedSerialized),
|
|
619
|
-
expectedDisplay: expectedTrimmed !== void 0 ? rawSnapshot ? expectedTrimmed : removeExtraLineBreaks(expectedTrimmed) : void 0,
|
|
620
|
-
stack,
|
|
621
|
-
rawSnapshot,
|
|
622
|
-
assertionName
|
|
623
|
-
});
|
|
624
|
-
}
|
|
625
|
-
processDomainSnapshot({ testId, received, expectedSnapshot, matchResult, isInline, error, assertionName }) {
|
|
626
|
-
const stack = isInline ? this._resolveInlineStack({
|
|
627
|
-
testId,
|
|
628
|
-
snapshot: received,
|
|
629
|
-
assertionName,
|
|
630
|
-
error: error || /* @__PURE__ */ new Error("STACK_TRACE_ERROR")
|
|
631
|
-
}) : void 0;
|
|
632
|
-
const actualResolved = matchResult?.resolved ?? received;
|
|
633
|
-
const expectedResolved = matchResult?.expected ?? expectedSnapshot.data;
|
|
634
|
-
return this._reconcile({
|
|
635
|
-
testId,
|
|
636
|
-
key: expectedSnapshot.key,
|
|
637
|
-
count: expectedSnapshot.count,
|
|
638
|
-
pass: matchResult?.pass ?? false,
|
|
639
|
-
hasSnapshot: !!expectedSnapshot.data,
|
|
640
|
-
snapshotIsPersisted: isInline ? true : this._fileExists,
|
|
641
|
-
addValue: actualResolved,
|
|
642
|
-
actualDisplay: removeExtraLineBreaks(actualResolved),
|
|
643
|
-
expectedDisplay: expectedResolved !== void 0 ? removeExtraLineBreaks(expectedResolved) : void 0,
|
|
644
|
-
stack,
|
|
645
|
-
assertionName
|
|
646
|
-
});
|
|
647
|
-
}
|
|
648
|
-
async pack() {
|
|
649
|
-
const snapshot = {
|
|
650
|
-
filepath: this.testFilePath,
|
|
651
|
-
added: 0,
|
|
652
|
-
fileDeleted: false,
|
|
653
|
-
matched: 0,
|
|
654
|
-
unchecked: 0,
|
|
655
|
-
uncheckedKeys: [],
|
|
656
|
-
unmatched: 0,
|
|
657
|
-
updated: 0
|
|
658
|
-
};
|
|
659
|
-
const uncheckedCount = this.getUncheckedCount();
|
|
660
|
-
const uncheckedKeys = this.getUncheckedKeys();
|
|
661
|
-
if (uncheckedCount) this.removeUncheckedKeys();
|
|
662
|
-
const status = await this.save();
|
|
663
|
-
snapshot.fileDeleted = status.deleted;
|
|
664
|
-
snapshot.added = this.added.total();
|
|
665
|
-
snapshot.matched = this.matched.total();
|
|
666
|
-
snapshot.unmatched = this.unmatched.total();
|
|
667
|
-
snapshot.updated = this.updated.total();
|
|
668
|
-
snapshot.unchecked = !status.deleted ? uncheckedCount : 0;
|
|
669
|
-
snapshot.uncheckedKeys = Array.from(uncheckedKeys);
|
|
670
|
-
return snapshot;
|
|
671
|
-
}
|
|
672
|
-
};
|
|
673
|
-
function createMismatchError(message, expand, actual, expected) {
|
|
674
|
-
const error = new Error(message);
|
|
675
|
-
Object.defineProperty(error, "actual", {
|
|
676
|
-
value: actual,
|
|
677
|
-
enumerable: true,
|
|
678
|
-
configurable: true,
|
|
679
|
-
writable: true
|
|
680
|
-
});
|
|
681
|
-
Object.defineProperty(error, "expected", {
|
|
682
|
-
value: expected,
|
|
683
|
-
enumerable: true,
|
|
684
|
-
configurable: true,
|
|
685
|
-
writable: true
|
|
686
|
-
});
|
|
687
|
-
Object.defineProperty(error, "diffOptions", { value: { expand } });
|
|
688
|
-
return error;
|
|
689
|
-
}
|
|
690
|
-
var SnapshotClient = class {
|
|
691
|
-
snapshotStateMap = /* @__PURE__ */ new Map();
|
|
692
|
-
constructor(options = {}) {
|
|
693
|
-
this.options = options;
|
|
694
|
-
}
|
|
695
|
-
async setup(filepath, options) {
|
|
696
|
-
if (this.snapshotStateMap.has(filepath)) return;
|
|
697
|
-
this.snapshotStateMap.set(filepath, await SnapshotState.create(filepath, options));
|
|
698
|
-
}
|
|
699
|
-
async finish(filepath) {
|
|
700
|
-
const result = await this.getSnapshotState(filepath).pack();
|
|
701
|
-
this.snapshotStateMap.delete(filepath);
|
|
702
|
-
return result;
|
|
703
|
-
}
|
|
704
|
-
skipTest(filepath, testName) {
|
|
705
|
-
this.getSnapshotState(filepath).markSnapshotsAsCheckedForTest(testName);
|
|
706
|
-
}
|
|
707
|
-
clearTest(filepath, testId) {
|
|
708
|
-
this.getSnapshotState(filepath).clearTest(testId);
|
|
709
|
-
}
|
|
710
|
-
getSnapshotState(filepath) {
|
|
711
|
-
const state = this.snapshotStateMap.get(filepath);
|
|
712
|
-
if (!state) throw new Error(`The snapshot state for '${filepath}' is not found. Did you call 'SnapshotClient.setup()'?`);
|
|
713
|
-
return state;
|
|
714
|
-
}
|
|
715
|
-
match(options) {
|
|
716
|
-
const { filepath, name, testId = name, message, isInline = false, properties, inlineSnapshot, error, errorMessage, rawSnapshot, assertionName } = options;
|
|
717
|
-
let { received } = options;
|
|
718
|
-
if (!filepath) throw new Error("Snapshot cannot be used outside of test");
|
|
719
|
-
const snapshotState = this.getSnapshotState(filepath);
|
|
720
|
-
const testName = [name, ...message ? [message] : []].join(" > ");
|
|
721
|
-
const expectedSnapshot = snapshotState.probeExpectedSnapshot({
|
|
722
|
-
testName,
|
|
723
|
-
testId,
|
|
724
|
-
isInline,
|
|
725
|
-
inlineSnapshot
|
|
726
|
-
});
|
|
727
|
-
if (typeof properties === "object") {
|
|
728
|
-
if (typeof received !== "object" || !received) {
|
|
729
|
-
expectedSnapshot.markAsChecked();
|
|
730
|
-
throw new Error("Received value must be an object when the matcher has properties");
|
|
731
|
-
}
|
|
732
|
-
let propertiesPass;
|
|
733
|
-
try {
|
|
734
|
-
propertiesPass = this.options.isEqual?.(received, properties) ?? false;
|
|
735
|
-
} catch (err) {
|
|
736
|
-
expectedSnapshot.markAsChecked();
|
|
737
|
-
throw err;
|
|
738
|
-
}
|
|
739
|
-
if (!propertiesPass) {
|
|
740
|
-
expectedSnapshot.markAsChecked();
|
|
741
|
-
return {
|
|
742
|
-
pass: false,
|
|
743
|
-
message: () => errorMessage || "Snapshot properties mismatched",
|
|
744
|
-
actual: received,
|
|
745
|
-
expected: properties
|
|
746
|
-
};
|
|
747
|
-
}
|
|
748
|
-
received = deepMergeSnapshot(received, properties);
|
|
749
|
-
}
|
|
750
|
-
const { actual, expected, key, pass } = snapshotState.match({
|
|
751
|
-
testId,
|
|
752
|
-
testName,
|
|
753
|
-
received,
|
|
754
|
-
isInline,
|
|
755
|
-
error,
|
|
756
|
-
inlineSnapshot,
|
|
757
|
-
rawSnapshot,
|
|
758
|
-
assertionName
|
|
759
|
-
});
|
|
760
|
-
return {
|
|
761
|
-
pass,
|
|
762
|
-
message: () => `Snapshot \`${key || "unknown"}\` mismatched`,
|
|
763
|
-
actual: rawSnapshot ? actual : actual?.trim(),
|
|
764
|
-
expected: rawSnapshot ? expected : expected?.trim()
|
|
765
|
-
};
|
|
766
|
-
}
|
|
767
|
-
assert(options) {
|
|
768
|
-
const result = this.match(options);
|
|
769
|
-
if (!result.pass) {
|
|
770
|
-
const snapshotState = this.getSnapshotState(options.filepath);
|
|
771
|
-
throw createMismatchError(result.message(), snapshotState.expand, result.actual, result.expected);
|
|
772
|
-
}
|
|
773
|
-
}
|
|
774
|
-
matchDomain(options) {
|
|
775
|
-
const { received, filepath, name, testId = name, message, adapter, isInline = false, inlineSnapshot, error } = options;
|
|
776
|
-
if (!filepath) throw new Error("Snapshot cannot be used outside of test");
|
|
777
|
-
const captured = adapter.capture(received);
|
|
778
|
-
const rendered = adapter.render(captured);
|
|
779
|
-
const snapshotState = this.getSnapshotState(filepath);
|
|
780
|
-
const testName = [name, ...message ? [message] : []].join(" > ");
|
|
781
|
-
const expectedSnapshot = snapshotState.probeExpectedSnapshot({
|
|
782
|
-
testName,
|
|
783
|
-
testId,
|
|
784
|
-
isInline,
|
|
785
|
-
inlineSnapshot
|
|
786
|
-
});
|
|
787
|
-
expectedSnapshot.markAsChecked();
|
|
788
|
-
const matchResult = expectedSnapshot.data ? adapter.match(captured, adapter.parseExpected(expectedSnapshot.data)) : void 0;
|
|
789
|
-
const { actual, expected, key, pass } = snapshotState.processDomainSnapshot({
|
|
790
|
-
testId,
|
|
791
|
-
received: rendered,
|
|
792
|
-
expectedSnapshot,
|
|
793
|
-
matchResult,
|
|
794
|
-
isInline,
|
|
795
|
-
error,
|
|
796
|
-
assertionName: options.assertionName
|
|
797
|
-
});
|
|
798
|
-
return {
|
|
799
|
-
pass,
|
|
800
|
-
message: () => `Snapshot \`${key}\` mismatched`,
|
|
801
|
-
actual: actual?.trim(),
|
|
802
|
-
expected: expected?.trim()
|
|
803
|
-
};
|
|
804
|
-
}
|
|
805
|
-
async pollMatchDomain(options) {
|
|
806
|
-
const { poll, filepath, name, testId = name, message, adapter, isInline = false, inlineSnapshot, error, timeout = 1e3, interval = 50 } = options;
|
|
807
|
-
if (!filepath) throw new Error("Snapshot cannot be used outside of test");
|
|
808
|
-
const snapshotState = this.getSnapshotState(filepath);
|
|
809
|
-
const testName = [name, ...message ? [message] : []].join(" > ");
|
|
810
|
-
const expectedSnapshot = snapshotState.probeExpectedSnapshot({
|
|
811
|
-
testName,
|
|
812
|
-
testId,
|
|
813
|
-
isInline,
|
|
814
|
-
inlineSnapshot
|
|
815
|
-
});
|
|
816
|
-
const reference = expectedSnapshot.data && snapshotState.snapshotUpdateState !== "all" ? adapter.parseExpected(expectedSnapshot.data) : void 0;
|
|
817
|
-
const stableResult = await getStableSnapshot({
|
|
818
|
-
adapter,
|
|
819
|
-
poll,
|
|
820
|
-
interval,
|
|
821
|
-
timedOut: timeout > 0 ? new Promise((r) => setTimeout(r, timeout)) : void 0,
|
|
822
|
-
match: reference ? (captured) => adapter.match(captured, reference).pass : void 0
|
|
823
|
-
});
|
|
824
|
-
expectedSnapshot.markAsChecked();
|
|
825
|
-
if (!stableResult?.rendered) {
|
|
826
|
-
if (stableResult?.lastPollError) throw stableResult.lastPollError;
|
|
827
|
-
return {
|
|
828
|
-
pass: false,
|
|
829
|
-
message: () => `poll() did not produce a stable snapshot within the timeout`
|
|
830
|
-
};
|
|
831
|
-
}
|
|
832
|
-
const matchResult = expectedSnapshot.data ? adapter.match(stableResult.captured, adapter.parseExpected(expectedSnapshot.data)) : void 0;
|
|
833
|
-
const { actual, expected, key, pass } = snapshotState.processDomainSnapshot({
|
|
834
|
-
testId,
|
|
835
|
-
received: stableResult.rendered,
|
|
836
|
-
expectedSnapshot,
|
|
837
|
-
matchResult,
|
|
838
|
-
isInline,
|
|
839
|
-
error,
|
|
840
|
-
assertionName: options.assertionName
|
|
841
|
-
});
|
|
842
|
-
return {
|
|
843
|
-
pass,
|
|
844
|
-
message: () => `Snapshot \`${key}\` mismatched`,
|
|
845
|
-
actual: actual?.trim(),
|
|
846
|
-
expected: expected?.trim()
|
|
847
|
-
};
|
|
848
|
-
}
|
|
849
|
-
async assertRaw(options) {
|
|
850
|
-
if (!options.rawSnapshot) throw new Error("Raw snapshot is required");
|
|
851
|
-
const { filepath, rawSnapshot } = options;
|
|
852
|
-
if (rawSnapshot.content == null) {
|
|
853
|
-
if (!filepath) throw new Error("Snapshot cannot be used outside of test");
|
|
854
|
-
const snapshotState = this.getSnapshotState(filepath);
|
|
855
|
-
options.filepath ||= filepath;
|
|
856
|
-
rawSnapshot.file = await snapshotState.environment.resolveRawPath(filepath, rawSnapshot.file);
|
|
857
|
-
rawSnapshot.content = await snapshotState.environment.readSnapshotFile(rawSnapshot.file) ?? void 0;
|
|
858
|
-
}
|
|
859
|
-
return this.assert(options);
|
|
860
|
-
}
|
|
861
|
-
clear() {
|
|
862
|
-
this.snapshotStateMap.clear();
|
|
863
|
-
}
|
|
864
|
-
};
|
|
865
|
-
/**
|
|
866
|
-
* Polls repeatedly until the value reaches a stable state.
|
|
867
|
-
*
|
|
868
|
-
* Compares consecutive rendered outputs from the current session —
|
|
869
|
-
* when two consecutive polls produce the same rendered string,
|
|
870
|
-
* the value is considered stable.
|
|
871
|
-
*
|
|
872
|
-
* Every `await` (poll call, interval delay) races against `timedOut`
|
|
873
|
-
* so that hanging polls and delays are interrupted.
|
|
874
|
-
*/
|
|
875
|
-
async function getStableSnapshot({ adapter, poll, interval, timedOut, match }) {
|
|
876
|
-
let lastRendered;
|
|
877
|
-
let lastPollError;
|
|
878
|
-
let lastStable;
|
|
879
|
-
while (true) {
|
|
880
|
-
try {
|
|
881
|
-
const pollResult = await raceWith(Promise.resolve(poll()), timedOut);
|
|
882
|
-
if (!pollResult.ok) break;
|
|
883
|
-
const captured = adapter.capture(pollResult.value);
|
|
884
|
-
const rendered = adapter.render(captured);
|
|
885
|
-
if (lastRendered !== void 0 && rendered === lastRendered) {
|
|
886
|
-
lastStable = {
|
|
887
|
-
captured,
|
|
888
|
-
rendered
|
|
889
|
-
};
|
|
890
|
-
if (!match || match(captured)) break;
|
|
891
|
-
} else {
|
|
892
|
-
lastRendered = rendered;
|
|
893
|
-
lastStable = void 0;
|
|
894
|
-
}
|
|
895
|
-
} catch (pollError) {
|
|
896
|
-
lastRendered = void 0;
|
|
897
|
-
lastStable = void 0;
|
|
898
|
-
lastPollError = pollError;
|
|
899
|
-
}
|
|
900
|
-
if (!(await raceWith(new Promise((r) => setTimeout(r, interval)), timedOut)).ok) break;
|
|
901
|
-
}
|
|
902
|
-
return {
|
|
903
|
-
...lastStable,
|
|
904
|
-
lastPollError
|
|
905
|
-
};
|
|
906
|
-
}
|
|
907
|
-
/** Type-safe `Promise.race` — tells you which promise won. */
|
|
908
|
-
function raceWith(promise, other) {
|
|
909
|
-
const left = promise.then((value) => ({
|
|
910
|
-
ok: true,
|
|
911
|
-
value
|
|
912
|
-
}));
|
|
913
|
-
if (!other) return left;
|
|
914
|
-
return Promise.race([left, other.then((value) => ({
|
|
915
|
-
ok: false,
|
|
916
|
-
value
|
|
917
|
-
}))]);
|
|
918
|
-
}
|
|
919
|
-
//#endregion
|
|
920
|
-
export { SnapshotClient, SnapshotState, addSerializer, getSerializers, stripSnapshotIndentation };
|
|
921
|
-
|
|
922
|
-
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJuYW1lcyI6W10sInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vbm9kZV9tb2R1bGVzLy5wbnBtL0B2aXRlc3Qrc25hcHNob3RANC4xLjEwL25vZGVfbW9kdWxlcy9Adml0ZXN0L3NuYXBzaG90L2Rpc3QvaW5kZXguanMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgcGFyc2VFcnJvclN0YWNrdHJhY2UgfSBmcm9tICdAdml0ZXN0L3V0aWxzL3NvdXJjZS1tYXAnO1xuaW1wb3J0IHsgaXNPYmplY3QsIGdldENhbGxMYXN0SW5kZXggfSBmcm9tICdAdml0ZXN0L3V0aWxzL2hlbHBlcnMnO1xuaW1wb3J0IHsgcG9zaXRpb25Ub09mZnNldCwgb2Zmc2V0VG9MaW5lTnVtYmVyLCBsaW5lU3BsaXRSRSB9IGZyb20gJ0B2aXRlc3QvdXRpbHMvb2Zmc2V0JztcbmltcG9ydCB7IHBsdWdpbnMsIGZvcm1hdCB9IGZyb20gJ0B2aXRlc3QvcHJldHR5LWZvcm1hdCc7XG5cbmZ1bmN0aW9uIGdldERlZmF1bHRFeHBvcnRGcm9tQ2pzKHgpIHtcblx0cmV0dXJuIHggJiYgeC5fX2VzTW9kdWxlICYmIE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbCh4LCBcImRlZmF1bHRcIikgPyB4W1wiZGVmYXVsdFwiXSA6IHg7XG59XG5cbnZhciBuYXR1cmFsQ29tcGFyZSQxID0ge2V4cG9ydHM6IHt9fTtcblxudmFyIGhhc1JlcXVpcmVkTmF0dXJhbENvbXBhcmU7XG5cbmZ1bmN0aW9uIHJlcXVpcmVOYXR1cmFsQ29tcGFyZSAoKSB7XG5cdGlmIChoYXNSZXF1aXJlZE5hdHVyYWxDb21wYXJlKSByZXR1cm4gbmF0dXJhbENvbXBhcmUkMS5leHBvcnRzO1xuXHRoYXNSZXF1aXJlZE5hdHVyYWxDb21wYXJlID0gMTtcblx0Lypcblx0ICogQHZlcnNpb24gICAgMS40LjBcblx0ICogQGRhdGUgICAgICAgMjAxNS0xMC0yNlxuXHQgKiBAc3RhYmlsaXR5ICAzIC0gU3RhYmxlXG5cdCAqIEBhdXRob3IgICAgIExhdXJpIFJvb2RlbiAoaHR0cHM6Ly9naXRodWIuY29tL2xpdGVqcy9uYXR1cmFsLWNvbXBhcmUtbGl0ZSlcblx0ICogQGxpY2Vuc2UgICAgTUlUIExpY2Vuc2Vcblx0ICovXG5cblxuXHR2YXIgbmF0dXJhbENvbXBhcmUgPSBmdW5jdGlvbihhLCBiKSB7XG5cdFx0dmFyIGksIGNvZGVBXG5cdFx0LCBjb2RlQiA9IDFcblx0XHQsIHBvc0EgPSAwXG5cdFx0LCBwb3NCID0gMFxuXHRcdCwgYWxwaGFiZXQgPSBTdHJpbmcuYWxwaGFiZXQ7XG5cblx0XHRmdW5jdGlvbiBnZXRDb2RlKHN0ciwgcG9zLCBjb2RlKSB7XG5cdFx0XHRpZiAoY29kZSkge1xuXHRcdFx0XHRmb3IgKGkgPSBwb3M7IGNvZGUgPSBnZXRDb2RlKHN0ciwgaSksIGNvZGUgPCA3NiAmJiBjb2RlID4gNjU7KSArK2k7XG5cdFx0XHRcdHJldHVybiArc3RyLnNsaWNlKHBvcyAtIDEsIGkpXG5cdFx0XHR9XG5cdFx0XHRjb2RlID0gYWxwaGFiZXQgJiYgYWxwaGFiZXQuaW5kZXhPZihzdHIuY2hhckF0KHBvcykpO1xuXHRcdFx0cmV0dXJuIGNvZGUgPiAtMSA/IGNvZGUgKyA3NiA6ICgoY29kZSA9IHN0ci5jaGFyQ29kZUF0KHBvcykgfHwgMCksIGNvZGUgPCA0NSB8fCBjb2RlID4gMTI3KSA/IGNvZGVcblx0XHRcdFx0OiBjb2RlIDwgNDYgPyA2NSAgICAgICAgICAgICAgIC8vIC1cblx0XHRcdFx0OiBjb2RlIDwgNDggPyBjb2RlIC0gMVxuXHRcdFx0XHQ6IGNvZGUgPCA1OCA/IGNvZGUgKyAxOCAgICAgICAgLy8gMC05XG5cdFx0XHRcdDogY29kZSA8IDY1ID8gY29kZSAtIDExXG5cdFx0XHRcdDogY29kZSA8IDkxID8gY29kZSArIDExICAgICAgICAvLyBBLVpcblx0XHRcdFx0OiBjb2RlIDwgOTcgPyBjb2RlIC0gMzdcblx0XHRcdFx0OiBjb2RlIDwgMTIzID8gY29kZSArIDUgICAgICAgIC8vIGEtelxuXHRcdFx0XHQ6IGNvZGUgLSA2M1xuXHRcdH1cblxuXG5cdFx0aWYgKChhKz1cIlwiKSAhPSAoYis9XCJcIikpIGZvciAoO2NvZGVCOykge1xuXHRcdFx0Y29kZUEgPSBnZXRDb2RlKGEsIHBvc0ErKyk7XG5cdFx0XHRjb2RlQiA9IGdldENvZGUoYiwgcG9zQisrKTtcblxuXHRcdFx0aWYgKGNvZGVBIDwgNzYgJiYgY29kZUIgPCA3NiAmJiBjb2RlQSA+IDY2ICYmIGNvZGVCID4gNjYpIHtcblx0XHRcdFx0Y29kZUEgPSBnZXRDb2RlKGEsIHBvc0EsIHBvc0EpO1xuXHRcdFx0XHRjb2RlQiA9IGdldENvZGUoYiwgcG9zQiwgcG9zQSA9IGkpO1xuXHRcdFx0XHRwb3NCID0gaTtcblx0XHRcdH1cblxuXHRcdFx0aWYgKGNvZGVBICE9IGNvZGVCKSByZXR1cm4gKGNvZGVBIDwgY29kZUIpID8gLTEgOiAxXG5cdFx0fVxuXHRcdHJldHVybiAwXG5cdH07XG5cblx0dHJ5IHtcblx0XHRuYXR1cmFsQ29tcGFyZSQxLmV4cG9ydHMgPSBuYXR1cmFsQ29tcGFyZTtcblx0fSBjYXRjaCAoZSkge1xuXHRcdFN0cmluZy5uYXR1cmFsQ29tcGFyZSA9IG5hdHVyYWxDb21wYXJlO1xuXHR9XG5cdHJldHVybiBuYXR1cmFsQ29tcGFyZSQxLmV4cG9ydHM7XG59XG5cbnZhciBuYXR1cmFsQ29tcGFyZUV4cG9ydHMgPSByZXF1aXJlTmF0dXJhbENvbXBhcmUoKTtcbnZhciBuYXR1cmFsQ29tcGFyZSA9IC8qQF9fUFVSRV9fKi9nZXREZWZhdWx0RXhwb3J0RnJvbUNqcyhuYXR1cmFsQ29tcGFyZUV4cG9ydHMpO1xuXG5jb25zdCBzZXJpYWxpemUkMSA9ICh2YWwsIGNvbmZpZywgaW5kZW50YXRpb24sIGRlcHRoLCByZWZzLCBwcmludGVyKSA9PiB7XG5cdC8vIFNlcmlhbGl6ZSBhIG5vbi1kZWZhdWx0IG5hbWUsIGV2ZW4gaWYgY29uZmlnLnByaW50RnVuY3Rpb25OYW1lIGlzIGZhbHNlLlxuXHRjb25zdCBuYW1lID0gdmFsLmdldE1vY2tOYW1lKCk7XG5cdGNvbnN0IG5hbWVTdHJpbmcgPSBuYW1lID09PSBcInZpLmZuKClcIiA/IFwiXCIgOiBgICR7bmFtZX1gO1xuXHRsZXQgY2FsbHNTdHJpbmcgPSBcIlwiO1xuXHRpZiAodmFsLm1vY2suY2FsbHMubGVuZ3RoICE9PSAwKSB7XG5cdFx0Y29uc3QgaW5kZW50YXRpb25OZXh0ID0gaW5kZW50YXRpb24gKyBjb25maWcuaW5kZW50O1xuXHRcdGNhbGxzU3RyaW5nID0gYCB7JHtjb25maWcuc3BhY2luZ091dGVyfSR7aW5kZW50YXRpb25OZXh0fVwiY2FsbHNcIjogJHtwcmludGVyKHZhbC5tb2NrLmNhbGxzLCBjb25maWcsIGluZGVudGF0aW9uTmV4dCwgZGVwdGgsIHJlZnMpfSR7Y29uZmlnLm1pbiA/IFwiLCBcIiA6IFwiLFwifSR7Y29uZmlnLnNwYWNpbmdPdXRlcn0ke2luZGVudGF0aW9uTmV4dH1cInJlc3VsdHNcIjogJHtwcmludGVyKHZhbC5tb2NrLnJlc3VsdHMsIGNvbmZpZywgaW5kZW50YXRpb25OZXh0LCBkZXB0aCwgcmVmcyl9JHtjb25maWcubWluID8gXCJcIiA6IFwiLFwifSR7Y29uZmlnLnNwYWNpbmdPdXRlcn0ke2luZGVudGF0aW9ufX1gO1xuXHR9XG5cdHJldHVybiBgW01vY2tGdW5jdGlvbiR7bmFtZVN0cmluZ31dJHtjYWxsc1N0cmluZ31gO1xufTtcbmNvbnN0IHRlc3QgPSAodmFsKSA9PiB2YWwgJiYgISF2YWwuX2lzTW9ja0Z1bmN0aW9uO1xuY29uc3QgcGx1Z2luID0ge1xuXHRzZXJpYWxpemU6IHNlcmlhbGl6ZSQxLFxuXHR0ZXN0XG59O1xuXG5jb25zdCB7IERPTUNvbGxlY3Rpb24sIERPTUVsZW1lbnQsIEltbXV0YWJsZSwgUmVhY3RFbGVtZW50LCBSZWFjdFRlc3RDb21wb25lbnQsIEFzeW1tZXRyaWNNYXRjaGVyIH0gPSBwbHVnaW5zO1xubGV0IFBMVUdJTlMgPSBbXG5cdFJlYWN0VGVzdENvbXBvbmVudCxcblx0UmVhY3RFbGVtZW50LFxuXHRET01FbGVtZW50LFxuXHRET01Db2xsZWN0aW9uLFxuXHRJbW11dGFibGUsXG5cdEFzeW1tZXRyaWNNYXRjaGVyLFxuXHRwbHVnaW5cbl07XG5mdW5jdGlvbiBhZGRTZXJpYWxpemVyKHBsdWdpbikge1xuXHRQTFVHSU5TID0gW3BsdWdpbl0uY29uY2F0KFBMVUdJTlMpO1xufVxuZnVuY3Rpb24gZ2V0U2VyaWFsaXplcnMoKSB7XG5cdHJldHVybiBQTFVHSU5TO1xufVxuXG4vLyBUT0RPOiByZXdyaXRlIGFuZCBjbGVhbiB1cFxuZnVuY3Rpb24gdGVzdE5hbWVUb0tleSh0ZXN0TmFtZSwgY291bnQpIHtcblx0cmV0dXJuIGAke3Rlc3ROYW1lfSAke2NvdW50fWA7XG59XG5mdW5jdGlvbiBrZXlUb1Rlc3ROYW1lKGtleSkge1xuXHRpZiAoIS8gXFxkKyQvLnRlc3Qoa2V5KSkge1xuXHRcdHRocm93IG5ldyBFcnJvcihcIlNuYXBzaG90IGtleXMgbXVzdCBlbmQgd2l0aCBhIG51bWJlci5cIik7XG5cdH1cblx0cmV0dXJuIGtleS5yZXBsYWNlKC8gXFxkKyQvLCBcIlwiKTtcbn1cbmZ1bmN0aW9uIGdldFNuYXBzaG90RGF0YShjb250ZW50LCBvcHRpb25zKSB7XG5cdGNvbnN0IHVwZGF0ZSA9IG9wdGlvbnMudXBkYXRlU25hcHNob3Q7XG5cdGNvbnN0IGRhdGEgPSBPYmplY3QuY3JlYXRlKG51bGwpO1xuXHRsZXQgc25hcHNob3RDb250ZW50cyA9IFwiXCI7XG5cdGxldCBkaXJ0eSA9IGZhbHNlO1xuXHRpZiAoY29udGVudCAhPSBudWxsKSB7XG5cdFx0dHJ5IHtcblx0XHRcdHNuYXBzaG90Q29udGVudHMgPSBjb250ZW50O1xuXHRcdFx0Ly8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLW5ldy1mdW5jXG5cdFx0XHRjb25zdCBwb3B1bGF0ZSA9IG5ldyBGdW5jdGlvbihcImV4cG9ydHNcIiwgc25hcHNob3RDb250ZW50cyk7XG5cdFx0XHRwb3B1bGF0ZShkYXRhKTtcblx0XHR9IGNhdGNoIHt9XG5cdH1cblx0Ly8gY29uc3QgdmFsaWRhdGlvblJlc3VsdCA9IHZhbGlkYXRlU25hcHNob3RWZXJzaW9uKHNuYXBzaG90Q29udGVudHMpXG5cdGNvbnN0IGlzSW52YWxpZCA9IHNuYXBzaG90Q29udGVudHM7XG5cdC8vIGlmICh1cGRhdGUgPT09ICdub25lJyAmJiBpc0ludmFsaWQpXG5cdC8vICAgdGhyb3cgdmFsaWRhdGlvblJlc3VsdFxuXHRpZiAoKHVwZGF0ZSA9PT0gXCJhbGxcIiB8fCB1cGRhdGUgPT09IFwibmV3XCIpICYmIGlzSW52YWxpZCkge1xuXHRcdGRpcnR5ID0gdHJ1ZTtcblx0fVxuXHRyZXR1cm4ge1xuXHRcdGRhdGEsXG5cdFx0ZGlydHlcblx0fTtcbn1cbi8vIEFkZCBleHRyYSBsaW5lIGJyZWFrcyBhdCBiZWdpbm5pbmcgYW5kIGVuZCBvZiBtdWx0aWxpbmUgc25hcHNob3Rcbi8vIHRvIG1ha2UgdGhlIGNvbnRlbnQgZWFzaWVyIHRvIHJlYWQuXG5mdW5jdGlvbiBhZGRFeHRyYUxpbmVCcmVha3Moc3RyaW5nKSB7XG5cdHJldHVybiBzdHJpbmcuaW5jbHVkZXMoXCJcXG5cIikgPyBgXFxuJHtzdHJpbmd9XFxuYCA6IHN0cmluZztcbn1cbi8vIFJlbW92ZSBleHRyYSBsaW5lIGJyZWFrcyBhdCBiZWdpbm5pbmcgYW5kIGVuZCBvZiBtdWx0aWxpbmUgc25hcHNob3QuXG4vLyBJbnN0ZWFkIG9mIHRyaW0sIHdoaWNoIGNhbiByZW1vdmUgYWRkaXRpb25hbCBuZXdsaW5lcyBvciBzcGFjZXNcbi8vIGF0IGJlZ2lubmluZyBvciBlbmQgb2YgdGhlIGNvbnRlbnQgZnJvbSBhIGN1c3RvbSBzZXJpYWxpemVyLlxuZnVuY3Rpb24gcmVtb3ZlRXh0cmFMaW5lQnJlYWtzKHN0cmluZykge1xuXHRyZXR1cm4gc3RyaW5nLmxlbmd0aCA+IDIgJiYgc3RyaW5nWzBdID09PSBcIlxcblwiICYmIHN0cmluZy5lbmRzV2l0aChcIlxcblwiKSA/IHN0cmluZy5zbGljZSgxLCAtMSkgOiBzdHJpbmc7XG59XG4vLyBleHBvcnQgY29uc3QgcmVtb3ZlTGluZXNCZWZvcmVFeHRlcm5hbE1hdGNoZXJUcmFwID0gKHN0YWNrOiBzdHJpbmcpOiBzdHJpbmcgPT4ge1xuLy8gICBjb25zdCBsaW5lcyA9IHN0YWNrLnNwbGl0KCdcXG4nKVxuLy8gICBmb3IgKGxldCBpID0gMDsgaSA8IGxpbmVzLmxlbmd0aDsgaSArPSAxKSB7XG4vLyAgICAgLy8gSXQncyBhIGZ1bmN0aW9uIG5hbWUgc3BlY2lmaWVkIGluIGBwYWNrYWdlcy9leHBlY3Qvc3JjL2luZGV4LnRzYFxuLy8gICAgIC8vIGZvciBleHRlcm5hbCBjdXN0b20gbWF0Y2hlcnMuXG4vLyAgICAgaWYgKGxpbmVzW2ldLmluY2x1ZGVzKCdfX0VYVEVSTkFMX01BVENIRVJfVFJBUF9fJykpXG4vLyAgICAgICByZXR1cm4gbGluZXMuc2xpY2UoaSArIDEpLmpvaW4oJ1xcbicpXG4vLyAgIH1cbi8vICAgcmV0dXJuIHN0YWNrXG4vLyB9XG5jb25zdCBlc2NhcGVSZWdleCA9IHRydWU7XG5jb25zdCBwcmludEZ1bmN0aW9uTmFtZSA9IGZhbHNlO1xuZnVuY3Rpb24gc2VyaWFsaXplKHZhbCwgaW5kZW50ID0gMiwgZm9ybWF0T3ZlcnJpZGVzID0ge30pIHtcblx0cmV0dXJuIG5vcm1hbGl6ZU5ld2xpbmVzKGZvcm1hdCh2YWwsIHtcblx0XHRlc2NhcGVSZWdleCxcblx0XHRpbmRlbnQsXG5cdFx0cGx1Z2luczogZ2V0U2VyaWFsaXplcnMoKSxcblx0XHRwcmludEZ1bmN0aW9uTmFtZSxcblx0XHQuLi5mb3JtYXRPdmVycmlkZXNcblx0fSkpO1xufVxuZnVuY3Rpb24gZXNjYXBlQmFja3RpY2tTdHJpbmcoc3RyKSB7XG5cdHJldHVybiBzdHIucmVwbGFjZSgvYHxcXFxcfFxcJFxcey9nLCBcIlxcXFwkJlwiKTtcbn1cbmZ1bmN0aW9uIHByaW50QmFja3RpY2tTdHJpbmcoc3RyKSB7XG5cdHJldHVybiBgXFxgJHtlc2NhcGVCYWNrdGlja1N0cmluZyhzdHIpfVxcYGA7XG59XG5mdW5jdGlvbiBub3JtYWxpemVOZXdsaW5lcyhzdHJpbmcpIHtcblx0cmV0dXJuIHN0cmluZy5yZXBsYWNlKC9cXHJcXG58XFxyL2csIFwiXFxuXCIpO1xufVxuYXN5bmMgZnVuY3Rpb24gc2F2ZVNuYXBzaG90RmlsZShlbnZpcm9ubWVudCwgc25hcHNob3REYXRhLCBzbmFwc2hvdFBhdGgpIHtcblx0Y29uc3Qgc25hcHNob3RzID0gT2JqZWN0LmtleXMoc25hcHNob3REYXRhKS5zb3J0KG5hdHVyYWxDb21wYXJlKS5tYXAoKGtleSkgPT4gYGV4cG9ydHNbJHtwcmludEJhY2t0aWNrU3RyaW5nKGtleSl9XSA9ICR7cHJpbnRCYWNrdGlja1N0cmluZyhub3JtYWxpemVOZXdsaW5lcyhzbmFwc2hvdERhdGFba2V5XSkpfTtgKTtcblx0Y29uc3QgY29udGVudCA9IGAke2Vudmlyb25tZW50LmdldEhlYWRlcigpfVxcblxcbiR7c25hcHNob3RzLmpvaW4oXCJcXG5cXG5cIil9XFxuYDtcblx0Y29uc3Qgb2xkQ29udGVudCA9IGF3YWl0IGVudmlyb25tZW50LnJlYWRTbmFwc2hvdEZpbGUoc25hcHNob3RQYXRoKTtcblx0Y29uc3Qgc2tpcFdyaXRpbmcgPSBvbGRDb250ZW50ICE9IG51bGwgJiYgb2xkQ29udGVudCA9PT0gY29udGVudDtcblx0aWYgKHNraXBXcml0aW5nKSB7XG5cdFx0cmV0dXJuO1xuXHR9XG5cdGF3YWl0IGVudmlyb25tZW50LnNhdmVTbmFwc2hvdEZpbGUoc25hcHNob3RQYXRoLCBjb250ZW50KTtcbn1cbmZ1bmN0aW9uIGRlZXBNZXJnZUFycmF5KHRhcmdldCA9IFtdLCBzb3VyY2UgPSBbXSkge1xuXHRjb25zdCBtZXJnZWRPdXRwdXQgPSBBcnJheS5mcm9tKHRhcmdldCk7XG5cdHNvdXJjZS5mb3JFYWNoKChzb3VyY2VFbGVtZW50LCBpbmRleCkgPT4ge1xuXHRcdGNvbnN0IHRhcmdldEVsZW1lbnQgPSBtZXJnZWRPdXRwdXRbaW5kZXhdO1xuXHRcdGlmIChBcnJheS5pc0FycmF5KHRhcmdldFtpbmRleF0pKSB7XG5cdFx0XHRtZXJnZWRPdXRwdXRbaW5kZXhdID0gZGVlcE1lcmdlQXJyYXkodGFyZ2V0W2luZGV4XSwgc291cmNlRWxlbWVudCk7XG5cdFx0fSBlbHNlIGlmIChpc09iamVjdCh0YXJnZXRFbGVtZW50KSkge1xuXHRcdFx0bWVyZ2VkT3V0cHV0W2luZGV4XSA9IGRlZXBNZXJnZVNuYXBzaG90KHRhcmdldFtpbmRleF0sIHNvdXJjZUVsZW1lbnQpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHQvLyBTb3VyY2UgZG9lcyBub3QgZXhpc3QgaW4gdGFyZ2V0IG9yIHRhcmdldCBpcyBwcmltaXRpdmUgYW5kIGNhbm5vdCBiZSBkZWVwIG1lcmdlZFxuXHRcdFx0bWVyZ2VkT3V0cHV0W2luZGV4XSA9IHNvdXJjZUVsZW1lbnQ7XG5cdFx0fVxuXHR9KTtcblx0cmV0dXJuIG1lcmdlZE91dHB1dDtcbn1cbi8qKlxuKiBEZWVwIG1lcmdlLCBidXQgY29uc2lkZXJzIGFzeW1tZXRyaWMgbWF0Y2hlcnMuIFVubGlrZSBiYXNlIHV0aWwncyBkZWVwIG1lcmdlLFxuKiB3aWxsIG1lcmdlIGFueSBvYmplY3QtbGlrZSBpbnN0YW5jZS5cbiogQ29tcGF0aWJsZSB3aXRoIEplc3QncyBzbmFwc2hvdCBtYXRjaGVyLiBTaG91bGQgbm90IGJlIHVzZWQgb3V0c2lkZSBvZiBzbmFwc2hvdC5cbipcbiogQGV4YW1wbGVcbiogYGBgdHNcbiogdG9NYXRjaFNuYXBzaG90KHtcbiogICBuYW1lOiBleHBlY3Quc3RyaW5nQ29udGFpbmluZygndGV4dCcpXG4qIH0pXG4qIGBgYFxuKi9cbmZ1bmN0aW9uIGRlZXBNZXJnZVNuYXBzaG90KHRhcmdldCwgc291cmNlKSB7XG5cdGlmIChpc09iamVjdCh0YXJnZXQpICYmIGlzT2JqZWN0KHNvdXJjZSkpIHtcblx0XHRjb25zdCBtZXJnZWRPdXRwdXQgPSB7IC4uLnRhcmdldCB9O1xuXHRcdE9iamVjdC5rZXlzKHNvdXJjZSkuZm9yRWFjaCgoa2V5KSA9PiB7XG5cdFx0XHRpZiAoaXNPYmplY3Qoc291cmNlW2tleV0pICYmICFzb3VyY2Vba2V5XS4kJHR5cGVvZikge1xuXHRcdFx0XHRpZiAoIShrZXkgaW4gdGFyZ2V0KSkge1xuXHRcdFx0XHRcdE9iamVjdC5hc3NpZ24obWVyZ2VkT3V0cHV0LCB7IFtrZXldOiBzb3VyY2Vba2V5XSB9KTtcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRtZXJnZWRPdXRwdXRba2V5XSA9IGRlZXBNZXJnZVNuYXBzaG90KHRhcmdldFtrZXldLCBzb3VyY2Vba2V5XSk7XG5cdFx0XHRcdH1cblx0XHRcdH0gZWxzZSBpZiAoQXJyYXkuaXNBcnJheShzb3VyY2Vba2V5XSkpIHtcblx0XHRcdFx0bWVyZ2VkT3V0cHV0W2tleV0gPSBkZWVwTWVyZ2VBcnJheSh0YXJnZXRba2V5XSwgc291cmNlW2tleV0pO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0T2JqZWN0LmFzc2lnbihtZXJnZWRPdXRwdXQsIHsgW2tleV06IHNvdXJjZVtrZXldIH0pO1xuXHRcdFx0fVxuXHRcdH0pO1xuXHRcdHJldHVybiBtZXJnZWRPdXRwdXQ7XG5cdH0gZWxzZSBpZiAoQXJyYXkuaXNBcnJheSh0YXJnZXQpICYmIEFycmF5LmlzQXJyYXkoc291cmNlKSkge1xuXHRcdHJldHVybiBkZWVwTWVyZ2VBcnJheSh0YXJnZXQsIHNvdXJjZSk7XG5cdH1cblx0cmV0dXJuIHRhcmdldDtcbn1cbmNsYXNzIERlZmF1bHRNYXAgZXh0ZW5kcyBNYXAge1xuXHRjb25zdHJ1Y3RvcihkZWZhdWx0Rm4sIGVudHJpZXMpIHtcblx0XHRzdXBlcihlbnRyaWVzKTtcblx0XHR0aGlzLmRlZmF1bHRGbiA9IGRlZmF1bHRGbjtcblx0fVxuXHRnZXQoa2V5KSB7XG5cdFx0aWYgKCF0aGlzLmhhcyhrZXkpKSB7XG5cdFx0XHR0aGlzLnNldChrZXksIHRoaXMuZGVmYXVsdEZuKGtleSkpO1xuXHRcdH1cblx0XHRyZXR1cm4gc3VwZXIuZ2V0KGtleSk7XG5cdH1cbn1cbmNsYXNzIENvdW50ZXJNYXAgZXh0ZW5kcyBEZWZhdWx0TWFwIHtcblx0Y29uc3RydWN0b3IoKSB7XG5cdFx0c3VwZXIoKCkgPT4gMCk7XG5cdH1cblx0Ly8gY29tcGF0IGZvciBqZXN0LWltYWdlLXNuYXBzaG90IGh0dHBzOi8vZ2l0aHViLmNvbS92aXRlc3QtZGV2L3ZpdGVzdC9pc3N1ZXMvNzMyMlxuXHQvLyBgdmFsdWVPZmAgYW5kIGBTbmFwc2hvdC5hZGRlZGAgc2V0dGVyIGFsbG93c1xuXHQvLyAgIHNuYXBzaG90U3RhdGUuYWRkZWQgPSBzbmFwc2hvdFN0YXRlLmFkZGVkICsgMVxuXHQvLyB0byBmdW5jdGlvbiBhc1xuXHQvLyAgIHNuYXBzaG90U3RhdGUuYWRkZWQudG90YWxfID0gc25hcHNob3RTdGF0ZS5hZGRlZC50b3RhbCgpICsgMVxuXHRfdG90YWw7XG5cdHZhbHVlT2YoKSB7XG5cdFx0cmV0dXJuIHRoaXMuX3RvdGFsID0gdGhpcy50b3RhbCgpO1xuXHR9XG5cdGluY3JlbWVudChrZXkpIHtcblx0XHRpZiAodHlwZW9mIHRoaXMuX3RvdGFsICE9PSBcInVuZGVmaW5lZFwiKSB7XG5cdFx0XHR0aGlzLl90b3RhbCsrO1xuXHRcdH1cblx0XHR0aGlzLnNldChrZXksIHRoaXMuZ2V0KGtleSkgKyAxKTtcblx0fVxuXHR0b3RhbCgpIHtcblx0XHRpZiAodHlwZW9mIHRoaXMuX3RvdGFsICE9PSBcInVuZGVmaW5lZFwiKSB7XG5cdFx0XHRyZXR1cm4gdGhpcy5fdG90YWw7XG5cdFx0fVxuXHRcdGxldCB0b3RhbCA9IDA7XG5cdFx0Zm9yIChjb25zdCB4IG9mIHRoaXMudmFsdWVzKCkpIHtcblx0XHRcdHRvdGFsICs9IHg7XG5cdFx0fVxuXHRcdHJldHVybiB0b3RhbDtcblx0fVxufVxuLyogQF9fTk9fU0lERV9FRkZFQ1RTX18gKi9cbmZ1bmN0aW9uIG1lbW8oZm4pIHtcblx0Y29uc3QgY2FjaGUgPSBuZXcgTWFwKCk7XG5cdHJldHVybiAoYXJnKSA9PiB7XG5cdFx0aWYgKCFjYWNoZS5oYXMoYXJnKSkge1xuXHRcdFx0Y2FjaGUuc2V0KGFyZywgZm4oYXJnKSk7XG5cdFx0fVxuXHRcdHJldHVybiBjYWNoZS5nZXQoYXJnKTtcblx0fTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gc2F2ZUlubGluZVNuYXBzaG90cyhlbnZpcm9ubWVudCwgc25hcHNob3RzKSB7XG5cdGNvbnN0IE1hZ2ljU3RyaW5nID0gKGF3YWl0IGltcG9ydCgnbWFnaWMtc3RyaW5nJykpLmRlZmF1bHQ7XG5cdGNvbnN0IGZpbGVzID0gbmV3IFNldChzbmFwc2hvdHMubWFwKChpKSA9PiBpLmZpbGUpKTtcblx0YXdhaXQgUHJvbWlzZS5hbGwoQXJyYXkuZnJvbShmaWxlcykubWFwKGFzeW5jIChmaWxlKSA9PiB7XG5cdFx0Y29uc3Qgc25hcHMgPSBzbmFwc2hvdHMuZmlsdGVyKChpKSA9PiBpLmZpbGUgPT09IGZpbGUpO1xuXHRcdGNvbnN0IGNvZGUgPSBhd2FpdCBlbnZpcm9ubWVudC5yZWFkU25hcHNob3RGaWxlKGZpbGUpO1xuXHRcdGlmIChjb2RlID09IG51bGwpIHtcblx0XHRcdHRocm93IG5ldyBFcnJvcihgY2Fubm90IHJlYWQgJHtmaWxlfSB3aGVuIHNhdmluZyBpbmxpbmUgc25hcHNob3RgKTtcblx0XHR9XG5cdFx0Y29uc3QgcyA9IG5ldyBNYWdpY1N0cmluZyhjb2RlKTtcblx0XHRmb3IgKGNvbnN0IHNuYXAgb2Ygc25hcHMpIHtcblx0XHRcdGNvbnN0IGluZGV4ID0gcG9zaXRpb25Ub09mZnNldChjb2RlLCBzbmFwLmxpbmUsIHNuYXAuY29sdW1uKTtcblx0XHRcdHJlcGxhY2VJbmxpbmVTbmFwKGNvZGUsIHMsIGluZGV4LCBzbmFwLnNuYXBzaG90LCBzbmFwLmFzc2VydGlvbk5hbWUpO1xuXHRcdH1cblx0XHRjb25zdCB0cmFuc2Zvcm1lZCA9IHMudG9TdHJpbmcoKTtcblx0XHRpZiAodHJhbnNmb3JtZWQgIT09IGNvZGUpIHtcblx0XHRcdGF3YWl0IGVudmlyb25tZW50LnNhdmVTbmFwc2hvdEZpbGUoZmlsZSwgdHJhbnNmb3JtZWQpO1xuXHRcdH1cblx0fSkpO1xufVxuY29uc3QgZGVmYXVsdFN0YXJ0T2JqZWN0UmVnZXggPSAvKD86dG9NYXRjaElubGluZVNuYXBzaG90fHRvVGhyb3dFcnJvck1hdGNoaW5nSW5saW5lU25hcHNob3QpXFxzKlxcKFxccyooPzpcXC9cXCpbXFxzXFxTXSpcXCpcXC9cXHMqfFxcL1xcLy4qKD86W1xcblxcclxcdTIwMjhcXHUyMDI5XVxccyp8W1xcdFxcdlxcZiBcXHhBMFxcdTE2ODBcXHUyMDAwLVxcdTIwMEFcXHUyMDJGXFx1MjA1RlxcdTMwMDBcXHVGRUZGXSkpKlxcey87XG5mdW5jdGlvbiBlc2NhcGVSZWdFeHAocykge1xuXHRyZXR1cm4gcy5yZXBsYWNlKC9bLiorP14ke30oKXxbXFxdXFxcXF0vZywgXCJcXFxcJCZcIik7XG59XG5jb25zdCBidWlsZFN0YXJ0T2JqZWN0UmVnZXggPSBtZW1vKChhc3NlcnRpb25OYW1lKSA9PiB7XG5cdGNvbnN0IHJlcGxhY2VkID0gZGVmYXVsdFN0YXJ0T2JqZWN0UmVnZXguc291cmNlLnJlcGxhY2UoXCJ0b01hdGNoSW5saW5lU25hcHNob3R8dG9UaHJvd0Vycm9yTWF0Y2hpbmdJbmxpbmVTbmFwc2hvdFwiLCBlc2NhcGVSZWdFeHAoYXNzZXJ0aW9uTmFtZSkpO1xuXHRyZXR1cm4gbmV3IFJlZ0V4cChyZXBsYWNlZCk7XG59KTtcbmZ1bmN0aW9uIHJlcGxhY2VPYmplY3RTbmFwKGNvZGUsIHMsIGluZGV4LCBuZXdTbmFwLCBhc3NlcnRpb25OYW1lKSB7XG5cdGxldCBfY29kZSA9IGNvZGUuc2xpY2UoaW5kZXgpO1xuXHRjb25zdCByZWdleCA9IGFzc2VydGlvbk5hbWUgPyBidWlsZFN0YXJ0T2JqZWN0UmVnZXgoYXNzZXJ0aW9uTmFtZSkgOiBkZWZhdWx0U3RhcnRPYmplY3RSZWdleDtcblx0Y29uc3Qgc3RhcnRNYXRjaCA9IHJlZ2V4LmV4ZWMoX2NvZGUpO1xuXHRpZiAoIXN0YXJ0TWF0Y2gpIHtcblx0XHRyZXR1cm4gZmFsc2U7XG5cdH1cblx0X2NvZGUgPSBfY29kZS5zbGljZShzdGFydE1hdGNoLmluZGV4KTtcblx0bGV0IGNhbGxFbmQgPSBnZXRDYWxsTGFzdEluZGV4KF9jb2RlKTtcblx0aWYgKGNhbGxFbmQgPT09IG51bGwpIHtcblx0XHRyZXR1cm4gZmFsc2U7XG5cdH1cblx0Y2FsbEVuZCArPSBpbmRleCArIHN0YXJ0TWF0Y2guaW5kZXg7XG5cdGNvbnN0IHNoYXBlU3RhcnQgPSBpbmRleCArIHN0YXJ0TWF0Y2guaW5kZXggKyBzdGFydE1hdGNoWzBdLmxlbmd0aDtcblx0Y29uc3Qgc2hhcGVFbmQgPSBnZXRPYmplY3RTaGFwZUVuZEluZGV4KGNvZGUsIHNoYXBlU3RhcnQpO1xuXHRjb25zdCBzbmFwID0gYCwgJHtwcmVwYXJlU25hcFN0cmluZyhuZXdTbmFwLCBjb2RlLCBpbmRleCl9YDtcblx0aWYgKHNoYXBlRW5kID09PSBjYWxsRW5kKSB7XG5cdFx0Ly8gdG9NYXRjaElubGluZVNuYXBzaG90KHsgZm9vOiBleHBlY3QuYW55KFN0cmluZykgfSlcblx0XHRzLmFwcGVuZExlZnQoY2FsbEVuZCwgc25hcCk7XG5cdH0gZWxzZSB7XG5cdFx0Ly8gdG9NYXRjaElubGluZVNuYXBzaG90KHsgZm9vOiBleHBlY3QuYW55KFN0cmluZykgfSwgYGApXG5cdFx0cy5vdmVyd3JpdGUoc2hhcGVFbmQsIGNhbGxFbmQsIHNuYXApO1xuXHR9XG5cdHJldHVybiB0cnVlO1xufVxuZnVuY3Rpb24gZ2V0T2JqZWN0U2hhcGVFbmRJbmRleChjb2RlLCBpbmRleCkge1xuXHRsZXQgc3RhcnRCcmFjZXMgPSAxO1xuXHRsZXQgZW5kQnJhY2VzID0gMDtcblx0d2hpbGUgKHN0YXJ0QnJhY2VzICE9PSBlbmRCcmFjZXMgJiYgaW5kZXggPCBjb2RlLmxlbmd0aCkge1xuXHRcdGNvbnN0IHMgPSBjb2RlW2luZGV4KytdO1xuXHRcdGlmIChzID09PSBcIntcIikge1xuXHRcdFx0c3RhcnRCcmFjZXMrKztcblx0XHR9IGVsc2UgaWYgKHMgPT09IFwifVwiKSB7XG5cdFx0XHRlbmRCcmFjZXMrKztcblx0XHR9XG5cdH1cblx0cmV0dXJuIGluZGV4O1xufVxuZnVuY3Rpb24gcHJlcGFyZVNuYXBTdHJpbmcoc25hcCwgc291cmNlLCBpbmRleCkge1xuXHRjb25zdCBsaW5lTnVtYmVyID0gb2Zmc2V0VG9MaW5lTnVtYmVyKHNvdXJjZSwgaW5kZXgpO1xuXHRjb25zdCBsaW5lID0gc291cmNlLnNwbGl0KGxpbmVTcGxpdFJFKVtsaW5lTnVtYmVyIC0gMV07XG5cdGNvbnN0IGluZGVudCA9IGxpbmUubWF0Y2goL15cXHMqLylbMF0gfHwgXCJcIjtcblx0Y29uc3QgaW5kZW50TmV4dCA9IGluZGVudC5pbmNsdWRlcyhcIlx0XCIpID8gYCR7aW5kZW50fVxcdGAgOiBgJHtpbmRlbnR9ICBgO1xuXHRjb25zdCBsaW5lcyA9IHNuYXAudHJpbSgpLnJlcGxhY2UoL1xcXFwvZywgXCJcXFxcXFxcXFwiKS5zcGxpdCgvXFxuL2cpO1xuXHRjb25zdCBpc09uZWxpbmUgPSBsaW5lcy5sZW5ndGggPD0gMTtcblx0Y29uc3QgcXVvdGUgPSBcImBcIjtcblx0aWYgKGlzT25lbGluZSkge1xuXHRcdHJldHVybiBgJHtxdW90ZX0ke2xpbmVzLmpvaW4oXCJcXG5cIikucmVwbGFjZSgvYC9nLCBcIlxcXFxgXCIpLnJlcGxhY2UoL1xcJFxcey9nLCBcIlxcXFwke1wiKX0ke3F1b3RlfWA7XG5cdH1cblx0cmV0dXJuIGAke3F1b3RlfVxcbiR7bGluZXMubWFwKChpKSA9PiBpID8gaW5kZW50TmV4dCArIGkgOiBcIlwiKS5qb2luKFwiXFxuXCIpLnJlcGxhY2UoL2AvZywgXCJcXFxcYFwiKS5yZXBsYWNlKC9cXCRcXHsvZywgXCJcXFxcJHtcIil9XFxuJHtpbmRlbnR9JHtxdW90ZX1gO1xufVxuY29uc3QgZGVmYXVsdE1ldGhvZE5hbWVzID0gW1widG9NYXRjaElubGluZVNuYXBzaG90XCIsIFwidG9UaHJvd0Vycm9yTWF0Y2hpbmdJbmxpbmVTbmFwc2hvdFwiXTtcbi8vIG9uIHdlYmtpdCwgdGhlIGxpbmUgbnVtYmVyIGlzIGF0IHRoZSBlbmQgb2YgdGhlIG1ldGhvZCwgbm90IGF0IHRoZSBzdGFydFxuZnVuY3Rpb24gZ2V0Q29kZVN0YXJ0aW5nQXRJbmRleChjb2RlLCBpbmRleCwgbWV0aG9kTmFtZXMpIHtcblx0Zm9yIChjb25zdCBuYW1lIG9mIG1ldGhvZE5hbWVzKSB7XG5cdFx0Y29uc3QgYWRqdXN0ZWQgPSBpbmRleCAtIG5hbWUubGVuZ3RoO1xuXHRcdGlmIChhZGp1c3RlZCA+PSAwICYmIGNvZGUuc2xpY2UoYWRqdXN0ZWQsIGluZGV4KSA9PT0gbmFtZSkge1xuXHRcdFx0cmV0dXJuIHtcblx0XHRcdFx0Y29kZTogY29kZS5zbGljZShhZGp1c3RlZCksXG5cdFx0XHRcdGluZGV4OiBhZGp1c3RlZFxuXHRcdFx0fTtcblx0XHR9XG5cdH1cblx0cmV0dXJuIHtcblx0XHRjb2RlOiBjb2RlLnNsaWNlKGluZGV4KSxcblx0XHRpbmRleFxuXHR9O1xufVxuY29uc3QgZGVmYXVsdFN0YXJ0UmVnZXggPSAvKD86dG9NYXRjaElubGluZVNuYXBzaG90fHRvVGhyb3dFcnJvck1hdGNoaW5nSW5saW5lU25hcHNob3QpXFxzKlxcKFxccyooPzpcXC9cXCpbXFxzXFxTXSpcXCpcXC9cXHMqfFxcL1xcLy4qKD86W1xcblxcclxcdTIwMjhcXHUyMDI5XVxccyp8W1xcdFxcdlxcZiBcXHhBMFxcdTE2ODBcXHUyMDAwLVxcdTIwMEFcXHUyMDJGXFx1MjA1RlxcdTMwMDBcXHVGRUZGXSkpKltcXHckXSooWydcImApXSkvO1xuY29uc3QgYnVpbGRTdGFydFJlZ2V4ID0gbWVtbygoYXNzZXJ0aW9uTmFtZSkgPT4ge1xuXHRjb25zdCByZXBsYWNlZCA9IGRlZmF1bHRTdGFydFJlZ2V4LnNvdXJjZS5yZXBsYWNlKFwidG9NYXRjaElubGluZVNuYXBzaG90fHRvVGhyb3dFcnJvck1hdGNoaW5nSW5saW5lU25hcHNob3RcIiwgZXNjYXBlUmVnRXhwKGFzc2VydGlvbk5hbWUpKTtcblx0cmV0dXJuIG5ldyBSZWdFeHAocmVwbGFjZWQpO1xufSk7XG5mdW5jdGlvbiByZXBsYWNlSW5saW5lU25hcChjb2RlLCBzLCBjdXJyZW50SW5kZXgsIG5ld1NuYXAsIGFzc2VydGlvbk5hbWUpIHtcblx0Y29uc3QgbWV0aG9kTmFtZXMgPSBhc3NlcnRpb25OYW1lID8gW2Fzc2VydGlvbk5hbWVdIDogZGVmYXVsdE1ldGhvZE5hbWVzO1xuXHRjb25zdCB7IGNvZGU6IGNvZGVTdGFydGluZ0F0SW5kZXgsIGluZGV4IH0gPSBnZXRDb2RlU3RhcnRpbmdBdEluZGV4KGNvZGUsIGN1cnJlbnRJbmRleCwgbWV0aG9kTmFtZXMpO1xuXHRjb25zdCBzdGFydFJlZ2V4ID0gYXNzZXJ0aW9uTmFtZSA/IGJ1aWxkU3RhcnRSZWdleChhc3NlcnRpb25OYW1lKSA6IGRlZmF1bHRTdGFydFJlZ2V4O1xuXHRjb25zdCBzdGFydE1hdGNoID0gc3RhcnRSZWdleC5leGVjKGNvZGVTdGFydGluZ0F0SW5kZXgpO1xuXHRjb25zdCBrZXl3b3JkUmVnZXggPSBhc3NlcnRpb25OYW1lID8gbmV3IFJlZ0V4cChlc2NhcGVSZWdFeHAoYXNzZXJ0aW9uTmFtZSkpIDogL3RvTWF0Y2hJbmxpbmVTbmFwc2hvdHx0b1Rocm93RXJyb3JNYXRjaGluZ0lubGluZVNuYXBzaG90Lztcblx0Y29uc3QgZmlyc3RLZXl3b3JkTWF0Y2ggPSBrZXl3b3JkUmVnZXguZXhlYyhjb2RlU3RhcnRpbmdBdEluZGV4KTtcblx0aWYgKCFzdGFydE1hdGNoIHx8IHN0YXJ0TWF0Y2guaW5kZXggIT09IGZpcnN0S2V5d29yZE1hdGNoPy5pbmRleCkge1xuXHRcdHJldHVybiByZXBsYWNlT2JqZWN0U25hcChjb2RlLCBzLCBpbmRleCwgbmV3U25hcCwgYXNzZXJ0aW9uTmFtZSk7XG5cdH1cblx0Y29uc3QgcXVvdGUgPSBzdGFydE1hdGNoWzFdO1xuXHRjb25zdCBzdGFydEluZGV4ID0gaW5kZXggKyBzdGFydE1hdGNoLmluZGV4ICsgc3RhcnRNYXRjaFswXS5sZW5ndGg7XG5cdGNvbnN0IHNuYXBTdHJpbmcgPSBwcmVwYXJlU25hcFN0cmluZyhuZXdTbmFwLCBjb2RlLCBpbmRleCk7XG5cdGlmIChxdW90ZSA9PT0gXCIpXCIpIHtcblx0XHRzLmFwcGVuZFJpZ2h0KHN0YXJ0SW5kZXggLSAxLCBzbmFwU3RyaW5nKTtcblx0XHRyZXR1cm4gdHJ1ZTtcblx0fVxuXHRjb25zdCBxdW90ZUVuZFJFID0gbmV3IFJlZ0V4cChgKD86XnxbXlxcXFxcXFxcXSkke3F1b3RlfWApO1xuXHRjb25zdCBlbmRNYXRjaCA9IHF1b3RlRW5kUkUuZXhlYyhjb2RlLnNsaWNlKHN0YXJ0SW5kZXgpKTtcblx0aWYgKCFlbmRNYXRjaCkge1xuXHRcdHJldHVybiBmYWxzZTtcblx0fVxuXHRjb25zdCBlbmRJbmRleCA9IHN0YXJ0SW5kZXggKyBlbmRNYXRjaC5pbmRleCArIGVuZE1hdGNoWzBdLmxlbmd0aDtcblx0cy5vdmVyd3JpdGUoc3RhcnRJbmRleCAtIDEsIGVuZEluZGV4LCBzbmFwU3RyaW5nKTtcblx0cmV0dXJuIHRydWU7XG59XG5jb25zdCBJTkRFTlRBVElPTl9SRUdFWCA9IC9eKFteXFxTXFxuXSopXFxTL207XG5mdW5jdGlvbiBzdHJpcFNuYXBzaG90SW5kZW50YXRpb24oaW5saW5lU25hcHNob3QpIHtcblx0Ly8gRmluZCBpbmRlbnRhdGlvbiBpZiBleGlzdHMuXG5cdGNvbnN0IG1hdGNoID0gaW5saW5lU25hcHNob3QubWF0Y2goSU5ERU5UQVRJT05fUkVHRVgpO1xuXHRpZiAoIW1hdGNoIHx8ICFtYXRjaFsxXSkge1xuXHRcdC8vIE5vIGluZGVudGF0aW9uLlxuXHRcdHJldHVybiBpbmxpbmVTbmFwc2hvdDtcblx0fVxuXHRjb25zdCBpbmRlbnRhdGlvbiA9IG1hdGNoWzFdO1xuXHRjb25zdCBsaW5lcyA9IGlubGluZVNuYXBzaG90LnNwbGl0KC9cXG4vZyk7XG5cdGlmIChsaW5lcy5sZW5ndGggPD0gMikge1xuXHRcdC8vIE11c3QgYmUgYXQgbGVhc3QgMyBsaW5lcy5cblx0XHRyZXR1cm4gaW5saW5lU25hcHNob3Q7XG5cdH1cblx0aWYgKGxpbmVzWzBdLnRyaW0oKSAhPT0gXCJcIiB8fCBsaW5lcy5hdCgtMSk/LnRyaW0oKSAhPT0gXCJcIikge1xuXHRcdC8vIElmIG5vdCBibGFuayBmaXJzdCBhbmQgbGFzdCBsaW5lcywgYWJvcnQuXG5cdFx0cmV0dXJuIGlubGluZVNuYXBzaG90O1xuXHR9XG5cdGZvciAobGV0IGkgPSAxOyBpIDwgbGluZXMubGVuZ3RoIC0gMTsgaSsrKSB7XG5cdFx0aWYgKGxpbmVzW2ldICE9PSBcIlwiKSB7XG5cdFx0XHRpZiAobGluZXNbaV0uaW5kZXhPZihpbmRlbnRhdGlvbikgIT09IDApIHtcblx0XHRcdFx0Ly8gQWxsIGxpbmVzIGV4Y2VwdCBmaXJzdCBhbmQgbGFzdCBzaG91bGQgZWl0aGVyIGJlIGJsYW5rIG9yIGhhdmUgdGhlIHNhbWVcblx0XHRcdFx0Ly8gaW5kZW50IGFzIHRoZSBmaXJzdCBsaW5lIChvciBtb3JlKS4gSWYgdGhpcyBpc24ndCB0aGUgY2FzZSB3ZSBkb24ndFxuXHRcdFx0XHQvLyB3YW50IHRvIHRvdWNoIHRoZSBzbmFwc2hvdCBhdCBhbGwuXG5cdFx0XHRcdHJldHVybiBpbmxpbmVTbmFwc2hvdDtcblx0XHRcdH1cblx0XHRcdGxpbmVzW2ldID0gbGluZXNbaV0uc3Vic3RyaW5nKGluZGVudGF0aW9uLmxlbmd0aCk7XG5cdFx0fVxuXHR9XG5cdC8vIExhc3QgbGluZSBpcyBhIHNwZWNpYWwgY2FzZSBiZWNhdXNlIGl0IHdvbid0IGhhdmUgdGhlIHNhbWUgaW5kZW50IGFzIG90aGVyc1xuXHQvLyBidXQgbWF5IHN0aWxsIGhhdmUgYmVlbiBnaXZlbiBzb21lIGluZGVudCB0byBsaW5lIHVwLlxuXHRsaW5lc1tsaW5lcy5sZW5ndGggLSAxXSA9IFwiXCI7XG5cdC8vIFJldHVybiBpbmxpbmUgc25hcHNob3QsIG5vdyBhdCBpbmRlbnQgMC5cblx0aW5saW5lU25hcHNob3QgPSBsaW5lcy5qb2luKFwiXFxuXCIpO1xuXHRyZXR1cm4gaW5saW5lU25hcHNob3Q7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHNhdmVSYXdTbmFwc2hvdHMoZW52aXJvbm1lbnQsIHNuYXBzaG90cykge1xuXHRhd2FpdCBQcm9taXNlLmFsbChzbmFwc2hvdHMubWFwKGFzeW5jIChzbmFwKSA9PiB7XG5cdFx0aWYgKCFzbmFwLnJlYWRvbmx5KSB7XG5cdFx0XHRhd2FpdCBlbnZpcm9ubWVudC5zYXZlU25hcHNob3RGaWxlKHNuYXAuZmlsZSwgc25hcC5zbmFwc2hvdCk7XG5cdFx0fVxuXHR9KSk7XG59XG5cbmZ1bmN0aW9uIGlzU2FtZVN0YWNrUG9zaXRpb24oeCwgeSkge1xuXHRyZXR1cm4geC5maWxlID09PSB5LmZpbGUgJiYgeC5jb2x1bW4gPT09IHkuY29sdW1uICYmIHgubGluZSA9PT0geS5saW5lO1xufVxuY2xhc3MgU25hcHNob3RTdGF0ZSB7XG5cdF9jb3VudGVycyA9IG5ldyBDb3VudGVyTWFwKCk7XG5cdF9kaXJ0eTtcblx0X3VwZGF0ZVNuYXBzaG90O1xuXHRfc25hcHNob3REYXRhO1xuXHRfaW5pdGlhbERhdGE7XG5cdF9pbmxpbmVTbmFwc2hvdHM7XG5cdF9pbmxpbmVTbmFwc2hvdFN0YWNrcztcblx0X3Rlc3RJZFRvS2V5cyA9IG5ldyBEZWZhdWx0TWFwKCgpID0+IFtdKTtcblx0X3Jhd1NuYXBzaG90cztcblx0X3VuY2hlY2tlZEtleXM7XG5cdF9zbmFwc2hvdEZvcm1hdDtcblx0X2Vudmlyb25tZW50O1xuXHRfZmlsZUV4aXN0cztcblx0ZXhwYW5kO1xuXHQvLyBnZXR0ZXIvc2V0dGVyIGZvciBqZXN0LWltYWdlLXNuYXBzaG90IGNvbXBhdFxuXHQvLyBodHRwczovL2dpdGh1Yi5jb20vdml0ZXN0LWRldi92aXRlc3QvaXNzdWVzLzczMjJcblx0X2FkZGVkID0gbmV3IENvdW50ZXJNYXAoKTtcblx0X21hdGNoZWQgPSBuZXcgQ291bnRlck1hcCgpO1xuXHRfdW5tYXRjaGVkID0gbmV3IENvdW50ZXJNYXAoKTtcblx0X3VwZGF0ZWQgPSBuZXcgQ291bnRlck1hcCgpO1xuXHRnZXQgYWRkZWQoKSB7XG5cdFx0cmV0dXJuIHRoaXMuX2FkZGVkO1xuXHR9XG5cdHNldCBhZGRlZCh2YWx1ZSkge1xuXHRcdHRoaXMuX2FkZGVkLl90b3RhbCA9IHZhbHVlO1xuXHR9XG5cdGdldCBtYXRjaGVkKCkge1xuXHRcdHJldHVybiB0aGlzLl9tYXRjaGVkO1xuXHR9XG5cdHNldCBtYXRjaGVkKHZhbHVlKSB7XG5cdFx0dGhpcy5fbWF0Y2hlZC5fdG90YWwgPSB2YWx1ZTtcblx0fVxuXHRnZXQgdW5tYXRjaGVkKCkge1xuXHRcdHJldHVybiB0aGlzLl91bm1hdGNoZWQ7XG5cdH1cblx0c2V0IHVubWF0Y2hlZCh2YWx1ZSkge1xuXHRcdHRoaXMuX3VubWF0Y2hlZC5fdG90YWwgPSB2YWx1ZTtcblx0fVxuXHRnZXQgdXBkYXRlZCgpIHtcblx0XHRyZXR1cm4gdGhpcy5fdXBkYXRlZDtcblx0fVxuXHRzZXQgdXBkYXRlZCh2YWx1ZSkge1xuXHRcdHRoaXMuX3VwZGF0ZWQuX3RvdGFsID0gdmFsdWU7XG5cdH1cblx0Y29uc3RydWN0b3IodGVzdEZpbGVQYXRoLCBzbmFwc2hvdFBhdGgsIHNuYXBzaG90Q29udGVudCwgb3B0aW9ucykge1xuXHRcdHRoaXMudGVzdEZpbGVQYXRoID0gdGVzdEZpbGVQYXRoO1xuXHRcdHRoaXMuc25hcHNob3RQYXRoID0gc25hcHNob3RQYXRoO1xuXHRcdGNvbnN0IHsgZGF0YSwgZGlydHkgfSA9IGdldFNuYXBzaG90RGF0YShzbmFwc2hvdENvbnRlbnQsIG9wdGlvbnMpO1xuXHRcdHRoaXMuX2ZpbGVFeGlzdHMgPSBzbmFwc2hvdENvbnRlbnQgIT0gbnVsbDtcblx0XHR0aGlzLl9pbml0aWFsRGF0YSA9IHsgLi4uZGF0YSB9O1xuXHRcdHRoaXMuX3NuYXBzaG90RGF0YSA9IHsgLi4uZGF0YSB9O1xuXHRcdHRoaXMuX2RpcnR5ID0gZGlydHk7XG5cdFx0dGhpcy5faW5saW5lU25hcHNob3RzID0gW107XG5cdFx0dGhpcy5faW5saW5lU25hcHNob3RTdGFja3MgPSBbXTtcblx0XHR0aGlzLl9yYXdTbmFwc2hvdHMgPSBbXTtcblx0XHR0aGlzLl91bmNoZWNrZWRLZXlzID0gbmV3IFNldChPYmplY3Qua2V5cyh0aGlzLl9zbmFwc2hvdERhdGEpKTtcblx0XHR0aGlzLmV4cGFuZCA9IG9wdGlvbnMuZXhwYW5kIHx8IGZhbHNlO1xuXHRcdHRoaXMuX3VwZGF0ZVNuYXBzaG90ID0gb3B0aW9ucy51cGRhdGVTbmFwc2hvdDtcblx0XHR0aGlzLl9zbmFwc2hvdEZvcm1hdCA9IHtcblx0XHRcdHByaW50QmFzaWNQcm90b3R5cGU6IGZhbHNlLFxuXHRcdFx0ZXNjYXBlU3RyaW5nOiBmYWxzZSxcblx0XHRcdG1heE91dHB1dExlbmd0aDogMiAqKiAyNyxcblx0XHRcdC4uLm9wdGlvbnMuc25hcHNob3RGb3JtYXRcblx0XHR9O1xuXHRcdHRoaXMuX2Vudmlyb25tZW50ID0gb3B0aW9ucy5zbmFwc2hvdEVudmlyb25tZW50O1xuXHR9XG5cdHN0YXRpYyBhc3luYyBjcmVhdGUodGVzdEZpbGVQYXRoLCBvcHRpb25zKSB7XG5cdFx0Y29uc3Qgc25hcHNob3RQYXRoID0gYXdhaXQgb3B0aW9ucy5zbmFwc2hvdEVudmlyb25tZW50LnJlc29sdmVQYXRoKHRlc3RGaWxlUGF0aCk7XG5cdFx0Y29uc3QgY29udGVudCA9IGF3YWl0IG9wdGlvbnMuc25hcHNob3RFbnZpcm9ubWVudC5yZWFkU25hcHNob3RGaWxlKHNuYXBzaG90UGF0aCk7XG5cdFx0cmV0dXJuIG5ldyBTbmFwc2hvdFN0YXRlKHRlc3RGaWxlUGF0aCwgc25hcHNob3RQYXRoLCBjb250ZW50LCBvcHRpb25zKTtcblx0fVxuXHRnZXQgc25hcHNob3RVcGRhdGVTdGF0ZSgpIHtcblx0XHRyZXR1cm4gdGhpcy5fdXBkYXRlU25hcHNob3Q7XG5cdH1cblx0Z2V0IGVudmlyb25tZW50KCkge1xuXHRcdHJldHVybiB0aGlzLl9lbnZpcm9ubWVudDtcblx0fVxuXHRtYXJrU25hcHNob3RzQXNDaGVja2VkRm9yVGVzdCh0ZXN0TmFtZSkge1xuXHRcdHRoaXMuX3VuY2hlY2tlZEtleXMuZm9yRWFjaCgodW5jaGVja2VkS2V5KSA9PiB7XG5cdFx0XHQvLyBza2lwIHNuYXBzaG90cyB3aXRoIGZvbGxvd2luZyBrZXlzXG5cdFx0XHQvLyAgIHRlc3ROYW1lIG5cblx0XHRcdC8vICAgdGVzdE5hbWUgPiB4eHggbiAodGhpcyBpcyBmb3IgdG9NYXRjaFNuYXBzaG90KFwieHh4XCIpIEFQSSlcblx0XHRcdGlmICgvIFxcZCskfCA+IC8udGVzdCh1bmNoZWNrZWRLZXkuc2xpY2UodGVzdE5hbWUubGVuZ3RoKSkpIHtcblx0XHRcdFx0dGhpcy5fdW5jaGVja2VkS2V5cy5kZWxldGUodW5jaGVja2VkS2V5KTtcblx0XHRcdH1cblx0XHR9KTtcblx0fVxuXHRjbGVhclRlc3QodGVzdElkKSB7XG5cdFx0Ly8gY2xlYXIgaW5saW5lXG5cdFx0dGhpcy5faW5saW5lU25hcHNob3RzID0gdGhpcy5faW5saW5lU25hcHNob3RzLmZpbHRlcigocykgPT4gcy50ZXN0SWQgIT09IHRlc3RJZCk7XG5cdFx0dGhpcy5faW5saW5lU25hcHNob3RTdGFja3MgPSB0aGlzLl9pbmxpbmVTbmFwc2hvdFN0YWNrcy5maWx0ZXIoKHMpID0+IHMudGVzdElkICE9PSB0ZXN0SWQpO1xuXHRcdC8vIGNsZWFyIGZpbGVcblx0XHRmb3IgKGNvbnN0IGtleSBvZiB0aGlzLl90ZXN0SWRUb0tleXMuZ2V0KHRlc3RJZCkpIHtcblx0XHRcdGNvbnN0IG5hbWUgPSBrZXlUb1Rlc3ROYW1lKGtleSk7XG5cdFx0XHRjb25zdCBjb3VudCA9IHRoaXMuX2NvdW50ZXJzLmdldChuYW1lKTtcblx0XHRcdGlmIChjb3VudCA+IDApIHtcblx0XHRcdFx0aWYgKGtleSBpbiB0aGlzLl9zbmFwc2hvdERhdGEgfHwga2V5IGluIHRoaXMuX2luaXRpYWxEYXRhKSB7XG5cdFx0XHRcdFx0dGhpcy5fc25hcHNob3REYXRhW2tleV0gPSB0aGlzLl9pbml0aWFsRGF0YVtrZXldO1xuXHRcdFx0XHR9XG5cdFx0XHRcdHRoaXMuX2NvdW50ZXJzLnNldChuYW1lLCBjb3VudCAtIDEpO1xuXHRcdFx0fVxuXHRcdH1cblx0XHR0aGlzLl90ZXN0SWRUb0tleXMuZGVsZXRlKHRlc3RJZCk7XG5cdFx0Ly8gY2xlYXIgc3RhdHNcblx0XHR0aGlzLmFkZGVkLmRlbGV0ZSh0ZXN0SWQpO1xuXHRcdHRoaXMudXBkYXRlZC5kZWxldGUodGVzdElkKTtcblx0XHR0aGlzLm1hdGNoZWQuZGVsZXRlKHRlc3RJZCk7XG5cdFx0dGhpcy51bm1hdGNoZWQuZGVsZXRlKHRlc3RJZCk7XG5cdH1cblx0X2luZmVySW5saW5lU25hcHNob3RTdGFjayhzdGFja3MpIHtcblx0XHQvLyBpZiBjYWxsZWQgaW5zaWRlIHJlc29sdmVzL3JlamVjdHMsIHN0YWNrdHJhY2UgaXMgZGlmZmVyZW50XG5cdFx0Y29uc3QgcHJvbWlzZUluZGV4ID0gc3RhY2tzLmZpbmRJbmRleCgoaSkgPT4gaS5tZXRob2QubWF0Y2goL19fVklURVNUXyhSRVNPTFZFU3xSRUpFQ1RTKV9fLykpO1xuXHRcdGlmIChwcm9taXNlSW5kZXggIT09IC0xKSB7XG5cdFx0XHRyZXR1cm4gc3RhY2tzW3Byb21pc2VJbmRleCArIDNdO1xuXHRcdH1cblx0XHQvLyBzdXBwb3J0IHBvbGwgKyBpbmxpbmUgc25hcHNob3Rcblx0XHRjb25zdCBwb2xsQ2hhaW5JbmRleCA9IHN0YWNrcy5maW5kSW5kZXgoKGkpID0+IGkubWV0aG9kLm1hdGNoKC9fX1ZJVEVTVF9QT0xMX0NIQUlOX18vKSk7XG5cdFx0aWYgKHBvbGxDaGFpbkluZGV4ICE9PSAtMSkge1xuXHRcdFx0cmV0dXJuIHN0YWNrc1twb2xsQ2hhaW5JbmRleCArIDFdO1xuXHRcdH1cblx0XHQvLyBpbmxpbmUgc25hcHNob3QgZnVuY3Rpb24gY2FuIGJlIG5hbWVkIF9fSU5MSU5FX1NOQVBTSE9UX09GRlNFVF88bj5fX1xuXHRcdC8vIHRvIHNwZWNpZnkgYSBjdXN0b20gc3RhY2sgb2Zmc2V0XG5cdFx0Zm9yIChsZXQgaSA9IDA7IGkgPCBzdGFja3MubGVuZ3RoOyBpKyspIHtcblx0XHRcdGNvbnN0IG1hdGNoID0gc3RhY2tzW2ldLm1ldGhvZC5tYXRjaCgvX19JTkxJTkVfU05BUFNIT1RfT0ZGU0VUXyhcXGQrKV9fLyk7XG5cdFx0XHRpZiAobWF0Y2gpIHtcblx0XHRcdFx0cmV0dXJuIHN0YWNrc1tpICsgTnVtYmVyKG1hdGNoWzFdKV0gPz8gbnVsbDtcblx0XHRcdH1cblx0XHR9XG5cdFx0Ly8gY3VzdG9tIG1hdGNoZXIgcmVnaXN0ZXJlZCB2aWEgZXhwZWN0LmV4dGVuZCgpIOKAlCB0aGUgd3JhcHBlciBmdW5jdGlvblxuXHRcdC8vIGluIGplc3QtZXh0ZW5kLnRzIGlzIG5hbWVkIF9fVklURVNUX0VYVEVORF9BU1NFUlRJT05fX1xuXHRcdGNvbnN0IGN1c3RvbU1hdGNoZXJJbmRleCA9IHN0YWNrcy5maW5kSW5kZXgoKGkpID0+IGkubWV0aG9kLmluY2x1ZGVzKFwiX19WSVRFU1RfRVhURU5EX0FTU0VSVElPTl9fXCIpKTtcblx0XHRpZiAoY3VzdG9tTWF0Y2hlckluZGV4ICE9PSAtMSkge1xuXHRcdFx0cmV0dXJuIHN0YWNrc1tjdXN0b21NYXRjaGVySW5kZXggKyAzXSA/PyBudWxsO1xuXHRcdH1cblx0XHQvLyBpbmxpbmUgc25hcHNob3QgZnVuY3Rpb24gaXMgY2FsbGVkIF9fSU5MSU5FX1NOQVBTSE9UX19cblx0XHQvLyBpbiBpbnRlZ3JhdGlvbnMvc25hcHNob3QvY2hhaS50c1xuXHRcdGNvbnN0IHN0YWNrSW5kZXggPSBzdGFja3MuZmluZEluZGV4KChpKSA9PiBpLm1ldGhvZC5pbmNsdWRlcyhcIl9fSU5MSU5FX1NOQVBTSE9UX19cIikpO1xuXHRcdHJldHVybiBzdGFja0luZGV4ICE9PSAtMSA/IHN0YWNrc1tzdGFja0luZGV4ICsgMl0gOiBudWxsO1xuXHR9XG5cdF9hZGRTbmFwc2hvdChrZXksIHJlY2VpdmVkU2VyaWFsaXplZCwgb3B0aW9ucykge1xuXHRcdHRoaXMuX2RpcnR5ID0gdHJ1ZTtcblx0XHRpZiAob3B0aW9ucy5zdGFjaykge1xuXHRcdFx0dGhpcy5faW5saW5lU25hcHNob3RzLnB1c2goe1xuXHRcdFx0XHQuLi5vcHRpb25zLnN0YWNrLFxuXHRcdFx0XHRzbmFwc2hvdDogcmVjZWl2ZWRTZXJpYWxpemVkLFxuXHRcdFx0XHR0ZXN0SWQ6IG9wdGlvbnMudGVzdElkLFxuXHRcdFx0XHRhc3NlcnRpb25OYW1lOiBvcHRpb25zLmFzc2VydGlvbk5hbWVcblx0XHRcdH0pO1xuXHRcdH0gZWxzZSBpZiAob3B0aW9ucy5yYXdTbmFwc2hvdCkge1xuXHRcdFx0dGhpcy5fcmF3U25hcHNob3RzLnB1c2goe1xuXHRcdFx0XHQuLi5vcHRpb25zLnJhd1NuYXBzaG90LFxuXHRcdFx0XHRzbmFwc2hvdDogcmVjZWl2ZWRTZXJpYWxpemVkXG5cdFx0XHR9KTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0dGhpcy5fc25hcHNob3REYXRhW2tleV0gPSByZWNlaXZlZFNlcmlhbGl6ZWQ7XG5cdFx0fVxuXHR9XG5cdF9yZXNvbHZlS2V5KHRlc3RJZCwgdGVzdE5hbWUsIGtleSkge1xuXHRcdHRoaXMuX2NvdW50ZXJzLmluY3JlbWVudCh0ZXN0TmFtZSk7XG5cdFx0Y29uc3QgY291bnQgPSB0aGlzLl9jb3VudGVycy5nZXQodGVzdE5hbWUpO1xuXHRcdGlmICgha2V5KSB7XG5cdFx0XHRrZXkgPSB0ZXN0TmFtZVRvS2V5KHRlc3ROYW1lLCBjb3VudCk7XG5cdFx0fVxuXHRcdHRoaXMuX3Rlc3RJZFRvS2V5cy5nZXQodGVzdElkKS5wdXNoKGtleSk7XG5cdFx0cmV0dXJuIHtcblx0XHRcdGtleSxcblx0XHRcdGNvdW50XG5cdFx0fTtcblx0fVxuXHRfcmVzb2x2ZUlubGluZVN0YWNrKG9wdGlvbnMpIHtcblx0XHRjb25zdCB7IHRlc3RJZCwgc25hcHNob3QsIGFzc2VydGlvbk5hbWUsIGVycm9yIH0gPSBvcHRpb25zO1xuXHRcdGNvbnN0IHN0YWNrcyA9IHBhcnNlRXJyb3JTdGFja3RyYWNlKGVycm9yLCB7IGlnbm9yZVN0YWNrRW50cmllczogW10gfSk7XG5cdFx0Y29uc3QgX3N0YWNrID0gdGhpcy5faW5mZXJJbmxpbmVTbmFwc2hvdFN0YWNrKHN0YWNrcyk7XG5cdFx0aWYgKCFfc3RhY2spIHtcblx0XHRcdGNvbnN0IG1lc3NhZ2UgPSBzdGFja3MubWFwKChzKSA9PiBgICAke3MuZmlsZX06JHtzLmxpbmV9OiR7cy5jb2x1bW59JHtzLm1ldGhvZCA/IGAgKCR7cy5tZXRob2R9KWAgOiBcIlwifWApLmpvaW4oXCJcXG5cIik7XG5cdFx0XHR0aHJvdyBuZXcgRXJyb3IoYEB2aXRlc3Qvc25hcHNob3Q6IENvdWxkbid0IGluZmVyIHN0YWNrIGZyYW1lIGZvciBpbmxpbmUgc25hcHNob3QuXFxuJHttZXNzYWdlfWApO1xuXHRcdH1cblx0XHRjb25zdCBzdGFjayA9IHRoaXMuZW52aXJvbm1lbnQucHJvY2Vzc1N0YWNrVHJhY2U/Lihfc3RhY2spIHx8IF9zdGFjaztcblx0XHQvLyByZW1vdmluZyAxIGNvbHVtbiwgYmVjYXVzZSBzb3VyY2UgbWFwIHBvaW50cyB0byB0aGUgd3Jvbmdcblx0XHQvLyBsb2NhdGlvbiBmb3IganMgZmlsZXMsIGJ1dCBgY29sdW1uLTFgIHBvaW50cyB0byB0aGUgc2FtZSBpbiBib3RoIGpzL3RzXG5cdFx0Ly8gaHR0cHM6Ly9naXRodWIuY29tL3ZpdGVqcy92aXRlL2lzc3Vlcy84NjU3XG5cdFx0c3RhY2suY29sdW1uLS07XG5cdFx0Ly8gcmVqZWN0IG11bHRpcGxlIGlubGluZSBzbmFwc2hvdHMgYXQgdGhlIHNhbWUgbG9jYXRpb24gaWYgc25hcHNob3QgaXMgZGlmZmVyZW50XG5cdFx0Y29uc3Qgc25hcHNob3RzV2l0aFNhbWVTdGFjayA9IHRoaXMuX2lubGluZVNuYXBzaG90U3RhY2tzLmZpbHRlcigocykgPT4gaXNTYW1lU3RhY2tQb3NpdGlvbihzLCBzdGFjaykpO1xuXHRcdGlmIChzbmFwc2hvdHNXaXRoU2FtZVN0YWNrLmxlbmd0aCA+IDApIHtcblx0XHRcdC8vIGVuc3VyZSBvbmx5IG9uZSBzbmFwc2hvdCB3aWxsIGJlIHdyaXR0ZW4gYXQgdGhlIHNhbWUgbG9jYXRpb25cblx0XHRcdHRoaXMuX2lubGluZVNuYXBzaG90cyA9IHRoaXMuX2lubGluZVNuYXBzaG90cy5maWx0ZXIoKHMpID0+ICFpc1NhbWVTdGFja1Bvc2l0aW9uKHMsIHN0YWNrKSk7XG5cdFx0XHRjb25zdCBkaWZmZXJlbnRTbmFwc2hvdCA9IHNuYXBzaG90c1dpdGhTYW1lU3RhY2suZmluZCgocykgPT4gcy5zbmFwc2hvdCAhPT0gc25hcHNob3QpO1xuXHRcdFx0aWYgKGRpZmZlcmVudFNuYXBzaG90KSB7XG5cdFx0XHRcdHRocm93IE9iamVjdC5hc3NpZ24obmV3IEVycm9yKGAke2Fzc2VydGlvbk5hbWV9IHdpdGggZGlmZmVyZW50IHNuYXBzaG90cyBjYW5ub3QgYmUgY2FsbGVkIGF0IHRoZSBzYW1lIGxvY2F0aW9uYCksIHtcblx0XHRcdFx0XHRhY3R1YWw6IHNuYXBzaG90LFxuXHRcdFx0XHRcdGV4cGVjdGVkOiBkaWZmZXJlbnRTbmFwc2hvdC5zbmFwc2hvdFxuXHRcdFx0XHR9KTtcblx0XHRcdH1cblx0XHR9XG5cdFx0dGhpcy5faW5saW5lU25hcHNob3RTdGFja3MucHVzaCh7XG5cdFx0XHQuLi5zdGFjayxcblx0XHRcdHRlc3RJZCxcblx0XHRcdHNuYXBzaG90XG5cdFx0fSk7XG5cdFx0cmV0dXJuIHN0YWNrO1xuXHR9XG5cdF9yZWNvbmNpbGUob3B0cykge1xuXHRcdC8vIFRoZXNlIGFyZSB0aGUgY29uZGl0aW9ucyBvbiB3aGVuIHRvIHdyaXRlIHNuYXBzaG90czpcblx0XHQvLyAgKiBUaGVyZSdzIG5vIHNuYXBzaG90IGZpbGUgaW4gYSBub24tQ0kgZW52aXJvbm1lbnQuXG5cdFx0Ly8gICogVGhlcmUgaXMgYSBzbmFwc2hvdCBmaWxlIGFuZCB3ZSBkZWNpZGVkIHRvIHVwZGF0ZSB0aGUgc25hcHNob3QuXG5cdFx0Ly8gICogVGhlcmUgaXMgYSBzbmFwc2hvdCBmaWxlLCBidXQgaXQgZG9lc24ndCBoYXZlIHRoaXMgc25hcHNob3QuXG5cdFx0Ly8gVGhlc2UgYXJlIHRoZSBjb25kaXRpb25zIG9uIHdoZW4gbm90IHRvIHdyaXRlIHNuYXBzaG90czpcblx0XHQvLyAgKiBUaGUgdXBkYXRlIGZsYWcgaXMgc2V0IHRvICdub25lJy5cblx0XHQvLyAgKiBUaGVyZSdzIG5vIHNuYXBzaG90IGZpbGUgb3IgYSBmaWxlIHdpdGhvdXQgdGhpcyBzbmFwc2hvdCBvbiBhIENJIGVudmlyb25tZW50LlxuXHRcdGlmIChvcHRzLmhhc1NuYXBzaG90ICYmIHRoaXMuX3VwZGF0ZVNuYXBzaG90ID09PSBcImFsbFwiIHx8ICghb3B0cy5oYXNTbmFwc2hvdCB8fCAhb3B0cy5zbmFwc2hvdElzUGVyc2lzdGVkKSAmJiAodGhpcy5fdXBkYXRlU25hcHNob3QgPT09IFwibmV3XCIgfHwgdGhpcy5fdXBkYXRlU25hcHNob3QgPT09IFwiYWxsXCIpKSB7XG5cdFx0XHRpZiAodGhpcy5fdXBkYXRlU25hcHNob3QgPT09IFwiYWxsXCIpIHtcblx0XHRcdFx0aWYgKCFvcHRzLnBhc3MpIHtcblx0XHRcdFx0XHRpZiAob3B0cy5oYXNTbmFwc2hvdCkge1xuXHRcdFx0XHRcdFx0dGhpcy51cGRhdGVkLmluY3JlbWVudChvcHRzLnRlc3RJZCk7XG5cdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdHRoaXMuYWRkZWQuaW5jcmVtZW50KG9wdHMudGVzdElkKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0dGhpcy5fYWRkU25hcHNob3Qob3B0cy5rZXksIG9wdHMuYWRkVmFsdWUsIHtcblx0XHRcdFx0XHRcdHN0YWNrOiBvcHRzLnN0YWNrLFxuXHRcdFx0XHRcdFx0dGVzdElkOiBvcHRzLnRlc3RJZCxcblx0XHRcdFx0XHRcdHJhd1NuYXBzaG90OiBvcHRzLnJhd1NuYXBzaG90LFxuXHRcdFx0XHRcdFx0YXNzZXJ0aW9uTmFtZTogb3B0cy5hc3NlcnRpb25OYW1lXG5cdFx0XHRcdFx0fSk7XG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0dGhpcy5tYXRjaGVkLmluY3JlbWVudChvcHRzLnRlc3RJZCk7XG5cdFx0XHRcdH1cblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdHRoaXMuX2FkZFNuYXBzaG90KG9wdHMua2V5LCBvcHRzLmFkZFZhbHVlLCB7XG5cdFx0XHRcdFx0c3RhY2s6IG9wdHMuc3RhY2ssXG5cdFx0XHRcdFx0dGVzdElkOiBvcHRzLnRlc3RJZCxcblx0XHRcdFx0XHRyYXdTbmFwc2hvdDogb3B0cy5yYXdTbmFwc2hvdCxcblx0XHRcdFx0XHRhc3NlcnRpb25OYW1lOiBvcHRzLmFzc2VydGlvbk5hbWVcblx0XHRcdFx0fSk7XG5cdFx0XHRcdHRoaXMuYWRkZWQuaW5jcmVtZW50KG9wdHMudGVzdElkKTtcblx0XHRcdH1cblx0XHRcdHJldHVybiB7XG5cdFx0XHRcdGFjdHVhbDogXCJcIixcblx0XHRcdFx0Y291bnQ6IG9wdHMuY291bnQsXG5cdFx0XHRcdGV4cGVjdGVkOiBcIlwiLFxuXHRcdFx0XHRrZXk6IG9wdHMua2V5LFxuXHRcdFx0XHRwYXNzOiB0cnVlXG5cdFx0XHR9O1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRpZiAoIW9wdHMucGFzcykge1xuXHRcdFx0XHR0aGlzLnVubWF0Y2hlZC5pbmNyZW1lbnQob3B0cy50ZXN0SWQpO1xuXHRcdFx0XHRyZXR1cm4ge1xuXHRcdFx0XHRcdGFjdHVhbDogb3B0cy5hY3R1YWxEaXNwbGF5LFxuXHRcdFx0XHRcdGNvdW50OiBvcHRzLmNvdW50LFxuXHRcdFx0XHRcdGV4cGVjdGVkOiBvcHRzLmV4cGVjdGVkRGlzcGxheSxcblx0XHRcdFx0XHRrZXk6IG9wdHMua2V5LFxuXHRcdFx0XHRcdHBhc3M6IGZhbHNlXG5cdFx0XHRcdH07XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHR0aGlzLm1hdGNoZWQuaW5jcmVtZW50KG9wdHMudGVzdElkKTtcblx0XHRcdFx0cmV0dXJuIHtcblx0XHRcdFx0XHRhY3R1YWw6IFwiXCIsXG5cdFx0XHRcdFx0Y291bnQ6IG9wdHMuY291bnQsXG5cdFx0XHRcdFx0ZXhwZWN0ZWQ6IFwiXCIsXG5cdFx0XHRcdFx0a2V5OiBvcHRzLmtleSxcblx0XHRcdFx0XHRwYXNzOiB0cnVlXG5cdFx0XHRcdH07XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cdGFzeW5jIHNhdmUoKSB7XG5cdFx0Y29uc3QgaGFzRXh0ZXJuYWxTbmFwc2hvdHMgPSBPYmplY3Qua2V5cyh0aGlzLl9zbmFwc2hvdERhdGEpLmxlbmd0aDtcblx0XHRjb25zdCBoYXNJbmxpbmVTbmFwc2hvdHMgPSB0aGlzLl9pbmxpbmVTbmFwc2hvdHMubGVuZ3RoO1xuXHRcdGNvbnN0IGhhc1Jhd1NuYXBzaG90cyA9IHRoaXMuX3Jhd1NuYXBzaG90cy5sZW5ndGg7XG5cdFx0Y29uc3QgaXNFbXB0eSA9ICFoYXNFeHRlcm5hbFNuYXBzaG90cyAmJiAhaGFzSW5saW5lU25hcHNob3RzICYmICFoYXNSYXdTbmFwc2hvdHM7XG5cdFx0Y29uc3Qgc3RhdHVzID0ge1xuXHRcdFx0ZGVsZXRlZDogZmFsc2UsXG5cdFx0XHRzYXZlZDogZmFsc2Vcblx0XHR9O1xuXHRcdGlmICgodGhpcy5fZGlydHkgfHwgdGhpcy5fdW5jaGVja2VkS2V5cy5zaXplKSAmJiAhaXNFbXB0eSkge1xuXHRcdFx0aWYgKGhhc0V4dGVybmFsU25hcHNob3RzKSB7XG5cdFx0XHRcdGF3YWl0IHNhdmVTbmFwc2hvdEZpbGUodGhpcy5fZW52aXJvbm1lbnQsIHRoaXMuX3NuYXBzaG90RGF0YSwgdGhpcy5zbmFwc2hvdFBhdGgpO1xuXHRcdFx0XHR0aGlzLl9maWxlRXhpc3RzID0gdHJ1ZTtcblx0XHRcdH1cblx0XHRcdGlmIChoYXNJbmxpbmVTbmFwc2hvdHMpIHtcblx0XHRcdFx0YXdhaXQgc2F2ZUlubGluZVNuYXBzaG90cyh0aGlzLl9lbnZpcm9ubWVudCwgdGhpcy5faW5saW5lU25hcHNob3RzKTtcblx0XHRcdH1cblx0XHRcdGlmIChoYXNSYXdTbmFwc2hvdHMpIHtcblx0XHRcdFx0YXdhaXQgc2F2ZVJhd1NuYXBzaG90cyh0aGlzLl9lbnZpcm9ubWVudCwgdGhpcy5fcmF3U25hcHNob3RzKTtcblx0XHRcdH1cblx0XHRcdHN0YXR1cy5zYXZlZCA9IHRydWU7XG5cdFx0fSBlbHNlIGlmICghaGFzRXh0ZXJuYWxTbmFwc2hvdHMgJiYgdGhpcy5fZmlsZUV4aXN0cykge1xuXHRcdFx0aWYgKHRoaXMuX3VwZGF0ZVNuYXBzaG90ID09PSBcImFsbFwiKSB7XG5cdFx0XHRcdGF3YWl0IHRoaXMuX2Vudmlyb25tZW50LnJlbW92ZVNuYXBzaG90RmlsZSh0aGlzLnNuYXBzaG90UGF0aCk7XG5cdFx0XHRcdHRoaXMuX2ZpbGVFeGlzdHMgPSBmYWxzZTtcblx0XHRcdH1cblx0XHRcdHN0YXR1cy5kZWxldGVkID0gdHJ1ZTtcblx0XHR9XG5cdFx0cmV0dXJuIHN0YXR1cztcblx0fVxuXHRnZXRVbmNoZWNrZWRDb3VudCgpIHtcblx0XHRyZXR1cm4gdGhpcy5fdW5jaGVja2VkS2V5cy5zaXplIHx8IDA7XG5cdH1cblx0Z2V0VW5jaGVja2VkS2V5cygpIHtcblx0XHRyZXR1cm4gQXJyYXkuZnJvbSh0aGlzLl91bmNoZWNrZWRLZXlzKTtcblx0fVxuXHRyZW1vdmVVbmNoZWNrZWRLZXlzKCkge1xuXHRcdGlmICh0aGlzLl91cGRhdGVTbmFwc2hvdCA9PT0gXCJhbGxcIiAmJiB0aGlzLl91bmNoZWNrZWRLZXlzLnNpemUpIHtcblx0XHRcdHRoaXMuX2RpcnR5ID0gdHJ1ZTtcblx0XHRcdHRoaXMuX3VuY2hlY2tlZEtleXMuZm9yRWFjaCgoa2V5KSA9PiBkZWxldGUgdGhpcy5fc25hcHNob3REYXRhW2tleV0pO1xuXHRcdFx0dGhpcy5fdW5jaGVja2VkS2V5cy5jbGVhcigpO1xuXHRcdH1cblx0fVxuXHRwcm9iZUV4cGVjdGVkU25hcHNob3Qob3B0aW9ucykge1xuXHRcdGNvbnN0IGNvdW50ID0gdGhpcy5fY291bnRlcnMuZ2V0KG9wdGlvbnMudGVzdE5hbWUpICsgMTtcblx0XHRjb25zdCBrZXkgPSB0ZXN0TmFtZVRvS2V5KG9wdGlvbnMudGVzdE5hbWUsIGNvdW50KTtcblx0XHRyZXR1cm4ge1xuXHRcdFx0a2V5LFxuXHRcdFx0Y291bnQsXG5cdFx0XHRkYXRhOiBvcHRpb25zPy5pc0lubGluZSA/IG9wdGlvbnMuaW5saW5lU25hcHNob3QgOiB0aGlzLl9zbmFwc2hvdERhdGFba2V5XSxcblx0XHRcdG1hcmtBc0NoZWNrZWQ6ICgpID0+IHtcblx0XHRcdFx0dGhpcy5fY291bnRlcnMuaW5jcmVtZW50KG9wdGlvbnMudGVzdE5hbWUpO1xuXHRcdFx0XHR0aGlzLl90ZXN0SWRUb0tleXMuZ2V0KG9wdGlvbnMudGVzdElkKS5wdXNoKGtleSk7XG5cdFx0XHRcdHRoaXMuX3VuY2hlY2tlZEtleXMuZGVsZXRlKGtleSk7XG5cdFx0XHR9XG5cdFx0fTtcblx0fVxuXHRtYXRjaCh7IHRlc3RJZCwgdGVzdE5hbWUsIHJlY2VpdmVkLCBrZXksIGlubGluZVNuYXBzaG90LCBpc0lubGluZSwgZXJyb3IsIHJhd1NuYXBzaG90LCBhc3NlcnRpb25OYW1lIH0pIHtcblx0XHRjb25zdCByZXNvbHZlZCA9IHRoaXMuX3Jlc29sdmVLZXkodGVzdElkLCB0ZXN0TmFtZSwga2V5KTtcblx0XHRrZXkgPSByZXNvbHZlZC5rZXk7XG5cdFx0Y29uc3QgY291bnQgPSByZXNvbHZlZC5jb3VudDtcblx0XHQvLyBEbyBub3QgbWFyayB0aGUgc25hcHNob3QgYXMgXCJjaGVja2VkXCIgaWYgdGhlIHNuYXBzaG90IGlzIGlubGluZSBhbmRcblx0XHQvLyB0aGVyZSdzIGFuIGV4dGVybmFsIHNuYXBzaG90LiBUaGlzIHdheSB0aGUgZXh0ZXJuYWwgc25hcHNob3QgY2FuIGJlXG5cdFx0Ly8gcmVtb3ZlZCB3aXRoIGAtLXVwZGF0ZVNuYXBzaG90YC5cblx0XHRpZiAoIShpc0lubGluZSAmJiB0aGlzLl9zbmFwc2hvdERhdGFba2V5XSAhPT0gdW5kZWZpbmVkKSkge1xuXHRcdFx0dGhpcy5fdW5jaGVja2VkS2V5cy5kZWxldGUoa2V5KTtcblx0XHR9XG5cdFx0bGV0IHJlY2VpdmVkU2VyaWFsaXplZCA9IHJhd1NuYXBzaG90ICYmIHR5cGVvZiByZWNlaXZlZCA9PT0gXCJzdHJpbmdcIiA/IHJlY2VpdmVkIDogc2VyaWFsaXplKHJlY2VpdmVkLCB1bmRlZmluZWQsIHRoaXMuX3NuYXBzaG90Rm9ybWF0KTtcblx0XHRpZiAoIXJhd1NuYXBzaG90KSB7XG5cdFx0XHRyZWNlaXZlZFNlcmlhbGl6ZWQgPSBhZGRFeHRyYUxpbmVCcmVha3MocmVjZWl2ZWRTZXJpYWxpemVkKTtcblx0XHR9XG5cdFx0aWYgKHJhd1NuYXBzaG90KSB7XG5cdFx0XHQvLyBub3JtYWxpemUgRU9MIHdoZW4gc25hcHNob3QgY29udGFpbnMgQ1JMRiBidXQgcmVjZWl2ZWQgaXMgTEZcblx0XHRcdGlmIChyYXdTbmFwc2hvdC5jb250ZW50ICYmIHJhd1NuYXBzaG90LmNvbnRlbnQubWF0Y2goL1xcclxcbi8pICYmICFyZWNlaXZlZFNlcmlhbGl6ZWQubWF0Y2goL1xcclxcbi8pKSB7XG5cdFx0XHRcdHJhd1NuYXBzaG90LmNvbnRlbnQgPSBub3JtYWxpemVOZXdsaW5lcyhyYXdTbmFwc2hvdC5jb250ZW50KTtcblx0XHRcdH1cblx0XHR9XG5cdFx0Y29uc3QgZXhwZWN0ZWQgPSBpc0lubGluZSA/IGlubGluZVNuYXBzaG90IDogcmF3U25hcHNob3QgPyByYXdTbmFwc2hvdC5jb250ZW50IDogdGhpcy5fc25hcHNob3REYXRhW2tleV07XG5cdFx0Y29uc3QgZXhwZWN0ZWRUcmltbWVkID0gcmF3U25hcHNob3QgPyBleHBlY3RlZCA6IGV4cGVjdGVkPy50cmltKCk7XG5cdFx0Y29uc3QgcGFzcyA9IGV4cGVjdGVkVHJpbW1lZCA9PT0gKHJhd1NuYXBzaG90ID8gcmVjZWl2ZWRTZXJpYWxpemVkIDogcmVjZWl2ZWRTZXJpYWxpemVkLnRyaW0oKSk7XG5cdFx0Y29uc3QgaGFzU25hcHNob3QgPSBleHBlY3RlZCAhPT0gdW5kZWZpbmVkO1xuXHRcdGNvbnN0IHNuYXBzaG90SXNQZXJzaXN0ZWQgPSBpc0lubGluZSB8fCB0aGlzLl9maWxlRXhpc3RzIHx8IHJhd1NuYXBzaG90ICYmIHJhd1NuYXBzaG90LmNvbnRlbnQgIT0gbnVsbDtcblx0XHRpZiAocGFzcyAmJiAhaXNJbmxpbmUgJiYgIXJhd1NuYXBzaG90KSB7XG5cdFx0XHQvLyBXaGVuIHRoZSBmaWxlIGlzIHJlLXNhdmVkIChiZWNhdXNlIG90aGVyIHNuYXBzaG90cyBjaGFuZ2VkKSwgdGhlIEpTXG5cdFx0XHQvLyByb3VuZC10cmlwIGNhbiBsb3NlIHByb3BlciBlc2NhcGluZy4gUmVmcmVzaCBpbi1tZW1vcnkgZGF0YSB3aXRoIHRoZVxuXHRcdFx0Ly8gZnJlc2hseSBzZXJpYWxpemVkIHN0cmluZyBzbyB0aGUgZmlsZSBpcyB3cml0dGVuIGNvcnJlY3RseS5cblx0XHRcdC8vIF9yZWNvbmNpbGUgZG9lcyBub3Qgd3JpdGUgX3NuYXBzaG90RGF0YSBvbiBwYXNzLCBzbyB0aGlzIGlzIHRoZSBvbmx5XG5cdFx0XHQvLyBwbGFjZSBpdCBnZXRzIHJlZnJlc2hlZC4gRG9tYWluIHNuYXBzaG90cyBza2lwIHRoaXMgYmVjYXVzZSB0aGUgc3RvcmVkXG5cdFx0XHQvLyB2YWx1ZSBtYXkgY29udGFpbiBtYXRjaCBwYXR0ZXJucyB0aGF0IGRpZmZlciBmcm9tIHRoZSByZWNlaXZlZCBvdXRwdXQuXG5cdFx0XHR0aGlzLl9zbmFwc2hvdERhdGFba2V5XSA9IHJlY2VpdmVkU2VyaWFsaXplZDtcblx0XHR9XG5cdFx0Y29uc3Qgc3RhY2sgPSBpc0lubGluZSA/IHRoaXMuX3Jlc29sdmVJbmxpbmVTdGFjayh7XG5cdFx0XHR0ZXN0SWQsXG5cdFx0XHRzbmFwc2hvdDogcmVjZWl2ZWRTZXJpYWxpemVkLFxuXHRcdFx0YXNzZXJ0aW9uTmFtZTogYXNzZXJ0aW9uTmFtZSB8fCBcInRvTWF0Y2hJbmxpbmVTbmFwc2hvdFwiLFxuXHRcdFx0ZXJyb3I6IGVycm9yIHx8IG5ldyBFcnJvcihcInNuYXBzaG90XCIpXG5cdFx0fSkgOiB1bmRlZmluZWQ7XG5cdFx0cmV0dXJuIHRoaXMuX3JlY29uY2lsZSh7XG5cdFx0XHR0ZXN0SWQsXG5cdFx0XHRrZXksXG5cdFx0XHRjb3VudCxcblx0XHRcdHBhc3MsXG5cdFx0XHRoYXNTbmFwc2hvdCxcblx0XHRcdHNuYXBzaG90SXNQZXJzaXN0ZWQ6ICEhc25hcHNob3RJc1BlcnNpc3RlZCxcblx0XHRcdGFkZFZhbHVlOiByZWNlaXZlZFNlcmlhbGl6ZWQsXG5cdFx0XHRhY3R1YWxEaXNwbGF5OiByYXdTbmFwc2hvdCA/IHJlY2VpdmVkU2VyaWFsaXplZCA6IHJlbW92ZUV4dHJhTGluZUJyZWFrcyhyZWNlaXZlZFNlcmlhbGl6ZWQpLFxuXHRcdFx0ZXhwZWN0ZWREaXNwbGF5OiBleHBlY3RlZFRyaW1tZWQgIT09IHVuZGVmaW5lZCA/IHJhd1NuYXBzaG90ID8gZXhwZWN0ZWRUcmltbWVkIDogcmVtb3ZlRXh0cmFMaW5lQnJlYWtzKGV4cGVjdGVkVHJpbW1lZCkgOiB1bmRlZmluZWQsXG5cdFx0XHRzdGFjayxcblx0XHRcdHJhd1NuYXBzaG90LFxuXHRcdFx0YXNzZXJ0aW9uTmFtZVxuXHRcdH0pO1xuXHR9XG5cdHByb2Nlc3NEb21haW5TbmFwc2hvdCh7IHRlc3RJZCwgcmVjZWl2ZWQsIGV4cGVjdGVkU25hcHNob3QsIG1hdGNoUmVzdWx0LCBpc0lubGluZSwgZXJyb3IsIGFzc2VydGlvbk5hbWUgfSkge1xuXHRcdGNvbnN0IHN0YWNrID0gaXNJbmxpbmUgPyB0aGlzLl9yZXNvbHZlSW5saW5lU3RhY2soe1xuXHRcdFx0dGVzdElkLFxuXHRcdFx0c25hcHNob3Q6IHJlY2VpdmVkLFxuXHRcdFx0YXNzZXJ0aW9uTmFtZSxcblx0XHRcdGVycm9yOiBlcnJvciB8fCBuZXcgRXJyb3IoXCJTVEFDS19UUkFDRV9FUlJPUlwiKVxuXHRcdH0pIDogdW5kZWZpbmVkO1xuXHRcdGNvbnN0IGFjdHVhbFJlc29sdmVkID0gbWF0Y2hSZXN1bHQ/LnJlc29sdmVkID8/IHJlY2VpdmVkO1xuXHRcdGNvbnN0IGV4cGVjdGVkUmVzb2x2ZWQgPSBtYXRjaFJlc3VsdD8uZXhwZWN0ZWQgPz8gZXhwZWN0ZWRTbmFwc2hvdC5kYXRhO1xuXHRcdHJldHVybiB0aGlzLl9yZWNvbmNpbGUoe1xuXHRcdFx0dGVzdElkLFxuXHRcdFx0a2V5OiBleHBlY3RlZFNuYXBzaG90LmtleSxcblx0XHRcdGNvdW50OiBleHBlY3RlZFNuYXBzaG90LmNvdW50LFxuXHRcdFx0cGFzczogbWF0Y2hSZXN1bHQ/LnBhc3MgPz8gZmFsc2UsXG5cdFx0XHRoYXNTbmFwc2hvdDogISFleHBlY3RlZFNuYXBzaG90LmRhdGEsXG5cdFx0XHRzbmFwc2hvdElzUGVyc2lzdGVkOiBpc0lubGluZSA/IHRydWUgOiB0aGlzLl9maWxlRXhpc3RzLFxuXHRcdFx0YWRkVmFsdWU6IGFjdHVhbFJlc29sdmVkLFxuXHRcdFx0YWN0dWFsRGlzcGxheTogcmVtb3ZlRXh0cmFMaW5lQnJlYWtzKGFjdHVhbFJlc29sdmVkKSxcblx0XHRcdGV4cGVjdGVkRGlzcGxheTogZXhwZWN0ZWRSZXNvbHZlZCAhPT0gdW5kZWZpbmVkID8gcmVtb3ZlRXh0cmFMaW5lQnJlYWtzKGV4cGVjdGVkUmVzb2x2ZWQpIDogdW5kZWZpbmVkLFxuXHRcdFx0c3RhY2ssXG5cdFx0XHRhc3NlcnRpb25OYW1lXG5cdFx0fSk7XG5cdH1cblx0YXN5bmMgcGFjaygpIHtcblx0XHRjb25zdCBzbmFwc2hvdCA9IHtcblx0XHRcdGZpbGVwYXRoOiB0aGlzLnRlc3RGaWxlUGF0aCxcblx0XHRcdGFkZGVkOiAwLFxuXHRcdFx0ZmlsZURlbGV0ZWQ6IGZhbHNlLFxuXHRcdFx0bWF0Y2hlZDogMCxcblx0XHRcdHVuY2hlY2tlZDogMCxcblx0XHRcdHVuY2hlY2tlZEtleXM6IFtdLFxuXHRcdFx0dW5tYXRjaGVkOiAwLFxuXHRcdFx0dXBkYXRlZDogMFxuXHRcdH07XG5cdFx0Y29uc3QgdW5jaGVja2VkQ291bnQgPSB0aGlzLmdldFVuY2hlY2tlZENvdW50KCk7XG5cdFx0Y29uc3QgdW5jaGVja2VkS2V5cyA9IHRoaXMuZ2V0VW5jaGVja2VkS2V5cygpO1xuXHRcdGlmICh1bmNoZWNrZWRDb3VudCkge1xuXHRcdFx0dGhpcy5yZW1vdmVVbmNoZWNrZWRLZXlzKCk7XG5cdFx0fVxuXHRcdGNvbnN0IHN0YXR1cyA9IGF3YWl0IHRoaXMuc2F2ZSgpO1xuXHRcdHNuYXBzaG90LmZpbGVEZWxldGVkID0gc3RhdHVzLmRlbGV0ZWQ7XG5cdFx0c25hcHNob3QuYWRkZWQgPSB0aGlzLmFkZGVkLnRvdGFsKCk7XG5cdFx0c25hcHNob3QubWF0Y2hlZCA9IHRoaXMubWF0Y2hlZC50b3RhbCgpO1xuXHRcdHNuYXBzaG90LnVubWF0Y2hlZCA9IHRoaXMudW5tYXRjaGVkLnRvdGFsKCk7XG5cdFx0c25hcHNob3QudXBkYXRlZCA9IHRoaXMudXBkYXRlZC50b3RhbCgpO1xuXHRcdHNuYXBzaG90LnVuY2hlY2tlZCA9ICFzdGF0dXMuZGVsZXRlZCA/IHVuY2hlY2tlZENvdW50IDogMDtcblx0XHRzbmFwc2hvdC51bmNoZWNrZWRLZXlzID0gQXJyYXkuZnJvbSh1bmNoZWNrZWRLZXlzKTtcblx0XHRyZXR1cm4gc25hcHNob3Q7XG5cdH1cbn1cblxuZnVuY3Rpb24gY3JlYXRlTWlzbWF0Y2hFcnJvcihtZXNzYWdlLCBleHBhbmQsIGFjdHVhbCwgZXhwZWN0ZWQpIHtcblx0Y29uc3QgZXJyb3IgPSBuZXcgRXJyb3IobWVzc2FnZSk7XG5cdE9iamVjdC5kZWZpbmVQcm9wZXJ0eShlcnJvciwgXCJhY3R1YWxcIiwge1xuXHRcdHZhbHVlOiBhY3R1YWwsXG5cdFx0ZW51bWVyYWJsZTogdHJ1ZSxcblx0XHRjb25maWd1cmFibGU6IHRydWUsXG5cdFx0d3JpdGFibGU6IHRydWVcblx0fSk7XG5cdE9iamVjdC5kZWZpbmVQcm9wZXJ0eShlcnJvciwgXCJleHBlY3RlZFwiLCB7XG5cdFx0dmFsdWU6IGV4cGVjdGVkLFxuXHRcdGVudW1lcmFibGU6IHRydWUsXG5cdFx0Y29uZmlndXJhYmxlOiB0cnVlLFxuXHRcdHdyaXRhYmxlOiB0cnVlXG5cdH0pO1xuXHRPYmplY3QuZGVmaW5lUHJvcGVydHkoZXJyb3IsIFwiZGlmZk9wdGlvbnNcIiwgeyB2YWx1ZTogeyBleHBhbmQgfSB9KTtcblx0cmV0dXJuIGVycm9yO1xufVxuY2xhc3MgU25hcHNob3RDbGllbnQge1xuXHRzbmFwc2hvdFN0YXRlTWFwID0gbmV3IE1hcCgpO1xuXHRjb25zdHJ1Y3RvcihvcHRpb25zID0ge30pIHtcblx0XHR0aGlzLm9wdGlvbnMgPSBvcHRpb25zO1xuXHR9XG5cdGFzeW5jIHNldHVwKGZpbGVwYXRoLCBvcHRpb25zKSB7XG5cdFx0aWYgKHRoaXMuc25hcHNob3RTdGF0ZU1hcC5oYXMoZmlsZXBhdGgpKSB7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXHRcdHRoaXMuc25hcHNob3RTdGF0ZU1hcC5zZXQoZmlsZXBhdGgsIGF3YWl0IFNuYXBzaG90U3RhdGUuY3JlYXRlKGZpbGVwYXRoLCBvcHRpb25zKSk7XG5cdH1cblx0YXN5bmMgZmluaXNoKGZpbGVwYXRoKSB7XG5cdFx0Y29uc3Qgc3RhdGUgPSB0aGlzLmdldFNuYXBzaG90U3RhdGUoZmlsZXBhdGgpO1xuXHRcdGNvbnN0IHJlc3VsdCA9IGF3YWl0IHN0YXRlLnBhY2soKTtcblx0XHR0aGlzLnNuYXBzaG90U3RhdGVNYXAuZGVsZXRlKGZpbGVwYXRoKTtcblx0XHRyZXR1cm4gcmVzdWx0O1xuXHR9XG5cdHNraXBUZXN0KGZpbGVwYXRoLCB0ZXN0TmFtZSkge1xuXHRcdGNvbnN0IHN0YXRlID0gdGhpcy5nZXRTbmFwc2hvdFN0YXRlKGZpbGVwYXRoKTtcblx0XHRzdGF0ZS5tYXJrU25hcHNob3RzQXNDaGVja2VkRm9yVGVzdCh0ZXN0TmFtZSk7XG5cdH1cblx0Y2xlYXJUZXN0KGZpbGVwYXRoLCB0ZXN0SWQpIHtcblx0XHRjb25zdCBzdGF0ZSA9IHRoaXMuZ2V0U25hcHNob3RTdGF0ZShmaWxlcGF0aCk7XG5cdFx0c3RhdGUuY2xlYXJUZXN0KHRlc3RJZCk7XG5cdH1cblx0Z2V0U25hcHNob3RTdGF0ZShmaWxlcGF0aCkge1xuXHRcdGNvbnN0IHN0YXRlID0gdGhpcy5zbmFwc2hvdFN0YXRlTWFwLmdldChmaWxlcGF0aCk7XG5cdFx0aWYgKCFzdGF0ZSkge1xuXHRcdFx0dGhyb3cgbmV3IEVycm9yKGBUaGUgc25hcHNob3Qgc3RhdGUgZm9yICcke2ZpbGVwYXRofScgaXMgbm90IGZvdW5kLiBEaWQgeW91IGNhbGwgJ1NuYXBzaG90Q2xpZW50LnNldHVwKCknP2ApO1xuXHRcdH1cblx0XHRyZXR1cm4gc3RhdGU7XG5cdH1cblx0bWF0Y2gob3B0aW9ucykge1xuXHRcdGNvbnN0IHsgZmlsZXBhdGgsIG5hbWUsIHRlc3RJZCA9IG5hbWUsIG1lc3NhZ2UsIGlzSW5saW5lID0gZmFsc2UsIHByb3BlcnRpZXMsIGlubGluZVNuYXBzaG90LCBlcnJvciwgZXJyb3JNZXNzYWdlLCByYXdTbmFwc2hvdCwgYXNzZXJ0aW9uTmFtZSB9ID0gb3B0aW9ucztcblx0XHRsZXQgeyByZWNlaXZlZCB9ID0gb3B0aW9ucztcblx0XHRpZiAoIWZpbGVwYXRoKSB7XG5cdFx0XHR0aHJvdyBuZXcgRXJyb3IoXCJTbmFwc2hvdCBjYW5ub3QgYmUgdXNlZCBvdXRzaWRlIG9mIHRlc3RcIik7XG5cdFx0fVxuXHRcdGNvbnN0IHNuYXBzaG90U3RhdGUgPSB0aGlzLmdldFNuYXBzaG90U3RhdGUoZmlsZXBhdGgpO1xuXHRcdGNvbnN0IHRlc3ROYW1lID0gW25hbWUsIC4uLm1lc3NhZ2UgPyBbbWVzc2FnZV0gOiBbXV0uam9pbihcIiA+IFwiKTtcblx0XHQvLyBQcm9iZSBmaXJzdCBzbyB3ZSBjYW4gbWFyayBhcyBjaGVja2VkIGV2ZW4gb24gZWFybHkgcmV0dXJuXG5cdFx0Y29uc3QgZXhwZWN0ZWRTbmFwc2hvdCA9IHNuYXBzaG90U3RhdGUucHJvYmVFeHBlY3RlZFNuYXBzaG90KHtcblx0XHRcdHRlc3ROYW1lLFxuXHRcdFx0dGVzdElkLFxuXHRcdFx0aXNJbmxpbmUsXG5cdFx0XHRpbmxpbmVTbmFwc2hvdFxuXHRcdH0pO1xuXHRcdGlmICh0eXBlb2YgcHJvcGVydGllcyA9PT0gXCJvYmplY3RcIikge1xuXHRcdFx0aWYgKHR5cGVvZiByZWNlaXZlZCAhPT0gXCJvYmplY3RcIiB8fCAhcmVjZWl2ZWQpIHtcblx0XHRcdFx0ZXhwZWN0ZWRTbmFwc2hvdC5tYXJrQXNDaGVja2VkKCk7XG5cdFx0XHRcdHRocm93IG5ldyBFcnJvcihcIlJlY2VpdmVkIHZhbHVlIG11c3QgYmUgYW4gb2JqZWN0IHdoZW4gdGhlIG1hdGNoZXIgaGFzIHByb3BlcnRpZXNcIik7XG5cdFx0XHR9XG5cdFx0XHRsZXQgcHJvcGVydGllc1Bhc3M7XG5cdFx0XHR0cnkge1xuXHRcdFx0XHRwcm9wZXJ0aWVzUGFzcyA9IHRoaXMub3B0aW9ucy5pc0VxdWFsPy4ocmVjZWl2ZWQsIHByb3BlcnRpZXMpID8/IGZhbHNlO1xuXHRcdFx0fSBjYXRjaCAoZXJyKSB7XG5cdFx0XHRcdGV4cGVjdGVkU25hcHNob3QubWFya0FzQ2hlY2tlZCgpO1xuXHRcdFx0XHR0aHJvdyBlcnI7XG5cdFx0XHR9XG5cdFx0XHRpZiAoIXByb3BlcnRpZXNQYXNzKSB7XG5cdFx0XHRcdGV4cGVjdGVkU25hcHNob3QubWFya0FzQ2hlY2tlZCgpO1xuXHRcdFx0XHRyZXR1cm4ge1xuXHRcdFx0XHRcdHBhc3M6IGZhbHNlLFxuXHRcdFx0XHRcdG1lc3NhZ2U6ICgpID0+IGVycm9yTWVzc2FnZSB8fCBcIlNuYXBzaG90IHByb3BlcnRpZXMgbWlzbWF0Y2hlZFwiLFxuXHRcdFx0XHRcdGFjdHVhbDogcmVjZWl2ZWQsXG5cdFx0XHRcdFx0ZXhwZWN0ZWQ6IHByb3BlcnRpZXNcblx0XHRcdFx0fTtcblx0XHRcdH1cblx0XHRcdHJlY2VpdmVkID0gZGVlcE1lcmdlU25hcHNob3QocmVjZWl2ZWQsIHByb3BlcnRpZXMpO1xuXHRcdH1cblx0XHRjb25zdCB7IGFjdHVhbCwgZXhwZWN0ZWQsIGtleSwgcGFzcyB9ID0gc25hcHNob3RTdGF0ZS5tYXRjaCh7XG5cdFx0XHR0ZXN0SWQsXG5cdFx0XHR0ZXN0TmFtZSxcblx0XHRcdHJlY2VpdmVkLFxuXHRcdFx0aXNJbmxpbmUsXG5cdFx0XHRlcnJvcixcblx0XHRcdGlubGluZVNuYXBzaG90LFxuXHRcdFx0cmF3U25hcHNob3QsXG5cdFx0XHRhc3NlcnRpb25OYW1lXG5cdFx0fSk7XG5cdFx0cmV0dXJuIHtcblx0XHRcdHBhc3MsXG5cdFx0XHRtZXNzYWdlOiAoKSA9PiBgU25hcHNob3QgXFxgJHtrZXkgfHwgXCJ1bmtub3duXCJ9XFxgIG1pc21hdGNoZWRgLFxuXHRcdFx0YWN0dWFsOiByYXdTbmFwc2hvdCA/IGFjdHVhbCA6IGFjdHVhbD8udHJpbSgpLFxuXHRcdFx0ZXhwZWN0ZWQ6IHJhd1NuYXBzaG90ID8gZXhwZWN0ZWQgOiBleHBlY3RlZD8udHJpbSgpXG5cdFx0fTtcblx0fVxuXHRhc3NlcnQob3B0aW9ucykge1xuXHRcdGNvbnN0IHJlc3VsdCA9IHRoaXMubWF0Y2gob3B0aW9ucyk7XG5cdFx0aWYgKCFyZXN1bHQucGFzcykge1xuXHRcdFx0Y29uc3Qgc25hcHNob3RTdGF0ZSA9IHRoaXMuZ2V0U25hcHNob3RTdGF0ZShvcHRpb25zLmZpbGVwYXRoKTtcblx0XHRcdHRocm93IGNyZWF0ZU1pc21hdGNoRXJyb3IocmVzdWx0Lm1lc3NhZ2UoKSwgc25hcHNob3RTdGF0ZS5leHBhbmQsIHJlc3VsdC5hY3R1YWwsIHJlc3VsdC5leHBlY3RlZCk7XG5cdFx0fVxuXHR9XG5cdG1hdGNoRG9tYWluKG9wdGlvbnMpIHtcblx0XHRjb25zdCB7IHJlY2VpdmVkLCBmaWxlcGF0aCwgbmFtZSwgdGVzdElkID0gbmFtZSwgbWVzc2FnZSwgYWRhcHRlciwgaXNJbmxpbmUgPSBmYWxzZSwgaW5saW5lU25hcHNob3QsIGVycm9yIH0gPSBvcHRpb25zO1xuXHRcdGlmICghZmlsZXBhdGgpIHtcblx0XHRcdHRocm93IG5ldyBFcnJvcihcIlNuYXBzaG90IGNhbm5vdCBiZSB1c2VkIG91dHNpZGUgb2YgdGVzdFwiKTtcblx0XHR9XG5cdFx0Y29uc3QgY2FwdHVyZWQgPSBhZGFwdGVyLmNhcHR1cmUocmVjZWl2ZWQpO1xuXHRcdGNvbnN0IHJlbmRlcmVkID0gYWRhcHRlci5yZW5kZXIoY2FwdHVyZWQpO1xuXHRcdGNvbnN0IHNuYXBzaG90U3RhdGUgPSB0aGlzLmdldFNuYXBzaG90U3RhdGUoZmlsZXBhdGgpO1xuXHRcdGNvbnN0IHRlc3ROYW1lID0gW25hbWUsIC4uLm1lc3NhZ2UgPyBbbWVzc2FnZV0gOiBbXV0uam9pbihcIiA+IFwiKTtcblx0XHRjb25zdCBleHBlY3RlZFNuYXBzaG90ID0gc25hcHNob3RTdGF0ZS5wcm9iZUV4cGVjdGVkU25hcHNob3Qoe1xuXHRcdFx0dGVzdE5hbWUsXG5cdFx0XHR0ZXN0SWQsXG5cdFx0XHRpc0lubGluZSxcblx0XHRcdGlubGluZVNuYXBzaG90XG5cdFx0fSk7XG5cdFx0ZXhwZWN0ZWRTbmFwc2hvdC5tYXJrQXNDaGVja2VkKCk7XG5cdFx0Y29uc3QgbWF0Y2hSZXN1bHQgPSBleHBlY3RlZFNuYXBzaG90LmRhdGEgPyBhZGFwdGVyLm1hdGNoKGNhcHR1cmVkLCBhZGFwdGVyLnBhcnNlRXhwZWN0ZWQoZXhwZWN0ZWRTbmFwc2hvdC5kYXRhKSkgOiB1bmRlZmluZWQ7XG5cdFx0Y29uc3QgeyBhY3R1YWwsIGV4cGVjdGVkLCBrZXksIHBhc3MgfSA9IHNuYXBzaG90U3RhdGUucHJvY2Vzc0RvbWFpblNuYXBzaG90KHtcblx0XHRcdHRlc3RJZCxcblx0XHRcdHJlY2VpdmVkOiByZW5kZXJlZCxcblx0XHRcdGV4cGVjdGVkU25hcHNob3QsXG5cdFx0XHRtYXRjaFJlc3VsdCxcblx0XHRcdGlzSW5saW5lLFxuXHRcdFx0ZXJyb3IsXG5cdFx0XHRhc3NlcnRpb25OYW1lOiBvcHRpb25zLmFzc2VydGlvbk5hbWVcblx0XHR9KTtcblx0XHRyZXR1cm4ge1xuXHRcdFx0cGFzcyxcblx0XHRcdG1lc3NhZ2U6ICgpID0+IGBTbmFwc2hvdCBcXGAke2tleX1cXGAgbWlzbWF0Y2hlZGAsXG5cdFx0XHRhY3R1YWw6IGFjdHVhbD8udHJpbSgpLFxuXHRcdFx0ZXhwZWN0ZWQ6IGV4cGVjdGVkPy50cmltKClcblx0XHR9O1xuXHR9XG5cdGFzeW5jIHBvbGxNYXRjaERvbWFpbihvcHRpb25zKSB7XG5cdFx0Y29uc3QgeyBwb2xsLCBmaWxlcGF0aCwgbmFtZSwgdGVzdElkID0gbmFtZSwgbWVzc2FnZSwgYWRhcHRlciwgaXNJbmxpbmUgPSBmYWxzZSwgaW5saW5lU25hcHNob3QsIGVycm9yLCB0aW1lb3V0ID0gMWUzLCBpbnRlcnZhbCA9IDUwIH0gPSBvcHRpb25zO1xuXHRcdGlmICghZmlsZXBhdGgpIHtcblx0XHRcdHRocm93IG5ldyBFcnJvcihcIlNuYXBzaG90IGNhbm5vdCBiZSB1c2VkIG91dHNpZGUgb2YgdGVzdFwiKTtcblx0XHR9XG5cdFx0Y29uc3Qgc25hcHNob3RTdGF0ZSA9IHRoaXMuZ2V0U25hcHNob3RTdGF0ZShmaWxlcGF0aCk7XG5cdFx0Y29uc3QgdGVzdE5hbWUgPSBbbmFtZSwgLi4ubWVzc2FnZSA/IFttZXNzYWdlXSA6IFtdXS5qb2luKFwiID4gXCIpO1xuXHRcdGNvbnN0IGV4cGVjdGVkU25hcHNob3QgPSBzbmFwc2hvdFN0YXRlLnByb2JlRXhwZWN0ZWRTbmFwc2hvdCh7XG5cdFx0XHR0ZXN0TmFtZSxcblx0XHRcdHRlc3RJZCxcblx0XHRcdGlzSW5saW5lLFxuXHRcdFx0aW5saW5lU25hcHNob3Rcblx0XHR9KTtcblx0XHRjb25zdCByZWZlcmVuY2UgPSBleHBlY3RlZFNuYXBzaG90LmRhdGEgJiYgc25hcHNob3RTdGF0ZS5zbmFwc2hvdFVwZGF0ZVN0YXRlICE9PSBcImFsbFwiID8gYWRhcHRlci5wYXJzZUV4cGVjdGVkKGV4cGVjdGVkU25hcHNob3QuZGF0YSkgOiB1bmRlZmluZWQ7XG5cdFx0Y29uc3QgdGltZWRPdXQgPSB0aW1lb3V0ID4gMCA/IG5ldyBQcm9taXNlKChyKSA9PiBzZXRUaW1lb3V0KHIsIHRpbWVvdXQpKSA6IHVuZGVmaW5lZDtcblx0XHRjb25zdCBzdGFibGVSZXN1bHQgPSBhd2FpdCBnZXRTdGFibGVTbmFwc2hvdCh7XG5cdFx0XHRhZGFwdGVyLFxuXHRcdFx0cG9sbCxcblx0XHRcdGludGVydmFsLFxuXHRcdFx0dGltZWRPdXQsXG5cdFx0XHRtYXRjaDogcmVmZXJlbmNlID8gKGNhcHR1cmVkKSA9PiBhZGFwdGVyLm1hdGNoKGNhcHR1cmVkLCByZWZlcmVuY2UpLnBhc3MgOiB1bmRlZmluZWRcblx0XHR9KTtcblx0XHRleHBlY3RlZFNuYXBzaG90Lm1hcmtBc0NoZWNrZWQoKTtcblx0XHRpZiAoIXN0YWJsZVJlc3VsdD8ucmVuZGVyZWQpIHtcblx0XHRcdC8vIHRoZSBvcmlnaW5hbCBjYWxsZXIgYGV4cGVjdC5wb2xsYCBsYXRlciBtYW5pcHVsYXRlcyBlcnJvciB2aWEgYHRocm93V2l0aENhdXNlYCxcblx0XHRcdC8vIHNvIGhlcmUgd2UgY2FuIGRpcmVjdGx5IHRocm93IGBsYXN0UG9sbEVycm9yYCBpZiBleGlzdHMuXG5cdFx0XHRpZiAoc3RhYmxlUmVzdWx0Py5sYXN0UG9sbEVycm9yKSB7XG5cdFx0XHRcdHRocm93IHN0YWJsZVJlc3VsdC5sYXN0UG9sbEVycm9yO1xuXHRcdFx0fVxuXHRcdFx0cmV0dXJuIHtcblx0XHRcdFx0cGFzczogZmFsc2UsXG5cdFx0XHRcdG1lc3NhZ2U6ICgpID0+IGBwb2xsKCkgZGlkIG5vdCBwcm9kdWNlIGEgc3RhYmxlIHNuYXBzaG90IHdpdGhpbiB0aGUgdGltZW91dGBcblx0XHRcdH07XG5cdFx0fVxuXHRcdC8vIFRPRE86IHNob3VsZCBgYWxsYCBtb2RlIGlnbm9yZSBwYXJzZSBlcnJvcj9cblx0XHQvLyBTaWVsZW50bHkgaGlkaW5nIHRoZSBlcnJvciBhbmQgY3JlYXRpbmcgc25hcGhzb3QgZnVsbCBzY3JhdGNoIGlzbid0IGdvb2QgZWl0aGVyLlxuXHRcdC8vIFVzZXJzIGNhbiBmaXggb3IgcHVyZ2UgdGhlIGJyb2tlbiBzbmFwc2hvdCBtYW51YWxseSBhbmQgdGhhdCBkZWNpc2lvbiBhZmZlY3RzIGhvdyBkb21haW4gc25hcHNob3QgZ2V0cyB1cGRhdGVkLlxuXHRcdGNvbnN0IG1hdGNoUmVzdWx0ID0gZXhwZWN0ZWRTbmFwc2hvdC5kYXRhID8gYWRhcHRlci5tYXRjaChzdGFibGVSZXN1bHQuY2FwdHVyZWQsIGFkYXB0ZXIucGFyc2VFeHBlY3RlZChleHBlY3RlZFNuYXBzaG90LmRhdGEpKSA6IHVuZGVmaW5lZDtcblx0XHRjb25zdCB7IGFjdHVhbCwgZXhwZWN0ZWQsIGtleSwgcGFzcyB9ID0gc25hcHNob3RTdGF0ZS5wcm9jZXNzRG9tYWluU25hcHNob3Qoe1xuXHRcdFx0dGVzdElkLFxuXHRcdFx0cmVjZWl2ZWQ6IHN0YWJsZVJlc3VsdC5yZW5kZXJlZCxcblx0XHRcdGV4cGVjdGVkU25hcHNob3QsXG5cdFx0XHRtYXRjaFJlc3VsdCxcblx0XHRcdGlzSW5saW5lLFxuXHRcdFx0ZXJyb3IsXG5cdFx0XHRhc3NlcnRpb25OYW1lOiBvcHRpb25zLmFzc2VydGlvbk5hbWVcblx0XHR9KTtcblx0XHRyZXR1cm4ge1xuXHRcdFx0cGFzcyxcblx0XHRcdG1lc3NhZ2U6ICgpID0+IGBTbmFwc2hvdCBcXGAke2tleX1cXGAgbWlzbWF0Y2hlZGAsXG5cdFx0XHRhY3R1YWw6IGFjdHVhbD8udHJpbSgpLFxuXHRcdFx0ZXhwZWN0ZWQ6IGV4cGVjdGVkPy50cmltKClcblx0XHR9O1xuXHR9XG5cdGFzeW5jIGFzc2VydFJhdyhvcHRpb25zKSB7XG5cdFx0aWYgKCFvcHRpb25zLnJhd1NuYXBzaG90KSB7XG5cdFx0XHR0aHJvdyBuZXcgRXJyb3IoXCJSYXcgc25hcHNob3QgaXMgcmVxdWlyZWRcIik7XG5cdFx0fVxuXHRcdGNvbnN0IHsgZmlsZXBhdGgsIHJhd1NuYXBzaG90IH0gPSBvcHRpb25zO1xuXHRcdGlmIChyYXdTbmFwc2hvdC5jb250ZW50ID09IG51bGwpIHtcblx0XHRcdGlmICghZmlsZXBhdGgpIHtcblx0XHRcdFx0dGhyb3cgbmV3IEVycm9yKFwiU25hcHNob3QgY2Fubm90IGJlIHVzZWQgb3V0c2lkZSBvZiB0ZXN0XCIpO1xuXHRcdFx0fVxuXHRcdFx0Y29uc3Qgc25hcHNob3RTdGF0ZSA9IHRoaXMuZ2V0U25hcHNob3RTdGF0ZShmaWxlcGF0aCk7XG5cdFx0XHQvLyBzYXZlIHRoZSBmaWxlcGF0aCwgc28gaXQgZG9uJ3QgbG9zZSBldmVuIGlmIHRoZSBhd2FpdCBtYWtlIGl0IG91dC1vZi1jb250ZXh0XG5cdFx0XHRvcHRpb25zLmZpbGVwYXRoIHx8PSBmaWxlcGF0aDtcblx0XHRcdC8vIHJlc29sdmUgYW5kIHJlYWQgdGhlIHJhdyBzbmFwc2hvdCBmaWxlXG5cdFx0XHRyYXdTbmFwc2hvdC5maWxlID0gYXdhaXQgc25hcHNob3RTdGF0ZS5lbnZpcm9ubWVudC5yZXNvbHZlUmF3UGF0aChmaWxlcGF0aCwgcmF3U25hcHNob3QuZmlsZSk7XG5cdFx0XHRyYXdTbmFwc2hvdC5jb250ZW50ID0gYXdhaXQgc25hcHNob3RTdGF0ZS5lbnZpcm9ubWVudC5yZWFkU25hcHNob3RGaWxlKHJhd1NuYXBzaG90LmZpbGUpID8/IHVuZGVmaW5lZDtcblx0XHR9XG5cdFx0cmV0dXJuIHRoaXMuYXNzZXJ0KG9wdGlvbnMpO1xuXHR9XG5cdGNsZWFyKCkge1xuXHRcdHRoaXMuc25hcHNob3RTdGF0ZU1hcC5jbGVhcigpO1xuXHR9XG59XG4vKipcbiogUG9sbHMgcmVwZWF0ZWRseSB1bnRpbCB0aGUgdmFsdWUgcmVhY2hlcyBhIHN0YWJsZSBzdGF0ZS5cbipcbiogQ29tcGFyZXMgY29uc2VjdXRpdmUgcmVuZGVyZWQgb3V0cHV0cyBmcm9tIHRoZSBjdXJyZW50IHNlc3Npb24g4oCUXG4qIHdoZW4gdHdvIGNvbnNlY3V0aXZlIHBvbGxzIHByb2R1Y2UgdGhlIHNhbWUgcmVuZGVyZWQgc3RyaW5nLFxuKiB0aGUgdmFsdWUgaXMgY29uc2lkZXJlZCBzdGFibGUuXG4qXG4qIEV2ZXJ5IGBhd2FpdGAgKHBvbGwgY2FsbCwgaW50ZXJ2YWwgZGVsYXkpIHJhY2VzIGFnYWluc3QgYHRpbWVkT3V0YFxuKiBzbyB0aGF0IGhhbmdpbmcgcG9sbHMgYW5kIGRlbGF5cyBhcmUgaW50ZXJydXB0ZWQuXG4qL1xuYXN5bmMgZnVuY3Rpb24gZ2V0U3RhYmxlU25hcHNob3QoeyBhZGFwdGVyLCBwb2xsLCBpbnRlcnZhbCwgdGltZWRPdXQsIG1hdGNoIH0pIHtcblx0bGV0IGxhc3RSZW5kZXJlZDtcblx0bGV0IGxhc3RQb2xsRXJyb3I7XG5cdGxldCBsYXN0U3RhYmxlO1xuXHR3aGlsZSAodHJ1ZSkge1xuXHRcdHRyeSB7XG5cdFx0XHRjb25zdCBwb2xsUmVzdWx0ID0gYXdhaXQgcmFjZVdpdGgoUHJvbWlzZS5yZXNvbHZlKHBvbGwoKSksIHRpbWVkT3V0KTtcblx0XHRcdGlmICghcG9sbFJlc3VsdC5vaykge1xuXHRcdFx0XHRicmVhaztcblx0XHRcdH1cblx0XHRcdGNvbnN0IGNhcHR1cmVkID0gYWRhcHRlci5jYXB0dXJlKHBvbGxSZXN1bHQudmFsdWUpO1xuXHRcdFx0Y29uc3QgcmVuZGVyZWQgPSBhZGFwdGVyLnJlbmRlcihjYXB0dXJlZCk7XG5cdFx0XHRpZiAobGFzdFJlbmRlcmVkICE9PSB1bmRlZmluZWQgJiYgcmVuZGVyZWQgPT09IGxhc3RSZW5kZXJlZCkge1xuXHRcdFx0XHRsYXN0U3RhYmxlID0ge1xuXHRcdFx0XHRcdGNhcHR1cmVkLFxuXHRcdFx0XHRcdHJlbmRlcmVkXG5cdFx0XHRcdH07XG5cdFx0XHRcdGlmICghbWF0Y2ggfHwgbWF0Y2goY2FwdHVyZWQpKSB7XG5cdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdH1cblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdGxhc3RSZW5kZXJlZCA9IHJlbmRlcmVkO1xuXHRcdFx0XHRsYXN0U3RhYmxlID0gdW5kZWZpbmVkO1xuXHRcdFx0fVxuXHRcdH0gY2F0Y2ggKHBvbGxFcnJvcikge1xuXHRcdFx0Ly8gcG9sbCgpIHRocmV3IOKAlCByZXNldCBzdGFiaWxpdHkgYmFzZWxpbmUgYW5kIHJldHJ5XG5cdFx0XHRsYXN0UmVuZGVyZWQgPSB1bmRlZmluZWQ7XG5cdFx0XHRsYXN0U3RhYmxlID0gdW5kZWZpbmVkO1xuXHRcdFx0bGFzdFBvbGxFcnJvciA9IHBvbGxFcnJvcjtcblx0XHR9XG5cdFx0Y29uc3QgZGVsYXllZCA9IGF3YWl0IHJhY2VXaXRoKG5ldyBQcm9taXNlKChyKSA9PiBzZXRUaW1lb3V0KHIsIGludGVydmFsKSksIHRpbWVkT3V0KTtcblx0XHRpZiAoIWRlbGF5ZWQub2spIHtcblx0XHRcdGJyZWFrO1xuXHRcdH1cblx0fVxuXHRyZXR1cm4ge1xuXHRcdC4uLmxhc3RTdGFibGUsXG5cdFx0bGFzdFBvbGxFcnJvclxuXHR9O1xufVxuLyoqIFR5cGUtc2FmZSBgUHJvbWlzZS5yYWNlYCDigJQgdGVsbHMgeW91IHdoaWNoIHByb21pc2Ugd29uLiAqL1xuZnVuY3Rpb24gcmFjZVdpdGgocHJvbWlzZSwgb3RoZXIpIHtcblx0Y29uc3QgbGVmdCA9IHByb21pc2UudGhlbigodmFsdWUpID0+ICh7XG5cdFx0b2s6IHRydWUsXG5cdFx0dmFsdWVcblx0fSkpO1xuXHRpZiAoIW90aGVyKSB7XG5cdFx0cmV0dXJuIGxlZnQ7XG5cdH1cblx0cmV0dXJuIFByb21pc2UucmFjZShbbGVmdCwgb3RoZXIudGhlbigodmFsdWUpID0+ICh7XG5cdFx0b2s6IGZhbHNlLFxuXHRcdHZhbHVlXG5cdH0pKV0pO1xufVxuXG5leHBvcnQgeyBTbmFwc2hvdENsaWVudCwgU25hcHNob3RTdGF0ZSwgYWRkU2VyaWFsaXplciwgZ2V0U2VyaWFsaXplcnMsIHN0cmlwU25hcHNob3RJbmRlbnRhdGlvbiB9O1xuIl0sInhfZ29vZ2xlX2lnbm9yZUxpc3QiOlswXSwibWFwcGluZ3MiOiI7Ozs7O0FBS0EsU0FBUyx3QkFBd0IsR0FBRztDQUNuQyxPQUFPLEtBQUssRUFBRSxjQUFjLE9BQU8sVUFBVSxlQUFlLEtBQUssR0FBRyxTQUFTLElBQUksRUFBRSxhQUFhO0FBQ2pHO0FBRUEsSUFBSSxtQkFBbUIsRUFBQyxTQUFTLENBQUMsRUFBQztBQUVuQyxJQUFJO0FBRUosU0FBUyx3QkFBeUI7Q0FDakMsSUFBSSwyQkFBMkIsT0FBTyxpQkFBaUI7Q0FDdkQsNEJBQTRCOzs7Ozs7OztDQVU1QixJQUFJLGlCQUFp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
|