@pipeline-builder/api-server 4.4.2 → 4.4.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/api/ai-call-reservation.d.ts +95 -0
- package/lib/api/ai-call-reservation.js +121 -0
- package/lib/api/app-factory.js +13 -5
- package/lib/api/check-quota.d.ts +47 -3
- package/lib/api/check-quota.js +203 -49
- package/lib/api/idempotency-middleware.d.ts +22 -0
- package/lib/api/idempotency-middleware.js +75 -23
- package/lib/api/index.d.ts +3 -2
- package/lib/api/index.js +4 -3
- package/lib/api/meter-quota.d.ts +42 -5
- package/lib/api/meter-quota.js +63 -11
- package/lib/api/metrics.d.ts +22 -6
- package/lib/api/metrics.js +105 -12
- package/lib/api/quota-reservation.d.ts +42 -3
- package/lib/api/quota-reservation.js +46 -19
- package/lib/api/server.js +5 -2
- package/lib/api/write-pin.js +29 -5
- package/lib/testing/exports.json +13 -0
- package/package.json +6 -5
package/lib/api/metrics.d.ts
CHANGED
|
@@ -24,6 +24,7 @@ export interface MetricHelpers {
|
|
|
24
24
|
incCounter(name: string, labels?: Record<string, string>, value?: number): void;
|
|
25
25
|
observe(name: string, labels: Record<string, string>, value: number): void;
|
|
26
26
|
setGauge(name: string, labels: Record<string, string>, value: number): void;
|
|
27
|
+
resetGauge(name: string): void;
|
|
27
28
|
}
|
|
28
29
|
/**
|
|
29
30
|
* Build `incCounter` / `observe` / `setGauge` over a caller-supplied registry.
|
|
@@ -45,12 +46,19 @@ export declare function createMetricHelpers(registry: Registry | (() => Registry
|
|
|
45
46
|
/**
|
|
46
47
|
* Increment a business counter, creating it on first use.
|
|
47
48
|
*
|
|
49
|
+
* Every example below is a call that EXISTS, with the labels it really passes. That is
|
|
50
|
+
* deliberate: an invented example reads as an inventory of what the system measures, and
|
|
51
|
+
* a metrics survey later counted three names from this block — `pipelines_generated_total`,
|
|
52
|
+
* `quota_threshold_crossed_total`, `compliance_violations_found_total` — as live metrics
|
|
53
|
+
* missing a dashboard panel. Nothing emitted any of them. Illustrative names in a docstring
|
|
54
|
+
* about metric naming are indistinguishable from real ones, so there are none here.
|
|
55
|
+
*
|
|
48
56
|
* @example
|
|
49
57
|
* ```typescript
|
|
50
|
-
* incCounter('
|
|
51
|
-
* incCounter('
|
|
52
|
-
* incCounter('
|
|
53
|
-
* incCounter('
|
|
58
|
+
* incCounter('plugin_builds_total', { status: 'success', org_id: orgId });
|
|
59
|
+
* incCounter('compliance_scans_total', { outcome: 'started' });
|
|
60
|
+
* incCounter('plugin_vuln_findings_total', { trigger, severity }, count);
|
|
61
|
+
* incCounter('ai_tokens_total', { route: 'agent', kind: 'input' }, inputTokens);
|
|
54
62
|
* ```
|
|
55
63
|
*/
|
|
56
64
|
export declare function incCounter(name: string, labels?: Record<string, string>, value?: number): void;
|
|
@@ -60,8 +68,8 @@ export declare function incCounter(name: string, labels?: Record<string, string>
|
|
|
60
68
|
*
|
|
61
69
|
* @example
|
|
62
70
|
* ```typescript
|
|
63
|
-
* observe('ai_generation_duration_seconds', {
|
|
64
|
-
* observe('plugin_build_duration_seconds', {
|
|
71
|
+
* observe('ai_generation_duration_seconds', { route, provider: providerLabel }, durationSec);
|
|
72
|
+
* observe('plugin_build_duration_seconds', { org_id: orgId }, durationSec);
|
|
65
73
|
* ```
|
|
66
74
|
*/
|
|
67
75
|
export declare function observe(name: string, labels: Record<string, string>, value: number): void;
|
|
@@ -77,3 +85,11 @@ export declare function observe(name: string, labels: Record<string, string>, va
|
|
|
77
85
|
* ```
|
|
78
86
|
*/
|
|
79
87
|
export declare function setGauge(name: string, labels: Record<string, string>, value: number): void;
|
|
88
|
+
/**
|
|
89
|
+
* Drop EVERY series of a business gauge. For a gauge that describes a SET — one
|
|
90
|
+
* series per configured entry — and is re-published whole: without the reset, a
|
|
91
|
+
* series for an entry that has since been deleted keeps its last value forever,
|
|
92
|
+
* and an alert on it keeps firing for something that no longer exists. Call it
|
|
93
|
+
* immediately before re-setting the current set. A gauge never set is a no-op.
|
|
94
|
+
*/
|
|
95
|
+
export declare function resetGauge(name: string): void;
|
package/lib/api/metrics.js
CHANGED
|
@@ -155,6 +155,77 @@ export function metricsHandler() {
|
|
|
155
155
|
res.end(await register.metrics());
|
|
156
156
|
};
|
|
157
157
|
}
|
|
158
|
+
// ---------------------------------------------------------------------------
|
|
159
|
+
// Business / domain metrics
|
|
160
|
+
//
|
|
161
|
+
// Services should emit counters for the things operators actually care about
|
|
162
|
+
// (pipelines generated, plugin builds completed, compliance violations,
|
|
163
|
+
// AI tokens consumed) — not just HTTP traffic. The helpers below register
|
|
164
|
+
// counters lazily on the shared registry so multiple services can call
|
|
165
|
+
// `incCounter('plugin_builds_total', { status: 'completed' })` without
|
|
166
|
+
// worrying about double-registration.
|
|
167
|
+
//
|
|
168
|
+
// Naming convention: `<domain>_<noun>_total` for counters, `_seconds` for
|
|
169
|
+
// histograms — matches Prometheus best-practice.
|
|
170
|
+
// ---------------------------------------------------------------------------
|
|
171
|
+
/**
|
|
172
|
+
* Bucket distributions for histograms whose observations are nowhere near the
|
|
173
|
+
* sub-second-to-minutes default.
|
|
174
|
+
*
|
|
175
|
+
* THIS TABLE EXISTS BECAUSE THE DEFAULT SILENTLY BREAKS ALERTS. The default set
|
|
176
|
+
* below ends at a 300-second bucket, and `histogram_quantile` cannot interpolate
|
|
177
|
+
* past the last FINITE boundary — everything above it lands in `+Inf` and the
|
|
178
|
+
* quantile reads back as 300 forever. An alert of the form `> 300` on such a
|
|
179
|
+
* histogram can therefore never fire, and a p90 panel flat-lines at five
|
|
180
|
+
* minutes however bad things get. Nothing errors, nothing is missing from the
|
|
181
|
+
* scrape, and the dashboard looks healthy: the only symptom is an alert that
|
|
182
|
+
* stays quiet through an outage. `support_first_response_seconds` measures hours
|
|
183
|
+
* to days and had a threshold of twelve hours sitting above a ceiling of five
|
|
184
|
+
* minutes.
|
|
185
|
+
*
|
|
186
|
+
* So a histogram whose natural range is minutes-to-days declares its buckets
|
|
187
|
+
* here, and ALERT THRESHOLDS ARE PUT ON BOUNDARIES: a threshold inside a wide
|
|
188
|
+
* bucket is served by linear interpolation across that bucket, which is a guess,
|
|
189
|
+
* while a threshold ON a boundary is exact. For support that means 6h (the alert)
|
|
190
|
+
* and 8h (the sold target) are both boundaries, 24h is the operational guard
|
|
191
|
+
* from the standard/priority rule, and 96h covers the longest legitimate wait a
|
|
192
|
+
* business-day target allows — a priority case raised at 17:01 on a Friday.
|
|
193
|
+
*
|
|
194
|
+
* Add a metric here when its observations can exceed five minutes. The table is
|
|
195
|
+
* read on FIRST USE of each name by `createMetricHelpers`, so both registries
|
|
196
|
+
* (api-server's and platform's own) get the same distribution, which is the
|
|
197
|
+
* drift the factory exists to prevent.
|
|
198
|
+
*/
|
|
199
|
+
const HISTOGRAM_BUCKETS = {
|
|
200
|
+
// 15m, 1h, 2h, 4h, 6h, 8h, 12h, 24h, 48h, 96h.
|
|
201
|
+
support_first_response_seconds: [900, 3600, 7200, 14400, 21600, 28800, 43200, 86400, 172800, 345600],
|
|
202
|
+
// Submission-to-decision latency is a human review queue: hours to days.
|
|
203
|
+
// 15m, 1h, 4h, 12h, 1d, 2d, 4d, 7d, 14d.
|
|
204
|
+
ecosystem_decision_latency_seconds: [900, 3600, 14400, 43200, 86400, 172800, 345600, 604800, 1209600],
|
|
205
|
+
// Queue wait. `PluginQueueProcessingSlow` asserts p95 > 300, which the default
|
|
206
|
+
// ceiling of 300 made unfireable; 300 is a boundary here so the comparison is
|
|
207
|
+
// exact rather than interpolated.
|
|
208
|
+
plugin_job_wait_seconds: [1, 5, 15, 30, 60, 120, 300, 600, 1800, 3600],
|
|
209
|
+
// A container build. Minutes normally, far longer for a cold base image.
|
|
210
|
+
plugin_build_duration_seconds: [10, 30, 60, 120, 300, 600, 1200, 1800, 3600],
|
|
211
|
+
// A full image scan, which routinely passes five minutes on a large image.
|
|
212
|
+
plugin_vuln_scan_duration_seconds: [1, 5, 15, 30, 60, 120, 300, 600, 1200],
|
|
213
|
+
// Time from an incident being raised to a human acknowledging it. The default
|
|
214
|
+
// buckets end at 300s, and `histogram_quantile` cannot interpolate past the
|
|
215
|
+
// last finite boundary — so with them, any threshold above five minutes could
|
|
216
|
+
// never fire, which is every threshold worth setting here. Boundaries at 1m,
|
|
217
|
+
// 2m, 5m, 10m, 15m, 30m, 1h, 2h, 4h: 15m is exact because that is the
|
|
218
|
+
// escalation delay the alert compares against, and the range reaches 4h so a
|
|
219
|
+
// page nobody ever picked up is still counted rather than clipped.
|
|
220
|
+
oncall_page_ack_seconds: [60, 120, 300, 600, 900, 1800, 3600, 7200, 14400],
|
|
221
|
+
// CSAT, 1-5. Not a duration at all, and listed here for the same reason as
|
|
222
|
+
// the others: the default buckets are sub-second, so every rating would land
|
|
223
|
+
// in the same bucket and the quantile would be meaningless. One boundary per
|
|
224
|
+
// possible score makes `_sum / _count` an exact average and each bucket a
|
|
225
|
+
// real count. It rides the histogram rather than a counter-per-score so the
|
|
226
|
+
// average needs no PromQL arithmetic over five series.
|
|
227
|
+
support_satisfaction: [1, 2, 3, 4, 5],
|
|
228
|
+
};
|
|
158
229
|
/**
|
|
159
230
|
* Build `incCounter` / `observe` / `setGauge` over a caller-supplied registry.
|
|
160
231
|
*
|
|
@@ -197,10 +268,12 @@ export function createMetricHelpers(registry) {
|
|
|
197
268
|
name,
|
|
198
269
|
help: humanizeName(name),
|
|
199
270
|
labelNames: Object.keys(labels),
|
|
200
|
-
// Default buckets target sub-second through several-minute
|
|
201
|
-
//
|
|
202
|
-
//
|
|
203
|
-
|
|
271
|
+
// Default buckets target sub-second through several-minute
|
|
272
|
+
// observations. Anything that can exceed five minutes MUST declare its
|
|
273
|
+
// own distribution in `HISTOGRAM_BUCKETS` above — past the last finite
|
|
274
|
+
// boundary a quantile reads back as that boundary, so a threshold
|
|
275
|
+
// beyond it never fires.
|
|
276
|
+
buckets: [...(HISTOGRAM_BUCKETS[name] ?? [0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10, 30, 60, 120, 300])],
|
|
204
277
|
registers: [registryOf()],
|
|
205
278
|
});
|
|
206
279
|
histograms.set(name, hist);
|
|
@@ -220,6 +293,9 @@ export function createMetricHelpers(registry) {
|
|
|
220
293
|
}
|
|
221
294
|
gauge.set(labels, value);
|
|
222
295
|
},
|
|
296
|
+
resetGauge(name) {
|
|
297
|
+
gauges.get(name)?.reset();
|
|
298
|
+
},
|
|
223
299
|
};
|
|
224
300
|
}
|
|
225
301
|
/** This service's own helpers, over the shared module-level registry. */
|
|
@@ -227,12 +303,19 @@ const businessMetrics = createMetricHelpers(register);
|
|
|
227
303
|
/**
|
|
228
304
|
* Increment a business counter, creating it on first use.
|
|
229
305
|
*
|
|
306
|
+
* Every example below is a call that EXISTS, with the labels it really passes. That is
|
|
307
|
+
* deliberate: an invented example reads as an inventory of what the system measures, and
|
|
308
|
+
* a metrics survey later counted three names from this block — `pipelines_generated_total`,
|
|
309
|
+
* `quota_threshold_crossed_total`, `compliance_violations_found_total` — as live metrics
|
|
310
|
+
* missing a dashboard panel. Nothing emitted any of them. Illustrative names in a docstring
|
|
311
|
+
* about metric naming are indistinguishable from real ones, so there are none here.
|
|
312
|
+
*
|
|
230
313
|
* @example
|
|
231
314
|
* ```typescript
|
|
232
|
-
* incCounter('
|
|
233
|
-
* incCounter('
|
|
234
|
-
* incCounter('
|
|
235
|
-
* incCounter('
|
|
315
|
+
* incCounter('plugin_builds_total', { status: 'success', org_id: orgId });
|
|
316
|
+
* incCounter('compliance_scans_total', { outcome: 'started' });
|
|
317
|
+
* incCounter('plugin_vuln_findings_total', { trigger, severity }, count);
|
|
318
|
+
* incCounter('ai_tokens_total', { route: 'agent', kind: 'input' }, inputTokens);
|
|
236
319
|
* ```
|
|
237
320
|
*/
|
|
238
321
|
export function incCounter(name, labels = {}, value = 1) {
|
|
@@ -244,8 +327,8 @@ export function incCounter(name, labels = {}, value = 1) {
|
|
|
244
327
|
*
|
|
245
328
|
* @example
|
|
246
329
|
* ```typescript
|
|
247
|
-
* observe('ai_generation_duration_seconds', {
|
|
248
|
-
* observe('plugin_build_duration_seconds', {
|
|
330
|
+
* observe('ai_generation_duration_seconds', { route, provider: providerLabel }, durationSec);
|
|
331
|
+
* observe('plugin_build_duration_seconds', { org_id: orgId }, durationSec);
|
|
249
332
|
* ```
|
|
250
333
|
*/
|
|
251
334
|
export function observe(name, labels, value) {
|
|
@@ -265,10 +348,20 @@ export function observe(name, labels, value) {
|
|
|
265
348
|
export function setGauge(name, labels, value) {
|
|
266
349
|
businessMetrics.setGauge(name, labels, value);
|
|
267
350
|
}
|
|
351
|
+
/**
|
|
352
|
+
* Drop EVERY series of a business gauge. For a gauge that describes a SET — one
|
|
353
|
+
* series per configured entry — and is re-published whole: without the reset, a
|
|
354
|
+
* series for an entry that has since been deleted keeps its last value forever,
|
|
355
|
+
* and an alert on it keeps firing for something that no longer exists. Call it
|
|
356
|
+
* immediately before re-setting the current set. A gauge never set is a no-op.
|
|
357
|
+
*/
|
|
358
|
+
export function resetGauge(name) {
|
|
359
|
+
businessMetrics.resetGauge(name);
|
|
360
|
+
}
|
|
268
361
|
function humanizeName(metricName) {
|
|
269
|
-
// `
|
|
362
|
+
// `plugin_builds_total` → "Plugin builds total"
|
|
270
363
|
return metricName
|
|
271
364
|
.replace(/_/g, ' ')
|
|
272
365
|
.replace(/^./, (c) => c.toUpperCase());
|
|
273
366
|
}
|
|
274
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWV0cmljcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9hcGkvbWV0cmljcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSwrQ0FBK0M7QUFDL0Msc0NBQXNDO0FBRXRDLE9BQU8sRUFBRSxvQkFBb0IsRUFBRSw4QkFBOEIsRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBQ2xHLE9BQU8sRUFBRSxNQUFNLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQztBQUV6RCxPQUFPLEVBQUUsUUFBUSxFQUFFLHFCQUFxQixFQUFFLE9BQU8sRUFBRSxTQUFTLEVBQUUsS0FBSyxFQUFFLE1BQU0sYUFBYSxDQUFDO0FBRXpGLE1BQU0sWUFBWSxHQUFJLE1BQU0sQ0FBQyxNQUFNLENBQUMsZUFBZSxDQUE2QixDQUFDLFdBQVcsQ0FBQztBQUU3RixpQ0FBaUM7QUFDakMsTUFBTSxRQUFRLEdBQUcsSUFBSSxRQUFRLEVBQUUsQ0FBQztBQUVoQyxxQ0FBcUM7QUFDckMsUUFBUSxDQUFDLGdCQUFnQixDQUFDLEVBQUUsT0FBTyxFQUFFLFlBQVksRUFBRSxDQUFDLENBQUM7QUFFckQsa0ZBQWtGO0FBQ2xGLHFCQUFxQixDQUFDLEVBQUUsUUFBUSxFQUFFLENBQUMsQ0FBQztBQUVwQzs7Ozs7O0dBTUc7QUFDSCxNQUFNLFVBQVUsMkJBQTJCLENBQUMsUUFBa0I7SUFDNUQsT0FBTyxJQUFJLEtBQUssQ0FBQztRQUNmLElBQUksRUFBRSw4QkFBOEI7UUFDcEMsSUFBSSxFQUFFLGtLQUFrSztRQUN4SyxVQUFVLEVBQUUsQ0FBQyxRQUFRLENBQVU7UUFDL0IsU0FBUyxFQUFFLENBQUMsUUFBUSxDQUFDO1FBQ3JCLE9BQU87WUFDTCxLQUFLLE1BQU0sRUFBRSxNQUFNLEVBQUUsV0FBVyxFQUFFLElBQUksb0JBQW9CLEVBQUUsRUFBRSxDQUFDO2dCQUM3RCxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsTUFBTSxFQUFFLEVBQUUsV0FBVyxDQUFDLENBQUMsQ0FBQyxD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O0FBQ0gsTUFBTSxVQUFVLFVBQVUsQ0FBQyxJQUFZLEVBQUUsTUFBTSxHQUEyQixFQUFFLEVBQUUsS0FBSyxHQUFHLENBQUM7SUFDckYsZUFBZSxDQUFDLFVBQVUsQ0FBQyxJQUFJLEVBQUUsTUFBTSxFQUFFLEtBQUssQ0FBQyxDQUFDO0FBQ2xELENBQUM7QUFFRDs7Ozs7Ozs7O0dBU0c7QUFDSCxNQUFNLFVBQVUsT0FBTyxDQUFDLElBQVksRUFBRSxNQUE4QixFQUFFLEtBQWE7SUFDakYsZUFBZSxDQUFDLE9BQU8sQ0FBQyxJQUFJLEVBQUUsTUFBTSxFQUFFLEtBQUssQ0FBQyxDQUFDO0FBQy9DLENBQUM7QUFFRDs7Ozs7Ozs7OztHQVVHO0FBQ0gsTUFBTSxVQUFVLFFBQVEsQ0FBQyxJQUFZLEVBQUUsTUFBOEIsRUFBRSxLQUFhO0lBQ2xGLGVBQWUsQ0FBQyxRQUFRLENBQUMsSUFBSSxFQUFFLE1BQU0sRUFBRSxLQUFLLENBQUMsQ0FBQztBQUNoRCxDQUFDO0FBRUQsU0FBUyxZQUFZLENBQUMsVUFBa0I7SUFDdEMsNERBQTREO0lBQzVELE9BQU8sVUFBVTtTQUNkLE9BQU8sQ0FBQyxJQUFJLEVBQUUsR0FBRyxDQUFDO1NBQ2xCLE9BQU8sQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxXQUFXLEVBQUUsQ0FBQyxDQUFDO0FBQzNDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBDb3B5cmlnaHQgMjAyNiBQaXBlbGluZSBCdWlsZGVyIENvbnRyaWJ1dG9yc1xuLy8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFwYWNoZS0yLjBcblxuaW1wb3J0IHsgcHJldmlvdXNTZWNyZXRTdGF0ZXMsIFNFQ1JFVF9ST1RBVElPTl9QUkVWSU9VU19HQVVHRSB9IGZyb20gJ0BwaXBlbGluZS1idWlsZGVyL2FwaS1jb3JlJztcbmltcG9ydCB7IENvbmZpZyB9IGZyb20gJ0BwaXBlbGluZS1idWlsZGVyL3BpcGVsaW5lLWNvcmUnO1xuaW1wb3J0IHR5cGUgeyBSZXF1ZXN0LCBSZXNwb25zZSwgTmV4dEZ1bmN0aW9uIH0gZnJvbSAnZXhwcmVzcyc7XG5pbXBvcnQgeyBSZWdpc3RyeSwgY29sbGVjdERlZmF1bHRNZXRyaWNzLCBDb3VudGVyLCBIaXN0b2dyYW0sIEdhdWdlIH0gZnJvbSAncHJvbS1jbGllbnQnO1xuXG5jb25zdCBTRVJWSUNFX05BTUUgPSAoQ29uZmlnLmdldEFueSgnb2JzZXJ2YWJpbGl0eScpIGFzIHsgc2VydmljZU5hbWU6IHN0cmluZyB9KS5zZXJ2aWNlTmFtZTtcblxuLyoqIFNoYXJlZCBQcm9tZXRoZXVzIHJlZ2lzdHJ5ICovXG5jb25zdCByZWdpc3RlciA9IG5ldyBSZWdpc3RyeSgpO1xuXG4vLyBTZXQgZGVmYXVsdCBsYWJlbHMgZm9yIGFsbCBtZXRyaWNzXG5yZWdpc3Rlci5zZXREZWZhdWx0TGFiZWxzKHsgc2VydmljZTogU0VSVklDRV9OQU1FIH0pO1xuXG4vLyBDb2xsZWN0IGRlZmF1bHQgTm9kZS5qcyBwcm9jZXNzIG1ldHJpY3MgKENQVSwgbWVtb3J5LCBoZWFwLCBldmVudCBsb29wIGxhZywgR0MpXG5jb2xsZWN0RGVmYXVsdE1ldHJpY3MoeyByZWdpc3RlciB9KTtcblxuLyoqXG4gKiBSZWdpc3RlciB0aGUgYHNlY3JldF9yb3RhdGlvbl9wcmV2aW91c19zZXR7c2VjcmV0fWAgZ2F1Z2Ugb24gYHJlZ2lzdHJ5YDogMVxuICogd2hpbGUgYSBzZWNyZXQncyBgKl9QUkVWSU9VU2Agcm90YXRpb24gdmFsdWUgaXMgc3RpbGwgc2V0LCAwIG90aGVyd2lzZS4gVGhlXG4gKiB2YWx1ZSBpcyByZWFkIGZyb20gYXBpLWNvcmUncyBwcm9iZSByZWdpc3RyeSBhdCBzY3JhcGUgdGltZSwgc28gaXQgYWx3YXlzXG4gKiByZWZsZWN0cyB0aGUgbGl2ZSBwcm9jZXNzLiBFeHBvcnRlZCBzbyBwbGF0Zm9ybSAob3duIHJlZ2lzdHJ5KSBleHBvc2VzIHRoZVxuICogaWRlbnRpY2FsIHNlcmllczsgdGhlIGBTZWNyZXRSb3RhdGlvblByZXZpb3VzTGluZ2VyaW5nYCBhbGVydCBrZXlzIG9uIGl0LlxuICovXG5leHBvcnQgZnVuY3Rpb24gcmVnaXN0ZXJTZWNyZXRSb3RhdGlvbkdhdWdlKHJlZ2lzdHJ5OiBSZWdpc3RyeSk6IEdhdWdlPCdzZWNyZXQnPiB7XG4gIHJldHVybiBuZXcgR2F1Z2Uoe1xuICAgIG5hbWU6IFNFQ1JFVF9ST1RBVElPTl9QUkVWSU9VU19HQVVHRSxcbiAgICBoZWxwOiAnMSB3aGlsZSBhIHNlY3JldCByb3RhdGlvbiBwcmV2aW91cyB2YWx1ZSAoZS5nLiBTRUNSRVRfRU5DUllQVElPTl9LRVlfUFJFVklPVVMpIG9yIGEgcmV0aXJpbmcgc2lnbmluZyBrZXkgaXMgc3RpbGwgYWNjZXB0ZWQ7IHNlZSBkb2NzL3J1bmJvb2tzL3NlY3JldC1yb3RhdGlvbi5tZCcsXG4gICAgbGFiZWxOYW1lczogWydzZWNyZXQnXSBhcyBjb25zdCxcbiAgICByZWdpc3RlcnM6IFtyZWdpc3RyeV0sXG4gICAgY29sbGVjdCgpIHtcbiAgICAgIGZvciAoY29uc3QgeyBzZWNyZXQsIHByZXZpb3VzU2V0IH0gb2YgcHJldmlvdXNTZWNyZXRTdGF0ZXMoKSkge1xuICAgICAgICB0aGlzLnNldCh7IHNlY3JldCB9LCBwcmV2aW91c1NldCA/IDEgOiAwKTtcbiAgICAgIH1cbiAgICB9LFxuICB9KTtcbn1cblxucmVnaXN0ZXJTZWNyZXRSb3RhdGlvbkdhdWdlKHJlZ2lzdGVyKTtcblxuLyoqIEhUVFAgcmVxdWVzdCBkdXJhdGlvbiBoaXN0b2dyYW0gKHNlY29uZHMpICovXG5jb25zdCBodHRwUmVxdWVzdER1cmF0aW9uID0gbmV3IEhpc3RvZ3JhbSh7XG4gIG5hbWU6ICdodHRwX3JlcXVlc3RfZHVyYXRpb25fc2Vjb25kcycsXG4gIGhlbHA6ICdEdXJhdGlvbiBvZiBIVFRQIHJlcXVlc3RzIGluIHNlY29uZHMnLFxuICBsYWJlbE5hbWVzOiBbJ21ldGhvZCcsICdyb3V0ZScsICdzdGF0dXNfY29kZSddIGFzIGNvbnN0LFxuICBidWNrZXRzOiBbMC4wMDUsIDAuMDEsIDAuMDI1LCAwLjA1LCAwLjEsIDAuMjUsIDAuNSwgMSwgMi41LCA1LCAxMF0sXG4gIHJlZ2lzdGVyczogW3JlZ2lzdGVyXSxcbn0pO1xuXG4vKiogSFRUUCByZXF1ZXN0IGNvdW50ZXIgKi9cbmNvbnN0IGh0dHBSZXF1ZXN0c1RvdGFsID0gbmV3IENvdW50ZXIoe1xuICBuYW1lOiAnaHR0cF9yZXF1ZXN0c190b3RhbCcsXG4gIGhlbHA6ICdUb3RhbCBudW1iZXIgb2YgSFRUUCByZXF1ZXN0cycsXG4gIGxhYmVsTmFtZXM6IFsnbWV0aG9kJywgJ3JvdXRlJywgJ3N0YXR1c19jb2RlJ10gYXMgY29uc3QsXG4gIHJlZ2lzdGVyczogW3JlZ2lzdGVyXSxcbn0pO1xuXG4vKipcbiAqIFBlci1vcmcgSFRUUCByZXF1ZXN0IGNvdW50ZXIg4oCUIFNBTVBMRUQgdG8ga2VlcCBQcm9tZXRoZXVzIGNhcmRpbmFsaXR5XG4gKiB1bmRlciBjb250cm9sLiBDYXJkaW5hbGl0eSBvZiBgb3JnX2lkICogbWV0aG9kICogcm91dGUgKiBzdGF0dXNfY29kZWBcbiAqIGdyb3dzIG11bHRpcGxpY2F0aXZlbHk7IHdpdGggTiBvcmdzICogNTAgcm91dGVzICogNSBzdGF0dXNfY29kZXMgdGhhdCdzXG4gKiAyNTDDl04gc2VyaWVzLiBXZSBzYW1wbGUgMS1pbi1OIHJlcXVlc3RzIChjb25maWd1cmFibGUgdmlhXG4gKiBgSFRUUF9NRVRSSUNTX09SR19TQU1QTEVfUkFURWAsIGRlZmF1bHQgMCA9IG9mZikuXG4gKlxuICogT3BlcmF0b3JzIGFuc3dlciBcIndoYXQncyBvcmcgWCdzIHA5OT9cIiB2aWEgc2VwYXJhdGUgcGVyLW9yZyBoaXN0b2dyYW1zXG4gKiBzY3JhcGVkIGF0IGEgbG93ZXIgcmF0ZSwgT1IgdmlhIExva2kgTG9nUUwgcXVlcmllcyBhZ2FpbnN0IHRoZVxuICogdW5zYW1wbGVkIGFjY2Vzcy1sb2cgc3RyZWFtLiBUaGlzIGNvdW50ZXIgaXMgdGhlIGZhc3QtcGF0aCBcIm5vaXN5XG4gKiBuZWlnaGJvciBkZXRlY3Rpb25cIiDigJQgb3BlcmF0b3JzIGFsZXJ0IHdoZW4gb25lIG9yZydzIHJlcXVlc3QgcmF0ZVxuICogZGV2aWF0ZXMgZnJvbSB0aGUgZmxlZXQgbWVkaWFuLlxuICpcbiAqIE5PVCBhIGhpc3RvZ3JhbTogaGlzdG9ncmFtIGxhYmVsIGNhcmRpbmFsaXR5IGlzIGV2ZW4gbW9yZSBzZW5zaXRpdmVcbiAqIChlYWNoIGJ1Y2tldCBpcyBhIHNlcGFyYXRlIHNlcmllcykuIElmIHBlci1vcmcgbGF0ZW5jeSBwZXJjZW50aWxlcyBhcmVcbiAqIG5lZWRlZCBsYXRlciwgYWRkIGEgc2VwYXJhdGUgaGlzdG9ncmFtIHdpdGggYSBjb2Fyc2VyIGJ1Y2tldCBzZXQgYW5kXG4gKiBsb3dlciBzYW1wbGUgcmF0ZS5cbiAqL1xuY29uc3QgaHR0cFJlcXVlc3RzQnlPcmdUb3RhbCA9IG5ldyBDb3VudGVyKHtcbiAgbmFtZTogJ2h0dHBfcmVxdWVzdHNfYnlfb3JnX3RvdGFsJyxcbiAgaGVscDogJ1NhbXBsZWQgcGVyLW9yZyBIVFRQIHJlcXVlc3QgY291bnQgKHNhbXBsZSByYXRlIHZpYSBIVFRQX01FVFJJQ1NfT1JHX1NBTVBMRV9SQVRFKScsXG4gIGxhYmVsTmFtZXM6IFsnbWV0aG9kJywgJ3JvdXRlJywgJ3N0YXR1c19jb2RlJywgJ29yZ19pZCddIGFzIGNvbnN0LFxuICByZWdpc3RlcnM6IFtyZWdpc3Rlcl0sXG59KTtcblxuLyoqXG4gKiBTYW1wbGUgcmF0ZSBmb3IgdGhlIHBlci1vcmcgY291bnRlci4gMS4wID0gZXZlcnkgcmVxdWVzdCwgMC4wID0gZGlzYWJsZWQuXG4gKiBQYXJzZWQgb25jZSBhdCBtb2R1bGUgbG9hZCDigJQgb3BlcmF0b3JzIHR1bmUgYnkgcmVzdGFydGluZyB0aGUgc2VydmljZS5cbiAqXG4gKiBEZWZhdWx0cyB0byAwIChPRkYpLiBgb3JnX2lkYCBpcyBhbiBVTkJPVU5ERUQsIHRlbmFudC1pZGVudGlmeWluZyBsYWJlbCBhbmRcbiAqIHByb20tY2xpZW50IGNvdW50ZXJzIG5ldmVyIGV4cGlyZSwgc28gYXQgMS4wIGV2ZXJ5IHNlcnZpY2UgYWNjdW11bGF0ZXMgYVxuICogc2VyaWVzIHBlciAob3JnIMOXIHJvdXRlIMOXIHN0YXR1cykgZm9yIHRoZSBwcm9jZXNzIGxpZmV0aW1lLCBhbmQgYC9tZXRyaWNzYCDigJRcbiAqIHdoaWNoIGlzIG5vdCBhdXRoLWdhdGVkIOKAlCBlbnVtZXJhdGVzIGV2ZXJ5IHRlbmFudCBpZCBhbG9uZyB3aXRoIGl0cyByZXF1ZXN0XG4gKiB2b2x1bWUgYW5kIGVycm9yIHJhdGUgdG8gYW55b25lIHdobyBjYW4gcmVhY2ggdGhlIHBvcnQuXG4gKlxuICogVHVybiBpdCBvbiBkZWxpYmVyYXRlbHkgKGFuZCBpZGVhbGx5IHdpdGggYSBzYW1wbGUgcmF0ZSB3ZWxsIHVuZGVyIDEuMCwgcGx1c1xuICogYE1FVFJJQ1NfU0NSQVBFX1RPS0VOYCBzZXQpIHdoZW4geW91IGFjdHVhbGx5IHdhbnQgcGVyLW9yZyBub2lzeS1uZWlnaGJvdXJcbiAqIGRldGVjdGlvbiBmcm9tIG1ldHJpY3MgcmF0aGVyIHRoYW4gZnJvbSB0aGUgYWNjZXNzLWxvZyBzdHJlYW0uXG4gKi9cbmNvbnN0IE9SR19TQU1QTEVfUkFURSA9ICgoKSA9PiB7XG4gIGNvbnN0IHJhdyA9IHByb2Nlc3MuZW52LkhUVFBfTUVUUklDU19PUkdfU0FNUExFX1JBVEU7XG4gIGlmIChyYXcgPT09IHVuZGVmaW5lZCB8fCByYXcgPT09ICcnKSByZXR1cm4gMDtcbiAgY29uc3QgcGFyc2VkID0gcGFyc2VGbG9hdChyYXcpO1xuICBpZiAoTnVtYmVyLmlzTmFOKHBhcnNlZCkgfHwgcGFyc2VkIDwgMCB8fCBwYXJzZWQgPiAxKSByZXR1cm4gMDtcbiAgcmV0dXJuIHBhcnNlZDtcbn0pKCk7XG5cbi8qKlxuICogTm9ybWFsaXplIGFuIEV4cHJlc3Mgcm91dGUgcGF0aCB0byBwcmV2ZW50IGxhYmVsIGNhcmRpbmFsaXR5IGV4cGxvc2lvbi5cbiAqXG4gKiBVc2VzIEV4cHJlc3MncyBtYXRjaGVkIHJvdXRlIHBhdHRlcm4gKGUuZy4gYC9wbHVnaW5zLzppZGApIHdoZW4gYXZhaWxhYmxlLFxuICogb3RoZXJ3aXNlIGZhbGxzIGJhY2sgdG8gdGhlIHJhdyBwYXRoIHdpdGggVVVJRC9udW1lcmljIHNlZ21lbnRzIHJlcGxhY2VkLlxuICovXG5mdW5jdGlvbiBub3JtYWxpemVSb3V0ZShyZXE6IFJlcXVlc3QpOiBzdHJpbmcge1xuICAvLyBQcmVmZXIgRXhwcmVzcyBtYXRjaGVkIHJvdXRlIHBhdHRlcm5cbiAgaWYgKHJlcS5yb3V0ZT8ucGF0aCkge1xuICAgIHJldHVybiByZXEuYmFzZVVybCArIHJlcS5yb3V0ZS5wYXRoO1xuICB9XG5cbiAgLy8gRmFsbGJhY2s6IHJlcGxhY2UgVVVJRHMgYW5kIG51bWVyaWMgSURzIHdpdGggOmlkXG4gIHJldHVybiByZXEucGF0aFxuICAgIC5yZXBsYWNlKC9bMC05YS1mXXs4fS1bMC05YS1mXXs0fS1bMC05YS1mXXs0fS1bMC05YS1mXXs0fS1bMC05YS1mXXsxMn0vZ2ksICc6aWQnKVxuICAgIC5yZXBsYWNlKC9cXC9cXGQrKD89XFwvfCQpL2csICcvOmlkJyk7XG59XG5cbi8qKlxuICogRXhwcmVzcyBtaWRkbGV3YXJlIHRoYXQgcmVjb3JkcyByZXF1ZXN0IGR1cmF0aW9uIGFuZCBjb3VudC5cbiAqXG4gKiBNdXN0IGJlIHJlZ2lzdGVyZWQgYmVmb3JlIHJvdXRlIGhhbmRsZXJzIHNvIGByZXMub24oJ2ZpbmlzaCcpYCBmaXJlc1xuICogYWZ0ZXIgdGhlIHJlc3BvbnNlIGlzIHNlbnQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBtZXRyaWNzTWlkZGxld2FyZSgpIHtcbiAgcmV0dXJuIChyZXE6IFJlcXVlc3QsIHJlczogUmVzcG9uc2UsIG5leHQ6IE5leHRGdW5jdGlvbik6IHZvaWQgPT4ge1xuICAgIC8vIE5PVEU6IG5vIC9tZXRyaWNzIG9yIC9oZWFsdGggc2tpcCBuZWVkZWQgaGVyZSDigJQgYm90aCBlbmRwb2ludHMgYXJlXG4gICAgLy8gcmVnaXN0ZXJlZCBpbiBhcHAtZmFjdG9yeSBCRUZPUkUgdGhpcyBtaWRkbGV3YXJlIChjcmVhdGVIZWFsdGhSb3V0ZXIgYW5kXG4gICAgLy8gYXBwLmdldCgnL21ldHJpY3MnKSBib3RoIHRlcm1pbmF0ZSB0aGUgcmVzcG9uc2UpLCBzbyBuZWl0aGVyIGV2ZXIgcmVhY2hlc1xuICAgIC8vIHRoaXMgaGFuZGxlci5cbiAgICBjb25zdCBlbmQgPSBodHRwUmVxdWVzdER1cmF0aW9uLnN0YXJ0VGltZXIoKTtcblxuICAgIHJlcy5vbignZmluaXNoJywgKCkgPT4ge1xuICAgICAgY29uc3Qgcm91dGUgPSBub3JtYWxpemVSb3V0ZShyZXEpO1xuICAgICAgY29uc3QgbGFiZWxzID0ge1xuICAgICAgICBtZXRob2Q6IHJlcS5tZXRob2QsXG4gICAgICAgIHJvdXRlLFxuICAgICAgICBzdGF0dXNfY29kZTogU3RyaW5nKHJlcy5zdGF0dXNDb2RlKSxcbiAgICAgIH07XG5cbiAgICAgIGVuZChsYWJlbHMpO1xuICAgICAgaHR0cFJlcXVlc3RzVG90YWwuaW5jKGxhYmVscyk7XG5cbiAgICAgIC8vIFBlci1vcmcgc2FtcGxlZCBjb3VudGVyLiBTa2lwIHdoZW46XG4gICAgICAvLyAgIC0gbm8gb3JnIGNvbnRleHQgb24gdGhlIHJlcXVlc3QgKGFub255bW91cyAvIGhlYWx0aCBlbmRwb2ludHMpXG4gICAgICAvLyAgIC0gc2FtcGxlIHJhdGUgaXMgMCAoZGlzYWJsZWQpXG4gICAgICAvLyAgIC0gZGljZSByb2xsIGZhaWxzXG4gICAgICAvLyBVc2luZyBNYXRoLnJhbmRvbSBmb3IgdGhlIHNhbXBsZXIg4oCUIGZvciB1bmJpYXNlZCBsb3ctcmF0ZSBzYW1wbGluZ1xuICAgICAgLy8gYSBkZXRlcm1pbmlzdGljIHBlci1yZXF1ZXN0IGhhc2ggd291bGQgYmUgbW9yZSB1bmlmb3JtLCBidXQgYXQgdGhlXG4gICAgICAvLyBkZWZhdWx0IHJhdGUgb2YgMS4wIGV2ZXJ5IHJlcXVlc3QgbGFuZHMgc28gdGhpcyBpcyBmaW5lLlxuICAgICAgY29uc3Qgb3JnSWQgPSByZXEudXNlcj8ub3JnYW5pemF0aW9uSWQ7XG4gICAgICBpZiAob3JnSWQgJiYgT1JHX1NBTVBMRV9SQVRFID4gMCAmJiBNYXRoLnJhbmRvbSgpIDwgT1JHX1NBTVBMRV9SQVRFKSB7XG4gICAgICAgIGh0dHBSZXF1ZXN0c0J5T3JnVG90YWwuaW5jKHsgLi4ubGFiZWxzLCBvcmdfaWQ6IG9yZ0lkIH0pO1xuICAgICAgfVxuICAgIH0pO1xuXG4gICAgbmV4dCgpO1xuICB9O1xufVxuXG4vKipcbiAqIEV4cHJlc3MgaGFuZGxlciB0aGF0IHJldHVybnMgUHJvbWV0aGV1cyBtZXRyaWNzIGluIHRleHQgZXhwb3NpdGlvbiBmb3JtYXQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBtZXRyaWNzSGFuZGxlcigpIHtcbiAgcmV0dXJuIGFzeW5jIChfcmVxOiBSZXF1ZXN0LCByZXM6IFJlc3BvbnNlKTogUHJvbWlzZTx2b2lkPiA9PiB7XG4gICAgcmVzLnNldCgnQ29udGVudC1UeXBlJywgcmVnaXN0ZXIuY29udGVudFR5cGUpO1xuICAgIHJlcy5lbmQoYXdhaXQgcmVnaXN0ZXIubWV0cmljcygpKTtcbiAgfTtcbn1cblxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4vLyBCdXNpbmVzcyAvIGRvbWFpbiBtZXRyaWNzXG4vL1xuLy8gU2VydmljZXMgc2hvdWxkIGVtaXQgY291bnRlcnMgZm9yIHRoZSB0aGluZ3Mgb3BlcmF0b3JzIGFjdHVhbGx5IGNhcmUgYWJvdXRcbi8vIChwaXBlbGluZXMgZ2VuZXJhdGVkLCBwbHVnaW4gYnVpbGRzIGNvbXBsZXRlZCwgY29tcGxpYW5jZSB2aW9sYXRpb25zLFxuLy8gQUkgdG9rZW5zIGNvbnN1bWVkKSDigJQgbm90IGp1c3QgSFRUUCB0cmFmZmljLiBUaGUgaGVscGVycyBiZWxvdyByZWdpc3RlclxuLy8gY291bnRlcnMgbGF6aWx5IG9uIHRoZSBzaGFyZWQgcmVnaXN0cnkgc28gbXVsdGlwbGUgc2VydmljZXMgY2FuIGNhbGxcbi8vIGBpbmNDb3VudGVyKCdwbHVnaW5fYnVpbGRzX3RvdGFsJywgeyBzdGF0dXM6ICdjb21wbGV0ZWQnIH0pYCB3aXRob3V0XG4vLyB3b3JyeWluZyBhYm91dCBkb3VibGUtcmVnaXN0cmF0aW9uLlxuLy9cbi8vIE5hbWluZyBjb252ZW50aW9uOiBgPGRvbWFpbj5fPG5vdW4+X3RvdGFsYCBmb3IgY291bnRlcnMsIGBfc2Vjb25kc2AgZm9yXG4vLyBoaXN0b2dyYW1zIOKAlCBtYXRjaGVzIFByb21ldGhldXMgYmVzdC1wcmFjdGljZS5cbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG4vKiogVGhlIGxhenkgYnVzaW5lc3MtbWV0cmljIGhlbHBlcnMsIGJvdW5kIHRvIG9uZSByZWdpc3RyeS4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgTWV0cmljSGVscGVycyB7XG4gIGluY0NvdW50ZXIobmFtZTogc3RyaW5nLCBsYWJlbHM/OiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+LCB2YWx1ZT86IG51bWJlcik6IHZvaWQ7XG4gIG9ic2VydmUobmFtZTogc3RyaW5nLCBsYWJlbHM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4sIHZhbHVlOiBudW1iZXIpOiB2b2lkO1xuICBzZXRHYXVnZShuYW1lOiBzdHJpbmcsIGxhYmVsczogUmVjb3JkPHN0cmluZywgc3RyaW5nPiwgdmFsdWU6IG51bWJlcik6IHZvaWQ7XG59XG5cbi8qKlxuICogQnVpbGQgYGluY0NvdW50ZXJgIC8gYG9ic2VydmVgIC8gYHNldEdhdWdlYCBvdmVyIGEgY2FsbGVyLXN1cHBsaWVkIHJlZ2lzdHJ5LlxuICpcbiAqIFRIRSBvbmUgaW1wbGVtZW50YXRpb24gb2YgdGhlIGxhenkgY291bnRlci9oaXN0b2dyYW0vZ2F1Z2UgbWFwcy4gYXBpLXNlcnZlcidzXG4gKiBvd24gZXhwb3J0cyBiZWxvdyBhcmUgdGhpcyBmYWN0b3J5IG92ZXIgaXRzIG1vZHVsZS1sZXZlbCBgcmVnaXN0ZXJgOyB0aGVcbiAqIHBsYXRmb3JtIHNlcnZpY2Ug4oCUIHdoaWNoIHJ1bnMgaXRzIG93biBFeHByZXNzIHNldHVwIGluc3RlYWQgb2YgYGNyZWF0ZUFwcGAsXG4gKiBhbmQgdGhlcmVmb3JlIG93bnMgYSBkaWZmZXJlbnQgcmVnaXN0cnkg4oCUIGJ1aWxkcyB0aGUgaWRlbnRpY2FsIGhlbHBlcnMgb3ZlclxuICogaXRzIG93bi4gV2l0aG91dCB0aGUgZmFjdG9yeSB0aGUgdHdvIGRyaWZ0OiB0aGV5IGRpZmZlciB0b2RheSBvbmx5IGluIHRoZVxuICogaGlzdG9ncmFtIGJ1Y2tldHMsIHdoaWNoIGlzIGV4YWN0bHkgdGhlIGtpbmQgb2YgZGlmZmVyZW5jZSBub2JvZHkgbm90aWNlc1xuICogdW50aWwgYSBkYXNoYm9hcmQgcmVhZHMgd3Jvbmcgb24gb25lIHNlcnZpY2UuXG4gKlxuICogYHJlZ2lzdHJ5YCBtYXkgYmUgYSB0aHVuaywgZm9yIGEgcmVnaXN0cnkgdGhhdCBpcyBpbmplY3RlZCBhZnRlciBtb2R1bGUgbG9hZFxuICogKHBsYXRmb3JtIHdpcmVzIGl0cyBvd24gb24gYXBwIGJvb3QpLiBUaGUgdGh1bmsgaXMgY2FsbGVkIG9uIHRoZSBGSVJTVCB1c2Ugb2ZcbiAqIGVhY2ggbWV0cmljIG5hbWUsIG5ldmVyIGF0IGltcG9ydCB0aW1lLCBzbyBidWlsZGluZyB0aGUgaGVscGVycyBoYXMgbm8gc2lkZVxuICogZWZmZWN0IG9mIGl0cyBvd24uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVNZXRyaWNIZWxwZXJzKHJlZ2lzdHJ5OiBSZWdpc3RyeSB8ICgoKSA9PiBSZWdpc3RyeSkpOiBNZXRyaWNIZWxwZXJzIHtcbiAgY29uc3QgcmVnaXN0cnlPZiA9ICgpOiBSZWdpc3RyeSA9PiAodHlwZW9mIHJlZ2lzdHJ5ID09PSAnZnVuY3Rpb24nID8gcmVnaXN0cnkoKSA6IHJlZ2lzdHJ5KTtcbiAgY29uc3QgY291bnRlcnMgPSBuZXcgTWFwPHN0cmluZywgQ291bnRlcjxzdHJpbmc+PigpO1xuICBjb25zdCBoaXN0b2dyYW1zID0gbmV3IE1hcDxzdHJpbmcsIEhpc3RvZ3JhbTxzdHJpbmc+PigpO1xuICBjb25zdCBnYXVnZXMgPSBuZXcgTWFwPHN0cmluZywgR2F1Z2U8c3RyaW5nPj4oKTtcblxuICByZXR1cm4ge1xuICAgIGluY0NvdW50ZXIobmFtZSwgbGFiZWxzID0ge30sIHZhbHVlID0gMSkge1xuICAgICAgbGV0IGNvdW50ZXIgPSBjb3VudGVycy5nZXQobmFtZSk7XG4gICAgICBpZiAoIWNvdW50ZXIpIHtcbiAgICAgICAgY291bnRlciA9IG5ldyBDb3VudGVyKHtcbiAgICAgICAgICBuYW1lLFxuICAgICAgICAgIGhlbHA6IGh1bWFuaXplTmFtZShuYW1lKSxcbiAgICAgICAgICBsYWJlbE5hbWVzOiBPYmplY3Qua2V5cyhsYWJlbHMpLFxuICAgICAgICAgIHJlZ2lzdGVyczogW3JlZ2lzdHJ5T2YoKV0sXG4gICAgICAgIH0pO1xuICAgICAgICBjb3VudGVycy5zZXQobmFtZSwgY291bnRlcik7XG4gICAgICB9XG4gICAgICBjb3VudGVyLmluYyhsYWJlbHMsIHZhbHVlKTtcbiAgICB9LFxuXG4gICAgb2JzZXJ2ZShuYW1lLCBsYWJlbHMsIHZhbHVlKSB7XG4gICAgICBsZXQgaGlzdCA9IGhpc3RvZ3JhbXMuZ2V0KG5hbWUpO1xuICAgICAgaWYgKCFoaXN0KSB7XG4gICAgICAgIGhpc3QgPSBuZXcgSGlzdG9ncmFtKHtcbiAgICAgICAgICBuYW1lLFxuICAgICAgICAgIGhlbHA6IGh1bWFuaXplTmFtZShuYW1lKSxcbiAgICAgICAgICBsYWJlbE5hbWVzOiBPYmplY3Qua2V5cyhsYWJlbHMpLFxuICAgICAgICAgIC8vIERlZmF1bHQgYnVja2V0cyB0YXJnZXQgc3ViLXNlY29uZCB0aHJvdWdoIHNldmVyYWwtbWludXRlIG9ic2VydmF0aW9ucy5cbiAgICAgICAgICAvLyBPdmVycmlkZSBieSByZWdpc3RlcmluZyB0aGUgaGlzdG9ncmFtIGV4cGxpY2l0bHkgYmVmb3JlIGZpcnN0IGNhbGxcbiAgICAgICAgICAvLyBpZiB5b3UgbmVlZCBhIGRpZmZlcmVudCBidWNrZXQgZGlzdHJpYnV0aW9uLlxuICAgICAgICAgIGJ1Y2tldHM6IFswLjA1LCAwLjEsIDAuMjUsIDAuNSwgMSwgMi41LCA1LCAxMCwgMzAsIDYwLCAxMjAsIDMwMF0sXG4gICAgICAgICAgcmVnaXN0ZXJzOiBbcmVnaXN0cnlPZigpXSxcbiAgICAgICAgfSk7XG4gICAgICAgIGhpc3RvZ3JhbXMuc2V0KG5hbWUsIGhpc3QpO1xuICAgICAgfVxuICAgICAgaGlzdC5vYnNlcnZlKGxhYmVscywgdmFsdWUpO1xuICAgIH0sXG5cbiAgICBzZXRHYXVnZShuYW1lLCBsYWJlbHMsIHZhbHVlKSB7XG4gICAgICBsZXQgZ2F1Z2UgPSBnYXVnZXMuZ2V0KG5hbWUpO1xuICAgICAgaWYgKCFnYXVnZSkge1xuICAgICAgICBnYXVnZSA9IG5ldyBHYXVnZSh7XG4gICAgICAgICAgbmFtZSxcbiAgICAgICAgICBoZWxwOiBodW1hbml6ZU5hbWUobmFtZSksXG4gICAgICAgICAgbGFiZWxOYW1lczogT2JqZWN0LmtleXMobGFiZWxzKSxcbiAgICAgICAgICByZWdpc3RlcnM6IFtyZWdpc3RyeU9mKCldLFxuICAgICAgICB9KTtcbiAgICAgICAgZ2F1Z2VzLnNldChuYW1lLCBnYXVnZSk7XG4gICAgICB9XG4gICAgICBnYXVnZS5zZXQobGFiZWxzLCB2YWx1ZSk7XG4gICAgfSxcbiAgfTtcbn1cblxuLyoqIFRoaXMgc2VydmljZSdzIG93biBoZWxwZXJzLCBvdmVyIHRoZSBzaGFyZWQgbW9kdWxlLWxldmVsIHJlZ2lzdHJ5LiAqL1xuY29uc3QgYnVzaW5lc3NNZXRyaWNzID0gY3JlYXRlTWV0cmljSGVscGVycyhyZWdpc3Rlcik7XG5cbi8qKlxuICogSW5jcmVtZW50IGEgYnVzaW5lc3MgY291bnRlciwgY3JlYXRpbmcgaXQgb24gZmlyc3QgdXNlLlxuICpcbiAqIEBleGFtcGxlXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiBpbmNDb3VudGVyKCdwaXBlbGluZXNfZ2VuZXJhdGVkX3RvdGFsJywgeyBwcm92aWRlcjogJ2FudGhyb3BpYycgfSk7XG4gKiBpbmNDb3VudGVyKCdwbHVnaW5fYnVpbGRzX3RvdGFsJywgeyBzdGF0dXM6ICdjb21wbGV0ZWQnIH0pO1xuICogaW5jQ291bnRlcigncXVvdGFfdGhyZXNob2xkX2Nyb3NzZWRfdG90YWwnLCB7IHR5cGU6ICdhaUNhbGxzJywgdGllcjogJ3BybycgfSk7XG4gKiBpbmNDb3VudGVyKCdjb21wbGlhbmNlX3Zpb2xhdGlvbnNfZm91bmRfdG90YWwnLCB7IHNldmVyaXR5OiAnY3JpdGljYWwnIH0pO1xuICogYGBgXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpbmNDb3VudGVyKG5hbWU6IHN0cmluZywgbGFiZWxzOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+ID0ge30sIHZhbHVlID0gMSk6IHZvaWQge1xuICBidXNpbmVzc01ldHJpY3MuaW5jQ291bnRlcihuYW1lLCBsYWJlbHMsIHZhbHVlKTtcbn1cblxuLyoqXG4gKiBSZWNvcmQgYW4gb2JzZXJ2YXRpb24gb24gYSBidXNpbmVzcyBoaXN0b2dyYW0sIGNyZWF0aW5nIGl0IG9uIGZpcnN0IHVzZS5cbiAqIFVzZSBmb3IgZHVyYXRpb25zLCBzaXplcywgYW55dGhpbmcgd2hlcmUgcGVyY2VudGlsZXMgbWF0dGVyLlxuICpcbiAqIEBleGFtcGxlXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiBvYnNlcnZlKCdhaV9nZW5lcmF0aW9uX2R1cmF0aW9uX3NlY29uZHMnLCB7IHByb3ZpZGVyOiAnYW50aHJvcGljJywgbW9kZWw6ICdzb25uZXQnIH0sIGR1cmF0aW9uU2VjKTtcbiAqIG9ic2VydmUoJ3BsdWdpbl9idWlsZF9kdXJhdGlvbl9zZWNvbmRzJywgeyBidWlsZFR5cGU6ICdkb2NrZXInIH0sIGR1cmF0aW9uU2VjKTtcbiAqIGBgYFxuICovXG5leHBvcnQgZnVuY3Rpb24gb2JzZXJ2ZShuYW1lOiBzdHJpbmcsIGxhYmVsczogUmVjb3JkPHN0cmluZywgc3RyaW5nPiwgdmFsdWU6IG51bWJlcik6IHZvaWQge1xuICBidXNpbmVzc01ldHJpY3Mub2JzZXJ2ZShuYW1lLCBsYWJlbHMsIHZhbHVlKTtcbn1cblxuLyoqXG4gKiBTZXQgdGhlIHZhbHVlIG9mIGEgYnVzaW5lc3MgZ2F1Z2UsIGNyZWF0aW5nIGl0IG9uIGZpcnN0IHVzZS4gVXNlIGZvclxuICogcG9pbnQtaW4tdGltZSBvYnNlcnZhdGlvbnMgc2FtcGxlZCBieSBhIHNjcmFwZXIg4oCUIHF1ZXVlIGRlcHRoLCBhY3RpdmVcbiAqIGNvbm5lY3Rpb24gY291bnRzLCBpbi1mbGlnaHQgcmVxdWVzdHMuXG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIHNldEdhdWdlKCdwbHVnaW5fcXVldWVfam9icycsIHsgcXVldWU6ICdwbHVnaW4tYnVpbGQnLCBzdGF0ZTogJ3dhaXRpbmcnIH0sIDEyKTtcbiAqIHNldEdhdWdlKCdwbHVnaW5fcXVldWVfam9icycsIHsgcXVldWU6ICdwbHVnaW4tYnVpbGQnLCBzdGF0ZTogJ2FjdGl2ZScgfSwgMyk7XG4gKiBgYGBcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNldEdhdWdlKG5hbWU6IHN0cmluZywgbGFiZWxzOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+LCB2YWx1ZTogbnVtYmVyKTogdm9pZCB7XG4gIGJ1c2luZXNzTWV0cmljcy5zZXRHYXVnZShuYW1lLCBsYWJlbHMsIHZhbHVlKTtcbn1cblxuZnVuY3Rpb24gaHVtYW5pemVOYW1lKG1ldHJpY05hbWU6IHN0cmluZyk6IHN0cmluZyB7XG4gIC8vIGBwaXBlbGluZXNfZ2VuZXJhdGVkX3RvdGFsYCDihpIgXCJQaXBlbGluZXMgZ2VuZXJhdGVkIHRvdGFsXCJcbiAgcmV0dXJuIG1ldHJpY05hbWVcbiAgICAucmVwbGFjZSgvXy9nLCAnICcpXG4gICAgLnJlcGxhY2UoL14uLywgKGMpID0+IGMudG9VcHBlckNhc2UoKSk7XG59XG4iXX0=
|
|
367
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWV0cmljcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9hcGkvbWV0cmljcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSwrQ0FBK0M7QUFDL0Msc0NBQXNDO0FBRXRDLE9BQU8sRUFBRSxvQkFBb0IsRUFBRSw4QkFBOEIsRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBQ2xHLE9BQU8sRUFBRSxNQUFNLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQztBQUV6RCxPQUFPLEVBQUUsUUFBUSxFQUFFLHFCQUFxQixFQUFFLE9BQU8sRUFBRSxTQUFTLEVBQUUsS0FBSyxFQUFFLE1BQU0sYUFBYSxDQUFDO0FBRXpGLE1BQU0sWUFBWSxHQUFJLE1BQU0sQ0FBQyxNQUFNLENBQUMsZUFBZSxDQUE2QixDQUFDLFdBQVcsQ0FBQztBQUU3RixpQ0FBaUM7QUFDakMsTUFBTSxRQUFRLEdBQUcsSUFBSSxRQUFRLEVBQUUsQ0FBQztBQUVoQyxxQ0FBcUM7QUFDckMsUUFBUSxDQUFDLGdCQUFnQixDQUFDLEVBQUUsT0FBTyxFQUFFLFlBQVksRUFBRSxDQUFDLENBQUM7QUFFckQsa0ZBQWtGO0FBQ2xGLHFCQUFxQixDQUFDLEVBQUUsUUFBUSxFQUFFLENBQUMsQ0FBQztBQUVwQzs7Ozs7O0dBTUc7QUFDSCxNQUFNLFVBQVUsMkJBQTJCLENBQUMsUUFBa0I7SUFDNUQsT0FBTyxJQUFJLEtBQUssQ0FBQztRQUNmLElBQUksRUFBRSw4QkFBOEI7UUFDcEMsSUFBSSxFQUFFLGtLQUFrSztRQUN4SyxVQUFVLEVBQUUsQ0FBQyxRQUFRLENBQVU7UUFDL0IsU0FBUyxFQUFFLENBQUMsUUFBUSxDQUFDO1FBQ3JCLE9BQU87WUFDTCxLQUFLLE1BQU0sRUFBRSxNQUFNLEVBQUUsV0FBVyxFQUFFLElBQUksb0JBQW9CLEVBQUUsRUFBRSxDQUFDO2dCQUM3RCxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsTUFBTSxFQUFFLEVBQUUsV0FBVyxDQUFDLENBQUMsQ0FBQyxD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LEtBQWE7SUFDbEYsZUFBZSxDQUFDLFFBQVEsQ0FBQyxJQUFJLEVBQUUsTUFBTSxFQUFFLEtBQUssQ0FBQyxDQUFDO0FBQ2hELENBQUM7QUFFRDs7Ozs7O0dBTUc7QUFDSCxNQUFNLFVBQVUsVUFBVSxDQUFDLElBQVk7SUFDckMsZUFBZSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsQ0FBQztBQUNuQyxDQUFDO0FBRUQsU0FBUyxZQUFZLENBQUMsVUFBa0I7SUFDdEMsZ0RBQWdEO0lBQ2hELE9BQU8sVUFBVTtTQUNkLE9BQU8sQ0FBQyxJQUFJLEVBQUUsR0FBRyxDQUFDO1NBQ2xCLE9BQU8sQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxXQUFXLEVBQUUsQ0FBQyxDQUFDO0FBQzNDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBDb3B5cmlnaHQgMjAyNiBQaXBlbGluZSBCdWlsZGVyIENvbnRyaWJ1dG9yc1xuLy8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFwYWNoZS0yLjBcblxuaW1wb3J0IHsgcHJldmlvdXNTZWNyZXRTdGF0ZXMsIFNFQ1JFVF9ST1RBVElPTl9QUkVWSU9VU19HQVVHRSB9IGZyb20gJ0BwaXBlbGluZS1idWlsZGVyL2FwaS1jb3JlJztcbmltcG9ydCB7IENvbmZpZyB9IGZyb20gJ0BwaXBlbGluZS1idWlsZGVyL3BpcGVsaW5lLWNvcmUnO1xuaW1wb3J0IHR5cGUgeyBSZXF1ZXN0LCBSZXNwb25zZSwgTmV4dEZ1bmN0aW9uIH0gZnJvbSAnZXhwcmVzcyc7XG5pbXBvcnQgeyBSZWdpc3RyeSwgY29sbGVjdERlZmF1bHRNZXRyaWNzLCBDb3VudGVyLCBIaXN0b2dyYW0sIEdhdWdlIH0gZnJvbSAncHJvbS1jbGllbnQnO1xuXG5jb25zdCBTRVJWSUNFX05BTUUgPSAoQ29uZmlnLmdldEFueSgnb2JzZXJ2YWJpbGl0eScpIGFzIHsgc2VydmljZU5hbWU6IHN0cmluZyB9KS5zZXJ2aWNlTmFtZTtcblxuLyoqIFNoYXJlZCBQcm9tZXRoZXVzIHJlZ2lzdHJ5ICovXG5jb25zdCByZWdpc3RlciA9IG5ldyBSZWdpc3RyeSgpO1xuXG4vLyBTZXQgZGVmYXVsdCBsYWJlbHMgZm9yIGFsbCBtZXRyaWNzXG5yZWdpc3Rlci5zZXREZWZhdWx0TGFiZWxzKHsgc2VydmljZTogU0VSVklDRV9OQU1FIH0pO1xuXG4vLyBDb2xsZWN0IGRlZmF1bHQgTm9kZS5qcyBwcm9jZXNzIG1ldHJpY3MgKENQVSwgbWVtb3J5LCBoZWFwLCBldmVudCBsb29wIGxhZywgR0MpXG5jb2xsZWN0RGVmYXVsdE1ldHJpY3MoeyByZWdpc3RlciB9KTtcblxuLyoqXG4gKiBSZWdpc3RlciB0aGUgYHNlY3JldF9yb3RhdGlvbl9wcmV2aW91c19zZXR7c2VjcmV0fWAgZ2F1Z2Ugb24gYHJlZ2lzdHJ5YDogMVxuICogd2hpbGUgYSBzZWNyZXQncyBgKl9QUkVWSU9VU2Agcm90YXRpb24gdmFsdWUgaXMgc3RpbGwgc2V0LCAwIG90aGVyd2lzZS4gVGhlXG4gKiB2YWx1ZSBpcyByZWFkIGZyb20gYXBpLWNvcmUncyBwcm9iZSByZWdpc3RyeSBhdCBzY3JhcGUgdGltZSwgc28gaXQgYWx3YXlzXG4gKiByZWZsZWN0cyB0aGUgbGl2ZSBwcm9jZXNzLiBFeHBvcnRlZCBzbyBwbGF0Zm9ybSAob3duIHJlZ2lzdHJ5KSBleHBvc2VzIHRoZVxuICogaWRlbnRpY2FsIHNlcmllczsgdGhlIGBTZWNyZXRSb3RhdGlvblByZXZpb3VzTGluZ2VyaW5nYCBhbGVydCBrZXlzIG9uIGl0LlxuICovXG5leHBvcnQgZnVuY3Rpb24gcmVnaXN0ZXJTZWNyZXRSb3RhdGlvbkdhdWdlKHJlZ2lzdHJ5OiBSZWdpc3RyeSk6IEdhdWdlPCdzZWNyZXQnPiB7XG4gIHJldHVybiBuZXcgR2F1Z2Uoe1xuICAgIG5hbWU6IFNFQ1JFVF9ST1RBVElPTl9QUkVWSU9VU19HQVVHRSxcbiAgICBoZWxwOiAnMSB3aGlsZSBhIHNlY3JldCByb3RhdGlvbiBwcmV2aW91cyB2YWx1ZSAoZS5nLiBTRUNSRVRfRU5DUllQVElPTl9LRVlfUFJFVklPVVMpIG9yIGEgcmV0aXJpbmcgc2lnbmluZyBrZXkgaXMgc3RpbGwgYWNjZXB0ZWQ7IHNlZSBkb2NzL3J1bmJvb2tzL3NlY3JldC1yb3RhdGlvbi5tZCcsXG4gICAgbGFiZWxOYW1lczogWydzZWNyZXQnXSBhcyBjb25zdCxcbiAgICByZWdpc3RlcnM6IFtyZWdpc3RyeV0sXG4gICAgY29sbGVjdCgpIHtcbiAgICAgIGZvciAoY29uc3QgeyBzZWNyZXQsIHByZXZpb3VzU2V0IH0gb2YgcHJldmlvdXNTZWNyZXRTdGF0ZXMoKSkge1xuICAgICAgICB0aGlzLnNldCh7IHNlY3JldCB9LCBwcmV2aW91c1NldCA/IDEgOiAwKTtcbiAgICAgIH1cbiAgICB9LFxuICB9KTtcbn1cblxucmVnaXN0ZXJTZWNyZXRSb3RhdGlvbkdhdWdlKHJlZ2lzdGVyKTtcblxuLyoqIEhUVFAgcmVxdWVzdCBkdXJhdGlvbiBoaXN0b2dyYW0gKHNlY29uZHMpICovXG5jb25zdCBodHRwUmVxdWVzdER1cmF0aW9uID0gbmV3IEhpc3RvZ3JhbSh7XG4gIG5hbWU6ICdodHRwX3JlcXVlc3RfZHVyYXRpb25fc2Vjb25kcycsXG4gIGhlbHA6ICdEdXJhdGlvbiBvZiBIVFRQIHJlcXVlc3RzIGluIHNlY29uZHMnLFxuICBsYWJlbE5hbWVzOiBbJ21ldGhvZCcsICdyb3V0ZScsICdzdGF0dXNfY29kZSddIGFzIGNvbnN0LFxuICBidWNrZXRzOiBbMC4wMDUsIDAuMDEsIDAuMDI1LCAwLjA1LCAwLjEsIDAuMjUsIDAuNSwgMSwgMi41LCA1LCAxMF0sXG4gIHJlZ2lzdGVyczogW3JlZ2lzdGVyXSxcbn0pO1xuXG4vKiogSFRUUCByZXF1ZXN0IGNvdW50ZXIgKi9cbmNvbnN0IGh0dHBSZXF1ZXN0c1RvdGFsID0gbmV3IENvdW50ZXIoe1xuICBuYW1lOiAnaHR0cF9yZXF1ZXN0c190b3RhbCcsXG4gIGhlbHA6ICdUb3RhbCBudW1iZXIgb2YgSFRUUCByZXF1ZXN0cycsXG4gIGxhYmVsTmFtZXM6IFsnbWV0aG9kJywgJ3JvdXRlJywgJ3N0YXR1c19jb2RlJ10gYXMgY29uc3QsXG4gIHJlZ2lzdGVyczogW3JlZ2lzdGVyXSxcbn0pO1xuXG4vKipcbiAqIFBlci1vcmcgSFRUUCByZXF1ZXN0IGNvdW50ZXIg4oCUIFNBTVBMRUQgdG8ga2VlcCBQcm9tZXRoZXVzIGNhcmRpbmFsaXR5XG4gKiB1bmRlciBjb250cm9sLiBDYXJkaW5hbGl0eSBvZiBgb3JnX2lkICogbWV0aG9kICogcm91dGUgKiBzdGF0dXNfY29kZWBcbiAqIGdyb3dzIG11bHRpcGxpY2F0aXZlbHk7IHdpdGggTiBvcmdzICogNTAgcm91dGVzICogNSBzdGF0dXNfY29kZXMgdGhhdCdzXG4gKiAyNTDDl04gc2VyaWVzLiBXZSBzYW1wbGUgMS1pbi1OIHJlcXVlc3RzIChjb25maWd1cmFibGUgdmlhXG4gKiBgSFRUUF9NRVRSSUNTX09SR19TQU1QTEVfUkFURWAsIGRlZmF1bHQgMCA9IG9mZikuXG4gKlxuICogT3BlcmF0b3JzIGFuc3dlciBcIndoYXQncyBvcmcgWCdzIHA5OT9cIiB2aWEgc2VwYXJhdGUgcGVyLW9yZyBoaXN0b2dyYW1zXG4gKiBzY3JhcGVkIGF0IGEgbG93ZXIgcmF0ZSwgT1IgdmlhIExva2kgTG9nUUwgcXVlcmllcyBhZ2FpbnN0IHRoZVxuICogdW5zYW1wbGVkIGFjY2Vzcy1sb2cgc3RyZWFtLiBUaGlzIGNvdW50ZXIgaXMgdGhlIGZhc3QtcGF0aCBcIm5vaXN5XG4gKiBuZWlnaGJvciBkZXRlY3Rpb25cIiDigJQgb3BlcmF0b3JzIGFsZXJ0IHdoZW4gb25lIG9yZydzIHJlcXVlc3QgcmF0ZVxuICogZGV2aWF0ZXMgZnJvbSB0aGUgZmxlZXQgbWVkaWFuLlxuICpcbiAqIE5PVCBhIGhpc3RvZ3JhbTogaGlzdG9ncmFtIGxhYmVsIGNhcmRpbmFsaXR5IGlzIGV2ZW4gbW9yZSBzZW5zaXRpdmVcbiAqIChlYWNoIGJ1Y2tldCBpcyBhIHNlcGFyYXRlIHNlcmllcykuIElmIHBlci1vcmcgbGF0ZW5jeSBwZXJjZW50aWxlcyBhcmVcbiAqIG5lZWRlZCBsYXRlciwgYWRkIGEgc2VwYXJhdGUgaGlzdG9ncmFtIHdpdGggYSBjb2Fyc2VyIGJ1Y2tldCBzZXQgYW5kXG4gKiBsb3dlciBzYW1wbGUgcmF0ZS5cbiAqL1xuY29uc3QgaHR0cFJlcXVlc3RzQnlPcmdUb3RhbCA9IG5ldyBDb3VudGVyKHtcbiAgbmFtZTogJ2h0dHBfcmVxdWVzdHNfYnlfb3JnX3RvdGFsJyxcbiAgaGVscDogJ1NhbXBsZWQgcGVyLW9yZyBIVFRQIHJlcXVlc3QgY291bnQgKHNhbXBsZSByYXRlIHZpYSBIVFRQX01FVFJJQ1NfT1JHX1NBTVBMRV9SQVRFKScsXG4gIGxhYmVsTmFtZXM6IFsnbWV0aG9kJywgJ3JvdXRlJywgJ3N0YXR1c19jb2RlJywgJ29yZ19pZCddIGFzIGNvbnN0LFxuICByZWdpc3RlcnM6IFtyZWdpc3Rlcl0sXG59KTtcblxuLyoqXG4gKiBTYW1wbGUgcmF0ZSBmb3IgdGhlIHBlci1vcmcgY291bnRlci4gMS4wID0gZXZlcnkgcmVxdWVzdCwgMC4wID0gZGlzYWJsZWQuXG4gKiBQYXJzZWQgb25jZSBhdCBtb2R1bGUgbG9hZCDigJQgb3BlcmF0b3JzIHR1bmUgYnkgcmVzdGFydGluZyB0aGUgc2VydmljZS5cbiAqXG4gKiBEZWZhdWx0cyB0byAwIChPRkYpLiBgb3JnX2lkYCBpcyBhbiBVTkJPVU5ERUQsIHRlbmFudC1pZGVudGlmeWluZyBsYWJlbCBhbmRcbiAqIHByb20tY2xpZW50IGNvdW50ZXJzIG5ldmVyIGV4cGlyZSwgc28gYXQgMS4wIGV2ZXJ5IHNlcnZpY2UgYWNjdW11bGF0ZXMgYVxuICogc2VyaWVzIHBlciAob3JnIMOXIHJvdXRlIMOXIHN0YXR1cykgZm9yIHRoZSBwcm9jZXNzIGxpZmV0aW1lLCBhbmQgYC9tZXRyaWNzYCDigJRcbiAqIHdoaWNoIGlzIG5vdCBhdXRoLWdhdGVkIOKAlCBlbnVtZXJhdGVzIGV2ZXJ5IHRlbmFudCBpZCBhbG9uZyB3aXRoIGl0cyByZXF1ZXN0XG4gKiB2b2x1bWUgYW5kIGVycm9yIHJhdGUgdG8gYW55b25lIHdobyBjYW4gcmVhY2ggdGhlIHBvcnQuXG4gKlxuICogVHVybiBpdCBvbiBkZWxpYmVyYXRlbHkgKGFuZCBpZGVhbGx5IHdpdGggYSBzYW1wbGUgcmF0ZSB3ZWxsIHVuZGVyIDEuMCwgcGx1c1xuICogYE1FVFJJQ1NfU0NSQVBFX1RPS0VOYCBzZXQpIHdoZW4geW91IGFjdHVhbGx5IHdhbnQgcGVyLW9yZyBub2lzeS1uZWlnaGJvdXJcbiAqIGRldGVjdGlvbiBmcm9tIG1ldHJpY3MgcmF0aGVyIHRoYW4gZnJvbSB0aGUgYWNjZXNzLWxvZyBzdHJlYW0uXG4gKi9cbmNvbnN0IE9SR19TQU1QTEVfUkFURSA9ICgoKSA9PiB7XG4gIGNvbnN0IHJhdyA9IHByb2Nlc3MuZW52LkhUVFBfTUVUUklDU19PUkdfU0FNUExFX1JBVEU7XG4gIGlmIChyYXcgPT09IHVuZGVmaW5lZCB8fCByYXcgPT09ICcnKSByZXR1cm4gMDtcbiAgY29uc3QgcGFyc2VkID0gcGFyc2VGbG9hdChyYXcpO1xuICBpZiAoTnVtYmVyLmlzTmFOKHBhcnNlZCkgfHwgcGFyc2VkIDwgMCB8fCBwYXJzZWQgPiAxKSByZXR1cm4gMDtcbiAgcmV0dXJuIHBhcnNlZDtcbn0pKCk7XG5cbi8qKlxuICogTm9ybWFsaXplIGFuIEV4cHJlc3Mgcm91dGUgcGF0aCB0byBwcmV2ZW50IGxhYmVsIGNhcmRpbmFsaXR5IGV4cGxvc2lvbi5cbiAqXG4gKiBVc2VzIEV4cHJlc3MncyBtYXRjaGVkIHJvdXRlIHBhdHRlcm4gKGUuZy4gYC9wbHVnaW5zLzppZGApIHdoZW4gYXZhaWxhYmxlLFxuICogb3RoZXJ3aXNlIGZhbGxzIGJhY2sgdG8gdGhlIHJhdyBwYXRoIHdpdGggVVVJRC9udW1lcmljIHNlZ21lbnRzIHJlcGxhY2VkLlxuICovXG5mdW5jdGlvbiBub3JtYWxpemVSb3V0ZShyZXE6IFJlcXVlc3QpOiBzdHJpbmcge1xuICAvLyBQcmVmZXIgRXhwcmVzcyBtYXRjaGVkIHJvdXRlIHBhdHRlcm5cbiAgaWYgKHJlcS5yb3V0ZT8ucGF0aCkge1xuICAgIHJldHVybiByZXEuYmFzZVVybCArIHJlcS5yb3V0ZS5wYXRoO1xuICB9XG5cbiAgLy8gRmFsbGJhY2s6IHJlcGxhY2UgVVVJRHMgYW5kIG51bWVyaWMgSURzIHdpdGggOmlkXG4gIHJldHVybiByZXEucGF0aFxuICAgIC5yZXBsYWNlKC9bMC05YS1mXXs4fS1bMC05YS1mXXs0fS1bMC05YS1mXXs0fS1bMC05YS1mXXs0fS1bMC05YS1mXXsxMn0vZ2ksICc6aWQnKVxuICAgIC5yZXBsYWNlKC9cXC9cXGQrKD89XFwvfCQpL2csICcvOmlkJyk7XG59XG5cbi8qKlxuICogRXhwcmVzcyBtaWRkbGV3YXJlIHRoYXQgcmVjb3JkcyByZXF1ZXN0IGR1cmF0aW9uIGFuZCBjb3VudC5cbiAqXG4gKiBNdXN0IGJlIHJlZ2lzdGVyZWQgYmVmb3JlIHJvdXRlIGhhbmRsZXJzIHNvIGByZXMub24oJ2ZpbmlzaCcpYCBmaXJlc1xuICogYWZ0ZXIgdGhlIHJlc3BvbnNlIGlzIHNlbnQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBtZXRyaWNzTWlkZGxld2FyZSgpIHtcbiAgcmV0dXJuIChyZXE6IFJlcXVlc3QsIHJlczogUmVzcG9uc2UsIG5leHQ6IE5leHRGdW5jdGlvbik6IHZvaWQgPT4ge1xuICAgIC8vIE5PVEU6IG5vIC9tZXRyaWNzIG9yIC9oZWFsdGggc2tpcCBuZWVkZWQgaGVyZSDigJQgYm90aCBlbmRwb2ludHMgYXJlXG4gICAgLy8gcmVnaXN0ZXJlZCBpbiBhcHAtZmFjdG9yeSBCRUZPUkUgdGhpcyBtaWRkbGV3YXJlIChjcmVhdGVIZWFsdGhSb3V0ZXIgYW5kXG4gICAgLy8gYXBwLmdldCgnL21ldHJpY3MnKSBib3RoIHRlcm1pbmF0ZSB0aGUgcmVzcG9uc2UpLCBzbyBuZWl0aGVyIGV2ZXIgcmVhY2hlc1xuICAgIC8vIHRoaXMgaGFuZGxlci5cbiAgICBjb25zdCBlbmQgPSBodHRwUmVxdWVzdER1cmF0aW9uLnN0YXJ0VGltZXIoKTtcblxuICAgIHJlcy5vbignZmluaXNoJywgKCkgPT4ge1xuICAgICAgY29uc3Qgcm91dGUgPSBub3JtYWxpemVSb3V0ZShyZXEpO1xuICAgICAgY29uc3QgbGFiZWxzID0ge1xuICAgICAgICBtZXRob2Q6IHJlcS5tZXRob2QsXG4gICAgICAgIHJvdXRlLFxuICAgICAgICBzdGF0dXNfY29kZTogU3RyaW5nKHJlcy5zdGF0dXNDb2RlKSxcbiAgICAgIH07XG5cbiAgICAgIGVuZChsYWJlbHMpO1xuICAgICAgaHR0cFJlcXVlc3RzVG90YWwuaW5jKGxhYmVscyk7XG5cbiAgICAgIC8vIFBlci1vcmcgc2FtcGxlZCBjb3VudGVyLiBTa2lwIHdoZW46XG4gICAgICAvLyAgIC0gbm8gb3JnIGNvbnRleHQgb24gdGhlIHJlcXVlc3QgKGFub255bW91cyAvIGhlYWx0aCBlbmRwb2ludHMpXG4gICAgICAvLyAgIC0gc2FtcGxlIHJhdGUgaXMgMCAoZGlzYWJsZWQpXG4gICAgICAvLyAgIC0gZGljZSByb2xsIGZhaWxzXG4gICAgICAvLyBVc2luZyBNYXRoLnJhbmRvbSBmb3IgdGhlIHNhbXBsZXIg4oCUIGZvciB1bmJpYXNlZCBsb3ctcmF0ZSBzYW1wbGluZ1xuICAgICAgLy8gYSBkZXRlcm1pbmlzdGljIHBlci1yZXF1ZXN0IGhhc2ggd291bGQgYmUgbW9yZSB1bmlmb3JtLCBidXQgYXQgdGhlXG4gICAgICAvLyBkZWZhdWx0IHJhdGUgb2YgMS4wIGV2ZXJ5IHJlcXVlc3QgbGFuZHMgc28gdGhpcyBpcyBmaW5lLlxuICAgICAgY29uc3Qgb3JnSWQgPSByZXEudXNlcj8ub3JnYW5pemF0aW9uSWQ7XG4gICAgICBpZiAob3JnSWQgJiYgT1JHX1NBTVBMRV9SQVRFID4gMCAmJiBNYXRoLnJhbmRvbSgpIDwgT1JHX1NBTVBMRV9SQVRFKSB7XG4gICAgICAgIGh0dHBSZXF1ZXN0c0J5T3JnVG90YWwuaW5jKHsgLi4ubGFiZWxzLCBvcmdfaWQ6IG9yZ0lkIH0pO1xuICAgICAgfVxuICAgIH0pO1xuXG4gICAgbmV4dCgpO1xuICB9O1xufVxuXG4vKipcbiAqIEV4cHJlc3MgaGFuZGxlciB0aGF0IHJldHVybnMgUHJvbWV0aGV1cyBtZXRyaWNzIGluIHRleHQgZXhwb3NpdGlvbiBmb3JtYXQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBtZXRyaWNzSGFuZGxlcigpIHtcbiAgcmV0dXJuIGFzeW5jIChfcmVxOiBSZXF1ZXN0LCByZXM6IFJlc3BvbnNlKTogUHJvbWlzZTx2b2lkPiA9PiB7XG4gICAgcmVzLnNldCgnQ29udGVudC1UeXBlJywgcmVnaXN0ZXIuY29udGVudFR5cGUpO1xuICAgIHJlcy5lbmQoYXdhaXQgcmVnaXN0ZXIubWV0cmljcygpKTtcbiAgfTtcbn1cblxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4vLyBCdXNpbmVzcyAvIGRvbWFpbiBtZXRyaWNzXG4vL1xuLy8gU2VydmljZXMgc2hvdWxkIGVtaXQgY291bnRlcnMgZm9yIHRoZSB0aGluZ3Mgb3BlcmF0b3JzIGFjdHVhbGx5IGNhcmUgYWJvdXRcbi8vIChwaXBlbGluZXMgZ2VuZXJhdGVkLCBwbHVnaW4gYnVpbGRzIGNvbXBsZXRlZCwgY29tcGxpYW5jZSB2aW9sYXRpb25zLFxuLy8gQUkgdG9rZW5zIGNvbnN1bWVkKSDigJQgbm90IGp1c3QgSFRUUCB0cmFmZmljLiBUaGUgaGVscGVycyBiZWxvdyByZWdpc3RlclxuLy8gY291bnRlcnMgbGF6aWx5IG9uIHRoZSBzaGFyZWQgcmVnaXN0cnkgc28gbXVsdGlwbGUgc2VydmljZXMgY2FuIGNhbGxcbi8vIGBpbmNDb3VudGVyKCdwbHVnaW5fYnVpbGRzX3RvdGFsJywgeyBzdGF0dXM6ICdjb21wbGV0ZWQnIH0pYCB3aXRob3V0XG4vLyB3b3JyeWluZyBhYm91dCBkb3VibGUtcmVnaXN0cmF0aW9uLlxuLy9cbi8vIE5hbWluZyBjb252ZW50aW9uOiBgPGRvbWFpbj5fPG5vdW4+X3RvdGFsYCBmb3IgY291bnRlcnMsIGBfc2Vjb25kc2AgZm9yXG4vLyBoaXN0b2dyYW1zIOKAlCBtYXRjaGVzIFByb21ldGhldXMgYmVzdC1wcmFjdGljZS5cbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG4vKipcbiAqIEJ1Y2tldCBkaXN0cmlidXRpb25zIGZvciBoaXN0b2dyYW1zIHdob3NlIG9ic2VydmF0aW9ucyBhcmUgbm93aGVyZSBuZWFyIHRoZVxuICogc3ViLXNlY29uZC10by1taW51dGVzIGRlZmF1bHQuXG4gKlxuICogVEhJUyBUQUJMRSBFWElTVFMgQkVDQVVTRSBUSEUgREVGQVVMVCBTSUxFTlRMWSBCUkVBS1MgQUxFUlRTLiBUaGUgZGVmYXVsdCBzZXRcbiAqIGJlbG93IGVuZHMgYXQgYSAzMDAtc2Vjb25kIGJ1Y2tldCwgYW5kIGBoaXN0b2dyYW1fcXVhbnRpbGVgIGNhbm5vdCBpbnRlcnBvbGF0ZVxuICogcGFzdCB0aGUgbGFzdCBGSU5JVEUgYm91bmRhcnkg4oCUIGV2ZXJ5dGhpbmcgYWJvdmUgaXQgbGFuZHMgaW4gYCtJbmZgIGFuZCB0aGVcbiAqIHF1YW50aWxlIHJlYWRzIGJhY2sgYXMgMzAwIGZvcmV2ZXIuIEFuIGFsZXJ0IG9mIHRoZSBmb3JtIGA+IDMwMGAgb24gc3VjaCBhXG4gKiBoaXN0b2dyYW0gY2FuIHRoZXJlZm9yZSBuZXZlciBmaXJlLCBhbmQgYSBwOTAgcGFuZWwgZmxhdC1saW5lcyBhdCBmaXZlXG4gKiBtaW51dGVzIGhvd2V2ZXIgYmFkIHRoaW5ncyBnZXQuIE5vdGhpbmcgZXJyb3JzLCBub3RoaW5nIGlzIG1pc3NpbmcgZnJvbSB0aGVcbiAqIHNjcmFwZSwgYW5kIHRoZSBkYXNoYm9hcmQgbG9va3MgaGVhbHRoeTogdGhlIG9ubHkgc3ltcHRvbSBpcyBhbiBhbGVydCB0aGF0XG4gKiBzdGF5cyBxdWlldCB0aHJvdWdoIGFuIG91dGFnZS4gYHN1cHBvcnRfZmlyc3RfcmVzcG9uc2Vfc2Vjb25kc2AgbWVhc3VyZXMgaG91cnNcbiAqIHRvIGRheXMgYW5kIGhhZCBhIHRocmVzaG9sZCBvZiB0d2VsdmUgaG91cnMgc2l0dGluZyBhYm92ZSBhIGNlaWxpbmcgb2YgZml2ZVxuICogbWludXRlcy5cbiAqXG4gKiBTbyBhIGhpc3RvZ3JhbSB3aG9zZSBuYXR1cmFsIHJhbmdlIGlzIG1pbnV0ZXMtdG8tZGF5cyBkZWNsYXJlcyBpdHMgYnVja2V0c1xuICogaGVyZSwgYW5kIEFMRVJUIFRIUkVTSE9MRFMgQVJFIFBVVCBPTiBCT1VOREFSSUVTOiBhIHRocmVzaG9sZCBpbnNpZGUgYSB3aWRlXG4gKiBidWNrZXQgaXMgc2VydmVkIGJ5IGxpbmVhciBpbnRlcnBvbGF0aW9uIGFjcm9zcyB0aGF0IGJ1Y2tldCwgd2hpY2ggaXMgYSBndWVzcyxcbiAqIHdoaWxlIGEgdGhyZXNob2xkIE9OIGEgYm91bmRhcnkgaXMgZXhhY3QuIEZvciBzdXBwb3J0IHRoYXQgbWVhbnMgNmggKHRoZSBhbGVydClcbiAqIGFuZCA4aCAodGhlIHNvbGQgdGFyZ2V0KSBhcmUgYm90aCBib3VuZGFyaWVzLCAyNGggaXMgdGhlIG9wZXJhdGlvbmFsIGd1YXJkXG4gKiBmcm9tIHRoZSBzdGFuZGFyZC9wcmlvcml0eSBydWxlLCBhbmQgOTZoIGNvdmVycyB0aGUgbG9uZ2VzdCBsZWdpdGltYXRlIHdhaXQgYVxuICogYnVzaW5lc3MtZGF5IHRhcmdldCBhbGxvd3Mg4oCUIGEgcHJpb3JpdHkgY2FzZSByYWlzZWQgYXQgMTc6MDEgb24gYSBGcmlkYXkuXG4gKlxuICogQWRkIGEgbWV0cmljIGhlcmUgd2hlbiBpdHMgb2JzZXJ2YXRpb25zIGNhbiBleGNlZWQgZml2ZSBtaW51dGVzLiBUaGUgdGFibGUgaXNcbiAqIHJlYWQgb24gRklSU1QgVVNFIG9mIGVhY2ggbmFtZSBieSBgY3JlYXRlTWV0cmljSGVscGVyc2AsIHNvIGJvdGggcmVnaXN0cmllc1xuICogKGFwaS1zZXJ2ZXIncyBhbmQgcGxhdGZvcm0ncyBvd24pIGdldCB0aGUgc2FtZSBkaXN0cmlidXRpb24sIHdoaWNoIGlzIHRoZVxuICogZHJpZnQgdGhlIGZhY3RvcnkgZXhpc3RzIHRvIHByZXZlbnQuXG4gKi9cbmNvbnN0IEhJU1RPR1JBTV9CVUNLRVRTOiBSZWFkb25seTxSZWNvcmQ8c3RyaW5nLCByZWFkb25seSBudW1iZXJbXT4+ID0ge1xuICAvLyAxNW0sIDFoLCAyaCwgNGgsIDZoLCA4aCwgMTJoLCAyNGgsIDQ4aCwgOTZoLlxuICBzdXBwb3J0X2ZpcnN0X3Jlc3BvbnNlX3NlY29uZHM6IFs5MDAsIDM2MDAsIDcyMDAsIDE0NDAwLCAyMTYwMCwgMjg4MDAsIDQzMjAwLCA4NjQwMCwgMTcyODAwLCAzNDU2MDBdLFxuICAvLyBTdWJtaXNzaW9uLXRvLWRlY2lzaW9uIGxhdGVuY3kgaXMgYSBodW1hbiByZXZpZXcgcXVldWU6IGhvdXJzIHRvIGRheXMuXG4gIC8vIDE1bSwgMWgsIDRoLCAxMmgsIDFkLCAyZCwgNGQsIDdkLCAxNGQuXG4gIGVjb3N5c3RlbV9kZWNpc2lvbl9sYXRlbmN5X3NlY29uZHM6IFs5MDAsIDM2MDAsIDE0NDAwLCA0MzIwMCwgODY0MDAsIDE3MjgwMCwgMzQ1NjAwLCA2MDQ4MDAsIDEyMDk2MDBdLFxuICAvLyBRdWV1ZSB3YWl0LiBgUGx1Z2luUXVldWVQcm9jZXNzaW5nU2xvd2AgYXNzZXJ0cyBwOTUgPiAzMDAsIHdoaWNoIHRoZSBkZWZhdWx0XG4gIC8vIGNlaWxpbmcgb2YgMzAwIG1hZGUgdW5maXJlYWJsZTsgMzAwIGlzIGEgYm91bmRhcnkgaGVyZSBzbyB0aGUgY29tcGFyaXNvbiBpc1xuICAvLyBleGFjdCByYXRoZXIgdGhhbiBpbnRlcnBvbGF0ZWQuXG4gIHBsdWdpbl9qb2Jfd2FpdF9zZWNvbmRzOiBbMSwgNSwgMTUsIDMwLCA2MCwgMTIwLCAzMDAsIDYwMCwgMTgwMCwgMzYwMF0sXG4gIC8vIEEgY29udGFpbmVyIGJ1aWxkLiBNaW51dGVzIG5vcm1hbGx5LCBmYXIgbG9uZ2VyIGZvciBhIGNvbGQgYmFzZSBpbWFnZS5cbiAgcGx1Z2luX2J1aWxkX2R1cmF0aW9uX3NlY29uZHM6IFsxMCwgMzAsIDYwLCAxMjAsIDMwMCwgNjAwLCAxMjAwLCAxODAwLCAzNjAwXSxcbiAgLy8gQSBmdWxsIGltYWdlIHNjYW4sIHdoaWNoIHJvdXRpbmVseSBwYXNzZXMgZml2ZSBtaW51dGVzIG9uIGEgbGFyZ2UgaW1hZ2UuXG4gIHBsdWdpbl92dWxuX3NjYW5fZHVyYXRpb25fc2Vjb25kczogWzEsIDUsIDE1LCAzMCwgNjAsIDEyMCwgMzAwLCA2MDAsIDEyMDBdLFxuICAvLyBUaW1lIGZyb20gYW4gaW5jaWRlbnQgYmVpbmcgcmFpc2VkIHRvIGEgaHVtYW4gYWNrbm93bGVkZ2luZyBpdC4gVGhlIGRlZmF1bHRcbiAgLy8gYnVja2V0cyBlbmQgYXQgMzAwcywgYW5kIGBoaXN0b2dyYW1fcXVhbnRpbGVgIGNhbm5vdCBpbnRlcnBvbGF0ZSBwYXN0IHRoZVxuICAvLyBsYXN0IGZpbml0ZSBib3VuZGFyeSDigJQgc28gd2l0aCB0aGVtLCBhbnkgdGhyZXNob2xkIGFib3ZlIGZpdmUgbWludXRlcyBjb3VsZFxuICAvLyBuZXZlciBmaXJlLCB3aGljaCBpcyBldmVyeSB0aHJlc2hvbGQgd29ydGggc2V0dGluZyBoZXJlLiBCb3VuZGFyaWVzIGF0IDFtLFxuICAvLyAybSwgNW0sIDEwbSwgMTVtLCAzMG0sIDFoLCAyaCwgNGg6IDE1bSBpcyBleGFjdCBiZWNhdXNlIHRoYXQgaXMgdGhlXG4gIC8vIGVzY2FsYXRpb24gZGVsYXkgdGhlIGFsZXJ0IGNvbXBhcmVzIGFnYWluc3QsIGFuZCB0aGUgcmFuZ2UgcmVhY2hlcyA0aCBzbyBhXG4gIC8vIHBhZ2Ugbm9ib2R5IGV2ZXIgcGlja2VkIHVwIGlzIHN0aWxsIGNvdW50ZWQgcmF0aGVyIHRoYW4gY2xpcHBlZC5cbiAgb25jYWxsX3BhZ2VfYWNrX3NlY29uZHM6IFs2MCwgMTIwLCAzMDAsIDYwMCwgOTAwLCAxODAwLCAzNjAwLCA3MjAwLCAxNDQwMF0sXG4gIC8vIENTQVQsIDEtNS4gTm90IGEgZHVyYXRpb24gYXQgYWxsLCBhbmQgbGlzdGVkIGhlcmUgZm9yIHRoZSBzYW1lIHJlYXNvbiBhc1xuICAvLyB0aGUgb3RoZXJzOiB0aGUgZGVmYXVsdCBidWNrZXRzIGFyZSBzdWItc2Vjb25kLCBzbyBldmVyeSByYXRpbmcgd291bGQgbGFuZFxuICAvLyBpbiB0aGUgc2FtZSBidWNrZXQgYW5kIHRoZSBxdWFudGlsZSB3b3VsZCBiZSBtZWFuaW5nbGVzcy4gT25lIGJvdW5kYXJ5IHBlclxuICAvLyBwb3NzaWJsZSBzY29yZSBtYWtlcyBgX3N1bSAvIF9jb3VudGAgYW4gZXhhY3QgYXZlcmFnZSBhbmQgZWFjaCBidWNrZXQgYVxuICAvLyByZWFsIGNvdW50LiBJdCByaWRlcyB0aGUgaGlzdG9ncmFtIHJhdGhlciB0aGFuIGEgY291bnRlci1wZXItc2NvcmUgc28gdGhlXG4gIC8vIGF2ZXJhZ2UgbmVlZHMgbm8gUHJvbVFMIGFyaXRobWV0aWMgb3ZlciBmaXZlIHNlcmllcy5cbiAgc3VwcG9ydF9zYXRpc2ZhY3Rpb246IFsxLCAyLCAzLCA0LCA1XSxcbn07XG5cbi8qKiBUaGUgbGF6eSBidXNpbmVzcy1tZXRyaWMgaGVscGVycywgYm91bmQgdG8gb25lIHJlZ2lzdHJ5LiAqL1xuZXhwb3J0IGludGVyZmFjZSBNZXRyaWNIZWxwZXJzIHtcbiAgaW5jQ291bnRlcihuYW1lOiBzdHJpbmcsIGxhYmVscz86IFJlY29yZDxzdHJpbmcsIHN0cmluZz4sIHZhbHVlPzogbnVtYmVyKTogdm9pZDtcbiAgb2JzZXJ2ZShuYW1lOiBzdHJpbmcsIGxhYmVsczogUmVjb3JkPHN0cmluZywgc3RyaW5nPiwgdmFsdWU6IG51bWJlcik6IHZvaWQ7XG4gIHNldEdhdWdlKG5hbWU6IHN0cmluZywgbGFiZWxzOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+LCB2YWx1ZTogbnVtYmVyKTogdm9pZDtcbiAgcmVzZXRHYXVnZShuYW1lOiBzdHJpbmcpOiB2b2lkO1xufVxuXG4vKipcbiAqIEJ1aWxkIGBpbmNDb3VudGVyYCAvIGBvYnNlcnZlYCAvIGBzZXRHYXVnZWAgb3ZlciBhIGNhbGxlci1zdXBwbGllZCByZWdpc3RyeS5cbiAqXG4gKiBUSEUgb25lIGltcGxlbWVudGF0aW9uIG9mIHRoZSBsYXp5IGNvdW50ZXIvaGlzdG9ncmFtL2dhdWdlIG1hcHMuIGFwaS1zZXJ2ZXInc1xuICogb3duIGV4cG9ydHMgYmVsb3cgYXJlIHRoaXMgZmFjdG9yeSBvdmVyIGl0cyBtb2R1bGUtbGV2ZWwgYHJlZ2lzdGVyYDsgdGhlXG4gKiBwbGF0Zm9ybSBzZXJ2aWNlIOKAlCB3aGljaCBydW5zIGl0cyBvd24gRXhwcmVzcyBzZXR1cCBpbnN0ZWFkIG9mIGBjcmVhdGVBcHBgLFxuICogYW5kIHRoZXJlZm9yZSBvd25zIGEgZGlmZmVyZW50IHJlZ2lzdHJ5IOKAlCBidWlsZHMgdGhlIGlkZW50aWNhbCBoZWxwZXJzIG92ZXJcbiAqIGl0cyBvd24uIFdpdGhvdXQgdGhlIGZhY3RvcnkgdGhlIHR3byBkcmlmdDogdGhleSBkaWZmZXIgdG9kYXkgb25seSBpbiB0aGVcbiAqIGhpc3RvZ3JhbSBidWNrZXRzLCB3aGljaCBpcyBleGFjdGx5IHRoZSBraW5kIG9mIGRpZmZlcmVuY2Ugbm9ib2R5IG5vdGljZXNcbiAqIHVudGlsIGEgZGFzaGJvYXJkIHJlYWRzIHdyb25nIG9uIG9uZSBzZXJ2aWNlLlxuICpcbiAqIGByZWdpc3RyeWAgbWF5IGJlIGEgdGh1bmssIGZvciBhIHJlZ2lzdHJ5IHRoYXQgaXMgaW5qZWN0ZWQgYWZ0ZXIgbW9kdWxlIGxvYWRcbiAqIChwbGF0Zm9ybSB3aXJlcyBpdHMgb3duIG9uIGFwcCBib290KS4gVGhlIHRodW5rIGlzIGNhbGxlZCBvbiB0aGUgRklSU1QgdXNlIG9mXG4gKiBlYWNoIG1ldHJpYyBuYW1lLCBuZXZlciBhdCBpbXBvcnQgdGltZSwgc28gYnVpbGRpbmcgdGhlIGhlbHBlcnMgaGFzIG5vIHNpZGVcbiAqIGVmZmVjdCBvZiBpdHMgb3duLlxuICovXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlTWV0cmljSGVscGVycyhyZWdpc3RyeTogUmVnaXN0cnkgfCAoKCkgPT4gUmVnaXN0cnkpKTogTWV0cmljSGVscGVycyB7XG4gIGNvbnN0IHJlZ2lzdHJ5T2YgPSAoKTogUmVnaXN0cnkgPT4gKHR5cGVvZiByZWdpc3RyeSA9PT0gJ2Z1bmN0aW9uJyA/IHJlZ2lzdHJ5KCkgOiByZWdpc3RyeSk7XG4gIGNvbnN0IGNvdW50ZXJzID0gbmV3IE1hcDxzdHJpbmcsIENvdW50ZXI8c3RyaW5nPj4oKTtcbiAgY29uc3QgaGlzdG9ncmFtcyA9IG5ldyBNYXA8c3RyaW5nLCBIaXN0b2dyYW08c3RyaW5nPj4oKTtcbiAgY29uc3QgZ2F1Z2VzID0gbmV3IE1hcDxzdHJpbmcsIEdhdWdlPHN0cmluZz4+KCk7XG5cbiAgcmV0dXJuIHtcbiAgICBpbmNDb3VudGVyKG5hbWUsIGxhYmVscyA9IHt9LCB2YWx1ZSA9IDEpIHtcbiAgICAgIGxldCBjb3VudGVyID0gY291bnRlcnMuZ2V0KG5hbWUpO1xuICAgICAgaWYgKCFjb3VudGVyKSB7XG4gICAgICAgIGNvdW50ZXIgPSBuZXcgQ291bnRlcih7XG4gICAgICAgICAgbmFtZSxcbiAgICAgICAgICBoZWxwOiBodW1hbml6ZU5hbWUobmFtZSksXG4gICAgICAgICAgbGFiZWxOYW1lczogT2JqZWN0LmtleXMobGFiZWxzKSxcbiAgICAgICAgICByZWdpc3RlcnM6IFtyZWdpc3RyeU9mKCldLFxuICAgICAgICB9KTtcbiAgICAgICAgY291bnRlcnMuc2V0KG5hbWUsIGNvdW50ZXIpO1xuICAgICAgfVxuICAgICAgY291bnRlci5pbmMobGFiZWxzLCB2YWx1ZSk7XG4gICAgfSxcblxuICAgIG9ic2VydmUobmFtZSwgbGFiZWxzLCB2YWx1ZSkge1xuICAgICAgbGV0IGhpc3QgPSBoaXN0b2dyYW1zLmdldChuYW1lKTtcbiAgICAgIGlmICghaGlzdCkge1xuICAgICAgICBoaXN0ID0gbmV3IEhpc3RvZ3JhbSh7XG4gICAgICAgICAgbmFtZSxcbiAgICAgICAgICBoZWxwOiBodW1hbml6ZU5hbWUobmFtZSksXG4gICAgICAgICAgbGFiZWxOYW1lczogT2JqZWN0LmtleXMobGFiZWxzKSxcbiAgICAgICAgICAvLyBEZWZhdWx0IGJ1Y2tldHMgdGFyZ2V0IHN1Yi1zZWNvbmQgdGhyb3VnaCBzZXZlcmFsLW1pbnV0ZVxuICAgICAgICAgIC8vIG9ic2VydmF0aW9ucy4gQW55dGhpbmcgdGhhdCBjYW4gZXhjZWVkIGZpdmUgbWludXRlcyBNVVNUIGRlY2xhcmUgaXRzXG4gICAgICAgICAgLy8gb3duIGRpc3RyaWJ1dGlvbiBpbiBgSElTVE9HUkFNX0JVQ0tFVFNgIGFib3ZlIOKAlCBwYXN0IHRoZSBsYXN0IGZpbml0ZVxuICAgICAgICAgIC8vIGJvdW5kYXJ5IGEgcXVhbnRpbGUgcmVhZHMgYmFjayBhcyB0aGF0IGJvdW5kYXJ5LCBzbyBhIHRocmVzaG9sZFxuICAgICAgICAgIC8vIGJleW9uZCBpdCBuZXZlciBmaXJlcy5cbiAgICAgICAgICBidWNrZXRzOiBbLi4uKEhJU1RPR1JBTV9CVUNLRVRTW25hbWVdID8/IFswLjA1LCAwLjEsIDAuMjUsIDAuNSwgMSwgMi41LCA1LCAxMCwgMzAsIDYwLCAxMjAsIDMwMF0pXSxcbiAgICAgICAgICByZWdpc3RlcnM6IFtyZWdpc3RyeU9mKCldLFxuICAgICAgICB9KTtcbiAgICAgICAgaGlzdG9ncmFtcy5zZXQobmFtZSwgaGlzdCk7XG4gICAgICB9XG4gICAgICBoaXN0Lm9ic2VydmUobGFiZWxzLCB2YWx1ZSk7XG4gICAgfSxcblxuICAgIHNldEdhdWdlKG5hbWUsIGxhYmVscywgdmFsdWUpIHtcbiAgICAgIGxldCBnYXVnZSA9IGdhdWdlcy5nZXQobmFtZSk7XG4gICAgICBpZiAoIWdhdWdlKSB7XG4gICAgICAgIGdhdWdlID0gbmV3IEdhdWdlKHtcbiAgICAgICAgICBuYW1lLFxuICAgICAgICAgIGhlbHA6IGh1bWFuaXplTmFtZShuYW1lKSxcbiAgICAgICAgICBsYWJlbE5hbWVzOiBPYmplY3Qua2V5cyhsYWJlbHMpLFxuICAgICAgICAgIHJlZ2lzdGVyczogW3JlZ2lzdHJ5T2YoKV0sXG4gICAgICAgIH0pO1xuICAgICAgICBnYXVnZXMuc2V0KG5hbWUsIGdhdWdlKTtcbiAgICAgIH1cbiAgICAgIGdhdWdlLnNldChsYWJlbHMsIHZhbHVlKTtcbiAgICB9LFxuXG4gICAgcmVzZXRHYXVnZShuYW1lKSB7XG4gICAgICBnYXVnZXMuZ2V0KG5hbWUpPy5yZXNldCgpO1xuICAgIH0sXG4gIH07XG59XG5cbi8qKiBUaGlzIHNlcnZpY2UncyBvd24gaGVscGVycywgb3ZlciB0aGUgc2hhcmVkIG1vZHVsZS1sZXZlbCByZWdpc3RyeS4gKi9cbmNvbnN0IGJ1c2luZXNzTWV0cmljcyA9IGNyZWF0ZU1ldHJpY0hlbHBlcnMocmVnaXN0ZXIpO1xuXG4vKipcbiAqIEluY3JlbWVudCBhIGJ1c2luZXNzIGNvdW50ZXIsIGNyZWF0aW5nIGl0IG9uIGZpcnN0IHVzZS5cbiAqXG4gKiBFdmVyeSBleGFtcGxlIGJlbG93IGlzIGEgY2FsbCB0aGF0IEVYSVNUUywgd2l0aCB0aGUgbGFiZWxzIGl0IHJlYWxseSBwYXNzZXMuIFRoYXQgaXNcbiAqIGRlbGliZXJhdGU6IGFuIGludmVudGVkIGV4YW1wbGUgcmVhZHMgYXMgYW4gaW52ZW50b3J5IG9mIHdoYXQgdGhlIHN5c3RlbSBtZWFzdXJlcywgYW5kXG4gKiBhIG1ldHJpY3Mgc3VydmV5IGxhdGVyIGNvdW50ZWQgdGhyZWUgbmFtZXMgZnJvbSB0aGlzIGJsb2NrIOKAlCBgcGlwZWxpbmVzX2dlbmVyYXRlZF90b3RhbGAsXG4gKiBgcXVvdGFfdGhyZXNob2xkX2Nyb3NzZWRfdG90YWxgLCBgY29tcGxpYW5jZV92aW9sYXRpb25zX2ZvdW5kX3RvdGFsYCDigJQgYXMgbGl2ZSBtZXRyaWNzXG4gKiBtaXNzaW5nIGEgZGFzaGJvYXJkIHBhbmVsLiBOb3RoaW5nIGVtaXR0ZWQgYW55IG9mIHRoZW0uIElsbHVzdHJhdGl2ZSBuYW1lcyBpbiBhIGRvY3N0cmluZ1xuICogYWJvdXQgbWV0cmljIG5hbWluZyBhcmUgaW5kaXN0aW5ndWlzaGFibGUgZnJvbSByZWFsIG9uZXMsIHNvIHRoZXJlIGFyZSBub25lIGhlcmUuXG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIGluY0NvdW50ZXIoJ3BsdWdpbl9idWlsZHNfdG90YWwnLCB7IHN0YXR1czogJ3N1Y2Nlc3MnLCBvcmdfaWQ6IG9yZ0lkIH0pO1xuICogaW5jQ291bnRlcignY29tcGxpYW5jZV9zY2Fuc190b3RhbCcsIHsgb3V0Y29tZTogJ3N0YXJ0ZWQnIH0pO1xuICogaW5jQ291bnRlcigncGx1Z2luX3Z1bG5fZmluZGluZ3NfdG90YWwnLCB7IHRyaWdnZXIsIHNldmVyaXR5IH0sIGNvdW50KTtcbiAqIGluY0NvdW50ZXIoJ2FpX3Rva2Vuc190b3RhbCcsIHsgcm91dGU6ICdhZ2VudCcsIGtpbmQ6ICdpbnB1dCcgfSwgaW5wdXRUb2tlbnMpO1xuICogYGBgXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpbmNDb3VudGVyKG5hbWU6IHN0cmluZywgbGFiZWxzOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+ID0ge30sIHZhbHVlID0gMSk6IHZvaWQge1xuICBidXNpbmVzc01ldHJpY3MuaW5jQ291bnRlcihuYW1lLCBsYWJlbHMsIHZhbHVlKTtcbn1cblxuLyoqXG4gKiBSZWNvcmQgYW4gb2JzZXJ2YXRpb24gb24gYSBidXNpbmVzcyBoaXN0b2dyYW0sIGNyZWF0aW5nIGl0IG9uIGZpcnN0IHVzZS5cbiAqIFVzZSBmb3IgZHVyYXRpb25zLCBzaXplcywgYW55dGhpbmcgd2hlcmUgcGVyY2VudGlsZXMgbWF0dGVyLlxuICpcbiAqIEBleGFtcGxlXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiBvYnNlcnZlKCdhaV9nZW5lcmF0aW9uX2R1cmF0aW9uX3NlY29uZHMnLCB7IHJvdXRlLCBwcm92aWRlcjogcHJvdmlkZXJMYWJlbCB9LCBkdXJhdGlvblNlYyk7XG4gKiBvYnNlcnZlKCdwbHVnaW5fYnVpbGRfZHVyYXRpb25fc2Vjb25kcycsIHsgb3JnX2lkOiBvcmdJZCB9LCBkdXJhdGlvblNlYyk7XG4gKiBgYGBcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG9ic2VydmUobmFtZTogc3RyaW5nLCBsYWJlbHM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4sIHZhbHVlOiBudW1iZXIpOiB2b2lkIHtcbiAgYnVzaW5lc3NNZXRyaWNzLm9ic2VydmUobmFtZSwgbGFiZWxzLCB2YWx1ZSk7XG59XG5cbi8qKlxuICogU2V0IHRoZSB2YWx1ZSBvZiBhIGJ1c2luZXNzIGdhdWdlLCBjcmVhdGluZyBpdCBvbiBmaXJzdCB1c2UuIFVzZSBmb3JcbiAqIHBvaW50LWluLXRpbWUgb2JzZXJ2YXRpb25zIHNhbXBsZWQgYnkgYSBzY3JhcGVyIOKAlCBxdWV1ZSBkZXB0aCwgYWN0aXZlXG4gKiBjb25uZWN0aW9uIGNvdW50cywgaW4tZmxpZ2h0IHJlcXVlc3RzLlxuICpcbiAqIEBleGFtcGxlXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiBzZXRHYXVnZSgncGx1Z2luX3F1ZXVlX2pvYnMnLCB7IHF1ZXVlOiAncGx1Z2luLWJ1aWxkJywgc3RhdGU6ICd3YWl0aW5nJyB9LCAxMik7XG4gKiBzZXRHYXVnZSgncGx1Z2luX3F1ZXVlX2pvYnMnLCB7IHF1ZXVlOiAncGx1Z2luLWJ1aWxkJywgc3RhdGU6ICdhY3RpdmUnIH0sIDMpO1xuICogYGBgXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzZXRHYXVnZShuYW1lOiBzdHJpbmcsIGxhYmVsczogUmVjb3JkPHN0cmluZywgc3RyaW5nPiwgdmFsdWU6IG51bWJlcik6IHZvaWQge1xuICBidXNpbmVzc01ldHJpY3Muc2V0R2F1Z2UobmFtZSwgbGFiZWxzLCB2YWx1ZSk7XG59XG5cbi8qKlxuICogRHJvcCBFVkVSWSBzZXJpZXMgb2YgYSBidXNpbmVzcyBnYXVnZS4gRm9yIGEgZ2F1Z2UgdGhhdCBkZXNjcmliZXMgYSBTRVQg4oCUIG9uZVxuICogc2VyaWVzIHBlciBjb25maWd1cmVkIGVudHJ5IOKAlCBhbmQgaXMgcmUtcHVibGlzaGVkIHdob2xlOiB3aXRob3V0IHRoZSByZXNldCwgYVxuICogc2VyaWVzIGZvciBhbiBlbnRyeSB0aGF0IGhhcyBzaW5jZSBiZWVuIGRlbGV0ZWQga2VlcHMgaXRzIGxhc3QgdmFsdWUgZm9yZXZlcixcbiAqIGFuZCBhbiBhbGVydCBvbiBpdCBrZWVwcyBmaXJpbmcgZm9yIHNvbWV0aGluZyB0aGF0IG5vIGxvbmdlciBleGlzdHMuIENhbGwgaXRcbiAqIGltbWVkaWF0ZWx5IGJlZm9yZSByZS1zZXR0aW5nIHRoZSBjdXJyZW50IHNldC4gQSBnYXVnZSBuZXZlciBzZXQgaXMgYSBuby1vcC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlc2V0R2F1Z2UobmFtZTogc3RyaW5nKTogdm9pZCB7XG4gIGJ1c2luZXNzTWV0cmljcy5yZXNldEdhdWdlKG5hbWUpO1xufVxuXG5mdW5jdGlvbiBodW1hbml6ZU5hbWUobWV0cmljTmFtZTogc3RyaW5nKTogc3RyaW5nIHtcbiAgLy8gYHBsdWdpbl9idWlsZHNfdG90YWxgIOKGkiBcIlBsdWdpbiBidWlsZHMgdG90YWxcIlxuICByZXR1cm4gbWV0cmljTmFtZVxuICAgIC5yZXBsYWNlKC9fL2csICcgJylcbiAgICAucmVwbGFjZSgvXi4vLCAoYykgPT4gYy50b1VwcGVyQ2FzZSgpKTtcbn1cbiJdfQ==
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type QuotaReserveResult, type QuotaService, type QuotaType } from '@pipeline-builder/api-core';
|
|
1
|
+
import { type QuotaReserveResult, type QuotaService, type QuotaType, type QuotaUsageAttribution } from '@pipeline-builder/api-core';
|
|
2
2
|
import type { Response } from 'express';
|
|
3
3
|
/** The reserved quota slot, handed to the guarded body. */
|
|
4
4
|
export interface QuotaSlot {
|
|
@@ -10,13 +10,27 @@ export interface QuotaSlot {
|
|
|
10
10
|
* responding). From here on a failure KEEPS the slot — the cost was incurred.
|
|
11
11
|
*/
|
|
12
12
|
markConsumed(): void;
|
|
13
|
-
/**
|
|
13
|
+
/**
|
|
14
|
+
* Give the slot back now. Idempotent: refunds at most once — and a NO-OP once
|
|
15
|
+
* {@link markConsumed} was called. A paid provider round-trip is never refunded,
|
|
16
|
+
* whatever path (a client abort, a later failure, an empty answer) asks for it
|
|
17
|
+
* afterwards; callers no longer need to guard `refund()` with their own
|
|
18
|
+
* "was the provider contacted" flag.
|
|
19
|
+
*/
|
|
14
20
|
refund(): void;
|
|
15
21
|
}
|
|
16
22
|
export interface QuotaReservationOptions {
|
|
17
23
|
quotaService: QuotaService;
|
|
18
24
|
orgId: string;
|
|
19
25
|
type: QuotaType;
|
|
26
|
+
/** Units to reserve (default 1) — e.g. an AI model's weight. Refunds give back the same amount. */
|
|
27
|
+
amount?: number;
|
|
28
|
+
/**
|
|
29
|
+
* Usage-ledger attribution for the reserve AND its refund. Defaults to the
|
|
30
|
+
* ambient request context (principal + request id, no route) — pass it
|
|
31
|
+
* explicitly to record the route, the feature and the model.
|
|
32
|
+
*/
|
|
33
|
+
attribution?: QuotaUsageAttribution;
|
|
20
34
|
/** Signer of the quota service token. Defaults to this process (`SERVICE_NAME`). */
|
|
21
35
|
serviceName?: string;
|
|
22
36
|
logWarn: (message: string, data?: unknown) => void;
|
|
@@ -35,12 +49,37 @@ export type QuotaReservationOutcome<T> = {
|
|
|
35
49
|
status: 'failed';
|
|
36
50
|
error: unknown;
|
|
37
51
|
};
|
|
52
|
+
/** What {@link reserveQuotaSlot} hands back: a live slot, or the denial. */
|
|
53
|
+
export type QuotaSlotReservation = {
|
|
54
|
+
status: 'denied';
|
|
55
|
+
reservation: QuotaReserveResult;
|
|
56
|
+
} | {
|
|
57
|
+
status: 'reserved';
|
|
58
|
+
slot: QuotaSlot;
|
|
59
|
+
};
|
|
60
|
+
/**
|
|
61
|
+
* Reserve one slot (of `amount` units) and return its handle, WITHOUT running
|
|
62
|
+
* anything. The primitive under {@link withQuotaReservation}, for a caller whose
|
|
63
|
+
* gated work does not fit one callback — e.g. a tool inside an agent turn that
|
|
64
|
+
* settles its own slot. The caller owns settlement: `markConsumed()` once the
|
|
65
|
+
* resource is spent, `refund()` on every path that fails before that.
|
|
66
|
+
*
|
|
67
|
+
* Denied → `{ status: 'denied' }`, answered on `res` when given.
|
|
68
|
+
*/
|
|
69
|
+
export declare function reserveQuotaSlot(opts: QuotaReservationOptions): Promise<QuotaSlotReservation>;
|
|
70
|
+
/**
|
|
71
|
+
* Run `body` against a reserved slot and settle it by ONE rule: keep it once
|
|
72
|
+
* the resource was consumed; refund it if the body fails first. Shared by
|
|
73
|
+
* {@link withQuotaReservation} and api-server's AI reservation.
|
|
74
|
+
*/
|
|
75
|
+
export declare function runWithSlot<T, S extends QuotaSlot>(slot: S, body: (slot: S) => Promise<T>, onError?: (error: unknown) => void | Promise<void>): Promise<QuotaReservationOutcome<T>>;
|
|
38
76
|
/**
|
|
39
77
|
* Reserve one quota slot, run `body`, and settle the slot by ONE rule:
|
|
40
78
|
* keep it once the resource was consumed; refund it if the body fails first.
|
|
41
79
|
*
|
|
42
80
|
* - Denied → `{ status: 'denied' }` (answered on `res` when given); `body` never runs.
|
|
43
|
-
* - `body` resolves → the slot is kept (unless `body` called `slot.refund()`
|
|
81
|
+
* - `body` resolves → the slot is kept (unless `body` called `slot.refund()`
|
|
82
|
+
* BEFORE marking it consumed — a refund after `markConsumed()` is ignored).
|
|
44
83
|
* - `body` throws → refunded unless consumed — marked via `slot.markConsumed()`
|
|
45
84
|
* or signalled by the error itself carrying `providerContacted === true`
|
|
46
85
|
* (an AI round-trip that completed but produced nothing usable). The error is
|
|
@@ -2,25 +2,22 @@
|
|
|
2
2
|
// SPDX-License-Identifier: Apache-2.0
|
|
3
3
|
import { decrementQuota, getServiceAuthHeader, reserveQuota, sendQuotaReserveDenied, serviceIdentity, } from '@pipeline-builder/api-core';
|
|
4
4
|
/**
|
|
5
|
-
* Reserve one
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
* - `body` throws → refunded unless consumed — marked via `slot.markConsumed()`
|
|
11
|
-
* or signalled by the error itself carrying `providerContacted === true`
|
|
12
|
-
* (an AI round-trip that completed but produced nothing usable). The error is
|
|
13
|
-
* then passed to `onError`, or rethrown when there is none.
|
|
5
|
+
* Reserve one slot (of `amount` units) and return its handle, WITHOUT running
|
|
6
|
+
* anything. The primitive under {@link withQuotaReservation}, for a caller whose
|
|
7
|
+
* gated work does not fit one callback — e.g. a tool inside an agent turn that
|
|
8
|
+
* settles its own slot. The caller owns settlement: `markConsumed()` once the
|
|
9
|
+
* resource is spent, `refund()` on every path that fails before that.
|
|
14
10
|
*
|
|
15
|
-
*
|
|
16
|
-
* end-user bearer: the quota increment endpoint rejects user principals.
|
|
11
|
+
* Denied → `{ status: 'denied' }`, answered on `res` when given.
|
|
17
12
|
*/
|
|
18
|
-
export async function
|
|
19
|
-
const { quotaService, orgId, type, logWarn } = opts;
|
|
13
|
+
export async function reserveQuotaSlot(opts) {
|
|
14
|
+
const { quotaService, orgId, type, logWarn, attribution } = opts;
|
|
15
|
+
const amount = opts.amount ?? 1;
|
|
20
16
|
const serviceAuth = getServiceAuthHeader({ serviceName: opts.serviceName ?? serviceIdentity(), orgId, role: 'member' });
|
|
21
17
|
// Reserve atomically BEFORE any work: two concurrent requests at the limit
|
|
22
|
-
// can't both pass.
|
|
23
|
-
|
|
18
|
+
// can't both pass. Attribution defaults to the ambient request context
|
|
19
|
+
// (principal + request id) inside the quota client.
|
|
20
|
+
const reservation = await reserveQuota(quotaService, orgId, type, serviceAuth, amount, attribution);
|
|
24
21
|
if (reservation.exceeded) {
|
|
25
22
|
if (opts.res)
|
|
26
23
|
sendQuotaReserveDenied(opts.res, type, reservation);
|
|
@@ -33,19 +30,28 @@ export async function withQuotaReservation(opts, body, onError) {
|
|
|
33
30
|
reservation,
|
|
34
31
|
markConsumed: () => { consumed = true; },
|
|
35
32
|
refund: () => {
|
|
36
|
-
if (refunded)
|
|
33
|
+
if (refunded || consumed)
|
|
37
34
|
return;
|
|
38
35
|
refunded = true;
|
|
39
36
|
// The reserved resetAt keeps a period rollover from being double-charged.
|
|
40
|
-
decrementQuota(quotaService, orgId, type, serviceAuth, logWarn,
|
|
37
|
+
decrementQuota(quotaService, orgId, type, serviceAuth, logWarn, amount, reservation.quota.resetAt, attribution);
|
|
41
38
|
},
|
|
42
39
|
};
|
|
40
|
+
return { status: 'reserved', slot };
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Run `body` against a reserved slot and settle it by ONE rule: keep it once
|
|
44
|
+
* the resource was consumed; refund it if the body fails first. Shared by
|
|
45
|
+
* {@link withQuotaReservation} and api-server's AI reservation.
|
|
46
|
+
*/
|
|
47
|
+
export async function runWithSlot(slot, body, onError) {
|
|
43
48
|
try {
|
|
44
49
|
return { status: 'done', value: await body(slot) };
|
|
45
50
|
}
|
|
46
51
|
catch (error) {
|
|
52
|
+
// `refund()` is itself a no-op once the slot was marked consumed.
|
|
47
53
|
const errorSaysConsumed = error?.providerContacted === true;
|
|
48
|
-
if (!
|
|
54
|
+
if (!errorSaysConsumed)
|
|
49
55
|
slot.refund();
|
|
50
56
|
if (!onError)
|
|
51
57
|
throw error;
|
|
@@ -53,4 +59,25 @@ export async function withQuotaReservation(opts, body, onError) {
|
|
|
53
59
|
return { status: 'failed', error };
|
|
54
60
|
}
|
|
55
61
|
}
|
|
56
|
-
|
|
62
|
+
/**
|
|
63
|
+
* Reserve one quota slot, run `body`, and settle the slot by ONE rule:
|
|
64
|
+
* keep it once the resource was consumed; refund it if the body fails first.
|
|
65
|
+
*
|
|
66
|
+
* - Denied → `{ status: 'denied' }` (answered on `res` when given); `body` never runs.
|
|
67
|
+
* - `body` resolves → the slot is kept (unless `body` called `slot.refund()`
|
|
68
|
+
* BEFORE marking it consumed — a refund after `markConsumed()` is ignored).
|
|
69
|
+
* - `body` throws → refunded unless consumed — marked via `slot.markConsumed()`
|
|
70
|
+
* or signalled by the error itself carrying `providerContacted === true`
|
|
71
|
+
* (an AI round-trip that completed but produced nothing usable). The error is
|
|
72
|
+
* then passed to `onError`, or rethrown when there is none.
|
|
73
|
+
*
|
|
74
|
+
* The reserve and refund authenticate with a minted service token, never the
|
|
75
|
+
* end-user bearer: the quota increment endpoint rejects user principals.
|
|
76
|
+
*/
|
|
77
|
+
export async function withQuotaReservation(opts, body, onError) {
|
|
78
|
+
const reserved = await reserveQuotaSlot(opts);
|
|
79
|
+
if (reserved.status === 'denied')
|
|
80
|
+
return reserved;
|
|
81
|
+
return runWithSlot(reserved.slot, body, onError);
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicXVvdGEtcmVzZXJ2YXRpb24uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvYXBpL3F1b3RhLXJlc2VydmF0aW9uLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLCtDQUErQztBQUMvQyxzQ0FBc0M7QUFFdEMsT0FBTyxFQUNMLGNBQWMsRUFDZCxvQkFBb0IsRUFDcEIsWUFBWSxFQUNaLHNCQUFzQixFQUN0QixlQUFlLEdBS2hCLE1BQU0sNEJBQTRCLENBQUM7QUFxRHBDOzs7Ozs7OztHQVFHO0FBQ0gsTUFBTSxDQUFDLEtBQUssVUFBVSxnQkFBZ0IsQ0FBQyxJQUE2QjtJQUNsRSxNQUFNLEVBQUUsWUFBWSxFQUFFLEtBQUssRUFBRSxJQUFJLEVBQUUsT0FBTyxFQUFFLFdBQVcsRUFBRSxHQUFHLElBQUksQ0FBQztJQUNqRSxNQUFNLE1BQU0sR0FBRyxJQUFJLENBQUMsTUFBTSxJQUFJLENBQUMsQ0FBQztJQUNoQyxNQUFNLFdBQVcsR0FBRyxvQkFBb0IsQ0FBQyxFQUFFLFdBQVcsRUFBRSxJQUFJLENBQUMsV0FBVyxJQUFJLGVBQWUsRUFBRSxFQUFFLEtBQUssRUFBRSxJQUFJLEVBQUUsUUFBUSxFQUFFLENBQUMsQ0FBQztJQUV4SCwyRUFBMkU7SUFDM0UsdUVBQXVFO0lBQ3ZFLG9EQUFvRDtJQUNwRCxNQUFNLFdBQVcsR0FBRyxNQUFNLFlBQVksQ0FBQyxZQUFZLEVBQUUsS0FBSyxFQUFFLElBQUksRUFBRSxXQUFXLEVBQUUsTUFBTSxFQUFFLFdBQVcsQ0FBQyxDQUFDO0lBQ3BHLElBQUksV0FBVyxDQUFDLFFBQVEsRUFBRSxDQUFDO1FBQ3pCLElBQUksSUFBSSxDQUFDLEdBQUc7WUFBRSxzQkFBc0IsQ0FBQyxJQUFJLENBQUMsR0FBRyxFQUFFLElBQUksRUFBRSxXQUFXLENBQUMsQ0FBQztRQUNsRSxPQUFPLEVBQUUsTUFBTSxFQUFFLFFBQVEsRUFBRSxXQUFXLEVBQUUsQ0FBQztJQUMzQyxDQUFDO0lBRUQsSUFBSSxRQUFRLEdBQUcsS0FBSyxDQUFDO0lBQ3JCLElBQUksUUFBUSxHQUFHLEtBQUssQ0FBQztJQUNyQixNQUFNLElBQUksR0FBYztRQUN0QixXQUFXO1FBQ1gsV0FBVztRQUNYLFlBQVksRUFBRSxHQUFHLEVBQUUsR0FBRyxRQUFRLEdBQUcsSUFBSSxDQUFDLENBQUMsQ0FBQztRQUN4QyxNQUFNLEVBQUUsR0FBRyxFQUFFO1lBQ1gsSUFBSSxRQUFRLElBQUksUUFBUTtnQkFBRSxPQUFPO1lBQ2pDLFFBQVEsR0FBRyxJQUFJLENBQUM7WUFDaEIsMEVBQTBFO1lBQzFFLGNBQWMsQ0FBQyxZQUFZLEVBQUUsS0FBSyxFQUFFLElBQUksRUFBRSxXQUFXLEVBQUUsT0FBTyxFQUFFLE1BQU0sRUFBRSxXQUFXLENBQUMsS0FBSyxDQUFDLE9BQU8sRUFBRSxXQUFXLENBQUMsQ0FBQztRQUNsSCxDQUFDO0tBQ0YsQ0FBQztJQUNGLE9BQU8sRUFBRSxNQUFNLEVBQUUsVUFBVSxFQUFFLElBQUksRUFBRSxDQUFDO0FBQ3RDLENBQUM7QUFFRDs7OztHQUlHO0FBQ0gsTUFBTSxDQUFDLEtBQUssVUFBVSxXQUFXLENBQy9CLElBQU8sRUFDUCxJQUE2QixFQUM3QixPQUFrRDtJQUVsRCxJQUFJLENBQUM7UUFDSCxPQUFPLEVBQUUsTUFBTSxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQUUsTUFBTSxJQUFJLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQztJQUNyRCxDQUFDO0lBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztRQUNmLGtFQUFrRTtRQUNsRSxNQUFNLGlCQUFpQixHQUFJLEtBQWdELEVBQUUsaUJBQWlCLEtBQUssSUFBSSxDQUFDO1FBQ3hHLElBQUksQ0FBQyxpQkFBaUI7WUFBRSxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7UUFDdEMsSUFBSSxDQUFDLE9BQU87WUFBRSxNQUFNLEtBQUssQ0FBQztRQUMxQixNQUFNLE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUNyQixPQUFPLEVBQUUsTUFBTSxFQUFFLFFBQVEsRUFBRSxLQUFLLEVBQUUsQ0FBQztJQUNyQyxDQUFDO0FBQ0gsQ0FBQztBQUVEOzs7Ozs7Ozs7Ozs7OztHQWNHO0FBQ0gsTUFBTSxDQUFDLEtBQUssVUFBVSxvQkFBb0IsQ0FDeEMsSUFBNkIsRUFDN0IsSUFBcUMsRUFDckMsT0FBa0Q7SUFFbEQsTUFBTSxRQUFRLEdBQUcsTUFBTSxnQkFBZ0IsQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUM5QyxJQUFJLFFBQVEsQ0FBQyxNQUFNLEtBQUssUUFBUTtRQUFFLE9BQU8sUUFBUSxDQUFDO0lBQ2xELE9BQU8sV0FBVyxDQUFDLFFBQVEsQ0FBQyxJQUFJLEVBQUUsSUFBSSxFQUFFLE9BQU8sQ0FBQyxDQUFDO0FBQ25ELENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBDb3B5cmlnaHQgMjAyNiBQaXBlbGluZSBCdWlsZGVyIENvbnRyaWJ1dG9yc1xuLy8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFwYWNoZS0yLjBcblxuaW1wb3J0IHtcbiAgZGVjcmVtZW50UXVvdGEsXG4gIGdldFNlcnZpY2VBdXRoSGVhZGVyLFxuICByZXNlcnZlUXVvdGEsXG4gIHNlbmRRdW90YVJlc2VydmVEZW5pZWQsXG4gIHNlcnZpY2VJZGVudGl0eSxcbiAgdHlwZSBRdW90YVJlc2VydmVSZXN1bHQsXG4gIHR5cGUgUXVvdGFTZXJ2aWNlLFxuICB0eXBlIFF1b3RhVHlwZSxcbiAgdHlwZSBRdW90YVVzYWdlQXR0cmlidXRpb24sXG59IGZyb20gJ0BwaXBlbGluZS1idWlsZGVyL2FwaS1jb3JlJztcbmltcG9ydCB0eXBlIHsgUmVzcG9uc2UgfSBmcm9tICdleHByZXNzJztcblxuLyoqIFRoZSByZXNlcnZlZCBxdW90YSBzbG90LCBoYW5kZWQgdG8gdGhlIGd1YXJkZWQgYm9keS4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgUXVvdGFTbG90IHtcbiAgLyoqIE1pbnRlZCBzZXJ2aWNlIHRva2VuIHRoZSByZXNlcnZhdGlvbiB1c2VkIOKAlCByZXVzZSBpdCBmb3IgdGhlIGJvZHkncyBvd24gUzJTIGNhbGxzLiAqL1xuICByZWFkb25seSBzZXJ2aWNlQXV0aDogc3RyaW5nO1xuICByZWFkb25seSByZXNlcnZhdGlvbjogUXVvdGFSZXNlcnZlUmVzdWx0O1xuICAvKipcbiAgICogVGhlIHJlc2VydmVkIHJlc291cmNlIGhhcyBiZWVuIGNvbnN1bWVkIChlLmcuIHRoZSBBSSBwcm92aWRlciBzdGFydGVkXG4gICAqIHJlc3BvbmRpbmcpLiBGcm9tIGhlcmUgb24gYSBmYWlsdXJlIEtFRVBTIHRoZSBzbG90IOKAlCB0aGUgY29zdCB3YXMgaW5jdXJyZWQuXG4gICAqL1xuICBtYXJrQ29uc3VtZWQoKTogdm9pZDtcbiAgLyoqXG4gICAqIEdpdmUgdGhlIHNsb3QgYmFjayBub3cuIElkZW1wb3RlbnQ6IHJlZnVuZHMgYXQgbW9zdCBvbmNlIOKAlCBhbmQgYSBOTy1PUCBvbmNlXG4gICAqIHtAbGluayBtYXJrQ29uc3VtZWR9IHdhcyBjYWxsZWQuIEEgcGFpZCBwcm92aWRlciByb3VuZC10cmlwIGlzIG5ldmVyIHJlZnVuZGVkLFxuICAgKiB3aGF0ZXZlciBwYXRoIChhIGNsaWVudCBhYm9ydCwgYSBsYXRlciBmYWlsdXJlLCBhbiBlbXB0eSBhbnN3ZXIpIGFza3MgZm9yIGl0XG4gICAqIGFmdGVyd2FyZHM7IGNhbGxlcnMgbm8gbG9uZ2VyIG5lZWQgdG8gZ3VhcmQgYHJlZnVuZCgpYCB3aXRoIHRoZWlyIG93blxuICAgKiBcIndhcyB0aGUgcHJvdmlkZXIgY29udGFjdGVkXCIgZmxhZy5cbiAgICovXG4gIHJlZnVuZCgpOiB2b2lkO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFF1b3RhUmVzZXJ2YXRpb25PcHRpb25zIHtcbiAgcXVvdGFTZXJ2aWNlOiBRdW90YVNlcnZpY2U7XG4gIG9yZ0lkOiBzdHJpbmc7XG4gIHR5cGU6IFF1b3RhVHlwZTtcbiAgLyoqIFVuaXRzIHRvIHJlc2VydmUgKGRlZmF1bHQgMSkg4oCUIGUuZy4gYW4gQUkgbW9kZWwncyB3ZWlnaHQuIFJlZnVuZHMgZ2l2ZSBiYWNrIHRoZSBzYW1lIGFtb3VudC4gKi9cbiAgYW1vdW50PzogbnVtYmVyO1xuICAvKipcbiAgICogVXNhZ2UtbGVkZ2VyIGF0dHJpYnV0aW9uIGZvciB0aGUgcmVzZXJ2ZSBBTkQgaXRzIHJlZnVuZC4gRGVmYXVsdHMgdG8gdGhlXG4gICAqIGFtYmllbnQgcmVxdWVzdCBjb250ZXh0IChwcmluY2lwYWwgKyByZXF1ZXN0IGlkLCBubyByb3V0ZSkg4oCUIHBhc3MgaXRcbiAgICogZXhwbGljaXRseSB0byByZWNvcmQgdGhlIHJvdXRlLCB0aGUgZmVhdHVyZSBhbmQgdGhlIG1vZGVsLlxuICAgKi9cbiAgYXR0cmlidXRpb24/OiBRdW90YVVzYWdlQXR0cmlidXRpb247XG4gIC8qKiBTaWduZXIgb2YgdGhlIHF1b3RhIHNlcnZpY2UgdG9rZW4uIERlZmF1bHRzIHRvIHRoaXMgcHJvY2VzcyAoYFNFUlZJQ0VfTkFNRWApLiAqL1xuICBzZXJ2aWNlTmFtZT86IHN0cmluZztcbiAgbG9nV2FybjogKG1lc3NhZ2U6IHN0cmluZywgZGF0YT86IHVua25vd24pID0+IHZvaWQ7XG4gIC8qKiBXaGVuIHNldCwgYSBkZW5pZWQgcmVzZXJ2YXRpb24gaXMgYW5zd2VyZWQgb24gaXQgKDQyOSwgb3IgNTAzIHdoZW4gdW5jb25maXJtYWJsZSkuICovXG4gIHJlcz86IFJlc3BvbnNlO1xufVxuXG5leHBvcnQgdHlwZSBRdW90YVJlc2VydmF0aW9uT3V0Y29tZTxUPiA9XG4gIHwgeyBzdGF0dXM6ICdkZW5pZWQnOyByZXNlcnZhdGlvbjogUXVvdGFSZXNlcnZlUmVzdWx0IH1cbiAgfCB7IHN0YXR1czogJ2RvbmUnOyB2YWx1ZTogVCB9XG4gIC8qKiBPbmx5IHdpdGggYW4gYG9uRXJyb3JgIGhhbmRsZXI6IHRoZSBib2R5IHRocmV3IGFuZCB0aGUgaGFuZGxlciBhbnN3ZXJlZC4gKi9cbiAgfCB7IHN0YXR1czogJ2ZhaWxlZCc7IGVycm9yOiB1bmtub3duIH07XG5cbi8qKiBXaGF0IHtAbGluayByZXNlcnZlUXVvdGFTbG90fSBoYW5kcyBiYWNrOiBhIGxpdmUgc2xvdCwgb3IgdGhlIGRlbmlhbC4gKi9cbmV4cG9ydCB0eXBlIFF1b3RhU2xvdFJlc2VydmF0aW9uID1cbiAgfCB7IHN0YXR1czogJ2RlbmllZCc7IHJlc2VydmF0aW9uOiBRdW90YVJlc2VydmVSZXN1bHQgfVxuICB8IHsgc3RhdHVzOiAncmVzZXJ2ZWQnOyBzbG90OiBRdW90YVNsb3QgfTtcblxuLyoqXG4gKiBSZXNlcnZlIG9uZSBzbG90IChvZiBgYW1vdW50YCB1bml0cykgYW5kIHJldHVybiBpdHMgaGFuZGxlLCBXSVRIT1VUIHJ1bm5pbmdcbiAqIGFueXRoaW5nLiBUaGUgcHJpbWl0aXZlIHVuZGVyIHtAbGluayB3aXRoUXVvdGFSZXNlcnZhdGlvbn0sIGZvciBhIGNhbGxlciB3aG9zZVxuICogZ2F0ZWQgd29yayBkb2VzIG5vdCBmaXQgb25lIGNhbGxiYWNrIOKAlCBlLmcuIGEgdG9vbCBpbnNpZGUgYW4gYWdlbnQgdHVybiB0aGF0XG4gKiBzZXR0bGVzIGl0cyBvd24gc2xvdC4gVGhlIGNhbGxlciBvd25zIHNldHRsZW1lbnQ6IGBtYXJrQ29uc3VtZWQoKWAgb25jZSB0aGVcbiAqIHJlc291cmNlIGlzIHNwZW50LCBgcmVmdW5kKClgIG9uIGV2ZXJ5IHBhdGggdGhhdCBmYWlscyBiZWZvcmUgdGhhdC5cbiAqXG4gKiBEZW5pZWQg4oaSIGB7IHN0YXR1czogJ2RlbmllZCcgfWAsIGFuc3dlcmVkIG9uIGByZXNgIHdoZW4gZ2l2ZW4uXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiByZXNlcnZlUXVvdGFTbG90KG9wdHM6IFF1b3RhUmVzZXJ2YXRpb25PcHRpb25zKTogUHJvbWlzZTxRdW90YVNsb3RSZXNlcnZhdGlvbj4ge1xuICBjb25zdCB7IHF1b3RhU2VydmljZSwgb3JnSWQsIHR5cGUsIGxvZ1dhcm4sIGF0dHJpYnV0aW9uIH0gPSBvcHRzO1xuICBjb25zdCBhbW91bnQgPSBvcHRzLmFtb3VudCA/PyAxO1xuICBjb25zdCBzZXJ2aWNlQXV0aCA9IGdldFNlcnZpY2VBdXRoSGVhZGVyKHsgc2VydmljZU5hbWU6IG9wdHMuc2VydmljZU5hbWUgPz8gc2VydmljZUlkZW50aXR5KCksIG9yZ0lkLCByb2xlOiAnbWVtYmVyJyB9KTtcblxuICAvLyBSZXNlcnZlIGF0b21pY2FsbHkgQkVGT1JFIGFueSB3b3JrOiB0d28gY29uY3VycmVudCByZXF1ZXN0cyBhdCB0aGUgbGltaXRcbiAgLy8gY2FuJ3QgYm90aCBwYXNzLiBBdHRyaWJ1dGlvbiBkZWZhdWx0cyB0byB0aGUgYW1iaWVudCByZXF1ZXN0IGNvbnRleHRcbiAgLy8gKHByaW5jaXBhbCArIHJlcXVlc3QgaWQpIGluc2lkZSB0aGUgcXVvdGEgY2xpZW50LlxuICBjb25zdCByZXNlcnZhdGlvbiA9IGF3YWl0IHJlc2VydmVRdW90YShxdW90YVNlcnZpY2UsIG9yZ0lkLCB0eXBlLCBzZXJ2aWNlQXV0aCwgYW1vdW50LCBhdHRyaWJ1dGlvbik7XG4gIGlmIChyZXNlcnZhdGlvbi5leGNlZWRlZCkge1xuICAgIGlmIChvcHRzLnJlcykgc2VuZFF1b3RhUmVzZXJ2ZURlbmllZChvcHRzLnJlcywgdHlwZSwgcmVzZXJ2YXRpb24pO1xuICAgIHJldHVybiB7IHN0YXR1czogJ2RlbmllZCcsIHJlc2VydmF0aW9uIH07XG4gIH1cblxuICBsZXQgY29uc3VtZWQgPSBmYWxzZTtcbiAgbGV0IHJlZnVuZGVkID0gZmFsc2U7XG4gIGNvbnN0IHNsb3Q6IFF1b3RhU2xvdCA9IHtcbiAgICBzZXJ2aWNlQXV0aCxcbiAgICByZXNlcnZhdGlvbixcbiAgICBtYXJrQ29uc3VtZWQ6ICgpID0+IHsgY29uc3VtZWQgPSB0cnVlOyB9LFxuICAgIHJlZnVuZDogKCkgPT4ge1xuICAgICAgaWYgKHJlZnVuZGVkIHx8IGNvbnN1bWVkKSByZXR1cm47XG4gICAgICByZWZ1bmRlZCA9IHRydWU7XG4gICAgICAvLyBUaGUgcmVzZXJ2ZWQgcmVzZXRBdCBrZWVwcyBhIHBlcmlvZCByb2xsb3ZlciBmcm9tIGJlaW5nIGRvdWJsZS1jaGFyZ2VkLlxuICAgICAgZGVjcmVtZW50UXVvdGEocXVvdGFTZXJ2aWNlLCBvcmdJZCwgdHlwZSwgc2VydmljZUF1dGgsIGxvZ1dhcm4sIGFtb3VudCwgcmVzZXJ2YXRpb24ucXVvdGEucmVzZXRBdCwgYXR0cmlidXRpb24pO1xuICAgIH0sXG4gIH07XG4gIHJldHVybiB7IHN0YXR1czogJ3Jlc2VydmVkJywgc2xvdCB9O1xufVxuXG4vKipcbiAqIFJ1biBgYm9keWAgYWdhaW5zdCBhIHJlc2VydmVkIHNsb3QgYW5kIHNldHRsZSBpdCBieSBPTkUgcnVsZToga2VlcCBpdCBvbmNlXG4gKiB0aGUgcmVzb3VyY2Ugd2FzIGNvbnN1bWVkOyByZWZ1bmQgaXQgaWYgdGhlIGJvZHkgZmFpbHMgZmlyc3QuIFNoYXJlZCBieVxuICoge0BsaW5rIHdpdGhRdW90YVJlc2VydmF0aW9ufSBhbmQgYXBpLXNlcnZlcidzIEFJIHJlc2VydmF0aW9uLlxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gcnVuV2l0aFNsb3Q8VCwgUyBleHRlbmRzIFF1b3RhU2xvdD4oXG4gIHNsb3Q6IFMsXG4gIGJvZHk6IChzbG90OiBTKSA9PiBQcm9taXNlPFQ+LFxuICBvbkVycm9yPzogKGVycm9yOiB1bmtub3duKSA9PiB2b2lkIHwgUHJvbWlzZTx2b2lkPixcbik6IFByb21pc2U8UXVvdGFSZXNlcnZhdGlvbk91dGNvbWU8VD4+IHtcbiAgdHJ5IHtcbiAgICByZXR1cm4geyBzdGF0dXM6ICdkb25lJywgdmFsdWU6IGF3YWl0IGJvZHkoc2xvdCkgfTtcbiAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAvLyBgcmVmdW5kKClgIGlzIGl0c2VsZiBhIG5vLW9wIG9uY2UgdGhlIHNsb3Qgd2FzIG1hcmtlZCBjb25zdW1lZC5cbiAgICBjb25zdCBlcnJvclNheXNDb25zdW1lZCA9IChlcnJvciBhcyB7IHByb3ZpZGVyQ29udGFjdGVkPzogdW5rbm93biB9IHwgbnVsbCk/LnByb3ZpZGVyQ29udGFjdGVkID09PSB0cnVlO1xuICAgIGlmICghZXJyb3JTYXlzQ29uc3VtZWQpIHNsb3QucmVmdW5kKCk7XG4gICAgaWYgKCFvbkVycm9yKSB0aHJvdyBlcnJvcjtcbiAgICBhd2FpdCBvbkVycm9yKGVycm9yKTtcbiAgICByZXR1cm4geyBzdGF0dXM6ICdmYWlsZWQnLCBlcnJvciB9O1xuICB9XG59XG5cbi8qKlxuICogUmVzZXJ2ZSBvbmUgcXVvdGEgc2xvdCwgcnVuIGBib2R5YCwgYW5kIHNldHRsZSB0aGUgc2xvdCBieSBPTkUgcnVsZTpcbiAqIGtlZXAgaXQgb25jZSB0aGUgcmVzb3VyY2Ugd2FzIGNvbnN1bWVkOyByZWZ1bmQgaXQgaWYgdGhlIGJvZHkgZmFpbHMgZmlyc3QuXG4gKlxuICogLSBEZW5pZWQg4oaSIGB7IHN0YXR1czogJ2RlbmllZCcgfWAgKGFuc3dlcmVkIG9uIGByZXNgIHdoZW4gZ2l2ZW4pOyBgYm9keWAgbmV2ZXIgcnVucy5cbiAqIC0gYGJvZHlgIHJlc29sdmVzIOKGkiB0aGUgc2xvdCBpcyBrZXB0ICh1bmxlc3MgYGJvZHlgIGNhbGxlZCBgc2xvdC5yZWZ1bmQoKWBcbiAqICAgQkVGT1JFIG1hcmtpbmcgaXQgY29uc3VtZWQg4oCUIGEgcmVmdW5kIGFmdGVyIGBtYXJrQ29uc3VtZWQoKWAgaXMgaWdub3JlZCkuXG4gKiAtIGBib2R5YCB0aHJvd3Mg4oaSIHJlZnVuZGVkIHVubGVzcyBjb25zdW1lZCDigJQgbWFya2VkIHZpYSBgc2xvdC5tYXJrQ29uc3VtZWQoKWBcbiAqICAgb3Igc2lnbmFsbGVkIGJ5IHRoZSBlcnJvciBpdHNlbGYgY2FycnlpbmcgYHByb3ZpZGVyQ29udGFjdGVkID09PSB0cnVlYFxuICogICAoYW4gQUkgcm91bmQtdHJpcCB0aGF0IGNvbXBsZXRlZCBidXQgcHJvZHVjZWQgbm90aGluZyB1c2FibGUpLiBUaGUgZXJyb3IgaXNcbiAqICAgdGhlbiBwYXNzZWQgdG8gYG9uRXJyb3JgLCBvciByZXRocm93biB3aGVuIHRoZXJlIGlzIG5vbmUuXG4gKlxuICogVGhlIHJlc2VydmUgYW5kIHJlZnVuZCBhdXRoZW50aWNhdGUgd2l0aCBhIG1pbnRlZCBzZXJ2aWNlIHRva2VuLCBuZXZlciB0aGVcbiAqIGVuZC11c2VyIGJlYXJlcjogdGhlIHF1b3RhIGluY3JlbWVudCBlbmRwb2ludCByZWplY3RzIHVzZXIgcHJpbmNpcGFscy5cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHdpdGhRdW90YVJlc2VydmF0aW9uPFQ+KFxuICBvcHRzOiBRdW90YVJlc2VydmF0aW9uT3B0aW9ucyxcbiAgYm9keTogKHNsb3Q6IFF1b3RhU2xvdCkgPT4gUHJvbWlzZTxUPixcbiAgb25FcnJvcj86IChlcnJvcjogdW5rbm93bikgPT4gdm9pZCB8IFByb21pc2U8dm9pZD4sXG4pOiBQcm9taXNlPFF1b3RhUmVzZXJ2YXRpb25PdXRjb21lPFQ+PiB7XG4gIGNvbnN0IHJlc2VydmVkID0gYXdhaXQgcmVzZXJ2ZVF1b3RhU2xvdChvcHRzKTtcbiAgaWYgKHJlc2VydmVkLnN0YXR1cyA9PT0gJ2RlbmllZCcpIHJldHVybiByZXNlcnZlZDtcbiAgcmV0dXJuIHJ1bldpdGhTbG90KHJlc2VydmVkLnNsb3QsIGJvZHksIG9uRXJyb3IpO1xufVxuIl19
|