@blokjs/trigger-webhook 0.2.1 → 0.6.2

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.
@@ -1,355 +1,354 @@
1
- "use strict";
2
1
  /**
3
- * WebhookTrigger - Handle webhook events from external services
2
+ * WebhookTrigger v0.7 PR 4 — Inbound webhook trigger that mounts
3
+ * verified POST routes on the shared Hono app. One route per workflow
4
+ * whose `trigger.webhook` config is registered.
4
5
  *
5
- * Extends TriggerBase to process webhook events from:
6
- * - GitHub (push, pull_request, issues, etc.)
7
- * - Stripe (payment_intent, checkout.session, etc.)
8
- * - Shopify (orders, products, customers)
9
- * - Custom webhooks
6
+ * **Authoring surface (built-in provider):**
10
7
  *
11
- * Features:
12
- * - Signature verification for security
13
- * - Event type filtering
14
- * - Retry support
15
- * - Dead letter handling
16
- */
17
- var __importDefault = (this && this.__importDefault) || function (mod) {
18
- return (mod && mod.__esModule) ? mod : { "default": mod };
19
- };
20
- Object.defineProperty(exports, "__esModule", { value: true });
21
- exports.sourceHandlers = exports.WebhookTrigger = void 0;
22
- const node_crypto_1 = __importDefault(require("node:crypto"));
23
- const runner_1 = require("@blok/runner");
24
- const api_1 = require("@opentelemetry/api");
25
- const uuid_1 = require("uuid");
26
- /**
27
- * Built-in source handlers
28
- */
29
- const sourceHandlers = {
30
- github: {
31
- getEventType: (headers) => headers["x-github-event"] || "unknown",
32
- getSignature: (headers) => headers["x-hub-signature-256"] || headers["x-hub-signature"],
33
- verifySignature: (rawBody, signature, secret) => {
34
- const hmac = node_crypto_1.default.createHmac("sha256", secret);
35
- const digest = `sha256=${hmac.update(rawBody).digest("hex")}`;
36
- const sigBuffer = Buffer.from(signature);
37
- const digestBuffer = Buffer.from(digest);
38
- // Length check first to avoid timing attack on length
39
- if (sigBuffer.length !== digestBuffer.length) {
40
- return { valid: false, error: "Invalid GitHub signature" };
41
- }
42
- const valid = node_crypto_1.default.timingSafeEqual(sigBuffer, digestBuffer);
43
- return { valid, error: valid ? undefined : "Invalid GitHub signature" };
44
- },
45
- getEventId: (headers) => headers["x-github-delivery"] || (0, uuid_1.v4)(),
46
- },
47
- stripe: {
48
- getEventType: (_, body) => body?.type || "unknown",
49
- getSignature: (headers) => headers["stripe-signature"],
50
- verifySignature: (rawBody, signature, secret) => {
51
- // Stripe signature format: t=timestamp,v1=signature
52
- const parts = signature.split(",").reduce((acc, part) => {
53
- const [key, value] = part.split("=");
54
- acc[key] = value;
55
- return acc;
56
- }, {});
57
- const timestamp = parts.t;
58
- const expectedSig = parts.v1;
59
- if (!timestamp || !expectedSig) {
60
- return { valid: false, error: "Invalid Stripe signature format" };
61
- }
62
- const payload = `${timestamp}.${rawBody}`;
63
- const hmac = node_crypto_1.default.createHmac("sha256", secret);
64
- const computedSig = hmac.update(payload).digest("hex");
65
- const sigBuffer = Buffer.from(expectedSig);
66
- const computedBuffer = Buffer.from(computedSig);
67
- if (sigBuffer.length !== computedBuffer.length) {
68
- return { valid: false, error: "Invalid Stripe signature" };
69
- }
70
- const valid = node_crypto_1.default.timingSafeEqual(sigBuffer, computedBuffer);
71
- return { valid, error: valid ? undefined : "Invalid Stripe signature" };
72
- },
73
- getEventId: (_, body) => body?.id || (0, uuid_1.v4)(),
74
- },
75
- shopify: {
76
- getEventType: (headers) => headers["x-shopify-topic"] || "unknown",
77
- getSignature: (headers) => headers["x-shopify-hmac-sha256"],
78
- verifySignature: (rawBody, signature, secret) => {
79
- const hmac = node_crypto_1.default.createHmac("sha256", secret);
80
- const digest = hmac.update(rawBody, "utf8").digest("base64");
81
- const sigBuffer = Buffer.from(signature, "base64");
82
- const digestBuffer = Buffer.from(digest, "base64");
83
- if (sigBuffer.length !== digestBuffer.length) {
84
- return { valid: false, error: "Invalid Shopify signature" };
85
- }
86
- const valid = node_crypto_1.default.timingSafeEqual(sigBuffer, digestBuffer);
87
- return { valid, error: valid ? undefined : "Invalid Shopify signature" };
88
- },
89
- getEventId: (headers) => headers["x-shopify-webhook-id"] || (0, uuid_1.v4)(),
90
- },
91
- custom: {
92
- getEventType: (headers, body) => headers["x-event-type"] || body?.event || "custom",
93
- getSignature: (headers) => headers["x-signature"] || headers["x-webhook-signature"],
94
- verifySignature: (rawBody, signature, secret) => {
95
- // Default: HMAC-SHA256
96
- const hmac = node_crypto_1.default.createHmac("sha256", secret);
97
- const digest = hmac.update(rawBody).digest("hex");
98
- const valid = signature === digest || signature === `sha256=${digest}`;
99
- return { valid, error: valid ? undefined : "Invalid signature" };
100
- },
101
- getEventId: (headers, body) => headers["x-event-id"] || body?.id || (0, uuid_1.v4)(),
102
- },
103
- };
104
- exports.sourceHandlers = sourceHandlers;
105
- /**
106
- * WebhookTrigger - Handle webhook events
8
+ * ```json
9
+ * {
10
+ * "name": "stripe-events",
11
+ * "trigger": {
12
+ * "webhook": {
13
+ * "provider": "stripe",
14
+ * "path": "/webhooks/stripe",
15
+ * "secretEnv": "STRIPE_WEBHOOK_SECRET",
16
+ * "namespace": "stripe",
17
+ * "idempotencyKey": "js/ctx.request.body.id"
18
+ * }
19
+ * },
20
+ * "steps": [
21
+ * { "id": "dispatch", "subworkflow": "js/ctx.request.body.type", "inputs": { "stripeEvent": "js/ctx.request.body" } }
22
+ * ]
23
+ * }
24
+ * ```
25
+ *
26
+ * **Pipeline (per inbound request):**
27
+ *
28
+ * 1. Read raw body — verifiers MUST sign the bytes that crossed
29
+ * the wire, not the JSON-re-stringified body (Stripe / GitHub /
30
+ * Slack all sign raw bytes).
31
+ * 2. Verify the signature via the per-provider strategy
32
+ * (`verifiers.ts`). On failure, return 401 with structured
33
+ * `{ error, reason, message }`.
34
+ * 3. Replay check: if `idempotencyKey` is configured, look up
35
+ * `(workflowName, eventId)` in the idempotency cache (same store
36
+ * as Tier 1 step caching). On hit, return 200 with
37
+ * `{ status: "duplicate", eventId }` and DON'T run the workflow.
38
+ * 4. Events allowlist: if `events: [...]` is configured, skip
39
+ * workflow runs whose event type isn't in the list — return
40
+ * 200 with `{ status: "ignored", eventType }` so the sender
41
+ * doesn't retry.
42
+ * 5. Run the workflow through `TriggerBase.run` so middleware,
43
+ * tracing, retries, concurrency, etc. apply uniformly.
44
+ * 6. Cache the eventId so a retry within the TTL window returns
45
+ * the duplicate response.
46
+ *
47
+ * **Hono integration:** identical to WebSocket and SSE — accepts the
48
+ * shared `Hono<any, any, any>` app and an optional `HttpTriggerLike`
49
+ * exposing `addPreCatchAllHook` so webhook routes mount BEFORE the
50
+ * legacy `/:workflow{.+}` catch-all and win Hono's first-match
51
+ * dispatch.
52
+ *
53
+ * See [additional-triggers-plan.mdx](../../../docs/c/devtools/additional-triggers-plan.mdx#webhook-trigger)
54
+ * for the full v0.7 design.
107
55
  */
