@pipeline-builder/api-core 4.1.3 → 4.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. package/README.md +3 -3
  2. package/lib/errors/app-errors.d.ts +0 -4
  3. package/lib/errors/app-errors.js +1 -8
  4. package/lib/helpers/restore-helpers.d.ts +3 -3
  5. package/lib/helpers/restore-helpers.js +4 -4
  6. package/lib/helpers/sse-helpers.d.ts +8 -1
  7. package/lib/helpers/sse-helpers.js +11 -3
  8. package/lib/middleware/auth.d.ts +174 -43
  9. package/lib/middleware/auth.js +384 -179
  10. package/lib/middleware/index.d.ts +1 -0
  11. package/lib/middleware/index.js +2 -1
  12. package/lib/middleware/route-table.d.ts +104 -0
  13. package/lib/middleware/route-table.js +230 -0
  14. package/lib/middleware/step-up.d.ts +48 -16
  15. package/lib/middleware/step-up.js +74 -36
  16. package/lib/services/api-key-exchange.d.ts +25 -0
  17. package/lib/services/api-key-exchange.js +219 -0
  18. package/lib/services/cache-service.d.ts +11 -26
  19. package/lib/services/cache-service.js +20 -74
  20. package/lib/services/compliance-event-subscriber.d.ts +5 -4
  21. package/lib/services/compliance-event-subscriber.js +8 -6
  22. package/lib/services/durable-event-bus.d.ts +22 -39
  23. package/lib/services/durable-event-bus.js +95 -43
  24. package/lib/services/env-redis.d.ts +27 -0
  25. package/lib/services/env-redis.js +63 -1
  26. package/lib/services/http-client.d.ts +10 -15
  27. package/lib/services/http-client.js +32 -27
  28. package/lib/services/index.d.ts +3 -0
  29. package/lib/services/index.js +4 -1
  30. package/lib/services/jwks-cache.d.ts +102 -0
  31. package/lib/services/jwks-cache.js +222 -0
  32. package/lib/services/quota.js +12 -4
  33. package/lib/services/remote-audit-client.d.ts +1 -1
  34. package/lib/services/remote-audit-client.js +32 -1
  35. package/lib/services/scheduler.d.ts +2 -3
  36. package/lib/services/scheduler.js +2 -2
  37. package/lib/services/service-boot.d.ts +4 -2
  38. package/lib/services/service-boot.js +7 -3
  39. package/lib/services/service-keys.d.ts +83 -0
  40. package/lib/services/service-keys.js +354 -0
  41. package/lib/services/sse-ticket-store.d.ts +55 -22
  42. package/lib/services/sse-ticket-store.js +122 -79
  43. package/lib/services/token-revocation.js +30 -18
  44. package/lib/testing/route-coverage.d.ts +64 -0
  45. package/lib/testing/route-coverage.js +183 -0
  46. package/lib/testing/service-tokens.d.ts +66 -0
  47. package/lib/testing/service-tokens.js +137 -0
  48. package/lib/testing/tier-mock.d.ts +2 -2
  49. package/lib/testing/tier-mock.js +3 -3
  50. package/lib/testing/user-tokens.d.ts +75 -0
  51. package/lib/testing/user-tokens.js +115 -0
  52. package/lib/types/catalog-metadata.d.ts +0 -2
  53. package/lib/types/catalog-metadata.js +1 -3
  54. package/lib/types/common.d.ts +103 -4
  55. package/lib/types/common.js +11 -1
  56. package/lib/types/error-codes.d.ts +15 -0
  57. package/lib/types/error-codes.js +22 -1
  58. package/lib/types/permissions.d.ts +35 -1
  59. package/lib/types/permissions.js +72 -2
  60. package/lib/utils/api-key.d.ts +34 -0
  61. package/lib/utils/api-key.js +75 -0
  62. package/lib/utils/env.d.ts +0 -2
  63. package/lib/utils/env.js +1 -6
  64. package/lib/utils/index.d.ts +4 -0
  65. package/lib/utils/index.js +5 -1
  66. package/lib/utils/jwk.d.ts +98 -0
  67. package/lib/utils/jwk.js +139 -0
  68. package/lib/utils/logger.d.ts +30 -1
  69. package/lib/utils/logger.js +74 -27
  70. package/lib/utils/secret-encryption.d.ts +7 -2
  71. package/lib/utils/secret-encryption.js +47 -4
  72. package/lib/utils/secret-rotation.d.ts +17 -0
  73. package/lib/utils/secret-rotation.js +54 -0
  74. package/lib/utils/sensitive-patterns.d.ts +49 -0
  75. package/lib/utils/sensitive-patterns.js +149 -0
  76. package/lib/validation/common-schemas.js +5 -4
  77. package/package.json +20 -1
@@ -1,37 +1,16 @@
1
- /**
2
- * Durable, at-least-once event backbone (Redis Streams).
3
- *
4
- * The platform's cross-service signalling today is point-to-point HTTP plus
5
- * polling reconcilers plus an IN-PROCESS best-effort emitter ({@link entityEvents}).
6
- * There is no durable bus, so a signal produced on one pod is either delivered
7
- * synchronously over HTTP (coupling + retry-storm risk) or lost if the consumer
8
- * is momentarily down (the reconcilers exist to paper over exactly that).
9
- *
10
- * This is that missing bus, as a reusable primitive:
11
- * - **publish(topic, payload)** → `XADD` onto a bounded (`MAXLEN ~`) per-topic
12
- * stream. Durable across restarts, shared by all replicas.
13
- * - **subscribe({topic, group, consumer, handler})** → a `XREADGROUP` consumer.
14
- * Consumer GROUPS give at-least-once: each group gets every message once, a
15
- * message stays pending until the handler `XACK`s it, and `XAUTOCLAIM`
16
- * reclaims messages stranded by a crashed consumer. Multiple groups on one
17
- * topic = independent fan-out (e.g. quota-sync AND audit both react).
18
- *
19
- * FAIL-SAFE + OPT-IN, exactly like the audit spool: {@link createEnvRedisDurableEventBus}
20
- * returns `null` when Redis isn't configured, so a service without it simply
21
- * doesn't use the bus (keeps today's behavior). A publish failure is dropped-with-
22
- * -metric, never thrown; a handler throw leaves the message un-acked for redelivery.
23
- *
24
- * Migrating a specific reconciler (e.g. billing→quota entitlement sync) onto this
25
- * is deliberately follow-on work — this lands the backbone + an additive entity-
26
- * event bridge; the reconcilers stay as the belt-and-suspenders backstop until a
27
- * flow is fully cut over.
28
- */
29
- import type { EntityEventSubscriber } from './entity-events.js';
30
- /** A delivered event: its stream id, topic, and decoded payload. */
1
+ /** A delivered event: its stream id, topic, publish time, and decoded payload. */
31
2
  export interface EventEnvelope<T = unknown> {
32
3
  /** Redis Stream entry id (`<ms>-<seq>`) — also the idempotency handle. */
33
4
  id: string;
34
5
  topic: string;
6
+ /**
7
+ * When the event was published (the Redis server time embedded in the stream
8
+ * id). A redelivery keeps its ORIGINAL publish time, so a consumer applying
9
+ * last-writer-wins state (e.g. an entitlement sync) can order events by it
10
+ * instead of by delivery time and refuse to let a stale retry overwrite a
11
+ * newer state.
12
+ */
13
+ publishedAt: Date;
35
14
  payload: T;
36
15
  }
