cdk-nextjs 0.6.2 → 0.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (263) hide show
  1. package/.jsii +2404 -2723
  2. package/.jsii.tabl.json +1 -1
  3. package/API.md +1681 -1930
  4. package/CLAUDE.md +2 -1
  5. package/README.md +429 -130
  6. package/assets/lambdas/post-deploy/post-deploy.lambda/index.js +148 -169
  7. package/assets/lambdas/redeploy-stage/redeploy-stage.lambda/index.js +875 -0
  8. package/docs/adapter-runtime.md +185 -0
  9. package/docs/breaking-changes.md +667 -4
  10. package/docs/caching-guide.md +156 -112
  11. package/docs/cdk-nextjs-cfn-exec-policy.json +2 -1
  12. package/docs/development-guide.md +1 -1
  13. package/docs/harness-coverage.md +598 -0
  14. package/docs/init-cache-deployment.md +32 -1
  15. package/docs/next-build-output-guide.md +30 -20
  16. package/examples/README.md +5 -1
  17. package/lib/adapter/__fixtures__/app-playground-base-path.json +4926 -0
  18. package/lib/adapter/__fixtures__/app-playground.json +4917 -0
  19. package/lib/adapter/__fixtures__/pages-i18n.json +1728 -0
  20. package/lib/adapter/adapter.mjs +1551 -185
  21. package/lib/adapter/adapter.test.js +106 -0
  22. package/lib/adapter/aws-cache-store.d.ts +489 -0
  23. package/lib/adapter/aws-cache-store.js +1004 -0
  24. package/lib/adapter/aws-cache-store.test.d.ts +1 -0
  25. package/lib/adapter/aws-cache-store.test.js +361 -0
  26. package/lib/adapter/build-outputs.d.ts +80 -0
  27. package/lib/adapter/build-outputs.js +857 -0
  28. package/lib/adapter/build-outputs.test.d.ts +1 -0
  29. package/lib/adapter/build-outputs.test.js +863 -0
  30. package/lib/adapter/cache-handler.d.ts +9 -2
  31. package/lib/adapter/cache-handler.js +72 -96
  32. package/lib/adapter/cache-handler.mjs +18956 -17774
  33. package/lib/adapter/cache-handler.test.js +263 -31
  34. package/lib/adapter/cache-kinds.d.ts +32 -0
  35. package/lib/adapter/cache-kinds.js +35 -0
  36. package/lib/adapter/cache-kinds.test.d.ts +1 -0
  37. package/lib/adapter/cache-kinds.test.js +69 -0
  38. package/lib/adapter/cache-utils.d.ts +90 -0
  39. package/lib/adapter/cache-utils.js +199 -4
  40. package/lib/adapter/cache-utils.test.d.ts +1 -0
  41. package/lib/adapter/cache-utils.test.js +179 -0
  42. package/lib/adapter/function-groups.d.ts +215 -0
  43. package/lib/adapter/function-groups.js +1099 -0
  44. package/lib/adapter/function-groups.test.d.ts +1 -0
  45. package/lib/adapter/function-groups.test.js +743 -0
  46. package/lib/adapter/init-cache.d.ts +6 -0
  47. package/lib/adapter/init-cache.js +245 -0
  48. package/lib/adapter/init-cache.test.d.ts +1 -0
  49. package/lib/adapter/init-cache.test.js +137 -0
  50. package/lib/adapter/local-file-cache-handler.d.ts +23 -0
  51. package/lib/adapter/local-file-cache-handler.js +52 -1
  52. package/lib/adapter/memory-cache-handler.d.ts +26 -17
  53. package/lib/adapter/memory-cache-handler.js +32 -50
  54. package/lib/adapter/memory-cache-handler.test.js +105 -85
  55. package/lib/adapter/s3-cache-handler.d.ts +179 -40
  56. package/lib/adapter/s3-cache-handler.js +807 -277
  57. package/lib/adapter/s3-cache-handler.test.js +1186 -31
  58. package/lib/adapter/use-cache-common.d.ts +90 -0
  59. package/lib/adapter/use-cache-common.js +250 -0
  60. package/lib/adapter/use-cache-common.test.d.ts +1 -0
  61. package/lib/adapter/use-cache-common.test.js +646 -0
  62. package/lib/adapter/use-cache-default-handler.d.ts +24 -0
  63. package/lib/adapter/use-cache-default-handler.js +90 -0
  64. package/lib/adapter/use-cache-default-handler.mjs +38645 -0
  65. package/lib/adapter/use-cache-handlers.test.d.ts +1 -0
  66. package/lib/adapter/use-cache-handlers.test.js +349 -0
  67. package/lib/adapter/use-cache-remote-handler.d.ts +26 -0
  68. package/lib/adapter/use-cache-remote-handler.js +186 -0
  69. package/lib/{image-optimization/handler.mjs → adapter/use-cache-remote-handler.mjs} +33572 -38798
  70. package/lib/generated-structs/OptionalNextjsApiProps.d.ts +59 -0
  71. package/lib/generated-structs/OptionalNextjsApiProps.js +3 -0
  72. package/lib/generated-structs/OptionalNextjsCacheProps.d.ts +15 -6
  73. package/lib/generated-structs/OptionalNextjsCacheProps.js +1 -1
  74. package/lib/generated-structs/OptionalNextjsContainersProps.d.ts +25 -11
  75. package/lib/generated-structs/OptionalNextjsContainersProps.js +1 -1
  76. package/lib/generated-structs/OptionalNextjsDistributionProps.d.ts +31 -9
  77. package/lib/generated-structs/OptionalNextjsDistributionProps.js +1 -1
  78. package/lib/generated-structs/OptionalNextjsPostDeployProps.d.ts +8 -0
  79. package/lib/generated-structs/OptionalNextjsPostDeployProps.js +1 -1
  80. package/lib/generated-structs/OptionalPostDeployCustomResourceProperties.d.ts +6 -4
  81. package/lib/generated-structs/OptionalPostDeployCustomResourceProperties.js +1 -1
  82. package/lib/index.d.ts +6 -7
  83. package/lib/index.js +2 -4
  84. package/lib/lambdas/post-deploy/prune-cache-bucket.d.ts +7 -3
  85. package/lib/lambdas/post-deploy/prune-cache-bucket.js +57 -71
  86. package/lib/lambdas/post-deploy/prune-cache-bucket.test.d.ts +1 -0
  87. package/lib/lambdas/post-deploy/prune-cache-bucket.test.js +114 -0
  88. package/lib/lambdas/post-deploy/prune-revalidation-table.d.ts +1 -0
  89. package/lib/lambdas/post-deploy/prune-revalidation-table.js +23 -31
  90. package/lib/lambdas/post-deploy/prune-revalidation-table.test.d.ts +1 -0
  91. package/lib/lambdas/post-deploy/prune-revalidation-table.test.js +71 -0
  92. package/lib/lambdas/post-deploy/prune-s3.d.ts +14 -5
  93. package/lib/lambdas/post-deploy/prune-s3.js +41 -12
  94. package/lib/lambdas/post-deploy/prune-s3.test.js +97 -18
  95. package/lib/lambdas/redeploy-stage/redeploy-stage-function.d.ts +13 -0
  96. package/lib/lambdas/redeploy-stage/redeploy-stage-function.js +55 -0
  97. package/lib/lambdas/redeploy-stage/redeploy-stage.d.ts +24 -0
  98. package/lib/lambdas/redeploy-stage/redeploy-stage.js +68 -0
  99. package/lib/lambdas/redeploy-stage/redeploy-stage.lambda.d.ts +20 -0
  100. package/lib/lambdas/redeploy-stage/redeploy-stage.lambda.js +24 -0
  101. package/lib/lambdas/redeploy-stage/redeploy-stage.test.d.ts +1 -0
  102. package/lib/lambdas/redeploy-stage/redeploy-stage.test.js +93 -0
  103. package/lib/nextjs-api.d.ts +102 -18
  104. package/lib/nextjs-api.js +338 -38
  105. package/lib/nextjs-api.test.js +537 -1
  106. package/lib/nextjs-build/global-containers.Dockerfile +15 -10
  107. package/lib/nextjs-build/nextjs-build.d.ts +339 -63
  108. package/lib/nextjs-build/nextjs-build.js +684 -327
  109. package/lib/nextjs-build/nextjs-build.test.d.ts +1 -0
  110. package/lib/nextjs-build/nextjs-build.test.js +412 -0
  111. package/lib/nextjs-build/patch-fetch.js +1 -1
  112. package/lib/nextjs-build/patch-fetch.test.js +166 -11
  113. package/lib/nextjs-build/regional-containers.Dockerfile +17 -10
  114. package/lib/nextjs-cache.d.ts +82 -4
  115. package/lib/nextjs-cache.js +186 -10
  116. package/lib/nextjs-cache.test.js +176 -1
  117. package/lib/nextjs-compute/nextjs-compute-base-props.d.ts +21 -8
  118. package/lib/nextjs-compute/nextjs-compute-base-props.js +41 -1
  119. package/lib/nextjs-compute/nextjs-compute-base-props.test.d.ts +1 -0
  120. package/lib/nextjs-compute/nextjs-compute-base-props.test.js +44 -0
  121. package/lib/nextjs-compute/nextjs-containers.d.ts +19 -0
  122. package/lib/nextjs-compute/nextjs-containers.js +57 -20
  123. package/lib/nextjs-compute/nextjs-functions.d.ts +122 -7
  124. package/lib/nextjs-compute/nextjs-functions.js +113 -67
  125. package/lib/nextjs-compute/nextjs-functions.test.d.ts +1 -0
  126. package/lib/nextjs-compute/nextjs-functions.test.js +99 -0
  127. package/lib/nextjs-distribution.d.ts +194 -23
  128. package/lib/nextjs-distribution.js +535 -62
  129. package/lib/nextjs-distribution.test.d.ts +1 -0
  130. package/lib/nextjs-distribution.test.js +697 -0
  131. package/lib/nextjs-post-deploy.d.ts +13 -5
  132. package/lib/nextjs-post-deploy.js +13 -10
  133. package/lib/nextjs-post-deploy.test.d.ts +1 -0
  134. package/lib/nextjs-post-deploy.test.js +34 -0
  135. package/lib/nextjs-static-assets.d.ts +17 -4
  136. package/lib/nextjs-static-assets.js +22 -5
  137. package/lib/root-constructs/nextjs-base-construct.d.ts +102 -58
  138. package/lib/root-constructs/nextjs-base-construct.js +139 -47
  139. package/lib/root-constructs/nextjs-global-containers.d.ts +18 -20
  140. package/lib/root-constructs/nextjs-global-containers.js +20 -71
  141. package/lib/root-constructs/nextjs-global-functions.d.ts +26 -28
  142. package/lib/root-constructs/nextjs-global-functions.js +52 -70
  143. package/lib/root-constructs/nextjs-regional-containers.d.ts +18 -5
  144. package/lib/root-constructs/nextjs-regional-containers.js +8 -15
  145. package/lib/root-constructs/nextjs-regional-functions.d.ts +22 -18
  146. package/lib/root-constructs/nextjs-regional-functions.js +8 -26
  147. package/lib/runtime/api-gateway-path.d.ts +34 -0
  148. package/lib/runtime/api-gateway-path.js +71 -0
  149. package/lib/runtime/api-gateway-path.test.d.ts +1 -0
  150. package/lib/runtime/api-gateway-path.test.js +65 -0
  151. package/lib/runtime/case-redirect.d.ts +22 -0
  152. package/lib/runtime/case-redirect.js +63 -0
  153. package/lib/runtime/case-redirect.test.d.ts +1 -0
  154. package/lib/runtime/case-redirect.test.js +32 -0
  155. package/lib/runtime/core.d.ts +234 -0
  156. package/lib/runtime/core.js +1216 -0
  157. package/lib/runtime/core.test.d.ts +1 -0
  158. package/lib/runtime/core.test.js +1686 -0
  159. package/lib/runtime/deployment-root.d.ts +13 -0
  160. package/lib/runtime/deployment-root.js +29 -0
  161. package/lib/runtime/dispatch.d.ts +331 -0
  162. package/lib/runtime/dispatch.js +751 -0
  163. package/lib/runtime/dispatch.test.d.ts +1 -0
  164. package/lib/runtime/dispatch.test.js +853 -0
  165. package/lib/runtime/entrypoints.d.ts +57 -0
  166. package/lib/runtime/entrypoints.js +115 -0
  167. package/lib/runtime/http/abort-signal.d.ts +6 -0
  168. package/lib/runtime/http/abort-signal.js +19 -0
  169. package/lib/runtime/http/abort-signal.test.d.ts +1 -0
  170. package/lib/runtime/http/abort-signal.test.js +49 -0
  171. package/lib/runtime/http/node-server.d.ts +38 -0
  172. package/lib/runtime/http/node-server.js +99 -0
  173. package/lib/runtime/http/node-server.test.d.ts +1 -0
  174. package/lib/runtime/http/node-server.test.js +96 -0
  175. package/lib/runtime/http/node-sink.d.ts +16 -0
  176. package/lib/runtime/http/node-sink.js +48 -0
  177. package/lib/runtime/http/node-sink.test.d.ts +1 -0
  178. package/lib/runtime/http/node-sink.test.js +66 -0
  179. package/lib/runtime/http/request.d.ts +62 -0
  180. package/lib/runtime/http/request.js +134 -0
  181. package/lib/runtime/http/request.test.d.ts +1 -0
  182. package/lib/runtime/http/request.test.js +103 -0
  183. package/lib/runtime/http/response.d.ts +77 -0
  184. package/lib/runtime/http/response.js +229 -0
  185. package/lib/runtime/http/response.test.d.ts +1 -0
  186. package/lib/runtime/http/response.test.js +178 -0
  187. package/lib/runtime/http/sink.d.ts +73 -0
  188. package/lib/runtime/http/sink.js +188 -0
  189. package/lib/runtime/http/sink.test.d.ts +1 -0
  190. package/lib/runtime/http/sink.test.js +257 -0
  191. package/lib/runtime/image-utils.d.ts +78 -0
  192. package/lib/runtime/image-utils.js +129 -0
  193. package/lib/runtime/image-utils.test.d.ts +1 -0
  194. package/lib/runtime/image-utils.test.js +237 -0
  195. package/lib/runtime/image.d.ts +76 -0
  196. package/lib/runtime/image.js +296 -0
  197. package/lib/runtime/image.test.d.ts +1 -0
  198. package/lib/runtime/image.test.js +405 -0
  199. package/lib/runtime/lambda-event.d.ts +4 -0
  200. package/lib/runtime/lambda-event.js +113 -0
  201. package/lib/runtime/lambda-event.test.d.ts +1 -0
  202. package/lib/runtime/lambda-event.test.js +119 -0
  203. package/lib/runtime/lambda.mjs +41600 -0
  204. package/lib/runtime/load-module.d.ts +8 -0
  205. package/lib/runtime/load-module.js +35 -0
  206. package/lib/runtime/manifest.d.ts +215 -0
  207. package/lib/runtime/manifest.js +118 -0
  208. package/lib/runtime/middleware.d.ts +43 -0
  209. package/lib/runtime/middleware.js +113 -0
  210. package/lib/runtime/middleware.test.d.ts +1 -0
  211. package/lib/runtime/middleware.test.js +259 -0
  212. package/lib/runtime/next-modules.d.ts +71 -0
  213. package/lib/runtime/next-modules.js +144 -0
  214. package/lib/runtime/next-modules.test.d.ts +1 -0
  215. package/lib/runtime/next-modules.test.js +34 -0
  216. package/lib/runtime/public-files.d.ts +32 -0
  217. package/lib/runtime/public-files.js +117 -0
  218. package/lib/runtime/public-files.test.d.ts +1 -0
  219. package/lib/runtime/public-files.test.js +97 -0
  220. package/lib/runtime/server.mjs +41593 -0
  221. package/lib/runtime/static-files.d.ts +50 -0
  222. package/lib/runtime/static-files.js +266 -0
  223. package/lib/runtime/static-files.test.d.ts +1 -0
  224. package/lib/runtime/static-files.test.js +118 -0
  225. package/lib/runtime/util.d.ts +28 -0
  226. package/lib/runtime/util.js +79 -0
  227. package/lib/utils/base-path.d.ts +106 -13
  228. package/lib/utils/base-path.js +254 -41
  229. package/lib/utils/base-path.test.js +219 -51
  230. package/lib/utils/get-architecture.d.ts +7 -8
  231. package/lib/utils/get-architecture.js +12 -13
  232. package/lib/utils/zip-directory.d.ts +14 -0
  233. package/lib/utils/zip-directory.js +121 -0
  234. package/lib/utils/zip-directory.test.d.ts +1 -0
  235. package/lib/utils/zip-directory.test.js +99 -0
  236. package/package.json +22 -3
  237. package/scripts/capture-adapter-fixture.mjs +325 -0
  238. package/scripts/e2e-deploy.sh +398 -0
  239. package/scripts/e2e-harness/README.md +707 -0
  240. package/scripts/e2e-harness/app.js +370 -0
  241. package/scripts/e2e-harness/common.sh +249 -0
  242. package/scripts/e2e-harness/screen.mjs +302 -0
  243. package/scripts/e2e-harness/stage-proxy.mjs +145 -0
  244. package/scripts/e2e-harness/type-filters.mjs +47 -0
  245. package/scripts/e2e-logs.sh +75 -0
  246. package/scripts/e2e-offline.sh +91 -0
  247. package/scripts/e2e-sweep.sh +370 -0
  248. package/scripts/e2e-warm.sh +114 -0
  249. package/scripts/zero-config-build.mjs +418 -0
  250. package/docs/1k-concurrent-users-executions.png +0 -0
  251. package/docs/plans/adapter-runtime-release.md +0 -362
  252. package/docs/plans/phase-0-image-function-opt-in.md +0 -295
  253. package/lib/generated-structs/OptionalDockerImageFunctionProps.d.ts +0 -425
  254. package/lib/generated-structs/OptionalDockerImageFunctionProps.js +0 -3
  255. package/lib/image-optimization/handler-utils.d.ts +0 -34
  256. package/lib/image-optimization/handler-utils.js +0 -83
  257. package/lib/image-optimization/handler-utils.test.js +0 -178
  258. package/lib/nextjs-build/functions.Dockerfile +0 -31
  259. package/lib/nextjs-compute/nextjs-image-function.d.ts +0 -53
  260. package/lib/nextjs-compute/nextjs-image-function.js +0 -59
  261. package/lib/utils/experimental-flags.d.ts +0 -24
  262. package/lib/utils/experimental-flags.js +0 -30
  263. /package/lib/{image-optimization/handler-utils.test.d.ts → adapter/adapter.test.d.ts} +0 -0