108
- class WebhookTrigger extends runner_1.TriggerBase {
56
+ import { DefaultLogger, RunTracker, TriggerBase, WorkflowRegistry, } from "@blokjs/runner";
57
+ import { SpanStatusCode, metrics, trace } from "@opentelemetry/api";
58
+ import { v4 as uuid } from "uuid";
59
+ import { BUILTIN_VERIFIERS, buildCustomVerifier } from "./verifiers";
60
+ const DEFAULT_TOLERANCE_SEC = 300;
61
+ const DEFAULT_REPLAY_TTL_MS = 5 * 60 * 1000; // 5 min — match Stripe / Svix default.
62
+ const REPLAY_NAMESPACE = "__webhook__";
63
+ // -----------------------------------------------------------------------------
64
+ // Trigger class
65
+ // -----------------------------------------------------------------------------
66
+ export default class WebhookTrigger extends TriggerBase {
109
67
  nodeMap = {};
110
- tracer = api_1.trace.getTracer(process.env.PROJECT_NAME || "trigger-webhook-workflow", process.env.PROJECT_VERSION || "0.0.1");
111
- logger = new runner_1.DefaultLogger();
112
- webhookWorkflows = [];
113
- constructor() {
68
+ logger = new DefaultLogger();
69
+ tracer = trace.getTracer(process.env.PROJECT_NAME || "trigger-webhook-workflow", process.env.PROJECT_VERSION || "0.0.1");
70
+ meter = metrics.getMeter("blok");
71
+ counterReceived = this.meter.createCounter("blok_webhook_received_total", {
72
+ description: "Webhook deliveries received (cumulative).",
73
+ unit: "1",
74
+ });
75
+ counterRejected = this.meter.createCounter("blok_webhook_rejected_total", {
76
+ description: "Webhook deliveries rejected (signature failure, allowlist miss, replay).",
77
+ unit: "1",
78
+ });
79
+ counterAccepted = this.meter.createCounter("blok_webhook_accepted_total", {
80
+ description: "Webhook deliveries that triggered a workflow run.",
81
+ unit: "1",
82
+ });
83
+ // biome-ignore lint/suspicious/noExplicitAny: Hono's generic propagation
84
+ app;
85
+ httpTrigger;
86
+ wired = false;
87
+ // biome-ignore lint/suspicious/noExplicitAny: matches `app` field's any generic
88
+ constructor(app, httpTrigger) {
114
89
  super();
115
- this.loadNodes();
116
- this.loadWorkflows();
117
- }
118
- /**
119
- * Load nodes into the node map
120
- */
121
- loadNodes() {
122
- this.nodeMap.nodes = new runner_1.NodeMap();
123
- const nodeKeys = Object.keys(this.nodes);
124
- for (const key of nodeKeys) {
125
- this.nodeMap.nodes.addNode(key, this.nodes[key]);
126
- }
90
+ this.app = app;
91
+ this.httpTrigger = httpTrigger ?? null;
92
+ _setActiveWebhookTrigger(this);
127
93
  }
128
94
  /**
129
- * Load workflows into the workflow map
95
+ * Inject the runner's GlobalOptions (nodes + workflows). Called by
96
+ * the orchestrator AFTER constructing the trigger but BEFORE
97
+ * `listen()`. Shares HttpTrigger's nodeMap so per-request workflow
98
+ * runs resolve helpers + sub-workflows through the same registry.
130
99
  */
131
- loadWorkflows() {
132
- this.nodeMap.workflows = this.workflows;
100
+ setNodeMap(nodeMap) {
101
+ this.nodeMap = nodeMap;
133
102
  }
134
- /**
135
- * Initialize webhook trigger (call after loading workflows)
136
- */
137
103
  async listen() {
138
104
  const startTime = this.startCounter();
139
- // Find all workflows with webhook triggers
140
- this.webhookWorkflows = this.getWebhookWorkflows();
141
- if (this.webhookWorkflows.length === 0) {
142
- this.logger.log("No workflows with webhook triggers found");
105
+ if (this.wired) {
106
+ this.logger.log("[blok][webhook] listen() called twice; ignoring");
107
+ return this.endCounter(startTime);
143
108
  }
144
- else {
145
- this.logger.log(`Webhook trigger initialized. ${this.webhookWorkflows.length} workflow(s) registered`);
109
+ this.wired = true;
110
+ if (this.httpTrigger) {
111
+ this.httpTrigger.addPreCatchAllHook(() => {
112
+ this.registerRoutesFromRegistry();
113
+ });
146
114
  }
147
- // Enable HMR in development mode
148
- if (process.env.BLOK_HMR === "true" || process.env.NODE_ENV === "development") {
149
- await this.enableHotReload();
115
+ else {
116
+ this.registerRoutesFromRegistry();
150
117
  }
151
118
  return this.endCounter(startTime);
152
119
  }
153
- /**
154
- * Stop the webhook trigger
155
- */
156
120
  async stop() {
157
- this.webhookWorkflows = [];
158
- this.logger.log("Webhook trigger stopped");
121
+ this.wired = false;
122
+ if (_getActiveWebhookTrigger() === this)
123
+ _setActiveWebhookTrigger(null);
124
+ this.destroyMonitoring();
125
+ this.logger.log("[blok][webhook] stopped");
159
126
  }
160
- async onHmrWorkflowChange() {
161
- this.loadWorkflows();
162
- this.webhookWorkflows = this.getWebhookWorkflows();
163
- this.logger.log(`[HMR] Webhook workflows reloaded. ${this.webhookWorkflows.length} workflow(s) registered`);
127
+ // ---------------------------------------------------------------------------
128
+ // Route registration
129
+ // ---------------------------------------------------------------------------
130
+ registerRoutesFromRegistry() {
131
+ const workflows = this.getWebhookWorkflows();
132
+ if (workflows.length === 0) {
133
+ this.logger.log("[blok][webhook] no workflows with trigger.webhook found");
134
+ return;
135
+ }
136
+ this.logger.log(`[blok][webhook] registering ${workflows.length} webhook route(s):`);
137
+ for (const entry of workflows) {
138
+ this.registerWebhookRoute(entry);
139
+ }
164
140
  }
165
- /**
166
- * Process an incoming webhook request
167
- * Call this from your HTTP endpoint handler
168
- */
169
- async handleWebhook(source, rawBody, headers) {
170
- const handler = sourceHandlers[source] || sourceHandlers.custom;
171
- // Parse body
172
- let body;
173
- try {
174
- body = JSON.parse(rawBody);
141
+ registerWebhookRoute(entry) {
142
+ const { workflowName, config } = entry;
143
+ const path = config.path ?? (config.provider ? `/webhooks/${config.provider}` : `/webhooks/${workflowName}`);
144
+ const label = config.provider ?? "custom";
145
+ this.logger.log(`[blok][webhook] POST ${path} ← ${workflowName} (${label})`);
146
+ this.app.post(path, (c) => this.handleRequest(c, workflowName, path, config));
147
+ }
148
+ async handleRequest(c, workflowName, path, config) {
149
+ this.counterReceived.add(1, { workflow_name: workflowName });
150
+ // 1. Capture raw body BEFORE parsing — verifiers sign the wire bytes.
151
+ const rawBody = await c.req.text();
152
+ let parsedBody = {};
153
+ if (rawBody.length > 0) {
154
+ try {
155
+ parsedBody = JSON.parse(rawBody);
156
+ }
157
+ catch {
158
+ // Non-JSON body — leave parsed as the raw text. Slack
159
+ // challenges & Shopify can post non-JSON occasionally.
160
+ parsedBody = rawBody;
161
+ }
175
162
  }
176
- catch {
177
- body = rawBody;
163
+ const headers = Object.fromEntries(c.req.raw.headers);
164
+ const pathParams = c.req.param();
165
+ const queryParams = Object.fromEntries(new URL(c.req.url).searchParams);
166
+ // 2. Pick the verifier.
167
+ const verifier = this.resolveVerifier(workflowName, config);
168
+ if (!verifier) {
169
+ this.counterRejected.add(1, { workflow_name: workflowName, reason: "no_verifier" });
170
+ return c.json({ error: "Configuration", reason: "no_verifier", message: "No verifier configured" }, 500);
178
171
  }
179
- // Create webhook event
180
- const event = {
181
- id: handler.getEventId(headers, body),
182
- source,
183
- eventType: handler.getEventType(headers, body),
184
- payload: body,
172
+ // 3. Resolve the secret from the env var.
173
+ const secretEnv = config.secretEnv ?? config.signature?.secretEnv;
174
+ const secret = secretEnv ? (process.env[secretEnv] ?? "") : "";
175
+ // 4. Verify.
176
+ const toleranceSec = config.tolerance ?? config.signature?.tolerance ?? DEFAULT_TOLERANCE_SEC;
177
+ const result = verifier.verify({
185
178
  headers,
186
- signature: handler.getSignature(headers),
187
- timestamp: new Date(),
188
179
  rawBody,
189
- };
190
- // Find matching workflow
191
- const workflow = this.findMatchingWorkflow(event);
192
- if (!workflow) {
193
- this.logger.log(`No matching workflow for webhook: ${source}/${event.eventType}`);
194
- return null;
180
+ parsedBody,
181
+ secret,
182
+ toleranceSec,
183
+ });
184
+ if (!result.ok) {
185
+ this.counterRejected.add(1, { workflow_name: workflowName, reason: result.reason });
186
+ this.logger.error(`[blok][webhook] ${workflowName}: verify failed reason=${result.reason} message="${result.message}"`);
187
+ return c.json({ error: "Unauthorized", reason: result.reason, message: result.message }, 401);
188
+ }
189
+ // 5. Events allowlist — verified-but-out-of-scope returns 200 (no retry).
190
+ if (Array.isArray(config.events) && config.events.length > 0 && !config.events.includes(result.eventType)) {
191
+ this.counterRejected.add(1, { workflow_name: workflowName, reason: "event_not_allowed" });
192
+ return c.json({ status: "ignored", reason: "event_not_allowed", eventType: result.eventType }, 200);
195
193
  }
196
- const config = workflow.config.trigger?.webhook;
197
- // Verify signature if secret is configured
198
- if (config.secret && event.signature) {
199
- const verification = handler.verifySignature(rawBody, event.signature, config.secret);
200
- if (!verification.valid) {
201
- this.logger.error(`Webhook signature verification failed: ${verification.error}`);
202
- throw new Error(`Signature verification failed: ${verification.error}`);
194
+ // 6. Replay protection via the idempotency cache.
195
+ if (config.idempotencyKey && result.eventId) {
196
+ const tracker = RunTracker.getInstance();
197
+ const store = tracker.getStore();
198
+ const cached = store.getIdempotencyCache(REPLAY_NAMESPACE, workflowName, result.eventId);
199
+ if (cached) {
200
+ this.counterRejected.add(1, { workflow_name: workflowName, reason: "replay" });
201
+ return c.json({
202
+ status: "duplicate",
203
+ eventId: result.eventId,
204
+ eventType: result.eventType,
205
+ firstSeenRunId: cached.sourceRunId,
206
+ }, 200);
203
207
  }
204
208
  }
205
- else if (config.secret && !event.signature) {
206
- this.logger.error("Webhook signature missing but secret is configured");
207
- throw new Error("Signature missing");
209
+ // 7. Verified + new event — dispatch the workflow.
210
+ this.counterAccepted.add(1, { workflow_name: workflowName });
211
+ const requestId = uuid();
212
+ const dispatchOutcome = await this.dispatchWorkflow({
213
+ workflowName,
214
+ path,
215
+ config,
216
+ requestId,
217
+ headers,
218
+ body: parsedBody,
219
+ rawBody,
220
+ pathParams,
221
+ queryParams,
222
+ eventId: result.eventId,
223
+ eventType: result.eventType,
224
+ });
225
+ // 8. Cache event id AFTER successful dispatch so retries on the
226
+ // same delivery are deduped. We cache even on workflow failure
227
+ // — webhook senders should not retry deliveries they've
228
+ // already delivered (the workflow's own retry / DLQ owns that).
229
+ if (config.idempotencyKey && result.eventId) {
230
+ const tracker = RunTracker.getInstance();
231
+ const store = tracker.getStore();
232
+ store.setIdempotencyCache(REPLAY_NAMESPACE, workflowName, result.eventId, {
233
+ data: { eventId: result.eventId, eventType: result.eventType },
234
+ cachedAt: Date.now(),
235
+ expiresAt: Date.now() + DEFAULT_REPLAY_TTL_MS,
236
+ sourceRunId: requestId,
237
+ sourceNodeRunId: requestId,
238
+ });
208
239
  }
209
- return this.executeWorkflow(event, workflow, config);
240
+ // 9. Shape the response. Workflow's `ctx.response` lands in the
241
+ // body for parity with HTTP triggers.
242
+ return c.json({
243
+ status: "ok",
244
+ eventId: result.eventId,
245
+ eventType: result.eventType,
246
+ runId: requestId,
247
+ response: dispatchOutcome,
248
+ }, 200);
210
249
  }
211
- /**
212
- * Get all workflows that have webhook triggers
213
- */
214
- getWebhookWorkflows() {
215
- const workflows = [];
216
- for (const [path, workflow] of Object.entries(this.nodeMap.workflows || {})) {
217
- const workflowConfig = workflow._config;
218
- if (workflowConfig?.trigger) {
219
- const triggerType = Object.keys(workflowConfig.trigger)[0];
220
- if (triggerType === "webhook" && workflowConfig.trigger.webhook) {
221
- workflows.push({
222
- path,
223
- config: workflowConfig,
224
- });
225
- }
250
+ resolveVerifier(workflowName, config) {
251
+ if (config.provider) {
252
+ const v = BUILTIN_VERIFIERS[config.provider];
253
+ if (!v) {
254
+ this.logger.error(`[blok][webhook] ${workflowName}: unknown provider "${config.provider}"`);
255
+ return null;
226
256
  }
257
+ return v;
227
258
  }
228
- return workflows;
229
- }
230
- /**
231
- * Find workflow matching the webhook event
232
- */
233
- findMatchingWorkflow(event) {
234
- for (const workflow of this.webhookWorkflows) {
235
- const config = workflow.config.trigger?.webhook;
236
- if (!config)
237
- continue;
238
- // Check source match
239
- if (config.source !== event.source)
240
- continue;
241
- // Check event type match
242
- if (config.events && config.events.length > 0) {
243
- const matches = config.events.some((pattern) => {
244
- // Support wildcards (e.g., "push", "pull_request.*")
245
- if (pattern === "*")
246
- return true;
247
- if (pattern.endsWith(".*")) {
248
- const prefix = pattern.slice(0, -2);
249
- return event.eventType.startsWith(prefix);
250
- }
251
- return pattern === event.eventType;
252
- });
253
- if (!matches)
254
- continue;
255
- }
256
- return workflow;
259
+ if (config.signature) {
260
+ return buildCustomVerifier({
261
+ scheme: config.signature.scheme ?? "hmac-sha256",
262
+ header: config.signature.header,
263
+ format: config.signature.format ?? "{hex}",
264
+ secretEnv: config.signature.secretEnv,
265
+ tolerance: config.signature.tolerance ?? DEFAULT_TOLERANCE_SEC,
266
+ timestampHeader: config.signature.timestampHeader,
267
+ });
257
268
  }
258
269
  return null;
259
270
  }
260
- /**
261
- * Execute a workflow for a webhook event
262
- */
263
- async executeWorkflow(event, workflow, _config) {
264
- const executionId = (0, uuid_1.v4)();
265
- const defaultMeter = api_1.metrics.getMeter("default");
266
- const webhookExecutions = defaultMeter.createCounter("webhook_executions", {
267
- description: "Webhook executions",
268
- });
269
- const webhookErrors = defaultMeter.createCounter("webhook_errors", {
270
- description: "Webhook execution errors",
271
- });
272
- return new Promise((resolve) => {
273
- this.tracer.startActiveSpan(`webhook:${event.source}/${event.eventType}`, async (span) => {
274
- try {
275
- const start = performance.now();
276
- // Initialize configuration for this workflow
277
- await this.configuration.init(workflow.path, this.nodeMap);
278
- // Create context
279
- const ctx = this.createContext(undefined, workflow.path, executionId);
280
- // Populate request with webhook event
281
- ctx.request = {
282
- body: event.payload,
283
- headers: event.headers,
284
- query: {},
285
- params: {
286
- source: event.source,
287
- eventType: event.eventType,
288
- eventId: event.id,
289
- },
290
- };
291
- // Store webhook context in vars
292
- if (!ctx.vars)
293
- ctx.vars = {};
294
- ctx.vars._webhook_event = {
295
- id: event.id,
296
- source: event.source,
297
- eventType: event.eventType,
298
- timestamp: event.timestamp.toISOString(),
299
- hasSignature: String(!!event.signature),
300
- };
301
- ctx.logger.log(`Processing webhook: ${event.source}/${event.eventType} (${event.id})`);
302
- // Execute workflow
303
- const response = await this.run(ctx);
304
- const end = performance.now();
305
- // Set span attributes
306
- span.setAttribute("success", true);
307
- span.setAttribute("event_id", event.id);
308
- span.setAttribute("source", event.source);
309
- span.setAttribute("event_type", event.eventType);
310
- span.setAttribute("workflow_path", workflow.path);
311
- span.setAttribute("elapsed_ms", end - start);
312
- span.setStatus({ code: api_1.SpanStatusCode.OK });
313
- // Record metrics
314
- webhookExecutions.add(1, {
315
- env: process.env.NODE_ENV,
316
- source: event.source,
317
- event_type: event.eventType,
318
- workflow_name: this.configuration.name,
319
- success: "true",
320
- });
321
- ctx.logger.log(`Webhook processed in ${(end - start).toFixed(2)}ms: ${event.id}`);
322
- resolve(response);
271
+ // ---------------------------------------------------------------------------
272
+ // Workflow dispatch
273
+ // ---------------------------------------------------------------------------
274
+ async dispatchWorkflow(opts) {
275
+ const { workflowName, requestId, headers, body, rawBody, pathParams, queryParams, eventId, eventType } = opts;
276
+ return this.tracer.startActiveSpan(`webhook:${workflowName}`, async (span) => {
277
+ try {
278
+ const registry = WorkflowRegistry.getInstance();
279
+ const entry = registry.get(workflowName);
280
+ if (!entry) {
281
+ throw new Error(`[blok][webhook] workflow "${workflowName}" not found in registry`);
323
282
  }
324
- catch (error) {
325
- const errorMessage = error.message;
326
- // Set span error
327
- span.setAttribute("success", false);
328
- span.recordException(error);
329
- span.setStatus({ code: api_1.SpanStatusCode.ERROR, message: errorMessage });
330
- // Record error metrics
331
- webhookErrors.add(1, {
332
- env: process.env.NODE_ENV,
333
- source: event.source,
334
- event_type: event.eventType,
335
- workflow_name: this.configuration?.name || "unknown",
336
- });
337
- this.logger.error(`Webhook failed ${event.id}: ${errorMessage}`, error.stack);
338
- throw error;
339
- }
340
- finally {
341
- span.end();
342
- }
343
- });
283
+ await this.configuration.init(workflowName, this.nodeMap, entry.workflow);
284
+ const ctx = this.createContext(undefined, workflowName, requestId);
285
+ ctx.request = {
286
+ body,
287
+ rawBody,
288
+ headers,
289
+ params: pathParams,
290
+ query: queryParams,
291
+ };
292
+ // Stamp webhook metadata onto ctx so polymorphic dispatch
293
+ // can read namespace + event metadata uniformly.
294
+ ctx._webhook = {
295
+ eventId,
296
+ eventType,
297
+ namespace: opts.config.namespace,
298
+ };
299
+ await this.applyMiddlewareChain(ctx, this.nodeMap);
300
+ await this.run(ctx);
301
+ span.setAttribute("workflow_name", workflowName);
302
+ span.setAttribute("event_id", eventId);
303
+ span.setAttribute("event_type", eventType);
304
+ span.setStatus({ code: SpanStatusCode.OK });
305
+ return ctx.response;
306
+ }
307
+ catch (err) {
308
+ const msg = err instanceof Error ? err.message : String(err);
309
+ span.recordException(err);
310
+ span.setStatus({ code: SpanStatusCode.ERROR, message: msg });
311
+ this.logger.error(`[blok][webhook] workflow ${workflowName} failed: ${msg}`);
312
+ return { error: msg };
313
+ }
314
+ finally {
315
+ span.end();
316
+ }
344
317
  });
345
318
  }
346
- /**
347
- * Register a custom source handler
348
- */
349
- static registerSourceHandler(source, handler) {
350
- sourceHandlers[source] = handler;
319
+ // ---------------------------------------------------------------------------
320
+ // Introspection
321
+ // ---------------------------------------------------------------------------
322
+ getStats() {
323
+ return { workflowsRegistered: this.getWebhookWorkflows().length };
351
324
  }
325
+ getWebhookWorkflows() {
326
+ const registry = WorkflowRegistry.getInstance();
327
+ const out = [];
328
+ for (const entry of registry.list()) {
329
+ const wf = entry.workflow;
330
+ const cfg = wf?.trigger?.webhook;
331
+ if (!cfg)
332
+ continue;
333
+ // Skip configs missing both provider AND signature — they can't
334
+ // verify anything. Authors get a structured error at boot.
335
+ if (!cfg.provider && !cfg.signature) {
336
+ this.logger.error(`[blok][webhook] workflow "${entry.name}" has trigger.webhook with neither \`provider\` nor \`signature\` — skipping. Add one to enable signature verification.`);
337
+ continue;
338
+ }
339
+ out.push({ workflowName: entry.name, config: cfg });
340
+ }
341
+ return out;
342
+ }
343
+ }
344
+ // -----------------------------------------------------------------------------
345
+ // Singleton accessor (mirrors WS / SSE)
346
+ // -----------------------------------------------------------------------------
347
+ let activeTrigger = null;
348
+ export function _setActiveWebhookTrigger(trigger) {
349
+ activeTrigger = trigger;
350
+ }
351
+ export function _getActiveWebhookTrigger() {
352
+ return activeTrigger;
352
353
  }
353
- exports.WebhookTrigger = WebhookTrigger;
354
- exports.default = WebhookTrigger;
355
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiV2ViaG9va1RyaWdnZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvV2ViaG9va1RyaWdnZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOzs7Ozs7Ozs7Ozs7OztHQWNHOzs7Ozs7QUFFSCw4REFBaUM7QUFFakMseUNBT3NCO0FBRXRCLDRDQUErRTtBQUMvRSwrQkFBa0M7QUE4RGxDOztHQUVHO0FBQ0gsTUFBTSxjQUFjLEdBQXlDO0lBQzVELE1BQU0sRUFBRTtRQUNQLFlBQVksRUFBRSxDQUFDLE9BQU8sRUFBRSxFQUFFLENBQUMsT0FBTyxDQUFDLGdCQUFnQixDQUFDLElBQUksU0FBUztRQUNqRSxZQUFZLEVBQUUsQ0FBQyxPQUFPLEVBQUUsRUFBRSxDQUFDLE9BQU8sQ0FBQyxxQkFBcUIsQ0FBQyxJQUFJLE9BQU8sQ0FBQyxpQkFBaUIsQ0FBQztRQUN2RixlQUFlLEVBQUUsQ0FBQyxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sRUFBRSxFQUFFO1lBQy9DLE1BQU0sSUFBSSxHQUFHLHFCQUFNLENBQUMsVUFBVSxDQUFDLFFBQVEsRUFBRSxNQUFNLENBQUMsQ0FBQztZQUNqRCxNQUFNLE1BQU0sR0FBRyxVQUFVLElBQUksQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUM7WUFDOUQsTUFBTSxTQUFTLEdBQUcsTUFBTSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQztZQUN6QyxNQUFNLFlBQVksR0FBRyxNQUFNLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1lBQ3pDLHNEQUFzRDtZQUN0RCxJQUFJLFNBQVMsQ0FBQyxNQUFNLEtBQUssWUFBWSxDQUFDLE1BQU0sRUFBRSxDQUFDO2dCQUM5QyxPQUFPLEVBQUUsS0FBSyxFQUFFLEtBQUssRUFBRSxLQUFLLEVBQUUsMEJBQTBCLEVBQUUsQ0FBQztZQUM1RCxDQUFDO1lBQ0QsTUFBTSxLQUFLLEdBQUcs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b0JBRXpGLE1BQU0sS0FBSyxDQUFDO2dCQUNiLENBQUM7d0JBQVMsQ0FBQztvQkFDVixJQUFJLENBQUMsR0FBRyxFQUFFLENBQUM7Z0JBQ1osQ0FBQztZQUNGLENBQUMsQ0FBQyxDQUFDO1FBQ0osQ0FBQyxDQUFDLENBQUM7SUFDSixDQUFDO0lBRUQ7O09BRUc7SUFDSCxNQUFNLENBQUMscUJBQXFCLENBQUMsTUFBYyxFQUFFLE9BQTZCO1FBQ3pFLGNBQWMsQ0FBQyxNQUFNLENBQUMsR0FBRyxPQUFPLENBQUM7SUFDbEMsQ0FBQztDQUNEO0FBdFNELHdDQXNTQztBQUVELGtCQUFlLGNBQWMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogV2ViaG9va1RyaWdnZXIgLSBIYW5kbGUgd2ViaG9vayBldmVudHMgZnJvbSBleHRlcm5hbCBzZXJ2aWNlc1xuICpcbiAqIEV4dGVuZHMgVHJpZ2dlckJhc2UgdG8gcHJvY2VzcyB3ZWJob29rIGV2ZW50cyBmcm9tOlxuICogLSBHaXRIdWIgKHB1c2gsIHB1bGxfcmVxdWVzdCwgaXNzdWVzLCBldGMuKVxuICogLSBTdHJpcGUgKHBheW1lbnRfaW50ZW50LCBjaGVja291dC5zZXNzaW9uLCBldGMuKVxuICogLSBTaG9waWZ5IChvcmRlcnMsIHByb2R1Y3RzLCBjdXN0b21lcnMpXG4gKiAtIEN1c3RvbSB3ZWJob29rc1xuICpcbiAqIEZlYXR1cmVzOlxuICogLSBTaWduYXR1cmUgdmVyaWZpY2F0aW9uIGZvciBzZWN1cml0eVxuICogLSBFdmVudCB0eXBlIGZpbHRlcmluZ1xuICogLSBSZXRyeSBzdXBwb3J0XG4gKiAtIERlYWQgbGV0dGVyIGhhbmRsaW5nXG4gKi9cblxuaW1wb3J0IGNyeXB0byBmcm9tIFwibm9kZTpjcnlwdG9cIjtcbmltcG9ydCB0eXBlIHsgSGVscGVyUmVzcG9uc2UsIFdlYmhvb2tUcmlnZ2VyT3B0cyB9IGZyb20gXCJAYmxvay9oZWxwZXJcIjtcbmltcG9ydCB7XG5cdERlZmF1bHRMb2dnZXIsXG5cdHR5cGUgR2xvYmFsT3B0aW9ucyxcblx0dHlwZSBCbG9rU2VydmljZSxcblx0Tm9kZU1hcCxcblx0VHJpZ2dlckJhc2UsXG5cdHR5cGUgVHJpZ2dlclJlc3BvbnNlLFxufSBmcm9tIFwiQGJsb2svcnVubmVyXCI7XG5pbXBvcnQgdHlwZSB7IENvbnRleHQsIFJlcXVlc3RDb250ZXh0IH0gZnJvbSBcIkBibG9rL3NoYXJlZFwiO1xuaW1wb3J0IHsgdHlwZSBTcGFuLCBTcGFuU3RhdHVzQ29kZSwgbWV0cmljcywgdHJhY2UgfSBmcm9tIFwiQG9wZW50ZWxlbWV0cnkvYXBpXCI7XG5pbXBvcnQgeyB2NCBhcyB1dWlkIH0gZnJvbSBcInV1aWRcIjtcblxuLyoqXG4gKiBXZWJob29rIGV2ZW50IHN0cnVjdHVyZVxuICovXG5leHBvcnQgaW50ZXJmYWNlIFdlYmhvb2tFdmVudCB7XG5cdC8qKiBVbmlxdWUgZXZlbnQgSUQgKi9cblx0aWQ6IHN0cmluZztcblx0LyoqIFNvdXJjZSBzZXJ2aWNlIChnaXRodWIsIHN0cmlwZSwgc2hvcGlmeSwgY3VzdG9tKSAqL1xuXHRzb3VyY2U6IHN0cmluZztcblx0LyoqIEV2ZW50IHR5cGUgKGUuZy4sIHB1c2gsIHBheW1lbnRfaW50ZW50LnN1Y2NlZWRlZCkgKi9cblx0ZXZlbnRUeXBlOiBzdHJpbmc7XG5cdC8qKiBFdmVudCBwYXlsb2FkICovXG5cdHBheWxvYWQ6IHVua25vd247XG5cdC8qKiBSZXF1ZXN0IGhlYWRlcnMgKi9cblx0aGVhZGVyczogUmVjb3JkPHN0cmluZywgc3RyaW5nPjtcblx0LyoqIFNpZ25hdHVyZSAoaWYgcHJvdmlkZWQpICovXG5cdHNpZ25hdHVyZT86IHN0cmluZztcblx0LyoqIFRpbWVzdGFtcCAqL1xuXHR0aW1lc3RhbXA6IERhdGU7XG5cdC8qKiBSYXcgcmVxdWVzdCBib2R5ICovXG5cdHJhd0JvZHk6IHN0cmluZztcbn1cblxuLyoqXG4gKiBTaWduYXR1cmUgdmVyaWZpY2F0aW9uIHJlc3VsdFxuICovXG5leHBvcnQgaW50ZXJmYWNlIFZlcmlmaWNhdGlvblJlc3VsdCB7XG5cdHZhbGlkOiBib29sZWFuO1xuXHRlcnJvcj86IHN0cmluZztcbn1cblxuLyoqXG4gKiBXZWJob29rIHNvdXJjZSBoYW5kbGVyc1xuICovXG5leHBvcnQgaW50ZXJmYWNlIFdlYmhvb2tTb3VyY2VIYW5kbGVyIHtcblx0LyoqIEV4dHJhY3QgZXZlbnQgdHlwZSBmcm9tIHJlcXVlc3QgKi9cblx0Z2V0RXZlbnRUeXBlKGhlYWRlcnM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4sIGJvZHk6IHVua25vd24pOiBzdHJpbmc7XG5cdC8qKiBHZXQgc2lnbmF0dXJlIGZyb20gcmVxdWVzdCAqL1xuXHRnZXRTaWduYXR1cmUoaGVhZGVyczogUmVjb3JkPHN0cmluZywgc3RyaW5nPik6IHN0cmluZyB8IHVuZGVmaW5lZDtcblx0LyoqIFZlcmlmeSBzaWduYXR1cmUgKi9cblx0dmVyaWZ5U2lnbmF0dXJlKHJhd0JvZHk6IHN0cmluZywgc2lnbmF0dXJlOiBzdHJpbmcsIHNlY3JldDogc3RyaW5nKTogVmVyaWZpY2F0aW9uUmVzdWx0O1xuXHQvKiogR2V0IGV2ZW50IElEICovXG5cdGdldEV2ZW50SWQoaGVhZGVyczogUmVjb3JkPHN0cmluZywgc3RyaW5nPiwgYm9keTogdW5rbm93bik6IHN0cmluZztcbn1cblxuLyoqXG4gKiBXb3JrZmxvdyBtb2RlbCB3aXRoIHdlYmhvb2sgdHJpZ2dlciBjb25maWd1cmF0aW9uXG4gKi9cbmludGVyZmFjZSBXZWJob29rV29ya2Zsb3dNb2RlbCB7XG5cdHBhdGg6IHN0cmluZztcblx0Y29uZmlnOiB7XG5cdFx0bmFtZTogc3RyaW5nO1xuXHRcdHZlcnNpb246IHN0cmluZztcblx0XHR0cmlnZ2VyPzoge1xuXHRcdFx0d2ViaG9vaz86IFdlYmhvb2tUcmlnZ2VyT3B0cztcblx0XHRcdFtrZXk6IHN0cmluZ106IHVua25vd247XG5cdFx0fTtcblx0XHRba2V5OiBzdHJpbmddOiB1bmtub3duO1xuXHR9O1xufVxuXG4vKipcbiAqIEJ1aWx0LWluIHNvdXJjZSBoYW5kbGVyc1xuICovXG5jb25zdCBzb3VyY2VIYW5kbGVyczogUmVjb3JkPHN0cmluZywgV2ViaG9va1NvdXJjZUhhbmRsZXI+ID0ge1xuXHRnaXRodWI6IHtcblx0XHRnZXRFdmVudFR5cGU6IChoZWFkZXJzKSA9PiBoZWFkZXJzW1wieC1naXRodWItZXZlbnRcIl0gfHwgXCJ1bmtub3duXCIsXG5cdFx0Z2V0U2lnbmF0dXJlOiAoaGVhZGVycykgPT4gaGVhZGVyc1tcIngtaHViLXNpZ25hdHVyZS0yNTZcIl0gfHwgaGVhZGVyc1tcIngtaHViLXNpZ25hdHVyZVwiXSxcblx0XHR2ZXJpZnlTaWduYXR1cmU6IChyYXdCb2R5LCBzaWduYXR1cmUsIHNlY3JldCkgPT4ge1xuXHRcdFx0Y29uc3QgaG1hYyA9IGNyeXB0by5jcmVhdGVIbWFjKFwic2hhMjU2XCIsIHNlY3JldCk7XG5cdFx0XHRjb25zdCBkaWdlc3QgPSBgc2hhMjU2PSR7aG1hYy51cGRhdGUocmF3Qm9keSkuZGlnZXN0KFwiaGV4XCIpfWA7XG5cdFx0XHRjb25zdCBzaWdCdWZmZXIgPSBCdWZmZXIuZnJvbShzaWduYXR1cmUpO1xuXHRcdFx0Y29uc3QgZGlnZXN0QnVmZmVyID0gQnVmZmVyLmZyb20oZGlnZXN0KTtcblx0XHRcdC8vIExlbmd0aCBjaGVjayBmaXJzdCB0byBhdm9pZCB0aW1pbmcgYXR0YWNrIG9uIGxlbmd0aFxuXHRcdFx0aWYgKHNpZ0J1ZmZlci5sZW5ndGggIT09IGRpZ2VzdEJ1ZmZlci5sZW5ndGgpIHtcblx0XHRcdFx0cmV0dXJuIHsgdmFsaWQ6IGZhbHNlLCBlcnJvcjogXCJJbnZhbGlkIEdpdEh1YiBzaWduYXR1cmVcIiB9O1xuXHRcdFx0fVxuXHRcdFx0Y29uc3QgdmFsaWQgPSBjcnlwdG8udGltaW5nU2FmZUVxdWFsKHNpZ0J1ZmZlciwgZGlnZXN0QnVmZmVyKTtcblx0XHRcdHJldHVybiB7IHZhbGlkLCBlcnJvcjogdmFsaWQgPyB1bmRlZmluZWQgOiBcIkludmFsaWQgR2l0SHViIHNpZ25hdHVyZVwiIH07XG5cdFx0fSxcblx0XHRnZXRFdmVudElkOiAoaGVhZGVycykgPT4gaGVhZGVyc1tcIngtZ2l0aHViLWRlbGl2ZXJ5XCJdIHx8IHV1aWQoKSxcblx0fSxcblxuXHRzdHJpcGU6IHtcblx0XHRnZXRFdmVudFR5cGU6IChfLCBib2R5KSA9PiAoYm9keSBhcyB7IHR5cGU/OiBzdHJpbmcgfSk/LnR5cGUgfHwgXCJ1bmtub3duXCIsXG5cdFx0Z2V0U2lnbmF0dXJlOiAoaGVhZGVycykgPT4gaGVhZGVyc1tcInN0cmlwZS1zaWduYXR1cmVcIl0sXG5cdFx0dmVyaWZ5U2lnbmF0dXJlOiAocmF3Qm9keSwgc2lnbmF0dXJlLCBzZWNyZXQpID0+IHtcblx0XHRcdC8vIFN0cmlwZSBzaWduYXR1cmUgZm9ybWF0OiB0PXRpbWVzdGFtcCx2MT1zaWduYXR1cmVcblx0XHRcdGNvbnN0IHBhcnRzID0gc2lnbmF0dXJlLnNwbGl0KFwiLFwiKS5yZWR1Y2UoXG5cdFx0XHRcdChhY2MsIHBhcnQpID0+IHtcblx0XHRcdFx0XHRjb25zdCBba2V5LCB2YWx1ZV0gPSBwYXJ0LnNwbGl0KFwiPVwiKTtcblx0XHRcdFx0XHRhY2Nba2V5XSA9IHZhbHVlO1xuXHRcdFx0XHRcdHJldHVybiBhY2M7XG5cdFx0XHRcdH0sXG5cdFx0XHRcdHt9IGFzIFJlY29yZDxzdHJpbmcsIHN0cmluZz4sXG5cdFx0XHQpO1xuXG5cdFx0XHRjb25zdCB0aW1lc3RhbXAgPSBwYXJ0cy50O1xuXHRcdFx0Y29uc3QgZXhwZWN0ZWRTaWcgPSBwYXJ0cy52MTtcblxuXHRcdFx0aWYgKCF0aW1lc3RhbXAgfHwgIWV4cGVjdGVkU2lnKSB7XG5cdFx0XHRcdHJldHVybiB7IHZhbGlkOiBmYWxzZSwgZXJyb3I6IFwiSW52YWxpZCBTdHJpcGUgc2lnbmF0dXJlIGZvcm1hdFwiIH07XG5cdFx0XHR9XG5cblx0XHRcdGNvbnN0IHBheWxvYWQgPSBgJHt0aW1lc3RhbXB9LiR7cmF3Qm9keX1gO1xuXHRcdFx0Y29uc3QgaG1hYyA9IGNyeXB0by5jcmVhdGVIbWFjKFwic2hhMjU2XCIsIHNlY3JldCk7XG5cdFx0XHRjb25zdCBjb21wdXRlZFNpZyA9IGhtYWMudXBkYXRlKHBheWxvYWQpLmRpZ2VzdChcImhleFwiKTtcblxuXHRcdFx0Y29uc3Qgc2lnQnVmZmVyID0gQnVmZmVyLmZyb20oZXhwZWN0ZWRTaWcpO1xuXHRcdFx0Y29uc3QgY29tcHV0ZWRCdWZmZXIgPSBCdWZmZXIuZnJvbShjb21wdXRlZFNpZyk7XG5cdFx0XHRpZiAoc2lnQnVmZmVyLmxlbmd0aCAhPT0gY29tcHV0ZWRCdWZmZXIubGVuZ3RoKSB7XG5cdFx0XHRcdHJldHVybiB7IHZhbGlkOiBmYWxzZSwgZXJyb3I6IFwiSW52YWxpZCBTdHJpcGUgc2lnbmF0dXJlXCIgfTtcblx0XHRcdH1cblx0XHRcdGNvbnN0IHZhbGlkID0gY3J5cHRvLnRpbWluZ1NhZmVFcXVhbChzaWdCdWZmZXIsIGNvbXB1dGVkQnVmZmVyKTtcblx0XHRcdHJldHVybiB7IHZhbGlkLCBlcnJvcjogdmFsaWQgPyB1bmRlZmluZWQgOiBcIkludmFsaWQgU3RyaXBlIHNpZ25hdHVyZVwiIH07XG5cdFx0fSxcblx0XHRnZXRFdmVudElkOiAoXywgYm9keSkgPT4gKGJvZHkgYXMgeyBpZD86IHN0cmluZyB9KT8uaWQgfHwgdXVpZCgpLFxuXHR9LFxuXG5cdHNob3BpZnk6IHtcblx0XHRnZXRFdmVudFR5cGU6IChoZWFkZXJzKSA9PiBoZWFkZXJzW1wieC1zaG9waWZ5LXRvcGljXCJdIHx8IFwidW5rbm93blwiLFxuXHRcdGdldFNpZ25hdHVyZTogKGhlYWRlcnMpID0+IGhlYWRlcnNbXCJ4LXNob3BpZnktaG1hYy1zaGEyNTZcIl0sXG5cdFx0dmVyaWZ5U2lnbmF0dXJlOiAocmF3Qm9keSwgc2lnbmF0dXJlLCBzZWNyZXQpID0+IHtcblx0XHRcdGNvbnN0IGhtYWMgPSBjcnlwdG8uY3JlYXRlSG1hYyhcInNoYTI1NlwiLCBzZWNyZXQpO1xuXHRcdFx0Y29uc3QgZGlnZXN0ID0gaG1hYy51cGRhdGUocmF3Qm9keSwgXCJ1dGY4XCIpLmRpZ2VzdChcImJhc2U2NFwiKTtcblx0XHRcdGNvbnN0IHNpZ0J1ZmZlciA9IEJ1ZmZlci5mcm9tKHNpZ25hdHVyZSwgXCJiYXNlNjRcIik7XG5cdFx0XHRjb25zdCBkaWdlc3RCdWZmZXIgPSBCdWZmZXIuZnJvbShkaWdlc3QsIFwiYmFzZTY0XCIpO1xuXHRcdFx0aWYgKHNpZ0J1ZmZlci5sZW5ndGggIT09IGRpZ2VzdEJ1ZmZlci5sZW5ndGgpIHtcblx0XHRcdFx0cmV0dXJuIHsgdmFsaWQ6IGZhbHNlLCBlcnJvcjogXCJJbnZhbGlkIFNob3BpZnkgc2lnbmF0dXJlXCIgfTtcblx0XHRcdH1cblx0XHRcdGNvbnN0IHZhbGlkID0gY3J5cHRvLnRpbWluZ1NhZmVFcXVhbChzaWdCdWZmZXIsIGRpZ2VzdEJ1ZmZlcik7XG5cdFx0XHRyZXR1cm4geyB2YWxpZCwgZXJyb3I6IHZhbGlkID8gdW5kZWZpbmVkIDogXCJJbnZhbGlkIFNob3BpZnkgc2lnbmF0dXJlXCIgfTtcblx0XHR9LFxuXHRcdGdldEV2ZW50SWQ6IChoZWFkZXJzKSA9PiBoZWFkZXJzW1wieC1zaG9waWZ5LXdlYmhvb2staWRcIl0gfHwgdXVpZCgpLFxuXHR9LFxuXG5cdGN1c3RvbToge1xuXHRcdGdldEV2ZW50VHlwZTogKGhlYWRlcnMsIGJvZHkpID0+IGhlYWRlcnNbXCJ4LWV2ZW50LXR5cGVcIl0gfHwgKGJvZHkgYXMgeyBldmVudD86IHN0cmluZyB9KT8uZXZlbnQgfHwgXCJjdXN0b21cIixcblx0XHRnZXRTaWduYXR1cmU6IChoZWFkZXJzKSA9PiBoZWFkZXJzW1wieC1zaWduYXR1cmVcIl0gfHwgaGVhZGVyc1tcIngtd2ViaG9vay1zaWduYXR1cmVcIl0sXG5cdFx0dmVyaWZ5U2lnbmF0dXJlOiAocmF3Qm9keSwgc2lnbmF0dXJlLCBzZWNyZXQpID0+IHtcblx0XHRcdC8vIERlZmF1bHQ6IEhNQUMtU0hBMjU2XG5cdFx0XHRjb25zdCBobWFjID0gY3J5cHRvLmNyZWF0ZUhtYWMoXCJzaGEyNTZcIiwgc2VjcmV0KTtcblx0XHRcdGNvbnN0IGRpZ2VzdCA9IGhtYWMudXBkYXRlKHJhd0JvZHkpLmRpZ2VzdChcImhleFwiKTtcblx0XHRcdGNvbnN0IHZhbGlkID0gc2lnbmF0dXJlID09PSBkaWdlc3QgfHwgc2lnbmF0dXJlID09PSBgc2hhMjU2PSR7ZGlnZXN0fWA7XG5cdFx0XHRyZXR1cm4geyB2YWxpZCwgZXJyb3I6IHZhbGlkID8gdW5kZWZpbmVkIDogXCJJbnZhbGlkIHNpZ25hdHVyZVwiIH07XG5cdFx0fSxcblx0XHRnZXRFdmVudElkOiAoaGVhZGVycywgYm9keSkgPT4gaGVhZGVyc1tcIngtZXZlbnQtaWRcIl0gfHwgKGJvZHkgYXMgeyBpZD86IHN0cmluZyB9KT8uaWQgfHwgdXVpZCgpLFxuXHR9LFxufTtcblxuLyoqXG4gKiBXZWJob29rVHJpZ2dlciAtIEhhbmRsZSB3ZWJob29rIGV2ZW50c1xuICovXG5leHBvcnQgYWJzdHJhY3QgY2xhc3MgV2ViaG9va1RyaWdnZXIgZXh0ZW5kcyBUcmlnZ2VyQmFzZSB7XG5cdHByb3RlY3RlZCBub2RlTWFwOiBHbG9iYWxPcHRpb25zID0ge30gYXMgR2xvYmFsT3B0aW9ucztcblx0cHJvdGVjdGVkIHJlYWRvbmx5IHRyYWNlciA9IHRyYWNlLmdldFRyYWNlcihcblx0XHRwcm9jZXNzLmVudi5QUk9KRUNUX05BTUUgfHwgXCJ0cmlnZ2VyLXdlYmhvb2std29ya2Zsb3dcIixcblx0XHRwcm9jZXNzLmVudi5QUk9KRUNUX1ZFUlNJT04gfHwgXCIwLjAuMVwiLFxuXHQpO1xuXHRwcm90ZWN0ZWQgcmVhZG9ubHkgbG9nZ2VyID0gbmV3IERlZmF1bHRMb2dnZXIoKTtcblx0cHJvdGVjdGVkIHdlYmhvb2tXb3JrZmxvd3M6IFdlYmhvb2tXb3JrZmxvd01vZGVsW10gPSBbXTtcblxuXHQvLyBTdWJjbGFzc2VzIHByb3ZpZGUgdGhlc2Vcblx0cHJvdGVjdGVkIGFic3RyYWN0IG5vZGVzOiBSZWNvcmQ8c3RyaW5nLCBCbG9rU2VydmljZTx1bmtub3duPj47XG5cdHByb3RlY3RlZCBhYnN0cmFjdCB3b3JrZmxvd3M6IFJlY29yZDxzdHJpbmcsIEhlbHBlclJlc3BvbnNlPjtcblxuXHRjb25zdHJ1Y3RvcigpIHtcblx0XHRzdXBlcigpO1xuXHRcdHRoaXMubG9hZE5vZGVzKCk7XG5cdFx0dGhpcy5sb2FkV29ya2Zsb3dzKCk7XG5cdH1cblxuXHQvKipcblx0ICogTG9hZCBub2RlcyBpbnRvIHRoZSBub2RlIG1hcFxuXHQgKi9cblx0bG9hZE5vZGVzKCk6IHZvaWQge1xuXHRcdHRoaXMubm9kZU1hcC5ub2RlcyA9IG5ldyBOb2RlTWFwKCk7XG5cdFx0Y29uc3Qgbm9kZUtleXMgPSBPYmplY3Qua2V5cyh0aGlzLm5vZGVzKTtcblx0XHRmb3IgKGNvbnN0IGtleSBvZiBub2RlS2V5cykge1xuXHRcdFx0dGhpcy5ub2RlTWFwLm5vZGVzLmFkZE5vZGUoa2V5LCB0aGlzLm5vZGVzW2tleV0pO1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBMb2FkIHdvcmtmbG93cyBpbnRvIHRoZSB3b3JrZmxvdyBtYXBcblx0ICovXG5cdGxvYWRXb3JrZmxvd3MoKTogdm9pZCB7XG5cdFx0dGhpcy5ub2RlTWFwLndvcmtmbG93cyA9IHRoaXMud29ya2Zsb3dzO1xuXHR9XG5cblx0LyoqXG5cdCAqIEluaXRpYWxpemUgd2ViaG9vayB0cmlnZ2VyIChjYWxsIGFmdGVyIGxvYWRpbmcgd29ya2Zsb3dzKVxuXHQgKi9cblx0YXN5bmMgbGlzdGVuKCk6IFByb21pc2U8bnVtYmVyPiB7XG5cdFx0Y29uc3Qgc3RhcnRUaW1lID0gdGhpcy5zdGFydENvdW50ZXIoKTtcblxuXHRcdC8vIEZpbmQgYWxsIHdvcmtmbG93cyB3aXRoIHdlYmhvb2sgdHJpZ2dlcnNcblx0XHR0aGlzLndlYmhvb2tXb3JrZmxvd3MgPSB0aGlzLmdldFdlYmhvb2tXb3JrZmxvd3MoKTtcblxuXHRcdGlmICh0aGlzLndlYmhvb2tXb3JrZmxvd3MubGVuZ3RoID09PSAwKSB7XG5cdFx0XHR0aGlzLmxvZ2dlci5sb2coXCJObyB3b3JrZmxvd3Mgd2l0aCB3ZWJob29rIHRyaWdnZXJzIGZvdW5kXCIpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHR0aGlzLmxvZ2dlci5sb2coYFdlYmhvb2sgdHJpZ2dlciBpbml0aWFsaXplZC4gJHt0aGlzLndlYmhvb2tXb3JrZmxvd3MubGVuZ3RofSB3b3JrZmxvdyhzKSByZWdpc3RlcmVkYCk7XG5cdFx0fVxuXG5cdFx0Ly8gRW5hYmxlIEhNUiBpbiBkZXZlbG9wbWVudCBtb2RlXG5cdFx0aWYgKHByb2Nlc3MuZW52LkJMT0tfSE1SID09PSBcInRydWVcIiB8fCBwcm9jZXNzLmVudi5OT0RFX0VOViA9PT0gXCJkZXZlbG9wbWVudFwiKSB7XG5cdFx0XHRhd2FpdCB0aGlzLmVuYWJsZUhvdFJlbG9hZCgpO1xuXHRcdH1cblxuXHRcdHJldHVybiB0aGlzLmVuZENvdW50ZXIoc3RhcnRUaW1lKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBTdG9wIHRoZSB3ZWJob29rIHRyaWdnZXJcblx0ICovXG5cdGFzeW5jIHN0b3AoKTogUHJvbWlzZTx2b2lkPiB7XG5cdFx0dGhpcy53ZWJob29rV29ya2Zsb3dzID0gW107XG5cdFx0dGhpcy5sb2dnZXIubG9nKFwiV2ViaG9vayB0cmlnZ2VyIHN0b3BwZWRcIik7XG5cdH1cblxuXHRwcm90ZWN0ZWQgb3ZlcnJpZGUgYXN5bmMgb25IbXJXb3JrZmxvd0NoYW5nZSgpOiBQcm9taXNlPHZvaWQ+IHtcblx0XHR0aGlzLmxvYWRXb3JrZmxvd3MoKTtcblx0XHR0aGlzLndlYmhvb2tXb3JrZmxvd3MgPSB0aGlzLmdldFdlYmhvb2tXb3JrZmxvd3MoKTtcblx0XHR0aGlzLmxvZ2dlci5sb2coYFtITVJdIFdlYmhvb2sgd29ya2Zsb3dzIHJlbG9hZGVkLiAke3RoaXMud2ViaG9va1dvcmtmbG93cy5sZW5ndGh9IHdvcmtmbG93KHMpIHJlZ2lzdGVyZWRgKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBQcm9jZXNzIGFuIGluY29taW5nIHdlYmhvb2sgcmVxdWVzdFxuXHQgKiBDYWxsIHRoaXMgZnJvbSB5b3VyIEhUVFAgZW5kcG9pbnQgaGFuZGxlclxuXHQgKi9cblx0YXN5bmMgaGFuZGxlV2ViaG9vayhcblx0XHRzb3VyY2U6IHN0cmluZyxcblx0XHRyYXdCb2R5OiBzdHJpbmcsXG5cdFx0aGVhZGVyczogUmVjb3JkPHN0cmluZywgc3RyaW5nPixcblx0KTogUHJvbWlzZTxUcmlnZ2VyUmVzcG9uc2UgfCBudWxsPiB7XG5cdFx0Y29uc3QgaGFuZGxlciA9IHNvdXJjZUhhbmRsZXJzW3NvdXJjZV0gfHwgc291cmNlSGFuZGxlcnMuY3VzdG9tO1xuXG5cdFx0Ly8gUGFyc2UgYm9keVxuXHRcdGxldCBib2R5OiB1bmtub3duO1xuXHRcdHRyeSB7XG5cdFx0XHRib2R5ID0gSlNPTi5wYXJzZShyYXdCb2R5KTtcblx0XHR9IGNhdGNoIHtcblx0XHRcdGJvZHkgPSByYXdCb2R5O1xuXHRcdH1cblxuXHRcdC8vIENyZWF0ZSB3ZWJob29rIGV2ZW50XG5cdFx0Y29uc3QgZXZlbnQ6IFdlYmhvb2tFdmVudCA9IHtcblx0XHRcdGlkOiBoYW5kbGVyLmdldEV2ZW50SWQoaGVhZGVycywgYm9keSksXG5cdFx0XHRzb3VyY2UsXG5cdFx0XHRldmVudFR5cGU6IGhhbmRsZXIuZ2V0RXZlbnRUeXBlKGhlYWRlcnMsIGJvZHkpLFxuXHRcdFx0cGF5bG9hZDogYm9keSxcblx0XHRcdGhlYWRlcnMsXG5cdFx0XHRzaWduYXR1cmU6IGhhbmRsZXIuZ2V0U2lnbmF0dXJlKGhlYWRlcnMpLFxuXHRcdFx0dGltZXN0YW1wOiBuZXcgRGF0ZSgpLFxuXHRcdFx0cmF3Qm9keSxcblx0XHR9O1xuXG5cdFx0Ly8gRmluZCBtYXRjaGluZyB3b3JrZmxvd1xuXHRcdGNvbnN0IHdvcmtmbG93ID0gdGhpcy5maW5kTWF0Y2hpbmdXb3JrZmxvdyhldmVudCk7XG5cdFx0aWYgKCF3b3JrZmxvdykge1xuXHRcdFx0dGhpcy5sb2dnZXIubG9nKGBObyBtYXRjaGluZyB3b3JrZmxvdyBmb3Igd2ViaG9vazogJHtzb3VyY2V9LyR7ZXZlbnQuZXZlbnRUeXBlfWApO1xuXHRcdFx0cmV0dXJuIG51bGw7XG5cdFx0fVxuXG5cdFx0Y29uc3QgY29uZmlnID0gd29ya2Zsb3cuY29uZmlnLnRyaWdnZXI/LndlYmhvb2sgYXMgV2ViaG9va1RyaWdnZXJPcHRzO1xuXG5cdFx0Ly8gVmVyaWZ5IHNpZ25hdHVyZSBpZiBzZWNyZXQgaXMgY29uZmlndXJlZFxuXHRcdGlmIChjb25maWcuc2VjcmV0ICYmIGV2ZW50LnNpZ25hdHVyZSkge1xuXHRcdFx0Y29uc3QgdmVyaWZpY2F0aW9uID0gaGFuZGxlci52ZXJpZnlTaWduYXR1cmUocmF3Qm9keSwgZXZlbnQuc2lnbmF0dXJlLCBjb25maWcuc2VjcmV0KTtcblx0XHRcdGlmICghdmVyaWZpY2F0aW9uLnZhbGlkKSB7XG5cdFx0XHRcdHRoaXMubG9nZ2VyLmVycm9yKGBXZWJob29rIHNpZ25hdHVyZSB2ZXJpZmljYXRpb24gZmFpbGVkOiAke3ZlcmlmaWNhdGlvbi5lcnJvcn1gKTtcblx0XHRcdFx0dGhyb3cgbmV3IEVycm9yKGBTaWduYXR1cmUgdmVyaWZpY2F0aW9uIGZhaWxlZDogJHt2ZXJpZmljYXRpb24uZXJyb3J9YCk7XG5cdFx0XHR9XG5cdFx0fSBlbHNlIGlmIChjb25maWcuc2VjcmV0ICYmICFldmVudC5zaWduYXR1cmUpIHtcblx0XHRcdHRoaXMubG9nZ2VyLmVycm9yKFwiV2ViaG9vayBzaWduYXR1cmUgbWlzc2luZyBidXQgc2VjcmV0IGlzIGNvbmZpZ3VyZWRcIik7XG5cdFx0XHR0aHJvdyBuZXcgRXJyb3IoXCJTaWduYXR1cmUgbWlzc2luZ1wiKTtcblx0XHR9XG5cblx0XHRyZXR1cm4gdGhpcy5leGVjdXRlV29ya2Zsb3coZXZlbnQsIHdvcmtmbG93LCBjb25maWcpO1xuXHR9XG5cblx0LyoqXG5cdCAqIEdldCBhbGwgd29ya2Zsb3dzIHRoYXQgaGF2ZSB3ZWJob29rIHRyaWdnZXJzXG5cdCAqL1xuXHRwcm90ZWN0ZWQgZ2V0V2ViaG9va1dvcmtmbG93cygpOiBXZWJob29rV29ya2Zsb3dNb2RlbFtdIHtcblx0XHRjb25zdCB3b3JrZmxvd3M6IFdlYmhvb2tXb3JrZmxvd01vZGVsW10gPSBbXTtcblxuXHRcdGZvciAoY29uc3QgW3BhdGgsIHdvcmtmbG93XSBvZiBPYmplY3QuZW50cmllcyh0aGlzLm5vZGVNYXAud29ya2Zsb3dzIHx8IHt9KSkge1xuXHRcdFx0Y29uc3Qgd29ya2Zsb3dDb25maWcgPSAod29ya2Zsb3cgYXMgdW5rbm93biBhcyB7IF9jb25maWc6IFdlYmhvb2tXb3JrZmxvd01vZGVsW1wiY29uZmlnXCJdIH0pLl9jb25maWc7XG5cblx0XHRcdGlmICh3b3JrZmxvd0NvbmZpZz8udHJpZ2dlcikge1xuXHRcdFx0XHRjb25zdCB0cmlnZ2VyVHlwZSA9IE9iamVjdC5rZXlzKHdvcmtmbG93Q29uZmlnLnRyaWdnZXIpWzBdO1xuXG5cdFx0XHRcdGlmICh0cmlnZ2VyVHlwZSA9PT0gXCJ3ZWJob29rXCIgJiYgd29ya2Zsb3dDb25maWcudHJpZ2dlci53ZWJob29rKSB7XG5cdFx0XHRcdFx0d29ya2Zsb3dzLnB1c2goe1xuXHRcdFx0XHRcdFx0cGF0aCxcblx0XHRcdFx0XHRcdGNvbmZpZzogd29ya2Zsb3dDb25maWcsXG5cdFx0XHRcdFx0fSk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cblx0XHRyZXR1cm4gd29ya2Zsb3dzO1xuXHR9XG5cblx0LyoqXG5cdCAqIEZpbmQgd29ya2Zsb3cgbWF0Y2hpbmcgdGhlIHdlYmhvb2sgZXZlbnRcblx0ICovXG5cdHByb3RlY3RlZCBmaW5kTWF0Y2hpbmdXb3JrZmxvdyhldmVudDogV2ViaG9va0V2ZW50KTogV2ViaG9va1dvcmtmbG93TW9kZWwgfCBudWxsIHtcblx0XHRmb3IgKGNvbnN0IHdvcmtmbG93IG9mIHRoaXMud2ViaG9va1dvcmtmbG93cykge1xuXHRcdFx0Y29uc3QgY29uZmlnID0gd29ya2Zsb3cuY29uZmlnLnRyaWdnZXI/LndlYmhvb2s7XG5cdFx0XHRpZiAoIWNvbmZpZykgY29udGludWU7XG5cblx0XHRcdC8vIENoZWNrIHNvdXJjZSBtYXRjaFxuXHRcdFx0aWYgKGNvbmZpZy5zb3VyY2UgIT09IGV2ZW50LnNvdXJjZSkgY29udGludWU7XG5cblx0XHRcdC8vIENoZWNrIGV2ZW50IHR5cGUgbWF0Y2hcblx0XHRcdGlmIChjb25maWcuZXZlbnRzICYmIGNvbmZpZy5ldmVudHMubGVuZ3RoID4gMCkge1xuXHRcdFx0XHRjb25zdCBtYXRjaGVzID0gY29uZmlnLmV2ZW50cy5zb21lKChwYXR0ZXJuKSA9PiB7XG5cdFx0XHRcdFx0Ly8gU3VwcG9ydCB3aWxkY2FyZHMgKGUuZy4sIFwicHVzaFwiLCBcInB1bGxfcmVxdWVzdC4qXCIpXG5cdFx0XHRcdFx0aWYgKHBhdHRlcm4gPT09IFwiKlwiKSByZXR1cm4gdHJ1ZTtcblx0XHRcdFx0XHRpZiAocGF0dGVybi5lbmRzV2l0aChcIi4qXCIpKSB7XG5cdFx0XHRcdFx0XHRjb25zdCBwcmVmaXggPSBwYXR0ZXJuLnNsaWNlKDAsIC0yKTtcblx0XHRcdFx0XHRcdHJldHVybiBldmVudC5ldmVudFR5cGUuc3RhcnRzV2l0aChwcmVmaXgpO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHRyZXR1cm4gcGF0dGVybiA9PT0gZXZlbnQuZXZlbnRUeXBlO1xuXHRcdFx0XHR9KTtcblx0XHRcdFx0aWYgKCFtYXRjaGVzKSBjb250aW51ZTtcblx0XHRcdH1cblxuXHRcdFx0cmV0dXJuIHdvcmtmbG93O1xuXHRcdH1cblxuXHRcdHJldHVybiBudWxsO1xuXHR9XG5cblx0LyoqXG5cdCAqIEV4ZWN1dGUgYSB3b3JrZmxvdyBmb3IgYSB3ZWJob29rIGV2ZW50XG5cdCAqL1xuXHRwcm90ZWN0ZWQgYXN5bmMgZXhlY3V0ZVdvcmtmbG93KFxuXHRcdGV2ZW50OiBXZWJob29rRXZlbnQsXG5cdFx0d29ya2Zsb3c6IFdlYmhvb2tXb3JrZmxvd01vZGVsLFxuXHRcdF9jb25maWc6IFdlYmhvb2tUcmlnZ2VyT3B0cyxcblx0KTogUHJvbWlzZTxUcmlnZ2VyUmVzcG9uc2U+IHtcblx0XHRjb25zdCBleGVjdXRpb25JZCA9IHV1aWQoKTtcblxuXHRcdGNvbnN0IGRlZmF1bHRNZXRlciA9IG1ldHJpY3MuZ2V0TWV0ZXIoXCJkZWZhdWx0XCIpO1xuXHRcdGNvbnN0IHdlYmhvb2tFeGVjdXRpb25zID0gZGVmYXVsdE1ldGVyLmNyZWF0ZUNvdW50ZXIoXCJ3ZWJob29rX2V4ZWN1dGlvbnNcIiwge1xuXHRcdFx0ZGVzY3JpcHRpb246IFwiV2ViaG9vayBleGVjdXRpb25zXCIsXG5cdFx0fSk7XG5cdFx0Y29uc3Qgd2ViaG9va0Vycm9ycyA9IGRlZmF1bHRNZXRlci5jcmVhdGVDb3VudGVyKFwid2ViaG9va19lcnJvcnNcIiwge1xuXHRcdFx0ZGVzY3JpcHRpb246IFwiV2ViaG9vayBleGVjdXRpb24gZXJyb3JzXCIsXG5cdFx0fSk7XG5cblx0XHRyZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUpID0+IHtcblx0XHRcdHRoaXMudHJhY2VyLnN0YXJ0QWN0aXZlU3Bhbihgd2ViaG9vazoke2V2ZW50LnNvdXJjZX0vJHtldmVudC5ldmVudFR5cGV9YCwgYXN5bmMgKHNwYW46IFNwYW4pID0+IHtcblx0XHRcdFx0dHJ5IHtcblx0XHRcdFx0XHRjb25zdCBzdGFydCA9IHBlcmZvcm1hbmNlLm5vdygpO1xuXG5cdFx0XHRcdFx0Ly8gSW5pdGlhbGl6ZSBjb25maWd1cmF0aW9uIGZvciB0aGlzIHdvcmtmbG93XG5cdFx0XHRcdFx0YXdhaXQgdGhpcy5jb25maWd1cmF0aW9uLmluaXQod29ya2Zsb3cucGF0aCwgdGhpcy5ub2RlTWFwKTtcblxuXHRcdFx0XHRcdC8vIENyZWF0ZSBjb250ZXh0XG5cdFx0XHRcdFx0Y29uc3QgY3R4OiBDb250ZXh0ID0gdGhpcy5jcmVhdGVDb250ZXh0KHVuZGVmaW5lZCwgd29ya2Zsb3cucGF0aCwgZXhlY3V0aW9uSWQpO1xuXG5cdFx0XHRcdFx0Ly8gUG9wdWxhdGUgcmVxdWVzdCB3aXRoIHdlYmhvb2sgZXZlbnRcblx0XHRcdFx0XHRjdHgucmVxdWVzdCA9IHtcblx0XHRcdFx0XHRcdGJvZHk6IGV2ZW50LnBheWxvYWQsXG5cdFx0XHRcdFx0XHRoZWFkZXJzOiBldmVudC5oZWFkZXJzLFxuXHRcdFx0XHRcdFx0cXVlcnk6IHt9LFxuXHRcdFx0XHRcdFx0cGFyYW1zOiB7XG5cdFx0XHRcdFx0XHRcdHNvdXJjZTogZXZlbnQuc291cmNlLFxuXHRcdFx0XHRcdFx0XHRldmVudFR5cGU6IGV2ZW50LmV2ZW50VHlwZSxcblx0XHRcdFx0XHRcdFx0ZXZlbnRJZDogZXZlbnQuaWQsXG5cdFx0XHRcdFx0XHR9LFxuXHRcdFx0XHRcdH0gYXMgdW5rbm93biBhcyBSZXF1ZXN0Q29udGV4dDtcblxuXHRcdFx0XHRcdC8vIFN0b3JlIHdlYmhvb2sgY29udGV4dCBpbiB2YXJzXG5cdFx0XHRcdFx0aWYgKCFjdHgudmFycykgY3R4LnZhcnMgPSB7fTtcblx0XHRcdFx0XHRjdHgudmFycy5fd2ViaG9va19ldmVudCA9IHtcblx0XHRcdFx0XHRcdGlkOiBldmVudC5pZCxcblx0XHRcdFx0XHRcdHNvdXJjZTogZXZlbnQuc291cmNlLFxuXHRcdFx0XHRcdFx0ZXZlbnRUeXBlOiBldmVudC5ldmVudFR5cGUsXG5cdFx0XHRcdFx0XHR0aW1lc3RhbXA6IGV2ZW50LnRpbWVzdGFtcC50b0lTT1N0cmluZygpLFxuXHRcdFx0XHRcdFx0aGFzU2lnbmF0dXJlOiBTdHJpbmcoISFldmVudC5zaWduYXR1cmUpLFxuXHRcdFx0XHRcdH07XG5cblx0XHRcdFx0XHRjdHgubG9nZ2VyLmxvZyhgUHJvY2Vzc2luZyB3ZWJob29rOiAke2V2ZW50LnNvdXJjZX0vJHtldmVudC5ldmVudFR5cGV9ICgke2V2ZW50LmlkfSlgKTtcblxuXHRcdFx0XHRcdC8vIEV4ZWN1dGUgd29ya2Zsb3dcblx0XHRcdFx0XHRjb25zdCByZXNwb25zZTogVHJpZ2dlclJlc3BvbnNlID0gYXdhaXQgdGhpcy5ydW4oY3R4KTtcblx0XHRcdFx0XHRjb25zdCBlbmQgPSBwZXJmb3JtYW5jZS5ub3coKTtcblxuXHRcdFx0XHRcdC8vIFNldCBzcGFuIGF0dHJpYnV0ZXNcblx0XHRcdFx0XHRzcGFuLnNldEF0dHJpYnV0ZShcInN1Y2Nlc3NcIiwgdHJ1ZSk7XG5cdFx0XHRcdFx0c3Bhbi5zZXRBdHRyaWJ1dGUoXCJldmVudF9pZFwiLCBldmVudC5pZCk7XG5cdFx0XHRcdFx0c3Bhbi5zZXRBdHRyaWJ1dGUoXCJzb3VyY2VcIiwgZXZlbnQuc291cmNlKTtcblx0XHRcdFx0XHRzcGFuLnNldEF0dHJpYnV0ZShcImV2ZW50X3R5cGVcIiwgZXZlbnQuZXZlbnRUeXBlKTtcblx0XHRcdFx0XHRzcGFuLnNldEF0dHJpYnV0ZShcIndvcmtmbG93X3BhdGhcIiwgd29ya2Zsb3cucGF0aCk7XG5cdFx0XHRcdFx0c3Bhbi5zZXRBdHRyaWJ1dGUoXCJlbGFwc2VkX21zXCIsIGVuZCAtIHN0YXJ0KTtcblx0XHRcdFx0XHRzcGFuLnNldFN0YXR1cyh7IGNvZGU6IFNwYW5TdGF0dXNDb2RlLk9LIH0pO1xuXG5cdFx0XHRcdFx0Ly8gUmVjb3JkIG1ldHJpY3Ncblx0XHRcdFx0XHR3ZWJob29rRXhlY3V0aW9ucy5hZGQoMSwge1xuXHRcdFx0XHRcdFx0ZW52OiBwcm9jZXNzLmVudi5OT0RFX0VOVixcblx0XHRcdFx0XHRcdHNvdXJjZTogZXZlbnQuc291cmNlLFxuXHRcdFx0XHRcdFx0ZXZlbnRfdHlwZTogZXZlbnQuZXZlbnRUeXBlLFxuXHRcdFx0XHRcdFx0d29ya2Zsb3dfbmFtZTogdGhpcy5jb25maWd1cmF0aW9uLm5hbWUsXG5cdFx0XHRcdFx0XHRzdWNjZXNzOiBcInRydWVcIixcblx0XHRcdFx0XHR9KTtcblxuXHRcdFx0XHRcdGN0eC5sb2dnZXIubG9nKGBXZWJob29rIHByb2Nlc3NlZCBpbiAkeyhlbmQgLSBzdGFydCkudG9GaXhlZCgyKX1tczogJHtldmVudC5pZH1gKTtcblxuXHRcdFx0XHRcdHJlc29sdmUocmVzcG9uc2UpO1xuXHRcdFx0XHR9IGNhdGNoIChlcnJvcikge1xuXHRcdFx0XHRcdGNvbnN0IGVycm9yTWVzc2FnZSA9IChlcnJvciBhcyBFcnJvcikubWVzc2FnZTtcblxuXHRcdFx0XHRcdC8vIFNldCBzcGFuIGVycm9yXG5cdFx0XHRcdFx0c3Bhbi5zZXRBdHRyaWJ1dGUoXCJzdWNjZXNzXCIsIGZhbHNlKTtcblx0XHRcdFx0XHRzcGFuLnJlY29yZEV4Y2VwdGlvbihlcnJvciBhcyBFcnJvcik7XG5cdFx0XHRcdFx0c3Bhbi5zZXRTdGF0dXMoeyBjb2RlOiBTcGFuU3RhdHVzQ29kZS5FUlJPUiwgbWVzc2FnZTogZXJyb3JNZXNzYWdlIH0pO1xuXG5cdFx0XHRcdFx0Ly8gUmVjb3JkIGVycm9yIG1ldHJpY3Ncblx0XHRcdFx0XHR3ZWJob29rRXJyb3JzLmFkZCgxLCB7XG5cdFx0XHRcdFx0XHRlbnY6IHByb2Nlc3MuZW52Lk5PREVfRU5WLFxuXHRcdFx0XHRcdFx0c291cmNlOiBldmVudC5zb3VyY2UsXG5cdFx0XHRcdFx0XHRldmVudF90eXBlOiBldmVudC5ldmVudFR5cGUsXG5cdFx0XHRcdFx0XHR3b3JrZmxvd19uYW1lOiB0aGlzLmNvbmZpZ3VyYXRpb24/Lm5hbWUgfHwgXCJ1bmtub3duXCIsXG5cdFx0XHRcdFx0fSk7XG5cblx0XHRcdFx0XHR0aGlzLmxvZ2dlci5lcnJvcihgV2ViaG9vayBmYWlsZWQgJHtldmVudC5pZH06ICR7ZXJyb3JNZXNzYWdlfWAsIChlcnJvciBhcyBFcnJvcikuc3RhY2spO1xuXG5cdFx0XHRcdFx0dGhyb3cgZXJyb3I7XG5cdFx0XHRcdH0gZmluYWxseSB7XG5cdFx0XHRcdFx0c3Bhbi5lbmQoKTtcblx0XHRcdFx0fVxuXHRcdFx0fSk7XG5cdFx0fSk7XG5cdH1cblxuXHQvKipcblx0ICogUmVnaXN0ZXIgYSBjdXN0b20gc291cmNlIGhhbmRsZXJcblx0ICovXG5cdHN0YXRpYyByZWdpc3RlclNvdXJjZUhhbmRsZXIoc291cmNlOiBzdHJpbmcsIGhhbmRsZXI6IFdlYmhvb2tTb3VyY2VIYW5kbGVyKTogdm9pZCB7XG5cdFx0c291cmNlSGFuZGxlcnNbc291cmNlXSA9IGhhbmRsZXI7XG5cdH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgV2ViaG9va1RyaWdnZXI7XG5leHBvcnQgeyBzb3VyY2VIYW5kbGVycyB9O1xuIl19
354
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiV2ViaG9va1RyaWdnZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvV2ViaG9va1RyaWdnZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQXNERztBQUVILE9BQU8sRUFDTixhQUFhLEVBQ2IsVUFBVSxFQUVWLFdBQVcsRUFDWCxnQkFBZ0IsR0FDaEIsTUFBTSxnQkFBZ0IsQ0FBQztBQUV4QixPQUFPLEVBQWEsY0FBYyxFQUFFLE9BQU8sRUFBRSxLQUFLLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUUvRSxPQUFPLEVBQUUsRUFBRSxJQUFJLElBQUksRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUVsQyxPQUFPLEVBQUUsaUJBQWlCLEVBQW9DLG1CQUFtQixFQUFFLE1BQU0sYUFBYSxDQUFDO0FBNkJ2RyxNQUFNLHFCQUFxQixHQUFHLEdBQUcsQ0FBQztBQUNsQyxNQUFNLHFCQUFxQixHQUFHLENBQUMsR0FBRyxFQUFFLEdBQUcsSUFBSSxDQUFDLENBQUMsdUNBQXVDO0FBQ3BGLE1BQU0sZ0JBQWdCLEdBQUcsYUFBYSxDQUFDO0FBRXZDLGdGQUFnRjtBQUNoRixnQkFBZ0I7QUFDaEIsZ0ZBQWdGO0FBRWhGLE1BQU0sQ0FBQyxPQUFPLE9BQU8sY0FBZSxTQUFRLFdBQVc7SUFDNUMsT0FBTyxHQUF3QixFQUF5QixDQUFDO0lBQ2hELE1BQU0sR0FBRyxJQUFJLGFBQWEsRUFBRSxDQUFDO0lBQzdCLE1BQU0sR0FBRyxLQUFLLENBQUMsU0FBUyxDQUMxQyxPQUFPLENBQUMsR0FBRyxDQUFDLFlBQVksSUFBSSwwQkFBMEIsRUFDdEQsT0FBTyxDQUFDLEdBQUcsQ0FBQyxlQUFlLElBQUksT0FBTyxDQUN0QyxDQUFDO0lBRWUsS0FBSyxHQUFHLE9BQU8sQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDakMsZUFBZSxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsYUFBYSxDQUFDLDZCQUE2QixFQUFFO1FBQzFGLFdBQVcsRUFBRSwyQ0FBMkM7UUFDeEQsSUFBSSxFQUFFLEdBQUc7S0FDVCxDQUFDLENBQUM7SUFDYyxlQUFlLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxhQUFhLENBQUMsNkJBQTZCLEVBQUU7UUFDMUYsV0FBVyxFQUFFLDBFQUEwRTtRQUN2RixJQUFJLEVBQUUsR0FBRztLQUNULENBQUMsQ0FBQztJQUNjLGVBQWUsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLGFBQWEsQ0FBQyw2QkFBNkIsRUFBRTtRQUMxRixXQUFXLEVBQUUsbURBQW1EO1FBQ2hFLElBQUksRUFBRSxHQUFHO0tBQ1QsQ0FBQyxDQUFDO0lBRUgseUVBQXlFO0lBQ3hELEdBQUcsQ0FBc0I7SUFDekIsV0FBVyxDQUF5QjtJQUU3QyxLQUFLLEdBQUcsS0FBSyxDQUFDO0lBRXRCLGdGQUFnRjtJQUNoRixZQUFZLEdBQXdCLEVBQUUsV0FBNkI7UUFDbEUsS0FBSyxFQUFFLENBQUM7UUFDUixJQUFJLENBQUMsR0FBRyxHQUFHLEdBQUcsQ0FBQztRQUNmLElBQUksQ0FBQyxXQUFXLEdBQUcsV0FBVyxJQUFJLElBQUksQ0FBQztRQUN2Qyx3QkFBd0IsQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUNoQyxDQUFDO0lBRUQ7Ozs7O09BS0c7SUFDSCxVQUFVLENBQUMsT0FBNEI7UUFDdEMsSUFBSSxDQUFDLE9BQU8sR0FBRyxPQUFPLENBQUM7SUFDeEIsQ0FBQztJQUVELEtBQUssQ0FBQyxNQUFNO1FBQ1gsTUFBTSxTQUFTLEdBQUcsSUFBSSxDQUFDLFlBQVksRUFBRSxDQUFDO1FBQ3RDLElBQUksSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFDO1lBQ2hCLElBQUksQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLGlEQUFpRCxDQUFDLENBQUM7WUFDbkUsT0FBTyxJQUFJLENBQUMsVUFBVSxDQUFDLFNBQVMsQ0FBQyxDQUFDO1FBQ25DLENBQUM7UUFDRCxJQUFJLENBQUMsS0FBSyxHQUFHLElBQUksQ0FBQztRQUVsQixJQUFJLElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQztZQUN0QixJQUFJLENBQUMsV0FBVyxDQUFDLGtCQUFrQixDQUFDLEdBQUcsRUFBRTtnQkFDeEMsSUFBSSxDQUFDLDBCQUEwQixFQUFFLENBQUM7WUFDbkMsQ0FBQyxDQUFDLENBQUM7UUFDSixDQUFDO2FBQU0sQ0FBQztZQUNQLElBQUksQ0FBQywwQkFBMEIsRUFBRSxDQUFDO1FBQ25DLENBQUM7UUFFRCxPQUFPLElBQUksQ0FBQyxVQUFVLENBQUMsU0FBUyxDQUFDLENBQUM7SUFDbkMsQ0FBQztJQUVELEtBQUssQ0FBQyxJQUFJO1FBQ1QsSUFBSSxDQUFDLEtBQUssR0FBRyxLQUFLLENBQUM7UUFDbkIsSUFBSSx3QkFBd0IsRUFBRSxLQUFLLElBQUk7WUFBRSx3QkFBd0IsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUN4RSxJQUFJLENBQUMsaUJBQWlCLEVBQUUsQ0FBQztRQUN6QixJQUFJLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyx5QkFBeUIsQ0FBQyxDQUFDO0lBQzVDLENBQUM7SUFFRCw4RUFBOEU7SUFDOUUscUJBQXFCO0lBQ3JCLDhFQUE4RTtJQUV0RSwwQkFBMEI7UUFDakMsTUFBTSxTQUFTLEdBQUcsSUFBSSxDQUFDLG1CQUFtQixFQUFFLENBQUM7UUFDN0MsSUFBSSxTQUFTLENBQUMsTUFBTSxLQUFLLENBQUMsRUFBRSxDQUFDO1lBQzVCLElBQUksQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLHlEQUF5RCxDQUFDLENBQUM7WUFDM0UsT0FBTztRQUNSLENBQUM7UUFDRCxJQUFJLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQywrQkFBK0IsU0FBUyxDQUFDLE1BQU0sb0JBQW9CLENBQUMsQ0FBQztRQUNyRixLQUFLLE1BQU0sS0FBSyxJQUFJLFNBQVMsRUFBRSxDQUFDO1lBQy9CLElBQUksQ0FBQyxvQkFBb0IsQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUNsQyxDQUFDO0lBQ0YsQ0FBQztJQUVPLG9CQUFvQixDQUFDLEtBQTZEO1FBQ3pGLE1BQU0sRUFBRSxZQUFZLEVBQUUsTUFBTSxFQUFFLEdBQUcsS0FBSyxDQUFDO1FBQ3ZDLE1BQU0sSUFBSSxHQUFHLE1BQU0sQ0FBQyxJQUFJLElBQUksQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxhQUFhLE1BQU0sQ0FBQyxRQUFRLEVBQUUsQ0FBQyxDQUFDLENBQUMsYUFBYSxZQUFZLEVBQUUsQ0FBQyxDQUFDO1FBQzdHLE1BQU0sS0FBSyxHQUFHLE1BQU0sQ0FBQyxRQUFRLElBQUksUUFBUSxDQUFDO1FBQzFDLElBQUksQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLDZCQUE2QixJQUFJLFFBQVEsWUFBWSxNQUFNLEtBQUssR0FBRyxDQUFDLENBQUM7UUFFckYsSUFBSSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBYyxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsYUFBYSxDQUFDLENBQUMsRUFBRSxZQUFZLEVBQUUsSUFBSSxFQUFFLE1BQU0sQ0FBQyxDQUFDLENBQUM7SUFDNUYsQ0FBQztJQUVPLEtBQUssQ0FBQyxhQUFhLENBQzFCLENBQWMsRUFDZCxZQUFvQixFQUNwQixJQUFZLEVBQ1osTUFBNEI7UUFFNUIsSUFBSSxDQUFDLGVBQWUsQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLEVBQUUsYUFBYSxFQUFFLFlBQVksRUFBRSxDQUFDLENBQUM7UUFFN0Qsc0VBQXNFO1FBQ3RFLE1BQU0sT0FBTyxHQUFHLE1BQU0sQ0FBQyxDQUFDLEdBQUcsQ0FBQyxJQUFJLEVBQUUsQ0FBQztRQUNuQyxJQUFJLFVBQVUsR0FBWSxFQUFFLENBQUM7UUFDN0IsSUFBSSxPQUFPLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRSxDQUFDO1lBQ3hCLElBQUksQ0FBQztnQkFDSixVQUFVLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQVksQ0FBQztZQUM3QyxDQUFDO1lBQUMsTUFBTSxDQUFDO2dCQUNSLHNEQUFzRDtnQkFDdEQsdURBQXVEO2dCQUN2RCxVQUFVLEdBQUcsT0FBTyxDQUFDO1lBQ3RCLENBQUM7UUFDRixDQUFDO1FBRUQsTUFBTSxPQUFPLEdBQUcsTUFBTSxDQUFDLFdBQVcsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUN0RCxNQUFNLFVBQVUsR0FBRyxDQUFDLENBQUMsR0FBRyxDQUFDLEtBQUssRUFBNEIsQ0FBQztRQUMzRCxNQUFNLFdBQVcsR0FBRyxNQUFNLENBQUMsV0FBVyxDQUFDLElBQUksR0FBRyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUMsWUFBWSxDQUFDLENBQUM7UUFFeEUsd0JBQXdCO1FBQ3hCLE1BQU0sUUFBUSxHQUFHLElBQUksQ0FBQyxlQUFlLENBQUMsWUFBWSxFQUFFLE1BQU0sQ0FBQyxDQUFDO1FBQzVELElBQUksQ0FBQyxRQUFRLEVBQUUsQ0FBQztZQUNmLElBQUksQ0FBQyxlQUFlLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxFQUFFLGFBQWEsRUFBRSxZQUFZLEVBQUUsTUFBTSxFQUFFLGFBQWEsRUFBRSxDQUFDLENBQUM7WUFDcEYsT0FBTyxDQUFDLENBQUMsSUFBSSxDQUFDLEVBQUUsS0FBSyxFQUFFLGVBQWUsRUFBRSxNQUFNLEVBQUUsYUFBYSxFQUFFLE9BQU8sRUFBRSx3QkFBd0IsRUFBRSxFQUFFLEdBQUcsQ0FBQyxDQUFDO1FBQzFHLENBQUM7UUFFRCwwQ0FBMEM7UUFDMUMsTUFBTSxTQUFTLEdBQUcsTUFBTSxDQUFDLFNBQVMsSUFBSSxNQUFNLENBQUMsU0FBUyxFQUFFLFNBQVMsQ0FBQztRQUNsRSxNQUFNLE1BQU0sR0FBRyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxTQUFTLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO1FBRS9ELGFBQWE7UUFDYixNQUFNLFlBQVksR0FBRyxNQUFNLENBQUMsU0FBUyxJQUFJLE1BQU0sQ0FBQyxTQUFTLEVBQUUsU0FBUyxJQUFJLHFCQUFxQixDQUFDO1FBQzlGLE1BQU0sTUFBTSxHQUFpQixRQUFRLENBQUMsTUFBTSxDQUFDO1lBQzVDLE9BQU87WUFDUCxPQUFPO1lBQ1AsVUFBVTtZQUNWLE1BQU07WUFDTixZQUFZO1NBQ1osQ0FBQyxDQUFDO1FBRUgsSUFBSSxDQUFDLE1BQU0sQ0FBQyxFQUFFLEVBQUUsQ0FBQztZQUNoQixJQUFJLENBQUMsZUFBZSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsRUFBRSxhQUFhLEVBQUUsWUFBWSxFQUFFLE1BQU0sRUFBRSxNQUFNLENBQUMsTUFBTSxFQUFFLENBQUMsQ0FBQztZQUNwRixJQUFJLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FDaEIsbUJBQW1CLFlBQVksMEJBQTBCLE1BQU0sQ0FBQyxNQUFNLGFBQWEsTUFBTSxDQUFDLE9BQU8sR0FBRyxDQUNwRyxDQUFDO1lBQ0YsT0FBTyxDQUFDLENBQUMsSUFBSSxDQUFDLEVBQUUsS0FBSyxFQUFFLGNBQWMsRUFBRSxNQUFNLEVBQUUsTUFBTSxDQUFDLE1BQU0sRUFBRSxPQUFPLEVBQUUsTUFBTSxDQUFDLE9BQU8sRUFBRSxFQUFFLEdBQUcsQ0FBQyxDQUFDO1FBQy9GLENBQUM7UUFFRCwwRUFBMEU7UUFDMUUsSUFBSSxLQUFLLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsSUFBSSxNQUFNLENBQUMsTUFBTSxDQUFDLE1BQU0sR0FBRyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLEVBQUUsQ0FBQztZQUMzRyxJQUFJLENBQUMsZUFBZSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsRUFBRSxhQUFhLEVBQUUsWUFBWSxFQUFFLE1BQU0sRUFBRSxtQkFBbUIsRUFBRSxDQUFDLENBQUM7WUFDMUYsT0FBTyxDQUFDLENBQUMsSUFBSSxDQUFDLEVBQUUsTUFBTSxFQUFFLFNBQVMsRUFBRSxNQUFNLEVBQUUsbUJBQW1CLEVBQUUsU0FBUyxFQUFFLE1BQU0sQ0FBQyxTQUFTLEVBQUUsRUFBRSxHQUFHLENBQUMsQ0FBQztRQUNyRyxDQUFDO1FBRUQsa0RBQWtEO1FBQ2xELElBQUksTUFBTSxDQUFDLGNBQWMsSUFBSSxNQUFNLENBQUMsT0FBTyxFQUFFLENBQUM7WUFDN0MsTUFBTSxPQUFPLEdBQUcsVUFBVSxDQUFDLFdBQVcsRUFBRSxDQUFDO1lBQ3pDLE1BQU0sS0FBSyxHQUFHLE9BQU8sQ0FBQyxRQUFRLEVBQUUsQ0FBQztZQUNqQyxNQUFNLE1BQU0sR0FBRyxLQUFLLENBQUMsbUJBQW1CLENBQUMsZ0JBQWdCLEVBQUUsWUFBWSxFQUFFLE1BQU0sQ0FBQyxPQUFPLENBQUMsQ0FBQztZQUN6RixJQUFJLE1BQU0sRUFBRSxDQUFDO2dCQUNaLElBQUksQ0FBQyxlQUFlLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxFQUFFLGFBQWEsRUFBRSxZQUFZLEVBQUUsTUFBTSxFQUFFLFFBQVEsRUFBRSxDQUFDLENBQUM7Z0JBQy9FLE9BQU8sQ0FBQyxDQUFDLElBQUksQ0FDWjtvQkFDQyxNQUFNLEVBQUUsV0FBVztvQkFDbkIsT0FBTyxFQUFFLE1BQU0sQ0FBQyxPQUFPO29CQUN2QixTQUFTLEVBQUUsTUFBTSxDQUFDLFNBQVM7b0JBQzNCLGNBQWMsRUFBRSxNQUFNLENBQUMsV0FBVztpQkFDbEMsRUFDRCxHQUFHLENBQ0gsQ0FBQztZQUNILENBQUM7UUFDRixDQUFDO1FBRUQsbURBQW1EO1FBQ25ELElBQUksQ0FBQyxlQUFlLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxFQUFFLGFBQWEsRUFBRSxZQUFZLEVBQUUsQ0FBQyxDQUFDO1FBQzdELE1BQU0sU0FBUyxHQUFHLElBQUksRUFBRSxDQUFDO1FBQ3pCLE1BQU0sZUFBZSxHQUFHLE1BQU0sSUFBSSxDQUFDLGdCQUFnQixDQUFDO1lBQ25ELFlBQVk7WUFDWixJQUFJO1lBQ0osTUFBTTtZQUNOLFNBQVM7WUFDVCxPQUFPO1lBQ1AsSUFBSSxFQUFFLFVBQVU7WUFDaEIsT0FBTztZQUNQLFVBQVU7WUFDVixXQUFXO1lBQ1gsT0FBTyxFQUFFLE1BQU0sQ0FBQyxPQUFPO1lBQ3ZCLFNBQVMsRUFBRSxNQUFNLENBQUMsU0FBUztTQUMzQixDQUFDLENBQUM7UUFFSCxnRUFBZ0U7UUFDaEUsa0VBQWtFO1FBQ2xFLDJEQUEyRDtRQUMzRCxtRUFBbUU7UUFDbkUsSUFBSSxNQUFNLENBQUMsY0FBYyxJQUFJLE1BQU0sQ0FBQyxPQUFPLEVBQUUsQ0FBQztZQUM3QyxNQUFNLE9BQU8sR0FBRyxVQUFVLENBQUMsV0FBVyxFQUFFLENBQUM7WUFDekMsTUFBTSxLQUFLLEdBQUcsT0FBTyxDQUFDLFFBQVEsRUFBRSxDQUFDO1lBQ2pDLEtBQUssQ0FBQyxtQkFBbUIsQ0FBQyxnQkFBZ0IsRUFBRSxZQUFZLEVBQUUsTUFBTSxDQUFDLE9BQU8sRUFBRTtnQkFDekUsSUFBSSxFQUFFLEVBQUUsT0FBTyxFQUFFLE1BQU0sQ0FBQyxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sQ0FBQyxTQUFTLEVBQUU7Z0JBQzlELFFBQVEsRUFBRSxJQUFJLENBQUMsR0FBRyxFQUFFO2dCQUNwQixTQUFTLEVBQUUsSUFBSSxDQUFDLEdBQUcsRUFBRSxHQUFHLHFCQUFxQjtnQkFDN0MsV0FBVyxFQUFFLFNBQVM7Z0JBQ3RCLGVBQWUsRUFBRSxTQUFTO2FBQzFCLENBQUMsQ0FBQztRQUNKLENBQUM7UUFFRCxnRUFBZ0U7UUFDaEUseUNBQXlDO1FBQ3pDLE9BQU8sQ0FBQyxDQUFDLElBQUksQ0FDWjtZQUNDLE1BQU0sRUFBRSxJQUFJO1lBQ1osT0FBTyxFQUFFLE1BQU0sQ0FBQyxPQUFPO1lBQ3ZCLFNBQVMsRUFBRSxNQUFNLENBQUMsU0FBUztZQUMzQixLQUFLLEVBQUUsU0FBUztZQUNoQixRQUFRLEVBQUUsZUFBZTtTQUN6QixFQUNELEdBQUcsQ0FDSCxDQUFDO0lBQ0gsQ0FBQztJQUVPLGVBQWUsQ0FBQyxZQUFvQixFQUFFLE1BQTRCO1FBQ3pFLElBQUksTUFBTSxDQUFDLFFBQVEsRUFBRSxDQUFDO1lBQ3JCLE1BQU0sQ0FBQyxHQUFHLGlCQUFpQixDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsQ0FBQztZQUM3QyxJQUFJLENBQUMsQ0FBQyxFQUFFLENBQUM7Z0JBQ1IsSUFBSSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsbUJBQW1CLFlBQVksdUJBQXVCLE1BQU0sQ0FBQyxRQUFRLEdBQUcsQ0FBQyxDQUFDO2dCQUM1RixPQUFPLElBQUksQ0FBQztZQUNiLENBQUM7WUFDRCxPQUFPLENBQUMsQ0FBQztRQUNWLENBQUM7UUFDRCxJQUFJLE1BQU0sQ0FBQyxTQUFTLEVBQUUsQ0FBQztZQUN0QixPQUFPLG1CQUFtQixDQUFDO2dCQUMxQixNQUFNLEVBQUUsTUFBTSxDQUFDLFNBQVMsQ0FBQyxNQUFNLElBQUksYUFBYTtnQkFDaEQsTUFBTSxFQUFFLE1BQU0sQ0FBQyxTQUFTLENBQUMsTUFBTTtnQkFDL0IsTUFBTSxFQUFFLE1BQU0sQ0FBQyxTQUFTLENBQUMsTUFBTSxJQUFJLE9BQU87Z0JBQzFDLFNBQVMsRUFBRSxNQUFNLENBQUMsU0FBUyxDQUFDLFNBQVM7Z0JBQ3JDLFNBQVMsRUFBRSxNQUFNLENBQUMsU0FBUyxDQUFDLFNBQVMsSUFBSSxxQkFBcUI7Z0JBQzlELGVBQWUsRUFBRSxNQUFNLENBQUMsU0FBUyxDQUFDLGVBQWU7YUFDakQsQ0FBQyxDQUFDO1FBQ0osQ0FBQztRQUNELE9BQU8sSUFBSSxDQUFDO0lBQ2IsQ0FBQztJQUVELDhFQUE4RTtJQUM5RSxvQkFBb0I7SUFDcEIsOEVBQThFO0lBRXRFLEtBQUssQ0FBQyxnQkFBZ0IsQ0FBQyxJQVk5QjtRQUNBLE1BQU0sRUFBRSxZQUFZLEVBQUUsU0FBUyxFQUFFLE9BQU8sRUFBRSxJQUFJLEVBQUUsT0FBTyxFQUFFLFVBQVUsRUFBRSxXQUFXLEVBQUUsT0FBTyxFQUFFLFNBQVMsRUFBRSxHQUFHLElBQUksQ0FBQztRQUU5RyxPQUFPLElBQUksQ0FBQyxNQUFNLENBQUMsZUFBZSxDQUFDLFdBQVcsWUFBWSxFQUFFLEVBQUUsS0FBSyxFQUFFLElBQVUsRUFBRSxFQUFFO1lBQ2xGLElBQUksQ0FBQztnQkFDSixNQUFNLFFBQVEsR0FBRyxnQkFBZ0IsQ0FBQyxXQUFXLEVBQUUsQ0FBQztnQkFDaEQsTUFBTSxLQUFLLEdBQUcsUUFBUSxDQUFDLEdBQUcsQ0FBQyxZQUFZLENBQUMsQ0FBQztnQkFDekMsSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFDO29CQUNaLE1BQU0sSUFBSSxLQUFLLENBQUMsNkJBQTZCLFlBQVkseUJBQXlCLENBQUMsQ0FBQztnQkFDckYsQ0FBQztnQkFDRCxNQUFNLElBQUksQ0FBQyxhQUFhLENBQUMsSUFBSSxDQUFDLFlBQVksRUFBRSxJQUFJLENBQUMsT0FBTyxFQUFFLEtBQUssQ0FBQyxRQUFRLENBQUMsQ0FBQztnQkFFMUUsTUFBTSxHQUFHLEdBQVksSUFBSSxDQUFDLGFBQWEsQ0FBQyxTQUFTLEVBQUUsWUFBWSxFQUFFLFNBQVMsQ0FBQyxDQUFDO2dCQUM1RSxHQUFHLENBQUMsT0FBTyxHQUFHO29CQUNiLElBQUk7b0JBQ0osT0FBTztvQkFDUCxPQUFPO29CQUNQLE1BQU0sRUFBRSxVQUFVO29CQUNsQixLQUFLLEVBQUUsV0FBVztpQkFDVyxDQUFDO2dCQUUvQiwwREFBMEQ7Z0JBQzFELGlEQUFpRDtnQkFDaEQsR0FBK0IsQ0FBQyxRQUFRLEdBQUc7b0JBQzNDLE9BQU87b0JBQ1AsU0FBUztvQkFDVCxTQUFTLEVBQUUsSUFBSSxDQUFDLE1BQU0sQ0FBQyxTQUFTO2lCQUNoQyxDQUFDO2dCQUVGLE1BQU0sSUFBSSxDQUFDLG9CQUFvQixDQUFDLEdBQUcsRUFBRSxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUM7Z0JBQ25ELE1BQU0sSUFBSSxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQztnQkFFcEIsSUFBSSxDQUFDLFlBQVksQ0FBQyxlQUFlLEVBQUUsWUFBWSxDQUFDLENBQUM7Z0JBQ2pELElBQUksQ0FBQyxZQUFZLENBQUMsVUFBVSxFQUFFLE9BQU8sQ0FBQyxDQUFDO2dCQUN2QyxJQUFJLENBQUMsWUFBWSxDQUFDLFlBQVksRUFBRSxTQUFTLENBQUMsQ0FBQztnQkFDM0MsSUFBSSxDQUFDLFNBQVMsQ0FBQyxFQUFFLElBQUksRUFBRSxjQUFjLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQztnQkFDNUMsT0FBTyxHQUFHLENBQUMsUUFBUSxDQUFDO1lBQ3JCLENBQUM7WUFBQyxPQUFPLEdBQUcsRUFBRSxDQUFDO2dCQUNkLE1BQU0sR0FBRyxHQUFHLEdBQUcsWUFBWSxLQUFLLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQztnQkFDN0QsSUFBSSxDQUFDLGVBQWUsQ0FBQyxHQUFZLENBQUMsQ0FBQztnQkFDbkMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxFQUFFLElBQUksRUFBRSxjQUFjLENBQUMsS0FBSyxFQUFFLE9BQU8sRUFBRSxHQUFHLEVBQUUsQ0FBQyxDQUFDO2dCQUM3RCxJQUFJLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyw0QkFBNEIsWUFBWSxZQUFZLEdBQUcsRUFBRSxDQUFDLENBQUM7Z0JBQzdFLE9BQU8sRUFBRSxLQUFLLEVBQUUsR0FBRyxFQUFFLENBQUM7WUFDdkIsQ0FBQztvQkFBUyxDQUFDO2dCQUNWLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQztZQUNaLENBQUM7UUFDRixDQUFDLENBQUMsQ0FBQztJQUNKLENBQUM7SUFFRCw4RUFBOEU7SUFDOUUsZ0JBQWdCO0lBQ2hCLDhFQUE4RTtJQUU5RSxRQUFRO1FBQ1AsT0FBTyxFQUFFLG1CQUFtQixFQUFFLElBQUksQ0FBQyxtQkFBbUIsRUFBRSxDQUFDLE1BQU0sRUFBRSxDQUFDO0lBQ25FLENBQUM7SUFFTyxtQkFBbUI7UUFDMUIsTUFBTSxRQUFRLEdBQUcsZ0JBQWdCLENBQUMsV0FBVyxFQUFFLENBQUM7UUFDaEQsTUFBTSxHQUFHLEdBQWtFLEVBQUUsQ0FBQztRQUM5RSxLQUFLLE1BQU0sS0FBSyxJQUFJLFFBQVEsQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDO1lBQ3JDLE1BQU0sRUFBRSxHQUFHLEtBQUssQ0FBQyxRQUF3RSxDQUFDO1lBQzFGLE1BQU0sR0FBRyxHQUFHLEVBQUUsRUFBRSxPQUFPLEVBQUUsT0FBTyxDQUFDO1lBQ2pDLElBQUksQ0FBQyxHQUFHO2dCQUFFLFNBQVM7WUFDbkIsZ0VBQWdFO1lBQ2hFLDJEQUEyRDtZQUMzRCxJQUFJLENBQUMsR0FBRyxDQUFDLFFBQVEsSUFBSSxDQUFDLEdBQUcsQ0FBQyxTQUFTLEVBQUUsQ0FBQztnQkFDckMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQ2hCLDZCQUE2QixLQUFLLENBQUMsSUFBSSx5SEFBeUgsQ0FDaEssQ0FBQztnQkFDRixTQUFTO1lBQ1YsQ0FBQztZQUNELEdBQUcsQ0FBQyxJQUFJLENBQUMsRUFBRSxZQUFZLEVBQUUsS0FBSyxDQUFDLElBQUksRUFBRSxNQUFNLEVBQUUsR0FBRyxFQUFFLENBQUMsQ0FBQztRQUNyRCxDQUFDO1FBQ0QsT0FBTyxHQUFHLENBQUM7SUFDWixDQUFDO0NBQ0Q7QUFFRCxnRkFBZ0Y7QUFDaEYsd0NBQXdDO0FBQ3hDLGdGQUFnRjtBQUVoRixJQUFJLGFBQWEsR0FBMEIsSUFBSSxDQUFDO0FBRWhELE1BQU0sVUFBVSx3QkFBd0IsQ0FBQyxPQUE4QjtJQUN0RSxhQUFhLEdBQUcsT0FBTyxDQUFDO0FBQ3pCLENBQUM7QUFFRCxNQUFNLFVBQVUsd0JBQXdCO0lBQ3ZDLE9BQU8sYUFBYSxDQUFDO0FBQ3RCLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIFdlYmhvb2tUcmlnZ2VyIOKAlCB2MC43IFBSIDQg4oCUIEluYm91bmQgd2ViaG9vayB0cmlnZ2VyIHRoYXQgbW91bnRzXG4gKiB2ZXJpZmllZCBQT1NUIHJvdXRlcyBvbiB0aGUgc2hhcmVkIEhvbm8gYXBwLiBPbmUgcm91dGUgcGVyIHdvcmtmbG93XG4gKiB3aG9zZSBgdHJpZ2dlci53ZWJob29rYCBjb25maWcgaXMgcmVnaXN0ZXJlZC5cbiAqXG4gKiAqKkF1dGhvcmluZyBzdXJmYWNlIChidWlsdC1pbiBwcm92aWRlcik6KipcbiAqXG4gKiBgYGBqc29uXG4gKiB7XG4gKiAgIFwibmFtZVwiOiBcInN0cmlwZS1ldmVudHNcIixcbiAqICAgXCJ0cmlnZ2VyXCI6IHtcbiAqICAgICBcIndlYmhvb2tcIjoge1xuICogICAgICAgXCJwcm92aWRlclwiOiBcInN0cmlwZVwiLFxuICogICAgICAgXCJwYXRoXCI6IFwiL3dlYmhvb2tzL3N0cmlwZVwiLFxuICogICAgICAgXCJzZWNyZXRFbnZcIjogXCJTVFJJUEVfV0VCSE9PS19TRUNSRVRcIixcbiAqICAgICAgIFwibmFtZXNwYWNlXCI6IFwic3RyaXBlXCIsXG4gKiAgICAgICBcImlkZW1wb3RlbmN5S2V5XCI6IFwianMvY3R4LnJlcXVlc3QuYm9keS5pZFwiXG4gKiAgICAgfVxuICogICB9LFxuICogICBcInN0ZXBzXCI6IFtcbiAqICAgICB7IFwiaWRcIjogXCJkaXNwYXRjaFwiLCBcInN1YndvcmtmbG93XCI6IFwianMvY3R4LnJlcXVlc3QuYm9keS50eXBlXCIsIFwiaW5wdXRzXCI6IHsgXCJzdHJpcGVFdmVudFwiOiBcImpzL2N0eC5yZXF1ZXN0LmJvZHlcIiB9IH1cbiAqICAgXVxuICogfVxuICogYGBgXG4gKlxuICogKipQaXBlbGluZSAocGVyIGluYm91bmQgcmVxdWVzdCk6KipcbiAqXG4gKiAgIDEuIFJlYWQgcmF3IGJvZHkg4oCUIHZlcmlmaWVycyBNVVNUIHNpZ24gdGhlIGJ5dGVzIHRoYXQgY3Jvc3NlZFxuICogICAgICB0aGUgd2lyZSwgbm90IHRoZSBKU09OLXJlLXN0cmluZ2lmaWVkIGJvZHkgKFN0cmlwZSAvIEdpdEh1YiAvXG4gKiAgICAgIFNsYWNrIGFsbCBzaWduIHJhdyBieXRlcykuXG4gKiAgIDIuIFZlcmlmeSB0aGUgc2lnbmF0dXJlIHZpYSB0aGUgcGVyLXByb3ZpZGVyIHN0cmF0ZWd5XG4gKiAgICAgIChgdmVyaWZpZXJzLnRzYCkuIE9uIGZhaWx1cmUsIHJldHVybiA0MDEgd2l0aCBzdHJ1Y3R1cmVkXG4gKiAgICAgIGB7IGVycm9yLCByZWFzb24sIG1lc3NhZ2UgfWAuXG4gKiAgIDMuIFJlcGxheSBjaGVjazogaWYgYGlkZW1wb3RlbmN5S2V5YCBpcyBjb25maWd1cmVkLCBsb29rIHVwXG4gKiAgICAgIGAod29ya2Zsb3dOYW1lLCBldmVudElkKWAgaW4gdGhlIGlkZW1wb3RlbmN5IGNhY2hlIChzYW1lIHN0b3JlXG4gKiAgICAgIGFzIFRpZXIgMSBzdGVwIGNhY2hpbmcpLiBPbiBoaXQsIHJldHVybiAyMDAgd2l0aFxuICogICAgICBgeyBzdGF0dXM6IFwiZHVwbGljYXRlXCIsIGV2ZW50SWQgfWAgYW5kIERPTidUIHJ1biB0aGUgd29ya2Zsb3cuXG4gKiAgIDQuIEV2ZW50cyBhbGxvd2xpc3Q6IGlmIGBldmVudHM6IFsuLi5dYCBpcyBjb25maWd1cmVkLCBza2lwXG4gKiAgICAgIHdvcmtmbG93IHJ1bnMgd2hvc2UgZXZlbnQgdHlwZSBpc24ndCBpbiB0aGUgbGlzdCDigJQgcmV0dXJuXG4gKiAgICAgIDIwMCB3aXRoIGB7IHN0YXR1czogXCJpZ25vcmVkXCIsIGV2ZW50VHlwZSB9YCBzbyB0aGUgc2VuZGVyXG4gKiAgICAgIGRvZXNuJ3QgcmV0cnkuXG4gKiAgIDUuIFJ1biB0aGUgd29ya2Zsb3cgdGhyb3VnaCBgVHJpZ2dlckJhc2UucnVuYCBzbyBtaWRkbGV3YXJlLFxuICogICAgICB0cmFjaW5nLCByZXRyaWVzLCBjb25jdXJyZW5jeSwgZXRjLiBhcHBseSB1bmlmb3JtbHkuXG4gKiAgIDYuIENhY2hlIHRoZSBldmVudElkIHNvIGEgcmV0cnkgd2l0aGluIHRoZSBUVEwgd2luZG93IHJldHVybnNcbiAqICAgICAgdGhlIGR1cGxpY2F0ZSByZXNwb25zZS5cbiAqXG4gKiAqKkhvbm8gaW50ZWdyYXRpb246KiogaWRlbnRpY2FsIHRvIFdlYlNvY2tldCBhbmQgU1NFIOKAlCBhY2NlcHRzIHRoZVxuICogc2hhcmVkIGBIb25vPGFueSwgYW55LCBhbnk+YCBhcHAgYW5kIGFuIG9wdGlvbmFsIGBIdHRwVHJpZ2dlckxpa2VgXG4gKiBleHBvc2luZyBgYWRkUHJlQ2F0Y2hBbGxIb29rYCBzbyB3ZWJob29rIHJvdXRlcyBtb3VudCBCRUZPUkUgdGhlXG4gKiBsZWdhY3kgYC86d29ya2Zsb3d7Lit9YCBjYXRjaC1hbGwgYW5kIHdpbiBIb25vJ3MgZmlyc3QtbWF0Y2hcbiAqIGRpc3BhdGNoLlxuICpcbiAqIFNlZSBbYWRkaXRpb25hbC10cmlnZ2Vycy1wbGFuLm1keF0oLi4vLi4vLi4vZG9jcy9jL2RldnRvb2xzL2FkZGl0aW9uYWwtdHJpZ2dlcnMtcGxhbi5tZHgjd2ViaG9vay10cmlnZ2VyKVxuICogZm9yIHRoZSBmdWxsIHYwLjcgZGVzaWduLlxuICovXG5cbmltcG9ydCB7XG5cdERlZmF1bHRMb2dnZXIsXG5cdFJ1blRyYWNrZXIsXG5cdHR5cGUgR2xvYmFsT3B0aW9ucyBhcyBSdW5uZXJHbG9iYWxPcHRpb25zLFxuXHRUcmlnZ2VyQmFzZSxcblx0V29ya2Zsb3dSZWdpc3RyeSxcbn0gZnJvbSBcIkBibG9ranMvcnVubmVyXCI7XG5pbXBvcnQgdHlwZSB7IENvbnRleHQsIFJlcXVlc3RDb250ZXh0IH0gZnJvbSBcIkBibG9ranMvc2hhcmVkXCI7XG5pbXBvcnQgeyB0eXBlIFNwYW4sIFNwYW5TdGF0dXNDb2RlLCBtZXRyaWNzLCB0cmFjZSB9IGZyb20gXCJAb3BlbnRlbGVtZXRyeS9hcGlcIjtcbmltcG9ydCB0eXBlIHsgSG9ubywgQ29udGV4dCBhcyBIb25vQ29udGV4dCB9IGZyb20gXCJob25vXCI7XG5pbXBvcnQgeyB2NCBhcyB1dWlkIH0gZnJvbSBcInV1aWRcIjtcblxuaW1wb3J0IHsgQlVJTFRJTl9WRVJJRklFUlMsIHR5cGUgVmVyaWZpZXIsIHR5cGUgVmVyaWZ5UmVzdWx0LCBidWlsZEN1c3RvbVZlcmlmaWVyIH0gZnJvbSBcIi4vdmVyaWZpZXJzXCI7XG5cbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4vLyBUeXBlc1xuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuaW50ZXJmYWNlIFdlYmhvb2tUcmlnZ2VyQ29uZmlnIHtcblx0cHJvdmlkZXI/OiBcImdpdGh1YlwiIHwgXCJzdHJpcGVcIiB8IFwic2xhY2tcIiB8IFwic2hvcGlmeVwiIHwgXCJzdml4XCI7XG5cdHBhdGg/OiBzdHJpbmc7XG5cdGV2ZW50cz86IHN0cmluZ1tdO1xuXHRzZWNyZXRFbnY/OiBzdHJpbmc7XG5cdHNpZ25hdHVyZT86IHtcblx0XHRzY2hlbWU/OiBcImhtYWMtc2hhMjU2XCIgfCBcImhtYWMtc2hhMVwiIHwgXCJobWFjLXNoYTUxMlwiO1xuXHRcdGhlYWRlcjogc3RyaW5nO1xuXHRcdGZvcm1hdD86IHN0cmluZztcblx0XHRzZWNyZXRFbnY6IHN0cmluZztcblx0XHR0b2xlcmFuY2U/OiBudW1iZXI7XG5cdFx0dGltZXN0YW1wSGVhZGVyPzogc3RyaW5nO1xuXHR9O1xuXHR0b2xlcmFuY2U/OiBudW1iZXI7XG5cdGlkZW1wb3RlbmN5S2V5Pzogc3RyaW5nO1xuXHRuYW1lc3BhY2U/OiBzdHJpbmc7XG5cdG1pZGRsZXdhcmU/OiBzdHJpbmdbXTtcbn1cblxuaW50ZXJmYWNlIEh0dHBUcmlnZ2VyTGlrZSB7XG5cdGFkZFByZUNhdGNoQWxsSG9vayhjYjogKCkgPT4gdm9pZCB8IFByb21pc2U8dm9pZD4pOiB2b2lkO1xufVxuXG5jb25zdCBERUZBVUxUX1RPTEVSQU5DRV9TRUMgPSAzMDA7XG5jb25zdCBERUZBVUxUX1JFUExBWV9UVExfTVMgPSA1ICogNjAgKiAxMDAwOyAvLyA1IG1pbiDigJQgbWF0Y2ggU3RyaXBlIC8gU3ZpeCBkZWZhdWx0LlxuY29uc3QgUkVQTEFZX05BTUVTUEFDRSA9IFwiX193ZWJob29rX19cIjtcblxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbi8vIFRyaWdnZXIgY2xhc3Ncbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFdlYmhvb2tUcmlnZ2VyIGV4dGVuZHMgVHJpZ2dlckJhc2Uge1xuXHRwcm90ZWN0ZWQgbm9kZU1hcDogUnVubmVyR2xvYmFsT3B0aW9ucyA9IHt9IGFzIFJ1bm5lckdsb2JhbE9wdGlvbnM7XG5cdHByb3RlY3RlZCByZWFkb25seSBsb2dnZXIgPSBuZXcgRGVmYXVsdExvZ2dlcigpO1xuXHRwcm90ZWN0ZWQgcmVhZG9ubHkgdHJhY2VyID0gdHJhY2UuZ2V0VHJhY2VyKFxuXHRcdHByb2Nlc3MuZW52LlBST0pFQ1RfTkFNRSB8fCBcInRyaWdnZXItd2ViaG9vay13b3JrZmxvd1wiLFxuXHRcdHByb2Nlc3MuZW52LlBST0pFQ1RfVkVSU0lPTiB8fCBcIjAuMC4xXCIsXG5cdCk7XG5cblx0cHJpdmF0ZSByZWFkb25seSBtZXRlciA9IG1ldHJpY3MuZ2V0TWV0ZXIoXCJibG9rXCIpO1xuXHRwcml2YXRlIHJlYWRvbmx5IGNvdW50ZXJSZWNlaXZlZCA9IHRoaXMubWV0ZXIuY3JlYXRlQ291bnRlcihcImJsb2tfd2ViaG9va19yZWNlaXZlZF90b3RhbFwiLCB7XG5cdFx0ZGVzY3JpcHRpb246IFwiV2ViaG9vayBkZWxpdmVyaWVzIHJlY2VpdmVkIChjdW11bGF0aXZlKS5cIixcblx0XHR1bml0OiBcIjFcIixcblx0fSk7XG5cdHByaXZhdGUgcmVhZG9ubHkgY291bnRlclJlamVjdGVkID0gdGhpcy5tZXRlci5jcmVhdGVDb3VudGVyKFwiYmxva193ZWJob29rX3JlamVjdGVkX3RvdGFsXCIsIHtcblx0XHRkZXNjcmlwdGlvbjogXCJXZWJob29rIGRlbGl2ZXJpZXMgcmVqZWN0ZWQgKHNpZ25hdHVyZSBmYWlsdXJlLCBhbGxvd2xpc3QgbWlzcywgcmVwbGF5KS5cIixcblx0XHR1bml0OiBcIjFcIixcblx0fSk7XG5cdHByaXZhdGUgcmVhZG9ubHkgY291bnRlckFjY2VwdGVkID0gdGhpcy5tZXRlci5jcmVhdGVDb3VudGVyKFwiYmxva193ZWJob29rX2FjY2VwdGVkX3RvdGFsXCIsIHtcblx0XHRkZXNjcmlwdGlvbjogXCJXZWJob29rIGRlbGl2ZXJpZXMgdGhhdCB0cmlnZ2VyZWQgYSB3b3JrZmxvdyBydW4uXCIsXG5cdFx0dW5pdDogXCIxXCIsXG5cdH0pO1xuXG5cdC8vIGJpb21lLWlnbm9yZSBsaW50L3N1c3BpY2lvdXMvbm9FeHBsaWNpdEFueTogSG9ubydzIGdlbmVyaWMgcHJvcGFnYXRpb25cblx0cHJpdmF0ZSByZWFkb25seSBhcHA6IEhvbm88YW55LCBhbnksIGFueT47XG5cdHByaXZhdGUgcmVhZG9ubHkgaHR0cFRyaWdnZXI6IEh0dHBUcmlnZ2VyTGlrZSB8IG51bGw7XG5cblx0cHJpdmF0ZSB3aXJlZCA9IGZhbHNlO1xuXG5cdC8vIGJpb21lLWlnbm9yZSBsaW50L3N1c3BpY2lvdXMvbm9FeHBsaWNpdEFueTogbWF0Y2hlcyBgYXBwYCBmaWVsZCdzIGFueSBnZW5lcmljXG5cdGNvbnN0cnVjdG9yKGFwcDogSG9ubzxhbnksIGFueSwgYW55PiwgaHR0cFRyaWdnZXI/OiBIdHRwVHJpZ2dlckxpa2UpIHtcblx0XHRzdXBlcigpO1xuXHRcdHRoaXMuYXBwID0gYXBwO1xuXHRcdHRoaXMuaHR0cFRyaWdnZXIgPSBodHRwVHJpZ2dlciA/PyBudWxsO1xuXHRcdF9zZXRBY3RpdmVXZWJob29rVHJpZ2dlcih0aGlzKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBJbmplY3QgdGhlIHJ1bm5lcidzIEdsb2JhbE9wdGlvbnMgKG5vZGVzICsgd29ya2Zsb3dzKS4gQ2FsbGVkIGJ5XG5cdCAqIHRoZSBvcmNoZXN0cmF0b3IgQUZURVIgY29uc3RydWN0aW5nIHRoZSB0cmlnZ2VyIGJ1dCBCRUZPUkVcblx0ICogYGxpc3RlbigpYC4gU2hhcmVzIEh0dHBUcmlnZ2VyJ3Mgbm9kZU1hcCBzbyBwZXItcmVxdWVzdCB3b3JrZmxvd1xuXHQgKiBydW5zIHJlc29sdmUgaGVscGVycyArIHN1Yi13b3JrZmxvd3MgdGhyb3VnaCB0aGUgc2FtZSByZWdpc3RyeS5cblx0ICovXG5cdHNldE5vZGVNYXAobm9kZU1hcDogUnVubmVyR2xvYmFsT3B0aW9ucyk6IHZvaWQge1xuXHRcdHRoaXMubm9kZU1hcCA9IG5vZGVNYXA7XG5cdH1cblxuXHRhc3luYyBsaXN0ZW4oKTogUHJvbWlzZTxudW1iZXI+IHtcblx0XHRjb25zdCBzdGFydFRpbWUgPSB0aGlzLnN0YXJ0Q291bnRlcigpO1xuXHRcdGlmICh0aGlzLndpcmVkKSB7XG5cdFx0XHR0aGlzLmxvZ2dlci5sb2coXCJbYmxva11bd2ViaG9va10gbGlzdGVuKCkgY2FsbGVkIHR3aWNlOyBpZ25vcmluZ1wiKTtcblx0XHRcdHJldHVybiB0aGlzLmVuZENvdW50ZXIoc3RhcnRUaW1lKTtcblx0XHR9XG5cdFx0dGhpcy53aXJlZCA9IHRydWU7XG5cblx0XHRpZiAodGhpcy5odHRwVHJpZ2dlcikge1xuXHRcdFx0dGhpcy5odHRwVHJpZ2dlci5hZGRQcmVDYXRjaEFsbEhvb2soKCkgPT4ge1xuXHRcdFx0XHR0aGlzLnJlZ2lzdGVyUm91dGVzRnJvbVJlZ2lzdHJ5KCk7XG5cdFx0XHR9KTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0dGhpcy5yZWdpc3RlclJvdXRlc0Zyb21SZWdpc3RyeSgpO1xuXHRcdH1cblxuXHRcdHJldHVybiB0aGlzLmVuZENvdW50ZXIoc3RhcnRUaW1lKTtcblx0fVxuXG5cdGFzeW5jIHN0b3AoKTogUHJvbWlzZTx2b2lkPiB7XG5cdFx0dGhpcy53aXJlZCA9IGZhbHNlO1xuXHRcdGlmIChfZ2V0QWN0aXZlV2ViaG9va1RyaWdnZXIoKSA9PT0gdGhpcykgX3NldEFjdGl2ZVdlYmhvb2tUcmlnZ2VyKG51bGwpO1xuXHRcdHRoaXMuZGVzdHJveU1vbml0b3JpbmcoKTtcblx0XHR0aGlzLmxvZ2dlci5sb2coXCJbYmxva11bd2ViaG9va10gc3RvcHBlZFwiKTtcblx0fVxuXG5cdC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXHQvLyBSb3V0ZSByZWdpc3RyYXRpb25cblx0Ly8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cblx0cHJpdmF0ZSByZWdpc3RlclJvdXRlc0Zyb21SZWdpc3RyeSgpOiB2b2lkIHtcblx0XHRjb25zdCB3b3JrZmxvd3MgPSB0aGlzLmdldFdlYmhvb2tXb3JrZmxvd3MoKTtcblx0XHRpZiAod29ya2Zsb3dzLmxlbmd0aCA9PT0gMCkge1xuXHRcdFx0dGhpcy5sb2dnZXIubG9nKFwiW2Jsb2tdW3dlYmhvb2tdIG5vIHdvcmtmbG93cyB3aXRoIHRyaWdnZXIud2ViaG9vayBmb3VuZFwiKTtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cdFx0dGhpcy5sb2dnZXIubG9nKGBbYmxva11bd2ViaG9va10gcmVnaXN0ZXJpbmcgJHt3b3JrZmxvd3MubGVuZ3RofSB3ZWJob29rIHJvdXRlKHMpOmApO1xuXHRcdGZvciAoY29uc3QgZW50cnkgb2Ygd29ya2Zsb3dzKSB7XG5cdFx0XHR0aGlzLnJlZ2lzdGVyV2ViaG9va1JvdXRlKGVudHJ5KTtcblx0XHR9XG5cdH1cblxuXHRwcml2YXRlIHJlZ2lzdGVyV2ViaG9va1JvdXRlKGVudHJ5OiB7IHdvcmtmbG93TmFtZTogc3RyaW5nOyBjb25maWc6IFdlYmhvb2tUcmlnZ2VyQ29uZmlnIH0pOiB2b2lkIHtcblx0XHRjb25zdCB7IHdvcmtmbG93TmFtZSwgY29uZmlnIH0gPSBlbnRyeTtcblx0XHRjb25zdCBwYXRoID0gY29uZmlnLnBhdGggPz8gKGNvbmZpZy5wcm92aWRlciA/IGAvd2ViaG9va3MvJHtjb25maWcucHJvdmlkZXJ9YCA6IGAvd2ViaG9va3MvJHt3b3JrZmxvd05hbWV9YCk7XG5cdFx0Y29uc3QgbGFiZWwgPSBjb25maWcucHJvdmlkZXIgPz8gXCJjdXN0b21cIjtcblx0XHR0aGlzLmxvZ2dlci5sb2coYFtibG9rXVt3ZWJob29rXSAgIFBPU1QgICAgJHtwYXRofSAg4oaQICAke3dvcmtmbG93TmFtZX0gICgke2xhYmVsfSlgKTtcblxuXHRcdHRoaXMuYXBwLnBvc3QocGF0aCwgKGM6IEhvbm9Db250ZXh0KSA9PiB0aGlzLmhhbmRsZVJlcXVlc3QoYywgd29ya2Zsb3dOYW1lLCBwYXRoLCBjb25maWcpKTtcblx0fVxuXG5cdHByaXZhdGUgYXN5bmMgaGFuZGxlUmVxdWVzdChcblx0XHRjOiBIb25vQ29udGV4dCxcblx0XHR3b3JrZmxvd05hbWU6IHN0cmluZyxcblx0XHRwYXRoOiBzdHJpbmcsXG5cdFx0Y29uZmlnOiBXZWJob29rVHJpZ2dlckNvbmZpZyxcblx0KTogUHJvbWlzZTxSZXNwb25zZT4ge1xuXHRcdHRoaXMuY291bnRlclJlY2VpdmVkLmFkZCgxLCB7IHdvcmtmbG93X25hbWU6IHdvcmtmbG93TmFtZSB9KTtcblxuXHRcdC8vIDEuIENhcHR1cmUgcmF3IGJvZHkgQkVGT1JFIHBhcnNpbmcg4oCUIHZlcmlmaWVycyBzaWduIHRoZSB3aXJlIGJ5dGVzLlxuXHRcdGNvbnN0IHJhd0JvZHkgPSBhd2FpdCBjLnJlcS50ZXh0KCk7XG5cdFx0bGV0IHBhcnNlZEJvZHk6IHVua25vd24gPSB7fTtcblx0XHRpZiAocmF3Qm9keS5sZW5ndGggPiAwKSB7XG5cdFx0XHR0cnkge1xuXHRcdFx0XHRwYXJzZWRCb2R5ID0gSlNPTi5wYXJzZShyYXdCb2R5KSBhcyB1bmtub3duO1xuXHRcdFx0fSBjYXRjaCB7XG5cdFx0XHRcdC8vIE5vbi1KU09OIGJvZHkg4oCUIGxlYXZlIHBhcnNlZCBhcyB0aGUgcmF3IHRleHQuIFNsYWNrXG5cdFx0XHRcdC8vIGNoYWxsZW5nZXMgJiBTaG9waWZ5IGNhbiBwb3N0IG5vbi1KU09OIG9jY2FzaW9uYWxseS5cblx0XHRcdFx0cGFyc2VkQm9keSA9IHJhd0JvZHk7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0Y29uc3QgaGVhZGVycyA9IE9iamVjdC5mcm9tRW50cmllcyhjLnJlcS5yYXcuaGVhZGVycyk7XG5cdFx0Y29uc3QgcGF0aFBhcmFtcyA9IGMucmVxLnBhcmFtKCkgYXMgUmVjb3JkPHN0cmluZywgc3RyaW5nPjtcblx0XHRjb25zdCBxdWVyeVBhcmFtcyA9IE9iamVjdC5mcm9tRW50cmllcyhuZXcgVVJMKGMucmVxLnVybCkuc2VhcmNoUGFyYW1zKTtcblxuXHRcdC8vIDIuIFBpY2sgdGhlIHZlcmlmaWVyLlxuXHRcdGNvbnN0IHZlcmlmaWVyID0gdGhpcy5yZXNvbHZlVmVyaWZpZXIod29ya2Zsb3dOYW1lLCBjb25maWcpO1xuXHRcdGlmICghdmVyaWZpZXIpIHtcblx0XHRcdHRoaXMuY291bnRlclJlamVjdGVkLmFkZCgxLCB7IHdvcmtmbG93X25hbWU6IHdvcmtmbG93TmFtZSwgcmVhc29uOiBcIm5vX3ZlcmlmaWVyXCIgfSk7XG5cdFx0XHRyZXR1cm4gYy5qc29uKHsgZXJyb3I6IFwiQ29uZmlndXJhdGlvblwiLCByZWFzb246IFwibm9fdmVyaWZpZXJcIiwgbWVzc2FnZTogXCJObyB2ZXJpZmllciBjb25maWd1cmVkXCIgfSwgNTAwKTtcblx0XHR9XG5cblx0XHQvLyAzLiBSZXNvbHZlIHRoZSBzZWNyZXQgZnJvbSB0aGUgZW52IHZhci5cblx0XHRjb25zdCBzZWNyZXRFbnYgPSBjb25maWcuc2VjcmV0RW52ID8/IGNvbmZpZy5zaWduYXR1cmU/LnNlY3JldEVudjtcblx0XHRjb25zdCBzZWNyZXQgPSBzZWNyZXRFbnYgPyAocHJvY2Vzcy5lbnZbc2VjcmV0RW52XSA/PyBcIlwiKSA6IFwiXCI7XG5cblx0XHQvLyA0LiBWZXJpZnkuXG5cdFx0Y29uc3QgdG9sZXJhbmNlU2VjID0gY29uZmlnLnRvbGVyYW5jZSA/PyBjb25maWcuc2lnbmF0dXJlPy50b2xlcmFuY2UgPz8gREVGQVVMVF9UT0xFUkFOQ0VfU0VDO1xuXHRcdGNvbnN0IHJlc3VsdDogVmVyaWZ5UmVzdWx0ID0gdmVyaWZpZXIudmVyaWZ5KHtcblx0XHRcdGhlYWRlcnMsXG5cdFx0XHRyYXdCb2R5LFxuXHRcdFx0cGFyc2VkQm9keSxcblx0XHRcdHNlY3JldCxcblx0XHRcdHRvbGVyYW5jZVNlYyxcblx0XHR9KTtcblxuXHRcdGlmICghcmVzdWx0Lm9rKSB7XG5cdFx0XHR0aGlzLmNvdW50ZXJSZWplY3RlZC5hZGQoMSwgeyB3b3JrZmxvd19uYW1lOiB3b3JrZmxvd05hbWUsIHJlYXNvbjogcmVzdWx0LnJlYXNvbiB9KTtcblx0XHRcdHRoaXMubG9nZ2VyLmVycm9yKFxuXHRcdFx0XHRgW2Jsb2tdW3dlYmhvb2tdICR7d29ya2Zsb3dOYW1lfTogdmVyaWZ5IGZhaWxlZCByZWFzb249JHtyZXN1bHQucmVhc29ufSBtZXNzYWdlPVwiJHtyZXN1bHQubWVzc2FnZX1cImAsXG5cdFx0XHQpO1xuXHRcdFx0cmV0dXJuIGMuanNvbih7IGVycm9yOiBcIlVuYXV0aG9yaXplZFwiLCByZWFzb246IHJlc3VsdC5yZWFzb24sIG1lc3NhZ2U6IHJlc3VsdC5tZXNzYWdlIH0sIDQwMSk7XG5cdFx0fVxuXG5cdFx0Ly8gNS4gRXZlbnRzIGFsbG93bGlzdCDigJQgdmVyaWZpZWQtYnV0LW91dC1vZi1zY29wZSByZXR1cm5zIDIwMCAobm8gcmV0cnkpLlxuXHRcdGlmIChBcnJheS5pc0FycmF5KGNvbmZpZy5ldmVudHMpICYmIGNvbmZpZy5ldmVudHMubGVuZ3RoID4gMCAmJiAhY29uZmlnLmV2ZW50cy5pbmNsdWRlcyhyZXN1bHQuZXZlbnRUeXBlKSkge1xuXHRcdFx0dGhpcy5jb3VudGVyUmVqZWN0ZWQuYWRkKDEsIHsgd29ya2Zsb3dfbmFtZTogd29ya2Zsb3dOYW1lLCByZWFzb246IFwiZXZlbnRfbm90X2FsbG93ZWRcIiB9KTtcblx0XHRcdHJldHVybiBjLmpzb24oeyBzdGF0dXM6IFwiaWdub3JlZFwiLCByZWFzb246IFwiZXZlbnRfbm90X2FsbG93ZWRcIiwgZXZlbnRUeXBlOiByZXN1bHQuZXZlbnRUeXBlIH0sIDIwMCk7XG5cdFx0fVxuXG5cdFx0Ly8gNi4gUmVwbGF5IHByb3RlY3Rpb24gdmlhIHRoZSBpZGVtcG90ZW5jeSBjYWNoZS5cblx0XHRpZiAoY29uZmlnLmlkZW1wb3RlbmN5S2V5ICYmIHJlc3VsdC5ldmVudElkKSB7XG5cdFx0XHRjb25zdCB0cmFja2VyID0gUnVuVHJhY2tlci5nZXRJbnN0YW5jZSgpO1xuXHRcdFx0Y29uc3Qgc3RvcmUgPSB0cmFja2VyLmdldFN0b3JlKCk7XG5cdFx0XHRjb25zdCBjYWNoZWQgPSBzdG9yZS5nZXRJZGVtcG90ZW5jeUNhY2hlKFJFUExBWV9OQU1FU1BBQ0UsIHdvcmtmbG93TmFtZSwgcmVzdWx0LmV2ZW50SWQpO1xuXHRcdFx0aWYgKGNhY2hlZCkge1xuXHRcdFx0XHR0aGlzLmNvdW50ZXJSZWplY3RlZC5hZGQoMSwgeyB3b3JrZmxvd19uYW1lOiB3b3JrZmxvd05hbWUsIHJlYXNvbjogXCJyZXBsYXlcIiB9KTtcblx0XHRcdFx0cmV0dXJuIGMuanNvbihcblx0XHRcdFx0XHR7XG5cdFx0XHRcdFx0XHRzdGF0dXM6IFwiZHVwbGljYXRlXCIsXG5cdFx0XHRcdFx0XHRldmVudElkOiByZXN1bHQuZXZlbnRJZCxcblx0XHRcdFx0XHRcdGV2ZW50VHlwZTogcmVzdWx0LmV2ZW50VHlwZSxcblx0XHRcdFx0XHRcdGZpcnN0U2VlblJ1bklkOiBjYWNoZWQuc291cmNlUnVuSWQsXG5cdFx0XHRcdFx0fSxcblx0XHRcdFx0XHQyMDAsXG5cdFx0XHRcdCk7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0Ly8gNy4gVmVyaWZpZWQgKyBuZXcgZXZlbnQg4oCUIGRpc3BhdGNoIHRoZSB3b3JrZmxvdy5cblx0XHR0aGlzLmNvdW50ZXJBY2NlcHRlZC5hZGQoMSwgeyB3b3JrZmxvd19uYW1lOiB3b3JrZmxvd05hbWUgfSk7XG5cdFx0Y29uc3QgcmVxdWVzdElkID0gdXVpZCgpO1xuXHRcdGNvbnN0IGRpc3BhdGNoT3V0Y29tZSA9IGF3YWl0IHRoaXMuZGlzcGF0Y2hXb3JrZmxvdyh7XG5cdFx0XHR3b3JrZmxvd05hbWUsXG5cdFx0XHRwYXRoLFxuXHRcdFx0Y29uZmlnLFxuXHRcdFx0cmVxdWVzdElkLFxuXHRcdFx0aGVhZGVycyxcblx0XHRcdGJvZHk6IHBhcnNlZEJvZHksXG5cdFx0XHRyYXdCb2R5LFxuXHRcdFx0cGF0aFBhcmFtcyxcblx0XHRcdHF1ZXJ5UGFyYW1zLFxuXHRcdFx0ZXZlbnRJZDogcmVzdWx0LmV2ZW50SWQsXG5cdFx0XHRldmVudFR5cGU6IHJlc3VsdC5ldmVudFR5cGUsXG5cdFx0fSk7XG5cblx0XHQvLyA4LiBDYWNoZSBldmVudCBpZCBBRlRFUiBzdWNjZXNzZnVsIGRpc3BhdGNoIHNvIHJldHJpZXMgb24gdGhlXG5cdFx0Ly8gICAgc2FtZSBkZWxpdmVyeSBhcmUgZGVkdXBlZC4gV2UgY2FjaGUgZXZlbiBvbiB3b3JrZmxvdyBmYWlsdXJlXG5cdFx0Ly8gICAg4oCUIHdlYmhvb2sgc2VuZGVycyBzaG91bGQgbm90IHJldHJ5IGRlbGl2ZXJpZXMgdGhleSd2ZVxuXHRcdC8vICAgIGFscmVhZHkgZGVsaXZlcmVkICh0aGUgd29ya2Zsb3cncyBvd24gcmV0cnkgLyBETFEgb3ducyB0aGF0KS5cblx0XHRpZiAoY29uZmlnLmlkZW1wb3RlbmN5S2V5ICYmIHJlc3VsdC5ldmVudElkKSB7XG5cdFx0XHRjb25zdCB0cmFja2VyID0gUnVuVHJhY2tlci5nZXRJbnN0YW5jZSgpO1xuXHRcdFx0Y29uc3Qgc3RvcmUgPSB0cmFja2VyLmdldFN0b3JlKCk7XG5cdFx0XHRzdG9yZS5zZXRJZGVtcG90ZW5jeUNhY2hlKFJFUExBWV9OQU1FU1BBQ0UsIHdvcmtmbG93TmFtZSwgcmVzdWx0LmV2ZW50SWQsIHtcblx0XHRcdFx0ZGF0YTogeyBldmVudElkOiByZXN1bHQuZXZlbnRJZCwgZXZlbnRUeXBlOiByZXN1bHQuZXZlbnRUeXBlIH0sXG5cdFx0XHRcdGNhY2hlZEF0OiBEYXRlLm5vdygpLFxuXHRcdFx0XHRleHBpcmVzQXQ6IERhdGUubm93KCkgKyBERUZBVUxUX1JFUExBWV9UVExfTVMsXG5cdFx0XHRcdHNvdXJjZVJ1bklkOiByZXF1ZXN0SWQsXG5cdFx0XHRcdHNvdXJjZU5vZGVSdW5JZDogcmVxdWVzdElkLFxuXHRcdFx0fSk7XG5cdFx0fVxuXG5cdFx0Ly8gOS4gU2hhcGUgdGhlIHJlc3BvbnNlLiBXb3JrZmxvdydzIGBjdHgucmVzcG9uc2VgIGxhbmRzIGluIHRoZVxuXHRcdC8vICAgIGJvZHkgZm9yIHBhcml0eSB3aXRoIEhUVFAgdHJpZ2dlcnMuXG5cdFx0cmV0dXJuIGMuanNvbihcblx0XHRcdHtcblx0XHRcdFx0c3RhdHVzOiBcIm9rXCIsXG5cdFx0XHRcdGV2ZW50SWQ6IHJlc3VsdC5ldmVudElkLFxuXHRcdFx0XHRldmVudFR5cGU6IHJlc3VsdC5ldmVudFR5cGUsXG5cdFx0XHRcdHJ1bklkOiByZXF1ZXN0SWQsXG5cdFx0XHRcdHJlc3BvbnNlOiBkaXNwYXRjaE91dGNvbWUsXG5cdFx0XHR9LFxuXHRcdFx0MjAwLFxuXHRcdCk7XG5cdH1cblxuXHRwcml2YXRlIHJlc29sdmVWZXJpZmllcih3b3JrZmxvd05hbWU6IHN0cmluZywgY29uZmlnOiBXZWJob29rVHJpZ2dlckNvbmZpZyk6IFZlcmlmaWVyIHwgbnVsbCB7XG5cdFx0aWYgKGNvbmZpZy5wcm92aWRlcikge1xuXHRcdFx0Y29uc3QgdiA9IEJVSUxUSU5fVkVSSUZJRVJTW2NvbmZpZy5wcm92aWRlcl07XG5cdFx0XHRpZiAoIXYpIHtcblx0XHRcdFx0dGhpcy5sb2dnZXIuZXJyb3IoYFtibG9rXVt3ZWJob29rXSAke3dvcmtmbG93TmFtZX06IHVua25vd24gcHJvdmlkZXIgXCIke2NvbmZpZy5wcm92aWRlcn1cImApO1xuXHRcdFx0XHRyZXR1cm4gbnVsbDtcblx0XHRcdH1cblx0XHRcdHJldHVybiB2O1xuXHRcdH1cblx0XHRpZiAoY29uZmlnLnNpZ25hdHVyZSkge1xuXHRcdFx0cmV0dXJuIGJ1aWxkQ3VzdG9tVmVyaWZpZXIoe1xuXHRcdFx0XHRzY2hlbWU6IGNvbmZpZy5zaWduYXR1cmUuc2NoZW1lID8/IFwiaG1hYy1zaGEyNTZcIixcblx0XHRcdFx0aGVhZGVyOiBjb25maWcuc2lnbmF0dXJlLmhlYWRlcixcblx0XHRcdFx0Zm9ybWF0OiBjb25maWcuc2lnbmF0dXJlLmZvcm1hdCA/PyBcIntoZXh9XCIsXG5cdFx0XHRcdHNlY3JldEVudjogY29uZmlnLnNpZ25hdHVyZS5zZWNyZXRFbnYsXG5cdFx0XHRcdHRvbGVyYW5jZTogY29uZmlnLnNpZ25hdHVyZS50b2xlcmFuY2UgPz8gREVGQVVMVF9UT0xFUkFOQ0VfU0VDLFxuXHRcdFx0XHR0aW1lc3RhbXBIZWFkZXI6IGNvbmZpZy5zaWduYXR1cmUudGltZXN0YW1wSGVhZGVyLFxuXHRcdFx0fSk7XG5cdFx0fVxuXHRcdHJldHVybiBudWxsO1xuXHR9XG5cblx0Ly8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cdC8vIFdvcmtmbG93IGRpc3BhdGNoXG5cdC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG5cdHByaXZhdGUgYXN5bmMgZGlzcGF0Y2hXb3JrZmxvdyhvcHRzOiB7XG5cdFx0d29ya2Zsb3dOYW1lOiBzdHJpbmc7XG5cdFx0cGF0aDogc3RyaW5nO1xuXHRcdGNvbmZpZzogV2ViaG9va1RyaWdnZXJDb25maWc7XG5cdFx0cmVxdWVzdElkOiBzdHJpbmc7XG5cdFx0aGVhZGVyczogUmVjb3JkPHN0cmluZywgc3RyaW5nPjtcblx0XHRib2R5OiB1bmtub3duO1xuXHRcdHJhd0JvZHk6IHN0cmluZztcblx0XHRwYXRoUGFyYW1zOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+O1xuXHRcdHF1ZXJ5UGFyYW1zOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+O1xuXHRcdGV2ZW50SWQ6IHN0cmluZztcblx0XHRldmVudFR5cGU6IHN0cmluZztcblx0fSk6IFByb21pc2U8dW5rbm93bj4ge1xuXHRcdGNvbnN0IHsgd29ya2Zsb3dOYW1lLCByZXF1ZXN0SWQsIGhlYWRlcnMsIGJvZHksIHJhd0JvZHksIHBhdGhQYXJhbXMsIHF1ZXJ5UGFyYW1zLCBldmVudElkLCBldmVudFR5cGUgfSA9IG9wdHM7XG5cblx0XHRyZXR1cm4gdGhpcy50cmFjZXIuc3RhcnRBY3RpdmVTcGFuKGB3ZWJob29rOiR7d29ya2Zsb3dOYW1lfWAsIGFzeW5jIChzcGFuOiBTcGFuKSA9PiB7XG5cdFx0XHR0cnkge1xuXHRcdFx0XHRjb25zdCByZWdpc3RyeSA9IFdvcmtmbG93UmVnaXN0cnkuZ2V0SW5zdGFuY2UoKTtcblx0XHRcdFx0Y29uc3QgZW50cnkgPSByZWdpc3RyeS5nZXQod29ya2Zsb3dOYW1lKTtcblx0XHRcdFx0aWYgKCFlbnRyeSkge1xuXHRcdFx0XHRcdHRocm93IG5ldyBFcnJvcihgW2Jsb2tdW3dlYmhvb2tdIHdvcmtmbG93IFwiJHt3b3JrZmxvd05hbWV9XCIgbm90IGZvdW5kIGluIHJlZ2lzdHJ5YCk7XG5cdFx0XHRcdH1cblx0XHRcdFx0YXdhaXQgdGhpcy5jb25maWd1cmF0aW9uLmluaXQod29ya2Zsb3dOYW1lLCB0aGlzLm5vZGVNYXAsIGVudHJ5LndvcmtmbG93KTtcblxuXHRcdFx0XHRjb25zdCBjdHg6IENvbnRleHQgPSB0aGlzLmNyZWF0ZUNvbnRleHQodW5kZWZpbmVkLCB3b3JrZmxvd05hbWUsIHJlcXVlc3RJZCk7XG5cdFx0XHRcdGN0eC5yZXF1ZXN0ID0ge1xuXHRcdFx0XHRcdGJvZHksXG5cdFx0XHRcdFx0cmF3Qm9keSxcblx0XHRcdFx0XHRoZWFkZXJzLFxuXHRcdFx0XHRcdHBhcmFtczogcGF0aFBhcmFtcyxcblx0XHRcdFx0XHRxdWVyeTogcXVlcnlQYXJhbXMsXG5cdFx0XHRcdH0gYXMgdW5rbm93biBhcyBSZXF1ZXN0Q29udGV4dDtcblxuXHRcdFx0XHQvLyBTdGFtcCB3ZWJob29rIG1ldGFkYXRhIG9udG8gY3R4IHNvIHBvbHltb3JwaGljIGRpc3BhdGNoXG5cdFx0XHRcdC8vIGNhbiByZWFkIG5hbWVzcGFjZSArIGV2ZW50IG1ldGFkYXRhIHVuaWZvcm1seS5cblx0XHRcdFx0KGN0eCBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPikuX3dlYmhvb2sgPSB7XG5cdFx0XHRcdFx0ZXZlbnRJZCxcblx0XHRcdFx0XHRldmVudFR5cGUsXG5cdFx0XHRcdFx0bmFtZXNwYWNlOiBvcHRzLmNvbmZpZy5uYW1lc3BhY2UsXG5cdFx0XHRcdH07XG5cblx0XHRcdFx0YXdhaXQgdGhpcy5hcHBseU1pZGRsZXdhcmVDaGFpbihjdHgsIHRoaXMubm9kZU1hcCk7XG5cdFx0XHRcdGF3YWl0IHRoaXMucnVuKGN0eCk7XG5cblx0XHRcdFx0c3Bhbi5zZXRBdHRyaWJ1dGUoXCJ3b3JrZmxvd19uYW1lXCIsIHdvcmtmbG93TmFtZSk7XG5cdFx0XHRcdHNwYW4uc2V0QXR0cmlidXRlKFwiZXZlbnRfaWRcIiwgZXZlbnRJZCk7XG5cdFx0XHRcdHNwYW4uc2V0QXR0cmlidXRlKFwiZXZlbnRfdHlwZVwiLCBldmVudFR5cGUpO1xuXHRcdFx0XHRzcGFuLnNldFN0YXR1cyh7IGNvZGU6IFNwYW5TdGF0dXNDb2RlLk9LIH0pO1xuXHRcdFx0XHRyZXR1cm4gY3R4LnJlc3BvbnNlO1xuXHRcdFx0fSBjYXRjaCAoZXJyKSB7XG5cdFx0XHRcdGNvbnN0IG1zZyA9IGVyciBpbnN0YW5jZW9mIEVycm9yID8gZXJyLm1lc3NhZ2UgOiBTdHJpbmcoZXJyKTtcblx0XHRcdFx0c3Bhbi5yZWNvcmRFeGNlcHRpb24oZXJyIGFzIEVycm9yKTtcblx0XHRcdFx0c3Bhbi5zZXRTdGF0dXMoeyBjb2RlOiBTcGFuU3RhdHVzQ29kZS5FUlJPUiwgbWVzc2FnZTogbXNnIH0pO1xuXHRcdFx0XHR0aGlzLmxvZ2dlci5lcnJvcihgW2Jsb2tdW3dlYmhvb2tdIHdvcmtmbG93ICR7d29ya2Zsb3dOYW1lfSBmYWlsZWQ6ICR7bXNnfWApO1xuXHRcdFx0XHRyZXR1cm4geyBlcnJvcjogbXNnIH07XG5cdFx0XHR9IGZpbmFsbHkge1xuXHRcdFx0XHRzcGFuLmVuZCgpO1xuXHRcdFx0fVxuXHRcdH0pO1xuXHR9XG5cblx0Ly8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cdC8vIEludHJvc3BlY3Rpb25cblx0Ly8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cblx0Z2V0U3RhdHMoKTogeyB3b3JrZmxvd3NSZWdpc3RlcmVkOiBudW1iZXIgfSB7XG5cdFx0cmV0dXJuIHsgd29ya2Zsb3dzUmVnaXN0ZXJlZDogdGhpcy5nZXRXZWJob29rV29ya2Zsb3dzKCkubGVuZ3RoIH07XG5cdH1cblxuXHRwcml2YXRlIGdldFdlYmhvb2tXb3JrZmxvd3MoKTogQXJyYXk8eyB3b3JrZmxvd05hbWU6IHN0cmluZzsgY29uZmlnOiBXZWJob29rVHJpZ2dlckNvbmZpZyB9PiB7XG5cdFx0Y29uc3QgcmVnaXN0cnkgPSBXb3JrZmxvd1JlZ2lzdHJ5LmdldEluc3RhbmNlKCk7XG5cdFx0Y29uc3Qgb3V0OiBBcnJheTx7IHdvcmtmbG93TmFtZTogc3RyaW5nOyBjb25maWc6IFdlYmhvb2tUcmlnZ2VyQ29uZmlnIH0+ID0gW107XG5cdFx0Zm9yIChjb25zdCBlbnRyeSBvZiByZWdpc3RyeS5saXN0KCkpIHtcblx0XHRcdGNvbnN0IHdmID0gZW50cnkud29ya2Zsb3cgYXMgeyB0cmlnZ2VyPzogeyB3ZWJob29rPzogV2ViaG9va1RyaWdnZXJDb25maWcgfSB9IHwgdW5kZWZpbmVkO1xuXHRcdFx0Y29uc3QgY2ZnID0gd2Y/LnRyaWdnZXI/LndlYmhvb2s7XG5cdFx0XHRpZiAoIWNmZykgY29udGludWU7XG5cdFx0XHQvLyBTa2lwIGNvbmZpZ3MgbWlzc2luZyBib3RoIHByb3ZpZGVyIEFORCBzaWduYXR1cmUg4oCUIHRoZXkgY2FuJ3Rcblx0XHRcdC8vIHZlcmlmeSBhbnl0aGluZy4gQXV0aG9ycyBnZXQgYSBzdHJ1Y3R1cmVkIGVycm9yIGF0IGJvb3QuXG5cdFx0XHRpZiAoIWNmZy5wcm92aWRlciAmJiAhY2ZnLnNpZ25hdHVyZSkge1xuXHRcdFx0XHR0aGlzLmxvZ2dlci5lcnJvcihcblx0XHRcdFx0XHRgW2Jsb2tdW3dlYmhvb2tdIHdvcmtmbG93IFwiJHtlbnRyeS5uYW1lfVwiIGhhcyB0cmlnZ2VyLndlYmhvb2sgd2l0aCBuZWl0aGVyIFxcYHByb3ZpZGVyXFxgIG5vciBcXGBzaWduYXR1cmVcXGAg4oCUIHNraXBwaW5nLiBBZGQgb25lIHRvIGVuYWJsZSBzaWduYXR1cmUgdmVyaWZpY2F0aW9uLmAsXG5cdFx0XHRcdCk7XG5cdFx0XHRcdGNvbnRpbnVlO1xuXHRcdFx0fVxuXHRcdFx0b3V0LnB1c2goeyB3b3JrZmxvd05hbWU6IGVudHJ5Lm5hbWUsIGNvbmZpZzogY2ZnIH0pO1xuXHRcdH1cblx0XHRyZXR1cm4gb3V0O1xuXHR9XG59XG5cbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4vLyBTaW5nbGV0b24gYWNjZXNzb3IgKG1pcnJvcnMgV1MgLyBTU0UpXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG5sZXQgYWN0aXZlVHJpZ2dlcjogV2ViaG9va1RyaWdnZXIgfCBudWxsID0gbnVsbDtcblxuZXhwb3J0IGZ1bmN0aW9uIF9zZXRBY3RpdmVXZWJob29rVHJpZ2dlcih0cmlnZ2VyOiBXZWJob29rVHJpZ2dlciB8IG51bGwpOiB2b2lkIHtcblx0YWN0aXZlVHJpZ2dlciA9IHRyaWdnZXI7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBfZ2V0QWN0aXZlV2ViaG9va1RyaWdnZXIoKTogV2ViaG9va1RyaWdnZXIgfCBudWxsIHtcblx0cmV0dXJuIGFjdGl2ZVRyaWdnZXI7XG59XG5cbmV4cG9ydCB0eXBlIHsgV2ViaG9va1RyaWdnZXJDb25maWcgfTtcbiJdfQ==