37
16
  export interface SubscribeOptions<T = unknown> {
@@ -49,6 +28,11 @@ export interface SubscribeOptions<T = unknown> {
49
28
  blockMs?: number;
50
29
  /** A pending message idle this long (ms) is reclaimed from a dead consumer (default 60000). */
51
30
  minIdleMs?: number;
31
+ /**
32
+ * Deliveries after which an un-acked message is dead-lettered to
33
+ * `evt:<topic>:dlq` and acked instead of being redelivered again (default 10).
34
+ */
35
+ maxDeliveries?: number;
52
36
  }
53
37
  export interface EventSubscription {
54
38
  /** Stop the consumer loop. Resolves once the in-flight read returns. */
@@ -71,7 +55,15 @@ export interface RedisStreamClient {
71
55
  xreadgroup(...args: (string | number)[]): Promise<unknown>;
72
56
  xack(key: string, group: string, ...ids: string[]): Promise<number>;
73
57
  xautoclaim(...args: (string | number)[]): Promise<unknown>;
58
+ xpending(key: string, group: string, ...args: (string | number)[]): Promise<unknown>;
59
+ xrange(key: string, start: string, end: string, ...args: (string | number)[]): Promise<unknown>;
60
+ /** A new connection with the same options — each subscriber reads on its own. */
61
+ duplicate(): RedisStreamClient;
62
+ quit?(): Promise<unknown>;
63
+ on?(event: 'error', cb: (err: unknown) => void): unknown;
74
64
  }
65
+ /** Dead-letter stream for a topic. */
66
+ export declare function deadLetterStreamKey(topic: string): string;
75
67
  /** Build a durable event bus over a Redis Streams client. */
76
68
  export declare function createRedisDurableEventBus(redis: RedisStreamClient, opts?: {
77
69
  maxLen?: number;
@@ -85,12 +77,3 @@ export declare function createRedisDurableEventBus(redis: RedisStreamClient, opt
85
77
  export declare function createEnvRedisDurableEventBus(opts?: {
86
78
  maxLen?: number;
87
79
  }): DurableEventBus | null;
88
- /** Topic the entity-event bridge publishes to. */
89
- export declare const ENTITY_EVENT_TOPIC = "entity-events";
90
- /**
91
- * An {@link EntityEventSubscriber} that forwards each entity event to the durable
92
- * bus. `bus.publish` is fail-safe (drops-with-metric, never throws), matching the
93
- * emitter's fire-and-forget contract. Note `EntityEvent.timestamp` (a Date)
94
- * serializes to an ISO string on the wire — a consumer re-hydrates as needed.
95
- */
96
- export declare function createEntityEventBusPublisher(bus: DurableEventBus): EntityEventSubscriber;
@@ -1,5 +1,32 @@
1
1
  // Copyright 2026 Pipeline Builder Contributors
2
2
  // SPDX-License-Identifier: Apache-2.0
3
+ /**
4
+ * Durable, at-least-once event backbone (Redis Streams).
5
+ *
6
+ * The platform's cross-service signalling today is point-to-point HTTP plus
7
+ * polling reconcilers plus an IN-PROCESS best-effort emitter ({@link entityEvents}).
8
+ * There is no durable bus, so a signal produced on one pod is either delivered
9
+ * synchronously over HTTP (coupling + retry-storm risk) or lost if the consumer
10
+ * is momentarily down (the reconcilers exist to paper over exactly that).
11
+ *
12
+ * This is that missing bus, as a reusable primitive:
13
+ * - **publish(topic, payload)** → `XADD` onto a bounded (`MAXLEN ~`) per-topic
14
+ * stream. Durable across restarts, shared by all replicas.
15
+ * - **subscribe({topic, group, consumer, handler})** → a `XREADGROUP` consumer
16
+ * on its OWN connection (`duplicate()`), so a blocking read never delays a
17
+ * publish. Consumer GROUPS give at-least-once: each group gets every message
18
+ * once, a message stays pending until the handler `XACK`s it, and `XAUTOCLAIM`
19
+ * reclaims messages stranded by a crashed consumer. A message that has been
20
+ * delivered `maxDeliveries` times without an ack is moved to a dead-letter
21
+ * stream (`evt:<topic>:dlq`) and acked, so a poison message can't redeliver
22
+ * forever. Multiple groups on one topic = independent fan-out.
23
+ *
24
+ * FAIL-SAFE + OPT-IN, exactly like the audit spool: {@link createEnvRedisDurableEventBus}
25
+ * returns `null` when Redis isn't configured, so a service without it simply
26
+ * doesn't use the bus (keeps today's behavior). A publish failure is dropped-with-
27
+ * -metric, never thrown; a handler throw leaves the message un-acked for redelivery.
28
+ *
29
+ */
3
30
  import { createEnvRedisClient } from './env-redis.js';
4
31
  import { createLogger } from '../utils/logger.js';
5
32
  import { emitCounter } from '../utils/metric-emitter.js';
@@ -8,12 +35,22 @@ const DEFAULT_MAXLEN = 10_000;
8
35
  const DEFAULT_BATCH = 16;
9
36
  const DEFAULT_BLOCK_MS = 5_000;
10
37
  const DEFAULT_MIN_IDLE_MS = 60_000;
38
+ const DEFAULT_MAX_DELIVERIES = 10;
11
39
  function errMsg(err) {
12
40
  return err instanceof Error ? err.message : String(err);
13
41
  }
14
42
  function streamKey(topic) {
15
43
  return `evt:${topic}`;
16
44
  }
45
+ /** Dead-letter stream for a topic. */
46
+ export function deadLetterStreamKey(topic) {
47
+ return `evt:${topic}:dlq`;
48
+ }
49
+ /** Publish time from a stream id (`<ms>-<seq>`); epoch 0 for an unparseable id. */
50
+ function publishedAtFromId(id) {
51
+ const ms = Number(id.split('-')[0]);
52
+ return new Date(Number.isFinite(ms) ? ms : 0);
53
+ }
17
54
  /** True when the error is Redis' "group already exists" (idempotent create). */
18
55
  function isBusyGroup(err) {
19
56
  return errMsg(err).includes('BUSYGROUP');
@@ -46,15 +83,16 @@ function parseEntries(topic, entries) {
46
83
  // A missing `d` field (an entry not written by publish()) OR a corrupt JSON
47
84
  // payload both yield an undefined-payload envelope so `deliver()` ACKs it —
48
85
  // a poison message must never wedge the group by staying perpetually pending.
86
+ const publishedAt = publishedAtFromId(id);
49
87
  if (raw === undefined) {
50
- out.push({ id, topic, payload: undefined });
88
+ out.push({ id, topic, publishedAt, payload: undefined });
51
89
  continue;
52
90
  }
53
91
  try {
54
- out.push({ id, topic, payload: JSON.parse(raw) });
92
+ out.push({ id, topic, publishedAt, payload: JSON.parse(raw) });
55
93
  }
56
94
  catch {
57
- out.push({ id, topic, payload: undefined });
95
+ out.push({ id, topic, publishedAt, payload: undefined });
58
96
  }
59
97
  }
60
98
  return out;
@@ -80,11 +118,18 @@ export function createRedisDurableEventBus(redis, opts = {}) {
80
118
  subscribe(subOpts) {
81
119
  const { topic, group, consumer, handler } = subOpts;
82
120
  const key = streamKey(topic);
121
+ const dlqKey = deadLetterStreamKey(topic);
83
122
  const batch = Math.max(1, subOpts.batchSize ?? DEFAULT_BATCH);
84
123
  const blockMs = Math.max(0, subOpts.blockMs ?? DEFAULT_BLOCK_MS);
85
124
  const minIdle = Math.max(0, subOpts.minIdleMs ?? DEFAULT_MIN_IDLE_MS);
125
+ const maxDeliveries = Math.max(1, subOpts.maxDeliveries ?? DEFAULT_MAX_DELIVERIES);
126
+ // `XREADGROUP BLOCK` holds its connection for up to `blockMs`; on the
127
+ // shared client every publish queued behind it. Read on a dedicated one.
128
+ const reader = redis.duplicate();
129
+ // A duplicated ioredis connection doesn't inherit listeners; without one a
130
+ // connection error is an unhandled 'error' event that crashes the process.
131
+ reader.on?.('error', (err) => logger.warn('Event bus reader connection error', { topic, group, error: errMsg(err) }));
86
132
  let stopped = false;
87
- let started = false;
88
133
  const deliver = async (envs) => {
89
134
  for (const env of envs) {
90
135
  try {
@@ -92,7 +137,7 @@ export function createRedisDurableEventBus(redis, opts = {}) {
92
137
  await handler(env);
93
138
  // Ack on success OR on an undefined (corrupt) payload — a poison
94
139
  // message must not block the group forever.
95
- await redis.xack(key, group, env.id);
140
+ await reader.xack(key, group, env.id);
96
141
  emitCounter('event_bus_delivered_total', { topic, group });
97
142
  }
98
143
  catch (err) {
@@ -104,6 +149,41 @@ export function createRedisDurableEventBus(redis, opts = {}) {
104
149
  }
105
150
  }
106
151
  };
152
+ /**
153
+ * Move every idle pending message that has already been delivered
154
+ * `maxDeliveries` times to the dead-letter stream and ack it. The entry
155
+ * keeps its payload plus where it came from, so an operator can inspect or
156
+ * replay it. If copying fails the message is left pending (retried next
157
+ * pass) — it is never acked without being preserved.
158
+ */
159
+ const deadLetterExhausted = async () => {
160
+ const pending = await reader.xpending(key, group, 'IDLE', minIdle, '-', '+', batch);
161
+ if (!Array.isArray(pending))
162
+ return;
163
+ for (const p of pending) {
164
+ if (!Array.isArray(p) || p.length < 4)
165
+ continue;
166
+ const id = String(p[0]);
167
+ const deliveries = Number(p[3]);
168
+ if (!(deliveries >= maxDeliveries))
169
+ continue;
170
+ const entries = await reader.xrange(key, id, id);
171
+ const fields = Array.isArray(entries) && Array.isArray(entries[0]) && Array.isArray(entries[0][1]) ? entries[0][1] : [];
172
+ let raw = '';
173
+ for (let i = 0; i + 1 < fields.length; i += 2) {
174
+ if (String(fields[i]) === 'd') {
175
+ raw = String(fields[i + 1]);
176
+ break;
177
+ }
178
+ }
179
+ await reader.xadd(dlqKey, 'MAXLEN', '~', maxLen, '*', 'd', raw, 'sourceId', id, 'group', group, 'deliveries', deliveries);
180
+ await reader.xack(key, group, id);
181
+ emitCounter('event_bus_dead_lettered_total', { topic, group });
182
+ logger.error('Event exceeded max deliveries; moved to dead-letter stream', {
183
+ topic, group, id, deliveries, deadLetterStream: dlqKey,
184
+ });
185
+ }
186
+ };
107
187
  // The consumer group must exist before XREADGROUP can succeed. Creating it
108
188
  // is retried inside the loop: at startup the client may not have connected
109
189
  // yet, and a single failed attempt used to leave the consumer reading a
@@ -112,7 +192,7 @@ export function createRedisDurableEventBus(redis, opts = {}) {
112
192
  const ensureGroup = async () => {
113
193
  try {
114
194
  // MKSTREAM so the stream need not exist yet; '$' = only new messages.
115
- await redis.xgroup('CREATE', key, group, '$', 'MKSTREAM');
195
+ await reader.xgroup('CREATE', key, group, '$', 'MKSTREAM');
116
196
  groupReady = true;
117
197
  }
118
198
  catch (err) {
@@ -126,8 +206,10 @@ export function createRedisDurableEventBus(redis, opts = {}) {
126
206
  try {
127
207
  if (!groupReady)
128
208
  await ensureGroup();
129
- // 1) Reclaim messages stranded by a crashed consumer in this group.
130
- const claimed = await redis.xautoclaim(key, group, consumer, minIdle, '0', 'COUNT', batch);
209
+ // 1) Dead-letter messages that have exhausted their deliveries, then
210
+ // reclaim the rest stranded by a failed/crashed consumer.
211
+ await deadLetterExhausted();
212
+ const claimed = await reader.xautoclaim(key, group, consumer, minIdle, '0', 'COUNT', batch);
131
213
  // XAUTOCLAIM reply: [nextCursor, entries, deletedIds]
132
214
  if (Array.isArray(claimed) && claimed.length >= 2) {
133
215
  await deliver(parseEntries(topic, claimed[1]));
@@ -135,7 +217,7 @@ export function createRedisDurableEventBus(redis, opts = {}) {
135
217
  if (stopped)
136
218
  break;
137
219
  // 2) Read new, never-delivered messages for this group ('>').
138
- const res = await redis.xreadgroup('GROUP', group, consumer, 'COUNT', batch, 'BLOCK', blockMs, 'STREAMS', key, '>');
220
+ const res = await reader.xreadgroup('GROUP', group, consumer, 'COUNT', batch, 'BLOCK', blockMs, 'STREAMS', key, '>');
139
221
  // XREADGROUP reply: [[streamKey, entries]] | null (on block timeout)
140
222
  if (Array.isArray(res) && res.length > 0 && Array.isArray(res[0]) && res[0].length >= 2) {
141
223
  await deliver(parseEntries(topic, res[0][1]));
@@ -153,12 +235,8 @@ export function createRedisDurableEventBus(redis, opts = {}) {
153
235
  }
154
236
  }
155
237
  };
156
- let loopPromise = Promise.resolve();
157
- if (!started) {
158
- started = true;
159
- loopPromise = loop();
160
- logger.info('Event bus consumer started', { topic, group, consumer });
161
- }
238
+ const loopPromise = loop();
239
+ logger.info('Event bus consumer started', { topic, group, consumer, maxDeliveries });
162
240
  return {
163
241
  async stop() {
164
242
  stopped = true;
@@ -166,6 +244,7 @@ export function createRedisDurableEventBus(redis, opts = {}) {
166
244
  // down its DB) doesn't race a message still being processed. Bounded by
167
245
  // the XREADGROUP BLOCK window. Never rejects — the loop swallows errors.
168
246
  await loopPromise.catch(() => undefined);
247
+ await Promise.resolve(reader.quit?.()).catch(() => undefined);
169
248
  },
170
249
  };
171
250
  },
@@ -184,31 +263,4 @@ export function createEnvRedisDurableEventBus(opts = {}) {
184
263
  logger.info('Redis durable event bus initialized');
185
264
  return createRedisDurableEventBus(inst, opts);
186
265
  }
187
- // ---------------------------------------------------------------------------
188
- // Entity-event bridge (additive, opt-in)
189
- //
190
- // Lets a service give its in-process {@link entityEvents} emitter a DURABLE,
191
- // cross-pod delivery leg WITHOUT changing existing behavior: register the
192
- // returned subscriber and every entity mutation is ALSO published to the bus.
193
- // A consumer elsewhere (`bus.subscribe`) then reacts at-least-once across pods
194
- // and restarts. The in-process subscribers keep firing exactly as before, so
195
- // this is purely additive — no double-processing unless a service intentionally
196
- // runs a bus consumer for the same reaction. Kept here (not in entity-events.ts)
197
- // so that module stays infrastructure-free per its own contract.
198
- // ---------------------------------------------------------------------------
199
- /** Topic the entity-event bridge publishes to. */
200
- export const ENTITY_EVENT_TOPIC = 'entity-events';
201
- /**
202
- * An {@link EntityEventSubscriber} that forwards each entity event to the durable
203
- * bus. `bus.publish` is fail-safe (drops-with-metric, never throws), matching the
204
- * emitter's fire-and-forget contract. Note `EntityEvent.timestamp` (a Date)
205
- * serializes to an ISO string on the wire — a consumer re-hydrates as needed.
206
- */
207
- export function createEntityEventBusPublisher(bus) {
208
- return {
209
- async onEntityEvent(event) {
210
- await bus.publish(ENTITY_EVENT_TOPIC, event);
211
- },
212
- };
213
- }
214
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZHVyYWJsZS1ldmVudC1idXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvc2VydmljZXMvZHVyYWJsZS1ldmVudC1idXMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsK0NBQStDO0FBQy9DLHNDQUFzQztBQWdDdEMsT0FBTyxFQUFFLG9CQUFvQixFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDdEQsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBQ2xELE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQUV6RCxNQUFNLE1BQU0sR0FBRyxZQUFZLENBQUMsbUJBQW1CLENBQUMsQ0FBQztBQW9EakQsTUFBTSxjQUFjLEdBQUcsTUFBTSxDQUFDO0FBQzlCLE1BQU0sYUFBYSxHQUFHLEVBQUUsQ0FBQztBQUN6QixNQUFNLGdCQUFnQixHQUFHLEtBQUssQ0FBQztBQUMvQixNQUFNLG1CQUFtQixHQUFHLE1BQU0sQ0FBQztBQUVuQyxTQUFTLE1BQU0sQ0FBQyxHQUFZO0lBQzFCLE9BQU8sR0FBRyxZQUFZLEtBQUssQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDO0FBQzFELENBQUM7QUFFRCxTQUFTLFNBQVMsQ0FBQyxLQUFhO0lBQzlCLE9BQU8sT0FBTyxLQUFLLEVBQUUsQ0FBQztBQUN4QixDQUFDO0FBRUQsZ0ZBQWdGO0FBQ2hGLFNBQVMsV0FBVyxDQUFDLEdBQVk7SUFDL0IsT0FBTyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsUUFBUSxDQUFDLFdBQVcsQ0FBQyxDQUFDO0FBQzNDLENBQUM7QUFFRDs7Ozs7R0FLRztBQUNILFNBQVMsWUFBWSxDQUFJLEtBQWEsRUFBRSxPQUFnQjtJQUN0RCxNQUFNLEdBQUcsR0FBdUIsRUFBRSxDQUFDO0lBQ25DLElBQUksQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLE9B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QUFFO0FBQ0YsNkVBQTZFO0FBQzdFLDBFQUEwRTtBQUMxRSw4RUFBOEU7QUFDOUUsK0VBQStFO0FBQy9FLDZFQUE2RTtBQUM3RSxnRkFBZ0Y7QUFDaEYsaUZBQWlGO0FBQ2pGLGlFQUFpRTtBQUNqRSw4RUFBOEU7QUFFOUUsa0RBQWtEO0FBQ2xELE1BQU0sQ0FBQyxNQUFNLGtCQUFrQixHQUFHLGVBQWUsQ0FBQztBQUVsRDs7Ozs7R0FLRztBQUNILE1BQU0sVUFBVSw2QkFBNkIsQ0FBQyxHQUFvQjtJQUNoRSxPQUFPO1FBQ0wsS0FBSyxDQUFDLGFBQWEsQ0FBQyxLQUFrQjtZQUNwQyxNQUFNLEdBQUcsQ0FBQyxPQUFPLENBQUMsa0JBQWtCLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFDL0MsQ0FBQztLQUNGLENBQUM7QUFDSixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQ29weXJpZ2h0IDIwMjYgUGlwZWxpbmUgQnVpbGRlciBDb250cmlidXRvcnNcbi8vIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBcGFjaGUtMi4wXG5cbi8qKlxuICogRHVyYWJsZSwgYXQtbGVhc3Qtb25jZSBldmVudCBiYWNrYm9uZSAoUmVkaXMgU3RyZWFtcykuXG4gKlxuICogVGhlIHBsYXRmb3JtJ3MgY3Jvc3Mtc2VydmljZSBzaWduYWxsaW5nIHRvZGF5IGlzIHBvaW50LXRvLXBvaW50IEhUVFAgcGx1c1xuICogcG9sbGluZyByZWNvbmNpbGVycyBwbHVzIGFuIElOLVBST0NFU1MgYmVzdC1lZmZvcnQgZW1pdHRlciAoe0BsaW5rIGVudGl0eUV2ZW50c30pLlxuICogVGhlcmUgaXMgbm8gZHVyYWJsZSBidXMsIHNvIGEgc2lnbmFsIHByb2R1Y2VkIG9uIG9uZSBwb2QgaXMgZWl0aGVyIGRlbGl2ZXJlZFxuICogc3luY2hyb25vdXNseSBvdmVyIEhUVFAgKGNvdXBsaW5nICsgcmV0cnktc3Rvcm0gcmlzaykgb3IgbG9zdCBpZiB0aGUgY29uc3VtZXJcbiAqIGlzIG1vbWVudGFyaWx5IGRvd24gKHRoZSByZWNvbmNpbGVycyBleGlzdCB0byBwYXBlciBvdmVyIGV4YWN0bHkgdGhhdCkuXG4gKlxuICogVGhpcyBpcyB0aGF0IG1pc3NpbmcgYnVzLCBhcyBhIHJldXNhYmxlIHByaW1pdGl2ZTpcbiAqICAtICoqcHVibGlzaCh0b3BpYywgcGF5bG9hZCkqKiDihpIgYFhBRERgIG9udG8gYSBib3VuZGVkIChgTUFYTEVOIH5gKSBwZXItdG9waWNcbiAqICAgIHN0cmVhbS4gRHVyYWJsZSBhY3Jvc3MgcmVzdGFydHMsIHNoYXJlZCBieSBhbGwgcmVwbGljYXMuXG4gKiAgLSAqKnN1YnNjcmliZSh7dG9waWMsIGdyb3VwLCBjb25zdW1lciwgaGFuZGxlcn0pKiog4oaSIGEgYFhSRUFER1JPVVBgIGNvbnN1bWVyLlxuICogICAgQ29uc3VtZXIgR1JPVVBTIGdpdmUgYXQtbGVhc3Qtb25jZTogZWFjaCBncm91cCBnZXRzIGV2ZXJ5IG1lc3NhZ2Ugb25jZSwgYVxuICogICAgbWVzc2FnZSBzdGF5cyBwZW5kaW5nIHVudGlsIHRoZSBoYW5kbGVyIGBYQUNLYHMgaXQsIGFuZCBgWEFVVE9DTEFJTWBcbiAqICAgIHJlY2xhaW1zIG1lc3NhZ2VzIHN0cmFuZGVkIGJ5IGEgY3Jhc2hlZCBjb25zdW1lci4gTXVsdGlwbGUgZ3JvdXBzIG9uIG9uZVxuICogICAgdG9waWMgPSBpbmRlcGVuZGVudCBmYW4tb3V0IChlLmcuIHF1b3RhLXN5bmMgQU5EIGF1ZGl0IGJvdGggcmVhY3QpLlxuICpcbiAqIEZBSUwtU0FGRSArIE9QVC1JTiwgZXhhY3RseSBsaWtlIHRoZSBhdWRpdCBzcG9vbDoge0BsaW5rIGNyZWF0ZUVudlJlZGlzRHVyYWJsZUV2ZW50QnVzfVxuICogcmV0dXJucyBgbnVsbGAgd2hlbiBSZWRpcyBpc24ndCBjb25maWd1cmVkLCBzbyBhIHNlcnZpY2Ugd2l0aG91dCBpdCBzaW1wbHlcbiAqIGRvZXNuJ3QgdXNlIHRoZSBidXMgKGtlZXBzIHRvZGF5J3MgYmVoYXZpb3IpLiBBIHB1Ymxpc2ggZmFpbHVyZSBpcyBkcm9wcGVkLXdpdGgtXG4gKiAtbWV0cmljLCBuZXZlciB0aHJvd247IGEgaGFuZGxlciB0aHJvdyBsZWF2ZXMgdGhlIG1lc3NhZ2UgdW4tYWNrZWQgZm9yIHJlZGVsaXZlcnkuXG4gKlxuICogTWlncmF0aW5nIGEgc3BlY2lmaWMgcmVjb25jaWxlciAoZS5nLiBiaWxsaW5n4oaScXVvdGEgZW50aXRsZW1lbnQgc3luYykgb250byB0aGlzXG4gKiBpcyBkZWxpYmVyYXRlbHkgZm9sbG93LW9uIHdvcmsg4oCUIHRoaXMgbGFuZHMgdGhlIGJhY2tib25lICsgYW4gYWRkaXRpdmUgZW50aXR5LVxuICogZXZlbnQgYnJpZGdlOyB0aGUgcmVjb25jaWxlcnMgc3RheSBhcyB0aGUgYmVsdC1hbmQtc3VzcGVuZGVycyBiYWNrc3RvcCB1bnRpbCBhXG4gKiBmbG93IGlzIGZ1bGx5IGN1dCBvdmVyLlxuICovXG5cbmltcG9ydCB0eXBlIHsgRW50aXR5RXZlbnQsIEVudGl0eUV2ZW50U3Vic2NyaWJlciB9IGZyb20gJy4vZW50aXR5LWV2ZW50cy5qcyc7XG5pbXBvcnQgeyBjcmVhdGVFbnZSZWRpc0NsaWVudCB9IGZyb20gJy4vZW52LXJlZGlzLmpzJztcbmltcG9ydCB7IGNyZWF0ZUxvZ2dlciB9IGZyb20gJy4uL3V0aWxzL2xvZ2dlci5qcyc7XG5pbXBvcnQgeyBlbWl0Q291bnRlciB9IGZyb20gJy4uL3V0aWxzL21ldHJpYy1lbWl0dGVyLmpzJztcblxuY29uc3QgbG9nZ2VyID0gY3JlYXRlTG9nZ2VyKCdkdXJhYmxlLWV2ZW50LWJ1cycpO1xuXG4vKiogQSBkZWxpdmVyZWQgZXZlbnQ6IGl0cyBzdHJlYW0gaWQsIHRvcGljLCBhbmQgZGVjb2RlZCBwYXlsb2FkLiAqL1xuZXhwb3J0IGludGVyZmFjZSBFdmVudEVudmVsb3BlPFQgPSB1bmtub3duPiB7XG4gIC8qKiBSZWRpcyBTdHJlYW0gZW50cnkgaWQgKGA8bXM+LTxzZXE+YCkg4oCUIGFsc28gdGhlIGlkZW1wb3RlbmN5IGhhbmRsZS4gKi9cbiAgaWQ6IHN0cmluZztcbiAgdG9waWM6IHN0cmluZztcbiAgcGF5bG9hZDogVDtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBTdWJzY3JpYmVPcHRpb25zPFQgPSB1bmtub3duPiB7XG4gIC8qKiBUb3BpYyAoc3RyZWFtKSB0byBjb25zdW1lLiAqL1xuICB0b3BpYzogc3RyaW5nO1xuICAvKiogQ29uc3VtZXIgZ3JvdXAg4oCUIG9uZSBkZWxpdmVyeSBwZXIgZ3JvdXA7IGRpc3RpbmN0IGdyb3VwcyBmYW4gb3V0LiAqL1xuICBncm91cDogc3RyaW5nO1xuICAvKiogVGhpcyBjb25zdW1lcidzIGlkIHdpdGhpbiB0aGUgZ3JvdXAgKGUuZy4gYCR7c2VydmljZX0tJHtwaWR9YCkuICovXG4gIGNvbnN1bWVyOiBzdHJpbmc7XG4gIC8qKiBBc3luYyBoYW5kbGVyLiBSZXNvbHZlcyDih5IgdGhlIG1lc3NhZ2UgaXMgYWNrZWQ7IHRocm93cyDih5IgbGVmdCBwZW5kaW5nIGZvciByZWRlbGl2ZXJ5LiAqL1xuICBoYW5kbGVyOiAoZW52OiBFdmVudEVudmVsb3BlPFQ+KSA9PiBQcm9taXNlPHZvaWQ+O1xuICAvKiogTWF4IG1lc3NhZ2VzIHBlciByZWFkIChkZWZhdWx0IDE2KS4gKi9cbiAgYmF0Y2hTaXplPzogbnVtYmVyO1xuICAvKiogWFJFQURHUk9VUCBibG9jayB0aW1lIGluIG1zIChkZWZhdWx0IDUwMDApLiAqL1xuICBibG9ja01zPzogbnVtYmVyO1xuICAvKiogQSBwZW5kaW5nIG1lc3NhZ2UgaWRsZSB0aGlzIGxvbmcgKG1zKSBpcyByZWNsYWltZWQgZnJvbSBhIGRlYWQgY29uc3VtZXIgKGRlZmF1bHQgNjAwMDApLiAqL1xuICBtaW5JZGxlTXM/OiBudW1iZXI7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgRXZlbnRTdWJzY3JpcHRpb24ge1xuICAvKiogU3RvcCB0aGUgY29uc3VtZXIgbG9vcC4gUmVzb2x2ZXMgb25jZSB0aGUgaW4tZmxpZ2h0IHJlYWQgcmV0dXJucy4gKi9cbiAgc3RvcCgpOiBQcm9taXNlPHZvaWQ+O1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIER1cmFibGVFdmVudEJ1cyB7XG4gIC8qKiBQdWJsaXNoIGEgcGF5bG9hZCB0byBhIHRvcGljLiBSZXR1cm5zIHRoZSBzdHJlYW0gaWQsIG9yIG51bGwgb24gZmFpbHVyZSAoZHJvcHBlZCwgbmV2ZXIgdGhyb3dzKS4gKi9cbiAgcHVibGlzaDxUPih0b3BpYzogc3RyaW5nLCBwYXlsb2FkOiBUKTogUHJvbWlzZTxzdHJpbmcgfCBudWxsPjtcbiAgLyoqIFN0YXJ0IGEgY29uc3VtZXItZ3JvdXAgcmVhZGVyIGZvciBhIHRvcGljLiBGaXJlLWFuZC1mb3JnZXQgbG9vcDsgY2FsbCBgc3RvcCgpYCB0byBlbmQgaXQuICovXG4gIHN1YnNjcmliZTxUPihvcHRzOiBTdWJzY3JpYmVPcHRpb25zPFQ+KTogRXZlbnRTdWJzY3JpcHRpb247XG59XG5cbi8qKlxuICogVGhlIHN1YnNldCBvZiBpb3JlZGlzJyBTdHJlYW0gQVBJIHRoZSBidXMgdXNlcy4gS2VwdCBtaW5pbWFsIHNvIGEgdGVzdCBjYW5cbiAqIHN1cHBseSBhbiBpbi1tZW1vcnkgZmFrZSBhbmQgc28gbWVyZWx5IGltcG9ydGluZyB0aGlzIG5ldmVyIGhhcmQtZGVwZW5kcyBvblxuICogaW9yZWRpcyAoY29uc3RydWN0ZWQgdmlhIHRoZSBzaGFyZWQgZW52IGhlbHBlcikuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgUmVkaXNTdHJlYW1DbGllbnQge1xuICB4YWRkKGtleTogc3RyaW5nLCAuLi5hcmdzOiAoc3RyaW5nIHwgbnVtYmVyKVtdKTogUHJvbWlzZTxzdHJpbmcgfCBudWxsPjtcbiAgeGdyb3VwKC4uLmFyZ3M6IChzdHJpbmcgfCBudW1iZXIpW10pOiBQcm9taXNlPHVua25vd24+O1xuICB4cmVhZGdyb3VwKC4uLmFyZ3M6IChzdHJpbmcgfCBudW1iZXIpW10pOiBQcm9taXNlPHVua25vd24+O1xuICB4YWNrKGtleTogc3RyaW5nLCBncm91cDogc3RyaW5nLCAuLi5pZHM6IHN0cmluZ1tdKTogUHJvbWlzZTxudW1iZXI+O1xuICB4YXV0b2NsYWltKC4uLmFyZ3M6IChzdHJpbmcgfCBudW1iZXIpW10pOiBQcm9taXNlPHVua25vd24+O1xufVxuXG5jb25zdCBERUZBVUxUX01BWExFTiA9IDEwXzAwMDtcbmNvbnN0IERFRkFVTFRfQkFUQ0ggPSAxNjtcbmNvbnN0IERFRkFVTFRfQkxPQ0tfTVMgPSA1XzAwMDtcbmNvbnN0IERFRkFVTFRfTUlOX0lETEVfTVMgPSA2MF8wMDA7XG5cbmZ1bmN0aW9uIGVyck1zZyhlcnI6IHVua25vd24pOiBzdHJpbmcge1xuICByZXR1cm4gZXJyIGluc3RhbmNlb2YgRXJyb3IgPyBlcnIubWVzc2FnZSA6IFN0cmluZyhlcnIpO1xufVxuXG5mdW5jdGlvbiBzdHJlYW1LZXkodG9waWM6IHN0cmluZyk6IHN0cmluZyB7XG4gIHJldHVybiBgZXZ0OiR7dG9waWN9YDtcbn1cblxuLyoqIFRydWUgd2hlbiB0aGUgZXJyb3IgaXMgUmVkaXMnIFwiZ3JvdXAgYWxyZWFkeSBleGlzdHNcIiAoaWRlbXBvdGVudCBjcmVhdGUpLiAqL1xuZnVuY3Rpb24gaXNCdXN5R3JvdXAoZXJyOiB1bmtub3duKTogYm9vbGVhbiB7XG4gIHJldHVybiBlcnJNc2coZXJyKS5pbmNsdWRlcygnQlVTWUdST1VQJyk7XG59XG5cbi8qKlxuICogUGFyc2UgdGhlIG5lc3RlZCBhcnJheSBzaGFwZSBYUkVBREdST1VQIC8gWEFVVE9DTEFJTSByZXR1cm4gaW50byBmbGF0IGVudmVsb3Blcy5cbiAqIFhSRUFER1JPVVA6IGBbW3N0cmVhbUtleSwgW1tpZCwgW2YsIHYsIC4uLl1dLCAuLi5dXV1gLlxuICogWEFVVE9DTEFJTTogYFtuZXh0Q3Vyc29yLCBbW2lkLCBbZiwgdiwgLi4uXV0sIC4uLl0sIGRlbGV0ZWRJZHNdYC5cbiAqIFdlIHN0b3JlIHRoZSBKU09OIHBheWxvYWQgdW5kZXIgYSBzaW5nbGUgZmllbGQgYGRgLlxuICovXG5mdW5jdGlvbiBwYXJzZUVudHJpZXM8VD4odG9waWM6IHN0cmluZywgZW50cmllczogdW5rbm93bik6IEV2ZW50RW52ZWxvcGU8VD5bXSB7XG4gIGNvbnN0IG91dDogRXZlbnRFbnZlbG9wZTxUPltdID0gW107XG4gIGlmICghQXJyYXkuaXNBcnJheShlbnRyaWVzKSkgcmV0dXJuIG91dDtcbiAgZm9yIChjb25zdCBlbnRyeSBvZiBlbnRyaWVzKSB7XG4gICAgaWYgKCFBcnJheS5pc0FycmF5KGVudHJ5KSB8fCBlbnRyeS5sZW5ndGggPCAyKSBjb250aW51ZTtcbiAgICBjb25zdCBpZCA9IFN0cmluZyhlbnRyeVswXSk7XG4gICAgY29uc3QgZmllbGRzID0gZW50cnlbMV07XG4gICAgaWYgKCFBcnJheS5pc0FycmF5KGZpZWxkcykpIGNvbnRpbnVlO1xuICAgIC8vIGZpZWxkcyBpcyBbbmFtZSwgdmFsdWUsIG5hbWUsIHZhbHVlLCAuLi5dOyBmaW5kICdkJy5cbiAgICBsZXQgcmF3OiBzdHJpbmcgfCB1bmRlZmluZWQ7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgKyAxIDwgZmllbGRzLmxlbmd0aDsgaSArPSAyKSB7XG4gICAgICBpZiAoU3RyaW5nKGZpZWxkc1tpXSkgPT09ICdkJykgeyByYXcgPSBTdHJpbmcoZmllbGRzW2kgKyAxXSk7IGJyZWFrOyB9XG4gICAgfVxuICAgIC8vIEEgbWlzc2luZyBgZGAgZmllbGQgKGFuIGVudHJ5IG5vdCB3cml0dGVuIGJ5IHB1Ymxpc2goKSkgT1IgYSBjb3JydXB0IEpTT05cbiAgICAvLyBwYXlsb2FkIGJvdGggeWllbGQgYW4gdW5kZWZpbmVkLXBheWxvYWQgZW52ZWxvcGUgc28gYGRlbGl2ZXIoKWAgQUNLcyBpdCDigJRcbiAgICAvLyBhIHBvaXNvbiBtZXNzYWdlIG11c3QgbmV2ZXIgd2VkZ2UgdGhlIGdyb3VwIGJ5IHN0YXlpbmcgcGVycGV0dWFsbHkgcGVuZGluZy5cbiAgICBpZiAocmF3ID09PSB1bmRlZmluZWQpIHtcbiAgICAgIG91dC5wdXNoKHsgaWQsIHRvcGljLCBwYXlsb2FkOiB1bmRlZmluZWQgYXMgdW5rbm93biBhcyBUIH0pO1xuICAgICAgY29udGludWU7XG4gICAgfVxuICAgIHRyeSB7XG4gICAgICBvdXQucHVzaCh7IGlkLCB0b3BpYywgcGF5bG9hZDogSlNPTi5wYXJzZShyYXcpIGFzIFQgfSk7XG4gICAgfSBjYXRjaCB7XG4gICAgICBvdXQucHVzaCh7IGlkLCB0b3BpYywgcGF5bG9hZDogdW5kZWZpbmVkIGFzIHVua25vd24gYXMgVCB9KTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIG91dDtcbn1cblxuLyoqIEJ1aWxkIGEgZHVyYWJsZSBldmVudCBidXMgb3ZlciBhIFJlZGlzIFN0cmVhbXMgY2xpZW50LiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZVJlZGlzRHVyYWJsZUV2ZW50QnVzKFxuICByZWRpczogUmVkaXNTdHJlYW1DbGllbnQsXG4gIG9wdHM6IHsgbWF4TGVuPzogbnVtYmVyIH0gPSB7fSxcbik6IER1cmFibGVFdmVudEJ1cyB7XG4gIGNvbnN0IG1heExlbiA9IE1hdGgubWF4KDEsIG9wdHMubWF4TGVuID8/IERFRkFVTFRfTUFYTEVOKTtcblxuICByZXR1cm4ge1xuICAgIGFzeW5jIHB1Ymxpc2g8VD4odG9waWM6IHN0cmluZywgcGF5bG9hZDogVCk6IFByb21pc2U8c3RyaW5nIHwgbnVsbD4ge1xuICAgICAgY29uc3Qga2V5ID0gc3RyZWFtS2V5KHRvcGljKTtcbiAgICAgIHRyeSB7XG4gICAgICAgIC8vIE1BWExFTiB+IDxuPiBib3VuZHMgdGhlIHN0cmVhbSBhcHByb3hpbWF0ZWx5IChjaGVhcCk7IGAqYCA9IHNlcnZlciBpZC5cbiAgICAgICAgY29uc3QgaWQgPSBhd2FpdCByZWRpcy54YWRkKGtleSwgJ01BWExFTicsICd+JywgbWF4TGVuLCAnKicsICdkJywgSlNPTi5zdHJpbmdpZnkocGF5bG9hZCkpO1xuICAgICAgICBlbWl0Q291bnRlcignZXZlbnRfYnVzX3B1Ymxpc2hlZF90b3RhbCcsIHsgdG9waWMgfSk7XG4gICAgICAgIHJldHVybiBpZDtcbiAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICBlbWl0Q291bnRlcignZXZlbnRfYnVzX3B1Ymxpc2hfZmFpbGVkX3RvdGFsJywgeyB0b3BpYyB9KTtcbiAgICAgICAgbG9nZ2VyLndhcm4oJ0V2ZW50IGJ1cyBwdWJsaXNoIGZhaWxlZCAoZXZlbnQgZHJvcHBlZCknLCB7IHRvcGljLCBlcnJvcjogZXJyTXNnKGVycikgfSk7XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgICAgfVxuICAgIH0sXG5cbiAgICBzdWJzY3JpYmU8VD4oc3ViT3B0czogU3Vic2NyaWJlT3B0aW9uczxUPik6IEV2ZW50U3Vic2NyaXB0aW9uIHtcbiAgICAgIGNvbnN0IHsgdG9waWMsIGdyb3VwLCBjb25zdW1lciwgaGFuZGxlciB9ID0gc3ViT3B0cztcbiAgICAgIGNvbnN0IGtleSA9IHN0cmVhbUtleSh0b3BpYyk7XG4gICAgICBjb25zdCBiYXRjaCA9IE1hdGgubWF4KDEsIHN1Yk9wdHMuYmF0Y2hTaXplID8/IERFRkFVTFRfQkFUQ0gpO1xuICAgICAgY29uc3QgYmxvY2tNcyA9IE1hdGgubWF4KDAsIHN1Yk9wdHMuYmxvY2tNcyA/PyBERUZBVUxUX0JMT0NLX01TKTtcbiAgICAgIGNvbnN0IG1pbklkbGUgPSBNYXRoLm1heCgwLCBzdWJPcHRzLm1pbklkbGVNcyA/PyBERUZBVUxUX01JTl9JRExFX01TKTtcblxuICAgICAgbGV0IHN0b3BwZWQgPSBmYWxzZTtcbiAgICAgIGxldCBzdGFydGVkID0gZmFsc2U7XG5cbiAgICAgIGNvbnN0IGRlbGl2ZXIgPSBhc3luYyAoZW52czogRXZlbnRFbnZlbG9wZTxUPltdKTogUHJvbWlzZTx2b2lkPiA9PiB7XG4gICAgICAgIGZvciAoY29uc3QgZW52IG9mIGVudnMpIHtcbiAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgaWYgKGVudi5wYXlsb2FkICE9PSB1bmRlZmluZWQpIGF3YWl0IGhhbmRsZXIoZW52KTtcbiAgICAgICAgICAgIC8vIEFjayBvbiBzdWNjZXNzIE9SIG9uIGFuIHVuZGVmaW5lZCAoY29ycnVwdCkgcGF5bG9hZCDigJQgYSBwb2lzb25cbiAgICAgICAgICAgIC8vIG1lc3NhZ2UgbXVzdCBub3QgYmxvY2sgdGhlIGdyb3VwIGZvcmV2ZXIuXG4gICAgICAgICAgICBhd2FpdCByZWRpcy54YWNrKGtleSwgZ3JvdXAsIGVudi5pZCk7XG4gICAgICAgICAgICBlbWl0Q291bnRlcignZXZlbnRfYnVzX2RlbGl2ZXJlZF90b3RhbCcsIHsgdG9waWMsIGdyb3VwIH0pO1xuICAgICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgLy8gTGVhdmUgaXQgcGVuZGluZyAobm8gWEFDSykg4oCUIFhBVVRPQ0xBSU0gcmVkZWxpdmVycyBpdCBhZnRlciBtaW5JZGxlLlxuICAgICAgICAgICAgZW1pdENvdW50ZXIoJ2V2ZW50X2J1c19oYW5kbGVyX2ZhaWxlZF90b3RhbCcsIHsgdG9waWMsIGdyb3VwIH0pO1xuICAgICAgICAgICAgbG9nZ2VyLndhcm4oJ0V2ZW50IGhhbmRsZXIgZmFpbGVkOyBsZWF2aW5nIG1lc3NhZ2UgcGVuZGluZyBmb3IgcmVkZWxpdmVyeScsIHtcbiAgICAgICAgICAgICAgdG9waWMsIGdyb3VwLCBpZDogZW52LmlkLCBlcnJvcjogZXJyTXNnKGVyciksXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH07XG5cbiAgICAgIC8vIFRoZSBjb25zdW1lciBncm91cCBtdXN0IGV4aXN0IGJlZm9yZSBYUkVBREdST1VQIGNhbiBzdWNjZWVkLiBDcmVhdGluZyBpdFxuICAgICAgLy8gaXMgcmV0cmllZCBpbnNpZGUgdGhlIGxvb3A6IGF0IHN0YXJ0dXAgdGhlIGNsaWVudCBtYXkgbm90IGhhdmUgY29ubmVjdGVkXG4gICAgICAvLyB5ZXQsIGFuZCBhIHNpbmdsZSBmYWlsZWQgYXR0ZW1wdCB1c2VkIHRvIGxlYXZlIHRoZSBjb25zdW1lciByZWFkaW5nIGFcbiAgICAgIC8vIGdyb3VwIHRoYXQgd2FzIG5ldmVyIGNyZWF0ZWQg4oCUIGZvcmV2ZXIuXG4gICAgICBsZXQgZ3JvdXBSZWFkeSA9IGZhbHNlO1xuICAgICAgY29uc3QgZW5zdXJlR3JvdXAgPSBhc3luYyAoKTogUHJvbWlzZTx2b2lkPiA9PiB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgLy8gTUtTVFJFQU0gc28gdGhlIHN0cmVhbSBuZWVkIG5vdCBleGlzdCB5ZXQ7ICckJyA9IG9ubHkgbmV3IG1lc3NhZ2VzLlxuICAgICAgICAgIGF3YWl0IHJlZGlzLnhncm91cCgnQ1JFQVRFJywga2V5LCBncm91cCwgJyQnLCAnTUtTVFJFQU0nKTtcbiAgICAgICAgICBncm91cFJlYWR5ID0gdHJ1ZTtcbiAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgaWYgKCFpc0J1c3lHcm91cChlcnIpKSB0aHJvdyBlcnI7XG4gICAgICAgICAgZ3JvdXBSZWFkeSA9IHRydWU7XG4gICAgICAgIH1cbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IGxvb3AgPSBhc3luYyAoKTogUHJvbWlzZTx2b2lkPiA9PiB7XG4gICAgICAgIHdoaWxlICghc3RvcHBlZCkge1xuICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICBpZiAoIWdyb3VwUmVhZHkpIGF3YWl0IGVuc3VyZUdyb3VwKCk7XG4gICAgICAgICAgICAvLyAxKSBSZWNsYWltIG1lc3NhZ2VzIHN0cmFuZGVkIGJ5IGEgY3Jhc2hlZCBjb25zdW1lciBpbiB0aGlzIGdyb3VwLlxuICAgICAgICAgICAgY29uc3QgY2xhaW1lZCA9IGF3YWl0IHJlZGlzLnhhdXRvY2xhaW0oa2V5LCBncm91cCwgY29uc3VtZXIsIG1pbklkbGUsICcwJywgJ0NPVU5UJywgYmF0Y2gpO1xuICAgICAgICAgICAgLy8gWEFVVE9DTEFJTSByZXBseTogW25leHRDdXJzb3IsIGVudHJpZXMsIGRlbGV0ZWRJZHNdXG4gICAgICAgICAgICBpZiAoQXJyYXkuaXNBcnJheShjbGFpbWVkKSAmJiBjbGFpbWVkLmxlbmd0aCA+PSAyKSB7XG4gICAgICAgICAgICAgIGF3YWl0IGRlbGl2ZXIocGFyc2VFbnRyaWVzPFQ+KHRvcGljLCBjbGFpbWVkWzFdKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoc3RvcHBlZCkgYnJlYWs7XG5cbiAgICAgICAgICAgIC8vIDIpIFJlYWQgbmV3LCBuZXZlci1kZWxpdmVyZWQgbWVzc2FnZXMgZm9yIHRoaXMgZ3JvdXAgKCc+JykuXG4gICAgICAgICAgICBjb25zdCByZXMgPSBhd2FpdCByZWRpcy54cmVhZGdyb3VwKFxuICAgICAgICAgICAgICAnR1JPVVAnLCBncm91cCwgY29uc3VtZXIsICdDT1VOVCcsIGJhdGNoLCAnQkxPQ0snLCBibG9ja01zLCAnU1RSRUFNUycsIGtleSwgJz4nLFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIC8vIFhSRUFER1JPVVAgcmVwbHk6IFtbc3RyZWFtS2V5LCBlbnRyaWVzXV0gfCBudWxsIChvbiBibG9jayB0aW1lb3V0KVxuICAgICAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkocmVzKSAmJiByZXMubGVuZ3RoID4gMCAmJiBBcnJheS5pc0FycmF5KHJlc1swXSkgJiYgcmVzWzBdLmxlbmd0aCA+PSAyKSB7XG4gICAgICAgICAgICAgIGF3YWl0IGRlbGl2ZXIocGFyc2VFbnRyaWVzPFQ+KHRvcGljLCByZXNbMF1bMV0pKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgIGlmIChzdG9wcGVkKSBicmVhaztcbiAgICAgICAgICAgIC8vIFRoZSBzdHJlYW0gb3IgZ3JvdXAgd2FzIGRlbGV0ZWQgb3V0IGZyb20gdW5kZXIgdXMg4oCUIHJlY3JlYXRlIGl0LlxuICAgICAgICAgICAgaWYgKC9OT0dST1VQL2kudGVzdChlcnJNc2coZXJyKSkpIGdyb3VwUmVhZHkgPSBmYWxzZTtcbiAgICAgICAgICAgIGxvZ2dlci53YXJuKCdFdmVudCBidXMgY29uc3VtZXIgbG9vcCBlcnJvcjsgYmFja2luZyBvZmYnLCB7IHRvcGljLCBncm91cCwgZXJyb3I6IGVyck1zZyhlcnIpIH0pO1xuICAgICAgICAgICAgLy8gQmFjayBvZmYgc28gYSBwZXJzaXN0ZW50IFJlZGlzIGVycm9yIGRvZXNuJ3QgaG90LXNwaW4uXG4gICAgICAgICAgICBhd2FpdCBuZXcgUHJvbWlzZSgocikgPT4gc2V0VGltZW91dChyLCAxMDAwKSk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9O1xuXG4gICAgICBsZXQgbG9vcFByb21pc2UgPSBQcm9taXNlLnJlc29sdmUoKTtcbiAgICAgIGlmICghc3RhcnRlZCkge1xuICAgICAgICBzdGFydGVkID0gdHJ1ZTtcbiAgICAgICAgbG9vcFByb21pc2UgPSBsb29wKCk7XG4gICAgICAgIGxvZ2dlci5pbmZvKCdFdmVudCBidXMgY29uc3VtZXIgc3RhcnRlZCcsIHsgdG9waWMsIGdyb3VwLCBjb25zdW1lciB9KTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHtcbiAgICAgICAgYXN5bmMgc3RvcCgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgICBzdG9wcGVkID0gdHJ1ZTtcbiAgICAgICAgICAvLyBBd2FpdCB0aGUgaW4tZmxpZ2h0IHJlYWQvaGFuZGxlciBzbyBhIGNhbGxlciAoZS5nLiBhIHNlcnZpY2Ugc2h1dHRpbmdcbiAgICAgICAgICAvLyBkb3duIGl0cyBEQikgZG9lc24ndCByYWNlIGEgbWVzc2FnZSBzdGlsbCBiZWluZyBwcm9jZXNzZWQuIEJvdW5kZWQgYnlcbiAgICAgICAgICAvLyB0aGUgWFJFQURHUk9VUCBCTE9DSyB3aW5kb3cuIE5ldmVyIHJlamVjdHMg4oCUIHRoZSBsb29wIHN3YWxsb3dzIGVycm9ycy5cbiAgICAgICAgICBhd2FpdCBsb29wUHJvbWlzZS5jYXRjaCgoKSA9PiB1bmRlZmluZWQpO1xuICAgICAgICB9LFxuICAgICAgfTtcbiAgICB9LFxuICB9O1xufVxuXG4vKipcbiAqIEJ1aWxkIGEgZHVyYWJsZSBldmVudCBidXMgZnJvbSB0aGUgYW1iaWVudCBSZWRpcyBlbnYgdmlhIHRoZSBzaGFyZWRcbiAqIGBjcmVhdGVFbnZSZWRpc0NsaWVudGAuIFJldHVybnMgYG51bGxgIHdoZW4gUmVkaXMgaXMgbm90IGNvbmZpZ3VyZWQg4oCUIHRoZVxuICogY2FsbGVyIHRoZW4gcnVucyB3aXRob3V0IGEgYnVzICh0b2RheSdzIEhUVFAvcmVjb25jaWxlciBiZWhhdmlvciksIG5ldmVyXG4gKiBjcmFzaGluZy4gT3B0IGluIHdpdGggYSBzaW5nbGUgYm9vdCBsaW5lIHdoZXJlIGEgc2VydmljZSB3YW50cyBkdXJhYmxlIGV2ZW50cy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZUVudlJlZGlzRHVyYWJsZUV2ZW50QnVzKG9wdHM6IHsgbWF4TGVuPzogbnVtYmVyIH0gPSB7fSk6IER1cmFibGVFdmVudEJ1cyB8IG51bGwge1xuICBjb25zdCBpbnN0ID0gY3JlYXRlRW52UmVkaXNDbGllbnQ8UmVkaXNTdHJlYW1DbGllbnQ+KCdldmVudC1idXMnKTtcbiAgaWYgKCFpbnN0KSByZXR1cm4gbnVsbDtcbiAgbG9nZ2VyLmluZm8oJ1JlZGlzIGR1cmFibGUgZXZlbnQgYnVzIGluaXRpYWxpemVkJyk7XG4gIHJldHVybiBjcmVhdGVSZWRpc0R1cmFibGVFdmVudEJ1cyhpbnN0LCBvcHRzKTtcbn1cblxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4vLyBFbnRpdHktZXZlbnQgYnJpZGdlIChhZGRpdGl2ZSwgb3B0LWluKVxuLy9cbi8vIExldHMgYSBzZXJ2aWNlIGdpdmUgaXRzIGluLXByb2Nlc3Mge0BsaW5rIGVudGl0eUV2ZW50c30gZW1pdHRlciBhIERVUkFCTEUsXG4vLyBjcm9zcy1wb2QgZGVsaXZlcnkgbGVnIFdJVEhPVVQgY2hhbmdpbmcgZXhpc3RpbmcgYmVoYXZpb3I6IHJlZ2lzdGVyIHRoZVxuLy8gcmV0dXJuZWQgc3Vic2NyaWJlciBhbmQgZXZlcnkgZW50aXR5IG11dGF0aW9uIGlzIEFMU08gcHVibGlzaGVkIHRvIHRoZSBidXMuXG4vLyBBIGNvbnN1bWVyIGVsc2V3aGVyZSAoYGJ1cy5zdWJzY3JpYmVgKSB0aGVuIHJlYWN0cyBhdC1sZWFzdC1vbmNlIGFjcm9zcyBwb2RzXG4vLyBhbmQgcmVzdGFydHMuIFRoZSBpbi1wcm9jZXNzIHN1YnNjcmliZXJzIGtlZXAgZmlyaW5nIGV4YWN0bHkgYXMgYmVmb3JlLCBzb1xuLy8gdGhpcyBpcyBwdXJlbHkgYWRkaXRpdmUg4oCUIG5vIGRvdWJsZS1wcm9jZXNzaW5nIHVubGVzcyBhIHNlcnZpY2UgaW50ZW50aW9uYWxseVxuLy8gcnVucyBhIGJ1cyBjb25zdW1lciBmb3IgdGhlIHNhbWUgcmVhY3Rpb24uIEtlcHQgaGVyZSAobm90IGluIGVudGl0eS1ldmVudHMudHMpXG4vLyBzbyB0aGF0IG1vZHVsZSBzdGF5cyBpbmZyYXN0cnVjdHVyZS1mcmVlIHBlciBpdHMgb3duIGNvbnRyYWN0LlxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cbi8qKiBUb3BpYyB0aGUgZW50aXR5LWV2ZW50IGJyaWRnZSBwdWJsaXNoZXMgdG8uICovXG5leHBvcnQgY29uc3QgRU5USVRZX0VWRU5UX1RPUElDID0gJ2VudGl0eS1ldmVudHMnO1xuXG4vKipcbiAqIEFuIHtAbGluayBFbnRpdHlFdmVudFN1YnNjcmliZXJ9IHRoYXQgZm9yd2FyZHMgZWFjaCBlbnRpdHkgZXZlbnQgdG8gdGhlIGR1cmFibGVcbiAqIGJ1cy4gYGJ1cy5wdWJsaXNoYCBpcyBmYWlsLXNhZmUgKGRyb3BzLXdpdGgtbWV0cmljLCBuZXZlciB0aHJvd3MpLCBtYXRjaGluZyB0aGVcbiAqIGVtaXR0ZXIncyBmaXJlLWFuZC1mb3JnZXQgY29udHJhY3QuIE5vdGUgYEVudGl0eUV2ZW50LnRpbWVzdGFtcGAgKGEgRGF0ZSlcbiAqIHNlcmlhbGl6ZXMgdG8gYW4gSVNPIHN0cmluZyBvbiB0aGUgd2lyZSDigJQgYSBjb25zdW1lciByZS1oeWRyYXRlcyBhcyBuZWVkZWQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVFbnRpdHlFdmVudEJ1c1B1Ymxpc2hlcihidXM6IER1cmFibGVFdmVudEJ1cyk6IEVudGl0eUV2ZW50U3Vic2NyaWJlciB7XG4gIHJldHVybiB7XG4gICAgYXN5bmMgb25FbnRpdHlFdmVudChldmVudDogRW50aXR5RXZlbnQpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgIGF3YWl0IGJ1cy5wdWJsaXNoKEVOVElUWV9FVkVOVF9UT1BJQywgZXZlbnQpO1xuICAgIH0sXG4gIH07XG59XG4iXX0=
266
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZHVyYWJsZS1ldmVudC1idXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvc2VydmljZXMvZHVyYWJsZS1ldmVudC1idXMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsK0NBQStDO0FBQy9DLHNDQUFzQztBQUV0Qzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0EwQkc7QUFFSCxPQUFPLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUN0RCxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFDbEQsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBRXpELE1BQU0sTUFBTSxHQUFHLFlBQVksQ0FBQyxtQkFBbUIsQ0FBQyxDQUFDO0FBdUVqRCxNQUFNLGNBQWMsR0FBRyxNQUFNLENBQUM7QUFDOUIsTUFBTSxhQUFhLEdBQUcsRUFBRSxDQUFDO0FBQ3pCLE1BQU0sZ0JBQWdCLEdBQUcsS0FBSyxDQUFDO0FBQy9CLE1BQU0sbUJBQW1CLEdBQUcsTUFBTSxDQUFDO0FBQ25DLE1BQU0sc0JBQXNCLEdBQUcsRUFBRSxDQUFDO0FBRWxDLFNBQVMsTUFBTSxDQUFDLEdBQVk7SUFDMUIsT0FBTyxHQUFHLFlBQVksS0FBSyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUM7QUFDMUQsQ0FBQztBQUVELFNBQVMsU0FBUyxDQUFDLEtBQWE7SUFDOUIsT0FBTyxPQUFPLEtBQUssRUFBRSxDQUFDO0FBQ3hCLENBQUM7QUFFRCxzQ0FBc0M7QUFDdEMsTUFBTSxVQUFVLG1CQUFtQixDQUFDLEtBQWE7SUFDL0MsT0FBTyxPQUFPLEtBQUssTUFBTSxDQUFDO0FBQzVCLENBQUM7QUFFRCxtRkFBbUY7QUFDbkYsU0FBUyxpQkFBaUIsQ0FBQyxFQUFVO0lBQ25DLE1BQU0sRUFBRSxHQUFHLE1BQU0sQ0FBQyxFQUFF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RyxJQUFJLEVBQUUsQ0FBQztZQUMzQixNQUFNLENBQUMsSUFBSSxDQUFDLDRCQUE0QixFQUFFLEVBQUUsS0FBSyxFQUFFLEtBQUssRUFBRSxRQUFRLEVBQUUsYUFBYSxFQUFFLENBQUMsQ0FBQztZQUVyRixPQUFPO2dCQUNMLEtBQUssQ0FBQyxJQUFJO29CQUNSLE9BQU8sR0FBRyxJQUFJLENBQUM7b0JBQ2Ysd0VBQXdFO29CQUN4RSx3RUFBd0U7b0JBQ3hFLHlFQUF5RTtvQkFDekUsTUFBTSxXQUFXLENBQUMsS0FBSyxDQUFDLEdBQUcsRUFBRSxDQUFDLFNBQVMsQ0FBQyxDQUFDO29CQUN6QyxNQUFNLE9BQU8sQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsQ0FBQyxLQUFLLENBQUMsR0FBRyxFQUFFLENBQUMsU0FBUyxDQUFDLENBQUM7Z0JBQ2hFLENBQUM7YUFDRixDQUFDO1FBQ0osQ0FBQztLQUNGLENBQUM7QUFDSixDQUFDO0FBRUQ7Ozs7O0dBS0c7QUFDSCxNQUFNLFVBQVUsNkJBQTZCLENBQUMsSUFBSSxHQUF3QixFQUFFO0lBQzFFLE1BQU0sSUFBSSxHQUFHLG9CQUFvQixDQUFvQixXQUFXLENBQUMsQ0FBQztJQUNsRSxJQUFJLENBQUMsSUFBSTtRQUFFLE9BQU8sSUFBSSxDQUFDO0lBQ3ZCLE1BQU0sQ0FBQyxJQUFJLENBQUMscUNBQXFDLENBQUMsQ0FBQztJQUNuRCxPQUFPLDBCQUEwQixDQUFDLElBQUksRUFBRSxJQUFJLENBQUMsQ0FBQztBQUNoRCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQ29weXJpZ2h0IDIwMjYgUGlwZWxpbmUgQnVpbGRlciBDb250cmlidXRvcnNcbi8vIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBcGFjaGUtMi4wXG5cbi8qKlxuICogRHVyYWJsZSwgYXQtbGVhc3Qtb25jZSBldmVudCBiYWNrYm9uZSAoUmVkaXMgU3RyZWFtcykuXG4gKlxuICogVGhlIHBsYXRmb3JtJ3MgY3Jvc3Mtc2VydmljZSBzaWduYWxsaW5nIHRvZGF5IGlzIHBvaW50LXRvLXBvaW50IEhUVFAgcGx1c1xuICogcG9sbGluZyByZWNvbmNpbGVycyBwbHVzIGFuIElOLVBST0NFU1MgYmVzdC1lZmZvcnQgZW1pdHRlciAoe0BsaW5rIGVudGl0eUV2ZW50c30pLlxuICogVGhlcmUgaXMgbm8gZHVyYWJsZSBidXMsIHNvIGEgc2lnbmFsIHByb2R1Y2VkIG9uIG9uZSBwb2QgaXMgZWl0aGVyIGRlbGl2ZXJlZFxuICogc3luY2hyb25vdXNseSBvdmVyIEhUVFAgKGNvdXBsaW5nICsgcmV0cnktc3Rvcm0gcmlzaykgb3IgbG9zdCBpZiB0aGUgY29uc3VtZXJcbiAqIGlzIG1vbWVudGFyaWx5IGRvd24gKHRoZSByZWNvbmNpbGVycyBleGlzdCB0byBwYXBlciBvdmVyIGV4YWN0bHkgdGhhdCkuXG4gKlxuICogVGhpcyBpcyB0aGF0IG1pc3NpbmcgYnVzLCBhcyBhIHJldXNhYmxlIHByaW1pdGl2ZTpcbiAqICAtICoqcHVibGlzaCh0b3BpYywgcGF5bG9hZCkqKiDihpIgYFhBRERgIG9udG8gYSBib3VuZGVkIChgTUFYTEVOIH5gKSBwZXItdG9waWNcbiAqICAgIHN0cmVhbS4gRHVyYWJsZSBhY3Jvc3MgcmVzdGFydHMsIHNoYXJlZCBieSBhbGwgcmVwbGljYXMuXG4gKiAgLSAqKnN1YnNjcmliZSh7dG9waWMsIGdyb3VwLCBjb25zdW1lciwgaGFuZGxlcn0pKiog4oaSIGEgYFhSRUFER1JPVVBgIGNvbnN1bWVyXG4gKiAgICBvbiBpdHMgT1dOIGNvbm5lY3Rpb24gKGBkdXBsaWNhdGUoKWApLCBzbyBhIGJsb2NraW5nIHJlYWQgbmV2ZXIgZGVsYXlzIGFcbiAqICAgIHB1Ymxpc2guIENvbnN1bWVyIEdST1VQUyBnaXZlIGF0LWxlYXN0LW9uY2U6IGVhY2ggZ3JvdXAgZ2V0cyBldmVyeSBtZXNzYWdlXG4gKiAgICBvbmNlLCBhIG1lc3NhZ2Ugc3RheXMgcGVuZGluZyB1bnRpbCB0aGUgaGFuZGxlciBgWEFDS2BzIGl0LCBhbmQgYFhBVVRPQ0xBSU1gXG4gKiAgICByZWNsYWltcyBtZXNzYWdlcyBzdHJhbmRlZCBieSBhIGNyYXNoZWQgY29uc3VtZXIuIEEgbWVzc2FnZSB0aGF0IGhhcyBiZWVuXG4gKiAgICBkZWxpdmVyZWQgYG1heERlbGl2ZXJpZXNgIHRpbWVzIHdpdGhvdXQgYW4gYWNrIGlzIG1vdmVkIHRvIGEgZGVhZC1sZXR0ZXJcbiAqICAgIHN0cmVhbSAoYGV2dDo8dG9waWM+OmRscWApIGFuZCBhY2tlZCwgc28gYSBwb2lzb24gbWVzc2FnZSBjYW4ndCByZWRlbGl2ZXJcbiAqICAgIGZvcmV2ZXIuIE11bHRpcGxlIGdyb3VwcyBvbiBvbmUgdG9waWMgPSBpbmRlcGVuZGVudCBmYW4tb3V0LlxuICpcbiAqIEZBSUwtU0FGRSArIE9QVC1JTiwgZXhhY3RseSBsaWtlIHRoZSBhdWRpdCBzcG9vbDoge0BsaW5rIGNyZWF0ZUVudlJlZGlzRHVyYWJsZUV2ZW50QnVzfVxuICogcmV0dXJucyBgbnVsbGAgd2hlbiBSZWRpcyBpc24ndCBjb25maWd1cmVkLCBzbyBhIHNlcnZpY2Ugd2l0aG91dCBpdCBzaW1wbHlcbiAqIGRvZXNuJ3QgdXNlIHRoZSBidXMgKGtlZXBzIHRvZGF5J3MgYmVoYXZpb3IpLiBBIHB1Ymxpc2ggZmFpbHVyZSBpcyBkcm9wcGVkLXdpdGgtXG4gKiAtbWV0cmljLCBuZXZlciB0aHJvd247IGEgaGFuZGxlciB0aHJvdyBsZWF2ZXMgdGhlIG1lc3NhZ2UgdW4tYWNrZWQgZm9yIHJlZGVsaXZlcnkuXG4gKlxuICovXG5cbmltcG9ydCB7IGNyZWF0ZUVudlJlZGlzQ2xpZW50IH0gZnJvbSAnLi9lbnYtcmVkaXMuanMnO1xuaW1wb3J0IHsgY3JlYXRlTG9nZ2VyIH0gZnJvbSAnLi4vdXRpbHMvbG9nZ2VyLmpzJztcbmltcG9ydCB7IGVtaXRDb3VudGVyIH0gZnJvbSAnLi4vdXRpbHMvbWV0cmljLWVtaXR0ZXIuanMnO1xuXG5jb25zdCBsb2dnZXIgPSBjcmVhdGVMb2dnZXIoJ2R1cmFibGUtZXZlbnQtYnVzJyk7XG5cbi8qKiBBIGRlbGl2ZXJlZCBldmVudDogaXRzIHN0cmVhbSBpZCwgdG9waWMsIHB1Ymxpc2ggdGltZSwgYW5kIGRlY29kZWQgcGF5bG9hZC4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgRXZlbnRFbnZlbG9wZTxUID0gdW5rbm93bj4ge1xuICAvKiogUmVkaXMgU3RyZWFtIGVudHJ5IGlkIChgPG1zPi08c2VxPmApIOKAlCBhbHNvIHRoZSBpZGVtcG90ZW5jeSBoYW5kbGUuICovXG4gIGlkOiBzdHJpbmc7XG4gIHRvcGljOiBzdHJpbmc7XG4gIC8qKlxuICAgKiBXaGVuIHRoZSBldmVudCB3YXMgcHVibGlzaGVkICh0aGUgUmVkaXMgc2VydmVyIHRpbWUgZW1iZWRkZWQgaW4gdGhlIHN0cmVhbVxuICAgKiBpZCkuIEEgcmVkZWxpdmVyeSBrZWVwcyBpdHMgT1JJR0lOQUwgcHVibGlzaCB0aW1lLCBzbyBhIGNvbnN1bWVyIGFwcGx5aW5nXG4gICAqIGxhc3Qtd3JpdGVyLXdpbnMgc3RhdGUgKGUuZy4gYW4gZW50aXRsZW1lbnQgc3luYykgY2FuIG9yZGVyIGV2ZW50cyBieSBpdFxuICAgKiBpbnN0ZWFkIG9mIGJ5IGRlbGl2ZXJ5IHRpbWUgYW5kIHJlZnVzZSB0byBsZXQgYSBzdGFsZSByZXRyeSBvdmVyd3JpdGUgYVxuICAgKiBuZXdlciBzdGF0ZS5cbiAgICovXG4gIHB1Ymxpc2hlZEF0OiBEYXRlO1xuICBwYXlsb2FkOiBUO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFN1YnNjcmliZU9wdGlvbnM8VCA9IHVua25vd24+IHtcbiAgLyoqIFRvcGljIChzdHJlYW0pIHRvIGNvbnN1bWUuICovXG4gIHRvcGljOiBzdHJpbmc7XG4gIC8qKiBDb25zdW1lciBncm91cCDigJQgb25lIGRlbGl2ZXJ5IHBlciBncm91cDsgZGlzdGluY3QgZ3JvdXBzIGZhbiBvdXQuICovXG4gIGdyb3VwOiBzdHJpbmc7XG4gIC8qKiBUaGlzIGNvbnN1bWVyJ3MgaWQgd2l0aGluIHRoZSBncm91cCAoZS5nLiBgJHtzZXJ2aWNlfS0ke3BpZH1gKS4gKi9cbiAgY29uc3VtZXI6IHN0cmluZztcbiAgLyoqIEFzeW5jIGhhbmRsZXIuIFJlc29sdmVzIOKHkiB0aGUgbWVzc2FnZSBpcyBhY2tlZDsgdGhyb3dzIOKHkiBsZWZ0IHBlbmRpbmcgZm9yIHJlZGVsaXZlcnkuICovXG4gIGhhbmRsZXI6IChlbnY6IEV2ZW50RW52ZWxvcGU8VD4pID0+IFByb21pc2U8dm9pZD47XG4gIC8qKiBNYXggbWVzc2FnZXMgcGVyIHJlYWQgKGRlZmF1bHQgMTYpLiAqL1xuICBiYXRjaFNpemU/OiBudW1iZXI7XG4gIC8qKiBYUkVBREdST1VQIGJsb2NrIHRpbWUgaW4gbXMgKGRlZmF1bHQgNTAwMCkuICovXG4gIGJsb2NrTXM/OiBudW1iZXI7XG4gIC8qKiBBIHBlbmRpbmcgbWVzc2FnZSBpZGxlIHRoaXMgbG9uZyAobXMpIGlzIHJlY2xhaW1lZCBmcm9tIGEgZGVhZCBjb25zdW1lciAoZGVmYXVsdCA2MDAwMCkuICovXG4gIG1pbklkbGVNcz86IG51bWJlcjtcbiAgLyoqXG4gICAqIERlbGl2ZXJpZXMgYWZ0ZXIgd2hpY2ggYW4gdW4tYWNrZWQgbWVzc2FnZSBpcyBkZWFkLWxldHRlcmVkIHRvXG4gICAqIGBldnQ6PHRvcGljPjpkbHFgIGFuZCBhY2tlZCBpbnN0ZWFkIG9mIGJlaW5nIHJlZGVsaXZlcmVkIGFnYWluIChkZWZhdWx0IDEwKS5cbiAgICovXG4gIG1heERlbGl2ZXJpZXM/OiBudW1iZXI7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgRXZlbnRTdWJzY3JpcHRpb24ge1xuICAvKiogU3RvcCB0aGUgY29uc3VtZXIgbG9vcC4gUmVzb2x2ZXMgb25jZSB0aGUgaW4tZmxpZ2h0IHJlYWQgcmV0dXJucy4gKi9cbiAgc3RvcCgpOiBQcm9taXNlPHZvaWQ+O1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIER1cmFibGVFdmVudEJ1cyB7XG4gIC8qKiBQdWJsaXNoIGEgcGF5bG9hZCB0byBhIHRvcGljLiBSZXR1cm5zIHRoZSBzdHJlYW0gaWQsIG9yIG51bGwgb24gZmFpbHVyZSAoZHJvcHBlZCwgbmV2ZXIgdGhyb3dzKS4gKi9cbiAgcHVibGlzaDxUPih0b3BpYzogc3RyaW5nLCBwYXlsb2FkOiBUKTogUHJvbWlzZTxzdHJpbmcgfCBudWxsPjtcbiAgLyoqIFN0YXJ0IGEgY29uc3VtZXItZ3JvdXAgcmVhZGVyIGZvciBhIHRvcGljLiBGaXJlLWFuZC1mb3JnZXQgbG9vcDsgY2FsbCBgc3RvcCgpYCB0byBlbmQgaXQuICovXG4gIHN1YnNjcmliZTxUPihvcHRzOiBTdWJzY3JpYmVPcHRpb25zPFQ+KTogRXZlbnRTdWJzY3JpcHRpb247XG59XG5cbi8qKlxuICogVGhlIHN1YnNldCBvZiBpb3JlZGlzJyBTdHJlYW0gQVBJIHRoZSBidXMgdXNlcy4gS2VwdCBtaW5pbWFsIHNvIGEgdGVzdCBjYW5cbiAqIHN1cHBseSBhbiBpbi1tZW1vcnkgZmFrZSBhbmQgc28gbWVyZWx5IGltcG9ydGluZyB0aGlzIG5ldmVyIGhhcmQtZGVwZW5kcyBvblxuICogaW9yZWRpcyAoY29uc3RydWN0ZWQgdmlhIHRoZSBzaGFyZWQgZW52IGhlbHBlcikuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgUmVkaXNTdHJlYW1DbGllbnQge1xuICB4YWRkKGtleTogc3RyaW5nLCAuLi5hcmdzOiAoc3RyaW5nIHwgbnVtYmVyKVtdKTogUHJvbWlzZTxzdHJpbmcgfCBudWxsPjtcbiAgeGdyb3VwKC4uLmFyZ3M6IChzdHJpbmcgfCBudW1iZXIpW10pOiBQcm9taXNlPHVua25vd24+O1xuICB4cmVhZGdyb3VwKC4uLmFyZ3M6IChzdHJpbmcgfCBudW1iZXIpW10pOiBQcm9taXNlPHVua25vd24+O1xuICB4YWNrKGtleTogc3RyaW5nLCBncm91cDogc3RyaW5nLCAuLi5pZHM6IHN0cmluZ1tdKTogUHJvbWlzZTxudW1iZXI+O1xuICB4YXV0b2NsYWltKC4uLmFyZ3M6IChzdHJpbmcgfCBudW1iZXIpW10pOiBQcm9taXNlPHVua25vd24+O1xuICB4cGVuZGluZyhrZXk6IHN0cmluZywgZ3JvdXA6IHN0cmluZywgLi4uYXJnczogKHN0cmluZyB8IG51bWJlcilbXSk6IFByb21pc2U8dW5rbm93bj47XG4gIHhyYW5nZShrZXk6IHN0cmluZywgc3RhcnQ6IHN0cmluZywgZW5kOiBzdHJpbmcsIC4uLmFyZ3M6IChzdHJpbmcgfCBudW1iZXIpW10pOiBQcm9taXNlPHVua25vd24+O1xuICAvKiogQSBuZXcgY29ubmVjdGlvbiB3aXRoIHRoZSBzYW1lIG9wdGlvbnMg4oCUIGVhY2ggc3Vic2NyaWJlciByZWFkcyBvbiBpdHMgb3duLiAqL1xuICBkdXBsaWNhdGUoKTogUmVkaXNTdHJlYW1DbGllbnQ7XG4gIHF1aXQ/KCk6IFByb21pc2U8dW5rbm93bj47XG4gIG9uPyhldmVudDogJ2Vycm9yJywgY2I6IChlcnI6IHVua25vd24pID0+IHZvaWQpOiB1bmtub3duO1xufVxuXG5jb25zdCBERUZBVUxUX01BWExFTiA9IDEwXzAwMDtcbmNvbnN0IERFRkFVTFRfQkFUQ0ggPSAxNjtcbmNvbnN0IERFRkFVTFRfQkxPQ0tfTVMgPSA1XzAwMDtcbmNvbnN0IERFRkFVTFRfTUlOX0lETEVfTVMgPSA2MF8wMDA7XG5jb25zdCBERUZBVUxUX01BWF9ERUxJVkVSSUVTID0gMTA7XG5cbmZ1bmN0aW9uIGVyck1zZyhlcnI6IHVua25vd24pOiBzdHJpbmcge1xuICByZXR1cm4gZXJyIGluc3RhbmNlb2YgRXJyb3IgPyBlcnIubWVzc2FnZSA6IFN0cmluZyhlcnIpO1xufVxuXG5mdW5jdGlvbiBzdHJlYW1LZXkodG9waWM6IHN0cmluZyk6IHN0cmluZyB7XG4gIHJldHVybiBgZXZ0OiR7dG9waWN9YDtcbn1cblxuLyoqIERlYWQtbGV0dGVyIHN0cmVhbSBmb3IgYSB0b3BpYy4gKi9cbmV4cG9ydCBmdW5jdGlvbiBkZWFkTGV0dGVyU3RyZWFtS2V5KHRvcGljOiBzdHJpbmcpOiBzdHJpbmcge1xuICByZXR1cm4gYGV2dDoke3RvcGljfTpkbHFgO1xufVxuXG4vKiogUHVibGlzaCB0aW1lIGZyb20gYSBzdHJlYW0gaWQgKGA8bXM+LTxzZXE+YCk7IGVwb2NoIDAgZm9yIGFuIHVucGFyc2VhYmxlIGlkLiAqL1xuZnVuY3Rpb24gcHVibGlzaGVkQXRGcm9tSWQoaWQ6IHN0cmluZyk6IERhdGUge1xuICBjb25zdCBtcyA9IE51bWJlcihpZC5zcGxpdCgnLScpWzBdKTtcbiAgcmV0dXJuIG5ldyBEYXRlKE51bWJlci5pc0Zpbml0ZShtcykgPyBtcyA6IDApO1xufVxuXG4vKiogVHJ1ZSB3aGVuIHRoZSBlcnJvciBpcyBSZWRpcycgXCJncm91cCBhbHJlYWR5IGV4aXN0c1wiIChpZGVtcG90ZW50IGNyZWF0ZSkuICovXG5mdW5jdGlvbiBpc0J1c3lHcm91cChlcnI6IHVua25vd24pOiBib29sZWFuIHtcbiAgcmV0dXJuIGVyck1zZyhlcnIpLmluY2x1ZGVzKCdCVVNZR1JPVVAnKTtcbn1cblxuLyoqXG4gKiBQYXJzZSB0aGUgbmVzdGVkIGFycmF5IHNoYXBlIFhSRUFER1JPVVAgLyBYQVVUT0NMQUlNIHJldHVybiBpbnRvIGZsYXQgZW52ZWxvcGVzLlxuICogWFJFQURHUk9VUDogYFtbc3RyZWFtS2V5LCBbW2lkLCBbZiwgdiwgLi4uXV0sIC4uLl1dXWAuXG4gKiBYQVVUT0NMQUlNOiBgW25leHRDdXJzb3IsIFtbaWQsIFtmLCB2LCAuLi5dXSwgLi4uXSwgZGVsZXRlZElkc11gLlxuICogV2Ugc3RvcmUgdGhlIEpTT04gcGF5bG9hZCB1bmRlciBhIHNpbmdsZSBmaWVsZCBgZGAuXG4gKi9cbmZ1bmN0aW9uIHBhcnNlRW50cmllczxUPih0b3BpYzogc3RyaW5nLCBlbnRyaWVzOiB1bmtub3duKTogRXZlbnRFbnZlbG9wZTxUPltdIHtcbiAgY29uc3Qgb3V0OiBFdmVudEVudmVsb3BlPFQ+W10gPSBbXTtcbiAgaWYgKCFBcnJheS5pc0FycmF5KGVudHJpZXMpKSByZXR1cm4gb3V0O1xuICBmb3IgKGNvbnN0IGVudHJ5IG9mIGVudHJpZXMpIHtcbiAgICBpZiAoIUFycmF5LmlzQXJyYXkoZW50cnkpIHx8IGVudHJ5Lmxlbmd0aCA8IDIpIGNvbnRpbnVlO1xuICAgIGNvbnN0IGlkID0gU3RyaW5nKGVudHJ5WzBdKTtcbiAgICBjb25zdCBmaWVsZHMgPSBlbnRyeVsxXTtcbiAgICBpZiAoIUFycmF5LmlzQXJyYXkoZmllbGRzKSkgY29udGludWU7XG4gICAgLy8gZmllbGRzIGlzIFtuYW1lLCB2YWx1ZSwgbmFtZSwgdmFsdWUsIC4uLl07IGZpbmQgJ2QnLlxuICAgIGxldCByYXc6IHN0cmluZyB8IHVuZGVmaW5lZDtcbiAgICBmb3IgKGxldCBpID0gMDsgaSArIDEgPCBmaWVsZHMubGVuZ3RoOyBpICs9IDIpIHtcbiAgICAgIGlmIChTdHJpbmcoZmllbGRzW2ldKSA9PT0gJ2QnKSB7IHJhdyA9IFN0cmluZyhmaWVsZHNbaSArIDFdKTsgYnJlYWs7IH1cbiAgICB9XG4gICAgLy8gQSBtaXNzaW5nIGBkYCBmaWVsZCAoYW4gZW50cnkgbm90IHdyaXR0ZW4gYnkgcHVibGlzaCgpKSBPUiBhIGNvcnJ1cHQgSlNPTlxuICAgIC8vIHBheWxvYWQgYm90aCB5aWVsZCBhbiB1bmRlZmluZWQtcGF5bG9hZCBlbnZlbG9wZSBzbyBgZGVsaXZlcigpYCBBQ0tzIGl0IOKAlFxuICAgIC8vIGEgcG9pc29uIG1lc3NhZ2UgbXVzdCBuZXZlciB3ZWRnZSB0aGUgZ3JvdXAgYnkgc3RheWluZyBwZXJwZXR1YWxseSBwZW5kaW5nLlxuICAgIGNvbnN0IHB1Ymxpc2hlZEF0ID0gcHVibGlzaGVkQXRGcm9tSWQoaWQpO1xuICAgIGlmIChyYXcgPT09IHVuZGVmaW5lZCkge1xuICAgICAgb3V0LnB1c2goeyBpZCwgdG9waWMsIHB1Ymxpc2hlZEF0LCBwYXlsb2FkOiB1bmRlZmluZWQgYXMgdW5rbm93biBhcyBUIH0pO1xuICAgICAgY29udGludWU7XG4gICAgfVxuICAgIHRyeSB7XG4gICAgICBvdXQucHVzaCh7IGlkLCB0b3BpYywgcHVibGlzaGVkQXQsIHBheWxvYWQ6IEpTT04ucGFyc2UocmF3KSBhcyBUIH0pO1xuICAgIH0gY2F0Y2gge1xuICAgICAgb3V0LnB1c2goeyBpZCwgdG9waWMsIHB1Ymxpc2hlZEF0LCBwYXlsb2FkOiB1bmRlZmluZWQgYXMgdW5rbm93biBhcyBUIH0pO1xuICAgIH1cbiAgfVxuICByZXR1cm4gb3V0O1xufVxuXG4vKiogQnVpbGQgYSBkdXJhYmxlIGV2ZW50IGJ1cyBvdmVyIGEgUmVkaXMgU3RyZWFtcyBjbGllbnQuICovXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlUmVkaXNEdXJhYmxlRXZlbnRCdXMoXG4gIHJlZGlzOiBSZWRpc1N0cmVhbUNsaWVudCxcbiAgb3B0czogeyBtYXhMZW4/OiBudW1iZXIgfSA9IHt9LFxuKTogRHVyYWJsZUV2ZW50QnVzIHtcbiAgY29uc3QgbWF4TGVuID0gTWF0aC5tYXgoMSwgb3B0cy5tYXhMZW4gPz8gREVGQVVMVF9NQVhMRU4pO1xuXG4gIHJldHVybiB7XG4gICAgYXN5bmMgcHVibGlzaDxUPih0b3BpYzogc3RyaW5nLCBwYXlsb2FkOiBUKTogUHJvbWlzZTxzdHJpbmcgfCBudWxsPiB7XG4gICAgICBjb25zdCBrZXkgPSBzdHJlYW1LZXkodG9waWMpO1xuICAgICAgdHJ5IHtcbiAgICAgICAgLy8gTUFYTEVOIH4gPG4+IGJvdW5kcyB0aGUgc3RyZWFtIGFwcHJveGltYXRlbHkgKGNoZWFwKTsgYCpgID0gc2VydmVyIGlkLlxuICAgICAgICBjb25zdCBpZCA9IGF3YWl0IHJlZGlzLnhhZGQoa2V5LCAnTUFYTEVOJywgJ34nLCBtYXhMZW4sICcqJywgJ2QnLCBKU09OLnN0cmluZ2lmeShwYXlsb2FkKSk7XG4gICAgICAgIGVtaXRDb3VudGVyKCdldmVudF9idXNfcHVibGlzaGVkX3RvdGFsJywgeyB0b3BpYyB9KTtcbiAgICAgICAgcmV0dXJuIGlkO1xuICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgIGVtaXRDb3VudGVyKCdldmVudF9idXNfcHVibGlzaF9mYWlsZWRfdG90YWwnLCB7IHRvcGljIH0pO1xuICAgICAgICBsb2dnZXIud2FybignRXZlbnQgYnVzIHB1Ymxpc2ggZmFpbGVkIChldmVudCBkcm9wcGVkKScsIHsgdG9waWMsIGVycm9yOiBlcnJNc2coZXJyKSB9KTtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICB9XG4gICAgfSxcblxuICAgIHN1YnNjcmliZTxUPihzdWJPcHRzOiBTdWJzY3JpYmVPcHRpb25zPFQ+KTogRXZlbnRTdWJzY3JpcHRpb24ge1xuICAgICAgY29uc3QgeyB0b3BpYywgZ3JvdXAsIGNvbnN1bWVyLCBoYW5kbGVyIH0gPSBzdWJPcHRzO1xuICAgICAgY29uc3Qga2V5ID0gc3RyZWFtS2V5KHRvcGljKTtcbiAgICAgIGNvbnN0IGRscUtleSA9IGRlYWRMZXR0ZXJTdHJlYW1LZXkodG9waWMpO1xuICAgICAgY29uc3QgYmF0Y2ggPSBNYXRoLm1heCgxLCBzdWJPcHRzLmJhdGNoU2l6ZSA/PyBERUZBVUxUX0JBVENIKTtcbiAgICAgIGNvbnN0IGJsb2NrTXMgPSBNYXRoLm1heCgwLCBzdWJPcHRzLmJsb2NrTXMgPz8gREVGQVVMVF9CTE9DS19NUyk7XG4gICAgICBjb25zdCBtaW5JZGxlID0gTWF0aC5tYXgoMCwgc3ViT3B0cy5taW5JZGxlTXMgPz8gREVGQVVMVF9NSU5fSURMRV9NUyk7XG4gICAgICBjb25zdCBtYXhEZWxpdmVyaWVzID0gTWF0aC5tYXgoMSwgc3ViT3B0cy5tYXhEZWxpdmVyaWVzID8/IERFRkFVTFRfTUFYX0RFTElWRVJJRVMpO1xuXG4gICAgICAvLyBgWFJFQURHUk9VUCBCTE9DS2AgaG9sZHMgaXRzIGNvbm5lY3Rpb24gZm9yIHVwIHRvIGBibG9ja01zYDsgb24gdGhlXG4gICAgICAvLyBzaGFyZWQgY2xpZW50IGV2ZXJ5IHB1Ymxpc2ggcXVldWVkIGJlaGluZCBpdC4gUmVhZCBvbiBhIGRlZGljYXRlZCBvbmUuXG4gICAgICBjb25zdCByZWFkZXIgPSByZWRpcy5kdXBsaWNhdGUoKTtcbiAgICAgIC8vIEEgZHVwbGljYXRlZCBpb3JlZGlzIGNvbm5lY3Rpb24gZG9lc24ndCBpbmhlcml0IGxpc3RlbmVyczsgd2l0aG91dCBvbmUgYVxuICAgICAgLy8gY29ubmVjdGlvbiBlcnJvciBpcyBhbiB1bmhhbmRsZWQgJ2Vycm9yJyBldmVudCB0aGF0IGNyYXNoZXMgdGhlIHByb2Nlc3MuXG4gICAgICByZWFkZXIub24/LignZXJyb3InLCAoZXJyKSA9PiBsb2dnZXIud2FybignRXZlbnQgYnVzIHJlYWRlciBjb25uZWN0aW9uIGVycm9yJywgeyB0b3BpYywgZ3JvdXAsIGVycm9yOiBlcnJNc2coZXJyKSB9KSk7XG5cbiAgICAgIGxldCBzdG9wcGVkID0gZmFsc2U7XG5cbiAgICAgIGNvbnN0IGRlbGl2ZXIgPSBhc3luYyAoZW52czogRXZlbnRFbnZlbG9wZTxUPltdKTogUHJvbWlzZTx2b2lkPiA9PiB7XG4gICAgICAgIGZvciAoY29uc3QgZW52IG9mIGVudnMpIHtcbiAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgaWYgKGVudi5wYXlsb2FkICE9PSB1bmRlZmluZWQpIGF3YWl0IGhhbmRsZXIoZW52KTtcbiAgICAgICAgICAgIC8vIEFjayBvbiBzdWNjZXNzIE9SIG9uIGFuIHVuZGVmaW5lZCAoY29ycnVwdCkgcGF5bG9hZCDigJQgYSBwb2lzb25cbiAgICAgICAgICAgIC8vIG1lc3NhZ2UgbXVzdCBub3QgYmxvY2sgdGhlIGdyb3VwIGZvcmV2ZXIuXG4gICAgICAgICAgICBhd2FpdCByZWFkZXIueGFjayhrZXksIGdyb3VwLCBlbnYuaWQpO1xuICAgICAgICAgICAgZW1pdENvdW50ZXIoJ2V2ZW50X2J1c19kZWxpdmVyZWRfdG90YWwnLCB7IHRvcGljLCBncm91cCB9KTtcbiAgICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgIC8vIExlYXZlIGl0IHBlbmRpbmcgKG5vIFhBQ0spIOKAlCBYQVVUT0NMQUlNIHJlZGVsaXZlcnMgaXQgYWZ0ZXIgbWluSWRsZS5cbiAgICAgICAgICAgIGVtaXRDb3VudGVyKCdldmVudF9idXNfaGFuZGxlcl9mYWlsZWRfdG90YWwnLCB7IHRvcGljLCBncm91cCB9KTtcbiAgICAgICAgICAgIGxvZ2dlci53YXJuKCdFdmVudCBoYW5kbGVyIGZhaWxlZDsgbGVhdmluZyBtZXNzYWdlIHBlbmRpbmcgZm9yIHJlZGVsaXZlcnknLCB7XG4gICAgICAgICAgICAgIHRvcGljLCBncm91cCwgaWQ6IGVudi5pZCwgZXJyb3I6IGVyck1zZyhlcnIpLFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9O1xuXG4gICAgICAvKipcbiAgICAgICAqIE1vdmUgZXZlcnkgaWRsZSBwZW5kaW5nIG1lc3NhZ2UgdGhhdCBoYXMgYWxyZWFkeSBiZWVuIGRlbGl2ZXJlZFxuICAgICAgICogYG1heERlbGl2ZXJpZXNgIHRpbWVzIHRvIHRoZSBkZWFkLWxldHRlciBzdHJlYW0gYW5kIGFjayBpdC4gVGhlIGVudHJ5XG4gICAgICAgKiBrZWVwcyBpdHMgcGF5bG9hZCBwbHVzIHdoZXJlIGl0IGNhbWUgZnJvbSwgc28gYW4gb3BlcmF0b3IgY2FuIGluc3BlY3Qgb3JcbiAgICAgICAqIHJlcGxheSBpdC4gSWYgY29weWluZyBmYWlscyB0aGUgbWVzc2FnZSBpcyBsZWZ0IHBlbmRpbmcgKHJldHJpZWQgbmV4dFxuICAgICAgICogcGFzcykg4oCUIGl0IGlzIG5ldmVyIGFja2VkIHdpdGhvdXQgYmVpbmcgcHJlc2VydmVkLlxuICAgICAgICovXG4gICAgICBjb25zdCBkZWFkTGV0dGVyRXhoYXVzdGVkID0gYXN5bmMgKCk6IFByb21pc2U8dm9pZD4gPT4ge1xuICAgICAgICBjb25zdCBwZW5kaW5nID0gYXdhaXQgcmVhZGVyLnhwZW5kaW5nKGtleSwgZ3JvdXAsICdJRExFJywgbWluSWRsZSwgJy0nLCAnKycsIGJhdGNoKTtcbiAgICAgICAgaWYgKCFBcnJheS5pc0FycmF5KHBlbmRpbmcpKSByZXR1cm47XG4gICAgICAgIGZvciAoY29uc3QgcCBvZiBwZW5kaW5nKSB7XG4gICAgICAgICAgaWYgKCFBcnJheS5pc0FycmF5KHApIHx8IHAubGVuZ3RoIDwgNCkgY29udGludWU7XG4gICAgICAgICAgY29uc3QgaWQgPSBTdHJpbmcocFswXSk7XG4gICAgICAgICAgY29uc3QgZGVsaXZlcmllcyA9IE51bWJlcihwWzNdKTtcbiAgICAgICAgICBpZiAoIShkZWxpdmVyaWVzID49IG1heERlbGl2ZXJpZXMpKSBjb250aW51ZTtcbiAgICAgICAgICBjb25zdCBlbnRyaWVzID0gYXdhaXQgcmVhZGVyLnhyYW5nZShrZXksIGlkLCBpZCk7XG4gICAgICAgICAgY29uc3QgZmllbGRzID0gQXJyYXkuaXNBcnJheShlbnRyaWVzKSAmJiBBcnJheS5pc0FycmF5KGVudHJpZXNbMF0pICYmIEFycmF5LmlzQXJyYXkoZW50cmllc1swXVsxXSkgPyBlbnRyaWVzWzBdWzFdIDogW107XG4gICAgICAgICAgbGV0IHJhdyA9ICcnO1xuICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpICsgMSA8IGZpZWxkcy5sZW5ndGg7IGkgKz0gMikge1xuICAgICAgICAgICAgaWYgKFN0cmluZyhmaWVsZHNbaV0pID09PSAnZCcpIHsgcmF3ID0gU3RyaW5nKGZpZWxkc1tpICsgMV0pOyBicmVhazsgfVxuICAgICAgICAgIH1cbiAgICAgICAgICBhd2FpdCByZWFkZXIueGFkZChcbiAgICAgICAgICAgIGRscUtleSwgJ01BWExFTicsICd+JywgbWF4TGVuLCAnKicsXG4gICAgICAgICAgICAnZCcsIHJhdywgJ3NvdXJjZUlkJywgaWQsICdncm91cCcsIGdyb3VwLCAnZGVsaXZlcmllcycsIGRlbGl2ZXJpZXMsXG4gICAgICAgICAgKTtcbiAgICAgICAgICBhd2FpdCByZWFkZXIueGFjayhrZXksIGdyb3VwLCBpZCk7XG4gICAgICAgICAgZW1pdENvdW50ZXIoJ2V2ZW50X2J1c19kZWFkX2xldHRlcmVkX3RvdGFsJywgeyB0b3BpYywgZ3JvdXAgfSk7XG4gICAgICAgICAgbG9nZ2VyLmVycm9yKCdFdmVudCBleGNlZWRlZCBtYXggZGVsaXZlcmllczsgbW92ZWQgdG8gZGVhZC1sZXR0ZXIgc3RyZWFtJywge1xuICAgICAgICAgICAgdG9waWMsIGdyb3VwLCBpZCwgZGVsaXZlcmllcywgZGVhZExldHRlclN0cmVhbTogZGxxS2V5LFxuICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICB9O1xuXG4gICAgICAvLyBUaGUgY29uc3VtZXIgZ3JvdXAgbXVzdCBleGlzdCBiZWZvcmUgWFJFQURHUk9VUCBjYW4gc3VjY2VlZC4gQ3JlYXRpbmcgaXRcbiAgICAgIC8vIGlzIHJldHJpZWQgaW5zaWRlIHRoZSBsb29wOiBhdCBzdGFydHVwIHRoZSBjbGllbnQgbWF5IG5vdCBoYXZlIGNvbm5lY3RlZFxuICAgICAgLy8geWV0LCBhbmQgYSBzaW5nbGUgZmFpbGVkIGF0dGVtcHQgdXNlZCB0byBsZWF2ZSB0aGUgY29uc3VtZXIgcmVhZGluZyBhXG4gICAgICAvLyBncm91cCB0aGF0IHdhcyBuZXZlciBjcmVhdGVkIOKAlCBmb3JldmVyLlxuICAgICAgbGV0IGdyb3VwUmVhZHkgPSBmYWxzZTtcbiAgICAgIGNvbnN0IGVuc3VyZUdyb3VwID0gYXN5bmMgKCk6IFByb21pc2U8dm9pZD4gPT4ge1xuICAgICAgICB0cnkge1xuICAgICAgICAgIC8vIE1LU1RSRUFNIHNvIHRoZSBzdHJlYW0gbmVlZCBub3QgZXhpc3QgeWV0OyAnJCcgPSBvbmx5IG5ldyBtZXNzYWdlcy5cbiAgICAgICAgICBhd2FpdCByZWFkZXIueGdyb3VwKCdDUkVBVEUnLCBrZXksIGdyb3VwLCAnJCcsICdNS1NUUkVBTScpO1xuICAgICAgICAgIGdyb3VwUmVhZHkgPSB0cnVlO1xuICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICBpZiAoIWlzQnVzeUdyb3VwKGVycikpIHRocm93IGVycjtcbiAgICAgICAgICBncm91cFJlYWR5ID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgfTtcblxuICAgICAgY29uc3QgbG9vcCA9IGFzeW5jICgpOiBQcm9taXNlPHZvaWQ+ID0+IHtcbiAgICAgICAgd2hpbGUgKCFzdG9wcGVkKSB7XG4gICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGlmICghZ3JvdXBSZWFkeSkgYXdhaXQgZW5zdXJlR3JvdXAoKTtcbiAgICAgICAgICAgIC8vIDEpIERlYWQtbGV0dGVyIG1lc3NhZ2VzIHRoYXQgaGF2ZSBleGhhdXN0ZWQgdGhlaXIgZGVsaXZlcmllcywgdGhlblxuICAgICAgICAgICAgLy8gICAgcmVjbGFpbSB0aGUgcmVzdCBzdHJhbmRlZCBieSBhIGZhaWxlZC9jcmFzaGVkIGNvbnN1bWVyLlxuICAgICAgICAgICAgYXdhaXQgZGVhZExldHRlckV4aGF1c3RlZCgpO1xuICAgICAgICAgICAgY29uc3QgY2xhaW1lZCA9IGF3YWl0IHJlYWRlci54YXV0b2NsYWltKGtleSwgZ3JvdXAsIGNvbnN1bWVyLCBtaW5JZGxlLCAnMCcsICdDT1VOVCcsIGJhdGNoKTtcbiAgICAgICAgICAgIC8vIFhBVVRPQ0xBSU0gcmVwbHk6IFtuZXh0Q3Vyc29yLCBlbnRyaWVzLCBkZWxldGVkSWRzXVxuICAgICAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkoY2xhaW1lZCkgJiYgY2xhaW1lZC5sZW5ndGggPj0gMikge1xuICAgICAgICAgICAgICBhd2FpdCBkZWxpdmVyKHBhcnNlRW50cmllczxUPih0b3BpYywgY2xhaW1lZFsxXSkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHN0b3BwZWQpIGJyZWFrO1xuXG4gICAgICAgICAgICAvLyAyKSBSZWFkIG5ldywgbmV2ZXItZGVsaXZlcmVkIG1lc3NhZ2VzIGZvciB0aGlzIGdyb3VwICgnPicpLlxuICAgICAgICAgICAgY29uc3QgcmVzID0gYXdhaXQgcmVhZGVyLnhyZWFkZ3JvdXAoXG4gICAgICAgICAgICAgICdHUk9VUCcsIGdyb3VwLCBjb25zdW1lciwgJ0NPVU5UJywgYmF0Y2gsICdCTE9DSycsIGJsb2NrTXMsICdTVFJFQU1TJywga2V5LCAnPicsXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgLy8gWFJFQURHUk9VUCByZXBseTogW1tzdHJlYW1LZXksIGVudHJpZXNdXSB8IG51bGwgKG9uIGJsb2NrIHRpbWVvdXQpXG4gICAgICAgICAgICBpZiAoQXJyYXkuaXNBcnJheShyZXMpICYmIHJlcy5sZW5ndGggPiAwICYmIEFycmF5LmlzQXJyYXkocmVzWzBdKSAmJiByZXNbMF0ubGVuZ3RoID49IDIpIHtcbiAgICAgICAgICAgICAgYXdhaXQgZGVsaXZlcihwYXJzZUVudHJpZXM8VD4odG9waWMsIHJlc1swXVsxXSkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgaWYgKHN0b3BwZWQpIGJyZWFrO1xuICAgICAgICAgICAgLy8gVGhlIHN0cmVhbSBvciBncm91cCB3YXMgZGVsZXRlZCBvdXQgZnJvbSB1bmRlciB1cyDigJQgcmVjcmVhdGUgaXQuXG4gICAgICAgICAgICBpZiAoL05PR1JPVVAvaS50ZXN0KGVyck1zZyhlcnIpKSkgZ3JvdXBSZWFkeSA9IGZhbHNlO1xuICAgICAgICAgICAgbG9nZ2VyLndhcm4oJ0V2ZW50IGJ1cyBjb25zdW1lciBsb29wIGVycm9yOyBiYWNraW5nIG9mZicsIHsgdG9waWMsIGdyb3VwLCBlcnJvcjogZXJyTXNnKGVycikgfSk7XG4gICAgICAgICAgICAvLyBCYWNrIG9mZiBzbyBhIHBlcnNpc3RlbnQgUmVkaXMgZXJyb3IgZG9lc24ndCBob3Qtc3Bpbi5cbiAgICAgICAgICAgIGF3YWl0IG5ldyBQcm9taXNlKChyKSA9PiBzZXRUaW1lb3V0KHIsIDEwMDApKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IGxvb3BQcm9taXNlID0gbG9vcCgpO1xuICAgICAgbG9nZ2VyLmluZm8oJ0V2ZW50IGJ1cyBjb25zdW1lciBzdGFydGVkJywgeyB0b3BpYywgZ3JvdXAsIGNvbnN1bWVyLCBtYXhEZWxpdmVyaWVzIH0pO1xuXG4gICAgICByZXR1cm4ge1xuICAgICAgICBhc3luYyBzdG9wKCk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICAgIHN0b3BwZWQgPSB0cnVlO1xuICAgICAgICAgIC8vIEF3YWl0IHRoZSBpbi1mbGlnaHQgcmVhZC9oYW5kbGVyIHNvIGEgY2FsbGVyIChlLmcuIGEgc2VydmljZSBzaHV0dGluZ1xuICAgICAgICAgIC8vIGRvd24gaXRzIERCKSBkb2Vzbid0IHJhY2UgYSBtZXNzYWdlIHN0aWxsIGJlaW5nIHByb2Nlc3NlZC4gQm91bmRlZCBieVxuICAgICAgICAgIC8vIHRoZSBYUkVBREdST1VQIEJMT0NLIHdpbmRvdy4gTmV2ZXIgcmVqZWN0cyDigJQgdGhlIGxvb3Agc3dhbGxvd3MgZXJyb3JzLlxuICAgICAgICAgIGF3YWl0IGxvb3BQcm9taXNlLmNhdGNoKCgpID0+IHVuZGVmaW5lZCk7XG4gICAgICAgICAgYXdhaXQgUHJvbWlzZS5yZXNvbHZlKHJlYWRlci5xdWl0Py4oKSkuY2F0Y2goKCkgPT4gdW5kZWZpbmVkKTtcbiAgICAgICAgfSxcbiAgICAgIH07XG4gICAgfSxcbiAgfTtcbn1cblxuLyoqXG4gKiBCdWlsZCBhIGR1cmFibGUgZXZlbnQgYnVzIGZyb20gdGhlIGFtYmllbnQgUmVkaXMgZW52IHZpYSB0aGUgc2hhcmVkXG4gKiBgY3JlYXRlRW52UmVkaXNDbGllbnRgLiBSZXR1cm5zIGBudWxsYCB3aGVuIFJlZGlzIGlzIG5vdCBjb25maWd1cmVkIOKAlCB0aGVcbiAqIGNhbGxlciB0aGVuIHJ1bnMgd2l0aG91dCBhIGJ1cyAodG9kYXkncyBIVFRQL3JlY29uY2lsZXIgYmVoYXZpb3IpLCBuZXZlclxuICogY3Jhc2hpbmcuIE9wdCBpbiB3aXRoIGEgc2luZ2xlIGJvb3QgbGluZSB3aGVyZSBhIHNlcnZpY2Ugd2FudHMgZHVyYWJsZSBldmVudHMuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVFbnZSZWRpc0R1cmFibGVFdmVudEJ1cyhvcHRzOiB7IG1heExlbj86IG51bWJlciB9ID0ge30pOiBEdXJhYmxlRXZlbnRCdXMgfCBudWxsIHtcbiAgY29uc3QgaW5zdCA9IGNyZWF0ZUVudlJlZGlzQ2xpZW50PFJlZGlzU3RyZWFtQ2xpZW50PignZXZlbnQtYnVzJyk7XG4gIGlmICghaW5zdCkgcmV0dXJuIG51bGw7XG4gIGxvZ2dlci5pbmZvKCdSZWRpcyBkdXJhYmxlIGV2ZW50IGJ1cyBpbml0aWFsaXplZCcpO1xuICByZXR1cm4gY3JlYXRlUmVkaXNEdXJhYmxlRXZlbnRCdXMoaW5zdCwgb3B0cyk7XG59XG4iXX0=
@@ -94,3 +94,30 @@ export interface ReadyAwareRedis {
94
94
  * (e.g. a test double) counts as ready.
95
95
  */
96
96
  export declare function whenRedisReady(client: ReadyAwareRedis, timeoutMs?: number): Promise<void>;
97
+ /** Default bound for {@link createRedisReadyGate}: short enough for a request path. */
98
+ export declare const REQUEST_PATH_REDIS_READY_TIMEOUT_MS = 2000;
99
+ /**
100
+ * A request-path readiness gate for a lazily built env Redis client.
101
+ *
102
+ * The env client has no offline queue, so a command issued before the first
103
+ * connection completes is rejected outright — the first request after a lazy
104
+ * construction would otherwise hit that rejection (e.g. the first step-up per
105
+ * pod failing, or the first impersonation check reading "unavailable").
106
+ *
107
+ * The returned function resolves once the client is ready, or after
108
+ * `timeoutMs` — it NEVER rejects: the caller then runs its command and keeps its
109
+ * own fail-open / fail-closed semantics. Concurrent callers share one wait. After
110
+ * a wait times out (Redis genuinely down) later calls stop waiting until the
111
+ * client reports `ready` again, so an outage costs one bounded wait instead of
112
+ * adding `timeoutMs` to every request.
113
+ */
114
+ export declare function createRedisReadyGate(client: ReadyAwareRedis, timeoutMs?: number): () => Promise<void>;
115
+ /** The subset of ioredis needed by {@link incrWindow}. */
116
+ export interface RedisEvalClient {
117
+ eval(script: string, numKeys: number, ...args: (string | number)[]): Promise<unknown>;
118
+ }
119
+ /**
120
+ * Increment `key` within a window of `windowMs` and return the new count.
121
+ * Throws when Redis errors — callers choose their own failure policy.
122
+ */
123
+ export declare function incrWindow(redis: RedisEvalClient, key: string, windowMs: number): Promise<number>;