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.
Files changed (94) hide show
  1. package/.jsii +2194 -424
  2. package/README.md +12 -0
  3. package/lib/annotations.js +4 -4
  4. package/lib/app.js +54 -5
  5. package/lib/aspect.js +3 -4
  6. package/lib/asset-hash.d.ts +75 -0
  7. package/lib/asset-hash.js +129 -0
  8. package/lib/asset-staging.d.ts +180 -0
  9. package/lib/asset-staging.js +464 -0
  10. package/lib/assets.d.ts +401 -0
  11. package/lib/assets.js +333 -0
  12. package/lib/backends/azurerm-backend.js +4 -6
  13. package/lib/backends/cloud-backend.js +15 -12
  14. package/lib/backends/consul-backend.js +4 -6
  15. package/lib/backends/cos-backend.js +4 -6
  16. package/lib/backends/gcs-backend.js +4 -6
  17. package/lib/backends/http-backend.js +4 -6
  18. package/lib/backends/local-backend.js +38 -7
  19. package/lib/backends/oss-backend.js +4 -6
  20. package/lib/backends/pg-backend.js +4 -6
  21. package/lib/backends/remote-backend.js +8 -10
  22. package/lib/backends/s3-backend.js +4 -6
  23. package/lib/backends/swift-backend.js +4 -6
  24. package/lib/complex-computed-list.js +114 -65
  25. package/lib/errors.d.ts +16 -0
  26. package/lib/errors.js +51 -3
  27. package/lib/functions/provider-function.js +2 -4
  28. package/lib/functions/terraform-functions.generated.js +2 -4
  29. package/lib/ignore-strategy.d.ts +82 -0
  30. package/lib/ignore-strategy.js +29 -0
  31. package/lib/importable-resource.js +8 -6
  32. package/lib/index.d.ts +4 -0
  33. package/lib/index.js +28 -2
  34. package/lib/manifest.js +49 -11
  35. package/lib/private/fs.d.ts +74 -2
  36. package/lib/private/fs.js +129 -17
  37. package/lib/private/unique.js +35 -2
  38. package/lib/resource.js +3 -4
  39. package/lib/synthesize/synthesizer.js +51 -25
  40. package/lib/terraform-asset.d.ts +68 -5
  41. package/lib/terraform-asset.js +127 -40
  42. package/lib/terraform-backend.js +3 -4
  43. package/lib/terraform-count.js +3 -4
  44. package/lib/terraform-data-resource.d.ts +1 -1
  45. package/lib/terraform-data-resource.js +18 -13
  46. package/lib/terraform-data-source.js +10 -4
  47. package/lib/terraform-dynamic-block.js +5 -2
  48. package/lib/terraform-dynamic-expression.js +4 -1
  49. package/lib/terraform-element.js +34 -6
  50. package/lib/terraform-ephemeral-resource.js +10 -4
  51. package/lib/terraform-functions.js +2 -4
  52. package/lib/terraform-hcl-module.js +3 -4
  53. package/lib/terraform-iterator.js +11 -12
  54. package/lib/terraform-local.js +3 -4
  55. package/lib/terraform-module-asset.js +39 -4
  56. package/lib/terraform-module.js +8 -4
  57. package/lib/terraform-operators.js +2 -4
  58. package/lib/terraform-output.js +7 -4
  59. package/lib/terraform-provider.js +5 -4
  60. package/lib/terraform-provisioner.js +2 -4
  61. package/lib/terraform-remote-state.js +5 -5
  62. package/lib/terraform-resource-targets.js +3 -7
  63. package/lib/terraform-resource.js +23 -7
  64. package/lib/terraform-stack.js +38 -38
  65. package/lib/terraform-variable.js +25 -22
  66. package/lib/testing/adapters/jest.d.ts +2 -1
  67. package/lib/testing/adapters/jest.js +3 -3
  68. package/lib/testing/index.js +42 -8
  69. package/lib/testing/matchers.d.ts +34 -30
  70. package/lib/testing/matchers.js +329 -93
  71. package/lib/tfExpression.js +25 -8
  72. package/lib/tokens/lazy.js +11 -7
  73. package/lib/tokens/private/dependency.js +2 -2
  74. package/lib/tokens/private/encoding.js +6 -1
  75. package/lib/tokens/private/intrinsic.js +6 -1
  76. package/lib/tokens/private/resolve.js +2 -5
  77. package/lib/tokens/private/token-map.js +4 -6
  78. package/lib/tokens/private/uniqueid.js +35 -2
  79. package/lib/tokens/resolvable.js +4 -6
  80. package/lib/tokens/string-fragments.js +6 -10
  81. package/lib/tokens/token.js +15 -18
  82. package/lib/upgrade-id-aspect.js +37 -6
  83. package/lib/validations/index.d.ts +0 -1
  84. package/lib/validations/index.js +1 -2
  85. package/lib/validations/target-versions.js +39 -2
  86. package/lib/validations/validate-function-version-support.js +2 -1
  87. package/lib/validations/validate-provider-function-target-support.js +2 -1
  88. package/lib/validations/validate-provider-presence.js +10 -9
  89. package/package.json +21 -7
  90. package/scripts/pack.mjs +27 -12
  91. package/lib/validations/validate-binary-version.d.ts +0 -23
  92. package/lib/validations/validate-binary-version.js +0 -54
  93. package/lib/validations/validate-terraform-version.d.ts +0 -13
  94. 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=