@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.
- package/dist/WebhookTrigger.d.ts +100 -117
- package/dist/WebhookTrigger.js +315 -316
- package/dist/index.d.ts +36 -65
- package/dist/index.js +34 -71
- package/dist/verifiers.d.ts +80 -0
- package/dist/verifiers.js +294 -0
- package/package.json +6 -4
- package/src/WebhookTrigger.integration.test.ts +162 -0
- package/src/WebhookTrigger.test.ts +232 -143
- package/src/WebhookTrigger.ts +386 -407
- package/src/index.ts +41 -70
- package/src/verifiers.test.ts +316 -0
- package/src/verifiers.ts +357 -0
package/dist/WebhookTrigger.js
CHANGED
|
@@ -1,355 +1,354 @@
|
|
|
1
|
-
"use strict";
|
|
2
1
|
/**
|
|
3
|
-
* WebhookTrigger
|
|
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
|
-
*
|
|
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
|
-
*
|
|
12
|
-
*
|
|
13
|
-
* -
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
*
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
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
|
-
|
|
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
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
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.
|
|
116
|
-
this.
|
|
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
|
-
*
|
|
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
|
-
|
|
132
|
-
this.nodeMap
|
|
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
|
-
|
|
140
|
-
|
|
141
|
-
|
|
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
|
-
|
|
145
|
-
|
|
109
|
+
this.wired = true;
|
|
110
|
+
if (this.httpTrigger) {
|
|
111
|
+
this.httpTrigger.addPreCatchAllHook(() => {
|
|
112
|
+
this.registerRoutesFromRegistry();
|
|
113
|
+
});
|
|
146
114
|
}
|
|
147
|
-
|
|
148
|
-
|
|
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.
|
|
158
|
-
|
|
121
|
+
this.wired = false;
|
|
122
|
+
if (_getActiveWebhookTrigger() === this)
|
|
123
|
+
_setActiveWebhookTrigger(null);
|
|
124
|
+
this.destroyMonitoring();
|
|
125
|
+
this.logger.log("[blok][webhook] stopped");
|
|
159
126
|
}
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
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
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
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
|
-
|
|
177
|
-
|
|
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
|
-
//
|
|
180
|
-
const
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
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
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
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
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
const
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
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
|
-
|
|
206
|
-
|
|
207
|
-
|
|
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
|
-
|
|
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
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
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
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
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
|
-
|
|
262
|
-
|
|
263
|
-
async
|
|
264
|
-
const
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
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
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
}
|
|
340
|
-
|
|
341
|
-
|
|
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
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiV2ViaG9va1RyaWdnZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvV2ViaG9va1RyaWdnZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQXNERztBQUVILE9BQU8sRUFDTixhQUFhLEVBQ2IsVUFBVSxFQUVWLFdBQVcsRUFDWCxnQkFBZ0IsR0FDaEIsTUFBTSxnQkFBZ0IsQ0FBQztBQUV4QixPQUFPLEVBQWEsY0FBYyxFQUFFLE9BQU8sRUFBRSxLQUFLLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUUvRSxPQUFPLEVBQUUsRUFBRSxJQUFJLElBQUksRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUVsQyxPQUFPLEVBQUUsaUJBQWlCLEVBQW9DLG1CQUFtQixFQUFFLE1BQU0sYUFBYSxDQUFDO0FBNkJ2RyxNQUFNLHFCQUFxQixHQUFHLEdBQUcsQ0FBQztBQUNsQyxNQUFNLHFCQUFxQixHQUFHLENBQUMsR0FBRyxFQUFFLEdBQUcsSUFBSSxDQUFDLENBQUMsdUNBQXVDO0FBQ3BGLE1BQU0sZ0JBQWdCLEdBQUcsYUFBYSxDQUFDO0FBRXZDLGdGQUFnRjtBQUNoRixnQkFBZ0I7QUFDaEIsZ0ZBQWdGO0FBRWhGLE1BQU0sQ0FBQyxPQUFPLE9BQU8sY0FBZSxTQUFRLFdBQVc7SUFDNUMsT0FBTyxHQUF3QixFQUF5QixDQUFDO0lBQ2hELE1BQU0sR0FBRyxJQUFJLGFBQWEsRUFBRSxDQUFDO0lBQzdCLE1BQU0sR0FBRyxLQUFLLENBQUMsU0FBUyxDQUMxQyxPQUFPLENBQUMsR0FBRyxDQUFDLFlBQVksSUFBSSwwQkFBMEIsRUFDdEQsT0FBTyxDQUFDLEdBQUcsQ0FBQyxlQUFlLElBQUksT0FBTyxDQUN0QyxDQUFDO0lBRWUsS0FBSyxHQUFHLE9BQU8sQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDakMsZUFBZSxHQUFHLElBQUks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RSxDQUFDO1lBQzFGLE1BQU0sR0FBRyxHQUFHLEVBQUUsRUFBRSxPQUFPLEVBQUUsT0FBTyxDQUFDO1lBQ2pDLElBQUksQ0FBQyxHQUFHO2dCQUFFLFNBQVM7WUFDbkIsZ0VBQWdFO1lBQ2hFLDJEQUEyRDtZQUMzRCxJQUFJLENBQUMsR0FBRyxDQUFDLFFBQVEsSUFBSSxDQUFDLEdBQUcsQ0FBQyxTQUFTLEVBQUUsQ0FBQztnQkFDckMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQ2hCLDZCQUE2QixLQUFLLENBQUMsSUFBSSx5SEFBeUgsQ0FDaEssQ0FBQztnQkFDRixTQUFTO1lBQ1YsQ0FBQztZQUNELEdBQUcsQ0FBQyxJQUFJLENBQUMsRUFBRSxZQUFZLEVBQUUsS0FBSyxDQUFDLElBQUksRUFBRSxNQUFNLEVBQUUsR0FBRyxFQUFFLENBQUMsQ0FBQztRQUNyRCxDQUFDO1FBQ0QsT0FBTyxHQUFHLENBQUM7SUFDWixDQUFDO0NBQ0Q7QUFFRCxnRkFBZ0Y7QUFDaEYsd0NBQXdDO0FBQ3hDLGdGQUFnRjtBQUVoRixJQUFJLGFBQWEsR0FBMEIsSUFBSSxDQUFDO0FBRWhELE1BQU0sVUFBVSx3QkFBd0IsQ0FBQyxPQUE4QjtJQUN0RSxhQUFhLEdBQUcsT0FBTyxDQUFDO0FBQ3pCLENBQUM7QUFFRCxNQUFNLFVBQVUsd0JBQXdCO0lBQ3ZDLE9BQU8sYUFBYSxDQUFDO0FBQ3RCLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIFdlYmhvb2tUcmlnZ2VyIOKAlCB2MC43IFBSIDQg4oCUIEluYm91bmQgd2ViaG9vayB0cmlnZ2VyIHRoYXQgbW91bnRzXG4gKiB2ZXJpZmllZCBQT1NUIHJvdXRlcyBvbiB0aGUgc2hhcmVkIEhvbm8gYXBwLiBPbmUgcm91dGUgcGVyIHdvcmtmbG93XG4gKiB3aG9zZSBgdHJpZ2dlci53ZWJob29rYCBjb25maWcgaXMgcmVnaXN0ZXJlZC5cbiAqXG4gKiAqKkF1dGhvcmluZyBzdXJmYWNlIChidWlsdC1pbiBwcm92aWRlcik6KipcbiAqXG4gKiBgYGBqc29uXG4gKiB7XG4gKiAgIFwibmFtZVwiOiBcInN0cmlwZS1ldmVudHNcIixcbiAqICAgXCJ0cmlnZ2VyXCI6IHtcbiAqICAgICBcIndlYmhvb2tcIjoge1xuICogICAgICAgXCJwcm92aWRlclwiOiBcInN0cmlwZVwiLFxuICogICAgICAgXCJwYXRoXCI6IFwiL3dlYmhvb2tzL3N0cmlwZVwiLFxuICogICAgICAgXCJzZWNyZXRFbnZcIjogXCJTVFJJUEVfV0VCSE9PS19TRUNSRVRcIixcbiAqICAgICAgIFwibmFtZXNwYWNlXCI6IFwic3RyaXBlXCIsXG4gKiAgICAgICBcImlkZW1wb3RlbmN5S2V5XCI6IFwianMvY3R4LnJlcXVlc3QuYm9keS5pZFwiXG4gKiAgICAgfVxuICogICB9LFxuICogICBcInN0ZXBzXCI6IFtcbiAqICAgICB7IFwiaWRcIjogXCJkaXNwYXRjaFwiLCBcInN1YndvcmtmbG93XCI6IFwianMvY3R4LnJlcXVlc3QuYm9keS50eXBlXCIsIFwiaW5wdXRzXCI6IHsgXCJzdHJpcGVFdmVudFwiOiBcImpzL2N0eC5yZXF1ZXN0LmJvZHlcIiB9IH1cbiAqICAgXVxuICogfVxuICogYGBgXG4gKlxuICogKipQaXBlbGluZSAocGVyIGluYm91bmQgcmVxdWVzdCk6KipcbiAqXG4gKiAgIDEuIFJlYWQgcmF3IGJvZHkg4oCUIHZlcmlmaWVycyBNVVNUIHNpZ24gdGhlIGJ5dGVzIHRoYXQgY3Jvc3NlZFxuICogICAgICB0aGUgd2lyZSwgbm90IHRoZSBKU09OLXJlLXN0cmluZ2lmaWVkIGJvZHkgKFN0cmlwZSAvIEdpdEh1YiAvXG4gKiAgICAgIFNsYWNrIGFsbCBzaWduIHJhdyBieXRlcykuXG4gKiAgIDIuIFZlcmlmeSB0aGUgc2lnbmF0dXJlIHZpYSB0aGUgcGVyLXByb3ZpZGVyIHN0cmF0ZWd5XG4gKiAgICAgIChgdmVyaWZpZXJzLnRzYCkuIE9uIGZhaWx1cmUsIHJldHVybiA0MDEgd2l0aCBzdHJ1Y3R1cmVkXG4gKiAgICAgIGB7IGVycm9yLCByZWFzb24sIG1lc3NhZ2UgfWAuXG4gKiAgIDMuIFJlcGxheSBjaGVjazogaWYgYGlkZW1wb3RlbmN5S2V5YCBpcyBjb25maWd1cmVkLCBsb29rIHVwXG4gKiAgICAgIGAod29ya2Zsb3dOYW1lLCBldmVudElkKWAgaW4gdGhlIGlkZW1wb3RlbmN5IGNhY2hlIChzYW1lIHN0b3JlXG4gKiAgICAgIGFzIFRpZXIgMSBzdGVwIGNhY2hpbmcpLiBPbiBoaXQsIHJldHVybiAyMDAgd2l0aFxuICogICAgICBgeyBzdGF0dXM6IFwiZHVwbGljYXRlXCIsIGV2ZW50SWQgfWAgYW5kIERPTidUIHJ1biB0aGUgd29ya2Zsb3cuXG4gKiAgIDQuIEV2ZW50cyBhbGxvd2xpc3Q6IGlmIGBldmVudHM6IFsuLi5dYCBpcyBjb25maWd1cmVkLCBza2lwXG4gKiAgICAgIHdvcmtmbG93IHJ1bnMgd2hvc2UgZXZlbnQgdHlwZSBpc24ndCBpbiB0aGUgbGlzdCDigJQgcmV0dXJuXG4gKiAgICAgIDIwMCB3aXRoIGB7IHN0YXR1czogXCJpZ25vcmVkXCIsIGV2ZW50VHlwZSB9YCBzbyB0aGUgc2VuZGVyXG4gKiAgICAgIGRvZXNuJ3QgcmV0cnkuXG4gKiAgIDUuIFJ1biB0aGUgd29ya2Zsb3cgdGhyb3VnaCBgVHJpZ2dlckJhc2UucnVuYCBzbyBtaWRkbGV3YXJlLFxuICogICAgICB0cmFjaW5nLCByZXRyaWVzLCBjb25jdXJyZW5jeSwgZXRjLiBhcHBseSB1bmlmb3JtbHkuXG4gKiAgIDYuIENhY2hlIHRoZSBldmVudElkIHNvIGEgcmV0cnkgd2l0aGluIHRoZSBUVEwgd2luZG93IHJldHVybnNcbiAqICAgICAgdGhlIGR1cGxpY2F0ZSByZXNwb25zZS5cbiAqXG4gKiAqKkhvbm8gaW50ZWdyYXRpb246KiogaWRlbnRpY2FsIHRvIFdlYlNvY2tldCBhbmQgU1NFIOKAlCBhY2NlcHRzIHRoZVxuICogc2hhcmVkIGBIb25vPGFueSwgYW55LCBhbnk+YCBhcHAgYW5kIGFuIG9wdGlvbmFsIGBIdHRwVHJpZ2dlckxpa2VgXG4gKiBleHBvc2luZyBgYWRkUHJlQ2F0Y2hBbGxIb29rYCBzbyB3ZWJob29rIHJvdXRlcyBtb3VudCBCRUZPUkUgdGhlXG4gKiBsZWdhY3kgYC86d29ya2Zsb3d7Lit9YCBjYXRjaC1hbGwgYW5kIHdpbiBIb25vJ3MgZmlyc3QtbWF0Y2hcbiAqIGRpc3BhdGNoLlxuICpcbiAqIFNlZSBbYWRkaXRpb25hbC10cmlnZ2Vycy1wbGFuLm1keF0oLi4vLi4vLi4vZG9jcy9jL2RldnRvb2xzL2FkZGl0aW9uYWwtdHJpZ2dlcnMtcGxhbi5tZHgjd2ViaG9vay10cmlnZ2VyKVxuICogZm9yIHRoZSBmdWxsIHYwLjcgZGVzaWduLlxuICovXG5cbmltcG9ydCB7XG5cdERlZmF1bHRMb2dnZXIsXG5cdFJ1blRyYWNrZXIsXG5cdHR5cGUgR2xvYmFsT3B0aW9ucyBhcyBSdW5uZXJHbG9iYWxPcHRpb25zLFxuXHRUcmlnZ2VyQmFzZSxcblx0V29ya2Zsb3dSZWdpc3RyeSxcbn0gZnJvbSBcIkBibG9ranMvcnVubmVyXCI7XG5pbXBvcnQgdHlwZSB7IENvbnRleHQsIFJlcXVlc3RDb250ZXh0IH0gZnJvbSBcIkBibG9ranMvc2hhcmVkXCI7XG5pbXBvcnQgeyB0eXBlIFNwYW4sIFNwYW5TdGF0dXNDb2RlLCBtZXRyaWNzLCB0cmFjZSB9IGZyb20gXCJAb3BlbnRlbGVtZXRyeS9hcGlcIjtcbmltcG9ydCB0eXBlIHsgSG9ubywgQ29udGV4dCBhcyBIb25vQ29udGV4dCB9IGZyb20gXCJob25vXCI7XG5pbXBvcnQgeyB2NCBhcyB1dWlkIH0gZnJvbSBcInV1aWRcIjtcblxuaW1wb3J0IHsgQlVJTFRJTl9WRVJJRklFUlMsIHR5cGUgVmVyaWZpZXIsIHR5cGUgVmVyaWZ5UmVzdWx0LCBidWlsZEN1c3RvbVZlcmlmaWVyIH0gZnJvbSBcIi4vdmVyaWZpZXJzXCI7XG5cbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4vLyBUeXBlc1xuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuaW50ZXJmYWNlIFdlYmhvb2tUcmlnZ2VyQ29uZmlnIHtcblx0cHJvdmlkZXI/OiBcImdpdGh1YlwiIHwgXCJzdHJpcGVcIiB8IFwic2xhY2tcIiB8IFwic2hvcGlmeVwiIHwgXCJzdml4XCI7XG5cdHBhdGg/OiBzdHJpbmc7XG5cdGV2ZW50cz86IHN0cmluZ1tdO1xuXHRzZWNyZXRFbnY/OiBzdHJpbmc7XG5cdHNpZ25hdHVyZT86IHtcblx0XHRzY2hlbWU/OiBcImhtYWMtc2hhMjU2XCIgfCBcImhtYWMtc2hhMVwiIHwgXCJobWFjLXNoYTUxMlwiO1xuXHRcdGhlYWRlcjogc3RyaW5nO1xuXHRcdGZvcm1hdD86IHN0cmluZztcblx0XHRzZWNyZXRFbnY6IHN0cmluZztcblx0XHR0b2xlcmFuY2U/OiBudW1iZXI7XG5cdFx0dGltZXN0YW1wSGVhZGVyPzogc3RyaW5nO1xuXHR9O1xuXHR0b2xlcmFuY2U/OiBudW1iZXI7XG5cdGlkZW1wb3RlbmN5S2V5Pzogc3RyaW5nO1xuXHRuYW1lc3BhY2U/OiBzdHJpbmc7XG5cdG1pZGRsZXdhcmU/OiBzdHJpbmdbXTtcbn1cblxuaW50ZXJmYWNlIEh0dHBUcmlnZ2VyTGlrZSB7XG5cdGFkZFByZUNhdGNoQWxsSG9vayhjYjogKCkgPT4gdm9pZCB8IFByb21pc2U8dm9pZD4pOiB2b2lkO1xufVxuXG5jb25zdCBERUZBVUxUX1RPTEVSQU5DRV9TRUMgPSAzMDA7XG5jb25zdCBERUZBVUxUX1JFUExBWV9UVExfTVMgPSA1ICogNjAgKiAxMDAwOyAvLyA1IG1pbiDigJQgbWF0Y2ggU3RyaXBlIC8gU3ZpeCBkZWZhdWx0LlxuY29uc3QgUkVQTEFZX05BTUVTUEFDRSA9IFwiX193ZWJob29rX19cIjtcblxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbi8vIFRyaWdnZXIgY2xhc3Ncbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFdlYmhvb2tUcmlnZ2VyIGV4dGVuZHMgVHJpZ2dlckJhc2Uge1xuXHRwcm90ZWN0ZWQgbm9kZU1hcDogUnVubmVyR2xvYmFsT3B0aW9ucyA9IHt9IGFzIFJ1bm5lckdsb2JhbE9wdGlvbnM7XG5cdHByb3RlY3RlZCByZWFkb25seSBsb2dnZXIgPSBuZXcgRGVmYXVsdExvZ2dlcigpO1xuXHRwcm90ZWN0ZWQgcmVhZG9ubHkgdHJhY2VyID0gdHJhY2UuZ2V0VHJhY2VyKFxuXHRcdHByb2Nlc3MuZW52LlBST0pFQ1RfTkFNRSB8fCBcInRyaWdnZXItd2ViaG9vay13b3JrZmxvd1wiLFxuXHRcdHByb2Nlc3MuZW52LlBST0pFQ1RfVkVSU0lPTiB8fCBcIjAuMC4xXCIsXG5cdCk7XG5cblx0cHJpdmF0ZSByZWFkb25seSBtZXRlciA9IG1ldHJpY3MuZ2V0TWV0ZXIoXCJibG9rXCIpO1xuXHRwcml2YXRlIHJlYWRvbmx5IGNvdW50ZXJSZWNlaXZlZCA9IHRoaXMubWV0ZXIuY3JlYXRlQ291bnRlcihcImJsb2tfd2ViaG9va19yZWNlaXZlZF90b3RhbFwiLCB7XG5cdFx0ZGVzY3JpcHRpb246IFwiV2ViaG9vayBkZWxpdmVyaWVzIHJlY2VpdmVkIChjdW11bGF0aXZlKS5cIixcblx0XHR1bml0OiBcIjFcIixcblx0fSk7XG5cdHByaXZhdGUgcmVhZG9ubHkgY291bnRlclJlamVjdGVkID0gdGhpcy5tZXRlci5jcmVhdGVDb3VudGVyKFwiYmxva193ZWJob29rX3JlamVjdGVkX3RvdGFsXCIsIHtcblx0XHRkZXNjcmlwdGlvbjogXCJXZWJob29rIGRlbGl2ZXJpZXMgcmVqZWN0ZWQgKHNpZ25hdHVyZSBmYWlsdXJlLCBhbGxvd2xpc3QgbWlzcywgcmVwbGF5KS5cIixcblx0XHR1bml0OiBcIjFcIixcblx0fSk7XG5cdHByaXZhdGUgcmVhZG9ubHkgY291bnRlckFjY2VwdGVkID0gdGhpcy5tZXRlci5jcmVhdGVDb3VudGVyKFwiYmxva193ZWJob29rX2FjY2VwdGVkX3RvdGFsXCIsIHtcblx0XHRkZXNjcmlwdGlvbjogXCJXZWJob29rIGRlbGl2ZXJpZXMgdGhhdCB0cmlnZ2VyZWQgYSB3b3JrZmxvdyBydW4uXCIsXG5cdFx0dW5pdDogXCIxXCIsXG5cdH0pO1xuXG5cdC8vIGJpb21lLWlnbm9yZSBsaW50L3N1c3BpY2lvdXMvbm9FeHBsaWNpdEFueTogSG9ubydzIGdlbmVyaWMgcHJvcGFnYXRpb25cblx0cHJpdmF0ZSByZWFkb25seSBhcHA6IEhvbm88YW55LCBhbnksIGFueT47XG5cdHByaXZhdGUgcmVhZG9ubHkgaHR0cFRyaWdnZXI6IEh0dHBUcmlnZ2VyTGlrZSB8IG51bGw7XG5cblx0cHJpdmF0ZSB3aXJlZCA9IGZhbHNlO1xuXG5cdC8vIGJpb21lLWlnbm9yZSBsaW50L3N1c3BpY2lvdXMvbm9FeHBsaWNpdEFueTogbWF0Y2hlcyBgYXBwYCBmaWVsZCdzIGFueSBnZW5lcmljXG5cdGNvbnN0cnVjdG9yKGFwcDogSG9ubzxhbnksIGFueSwgYW55PiwgaHR0cFRyaWdnZXI/OiBIdHRwVHJpZ2dlckxpa2UpIHtcblx0XHRzdXBlcigpO1xuXHRcdHRoaXMuYXBwID0gYXBwO1xuXHRcdHRoaXMuaHR0cFRyaWdnZXIgPSBodHRwVHJpZ2dlciA/PyBudWxsO1xuXHRcdF9zZXRBY3RpdmVXZWJob29rVHJpZ2dlcih0aGlzKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBJbmplY3QgdGhlIHJ1bm5lcidzIEdsb2JhbE9wdGlvbnMgKG5vZGVzICsgd29ya2Zsb3dzKS4gQ2FsbGVkIGJ5XG5cdCAqIHRoZSBvcmNoZXN0cmF0b3IgQUZURVIgY29uc3RydWN0aW5nIHRoZSB0cmlnZ2VyIGJ1dCBCRUZPUkVcblx0ICogYGxpc3RlbigpYC4gU2hhcmVzIEh0dHBUcmlnZ2VyJ3Mgbm9kZU1hcCBzbyBwZXItcmVxdWVzdCB3b3JrZmxvd1xuXHQgKiBydW5zIHJlc29sdmUgaGVscGVycyArIHN1Yi13b3JrZmxvd3MgdGhyb3VnaCB0aGUgc2FtZSByZWdpc3RyeS5cblx0ICovXG5cdHNldE5vZGVNYXAobm9kZU1hcDogUnVubmVyR2xvYmFsT3B0aW9ucyk6IHZvaWQge1xuXHRcdHRoaXMubm9kZU1hcCA9IG5vZGVNYXA7XG5cdH1cblxuXHRhc3luYyBsaXN0ZW4oKTogUHJvbWlzZTxudW1iZXI+IHtcblx0XHRjb25zdCBzdGFydFRpbWUgPSB0aGlzLnN0YXJ0Q291bnRlcigpO1xuXHRcdGlmICh0aGlzLndpcmVkKSB7XG5cdFx0XHR0aGlzLmxvZ2dlci5sb2coXCJbYmxva11bd2ViaG9va10gbGlzdGVuKCkgY2FsbGVkIHR3aWNlOyBpZ25vcmluZ1wiKTtcblx0XHRcdHJldHVybiB0aGlzLmVuZENvdW50ZXIoc3RhcnRUaW1lKTtcblx0XHR9XG5cdFx0dGhpcy53aXJlZCA9IHRydWU7XG5cblx0XHRpZiAodGhpcy5odHRwVHJpZ2dlcikge1xuXHRcdFx0dGhpcy5odHRwVHJpZ2dlci5hZGRQcmVDYXRjaEFsbEhvb2soKCkgPT4ge1xuXHRcdFx0XHR0aGlzLnJlZ2lzdGVyUm91dGVzRnJvbVJlZ2lzdHJ5KCk7XG5cdFx0XHR9KTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0dGhpcy5yZWdpc3RlclJvdXRlc0Zyb21SZWdpc3RyeSgpO1xuXHRcdH1cblxuXHRcdHJldHVybiB0aGlzLmVuZENvdW50ZXIoc3RhcnRUaW1lKTtcblx0fVxuXG5cdGFzeW5jIHN0b3AoKTogUHJvbWlzZTx2b2lkPiB7XG5cdFx0dGhpcy53aXJlZCA9IGZhbHNlO1xuXHRcdGlmIChfZ2V0QWN0aXZlV2ViaG9va1RyaWdnZXIoKSA9PT0gdGhpcykgX3NldEFjdGl2ZVdlYmhvb2tUcmlnZ2VyKG51bGwpO1xuXHRcdHRoaXMuZGVzdHJveU1vbml0b3JpbmcoKTtcblx0XHR0aGlzLmxvZ2dlci5sb2coXCJbYmxva11bd2ViaG9va10gc3RvcHBlZFwiKTtcblx0fVxuXG5cdC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXHQvLyBSb3V0ZSByZWdpc3RyYXRpb25cblx0Ly8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cblx0cHJpdmF0ZSByZWdpc3RlclJvdXRlc0Zyb21SZWdpc3RyeSgpOiB2b2lkIHtcblx0XHRjb25zdCB3b3JrZmxvd3MgPSB0aGlzLmdldFdlYmhvb2tXb3JrZmxvd3MoKTtcblx0XHRpZiAod29ya2Zsb3dzLmxlbmd0aCA9PT0gMCkge1xuXHRcdFx0dGhpcy5sb2dnZXIubG9nKFwiW2Jsb2tdW3dlYmhvb2tdIG5vIHdvcmtmbG93cyB3aXRoIHRyaWdnZXIud2ViaG9vayBmb3VuZFwiKTtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cdFx0dGhpcy5sb2dnZXIubG9nKGBbYmxva11bd2ViaG9va10gcmVnaXN0ZXJpbmcgJHt3b3JrZmxvd3MubGVuZ3RofSB3ZWJob29rIHJvdXRlKHMpOmApO1xuXHRcdGZvciAoY29uc3QgZW50cnkgb2Ygd29ya2Zsb3dzKSB7XG5cdFx0XHR0aGlzLnJlZ2lzdGVyV2ViaG9va1JvdXRlKGVudHJ5KTtcblx0XHR9XG5cdH1cblxuXHRwcml2YXRlIHJlZ2lzdGVyV2ViaG9va1JvdXRlKGVudHJ5OiB7IHdvcmtmbG93TmFtZTogc3RyaW5nOyBjb25maWc6IFdlYmhvb2tUcmlnZ2VyQ29uZmlnIH0pOiB2b2lkIHtcblx0XHRjb25zdCB7IHdvcmtmbG93TmFtZSwgY29uZmlnIH0gPSBlbnRyeTtcblx0XHRjb25zdCBwYXRoID0gY29uZmlnLnBhdGggPz8gKGNvbmZpZy5wcm92aWRlciA/IGAvd2ViaG9va3MvJHtjb25maWcucHJvdmlkZXJ9YCA6IGAvd2ViaG9va3MvJHt3b3JrZmxvd05hbWV9YCk7XG5cdFx0Y29uc3QgbGFiZWwgPSBjb25maWcucHJvdmlkZXIgPz8gXCJjdXN0b21cIjtcblx0XHR0aGlzLmxvZ2dlci5sb2coYFtibG9rXVt3ZWJob29rXSAgIFBPU1QgICAgJHtwYXRofSAg4oaQICAke3dvcmtmbG93TmFtZX0gICgke2xhYmVsfSlgKTtcblxuXHRcdHRoaXMuYXBwLnBvc3QocGF0aCwgKGM6IEhvbm9Db250ZXh0KSA9PiB0aGlzLmhhbmRsZVJlcXVlc3QoYywgd29ya2Zsb3dOYW1lLCBwYXRoLCBjb25maWcpKTtcblx0fVxuXG5cdHByaXZhdGUgYXN5bmMgaGFuZGxlUmVxdWVzdChcblx0XHRjOiBIb25vQ29udGV4dCxcblx0XHR3b3JrZmxvd05hbWU6IHN0cmluZyxcblx0XHRwYXRoOiBzdHJpbmcsXG5cdFx0Y29uZmlnOiBXZWJob29rVHJpZ2dlckNvbmZpZyxcblx0KTogUHJvbWlzZTxSZXNwb25zZT4ge1xuXHRcdHRoaXMuY291bnRlclJlY2VpdmVkLmFkZCgxLCB7IHdvcmtmbG93X25hbWU6IHdvcmtmbG93TmFtZSB9KTtcblxuXHRcdC8vIDEuIENhcHR1cmUgcmF3IGJvZHkgQkVGT1JFIHBhcnNpbmcg4oCUIHZlcmlmaWVycyBzaWduIHRoZSB3aXJlIGJ5dGVzLlxuXHRcdGNvbnN0IHJhd0JvZHkgPSBhd2FpdCBjLnJlcS50ZXh0KCk7XG5cdFx0bGV0IHBhcnNlZEJvZHk6IHVua25vd24gPSB7fTtcblx0XHRpZiAocmF3Qm9keS5sZW5ndGggPiAwKSB7XG5cdFx0XHR0cnkge1xuXHRcdFx0XHRwYXJzZWRCb2R5ID0gSlNPTi5wYXJzZShyYXdCb2R5KSBhcyB1bmtub3duO1xuXHRcdFx0fSBjYXRjaCB7XG5cdFx0XHRcdC8vIE5vbi1KU09OIGJvZHkg4oCUIGxlYXZlIHBhcnNlZCBhcyB0aGUgcmF3IHRleHQuIFNsYWNrXG5cdFx0XHRcdC8vIGNoYWxsZW5nZXMgJiBTaG9waWZ5IGNhbiBwb3N0IG5vbi1KU09OIG9jY2FzaW9uYWxseS5cblx0XHRcdFx0cGFyc2VkQm9keSA9IHJhd0JvZHk7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0Y29uc3QgaGVhZGVycyA9IE9iamVjdC5mcm9tRW50cmllcyhjLnJlcS5yYXcuaGVhZGVycyk7XG5cdFx0Y29uc3QgcGF0aFBhcmFtcyA9IGMucmVxLnBhcmFtKCkgYXMgUmVjb3JkPHN0cmluZywgc3RyaW5nPjtcblx0XHRjb25zdCBxdWVyeVBhcmFtcyA9IE9iamVjdC5mcm9tRW50cmllcyhuZXcgVVJMKGMucmVxLnVybCkuc2VhcmNoUGFyYW1zKTtcblxuXHRcdC8vIDIuIFBpY2sgdGhlIHZlcmlmaWVyLlxuXHRcdGNvbnN0IHZlcmlmaWVyID0gdGhpcy5yZXNvbHZlVmVyaWZpZXIod29ya2Zsb3dOYW1lLCBjb25maWcpO1xuXHRcdGlmICghdmVyaWZpZXIpIHtcblx0XHRcdHRoaXMuY291bnRlclJlamVjdGVkLmFkZCgxLCB7IHdvcmtmbG93X25hbWU6IHdvcmtmbG93TmFtZSwgcmVhc29uOiBcIm5vX3ZlcmlmaWVyXCIgfSk7XG5cdFx0XHRyZXR1cm4gYy5qc29uKHsgZXJyb3I6IFwiQ29uZmlndXJhdGlvblwiLCByZWFzb246IFwibm9fdmVyaWZpZXJcIiwgbWVzc2FnZTogXCJObyB2ZXJpZmllciBjb25maWd1cmVkXCIgfSwgNTAwKTtcblx0XHR9XG5cblx0XHQvLyAzLiBSZXNvbHZlIHRoZSBzZWNyZXQgZnJvbSB0aGUgZW52IHZhci5cblx0XHRjb25zdCBzZWNyZXRFbnYgPSBjb25maWcuc2VjcmV0RW52ID8/IGNvbmZpZy5zaWduYXR1cmU/LnNlY3JldEVudjtcblx0XHRjb25zdCBzZWNyZXQgPSBzZWNyZXRFbnYgPyAocHJvY2Vzcy5lbnZbc2VjcmV0RW52XSA/PyBcIlwiKSA6IFwiXCI7XG5cblx0XHQvLyA0LiBWZXJpZnkuXG5cdFx0Y29uc3QgdG9sZXJhbmNlU2VjID0gY29uZmlnLnRvbGVyYW5jZSA/PyBjb25maWcuc2lnbmF0dXJlPy50b2xlcmFuY2UgPz8gREVGQVVMVF9UT0xFUkFOQ0VfU0VDO1xuXHRcdGNvbnN0IHJlc3VsdDogVmVyaWZ5UmVzdWx0ID0gdmVyaWZpZXIudmVyaWZ5KHtcblx0XHRcdGhlYWRlcnMsXG5cdFx0XHRyYXdCb2R5LFxuXHRcdFx0cGFyc2VkQm9keSxcblx0XHRcdHNlY3JldCxcblx0XHRcdHRvbGVyYW5jZVNlYyxcblx0XHR9KTtcblxuXHRcdGlmICghcmVzdWx0Lm9rKSB7XG5cdFx0XHR0aGlzLmNvdW50ZXJSZWplY3RlZC5hZGQoMSwgeyB3b3JrZmxvd19uYW1lOiB3b3JrZmxvd05hbWUsIHJlYXNvbjogcmVzdWx0LnJlYXNvbiB9KTtcblx0XHRcdHRoaXMubG9nZ2VyLmVycm9yKFxuXHRcdFx0XHRgW2Jsb2tdW3dlYmhvb2tdICR7d29ya2Zsb3dOYW1lfTogdmVyaWZ5IGZhaWxlZCByZWFzb249JHtyZXN1bHQucmVhc29ufSBtZXNzYWdlPVwiJHtyZXN1bHQubWVzc2FnZX1cImAsXG5cdFx0XHQpO1xuXHRcdFx0cmV0dXJuIGMuanNvbih7IGVycm9yOiBcIlVuYXV0aG9yaXplZFwiLCByZWFzb246IHJlc3VsdC5yZWFzb24sIG1lc3NhZ2U6IHJlc3VsdC5tZXNzYWdlIH0sIDQwMSk7XG5cdFx0fVxuXG5cdFx0Ly8gNS4gRXZlbnRzIGFsbG93bGlzdCDigJQgdmVyaWZpZWQtYnV0LW91dC1vZi1zY29wZSByZXR1cm5zIDIwMCAobm8gcmV0cnkpLlxuXHRcdGlmIChBcnJheS5pc0FycmF5KGNvbmZpZy5ldmVudHMpICYmIGNvbmZpZy5ldmVudHMubGVuZ3RoID4gMCAmJiAhY29uZmlnLmV2ZW50cy5pbmNsdWRlcyhyZXN1bHQuZXZlbnRUeXBlKSkge1xuXHRcdFx0dGhpcy5jb3VudGVyUmVqZWN0ZWQuYWRkKDEsIHsgd29ya2Zsb3dfbmFtZTogd29ya2Zsb3dOYW1lLCByZWFzb246IFwiZXZlbnRfbm90X2FsbG93ZWRcIiB9KTtcblx0XHRcdHJldHVybiBjLmpzb24oeyBzdGF0dXM6IFwiaWdub3JlZFwiLCByZWFzb246IFwiZXZlbnRfbm90X2FsbG93ZWRcIiwgZXZlbnRUeXBlOiByZXN1bHQuZXZlbnRUeXBlIH0sIDIwMCk7XG5cdFx0fVxuXG5cdFx0Ly8gNi4gUmVwbGF5IHByb3RlY3Rpb24gdmlhIHRoZSBpZGVtcG90ZW5jeSBjYWNoZS5cblx0XHRpZiAoY29uZmlnLmlkZW1wb3RlbmN5S2V5ICYmIHJlc3VsdC5ldmVudElkKSB7XG5cdFx0XHRjb25zdCB0cmFja2VyID0gUnVuVHJhY2tlci5nZXRJbnN0YW5jZSgpO1xuXHRcdFx0Y29uc3Qgc3RvcmUgPSB0cmFja2VyLmdldFN0b3JlKCk7XG5cdFx0XHRjb25zdCBjYWNoZWQgPSBzdG9yZS5nZXRJZGVtcG90ZW5jeUNhY2hlKFJFUExBWV9OQU1FU1BBQ0UsIHdvcmtmbG93TmFtZSwgcmVzdWx0LmV2ZW50SWQpO1xuXHRcdFx0aWYgKGNhY2hlZCkge1xuXHRcdFx0XHR0aGlzLmNvdW50ZXJSZWplY3RlZC5hZGQoMSwgeyB3b3JrZmxvd19uYW1lOiB3b3JrZmxvd05hbWUsIHJlYXNvbjogXCJyZXBsYXlcIiB9KTtcblx0XHRcdFx0cmV0dXJuIGMuanNvbihcblx0XHRcdFx0XHR7XG5cdFx0XHRcdFx0XHRzdGF0dXM6IFwiZHVwbGljYXRlXCIsXG5cdFx0XHRcdFx0XHRldmVudElkOiByZXN1bHQuZXZlbnRJZCxcblx0XHRcdFx0XHRcdGV2ZW50VHlwZTogcmVzdWx0LmV2ZW50VHlwZSxcblx0XHRcdFx0XHRcdGZpcnN0U2VlblJ1bklkOiBjYWNoZWQuc291cmNlUnVuSWQsXG5cdFx0XHRcdFx0fSxcblx0XHRcdFx0XHQyMDAsXG5cdFx0XHRcdCk7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0Ly8gNy4gVmVyaWZpZWQgKyBuZXcgZXZlbnQg4oCUIGRpc3BhdGNoIHRoZSB3b3JrZmxvdy5cblx0XHR0aGlzLmNvdW50ZXJBY2NlcHRlZC5hZGQoMSwgeyB3b3JrZmxvd19uYW1lOiB3b3JrZmxvd05hbWUgfSk7XG5cdFx0Y29uc3QgcmVxdWVzdElkID0gdXVpZCgpO1xuXHRcdGNvbnN0IGRpc3BhdGNoT3V0Y29tZSA9IGF3YWl0IHRoaXMuZGlzcGF0Y2hXb3JrZmxvdyh7XG5cdFx0XHR3b3JrZmxvd05hbWUsXG5cdFx0XHRwYXRoLFxuXHRcdFx0Y29uZmlnLFxuXHRcdFx0cmVxdWVzdElkLFxuXHRcdFx0aGVhZGVycyxcblx0XHRcdGJvZHk6IHBhcnNlZEJvZHksXG5cdFx0XHRyYXdCb2R5LFxuXHRcdFx0cGF0aFBhcmFtcyxcblx0XHRcdHF1ZXJ5UGFyYW1zLFxuXHRcdFx0ZXZlbnRJZDogcmVzdWx0LmV2ZW50SWQsXG5cdFx0XHRldmVudFR5cGU6IHJlc3VsdC5ldmVudFR5cGUsXG5cdFx0fSk7XG5cblx0XHQvLyA4LiBDYWNoZSBldmVudCBpZCBBRlRFUiBzdWNjZXNzZnVsIGRpc3BhdGNoIHNvIHJldHJpZXMgb24gdGhlXG5cdFx0Ly8gICAgc2FtZSBkZWxpdmVyeSBhcmUgZGVkdXBlZC4gV2UgY2FjaGUgZXZlbiBvbiB3b3JrZmxvdyBmYWlsdXJlXG5cdFx0Ly8gICAg4oCUIHdlYmhvb2sgc2VuZGVycyBzaG91bGQgbm90IHJldHJ5IGRlbGl2ZXJpZXMgdGhleSd2ZVxuXHRcdC8vICAgIGFscmVhZHkgZGVsaXZlcmVkICh0aGUgd29ya2Zsb3cncyBvd24gcmV0cnkgLyBETFEgb3ducyB0aGF0KS5cblx0XHRpZiAoY29uZmlnLmlkZW1wb3RlbmN5S2V5ICYmIHJlc3VsdC5ldmVudElkKSB7XG5cdFx0XHRjb25zdCB0cmFja2VyID0gUnVuVHJhY2tlci5nZXRJbnN0YW5jZSgpO1xuXHRcdFx0Y29uc3Qgc3RvcmUgPSB0cmFja2VyLmdldFN0b3JlKCk7XG5cdFx0XHRzdG9yZS5zZXRJZGVtcG90ZW5jeUNhY2hlKFJFUExBWV9OQU1FU1BBQ0UsIHdvcmtmbG93TmFtZSwgcmVzdWx0LmV2ZW50SWQsIHtcblx0XHRcdFx0ZGF0YTogeyBldmVudElkOiByZXN1bHQuZXZlbnRJZCwgZXZlbnRUeXBlOiByZXN1bHQuZXZlbnRUeXBlIH0sXG5cdFx0XHRcdGNhY2hlZEF0OiBEYXRlLm5vdygpLFxuXHRcdFx0XHRleHBpcmVzQXQ6IERhdGUubm93KCkgKyBERUZBVUxUX1JFUExBWV9UVExfTVMsXG5cdFx0XHRcdHNvdXJjZVJ1bklkOiByZXF1ZXN0SWQsXG5cdFx0XHRcdHNvdXJjZU5vZGVSdW5JZDogcmVxdWVzdElkLFxuXHRcdFx0fSk7XG5cdFx0fVxuXG5cdFx0Ly8gOS4gU2hhcGUgdGhlIHJlc3BvbnNlLiBXb3JrZmxvdydzIGBjdHgucmVzcG9uc2VgIGxhbmRzIGluIHRoZVxuXHRcdC8vICAgIGJvZHkgZm9yIHBhcml0eSB3aXRoIEhUVFAgdHJpZ2dlcnMuXG5cdFx0cmV0dXJuIGMuanNvbihcblx0XHRcdHtcblx0XHRcdFx0c3RhdHVzOiBcIm9rXCIsXG5cdFx0XHRcdGV2ZW50SWQ6IHJlc3VsdC5ldmVudElkLFxuXHRcdFx0XHRldmVudFR5cGU6IHJlc3VsdC5ldmVudFR5cGUsXG5cdFx0XHRcdHJ1bklkOiByZXF1ZXN0SWQsXG5cdFx0XHRcdHJlc3BvbnNlOiBkaXNwYXRjaE91dGNvbWUsXG5cdFx0XHR9LFxuXHRcdFx0MjAwLFxuXHRcdCk7XG5cdH1cblxuXHRwcml2YXRlIHJlc29sdmVWZXJpZmllcih3b3JrZmxvd05hbWU6IHN0cmluZywgY29uZmlnOiBXZWJob29rVHJpZ2dlckNvbmZpZyk6IFZlcmlmaWVyIHwgbnVsbCB7XG5cdFx0aWYgKGNvbmZpZy5wcm92aWRlcikge1xuXHRcdFx0Y29uc3QgdiA9IEJVSUxUSU5fVkVSSUZJRVJTW2NvbmZpZy5wcm92aWRlcl07XG5cdFx0XHRpZiAoIXYpIHtcblx0XHRcdFx0dGhpcy5sb2dnZXIuZXJyb3IoYFtibG9rXVt3ZWJob29rXSAke3dvcmtmbG93TmFtZX06IHVua25vd24gcHJvdmlkZXIgXCIke2NvbmZpZy5wcm92aWRlcn1cImApO1xuXHRcdFx0XHRyZXR1cm4gbnVsbDtcblx0XHRcdH1cblx0XHRcdHJldHVybiB2O1xuXHRcdH1cblx0XHRpZiAoY29uZmlnLnNpZ25hdHVyZSkge1xuXHRcdFx0cmV0dXJuIGJ1aWxkQ3VzdG9tVmVyaWZpZXIoe1xuXHRcdFx0XHRzY2hlbWU6IGNvbmZpZy5zaWduYXR1cmUuc2NoZW1lID8/IFwiaG1hYy1zaGEyNTZcIixcblx0XHRcdFx0aGVhZGVyOiBjb25maWcuc2lnbmF0dXJlLmhlYWRlcixcblx0XHRcdFx0Zm9ybWF0OiBjb25maWcuc2lnbmF0dXJlLmZvcm1hdCA/PyBcIntoZXh9XCIsXG5cdFx0XHRcdHNlY3JldEVudjogY29uZmlnLnNpZ25hdHVyZS5zZWNyZXRFbnYsXG5cdFx0XHRcdHRvbGVyYW5jZTogY29uZmlnLnNpZ25hdHVyZS50b2xlcmFuY2UgPz8gREVGQVVMVF9UT0xFUkFOQ0VfU0VDLFxuXHRcdFx0XHR0aW1lc3RhbXBIZWFkZXI6IGNvbmZpZy5zaWduYXR1cmUudGltZXN0YW1wSGVhZGVyLFxuXHRcdFx0fSk7XG5cdFx0fVxuXHRcdHJldHVybiBudWxsO1xuXHR9XG5cblx0Ly8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cdC8vIFdvcmtmbG93IGRpc3BhdGNoXG5cdC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG5cdHByaXZhdGUgYXN5bmMgZGlzcGF0Y2hXb3JrZmxvdyhvcHRzOiB7XG5cdFx0d29ya2Zsb3dOYW1lOiBzdHJpbmc7XG5cdFx0cGF0aDogc3RyaW5nO1xuXHRcdGNvbmZpZzogV2ViaG9va1RyaWdnZXJDb25maWc7XG5cdFx0cmVxdWVzdElkOiBzdHJpbmc7XG5cdFx0aGVhZGVyczogUmVjb3JkPHN0cmluZywgc3RyaW5nPjtcblx0XHRib2R5OiB1bmtub3duO1xuXHRcdHJhd0JvZHk6IHN0cmluZztcblx0XHRwYXRoUGFyYW1zOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+O1xuXHRcdHF1ZXJ5UGFyYW1zOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+O1xuXHRcdGV2ZW50SWQ6IHN0cmluZztcblx0XHRldmVudFR5cGU6IHN0cmluZztcblx0fSk6IFByb21pc2U8dW5rbm93bj4ge1xuXHRcdGNvbnN0IHsgd29ya2Zsb3dOYW1lLCByZXF1ZXN0SWQsIGhlYWRlcnMsIGJvZHksIHJhd0JvZHksIHBhdGhQYXJhbXMsIHF1ZXJ5UGFyYW1zLCBldmVudElkLCBldmVudFR5cGUgfSA9IG9wdHM7XG5cblx0XHRyZXR1cm4gdGhpcy50cmFjZXIuc3RhcnRBY3RpdmVTcGFuKGB3ZWJob29rOiR7d29ya2Zsb3dOYW1lfWAsIGFzeW5jIChzcGFuOiBTcGFuKSA9PiB7XG5cdFx0XHR0cnkge1xuXHRcdFx0XHRjb25zdCByZWdpc3RyeSA9IFdvcmtmbG93UmVnaXN0cnkuZ2V0SW5zdGFuY2UoKTtcblx0XHRcdFx0Y29uc3QgZW50cnkgPSByZWdpc3RyeS5nZXQod29ya2Zsb3dOYW1lKTtcblx0XHRcdFx0aWYgKCFlbnRyeSkge1xuXHRcdFx0XHRcdHRocm93IG5ldyBFcnJvcihgW2Jsb2tdW3dlYmhvb2tdIHdvcmtmbG93IFwiJHt3b3JrZmxvd05hbWV9XCIgbm90IGZvdW5kIGluIHJlZ2lzdHJ5YCk7XG5cdFx0XHRcdH1cblx0XHRcdFx0YXdhaXQgdGhpcy5jb25maWd1cmF0aW9uLmluaXQod29ya2Zsb3dOYW1lLCB0aGlzLm5vZGVNYXAsIGVudHJ5LndvcmtmbG93KTtcblxuXHRcdFx0XHRjb25zdCBjdHg6IENvbnRleHQgPSB0aGlzLmNyZWF0ZUNvbnRleHQodW5kZWZpbmVkLCB3b3JrZmxvd05hbWUsIHJlcXVlc3RJZCk7XG5cdFx0XHRcdGN0eC5yZXF1ZXN0ID0ge1xuXHRcdFx0XHRcdGJvZHksXG5cdFx0XHRcdFx0cmF3Qm9keSxcblx0XHRcdFx0XHRoZWFkZXJzLFxuXHRcdFx0XHRcdHBhcmFtczogcGF0aFBhcmFtcyxcblx0XHRcdFx0XHRxdWVyeTogcXVlcnlQYXJhbXMsXG5cdFx0XHRcdH0gYXMgdW5rbm93biBhcyBSZXF1ZXN0Q29udGV4dDtcblxuXHRcdFx0XHQvLyBTdGFtcCB3ZWJob29rIG1ldGFkYXRhIG9udG8gY3R4IHNvIHBvbHltb3JwaGljIGRpc3BhdGNoXG5cdFx0XHRcdC8vIGNhbiByZWFkIG5hbWVzcGFjZSArIGV2ZW50IG1ldGFkYXRhIHVuaWZvcm1seS5cblx0XHRcdFx0KGN0eCBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPikuX3dlYmhvb2sgPSB7XG5cdFx0XHRcdFx0ZXZlbnRJZCxcblx0XHRcdFx0XHRldmVudFR5cGUsXG5cdFx0XHRcdFx0bmFtZXNwYWNlOiBvcHRzLmNvbmZpZy5uYW1lc3BhY2UsXG5cdFx0XHRcdH07XG5cblx0XHRcdFx0YXdhaXQgdGhpcy5hcHBseU1pZGRsZXdhcmVDaGFpbihjdHgsIHRoaXMubm9kZU1hcCk7XG5cdFx0XHRcdGF3YWl0IHRoaXMucnVuKGN0eCk7XG5cblx0XHRcdFx0c3Bhbi5zZXRBdHRyaWJ1dGUoXCJ3b3JrZmxvd19uYW1lXCIsIHdvcmtmbG93TmFtZSk7XG5cdFx0XHRcdHNwYW4uc2V0QXR0cmlidXRlKFwiZXZlbnRfaWRcIiwgZXZlbnRJZCk7XG5cdFx0XHRcdHNwYW4uc2V0QXR0cmlidXRlKFwiZXZlbnRfdHlwZVwiLCBldmVudFR5cGUpO1xuXHRcdFx0XHRzcGFuLnNldFN0YXR1cyh7IGNvZGU6IFNwYW5TdGF0dXNDb2RlLk9LIH0pO1xuXHRcdFx0XHRyZXR1cm4gY3R4LnJlc3BvbnNlO1xuXHRcdFx0fSBjYXRjaCAoZXJyKSB7XG5cdFx0XHRcdGNvbnN0IG1zZyA9IGVyciBpbnN0YW5jZW9mIEVycm9yID8gZXJyLm1lc3NhZ2UgOiBTdHJpbmcoZXJyKTtcblx0XHRcdFx0c3Bhbi5yZWNvcmRFeGNlcHRpb24oZXJyIGFzIEVycm9yKTtcblx0XHRcdFx0c3Bhbi5zZXRTdGF0dXMoeyBjb2RlOiBTcGFuU3RhdHVzQ29kZS5FUlJPUiwgbWVzc2FnZTogbXNnIH0pO1xuXHRcdFx0XHR0aGlzLmxvZ2dlci5lcnJvcihgW2Jsb2tdW3dlYmhvb2tdIHdvcmtmbG93ICR7d29ya2Zsb3dOYW1lfSBmYWlsZWQ6ICR7bXNnfWApO1xuXHRcdFx0XHRyZXR1cm4geyBlcnJvcjogbXNnIH07XG5cdFx0XHR9IGZpbmFsbHkge1xuXHRcdFx0XHRzcGFuLmVuZCgpO1xuXHRcdFx0fVxuXHRcdH0pO1xuXHR9XG5cblx0Ly8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cdC8vIEludHJvc3BlY3Rpb25cblx0Ly8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cblx0Z2V0U3RhdHMoKTogeyB3b3JrZmxvd3NSZWdpc3RlcmVkOiBudW1iZXIgfSB7XG5cdFx0cmV0dXJuIHsgd29ya2Zsb3dzUmVnaXN0ZXJlZDogdGhpcy5nZXRXZWJob29rV29ya2Zsb3dzKCkubGVuZ3RoIH07XG5cdH1cblxuXHRwcml2YXRlIGdldFdlYmhvb2tXb3JrZmxvd3MoKTogQXJyYXk8eyB3b3JrZmxvd05hbWU6IHN0cmluZzsgY29uZmlnOiBXZWJob29rVHJpZ2dlckNvbmZpZyB9PiB7XG5cdFx0Y29uc3QgcmVnaXN0cnkgPSBXb3JrZmxvd1JlZ2lzdHJ5LmdldEluc3RhbmNlKCk7XG5cdFx0Y29uc3Qgb3V0OiBBcnJheTx7IHdvcmtmbG93TmFtZTogc3RyaW5nOyBjb25maWc6IFdlYmhvb2tUcmlnZ2VyQ29uZmlnIH0+ID0gW107XG5cdFx0Zm9yIChjb25zdCBlbnRyeSBvZiByZWdpc3RyeS5saXN0KCkpIHtcblx0XHRcdGNvbnN0IHdmID0gZW50cnkud29ya2Zsb3cgYXMgeyB0cmlnZ2VyPzogeyB3ZWJob29rPzogV2ViaG9va1RyaWdnZXJDb25maWcgfSB9IHwgdW5kZWZpbmVkO1xuXHRcdFx0Y29uc3QgY2ZnID0gd2Y/LnRyaWdnZXI/LndlYmhvb2s7XG5cdFx0XHRpZiAoIWNmZykgY29udGludWU7XG5cdFx0XHQvLyBTa2lwIGNvbmZpZ3MgbWlzc2luZyBib3RoIHByb3ZpZGVyIEFORCBzaWduYXR1cmUg4oCUIHRoZXkgY2FuJ3Rcblx0XHRcdC8vIHZlcmlmeSBhbnl0aGluZy4gQXV0aG9ycyBnZXQgYSBzdHJ1Y3R1cmVkIGVycm9yIGF0IGJvb3QuXG5cdFx0XHRpZiAoIWNmZy5wcm92aWRlciAmJiAhY2ZnLnNpZ25hdHVyZSkge1xuXHRcdFx0XHR0aGlzLmxvZ2dlci5lcnJvcihcblx0XHRcdFx0XHRgW2Jsb2tdW3dlYmhvb2tdIHdvcmtmbG93IFwiJHtlbnRyeS5uYW1lfVwiIGhhcyB0cmlnZ2VyLndlYmhvb2sgd2l0aCBuZWl0aGVyIFxcYHByb3ZpZGVyXFxgIG5vciBcXGBzaWduYXR1cmVcXGAg4oCUIHNraXBwaW5nLiBBZGQgb25lIHRvIGVuYWJsZSBzaWduYXR1cmUgdmVyaWZpY2F0aW9uLmAsXG5cdFx0XHRcdCk7XG5cdFx0XHRcdGNvbnRpbnVlO1xuXHRcdFx0fVxuXHRcdFx0b3V0LnB1c2goeyB3b3JrZmxvd05hbWU6IGVudHJ5Lm5hbWUsIGNvbmZpZzogY2ZnIH0pO1xuXHRcdH1cblx0XHRyZXR1cm4gb3V0O1xuXHR9XG59XG5cbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4vLyBTaW5nbGV0b24gYWNjZXNzb3IgKG1pcnJvcnMgV1MgLyBTU0UpXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG5sZXQgYWN0aXZlVHJpZ2dlcjogV2ViaG9va1RyaWdnZXIgfCBudWxsID0gbnVsbDtcblxuZXhwb3J0IGZ1bmN0aW9uIF9zZXRBY3RpdmVXZWJob29rVHJpZ2dlcih0cmlnZ2VyOiBXZWJob29rVHJpZ2dlciB8IG51bGwpOiB2b2lkIHtcblx0YWN0aXZlVHJpZ2dlciA9IHRyaWdnZXI7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBfZ2V0QWN0aXZlV2ViaG9va1RyaWdnZXIoKTogV2ViaG9va1RyaWdnZXIgfCBudWxsIHtcblx0cmV0dXJuIGFjdGl2ZVRyaWdnZXI7XG59XG5cbmV4cG9ydCB0eXBlIHsgV2ViaG9va1RyaWdnZXJDb25maWcgfTtcbiJdfQ==
|