cdktn 0.25.0-pre.8 → 0.25.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.jsii +2194 -424
- package/README.md +12 -0
- package/lib/annotations.js +4 -4
- package/lib/app.js +54 -5
- package/lib/aspect.js +3 -4
- package/lib/asset-hash.d.ts +75 -0
- package/lib/asset-hash.js +129 -0
- package/lib/asset-staging.d.ts +180 -0
- package/lib/asset-staging.js +464 -0
- package/lib/assets.d.ts +401 -0
- package/lib/assets.js +333 -0
- package/lib/backends/azurerm-backend.js +4 -6
- package/lib/backends/cloud-backend.js +15 -12
- package/lib/backends/consul-backend.js +4 -6
- package/lib/backends/cos-backend.js +4 -6
- package/lib/backends/gcs-backend.js +4 -6
- package/lib/backends/http-backend.js +4 -6
- package/lib/backends/local-backend.js +38 -7
- package/lib/backends/oss-backend.js +4 -6
- package/lib/backends/pg-backend.js +4 -6
- package/lib/backends/remote-backend.js +8 -10
- package/lib/backends/s3-backend.js +4 -6
- package/lib/backends/swift-backend.js +4 -6
- package/lib/complex-computed-list.js +114 -65
- package/lib/errors.d.ts +16 -0
- package/lib/errors.js +51 -3
- package/lib/functions/provider-function.js +2 -4
- package/lib/functions/terraform-functions.generated.js +2 -4
- package/lib/ignore-strategy.d.ts +82 -0
- package/lib/ignore-strategy.js +29 -0
- package/lib/importable-resource.js +8 -6
- package/lib/index.d.ts +4 -0
- package/lib/index.js +28 -2
- package/lib/manifest.js +49 -11
- package/lib/private/fs.d.ts +74 -2
- package/lib/private/fs.js +129 -17
- package/lib/private/unique.js +35 -2
- package/lib/resource.js +3 -4
- package/lib/synthesize/synthesizer.js +51 -25
- package/lib/terraform-asset.d.ts +68 -5
- package/lib/terraform-asset.js +127 -40
- package/lib/terraform-backend.js +3 -4
- package/lib/terraform-count.js +3 -4
- package/lib/terraform-data-resource.d.ts +1 -1
- package/lib/terraform-data-resource.js +18 -13
- package/lib/terraform-data-source.js +10 -4
- package/lib/terraform-dynamic-block.js +5 -2
- package/lib/terraform-dynamic-expression.js +4 -1
- package/lib/terraform-element.js +34 -6
- package/lib/terraform-ephemeral-resource.js +10 -4
- package/lib/terraform-functions.js +2 -4
- package/lib/terraform-hcl-module.js +3 -4
- package/lib/terraform-iterator.js +11 -12
- package/lib/terraform-local.js +3 -4
- package/lib/terraform-module-asset.js +39 -4
- package/lib/terraform-module.js +8 -4
- package/lib/terraform-operators.js +2 -4
- package/lib/terraform-output.js +7 -4
- package/lib/terraform-provider.js +5 -4
- package/lib/terraform-provisioner.js +2 -4
- package/lib/terraform-remote-state.js +5 -5
- package/lib/terraform-resource-targets.js +3 -7
- package/lib/terraform-resource.js +23 -7
- package/lib/terraform-stack.js +38 -38
- package/lib/terraform-variable.js +25 -22
- package/lib/testing/adapters/jest.d.ts +2 -1
- package/lib/testing/adapters/jest.js +3 -3
- package/lib/testing/index.js +42 -8
- package/lib/testing/matchers.d.ts +34 -30
- package/lib/testing/matchers.js +329 -93
- package/lib/tfExpression.js +25 -8
- package/lib/tokens/lazy.js +11 -7
- package/lib/tokens/private/dependency.js +2 -2
- package/lib/tokens/private/encoding.js +6 -1
- package/lib/tokens/private/intrinsic.js +6 -1
- package/lib/tokens/private/resolve.js +2 -5
- package/lib/tokens/private/token-map.js +4 -6
- package/lib/tokens/private/uniqueid.js +35 -2
- package/lib/tokens/resolvable.js +4 -6
- package/lib/tokens/string-fragments.js +6 -10
- package/lib/tokens/token.js +15 -18
- package/lib/upgrade-id-aspect.js +37 -6
- package/lib/validations/index.d.ts +0 -1
- package/lib/validations/index.js +1 -2
- package/lib/validations/target-versions.js +39 -2
- package/lib/validations/validate-function-version-support.js +2 -1
- package/lib/validations/validate-provider-function-target-support.js +2 -1
- package/lib/validations/validate-provider-presence.js +10 -9
- package/package.json +21 -7
- package/scripts/pack.mjs +27 -12
- package/lib/validations/validate-binary-version.d.ts +0 -23
- package/lib/validations/validate-binary-version.js +0 -54
- package/lib/validations/validate-terraform-version.d.ts +0 -13
- package/lib/validations/validate-terraform-version.js +0 -21
|
@@ -0,0 +1,464 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.AssetStaging = exports.ASSET_HASH_SALT_CONTEXT_KEY = void 0;
|
|
37
|
+
const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
|
|
38
|
+
// Copyright (c) HashiCorp, Inc
|
|
39
|
+
// SPDX-License-Identifier: MPL-2.0
|
|
40
|
+
const constructs_1 = require("constructs");
|
|
41
|
+
const crypto = __importStar(require("crypto"));
|
|
42
|
+
const fs = __importStar(require("fs"));
|
|
43
|
+
const os = __importStar(require("os"));
|
|
44
|
+
const path = __importStar(require("path"));
|
|
45
|
+
const assets_1 = require("./assets");
|
|
46
|
+
const errors_1 = require("./errors");
|
|
47
|
+
const features_1 = require("./features");
|
|
48
|
+
const ignore_strategy_1 = require("./ignore-strategy");
|
|
49
|
+
const fs_1 = require("./private/fs");
|
|
50
|
+
// A resolved hash is used verbatim as a path segment (see `TerraformAsset.path`),
|
|
51
|
+
// so it may only contain characters that are always safe there.
|
|
52
|
+
const SAFE_ASSET_HASH = /^[A-Za-z0-9_.-]+$/;
|
|
53
|
+
/**
|
|
54
|
+
* Context key for a value folded into every computed asset hash in the
|
|
55
|
+
* construct tree, alongside `extraHash`. A bulk cache-busting escape hatch —
|
|
56
|
+
* `extraHash` is scoped to one asset, this is scoped to the whole app.
|
|
57
|
+
*/
|
|
58
|
+
exports.ASSET_HASH_SALT_CONTEXT_KEY = "cdktn:assetHashSalt";
|
|
59
|
+
/**
|
|
60
|
+
* Caches the base (pre `extraHash`/salt) hash of a `SOURCE`/`OUTPUT` walk,
|
|
61
|
+
* so that multiple `AssetStaging` instances with identical inputs — the same
|
|
62
|
+
* asset referenced from more than one resource or stack — hash the source
|
|
63
|
+
* tree once per synth instead of once per reference.
|
|
64
|
+
*
|
|
65
|
+
* Keyed per construct-tree root (the `App`) rather than at module scope: an
|
|
66
|
+
* App instance lives exactly as long as one synth, so a long-running process
|
|
67
|
+
* that synths repeatedly against changing files (e.g. `cdktn watch`) always
|
|
68
|
+
* gets a fresh cache instead of a stale hash from a previous synth.
|
|
69
|
+
*/
|
|
70
|
+
const hashCachesByRoot = new WeakMap();
|
|
71
|
+
/**
|
|
72
|
+
* The hash cache scoped to a construct-tree root, created on first use.
|
|
73
|
+
*
|
|
74
|
+
* See {@link hashCachesByRoot} for why the cache is scoped per root.
|
|
75
|
+
*/
|
|
76
|
+
function hashCacheFor(root) {
|
|
77
|
+
let cache = hashCachesByRoot.get(root);
|
|
78
|
+
if (!cache) {
|
|
79
|
+
cache = new Map();
|
|
80
|
+
hashCachesByRoot.set(root, cache);
|
|
81
|
+
}
|
|
82
|
+
return cache;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Eager-build scratch directories awaiting cleanup, swept on process exit or
|
|
86
|
+
* an interrupting signal.
|
|
87
|
+
*
|
|
88
|
+
* An `OUTPUT`-hash build runs in the constructor but is normally torn down in
|
|
89
|
+
* `stage()`. When the asset's stack is not synthesized this pass, `stage()`
|
|
90
|
+
* never runs, so the sweep reclaims what can be large trees (`node_modules`,
|
|
91
|
+
* build caches) that `os.tmpdir()` does not clear reliably.
|
|
92
|
+
*/
|
|
93
|
+
const strandedScratchDirs = new Set();
|
|
94
|
+
let exitSweepInstalled = false;
|
|
95
|
+
/**
|
|
96
|
+
* Synchronously remove every still-registered scratch directory.
|
|
97
|
+
*/
|
|
98
|
+
function sweepStrandedScratch() {
|
|
99
|
+
for (const stray of strandedScratchDirs) {
|
|
100
|
+
try {
|
|
101
|
+
fs.rmSync(stray, { recursive: true, force: true });
|
|
102
|
+
}
|
|
103
|
+
catch {
|
|
104
|
+
// Best-effort on the way out; nothing useful to do if it fails.
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
strandedScratchDirs.clear();
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Track a scratch directory for removal if it survives to process exit.
|
|
111
|
+
*
|
|
112
|
+
* `exit` alone misses a Ctrl-C or a `kill` during synth — exactly when the
|
|
113
|
+
* largest trees (`node_modules`, build caches) are left behind — because Node
|
|
114
|
+
* does not run `exit` handlers on `SIGINT`/`SIGTERM`. The signal handlers
|
|
115
|
+
* sweep, then re-raise the signal so any other listeners (the CLI's own) still
|
|
116
|
+
* run, or the default disposition terminates the process if there are none.
|
|
117
|
+
*/
|
|
118
|
+
function registerStrandedScratch(dir) {
|
|
119
|
+
strandedScratchDirs.add(dir);
|
|
120
|
+
if (!exitSweepInstalled) {
|
|
121
|
+
exitSweepInstalled = true;
|
|
122
|
+
// `exit` handlers must be synchronous; `rmSync` is.
|
|
123
|
+
process.once("exit", sweepStrandedScratch);
|
|
124
|
+
for (const signal of ["SIGINT", "SIGTERM"]) {
|
|
125
|
+
process.once(signal, () => {
|
|
126
|
+
sweepStrandedScratch();
|
|
127
|
+
// Re-raise so the signal is not swallowed. `process.once` has already
|
|
128
|
+
// removed this listener, so the re-raise reaches whatever else is
|
|
129
|
+
// registered — the CLI's own SIGINT/SIGTERM handlers — or, if nothing
|
|
130
|
+
// is, the default disposition that terminates the process. Removing
|
|
131
|
+
// other listeners here would discard exactly those the app relies on.
|
|
132
|
+
process.kill(process.pid, signal);
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Resolves an asset's identity and stages its content to disk.
|
|
139
|
+
*
|
|
140
|
+
* The hash is available immediately after construction; the filesystem write
|
|
141
|
+
* is deferred to `stage()`, the one window where it is safe. Hashing is
|
|
142
|
+
* cached per synth (see {@link hashCachesByRoot}) so an asset referenced from
|
|
143
|
+
* several places is walked once. Without a bundler, `SOURCE` and `OUTPUT` both
|
|
144
|
+
* hash the source; with one they diverge, as `AssetStagingOptions.bundler`
|
|
145
|
+
* describes.
|
|
146
|
+
*/
|
|
147
|
+
class AssetStaging extends constructs_1.Construct {
|
|
148
|
+
static [JSII_RTTI_SYMBOL_1] = { fqn: "cdktn.AssetStaging", version: "0.25.0" };
|
|
149
|
+
sourcePath;
|
|
150
|
+
displayName;
|
|
151
|
+
ignoreStrategy;
|
|
152
|
+
hasExclusions;
|
|
153
|
+
hashCache;
|
|
154
|
+
bundler;
|
|
155
|
+
/**
|
|
156
|
+
* Output of an eager `OUTPUT`-hash build, carried to `stage()` for reuse.
|
|
157
|
+
*
|
|
158
|
+
* Undefined on every other path, where the build is deferred or absent.
|
|
159
|
+
*/
|
|
160
|
+
eagerBuild;
|
|
161
|
+
/**
|
|
162
|
+
* Set once `stage()` has run, so a second call cannot rebuild. An eager
|
|
163
|
+
* `OUTPUT` build is captured at construction and consumed by the first
|
|
164
|
+
* `stage()`; without this guard a second call would fall through to the
|
|
165
|
+
* deferred build path and stage bytes that no longer match the hash.
|
|
166
|
+
*/
|
|
167
|
+
staged = false;
|
|
168
|
+
packaging;
|
|
169
|
+
isDirectory;
|
|
170
|
+
assetHash;
|
|
171
|
+
constructor(scope, id, props) {
|
|
172
|
+
super(scope, id);
|
|
173
|
+
this.sourcePath = props.sourcePath;
|
|
174
|
+
this.displayName = props.displayName ?? id;
|
|
175
|
+
this.packaging = props.packaging;
|
|
176
|
+
this.isDirectory = props.packaging.producesDirectory;
|
|
177
|
+
this.hashCache = hashCacheFor(this.node.root);
|
|
178
|
+
this.bundler = props.bundler;
|
|
179
|
+
if (props.exclude?.length && props.ignoreStrategy) {
|
|
180
|
+
throw (0, errors_1.assetStagingConflictingExcludeOptions)(this.displayName);
|
|
181
|
+
}
|
|
182
|
+
this.ignoreStrategy =
|
|
183
|
+
props.ignoreStrategy ?? new ignore_strategy_1.ExcludeIgnoreStrategy(props.exclude ?? []);
|
|
184
|
+
// A custom strategy is assumed to exclude something; the built-in one only
|
|
185
|
+
// does with a non-empty `exclude`. Drives whether the bundler is handed a
|
|
186
|
+
// materialised filtered copy or the source directly.
|
|
187
|
+
this.hasExclusions =
|
|
188
|
+
props.ignoreStrategy !== undefined || !!props.exclude?.length;
|
|
189
|
+
// Bundler output shape (directory vs file) is only known once `bundle`
|
|
190
|
+
// runs, so its compatibility with the packaging is checked then, not here
|
|
191
|
+
// — a deferred SOURCE build has not run yet at construction time.
|
|
192
|
+
this.assetHash = this.resolveAssetHash(this.displayName, props);
|
|
193
|
+
}
|
|
194
|
+
resolveAssetHash(id, props) {
|
|
195
|
+
const { assetHash, assetHashType, extraHash } = props;
|
|
196
|
+
if (assetHash !== undefined) {
|
|
197
|
+
if (assetHashType !== undefined &&
|
|
198
|
+
assetHashType !== assets_1.AssetHashType.CUSTOM) {
|
|
199
|
+
throw (0, errors_1.assetHashConflictingHashType)(id);
|
|
200
|
+
}
|
|
201
|
+
if (!SAFE_ASSET_HASH.test(assetHash)) {
|
|
202
|
+
throw (0, errors_1.assetHashInvalid)(id, assetHash);
|
|
203
|
+
}
|
|
204
|
+
return assetHash;
|
|
205
|
+
}
|
|
206
|
+
switch (assetHashType) {
|
|
207
|
+
case assets_1.AssetHashType.CUSTOM:
|
|
208
|
+
throw (0, errors_1.assetHashTypeCustomRequiresHash)(id);
|
|
209
|
+
case assets_1.AssetHashType.SOURCE:
|
|
210
|
+
case assets_1.AssetHashType.OUTPUT:
|
|
211
|
+
case undefined: {
|
|
212
|
+
const canonical = !!this.node.tryGetContext(features_1.CANONICAL_ASSET_HASHES);
|
|
213
|
+
const archive = this.packaging.omitsDirectoryEntries;
|
|
214
|
+
const salt = this.node.tryGetContext(exports.ASSET_HASH_SALT_CONTEXT_KEY);
|
|
215
|
+
// OUTPUT hashes the built artifact and so must build eagerly, forgoing
|
|
216
|
+
// skippability (#380); every other case hashes the source verbatim.
|
|
217
|
+
const baseHash = this.bundler && assetHashType === assets_1.AssetHashType.OUTPUT
|
|
218
|
+
? this.hashOutput(canonical, archive)
|
|
219
|
+
: this.hashSource(canonical, archive);
|
|
220
|
+
// For SOURCE, folding in bundlerKey is the only way build identity
|
|
221
|
+
// reaches the hash, since the source tree cannot see the build.
|
|
222
|
+
const bundlerKey = this.bundler?.bundlerKey;
|
|
223
|
+
if (!extraHash && !salt && !bundlerKey) {
|
|
224
|
+
return baseHash;
|
|
225
|
+
}
|
|
226
|
+
const folded = crypto.createHash("md5").update(baseHash);
|
|
227
|
+
if (extraHash) {
|
|
228
|
+
folded.update(extraHash);
|
|
229
|
+
}
|
|
230
|
+
if (bundlerKey) {
|
|
231
|
+
folded.update(bundlerKey);
|
|
232
|
+
}
|
|
233
|
+
if (salt) {
|
|
234
|
+
folded.update(String(salt));
|
|
235
|
+
}
|
|
236
|
+
return folded.digest("hex").slice(0, 32).toUpperCase();
|
|
237
|
+
}
|
|
238
|
+
default:
|
|
239
|
+
// Out-of-range value from a non-TypeScript caller.
|
|
240
|
+
throw (0, errors_1.assetHashTypeUnknown)(id, assetHashType);
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* Hash the source tree, honoring the ignore strategy.
|
|
245
|
+
*
|
|
246
|
+
* Cached per synth so an asset referenced more than once is walked once.
|
|
247
|
+
*/
|
|
248
|
+
hashSource(canonical, archive) {
|
|
249
|
+
// Only cacheable when the ignore strategy can summarize its behavior
|
|
250
|
+
// as a string (see `IIgnoreStrategy.cacheKey`); otherwise every call
|
|
251
|
+
// is treated as unique.
|
|
252
|
+
const cacheKey = this.ignoreStrategy.cacheKey !== undefined
|
|
253
|
+
? JSON.stringify({
|
|
254
|
+
sourcePath: this.sourcePath,
|
|
255
|
+
canonical,
|
|
256
|
+
archive,
|
|
257
|
+
ignore: this.ignoreStrategy.cacheKey,
|
|
258
|
+
})
|
|
259
|
+
: undefined;
|
|
260
|
+
const cached = cacheKey ? this.hashCache.get(cacheKey) : undefined;
|
|
261
|
+
if (cached !== undefined) {
|
|
262
|
+
return cached;
|
|
263
|
+
}
|
|
264
|
+
const hash = (0, fs_1.hashPath)(this.sourcePath, {
|
|
265
|
+
canonical,
|
|
266
|
+
archive,
|
|
267
|
+
shouldExclude: (relativePath, isDirectory) => this.ignoreStrategy.ignores({ relativePath, isDirectory }),
|
|
268
|
+
descendIntoExcludedDirectories: this.ignoreStrategy.pruneExcludedDirectories === false,
|
|
269
|
+
});
|
|
270
|
+
if (cacheKey) {
|
|
271
|
+
this.hashCache.set(cacheKey, hash);
|
|
272
|
+
}
|
|
273
|
+
return hash;
|
|
274
|
+
}
|
|
275
|
+
/**
|
|
276
|
+
* Build the bundler's output eagerly and hash the built artifact.
|
|
277
|
+
*
|
|
278
|
+
* The output is stashed for `stage()` to reuse, so the build is not
|
|
279
|
+
* repeated. It is hashed verbatim: `exclude` filters the source a bundler
|
|
280
|
+
* reads, not the artifact it produces.
|
|
281
|
+
*/
|
|
282
|
+
hashOutput(canonical, archive) {
|
|
283
|
+
const scratch = fs.mkdtempSync(path.join(os.tmpdir(), "cdktn-bundle-"));
|
|
284
|
+
// Registered so the exit sweep reclaims it if stage() never runs for an
|
|
285
|
+
// unsynthesized stack; stage() removes and unregisters it otherwise.
|
|
286
|
+
registerStrandedScratch(scratch);
|
|
287
|
+
try {
|
|
288
|
+
const { produced, outputType } = this.runBundle(scratch);
|
|
289
|
+
this.eagerBuild = { scratch, produced, outputType };
|
|
290
|
+
// A single-file artifact is hashed as a file (no archive framing); a
|
|
291
|
+
// directory is hashed as the packaged tree would be.
|
|
292
|
+
const isFile = outputType === assets_1.BundleOutputType.FILE;
|
|
293
|
+
return (0, fs_1.hashPath)(produced, { canonical, archive: archive && !isFile });
|
|
294
|
+
}
|
|
295
|
+
catch (e) {
|
|
296
|
+
// The build failed before `eagerBuild` was set, so stage() can never
|
|
297
|
+
// reach this scratch to clean it. Reclaim it now rather than leaving a
|
|
298
|
+
// potentially large tree (node_modules, build caches) to the exit sweep.
|
|
299
|
+
this.cleanupScratch(scratch);
|
|
300
|
+
throw e;
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
/**
|
|
304
|
+
* Run the bundler against the filtered source and return its output.
|
|
305
|
+
*
|
|
306
|
+
* The bundler is handed an absolute `source` (its cwd is its own, so a
|
|
307
|
+
* relative path would resolve elsewhere) that has already had `exclude`
|
|
308
|
+
* applied. Materialising the filtered input here is what makes the bundler
|
|
309
|
+
* read exactly the tree the hash was taken over, which a raw source
|
|
310
|
+
* hand-off would not, since `hashSource` honours `exclude`.
|
|
311
|
+
*/
|
|
312
|
+
runBundle(scratch) {
|
|
313
|
+
const outputDir = path.join(scratch, "output");
|
|
314
|
+
fs.mkdirSync(outputDir);
|
|
315
|
+
const result = this.bundler.bundle({
|
|
316
|
+
source: this.filteredSource(scratch),
|
|
317
|
+
outputDir,
|
|
318
|
+
});
|
|
319
|
+
// A bare bundler that declines has nothing to fall back to — declining is
|
|
320
|
+
// only meaningful inside a ChainBundler, which consumes it before it
|
|
321
|
+
// reaches here. A non-declined result always carries a path and shape.
|
|
322
|
+
if (result.isDeclined ||
|
|
323
|
+
result.path === undefined ||
|
|
324
|
+
result.outputType === undefined) {
|
|
325
|
+
throw (0, errors_1.assetStagingBundlerOutputNotDirectory)(this.displayName, String(result.path));
|
|
326
|
+
}
|
|
327
|
+
const produced = result.path;
|
|
328
|
+
this.validateOutputShape(produced, result.outputType);
|
|
329
|
+
return { produced, outputType: result.outputType };
|
|
330
|
+
}
|
|
331
|
+
/**
|
|
332
|
+
* Reject a bundler result whose declared shape does not match what is on
|
|
333
|
+
* disk, or does not match the packaging.
|
|
334
|
+
*
|
|
335
|
+
* Catching the mismatch here turns an opaque EISDIR/EPERM at pack time into
|
|
336
|
+
* a clear error naming the packaging the bundler's output shape needs.
|
|
337
|
+
*/
|
|
338
|
+
validateOutputShape(produced, outputType) {
|
|
339
|
+
const exists = fs.existsSync(produced);
|
|
340
|
+
const stat = exists ? fs.statSync(produced) : undefined;
|
|
341
|
+
if (outputType === assets_1.BundleOutputType.FILE) {
|
|
342
|
+
if (!stat?.isFile()) {
|
|
343
|
+
throw (0, errors_1.assetStagingBundlerOutputNotFile)(this.displayName, produced);
|
|
344
|
+
}
|
|
345
|
+
if (!this.stagesSingleFile) {
|
|
346
|
+
throw (0, errors_1.assetStagingBundlerFileOutputNeedsFilePackaging)(this.displayName);
|
|
347
|
+
}
|
|
348
|
+
return;
|
|
349
|
+
}
|
|
350
|
+
if (!stat?.isDirectory()) {
|
|
351
|
+
throw (0, errors_1.assetStagingBundlerOutputNotDirectory)(this.displayName, produced);
|
|
352
|
+
}
|
|
353
|
+
if (!this.packaging.acceptsDirectorySource) {
|
|
354
|
+
throw (0, errors_1.assetStagingBundlerDirectoryOutputNeedsDirectoryPackaging)(this.displayName);
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
/**
|
|
358
|
+
* Whether the packaging stages a single file verbatim (AssetType.FILE).
|
|
359
|
+
*
|
|
360
|
+
* A verbatim-file packaging neither produces a directory nor reads one as
|
|
361
|
+
* its source. Derived from existing `IAssetPackaging` flags so out-of-tree
|
|
362
|
+
* packagings need no new interface member.
|
|
363
|
+
*/
|
|
364
|
+
get stagesSingleFile() {
|
|
365
|
+
return (!this.packaging.producesDirectory &&
|
|
366
|
+
!this.packaging.acceptsDirectorySource);
|
|
367
|
+
}
|
|
368
|
+
/**
|
|
369
|
+
* Absolute path to the source the bundler should read.
|
|
370
|
+
*
|
|
371
|
+
* With no exclusions, or with a file source, the resolved source is handed
|
|
372
|
+
* over directly — a file has no children to filter, matching `hashSource`,
|
|
373
|
+
* which only ever applies the ignore strategy to a directory's entries and
|
|
374
|
+
* never to the root itself. Otherwise the excluded source tree is
|
|
375
|
+
* materialised into the scratch directory, so the bundler sees the same
|
|
376
|
+
* file set the hash was taken over.
|
|
377
|
+
*/
|
|
378
|
+
filteredSource(scratch) {
|
|
379
|
+
const absoluteSource = path.resolve(this.sourcePath);
|
|
380
|
+
if (!this.hasExclusions || fs.statSync(absoluteSource).isFile()) {
|
|
381
|
+
return absoluteSource;
|
|
382
|
+
}
|
|
383
|
+
const input = path.join(scratch, "input");
|
|
384
|
+
fs.mkdirSync(input);
|
|
385
|
+
(0, fs_1.copySync)(absoluteSource, input, {
|
|
386
|
+
shouldExclude: (relativePath, isDirectory) => this.ignoreStrategy.ignores({ relativePath, isDirectory }),
|
|
387
|
+
descendIntoExcludedDirectories: this.ignoreStrategy.pruneExcludedDirectories === false,
|
|
388
|
+
});
|
|
389
|
+
return input;
|
|
390
|
+
}
|
|
391
|
+
/**
|
|
392
|
+
* Stage the asset's content to `targetPath`.
|
|
393
|
+
*
|
|
394
|
+
* Called from the owning construct's `onSynthesize` hook. Without a bundler
|
|
395
|
+
* the source is packaged verbatim; with one, the bundler's output is, built
|
|
396
|
+
* eagerly for `OUTPUT` hashing or deferred to here for `SOURCE`.
|
|
397
|
+
*/
|
|
398
|
+
stage(targetPath) {
|
|
399
|
+
// Stage exactly once: a rebuild could stage bytes not matching the
|
|
400
|
+
// already-computed hash (see the `staged` field).
|
|
401
|
+
if (this.staged) {
|
|
402
|
+
throw (0, errors_1.assetStagingAlreadyStaged)(this.displayName);
|
|
403
|
+
}
|
|
404
|
+
this.staged = true;
|
|
405
|
+
if (!this.bundler) {
|
|
406
|
+
this.packaging.pack({
|
|
407
|
+
source: this.sourcePath,
|
|
408
|
+
target: targetPath,
|
|
409
|
+
ignoreStrategy: this.ignoreStrategy,
|
|
410
|
+
});
|
|
411
|
+
return;
|
|
412
|
+
}
|
|
413
|
+
// `OUTPUT` hashing already built the artifact in the constructor; package
|
|
414
|
+
// that exact result and clean up its scratch, rather than building twice.
|
|
415
|
+
if (this.eagerBuild) {
|
|
416
|
+
const { scratch, produced } = this.eagerBuild;
|
|
417
|
+
this.eagerBuild = undefined;
|
|
418
|
+
try {
|
|
419
|
+
this.packBundlerOutput(produced, targetPath);
|
|
420
|
+
}
|
|
421
|
+
finally {
|
|
422
|
+
this.cleanupScratch(scratch);
|
|
423
|
+
}
|
|
424
|
+
return;
|
|
425
|
+
}
|
|
426
|
+
// `SOURCE` hashing defers the build to here.
|
|
427
|
+
const scratch = fs.mkdtempSync(path.join(os.tmpdir(), "cdktn-bundle-"));
|
|
428
|
+
try {
|
|
429
|
+
const { produced } = this.runBundle(scratch);
|
|
430
|
+
this.packBundlerOutput(produced, targetPath);
|
|
431
|
+
}
|
|
432
|
+
finally {
|
|
433
|
+
this.cleanupScratch(scratch);
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
/**
|
|
437
|
+
* Remove a bundler scratch directory and drop it from the exit-sweep set.
|
|
438
|
+
*/
|
|
439
|
+
cleanupScratch(scratch) {
|
|
440
|
+
fs.rmSync(scratch, { recursive: true, force: true });
|
|
441
|
+
strandedScratchDirs.delete(scratch);
|
|
442
|
+
}
|
|
443
|
+
/**
|
|
444
|
+
* Package a bundler's output into `targetPath`, verbatim.
|
|
445
|
+
*
|
|
446
|
+
* The output's shape was already validated against the packaging in
|
|
447
|
+
* {@link runBundle}, so the packaging handles the source directly — a file
|
|
448
|
+
* source for AssetType.FILE, a directory source otherwise.
|
|
449
|
+
*
|
|
450
|
+
* The ignore strategy is deliberately not applied. `exclude` filters the
|
|
451
|
+
* source a bundler reads, not its product: an install-style bundler
|
|
452
|
+
* (`npm install --production`, `pip install -t`) writes exactly the
|
|
453
|
+
* dependency directory a user excludes from source, and re-applying the
|
|
454
|
+
* exclusion would ship an artifact missing those dependencies.
|
|
455
|
+
*/
|
|
456
|
+
packBundlerOutput(produced, targetPath) {
|
|
457
|
+
this.packaging.pack({
|
|
458
|
+
source: produced,
|
|
459
|
+
target: targetPath,
|
|
460
|
+
});
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
exports.AssetStaging = AssetStaging;
|
|
464
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXNzZXQtc3RhZ2luZy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9hc3NldC1zdGFnaW5nLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQSwrQkFBK0I7QUFDL0IsbUNBQW1DO0FBQ25DLDJDQUFtRDtBQUNuRCwrQ0FBaUM7QUFDakMsdUNBQXlCO0FBQ3pCLHVDQUF5QjtBQUN6QiwyQ0FBNkI7QUFDN0IscUNBT2tCO0FBQ2xCLHFDQVdrQjtBQUNsQix5Q0FBb0Q7QUFDcEQsdURBQTJFO0FBQzNFLHFDQUFrRDtBQUVsRCxrRkFBa0Y7QUFDbEYsZ0VBQWdFO0FBQ2hFLE1BQU0sZUFBZSxHQUFHLG1CQUFtQixDQUFDO0FBRTVDOzs7O0dBSUc7QUFDVSxRQUFBLDJCQUEyQixHQUFHLHFCQUFxQixDQUFDO0FBRWpFOzs7Ozs7Ozs7O0dBVUc7QUFDSCxNQUFNLGdCQUFnQixHQUFHLElBQUksT0FBTyxFQUFtQyxDQUFDO0FBRXhFOzs7O0dBSUc7QUFDSCxTQUFTLFlBQVksQ0FBQyxJQUFnQjtJQUNwQyxJQUFJLEtBQUssR0FBRyxnQkFBZ0IsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDdkMsSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFDO1FBQ1gsS0FBSyxHQUFHLElBQUksR0FBRyxFQUFFLENBQUM7UUFDbEIsZ0JBQWdCLENBQUMsR0FBRyxDQUFDLElBQUksRUFBRSxLQUFLLENBQUMsQ0FBQztJQUNwQyxDQUFDO0lBQ0QsT0FBTyxLQUFLLENBQUM7QUFDZixDQUFDO0FBRUQ7Ozs7Ozs7O0dBUUc7QUFDSCxNQUFNLG1CQUFtQixHQUFHLElBQUksR0FBRyxFQUFVLENBQUM7QUFDOUMsSUFBSSxrQkFBa0IsR0FBRyxLQUFLLENBQUM7QUFFL0I7O0dBRUc7QUFDSCxTQUFTLG9CQUFvQjtJQUMzQixLQUFLLE1BQU0sS0FBSyxJQUFJLG1CQUFtQixFQUFFLENBQUM7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VyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLE1BQU0sRUFBRSxFQUFFLGVBQWUsQ0FBQyxDQUFDLENBQUM7UUFDeEUsSUFBSSxDQUFDO1lBQ0gsTUFBTSxFQUFFLFFBQVEsRUFBRSxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsT0FBTyxDQUFDLENBQUM7WUFDN0MsSUFBSSxDQUFDLGlCQUFpQixDQUFDLFFBQVEsRUFBRSxVQUFVLENBQUMsQ0FBQztRQUMvQyxDQUFDO2dCQUFTLENBQUM7WUFDVCxJQUFJLENBQUMsY0FBYyxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQy9CLENBQUM7SUFDSCxDQUFDO0lBRUQ7O09BRUc7SUFDSyxjQUFjLENBQUMsT0FBZTtRQUNwQyxFQUFFLENBQUMsTUFBTSxDQUFDLE9BQU8sRUFBRSxFQUFFLFNBQVMsRUFBRSxJQUFJLEVBQUUsS0FBSyxFQUFFLElBQUksRUFBRSxDQUFDLENBQUM7UUFDckQsbUJBQW1CLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQ3RDLENBQUM7SUFFRDs7Ozs7Ozs7Ozs7O09BWUc7SUFDSyxpQkFBaUIsQ0FBQyxRQUFnQixFQUFFLFVBQWtCO1FBQzVELElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDO1lBQ2xCLE1BQU0sRUFBRSxRQUFRO1lBQ2hCLE1BQU0sRUFBRSxVQUFVO1NBQ25CLENBQUMsQ0FBQztJQUNMLENBQUM7O0FBaFhILG9DQWlYQyIsInNvdXJjZXNDb250ZW50IjpbIi8vIENvcHlyaWdodCAoYykgSGFzaGlDb3JwLCBJbmNcbi8vIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBNUEwtMi4wXG5pbXBvcnQgeyBDb25zdHJ1Y3QsIElDb25zdHJ1Y3QgfSBmcm9tIFwiY29uc3RydWN0c1wiO1xuaW1wb3J0ICogYXMgY3J5cHRvIGZyb20gXCJjcnlwdG9cIjtcbmltcG9ydCAqIGFzIGZzIGZyb20gXCJmc1wiO1xuaW1wb3J0ICogYXMgb3MgZnJvbSBcIm9zXCI7XG5pbXBvcnQgKiBhcyBwYXRoIGZyb20gXCJwYXRoXCI7XG5pbXBvcnQge1xuICBBc3NldEhhc2hUeXBlLFxuICBBc3NldE9wdGlvbnMsXG4gIEJ1bmRsZU91dHB1dFR5cGUsXG4gIElBc3NldCxcbiAgSUFzc2V0QnVuZGxlcixcbiAgSUFzc2V0UGFja2FnaW5nLFxufSBmcm9tIFwiLi9hc3NldHNcIjtcbmltcG9ydCB7XG4gIGFzc2V0SGFzaENvbmZsaWN0aW5nSGFzaFR5cGUsXG4gIGFzc2V0SGFzaEludmFsaWQsXG4gIGFzc2V0SGFzaFR5cGVDdXN0b21SZXF1aXJlc0hhc2gsXG4gIGFzc2V0SGFzaFR5cGVVbmtub3duLFxuICBhc3NldFN0YWdpbmdBbHJlYWR5U3RhZ2VkLFxuICBhc3NldFN0YWdpbmdCdW5kbGVyRGlyZWN0b3J5T3V0cHV0TmVlZHNEaXJlY3RvcnlQYWNrYWdpbmcsXG4gIGFzc2V0U3RhZ2luZ0J1bmRsZXJGaWxlT3V0cHV0TmVlZHNGaWxlUGFja2FnaW5nLFxuICBhc3NldFN0YWdpbmdCdW5kbGVyT3V0cHV0Tm90RGlyZWN0b3J5LFxuICBhc3NldFN0YWdpbmdCdW5kbGVyT3V0cHV0Tm90RmlsZSxcbiAgYXNzZXRTdGFnaW5nQ29uZmxpY3RpbmdFeGNsdWRlT3B0aW9ucyxcbn0gZnJvbSBcIi4vZXJyb3JzXCI7XG5pbXBvcnQgeyBDQU5PTklDQUxfQVNTRVRfSEFTSEVTIH0gZnJvbSBcIi4vZmVhdHVyZXNcIjtcbmltcG9ydCB7IEV4Y2x1ZGVJZ25vcmVTdHJhdGVneSwgSUlnbm9yZVN0cmF0ZWd5IH0gZnJvbSBcIi4vaWdub3JlLXN0cmF0ZWd5XCI7XG5pbXBvcnQgeyBjb3B5U3luYywgaGFzaFBhdGggfSBmcm9tIFwiLi9wcml2YXRlL2ZzXCI7XG5cbi8vIEEgcmVzb2x2ZWQgaGFzaCBpcyB1c2VkIHZlcmJhdGltIGFzIGEgcGF0aCBzZWdtZW50IChzZWUgYFRlcnJhZm9ybUFzc2V0LnBhdGhgKSxcbi8vIHNvIGl0IG1heSBvbmx5IGNvbnRhaW4gY2hhcmFjdGVycyB0aGF0IGFyZSBhbHdheXMgc2FmZSB0aGVyZS5cbmNvbnN0IFNBRkVfQVNTRVRfSEFTSCA9IC9eW0EtWmEtejAtOV8uLV0rJC87XG5cbi8qKlxuICogQ29udGV4dCBrZXkgZm9yIGEgdmFsdWUgZm9sZGVkIGludG8gZXZlcnkgY29tcHV0ZWQgYXNzZXQgaGFzaCBpbiB0aGVcbiAqIGNvbnN0cnVjdCB0cmVlLCBhbG9uZ3NpZGUgYGV4dHJhSGFzaGAuIEEgYnVsayBjYWNoZS1idXN0aW5nIGVzY2FwZSBoYXRjaCDigJRcbiAqIGBleHRyYUhhc2hgIGlzIHNjb3BlZCB0byBvbmUgYXNzZXQsIHRoaXMgaXMgc2NvcGVkIHRvIHRoZSB3aG9sZSBhcHAuXG4gKi9cbmV4cG9ydCBjb25zdCBBU1NFVF9IQVNIX1NBTFRfQ09OVEVYVF9LRVkgPSBcImNka3RuOmFzc2V0SGFzaFNhbHRcIjtcblxuLyoqXG4gKiBDYWNoZXMgdGhlIGJhc2UgKHByZSBgZXh0cmFIYXNoYC9zYWx0KSBoYXNoIG9mIGEgYFNPVVJDRWAvYE9VVFBVVGAgd2FsayxcbiAqIHNvIHRoYXQgbXVsdGlwbGUgYEFzc2V0U3RhZ2luZ2AgaW5zdGFuY2VzIHdpdGggaWRlbnRpY2FsIGlucHV0cyDigJQgdGhlIHNhbWVcbiAqIGFzc2V0IHJlZmVyZW5jZWQgZnJvbSBtb3JlIHRoYW4gb25lIHJlc291cmNlIG9yIHN0YWNrIOKAlCBoYXNoIHRoZSBzb3VyY2VcbiAqIHRyZWUgb25jZSBwZXIgc3ludGggaW5zdGVhZCBvZiBvbmNlIHBlciByZWZlcmVuY2UuXG4gKlxuICogS2V5ZWQgcGVyIGNvbnN0cnVjdC10cmVlIHJvb3QgKHRoZSBgQXBwYCkgcmF0aGVyIHRoYW4gYXQgbW9kdWxlIHNjb3BlOiBhblxuICogQXBwIGluc3RhbmNlIGxpdmVzIGV4YWN0bHkgYXMgbG9uZyBhcyBvbmUgc3ludGgsIHNvIGEgbG9uZy1ydW5uaW5nIHByb2Nlc3NcbiAqIHRoYXQgc3ludGhzIHJlcGVhdGVkbHkgYWdhaW5zdCBjaGFuZ2luZyBmaWxlcyAoZS5nLiBgY2RrdG4gd2F0Y2hgKSBhbHdheXNcbiAqIGdldHMgYSBmcmVzaCBjYWNoZSBpbnN0ZWFkIG9mIGEgc3RhbGUgaGFzaCBmcm9tIGEgcHJldmlvdXMgc3ludGguXG4gKi9cbmNvbnN0IGhhc2hDYWNoZXNCeVJvb3QgPSBuZXcgV2Vha01hcDxJQ29uc3RydWN0LCBNYXA8c3RyaW5nLCBzdHJpbmc+PigpO1xuXG4vKipcbiAqIFRoZSBoYXNoIGNhY2hlIHNjb3BlZCB0byBhIGNvbnN0cnVjdC10cmVlIHJvb3QsIGNyZWF0ZWQgb24gZmlyc3QgdXNlLlxuICpcbiAqIFNlZSB7QGxpbmsgaGFzaENhY2hlc0J5Um9vdH0gZm9yIHdoeSB0aGUgY2FjaGUgaXMgc2NvcGVkIHBlciByb290LlxuICovXG5mdW5jdGlvbiBoYXNoQ2FjaGVGb3Iocm9vdDogSUNvbnN0cnVjdCk6IE1hcDxzdHJpbmcsIHN0cmluZz4ge1xuICBsZXQgY2FjaGUgPSBoYXNoQ2FjaGVzQnlSb290LmdldChyb290KTtcbiAgaWYgKCFjYWNoZSkge1xuICAgIGNhY2hlID0gbmV3IE1hcCgpO1xuICAgIGhhc2hDYWNoZXNCeVJvb3Quc2V0KHJvb3QsIGNhY2hlKTtcbiAgfVxuICByZXR1cm4gY2FjaGU7XG59XG5cbi8qKlxuICogRWFnZXItYnVpbGQgc2NyYXRjaCBkaXJlY3RvcmllcyBhd2FpdGluZyBjbGVhbnVwLCBzd2VwdCBvbiBwcm9jZXNzIGV4aXQgb3JcbiAqIGFuIGludGVycnVwdGluZyBzaWduYWwuXG4gKlxuICogQW4gYE9VVFBVVGAtaGFzaCBidWlsZCBydW5zIGluIHRoZSBjb25zdHJ1Y3RvciBidXQgaXMgbm9ybWFsbHkgdG9ybiBkb3duIGluXG4gKiBgc3RhZ2UoKWAuIFdoZW4gdGhlIGFzc2V0J3Mgc3RhY2sgaXMgbm90IHN5bnRoZXNpemVkIHRoaXMgcGFzcywgYHN0YWdlKClgXG4gKiBuZXZlciBydW5zLCBzbyB0aGUgc3dlZXAgcmVjbGFpbXMgd2hhdCBjYW4gYmUgbGFyZ2UgdHJlZXMgKGBub2RlX21vZHVsZXNgLFxuICogYnVpbGQgY2FjaGVzKSB0aGF0IGBvcy50bXBkaXIoKWAgZG9lcyBub3QgY2xlYXIgcmVsaWFibHkuXG4gKi9cbmNvbnN0IHN0cmFuZGVkU2NyYXRjaERpcnMgPSBuZXcgU2V0PHN0cmluZz4oKTtcbmxldCBleGl0U3dlZXBJbnN0YWxsZWQgPSBmYWxzZTtcblxuLyoqXG4gKiBTeW5jaHJvbm91c2x5IHJlbW92ZSBldmVyeSBzdGlsbC1yZWdpc3RlcmVkIHNjcmF0Y2ggZGlyZWN0b3J5LlxuICovXG5mdW5jdGlvbiBzd2VlcFN0cmFuZGVkU2NyYXRjaCgpOiB2b2lkIHtcbiAgZm9yIChjb25zdCBzdHJheSBvZiBzdHJhbmRlZFNjcmF0Y2hEaXJzKSB7XG4gICAgdHJ5IHtcbiAgICAgIGZzLnJtU3luYyhzdHJheSwgeyByZWN1cnNpdmU6IHRydWUsIGZvcmNlOiB0cnVlIH0pO1xuICAgIH0gY2F0Y2gge1xuICAgICAgLy8gQmVzdC1lZmZvcnQgb24gdGhlIHdheSBvdXQ7IG5vdGhpbmcgdXNlZnVsIHRvIGRvIGlmIGl0IGZhaWxzLlxuICAgIH1cbiAgfVxuICBzdHJhbmRlZFNjcmF0Y2hEaXJzLmNsZWFyKCk7XG59XG5cbi8qKlxuICogVHJhY2sgYSBzY3JhdGNoIGRpcmVjdG9yeSBmb3IgcmVtb3ZhbCBpZiBpdCBzdXJ2aXZlcyB0byBwcm9jZXNzIGV4aXQuXG4gKlxuICogYGV4aXRgIGFsb25lIG1pc3NlcyBhIEN0cmwtQyBvciBhIGBraWxsYCBkdXJpbmcgc3ludGgg4oCUIGV4YWN0bHkgd2hlbiB0aGVcbiAqIGxhcmdlc3QgdHJlZXMgKGBub2RlX21vZHVsZXNgLCBidWlsZCBjYWNoZXMpIGFyZSBsZWZ0IGJlaGluZCDigJQgYmVjYXVzZSBOb2RlXG4gKiBkb2VzIG5vdCBydW4gYGV4aXRgIGhhbmRsZXJzIG9uIGBTSUdJTlRgL2BTSUdURVJNYC4gVGhlIHNpZ25hbCBoYW5kbGVyc1xuICogc3dlZXAsIHRoZW4gcmUtcmFpc2UgdGhlIHNpZ25hbCBzbyBhbnkgb3RoZXIgbGlzdGVuZXJzICh0aGUgQ0xJJ3Mgb3duKSBzdGlsbFxuICogcnVuLCBvciB0aGUgZGVmYXVsdCBkaXNwb3NpdGlvbiB0ZXJtaW5hdGVzIHRoZSBwcm9jZXNzIGlmIHRoZXJlIGFyZSBub25lLlxuICovXG5mdW5jdGlvbiByZWdpc3RlclN0cmFuZGVkU2NyYXRjaChkaXI6IHN0cmluZyk6IHZvaWQge1xuICBzdHJhbmRlZFNjcmF0Y2hEaXJzLmFkZChkaXIpO1xuICBpZiAoIWV4aXRTd2VlcEluc3RhbGxlZCkge1xuICAgIGV4aXRTd2VlcEluc3RhbGxlZCA9IHRydWU7XG4gICAgLy8gYGV4aXRgIGhhbmRsZXJzIG11c3QgYmUgc3luY2hyb25vdXM7IGBybVN5bmNgIGlzLlxuICAgIHByb2Nlc3Mub25jZShcImV4aXRcIiwgc3dlZXBTdHJhbmRlZFNjcmF0Y2gpO1xuICAgIGZvciAoY29uc3Qgc2lnbmFsIG9mIFtcIlNJR0lOVFwiLCBcIlNJR1RFUk1cIl0gYXMgY29uc3QpIHtcbiAgICAgIHByb2Nlc3Mub25jZShzaWduYWwsICgpID0+IHtcbiAgICAgICAgc3dlZXBTdHJhbmRlZFNjcmF0Y2goKTtcbiAgICAgICAgLy8gUmUtcmFpc2Ugc28gdGhlIHNpZ25hbCBpcyBub3Qgc3dhbGxvd2VkLiBgcHJvY2Vzcy5vbmNlYCBoYXMgYWxyZWFkeVxuICAgICAgICAvLyByZW1vdmVkIHRoaXMgbGlzdGVuZXIsIHNvIHRoZSByZS1yYWlzZSByZWFjaGVzIHdoYXRldmVyIGVsc2UgaXNcbiAgICAgICAgLy8gcmVnaXN0ZXJlZCDigJQgdGhlIENMSSdzIG93biBTSUdJTlQvU0lHVEVSTSBoYW5kbGVycyDigJQgb3IsIGlmIG5vdGhpbmdcbiAgICAgICAgLy8gaXMsIHRoZSBkZWZhdWx0IGRpc3Bvc2l0aW9uIHRoYXQgdGVybWluYXRlcyB0aGUgcHJvY2Vzcy4gUmVtb3ZpbmdcbiAgICAgICAgLy8gb3RoZXIgbGlzdGVuZXJzIGhlcmUgd291bGQgZGlzY2FyZCBleGFjdGx5IHRob3NlIHRoZSBhcHAgcmVsaWVzIG9uLlxuICAgICAgICBwcm9jZXNzLmtpbGwocHJvY2Vzcy5waWQsIHNpZ25hbCk7XG4gICAgICB9KTtcbiAgICB9XG4gIH1cbn1cblxuLyoqXG4gKiBPcHRpb25zIGZvciB7QGxpbmsgQXNzZXRTdGFnaW5nfS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBBc3NldFN0YWdpbmdPcHRpb25zIGV4dGVuZHMgQXNzZXRPcHRpb25zIHtcbiAgLyoqXG4gICAqIEFic29sdXRlIHBhdGggdG8gdGhlIHNvdXJjZSBmaWxlIG9yIGRpcmVjdG9yeS4gUmVzb2x2aW5nIGEgcmVsYXRpdmUgcGF0aFxuICAgKiBhZ2FpbnN0IGBjZGt0Zi5qc29uYCBpcyB0aGUgY2FsbGVyJ3MgcmVzcG9uc2liaWxpdHkuXG4gICAqL1xuICByZWFkb25seSBzb3VyY2VQYXRoOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIEhvdyB0aGUgc3RhZ2VkIHJlc3VsdCBpcyBwcm9kdWNlZCBhbmQgc2hhcGVkLiBUaGUgY2FsbGVyIGRlY2lkZXMgdGhpc1xuICAgKiAoZS5nLiBmcm9tIGl0cyBvd24gYEFzc2V0VHlwZWApIOKAlCBgQXNzZXRTdGFnaW5nYCBuZXZlciBpbmZlcnMgb3IgY2hhbmdlc1xuICAgKiBpdCBiYXNlZCBvbiBgZXhjbHVkZWAvYGV4dHJhSGFzaGAuXG4gICAqL1xuICByZWFkb25seSBwYWNrYWdpbmc6IElBc3NldFBhY2thZ2luZztcblxuICAvKipcbiAgICogUGF0aHMgdG8gZXhjbHVkZSwgcmVsYXRpdmUgdG8gYHNvdXJjZVBhdGhgLiBDYW5ub3QgYmUgY29tYmluZWQgd2l0aFxuICAgKiBgaWdub3JlU3RyYXRlZ3lgLCB3aGljaCByZXBsYWNlcyB0aGlzIG1hdGNoZXIgcmF0aGVyIHRoYW4gbGF5ZXJpbmcgb25cbiAgICogdG9wIG9mIGl0LlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIG5vdGhpbmcgaXMgZXhjbHVkZWRcbiAgICovXG4gIHJlYWRvbmx5IGV4Y2x1ZGU/OiBzdHJpbmdbXTtcblxuICAvKipcbiAgICogRXhjbHVzaW9uIG1hdGNoaW5nLCBmb3IgY2FsbGVycyB0aGF0IG5lZWQgYC5naXRpZ25vcmVgIC8gYC5kb2NrZXJpZ25vcmVgXG4gICAqIHBhcml0eSByYXRoZXIgdGhhbiB0aGUgYnVpbHQtaW4gZXhhY3QtcGF0aCAvIHN1ZmZpeCAvIGRpcmVjdG9yeSBtYXRjaGVyLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIGBleGNsdWRlYCBpcyB1c2VkIHdpdGggdGhlIGJ1aWx0LWluIG1hdGNoZXJcbiAgICovXG4gIHJlYWRvbmx5IGlnbm9yZVN0cmF0ZWd5PzogSUlnbm9yZVN0cmF0ZWd5O1xuXG4gIC8qKlxuICAgKiBFeHRyYSBpbmZvcm1hdGlvbiB0byBmb2xkIGludG8gdGhlIGhhc2ggKGUuZy4gYnVpbGQgaW5zdHJ1Y3Rpb25zIGFuZFxuICAgKiBvdGhlciBpbnB1dHMpLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIG5vIGV4dHJhIGhhc2hcbiAgICovXG4gIHJlYWRvbmx5IGV4dHJhSGFzaD86IHN0cmluZztcblxuICAvKipcbiAgICogQSBidW5kbGVyIHRoYXQgYnVpbGRzIHRoZSBzb3VyY2UgaW50byBhbiBhcnRpZmFjdCBiZWZvcmUgc3RhZ2luZy5cbiAgICpcbiAgICogVW5kZXIgdGhlIGRlZmF1bHQgYFNPVVJDRWAgaGFzaGluZyB0aGUgYnVpbGQgaXMgZGVmZXJyZWQgdG8gYHN0YWdlKClgIGFuZFxuICAgKiBzdGF5cyBza2lwcGFibGU7IGBPVVRQVVRgIGhhc2hpbmcgYnVpbGRzIGVhZ2VybHkgYXQgY29uc3RydWN0aW9uIHRpbWUgdG9cbiAgICogaGFzaCB0aGUgYXJ0aWZhY3QsIGZvcmdvaW5nIHNraXBwYWJpbGl0eS4gVGhlIGJ1bmRsZXIncyBkZWNsYXJlZCBvdXRwdXRcbiAgICogc2hhcGUgbXVzdCBtYXRjaCB0aGUgcGFja2FnaW5nOiBhIGBCdW5kbGVSZXN1bHQuZGlyZWN0b3J5YCBuZWVkcyBhXG4gICAqIGRpcmVjdG9yeS1hY2NlcHRpbmcgcGFja2FnaW5nLCBhIGBCdW5kbGVSZXN1bHQuZmlsZWAgYSBzaW5nbGUtZmlsZSBvbmVcbiAgICogKGBBc3NldFR5cGUuRklMRWApLiBUaGUgbWlzbWF0Y2ggaXMgY2F1Z2h0IG9uY2UgdGhlIGJ1aWxkIHJ1bnMuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gdGhlIHNvdXJjZSBpcyBzdGFnZWQgdmVyYmF0aW0sIHdpdGggbm8gYnVpbGQgc3RlcFxuICAgKi9cbiAgcmVhZG9ubHkgYnVuZGxlcj86IElBc3NldEJ1bmRsZXI7XG5cbiAgLyoqXG4gICAqIElkZW50aWZpZXIgdXNlZCBpbiBlcnJvciBtZXNzYWdlcywgc28gdGhleSBuYW1lIHRoZSB1c2VyLWZhY2luZyBjb25zdHJ1Y3RcbiAgICogKGUuZy4gdGhlIGBUZXJyYWZvcm1Bc3NldGApIHJhdGhlciB0aGFuIHRoaXMgaW50ZXJuYWwgc3RhZ2luZyBjaGlsZC5cbiAgICpcbiAgICogQGRlZmF1bHQgLSB0aGUgc3RhZ2luZyBjb25zdHJ1Y3QncyBvd24gaWRcbiAgICovXG4gIHJlYWRvbmx5IGRpc3BsYXlOYW1lPzogc3RyaW5nO1xufVxuXG4vKipcbiAqIFJlc29sdmVzIGFuIGFzc2V0J3MgaWRlbnRpdHkgYW5kIHN0YWdlcyBpdHMgY29udGVudCB0byBkaXNrLlxuICpcbiAqIFRoZSBoYXNoIGlzIGF2YWlsYWJsZSBpbW1lZGlhdGVseSBhZnRlciBjb25zdHJ1Y3Rpb247IHRoZSBmaWxlc3lzdGVtIHdyaXRlXG4gKiBpcyBkZWZlcnJlZCB0byBgc3RhZ2UoKWAsIHRoZSBvbmUgd2luZG93IHdoZXJlIGl0IGlzIHNhZmUuIEhhc2hpbmcgaXNcbiAqIGNhY2hlZCBwZXIgc3ludGggKHNlZSB7QGxpbmsgaGFzaENhY2hlc0J5Um9vdH0pIHNvIGFuIGFzc2V0IHJlZmVyZW5jZWQgZnJvbVxuICogc2V2ZXJhbCBwbGFjZXMgaXMgd2Fsa2VkIG9uY2UuIFdpdGhvdXQgYSBidW5kbGVyLCBgU09VUkNFYCBhbmQgYE9VVFBVVGAgYm90aFxuICogaGFzaCB0aGUgc291cmNlOyB3aXRoIG9uZSB0aGV5IGRpdmVyZ2UsIGFzIGBBc3NldFN0YWdpbmdPcHRpb25zLmJ1bmRsZXJgXG4gKiBkZXNjcmliZXMuXG4gKi9cbmV4cG9ydCBjbGFzcyBBc3NldFN0YWdpbmcgZXh0ZW5kcyBDb25zdHJ1Y3QgaW1wbGVtZW50cyBJQXNzZXQge1xuICBwcml2YXRlIHJlYWRvbmx5IHNvdXJjZVBhdGg6IHN0cmluZztcbiAgcHJpdmF0ZSByZWFkb25seSBkaXNwbGF5TmFtZTogc3RyaW5nO1xuICBwcml2YXRlIHJlYWRvbmx5IGlnbm9yZVN0cmF0ZWd5OiBJSWdub3JlU3RyYXRlZ3k7XG4gIHByaXZhdGUgcmVhZG9ubHkgaGFzRXhjbHVzaW9uczogYm9vbGVhbjtcbiAgcHJpdmF0ZSByZWFkb25seSBoYXNoQ2FjaGU6IE1hcDxzdHJpbmcsIHN0cmluZz47XG4gIHByaXZhdGUgcmVhZG9ubHkgYnVuZGxlcj86IElBc3NldEJ1bmRsZXI7XG5cbiAgLyoqXG4gICAqIE91dHB1dCBvZiBhbiBlYWdlciBgT1VUUFVUYC1oYXNoIGJ1aWxkLCBjYXJyaWVkIHRvIGBzdGFnZSgpYCBmb3IgcmV1c2UuXG4gICAqXG4gICAqIFVuZGVmaW5lZCBvbiBldmVyeSBvdGhlciBwYXRoLCB3aGVyZSB0aGUgYnVpbGQgaXMgZGVmZXJyZWQgb3IgYWJzZW50LlxuICAgKi9cbiAgcHJpdmF0ZSBlYWdlckJ1aWxkPzoge1xuICAgIHJlYWRvbmx5IHNjcmF0Y2g6IHN0cmluZztcbiAgICByZWFkb25seSBwcm9kdWNlZDogc3RyaW5nO1xuICAgIHJlYWRvbmx5IG91dHB1dFR5cGU6IEJ1bmRsZU91dHB1dFR5cGU7XG4gIH07XG5cbiAgLyoqXG4gICAqIFNldCBvbmNlIGBzdGFnZSgpYCBoYXMgcnVuLCBzbyBhIHNlY29uZCBjYWxsIGNhbm5vdCByZWJ1aWxkLiBBbiBlYWdlclxuICAgKiBgT1VUUFVUYCBidWlsZCBpcyBjYXB0dXJlZCBhdCBjb25zdHJ1Y3Rpb24gYW5kIGNvbnN1bWVkIGJ5IHRoZSBmaXJzdFxuICAgKiBgc3RhZ2UoKWA7IHdpdGhvdXQgdGhpcyBndWFyZCBhIHNlY29uZCBjYWxsIHdvdWxkIGZhbGwgdGhyb3VnaCB0byB0aGVcbiAgICogZGVmZXJyZWQgYnVpbGQgcGF0aCBhbmQgc3RhZ2UgYnl0ZXMgdGhhdCBubyBsb25nZXIgbWF0Y2ggdGhlIGhhc2guXG4gICAqL1xuICBwcml2YXRlIHN0YWdlZCA9IGZhbHNlO1xuXG4gIHB1YmxpYyByZWFkb25seSBwYWNrYWdpbmc6IElBc3NldFBhY2thZ2luZztcbiAgcHVibGljIHJlYWRvbmx5IGlzRGlyZWN0b3J5OiBib29sZWFuO1xuICBwdWJsaWMgcmVhZG9ubHkgYXNzZXRIYXNoOiBzdHJpbmc7XG5cbiAgcHVibGljIGNvbnN0cnVjdG9yKHNjb3BlOiBDb25zdHJ1Y3QsIGlkOiBzdHJpbmcsIHByb3BzOiBBc3NldFN0YWdpbmdPcHRpb25zKSB7XG4gICAgc3VwZXIoc2NvcGUsIGlkKTtcblxuICAgIHRoaXMuc291cmNlUGF0aCA9IHByb3BzLnNvdXJjZVBhdGg7XG4gICAgdGhpcy5kaXNwbGF5TmFtZSA9IHByb3BzLmRpc3BsYXlOYW1lID8/IGlkO1xuICAgIHRoaXMucGFja2FnaW5nID0gcHJvcHMucGFja2FnaW5nO1xuICAgIHRoaXMuaXNEaXJlY3RvcnkgPSBwcm9wcy5wYWNrYWdpbmcucHJvZHVjZXNEaXJlY3Rvcnk7XG4gICAgdGhpcy5oYXNoQ2FjaGUgPSBoYXNoQ2FjaGVGb3IodGhpcy5ub2RlLnJvb3QpO1xuICAgIHRoaXMuYnVuZGxlciA9IHByb3BzLmJ1bmRsZXI7XG5cbiAgICBpZiAocHJvcHMuZXhjbHVkZT8ubGVuZ3RoICYmIHByb3BzLmlnbm9yZVN0cmF0ZWd5KSB7XG4gICAgICB0aHJvdyBhc3NldFN0YWdpbmdDb25mbGljdGluZ0V4Y2x1ZGVPcHRpb25zKHRoaXMuZGlzcGxheU5hbWUpO1xuICAgIH1cbiAgICB0aGlzLmlnbm9yZVN0cmF0ZWd5ID1cbiAgICAgIHByb3BzLmlnbm9yZVN0cmF0ZWd5ID8/IG5ldyBFeGNsdWRlSWdub3JlU3RyYXRlZ3kocHJvcHMuZXhjbHVkZSA/PyBbXSk7XG4gICAgLy8gQSBjdXN0b20gc3RyYXRlZ3kgaXMgYXNzdW1lZCB0byBleGNsdWRlIHNvbWV0aGluZzsgdGhlIGJ1aWx0LWluIG9uZSBvbmx5XG4gICAgLy8gZG9lcyB3aXRoIGEgbm9uLWVtcHR5IGBleGNsdWRlYC4gRHJpdmVzIHdoZXRoZXIgdGhlIGJ1bmRsZXIgaXMgaGFuZGVkIGFcbiAgICAvLyBtYXRlcmlhbGlzZWQgZmlsdGVyZWQgY29weSBvciB0aGUgc291cmNlIGRpcmVjdGx5LlxuICAgIHRoaXMuaGFzRXhjbHVzaW9ucyA9XG4gICAgICBwcm9wcy5pZ25vcmVTdHJhdGVneSAhPT0gdW5kZWZpbmVkIHx8ICEhcHJvcHMuZXhjbHVkZT8ubGVuZ3RoO1xuXG4gICAgLy8gQnVuZGxlciBvdXRwdXQgc2hhcGUgKGRpcmVjdG9yeSB2cyBmaWxlKSBpcyBvbmx5IGtub3duIG9uY2UgYGJ1bmRsZWBcbiAgICAvLyBydW5zLCBzbyBpdHMgY29tcGF0aWJpbGl0eSB3aXRoIHRoZSBwYWNrYWdpbmcgaXMgY2hlY2tlZCB0aGVuLCBub3QgaGVyZVxuICAgIC8vIOKAlCBhIGRlZmVycmVkIFNPVVJDRSBidWlsZCBoYXMgbm90IHJ1biB5ZXQgYXQgY29uc3RydWN0aW9uIHRpbWUuXG5cbiAgICB0aGlzLmFzc2V0SGFzaCA9IHRoaXMucmVzb2x2ZUFzc2V0SGFzaCh0aGlzLmRpc3BsYXlOYW1lLCBwcm9wcyk7XG4gIH1cblxuICBwcml2YXRlIHJlc29sdmVBc3NldEhhc2goaWQ6IHN0cmluZywgcHJvcHM6IEFzc2V0U3RhZ2luZ09wdGlvbnMpOiBzdHJpbmcge1xuICAgIGNvbnN0IHsgYXNzZXRIYXNoLCBhc3NldEhhc2hUeXBlLCBleHRyYUhhc2ggfSA9IHByb3BzO1xuXG4gICAgaWYgKGFzc2V0SGFzaCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICBpZiAoXG4gICAgICAgIGFzc2V0SGFzaFR5cGUgIT09IHVuZGVmaW5lZCAmJlxuICAgICAgICBhc3NldEhhc2hUeXBlICE9PSBBc3NldEhhc2hUeXBlLkNVU1RPTVxuICAgICAgKSB7XG4gICAgICAgIHRocm93IGFzc2V0SGFzaENvbmZsaWN0aW5nSGFzaFR5cGUoaWQpO1xuICAgICAgfVxuICAgICAgaWYgKCFTQUZFX0FTU0VUX0hBU0gudGVzdChhc3NldEhhc2gpKSB7XG4gICAgICAgIHRocm93IGFzc2V0SGFzaEludmFsaWQoaWQsIGFzc2V0SGFzaCk7XG4gICAgICB9XG4gICAgICByZXR1cm4gYXNzZXRIYXNoO1xuICAgIH1cblxuICAgIHN3aXRjaCAoYXNzZXRIYXNoVHlwZSkge1xuICAgICAgY2FzZSBBc3NldEhhc2hUeXBlLkNVU1RPTTpcbiAgICAgICAgdGhyb3cgYXNzZXRIYXNoVHlwZUN1c3RvbVJlcXVpcmVzSGFzaChpZCk7XG4gICAgICBjYXNlIEFzc2V0SGFzaFR5cGUuU09VUkNFOlxuICAgICAgY2FzZSBBc3NldEhhc2hUeXBlLk9VVFBVVDpcbiAgICAgIGNhc2UgdW5kZWZpbmVkOiB7XG4gICAgICAgIGNvbnN0IGNhbm9uaWNhbCA9ICEhdGhpcy5ub2RlLnRyeUdldENvbnRleHQoQ0FOT05JQ0FMX0FTU0VUX0hBU0hFUyk7XG4gICAgICAgIGNvbnN0IGFyY2hpdmUgPSB0aGlzLnBhY2thZ2luZy5vbWl0c0RpcmVjdG9yeUVudHJpZXM7XG4gICAgICAgIGNvbnN0IHNhbHQgPSB0aGlzLm5vZGUudHJ5R2V0Q29udGV4dChBU1NFVF9IQVNIX1NBTFRfQ09OVEVYVF9LRVkpO1xuXG4gICAgICAgIC8vIE9VVFBVVCBoYXNoZXMgdGhlIGJ1aWx0IGFydGlmYWN0IGFuZCBzbyBtdXN0IGJ1aWxkIGVhZ2VybHksIGZvcmdvaW5nXG4gICAgICAgIC8vIHNraXBwYWJpbGl0eSAoIzM4MCk7IGV2ZXJ5IG90aGVyIGNhc2UgaGFzaGVzIHRoZSBzb3VyY2UgdmVyYmF0aW0uXG4gICAgICAgIGNvbnN0IGJhc2VIYXNoID1cbiAgICAgICAgICB0aGlzLmJ1bmRsZXIgJiYgYXNzZXRIYXNoVHlwZSA9PT0gQXNzZXRIYXNoVHlwZS5PVVRQVVRcbiAgICAgICAgICAgID8gdGhpcy5oYXNoT3V0cHV0KGNhbm9uaWNhbCwgYXJjaGl2ZSlcbiAgICAgICAgICAgIDogdGhpcy5oYXNoU291cmNlKGNhbm9uaWNhbCwgYXJjaGl2ZSk7XG5cbiAgICAgICAgLy8gRm9yIFNPVVJDRSwgZm9sZGluZyBpbiBidW5kbGVyS2V5IGlzIHRoZSBvbmx5IHdheSBidWlsZCBpZGVudGl0eVxuICAgICAgICAvLyByZWFjaGVzIHRoZSBoYXNoLCBzaW5jZSB0aGUgc291cmNlIHRyZWUgY2Fubm90IHNlZSB0aGUgYnVpbGQuXG4gICAgICAgIGNvbnN0IGJ1bmRsZXJLZXkgPSB0aGlzLmJ1bmRsZXI/LmJ1bmRsZXJLZXk7XG4gICAgICAgIGlmICghZXh0cmFIYXNoICYmICFzYWx0ICYmICFidW5kbGVyS2V5KSB7XG4gICAgICAgICAgcmV0dXJuIGJhc2VIYXNoO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGZvbGRlZCA9IGNyeXB0by5jcmVhdGVIYXNoKFwibWQ1XCIpLnVwZGF0ZShiYXNlSGFzaCk7XG4gICAgICAgIGlmIChleHRyYUhhc2gpIHtcbiAgICAgICAgICBmb2xkZWQudXBkYXRlKGV4dHJhSGFzaCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGJ1bmRsZXJLZXkpIHtcbiAgICAgICAgICBmb2xkZWQudXBkYXRlKGJ1bmRsZXJLZXkpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChzYWx0KSB7XG4gICAgICAgICAgZm9sZGVkLnVwZGF0ZShTdHJpbmcoc2FsdCkpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBmb2xkZWQuZGlnZXN0KFwiaGV4XCIpLnNsaWNlKDAsIDMyKS50b1VwcGVyQ2FzZSgpO1xuICAgICAgfVxuICAgICAgZGVmYXVsdDpcbiAgICAgICAgLy8gT3V0LW9mLXJhbmdlIHZhbHVlIGZyb20gYSBub24tVHlwZVNjcmlwdCBjYWxsZXIuXG4gICAgICAgIHRocm93IGFzc2V0SGFzaFR5cGVVbmtub3duKGlkLCBhc3NldEhhc2hUeXBlKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogSGFzaCB0aGUgc291cmNlIHRyZWUsIGhvbm9yaW5nIHRoZSBpZ25vcmUgc3RyYXRlZ3kuXG4gICAqXG4gICAqIENhY2hlZCBwZXIgc3ludGggc28gYW4gYXNzZXQgcmVmZXJlbmNlZCBtb3JlIHRoYW4gb25jZSBpcyB3YWxrZWQgb25jZS5cbiAgICovXG4gIHByaXZhdGUgaGFzaFNvdXJjZShjYW5vbmljYWw6IGJvb2xlYW4sIGFyY2hpdmU6IGJvb2xlYW4pOiBzdHJpbmcge1xuICAgIC8vIE9ubHkgY2FjaGVhYmxlIHdoZW4gdGhlIGlnbm9yZSBzdHJhdGVneSBjYW4gc3VtbWFyaXplIGl0cyBiZWhhdmlvclxuICAgIC8vIGFzIGEgc3RyaW5nIChzZWUgYElJZ25vcmVTdHJhdGVneS5jYWNoZUtleWApOyBvdGhlcndpc2UgZXZlcnkgY2FsbFxuICAgIC8vIGlzIHRyZWF0ZWQgYXMgdW5pcXVlLlxuICAgIGNvbnN0IGNhY2hlS2V5ID1cbiAgICAgIHRoaXMuaWdub3JlU3RyYXRlZ3kuY2FjaGVLZXkgIT09IHVuZGVmaW5lZFxuICAgICAgICA/IEpTT04uc3RyaW5naWZ5KHtcbiAgICAgICAgICAgIHNvdXJjZVBhdGg6IHRoaXMuc291cmNlUGF0aCxcbiAgICAgICAgICAgIGNhbm9uaWNhbCxcbiAgICAgICAgICAgIGFyY2hpdmUsXG4gICAgICAgICAgICBpZ25vcmU6IHRoaXMuaWdub3JlU3RyYXRlZ3kuY2FjaGVLZXksXG4gICAgICAgICAgfSlcbiAgICAgICAgOiB1bmRlZmluZWQ7XG5cbiAgICBjb25zdCBjYWNoZWQgPSBjYWNoZUtleSA/IHRoaXMuaGFzaENhY2hlLmdldChjYWNoZUtleSkgOiB1bmRlZmluZWQ7XG4gICAgaWYgKGNhY2hlZCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICByZXR1cm4gY2FjaGVkO1xuICAgIH1cblxuICAgIGNvbnN0IGhhc2ggPSBoYXNoUGF0aCh0aGlzLnNvdXJjZVBhdGgsIHtcbiAgICAgIGNhbm9uaWNhbCxcbiAgICAgIGFyY2hpdmUsXG4gICAgICBzaG91bGRFeGNsdWRlOiAocmVsYXRpdmVQYXRoLCBpc0RpcmVjdG9yeSkgPT5cbiAgICAgICAgdGhpcy5pZ25vcmVTdHJhdGVneS5pZ25vcmVzKHsgcmVsYXRpdmVQYXRoLCBpc0RpcmVjdG9yeSB9KSxcbiAgICAgIGRlc2NlbmRJbnRvRXhjbHVkZWREaXJlY3RvcmllczpcbiAgICAgICAgdGhpcy5pZ25vcmVTdHJhdGVneS5wcnVuZUV4Y2x1ZGVkRGlyZWN0b3JpZXMgPT09IGZhbHNlLFxuICAgIH0pO1xuICAgIGlmIChjYWNoZUtleSkge1xuICAgICAgdGhpcy5oYXNoQ2FjaGUuc2V0KGNhY2hlS2V5LCBoYXNoKTtcbiAgICB9XG4gICAgcmV0dXJuIGhhc2g7XG4gIH1cblxuICAvKipcbiAgICogQnVpbGQgdGhlIGJ1bmRsZXIncyBvdXRwdXQgZWFnZXJseSBhbmQgaGFzaCB0aGUgYnVpbHQgYXJ0aWZhY3QuXG4gICAqXG4gICAqIFRoZSBvdXRwdXQgaXMgc3Rhc2hlZCBmb3IgYHN0YWdlKClgIHRvIHJldXNlLCBzbyB0aGUgYnVpbGQgaXMgbm90XG4gICAqIHJlcGVhdGVkLiBJdCBpcyBoYXNoZWQgdmVyYmF0aW06IGBleGNsdWRlYCBmaWx0ZXJzIHRoZSBzb3VyY2UgYSBidW5kbGVyXG4gICAqIHJlYWRzLCBub3QgdGhlIGFydGlmYWN0IGl0IHByb2R1Y2VzLlxuICAgKi9cbiAgcHJpdmF0ZSBoYXNoT3V0cHV0KGNhbm9uaWNhbDogYm9vbGVhbiwgYXJjaGl2ZTogYm9vbGVhbik6IHN0cmluZyB7XG4gICAgY29uc3Qgc2NyYXRjaCA9IGZzLm1rZHRlbXBTeW5jKHBhdGguam9pbihvcy50bXBkaXIoKSwgXCJjZGt0bi1idW5kbGUtXCIpKTtcbiAgICAvLyBSZWdpc3RlcmVkIHNvIHRoZSBleGl0IHN3ZWVwIHJlY2xhaW1zIGl0IGlmIHN0YWdlKCkgbmV2ZXIgcnVucyBmb3IgYW5cbiAgICAvLyB1bnN5bnRoZXNpemVkIHN0YWNrOyBzdGFnZSgpIHJlbW92ZXMgYW5kIHVucmVnaXN0ZXJzIGl0IG90aGVyd2lzZS5cbiAgICByZWdpc3RlclN0cmFuZGVkU2NyYXRjaChzY3JhdGNoKTtcbiAgICB0cnkge1xuICAgICAgY29uc3QgeyBwcm9kdWNlZCwgb3V0cHV0VHlwZSB9ID0gdGhpcy5ydW5CdW5kbGUoc2NyYXRjaCk7XG4gICAgICB0aGlzLmVhZ2VyQnVpbGQgPSB7IHNjcmF0Y2gsIHByb2R1Y2VkLCBvdXRwdXRUeXBlIH07XG4gICAgICAvLyBBIHNpbmdsZS1maWxlIGFydGlmYWN0IGlzIGhhc2hlZCBhcyBhIGZpbGUgKG5vIGFyY2hpdmUgZnJhbWluZyk7IGFcbiAgICAgIC8vIGRpcmVjdG9yeSBpcyBoYXNoZWQgYXMgdGhlIHBhY2thZ2VkIHRyZWUgd291bGQgYmUuXG4gICAgICBjb25zdCBpc0ZpbGUgPSBvdXRwdXRUeXBlID09PSBCdW5kbGVPdXRwdXRUeXBlLkZJTEU7XG4gICAgICByZXR1cm4gaGFzaFBhdGgocHJvZHVjZWQsIHsgY2Fub25pY2FsLCBhcmNoaXZlOiBhcmNoaXZlICYmICFpc0ZpbGUgfSk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgLy8gVGhlIGJ1aWxkIGZhaWxlZCBiZWZvcmUgYGVhZ2VyQnVpbGRgIHdhcyBzZXQsIHNvIHN0YWdlKCkgY2FuIG5ldmVyXG4gICAgICAvLyByZWFjaCB0aGlzIHNjcmF0Y2ggdG8gY2xlYW4gaXQuIFJlY2xhaW0gaXQgbm93IHJhdGhlciB0aGFuIGxlYXZpbmcgYVxuICAgICAgLy8gcG90ZW50aWFsbHkgbGFyZ2UgdHJlZSAobm9kZV9tb2R1bGVzLCBidWlsZCBjYWNoZXMpIHRvIHRoZSBleGl0IHN3ZWVwLlxuICAgICAgdGhpcy5jbGVhbnVwU2NyYXRjaChzY3JhdGNoKTtcbiAgICAgIHRocm93IGU7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJ1biB0aGUgYnVuZGxlciBhZ2FpbnN0IHRoZSBmaWx0ZXJlZCBzb3VyY2UgYW5kIHJldHVybiBpdHMgb3V0cHV0LlxuICAgKlxuICAgKiBUaGUgYnVuZGxlciBpcyBoYW5kZWQgYW4gYWJzb2x1dGUgYHNvdXJjZWAgKGl0cyBjd2QgaXMgaXRzIG93biwgc28gYVxuICAgKiByZWxhdGl2ZSBwYXRoIHdvdWxkIHJlc29sdmUgZWxzZXdoZXJlKSB0aGF0IGhhcyBhbHJlYWR5IGhhZCBgZXhjbHVkZWBcbiAgICogYXBwbGllZC4gTWF0ZXJpYWxpc2luZyB0aGUgZmlsdGVyZWQgaW5wdXQgaGVyZSBpcyB3aGF0IG1ha2VzIHRoZSBidW5kbGVyXG4gICAqIHJlYWQgZXhhY3RseSB0aGUgdHJlZSB0aGUgaGFzaCB3YXMgdGFrZW4gb3Zlciwgd2hpY2ggYSByYXcgc291cmNlXG4gICAqIGhhbmQtb2ZmIHdvdWxkIG5vdCwgc2luY2UgYGhhc2hTb3VyY2VgIGhvbm91cnMgYGV4Y2x1ZGVgLlxuICAgKi9cbiAgcHJpdmF0ZSBydW5CdW5kbGUoc2NyYXRjaDogc3RyaW5nKToge1xuICAgIHByb2R1Y2VkOiBzdHJpbmc7XG4gICAgb3V0cHV0VHlwZTogQnVuZGxlT3V0cHV0VHlwZTtcbiAgfSB7XG4gICAgY29uc3Qgb3V0cHV0RGlyID0gcGF0aC5qb2luKHNjcmF0Y2gsIFwib3V0cHV0XCIpO1xuICAgIGZzLm1rZGlyU3luYyhvdXRwdXREaXIpO1xuICAgIGNvbnN0IHJlc3VsdCA9IHRoaXMuYnVuZGxlciEuYnVuZGxlKHtcbiAgICAgIHNvdXJjZTogdGhpcy5maWx0ZXJlZFNvdXJjZShzY3JhdGNoKSxcbiAgICAgIG91dHB1dERpcixcbiAgICB9KTtcblxuICAgIC8vIEEgYmFyZSBidW5kbGVyIHRoYXQgZGVjbGluZXMgaGFzIG5vdGhpbmcgdG8gZmFsbCBiYWNrIHRvIOKAlCBkZWNsaW5pbmcgaXNcbiAgICAvLyBvbmx5IG1lYW5pbmdmdWwgaW5zaWRlIGEgQ2hhaW5CdW5kbGVyLCB3aGljaCBjb25zdW1lcyBpdCBiZWZvcmUgaXRcbiAgICAvLyByZWFjaGVzIGhlcmUuIEEgbm9uLWRlY2xpbmVkIHJlc3VsdCBhbHdheXMgY2FycmllcyBhIHBhdGggYW5kIHNoYXBlLlxuICAgIGlmIChcbiAgICAgIHJlc3VsdC5pc0RlY2xpbmVkIHx8XG4gICAgICByZXN1bHQucGF0aCA9PT0gdW5kZWZpbmVkIHx8XG4gICAgICByZXN1bHQub3V0cHV0VHlwZSA9PT0gdW5kZWZpbmVkXG4gICAgKSB7XG4gICAgICB0aHJvdyBhc3NldFN0YWdpbmdCdW5kbGVyT3V0cHV0Tm90RGlyZWN0b3J5KFxuICAgICAgICB0aGlzLmRpc3BsYXlOYW1lLFxuICAgICAgICBTdHJpbmcocmVzdWx0LnBhdGgpLFxuICAgICAgKTtcbiAgICB9XG5cbiAgICBjb25zdCBwcm9kdWNlZCA9IHJlc3VsdC5wYXRoO1xuICAgIHRoaXMudmFsaWRhdGVPdXRwdXRTaGFwZShwcm9kdWNlZCwgcmVzdWx0Lm91dHB1dFR5cGUpO1xuICAgIHJldHVybiB7IHByb2R1Y2VkLCBvdXRwdXRUeXBlOiByZXN1bHQub3V0cHV0VHlwZSB9O1xuICB9XG5cbiAgLyoqXG4gICAqIFJlamVjdCBhIGJ1bmRsZXIgcmVzdWx0IHdob3NlIGRlY2xhcmVkIHNoYXBlIGRvZXMgbm90IG1hdGNoIHdoYXQgaXMgb25cbiAgICogZGlzaywgb3IgZG9lcyBub3QgbWF0Y2ggdGhlIHBhY2thZ2luZy5cbiAgICpcbiAgICogQ2F0Y2hpbmcgdGhlIG1pc21hdGNoIGhlcmUgdHVybnMgYW4gb3BhcXVlIEVJU0RJUi9FUEVSTSBhdCBwYWNrIHRpbWUgaW50b1xuICAgKiBhIGNsZWFyIGVycm9yIG5hbWluZyB0aGUgcGFja2FnaW5nIHRoZSBidW5kbGVyJ3Mgb3V0cHV0IHNoYXBlIG5lZWRzLlxuICAgKi9cbiAgcHJpdmF0ZSB2YWxpZGF0ZU91dHB1dFNoYXBlKFxuICAgIHByb2R1Y2VkOiBzdHJpbmcsXG4gICAgb3V0cHV0VHlwZTogQnVuZGxlT3V0cHV0VHlwZSxcbiAgKTogdm9pZCB7XG4gICAgY29uc3QgZXhpc3RzID0gZnMuZXhpc3RzU3luYyhwcm9kdWNlZCk7XG4gICAgY29uc3Qgc3RhdCA9IGV4aXN0cyA/IGZzLnN0YXRTeW5jKHByb2R1Y2VkKSA6IHVuZGVmaW5lZDtcblxuICAgIGlmIChvdXRwdXRUeXBlID09PSBCdW5kbGVPdXRwdXRUeXBlLkZJTEUpIHtcbiAgICAgIGlmICghc3RhdD8uaXNGaWxlKCkpIHtcbiAgICAgICAgdGhyb3cgYXNzZXRTdGFnaW5nQnVuZGxlck91dHB1dE5vdEZpbGUodGhpcy5kaXNwbGF5TmFtZSwgcHJvZHVjZWQpO1xuICAgICAgfVxuICAgICAgaWYgKCF0aGlzLnN0YWdlc1NpbmdsZUZpbGUpIHtcbiAgICAgICAgdGhyb3cgYXNzZXRTdGFnaW5nQnVuZGxlckZpbGVPdXRwdXROZWVkc0ZpbGVQYWNrYWdpbmcodGhpcy5kaXNwbGF5TmFtZSk7XG4gICAgICB9XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKCFzdGF0Py5pc0RpcmVjdG9yeSgpKSB7XG4gICAgICB0aHJvdyBhc3NldFN0YWdpbmdCdW5kbGVyT3V0cHV0Tm90RGlyZWN0b3J5KHRoaXMuZGlzcGxheU5hbWUsIHByb2R1Y2VkKTtcbiAgICB9XG4gICAgaWYgKCF0aGlzLnBhY2thZ2luZy5hY2NlcHRzRGlyZWN0b3J5U291cmNlKSB7XG4gICAgICB0aHJvdyBhc3NldFN0YWdpbmdCdW5kbGVyRGlyZWN0b3J5T3V0cHV0TmVlZHNEaXJlY3RvcnlQYWNrYWdpbmcoXG4gICAgICAgIHRoaXMuZGlzcGxheU5hbWUsXG4gICAgICApO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBXaGV0aGVyIHRoZSBwYWNrYWdpbmcgc3RhZ2VzIGEgc2luZ2xlIGZpbGUgdmVyYmF0aW0gKEFzc2V0VHlwZS5GSUxFKS5cbiAgICpcbiAgICogQSB2ZXJiYXRpbS1maWxlIHBhY2thZ2luZyBuZWl0aGVyIHByb2R1Y2VzIGEgZGlyZWN0b3J5IG5vciByZWFkcyBvbmUgYXNcbiAgICogaXRzIHNvdXJjZS4gRGVyaXZlZCBmcm9tIGV4aXN0aW5nIGBJQXNzZXRQYWNrYWdpbmdgIGZsYWdzIHNvIG91dC1vZi10cmVlXG4gICAqIHBhY2thZ2luZ3MgbmVlZCBubyBuZXcgaW50ZXJmYWNlIG1lbWJlci5cbiAgICovXG4gIHByaXZhdGUgZ2V0IHN0YWdlc1NpbmdsZUZpbGUoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIChcbiAgICAgICF0aGlzLnBhY2thZ2luZy5wcm9kdWNlc0RpcmVjdG9yeSAmJlxuICAgICAgIXRoaXMucGFja2FnaW5nLmFjY2VwdHNEaXJlY3RvcnlTb3VyY2VcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIEFic29sdXRlIHBhdGggdG8gdGhlIHNvdXJjZSB0aGUgYnVuZGxlciBzaG91bGQgcmVhZC5cbiAgICpcbiAgICogV2l0aCBubyBleGNsdXNpb25zLCBvciB3aXRoIGEgZmlsZSBzb3VyY2UsIHRoZSByZXNvbHZlZCBzb3VyY2UgaXMgaGFuZGVkXG4gICAqIG92ZXIgZGlyZWN0bHkg4oCUIGEgZmlsZSBoYXMgbm8gY2hpbGRyZW4gdG8gZmlsdGVyLCBtYXRjaGluZyBgaGFzaFNvdXJjZWAsXG4gICAqIHdoaWNoIG9ubHkgZXZlciBhcHBsaWVzIHRoZSBpZ25vcmUgc3RyYXRlZ3kgdG8gYSBkaXJlY3RvcnkncyBlbnRyaWVzIGFuZFxuICAgKiBuZXZlciB0byB0aGUgcm9vdCBpdHNlbGYuIE90aGVyd2lzZSB0aGUgZXhjbHVkZWQgc291cmNlIHRyZWUgaXNcbiAgICogbWF0ZXJpYWxpc2VkIGludG8gdGhlIHNjcmF0Y2ggZGlyZWN0b3J5LCBzbyB0aGUgYnVuZGxlciBzZWVzIHRoZSBzYW1lXG4gICAqIGZpbGUgc2V0IHRoZSBoYXNoIHdhcyB0YWtlbiBvdmVyLlxuICAgKi9cbiAgcHJpdmF0ZSBmaWx0ZXJlZFNvdXJjZShzY3JhdGNoOiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIGNvbnN0IGFic29sdXRlU291cmNlID0gcGF0aC5yZXNvbHZlKHRoaXMuc291cmNlUGF0aCk7XG4gICAgaWYgKCF0aGlzLmhhc0V4Y2x1c2lvbnMgfHwgZnMuc3RhdFN5bmMoYWJzb2x1dGVTb3VyY2UpLmlzRmlsZSgpKSB7XG4gICAgICByZXR1cm4gYWJzb2x1dGVTb3VyY2U7XG4gICAgfVxuICAgIGNvbnN0IGlucHV0ID0gcGF0aC5qb2luKHNjcmF0Y2gsIFwiaW5wdXRcIik7XG4gICAgZnMubWtkaXJTeW5jKGlucHV0KTtcbiAgICBjb3B5U3luYyhhYnNvbHV0ZVNvdXJjZSwgaW5wdXQsIHtcbiAgICAgIHNob3VsZEV4Y2x1ZGU6IChyZWxhdGl2ZVBhdGgsIGlzRGlyZWN0b3J5KSA9PlxuICAgICAgICB0aGlzLmlnbm9yZVN0cmF0ZWd5Lmlnbm9yZXMoeyByZWxhdGl2ZVBhdGgsIGlzRGlyZWN0b3J5IH0pLFxuICAgICAgZGVzY2VuZEludG9FeGNsdWRlZERpcmVjdG9yaWVzOlxuICAgICAgICB0aGlzLmlnbm9yZVN0cmF0ZWd5LnBydW5lRXhjbHVkZWREaXJlY3RvcmllcyA9PT0gZmFsc2UsXG4gICAgfSk7XG4gICAgcmV0dXJuIGlucHV0O1xuICB9XG5cbiAgLyoqXG4gICAqIFN0YWdlIHRoZSBhc3NldCdzIGNvbnRlbnQgdG8gYHRhcmdldFBhdGhgLlxuICAgKlxuICAgKiBDYWxsZWQgZnJvbSB0aGUgb3duaW5nIGNvbnN0cnVjdCdzIGBvblN5bnRoZXNpemVgIGhvb2suIFdpdGhvdXQgYSBidW5kbGVyXG4gICAqIHRoZSBzb3VyY2UgaXMgcGFja2FnZWQgdmVyYmF0aW07IHdpdGggb25lLCB0aGUgYnVuZGxlcidzIG91dHB1dCBpcywgYnVpbHRcbiAgICogZWFnZXJseSBmb3IgYE9VVFBVVGAgaGFzaGluZyBvciBkZWZlcnJlZCB0byBoZXJlIGZvciBgU09VUkNFYC5cbiAgICovXG4gIHB1YmxpYyBzdGFnZSh0YXJnZXRQYXRoOiBzdHJpbmcpOiB2b2lkIHtcbiAgICAvLyBTdGFnZSBleGFjdGx5IG9uY2U6IGEgcmVidWlsZCBjb3VsZCBzdGFnZSBieXRlcyBub3QgbWF0Y2hpbmcgdGhlXG4gICAgLy8gYWxyZWFkeS1jb21wdXRlZCBoYXNoIChzZWUgdGhlIGBzdGFnZWRgIGZpZWxkKS5cbiAgICBpZiAodGhpcy5zdGFnZWQpIHtcbiAgICAgIHRocm93IGFzc2V0U3RhZ2luZ0FscmVhZHlTdGFnZWQodGhpcy5kaXNwbGF5TmFtZSk7XG4gICAgfVxuICAgIHRoaXMuc3RhZ2VkID0gdHJ1ZTtcblxuICAgIGlmICghdGhpcy5idW5kbGVyKSB7XG4gICAgICB0aGlzLnBhY2thZ2luZy5wYWNrKHtcbiAgICAgICAgc291cmNlOiB0aGlzLnNvdXJjZVBhdGgsXG4gICAgICAgIHRhcmdldDogdGFyZ2V0UGF0aCxcbiAgICAgICAgaWdub3JlU3RyYXRlZ3k6IHRoaXMuaWdub3JlU3RyYXRlZ3ksXG4gICAgICB9KTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyBgT1VUUFVUYCBoYXNoaW5nIGFscmVhZHkgYnVpbHQgdGhlIGFydGlmYWN0IGluIHRoZSBjb25zdHJ1Y3RvcjsgcGFja2FnZVxuICAgIC8vIHRoYXQgZXhhY3QgcmVzdWx0IGFuZCBjbGVhbiB1cCBpdHMgc2NyYXRjaCwgcmF0aGVyIHRoYW4gYnVpbGRpbmcgdHdpY2UuXG4gICAgaWYgKHRoaXMuZWFnZXJCdWlsZCkge1xuICAgICAgY29uc3QgeyBzY3JhdGNoLCBwcm9kdWNlZCB9ID0gdGhpcy5lYWdlckJ1aWxkO1xuICAgICAgdGhpcy5lYWdlckJ1aWxkID0gdW5kZWZpbmVkO1xuICAgICAgdHJ5IHtcbiAgICAgICAgdGhpcy5wYWNrQnVuZGxlck91dHB1dChwcm9kdWNlZCwgdGFyZ2V0UGF0aCk7XG4gICAgICB9IGZpbmFsbHkge1xuICAgICAgICB0aGlzLmNsZWFudXBTY3JhdGNoKHNjcmF0Y2gpO1xuICAgICAgfVxuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIGBTT1VSQ0VgIGhhc2hpbmcgZGVmZXJzIHRoZSBidWlsZCB0byBoZXJlLlxuICAgIGNvbnN0IHNjcmF0Y2ggPSBmcy5ta2R0ZW1wU3luYyhwYXRoLmpvaW4ob3MudG1wZGlyKCksIFwiY2RrdG4tYnVuZGxlLVwiKSk7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHsgcHJvZHVjZWQgfSA9IHRoaXMucnVuQnVuZGxlKHNjcmF0Y2gpO1xuICAgICAgdGhpcy5wYWNrQnVuZGxlck91dHB1dChwcm9kdWNlZCwgdGFyZ2V0UGF0aCk7XG4gICAgfSBmaW5hbGx5IHtcbiAgICAgIHRoaXMuY2xlYW51cFNjcmF0Y2goc2NyYXRjaCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJlbW92ZSBhIGJ1bmRsZXIgc2NyYXRjaCBkaXJlY3RvcnkgYW5kIGRyb3AgaXQgZnJvbSB0aGUgZXhpdC1zd2VlcCBzZXQuXG4gICAqL1xuICBwcml2YXRlIGNsZWFudXBTY3JhdGNoKHNjcmF0Y2g6IHN0cmluZyk6IHZvaWQge1xuICAgIGZzLnJtU3luYyhzY3JhdGNoLCB7IHJlY3Vyc2l2ZTogdHJ1ZSwgZm9yY2U6IHRydWUgfSk7XG4gICAgc3RyYW5kZWRTY3JhdGNoRGlycy5kZWxldGUoc2NyYXRjaCk7XG4gIH1cblxuICAvKipcbiAgICogUGFja2FnZSBhIGJ1bmRsZXIncyBvdXRwdXQgaW50byBgdGFyZ2V0UGF0aGAsIHZlcmJhdGltLlxuICAgKlxuICAgKiBUaGUgb3V0cHV0J3Mgc2hhcGUgd2FzIGFscmVhZHkgdmFsaWRhdGVkIGFnYWluc3QgdGhlIHBhY2thZ2luZyBpblxuICAgKiB7QGxpbmsgcnVuQnVuZGxlfSwgc28gdGhlIHBhY2thZ2luZyBoYW5kbGVzIHRoZSBzb3VyY2UgZGlyZWN0bHkg4oCUIGEgZmlsZVxuICAgKiBzb3VyY2UgZm9yIEFzc2V0VHlwZS5GSUxFLCBhIGRpcmVjdG9yeSBzb3VyY2Ugb3RoZXJ3aXNlLlxuICAgKlxuICAgKiBUaGUgaWdub3JlIHN0cmF0ZWd5IGlzIGRlbGliZXJhdGVseSBub3QgYXBwbGllZC4gYGV4Y2x1ZGVgIGZpbHRlcnMgdGhlXG4gICAqIHNvdXJjZSBhIGJ1bmRsZXIgcmVhZHMsIG5vdCBpdHMgcHJvZHVjdDogYW4gaW5zdGFsbC1zdHlsZSBidW5kbGVyXG4gICAqIChgbnBtIGluc3RhbGwgLS1wcm9kdWN0aW9uYCwgYHBpcCBpbnN0YWxsIC10YCkgd3JpdGVzIGV4YWN0bHkgdGhlXG4gICAqIGRlcGVuZGVuY3kgZGlyZWN0b3J5IGEgdXNlciBleGNsdWRlcyBmcm9tIHNvdXJjZSwgYW5kIHJlLWFwcGx5aW5nIHRoZVxuICAgKiBleGNsdXNpb24gd291bGQgc2hpcCBhbiBhcnRpZmFjdCBtaXNzaW5nIHRob3NlIGRlcGVuZGVuY2llcy5cbiAgICovXG4gIHByaXZhdGUgcGFja0J1bmRsZXJPdXRwdXQocHJvZHVjZWQ6IHN0cmluZywgdGFyZ2V0UGF0aDogc3RyaW5nKTogdm9pZCB7XG4gICAgdGhpcy5wYWNrYWdpbmcucGFjayh7XG4gICAgICBzb3VyY2U6IHByb2R1Y2VkLFxuICAgICAgdGFyZ2V0OiB0YXJnZXRQYXRoLFxuICAgIH0pO1xuICB9XG59XG4iXX0=
|