@logixjs/sandbox 0.0.1 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/package.json +3 -1
- package/public/sandbox/chunks/chunk-2AUQRESB.js +1114 -0
- package/public/sandbox/chunks/chunk-2F72LQKW.js +194 -0
- package/public/sandbox/chunks/chunk-2PYDGDD3.js +4071 -0
- package/public/sandbox/chunks/chunk-2UGKSXDZ.js +16 -0
- package/public/sandbox/chunks/chunk-2XVE7F26.js +153 -0
- package/public/sandbox/chunks/chunk-3A7TFNZN.js +219 -0
- package/public/sandbox/chunks/chunk-3BHC6JAV.js +1070 -0
- package/public/sandbox/chunks/chunk-3U4CAKCX.js +61 -0
- package/public/sandbox/chunks/chunk-3VU3JLZO.js +272 -0
- package/public/sandbox/chunks/chunk-4CPONKWY.js +1170 -0
- package/public/sandbox/chunks/chunk-4GMUQTWH.js +850 -0
- package/public/sandbox/chunks/chunk-4KIYG5E4.js +749 -0
- package/public/sandbox/chunks/chunk-4MY35XR3.js +175 -0
- package/public/sandbox/chunks/chunk-5DNHJMHA.js +69 -0
- package/public/sandbox/chunks/chunk-5EC4S7X6.js +42 -0
- package/public/sandbox/chunks/chunk-5FB7QFSH.js +227 -0
- package/public/sandbox/chunks/chunk-5GEYCJW2.js +206 -0
- package/public/sandbox/chunks/chunk-5PT7Q5SS.js +373 -0
- package/public/sandbox/chunks/chunk-5WN5IGKA.js +166 -0
- package/public/sandbox/chunks/chunk-5XOBKSOT.js +213 -0
- package/public/sandbox/chunks/chunk-67RVISUC.js +313 -0
- package/public/sandbox/chunks/chunk-6ELJEKZS.js +12 -0
- package/public/sandbox/chunks/chunk-6FKWRVP4.js +85 -0
- package/public/sandbox/chunks/chunk-6JRP52YT.js +34 -0
- package/public/sandbox/chunks/chunk-6JYAC3G6.js +42 -0
- package/public/sandbox/chunks/chunk-6TUOP63Q.js +86 -0
- package/public/sandbox/chunks/{chunk-A6JFUNQQ.js → chunk-74C5VW7Z.js} +2 -2
- package/public/sandbox/chunks/chunk-75DQFC5M.js +16 -0
- package/public/sandbox/chunks/{chunk-UCFEP3BH.js → chunk-7GPAF2UK.js} +1 -1
- package/public/sandbox/chunks/chunk-7KQFTS2Y.js +135 -0
- package/public/sandbox/chunks/chunk-7POKWYE3.js +112 -0
- package/public/sandbox/chunks/chunk-7VUEF5F3.js +395 -0
- package/public/sandbox/chunks/chunk-7W5APZS2.js +77 -0
- package/public/sandbox/chunks/chunk-A6OFCXDQ.js +397 -0
- package/public/sandbox/chunks/chunk-A7HLOSO6.js +216 -0
- package/public/sandbox/chunks/chunk-AGF4RRCB.js +408 -0
- package/public/sandbox/chunks/chunk-ASJSJAAL.js +122 -0
- package/public/sandbox/chunks/chunk-ASVMK364.js +283 -0
- package/public/sandbox/chunks/chunk-AUDTI2BQ.js +895 -0
- package/public/sandbox/chunks/chunk-B2SZTA3M.js +16 -0
- package/public/sandbox/chunks/chunk-B6YS2UMV.js +372 -0
- package/public/sandbox/chunks/chunk-BCEO3MGD.js +244 -0
- package/public/sandbox/chunks/chunk-BCOO65D4.js +373 -0
- package/public/sandbox/chunks/chunk-BJOWSSEL.js +38 -0
- package/public/sandbox/chunks/chunk-BS2WBFW4.js +373 -0
- package/public/sandbox/chunks/chunk-BUVHG3NJ.js +439 -0
- package/public/sandbox/chunks/chunk-BVE33AN6.js +42 -0
- package/public/sandbox/chunks/chunk-BWTGJZVP.js +19 -0
- package/public/sandbox/chunks/chunk-BXD7GZC3.js +1025 -0
- package/public/sandbox/chunks/chunk-BZH4EUUD.js +164 -0
- package/public/sandbox/chunks/{chunk-HFV5GJPK.js → chunk-C2MYMMO4.js} +3 -3
- package/public/sandbox/chunks/chunk-CRE4NJJ6.js +271 -0
- package/public/sandbox/chunks/chunk-CVZPRIDB.js +706 -0
- package/public/sandbox/chunks/chunk-CWOXD5NG.js +991 -0
- package/public/sandbox/chunks/chunk-D6DOC3BJ.js +373 -0
- package/public/sandbox/chunks/chunk-DEPSGFSY.js +1698 -0
- package/public/sandbox/chunks/chunk-DM7C5NP5.js +819 -0
- package/public/sandbox/chunks/chunk-DN33LMOF.js +1112 -0
- package/public/sandbox/chunks/{chunk-S46P7MC6.js → chunk-DT7YIIWE.js} +2 -2
- package/public/sandbox/chunks/chunk-DVB5WRCI.js +260 -0
- package/public/sandbox/chunks/{chunk-TOHCFMQS.js → chunk-E3EVW7NR.js} +11 -18
- package/public/sandbox/chunks/chunk-E5BV567Q.js +417 -0
- package/public/sandbox/chunks/chunk-E7BIWMQQ.js +203 -0
- package/public/sandbox/chunks/chunk-EAKGPSOQ.js +83 -0
- package/public/sandbox/chunks/chunk-EGUYL2ER.js +75 -0
- package/public/sandbox/chunks/chunk-EP5GQYZ5.js +85 -0
- package/public/sandbox/chunks/chunk-ET6CJEHC.js +221 -0
- package/public/sandbox/chunks/chunk-EU67YZHZ.js +1070 -0
- package/public/sandbox/chunks/{chunk-PTSJJANP.js → chunk-EYNDQLSB.js} +1 -1
- package/public/sandbox/chunks/{chunk-CEGSWZ5S.js → chunk-EZTMVCJF.js} +1 -1
- package/public/sandbox/chunks/chunk-F5CLVIS6.js +907 -0
- package/public/sandbox/chunks/chunk-F743SKYD.js +85 -0
- package/public/sandbox/chunks/chunk-FEGFZ5OX.js +86 -0
- package/public/sandbox/chunks/chunk-FG5B7ZX3.js +373 -0
- package/public/sandbox/chunks/chunk-FKZPYMDG.js +373 -0
- package/public/sandbox/chunks/chunk-FNLXHWIU.js +220 -0
- package/public/sandbox/chunks/chunk-FQRUTYAD.js +1991 -0
- package/public/sandbox/chunks/{chunk-VLYP4WUS.js → chunk-FY5A73NK.js} +5 -5
- package/public/sandbox/chunks/chunk-G7FAOG3O.js +221 -0
- package/public/sandbox/chunks/chunk-GFXHUC7Y.js +73 -0
- package/public/sandbox/chunks/chunk-GIPXUIZQ.js +534 -0
- package/public/sandbox/chunks/chunk-GP37MEGJ.js +52 -0
- package/public/sandbox/chunks/chunk-GXL5QCMF.js +4511 -0
- package/public/sandbox/chunks/chunk-GZ2NSE6A.js +177 -0
- package/public/sandbox/chunks/chunk-GZATW4YD.js +69 -0
- package/public/sandbox/chunks/chunk-H4EBXROQ.js +166 -0
- package/public/sandbox/chunks/chunk-HETCPK6Z.js +153 -0
- package/public/sandbox/chunks/chunk-HGUFQ2QC.js +4431 -0
- package/public/sandbox/chunks/chunk-HGV3VNH3.js +255 -0
- package/public/sandbox/chunks/chunk-HIJ67QWR.js +5397 -0
- package/public/sandbox/chunks/chunk-IDHERBKW.js +1114 -0
- package/public/sandbox/chunks/chunk-IDTK4FIY.js +102 -0
- package/public/sandbox/chunks/chunk-ILFVY7H5.js +164 -0
- package/public/sandbox/chunks/chunk-ISGSRYGO.js +57 -0
- package/public/sandbox/chunks/chunk-J45VPU24.js +408 -0
- package/public/sandbox/chunks/chunk-JAUIM3O5.js +42 -0
- package/public/sandbox/chunks/chunk-JB7OQEM6.js +373 -0
- package/public/sandbox/chunks/chunk-JCKW6NHD.js +15 -0
- package/public/sandbox/chunks/chunk-JMA7GY7Z.js +221 -0
- package/public/sandbox/chunks/chunk-JY46J6IL.js +836 -0
- package/public/sandbox/chunks/{chunk-X72PZOFA.js → chunk-K2MQ66O7.js} +1 -1
- package/public/sandbox/chunks/chunk-KA7PZA6F.js +464 -0
- package/public/sandbox/chunks/chunk-KDEQTUID.js +102 -0
- package/public/sandbox/chunks/chunk-KDJR27JV.js +1696 -0
- package/public/sandbox/chunks/chunk-KFE3JO6N.js +77 -0
- package/public/sandbox/chunks/chunk-KLDSYWT5.js +536 -0
- package/public/sandbox/chunks/chunk-KQWWFYBF.js +203 -0
- package/public/sandbox/chunks/chunk-KTFZSXOW.js +6473 -0
- package/public/sandbox/chunks/chunk-KXVIC55U.js +108 -0
- package/public/sandbox/chunks/{chunk-HNEDTEGQ.js → chunk-L4PNO2H6.js} +1 -1
- package/public/sandbox/chunks/{chunk-WE4STGO2.js → chunk-L4ZNW5DI.js} +2 -2
- package/public/sandbox/chunks/chunk-LBUINGZ4.js +836 -0
- package/public/sandbox/chunks/chunk-LIYPPU6I.js +112 -0
- package/public/sandbox/chunks/chunk-LJHTOJXW.js +221 -0
- package/public/sandbox/chunks/{chunk-BWSNPKO5.js → chunk-LQL23SWJ.js} +2 -2
- package/public/sandbox/chunks/chunk-LTFCYZQ6.js +46 -0
- package/public/sandbox/chunks/chunk-LTWLVCKQ.js +166 -0
- package/public/sandbox/chunks/chunk-LWI7BXFN.js +395 -0
- package/public/sandbox/chunks/chunk-LYBBX6WM.js +225 -0
- package/public/sandbox/chunks/chunk-MXE7HIBM.js +474 -0
- package/public/sandbox/chunks/chunk-MYBDYNK4.js +6004 -0
- package/public/sandbox/chunks/chunk-NC2MIWZX.js +732 -0
- package/public/sandbox/chunks/chunk-NE447XAF.js +597 -0
- package/public/sandbox/chunks/chunk-NEAYV5C2.js +255 -0
- package/public/sandbox/chunks/chunk-NMGFJZ4I.js +26 -0
- package/public/sandbox/chunks/chunk-NWCJJZNQ.js +71 -0
- package/public/sandbox/chunks/chunk-O57OZBDR.js +214 -0
- package/public/sandbox/chunks/chunk-OJJT664Q.js +731 -0
- package/public/sandbox/chunks/chunk-OKTBUTCH.js +1175 -0
- package/public/sandbox/chunks/chunk-OQ4SYV5D.js +534 -0
- package/public/sandbox/chunks/chunk-OTVVIHJD.js +219 -0
- package/public/sandbox/chunks/chunk-OWTMSCF7.js +1052 -0
- package/public/sandbox/chunks/chunk-P5ZQNFC3.js +122 -0
- package/public/sandbox/chunks/chunk-PBPT2U2N.js +1698 -0
- package/public/sandbox/chunks/chunk-PHBJLCP3.js +836 -0
- package/public/sandbox/chunks/chunk-PHV4HYHB.js +397 -0
- package/public/sandbox/chunks/chunk-PIXQ6SOX.js +4071 -0
- package/public/sandbox/chunks/chunk-PKJL6YLK.js +73 -0
- package/public/sandbox/chunks/chunk-PKPOITIU.js +221 -0
- package/public/sandbox/chunks/{chunk-NQW73ACJ.js → chunk-PMXBOYQI.js} +1 -1
- package/public/sandbox/chunks/chunk-PQLZD7NR.js +836 -0
- package/public/sandbox/chunks/chunk-QEESVOZU.js +16 -0
- package/public/sandbox/chunks/chunk-QGIM3FQK.js +159 -0
- package/public/sandbox/chunks/chunk-QL5JNEDO.js +69 -0
- package/public/sandbox/chunks/chunk-QQOZ3RMH.js +867 -0
- package/public/sandbox/chunks/chunk-QUMEVT2F.js +194 -0
- package/public/sandbox/chunks/chunk-QVZBXYVY.js +102 -0
- package/public/sandbox/chunks/chunk-R5HQS6RB.js +135 -0
- package/public/sandbox/chunks/chunk-R75Q2CTT.js +900 -0
- package/public/sandbox/chunks/chunk-RBB6SHW2.js +253 -0
- package/public/sandbox/chunks/chunk-RDHNRWQP.js +383 -0
- package/public/sandbox/chunks/chunk-RIWOEI3T.js +1101 -0
- package/public/sandbox/chunks/chunk-RS5FFPUV.js +103 -0
- package/public/sandbox/chunks/chunk-RYSSJBGX.js +203 -0
- package/public/sandbox/chunks/chunk-S3KBAE5Z.js +1114 -0
- package/public/sandbox/chunks/chunk-S6ZZHV6G.js +244 -0
- package/public/sandbox/chunks/chunk-SFXJ24HY.js +499 -0
- package/public/sandbox/chunks/chunk-SH7TP5CJ.js +1109 -0
- package/public/sandbox/chunks/chunk-SI5OKFFY.js +317 -0
- package/public/sandbox/chunks/chunk-SIXNQNIR.js +86 -0
- package/public/sandbox/chunks/chunk-ST353BOX.js +42 -0
- package/public/sandbox/chunks/chunk-SYEHKMLP.js +1140 -0
- package/public/sandbox/chunks/chunk-SZ4KQUJU.js +69 -0
- package/public/sandbox/chunks/{chunk-5SOP6EKV.js → chunk-SZI65PSP.js} +5 -10
- package/public/sandbox/chunks/chunk-T7RLTSMX.js +78 -0
- package/public/sandbox/chunks/chunk-TJ2RLUTW.js +57 -0
- package/public/sandbox/chunks/chunk-TJB73XPN.js +4071 -0
- package/public/sandbox/chunks/chunk-TXJCYO56.js +4046 -0
- package/public/sandbox/chunks/chunk-U5J3LCYI.js +731 -0
- package/public/sandbox/chunks/chunk-UABFN3NH.js +208 -0
- package/public/sandbox/chunks/chunk-UBMUY7WO.js +13 -0
- package/public/sandbox/chunks/chunk-UC27CE32.js +69 -0
- package/public/sandbox/chunks/chunk-UJGVDFZN.js +147 -0
- package/public/sandbox/chunks/chunk-UNVLTK4N.js +122 -0
- package/public/sandbox/chunks/chunk-UQKQ6V3V.js +208 -0
- package/public/sandbox/chunks/chunk-UZZBHWIO.js +703 -0
- package/public/sandbox/chunks/chunk-VKZIJERL.js +1114 -0
- package/public/sandbox/chunks/chunk-VQQEAGID.js +372 -0
- package/public/sandbox/chunks/{chunk-3LX3KIQQ.js → chunk-W365QUZ5.js} +3 -5
- package/public/sandbox/chunks/chunk-WJY2LSWG.js +1052 -0
- package/public/sandbox/chunks/chunk-WNOBN3DX.js +391 -0
- package/public/sandbox/chunks/chunk-X2Z5VYG3.js +245 -0
- package/public/sandbox/chunks/chunk-X74KU74D.js +959 -0
- package/public/sandbox/chunks/chunk-XE7ULSGQ.js +46 -0
- package/public/sandbox/chunks/chunk-XRXUJZ3X.js +431 -0
- package/public/sandbox/chunks/chunk-XWHIN7CC.js +85 -0
- package/public/sandbox/chunks/chunk-Y2TVGGVL.js +527 -0
- package/public/sandbox/chunks/chunk-YMVMZA3U.js +1395 -0
- package/public/sandbox/chunks/chunk-YOBLFWDV.js +431 -0
- package/public/sandbox/chunks/chunk-YR2RFEZA.js +11 -0
- package/public/sandbox/chunks/chunk-YTD6A35P.js +836 -0
- package/public/sandbox/chunks/chunk-Z5L7EZXS.js +81 -0
- package/public/sandbox/chunks/chunk-Z65I5ET2.js +108 -0
- package/public/sandbox/chunks/chunk-Z6LV34RO.js +390 -0
- package/public/sandbox/chunks/chunk-ZAKUP6QG.js +1634 -0
- package/public/sandbox/chunks/chunk-ZHNYE2YH.js +731 -0
- package/public/sandbox/chunks/chunk-ZHQX3B3Y.js +867 -0
- package/public/sandbox/chunks/chunk-ZIXDFRHJ.js +731 -0
- package/public/sandbox/chunks/chunk-ZPZ2MZ4D.js +528 -0
- package/public/sandbox/chunks/chunk-ZQD6NZXB.js +373 -0
- package/public/sandbox/chunks/chunk-ZVVBP7ON.js +16 -0
- package/public/sandbox/chunks/chunk-ZWE3P6X2.js +11 -0
- package/public/sandbox/logix-core/Bound.js +14 -14
- package/public/sandbox/logix-core/Debug.js +12 -10
- package/public/sandbox/logix-core/EffectOp.js +3 -4
- package/public/sandbox/logix-core/Env.js +5 -2
- package/public/sandbox/logix-core/ExternalStore.js +239 -0
- package/public/sandbox/logix-core/Flow.js +7 -8
- package/public/sandbox/logix-core/Kernel.js +7 -4
- package/public/sandbox/logix-core/Link.js +33 -25
- package/public/sandbox/logix-core/Middleware.js +13 -11
- package/public/sandbox/logix-core/Module.js +93 -30
- package/public/sandbox/logix-core/ModuleTag.js +28 -25
- package/public/sandbox/logix-core/Observability.js +21 -19
- package/public/sandbox/logix-core/Process.js +27 -22
- package/public/sandbox/logix-core/ReadQuery.js +7 -11
- package/public/sandbox/logix-core/Reflection.js +173 -53
- package/public/sandbox/logix-core/Resource.js +6 -3
- package/public/sandbox/logix-core/Root.js +7 -3
- package/public/sandbox/logix-core/Runtime.js +54 -40
- package/public/sandbox/logix-core/ScopeRegistry.js +6 -3
- package/public/sandbox/logix-core/StateTrait.js +17 -14
- package/public/sandbox/logix-core/TraitLifecycle.js +8 -8
- package/public/sandbox/logix-core/Workflow.js +332 -0
- package/public/sandbox/logix-core.js +11133 -6622
- package/public/sandbox/logix-core.manifest.json +4 -2
- package/public/sandbox/worker.js +3 -3
- package/public/sandbox/chunks/chunk-4LRLOTMA.js +0 -1698
- package/public/sandbox/chunks/chunk-CDLXJHXY.js +0 -120
- package/public/sandbox/chunks/chunk-CZRI7MHA.js +0 -46
- package/public/sandbox/chunks/chunk-EJDFUZ4B.js +0 -408
- package/public/sandbox/chunks/chunk-IP63FME6.js +0 -282
- package/public/sandbox/chunks/chunk-JIXTOQXJ.js +0 -1103
- package/public/sandbox/chunks/chunk-MPUSOFJ3.js +0 -1928
- package/public/sandbox/chunks/chunk-ON2LY6HJ.js +0 -135
- package/public/sandbox/chunks/chunk-POIBXAH5.js +0 -995
- package/public/sandbox/chunks/chunk-PQ652ULI.js +0 -6359
- package/public/sandbox/chunks/chunk-RJQ4PG2F.js +0 -77
- package/public/sandbox/chunks/chunk-S4EXG3OS.js +0 -533
- package/public/sandbox/chunks/chunk-SUXDGXVE.js +0 -390
- package/public/sandbox/chunks/chunk-TOQ6SJ6O.js +0 -244
- package/public/sandbox/chunks/chunk-UKYAF3NL.js +0 -1036
- package/public/sandbox/chunks/chunk-UMVN3AWO.js +0 -395
- package/public/sandbox/chunks/chunk-WFV5PPWJ.js +0 -194
- package/public/sandbox/chunks/chunk-YF6IO732.js +0 -206
- package/public/sandbox/chunks/chunk-ZUBABAAO.js +0 -86
|
@@ -0,0 +1,1991 @@
|
|
|
1
|
+
// @logixjs/core subpath bundles for @logixjs/sandbox
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
ReplayLog,
|
|
5
|
+
getAtPath,
|
|
6
|
+
parseListItemFieldPath,
|
|
7
|
+
setAtPathMutating,
|
|
8
|
+
toListItemValuePath
|
|
9
|
+
} from "./chunk-C2MYMMO4.js";
|
|
10
|
+
import {
|
|
11
|
+
Snapshot,
|
|
12
|
+
internal,
|
|
13
|
+
keyHash
|
|
14
|
+
} from "./chunk-EZTMVCJF.js";
|
|
15
|
+
import {
|
|
16
|
+
create
|
|
17
|
+
} from "./chunk-KE2H62D6.js";
|
|
18
|
+
import {
|
|
19
|
+
mergeCanonical,
|
|
20
|
+
sanitize
|
|
21
|
+
} from "./chunk-X2Z5VYG3.js";
|
|
22
|
+
import {
|
|
23
|
+
compareFieldPath,
|
|
24
|
+
getFieldPathId,
|
|
25
|
+
makeFieldPathIdRegistry,
|
|
26
|
+
normalizeFieldPath
|
|
27
|
+
} from "./chunk-ASVMK364.js";
|
|
28
|
+
import {
|
|
29
|
+
getBoundInternals
|
|
30
|
+
} from "./chunk-7GPAF2UK.js";
|
|
31
|
+
import {
|
|
32
|
+
ReplayModeConfigTag,
|
|
33
|
+
forceSourceRefresh,
|
|
34
|
+
inSyncTransactionFiber,
|
|
35
|
+
isDevEnv
|
|
36
|
+
} from "./chunk-YMVMZA3U.js";
|
|
37
|
+
import {
|
|
38
|
+
RunSessionTag,
|
|
39
|
+
make,
|
|
40
|
+
run
|
|
41
|
+
} from "./chunk-W365QUZ5.js";
|
|
42
|
+
import {
|
|
43
|
+
currentDiagnosticsLevel,
|
|
44
|
+
record
|
|
45
|
+
} from "./chunk-SH7TP5CJ.js";
|
|
46
|
+
import {
|
|
47
|
+
EffectOpMiddlewareTag
|
|
48
|
+
} from "./chunk-SI5OKFFY.js";
|
|
49
|
+
import {
|
|
50
|
+
fnv1a32,
|
|
51
|
+
stableStringify
|
|
52
|
+
} from "./chunk-DT7YIIWE.js";
|
|
53
|
+
|
|
54
|
+
// ../logix-core/src/internal/state-trait/build.ts
|
|
55
|
+
import * as SchemaAST from "../effect/SchemaAST.js";
|
|
56
|
+
|
|
57
|
+
// ../logix-core/src/internal/state-trait/model.ts
|
|
58
|
+
var normalizeSpec = (spec) => {
|
|
59
|
+
const entries = [];
|
|
60
|
+
const isNode = (value) => typeof value === "object" && value !== null && value._tag === "StateTraitNode";
|
|
61
|
+
const isList = (value) => typeof value === "object" && value !== null && value._tag === "StateTraitList";
|
|
62
|
+
const joinPath = (prefix, suffix) => {
|
|
63
|
+
if (!prefix) return suffix;
|
|
64
|
+
if (!suffix) return prefix;
|
|
65
|
+
return `${prefix}.${suffix}`;
|
|
66
|
+
};
|
|
67
|
+
const prefixDeps = (deps, prefix) => {
|
|
68
|
+
if (!deps || deps.length === 0) return [];
|
|
69
|
+
return deps.map((d) => prefix ? joinPath(prefix, d) : d);
|
|
70
|
+
};
|
|
71
|
+
const normalizeEntry = (entry, fieldPath, depPrefix) => {
|
|
72
|
+
if (entry.kind === "computed") {
|
|
73
|
+
const meta = entry.meta;
|
|
74
|
+
const rawDeps = meta.deps;
|
|
75
|
+
const deps = rawDeps !== void 0 ? prefixDeps(rawDeps, depPrefix) : void 0;
|
|
76
|
+
return {
|
|
77
|
+
...entry,
|
|
78
|
+
fieldPath,
|
|
79
|
+
meta: { ...meta, deps }
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
if (entry.kind === "source") {
|
|
83
|
+
const meta = entry.meta;
|
|
84
|
+
const rawDeps = meta.deps;
|
|
85
|
+
const deps = rawDeps !== void 0 ? prefixDeps(rawDeps, depPrefix) : void 0;
|
|
86
|
+
return {
|
|
87
|
+
...entry,
|
|
88
|
+
fieldPath,
|
|
89
|
+
meta: { ...meta, deps, _fieldPath: fieldPath }
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
if (entry.kind === "externalStore") {
|
|
93
|
+
const meta = entry.meta;
|
|
94
|
+
return {
|
|
95
|
+
...entry,
|
|
96
|
+
fieldPath,
|
|
97
|
+
meta: { ...meta, _fieldPath: fieldPath }
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
if (entry.kind === "link") {
|
|
101
|
+
const meta = entry.meta;
|
|
102
|
+
const from = prefixDeps([meta.from], depPrefix)[0] ?? meta.from;
|
|
103
|
+
return {
|
|
104
|
+
...entry,
|
|
105
|
+
fieldPath,
|
|
106
|
+
meta: { ...meta, from }
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
return {
|
|
110
|
+
...entry,
|
|
111
|
+
fieldPath
|
|
112
|
+
};
|
|
113
|
+
};
|
|
114
|
+
const expandNode = (scopeId, joinPrefix, node, options) => {
|
|
115
|
+
const addEntry = (relativeTarget, raw) => {
|
|
116
|
+
const rel = raw.fieldPath ?? relativeTarget;
|
|
117
|
+
const fieldPath = joinPrefix ? joinPath(joinPrefix, String(rel)) : String(rel);
|
|
118
|
+
entries.push(normalizeEntry(raw, fieldPath, joinPrefix));
|
|
119
|
+
};
|
|
120
|
+
const expandMaybeRecord = (value) => {
|
|
121
|
+
if (!value) return;
|
|
122
|
+
if (typeof value.kind === "string") {
|
|
123
|
+
addEntry("", value);
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
const record2 = value;
|
|
127
|
+
for (const key in record2) {
|
|
128
|
+
if (!Object.prototype.hasOwnProperty.call(record2, key)) continue;
|
|
129
|
+
const entry = record2[key];
|
|
130
|
+
if (!entry) continue;
|
|
131
|
+
addEntry(key, entry);
|
|
132
|
+
}
|
|
133
|
+
};
|
|
134
|
+
expandMaybeRecord(node.computed);
|
|
135
|
+
expandMaybeRecord(node.source);
|
|
136
|
+
expandMaybeRecord(node.link);
|
|
137
|
+
expandMaybeRecord(node.externalStore);
|
|
138
|
+
if (node.check) {
|
|
139
|
+
const rules = {};
|
|
140
|
+
const checkDepsPrefix = options?.checkDepsPrefix ?? (joinPrefix.endsWith("[]") ? joinPrefix : "");
|
|
141
|
+
const prefixCheckDeps = (deps) => {
|
|
142
|
+
if (!deps || deps.length === 0) return [];
|
|
143
|
+
return deps.map((d) => d === "" ? scopeId : checkDepsPrefix ? joinPath(checkDepsPrefix, d) : d);
|
|
144
|
+
};
|
|
145
|
+
for (const name of Object.keys(node.check)) {
|
|
146
|
+
const rule = node.check[name];
|
|
147
|
+
if (typeof rule === "function") {
|
|
148
|
+
rules[name] = rule;
|
|
149
|
+
continue;
|
|
150
|
+
}
|
|
151
|
+
if (rule && typeof rule === "object") {
|
|
152
|
+
const meta = sanitize(rule.meta);
|
|
153
|
+
rules[name] = {
|
|
154
|
+
...rule,
|
|
155
|
+
deps: prefixCheckDeps(rule.deps),
|
|
156
|
+
meta
|
|
157
|
+
};
|
|
158
|
+
continue;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
entries.push({
|
|
162
|
+
fieldPath: scopeId,
|
|
163
|
+
kind: "check",
|
|
164
|
+
meta: {
|
|
165
|
+
rules,
|
|
166
|
+
writeback: { kind: "errors" }
|
|
167
|
+
}
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
};
|
|
171
|
+
for (const key in spec) {
|
|
172
|
+
if (!Object.prototype.hasOwnProperty.call(spec, key)) continue;
|
|
173
|
+
const raw = spec[key];
|
|
174
|
+
if (!raw) continue;
|
|
175
|
+
if (isList(raw)) {
|
|
176
|
+
const listPath = key;
|
|
177
|
+
if (raw.item) {
|
|
178
|
+
expandNode(`${listPath}[]`, `${listPath}[]`, raw.item);
|
|
179
|
+
}
|
|
180
|
+
if (raw.list) {
|
|
181
|
+
expandNode(listPath, listPath, raw.list, {
|
|
182
|
+
checkDepsPrefix: `${listPath}[]`
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
continue;
|
|
186
|
+
}
|
|
187
|
+
if (isNode(raw)) {
|
|
188
|
+
if (key === "$root") {
|
|
189
|
+
expandNode("$root", "", raw);
|
|
190
|
+
} else {
|
|
191
|
+
expandNode(key, key, raw);
|
|
192
|
+
}
|
|
193
|
+
continue;
|
|
194
|
+
}
|
|
195
|
+
const entry = raw;
|
|
196
|
+
const fieldPath = entry.fieldPath ?? key;
|
|
197
|
+
entries.push(normalizeEntry(entry, String(fieldPath), ""));
|
|
198
|
+
}
|
|
199
|
+
return entries;
|
|
200
|
+
};
|
|
201
|
+
var collectNodeMeta = (spec) => {
|
|
202
|
+
const out = /* @__PURE__ */ new Map();
|
|
203
|
+
const isNode = (value) => typeof value === "object" && value !== null && value._tag === "StateTraitNode";
|
|
204
|
+
const isList = (value) => typeof value === "object" && value !== null && value._tag === "StateTraitList";
|
|
205
|
+
const add = (scopeId, node) => {
|
|
206
|
+
const meta = sanitize(node.meta);
|
|
207
|
+
if (meta) out.set(scopeId, meta);
|
|
208
|
+
};
|
|
209
|
+
for (const key in spec) {
|
|
210
|
+
if (!Object.prototype.hasOwnProperty.call(spec, key)) continue;
|
|
211
|
+
const raw = spec[key];
|
|
212
|
+
if (!raw) continue;
|
|
213
|
+
if (isList(raw)) {
|
|
214
|
+
const listPath = key;
|
|
215
|
+
if (raw.item) add(`${listPath}[]`, raw.item);
|
|
216
|
+
if (raw.list) add(listPath, raw.list);
|
|
217
|
+
continue;
|
|
218
|
+
}
|
|
219
|
+
if (isNode(raw)) {
|
|
220
|
+
if (key === "$root") add("$root", raw);
|
|
221
|
+
else add(key, raw);
|
|
222
|
+
continue;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
return out;
|
|
226
|
+
};
|
|
227
|
+
|
|
228
|
+
// ../logix-core/src/internal/state-trait/build.ts
|
|
229
|
+
var nowPerf = () => typeof globalThis.performance !== "undefined" && typeof globalThis.performance.now === "function" ? globalThis.performance.now() : Date.now();
|
|
230
|
+
var collectMultipleWritersError = (entries) => {
|
|
231
|
+
const kindsByFieldPath = /* @__PURE__ */ new Map();
|
|
232
|
+
for (const entry of entries) {
|
|
233
|
+
if (entry.kind !== "computed" && entry.kind !== "link" && entry.kind !== "source" && entry.kind !== "externalStore") {
|
|
234
|
+
continue;
|
|
235
|
+
}
|
|
236
|
+
const set = kindsByFieldPath.get(entry.fieldPath) ?? /* @__PURE__ */ new Set();
|
|
237
|
+
set.add(entry.kind);
|
|
238
|
+
kindsByFieldPath.set(entry.fieldPath, set);
|
|
239
|
+
}
|
|
240
|
+
const conflicts = [];
|
|
241
|
+
for (const [fieldPath, kinds] of kindsByFieldPath.entries()) {
|
|
242
|
+
if (kinds.size <= 1) continue;
|
|
243
|
+
conflicts.push({ fieldPath, kinds: Array.from(kinds).sort() });
|
|
244
|
+
}
|
|
245
|
+
if (conflicts.length === 0) return void 0;
|
|
246
|
+
conflicts.sort((a, b) => a.fieldPath < b.fieldPath ? -1 : a.fieldPath > b.fieldPath ? 1 : 0);
|
|
247
|
+
const fields = conflicts.map((c) => c.fieldPath);
|
|
248
|
+
const primary = conflicts[0];
|
|
249
|
+
const kindSummary = primary.kinds.join(" + ");
|
|
250
|
+
return {
|
|
251
|
+
code: "MULTIPLE_WRITERS",
|
|
252
|
+
message: `[StateTrait.build] Multiple writers for field "${primary.fieldPath}" (${kindSummary}). Only one of computed/link/source/externalStore can write a fieldPath.`,
|
|
253
|
+
fields
|
|
254
|
+
};
|
|
255
|
+
};
|
|
256
|
+
var getConvergeWriterDeps = (entry) => {
|
|
257
|
+
if (entry.kind === "computed") {
|
|
258
|
+
return entry.meta?.deps ?? [];
|
|
259
|
+
}
|
|
260
|
+
return [entry.meta.from];
|
|
261
|
+
};
|
|
262
|
+
var computeConvergeTopoOrder = (writers) => {
|
|
263
|
+
const writerByPath = /* @__PURE__ */ new Map();
|
|
264
|
+
for (const entry of writers) {
|
|
265
|
+
const existing = writerByPath.get(entry.fieldPath);
|
|
266
|
+
if (existing) {
|
|
267
|
+
return {
|
|
268
|
+
order: [],
|
|
269
|
+
configError: {
|
|
270
|
+
code: "MULTIPLE_WRITERS",
|
|
271
|
+
message: `[StateTrait.converge] Multiple writers for field "${entry.fieldPath}" (${existing.kind} + ${entry.kind}).`,
|
|
272
|
+
fields: [entry.fieldPath]
|
|
273
|
+
}
|
|
274
|
+
};
|
|
275
|
+
}
|
|
276
|
+
writerByPath.set(entry.fieldPath, entry);
|
|
277
|
+
}
|
|
278
|
+
const nodes = /* @__PURE__ */ new Set();
|
|
279
|
+
for (const entry of writers) {
|
|
280
|
+
nodes.add(entry.fieldPath);
|
|
281
|
+
}
|
|
282
|
+
const indegree = /* @__PURE__ */ new Map();
|
|
283
|
+
const forward = /* @__PURE__ */ new Map();
|
|
284
|
+
for (const node of nodes) {
|
|
285
|
+
indegree.set(node, 0);
|
|
286
|
+
forward.set(node, []);
|
|
287
|
+
}
|
|
288
|
+
for (const entry of writers) {
|
|
289
|
+
const to = entry.fieldPath;
|
|
290
|
+
const deps = getConvergeWriterDeps(entry);
|
|
291
|
+
for (const dep of deps) {
|
|
292
|
+
if (!nodes.has(dep)) continue;
|
|
293
|
+
forward.get(dep).push(to);
|
|
294
|
+
indegree.set(to, (indegree.get(to) ?? 0) + 1);
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
const queue = [];
|
|
298
|
+
for (const [node, deg] of indegree.entries()) {
|
|
299
|
+
if (deg === 0) queue.push(node);
|
|
300
|
+
}
|
|
301
|
+
const order = [];
|
|
302
|
+
while (queue.length) {
|
|
303
|
+
const n = queue.shift();
|
|
304
|
+
order.push(n);
|
|
305
|
+
const outs = forward.get(n);
|
|
306
|
+
for (const to of outs) {
|
|
307
|
+
const next = (indegree.get(to) ?? 0) - 1;
|
|
308
|
+
indegree.set(to, next);
|
|
309
|
+
if (next === 0) queue.push(to);
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
if (order.length !== nodes.size) {
|
|
313
|
+
const remaining = Array.from(nodes).filter((n) => !order.includes(n));
|
|
314
|
+
return {
|
|
315
|
+
order: [],
|
|
316
|
+
configError: {
|
|
317
|
+
code: "CYCLE_DETECTED",
|
|
318
|
+
message: `[StateTrait.converge] Cycle detected in computed/link graph: ${remaining.join(", ")}`,
|
|
319
|
+
fields: remaining
|
|
320
|
+
}
|
|
321
|
+
};
|
|
322
|
+
}
|
|
323
|
+
return { order };
|
|
324
|
+
};
|
|
325
|
+
var collectSchemaFieldPaths = (schema) => {
|
|
326
|
+
const byKey = /* @__PURE__ */ new Map();
|
|
327
|
+
const add = (path) => {
|
|
328
|
+
const normalized = normalizeFieldPath(path);
|
|
329
|
+
if (!normalized) return;
|
|
330
|
+
byKey.set(JSON.stringify(normalized), normalized);
|
|
331
|
+
};
|
|
332
|
+
const visit = (ast, prefix, seen) => {
|
|
333
|
+
let current = ast;
|
|
334
|
+
while (true) {
|
|
335
|
+
if (SchemaAST.isSuspend(current)) {
|
|
336
|
+
if (seen.has(current)) return;
|
|
337
|
+
seen.add(current);
|
|
338
|
+
current = current.f();
|
|
339
|
+
continue;
|
|
340
|
+
}
|
|
341
|
+
if (SchemaAST.isRefinement(current)) {
|
|
342
|
+
current = current.from;
|
|
343
|
+
continue;
|
|
344
|
+
}
|
|
345
|
+
break;
|
|
346
|
+
}
|
|
347
|
+
if (SchemaAST.isTransformation(current)) {
|
|
348
|
+
visit(current.to, prefix, seen);
|
|
349
|
+
visit(current.from, prefix, seen);
|
|
350
|
+
return;
|
|
351
|
+
}
|
|
352
|
+
if (SchemaAST.isUnion(current)) {
|
|
353
|
+
for (const t of current.types) {
|
|
354
|
+
visit(t, prefix, seen);
|
|
355
|
+
}
|
|
356
|
+
return;
|
|
357
|
+
}
|
|
358
|
+
if (SchemaAST.isTupleType(current)) {
|
|
359
|
+
for (const e of current.elements) {
|
|
360
|
+
visit(e.type, prefix, seen);
|
|
361
|
+
}
|
|
362
|
+
for (const r of current.rest) {
|
|
363
|
+
visit(r.type, prefix, seen);
|
|
364
|
+
}
|
|
365
|
+
return;
|
|
366
|
+
}
|
|
367
|
+
if (SchemaAST.isTypeLiteral(current)) {
|
|
368
|
+
for (const ps of current.propertySignatures) {
|
|
369
|
+
const seg = String(ps.name);
|
|
370
|
+
if (!seg) continue;
|
|
371
|
+
const next = [...prefix, seg];
|
|
372
|
+
add(next);
|
|
373
|
+
visit(ps.type, next, seen);
|
|
374
|
+
}
|
|
375
|
+
return;
|
|
376
|
+
}
|
|
377
|
+
};
|
|
378
|
+
visit(schema.ast, [], /* @__PURE__ */ new Set());
|
|
379
|
+
return Array.from(byKey.values()).sort(compareFieldPath);
|
|
380
|
+
};
|
|
381
|
+
var buildConvergeIr = (stateSchema, entries) => {
|
|
382
|
+
const startedAt = nowPerf();
|
|
383
|
+
const generation = 0;
|
|
384
|
+
const multipleWritersError = collectMultipleWritersError(entries);
|
|
385
|
+
const writers = entries.filter((e) => e.kind === "computed" || e.kind === "link");
|
|
386
|
+
const writersKey = writers.map((entry) => `${entry.kind}:${entry.fieldPath}`).sort().join("|");
|
|
387
|
+
const depsKey = writers.map((entry) => {
|
|
388
|
+
const deps = getConvergeWriterDeps(entry).slice().sort().join(",");
|
|
389
|
+
const scheduling = entry.meta?.scheduling === "deferred" ? "d" : "i";
|
|
390
|
+
return `${entry.kind}:${entry.fieldPath}@${scheduling}=>${deps}`;
|
|
391
|
+
}).sort().join("|");
|
|
392
|
+
const writerByPath = /* @__PURE__ */ new Map();
|
|
393
|
+
for (const entry of writers) {
|
|
394
|
+
writerByPath.set(entry.fieldPath, entry);
|
|
395
|
+
}
|
|
396
|
+
const topo = multipleWritersError ? { order: [] } : writers.length > 0 ? computeConvergeTopoOrder(writers) : { order: [] };
|
|
397
|
+
const stepsById = topo.configError ? [] : topo.order.map((path) => writerByPath.get(path));
|
|
398
|
+
const fieldPathTable = /* @__PURE__ */ new Map();
|
|
399
|
+
const addPath = (path) => {
|
|
400
|
+
for (let i = 1; i <= path.length; i++) {
|
|
401
|
+
const prefix = path.slice(0, i);
|
|
402
|
+
const key = JSON.stringify(prefix);
|
|
403
|
+
if (!fieldPathTable.has(key)) fieldPathTable.set(key, prefix);
|
|
404
|
+
}
|
|
405
|
+
};
|
|
406
|
+
for (const schemaPath of collectSchemaFieldPaths(stateSchema)) {
|
|
407
|
+
addPath(schemaPath);
|
|
408
|
+
}
|
|
409
|
+
for (const entry of writers) {
|
|
410
|
+
const out = normalizeFieldPath(entry.fieldPath);
|
|
411
|
+
if (out) addPath(out);
|
|
412
|
+
for (const dep of getConvergeWriterDeps(entry)) {
|
|
413
|
+
const depPath = normalizeFieldPath(dep);
|
|
414
|
+
if (depPath) addPath(depPath);
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
const fieldPaths = Array.from(fieldPathTable.values()).sort(compareFieldPath);
|
|
418
|
+
const fieldPathIdRegistry = makeFieldPathIdRegistry(fieldPaths);
|
|
419
|
+
const fieldPathsKey = fnv1a32(stableStringify(fieldPaths));
|
|
420
|
+
const stepOutFieldPathIdByStepId = [];
|
|
421
|
+
const stepDepsFieldPathIdsByStepId = [];
|
|
422
|
+
const stepSchedulingByStepId = [];
|
|
423
|
+
for (const entry of stepsById) {
|
|
424
|
+
const out = normalizeFieldPath(entry.fieldPath);
|
|
425
|
+
const outId = out != null ? getFieldPathId(fieldPathIdRegistry, out) : void 0;
|
|
426
|
+
if (outId == null) {
|
|
427
|
+
throw new Error(`[StateTrait.build] Failed to map converge output fieldPath "${entry.fieldPath}" to FieldPathId.`);
|
|
428
|
+
}
|
|
429
|
+
const depIds = [];
|
|
430
|
+
for (const dep of getConvergeWriterDeps(entry)) {
|
|
431
|
+
const depPath = normalizeFieldPath(dep);
|
|
432
|
+
if (!depPath) continue;
|
|
433
|
+
const depId = getFieldPathId(fieldPathIdRegistry, depPath);
|
|
434
|
+
if (depId != null) depIds.push(depId);
|
|
435
|
+
}
|
|
436
|
+
stepOutFieldPathIdByStepId.push(outId);
|
|
437
|
+
stepDepsFieldPathIdsByStepId.push(depIds);
|
|
438
|
+
stepSchedulingByStepId.push(entry.meta?.scheduling === "deferred" ? "deferred" : "immediate");
|
|
439
|
+
}
|
|
440
|
+
const topoOrder = stepsById.map((_, i) => i);
|
|
441
|
+
const buildDurationMs = Math.max(0, nowPerf() - startedAt);
|
|
442
|
+
return {
|
|
443
|
+
generation,
|
|
444
|
+
writersKey,
|
|
445
|
+
depsKey,
|
|
446
|
+
fieldPathsKey,
|
|
447
|
+
fieldPaths,
|
|
448
|
+
fieldPathIdRegistry,
|
|
449
|
+
...multipleWritersError ? { configError: multipleWritersError } : topo.configError ? { configError: topo.configError } : null,
|
|
450
|
+
stepsById,
|
|
451
|
+
stepOutFieldPathIdByStepId,
|
|
452
|
+
stepDepsFieldPathIdsByStepId,
|
|
453
|
+
stepSchedulingByStepId,
|
|
454
|
+
topoOrder,
|
|
455
|
+
buildDurationMs
|
|
456
|
+
};
|
|
457
|
+
};
|
|
458
|
+
var toFieldTrait = (entry) => {
|
|
459
|
+
const deps = [];
|
|
460
|
+
if (entry.kind === "computed") {
|
|
461
|
+
const meta = entry.meta;
|
|
462
|
+
const list = meta.deps;
|
|
463
|
+
if (list) deps.push(...list);
|
|
464
|
+
} else if (entry.kind === "source") {
|
|
465
|
+
const meta = entry.meta;
|
|
466
|
+
const list = meta.deps;
|
|
467
|
+
if (list) deps.push(...list);
|
|
468
|
+
} else if (entry.kind === "link") {
|
|
469
|
+
deps.push(entry.meta.from);
|
|
470
|
+
} else if (entry.kind === "check") {
|
|
471
|
+
const meta = entry.meta;
|
|
472
|
+
const rules = meta?.rules ?? {};
|
|
473
|
+
for (const name of Object.keys(rules)) {
|
|
474
|
+
const rule = rules[name];
|
|
475
|
+
if (rule && typeof rule === "object") {
|
|
476
|
+
const list = rule.deps;
|
|
477
|
+
if (list) deps.push(...list);
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
return {
|
|
482
|
+
fieldId: entry.fieldPath,
|
|
483
|
+
kind: entry.kind,
|
|
484
|
+
// Keep meta identical to Entry.meta at runtime so install can reuse it directly.
|
|
485
|
+
meta: entry.meta,
|
|
486
|
+
deps
|
|
487
|
+
};
|
|
488
|
+
};
|
|
489
|
+
var buildGraph = (entries, nodeMetaByFieldPath) => {
|
|
490
|
+
const fieldMap = /* @__PURE__ */ new Map();
|
|
491
|
+
const nodes = [];
|
|
492
|
+
const edges = [];
|
|
493
|
+
const resourcesById = /* @__PURE__ */ new Map();
|
|
494
|
+
const planSteps = [];
|
|
495
|
+
const ensureField = (fieldPath) => {
|
|
496
|
+
let field = fieldMap.get(fieldPath);
|
|
497
|
+
if (!field) {
|
|
498
|
+
field = {
|
|
499
|
+
id: fieldPath,
|
|
500
|
+
path: fieldPath,
|
|
501
|
+
traits: []
|
|
502
|
+
};
|
|
503
|
+
fieldMap.set(fieldPath, field);
|
|
504
|
+
}
|
|
505
|
+
return field;
|
|
506
|
+
};
|
|
507
|
+
for (const entry of entries) {
|
|
508
|
+
const fieldPath = entry.fieldPath;
|
|
509
|
+
const field = ensureField(fieldPath);
|
|
510
|
+
const trait = toFieldTrait(entry);
|
|
511
|
+
field.traits.push(trait);
|
|
512
|
+
if (entry.kind === "computed") {
|
|
513
|
+
const stepId = `computed:${fieldPath}`;
|
|
514
|
+
planSteps.push({
|
|
515
|
+
id: stepId,
|
|
516
|
+
kind: "computed-update",
|
|
517
|
+
targetFieldPath: fieldPath
|
|
518
|
+
// Note: the current version does not statically analyze computed dependencies; sourceFieldPaths remains empty.
|
|
519
|
+
});
|
|
520
|
+
const deps = entry.meta.deps;
|
|
521
|
+
if (deps) {
|
|
522
|
+
for (const dep of deps) {
|
|
523
|
+
ensureField(dep);
|
|
524
|
+
edges.push({
|
|
525
|
+
id: `computed:${dep}->${fieldPath}`,
|
|
526
|
+
from: dep,
|
|
527
|
+
to: fieldPath,
|
|
528
|
+
kind: "computed"
|
|
529
|
+
});
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
} else if (entry.kind === "link") {
|
|
533
|
+
const from = entry.meta.from;
|
|
534
|
+
ensureField(from);
|
|
535
|
+
const edgeId = `link:${from}->${fieldPath}`;
|
|
536
|
+
edges.push({
|
|
537
|
+
id: edgeId,
|
|
538
|
+
from,
|
|
539
|
+
to: fieldPath,
|
|
540
|
+
kind: "link"
|
|
541
|
+
});
|
|
542
|
+
planSteps.push({
|
|
543
|
+
id: `link:${fieldPath}`,
|
|
544
|
+
kind: "link-propagate",
|
|
545
|
+
targetFieldPath: fieldPath,
|
|
546
|
+
sourceFieldPaths: [from],
|
|
547
|
+
debugInfo: {
|
|
548
|
+
graphEdgeId: edgeId
|
|
549
|
+
}
|
|
550
|
+
});
|
|
551
|
+
} else if (entry.kind === "source") {
|
|
552
|
+
const resourceId = entry.meta.resource;
|
|
553
|
+
const resourceMeta = sanitize(entry.meta.meta);
|
|
554
|
+
const existing = resourcesById.get(resourceId);
|
|
555
|
+
if (existing) {
|
|
556
|
+
const ownerFields = [...existing.ownerFields, fieldPath];
|
|
557
|
+
let meta = existing.meta;
|
|
558
|
+
let metaOrigin = existing.metaOrigin;
|
|
559
|
+
let metaConflicts = existing.metaConflicts;
|
|
560
|
+
if (resourceMeta) {
|
|
561
|
+
const merged = mergeCanonical(
|
|
562
|
+
{ meta, origin: metaOrigin, conflicts: metaConflicts },
|
|
563
|
+
{ origin: fieldPath, meta: resourceMeta }
|
|
564
|
+
);
|
|
565
|
+
meta = merged.meta;
|
|
566
|
+
metaOrigin = merged.origin;
|
|
567
|
+
metaConflicts = merged.conflicts;
|
|
568
|
+
}
|
|
569
|
+
resourcesById.set(resourceId, {
|
|
570
|
+
...existing,
|
|
571
|
+
ownerFields,
|
|
572
|
+
meta,
|
|
573
|
+
metaOrigin,
|
|
574
|
+
metaConflicts
|
|
575
|
+
});
|
|
576
|
+
} else {
|
|
577
|
+
resourcesById.set(resourceId, {
|
|
578
|
+
resourceId,
|
|
579
|
+
// Use a simple identifier string for now; may evolve into a structured form based on key rules.
|
|
580
|
+
keySelector: `StateTrait.source@${fieldPath}`,
|
|
581
|
+
ownerFields: [fieldPath],
|
|
582
|
+
meta: resourceMeta,
|
|
583
|
+
metaOrigin: resourceMeta ? fieldPath : void 0
|
|
584
|
+
});
|
|
585
|
+
}
|
|
586
|
+
planSteps.push({
|
|
587
|
+
id: `source:${fieldPath}`,
|
|
588
|
+
kind: "source-refresh",
|
|
589
|
+
targetFieldPath: fieldPath,
|
|
590
|
+
resourceId,
|
|
591
|
+
keySelectorId: `StateTrait.source@${fieldPath}`
|
|
592
|
+
});
|
|
593
|
+
const deps = entry.meta.deps;
|
|
594
|
+
if (deps) {
|
|
595
|
+
for (const dep of deps) {
|
|
596
|
+
ensureField(dep);
|
|
597
|
+
edges.push({
|
|
598
|
+
id: `source-dep:${dep}->${fieldPath}`,
|
|
599
|
+
from: dep,
|
|
600
|
+
to: fieldPath,
|
|
601
|
+
kind: "source-dep"
|
|
602
|
+
});
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
} else if (entry.kind === "externalStore") {
|
|
606
|
+
planSteps.push({
|
|
607
|
+
id: `external-store:${fieldPath}`,
|
|
608
|
+
kind: "external-store-sync",
|
|
609
|
+
targetFieldPath: fieldPath
|
|
610
|
+
});
|
|
611
|
+
} else if (entry.kind === "check") {
|
|
612
|
+
planSteps.push({
|
|
613
|
+
id: `check:${fieldPath}`,
|
|
614
|
+
kind: "check-validate",
|
|
615
|
+
targetFieldPath: fieldPath
|
|
616
|
+
});
|
|
617
|
+
if (trait.deps.length > 0) {
|
|
618
|
+
for (const dep of trait.deps) {
|
|
619
|
+
ensureField(dep);
|
|
620
|
+
edges.push({
|
|
621
|
+
id: `check-dep:${dep}->${fieldPath}`,
|
|
622
|
+
from: dep,
|
|
623
|
+
to: fieldPath,
|
|
624
|
+
kind: "check-dep"
|
|
625
|
+
});
|
|
626
|
+
}
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
for (const field of fieldMap.values()) {
|
|
631
|
+
nodes.push({
|
|
632
|
+
id: field.id,
|
|
633
|
+
field,
|
|
634
|
+
traits: field.traits,
|
|
635
|
+
meta: nodeMetaByFieldPath.get(field.id)
|
|
636
|
+
});
|
|
637
|
+
}
|
|
638
|
+
const graph = {
|
|
639
|
+
_tag: "StateTraitGraph",
|
|
640
|
+
nodes,
|
|
641
|
+
edges,
|
|
642
|
+
resources: Array.from(resourcesById.values())
|
|
643
|
+
};
|
|
644
|
+
const plan = {
|
|
645
|
+
_tag: "StateTraitPlan",
|
|
646
|
+
steps: planSteps
|
|
647
|
+
};
|
|
648
|
+
return { graph, plan };
|
|
649
|
+
};
|
|
650
|
+
var assertNoLinkCycles = (edges) => {
|
|
651
|
+
const adjacency = /* @__PURE__ */ new Map();
|
|
652
|
+
for (const edge of edges) {
|
|
653
|
+
if (edge.kind !== "link") continue;
|
|
654
|
+
const list = adjacency.get(edge.from) ?? [];
|
|
655
|
+
list.push(edge.to);
|
|
656
|
+
adjacency.set(edge.from, list);
|
|
657
|
+
}
|
|
658
|
+
const visited = /* @__PURE__ */ new Set();
|
|
659
|
+
const stack = /* @__PURE__ */ new Set();
|
|
660
|
+
const dfs = (node) => {
|
|
661
|
+
if (stack.has(node)) {
|
|
662
|
+
throw new Error(
|
|
663
|
+
`[StateTrait.build] link cycle detected at field "${node}". Please check link traits for circular dependencies.`
|
|
664
|
+
);
|
|
665
|
+
}
|
|
666
|
+
if (visited.has(node)) return;
|
|
667
|
+
visited.add(node);
|
|
668
|
+
stack.add(node);
|
|
669
|
+
const nexts = adjacency.get(node);
|
|
670
|
+
if (nexts) {
|
|
671
|
+
for (const to of nexts) {
|
|
672
|
+
dfs(to);
|
|
673
|
+
}
|
|
674
|
+
}
|
|
675
|
+
stack.delete(node);
|
|
676
|
+
};
|
|
677
|
+
for (const node of adjacency.keys()) {
|
|
678
|
+
if (!visited.has(node)) {
|
|
679
|
+
dfs(node);
|
|
680
|
+
}
|
|
681
|
+
}
|
|
682
|
+
};
|
|
683
|
+
var collectSchemaPaths = (entries) => {
|
|
684
|
+
const byKey = /* @__PURE__ */ new Map();
|
|
685
|
+
const add = (ref) => {
|
|
686
|
+
if (!ref.path) return;
|
|
687
|
+
const k = `${ref.kind}|${ref.entryKind}|${ref.entryFieldPath}|${ref.ruleName ?? ""}|${ref.path}`;
|
|
688
|
+
byKey.set(k, ref);
|
|
689
|
+
};
|
|
690
|
+
const getCheckWritebackPath = (entry) => {
|
|
691
|
+
const wb = entry.meta?.writeback;
|
|
692
|
+
const p = wb && typeof wb === "object" ? wb.path : void 0;
|
|
693
|
+
const writebackPath = typeof p === "string" && p.startsWith("errors.") ? p : void 0;
|
|
694
|
+
if (writebackPath) return writebackPath;
|
|
695
|
+
const fieldPath = entry.fieldPath;
|
|
696
|
+
if (fieldPath.endsWith("[]")) {
|
|
697
|
+
return `errors.${fieldPath.slice(0, -2)}`;
|
|
698
|
+
}
|
|
699
|
+
return `errors.${fieldPath}`;
|
|
700
|
+
};
|
|
701
|
+
for (const entry of entries) {
|
|
702
|
+
add({
|
|
703
|
+
kind: "fieldPath",
|
|
704
|
+
entryKind: entry.kind,
|
|
705
|
+
entryFieldPath: entry.fieldPath,
|
|
706
|
+
path: entry.fieldPath
|
|
707
|
+
});
|
|
708
|
+
if (entry.kind === "computed" || entry.kind === "source") {
|
|
709
|
+
const deps = entry.meta?.deps ?? [];
|
|
710
|
+
for (const dep of deps) {
|
|
711
|
+
add({
|
|
712
|
+
kind: "dep",
|
|
713
|
+
entryKind: entry.kind,
|
|
714
|
+
entryFieldPath: entry.fieldPath,
|
|
715
|
+
path: dep
|
|
716
|
+
});
|
|
717
|
+
}
|
|
718
|
+
}
|
|
719
|
+
if (entry.kind === "link") {
|
|
720
|
+
add({
|
|
721
|
+
kind: "link_from",
|
|
722
|
+
entryKind: "link",
|
|
723
|
+
entryFieldPath: entry.fieldPath,
|
|
724
|
+
path: entry.meta.from
|
|
725
|
+
});
|
|
726
|
+
}
|
|
727
|
+
if (entry.kind === "check") {
|
|
728
|
+
add({
|
|
729
|
+
kind: "check_writeback",
|
|
730
|
+
entryKind: "check",
|
|
731
|
+
entryFieldPath: entry.fieldPath,
|
|
732
|
+
path: getCheckWritebackPath(entry)
|
|
733
|
+
});
|
|
734
|
+
const rules = entry.meta?.rules ?? {};
|
|
735
|
+
for (const name of Object.keys(rules)) {
|
|
736
|
+
const rule = rules[name];
|
|
737
|
+
if (!rule || typeof rule !== "object") continue;
|
|
738
|
+
const deps = rule.deps ?? [];
|
|
739
|
+
for (const dep of deps) {
|
|
740
|
+
add({
|
|
741
|
+
kind: "dep",
|
|
742
|
+
entryKind: "check",
|
|
743
|
+
entryFieldPath: entry.fieldPath,
|
|
744
|
+
ruleName: name,
|
|
745
|
+
path: dep
|
|
746
|
+
});
|
|
747
|
+
}
|
|
748
|
+
}
|
|
749
|
+
}
|
|
750
|
+
}
|
|
751
|
+
return Array.from(byKey.entries()).sort((a, b) => a[0] < b[0] ? -1 : a[0] > b[0] ? 1 : 0).map(([, v]) => v);
|
|
752
|
+
};
|
|
753
|
+
var build = (stateSchema, spec) => {
|
|
754
|
+
const entries = normalizeSpec(spec);
|
|
755
|
+
const nodeMetaByFieldPath = collectNodeMeta(spec);
|
|
756
|
+
for (const entry of entries) {
|
|
757
|
+
if (entry.kind === "computed") {
|
|
758
|
+
const deps = entry.meta.deps;
|
|
759
|
+
if (deps === void 0) {
|
|
760
|
+
throw new Error(
|
|
761
|
+
`[StateTrait.build] Missing explicit deps for computed "${entry.fieldPath}". Please use StateTrait.computed({ deps: [...], get: ... }).`
|
|
762
|
+
);
|
|
763
|
+
}
|
|
764
|
+
}
|
|
765
|
+
if (entry.kind === "source") {
|
|
766
|
+
const deps = entry.meta.deps;
|
|
767
|
+
if (deps === void 0) {
|
|
768
|
+
throw new Error(
|
|
769
|
+
`[StateTrait.build] Missing explicit deps for source "${entry.fieldPath}". Please provide meta.deps for StateTrait.source({ deps: [...], ... }).`
|
|
770
|
+
);
|
|
771
|
+
}
|
|
772
|
+
}
|
|
773
|
+
if (entry.kind === "check") {
|
|
774
|
+
const rules = entry.meta?.rules ?? {};
|
|
775
|
+
for (const name of Object.keys(rules)) {
|
|
776
|
+
const rule = rules[name];
|
|
777
|
+
if (typeof rule === "function" || !rule || typeof rule !== "object") {
|
|
778
|
+
throw new Error(
|
|
779
|
+
`[StateTrait.build] Missing explicit deps for check "${entry.fieldPath}" rule "${name}". Please use { deps: [...], validate: ... } form.`
|
|
780
|
+
);
|
|
781
|
+
}
|
|
782
|
+
if (rule.deps === void 0) {
|
|
783
|
+
throw new Error(
|
|
784
|
+
`[StateTrait.build] Missing explicit deps for check "${entry.fieldPath}" rule "${name}". Please provide deps: [...].`
|
|
785
|
+
);
|
|
786
|
+
}
|
|
787
|
+
}
|
|
788
|
+
}
|
|
789
|
+
}
|
|
790
|
+
const { graph, plan } = buildGraph(entries, nodeMetaByFieldPath);
|
|
791
|
+
assertNoLinkCycles(graph.edges);
|
|
792
|
+
return {
|
|
793
|
+
stateSchema,
|
|
794
|
+
spec,
|
|
795
|
+
entries,
|
|
796
|
+
graph,
|
|
797
|
+
plan,
|
|
798
|
+
convergeIr: buildConvergeIr(stateSchema, entries),
|
|
799
|
+
schemaPaths: collectSchemaPaths(entries)
|
|
800
|
+
};
|
|
801
|
+
};
|
|
802
|
+
|
|
803
|
+
// ../logix-core/src/internal/state-trait/source.impl.ts
|
|
804
|
+
import { Effect, Fiber, FiberRef, Option } from "../effect.js";
|
|
805
|
+
|
|
806
|
+
// ../logix-core/src/internal/state-trait/deps-trace.ts
|
|
807
|
+
var isTraceableObject = (value) => {
|
|
808
|
+
if (!value || typeof value !== "object") return false;
|
|
809
|
+
if (Array.isArray(value)) return true;
|
|
810
|
+
if (value instanceof Date) return false;
|
|
811
|
+
if (value instanceof RegExp) return false;
|
|
812
|
+
if (value instanceof Error) return false;
|
|
813
|
+
if (value instanceof Map) return false;
|
|
814
|
+
if (value instanceof Set) return false;
|
|
815
|
+
if (value instanceof WeakMap) return false;
|
|
816
|
+
if (value instanceof WeakSet) return false;
|
|
817
|
+
return true;
|
|
818
|
+
};
|
|
819
|
+
var shouldIgnoreKey = (key) => key === "__proto__" || key === "prototype" || key === "constructor";
|
|
820
|
+
var normalizeReads = (reads) => {
|
|
821
|
+
const all = Array.from(reads).filter((p) => typeof p === "string" && p.length > 0);
|
|
822
|
+
all.sort();
|
|
823
|
+
const isPrefix = (prefix, full) => full !== prefix && full.startsWith(prefix + ".");
|
|
824
|
+
const pruned = [];
|
|
825
|
+
for (const p of all) {
|
|
826
|
+
let hasMoreSpecific = false;
|
|
827
|
+
for (const other of all) {
|
|
828
|
+
if (isPrefix(p, other)) {
|
|
829
|
+
hasMoreSpecific = true;
|
|
830
|
+
break;
|
|
831
|
+
}
|
|
832
|
+
}
|
|
833
|
+
if (!hasMoreSpecific) {
|
|
834
|
+
pruned.push(p);
|
|
835
|
+
}
|
|
836
|
+
}
|
|
837
|
+
pruned.sort();
|
|
838
|
+
return pruned;
|
|
839
|
+
};
|
|
840
|
+
var covers = (declared, read) => declared === read || read.startsWith(declared + ".");
|
|
841
|
+
var diffDeps = (declared, reads) => {
|
|
842
|
+
const declaredList = Array.from(new Set(declared)).filter((p) => typeof p === "string" && p.length > 0);
|
|
843
|
+
declaredList.sort();
|
|
844
|
+
const readList = Array.from(new Set(reads)).filter((p) => typeof p === "string" && p.length > 0);
|
|
845
|
+
readList.sort();
|
|
846
|
+
const missing = readList.filter((r) => declaredList.every((d) => !covers(d, r)));
|
|
847
|
+
const unused = declaredList.filter((d) => readList.every((r) => !covers(d, r)));
|
|
848
|
+
if (missing.length === 0 && unused.length === 0) return void 0;
|
|
849
|
+
return {
|
|
850
|
+
reads: readList,
|
|
851
|
+
declared: declaredList,
|
|
852
|
+
missing,
|
|
853
|
+
unused
|
|
854
|
+
};
|
|
855
|
+
};
|
|
856
|
+
var trace = (fn, state) => {
|
|
857
|
+
if (!isTraceableObject(state)) {
|
|
858
|
+
return { value: fn(state), reads: [] };
|
|
859
|
+
}
|
|
860
|
+
const reads = /* @__PURE__ */ new Set();
|
|
861
|
+
const proxyCache = /* @__PURE__ */ new WeakMap();
|
|
862
|
+
const proxyToTarget = /* @__PURE__ */ new WeakMap();
|
|
863
|
+
const wrap = (value2, path) => {
|
|
864
|
+
if (!isTraceableObject(value2)) return value2;
|
|
865
|
+
return getProxy(value2, path);
|
|
866
|
+
};
|
|
867
|
+
const unwrap = (value2) => {
|
|
868
|
+
if (value2 && (typeof value2 === "object" || typeof value2 === "function")) {
|
|
869
|
+
const target = proxyToTarget.get(value2);
|
|
870
|
+
if (target) return target;
|
|
871
|
+
}
|
|
872
|
+
return value2;
|
|
873
|
+
};
|
|
874
|
+
const getProxy = (target, basePath) => {
|
|
875
|
+
let byPath = proxyCache.get(target);
|
|
876
|
+
if (!byPath) {
|
|
877
|
+
byPath = /* @__PURE__ */ new Map();
|
|
878
|
+
proxyCache.set(target, byPath);
|
|
879
|
+
}
|
|
880
|
+
const cached = byPath.get(basePath);
|
|
881
|
+
if (cached) return cached;
|
|
882
|
+
const record2 = (path) => {
|
|
883
|
+
if (path) reads.add(path);
|
|
884
|
+
};
|
|
885
|
+
const proxy = new Proxy(target, {
|
|
886
|
+
get: (t, prop, receiver) => {
|
|
887
|
+
if (typeof prop === "symbol") {
|
|
888
|
+
return Reflect.get(t, prop, receiver);
|
|
889
|
+
}
|
|
890
|
+
const key = String(prop);
|
|
891
|
+
if (shouldIgnoreKey(key)) {
|
|
892
|
+
return Reflect.get(t, prop, receiver);
|
|
893
|
+
}
|
|
894
|
+
const nextPath = basePath ? `${basePath}.${key}` : key;
|
|
895
|
+
record2(nextPath);
|
|
896
|
+
const value2 = Reflect.get(t, prop, receiver);
|
|
897
|
+
return wrap(value2, nextPath);
|
|
898
|
+
},
|
|
899
|
+
has: (t, prop) => {
|
|
900
|
+
if (typeof prop === "symbol") return Reflect.has(t, prop);
|
|
901
|
+
const key = String(prop);
|
|
902
|
+
if (!shouldIgnoreKey(key)) {
|
|
903
|
+
const nextPath = basePath ? `${basePath}.${key}` : key;
|
|
904
|
+
record2(nextPath);
|
|
905
|
+
}
|
|
906
|
+
return Reflect.has(t, prop);
|
|
907
|
+
},
|
|
908
|
+
ownKeys: (t) => {
|
|
909
|
+
if (basePath) record2(basePath);
|
|
910
|
+
return Reflect.ownKeys(t);
|
|
911
|
+
},
|
|
912
|
+
getOwnPropertyDescriptor: (t, prop) => {
|
|
913
|
+
if (typeof prop === "symbol") {
|
|
914
|
+
return Reflect.getOwnPropertyDescriptor(t, prop);
|
|
915
|
+
}
|
|
916
|
+
const key = String(prop);
|
|
917
|
+
if (!shouldIgnoreKey(key)) {
|
|
918
|
+
const nextPath = basePath ? `${basePath}.${key}` : key;
|
|
919
|
+
record2(nextPath);
|
|
920
|
+
}
|
|
921
|
+
return Reflect.getOwnPropertyDescriptor(t, prop);
|
|
922
|
+
},
|
|
923
|
+
set: () => {
|
|
924
|
+
throw new Error(
|
|
925
|
+
"[deps-trace] Attempted to mutate state during deps tracing (state is readonly in dev-mode diagnostics)."
|
|
926
|
+
);
|
|
927
|
+
},
|
|
928
|
+
defineProperty: () => {
|
|
929
|
+
throw new Error(
|
|
930
|
+
"[deps-trace] Attempted to define property on state during deps tracing (state is readonly in dev-mode diagnostics)."
|
|
931
|
+
);
|
|
932
|
+
},
|
|
933
|
+
deleteProperty: () => {
|
|
934
|
+
throw new Error(
|
|
935
|
+
"[deps-trace] Attempted to delete property on state during deps tracing (state is readonly in dev-mode diagnostics)."
|
|
936
|
+
);
|
|
937
|
+
}
|
|
938
|
+
});
|
|
939
|
+
byPath.set(basePath, proxy);
|
|
940
|
+
proxyToTarget.set(proxy, target);
|
|
941
|
+
return proxy;
|
|
942
|
+
};
|
|
943
|
+
const root = getProxy(state, "");
|
|
944
|
+
const value = unwrap(fn(root));
|
|
945
|
+
return {
|
|
946
|
+
value,
|
|
947
|
+
reads: normalizeReads(reads)
|
|
948
|
+
};
|
|
949
|
+
};
|
|
950
|
+
|
|
951
|
+
// ../logix-core/src/internal/state-trait/source.impl.ts
|
|
952
|
+
var onceInRunSession = (key) => Effect.serviceOption(RunSessionTag).pipe(
|
|
953
|
+
Effect.map((maybe) => Option.isSome(maybe) ? maybe.value.local.once(key) : true)
|
|
954
|
+
);
|
|
955
|
+
var formatList = (items, limit = 10) => {
|
|
956
|
+
if (items.length === 0) return "";
|
|
957
|
+
if (items.length <= limit) return items.join(", ");
|
|
958
|
+
return `${items.slice(0, limit).join(", ")}, \u2026(+${items.length - limit})`;
|
|
959
|
+
};
|
|
960
|
+
var emitDepsMismatch = (params) => Effect.gen(function* () {
|
|
961
|
+
const key = `${params.instanceId ?? "unknown"}::${params.kind}::${params.fieldPath}`;
|
|
962
|
+
const shouldEmit = yield* onceInRunSession(`deps_mismatch:${key}`);
|
|
963
|
+
if (!shouldEmit) return;
|
|
964
|
+
yield* record({
|
|
965
|
+
type: "diagnostic",
|
|
966
|
+
moduleId: params.moduleId,
|
|
967
|
+
instanceId: params.instanceId,
|
|
968
|
+
code: "state_trait::deps_mismatch",
|
|
969
|
+
severity: "warning",
|
|
970
|
+
message: `[deps] ${params.kind} "${params.fieldPath}" declared=[${formatList(params.diff.declared)}] reads=[${formatList(params.diff.reads)}] missing=[${formatList(params.diff.missing)}] unused=[${formatList(params.diff.unused)}]`,
|
|
971
|
+
hint: 'deps is the single source of truth for dependencies: incremental scheduling / reverse closures / performance optimizations rely on deps only. Keep deps consistent with actual reads; if you really depend on the whole object, declare a coarser-grained dep (e.g. "profile") to cover sub-field reads.',
|
|
972
|
+
kind: `deps_mismatch:${params.kind}`
|
|
973
|
+
});
|
|
974
|
+
});
|
|
975
|
+
var getMiddlewareStack = () => Effect.serviceOption(EffectOpMiddlewareTag).pipe(
|
|
976
|
+
Effect.map((maybe) => Option.isSome(maybe) ? maybe.value.stack : [])
|
|
977
|
+
);
|
|
978
|
+
var recordTraitPatch = (bound, path, reason, from, to, traitNodeId) => {
|
|
979
|
+
const normalized = normalizeFieldPath(path) ?? [];
|
|
980
|
+
try {
|
|
981
|
+
const internals = getBoundInternals(bound);
|
|
982
|
+
internals.txn.recordStatePatch(normalized, reason, from, to, traitNodeId);
|
|
983
|
+
} catch {
|
|
984
|
+
}
|
|
985
|
+
};
|
|
986
|
+
var recordReplayEvent = (bound, event) => {
|
|
987
|
+
try {
|
|
988
|
+
const internals = getBoundInternals(bound);
|
|
989
|
+
internals.txn.recordReplayEvent(event);
|
|
990
|
+
} catch {
|
|
991
|
+
}
|
|
992
|
+
};
|
|
993
|
+
var getBoundScope = (bound) => {
|
|
994
|
+
try {
|
|
995
|
+
const internals = getBoundInternals(bound);
|
|
996
|
+
return { moduleId: internals.moduleId, instanceId: internals.instanceId };
|
|
997
|
+
} catch {
|
|
998
|
+
return { moduleId: void 0, instanceId: void 0 };
|
|
999
|
+
}
|
|
1000
|
+
};
|
|
1001
|
+
var setSnapshotInTxn = (bound, fieldPath, next, reason, stepId, traitNodeId) => Effect.gen(function* () {
|
|
1002
|
+
let wrote = false;
|
|
1003
|
+
yield* bound.state.mutate((draft) => {
|
|
1004
|
+
const prev = getAtPath(draft, fieldPath);
|
|
1005
|
+
if (Object.is(prev, next)) return;
|
|
1006
|
+
wrote = true;
|
|
1007
|
+
setAtPathMutating(draft, fieldPath, next);
|
|
1008
|
+
recordTraitPatch(bound, fieldPath, reason, prev, next, traitNodeId);
|
|
1009
|
+
});
|
|
1010
|
+
return wrote;
|
|
1011
|
+
});
|
|
1012
|
+
var writebackIfCurrentKeyHash = (bound, fieldPath, keyHash2, next, reason, stepId, traitNodeId, replayEvent) => Effect.gen(function* () {
|
|
1013
|
+
let wrote = false;
|
|
1014
|
+
yield* bound.state.mutate((draft) => {
|
|
1015
|
+
const current = getAtPath(draft, fieldPath);
|
|
1016
|
+
const currentKeyHash = current && typeof current === "object" ? current.keyHash : void 0;
|
|
1017
|
+
if (currentKeyHash !== keyHash2) return;
|
|
1018
|
+
const prev = current;
|
|
1019
|
+
if (Object.is(prev, next)) return;
|
|
1020
|
+
wrote = true;
|
|
1021
|
+
setAtPathMutating(draft, fieldPath, next);
|
|
1022
|
+
if (replayEvent) {
|
|
1023
|
+
recordReplayEvent(bound, replayEvent);
|
|
1024
|
+
}
|
|
1025
|
+
recordTraitPatch(bound, fieldPath, reason, prev, next, traitNodeId);
|
|
1026
|
+
});
|
|
1027
|
+
return wrote;
|
|
1028
|
+
});
|
|
1029
|
+
var syncIdleInTransaction = (program, ctx) => Effect.sync(() => {
|
|
1030
|
+
const draft = ctx.getDraft();
|
|
1031
|
+
const updates = [];
|
|
1032
|
+
for (const entry of program.entries) {
|
|
1033
|
+
if (entry.kind !== "source") continue;
|
|
1034
|
+
const fieldPath = entry.fieldPath;
|
|
1035
|
+
const listItem = parseListItemFieldPath(fieldPath);
|
|
1036
|
+
if (listItem) {
|
|
1037
|
+
const listValue = getAtPath(draft, listItem.listPath);
|
|
1038
|
+
const items = Array.isArray(listValue) ? listValue : [];
|
|
1039
|
+
for (let index = 0; index < items.length; index++) {
|
|
1040
|
+
const item = items[index];
|
|
1041
|
+
let key2;
|
|
1042
|
+
try {
|
|
1043
|
+
key2 = entry.meta.key(item);
|
|
1044
|
+
} catch {
|
|
1045
|
+
continue;
|
|
1046
|
+
}
|
|
1047
|
+
if (key2 !== void 0) continue;
|
|
1048
|
+
const concretePath = toListItemValuePath(listItem.listPath, index, listItem.itemPath);
|
|
1049
|
+
const prev2 = getAtPath(draft, concretePath);
|
|
1050
|
+
const prevStatus2 = prev2 && typeof prev2 === "object" ? prev2.status : void 0;
|
|
1051
|
+
if (prevStatus2 === "idle") {
|
|
1052
|
+
const data = prev2?.data;
|
|
1053
|
+
const error = prev2?.error;
|
|
1054
|
+
if (data === void 0 && error === void 0) {
|
|
1055
|
+
continue;
|
|
1056
|
+
}
|
|
1057
|
+
}
|
|
1058
|
+
updates.push({ fieldPath: concretePath, prev: prev2 });
|
|
1059
|
+
}
|
|
1060
|
+
continue;
|
|
1061
|
+
}
|
|
1062
|
+
let key;
|
|
1063
|
+
try {
|
|
1064
|
+
key = entry.meta.key(draft);
|
|
1065
|
+
} catch {
|
|
1066
|
+
continue;
|
|
1067
|
+
}
|
|
1068
|
+
if (key !== void 0) continue;
|
|
1069
|
+
const prev = getAtPath(draft, fieldPath);
|
|
1070
|
+
const prevStatus = prev && typeof prev === "object" ? prev.status : void 0;
|
|
1071
|
+
if (prevStatus === "idle") {
|
|
1072
|
+
const data = prev?.data;
|
|
1073
|
+
const error = prev?.error;
|
|
1074
|
+
if (data === void 0 && error === void 0) {
|
|
1075
|
+
continue;
|
|
1076
|
+
}
|
|
1077
|
+
}
|
|
1078
|
+
updates.push({ fieldPath, prev });
|
|
1079
|
+
}
|
|
1080
|
+
if (updates.length === 0) return;
|
|
1081
|
+
const reason = "source-refresh";
|
|
1082
|
+
const nextDraft = create(draft, (next) => {
|
|
1083
|
+
for (const u of updates) {
|
|
1084
|
+
setAtPathMutating(next, u.fieldPath, Snapshot.idle());
|
|
1085
|
+
}
|
|
1086
|
+
});
|
|
1087
|
+
ctx.setDraft(nextDraft);
|
|
1088
|
+
for (const u of updates) {
|
|
1089
|
+
const normalized = normalizeFieldPath(u.fieldPath) ?? [];
|
|
1090
|
+
ctx.recordPatch(normalized, reason, u.prev, Snapshot.idle(), `source:${u.fieldPath}:idle`);
|
|
1091
|
+
}
|
|
1092
|
+
});
|
|
1093
|
+
var installSourceRefresh = (bound, step, entry) => {
|
|
1094
|
+
if (!step.targetFieldPath) return Effect.void;
|
|
1095
|
+
const fieldPath = step.targetFieldPath;
|
|
1096
|
+
const resourceId = step.resourceId ?? entry.meta.resource;
|
|
1097
|
+
const listItem = parseListItemFieldPath(fieldPath);
|
|
1098
|
+
let internals;
|
|
1099
|
+
try {
|
|
1100
|
+
internals = getBoundInternals(bound);
|
|
1101
|
+
} catch {
|
|
1102
|
+
return Effect.void;
|
|
1103
|
+
}
|
|
1104
|
+
const register = internals.traits.registerSourceRefresh;
|
|
1105
|
+
const recordSnapshot = (replayMode, replayLog, input) => {
|
|
1106
|
+
if (!replayLog) return Effect.void;
|
|
1107
|
+
if (replayMode !== "live") return Effect.void;
|
|
1108
|
+
const event = input && typeof input === "object" && input._tag === "ResourceSnapshot" ? input : {
|
|
1109
|
+
_tag: "ResourceSnapshot",
|
|
1110
|
+
resourceId,
|
|
1111
|
+
fieldPath: input.fieldPath,
|
|
1112
|
+
keyHash: input.keyHash,
|
|
1113
|
+
concurrency: input.concurrency,
|
|
1114
|
+
phase: input.phase,
|
|
1115
|
+
snapshot: input.snapshot,
|
|
1116
|
+
timestamp: Date.now(),
|
|
1117
|
+
moduleId: input.moduleId,
|
|
1118
|
+
instanceId: input.instanceId
|
|
1119
|
+
};
|
|
1120
|
+
return replayLog.record(event);
|
|
1121
|
+
};
|
|
1122
|
+
if (listItem) {
|
|
1123
|
+
const store = internals.traits.rowIdStore;
|
|
1124
|
+
if (!store) {
|
|
1125
|
+
return Effect.void;
|
|
1126
|
+
}
|
|
1127
|
+
const listPath = listItem.listPath;
|
|
1128
|
+
const itemPath = listItem.itemPath;
|
|
1129
|
+
if (!itemPath) {
|
|
1130
|
+
return Effect.void;
|
|
1131
|
+
}
|
|
1132
|
+
const concurrency2 = entry.meta.concurrency;
|
|
1133
|
+
const mode2 = concurrency2 ?? "switch";
|
|
1134
|
+
const inFlight2 = /* @__PURE__ */ new Map();
|
|
1135
|
+
const trailing2 = /* @__PURE__ */ new Map();
|
|
1136
|
+
let gen2 = 0;
|
|
1137
|
+
store.onRemoved(listPath, (rowId) => {
|
|
1138
|
+
trailing2.delete(rowId);
|
|
1139
|
+
inFlight2.delete(rowId);
|
|
1140
|
+
});
|
|
1141
|
+
const setSnapshotForRowInTxn = (rowId, next, reason, stepId) => Effect.gen(function* () {
|
|
1142
|
+
let wrotePath;
|
|
1143
|
+
yield* bound.state.mutate((draft) => {
|
|
1144
|
+
const index = store.getIndex(listPath, rowId);
|
|
1145
|
+
if (index === void 0) return;
|
|
1146
|
+
const concretePath = toListItemValuePath(listPath, index, itemPath);
|
|
1147
|
+
const prev = getAtPath(draft, concretePath);
|
|
1148
|
+
if (Object.is(prev, next)) return;
|
|
1149
|
+
wrotePath = concretePath;
|
|
1150
|
+
setAtPathMutating(draft, concretePath, next);
|
|
1151
|
+
recordTraitPatch(bound, concretePath, reason, prev, next, step.debugInfo?.graphNodeId);
|
|
1152
|
+
});
|
|
1153
|
+
return wrotePath;
|
|
1154
|
+
});
|
|
1155
|
+
const writebackIfCurrentKeyHashForRow = (rowId, keyHash2, next, reason, stepId, phase) => Effect.gen(function* () {
|
|
1156
|
+
let wrotePath;
|
|
1157
|
+
yield* bound.state.mutate((draft) => {
|
|
1158
|
+
const index = store.getIndex(listPath, rowId);
|
|
1159
|
+
if (index === void 0) return;
|
|
1160
|
+
const concretePath = toListItemValuePath(listPath, index, itemPath);
|
|
1161
|
+
const current = getAtPath(draft, concretePath);
|
|
1162
|
+
const currentKeyHash = current && typeof current === "object" ? current.keyHash : void 0;
|
|
1163
|
+
if (currentKeyHash !== keyHash2) return;
|
|
1164
|
+
const prev = current;
|
|
1165
|
+
if (Object.is(prev, next)) return;
|
|
1166
|
+
wrotePath = concretePath;
|
|
1167
|
+
setAtPathMutating(draft, concretePath, next);
|
|
1168
|
+
if (phase) {
|
|
1169
|
+
const { moduleId, instanceId } = getBoundScope(bound);
|
|
1170
|
+
recordReplayEvent(bound, {
|
|
1171
|
+
_tag: "ResourceSnapshot",
|
|
1172
|
+
resourceId,
|
|
1173
|
+
fieldPath: concretePath,
|
|
1174
|
+
keyHash: keyHash2,
|
|
1175
|
+
concurrency: mode2,
|
|
1176
|
+
phase,
|
|
1177
|
+
snapshot: next,
|
|
1178
|
+
timestamp: Date.now(),
|
|
1179
|
+
moduleId,
|
|
1180
|
+
instanceId
|
|
1181
|
+
});
|
|
1182
|
+
}
|
|
1183
|
+
recordTraitPatch(bound, concretePath, reason, prev, next, step.debugInfo?.graphNodeId);
|
|
1184
|
+
});
|
|
1185
|
+
return wrotePath;
|
|
1186
|
+
});
|
|
1187
|
+
const startFetch2 = (rowId, key, keyHash2, replayMode, replayLog) => Effect.gen(function* () {
|
|
1188
|
+
const { moduleId, instanceId } = getBoundScope(bound);
|
|
1189
|
+
const indexForLog = store.getIndex(listPath, rowId);
|
|
1190
|
+
const logFieldPath = indexForLog === void 0 ? void 0 : toListItemValuePath(listPath, indexForLog, itemPath);
|
|
1191
|
+
let loadingSnapshot = Snapshot.loading({ keyHash: keyHash2 });
|
|
1192
|
+
if (replayMode === "replay" && replayLog && logFieldPath) {
|
|
1193
|
+
const replayLoading = yield* replayLog.consumeNextResourceSnapshot({
|
|
1194
|
+
resourceId,
|
|
1195
|
+
fieldPath: logFieldPath,
|
|
1196
|
+
keyHash: keyHash2,
|
|
1197
|
+
phase: "loading"
|
|
1198
|
+
});
|
|
1199
|
+
if (replayLoading) {
|
|
1200
|
+
loadingSnapshot = replayLoading.snapshot;
|
|
1201
|
+
}
|
|
1202
|
+
}
|
|
1203
|
+
const wroteLoadingPath = yield* setSnapshotForRowInTxn(
|
|
1204
|
+
rowId,
|
|
1205
|
+
loadingSnapshot,
|
|
1206
|
+
"source-refresh",
|
|
1207
|
+
`source:${fieldPath}:${rowId}:loading`
|
|
1208
|
+
);
|
|
1209
|
+
if (wroteLoadingPath) {
|
|
1210
|
+
const event = {
|
|
1211
|
+
_tag: "ResourceSnapshot",
|
|
1212
|
+
resourceId,
|
|
1213
|
+
fieldPath: wroteLoadingPath,
|
|
1214
|
+
keyHash: keyHash2,
|
|
1215
|
+
concurrency: mode2,
|
|
1216
|
+
phase: "loading",
|
|
1217
|
+
snapshot: loadingSnapshot,
|
|
1218
|
+
timestamp: Date.now(),
|
|
1219
|
+
moduleId,
|
|
1220
|
+
instanceId
|
|
1221
|
+
};
|
|
1222
|
+
recordReplayEvent(bound, event);
|
|
1223
|
+
yield* recordSnapshot(replayMode, replayLog, event);
|
|
1224
|
+
}
|
|
1225
|
+
const io = Effect.gen(function* () {
|
|
1226
|
+
if (replayMode === "replay" && replayLog) {
|
|
1227
|
+
yield* Effect.yieldNow();
|
|
1228
|
+
const consumePath = wroteLoadingPath ?? logFieldPath;
|
|
1229
|
+
if (!consumePath) return yield* Effect.void;
|
|
1230
|
+
const replayed = yield* replayLog.consumeNextResourceSnapshot({
|
|
1231
|
+
resourceId,
|
|
1232
|
+
fieldPath: consumePath,
|
|
1233
|
+
keyHash: keyHash2
|
|
1234
|
+
});
|
|
1235
|
+
if (!replayed) return yield* Effect.void;
|
|
1236
|
+
if (replayed.phase === "success") {
|
|
1237
|
+
yield* writebackIfCurrentKeyHashForRow(
|
|
1238
|
+
rowId,
|
|
1239
|
+
keyHash2,
|
|
1240
|
+
replayed.snapshot,
|
|
1241
|
+
"source-refresh",
|
|
1242
|
+
`source:${fieldPath}:${rowId}:success`,
|
|
1243
|
+
"success"
|
|
1244
|
+
);
|
|
1245
|
+
} else if (replayed.phase === "error") {
|
|
1246
|
+
yield* writebackIfCurrentKeyHashForRow(
|
|
1247
|
+
rowId,
|
|
1248
|
+
keyHash2,
|
|
1249
|
+
replayed.snapshot,
|
|
1250
|
+
"source-refresh",
|
|
1251
|
+
`source:${fieldPath}:${rowId}:error`,
|
|
1252
|
+
"error"
|
|
1253
|
+
);
|
|
1254
|
+
}
|
|
1255
|
+
return yield* Effect.void;
|
|
1256
|
+
}
|
|
1257
|
+
const stack = yield* getMiddlewareStack();
|
|
1258
|
+
const registryOpt = yield* Effect.serviceOption(internal.ResourceRegistryTag);
|
|
1259
|
+
const registry = Option.isSome(registryOpt) ? registryOpt.value : void 0;
|
|
1260
|
+
const spec = registry?.specs.get(resourceId);
|
|
1261
|
+
if (!spec) {
|
|
1262
|
+
return yield* Effect.void;
|
|
1263
|
+
}
|
|
1264
|
+
const loadEffect = spec.load(key);
|
|
1265
|
+
const meta = {
|
|
1266
|
+
moduleId,
|
|
1267
|
+
instanceId,
|
|
1268
|
+
fieldPath,
|
|
1269
|
+
resourceId,
|
|
1270
|
+
key,
|
|
1271
|
+
keyHash: keyHash2,
|
|
1272
|
+
rowId,
|
|
1273
|
+
traitNodeId: step.debugInfo?.graphNodeId,
|
|
1274
|
+
stepId: step.id
|
|
1275
|
+
};
|
|
1276
|
+
if (!(typeof meta.opSeq === "number" && Number.isFinite(meta.opSeq))) {
|
|
1277
|
+
const sessionOpt = yield* Effect.serviceOption(RunSessionTag);
|
|
1278
|
+
if (Option.isSome(sessionOpt)) {
|
|
1279
|
+
const seqKey = instanceId ?? "global";
|
|
1280
|
+
meta.opSeq = sessionOpt.value.local.nextSeq("opSeq", seqKey);
|
|
1281
|
+
}
|
|
1282
|
+
}
|
|
1283
|
+
const op = make({
|
|
1284
|
+
kind: "service",
|
|
1285
|
+
name: resourceId,
|
|
1286
|
+
effect: loadEffect,
|
|
1287
|
+
meta
|
|
1288
|
+
});
|
|
1289
|
+
const exit = yield* Effect.exit(run(op, stack));
|
|
1290
|
+
if (exit._tag === "Success") {
|
|
1291
|
+
const successSnapshot = Snapshot.success({ keyHash: keyHash2, data: exit.value });
|
|
1292
|
+
const wroteSuccessPath = yield* writebackIfCurrentKeyHashForRow(
|
|
1293
|
+
rowId,
|
|
1294
|
+
keyHash2,
|
|
1295
|
+
successSnapshot,
|
|
1296
|
+
"source-refresh",
|
|
1297
|
+
`source:${fieldPath}:${rowId}:success`,
|
|
1298
|
+
"success"
|
|
1299
|
+
);
|
|
1300
|
+
if (wroteSuccessPath) {
|
|
1301
|
+
yield* recordSnapshot(replayMode, replayLog, {
|
|
1302
|
+
_tag: "ResourceSnapshot",
|
|
1303
|
+
resourceId,
|
|
1304
|
+
fieldPath: wroteSuccessPath,
|
|
1305
|
+
keyHash: keyHash2,
|
|
1306
|
+
concurrency: mode2,
|
|
1307
|
+
phase: "success",
|
|
1308
|
+
snapshot: successSnapshot,
|
|
1309
|
+
timestamp: Date.now(),
|
|
1310
|
+
moduleId,
|
|
1311
|
+
instanceId
|
|
1312
|
+
});
|
|
1313
|
+
}
|
|
1314
|
+
} else {
|
|
1315
|
+
const errorSnapshot = Snapshot.error({ keyHash: keyHash2, error: exit.cause });
|
|
1316
|
+
const wroteErrorPath = yield* writebackIfCurrentKeyHashForRow(
|
|
1317
|
+
rowId,
|
|
1318
|
+
keyHash2,
|
|
1319
|
+
errorSnapshot,
|
|
1320
|
+
"source-refresh",
|
|
1321
|
+
`source:${fieldPath}:${rowId}:error`,
|
|
1322
|
+
"error"
|
|
1323
|
+
);
|
|
1324
|
+
if (wroteErrorPath) {
|
|
1325
|
+
yield* recordSnapshot(replayMode, replayLog, {
|
|
1326
|
+
_tag: "ResourceSnapshot",
|
|
1327
|
+
resourceId,
|
|
1328
|
+
fieldPath: wroteErrorPath,
|
|
1329
|
+
keyHash: keyHash2,
|
|
1330
|
+
concurrency: mode2,
|
|
1331
|
+
phase: "error",
|
|
1332
|
+
snapshot: errorSnapshot,
|
|
1333
|
+
timestamp: Date.now(),
|
|
1334
|
+
moduleId,
|
|
1335
|
+
instanceId
|
|
1336
|
+
});
|
|
1337
|
+
}
|
|
1338
|
+
}
|
|
1339
|
+
}).pipe(Effect.catchAllCause(() => Effect.void));
|
|
1340
|
+
const fiber = yield* Effect.forkScoped(Effect.locally(inSyncTransactionFiber, false)(io));
|
|
1341
|
+
const myGen = gen2 += 1;
|
|
1342
|
+
inFlight2.set(rowId, { gen: myGen, fiber, keyHash: keyHash2 });
|
|
1343
|
+
yield* Effect.forkScoped(
|
|
1344
|
+
Effect.locally(
|
|
1345
|
+
inSyncTransactionFiber,
|
|
1346
|
+
false
|
|
1347
|
+
)(
|
|
1348
|
+
Fiber.await(fiber).pipe(
|
|
1349
|
+
Effect.zipRight(
|
|
1350
|
+
Effect.sync(() => {
|
|
1351
|
+
const current = inFlight2.get(rowId);
|
|
1352
|
+
if (current && current.gen === myGen) {
|
|
1353
|
+
inFlight2.delete(rowId);
|
|
1354
|
+
}
|
|
1355
|
+
})
|
|
1356
|
+
),
|
|
1357
|
+
Effect.zipRight(
|
|
1358
|
+
mode2 === "exhaust-trailing" ? Effect.gen(function* () {
|
|
1359
|
+
const next = trailing2.get(rowId);
|
|
1360
|
+
trailing2.delete(rowId);
|
|
1361
|
+
if (next) {
|
|
1362
|
+
yield* startFetch2(rowId, next.key, next.keyHash, replayMode, replayLog);
|
|
1363
|
+
}
|
|
1364
|
+
}) : Effect.void
|
|
1365
|
+
),
|
|
1366
|
+
Effect.catchAllCause(() => Effect.void)
|
|
1367
|
+
)
|
|
1368
|
+
)
|
|
1369
|
+
);
|
|
1370
|
+
});
|
|
1371
|
+
register(
|
|
1372
|
+
fieldPath,
|
|
1373
|
+
(state) => Effect.gen(function* () {
|
|
1374
|
+
const { moduleId, instanceId } = getBoundScope(bound);
|
|
1375
|
+
const replayModeOpt = yield* Effect.serviceOption(ReplayModeConfigTag);
|
|
1376
|
+
const replayMode = Option.isSome(replayModeOpt) ? replayModeOpt.value.mode : "live";
|
|
1377
|
+
const replayLogOpt = yield* Effect.serviceOption(ReplayLog);
|
|
1378
|
+
const replayLog = Option.isSome(replayLogOpt) ? replayLogOpt.value : void 0;
|
|
1379
|
+
const force = yield* FiberRef.get(forceSourceRefresh);
|
|
1380
|
+
const listValue = getAtPath(state, listPath);
|
|
1381
|
+
const items = Array.isArray(listValue) ? listValue : [];
|
|
1382
|
+
const ids = store.ensureList(listPath, items);
|
|
1383
|
+
const traceKey = `${instanceId ?? "unknown"}::source::${fieldPath}`;
|
|
1384
|
+
if (isDevEnv() && (yield* onceInRunSession(`deps_trace_settled:${traceKey}`))) {
|
|
1385
|
+
try {
|
|
1386
|
+
const sample = items[0];
|
|
1387
|
+
if (sample !== void 0) {
|
|
1388
|
+
const traced = trace((s) => entry.meta.key(s), sample);
|
|
1389
|
+
const prefixedReads = traced.reads.map((r) => r ? `${listPath}[].${r}` : `${listPath}[]`);
|
|
1390
|
+
const diff = diffDeps(entry.meta.deps ?? [], prefixedReads);
|
|
1391
|
+
if (diff) {
|
|
1392
|
+
yield* emitDepsMismatch({
|
|
1393
|
+
moduleId,
|
|
1394
|
+
instanceId,
|
|
1395
|
+
kind: "source",
|
|
1396
|
+
fieldPath,
|
|
1397
|
+
diff
|
|
1398
|
+
});
|
|
1399
|
+
}
|
|
1400
|
+
}
|
|
1401
|
+
} catch {
|
|
1402
|
+
}
|
|
1403
|
+
}
|
|
1404
|
+
for (let index = 0; index < items.length; index++) {
|
|
1405
|
+
const rowId = ids[index];
|
|
1406
|
+
if (!rowId) continue;
|
|
1407
|
+
const concretePath = toListItemValuePath(listPath, index, itemPath);
|
|
1408
|
+
const prevSnapshot = getAtPath(state, concretePath);
|
|
1409
|
+
let key;
|
|
1410
|
+
try {
|
|
1411
|
+
key = entry.meta.key(items[index]);
|
|
1412
|
+
} catch {
|
|
1413
|
+
key = void 0;
|
|
1414
|
+
}
|
|
1415
|
+
const current = inFlight2.get(rowId);
|
|
1416
|
+
if (key === void 0) {
|
|
1417
|
+
trailing2.delete(rowId);
|
|
1418
|
+
inFlight2.delete(rowId);
|
|
1419
|
+
if (prevSnapshot && typeof prevSnapshot === "object" && prevSnapshot.status === "idle" && prevSnapshot.data === void 0 && prevSnapshot.error === void 0) {
|
|
1420
|
+
continue;
|
|
1421
|
+
}
|
|
1422
|
+
const idleSnapshot = Snapshot.idle();
|
|
1423
|
+
const wroteIdlePath = yield* setSnapshotForRowInTxn(
|
|
1424
|
+
rowId,
|
|
1425
|
+
idleSnapshot,
|
|
1426
|
+
"source-refresh",
|
|
1427
|
+
`source:${fieldPath}:${rowId}:idle`
|
|
1428
|
+
);
|
|
1429
|
+
if (wroteIdlePath) {
|
|
1430
|
+
const event = {
|
|
1431
|
+
_tag: "ResourceSnapshot",
|
|
1432
|
+
resourceId,
|
|
1433
|
+
fieldPath: wroteIdlePath,
|
|
1434
|
+
keyHash: void 0,
|
|
1435
|
+
concurrency: mode2,
|
|
1436
|
+
phase: "idle",
|
|
1437
|
+
snapshot: idleSnapshot,
|
|
1438
|
+
timestamp: Date.now(),
|
|
1439
|
+
moduleId,
|
|
1440
|
+
instanceId
|
|
1441
|
+
};
|
|
1442
|
+
recordReplayEvent(bound, event);
|
|
1443
|
+
yield* recordSnapshot(replayMode, replayLog, event);
|
|
1444
|
+
}
|
|
1445
|
+
continue;
|
|
1446
|
+
}
|
|
1447
|
+
const h = keyHash(key);
|
|
1448
|
+
if (!force && current && current.keyHash === h) {
|
|
1449
|
+
continue;
|
|
1450
|
+
}
|
|
1451
|
+
const prevKeyHash = prevSnapshot && typeof prevSnapshot === "object" ? prevSnapshot.keyHash : void 0;
|
|
1452
|
+
if (!force && !current && prevKeyHash === h) {
|
|
1453
|
+
continue;
|
|
1454
|
+
}
|
|
1455
|
+
if (mode2 === "exhaust-trailing" && current) {
|
|
1456
|
+
trailing2.set(rowId, { key, keyHash: h });
|
|
1457
|
+
const loadingSnapshot = Snapshot.loading({ keyHash: h });
|
|
1458
|
+
const wroteLoadingPath = yield* setSnapshotForRowInTxn(
|
|
1459
|
+
rowId,
|
|
1460
|
+
loadingSnapshot,
|
|
1461
|
+
"source-refresh",
|
|
1462
|
+
`source:${fieldPath}:${rowId}:loading`
|
|
1463
|
+
);
|
|
1464
|
+
if (wroteLoadingPath) {
|
|
1465
|
+
const event = {
|
|
1466
|
+
_tag: "ResourceSnapshot",
|
|
1467
|
+
resourceId,
|
|
1468
|
+
fieldPath: wroteLoadingPath,
|
|
1469
|
+
keyHash: h,
|
|
1470
|
+
concurrency: mode2,
|
|
1471
|
+
phase: "loading",
|
|
1472
|
+
snapshot: loadingSnapshot,
|
|
1473
|
+
timestamp: Date.now(),
|
|
1474
|
+
moduleId,
|
|
1475
|
+
instanceId
|
|
1476
|
+
};
|
|
1477
|
+
recordReplayEvent(bound, event);
|
|
1478
|
+
yield* recordSnapshot(replayMode, replayLog, event);
|
|
1479
|
+
}
|
|
1480
|
+
continue;
|
|
1481
|
+
}
|
|
1482
|
+
if (mode2 === "switch" && current) {
|
|
1483
|
+
trailing2.delete(rowId);
|
|
1484
|
+
inFlight2.delete(rowId);
|
|
1485
|
+
}
|
|
1486
|
+
yield* startFetch2(rowId, key, h, replayMode, replayLog);
|
|
1487
|
+
}
|
|
1488
|
+
})
|
|
1489
|
+
);
|
|
1490
|
+
return Effect.void;
|
|
1491
|
+
}
|
|
1492
|
+
let inFlight;
|
|
1493
|
+
let gen = 0;
|
|
1494
|
+
let trailing;
|
|
1495
|
+
const concurrency = entry.meta.concurrency;
|
|
1496
|
+
const mode = concurrency ?? "switch";
|
|
1497
|
+
const startFetch = (key, keyHash2, replayMode, replayLog) => Effect.gen(function* () {
|
|
1498
|
+
const { moduleId, instanceId } = getBoundScope(bound);
|
|
1499
|
+
let loadingSnapshot = Snapshot.loading({ keyHash: keyHash2 });
|
|
1500
|
+
if (replayMode === "replay" && replayLog) {
|
|
1501
|
+
const replayLoading = yield* replayLog.consumeNextResourceSnapshot({
|
|
1502
|
+
resourceId,
|
|
1503
|
+
fieldPath,
|
|
1504
|
+
keyHash: keyHash2,
|
|
1505
|
+
phase: "loading"
|
|
1506
|
+
});
|
|
1507
|
+
if (replayLoading) {
|
|
1508
|
+
loadingSnapshot = replayLoading.snapshot;
|
|
1509
|
+
}
|
|
1510
|
+
}
|
|
1511
|
+
const wroteLoading = yield* setSnapshotInTxn(
|
|
1512
|
+
bound,
|
|
1513
|
+
fieldPath,
|
|
1514
|
+
loadingSnapshot,
|
|
1515
|
+
"source-refresh",
|
|
1516
|
+
`source:${fieldPath}:loading`,
|
|
1517
|
+
step.debugInfo?.graphNodeId
|
|
1518
|
+
);
|
|
1519
|
+
if (wroteLoading) {
|
|
1520
|
+
const event = {
|
|
1521
|
+
_tag: "ResourceSnapshot",
|
|
1522
|
+
resourceId,
|
|
1523
|
+
fieldPath,
|
|
1524
|
+
keyHash: keyHash2,
|
|
1525
|
+
concurrency: mode,
|
|
1526
|
+
phase: "loading",
|
|
1527
|
+
snapshot: loadingSnapshot,
|
|
1528
|
+
timestamp: Date.now(),
|
|
1529
|
+
moduleId,
|
|
1530
|
+
instanceId
|
|
1531
|
+
};
|
|
1532
|
+
recordReplayEvent(bound, event);
|
|
1533
|
+
yield* recordSnapshot(replayMode, replayLog, event);
|
|
1534
|
+
}
|
|
1535
|
+
const io = Effect.gen(function* () {
|
|
1536
|
+
if (replayMode === "replay" && replayLog) {
|
|
1537
|
+
yield* Effect.yieldNow();
|
|
1538
|
+
const replayed = yield* replayLog.consumeNextResourceSnapshot({
|
|
1539
|
+
resourceId,
|
|
1540
|
+
fieldPath,
|
|
1541
|
+
keyHash: keyHash2
|
|
1542
|
+
});
|
|
1543
|
+
if (!replayed) return yield* Effect.void;
|
|
1544
|
+
if (replayed.phase === "success") {
|
|
1545
|
+
const event = {
|
|
1546
|
+
_tag: "ResourceSnapshot",
|
|
1547
|
+
resourceId,
|
|
1548
|
+
fieldPath,
|
|
1549
|
+
keyHash: keyHash2,
|
|
1550
|
+
concurrency: mode,
|
|
1551
|
+
phase: "success",
|
|
1552
|
+
snapshot: replayed.snapshot,
|
|
1553
|
+
timestamp: Date.now(),
|
|
1554
|
+
moduleId,
|
|
1555
|
+
instanceId
|
|
1556
|
+
};
|
|
1557
|
+
yield* writebackIfCurrentKeyHash(
|
|
1558
|
+
bound,
|
|
1559
|
+
fieldPath,
|
|
1560
|
+
keyHash2,
|
|
1561
|
+
replayed.snapshot,
|
|
1562
|
+
"source-refresh",
|
|
1563
|
+
`source:${fieldPath}:success`,
|
|
1564
|
+
step.debugInfo?.graphNodeId,
|
|
1565
|
+
event
|
|
1566
|
+
);
|
|
1567
|
+
} else if (replayed.phase === "error") {
|
|
1568
|
+
const event = {
|
|
1569
|
+
_tag: "ResourceSnapshot",
|
|
1570
|
+
resourceId,
|
|
1571
|
+
fieldPath,
|
|
1572
|
+
keyHash: keyHash2,
|
|
1573
|
+
concurrency: mode,
|
|
1574
|
+
phase: "error",
|
|
1575
|
+
snapshot: replayed.snapshot,
|
|
1576
|
+
timestamp: Date.now(),
|
|
1577
|
+
moduleId,
|
|
1578
|
+
instanceId
|
|
1579
|
+
};
|
|
1580
|
+
yield* writebackIfCurrentKeyHash(
|
|
1581
|
+
bound,
|
|
1582
|
+
fieldPath,
|
|
1583
|
+
keyHash2,
|
|
1584
|
+
replayed.snapshot,
|
|
1585
|
+
"source-refresh",
|
|
1586
|
+
`source:${fieldPath}:error`,
|
|
1587
|
+
step.debugInfo?.graphNodeId,
|
|
1588
|
+
event
|
|
1589
|
+
);
|
|
1590
|
+
}
|
|
1591
|
+
return yield* Effect.void;
|
|
1592
|
+
}
|
|
1593
|
+
const stack = yield* getMiddlewareStack();
|
|
1594
|
+
const registryOpt = yield* Effect.serviceOption(internal.ResourceRegistryTag);
|
|
1595
|
+
const registry = Option.isSome(registryOpt) ? registryOpt.value : void 0;
|
|
1596
|
+
const spec = registry?.specs.get(resourceId);
|
|
1597
|
+
if (!spec) {
|
|
1598
|
+
return yield* Effect.void;
|
|
1599
|
+
}
|
|
1600
|
+
const loadEffect = spec.load(key);
|
|
1601
|
+
const meta = {
|
|
1602
|
+
moduleId,
|
|
1603
|
+
instanceId,
|
|
1604
|
+
fieldPath,
|
|
1605
|
+
resourceId,
|
|
1606
|
+
key,
|
|
1607
|
+
keyHash: keyHash2,
|
|
1608
|
+
traitNodeId: step.debugInfo?.graphNodeId,
|
|
1609
|
+
stepId: step.id
|
|
1610
|
+
};
|
|
1611
|
+
if (!(typeof meta.opSeq === "number" && Number.isFinite(meta.opSeq))) {
|
|
1612
|
+
const sessionOpt = yield* Effect.serviceOption(RunSessionTag);
|
|
1613
|
+
if (Option.isSome(sessionOpt)) {
|
|
1614
|
+
const seqKey = instanceId ?? "global";
|
|
1615
|
+
meta.opSeq = sessionOpt.value.local.nextSeq("opSeq", seqKey);
|
|
1616
|
+
}
|
|
1617
|
+
}
|
|
1618
|
+
const op = make({
|
|
1619
|
+
kind: "trait-source",
|
|
1620
|
+
name: resourceId,
|
|
1621
|
+
effect: loadEffect,
|
|
1622
|
+
meta
|
|
1623
|
+
});
|
|
1624
|
+
const exit = yield* Effect.exit(run(op, stack));
|
|
1625
|
+
if (exit._tag === "Success") {
|
|
1626
|
+
const successSnapshot = Snapshot.success({ keyHash: keyHash2, data: exit.value });
|
|
1627
|
+
const event = {
|
|
1628
|
+
_tag: "ResourceSnapshot",
|
|
1629
|
+
resourceId,
|
|
1630
|
+
fieldPath,
|
|
1631
|
+
keyHash: keyHash2,
|
|
1632
|
+
concurrency: mode,
|
|
1633
|
+
phase: "success",
|
|
1634
|
+
snapshot: successSnapshot,
|
|
1635
|
+
timestamp: Date.now(),
|
|
1636
|
+
moduleId,
|
|
1637
|
+
instanceId
|
|
1638
|
+
};
|
|
1639
|
+
const wroteSuccess = yield* writebackIfCurrentKeyHash(
|
|
1640
|
+
bound,
|
|
1641
|
+
fieldPath,
|
|
1642
|
+
keyHash2,
|
|
1643
|
+
successSnapshot,
|
|
1644
|
+
"source-refresh",
|
|
1645
|
+
`source:${fieldPath}:success`,
|
|
1646
|
+
step.debugInfo?.graphNodeId,
|
|
1647
|
+
event
|
|
1648
|
+
);
|
|
1649
|
+
if (wroteSuccess) {
|
|
1650
|
+
yield* recordSnapshot(replayMode, replayLog, event);
|
|
1651
|
+
}
|
|
1652
|
+
} else {
|
|
1653
|
+
const errorSnapshot = Snapshot.error({ keyHash: keyHash2, error: exit.cause });
|
|
1654
|
+
const event = {
|
|
1655
|
+
_tag: "ResourceSnapshot",
|
|
1656
|
+
resourceId,
|
|
1657
|
+
fieldPath,
|
|
1658
|
+
keyHash: keyHash2,
|
|
1659
|
+
concurrency: mode,
|
|
1660
|
+
phase: "error",
|
|
1661
|
+
snapshot: errorSnapshot,
|
|
1662
|
+
timestamp: Date.now(),
|
|
1663
|
+
moduleId,
|
|
1664
|
+
instanceId
|
|
1665
|
+
};
|
|
1666
|
+
const wroteError = yield* writebackIfCurrentKeyHash(
|
|
1667
|
+
bound,
|
|
1668
|
+
fieldPath,
|
|
1669
|
+
keyHash2,
|
|
1670
|
+
errorSnapshot,
|
|
1671
|
+
"source-refresh",
|
|
1672
|
+
`source:${fieldPath}:error`,
|
|
1673
|
+
step.debugInfo?.graphNodeId,
|
|
1674
|
+
event
|
|
1675
|
+
);
|
|
1676
|
+
if (wroteError) {
|
|
1677
|
+
yield* recordSnapshot(replayMode, replayLog, event);
|
|
1678
|
+
}
|
|
1679
|
+
}
|
|
1680
|
+
}).pipe(Effect.catchAllCause(() => Effect.void));
|
|
1681
|
+
const fiber = yield* Effect.forkScoped(Effect.locally(inSyncTransactionFiber, false)(io));
|
|
1682
|
+
const myGen = gen += 1;
|
|
1683
|
+
inFlight = { gen: myGen, fiber, keyHash: keyHash2 };
|
|
1684
|
+
yield* Effect.forkScoped(
|
|
1685
|
+
Effect.locally(
|
|
1686
|
+
inSyncTransactionFiber,
|
|
1687
|
+
false
|
|
1688
|
+
)(
|
|
1689
|
+
Fiber.await(fiber).pipe(
|
|
1690
|
+
Effect.zipRight(
|
|
1691
|
+
Effect.sync(() => {
|
|
1692
|
+
if (inFlight && inFlight.gen === myGen) {
|
|
1693
|
+
inFlight = void 0;
|
|
1694
|
+
}
|
|
1695
|
+
})
|
|
1696
|
+
),
|
|
1697
|
+
Effect.zipRight(
|
|
1698
|
+
mode === "exhaust-trailing" ? Effect.gen(function* () {
|
|
1699
|
+
const next = trailing;
|
|
1700
|
+
trailing = void 0;
|
|
1701
|
+
if (next) {
|
|
1702
|
+
yield* startFetch(next.key, next.keyHash, replayMode, replayLog);
|
|
1703
|
+
}
|
|
1704
|
+
}) : Effect.void
|
|
1705
|
+
),
|
|
1706
|
+
Effect.catchAllCause(() => Effect.void)
|
|
1707
|
+
)
|
|
1708
|
+
)
|
|
1709
|
+
);
|
|
1710
|
+
});
|
|
1711
|
+
register(
|
|
1712
|
+
fieldPath,
|
|
1713
|
+
(state) => Effect.gen(function* () {
|
|
1714
|
+
const { moduleId, instanceId } = getBoundScope(bound);
|
|
1715
|
+
const replayModeOpt = yield* Effect.serviceOption(ReplayModeConfigTag);
|
|
1716
|
+
const replayMode = Option.isSome(replayModeOpt) ? replayModeOpt.value.mode : "live";
|
|
1717
|
+
const replayLogOpt = yield* Effect.serviceOption(ReplayLog);
|
|
1718
|
+
const replayLog = Option.isSome(replayLogOpt) ? replayLogOpt.value : void 0;
|
|
1719
|
+
const force = yield* FiberRef.get(forceSourceRefresh);
|
|
1720
|
+
let key;
|
|
1721
|
+
try {
|
|
1722
|
+
key = entry.meta.key(state);
|
|
1723
|
+
} catch {
|
|
1724
|
+
key = void 0;
|
|
1725
|
+
}
|
|
1726
|
+
const traceKey = `${instanceId ?? "unknown"}::source::${fieldPath}`;
|
|
1727
|
+
if (isDevEnv() && (yield* onceInRunSession(`deps_trace_settled:${traceKey}`))) {
|
|
1728
|
+
try {
|
|
1729
|
+
const traced = trace((s) => entry.meta.key(s), state);
|
|
1730
|
+
const diff = diffDeps(entry.meta.deps ?? [], traced.reads);
|
|
1731
|
+
if (diff) {
|
|
1732
|
+
yield* emitDepsMismatch({
|
|
1733
|
+
moduleId,
|
|
1734
|
+
instanceId,
|
|
1735
|
+
kind: "source",
|
|
1736
|
+
fieldPath,
|
|
1737
|
+
diff
|
|
1738
|
+
});
|
|
1739
|
+
}
|
|
1740
|
+
} catch {
|
|
1741
|
+
}
|
|
1742
|
+
}
|
|
1743
|
+
if (key === void 0) {
|
|
1744
|
+
if (inFlight) {
|
|
1745
|
+
yield* Fiber.interruptFork(inFlight.fiber);
|
|
1746
|
+
inFlight = void 0;
|
|
1747
|
+
}
|
|
1748
|
+
trailing = void 0;
|
|
1749
|
+
const idleSnapshot = Snapshot.idle();
|
|
1750
|
+
const wroteIdle = yield* setSnapshotInTxn(
|
|
1751
|
+
bound,
|
|
1752
|
+
fieldPath,
|
|
1753
|
+
idleSnapshot,
|
|
1754
|
+
"source-refresh",
|
|
1755
|
+
`source:${fieldPath}:idle`,
|
|
1756
|
+
step.debugInfo?.graphNodeId
|
|
1757
|
+
);
|
|
1758
|
+
if (wroteIdle) {
|
|
1759
|
+
const event = {
|
|
1760
|
+
_tag: "ResourceSnapshot",
|
|
1761
|
+
resourceId,
|
|
1762
|
+
fieldPath,
|
|
1763
|
+
keyHash: void 0,
|
|
1764
|
+
concurrency: mode,
|
|
1765
|
+
phase: "idle",
|
|
1766
|
+
snapshot: idleSnapshot,
|
|
1767
|
+
timestamp: Date.now(),
|
|
1768
|
+
moduleId,
|
|
1769
|
+
instanceId
|
|
1770
|
+
};
|
|
1771
|
+
recordReplayEvent(bound, event);
|
|
1772
|
+
yield* recordSnapshot(replayMode, replayLog, event);
|
|
1773
|
+
}
|
|
1774
|
+
return;
|
|
1775
|
+
}
|
|
1776
|
+
const h = keyHash(key);
|
|
1777
|
+
if (!force) {
|
|
1778
|
+
if (inFlight && inFlight.keyHash === h) {
|
|
1779
|
+
return;
|
|
1780
|
+
}
|
|
1781
|
+
const currentSnapshot = getAtPath(state, fieldPath);
|
|
1782
|
+
const currentKeyHash = currentSnapshot && typeof currentSnapshot === "object" ? currentSnapshot.keyHash : void 0;
|
|
1783
|
+
const currentStatus = currentSnapshot && typeof currentSnapshot === "object" ? currentSnapshot.status : void 0;
|
|
1784
|
+
if (currentStatus && currentStatus !== "idle" && currentKeyHash === h) {
|
|
1785
|
+
return;
|
|
1786
|
+
}
|
|
1787
|
+
}
|
|
1788
|
+
if (mode === "exhaust-trailing" && inFlight) {
|
|
1789
|
+
trailing = { key, keyHash: h };
|
|
1790
|
+
const loadingSnapshot = Snapshot.loading({ keyHash: h });
|
|
1791
|
+
const wroteLoading = yield* setSnapshotInTxn(
|
|
1792
|
+
bound,
|
|
1793
|
+
fieldPath,
|
|
1794
|
+
loadingSnapshot,
|
|
1795
|
+
"source-refresh",
|
|
1796
|
+
`source:${fieldPath}:loading`,
|
|
1797
|
+
step.debugInfo?.graphNodeId
|
|
1798
|
+
);
|
|
1799
|
+
if (wroteLoading) {
|
|
1800
|
+
const event = {
|
|
1801
|
+
_tag: "ResourceSnapshot",
|
|
1802
|
+
resourceId,
|
|
1803
|
+
fieldPath,
|
|
1804
|
+
keyHash: h,
|
|
1805
|
+
concurrency: mode,
|
|
1806
|
+
phase: "loading",
|
|
1807
|
+
snapshot: loadingSnapshot,
|
|
1808
|
+
timestamp: Date.now(),
|
|
1809
|
+
moduleId,
|
|
1810
|
+
instanceId
|
|
1811
|
+
};
|
|
1812
|
+
recordReplayEvent(bound, event);
|
|
1813
|
+
yield* recordSnapshot(replayMode, replayLog, event);
|
|
1814
|
+
}
|
|
1815
|
+
return;
|
|
1816
|
+
}
|
|
1817
|
+
if (mode === "switch" && inFlight) {
|
|
1818
|
+
yield* Fiber.interruptFork(inFlight.fiber);
|
|
1819
|
+
inFlight = void 0;
|
|
1820
|
+
trailing = void 0;
|
|
1821
|
+
}
|
|
1822
|
+
yield* startFetch(key, h, replayMode, replayLog);
|
|
1823
|
+
})
|
|
1824
|
+
);
|
|
1825
|
+
return Effect.void;
|
|
1826
|
+
};
|
|
1827
|
+
|
|
1828
|
+
// ../logix-core/src/internal/state-trait/converge-diagnostics.ts
|
|
1829
|
+
import { Effect as Effect2, FiberRef as FiberRef2, Option as Option2 } from "../effect.js";
|
|
1830
|
+
import * as SchemaAST2 from "../effect/SchemaAST.js";
|
|
1831
|
+
var onceKeysFallback = /* @__PURE__ */ new Set();
|
|
1832
|
+
var onceInRunSession2 = (key) => Effect2.serviceOption(RunSessionTag).pipe(
|
|
1833
|
+
Effect2.map((maybe) => {
|
|
1834
|
+
if (Option2.isSome(maybe)) {
|
|
1835
|
+
return maybe.value.local.once(key);
|
|
1836
|
+
}
|
|
1837
|
+
if (onceKeysFallback.has(key)) return false;
|
|
1838
|
+
onceKeysFallback.add(key);
|
|
1839
|
+
return true;
|
|
1840
|
+
})
|
|
1841
|
+
);
|
|
1842
|
+
var formatList2 = (items, limit = 10) => {
|
|
1843
|
+
if (items.length === 0) return "";
|
|
1844
|
+
if (items.length <= limit) return items.join(", ");
|
|
1845
|
+
return `${items.slice(0, limit).join(", ")}, \u2026(+${items.length - limit})`;
|
|
1846
|
+
};
|
|
1847
|
+
var emitDepsMismatch2 = (params) => {
|
|
1848
|
+
return Effect2.gen(function* () {
|
|
1849
|
+
const key = `${params.moduleId ?? "unknown"}::${params.instanceId ?? "unknown"}::${params.kind}::${params.fieldPath}`;
|
|
1850
|
+
const shouldEmit = yield* onceInRunSession2(`deps_mismatch:${key}`);
|
|
1851
|
+
if (!shouldEmit) return;
|
|
1852
|
+
yield* record({
|
|
1853
|
+
type: "diagnostic",
|
|
1854
|
+
moduleId: params.moduleId,
|
|
1855
|
+
instanceId: params.instanceId,
|
|
1856
|
+
code: "state_trait::deps_mismatch",
|
|
1857
|
+
severity: "warning",
|
|
1858
|
+
message: `[deps] ${params.kind} "${params.fieldPath}" declared=[${formatList2(params.diff.declared)}] reads=[${formatList2(params.diff.reads)}] missing=[${formatList2(params.diff.missing)}] unused=[${formatList2(params.diff.unused)}]`,
|
|
1859
|
+
hint: 'deps is the single source of truth for dependencies: incremental scheduling / reverse closures / performance optimizations rely on deps only. Keep deps consistent with actual reads; if you really depend on the whole object, declare a coarser-grained dep (e.g. "profile") to cover sub-field reads.',
|
|
1860
|
+
kind: `deps_mismatch:${params.kind}`
|
|
1861
|
+
});
|
|
1862
|
+
});
|
|
1863
|
+
};
|
|
1864
|
+
var schemaHasPath = (ast, segments, seen = /* @__PURE__ */ new Set()) => {
|
|
1865
|
+
if (segments.length === 0) return true;
|
|
1866
|
+
let current = ast;
|
|
1867
|
+
while (true) {
|
|
1868
|
+
if (SchemaAST2.isSuspend(current)) {
|
|
1869
|
+
if (seen.has(current)) {
|
|
1870
|
+
return true;
|
|
1871
|
+
}
|
|
1872
|
+
seen.add(current);
|
|
1873
|
+
current = current.f();
|
|
1874
|
+
continue;
|
|
1875
|
+
}
|
|
1876
|
+
if (SchemaAST2.isRefinement(current)) {
|
|
1877
|
+
current = current.from;
|
|
1878
|
+
continue;
|
|
1879
|
+
}
|
|
1880
|
+
break;
|
|
1881
|
+
}
|
|
1882
|
+
if (SchemaAST2.isTransformation(current)) {
|
|
1883
|
+
return schemaHasPath(current.to, segments, seen) || schemaHasPath(current.from, segments, seen);
|
|
1884
|
+
}
|
|
1885
|
+
if (SchemaAST2.isUnion(current)) {
|
|
1886
|
+
return current.types.some((t) => schemaHasPath(t, segments, seen));
|
|
1887
|
+
}
|
|
1888
|
+
if (SchemaAST2.isTupleType(current)) {
|
|
1889
|
+
const candidates = [];
|
|
1890
|
+
for (const e of current.elements) candidates.push(e.type);
|
|
1891
|
+
for (const r of current.rest) candidates.push(r.type);
|
|
1892
|
+
if (candidates.length === 0) return true;
|
|
1893
|
+
return candidates.some((t) => schemaHasPath(t, segments, seen));
|
|
1894
|
+
}
|
|
1895
|
+
if (SchemaAST2.isTypeLiteral(current)) {
|
|
1896
|
+
const [head, ...tail] = segments;
|
|
1897
|
+
for (const ps of current.propertySignatures) {
|
|
1898
|
+
if (String(ps.name) !== head) continue;
|
|
1899
|
+
return schemaHasPath(ps.type, tail, seen);
|
|
1900
|
+
}
|
|
1901
|
+
for (const sig of current.indexSignatures) {
|
|
1902
|
+
let param = sig.parameter;
|
|
1903
|
+
while (SchemaAST2.isRefinement(param)) {
|
|
1904
|
+
param = param.from;
|
|
1905
|
+
}
|
|
1906
|
+
const tag2 = param?._tag;
|
|
1907
|
+
if (tag2 === "StringKeyword" || tag2 === "TemplateLiteral") {
|
|
1908
|
+
return schemaHasPath(sig.type, tail, seen);
|
|
1909
|
+
}
|
|
1910
|
+
}
|
|
1911
|
+
return false;
|
|
1912
|
+
}
|
|
1913
|
+
const tag = current?._tag;
|
|
1914
|
+
if (tag === "AnyKeyword" || tag === "UnknownKeyword" || tag === "ObjectKeyword" || tag === "Declaration") {
|
|
1915
|
+
return true;
|
|
1916
|
+
}
|
|
1917
|
+
return false;
|
|
1918
|
+
};
|
|
1919
|
+
var schemaHasFieldPath = (stateSchemaAst, path) => {
|
|
1920
|
+
if (!path) return true;
|
|
1921
|
+
if (path === "$root") return true;
|
|
1922
|
+
const normalized = normalizeFieldPath(path);
|
|
1923
|
+
if (!normalized) return false;
|
|
1924
|
+
const segs = normalized[0] === "$root" ? normalized.slice(1) : normalized;
|
|
1925
|
+
return schemaHasPath(stateSchemaAst, segs);
|
|
1926
|
+
};
|
|
1927
|
+
var formatSchemaMismatchLine = (ref) => {
|
|
1928
|
+
if (ref.kind === "fieldPath") {
|
|
1929
|
+
return `- ${ref.entryKind} "${ref.entryFieldPath}" fieldPath="${ref.path}"`;
|
|
1930
|
+
}
|
|
1931
|
+
if (ref.kind === "dep") {
|
|
1932
|
+
const rule = ref.ruleName ? ` rule="${ref.ruleName}"` : "";
|
|
1933
|
+
return `- ${ref.entryKind} "${ref.entryFieldPath}" deps="${ref.path}"${rule}`;
|
|
1934
|
+
}
|
|
1935
|
+
if (ref.kind === "link_from") {
|
|
1936
|
+
return `- link "${ref.entryFieldPath}" from="${ref.path}"`;
|
|
1937
|
+
}
|
|
1938
|
+
if (ref.kind === "check_writeback") {
|
|
1939
|
+
return `- check "${ref.entryFieldPath}" writeback="${ref.path}"`;
|
|
1940
|
+
}
|
|
1941
|
+
return `- ${ref.entryKind} "${ref.entryFieldPath}" path="${ref.path}"`;
|
|
1942
|
+
};
|
|
1943
|
+
var emitSchemaMismatch = (program, ctx) => Effect2.gen(function* () {
|
|
1944
|
+
if (!isDevEnv()) return;
|
|
1945
|
+
const level = yield* FiberRef2.get(currentDiagnosticsLevel);
|
|
1946
|
+
if (level === "off") return;
|
|
1947
|
+
const key = `${ctx.moduleId ?? "unknown"}::${ctx.instanceId}`;
|
|
1948
|
+
const shouldEmit = yield* onceInRunSession2(`schema_mismatch:${key}`);
|
|
1949
|
+
if (!shouldEmit) return;
|
|
1950
|
+
const refs = program.schemaPaths ?? [];
|
|
1951
|
+
if (refs.length === 0) return;
|
|
1952
|
+
const stateSchemaAst = program.stateSchema.ast;
|
|
1953
|
+
const mismatches = [];
|
|
1954
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1955
|
+
for (const ref of refs) {
|
|
1956
|
+
if (schemaHasFieldPath(stateSchemaAst, ref.path)) continue;
|
|
1957
|
+
const k = `${ref.kind}|${ref.entryKind}|${ref.entryFieldPath}|${ref.ruleName ?? ""}|${ref.path}`;
|
|
1958
|
+
if (seen.has(k)) continue;
|
|
1959
|
+
seen.add(k);
|
|
1960
|
+
mismatches.push(ref);
|
|
1961
|
+
}
|
|
1962
|
+
if (mismatches.length === 0) return;
|
|
1963
|
+
const limit = level === "light" ? 8 : 24;
|
|
1964
|
+
const lines = mismatches.slice(0, limit).map(formatSchemaMismatchLine);
|
|
1965
|
+
if (mismatches.length > limit) {
|
|
1966
|
+
lines.push(`- \u2026(+${mismatches.length - limit})`);
|
|
1967
|
+
}
|
|
1968
|
+
yield* record({
|
|
1969
|
+
type: "diagnostic",
|
|
1970
|
+
moduleId: ctx.moduleId,
|
|
1971
|
+
instanceId: ctx.instanceId,
|
|
1972
|
+
code: "state_trait::schema_mismatch",
|
|
1973
|
+
severity: "warning",
|
|
1974
|
+
message: `[schema] The following paths are not declared in stateSchema (total ${mismatches.length}):
|
|
1975
|
+
${lines.join("\n")}`,
|
|
1976
|
+
hint: "StateTrait writeback will create missing objects/fields. Declare all fieldPath/deps/link.from and errors.* writeback paths in stateSchema, or fix typos in trait paths.",
|
|
1977
|
+
kind: "schema_mismatch"
|
|
1978
|
+
});
|
|
1979
|
+
});
|
|
1980
|
+
|
|
1981
|
+
export {
|
|
1982
|
+
onceInRunSession2 as onceInRunSession,
|
|
1983
|
+
emitDepsMismatch2 as emitDepsMismatch,
|
|
1984
|
+
emitSchemaMismatch,
|
|
1985
|
+
diffDeps,
|
|
1986
|
+
trace,
|
|
1987
|
+
syncIdleInTransaction,
|
|
1988
|
+
installSourceRefresh,
|
|
1989
|
+
build
|
|
1990
|
+
};
|
|
1991
|
+
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vLi4vLi4vbG9naXgtY29yZS9zcmMvaW50ZXJuYWwvc3RhdGUtdHJhaXQvYnVpbGQudHMiLCAiLi4vLi4vLi4vLi4vbG9naXgtY29yZS9zcmMvaW50ZXJuYWwvc3RhdGUtdHJhaXQvbW9kZWwudHMiLCAiLi4vLi4vLi4vLi4vbG9naXgtY29yZS9zcmMvaW50ZXJuYWwvc3RhdGUtdHJhaXQvc291cmNlLmltcGwudHMiLCAiLi4vLi4vLi4vLi4vbG9naXgtY29yZS9zcmMvaW50ZXJuYWwvc3RhdGUtdHJhaXQvZGVwcy10cmFjZS50cyIsICIuLi8uLi8uLi8uLi9sb2dpeC1jb3JlL3NyYy9pbnRlcm5hbC9zdGF0ZS10cmFpdC9jb252ZXJnZS1kaWFnbm9zdGljcy50cyJdLAogICJzb3VyY2VzQ29udGVudCI6IFsiaW1wb3J0IHR5cGUgeyBTY2hlbWEgfSBmcm9tICdlZmZlY3QnXG5pbXBvcnQgKiBhcyBTY2hlbWFBU1QgZnJvbSAnZWZmZWN0L1NjaGVtYUFTVCdcbmltcG9ydCB7XG4gIHR5cGUgU3RhdGVUcmFpdFByb2dyYW0sXG4gIHR5cGUgU3RhdGVUcmFpdFNwZWMsXG4gIHR5cGUgU3RhdGVUcmFpdEVudHJ5LFxuICB0eXBlIFN0YXRlVHJhaXRHcmFwaCxcbiAgdHlwZSBTdGF0ZVRyYWl0R3JhcGhFZGdlLFxuICB0eXBlIFN0YXRlVHJhaXRHcmFwaE5vZGUsXG4gIHR5cGUgU3RhdGVUcmFpdEZpZWxkLFxuICB0eXBlIFN0YXRlVHJhaXRGaWVsZFRyYWl0LFxuICB0eXBlIFN0YXRlVHJhaXRLaW5kLFxuICB0eXBlIFN0YXRlVHJhaXRQbGFuLFxuICB0eXBlIFN0YXRlVHJhaXRQbGFuU3RlcCxcbiAgdHlwZSBTdGF0ZVRyYWl0UmVzb3VyY2UsXG4gIHR5cGUgU3RhdGVUcmFpdFNjaGVtYVBhdGhSZWYsXG4gIGNvbGxlY3ROb2RlTWV0YSxcbiAgbm9ybWFsaXplU3BlYyxcbn0gZnJvbSAnLi9tb2RlbC5qcydcbmltcG9ydCAqIGFzIE1ldGEgZnJvbSAnLi9tZXRhLmpzJ1xuaW1wb3J0IHtcbiAgY29tcGFyZUZpZWxkUGF0aCxcbiAgZ2V0RmllbGRQYXRoSWQsXG4gIG1ha2VGaWVsZFBhdGhJZFJlZ2lzdHJ5LFxuICBub3JtYWxpemVGaWVsZFBhdGgsXG4gIHR5cGUgRmllbGRQYXRoLFxuICB0eXBlIEZpZWxkUGF0aElkLFxufSBmcm9tICcuLi9maWVsZC1wYXRoLmpzJ1xuaW1wb3J0IHsgZm52MWEzMiwgc3RhYmxlU3RyaW5naWZ5IH0gZnJvbSAnLi4vZGlnZXN0LmpzJ1xuaW1wb3J0IHR5cGUgeyBDb252ZXJnZVN0YXRpY0lyUmVnaXN0cnkgfSBmcm9tICcuL2NvbnZlcmdlLWlyLmpzJ1xuXG5jb25zdCBub3dQZXJmID0gKCk6IG51bWJlciA9PlxuICB0eXBlb2YgZ2xvYmFsVGhpcy5wZXJmb3JtYW5jZSAhPT0gJ3VuZGVmaW5lZCcgJiYgdHlwZW9mIGdsb2JhbFRoaXMucGVyZm9ybWFuY2Uubm93ID09PSAnZnVuY3Rpb24nXG4gICAgPyBnbG9iYWxUaGlzLnBlcmZvcm1hbmNlLm5vdygpXG4gICAgOiBEYXRlLm5vdygpXG5cbnR5cGUgQ29udmVyZ2VXcml0ZXIgPSBFeHRyYWN0PFN0YXRlVHJhaXRFbnRyeTxhbnksIHN0cmluZz4sIHsgcmVhZG9ubHkga2luZDogJ2NvbXB1dGVkJyB8ICdsaW5rJyB9PlxuXG5jb25zdCBjb2xsZWN0TXVsdGlwbGVXcml0ZXJzRXJyb3IgPSAoXG4gIGVudHJpZXM6IFJlYWRvbmx5QXJyYXk8U3RhdGVUcmFpdEVudHJ5PGFueSwgc3RyaW5nPj4sXG4pOiBDb252ZXJnZVN0YXRpY0lyUmVnaXN0cnlbJ2NvbmZpZ0Vycm9yJ10gfCB1bmRlZmluZWQgPT4ge1xuICBjb25zdCBraW5kc0J5RmllbGRQYXRoID0gbmV3IE1hcDxzdHJpbmcsIFNldDxTdGF0ZVRyYWl0S2luZD4+KClcblxuICBmb3IgKGNvbnN0IGVudHJ5IG9mIGVudHJpZXMpIHtcbiAgICBpZiAoZW50cnkua2luZCAhPT0gJ2NvbXB1dGVkJyAmJiBlbnRyeS5raW5kICE9PSAnbGluaycgJiYgZW50cnkua2luZCAhPT0gJ3NvdXJjZScgJiYgZW50cnkua2luZCAhPT0gJ2V4dGVybmFsU3RvcmUnKSB7XG4gICAgICBjb250aW51ZVxuICAgIH1cbiAgICBjb25zdCBzZXQgPSBraW5kc0J5RmllbGRQYXRoLmdldChlbnRyeS5maWVsZFBhdGgpID8/IG5ldyBTZXQ8U3RhdGVUcmFpdEtpbmQ+KClcbiAgICBzZXQuYWRkKGVudHJ5LmtpbmQpXG4gICAga2luZHNCeUZpZWxkUGF0aC5zZXQoZW50cnkuZmllbGRQYXRoLCBzZXQpXG4gIH1cblxuICBjb25zdCBjb25mbGljdHM6IEFycmF5PHsgcmVhZG9ubHkgZmllbGRQYXRoOiBzdHJpbmc7IHJlYWRvbmx5IGtpbmRzOiBSZWFkb25seUFycmF5PFN0YXRlVHJhaXRLaW5kPiB9PiA9IFtdXG4gIGZvciAoY29uc3QgW2ZpZWxkUGF0aCwga2luZHNdIG9mIGtpbmRzQnlGaWVsZFBhdGguZW50cmllcygpKSB7XG4gICAgaWYgKGtpbmRzLnNpemUgPD0gMSkgY29udGludWVcbiAgICBjb25mbGljdHMucHVzaCh7IGZpZWxkUGF0aCwga2luZHM6IEFycmF5LmZyb20oa2luZHMpLnNvcnQoKSB9KVxuICB9XG5cbiAgaWYgKGNvbmZsaWN0cy5sZW5ndGggPT09IDApIHJldHVybiB1bmRlZmluZWRcblxuICBjb25mbGljdHMuc29ydCgoYSwgYikgPT4gKGEuZmllbGRQYXRoIDwgYi5maWVsZFBhdGggPyAtMSA6IGEuZmllbGRQYXRoID4gYi5maWVsZFBhdGggPyAxIDogMCkpXG4gIGNvbnN0IGZpZWxkcyA9IGNvbmZsaWN0cy5tYXAoKGMpID0+IGMuZmllbGRQYXRoKVxuICBjb25zdCBwcmltYXJ5ID0gY29uZmxpY3RzWzBdIVxuICBjb25zdCBraW5kU3VtbWFyeSA9IHByaW1hcnkua2luZHMuam9pbignICsgJylcblxuICByZXR1cm4ge1xuICAgIGNvZGU6ICdNVUxUSVBMRV9XUklURVJTJyxcbiAgICBtZXNzYWdlOlxuICAgICAgYFtTdGF0ZVRyYWl0LmJ1aWxkXSBNdWx0aXBsZSB3cml0ZXJzIGZvciBmaWVsZCBcIiR7cHJpbWFyeS5maWVsZFBhdGh9XCIgKCR7a2luZFN1bW1hcnl9KS4gYCArXG4gICAgICAnT25seSBvbmUgb2YgY29tcHV0ZWQvbGluay9zb3VyY2UvZXh0ZXJuYWxTdG9yZSBjYW4gd3JpdGUgYSBmaWVsZFBhdGguJyxcbiAgICBmaWVsZHMsXG4gIH1cbn1cblxuY29uc3QgZ2V0Q29udmVyZ2VXcml0ZXJEZXBzID0gKGVudHJ5OiBDb252ZXJnZVdyaXRlcik6IFJlYWRvbmx5QXJyYXk8c3RyaW5nPiA9PiB7XG4gIGlmIChlbnRyeS5raW5kID09PSAnY29tcHV0ZWQnKSB7XG4gICAgcmV0dXJuICgoZW50cnkubWV0YSBhcyBhbnkpPy5kZXBzID8/IFtdKSBhcyBSZWFkb25seUFycmF5PHN0cmluZz5cbiAgfVxuICByZXR1cm4gW2VudHJ5Lm1ldGEuZnJvbSBhcyBzdHJpbmddXG59XG5cbmNvbnN0IGNvbXB1dGVDb252ZXJnZVRvcG9PcmRlciA9IChcbiAgd3JpdGVyczogUmVhZG9ubHlBcnJheTxDb252ZXJnZVdyaXRlcj4sXG4pOiB7IHJlYWRvbmx5IG9yZGVyOiBSZWFkb25seUFycmF5PHN0cmluZz47IHJlYWRvbmx5IGNvbmZpZ0Vycm9yPzogQ29udmVyZ2VTdGF0aWNJclJlZ2lzdHJ5Wydjb25maWdFcnJvciddIH0gPT4ge1xuICBjb25zdCB3cml0ZXJCeVBhdGggPSBuZXcgTWFwPHN0cmluZywgQ29udmVyZ2VXcml0ZXI+KClcbiAgZm9yIChjb25zdCBlbnRyeSBvZiB3cml0ZXJzKSB7XG4gICAgY29uc3QgZXhpc3RpbmcgPSB3cml0ZXJCeVBhdGguZ2V0KGVudHJ5LmZpZWxkUGF0aClcbiAgICBpZiAoZXhpc3RpbmcpIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIG9yZGVyOiBbXSxcbiAgICAgICAgY29uZmlnRXJyb3I6IHtcbiAgICAgICAgICBjb2RlOiAnTVVMVElQTEVfV1JJVEVSUycsXG4gICAgICAgICAgbWVzc2FnZTogYFtTdGF0ZVRyYWl0LmNvbnZlcmdlXSBNdWx0aXBsZSB3cml0ZXJzIGZvciBmaWVsZCBcIiR7ZW50cnkuZmllbGRQYXRofVwiICgke2V4aXN0aW5nLmtpbmR9ICsgJHtlbnRyeS5raW5kfSkuYCxcbiAgICAgICAgICBmaWVsZHM6IFtlbnRyeS5maWVsZFBhdGhdLFxuICAgICAgICB9LFxuICAgICAgfVxuICAgIH1cbiAgICB3cml0ZXJCeVBhdGguc2V0KGVudHJ5LmZpZWxkUGF0aCwgZW50cnkpXG4gIH1cblxuICBjb25zdCBub2RlcyA9IG5ldyBTZXQ8c3RyaW5nPigpXG4gIGZvciAoY29uc3QgZW50cnkgb2Ygd3JpdGVycykge1xuICAgIG5vZGVzLmFkZChlbnRyeS5maWVsZFBhdGgpXG4gIH1cblxuICBjb25zdCBpbmRlZ3JlZSA9IG5ldyBNYXA8c3RyaW5nLCBudW1iZXI+KClcbiAgY29uc3QgZm9yd2FyZCA9IG5ldyBNYXA8c3RyaW5nLCBBcnJheTxzdHJpbmc+PigpXG5cbiAgZm9yIChjb25zdCBub2RlIG9mIG5vZGVzKSB7XG4gICAgaW5kZWdyZWUuc2V0KG5vZGUsIDApXG4gICAgZm9yd2FyZC5zZXQobm9kZSwgW10pXG4gIH1cblxuICBmb3IgKGNvbnN0IGVudHJ5IG9mIHdyaXRlcnMpIHtcbiAgICBjb25zdCB0byA9IGVudHJ5LmZpZWxkUGF0aFxuICAgIGNvbnN0IGRlcHMgPSBnZXRDb252ZXJnZVdyaXRlckRlcHMoZW50cnkpXG4gICAgZm9yIChjb25zdCBkZXAgb2YgZGVwcykge1xuICAgICAgaWYgKCFub2Rlcy5oYXMoZGVwKSkgY29udGludWVcbiAgICAgIGZvcndhcmQuZ2V0KGRlcCkhLnB1c2godG8pXG4gICAgICBpbmRlZ3JlZS5zZXQodG8sIChpbmRlZ3JlZS5nZXQodG8pID8/IDApICsgMSlcbiAgICB9XG4gIH1cblxuICBjb25zdCBxdWV1ZTogQXJyYXk8c3RyaW5nPiA9IFtdXG4gIGZvciAoY29uc3QgW25vZGUsIGRlZ10gb2YgaW5kZWdyZWUuZW50cmllcygpKSB7XG4gICAgaWYgKGRlZyA9PT0gMCkgcXVldWUucHVzaChub2RlKVxuICB9XG5cbiAgY29uc3Qgb3JkZXI6IEFycmF5PHN0cmluZz4gPSBbXVxuICB3aGlsZSAocXVldWUubGVuZ3RoKSB7XG4gICAgY29uc3QgbiA9IHF1ZXVlLnNoaWZ0KCkhXG4gICAgb3JkZXIucHVzaChuKVxuICAgIGNvbnN0IG91dHMgPSBmb3J3YXJkLmdldChuKSFcbiAgICBmb3IgKGNvbnN0IHRvIG9mIG91dHMpIHtcbiAgICAgIGNvbnN0IG5leHQgPSAoaW5kZWdyZWUuZ2V0KHRvKSA/PyAwKSAtIDFcbiAgICAgIGluZGVncmVlLnNldCh0bywgbmV4dClcbiAgICAgIGlmIChuZXh0ID09PSAwKSBxdWV1ZS5wdXNoKHRvKVxuICAgIH1cbiAgfVxuXG4gIGlmIChvcmRlci5sZW5ndGggIT09IG5vZGVzLnNpemUpIHtcbiAgICBjb25zdCByZW1haW5pbmcgPSBBcnJheS5mcm9tKG5vZGVzKS5maWx0ZXIoKG4pID0+ICFvcmRlci5pbmNsdWRlcyhuKSlcbiAgICByZXR1cm4ge1xuICAgICAgb3JkZXI6IFtdLFxuICAgICAgY29uZmlnRXJyb3I6IHtcbiAgICAgICAgY29kZTogJ0NZQ0xFX0RFVEVDVEVEJyxcbiAgICAgICAgbWVzc2FnZTogYFtTdGF0ZVRyYWl0LmNvbnZlcmdlXSBDeWNsZSBkZXRlY3RlZCBpbiBjb21wdXRlZC9saW5rIGdyYXBoOiAke3JlbWFpbmluZy5qb2luKCcsICcpfWAsXG4gICAgICAgIGZpZWxkczogcmVtYWluaW5nLFxuICAgICAgfSxcbiAgICB9XG4gIH1cblxuICByZXR1cm4geyBvcmRlciB9XG59XG5cbmNvbnN0IGNvbGxlY3RTY2hlbWFGaWVsZFBhdGhzID0gKHNjaGVtYTogU2NoZW1hLlNjaGVtYTxhbnksIGFueT4pOiBSZWFkb25seUFycmF5PEZpZWxkUGF0aD4gPT4ge1xuICBjb25zdCBieUtleSA9IG5ldyBNYXA8c3RyaW5nLCBGaWVsZFBhdGg+KClcblxuICBjb25zdCBhZGQgPSAocGF0aDogRmllbGRQYXRoKTogdm9pZCA9PiB7XG4gICAgY29uc3Qgbm9ybWFsaXplZCA9IG5vcm1hbGl6ZUZpZWxkUGF0aChwYXRoKVxuICAgIGlmICghbm9ybWFsaXplZCkgcmV0dXJuXG4gICAgYnlLZXkuc2V0KEpTT04uc3RyaW5naWZ5KG5vcm1hbGl6ZWQpLCBub3JtYWxpemVkKVxuICB9XG5cbiAgY29uc3QgdmlzaXQgPSAoYXN0OiBTY2hlbWFBU1QuQVNULCBwcmVmaXg6IFJlYWRvbmx5QXJyYXk8c3RyaW5nPiwgc2VlbjogU2V0PFNjaGVtYUFTVC5BU1Q+KTogdm9pZCA9PiB7XG4gICAgbGV0IGN1cnJlbnQ6IFNjaGVtYUFTVC5BU1QgPSBhc3RcblxuICAgIC8vIFVud3JhcCBTdXNwZW5kL1JlZmluZW1lbnQgKHJlY3Vyc2l2ZSBzY2hlbWEgLyBicmFuZGVkIHNjaGVtYSkuXG4gICAgd2hpbGUgKHRydWUpIHtcbiAgICAgIGlmIChTY2hlbWFBU1QuaXNTdXNwZW5kKGN1cnJlbnQpKSB7XG4gICAgICAgIGlmIChzZWVuLmhhcyhjdXJyZW50KSkgcmV0dXJuXG4gICAgICAgIHNlZW4uYWRkKGN1cnJlbnQpXG4gICAgICAgIGN1cnJlbnQgPSBjdXJyZW50LmYoKVxuICAgICAgICBjb250aW51ZVxuICAgICAgfVxuICAgICAgaWYgKFNjaGVtYUFTVC5pc1JlZmluZW1lbnQoY3VycmVudCkpIHtcbiAgICAgICAgY3VycmVudCA9IGN1cnJlbnQuZnJvbVxuICAgICAgICBjb250aW51ZVxuICAgICAgfVxuICAgICAgYnJlYWtcbiAgICB9XG5cbiAgICBpZiAoU2NoZW1hQVNULmlzVHJhbnNmb3JtYXRpb24oY3VycmVudCkpIHtcbiAgICAgIHZpc2l0KGN1cnJlbnQudG8sIHByZWZpeCwgc2VlbilcbiAgICAgIHZpc2l0KGN1cnJlbnQuZnJvbSwgcHJlZml4LCBzZWVuKVxuICAgICAgcmV0dXJuXG4gICAgfVxuXG4gICAgaWYgKFNjaGVtYUFTVC5pc1VuaW9uKGN1cnJlbnQpKSB7XG4gICAgICBmb3IgKGNvbnN0IHQgb2YgY3VycmVudC50eXBlcykge1xuICAgICAgICB2aXNpdCh0LCBwcmVmaXgsIHNlZW4pXG4gICAgICB9XG4gICAgICByZXR1cm5cbiAgICB9XG5cbiAgICAvLyBBcnJheSAvIFR1cGxlOiBpbmRpY2VzIGRvIG5vdCBlbnRlciB0aGUgRmllbGRQYXRoSWQgc3BhY2U7IHJlY3Vyc2UgaW50byBlbGVtZW50IHR5cGVzIHRvIHN1cHBvcnQgYGl0ZW1zWzBdLm5hbWUgLT4gaXRlbXMubmFtZWAuXG4gICAgaWYgKFNjaGVtYUFTVC5pc1R1cGxlVHlwZShjdXJyZW50KSkge1xuICAgICAgZm9yIChjb25zdCBlIG9mIGN1cnJlbnQuZWxlbWVudHMpIHtcbiAgICAgICAgdmlzaXQoZS50eXBlLCBwcmVmaXgsIHNlZW4pXG4gICAgICB9XG4gICAgICBmb3IgKGNvbnN0IHIgb2YgY3VycmVudC5yZXN0KSB7XG4gICAgICAgIHZpc2l0KHIudHlwZSwgcHJlZml4LCBzZWVuKVxuICAgICAgfVxuICAgICAgcmV0dXJuXG4gICAgfVxuXG4gICAgaWYgKFNjaGVtYUFTVC5pc1R5cGVMaXRlcmFsKGN1cnJlbnQpKSB7XG4gICAgICBmb3IgKGNvbnN0IHBzIG9mIGN1cnJlbnQucHJvcGVydHlTaWduYXR1cmVzKSB7XG4gICAgICAgIGNvbnN0IHNlZyA9IFN0cmluZyhwcy5uYW1lKVxuICAgICAgICBpZiAoIXNlZykgY29udGludWVcbiAgICAgICAgY29uc3QgbmV4dCA9IFsuLi5wcmVmaXgsIHNlZ11cbiAgICAgICAgYWRkKG5leHQpXG4gICAgICAgIHZpc2l0KHBzLnR5cGUsIG5leHQsIHNlZW4pXG4gICAgICB9XG4gICAgICAvLyBJbmRleCBzaWduYXR1cmUgKFJlY29yZDxzdHJpbmcsIFQ+KSBjYW4ndCBiZSBlbnVtZXJhdGVkIHN0YXRpY2FsbHk6IGF2b2lkIGdlbmVyYXRpbmcgbWlzYWxpZ25lZCBkeW5hbWljIGtleSBwYXRocy5cbiAgICAgIHJldHVyblxuICAgIH1cblxuICAgIC8vIEFueSAvIFVua25vd24gLyBPYmplY3QgLyBEZWNsYXJhdGlvbiAob3BlbiB0eXBlcyk6IGNhbm5vdCBlbnVtZXJhdGUgbmVzdGVkIHBhdGhzOyBzdG9wIGNvbnNlcnZhdGl2ZWx5LlxuICB9XG5cbiAgdmlzaXQoc2NoZW1hLmFzdCBhcyB1bmtub3duIGFzIFNjaGVtYUFTVC5BU1QsIFtdLCBuZXcgU2V0KCkpXG4gIHJldHVybiBBcnJheS5mcm9tKGJ5S2V5LnZhbHVlcygpKS5zb3J0KGNvbXBhcmVGaWVsZFBhdGgpXG59XG5cbmNvbnN0IGJ1aWxkQ29udmVyZ2VJciA9IChcbiAgc3RhdGVTY2hlbWE6IFNjaGVtYS5TY2hlbWE8YW55LCBhbnk+LFxuICBlbnRyaWVzOiBSZWFkb25seUFycmF5PFN0YXRlVHJhaXRFbnRyeTxhbnksIHN0cmluZz4+LFxuKTogQ29udmVyZ2VTdGF0aWNJclJlZ2lzdHJ5ID0+IHtcbiAgY29uc3Qgc3RhcnRlZEF0ID0gbm93UGVyZigpXG4gIGNvbnN0IGdlbmVyYXRpb24gPSAwXG5cbiAgY29uc3QgbXVsdGlwbGVXcml0ZXJzRXJyb3IgPSBjb2xsZWN0TXVsdGlwbGVXcml0ZXJzRXJyb3IoZW50cmllcylcblxuICBjb25zdCB3cml0ZXJzID0gZW50cmllcy5maWx0ZXIoKGUpOiBlIGlzIENvbnZlcmdlV3JpdGVyID0+IGUua2luZCA9PT0gJ2NvbXB1dGVkJyB8fCBlLmtpbmQgPT09ICdsaW5rJylcblxuICBjb25zdCB3cml0ZXJzS2V5ID0gd3JpdGVyc1xuICAgIC5tYXAoKGVudHJ5KSA9PiBgJHtlbnRyeS5raW5kfToke2VudHJ5LmZpZWxkUGF0aH1gKVxuICAgIC5zb3J0KClcbiAgICAuam9pbignfCcpXG5cbiAgY29uc3QgZGVwc0tleSA9IHdyaXRlcnNcbiAgICAubWFwKChlbnRyeSkgPT4ge1xuICAgICAgY29uc3QgZGVwcyA9IGdldENvbnZlcmdlV3JpdGVyRGVwcyhlbnRyeSkuc2xpY2UoKS5zb3J0KCkuam9pbignLCcpXG4gICAgICBjb25zdCBzY2hlZHVsaW5nID0gKGVudHJ5Lm1ldGEgYXMgYW55KT8uc2NoZWR1bGluZyA9PT0gJ2RlZmVycmVkJyA/ICdkJyA6ICdpJ1xuICAgICAgcmV0dXJuIGAke2VudHJ5LmtpbmR9OiR7ZW50cnkuZmllbGRQYXRofUAke3NjaGVkdWxpbmd9PT4ke2RlcHN9YFxuICAgIH0pXG4gICAgLnNvcnQoKVxuICAgIC5qb2luKCd8JylcblxuICBjb25zdCB3cml0ZXJCeVBhdGggPSBuZXcgTWFwPHN0cmluZywgQ29udmVyZ2VXcml0ZXI+KClcbiAgZm9yIChjb25zdCBlbnRyeSBvZiB3cml0ZXJzKSB7XG4gICAgd3JpdGVyQnlQYXRoLnNldChlbnRyeS5maWVsZFBhdGgsIGVudHJ5KVxuICB9XG5cbiAgY29uc3QgdG9wbyA9IG11bHRpcGxlV3JpdGVyc0Vycm9yXG4gICAgPyB7IG9yZGVyOiBbXSBhcyBSZWFkb25seUFycmF5PHN0cmluZz4gfVxuICAgIDogd3JpdGVycy5sZW5ndGggPiAwXG4gICAgICA/IGNvbXB1dGVDb252ZXJnZVRvcG9PcmRlcih3cml0ZXJzKVxuICAgICAgOiB7IG9yZGVyOiBbXSBhcyBSZWFkb25seUFycmF5PHN0cmluZz4gfVxuICBjb25zdCBzdGVwc0J5SWQ6IEFycmF5PENvbnZlcmdlV3JpdGVyPiA9IHRvcG8uY29uZmlnRXJyb3IgPyBbXSA6IHRvcG8ub3JkZXIubWFwKChwYXRoKSA9PiB3cml0ZXJCeVBhdGguZ2V0KHBhdGgpISlcblxuICBjb25zdCBmaWVsZFBhdGhUYWJsZSA9IG5ldyBNYXA8c3RyaW5nLCBGaWVsZFBhdGg+KClcbiAgY29uc3QgYWRkUGF0aCA9IChwYXRoOiBGaWVsZFBhdGgpOiB2b2lkID0+IHtcbiAgICBmb3IgKGxldCBpID0gMTsgaSA8PSBwYXRoLmxlbmd0aDsgaSsrKSB7XG4gICAgICBjb25zdCBwcmVmaXggPSBwYXRoLnNsaWNlKDAsIGkpXG4gICAgICBjb25zdCBrZXkgPSBKU09OLnN0cmluZ2lmeShwcmVmaXgpXG4gICAgICBpZiAoIWZpZWxkUGF0aFRhYmxlLmhhcyhrZXkpKSBmaWVsZFBhdGhUYWJsZS5zZXQoa2V5LCBwcmVmaXgpXG4gICAgfVxuICB9XG5cbiAgLy8gMDY1OiBGaWVsZFBhdGhJZCBzZW1hbnRpY3MgbXVzdCBjb3ZlciBhbGwgZW51bWVyYWJsZSBmaWVsZCBwYXRocyBvZiBzdGF0ZVNjaGVtYTsgb3RoZXJ3aXNlIHJlZHVjZXIgcGF0Y2hQYXRocyBjYW4ndCBtYXAgYW5kIHdpbGwgZmFsbCBiYWNrIHRvIGRpcnR5QWxsLlxuICBmb3IgKGNvbnN0IHNjaGVtYVBhdGggb2YgY29sbGVjdFNjaGVtYUZpZWxkUGF0aHMoc3RhdGVTY2hlbWEpKSB7XG4gICAgYWRkUGF0aChzY2hlbWFQYXRoKVxuICB9XG5cbiAgZm9yIChjb25zdCBlbnRyeSBvZiB3cml0ZXJzKSB7XG4gICAgY29uc3Qgb3V0ID0gbm9ybWFsaXplRmllbGRQYXRoKGVudHJ5LmZpZWxkUGF0aClcbiAgICBpZiAob3V0KSBhZGRQYXRoKG91dClcbiAgICBmb3IgKGNvbnN0IGRlcCBvZiBnZXRDb252ZXJnZVdyaXRlckRlcHMoZW50cnkpKSB7XG4gICAgICBjb25zdCBkZXBQYXRoID0gbm9ybWFsaXplRmllbGRQYXRoKGRlcClcbiAgICAgIGlmIChkZXBQYXRoKSBhZGRQYXRoKGRlcFBhdGgpXG4gICAgfVxuICB9XG5cbiAgY29uc3QgZmllbGRQYXRocyA9IEFycmF5LmZyb20oZmllbGRQYXRoVGFibGUudmFsdWVzKCkpLnNvcnQoY29tcGFyZUZpZWxkUGF0aClcbiAgY29uc3QgZmllbGRQYXRoSWRSZWdpc3RyeSA9IG1ha2VGaWVsZFBhdGhJZFJlZ2lzdHJ5KGZpZWxkUGF0aHMpXG4gIGNvbnN0IGZpZWxkUGF0aHNLZXkgPSBmbnYxYTMyKHN0YWJsZVN0cmluZ2lmeShmaWVsZFBhdGhzKSlcblxuICBjb25zdCBzdGVwT3V0RmllbGRQYXRoSWRCeVN0ZXBJZDogQXJyYXk8RmllbGRQYXRoSWQ+ID0gW11cbiAgY29uc3Qgc3RlcERlcHNGaWVsZFBhdGhJZHNCeVN0ZXBJZDogQXJyYXk8UmVhZG9ubHlBcnJheTxGaWVsZFBhdGhJZD4+ID0gW11cbiAgY29uc3Qgc3RlcFNjaGVkdWxpbmdCeVN0ZXBJZDogQXJyYXk8J2ltbWVkaWF0ZScgfCAnZGVmZXJyZWQnPiA9IFtdXG5cbiAgZm9yIChjb25zdCBlbnRyeSBvZiBzdGVwc0J5SWQpIHtcbiAgICBjb25zdCBvdXQgPSBub3JtYWxpemVGaWVsZFBhdGgoZW50cnkuZmllbGRQYXRoKVxuICAgIGNvbnN0IG91dElkID0gb3V0ICE9IG51bGwgPyBnZXRGaWVsZFBhdGhJZChmaWVsZFBhdGhJZFJlZ2lzdHJ5LCBvdXQpIDogdW5kZWZpbmVkXG4gICAgaWYgKG91dElkID09IG51bGwpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgW1N0YXRlVHJhaXQuYnVpbGRdIEZhaWxlZCB0byBtYXAgY29udmVyZ2Ugb3V0cHV0IGZpZWxkUGF0aCBcIiR7ZW50cnkuZmllbGRQYXRofVwiIHRvIEZpZWxkUGF0aElkLmApXG4gICAgfVxuXG4gICAgY29uc3QgZGVwSWRzOiBBcnJheTxGaWVsZFBhdGhJZD4gPSBbXVxuICAgIGZvciAoY29uc3QgZGVwIG9mIGdldENvbnZlcmdlV3JpdGVyRGVwcyhlbnRyeSkpIHtcbiAgICAgIGNvbnN0IGRlcFBhdGggPSBub3JtYWxpemVGaWVsZFBhdGgoZGVwKVxuICAgICAgaWYgKCFkZXBQYXRoKSBjb250aW51ZVxuICAgICAgY29uc3QgZGVwSWQgPSBnZXRGaWVsZFBhdGhJZChmaWVsZFBhdGhJZFJlZ2lzdHJ5LCBkZXBQYXRoKVxuICAgICAgaWYgKGRlcElkICE9IG51bGwpIGRlcElkcy5wdXNoKGRlcElkKVxuICAgIH1cblxuICAgIHN0ZXBPdXRGaWVsZFBhdGhJZEJ5U3RlcElkLnB1c2gob3V0SWQpXG4gICAgc3RlcERlcHNGaWVsZFBhdGhJZHNCeVN0ZXBJZC5wdXNoKGRlcElkcylcbiAgICBzdGVwU2NoZWR1bGluZ0J5U3RlcElkLnB1c2goKGVudHJ5Lm1ldGEgYXMgYW55KT8uc2NoZWR1bGluZyA9PT0gJ2RlZmVycmVkJyA/ICdkZWZlcnJlZCcgOiAnaW1tZWRpYXRlJylcbiAgfVxuXG4gIGNvbnN0IHRvcG9PcmRlciA9IHN0ZXBzQnlJZC5tYXAoKF8sIGkpID0+IGkpXG4gIGNvbnN0IGJ1aWxkRHVyYXRpb25NcyA9IE1hdGgubWF4KDAsIG5vd1BlcmYoKSAtIHN0YXJ0ZWRBdClcblxuICByZXR1cm4ge1xuICAgIGdlbmVyYXRpb24sXG4gICAgd3JpdGVyc0tleSxcbiAgICBkZXBzS2V5LFxuICAgIGZpZWxkUGF0aHNLZXksXG4gICAgZmllbGRQYXRocyxcbiAgICBmaWVsZFBhdGhJZFJlZ2lzdHJ5LFxuICAgIC4uLihtdWx0aXBsZVdyaXRlcnNFcnJvciA/IHsgY29uZmlnRXJyb3I6IG11bHRpcGxlV3JpdGVyc0Vycm9yIH0gOiB0b3BvLmNvbmZpZ0Vycm9yID8geyBjb25maWdFcnJvcjogdG9wby5jb25maWdFcnJvciB9IDogbnVsbCksXG4gICAgc3RlcHNCeUlkLFxuICAgIHN0ZXBPdXRGaWVsZFBhdGhJZEJ5U3RlcElkLFxuICAgIHN0ZXBEZXBzRmllbGRQYXRoSWRzQnlTdGVwSWQsXG4gICAgc3RlcFNjaGVkdWxpbmdCeVN0ZXBJZCxcbiAgICB0b3BvT3JkZXIsXG4gICAgYnVpbGREdXJhdGlvbk1zLFxuICB9XG59XG5cbi8qKlxuICogQnVpbGRzIGEgbm9ybWFsaXplZCBGaWVsZFRyYWl0IGZyb20gYSBTdGF0ZVRyYWl0RW50cnkuXG4gKlxuICogLSBDdXJyZW50bHkgdXNlcyBleHBsaWNpdCBkZXBzIGZvciBjb21wdXRlZC9zb3VyY2UgYW5kIGxpbmsgZWRnZXM7IGRlZXBlciBkZXBlbmRlbmN5IGFuYWx5c2lzIGlzIGludGVudGlvbmFsbHkgbm90IHBlcmZvcm1lZC5cbiAqIC0gSWYgd2UgZXZvbHZlIGV4cGxpY2l0IGRlcGVuZGVuY3kgZGVjbGFyYXRpb25zIGZ1cnRoZXIsIGV4dGVuZCBoZXJlLlxuICovXG5jb25zdCB0b0ZpZWxkVHJhaXQgPSAoZW50cnk6IFN0YXRlVHJhaXRFbnRyeTxhbnksIHN0cmluZz4pOiBTdGF0ZVRyYWl0RmllbGRUcmFpdCA9PiB7XG4gIGNvbnN0IGRlcHM6IEFycmF5PHN0cmluZz4gPSBbXVxuXG4gIGlmIChlbnRyeS5raW5kID09PSAnY29tcHV0ZWQnKSB7XG4gICAgY29uc3QgbWV0YSA9IGVudHJ5Lm1ldGEgYXMgYW55XG4gICAgY29uc3QgbGlzdCA9IG1ldGEuZGVwcyBhcyBSZWFkb25seUFycmF5PHN0cmluZz4gfCB1bmRlZmluZWRcbiAgICBpZiAobGlzdCkgZGVwcy5wdXNoKC4uLmxpc3QpXG4gIH0gZWxzZSBpZiAoZW50cnkua2luZCA9PT0gJ3NvdXJjZScpIHtcbiAgICBjb25zdCBtZXRhID0gZW50cnkubWV0YSBhcyBhbnlcbiAgICBjb25zdCBsaXN0ID0gbWV0YS5kZXBzIGFzIFJlYWRvbmx5QXJyYXk8c3RyaW5nPiB8IHVuZGVmaW5lZFxuICAgIGlmIChsaXN0KSBkZXBzLnB1c2goLi4ubGlzdClcbiAgfSBlbHNlIGlmIChlbnRyeS5raW5kID09PSAnbGluaycpIHtcbiAgICBkZXBzLnB1c2goZW50cnkubWV0YS5mcm9tIGFzIHN0cmluZylcbiAgfSBlbHNlIGlmIChlbnRyeS5raW5kID09PSAnY2hlY2snKSB7XG4gICAgY29uc3QgbWV0YSA9IGVudHJ5Lm1ldGEgYXMgYW55XG4gICAgY29uc3QgcnVsZXMgPSAobWV0YT8ucnVsZXMgPz8ge30pIGFzIFJlY29yZDxzdHJpbmcsIGFueT5cbiAgICBmb3IgKGNvbnN0IG5hbWUgb2YgT2JqZWN0LmtleXMocnVsZXMpKSB7XG4gICAgICBjb25zdCBydWxlID0gcnVsZXNbbmFtZV1cbiAgICAgIGlmIChydWxlICYmIHR5cGVvZiBydWxlID09PSAnb2JqZWN0Jykge1xuICAgICAgICBjb25zdCBsaXN0ID0gcnVsZS5kZXBzIGFzIFJlYWRvbmx5QXJyYXk8c3RyaW5nPiB8IHVuZGVmaW5lZFxuICAgICAgICBpZiAobGlzdCkgZGVwcy5wdXNoKC4uLmxpc3QpXG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHtcbiAgICBmaWVsZElkOiBlbnRyeS5maWVsZFBhdGgsXG4gICAga2luZDogZW50cnkua2luZCxcbiAgICAvLyBLZWVwIG1ldGEgaWRlbnRpY2FsIHRvIEVudHJ5Lm1ldGEgYXQgcnVudGltZSBzbyBpbnN0YWxsIGNhbiByZXVzZSBpdCBkaXJlY3RseS5cbiAgICBtZXRhOiBlbnRyeS5tZXRhIGFzIGFueSxcbiAgICBkZXBzLFxuICB9XG59XG5cbi8qKlxuICogQnVpbGRzIEZpZWxkIC8gTm9kZSAvIEVkZ2UgLyBSZXNvdXJjZSBzZXRzIGZyb20gbm9ybWFsaXplZCBlbnRyaWVzLlxuICovXG5jb25zdCBidWlsZEdyYXBoID0gKFxuICBlbnRyaWVzOiBSZWFkb25seUFycmF5PFN0YXRlVHJhaXRFbnRyeTxhbnksIHN0cmluZz4+LFxuICBub2RlTWV0YUJ5RmllbGRQYXRoOiBSZWFkb25seU1hcDxzdHJpbmcsIE1ldGEuVHJhaXRNZXRhPixcbik6IHtcbiAgcmVhZG9ubHkgZ3JhcGg6IFN0YXRlVHJhaXRHcmFwaFxuICByZWFkb25seSBwbGFuOiBTdGF0ZVRyYWl0UGxhblxufSA9PiB7XG4gIGNvbnN0IGZpZWxkTWFwID0gbmV3IE1hcDxzdHJpbmcsIFN0YXRlVHJhaXRGaWVsZD4oKVxuICBjb25zdCBub2RlczogQXJyYXk8U3RhdGVUcmFpdEdyYXBoTm9kZT4gPSBbXVxuICBjb25zdCBlZGdlczogQXJyYXk8U3RhdGVUcmFpdEdyYXBoRWRnZT4gPSBbXVxuICBjb25zdCByZXNvdXJjZXNCeUlkID0gbmV3IE1hcDxzdHJpbmcsIFN0YXRlVHJhaXRSZXNvdXJjZT4oKVxuICBjb25zdCBwbGFuU3RlcHM6IEFycmF5PFN0YXRlVHJhaXRQbGFuU3RlcD4gPSBbXVxuXG4gIGNvbnN0IGVuc3VyZUZpZWxkID0gKGZpZWxkUGF0aDogc3RyaW5nKTogU3RhdGVUcmFpdEZpZWxkID0+IHtcbiAgICBsZXQgZmllbGQgPSBmaWVsZE1hcC5nZXQoZmllbGRQYXRoKVxuICAgIGlmICghZmllbGQpIHtcbiAgICAgIGZpZWxkID0ge1xuICAgICAgICBpZDogZmllbGRQYXRoLFxuICAgICAgICBwYXRoOiBmaWVsZFBhdGgsXG4gICAgICAgIHRyYWl0czogW10sXG4gICAgICB9XG4gICAgICBmaWVsZE1hcC5zZXQoZmllbGRQYXRoLCBmaWVsZClcbiAgICB9XG4gICAgcmV0dXJuIGZpZWxkXG4gIH1cblxuICBmb3IgKGNvbnN0IGVudHJ5IG9mIGVudHJpZXMpIHtcbiAgICBjb25zdCBmaWVsZFBhdGggPSBlbnRyeS5maWVsZFBhdGhcbiAgICBjb25zdCBmaWVsZCA9IGVuc3VyZUZpZWxkKGZpZWxkUGF0aClcbiAgICBjb25zdCB0cmFpdCA9IHRvRmllbGRUcmFpdChlbnRyeSlcblxuICAgIDsoZmllbGQudHJhaXRzIGFzIEFycmF5PFN0YXRlVHJhaXRGaWVsZFRyYWl0PikucHVzaCh0cmFpdClcblxuICAgIC8vIEJ1aWxkIEdyYXBoIGVkZ2VzIGFuZCBQbGFuIHN0ZXBzIGJ5IGtpbmQuXG4gICAgaWYgKGVudHJ5LmtpbmQgPT09ICdjb21wdXRlZCcpIHtcbiAgICAgIGNvbnN0IHN0ZXBJZCA9IGBjb21wdXRlZDoke2ZpZWxkUGF0aH1gXG4gICAgICBwbGFuU3RlcHMucHVzaCh7XG4gICAgICAgIGlkOiBzdGVwSWQsXG4gICAgICAgIGtpbmQ6ICdjb21wdXRlZC11cGRhdGUnLFxuICAgICAgICB0YXJnZXRGaWVsZFBhdGg6IGZpZWxkUGF0aCxcbiAgICAgICAgLy8gTm90ZTogdGhlIGN1cnJlbnQgdmVyc2lvbiBkb2VzIG5vdCBzdGF0aWNhbGx5IGFuYWx5emUgY29tcHV0ZWQgZGVwZW5kZW5jaWVzOyBzb3VyY2VGaWVsZFBhdGhzIHJlbWFpbnMgZW1wdHkuXG4gICAgICB9KVxuICAgICAgLy8gSWYgZGVwcyBpcyBleHBsaWNpdGx5IGRlY2xhcmVkLCBhZGQgR3JhcGggZWRnZXMgKGZvciBkaWFnbm9zdGljcyAvIHJldmVyc2UtY2xvc3VyZSBjb21wdXRhdGlvbikuXG4gICAgICBjb25zdCBkZXBzID0gKGVudHJ5Lm1ldGEgYXMgYW55KS5kZXBzIGFzIFJlYWRvbmx5QXJyYXk8c3RyaW5nPiB8IHVuZGVmaW5lZFxuICAgICAgaWYgKGRlcHMpIHtcbiAgICAgICAgZm9yIChjb25zdCBkZXAgb2YgZGVwcykge1xuICAgICAgICAgIGVuc3VyZUZpZWxkKGRlcClcbiAgICAgICAgICBlZGdlcy5wdXNoKHtcbiAgICAgICAgICAgIGlkOiBgY29tcHV0ZWQ6JHtkZXB9LT4ke2ZpZWxkUGF0aH1gLFxuICAgICAgICAgICAgZnJvbTogZGVwLFxuICAgICAgICAgICAgdG86IGZpZWxkUGF0aCxcbiAgICAgICAgICAgIGtpbmQ6ICdjb21wdXRlZCcsXG4gICAgICAgICAgfSlcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0gZWxzZSBpZiAoZW50cnkua2luZCA9PT0gJ2xpbmsnKSB7XG4gICAgICBjb25zdCBmcm9tID0gZW50cnkubWV0YS5mcm9tIGFzIHN0cmluZ1xuICAgICAgZW5zdXJlRmllbGQoZnJvbSlcblxuICAgICAgY29uc3QgZWRnZUlkID0gYGxpbms6JHtmcm9tfS0+JHtmaWVsZFBhdGh9YFxuICAgICAgZWRnZXMucHVzaCh7XG4gICAgICAgIGlkOiBlZGdlSWQsXG4gICAgICAgIGZyb20sXG4gICAgICAgIHRvOiBmaWVsZFBhdGgsXG4gICAgICAgIGtpbmQ6ICdsaW5rJyxcbiAgICAgIH0pXG5cbiAgICAgIHBsYW5TdGVwcy5wdXNoKHtcbiAgICAgICAgaWQ6IGBsaW5rOiR7ZmllbGRQYXRofWAsXG4gICAgICAgIGtpbmQ6ICdsaW5rLXByb3BhZ2F0ZScsXG4gICAgICAgIHRhcmdldEZpZWxkUGF0aDogZmllbGRQYXRoLFxuICAgICAgICBzb3VyY2VGaWVsZFBhdGhzOiBbZnJvbV0sXG4gICAgICAgIGRlYnVnSW5mbzoge1xuICAgICAgICAgIGdyYXBoRWRnZUlkOiBlZGdlSWQsXG4gICAgICAgIH0sXG4gICAgICB9KVxuICAgIH0gZWxzZSBpZiAoZW50cnkua2luZCA9PT0gJ3NvdXJjZScpIHtcbiAgICAgIGNvbnN0IHJlc291cmNlSWQgPSBlbnRyeS5tZXRhLnJlc291cmNlXG4gICAgICBjb25zdCByZXNvdXJjZU1ldGEgPSBNZXRhLnNhbml0aXplKChlbnRyeS5tZXRhIGFzIGFueSkubWV0YSlcblxuICAgICAgY29uc3QgZXhpc3RpbmcgPSByZXNvdXJjZXNCeUlkLmdldChyZXNvdXJjZUlkKVxuICAgICAgaWYgKGV4aXN0aW5nKSB7XG4gICAgICAgIGNvbnN0IG93bmVyRmllbGRzID0gWy4uLmV4aXN0aW5nLm93bmVyRmllbGRzLCBmaWVsZFBhdGhdXG4gICAgICAgIGxldCBtZXRhID0gZXhpc3RpbmcubWV0YVxuICAgICAgICBsZXQgbWV0YU9yaWdpbiA9IGV4aXN0aW5nLm1ldGFPcmlnaW5cbiAgICAgICAgbGV0IG1ldGFDb25mbGljdHMgPSBleGlzdGluZy5tZXRhQ29uZmxpY3RzXG5cbiAgICAgICAgaWYgKHJlc291cmNlTWV0YSkge1xuICAgICAgICAgIGNvbnN0IG1lcmdlZCA9IE1ldGEubWVyZ2VDYW5vbmljYWwoXG4gICAgICAgICAgICB7IG1ldGEsIG9yaWdpbjogbWV0YU9yaWdpbiwgY29uZmxpY3RzOiBtZXRhQ29uZmxpY3RzIH0sXG4gICAgICAgICAgICB7IG9yaWdpbjogZmllbGRQYXRoLCBtZXRhOiByZXNvdXJjZU1ldGEgfSxcbiAgICAgICAgICApXG4gICAgICAgICAgbWV0YSA9IG1lcmdlZC5tZXRhXG4gICAgICAgICAgbWV0YU9yaWdpbiA9IG1lcmdlZC5vcmlnaW5cbiAgICAgICAgICBtZXRhQ29uZmxpY3RzID0gbWVyZ2VkLmNvbmZsaWN0c1xuICAgICAgICB9XG5cbiAgICAgICAgcmVzb3VyY2VzQnlJZC5zZXQocmVzb3VyY2VJZCwge1xuICAgICAgICAgIC4uLmV4aXN0aW5nLFxuICAgICAgICAgIG93bmVyRmllbGRzLFxuICAgICAgICAgIG1ldGEsXG4gICAgICAgICAgbWV0YU9yaWdpbixcbiAgICAgICAgICBtZXRhQ29uZmxpY3RzLFxuICAgICAgICB9KVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmVzb3VyY2VzQnlJZC5zZXQocmVzb3VyY2VJZCwge1xuICAgICAgICAgIHJlc291cmNlSWQsXG4gICAgICAgICAgLy8gVXNlIGEgc2ltcGxlIGlkZW50aWZpZXIgc3RyaW5nIGZvciBub3c7IG1heSBldm9sdmUgaW50byBhIHN0cnVjdHVyZWQgZm9ybSBiYXNlZCBvbiBrZXkgcnVsZXMuXG4gICAgICAgICAga2V5U2VsZWN0b3I6IGBTdGF0ZVRyYWl0LnNvdXJjZUAke2ZpZWxkUGF0aH1gLFxuICAgICAgICAgIG93bmVyRmllbGRzOiBbZmllbGRQYXRoXSxcbiAgICAgICAgICBtZXRhOiByZXNvdXJjZU1ldGEsXG4gICAgICAgICAgbWV0YU9yaWdpbjogcmVzb3VyY2VNZXRhID8gZmllbGRQYXRoIDogdW5kZWZpbmVkLFxuICAgICAgICB9KVxuICAgICAgfVxuXG4gICAgICBwbGFuU3RlcHMucHVzaCh7XG4gICAgICAgIGlkOiBgc291cmNlOiR7ZmllbGRQYXRofWAsXG4gICAgICAgIGtpbmQ6ICdzb3VyY2UtcmVmcmVzaCcsXG4gICAgICAgIHRhcmdldEZpZWxkUGF0aDogZmllbGRQYXRoLFxuICAgICAgICByZXNvdXJjZUlkLFxuICAgICAgICBrZXlTZWxlY3RvcklkOiBgU3RhdGVUcmFpdC5zb3VyY2VAJHtmaWVsZFBhdGh9YCxcbiAgICAgIH0pXG5cbiAgICAgIGNvbnN0IGRlcHMgPSAoZW50cnkubWV0YSBhcyBhbnkpLmRlcHMgYXMgUmVhZG9ubHlBcnJheTxzdHJpbmc+IHwgdW5kZWZpbmVkXG4gICAgICBpZiAoZGVwcykge1xuICAgICAgICBmb3IgKGNvbnN0IGRlcCBvZiBkZXBzKSB7XG4gICAgICAgICAgZW5zdXJlRmllbGQoZGVwKVxuICAgICAgICAgIGVkZ2VzLnB1c2goe1xuICAgICAgICAgICAgaWQ6IGBzb3VyY2UtZGVwOiR7ZGVwfS0+JHtmaWVsZFBhdGh9YCxcbiAgICAgICAgICAgIGZyb206IGRlcCxcbiAgICAgICAgICAgIHRvOiBmaWVsZFBhdGgsXG4gICAgICAgICAgICBraW5kOiAnc291cmNlLWRlcCcsXG4gICAgICAgICAgfSlcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0gZWxzZSBpZiAoZW50cnkua2luZCA9PT0gJ2V4dGVybmFsU3RvcmUnKSB7XG4gICAgICBwbGFuU3RlcHMucHVzaCh7XG4gICAgICAgIGlkOiBgZXh0ZXJuYWwtc3RvcmU6JHtmaWVsZFBhdGh9YCxcbiAgICAgICAga2luZDogJ2V4dGVybmFsLXN0b3JlLXN5bmMnLFxuICAgICAgICB0YXJnZXRGaWVsZFBhdGg6IGZpZWxkUGF0aCxcbiAgICAgIH0pXG4gICAgfSBlbHNlIGlmIChlbnRyeS5raW5kID09PSAnY2hlY2snKSB7XG4gICAgICBwbGFuU3RlcHMucHVzaCh7XG4gICAgICAgIGlkOiBgY2hlY2s6JHtmaWVsZFBhdGh9YCxcbiAgICAgICAga2luZDogJ2NoZWNrLXZhbGlkYXRlJyxcbiAgICAgICAgdGFyZ2V0RmllbGRQYXRoOiBmaWVsZFBhdGgsXG4gICAgICB9KVxuXG4gICAgICAvLyBJZiB0aGUgcnVsZSBleHBsaWNpdGx5IGRlY2xhcmVzIGRlcHMsIGFkZCBHcmFwaCBlZGdlcyAoZm9yIFJldmVyc2VDbG9zdXJlIHNjb3BlZCB2YWxpZGF0ZSkuXG4gICAgICBpZiAodHJhaXQuZGVwcy5sZW5ndGggPiAwKSB7XG4gICAgICAgIGZvciAoY29uc3QgZGVwIG9mIHRyYWl0LmRlcHMpIHtcbiAgICAgICAgICBlbnN1cmVGaWVsZChkZXApXG4gICAgICAgICAgZWRnZXMucHVzaCh7XG4gICAgICAgICAgICBpZDogYGNoZWNrLWRlcDoke2RlcH0tPiR7ZmllbGRQYXRofWAsXG4gICAgICAgICAgICBmcm9tOiBkZXAsXG4gICAgICAgICAgICB0bzogZmllbGRQYXRoLFxuICAgICAgICAgICAga2luZDogJ2NoZWNrLWRlcCcsXG4gICAgICAgICAgfSlcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIGZvciAoY29uc3QgZmllbGQgb2YgZmllbGRNYXAudmFsdWVzKCkpIHtcbiAgICBub2Rlcy5wdXNoKHtcbiAgICAgIGlkOiBmaWVsZC5pZCxcbiAgICAgIGZpZWxkLFxuICAgICAgdHJhaXRzOiBmaWVsZC50cmFpdHMsXG4gICAgICBtZXRhOiBub2RlTWV0YUJ5RmllbGRQYXRoLmdldChmaWVsZC5pZCksXG4gICAgfSlcbiAgfVxuXG4gIGNvbnN0IGdyYXBoOiBTdGF0ZVRyYWl0R3JhcGggPSB7XG4gICAgX3RhZzogJ1N0YXRlVHJhaXRHcmFwaCcsXG4gICAgbm9kZXMsXG4gICAgZWRnZXMsXG4gICAgcmVzb3VyY2VzOiBBcnJheS5mcm9tKHJlc291cmNlc0J5SWQudmFsdWVzKCkpLFxuICB9XG5cbiAgY29uc3QgcGxhbjogU3RhdGVUcmFpdFBsYW4gPSB7XG4gICAgX3RhZzogJ1N0YXRlVHJhaXRQbGFuJyxcbiAgICBzdGVwczogcGxhblN0ZXBzLFxuICB9XG5cbiAgcmV0dXJuIHsgZ3JhcGgsIHBsYW4gfVxufVxuXG4vKipcbiAqIFBlcmZvcm1zIGEgc2ltcGxlIGN5Y2xlIGRldGVjdGlvbiBmb3IgbGluayBlZGdlcy5cbiAqXG4gKiAtIE9ubHkgY29uc2lkZXJzIGVkZ2VzIHdpdGgga2luZCA9ICdsaW5rJzsgY29tcHV0ZWQvc291cmNlIGRvIG5vdCBwYXJ0aWNpcGF0ZSBpbiB0aGUgZmlyc3QgdmVyc2lvbi5cbiAqIC0gT24gY3ljbGUgZGV0ZWN0aW9uLCB0aHJvd3MgYW4gZXJyb3Igd2l0aCBwYXRoIGNvbnRleHQgdG8gYXZvaWQgaW5maW5pdGUgdXBkYXRlcyBhdCBydW50aW1lLlxuICovXG5jb25zdCBhc3NlcnROb0xpbmtDeWNsZXMgPSAoZWRnZXM6IFJlYWRvbmx5QXJyYXk8U3RhdGVUcmFpdEdyYXBoRWRnZT4pOiB2b2lkID0+IHtcbiAgY29uc3QgYWRqYWNlbmN5ID0gbmV3IE1hcDxzdHJpbmcsIHN0cmluZ1tdPigpXG5cbiAgZm9yIChjb25zdCBlZGdlIG9mIGVkZ2VzKSB7XG4gICAgaWYgKGVkZ2Uua2luZCAhPT0gJ2xpbmsnKSBjb250aW51ZVxuICAgIGNvbnN0IGxpc3QgPSBhZGphY2VuY3kuZ2V0KGVkZ2UuZnJvbSkgPz8gW11cbiAgICBsaXN0LnB1c2goZWRnZS50bylcbiAgICBhZGphY2VuY3kuc2V0KGVkZ2UuZnJvbSwgbGlzdClcbiAgfVxuXG4gIGNvbnN0IHZpc2l0ZWQgPSBuZXcgU2V0PHN0cmluZz4oKVxuICBjb25zdCBzdGFjayA9IG5ldyBTZXQ8c3RyaW5nPigpXG5cbiAgY29uc3QgZGZzID0gKG5vZGU6IHN0cmluZyk6IHZvaWQgPT4ge1xuICAgIGlmIChzdGFjay5oYXMobm9kZSkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgYFtTdGF0ZVRyYWl0LmJ1aWxkXSBsaW5rIGN5Y2xlIGRldGVjdGVkIGF0IGZpZWxkIFwiJHtub2RlfVwiLiBgICtcbiAgICAgICAgICAnUGxlYXNlIGNoZWNrIGxpbmsgdHJhaXRzIGZvciBjaXJjdWxhciBkZXBlbmRlbmNpZXMuJyxcbiAgICAgIClcbiAgICB9XG4gICAgaWYgKHZpc2l0ZWQuaGFzKG5vZGUpKSByZXR1cm5cbiAgICB2aXNpdGVkLmFkZChub2RlKVxuICAgIHN0YWNrLmFkZChub2RlKVxuXG4gICAgY29uc3QgbmV4dHMgPSBhZGphY2VuY3kuZ2V0KG5vZGUpXG4gICAgaWYgKG5leHRzKSB7XG4gICAgICBmb3IgKGNvbnN0IHRvIG9mIG5leHRzKSB7XG4gICAgICAgIGRmcyh0bylcbiAgICAgIH1cbiAgICB9XG5cbiAgICBzdGFjay5kZWxldGUobm9kZSlcbiAgfVxuXG4gIGZvciAoY29uc3Qgbm9kZSBvZiBhZGphY2VuY3kua2V5cygpKSB7XG4gICAgaWYgKCF2aXNpdGVkLmhhcyhub2RlKSkge1xuICAgICAgZGZzKG5vZGUpXG4gICAgfVxuICB9XG59XG5cbmNvbnN0IGNvbGxlY3RTY2hlbWFQYXRocyA9IChcbiAgZW50cmllczogUmVhZG9ubHlBcnJheTxTdGF0ZVRyYWl0RW50cnk8YW55LCBzdHJpbmc+Pixcbik6IFJlYWRvbmx5QXJyYXk8U3RhdGVUcmFpdFNjaGVtYVBhdGhSZWY+ID0+IHtcbiAgY29uc3QgYnlLZXkgPSBuZXcgTWFwPHN0cmluZywgU3RhdGVUcmFpdFNjaGVtYVBhdGhSZWY+KClcblxuICBjb25zdCBhZGQgPSAocmVmOiBTdGF0ZVRyYWl0U2NoZW1hUGF0aFJlZik6IHZvaWQgPT4ge1xuICAgIGlmICghcmVmLnBhdGgpIHJldHVyblxuICAgIGNvbnN0IGsgPSBgJHtyZWYua2luZH18JHtyZWYuZW50cnlLaW5kfXwke3JlZi5lbnRyeUZpZWxkUGF0aH18JHtyZWYucnVsZU5hbWUgPz8gJyd9fCR7cmVmLnBhdGh9YFxuICAgIGJ5S2V5LnNldChrLCByZWYpXG4gIH1cblxuICBjb25zdCBnZXRDaGVja1dyaXRlYmFja1BhdGggPSAoZW50cnk6IEV4dHJhY3Q8U3RhdGVUcmFpdEVudHJ5PGFueSwgc3RyaW5nPiwgeyByZWFkb25seSBraW5kOiAnY2hlY2snIH0+KTogc3RyaW5nID0+IHtcbiAgICBjb25zdCB3YiA9IChlbnRyeS5tZXRhIGFzIGFueSk/LndyaXRlYmFja1xuICAgIGNvbnN0IHAgPSB3YiAmJiB0eXBlb2Ygd2IgPT09ICdvYmplY3QnID8gKHdiIGFzIGFueSkucGF0aCA6IHVuZGVmaW5lZFxuICAgIGNvbnN0IHdyaXRlYmFja1BhdGggPSB0eXBlb2YgcCA9PT0gJ3N0cmluZycgJiYgcC5zdGFydHNXaXRoKCdlcnJvcnMuJykgPyBwIDogdW5kZWZpbmVkXG5cbiAgICBpZiAod3JpdGViYWNrUGF0aCkgcmV0dXJuIHdyaXRlYmFja1BhdGhcblxuICAgIGNvbnN0IGZpZWxkUGF0aCA9IGVudHJ5LmZpZWxkUGF0aFxuICAgIGlmIChmaWVsZFBhdGguZW5kc1dpdGgoJ1tdJykpIHtcbiAgICAgIHJldHVybiBgZXJyb3JzLiR7ZmllbGRQYXRoLnNsaWNlKDAsIC0yKX1gXG4gICAgfVxuICAgIHJldHVybiBgZXJyb3JzLiR7ZmllbGRQYXRofWBcbiAgfVxuXG4gIGZvciAoY29uc3QgZW50cnkgb2YgZW50cmllcykge1xuICAgIGFkZCh7XG4gICAgICBraW5kOiAnZmllbGRQYXRoJyxcbiAgICAgIGVudHJ5S2luZDogZW50cnkua2luZCxcbiAgICAgIGVudHJ5RmllbGRQYXRoOiBlbnRyeS5maWVsZFBhdGgsXG4gICAgICBwYXRoOiBlbnRyeS5maWVsZFBhdGgsXG4gICAgfSlcblxuICAgIGlmIChlbnRyeS5raW5kID09PSAnY29tcHV0ZWQnIHx8IGVudHJ5LmtpbmQgPT09ICdzb3VyY2UnKSB7XG4gICAgICBjb25zdCBkZXBzID0gKChlbnRyeS5tZXRhIGFzIGFueSk/LmRlcHMgPz8gW10pIGFzIFJlYWRvbmx5QXJyYXk8c3RyaW5nPlxuICAgICAgZm9yIChjb25zdCBkZXAgb2YgZGVwcykge1xuICAgICAgICBhZGQoe1xuICAgICAgICAgIGtpbmQ6ICdkZXAnLFxuICAgICAgICAgIGVudHJ5S2luZDogZW50cnkua2luZCxcbiAgICAgICAgICBlbnRyeUZpZWxkUGF0aDogZW50cnkuZmllbGRQYXRoLFxuICAgICAgICAgIHBhdGg6IGRlcCxcbiAgICAgICAgfSlcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoZW50cnkua2luZCA9PT0gJ2xpbmsnKSB7XG4gICAgICBhZGQoe1xuICAgICAgICBraW5kOiAnbGlua19mcm9tJyxcbiAgICAgICAgZW50cnlLaW5kOiAnbGluaycsXG4gICAgICAgIGVudHJ5RmllbGRQYXRoOiBlbnRyeS5maWVsZFBhdGgsXG4gICAgICAgIHBhdGg6IGVudHJ5Lm1ldGEuZnJvbSBhcyBzdHJpbmcsXG4gICAgICB9KVxuICAgIH1cblxuICAgIGlmIChlbnRyeS5raW5kID09PSAnY2hlY2snKSB7XG4gICAgICBhZGQoe1xuICAgICAgICBraW5kOiAnY2hlY2tfd3JpdGViYWNrJyxcbiAgICAgICAgZW50cnlLaW5kOiAnY2hlY2snLFxuICAgICAgICBlbnRyeUZpZWxkUGF0aDogZW50cnkuZmllbGRQYXRoLFxuICAgICAgICBwYXRoOiBnZXRDaGVja1dyaXRlYmFja1BhdGgoZW50cnkpLFxuICAgICAgfSlcblxuICAgICAgY29uc3QgcnVsZXMgPSAoKGVudHJ5Lm1ldGEgYXMgYW55KT8ucnVsZXMgPz8ge30pIGFzIFJlY29yZDxzdHJpbmcsIGFueT5cbiAgICAgIGZvciAoY29uc3QgbmFtZSBvZiBPYmplY3Qua2V5cyhydWxlcykpIHtcbiAgICAgICAgY29uc3QgcnVsZSA9IHJ1bGVzW25hbWVdXG4gICAgICAgIGlmICghcnVsZSB8fCB0eXBlb2YgcnVsZSAhPT0gJ29iamVjdCcpIGNvbnRpbnVlXG4gICAgICAgIGNvbnN0IGRlcHMgPSAocnVsZS5kZXBzID8/IFtdKSBhcyBSZWFkb25seUFycmF5PHN0cmluZz5cbiAgICAgICAgZm9yIChjb25zdCBkZXAgb2YgZGVwcykge1xuICAgICAgICAgIGFkZCh7XG4gICAgICAgICAgICBraW5kOiAnZGVwJyxcbiAgICAgICAgICAgIGVudHJ5S2luZDogJ2NoZWNrJyxcbiAgICAgICAgICAgIGVudHJ5RmllbGRQYXRoOiBlbnRyeS5maWVsZFBhdGgsXG4gICAgICAgICAgICBydWxlTmFtZTogbmFtZSxcbiAgICAgICAgICAgIHBhdGg6IGRlcCxcbiAgICAgICAgICB9KVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIEFycmF5LmZyb20oYnlLZXkuZW50cmllcygpKVxuICAgIC5zb3J0KChhLCBiKSA9PiAoYVswXSA8IGJbMF0gPyAtMSA6IGFbMF0gPiBiWzBdID8gMSA6IDApKVxuICAgIC5tYXAoKFssIHZdKSA9PiB2KVxufVxuXG4vKipcbiAqIEJ1aWxkcyBhIFN0YXRlVHJhaXRQcm9ncmFtIGZyb20gdGhlIGdpdmVuIHN0YXRlU2NoZW1hIGFuZCB0cmFpdCBzcGVjLlxuICpcbiAqIC0gUHVyZSBmdW5jdGlvbjogZG9lcyBub3QgZGVwZW5kIG9uIGV4dGVybmFsIEVudiAvIGdsb2JhbCBzdGF0ZS5cbiAqIC0gQ3VycmVudCBpbXBsZW1lbnRhdGlvbiBmb2N1c2VzIG9uOlxuICogICAtIE5vcm1hbGl6aW5nIFNwZWMgaW50byBlbnRyaWVzLlxuICogICAtIEJ1aWxkaW5nIGEgbGlnaHR3ZWlnaHQgR3JhcGggLyBQbGFuIGZyb20gZW50cmllcy5cbiAqICAgLSBSdW5uaW5nIGJhc2ljIGN5Y2xlIGRldGVjdGlvbiBmb3IgbGluayBlZGdlcy5cbiAqXG4gKiBJZiB3ZSBsYXRlciBuZWVkIGZpbmVyLWdyYWluZWQgZGVwZW5kZW5jeSBhbmFseXNpcyAoZS5nLiBzdGF0aWMgYW5hbHlzaXMgZm9yIGNvbXB1dGVkL2tleSksXG4gKiBldm9sdmUgaXQgaW5zaWRlIHRoaXMgbW9kdWxlIHdpdGhvdXQgY2hhbmdpbmcgdGhlIHB1YmxpYyBBUEkgc3VyZmFjZS5cbiAqL1xuZXhwb3J0IGNvbnN0IGJ1aWxkID0gPFMgZXh0ZW5kcyBvYmplY3Q+KFxuICBzdGF0ZVNjaGVtYTogU2NoZW1hLlNjaGVtYTxTLCBhbnk+LFxuICBzcGVjOiBTdGF0ZVRyYWl0U3BlYzxTPixcbik6IFN0YXRlVHJhaXRQcm9ncmFtPFM+ID0+IHtcbiAgY29uc3QgZW50cmllcyA9IG5vcm1hbGl6ZVNwZWMoc3BlYykgYXMgUmVhZG9ubHlBcnJheTxTdGF0ZVRyYWl0RW50cnk8Uywgc3RyaW5nPj5cbiAgY29uc3Qgbm9kZU1ldGFCeUZpZWxkUGF0aCA9IGNvbGxlY3ROb2RlTWV0YShzcGVjKVxuXG4gIC8vIFBoYXNlIDQgKFVTMik6IHJlcXVpcmUgZXhwbGljaXQgZGVwcyAoR3JhcGgvZGlhZ25vc3RpY3MvcmVwbGF5IHRyZWF0IGRlcHMgYXMgdGhlIHNpbmdsZSBkZXBlbmRlbmN5IHNvdXJjZSBvZiB0cnV0aCkuXG4gIGZvciAoY29uc3QgZW50cnkgb2YgZW50cmllcykge1xuICAgIGlmIChlbnRyeS5raW5kID09PSAnY29tcHV0ZWQnKSB7XG4gICAgICBjb25zdCBkZXBzID0gKGVudHJ5Lm1ldGEgYXMgYW55KS5kZXBzIGFzIFJlYWRvbmx5QXJyYXk8c3RyaW5nPiB8IHVuZGVmaW5lZFxuICAgICAgaWYgKGRlcHMgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgYFtTdGF0ZVRyYWl0LmJ1aWxkXSBNaXNzaW5nIGV4cGxpY2l0IGRlcHMgZm9yIGNvbXB1dGVkIFwiJHtlbnRyeS5maWVsZFBhdGh9XCIuIGAgK1xuICAgICAgICAgICAgJ1BsZWFzZSB1c2UgU3RhdGVUcmFpdC5jb21wdXRlZCh7IGRlcHM6IFsuLi5dLCBnZXQ6IC4uLiB9KS4nLFxuICAgICAgICApXG4gICAgICB9XG4gICAgfVxuICAgIGlmIChlbnRyeS5raW5kID09PSAnc291cmNlJykge1xuICAgICAgY29uc3QgZGVwcyA9IChlbnRyeS5tZXRhIGFzIGFueSkuZGVwcyBhcyBSZWFkb25seUFycmF5PHN0cmluZz4gfCB1bmRlZmluZWRcbiAgICAgIGlmIChkZXBzID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAgIGBbU3RhdGVUcmFpdC5idWlsZF0gTWlzc2luZyBleHBsaWNpdCBkZXBzIGZvciBzb3VyY2UgXCIke2VudHJ5LmZpZWxkUGF0aH1cIi4gYCArXG4gICAgICAgICAgICAnUGxlYXNlIHByb3ZpZGUgbWV0YS5kZXBzIGZvciBTdGF0ZVRyYWl0LnNvdXJjZSh7IGRlcHM6IFsuLi5dLCAuLi4gfSkuJyxcbiAgICAgICAgKVxuICAgICAgfVxuICAgIH1cbiAgICBpZiAoZW50cnkua2luZCA9PT0gJ2NoZWNrJykge1xuICAgICAgY29uc3QgcnVsZXMgPSAoKGVudHJ5Lm1ldGEgYXMgYW55KT8ucnVsZXMgPz8ge30pIGFzIFJlY29yZDxzdHJpbmcsIGFueT5cbiAgICAgIGZvciAoY29uc3QgbmFtZSBvZiBPYmplY3Qua2V5cyhydWxlcykpIHtcbiAgICAgICAgY29uc3QgcnVsZSA9IHJ1bGVzW25hbWVdXG4gICAgICAgIGlmICh0eXBlb2YgcnVsZSA9PT0gJ2Z1bmN0aW9uJyB8fCAhcnVsZSB8fCB0eXBlb2YgcnVsZSAhPT0gJ29iamVjdCcpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgICBgW1N0YXRlVHJhaXQuYnVpbGRdIE1pc3NpbmcgZXhwbGljaXQgZGVwcyBmb3IgY2hlY2sgXCIke2VudHJ5LmZpZWxkUGF0aH1cIiBydWxlIFwiJHtuYW1lfVwiLiBgICtcbiAgICAgICAgICAgICAgJ1BsZWFzZSB1c2UgeyBkZXBzOiBbLi4uXSwgdmFsaWRhdGU6IC4uLiB9IGZvcm0uJyxcbiAgICAgICAgICApXG4gICAgICAgIH1cbiAgICAgICAgaWYgKChydWxlIGFzIGFueSkuZGVwcyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAgICAgYFtTdGF0ZVRyYWl0LmJ1aWxkXSBNaXNzaW5nIGV4cGxpY2l0IGRlcHMgZm9yIGNoZWNrIFwiJHtlbnRyeS5maWVsZFBhdGh9XCIgcnVsZSBcIiR7bmFtZX1cIi4gYCArXG4gICAgICAgICAgICAgICdQbGVhc2UgcHJvdmlkZSBkZXBzOiBbLi4uXS4nLFxuICAgICAgICAgIClcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIGNvbnN0IHsgZ3JhcGgsIHBsYW4gfSA9IGJ1aWxkR3JhcGgoZW50cmllcywgbm9kZU1ldGFCeUZpZWxkUGF0aClcblxuICAvLyBSdW4gYSBjeWNsZSBjaGVjayBmb3IgbGluayBlZGdlcyB0byBhdm9pZCBvYnZpb3VzIGNvbmZpZ3VyYXRpb24gZXJyb3JzLlxuICBhc3NlcnROb0xpbmtDeWNsZXMoZ3JhcGguZWRnZXMpXG5cbiAgcmV0dXJuIHtcbiAgICBzdGF0ZVNjaGVtYSxcbiAgICBzcGVjLFxuICAgIGVudHJpZXM6IGVudHJpZXMgYXMgUmVhZG9ubHlBcnJheTxTdGF0ZVRyYWl0RW50cnk8YW55LCBzdHJpbmc+PixcbiAgICBncmFwaCxcbiAgICBwbGFuLFxuICAgIGNvbnZlcmdlSXI6IGJ1aWxkQ29udmVyZ2VJcihzdGF0ZVNjaGVtYSBhcyBhbnksIGVudHJpZXMgYXMgUmVhZG9ubHlBcnJheTxTdGF0ZVRyYWl0RW50cnk8YW55LCBzdHJpbmc+PiksXG4gICAgc2NoZW1hUGF0aHM6IGNvbGxlY3RTY2hlbWFQYXRocyhlbnRyaWVzIGFzIFJlYWRvbmx5QXJyYXk8U3RhdGVUcmFpdEVudHJ5PGFueSwgc3RyaW5nPj4pLFxuICB9XG59XG4iLCAiaW1wb3J0IHR5cGUgeyBTY2hlbWEgfSBmcm9tICdlZmZlY3QnXG5pbXBvcnQgdHlwZSB7IFN0YXRlQXRQYXRoLCBTdGF0ZUZpZWxkUGF0aCB9IGZyb20gJy4vZmllbGQtcGF0aC5qcydcbmltcG9ydCB0eXBlIHsgRGlydHlBbGxSZWFzb24gfSBmcm9tICcuLi9maWVsZC1wYXRoLmpzJ1xuaW1wb3J0ICogYXMgTWV0YSBmcm9tICcuL21ldGEuanMnXG5pbXBvcnQgdHlwZSB7IENvbnZlcmdlU3RhdGljSXJSZWdpc3RyeSB9IGZyb20gJy4vY29udmVyZ2UtaXIuanMnXG5pbXBvcnQgdHlwZSB7IENvbnZlcmdlRXhlY0lyIH0gZnJvbSAnLi9jb252ZXJnZS1leGVjLWlyLmpzJ1xuXG4vLyBTdGF0ZVRyYWl0IGNvcmUgbW9kZWwuXG4vLyBLZWVwIHRoZSBmaWVsZCBzZW1hbnRpY3MgYWxpZ25lZCB3aXRoIGRhdGEtbW9kZWwubWQgLyByZWZlcmVuY2VzL3N0YXRlLXRyYWl0LWNvcmUubWQuXG5cbi8qKlxuICogU3RhdGVUcmFpdFNwZWM8Uz5cdUZGMUFcbiAqIC0gVGhlIHN0YW5kYXJkIHNoYXBlIGZvciB0aGUgYHRyYWl0c2Agc2xvdCBpbiBhIE1vZHVsZSBibHVlcHJpbnQuXG4gKiAtIEtleXMgYXJlIGNvbnN0cmFpbmVkIGJ5IFN0YXRlRmllbGRQYXRoPFM+OyB2YWx1ZXMgYXJlIGRlY2xhcmF0aW9ucyBmb3IgdGhlIGNvcnJlc3BvbmRpbmcgc2NvcGUgKEVudHJ5IC8gTm9kZSAvIExpc3QpLlxuICovXG5leHBvcnQgdHlwZSBTdGF0ZVRyYWl0U3BlYzxTPiA9IFMgZXh0ZW5kcyBvYmplY3RcbiAgPyB7XG4gICAgICBbUGF0aCBpbiBTdGF0ZUZpZWxkUGF0aDxTPiB8ICckcm9vdCddPzogU3RhdGVUcmFpdFNwZWNWYWx1ZTxTLCBQYXRoPlxuICAgIH1cbiAgOiBuZXZlclxuXG5leHBvcnQgdHlwZSBTdGF0ZVRyYWl0S2luZCA9ICdjb21wdXRlZCcgfCAnc291cmNlJyB8ICdsaW5rJyB8ICdleHRlcm5hbFN0b3JlJyB8ICdjaGVjaydcblxuZXhwb3J0IHR5cGUgVHJhaXRMYW5lID0gJ3VyZ2VudCcgfCAnbm9uVXJnZW50J1xuXG4vKipcbiAqIFRyYWl0Q29udmVyZ2VTY2hlZHVsaW5nXHVGRjFBXG4gKiAtIFNjaGVkdWxpbmcgc2VtYW50aWNzIGZvciBjb252ZXJnZS9kaXJ0eS1jaGVjayAoMDQzKTogZGVjaWRlcyB3aGV0aGVyIGEgc3RlcCBtdXN0IGNvbnZlcmdlIHdpdGhpbiBlYWNoIHRyYW5zYWN0aW9uIHdpbmRvdy5cbiAqIC0gRGVmYXVsdCBgaW1tZWRpYXRlYCAoa2VlcHMgbGVnYWN5IGJlaGF2aW9yKTsgYGRlZmVycmVkYCB0YWtlcyBlZmZlY3Qgb25seSB3aXRoIGV4cGxpY2l0IGRlY2xhcmF0aW9uICsgdGltZS1zbGljaW5nIGVuYWJsZWQuXG4gKi9cbmV4cG9ydCB0eXBlIFRyYWl0Q29udmVyZ2VTY2hlZHVsaW5nID0gJ2ltbWVkaWF0ZScgfCAnZGVmZXJyZWQnXG5cbmV4cG9ydCBpbnRlcmZhY2UgQ29tcHV0ZWRNZXRhPFMsIFA+IHtcbiAgLyoqXG4gICAqIEV4cGxpY2l0IGRlcGVuZGVuY3kgZmllbGQgcGF0aHMgKHJlcXVpcmVkKTpcbiAgICpcbiAgICogLSBkZXBzIGlzIHRoZSBzaW5nbGUgc291cmNlIG9mIHRydXRoIGZvciBkZXBlbmRlbmNpZXM6IEdyYXBoL1JldmVyc2VDbG9zdXJlL2luY3JlbWVudGFsIHNjaGVkdWxpbmcvcGVyZiBvcHRpbWl6YXRpb25zIHJlbHkgb24gZGVwcyBvbmx5LlxuICAgKiAtIEluIHRoZSBEU0wsIGBTdGF0ZVRyYWl0LmNvbXB1dGVkKHsgZGVwcywgZ2V0IH0pYCB1c2VzIGRlcHMtYXMtYXJnczsgaXQgZG9lcyBub3QgZXhwb3NlIGAoc3RhdGUpID0+IC4uLmAuXG4gICAqIC0gRHVyaW5nIGJ1aWxkLCBgZ2V0KC4uLmRlcHNWYWx1ZXMpYCBpcyBsb3dlcmVkIGludG8gYGRlcml2ZShzdGF0ZSlgIGZvciBydW50aW1lIGV4ZWN1dGlvbiwgYnV0IHRoZSBkZXBlbmRlbmN5IHJlYWQtc2V0IHJlbWFpbnMgZGVwcy1iYXNlZC5cbiAgICogLSBJbiBkZXYtbW9kZSwgaWYgYWN0dWFsIHJlYWRzIGluIGBkZXJpdmUoc3RhdGUpYCBkaXNhZ3JlZSB3aXRoIGRlcHMsIGEgYGRlcHNfbWlzbWF0Y2hgIGRpYWdub3N0aWMgd2FybmluZyBpcyBlbWl0dGVkLlxuICAgKlxuICAgKiAtIEZvciByb290IHNjb3BlOiBkZXBzIGFyZSBTdGF0ZUZpZWxkUGF0aDxTdGF0ZT4uXG4gICAqIC0gRm9yIGxpc3QuaXRlbSBzY29wZTogZGVwcyBhcmUgU3RhdGVGaWVsZFBhdGg8SXRlbT4gKHJlbGF0aXZlIHBhdGhzOyBidWlsZCB3aWxsIHByZWZpeCB0aGVtKS5cbiAgICovXG4gIHJlYWRvbmx5IGRlcHM6IFJlYWRvbmx5QXJyYXk8U3RhdGVGaWVsZFBhdGg8Uz4+XG4gIHJlYWRvbmx5IGRlcml2ZTogKHN0YXRlOiBSZWFkb25seTxTPikgPT4gU3RhdGVBdFBhdGg8UywgUD5cbiAgLyoqXG4gICAqIE9wdGlvbmFsOiBlcXVhbGl0eSBwcmVkaWNhdGUgKHVzZWQgdG8gc2tpcCBuby1vcCB3cml0ZWJhY2tzKS5cbiAgICovXG4gIHJlYWRvbmx5IGVxdWFscz86IChwcmV2OiBTdGF0ZUF0UGF0aDxTLCBQPiwgbmV4dDogU3RhdGVBdFBhdGg8UywgUD4pID0+IGJvb2xlYW5cbiAgLyoqXG4gICAqIENvbnZlcmdlIHNjaGVkdWxpbmcgKDA0Myk6IGRlZmF1bHRzIHRvIGltbWVkaWF0ZS5cbiAgICovXG4gIHJlYWRvbmx5IHNjaGVkdWxpbmc/OiBUcmFpdENvbnZlcmdlU2NoZWR1bGluZ1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFNvdXJjZU1ldGE8UywgUD4ge1xuICByZWFkb25seSBkZXBzOiBSZWFkb25seUFycmF5PFN0YXRlRmllbGRQYXRoPFM+PlxuICAvKipcbiAgICogTG9naWNhbCByZXNvdXJjZSBpZGVudGlmaWVyIChlLmcuIFwidXNlci9wcm9maWxlXCIpLlxuICAgKlxuICAgKiAtIEluIHRoZSBTdGF0ZVRyYWl0LnNvdXJjZSBEU0wsIGByZXNvdXJjZWAgaXMgc3RvcmVkIGhlcmUgZHVyaW5nIGJ1aWxkLlxuICAgKiAtIGRhdGEtbW9kZWwubWQgY2FsbHMgaXQgcmVzb3VyY2VJZDsgd2Uga2VlcCB0aGUgRFNMIG5hbWluZyBoZXJlIHRvIGF2b2lkIGNvbmZ1c2lvbi5cbiAgICovXG4gIHJlYWRvbmx5IHJlc291cmNlOiBzdHJpbmdcbiAgLyoqXG4gICAqIFJ1bGUgZm9yIGNvbXB1dGluZyB0aGUga2V5IHJlcXVpcmVkIHRvIGFjY2VzcyB0aGUgcmVzb3VyY2UuXG4gICAqXG4gICAqIC0gZGVwcyBpcyB0aGUgc2luZ2xlIHNvdXJjZSBvZiB0cnV0aCBmb3IgZGVwZW5kZW5jaWVzOiBHcmFwaC9SZXZlcnNlQ2xvc3VyZS9pbmNyZW1lbnRhbCBzY2hlZHVsaW5nL3BlcmYgb3B0aW1pemF0aW9ucyByZWx5IG9uIGRlcHMgb25seS5cbiAgICogLSBJbiB0aGUgRFNMLCBgU3RhdGVUcmFpdC5zb3VyY2UoeyBkZXBzLCBrZXkgfSlgIHVzZXMgZGVwcy1hcy1hcmdzOyBpdCBkb2VzIG5vdCBleHBvc2UgYChzdGF0ZSkgPT4gLi4uYC5cbiAgICogLSBEdXJpbmcgYnVpbGQsIGBrZXkoLi4uZGVwc1ZhbHVlcylgIGlzIGxvd2VyZWQgaW50byBga2V5KHN0YXRlKWAgZm9yIHJ1bnRpbWUgZXhlY3V0aW9uLCBidXQgdGhlIGRlcGVuZGVuY3kgcmVhZC1zZXQgcmVtYWlucyBkZXBzLWJhc2VkLlxuICAgKlxuICAgKiAtIFJldHVybmluZyB1bmRlZmluZWQgbWVhbnMgdGhlIHJlc291cmNlIGlzIGluYWN0aXZlIHVuZGVyIHRoZSBjdXJyZW50IHN0YXRlIChzaG91bGQgYmUgcmVjeWNsZWQgdG8gaWRsZSkuXG4gICAqL1xuICByZWFkb25seSBrZXk6IChzdGF0ZTogUmVhZG9ubHk8Uz4pID0+IHVua25vd25cbiAgcmVhZG9ubHkgdHJpZ2dlcnM/OiBSZWFkb25seUFycmF5PCdvbk1vdW50JyB8ICdvbktleUNoYW5nZScgfCAnbWFudWFsJz5cbiAgcmVhZG9ubHkgZGVib3VuY2VNcz86IG51bWJlclxuICByZWFkb25seSBjb25jdXJyZW5jeT86ICdzd2l0Y2gnIHwgJ2V4aGF1c3QtdHJhaWxpbmcnXG4gIC8qKlxuICAgKiBTZXJpYWxpemFibGUgbWV0YWRhdGEgZm9yIGRldnRvb2xzL2RvY3MgKHdoaXRlbGlzdGVkIGZpZWxkcykuXG4gICAqL1xuICByZWFkb25seSBtZXRhPzogTWV0YS5UcmFpdE1ldGFcbiAgLyoqXG4gICAqIFJlc2VydmVkOiBidWlsZCBtYXkgcG9wdWxhdGUgdGhlIGZpZWxkIHBhdGggdGhpcyB0cmFpdCBpcyBhdHRhY2hlZCB0bywgZm9yIGVhc2llciBkZWJ1Z2dpbmcuXG4gICAqL1xuICByZWFkb25seSBfZmllbGRQYXRoPzogUFxufVxuXG5leHBvcnQgaW50ZXJmYWNlIExpbmtNZXRhPFM+IHtcbiAgLyoqXG4gICAqIFNvdXJjZSBmaWVsZCBwYXRoIChhbHNvIGNvbnN0cmFpbmVkIGJ5IFN0YXRlRmllbGRQYXRoPFM+KS5cbiAgICovXG4gIHJlYWRvbmx5IGZyb206IFN0YXRlRmllbGRQYXRoPFM+XG4gIC8qKlxuICAgKiBDb252ZXJnZSBzY2hlZHVsaW5nICgwNDMpOiBkZWZhdWx0cyB0byBpbW1lZGlhdGUuXG4gICAqL1xuICByZWFkb25seSBzY2hlZHVsaW5nPzogVHJhaXRDb252ZXJnZVNjaGVkdWxpbmdcbn1cblxuZXhwb3J0IGludGVyZmFjZSBFeHRlcm5hbFN0b3JlTGlrZTxUPiB7XG4gIHJlYWRvbmx5IGdldFNuYXBzaG90OiAoKSA9PiBUXG4gIHJlYWRvbmx5IGdldFNlcnZlclNuYXBzaG90PzogKCkgPT4gVFxuICByZWFkb25seSBzdWJzY3JpYmU6IChsaXN0ZW5lcjogKCkgPT4gdm9pZCkgPT4gKCkgPT4gdm9pZFxufVxuXG5leHBvcnQgaW50ZXJmYWNlIEV4dGVybmFsU3RvcmVNZXRhPFMsIFAsIFQgPSB1bmtub3duPiB7XG4gIHJlYWRvbmx5IHN0b3JlOiBFeHRlcm5hbFN0b3JlTGlrZTxUPlxuICByZWFkb25seSBzZWxlY3Q/OiAoc25hcHNob3Q6IFQpID0+IFN0YXRlQXRQYXRoPFMsIFA+XG4gIHJlYWRvbmx5IGVxdWFscz86IChwcmV2OiBTdGF0ZUF0UGF0aDxTLCBQPiwgbmV4dDogU3RhdGVBdFBhdGg8UywgUD4pID0+IGJvb2xlYW5cbiAgcmVhZG9ubHkgY29hbGVzY2VXaW5kb3dNcz86IG51bWJlclxuICByZWFkb25seSBwcmlvcml0eT86IFRyYWl0TGFuZVxuICByZWFkb25seSBtZXRhPzogTWV0YS5UcmFpdE1ldGFcbiAgcmVhZG9ubHkgX2ZpZWxkUGF0aD86IFBcbn1cblxuZXhwb3J0IHR5cGUgQ2hlY2tSdWxlPElucHV0ID0gdW5rbm93biwgQ3R4ID0gdW5rbm93bj4gPSB7XG4gIHJlYWRvbmx5IGRlcHM6IFJlYWRvbmx5QXJyYXk8c3RyaW5nPlxuICAvKipcbiAgICogdmFsaWRhdGVPblx1RkYxQVxuICAgKiAtIEFmZmVjdHMgb25seSBhdXRvIHZhbGlkYXRpb24gcGhhc2VzIChvbkNoYW5nZS9vbkJsdXIpOyBzdWJtaXQvbWFudWFsIGFsd2F5cyBydW4uXG4gICAqIC0gRW1wdHkgYXJyYXkgZGlzYWJsZXMgYXV0byB2YWxpZGF0aW9uIChvbmx5IHN1Ym1pdC9tYW51YWwgcnVuKS5cbiAgICovXG4gIHJlYWRvbmx5IHZhbGlkYXRlT24/OiBSZWFkb25seUFycmF5PCdvbkNoYW5nZScgfCAnb25CbHVyJz5cbiAgcmVhZG9ubHkgdmFsaWRhdGU6IChpbnB1dDogSW5wdXQsIGN0eDogQ3R4KSA9PiB1bmtub3duXG4gIHJlYWRvbmx5IG1ldGE/OiBNZXRhLlRyYWl0TWV0YVxufVxuXG5leHBvcnQgaW50ZXJmYWNlIENoZWNrTWV0YTxJbnB1dCA9IHVua25vd24sIEN0eCA9IHVua25vd24+IHtcbiAgLyoqXG4gICAqIE5hbWVkIHJ1bGUgc2V0ICh1c2VkIGZvciBkZXRlcm1pbmlzdGljIG1lcmdlIGFuZCBkaWFnbm9zdGljcyBkaXNwbGF5KS5cbiAgICovXG4gIHJlYWRvbmx5IHJ1bGVzOiBSZWFkb25seTxSZWNvcmQ8c3RyaW5nLCBDaGVja1J1bGU8SW5wdXQsIEN0eD4+PlxuICAvKipcbiAgICogRXJyb3ItdHJlZSB3cml0ZWJhY2sgKFBoYXNlIDI6IHN0cnVjdHVyZSBvbmx5OyBjb25jcmV0ZSB3cml0ZWJhY2sgc2VtYW50aWNzIGxhbmQgaW4gbGF0ZXIgcGhhc2VzKS5cbiAgICovXG4gIHJlYWRvbmx5IHdyaXRlYmFjaz86IHtcbiAgICByZWFkb25seSBraW5kOiAnZXJyb3JzJ1xuICAgIHJlYWRvbmx5IHBhdGg/OiBzdHJpbmdcbiAgfVxufVxuXG4vKipcbiAqIFN0YXRlVHJhaXRFbnRyeTxTLCBQPlx1RkYxQVxuICogLSBBIHNpbmdsZSBUcmFpdCBjb25maWd1cmF0aW9uIGF0dGFjaGVkIHRvIGEgZmllbGQgcGF0aCBQLlxuICogLSBraW5kIGFuZCBtZXRhIGFsd2F5cyBjb21lIHRvZ2V0aGVyIGFuZCBhcmUgdXNlZCB0byBkaXNwYXRjaCBiZWhhdmlvciBkdXJpbmcgYnVpbGQvaW5zdGFsbC5cbiAqL1xuZXhwb3J0IHR5cGUgU3RhdGVUcmFpdEVudHJ5PFMgPSB1bmtub3duLCBQIGV4dGVuZHMgc3RyaW5nID0gU3RhdGVGaWVsZFBhdGg8Uz4+ID1cbiAgfCB7XG4gICAgICByZWFkb25seSBmaWVsZFBhdGg6IFBcbiAgICAgIHJlYWRvbmx5IGtpbmQ6ICdjb21wdXRlZCdcbiAgICAgIHJlYWRvbmx5IG1ldGE6IENvbXB1dGVkTWV0YTxTLCBQPlxuICAgIH1cbiAgfCB7XG4gICAgICByZWFkb25seSBmaWVsZFBhdGg6IFBcbiAgICAgIHJlYWRvbmx5IGtpbmQ6ICdzb3VyY2UnXG4gICAgICByZWFkb25seSBtZXRhOiBTb3VyY2VNZXRhPFMsIFA+XG4gICAgfVxuICB8IHtcbiAgICAgIHJlYWRvbmx5IGZpZWxkUGF0aDogUFxuICAgICAgcmVhZG9ubHkga2luZDogJ2xpbmsnXG4gICAgICByZWFkb25seSBtZXRhOiBMaW5rTWV0YTxTPlxuICAgIH1cbiAgfCB7XG4gICAgICByZWFkb25seSBmaWVsZFBhdGg6IFBcbiAgICAgIHJlYWRvbmx5IGtpbmQ6ICdleHRlcm5hbFN0b3JlJ1xuICAgICAgcmVhZG9ubHkgbWV0YTogRXh0ZXJuYWxTdG9yZU1ldGE8UywgUD5cbiAgICB9XG4gIHwge1xuICAgICAgcmVhZG9ubHkgZmllbGRQYXRoOiBQXG4gICAgICByZWFkb25seSBraW5kOiAnY2hlY2snXG4gICAgICByZWFkb25seSBtZXRhOiBDaGVja01ldGE8dW5rbm93biwgdW5rbm93bj5cbiAgICB9XG5cbmV4cG9ydCBpbnRlcmZhY2UgU3RhdGVUcmFpdE5vZGU8SW5wdXQgPSB1bmtub3duLCBDdHggPSB1bmtub3duPiB7XG4gIHJlYWRvbmx5IF90YWc6ICdTdGF0ZVRyYWl0Tm9kZSdcbiAgcmVhZG9ubHkgY29tcHV0ZWQ/OiBTdGF0ZVRyYWl0RW50cnk8SW5wdXQsIGFueT4gfCBSZWFkb25seTxSZWNvcmQ8c3RyaW5nLCBTdGF0ZVRyYWl0RW50cnk8SW5wdXQsIGFueT4+PlxuICByZWFkb25seSBzb3VyY2U/OiBTdGF0ZVRyYWl0RW50cnk8SW5wdXQsIGFueT4gfCBSZWFkb25seTxSZWNvcmQ8c3RyaW5nLCBTdGF0ZVRyYWl0RW50cnk8SW5wdXQsIGFueT4+PlxuICByZWFkb25seSBsaW5rPzogU3RhdGVUcmFpdEVudHJ5PElucHV0LCBhbnk+IHwgUmVhZG9ubHk8UmVjb3JkPHN0cmluZywgU3RhdGVUcmFpdEVudHJ5PElucHV0LCBhbnk+Pj5cbiAgcmVhZG9ubHkgZXh0ZXJuYWxTdG9yZT86IFN0YXRlVHJhaXRFbnRyeTxJbnB1dCwgYW55PiB8IFJlYWRvbmx5PFJlY29yZDxzdHJpbmcsIFN0YXRlVHJhaXRFbnRyeTxJbnB1dCwgYW55Pj4+XG4gIHJlYWRvbmx5IGNoZWNrPzogUmVhZG9ubHk8UmVjb3JkPHN0cmluZywgQ2hlY2tSdWxlPElucHV0LCBDdHg+Pj5cbiAgcmVhZG9ubHkgbWV0YT86IE1ldGEuVHJhaXRNZXRhXG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgU3RhdGVUcmFpdExpc3Q8SXRlbSA9IHVua25vd24+IHtcbiAgcmVhZG9ubHkgX3RhZzogJ1N0YXRlVHJhaXRMaXN0J1xuICByZWFkb25seSBpdGVtPzogU3RhdGVUcmFpdE5vZGU8SXRlbSwgYW55PlxuICByZWFkb25seSBsaXN0PzogU3RhdGVUcmFpdE5vZGU8UmVhZG9ubHlBcnJheTxJdGVtPiwgYW55PlxuICByZWFkb25seSBpZGVudGl0eUhpbnQ/OiB7XG4gICAgcmVhZG9ubHkgdHJhY2tCeT86IHN0cmluZ1xuICB9XG59XG5cbmV4cG9ydCB0eXBlIFN0YXRlVHJhaXRTcGVjVmFsdWU8UywgUCBleHRlbmRzIHN0cmluZz4gPVxuICB8IFN0YXRlVHJhaXRFbnRyeTxTLCBQPlxuICB8IFN0YXRlVHJhaXROb2RlPGFueSwgYW55PlxuICB8IFN0YXRlVHJhaXRMaXN0PGFueT5cblxuLyoqXG4gKiBTdGF0ZVRyYWl0RmllbGRcdUZGMUFcbiAqIC0gUmVwcmVzZW50cyBhIGZpZWxkIG5vZGUgaW4gU3RhdGUgKHdoZXRoZXIgb3Igbm90IHRyYWl0cyBhcmUgYXR0YWNoZWQpLlxuICogLSBOb3JtYWxpemVkIGZyb20gU3RhdGVUcmFpdFNwZWMgZHVyaW5nIGJ1aWxkLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFN0YXRlVHJhaXRGaWVsZCB7XG4gIHJlYWRvbmx5IGlkOiBzdHJpbmdcbiAgcmVhZG9ubHkgcGF0aDogc3RyaW5nXG4gIHJlYWRvbmx5IGRpc3BsYXlOYW1lPzogc3RyaW5nXG4gIHJlYWRvbmx5IHZhbHVlVHlwZT86IHN0cmluZ1xuICByZWFkb25seSB0cmFpdHM6IFJlYWRvbmx5QXJyYXk8U3RhdGVUcmFpdEZpZWxkVHJhaXQ+XG59XG5cbi8qKlxuICogU3RhdGVUcmFpdEZpZWxkVHJhaXRcdUZGMUFcbiAqIC0gQSBzdHJ1Y3R1cmVkIGRlc2NyaXB0aW9uIG9mIGEgZmllbGQgdHJhaXQgKGNvbXB1dGVkIC8gc291cmNlIC8gbGluaykuXG4gKiAtIG1ldGEgbWF0Y2hlcyBTdGF0ZVRyYWl0RW50cnkubWV0YTsgZGVwcyBpcyB0aGUgc2V0IG9mIGZpZWxkIHBhdGhzIHRoaXMgdHJhaXQgZGVwZW5kcyBvbi5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBTdGF0ZVRyYWl0RmllbGRUcmFpdCB7XG4gIHJlYWRvbmx5IGZpZWxkSWQ6IHN0cmluZ1xuICByZWFkb25seSBraW5kOiBTdGF0ZVRyYWl0S2luZFxuICByZWFkb25seSBtZXRhOlxuICAgIHwgQ29tcHV0ZWRNZXRhPHVua25vd24sIHN0cmluZz5cbiAgICB8IFNvdXJjZU1ldGE8dW5rbm93biwgc3RyaW5nPlxuICAgIHwgTGlua01ldGE8dW5rbm93bj5cbiAgICB8IEV4dGVybmFsU3RvcmVNZXRhPHVua25vd24sIHN0cmluZz5cbiAgICB8IENoZWNrTWV0YTx1bmtub3duLCB1bmtub3duPlxuICByZWFkb25seSBkZXBzOiBSZWFkb25seUFycmF5PHN0cmluZz5cbn1cblxuLyoqXG4gKiBTdGF0ZVRyYWl0UmVzb3VyY2VcdUZGMUFcbiAqIC0gRGVzY3JpYmVzIHRoZSBsb2dpY2FsIHJlc291cmNlIG1ldGFkYXRhIHRoYXQgYSBzb3VyY2UgdHJhaXQgZGVwZW5kcyBvbi5cbiAqIC0gQ29uY3JldGUgUmVzb3VyY2VTcGVjIGltcGxlbWVudGF0aW9uIGxpdmVzIGluIHRoZSBSZXNvdXJjZSBuYW1lc3BhY2U7IHRoaXMga2VlcHMgb25seSB0cmFpdC1wZXJzcGVjdGl2ZSBkZXBlbmRlbmN5IGluZm8uXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgU3RhdGVUcmFpdFJlc291cmNlIHtcbiAgcmVhZG9ubHkgcmVzb3VyY2VJZDogc3RyaW5nXG4gIHJlYWRvbmx5IGtleVNlbGVjdG9yOiBzdHJpbmdcbiAgcmVhZG9ubHkga2V5RXhhbXBsZT86IHVua25vd25cbiAgcmVhZG9ubHkgb3duZXJGaWVsZHM6IFJlYWRvbmx5QXJyYXk8c3RyaW5nPlxuICByZWFkb25seSBtZXRhPzogTWV0YS5UcmFpdE1ldGFcbiAgcmVhZG9ubHkgbWV0YU9yaWdpbj86IHN0cmluZ1xuICByZWFkb25seSBtZXRhQ29uZmxpY3RzPzogUmVhZG9ubHlBcnJheTxNZXRhLlRyYWl0TWV0YUNvbmZsaWN0PlxufVxuXG4vKipcbiAqIEdyYXBoIE5vZGUgLyBFZGdlXHVGRjFBXG4gKiAtIE5vZGVzIHR5cGljYWxseSBjb3JyZXNwb25kIHRvIGZpZWxkcy5cbiAqIC0gRWRnZXMgcmVwcmVzZW50IGRlcGVuZGVuY2llcyBiZXR3ZWVuIGZpZWxkcywgb3IgYmV0d2VlbiBmaWVsZHMgYW5kIHJlc291cmNlcy5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBTdGF0ZVRyYWl0R3JhcGhOb2RlIHtcbiAgcmVhZG9ubHkgaWQ6IHN0cmluZ1xuICByZWFkb25seSBmaWVsZDogU3RhdGVUcmFpdEZpZWxkXG4gIHJlYWRvbmx5IHRyYWl0czogUmVhZG9ubHlBcnJheTxTdGF0ZVRyYWl0RmllbGRUcmFpdD5cbiAgcmVhZG9ubHkgbWV0YT86IE1ldGEuVHJhaXRNZXRhXG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgU3RhdGVUcmFpdEdyYXBoRWRnZSB7XG4gIHJlYWRvbmx5IGlkOiBzdHJpbmdcbiAgcmVhZG9ubHkgZnJvbTogc3RyaW5nXG4gIHJlYWRvbmx5IHRvOiBzdHJpbmdcbiAgcmVhZG9ubHkga2luZDogJ2NvbXB1dGVkJyB8ICdsaW5rJyB8ICdzb3VyY2UtZGVwJyB8ICdjaGVjay1kZXAnXG59XG5cbi8qKlxuICogU3RhdGVUcmFpdEdyYXBoXHVGRjFBXG4gKiAtIFN0cnVjdHVyYWwgdmlldyBvZiB0aGUgU3RhdGVUcmFpdCBlbmdpbmU6IGEgZ3JhcGggb2Ygbm9kZXMgYW5kIGRlcGVuZGVuY3kgZWRnZXMuXG4gKiAtIFVzZWQgYnkgRGV2dG9vbHMgLyBTdHVkaW8gLyBSdW50aW1lIGZvciBzdHJ1Y3R1cmFsIGFuYWx5c2lzIGFuZCB2aXN1YWxpemF0aW9uLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFN0YXRlVHJhaXRHcmFwaCB7XG4gIHJlYWRvbmx5IF90YWc6ICdTdGF0ZVRyYWl0R3JhcGgnXG4gIHJlYWRvbmx5IG5vZGVzOiBSZWFkb25seUFycmF5PFN0YXRlVHJhaXRHcmFwaE5vZGU+XG4gIHJlYWRvbmx5IGVkZ2VzOiBSZWFkb25seUFycmF5PFN0YXRlVHJhaXRHcmFwaEVkZ2U+XG4gIHJlYWRvbmx5IHJlc291cmNlczogUmVhZG9ubHlBcnJheTxTdGF0ZVRyYWl0UmVzb3VyY2U+XG4gIHJlYWRvbmx5IG1ldGE/OiB7XG4gICAgcmVhZG9ubHkgbW9kdWxlSWQ/OiBzdHJpbmdcbiAgICByZWFkb25seSB2ZXJzaW9uPzogc3RyaW5nXG4gIH1cbn1cblxuLyoqXG4gKiBTdGF0ZVRyYWl0UGxhblN0ZXBcdUZGMUFcbiAqIC0gVGhlIHNtYWxsZXN0IGluc3RydWN0aW9uIHVuaXQgdXNlZCBieSBTdGF0ZVRyYWl0Lmluc3RhbGwgLyBSdW50aW1lIGV4ZWN1dGlvbi5cbiAqIC0gRGVyaXZlZCBmcm9tIHRoZSBncmFwaDsgdXNlZCBhdCBydW50aW1lIHRvIGluc3RhbGwgd2F0Y2hlcnMgb3IgdHJpZ2dlciBleHRlcm5hbCBjYWxscy5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBTdGF0ZVRyYWl0UGxhblN0ZXAge1xuICByZWFkb25seSBpZDogc3RyaW5nXG4gIHJlYWRvbmx5IGtpbmQ6ICdjb21wdXRlZC11cGRhdGUnIHwgJ2xpbmstcHJvcGFnYXRlJyB8ICdzb3VyY2UtcmVmcmVzaCcgfCAnZXh0ZXJuYWwtc3RvcmUtc3luYycgfCAnY2hlY2stdmFsaWRhdGUnXG4gIHJlYWRvbmx5IHRhcmdldEZpZWxkUGF0aD86IHN0cmluZ1xuICByZWFkb25seSBzb3VyY2VGaWVsZFBhdGhzPzogUmVhZG9ubHlBcnJheTxzdHJpbmc+XG4gIHJlYWRvbmx5IHJlc291cmNlSWQ/OiBzdHJpbmdcbiAgcmVhZG9ubHkga2V5U2VsZWN0b3JJZD86IHN0cmluZ1xuICByZWFkb25seSBkZWJ1Z0luZm8/OiB7XG4gICAgcmVhZG9ubHkgZ3JhcGhOb2RlSWQ/OiBzdHJpbmdcbiAgICByZWFkb25seSBncmFwaEVkZ2VJZD86IHN0cmluZ1xuICB9XG59XG5cbi8qKlxuICogU3RhdGVUcmFpdFBsYW5cdUZGMUFcbiAqIC0gRXhlY3V0aW9uIHBsYW4gc3VtbWFyaXppbmcgYWxsIHRyYWl0IGJlaGF2aW9ycyBmb3IgYSBtb2R1bGUuXG4gKiAtIGluc3RhbGwgbW91bnRzIGJlaGF2aW9ycyBvbnRvIEJvdW5kIEFQSSAvIEVmZmVjdE9wIHBpcGVsaW5lcyBhY2NvcmRpbmcgdG8gdGhlIHBsYW4uXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgU3RhdGVUcmFpdFBsYW4ge1xuICByZWFkb25seSBfdGFnOiAnU3RhdGVUcmFpdFBsYW4nXG4gIHJlYWRvbmx5IG1vZHVsZUlkPzogc3RyaW5nXG4gIHJlYWRvbmx5IHN0ZXBzOiBSZWFkb25seUFycmF5PFN0YXRlVHJhaXRQbGFuU3RlcD5cbiAgcmVhZG9ubHkgbWV0YT86IFJlY29yZDxzdHJpbmcsIHVua25vd24+XG59XG5cbmV4cG9ydCB0eXBlIFN0YXRlVHJhaXRTY2hlbWFQYXRoS2luZCA9ICdmaWVsZFBhdGgnIHwgJ2RlcCcgfCAnbGlua19mcm9tJyB8ICdjaGVja193cml0ZWJhY2snXG5cbmV4cG9ydCBpbnRlcmZhY2UgU3RhdGVUcmFpdFNjaGVtYVBhdGhSZWYge1xuICByZWFkb25seSBraW5kOiBTdGF0ZVRyYWl0U2NoZW1hUGF0aEtpbmRcbiAgcmVhZG9ubHkgZW50cnlLaW5kOiBTdGF0ZVRyYWl0S2luZFxuICByZWFkb25seSBlbnRyeUZpZWxkUGF0aDogc3RyaW5nXG4gIHJlYWRvbmx5IHBhdGg6IHN0cmluZ1xuICByZWFkb25seSBydWxlTmFtZT86IHN0cmluZ1xufVxuXG4vKipcbiAqIFN0YXRlVHJhaXRQcm9ncmFtPFM+XHVGRjFBXG4gKiAtIFByb2dyYW0gb3V0cHV0IG9mIHRoZSBTdGF0ZVRyYWl0IGVuZ2luZTsgdGhlIHVuaWZpZWQgZW50cnlwb2ludCBmb3IgUnVudGltZSAvIERldnRvb2xzLlxuICogLSBzdGF0ZVNjaGVtYSBhbmQgc3BlYyBwcmVzZXJ2ZSBvcmlnaW5hbCBpbnB1dHM7IGdyYXBoL3BsYW4gYXJlIGludGVybmFsIElSLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFN0YXRlVHJhaXRQcm9ncmFtPFM+IHtcbiAgcmVhZG9ubHkgc3RhdGVTY2hlbWE6IFNjaGVtYS5TY2hlbWE8UywgYW55PlxuICByZWFkb25seSBzcGVjOiBTdGF0ZVRyYWl0U3BlYzxTPlxuICAvKipcbiAgICogUHJvZ3JhbS5lbnRyaWVzXHVGRjFBXG4gICAqIC0gTWluaW1hbCBydWxlIHNldCBub3JtYWxpemVkIGZyb20gc3BlYyAoaW5jbHVkaW5nIG5vZGUvbGlzdC8kcm9vdCkgZHVyaW5nIGJ1aWxkLlxuICAgKiAtIFBoYXNlIDIgZm9jdXNlcyBvbiBhIHJlYWRhYmxlL2RpYWdub3NhYmxlIHN0cnVjdHVyZTsgbGF0ZXIgcGhhc2VzIGFkZCBleGVjdXRpb24gYW5kIGNvbnZlcmdlIHNlbWFudGljcy5cbiAgICovXG4gIHJlYWRvbmx5IGVudHJpZXM6IFJlYWRvbmx5QXJyYXk8U3RhdGVUcmFpdEVudHJ5PGFueSwgc3RyaW5nPj5cbiAgcmVhZG9ubHkgZ3JhcGg6IFN0YXRlVHJhaXRHcmFwaFxuICByZWFkb25seSBwbGFuOiBTdGF0ZVRyYWl0UGxhblxuICByZWFkb25seSBjb252ZXJnZUlyPzogQ29udmVyZ2VTdGF0aWNJclJlZ2lzdHJ5XG4gIHJlYWRvbmx5IGNvbnZlcmdlRXhlY0lyPzogQ29udmVyZ2VFeGVjSXJcbiAgLyoqXG4gICAqIHNjaGVtYVBhdGhzXHVGRjFBXG4gICAqIC0gUGF0aCByZWZlcmVuY2VzIHRoYXQgbXVzdCBleGlzdCBpbiBzdGF0ZVNjaGVtYSwgY29sbGVjdGVkIGZyb20gZW50cmllcyBkdXJpbmcgYnVpbGQ7IGRldi1vbmx5IGRpYWdub3N0aWNzIChlLmcuIHNjaGVtYV9taXNtYXRjaCkuXG4gICAqIC0gV2hlbiBkaWFnbm9zdGljcz1vZmYsIHZhbGlkYXRpb24gY2FuIGJlIHNraXBwZWQgZW50aXJlbHkgdG8ga2VlcCBuZWFyLXplcm8gY29zdC5cbiAgICovXG4gIHJlYWRvbmx5IHNjaGVtYVBhdGhzPzogUmVhZG9ubHlBcnJheTxTdGF0ZVRyYWl0U2NoZW1hUGF0aFJlZj5cbn1cblxuLyoqXG4gKiBCdWlsZCBhIG5vcm1hbGl6ZWQgZW50cnkgbGlzdCBmcm9tIFN0YXRlVHJhaXRTcGVjLlxuICpcbiAqIC0gUGhhc2UgMjogc3VwcG9ydHMgc3RydWN0dXJhbCBleHBhbnNpb24gb2Ygbm9kZS9saXN0LyRyb290IGFuZCBmaWxscy9wcmVmaXhlcyBmaWVsZFBhdGgvZGVwcyB3aGVuIG5lY2Vzc2FyeS5cbiAqIC0gTGF0ZXIgcGhhc2VzIG1heSBleHRlbmQgdmFsaWRhdGlvbiBoZXJlIChlLmcuIGRldGVjdGluZyBkdXBsaWNhdGVzLCBvdmVycmlkZSBydWxlcywgZXRjLikuXG4gKi9cbmV4cG9ydCBjb25zdCBub3JtYWxpemVTcGVjID0gPFM+KHNwZWM6IFN0YXRlVHJhaXRTcGVjPFM+KTogUmVhZG9ubHlBcnJheTxTdGF0ZVRyYWl0RW50cnk8YW55LCBzdHJpbmc+PiA9PiB7XG4gIGNvbnN0IGVudHJpZXM6IEFycmF5PFN0YXRlVHJhaXRFbnRyeTxhbnksIHN0cmluZz4+ID0gW11cblxuICBjb25zdCBpc05vZGUgPSAodmFsdWU6IHVua25vd24pOiB2YWx1ZSBpcyBTdGF0ZVRyYWl0Tm9kZTxhbnksIGFueT4gPT5cbiAgICB0eXBlb2YgdmFsdWUgPT09ICdvYmplY3QnICYmIHZhbHVlICE9PSBudWxsICYmICh2YWx1ZSBhcyBhbnkpLl90YWcgPT09ICdTdGF0ZVRyYWl0Tm9kZSdcblxuICBjb25zdCBpc0xpc3QgPSAodmFsdWU6IHVua25vd24pOiB2YWx1ZSBpcyBTdGF0ZVRyYWl0TGlzdDxhbnk+ID0+XG4gICAgdHlwZW9mIHZhbHVlID09PSAnb2JqZWN0JyAmJiB2YWx1ZSAhPT0gbnVsbCAmJiAodmFsdWUgYXMgYW55KS5fdGFnID09PSAnU3RhdGVUcmFpdExpc3QnXG5cbiAgY29uc3Qgam9pblBhdGggPSAocHJlZml4OiBzdHJpbmcsIHN1ZmZpeDogc3RyaW5nKTogc3RyaW5nID0+IHtcbiAgICBpZiAoIXByZWZpeCkgcmV0dXJuIHN1ZmZpeFxuICAgIGlmICghc3VmZml4KSByZXR1cm4gcHJlZml4XG4gICAgcmV0dXJuIGAke3ByZWZpeH0uJHtzdWZmaXh9YFxuICB9XG5cbiAgY29uc3QgcHJlZml4RGVwcyA9IChkZXBzOiBSZWFkb25seUFycmF5PHN0cmluZz4gfCB1bmRlZmluZWQsIHByZWZpeDogc3RyaW5nKTogUmVhZG9ubHlBcnJheTxzdHJpbmc+ID0+IHtcbiAgICBpZiAoIWRlcHMgfHwgZGVwcy5sZW5ndGggPT09IDApIHJldHVybiBbXVxuICAgIHJldHVybiBkZXBzLm1hcCgoZCkgPT4gKHByZWZpeCA/IGpvaW5QYXRoKHByZWZpeCwgZCkgOiBkKSlcbiAgfVxuXG4gIGNvbnN0IG5vcm1hbGl6ZUVudHJ5ID0gKFxuICAgIGVudHJ5OiBTdGF0ZVRyYWl0RW50cnk8YW55LCBzdHJpbmc+LFxuICAgIGZpZWxkUGF0aDogc3RyaW5nLFxuICAgIGRlcFByZWZpeDogc3RyaW5nLFxuICApOiBTdGF0ZVRyYWl0RW50cnk8YW55LCBzdHJpbmc+ID0+IHtcbiAgICBpZiAoZW50cnkua2luZCA9PT0gJ2NvbXB1dGVkJykge1xuICAgICAgY29uc3QgbWV0YSA9IGVudHJ5Lm1ldGEgYXMgYW55XG4gICAgICBjb25zdCByYXdEZXBzID0gbWV0YS5kZXBzIGFzIFJlYWRvbmx5QXJyYXk8c3RyaW5nPiB8IHVuZGVmaW5lZFxuICAgICAgY29uc3QgZGVwcyA9IHJhd0RlcHMgIT09IHVuZGVmaW5lZCA/IHByZWZpeERlcHMocmF3RGVwcywgZGVwUHJlZml4KSA6IHVuZGVmaW5lZFxuICAgICAgcmV0dXJuIHtcbiAgICAgICAgLi4uKGVudHJ5IGFzIGFueSksXG4gICAgICAgIGZpZWxkUGF0aCxcbiAgICAgICAgbWV0YTogeyAuLi5tZXRhLCBkZXBzIH0sXG4gICAgICB9XG4gICAgfVxuICAgIGlmIChlbnRyeS5raW5kID09PSAnc291cmNlJykge1xuICAgICAgY29uc3QgbWV0YSA9IGVudHJ5Lm1ldGEgYXMgYW55XG4gICAgICBjb25zdCByYXdEZXBzID0gbWV0YS5kZXBzIGFzIFJlYWRvbmx5QXJyYXk8c3RyaW5nPiB8IHVuZGVmaW5lZFxuICAgICAgY29uc3QgZGVwcyA9IHJhd0RlcHMgIT09IHVuZGVmaW5lZCA/IHByZWZpeERlcHMocmF3RGVwcywgZGVwUHJlZml4KSA6IHVuZGVmaW5lZFxuICAgICAgcmV0dXJuIHtcbiAgICAgICAgLi4uKGVudHJ5IGFzIGFueSksXG4gICAgICAgIGZpZWxkUGF0aCxcbiAgICAgICAgbWV0YTogeyAuLi5tZXRhLCBkZXBzLCBfZmllbGRQYXRoOiBmaWVsZFBhdGggfSxcbiAgICAgIH1cbiAgICB9XG4gICAgaWYgKGVudHJ5LmtpbmQgPT09ICdleHRlcm5hbFN0b3JlJykge1xuICAgICAgY29uc3QgbWV0YSA9IGVudHJ5Lm1ldGEgYXMgYW55XG4gICAgICByZXR1cm4ge1xuICAgICAgICAuLi4oZW50cnkgYXMgYW55KSxcbiAgICAgICAgZmllbGRQYXRoLFxuICAgICAgICBtZXRhOiB7IC4uLm1ldGEsIF9maWVsZFBhdGg6IGZpZWxkUGF0aCB9LFxuICAgICAgfVxuICAgIH1cbiAgICBpZiAoZW50cnkua2luZCA9PT0gJ2xpbmsnKSB7XG4gICAgICBjb25zdCBtZXRhID0gZW50cnkubWV0YSBhcyBhbnlcbiAgICAgIGNvbnN0IGZyb20gPSBwcmVmaXhEZXBzKFttZXRhLmZyb20gYXMgc3RyaW5nXSwgZGVwUHJlZml4KVswXSA/PyBtZXRhLmZyb21cbiAgICAgIHJldHVybiB7XG4gICAgICAgIC4uLihlbnRyeSBhcyBhbnkpLFxuICAgICAgICBmaWVsZFBhdGgsXG4gICAgICAgIG1ldGE6IHsgLi4ubWV0YSwgZnJvbSB9LFxuICAgICAgfVxuICAgIH1cbiAgICAvLyBjaGVjazogUGhhc2UgMiBhZGp1c3RzIGZpZWxkUGF0aCBvbmx5OyBkZXBzIGFyZSBzdGlsbCBjb2xsZWN0ZWQgZnJvbSBtZXRhLnJ1bGVzIGR1cmluZyBidWlsZC5cbiAgICByZXR1cm4ge1xuICAgICAgLi4uKGVudHJ5IGFzIGFueSksXG4gICAgICBmaWVsZFBhdGgsXG4gICAgfVxuICB9XG5cbiAgY29uc3QgZXhwYW5kTm9kZSA9IChcbiAgICBzY29wZUlkOiBzdHJpbmcsXG4gICAgam9pblByZWZpeDogc3RyaW5nLFxuICAgIG5vZGU6IFN0YXRlVHJhaXROb2RlPGFueSwgYW55PixcbiAgICBvcHRpb25zPzoge1xuICAgICAgLyoqXG4gICAgICAgKiBQcmVmaXggZm9yIGNoZWNrIGRlcHM6IGRlZmF1bHQgc2VtYW50aWNzIGZvciBsaXN0LXNjb3BlIGNoZWNrcyAoZGVwcyBhcmUgcmVsYXRpdmUgdG8gYSByb3cgaXRlbSByYXRoZXIgdGhhbiB0aGUgbGlzdCByb290KS5cbiAgICAgICAqXG4gICAgICAgKiAtIGl0ZW0gc2NvcGU6IGRlcHNQcmVmaXggPSBgJHtsaXN0UGF0aH1bXWAgKG1hdGNoZXMgam9pblByZWZpeCkuXG4gICAgICAgKiAtIGxpc3Qgc2NvcGU6IGZpZWxkUGF0aCA9IGAke2xpc3RQYXRofWAsIGJ1dCBkZXBzUHJlZml4IHNob3VsZCBiZSBgJHtsaXN0UGF0aH1bXWAuXG4gICAgICAgKi9cbiAgICAgIHJlYWRvbmx5IGNoZWNrRGVwc1ByZWZpeD86IHN0cmluZ1xuICAgIH0sXG4gICk6IHZvaWQgPT4ge1xuICAgIGNvbnN0IGFkZEVudHJ5ID0gKHJlbGF0aXZlVGFyZ2V0OiBzdHJpbmcsIHJhdzogU3RhdGVUcmFpdEVudHJ5PGFueSwgc3RyaW5nPik6IHZvaWQgPT4ge1xuICAgICAgY29uc3QgcmVsID0gKHJhdyBhcyBhbnkpLmZpZWxkUGF0aCA/PyByZWxhdGl2ZVRhcmdldFxuICAgICAgY29uc3QgZmllbGRQYXRoID0gam9pblByZWZpeCA/IGpvaW5QYXRoKGpvaW5QcmVmaXgsIFN0cmluZyhyZWwpKSA6IFN0cmluZyhyZWwpXG4gICAgICBlbnRyaWVzLnB1c2gobm9ybWFsaXplRW50cnkocmF3LCBmaWVsZFBhdGgsIGpvaW5QcmVmaXgpKVxuICAgIH1cblxuICAgIGNvbnN0IGV4cGFuZE1heWJlUmVjb3JkID0gKFxuICAgICAgdmFsdWU6IFN0YXRlVHJhaXRFbnRyeTxhbnksIGFueT4gfCBSZWFkb25seTxSZWNvcmQ8c3RyaW5nLCBTdGF0ZVRyYWl0RW50cnk8YW55LCBhbnk+Pj4gfCB1bmRlZmluZWQsXG4gICAgKTogdm9pZCA9PiB7XG4gICAgICBpZiAoIXZhbHVlKSByZXR1cm5cbiAgICAgIGlmICh0eXBlb2YgKHZhbHVlIGFzIGFueSkua2luZCA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgYWRkRW50cnkoJycsIHZhbHVlIGFzIGFueSlcbiAgICAgICAgcmV0dXJuXG4gICAgICB9XG4gICAgICBjb25zdCByZWNvcmQgPSB2YWx1ZSBhcyBSZWFkb25seTxSZWNvcmQ8c3RyaW5nLCBTdGF0ZVRyYWl0RW50cnk8YW55LCBhbnk+Pj5cbiAgICAgIGZvciAoY29uc3Qga2V5IGluIHJlY29yZCkge1xuICAgICAgICBpZiAoIU9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChyZWNvcmQsIGtleSkpIGNvbnRpbnVlXG4gICAgICAgIGNvbnN0IGVudHJ5ID0gcmVjb3JkW2tleV1cbiAgICAgICAgaWYgKCFlbnRyeSkgY29udGludWVcbiAgICAgICAgYWRkRW50cnkoa2V5LCBlbnRyeSBhcyBhbnkpXG4gICAgICB9XG4gICAgfVxuXG4gICAgZXhwYW5kTWF5YmVSZWNvcmQobm9kZS5jb21wdXRlZClcbiAgICBleHBhbmRNYXliZVJlY29yZChub2RlLnNvdXJjZSlcbiAgICBleHBhbmRNYXliZVJlY29yZChub2RlLmxpbmspXG4gICAgZXhwYW5kTWF5YmVSZWNvcmQobm9kZS5leHRlcm5hbFN0b3JlKVxuXG4gICAgaWYgKG5vZGUuY2hlY2spIHtcbiAgICAgIGNvbnN0IHJ1bGVzOiBSZWNvcmQ8c3RyaW5nLCBDaGVja1J1bGU8YW55LCBhbnk+PiA9IHt9XG4gICAgICBjb25zdCBjaGVja0RlcHNQcmVmaXggPSBvcHRpb25zPy5jaGVja0RlcHNQcmVmaXggPz8gKGpvaW5QcmVmaXguZW5kc1dpdGgoJ1tdJykgPyBqb2luUHJlZml4IDogJycpXG5cbiAgICAgIGNvbnN0IHByZWZpeENoZWNrRGVwcyA9IChkZXBzOiBSZWFkb25seUFycmF5PHN0cmluZz4gfCB1bmRlZmluZWQpOiBSZWFkb25seUFycmF5PHN0cmluZz4gPT4ge1xuICAgICAgICBpZiAoIWRlcHMgfHwgZGVwcy5sZW5ndGggPT09IDApIHJldHVybiBbXVxuICAgICAgICByZXR1cm4gZGVwcy5tYXAoKGQpID0+IChkID09PSAnJyA/IHNjb3BlSWQgOiBjaGVja0RlcHNQcmVmaXggPyBqb2luUGF0aChjaGVja0RlcHNQcmVmaXgsIGQpIDogZCkpXG4gICAgICB9XG4gICAgICBmb3IgKGNvbnN0IG5hbWUgb2YgT2JqZWN0LmtleXMobm9kZS5jaGVjaykpIHtcbiAgICAgICAgY29uc3QgcnVsZSA9IChub2RlLmNoZWNrIGFzIGFueSlbbmFtZV0gYXMgQ2hlY2tSdWxlPGFueSwgYW55PlxuICAgICAgICBpZiAodHlwZW9mIHJ1bGUgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICBydWxlc1tuYW1lXSA9IHJ1bGVcbiAgICAgICAgICBjb250aW51ZVxuICAgICAgICB9XG4gICAgICAgIGlmIChydWxlICYmIHR5cGVvZiBydWxlID09PSAnb2JqZWN0Jykge1xuICAgICAgICAgIGNvbnN0IG1ldGEgPSBNZXRhLnNhbml0aXplKChydWxlIGFzIGFueSkubWV0YSlcbiAgICAgICAgICBydWxlc1tuYW1lXSA9IHtcbiAgICAgICAgICAgIC4uLnJ1bGUsXG4gICAgICAgICAgICBkZXBzOiBwcmVmaXhDaGVja0RlcHMocnVsZS5kZXBzKSxcbiAgICAgICAgICAgIG1ldGEsXG4gICAgICAgICAgfVxuICAgICAgICAgIGNvbnRpbnVlXG4gICAgICAgIH1cbiAgICAgICAgLy8gSW52YWxpZCBpbnB1dDogaWdub3JlIChsYXRlciBwaGFzZXMgbWF5IHByb21vdGUgdGhpcyBpbnRvIGEgYnVpbGQtdGltZSBjb25maWcgZXJyb3IpLlxuICAgICAgfVxuXG4gICAgICBlbnRyaWVzLnB1c2goe1xuICAgICAgICBmaWVsZFBhdGg6IHNjb3BlSWQsXG4gICAgICAgIGtpbmQ6ICdjaGVjaycsXG4gICAgICAgIG1ldGE6IHtcbiAgICAgICAgICBydWxlcyxcbiAgICAgICAgICB3cml0ZWJhY2s6IHsga2luZDogJ2Vycm9ycycgfSxcbiAgICAgICAgfSxcbiAgICAgIH0gYXMgU3RhdGVUcmFpdEVudHJ5PGFueSwgYW55PilcbiAgICB9XG4gIH1cblxuICBmb3IgKGNvbnN0IGtleSBpbiBzcGVjKSB7XG4gICAgaWYgKCFPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoc3BlYywga2V5KSkgY29udGludWVcbiAgICBjb25zdCByYXcgPSBzcGVjW2tleSBhcyBrZXlvZiB0eXBlb2Ygc3BlY10gYXMgU3RhdGVUcmFpdFNwZWNWYWx1ZTxTLCBhbnk+IHwgdW5kZWZpbmVkXG4gICAgaWYgKCFyYXcpIGNvbnRpbnVlXG5cbiAgICBpZiAoaXNMaXN0KHJhdykpIHtcbiAgICAgIGNvbnN0IGxpc3RQYXRoID0ga2V5XG4gICAgICBpZiAocmF3Lml0ZW0pIHtcbiAgICAgICAgZXhwYW5kTm9kZShgJHtsaXN0UGF0aH1bXWAsIGAke2xpc3RQYXRofVtdYCwgcmF3Lml0ZW0pXG4gICAgICB9XG4gICAgICBpZiAocmF3Lmxpc3QpIHtcbiAgICAgICAgZXhwYW5kTm9kZShsaXN0UGF0aCwgbGlzdFBhdGgsIHJhdy5saXN0LCB7XG4gICAgICAgICAgY2hlY2tEZXBzUHJlZml4OiBgJHtsaXN0UGF0aH1bXWAsXG4gICAgICAgIH0pXG4gICAgICB9XG4gICAgICBjb250aW51ZVxuICAgIH1cblxuICAgIGlmIChpc05vZGUocmF3KSkge1xuICAgICAgaWYgKGtleSA9PT0gJyRyb290Jykge1xuICAgICAgICBleHBhbmROb2RlKCckcm9vdCcsICcnLCByYXcpXG4gICAgICB9IGVsc2Uge1xuICAgICAgICBleHBhbmROb2RlKGtleSwga2V5LCByYXcpXG4gICAgICB9XG4gICAgICBjb250aW51ZVxuICAgIH1cblxuICAgIGNvbnN0IGVudHJ5ID0gcmF3IGFzIGFueSBhcyBTdGF0ZVRyYWl0RW50cnk8YW55LCBzdHJpbmc+XG4gICAgY29uc3QgZmllbGRQYXRoID0gKGVudHJ5IGFzIGFueSkuZmllbGRQYXRoID8/IGtleVxuICAgIGVudHJpZXMucHVzaChub3JtYWxpemVFbnRyeShlbnRyeSwgU3RyaW5nKGZpZWxkUGF0aCksICcnKSlcbiAgfVxuXG4gIHJldHVybiBlbnRyaWVzXG59XG5cbi8qKlxuICogY29sbGVjdE5vZGVNZXRhXHVGRjFBXG4gKiAtIEV4dHJhY3QgU3RhdGVUcmFpdE5vZGUubWV0YSAod2hpdGVsaXN0ZWQgZmllbGRzKSBmcm9tIFN0YXRlVHJhaXRTcGVjIGZvciBkZXZ0b29scyBzdHJ1Y3R1cmFsIGRpc3BsYXkuXG4gKiAtIG1ldGEgaXMgZm9yIGRpYWdub3N0aWNzL2Rpc3BsYXkgb25seSBhbmQgZG9lcyBub3QgcGFydGljaXBhdGUgaW4gcnVudGltZSBzZW1hbnRpY3MuXG4gKi9cbmV4cG9ydCBjb25zdCBjb2xsZWN0Tm9kZU1ldGEgPSA8Uz4oc3BlYzogU3RhdGVUcmFpdFNwZWM8Uz4pOiBSZWFkb25seU1hcDxzdHJpbmcsIE1ldGEuVHJhaXRNZXRhPiA9PiB7XG4gIGNvbnN0IG91dCA9IG5ldyBNYXA8c3RyaW5nLCBNZXRhLlRyYWl0TWV0YT4oKVxuXG4gIGNvbnN0IGlzTm9kZSA9ICh2YWx1ZTogdW5rbm93bik6IHZhbHVlIGlzIFN0YXRlVHJhaXROb2RlPGFueSwgYW55PiA9PlxuICAgIHR5cGVvZiB2YWx1ZSA9PT0gJ29iamVjdCcgJiYgdmFsdWUgIT09IG51bGwgJiYgKHZhbHVlIGFzIGFueSkuX3RhZyA9PT0gJ1N0YXRlVHJhaXROb2RlJ1xuXG4gIGNvbnN0IGlzTGlzdCA9ICh2YWx1ZTogdW5rbm93bik6IHZhbHVlIGlzIFN0YXRlVHJhaXRMaXN0PGFueT4gPT5cbiAgICB0eXBlb2YgdmFsdWUgPT09ICdvYmplY3QnICYmIHZhbHVlICE9PSBudWxsICYmICh2YWx1ZSBhcyBhbnkpLl90YWcgPT09ICdTdGF0ZVRyYWl0TGlzdCdcblxuICBjb25zdCBhZGQgPSAoc2NvcGVJZDogc3RyaW5nLCBub2RlOiBTdGF0ZVRyYWl0Tm9kZTxhbnksIGFueT4pOiB2b2lkID0+IHtcbiAgICBjb25zdCBtZXRhID0gTWV0YS5zYW5pdGl6ZShub2RlLm1ldGEpXG4gICAgaWYgKG1ldGEpIG91dC5zZXQoc2NvcGVJZCwgbWV0YSlcbiAgfVxuXG4gIGZvciAoY29uc3Qga2V5IGluIHNwZWMpIHtcbiAgICBpZiAoIU9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChzcGVjLCBrZXkpKSBjb250aW51ZVxuICAgIGNvbnN0IHJhdyA9IHNwZWNba2V5IGFzIGtleW9mIHR5cGVvZiBzcGVjXSBhcyBTdGF0ZVRyYWl0U3BlY1ZhbHVlPFMsIGFueT4gfCB1bmRlZmluZWRcbiAgICBpZiAoIXJhdykgY29udGludWVcblxuICAgIGlmIChpc0xpc3QocmF3KSkge1xuICAgICAgY29uc3QgbGlzdFBhdGggPSBrZXlcbiAgICAgIGlmIChyYXcuaXRlbSkgYWRkKGAke2xpc3RQYXRofVtdYCwgcmF3Lml0ZW0pXG4gICAgICBpZiAocmF3Lmxpc3QpIGFkZChsaXN0UGF0aCwgcmF3Lmxpc3QpXG4gICAgICBjb250aW51ZVxuICAgIH1cblxuICAgIGlmIChpc05vZGUocmF3KSkge1xuICAgICAgaWYgKGtleSA9PT0gJyRyb290JykgYWRkKCckcm9vdCcsIHJhdylcbiAgICAgIGVsc2UgYWRkKGtleSwgcmF3KVxuICAgICAgY29udGludWVcbiAgICB9XG4gIH1cblxuICByZXR1cm4gb3V0XG59XG5cbi8vIC0tLS0gQ29udmVyZ2UgKDAxMykgZXZpZGVuY2UgbW9kZWwgLS0tLVxuXG5leHBvcnQgdHlwZSBUcmFpdENvbnZlcmdlUmVxdWVzdGVkTW9kZSA9ICdhdXRvJyB8ICdmdWxsJyB8ICdkaXJ0eSdcbmV4cG9ydCB0eXBlIFRyYWl0Q29udmVyZ2VFeGVjdXRlZE1vZGUgPSAnZnVsbCcgfCAnZGlydHknXG5leHBvcnQgdHlwZSBUcmFpdENvbnZlcmdlT3V0Y29tZSA9ICdDb252ZXJnZWQnIHwgJ05vb3AnIHwgJ0RlZ3JhZGVkJ1xuXG5leHBvcnQgdHlwZSBUcmFpdENvbnZlcmdlQ29uZmlnU2NvcGUgPSAncHJvdmlkZXInIHwgJ3J1bnRpbWVfbW9kdWxlJyB8ICdydW50aW1lX2RlZmF1bHQnIHwgJ2J1aWx0aW4nXG5cbmV4cG9ydCB0eXBlIFRyYWl0Q29udmVyZ2VSZWFzb24gPVxuICB8ICdjb2xkX3N0YXJ0J1xuICB8ICdjYWNoZV9oaXQnXG4gIHwgJ2NhY2hlX21pc3MnXG4gIHwgJ2J1ZGdldF9jdXRvZmYnXG4gIHwgJ25lYXJfZnVsbCdcbiAgfCAndW5rbm93bl93cml0ZSdcbiAgfCAnZGlydHlfYWxsJ1xuICB8ICdnZW5lcmF0aW9uX2J1bXBlZCdcbiAgfCAnbG93X2hpdF9yYXRlX3Byb3RlY3Rpb24nXG4gIHwgJ21vZHVsZV9vdmVycmlkZSdcbiAgfCAndGltZV9zbGljaW5nX2ltbWVkaWF0ZSdcbiAgfCAndGltZV9zbGljaW5nX2RlZmVycmVkJ1xuXG5leHBvcnQgaW50ZXJmYWNlIFRyYWl0Q29udmVyZ2VTdGVwU3RhdHMge1xuICByZWFkb25seSB0b3RhbFN0ZXBzOiBudW1iZXJcbiAgcmVhZG9ubHkgZXhlY3V0ZWRTdGVwczogbnVtYmVyXG4gIHJlYWRvbmx5IHNraXBwZWRTdGVwczogbnVtYmVyXG4gIHJlYWRvbmx5IGNoYW5nZWRTdGVwczogbnVtYmVyXG4gIHJlYWRvbmx5IGFmZmVjdGVkU3RlcHM/OiBudW1iZXJcbn1cblxuZXhwb3J0IGludGVyZmFjZSBUcmFpdENvbnZlcmdlRGlydHlTdW1tYXJ5IHtcbiAgcmVhZG9ubHkgZGlydHlBbGw6IGJvb2xlYW5cbiAgcmVhZG9ubHkgcmVhc29uPzogRGlydHlBbGxSZWFzb25cbiAgcmVhZG9ubHkgcm9vdENvdW50PzogbnVtYmVyXG4gIHJlYWRvbmx5IHJvb3RJZHM/OiBSZWFkb25seUFycmF5PG51bWJlcj5cbiAgcmVhZG9ubHkgcm9vdElkc1RydW5jYXRlZD86IGJvb2xlYW5cbn1cblxuZXhwb3J0IGludGVyZmFjZSBUcmFpdENvbnZlcmdlUGxhbkNhY2hlRXZpZGVuY2Uge1xuICByZWFkb25seSBjYXBhY2l0eTogbnVtYmVyXG4gIHJlYWRvbmx5IHNpemU6IG51bWJlclxuICByZWFkb25seSBoaXRzOiBudW1iZXJcbiAgcmVhZG9ubHkgbWlzc2VzOiBudW1iZXJcbiAgcmVhZG9ubHkgZXZpY3RzOiBudW1iZXJcbiAgcmVhZG9ubHkgaGl0OiBib29sZWFuXG4gIHJlYWRvbmx5IGtleVNpemU/OiBudW1iZXJcbiAgcmVhZG9ubHkgbWlzc1JlYXNvbj86ICdjb2xkX3N0YXJ0JyB8ICdnZW5lcmF0aW9uX2J1bXBlZCcgfCAnbm90X2NhY2hlZCcgfCAndW5rbm93bidcbiAgcmVhZG9ubHkgZGlzYWJsZWQ/OiBib29sZWFuXG4gIHJlYWRvbmx5IGRpc2FibGVSZWFzb24/OiAnbG93X2hpdF9yYXRlJyB8ICdnZW5lcmF0aW9uX3RocmFzaCcgfCAnbWFudWFsX292ZXJyaWRlJyB8ICd1bmtub3duJ1xufVxuXG5leHBvcnQgdHlwZSBUcmFpdENvbnZlcmdlR2VuZXJhdGlvbkJ1bXBSZWFzb24gPVxuICB8ICd3cml0ZXJzX2NoYW5nZWQnXG4gIHwgJ2RlcHNfY2hhbmdlZCdcbiAgfCAnbG9naWNfaW5zdGFsbGVkJ1xuICB8ICdsb2dpY191bmluc3RhbGxlZCdcbiAgfCAnaW1wb3J0c19jaGFuZ2VkJ1xuICB8ICd1bmtub3duJ1xuXG5leHBvcnQgaW50ZXJmYWNlIFRyYWl0Q29udmVyZ2VHZW5lcmF0aW9uRXZpZGVuY2Uge1xuICByZWFkb25seSBnZW5lcmF0aW9uOiBudW1iZXJcbiAgcmVhZG9ubHkgZ2VuZXJhdGlvbkJ1bXBDb3VudD86IG51bWJlclxuICByZWFkb25seSBsYXN0QnVtcFJlYXNvbj86IFRyYWl0Q29udmVyZ2VHZW5lcmF0aW9uQnVtcFJlYXNvblxufVxuXG5leHBvcnQgaW50ZXJmYWNlIFRyYWl0Q29udmVyZ2VTdGF0aWNJckV2aWRlbmNlIHtcbiAgcmVhZG9ubHkgZmllbGRQYXRoQ291bnQ6IG51bWJlclxuICByZWFkb25seSBzdGVwQ291bnQ6IG51bWJlclxuICByZWFkb25seSBidWlsZER1cmF0aW9uTXM/OiBudW1iZXJcbn1cblxuZXhwb3J0IGludGVyZmFjZSBUcmFpdENvbnZlcmdlSG90c3BvdCB7XG4gIHJlYWRvbmx5IGtpbmQ/OiBzdHJpbmdcbiAgcmVhZG9ubHkgc3RlcElkOiBudW1iZXJcbiAgcmVhZG9ubHkgb3V0RmllbGRQYXRoSWQ/OiBudW1iZXJcbiAgcmVhZG9ubHkgZHVyYXRpb25NczogbnVtYmVyXG4gIHJlYWRvbmx5IGNoYW5nZWQ6IGJvb2xlYW5cbn1cblxuZXhwb3J0IGludGVyZmFjZSBUcmFpdENvbnZlcmdlVGltZVNsaWNpbmdTdW1tYXJ5IHtcbiAgcmVhZG9ubHkgc2NvcGU6ICdhbGwnIHwgJ2ltbWVkaWF0ZScgfCAnZGVmZXJyZWQnXG4gIHJlYWRvbmx5IGltbWVkaWF0ZVN0ZXBDb3VudDogbnVtYmVyXG4gIHJlYWRvbmx5IGRlZmVycmVkU3RlcENvdW50OiBudW1iZXJcbn1cblxuZXhwb3J0IGludGVyZmFjZSBUcmFpdENvbnZlcmdlRGlhZ25vc3RpY3NTYW1wbGluZ1N1bW1hcnkge1xuICAvKipcbiAgICogRGV0ZXJtaW5pc3RpYyBzYW1wbGluZzogdXNlIHN0YWJsZSB0eG5TZXEgYXMgYW4gYW5jaG9yIGFuZCBzYW1wbGUgZXZlcnkgTiB0cmFuc2FjdGlvbnMuXG4gICAqIC0gc2FtcGxlZD10cnVlIG1lYW5zIHRoaXMgaW52b2NhdGlvbiBjYXB0dXJlZCBwZXItc3RlcCB0aW1pbmdzIGFuZCBwcm9kdWNlZCBob3RzcG90cy5cbiAgICovXG4gIHJlYWRvbmx5IHN0cmF0ZWd5OiAndHhuU2VxX2ludGVydmFsJ1xuICByZWFkb25seSBzYW1wbGVFdmVyeU46IG51bWJlclxuICByZWFkb25seSB0b3BLOiBudW1iZXJcbiAgcmVhZG9ubHkgc2FtcGxlZDogYm9vbGVhblxufVxuXG5leHBvcnQgaW50ZXJmYWNlIFRyYWl0Q29udmVyZ2VEZWNpc2lvblN1bW1hcnkge1xuICByZWFkb25seSByZXF1ZXN0ZWRNb2RlOiBUcmFpdENvbnZlcmdlUmVxdWVzdGVkTW9kZVxuICByZWFkb25seSBleGVjdXRlZE1vZGU6IFRyYWl0Q29udmVyZ2VFeGVjdXRlZE1vZGVcbiAgcmVhZG9ubHkgb3V0Y29tZTogVHJhaXRDb252ZXJnZU91dGNvbWVcbiAgcmVhZG9ubHkgY29uZmlnU2NvcGU6IFRyYWl0Q29udmVyZ2VDb25maWdTY29wZVxuICByZWFkb25seSBzdGF0aWNJckRpZ2VzdDogc3RyaW5nXG4gIHJlYWRvbmx5IGV4ZWN1dGlvbkJ1ZGdldE1zOiBudW1iZXJcbiAgcmVhZG9ubHkgZXhlY3V0aW9uRHVyYXRpb25NczogbnVtYmVyXG4gIHJlYWRvbmx5IGRlY2lzaW9uQnVkZ2V0TXM/OiBudW1iZXJcbiAgcmVhZG9ubHkgZGVjaXNpb25EdXJhdGlvbk1zPzogbnVtYmVyXG4gIHJlYWRvbmx5IHJlYXNvbnM6IFJlYWRvbmx5QXJyYXk8VHJhaXRDb252ZXJnZVJlYXNvbj5cbiAgcmVhZG9ubHkgc3RlcFN0YXRzOiBUcmFpdENvbnZlcmdlU3RlcFN0YXRzXG4gIHJlYWRvbmx5IGRpcnR5PzogVHJhaXRDb252ZXJnZURpcnR5U3VtbWFyeVxuICByZWFkb25seSBjYWNoZT86IFRyYWl0Q29udmVyZ2VQbGFuQ2FjaGVFdmlkZW5jZVxuICByZWFkb25seSBnZW5lcmF0aW9uPzogVHJhaXRDb252ZXJnZUdlbmVyYXRpb25FdmlkZW5jZVxuICByZWFkb25seSBzdGF0aWNJcj86IFRyYWl0Q29udmVyZ2VTdGF0aWNJckV2aWRlbmNlXG4gIHJlYWRvbmx5IHRpbWVTbGljaW5nPzogVHJhaXRDb252ZXJnZVRpbWVTbGljaW5nU3VtbWFyeVxuICByZWFkb25seSB0aHJlc2hvbGRzPzogeyByZWFkb25seSBmbG9vclJhdGlvPzogbnVtYmVyIH1cbiAgcmVhZG9ubHkgZGlhZ25vc3RpY3NTYW1wbGluZz86IFRyYWl0Q29udmVyZ2VEaWFnbm9zdGljc1NhbXBsaW5nU3VtbWFyeVxuICByZWFkb25seSB0b3AzPzogUmVhZG9ubHlBcnJheTxUcmFpdENvbnZlcmdlSG90c3BvdD5cbn1cbiIsICJpbXBvcnQgeyBFZmZlY3QsIEZpYmVyLCBGaWJlclJlZiwgT3B0aW9uIH0gZnJvbSAnZWZmZWN0J1xuaW1wb3J0IHsgY3JlYXRlIH0gZnJvbSAnbXV0YXRpdmUnXG5pbXBvcnQgKiBhcyBFZmZlY3RPcCBmcm9tICcuLi9lZmZlY3Qtb3AuanMnXG5pbXBvcnQgeyBTbmFwc2hvdCwgaW50ZXJuYWwgYXMgUmVzb3VyY2VJbnRlcm5hbCwga2V5SGFzaCBhcyBoYXNoS2V5IH0gZnJvbSAnLi4vcmVzb3VyY2UuanMnXG5pbXBvcnQgKiBhcyBFZmZlY3RPcENvcmUgZnJvbSAnLi4vcnVudGltZS9jb3JlL0VmZmVjdE9wQ29yZS5qcydcbmltcG9ydCAqIGFzIERlYnVnIGZyb20gJy4uL3J1bnRpbWUvY29yZS9EZWJ1Z1NpbmsuanMnXG5pbXBvcnQgKiBhcyBUYXNrUnVubmVyIGZyb20gJy4uL3J1bnRpbWUvY29yZS9UYXNrUnVubmVyLmpzJ1xuaW1wb3J0IHsgaXNEZXZFbnYsIFJlcGxheU1vZGVDb25maWdUYWcgfSBmcm9tICcuLi9ydW50aW1lL2NvcmUvZW52LmpzJ1xuaW1wb3J0ICogYXMgUmVwbGF5TG9nIGZyb20gJy4uL3J1bnRpbWUvY29yZS9SZXBsYXlMb2cuanMnXG5pbXBvcnQgdHlwZSB7IFBhdGNoUmVhc29uIH0gZnJvbSAnLi4vcnVudGltZS9jb3JlL1N0YXRlVHJhbnNhY3Rpb24uanMnXG5pbXBvcnQgdHlwZSB7IEZpZWxkUGF0aCwgRmllbGRQYXRoSWQgfSBmcm9tICcuLi9maWVsZC1wYXRoLmpzJ1xuaW1wb3J0IHsgbm9ybWFsaXplRmllbGRQYXRoIH0gZnJvbSAnLi4vZmllbGQtcGF0aC5qcydcbmltcG9ydCB0eXBlIHsgQm91bmRBcGkgfSBmcm9tICcuLi9ydW50aW1lL2NvcmUvbW9kdWxlLmpzJ1xuaW1wb3J0IHsgZ2V0Qm91bmRJbnRlcm5hbHMgfSBmcm9tICcuLi9ydW50aW1lL2NvcmUvcnVudGltZUludGVybmFsc0FjY2Vzc29yLmpzJ1xuaW1wb3J0IHsgUnVuU2Vzc2lvblRhZyB9IGZyb20gJy4uL29ic2VydmFiaWxpdHkvcnVuU2Vzc2lvbi5qcydcbmltcG9ydCAqIGFzIERlcHNUcmFjZSBmcm9tICcuL2RlcHMtdHJhY2UuanMnXG5pbXBvcnQgKiBhcyBSb3dJZCBmcm9tICcuL3Jvd2lkLmpzJ1xuaW1wb3J0IHR5cGUgeyBTdGF0ZVRyYWl0RW50cnksIFN0YXRlVHJhaXRQbGFuU3RlcCwgU3RhdGVUcmFpdFByb2dyYW0gfSBmcm9tICcuL21vZGVsLmpzJ1xuXG5leHBvcnQgaW50ZXJmYWNlIFNvdXJjZVN5bmNDb250ZXh0PFM+IHtcbiAgcmVhZG9ubHkgbW9kdWxlSWQ/OiBzdHJpbmdcbiAgcmVhZG9ubHkgaW5zdGFuY2VJZD86IHN0cmluZ1xuICByZWFkb25seSBnZXREcmFmdDogKCkgPT4gU1xuICByZWFkb25seSBzZXREcmFmdDogKG5leHQ6IFMpID0+IHZvaWRcbiAgcmVhZG9ubHkgcmVjb3JkUGF0Y2g6IChcbiAgICBwYXRoOiBzdHJpbmcgfCBGaWVsZFBhdGggfCBGaWVsZFBhdGhJZCB8IHVuZGVmaW5lZCxcbiAgICByZWFzb246IFBhdGNoUmVhc29uLFxuICAgIGZyb20/OiB1bmtub3duLFxuICAgIHRvPzogdW5rbm93bixcbiAgICB0cmFpdE5vZGVJZD86IHN0cmluZyxcbiAgICBzdGVwSWQ/OiBudW1iZXIsXG4gICkgPT4gdm9pZFxufVxuXG5jb25zdCBvbmNlSW5SdW5TZXNzaW9uID0gKGtleTogc3RyaW5nKTogRWZmZWN0LkVmZmVjdDxib29sZWFuLCBuZXZlciwgYW55PiA9PlxuICBFZmZlY3Quc2VydmljZU9wdGlvbihSdW5TZXNzaW9uVGFnKS5waXBlKFxuICAgIEVmZmVjdC5tYXAoKG1heWJlKSA9PiAoT3B0aW9uLmlzU29tZShtYXliZSkgPyBtYXliZS52YWx1ZS5sb2NhbC5vbmNlKGtleSkgOiB0cnVlKSksXG4gIClcblxuY29uc3QgZm9ybWF0TGlzdCA9IChpdGVtczogUmVhZG9ubHlBcnJheTxzdHJpbmc+LCBsaW1pdCA9IDEwKTogc3RyaW5nID0+IHtcbiAgaWYgKGl0ZW1zLmxlbmd0aCA9PT0gMCkgcmV0dXJuICcnXG4gIGlmIChpdGVtcy5sZW5ndGggPD0gbGltaXQpIHJldHVybiBpdGVtcy5qb2luKCcsICcpXG4gIHJldHVybiBgJHtpdGVtcy5zbGljZSgwLCBsaW1pdCkuam9pbignLCAnKX0sIFx1MjAyNigrJHtpdGVtcy5sZW5ndGggLSBsaW1pdH0pYFxufVxuXG5jb25zdCBlbWl0RGVwc01pc21hdGNoID0gKHBhcmFtczoge1xuICByZWFkb25seSBtb2R1bGVJZD86IHN0cmluZ1xuICByZWFkb25seSBpbnN0YW5jZUlkPzogc3RyaW5nXG4gIHJlYWRvbmx5IGtpbmQ6ICdjb21wdXRlZCcgfCAnc291cmNlJ1xuICByZWFkb25seSBmaWVsZFBhdGg6IHN0cmluZ1xuICByZWFkb25seSBkaWZmOiBEZXBzVHJhY2UuRGVwc0RpZmZcbn0pOiBFZmZlY3QuRWZmZWN0PHZvaWQsIG5ldmVyLCBhbnk+ID0+XG4gIEVmZmVjdC5nZW4oZnVuY3Rpb24qICgpIHtcbiAgICBjb25zdCBrZXkgPSBgJHtwYXJhbXMuaW5zdGFuY2VJZCA/PyAndW5rbm93bid9Ojoke3BhcmFtcy5raW5kfTo6JHtwYXJhbXMuZmllbGRQYXRofWBcbiAgICBjb25zdCBzaG91bGRFbWl0ID0geWllbGQqIG9uY2VJblJ1blNlc3Npb24oYGRlcHNfbWlzbWF0Y2g6JHtrZXl9YClcbiAgICBpZiAoIXNob3VsZEVtaXQpIHJldHVyblxuXG4gICAgeWllbGQqIERlYnVnLnJlY29yZCh7XG4gICAgICB0eXBlOiAnZGlhZ25vc3RpYycsXG4gICAgICBtb2R1bGVJZDogcGFyYW1zLm1vZHVsZUlkLFxuICAgICAgaW5zdGFuY2VJZDogcGFyYW1zLmluc3RhbmNlSWQsXG4gICAgICBjb2RlOiAnc3RhdGVfdHJhaXQ6OmRlcHNfbWlzbWF0Y2gnLFxuICAgICAgc2V2ZXJpdHk6ICd3YXJuaW5nJyxcbiAgICAgIG1lc3NhZ2U6XG4gICAgICAgIGBbZGVwc10gJHtwYXJhbXMua2luZH0gXCIke3BhcmFtcy5maWVsZFBhdGh9XCIgZGVjbGFyZWQ9WyR7Zm9ybWF0TGlzdChwYXJhbXMuZGlmZi5kZWNsYXJlZCl9XSBgICtcbiAgICAgICAgYHJlYWRzPVske2Zvcm1hdExpc3QocGFyYW1zLmRpZmYucmVhZHMpfV0gbWlzc2luZz1bJHtmb3JtYXRMaXN0KHBhcmFtcy5kaWZmLm1pc3NpbmcpfV0gYCArXG4gICAgICAgIGB1bnVzZWQ9WyR7Zm9ybWF0TGlzdChwYXJhbXMuZGlmZi51bnVzZWQpfV1gLFxuICAgICAgaGludDpcbiAgICAgICAgJ2RlcHMgaXMgdGhlIHNpbmdsZSBzb3VyY2Ugb2YgdHJ1dGggZm9yIGRlcGVuZGVuY2llczogaW5jcmVtZW50YWwgc2NoZWR1bGluZyAvIHJldmVyc2UgY2xvc3VyZXMgLyBwZXJmb3JtYW5jZSBvcHRpbWl6YXRpb25zIHJlbHkgb24gZGVwcyBvbmx5LiAnICtcbiAgICAgICAgJ0tlZXAgZGVwcyBjb25zaXN0ZW50IHdpdGggYWN0dWFsIHJlYWRzOyBpZiB5b3UgcmVhbGx5IGRlcGVuZCBvbiB0aGUgd2hvbGUgb2JqZWN0LCBkZWNsYXJlIGEgY29hcnNlci1ncmFpbmVkIGRlcCAoZS5nLiBcInByb2ZpbGVcIikgdG8gY292ZXIgc3ViLWZpZWxkIHJlYWRzLicsXG4gICAgICBraW5kOiBgZGVwc19taXNtYXRjaDoke3BhcmFtcy5raW5kfWAsXG4gICAgfSlcbiAgfSlcblxuY29uc3QgZ2V0TWlkZGxld2FyZVN0YWNrID0gKCk6IEVmZmVjdC5FZmZlY3Q8RWZmZWN0T3AuTWlkZGxld2FyZVN0YWNrLCBuZXZlciwgYW55PiA9PlxuICBFZmZlY3Quc2VydmljZU9wdGlvbihFZmZlY3RPcENvcmUuRWZmZWN0T3BNaWRkbGV3YXJlVGFnKS5waXBlKFxuICAgIEVmZmVjdC5tYXAoKG1heWJlKSA9PiAoT3B0aW9uLmlzU29tZShtYXliZSkgPyBtYXliZS52YWx1ZS5zdGFjayA6IFtdKSksXG4gIClcblxuY29uc3QgcmVjb3JkVHJhaXRQYXRjaCA9IChcbiAgYm91bmQ6IEJvdW5kQXBpPGFueSwgYW55PixcbiAgcGF0aDogc3RyaW5nLFxuICByZWFzb246IFBhdGNoUmVhc29uLFxuICBmcm9tPzogdW5rbm93bixcbiAgdG8/OiB1bmtub3duLFxuICB0cmFpdE5vZGVJZD86IHN0cmluZyxcbik6IHZvaWQgPT4ge1xuICBjb25zdCBub3JtYWxpemVkID0gbm9ybWFsaXplRmllbGRQYXRoKHBhdGgpID8/IFtdXG4gIHRyeSB7XG4gICAgY29uc3QgaW50ZXJuYWxzID0gZ2V0Qm91bmRJbnRlcm5hbHMoYm91bmQgYXMgYW55KVxuICAgIGludGVybmFscy50eG4ucmVjb3JkU3RhdGVQYXRjaChub3JtYWxpemVkLCByZWFzb24sIGZyb20sIHRvLCB0cmFpdE5vZGVJZClcbiAgfSBjYXRjaCB7XG4gICAgLy8gbm8tb3AgZm9yIGxlZ2FjeS9tb2NrZWQgYm91bmRcbiAgfVxufVxuXG5jb25zdCByZWNvcmRSZXBsYXlFdmVudCA9IChib3VuZDogQm91bmRBcGk8YW55LCBhbnk+LCBldmVudDogUmVwbGF5TG9nLlJlcGxheUxvZ0V2ZW50KTogdm9pZCA9PiB7XG4gIHRyeSB7XG4gICAgY29uc3QgaW50ZXJuYWxzID0gZ2V0Qm91bmRJbnRlcm5hbHMoYm91bmQgYXMgYW55KVxuICAgIGludGVybmFscy50eG4ucmVjb3JkUmVwbGF5RXZlbnQoZXZlbnQpXG4gIH0gY2F0Y2gge1xuICAgIC8vIG5vLW9wIGZvciBsZWdhY3kvbW9ja2VkIGJvdW5kXG4gIH1cbn1cblxuY29uc3QgZ2V0Qm91bmRTY29wZSA9IChib3VuZDogQm91bmRBcGk8YW55LCBhbnk+KTogeyByZWFkb25seSBtb2R1bGVJZD86IHN0cmluZzsgcmVhZG9ubHkgaW5zdGFuY2VJZD86IHN0cmluZyB9ID0+IHtcbiAgdHJ5IHtcbiAgICBjb25zdCBpbnRlcm5hbHMgPSBnZXRCb3VuZEludGVybmFscyhib3VuZCBhcyBhbnkpXG4gICAgcmV0dXJuIHsgbW9kdWxlSWQ6IGludGVybmFscy5tb2R1bGVJZCwgaW5zdGFuY2VJZDogaW50ZXJuYWxzLmluc3RhbmNlSWQgfVxuICB9IGNhdGNoIHtcbiAgICByZXR1cm4geyBtb2R1bGVJZDogdW5kZWZpbmVkLCBpbnN0YW5jZUlkOiB1bmRlZmluZWQgfVxuICB9XG59XG5cbmNvbnN0IHNldFNuYXBzaG90SW5UeG4gPSAoXG4gIGJvdW5kOiBCb3VuZEFwaTxhbnksIGFueT4sXG4gIGZpZWxkUGF0aDogc3RyaW5nLFxuICBuZXh0OiB1bmtub3duLFxuICByZWFzb246IFBhdGNoUmVhc29uLFxuICBzdGVwSWQ6IHN0cmluZyxcbiAgdHJhaXROb2RlSWQ/OiBzdHJpbmcsXG4pOiBFZmZlY3QuRWZmZWN0PGJvb2xlYW4sIG5ldmVyLCBhbnk+ID0+XG4gIEVmZmVjdC5nZW4oZnVuY3Rpb24qICgpIHtcbiAgICBsZXQgd3JvdGUgPSBmYWxzZVxuICAgIHlpZWxkKiBib3VuZC5zdGF0ZS5tdXRhdGUoKGRyYWZ0KSA9PiB7XG4gICAgICBjb25zdCBwcmV2ID0gUm93SWQuZ2V0QXRQYXRoKGRyYWZ0LCBmaWVsZFBhdGgpXG4gICAgICBpZiAoT2JqZWN0LmlzKHByZXYsIG5leHQpKSByZXR1cm5cbiAgICAgIHdyb3RlID0gdHJ1ZVxuICAgICAgUm93SWQuc2V0QXRQYXRoTXV0YXRpbmcoZHJhZnQsIGZpZWxkUGF0aCwgbmV4dClcbiAgICAgIHJlY29yZFRyYWl0UGF0Y2goYm91bmQsIGZpZWxkUGF0aCwgcmVhc29uLCBwcmV2LCBuZXh0LCB0cmFpdE5vZGVJZClcbiAgICB9KVxuICAgIHJldHVybiB3cm90ZVxuICB9KVxuXG5jb25zdCB3cml0ZWJhY2tJZkN1cnJlbnRLZXlIYXNoID0gKFxuICBib3VuZDogQm91bmRBcGk8YW55LCBhbnk+LFxuICBmaWVsZFBhdGg6IHN0cmluZyxcbiAga2V5SGFzaDogc3RyaW5nLFxuICBuZXh0OiB1bmtub3duLFxuICByZWFzb246IFBhdGNoUmVhc29uLFxuICBzdGVwSWQ6IHN0cmluZyxcbiAgdHJhaXROb2RlSWQ/OiBzdHJpbmcsXG4gIHJlcGxheUV2ZW50PzogUmVwbGF5TG9nLlJlcGxheUxvZ0V2ZW50LFxuKTogRWZmZWN0LkVmZmVjdDxib29sZWFuLCBuZXZlciwgYW55PiA9PlxuICBFZmZlY3QuZ2VuKGZ1bmN0aW9uKiAoKSB7XG4gICAgbGV0IHdyb3RlID0gZmFsc2VcbiAgICB5aWVsZCogYm91bmQuc3RhdGUubXV0YXRlKChkcmFmdCkgPT4ge1xuICAgICAgY29uc3QgY3VycmVudCA9IFJvd0lkLmdldEF0UGF0aChkcmFmdCwgZmllbGRQYXRoKVxuICAgICAgY29uc3QgY3VycmVudEtleUhhc2ggPSBjdXJyZW50ICYmIHR5cGVvZiBjdXJyZW50ID09PSAnb2JqZWN0JyA/IChjdXJyZW50IGFzIGFueSkua2V5SGFzaCA6IHVuZGVmaW5lZFxuICAgICAgaWYgKGN1cnJlbnRLZXlIYXNoICE9PSBrZXlIYXNoKSByZXR1cm5cblxuICAgICAgY29uc3QgcHJldiA9IGN1cnJlbnRcbiAgICAgIGlmIChPYmplY3QuaXMocHJldiwgbmV4dCkpIHJldHVyblxuXG4gICAgICB3cm90ZSA9IHRydWVcbiAgICAgIFJvd0lkLnNldEF0UGF0aE11dGF0aW5nKGRyYWZ0LCBmaWVsZFBhdGgsIG5leHQpXG4gICAgICBpZiAocmVwbGF5RXZlbnQpIHtcbiAgICAgICAgcmVjb3JkUmVwbGF5RXZlbnQoYm91bmQsIHJlcGxheUV2ZW50KVxuICAgICAgfVxuICAgICAgcmVjb3JkVHJhaXRQYXRjaChib3VuZCwgZmllbGRQYXRoLCByZWFzb24sIHByZXYsIG5leHQsIHRyYWl0Tm9kZUlkKVxuICAgIH0pXG4gICAgcmV0dXJuIHdyb3RlXG4gIH0pXG5cbi8qKlxuICogc3luY0lkbGVJblRyYW5zYWN0aW9uXHVGRjFBXG4gKiAtIFN5bmNocm9ub3VzbHkgZXZhbHVhdGUgYWxsIHNvdXJjZS5rZXkoc3RhdGUpIHdpdGhpbiB0aGUgdHJhbnNhY3Rpb24gd2luZG93LlxuICogLSBJZiBhIGtleSBiZWNvbWVzIGVtcHR5ICh1bmRlZmluZWQpLCBzeW5jaHJvbm91c2x5IHJlc2V0IHRoZSBmaWVsZCB0byBhbiBpZGxlIHNuYXBzaG90IChhdm9pZCB0ZWFyaW5nKS5cbiAqL1xuZXhwb3J0IGNvbnN0IHN5bmNJZGxlSW5UcmFuc2FjdGlvbiA9IDxTIGV4dGVuZHMgb2JqZWN0PihcbiAgcHJvZ3JhbTogU3RhdGVUcmFpdFByb2dyYW08Uz4sXG4gIGN0eDogU291cmNlU3luY0NvbnRleHQ8Uz4sXG4pOiBFZmZlY3QuRWZmZWN0PHZvaWQ+ID0+XG4gIEVmZmVjdC5zeW5jKCgpID0+IHtcbiAgICBjb25zdCBkcmFmdCA9IGN0eC5nZXREcmFmdCgpIGFzIGFueVxuICAgIGNvbnN0IHVwZGF0ZXM6IEFycmF5PHsgcmVhZG9ubHkgZmllbGRQYXRoOiBzdHJpbmc7IHJlYWRvbmx5IHByZXY6IHVua25vd24gfT4gPSBbXVxuXG4gICAgZm9yIChjb25zdCBlbnRyeSBvZiBwcm9ncmFtLmVudHJpZXMpIHtcbiAgICAgIGlmIChlbnRyeS5raW5kICE9PSAnc291cmNlJykgY29udGludWVcbiAgICAgIGNvbnN0IGZpZWxkUGF0aCA9IGVudHJ5LmZpZWxkUGF0aFxuICAgICAgY29uc3QgbGlzdEl0ZW0gPSBSb3dJZC5wYXJzZUxpc3RJdGVtRmllbGRQYXRoKGZpZWxkUGF0aClcblxuICAgICAgaWYgKGxpc3RJdGVtKSB7XG4gICAgICAgIC8vIGxpc3QuaXRlbSBzY29wZTogZXZhbHVhdGUga2V5IHBlciByb3cgYnkgaW5kZXgsIGFuZCBzeW5jaHJvbm91c2x5IHdyaXRlIGJhY2sgaWRsZSBmb3IgaW5hY3RpdmUgcm93cy5cbiAgICAgICAgY29uc3QgbGlzdFZhbHVlID0gUm93SWQuZ2V0QXRQYXRoKGRyYWZ0LCBsaXN0SXRlbS5saXN0UGF0aClcbiAgICAgICAgY29uc3QgaXRlbXM6IFJlYWRvbmx5QXJyYXk8dW5rbm93bj4gPSBBcnJheS5pc0FycmF5KGxpc3RWYWx1ZSkgPyBsaXN0VmFsdWUgOiBbXVxuXG4gICAgICAgIGZvciAobGV0IGluZGV4ID0gMDsgaW5kZXggPCBpdGVtcy5sZW5ndGg7IGluZGV4KyspIHtcbiAgICAgICAgICBjb25zdCBpdGVtID0gaXRlbXNbaW5kZXhdXG5cbiAgICAgICAgICBsZXQga2V5OiB1bmtub3duXG4gICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGtleSA9IChlbnRyeS5tZXRhIGFzIGFueSkua2V5KGl0ZW0pXG4gICAgICAgICAgfSBjYXRjaCB7XG4gICAgICAgICAgICBjb250aW51ZVxuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmIChrZXkgIT09IHVuZGVmaW5lZCkgY29udGludWVcblxuICAgICAgICAgIGNvbnN0IGNvbmNyZXRlUGF0aCA9IFJvd0lkLnRvTGlzdEl0ZW1WYWx1ZVBhdGgobGlzdEl0ZW0ubGlzdFBhdGgsIGluZGV4LCBsaXN0SXRlbS5pdGVtUGF0aClcbiAgICAgICAgICBjb25zdCBwcmV2ID0gUm93SWQuZ2V0QXRQYXRoKGRyYWZ0LCBjb25jcmV0ZVBhdGgpXG4gICAgICAgICAgY29uc3QgcHJldlN0YXR1cyA9IHByZXYgJiYgdHlwZW9mIHByZXYgPT09ICdvYmplY3QnID8gKHByZXYgYXMgYW55KS5zdGF0dXMgOiB1bmRlZmluZWRcbiAgICAgICAgICBpZiAocHJldlN0YXR1cyA9PT0gJ2lkbGUnKSB7XG4gICAgICAgICAgICBjb25zdCBkYXRhID0gKHByZXYgYXMgYW55KT8uZGF0YVxuICAgICAgICAgICAgY29uc3QgZXJyb3IgPSAocHJldiBhcyBhbnkpPy5lcnJvclxuICAgICAgICAgICAgaWYgKGRhdGEgPT09IHVuZGVmaW5lZCAmJiBlcnJvciA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgIGNvbnRpbnVlXG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgdXBkYXRlcy5wdXNoKHsgZmllbGRQYXRoOiBjb25jcmV0ZVBhdGgsIHByZXYgfSlcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnRpbnVlXG4gICAgICB9XG5cbiAgICAgIGxldCBrZXk6IHVua25vd25cbiAgICAgIHRyeSB7XG4gICAgICAgIGtleSA9IChlbnRyeS5tZXRhIGFzIGFueSkua2V5KGRyYWZ0KVxuICAgICAgfSBjYXRjaCB7XG4gICAgICAgIGNvbnRpbnVlXG4gICAgICB9XG5cbiAgICAgIGlmIChrZXkgIT09IHVuZGVmaW5lZCkgY29udGludWVcblxuICAgICAgY29uc3QgcHJldiA9IFJvd0lkLmdldEF0UGF0aChkcmFmdCwgZmllbGRQYXRoKVxuICAgICAgY29uc3QgcHJldlN0YXR1cyA9IHByZXYgJiYgdHlwZW9mIHByZXYgPT09ICdvYmplY3QnID8gKHByZXYgYXMgYW55KS5zdGF0dXMgOiB1bmRlZmluZWRcbiAgICAgIGlmIChwcmV2U3RhdHVzID09PSAnaWRsZScpIHtcbiAgICAgICAgLy8gU3RpbGwgZW5zdXJlIGRhdGEvZXJyb3IgYXJlIGNsZWFyZWQuXG4gICAgICAgIGNvbnN0IGRhdGEgPSAocHJldiBhcyBhbnkpPy5kYXRhXG4gICAgICAgIGNvbnN0IGVycm9yID0gKHByZXYgYXMgYW55KT8uZXJyb3JcbiAgICAgICAgaWYgKGRhdGEgPT09IHVuZGVmaW5lZCAmJiBlcnJvciA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgY29udGludWVcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICB1cGRhdGVzLnB1c2goeyBmaWVsZFBhdGgsIHByZXYgfSlcbiAgICB9XG5cbiAgICBpZiAodXBkYXRlcy5sZW5ndGggPT09IDApIHJldHVyblxuXG4gICAgY29uc3QgcmVhc29uOiBQYXRjaFJlYXNvbiA9ICdzb3VyY2UtcmVmcmVzaCdcblxuICAgIGNvbnN0IG5leHREcmFmdCA9IGNyZWF0ZShkcmFmdCwgKG5leHQpID0+IHtcbiAgICAgIGZvciAoY29uc3QgdSBvZiB1cGRhdGVzKSB7XG4gICAgICAgIFJvd0lkLnNldEF0UGF0aE11dGF0aW5nKG5leHQsIHUuZmllbGRQYXRoLCBTbmFwc2hvdC5pZGxlKCkpXG4gICAgICB9XG4gICAgfSlcblxuICAgIGN0eC5zZXREcmFmdChuZXh0RHJhZnQgYXMgUylcblxuICAgIGZvciAoY29uc3QgdSBvZiB1cGRhdGVzKSB7XG4gICAgICBjb25zdCBub3JtYWxpemVkID0gbm9ybWFsaXplRmllbGRQYXRoKHUuZmllbGRQYXRoKSA/PyBbXVxuICAgICAgY3R4LnJlY29yZFBhdGNoKG5vcm1hbGl6ZWQsIHJlYXNvbiwgdS5wcmV2LCBTbmFwc2hvdC5pZGxlKCksIGBzb3VyY2U6JHt1LmZpZWxkUGF0aH06aWRsZWApXG4gICAgfVxuICB9KVxuXG4vKipcbiAqIGluc3RhbGxTb3VyY2VSZWZyZXNoXHVGRjFBXG4gKiAtIFJlZ2lzdGVyIHRoZSByZWZyZXNoIGltcGxlbWVudGF0aW9uIGZvciBhIHNpbmdsZSBzb3VyY2UgZmllbGQgKFJlc291cmNlU25hcHNob3QgKyBrZXlIYXNoIGdhdGUgKyBjb25jdXJyZW5jeSkuXG4gKi9cbmV4cG9ydCBjb25zdCBpbnN0YWxsU291cmNlUmVmcmVzaCA9IDxTPihcbiAgYm91bmQ6IEJvdW5kQXBpPGFueSwgYW55PixcbiAgc3RlcDogU3RhdGVUcmFpdFBsYW5TdGVwLFxuICBlbnRyeTogRXh0cmFjdDxTdGF0ZVRyYWl0RW50cnk8Uywgc3RyaW5nPiwgeyByZWFkb25seSBraW5kOiAnc291cmNlJyB9Pixcbik6IEVmZmVjdC5FZmZlY3Q8dm9pZCwgbmV2ZXIsIGFueT4gPT4ge1xuICBpZiAoIXN0ZXAudGFyZ2V0RmllbGRQYXRoKSByZXR1cm4gRWZmZWN0LnZvaWRcblxuICBjb25zdCBmaWVsZFBhdGggPSBzdGVwLnRhcmdldEZpZWxkUGF0aFxuICBjb25zdCByZXNvdXJjZUlkID0gc3RlcC5yZXNvdXJjZUlkID8/IGVudHJ5Lm1ldGEucmVzb3VyY2VcbiAgY29uc3QgbGlzdEl0ZW0gPSBSb3dJZC5wYXJzZUxpc3RJdGVtRmllbGRQYXRoKGZpZWxkUGF0aClcblxuICBsZXQgaW50ZXJuYWxzOiBSZXR1cm5UeXBlPHR5cGVvZiBnZXRCb3VuZEludGVybmFscz4gfCB1bmRlZmluZWRcbiAgdHJ5IHtcbiAgICBpbnRlcm5hbHMgPSBnZXRCb3VuZEludGVybmFscyhib3VuZCBhcyBhbnkpXG4gIH0gY2F0Y2gge1xuICAgIHJldHVybiBFZmZlY3Qudm9pZFxuICB9XG5cbiAgY29uc3QgcmVnaXN0ZXIgPSBpbnRlcm5hbHMudHJhaXRzLnJlZ2lzdGVyU291cmNlUmVmcmVzaFxuXG4gIGNvbnN0IHJlY29yZFNuYXBzaG90ID0gKFxuICAgIHJlcGxheU1vZGU6ICdsaXZlJyB8ICdyZXBsYXknLFxuICAgIHJlcGxheUxvZzogUmVwbGF5TG9nLlJlcGxheUxvZ1NlcnZpY2UgfCB1bmRlZmluZWQsXG4gICAgaW5wdXQ6XG4gICAgICB8IFJlcGxheUxvZy5SZXBsYXlMb2dFdmVudFxuICAgICAgfCB7XG4gICAgICAgICAgcmVhZG9ubHkgbW9kdWxlSWQ/OiBzdHJpbmdcbiAgICAgICAgICByZWFkb25seSBpbnN0YW5jZUlkPzogc3RyaW5nXG4gICAgICAgICAgcmVhZG9ubHkgZmllbGRQYXRoOiBzdHJpbmdcbiAgICAgICAgICByZWFkb25seSBrZXlIYXNoPzogc3RyaW5nXG4gICAgICAgICAgcmVhZG9ubHkgY29uY3VycmVuY3k/OiBzdHJpbmdcbiAgICAgICAgICByZWFkb25seSBwaGFzZTogUmVwbGF5TG9nLlJlc291cmNlU25hcHNob3RQaGFzZVxuICAgICAgICAgIHJlYWRvbmx5IHNuYXBzaG90OiB1bmtub3duXG4gICAgICAgIH0sXG4gICk6IEVmZmVjdC5FZmZlY3Q8dm9pZCwgbmV2ZXIsIGFueT4gPT4ge1xuICAgIGlmICghcmVwbGF5TG9nKSByZXR1cm4gRWZmZWN0LnZvaWRcbiAgICBpZiAocmVwbGF5TW9kZSAhPT0gJ2xpdmUnKSByZXR1cm4gRWZmZWN0LnZvaWRcbiAgICBjb25zdCBldmVudDogUmVwbGF5TG9nLlJlcGxheUxvZ0V2ZW50ID1cbiAgICAgIGlucHV0ICYmIHR5cGVvZiBpbnB1dCA9PT0gJ29iamVjdCcgJiYgKGlucHV0IGFzIGFueSkuX3RhZyA9PT0gJ1Jlc291cmNlU25hcHNob3QnXG4gICAgICAgID8gKGlucHV0IGFzIFJlcGxheUxvZy5SZXBsYXlMb2dFdmVudClcbiAgICAgICAgOiB7XG4gICAgICAgICAgICBfdGFnOiAnUmVzb3VyY2VTbmFwc2hvdCcsXG4gICAgICAgICAgICByZXNvdXJjZUlkLFxuICAgICAgICAgICAgZmllbGRQYXRoOiAoaW5wdXQgYXMgYW55KS5maWVsZFBhdGgsXG4gICAgICAgICAgICBrZXlIYXNoOiAoaW5wdXQgYXMgYW55KS5rZXlIYXNoLFxuICAgICAgICAgICAgY29uY3VycmVuY3k6IChpbnB1dCBhcyBhbnkpLmNvbmN1cnJlbmN5LFxuICAgICAgICAgICAgcGhhc2U6IChpbnB1dCBhcyBhbnkpLnBoYXNlLFxuICAgICAgICAgICAgc25hcHNob3Q6IChpbnB1dCBhcyBhbnkpLnNuYXBzaG90LFxuICAgICAgICAgICAgdGltZXN0YW1wOiBEYXRlLm5vdygpLFxuICAgICAgICAgICAgbW9kdWxlSWQ6IChpbnB1dCBhcyBhbnkpLm1vZHVsZUlkLFxuICAgICAgICAgICAgaW5zdGFuY2VJZDogKGlucHV0IGFzIGFueSkuaW5zdGFuY2VJZCxcbiAgICAgICAgICB9XG4gICAgcmV0dXJuIHJlcGxheUxvZy5yZWNvcmQoZXZlbnQpXG4gIH1cblxuICAvLyBsaXN0Lml0ZW0gc2NvcGU6IGluLWZsaWdodCBnYXRpbmcgYnkgUm93SUQgKGF2b2lkIHdyaXRpbmcgdG8gdGhlIHdyb25nIHJvdyB1bmRlciBpbnNlcnQvcmVtb3ZlL3Jlb3JkZXIpLlxuICBpZiAobGlzdEl0ZW0pIHtcbiAgICBjb25zdCBzdG9yZSA9IGludGVybmFscy50cmFpdHMucm93SWRTdG9yZSBhcyBSb3dJZC5Sb3dJZFN0b3JlIHwgdW5kZWZpbmVkXG4gICAgaWYgKCFzdG9yZSkge1xuICAgICAgcmV0dXJuIEVmZmVjdC52b2lkXG4gICAgfVxuXG4gICAgY29uc3QgbGlzdFBhdGggPSBsaXN0SXRlbS5saXN0UGF0aFxuICAgIGNvbnN0IGl0ZW1QYXRoID0gbGlzdEl0ZW0uaXRlbVBhdGhcbiAgICBpZiAoIWl0ZW1QYXRoKSB7XG4gICAgICAvLyBOZXZlciB3cml0ZSB0aGUgc25hcHNob3QgYmFjayB0byB0aGUgd2hvbGUgaXRlbSAoaXQgd291bGQgb3ZlcndyaXRlIGJ1c2luZXNzIHZhbHVlcykuXG4gICAgICByZXR1cm4gRWZmZWN0LnZvaWRcbiAgICB9XG5cbiAgICBjb25zdCBjb25jdXJyZW5jeSA9IChlbnRyeS5tZXRhIGFzIGFueSkuY29uY3VycmVuY3kgYXMgJ3N3aXRjaCcgfCAnZXhoYXVzdC10cmFpbGluZycgfCB1bmRlZmluZWRcbiAgICBjb25zdCBtb2RlID0gY29uY3VycmVuY3kgPz8gJ3N3aXRjaCdcblxuICAgIGNvbnN0IGluRmxpZ2h0ID0gbmV3IE1hcDxcbiAgICAgIFJvd0lkLlJvd0lkLFxuICAgICAge1xuICAgICAgICByZWFkb25seSBnZW46IG51bWJlclxuICAgICAgICByZWFkb25seSBmaWJlcjogRmliZXIuUnVudGltZUZpYmVyPHZvaWQsIG5ldmVyPlxuICAgICAgICByZWFkb25seSBrZXlIYXNoOiBzdHJpbmdcbiAgICAgIH1cbiAgICA+KClcbiAgICBjb25zdCB0cmFpbGluZyA9IG5ldyBNYXA8Um93SWQuUm93SWQsIHsgcmVhZG9ubHkga2V5OiB1bmtub3duOyByZWFkb25seSBrZXlIYXNoOiBzdHJpbmcgfT4oKVxuICAgIGxldCBnZW4gPSAwXG5cbiAgICAvLyBXaGVuIGEgcm93IGlzIHJlbW92ZWQ6IGNsZWFyIHRyYWlsaW5nL2luRmxpZ2h0IHJlZmVyZW5jZXMgdG8gYXZvaWQgd3JvbmcgYXR0cmlidXRpb24gb3IgbWVtb3J5IGxlYWtzLlxuICAgIHN0b3JlLm9uUmVtb3ZlZChsaXN0UGF0aCwgKHJvd0lkKSA9PiB7XG4gICAgICB0cmFpbGluZy5kZWxldGUocm93SWQpXG4gICAgICBpbkZsaWdodC5kZWxldGUocm93SWQpXG4gICAgfSlcblxuICAgIGNvbnN0IHNldFNuYXBzaG90Rm9yUm93SW5UeG4gPSAoXG4gICAgICByb3dJZDogUm93SWQuUm93SWQsXG4gICAgICBuZXh0OiB1bmtub3duLFxuICAgICAgcmVhc29uOiBQYXRjaFJlYXNvbixcbiAgICAgIHN0ZXBJZDogc3RyaW5nLFxuICAgICk6IEVmZmVjdC5FZmZlY3Q8c3RyaW5nIHwgdW5kZWZpbmVkLCBuZXZlciwgYW55PiA9PlxuICAgICAgRWZmZWN0LmdlbihmdW5jdGlvbiogKCkge1xuICAgICAgICBsZXQgd3JvdGVQYXRoOiBzdHJpbmcgfCB1bmRlZmluZWRcbiAgICAgICAgeWllbGQqIGJvdW5kLnN0YXRlLm11dGF0ZSgoZHJhZnQpID0+IHtcbiAgICAgICAgICBjb25zdCBpbmRleCA9IHN0b3JlLmdldEluZGV4KGxpc3RQYXRoLCByb3dJZClcbiAgICAgICAgICBpZiAoaW5kZXggPT09IHVuZGVmaW5lZCkgcmV0dXJuXG4gICAgICAgICAgY29uc3QgY29uY3JldGVQYXRoID0gUm93SWQudG9MaXN0SXRlbVZhbHVlUGF0aChsaXN0UGF0aCwgaW5kZXgsIGl0ZW1QYXRoKVxuICAgICAgICAgIGNvbnN0IHByZXYgPSBSb3dJZC5nZXRBdFBhdGgoZHJhZnQsIGNvbmNyZXRlUGF0aClcbiAgICAgICAgICBpZiAoT2JqZWN0LmlzKHByZXYsIG5leHQpKSByZXR1cm5cbiAgICAgICAgICB3cm90ZVBhdGggPSBjb25jcmV0ZVBhdGhcbiAgICAgICAgICBSb3dJZC5zZXRBdFBhdGhNdXRhdGluZyhkcmFmdCwgY29uY3JldGVQYXRoLCBuZXh0KVxuICAgICAgICAgIHJlY29yZFRyYWl0UGF0Y2goYm91bmQsIGNvbmNyZXRlUGF0aCwgcmVhc29uLCBwcmV2LCBuZXh0LCBzdGVwLmRlYnVnSW5mbz8uZ3JhcGhOb2RlSWQpXG4gICAgICAgIH0pXG4gICAgICAgIHJldHVybiB3cm90ZVBhdGhcbiAgICAgIH0pXG5cbiAgICBjb25zdCB3cml0ZWJhY2tJZkN1cnJlbnRLZXlIYXNoRm9yUm93ID0gKFxuICAgICAgcm93SWQ6IFJvd0lkLlJvd0lkLFxuICAgICAga2V5SGFzaDogc3RyaW5nLFxuICAgICAgbmV4dDogdW5rbm93bixcbiAgICAgIHJlYXNvbjogUGF0Y2hSZWFzb24sXG4gICAgICBzdGVwSWQ6IHN0cmluZyxcbiAgICAgIHBoYXNlPzogUmVwbGF5TG9nLlJlc291cmNlU25hcHNob3RQaGFzZSxcbiAgICApOiBFZmZlY3QuRWZmZWN0PHN0cmluZyB8IHVuZGVmaW5lZCwgbmV2ZXIsIGFueT4gPT5cbiAgICAgIEVmZmVjdC5nZW4oZnVuY3Rpb24qICgpIHtcbiAgICAgICAgbGV0IHdyb3RlUGF0aDogc3RyaW5nIHwgdW5kZWZpbmVkXG4gICAgICAgIHlpZWxkKiBib3VuZC5zdGF0ZS5tdXRhdGUoKGRyYWZ0KSA9PiB7XG4gICAgICAgICAgY29uc3QgaW5kZXggPSBzdG9yZS5nZXRJbmRleChsaXN0UGF0aCwgcm93SWQpXG4gICAgICAgICAgaWYgKGluZGV4ID09PSB1bmRlZmluZWQpIHJldHVyblxuICAgICAgICAgIGNvbnN0IGNvbmNyZXRlUGF0aCA9IFJvd0lkLnRvTGlzdEl0ZW1WYWx1ZVBhdGgobGlzdFBhdGgsIGluZGV4LCBpdGVtUGF0aClcblxuICAgICAgICAgIGNvbnN0IGN1cnJlbnQgPSBSb3dJZC5nZXRBdFBhdGgoZHJhZnQsIGNvbmNyZXRlUGF0aClcbiAgICAgICAgICBjb25zdCBjdXJyZW50S2V5SGFzaCA9IGN1cnJlbnQgJiYgdHlwZW9mIGN1cnJlbnQgPT09ICdvYmplY3QnID8gKGN1cnJlbnQgYXMgYW55KS5rZXlIYXNoIDogdW5kZWZpbmVkXG4gICAgICAgICAgaWYgKGN1cnJlbnRLZXlIYXNoICE9PSBrZXlIYXNoKSByZXR1cm5cblxuICAgICAgICAgIGNvbnN0IHByZXYgPSBjdXJyZW50XG4gICAgICAgICAgaWYgKE9iamVjdC5pcyhwcmV2LCBuZXh0KSkgcmV0dXJuXG5cbiAgICAgICAgICB3cm90ZVBhdGggPSBjb25jcmV0ZVBhdGhcbiAgICAgICAgICBSb3dJZC5zZXRBdFBhdGhNdXRhdGluZyhkcmFmdCwgY29uY3JldGVQYXRoLCBuZXh0KVxuICAgICAgICAgIGlmIChwaGFzZSkge1xuICAgICAgICAgICAgY29uc3QgeyBtb2R1bGVJZCwgaW5zdGFuY2VJZCB9ID0gZ2V0Qm91bmRTY29wZShib3VuZClcbiAgICAgICAgICAgIHJlY29yZFJlcGxheUV2ZW50KGJvdW5kLCB7XG4gICAgICAgICAgICAgIF90YWc6ICdSZXNvdXJjZVNuYXBzaG90JyxcbiAgICAgICAgICAgICAgcmVzb3VyY2VJZCxcbiAgICAgICAgICAgICAgZmllbGRQYXRoOiBjb25jcmV0ZVBhdGgsXG4gICAgICAgICAgICAgIGtleUhhc2gsXG4gICAgICAgICAgICAgIGNvbmN1cnJlbmN5OiBtb2RlLFxuICAgICAgICAgICAgICBwaGFzZSxcbiAgICAgICAgICAgICAgc25hcHNob3Q6IG5leHQsXG4gICAgICAgICAgICAgIHRpbWVzdGFtcDogRGF0ZS5ub3coKSxcbiAgICAgICAgICAgICAgbW9kdWxlSWQsXG4gICAgICAgICAgICAgIGluc3RhbmNlSWQsXG4gICAgICAgICAgICB9KVxuICAgICAgICAgIH1cbiAgICAgICAgICByZWNvcmRUcmFpdFBhdGNoKGJvdW5kLCBjb25jcmV0ZVBhdGgsIHJlYXNvbiwgcHJldiwgbmV4dCwgc3RlcC5kZWJ1Z0luZm8/LmdyYXBoTm9kZUlkKVxuICAgICAgICB9KVxuICAgICAgICByZXR1cm4gd3JvdGVQYXRoXG4gICAgICB9KVxuXG4gICAgY29uc3Qgc3RhcnRGZXRjaCA9IChcbiAgICAgIHJvd0lkOiBSb3dJZC5Sb3dJZCxcbiAgICAgIGtleTogdW5rbm93bixcbiAgICAgIGtleUhhc2g6IHN0cmluZyxcbiAgICAgIHJlcGxheU1vZGU6ICdsaXZlJyB8ICdyZXBsYXknLFxuICAgICAgcmVwbGF5TG9nOiBSZXBsYXlMb2cuUmVwbGF5TG9nU2VydmljZSB8IHVuZGVmaW5lZCxcbiAgICApOiBFZmZlY3QuRWZmZWN0PHZvaWQsIG5ldmVyLCBhbnk+ID0+XG4gICAgICBFZmZlY3QuZ2VuKGZ1bmN0aW9uKiAoKSB7XG4gICAgICAgIGNvbnN0IHsgbW9kdWxlSWQsIGluc3RhbmNlSWQgfSA9IGdldEJvdW5kU2NvcGUoYm91bmQpXG5cbiAgICAgICAgY29uc3QgaW5kZXhGb3JMb2cgPSBzdG9yZS5nZXRJbmRleChsaXN0UGF0aCwgcm93SWQpXG4gICAgICAgIGNvbnN0IGxvZ0ZpZWxkUGF0aCA9XG4gICAgICAgICAgaW5kZXhGb3JMb2cgPT09IHVuZGVmaW5lZCA/IHVuZGVmaW5lZCA6IFJvd0lkLnRvTGlzdEl0ZW1WYWx1ZVBhdGgobGlzdFBhdGgsIGluZGV4Rm9yTG9nLCBpdGVtUGF0aClcblxuICAgICAgICBsZXQgbG9hZGluZ1NuYXBzaG90OiB1bmtub3duID0gU25hcHNob3QubG9hZGluZyh7IGtleUhhc2ggfSlcbiAgICAgICAgaWYgKHJlcGxheU1vZGUgPT09ICdyZXBsYXknICYmIHJlcGxheUxvZyAmJiBsb2dGaWVsZFBhdGgpIHtcbiAgICAgICAgICBjb25zdCByZXBsYXlMb2FkaW5nID0geWllbGQqIHJlcGxheUxvZy5jb25zdW1lTmV4dFJlc291cmNlU25hcHNob3Qoe1xuICAgICAgICAgICAgcmVzb3VyY2VJZCxcbiAgICAgICAgICAgIGZpZWxkUGF0aDogbG9nRmllbGRQYXRoLFxuICAgICAgICAgICAga2V5SGFzaCxcbiAgICAgICAgICAgIHBoYXNlOiAnbG9hZGluZycsXG4gICAgICAgICAgfSlcbiAgICAgICAgICBpZiAocmVwbGF5TG9hZGluZykge1xuICAgICAgICAgICAgbG9hZGluZ1NuYXBzaG90ID0gcmVwbGF5TG9hZGluZy5zbmFwc2hvdFxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBjb25zdCB3cm90ZUxvYWRpbmdQYXRoID0geWllbGQqIHNldFNuYXBzaG90Rm9yUm93SW5UeG4oXG4gICAgICAgICAgcm93SWQsXG4gICAgICAgICAgbG9hZGluZ1NuYXBzaG90LFxuICAgICAgICAgICdzb3VyY2UtcmVmcmVzaCcsXG4gICAgICAgICAgYHNvdXJjZToke2ZpZWxkUGF0aH06JHtyb3dJZH06bG9hZGluZ2AsXG4gICAgICAgIClcbiAgICAgICAgaWYgKHdyb3RlTG9hZGluZ1BhdGgpIHtcbiAgICAgICAgICBjb25zdCBldmVudDogUmVwbGF5TG9nLlJlcGxheUxvZ0V2ZW50ID0ge1xuICAgICAgICAgICAgX3RhZzogJ1Jlc291cmNlU25hcHNob3QnLFxuICAgICAgICAgICAgcmVzb3VyY2VJZCxcbiAgICAgICAgICAgIGZpZWxkUGF0aDogd3JvdGVMb2FkaW5nUGF0aCxcbiAgICAgICAgICAgIGtleUhhc2gsXG4gICAgICAgICAgICBjb25jdXJyZW5jeTogbW9kZSxcbiAgICAgICAgICAgIHBoYXNlOiAnbG9hZGluZycsXG4gICAgICAgICAgICBzbmFwc2hvdDogbG9hZGluZ1NuYXBzaG90LFxuICAgICAgICAgICAgdGltZXN0YW1wOiBEYXRlLm5vdygpLFxuICAgICAgICAgICAgbW9kdWxlSWQsXG4gICAgICAgICAgICBpbnN0YW5jZUlkLFxuICAgICAgICAgIH1cbiAgICAgICAgICByZWNvcmRSZXBsYXlFdmVudChib3VuZCwgZXZlbnQpXG4gICAgICAgICAgeWllbGQqIHJlY29yZFNuYXBzaG90KHJlcGxheU1vZGUsIHJlcGxheUxvZywgZXZlbnQpXG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBpbyA9IEVmZmVjdC5nZW4oZnVuY3Rpb24qICgpIHtcbiAgICAgICAgICBpZiAocmVwbGF5TW9kZSA9PT0gJ3JlcGxheScgJiYgcmVwbGF5TG9nKSB7XG4gICAgICAgICAgICAvLyBMZXQgbG9hZGluZyBjb21taXQgYmVjb21lIHZpc2libGUgZmlyc3QsIHRoZW4gcmVwbGF5IHRoZSBzZXR0bGVkIHBoYXNlIChwcmVzZXJ2ZSB0aGUgYXN5bmMtcmVzb3VyY2UgdGltZWxpbmUgc2hhcGUpLlxuICAgICAgICAgICAgeWllbGQqIEVmZmVjdC55aWVsZE5vdygpXG4gICAgICAgICAgICBjb25zdCBjb25zdW1lUGF0aCA9IHdyb3RlTG9hZGluZ1BhdGggPz8gbG9nRmllbGRQYXRoXG4gICAgICAgICAgICBpZiAoIWNvbnN1bWVQYXRoKSByZXR1cm4geWllbGQqIEVmZmVjdC52b2lkXG5cbiAgICAgICAgICAgIGNvbnN0IHJlcGxheWVkID0geWllbGQqIHJlcGxheUxvZy5jb25zdW1lTmV4dFJlc291cmNlU25hcHNob3Qoe1xuICAgICAgICAgICAgICByZXNvdXJjZUlkLFxuICAgICAgICAgICAgICBmaWVsZFBhdGg6IGNvbnN1bWVQYXRoLFxuICAgICAgICAgICAgICBrZXlIYXNoLFxuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIGlmICghcmVwbGF5ZWQpIHJldHVybiB5aWVsZCogRWZmZWN0LnZvaWRcblxuICAgICAgICAgICAgaWYgKHJlcGxheWVkLnBoYXNlID09PSAnc3VjY2VzcycpIHtcbiAgICAgICAgICAgICAgeWllbGQqIHdyaXRlYmFja0lmQ3VycmVudEtleUhhc2hGb3JSb3coXG4gICAgICAgICAgICAgICAgcm93SWQsXG4gICAgICAgICAgICAgICAga2V5SGFzaCxcbiAgICAgICAgICAgICAgICByZXBsYXllZC5zbmFwc2hvdCxcbiAgICAgICAgICAgICAgICAnc291cmNlLXJlZnJlc2gnLFxuICAgICAgICAgICAgICAgIGBzb3VyY2U6JHtmaWVsZFBhdGh9OiR7cm93SWR9OnN1Y2Nlc3NgLFxuICAgICAgICAgICAgICAgICdzdWNjZXNzJyxcbiAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgfSBlbHNlIGlmIChyZXBsYXllZC5waGFzZSA9PT0gJ2Vycm9yJykge1xuICAgICAgICAgICAgICB5aWVsZCogd3JpdGViYWNrSWZDdXJyZW50S2V5SGFzaEZvclJvdyhcbiAgICAgICAgICAgICAgICByb3dJZCxcbiAgICAgICAgICAgICAgICBrZXlIYXNoLFxuICAgICAgICAgICAgICAgIHJlcGxheWVkLnNuYXBzaG90LFxuICAgICAgICAgICAgICAgICdzb3VyY2UtcmVmcmVzaCcsXG4gICAgICAgICAgICAgICAgYHNvdXJjZToke2ZpZWxkUGF0aH06JHtyb3dJZH06ZXJyb3JgLFxuICAgICAgICAgICAgICAgICdlcnJvcicsXG4gICAgICAgICAgICAgIClcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcmV0dXJuIHlpZWxkKiBFZmZlY3Qudm9pZFxuICAgICAgICAgIH1cblxuICAgICAgICAgIGNvbnN0IHN0YWNrID0geWllbGQqIGdldE1pZGRsZXdhcmVTdGFjaygpXG5cbiAgICAgICAgICBjb25zdCByZWdpc3RyeU9wdCA9IHlpZWxkKiBFZmZlY3Quc2VydmljZU9wdGlvbihSZXNvdXJjZUludGVybmFsLlJlc291cmNlUmVnaXN0cnlUYWcpXG4gICAgICAgICAgY29uc3QgcmVnaXN0cnkgPSBPcHRpb24uaXNTb21lKHJlZ2lzdHJ5T3B0KSA/IHJlZ2lzdHJ5T3B0LnZhbHVlIDogdW5kZWZpbmVkXG4gICAgICAgICAgY29uc3Qgc3BlYyA9IHJlZ2lzdHJ5Py5zcGVjcy5nZXQocmVzb3VyY2VJZClcblxuICAgICAgICAgIGlmICghc3BlYykge1xuICAgICAgICAgICAgcmV0dXJuIHlpZWxkKiBFZmZlY3Qudm9pZFxuICAgICAgICAgIH1cblxuICAgICAgICAgIGNvbnN0IGxvYWRFZmZlY3QgPSAoc3BlYy5sb2FkIGFzIGFueSkoa2V5KSBhcyBFZmZlY3QuRWZmZWN0PGFueSwgYW55LCBhbnk+XG5cbiAgICAgICAgICBjb25zdCBtZXRhOiBhbnkgPSB7XG4gICAgICAgICAgICBtb2R1bGVJZCxcbiAgICAgICAgICAgIGluc3RhbmNlSWQsXG4gICAgICAgICAgICBmaWVsZFBhdGgsXG4gICAgICAgICAgICByZXNvdXJjZUlkLFxuICAgICAgICAgICAga2V5LFxuICAgICAgICAgICAga2V5SGFzaCxcbiAgICAgICAgICAgIHJvd0lkLFxuICAgICAgICAgICAgdHJhaXROb2RlSWQ6IHN0ZXAuZGVidWdJbmZvPy5ncmFwaE5vZGVJZCxcbiAgICAgICAgICAgIHN0ZXBJZDogc3RlcC5pZCxcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAoISh0eXBlb2YgbWV0YS5vcFNlcSA9PT0gJ251bWJlcicgJiYgTnVtYmVyLmlzRmluaXRlKG1ldGEub3BTZXEpKSkge1xuICAgICAgICAgICAgY29uc3Qgc2Vzc2lvbk9wdCA9IHlpZWxkKiBFZmZlY3Quc2VydmljZU9wdGlvbihSdW5TZXNzaW9uVGFnKVxuICAgICAgICAgICAgaWYgKE9wdGlvbi5pc1NvbWUoc2Vzc2lvbk9wdCkpIHtcbiAgICAgICAgICAgICAgY29uc3Qgc2VxS2V5ID0gaW5zdGFuY2VJZCA/PyAnZ2xvYmFsJ1xuICAgICAgICAgICAgICBtZXRhLm9wU2VxID0gc2Vzc2lvbk9wdC52YWx1ZS5sb2NhbC5uZXh0U2VxKCdvcFNlcScsIHNlcUtleSlcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG5cbiAgICAgICAgICBjb25zdCBvcCA9IEVmZmVjdE9wLm1ha2U8YW55LCBhbnksIGFueT4oe1xuICAgICAgICAgICAga2luZDogJ3NlcnZpY2UnLFxuICAgICAgICAgICAgbmFtZTogcmVzb3VyY2VJZCxcbiAgICAgICAgICAgIGVmZmVjdDogbG9hZEVmZmVjdCxcbiAgICAgICAgICAgIG1ldGEsXG4gICAgICAgICAgfSlcblxuICAgICAgICAgIGNvbnN0IGV4aXQgPSB5aWVsZCogRWZmZWN0LmV4aXQoRWZmZWN0T3AucnVuKG9wLCBzdGFjaykpXG5cbiAgICAgICAgICBpZiAoZXhpdC5fdGFnID09PSAnU3VjY2VzcycpIHtcbiAgICAgICAgICAgIGNvbnN0IHN1Y2Nlc3NTbmFwc2hvdCA9IFNuYXBzaG90LnN1Y2Nlc3MoeyBrZXlIYXNoLCBkYXRhOiBleGl0LnZhbHVlIH0pXG4gICAgICAgICAgICBjb25zdCB3cm90ZVN1Y2Nlc3NQYXRoID0geWllbGQqIHdyaXRlYmFja0lmQ3VycmVudEtleUhhc2hGb3JSb3coXG4gICAgICAgICAgICAgIHJvd0lkLFxuICAgICAgICAgICAgICBrZXlIYXNoLFxuICAgICAgICAgICAgICBzdWNjZXNzU25hcHNob3QsXG4gICAgICAgICAgICAgICdzb3VyY2UtcmVmcmVzaCcsXG4gICAgICAgICAgICAgIGBzb3VyY2U6JHtmaWVsZFBhdGh9OiR7cm93SWR9OnN1Y2Nlc3NgLFxuICAgICAgICAgICAgICAnc3VjY2VzcycsXG4gICAgICAgICAgICApXG4gICAgICAgICAgICBpZiAod3JvdGVTdWNjZXNzUGF0aCkge1xuICAgICAgICAgICAgICB5aWVsZCogcmVjb3JkU25hcHNob3QocmVwbGF5TW9kZSwgcmVwbGF5TG9nLCB7XG4gICAgICAgICAgICAgICAgX3RhZzogJ1Jlc291cmNlU25hcHNob3QnLFxuICAgICAgICAgICAgICAgIHJlc291cmNlSWQsXG4gICAgICAgICAgICAgICAgZmllbGRQYXRoOiB3cm90ZVN1Y2Nlc3NQYXRoLFxuICAgICAgICAgICAgICAgIGtleUhhc2gsXG4gICAgICAgICAgICAgICAgY29uY3VycmVuY3k6IG1vZGUsXG4gICAgICAgICAgICAgICAgcGhhc2U6ICdzdWNjZXNzJyxcbiAgICAgICAgICAgICAgICBzbmFwc2hvdDogc3VjY2Vzc1NuYXBzaG90LFxuICAgICAgICAgICAgICAgIHRpbWVzdGFtcDogRGF0ZS5ub3coKSxcbiAgICAgICAgICAgICAgICBtb2R1bGVJZCxcbiAgICAgICAgICAgICAgICBpbnN0YW5jZUlkLFxuICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgfVxuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjb25zdCBlcnJvclNuYXBzaG90ID0gU25hcHNob3QuZXJyb3IoeyBrZXlIYXNoLCBlcnJvcjogZXhpdC5jYXVzZSB9KVxuICAgICAgICAgICAgY29uc3Qgd3JvdGVFcnJvclBhdGggPSB5aWVsZCogd3JpdGViYWNrSWZDdXJyZW50S2V5SGFzaEZvclJvdyhcbiAgICAgICAgICAgICAgcm93SWQsXG4gICAgICAgICAgICAgIGtleUhhc2gsXG4gICAgICAgICAgICAgIGVycm9yU25hcHNob3QsXG4gICAgICAgICAgICAgICdzb3VyY2UtcmVmcmVzaCcsXG4gICAgICAgICAgICAgIGBzb3VyY2U6JHtmaWVsZFBhdGh9OiR7cm93SWR9OmVycm9yYCxcbiAgICAgICAgICAgICAgJ2Vycm9yJyxcbiAgICAgICAgICAgIClcbiAgICAgICAgICAgIGlmICh3cm90ZUVycm9yUGF0aCkge1xuICAgICAgICAgICAgICB5aWVsZCogcmVjb3JkU25hcHNob3QocmVwbGF5TW9kZSwgcmVwbGF5TG9nLCB7XG4gICAgICAgICAgICAgICAgX3RhZzogJ1Jlc291cmNlU25hcHNob3QnLFxuICAgICAgICAgICAgICAgIHJlc291cmNlSWQsXG4gICAgICAgICAgICAgICAgZmllbGRQYXRoOiB3cm90ZUVycm9yUGF0aCxcbiAgICAgICAgICAgICAgICBrZXlIYXNoLFxuICAgICAgICAgICAgICAgIGNvbmN1cnJlbmN5OiBtb2RlLFxuICAgICAgICAgICAgICAgIHBoYXNlOiAnZXJyb3InLFxuICAgICAgICAgICAgICAgIHNuYXBzaG90OiBlcnJvclNuYXBzaG90LFxuICAgICAgICAgICAgICAgIHRpbWVzdGFtcDogRGF0ZS5ub3coKSxcbiAgICAgICAgICAgICAgICBtb2R1bGVJZCxcbiAgICAgICAgICAgICAgICBpbnN0YW5jZUlkLFxuICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfSkucGlwZShFZmZlY3QuY2F0Y2hBbGxDYXVzZSgoKSA9PiBFZmZlY3Qudm9pZCkpXG5cbiAgICAgICAgLy8gbGlzdC5pdGVtOiBJTyBmaWJlcnMgbXVzdCBkZXRhY2ggZnJvbSB0aGUgc3luYy10cmFuc2FjdGlvbiBGaWJlclJlZjsgb3RoZXJ3aXNlIHRoZXknZCBiZSBtaXNjbGFzc2lmaWVkIGFzIFwiaW4gdHhuIHdpbmRvd1wiXG4gICAgICAgIC8vIGFuZCBibG9jayBzdWJzZXF1ZW50IHdyaXRlYmFjayBlbnRyeXBvaW50cy5cbiAgICAgICAgY29uc3QgZmliZXIgPSB5aWVsZCogRWZmZWN0LmZvcmtTY29wZWQoRWZmZWN0LmxvY2FsbHkoVGFza1J1bm5lci5pblN5bmNUcmFuc2FjdGlvbkZpYmVyLCBmYWxzZSkoaW8pKVxuICAgICAgICBjb25zdCBteUdlbiA9IChnZW4gKz0gMSlcbiAgICAgICAgaW5GbGlnaHQuc2V0KHJvd0lkLCB7IGdlbjogbXlHZW4sIGZpYmVyLCBrZXlIYXNoIH0pXG5cbiAgICAgICAgeWllbGQqIEVmZmVjdC5mb3JrU2NvcGVkKFxuICAgICAgICAgIEVmZmVjdC5sb2NhbGx5KFxuICAgICAgICAgICAgVGFza1J1bm5lci5pblN5bmNUcmFuc2FjdGlvbkZpYmVyLFxuICAgICAgICAgICAgZmFsc2UsXG4gICAgICAgICAgKShcbiAgICAgICAgICAgIEZpYmVyLmF3YWl0KGZpYmVyKS5waXBlKFxuICAgICAgICAgICAgICBFZmZlY3QuemlwUmlnaHQoXG4gICAgICAgICAgICAgICAgRWZmZWN0LnN5bmMoKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgY29uc3QgY3VycmVudCA9IGluRmxpZ2h0LmdldChyb3dJZClcbiAgICAgICAgICAgICAgICAgIGlmIChjdXJyZW50ICYmIGN1cnJlbnQuZ2VuID09PSBteUdlbikge1xuICAgICAgICAgICAgICAgICAgICBpbkZsaWdodC5kZWxldGUocm93SWQpXG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSksXG4gICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgIEVmZmVjdC56aXBSaWdodChcbiAgICAgICAgICAgICAgICBtb2RlID09PSAnZXhoYXVzdC10cmFpbGluZydcbiAgICAgICAgICAgICAgICAgID8gRWZmZWN0LmdlbihmdW5jdGlvbiogKCkge1xuICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG5leHQgPSB0cmFpbGluZy5nZXQocm93SWQpXG4gICAgICAgICAgICAgICAgICAgICAgdHJhaWxpbmcuZGVsZXRlKHJvd0lkKVxuICAgICAgICAgICAgICAgICAgICAgIGlmIChuZXh0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB5aWVsZCogc3RhcnRGZXRjaChyb3dJZCwgbmV4dC5rZXksIG5leHQua2V5SGFzaCwgcmVwbGF5TW9kZSwgcmVwbGF5TG9nKVxuICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAgIDogRWZmZWN0LnZvaWQsXG4gICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgIEVmZmVjdC5jYXRjaEFsbENhdXNlKCgpID0+IEVmZmVjdC52b2lkKSxcbiAgICAgICAgICAgICksXG4gICAgICAgICAgKSxcbiAgICAgICAgKVxuICAgICAgfSlcblxuICAgIHJlZ2lzdGVyKGZpZWxkUGF0aCwgKHN0YXRlOiBhbnkpID0+XG4gICAgICBFZmZlY3QuZ2VuKGZ1bmN0aW9uKiAoKSB7XG4gICAgICAgIGNvbnN0IHsgbW9kdWxlSWQsIGluc3RhbmNlSWQgfSA9IGdldEJvdW5kU2NvcGUoYm91bmQpXG4gICAgICAgIGNvbnN0IHJlcGxheU1vZGVPcHQgPSB5aWVsZCogRWZmZWN0LnNlcnZpY2VPcHRpb24oUmVwbGF5TW9kZUNvbmZpZ1RhZylcbiAgICAgICAgY29uc3QgcmVwbGF5TW9kZSA9IE9wdGlvbi5pc1NvbWUocmVwbGF5TW9kZU9wdCkgPyByZXBsYXlNb2RlT3B0LnZhbHVlLm1vZGUgOiAnbGl2ZSdcbiAgICAgICAgY29uc3QgcmVwbGF5TG9nT3B0ID0geWllbGQqIEVmZmVjdC5zZXJ2aWNlT3B0aW9uKFJlcGxheUxvZy5SZXBsYXlMb2cpXG4gICAgICAgIGNvbnN0IHJlcGxheUxvZyA9IE9wdGlvbi5pc1NvbWUocmVwbGF5TG9nT3B0KSA/IHJlcGxheUxvZ09wdC52YWx1ZSA6IHVuZGVmaW5lZFxuICAgICAgICBjb25zdCBmb3JjZSA9IHlpZWxkKiBGaWJlclJlZi5nZXQoVGFza1J1bm5lci5mb3JjZVNvdXJjZVJlZnJlc2gpXG5cbiAgICAgICAgY29uc3QgbGlzdFZhbHVlID0gUm93SWQuZ2V0QXRQYXRoKHN0YXRlLCBsaXN0UGF0aClcbiAgICAgICAgY29uc3QgaXRlbXM6IFJlYWRvbmx5QXJyYXk8dW5rbm93bj4gPSBBcnJheS5pc0FycmF5KGxpc3RWYWx1ZSkgPyBsaXN0VmFsdWUgOiBbXVxuICAgICAgICBjb25zdCBpZHMgPSBzdG9yZS5lbnN1cmVMaXN0KGxpc3RQYXRoLCBpdGVtcylcblxuICAgICAgICAvLyBkZXYtbW9kZTogdHJhY2UgZGVwcyBvbmNlIGZvciB0aGUgZmlyc3Qgcm93IChkaWFnbm9zdGljcyBvbmx5OyBkb2VzIG5vdCBhZmZlY3QgZXhlY3V0aW9uIHNlbWFudGljcykuXG4gICAgICAgIGNvbnN0IHRyYWNlS2V5ID0gYCR7aW5zdGFuY2VJZCA/PyAndW5rbm93bid9Ojpzb3VyY2U6OiR7ZmllbGRQYXRofWBcbiAgICAgICAgaWYgKGlzRGV2RW52KCkgJiYgKHlpZWxkKiBvbmNlSW5SdW5TZXNzaW9uKGBkZXBzX3RyYWNlX3NldHRsZWQ6JHt0cmFjZUtleX1gKSkpIHtcbiAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgY29uc3Qgc2FtcGxlID0gaXRlbXNbMF1cbiAgICAgICAgICAgIGlmIChzYW1wbGUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICBjb25zdCB0cmFjZWQgPSBEZXBzVHJhY2UudHJhY2UoKHMpID0+IChlbnRyeS5tZXRhIGFzIGFueSkua2V5KHMpLCBzYW1wbGUgYXMgYW55KVxuICAgICAgICAgICAgICBjb25zdCBwcmVmaXhlZFJlYWRzID0gdHJhY2VkLnJlYWRzLm1hcCgocikgPT4gKHIgPyBgJHtsaXN0UGF0aH1bXS4ke3J9YCA6IGAke2xpc3RQYXRofVtdYCkpXG4gICAgICAgICAgICAgIGNvbnN0IGRpZmYgPSBEZXBzVHJhY2UuZGlmZkRlcHMoKChlbnRyeS5tZXRhIGFzIGFueSkuZGVwcyA/PyBbXSkgYXMgUmVhZG9ubHlBcnJheTxzdHJpbmc+LCBwcmVmaXhlZFJlYWRzKVxuICAgICAgICAgICAgICBpZiAoZGlmZikge1xuICAgICAgICAgICAgICAgIHlpZWxkKiBlbWl0RGVwc01pc21hdGNoKHtcbiAgICAgICAgICAgICAgICAgIG1vZHVsZUlkLFxuICAgICAgICAgICAgICAgICAgaW5zdGFuY2VJZCxcbiAgICAgICAgICAgICAgICAgIGtpbmQ6ICdzb3VyY2UnLFxuICAgICAgICAgICAgICAgICAgZmllbGRQYXRoLFxuICAgICAgICAgICAgICAgICAgZGlmZixcbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSBjYXRjaCB7XG4gICAgICAgICAgICAvLyB0cmFjaW5nIGZhaWx1cmUgc2hvdWxkIG5ldmVyIGJyZWFrIHJlZnJlc2ggZmxvd1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGZvciAobGV0IGluZGV4ID0gMDsgaW5kZXggPCBpdGVtcy5sZW5ndGg7IGluZGV4KyspIHtcbiAgICAgICAgICBjb25zdCByb3dJZCA9IGlkc1tpbmRleF1cbiAgICAgICAgICBpZiAoIXJvd0lkKSBjb250aW51ZVxuXG4gICAgICAgICAgY29uc3QgY29uY3JldGVQYXRoID0gUm93SWQudG9MaXN0SXRlbVZhbHVlUGF0aChsaXN0UGF0aCwgaW5kZXgsIGl0ZW1QYXRoKVxuICAgICAgICAgIGNvbnN0IHByZXZTbmFwc2hvdCA9IFJvd0lkLmdldEF0UGF0aChzdGF0ZSwgY29uY3JldGVQYXRoKSBhcyBhbnlcblxuICAgICAgICAgIGxldCBrZXk6IHVua25vd25cbiAgICAgICAgICB0cnkge1xuICAgICAgICAgICAga2V5ID0gKGVudHJ5Lm1ldGEgYXMgYW55KS5rZXkoaXRlbXNbaW5kZXhdKVxuICAgICAgICAgIH0gY2F0Y2gge1xuICAgICAgICAgICAga2V5ID0gdW5kZWZpbmVkXG4gICAgICAgICAgfVxuXG4gICAgICAgICAgY29uc3QgY3VycmVudCA9IGluRmxpZ2h0LmdldChyb3dJZClcblxuICAgICAgICAgIGlmIChrZXkgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgdHJhaWxpbmcuZGVsZXRlKHJvd0lkKVxuICAgICAgICAgICAgaW5GbGlnaHQuZGVsZXRlKHJvd0lkKVxuXG4gICAgICAgICAgICAvLyBJZiBpdCdzIGFscmVhZHkgY2xlYW4gaWRsZSwgYXZvaWQgcmVkdW5kYW50IHdyaXRlYmFjayAocHJldmVudHMgbWVhbmluZ2xlc3MgcGF0Y2hlcyBhbmQgVUkgaml0dGVyKS5cbiAgICAgICAgICAgIGlmIChcbiAgICAgICAgICAgICAgcHJldlNuYXBzaG90ICYmXG4gICAgICAgICAgICAgIHR5cGVvZiBwcmV2U25hcHNob3QgPT09ICdvYmplY3QnICYmXG4gICAgICAgICAgICAgIHByZXZTbmFwc2hvdC5zdGF0dXMgPT09ICdpZGxlJyAmJlxuICAgICAgICAgICAgICBwcmV2U25hcHNob3QuZGF0YSA9PT0gdW5kZWZpbmVkICYmXG4gICAgICAgICAgICAgIHByZXZTbmFwc2hvdC5lcnJvciA9PT0gdW5kZWZpbmVkXG4gICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgY29udGludWVcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgY29uc3QgaWRsZVNuYXBzaG90ID0gU25hcHNob3QuaWRsZSgpXG4gICAgICAgICAgICBjb25zdCB3cm90ZUlkbGVQYXRoID0geWllbGQqIHNldFNuYXBzaG90Rm9yUm93SW5UeG4oXG4gICAgICAgICAgICAgIHJvd0lkLFxuICAgICAgICAgICAgICBpZGxlU25hcHNob3QsXG4gICAgICAgICAgICAgICdzb3VyY2UtcmVmcmVzaCcsXG4gICAgICAgICAgICAgIGBzb3VyY2U6JHtmaWVsZFBhdGh9OiR7cm93SWR9OmlkbGVgLFxuICAgICAgICAgICAgKVxuICAgICAgICAgICAgaWYgKHdyb3RlSWRsZVBhdGgpIHtcbiAgICAgICAgICAgICAgY29uc3QgZXZlbnQ6IFJlcGxheUxvZy5SZXBsYXlMb2dFdmVudCA9IHtcbiAgICAgICAgICAgICAgICBfdGFnOiAnUmVzb3VyY2VTbmFwc2hvdCcsXG4gICAgICAgICAgICAgICAgcmVzb3VyY2VJZCxcbiAgICAgICAgICAgICAgICBmaWVsZFBhdGg6IHdyb3RlSWRsZVBhdGgsXG4gICAgICAgICAgICAgICAga2V5SGFzaDogdW5kZWZpbmVkLFxuICAgICAgICAgICAgICAgIGNvbmN1cnJlbmN5OiBtb2RlLFxuICAgICAgICAgICAgICAgIHBoYXNlOiAnaWRsZScsXG4gICAgICAgICAgICAgICAgc25hcHNob3Q6IGlkbGVTbmFwc2hvdCxcbiAgICAgICAgICAgICAgICB0aW1lc3RhbXA6IERhdGUubm93KCksXG4gICAgICAgICAgICAgICAgbW9kdWxlSWQsXG4gICAgICAgICAgICAgICAgaW5zdGFuY2VJZCxcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICByZWNvcmRSZXBsYXlFdmVudChib3VuZCwgZXZlbnQpXG4gICAgICAgICAgICAgIHlpZWxkKiByZWNvcmRTbmFwc2hvdChyZXBsYXlNb2RlLCByZXBsYXlMb2csIGV2ZW50KVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29udGludWVcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBjb25zdCBoID0gaGFzaEtleShrZXkpXG5cbiAgICAgICAgICAvLyBrZXlIYXNoIHVuY2hhbmdlZDogYXZvaWQgcmVkdW5kYW50IHJlZnJlc2ggd2hpbGUga2VlcGluZyBpbi1mbGlnaHQuXG4gICAgICAgICAgaWYgKCFmb3JjZSAmJiBjdXJyZW50ICYmIGN1cnJlbnQua2V5SGFzaCA9PT0gaCkge1xuICAgICAgICAgICAgY29udGludWVcbiAgICAgICAgICB9XG5cbiAgICAgICAgICAvLyBOb3QgaW4tZmxpZ2h0OiBpZiBzbmFwc2hvdC5rZXlIYXNoIGFscmVhZHkgbWF0Y2hlcywgdHJlYXQgaXQgYXMgYWxyZWFkeSB1cC10by1kYXRlIChhdm9pZCBmdWxsIHJlZnJlc2ggYW5kIHJvdyBqaXR0ZXIpLlxuICAgICAgICAgIGNvbnN0IHByZXZLZXlIYXNoID1cbiAgICAgICAgICAgIHByZXZTbmFwc2hvdCAmJiB0eXBlb2YgcHJldlNuYXBzaG90ID09PSAnb2JqZWN0JyA/IChwcmV2U25hcHNob3QgYXMgYW55KS5rZXlIYXNoIDogdW5kZWZpbmVkXG4gICAgICAgICAgaWYgKCFmb3JjZSAmJiAhY3VycmVudCAmJiBwcmV2S2V5SGFzaCA9PT0gaCkge1xuICAgICAgICAgICAgY29udGludWVcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAobW9kZSA9PT0gJ2V4aGF1c3QtdHJhaWxpbmcnICYmIGN1cnJlbnQpIHtcbiAgICAgICAgICAgIHRyYWlsaW5nLnNldChyb3dJZCwgeyBrZXksIGtleUhhc2g6IGggfSlcbiAgICAgICAgICAgIGNvbnN0IGxvYWRpbmdTbmFwc2hvdCA9IFNuYXBzaG90LmxvYWRpbmcoeyBrZXlIYXNoOiBoIH0pXG4gICAgICAgICAgICBjb25zdCB3cm90ZUxvYWRpbmdQYXRoID0geWllbGQqIHNldFNuYXBzaG90Rm9yUm93SW5UeG4oXG4gICAgICAgICAgICAgIHJvd0lkLFxuICAgICAgICAgICAgICBsb2FkaW5nU25hcHNob3QsXG4gICAgICAgICAgICAgICdzb3VyY2UtcmVmcmVzaCcsXG4gICAgICAgICAgICAgIGBzb3VyY2U6JHtmaWVsZFBhdGh9OiR7cm93SWR9OmxvYWRpbmdgLFxuICAgICAgICAgICAgKVxuICAgICAgICAgICAgaWYgKHdyb3RlTG9hZGluZ1BhdGgpIHtcbiAgICAgICAgICAgICAgY29uc3QgZXZlbnQ6IFJlcGxheUxvZy5SZXBsYXlMb2dFdmVudCA9IHtcbiAgICAgICAgICAgICAgICBfdGFnOiAnUmVzb3VyY2VTbmFwc2hvdCcsXG4gICAgICAgICAgICAgICAgcmVzb3VyY2VJZCxcbiAgICAgICAgICAgICAgICBmaWVsZFBhdGg6IHdyb3RlTG9hZGluZ1BhdGgsXG4gICAgICAgICAgICAgICAga2V5SGFzaDogaCxcbiAgICAgICAgICAgICAgICBjb25jdXJyZW5jeTogbW9kZSxcbiAgICAgICAgICAgICAgICBwaGFzZTogJ2xvYWRpbmcnLFxuICAgICAgICAgICAgICAgIHNuYXBzaG90OiBsb2FkaW5nU25hcHNob3QsXG4gICAgICAgICAgICAgICAgdGltZXN0YW1wOiBEYXRlLm5vdygpLFxuICAgICAgICAgICAgICAgIG1vZHVsZUlkLFxuICAgICAgICAgICAgICAgIGluc3RhbmNlSWQsXG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgcmVjb3JkUmVwbGF5RXZlbnQoYm91bmQsIGV2ZW50KVxuICAgICAgICAgICAgICB5aWVsZCogcmVjb3JkU25hcHNob3QocmVwbGF5TW9kZSwgcmVwbGF5TG9nLCBldmVudClcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnRpbnVlXG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKG1vZGUgPT09ICdzd2l0Y2gnICYmIGN1cnJlbnQpIHtcbiAgICAgICAgICAgIC8vIERvIG5vdCByZWx5IG9uIGNhbmNlbGxhdGlvbiBjb3JyZWN0bmVzczogc3RhbGUgd3JpdGViYWNrcyBhcmUgZHJvcHBlZCBieSB0aGUga2V5SGFzaCBnYXRlLlxuICAgICAgICAgICAgdHJhaWxpbmcuZGVsZXRlKHJvd0lkKVxuICAgICAgICAgICAgaW5GbGlnaHQuZGVsZXRlKHJvd0lkKVxuICAgICAgICAgIH1cblxuICAgICAgICAgIHlpZWxkKiBzdGFydEZldGNoKHJvd0lkLCBrZXksIGgsIHJlcGxheU1vZGUsIHJlcGxheUxvZylcbiAgICAgICAgfVxuICAgICAgfSksXG4gICAgKVxuXG4gICAgcmV0dXJuIEVmZmVjdC52b2lkXG4gIH1cblxuICAvLyBpbi1mbGlnaHQgc3RhdGUgKHBlciBmaWVsZClcbiAgbGV0IGluRmxpZ2h0OlxuICAgIHwge1xuICAgICAgICByZWFkb25seSBnZW46IG51bWJlclxuICAgICAgICByZWFkb25seSBmaWJlcjogRmliZXIuUnVudGltZUZpYmVyPHZvaWQsIG5ldmVyPlxuICAgICAgICByZWFkb25seSBrZXlIYXNoOiBzdHJpbmdcbiAgICAgIH1cbiAgICB8IHVuZGVmaW5lZFxuICBsZXQgZ2VuID0gMFxuICBsZXQgdHJhaWxpbmc6IHsgcmVhZG9ubHkga2V5OiB1bmtub3duOyByZWFkb25seSBrZXlIYXNoOiBzdHJpbmcgfSB8IHVuZGVmaW5lZFxuXG4gIGNvbnN0IGNvbmN1cnJlbmN5ID0gKGVudHJ5Lm1ldGEgYXMgYW55KS5jb25jdXJyZW5jeSBhcyAnc3dpdGNoJyB8ICdleGhhdXN0LXRyYWlsaW5nJyB8IHVuZGVmaW5lZFxuICBjb25zdCBtb2RlID0gY29uY3VycmVuY3kgPz8gJ3N3aXRjaCdcblxuICBjb25zdCBzdGFydEZldGNoID0gKFxuICAgIGtleTogdW5rbm93bixcbiAgICBrZXlIYXNoOiBzdHJpbmcsXG4gICAgcmVwbGF5TW9kZTogJ2xpdmUnIHwgJ3JlcGxheScsXG4gICAgcmVwbGF5TG9nOiBSZXBsYXlMb2cuUmVwbGF5TG9nU2VydmljZSB8IHVuZGVmaW5lZCxcbiAgKTogRWZmZWN0LkVmZmVjdDx2b2lkLCBuZXZlciwgYW55PiA9PlxuICAgIEVmZmVjdC5nZW4oZnVuY3Rpb24qICgpIHtcbiAgICAgIGNvbnN0IHsgbW9kdWxlSWQsIGluc3RhbmNlSWQgfSA9IGdldEJvdW5kU2NvcGUoYm91bmQpXG5cbiAgICAgIC8vIDEpIHBlbmRpbmc6IHN5bmNocm9ub3VzbHkgd3JpdGUgYSBsb2FkaW5nIHNuYXBzaG90ICh3aXRoaW4gdGhlIGN1cnJlbnQgdHJhbnNhY3Rpb24gd2luZG93KS5cbiAgICAgIGxldCBsb2FkaW5nU25hcHNob3Q6IHVua25vd24gPSBTbmFwc2hvdC5sb2FkaW5nKHsga2V5SGFzaCB9KVxuICAgICAgaWYgKHJlcGxheU1vZGUgPT09ICdyZXBsYXknICYmIHJlcGxheUxvZykge1xuICAgICAgICBjb25zdCByZXBsYXlMb2FkaW5nID0geWllbGQqIHJlcGxheUxvZy5jb25zdW1lTmV4dFJlc291cmNlU25hcHNob3Qoe1xuICAgICAgICAgIHJlc291cmNlSWQsXG4gICAgICAgICAgZmllbGRQYXRoLFxuICAgICAgICAgIGtleUhhc2gsXG4gICAgICAgICAgcGhhc2U6ICdsb2FkaW5nJyxcbiAgICAgICAgfSlcbiAgICAgICAgaWYgKHJlcGxheUxvYWRpbmcpIHtcbiAgICAgICAgICBsb2FkaW5nU25hcHNob3QgPSByZXBsYXlMb2FkaW5nLnNuYXBzaG90XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGNvbnN0IHdyb3RlTG9hZGluZyA9IHlpZWxkKiBzZXRTbmFwc2hvdEluVHhuKFxuICAgICAgICBib3VuZCxcbiAgICAgICAgZmllbGRQYXRoLFxuICAgICAgICBsb2FkaW5nU25hcHNob3QsXG4gICAgICAgICdzb3VyY2UtcmVmcmVzaCcsXG4gICAgICAgIGBzb3VyY2U6JHtmaWVsZFBhdGh9OmxvYWRpbmdgLFxuICAgICAgICBzdGVwLmRlYnVnSW5mbz8uZ3JhcGhOb2RlSWQsXG4gICAgICApXG4gICAgICBpZiAod3JvdGVMb2FkaW5nKSB7XG4gICAgICAgIGNvbnN0IGV2ZW50OiBSZXBsYXlMb2cuUmVwbGF5TG9nRXZlbnQgPSB7XG4gICAgICAgICAgX3RhZzogJ1Jlc291cmNlU25hcHNob3QnLFxuICAgICAgICAgIHJlc291cmNlSWQsXG4gICAgICAgICAgZmllbGRQYXRoLFxuICAgICAgICAgIGtleUhhc2gsXG4gICAgICAgICAgY29uY3VycmVuY3k6IG1vZGUsXG4gICAgICAgICAgcGhhc2U6ICdsb2FkaW5nJyxcbiAgICAgICAgICBzbmFwc2hvdDogbG9hZGluZ1NuYXBzaG90LFxuICAgICAgICAgIHRpbWVzdGFtcDogRGF0ZS5ub3coKSxcbiAgICAgICAgICBtb2R1bGVJZCxcbiAgICAgICAgICBpbnN0YW5jZUlkLFxuICAgICAgICB9XG4gICAgICAgIHJlY29yZFJlcGxheUV2ZW50KGJvdW5kLCBldmVudClcbiAgICAgICAgeWllbGQqIHJlY29yZFNuYXBzaG90KHJlcGxheU1vZGUsIHJlcGxheUxvZywgZXZlbnQpXG4gICAgICB9XG5cbiAgICAgIC8vIDIpIElPOiBydW4gaW4gYSBiYWNrZ3JvdW5kIGZpYmVyIChhdm9pZCBibG9ja2luZyB0aGUgY3VycmVudCB0cmFuc2FjdGlvbikuXG4gICAgICBjb25zdCBpbyA9IEVmZmVjdC5nZW4oZnVuY3Rpb24qICgpIHtcbiAgICAgICAgaWYgKHJlcGxheU1vZGUgPT09ICdyZXBsYXknICYmIHJlcGxheUxvZykge1xuICAgICAgICAgIC8vIExldCBsb2FkaW5nIGNvbW1pdCBiZWNvbWUgdmlzaWJsZSBmaXJzdCwgdGhlbiByZXBsYXkgdGhlIHNldHRsZWQgcGhhc2UgKHByZXNlcnZlIHRoZSBhc3luYy1yZXNvdXJjZSB0aW1lbGluZSBzaGFwZSkuXG4gICAgICAgICAgeWllbGQqIEVmZmVjdC55aWVsZE5vdygpXG4gICAgICAgICAgY29uc3QgcmVwbGF5ZWQgPSB5aWVsZCogcmVwbGF5TG9nLmNvbnN1bWVOZXh0UmVzb3VyY2VTbmFwc2hvdCh7XG4gICAgICAgICAgICByZXNvdXJjZUlkLFxuICAgICAgICAgICAgZmllbGRQYXRoLFxuICAgICAgICAgICAga2V5SGFzaCxcbiAgICAgICAgICB9KVxuICAgICAgICAgIGlmICghcmVwbGF5ZWQpIHJldHVybiB5aWVsZCogRWZmZWN0LnZvaWRcblxuICAgICAgICAgIGlmIChyZXBsYXllZC5waGFzZSA9PT0gJ3N1Y2Nlc3MnKSB7XG4gICAgICAgICAgICBjb25zdCBldmVudDogUmVwbGF5TG9nLlJlcGxheUxvZ0V2ZW50ID0ge1xuICAgICAgICAgICAgICBfdGFnOiAnUmVzb3VyY2VTbmFwc2hvdCcsXG4gICAgICAgICAgICAgIHJlc291cmNlSWQsXG4gICAgICAgICAgICAgIGZpZWxkUGF0aCxcbiAgICAgICAgICAgICAga2V5SGFzaCxcbiAgICAgICAgICAgICAgY29uY3VycmVuY3k6IG1vZGUsXG4gICAgICAgICAgICAgIHBoYXNlOiAnc3VjY2VzcycsXG4gICAgICAgICAgICAgIHNuYXBzaG90OiByZXBsYXllZC5zbmFwc2hvdCxcbiAgICAgICAgICAgICAgdGltZXN0YW1wOiBEYXRlLm5vdygpLFxuICAgICAgICAgICAgICBtb2R1bGVJZCxcbiAgICAgICAgICAgICAgaW5zdGFuY2VJZCxcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHlpZWxkKiB3cml0ZWJhY2tJZkN1cnJlbnRLZXlIYXNoKFxuICAgICAgICAgICAgICBib3VuZCxcbiAgICAgICAgICAgICAgZmllbGRQYXRoLFxuICAgICAgICAgICAgICBrZXlIYXNoLFxuICAgICAgICAgICAgICByZXBsYXllZC5zbmFwc2hvdCxcbiAgICAgICAgICAgICAgJ3NvdXJjZS1yZWZyZXNoJyxcbiAgICAgICAgICAgICAgYHNvdXJjZToke2ZpZWxkUGF0aH06c3VjY2Vzc2AsXG4gICAgICAgICAgICAgIHN0ZXAuZGVidWdJbmZvPy5ncmFwaE5vZGVJZCxcbiAgICAgICAgICAgICAgZXZlbnQsXG4gICAgICAgICAgICApXG4gICAgICAgICAgfSBlbHNlIGlmIChyZXBsYXllZC5waGFzZSA9PT0gJ2Vycm9yJykge1xuICAgICAgICAgICAgY29uc3QgZXZlbnQ6IFJlcGxheUxvZy5SZXBsYXlMb2dFdmVudCA9IHtcbiAgICAgICAgICAgICAgX3RhZzogJ1Jlc291cmNlU25hcHNob3QnLFxuICAgICAgICAgICAgICByZXNvdXJjZUlkLFxuICAgICAgICAgICAgICBmaWVsZFBhdGgsXG4gICAgICAgICAgICAgIGtleUhhc2gsXG4gICAgICAgICAgICAgIGNvbmN1cnJlbmN5OiBtb2RlLFxuICAgICAgICAgICAgICBwaGFzZTogJ2Vycm9yJyxcbiAgICAgICAgICAgICAgc25hcHNob3Q6IHJlcGxheWVkLnNuYXBzaG90LFxuICAgICAgICAgICAgICB0aW1lc3RhbXA6IERhdGUubm93KCksXG4gICAgICAgICAgICAgIG1vZHVsZUlkLFxuICAgICAgICAgICAgICBpbnN0YW5jZUlkLFxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgeWllbGQqIHdyaXRlYmFja0lmQ3VycmVudEtleUhhc2goXG4gICAgICAgICAgICAgIGJvdW5kLFxuICAgICAgICAgICAgICBmaWVsZFBhdGgsXG4gICAgICAgICAgICAgIGtleUhhc2gsXG4gICAgICAgICAgICAgIHJlcGxheWVkLnNuYXBzaG90LFxuICAgICAgICAgICAgICAnc291cmNlLXJlZnJlc2gnLFxuICAgICAgICAgICAgICBgc291cmNlOiR7ZmllbGRQYXRofTplcnJvcmAsXG4gICAgICAgICAgICAgIHN0ZXAuZGVidWdJbmZvPy5ncmFwaE5vZGVJZCxcbiAgICAgICAgICAgICAgZXZlbnQsXG4gICAgICAgICAgICApXG4gICAgICAgICAgfVxuXG4gICAgICAgICAgcmV0dXJuIHlpZWxkKiBFZmZlY3Qudm9pZFxuICAgICAgICB9XG5cbiAgICAgICAgY29uc3Qgc3RhY2sgPSB5aWVsZCogZ2V0TWlkZGxld2FyZVN0YWNrKClcblxuICAgICAgICBjb25zdCByZWdpc3RyeU9wdCA9IHlpZWxkKiBFZmZlY3Quc2VydmljZU9wdGlvbihSZXNvdXJjZUludGVybmFsLlJlc291cmNlUmVnaXN0cnlUYWcpXG4gICAgICAgIGNvbnN0IHJlZ2lzdHJ5ID0gT3B0aW9uLmlzU29tZShyZWdpc3RyeU9wdCkgPyByZWdpc3RyeU9wdC52YWx1ZSA6IHVuZGVmaW5lZFxuICAgICAgICBjb25zdCBzcGVjID0gcmVnaXN0cnk/LnNwZWNzLmdldChyZXNvdXJjZUlkKVxuXG4gICAgICAgIGlmICghc3BlYykge1xuICAgICAgICAgIHJldHVybiB5aWVsZCogRWZmZWN0LnZvaWRcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGxvYWRFZmZlY3QgPSAoc3BlYy5sb2FkIGFzIGFueSkoa2V5KSBhcyBFZmZlY3QuRWZmZWN0PGFueSwgYW55LCBhbnk+XG5cbiAgICAgICAgY29uc3QgbWV0YTogYW55ID0ge1xuICAgICAgICAgIG1vZHVsZUlkLFxuICAgICAgICAgIGluc3RhbmNlSWQsXG4gICAgICAgICAgZmllbGRQYXRoLFxuICAgICAgICAgIHJlc291cmNlSWQsXG4gICAgICAgICAga2V5LFxuICAgICAgICAgIGtleUhhc2gsXG4gICAgICAgICAgdHJhaXROb2RlSWQ6IHN0ZXAuZGVidWdJbmZvPy5ncmFwaE5vZGVJZCxcbiAgICAgICAgICBzdGVwSWQ6IHN0ZXAuaWQsXG4gICAgICAgIH1cblxuICAgICAgICBpZiAoISh0eXBlb2YgbWV0YS5vcFNlcSA9PT0gJ251bWJlcicgJiYgTnVtYmVyLmlzRmluaXRlKG1ldGEub3BTZXEpKSkge1xuICAgICAgICAgIGNvbnN0IHNlc3Npb25PcHQgPSB5aWVsZCogRWZmZWN0LnNlcnZpY2VPcHRpb24oUnVuU2Vzc2lvblRhZylcbiAgICAgICAgICBpZiAoT3B0aW9uLmlzU29tZShzZXNzaW9uT3B0KSkge1xuICAgICAgICAgICAgY29uc3Qgc2VxS2V5ID0gaW5zdGFuY2VJZCA/PyAnZ2xvYmFsJ1xuICAgICAgICAgICAgbWV0YS5vcFNlcSA9IHNlc3Npb25PcHQudmFsdWUubG9jYWwubmV4dFNlcSgnb3BTZXEnLCBzZXFLZXkpXG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgY29uc3Qgb3AgPSBFZmZlY3RPcC5tYWtlPGFueSwgYW55LCBhbnk+KHtcbiAgICAgICAgICBraW5kOiAndHJhaXQtc291cmNlJyxcbiAgICAgICAgICBuYW1lOiByZXNvdXJjZUlkLFxuICAgICAgICAgIGVmZmVjdDogbG9hZEVmZmVjdCxcbiAgICAgICAgICBtZXRhLFxuICAgICAgICB9KVxuXG4gICAgICAgIGNvbnN0IGV4aXQgPSB5aWVsZCogRWZmZWN0LmV4aXQoRWZmZWN0T3AucnVuKG9wLCBzdGFjaykpXG5cbiAgICAgICAgLy8gMykgd3JpdGViYWNrOiB1c2UgYSBrZXlIYXNoIGdhdGUgdG8gcHJldmVudCBzdGFsZSByZXN1bHRzIGZyb20gd3JpdGluZyBiYWNrIG9udG8gYSBuZXcga2V5LlxuICAgICAgICBpZiAoZXhpdC5fdGFnID09PSAnU3VjY2VzcycpIHtcbiAgICAgICAgICBjb25zdCBzdWNjZXNzU25hcHNob3QgPSBTbmFwc2hvdC5zdWNjZXNzKHsga2V5SGFzaCwgZGF0YTogZXhpdC52YWx1ZSB9KVxuICAgICAgICAgIGNvbnN0IGV2ZW50OiBSZXBsYXlMb2cuUmVwbGF5TG9nRXZlbnQgPSB7XG4gICAgICAgICAgICBfdGFnOiAnUmVzb3VyY2VTbmFwc2hvdCcsXG4gICAgICAgICAgICByZXNvdXJjZUlkLFxuICAgICAgICAgICAgZmllbGRQYXRoLFxuICAgICAgICAgICAga2V5SGFzaCxcbiAgICAgICAgICAgIGNvbmN1cnJlbmN5OiBtb2RlLFxuICAgICAgICAgICAgcGhhc2U6ICdzdWNjZXNzJyxcbiAgICAgICAgICAgIHNuYXBzaG90OiBzdWNjZXNzU25hcHNob3QsXG4gICAgICAgICAgICB0aW1lc3RhbXA6IERhdGUubm93KCksXG4gICAgICAgICAgICBtb2R1bGVJZCxcbiAgICAgICAgICAgIGluc3RhbmNlSWQsXG4gICAgICAgICAgfVxuICAgICAgICAgIGNvbnN0IHdyb3RlU3VjY2VzcyA9IHlpZWxkKiB3cml0ZWJhY2tJZkN1cnJlbnRLZXlIYXNoKFxuICAgICAgICAgICAgYm91bmQsXG4gICAgICAgICAgICBmaWVsZFBhdGgsXG4gICAgICAgICAgICBrZXlIYXNoLFxuICAgICAgICAgICAgc3VjY2Vzc1NuYXBzaG90LFxuICAgICAgICAgICAgJ3NvdXJjZS1yZWZyZXNoJyxcbiAgICAgICAgICAgIGBzb3VyY2U6JHtmaWVsZFBhdGh9OnN1Y2Nlc3NgLFxuICAgICAgICAgICAgc3RlcC5kZWJ1Z0luZm8/LmdyYXBoTm9kZUlkLFxuICAgICAgICAgICAgZXZlbnQsXG4gICAgICAgICAgKVxuICAgICAgICAgIGlmICh3cm90ZVN1Y2Nlc3MpIHtcbiAgICAgICAgICAgIHlpZWxkKiByZWNvcmRTbmFwc2hvdChyZXBsYXlNb2RlLCByZXBsYXlMb2csIGV2ZW50KVxuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBjb25zdCBlcnJvclNuYXBzaG90ID0gU25hcHNob3QuZXJyb3IoeyBrZXlIYXNoLCBlcnJvcjogZXhpdC5jYXVzZSB9KVxuICAgICAgICAgIGNvbnN0IGV2ZW50OiBSZXBsYXlMb2cuUmVwbGF5TG9nRXZlbnQgPSB7XG4gICAgICAgICAgICBfdGFnOiAnUmVzb3VyY2VTbmFwc2hvdCcsXG4gICAgICAgICAgICByZXNvdXJjZUlkLFxuICAgICAgICAgICAgZmllbGRQYXRoLFxuICAgICAgICAgICAga2V5SGFzaCxcbiAgICAgICAgICAgIGNvbmN1cnJlbmN5OiBtb2RlLFxuICAgICAgICAgICAgcGhhc2U6ICdlcnJvcicsXG4gICAgICAgICAgICBzbmFwc2hvdDogZXJyb3JTbmFwc2hvdCxcbiAgICAgICAgICAgIHRpbWVzdGFtcDogRGF0ZS5ub3coKSxcbiAgICAgICAgICAgIG1vZHVsZUlkLFxuICAgICAgICAgICAgaW5zdGFuY2VJZCxcbiAgICAgICAgICB9XG4gICAgICAgICAgY29uc3Qgd3JvdGVFcnJvciA9IHlpZWxkKiB3cml0ZWJhY2tJZkN1cnJlbnRLZXlIYXNoKFxuICAgICAgICAgICAgYm91bmQsXG4gICAgICAgICAgICBmaWVsZFBhdGgsXG4gICAgICAgICAgICBrZXlIYXNoLFxuICAgICAgICAgICAgZXJyb3JTbmFwc2hvdCxcbiAgICAgICAgICAgICdzb3VyY2UtcmVmcmVzaCcsXG4gICAgICAgICAgICBgc291cmNlOiR7ZmllbGRQYXRofTplcnJvcmAsXG4gICAgICAgICAgICBzdGVwLmRlYnVnSW5mbz8uZ3JhcGhOb2RlSWQsXG4gICAgICAgICAgICBldmVudCxcbiAgICAgICAgICApXG4gICAgICAgICAgaWYgKHdyb3RlRXJyb3IpIHtcbiAgICAgICAgICAgIHlpZWxkKiByZWNvcmRTbmFwc2hvdChyZXBsYXlNb2RlLCByZXBsYXlMb2csIGV2ZW50KVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfSkucGlwZShFZmZlY3QuY2F0Y2hBbGxDYXVzZSgoKSA9PiBFZmZlY3Qudm9pZCkpXG5cbiAgICAgIC8vIERvIG5vdCB3YWl0IGZvciBJTyBjb21wbGV0aW9uOiBmb3JrU2NvcGVkIGludG8gdGhlIHJ1bnRpbWUgc2NvcGUgc28gdW5tb3VudCB3aWxsIGludGVycnVwdCBhdXRvbWF0aWNhbGx5LlxuICAgICAgY29uc3QgZmliZXIgPSB5aWVsZCogRWZmZWN0LmZvcmtTY29wZWQoRWZmZWN0LmxvY2FsbHkoVGFza1J1bm5lci5pblN5bmNUcmFuc2FjdGlvbkZpYmVyLCBmYWxzZSkoaW8pKVxuICAgICAgY29uc3QgbXlHZW4gPSAoZ2VuICs9IDEpXG4gICAgICBpbkZsaWdodCA9IHsgZ2VuOiBteUdlbiwgZmliZXIsIGtleUhhc2ggfVxuXG4gICAgICAvLyBBZnRlciBpbi1mbGlnaHQgY29tcGxldGVzLCBjbGVhbiB1cDsgaW4gZXhoYXVzdC10cmFpbGluZyBtb2RlLCBydW4gb25lIHRyYWlsaW5nIGZldGNoIGlmIHByZXNlbnQuXG4gICAgICB5aWVsZCogRWZmZWN0LmZvcmtTY29wZWQoXG4gICAgICAgIEVmZmVjdC5sb2NhbGx5KFxuICAgICAgICAgIFRhc2tSdW5uZXIuaW5TeW5jVHJhbnNhY3Rpb25GaWJlcixcbiAgICAgICAgICBmYWxzZSxcbiAgICAgICAgKShcbiAgICAgICAgICBGaWJlci5hd2FpdChmaWJlcikucGlwZShcbiAgICAgICAgICAgIEVmZmVjdC56aXBSaWdodChcbiAgICAgICAgICAgICAgRWZmZWN0LnN5bmMoKCkgPT4ge1xuICAgICAgICAgICAgICAgIGlmIChpbkZsaWdodCAmJiBpbkZsaWdodC5nZW4gPT09IG15R2VuKSB7XG4gICAgICAgICAgICAgICAgICBpbkZsaWdodCA9IHVuZGVmaW5lZFxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgfSksXG4gICAgICAgICAgICApLFxuICAgICAgICAgICAgRWZmZWN0LnppcFJpZ2h0KFxuICAgICAgICAgICAgICBtb2RlID09PSAnZXhoYXVzdC10cmFpbGluZydcbiAgICAgICAgICAgICAgICA/IEVmZmVjdC5nZW4oZnVuY3Rpb24qICgpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgbmV4dCA9IHRyYWlsaW5nXG4gICAgICAgICAgICAgICAgICAgIHRyYWlsaW5nID0gdW5kZWZpbmVkXG4gICAgICAgICAgICAgICAgICAgIGlmIChuZXh0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgeWllbGQqIHN0YXJ0RmV0Y2gobmV4dC5rZXksIG5leHQua2V5SGFzaCwgcmVwbGF5TW9kZSwgcmVwbGF5TG9nKVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgIDogRWZmZWN0LnZvaWQsXG4gICAgICAgICAgICApLFxuICAgICAgICAgICAgRWZmZWN0LmNhdGNoQWxsQ2F1c2UoKCkgPT4gRWZmZWN0LnZvaWQpLFxuICAgICAgICAgICksXG4gICAgICAgICksXG4gICAgICApXG4gICAgfSlcblxuICByZWdpc3RlcihmaWVsZFBhdGgsIChzdGF0ZTogYW55KSA9PlxuICAgIEVmZmVjdC5nZW4oZnVuY3Rpb24qICgpIHtcbiAgICAgIGNvbnN0IHsgbW9kdWxlSWQsIGluc3RhbmNlSWQgfSA9IGdldEJvdW5kU2NvcGUoYm91bmQpXG4gICAgICBjb25zdCByZXBsYXlNb2RlT3B0ID0geWllbGQqIEVmZmVjdC5zZXJ2aWNlT3B0aW9uKFJlcGxheU1vZGVDb25maWdUYWcpXG4gICAgICBjb25zdCByZXBsYXlNb2RlID0gT3B0aW9uLmlzU29tZShyZXBsYXlNb2RlT3B0KSA/IHJlcGxheU1vZGVPcHQudmFsdWUubW9kZSA6ICdsaXZlJ1xuICAgICAgY29uc3QgcmVwbGF5TG9nT3B0ID0geWllbGQqIEVmZmVjdC5zZXJ2aWNlT3B0aW9uKFJlcGxheUxvZy5SZXBsYXlMb2cpXG4gICAgICBjb25zdCByZXBsYXlMb2cgPSBPcHRpb24uaXNTb21lKHJlcGxheUxvZ09wdCkgPyByZXBsYXlMb2dPcHQudmFsdWUgOiB1bmRlZmluZWRcbiAgICAgIGNvbnN0IGZvcmNlID0geWllbGQqIEZpYmVyUmVmLmdldChUYXNrUnVubmVyLmZvcmNlU291cmNlUmVmcmVzaClcblxuICAgICAgbGV0IGtleTogdW5rbm93blxuICAgICAgdHJ5IHtcbiAgICAgICAga2V5ID0gKGVudHJ5Lm1ldGEgYXMgYW55KS5rZXkoc3RhdGUpXG4gICAgICB9IGNhdGNoIHtcbiAgICAgICAga2V5ID0gdW5kZWZpbmVkXG4gICAgICB9XG5cbiAgICAgIC8vIGRldi1tb2RlOiBkZXRlY3QgbWlzbWF0Y2ggYmV0d2VlbiBhY3R1YWwgcmVhZHMgaW4ga2V5U2VsZWN0b3IgYW5kIGRlY2xhcmVkIGRlcHMgKGRpYWdub3N0aWNzIG9ubHk7IGRvZXMgbm90IGFmZmVjdCBleGVjdXRpb24gc2VtYW50aWNzKS5cbiAgICAgIGNvbnN0IHRyYWNlS2V5ID0gYCR7aW5zdGFuY2VJZCA/PyAndW5rbm93bid9Ojpzb3VyY2U6OiR7ZmllbGRQYXRofWBcbiAgICAgIGlmIChpc0RldkVudigpICYmICh5aWVsZCogb25jZUluUnVuU2Vzc2lvbihgZGVwc190cmFjZV9zZXR0bGVkOiR7dHJhY2VLZXl9YCkpKSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgY29uc3QgdHJhY2VkID0gRGVwc1RyYWNlLnRyYWNlKChzKSA9PiAoZW50cnkubWV0YSBhcyBhbnkpLmtleShzKSwgc3RhdGUpXG4gICAgICAgICAgY29uc3QgZGlmZiA9IERlcHNUcmFjZS5kaWZmRGVwcygoKGVudHJ5Lm1ldGEgYXMgYW55KS5kZXBzID8/IFtdKSBhcyBSZWFkb25seUFycmF5PHN0cmluZz4sIHRyYWNlZC5yZWFkcylcbiAgICAgICAgICBpZiAoZGlmZikge1xuICAgICAgICAgICAgeWllbGQqIGVtaXREZXBzTWlzbWF0Y2goe1xuICAgICAgICAgICAgICBtb2R1bGVJZCxcbiAgICAgICAgICAgICAgaW5zdGFuY2VJZCxcbiAgICAgICAgICAgICAga2luZDogJ3NvdXJjZScsXG4gICAgICAgICAgICAgIGZpZWxkUGF0aCxcbiAgICAgICAgICAgICAgZGlmZixcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgfVxuICAgICAgICB9IGNhdGNoIHtcbiAgICAgICAgICAvLyB0cmFjaW5nIGZhaWx1cmUgc2hvdWxkIG5ldmVyIGJyZWFrIHJlZnJlc2ggZmxvd1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIC8vIEtleSBiZWNvbWVzIGVtcHR5OiBzeW5jaHJvbm91c2x5IGNsZWFyIHRvIGlkbGUgKGFuZCBpbnRlcnJ1cHQgaW4tZmxpZ2h0KS5cbiAgICAgIGlmIChrZXkgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICBpZiAoaW5GbGlnaHQpIHtcbiAgICAgICAgICB5aWVsZCogRmliZXIuaW50ZXJydXB0Rm9yayhpbkZsaWdodC5maWJlcilcbiAgICAgICAgICBpbkZsaWdodCA9IHVuZGVmaW5lZFxuICAgICAgICB9XG4gICAgICAgIHRyYWlsaW5nID0gdW5kZWZpbmVkXG5cbiAgICAgICAgY29uc3QgaWRsZVNuYXBzaG90ID0gU25hcHNob3QuaWRsZSgpXG4gICAgICAgIGNvbnN0IHdyb3RlSWRsZSA9IHlpZWxkKiBzZXRTbmFwc2hvdEluVHhuKFxuICAgICAgICAgIGJvdW5kLFxuICAgICAgICAgIGZpZWxkUGF0aCxcbiAgICAgICAgICBpZGxlU25hcHNob3QsXG4gICAgICAgICAgJ3NvdXJjZS1yZWZyZXNoJyxcbiAgICAgICAgICBgc291cmNlOiR7ZmllbGRQYXRofTppZGxlYCxcbiAgICAgICAgICBzdGVwLmRlYnVnSW5mbz8uZ3JhcGhOb2RlSWQsXG4gICAgICAgIClcbiAgICAgICAgaWYgKHdyb3RlSWRsZSkge1xuICAgICAgICAgIGNvbnN0IGV2ZW50OiBSZXBsYXlMb2cuUmVwbGF5TG9nRXZlbnQgPSB7XG4gICAgICAgICAgICBfdGFnOiAnUmVzb3VyY2VTbmFwc2hvdCcsXG4gICAgICAgICAgICByZXNvdXJjZUlkLFxuICAgICAgICAgICAgZmllbGRQYXRoLFxuICAgICAgICAgICAga2V5SGFzaDogdW5kZWZpbmVkLFxuICAgICAgICAgICAgY29uY3VycmVuY3k6IG1vZGUsXG4gICAgICAgICAgICBwaGFzZTogJ2lkbGUnLFxuICAgICAgICAgICAgc25hcHNob3Q6IGlkbGVTbmFwc2hvdCxcbiAgICAgICAgICAgIHRpbWVzdGFtcDogRGF0ZS5ub3coKSxcbiAgICAgICAgICAgIG1vZHVsZUlkLFxuICAgICAgICAgICAgaW5zdGFuY2VJZCxcbiAgICAgICAgICB9XG4gICAgICAgICAgcmVjb3JkUmVwbGF5RXZlbnQoYm91bmQsIGV2ZW50KVxuICAgICAgICAgIHlpZWxkKiByZWNvcmRTbmFwc2hvdChyZXBsYXlNb2RlLCByZXBsYXlMb2csIGV2ZW50KVxuICAgICAgICB9XG4gICAgICAgIHJldHVyblxuICAgICAgfVxuXG4gICAgICBjb25zdCBoID0gaGFzaEtleShrZXkpXG5cbiAgICAgIC8vIERlZmF1bHQgc2VtYW50aWNzOiB3aGVuIGEgbm9uLWlkbGUgc25hcHNob3QgYWxyZWFkeSBleGlzdHMgZm9yIHRoZSBzYW1lIGtleUhhc2gsIHJlZnJlc2ggc2hvdWxkIGJlIGEgbm8tb3Agd2hlbiBwb3NzaWJsZVxuICAgICAgLy8gKGF2b2lkIGR1cGxpY2F0ZSBJTy93cml0ZWJhY2spLiBFeHBsaWNpdCByZWZyZXNoL2ludmFsaWRhdGUgY2FuIGJ5cGFzcyB2aWEgZm9yY2UuXG4gICAgICBpZiAoIWZvcmNlKSB7XG4gICAgICAgIGlmIChpbkZsaWdodCAmJiBpbkZsaWdodC5rZXlIYXNoID09PSBoKSB7XG4gICAgICAgICAgcmV0dXJuXG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBjdXJyZW50U25hcHNob3QgPSBSb3dJZC5nZXRBdFBhdGgoc3RhdGUsIGZpZWxkUGF0aCkgYXMgYW55XG4gICAgICAgIGNvbnN0IGN1cnJlbnRLZXlIYXNoID1cbiAgICAgICAgICBjdXJyZW50U25hcHNob3QgJiYgdHlwZW9mIGN1cnJlbnRTbmFwc2hvdCA9PT0gJ29iamVjdCcgPyAoY3VycmVudFNuYXBzaG90IGFzIGFueSkua2V5SGFzaCA6IHVuZGVmaW5lZFxuICAgICAgICBjb25zdCBjdXJyZW50U3RhdHVzID1cbiAgICAgICAgICBjdXJyZW50U25hcHNob3QgJiYgdHlwZW9mIGN1cnJlbnRTbmFwc2hvdCA9PT0gJ29iamVjdCcgPyAoY3VycmVudFNuYXBzaG90IGFzIGFueSkuc3RhdHVzIDogdW5kZWZpbmVkXG4gICAgICAgIGlmIChjdXJyZW50U3RhdHVzICYmIGN1cnJlbnRTdGF0dXMgIT09ICdpZGxlJyAmJiBjdXJyZW50S2V5SGFzaCA9PT0gaCkge1xuICAgICAgICAgIHJldHVyblxuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGlmIChtb2RlID09PSAnZXhoYXVzdC10cmFpbGluZycgJiYgaW5GbGlnaHQpIHtcbiAgICAgICAgLy8gQnVzeTogcmVjb3JkIHRyYWlsaW5nIGFuZCB1cGRhdGUgbG9hZGluZyBpbW1lZGlhdGVseTsgc3RhbGUgaW4tZmxpZ2h0IHdyaXRlYmFja3Mgd2lsbCBiZSBibG9ja2VkIGJ5IHRoZSBrZXlIYXNoIGdhdGUuXG4gICAgICAgIHRyYWlsaW5nID0geyBrZXksIGtleUhhc2g6IGggfVxuICAgICAgICBjb25zdCBsb2FkaW5nU25hcHNob3QgPSBTbmFwc2hvdC5sb2FkaW5nKHsga2V5SGFzaDogaCB9KVxuICAgICAgICBjb25zdCB3cm90ZUxvYWRpbmcgPSB5aWVsZCogc2V0U25hcHNob3RJblR4bihcbiAgICAgICAgICBib3VuZCxcbiAgICAgICAgICBmaWVsZFBhdGgsXG4gICAgICAgICAgbG9hZGluZ1NuYXBzaG90LFxuICAgICAgICAgICdzb3VyY2UtcmVmcmVzaCcsXG4gICAgICAgICAgYHNvdXJjZToke2ZpZWxkUGF0aH06bG9hZGluZ2AsXG4gICAgICAgICAgc3RlcC5kZWJ1Z0luZm8/LmdyYXBoTm9kZUlkLFxuICAgICAgICApXG4gICAgICAgIGlmICh3cm90ZUxvYWRpbmcpIHtcbiAgICAgICAgICBjb25zdCBldmVudDogUmVwbGF5TG9nLlJlcGxheUxvZ0V2ZW50ID0ge1xuICAgICAgICAgICAgX3RhZzogJ1Jlc291cmNlU25hcHNob3QnLFxuICAgICAgICAgICAgcmVzb3VyY2VJZCxcbiAgICAgICAgICAgIGZpZWxkUGF0aCxcbiAgICAgICAgICAgIGtleUhhc2g6IGgsXG4gICAgICAgICAgICBjb25jdXJyZW5jeTogbW9kZSxcbiAgICAgICAgICAgIHBoYXNlOiAnbG9hZGluZycsXG4gICAgICAgICAgICBzbmFwc2hvdDogbG9hZGluZ1NuYXBzaG90LFxuICAgICAgICAgICAgdGltZXN0YW1wOiBEYXRlLm5vdygpLFxuICAgICAgICAgICAgbW9kdWxlSWQsXG4gICAgICAgICAgICBpbnN0YW5jZUlkLFxuICAgICAgICAgIH1cbiAgICAgICAgICByZWNvcmRSZXBsYXlFdmVudChib3VuZCwgZXZlbnQpXG4gICAgICAgICAgeWllbGQqIHJlY29yZFNuYXBzaG90KHJlcGxheU1vZGUsIHJlcGxheUxvZywgZXZlbnQpXG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuXG4gICAgICB9XG5cbiAgICAgIGlmIChtb2RlID09PSAnc3dpdGNoJyAmJiBpbkZsaWdodCkge1xuICAgICAgICB5aWVsZCogRmliZXIuaW50ZXJydXB0Rm9yayhpbkZsaWdodC5maWJlcilcbiAgICAgICAgaW5GbGlnaHQgPSB1bmRlZmluZWRcbiAgICAgICAgdHJhaWxpbmcgPSB1bmRlZmluZWRcbiAgICAgIH1cblxuICAgICAgLy8gc3RhcnQgZmV0Y2ggKHBlbmRpbmcgdHggKyBmb3JrIElPKVxuICAgICAgeWllbGQqIHN0YXJ0RmV0Y2goa2V5LCBoLCByZXBsYXlNb2RlLCByZXBsYXlMb2cpXG4gICAgfSksXG4gIClcblxuICByZXR1cm4gRWZmZWN0LnZvaWRcbn1cbiIsICJleHBvcnQgaW50ZXJmYWNlIERlcHNUcmFjZVJlc3VsdDxUPiB7XG4gIHJlYWRvbmx5IHZhbHVlOiBUXG4gIHJlYWRvbmx5IHJlYWRzOiBSZWFkb25seUFycmF5PHN0cmluZz5cbn1cblxuZXhwb3J0IGludGVyZmFjZSBEZXBzRGlmZiB7XG4gIHJlYWRvbmx5IHJlYWRzOiBSZWFkb25seUFycmF5PHN0cmluZz5cbiAgcmVhZG9ubHkgZGVjbGFyZWQ6IFJlYWRvbmx5QXJyYXk8c3RyaW5nPlxuICByZWFkb25seSBtaXNzaW5nOiBSZWFkb25seUFycmF5PHN0cmluZz5cbiAgcmVhZG9ubHkgdW51c2VkOiBSZWFkb25seUFycmF5PHN0cmluZz5cbn1cblxuY29uc3QgaXNUcmFjZWFibGVPYmplY3QgPSAodmFsdWU6IHVua25vd24pOiB2YWx1ZSBpcyBvYmplY3QgPT4ge1xuICBpZiAoIXZhbHVlIHx8IHR5cGVvZiB2YWx1ZSAhPT0gJ29iamVjdCcpIHJldHVybiBmYWxzZVxuICBpZiAoQXJyYXkuaXNBcnJheSh2YWx1ZSkpIHJldHVybiB0cnVlXG4gIGlmICh2YWx1ZSBpbnN0YW5jZW9mIERhdGUpIHJldHVybiBmYWxzZVxuICBpZiAodmFsdWUgaW5zdGFuY2VvZiBSZWdFeHApIHJldHVybiBmYWxzZVxuICBpZiAodmFsdWUgaW5zdGFuY2VvZiBFcnJvcikgcmV0dXJuIGZhbHNlXG4gIGlmICh2YWx1ZSBpbnN0YW5jZW9mIE1hcCkgcmV0dXJuIGZhbHNlXG4gIGlmICh2YWx1ZSBpbnN0YW5jZW9mIFNldCkgcmV0dXJuIGZhbHNlXG4gIGlmICh2YWx1ZSBpbnN0YW5jZW9mIFdlYWtNYXApIHJldHVybiBmYWxzZVxuICBpZiAodmFsdWUgaW5zdGFuY2VvZiBXZWFrU2V0KSByZXR1cm4gZmFsc2VcbiAgcmV0dXJuIHRydWVcbn1cblxuY29uc3Qgc2hvdWxkSWdub3JlS2V5ID0gKGtleTogc3RyaW5nKTogYm9vbGVhbiA9PiBrZXkgPT09ICdfX3Byb3RvX18nIHx8IGtleSA9PT0gJ3Byb3RvdHlwZScgfHwga2V5ID09PSAnY29uc3RydWN0b3InXG5cbmNvbnN0IG5vcm1hbGl6ZVJlYWRzID0gKHJlYWRzOiBSZWFkb25seVNldDxzdHJpbmc+KTogUmVhZG9ubHlBcnJheTxzdHJpbmc+ID0+IHtcbiAgY29uc3QgYWxsID0gQXJyYXkuZnJvbShyZWFkcykuZmlsdGVyKChwKSA9PiB0eXBlb2YgcCA9PT0gJ3N0cmluZycgJiYgcC5sZW5ndGggPiAwKVxuICBhbGwuc29ydCgpXG5cbiAgLy8gRHJvcCBzdHJpY3QgcHJlZml4IHBhdGhzIChlLmcuIGlmIGJvdGggcHJvZmlsZSBhbmQgcHJvZmlsZS5pZCBhcmUgcmVhZCwga2VlcCBvbmx5IHRoZSBtb3JlIHNwZWNpZmljIHByb2ZpbGUuaWQpLlxuICBjb25zdCBpc1ByZWZpeCA9IChwcmVmaXg6IHN0cmluZywgZnVsbDogc3RyaW5nKTogYm9vbGVhbiA9PiBmdWxsICE9PSBwcmVmaXggJiYgZnVsbC5zdGFydHNXaXRoKHByZWZpeCArICcuJylcblxuICBjb25zdCBwcnVuZWQ6IEFycmF5PHN0cmluZz4gPSBbXVxuICBmb3IgKGNvbnN0IHAgb2YgYWxsKSB7XG4gICAgbGV0IGhhc01vcmVTcGVjaWZpYyA9IGZhbHNlXG4gICAgZm9yIChjb25zdCBvdGhlciBvZiBhbGwpIHtcbiAgICAgIGlmIChpc1ByZWZpeChwLCBvdGhlcikpIHtcbiAgICAgICAgaGFzTW9yZVNwZWNpZmljID0gdHJ1ZVxuICAgICAgICBicmVha1xuICAgICAgfVxuICAgIH1cbiAgICBpZiAoIWhhc01vcmVTcGVjaWZpYykge1xuICAgICAgcHJ1bmVkLnB1c2gocClcbiAgICB9XG4gIH1cblxuICBwcnVuZWQuc29ydCgpXG4gIHJldHVybiBwcnVuZWRcbn1cblxuY29uc3QgY292ZXJzID0gKGRlY2xhcmVkOiBzdHJpbmcsIHJlYWQ6IHN0cmluZyk6IGJvb2xlYW4gPT4gZGVjbGFyZWQgPT09IHJlYWQgfHwgcmVhZC5zdGFydHNXaXRoKGRlY2xhcmVkICsgJy4nKVxuXG5leHBvcnQgY29uc3QgZGlmZkRlcHMgPSAoZGVjbGFyZWQ6IFJlYWRvbmx5QXJyYXk8c3RyaW5nPiwgcmVhZHM6IFJlYWRvbmx5QXJyYXk8c3RyaW5nPik6IERlcHNEaWZmIHwgdW5kZWZpbmVkID0+IHtcbiAgY29uc3QgZGVjbGFyZWRMaXN0ID0gQXJyYXkuZnJvbShuZXcgU2V0KGRlY2xhcmVkKSkuZmlsdGVyKChwKSA9PiB0eXBlb2YgcCA9PT0gJ3N0cmluZycgJiYgcC5sZW5ndGggPiAwKVxuICBkZWNsYXJlZExpc3Quc29ydCgpXG4gIGNvbnN0IHJlYWRMaXN0ID0gQXJyYXkuZnJvbShuZXcgU2V0KHJlYWRzKSkuZmlsdGVyKChwKSA9PiB0eXBlb2YgcCA9PT0gJ3N0cmluZycgJiYgcC5sZW5ndGggPiAwKVxuICByZWFkTGlzdC5zb3J0KClcblxuICBjb25zdCBtaXNzaW5nID0gcmVhZExpc3QuZmlsdGVyKChyKSA9PiBkZWNsYXJlZExpc3QuZXZlcnkoKGQpID0+ICFjb3ZlcnMoZCwgcikpKVxuICBjb25zdCB1bnVzZWQgPSBkZWNsYXJlZExpc3QuZmlsdGVyKChkKSA9PiByZWFkTGlzdC5ldmVyeSgocikgPT4gIWNvdmVycyhkLCByKSkpXG5cbiAgaWYgKG1pc3NpbmcubGVuZ3RoID09PSAwICYmIHVudXNlZC5sZW5ndGggPT09IDApIHJldHVybiB1bmRlZmluZWRcblxuICByZXR1cm4ge1xuICAgIHJlYWRzOiByZWFkTGlzdCxcbiAgICBkZWNsYXJlZDogZGVjbGFyZWRMaXN0LFxuICAgIG1pc3NpbmcsXG4gICAgdW51c2VkLFxuICB9XG59XG5cbmV4cG9ydCBjb25zdCB0cmFjZSA9IDxUPihmbjogKHN0YXRlOiBhbnkpID0+IFQsIHN0YXRlOiB1bmtub3duKTogRGVwc1RyYWNlUmVzdWx0PFQ+ID0+IHtcbiAgaWYgKCFpc1RyYWNlYWJsZU9iamVjdChzdGF0ZSkpIHtcbiAgICByZXR1cm4geyB2YWx1ZTogZm4oc3RhdGUgYXMgYW55KSwgcmVhZHM6IFtdIH1cbiAgfVxuXG4gIGNvbnN0IHJlYWRzID0gbmV3IFNldDxzdHJpbmc+KClcblxuICAvLyBwZXItdHJhY2UgY2FjaGVzIHRvIHByZXNlcnZlIHJlZmVyZW5jZSBpZGVudGl0eSB3aXRoaW4gdGhlIHRyYWNlZCBjYWxsLlxuICBjb25zdCBwcm94eUNhY2hlID0gbmV3IFdlYWtNYXA8b2JqZWN0LCBNYXA8c3RyaW5nLCBhbnk+PigpXG4gIGNvbnN0IHByb3h5VG9UYXJnZXQgPSBuZXcgV2Vha01hcDxvYmplY3QsIG9iamVjdD4oKVxuXG4gIGNvbnN0IHdyYXAgPSAodmFsdWU6IHVua25vd24sIHBhdGg6IHN0cmluZyk6IHVua25vd24gPT4ge1xuICAgIGlmICghaXNUcmFjZWFibGVPYmplY3QodmFsdWUpKSByZXR1cm4gdmFsdWVcbiAgICByZXR1cm4gZ2V0UHJveHkodmFsdWUgYXMgYW55LCBwYXRoKVxuICB9XG5cbiAgY29uc3QgdW53cmFwID0gPFY+KHZhbHVlOiBWKTogViA9PiB7XG4gICAgaWYgKHZhbHVlICYmICh0eXBlb2YgdmFsdWUgPT09ICdvYmplY3QnIHx8IHR5cGVvZiB2YWx1ZSA9PT0gJ2Z1bmN0aW9uJykpIHtcbiAgICAgIGNvbnN0IHRhcmdldCA9IHByb3h5VG9UYXJnZXQuZ2V0KHZhbHVlIGFzIGFueSlcbiAgICAgIGlmICh0YXJnZXQpIHJldHVybiB0YXJnZXQgYXMgYW55IGFzIFZcbiAgICB9XG4gICAgcmV0dXJuIHZhbHVlXG4gIH1cblxuICBjb25zdCBnZXRQcm94eSA9ICh0YXJnZXQ6IG9iamVjdCwgYmFzZVBhdGg6IHN0cmluZyk6IGFueSA9PiB7XG4gICAgbGV0IGJ5UGF0aCA9IHByb3h5Q2FjaGUuZ2V0KHRhcmdldClcbiAgICBpZiAoIWJ5UGF0aCkge1xuICAgICAgYnlQYXRoID0gbmV3IE1hcCgpXG4gICAgICBwcm94eUNhY2hlLnNldCh0YXJnZXQsIGJ5UGF0aClcbiAgICB9XG5cbiAgICBjb25zdCBjYWNoZWQgPSBieVBhdGguZ2V0KGJhc2VQYXRoKVxuICAgIGlmIChjYWNoZWQpIHJldHVybiBjYWNoZWRcblxuICAgIGNvbnN0IHJlY29yZCA9IChwYXRoOiBzdHJpbmcpID0+IHtcbiAgICAgIGlmIChwYXRoKSByZWFkcy5hZGQocGF0aClcbiAgICB9XG5cbiAgICBjb25zdCBwcm94eSA9IG5ldyBQcm94eSh0YXJnZXQgYXMgYW55LCB7XG4gICAgICBnZXQ6ICh0LCBwcm9wLCByZWNlaXZlcikgPT4ge1xuICAgICAgICBpZiAodHlwZW9mIHByb3AgPT09ICdzeW1ib2wnKSB7XG4gICAgICAgICAgcmV0dXJuIFJlZmxlY3QuZ2V0KHQsIHByb3AsIHJlY2VpdmVyKVxuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGtleSA9IFN0cmluZyhwcm9wKVxuICAgICAgICBpZiAoc2hvdWxkSWdub3JlS2V5KGtleSkpIHtcbiAgICAgICAgICByZXR1cm4gUmVmbGVjdC5nZXQodCwgcHJvcCwgcmVjZWl2ZXIpXG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBuZXh0UGF0aCA9IGJhc2VQYXRoID8gYCR7YmFzZVBhdGh9LiR7a2V5fWAgOiBrZXlcbiAgICAgICAgcmVjb3JkKG5leHRQYXRoKVxuXG4gICAgICAgIGNvbnN0IHZhbHVlID0gUmVmbGVjdC5nZXQodCwgcHJvcCwgcmVjZWl2ZXIpIGFzIHVua25vd25cbiAgICAgICAgcmV0dXJuIHdyYXAodmFsdWUsIG5leHRQYXRoKVxuICAgICAgfSxcbiAgICAgIGhhczogKHQsIHByb3ApID0+IHtcbiAgICAgICAgaWYgKHR5cGVvZiBwcm9wID09PSAnc3ltYm9sJykgcmV0dXJuIFJlZmxlY3QuaGFzKHQsIHByb3ApXG4gICAgICAgIGNvbnN0IGtleSA9IFN0cmluZyhwcm9wKVxuICAgICAgICBpZiAoIXNob3VsZElnbm9yZUtleShrZXkpKSB7XG4gICAgICAgICAgY29uc3QgbmV4dFBhdGggPSBiYXNlUGF0aCA/IGAke2Jhc2VQYXRofS4ke2tleX1gIDoga2V5XG4gICAgICAgICAgcmVjb3JkKG5leHRQYXRoKVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBSZWZsZWN0Lmhhcyh0LCBwcm9wKVxuICAgICAgfSxcbiAgICAgIG93bktleXM6ICh0KSA9PiB7XG4gICAgICAgIGlmIChiYXNlUGF0aCkgcmVjb3JkKGJhc2VQYXRoKVxuICAgICAgICByZXR1cm4gUmVmbGVjdC5vd25LZXlzKHQpXG4gICAgICB9LFxuICAgICAgZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yOiAodCwgcHJvcCkgPT4ge1xuICAgICAgICBpZiAodHlwZW9mIHByb3AgPT09ICdzeW1ib2wnKSB7XG4gICAgICAgICAgcmV0dXJuIFJlZmxlY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKHQsIHByb3ApXG4gICAgICAgIH1cbiAgICAgICAgY29uc3Qga2V5ID0gU3RyaW5nKHByb3ApXG4gICAgICAgIGlmICghc2hvdWxkSWdub3JlS2V5KGtleSkpIHtcbiAgICAgICAgICBjb25zdCBuZXh0UGF0aCA9IGJhc2VQYXRoID8gYCR7YmFzZVBhdGh9LiR7a2V5fWAgOiBrZXlcbiAgICAgICAgICByZWNvcmQobmV4dFBhdGgpXG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIFJlZmxlY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKHQsIHByb3ApXG4gICAgICB9LFxuICAgICAgc2V0OiAoKSA9PiB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICAnW2RlcHMtdHJhY2VdIEF0dGVtcHRlZCB0byBtdXRhdGUgc3RhdGUgZHVyaW5nIGRlcHMgdHJhY2luZyAoc3RhdGUgaXMgcmVhZG9ubHkgaW4gZGV2LW1vZGUgZGlhZ25vc3RpY3MpLicsXG4gICAgICAgIClcbiAgICAgIH0sXG4gICAgICBkZWZpbmVQcm9wZXJ0eTogKCkgPT4ge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgJ1tkZXBzLXRyYWNlXSBBdHRlbXB0ZWQgdG8gZGVmaW5lIHByb3BlcnR5IG9uIHN0YXRlIGR1cmluZyBkZXBzIHRyYWNpbmcgKHN0YXRlIGlzIHJlYWRvbmx5IGluIGRldi1tb2RlIGRpYWdub3N0aWNzKS4nLFxuICAgICAgICApXG4gICAgICB9LFxuICAgICAgZGVsZXRlUHJvcGVydHk6ICgpID0+IHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAgICdbZGVwcy10cmFjZV0gQXR0ZW1wdGVkIHRvIGRlbGV0ZSBwcm9wZXJ0eSBvbiBzdGF0ZSBkdXJpbmcgZGVwcyB0cmFjaW5nIChzdGF0ZSBpcyByZWFkb25seSBpbiBkZXYtbW9kZSBkaWFnbm9zdGljcykuJyxcbiAgICAgICAgKVxuICAgICAgfSxcbiAgICB9KVxuXG4gICAgYnlQYXRoLnNldChiYXNlUGF0aCwgcHJveHkpXG4gICAgcHJveHlUb1RhcmdldC5zZXQocHJveHksIHRhcmdldClcbiAgICByZXR1cm4gcHJveHlcbiAgfVxuXG4gIGNvbnN0IHJvb3QgPSBnZXRQcm94eShzdGF0ZSBhcyBhbnksICcnKVxuICBjb25zdCB2YWx1ZSA9IHVud3JhcChmbihyb290KSlcblxuICByZXR1cm4ge1xuICAgIHZhbHVlLFxuICAgIHJlYWRzOiBub3JtYWxpemVSZWFkcyhyZWFkcyksXG4gIH1cbn1cbiIsICJpbXBvcnQgeyBFZmZlY3QsIEZpYmVyUmVmLCBPcHRpb24gfSBmcm9tICdlZmZlY3QnXG5pbXBvcnQgKiBhcyBTY2hlbWFBU1QgZnJvbSAnZWZmZWN0L1NjaGVtYUFTVCdcbmltcG9ydCAqIGFzIERlYnVnIGZyb20gJy4uL3J1bnRpbWUvY29yZS9EZWJ1Z1NpbmsuanMnXG5pbXBvcnQgeyBpc0RldkVudiB9IGZyb20gJy4uL3J1bnRpbWUvY29yZS9lbnYuanMnXG5pbXBvcnQgeyBSdW5TZXNzaW9uVGFnIH0gZnJvbSAnLi4vb2JzZXJ2YWJpbGl0eS9ydW5TZXNzaW9uLmpzJ1xuaW1wb3J0IHsgbm9ybWFsaXplRmllbGRQYXRoIH0gZnJvbSAnLi4vZmllbGQtcGF0aC5qcydcbmltcG9ydCAqIGFzIERlcHNUcmFjZSBmcm9tICcuL2RlcHMtdHJhY2UuanMnXG5pbXBvcnQgdHlwZSB7IENvbnZlcmdlQ29udGV4dCB9IGZyb20gJy4vY29udmVyZ2UudHlwZXMuanMnXG5pbXBvcnQgdHlwZSB7IFN0YXRlVHJhaXRQcm9ncmFtLCBTdGF0ZVRyYWl0U2NoZW1hUGF0aFJlZiB9IGZyb20gJy4vbW9kZWwuanMnXG5cbmNvbnN0IG9uY2VLZXlzRmFsbGJhY2sgPSBuZXcgU2V0PHN0cmluZz4oKVxuXG5leHBvcnQgY29uc3Qgb25jZUluUnVuU2Vzc2lvbiA9IChrZXk6IHN0cmluZyk6IEVmZmVjdC5FZmZlY3Q8Ym9vbGVhbj4gPT5cbiAgRWZmZWN0LnNlcnZpY2VPcHRpb24oUnVuU2Vzc2lvblRhZykucGlwZShcbiAgICBFZmZlY3QubWFwKChtYXliZSkgPT4ge1xuICAgICAgaWYgKE9wdGlvbi5pc1NvbWUobWF5YmUpKSB7XG4gICAgICAgIHJldHVybiBtYXliZS52YWx1ZS5sb2NhbC5vbmNlKGtleSlcbiAgICAgIH1cbiAgICAgIGlmIChvbmNlS2V5c0ZhbGxiYWNrLmhhcyhrZXkpKSByZXR1cm4gZmFsc2VcbiAgICAgIG9uY2VLZXlzRmFsbGJhY2suYWRkKGtleSlcbiAgICAgIHJldHVybiB0cnVlXG4gICAgfSksXG4gIClcblxuY29uc3QgZm9ybWF0TGlzdCA9IChpdGVtczogUmVhZG9ubHlBcnJheTxzdHJpbmc+LCBsaW1pdCA9IDEwKTogc3RyaW5nID0+IHtcbiAgaWYgKGl0ZW1zLmxlbmd0aCA9PT0gMCkgcmV0dXJuICcnXG4gIGlmIChpdGVtcy5sZW5ndGggPD0gbGltaXQpIHJldHVybiBpdGVtcy5qb2luKCcsICcpXG4gIHJldHVybiBgJHtpdGVtcy5zbGljZSgwLCBsaW1pdCkuam9pbignLCAnKX0sIFx1MjAyNigrJHtpdGVtcy5sZW5ndGggLSBsaW1pdH0pYFxufVxuXG5leHBvcnQgY29uc3QgZW1pdERlcHNNaXNtYXRjaCA9IChwYXJhbXM6IHtcbiAgcmVhZG9ubHkgbW9kdWxlSWQ/OiBzdHJpbmdcbiAgcmVhZG9ubHkgaW5zdGFuY2VJZD86IHN0cmluZ1xuICByZWFkb25seSBraW5kOiAnY29tcHV0ZWQnIHwgJ3NvdXJjZSdcbiAgcmVhZG9ubHkgZmllbGRQYXRoOiBzdHJpbmdcbiAgcmVhZG9ubHkgZGlmZjogRGVwc1RyYWNlLkRlcHNEaWZmXG59KTogRWZmZWN0LkVmZmVjdDx2b2lkPiA9PiB7XG4gIHJldHVybiBFZmZlY3QuZ2VuKGZ1bmN0aW9uKiAoKSB7XG4gICAgY29uc3Qga2V5ID0gYCR7cGFyYW1zLm1vZHVsZUlkID8/ICd1bmtub3duJ306OiR7cGFyYW1zLmluc3RhbmNlSWQgPz8gJ3Vua25vd24nfTo6JHtwYXJhbXMua2luZH06OiR7cGFyYW1zLmZpZWxkUGF0aH1gXG4gICAgY29uc3Qgc2hvdWxkRW1pdCA9IHlpZWxkKiBvbmNlSW5SdW5TZXNzaW9uKGBkZXBzX21pc21hdGNoOiR7a2V5fWApXG4gICAgaWYgKCFzaG91bGRFbWl0KSByZXR1cm5cblxuICAgIHlpZWxkKiBEZWJ1Zy5yZWNvcmQoe1xuICAgICAgdHlwZTogJ2RpYWdub3N0aWMnLFxuICAgICAgbW9kdWxlSWQ6IHBhcmFtcy5tb2R1bGVJZCxcbiAgICAgIGluc3RhbmNlSWQ6IHBhcmFtcy5pbnN0YW5jZUlkLFxuICAgICAgY29kZTogJ3N0YXRlX3RyYWl0OjpkZXBzX21pc21hdGNoJyxcbiAgICAgIHNldmVyaXR5OiAnd2FybmluZycsXG4gICAgICBtZXNzYWdlOlxuICAgICAgICBgW2RlcHNdICR7cGFyYW1zLmtpbmR9IFwiJHtwYXJhbXMuZmllbGRQYXRofVwiIGRlY2xhcmVkPVske2Zvcm1hdExpc3QocGFyYW1zLmRpZmYuZGVjbGFyZWQpfV0gYCArXG4gICAgICAgIGByZWFkcz1bJHtmb3JtYXRMaXN0KHBhcmFtcy5kaWZmLnJlYWRzKX1dIG1pc3Npbmc9WyR7Zm9ybWF0TGlzdChwYXJhbXMuZGlmZi5taXNzaW5nKX1dIGAgK1xuICAgICAgICBgdW51c2VkPVske2Zvcm1hdExpc3QocGFyYW1zLmRpZmYudW51c2VkKX1dYCxcbiAgICAgIGhpbnQ6XG4gICAgICAgICdkZXBzIGlzIHRoZSBzaW5nbGUgc291cmNlIG9mIHRydXRoIGZvciBkZXBlbmRlbmNpZXM6IGluY3JlbWVudGFsIHNjaGVkdWxpbmcgLyByZXZlcnNlIGNsb3N1cmVzIC8gcGVyZm9ybWFuY2Ugb3B0aW1pemF0aW9ucyByZWx5IG9uIGRlcHMgb25seS4gJyArXG4gICAgICAgICdLZWVwIGRlcHMgY29uc2lzdGVudCB3aXRoIGFjdHVhbCByZWFkczsgaWYgeW91IHJlYWxseSBkZXBlbmQgb24gdGhlIHdob2xlIG9iamVjdCwgZGVjbGFyZSBhIGNvYXJzZXItZ3JhaW5lZCBkZXAgKGUuZy4gXCJwcm9maWxlXCIpIHRvIGNvdmVyIHN1Yi1maWVsZCByZWFkcy4nLFxuICAgICAga2luZDogYGRlcHNfbWlzbWF0Y2g6JHtwYXJhbXMua2luZH1gLFxuICAgIH0pXG4gIH0pXG59XG5cbmNvbnN0IHNjaGVtYUhhc1BhdGggPSAoXG4gIGFzdDogU2NoZW1hQVNULkFTVCxcbiAgc2VnbWVudHM6IFJlYWRvbmx5QXJyYXk8c3RyaW5nPixcbiAgc2VlbjogU2V0PFNjaGVtYUFTVC5BU1Q+ID0gbmV3IFNldCgpLFxuKTogYm9vbGVhbiA9PiB7XG4gIGlmIChzZWdtZW50cy5sZW5ndGggPT09IDApIHJldHVybiB0cnVlXG5cbiAgbGV0IGN1cnJlbnQgPSBhc3RcblxuICAvLyB1bndyYXAgU3VzcGVuZC9SZWZpbmVtZW50IChjb21tb24gZm9yIHJlY3Vyc2l2ZSBzY2hlbWFzIGFuZCBicmFuZGVkIHNjaGVtYXMpXG4gIHdoaWxlICh0cnVlKSB7XG4gICAgaWYgKFNjaGVtYUFTVC5pc1N1c3BlbmQoY3VycmVudCkpIHtcbiAgICAgIGlmIChzZWVuLmhhcyhjdXJyZW50KSkge1xuICAgICAgICAvLyBSZWN1cnNpb246IGlmIHdlIGNhbid0IHN0YXRpY2FsbHkgZGVjaWRlIGZ1cnRoZXIsIGFsbG93IGNvbnNlcnZhdGl2ZWx5IHRvIGF2b2lkIGZhbHNlIHBvc2l0aXZlcy5cbiAgICAgICAgcmV0dXJuIHRydWVcbiAgICAgIH1cbiAgICAgIHNlZW4uYWRkKGN1cnJlbnQpXG4gICAgICBjdXJyZW50ID0gY3VycmVudC5mKClcbiAgICAgIGNvbnRpbnVlXG4gICAgfVxuICAgIGlmIChTY2hlbWFBU1QuaXNSZWZpbmVtZW50KGN1cnJlbnQpKSB7XG4gICAgICBjdXJyZW50ID0gY3VycmVudC5mcm9tXG4gICAgICBjb250aW51ZVxuICAgIH1cbiAgICBicmVha1xuICB9XG5cbiAgLy8gVHJhbnNmb3JtYXRpb246IHByZWZlciBgdG9gIChkZWNvZGVkIHNoYXBlKSwgYnV0IGFsc28gYWxsb3cgYGZyb21gIHRvIHJlZHVjZSBmYWxzZSBwb3NpdGl2ZXMuXG4gIGlmIChTY2hlbWFBU1QuaXNUcmFuc2Zvcm1hdGlvbihjdXJyZW50KSkge1xuICAgIHJldHVybiBzY2hlbWFIYXNQYXRoKGN1cnJlbnQudG8sIHNlZ21lbnRzLCBzZWVuKSB8fCBzY2hlbWFIYXNQYXRoKGN1cnJlbnQuZnJvbSwgc2VnbWVudHMsIHNlZW4pXG4gIH1cblxuICBpZiAoU2NoZW1hQVNULmlzVW5pb24oY3VycmVudCkpIHtcbiAgICByZXR1cm4gY3VycmVudC50eXBlcy5zb21lKCh0KSA9PiBzY2hlbWFIYXNQYXRoKHQsIHNlZ21lbnRzLCBzZWVuKSlcbiAgfVxuXG4gIGlmIChTY2hlbWFBU1QuaXNUdXBsZVR5cGUoY3VycmVudCkpIHtcbiAgICBjb25zdCBjYW5kaWRhdGVzOiBBcnJheTxTY2hlbWFBU1QuQVNUPiA9IFtdXG4gICAgZm9yIChjb25zdCBlIG9mIGN1cnJlbnQuZWxlbWVudHMpIGNhbmRpZGF0ZXMucHVzaChlLnR5cGUpXG4gICAgZm9yIChjb25zdCByIG9mIGN1cnJlbnQucmVzdCkgY2FuZGlkYXRlcy5wdXNoKHIudHlwZSlcbiAgICBpZiAoY2FuZGlkYXRlcy5sZW5ndGggPT09IDApIHJldHVybiB0cnVlXG4gICAgcmV0dXJuIGNhbmRpZGF0ZXMuc29tZSgodCkgPT4gc2NoZW1hSGFzUGF0aCh0LCBzZWdtZW50cywgc2VlbikpXG4gIH1cblxuICBpZiAoU2NoZW1hQVNULmlzVHlwZUxpdGVyYWwoY3VycmVudCkpIHtcbiAgICBjb25zdCBbaGVhZCwgLi4udGFpbF0gPSBzZWdtZW50c1xuXG4gICAgZm9yIChjb25zdCBwcyBvZiBjdXJyZW50LnByb3BlcnR5U2lnbmF0dXJlcykge1xuICAgICAgaWYgKFN0cmluZyhwcy5uYW1lKSAhPT0gaGVhZCkgY29udGludWVcbiAgICAgIHJldHVybiBzY2hlbWFIYXNQYXRoKHBzLnR5cGUsIHRhaWwsIHNlZW4pXG4gICAgfVxuXG4gICAgLy8gaW5kZXggc2lnbmF0dXJlOiBvcGVuIG9iamVjdHMgbGlrZSBSZWNvcmQ8c3RyaW5nLCBUPiBhbGxvdyBhbnkga2V5XG4gICAgZm9yIChjb25zdCBzaWcgb2YgY3VycmVudC5pbmRleFNpZ25hdHVyZXMpIHtcbiAgICAgIGxldCBwYXJhbTogU2NoZW1hQVNULkFTVCA9IHNpZy5wYXJhbWV0ZXIgYXMgdW5rbm93biBhcyBTY2hlbWFBU1QuQVNUXG4gICAgICB3aGlsZSAoU2NoZW1hQVNULmlzUmVmaW5lbWVudChwYXJhbSkpIHtcbiAgICAgICAgcGFyYW0gPSBwYXJhbS5mcm9tXG4gICAgICB9XG4gICAgICBjb25zdCB0YWcgPSAocGFyYW0gYXMgYW55KT8uX3RhZ1xuICAgICAgaWYgKHRhZyA9PT0gJ1N0cmluZ0tleXdvcmQnIHx8IHRhZyA9PT0gJ1RlbXBsYXRlTGl0ZXJhbCcpIHtcbiAgICAgICAgcmV0dXJuIHNjaGVtYUhhc1BhdGgoc2lnLnR5cGUsIHRhaWwsIHNlZW4pXG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlXG4gIH1cblxuICBjb25zdCB0YWcgPSAoY3VycmVudCBhcyBhbnkpPy5fdGFnXG4gIGlmICh0YWcgPT09ICdBbnlLZXl3b3JkJyB8fCB0YWcgPT09ICdVbmtub3duS2V5d29yZCcgfHwgdGFnID09PSAnT2JqZWN0S2V5d29yZCcgfHwgdGFnID09PSAnRGVjbGFyYXRpb24nKSB7XG4gICAgcmV0dXJuIHRydWVcbiAgfVxuXG4gIHJldHVybiBmYWxzZVxufVxuXG5jb25zdCBzY2hlbWFIYXNGaWVsZFBhdGggPSAoc3RhdGVTY2hlbWFBc3Q6IFNjaGVtYUFTVC5BU1QsIHBhdGg6IHN0cmluZyk6IGJvb2xlYW4gPT4ge1xuICBpZiAoIXBhdGgpIHJldHVybiB0cnVlXG4gIGlmIChwYXRoID09PSAnJHJvb3QnKSByZXR1cm4gdHJ1ZVxuXG4gIGNvbnN0IG5vcm1hbGl6ZWQgPSBub3JtYWxpemVGaWVsZFBhdGgocGF0aClcbiAgaWYgKCFub3JtYWxpemVkKSByZXR1cm4gZmFsc2VcblxuICBjb25zdCBzZWdzID0gbm9ybWFsaXplZFswXSA9PT0gJyRyb290JyA/IG5vcm1hbGl6ZWQuc2xpY2UoMSkgOiBub3JtYWxpemVkXG4gIHJldHVybiBzY2hlbWFIYXNQYXRoKHN0YXRlU2NoZW1hQXN0LCBzZWdzKVxufVxuXG5jb25zdCBmb3JtYXRTY2hlbWFNaXNtYXRjaExpbmUgPSAocmVmOiBTdGF0ZVRyYWl0U2NoZW1hUGF0aFJlZik6IHN0cmluZyA9PiB7XG4gIGlmIChyZWYua2luZCA9PT0gJ2ZpZWxkUGF0aCcpIHtcbiAgICByZXR1cm4gYC0gJHtyZWYuZW50cnlLaW5kfSBcIiR7cmVmLmVudHJ5RmllbGRQYXRofVwiIGZpZWxkUGF0aD1cIiR7cmVmLnBhdGh9XCJgXG4gIH1cbiAgaWYgKHJlZi5raW5kID09PSAnZGVwJykge1xuICAgIGNvbnN0IHJ1bGUgPSByZWYucnVsZU5hbWUgPyBgIHJ1bGU9XCIke3JlZi5ydWxlTmFtZX1cImAgOiAnJ1xuICAgIHJldHVybiBgLSAke3JlZi5lbnRyeUtpbmR9IFwiJHtyZWYuZW50cnlGaWVsZFBhdGh9XCIgZGVwcz1cIiR7cmVmLnBhdGh9XCIke3J1bGV9YFxuICB9XG4gIGlmIChyZWYua2luZCA9PT0gJ2xpbmtfZnJvbScpIHtcbiAgICByZXR1cm4gYC0gbGluayBcIiR7cmVmLmVudHJ5RmllbGRQYXRofVwiIGZyb209XCIke3JlZi5wYXRofVwiYFxuICB9XG4gIGlmIChyZWYua2luZCA9PT0gJ2NoZWNrX3dyaXRlYmFjaycpIHtcbiAgICByZXR1cm4gYC0gY2hlY2sgXCIke3JlZi5lbnRyeUZpZWxkUGF0aH1cIiB3cml0ZWJhY2s9XCIke3JlZi5wYXRofVwiYFxuICB9XG4gIHJldHVybiBgLSAke3JlZi5lbnRyeUtpbmR9IFwiJHtyZWYuZW50cnlGaWVsZFBhdGh9XCIgcGF0aD1cIiR7cmVmLnBhdGh9XCJgXG59XG5cbmV4cG9ydCBjb25zdCBlbWl0U2NoZW1hTWlzbWF0Y2ggPSA8UyBleHRlbmRzIG9iamVjdD4oXG4gIHByb2dyYW06IFN0YXRlVHJhaXRQcm9ncmFtPFM+LFxuICBjdHg6IFBpY2s8Q29udmVyZ2VDb250ZXh0PFM+LCAnbW9kdWxlSWQnIHwgJ2luc3RhbmNlSWQnPixcbik6IEVmZmVjdC5FZmZlY3Q8dm9pZD4gPT5cbiAgRWZmZWN0LmdlbihmdW5jdGlvbiogKCkge1xuICAgIGlmICghaXNEZXZFbnYoKSkgcmV0dXJuXG5cbiAgICBjb25zdCBsZXZlbCA9IHlpZWxkKiBGaWJlclJlZi5nZXQoRGVidWcuY3VycmVudERpYWdub3N0aWNzTGV2ZWwpXG4gICAgaWYgKGxldmVsID09PSAnb2ZmJykgcmV0dXJuXG5cbiAgICBjb25zdCBrZXkgPSBgJHtjdHgubW9kdWxlSWQgPz8gJ3Vua25vd24nfTo6JHtjdHguaW5zdGFuY2VJZH1gXG4gICAgY29uc3Qgc2hvdWxkRW1pdCA9IHlpZWxkKiBvbmNlSW5SdW5TZXNzaW9uKGBzY2hlbWFfbWlzbWF0Y2g6JHtrZXl9YClcbiAgICBpZiAoIXNob3VsZEVtaXQpIHJldHVyblxuXG4gICAgY29uc3QgcmVmcyA9IChwcm9ncmFtLnNjaGVtYVBhdGhzID8/IFtdKSBhcyBSZWFkb25seUFycmF5PFN0YXRlVHJhaXRTY2hlbWFQYXRoUmVmPlxuICAgIGlmIChyZWZzLmxlbmd0aCA9PT0gMCkgcmV0dXJuXG5cbiAgICBjb25zdCBzdGF0ZVNjaGVtYUFzdCA9IHByb2dyYW0uc3RhdGVTY2hlbWEuYXN0IGFzIHVua25vd24gYXMgU2NoZW1hQVNULkFTVFxuXG4gICAgY29uc3QgbWlzbWF0Y2hlczogQXJyYXk8U3RhdGVUcmFpdFNjaGVtYVBhdGhSZWY+ID0gW11cbiAgICBjb25zdCBzZWVuID0gbmV3IFNldDxzdHJpbmc+KClcblxuICAgIGZvciAoY29uc3QgcmVmIG9mIHJlZnMpIHtcbiAgICAgIGlmIChzY2hlbWFIYXNGaWVsZFBhdGgoc3RhdGVTY2hlbWFBc3QsIHJlZi5wYXRoKSkgY29udGludWVcbiAgICAgIGNvbnN0IGsgPSBgJHtyZWYua2luZH18JHtyZWYuZW50cnlLaW5kfXwke3JlZi5lbnRyeUZpZWxkUGF0aH18JHtyZWYucnVsZU5hbWUgPz8gJyd9fCR7cmVmLnBhdGh9YFxuICAgICAgaWYgKHNlZW4uaGFzKGspKSBjb250aW51ZVxuICAgICAgc2Vlbi5hZGQoaylcbiAgICAgIG1pc21hdGNoZXMucHVzaChyZWYpXG4gICAgfVxuXG4gICAgaWYgKG1pc21hdGNoZXMubGVuZ3RoID09PSAwKSByZXR1cm5cblxuICAgIGNvbnN0IGxpbWl0ID0gbGV2ZWwgPT09ICdsaWdodCcgPyA4IDogMjRcbiAgICBjb25zdCBsaW5lcyA9IG1pc21hdGNoZXMuc2xpY2UoMCwgbGltaXQpLm1hcChmb3JtYXRTY2hlbWFNaXNtYXRjaExpbmUpXG4gICAgaWYgKG1pc21hdGNoZXMubGVuZ3RoID4gbGltaXQpIHtcbiAgICAgIGxpbmVzLnB1c2goYC0gXHUyMDI2KCske21pc21hdGNoZXMubGVuZ3RoIC0gbGltaXR9KWApXG4gICAgfVxuXG4gICAgeWllbGQqIERlYnVnLnJlY29yZCh7XG4gICAgICB0eXBlOiAnZGlhZ25vc3RpYycsXG4gICAgICBtb2R1bGVJZDogY3R4Lm1vZHVsZUlkLFxuICAgICAgaW5zdGFuY2VJZDogY3R4Lmluc3RhbmNlSWQsXG4gICAgICBjb2RlOiAnc3RhdGVfdHJhaXQ6OnNjaGVtYV9taXNtYXRjaCcsXG4gICAgICBzZXZlcml0eTogJ3dhcm5pbmcnLFxuICAgICAgbWVzc2FnZTogYFtzY2hlbWFdIFRoZSBmb2xsb3dpbmcgcGF0aHMgYXJlIG5vdCBkZWNsYXJlZCBpbiBzdGF0ZVNjaGVtYSAodG90YWwgJHttaXNtYXRjaGVzLmxlbmd0aH0pOlxcbiR7bGluZXMuam9pbignXFxuJyl9YCxcbiAgICAgIGhpbnQ6ICdTdGF0ZVRyYWl0IHdyaXRlYmFjayB3aWxsIGNyZWF0ZSBtaXNzaW5nIG9iamVjdHMvZmllbGRzLiBEZWNsYXJlIGFsbCBmaWVsZFBhdGgvZGVwcy9saW5rLmZyb20gYW5kIGVycm9ycy4qIHdyaXRlYmFjayBwYXRocyBpbiBzdGF0ZVNjaGVtYSwgb3IgZml4IHR5cG9zIGluIHRyYWl0IHBhdGhzLicsXG4gICAgICBraW5kOiAnc2NoZW1hX21pc21hdGNoJyxcbiAgICB9KVxuICB9KVxuIl0sCiAgIm1hcHBpbmdzIjogIjs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQ0EsWUFBWSxlQUFlOzs7QUM0VnBCLElBQU0sZ0JBQWdCLENBQUksU0FBeUU7QUFDeEcsUUFBTSxVQUErQyxDQUFDO0FBRXRELFFBQU0sU0FBUyxDQUFDLFVBQ2QsT0FBTyxVQUFVLFlBQVksVUFBVSxRQUFTLE1BQWMsU0FBUztBQUV6RSxRQUFNLFNBQVMsQ0FBQyxVQUNkLE9BQU8sVUFBVSxZQUFZLFVBQVUsUUFBUyxNQUFjLFNBQVM7QUFFekUsUUFBTSxXQUFXLENBQUMsUUFBZ0IsV0FBMkI7QUFDM0QsUUFBSSxDQUFDLE9BQVEsUUFBTztBQUNwQixRQUFJLENBQUMsT0FBUSxRQUFPO0FBQ3BCLFdBQU8sR0FBRyxNQUFNLElBQUksTUFBTTtBQUFBLEVBQzVCO0FBRUEsUUFBTSxhQUFhLENBQUMsTUFBeUMsV0FBMEM7QUFDckcsUUFBSSxDQUFDLFFBQVEsS0FBSyxXQUFXLEVBQUcsUUFBTyxDQUFDO0FBQ3hDLFdBQU8sS0FBSyxJQUFJLENBQUMsTUFBTyxTQUFTLFNBQVMsUUFBUSxDQUFDLElBQUksQ0FBRTtBQUFBLEVBQzNEO0FBRUEsUUFBTSxpQkFBaUIsQ0FDckIsT0FDQSxXQUNBLGNBQ2lDO0FBQ2pDLFFBQUksTUFBTSxTQUFTLFlBQVk7QUFDN0IsWUFBTSxPQUFPLE1BQU07QUFDbkIsWUFBTSxVQUFVLEtBQUs7QUFDckIsWUFBTSxPQUFPLFlBQVksU0FBWSxXQUFXLFNBQVMsU0FBUyxJQUFJO0FBQ3RFLGFBQU87QUFBQSxRQUNMLEdBQUk7QUFBQSxRQUNKO0FBQUEsUUFD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QUMsRUFBRztBQUNqQixTQUFLLElBQUksQ0FBQztBQUNWLGVBQVcsS0FBSyxHQUFHO0FBQUEsRUFDckI7QUFFQSxNQUFJLFdBQVcsV0FBVyxFQUFHO0FBRTdCLFFBQU0sUUFBUSxVQUFVLFVBQVUsSUFBSTtBQUN0QyxRQUFNLFFBQVEsV0FBVyxNQUFNLEdBQUcsS0FBSyxFQUFFLElBQUksd0JBQXdCO0FBQ3JFLE1BQUksV0FBVyxTQUFTLE9BQU87QUFDN0IsVUFBTSxLQUFLLGFBQVEsV0FBVyxTQUFTLEtBQUssR0FBRztBQUFBLEVBQ2pEO0FBRUEsU0FBYSxPQUFPO0FBQUEsSUFDbEIsTUFBTTtBQUFBLElBQ04sVUFBVSxJQUFJO0FBQUEsSUFDZCxZQUFZLElBQUk7QUFBQSxJQUNoQixNQUFNO0FBQUEsSUFDTixVQUFVO0FBQUEsSUFDVixTQUFTLHVFQUF1RSxXQUFXLE1BQU07QUFBQSxFQUFPLE1BQU0sS0FBSyxJQUFJLENBQUM7QUFBQSxJQUN4SCxNQUFNO0FBQUEsSUFDTixNQUFNO0FBQUEsRUFDUixDQUFDO0FBQ0gsQ0FBQzsiLAogICJuYW1lcyI6IFsicmVjb3JkIiwgInZhbHVlIiwgInJlY29yZCIsICJrZXlIYXNoIiwgImtleSIsICJwcmV2IiwgInByZXZTdGF0dXMiLCAiY29uY3VycmVuY3kiLCAibW9kZSIsICJpbkZsaWdodCIsICJ0cmFpbGluZyIsICJnZW4iLCAic3RhcnRGZXRjaCIsICJFZmZlY3QiLCAiRmliZXJSZWYiLCAiT3B0aW9uIiwgIlNjaGVtYUFTVCIsICJvbmNlSW5SdW5TZXNzaW9uIiwgIkVmZmVjdCIsICJPcHRpb24iLCAiZm9ybWF0TGlzdCIsICJlbWl0RGVwc01pc21hdGNoIiwgInRhZyIsICJGaWJlclJlZiJdCn0K
|