@pipeline-builder/api-server 4.4.3 → 4.4.4

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.
@@ -156,6 +156,76 @@ export function getIdempotencyStore() {
156
156
  * pending reservation and answered 409.
157
157
  */
158
158
  const IDEMPOTENCY_HANDLED = Symbol('pipeline-builder.idempotency.handled');
159
+ /**
160
+ * `res.locals` key set to `true` when the response was REPLAYED from the
161
+ * idempotency cache instead of running the handler. A replay did no work, so
162
+ * anything that bills per successful response (`meterQuotaOnSuccess`) must skip
163
+ * it — the original request already paid. Use {@link isIdempotentReplay}.
164
+ */
165
+ export const IDEMPOTENT_REPLAY_LOCAL = 'idempotentReplay';
166
+ /** True when `res` is a replay of a cached idempotent response. */
167
+ export function isIdempotentReplay(res) {
168
+ return res.locals?.[IDEMPOTENT_REPLAY_LOCAL] === true;
169
+ }
170
+ /**
171
+ * The store key a request's `Idempotency-Key` is recorded under, or `undefined`
172
+ * when the request has no org to namespace it by (unauthenticated — skipped).
173
+ *
174
+ * Namespace by orgId to prevent cross-org cache collisions. Prefer the VERIFIED
175
+ * auth org (`req.user`, populated by requireAuth after signature verification)
176
+ * over `req.context.identity`, which some services populate pre-auth from an
177
+ * UNVERIFIED token peek — namespacing a mutation's replay cache on an
178
+ * unverified, caller-influenced org id would be unsafe.
179
+ *
180
+ * Namespace the stored key by (method, route, org, body) so an Idempotency-Key
181
+ * is scoped to ONE specific endpoint+payload. Reusing a single key across two
182
+ * routes (e.g. POST /pipelines then POST /plugins) must not replay the first
183
+ * endpoint's 2xx for the second — the store is a module-level singleton shared
184
+ * by every route. Folding in method + route path + a body fingerprint only makes
185
+ * keys MORE specific, so there is no cross-contamination risk. Also namespace by
186
+ * the VERIFIED user. `Idempotency-Key` is chosen by the client, so two users in
187
+ * the same org sending the same body with the same key collided: the second
188
+ * user's mutation was SKIPPED and they were served the first user's cached
189
+ * response. Falls back to the org alone only when there is no verified subject
190
+ * (service principals carry one).
191
+ */
192
+ function idempotencyStoreKey(req, key) {
193
+ const orgId = req.user?.organizationId || req.context?.identity?.orgId;
194
+ if (!orgId)
195
+ return undefined;
196
+ const sub = req.user?.sub;
197
+ const routePath = (req.baseUrl ?? '') + (req.route?.path ?? req.path ?? '');
198
+ return `${req.method}:${routePath}:${orgId}:${sub ?? '-'}:${bodyFingerprint(req.body)}:${key}`;
199
+ }
200
+ /** Methods the idempotency middleware applies to. */
201
+ const IDEMPOTENT_METHODS = ['POST', 'PUT', 'DELETE'];
202
+ /**
203
+ * True when this request is a RETRY of an idempotent mutation whose original
204
+ * has COMPLETED (a cached 2xx on record) — i.e. the idempotency middleware will
205
+ * replay it without running the handler. The apiCalls check uses it to skip
206
+ * the gate for such a retry: the replay does no work and is never metered, so
207
+ * refusing it at the quota gate (which runs in requireAuth, BEFORE replay
208
+ * detection in most chains) would 429 a client for re-reading its own result.
209
+ *
210
+ * One store read, and only for a mutation carrying `Idempotency-Key`; every
211
+ * failure answers `false` (the gate then runs as usual). Uses the process-wide
212
+ * store — the same one the route chains' middleware resolves.
213
+ */
214
+ export async function hasCompletedIdempotentResponse(req) {
215
+ const key = req.headers?.['idempotency-key'];
216
+ if (typeof key !== 'string' || !key || !IDEMPOTENT_METHODS.includes(req.method))
217
+ return false;
218
+ const fullKey = idempotencyStoreKey(req, key);
219
+ if (!fullKey)
220
+ return false;
221
+ try {
222
+ const cached = await defaultStore.get(fullKey);
223
+ return !!cached && !cached.pending;
224
+ }
225
+ catch {
226
+ return false;
227
+ }
228
+ }
159
229
  /**
160
230
  * Middleware that supports idempotency keys for POST/PUT/DELETE mutations.
161
231
  *
@@ -185,35 +255,16 @@ export function idempotencyMiddleware(options = {}) {
185
255
  if (!key)
186
256
  return next();
187
257
  // Only apply to mutation methods
188
- if (!['POST', 'PUT', 'DELETE'].includes(req.method))
258
+ if (!IDEMPOTENT_METHODS.includes(req.method))
189
259
  return next();
190
260
  // One pass per request: a later stacked chain must not re-check the key.
191
261
  const marked = req;
192
262
  if (marked[IDEMPOTENCY_HANDLED])
193
263
  return next();
194
- // Namespace by orgId to prevent cross-org cache collisions. Prefer the
195
- // VERIFIED auth org (`req.user`, populated by requireAuth after signature
196
- // verification) over `req.context.identity`, which some services populate
197
- // pre-auth from an UNVERIFIED token peek — namespacing a mutation's replay
198
- // cache on an unverified, caller-influenced org id would be unsafe.
199
- const orgId = req.user?.organizationId || req.context?.identity?.orgId;
200
- if (!orgId)
264
+ const fullKey = idempotencyStoreKey(req, key);
265
+ if (!fullKey)
201
266
  return next(); // skip idempotency for unauthenticated requests
202
267
  marked[IDEMPOTENCY_HANDLED] = true;
203
- // Namespace the stored key by (method, route, org, body) so an Idempotency-Key
204
- // is scoped to ONE specific endpoint+payload. Reusing a single key across two
205
- // routes (e.g. POST /pipelines then POST /plugins) must not replay the
206
- // first endpoint's 2xx for the second — the store is a module-level singleton
207
- // shared by every route. Folding in method + route path + a body fingerprint
208
- // only makes keys MORE specific, so there is no cross-contamination risk.
209
- // Also namespace by the VERIFIED user. `Idempotency-Key` is chosen by the
210
- // client, so two users in the same org sending the same body with the same
211
- // key collided: the second user's mutation was SKIPPED and they were served
212
- // the first user's cached response. Falls back to the org alone only when
213
- // there is no verified subject (service principals carry one).
214
- const sub = req.user?.sub;
215
- const routePath = (req.baseUrl ?? '') + (req.route?.path ?? req.path ?? '');
216
- const fullKey = `${req.method}:${routePath}:${orgId}:${sub ?? '-'}:${bodyFingerprint(req.body)}:${key}`;
217
268
  /** Reject a duplicate whose original is still in-flight. */
218
269
  const sendInProgress = () => {
219
270
  res.setHeader('Retry-After', '1');
@@ -223,6 +274,7 @@ export function idempotencyMiddleware(options = {}) {
223
274
  if (cached && !cached.pending) {
224
275
  // Completed response on record → replay it.
225
276
  logger.debug('Idempotent request replayed', { key: fullKey });
277
+ (res.locals ??= {})[IDEMPOTENT_REPLAY_LOCAL] = true;
226
278
  res.setHeader('X-Idempotent-Replayed', 'true');
227
279
  res.status(cached.statusCode).json(cached.body);
228
280
  return;
@@ -345,4 +397,4 @@ export function idempotencyMiddleware(options = {}) {
345
397
  });
346
398
  };
347
399
  }
348
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaWRlbXBvdGVuY3ktbWlkZGxld2FyZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9hcGkvaWRlbXBvdGVuY3ktbWlkZGxld2FyZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSwrQ0FBK0M7QUFDL0Msc0NBQXNDO0FBRXRDLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxRQUFRLENBQUM7QUFDcEMsT0FBTyxFQUFFLFlBQVksRUFBRSxTQUFTLEVBQUUsU0FBUyxFQUFFLG9CQUFvQixFQUFFLFlBQVksRUFBRSxlQUFlLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQUNySSxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0saUNBQWlDLENBQUM7QUFHaEUsTUFBTSxNQUFNLEdBQUcsWUFBWSxDQUFDLGFBQWEsQ0FBQyxDQUFDO0FBRTNDOzs7OztHQUtHO0FBQ0gsU0FBUyxlQUFlLENBQUMsSUFBYTtJQUNwQyxJQUFJLElBQUksS0FBSyxTQUFTLElBQUksSUFBSSxLQUFLLElBQUk7UUFBRSxPQUFPLEdBQUcsQ0FBQztJQUNwRCxJQUFJLE9BQU8sSUFBSSxLQUFLLFFBQVEsSUFBSSxNQUFNLENBQUMsSUFBSSxDQUFDLElBQWMsQ0FBQyxDQUFDLE1BQU0sS0FBSyxDQUFDO1FBQUUsT0FBTyxHQUFHLENBQUM7SUFDckYsSUFBSSxDQUFDO1FBQ0gsT0FBTyxVQUFVLENBQUMsUUFBUSxDQUFDLENBQUMsTUFBTSxDQUFDLGVBQWUsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDO0lBQ3ZGLENBQUM7SUFBQyxNQUFNLENBQUM7UUFDUCwwRUFBMEU7UUFDMUUsdUVBQXVFO1FBQ3ZFLE9BQU8sR0FBRyxDQUFDO0lBQ2IsQ0FBQztBQUNILENBQUM7QUFpQ0QsMEVBQTBFO0FBQzFFLE1BQU0sVUFBVSxpQkFBaUI7SUFDL0IsTUFBTSxHQUFHLEdBQUcsSUFBSSxHQUFHLEVBQXVCLENBQUM7SUFDM0MsTUFBTSxZQUFZLEdBQUcsV0FBVyxDQUFDLEdBQUcsRUFBRTtRQUNwQyxNQUFNLEdBQUcsR0FBRyxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUM7UUFDdkIsS0FBSyxNQUFNLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxJQUFJLEdBQUcsRUFBRSxDQUFDO1lBQ3pCLElBQUksR0FBRyxHQUFHLENBQUMsQ0FBQyxTQUFTO2dCQUFFLEdBQUcsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDdkMsQ0FBQztJQUNILENBQUMsRUFBRSxhQUFhLENBQUMsK0JBQStCLENBQUMsQ0FBQztJQUNsRCxZQUFZLENBQUMsS0FBSyxFQUFFLENBQUM7SUFFckIsMEVBQTBFO0lBQzFFLE1BQU0sSUFBSSxHQUFHLENBQUMsR0FBVyxFQUFzQixFQUFFO1FBQy9DLE1BQU0sS0FBSyxHQUFHLEdBQUcsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDM0IsSUFBSSxDQUFDLEtBQUs7WUFBRSxPQUFPLElBQUksQ0FBQztRQUN4QixJQUFJLElBQUksQ0FBQyxHQUFHLEVBQUUsR0FBRyxLQUFLLENBQUMsU0FBUyxFQUFFLENBQUM7WUFDakMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQztZQUNoQixPQUFPLElBQUksQ0FBQztRQUNkLENBQUM7UUFDRCxPQUFPLEtBQUssQ0FBQztJQUNmLENBQUMsQ0FBQztJQUNGOzs7OztPQUtHO0lBQ0gsTUFBTSxXQUFXLEdBQUcsQ0FBQyxHQUFXLEVBQVEsRUFBRTtRQUN4QyxJQUFJLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsSUFBSSxHQUFHLENBQUMsSUFBSSxJQUFJLGFBQWEsQ0FBQywwQkFBMEIsRUFBRSxDQUFDO1lBQzFFLE1BQU0sTUFBTSxHQUFHLEdBQUcsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxLQUFLLENBQUM7WUFDdkMsSUFBSSxNQUFNLEtBQUssU0FBUztnQkFBRSxHQUFHLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQy9DLENBQUM7SUFDSCxDQUFDLENBQUM7SUFDRixPQUFPO1FBQ0wsS0FBSyxDQUFDLEdBQUcsQ0FBQyxHQUFHO1lBQ1gsT0FBTyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDbkIsQ0FBQztRQUNELEtBQUssQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLEtBQUs7WUFDbEIsV0FBVyxDQUFDLEdBQUcsQ0FBQyxDQUFDO1lBQ2pCLEdBQUcsQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLEtBQUssQ0FBQyxDQUFDO1FBQ3RCLENBQUM7UUFDRCxLQUFLLENBQUMsT0FBTyxDQUFDLEdBQUcsRUFBRSxLQUFLO1lBQ3RCLDJFQUEyRTtZQUMzRSxzRUFBc0U7WUFDdEUsSUFBSSxJQUFJLENBQUMsR0FBRyxDQUFDO2dCQUFFLE9BQU8sS0FBSyxDQUFDO1lBQzVCLFdBQVcsQ0FBQyxHQUFHLENBQUMsQ0FBQztZQUNqQixHQUFHLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBRSxLQUFLLENBQUMsQ0FBQztZQUNwQixPQUFPLElBQUksQ0FBQztRQUNkLENBQUM7UUFDRCxLQUFLLENBQUMsTUFBTSxDQUFDLEdBQUc7WUFDZCxHQUFHLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQ2xCLENBQUM7S0FDRixDQUFDO0FBQ0osQ0FBQztBQWFELE1BQU0sZ0JBQWdCLEdBQUcsT0FBTyxDQUFDO0FBRWpDOzs7Ozs7O0dBT0c7QUFDSCxNQUFNLFVBQVUsMkJBQTJCLENBQUMsS0FBNkI7SUFDdkUsTUFBTSxDQUFDLEdBQUcsQ0FBQyxHQUFXLEVBQVUsRUFBRSxDQUFDLEdBQUcsZ0JBQWdCLEdBQUcsR0FBRyxFQUFFLENBQUM7SUFDL0QsT0FBTztRQUNMLEtBQUssQ0FBQyxHQUFHLENBQUMsR0FBRztZQUNYLE1BQU0sR0FBRyxHQUFHLE1BQU0sS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztZQUNwQyxJQUFJLENBQUMsR0FBRztnQkFBRSxPQUFPLElBQUksQ0FBQztZQUN0QixJQUFJLENBQUM7Z0JBQ0gsT0FBTyxJQUFJLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBZ0IsQ0FBQztZQUN4QyxDQUFDO1lBQUMsTUFBTSxDQUFDO2dCQUNQLGlFQUFpRTtnQkFDakUsT0FBTyxJQUFJLENBQUM7WUFDZCxDQUFDO1FBQ0gsQ0FBQztRQUNELEtBQUssQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLEtBQUssRUFBRSxVQUFVO1lBQzlCLE1BQU0sS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsRUFBRSxJQUFJLEVBQUUsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsVUFBVSxDQUFDLENBQUMsQ0FBQztRQUNoRixDQUFDO1FBQ0QsS0FBSyxDQUFDLE9BQU8sQ0FBQyxHQUFHLEVBQUUsS0FBSyxFQUFFLFVBQVU7WUFDbEMseUVBQXlFO1lBQ3pFLE1BQU0sR0FBRyxHQUFHLE1BQU0sS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsRUFBRSxJQUFJLEVBQUUsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsVUFBVSxDQUFDLEVBQUUsSUFBSSxDQUFDLENBQUM7WUFDaEcsT0FBTyxHQUFHLEtBQUssSUFBSSxDQUFDO1FBQ3RCLENBQUM7UUFDRCxLQUFLLENBQUMsTUFBTSxDQUFDLEdBQUc7WUFDZCxNQUFNLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7UUFDMUIsQ0FBQztLQUNGLENBQUM7QUFDSixDQUFDO0FBRUQ7Ozs7O0dBS0c7QUFDSCxNQUFNLFVBQVUsOEJBQThCO0lBQzVDLE1BQU0sTUFBTSxHQUFHLG9CQUFvQixDQUF5QixhQUFhLENBQUMsQ0FBQztJQUMzRSxJQUFJLENBQUMsTUFBTTtRQUFFLE9BQU8sSUFBSSxDQUFDO0lBQ3pCLE1BQU0sQ0FBQyxJQUFJLENBQUMscUNBQXFDLENBQUMsQ0FBQztJQUNuRCxPQUFPLDJCQUEyQixDQUFDLE1BQU0sQ0FBQyxDQUFDO0FBQzdDLENBQUM7QUFFRCxNQUFNLFdBQVcsR0FBRyxpQkFBaUIsRUFBRSxDQUFDO0FBRXhDOzs7Ozs7R0FNRztBQUNILElBQUksWUFBWSxHQUFxQixXQUFXLENBQUM7QUFFakQsMkVBQTJFO0FBQzNFLE1BQU0sVUFBVSxtQkFBbUIsQ0FBQyxLQUF1QjtJQUN6RCxZQUFZLEdBQUcsS0FBSyxDQUFDO0FBQ3ZCLENBQUM7QUFFRCw0RUFBNEU7QUFDNUUsTUFBTSxVQUFVLG1CQUFtQjtJQUNqQyxPQUFPLFlBQVksQ0FBQztBQUN0QixDQUFDO0FBRUQ7Ozs7OztHQU1HO0FBQ0gsTUFBTSxtQkFBbUIsR0FBRyxNQUFNLENBQUMsc0NBQXNDLENBQUMsQ0FBQztBQVEzRTs7Ozs7Ozs7OztHQVVHO0FBQ0gsTUFBTSxVQUFVLHFCQUFxQixDQUFDLE9BQU8sR0FBaUMsRUFBRTtJQUM5RSw2RUFBNkU7SUFDN0UsNkVBQTZFO0lBQzdFLCtCQUErQjtJQUMvQixNQUFNLGFBQWEsR0FBRyxPQUFPLENBQUMsS0FBSyxDQUFDO0lBQ3BDLE1BQU0sS0FBSyxHQUFHLGFBQWEsQ0FBQyxrQkFBa0IsQ0FBQztJQUMvQyxNQUFNLE1BQU0sR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLEtBQUssR0FBRyxJQUFJLENBQUMsQ0FBQztJQUN4Qyx1RUFBdUU7SUFDdkUsNEVBQTRFO0lBQzVFLDREQUE0RDtJQUM1RCxNQUFNLFlBQVksR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLGFBQWEsQ0FBQywwQkFBMEIsRUFBRSxLQUFLLENBQUMsQ0FBQztJQUMvRSxNQUFNLGFBQWEsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxJQUFJLENBQUMsS0FBSyxDQUFDLFlBQVksR0FBRyxJQUFJLENBQUMsQ0FBQyxDQUFDO0lBRW5FLE9BQU8sQ0FBQyxHQUFZLEVBQUUsR0FBYSxFQUFFLElBQWtCLEVBQUUsRUFBRTtRQUN6RCxNQUFNLEtBQUssR0FBRyxhQUFhLElBQUksWUFBWSxDQUFDO1FBQzVDLE1BQU0sR0FBRyxHQUFHLEdBQUcsQ0FBQyxPQUFPLENBQUMsaUJBQWlCLENBQXVCLENBQUM7UUFDakUsSUFBSSxDQUFDLEdBQUc7WUFBRSxPQUFPLElBQUksRUFBRSxDQUFDO1FBRXhCLGlDQUFpQztRQUNqQyxJQUFJLENBQUMsQ0FBQyxNQUFNLEVBQUUsS0FBSyxFQUFFLFFBQVEsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDO1lBQUUsT0FBTyxJQUFJLEVBQUUsQ0FBQztRQUVuRSx5RUFBeUU7UUFDekUsTUFBTSxNQUFNLEdBQUcsR0FBaUQsQ0FBQztRQUNqRSxJQUFJLE1BQU0sQ0FBQyxtQkFBbUIsQ0FBQztZQUFFLE9BQU8sSUFBSSxFQUFFLENBQUM7UUFFL0MsdUVBQXVFO1FBQ3ZFLDBFQUEwRTtRQUMxRSwwRUFBMEU7UUFDMUUsMkVBQTJFO1FBQzNFLG9FQUFvRTtRQUNwRSxNQUFNLEtBQUssR0FBRyxHQUFHLENBQUMsSUFBSSxFQUFFLGNBQWMsSUFBSSxHQUFHLENBQUMsT0FBTyxFQUFFLFFBQVEsRUFBRSxLQUFLLENBQUM7UUFDdkUsSUFBSSxDQUFDLEtBQUs7WUFBRSxPQUFPLElBQUksRUFBRSxDQUFDLENBQUMsZ0RBQWdEO1FBQzNFLE1BQU0sQ0FBQyxtQkFBbUIsQ0FBQyxHQUFHLElBQUksQ0FBQztRQUVuQywrRUFBK0U7UUFDL0UsOEVBQThFO1FBQzlFLHVFQUF1RTtRQUN2RSw4RUFBOEU7UUFDOUUsNkVBQTZFO1FBQzdFLDBFQUEwRTtRQUMxRSwwRUFBMEU7UUFDMUUsMkVBQTJFO1FBQzNFLDRFQUE0RTtRQUM1RSwwRUFBMEU7UUFDMUUsK0RBQStEO1FBQy9ELE1BQU0sR0FBRyxHQUFHLEdBQUcsQ0FBQyxJQUFJLEVBQUUsR0FBRyxDQUFDO1FBQzFCLE1BQU0sU0FBUyxHQUFHLENBQUMsR0FBRyxDQUFDLE9BQU8sSUFBSSxFQUFFLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxLQUFLLEVBQUUsSUFBSSxJQUFJLEdBQUcsQ0FBQyxJQUFJLElBQUksRUFBRSxDQUFDLENBQUM7UUFDNUUsTUFBTSxPQUFPLEdBQUcsR0FBRyxHQUFHLENBQUMsTUFBTSxJQUFJLFNBQVMsSUFBSSxLQUFLLElBQUksR0FBRyxJQUFJLEdBQUcsSUFBSSxlQUFlLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxJQUFJLEdBQUcsRUFBRSxDQUFDO1FBRXhHLDREQUE0RDtRQUM1RCxNQUFNLGNBQWMsR0FBRyxHQUFTLEVBQUU7WUFDaEMsR0FBRyxDQUFDLFNBQVMsQ0FBQyxhQUFhLEVBQUUsR0FBRyxDQUFDLENBQUM7WUFDbEMsU0FBUyxDQUFDLEdBQUcsRUFBRSxHQUFHLEVBQUUsZ0VBQWdFLEVBQUUsU0FBUyxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQzVHLENBQUMsQ0FBQztRQUVGLEtBQUssQ0FBQyxHQUFHLENBQUMsT0FBTyxDQUFDLENBQUMsSUFBSSxDQUFDLEtBQUssRUFBRSxNQUFNLEVBQUUsRUFBRTtZQUN2QyxJQUFJLE1BQU0sSUFBSSxDQUFDLE1BQU0sQ0FBQyxPQUFPLEVBQUUsQ0FBQztnQkFDOUIsNENBQTRDO2dCQUM1QyxNQUFNLENBQUMsS0FBSyxDQUFDLDZCQUE2QixFQUFFLEVBQUUsR0FBRyxFQUFFLE9BQU8sRUFBRSxDQUFDLENBQUM7Z0JBQzlELEdBQUcsQ0FBQyxTQUFTLENBQUMsdUJBQXVCLEVBQUUsTUFBTSxDQUFDLENBQUM7Z0JBQy9DLEdBQUcsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLFVBQVUsQ0FBQyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUM7Z0JBQ2hELE9BQU87WUFDVCxDQUFDO1lBQ0QsSUFBSSxNQUFNLElBQUksTUFBTSxDQUFDLE9BQU8sRUFBRSxDQUFDO2dCQUM3Qix3RUFBd0U7Z0JBQ3hFLE1BQU0sQ0FBQyxLQUFLLENBQUMsMkNBQTJDLEVBQUUsRUFBRSxHQUFHLEVBQUUsT0FBTyxFQUFFLENBQUMsQ0FBQztnQkFDNUUsT0FBTyxjQUFjLEVBQUUsQ0FBQztZQUMxQixDQUFDO1lBRUQsMEVBQTBFO1lBQzFFLDREQUE0RDtZQUM1RCxNQUFNLEdBQUcsR0FBRyxNQUFNLEtBQUssQ0FBQyxPQUFPLENBQzdCLE9BQU8sRUFDUCxFQUFFLFVBQVUsRUFBRSxDQUFDLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxPQUFPLEVBQUUsSUFBSSxFQUFFLFNBQVMsRUFBRSxJQUFJLENBQUMsR0FBRyxFQUFFLEdBQUcsWUFBWSxFQUFFLEVBQ2xGLGFBQWEsQ0FDZCxDQUFDO1lBQ0YsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDO2dCQUNULE1BQU0sQ0FBQyxLQUFLLENBQUMsaURBQWlELEVBQUUsRUFBRSxHQUFHLEVBQUUsT0FBTyxFQUFFLENBQUMsQ0FBQztnQkFDbEYsT0FBTyxjQUFjLEVBQUUsQ0FBQztZQUMxQixDQUFDO1lBRUQsd0VBQXdFO1lBQ3hFLDRFQUE0RTtZQUM1RSxrRUFBa0U7WUFDbEUsSUFBSSxPQUFPLEdBQUcsS0FBSyxDQUFDO1lBQ3BCLElBQUksWUFBcUIsQ0FBQztZQUMxQixJQUFJLFlBQVksR0FBRyxLQUFLLENBQUM7WUFFekIsa0VBQWtFO1lBQ2xFLE1BQU0sV0FBVyxHQUFHLENBQUMsSUFBYSxFQUFRLEVBQUU7Z0JBQzFDLElBQUksQ0FBQyxZQUFZLEVBQUUsQ0FBQztvQkFDbEIsWUFBWSxHQUFHLElBQUksQ0FBQztvQkFDcEIsWUFBWSxHQUFHLElBQUksQ0FBQztnQkFDdEIsQ0FBQztZQUNILENBQUMsQ0FBQztZQUVGLE1BQU0sT0FBTyxHQUFHLEdBQVMsRUFBRTtnQkFDekIsSUFBSSxPQUFPO29CQUFFLE9BQU87Z0JBQ3BCLE9BQU8sR0FBRyxJQUFJLENBQUM7Z0JBQ2YsS0FBSyxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxHQUFHLEVBQUUsRUFBRTtvQkFDbEMsTUFBTSxDQUFDLElBQUksQ0FBQyx3Q0FBd0MsRUFBRSxFQUFFLEdBQUcsRUFBRSxPQUFPLEVBQUUsS0FBSyxFQUFFLFlBQVksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUM7Z0JBQ3BHLENBQUMsQ0FBQyxDQUFDO1lBQ0wsQ0FBQyxDQUFDO1lBRUYsTUFBTSxZQUFZLEdBQUcsR0FBUyxFQUFFO2dCQUM5QixJQUFJLE9BQU87b0JBQUUsT0FBTztnQkFDcEIsT0FBTyxHQUFHLElBQUksQ0FBQztnQkFDZixLQUFLLENBQUMsR0FBRyxDQUFDLE9BQU8sRUFBRTtvQkFDakIsVUFBVSxFQUFFLEdBQUcsQ0FBQyxVQUFVO29CQUMxQixJQUFJLEVBQUUsWUFBWSxDQUFDLENBQUMsQ0FBQyxZQUFZLENBQUMsQ0FBQyxDQUFDLElBQUk7b0JBQ3hDLFNBQVMsRUFBRSxJQUFJLENBQUMsR0FBRyxFQUFFLEdBQUcsS0FBSztpQkFDOUIsRUFBRSxNQUFNLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxHQUFHLEVBQUUsRUFBRTtvQkFDdkIsTUFBTSxDQUFDLElBQUksQ0FBQyw4QkFBOEIsRUFBRSxFQUFFLEdBQUcsRUFBRSxPQUFPLEVBQUUsS0FBSyxFQUFFLFlBQVksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUM7Z0JBQzFGLENBQUMsQ0FBQyxDQUFDO1lBQ0wsQ0FBQyxDQUFDO1lBRUY7Ozs7ZUFJRztZQUNILE1BQU0sZ0JBQWdCLEdBQUcsR0FBUyxFQUFFO2dCQUNsQyxJQUFJLE9BQU87b0JBQUUsT0FBTztnQkFDcEIsSUFBSSxHQUFHLENBQUMsVUFBVSxJQUFJLEdBQUcsSUFBSSxHQUFHLENBQUMsVUFBVSxHQUFHLEdBQUc7b0JBQUUsWUFBWSxFQUFFLENBQUM7O29CQUM3RCxPQUFPLEVBQUUsQ0FBQztZQUNqQixDQUFDLENBQUM7WUFFRiw0RUFBNEU7WUFDNUUsK0RBQStEO1lBQy9ELE1BQU0sWUFBWSxHQUFHLEdBQUcsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1lBQ3hDLEdBQUcsQ0FBQyxJQUFJLEdBQUcsQ0FBQyxJQUFhLEVBQUUsRUFBRTtnQkFDM0IsR0FBRyxDQUFDLFNBQVMsQ0FBQyx1QkFBdUIsRUFBRSxPQUFPLENBQUMsQ0FBQztnQkFDaEQsV0FBVyxDQUFDLElBQUksQ0FBQyxDQUFDO2dCQUNsQixnQkFBZ0IsRUFBRSxDQUFDO2dCQUNuQixPQUFPLFlBQVksQ0FBQyxJQUFJLENBQUMsQ0FBQztZQUM1QixDQUFDLENBQUM7WUFFRiw4REFBOEQ7WUFDOUQsNkVBQTZFO1lBQzdFLHlFQUF5RTtZQUN6RSxzRUFBc0U7WUFDdEUsMEJBQTBCO1lBQzFCLE1BQU0sT0FBTyxHQUFHLEdBSWYsQ0FBQztZQUNGLElBQUksT0FBTyxPQUFPLENBQUMsSUFBSSxLQUFLLFVBQVUsRUFBRSxDQUFDO2dCQUN2QyxNQUFNLFlBQVksR0FBRyxPQUFPLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQztnQkFDNUMsT0FBTyxDQUFDLElBQUksR0FBRyxDQUFDLElBQWMsRUFBRSxFQUFFO29CQUNoQyxXQUFXLENBQUMsSUFBSSxDQUFDLENBQUM7b0JBQ2xCLE9BQU8sWUFBWSxDQUFDLElBQUksQ0FBQyxDQUFDO2dCQUM1QixDQUFDLENBQUM7WUFDSixDQUFDO1lBQ0QsSUFBSSxPQUFPLE9BQU8sQ0FBQyxHQUFHLEtBQUssVUFBVSxFQUFFLENBQUM7Z0JBQ3RDLE1BQU0sV0FBVyxHQUFHLE9BQU8sQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDO2dCQUMxQyxPQUFPLENBQUMsR0FBRyxHQUFHLENBQUMsR0FBRyxJQUFlLEVBQUUsRUFBRTtvQkFDbkMsTUFBTSxLQUFLLEdBQUcsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDO29CQUN0QixJQUFJLEtBQUssS0FBSyxTQUFTLElBQUksT0FBTyxLQUFLLEtBQUssVUFBVTt3QkFBRSxXQUFXLENBQUMsS0FBSyxDQUFDLENBQUM7b0JBQzNFLE1BQU0sR0FBRyxHQUFHLFdBQVcsQ0FBQyxHQUFHLElBQUksQ0FBQyxDQUFDO29CQUNqQyxxRUFBcUU7b0JBQ3JFLHdFQUF3RTtvQkFDeEUsb0RBQW9EO29CQUNwRCxnQkFBZ0IsRUFBRSxDQUFDO29CQUNuQixPQUFPLEdBQUcsQ0FBQztnQkFDYixDQUFDLENBQUM7WUFDSixDQUFDO1lBRUQsdUVBQXVFO1lBQ3ZFLHdFQUF3RTtZQUN4RSx5RUFBeUU7WUFDekUsc0VBQXNFO1lBQ3RFLDBFQUEwRTtZQUMxRSx1RUFBdUU7WUFDdkUsSUFBSSxPQUFPLE9BQU8sQ0FBQyxFQUFFLEtBQUssVUFBVSxFQUFFLENBQUM7Z0JBQ3JDLE9BQU8sQ0FBQyxFQUFFLENBQUMsUUFBUSxFQUFFLGdCQUFnQixDQUFDLENBQUM7Z0JBQ3ZDLHFFQUFxRTtnQkFDckUscUVBQXFFO2dCQUNyRSx5RUFBeUU7Z0JBQ3pFLG9FQUFvRTtnQkFDcEUscUVBQXFFO2dCQUNyRSxtRUFBbUU7Z0JBQ25FLG1DQUFtQztZQUNyQyxDQUFDO1lBRUQsSUFBSSxFQUFFLENBQUM7UUFDVCxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxHQUFHLEVBQUUsRUFBRTtZQUNmLDBFQUEwRTtZQUMxRSxNQUFNLENBQUMsSUFBSSxDQUFDLHdEQUF3RCxFQUFFLEVBQUUsR0FBRyxFQUFFLE9BQU8sRUFBRSxLQUFLLEVBQUUsWUFBWSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsQ0FBQztZQUNsSCxJQUFJLEVBQUUsQ0FBQztRQUNULENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQyxDQUFDO0FBQ0osQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8vIENvcHlyaWdodCAyMDI2IFBpcGVsaW5lIEJ1aWxkZXIgQ29udHJpYnV0b3JzXG4vLyBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQXBhY2hlLTIuMFxuXG5pbXBvcnQgeyBjcmVhdGVIYXNoIH0gZnJvbSAnY3J5cHRvJztcbmltcG9ydCB7IGNyZWF0ZUxvZ2dlciwgc2VuZEVycm9yLCBFcnJvckNvZGUsIGNyZWF0ZUVudlJlZGlzQ2xpZW50LCBlcnJvck1lc3NhZ2UsIHN0YWJsZVN0cmluZ2lmeSB9IGZyb20gJ0BwaXBlbGluZS1idWlsZGVyL2FwaS1jb3JlJztcbmltcG9ydCB7IENvcmVDb25zdGFudHMgfSBmcm9tICdAcGlwZWxpbmUtYnVpbGRlci9waXBlbGluZS1jb3JlJztcbmltcG9ydCB0eXBlIHsgUmVxdWVzdCwgUmVzcG9uc2UsIE5leHRGdW5jdGlvbiB9IGZyb20gJ2V4cHJlc3MnO1xuXG5jb25zdCBsb2dnZXIgPSBjcmVhdGVMb2dnZXIoJ2lkZW1wb3RlbmN5Jyk7XG5cbi8qKlxuICogU2hvcnQsIHN0YWJsZSBmaW5nZXJwcmludCBvZiBhIHJlcXVlc3QgYm9keS4gRm9sZHMgdGhlIHBheWxvYWQgaW50byB0aGVcbiAqIGlkZW1wb3RlbmN5IGtleSBzbyByZXBsYXlpbmcgdGhlIFNBTUUga2V5IHdpdGggYSBESUZGRVJFTlQgYm9keSBpcyB0cmVhdGVkIGFzXG4gKiBhIGRpc3RpbmN0IG9wZXJhdGlvbiAoZnJlc2ggZXhlY3V0aW9uKSByYXRoZXIgdGhhbiByZXBsYXlpbmcgdGhlIG9sZCByZXNwb25zZS5cbiAqIEVtcHR5L2Fic2VudCBib2RpZXMgY29sbGFwc2UgdG8gJy0nIHNvIGJvZHktbGVzcyBtdXRhdGlvbnMgc3RheSB1bmFmZmVjdGVkLlxuICovXG5mdW5jdGlvbiBib2R5RmluZ2VycHJpbnQoYm9keTogdW5rbm93bik6IHN0cmluZyB7XG4gIGlmIChib2R5ID09PSB1bmRlZmluZWQgfHwgYm9keSA9PT0gbnVsbCkgcmV0dXJuICctJztcbiAgaWYgKHR5cGVvZiBib2R5ID09PSAnb2JqZWN0JyAmJiBPYmplY3Qua2V5cyhib2R5IGFzIG9iamVjdCkubGVuZ3RoID09PSAwKSByZXR1cm4gJy0nO1xuICB0cnkge1xuICAgIHJldHVybiBjcmVhdGVIYXNoKCdzaGEyNTYnKS51cGRhdGUoc3RhYmxlU3RyaW5naWZ5KGJvZHkpKS5kaWdlc3QoJ2hleCcpLnNsaWNlKDAsIDE2KTtcbiAgfSBjYXRjaCB7XG4gICAgLy8gTm9uLXNlcmlhbGl6YWJsZSBib2R5IChlLmcuIGEgc3RyZWFtL2NpcmN1bGFyIHJlZik6IHNraXAgZmluZ2VycHJpbnRpbmdcbiAgICAvLyByYXRoZXIgdGhhbiBmYWlsIHRoZSByZXF1ZXN0IOKAlCBrZXkgc3RheXMgc2NvcGVkIGJ5IG1ldGhvZCtyb3V0ZStvcmcuXG4gICAgcmV0dXJuICctJztcbiAgfVxufVxuXG5pbnRlcmZhY2UgQ2FjaGVkRW50cnkge1xuICBzdGF0dXNDb2RlOiBudW1iZXI7XG4gIGJvZHk6IHVua25vd247XG4gIGV4cGlyZXNBdDogbnVtYmVyO1xuICAvKiogUmVzZXJ2YXRpb24gcGxhY2Vob2xkZXI6IHRoZSByZXF1ZXN0IGlzIGluLWZsaWdodCwgbm8gcmVhbCByZXNwb25zZSB5ZXQuXG4gICAqICBBIGR1cGxpY2F0ZSB0aGF0IHNlZXMgYSBwZW5kaW5nIGVudHJ5IGlzIHJlamVjdGVkIHdpdGggNDA5LCBub3QgcmVwbGF5ZWQuICovXG4gIHBlbmRpbmc/OiBib29sZWFuO1xufVxuXG4vKipcbiAqIFBsdWdnYWJsZSBiYWNrZW5kIGZvciBpZGVtcG90ZW5jeS1rZXkgcmVwbGF5IGNhY2hlLiBUaGUgZGVmYXVsdCBpbi1tZW1vcnlcbiAqIGltcGxlbWVudGF0aW9uIHdvcmtzIGZpbmUgc2luZ2xlLXJlcGxpY2E7IGEgUmVkaXMtYmFja2VkIGltcGxlbWVudGF0aW9uXG4gKiBpcyByZXF1aXJlZCBmb3IgY29ycmVjdCBkZWR1cGxpY2F0aW9uIGFjcm9zcyBob3Jpem9udGFsbHktc2NhbGVkIHJlcGxpY2FzXG4gKiAob3RoZXJ3aXNlIHR3byByZXBsaWNhcyBiZWhpbmQgYSBsb2FkLWJhbGFuY2VyIGNhY2hlIGluZGVwZW5kZW50bHkgYW5kIGFcbiAqIHJldHJ5IGhpdHRpbmcgYSBkaWZmZXJlbnQgcG9kIHdvbid0IHJlcGxheSkuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgSWRlbXBvdGVuY3lTdG9yZSB7XG4gIGdldChrZXk6IHN0cmluZyk6IFByb21pc2U8Q2FjaGVkRW50cnkgfCBudWxsPjtcbiAgc2V0KGtleTogc3RyaW5nLCBlbnRyeTogQ2FjaGVkRW50cnksIHR0bFNlY29uZHM6IG51bWJlcik6IFByb21pc2U8dm9pZD47XG4gIC8qKlxuICAgKiBBdG9taWNhbGx5IGNsYWltIGBrZXlgIElGRiBpdCBpcyBjdXJyZW50bHkgYWJzZW50LiBSZXR1cm5zIGB0cnVlYCB3aGVuIFRISVNcbiAgICogY2FsbGVyIHNldCB0aGUgZW50cnkgKHdvbiB0aGUgcmFjZSksIGBmYWxzZWAgd2hlbiBhbiBlbnRyeSBhbHJlYWR5IGV4aXN0cy5cbiAgICogVGhpcyBpcyB3aGF0IHNlcmlhbGl6ZXMgY29uY3VycmVudCBmaXJzdC10aW1lIHJlcXVlc3RzIHRoYXQgc2hhcmUgYW5cbiAgICogSWRlbXBvdGVuY3ktS2V5IOKAlCBhIHBsYWluIGdldC10aGVuLXNldCBsZWF2ZXMgYSB3aW5kb3cgd2hlcmUgdHdvIHJlcXVlc3RzXG4gICAqIGJvdGggc2VlIFwibm90IGNhY2hlZFwiIGFuZCBib3RoIGV4ZWN1dGUgdGhlIG11dGF0aW9uLlxuICAgKi9cbiAgcmVzZXJ2ZShrZXk6IHN0cmluZywgZW50cnk6IENhY2hlZEVudHJ5LCB0dGxTZWNvbmRzOiBudW1iZXIpOiBQcm9taXNlPGJvb2xlYW4+O1xuICAvKiogUmVtb3ZlIGEga2V5IOKAlCByZWxlYXNlcyBhIHJlc2VydmF0aW9uIGFmdGVyIGEgbm9uLWNhY2hlYWJsZSAobm9uLTJ4eCkgcmVzcG9uc2UuICovXG4gIGRlbGV0ZShrZXk6IHN0cmluZyk6IFByb21pc2U8dm9pZD47XG59XG5cbi8qKiBEZWZhdWx0IGluLW1lbW9yeSBzdG9yZS4gU2luZ2xlLXJlcGxpY2Egb25seS4gRXhwb3J0ZWQgZm9yIHRlc3RpbmcuICovXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlTWVtb3J5U3RvcmUoKTogSWRlbXBvdGVuY3lTdG9yZSB7XG4gIGNvbnN0IG1hcCA9IG5ldyBNYXA8c3RyaW5nLCBDYWNoZWRFbnRyeT4oKTtcbiAgY29uc3QgY2xlYW51cFRpbWVyID0gc2V0SW50ZXJ2YWwoKCkgPT4ge1xuICAgIGNvbnN0IG5vdyA9IERhdGUubm93KCk7XG4gICAgZm9yIChjb25zdCBbaywgdl0gb2YgbWFwKSB7XG4gICAgICBpZiAobm93ID4gdi5leHBpcmVzQXQpIG1hcC5kZWxldGUoayk7XG4gICAgfVxuICB9LCBDb3JlQ29uc3RhbnRzLklERU1QT1RFTkNZX0NMRUFOVVBfSU5URVJWQUxfTVMpO1xuICBjbGVhbnVwVGltZXIudW5yZWYoKTtcblxuICAvKiogUmV0dXJuIHRoZSBsaXZlIChub24tZXhwaXJlZCkgZW50cnksIGV2aWN0aW5nIGl0IGxhemlseSBpZiBleHBpcmVkLiAqL1xuICBjb25zdCBsaXZlID0gKGtleTogc3RyaW5nKTogQ2FjaGVkRW50cnkgfCBudWxsID0+IHtcbiAgICBjb25zdCBlbnRyeSA9IG1hcC5nZXQoa2V5KTtcbiAgICBpZiAoIWVudHJ5KSByZXR1cm4gbnVsbDtcbiAgICBpZiAoRGF0ZS5ub3coKSA+IGVudHJ5LmV4cGlyZXNBdCkge1xuICAgICAgbWFwLmRlbGV0ZShrZXkpO1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICAgIHJldHVybiBlbnRyeTtcbiAgfTtcbiAgLyoqXG4gICAqIEF0IGNhcGFjaXR5LCBldmljdCB0aGUgT0xERVNUIGVudHJ5IChNYXAgcHJlc2VydmVzIGluc2VydGlvbiBvcmRlcikgcmF0aGVyXG4gICAqIHRoYW4gc2lsZW50bHkgZHJvcHBpbmcgdGhlIE5FVyBrZXkg4oCUIG90aGVyd2lzZSwgb25jZSBmdWxsLCB0aGUgc3RvcmUgc3RvcHNcbiAgICogZGVkdXBsaWNhdGluZyBmcmVzaCByZXF1ZXN0cyB1bnRpbCB0aGUgVFRMIHN3ZWVwIHJ1bnMuIFN0YXlzIGJvdW5kZWQ7IGZhdm9yc1xuICAgKiByZWNlbnQga2V5cyAobW9zdCBsaWtlbHkgdG8gYmUgcmV0cmllZCkuXG4gICAqL1xuICBjb25zdCBldmljdElmRnVsbCA9IChrZXk6IHN0cmluZyk6IHZvaWQgPT4ge1xuICAgIGlmICghbWFwLmhhcyhrZXkpICYmIG1hcC5zaXplID49IENvcmVDb25zdGFudHMuSURFTVBPVEVOQ1lfTUFYX1NUT1JFX1NJWkUpIHtcbiAgICAgIGNvbnN0IG9sZGVzdCA9IG1hcC5rZXlzKCkubmV4dCgpLnZhbHVlO1xuICAgICAgaWYgKG9sZGVzdCAhPT0gdW5kZWZpbmVkKSBtYXAuZGVsZXRlKG9sZGVzdCk7XG4gICAgfVxuICB9O1xuICByZXR1cm4ge1xuICAgIGFzeW5jIGdldChrZXkpIHtcbiAgICAgIHJldHVybiBsaXZlKGtleSk7XG4gICAgfSxcbiAgICBhc3luYyBzZXQoa2V5LCBlbnRyeSkge1xuICAgICAgZXZpY3RJZkZ1bGwoa2V5KTtcbiAgICAgIG1hcC5zZXQoa2V5LCBlbnRyeSk7XG4gICAgfSxcbiAgICBhc3luYyByZXNlcnZlKGtleSwgZW50cnkpIHtcbiAgICAgIC8vIEF0b21pYyBpbiBhIHNpbmdsZS10aHJlYWRlZCBydW50aW1lOiBubyBhd2FpdCBiZXR3ZWVuIHRoZSBsaXZlbmVzcyBjaGVja1xuICAgICAgLy8gYW5kIHRoZSBzZXQsIHNvIHR3byBjb25jdXJyZW50IGNhbGxlcnMgY2FuJ3QgYm90aCBvYnNlcnZlIFwiYWJzZW50XCIuXG4gICAgICBpZiAobGl2ZShrZXkpKSByZXR1cm4gZmFsc2U7XG4gICAgICBldmljdElmRnVsbChrZXkpO1xuICAgICAgbWFwLnNldChrZXksIGVudHJ5KTtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH0sXG4gICAgYXN5bmMgZGVsZXRlKGtleSkge1xuICAgICAgbWFwLmRlbGV0ZShrZXkpO1xuICAgIH0sXG4gIH07XG59XG5cbi8qKlxuICogTWluaW1hbCBSZWRpcyBzdXJmYWNlIHRoZSBpZGVtcG90ZW5jeSBzdG9yZSBuZWVkcyAoYW4gaW9yZWRpcyBzdWJzZXQpLlxuICogYHNldGAgc3VwcG9ydHMgdGhlIHZhcmlhZGljIG9wdGlvbiB0YWlsOiBgU0VUIGtleSB2YWwgRVggPHR0bD4gW05YXWAsIHdoaWNoXG4gKiByZXR1cm5zIGAnT0snYCBvbiBzdWNjZXNzIGFuZCBgbnVsbGAgd2hlbiBhbiBgTlhgIHNldCB3YXMgcmVmdXNlZC5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBSZWRpc0lkZW1wb3RlbmN5Q2xpZW50IHtcbiAgZ2V0KGtleTogc3RyaW5nKTogUHJvbWlzZTxzdHJpbmcgfCBudWxsPjtcbiAgc2V0KGtleTogc3RyaW5nLCB2YWx1ZTogc3RyaW5nLCAuLi5hcmdzOiAoc3RyaW5nIHwgbnVtYmVyKVtdKTogUHJvbWlzZTxzdHJpbmcgfCBudWxsPjtcbiAgZGVsKGtleTogc3RyaW5nKTogUHJvbWlzZTxudW1iZXI+O1xufVxuXG5jb25zdCBSRURJU19LRVlfUFJFRklYID0gJ2lkZW06JztcblxuLyoqXG4gKiBSZWRpcy1iYWNrZWQge0BsaW5rIElkZW1wb3RlbmN5U3RvcmV9IGZvciBjb3JyZWN0IGRlZHVwbGljYXRpb24gYWNyb3NzXG4gKiBob3Jpem9udGFsbHktc2NhbGVkIHJlcGxpY2FzLiBgcmVzZXJ2ZWAgbWFwcyB0byBhbiBhdG9taWMgYFNFVCDigKYgTlhgIHNvIHR3b1xuICogcG9kcyBiZWhpbmQgYSBsb2FkLWJhbGFuY2VyIGNhbid0IGJvdGggd2luIGEgZmlyc3QtdGltZSByZXF1ZXN0IHNoYXJpbmcgYW5cbiAqIElkZW1wb3RlbmN5LUtleTsgYSByZXRyeSBsYW5kaW5nIG9uIEFOWSBwb2Qgc2VlcyB0aGUgc2FtZSBjb21taXR0ZWQgcmVzcG9uc2UuXG4gKiBSZWRpcyBUVEwgb3ducyBleHBpcnkgKHRoZSBgQ2FjaGVkRW50cnkuZXhwaXJlc0F0YCBmaWVsZCBpcyBjYXJyaWVkIG9ubHkgZm9yXG4gKiBBUEktc2hhcGUgcGFyaXR5IHdpdGggdGhlIG1lbW9yeSBzdG9yZSkuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVSZWRpc0lkZW1wb3RlbmN5U3RvcmUocmVkaXM6IFJlZGlzSWRlbXBvdGVuY3lDbGllbnQpOiBJZGVtcG90ZW5jeVN0b3JlIHtcbiAgY29uc3QgayA9IChrZXk6IHN0cmluZyk6IHN0cmluZyA9PiBgJHtSRURJU19LRVlfUFJFRklYfSR7a2V5fWA7XG4gIHJldHVybiB7XG4gICAgYXN5bmMgZ2V0KGtleSkge1xuICAgICAgY29uc3QgcmF3ID0gYXdhaXQgcmVkaXMuZ2V0KGsoa2V5KSk7XG4gICAgICBpZiAoIXJhdykgcmV0dXJuIG51bGw7XG4gICAgICB0cnkge1xuICAgICAgICByZXR1cm4gSlNPTi5wYXJzZShyYXcpIGFzIENhY2hlZEVudHJ5O1xuICAgICAgfSBjYXRjaCB7XG4gICAgICAgIC8vIENvcnJ1cHQgZW50cnkg4oaSIHRyZWF0IGFzIGFic2VudCBzbyB0aGUgcmVxdWVzdCBwcm9jZWVkcyBmcmVzaC5cbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICB9XG4gICAgfSxcbiAgICBhc3luYyBzZXQoa2V5LCBlbnRyeSwgdHRsU2Vjb25kcykge1xuICAgICAgYXdhaXQgcmVkaXMuc2V0KGsoa2V5KSwgSlNPTi5zdHJpbmdpZnkoZW50cnkpLCAnRVgnLCBNYXRoLm1heCgxLCB0dGxTZWNvbmRzKSk7XG4gICAgfSxcbiAgICBhc3luYyByZXNlcnZlKGtleSwgZW50cnksIHR0bFNlY29uZHMpIHtcbiAgICAgIC8vIEF0b21pYyBjbGFpbTogU0VUIGtleSB2YWwgRVggdHRsIE5YIOKGkiAnT0snIG9ubHkgaWYgdGhlIGtleSB3YXMgYWJzZW50LlxuICAgICAgY29uc3QgcmVzID0gYXdhaXQgcmVkaXMuc2V0KGsoa2V5KSwgSlNPTi5zdHJpbmdpZnkoZW50cnkpLCAnRVgnLCBNYXRoLm1heCgxLCB0dGxTZWNvbmRzKSwgJ05YJyk7XG4gICAgICByZXR1cm4gcmVzID09PSAnT0snO1xuICAgIH0sXG4gICAgYXN5bmMgZGVsZXRlKGtleSkge1xuICAgICAgYXdhaXQgcmVkaXMuZGVsKGsoa2V5KSk7XG4gICAgfSxcbiAgfTtcbn1cblxuLyoqXG4gKiBCdWlsZCBhIFJlZGlzLWJhY2tlZCBpZGVtcG90ZW5jeSBzdG9yZSBmcm9tIHRoZSBzaGFyZWQgZW52IFJlZGlzICh0aGUgc2FtZVxuICogYFJFRElTX1VSTGAgLyBgUkVESVNfU0VOVElORUxTYCB3aXJpbmcgdGhlIHJhdGUtbGltaXRlciBhbmQgYXVkaXQtc3Bvb2wgdXNlKS5cbiAqIFJldHVybnMgYG51bGxgIHdoZW4gUmVkaXMgaXNuJ3QgY29uZmlndXJlZC9hdmFpbGFibGUgc28gdGhlIGNhbGxlciBrZWVwcyB0aGVcbiAqIGluLW1lbW9yeSBkZWZhdWx0IChzaW5nbGUtcmVwbGljYSBjb3JyZWN0bmVzcykuIE5ldmVyIHRocm93cy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZUVudlJlZGlzSWRlbXBvdGVuY3lTdG9yZSgpOiBJZGVtcG90ZW5jeVN0b3JlIHwgbnVsbCB7XG4gIGNvbnN0IGNsaWVudCA9IGNyZWF0ZUVudlJlZGlzQ2xpZW50PFJlZGlzSWRlbXBvdGVuY3lDbGllbnQ+KCdpZGVtcG90ZW5jeScpO1xuICBpZiAoIWNsaWVudCkgcmV0dXJuIG51bGw7XG4gIGxvZ2dlci5pbmZvKCdSZWRpcyBpZGVtcG90ZW5jeSBzdG9yZSBpbml0aWFsaXplZCcpO1xuICByZXR1cm4gY3JlYXRlUmVkaXNJZGVtcG90ZW5jeVN0b3JlKGNsaWVudCk7XG59XG5cbmNvbnN0IG1lbW9yeVN0b3JlID0gY3JlYXRlTWVtb3J5U3RvcmUoKTtcblxuLyoqXG4gKiBQcm9jZXNzLXdpZGUgZGVmYXVsdCBzdG9yZSB1c2VkIGJ5IGBpZGVtcG90ZW5jeU1pZGRsZXdhcmUoKWAgd2hlbiBubyBleHBsaWNpdFxuICogYHN0b3JlYCBpcyBwYXNzZWQuIERlZmF1bHRzIHRvIHRoZSBpbi1tZW1vcnkgc3RvcmU7IGBjcmVhdGVBcHBgIHByb21vdGVzIGl0IHRvXG4gKiB0aGUgc2hhcmVkIGVudi1SZWRpcyBzdG9yZSAobXVsdGktcmVwbGljYSBkZWR1cCkgYXQgc3RhcnR1cCB2aWFcbiAqIHtAbGluayBzZXRJZGVtcG90ZW5jeVN0b3JlfS4gVGhlIHJvdXRlIGZhY3RvcmllcyBrZWVwIGNhbGxpbmdcbiAqIGBpZGVtcG90ZW5jeU1pZGRsZXdhcmUoKWAgd2l0aCBubyBhcmdzIGFuZCB0cmFuc3BhcmVudGx5IHBpY2sgdGhpcyB1cC5cbiAqL1xubGV0IGRlZmF1bHRTdG9yZTogSWRlbXBvdGVuY3lTdG9yZSA9IG1lbW9yeVN0b3JlO1xuXG4vKiogSW5qZWN0IHRoZSBwcm9jZXNzLXdpZGUgaWRlbXBvdGVuY3kgc3RvcmUgKGUuZy4gYSBSZWRpcy1iYWNrZWQgb25lKS4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzZXRJZGVtcG90ZW5jeVN0b3JlKHN0b3JlOiBJZGVtcG90ZW5jeVN0b3JlKTogdm9pZCB7XG4gIGRlZmF1bHRTdG9yZSA9IHN0b3JlO1xufVxuXG4vKiogVGhlIGN1cnJlbnQgcHJvY2Vzcy13aWRlIGRlZmF1bHQgc3RvcmUgKGluLW1lbW9yeSB1bmxlc3Mgb3ZlcnJpZGRlbikuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0SWRlbXBvdGVuY3lTdG9yZSgpOiBJZGVtcG90ZW5jeVN0b3JlIHtcbiAgcmV0dXJuIGRlZmF1bHRTdG9yZTtcbn1cblxuLyoqXG4gKiBNYXJrcyBhIHJlcXVlc3QgaWRlbXBvdGVuY3kgaGFzIGFscmVhZHkgaGFuZGxlZC4gUm91dGUgY2hhaW5zIGFyZSBzdGFja2VkIOKAlFxuICogc2V2ZXJhbCBgYXBwLnVzZShwcmVmaXgsIC4uLmNyZWF0ZUF1dGhlbnRpY2F0ZWRXaXRoT3JnUm91dGUoKSwgcm91dGVyKWAgbW91bnRzXG4gKiBzaGFyZSBhIHByZWZpeCwgYW5kIGEgcmVxdWVzdCB0aGF0IGZhbGxzIHRocm91Z2ggdGhlIGZpcnN0IHJvdXRlciBydW5zIHRoZVxuICogbmV4dCBjaGFpbidzIGlkZW1wb3RlbmN5IG1pZGRsZXdhcmUgYWdhaW4uIFRoYXQgc2Vjb25kIHBhc3MgZm91bmQgaXRzIE9XTlxuICogcGVuZGluZyByZXNlcnZhdGlvbiBhbmQgYW5zd2VyZWQgNDA5LlxuICovXG5jb25zdCBJREVNUE9URU5DWV9IQU5ETEVEID0gU3ltYm9sKCdwaXBlbGluZS1idWlsZGVyLmlkZW1wb3RlbmN5LmhhbmRsZWQnKTtcblxuZXhwb3J0IGludGVyZmFjZSBJZGVtcG90ZW5jeU1pZGRsZXdhcmVPcHRpb25zIHtcbiAgLyoqIEN1c3RvbSBzdG9yZSBiYWNrZW5kLiBEZWZhdWx0cyB0byB0aGUgcHJvY2Vzcy13aWRlIHN0b3JlIHNldCB2aWFcbiAgICogIHtAbGluayBzZXRJZGVtcG90ZW5jeVN0b3JlfSAoaW4tbWVtb3J5IHVudGlsIGBjcmVhdGVBcHBgIHdpcmVzIFJlZGlzKS4gKi9cbiAgc3RvcmU/OiBJZGVtcG90ZW5jeVN0b3JlO1xufVxuXG4vKipcbiAqIE1pZGRsZXdhcmUgdGhhdCBzdXBwb3J0cyBpZGVtcG90ZW5jeSBrZXlzIGZvciBQT1NUL1BVVC9ERUxFVEUgbXV0YXRpb25zLlxuICpcbiAqIFdoZW4gYSByZXF1ZXN0IGluY2x1ZGVzIHRoZSBgSWRlbXBvdGVuY3ktS2V5YCBoZWFkZXI6XG4gKiAtIEZpcnN0IGNhbGw6IHByb2Nlc3NlcyBub3JtYWxseSwgY2FjaGVzIHRoZSByZXNwb25zZVxuICogLSBTdWJzZXF1ZW50IGNhbGxzIHdpdGggc2FtZSBrZXk6IHJldHVybnMgY2FjaGVkIHJlc3BvbnNlIChwcmV2ZW50cyBkdXBsaWNhdGUgbXV0YXRpb25zKVxuICpcbiAqIERlZmF1bHRzIHRvIGFuIGluLW1lbW9yeSBzdG9yZSAoc2luZ2xlLXJlcGxpY2EpLiBQYXNzIGEgY3VzdG9tXG4gKiBjcm9zcy1yZXBsaWNhIGB7IHN0b3JlIH1gIGltcGxlbWVudGluZyBgSWRlbXBvdGVuY3lTdG9yZWAgdG8gZGVkdXBlIGFjcm9zc1xuICogcmVwbGljYXMuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpZGVtcG90ZW5jeU1pZGRsZXdhcmUob3B0aW9uczogSWRlbXBvdGVuY3lNaWRkbGV3YXJlT3B0aW9ucyA9IHt9KSB7XG4gIC8vIFJlc29sdmUgdGhlIHN0b3JlIFBFUiBSRVFVRVNUIChub3QgYXQgZmFjdG9yeSB0aW1lKSBzbyBhIHN0b3JlIGluamVjdGVkIGJ5XG4gIC8vIGNyZWF0ZUFwcCBBRlRFUiB0aGUgcm91dGUgY2hhaW5zIGFyZSBidWlsdCBzdGlsbCB0YWtlcyBlZmZlY3QuIEFuIGV4cGxpY2l0XG4gIC8vIGBvcHRpb25zLnN0b3JlYCBhbHdheXMgd2lucy5cbiAgY29uc3QgZXhwbGljaXRTdG9yZSA9IG9wdGlvbnMuc3RvcmU7XG4gIGNvbnN0IHR0bE1zID0gQ29yZUNvbnN0YW50cy5JREVNUE9URU5DWV9UVExfTVM7XG4gIGNvbnN0IHR0bFNlYyA9IE1hdGguZmxvb3IodHRsTXMgLyAxMDAwKTtcbiAgLy8gQSByZXNlcnZhdGlvbiBsaXZlcyBvbmx5IGFzIGxvbmcgYXMgYSBoYW5kbGVyIHBsYXVzaWJseSBydW5zOiBpZiB0aGVcbiAgLy8gcHJvY2VzcyBkaWVzIG1pZC1oYW5kbGVyIG5vdGhpbmcgZXZlciBzZXR0bGVzIGl0LCBhbmQgdGhpcyDigJQgbm90IHRoZSBmdWxsXG4gIC8vIHJlcGxheSBUVEwg4oCUIGlzIGhvdyBsb25nIHJldHJpZXMgb2YgdGhhdCBrZXkgYXJlIHJlZnVzZWQuXG4gIGNvbnN0IHBlbmRpbmdUdGxNcyA9IE1hdGgubWluKENvcmVDb25zdGFudHMuSURFTVBPVEVOQ1lfUEVORElOR19UVExfTVMsIHR0bE1zKTtcbiAgY29uc3QgcGVuZGluZ1R0bFNlYyA9IE1hdGgubWF4KDEsIE1hdGguZmxvb3IocGVuZGluZ1R0bE1zIC8gMTAwMCkpO1xuXG4gIHJldHVybiAocmVxOiBSZXF1ZXN0LCByZXM6IFJlc3BvbnNlLCBuZXh0OiBOZXh0RnVuY3Rpb24pID0+IHtcbiAgICBjb25zdCBzdG9yZSA9IGV4cGxpY2l0U3RvcmUgPz8gZGVmYXVsdFN0b3JlO1xuICAgIGNvbnN0IGtleSA9IHJlcS5oZWFkZXJzWydpZGVtcG90ZW5jeS1rZXknXSBhcyBzdHJpbmcgfCB1bmRlZmluZWQ7XG4gICAgaWYgKCFrZXkpIHJldHVybiBuZXh0KCk7XG5cbiAgICAvLyBPbmx5IGFwcGx5IHRvIG11dGF0aW9uIG1ldGhvZHNcbiAgICBpZiAoIVsnUE9TVCcsICdQVVQnLCAnREVMRVRFJ10uaW5jbHVkZXMocmVxLm1ldGhvZCkpIHJldHVybiBuZXh0KCk7XG5cbiAgICAvLyBPbmUgcGFzcyBwZXIgcmVxdWVzdDogYSBsYXRlciBzdGFja2VkIGNoYWluIG11c3Qgbm90IHJlLWNoZWNrIHRoZSBrZXkuXG4gICAgY29uc3QgbWFya2VkID0gcmVxIGFzIFJlcXVlc3QgJiB7IFtJREVNUE9URU5DWV9IQU5ETEVEXT86IHRydWUgfTtcbiAgICBpZiAobWFya2VkW0lERU1QT1RFTkNZX0hBTkRMRURdKSByZXR1cm4gbmV4dCgpO1xuXG4gICAgLy8gTmFtZXNwYWNlIGJ5IG9yZ0lkIHRvIHByZXZlbnQgY3Jvc3Mtb3JnIGNhY2hlIGNvbGxpc2lvbnMuIFByZWZlciB0aGVcbiAgICAvLyBWRVJJRklFRCBhdXRoIG9yZyAoYHJlcS51c2VyYCwgcG9wdWxhdGVkIGJ5IHJlcXVpcmVBdXRoIGFmdGVyIHNpZ25hdHVyZVxuICAgIC8vIHZlcmlmaWNhdGlvbikgb3ZlciBgcmVxLmNvbnRleHQuaWRlbnRpdHlgLCB3aGljaCBzb21lIHNlcnZpY2VzIHBvcHVsYXRlXG4gICAgLy8gcHJlLWF1dGggZnJvbSBhbiBVTlZFUklGSUVEIHRva2VuIHBlZWsg4oCUIG5hbWVzcGFjaW5nIGEgbXV0YXRpb24ncyByZXBsYXlcbiAgICAvLyBjYWNoZSBvbiBhbiB1bnZlcmlmaWVkLCBjYWxsZXItaW5mbHVlbmNlZCBvcmcgaWQgd291bGQgYmUgdW5zYWZlLlxuICAgIGNvbnN0IG9yZ0lkID0gcmVxLnVzZXI/Lm9yZ2FuaXphdGlvbklkIHx8IHJlcS5jb250ZXh0Py5pZGVudGl0eT8ub3JnSWQ7XG4gICAgaWYgKCFvcmdJZCkgcmV0dXJuIG5leHQoKTsgLy8gc2tpcCBpZGVtcG90ZW5jeSBmb3IgdW5hdXRoZW50aWNhdGVkIHJlcXVlc3RzXG4gICAgbWFya2VkW0lERU1QT1RFTkNZX0hBTkRMRURdID0gdHJ1ZTtcblxuICAgIC8vIE5hbWVzcGFjZSB0aGUgc3RvcmVkIGtleSBieSAobWV0aG9kLCByb3V0ZSwgb3JnLCBib2R5KSBzbyBhbiBJZGVtcG90ZW5jeS1LZXlcbiAgICAvLyBpcyBzY29wZWQgdG8gT05FIHNwZWNpZmljIGVuZHBvaW50K3BheWxvYWQuIFJldXNpbmcgYSBzaW5nbGUga2V5IGFjcm9zcyB0d29cbiAgICAvLyByb3V0ZXMgKGUuZy4gUE9TVCAvcGlwZWxpbmVzIHRoZW4gUE9TVCAvcGx1Z2lucykgbXVzdCBub3QgcmVwbGF5IHRoZVxuICAgIC8vIGZpcnN0IGVuZHBvaW50J3MgMnh4IGZvciB0aGUgc2Vjb25kIOKAlCB0aGUgc3RvcmUgaXMgYSBtb2R1bGUtbGV2ZWwgc2luZ2xldG9uXG4gICAgLy8gc2hhcmVkIGJ5IGV2ZXJ5IHJvdXRlLiBGb2xkaW5nIGluIG1ldGhvZCArIHJvdXRlIHBhdGggKyBhIGJvZHkgZmluZ2VycHJpbnRcbiAgICAvLyBvbmx5IG1ha2VzIGtleXMgTU9SRSBzcGVjaWZpYywgc28gdGhlcmUgaXMgbm8gY3Jvc3MtY29udGFtaW5hdGlvbiByaXNrLlxuICAgIC8vIEFsc28gbmFtZXNwYWNlIGJ5IHRoZSBWRVJJRklFRCB1c2VyLiBgSWRlbXBvdGVuY3ktS2V5YCBpcyBjaG9zZW4gYnkgdGhlXG4gICAgLy8gY2xpZW50LCBzbyB0d28gdXNlcnMgaW4gdGhlIHNhbWUgb3JnIHNlbmRpbmcgdGhlIHNhbWUgYm9keSB3aXRoIHRoZSBzYW1lXG4gICAgLy8ga2V5IGNvbGxpZGVkOiB0aGUgc2Vjb25kIHVzZXIncyBtdXRhdGlvbiB3YXMgU0tJUFBFRCBhbmQgdGhleSB3ZXJlIHNlcnZlZFxuICAgIC8vIHRoZSBmaXJzdCB1c2VyJ3MgY2FjaGVkIHJlc3BvbnNlLiBGYWxscyBiYWNrIHRvIHRoZSBvcmcgYWxvbmUgb25seSB3aGVuXG4gICAgLy8gdGhlcmUgaXMgbm8gdmVyaWZpZWQgc3ViamVjdCAoc2VydmljZSBwcmluY2lwYWxzIGNhcnJ5IG9uZSkuXG4gICAgY29uc3Qgc3ViID0gcmVxLnVzZXI/LnN1YjtcbiAgICBjb25zdCByb3V0ZVBhdGggPSAocmVxLmJhc2VVcmwgPz8gJycpICsgKHJlcS5yb3V0ZT8ucGF0aCA/PyByZXEucGF0aCA/PyAnJyk7XG4gICAgY29uc3QgZnVsbEtleSA9IGAke3JlcS5tZXRob2R9OiR7cm91dGVQYXRofToke29yZ0lkfToke3N1YiA/PyAnLSd9OiR7Ym9keUZpbmdlcnByaW50KHJlcS5ib2R5KX06JHtrZXl9YDtcblxuICAgIC8qKiBSZWplY3QgYSBkdXBsaWNhdGUgd2hvc2Ugb3JpZ2luYWwgaXMgc3RpbGwgaW4tZmxpZ2h0LiAqL1xuICAgIGNvbnN0IHNlbmRJblByb2dyZXNzID0gKCk6IHZvaWQgPT4ge1xuICAgICAgcmVzLnNldEhlYWRlcignUmV0cnktQWZ0ZXInLCAnMScpO1xuICAgICAgc2VuZEVycm9yKHJlcywgNDA5LCAnQSByZXF1ZXN0IHdpdGggdGhpcyBJZGVtcG90ZW5jeS1LZXkgaXMgYWxyZWFkeSBiZWluZyBwcm9jZXNzZWQnLCBFcnJvckNvZGUuQ09ORkxJQ1QpO1xuICAgIH07XG5cbiAgICBzdG9yZS5nZXQoZnVsbEtleSkudGhlbihhc3luYyAoY2FjaGVkKSA9PiB7XG4gICAgICBpZiAoY2FjaGVkICYmICFjYWNoZWQucGVuZGluZykge1xuICAgICAgICAvLyBDb21wbGV0ZWQgcmVzcG9uc2Ugb24gcmVjb3JkIOKGkiByZXBsYXkgaXQuXG4gICAgICAgIGxvZ2dlci5kZWJ1ZygnSWRlbXBvdGVudCByZXF1ZXN0IHJlcGxheWVkJywgeyBrZXk6IGZ1bGxLZXkgfSk7XG4gICAgICAgIHJlcy5zZXRIZWFkZXIoJ1gtSWRlbXBvdGVudC1SZXBsYXllZCcsICd0cnVlJyk7XG4gICAgICAgIHJlcy5zdGF0dXMoY2FjaGVkLnN0YXR1c0NvZGUpLmpzb24oY2FjaGVkLmJvZHkpO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICBpZiAoY2FjaGVkICYmIGNhY2hlZC5wZW5kaW5nKSB7XG4gICAgICAgIC8vIFRoZSBvcmlnaW5hbCBpcyBzdGlsbCBydW5uaW5nIOKAlCBkb24ndCBydW4gdGhlIG11dGF0aW9uIGEgc2Vjb25kIHRpbWUuXG4gICAgICAgIGxvZ2dlci5kZWJ1ZygnSWRlbXBvdGVudCByZXF1ZXN0IHJlamVjdGVkIChpbiBwcm9ncmVzcyknLCB7IGtleTogZnVsbEtleSB9KTtcbiAgICAgICAgcmV0dXJuIHNlbmRJblByb2dyZXNzKCk7XG4gICAgICB9XG5cbiAgICAgIC8vIEF0b21pY2FsbHkgcmVzZXJ2ZSB0aGUga2V5LiBMb3NpbmcgdGhpcyByYWNlIG1lYW5zIGEgY29uY3VycmVudCByZXF1ZXN0XG4gICAgICAvLyB3aXRoIHRoZSBzYW1lIGtleSBnb3QgdGhlcmUgZmlyc3QgYW5kIGlzIGluLWZsaWdodCDihpIgNDA5LlxuICAgICAgY29uc3Qgd29uID0gYXdhaXQgc3RvcmUucmVzZXJ2ZShcbiAgICAgICAgZnVsbEtleSxcbiAgICAgICAgeyBzdGF0dXNDb2RlOiAwLCBib2R5OiBudWxsLCBwZW5kaW5nOiB0cnVlLCBleHBpcmVzQXQ6IERhdGUubm93KCkgKyBwZW5kaW5nVHRsTXMgfSxcbiAgICAgICAgcGVuZGluZ1R0bFNlYyxcbiAgICAgICk7XG4gICAgICBpZiAoIXdvbikge1xuICAgICAgICBsb2dnZXIuZGVidWcoJ0lkZW1wb3RlbnQgcmVxdWVzdCByZWplY3RlZCAobG9zdCByZXNlcnZlIHJhY2UpJywgeyBrZXk6IGZ1bGxLZXkgfSk7XG4gICAgICAgIHJldHVybiBzZW5kSW5Qcm9ncmVzcygpO1xuICAgICAgfVxuXG4gICAgICAvLyBXZSBvd24gdGhlIHJlc2VydmF0aW9uLiBJdCBNVVNUIGJlIHJlc29sdmVkIGV4YWN0bHkgb25jZSDigJQgZWl0aGVyIHRoZVxuICAgICAgLy8gcmVhbCAyeHggcmVzcG9uc2UgaXMgY2FjaGVkIGZvciByZXBsYXksIG9yIHRoZSByZXNlcnZhdGlvbiBpcyByZWxlYXNlZCBzb1xuICAgICAgLy8gYSByZXRyeSBjYW4gcHJvY2VlZC4gYHNldHRsZWRgIGd1YXJkcyBhZ2FpbnN0IGEgZG91YmxlLXJlc29sdmUuXG4gICAgICBsZXQgc2V0dGxlZCA9IGZhbHNlO1xuICAgICAgbGV0IGNhcHR1cmVkQm9keTogdW5rbm93bjtcbiAgICAgIGxldCBib2R5Q2FwdHVyZWQgPSBmYWxzZTtcblxuICAgICAgLyoqIFJlbWVtYmVyIHRoZSByZXNwb25zZSBib2R5IGZvciByZXBsYXkgKGZpcnN0IGNhcHR1cmUgd2lucykuICovXG4gICAgICBjb25zdCBjYXB0dXJlQm9keSA9IChib2R5OiB1bmtub3duKTogdm9pZCA9PiB7XG4gICAgICAgIGlmICghYm9keUNhcHR1cmVkKSB7XG4gICAgICAgICAgY2FwdHVyZWRCb2R5ID0gYm9keTtcbiAgICAgICAgICBib2R5Q2FwdHVyZWQgPSB0cnVlO1xuICAgICAgICB9XG4gICAgICB9O1xuXG4gICAgICBjb25zdCByZWxlYXNlID0gKCk6IHZvaWQgPT4ge1xuICAgICAgICBpZiAoc2V0dGxlZCkgcmV0dXJuO1xuICAgICAgICBzZXR0bGVkID0gdHJ1ZTtcbiAgICAgICAgc3RvcmUuZGVsZXRlKGZ1bGxLZXkpLmNhdGNoKChlcnIpID0+IHtcbiAgICAgICAgICBsb2dnZXIud2FybignSWRlbXBvdGVuY3kgcmVzZXJ2YXRpb24gcmVsZWFzZSBmYWlsZWQnLCB7IGtleTogZnVsbEtleSwgZXJyb3I6IGVycm9yTWVzc2FnZShlcnIpIH0pO1xuICAgICAgICB9KTtcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IGNhY2hlU3VjY2VzcyA9ICgpOiB2b2lkID0+IHtcbiAgICAgICAgaWYgKHNldHRsZWQpIHJldHVybjtcbiAgICAgICAgc2V0dGxlZCA9IHRydWU7XG4gICAgICAgIHN0b3JlLnNldChmdWxsS2V5LCB7XG4gICAgICAgICAgc3RhdHVzQ29kZTogcmVzLnN0YXR1c0NvZGUsXG4gICAgICAgICAgYm9keTogYm9keUNhcHR1cmVkID8gY2FwdHVyZWRCb2R5IDogbnVsbCxcbiAgICAgICAgICBleHBpcmVzQXQ6IERhdGUubm93KCkgKyB0dGxNcyxcbiAgICAgICAgfSwgdHRsU2VjKS5jYXRjaCgoZXJyKSA9PiB7XG4gICAgICAgICAgbG9nZ2VyLndhcm4oJ0lkZW1wb3RlbmN5IHN0b3JlLnNldCBmYWlsZWQnLCB7IGtleTogZnVsbEtleSwgZXJyb3I6IGVycm9yTWVzc2FnZShlcnIpIH0pO1xuICAgICAgICB9KTtcbiAgICAgIH07XG5cbiAgICAgIC8qKlxuICAgICAgICogUmVzb2x2ZSB0aGUgcmVzZXJ2YXRpb24gZnJvbSB0aGUgQUNUVUFMIGZpbmFsIHN0YXR1czogYSAyeHggaXMgY2FjaGVkIGZvclxuICAgICAgICogcmVwbGF5OyBhbnl0aGluZyBlbHNlICh0aGUgaGFuZGxlciByZWZ1c2VkIG9yIGZhaWxlZCDigJQgdGhlIG11dGF0aW9uIGRpZFxuICAgICAgICogbm90IHRha2UgZWZmZWN0KSByZWxlYXNlcyB0aGUga2V5IHNvIGEgcmV0cnkgZ2VudWluZWx5IHJlLXJ1bnMuXG4gICAgICAgKi9cbiAgICAgIGNvbnN0IHNldHRsZUZyb21TdGF0dXMgPSAoKTogdm9pZCA9PiB7XG4gICAgICAgIGlmIChzZXR0bGVkKSByZXR1cm47XG4gICAgICAgIGlmIChyZXMuc3RhdHVzQ29kZSA+PSAyMDAgJiYgcmVzLnN0YXR1c0NvZGUgPCAzMDApIGNhY2hlU3VjY2VzcygpO1xuICAgICAgICBlbHNlIHJlbGVhc2UoKTtcbiAgICAgIH07XG5cbiAgICAgIC8vIEZhc3QgcGF0aDogcmVzLmpzb24gaXMgdGhlIGNvbW1vbiBjb21wbGV0aW9uLiBDYXB0dXJlIHRoZSBib2R5IGFuZCBzZXR0bGVcbiAgICAgIC8vIGltbWVkaWF0ZWx5IG9mZiB0aGUgc3RhdHVzIHNldCBieSByZXMuc3RhdHVzKC4uLikuanNvbiguLi4pLlxuICAgICAgY29uc3Qgb3JpZ2luYWxKc29uID0gcmVzLmpzb24uYmluZChyZXMpO1xuICAgICAgcmVzLmpzb24gPSAoYm9keTogdW5rbm93bikgPT4ge1xuICAgICAgICByZXMuc2V0SGVhZGVyKCdYLUlkZW1wb3RlbnQtUmVwbGF5ZWQnLCAnZmFsc2UnKTtcbiAgICAgICAgY2FwdHVyZUJvZHkoYm9keSk7XG4gICAgICAgIHNldHRsZUZyb21TdGF0dXMoKTtcbiAgICAgICAgcmV0dXJuIG9yaWdpbmFsSnNvbihib2R5KTtcbiAgICAgIH07XG5cbiAgICAgIC8vIEJvZHktY2FwdHVyZSBiYWNrc3RvcHMgZm9yIGNvbXBsZXRpb25zIHRoYXQgYnlwYXNzIHJlcy5qc29uXG4gICAgICAvLyAocmVzLnNlbmQgLyByZXMuZW5kIC8gcmVzLnNlbmRGaWxlIOKGkiByZXMuZW5kKS4gVGhlc2Ugb25seSBSRUNPUkQgdGhlIGJvZHk7XG4gICAgICAvLyB0aGUgYWN0dWFsIHNldHRsZSBoYXBwZW5zIG9uIGBmaW5pc2hgIGZyb20gdGhlIHJlYWwgc3RhdHVzIGNvZGUuIEZpcnN0XG4gICAgICAvLyBjYXB0dXJlIHdpbnMsIHNvIHJlcy5qc29uJ3MgYm9keSBpcyBuZXZlciBjbG9iYmVyZWQgYnkgaXRzIGludGVybmFsXG4gICAgICAvLyByZXMuc2VuZC9yZXMuZW5kIGNhbGxzLlxuICAgICAgY29uc3QgcGF0Y2hlZCA9IHJlcyBhcyB1bmtub3duIGFzIHtcbiAgICAgICAgc2VuZD86IChib2R5PzogdW5rbm93bikgPT4gdW5rbm93bjtcbiAgICAgICAgZW5kPzogKC4uLmFyZ3M6IHVua25vd25bXSkgPT4gdW5rbm93bjtcbiAgICAgICAgb24/OiAoZXZlbnQ6IHN0cmluZywgY2I6ICgpID0+IHZvaWQpID0+IHVua25vd247XG4gICAgICB9O1xuICAgICAgaWYgKHR5cGVvZiBwYXRjaGVkLnNlbmQgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgY29uc3Qgb3JpZ2luYWxTZW5kID0gcGF0Y2hlZC5zZW5kLmJpbmQocmVzKTtcbiAgICAgICAgcGF0Y2hlZC5zZW5kID0gKGJvZHk/OiB1bmtub3duKSA9PiB7XG4gICAgICAgICAgY2FwdHVyZUJvZHkoYm9keSk7XG4gICAgICAgICAgcmV0dXJuIG9yaWdpbmFsU2VuZChib2R5KTtcbiAgICAgICAgfTtcbiAgICAgIH1cbiAgICAgIGlmICh0eXBlb2YgcGF0Y2hlZC5lbmQgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgY29uc3Qgb3JpZ2luYWxFbmQgPSBwYXRjaGVkLmVuZC5iaW5kKHJlcyk7XG4gICAgICAgIHBhdGNoZWQuZW5kID0gKC4uLmFyZ3M6IHVua25vd25bXSkgPT4ge1xuICAgICAgICAgIGNvbnN0IGNodW5rID0gYXJnc1swXTtcbiAgICAgICAgICBpZiAoY2h1bmsgIT09IHVuZGVmaW5lZCAmJiB0eXBlb2YgY2h1bmsgIT09ICdmdW5jdGlvbicpIGNhcHR1cmVCb2R5KGNodW5rKTtcbiAgICAgICAgICBjb25zdCBvdXQgPSBvcmlnaW5hbEVuZCguLi5hcmdzKTtcbiAgICAgICAgICAvLyBUaGUgaGFuZGxlciBoYXMgcHJvZHVjZWQgaXRzIGZpbmFsIHN0YXR1cy4gU2V0dGxlIEhFUkUgcmF0aGVyIHRoYW5cbiAgICAgICAgICAvLyB3YWl0aW5nIGZvciAnZmluaXNoJzogYWZ0ZXIgYSBjbGllbnQgZGlzY29ubmVjdCAnZmluaXNoJyBuZXZlciBmaXJlcyxcbiAgICAgICAgICAvLyBhbmQgdGhlIGhhbmRsZXIncyBvdXRjb21lIG11c3Qgc3RpbGwgYmUgcmVjb3JkZWQuXG4gICAgICAgICAgc2V0dGxlRnJvbVN0YXR1cygpO1xuICAgICAgICAgIHJldHVybiBvdXQ7XG4gICAgICAgIH07XG4gICAgICB9XG5cbiAgICAgIC8vIEJhY2tzdG9wIGZvciBBTlkgY29tcGxldGlvbiBwYXRoIOKAlCBpbmNsdWRpbmcgYSAyeHggdGhhdCBmaW5pc2hlZCB2aWFcbiAgICAgIC8vIHJlcy5zZW5kL3Jlcy5lbmQvcmVzLnNlbmRGaWxlLzIwNCBhbmQgbmV2ZXIgaGl0IHRoZSBwYXRjaGVkIHJlcy5qc29uLlxuICAgICAgLy8gRGVjaWRpbmcgb24gdGhlIHJlYWwgZmluYWwgc3RhdHVzIGhlcmUgbWVhbnMgYSBzdWNjZXNzZnVsIG9wIGlzIGNhY2hlZFxuICAgICAgLy8gKG9yIGEgZmFpbGVkIG9uZSByZWxlYXNlZCkgaW5zdGVhZCBvZiBzdHJhbmRpbmcgdGhlIHJlc2VydmF0aW9uIGFuZFxuICAgICAgLy8gNDA5LWluZyBldmVyeSByZXRyeSBmb3IgdGhlIGZ1bGwgVFRMLiBHdWFyZGVkIOKAlCB0ZXN0IGRvdWJsZXMgbWF5IG5vdCBiZVxuICAgICAgLy8gRXZlbnRFbWl0dGVyczsgcmVzLmpzb24ncyBmYXN0IHBhdGggYWxyZWFkeSBzZXR0bGVkIHRoZSBjb21tb24gY2FzZS5cbiAgICAgIGlmICh0eXBlb2YgcGF0Y2hlZC5vbiA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICBwYXRjaGVkLm9uKCdmaW5pc2gnLCBzZXR0bGVGcm9tU3RhdHVzKTtcbiAgICAgICAgLy8gQSBjbGllbnQgdGhhdCBkaXNjb25uZWN0cyBlbWl0cyAnY2xvc2UnIFdJVEhPVVQgJ2ZpbmlzaCcg4oCUIGJ1dCB0aGVcbiAgICAgICAgLy8gSEFORExFUiBrZWVwcyBydW5uaW5nIGFuZCBtYXkgc3RpbGwgY29tbWl0IHRoZSBtdXRhdGlvbi4gUmVsZWFzaW5nXG4gICAgICAgIC8vIGhlcmUgbGV0IHRoZSBjbGllbnQncyByZXRyeSBydW4gaXQgYSBzZWNvbmQgdGltZSAoYSBkdXBsaWNhdGUgY3JlYXRlIC9cbiAgICAgICAgLy8gZG91YmxlIGNoYXJnZSDigJQgdGhlIHZlcnkgdGhpbmcgdGhlIGtleSBleGlzdHMgdG8gcHJldmVudCkuIFNvIHRoZVxuICAgICAgICAvLyByZXNlcnZhdGlvbiBzdGF5cyBwZW5kaW5nOiB0aGUgaGFuZGxlcidzIG93biBjb21wbGV0aW9uIHNldHRsZXMgaXRcbiAgICAgICAgLy8gKHJlcy5qc29uIC8gcmVzLmVuZCBhYm92ZSksIGFuZCBpZiB0aGUgcHJvY2VzcyBkaWVzIGluc3RlYWQsIHRoZVxuICAgICAgICAvLyBzaG9ydCBwZW5kaW5nIFRUTCBmcmVlcyB0aGUga2V5LlxuICAgICAgfVxuXG4gICAgICBuZXh0KCk7XG4gICAgfSkuY2F0Y2goKGVycikgPT4ge1xuICAgICAgLy8gSWYgdGhlIHN0b3JlIGJhY2tlbmQgaXMgZG93biwgZmFpbCBvcGVuIOKAlCBwcm9jZXNzIHRoZSByZXF1ZXN0IG5vcm1hbGx5LlxuICAgICAgbG9nZ2VyLndhcm4oJ0lkZW1wb3RlbmN5IHN0b3JlLmdldCBmYWlsZWQ7IHByb2NlZWRpbmcgd2l0aG91dCBkZWR1cCcsIHsga2V5OiBmdWxsS2V5LCBlcnJvcjogZXJyb3JNZXNzYWdlKGVycikgfSk7XG4gICAgICBuZXh0KCk7XG4gICAgfSk7XG4gIH07XG59XG4iXX0=
400
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaWRlbXBvdGVuY3ktbWlkZGxld2FyZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9hcGkvaWRlbXBvdGVuY3ktbWlkZGxld2FyZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSwrQ0FBK0M7QUFDL0Msc0NBQXNDO0FBRXRDLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxRQUFRLENBQUM7QUFDcEMsT0FBTyxFQUFFLFlBQVksRUFBRSxTQUFTLEVBQUUsU0FBUyxFQUFFLG9CQUFvQixFQUFFLFlBQVksRUFBRSxlQUFlLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQUNySSxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0saUNBQWlDLENBQUM7QUFHaEUsTUFBTSxNQUFNLEdBQUcsWUFBWSxDQUFDLGFBQWEsQ0FBQyxDQUFDO0FBRTNDOzs7OztHQUtHO0FBQ0gsU0FBUyxlQUFlLENBQUMsSUFBYTtJQUNwQyxJQUFJLElBQUksS0FBSyxTQUFTLElBQUksSUFBSSxLQUFLLElBQUk7UUFBRSxPQUFPLEdBQUcsQ0FBQztJQUNwRCxJQUFJLE9BQU8sSUFBSSxLQUFLLFFBQVEsSUFBSSxNQUFNLENBQUMsSUFBSSxDQUFDLElBQWMsQ0FBQyxDQUFDLE1BQU0sS0FBSyxDQUFDO1FBQUUsT0FBTyxHQUFHLENBQUM7SUFDckYsSUFBSSxDQUFDO1FBQ0gsT0FBTyxVQUFVLENBQUMsUUFBUSxDQUFDLENBQUMsTUFBTSxDQUFDLGVBQWUsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDO0lBQ3ZGLENBQUM7SUFBQyxNQUFNLENBQUM7UUFDUCwwRUFBMEU7UUFDMUUsdUVBQXVFO1FBQ3ZFLE9BQU8sR0FBRyxDQUFDO0lBQ2IsQ0FBQztBQUNILENBQUM7QUFpQ0QsMEVBQTBFO0FBQzFFLE1BQU0sVUFBVSxpQkFBaUI7SUFDL0IsTUFBTSxHQUFHLEdBQUcsSUFBSSxHQUFHLEVBQXVCLENBQUM7SUFDM0MsTUFBTSxZQUFZLEdBQUcsV0FBVyxDQUFDLEdBQUcsRUFBRTtRQUNwQyxNQUFNLEdBQUcsR0FBRyxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUM7UUFDdkIsS0FBSyxNQUFNLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxJQUFJLEdBQUcsRUFBRSxDQUFDO1lBQ3pCLElBQUksR0FBRyxHQUFHLENBQUMsQ0FBQyxTQUFTO2dCQUFFLEdBQUcsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDdkMsQ0FBQztJQUNILENBQUMsRUFBRSxhQUFhLENBQUMsK0JBQStCLENBQUMsQ0FBQztJQUNsRCxZQUFZLENBQUMsS0FBSyxFQUFFLENBQUM7SUFFckIsMEVBQTBFO0lBQzFFLE1BQU0sSUFBSSxHQUFHLENBQUMsR0FBVyxFQUFzQixFQUFFO1FBQy9DLE1BQU0sS0FBSyxHQUFHLEdBQUcsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDM0IsSUFBSSxDQUFDLEtBQUs7WUFBRSxPQUFPLElBQUksQ0FBQztRQUN4QixJQUFJLElBQUksQ0FBQyxHQUFHLEVBQUUsR0FBRyxLQUFLLENBQUMsU0FBUyxFQUFFLENBQUM7WUFDakMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQztZQUNoQixPQUFPLElBQUksQ0FBQztRQUNkLENBQUM7UUFDRCxPQUFPLEtBQUssQ0FBQztJQUNmLENBQUMsQ0FBQztJQUNGOzs7OztPQUtHO0lBQ0gsTUFBTSxXQUFXLEdBQUcsQ0FBQyxHQUFXLEVBQVEsRUFBRTtRQUN4QyxJQUFJLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsSUFBSSxHQUFHLENBQUMsSUFBSSxJQUFJLGFBQWEsQ0FBQywwQkFBMEIsRUFBRSxDQUFDO1lBQzFFLE1BQU0sTUFBTSxHQUFHLEdBQUcsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxLQUFLLENBQUM7WUFDdkMsSUFBSSxNQUFNLEtBQUssU0FBUztnQkFBRSxHQUFHLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQy9DLENBQUM7SUFDSCxDQUFDLENBQUM7SUFDRixPQUFPO1FBQ0wsS0FBSyxDQUFDLEdBQUcsQ0FBQyxHQUFHO1lBQ1gsT0FBTyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDbkIsQ0FBQztRQUNELEtBQUssQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLEtBQUs7WUFDbEIsV0FBVyxDQUFDLEdBQUcsQ0FBQyxDQUFDO1lBQ2pCLEdBQUcsQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLEtBQUssQ0FBQyxDQUFDO1FBQ3RCLENBQUM7UUFDRCxLQUFLLENBQUMsT0FBTyxDQUFDLEdBQUcsRUFBRSxLQUFLO1lBQ3RCLDJFQUEyRTtZQUMzRSxzRUFBc0U7WUFDdEUsSUFBSSxJQUFJLENBQUMsR0FBRyxDQUFDO2dCQUFFLE9BQU8sS0FBSyxDQUFDO1lBQzVCLFdBQVcsQ0FBQyxHQUFHLENBQUMsQ0FBQztZQUNqQixHQUFHLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBRSxLQUFLLENBQUMsQ0FBQztZQUNwQixPQUFPLElBQUksQ0FBQztRQUNkLENBQUM7UUFDRCxLQUFLLENBQUMsTUFBTSxDQUFDLEdBQUc7WUFDZCxHQUFHLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQ2xCLENBQUM7S0FDRixDQUFDO0FBQ0osQ0FBQztBQWFELE1BQU0sZ0JBQWdCLEdBQUcsT0FBTyxDQUFDO0FBRWpDOzs7Ozs7O0dBT0c7QUFDSCxNQUFNLFVBQVUsMkJBQTJCLENBQUMsS0FBNkI7SUFDdkUsTUFBTSxDQUFDLEdBQUcsQ0FBQyxHQUFXLEVBQVUsRUFBRSxDQUFDLEdBQUcsZ0JBQWdCLEdBQUcsR0FBRyxFQUFFLENBQUM7SUFDL0QsT0FBTztRQUNMLEtBQUssQ0FBQyxHQUFHLENBQUMsR0FBRztZQUNYLE1BQU0sR0FBRyxHQUFHLE1BQU0sS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztZQUNwQyxJQUFJLENBQUMsR0FBRztnQkFBRSxPQUFPLElBQUksQ0FBQztZQUN0QixJQUFJLENBQUM7Z0JBQ0gsT0FBTyxJQUFJLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBZ0IsQ0FBQztZQUN4QyxDQUFDO1lBQUMsTUFBTSxDQUFDO2dCQUNQLGlFQUFpRTtnQkFDakUsT0FBTyxJQUFJLENBQUM7WUFDZCxDQUFDO1FBQ0gsQ0FBQztRQUNELEtBQUssQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLEtBQUssRUFBRSxVQUFVO1lBQzlCLE1BQU0sS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsRUFBRSxJQUFJLEVBQUUsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsVUFBVSxDQUFDLENBQUMsQ0FBQztRQUNoRixDQUFDO1FBQ0QsS0FBSyxDQUFDLE9BQU8sQ0FBQyxHQUFHLEVBQUUsS0FBSyxFQUFFLFVBQVU7WUFDbEMseUVBQXlFO1lBQ3pFLE1BQU0sR0FBRyxHQUFHLE1BQU0sS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsRUFBRSxJQUFJLEVBQUUsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsVUFBVSxDQUFDLEVBQUUsSUFBSSxDQUFDLENBQUM7WUFDaEcsT0FBTyxHQUFHLEtBQUssSUFBSSxDQUFDO1FBQ3RCLENBQUM7UUFDRCxLQUFLLENBQUMsTUFBTSxDQUFDLEdBQUc7WUFDZCxNQUFNLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7UUFDMUIsQ0FBQztLQUNGLENBQUM7QUFDSixDQUFDO0FBRUQ7Ozs7O0dBS0c7QUFDSCxNQUFNLFVBQVUsOEJBQThCO0lBQzVDLE1BQU0sTUFBTSxHQUFHLG9CQUFvQixDQUF5QixhQUFhLENBQUMsQ0FBQztJQUMzRSxJQUFJLENBQUMsTUFBTTtRQUFFLE9BQU8sSUFBSSxDQUFDO0lBQ3pCLE1BQU0sQ0FBQyxJQUFJLENBQUMscUNBQXFDLENBQUMsQ0FBQztJQUNuRCxPQUFPLDJCQUEyQixDQUFDLE1BQU0sQ0FBQyxDQUFDO0FBQzdDLENBQUM7QUFFRCxNQUFNLFdBQVcsR0FBRyxpQkFBaUIsRUFBRSxDQUFDO0FBRXhDOzs7Ozs7R0FNRztBQUNILElBQUksWUFBWSxHQUFxQixXQUFXLENBQUM7QUFFakQsMkVBQTJFO0FBQzNFLE1BQU0sVUFBVSxtQkFBbUIsQ0FBQyxLQUF1QjtJQUN6RCxZQUFZLEdBQUcsS0FBSyxDQUFDO0FBQ3ZCLENBQUM7QUFFRCw0RUFBNEU7QUFDNUUsTUFBTSxVQUFVLG1CQUFtQjtJQUNqQyxPQUFPLFlBQVksQ0FBQztBQUN0QixDQUFDO0FBRUQ7Ozs7OztHQU1HO0FBQ0gsTUFBTSxtQkFBbUIsR0FBRyxNQUFNLENBQUMsc0NBQXNDLENBQUMsQ0FBQztBQUUzRTs7Ozs7R0FLRztBQUNILE1BQU0sQ0FBQyxNQUFNLHVCQUF1QixHQUFHLGtCQUFrQixDQUFDO0FBRTFELG1FQUFtRTtBQUNuRSxNQUFNLFVBQVUsa0JBQWtCLENBQUMsR0FBYTtJQUM5QyxPQUFPLEdBQUcsQ0FBQyxNQUFNLEVBQUUsQ0FBQyx1QkFBdUIsQ0FBQyxLQUFLLElBQUksQ0FBQztBQUN4RCxDQUFDO0FBRUQ7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQXFCRztBQUNILFNBQVMsbUJBQW1CLENBQUMsR0FBWSxFQUFFLEdBQVc7SUFDcEQsTUFBTSxLQUFLLEdBQUcsR0FBRyxDQUFDLElBQUksRUFBRSxjQUFjLElBQUksR0FBRyxDQUFDLE9BQU8sRUFBRSxRQUFRLEVBQUUsS0FBSyxDQUFDO0lBQ3ZFLElBQUksQ0FBQyxLQUFLO1FBQUUsT0FBTyxTQUFTLENBQUM7SUFDN0IsTUFBTSxHQUFHLEdBQUcsR0FBRyxDQUFDLElBQUksRUFBRSxHQUFHLENBQUM7SUFDMUIsTUFBTSxTQUFTLEdBQUcsQ0FBQyxHQUFHLENBQUMsT0FBTyxJQUFJLEVBQUUsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLEtBQUssRUFBRSxJQUFJLElBQUksR0FBRyxDQUFDLElBQUksSUFBSSxFQUFFLENBQUMsQ0FBQztJQUM1RSxPQUFPLEdBQUcsR0FBRyxDQUFDLE1BQU0sSUFBSSxTQUFTLElBQUksS0FBSyxJQUFJLEdBQUcsSUFBSSxHQUFHLElBQUksZUFBZSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsSUFBSSxHQUFHLEVBQUUsQ0FBQztBQUNqRyxDQUFDO0FBRUQscURBQXFEO0FBQ3JELE1BQU0sa0JBQWtCLEdBQUcsQ0FBQyxNQUFNLEVBQUUsS0FBSyxFQUFFLFFBQVEsQ0FBQyxDQUFDO0FBRXJEOzs7Ozs7Ozs7OztHQVdHO0FBQ0gsTUFBTSxDQUFDLEtBQUssVUFBVSw4QkFBOEIsQ0FBQyxHQUFZO0lBQy9ELE1BQU0sR0FBRyxHQUFHLEdBQUcsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDO0lBQzdDLElBQUksT0FBTyxHQUFHLEtBQUssUUFBUSxJQUFJLENBQUMsR0FBRyxJQUFJLENBQUMsa0JBQWtCLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUM7UUFBRSxPQUFPLEtBQUssQ0FBQztJQUM5RixNQUFNLE9BQU8sR0FBRyxtQkFBbUIsQ0FBQyxHQUFHLEVBQUUsR0FBRyxDQUFDLENBQUM7SUFDOUMsSUFBSSxDQUFDLE9BQU87UUFBRSxPQUFPLEtBQUssQ0FBQztJQUMzQixJQUFJLENBQUM7UUFDSCxNQUFNLE1BQU0sR0FBRyxNQUFNLFlBQVksQ0FBQyxHQUFHLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDL0MsT0FBTyxDQUFDLENBQUMsTUFBTSxJQUFJLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQztJQUNyQyxDQUFDO0lBQUMsTUFBTSxDQUFDO1FBQ1AsT0FBTyxLQUFLLENBQUM7SUFDZixDQUFDO0FBQ0gsQ0FBQztBQVFEOzs7Ozs7Ozs7O0dBVUc7QUFDSCxNQUFNLFVBQVUscUJBQXFCLENBQUMsT0FBTyxHQUFpQyxFQUFFO0lBQzlFLDZFQUE2RTtJQUM3RSw2RUFBNkU7SUFDN0UsK0JBQStCO0lBQy9CLE1BQU0sYUFBYSxHQUFHLE9BQU8sQ0FBQyxLQUFLLENBQUM7SUFDcEMsTUFBTSxLQUFLLEdBQUcsYUFBYSxDQUFDLGtCQUFrQixDQUFDO0lBQy9DLE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsS0FBSyxHQUFHLElBQUksQ0FBQyxDQUFDO0lBQ3hDLHVFQUF1RTtJQUN2RSw0RUFBNEU7SUFDNUUsNERBQTREO0lBQzVELE1BQU0sWUFBWSxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsYUFBYSxDQUFDLDBCQUEwQixFQUFFLEtBQUssQ0FBQyxDQUFDO0lBQy9FLE1BQU0sYUFBYSxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLElBQUksQ0FBQyxLQUFLLENBQUMsWUFBWSxHQUFHLElBQUksQ0FBQyxDQUFDLENBQUM7SUFFbkUsT0FBTyxDQUFDLEdBQVksRUFBRSxHQUFhLEVBQUUsSUFBa0IsRUFBRSxFQUFFO1FBQ3pELE1BQU0sS0FBSyxHQUFHLGFBQWEsSUFBSSxZQUFZLENBQUM7UUFDNUMsTUFBTSxHQUFHLEdBQUcsR0FBRyxDQUFDLE9BQU8sQ0FBQyxpQkFBaUIsQ0FBdUIsQ0FBQztRQUNqRSxJQUFJLENBQUMsR0FBRztZQUFFLE9BQU8sSUFBSSxFQUFFLENBQUM7UUFFeEIsaUNBQWlDO1FBQ2pDLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQztZQUFFLE9BQU8sSUFBSSxFQUFFLENBQUM7UUFFNUQseUVBQXlFO1FBQ3pFLE1BQU0sTUFBTSxHQUFHLEdBQWlELENBQUM7UUFDakUsSUFBSSxNQUFNLENBQUMsbUJBQW1CLENBQUM7WUFBRSxPQUFPLElBQUksRUFBRSxDQUFDO1FBRS9DLE1BQU0sT0FBTyxHQUFHLG1CQUFtQixDQUFDLEdBQUcsRUFBRSxHQUFHLENBQUMsQ0FBQztRQUM5QyxJQUFJLENBQUMsT0FBTztZQUFFLE9BQU8sSUFBSSxFQUFFLENBQUMsQ0FBQyxnREFBZ0Q7UUFDN0UsTUFBTSxDQUFDLG1CQUFtQixDQUFDLEdBQUcsSUFBSSxDQUFDO1FBRW5DLDREQUE0RDtRQUM1RCxNQUFNLGNBQWMsR0FBRyxHQUFTLEVBQUU7WUFDaEMsR0FBRyxDQUFDLFNBQVMsQ0FBQyxhQUFhLEVBQUUsR0FBRyxDQUFDLENBQUM7WUFDbEMsU0FBUyxDQUFDLEdBQUcsRUFBRSxHQUFHLEVBQUUsZ0VBQWdFLEVBQUUsU0FBUyxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQzVHLENBQUMsQ0FBQztRQUVGLEtBQUssQ0FBQyxHQUFHLENBQUMsT0FBTyxDQUFDLENBQUMsSUFBSSxDQUFDLEtBQUssRUFBRSxNQUFNLEVBQUUsRUFBRTtZQUN2QyxJQUFJLE1BQU0sSUFBSSxDQUFDLE1BQU0sQ0FBQyxPQUFPLEVBQUUsQ0FBQztnQkFDOUIsNENBQTRDO2dCQUM1QyxNQUFNLENBQUMsS0FBSyxDQUFDLDZCQUE2QixFQUFFLEVBQUUsR0FBRyxFQUFFLE9BQU8sRUFBRSxDQUFDLENBQUM7Z0JBQzlELENBQUMsR0FBRyxDQUFDLE1BQU0sS0FBSyxFQUFFLENBQUMsQ0FBQyx1QkFBdUIsQ0FBQyxHQUFHLElBQUksQ0FBQztnQkFDcEQsR0FBRyxDQUFDLFNBQVMsQ0FBQyx1QkFBdUIsRUFBRSxNQUFNLENBQUMsQ0FBQztnQkFDL0MsR0FBRyxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsVUFBVSxDQUFDLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQztnQkFDaEQsT0FBTztZQUNULENBQUM7WUFDRCxJQUFJLE1BQU0sSUFBSSxNQUFNLENBQUMsT0FBTyxFQUFFLENBQUM7Z0JBQzdCLHdFQUF3RTtnQkFDeEUsTUFBTSxDQUFDLEtBQUssQ0FBQywyQ0FBMkMsRUFBRSxFQUFFLEdBQUcsRUFBRSxPQUFPLEVBQUUsQ0FBQyxDQUFDO2dCQUM1RSxPQUFPLGNBQWMsRUFBRSxDQUFDO1lBQzFCLENBQUM7WUFFRCwwRUFBMEU7WUFDMUUsNERBQTREO1lBQzVELE1BQU0sR0FBRyxHQUFHLE1BQU0sS0FBSyxDQUFDLE9BQU8sQ0FDN0IsT0FBTyxFQUNQLEVBQUUsVUFBVSxFQUFFLENBQUMsRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFFLE9BQU8sRUFBRSxJQUFJLEVBQUUsU0FBUyxFQUFFLElBQUksQ0FBQyxHQUFHLEVBQUUsR0FBRyxZQUFZLEVBQUUsRUFDbEYsYUFBYSxDQUNkLENBQUM7WUFDRixJQUFJLENBQUMsR0FBRyxFQUFFLENBQUM7Z0JBQ1QsTUFBTSxDQUFDLEtBQUssQ0FBQyxpREFBaUQsRUFBRSxFQUFFLEdBQUcsRUFBRSxPQUFPLEVBQUUsQ0FBQyxDQUFDO2dCQUNsRixPQUFPLGNBQWMsRUFBRSxDQUFDO1lBQzFCLENBQUM7WUFFRCx3RUFBd0U7WUFDeEUsNEVBQTRFO1lBQzVFLGtFQUFrRTtZQUNsRSxJQUFJLE9BQU8sR0FBRyxLQUFLLENBQUM7WUFDcEIsSUFBSSxZQUFxQixDQUFDO1lBQzFCLElBQUksWUFBWSxHQUFHLEtBQUssQ0FBQztZQUV6QixrRUFBa0U7WUFDbEUsTUFBTSxXQUFXLEdBQUcsQ0FBQyxJQUFhLEVBQVEsRUFBRTtnQkFDMUMsSUFBSSxDQUFDLFlBQVksRUFBRSxDQUFDO29CQUNsQixZQUFZLEdBQUcsSUFBSSxDQUFDO29CQUNwQixZQUFZLEdBQUcsSUFBSSxDQUFDO2dCQUN0QixDQUFDO1lBQ0gsQ0FBQyxDQUFDO1lBRUYsTUFBTSxPQUFPLEdBQUcsR0FBUyxFQUFFO2dCQUN6QixJQUFJLE9BQU87b0JBQUUsT0FBTztnQkFDcEIsT0FBTyxHQUFHLElBQUksQ0FBQztnQkFDZixLQUFLLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLEdBQUcsRUFBRSxFQUFFO29CQUNsQyxNQUFNLENBQUMsSUFBSSxDQUFDLHdDQUF3QyxFQUFFLEVBQUUsR0FBRyxFQUFFLE9BQU8sRUFBRSxLQUFLLEVBQUUsWUFBWSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsQ0FBQztnQkFDcEcsQ0FBQyxDQUFDLENBQUM7WUFDTCxDQUFDLENBQUM7WUFFRixNQUFNLFlBQVksR0FBRyxHQUFTLEVBQUU7Z0JBQzlCLElBQUksT0FBTztvQkFBRSxPQUFPO2dCQUNwQixPQUFPLEdBQUcsSUFBSSxDQUFDO2dCQUNmLEtBQUssQ0FBQyxHQUFHLENBQUMsT0FBTyxFQUFFO29CQUNqQixVQUFVLEVBQUUsR0FBRyxDQUFDLFVBQVU7b0JBQzFCLElBQUksRUFBRSxZQUFZLENBQUMsQ0FBQyxDQUFDLFlBQVksQ0FBQyxDQUFDLENBQUMsSUFBSTtvQkFDeEMsU0FBUyxFQUFFLElBQUksQ0FBQyxHQUFHLEVBQUUsR0FBRyxLQUFLO2lCQUM5QixFQUFFLE1BQU0sQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLEdBQUcsRUFBRSxFQUFFO29CQUN2QixNQUFNLENBQUMsSUFBSSxDQUFDLDhCQUE4QixFQUFFLEVBQUUsR0FBRyxFQUFFLE9BQU8sRUFBRSxLQUFLLEVBQUUsWUFBWSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsQ0FBQztnQkFDMUYsQ0FBQyxDQUFDLENBQUM7WUFDTCxDQUFDLENBQUM7WUFFRjs7OztlQUlHO1lBQ0gsTUFBTSxnQkFBZ0IsR0FBRyxHQUFTLEVBQUU7Z0JBQ2xDLElBQUksT0FBTztvQkFBRSxPQUFPO2dCQUNwQixJQUFJLEdBQUcsQ0FBQyxVQUFVLElBQUksR0FBRyxJQUFJLEdBQUcsQ0FBQyxVQUFVLEdBQUcsR0FBRztvQkFBRSxZQUFZLEVBQUUsQ0FBQzs7b0JBQzdELE9BQU8sRUFBRSxDQUFDO1lBQ2pCLENBQUMsQ0FBQztZQUVGLDRFQUE0RTtZQUM1RSwrREFBK0Q7WUFDL0QsTUFBTSxZQUFZLEdBQUcsR0FBRyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUM7WUFDeEMsR0FBRyxDQUFDLElBQUksR0FBRyxDQUFDLElBQWEsRUFBRSxFQUFFO2dCQUMzQixHQUFHLENBQUMsU0FBUyxDQUFDLHVCQUF1QixFQUFFLE9BQU8sQ0FBQyxDQUFDO2dCQUNoRCxXQUFXLENBQUMsSUFBSSxDQUFDLENBQUM7Z0JBQ2xCLGdCQUFnQixFQUFFLENBQUM7Z0JBQ25CLE9BQU8sWUFBWSxDQUFDLElBQUksQ0FBQyxDQUFDO1lBQzVCLENBQUMsQ0FBQztZQUVGLDhEQUE4RDtZQUM5RCw2RUFBNkU7WUFDN0UseUVBQXlFO1lBQ3pFLHNFQUFzRTtZQUN0RSwwQkFBMEI7WUFDMUIsTUFBTSxPQUFPLEdBQUcsR0FJZixDQUFDO1lBQ0YsSUFBSSxPQUFPLE9BQU8sQ0FBQyxJQUFJLEtBQUssVUFBVSxFQUFFLENBQUM7Z0JBQ3ZDLE1BQU0sWUFBWSxHQUFHLE9BQU8sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDO2dCQUM1QyxPQUFPLENBQUMsSUFBSSxHQUFHLENBQUMsSUFBYyxFQUFFLEVBQUU7b0JBQ2hDLFdBQVcsQ0FBQyxJQUFJLENBQUMsQ0FBQztvQkFDbEIsT0FBTyxZQUFZLENBQUMsSUFBSSxDQUFDLENBQUM7Z0JBQzVCLENBQUMsQ0FBQztZQUNKLENBQUM7WUFDRCxJQUFJLE9BQU8sT0FBTyxDQUFDLEdBQUcsS0FBSyxVQUFVLEVBQUUsQ0FBQztnQkFDdEMsTUFBTSxXQUFXLEdBQUcsT0FBTyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUM7Z0JBQzFDLE9BQU8sQ0FBQyxHQUFHLEdBQUcsQ0FBQyxHQUFHLElBQWUsRUFBRSxFQUFFO29CQUNuQyxNQUFNLEtBQUssR0FBRyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUM7b0JBQ3RCLElBQUksS0FBSyxLQUFLLFNBQVMsSUFBSSxPQUFPLEtBQUssS0FBSyxVQUFVO3dCQUFFLFdBQVcsQ0FBQyxLQUFLLENBQUMsQ0FBQztvQkFDM0UsTUFBTSxHQUFHLEdBQUcsV0FBVyxDQUFDLEdBQUcsSUFBSSxDQUFDLENBQUM7b0JBQ2pDLHFFQUFxRTtvQkFDckUsd0VBQXdFO29CQUN4RSxvREFBb0Q7b0JBQ3BELGdCQUFnQixFQUFFLENBQUM7b0JBQ25CLE9BQU8sR0FBRyxDQUFDO2dCQUNiLENBQUMsQ0FBQztZQUNKLENBQUM7WUFFRCx1RUFBdUU7WUFDdkUsd0VBQXdFO1lBQ3hFLHlFQUF5RTtZQUN6RSxzRUFBc0U7WUFDdEUsMEVBQTBFO1lBQzFFLHVFQUF1RTtZQUN2RSxJQUFJLE9BQU8sT0FBTyxDQUFDLEVBQUUsS0FBSyxVQUFVLEVBQUUsQ0FBQztnQkFDckMsT0FBTyxDQUFDLEVBQUUsQ0FBQyxRQUFRLEVBQUUsZ0JBQWdCLENBQUMsQ0FBQztnQkFDdkMscUVBQXFFO2dCQUNyRSxxRUFBcUU7Z0JBQ3JFLHlFQUF5RTtnQkFDekUsb0VBQW9FO2dCQUNwRSxxRUFBcUU7Z0JBQ3JFLG1FQUFtRTtnQkFDbkUsbUNBQW1DO1lBQ3JDLENBQUM7WUFFRCxJQUFJLEVBQUUsQ0FBQztRQUNULENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLEdBQUcsRUFBRSxFQUFFO1lBQ2YsMEVBQTBFO1lBQzFFLE1BQU0sQ0FBQyxJQUFJLENBQUMsd0RBQXdELEVBQUUsRUFBRSxHQUFHLEVBQUUsT0FBTyxFQUFFLEtBQUssRUFBRSxZQUFZLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxDQUFDO1lBQ2xILElBQUksRUFBRSxDQUFDO1FBQ1QsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDLENBQUM7QUFDSixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQ29weXJpZ2h0IDIwMjYgUGlwZWxpbmUgQnVpbGRlciBDb250cmlidXRvcnNcbi8vIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBcGFjaGUtMi4wXG5cbmltcG9ydCB7IGNyZWF0ZUhhc2ggfSBmcm9tICdjcnlwdG8nO1xuaW1wb3J0IHsgY3JlYXRlTG9nZ2VyLCBzZW5kRXJyb3IsIEVycm9yQ29kZSwgY3JlYXRlRW52UmVkaXNDbGllbnQsIGVycm9yTWVzc2FnZSwgc3RhYmxlU3RyaW5naWZ5IH0gZnJvbSAnQHBpcGVsaW5lLWJ1aWxkZXIvYXBpLWNvcmUnO1xuaW1wb3J0IHsgQ29yZUNvbnN0YW50cyB9IGZyb20gJ0BwaXBlbGluZS1idWlsZGVyL3BpcGVsaW5lLWNvcmUnO1xuaW1wb3J0IHR5cGUgeyBSZXF1ZXN0LCBSZXNwb25zZSwgTmV4dEZ1bmN0aW9uIH0gZnJvbSAnZXhwcmVzcyc7XG5cbmNvbnN0IGxvZ2dlciA9IGNyZWF0ZUxvZ2dlcignaWRlbXBvdGVuY3knKTtcblxuLyoqXG4gKiBTaG9ydCwgc3RhYmxlIGZpbmdlcnByaW50IG9mIGEgcmVxdWVzdCBib2R5LiBGb2xkcyB0aGUgcGF5bG9hZCBpbnRvIHRoZVxuICogaWRlbXBvdGVuY3kga2V5IHNvIHJlcGxheWluZyB0aGUgU0FNRSBrZXkgd2l0aCBhIERJRkZFUkVOVCBib2R5IGlzIHRyZWF0ZWQgYXNcbiAqIGEgZGlzdGluY3Qgb3BlcmF0aW9uIChmcmVzaCBleGVjdXRpb24pIHJhdGhlciB0aGFuIHJlcGxheWluZyB0aGUgb2xkIHJlc3BvbnNlLlxuICogRW1wdHkvYWJzZW50IGJvZGllcyBjb2xsYXBzZSB0byAnLScgc28gYm9keS1sZXNzIG11dGF0aW9ucyBzdGF5IHVuYWZmZWN0ZWQuXG4gKi9cbmZ1bmN0aW9uIGJvZHlGaW5nZXJwcmludChib2R5OiB1bmtub3duKTogc3RyaW5nIHtcbiAgaWYgKGJvZHkgPT09IHVuZGVmaW5lZCB8fCBib2R5ID09PSBudWxsKSByZXR1cm4gJy0nO1xuICBpZiAodHlwZW9mIGJvZHkgPT09ICdvYmplY3QnICYmIE9iamVjdC5rZXlzKGJvZHkgYXMgb2JqZWN0KS5sZW5ndGggPT09IDApIHJldHVybiAnLSc7XG4gIHRyeSB7XG4gICAgcmV0dXJuIGNyZWF0ZUhhc2goJ3NoYTI1NicpLnVwZGF0ZShzdGFibGVTdHJpbmdpZnkoYm9keSkpLmRpZ2VzdCgnaGV4Jykuc2xpY2UoMCwgMTYpO1xuICB9IGNhdGNoIHtcbiAgICAvLyBOb24tc2VyaWFsaXphYmxlIGJvZHkgKGUuZy4gYSBzdHJlYW0vY2lyY3VsYXIgcmVmKTogc2tpcCBmaW5nZXJwcmludGluZ1xuICAgIC8vIHJhdGhlciB0aGFuIGZhaWwgdGhlIHJlcXVlc3Qg4oCUIGtleSBzdGF5cyBzY29wZWQgYnkgbWV0aG9kK3JvdXRlK29yZy5cbiAgICByZXR1cm4gJy0nO1xuICB9XG59XG5cbmludGVyZmFjZSBDYWNoZWRFbnRyeSB7XG4gIHN0YXR1c0NvZGU6IG51bWJlcjtcbiAgYm9keTogdW5rbm93bjtcbiAgZXhwaXJlc0F0OiBudW1iZXI7XG4gIC8qKiBSZXNlcnZhdGlvbiBwbGFjZWhvbGRlcjogdGhlIHJlcXVlc3QgaXMgaW4tZmxpZ2h0LCBubyByZWFsIHJlc3BvbnNlIHlldC5cbiAgICogIEEgZHVwbGljYXRlIHRoYXQgc2VlcyBhIHBlbmRpbmcgZW50cnkgaXMgcmVqZWN0ZWQgd2l0aCA0MDksIG5vdCByZXBsYXllZC4gKi9cbiAgcGVuZGluZz86IGJvb2xlYW47XG59XG5cbi8qKlxuICogUGx1Z2dhYmxlIGJhY2tlbmQgZm9yIGlkZW1wb3RlbmN5LWtleSByZXBsYXkgY2FjaGUuIFRoZSBkZWZhdWx0IGluLW1lbW9yeVxuICogaW1wbGVtZW50YXRpb24gd29ya3MgZmluZSBzaW5nbGUtcmVwbGljYTsgYSBSZWRpcy1iYWNrZWQgaW1wbGVtZW50YXRpb25cbiAqIGlzIHJlcXVpcmVkIGZvciBjb3JyZWN0IGRlZHVwbGljYXRpb24gYWNyb3NzIGhvcml6b250YWxseS1zY2FsZWQgcmVwbGljYXNcbiAqIChvdGhlcndpc2UgdHdvIHJlcGxpY2FzIGJlaGluZCBhIGxvYWQtYmFsYW5jZXIgY2FjaGUgaW5kZXBlbmRlbnRseSBhbmQgYVxuICogcmV0cnkgaGl0dGluZyBhIGRpZmZlcmVudCBwb2Qgd29uJ3QgcmVwbGF5KS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBJZGVtcG90ZW5jeVN0b3JlIHtcbiAgZ2V0KGtleTogc3RyaW5nKTogUHJvbWlzZTxDYWNoZWRFbnRyeSB8IG51bGw+O1xuICBzZXQoa2V5OiBzdHJpbmcsIGVudHJ5OiBDYWNoZWRFbnRyeSwgdHRsU2Vjb25kczogbnVtYmVyKTogUHJvbWlzZTx2b2lkPjtcbiAgLyoqXG4gICAqIEF0b21pY2FsbHkgY2xhaW0gYGtleWAgSUZGIGl0IGlzIGN1cnJlbnRseSBhYnNlbnQuIFJldHVybnMgYHRydWVgIHdoZW4gVEhJU1xuICAgKiBjYWxsZXIgc2V0IHRoZSBlbnRyeSAod29uIHRoZSByYWNlKSwgYGZhbHNlYCB3aGVuIGFuIGVudHJ5IGFscmVhZHkgZXhpc3RzLlxuICAgKiBUaGlzIGlzIHdoYXQgc2VyaWFsaXplcyBjb25jdXJyZW50IGZpcnN0LXRpbWUgcmVxdWVzdHMgdGhhdCBzaGFyZSBhblxuICAgKiBJZGVtcG90ZW5jeS1LZXkg4oCUIGEgcGxhaW4gZ2V0LXRoZW4tc2V0IGxlYXZlcyBhIHdpbmRvdyB3aGVyZSB0d28gcmVxdWVzdHNcbiAgICogYm90aCBzZWUgXCJub3QgY2FjaGVkXCIgYW5kIGJvdGggZXhlY3V0ZSB0aGUgbXV0YXRpb24uXG4gICAqL1xuICByZXNlcnZlKGtleTogc3RyaW5nLCBlbnRyeTogQ2FjaGVkRW50cnksIHR0bFNlY29uZHM6IG51bWJlcik6IFByb21pc2U8Ym9vbGVhbj47XG4gIC8qKiBSZW1vdmUgYSBrZXkg4oCUIHJlbGVhc2VzIGEgcmVzZXJ2YXRpb24gYWZ0ZXIgYSBub24tY2FjaGVhYmxlIChub24tMnh4KSByZXNwb25zZS4gKi9cbiAgZGVsZXRlKGtleTogc3RyaW5nKTogUHJvbWlzZTx2b2lkPjtcbn1cblxuLyoqIERlZmF1bHQgaW4tbWVtb3J5IHN0b3JlLiBTaW5nbGUtcmVwbGljYSBvbmx5LiBFeHBvcnRlZCBmb3IgdGVzdGluZy4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVNZW1vcnlTdG9yZSgpOiBJZGVtcG90ZW5jeVN0b3JlIHtcbiAgY29uc3QgbWFwID0gbmV3IE1hcDxzdHJpbmcsIENhY2hlZEVudHJ5PigpO1xuICBjb25zdCBjbGVhbnVwVGltZXIgPSBzZXRJbnRlcnZhbCgoKSA9PiB7XG4gICAgY29uc3Qgbm93ID0gRGF0ZS5ub3coKTtcbiAgICBmb3IgKGNvbnN0IFtrLCB2XSBvZiBtYXApIHtcbiAgICAgIGlmIChub3cgPiB2LmV4cGlyZXNBdCkgbWFwLmRlbGV0ZShrKTtcbiAgICB9XG4gIH0sIENvcmVDb25zdGFudHMuSURFTVBPVEVOQ1lfQ0xFQU5VUF9JTlRFUlZBTF9NUyk7XG4gIGNsZWFudXBUaW1lci51bnJlZigpO1xuXG4gIC8qKiBSZXR1cm4gdGhlIGxpdmUgKG5vbi1leHBpcmVkKSBlbnRyeSwgZXZpY3RpbmcgaXQgbGF6aWx5IGlmIGV4cGlyZWQuICovXG4gIGNvbnN0IGxpdmUgPSAoa2V5OiBzdHJpbmcpOiBDYWNoZWRFbnRyeSB8IG51bGwgPT4ge1xuICAgIGNvbnN0IGVudHJ5ID0gbWFwLmdldChrZXkpO1xuICAgIGlmICghZW50cnkpIHJldHVybiBudWxsO1xuICAgIGlmIChEYXRlLm5vdygpID4gZW50cnkuZXhwaXJlc0F0KSB7XG4gICAgICBtYXAuZGVsZXRlKGtleSk7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gICAgcmV0dXJuIGVudHJ5O1xuICB9O1xuICAvKipcbiAgICogQXQgY2FwYWNpdHksIGV2aWN0IHRoZSBPTERFU1QgZW50cnkgKE1hcCBwcmVzZXJ2ZXMgaW5zZXJ0aW9uIG9yZGVyKSByYXRoZXJcbiAgICogdGhhbiBzaWxlbnRseSBkcm9wcGluZyB0aGUgTkVXIGtleSDigJQgb3RoZXJ3aXNlLCBvbmNlIGZ1bGwsIHRoZSBzdG9yZSBzdG9wc1xuICAgKiBkZWR1cGxpY2F0aW5nIGZyZXNoIHJlcXVlc3RzIHVudGlsIHRoZSBUVEwgc3dlZXAgcnVucy4gU3RheXMgYm91bmRlZDsgZmF2b3JzXG4gICAqIHJlY2VudCBrZXlzIChtb3N0IGxpa2VseSB0byBiZSByZXRyaWVkKS5cbiAgICovXG4gIGNvbnN0IGV2aWN0SWZGdWxsID0gKGtleTogc3RyaW5nKTogdm9pZCA9PiB7XG4gICAgaWYgKCFtYXAuaGFzKGtleSkgJiYgbWFwLnNpemUgPj0gQ29yZUNvbnN0YW50cy5JREVNUE9URU5DWV9NQVhfU1RPUkVfU0laRSkge1xuICAgICAgY29uc3Qgb2xkZXN0ID0gbWFwLmtleXMoKS5uZXh0KCkudmFsdWU7XG4gICAgICBpZiAob2xkZXN0ICE9PSB1bmRlZmluZWQpIG1hcC5kZWxldGUob2xkZXN0KTtcbiAgICB9XG4gIH07XG4gIHJldHVybiB7XG4gICAgYXN5bmMgZ2V0KGtleSkge1xuICAgICAgcmV0dXJuIGxpdmUoa2V5KTtcbiAgICB9LFxuICAgIGFzeW5jIHNldChrZXksIGVudHJ5KSB7XG4gICAgICBldmljdElmRnVsbChrZXkpO1xuICAgICAgbWFwLnNldChrZXksIGVudHJ5KTtcbiAgICB9LFxuICAgIGFzeW5jIHJlc2VydmUoa2V5LCBlbnRyeSkge1xuICAgICAgLy8gQXRvbWljIGluIGEgc2luZ2xlLXRocmVhZGVkIHJ1bnRpbWU6IG5vIGF3YWl0IGJldHdlZW4gdGhlIGxpdmVuZXNzIGNoZWNrXG4gICAgICAvLyBhbmQgdGhlIHNldCwgc28gdHdvIGNvbmN1cnJlbnQgY2FsbGVycyBjYW4ndCBib3RoIG9ic2VydmUgXCJhYnNlbnRcIi5cbiAgICAgIGlmIChsaXZlKGtleSkpIHJldHVybiBmYWxzZTtcbiAgICAgIGV2aWN0SWZGdWxsKGtleSk7XG4gICAgICBtYXAuc2V0KGtleSwgZW50cnkpO1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfSxcbiAgICBhc3luYyBkZWxldGUoa2V5KSB7XG4gICAgICBtYXAuZGVsZXRlKGtleSk7XG4gICAgfSxcbiAgfTtcbn1cblxuLyoqXG4gKiBNaW5pbWFsIFJlZGlzIHN1cmZhY2UgdGhlIGlkZW1wb3RlbmN5IHN0b3JlIG5lZWRzIChhbiBpb3JlZGlzIHN1YnNldCkuXG4gKiBgc2V0YCBzdXBwb3J0cyB0aGUgdmFyaWFkaWMgb3B0aW9uIHRhaWw6IGBTRVQga2V5IHZhbCBFWCA8dHRsPiBbTlhdYCwgd2hpY2hcbiAqIHJldHVybnMgYCdPSydgIG9uIHN1Y2Nlc3MgYW5kIGBudWxsYCB3aGVuIGFuIGBOWGAgc2V0IHdhcyByZWZ1c2VkLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFJlZGlzSWRlbXBvdGVuY3lDbGllbnQge1xuICBnZXQoa2V5OiBzdHJpbmcpOiBQcm9taXNlPHN0cmluZyB8IG51bGw+O1xuICBzZXQoa2V5OiBzdHJpbmcsIHZhbHVlOiBzdHJpbmcsIC4uLmFyZ3M6IChzdHJpbmcgfCBudW1iZXIpW10pOiBQcm9taXNlPHN0cmluZyB8IG51bGw+O1xuICBkZWwoa2V5OiBzdHJpbmcpOiBQcm9taXNlPG51bWJlcj47XG59XG5cbmNvbnN0IFJFRElTX0tFWV9QUkVGSVggPSAnaWRlbTonO1xuXG4vKipcbiAqIFJlZGlzLWJhY2tlZCB7QGxpbmsgSWRlbXBvdGVuY3lTdG9yZX0gZm9yIGNvcnJlY3QgZGVkdXBsaWNhdGlvbiBhY3Jvc3NcbiAqIGhvcml6b250YWxseS1zY2FsZWQgcmVwbGljYXMuIGByZXNlcnZlYCBtYXBzIHRvIGFuIGF0b21pYyBgU0VUIOKApiBOWGAgc28gdHdvXG4gKiBwb2RzIGJlaGluZCBhIGxvYWQtYmFsYW5jZXIgY2FuJ3QgYm90aCB3aW4gYSBmaXJzdC10aW1lIHJlcXVlc3Qgc2hhcmluZyBhblxuICogSWRlbXBvdGVuY3ktS2V5OyBhIHJldHJ5IGxhbmRpbmcgb24gQU5ZIHBvZCBzZWVzIHRoZSBzYW1lIGNvbW1pdHRlZCByZXNwb25zZS5cbiAqIFJlZGlzIFRUTCBvd25zIGV4cGlyeSAodGhlIGBDYWNoZWRFbnRyeS5leHBpcmVzQXRgIGZpZWxkIGlzIGNhcnJpZWQgb25seSBmb3JcbiAqIEFQSS1zaGFwZSBwYXJpdHkgd2l0aCB0aGUgbWVtb3J5IHN0b3JlKS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZVJlZGlzSWRlbXBvdGVuY3lTdG9yZShyZWRpczogUmVkaXNJZGVtcG90ZW5jeUNsaWVudCk6IElkZW1wb3RlbmN5U3RvcmUge1xuICBjb25zdCBrID0gKGtleTogc3RyaW5nKTogc3RyaW5nID0+IGAke1JFRElTX0tFWV9QUkVGSVh9JHtrZXl9YDtcbiAgcmV0dXJuIHtcbiAgICBhc3luYyBnZXQoa2V5KSB7XG4gICAgICBjb25zdCByYXcgPSBhd2FpdCByZWRpcy5nZXQoayhrZXkpKTtcbiAgICAgIGlmICghcmF3KSByZXR1cm4gbnVsbDtcbiAgICAgIHRyeSB7XG4gICAgICAgIHJldHVybiBKU09OLnBhcnNlKHJhdykgYXMgQ2FjaGVkRW50cnk7XG4gICAgICB9IGNhdGNoIHtcbiAgICAgICAgLy8gQ29ycnVwdCBlbnRyeSDihpIgdHJlYXQgYXMgYWJzZW50IHNvIHRoZSByZXF1ZXN0IHByb2NlZWRzIGZyZXNoLlxuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgIH1cbiAgICB9LFxuICAgIGFzeW5jIHNldChrZXksIGVudHJ5LCB0dGxTZWNvbmRzKSB7XG4gICAgICBhd2FpdCByZWRpcy5zZXQoayhrZXkpLCBKU09OLnN0cmluZ2lmeShlbnRyeSksICdFWCcsIE1hdGgubWF4KDEsIHR0bFNlY29uZHMpKTtcbiAgICB9LFxuICAgIGFzeW5jIHJlc2VydmUoa2V5LCBlbnRyeSwgdHRsU2Vjb25kcykge1xuICAgICAgLy8gQXRvbWljIGNsYWltOiBTRVQga2V5IHZhbCBFWCB0dGwgTlgg4oaSICdPSycgb25seSBpZiB0aGUga2V5IHdhcyBhYnNlbnQuXG4gICAgICBjb25zdCByZXMgPSBhd2FpdCByZWRpcy5zZXQoayhrZXkpLCBKU09OLnN0cmluZ2lmeShlbnRyeSksICdFWCcsIE1hdGgubWF4KDEsIHR0bFNlY29uZHMpLCAnTlgnKTtcbiAgICAgIHJldHVybiByZXMgPT09ICdPSyc7XG4gICAgfSxcbiAgICBhc3luYyBkZWxldGUoa2V5KSB7XG4gICAgICBhd2FpdCByZWRpcy5kZWwoayhrZXkpKTtcbiAgICB9LFxuICB9O1xufVxuXG4vKipcbiAqIEJ1aWxkIGEgUmVkaXMtYmFja2VkIGlkZW1wb3RlbmN5IHN0b3JlIGZyb20gdGhlIHNoYXJlZCBlbnYgUmVkaXMgKHRoZSBzYW1lXG4gKiBgUkVESVNfVVJMYCAvIGBSRURJU19TRU5USU5FTFNgIHdpcmluZyB0aGUgcmF0ZS1saW1pdGVyIGFuZCBhdWRpdC1zcG9vbCB1c2UpLlxuICogUmV0dXJucyBgbnVsbGAgd2hlbiBSZWRpcyBpc24ndCBjb25maWd1cmVkL2F2YWlsYWJsZSBzbyB0aGUgY2FsbGVyIGtlZXBzIHRoZVxuICogaW4tbWVtb3J5IGRlZmF1bHQgKHNpbmdsZS1yZXBsaWNhIGNvcnJlY3RuZXNzKS4gTmV2ZXIgdGhyb3dzLlxuICovXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlRW52UmVkaXNJZGVtcG90ZW5jeVN0b3JlKCk6IElkZW1wb3RlbmN5U3RvcmUgfCBudWxsIHtcbiAgY29uc3QgY2xpZW50ID0gY3JlYXRlRW52UmVkaXNDbGllbnQ8UmVkaXNJZGVtcG90ZW5jeUNsaWVudD4oJ2lkZW1wb3RlbmN5Jyk7XG4gIGlmICghY2xpZW50KSByZXR1cm4gbnVsbDtcbiAgbG9nZ2VyLmluZm8oJ1JlZGlzIGlkZW1wb3RlbmN5IHN0b3JlIGluaXRpYWxpemVkJyk7XG4gIHJldHVybiBjcmVhdGVSZWRpc0lkZW1wb3RlbmN5U3RvcmUoY2xpZW50KTtcbn1cblxuY29uc3QgbWVtb3J5U3RvcmUgPSBjcmVhdGVNZW1vcnlTdG9yZSgpO1xuXG4vKipcbiAqIFByb2Nlc3Mtd2lkZSBkZWZhdWx0IHN0b3JlIHVzZWQgYnkgYGlkZW1wb3RlbmN5TWlkZGxld2FyZSgpYCB3aGVuIG5vIGV4cGxpY2l0XG4gKiBgc3RvcmVgIGlzIHBhc3NlZC4gRGVmYXVsdHMgdG8gdGhlIGluLW1lbW9yeSBzdG9yZTsgYGNyZWF0ZUFwcGAgcHJvbW90ZXMgaXQgdG9cbiAqIHRoZSBzaGFyZWQgZW52LVJlZGlzIHN0b3JlIChtdWx0aS1yZXBsaWNhIGRlZHVwKSBhdCBzdGFydHVwIHZpYVxuICoge0BsaW5rIHNldElkZW1wb3RlbmN5U3RvcmV9LiBUaGUgcm91dGUgZmFjdG9yaWVzIGtlZXAgY2FsbGluZ1xuICogYGlkZW1wb3RlbmN5TWlkZGxld2FyZSgpYCB3aXRoIG5vIGFyZ3MgYW5kIHRyYW5zcGFyZW50bHkgcGljayB0aGlzIHVwLlxuICovXG5sZXQgZGVmYXVsdFN0b3JlOiBJZGVtcG90ZW5jeVN0b3JlID0gbWVtb3J5U3RvcmU7XG5cbi8qKiBJbmplY3QgdGhlIHByb2Nlc3Mtd2lkZSBpZGVtcG90ZW5jeSBzdG9yZSAoZS5nLiBhIFJlZGlzLWJhY2tlZCBvbmUpLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNldElkZW1wb3RlbmN5U3RvcmUoc3RvcmU6IElkZW1wb3RlbmN5U3RvcmUpOiB2b2lkIHtcbiAgZGVmYXVsdFN0b3JlID0gc3RvcmU7XG59XG5cbi8qKiBUaGUgY3VycmVudCBwcm9jZXNzLXdpZGUgZGVmYXVsdCBzdG9yZSAoaW4tbWVtb3J5IHVubGVzcyBvdmVycmlkZGVuKS4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRJZGVtcG90ZW5jeVN0b3JlKCk6IElkZW1wb3RlbmN5U3RvcmUge1xuICByZXR1cm4gZGVmYXVsdFN0b3JlO1xufVxuXG4vKipcbiAqIE1hcmtzIGEgcmVxdWVzdCBpZGVtcG90ZW5jeSBoYXMgYWxyZWFkeSBoYW5kbGVkLiBSb3V0ZSBjaGFpbnMgYXJlIHN0YWNrZWQg4oCUXG4gKiBzZXZlcmFsIGBhcHAudXNlKHByZWZpeCwgLi4uY3JlYXRlQXV0aGVudGljYXRlZFdpdGhPcmdSb3V0ZSgpLCByb3V0ZXIpYCBtb3VudHNcbiAqIHNoYXJlIGEgcHJlZml4LCBhbmQgYSByZXF1ZXN0IHRoYXQgZmFsbHMgdGhyb3VnaCB0aGUgZmlyc3Qgcm91dGVyIHJ1bnMgdGhlXG4gKiBuZXh0IGNoYWluJ3MgaWRlbXBvdGVuY3kgbWlkZGxld2FyZSBhZ2Fpbi4gVGhhdCBzZWNvbmQgcGFzcyBmb3VuZCBpdHMgT1dOXG4gKiBwZW5kaW5nIHJlc2VydmF0aW9uIGFuZCBhbnN3ZXJlZCA0MDkuXG4gKi9cbmNvbnN0IElERU1QT1RFTkNZX0hBTkRMRUQgPSBTeW1ib2woJ3BpcGVsaW5lLWJ1aWxkZXIuaWRlbXBvdGVuY3kuaGFuZGxlZCcpO1xuXG4vKipcbiAqIGByZXMubG9jYWxzYCBrZXkgc2V0IHRvIGB0cnVlYCB3aGVuIHRoZSByZXNwb25zZSB3YXMgUkVQTEFZRUQgZnJvbSB0aGVcbiAqIGlkZW1wb3RlbmN5IGNhY2hlIGluc3RlYWQgb2YgcnVubmluZyB0aGUgaGFuZGxlci4gQSByZXBsYXkgZGlkIG5vIHdvcmssIHNvXG4gKiBhbnl0aGluZyB0aGF0IGJpbGxzIHBlciBzdWNjZXNzZnVsIHJlc3BvbnNlIChgbWV0ZXJRdW90YU9uU3VjY2Vzc2ApIG11c3Qgc2tpcFxuICogaXQg4oCUIHRoZSBvcmlnaW5hbCByZXF1ZXN0IGFscmVhZHkgcGFpZC4gVXNlIHtAbGluayBpc0lkZW1wb3RlbnRSZXBsYXl9LlxuICovXG5leHBvcnQgY29uc3QgSURFTVBPVEVOVF9SRVBMQVlfTE9DQUwgPSAnaWRlbXBvdGVudFJlcGxheSc7XG5cbi8qKiBUcnVlIHdoZW4gYHJlc2AgaXMgYSByZXBsYXkgb2YgYSBjYWNoZWQgaWRlbXBvdGVudCByZXNwb25zZS4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc0lkZW1wb3RlbnRSZXBsYXkocmVzOiBSZXNwb25zZSk6IGJvb2xlYW4ge1xuICByZXR1cm4gcmVzLmxvY2Fscz8uW0lERU1QT1RFTlRfUkVQTEFZX0xPQ0FMXSA9PT0gdHJ1ZTtcbn1cblxuLyoqXG4gKiBUaGUgc3RvcmUga2V5IGEgcmVxdWVzdCdzIGBJZGVtcG90ZW5jeS1LZXlgIGlzIHJlY29yZGVkIHVuZGVyLCBvciBgdW5kZWZpbmVkYFxuICogd2hlbiB0aGUgcmVxdWVzdCBoYXMgbm8gb3JnIHRvIG5hbWVzcGFjZSBpdCBieSAodW5hdXRoZW50aWNhdGVkIOKAlCBza2lwcGVkKS5cbiAqXG4gKiBOYW1lc3BhY2UgYnkgb3JnSWQgdG8gcHJldmVudCBjcm9zcy1vcmcgY2FjaGUgY29sbGlzaW9ucy4gUHJlZmVyIHRoZSBWRVJJRklFRFxuICogYXV0aCBvcmcgKGByZXEudXNlcmAsIHBvcHVsYXRlZCBieSByZXF1aXJlQXV0aCBhZnRlciBzaWduYXR1cmUgdmVyaWZpY2F0aW9uKVxuICogb3ZlciBgcmVxLmNvbnRleHQuaWRlbnRpdHlgLCB3aGljaCBzb21lIHNlcnZpY2VzIHBvcHVsYXRlIHByZS1hdXRoIGZyb20gYW5cbiAqIFVOVkVSSUZJRUQgdG9rZW4gcGVlayDigJQgbmFtZXNwYWNpbmcgYSBtdXRhdGlvbidzIHJlcGxheSBjYWNoZSBvbiBhblxuICogdW52ZXJpZmllZCwgY2FsbGVyLWluZmx1ZW5jZWQgb3JnIGlkIHdvdWxkIGJlIHVuc2FmZS5cbiAqXG4gKiBOYW1lc3BhY2UgdGhlIHN0b3JlZCBrZXkgYnkgKG1ldGhvZCwgcm91dGUsIG9yZywgYm9keSkgc28gYW4gSWRlbXBvdGVuY3ktS2V5XG4gKiBpcyBzY29wZWQgdG8gT05FIHNwZWNpZmljIGVuZHBvaW50K3BheWxvYWQuIFJldXNpbmcgYSBzaW5nbGUga2V5IGFjcm9zcyB0d29cbiAqIHJvdXRlcyAoZS5nLiBQT1NUIC9waXBlbGluZXMgdGhlbiBQT1NUIC9wbHVnaW5zKSBtdXN0IG5vdCByZXBsYXkgdGhlIGZpcnN0XG4gKiBlbmRwb2ludCdzIDJ4eCBmb3IgdGhlIHNlY29uZCDigJQgdGhlIHN0b3JlIGlzIGEgbW9kdWxlLWxldmVsIHNpbmdsZXRvbiBzaGFyZWRcbiAqIGJ5IGV2ZXJ5IHJvdXRlLiBGb2xkaW5nIGluIG1ldGhvZCArIHJvdXRlIHBhdGggKyBhIGJvZHkgZmluZ2VycHJpbnQgb25seSBtYWtlc1xuICoga2V5cyBNT1JFIHNwZWNpZmljLCBzbyB0aGVyZSBpcyBubyBjcm9zcy1jb250YW1pbmF0aW9uIHJpc2suIEFsc28gbmFtZXNwYWNlIGJ5XG4gKiB0aGUgVkVSSUZJRUQgdXNlci4gYElkZW1wb3RlbmN5LUtleWAgaXMgY2hvc2VuIGJ5IHRoZSBjbGllbnQsIHNvIHR3byB1c2VycyBpblxuICogdGhlIHNhbWUgb3JnIHNlbmRpbmcgdGhlIHNhbWUgYm9keSB3aXRoIHRoZSBzYW1lIGtleSBjb2xsaWRlZDogdGhlIHNlY29uZFxuICogdXNlcidzIG11dGF0aW9uIHdhcyBTS0lQUEVEIGFuZCB0aGV5IHdlcmUgc2VydmVkIHRoZSBmaXJzdCB1c2VyJ3MgY2FjaGVkXG4gKiByZXNwb25zZS4gRmFsbHMgYmFjayB0byB0aGUgb3JnIGFsb25lIG9ubHkgd2hlbiB0aGVyZSBpcyBubyB2ZXJpZmllZCBzdWJqZWN0XG4gKiAoc2VydmljZSBwcmluY2lwYWxzIGNhcnJ5IG9uZSkuXG4gKi9cbmZ1bmN0aW9uIGlkZW1wb3RlbmN5U3RvcmVLZXkocmVxOiBSZXF1ZXN0LCBrZXk6IHN0cmluZyk6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gIGNvbnN0IG9yZ0lkID0gcmVxLnVzZXI/Lm9yZ2FuaXphdGlvbklkIHx8IHJlcS5jb250ZXh0Py5pZGVudGl0eT8ub3JnSWQ7XG4gIGlmICghb3JnSWQpIHJldHVybiB1bmRlZmluZWQ7XG4gIGNvbnN0IHN1YiA9IHJlcS51c2VyPy5zdWI7XG4gIGNvbnN0IHJvdXRlUGF0aCA9IChyZXEuYmFzZVVybCA/PyAnJykgKyAocmVxLnJvdXRlPy5wYXRoID8/IHJlcS5wYXRoID8/ICcnKTtcbiAgcmV0dXJuIGAke3JlcS5tZXRob2R9OiR7cm91dGVQYXRofToke29yZ0lkfToke3N1YiA/PyAnLSd9OiR7Ym9keUZpbmdlcnByaW50KHJlcS5ib2R5KX06JHtrZXl9YDtcbn1cblxuLyoqIE1ldGhvZHMgdGhlIGlkZW1wb3RlbmN5IG1pZGRsZXdhcmUgYXBwbGllcyB0by4gKi9cbmNvbnN0IElERU1QT1RFTlRfTUVUSE9EUyA9IFsnUE9TVCcsICdQVVQnLCAnREVMRVRFJ107XG5cbi8qKlxuICogVHJ1ZSB3aGVuIHRoaXMgcmVxdWVzdCBpcyBhIFJFVFJZIG9mIGFuIGlkZW1wb3RlbnQgbXV0YXRpb24gd2hvc2Ugb3JpZ2luYWxcbiAqIGhhcyBDT01QTEVURUQgKGEgY2FjaGVkIDJ4eCBvbiByZWNvcmQpIOKAlCBpLmUuIHRoZSBpZGVtcG90ZW5jeSBtaWRkbGV3YXJlIHdpbGxcbiAqIHJlcGxheSBpdCB3aXRob3V0IHJ1bm5pbmcgdGhlIGhhbmRsZXIuIFRoZSBhcGlDYWxscyBjaGVjayB1c2VzIGl0IHRvIHNraXBcbiAqIHRoZSBnYXRlIGZvciBzdWNoIGEgcmV0cnk6IHRoZSByZXBsYXkgZG9lcyBubyB3b3JrIGFuZCBpcyBuZXZlciBtZXRlcmVkLCBzb1xuICogcmVmdXNpbmcgaXQgYXQgdGhlIHF1b3RhIGdhdGUgKHdoaWNoIHJ1bnMgaW4gcmVxdWlyZUF1dGgsIEJFRk9SRSByZXBsYXlcbiAqIGRldGVjdGlvbiBpbiBtb3N0IGNoYWlucykgd291bGQgNDI5IGEgY2xpZW50IGZvciByZS1yZWFkaW5nIGl0cyBvd24gcmVzdWx0LlxuICpcbiAqIE9uZSBzdG9yZSByZWFkLCBhbmQgb25seSBmb3IgYSBtdXRhdGlvbiBjYXJyeWluZyBgSWRlbXBvdGVuY3ktS2V5YDsgZXZlcnlcbiAqIGZhaWx1cmUgYW5zd2VycyBgZmFsc2VgICh0aGUgZ2F0ZSB0aGVuIHJ1bnMgYXMgdXN1YWwpLiBVc2VzIHRoZSBwcm9jZXNzLXdpZGVcbiAqIHN0b3JlIOKAlCB0aGUgc2FtZSBvbmUgdGhlIHJvdXRlIGNoYWlucycgbWlkZGxld2FyZSByZXNvbHZlcy5cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGhhc0NvbXBsZXRlZElkZW1wb3RlbnRSZXNwb25zZShyZXE6IFJlcXVlc3QpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgY29uc3Qga2V5ID0gcmVxLmhlYWRlcnM/LlsnaWRlbXBvdGVuY3kta2V5J107XG4gIGlmICh0eXBlb2Yga2V5ICE9PSAnc3RyaW5nJyB8fCAha2V5IHx8ICFJREVNUE9URU5UX01FVEhPRFMuaW5jbHVkZXMocmVxLm1ldGhvZCkpIHJldHVybiBmYWxzZTtcbiAgY29uc3QgZnVsbEtleSA9IGlkZW1wb3RlbmN5U3RvcmVLZXkocmVxLCBrZXkpO1xuICBpZiAoIWZ1bGxLZXkpIHJldHVybiBmYWxzZTtcbiAgdHJ5IHtcbiAgICBjb25zdCBjYWNoZWQgPSBhd2FpdCBkZWZhdWx0U3RvcmUuZ2V0KGZ1bGxLZXkpO1xuICAgIHJldHVybiAhIWNhY2hlZCAmJiAhY2FjaGVkLnBlbmRpbmc7XG4gIH0gY2F0Y2gge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxufVxuXG5leHBvcnQgaW50ZXJmYWNlIElkZW1wb3RlbmN5TWlkZGxld2FyZU9wdGlvbnMge1xuICAvKiogQ3VzdG9tIHN0b3JlIGJhY2tlbmQuIERlZmF1bHRzIHRvIHRoZSBwcm9jZXNzLXdpZGUgc3RvcmUgc2V0IHZpYVxuICAgKiAge0BsaW5rIHNldElkZW1wb3RlbmN5U3RvcmV9IChpbi1tZW1vcnkgdW50aWwgYGNyZWF0ZUFwcGAgd2lyZXMgUmVkaXMpLiAqL1xuICBzdG9yZT86IElkZW1wb3RlbmN5U3RvcmU7XG59XG5cbi8qKlxuICogTWlkZGxld2FyZSB0aGF0IHN1cHBvcnRzIGlkZW1wb3RlbmN5IGtleXMgZm9yIFBPU1QvUFVUL0RFTEVURSBtdXRhdGlvbnMuXG4gKlxuICogV2hlbiBhIHJlcXVlc3QgaW5jbHVkZXMgdGhlIGBJZGVtcG90ZW5jeS1LZXlgIGhlYWRlcjpcbiAqIC0gRmlyc3QgY2FsbDogcHJvY2Vzc2VzIG5vcm1hbGx5LCBjYWNoZXMgdGhlIHJlc3BvbnNlXG4gKiAtIFN1YnNlcXVlbnQgY2FsbHMgd2l0aCBzYW1lIGtleTogcmV0dXJucyBjYWNoZWQgcmVzcG9uc2UgKHByZXZlbnRzIGR1cGxpY2F0ZSBtdXRhdGlvbnMpXG4gKlxuICogRGVmYXVsdHMgdG8gYW4gaW4tbWVtb3J5IHN0b3JlIChzaW5nbGUtcmVwbGljYSkuIFBhc3MgYSBjdXN0b21cbiAqIGNyb3NzLXJlcGxpY2EgYHsgc3RvcmUgfWAgaW1wbGVtZW50aW5nIGBJZGVtcG90ZW5jeVN0b3JlYCB0byBkZWR1cGUgYWNyb3NzXG4gKiByZXBsaWNhcy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlkZW1wb3RlbmN5TWlkZGxld2FyZShvcHRpb25zOiBJZGVtcG90ZW5jeU1pZGRsZXdhcmVPcHRpb25zID0ge30pIHtcbiAgLy8gUmVzb2x2ZSB0aGUgc3RvcmUgUEVSIFJFUVVFU1QgKG5vdCBhdCBmYWN0b3J5IHRpbWUpIHNvIGEgc3RvcmUgaW5qZWN0ZWQgYnlcbiAgLy8gY3JlYXRlQXBwIEFGVEVSIHRoZSByb3V0ZSBjaGFpbnMgYXJlIGJ1aWx0IHN0aWxsIHRha2VzIGVmZmVjdC4gQW4gZXhwbGljaXRcbiAgLy8gYG9wdGlvbnMuc3RvcmVgIGFsd2F5cyB3aW5zLlxuICBjb25zdCBleHBsaWNpdFN0b3JlID0gb3B0aW9ucy5zdG9yZTtcbiAgY29uc3QgdHRsTXMgPSBDb3JlQ29uc3RhbnRzLklERU1QT1RFTkNZX1RUTF9NUztcbiAgY29uc3QgdHRsU2VjID0gTWF0aC5mbG9vcih0dGxNcyAvIDEwMDApO1xuICAvLyBBIHJlc2VydmF0aW9uIGxpdmVzIG9ubHkgYXMgbG9uZyBhcyBhIGhhbmRsZXIgcGxhdXNpYmx5IHJ1bnM6IGlmIHRoZVxuICAvLyBwcm9jZXNzIGRpZXMgbWlkLWhhbmRsZXIgbm90aGluZyBldmVyIHNldHRsZXMgaXQsIGFuZCB0aGlzIOKAlCBub3QgdGhlIGZ1bGxcbiAgLy8gcmVwbGF5IFRUTCDigJQgaXMgaG93IGxvbmcgcmV0cmllcyBvZiB0aGF0IGtleSBhcmUgcmVmdXNlZC5cbiAgY29uc3QgcGVuZGluZ1R0bE1zID0gTWF0aC5taW4oQ29yZUNvbnN0YW50cy5JREVNUE9URU5DWV9QRU5ESU5HX1RUTF9NUywgdHRsTXMpO1xuICBjb25zdCBwZW5kaW5nVHRsU2VjID0gTWF0aC5tYXgoMSwgTWF0aC5mbG9vcihwZW5kaW5nVHRsTXMgLyAxMDAwKSk7XG5cbiAgcmV0dXJuIChyZXE6IFJlcXVlc3QsIHJlczogUmVzcG9uc2UsIG5leHQ6IE5leHRGdW5jdGlvbikgPT4ge1xuICAgIGNvbnN0IHN0b3JlID0gZXhwbGljaXRTdG9yZSA/PyBkZWZhdWx0U3RvcmU7XG4gICAgY29uc3Qga2V5ID0gcmVxLmhlYWRlcnNbJ2lkZW1wb3RlbmN5LWtleSddIGFzIHN0cmluZyB8IHVuZGVmaW5lZDtcbiAgICBpZiAoIWtleSkgcmV0dXJuIG5leHQoKTtcblxuICAgIC8vIE9ubHkgYXBwbHkgdG8gbXV0YXRpb24gbWV0aG9kc1xuICAgIGlmICghSURFTVBPVEVOVF9NRVRIT0RTLmluY2x1ZGVzKHJlcS5tZXRob2QpKSByZXR1cm4gbmV4dCgpO1xuXG4gICAgLy8gT25lIHBhc3MgcGVyIHJlcXVlc3Q6IGEgbGF0ZXIgc3RhY2tlZCBjaGFpbiBtdXN0IG5vdCByZS1jaGVjayB0aGUga2V5LlxuICAgIGNvbnN0IG1hcmtlZCA9IHJlcSBhcyBSZXF1ZXN0ICYgeyBbSURFTVBPVEVOQ1lfSEFORExFRF0/OiB0cnVlIH07XG4gICAgaWYgKG1hcmtlZFtJREVNUE9URU5DWV9IQU5ETEVEXSkgcmV0dXJuIG5leHQoKTtcblxuICAgIGNvbnN0IGZ1bGxLZXkgPSBpZGVtcG90ZW5jeVN0b3JlS2V5KHJlcSwga2V5KTtcbiAgICBpZiAoIWZ1bGxLZXkpIHJldHVybiBuZXh0KCk7IC8vIHNraXAgaWRlbXBvdGVuY3kgZm9yIHVuYXV0aGVudGljYXRlZCByZXF1ZXN0c1xuICAgIG1hcmtlZFtJREVNUE9URU5DWV9IQU5ETEVEXSA9IHRydWU7XG5cbiAgICAvKiogUmVqZWN0IGEgZHVwbGljYXRlIHdob3NlIG9yaWdpbmFsIGlzIHN0aWxsIGluLWZsaWdodC4gKi9cbiAgICBjb25zdCBzZW5kSW5Qcm9ncmVzcyA9ICgpOiB2b2lkID0+IHtcbiAgICAgIHJlcy5zZXRIZWFkZXIoJ1JldHJ5LUFmdGVyJywgJzEnKTtcbiAgICAgIHNlbmRFcnJvcihyZXMsIDQwOSwgJ0EgcmVxdWVzdCB3aXRoIHRoaXMgSWRlbXBvdGVuY3ktS2V5IGlzIGFscmVhZHkgYmVpbmcgcHJvY2Vzc2VkJywgRXJyb3JDb2RlLkNPTkZMSUNUKTtcbiAgICB9O1xuXG4gICAgc3RvcmUuZ2V0KGZ1bGxLZXkpLnRoZW4oYXN5bmMgKGNhY2hlZCkgPT4ge1xuICAgICAgaWYgKGNhY2hlZCAmJiAhY2FjaGVkLnBlbmRpbmcpIHtcbiAgICAgICAgLy8gQ29tcGxldGVkIHJlc3BvbnNlIG9uIHJlY29yZCDihpIgcmVwbGF5IGl0LlxuICAgICAgICBsb2dnZXIuZGVidWcoJ0lkZW1wb3RlbnQgcmVxdWVzdCByZXBsYXllZCcsIHsga2V5OiBmdWxsS2V5IH0pO1xuICAgICAgICAocmVzLmxvY2FscyA/Pz0ge30pW0lERU1QT1RFTlRfUkVQTEFZX0xPQ0FMXSA9IHRydWU7XG4gICAgICAgIHJlcy5zZXRIZWFkZXIoJ1gtSWRlbXBvdGVudC1SZXBsYXllZCcsICd0cnVlJyk7XG4gICAgICAgIHJlcy5zdGF0dXMoY2FjaGVkLnN0YXR1c0NvZGUpLmpzb24oY2FjaGVkLmJvZHkpO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICBpZiAoY2FjaGVkICYmIGNhY2hlZC5wZW5kaW5nKSB7XG4gICAgICAgIC8vIFRoZSBvcmlnaW5hbCBpcyBzdGlsbCBydW5uaW5nIOKAlCBkb24ndCBydW4gdGhlIG11dGF0aW9uIGEgc2Vjb25kIHRpbWUuXG4gICAgICAgIGxvZ2dlci5kZWJ1ZygnSWRlbXBvdGVudCByZXF1ZXN0IHJlamVjdGVkIChpbiBwcm9ncmVzcyknLCB7IGtleTogZnVsbEtleSB9KTtcbiAgICAgICAgcmV0dXJuIHNlbmRJblByb2dyZXNzKCk7XG4gICAgICB9XG5cbiAgICAgIC8vIEF0b21pY2FsbHkgcmVzZXJ2ZSB0aGUga2V5LiBMb3NpbmcgdGhpcyByYWNlIG1lYW5zIGEgY29uY3VycmVudCByZXF1ZXN0XG4gICAgICAvLyB3aXRoIHRoZSBzYW1lIGtleSBnb3QgdGhlcmUgZmlyc3QgYW5kIGlzIGluLWZsaWdodCDihpIgNDA5LlxuICAgICAgY29uc3Qgd29uID0gYXdhaXQgc3RvcmUucmVzZXJ2ZShcbiAgICAgICAgZnVsbEtleSxcbiAgICAgICAgeyBzdGF0dXNDb2RlOiAwLCBib2R5OiBudWxsLCBwZW5kaW5nOiB0cnVlLCBleHBpcmVzQXQ6IERhdGUubm93KCkgKyBwZW5kaW5nVHRsTXMgfSxcbiAgICAgICAgcGVuZGluZ1R0bFNlYyxcbiAgICAgICk7XG4gICAgICBpZiAoIXdvbikge1xuICAgICAgICBsb2dnZXIuZGVidWcoJ0lkZW1wb3RlbnQgcmVxdWVzdCByZWplY3RlZCAobG9zdCByZXNlcnZlIHJhY2UpJywgeyBrZXk6IGZ1bGxLZXkgfSk7XG4gICAgICAgIHJldHVybiBzZW5kSW5Qcm9ncmVzcygpO1xuICAgICAgfVxuXG4gICAgICAvLyBXZSBvd24gdGhlIHJlc2VydmF0aW9uLiBJdCBNVVNUIGJlIHJlc29sdmVkIGV4YWN0bHkgb25jZSDigJQgZWl0aGVyIHRoZVxuICAgICAgLy8gcmVhbCAyeHggcmVzcG9uc2UgaXMgY2FjaGVkIGZvciByZXBsYXksIG9yIHRoZSByZXNlcnZhdGlvbiBpcyByZWxlYXNlZCBzb1xuICAgICAgLy8gYSByZXRyeSBjYW4gcHJvY2VlZC4gYHNldHRsZWRgIGd1YXJkcyBhZ2FpbnN0IGEgZG91YmxlLXJlc29sdmUuXG4gICAgICBsZXQgc2V0dGxlZCA9IGZhbHNlO1xuICAgICAgbGV0IGNhcHR1cmVkQm9keTogdW5rbm93bjtcbiAgICAgIGxldCBib2R5Q2FwdHVyZWQgPSBmYWxzZTtcblxuICAgICAgLyoqIFJlbWVtYmVyIHRoZSByZXNwb25zZSBib2R5IGZvciByZXBsYXkgKGZpcnN0IGNhcHR1cmUgd2lucykuICovXG4gICAgICBjb25zdCBjYXB0dXJlQm9keSA9IChib2R5OiB1bmtub3duKTogdm9pZCA9PiB7XG4gICAgICAgIGlmICghYm9keUNhcHR1cmVkKSB7XG4gICAgICAgICAgY2FwdHVyZWRCb2R5ID0gYm9keTtcbiAgICAgICAgICBib2R5Q2FwdHVyZWQgPSB0cnVlO1xuICAgICAgICB9XG4gICAgICB9O1xuXG4gICAgICBjb25zdCByZWxlYXNlID0gKCk6IHZvaWQgPT4ge1xuICAgICAgICBpZiAoc2V0dGxlZCkgcmV0dXJuO1xuICAgICAgICBzZXR0bGVkID0gdHJ1ZTtcbiAgICAgICAgc3RvcmUuZGVsZXRlKGZ1bGxLZXkpLmNhdGNoKChlcnIpID0+IHtcbiAgICAgICAgICBsb2dnZXIud2FybignSWRlbXBvdGVuY3kgcmVzZXJ2YXRpb24gcmVsZWFzZSBmYWlsZWQnLCB7IGtleTogZnVsbEtleSwgZXJyb3I6IGVycm9yTWVzc2FnZShlcnIpIH0pO1xuICAgICAgICB9KTtcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IGNhY2hlU3VjY2VzcyA9ICgpOiB2b2lkID0+IHtcbiAgICAgICAgaWYgKHNldHRsZWQpIHJldHVybjtcbiAgICAgICAgc2V0dGxlZCA9IHRydWU7XG4gICAgICAgIHN0b3JlLnNldChmdWxsS2V5LCB7XG4gICAgICAgICAgc3RhdHVzQ29kZTogcmVzLnN0YXR1c0NvZGUsXG4gICAgICAgICAgYm9keTogYm9keUNhcHR1cmVkID8gY2FwdHVyZWRCb2R5IDogbnVsbCxcbiAgICAgICAgICBleHBpcmVzQXQ6IERhdGUubm93KCkgKyB0dGxNcyxcbiAgICAgICAgfSwgdHRsU2VjKS5jYXRjaCgoZXJyKSA9PiB7XG4gICAgICAgICAgbG9nZ2VyLndhcm4oJ0lkZW1wb3RlbmN5IHN0b3JlLnNldCBmYWlsZWQnLCB7IGtleTogZnVsbEtleSwgZXJyb3I6IGVycm9yTWVzc2FnZShlcnIpIH0pO1xuICAgICAgICB9KTtcbiAgICAgIH07XG5cbiAgICAgIC8qKlxuICAgICAgICogUmVzb2x2ZSB0aGUgcmVzZXJ2YXRpb24gZnJvbSB0aGUgQUNUVUFMIGZpbmFsIHN0YXR1czogYSAyeHggaXMgY2FjaGVkIGZvclxuICAgICAgICogcmVwbGF5OyBhbnl0aGluZyBlbHNlICh0aGUgaGFuZGxlciByZWZ1c2VkIG9yIGZhaWxlZCDigJQgdGhlIG11dGF0aW9uIGRpZFxuICAgICAgICogbm90IHRha2UgZWZmZWN0KSByZWxlYXNlcyB0aGUga2V5IHNvIGEgcmV0cnkgZ2VudWluZWx5IHJlLXJ1bnMuXG4gICAgICAgKi9cbiAgICAgIGNvbnN0IHNldHRsZUZyb21TdGF0dXMgPSAoKTogdm9pZCA9PiB7XG4gICAgICAgIGlmIChzZXR0bGVkKSByZXR1cm47XG4gICAgICAgIGlmIChyZXMuc3RhdHVzQ29kZSA+PSAyMDAgJiYgcmVzLnN0YXR1c0NvZGUgPCAzMDApIGNhY2hlU3VjY2VzcygpO1xuICAgICAgICBlbHNlIHJlbGVhc2UoKTtcbiAgICAgIH07XG5cbiAgICAgIC8vIEZhc3QgcGF0aDogcmVzLmpzb24gaXMgdGhlIGNvbW1vbiBjb21wbGV0aW9uLiBDYXB0dXJlIHRoZSBib2R5IGFuZCBzZXR0bGVcbiAgICAgIC8vIGltbWVkaWF0ZWx5IG9mZiB0aGUgc3RhdHVzIHNldCBieSByZXMuc3RhdHVzKC4uLikuanNvbiguLi4pLlxuICAgICAgY29uc3Qgb3JpZ2luYWxKc29uID0gcmVzLmpzb24uYmluZChyZXMpO1xuICAgICAgcmVzLmpzb24gPSAoYm9keTogdW5rbm93bikgPT4ge1xuICAgICAgICByZXMuc2V0SGVhZGVyKCdYLUlkZW1wb3RlbnQtUmVwbGF5ZWQnLCAnZmFsc2UnKTtcbiAgICAgICAgY2FwdHVyZUJvZHkoYm9keSk7XG4gICAgICAgIHNldHRsZUZyb21TdGF0dXMoKTtcbiAgICAgICAgcmV0dXJuIG9yaWdpbmFsSnNvbihib2R5KTtcbiAgICAgIH07XG5cbiAgICAgIC8vIEJvZHktY2FwdHVyZSBiYWNrc3RvcHMgZm9yIGNvbXBsZXRpb25zIHRoYXQgYnlwYXNzIHJlcy5qc29uXG4gICAgICAvLyAocmVzLnNlbmQgLyByZXMuZW5kIC8gcmVzLnNlbmRGaWxlIOKGkiByZXMuZW5kKS4gVGhlc2Ugb25seSBSRUNPUkQgdGhlIGJvZHk7XG4gICAgICAvLyB0aGUgYWN0dWFsIHNldHRsZSBoYXBwZW5zIG9uIGBmaW5pc2hgIGZyb20gdGhlIHJlYWwgc3RhdHVzIGNvZGUuIEZpcnN0XG4gICAgICAvLyBjYXB0dXJlIHdpbnMsIHNvIHJlcy5qc29uJ3MgYm9keSBpcyBuZXZlciBjbG9iYmVyZWQgYnkgaXRzIGludGVybmFsXG4gICAgICAvLyByZXMuc2VuZC9yZXMuZW5kIGNhbGxzLlxuICAgICAgY29uc3QgcGF0Y2hlZCA9IHJlcyBhcyB1bmtub3duIGFzIHtcbiAgICAgICAgc2VuZD86IChib2R5PzogdW5rbm93bikgPT4gdW5rbm93bjtcbiAgICAgICAgZW5kPzogKC4uLmFyZ3M6IHVua25vd25bXSkgPT4gdW5rbm93bjtcbiAgICAgICAgb24/OiAoZXZlbnQ6IHN0cmluZywgY2I6ICgpID0+IHZvaWQpID0+IHVua25vd247XG4gICAgICB9O1xuICAgICAgaWYgKHR5cGVvZiBwYXRjaGVkLnNlbmQgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgY29uc3Qgb3JpZ2luYWxTZW5kID0gcGF0Y2hlZC5zZW5kLmJpbmQocmVzKTtcbiAgICAgICAgcGF0Y2hlZC5zZW5kID0gKGJvZHk/OiB1bmtub3duKSA9PiB7XG4gICAgICAgICAgY2FwdHVyZUJvZHkoYm9keSk7XG4gICAgICAgICAgcmV0dXJuIG9yaWdpbmFsU2VuZChib2R5KTtcbiAgICAgICAgfTtcbiAgICAgIH1cbiAgICAgIGlmICh0eXBlb2YgcGF0Y2hlZC5lbmQgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgY29uc3Qgb3JpZ2luYWxFbmQgPSBwYXRjaGVkLmVuZC5iaW5kKHJlcyk7XG4gICAgICAgIHBhdGNoZWQuZW5kID0gKC4uLmFyZ3M6IHVua25vd25bXSkgPT4ge1xuICAgICAgICAgIGNvbnN0IGNodW5rID0gYXJnc1swXTtcbiAgICAgICAgICBpZiAoY2h1bmsgIT09IHVuZGVmaW5lZCAmJiB0eXBlb2YgY2h1bmsgIT09ICdmdW5jdGlvbicpIGNhcHR1cmVCb2R5KGNodW5rKTtcbiAgICAgICAgICBjb25zdCBvdXQgPSBvcmlnaW5hbEVuZCguLi5hcmdzKTtcbiAgICAgICAgICAvLyBUaGUgaGFuZGxlciBoYXMgcHJvZHVjZWQgaXRzIGZpbmFsIHN0YXR1cy4gU2V0dGxlIEhFUkUgcmF0aGVyIHRoYW5cbiAgICAgICAgICAvLyB3YWl0aW5nIGZvciAnZmluaXNoJzogYWZ0ZXIgYSBjbGllbnQgZGlzY29ubmVjdCAnZmluaXNoJyBuZXZlciBmaXJlcyxcbiAgICAgICAgICAvLyBhbmQgdGhlIGhhbmRsZXIncyBvdXRjb21lIG11c3Qgc3RpbGwgYmUgcmVjb3JkZWQuXG4gICAgICAgICAgc2V0dGxlRnJvbVN0YXR1cygpO1xuICAgICAgICAgIHJldHVybiBvdXQ7XG4gICAgICAgIH07XG4gICAgICB9XG5cbiAgICAgIC8vIEJhY2tzdG9wIGZvciBBTlkgY29tcGxldGlvbiBwYXRoIOKAlCBpbmNsdWRpbmcgYSAyeHggdGhhdCBmaW5pc2hlZCB2aWFcbiAgICAgIC8vIHJlcy5zZW5kL3Jlcy5lbmQvcmVzLnNlbmRGaWxlLzIwNCBhbmQgbmV2ZXIgaGl0IHRoZSBwYXRjaGVkIHJlcy5qc29uLlxuICAgICAgLy8gRGVjaWRpbmcgb24gdGhlIHJlYWwgZmluYWwgc3RhdHVzIGhlcmUgbWVhbnMgYSBzdWNjZXNzZnVsIG9wIGlzIGNhY2hlZFxuICAgICAgLy8gKG9yIGEgZmFpbGVkIG9uZSByZWxlYXNlZCkgaW5zdGVhZCBvZiBzdHJhbmRpbmcgdGhlIHJlc2VydmF0aW9uIGFuZFxuICAgICAgLy8gNDA5LWluZyBldmVyeSByZXRyeSBmb3IgdGhlIGZ1bGwgVFRMLiBHdWFyZGVkIOKAlCB0ZXN0IGRvdWJsZXMgbWF5IG5vdCBiZVxuICAgICAgLy8gRXZlbnRFbWl0dGVyczsgcmVzLmpzb24ncyBmYXN0IHBhdGggYWxyZWFkeSBzZXR0bGVkIHRoZSBjb21tb24gY2FzZS5cbiAgICAgIGlmICh0eXBlb2YgcGF0Y2hlZC5vbiA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICBwYXRjaGVkLm9uKCdmaW5pc2gnLCBzZXR0bGVGcm9tU3RhdHVzKTtcbiAgICAgICAgLy8gQSBjbGllbnQgdGhhdCBkaXNjb25uZWN0cyBlbWl0cyAnY2xvc2UnIFdJVEhPVVQgJ2ZpbmlzaCcg4oCUIGJ1dCB0aGVcbiAgICAgICAgLy8gSEFORExFUiBrZWVwcyBydW5uaW5nIGFuZCBtYXkgc3RpbGwgY29tbWl0IHRoZSBtdXRhdGlvbi4gUmVsZWFzaW5nXG4gICAgICAgIC8vIGhlcmUgbGV0IHRoZSBjbGllbnQncyByZXRyeSBydW4gaXQgYSBzZWNvbmQgdGltZSAoYSBkdXBsaWNhdGUgY3JlYXRlIC9cbiAgICAgICAgLy8gZG91YmxlIGNoYXJnZSDigJQgdGhlIHZlcnkgdGhpbmcgdGhlIGtleSBleGlzdHMgdG8gcHJldmVudCkuIFNvIHRoZVxuICAgICAgICAvLyByZXNlcnZhdGlvbiBzdGF5cyBwZW5kaW5nOiB0aGUgaGFuZGxlcidzIG93biBjb21wbGV0aW9uIHNldHRsZXMgaXRcbiAgICAgICAgLy8gKHJlcy5qc29uIC8gcmVzLmVuZCBhYm92ZSksIGFuZCBpZiB0aGUgcHJvY2VzcyBkaWVzIGluc3RlYWQsIHRoZVxuICAgICAgICAvLyBzaG9ydCBwZW5kaW5nIFRUTCBmcmVlcyB0aGUga2V5LlxuICAgICAgfVxuXG4gICAgICBuZXh0KCk7XG4gICAgfSkuY2F0Y2goKGVycikgPT4ge1xuICAgICAgLy8gSWYgdGhlIHN0b3JlIGJhY2tlbmQgaXMgZG93biwgZmFpbCBvcGVuIOKAlCBwcm9jZXNzIHRoZSByZXF1ZXN0IG5vcm1hbGx5LlxuICAgICAgbG9nZ2VyLndhcm4oJ0lkZW1wb3RlbmN5IHN0b3JlLmdldCBmYWlsZWQ7IHByb2NlZWRpbmcgd2l0aG91dCBkZWR1cCcsIHsga2V5OiBmdWxsS2V5LCBlcnJvcjogZXJyb3JNZXNzYWdlKGVycikgfSk7XG4gICAgICBuZXh0KCk7XG4gICAgfSk7XG4gIH07XG59XG4iXX0=
@@ -12,9 +12,10 @@ export * from './app-factory.js';
12
12
  export * from './health-checks.js';
13
13
  export * from './mongo-connect.js';
14
14
  export * from './quota-reservation.js';
15
- export { getIdempotencyStore, type IdempotencyStore } from './idempotency-middleware.js';
15
+ export * from './ai-call-reservation.js';
16
+ export { getIdempotencyStore, isIdempotentReplay, IDEMPOTENT_REPLAY_LOCAL, type IdempotencyStore } from './idempotency-middleware.js';
16
17
  export { withSpan, currentTraceId } from './tracing.js';
17
- export { registerSecretRotationGauge, incCounter, observe, setGauge, createMetricHelpers, type MetricHelpers } from './metrics.js';
18
+ export { registerSecretRotationGauge, incCounter, observe, setGauge, resetGauge, createMetricHelpers, type MetricHelpers } from './metrics.js';
18
19
  export * from './server.js';
19
20
  export { isReady, setReady, readinessGuard } from './readiness.js';
20
21
  export * from './route-wrapper.js';
package/lib/api/index.js CHANGED
@@ -19,14 +19,15 @@ export * from './health-checks.js';
19
19
  export * from './mongo-connect.js';
20
20
  // Quota helpers
21
21
  export * from './quota-reservation.js';
22
+ export * from './ai-call-reservation.js';
22
23
  // Idempotency — only the store accessor is public; the middleware, the store
23
24
  // factories and the store setter are wired by `createApp`/`middleware-factory`
24
25
  // inside this package and have no external caller.
25
- export { getIdempotencyStore } from './idempotency-middleware.js';
26
+ export { getIdempotencyStore, isIdempotentReplay, IDEMPOTENT_REPLAY_LOCAL } from './idempotency-middleware.js';
26
27
  // Observability. `shutdownTracing` is called by this package's own `server.js`
27
28
  // shutdown path, and the metrics middleware/handler are mounted by `createApp`.
28
29
  export { withSpan, currentTraceId } from './tracing.js';
29
- export { registerSecretRotationGauge, incCounter, observe, setGauge, createMetricHelpers } from './metrics.js';
30
+ export { registerSecretRotationGauge, incCounter, observe, setGauge, resetGauge, createMetricHelpers } from './metrics.js';
30
31
  // Server utilities
31
32
  export * from './server.js';
32
33
  // Readiness state + guard middleware. `DEFAULT_READINESS_BYPASS` is the guard's
@@ -34,4 +35,4 @@ export * from './server.js';
34
35
  export { isReady, setReady, readinessGuard } from './readiness.js';
35
36
  // Route wrapper
36
37
  export * from './route-wrapper.js';
37
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvYXBpL2luZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLCtDQUErQztBQUMvQyxzQ0FBc0M7QUFFdEMsYUFBYTtBQUNiLGNBQWMseUJBQXlCLENBQUM7QUFDeEMsY0FBYyx5QkFBeUIsQ0FBQztBQUN4QyxjQUFjLGtCQUFrQixDQUFDO0FBQ2pDLGNBQWMsa0JBQWtCLENBQUM7QUFDakMsY0FBYyx3QkFBd0IsQ0FBQztBQUN2QyxPQUFPLEVBQUUsMEJBQTBCLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQztBQUNuRSxjQUFjLHFCQUFxQixDQUFDO0FBQ3BDLGNBQWMscUJBQXFCLENBQUM7QUFDcEMsY0FBYyxnQkFBZ0IsQ0FBQztBQUMvQixjQUFjLGtCQUFrQixDQUFDO0FBRWpDLGNBQWM7QUFDZCxjQUFjLGtCQUFrQixDQUFDO0FBRWpDLHVCQUF1QjtBQUN2QixjQUFjLG9CQUFvQixDQUFDO0FBRW5DLDJEQUEyRDtBQUMzRCxjQUFjLG9CQUFvQixDQUFDO0FBRW5DLGdCQUFnQjtBQUNoQixjQUFjLHdCQUF3QixDQUFDO0FBRXZDLDZFQUE2RTtBQUM3RSwrRUFBK0U7QUFDL0UsbURBQW1EO0FBQ25ELE9BQU8sRUFBRSxtQkFBbUIsRUFBeUIsTUFBTSw2QkFBNkIsQ0FBQztBQUV6RiwrRUFBK0U7QUFDL0UsZ0ZBQWdGO0FBQ2hGLE9BQU8sRUFBRSxRQUFRLEVBQUUsY0FBYyxFQUFFLE1BQU0sY0FBYyxDQUFDO0FBQ3hELE9BQU8sRUFBRSwyQkFBMkIsRUFBRSxVQUFVLEVBQUUsT0FBTyxFQUFFLFFBQVEsRUFBRSxtQkFBbUIsRUFBc0IsTUFBTSxjQUFjLENBQUM7QUFFbkksbUJBQW1CO0FBQ25CLGNBQWMsYUFBYSxDQUFDO0FBRTVCLGdGQUFnRjtBQUNoRiw0RUFBNEU7QUFDNUUsT0FBTyxFQUFFLE9BQU8sRUFBRSxRQUFRLEVBQUUsY0FBYyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFFbkUsZ0JBQWdCO0FBQ2hCLGNBQWMsb0JBQW9CLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBDb3B5cmlnaHQgMjAyNiBQaXBlbGluZSBCdWlsZGVyIENvbnRyaWJ1dG9yc1xuLy8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFwYWNoZS0yLjBcblxuLy8gTWlkZGxld2FyZVxuZXhwb3J0ICogZnJvbSAnLi9taWRkbGV3YXJlLWZhY3RvcnkuanMnO1xuZXhwb3J0ICogZnJvbSAnLi9jb250ZXh0LW1pZGRsZXdhcmUuanMnO1xuZXhwb3J0ICogZnJvbSAnLi9jaGVjay1xdW90YS5qcyc7XG5leHBvcnQgKiBmcm9tICcuL21ldGVyLXF1b3RhLmpzJztcbmV4cG9ydCAqIGZyb20gJy4vcmF0ZS1saW1pdC1ieS1vcmcuanMnO1xuZXhwb3J0IHsgY3JlYXRlU2hhcmVkUmF0ZUxpbWl0U3RvcmUgfSBmcm9tICcuL3JhdGUtbGltaXQtc3RvcmUuanMnO1xuZXhwb3J0ICogZnJvbSAnLi9yZXF1aXJlLW9yZy1pZC5qcyc7XG5leHBvcnQgKiBmcm9tICcuL3RlbmFudC1jb250ZXh0LmpzJztcbmV4cG9ydCAqIGZyb20gJy4vd3JpdGUtcGluLmpzJztcbmV4cG9ydCAqIGZyb20gJy4vZ2V0LWNvbnRleHQuanMnO1xuXG4vLyBBcHAgZmFjdG9yeVxuZXhwb3J0ICogZnJvbSAnLi9hcHAtZmFjdG9yeS5qcyc7XG5cbi8vIEhlYWx0aC1jaGVjayBoZWxwZXJzXG5leHBvcnQgKiBmcm9tICcuL2hlYWx0aC1jaGVja3MuanMnO1xuXG4vLyBNb25nb0RCIGNvbm5lY3Rpb24gaGVscGVyIChkZXBlbmRlbmN5LWluamVjdGVkIG1vbmdvb3NlKVxuZXhwb3J0ICogZnJvbSAnLi9tb25nby1jb25uZWN0LmpzJztcblxuLy8gUXVvdGEgaGVscGVyc1xuZXhwb3J0ICogZnJvbSAnLi9xdW90YS1yZXNlcnZhdGlvbi5qcyc7XG5cbi8vIElkZW1wb3RlbmN5IOKAlCBvbmx5IHRoZSBzdG9yZSBhY2Nlc3NvciBpcyBwdWJsaWM7IHRoZSBtaWRkbGV3YXJlLCB0aGUgc3RvcmVcbi8vIGZhY3RvcmllcyBhbmQgdGhlIHN0b3JlIHNldHRlciBhcmUgd2lyZWQgYnkgYGNyZWF0ZUFwcGAvYG1pZGRsZXdhcmUtZmFjdG9yeWBcbi8vIGluc2lkZSB0aGlzIHBhY2thZ2UgYW5kIGhhdmUgbm8gZXh0ZXJuYWwgY2FsbGVyLlxuZXhwb3J0IHsgZ2V0SWRlbXBvdGVuY3lTdG9yZSwgdHlwZSBJZGVtcG90ZW5jeVN0b3JlIH0gZnJvbSAnLi9pZGVtcG90ZW5jeS1taWRkbGV3YXJlLmpzJztcblxuLy8gT2JzZXJ2YWJpbGl0eS4gYHNodXRkb3duVHJhY2luZ2AgaXMgY2FsbGVkIGJ5IHRoaXMgcGFja2FnZSdzIG93biBgc2VydmVyLmpzYFxuLy8gc2h1dGRvd24gcGF0aCwgYW5kIHRoZSBtZXRyaWNzIG1pZGRsZXdhcmUvaGFuZGxlciBhcmUgbW91bnRlZCBieSBgY3JlYXRlQXBwYC5cbmV4cG9ydCB7IHdpdGhTcGFuLCBjdXJyZW50VHJhY2VJZCB9IGZyb20gJy4vdHJhY2luZy5qcyc7XG5leHBvcnQgeyByZWdpc3RlclNlY3JldFJvdGF0aW9uR2F1Z2UsIGluY0NvdW50ZXIsIG9ic2VydmUsIHNldEdhdWdlLCBjcmVhdGVNZXRyaWNIZWxwZXJzLCB0eXBlIE1ldHJpY0hlbHBlcnMgfSBmcm9tICcuL21ldHJpY3MuanMnO1xuXG4vLyBTZXJ2ZXIgdXRpbGl0aWVzXG5leHBvcnQgKiBmcm9tICcuL3NlcnZlci5qcyc7XG5cbi8vIFJlYWRpbmVzcyBzdGF0ZSArIGd1YXJkIG1pZGRsZXdhcmUuIGBERUZBVUxUX1JFQURJTkVTU19CWVBBU1NgIGlzIHRoZSBndWFyZCdzXG4vLyBvd24gZGVmYXVsdCDigJQgY2FsbGVycyBwYXNzIHRoZWlyIG93biBsaXN0IG9yIHRha2UgdGhlIGRlZmF1bHQgaW1wbGljaXRseS5cbmV4cG9ydCB7IGlzUmVhZHksIHNldFJlYWR5LCByZWFkaW5lc3NHdWFyZCB9IGZyb20gJy4vcmVhZGluZXNzLmpzJztcblxuLy8gUm91dGUgd3JhcHBlclxuZXhwb3J0ICogZnJvbSAnLi9yb3V0ZS13cmFwcGVyLmpzJztcblxuLy8gUmVxdWVzdC9SZXNwb25zZSB0eXBlcy4gYGNyZWF0ZVJlcXVlc3RDb250ZXh0YCBpcyB0aGUgZmFjdG9yeVxuLy8gYGF0dGFjaFJlcXVlc3RDb250ZXh0YCBjYWxsczsgaXQgaXMgbm90IHBhcnQgb2YgdGhlIHB1YmxpYyBzdXJmYWNlLlxuZXhwb3J0IHR5cGUgeyBSZXF1ZXN0TG9nZ2VyLCBSZXF1ZXN0Q29udGV4dCB9IGZyb20gJy4vcmVxdWVzdC10eXBlcy5qcyc7XG4iXX0=
38
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvYXBpL2luZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLCtDQUErQztBQUMvQyxzQ0FBc0M7QUFFdEMsYUFBYTtBQUNiLGNBQWMseUJBQXlCLENBQUM7QUFDeEMsY0FBYyx5QkFBeUIsQ0FBQztBQUN4QyxjQUFjLGtCQUFrQixDQUFDO0FBQ2pDLGNBQWMsa0JBQWtCLENBQUM7QUFDakMsY0FBYyx3QkFBd0IsQ0FBQztBQUN2QyxPQUFPLEVBQUUsMEJBQTBCLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQztBQUNuRSxjQUFjLHFCQUFxQixDQUFDO0FBQ3BDLGNBQWMscUJBQXFCLENBQUM7QUFDcEMsY0FBYyxnQkFBZ0IsQ0FBQztBQUMvQixjQUFjLGtCQUFrQixDQUFDO0FBRWpDLGNBQWM7QUFDZCxjQUFjLGtCQUFrQixDQUFDO0FBRWpDLHVCQUF1QjtBQUN2QixjQUFjLG9CQUFvQixDQUFDO0FBRW5DLDJEQUEyRDtBQUMzRCxjQUFjLG9CQUFvQixDQUFDO0FBRW5DLGdCQUFnQjtBQUNoQixjQUFjLHdCQUF3QixDQUFDO0FBQ3ZDLGNBQWMsMEJBQTBCLENBQUM7QUFFekMsNkVBQTZFO0FBQzdFLCtFQUErRTtBQUMvRSxtREFBbUQ7QUFDbkQsT0FBTyxFQUFFLG1CQUFtQixFQUFFLGtCQUFrQixFQUFFLHVCQUF1QixFQUF5QixNQUFNLDZCQUE2QixDQUFDO0FBRXRJLCtFQUErRTtBQUMvRSxnRkFBZ0Y7QUFDaEYsT0FBTyxFQUFFLFFBQVEsRUFBRSxjQUFjLEVBQUUsTUFBTSxjQUFjLENBQUM7QUFDeEQsT0FBTyxFQUFFLDJCQUEyQixFQUFFLFVBQVUsRUFBRSxPQUFPLEVBQUUsUUFBUSxFQUFFLFVBQVUsRUFBRSxtQkFBbUIsRUFBc0IsTUFBTSxjQUFjLENBQUM7QUFFL0ksbUJBQW1CO0FBQ25CLGNBQWMsYUFBYSxDQUFDO0FBRTVCLGdGQUFnRjtBQUNoRiw0RUFBNEU7QUFDNUUsT0FBTyxFQUFFLE9BQU8sRUFBRSxRQUFRLEVBQUUsY0FBYyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFFbkUsZ0JBQWdCO0FBQ2hCLGNBQWMsb0JBQW9CLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBDb3B5cmlnaHQgMjAyNiBQaXBlbGluZSBCdWlsZGVyIENvbnRyaWJ1dG9yc1xuLy8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFwYWNoZS0yLjBcblxuLy8gTWlkZGxld2FyZVxuZXhwb3J0ICogZnJvbSAnLi9taWRkbGV3YXJlLWZhY3RvcnkuanMnO1xuZXhwb3J0ICogZnJvbSAnLi9jb250ZXh0LW1pZGRsZXdhcmUuanMnO1xuZXhwb3J0ICogZnJvbSAnLi9jaGVjay1xdW90YS5qcyc7XG5leHBvcnQgKiBmcm9tICcuL21ldGVyLXF1b3RhLmpzJztcbmV4cG9ydCAqIGZyb20gJy4vcmF0ZS1saW1pdC1ieS1vcmcuanMnO1xuZXhwb3J0IHsgY3JlYXRlU2hhcmVkUmF0ZUxpbWl0U3RvcmUgfSBmcm9tICcuL3JhdGUtbGltaXQtc3RvcmUuanMnO1xuZXhwb3J0ICogZnJvbSAnLi9yZXF1aXJlLW9yZy1pZC5qcyc7XG5leHBvcnQgKiBmcm9tICcuL3RlbmFudC1jb250ZXh0LmpzJztcbmV4cG9ydCAqIGZyb20gJy4vd3JpdGUtcGluLmpzJztcbmV4cG9ydCAqIGZyb20gJy4vZ2V0LWNvbnRleHQuanMnO1xuXG4vLyBBcHAgZmFjdG9yeVxuZXhwb3J0ICogZnJvbSAnLi9hcHAtZmFjdG9yeS5qcyc7XG5cbi8vIEhlYWx0aC1jaGVjayBoZWxwZXJzXG5leHBvcnQgKiBmcm9tICcuL2hlYWx0aC1jaGVja3MuanMnO1xuXG4vLyBNb25nb0RCIGNvbm5lY3Rpb24gaGVscGVyIChkZXBlbmRlbmN5LWluamVjdGVkIG1vbmdvb3NlKVxuZXhwb3J0ICogZnJvbSAnLi9tb25nby1jb25uZWN0LmpzJztcblxuLy8gUXVvdGEgaGVscGVyc1xuZXhwb3J0ICogZnJvbSAnLi9xdW90YS1yZXNlcnZhdGlvbi5qcyc7XG5leHBvcnQgKiBmcm9tICcuL2FpLWNhbGwtcmVzZXJ2YXRpb24uanMnO1xuXG4vLyBJZGVtcG90ZW5jeSDigJQgb25seSB0aGUgc3RvcmUgYWNjZXNzb3IgaXMgcHVibGljOyB0aGUgbWlkZGxld2FyZSwgdGhlIHN0b3JlXG4vLyBmYWN0b3JpZXMgYW5kIHRoZSBzdG9yZSBzZXR0ZXIgYXJlIHdpcmVkIGJ5IGBjcmVhdGVBcHBgL2BtaWRkbGV3YXJlLWZhY3RvcnlgXG4vLyBpbnNpZGUgdGhpcyBwYWNrYWdlIGFuZCBoYXZlIG5vIGV4dGVybmFsIGNhbGxlci5cbmV4cG9ydCB7IGdldElkZW1wb3RlbmN5U3RvcmUsIGlzSWRlbXBvdGVudFJlcGxheSwgSURFTVBPVEVOVF9SRVBMQVlfTE9DQUwsIHR5cGUgSWRlbXBvdGVuY3lTdG9yZSB9IGZyb20gJy4vaWRlbXBvdGVuY3ktbWlkZGxld2FyZS5qcyc7XG5cbi8vIE9ic2VydmFiaWxpdHkuIGBzaHV0ZG93blRyYWNpbmdgIGlzIGNhbGxlZCBieSB0aGlzIHBhY2thZ2UncyBvd24gYHNlcnZlci5qc2Bcbi8vIHNodXRkb3duIHBhdGgsIGFuZCB0aGUgbWV0cmljcyBtaWRkbGV3YXJlL2hhbmRsZXIgYXJlIG1vdW50ZWQgYnkgYGNyZWF0ZUFwcGAuXG5leHBvcnQgeyB3aXRoU3BhbiwgY3VycmVudFRyYWNlSWQgfSBmcm9tICcuL3RyYWNpbmcuanMnO1xuZXhwb3J0IHsgcmVnaXN0ZXJTZWNyZXRSb3RhdGlvbkdhdWdlLCBpbmNDb3VudGVyLCBvYnNlcnZlLCBzZXRHYXVnZSwgcmVzZXRHYXVnZSwgY3JlYXRlTWV0cmljSGVscGVycywgdHlwZSBNZXRyaWNIZWxwZXJzIH0gZnJvbSAnLi9tZXRyaWNzLmpzJztcblxuLy8gU2VydmVyIHV0aWxpdGllc1xuZXhwb3J0ICogZnJvbSAnLi9zZXJ2ZXIuanMnO1xuXG4vLyBSZWFkaW5lc3Mgc3RhdGUgKyBndWFyZCBtaWRkbGV3YXJlLiBgREVGQVVMVF9SRUFESU5FU1NfQllQQVNTYCBpcyB0aGUgZ3VhcmQnc1xuLy8gb3duIGRlZmF1bHQg4oCUIGNhbGxlcnMgcGFzcyB0aGVpciBvd24gbGlzdCBvciB0YWtlIHRoZSBkZWZhdWx0IGltcGxpY2l0bHkuXG5leHBvcnQgeyBpc1JlYWR5LCBzZXRSZWFkeSwgcmVhZGluZXNzR3VhcmQgfSBmcm9tICcuL3JlYWRpbmVzcy5qcyc7XG5cbi8vIFJvdXRlIHdyYXBwZXJcbmV4cG9ydCAqIGZyb20gJy4vcm91dGUtd3JhcHBlci5qcyc7XG5cbi8vIFJlcXVlc3QvUmVzcG9uc2UgdHlwZXMuIGBjcmVhdGVSZXF1ZXN0Q29udGV4dGAgaXMgdGhlIGZhY3Rvcnlcbi8vIGBhdHRhY2hSZXF1ZXN0Q29udGV4dGAgY2FsbHM7IGl0IGlzIG5vdCBwYXJ0IG9mIHRoZSBwdWJsaWMgc3VyZmFjZS5cbmV4cG9ydCB0eXBlIHsgUmVxdWVzdExvZ2dlciwgUmVxdWVzdENvbnRleHQgfSBmcm9tICcuL3JlcXVlc3QtdHlwZXMuanMnO1xuIl19
@@ -1,5 +1,5 @@
1
1
  import type { QuotaType, QuotaService } from '@pipeline-builder/api-core';
2
- import type { Request, Response, NextFunction } from 'express';
2
+ import type { Request, RequestHandler, Response, NextFunction } from 'express';
3
3
  /**
4
4
  * Middleware that METERS (increments) a quota counter once per SUCCESSFUL
5
5
  * request, on response `finish`.
@@ -13,19 +13,56 @@ import type { Request, Response, NextFunction } from 'express';
13
13
  *
14
14
  * Fire-and-forget + fail-safe by construction:
15
15
  * - runs in a `finish` listener, so it never blocks or fails the response;
16
- * - `incrementQuota` swallows its own errors (logs a warning);
17
- * - only 2xx responses are metered (a rejected/errored request costs nothing);
16
+ * - `incrementQuota` BUFFERS the unit (api-core quota-increment-batcher): the
17
+ * pod sends one metered increment per (org, type) per flush interval, so the
18
+ * counter lags by at most `QUOTA_INCREMENT_FLUSH_MS`, and a unit past the cap
19
+ * is recorded as `overshoot` rather than counted. Errors are swallowed and
20
+ * counted (`quota_increment_failures_total`);
21
+ * - only 2xx responses are metered (a rejected/errored request costs nothing).
22
+ * A 304 from an ETag match is not 2xx, so revalidating an unchanged
23
+ * resource is free; a response that never FINISHES (client aborted a stream
24
+ * mid-flight, socket destroyed) never emits `finish` and is not counted;
25
+ * - a response REPLAYED from the idempotency cache is skipped — the original
26
+ * request already paid, and the replay did no work. This holds whether the
27
+ * meter is mounted before or after the idempotency middleware: the flag is
28
+ * read at `finish`, after both have run;
18
29
  * - a request with no VERIFIED org (`req.user.organizationId` — set by
19
30
  * requireAuth, never the spoofable header identity) is skipped
20
31
  * (unauthenticated / health / early-terminated);
21
32
  * - SERVICE-PRINCIPAL callers are skipped: internal service-to-service traffic
22
33
  * (e.g. a peer calling compliance `validate`) must not burn a tenant's quota —
23
34
  * the originating service already meters the user action that triggered it.
35
+ * An ORG SERVICE ACCOUNT (or a personal access key) is not a service principal
36
+ * and IS metered — on `automationCalls` instead of `apiCalls`
37
+ * ({@link meteredQuotaTypeFor});
38
+ * - for `apiCalls`, an IMPERSONATION session and an ON-BEHALF hop (a user token
39
+ * forwarded by ask/pipeline with a signed marker) are skipped too — see
40
+ * api-core `callQuotaExemption`;
41
+ * - an `apiCalls` request on the fleet-wide `QUOTA_EXEMPT_ROUTES` (console
42
+ * polling) is skipped.
43
+ *
44
+ * Every increment carries usage attribution (principal, key, route pattern,
45
+ * pipeline, request id) for the quota service's usage ledger.
24
46
  *
25
47
  * Mount it once per route: a second meter for the same quota type on the same
26
- * request double-counts.
48
+ * request double-counts (the route table records each meter, and the quota
49
+ * coverage check fails a route metered twice).
27
50
  *
28
51
  * @param quotaService - Quota service client
29
- * @param quotaType - Which quota to meter (e.g. 'apiCalls')
52
+ * @param quotaType - Which quota to meter (e.g. 'apiCalls' — split per request
53
+ * into apiCalls / automationCalls by principal)
30
54
  */
31
55
  export declare function meterQuotaOnSuccess(quotaService: QuotaService, quotaType: QuotaType): (req: Request, res: Response, next: NextFunction) => void;
56
+ /**
57
+ * THE apiCalls convention for a service's user surface: meter once per 2xx AND
58
+ * gate after authentication, mounted ONCE at the app-routes level ahead of the
59
+ * routers it covers — `app.use('/things', ...apiCallsQuota(quotaService))`.
60
+ *
61
+ * The check is DEFERRED to `requireAuth` ({@link deferredCheckQuota}), so the
62
+ * mount can precede routers that authenticate per route. Both halves skip
63
+ * service principals, unauthenticated requests and the console-polling
64
+ * `QUOTA_EXEMPT_ROUTES`; a service account spends `automationCalls`. A route
65
+ * under such a prefix must NOT also mount its own `meterQuotaOnSuccess` for
66
+ * apiCalls (that bills twice — the quota coverage check fails it).
67
+ */
68
+ export declare function apiCallsQuota(quotaService: QuotaService): RequestHandler[];
@@ -1,7 +1,9 @@
1
1
  // Copyright 2026 Pipeline Builder Contributors
2
2
  // SPDX-License-Identifier: Apache-2.0
3
- import { incrementQuota, isServicePrincipal, createLogger } from '@pipeline-builder/api-core';
3
+ import { callQuotaExemption, incrementQuota, isQuotaExemptRoute, createLogger, meteredQuotaTypeFor, quotaAttributionFromRequest, tagRouteGate } from '@pipeline-builder/api-core';
4
+ import { deferredCheckQuota, requestPath } from './check-quota.js';
4
5
  import { getContext } from './get-context.js';
6
+ import { isIdempotentReplay } from './idempotency-middleware.js';
5
7
  const logger = createLogger('meter-quota');
6
8
  /**
7
9
  * Middleware that METERS (increments) a quota counter once per SUCCESSFUL
@@ -16,28 +18,55 @@ const logger = createLogger('meter-quota');
16
18
  *
17
19
  * Fire-and-forget + fail-safe by construction:
18
20
  * - runs in a `finish` listener, so it never blocks or fails the response;
19
- * - `incrementQuota` swallows its own errors (logs a warning);
20
- * - only 2xx responses are metered (a rejected/errored request costs nothing);
21
+ * - `incrementQuota` BUFFERS the unit (api-core quota-increment-batcher): the
22
+ * pod sends one metered increment per (org, type) per flush interval, so the
23
+ * counter lags by at most `QUOTA_INCREMENT_FLUSH_MS`, and a unit past the cap
24
+ * is recorded as `overshoot` rather than counted. Errors are swallowed and
25
+ * counted (`quota_increment_failures_total`);
26
+ * - only 2xx responses are metered (a rejected/errored request costs nothing).
27
+ * A 304 from an ETag match is not 2xx, so revalidating an unchanged
28
+ * resource is free; a response that never FINISHES (client aborted a stream
29
+ * mid-flight, socket destroyed) never emits `finish` and is not counted;
30
+ * - a response REPLAYED from the idempotency cache is skipped — the original
31
+ * request already paid, and the replay did no work. This holds whether the
32
+ * meter is mounted before or after the idempotency middleware: the flag is
33
+ * read at `finish`, after both have run;
21
34
  * - a request with no VERIFIED org (`req.user.organizationId` — set by
22
35
  * requireAuth, never the spoofable header identity) is skipped
23
36
  * (unauthenticated / health / early-terminated);
24
37
  * - SERVICE-PRINCIPAL callers are skipped: internal service-to-service traffic
25
38
  * (e.g. a peer calling compliance `validate`) must not burn a tenant's quota —
26
39
  * the originating service already meters the user action that triggered it.
40
+ * An ORG SERVICE ACCOUNT (or a personal access key) is not a service principal
41
+ * and IS metered — on `automationCalls` instead of `apiCalls`
42
+ * ({@link meteredQuotaTypeFor});
43
+ * - for `apiCalls`, an IMPERSONATION session and an ON-BEHALF hop (a user token
44
+ * forwarded by ask/pipeline with a signed marker) are skipped too — see
45
+ * api-core `callQuotaExemption`;
46
+ * - an `apiCalls` request on the fleet-wide `QUOTA_EXEMPT_ROUTES` (console
47
+ * polling) is skipped.
48
+ *
49
+ * Every increment carries usage attribution (principal, key, route pattern,
50
+ * pipeline, request id) for the quota service's usage ledger.
27
51
  *
28
52
  * Mount it once per route: a second meter for the same quota type on the same
29
- * request double-counts.
53
+ * request double-counts (the route table records each meter, and the quota
54
+ * coverage check fails a route metered twice).
30
55
  *
31
56
  * @param quotaService - Quota service client
32
- * @param quotaType - Which quota to meter (e.g. 'apiCalls')
57
+ * @param quotaType - Which quota to meter (e.g. 'apiCalls' — split per request
58
+ * into apiCalls / automationCalls by principal)
33
59
  */
34
60
  export function meterQuotaOnSuccess(quotaService, quotaType) {
35
- return (req, res, next) => {
61
+ return tagRouteGate((req, res, next) => {
36
62
  res.on('finish', () => {
37
63
  try {
38
64
  // Only successful responses are billable.
39
65
  if (res.statusCode < 200 || res.statusCode >= 300)
40
66
  return;
67
+ // A cached replay did no work; the original already paid.
68
+ if (isIdempotentReplay(res))
69
+ return;
41
70
  // Resolve the org id from the SAME source `checkQuota` reads —
42
71
  // `getContext().identity.orgId`, which is normalized (trimmed + lowercased).
43
72
  // Metering off the raw `req.user.organizationId` while the gate checks the
@@ -60,12 +89,17 @@ export function meterQuotaOnSuccess(quotaService, quotaType) {
60
89
  }
61
90
  if (!orgId)
62
91
  return;
63
- // Internal service-to-service calls must not consume a tenant's quota.
64
- if (isServicePrincipal(req))
92
+ // Internal service-to-service calls must not consume a tenant's quota;
93
+ // nor, on the call budget, impersonation sessions or on-behalf hops.
94
+ const exemption = callQuotaExemption(req);
95
+ if (exemption === 'service' || (exemption && quotaType === 'apiCalls'))
96
+ return;
97
+ // Console polling never spends a call.
98
+ if (quotaType === 'apiCalls' && isQuotaExemptRoute(req.method, requestPath(req)))
65
99
  return;
66
100
  // incrementQuota authenticates as THIS service (the increment endpoint
67
101
  // is service-principal only — a forwarded user token is always 403).
68
- incrementQuota(quotaService, orgId, quotaType, (message, data) => logger.warn(message, data));
102
+ incrementQuota(quotaService, orgId, meteredQuotaTypeFor(req, quotaType), (message, data) => logger.warn(message, data), quotaAttributionFromRequest(req));
69
103
  }
70
104
  catch {
71
105
  // Metering must never affect the response; a missing user/context just
@@ -73,6 +107,24 @@ export function meterQuotaOnSuccess(quotaService, quotaType) {
73
107
  }
74
108
  });
75
109
  next();
76
- };
110
+ }, { kind: 'quota', mode: 'meter', quotaType });
111
+ }
112
+ /**
113
+ * THE apiCalls convention for a service's user surface: meter once per 2xx AND
114
+ * gate after authentication, mounted ONCE at the app-routes level ahead of the
115
+ * routers it covers — `app.use('/things', ...apiCallsQuota(quotaService))`.
116
+ *
117
+ * The check is DEFERRED to `requireAuth` ({@link deferredCheckQuota}), so the
118
+ * mount can precede routers that authenticate per route. Both halves skip
119
+ * service principals, unauthenticated requests and the console-polling
120
+ * `QUOTA_EXEMPT_ROUTES`; a service account spends `automationCalls`. A route
121
+ * under such a prefix must NOT also mount its own `meterQuotaOnSuccess` for
122
+ * apiCalls (that bills twice — the quota coverage check fails it).
123
+ */
124
+ export function apiCallsQuota(quotaService) {
125
+ return [
126
+ meterQuotaOnSuccess(quotaService, 'apiCalls'),
127
+ deferredCheckQuota(quotaService, 'apiCalls'),
128
+ ];
77
129
  }
78
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWV0ZXItcXVvdGEuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvYXBpL21ldGVyLXF1b3RhLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLCtDQUErQztBQUMvQyxzQ0FBc0M7QUFFdEMsT0FBTyxFQUFFLGNBQWMsRUFBRSxrQkFBa0IsRUFBRSxZQUFZLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQUc5RixPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFFOUMsTUFBTSxNQUFNLEdBQUcsWUFBWSxDQUFDLGFBQWEsQ0FBQyxDQUFDO0FBRTNDOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0EyQkc7QUFDSCxNQUFNLFVBQVUsbUJBQW1CLENBQUMsWUFBMEIsRUFBRSxTQUFvQjtJQUNsRixPQUFPLENBQUMsR0FBWSxFQUFFLEdBQWEsRUFBRSxJQUFrQixFQUFRLEVBQUU7UUFDL0QsR0FBRyxDQUFDLEVBQUUsQ0FBQyxRQUFRLEVBQUUsR0FBRyxFQUFFO1lBQ3BCLElBQUksQ0FBQztnQkFDSCwwQ0FBMEM7Z0JBQzFDLElBQUksR0FBRyxDQUFDLFVBQVUsR0FBRyxHQUFHLElBQUksR0FBRyxDQUFDLFVBQVUsSUFBSSxHQUFHO29CQUFFLE9BQU87Z0JBQzFELCtEQUErRDtnQkFDL0QsNkVBQTZFO2dCQUM3RSwyRUFBMkU7Z0JBQzNFLHdFQUF3RTtnQkFDeEUsNkVBQTZFO2dCQUM3RSwrREFBK0Q7Z0JBQy9ELEVBQUU7Z0JBQ0YscUVBQXFFO2dCQUNyRSwwRUFBMEU7Z0JBQzFFLHdFQUF3RTtnQkFDeEUscUNBQXFDO2dCQUNyQyxJQUFJLENBQUMsR0FBRyxDQUFDLElBQUksRUFBRSxjQUFjO29CQUFFLE9BQU87Z0JBQ3RDLElBQUksS0FBeUIsQ0FBQztnQkFDOUIsSUFBSSxDQUFDO29CQUFDLEtBQUssR0FBRyxVQUFVLENBQUMsR0FBRyxDQUFDLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQztnQkFBQyxDQUFDO2dCQUFDLE1BQU0sQ0FBQztvQkFBQyxLQUFLLEdBQUcsR0FBRyxDQUFDLElBQUksQ0FBQyxjQUFjLENBQUM7Z0JBQUMsQ0FBQztnQkFDMUYsSUFBSSxDQUFDLEtBQUs7b0JBQUUsT0FBTztnQkFDbkIsdUVBQXVFO2dCQUN2RSxJQUFJLGtCQUFrQixDQUFDLEdBQUcsQ0FBQztvQkFBRSxPQUFPO2dCQUNwQyx1RUFBdUU7Z0JBQ3ZFLHFFQUFxRTtnQkFDckUsY0FBYyxDQUNaLFlBQVksRUFDWixLQUFLLEVBQ0wsU0FBUyxFQUNULENBQUMsT0FBTyxFQUFFLElBQUksRUFBRSxFQUFFLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsSUFBK0IsQ0FBQyxDQUN6RSxDQUFDO1lBQ0osQ0FBQztZQUFDLE1BQU0sQ0FBQztnQkFDUCx1RUFBdUU7Z0JBQ3ZFLHdFQUF3RTtZQUMxRSxDQUFDO1FBQ0gsQ0FBQyxDQUFDLENBQUM7UUFDSCxJQUFJLEVBQUUsQ0FBQztJQUNULENBQUMsQ0FBQztBQUNKLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBDb3B5cmlnaHQgMjAyNiBQaXBlbGluZSBCdWlsZGVyIENvbnRyaWJ1dG9yc1xuLy8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFwYWNoZS0yLjBcblxuaW1wb3J0IHsgaW5jcmVtZW50UXVvdGEsIGlzU2VydmljZVByaW5jaXBhbCwgY3JlYXRlTG9nZ2VyIH0gZnJvbSAnQHBpcGVsaW5lLWJ1aWxkZXIvYXBpLWNvcmUnO1xuaW1wb3J0IHR5cGUgeyBRdW90YVR5cGUsIFF1b3RhU2VydmljZSB9IGZyb20gJ0BwaXBlbGluZS1idWlsZGVyL2FwaS1jb3JlJztcbmltcG9ydCB0eXBlIHsgUmVxdWVzdCwgUmVzcG9uc2UsIE5leHRGdW5jdGlvbiB9IGZyb20gJ2V4cHJlc3MnO1xuaW1wb3J0IHsgZ2V0Q29udGV4dCB9IGZyb20gJy4vZ2V0LWNvbnRleHQuanMnO1xuXG5jb25zdCBsb2dnZXIgPSBjcmVhdGVMb2dnZXIoJ21ldGVyLXF1b3RhJyk7XG5cbi8qKlxuICogTWlkZGxld2FyZSB0aGF0IE1FVEVSUyAoaW5jcmVtZW50cykgYSBxdW90YSBjb3VudGVyIG9uY2UgcGVyIFNVQ0NFU1NGVUxcbiAqIHJlcXVlc3QsIG9uIHJlc3BvbnNlIGBmaW5pc2hgLlxuICpcbiAqIFRoZSBjb21wbGVtZW50IHRvIHtAbGluayBjaGVja1F1b3RhfTogYGNoZWNrUXVvdGFgIG9ubHkgR0FURVMgKHJlYWRzIGN1cnJlbnRcbiAqIHVzYWdlIGFuZCA0MjlzIHdoZW4gb3Zlcikg4oCUIGl0IG5ldmVyIGluY3JlbWVudHMsIHNvIGEgc2VydmljZSB0aGF0IG1vdW50cyBpdFxuICogYnV0IG5ldmVyIGluY3JlbWVudHMgY2hlY2tzIGFnYWluc3QgYSBjb3VudGVyIGl0cyBvd24gdHJhZmZpYyBuZXZlciBtb3Zlcy5cbiAqIFRoaXMgaXMgVEhFIGFwaUNhbGxzIG1ldGVyaW5nIGNvbnZlbnRpb246IHB1dCBpdCBvbiBlYWNoIG1ldGVyZWQgcm91dGUgKG9yXG4gKiBtb3VudCBpdCBhaGVhZCBvZiBhIHNlcnZpY2UncyB3aG9sZSBzdXJmYWNlKSByYXRoZXIgdGhhbiBpbmNyZW1lbnRpbmcgYnkgaGFuZFxuICogaW4gaGFuZGxlcnMuXG4gKlxuICogRmlyZS1hbmQtZm9yZ2V0ICsgZmFpbC1zYWZlIGJ5IGNvbnN0cnVjdGlvbjpcbiAqIC0gcnVucyBpbiBhIGBmaW5pc2hgIGxpc3RlbmVyLCBzbyBpdCBuZXZlciBibG9ja3Mgb3IgZmFpbHMgdGhlIHJlc3BvbnNlO1xuICogLSBgaW5jcmVtZW50UXVvdGFgIHN3YWxsb3dzIGl0cyBvd24gZXJyb3JzIChsb2dzIGEgd2FybmluZyk7XG4gKiAtIG9ubHkgMnh4IHJlc3BvbnNlcyBhcmUgbWV0ZXJlZCAoYSByZWplY3RlZC9lcnJvcmVkIHJlcXVlc3QgY29zdHMgbm90aGluZyk7XG4gKiAtIGEgcmVxdWVzdCB3aXRoIG5vIFZFUklGSUVEIG9yZyAoYHJlcS51c2VyLm9yZ2FuaXphdGlvbklkYCDigJQgc2V0IGJ5XG4gKiAgIHJlcXVpcmVBdXRoLCBuZXZlciB0aGUgc3Bvb2ZhYmxlIGhlYWRlciBpZGVudGl0eSkgaXMgc2tpcHBlZFxuICogICAodW5hdXRoZW50aWNhdGVkIC8gaGVhbHRoIC8gZWFybHktdGVybWluYXRlZCk7XG4gKiAtIFNFUlZJQ0UtUFJJTkNJUEFMIGNhbGxlcnMgYXJlIHNraXBwZWQ6IGludGVybmFsIHNlcnZpY2UtdG8tc2VydmljZSB0cmFmZmljXG4gKiAgIChlLmcuIGEgcGVlciBjYWxsaW5nIGNvbXBsaWFuY2UgYHZhbGlkYXRlYCkgbXVzdCBub3QgYnVybiBhIHRlbmFudCdzIHF1b3RhIOKAlFxuICogICB0aGUgb3JpZ2luYXRpbmcgc2VydmljZSBhbHJlYWR5IG1ldGVycyB0aGUgdXNlciBhY3Rpb24gdGhhdCB0cmlnZ2VyZWQgaXQuXG4gKlxuICogTW91bnQgaXQgb25jZSBwZXIgcm91dGU6IGEgc2Vjb25kIG1ldGVyIGZvciB0aGUgc2FtZSBxdW90YSB0eXBlIG9uIHRoZSBzYW1lXG4gKiByZXF1ZXN0IGRvdWJsZS1jb3VudHMuXG4gKlxuICogQHBhcmFtIHF1b3RhU2VydmljZSAtIFF1b3RhIHNlcnZpY2UgY2xpZW50XG4gKiBAcGFyYW0gcXVvdGFUeXBlIC0gV2hpY2ggcXVvdGEgdG8gbWV0ZXIgKGUuZy4gJ2FwaUNhbGxzJylcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG1ldGVyUXVvdGFPblN1Y2Nlc3MocXVvdGFTZXJ2aWNlOiBRdW90YVNlcnZpY2UsIHF1b3RhVHlwZTogUXVvdGFUeXBlKSB7XG4gIHJldHVybiAocmVxOiBSZXF1ZXN0LCByZXM6IFJlc3BvbnNlLCBuZXh0OiBOZXh0RnVuY3Rpb24pOiB2b2lkID0+IHtcbiAgICByZXMub24oJ2ZpbmlzaCcsICgpID0+IHtcbiAgICAgIHRyeSB7XG4gICAgICAgIC8vIE9ubHkgc3VjY2Vzc2Z1bCByZXNwb25zZXMgYXJlIGJpbGxhYmxlLlxuICAgICAgICBpZiAocmVzLnN0YXR1c0NvZGUgPCAyMDAgfHwgcmVzLnN0YXR1c0NvZGUgPj0gMzAwKSByZXR1cm47XG4gICAgICAgIC8vIFJlc29sdmUgdGhlIG9yZyBpZCBmcm9tIHRoZSBTQU1FIHNvdXJjZSBgY2hlY2tRdW90YWAgcmVhZHMg4oCUXG4gICAgICAgIC8vIGBnZXRDb250ZXh0KCkuaWRlbnRpdHkub3JnSWRgLCB3aGljaCBpcyBub3JtYWxpemVkICh0cmltbWVkICsgbG93ZXJjYXNlZCkuXG4gICAgICAgIC8vIE1ldGVyaW5nIG9mZiB0aGUgcmF3IGByZXEudXNlci5vcmdhbml6YXRpb25JZGAgd2hpbGUgdGhlIGdhdGUgY2hlY2tzIHRoZVxuICAgICAgICAvLyBub3JtYWxpemVkIGlkIHdvdWxkIGxhbmQgaW5jcmVtZW50cyBvbiBhIGRpZmZlcmVudCBrZXkgdGhhbiB0aGUgY2hlY2tcbiAgICAgICAgLy8gcmVhZHMgKGEgc2lsZW50IGJ5cGFzcyBpZiBhbiBvcmcgaWQgZXZlciBjYXJyaWVzIG1peGVkIGNhc2UpLiBGYWxsIGJhY2sgdG9cbiAgICAgICAgLy8gdGhlIHJhdyBhdXRoIG9yZyBvbmx5IHdoZW4gY29udGV4dCBtaWRkbGV3YXJlIGlzbid0IG1vdW50ZWQuXG4gICAgICAgIC8vXG4gICAgICAgIC8vIE9ubHkgYSBWRVJJRklFRCBjYWxsZXIgaXMgbWV0ZXJlZC4gVGhlIGluY3JlbWVudCBpcyBzZW50IHdpdGggVEhJU1xuICAgICAgICAvLyBzZXJ2aWNlJ3MgY3JlZGVudGlhbHMsIHNvIG1ldGVyaW5nIGFuIG9yZyB0YWtlbiBmcm9tIHRoZSBoZWFkZXItZGVyaXZlZFxuICAgICAgICAvLyBpZGVudGl0eSBvZiBhbiB1bmF1dGhlbnRpY2F0ZWQgcmVxdWVzdCB3b3VsZCBsZXQgYW55b25lIGJ1cm4gYSB2aWN0aW1cbiAgICAgICAgLy8gb3JnJ3MgcXVvdGEgYnkgc2V0dGluZyBgeC1vcmctaWRgLlxuICAgICAgICBpZiAoIXJlcS51c2VyPy5vcmdhbml6YXRpb25JZCkgcmV0dXJuO1xuICAgICAgICBsZXQgb3JnSWQ6IHN0cmluZyB8IHVuZGVmaW5lZDtcbiAgICAgICAgdHJ5IHsgb3JnSWQgPSBnZXRDb250ZXh0KHJlcSkuaWRlbnRpdHkub3JnSWQ7IH0gY2F0Y2ggeyBvcmdJZCA9IHJlcS51c2VyLm9yZ2FuaXphdGlvbklkOyB9XG4gICAgICAgIGlmICghb3JnSWQpIHJldHVybjtcbiAgICAgICAgLy8gSW50ZXJuYWwgc2VydmljZS10by1zZXJ2aWNlIGNhbGxzIG11c3Qgbm90IGNvbnN1bWUgYSB0ZW5hbnQncyBxdW90YS5cbiAgICAgICAgaWYgKGlzU2VydmljZVByaW5jaXBhbChyZXEpKSByZXR1cm47XG4gICAgICAgIC8vIGluY3JlbWVudFF1b3RhIGF1dGhlbnRpY2F0ZXMgYXMgVEhJUyBzZXJ2aWNlICh0aGUgaW5jcmVtZW50IGVuZHBvaW50XG4gICAgICAgIC8vIGlzIHNlcnZpY2UtcHJpbmNpcGFsIG9ubHkg4oCUIGEgZm9yd2FyZGVkIHVzZXIgdG9rZW4gaXMgYWx3YXlzIDQwMykuXG4gICAgICAgIGluY3JlbWVudFF1b3RhKFxuICAgICAgICAgIHF1b3RhU2VydmljZSxcbiAgICAgICAgICBvcmdJZCxcbiAgICAgICAgICBxdW90YVR5cGUsXG4gICAgICAgICAgKG1lc3NhZ2UsIGRhdGEpID0+IGxvZ2dlci53YXJuKG1lc3NhZ2UsIGRhdGEgYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj4pLFxuICAgICAgICApO1xuICAgICAgfSBjYXRjaCB7XG4gICAgICAgIC8vIE1ldGVyaW5nIG11c3QgbmV2ZXIgYWZmZWN0IHRoZSByZXNwb25zZTsgYSBtaXNzaW5nIHVzZXIvY29udGV4dCBqdXN0XG4gICAgICAgIC8vIG1lYW5zIGFuIHVuYXV0aGVudGljYXRlZCBvciBlYXJseS10ZXJtaW5hdGVkIHJlcXVlc3Qg4oCUIHNraXAgc2lsZW50bHkuXG4gICAgICB9XG4gICAgfSk7XG4gICAgbmV4dCgpO1xuICB9O1xufVxuIl19
130
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWV0ZXItcXVvdGEuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvYXBpL21ldGVyLXF1b3RhLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLCtDQUErQztBQUMvQyxzQ0FBc0M7QUFFdEMsT0FBTyxFQUFFLGtCQUFrQixFQUFFLGNBQWMsRUFBRSxrQkFBa0IsRUFBRSxZQUFZLEVBQUUsbUJBQW1CLEVBQUUsMkJBQTJCLEVBQUUsWUFBWSxFQUFFLE1BQU0sNEJBQTRCLENBQUM7QUFHbEwsT0FBTyxFQUFFLGtCQUFrQixFQUFFLFdBQVcsRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBQ25FLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUM5QyxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSw2QkFBNkIsQ0FBQztBQUVqRSxNQUFNLE1BQU0sR0FBRyxZQUFZLENBQUMsYUFBYSxDQUFDLENBQUM7QUFFM0M7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQW1ERztBQUNILE1BQU0sVUFBVSxtQkFBbUIsQ0FBQyxZQUEwQixFQUFFLFNBQW9CO0lBQ2xGLE9BQU8sWUFBWSxDQUFDLENBQUMsR0FBWSxFQUFFLEdBQWEsRUFBRSxJQUFrQixFQUFRLEVBQUU7UUFDNUUsR0FBRyxDQUFDLEVBQUUsQ0FBQyxRQUFRLEVBQUUsR0FBRyxFQUFFO1lBQ3BCLElBQUksQ0FBQztnQkFDSCwwQ0FBMEM7Z0JBQzFDLElBQUksR0FBRyxDQUFDLFVBQVUsR0FBRyxHQUFHLElBQUksR0FBRyxDQUFDLFVBQVUsSUFBSSxHQUFHO29CQUFFLE9BQU87Z0JBQzFELDBEQUEwRDtnQkFDMUQsSUFBSSxrQkFBa0IsQ0FBQyxHQUFHLENBQUM7b0JBQUUsT0FBTztnQkFDcEMsK0RBQStEO2dCQUMvRCw2RUFBNkU7Z0JBQzdFLDJFQUEyRTtnQkFDM0Usd0VBQXdFO2dCQUN4RSw2RUFBNkU7Z0JBQzdFLCtEQUErRDtnQkFDL0QsRUFBRTtnQkFDRixxRUFBcUU7Z0JBQ3JFLDBFQUEwRTtnQkFDMUUsd0VBQXdFO2dCQUN4RSxxQ0FBcUM7Z0JBQ3JDLElBQUksQ0FBQyxHQUFHLENBQUMsSUFBSSxFQUFFLGNBQWM7b0JBQUUsT0FBTztnQkFDdEMsSUFBSSxLQUF5QixDQUFDO2dCQUM5QixJQUFJLENBQUM7b0JBQUMsS0FBSyxHQUFHLFVBQVUsQ0FBQyxHQUFHLENBQUMsQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDO2dCQUFDLENBQUM7Z0JBQUMsTUFBTSxDQUFDO29CQUFDLEtBQUssR0FBRyxHQUFHLENBQUMsSUFBSSxDQUFDLGNBQWMsQ0FBQztnQkFBQyxDQUFDO2dCQUMxRixJQUFJLENBQUMsS0FBSztvQkFBRSxPQUFPO2dCQUNuQix1RUFBdUU7Z0JBQ3ZFLHFFQUFxRTtnQkFDckUsTUFBTSxTQUFTLEdBQUcsa0JBQWtCLENBQUMsR0FBRyxDQUFDLENBQUM7Z0JBQzFDLElBQUksU0FBUyxLQUFLLFNBQVMsSUFBSSxDQUFDLFNBQVMsSUFBSSxTQUFTLEtBQUssVUFBVSxDQUFDO29CQUFFLE9BQU87Z0JBQy9FLHVDQUF1QztnQkFDdkMsSUFBSSxTQUFTLEtBQUssVUFBVSxJQUFJLGtCQUFrQixDQUFDLEdBQUcsQ0FBQyxNQUFNLEVBQUUsV0FBVyxDQUFDLEdBQUcsQ0FBQyxDQUFDO29CQUFFLE9BQU87Z0JBQ3pGLHVFQUF1RTtnQkFDdkUscUVBQXFFO2dCQUNyRSxjQUFjLENBQ1osWUFBWSxFQUNaLEtBQUssRUFDTCxtQkFBbUIsQ0FBQyxHQUFHLEVBQUUsU0FBUyxDQUFDLEVBQ25DLENBQUMsT0FBTyxFQUFFLElBQUksRUFBRSxFQUFFLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsSUFBK0IsQ0FBQyxFQUN4RSwyQkFBMkIsQ0FBQyxHQUFHLENBQUMsQ0FDakMsQ0FBQztZQUNKLENBQUM7WUFBQyxNQUFNLENBQUM7Z0JBQ1AsdUVBQXVFO2dCQUN2RSx3RUFBd0U7WUFDMUUsQ0FBQztRQUNILENBQUMsQ0FBQyxDQUFDO1FBQ0gsSUFBSSxFQUFFLENBQUM7SUFDVCxDQUFDLEVBQUUsRUFBRSxJQUFJLEVBQUUsT0FBTyxFQUFFLElBQUksRUFBRSxPQUFPLEVBQUUsU0FBUyxFQUFFLENBQUMsQ0FBQztBQUNsRCxDQUFDO0FBRUQ7Ozs7Ozs7Ozs7O0dBV0c7QUFDSCxNQUFNLFVBQVUsYUFBYSxDQUFDLFlBQTBCO0lBQ3RELE9BQU87UUFDTCxtQkFBbUIsQ0FBQyxZQUFZLEVBQUUsVUFBVSxDQUFtQjtRQUMvRCxrQkFBa0IsQ0FBQyxZQUFZLEVBQUUsVUFBVSxDQUFDO0tBQzdDLENBQUM7QUFDSixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQ29weXJpZ2h0IDIwMjYgUGlwZWxpbmUgQnVpbGRlciBDb250cmlidXRvcnNcbi8vIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBcGFjaGUtMi4wXG5cbmltcG9ydCB7IGNhbGxRdW90YUV4ZW1wdGlvbiwgaW5jcmVtZW50UXVvdGEsIGlzUXVvdGFFeGVtcHRSb3V0ZSwgY3JlYXRlTG9nZ2VyLCBtZXRlcmVkUXVvdGFUeXBlRm9yLCBxdW90YUF0dHJpYnV0aW9uRnJvbVJlcXVlc3QsIHRhZ1JvdXRlR2F0ZSB9IGZyb20gJ0BwaXBlbGluZS1idWlsZGVyL2FwaS1jb3JlJztcbmltcG9ydCB0eXBlIHsgUXVvdGFUeXBlLCBRdW90YVNlcnZpY2UgfSBmcm9tICdAcGlwZWxpbmUtYnVpbGRlci9hcGktY29yZSc7XG5pbXBvcnQgdHlwZSB7IFJlcXVlc3QsIFJlcXVlc3RIYW5kbGVyLCBSZXNwb25zZSwgTmV4dEZ1bmN0aW9uIH0gZnJvbSAnZXhwcmVzcyc7XG5pbXBvcnQgeyBkZWZlcnJlZENoZWNrUXVvdGEsIHJlcXVlc3RQYXRoIH0gZnJvbSAnLi9jaGVjay1xdW90YS5qcyc7XG5pbXBvcnQgeyBnZXRDb250ZXh0IH0gZnJvbSAnLi9nZXQtY29udGV4dC5qcyc7XG5pbXBvcnQgeyBpc0lkZW1wb3RlbnRSZXBsYXkgfSBmcm9tICcuL2lkZW1wb3RlbmN5LW1pZGRsZXdhcmUuanMnO1xuXG5jb25zdCBsb2dnZXIgPSBjcmVhdGVMb2dnZXIoJ21ldGVyLXF1b3RhJyk7XG5cbi8qKlxuICogTWlkZGxld2FyZSB0aGF0IE1FVEVSUyAoaW5jcmVtZW50cykgYSBxdW90YSBjb3VudGVyIG9uY2UgcGVyIFNVQ0NFU1NGVUxcbiAqIHJlcXVlc3QsIG9uIHJlc3BvbnNlIGBmaW5pc2hgLlxuICpcbiAqIFRoZSBjb21wbGVtZW50IHRvIHtAbGluayBjaGVja1F1b3RhfTogYGNoZWNrUXVvdGFgIG9ubHkgR0FURVMgKHJlYWRzIGN1cnJlbnRcbiAqIHVzYWdlIGFuZCA0MjlzIHdoZW4gb3Zlcikg4oCUIGl0IG5ldmVyIGluY3JlbWVudHMsIHNvIGEgc2VydmljZSB0aGF0IG1vdW50cyBpdFxuICogYnV0IG5ldmVyIGluY3JlbWVudHMgY2hlY2tzIGFnYWluc3QgYSBjb3VudGVyIGl0cyBvd24gdHJhZmZpYyBuZXZlciBtb3Zlcy5cbiAqIFRoaXMgaXMgVEhFIGFwaUNhbGxzIG1ldGVyaW5nIGNvbnZlbnRpb246IHB1dCBpdCBvbiBlYWNoIG1ldGVyZWQgcm91dGUgKG9yXG4gKiBtb3VudCBpdCBhaGVhZCBvZiBhIHNlcnZpY2UncyB3aG9sZSBzdXJmYWNlKSByYXRoZXIgdGhhbiBpbmNyZW1lbnRpbmcgYnkgaGFuZFxuICogaW4gaGFuZGxlcnMuXG4gKlxuICogRmlyZS1hbmQtZm9yZ2V0ICsgZmFpbC1zYWZlIGJ5IGNvbnN0cnVjdGlvbjpcbiAqIC0gcnVucyBpbiBhIGBmaW5pc2hgIGxpc3RlbmVyLCBzbyBpdCBuZXZlciBibG9ja3Mgb3IgZmFpbHMgdGhlIHJlc3BvbnNlO1xuICogLSBgaW5jcmVtZW50UXVvdGFgIEJVRkZFUlMgdGhlIHVuaXQgKGFwaS1jb3JlIHF1b3RhLWluY3JlbWVudC1iYXRjaGVyKTogdGhlXG4gKiAgIHBvZCBzZW5kcyBvbmUgbWV0ZXJlZCBpbmNyZW1lbnQgcGVyIChvcmcsIHR5cGUpIHBlciBmbHVzaCBpbnRlcnZhbCwgc28gdGhlXG4gKiAgIGNvdW50ZXIgbGFncyBieSBhdCBtb3N0IGBRVU9UQV9JTkNSRU1FTlRfRkxVU0hfTVNgLCBhbmQgYSB1bml0IHBhc3QgdGhlIGNhcFxuICogICBpcyByZWNvcmRlZCBhcyBgb3ZlcnNob290YCByYXRoZXIgdGhhbiBjb3VudGVkLiBFcnJvcnMgYXJlIHN3YWxsb3dlZCBhbmRcbiAqICAgY291bnRlZCAoYHF1b3RhX2luY3JlbWVudF9mYWlsdXJlc190b3RhbGApO1xuICogLSBvbmx5IDJ4eCByZXNwb25zZXMgYXJlIG1ldGVyZWQgKGEgcmVqZWN0ZWQvZXJyb3JlZCByZXF1ZXN0IGNvc3RzIG5vdGhpbmcpLlxuICogICBBIDMwNCBmcm9tIGFuIEVUYWcgbWF0Y2ggaXMgbm90IDJ4eCwgc28gcmV2YWxpZGF0aW5nIGFuIHVuY2hhbmdlZFxuICogICByZXNvdXJjZSBpcyBmcmVlOyBhIHJlc3BvbnNlIHRoYXQgbmV2ZXIgRklOSVNIRVMgKGNsaWVudCBhYm9ydGVkIGEgc3RyZWFtXG4gKiAgIG1pZC1mbGlnaHQsIHNvY2tldCBkZXN0cm95ZWQpIG5ldmVyIGVtaXRzIGBmaW5pc2hgIGFuZCBpcyBub3QgY291bnRlZDtcbiAqIC0gYSByZXNwb25zZSBSRVBMQVlFRCBmcm9tIHRoZSBpZGVtcG90ZW5jeSBjYWNoZSBpcyBza2lwcGVkIOKAlCB0aGUgb3JpZ2luYWxcbiAqICAgcmVxdWVzdCBhbHJlYWR5IHBhaWQsIGFuZCB0aGUgcmVwbGF5IGRpZCBubyB3b3JrLiBUaGlzIGhvbGRzIHdoZXRoZXIgdGhlXG4gKiAgIG1ldGVyIGlzIG1vdW50ZWQgYmVmb3JlIG9yIGFmdGVyIHRoZSBpZGVtcG90ZW5jeSBtaWRkbGV3YXJlOiB0aGUgZmxhZyBpc1xuICogICByZWFkIGF0IGBmaW5pc2hgLCBhZnRlciBib3RoIGhhdmUgcnVuO1xuICogLSBhIHJlcXVlc3Qgd2l0aCBubyBWRVJJRklFRCBvcmcgKGByZXEudXNlci5vcmdhbml6YXRpb25JZGAg4oCUIHNldCBieVxuICogICByZXF1aXJlQXV0aCwgbmV2ZXIgdGhlIHNwb29mYWJsZSBoZWFkZXIgaWRlbnRpdHkpIGlzIHNraXBwZWRcbiAqICAgKHVuYXV0aGVudGljYXRlZCAvIGhlYWx0aCAvIGVhcmx5LXRlcm1pbmF0ZWQpO1xuICogLSBTRVJWSUNFLVBSSU5DSVBBTCBjYWxsZXJzIGFyZSBza2lwcGVkOiBpbnRlcm5hbCBzZXJ2aWNlLXRvLXNlcnZpY2UgdHJhZmZpY1xuICogICAoZS5nLiBhIHBlZXIgY2FsbGluZyBjb21wbGlhbmNlIGB2YWxpZGF0ZWApIG11c3Qgbm90IGJ1cm4gYSB0ZW5hbnQncyBxdW90YSDigJRcbiAqICAgdGhlIG9yaWdpbmF0aW5nIHNlcnZpY2UgYWxyZWFkeSBtZXRlcnMgdGhlIHVzZXIgYWN0aW9uIHRoYXQgdHJpZ2dlcmVkIGl0LlxuICogICBBbiBPUkcgU0VSVklDRSBBQ0NPVU5UIChvciBhIHBlcnNvbmFsIGFjY2VzcyBrZXkpIGlzIG5vdCBhIHNlcnZpY2UgcHJpbmNpcGFsXG4gKiAgIGFuZCBJUyBtZXRlcmVkIOKAlCBvbiBgYXV0b21hdGlvbkNhbGxzYCBpbnN0ZWFkIG9mIGBhcGlDYWxsc2BcbiAqICAgKHtAbGluayBtZXRlcmVkUXVvdGFUeXBlRm9yfSk7XG4gKiAtIGZvciBgYXBpQ2FsbHNgLCBhbiBJTVBFUlNPTkFUSU9OIHNlc3Npb24gYW5kIGFuIE9OLUJFSEFMRiBob3AgKGEgdXNlciB0b2tlblxuICogICBmb3J3YXJkZWQgYnkgYXNrL3BpcGVsaW5lIHdpdGggYSBzaWduZWQgbWFya2VyKSBhcmUgc2tpcHBlZCB0b28g4oCUIHNlZVxuICogICBhcGktY29yZSBgY2FsbFF1b3RhRXhlbXB0aW9uYDtcbiAqIC0gYW4gYGFwaUNhbGxzYCByZXF1ZXN0IG9uIHRoZSBmbGVldC13aWRlIGBRVU9UQV9FWEVNUFRfUk9VVEVTYCAoY29uc29sZVxuICogICBwb2xsaW5nKSBpcyBza2lwcGVkLlxuICpcbiAqIEV2ZXJ5IGluY3JlbWVudCBjYXJyaWVzIHVzYWdlIGF0dHJpYnV0aW9uIChwcmluY2lwYWwsIGtleSwgcm91dGUgcGF0dGVybixcbiAqIHBpcGVsaW5lLCByZXF1ZXN0IGlkKSBmb3IgdGhlIHF1b3RhIHNlcnZpY2UncyB1c2FnZSBsZWRnZXIuXG4gKlxuICogTW91bnQgaXQgb25jZSBwZXIgcm91dGU6IGEgc2Vjb25kIG1ldGVyIGZvciB0aGUgc2FtZSBxdW90YSB0eXBlIG9uIHRoZSBzYW1lXG4gKiByZXF1ZXN0IGRvdWJsZS1jb3VudHMgKHRoZSByb3V0ZSB0YWJsZSByZWNvcmRzIGVhY2ggbWV0ZXIsIGFuZCB0aGUgcXVvdGFcbiAqIGNvdmVyYWdlIGNoZWNrIGZhaWxzIGEgcm91dGUgbWV0ZXJlZCB0d2ljZSkuXG4gKlxuICogQHBhcmFtIHF1b3RhU2VydmljZSAtIFF1b3RhIHNlcnZpY2UgY2xpZW50XG4gKiBAcGFyYW0gcXVvdGFUeXBlIC0gV2hpY2ggcXVvdGEgdG8gbWV0ZXIgKGUuZy4gJ2FwaUNhbGxzJyDigJQgc3BsaXQgcGVyIHJlcXVlc3RcbiAqICAgaW50byBhcGlDYWxscyAvIGF1dG9tYXRpb25DYWxscyBieSBwcmluY2lwYWwpXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBtZXRlclF1b3RhT25TdWNjZXNzKHF1b3RhU2VydmljZTogUXVvdGFTZXJ2aWNlLCBxdW90YVR5cGU6IFF1b3RhVHlwZSkge1xuICByZXR1cm4gdGFnUm91dGVHYXRlKChyZXE6IFJlcXVlc3QsIHJlczogUmVzcG9uc2UsIG5leHQ6IE5leHRGdW5jdGlvbik6IHZvaWQgPT4ge1xuICAgIHJlcy5vbignZmluaXNoJywgKCkgPT4ge1xuICAgICAgdHJ5IHtcbiAgICAgICAgLy8gT25seSBzdWNjZXNzZnVsIHJlc3BvbnNlcyBhcmUgYmlsbGFibGUuXG4gICAgICAgIGlmIChyZXMuc3RhdHVzQ29kZSA8IDIwMCB8fCByZXMuc3RhdHVzQ29kZSA+PSAzMDApIHJldHVybjtcbiAgICAgICAgLy8gQSBjYWNoZWQgcmVwbGF5IGRpZCBubyB3b3JrOyB0aGUgb3JpZ2luYWwgYWxyZWFkeSBwYWlkLlxuICAgICAgICBpZiAoaXNJZGVtcG90ZW50UmVwbGF5KHJlcykpIHJldHVybjtcbiAgICAgICAgLy8gUmVzb2x2ZSB0aGUgb3JnIGlkIGZyb20gdGhlIFNBTUUgc291cmNlIGBjaGVja1F1b3RhYCByZWFkcyDigJRcbiAgICAgICAgLy8gYGdldENvbnRleHQoKS5pZGVudGl0eS5vcmdJZGAsIHdoaWNoIGlzIG5vcm1hbGl6ZWQgKHRyaW1tZWQgKyBsb3dlcmNhc2VkKS5cbiAgICAgICAgLy8gTWV0ZXJpbmcgb2ZmIHRoZSByYXcgYHJlcS51c2VyLm9yZ2FuaXphdGlvbklkYCB3aGlsZSB0aGUgZ2F0ZSBjaGVja3MgdGhlXG4gICAgICAgIC8vIG5vcm1hbGl6ZWQgaWQgd291bGQgbGFuZCBpbmNyZW1lbnRzIG9uIGEgZGlmZmVyZW50IGtleSB0aGFuIHRoZSBjaGVja1xuICAgICAgICAvLyByZWFkcyAoYSBzaWxlbnQgYnlwYXNzIGlmIGFuIG9yZyBpZCBldmVyIGNhcnJpZXMgbWl4ZWQgY2FzZSkuIEZhbGwgYmFjayB0b1xuICAgICAgICAvLyB0aGUgcmF3IGF1dGggb3JnIG9ubHkgd2hlbiBjb250ZXh0IG1pZGRsZXdhcmUgaXNuJ3QgbW91bnRlZC5cbiAgICAgICAgLy9cbiAgICAgICAgLy8gT25seSBhIFZFUklGSUVEIGNhbGxlciBpcyBtZXRlcmVkLiBUaGUgaW5jcmVtZW50IGlzIHNlbnQgd2l0aCBUSElTXG4gICAgICAgIC8vIHNlcnZpY2UncyBjcmVkZW50aWFscywgc28gbWV0ZXJpbmcgYW4gb3JnIHRha2VuIGZyb20gdGhlIGhlYWRlci1kZXJpdmVkXG4gICAgICAgIC8vIGlkZW50aXR5IG9mIGFuIHVuYXV0aGVudGljYXRlZCByZXF1ZXN0IHdvdWxkIGxldCBhbnlvbmUgYnVybiBhIHZpY3RpbVxuICAgICAgICAvLyBvcmcncyBxdW90YSBieSBzZXR0aW5nIGB4LW9yZy1pZGAuXG4gICAgICAgIGlmICghcmVxLnVzZXI/Lm9yZ2FuaXphdGlvbklkKSByZXR1cm47XG4gICAgICAgIGxldCBvcmdJZDogc3RyaW5nIHwgdW5kZWZpbmVkO1xuICAgICAgICB0cnkgeyBvcmdJZCA9IGdldENvbnRleHQocmVxKS5pZGVudGl0eS5vcmdJZDsgfSBjYXRjaCB7IG9yZ0lkID0gcmVxLnVzZXIub3JnYW5pemF0aW9uSWQ7IH1cbiAgICAgICAgaWYgKCFvcmdJZCkgcmV0dXJuO1xuICAgICAgICAvLyBJbnRlcm5hbCBzZXJ2aWNlLXRvLXNlcnZpY2UgY2FsbHMgbXVzdCBub3QgY29uc3VtZSBhIHRlbmFudCdzIHF1b3RhO1xuICAgICAgICAvLyBub3IsIG9uIHRoZSBjYWxsIGJ1ZGdldCwgaW1wZXJzb25hdGlvbiBzZXNzaW9ucyBvciBvbi1iZWhhbGYgaG9wcy5cbiAgICAgICAgY29uc3QgZXhlbXB0aW9uID0gY2FsbFF1b3RhRXhlbXB0aW9uKHJlcSk7XG4gICAgICAgIGlmIChleGVtcHRpb24gPT09ICdzZXJ2aWNlJyB8fCAoZXhlbXB0aW9uICYmIHF1b3RhVHlwZSA9PT0gJ2FwaUNhbGxzJykpIHJldHVybjtcbiAgICAgICAgLy8gQ29uc29sZSBwb2xsaW5nIG5ldmVyIHNwZW5kcyBhIGNhbGwuXG4gICAgICAgIGlmIChxdW90YVR5cGUgPT09ICdhcGlDYWxscycgJiYgaXNRdW90YUV4ZW1wdFJvdXRlKHJlcS5tZXRob2QsIHJlcXVlc3RQYXRoKHJlcSkpKSByZXR1cm47XG4gICAgICAgIC8vIGluY3JlbWVudFF1b3RhIGF1dGhlbnRpY2F0ZXMgYXMgVEhJUyBzZXJ2aWNlICh0aGUgaW5jcmVtZW50IGVuZHBvaW50XG4gICAgICAgIC8vIGlzIHNlcnZpY2UtcHJpbmNpcGFsIG9ubHkg4oCUIGEgZm9yd2FyZGVkIHVzZXIgdG9rZW4gaXMgYWx3YXlzIDQwMykuXG4gICAgICAgIGluY3JlbWVudFF1b3RhKFxuICAgICAgICAgIHF1b3RhU2VydmljZSxcbiAgICAgICAgICBvcmdJZCxcbiAgICAgICAgICBtZXRlcmVkUXVvdGFUeXBlRm9yKHJlcSwgcXVvdGFUeXBlKSxcbiAgICAgICAgICAobWVzc2FnZSwgZGF0YSkgPT4gbG9nZ2VyLndhcm4obWVzc2FnZSwgZGF0YSBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiksXG4gICAgICAgICAgcXVvdGFBdHRyaWJ1dGlvbkZyb21SZXF1ZXN0KHJlcSksXG4gICAgICAgICk7XG4gICAgICB9IGNhdGNoIHtcbiAgICAgICAgLy8gTWV0ZXJpbmcgbXVzdCBuZXZlciBhZmZlY3QgdGhlIHJlc3BvbnNlOyBhIG1pc3NpbmcgdXNlci9jb250ZXh0IGp1c3RcbiAgICAgICAgLy8gbWVhbnMgYW4gdW5hdXRoZW50aWNhdGVkIG9yIGVhcmx5LXRlcm1pbmF0ZWQgcmVxdWVzdCDigJQgc2tpcCBzaWxlbnRseS5cbiAgICAgIH1cbiAgICB9KTtcbiAgICBuZXh0KCk7XG4gIH0sIHsga2luZDogJ3F1b3RhJywgbW9kZTogJ21ldGVyJywgcXVvdGFUeXBlIH0pO1xufVxuXG4vKipcbiAqIFRIRSBhcGlDYWxscyBjb252ZW50aW9uIGZvciBhIHNlcnZpY2UncyB1c2VyIHN1cmZhY2U6IG1ldGVyIG9uY2UgcGVyIDJ4eCBBTkRcbiAqIGdhdGUgYWZ0ZXIgYXV0aGVudGljYXRpb24sIG1vdW50ZWQgT05DRSBhdCB0aGUgYXBwLXJvdXRlcyBsZXZlbCBhaGVhZCBvZiB0aGVcbiAqIHJvdXRlcnMgaXQgY292ZXJzIOKAlCBgYXBwLnVzZSgnL3RoaW5ncycsIC4uLmFwaUNhbGxzUXVvdGEocXVvdGFTZXJ2aWNlKSlgLlxuICpcbiAqIFRoZSBjaGVjayBpcyBERUZFUlJFRCB0byBgcmVxdWlyZUF1dGhgICh7QGxpbmsgZGVmZXJyZWRDaGVja1F1b3RhfSksIHNvIHRoZVxuICogbW91bnQgY2FuIHByZWNlZGUgcm91dGVycyB0aGF0IGF1dGhlbnRpY2F0ZSBwZXIgcm91dGUuIEJvdGggaGFsdmVzIHNraXBcbiAqIHNlcnZpY2UgcHJpbmNpcGFscywgdW5hdXRoZW50aWNhdGVkIHJlcXVlc3RzIGFuZCB0aGUgY29uc29sZS1wb2xsaW5nXG4gKiBgUVVPVEFfRVhFTVBUX1JPVVRFU2A7IGEgc2VydmljZSBhY2NvdW50IHNwZW5kcyBgYXV0b21hdGlvbkNhbGxzYC4gQSByb3V0ZVxuICogdW5kZXIgc3VjaCBhIHByZWZpeCBtdXN0IE5PVCBhbHNvIG1vdW50IGl0cyBvd24gYG1ldGVyUXVvdGFPblN1Y2Nlc3NgIGZvclxuICogYXBpQ2FsbHMgKHRoYXQgYmlsbHMgdHdpY2Ug4oCUIHRoZSBxdW90YSBjb3ZlcmFnZSBjaGVjayBmYWlscyBpdCkuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBhcGlDYWxsc1F1b3RhKHF1b3RhU2VydmljZTogUXVvdGFTZXJ2aWNlKTogUmVxdWVzdEhhbmRsZXJbXSB7XG4gIHJldHVybiBbXG4gICAgbWV0ZXJRdW90YU9uU3VjY2VzcyhxdW90YVNlcnZpY2UsICdhcGlDYWxscycpIGFzIFJlcXVlc3RIYW5kbGVyLFxuICAgIGRlZmVycmVkQ2hlY2tRdW90YShxdW90YVNlcnZpY2UsICdhcGlDYWxscycpLFxuICBdO1xufVxuIl19
@@ -24,6 +24,7 @@ export interface MetricHelpers {
24
24
  incCounter(name: string, labels?: Record<string, string>, value?: number): void;
25
25
  observe(name: string, labels: Record<string, string>, value: number): void;
26
26
  setGauge(name: string, labels: Record<string, string>, value: number): void;
27
+ resetGauge(name: string): void;
27
28
  }
28
29
  /**
29
30
  * Build `incCounter` / `observe` / `setGauge` over a caller-supplied registry.
@@ -84,3 +85,11 @@ export declare function observe(name: string, labels: Record<string, string>, va
84
85
  * ```
85
86
  */
86
87
  export declare function setGauge(name: string, labels: Record<string, string>, value: number): void;
88
+ /**
89
+ * Drop EVERY series of a business gauge. For a gauge that describes a SET — one
90
+ * series per configured entry — and is re-published whole: without the reset, a
91
+ * series for an entry that has since been deleted keeps its last value forever,
92
+ * and an alert on it keeps firing for something that no longer exists. Call it
93
+ * immediately before re-setting the current set. A gauge never set is a no-op.
94
+ */
95
+ export declare function resetGauge(name: string): void;