@@ -39,9 +39,16 @@ export default class CdkNextjsCacheHandler implements CacheHandler {
39
39
  * - Build time: Not implemented
40
40
  * - Runtime: Delegate to S3/DynamoDB handler
41
41
  */
42
- revalidateTag(tag: string): Promise<void>;
42
+ revalidateTag(tag: string | string[], durations?: {
43
+ expire?: number;
44
+ }): Promise<void>;
43
45
  /**
44
- * Reset request cache (called between requests)
46
+ * Deliberately a no-op. Next.js calls `resetRequestCache` at the start of
47
+ * every request (`base-server`, `app-page`, `app-route`), and its own
48
+ * `FileSystemCache` - whose LRU is shared across requests the same way the
49
+ * memory layer is - leaves it empty: the hook is for state scoped to one
50
+ * request, and nothing here is. Clearing the memory layer in it meant no
51
+ * entry ever survived to a second request, so every read went to S3.
45
52
  */
46
53
  resetRequestCache(): Promise<void>;
47
54
  }
@@ -12,11 +12,11 @@ Object.defineProperty(exports, "__esModule", { value: true });
12
12
  */
13
13
  /* eslint-disable import/no-extraneous-dependencies */
14
14
  const debug_1 = __importDefault(require("debug"));
15
+ const cache_utils_1 = require("./cache-utils");
15
16
  const local_file_cache_handler_1 = require("./local-file-cache-handler");
16
17
  const memory_cache_handler_1 = require("./memory-cache-handler");
17
18
  const s3_cache_handler_1 = require("./s3-cache-handler");
18
- // Helper to safely extract tags from context
19
- const getTags = (ctx) => ("tags" in ctx ? ctx.tags : undefined);
19
+ const use_cache_common_1 = require("./use-cache-common");
20
20
  /**
21
21
  * Orchestrator cache handler that conditionally instantiates handlers based on environment
22
22
  */
