@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
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { type AiKeySource, type QuotaReserveResult, type QuotaUsageAttribution } from '@pipeline-builder/api-core';
|
|
2
|
+
import type { Request } from 'express';
|
|
3
|
+
import { type QuotaReservationOptions, type QuotaReservationOutcome, type QuotaSlot } from './quota-reservation.js';
|
|
4
|
+
/**
|
|
5
|
+
* Which product surface an AI call belongs to — the usage ledger's `feature`
|
|
6
|
+
* dimension. `agent-tool:<name>` is a generation an agent TOOL runs in-process
|
|
7
|
+
* (its own slot, beside the turn's).
|
|
8
|
+
*/
|
|
9
|
+
export type AiFeature = 'ask' | 'agent' | `agent-tool:${string}` | 'pipeline-generate' | 'plugin-generate' | 'report-summary';
|
|
10
|
+
/** The part of a resolved model selection the reservation reads (ai-core `ResolvedModelSelection` fits). */
|
|
11
|
+
export interface AiCallSelection {
|
|
12
|
+
provider: string;
|
|
13
|
+
modelId: string;
|
|
14
|
+
keySource: AiKeySource;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Why an AI call spent no `aiCalls` unit:
|
|
18
|
+
* - `byok` — the org's own key or the caller's request key served it
|
|
19
|
+
* (`keySource !== 'platform'`): the customer pays the provider, not us;
|
|
20
|
+
* - `impersonation` — a sysadmin impersonation session: vendor staff neither
|
|
21
|
+
* spend the tenant's budget nor get locked out by it (mirrors the apiCalls
|
|
22
|
+
* exemption; the call is still audited);
|
|
23
|
+
* - `unweighted` — the model's `AI_MODEL_WEIGHTS` weight is 0 (by default the
|
|
24
|
+
* self-hosted OpenAI-compatible provider).
|
|
25
|
+
* A waived call is still recorded in the usage ledger (zero units, its tokens).
|
|
26
|
+
*/
|
|
27
|
+
export type AiSlotWaiver = 'byok' | 'impersonation' | 'unweighted';
|
|
28
|
+
/** Token counts as the AI SDK / ai-core report them (missing → 0). */
|
|
29
|
+
export interface AiCallTokens {
|
|
30
|
+
inputTokens?: number;
|
|
31
|
+
outputTokens?: number;
|
|
32
|
+
}
|
|
33
|
+
/** A settled-by-rule `aiCalls` slot, plus what the AI path needs on top of {@link QuotaSlot}. */
|
|
34
|
+
export interface AiCallSlot extends QuotaSlot {
|
|
35
|
+
/** Units reserved: the model's weight, or 0 when {@link waived}. */
|
|
36
|
+
readonly amount: number;
|
|
37
|
+
/** Set when no unit was reserved, and why. */
|
|
38
|
+
readonly waived?: AiSlotWaiver;
|
|
39
|
+
/** The attribution the reserve, refund and usage report carry. */
|
|
40
|
+
readonly attribution: QuotaUsageAttribution;
|
|
41
|
+
/**
|
|
42
|
+
* Report the call's token usage to the usage ledger (once; later calls are
|
|
43
|
+
* ignored). Fire-and-forget. Call it after the call settles — success, abort or
|
|
44
|
+
* failure — with whatever usage the provider reported.
|
|
45
|
+
*/
|
|
46
|
+
reportUsage(tokens: AiCallTokens | undefined): void;
|
|
47
|
+
}
|
|
48
|
+
export interface AiCallReservationOptions extends Omit<QuotaReservationOptions, 'type' | 'amount' | 'attribution'> {
|
|
49
|
+
feature: AiFeature;
|
|
50
|
+
/**
|
|
51
|
+
* The inbound request, when there is one: its route pattern + verified
|
|
52
|
+
* principal become the attribution, and an impersonation session waives the
|
|
53
|
+
* slot. Absent for scheduled work, which passes {@link attribution} instead.
|
|
54
|
+
*/
|
|
55
|
+
req?: Pick<Request, 'user' | 'route' | 'method' | 'baseUrl' | 'params' | 'headers'>;
|
|
56
|
+
/** Attribution merged OVER the request's (a scheduler names its principal + route here). */
|
|
57
|
+
attribution?: QuotaUsageAttribution;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Reserve the `aiCalls` slot for ONE AI call on an already-resolved model —
|
|
61
|
+
* or waive it — and return the handle; the caller settles it (`markConsumed()`
|
|
62
|
+
* on the provider's first response, `refund()` on a pre-contact failure,
|
|
63
|
+
* `reportUsage()` once settled). The primitive under
|
|
64
|
+
* {@link withAiCallReservation}, for work that does not fit one callback (an
|
|
65
|
+
* agent tool's in-process generation, a scheduled report summary).
|
|
66
|
+
*
|
|
67
|
+
* The model is resolved FIRST because it decides the charge:
|
|
68
|
+
* - a BYOK key (`keySource` `org` / `request`), an impersonation session or a
|
|
69
|
+
* weight-0 model reserves NOTHING ({@link AiSlotWaiver});
|
|
70
|
+
* - otherwise the reservation is `aiCallWeight(selection)` units (1 unless
|
|
71
|
+
* `AI_MODEL_WEIGHTS` says otherwise), attributed to the route, principal,
|
|
72
|
+
* feature, model and key source.
|
|
73
|
+
* The quota service also applies the org's optional AI controls to that
|
|
74
|
+
* reservation (per-member share, token budget) and answers a distinct 429 code.
|
|
75
|
+
*/
|
|
76
|
+
export declare function reserveAiCallSlot(opts: AiCallReservationOptions, selection: AiCallSelection): Promise<{
|
|
77
|
+
status: 'denied';
|
|
78
|
+
reservation: QuotaReserveResult;
|
|
79
|
+
} | {
|
|
80
|
+
status: 'reserved';
|
|
81
|
+
slot: AiCallSlot;
|
|
82
|
+
}>;
|
|
83
|
+
/**
|
|
84
|
+
* Resolve the model, reserve (or waive) its `aiCalls` slot, run `body`, and
|
|
85
|
+
* settle by the {@link withQuotaReservation} rule — keep once consumed, refund
|
|
86
|
+
* when the body fails first.
|
|
87
|
+
*
|
|
88
|
+
* `resolve` runs BEFORE any reservation (its result decides the charge — see
|
|
89
|
+
* {@link reserveAiCallSlot}); a resolution failure (AI switched off, an
|
|
90
|
+
* unloadable org key, nothing configured) goes to `onError` with no slot taken.
|
|
91
|
+
* Denied → `{ status: 'denied' }`, answered on `res` when given.
|
|
92
|
+
*/
|
|
93
|
+
export declare function withAiCallReservation<T, S extends AiCallSelection>(opts: AiCallReservationOptions & {
|
|
94
|
+
resolve: () => Promise<S>;
|
|
95
|
+
}, body: (slot: AiCallSlot, selection: S) => Promise<T>, onError?: (error: unknown) => void | Promise<void>): Promise<QuotaReservationOutcome<T>>;
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
// Copyright 2026 Pipeline Builder Contributors
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
import { aiCallWeight, emitCounter, getServiceAuthHeader, quotaAttributionFromRequest, serviceIdentity, } from '@pipeline-builder/api-core';
|
|
4
|
+
import { reserveQuotaSlot, runWithSlot, } from './quota-reservation.js';
|
|
5
|
+
/** The synthetic reservation a waived slot carries (nothing was reserved). */
|
|
6
|
+
function waivedReservation() {
|
|
7
|
+
return { exceeded: false, quota: { type: 'aiCalls', limit: -1, used: 0, remaining: -1 } };
|
|
8
|
+
}
|
|
9
|
+
/** Attribution for one AI call: request (or explicit) + feature, model, keySource. */
|
|
10
|
+
function aiAttribution(opts, selection) {
|
|
11
|
+
return {
|
|
12
|
+
...(opts.req ? quotaAttributionFromRequest(opts.req) : {}),
|
|
13
|
+
...opts.attribution,
|
|
14
|
+
feature: opts.feature,
|
|
15
|
+
model: selection.modelId.slice(0, 200),
|
|
16
|
+
keySource: selection.keySource,
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
function waiverFor(opts, selection, weight) {
|
|
20
|
+
if (selection.keySource !== 'platform')
|
|
21
|
+
return 'byok';
|
|
22
|
+
if (opts.req?.user?.impersonatorId)
|
|
23
|
+
return 'impersonation';
|
|
24
|
+
if (weight <= 0)
|
|
25
|
+
return 'unweighted';
|
|
26
|
+
return undefined;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Reserve the `aiCalls` slot for ONE AI call on an already-resolved model —
|
|
30
|
+
* or waive it — and return the handle; the caller settles it (`markConsumed()`
|
|
31
|
+
* on the provider's first response, `refund()` on a pre-contact failure,
|
|
32
|
+
* `reportUsage()` once settled). The primitive under
|
|
33
|
+
* {@link withAiCallReservation}, for work that does not fit one callback (an
|
|
34
|
+
* agent tool's in-process generation, a scheduled report summary).
|
|
35
|
+
*
|
|
36
|
+
* The model is resolved FIRST because it decides the charge:
|
|
37
|
+
* - a BYOK key (`keySource` `org` / `request`), an impersonation session or a
|
|
38
|
+
* weight-0 model reserves NOTHING ({@link AiSlotWaiver});
|
|
39
|
+
* - otherwise the reservation is `aiCallWeight(selection)` units (1 unless
|
|
40
|
+
* `AI_MODEL_WEIGHTS` says otherwise), attributed to the route, principal,
|
|
41
|
+
* feature, model and key source.
|
|
42
|
+
* The quota service also applies the org's optional AI controls to that
|
|
43
|
+
* reservation (per-member share, token budget) and answers a distinct 429 code.
|
|
44
|
+
*/
|
|
45
|
+
export async function reserveAiCallSlot(opts, selection) {
|
|
46
|
+
const weight = aiCallWeight(selection);
|
|
47
|
+
const waived = waiverFor(opts, selection, weight);
|
|
48
|
+
const attribution = aiAttribution(opts, selection);
|
|
49
|
+
let base;
|
|
50
|
+
if (waived) {
|
|
51
|
+
emitCounter('ai_quota_waived_total', { feature: featureLabel(opts.feature), reason: waived });
|
|
52
|
+
// Nothing reserved, so nothing to keep or give back.
|
|
53
|
+
base = {
|
|
54
|
+
serviceAuth: getServiceAuthHeader({ serviceName: opts.serviceName ?? serviceIdentity(), orgId: opts.orgId, role: 'member' }),
|
|
55
|
+
reservation: waivedReservation(),
|
|
56
|
+
markConsumed: () => undefined,
|
|
57
|
+
refund: () => undefined,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
const reserved = await reserveQuotaSlot({ ...opts, type: 'aiCalls', amount: weight, attribution });
|
|
62
|
+
if (reserved.status === 'denied')
|
|
63
|
+
return reserved;
|
|
64
|
+
base = reserved.slot;
|
|
65
|
+
}
|
|
66
|
+
let consumed = false;
|
|
67
|
+
let reported = false;
|
|
68
|
+
const slot = {
|
|
69
|
+
serviceAuth: base.serviceAuth,
|
|
70
|
+
reservation: base.reservation,
|
|
71
|
+
amount: waived ? 0 : weight,
|
|
72
|
+
...(waived ? { waived } : {}),
|
|
73
|
+
attribution,
|
|
74
|
+
markConsumed: () => { consumed = true; base.markConsumed(); },
|
|
75
|
+
refund: () => base.refund(),
|
|
76
|
+
reportUsage: (tokens) => {
|
|
77
|
+
if (reported)
|
|
78
|
+
return;
|
|
79
|
+
reported = true;
|
|
80
|
+
const tokensIn = tokens?.inputTokens ?? 0;
|
|
81
|
+
const tokensOut = tokens?.outputTokens ?? 0;
|
|
82
|
+
// A call that never reached the provider and spent no tokens has nothing
|
|
83
|
+
// to record (its reservation, if any, was refunded and ledgered as such).
|
|
84
|
+
if (tokensIn + tokensOut === 0 && !(waived && consumed))
|
|
85
|
+
return;
|
|
86
|
+
void opts.quotaService.reportUsage?.(opts.orgId, 'aiCalls', base.serviceAuth, { tokensIn, tokensOut }, attribution);
|
|
87
|
+
},
|
|
88
|
+
};
|
|
89
|
+
return { status: 'reserved', slot };
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Resolve the model, reserve (or waive) its `aiCalls` slot, run `body`, and
|
|
93
|
+
* settle by the {@link withQuotaReservation} rule — keep once consumed, refund
|
|
94
|
+
* when the body fails first.
|
|
95
|
+
*
|
|
96
|
+
* `resolve` runs BEFORE any reservation (its result decides the charge — see
|
|
97
|
+
* {@link reserveAiCallSlot}); a resolution failure (AI switched off, an
|
|
98
|
+
* unloadable org key, nothing configured) goes to `onError` with no slot taken.
|
|
99
|
+
* Denied → `{ status: 'denied' }`, answered on `res` when given.
|
|
100
|
+
*/
|
|
101
|
+
export async function withAiCallReservation(opts, body, onError) {
|
|
102
|
+
let selection;
|
|
103
|
+
try {
|
|
104
|
+
selection = await opts.resolve();
|
|
105
|
+
}
|
|
106
|
+
catch (error) {
|
|
107
|
+
if (!onError)
|
|
108
|
+
throw error;
|
|
109
|
+
await onError(error);
|
|
110
|
+
return { status: 'failed', error };
|
|
111
|
+
}
|
|
112
|
+
const reserved = await reserveAiCallSlot(opts, selection);
|
|
113
|
+
if (reserved.status === 'denied')
|
|
114
|
+
return reserved;
|
|
115
|
+
return runWithSlot(reserved.slot, (slot) => body(slot, selection), onError);
|
|
116
|
+
}
|
|
117
|
+
/** Bounded metric label: `agent-tool:<name>` collapses to `agent-tool`. */
|
|
118
|
+
function featureLabel(feature) {
|
|
119
|
+
return feature.startsWith('agent-tool:') ? 'agent-tool' : feature;
|
|
120
|
+
}
|
|
121
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWktY2FsbC1yZXNlcnZhdGlvbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9hcGkvYWktY2FsbC1yZXNlcnZhdGlvbi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSwrQ0FBK0M7QUFDL0Msc0NBQXNDO0FBRXRDLE9BQU8sRUFDTCxZQUFZLEVBQ1osV0FBVyxFQUNYLG9CQUFvQixFQUNwQiwyQkFBMkIsRUFDM0IsZUFBZSxHQUloQixNQUFNLDRCQUE0QixDQUFDO0FBR3BDLE9BQU8sRUFDTCxnQkFBZ0IsRUFDaEIsV0FBVyxHQUlaLE1BQU0sd0JBQXdCLENBQUM7QUFxRWhDLDhFQUE4RTtBQUM5RSxTQUFTLGlCQUFpQjtJQUN4QixPQUFPLEVBQUUsUUFBUSxFQUFFLEtBQUssRUFBRSxLQUFLLEVBQUUsRUFBRSxJQUFJLEVBQUUsU0FBUyxFQUFFLEtBQUssRUFBRSxDQUFDLENBQUMsRUFBRSxJQUFJLEVBQUUsQ0FBQyxFQUFFLFNBQVMsRUFBRSxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUM7QUFDNUYsQ0FBQztBQUVELHNGQUFzRjtBQUN0RixTQUFTLGFBQWEsQ0FBQyxJQUE4QixFQUFFLFNBQTBCO0lBQy9FLE9BQU87UUFDTCxHQUFHLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsMkJBQTJCLENBQUMsSUFBSSxDQUFDLEdBQWMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7UUFDckUsR0FBRyxJQUFJLENBQUMsV0FBVztRQUNuQixPQUFPLEVBQUUsSUFBSSxDQUFDLE9BQU87UUFDckIsS0FBSyxFQUFFLFNBQVMsQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLENBQUMsRUFBRSxHQUFHLENBQUM7UUFDdEMsU0FBUyxFQUFFLFNBQVMsQ0FBQyxTQUFTO0tBQy9CLENBQUM7QUFDSixDQUFDO0FBRUQsU0FBUyxTQUFTLENBQUMsSUFBOEIsRUFBRSxTQUEwQixFQUFFLE1BQWM7SUFDM0YsSUFBSSxTQUFT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QUMsVUFBVSxDQUFDLGFBQWEsQ0FBQyxDQUFDLENBQUMsQ0FBQyxZQUFZLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQztBQUNwRSxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQ29weXJpZ2h0IDIwMjYgUGlwZWxpbmUgQnVpbGRlciBDb250cmlidXRvcnNcbi8vIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBcGFjaGUtMi4wXG5cbmltcG9ydCB7XG4gIGFpQ2FsbFdlaWdodCxcbiAgZW1pdENvdW50ZXIsXG4gIGdldFNlcnZpY2VBdXRoSGVhZGVyLFxuICBxdW90YUF0dHJpYnV0aW9uRnJvbVJlcXVlc3QsXG4gIHNlcnZpY2VJZGVudGl0eSxcbiAgdHlwZSBBaUtleVNvdXJjZSxcbiAgdHlwZSBRdW90YVJlc2VydmVSZXN1bHQsXG4gIHR5cGUgUXVvdGFVc2FnZUF0dHJpYnV0aW9uLFxufSBmcm9tICdAcGlwZWxpbmUtYnVpbGRlci9hcGktY29yZSc7XG5pbXBvcnQgdHlwZSB7IFJlcXVlc3QgfSBmcm9tICdleHByZXNzJztcblxuaW1wb3J0IHtcbiAgcmVzZXJ2ZVF1b3RhU2xvdCxcbiAgcnVuV2l0aFNsb3QsXG4gIHR5cGUgUXVvdGFSZXNlcnZhdGlvbk9wdGlvbnMsXG4gIHR5cGUgUXVvdGFSZXNlcnZhdGlvbk91dGNvbWUsXG4gIHR5cGUgUXVvdGFTbG90LFxufSBmcm9tICcuL3F1b3RhLXJlc2VydmF0aW9uLmpzJztcblxuLyoqXG4gKiBXaGljaCBwcm9kdWN0IHN1cmZhY2UgYW4gQUkgY2FsbCBiZWxvbmdzIHRvIOKAlCB0aGUgdXNhZ2UgbGVkZ2VyJ3MgYGZlYXR1cmVgXG4gKiBkaW1lbnNpb24uIGBhZ2VudC10b29sOjxuYW1lPmAgaXMgYSBnZW5lcmF0aW9uIGFuIGFnZW50IFRPT0wgcnVucyBpbi1wcm9jZXNzXG4gKiAoaXRzIG93biBzbG90LCBiZXNpZGUgdGhlIHR1cm4ncykuXG4gKi9cbmV4cG9ydCB0eXBlIEFpRmVhdHVyZSA9XG4gIHwgJ2FzaydcbiAgfCAnYWdlbnQnXG4gIHwgYGFnZW50LXRvb2w6JHtzdHJpbmd9YFxuICB8ICdwaXBlbGluZS1nZW5lcmF0ZSdcbiAgfCAncGx1Z2luLWdlbmVyYXRlJ1xuICB8ICdyZXBvcnQtc3VtbWFyeSc7XG5cbi8qKiBUaGUgcGFydCBvZiBhIHJlc29sdmVkIG1vZGVsIHNlbGVjdGlvbiB0aGUgcmVzZXJ2YXRpb24gcmVhZHMgKGFpLWNvcmUgYFJlc29sdmVkTW9kZWxTZWxlY3Rpb25gIGZpdHMpLiAqL1xuZXhwb3J0IGludGVyZmFjZSBBaUNhbGxTZWxlY3Rpb24ge1xuICBwcm92aWRlcjogc3RyaW5nO1xuICBtb2RlbElkOiBzdHJpbmc7XG4gIGtleVNvdXJjZTogQWlLZXlTb3VyY2U7XG59XG5cbi8qKlxuICogV2h5IGFuIEFJIGNhbGwgc3BlbnQgbm8gYGFpQ2FsbHNgIHVuaXQ6XG4gKiAgLSBgYnlva2Ag4oCUIHRoZSBvcmcncyBvd24ga2V5IG9yIHRoZSBjYWxsZXIncyByZXF1ZXN0IGtleSBzZXJ2ZWQgaXRcbiAqICAgIChga2V5U291cmNlICE9PSAncGxhdGZvcm0nYCk6IHRoZSBjdXN0b21lciBwYXlzIHRoZSBwcm92aWRlciwgbm90IHVzO1xuICogIC0gYGltcGVyc29uYXRpb25gIOKAlCBhIHN5c2FkbWluIGltcGVyc29uYXRpb24gc2Vzc2lvbjogdmVuZG9yIHN0YWZmIG5laXRoZXJcbiAqICAgIHNwZW5kIHRoZSB0ZW5hbnQncyBidWRnZXQgbm9yIGdldCBsb2NrZWQgb3V0IGJ5IGl0IChtaXJyb3JzIHRoZSBhcGlDYWxsc1xuICogICAgZXhlbXB0aW9uOyB0aGUgY2FsbCBpcyBzdGlsbCBhdWRpdGVkKTtcbiAqICAtIGB1bndlaWdodGVkYCDigJQgdGhlIG1vZGVsJ3MgYEFJX01PREVMX1dFSUdIVFNgIHdlaWdodCBpcyAwIChieSBkZWZhdWx0IHRoZVxuICogICAgc2VsZi1ob3N0ZWQgT3BlbkFJLWNvbXBhdGlibGUgcHJvdmlkZXIpLlxuICogQSB3YWl2ZWQgY2FsbCBpcyBzdGlsbCByZWNvcmRlZCBpbiB0aGUgdXNhZ2UgbGVkZ2VyICh6ZXJvIHVuaXRzLCBpdHMgdG9rZW5zKS5cbiAqL1xuZXhwb3J0IHR5cGUgQWlTbG90V2FpdmVyID0gJ2J5b2snIHwgJ2ltcGVyc29uYXRpb24nIHwgJ3Vud2VpZ2h0ZWQnO1xuXG4vKiogVG9rZW4gY291bnRzIGFzIHRoZSBBSSBTREsgLyBhaS1jb3JlIHJlcG9ydCB0aGVtIChtaXNzaW5nIOKGkiAwKS4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgQWlDYWxsVG9rZW5zIHtcbiAgaW5wdXRUb2tlbnM/OiBudW1iZXI7XG4gIG91dHB1dFRva2Vucz86IG51bWJlcjtcbn1cblxuLyoqIEEgc2V0dGxlZC1ieS1ydWxlIGBhaUNhbGxzYCBzbG90LCBwbHVzIHdoYXQgdGhlIEFJIHBhdGggbmVlZHMgb24gdG9wIG9mIHtAbGluayBRdW90YVNsb3R9LiAqL1xuZXhwb3J0IGludGVyZmFjZSBBaUNhbGxTbG90IGV4dGVuZHMgUXVvdGFTbG90IHtcbiAgLyoqIFVuaXRzIHJlc2VydmVkOiB0aGUgbW9kZWwncyB3ZWlnaHQsIG9yIDAgd2hlbiB7QGxpbmsgd2FpdmVkfS4gKi9cbiAgcmVhZG9ubHkgYW1vdW50OiBudW1iZXI7XG4gIC8qKiBTZXQgd2hlbiBubyB1bml0IHdhcyByZXNlcnZlZCwgYW5kIHdoeS4gKi9cbiAgcmVhZG9ubHkgd2FpdmVkPzogQWlTbG90V2FpdmVyO1xuICAvKiogVGhlIGF0dHJpYnV0aW9uIHRoZSByZXNlcnZlLCByZWZ1bmQgYW5kIHVzYWdlIHJlcG9ydCBjYXJyeS4gKi9cbiAgcmVhZG9ubHkgYXR0cmlidXRpb246IFF1b3RhVXNhZ2VBdHRyaWJ1dGlvbjtcbiAgLyoqXG4gICAqIFJlcG9ydCB0aGUgY2FsbCdzIHRva2VuIHVzYWdlIHRvIHRoZSB1c2FnZSBsZWRnZXIgKG9uY2U7IGxhdGVyIGNhbGxzIGFyZVxuICAgKiBpZ25vcmVkKS4gRmlyZS1hbmQtZm9yZ2V0LiBDYWxsIGl0IGFmdGVyIHRoZSBjYWxsIHNldHRsZXMg4oCUIHN1Y2Nlc3MsIGFib3J0IG9yXG4gICAqIGZhaWx1cmUg4oCUIHdpdGggd2hhdGV2ZXIgdXNhZ2UgdGhlIHByb3ZpZGVyIHJlcG9ydGVkLlxuICAgKi9cbiAgcmVwb3J0VXNhZ2UodG9rZW5zOiBBaUNhbGxUb2tlbnMgfCB1bmRlZmluZWQpOiB2b2lkO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIEFpQ2FsbFJlc2VydmF0aW9uT3B0aW9ucyBleHRlbmRzIE9taXQ8UXVvdGFSZXNlcnZhdGlvbk9wdGlvbnMsICd0eXBlJyB8ICdhbW91bnQnIHwgJ2F0dHJpYnV0aW9uJz4ge1xuICBmZWF0dXJlOiBBaUZlYXR1cmU7XG4gIC8qKlxuICAgKiBUaGUgaW5ib3VuZCByZXF1ZXN0LCB3aGVuIHRoZXJlIGlzIG9uZTogaXRzIHJvdXRlIHBhdHRlcm4gKyB2ZXJpZmllZFxuICAgKiBwcmluY2lwYWwgYmVjb21lIHRoZSBhdHRyaWJ1dGlvbiwgYW5kIGFuIGltcGVyc29uYXRpb24gc2Vzc2lvbiB3YWl2ZXMgdGhlXG4gICAqIHNsb3QuIEFic2VudCBmb3Igc2NoZWR1bGVkIHdvcmssIHdoaWNoIHBhc3NlcyB7QGxpbmsgYXR0cmlidXRpb259IGluc3RlYWQuXG4gICAqL1xuICByZXE/OiBQaWNrPFJlcXVlc3QsICd1c2VyJyB8ICdyb3V0ZScgfCAnbWV0aG9kJyB8ICdiYXNlVXJsJyB8ICdwYXJhbXMnIHwgJ2hlYWRlcnMnPjtcbiAgLyoqIEF0dHJpYnV0aW9uIG1lcmdlZCBPVkVSIHRoZSByZXF1ZXN0J3MgKGEgc2NoZWR1bGVyIG5hbWVzIGl0cyBwcmluY2lwYWwgKyByb3V0ZSBoZXJlKS4gKi9cbiAgYXR0cmlidXRpb24/OiBRdW90YVVzYWdlQXR0cmlidXRpb247XG59XG5cbi8qKiBUaGUgc3ludGhldGljIHJlc2VydmF0aW9uIGEgd2FpdmVkIHNsb3QgY2FycmllcyAobm90aGluZyB3YXMgcmVzZXJ2ZWQpLiAqL1xuZnVuY3Rpb24gd2FpdmVkUmVzZXJ2YXRpb24oKTogUXVvdGFSZXNlcnZlUmVzdWx0IHtcbiAgcmV0dXJuIHsgZXhjZWVkZWQ6IGZhbHNlLCBxdW90YTogeyB0eXBlOiAnYWlDYWxscycsIGxpbWl0OiAtMSwgdXNlZDogMCwgcmVtYWluaW5nOiAtMSB9IH07XG59XG5cbi8qKiBBdHRyaWJ1dGlvbiBmb3Igb25lIEFJIGNhbGw6IHJlcXVlc3QgKG9yIGV4cGxpY2l0KSArIGZlYXR1cmUsIG1vZGVsLCBrZXlTb3VyY2UuICovXG5mdW5jdGlvbiBhaUF0dHJpYnV0aW9uKG9wdHM6IEFpQ2FsbFJlc2VydmF0aW9uT3B0aW9ucywgc2VsZWN0aW9uOiBBaUNhbGxTZWxlY3Rpb24pOiBRdW90YVVzYWdlQXR0cmlidXRpb24ge1xuICByZXR1cm4ge1xuICAgIC4uLihvcHRzLnJlcSA/IHF1b3RhQXR0cmlidXRpb25Gcm9tUmVxdWVzdChvcHRzLnJlcSBhcyBSZXF1ZXN0KSA6IHt9KSxcbiAgICAuLi5vcHRzLmF0dHJpYnV0aW9uLFxuICAgIGZlYXR1cmU6IG9wdHMuZmVhdHVyZSxcbiAgICBtb2RlbDogc2VsZWN0aW9uLm1vZGVsSWQuc2xpY2UoMCwgMjAwKSxcbiAgICBrZXlTb3VyY2U6IHNlbGVjdGlvbi5rZXlTb3VyY2UsXG4gIH07XG59XG5cbmZ1bmN0aW9uIHdhaXZlckZvcihvcHRzOiBBaUNhbGxSZXNlcnZhdGlvbk9wdGlvbnMsIHNlbGVjdGlvbjogQWlDYWxsU2VsZWN0aW9uLCB3ZWlnaHQ6IG51bWJlcik6IEFpU2xvdFdhaXZlciB8IHVuZGVmaW5lZCB7XG4gIGlmIChzZWxlY3Rpb24ua2V5U291cmNlICE9PSAncGxhdGZvcm0nKSByZXR1cm4gJ2J5b2snO1xuICBpZiAob3B0cy5yZXE/LnVzZXI/LmltcGVyc29uYXRvcklkKSByZXR1cm4gJ2ltcGVyc29uYXRpb24nO1xuICBpZiAod2VpZ2h0IDw9IDApIHJldHVybiAndW53ZWlnaHRlZCc7XG4gIHJldHVybiB1bmRlZmluZWQ7XG59XG5cbi8qKlxuICogUmVzZXJ2ZSB0aGUgYGFpQ2FsbHNgIHNsb3QgZm9yIE9ORSBBSSBjYWxsIG9uIGFuIGFscmVhZHktcmVzb2x2ZWQgbW9kZWwg4oCUXG4gKiBvciB3YWl2ZSBpdCDigJQgYW5kIHJldHVybiB0aGUgaGFuZGxlOyB0aGUgY2FsbGVyIHNldHRsZXMgaXQgKGBtYXJrQ29uc3VtZWQoKWBcbiAqIG9uIHRoZSBwcm92aWRlcidzIGZpcnN0IHJlc3BvbnNlLCBgcmVmdW5kKClgIG9uIGEgcHJlLWNvbnRhY3QgZmFpbHVyZSxcbiAqIGByZXBvcnRVc2FnZSgpYCBvbmNlIHNldHRsZWQpLiBUaGUgcHJpbWl0aXZlIHVuZGVyXG4gKiB7QGxpbmsgd2l0aEFpQ2FsbFJlc2VydmF0aW9ufSwgZm9yIHdvcmsgdGhhdCBkb2VzIG5vdCBmaXQgb25lIGNhbGxiYWNrIChhblxuICogYWdlbnQgdG9vbCdzIGluLXByb2Nlc3MgZ2VuZXJhdGlvbiwgYSBzY2hlZHVsZWQgcmVwb3J0IHN1bW1hcnkpLlxuICpcbiAqIFRoZSBtb2RlbCBpcyByZXNvbHZlZCBGSVJTVCBiZWNhdXNlIGl0IGRlY2lkZXMgdGhlIGNoYXJnZTpcbiAqICAtIGEgQllPSyBrZXkgKGBrZXlTb3VyY2VgIGBvcmdgIC8gYHJlcXVlc3RgKSwgYW4gaW1wZXJzb25hdGlvbiBzZXNzaW9uIG9yIGFcbiAqICAgIHdlaWdodC0wIG1vZGVsIHJlc2VydmVzIE5PVEhJTkcgKHtAbGluayBBaVNsb3RXYWl2ZXJ9KTtcbiAqICAtIG90aGVyd2lzZSB0aGUgcmVzZXJ2YXRpb24gaXMgYGFpQ2FsbFdlaWdodChzZWxlY3Rpb24pYCB1bml0cyAoMSB1bmxlc3NcbiAqICAgIGBBSV9NT0RFTF9XRUlHSFRTYCBzYXlzIG90aGVyd2lzZSksIGF0dHJpYnV0ZWQgdG8gdGhlIHJvdXRlLCBwcmluY2lwYWwsXG4gKiAgICBmZWF0dXJlLCBtb2RlbCBhbmQga2V5IHNvdXJjZS5cbiAqIFRoZSBxdW90YSBzZXJ2aWNlIGFsc28gYXBwbGllcyB0aGUgb3JnJ3Mgb3B0aW9uYWwgQUkgY29udHJvbHMgdG8gdGhhdFxuICogcmVzZXJ2YXRpb24gKHBlci1tZW1iZXIgc2hhcmUsIHRva2VuIGJ1ZGdldCkgYW5kIGFuc3dlcnMgYSBkaXN0aW5jdCA0MjkgY29kZS5cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHJlc2VydmVBaUNhbGxTbG90KFxuICBvcHRzOiBBaUNhbGxSZXNlcnZhdGlvbk9wdGlvbnMsXG4gIHNlbGVjdGlvbjogQWlDYWxsU2VsZWN0aW9uLFxuKTogUHJvbWlzZTx7IHN0YXR1czogJ2RlbmllZCc7IHJlc2VydmF0aW9uOiBRdW90YVJlc2VydmVSZXN1bHQgfSB8IHsgc3RhdHVzOiAncmVzZXJ2ZWQnOyBzbG90OiBBaUNhbGxTbG90IH0+IHtcbiAgY29uc3Qgd2VpZ2h0ID0gYWlDYWxsV2VpZ2h0KHNlbGVjdGlvbik7XG4gIGNvbnN0IHdhaXZlZCA9IHdhaXZlckZvcihvcHRzLCBzZWxlY3Rpb24sIHdlaWdodCk7XG4gIGNvbnN0IGF0dHJpYnV0aW9uID0gYWlBdHRyaWJ1dGlvbihvcHRzLCBzZWxlY3Rpb24pO1xuXG4gIGxldCBiYXNlOiBRdW90YVNsb3Q7XG4gIGlmICh3YWl2ZWQpIHtcbiAgICBlbWl0Q291bnRlcignYWlfcXVvdGFfd2FpdmVkX3RvdGFsJywgeyBmZWF0dXJlOiBmZWF0dXJlTGFiZWwob3B0cy5mZWF0dXJlKSwgcmVhc29uOiB3YWl2ZWQgfSk7XG4gICAgLy8gTm90aGluZyByZXNlcnZlZCwgc28gbm90aGluZyB0byBrZWVwIG9yIGdpdmUgYmFjay5cbiAgICBiYXNlID0ge1xuICAgICAgc2VydmljZUF1dGg6IGdldFNlcnZpY2VBdXRoSGVhZGVyKHsgc2VydmljZU5hbWU6IG9wdHMuc2VydmljZU5hbWUgPz8gc2VydmljZUlkZW50aXR5KCksIG9yZ0lkOiBvcHRzLm9yZ0lkLCByb2xlOiAnbWVtYmVyJyB9KSxcbiAgICAgIHJlc2VydmF0aW9uOiB3YWl2ZWRSZXNlcnZhdGlvbigpLFxuICAgICAgbWFya0NvbnN1bWVkOiAoKSA9PiB1bmRlZmluZWQsXG4gICAgICByZWZ1bmQ6ICgpID0+IHVuZGVmaW5lZCxcbiAgICB9O1xuICB9IGVsc2Uge1xuICAgIGNvbnN0IHJlc2VydmVkID0gYXdhaXQgcmVzZXJ2ZVF1b3RhU2xvdCh7IC4uLm9wdHMsIHR5cGU6ICdhaUNhbGxzJywgYW1vdW50OiB3ZWlnaHQsIGF0dHJpYnV0aW9uIH0pO1xuICAgIGlmIChyZXNlcnZlZC5zdGF0dXMgPT09ICdkZW5pZWQnKSByZXR1cm4gcmVzZXJ2ZWQ7XG4gICAgYmFzZSA9IHJlc2VydmVkLnNsb3Q7XG4gIH1cblxuICBsZXQgY29uc3VtZWQgPSBmYWxzZTtcbiAgbGV0IHJlcG9ydGVkID0gZmFsc2U7XG4gIGNvbnN0IHNsb3Q6IEFpQ2FsbFNsb3QgPSB7XG4gICAgc2VydmljZUF1dGg6IGJhc2Uuc2VydmljZUF1dGgsXG4gICAgcmVzZXJ2YXRpb246IGJhc2UucmVzZXJ2YXRpb24sXG4gICAgYW1vdW50OiB3YWl2ZWQgPyAwIDogd2VpZ2h0LFxuICAgIC4uLih3YWl2ZWQgPyB7IHdhaXZlZCB9IDoge30pLFxuICAgIGF0dHJpYnV0aW9uLFxuICAgIG1hcmtDb25zdW1lZDogKCkgPT4geyBjb25zdW1lZCA9IHRydWU7IGJhc2UubWFya0NvbnN1bWVkKCk7IH0sXG4gICAgcmVmdW5kOiAoKSA9PiBiYXNlLnJlZnVuZCgpLFxuICAgIHJlcG9ydFVzYWdlOiAodG9rZW5zKSA9PiB7XG4gICAgICBpZiAocmVwb3J0ZWQpIHJldHVybjtcbiAgICAgIHJlcG9ydGVkID0gdHJ1ZTtcbiAgICAgIGNvbnN0IHRva2Vuc0luID0gdG9rZW5zPy5pbnB1dFRva2VucyA/PyAwO1xuICAgICAgY29uc3QgdG9rZW5zT3V0ID0gdG9rZW5zPy5vdXRwdXRUb2tlbnMgPz8gMDtcbiAgICAgIC8vIEEgY2FsbCB0aGF0IG5ldmVyIHJlYWNoZWQgdGhlIHByb3ZpZGVyIGFuZCBzcGVudCBubyB0b2tlbnMgaGFzIG5vdGhpbmdcbiAgICAgIC8vIHRvIHJlY29yZCAoaXRzIHJlc2VydmF0aW9uLCBpZiBhbnksIHdhcyByZWZ1bmRlZCBhbmQgbGVkZ2VyZWQgYXMgc3VjaCkuXG4gICAgICBpZiAodG9rZW5zSW4gKyB0b2tlbnNPdXQgPT09IDAgJiYgISh3YWl2ZWQgJiYgY29uc3VtZWQpKSByZXR1cm47XG4gICAgICB2b2lkIG9wdHMucXVvdGFTZXJ2aWNlLnJlcG9ydFVzYWdlPy4ob3B0cy5vcmdJZCwgJ2FpQ2FsbHMnLCBiYXNlLnNlcnZpY2VBdXRoLCB7IHRva2Vuc0luLCB0b2tlbnNPdXQgfSwgYXR0cmlidXRpb24pO1xuICAgIH0sXG4gIH07XG4gIHJldHVybiB7IHN0YXR1czogJ3Jlc2VydmVkJywgc2xvdCB9O1xufVxuXG4vKipcbiAqIFJlc29sdmUgdGhlIG1vZGVsLCByZXNlcnZlIChvciB3YWl2ZSkgaXRzIGBhaUNhbGxzYCBzbG90LCBydW4gYGJvZHlgLCBhbmRcbiAqIHNldHRsZSBieSB0aGUge0BsaW5rIHdpdGhRdW90YVJlc2VydmF0aW9ufSBydWxlIOKAlCBrZWVwIG9uY2UgY29uc3VtZWQsIHJlZnVuZFxuICogd2hlbiB0aGUgYm9keSBmYWlscyBmaXJzdC5cbiAqXG4gKiBgcmVzb2x2ZWAgcnVucyBCRUZPUkUgYW55IHJlc2VydmF0aW9uIChpdHMgcmVzdWx0IGRlY2lkZXMgdGhlIGNoYXJnZSDigJQgc2VlXG4gKiB7QGxpbmsgcmVzZXJ2ZUFpQ2FsbFNsb3R9KTsgYSByZXNvbHV0aW9uIGZhaWx1cmUgKEFJIHN3aXRjaGVkIG9mZiwgYW5cbiAqIHVubG9hZGFibGUgb3JnIGtleSwgbm90aGluZyBjb25maWd1cmVkKSBnb2VzIHRvIGBvbkVycm9yYCB3aXRoIG5vIHNsb3QgdGFrZW4uXG4gKiBEZW5pZWQg4oaSIGB7IHN0YXR1czogJ2RlbmllZCcgfWAsIGFuc3dlcmVkIG9uIGByZXNgIHdoZW4gZ2l2ZW4uXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiB3aXRoQWlDYWxsUmVzZXJ2YXRpb248VCwgUyBleHRlbmRzIEFpQ2FsbFNlbGVjdGlvbj4oXG4gIG9wdHM6IEFpQ2FsbFJlc2VydmF0aW9uT3B0aW9ucyAmIHsgcmVzb2x2ZTogKCkgPT4gUHJvbWlzZTxTPiB9LFxuICBib2R5OiAoc2xvdDogQWlDYWxsU2xvdCwgc2VsZWN0aW9uOiBTKSA9PiBQcm9taXNlPFQ+LFxuICBvbkVycm9yPzogKGVycm9yOiB1bmtub3duKSA9PiB2b2lkIHwgUHJvbWlzZTx2b2lkPixcbik6IFByb21pc2U8UXVvdGFSZXNlcnZhdGlvbk91dGNvbWU8VD4+IHtcbiAgbGV0IHNlbGVjdGlvbjogUztcbiAgdHJ5IHtcbiAgICBzZWxlY3Rpb24gPSBhd2FpdCBvcHRzLnJlc29sdmUoKTtcbiAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICBpZiAoIW9uRXJyb3IpIHRocm93IGVycm9yO1xuICAgIGF3YWl0IG9uRXJyb3IoZXJyb3IpO1xuICAgIHJldHVybiB7IHN0YXR1czogJ2ZhaWxlZCcsIGVycm9yIH07XG4gIH1cbiAgY29uc3QgcmVzZXJ2ZWQgPSBhd2FpdCByZXNlcnZlQWlDYWxsU2xvdChvcHRzLCBzZWxlY3Rpb24pO1xuICBpZiAocmVzZXJ2ZWQuc3RhdHVzID09PSAnZGVuaWVkJykgcmV0dXJuIHJlc2VydmVkO1xuICByZXR1cm4gcnVuV2l0aFNsb3QocmVzZXJ2ZWQuc2xvdCwgKHNsb3QpID0+IGJvZHkoc2xvdCwgc2VsZWN0aW9uKSwgb25FcnJvcik7XG59XG5cbi8qKiBCb3VuZGVkIG1ldHJpYyBsYWJlbDogYGFnZW50LXRvb2w6PG5hbWU+YCBjb2xsYXBzZXMgdG8gYGFnZW50LXRvb2xgLiAqL1xuZnVuY3Rpb24gZmVhdHVyZUxhYmVsKGZlYXR1cmU6IEFpRmVhdHVyZSk6IHN0cmluZyB7XG4gIHJldHVybiBmZWF0dXJlLnN0YXJ0c1dpdGgoJ2FnZW50LXRvb2w6JykgPyAnYWdlbnQtdG9vbCcgOiBmZWF0dXJlO1xufVxuIl19
|
package/lib/api/app-factory.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Copyright 2026 Pipeline Builder Contributors
|
|
2
2
|
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
-
import { sendSuccess, sendError, generateOpenApiSpec, ErrorCode, createLogger, verifyServicePrincipal, createHealthRouter, setCounterEmitter, setGaugeEmitter, requireAuth, safeEqual, createEnvSseTicketStore, SSE_TICKET_TTL_MS } from '@pipeline-builder/api-core';
|
|
3
|
+
import { sendSuccess, sendError, generateOpenApiSpec, ErrorCode, createLogger, verifyServicePrincipal, createHealthRouter, setCounterEmitter, setGaugeEmitter, requireAuth, safeEqual, createEnvSseTicketStore, SSE_TICKET_TTL_MS, auditContextFromRequest, runWithAuditContext, sanitizeCorrelationId } from '@pipeline-builder/api-core';
|
|
4
4
|
import { Config, CoreConstants } from '@pipeline-builder/pipeline-core';
|
|
5
5
|
import { getConnection } from '@pipeline-builder/pipeline-data';
|
|
6
6
|
import compression from 'compression';
|
|
@@ -15,6 +15,7 @@ import { createEnvRedisIdempotencyStore, setIdempotencyStore } from './idempoten
|
|
|
15
15
|
import { metricsMiddleware, metricsHandler, incCounter, setGauge } from './metrics.js';
|
|
16
16
|
import { createSharedRateLimitStore } from './rate-limit-store.js';
|
|
17
17
|
import { readinessGuard } from './readiness.js';
|
|
18
|
+
import { currentTraceId } from './tracing.js';
|
|
18
19
|
import { SSEManager, SSE_REQUEST_ID_RE } from '../http/sse-connection-manager.js';
|
|
19
20
|
import { createEnvRedisSSERelay } from '../http/sse-relay.js';
|
|
20
21
|
// Wire api-core's counter shim to the real prom-client registry. This is
|
|
@@ -363,13 +364,20 @@ export function createApp(options = {}) {
|
|
|
363
364
|
applyBodyParsing(app, options);
|
|
364
365
|
// Trust proxy (must be set before rate limiter so req.ip resolves correctly)
|
|
365
366
|
app.set('trust proxy', Config.get('server').trustProxy);
|
|
366
|
-
// Request ID
|
|
367
|
+
// Request ID + audit context. Prefer the inbound `X-Request-Id` (nginx, or a
|
|
368
|
+
// peer service / CLI forwarding its own) when it is a bounded opaque token —
|
|
369
|
+
// an oversized or junk value is replaced, not stored — otherwise generate one.
|
|
370
|
+
// The rest of the request then runs inside an audit-context scope, so every
|
|
371
|
+
// `recordAudit` it makes carries the request id, trace id, client ip / UA, the
|
|
372
|
+
// verified credential (read lazily, after `requireAuth`) and any inbound
|
|
373
|
+
// `X-Pipeline-Execution-Id` / `X-CodeBuild-Build-Id` / `X-Source-Event-Id`
|
|
374
|
+
// with no call-site change. Mounted after `trust proxy` so `req.ip` is real.
|
|
367
375
|
app.use((req, res, next) => {
|
|
368
376
|
const hdr = req.headers['x-request-id'];
|
|
369
|
-
const requestId = (Array.isArray(hdr) ? hdr[0] : hdr)
|
|
377
|
+
const requestId = sanitizeCorrelationId(Array.isArray(hdr) ? hdr[0] : hdr) ?? uuid();
|
|
370
378
|
req.requestId = requestId;
|
|
371
379
|
res.setHeader('X-Request-Id', requestId);
|
|
372
|
-
|
|
380
|
+
runWithAuditContext(auditContextFromRequest(req, { requestId, traceId: currentTraceId() }), next);
|
|
373
381
|
});
|
|
374
382
|
mountInfraEndpoints(app, options, serviceName, enableOpenApi);
|
|
375
383
|
if (enableRateLimit)
|
|
@@ -385,4 +393,4 @@ export function createApp(options = {}) {
|
|
|
385
393
|
wireSse(app, sseManager);
|
|
386
394
|
return { app, sseManager };
|
|
387
395
|
}
|
|
388
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXBwLWZhY3RvcnkuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvYXBpL2FwcC1mYWN0b3J5LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLCtDQUErQztBQUMvQyxzQ0FBc0M7QUFFdEMsT0FBTyxFQUFFLFdBQVcsRUFBRSxTQUFTLEVBQUUsbUJBQW1CLEVBQUUsU0FBUyxFQUFFLFlBQVksRUFBRSxzQkFBc0IsRUFBRSxrQkFBa0IsRUFBRSxpQkFBaUIsRUFBRSxlQUFlLEVBQUUsV0FBVyxFQUFFLFNBQVMsRUFBRSx1QkFBdUIsRUFBRSxpQkFBaUIsRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBRXRRLE9BQU8sRUFBRSxNQUFNLEVBQUUsYUFBYSxFQUFFLE1BQU0saUNBQWlDLENBQUM7QUFDeEUsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLGlDQUFpQyxDQUFDO0FBQ2hFLE9BQU8sV0FBVyxNQUFNLGFBQWEsQ0FBQztBQUN0QyxPQUFPLElBQUksTUFBTSxNQUFNLENBQUM7QUFDeEIsT0FBTyxPQUFPLEVBQUUsRUFBZ0UsTUFBTSxTQUFTLENBQUM7QUFDaEcsT0FBTyxTQUFTLEVBQUUsRUFBRSxjQUFjLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUMvRCxPQUFPLE1BQU0sTUFBTSxRQUFRLENBQUM7QUFDNUIsT0FBTyxTQUFTLE1BQU0sb0JBQW9CLENBQUM7QUFDM0MsT0FBTyxFQUFFLEVBQUUsSUFBSSxJQUFJLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDbEMsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBQ3RELE9BQU8sRUFBRSw4QkFBOEIsRUFBRSxtQkFBbUIsRUFBeUIsTUFBTSw2QkFBNkIsQ0FBQztBQUN6SCxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsY0FBYyxFQUFFLFVBQVUsRUFBRSxRQUFRLEVBQUUsTUFBTSxjQUFjLENBQUM7QUFDdkYsT0FBTyxFQUFFLDBCQUEwQixFQUFFLE1BQU0sdUJBQXVC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NEVBQTRFO0lBQzVFLCtFQUErRTtJQUMvRSxpRUFBaUU7SUFDakUsOERBQThEO0lBRTlELElBQUksU0FBUztRQUFFLE9BQU8sQ0FBQyxHQUFHLEVBQUUsVUFBVSxDQUFDLENBQUM7SUFFeEMsT0FBTyxFQUFFLEdBQUcsRUFBRSxVQUFVLEVBQUUsQ0FBQztBQUM3QixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQ29weXJpZ2h0IDIwMjYgUGlwZWxpbmUgQnVpbGRlciBDb250cmlidXRvcnNcbi8vIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBcGFjaGUtMi4wXG5cbmltcG9ydCB7IHNlbmRTdWNjZXNzLCBzZW5kRXJyb3IsIGdlbmVyYXRlT3BlbkFwaVNwZWMsIEVycm9yQ29kZSwgY3JlYXRlTG9nZ2VyLCB2ZXJpZnlTZXJ2aWNlUHJpbmNpcGFsLCBjcmVhdGVIZWFsdGhSb3V0ZXIsIHNldENvdW50ZXJFbWl0dGVyLCBzZXRHYXVnZUVtaXR0ZXIsIHJlcXVpcmVBdXRoLCBzYWZlRXF1YWwsIGNyZWF0ZUVudlNzZVRpY2tldFN0b3JlLCBTU0VfVElDS0VUX1RUTF9NUyB9IGZyb20gJ0BwaXBlbGluZS1idWlsZGVyL2FwaS1jb3JlJztcbmltcG9ydCB0eXBlIHsgT3BlbkFwaVNwZWNPcHRpb25zIH0gZnJvbSAnQHBpcGVsaW5lLWJ1aWxkZXIvYXBpLWNvcmUnO1xuaW1wb3J0IHsgQ29uZmlnLCBDb3JlQ29uc3RhbnRzIH0gZnJvbSAnQHBpcGVsaW5lLWJ1aWxkZXIvcGlwZWxpbmUtY29yZSc7XG5pbXBvcnQgeyBnZXRDb25uZWN0aW9uIH0gZnJvbSAnQHBpcGVsaW5lLWJ1aWxkZXIvcGlwZWxpbmUtZGF0YSc7XG5pbXBvcnQgY29tcHJlc3Npb24gZnJvbSAnY29tcHJlc3Npb24nO1xuaW1wb3J0IGNvcnMgZnJvbSAnY29ycyc7XG5pbXBvcnQgZXhwcmVzcywgeyB0eXBlIEV4cHJlc3MsIHR5cGUgTmV4dEZ1bmN0aW9uLCB0eXBlIFJlcXVlc3QsIHR5cGUgUmVzcG9uc2UgfSBmcm9tICdleHByZXNzJztcbmltcG9ydCByYXRlTGltaXQsIHsgaXBLZXlHZW5lcmF0b3IgfSBmcm9tICdleHByZXNzLXJhdGUtbGltaXQnO1xuaW1wb3J0IGhlbG1ldCBmcm9tICdoZWxtZXQnO1xuaW1wb3J0IHN3YWdnZXJVaSBmcm9tICdzd2FnZ2VyLXVpLWV4cHJlc3MnO1xuaW1wb3J0IHsgdjcgYXMgdXVpZCB9IGZyb20gJ3V1aWQnO1xuaW1wb3J0IHsgZXRhZ01pZGRsZXdhcmUgfSBmcm9tICcuL2V0YWctbWlkZGxld2FyZS5qcyc7XG5pbXBvcnQgeyBjcmVhdGVFbnZSZWRpc0lkZW1wb3RlbmN5U3RvcmUsIHNldElkZW1wb3RlbmN5U3RvcmUsIHR5cGUgSWRlbXBvdGVuY3lTdG9yZSB9IGZyb20gJy4vaWRlbXBvdGVuY3ktbWlkZGxld2FyZS5qcyc7XG5pbXBvcnQgeyBtZXRyaWNzTWlkZGxld2FyZSwgbWV0cmljc0hhbmRsZXIsIGluY0NvdW50ZXIsIHNldEdhdWdlIH0gZnJvbSAnLi9tZXRyaWNzLmpzJztcbmltcG9ydCB7IGNyZWF0ZVNoYXJlZFJhdGVMaW1pdFN0b3JlIH0gZnJvbSAnLi9yYXRlLWxpbWl0LXN0b3JlLmpzJztcbmltcG9ydCB7IHJlYWRpbmVzc0d1YXJkIH0gZnJvbSAnLi9yZWFkaW5lc3MuanMnO1xuaW1wb3J0IHsgU1NFTWFuYWdlciwgU1NFX1JFUVVFU1RfSURfUkUgfSBmcm9tICcuLi9odHRwL3NzZS1jb25uZWN0aW9uLW1hbmFnZXIuanMnO1xuaW1wb3J0IHsgY3JlYXRlRW52UmVkaXNTU0VSZWxheSB9IGZyb20gJy4uL2h0dHAvc3NlLXJlbGF5LmpzJztcblxuLy8gV2lyZSBhcGktY29yZSdzIGNvdW50ZXIgc2hpbSB0byB0aGUgcmVhbCBwcm9tLWNsaWVudCByZWdpc3RyeS4gVGhpcyBpc1xuLy8gYSBuby1vcCB1bnRpbCBpbmNDb3VudGVyIGlzIGNhbGxlZCBmb3IgdGhlIGZpcnN0IHRpbWUgKGxhenkgcmVnaXN0cmF0aW9uXG4vLyBpbiBtZXRyaWNzLnRzKSwgYW5kIGxldHMgYXBpLWNvcmUgaGVscGVycyBsaWtlIHRoZSBxdW90YSBjbGllbnQgcmVjb3JkXG4vLyBgcXVvdGFfZmFpbF9vcGVuX3RvdGFsYCB3aXRob3V0IHRha2luZyBhIGhhcmQgZGVwIG9uIGFwaS1zZXJ2ZXIuXG5zZXRDb3VudGVyRW1pdHRlcihpbmNDb3VudGVyKTtcbi8vIFNhbWUgc2VhbSBmb3IgR0FVR0VTLiBwaXBlbGluZS1kYXRhJ3MgcmVhZC1yZXBsaWNhIGxhZyBzYW1wbGVyIG5lZWRzIGl0OlxuLy8gcmVwbGF5IGxhZyBhbmQgdGhlIHN0YXRlIG9mIHRoZSByZWFkIGZhbGxiYWNrIGNpcmN1aXQgYXJlIHNhbXBsZWRcbi8vIHBvaW50LWluLXRpbWUgdmFsdWVzLCBzbyBlbWl0dGluZyB0aGVtIGFzIGNvdW50ZXJzIHdvdWxkIG1ha2UgZXZlcnkgcXVlcnlcbi8vIG92ZXIgdGhlbSB3cm9uZy4gcGlwZWxpbmUtZGF0YSBkZXBlbmRzIG9uIGFwaS1jb3JlIGFuZCBtdXN0IG5vdCBkZXBlbmQgb25cbi8vIGFwaS1zZXJ2ZXIsIGhlbmNlIHRoZSBzaGltIHJhdGhlciB0aGFuIGEgZGlyZWN0IGltcG9ydC5cbnNldEdhdWdlRW1pdHRlcihzZXRHYXVnZSk7XG5cbi8qKlxuICogT3B0aW9ucyBmb3IgY3JlYXRpbmcgYW4gRXhwcmVzcyBhcHBsaWNhdGlvblxuICovXG5leHBvcnQgaW50ZXJmYWNlIENyZWF0ZUFwcE9wdGlvbnMge1xuICAvKiogRW5hYmxlIENPUlMgKGRlZmF1bHQ6IHRydWUpICovXG4gIGVuYWJsZUNvcnM/OiBib29sZWFuO1xuICAvKiogRW5hYmxlIEhlbG1ldCBzZWN1cml0eSBoZWFkZXJzIChkZWZhdWx0OiB0cnVlKSAqL1xuICBlbmFibGVIZWxtZXQ/OiBib29sZWFuO1xuICAvKiogRW5hYmxlIHJhdGUgbGltaXRpbmcgKGRlZmF1bHQ6IHRydWUpICovXG4gIGVuYWJsZVJhdGVMaW1pdD86IGJvb2xlYW47XG4gIC8qKiBFbmFibGUgSlNPTiBib2R5IHBhcnNpbmcgKGRlZmF1bHQ6IHRydWUpICovXG4gIGVuYWJsZUpzb25Cb2R5PzogYm9vbGVhbjtcbiAgLyoqIEpTT04gYm9keSBzaXplIGxpbWl0IChkZWZhdWx0OiAnMW1iJykgKi9cbiAganNvbkxpbWl0Pzogc3RyaW5nO1xuICAvKipcbiAgICogUGF0aCBwcmVmaXhlcyB0aGUgZ2xvYmFsIEpTT04gYm9keSBwYXJzZXIgbXVzdCBOT1QgdG91Y2gg4oCUIGZvciByb3V0ZXMgdGhhdCBuZWVkXG4gICAqIHRoZSByYXcgYm9keSAoZS5nLiBhIFN0cmlwZSB3ZWJob29rIHdob3NlIEhNQUMgaXMgY29tcHV0ZWQgb3ZlciB0aGUgZXhhY3QgYnl0ZXMpLlxuICAgKiBXaXRob3V0IHRoaXMgdGhlIGdsb2JhbCBwYXJzZXIgY29uc3VtZXMgdGhlIGJvZHkgZmlyc3QgYW5kIGEgbGF0ZXIgYGV4cHJlc3MucmF3KClgXG4gICAqIG9uIHRoZSBzYW1lIHBhdGggaXMgYSBuby1vcCwgYnJlYWtpbmcgc2lnbmF0dXJlIHZlcmlmaWNhdGlvbi5cbiAgICovXG4gIGpzb25Cb2R5RXhjbHVkZT86IHN0cmluZ1tdO1xuICAvKiogRW5hYmxlIFVSTC1lbmNvZGVkIGJvZHkgcGFyc2luZyAoZGVmYXVsdDogdHJ1ZSkgKi9cbiAgZW5hYmxlVXJsRW5jb2RlZD86IGJvb2xlYW47XG4gIC8qKiBVUkwtZW5jb2RlZCBib2R5IHNpemUgbGltaXQgKGRlZmF1bHQ6ICcxbWInKSAqL1xuICB1cmxFbmNvZGVkTGltaXQ/OiBzdHJpbmc7XG4gIC8qKiBDdXN0b20gU1NFIG1hbmFnZXIgaW5zdGFuY2UgKi9cbiAgc3NlTWFuYWdlcj86IFNTRU1hbmFnZXI7XG4gIC8qKlxuICAgKiBTZXJ2ZSB0aGUgcGVyLXJlcXVlc3QgYnVpbGQtbG9nIHN0cmVhbTogYFBPU1QgL2xvZ3MvdGlja2V0YCArXG4gICAqIGBHRVQgL2xvZ3MvOnJlcXVlc3RJZGAsIGEgbG9nIHRpY2tldCBzdG9yZSwgdGhlIGNyb3NzLXBvZCByZWxheSwgYW5kXG4gICAqIGBjdHgubG9nYCBmcmFtZXMgcHVzaGVkIHRvIFNTRS4gRGVmYXVsdCBmYWxzZSDigJQgYSBzZXJ2aWNlIHdpdGhvdXQgaXQgaGFzIG5vXG4gICAqIGAvbG9nc2Agcm91dGVzIGFuZCBgY3R4LmxvZ2Agb25seSB3cml0ZXMgdG8gdGhlIGxvZ2dlci5cbiAgICovXG4gIGxvZ1N0cmVhbT86IGJvb2xlYW47XG4gIC8qKiBIZWFsdGggY2hlY2sgZGVwZW5kZW5jeSBjaGVja2VyIOKAlCBpZiBwcm92aWRlZCwgL2hlYWx0aCByZXBvcnRzIGRlcGVuZGVuY3kgc3RhdHVzICovXG4gIGNoZWNrRGVwZW5kZW5jaWVzPzogKCkgPT4gUHJvbWlzZTxSZWNvcmQ8c3RyaW5nLCAnY29ubmVjdGVkJyB8ICdkaXNjb25uZWN0ZWQnIHwgJ3Vua25vd24nPj47XG4gIC8qKlxuICAgKiBTZXJ2ZSB0aGUgT3BlbkFQSSBzcGVjIGF0IGAvZG9jcy9vcGVuYXBpLmpzb25gIGFuZCBTd2FnZ2VyIFVJIGF0IGAvZG9jc2AuXG4gICAqXG4gICAqIERlZmF1bHRzIHRvIE9GRiB1bmRlciBgTk9ERV9FTlY9cHJvZHVjdGlvbmA6IHRoZSByb3V0ZXMgYXJlIHJlZ2lzdGVyZWQgYWJvdmVcbiAgICogdGhlIHJhdGUgbGltaXRlciBhbmQgYXJlIG5vdCBhdXRoLWdhdGVkLCBzbyBpbiBwcm9kdWN0aW9uIHRoZXkgd291bGQgcHVibGlzaFxuICAgKiB0aGUgZnVsbCByb3V0ZSArIHNjaGVtYSBpbnZlbnRvcnkgb2YgZXZlcnkgc2VydmljZSB0byBhbnlvbmUgd2hvIGNvdWxkIHJlYWNoXG4gICAqIHRoZSBwb3J0LiBQYXNzIGB0cnVlYCBleHBsaWNpdGx5IHRvIHNlcnZlIHRoZW0gaW4gcHJvZHVjdGlvbiBhbnl3YXkuXG4gICAqL1xuICBlbmFibGVPcGVuQXBpPzogYm9vbGVhbjtcbiAgLyoqIE9wZW5BUEkgc3BlYyBjdXN0b21pemF0aW9uIG9wdGlvbnMgKi9cbiAgb3BlbkFwaU9wdGlvbnM/OiBPcGVuQXBpU3BlY09wdGlvbnM7XG4gIC8qKiBFbmFibGUgZ3ppcC9kZWZsYXRlIHJlc3BvbnNlIGNvbXByZXNzaW9uIChkZWZhdWx0OiB0cnVlKSAqL1xuICBlbmFibGVDb21wcmVzc2lvbj86IGJvb2xlYW47XG4gIC8qKlxuICAgKiBJZGVtcG90ZW5jeSByZXBsYXktY2FjaGUgYmFja2VuZCBmb3Iga2V5ZWQgbXV0YXRpb24gcmV0cmllcy4gV2hlbiBvbWl0dGVkLFxuICAgKiBjcmVhdGVBcHAgYXV0by13aXJlcyB0aGUgc2hhcmVkIGVudiBSZWRpcyBzdG9yZSAobXVsdGktcmVwbGljYSBkZWR1cCkgaWZcbiAgICogUmVkaXMgaXMgY29uZmlndXJlZCwgZWxzZSBrZWVwcyB0aGUgaW4tbWVtb3J5IGRlZmF1bHQgKHNpbmdsZS1yZXBsaWNhKS5cbiAgICogUGFzcyBhbiBleHBsaWNpdCBzdG9yZSB0byBpbmplY3QgYSBiZXNwb2tlIGJhY2tlbmQgKGUuZy4gYSBzZXJ2aWNlJ3Mgb3duXG4gICAqIGlvcmVkaXMgY29ubmVjdGlvbikuXG4gICAqL1xuICBpZGVtcG90ZW5jeVN0b3JlPzogSWRlbXBvdGVuY3lTdG9yZTtcbiAgLyoqXG4gICAqIEV4dHJhIHdhcm11cCBjYWxsYmFja3MgaW52b2tlZCBieSBgR0VUIC93YXJtdXBgIGluIGFkZGl0aW9uIHRvIHRoZVxuICAgKiBkZWZhdWx0IFBvc3RncmVzIHBpbmcuIFVzZSBmb3Igc2VydmljZXMgdGhhdCBkZXBlbmQgb24gTW9uZ28sIFJlZGlzLFxuICAgKiBTUVMsIGV0Yy4g4oCUIHByZS13YXJtaW5nIG9wZW5zIGNvbm5lY3Rpb24gcG9vbHMgYmVmb3JlIHJlYWwgdHJhZmZpY1xuICAgKiBhcnJpdmVzLiBFYWNoIGNhbGxiYWNrIHNob3VsZCByZXNvbHZlIHdoZW4gaXRzIGRlcGVuZGVuY3kgaXMgcmVhZHk7XG4gICAqIGFueSByZWplY3Rpb24gY2F1c2VzIC93YXJtdXAgdG8gcmV0dXJuIDUwMy5cbiAgICovXG4gIHdhcm11cEhvb2tzPzogQXJyYXk8KCkgPT4gUHJvbWlzZTx2b2lkPj47XG59XG5cbi8qKlxuICogUmVzdWx0IG9mIGNyZWF0aW5nIGFuIEV4cHJlc3MgYXBwbGljYXRpb25cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBDcmVhdGVBcHBSZXN1bHQge1xuICAvKiogQ29uZmlndXJlZCBFeHByZXNzIGFwcGxpY2F0aW9uICovXG4gIGFwcDogRXhwcmVzcztcbiAgLyoqIFNTRSBtYW5hZ2VyIGluc3RhbmNlICovXG4gIHNzZU1hbmFnZXI6IFNTRU1hbmFnZXI7XG59XG5cbi8qKiBIZWxtZXQgKHN0cmljdCBDU1ApLCBDT1JTLCBjb21wcmVzc2lvbiBhbmQgRVRhZ3MuICovXG5mdW5jdGlvbiBhcHBseVNlY3VyaXR5SGVhZGVycyhhcHA6IEV4cHJlc3MsIG9wdGlvbnM6IENyZWF0ZUFwcE9wdGlvbnMsIGVuYWJsZU9wZW5BcGk6IGJvb2xlYW4pOiB2b2lkIHtcbiAgY29uc3QgeyBlbmFibGVDb3JzID0gdHJ1ZSwgZW5hYmxlSGVsbWV0ID0gdHJ1ZSwgZW5hYmxlQ29tcHJlc3Npb24gPSB0cnVlIH0gPSBvcHRpb25zO1xuICAvLyBTd2FnZ2VyIFVJIG5lZWRzIHVuc2FmZS1pbmxpbmUgKyB1bnNhZmUtZXZhbCBmb3IgaXRzIGJ1bmRsZWQgc2NyaXB0cyDigJRcbiAgLy8gYnV0IENTUCBpcyBvbmx5IHJlbGF4ZWQgdGhhdCBmYXIgd2hlbiAoYSkgT3BlbkFQSSBpcyBlbmFibGVkIEFORCAoYikgd2UncmVcbiAgLy8gbm90IGluIHByb2R1Y3Rpb24uIEluIHByb2QsIFN3YWdnZXIgc2hvdWxkIGJlIHNlcnZlZCBiZWhpbmQgYSBzZXBhcmF0ZVxuICAvLyBob3N0IG9yIGF1dGgtZ2F0ZWQgcm91dGU7IHRoZSBtYWluIGFwcCBrZWVwcyB0aGUgc3RyaWN0IENTUCBzbyBhIFN0b3JlZFxuICAvLyBYU1MgaW4gYW55IGhhbmRsZXIgY2FuJ3QgYGV2YWwoKWAgYXJiaXRyYXJ5IHNjcmlwdC5cbiAgY29uc3QgYWxsb3dTd2FnZ2VyQ3NwID0gZW5hYmxlT3BlbkFwaSAmJiBwcm9jZXNzLmVudi5OT0RFX0VOViAhPT0gJ3Byb2R1Y3Rpb24nO1xuICBpZiAoZW5hYmxlSGVsbWV0KSB7XG4gICAgYXBwLnVzZShoZWxtZXQoe1xuICAgICAgY29udGVudFNlY3VyaXR5UG9saWN5OiB7XG4gICAgICAgIGRpcmVjdGl2ZXM6IHtcbiAgICAgICAgICBkZWZhdWx0U3JjOiBbXCInc2VsZidcIl0sXG4gICAgICAgICAgc2NyaXB0U3JjOiBhbGxvd1N3YWdnZXJDc3BcbiAgICAgICAgICAgID8gW1wiJ3NlbGYnXCIsIFwiJ3Vuc2FmZS1pbmxpbmUnXCIsIFwiJ3Vuc2FmZS1ldmFsJ1wiXVxuICAgICAgICAgICAgOiBbXCInc2VsZidcIl0sXG4gICAgICAgICAgc3R5bGVTcmM6IFtcIidzZWxmJ1wiLCBcIid1bnNhZmUtaW5saW5lJ1wiXSxcbiAgICAgICAgICBpbWdTcmM6IFtcIidzZWxmJ1wiLCAnZGF0YTonLCAnYmxvYjonXSxcbiAgICAgICAgICBjb25uZWN0U3JjOiBbXCInc2VsZidcIl0sXG4gICAgICAgICAgZm9udFNyYzogW1wiJ3NlbGYnXCJdLFxuICAgICAgICAgIG9iamVjdFNyYzogW1wiJ25vbmUnXCJdLFxuICAgICAgICAgIGZyYW1lQW5jZXN0b3JzOiBbXCInbm9uZSdcIl0sXG4gICAgICAgICAgYmFzZVVyaTogW1wiJ3NlbGYnXCJdLFxuICAgICAgICAgIGZvcm1BY3Rpb246IFtcIidzZWxmJ1wiXSxcbiAgICAgICAgfSxcbiAgICAgIH0sXG4gICAgfSkpO1xuICB9XG5cbiAgaWYgKGVuYWJsZUNvcnMpIHtcbiAgICBhcHAudXNlKGNvcnMoQ29uZmlnLmdldCgnc2VydmVyJykuY29ycykpO1xuICB9XG5cbiAgLy8gUmVzcG9uc2UgY29tcHJlc3Npb24gKGd6aXAvZGVmbGF0ZSkg4oCUIHNraXAgU1NFIHN0cmVhbXNcbiAgaWYgKGVuYWJsZUNvbXByZXNzaW9uKSB7XG4gICAgYXBwLnVzZShjb21wcmVzc2lvbih7XG4gICAgICBmaWx0ZXI6IChyZXE6IFJlcXVlc3QsIHJlczogUmVzcG9uc2UpID0+IHtcbiAgICAgICAgLy8gRG9uJ3QgY29tcHJlc3MgU1NFIHN0cmVhbXMuIE1hdGNoIGJ5IGluY2x1c2lvbjogdGhlIEFjY2VwdCBoZWFkZXIgaXNcbiAgICAgICAgLy8gb2Z0ZW4gYSBsaXN0IChlLmcuIFwidGV4dC9ldmVudC1zdHJlYW0sICovKlwiKSwgd2hpY2ggZXhhY3QgZXF1YWxpdHlcbiAgICAgICAgLy8gd291bGQgbWlzcywgY29tcHJlc3NpbmcvYnVmZmVyaW5nIHRoZSBzdHJlYW0uXG4gICAgICAgIGlmICgocmVxLmhlYWRlcnMuYWNjZXB0IHx8ICcnKS5pbmNsdWRlcygndGV4dC9ldmVudC1zdHJlYW0nKSkgcmV0dXJuIGZhbHNlO1xuICAgICAgICByZXR1cm4gY29tcHJlc3Npb24uZmlsdGVyKHJlcSwgcmVzKTtcbiAgICAgIH0sXG4gICAgICB0aHJlc2hvbGQ6IENvcmVDb25zdGFudHMuQ09NUFJFU1NJT05fVEhSRVNIT0xEX0JZVEVTLFxuICAgIH0pKTtcbiAgfVxuXG4gIC8vIEVUYWcgc3VwcG9ydCBmb3IgY29uZGl0aW9uYWwgR0VUIHJlcXVlc3RzICgzMDQgTm90IE1vZGlmaWVkKVxuICBhcHAudXNlKGV0YWdNaWRkbGV3YXJlKCkpO1xufVxuXG4vKiogSlNPTiArIFVSTC1lbmNvZGVkIGJvZHkgcGFyc2Vycy4gKi9cbmZ1bmN0aW9uIGFwcGx5Qm9keVBhcnNpbmcoYXBwOiBFeHByZXNzLCBvcHRpb25zOiBDcmVhdGVBcHBPcHRpb25zKTogdm9pZCB7XG4gIGNvbnN0IHsgZW5hYmxlSnNvbkJvZHkgPSB0cnVlLCBqc29uTGltaXQgPSAnMW1iJywgZW5hYmxlVXJsRW5jb2RlZCA9IHRydWUsIHVybEVuY29kZWRMaW1pdCA9ICcxbWInIH0gPSBvcHRpb25zO1xuICBpZiAoZW5hYmxlSnNvbkJvZHkpIHtcbiAgICBjb25zdCBqc29uUGFyc2VyID0gZXhwcmVzcy5qc29uKHsgbGltaXQ6IGpzb25MaW1pdCB9KTtcbiAgICBjb25zdCBleGNsdWRlID0gb3B0aW9ucy5qc29uQm9keUV4Y2x1ZGUgPz8gW107XG4gICAgaWYgKGV4Y2x1ZGUubGVuZ3RoID4gMCkge1xuICAgICAgLy8gU2tpcCB0aGUgZ2xvYmFsIEpTT04gcGFyc2VyIGZvciByYXctYm9keSBwYXRocyBzbyBhIHBlci1wYXRoIGBleHByZXNzLnJhdygpYFxuICAgICAgLy8gY2FuIHJlYWQgdGhlIGV4YWN0IGJ5dGVzIChzZWUgYGpzb25Cb2R5RXhjbHVkZWApLlxuICAgICAgYXBwLnVzZSgocmVxLCByZXMsIG5leHQpID0+IChleGNsdWRlLnNvbWUoKHApID0+IHJlcS5wYXRoLnN0YXJ0c1dpdGgocCkpID8gbmV4dCgpIDoganNvblBhcnNlcihyZXEsIHJlcywgbmV4dCkpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgYXBwLnVzZShqc29uUGFyc2VyKTtcbiAgICB9XG4gIH1cblxuICBpZiAoZW5hYmxlVXJsRW5jb2RlZCkge1xuICAgIGFwcC51c2UoZXhwcmVzcy51cmxlbmNvZGVkKHsgZXh0ZW5kZWQ6IHRydWUsIGxpbWl0OiB1cmxFbmNvZGVkTGltaXQgfSkpO1xuICB9XG59XG5cbi8qKlxuICogSGVhbHRoLCByZWFkaW5lc3MgZ3VhcmQsIGAvd2FybXVwYCwgYC9tZXRyaWNzYCBhbmQgdGhlIE9wZW5BUEkgZG9jcyDigJQgYWxsXG4gKiByZWdpc3RlcmVkIGJlZm9yZSB0aGUgcmF0ZSBsaW1pdGVyIHNvIHRoZXkgYXJlIG5ldmVyIHRocm90dGxlZC5cbiAqL1xuZnVuY3Rpb24gbW91bnRJbmZyYUVuZHBvaW50cyhhcHA6IEV4cHJlc3MsIG9wdGlvbnM6IENyZWF0ZUFwcE9wdGlvbnMsIHNlcnZpY2VOYW1lOiBzdHJpbmcsIGVuYWJsZU9wZW5BcGk6IGJvb2xlYW4pOiB2b2lkIHtcbiAgY29uc3QgeyBjaGVja0RlcGVuZGVuY2llcywgb3BlbkFwaU9wdGlvbnMsIHdhcm11cEhvb2tzID0gW10gfSA9IG9wdGlvbnM7XG5cbiAgYXBwLnVzZShjcmVhdGVIZWFsdGhSb3V0ZXIoe1xuICAgIHNlcnZpY2VOYW1lLFxuICAgIGNoZWNrRGVwZW5kZW5jaWVzLFxuICB9KSk7XG5cbiAgLy8gUmVhZGluZXNzIGd1YXJkIOKAlCA1MDNzIGJ1c2luZXNzIHRyYWZmaWMgd2hpbGUgdGhlIHNlcnZpY2UgaXMgTm90UmVhZHlcbiAgLy8gKGRhdGFzdG9yZSBzdGlsbCBjb25uZWN0aW5nIGF0IHN0YXJ0dXAsIG9yIGRyb3BwZWQpLiBNb3VudGVkIHJpZ2h0IGFmdGVyXG4gIC8vIHRoZSBoZWFsdGggcm91dGVyIGFuZCBiZWZvcmUgZXZlcnl0aGluZyBlbHNlIHNvIGEgTm90UmVhZHkgcmVxdWVzdCBpc1xuICAvLyByZWplY3RlZCBjaGVhcGx5LCBiZWZvcmUgcmF0ZS1saW1pdCAvIGlkZW1wb3RlbmN5IC8gYnVzaW5lc3MgaGFuZGxlcnMgZXZlclxuICAvLyB0b3VjaCBhIGRpc2Nvbm5lY3RlZCBkYXRhc3RvcmUuIEl0IGFsbG93bGlzdHMgdGhlIGluZnJhIGVuZHBvaW50c1xuICAvLyAoL21ldHJpY3MsIC93YXJtdXAsIC9kb2NzLCAvbG9ncykgcmVnaXN0ZXJlZCBiZWxvdywgcGx1cyAvaGVhbHRoICsgL3JlYWR5LlxuICBhcHAudXNlKHJlYWRpbmVzc0d1YXJkKCkpO1xuXG4gIC8vIFdhcm0tdXAgZW5kcG9pbnQg4oCUIHByZS1vcGVucyBjb25uZWN0aW9uIHBvb2xzIHNvIHRoZSBmaXJzdCByZWFsIHJlcXVlc3RcbiAgLy8gZG9lc24ndCBwYXkgY29sZC1zdGFydCBsYXRlbmN5LiBBbHdheXMgcGluZ3MgUG9zdGdyZXM7IHNlcnZpY2VzIHVzaW5nXG4gIC8vIE1vbmdvIC8gUmVkaXMgLyBTUVMgcGFzcyBgd2FybXVwSG9va3NgIHNvIHRob3NlIGFyZSB3YXJtZWQgaW4gcGFyYWxsZWwuXG4gIC8vXG4gIC8vIEdBVEVEIHRvIHZlcmlmaWVkIHNlcnZpY2UgcHJpbmNpcGFscy4gRXZlcnkgaGl0IHJ1bnMgYSBQb3N0Z3JlcyByb3VuZC10cmlwXG4gIC8vIHBsdXMgYWxsIGB3YXJtdXBIb29rc2AgKE1vbmdvL1JlZGlzL1NRUyksIHNvIGFuIG9wZW4gZW5kcG9pbnQgd291bGQgbGV0IGFuXG4gIC8vIGFub255bW91cyBsb29wIGFtcGxpZnkgaW50byBkYXRhc3RvcmUgbG9hZCBvbiBldmVyeSBzZXJ2aWNlIGluIHRoZSBmbGVldCDigJRcbiAgLy8gYW5kIGl0IGlzIHJlZ2lzdGVyZWQgYWJvdmUgdGhlIHJhdGUgbGltaXRlciwgc28gbm90aGluZyB3b3VsZCB0aHJvdHRsZSBpdC5cbiAgLy8gYHZlcmlmeVNlcnZpY2VQcmluY2lwYWxgIGNoZWNrcyB0aGUgYmVhcmVyIHRva2VuIGNyeXB0b2dyYXBoaWNhbGx5LCBzbyBpdCBpc1xuICAvLyBzYWZlIGhlcmUsIGFib3ZlIGByZXF1aXJlQXV0aGAuXG4gIGFwcC5nZXQoJy93YXJtdXAnLCBhc3luYyAocmVxOiBSZXF1ZXN0LCByZXM6IFJlc3BvbnNlKSA9PiB7XG4gICAgaWYgKCF2ZXJpZnlTZXJ2aWNlUHJpbmNpcGFsKHJlcSkpIHtcbiAgICAgIHNlbmRFcnJvcihyZXMsIDQwNCwgJ05vdCBmb3VuZCcpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB0cnkge1xuICAgICAgYXdhaXQgUHJvbWlzZS5hbGwoW1xuICAgICAgICBnZXRDb25uZWN0aW9uKCkudGVzdENvbm5lY3Rpb24oKSxcbiAgICAgICAgLi4ud2FybXVwSG9va3MubWFwKChob29rKSA9PiBob29rKCkpLFxuICAgICAgXSk7XG4gICAgICBzZW5kU3VjY2VzcyhyZXMsIDIwMCwgeyB3YXJtZWQ6IHRydWUsIGhvb2tzOiB3YXJtdXBIb29rcy5sZW5ndGggfSk7XG4gICAgfSBjYXRjaCB7XG4gICAgICBzZW5kRXJyb3IocmVzLCA1MDMsICdXYXJtdXAgZmFpbGVkJyk7XG4gICAgfVxuICB9KTtcblxuICAvLyBQcm9tZXRoZXVzIG1ldHJpY3MgZW5kcG9pbnQg4oCUIGFsd2F5cyByZWdpc3RlcmVkIChuZXZlciB0aHJvdHRsZWQpLlxuICAvL1xuICAvLyBPcHRpb25hbGx5IGdhdGVkOiB3aGVuIGBNRVRSSUNTX1NDUkFQRV9UT0tFTmAgaXMgc2V0LCB0aGUgc2NyYXBlciBtdXN0IHNlbmRcbiAgLy8gaXQgYXMgYSBiZWFyZXIgdG9rZW4gKFByb21ldGhldXMgYGJlYXJlcl90b2tlbmAgLyBgYmVhcmVyX3Rva2VuX2ZpbGVgIGluIHRoZVxuICAvLyBzY3JhcGUgY29uZmlnKS4gTGVmdCB1bmdhdGVkIHdoZW4gdW5zZXQgc28gZW5hYmxpbmcgaXQgaXMgYSBkZWxpYmVyYXRlLFxuICAvLyBjb29yZGluYXRlZCBjaGFuZ2UgcmF0aGVyIHRoYW4gYSBzaWxlbnQgbW9uaXRvcmluZyBvdXRhZ2Ug4oCUIHRlbmFudCBpZHMgc3RheVxuICAvLyBvdXQgb2YgdGhlIG91dHB1dCByZWdhcmRsZXNzLCBiZWNhdXNlIHRoZSBwZXItb3JnIGxhYmVsIGRlZmF1bHRzIE9GRiAoc2VlXG4gIC8vIEhUVFBfTUVUUklDU19PUkdfU0FNUExFX1JBVEUgaW4gbWV0cmljcy50cykuXG4gIGNvbnN0IG1ldHJpY3NUb2tlbiA9IHByb2Nlc3MuZW52Lk1FVFJJQ1NfU0NSQVBFX1RPS0VOO1xuICBhcHAuZ2V0KCcvbWV0cmljcycsIChyZXE6IFJlcXVlc3QsIHJlczogUmVzcG9uc2UsIG5leHQ6IE5leHRGdW5jdGlvbikgPT4ge1xuICAgIGlmICghbWV0cmljc1Rva2VuKSB7XG4gICAgICBuZXh0KCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGNvbnN0IGhlYWRlciA9IHJlcS5oZWFkZXJzLmF1dGhvcml6YXRpb247XG4gICAgY29uc3QgcHJlc2VudGVkID0gaGVhZGVyPy5zdGFydHNXaXRoKCdCZWFyZXIgJykgPyBoZWFkZXIuc2xpY2UoNykgOiB1bmRlZmluZWQ7XG4gICAgLy8gQ29uc3RhbnQtdGltZSBjb21wYXJlIOKAlCBhIGxlbmd0aC1pbmRlcGVuZGVudCBlcXVhbGl0eSBjaGVjayBoZXJlIHdvdWxkXG4gICAgLy8gbGVhayB0aGUgdG9rZW4gYSBieXRlIGF0IGEgdGltZS5cbiAgICBpZiAoIXByZXNlbnRlZCB8fCAhc2FmZUVxdWFsKHByZXNlbnRlZCwgbWV0cmljc1Rva2VuKSkge1xuICAgICAgc2VuZEVycm9yKHJlcywgNDA0LCAnTm90IGZvdW5kJyk7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIG5leHQoKTtcbiAgfSwgbWV0cmljc0hhbmRsZXIoKSk7XG5cbiAgaWYgKGVuYWJsZU9wZW5BcGkpIHtcbiAgICBjb25zdCBzcGVjID0gZ2VuZXJhdGVPcGVuQXBpU3BlYyhvcGVuQXBpT3B0aW9ucyk7XG4gICAgYXBwLmdldCgnL2RvY3Mvb3BlbmFwaS5qc29uJywgKF9yZXE6IFJlcXVlc3QsIHJlczogUmVzcG9uc2UpID0+IHtcbiAgICAgIHJlcy5qc29uKHNwZWMpO1xuICAgIH0pO1xuICAgIGFwcC51c2UoJy9kb2NzJywgc3dhZ2dlclVpLnNlcnZlLCBzd2FnZ2VyVWkuc2V0dXAoc3BlYywge1xuICAgICAgY3VzdG9tU2l0ZVRpdGxlOiBvcGVuQXBpT3B0aW9ucz8udGl0bGUgPz8gJ1BpcGVsaW5lIEJ1aWxkZXIgQVBJIERvY3MnLFxuICAgIH0pKTtcbiAgfVxufVxuXG4vKiogR2xvYmFsIHJhdGUgbGltaXRlciDigJQgc2hhcmVkIGFjcm9zcyByZXBsaWNhcyB2aWEgdGhlIGVudiBSZWRpcyB3aGVuIGNvbmZpZ3VyZWQuICovXG5mdW5jdGlvbiBtb3VudFJhdGVMaW1pdGVyKGFwcDogRXhwcmVzcywgc2VydmljZU5hbWU6IHN0cmluZyk6IHZvaWQge1xuICBjb25zdCByYXRlTGltaXRDb25maWcgPSBDb25maWcuZ2V0KCdyYXRlTGltaXQnKTtcblxuICBjb25zdCByYXRlTGltaXRPcHRpb25zOiBQYXJhbWV0ZXJzPHR5cGVvZiByYXRlTGltaXQ+WzBdID0ge1xuICAgIG1heDogcmF0ZUxpbWl0Q29uZmlnLm1heCxcbiAgICB3aW5kb3dNczogcmF0ZUxpbWl0Q29uZmlnLndpbmRvd01zLFxuICAgIHN0YW5kYXJkSGVhZGVyczogdHJ1ZSxcbiAgICBsZWdhY3lIZWFkZXJzOiBmYWxzZSxcbiAgICAvLyBTa2lwIHJhdGUgbGltaXRpbmcgb25seSBmb3IgQ1JZUFRPR1JBUEhJQ0FMTFktVkVSSUZJRUQgaW50ZXJuYWwgc2VydmljZVxuICAgIC8vIGNhbGxlcnMuIFRoZSBsaW1pdGVyIHJ1bnMgYmVmb3JlIHJlcXVpcmVBdXRoLCBzbyBhIHBsYWludGV4dCBoZWFkZXJcbiAgICAvLyB3b3VsZCBiZSBzcG9vZmFibGUgYnkgYW55IGV4dGVybmFsIGNsaWVudCDihpIgdG90YWwgYnlwYXNzLlxuICAgIC8vIHZlcmlmeVNlcnZpY2VQcmluY2lwYWwgdmVyaWZpZXMgdGhlIHNpZ25lZCBzZXJ2aWNlIEpXVCBpbnN0ZWFkO1xuICAgIC8vIGludGVyLXNlcnZpY2UgY2FsbGVycyBhbGwgc2VuZCBvbmUgKGdldFNlcnZpY2VBdXRoSGVhZGVyKS5cbiAgICBza2lwOiAocmVxOiBSZXF1ZXN0KSA9PiB2ZXJpZnlTZXJ2aWNlUHJpbmNpcGFsKHJlcSksXG4gICAgLy8gS2V5IG9uIGNsaWVudCBJUCBvbmx5LiBUaGUgbGltaXRlciBydW5zIHByZS1hdXRoLCBzbyBgcmVxLnVzZXJgIGlzIHVuc2V0XG4gICAgLy8gYW5kIGFueSBvcmcgaWQgd291bGQgY29tZSBmcm9tIHRoZSBjYWxsZXItc3VwcGxpZWQgYHgtb3JnLWlkYCBoZWFkZXIg4oCUXG4gICAgLy8gc3Bvb2ZhYmxlLCBsZXR0aW5nIGFuIGF0dGFja2VyIHJvdGF0ZSB2YWx1ZXMgdG8gZXZhZGUgdGhlIGJ1Y2tldCBvclxuICAgIC8vIGZsb29kIGEgdmljdGltIG9yZydzIGJ1Y2tldC4gaXBLZXlHZW5lcmF0b3Igbm9ybWFsaXplcyBJUHY2IHRvIGEgLzY0XG4gICAgLy8gcHJlZml4IChhbHNvIHJlcXVpcmVkIGJ5IGV4cHJlc3MtcmF0ZS1saW1pdCA4LngncyB2YWxpZGF0b3IpLlxuICAgIGtleUdlbmVyYXRvcjogKHJlcTogUmVxdWVzdCkgPT4gaXBLZXlHZW5lcmF0b3IocmVxLmlwIHx8ICdhbm9uJywgNjQpLFxuICAgIC8vIEEgc3RvcmUgZmFpbHVyZSAoUmVkaXMgZG93biAvIGZhaWxpbmcgb3ZlcikgbXVzdCBkZWdyYWRlIHRvIFwibm90IHJhdGVcbiAgICAvLyBsaW1pdGVkXCIsIG5ldmVyIHRvIGEgNTAwIG9uIGV2ZXJ5IHJlcXVlc3Qgb2YgZXZlcnkgc2VydmljZS5cbiAgICBwYXNzT25TdG9yZUVycm9yOiB0cnVlLFxuICAgIGhhbmRsZXI6IChfcmVxOiBSZXF1ZXN0LCByZXM6IFJlc3BvbnNlKSA9PiB7XG4gICAgICBzZW5kRXJyb3IocmVzLCA0MjksICdUb28gbWFueSByZXF1ZXN0cywgcGxlYXNlIHRyeSBhZ2FpbiBsYXRlci4nLCBFcnJvckNvZGUuUkFURV9MSU1JVF9FWENFRURFRCk7XG4gICAgfSxcbiAgICAvLyBTaGFyZWQgc3RhdGUgYWNyb3NzIHJlcGxpY2FzICh0aGUgcHJvY2Vzcy13aWRlIHJhdGUtbGltaXQgUmVkaXMgY29ubmVjdGlvbjtcbiAgICAvLyB1bmRlZmluZWQgd2l0aG91dCBSZWRpcyDihpIgcGVyLXByb2Nlc3MgbWVtb3J5IHN0b3JlLCByaWdodCBmb3Igb25lIHJlcGxpY2EpLlxuICAgIC8vIE5hbWVzcGFjZWQgcGVyIFNFUlZJQ0U6IGV2ZXJ5IHNlcnZpY2Ugc2hhcmVzIG9uZSBSZWRpcywgYW5kIGFuIHVucHJlZml4ZWRcbiAgICAvLyBgcmw6PGlwPmAga2V5IHdvdWxkIGxldCBvbmUgY2xpZW50J3MgdHJhZmZpYyB0byBBTlkgc2VydmljZSBkcmFpbiBpdHNcbiAgICAvLyBidWRnZXQgb24gRVZFUlkgc2VydmljZS5cbiAgICBzdG9yZTogY3JlYXRlU2hhcmVkUmF0ZUxpbWl0U3RvcmUoYCR7c2VydmljZU5hbWV9Omdsb2JhbGApLFxuICB9O1xuXG4gIGFwcC51c2UocmF0ZUxpbWl0KHJhdGVMaW1pdE9wdGlvbnMpKTtcbn1cblxuLyoqIFJlcXVlc3QgdGltZW91dCwgZHVyYXRpb24gbG9nZ2luZyBhbmQgSFRUUCBtZXRyaWNzLiAqL1xuZnVuY3Rpb24gYXBwbHlSZXF1ZXN0VGVsZW1ldHJ5KGFwcDogRXhwcmVzcyk6IHZvaWQge1xuICAvLyBFeHByZXNzIHJlcXVlc3QgdGltZW91dCDigJQgdXNlcyBDb3JlQ29uc3RhbnRzIHRvIHNoYXJlIHRoZSBzYW1lIGRlZmF1bHQgYXMgTGFtYmRhIGhhbmRsZXJzXG4gIGNvbnN0IHRpbWVvdXRNcyA9IENvcmVDb25zdGFudHMuSEFORExFUl9USU1FT1VUX01TO1xuICBhcHAudXNlKChfcmVxOiBSZXF1ZXN0LCByZXM6IFJlc3BvbnNlLCBuZXh0OiBOZXh0RnVuY3Rpb24pID0+IHtcbiAgICByZXMuc2V0VGltZW91dCh0aW1lb3V0TXMsICgpID0+IHtcbiAgICAgIGlmICghcmVzLmhlYWRlcnNTZW50KSB7XG4gICAgICAgIHNlbmRFcnJvcihyZXMsIDUwMywgJ1JlcXVlc3QgdGltZW91dCcpO1xuICAgICAgfVxuICAgIH0pO1xuICAgIG5leHQoKTtcbiAgfSk7XG5cbiAgLy8gUmVxdWVzdCBkdXJhdGlvbiBsb2dnaW5nXG4gIGNvbnN0IGR1cmF0aW9uTG9nZ2VyID0gY3JlYXRlTG9nZ2VyKCdyZXF1ZXN0LWR1cmF0aW9uJyk7XG4gIGFwcC51c2UoKHJlcTogUmVxdWVzdCwgcmVzOiBSZXNwb25zZSwgbmV4dDogTmV4dEZ1bmN0aW9uKSA9PiB7XG4gICAgY29uc3Qgc3RhcnQgPSBEYXRlLm5vdygpO1xuICAgIHJlcy5vbignZmluaXNoJywgKCkgPT4ge1xuICAgICAgY29uc3QgZHVyYXRpb24gPSBEYXRlLm5vdygpIC0gc3RhcnQ7XG4gICAgICAvLyBMb2cgYHJlcS5wYXRoYCAobm8gcXVlcnkgc3RyaW5nKSDigJQgYSBzdHJheSBgP3Rva2VuPWAvYD90aWNrZXQ9YCBtdXN0IG5vdCBiZVxuICAgICAgLy8gcGVyc2lzdGVkIHZlcmJhdGltIG9uIGV2ZXJ5IHJlcXVlc3QgKG1pcnJvcnMgdGhlIGF1dGh6LWRlbmlhbCBhdWRpdG9yJ3Mgc3RyaXApLlxuICAgICAgZHVyYXRpb25Mb2dnZXIuaW5mbyhgJHtyZXEubWV0aG9kfSAke3JlcS5wYXRofSAke3Jlcy5zdGF0dXNDb2RlfSAke2R1cmF0aW9ufW1zYCwge1xuICAgICAgICBtZXRob2Q6IHJlcS5tZXRob2QsXG4gICAgICAgIHBhdGg6IHJlcS5wYXRoLFxuICAgICAgICBzdGF0dXNDb2RlOiByZXMuc3RhdHVzQ29kZSxcbiAgICAgICAgZHVyYXRpb25NczogZHVyYXRpb24sXG4gICAgICAgIHJlcXVlc3RJZDogcmVxLnJlcXVlc3RJZCxcbiAgICAgIH0pO1xuICAgIH0pO1xuICAgIG5leHQoKTtcbiAgfSk7XG5cbiAgLy8gUHJvbWV0aGV1cyBtZXRyaWNzIG1pZGRsZXdhcmUg4oCUIHJlY29yZHMgcmVxdWVzdCBkdXJhdGlvbiBhbmQgY291bnRcbiAgYXBwLnVzZShtZXRyaWNzTWlkZGxld2FyZSgpKTtcbn1cblxuLyoqXG4gKiBUaGUgZGVmYXVsdCBTU0UgbWFuYWdlci4gVGhlIHJlbGF5ICh0aGlzIHNlcnZpY2UncyBvd24gUmVkaXMgY2hhbm5lbCkgaXNcbiAqIGJ1aWx0IG9ubHkgd2hlbiBzb21ldGhpbmcgc3RyZWFtczogdGhlIGxvZyBzdHJlYW0gdHVybnMgaXQgb24gaGVyZSwgYW5kIGFuXG4gKiBvcmcta2V5ZWQgY2hhbm5lbCB0dXJucyBpdCBvbiB3aGVuIHJlZ2lzdGVyZWQgKHJlZ2lzdGVyU3NlVGlja2V0Q2hhbm5lbCkuXG4gKiBUaGUgbG9nIHRpY2tldCBzdG9yZSBleGlzdHMgb25seSB3aXRoIHRoZSBsb2cgc3RyZWFtLlxuICovXG5mdW5jdGlvbiBjcmVhdGVEZWZhdWx0U3NlTWFuYWdlcihzZXJ2aWNlTmFtZTogc3RyaW5nLCBsb2dTdHJlYW06IGJvb2xlYW4pOiBTU0VNYW5hZ2VyIHtcbiAgY29uc3Qgc3NlTWFuYWdlciA9IG5ldyBTU0VNYW5hZ2VyKHtcbiAgICBsb2dTdHJlYW0sXG4gICAgcmVsYXlGYWN0b3J5OiAoKSA9PiBjcmVhdGVFbnZSZWRpc1NTRVJlbGF5KHNlcnZpY2VOYW1lKSxcbiAgICAuLi4obG9nU3RyZWFtICYmIHtcbiAgICAgIHRpY2tldFN0b3JlOiBjcmVhdGVFbnZTc2VUaWNrZXRTdG9yZSh7XG4gICAgICAgIHR0bE1zOiBTU0VfVElDS0VUX1RUTF9NUyxcbiAgICAgICAga2V5UHJlZml4OiBgbG9nczoke3NlcnZpY2VOYW1lfWAsXG4gICAgICB9KSxcbiAgICB9KSxcbiAgfSk7XG4gIGlmIChsb2dTdHJlYW0pIHNzZU1hbmFnZXIuZW5hYmxlUmVsYXkoKTtcbiAgcmV0dXJuIHNzZU1hbmFnZXI7XG59XG5cbi8qKlxuICogVGhlIHBlci1yZXF1ZXN0IGJ1aWxkLWxvZyBzdHJlYW06IGBQT1NUIC9sb2dzL3RpY2tldGAgKyBgR0VUIC9sb2dzLzpyZXF1ZXN0SWRgLlxuICpcbiAqIFRpY2tldC1nYXRlZCDigJQgdGhlIHN0cmVhbSBjYXJyaWVzIHBlci1vcmcgYnVpbGQgbG9ncywgc28gaXQgbXVzdCBub3QgYmVcbiAqIHdvcmxkLXJlYWRhYmxlLiBDbGllbnRzIGZpcnN0IFBPU1QgL2xvZ3MvdGlja2V0IChKV1QtYXV0aGVudGljYXRlZCkgdG8gbWludCBhXG4gKiBzaG9ydC1saXZlZCwgc2luZ2xlLXVzZSB0aWNrZXQgYm91bmQgdG8gdGhlaXIgb3JnIEFORCB0byB0aGUgc3BlY2lmaWNcbiAqIGByZXF1ZXN0SWRgIHN0cmVhbSB0aGV5IGludGVuZCB0byBvcGVuLCB0aGVuIG9wZW4gdGhlIEV2ZW50U291cmNlIHdpdGhcbiAqID90aWNrZXQ9PHQ+LiBUaGlzIGtlZXBzIHRoZSBKV1Qgb3V0IG9mIHF1ZXJ5IHN0cmluZ3MgLyBhY2Nlc3MgbG9ncyB3aGlsZVxuICogZW5mb3JjaW5nIG9yZyBvd25lcnNoaXAsIHBlci1zdWJqZWN0IGF1dGhvcml6YXRpb24sIGFuZCB0aGUgcGVyLW9yZ1xuICogY29ubmVjdGlvbiBjYXAgb24gdGhlIHN0cmVhbS4gTWlycm9ycyB0aGUgbWVzc2FnZS1zZXJ2aWNlIG5vdGlmaWNhdGlvbnMgU1NFXG4gKiB0aWNrZXQgZXhjaGFuZ2UuXG4gKi9cbmZ1bmN0aW9uIHdpcmVTc2UoYXBwOiBFeHByZXNzLCBzc2VNYW5hZ2VyOiBTU0VNYW5hZ2VyKTogdm9pZCB7XG4gIGFwcC5wb3N0KCcvbG9ncy90aWNrZXQnLCByZXF1aXJlQXV0aCwgYXN5bmMgKHJlcTogUmVxdWVzdCwgcmVzOiBSZXNwb25zZSkgPT4ge1xuICAgIGNvbnN0IG9yZ0lkID0gcmVxLnVzZXI/Lm9yZ2FuaXphdGlvbklkPy50b0xvd2VyQ2FzZSgpO1xuICAgIGlmICghb3JnSWQpIHtcbiAgICAgIHNlbmRFcnJvcihyZXMsIDQwMCwgJ1Rva2VuIG1pc3Npbmcgb3JnYW5pemF0aW9uJywgRXJyb3JDb2RlLlZBTElEQVRJT05fRVJST1IpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICAvLyBUaGUgY2FsbGVyIG11c3QgbmFtZSB0aGUgc3RyZWFtIHN1YmplY3QgdXAgZnJvbnQgc28gdGhlIHRpY2tldCBpcyBib3VuZCB0b1xuICAgIC8vIGl0LiBXaXRob3V0IHRoaXMsIGEgdGlja2V0IGNvdWxkIGJlIHJlcGxheWVkIGFnYWluc3QgQU5ZIHJlcXVlc3RJZCB0aGVcbiAgICAvLyBvcmcgY291bGQgZ3Vlc3MsIGxldHRpbmcgaXQgYXR0YWNoIHRvIGFub3RoZXIgb3JnJ3MgbG9nIHN0cmVhbS4gU3RyaWN0bHlcbiAgICAvLyBmb3JtYXQtdmFsaWRhdGVkIHNvIGl0IGNhbid0IGNhcnJ5IGFuIGluamVjdGlvbiBwYXlsb2FkIGludG8gdGhlIHN1YmplY3QuXG4gICAgY29uc3QgcmVxdWVzdElkID0gKHJlcS5ib2R5IGFzIHsgcmVxdWVzdElkPzogdW5rbm93biB9IHwgdW5kZWZpbmVkKT8ucmVxdWVzdElkO1xuICAgIGlmICh0eXBlb2YgcmVxdWVzdElkICE9PSAnc3RyaW5nJyB8fCAhU1NFX1JFUVVFU1RfSURfUkUudGVzdChyZXF1ZXN0SWQpKSB7XG4gICAgICBzZW5kRXJyb3IocmVzLCA0MDAsICdNaXNzaW5nIG9yIGludmFsaWQgcmVxdWVzdElkJywgRXJyb3JDb2RlLlZBTElEQVRJT05fRVJST1IpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBzc2VNYW5hZ2VyLmNyZWF0ZVRpY2tldChvcmdJZCwgcmVxdWVzdElkKTtcbiAgICBpZiAoIXJlc3VsdC5vaykge1xuICAgICAgaWYgKHJlc3VsdC5yZWFzb24gPT09ICdmb3JiaWRkZW4nKSB7XG4gICAgICAgIC8vIFRoZSBzdWJqZWN0IGlzIG93bmVkIGJ5IGFub3RoZXIgb3JnIOKAlCBkbyBub3QgY29uZmlybSBpdCBleGlzdHM7IGEgcGxhaW5cbiAgICAgICAgLy8gNDAzIGlzIGVub3VnaCBhbmQgbGVha3Mgbm90aGluZyBhYm91dCB3aGljaCByZXF1ZXN0SWRzIGFyZSBsaXZlLlxuICAgICAgICBzZW5kRXJyb3IocmVzLCA0MDMsICdOb3QgYXV0aG9yaXplZCBmb3IgdGhpcyBsb2cgc3RyZWFtJywgRXJyb3JDb2RlLklOU1VGRklDSUVOVF9QRVJNSVNTSU9OUyk7XG4gICAgICB9IGVsc2UgaWYgKHJlc3VsdC5yZWFzb24gPT09ICdvcmctbGltaXQnKSB7XG4gICAgICAgIHNlbmRFcnJvcihyZXMsIDQyOSwgJ1RvbyBtYW55IGxvZyBzdHJlYW0gdGlja2V0cyBpc3N1ZWQnLCBFcnJvckNvZGUuUVVPVEFfRVhDRUVERUQpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgc2VuZEVycm9yKHJlcywgNTAzLCAnTG9nIHN0cmVhbWluZyBzdWJzeXN0ZW0gYXQgY2FwYWNpdHknLCBFcnJvckNvZGUuUVVPVEFfRVhDRUVERUQpO1xuICAgICAgfVxuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBzZW5kU3VjY2VzcyhyZXMsIDIwMCwgeyB0aWNrZXQ6IHJlc3VsdC50aWNrZXQgfSk7XG4gIH0pO1xuXG4gIC8vIFRoZSBzdHJlYW0gaXRzZWxmIHJlc29sdmVzICsgY29uc3VtZXMgdGhlIHRpY2tldCBpbnNpZGUgbWlkZGxld2FyZSgpIGFuZFxuICAvLyByZWplY3RzIGFueSBhbm9ueW1vdXMgLyBpbnZhbGlkIC8gZXhwaXJlZCAvIGFscmVhZHktdXNlZCB0aWNrZXQgd2l0aCA0MDEuXG4gIGFwcC5nZXQoJy9sb2dzLzpyZXF1ZXN0SWQnLCBzc2VNYW5hZ2VyLm1pZGRsZXdhcmUoKSk7XG59XG5cbi8qKlxuICogQ3JlYXRlIGFuZCBjb25maWd1cmUgYW4gRXhwcmVzcyBhcHBsaWNhdGlvbiB3aXRoIGNvbW1vbiBtaWRkbGV3YXJlXG4gKlxuICogU2V0cyB1cDpcbiAqIC0gQ09SUyB3aXRoIGNvbmZpZ3VyZWQgb3JpZ2luc1xuICogLSBIZWxtZXQgc2VjdXJpdHkgaGVhZGVyc1xuICogLSBSYXRlIGxpbWl0aW5nXG4gKiAtIEpTT04gYW5kIFVSTC1lbmNvZGVkIGJvZHkgcGFyc2luZ1xuICogLSBUcnVzdCBwcm94eSBzZXR0aW5nc1xuICogLSBIZWFsdGggY2hlY2sgZW5kcG9pbnQgKC9oZWFsdGgpXG4gKiAtIE1ldHJpY3MgZW5kcG9pbnQgKC9tZXRyaWNzKVxuICogLSBTU0UgbG9ncyBlbmRwb2ludCAoL2xvZ3MvOnJlcXVlc3RJZCkg4oCUIG9ubHkgd2l0aCBgbG9nU3RyZWFtOiB0cnVlYFxuICpcbiAqIEBwYXJhbSBvcHRpb25zIC0gQ29uZmlndXJhdGlvbiBvcHRpb25zXG4gKiBAcmV0dXJucyBDb25maWd1cmVkIEV4cHJlc3MgYXBwIGFuZCBTU0UgbWFuYWdlclxuICpcbiAqIEBleGFtcGxlXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiBjb25zdCB7IGFwcCwgc3NlTWFuYWdlciB9ID0gY3JlYXRlQXBwKCk7XG4gKlxuICogYXBwLnBvc3QoJy9hcGkvcmVzb3VyY2UnLCByZXF1aXJlQXV0aCwgYXN5bmMgKHJlcSwgcmVzKSA9PiB7XG4gKiAgIC8vIFlvdXIgcm91dGUgaGFuZGxlclxuICogfSk7XG4gKlxuICogc3RhcnRTZXJ2ZXIoYXBwLCB7IG5hbWU6ICdNeSBTZXJ2aWNlJyB9KTtcbiAqIGBgYFxuICovXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlQXBwKG9wdGlvbnM6IENyZWF0ZUFwcE9wdGlvbnMgPSB7fSk6IENyZWF0ZUFwcFJlc3VsdCB7XG4gIGNvbnN0IHtcbiAgICBlbmFibGVSYXRlTGltaXQgPSB0cnVlLFxuICAgIGxvZ1N0cmVhbSA9IGZhbHNlLFxuICAgIGVuYWJsZU9wZW5BcGkgPSBwcm9jZXNzLmVudi5OT0RFX0VOViAhPT0gJ3Byb2R1Y3Rpb24nLFxuICB9ID0gb3B0aW9ucztcblxuICBjb25zdCBzZXJ2aWNlTmFtZSA9IHByb2Nlc3MuZW52LlNFUlZJQ0VfTkFNRSB8fCAnYXBpJztcblxuICAvLyBBIGNhbGxlci1zdXBwbGllZCBgc3NlTWFuYWdlcmAgc2tpcHMgdGhlIGRlZmF1bHQgY29uc3RydWN0aW9uIGVudGlyZWx5LlxuICBjb25zdCBzc2VNYW5hZ2VyID0gb3B0aW9ucy5zc2VNYW5hZ2VyID8/IGNyZWF0ZURlZmF1bHRTc2VNYW5hZ2VyKHNlcnZpY2VOYW1lLCBsb2dTdHJlYW0pO1xuXG4gIC8vIFdpcmUgdGhlIGlkZW1wb3RlbmN5IHJlcGxheS1jYWNoZSBiYWNrZW5kIHVzZWQgYnkgdGhlIHBvc3QtYXV0aCByb3V0ZVxuICAvLyBmYWN0b3JpZXMgKGNyZWF0ZVByb3RlY3RlZFJvdXRlIC8gY3JlYXRlQXV0aGVudGljYXRlZFdpdGhPcmdSb3V0ZSkuIFByZWZlclxuICAvLyBhbiBleHBsaWNpdGx5IGluamVjdGVkIHN0b3JlOyBvdGhlcndpc2UgYXV0by1jb25zdHJ1Y3QgZnJvbSB0aGUgc2hhcmVkIGVudlxuICAvLyBSZWRpcyBzbyBrZXllZCBtdXRhdGlvbiByZXRyaWVzIGRlZHVwZSBhY3Jvc3MgcmVwbGljYXMuIEZhbGxzIGJhY2sgdG8gdGhlXG4gIC8vIGluLW1lbW9yeSBkZWZhdWx0IHdoZW4gbm8gUmVkaXMgaXMgY29uZmlndXJlZCAoc2luZ2xlLXJlcGxpY2EgY29ycmVjdG5lc3MpLlxuICBjb25zdCByZXNvbHZlZElkZW1wb3RlbmN5U3RvcmUgPSBvcHRpb25zLmlkZW1wb3RlbmN5U3RvcmUgPz8gY3JlYXRlRW52UmVkaXNJZGVtcG90ZW5jeVN0b3JlKCk7XG4gIGlmIChyZXNvbHZlZElkZW1wb3RlbmN5U3RvcmUpIHtcbiAgICBzZXRJZGVtcG90ZW5jeVN0b3JlKHJlc29sdmVkSWRlbXBvdGVuY3lTdG9yZSk7XG4gIH1cblxuICAvLyBPcGVuVGVsZW1ldHJ5IGlzIE5PVCBpbml0aWFsaXplZCBoZXJlOiBieSB0aGUgdGltZSBjcmVhdGVBcHAgcnVucywgZXhwcmVzc1xuICAvLyBhbmQgaHR0cCBoYXZlIGFscmVhZHkgYmVlbiByZXF1aXJlZCwgc28gdGhlIGF1dG8taW5zdHJ1bWVudGF0aW9uIGhvb2tzXG4gIC8vIHdvdWxkIGhhdmUgbm90aGluZyB0byBwYXRjaCAobm8gaW5ib3VuZCBzcGFuIOKGkiBubyB0cmFjZSBpZCkuIFRyYWNpbmcgaXNcbiAgLy8gc3RhcnRlZCBieSB0aGUgYG90ZWwtYm9vdHN0cmFwLmpzYCBwcmVsb2FkIGluc3RlYWQgKG5vZGUgLXIg4oCmIOKAlCBzZWUgZWFjaFxuICAvLyBzZXJ2aWNlJ3MgRG9ja2VyZmlsZSBDTUQgLyBzdGFydCBzY3JpcHQpLCB3aGljaCBydW5zIGJlZm9yZSBhbnlcbiAgLy8gaW5zdHJ1bWVudGVkIG1vZHVsZSBsb2Fkcy4gYGN1cnJlbnRUcmFjZUlkKClgIHRoZW4gcmVhZHMgdGhlIGFjdGl2ZSBzcGFuLlxuXG4gIGNvbnN0IGFwcCA9IGV4cHJlc3MoKTtcblxuICBhcHBseVNlY3VyaXR5SGVhZGVycyhhcHAsIG9wdGlvbnMsIGVuYWJsZU9wZW5BcGkpO1xuICBhcHBseUJvZHlQYXJzaW5nKGFwcCwgb3B0aW9ucyk7XG5cbiAgLy8gVHJ1c3QgcHJveHkgKG11c3QgYmUgc2V0IGJlZm9yZSByYXRlIGxpbWl0ZXIgc28gcmVxLmlwIHJlc29sdmVzIGNvcnJlY3RseSlcbiAgYXBwLnNldCgndHJ1c3QgcHJveHknLCBDb25maWcuZ2V0KCdzZXJ2ZXInKS50cnVzdFByb3h5KTtcblxuICAvLyBSZXF1ZXN0IElEIOKAlCBwcmVmZXIgZXhpc3RpbmcgaGVhZGVyIGZyb20gbmdpbngsIG90aGVyd2lzZSBnZW5lcmF0ZSBvbmVcbiAgYXBwLnVzZSgocmVxOiBSZXF1ZXN0LCByZXM6IFJlc3BvbnNlLCBuZXh0OiBOZXh0RnVuY3Rpb24pID0+IHtcbiAgICBjb25zdCBoZHIgPSByZXEuaGVhZGVyc1sneC1yZXF1ZXN0LWlkJ107XG4gICAgY29uc3QgcmVxdWVzdElkID0gKEFycmF5LmlzQXJyYXkoaGRyKSA/IGhkclswXSA6IGhkcikgfHwgdXVpZCgpO1xuICAgIHJlcS5yZXF1ZXN0SWQgPSByZXF1ZXN0SWQ7XG4gICAgcmVzLnNldEhlYWRlcignWC1SZXF1ZXN0LUlkJywgcmVxdWVzdElkKTtcbiAgICBuZXh0KCk7XG4gIH0pO1xuXG4gIG1vdW50SW5mcmFFbmRwb2ludHMoYXBwLCBvcHRpb25zLCBzZXJ2aWNlTmFtZSwgZW5hYmxlT3BlbkFwaSk7XG4gIGlmIChlbmFibGVSYXRlTGltaXQpIG1vdW50UmF0ZUxpbWl0ZXIoYXBwLCBzZXJ2aWNlTmFtZSk7XG4gIGFwcGx5UmVxdWVzdFRlbGVtZXRyeShhcHApO1xuXG4gIC8vIE5PVEU6IGlkZW1wb3RlbmN5IGlzIGludGVudGlvbmFsbHkgTk9UIG1vdW50ZWQgaGVyZS4gSXQgbmVlZHMgdGhlIFZFUklGSUVEXG4gIC8vIG9yZyBpZCB0byBuYW1lc3BhY2UgaXRzIHJlcGxheSBjYWNoZSwgYnV0IHRoaXMgcHJlLWF1dGggcG9zaXRpb24gcnVucyBiZWZvcmVcbiAgLy8gYHJlcXVpcmVBdXRoYC9gYXR0YWNoUmVxdWVzdENvbnRleHRgIHBvcHVsYXRlIGlkZW50aXR5LCBzbyBhIGdsb2JhbCBtb3VudFxuICAvLyBoZXJlIGlzIGEgcGVybWFuZW50IG5vLW9wIChvcmcgYWx3YXlzIHVuZGVmaW5lZCDihpIgc2tpcCkuIEl0IGlzIGluc3RlYWQgd2lyZWRcbiAgLy8gaW50byB0aGUgcG9zdC1hdXRoIHJvdXRlIGNoYWlucyDigJQgc2VlIGBjcmVhdGVQcm90ZWN0ZWRSb3V0ZWAgL1xuICAvLyBgY3JlYXRlQXV0aGVudGljYXRlZFdpdGhPcmdSb3V0ZWAgaW4gbWlkZGxld2FyZS1mYWN0b3J5LnRzLlxuXG4gIGlmIChsb2dTdHJlYW0pIHdpcmVTc2UoYXBwLCBzc2VNYW5hZ2VyKTtcblxuICByZXR1cm4geyBhcHAsIHNzZU1hbmFnZXIgfTtcbn1cbiJdfQ==
|
|
396
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXBwLWZhY3RvcnkuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvYXBpL2FwcC1mYWN0b3J5LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLCtDQUErQztBQUMvQyxzQ0FBc0M7QUFFdEMsT0FBTyxFQUFFLFdBQVcsRUFBRSxTQUFTLEVBQUUsbUJBQW1CLEVBQUUsU0FBUyxFQUFFLFlBQVksRUFBRSxzQkFBc0IsRUFBRSxrQkFBa0IsRUFBRSxpQkFBaUIsRUFBRSxlQUFlLEVBQUUsV0FBVyxFQUFFLFNBQVMsRUFBRSx1QkFBdUIsRUFBRSxpQkFBaUIsRUFBRSx1QkFBdUIsRUFBRSxtQkFBbUIsRUFBRSxxQkFBcUIsRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBRTNVLE9BQU8sRUFBRSxNQUFNLEVBQUUsYUFBYSxFQUFFLE1BQU0saUNBQWlDLENBQUM7QUFDeEUsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLGlDQUFpQyxDQUFDO0FBQ2hFLE9BQU8sV0FBVyxNQUFNLGFBQWEsQ0FBQztBQUN0QyxPQUFPLElBQUksTUFBTSxNQUFNLENBQUM7QUFDeEIsT0FBTyxPQUFPLEVBQUUsRUFBZ0UsTUFBTSxTQUFTLENBQUM7QUFDaEcsT0FBTyxTQUFTLEVBQUUsRUFBRSxjQUFjLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUMvRCxPQUFPLE1BQU0sTUFBTSxRQUFRLENBQUM7QUFDNUIsT0FBTyxTQUFTLE1BQU0sb0JBQW9CLENBQUM7QUFDM0MsT0FBTyxFQUFFLEVBQUUsSUFBSSxJQUFJLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDbEMsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBQ3RELE9BQU8sRUFBRSw4QkFBOEIsRUFBRSxtQkFBbUIsRUFBeUIsTUFBTSw2QkFBNkIsQ0FBQztBQUN6SCxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsY0FBYyxFQUFFLFVBQVUsRUFBRSxRQUFRLEVBQUUsTUFBTSxjQUFjLENBQUM7QUFD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QUFFLE9BQU8sRUFBRSxjQUFjLEVBQUUsRUFBRSxDQUFDLEVBQUUsSUFBSSxDQUFDLENBQUM7SUFDcEcsQ0FBQyxDQUFDLENBQUM7SUFFSCxtQkFBbUIsQ0FBQyxHQUFHLEVBQUUsT0FBTyxFQUFFLFdBQVcsRUFBRSxhQUFhLENBQUMsQ0FBQztJQUM5RCxJQUFJLGVBQWU7UUFBRSxnQkFBZ0IsQ0FBQyxHQUFHLEVBQUUsV0FBVyxDQUFDLENBQUM7SUFDeEQscUJBQXFCLENBQUMsR0FBRyxDQUFDLENBQUM7SUFFM0IsNkVBQTZFO0lBQzdFLCtFQUErRTtJQUMvRSw0RUFBNEU7SUFDNUUsK0VBQStFO0lBQy9FLGlFQUFpRTtJQUNqRSw4REFBOEQ7SUFFOUQsSUFBSSxTQUFTO1FBQUUsT0FBTyxDQUFDLEdBQUcsRUFBRSxVQUFVLENBQUMsQ0FBQztJQUV4QyxPQUFPLEVBQUUsR0FBRyxFQUFFLFVBQVUsRUFBRSxDQUFDO0FBQzdCLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBDb3B5cmlnaHQgMjAyNiBQaXBlbGluZSBCdWlsZGVyIENvbnRyaWJ1dG9yc1xuLy8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFwYWNoZS0yLjBcblxuaW1wb3J0IHsgc2VuZFN1Y2Nlc3MsIHNlbmRFcnJvciwgZ2VuZXJhdGVPcGVuQXBpU3BlYywgRXJyb3JDb2RlLCBjcmVhdGVMb2dnZXIsIHZlcmlmeVNlcnZpY2VQcmluY2lwYWwsIGNyZWF0ZUhlYWx0aFJvdXRlciwgc2V0Q291bnRlckVtaXR0ZXIsIHNldEdhdWdlRW1pdHRlciwgcmVxdWlyZUF1dGgsIHNhZmVFcXVhbCwgY3JlYXRlRW52U3NlVGlja2V0U3RvcmUsIFNTRV9USUNLRVRfVFRMX01TLCBhdWRpdENvbnRleHRGcm9tUmVxdWVzdCwgcnVuV2l0aEF1ZGl0Q29udGV4dCwgc2FuaXRpemVDb3JyZWxhdGlvbklkIH0gZnJvbSAnQHBpcGVsaW5lLWJ1aWxkZXIvYXBpLWNvcmUnO1xuaW1wb3J0IHR5cGUgeyBPcGVuQXBpU3BlY09wdGlvbnMgfSBmcm9tICdAcGlwZWxpbmUtYnVpbGRlci9hcGktY29yZSc7XG5pbXBvcnQgeyBDb25maWcsIENvcmVDb25zdGFudHMgfSBmcm9tICdAcGlwZWxpbmUtYnVpbGRlci9waXBlbGluZS1jb3JlJztcbmltcG9ydCB7IGdldENvbm5lY3Rpb24gfSBmcm9tICdAcGlwZWxpbmUtYnVpbGRlci9waXBlbGluZS1kYXRhJztcbmltcG9ydCBjb21wcmVzc2lvbiBmcm9tICdjb21wcmVzc2lvbic7XG5pbXBvcnQgY29ycyBmcm9tICdjb3JzJztcbmltcG9ydCBleHByZXNzLCB7IHR5cGUgRXhwcmVzcywgdHlwZSBOZXh0RnVuY3Rpb24sIHR5cGUgUmVxdWVzdCwgdHlwZSBSZXNwb25zZSB9IGZyb20gJ2V4cHJlc3MnO1xuaW1wb3J0IHJhdGVMaW1pdCwgeyBpcEtleUdlbmVyYXRvciB9IGZyb20gJ2V4cHJlc3MtcmF0ZS1saW1pdCc7XG5pbXBvcnQgaGVsbWV0IGZyb20gJ2hlbG1ldCc7XG5pbXBvcnQgc3dhZ2dlclVpIGZyb20gJ3N3YWdnZXItdWktZXhwcmVzcyc7XG5pbXBvcnQgeyB2NyBhcyB1dWlkIH0gZnJvbSAndXVpZCc7XG5pbXBvcnQgeyBldGFnTWlkZGxld2FyZSB9IGZyb20gJy4vZXRhZy1taWRkbGV3YXJlLmpzJztcbmltcG9ydCB7IGNyZWF0ZUVudlJlZGlzSWRlbXBvdGVuY3lTdG9yZSwgc2V0SWRlbXBvdGVuY3lTdG9yZSwgdHlwZSBJZGVtcG90ZW5jeVN0b3JlIH0gZnJvbSAnLi9pZGVtcG90ZW5jeS1taWRkbGV3YXJlLmpzJztcbmltcG9ydCB7IG1ldHJpY3NNaWRkbGV3YXJlLCBtZXRyaWNzSGFuZGxlciwgaW5jQ291bnRlciwgc2V0R2F1Z2UgfSBmcm9tICcuL21ldHJpY3MuanMnO1xuaW1wb3J0IHsgY3JlYXRlU2hhcmVkUmF0ZUxpbWl0U3RvcmUgfSBmcm9tICcuL3JhdGUtbGltaXQtc3RvcmUuanMnO1xuaW1wb3J0IHsgcmVhZGluZXNzR3VhcmQgfSBmcm9tICcuL3JlYWRpbmVzcy5qcyc7XG5pbXBvcnQgeyBjdXJyZW50VHJhY2VJZCB9IGZyb20gJy4vdHJhY2luZy5qcyc7XG5pbXBvcnQgeyBTU0VNYW5hZ2VyLCBTU0VfUkVRVUVTVF9JRF9SRSB9IGZyb20gJy4uL2h0dHAvc3NlLWNvbm5lY3Rpb24tbWFuYWdlci5qcyc7XG5pbXBvcnQgeyBjcmVhdGVFbnZSZWRpc1NTRVJlbGF5IH0gZnJvbSAnLi4vaHR0cC9zc2UtcmVsYXkuanMnO1xuXG4vLyBXaXJlIGFwaS1jb3JlJ3MgY291bnRlciBzaGltIHRvIHRoZSByZWFsIHByb20tY2xpZW50IHJlZ2lzdHJ5LiBUaGlzIGlzXG4vLyBhIG5vLW9wIHVudGlsIGluY0NvdW50ZXIgaXMgY2FsbGVkIGZvciB0aGUgZmlyc3QgdGltZSAobGF6eSByZWdpc3RyYXRpb25cbi8vIGluIG1ldHJpY3MudHMpLCBhbmQgbGV0cyBhcGktY29yZSBoZWxwZXJzIGxpa2UgdGhlIHF1b3RhIGNsaWVudCByZWNvcmRcbi8vIGBxdW90YV9mYWlsX29wZW5fdG90YWxgIHdpdGhvdXQgdGFraW5nIGEgaGFyZCBkZXAgb24gYXBpLXNlcnZlci5cbnNldENvdW50ZXJFbWl0dGVyKGluY0NvdW50ZXIpO1xuLy8gU2FtZSBzZWFtIGZvciBHQVVHRVMuIHBpcGVsaW5lLWRhdGEncyByZWFkLXJlcGxpY2EgbGFnIHNhbXBsZXIgbmVlZHMgaXQ6XG4vLyByZXBsYXkgbGFnIGFuZCB0aGUgc3RhdGUgb2YgdGhlIHJlYWQgZmFsbGJhY2sgY2lyY3VpdCBhcmUgc2FtcGxlZFxuLy8gcG9pbnQtaW4tdGltZSB2YWx1ZXMsIHNvIGVtaXR0aW5nIHRoZW0gYXMgY291bnRlcnMgd291bGQgbWFrZSBldmVyeSBxdWVyeVxuLy8gb3ZlciB0aGVtIHdyb25nLiBwaXBlbGluZS1kYXRhIGRlcGVuZHMgb24gYXBpLWNvcmUgYW5kIG11c3Qgbm90IGRlcGVuZCBvblxuLy8gYXBpLXNlcnZlciwgaGVuY2UgdGhlIHNoaW0gcmF0aGVyIHRoYW4gYSBkaXJlY3QgaW1wb3J0Llxuc2V0R2F1Z2VFbWl0dGVyKHNldEdhdWdlKTtcblxuLyoqXG4gKiBPcHRpb25zIGZvciBjcmVhdGluZyBhbiBFeHByZXNzIGFwcGxpY2F0aW9uXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgQ3JlYXRlQXBwT3B0aW9ucyB7XG4gIC8qKiBFbmFibGUgQ09SUyAoZGVmYXVsdDogdHJ1ZSkgKi9cbiAgZW5hYmxlQ29ycz86IGJvb2xlYW47XG4gIC8qKiBFbmFibGUgSGVsbWV0IHNlY3VyaXR5IGhlYWRlcnMgKGRlZmF1bHQ6IHRydWUpICovXG4gIGVuYWJsZUhlbG1ldD86IGJvb2xlYW47XG4gIC8qKiBFbmFibGUgcmF0ZSBsaW1pdGluZyAoZGVmYXVsdDogdHJ1ZSkgKi9cbiAgZW5hYmxlUmF0ZUxpbWl0PzogYm9vbGVhbjtcbiAgLyoqIEVuYWJsZSBKU09OIGJvZHkgcGFyc2luZyAoZGVmYXVsdDogdHJ1ZSkgKi9cbiAgZW5hYmxlSnNvbkJvZHk/OiBib29sZWFuO1xuICAvKiogSlNPTiBib2R5IHNpemUgbGltaXQgKGRlZmF1bHQ6ICcxbWInKSAqL1xuICBqc29uTGltaXQ/OiBzdHJpbmc7XG4gIC8qKlxuICAgKiBQYXRoIHByZWZpeGVzIHRoZSBnbG9iYWwgSlNPTiBib2R5IHBhcnNlciBtdXN0IE5PVCB0b3VjaCDigJQgZm9yIHJvdXRlcyB0aGF0IG5lZWRcbiAgICogdGhlIHJhdyBib2R5IChlLmcuIGEgU3RyaXBlIHdlYmhvb2sgd2hvc2UgSE1BQyBpcyBjb21wdXRlZCBvdmVyIHRoZSBleGFjdCBieXRlcykuXG4gICAqIFdpdGhvdXQgdGhpcyB0aGUgZ2xvYmFsIHBhcnNlciBjb25zdW1lcyB0aGUgYm9keSBmaXJzdCBhbmQgYSBsYXRlciBgZXhwcmVzcy5yYXcoKWBcbiAgICogb24gdGhlIHNhbWUgcGF0aCBpcyBhIG5vLW9wLCBicmVha2luZyBzaWduYXR1cmUgdmVyaWZpY2F0aW9uLlxuICAgKi9cbiAganNvbkJvZHlFeGNsdWRlPzogc3RyaW5nW107XG4gIC8qKiBFbmFibGUgVVJMLWVuY29kZWQgYm9keSBwYXJzaW5nIChkZWZhdWx0OiB0cnVlKSAqL1xuICBlbmFibGVVcmxFbmNvZGVkPzogYm9vbGVhbjtcbiAgLyoqIFVSTC1lbmNvZGVkIGJvZHkgc2l6ZSBsaW1pdCAoZGVmYXVsdDogJzFtYicpICovXG4gIHVybEVuY29kZWRMaW1pdD86IHN0cmluZztcbiAgLyoqIEN1c3RvbSBTU0UgbWFuYWdlciBpbnN0YW5jZSAqL1xuICBzc2VNYW5hZ2VyPzogU1NFTWFuYWdlcjtcbiAgLyoqXG4gICAqIFNlcnZlIHRoZSBwZXItcmVxdWVzdCBidWlsZC1sb2cgc3RyZWFtOiBgUE9TVCAvbG9ncy90aWNrZXRgICtcbiAgICogYEdFVCAvbG9ncy86cmVxdWVzdElkYCwgYSBsb2cgdGlja2V0IHN0b3JlLCB0aGUgY3Jvc3MtcG9kIHJlbGF5LCBhbmRcbiAgICogYGN0eC5sb2dgIGZyYW1lcyBwdXNoZWQgdG8gU1NFLiBEZWZhdWx0IGZhbHNlIOKAlCBhIHNlcnZpY2Ugd2l0aG91dCBpdCBoYXMgbm9cbiAgICogYC9sb2dzYCByb3V0ZXMgYW5kIGBjdHgubG9nYCBvbmx5IHdyaXRlcyB0byB0aGUgbG9nZ2VyLlxuICAgKi9cbiAgbG9nU3RyZWFtPzogYm9vbGVhbjtcbiAgLyoqIEhlYWx0aCBjaGVjayBkZXBlbmRlbmN5IGNoZWNrZXIg4oCUIGlmIHByb3ZpZGVkLCAvaGVhbHRoIHJlcG9ydHMgZGVwZW5kZW5jeSBzdGF0dXMgKi9cbiAgY2hlY2tEZXBlbmRlbmNpZXM/OiAoKSA9PiBQcm9taXNlPFJlY29yZDxzdHJpbmcsICdjb25uZWN0ZWQnIHwgJ2Rpc2Nvbm5lY3RlZCcgfCAndW5rbm93bic+PjtcbiAgLyoqXG4gICAqIFNlcnZlIHRoZSBPcGVuQVBJIHNwZWMgYXQgYC9kb2NzL29wZW5hcGkuanNvbmAgYW5kIFN3YWdnZXIgVUkgYXQgYC9kb2NzYC5cbiAgICpcbiAgICogRGVmYXVsdHMgdG8gT0ZGIHVuZGVyIGBOT0RFX0VOVj1wcm9kdWN0aW9uYDogdGhlIHJvdXRlcyBhcmUgcmVnaXN0ZXJlZCBhYm92ZVxuICAgKiB0aGUgcmF0ZSBsaW1pdGVyIGFuZCBhcmUgbm90IGF1dGgtZ2F0ZWQsIHNvIGluIHByb2R1Y3Rpb24gdGhleSB3b3VsZCBwdWJsaXNoXG4gICAqIHRoZSBmdWxsIHJvdXRlICsgc2NoZW1hIGludmVudG9yeSBvZiBldmVyeSBzZXJ2aWNlIHRvIGFueW9uZSB3aG8gY291bGQgcmVhY2hcbiAgICogdGhlIHBvcnQuIFBhc3MgYHRydWVgIGV4cGxpY2l0bHkgdG8gc2VydmUgdGhlbSBpbiBwcm9kdWN0aW9uIGFueXdheS5cbiAgICovXG4gIGVuYWJsZU9wZW5BcGk/OiBib29sZWFuO1xuICAvKiogT3BlbkFQSSBzcGVjIGN1c3RvbWl6YXRpb24gb3B0aW9ucyAqL1xuICBvcGVuQXBpT3B0aW9ucz86IE9wZW5BcGlTcGVjT3B0aW9ucztcbiAgLyoqIEVuYWJsZSBnemlwL2RlZmxhdGUgcmVzcG9uc2UgY29tcHJlc3Npb24gKGRlZmF1bHQ6IHRydWUpICovXG4gIGVuYWJsZUNvbXByZXNzaW9uPzogYm9vbGVhbjtcbiAgLyoqXG4gICAqIElkZW1wb3RlbmN5IHJlcGxheS1jYWNoZSBiYWNrZW5kIGZvciBrZXllZCBtdXRhdGlvbiByZXRyaWVzLiBXaGVuIG9taXR0ZWQsXG4gICAqIGNyZWF0ZUFwcCBhdXRvLXdpcmVzIHRoZSBzaGFyZWQgZW52IFJlZGlzIHN0b3JlIChtdWx0aS1yZXBsaWNhIGRlZHVwKSBpZlxuICAgKiBSZWRpcyBpcyBjb25maWd1cmVkLCBlbHNlIGtlZXBzIHRoZSBpbi1tZW1vcnkgZGVmYXVsdCAoc2luZ2xlLXJlcGxpY2EpLlxuICAgKiBQYXNzIGFuIGV4cGxpY2l0IHN0b3JlIHRvIGluamVjdCBhIGJlc3Bva2UgYmFja2VuZCAoZS5nLiBhIHNlcnZpY2UncyBvd25cbiAgICogaW9yZWRpcyBjb25uZWN0aW9uKS5cbiAgICovXG4gIGlkZW1wb3RlbmN5U3RvcmU/OiBJZGVtcG90ZW5jeVN0b3JlO1xuICAvKipcbiAgICogRXh0cmEgd2FybXVwIGNhbGxiYWNrcyBpbnZva2VkIGJ5IGBHRVQgL3dhcm11cGAgaW4gYWRkaXRpb24gdG8gdGhlXG4gICAqIGRlZmF1bHQgUG9zdGdyZXMgcGluZy4gVXNlIGZvciBzZXJ2aWNlcyB0aGF0IGRlcGVuZCBvbiBNb25nbywgUmVkaXMsXG4gICAqIFNRUywgZXRjLiDigJQgcHJlLXdhcm1pbmcgb3BlbnMgY29ubmVjdGlvbiBwb29scyBiZWZvcmUgcmVhbCB0cmFmZmljXG4gICAqIGFycml2ZXMuIEVhY2ggY2FsbGJhY2sgc2hvdWxkIHJlc29sdmUgd2hlbiBpdHMgZGVwZW5kZW5jeSBpcyByZWFkeTtcbiAgICogYW55IHJlamVjdGlvbiBjYXVzZXMgL3dhcm11cCB0byByZXR1cm4gNTAzLlxuICAgKi9cbiAgd2FybXVwSG9va3M/OiBBcnJheTwoKSA9PiBQcm9taXNlPHZvaWQ+Pjtcbn1cblxuLyoqXG4gKiBSZXN1bHQgb2YgY3JlYXRpbmcgYW4gRXhwcmVzcyBhcHBsaWNhdGlvblxuICovXG5leHBvcnQgaW50ZXJmYWNlIENyZWF0ZUFwcFJlc3VsdCB7XG4gIC8qKiBDb25maWd1cmVkIEV4cHJlc3MgYXBwbGljYXRpb24gKi9cbiAgYXBwOiBFeHByZXNzO1xuICAvKiogU1NFIG1hbmFnZXIgaW5zdGFuY2UgKi9cbiAgc3NlTWFuYWdlcjogU1NFTWFuYWdlcjtcbn1cblxuLyoqIEhlbG1ldCAoc3RyaWN0IENTUCksIENPUlMsIGNvbXByZXNzaW9uIGFuZCBFVGFncy4gKi9cbmZ1bmN0aW9uIGFwcGx5U2VjdXJpdHlIZWFkZXJzKGFwcDogRXhwcmVzcywgb3B0aW9uczogQ3JlYXRlQXBwT3B0aW9ucywgZW5hYmxlT3BlbkFwaTogYm9vbGVhbik6IHZvaWQge1xuICBjb25zdCB7IGVuYWJsZUNvcnMgPSB0cnVlLCBlbmFibGVIZWxtZXQgPSB0cnVlLCBlbmFibGVDb21wcmVzc2lvbiA9IHRydWUgfSA9IG9wdGlvbnM7XG4gIC8vIFN3YWdnZXIgVUkgbmVlZHMgdW5zYWZlLWlubGluZSArIHVuc2FmZS1ldmFsIGZvciBpdHMgYnVuZGxlZCBzY3JpcHRzIOKAlFxuICAvLyBidXQgQ1NQIGlzIG9ubHkgcmVsYXhlZCB0aGF0IGZhciB3aGVuIChhKSBPcGVuQVBJIGlzIGVuYWJsZWQgQU5EIChiKSB3ZSdyZVxuICAvLyBub3QgaW4gcHJvZHVjdGlvbi4gSW4gcHJvZCwgU3dhZ2dlciBzaG91bGQgYmUgc2VydmVkIGJlaGluZCBhIHNlcGFyYXRlXG4gIC8vIGhvc3Qgb3IgYXV0aC1nYXRlZCByb3V0ZTsgdGhlIG1haW4gYXBwIGtlZXBzIHRoZSBzdHJpY3QgQ1NQIHNvIGEgU3RvcmVkXG4gIC8vIFhTUyBpbiBhbnkgaGFuZGxlciBjYW4ndCBgZXZhbCgpYCBhcmJpdHJhcnkgc2NyaXB0LlxuICBjb25zdCBhbGxvd1N3YWdnZXJDc3AgPSBlbmFibGVPcGVuQXBpICYmIHByb2Nlc3MuZW52Lk5PREVfRU5WICE9PSAncHJvZHVjdGlvbic7XG4gIGlmIChlbmFibGVIZWxtZXQpIHtcbiAgICBhcHAudXNlKGhlbG1ldCh7XG4gICAgICBjb250ZW50U2VjdXJpdHlQb2xpY3k6IHtcbiAgICAgICAgZGlyZWN0aXZlczoge1xuICAgICAgICAgIGRlZmF1bHRTcmM6IFtcIidzZWxmJ1wiXSxcbiAgICAgICAgICBzY3JpcHRTcmM6IGFsbG93U3dhZ2dlckNzcFxuICAgICAgICAgICAgPyBbXCInc2VsZidcIiwgXCIndW5zYWZlLWlubGluZSdcIiwgXCIndW5zYWZlLWV2YWwnXCJdXG4gICAgICAgICAgICA6IFtcIidzZWxmJ1wiXSxcbiAgICAgICAgICBzdHlsZVNyYzogW1wiJ3NlbGYnXCIsIFwiJ3Vuc2FmZS1pbmxpbmUnXCJdLFxuICAgICAgICAgIGltZ1NyYzogW1wiJ3NlbGYnXCIsICdkYXRhOicsICdibG9iOiddLFxuICAgICAgICAgIGNvbm5lY3RTcmM6IFtcIidzZWxmJ1wiXSxcbiAgICAgICAgICBmb250U3JjOiBbXCInc2VsZidcIl0sXG4gICAgICAgICAgb2JqZWN0U3JjOiBbXCInbm9uZSdcIl0sXG4gICAgICAgICAgZnJhbWVBbmNlc3RvcnM6IFtcIidub25lJ1wiXSxcbiAgICAgICAgICBiYXNlVXJpOiBbXCInc2VsZidcIl0sXG4gICAgICAgICAgZm9ybUFjdGlvbjogW1wiJ3NlbGYnXCJdLFxuICAgICAgICB9LFxuICAgICAgfSxcbiAgICB9KSk7XG4gIH1cblxuICBpZiAoZW5hYmxlQ29ycykge1xuICAgIGFwcC51c2UoY29ycyhDb25maWcuZ2V0KCdzZXJ2ZXInKS5jb3JzKSk7XG4gIH1cblxuICAvLyBSZXNwb25zZSBjb21wcmVzc2lvbiAoZ3ppcC9kZWZsYXRlKSDigJQgc2tpcCBTU0Ugc3RyZWFtc1xuICBpZiAoZW5hYmxlQ29tcHJlc3Npb24pIHtcbiAgICBhcHAudXNlKGNvbXByZXNzaW9uKHtcbiAgICAgIGZpbHRlcjogKHJlcTogUmVxdWVzdCwgcmVzOiBSZXNwb25zZSkgPT4ge1xuICAgICAgICAvLyBEb24ndCBjb21wcmVzcyBTU0Ugc3RyZWFtcy4gTWF0Y2ggYnkgaW5jbHVzaW9uOiB0aGUgQWNjZXB0IGhlYWRlciBpc1xuICAgICAgICAvLyBvZnRlbiBhIGxpc3QgKGUuZy4gXCJ0ZXh0L2V2ZW50LXN0cmVhbSwgKi8qXCIpLCB3aGljaCBleGFjdCBlcXVhbGl0eVxuICAgICAgICAvLyB3b3VsZCBtaXNzLCBjb21wcmVzc2luZy9idWZmZXJpbmcgdGhlIHN0cmVhbS5cbiAgICAgICAgaWYgKChyZXEuaGVhZGVycy5hY2NlcHQgfHwgJycpLmluY2x1ZGVzKCd0ZXh0L2V2ZW50LXN0cmVhbScpKSByZXR1cm4gZmFsc2U7XG4gICAgICAgIHJldHVybiBjb21wcmVzc2lvbi5maWx0ZXIocmVxLCByZXMpO1xuICAgICAgfSxcbiAgICAgIHRocmVzaG9sZDogQ29yZUNvbnN0YW50cy5DT01QUkVTU0lPTl9USFJFU0hPTERfQllURVMsXG4gICAgfSkpO1xuICB9XG5cbiAgLy8gRVRhZyBzdXBwb3J0IGZvciBjb25kaXRpb25hbCBHRVQgcmVxdWVzdHMgKDMwNCBOb3QgTW9kaWZpZWQpXG4gIGFwcC51c2UoZXRhZ01pZGRsZXdhcmUoKSk7XG59XG5cbi8qKiBKU09OICsgVVJMLWVuY29kZWQgYm9keSBwYXJzZXJzLiAqL1xuZnVuY3Rpb24gYXBwbHlCb2R5UGFyc2luZyhhcHA6IEV4cHJlc3MsIG9wdGlvbnM6IENyZWF0ZUFwcE9wdGlvbnMpOiB2b2lkIHtcbiAgY29uc3QgeyBlbmFibGVKc29uQm9keSA9IHRydWUsIGpzb25MaW1pdCA9ICcxbWInLCBlbmFibGVVcmxFbmNvZGVkID0gdHJ1ZSwgdXJsRW5jb2RlZExpbWl0ID0gJzFtYicgfSA9IG9wdGlvbnM7XG4gIGlmIChlbmFibGVKc29uQm9keSkge1xuICAgIGNvbnN0IGpzb25QYXJzZXIgPSBleHByZXNzLmpzb24oeyBsaW1pdDoganNvbkxpbWl0IH0pO1xuICAgIGNvbnN0IGV4Y2x1ZGUgPSBvcHRpb25zLmpzb25Cb2R5RXhjbHVkZSA/PyBbXTtcbiAgICBpZiAoZXhjbHVkZS5sZW5ndGggPiAwKSB7XG4gICAgICAvLyBTa2lwIHRoZSBnbG9iYWwgSlNPTiBwYXJzZXIgZm9yIHJhdy1ib2R5IHBhdGhzIHNvIGEgcGVyLXBhdGggYGV4cHJlc3MucmF3KClgXG4gICAgICAvLyBjYW4gcmVhZCB0aGUgZXhhY3QgYnl0ZXMgKHNlZSBganNvbkJvZHlFeGNsdWRlYCkuXG4gICAgICBhcHAudXNlKChyZXEsIHJlcywgbmV4dCkgPT4gKGV4Y2x1ZGUuc29tZSgocCkgPT4gcmVxLnBhdGguc3RhcnRzV2l0aChwKSkgPyBuZXh0KCkgOiBqc29uUGFyc2VyKHJlcSwgcmVzLCBuZXh0KSkpO1xuICAgIH0gZWxzZSB7XG4gICAgICBhcHAudXNlKGpzb25QYXJzZXIpO1xuICAgIH1cbiAgfVxuXG4gIGlmIChlbmFibGVVcmxFbmNvZGVkKSB7XG4gICAgYXBwLnVzZShleHByZXNzLnVybGVuY29kZWQoeyBleHRlbmRlZDogdHJ1ZSwgbGltaXQ6IHVybEVuY29kZWRMaW1pdCB9KSk7XG4gIH1cbn1cblxuLyoqXG4gKiBIZWFsdGgsIHJlYWRpbmVzcyBndWFyZCwgYC93YXJtdXBgLCBgL21ldHJpY3NgIGFuZCB0aGUgT3BlbkFQSSBkb2NzIOKAlCBhbGxcbiAqIHJlZ2lzdGVyZWQgYmVmb3JlIHRoZSByYXRlIGxpbWl0ZXIgc28gdGhleSBhcmUgbmV2ZXIgdGhyb3R0bGVkLlxuICovXG5mdW5jdGlvbiBtb3VudEluZnJhRW5kcG9pbnRzKGFwcDogRXhwcmVzcywgb3B0aW9uczogQ3JlYXRlQXBwT3B0aW9ucywgc2VydmljZU5hbWU6IHN0cmluZywgZW5hYmxlT3BlbkFwaTogYm9vbGVhbik6IHZvaWQge1xuICBjb25zdCB7IGNoZWNrRGVwZW5kZW5jaWVzLCBvcGVuQXBpT3B0aW9ucywgd2FybXVwSG9va3MgPSBbXSB9ID0gb3B0aW9ucztcblxuICBhcHAudXNlKGNyZWF0ZUhlYWx0aFJvdXRlcih7XG4gICAgc2VydmljZU5hbWUsXG4gICAgY2hlY2tEZXBlbmRlbmNpZXMsXG4gIH0pKTtcblxuICAvLyBSZWFkaW5lc3MgZ3VhcmQg4oCUIDUwM3MgYnVzaW5lc3MgdHJhZmZpYyB3aGlsZSB0aGUgc2VydmljZSBpcyBOb3RSZWFkeVxuICAvLyAoZGF0YXN0b3JlIHN0aWxsIGNvbm5lY3RpbmcgYXQgc3RhcnR1cCwgb3IgZHJvcHBlZCkuIE1vdW50ZWQgcmlnaHQgYWZ0ZXJcbiAgLy8gdGhlIGhlYWx0aCByb3V0ZXIgYW5kIGJlZm9yZSBldmVyeXRoaW5nIGVsc2Ugc28gYSBOb3RSZWFkeSByZXF1ZXN0IGlzXG4gIC8vIHJlamVjdGVkIGNoZWFwbHksIGJlZm9yZSByYXRlLWxpbWl0IC8gaWRlbXBvdGVuY3kgLyBidXNpbmVzcyBoYW5kbGVycyBldmVyXG4gIC8vIHRvdWNoIGEgZGlzY29ubmVjdGVkIGRhdGFzdG9yZS4gSXQgYWxsb3dsaXN0cyB0aGUgaW5mcmEgZW5kcG9pbnRzXG4gIC8vICgvbWV0cmljcywgL3dhcm11cCwgL2RvY3MsIC9sb2dzKSByZWdpc3RlcmVkIGJlbG93LCBwbHVzIC9oZWFsdGggKyAvcmVhZHkuXG4gIGFwcC51c2UocmVhZGluZXNzR3VhcmQoKSk7XG5cbiAgLy8gV2FybS11cCBlbmRwb2ludCDigJQgcHJlLW9wZW5zIGNvbm5lY3Rpb24gcG9vbHMgc28gdGhlIGZpcnN0IHJlYWwgcmVxdWVzdFxuICAvLyBkb2Vzbid0IHBheSBjb2xkLXN0YXJ0IGxhdGVuY3kuIEFsd2F5cyBwaW5ncyBQb3N0Z3Jlczsgc2VydmljZXMgdXNpbmdcbiAgLy8gTW9uZ28gLyBSZWRpcyAvIFNRUyBwYXNzIGB3YXJtdXBIb29rc2Agc28gdGhvc2UgYXJlIHdhcm1lZCBpbiBwYXJhbGxlbC5cbiAgLy9cbiAgLy8gR0FURUQgdG8gdmVyaWZpZWQgc2VydmljZSBwcmluY2lwYWxzLiBFdmVyeSBoaXQgcnVucyBhIFBvc3RncmVzIHJvdW5kLXRyaXBcbiAgLy8gcGx1cyBhbGwgYHdhcm11cEhvb2tzYCAoTW9uZ28vUmVkaXMvU1FTKSwgc28gYW4gb3BlbiBlbmRwb2ludCB3b3VsZCBsZXQgYW5cbiAgLy8gYW5vbnltb3VzIGxvb3AgYW1wbGlmeSBpbnRvIGRhdGFzdG9yZSBsb2FkIG9uIGV2ZXJ5IHNlcnZpY2UgaW4gdGhlIGZsZWV0IOKAlFxuICAvLyBhbmQgaXQgaXMgcmVnaXN0ZXJlZCBhYm92ZSB0aGUgcmF0ZSBsaW1pdGVyLCBzbyBub3RoaW5nIHdvdWxkIHRocm90dGxlIGl0LlxuICAvLyBgdmVyaWZ5U2VydmljZVByaW5jaXBhbGAgY2hlY2tzIHRoZSBiZWFyZXIgdG9rZW4gY3J5cHRvZ3JhcGhpY2FsbHksIHNvIGl0IGlzXG4gIC8vIHNhZmUgaGVyZSwgYWJvdmUgYHJlcXVpcmVBdXRoYC5cbiAgYXBwLmdldCgnL3dhcm11cCcsIGFzeW5jIChyZXE6IFJlcXVlc3QsIHJlczogUmVzcG9uc2UpID0+IHtcbiAgICBpZiAoIXZlcmlmeVNlcnZpY2VQcmluY2lwYWwocmVxKSkge1xuICAgICAgc2VuZEVycm9yKHJlcywgNDA0LCAnTm90IGZvdW5kJyk7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHRyeSB7XG4gICAgICBhd2FpdCBQcm9taXNlLmFsbChbXG4gICAgICAgIGdldENvbm5lY3Rpb24oKS50ZXN0Q29ubmVjdGlvbigpLFxuICAgICAgICAuLi53YXJtdXBIb29rcy5tYXAoKGhvb2spID0+IGhvb2soKSksXG4gICAgICBdKTtcbiAgICAgIHNlbmRTdWNjZXNzKHJlcywgMjAwLCB7IHdhcm1lZDogdHJ1ZSwgaG9va3M6IHdhcm11cEhvb2tzLmxlbmd0aCB9KTtcbiAgICB9IGNhdGNoIHtcbiAgICAgIHNlbmRFcnJvcihyZXMsIDUwMywgJ1dhcm11cCBmYWlsZWQnKTtcbiAgICB9XG4gIH0pO1xuXG4gIC8vIFByb21ldGhldXMgbWV0cmljcyBlbmRwb2ludCDigJQgYWx3YXlzIHJlZ2lzdGVyZWQgKG5ldmVyIHRocm90dGxlZCkuXG4gIC8vXG4gIC8vIE9wdGlvbmFsbHkgZ2F0ZWQ6IHdoZW4gYE1FVFJJQ1NfU0NSQVBFX1RPS0VOYCBpcyBzZXQsIHRoZSBzY3JhcGVyIG11c3Qgc2VuZFxuICAvLyBpdCBhcyBhIGJlYXJlciB0b2tlbiAoUHJvbWV0aGV1cyBgYmVhcmVyX3Rva2VuYCAvIGBiZWFyZXJfdG9rZW5fZmlsZWAgaW4gdGhlXG4gIC8vIHNjcmFwZSBjb25maWcpLiBMZWZ0IHVuZ2F0ZWQgd2hlbiB1bnNldCBzbyBlbmFibGluZyBpdCBpcyBhIGRlbGliZXJhdGUsXG4gIC8vIGNvb3JkaW5hdGVkIGNoYW5nZSByYXRoZXIgdGhhbiBhIHNpbGVudCBtb25pdG9yaW5nIG91dGFnZSDigJQgdGVuYW50IGlkcyBzdGF5XG4gIC8vIG91dCBvZiB0aGUgb3V0cHV0IHJlZ2FyZGxlc3MsIGJlY2F1c2UgdGhlIHBlci1vcmcgbGFiZWwgZGVmYXVsdHMgT0ZGIChzZWVcbiAgLy8gSFRUUF9NRVRSSUNTX09SR19TQU1QTEVfUkFURSBpbiBtZXRyaWNzLnRzKS5cbiAgY29uc3QgbWV0cmljc1Rva2VuID0gcHJvY2Vzcy5lbnYuTUVUUklDU19TQ1JBUEVfVE9LRU47XG4gIGFwcC5nZXQoJy9tZXRyaWNzJywgKHJlcTogUmVxdWVzdCwgcmVzOiBSZXNwb25zZSwgbmV4dDogTmV4dEZ1bmN0aW9uKSA9PiB7XG4gICAgaWYgKCFtZXRyaWNzVG9rZW4pIHtcbiAgICAgIG5leHQoKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgY29uc3QgaGVhZGVyID0gcmVxLmhlYWRlcnMuYXV0aG9yaXphdGlvbjtcbiAgICBjb25zdCBwcmVzZW50ZWQgPSBoZWFkZXI/LnN0YXJ0c1dpdGgoJ0JlYXJlciAnKSA/IGhlYWRlci5zbGljZSg3KSA6IHVuZGVmaW5lZDtcbiAgICAvLyBDb25zdGFudC10aW1lIGNvbXBhcmUg4oCUIGEgbGVuZ3RoLWluZGVwZW5kZW50IGVxdWFsaXR5IGNoZWNrIGhlcmUgd291bGRcbiAgICAvLyBsZWFrIHRoZSB0b2tlbiBhIGJ5dGUgYXQgYSB0aW1lLlxuICAgIGlmICghcHJlc2VudGVkIHx8ICFzYWZlRXF1YWwocHJlc2VudGVkLCBtZXRyaWNzVG9rZW4pKSB7XG4gICAgICBzZW5kRXJyb3IocmVzLCA0MDQsICdOb3QgZm91bmQnKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgbmV4dCgpO1xuICB9LCBtZXRyaWNzSGFuZGxlcigpKTtcblxuICBpZiAoZW5hYmxlT3BlbkFwaSkge1xuICAgIGNvbnN0IHNwZWMgPSBnZW5lcmF0ZU9wZW5BcGlTcGVjKG9wZW5BcGlPcHRpb25zKTtcbiAgICBhcHAuZ2V0KCcvZG9jcy9vcGVuYXBpLmpzb24nLCAoX3JlcTogUmVxdWVzdCwgcmVzOiBSZXNwb25zZSkgPT4ge1xuICAgICAgcmVzLmpzb24oc3BlYyk7XG4gICAgfSk7XG4gICAgYXBwLnVzZSgnL2RvY3MnLCBzd2FnZ2VyVWkuc2VydmUsIHN3YWdnZXJVaS5zZXR1cChzcGVjLCB7XG4gICAgICBjdXN0b21TaXRlVGl0bGU6IG9wZW5BcGlPcHRpb25zPy50aXRsZSA/PyAnUGlwZWxpbmUgQnVpbGRlciBBUEkgRG9jcycsXG4gICAgfSkpO1xuICB9XG59XG5cbi8qKiBHbG9iYWwgcmF0ZSBsaW1pdGVyIOKAlCBzaGFyZWQgYWNyb3NzIHJlcGxpY2FzIHZpYSB0aGUgZW52IFJlZGlzIHdoZW4gY29uZmlndXJlZC4gKi9cbmZ1bmN0aW9uIG1vdW50UmF0ZUxpbWl0ZXIoYXBwOiBFeHByZXNzLCBzZXJ2aWNlTmFtZTogc3RyaW5nKTogdm9pZCB7XG4gIGNvbnN0IHJhdGVMaW1pdENvbmZpZyA9IENvbmZpZy5nZXQoJ3JhdGVMaW1pdCcpO1xuXG4gIGNvbnN0IHJhdGVMaW1pdE9wdGlvbnM6IFBhcmFtZXRlcnM8dHlwZW9mIHJhdGVMaW1pdD5bMF0gPSB7XG4gICAgbWF4OiByYXRlTGltaXRDb25maWcubWF4LFxuICAgIHdpbmRvd01zOiByYXRlTGltaXRDb25maWcud2luZG93TXMsXG4gICAgc3RhbmRhcmRIZWFkZXJzOiB0cnVlLFxuICAgIGxlZ2FjeUhlYWRlcnM6IGZhbHNlLFxuICAgIC8vIFNraXAgcmF0ZSBsaW1pdGluZyBvbmx5IGZvciBDUllQVE9HUkFQSElDQUxMWS1WRVJJRklFRCBpbnRlcm5hbCBzZXJ2aWNlXG4gICAgLy8gY2FsbGVycy4gVGhlIGxpbWl0ZXIgcnVucyBiZWZvcmUgcmVxdWlyZUF1dGgsIHNvIGEgcGxhaW50ZXh0IGhlYWRlclxuICAgIC8vIHdvdWxkIGJlIHNwb29mYWJsZSBieSBhbnkgZXh0ZXJuYWwgY2xpZW50IOKGkiB0b3RhbCBieXBhc3MuXG4gICAgLy8gdmVyaWZ5U2VydmljZVByaW5jaXBhbCB2ZXJpZmllcyB0aGUgc2lnbmVkIHNlcnZpY2UgSldUIGluc3RlYWQ7XG4gICAgLy8gaW50ZXItc2VydmljZSBjYWxsZXJzIGFsbCBzZW5kIG9uZSAoZ2V0U2VydmljZUF1dGhIZWFkZXIpLlxuICAgIHNraXA6IChyZXE6IFJlcXVlc3QpID0+IHZlcmlmeVNlcnZpY2VQcmluY2lwYWwocmVxKSxcbiAgICAvLyBLZXkgb24gY2xpZW50IElQIG9ubHkuIFRoZSBsaW1pdGVyIHJ1bnMgcHJlLWF1dGgsIHNvIGByZXEudXNlcmAgaXMgdW5zZXRcbiAgICAvLyBhbmQgYW55IG9yZyBpZCB3b3VsZCBjb21lIGZyb20gdGhlIGNhbGxlci1zdXBwbGllZCBgeC1vcmctaWRgIGhlYWRlciDigJRcbiAgICAvLyBzcG9vZmFibGUsIGxldHRpbmcgYW4gYXR0YWNrZXIgcm90YXRlIHZhbHVlcyB0byBldmFkZSB0aGUgYnVja2V0IG9yXG4gICAgLy8gZmxvb2QgYSB2aWN0aW0gb3JnJ3MgYnVja2V0LiBpcEtleUdlbmVyYXRvciBub3JtYWxpemVzIElQdjYgdG8gYSAvNjRcbiAgICAvLyBwcmVmaXggKGFsc28gcmVxdWlyZWQgYnkgZXhwcmVzcy1yYXRlLWxpbWl0IDgueCdzIHZhbGlkYXRvcikuXG4gICAga2V5R2VuZXJhdG9yOiAocmVxOiBSZXF1ZXN0KSA9PiBpcEtleUdlbmVyYXRvcihyZXEuaXAgfHwgJ2Fub24nLCA2NCksXG4gICAgLy8gQSBzdG9yZSBmYWlsdXJlIChSZWRpcyBkb3duIC8gZmFpbGluZyBvdmVyKSBtdXN0IGRlZ3JhZGUgdG8gXCJub3QgcmF0ZVxuICAgIC8vIGxpbWl0ZWRcIiwgbmV2ZXIgdG8gYSA1MDAgb24gZXZlcnkgcmVxdWVzdCBvZiBldmVyeSBzZXJ2aWNlLlxuICAgIHBhc3NPblN0b3JlRXJyb3I6IHRydWUsXG4gICAgaGFuZGxlcjogKF9yZXE6IFJlcXVlc3QsIHJlczogUmVzcG9uc2UpID0+IHtcbiAgICAgIHNlbmRFcnJvcihyZXMsIDQyOSwgJ1RvbyBtYW55IHJlcXVlc3RzLCBwbGVhc2UgdHJ5IGFnYWluIGxhdGVyLicsIEVycm9yQ29kZS5SQVRFX0xJTUlUX0VYQ0VFREVEKTtcbiAgICB9LFxuICAgIC8vIFNoYXJlZCBzdGF0ZSBhY3Jvc3MgcmVwbGljYXMgKHRoZSBwcm9jZXNzLXdpZGUgcmF0ZS1saW1pdCBSZWRpcyBjb25uZWN0aW9uO1xuICAgIC8vIHVuZGVmaW5lZCB3aXRob3V0IFJlZGlzIOKGkiBwZXItcHJvY2VzcyBtZW1vcnkgc3RvcmUsIHJpZ2h0IGZvciBvbmUgcmVwbGljYSkuXG4gICAgLy8gTmFtZXNwYWNlZCBwZXIgU0VSVklDRTogZXZlcnkgc2VydmljZSBzaGFyZXMgb25lIFJlZGlzLCBhbmQgYW4gdW5wcmVmaXhlZFxuICAgIC8vIGBybDo8aXA+YCBrZXkgd291bGQgbGV0IG9uZSBjbGllbnQncyB0cmFmZmljIHRvIEFOWSBzZXJ2aWNlIGRyYWluIGl0c1xuICAgIC8vIGJ1ZGdldCBvbiBFVkVSWSBzZXJ2aWNlLlxuICAgIHN0b3JlOiBjcmVhdGVTaGFyZWRSYXRlTGltaXRTdG9yZShgJHtzZXJ2aWNlTmFtZX06Z2xvYmFsYCksXG4gIH07XG5cbiAgYXBwLnVzZShyYXRlTGltaXQocmF0ZUxpbWl0T3B0aW9ucykpO1xufVxuXG4vKiogUmVxdWVzdCB0aW1lb3V0LCBkdXJhdGlvbiBsb2dnaW5nIGFuZCBIVFRQIG1ldHJpY3MuICovXG5mdW5jdGlvbiBhcHBseVJlcXVlc3RUZWxlbWV0cnkoYXBwOiBFeHByZXNzKTogdm9pZCB7XG4gIC8vIEV4cHJlc3MgcmVxdWVzdCB0aW1lb3V0IOKAlCB1c2VzIENvcmVDb25zdGFudHMgdG8gc2hhcmUgdGhlIHNhbWUgZGVmYXVsdCBhcyBMYW1iZGEgaGFuZGxlcnNcbiAgY29uc3QgdGltZW91dE1zID0gQ29yZUNvbnN0YW50cy5IQU5ETEVSX1RJTUVPVVRfTVM7XG4gIGFwcC51c2UoKF9yZXE6IFJlcXVlc3QsIHJlczogUmVzcG9uc2UsIG5leHQ6IE5leHRGdW5jdGlvbikgPT4ge1xuICAgIHJlcy5zZXRUaW1lb3V0KHRpbWVvdXRNcywgKCkgPT4ge1xuICAgICAgaWYgKCFyZXMuaGVhZGVyc1NlbnQpIHtcbiAgICAgICAgc2VuZEVycm9yKHJlcywgNTAzLCAnUmVxdWVzdCB0aW1lb3V0Jyk7XG4gICAgICB9XG4gICAgfSk7XG4gICAgbmV4dCgpO1xuICB9KTtcblxuICAvLyBSZXF1ZXN0IGR1cmF0aW9uIGxvZ2dpbmdcbiAgY29uc3QgZHVyYXRpb25Mb2dnZXIgPSBjcmVhdGVMb2dnZXIoJ3JlcXVlc3QtZHVyYXRpb24nKTtcbiAgYXBwLnVzZSgocmVxOiBSZXF1ZXN0LCByZXM6IFJlc3BvbnNlLCBuZXh0OiBOZXh0RnVuY3Rpb24pID0+IHtcbiAgICBjb25zdCBzdGFydCA9IERhdGUubm93KCk7XG4gICAgcmVzLm9uKCdmaW5pc2gnLCAoKSA9PiB7XG4gICAgICBjb25zdCBkdXJhdGlvbiA9IERhdGUubm93KCkgLSBzdGFydDtcbiAgICAgIC8vIExvZyBgcmVxLnBhdGhgIChubyBxdWVyeSBzdHJpbmcpIOKAlCBhIHN0cmF5IGA/dG9rZW49YC9gP3RpY2tldD1gIG11c3Qgbm90IGJlXG4gICAgICAvLyBwZXJzaXN0ZWQgdmVyYmF0aW0gb24gZXZlcnkgcmVxdWVzdCAobWlycm9ycyB0aGUgYXV0aHotZGVuaWFsIGF1ZGl0b3IncyBzdHJpcCkuXG4gICAgICBkdXJhdGlvbkxvZ2dlci5pbmZvKGAke3JlcS5tZXRob2R9ICR7cmVxLnBhdGh9ICR7cmVzLnN0YXR1c0NvZGV9ICR7ZHVyYXRpb259bXNgLCB7XG4gICAgICAgIG1ldGhvZDogcmVxLm1ldGhvZCxcbiAgICAgICAgcGF0aDogcmVxLnBhdGgsXG4gICAgICAgIHN0YXR1c0NvZGU6IHJlcy5zdGF0dXNDb2RlLFxuICAgICAgICBkdXJhdGlvbk1zOiBkdXJhdGlvbixcbiAgICAgICAgcmVxdWVzdElkOiByZXEucmVxdWVzdElkLFxuICAgICAgfSk7XG4gICAgfSk7XG4gICAgbmV4dCgpO1xuICB9KTtcblxuICAvLyBQcm9tZXRoZXVzIG1ldHJpY3MgbWlkZGxld2FyZSDigJQgcmVjb3JkcyByZXF1ZXN0IGR1cmF0aW9uIGFuZCBjb3VudFxuICBhcHAudXNlKG1ldHJpY3NNaWRkbGV3YXJlKCkpO1xufVxuXG4vKipcbiAqIFRoZSBkZWZhdWx0IFNTRSBtYW5hZ2VyLiBUaGUgcmVsYXkgKHRoaXMgc2VydmljZSdzIG93biBSZWRpcyBjaGFubmVsKSBpc1xuICogYnVpbHQgb25seSB3aGVuIHNvbWV0aGluZyBzdHJlYW1zOiB0aGUgbG9nIHN0cmVhbSB0dXJucyBpdCBvbiBoZXJlLCBhbmQgYW5cbiAqIG9yZy1rZXllZCBjaGFubmVsIHR1cm5zIGl0IG9uIHdoZW4gcmVnaXN0ZXJlZCAocmVnaXN0ZXJTc2VUaWNrZXRDaGFubmVsKS5cbiAqIFRoZSBsb2cgdGlja2V0IHN0b3JlIGV4aXN0cyBvbmx5IHdpdGggdGhlIGxvZyBzdHJlYW0uXG4gKi9cbmZ1bmN0aW9uIGNyZWF0ZURlZmF1bHRTc2VNYW5hZ2VyKHNlcnZpY2VOYW1lOiBzdHJpbmcsIGxvZ1N0cmVhbTogYm9vbGVhbik6IFNTRU1hbmFnZXIge1xuICBjb25zdCBzc2VNYW5hZ2VyID0gbmV3IFNTRU1hbmFnZXIoe1xuICAgIGxvZ1N0cmVhbSxcbiAgICByZWxheUZhY3Rvcnk6ICgpID0+IGNyZWF0ZUVudlJlZGlzU1NFUmVsYXkoc2VydmljZU5hbWUpLFxuICAgIC4uLihsb2dTdHJlYW0gJiYge1xuICAgICAgdGlja2V0U3RvcmU6IGNyZWF0ZUVudlNzZVRpY2tldFN0b3JlKHtcbiAgICAgICAgdHRsTXM6IFNTRV9USUNLRVRfVFRMX01TLFxuICAgICAgICBrZXlQcmVmaXg6IGBsb2dzOiR7c2VydmljZU5hbWV9YCxcbiAgICAgIH0pLFxuICAgIH0pLFxuICB9KTtcbiAgaWYgKGxvZ1N0cmVhbSkgc3NlTWFuYWdlci5lbmFibGVSZWxheSgpO1xuICByZXR1cm4gc3NlTWFuYWdlcjtcbn1cblxuLyoqXG4gKiBUaGUgcGVyLXJlcXVlc3QgYnVpbGQtbG9nIHN0cmVhbTogYFBPU1QgL2xvZ3MvdGlja2V0YCArIGBHRVQgL2xvZ3MvOnJlcXVlc3RJZGAuXG4gKlxuICogVGlja2V0LWdhdGVkIOKAlCB0aGUgc3RyZWFtIGNhcnJpZXMgcGVyLW9yZyBidWlsZCBsb2dzLCBzbyBpdCBtdXN0IG5vdCBiZVxuICogd29ybGQtcmVhZGFibGUuIENsaWVudHMgZmlyc3QgUE9TVCAvbG9ncy90aWNrZXQgKEpXVC1hdXRoZW50aWNhdGVkKSB0byBtaW50IGFcbiAqIHNob3J0LWxpdmVkLCBzaW5nbGUtdXNlIHRpY2tldCBib3VuZCB0byB0aGVpciBvcmcgQU5EIHRvIHRoZSBzcGVjaWZpY1xuICogYHJlcXVlc3RJZGAgc3RyZWFtIHRoZXkgaW50ZW5kIHRvIG9wZW4sIHRoZW4gb3BlbiB0aGUgRXZlbnRTb3VyY2Ugd2l0aFxuICogP3RpY2tldD08dD4uIFRoaXMga2VlcHMgdGhlIEpXVCBvdXQgb2YgcXVlcnkgc3RyaW5ncyAvIGFjY2VzcyBsb2dzIHdoaWxlXG4gKiBlbmZvcmNpbmcgb3JnIG93bmVyc2hpcCwgcGVyLXN1YmplY3QgYXV0aG9yaXphdGlvbiwgYW5kIHRoZSBwZXItb3JnXG4gKiBjb25uZWN0aW9uIGNhcCBvbiB0aGUgc3RyZWFtLiBNaXJyb3JzIHRoZSBtZXNzYWdlLXNlcnZpY2Ugbm90aWZpY2F0aW9ucyBTU0VcbiAqIHRpY2tldCBleGNoYW5nZS5cbiAqL1xuZnVuY3Rpb24gd2lyZVNzZShhcHA6IEV4cHJlc3MsIHNzZU1hbmFnZXI6IFNTRU1hbmFnZXIpOiB2b2lkIHtcbiAgYXBwLnBvc3QoJy9sb2dzL3RpY2tldCcsIHJlcXVpcmVBdXRoLCBhc3luYyAocmVxOiBSZXF1ZXN0LCByZXM6IFJlc3BvbnNlKSA9PiB7XG4gICAgY29uc3Qgb3JnSWQgPSByZXEudXNlcj8ub3JnYW5pemF0aW9uSWQ/LnRvTG93ZXJDYXNlKCk7XG4gICAgaWYgKCFvcmdJZCkge1xuICAgICAgc2VuZEVycm9yKHJlcywgNDAwLCAnVG9rZW4gbWlzc2luZyBvcmdhbml6YXRpb24nLCBFcnJvckNvZGUuVkFMSURBVElPTl9FUlJPUik7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIC8vIFRoZSBjYWxsZXIgbXVzdCBuYW1lIHRoZSBzdHJlYW0gc3ViamVjdCB1cCBmcm9udCBzbyB0aGUgdGlja2V0IGlzIGJvdW5kIHRvXG4gICAgLy8gaXQuIFdpdGhvdXQgdGhpcywgYSB0aWNrZXQgY291bGQgYmUgcmVwbGF5ZWQgYWdhaW5zdCBBTlkgcmVxdWVzdElkIHRoZVxuICAgIC8vIG9yZyBjb3VsZCBndWVzcywgbGV0dGluZyBpdCBhdHRhY2ggdG8gYW5vdGhlciBvcmcncyBsb2cgc3RyZWFtLiBTdHJpY3RseVxuICAgIC8vIGZvcm1hdC12YWxpZGF0ZWQgc28gaXQgY2FuJ3QgY2FycnkgYW4gaW5qZWN0aW9uIHBheWxvYWQgaW50byB0aGUgc3ViamVjdC5cbiAgICBjb25zdCByZXF1ZXN0SWQgPSAocmVxLmJvZHkgYXMgeyByZXF1ZXN0SWQ/OiB1bmtub3duIH0gfCB1bmRlZmluZWQpPy5yZXF1ZXN0SWQ7XG4gICAgaWYgKHR5cGVvZiByZXF1ZXN0SWQgIT09ICdzdHJpbmcnIHx8ICFTU0VfUkVRVUVTVF9JRF9SRS50ZXN0KHJlcXVlc3RJZCkpIHtcbiAgICAgIHNlbmRFcnJvcihyZXMsIDQwMCwgJ01pc3Npbmcgb3IgaW52YWxpZCByZXF1ZXN0SWQnLCBFcnJvckNvZGUuVkFMSURBVElPTl9FUlJPUik7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHNzZU1hbmFnZXIuY3JlYXRlVGlja2V0KG9yZ0lkLCByZXF1ZXN0SWQpO1xuICAgIGlmICghcmVzdWx0Lm9rKSB7XG4gICAgICBpZiAocmVzdWx0LnJlYXNvbiA9PT0gJ2ZvcmJpZGRlbicpIHtcbiAgICAgICAgLy8gVGhlIHN1YmplY3QgaXMgb3duZWQgYnkgYW5vdGhlciBvcmcg4oCUIGRvIG5vdCBjb25maXJtIGl0IGV4aXN0czsgYSBwbGFpblxuICAgICAgICAvLyA0MDMgaXMgZW5vdWdoIGFuZCBsZWFrcyBub3RoaW5nIGFib3V0IHdoaWNoIHJlcXVlc3RJZHMgYXJlIGxpdmUuXG4gICAgICAgIHNlbmRFcnJvcihyZXMsIDQwMywgJ05vdCBhdXRob3JpemVkIGZvciB0aGlzIGxvZyBzdHJlYW0nLCBFcnJvckNvZGUuSU5TVUZGSUNJRU5UX1BFUk1JU1NJT05TKTtcbiAgICAgIH0gZWxzZSBpZiAocmVzdWx0LnJlYXNvbiA9PT0gJ29yZy1saW1pdCcpIHtcbiAgICAgICAgc2VuZEVycm9yKHJlcywgNDI5LCAnVG9vIG1hbnkgbG9nIHN0cmVhbSB0aWNrZXRzIGlzc3VlZCcsIEVycm9yQ29kZS5RVU9UQV9FWENFRURFRCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBzZW5kRXJyb3IocmVzLCA1MDMsICdMb2cgc3RyZWFtaW5nIHN1YnN5c3RlbSBhdCBjYXBhY2l0eScsIEVycm9yQ29kZS5RVU9UQV9FWENFRURFRCk7XG4gICAgICB9XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHNlbmRTdWNjZXNzKHJlcywgMjAwLCB7IHRpY2tldDogcmVzdWx0LnRpY2tldCB9KTtcbiAgfSk7XG5cbiAgLy8gVGhlIHN0cmVhbSBpdHNlbGYgcmVzb2x2ZXMgKyBjb25zdW1lcyB0aGUgdGlja2V0IGluc2lkZSBtaWRkbGV3YXJlKCkgYW5kXG4gIC8vIHJlamVjdHMgYW55IGFub255bW91cyAvIGludmFsaWQgLyBleHBpcmVkIC8gYWxyZWFkeS11c2VkIHRpY2tldCB3aXRoIDQwMS5cbiAgYXBwLmdldCgnL2xvZ3MvOnJlcXVlc3RJZCcsIHNzZU1hbmFnZXIubWlkZGxld2FyZSgpKTtcbn1cblxuLyoqXG4gKiBDcmVhdGUgYW5kIGNvbmZpZ3VyZSBhbiBFeHByZXNzIGFwcGxpY2F0aW9uIHdpdGggY29tbW9uIG1pZGRsZXdhcmVcbiAqXG4gKiBTZXRzIHVwOlxuICogLSBDT1JTIHdpdGggY29uZmlndXJlZCBvcmlnaW5zXG4gKiAtIEhlbG1ldCBzZWN1cml0eSBoZWFkZXJzXG4gKiAtIFJhdGUgbGltaXRpbmdcbiAqIC0gSlNPTiBhbmQgVVJMLWVuY29kZWQgYm9keSBwYXJzaW5nXG4gKiAtIFRydXN0IHByb3h5IHNldHRpbmdzXG4gKiAtIEhlYWx0aCBjaGVjayBlbmRwb2ludCAoL2hlYWx0aClcbiAqIC0gTWV0cmljcyBlbmRwb2ludCAoL21ldHJpY3MpXG4gKiAtIFNTRSBsb2dzIGVuZHBvaW50ICgvbG9ncy86cmVxdWVzdElkKSDigJQgb25seSB3aXRoIGBsb2dTdHJlYW06IHRydWVgXG4gKlxuICogQHBhcmFtIG9wdGlvbnMgLSBDb25maWd1cmF0aW9uIG9wdGlvbnNcbiAqIEByZXR1cm5zIENvbmZpZ3VyZWQgRXhwcmVzcyBhcHAgYW5kIFNTRSBtYW5hZ2VyXG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIGNvbnN0IHsgYXBwLCBzc2VNYW5hZ2VyIH0gPSBjcmVhdGVBcHAoKTtcbiAqXG4gKiBhcHAucG9zdCgnL2FwaS9yZXNvdXJjZScsIHJlcXVpcmVBdXRoLCBhc3luYyAocmVxLCByZXMpID0+IHtcbiAqICAgLy8gWW91ciByb3V0ZSBoYW5kbGVyXG4gKiB9KTtcbiAqXG4gKiBzdGFydFNlcnZlcihhcHAsIHsgbmFtZTogJ015IFNlcnZpY2UnIH0pO1xuICogYGBgXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVBcHAob3B0aW9uczogQ3JlYXRlQXBwT3B0aW9ucyA9IHt9KTogQ3JlYXRlQXBwUmVzdWx0IHtcbiAgY29uc3Qge1xuICAgIGVuYWJsZVJhdGVMaW1pdCA9IHRydWUsXG4gICAgbG9nU3RyZWFtID0gZmFsc2UsXG4gICAgZW5hYmxlT3BlbkFwaSA9IHByb2Nlc3MuZW52Lk5PREVfRU5WICE9PSAncHJvZHVjdGlvbicsXG4gIH0gPSBvcHRpb25zO1xuXG4gIGNvbnN0IHNlcnZpY2VOYW1lID0gcHJvY2Vzcy5lbnYuU0VSVklDRV9OQU1FIHx8ICdhcGknO1xuXG4gIC8vIEEgY2FsbGVyLXN1cHBsaWVkIGBzc2VNYW5hZ2VyYCBza2lwcyB0aGUgZGVmYXVsdCBjb25zdHJ1Y3Rpb24gZW50aXJlbHkuXG4gIGNvbnN0IHNzZU1hbmFnZXIgPSBvcHRpb25zLnNzZU1hbmFnZXIgPz8gY3JlYXRlRGVmYXVsdFNzZU1hbmFnZXIoc2VydmljZU5hbWUsIGxvZ1N0cmVhbSk7XG5cbiAgLy8gV2lyZSB0aGUgaWRlbXBvdGVuY3kgcmVwbGF5LWNhY2hlIGJhY2tlbmQgdXNlZCBieSB0aGUgcG9zdC1hdXRoIHJvdXRlXG4gIC8vIGZhY3RvcmllcyAoY3JlYXRlUHJvdGVjdGVkUm91dGUgLyBjcmVhdGVBdXRoZW50aWNhdGVkV2l0aE9yZ1JvdXRlKS4gUHJlZmVyXG4gIC8vIGFuIGV4cGxpY2l0bHkgaW5qZWN0ZWQgc3RvcmU7IG90aGVyd2lzZSBhdXRvLWNvbnN0cnVjdCBmcm9tIHRoZSBzaGFyZWQgZW52XG4gIC8vIFJlZGlzIHNvIGtleWVkIG11dGF0aW9uIHJldHJpZXMgZGVkdXBlIGFjcm9zcyByZXBsaWNhcy4gRmFsbHMgYmFjayB0byB0aGVcbiAgLy8gaW4tbWVtb3J5IGRlZmF1bHQgd2hlbiBubyBSZWRpcyBpcyBjb25maWd1cmVkIChzaW5nbGUtcmVwbGljYSBjb3JyZWN0bmVzcykuXG4gIGNvbnN0IHJlc29sdmVkSWRlbXBvdGVuY3lTdG9yZSA9IG9wdGlvbnMuaWRlbXBvdGVuY3lTdG9yZSA/PyBjcmVhdGVFbnZSZWRpc0lkZW1wb3RlbmN5U3RvcmUoKTtcbiAgaWYgKHJlc29sdmVkSWRlbXBvdGVuY3lTdG9yZSkge1xuICAgIHNldElkZW1wb3RlbmN5U3RvcmUocmVzb2x2ZWRJZGVtcG90ZW5jeVN0b3JlKTtcbiAgfVxuXG4gIC8vIE9wZW5UZWxlbWV0cnkgaXMgTk9UIGluaXRpYWxpemVkIGhlcmU6IGJ5IHRoZSB0aW1lIGNyZWF0ZUFwcCBydW5zLCBleHByZXNzXG4gIC8vIGFuZCBodHRwIGhhdmUgYWxyZWFkeSBiZWVuIHJlcXVpcmVkLCBzbyB0aGUgYXV0by1pbnN0cnVtZW50YXRpb24gaG9va3NcbiAgLy8gd291bGQgaGF2ZSBub3RoaW5nIHRvIHBhdGNoIChubyBpbmJvdW5kIHNwYW4g4oaSIG5vIHRyYWNlIGlkKS4gVHJhY2luZyBpc1xuICAvLyBzdGFydGVkIGJ5IHRoZSBgb3RlbC1ib290c3RyYXAuanNgIHByZWxvYWQgaW5zdGVhZCAobm9kZSAtciDigKYg4oCUIHNlZSBlYWNoXG4gIC8vIHNlcnZpY2UncyBEb2NrZXJmaWxlIENNRCAvIHN0YXJ0IHNjcmlwdCksIHdoaWNoIHJ1bnMgYmVmb3JlIGFueVxuICAvLyBpbnN0cnVtZW50ZWQgbW9kdWxlIGxvYWRzLiBgY3VycmVudFRyYWNlSWQoKWAgdGhlbiByZWFkcyB0aGUgYWN0aXZlIHNwYW4uXG5cbiAgY29uc3QgYXBwID0gZXhwcmVzcygpO1xuXG4gIGFwcGx5U2VjdXJpdHlIZWFkZXJzKGFwcCwgb3B0aW9ucywgZW5hYmxlT3BlbkFwaSk7XG4gIGFwcGx5Qm9keVBhcnNpbmcoYXBwLCBvcHRpb25zKTtcblxuICAvLyBUcnVzdCBwcm94eSAobXVzdCBiZSBzZXQgYmVmb3JlIHJhdGUgbGltaXRlciBzbyByZXEuaXAgcmVzb2x2ZXMgY29ycmVjdGx5KVxuICBhcHAuc2V0KCd0cnVzdCBwcm94eScsIENvbmZpZy5nZXQoJ3NlcnZlcicpLnRydXN0UHJveHkpO1xuXG4gIC8vIFJlcXVlc3QgSUQgKyBhdWRpdCBjb250ZXh0LiBQcmVmZXIgdGhlIGluYm91bmQgYFgtUmVxdWVzdC1JZGAgKG5naW54LCBvciBhXG4gIC8vIHBlZXIgc2VydmljZSAvIENMSSBmb3J3YXJkaW5nIGl0cyBvd24pIHdoZW4gaXQgaXMgYSBib3VuZGVkIG9wYXF1ZSB0b2tlbiDigJRcbiAgLy8gYW4gb3ZlcnNpemVkIG9yIGp1bmsgdmFsdWUgaXMgcmVwbGFjZWQsIG5vdCBzdG9yZWQg4oCUIG90aGVyd2lzZSBnZW5lcmF0ZSBvbmUuXG4gIC8vIFRoZSByZXN0IG9mIHRoZSByZXF1ZXN0IHRoZW4gcnVucyBpbnNpZGUgYW4gYXVkaXQtY29udGV4dCBzY29wZSwgc28gZXZlcnlcbiAgLy8gYHJlY29yZEF1ZGl0YCBpdCBtYWtlcyBjYXJyaWVzIHRoZSByZXF1ZXN0IGlkLCB0cmFjZSBpZCwgY2xpZW50IGlwIC8gVUEsIHRoZVxuICAvLyB2ZXJpZmllZCBjcmVkZW50aWFsIChyZWFkIGxhemlseSwgYWZ0ZXIgYHJlcXVpcmVBdXRoYCkgYW5kIGFueSBpbmJvdW5kXG4gIC8vIGBYLVBpcGVsaW5lLUV4ZWN1dGlvbi1JZGAgLyBgWC1Db2RlQnVpbGQtQnVpbGQtSWRgIC8gYFgtU291cmNlLUV2ZW50LUlkYFxuICAvLyB3aXRoIG5vIGNhbGwtc2l0ZSBjaGFuZ2UuIE1vdW50ZWQgYWZ0ZXIgYHRydXN0IHByb3h5YCBzbyBgcmVxLmlwYCBpcyByZWFsLlxuICBhcHAudXNlKChyZXE6IFJlcXVlc3QsIHJlczogUmVzcG9uc2UsIG5leHQ6IE5leHRGdW5jdGlvbikgPT4ge1xuICAgIGNvbnN0IGhkciA9IHJlcS5oZWFkZXJzWyd4LXJlcXVlc3QtaWQnXTtcbiAgICBjb25zdCByZXF1ZXN0SWQgPSBzYW5pdGl6ZUNvcnJlbGF0aW9uSWQoQXJyYXkuaXNBcnJheShoZHIpID8gaGRyWzBdIDogaGRyKSA/PyB1dWlkKCk7XG4gICAgcmVxLnJlcXVlc3RJZCA9IHJlcXVlc3RJZDtcbiAgICByZXMuc2V0SGVhZGVyKCdYLVJlcXVlc3QtSWQnLCByZXF1ZXN0SWQpO1xuICAgIHJ1bldpdGhBdWRpdENvbnRleHQoYXVkaXRDb250ZXh0RnJvbVJlcXVlc3QocmVxLCB7IHJlcXVlc3RJZCwgdHJhY2VJZDogY3VycmVudFRyYWNlSWQoKSB9KSwgbmV4dCk7XG4gIH0pO1xuXG4gIG1vdW50SW5mcmFFbmRwb2ludHMoYXBwLCBvcHRpb25zLCBzZXJ2aWNlTmFtZSwgZW5hYmxlT3BlbkFwaSk7XG4gIGlmIChlbmFibGVSYXRlTGltaXQpIG1vdW50UmF0ZUxpbWl0ZXIoYXBwLCBzZXJ2aWNlTmFtZSk7XG4gIGFwcGx5UmVxdWVzdFRlbGVtZXRyeShhcHApO1xuXG4gIC8vIE5PVEU6IGlkZW1wb3RlbmN5IGlzIGludGVudGlvbmFsbHkgTk9UIG1vdW50ZWQgaGVyZS4gSXQgbmVlZHMgdGhlIFZFUklGSUVEXG4gIC8vIG9yZyBpZCB0byBuYW1lc3BhY2UgaXRzIHJlcGxheSBjYWNoZSwgYnV0IHRoaXMgcHJlLWF1dGggcG9zaXRpb24gcnVucyBiZWZvcmVcbiAgLy8gYHJlcXVpcmVBdXRoYC9gYXR0YWNoUmVxdWVzdENvbnRleHRgIHBvcHVsYXRlIGlkZW50aXR5LCBzbyBhIGdsb2JhbCBtb3VudFxuICAvLyBoZXJlIGlzIGEgcGVybWFuZW50IG5vLW9wIChvcmcgYWx3YXlzIHVuZGVmaW5lZCDihpIgc2tpcCkuIEl0IGlzIGluc3RlYWQgd2lyZWRcbiAgLy8gaW50byB0aGUgcG9zdC1hdXRoIHJvdXRlIGNoYWlucyDigJQgc2VlIGBjcmVhdGVQcm90ZWN0ZWRSb3V0ZWAgL1xuICAvLyBgY3JlYXRlQXV0aGVudGljYXRlZFdpdGhPcmdSb3V0ZWAgaW4gbWlkZGxld2FyZS1mYWN0b3J5LnRzLlxuXG4gIGlmIChsb2dTdHJlYW0pIHdpcmVTc2UoYXBwLCBzc2VNYW5hZ2VyKTtcblxuICByZXR1cm4geyBhcHAsIHNzZU1hbmFnZXIgfTtcbn1cbiJdfQ==
|
package/lib/api/check-quota.d.ts
CHANGED
|
@@ -1,13 +1,57 @@
|
|
|
1
1
|
import type { QuotaType, QuotaService } from '@pipeline-builder/api-core';
|
|
2
|
-
import type { Request, Response, NextFunction } from 'express';
|
|
2
|
+
import type { Request, RequestHandler, Response, NextFunction } from 'express';
|
|
3
|
+
/** TTL (ms) of a cached ALLOWED check. `0` disables the cache. */
|
|
4
|
+
export declare const QUOTA_CHECK_CACHE_TTL_MS: number;
|
|
5
|
+
/** Longest (ms) a DENIED check is reused before re-asking (it never outlives `resetAt`). */
|
|
6
|
+
export declare const QUOTA_CHECK_DENIED_CACHE_MS: number;
|
|
7
|
+
/** Drop every cached check (tests; also a safe operational reset). */
|
|
8
|
+
export declare function clearQuotaCheckCache(): void;
|
|
3
9
|
/**
|
|
4
10
|
* Create middleware that checks a specific quota type before proceeding.
|
|
5
11
|
*
|
|
6
|
-
* On quota exceeded, returns a 429 response with quota details
|
|
12
|
+
* On quota exceeded, returns a 429 response with quota details (quotaType,
|
|
13
|
+
* limit, used, resetAt, upgradeUrl — see api-core `sendQuotaExceeded`).
|
|
7
14
|
* On quota service failure, fails open (allows the request).
|
|
8
15
|
*
|
|
16
|
+
* `apiCalls` is split per request by principal: an org service account or a
|
|
17
|
+
* personal access key is checked against `automationCalls` instead
|
|
18
|
+
* ({@link meteredQuotaTypeFor}), the
|
|
19
|
+
* same type `meterQuotaOnSuccess` increments — so mount both with `'apiCalls'`.
|
|
20
|
+
*
|
|
21
|
+
* Skipped (passes through) exactly where the meter skips, so the gate never
|
|
22
|
+
* refuses a call the meter would not bill (`callQuotaExemption`):
|
|
23
|
+
* - a SERVICE PRINCIPAL (peer-service traffic is never metered, so a tenant at
|
|
24
|
+
* its limit must not break the internal calls its own earlier actions caused);
|
|
25
|
+
* - for `apiCalls`: an IMPERSONATION session (vendor staff diagnosing an
|
|
26
|
+
* exhausted org must not be locked out by it) and an ON-BEHALF hop (a user
|
|
27
|
+
* token forwarded by ask/pipeline with a signed marker — the originating
|
|
28
|
+
* request was already gated and metered);
|
|
29
|
+
* - an `apiCalls` request on the fleet-wide `QUOTA_EXEMPT_ROUTES` (console
|
|
30
|
+
* polling — an exhausted org must still render the banner saying so);
|
|
31
|
+
* - an idempotent RETRY whose original already completed (the replay is served
|
|
32
|
+
* from the idempotency cache, does no work and is never metered; refusing it
|
|
33
|
+
* would 429 a client for asking what its own earlier request returned).
|
|
34
|
+
*
|
|
35
|
+
* Readings are cached per pod (see the cache notes above), and the read itself
|
|
36
|
+
* has a short budget (api-core `QUOTA_CHECK_TIMEOUT_MS`, no retry) — a slow
|
|
37
|
+
* quota service fails open quickly instead of stalling every request.
|
|
38
|
+
*
|
|
39
|
+
* Mountable at the app-routes level (`app.use(prefix, …auth, checkQuota(...))`):
|
|
40
|
+
* the org comes from the request context when one is attached, else from the
|
|
41
|
+
* verified `req.user.organizationId` — the same fallback the meter uses.
|
|
42
|
+
*
|
|
9
43
|
* @param quotaService - Quota service client
|
|
10
44
|
* @param quotaType - Which quota to check (e.g. 'apiCalls', 'pipelines', 'plugins')
|
|
11
45
|
* @returns Express middleware
|
|
12
46
|
*/
|
|
13
|
-
export declare function checkQuota(quotaService: QuotaService,
|
|
47
|
+
export declare function checkQuota(quotaService: QuotaService, baseQuotaType: QuotaType): (req: Request, res: Response, next: NextFunction) => Promise<void>;
|
|
48
|
+
/** The service-local request path, without the query string. */
|
|
49
|
+
export declare function requestPath(req: Request): string;
|
|
50
|
+
/**
|
|
51
|
+
* The DEFERRED form of {@link checkQuota}: arms the check at mount time and lets
|
|
52
|
+
* `requireAuth` run it once the caller is verified (api-core
|
|
53
|
+
* `armDeferredQuotaCheck`). For a prefix mount ahead of routers that
|
|
54
|
+
* authenticate per route — use {@link apiCallsQuota}, which pairs it with the
|
|
55
|
+
* meter. Tagged as the check gate, so the route table records it.
|
|
56
|
+
*/
|
|
57
|
+
export declare function deferredCheckQuota(quotaService: QuotaService, quotaType: QuotaType): RequestHandler;
|