@@ -33,38 +33,23 @@ class CdkNextjsCacheHandler {
33
33
  */
34
34
  static sharedMemoryHandler = null;
35
35
  static sharedS3DynamoHandler = null;
36
- isBuildTime = process.env.NEXT_PHASE === "phase-production-build";
36
+ isBuildTime = (0, use_cache_common_1.isBuildPhase)();
37
37
  debug = (0, debug_1.default)("cdk-nextjs:cache-handler:orchestrator");
38
- // Build-time handler
39
- localFileHandler = null;
40
- // Runtime handlers (shared across all instances)
41
- memoryHandler = null;
42
- s3DynamoHandler = null;
38
+ // Set only at build time.
39
+ localFileHandler;
40
+ // Set only at runtime, shared across all instances.
41
+ memoryHandler;
42
+ s3DynamoHandler;
43
43
  constructor(options) {
44
44
  if (this.isBuildTime) {
45
- // Build time: only local file cache
46
45
  this.localFileHandler = new local_file_cache_handler_1.LocalFileCacheHandler();
47
- this.debug("Build-time mode: LocalFileCacheHandler initialized");
48
- this.debug(`Cache directory: ${this.localFileHandler.getCacheDir()}`);
46
+ this.debug(`Build-time cache directory: ${this.localFileHandler.getCacheDir()}`);
49
47
  }
50
48
  else {
51
- // Runtime: reuse shared handlers (singleton pattern)
52
- // Initialize once on first construction
53
- if (!CdkNextjsCacheHandler.sharedS3DynamoHandler) {
54
- CdkNextjsCacheHandler.sharedS3DynamoHandler = new s3_cache_handler_1.S3CacheHandler({
55
- context: options,
56
- });
57
- this.debug("Initialized shared S3/DynamoDB handler");
58
- }
59
- if (!CdkNextjsCacheHandler.sharedMemoryHandler) {
60
- CdkNextjsCacheHandler.sharedMemoryHandler = new memory_cache_handler_1.MemoryCacheHandler({
61
- context: options,
62
- });
63
- this.debug("Initialized shared Memory handler");
64
- }
65
- // Reference shared instances
66
- this.s3DynamoHandler = CdkNextjsCacheHandler.sharedS3DynamoHandler;
67
- this.memoryHandler = CdkNextjsCacheHandler.sharedMemoryHandler;
49
+ this.s3DynamoHandler = CdkNextjsCacheHandler.sharedS3DynamoHandler ??=
50
+ new s3_cache_handler_1.S3CacheHandler({ context: options });
51
+ this.memoryHandler = CdkNextjsCacheHandler.sharedMemoryHandler ??=
52
+ new memory_cache_handler_1.MemoryCacheHandler();
68
53
  }
69
54
  }
70
55
  /**
@@ -74,28 +59,49 @@ class CdkNextjsCacheHandler {
74
59
  */
75
60
  async get(cacheKey, ctx) {
76
61
  if (this.isBuildTime) {
77
- // Build time doesn't read from cache
78
- return null;
62
+ // Reads back what this build wrote, which `cacheComponents` prerendering
63
+ // requires; see {@link LocalFileCacheHandler.get}.
64
+ return this.localFileHandler.get(cacheKey);
79
65
  }
80
66
  // Runtime: try memory first
81
- if (this.memoryHandler) {
82
- const memoryResult = await this.memoryHandler.get(cacheKey, ctx);
83
- if (memoryResult) {
84
- this.debug(`Memory cache HIT: ${cacheKey}`);
85
- return memoryResult;
86
- }
67
+ const memoryResult = await this.memoryHandler.get(cacheKey);
68
+ // A memory hit is checked against the same tag markers an S3 read is.
69
+ // `revalidateTag` can only clear the memory of the instance that ran it,
70
+ // so skipping the check left every other instance answering from memory
71
+ // for the whole memory TTL - and CloudFront, whose copy that
72
+ // `revalidateTag` had just invalidated, cached the stale page again.
73
+ // The check is one DynamoDB `BatchGetItem`; what the memory layer still
74
+ // saves is the S3 read and the parse of the body. A revalidated entry is
75
+ // dropped and read from S3, which hands it back expired or as a miss.
76
+ if (memoryResult &&
77
+ (await this.s3DynamoHandler.isRevalidated({
78
+ lastModified: memoryResult.lastModified,
79
+ value: memoryResult.value,
80
+ }, ctx, cacheKey))) {
81
+ this.debug(`Memory cache REVALIDATED: ${cacheKey}`);
82
+ await this.memoryHandler.set(cacheKey, null);
83
+ }
84
+ else if (memoryResult) {
85
+ this.debug(`Memory cache HIT: ${cacheKey}`);
86
+ return memoryResult;
87
87
  }
88
88
  // Memory miss - try S3/DynamoDB
89
- if (this.s3DynamoHandler) {
90
- const s3Result = await this.s3DynamoHandler.get(cacheKey, ctx);
91
- if (s3Result) {
92
- this.debug(`S3 cache HIT: ${cacheKey}`);
93
- // Populate memory cache for next time
94
- if (this.memoryHandler) {
95
- await this.memoryHandler.set(cacheKey, s3Result.value, ctx);
96
- }
97
- return s3Result;
89
+ const s3Result = await this.s3DynamoHandler.get(cacheKey, ctx);
90
+ if (s3Result) {
91
+ this.debug(`S3 cache HIT: ${cacheKey}`);
92
+ // Promoted with the S3 entry's own `lastModified`, not the time of the
93
+ // copy: Next.js ages the entry from it for time-based revalidation, and
94
+ // the tag markers are compared against it too. Stamping `Date.now()`
95
+ // made an entry that was due for regeneration look freshly rendered,
96
+ // and one a soft `revalidateTag` had made stale look newer than the
97
+ // stale mark, so memory hits served it as fresh for the whole memory
98
+ // TTL. An entry a tag revalidation expired (`lastModified: -1`) is not
99
+ // copied at all: the re-render it asks for writes the fresh entry to
100
+ // both layers.
101
+ if (s3Result.lastModified !== -1) {
102
+ await this.memoryHandler.set(cacheKey, s3Result.value, s3Result.lastModified);
98
103
  }
104
+ return s3Result;
99
105
  }
100
106
  this.debug(`Cache MISS: ${cacheKey}`);
101
107
  return null;
@@ -107,73 +113,43 @@ class CdkNextjsCacheHandler {
107
113
  */
108
114
  async set(cacheKey, data, ctx) {
109
115
  if (this.isBuildTime) {
110
- // Build time: write or delete from local file cache
111
- if (this.localFileHandler) {
112
- if (data) {
113
- const tags = getTags(ctx);
114
- await this.localFileHandler.set(cacheKey, data, tags);
115
- this.debug(`Build cache write: ${cacheKey}`);
116
- }
117
- else {
118
- // Delete not implemented for local file cache (build-time only creates files)
119
- this.debug(`Build cache delete ignored: ${cacheKey}`);
120
- }
121
- }
122
- }
123
- else {
124
- // Runtime: write or delete from memory and S3/DynamoDB
125
116
  if (data) {
126
- // Write to memory
127
- if (this.memoryHandler) {
128
- await this.memoryHandler.set(cacheKey, data, ctx);
129
- this.debug(`Memory cache write: ${cacheKey}`);
130
- }
131
- // Also write to S3/DynamoDB for persistence
132
- if (this.s3DynamoHandler) {
133
- await this.s3DynamoHandler.set(cacheKey, data, ctx);
134
- this.debug(`S3 cache write: ${cacheKey}`);
135
- }
117
+ await this.localFileHandler.set(cacheKey, data, (0, cache_utils_1.getTags)(ctx));
118
+ this.debug(`Build cache write: ${cacheKey}`);
136
119
  }
137
120
  else {
138
- // Delete from both layers
139
- this.debug(`Cache delete: ${cacheKey}`);
140
- // Delete from memory (removes from cache Map)
141
- if (this.memoryHandler) {
142
- await this.memoryHandler.set(cacheKey, null, ctx);
143
- }
144
- // Delete from S3/DynamoDB
145
- if (this.s3DynamoHandler) {
146
- await this.s3DynamoHandler.set(cacheKey, null, ctx);
147
- }
121
+ // Delete not implemented for local file cache (build-time only creates files)
122
+ this.debug(`Build cache delete ignored: ${cacheKey}`);
148
123
  }
124
+ return;
149
125
  }
126
+ // Runtime: both layers, where `null` is a delete.
127
+ this.debug(`Cache ${data ? "write" : "delete"}: ${cacheKey}`);
128
+ await this.memoryHandler.set(cacheKey, data);
129
+ await this.s3DynamoHandler.set(cacheKey, data, ctx);
150
130
  }
151
131
  /**
152
132
  * Revalidate tags
153
133
  * - Build time: Not implemented
154
134
  * - Runtime: Delegate to S3/DynamoDB handler
155
135
  */
156
- async revalidateTag(tag) {
136
+ async revalidateTag(tag, durations) {
157
137
  if (this.isBuildTime) {
158
138
  return;
159
139
  }
160
- // Clear from memory
161
- if (this.memoryHandler) {
162
- await this.memoryHandler.revalidateTag(tag);
163
- }
164
- // Clear from S3/DynamoDB
165
- if (this.s3DynamoHandler) {
166
- await this.s3DynamoHandler.revalidateTag(tag);
167
- }
140
+ // Memory hits are checked against the same markers (see `get`), so only
141
+ // the S3/DynamoDB handler has anything to record.
142
+ await this.s3DynamoHandler.revalidateTag(tag, durations);
168
143
  }
169
144
  /**
170
- * Reset request cache (called between requests)
145
+ * Deliberately a no-op. Next.js calls `resetRequestCache` at the start of
146
+ * every request (`base-server`, `app-page`, `app-route`), and its own
147
+ * `FileSystemCache` - whose LRU is shared across requests the same way the
148
+ * memory layer is - leaves it empty: the hook is for state scoped to one
149
+ * request, and nothing here is. Clearing the memory layer in it meant no
150
+ * entry ever survived to a second request, so every read went to S3.
171
151
  */
172
- async resetRequestCache() {
173
- if (this.memoryHandler) {
174
- await this.memoryHandler.resetRequestCache();
175
- }
176
- }
152
+ async resetRequestCache() { }
177
153
  }
178
154
  exports.default = CdkNextjsCacheHandler;
179
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2FjaGUtaGFuZGxlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9hZGFwdGVyL2NhY2hlLWhhbmRsZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFBQTs7Ozs7O0VBTUU7QUFDRixzREFBc0Q7QUFDdEQsa0RBQTZCO0FBYTdCLHlFQUFtRTtBQUNuRSxpRUFBNEQ7QUFDNUQseURBQW9EO0FBRXBELDZDQUE2QztBQUM3QyxNQUFNLE9BQU8sR0FBRyxDQUNkLEdBQXlFLEVBQ25ELEVBQUUsQ0FBQyxDQUFDLE1BQU0sSUFBSSxHQUFHLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxDQUFDO0FBRWxFOztHQUVHO0FBQ0gsTUFBcUIscUJBQXFCO0lBQ3hDOzs7Ozs7Ozs7T0FTRztJQUNLLE1BQU0sQ0FBQyxtQkFBbUIsR0FBOEIsSUFBSSxDQUFDO0lBQzdELE1BQU0sQ0FBQyxxQkFBcUIsR0FBMEIsSUFBSSxDQUFDO0lBRWxELFdBQVcsR0FDMUIsT0FBTyxDQUFDLEdBQUcsQ0FBQyxVQUFVLEtBQUssd0JBQXdCLENBQUM7SUFDckMsS0FBSyxHQUFHLElBQUEsZUFBUSxFQUFDLHVDQUF1QyxDQUFDLENBQUM7SUFFM0UscUJBQXFCO0lBQ2IsZ0JBQWdCLEdBQWlDLElBQUksQ0FBQztJQUU5RCxpREFBaUQ7SUFDekMsYUFBYSxHQUE4QixJQUFJLENBQUM7SUFDaEQsZUFBZSxHQUEwQixJQUFJLENBQUM7SUFFdEQsWUFBWSxPQUE0QjtRQUN0QyxJQUFJLElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQztZQUNyQixvQ0FBb0M7WUFDcEMsSUFBSSxDQUFDLGdCQUFnQixHQUFHLElBQUksZ0RBQXFCLEVBQUUsQ0FBQztZQUVwRCxJQUFJLENBQUMsS0FBSyxDQUFDLG9EQUFvRCxDQUFDLENBQUM7WUFDakUsSUFBSSxDQUFDLEtBQUssQ0FBQyxvQkFBb0IsSUFBSSxDQUFDLGdCQUFn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SSxFQUFFLEdBQUcsQ0FBQyxDQUFDO2dCQUN0RCxDQUFDO1lBQ0gsQ0FBQztRQUNILENBQUM7SUFDSCxDQUFDO0lBRUQ7Ozs7T0FJRztJQUNILEtBQUssQ0FBQyxhQUFhLENBQUMsR0FBVztRQUM3QixJQUFJLElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQztZQUNyQixPQUFPO1FBQ1QsQ0FBQztRQUVELG9CQUFvQjtRQUNwQixJQUFJLElBQUksQ0FBQyxhQUFhLEVBQUUsQ0FBQztZQUN2QixNQUFNLElBQUksQ0FBQyxhQUFhLENBQUMsYUFBYSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQzlDLENBQUM7UUFFRCx5QkFBeUI7UUFDekIsSUFBSSxJQUFJLENBQUMsZUFBZSxFQUFFLENBQUM7WUFDekIsTUFBTSxJQUFJLENBQUMsZUFBZSxDQUFDLGFBQWEsQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUNoRCxDQUFDO0lBQ0gsQ0FBQztJQUVEOztPQUVHO0lBQ0gsS0FBSyxDQUFDLGlCQUFpQjtRQUNyQixJQUFJLElBQUksQ0FBQyxhQUFhLEVBQUUsQ0FBQztZQUN2QixNQUFNLElBQUksQ0FBQyxhQUFhLENBQUMsaUJBQWlCLEVBQUUsQ0FBQztRQUMvQyxDQUFDO0lBQ0gsQ0FBQzs7QUFoTEgsd0NBaUxDIiwic291cmNlc0NvbnRlbnQiOlsiLypcbiAgTmV4dC5qcyBDdXN0b20gQ2FjaGUgSGFuZGxlci4gU2VlOiBodHRwczovL25leHRqcy5vcmcvZG9jcy9hcHAvYXBpLXJlZmVyZW5jZS9uZXh0LWNvbmZpZy1qcy9pbmNyZW1lbnRhbENhY2hlSGFuZGxlclBhdGhcbiAgXG4gIE9yY2hlc3RyYXRvciBjYWNoZSBoYW5kbGVyIHRoYXQgY29uZGl0aW9uYWxseSB1c2VzIGRpZmZlcmVudCBjYWNoaW5nIHN0cmF0ZWdpZXM6XG4gIC0gQnVpbGQgdGltZTogTG9jYWxGaWxlQ2FjaGVIYW5kbGVyIGZvciBwcmUtY2FjaGluZ1xuICAtIFJ1bnRpbWU6IE1lbW9yeUNhY2hlSGFuZGxlciAoZmFzdCkgKyBTM0R5bmFtb0NhY2hlSGFuZGxlciAocGVyc2lzdGVudClcbiovXG4vKiBlc2xpbnQtZGlzYWJsZSBpbXBvcnQvbm8tZXh0cmFuZW91cy1kZXBlbmRlbmNpZXMgKi9cbmltcG9ydCBnZXREZWJ1ZyBmcm9tIFwiZGVidWdcIjtcbmltcG9ydCB7XG4gIENhY2hlSGFuZGxlcixcbiAgQ2FjaGVIYW5kbGVyVmFsdWUsXG4gIENhY2hlSGFuZGxlckNvbnRleHQsXG59IGZyb20gXCJuZXh0L2Rpc3Qvc2VydmVyL2xpYi9pbmNyZW1lbnRhbC1jYWNoZVwiO1xuaW1wb3J0IHR5cGUge1xuICBJbmNyZW1lbnRhbENhY2hlVmFsdWUsXG4gIEdldEluY3JlbWVudGFsRmV0Y2hDYWNoZUNvbnRleHQsXG4gIEdldEluY3JlbWVudGFsUmVzcG9uc2VDYWNoZUNvbnRleHQsXG4gIFNldEluY3JlbWVudGFsRmV0Y2hDYWNoZUNvbnRleHQsXG4gIFNldEluY3JlbWVudGFsUmVzcG9uc2VDYWNoZUNvbnRleHQsXG59IGZyb20gXCJuZXh0L2Rpc3Qvc2VydmVyL3Jlc3BvbnNlLWNhY2hlXCI7XG5pbXBvcnQgeyBMb2NhbEZpbGVDYWNoZUhhbmRsZXIgfSBmcm9tIFwiLi9sb2NhbC1maWxlLWNhY2hlLWhhbmRsZXJcIjtcbmltcG9ydCB7IE1lbW9yeUNhY2hlSGFuZGxlciB9IGZyb20gXCIuL21lbW9yeS1jYWNoZS1oYW5kbGVyXCI7XG5pbXBvcnQgeyBTM0NhY2hlSGFuZGxlciB9IGZyb20gXCIuL3MzLWNhY2hlLWhhbmRsZXJcIjtcblxuLy8gSGVscGVyIHRvIHNhZmVseSBleHRyYWN0IHRhZ3MgZnJvbSBjb250ZXh0XG5jb25zdCBnZXRUYWdzID0gKFxuICBjdHg6IFNldEluY3JlbWVudGFsRmV0Y2hDYWNoZUNvbnRleHQgfCBTZXRJbmNyZW1lbnRhbFJlc3BvbnNlQ2FjaGVDb250ZXh0LFxuKTogc3RyaW5nW10gfCB1bmRlZmluZWQgPT4gKFwidGFnc1wiIGluIGN0eCA/IGN0eC50YWdzIDogdW5kZWZpbmVkKTtcblxuLyoqXG4gKiBPcmNoZXN0cmF0b3IgY2FjaGUgaGFuZGxlciB0aGF0IGNvbmRpdGlvbmFsbHkgaW5zdGFudGlhdGVzIGhhbmRsZXJzIGJhc2VkIG9uIGVudmlyb25tZW50XG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIENka05leHRqc0NhY2hlSGFuZGxlciBpbXBsZW1lbnRzIENhY2hlSGFuZGxlciB7XG4gIC8qKlxuICAgKiBTaGFyZWQgc2luZ2xldG9uIGhhbmRsZXJzIGZvciBydW50aW1lLlxuICAgKlxuICAgKiBOZXh0LmpzIGNyZWF0ZXMgbXVsdGlwbGUgY2FjaGUgaGFuZGxlciBpbnN0YW5jZXMgKG9uZSBlYWNoIGZvciBBUFBfUEFHRSwgQVBQX1JPVVRFLCBGRVRDSCwgZXRjKS5cbiAgICogVXNpbmcgc2luZ2xldG9uIHBhdHRlcm4gcHJvdmlkZXM6XG4gICAqIC0gU2luZ2xlIFMzIGNsaWVudCBjb25uZWN0aW9uIHBvb2wgc2hhcmVkIGFjcm9zcyBhbGwgY2FjaGUgdHlwZXNcbiAgICogLSBVbmlmaWVkIG1lbW9yeSBjYWNoZSBhY2Nlc3NpYmxlIGJ5IGFsbCBpbnN0YW5jZXMgKGNhY2hlIGhpdHMgYmVuZWZpdCBhbGwpXG4gICAqIC0gTG93ZXIgbWVtb3J5IGZvb3RwcmludCBhbmQgZmFzdGVyIGluaXRpYWxpemF0aW9uXG4gICAqIC0gU2FtZSBDYWNoZUhhbmRsZXJDb250ZXh0IGZvciBhbGwgaW5zdGFuY2VzLCBzbyBubyBjb25maWd1cmF0aW9uIGxvc3NcbiAgICovXG4gIHByaXZhdGUgc3RhdGljIHNoYXJlZE1lbW9yeUhhbmRsZXI6IE1lbW9yeUNhY2hlSGFuZGxlciB8IG51bGwgPSBudWxsO1xuICBwcml2YXRlIHN0YXRpYyBzaGFyZWRTM0R5bmFtb0hhbmRsZXI6IFMzQ2FjaGVIYW5kbGVyIHwgbnVsbCA9IG51bGw7XG5cbiAgcHJpdmF0ZSByZWFkb25seSBpc0J1aWxkVGltZSA9XG4gICAgcHJvY2Vzcy5lbnYuTkVYVF9QSEFTRSA9PT0gXCJwaGFzZS1wcm9kdWN0aW9uLWJ1aWxkXCI7XG4gIHByaXZhdGUgcmVhZG9ubHkgZGVidWcgPSBnZXREZWJ1ZyhcImNkay1uZXh0anM6Y2FjaGUtaGFuZGxlcjpvcmNoZXN0cmF0b3JcIik7XG5cbiAgLy8gQnVpbGQtdGltZSBoYW5kbGVyXG4gIHByaXZhdGUgbG9jYWxGaWxlSGFuZGxlcjogTG9jYWxGaWxlQ2FjaGVIYW5kbGVyIHwgbnVsbCA9IG51bGw7XG5cbiAgLy8gUnVudGltZSBoYW5kbGVycyAoc2hhcmVkIGFjcm9zcyBhbGwgaW5zdGFuY2VzKVxuICBwcml2YXRlIG1lbW9yeUhhbmRsZXI6IE1lbW9yeUNhY2hlSGFuZGxlciB8IG51bGwgPSBudWxsO1xuICBwcml2YXRlIHMzRHluYW1vSGFuZGxlcjogUzNDYWNoZUhhbmRsZXIgfCBudWxsID0gbnVsbDtcblxuICBjb25zdHJ1Y3RvcihvcHRpb25zOiBDYWNoZUhhbmRsZXJDb250ZXh0KSB7XG4gICAgaWYgKHRoaXMuaXNCdWlsZFRpbWUpIHtcbiAgICAgIC8vIEJ1aWxkIHRpbWU6IG9ubHkgbG9jYWwgZmlsZSBjYWNoZVxuICAgICAgdGhpcy5sb2NhbEZpbGVIYW5kbGVyID0gbmV3IExvY2FsRmlsZUNhY2hlSGFuZGxlcigpO1xuXG4gICAgICB0aGlzLmRlYnVnKFwiQnVpbGQtdGltZSBtb2RlOiBMb2NhbEZpbGVDYWNoZUhhbmRsZXIgaW5pdGlhbGl6ZWRcIik7XG4gICAgICB0aGlzLmRlYnVnKGBDYWNoZSBkaXJlY3Rvcnk6ICR7dGhpcy5sb2NhbEZpbGVIYW5kbGVyLmdldENhY2hlRGlyKCl9YCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIFJ1bnRpbWU6IHJldXNlIHNoYXJlZCBoYW5kbGVycyAoc2luZ2xldG9uIHBhdHRlcm4pXG4gICAgICAvLyBJbml0aWFsaXplIG9uY2Ugb24gZmlyc3QgY29uc3RydWN0aW9uXG4gICAgICBpZiAoIUNka05leHRqc0NhY2hlSGFuZGxlci5zaGFyZWRTM0R5bmFtb0hhbmRsZXIpIHtcbiAgICAgICAgQ2RrTmV4dGpzQ2FjaGVIYW5kbGVyLnNoYXJlZFMzRHluYW1vSGFuZGxlciA9IG5ldyBTM0NhY2hlSGFuZGxlcih7XG4gICAgICAgICAgY29udGV4dDogb3B0aW9ucyxcbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMuZGVidWcoXCJJbml0aWFsaXplZCBzaGFyZWQgUzMvRHluYW1vREIgaGFuZGxlclwiKTtcbiAgICAgIH1cblxuICAgICAgaWYgKCFDZGtOZXh0anNDYWNoZUhhbmRsZXIuc2hhcmVkTWVtb3J5SGFuZGxlcikge1xuICAgICAgICBDZGtOZXh0anNDYWNoZUhhbmRsZXIuc2hhcmVkTWVtb3J5SGFuZGxlciA9IG5ldyBNZW1vcnlDYWNoZUhhbmRsZXIoe1xuICAgICAgICAgIGNvbnRleHQ6IG9wdGlvbnMsXG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLmRlYnVnKFwiSW5pdGlhbGl6ZWQgc2hhcmVkIE1lbW9yeSBoYW5kbGVyXCIpO1xuICAgICAgfVxuXG4gICAgICAvLyBSZWZlcmVuY2Ugc2hhcmVkIGluc3RhbmNlc1xuICAgICAgdGhpcy5zM0R5bmFtb0hhbmRsZXIgPSBDZGtOZXh0anNDYWNoZUhhbmRsZXIuc2hhcmVkUzNEeW5hbW9IYW5kbGVyO1xuICAgICAgdGhpcy5tZW1vcnlIYW5kbGVyID0gQ2RrTmV4dGpzQ2FjaGVIYW5kbGVyLnNoYXJlZE1lbW9yeUhhbmRsZXI7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEdldCBjYWNoZSBlbnRyeVxuICAgKiAtIEJ1aWxkIHRpbWU6IE5vdCBpbXBsZW1lbnRlZCAoYnVpbGQgZG9lc24ndCByZWFkIGNhY2hlKVxuICAgKiAtIFJ1bnRpbWU6IFRyeSBtZW1vcnkgZmlyc3QsIHRoZW4gUzMvRHluYW1vREJcbiAgICovXG4gIGFzeW5jIGdldChcbiAgICBjYWNoZUtleTogc3RyaW5nLFxuICAgIGN0eDogR2V0SW5jcmVtZW50YWxGZXRjaENhY2hlQ29udGV4dCB8IEdldEluY3JlbWVudGFsUmVzcG9uc2VDYWNoZUNvbnRleHQsXG4gICk6IFByb21pc2U8Q2FjaGVIYW5kbGVyVmFsdWUgfCBudWxsPiB7XG4gICAgaWYgKHRoaXMuaXNCdWlsZFRpbWUpIHtcbiAgICAgIC8vIEJ1aWxkIHRpbWUgZG9lc24ndCByZWFkIGZyb20gY2FjaGVcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIC8vIFJ1bnRpbWU6IHRyeSBtZW1vcnkgZmlyc3RcbiAgICBpZiAodGhpcy5tZW1vcnlIYW5kbGVyKSB7XG4gICAgICBjb25zdCBtZW1vcnlSZXN1bHQgPSBhd2FpdCB0aGlzLm1lbW9yeUhhbmRsZXIuZ2V0KGNhY2hlS2V5LCBjdHgpO1xuICAgICAgaWYgKG1lbW9yeVJlc3VsdCkge1xuICAgICAgICB0aGlzLmRlYnVnKGBNZW1vcnkgY2FjaGUgSElUOiAke2NhY2hlS2V5fWApO1xuICAgICAgICByZXR1cm4gbWVtb3J5UmVzdWx0O1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIE1lbW9yeSBtaXNzIC0gdHJ5IFMzL0R5bmFtb0RCXG4gICAgaWYgKHRoaXMuczNEeW5hbW9IYW5kbGVyKSB7XG4gICAgICBjb25zdCBzM1Jlc3VsdCA9IGF3YWl0IHRoaXMuczNEeW5hbW9IYW5kbGVyLmdldChjYWNoZUtleSwgY3R4KTtcbiAgICAgIGlmIChzM1Jlc3VsdCkge1xuICAgICAgICB0aGlzLmRlYnVnKGBTMyBjYWNoZSBISVQ6ICR7Y2FjaGVLZXl9YCk7XG4gICAgICAgIC8vIFBvcHVsYXRlIG1lbW9yeSBjYWNoZSBmb3IgbmV4dCB0aW1lXG4gICAgICAgIGlmICh0aGlzLm1lbW9yeUhhbmRsZXIpIHtcbiAgICAgICAgICBhd2FpdCB0aGlzLm1lbW9yeUhhbmRsZXIuc2V0KGNhY2hlS2V5LCBzM1Jlc3VsdC52YWx1ZSwgY3R4IGFzIGFueSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHMzUmVzdWx0O1xuICAgICAgfVxuICAgIH1cblxuICAgIHRoaXMuZGVidWcoYENhY2hlIE1JU1M6ICR7Y2FjaGVLZXl9YCk7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICAvKipcbiAgICogU2V0IGNhY2hlIGVudHJ5XG4gICAqIC0gQnVpbGQgdGltZTogV3JpdGUgdG8gbG9jYWwgZmlsZSBjYWNoZSBvbmx5IChvciBkZWxldGUgaWYgZGF0YSBpcyBudWxsKVxuICAgKiAtIFJ1bnRpbWU6IFdyaXRlIHRvIGJvdGggbWVtb3J5IGFuZCBTMy9EeW5hbW9EQiAob3IgZGVsZXRlIGlmIGRhdGEgaXMgbnVsbClcbiAgICovXG4gIGFzeW5jIHNldChcbiAgICBjYWNoZUtleTogc3RyaW5nLFxuICAgIGRhdGE6IEluY3JlbWVudGFsQ2FjaGVWYWx1ZSB8IG51bGwsXG4gICAgY3R4OiBTZXRJbmNyZW1lbnRhbEZldGNoQ2FjaGVDb250ZXh0IHwgU2V0SW5jcmVtZW50YWxSZXNwb25zZUNhY2hlQ29udGV4dCxcbiAgKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgaWYgKHRoaXMuaXNCdWlsZFRpbWUpIHtcbiAgICAgIC8vIEJ1aWxkIHRpbWU6IHdyaXRlIG9yIGRlbGV0ZSBmcm9tIGxvY2FsIGZpbGUgY2FjaGVcbiAgICAgIGlmICh0aGlzLmxvY2FsRmlsZUhhbmRsZXIpIHtcbiAgICAgICAgaWYgKGRhdGEpIHtcbiAgICAgICAgICBjb25zdCB0YWdzID0gZ2V0VGFncyhjdHgpO1xuICAgICAgICAgIGF3YWl0IHRoaXMubG9jYWxGaWxlSGFuZGxlci5zZXQoY2FjaGVLZXksIGRhdGEsIHRhZ3MpO1xuICAgICAgICAgIHRoaXMuZGVidWcoYEJ1aWxkIGNhY2hlIHdyaXRlOiAke2NhY2hlS2V5fWApO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIC8vIERlbGV0ZSBub3QgaW1wbGVtZW50ZWQgZm9yIGxvY2FsIGZpbGUgY2FjaGUgKGJ1aWxkLXRpbWUgb25seSBjcmVhdGVzIGZpbGVzKVxuICAgICAgICAgIHRoaXMuZGVidWcoYEJ1aWxkIGNhY2hlIGRlbGV0ZSBpZ25vcmVkOiAke2NhY2hlS2V5fWApO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIFJ1bnRpbWU6IHdyaXRlIG9yIGRlbGV0ZSBmcm9tIG1lbW9yeSBhbmQgUzMvRHluYW1vREJcbiAgICAgIGlmIChkYXRhKSB7XG4gICAgICAgIC8vIFdyaXRlIHRvIG1lbW9yeVxuICAgICAgICBpZiAodGhpcy5tZW1vcnlIYW5kbGVyKSB7XG4gICAgICAgICAgYXdhaXQgdGhpcy5tZW1vcnlIYW5kbGVyLnNldChjYWNoZUtleSwgZGF0YSwgY3R4KTtcbiAgICAgICAgICB0aGlzLmRlYnVnKGBNZW1vcnkgY2FjaGUgd3JpdGU6ICR7Y2FjaGVLZXl9YCk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBBbHNvIHdyaXRlIHRvIFMzL0R5bmFtb0RCIGZvciBwZXJzaXN0ZW5jZVxuICAgICAgICBpZiAodGhpcy5zM0R5bmFtb0hhbmRsZXIpIHtcbiAgICAgICAgICBhd2FpdCB0aGlzLnMzRHluYW1vSGFuZGxlci5zZXQoY2FjaGVLZXksIGRhdGEsIGN0eCk7XG4gICAgICAgICAgdGhpcy5kZWJ1ZyhgUzMgY2FjaGUgd3JpdGU6ICR7Y2FjaGVLZXl9YCk7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIERlbGV0ZSBmcm9tIGJvdGggbGF5ZXJzXG4gICAgICAgIHRoaXMuZGVidWcoYENhY2hlIGRlbGV0ZTogJHtjYWNoZUtleX1gKTtcblxuICAgICAgICAvLyBEZWxldGUgZnJvbSBtZW1vcnkgKHJlbW92ZXMgZnJvbSBjYWNoZSBNYXApXG4gICAgICAgIGlmICh0aGlzLm1lbW9yeUhhbmRsZXIpIHtcbiAgICAgICAgICBhd2FpdCB0aGlzLm1lbW9yeUhhbmRsZXIuc2V0KGNhY2hlS2V5LCBudWxsLCBjdHgpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gRGVsZXRlIGZyb20gUzMvRHluYW1vREJcbiAgICAgICAgaWYgKHRoaXMuczNEeW5hbW9IYW5kbGVyKSB7XG4gICAgICAgICAgYXdhaXQgdGhpcy5zM0R5bmFtb0hhbmRsZXIuc2V0KGNhY2hlS2V5LCBudWxsLCBjdHgpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJldmFsaWRhdGUgdGFnc1xuICAgKiAtIEJ1aWxkIHRpbWU6IE5vdCBpbXBsZW1lbnRlZFxuICAgKiAtIFJ1bnRpbWU6IERlbGVnYXRlIHRvIFMzL0R5bmFtb0RCIGhhbmRsZXJcbiAgICovXG4gIGFzeW5jIHJldmFsaWRhdGVUYWcodGFnOiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBpZiAodGhpcy5pc0J1aWxkVGltZSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIENsZWFyIGZyb20gbWVtb3J5XG4gICAgaWYgKHRoaXMubWVtb3J5SGFuZGxlcikge1xuICAgICAgYXdhaXQgdGhpcy5tZW1vcnlIYW5kbGVyLnJldmFsaWRhdGVUYWcodGFnKTtcbiAgICB9XG5cbiAgICAvLyBDbGVhciBmcm9tIFMzL0R5bmFtb0RCXG4gICAgaWYgKHRoaXMuczNEeW5hbW9IYW5kbGVyKSB7XG4gICAgICBhd2FpdCB0aGlzLnMzRHluYW1vSGFuZGxlci5yZXZhbGlkYXRlVGFnKHRhZyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJlc2V0IHJlcXVlc3QgY2FjaGUgKGNhbGxlZCBiZXR3ZWVuIHJlcXVlc3RzKVxuICAgKi9cbiAgYXN5bmMgcmVzZXRSZXF1ZXN0Q2FjaGUoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgaWYgKHRoaXMubWVtb3J5SGFuZGxlcikge1xuICAgICAgYXdhaXQgdGhpcy5tZW1vcnlIYW5kbGVyLnJlc2V0UmVxdWVzdENhY2hlKCk7XG4gICAgfVxuICB9XG59XG4iXX0=
155
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2FjaGUtaGFuZGxlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9hZGFwdGVyL2NhY2hlLWhhbmRsZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFBQTs7Ozs7O0VBTUU7QUFDRixzREFBc0Q7QUFDdEQsa0RBQTZCO0FBYTdCLCtDQUF3QztBQUN4Qyx5RUFBbUU7QUFDbkUsaUVBQTREO0FBQzVELHlEQUFvRDtBQUNwRCx5REFBa0Q7QUFFbEQ7O0dBRUc7QUFDSCxNQUFxQixxQkFBcUI7SUFDeEM7Ozs7Ozs7OztPQVNHO0lBQ0ssTUFBTSxDQUFDLG1CQUFtQixHQUE4QixJQUFJLENBQUM7SUFDN0QsTUFBTSxDQUFDLHFCQUFxQixHQUEwQixJQUFJLENBQUM7SUFFbEQsV0FBVyxHQUFHLElBQUEsK0JBQVksR0FBRSxDQUFDO0lBQzdCLEtBQUssR0FBRyxJQUFBLGVBQVEsRUFBQyx1Q0FBdUMsQ0FBQyxDQUFDO0lBRTNFLDBCQUEwQjtJQUNsQixnQkFBZ0IsQ0FBeUI7SUFFakQsb0RBQW9EO0lBQzVDLGFBQWEsQ0FBc0I7SUFDbkMsZUFBZSxDQUFrQjtJQUV6QyxZQUFZLE9BQTRCO1FBQ3RDLElBQUksSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDO1lBQ3JCLElBQUksQ0FBQyxnQkFBZ0IsR0FBRyxJQUFJLGdEQUFxQixFQUFFLENBQUM7WUFDcEQsSUFBSSxDQUFDLEtBQUssQ0FDUiwrQkFBK0IsSUFBSSxDQUFDLGdCQUFnQixDQUFDLFdBQVcsRUFBRSxFQUFFLENBQ3JFLENBQUM7UUFDSixDQUFDO2FBQU0sQ0FBQztZQUNOLElBQUksQ0FBQyxlQUFlLEdBQUcscUJBQXFCLENBQUMscUJBQXFCO2dCQUNoRSxJQUFJLGlDQUFjLENBQUMsRUFBRSxPQUFPLEVBQUUsT0FBTyxFQUFFLENBQUMsQ0FBQztZQUMzQyxJQUFJLENBQUMsYUFBYSxHQUFHLHFCQUFxQixDQUFDLG1CQUFtQjtnQkFDNUQsSUFBSSx5Q0FBa0IsRUFB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S0FBSyxDQUFDLFNBQVMsSUFBSSxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLFFBQVEsS0FBSyxRQUFRLEVBQUUsQ0FBQyxDQUFDO1FBQzlELE1BQU0sSUFBSSxDQUFDLGFBQWEsQ0FBQyxHQUFHLENBQUMsUUFBUSxFQUFFLElBQUksQ0FBQyxDQUFDO1FBQzdDLE1BQU0sSUFBSSxDQUFDLGVBQWUsQ0FBQyxHQUFHLENBQUMsUUFBUSxFQUFFLElBQUksRUFBRSxHQUFHLENBQUMsQ0FBQztJQUN0RCxDQUFDO0lBRUQ7Ozs7T0FJRztJQUNILEtBQUssQ0FBQyxhQUFhLENBQ2pCLEdBQXNCLEVBQ3RCLFNBQStCO1FBRS9CLElBQUksSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDO1lBQ3JCLE9BQU87UUFDVCxDQUFDO1FBRUQsd0VBQXdFO1FBQ3hFLGtEQUFrRDtRQUNsRCxNQUFNLElBQUksQ0FBQyxlQUFlLENBQUMsYUFBYSxDQUFDLEdBQUcsRUFBRSxTQUFTLENBQUMsQ0FBQztJQUMzRCxDQUFDO0lBRUQ7Ozs7Ozs7T0FPRztJQUNILEtBQUssQ0FBQyxpQkFBaUIsS0FBbUIsQ0FBQzs7QUFoSzdDLHdDQWlLQyIsInNvdXJjZXNDb250ZW50IjpbIi8qXG4gIE5leHQuanMgQ3VzdG9tIENhY2hlIEhhbmRsZXIuIFNlZTogaHR0cHM6Ly9uZXh0anMub3JnL2RvY3MvYXBwL2FwaS1yZWZlcmVuY2UvbmV4dC1jb25maWctanMvaW5jcmVtZW50YWxDYWNoZUhhbmRsZXJQYXRoXG4gIFxuICBPcmNoZXN0cmF0b3IgY2FjaGUgaGFuZGxlciB0aGF0IGNvbmRpdGlvbmFsbHkgdXNlcyBkaWZmZXJlbnQgY2FjaGluZyBzdHJhdGVnaWVzOlxuICAtIEJ1aWxkIHRpbWU6IExvY2FsRmlsZUNhY2hlSGFuZGxlciBmb3IgcHJlLWNhY2hpbmdcbiAgLSBSdW50aW1lOiBNZW1vcnlDYWNoZUhhbmRsZXIgKGZhc3QpICsgUzNEeW5hbW9DYWNoZUhhbmRsZXIgKHBlcnNpc3RlbnQpXG4qL1xuLyogZXNsaW50LWRpc2FibGUgaW1wb3J0L25vLWV4dHJhbmVvdXMtZGVwZW5kZW5jaWVzICovXG5pbXBvcnQgZ2V0RGVidWcgZnJvbSBcImRlYnVnXCI7XG5pbXBvcnQge1xuICBDYWNoZUhhbmRsZXIsXG4gIENhY2hlSGFuZGxlclZhbHVlLFxuICBDYWNoZUhhbmRsZXJDb250ZXh0LFxufSBmcm9tIFwibmV4dC9kaXN0L3NlcnZlci9saWIvaW5jcmVtZW50YWwtY2FjaGVcIjtcbmltcG9ydCB0eXBlIHtcbiAgSW5jcmVtZW50YWxDYWNoZVZhbHVlLFxuICBHZXRJbmNyZW1lbnRhbEZldGNoQ2FjaGVDb250ZXh0LFxuICBHZXRJbmNyZW1lbnRhbFJlc3BvbnNlQ2FjaGVDb250ZXh0LFxuICBTZXRJbmNyZW1lbnRhbEZldGNoQ2FjaGVDb250ZXh0LFxuICBTZXRJbmNyZW1lbnRhbFJlc3BvbnNlQ2FjaGVDb250ZXh0LFxufSBmcm9tIFwibmV4dC9kaXN0L3NlcnZlci9yZXNwb25zZS1jYWNoZVwiO1xuaW1wb3J0IHsgZ2V0VGFncyB9IGZyb20gXCIuL2NhY2hlLXV0aWxzXCI7XG5pbXBvcnQgeyBMb2NhbEZpbGVDYWNoZUhhbmRsZXIgfSBmcm9tIFwiLi9sb2NhbC1maWxlLWNhY2hlLWhhbmRsZXJcIjtcbmltcG9ydCB7IE1lbW9yeUNhY2hlSGFuZGxlciB9IGZyb20gXCIuL21lbW9yeS1jYWNoZS1oYW5kbGVyXCI7XG5pbXBvcnQgeyBTM0NhY2hlSGFuZGxlciB9IGZyb20gXCIuL3MzLWNhY2hlLWhhbmRsZXJcIjtcbmltcG9ydCB7IGlzQnVpbGRQaGFzZSB9IGZyb20gXCIuL3VzZS1jYWNoZS1jb21tb25cIjtcblxuLyoqXG4gKiBPcmNoZXN0cmF0b3IgY2FjaGUgaGFuZGxlciB0aGF0IGNvbmRpdGlvbmFsbHkgaW5zdGFudGlhdGVzIGhhbmRsZXJzIGJhc2VkIG9uIGVudmlyb25tZW50XG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIENka05leHRqc0NhY2hlSGFuZGxlciBpbXBsZW1lbnRzIENhY2hlSGFuZGxlciB7XG4gIC8qKlxuICAgKiBTaGFyZWQgc2luZ2xldG9uIGhhbmRsZXJzIGZvciBydW50aW1lLlxuICAgKlxuICAgKiBOZXh0LmpzIGNyZWF0ZXMgbXVsdGlwbGUgY2FjaGUgaGFuZGxlciBpbnN0YW5jZXMgKG9uZSBlYWNoIGZvciBBUFBfUEFHRSwgQVBQX1JPVVRFLCBGRVRDSCwgZXRjKS5cbiAgICogVXNpbmcgc2luZ2xldG9uIHBhdHRlcm4gcHJvdmlkZXM6XG4gICAqIC0gU2luZ2xlIFMzIGNsaWVudCBjb25uZWN0aW9uIHBvb2wgc2hhcmVkIGFjcm9zcyBhbGwgY2FjaGUgdHlwZXNcbiAgICogLSBVbmlmaWVkIG1lbW9yeSBjYWNoZSBhY2Nlc3NpYmxlIGJ5IGFsbCBpbnN0YW5jZXMgKGNhY2hlIGhpdHMgYmVuZWZpdCBhbGwpXG4gICAqIC0gTG93ZXIgbWVtb3J5IGZvb3RwcmludCBhbmQgZmFzdGVyIGluaXRpYWxpemF0aW9uXG4gICAqIC0gU2FtZSBDYWNoZUhhbmRsZXJDb250ZXh0IGZvciBhbGwgaW5zdGFuY2VzLCBzbyBubyBjb25maWd1cmF0aW9uIGxvc3NcbiAgICovXG4gIHByaXZhdGUgc3RhdGljIHNoYXJlZE1lbW9yeUhhbmRsZXI6IE1lbW9yeUNhY2hlSGFuZGxlciB8IG51bGwgPSBudWxsO1xuICBwcml2YXRlIHN0YXRpYyBzaGFyZWRTM0R5bmFtb0hhbmRsZXI6IFMzQ2FjaGVIYW5kbGVyIHwgbnVsbCA9IG51bGw7XG5cbiAgcHJpdmF0ZSByZWFkb25seSBpc0J1aWxkVGltZSA9IGlzQnVpbGRQaGFzZSgpO1xuICBwcml2YXRlIHJlYWRvbmx5IGRlYnVnID0gZ2V0RGVidWcoXCJjZGstbmV4dGpzOmNhY2hlLWhhbmRsZXI6b3JjaGVzdHJhdG9yXCIpO1xuXG4gIC8vIFNldCBvbmx5IGF0IGJ1aWxkIHRpbWUuXG4gIHByaXZhdGUgbG9jYWxGaWxlSGFuZGxlciE6IExvY2FsRmlsZUNhY2hlSGFuZGxlcjtcblxuICAvLyBTZXQgb25seSBhdCBydW50aW1lLCBzaGFyZWQgYWNyb3NzIGFsbCBpbnN0YW5jZXMuXG4gIHByaXZhdGUgbWVtb3J5SGFuZGxlciE6IE1lbW9yeUNhY2hlSGFuZGxlcjtcbiAgcHJpdmF0ZSBzM0R5bmFtb0hhbmRsZXIhOiBTM0NhY2hlSGFuZGxlcjtcblxuICBjb25zdHJ1Y3RvcihvcHRpb25zOiBDYWNoZUhhbmRsZXJDb250ZXh0KSB7XG4gICAgaWYgKHRoaXMuaXNCdWlsZFRpbWUpIHtcbiAgICAgIHRoaXMubG9jYWxGaWxlSGFuZGxlciA9IG5ldyBMb2NhbEZpbGVDYWNoZUhhbmRsZXIoKTtcbiAgICAgIHRoaXMuZGVidWcoXG4gICAgICAgIGBCdWlsZC10aW1lIGNhY2hlIGRpcmVjdG9yeTogJHt0aGlzLmxvY2FsRmlsZUhhbmRsZXIuZ2V0Q2FjaGVEaXIoKX1gLFxuICAgICAgKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5zM0R5bmFtb0hhbmRsZXIgPSBDZGtOZXh0anNDYWNoZUhhbmRsZXIuc2hhcmVkUzNEeW5hbW9IYW5kbGVyID8/PVxuICAgICAgICBuZXcgUzNDYWNoZUhhbmRsZXIoeyBjb250ZXh0OiBvcHRpb25zIH0pO1xuICAgICAgdGhpcy5tZW1vcnlIYW5kbGVyID0gQ2RrTmV4dGpzQ2FjaGVIYW5kbGVyLnNoYXJlZE1lbW9yeUhhbmRsZXIgPz89XG4gICAgICAgIG5ldyBNZW1vcnlDYWNoZUhhbmRsZXIoKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogR2V0IGNhY2hlIGVudHJ5XG4gICAqIC0gQnVpbGQgdGltZTogTm90IGltcGxlbWVudGVkIChidWlsZCBkb2Vzbid0IHJlYWQgY2FjaGUpXG4gICAqIC0gUnVudGltZTogVHJ5IG1lbW9yeSBmaXJzdCwgdGhlbiBTMy9EeW5hbW9EQlxuICAgKi9cbiAgYXN5bmMgZ2V0KFxuICAgIGNhY2hlS2V5OiBzdHJpbmcsXG4gICAgY3R4OiBHZXRJbmNyZW1lbnRhbEZldGNoQ2FjaGVDb250ZXh0IHwgR2V0SW5jcmVtZW50YWxSZXNwb25zZUNhY2hlQ29udGV4dCxcbiAgKTogUHJvbWlzZTxDYWNoZUhhbmRsZXJWYWx1ZSB8IG51bGw+IHtcbiAgICBpZiAodGhpcy5pc0J1aWxkVGltZSkge1xuICAgICAgLy8gUmVhZHMgYmFjayB3aGF0IHRoaXMgYnVpbGQgd3JvdGUsIHdoaWNoIGBjYWNoZUNvbXBvbmVudHNgIHByZXJlbmRlcmluZ1xuICAgICAgLy8gcmVxdWlyZXM7IHNlZSB7QGxpbmsgTG9jYWxGaWxlQ2FjaGVIYW5kbGVyLmdldH0uXG4gICAgICByZXR1cm4gdGhpcy5sb2NhbEZpbGVIYW5kbGVyLmdldChjYWNoZUtleSk7XG4gICAgfVxuXG4gICAgLy8gUnVudGltZTogdHJ5IG1lbW9yeSBmaXJzdFxuICAgIGNvbnN0IG1lbW9yeVJlc3VsdCA9IGF3YWl0IHRoaXMubWVtb3J5SGFuZGxlci5nZXQoY2FjaGVLZXkpO1xuICAgIC8vIEEgbWVtb3J5IGhpdCBpcyBjaGVja2VkIGFnYWluc3QgdGhlIHNhbWUgdGFnIG1hcmtlcnMgYW4gUzMgcmVhZCBpcy5cbiAgICAvLyBgcmV2YWxpZGF0ZVRhZ2AgY2FuIG9ubHkgY2xlYXIgdGhlIG1lbW9yeSBvZiB0aGUgaW5zdGFuY2UgdGhhdCByYW4gaXQsXG4gICAgLy8gc28gc2tpcHBpbmcgdGhlIGNoZWNrIGxlZnQgZXZlcnkgb3RoZXIgaW5zdGFuY2UgYW5zd2VyaW5nIGZyb20gbWVtb3J5XG4gICAgLy8gZm9yIHRoZSB3aG9sZSBtZW1vcnkgVFRMIC0gYW5kIENsb3VkRnJvbnQsIHdob3NlIGNvcHkgdGhhdFxuICAgIC8vIGByZXZhbGlkYXRlVGFnYCBoYWQganVzdCBpbnZhbGlkYXRlZCwgY2FjaGVkIHRoZSBzdGFsZSBwYWdlIGFnYWluLlxuICAgIC8vIFRoZSBjaGVjayBpcyBvbmUgRHluYW1vREIgYEJhdGNoR2V0SXRlbWA7IHdoYXQgdGhlIG1lbW9yeSBsYXllciBzdGlsbFxuICAgIC8vIHNhdmVzIGlzIHRoZSBTMyByZWFkIGFuZCB0aGUgcGFyc2Ugb2YgdGhlIGJvZHkuIEEgcmV2YWxpZGF0ZWQgZW50cnkgaXNcbiAgICAvLyBkcm9wcGVkIGFuZCByZWFkIGZyb20gUzMsIHdoaWNoIGhhbmRzIGl0IGJhY2sgZXhwaXJlZCBvciBhcyBhIG1pc3MuXG4gICAgaWYgKFxuICAgICAgbWVtb3J5UmVzdWx0ICYmXG4gICAgICAoYXdhaXQgdGhpcy5zM0R5bmFtb0hhbmRsZXIuaXNSZXZhbGlkYXRlZChcbiAgICAgICAge1xuICAgICAgICAgIGxhc3RNb2RpZmllZDogbWVtb3J5UmVzdWx0Lmxhc3RNb2RpZmllZCxcbiAgICAgICAgICB2YWx1ZTogbWVtb3J5UmVzdWx0LnZhbHVlLFxuICAgICAgICB9LFxuICAgICAgICBjdHgsXG4gICAgICAgIGNhY2hlS2V5LFxuICAgICAgKSlcbiAgICApIHtcbiAgICAgIHRoaXMuZGVidWcoYE1lbW9yeSBjYWNoZSBSRVZBTElEQVRFRDogJHtjYWNoZUtleX1gKTtcbiAgICAgIGF3YWl0IHRoaXMubWVtb3J5SGFuZGxlci5zZXQoY2FjaGVLZXksIG51bGwpO1xuICAgIH0gZWxzZSBpZiAobWVtb3J5UmVzdWx0KSB7XG4gICAgICB0aGlzLmRlYnVnKGBNZW1vcnkgY2FjaGUgSElUOiAke2NhY2hlS2V5fWApO1xuICAgICAgcmV0dXJuIG1lbW9yeVJlc3VsdDtcbiAgICB9XG5cbiAgICAvLyBNZW1vcnkgbWlzcyAtIHRyeSBTMy9EeW5hbW9EQlxuICAgIGNvbnN0IHMzUmVzdWx0ID0gYXdhaXQgdGhpcy5zM0R5bmFtb0hhbmRsZXIuZ2V0KGNhY2hlS2V5LCBjdHgpO1xuICAgIGlmIChzM1Jlc3VsdCkge1xuICAgICAgdGhpcy5kZWJ1ZyhgUzMgY2FjaGUgSElUOiAke2NhY2hlS2V5fWApO1xuICAgICAgLy8gUHJvbW90ZWQgd2l0aCB0aGUgUzMgZW50cnkncyBvd24gYGxhc3RNb2RpZmllZGAsIG5vdCB0aGUgdGltZSBvZiB0aGVcbiAgICAgIC8vIGNvcHk6IE5leHQuanMgYWdlcyB0aGUgZW50cnkgZnJvbSBpdCBmb3IgdGltZS1iYXNlZCByZXZhbGlkYXRpb24sIGFuZFxuICAgICAgLy8gdGhlIHRhZyBtYXJrZXJzIGFyZSBjb21wYXJlZCBhZ2FpbnN0IGl0IHRvby4gU3RhbXBpbmcgYERhdGUubm93KClgXG4gICAgICAvLyBtYWRlIGFuIGVudHJ5IHRoYXQgd2FzIGR1ZSBmb3IgcmVnZW5lcmF0aW9uIGxvb2sgZnJlc2hseSByZW5kZXJlZCxcbiAgICAgIC8vIGFuZCBvbmUgYSBzb2Z0IGByZXZhbGlkYXRlVGFnYCBoYWQgbWFkZSBzdGFsZSBsb29rIG5ld2VyIHRoYW4gdGhlXG4gICAgICAvLyBzdGFsZSBtYXJrLCBzbyBtZW1vcnkgaGl0cyBzZXJ2ZWQgaXQgYXMgZnJlc2ggZm9yIHRoZSB3aG9sZSBtZW1vcnlcbiAgICAgIC8vIFRUTC4gQW4gZW50cnkgYSB0YWcgcmV2YWxpZGF0aW9uIGV4cGlyZWQgKGBsYXN0TW9kaWZpZWQ6IC0xYCkgaXMgbm90XG4gICAgICAvLyBjb3BpZWQgYXQgYWxsOiB0aGUgcmUtcmVuZGVyIGl0IGFza3MgZm9yIHdyaXRlcyB0aGUgZnJlc2ggZW50cnkgdG9cbiAgICAgIC8vIGJvdGggbGF5ZXJzLlxuICAgICAgaWYgKHMzUmVzdWx0Lmxhc3RNb2RpZmllZCAhPT0gLTEpIHtcbiAgICAgICAgYXdhaXQgdGhpcy5tZW1vcnlIYW5kbGVyLnNldChcbiAgICAgICAgICBjYWNoZUtleSxcbiAgICAgICAgICBzM1Jlc3VsdC52YWx1ZSxcbiAgICAgICAgICBzM1Jlc3VsdC5sYXN0TW9kaWZpZWQsXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgICByZXR1cm4gczNSZXN1bHQ7XG4gICAgfVxuXG4gICAgdGhpcy5kZWJ1ZyhgQ2FjaGUgTUlTUzogJHtjYWNoZUtleX1gKTtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIC8qKlxuICAgKiBTZXQgY2FjaGUgZW50cnlcbiAgICogLSBCdWlsZCB0aW1lOiBXcml0ZSB0byBsb2NhbCBmaWxlIGNhY2hlIG9ubHkgKG9yIGRlbGV0ZSBpZiBkYXRhIGlzIG51bGwpXG4gICAqIC0gUnVudGltZTogV3JpdGUgdG8gYm90aCBtZW1vcnkgYW5kIFMzL0R5bmFtb0RCIChvciBkZWxldGUgaWYgZGF0YSBpcyBudWxsKVxuICAgKi9cbiAgYXN5bmMgc2V0KFxuICAgIGNhY2hlS2V5OiBzdHJpbmcsXG4gICAgZGF0YTogSW5jcmVtZW50YWxDYWNoZVZhbHVlIHwgbnVsbCxcbiAgICBjdHg6IFNldEluY3JlbWVudGFsRmV0Y2hDYWNoZUNvbnRleHQgfCBTZXRJbmNyZW1lbnRhbFJlc3BvbnNlQ2FjaGVDb250ZXh0LFxuICApOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBpZiAodGhpcy5pc0J1aWxkVGltZSkge1xuICAgICAgaWYgKGRhdGEpIHtcbiAgICAgICAgYXdhaXQgdGhpcy5sb2NhbEZpbGVIYW5kbGVyLnNldChjYWNoZUtleSwgZGF0YSwgZ2V0VGFncyhjdHgpKTtcbiAgICAgICAgdGhpcy5kZWJ1ZyhgQnVpbGQgY2FjaGUgd3JpdGU6ICR7Y2FjaGVLZXl9YCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAvLyBEZWxldGUgbm90IGltcGxlbWVudGVkIGZvciBsb2NhbCBmaWxlIGNhY2hlIChidWlsZC10aW1lIG9ubHkgY3JlYXRlcyBmaWxlcylcbiAgICAgICAgdGhpcy5kZWJ1ZyhgQnVpbGQgY2FjaGUgZGVsZXRlIGlnbm9yZWQ6ICR7Y2FjaGVLZXl9YCk7XG4gICAgICB9XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIC8vIFJ1bnRpbWU6IGJvdGggbGF5ZXJzLCB3aGVyZSBgbnVsbGAgaXMgYSBkZWxldGUuXG4gICAgdGhpcy5kZWJ1ZyhgQ2FjaGUgJHtkYXRhID8gXCJ3cml0ZVwiIDogXCJkZWxldGVcIn06ICR7Y2FjaGVLZXl9YCk7XG4gICAgYXdhaXQgdGhpcy5tZW1vcnlIYW5kbGVyLnNldChjYWNoZUtleSwgZGF0YSk7XG4gICAgYXdhaXQgdGhpcy5zM0R5bmFtb0hhbmRsZXIuc2V0KGNhY2hlS2V5LCBkYXRhLCBjdHgpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldmFsaWRhdGUgdGFnc1xuICAgKiAtIEJ1aWxkIHRpbWU6IE5vdCBpbXBsZW1lbnRlZFxuICAgKiAtIFJ1bnRpbWU6IERlbGVnYXRlIHRvIFMzL0R5bmFtb0RCIGhhbmRsZXJcbiAgICovXG4gIGFzeW5jIHJldmFsaWRhdGVUYWcoXG4gICAgdGFnOiBzdHJpbmcgfCBzdHJpbmdbXSxcbiAgICBkdXJhdGlvbnM/OiB7IGV4cGlyZT86IG51bWJlciB9LFxuICApOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBpZiAodGhpcy5pc0J1aWxkVGltZSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIE1lbW9yeSBoaXRzIGFyZSBjaGVja2VkIGFnYWluc3QgdGhlIHNhbWUgbWFya2VycyAoc2VlIGBnZXRgKSwgc28gb25seVxuICAgIC8vIHRoZSBTMy9EeW5hbW9EQiBoYW5kbGVyIGhhcyBhbnl0aGluZyB0byByZWNvcmQuXG4gICAgYXdhaXQgdGhpcy5zM0R5bmFtb0hhbmRsZXIucmV2YWxpZGF0ZVRhZyh0YWcsIGR1cmF0aW9ucyk7XG4gIH1cblxuICAvKipcbiAgICogRGVsaWJlcmF0ZWx5IGEgbm8tb3AuIE5leHQuanMgY2FsbHMgYHJlc2V0UmVxdWVzdENhY2hlYCBhdCB0aGUgc3RhcnQgb2ZcbiAgICogZXZlcnkgcmVxdWVzdCAoYGJhc2Utc2VydmVyYCwgYGFwcC1wYWdlYCwgYGFwcC1yb3V0ZWApLCBhbmQgaXRzIG93blxuICAgKiBgRmlsZVN5c3RlbUNhY2hlYCAtIHdob3NlIExSVSBpcyBzaGFyZWQgYWNyb3NzIHJlcXVlc3RzIHRoZSBzYW1lIHdheSB0aGVcbiAgICogbWVtb3J5IGxheWVyIGlzIC0gbGVhdmVzIGl0IGVtcHR5OiB0aGUgaG9vayBpcyBmb3Igc3RhdGUgc2NvcGVkIHRvIG9uZVxuICAgKiByZXF1ZXN0LCBhbmQgbm90aGluZyBoZXJlIGlzLiBDbGVhcmluZyB0aGUgbWVtb3J5IGxheWVyIGluIGl0IG1lYW50IG5vXG4gICAqIGVudHJ5IGV2ZXIgc3Vydml2ZWQgdG8gYSBzZWNvbmQgcmVxdWVzdCwgc28gZXZlcnkgcmVhZCB3ZW50IHRvIFMzLlxuICAgKi9cbiAgYXN5bmMgcmVzZXRSZXF1ZXN0Q2FjaGUoKTogUHJvbWlzZTx2b2lkPiB7fVxufVxuIl19