@pipeline-builder/api-core 3.4.96 → 3.4.99
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/errors/app-errors.js +1 -1
- package/lib/helpers/access-helpers.d.ts +2 -1
- package/lib/helpers/access-helpers.js +11 -5
- package/lib/helpers/org-hierarchy-http.d.ts +13 -3
- package/lib/helpers/org-hierarchy-http.js +10 -5
- package/lib/middleware/auth.d.ts +16 -5
- package/lib/middleware/auth.js +17 -7
- package/lib/services/audit-spool.d.ts +4 -5
- package/lib/services/audit-spool.js +10 -27
- package/lib/services/cache-service.js +11 -10
- package/lib/services/compliance-event-subscriber.js +1 -1
- package/lib/services/env-redis.d.ts +20 -0
- package/lib/services/env-redis.js +47 -0
- package/lib/services/leader-lock.d.ts +10 -0
- package/lib/services/leader-lock.js +19 -1
- package/lib/services/quota.js +14 -5
- package/lib/services/remote-audit-client.d.ts +19 -1
- package/lib/services/remote-audit-client.js +41 -1
- package/lib/services/scheduler.js +15 -1
- package/lib/services/token-revocation.js +8 -30
- package/lib/types/common.d.ts +1 -1
- package/lib/types/feature-flags.d.ts +1 -1
- package/lib/types/feature-flags.js +6 -1
- package/lib/types/pipeline.d.ts +9 -9
- package/lib/utils/crash-handlers.js +1 -1
- package/lib/utils/index.d.ts +0 -1
- package/lib/utils/index.js +1 -2
- package/lib/utils/logger.js +1 -1
- package/lib/utils/metric-emitter.js +1 -1
- package/lib/utils/params.d.ts +1 -1
- package/lib/utils/params.js +1 -1
- package/lib/utils/response.js +1 -1
- package/lib/utils/secret-encryption.js +1 -1
- package/lib/utils/ssrf.d.ts +1 -1
- package/lib/utils/ssrf.js +1 -1
- package/lib/validation/ai-schemas.d.ts +4 -4
- package/lib/validation/common-schemas.d.ts +8 -8
- package/lib/validation/message-schemas.d.ts +10 -10
- package/lib/validation/pipeline-schemas.d.ts +13 -13
- package/lib/validation/plugin-schemas.d.ts +18 -18
- package/package.json +11 -10
- package/lib/utils/org-aws-credentials.d.ts +0 -154
- package/lib/utils/org-aws-credentials.js +0 -139
|
@@ -1,154 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Per-org IAM role assumption for build / runtime AWS API calls.
|
|
3
|
-
*
|
|
4
|
-
* The shared posture for AWS calls today is "the service's IAM role, full
|
|
5
|
-
* blast radius across every org." The operator-side mitigation operators
|
|
6
|
-
* actually want is: each customer org gets its own IAM role in its own
|
|
7
|
-
* account; build/runtime AWS calls for that org `sts:AssumeRole` into the
|
|
8
|
-
* customer's role; a compromise of one org's role can't enumerate another
|
|
9
|
-
* org's S3 buckets / ECR repos.
|
|
10
|
-
*
|
|
11
|
-
* This module is the credential-provider primitive. It's pluggable on the
|
|
12
|
-
* org-config resolver so the same code path works whether config is read
|
|
13
|
-
* from Mongo, Postgres, or env vars. Callers receive a standard SDK v3
|
|
14
|
-
* `AwsCredentialIdentityProvider` and pass it to any SDK client
|
|
15
|
-
* (`new CodeBuildClient({ credentials })`, etc.).
|
|
16
|
-
*
|
|
17
|
-
* No global state — callers construct one `OrgAwsCredentialsManager` per
|
|
18
|
-
* process and `await manager.getCredentials(orgId)` before each AWS call.
|
|
19
|
-
* The returned provider handles credential refresh internally (the
|
|
20
|
-
* underlying `fromTemporaryCredentials` re-calls AssumeRole ~5 min before
|
|
21
|
-
* the temporary credentials expire), so call sites don't manage TTL.
|
|
22
|
-
*
|
|
23
|
-
* Safety properties:
|
|
24
|
-
* - `externalId` is plumbed through to AssumeRole. Operators bake this
|
|
25
|
-
* into the IAM trust policy as the "confused deputy" mitigation; this
|
|
26
|
-
* module never silently omits it.
|
|
27
|
-
* - Orgs without a configured role fall through to the supplied
|
|
28
|
-
* `fallback` provider (typically the SDK default chain). Mixed-mode
|
|
29
|
-
* deployments where some orgs have per-org roles and others use the
|
|
30
|
-
* shared role are explicitly supported.
|
|
31
|
-
* - `evict(orgId)` drops the cached provider so the next call re-resolves
|
|
32
|
-
* from the resolver — use after the operator changes an org's role.
|
|
33
|
-
*
|
|
34
|
-
* Integration pattern for AWS SDK clients:
|
|
35
|
-
*
|
|
36
|
-
* ```ts
|
|
37
|
-
* import { S3Client } from '@aws-sdk/client-s3';
|
|
38
|
-
* import { withOrgAwsCredentials } from '@pipeline-builder/api-core';
|
|
39
|
-
*
|
|
40
|
-
* const manager = new OrgAwsCredentialsManager({ resolver });
|
|
41
|
-
*
|
|
42
|
-
* async function s3ForOrg(orgId: string) {
|
|
43
|
-
* return withOrgAwsCredentials(manager, orgId, (creds) =>
|
|
44
|
-
* new S3Client({ credentials: creds, region: 'us-west-2' }));
|
|
45
|
-
* }
|
|
46
|
-
* ```
|
|
47
|
-
*
|
|
48
|
-
* Today's codebase: no platform-side service makes AWS API calls scoped to
|
|
49
|
-
* a customer org (build runners use buildkitd; AWS Lambda handlers run in
|
|
50
|
-
* customer territory with their own IAM). This primitive is in place for
|
|
51
|
-
* when the architecture grows to add such call sites — per-org S3 buckets,
|
|
52
|
-
* per-org ECR repos, per-org CodeBuild projects — without forcing an
|
|
53
|
-
* insecure default.
|
|
54
|
-
*/
|
|
55
|
-
/** Structural shape of an AWS credential. Matches `@smithy/types#AwsCredentialIdentity`
|
|
56
|
-
* exactly — defined locally so api-core doesn't need to declare @smithy/types
|
|
57
|
-
* as a direct dep (it's a transitive of every AWS SDK client we use). */
|
|
58
|
-
export interface AwsCredentialIdentity {
|
|
59
|
-
accessKeyId: string;
|
|
60
|
-
secretAccessKey: string;
|
|
61
|
-
sessionToken?: string;
|
|
62
|
-
expiration?: Date;
|
|
63
|
-
credentialScope?: string;
|
|
64
|
-
accountId?: string;
|
|
65
|
-
}
|
|
66
|
-
/** Standard credential-provider callable. Matches `@smithy/types#AwsCredentialIdentityProvider`. */
|
|
67
|
-
export type AwsCredentialIdentityProvider = () => Promise<AwsCredentialIdentity>;
|
|
68
|
-
/** Operator-supplied per-org IAM role + region pinning. */
|
|
69
|
-
export interface OrgAwsConfig {
|
|
70
|
-
/** ARN of the role this org's build/runtime code should assume. */
|
|
71
|
-
assumeRoleArn: string;
|
|
72
|
-
/** External id baked into the role's trust policy (recommended). */
|
|
73
|
-
externalId?: string;
|
|
74
|
-
/** Region to use when the calling code doesn't pin one. */
|
|
75
|
-
region?: string;
|
|
76
|
-
/** AssumeRole session duration (seconds). AWS allows 900-43200; the
|
|
77
|
-
* effective ceiling is the role's `MaxSessionDuration`. Default 3600. */
|
|
78
|
-
sessionDurationSeconds?: number;
|
|
79
|
-
/** Session name embedded in CloudTrail. Useful for incident-response
|
|
80
|
-
* attribution. Default `pipeline-builder-<orgId>`. */
|
|
81
|
-
roleSessionName?: string;
|
|
82
|
-
}
|
|
83
|
-
/** Async resolver: orgId → config | null. Returning null means "this org
|
|
84
|
-
* has no per-org role; use the fallback provider." */
|
|
85
|
-
export type OrgAwsConfigResolver = (orgId: string) => Promise<OrgAwsConfig | null>;
|
|
86
|
-
/** Constructor options. */
|
|
87
|
-
export interface OrgAwsCredentialsManagerOptions {
|
|
88
|
-
resolver: OrgAwsConfigResolver;
|
|
89
|
-
/** Provider used for orgs whose resolver returns null. Default: the SDK
|
|
90
|
-
* default chain via `@aws-sdk/credential-providers#fromNodeProviderChain`. */
|
|
91
|
-
fallback?: AwsCredentialIdentityProvider;
|
|
92
|
-
/** Region passed to the inner STS client when the org config doesn't
|
|
93
|
-
* pin one. Default: `AWS_REGION` / `AWS_DEFAULT_REGION` env. */
|
|
94
|
-
region?: string;
|
|
95
|
-
/** STS endpoint override (LocalStack, VPC endpoint). Default: SDK default. */
|
|
96
|
-
endpoint?: string;
|
|
97
|
-
}
|
|
98
|
-
/**
|
|
99
|
-
* Per-process manager that resolves and caches per-org credential providers.
|
|
100
|
-
* One instance per service; share it across handlers.
|
|
101
|
-
*/
|
|
102
|
-
export declare class OrgAwsCredentialsManager {
|
|
103
|
-
private readonly resolver;
|
|
104
|
-
private readonly fallbackOverride?;
|
|
105
|
-
private readonly region?;
|
|
106
|
-
private readonly endpoint?;
|
|
107
|
-
private readonly cache;
|
|
108
|
-
private readonly inFlight;
|
|
109
|
-
/** Lazy default chain. Built once per manager so we don't import the
|
|
110
|
-
* credential-providers SDK in test environments that never touch the
|
|
111
|
-
* fallback path. */
|
|
112
|
-
private fallbackCache?;
|
|
113
|
-
constructor(opts: OrgAwsCredentialsManagerOptions);
|
|
114
|
-
/**
|
|
115
|
-
* Return an AwsCredentialIdentityProvider scoped to `orgId`. Pass the
|
|
116
|
-
* returned value into any SDK v3 client's `credentials` option.
|
|
117
|
-
*
|
|
118
|
-
* Concurrent first-touch callers share one resolver invocation; later
|
|
119
|
-
* calls hit the cache. The provider itself caches and refreshes
|
|
120
|
-
* AssumeRole-derived credentials internally.
|
|
121
|
-
*/
|
|
122
|
-
getCredentials(orgId: string): Promise<AwsCredentialIdentityProvider>;
|
|
123
|
-
/** Drop the cached provider for an org. Call after the operator rotates
|
|
124
|
-
* the role ARN or external id so the next request rebuilds. */
|
|
125
|
-
evict(orgId: string): void;
|
|
126
|
-
/** Drop every cached provider. Useful in tests; rarely in production. */
|
|
127
|
-
evictAll(): void;
|
|
128
|
-
private resolveAndBuild;
|
|
129
|
-
private getFallback;
|
|
130
|
-
private buildAssumeRoleProvider;
|
|
131
|
-
}
|
|
132
|
-
/** Convenience: directly resolve credentials for a single call. The manager
|
|
133
|
-
* doesn't cache when called this way — useful in CLIs / one-shot scripts. */
|
|
134
|
-
export declare function resolveOrgCredentialsOnce(orgId: string, resolver: OrgAwsConfigResolver): Promise<AwsCredentialIdentity>;
|
|
135
|
-
/**
|
|
136
|
-
* Adapter: resolve per-org credentials and construct an AWS SDK client
|
|
137
|
-
* pre-bound to them. The factory is async because credential resolution may
|
|
138
|
-
* need to make a network call (fetching org config + AssumeRole). Once
|
|
139
|
-
* resolved, the returned client is ready for normal SDK calls; the provider
|
|
140
|
-
* inside refreshes credentials automatically before they expire.
|
|
141
|
-
*
|
|
142
|
-
* Typical usage:
|
|
143
|
-
* ```ts
|
|
144
|
-
* const s3 = await withOrgAwsCredentials(manager, orgId, (creds) =>
|
|
145
|
-
* new S3Client({ credentials: creds, region: 'us-west-2' }));
|
|
146
|
-
* await s3.send(new ListObjectsV2Command({ Bucket: bucketFor(orgId) }));
|
|
147
|
-
* ```
|
|
148
|
-
*
|
|
149
|
-
* The factory is invoked exactly once per call — callers that need a
|
|
150
|
-
* long-lived client should cache the result themselves rather than rebuilding
|
|
151
|
-
* on every operation. (Re-resolving on every op is fine for cold paths and
|
|
152
|
-
* a wasted couple of object allocations on hot paths.)
|
|
153
|
-
*/
|
|
154
|
-
export declare function withOrgAwsCredentials<TClient>(manager: OrgAwsCredentialsManager, orgId: string, factory: (credentials: AwsCredentialIdentityProvider) => TClient): Promise<TClient>;
|
|
@@ -1,139 +0,0 @@
|
|
|
1
|
-
// Copyright 2026 Pipeline Builder Contributors
|
|
2
|
-
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
-
/**
|
|
4
|
-
* Per-process manager that resolves and caches per-org credential providers.
|
|
5
|
-
* One instance per service; share it across handlers.
|
|
6
|
-
*/
|
|
7
|
-
export class OrgAwsCredentialsManager {
|
|
8
|
-
resolver;
|
|
9
|
-
fallbackOverride;
|
|
10
|
-
region;
|
|
11
|
-
endpoint;
|
|
12
|
-
cache = new Map();
|
|
13
|
-
inFlight = new Map();
|
|
14
|
-
/** Lazy default chain. Built once per manager so we don't import the
|
|
15
|
-
* credential-providers SDK in test environments that never touch the
|
|
16
|
-
* fallback path. */
|
|
17
|
-
fallbackCache;
|
|
18
|
-
constructor(opts) {
|
|
19
|
-
this.resolver = opts.resolver;
|
|
20
|
-
this.fallbackOverride = opts.fallback;
|
|
21
|
-
this.region = opts.region ?? process.env.AWS_REGION ?? process.env.AWS_DEFAULT_REGION;
|
|
22
|
-
this.endpoint = opts.endpoint ?? process.env.AWS_STS_ENDPOINT;
|
|
23
|
-
}
|
|
24
|
-
/**
|
|
25
|
-
* Return an AwsCredentialIdentityProvider scoped to `orgId`. Pass the
|
|
26
|
-
* returned value into any SDK v3 client's `credentials` option.
|
|
27
|
-
*
|
|
28
|
-
* Concurrent first-touch callers share one resolver invocation; later
|
|
29
|
-
* calls hit the cache. The provider itself caches and refreshes
|
|
30
|
-
* AssumeRole-derived credentials internally.
|
|
31
|
-
*/
|
|
32
|
-
async getCredentials(orgId) {
|
|
33
|
-
if (!orgId)
|
|
34
|
-
throw new Error('OrgAwsCredentialsManager.getCredentials requires a non-empty orgId');
|
|
35
|
-
const cached = this.cache.get(orgId);
|
|
36
|
-
if (cached)
|
|
37
|
-
return cached;
|
|
38
|
-
let pending = this.inFlight.get(orgId);
|
|
39
|
-
if (!pending) {
|
|
40
|
-
pending = this.resolveAndBuild(orgId);
|
|
41
|
-
this.inFlight.set(orgId, pending);
|
|
42
|
-
void pending.finally(() => {
|
|
43
|
-
if (this.inFlight.get(orgId) === pending)
|
|
44
|
-
this.inFlight.delete(orgId);
|
|
45
|
-
});
|
|
46
|
-
}
|
|
47
|
-
return pending;
|
|
48
|
-
}
|
|
49
|
-
/** Drop the cached provider for an org. Call after the operator rotates
|
|
50
|
-
* the role ARN or external id so the next request rebuilds. */
|
|
51
|
-
evict(orgId) {
|
|
52
|
-
this.cache.delete(orgId);
|
|
53
|
-
}
|
|
54
|
-
/** Drop every cached provider. Useful in tests; rarely in production. */
|
|
55
|
-
evictAll() {
|
|
56
|
-
this.cache.clear();
|
|
57
|
-
}
|
|
58
|
-
async resolveAndBuild(orgId) {
|
|
59
|
-
const cfg = await this.resolver(orgId);
|
|
60
|
-
if (!cfg || !cfg.assumeRoleArn) {
|
|
61
|
-
const fallback = await this.getFallback();
|
|
62
|
-
this.cache.set(orgId, fallback);
|
|
63
|
-
return fallback;
|
|
64
|
-
}
|
|
65
|
-
const provider = await this.buildAssumeRoleProvider(orgId, cfg);
|
|
66
|
-
this.cache.set(orgId, provider);
|
|
67
|
-
return provider;
|
|
68
|
-
}
|
|
69
|
-
async getFallback() {
|
|
70
|
-
if (this.fallbackOverride)
|
|
71
|
-
return this.fallbackOverride;
|
|
72
|
-
if (this.fallbackCache)
|
|
73
|
-
return this.fallbackCache;
|
|
74
|
-
// Lazy-import so test envs that supply their own resolver/fallback
|
|
75
|
-
// don't load the credential-providers SDK.
|
|
76
|
-
const { fromNodeProviderChain } = await import('@aws-sdk/credential-providers');
|
|
77
|
-
this.fallbackCache = fromNodeProviderChain();
|
|
78
|
-
return this.fallbackCache;
|
|
79
|
-
}
|
|
80
|
-
async buildAssumeRoleProvider(orgId, cfg) {
|
|
81
|
-
// Dynamic import — credential-providers is heavyweight and services that
|
|
82
|
-
// never have per-org roles configured shouldn't load it.
|
|
83
|
-
const { fromTemporaryCredentials } = await import('@aws-sdk/credential-providers');
|
|
84
|
-
const masterCredentials = this.fallbackOverride ?? (await this.getFallback());
|
|
85
|
-
const sessionName = cfg.roleSessionName ?? `pipeline-builder-${orgId}`.slice(0, 64);
|
|
86
|
-
const region = cfg.region ?? this.region;
|
|
87
|
-
return fromTemporaryCredentials({
|
|
88
|
-
// Inner STS client uses the service's own credentials (the fallback
|
|
89
|
-
// chain). Those creds need `sts:AssumeRole` on the org's role.
|
|
90
|
-
masterCredentials,
|
|
91
|
-
clientConfig: {
|
|
92
|
-
region,
|
|
93
|
-
...(this.endpoint ? { endpoint: this.endpoint } : {}),
|
|
94
|
-
// Cast to the exact clientConfig type fromTemporaryCredentials expects.
|
|
95
|
-
// @aws-sdk ships STSClientConfig from both `client-sts` and the
|
|
96
|
-
// `nested-clients` STS submodule at independently-bumped versions, so a
|
|
97
|
-
// `typeof STSClient` cast can resolve to the wrong one; deriving it from
|
|
98
|
-
// the function's own Parameters keeps them in lockstep.
|
|
99
|
-
},
|
|
100
|
-
params: {
|
|
101
|
-
RoleArn: cfg.assumeRoleArn,
|
|
102
|
-
RoleSessionName: sessionName,
|
|
103
|
-
DurationSeconds: cfg.sessionDurationSeconds ?? 3600,
|
|
104
|
-
...(cfg.externalId ? { ExternalId: cfg.externalId } : {}),
|
|
105
|
-
},
|
|
106
|
-
});
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
/** Convenience: directly resolve credentials for a single call. The manager
|
|
110
|
-
* doesn't cache when called this way — useful in CLIs / one-shot scripts. */
|
|
111
|
-
export async function resolveOrgCredentialsOnce(orgId, resolver) {
|
|
112
|
-
const manager = new OrgAwsCredentialsManager({ resolver });
|
|
113
|
-
const provider = await manager.getCredentials(orgId);
|
|
114
|
-
return provider();
|
|
115
|
-
}
|
|
116
|
-
/**
|
|
117
|
-
* Adapter: resolve per-org credentials and construct an AWS SDK client
|
|
118
|
-
* pre-bound to them. The factory is async because credential resolution may
|
|
119
|
-
* need to make a network call (fetching org config + AssumeRole). Once
|
|
120
|
-
* resolved, the returned client is ready for normal SDK calls; the provider
|
|
121
|
-
* inside refreshes credentials automatically before they expire.
|
|
122
|
-
*
|
|
123
|
-
* Typical usage:
|
|
124
|
-
* ```ts
|
|
125
|
-
* const s3 = await withOrgAwsCredentials(manager, orgId, (creds) =>
|
|
126
|
-
* new S3Client({ credentials: creds, region: 'us-west-2' }));
|
|
127
|
-
* await s3.send(new ListObjectsV2Command({ Bucket: bucketFor(orgId) }));
|
|
128
|
-
* ```
|
|
129
|
-
*
|
|
130
|
-
* The factory is invoked exactly once per call — callers that need a
|
|
131
|
-
* long-lived client should cache the result themselves rather than rebuilding
|
|
132
|
-
* on every operation. (Re-resolving on every op is fine for cold paths and
|
|
133
|
-
* a wasted couple of object allocations on hot paths.)
|
|
134
|
-
*/
|
|
135
|
-
export async function withOrgAwsCredentials(manager, orgId, factory) {
|
|
136
|
-
const credentials = await manager.getCredentials(orgId);
|
|
137
|
-
return factory(credentials);
|
|
138
|
-
}
|
|
139
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3JnLWF3cy1jcmVkZW50aWFscy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy91dGlscy9vcmctYXdzLWNyZWRlbnRpYWxzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLCtDQUErQztBQUMvQyxzQ0FBc0M7QUF5R3RDOzs7R0FHRztBQUNILE1BQU0sT0FBTyx3QkFBd0I7SUFDbEIsUUFBUSxDQUF1QjtJQUMvQixnQkFBZ0IsQ0FBaUM7SUFDakQsTUFBTSxDQUFVO0lBQ2hCLFFBQVEsQ0FBVTtJQUNsQixLQUFLLEdBQUcsSUFBSSxHQUFHLEVBQXlDLENBQUM7SUFDekQsUUFBUSxHQUFHLElBQUksR0FBRyxFQUFrRCxDQUFDO0lBQ3RGOzt5QkFFcUI7SUFDYixhQUFhLENBQWlDO0lBRXRELFlBQVksSUFBcUM7UUFDL0MsSUFBSSxDQUFDLFFBQVEsR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFDO1FBQzlCLElBQUksQ0FBQyxnQkFBZ0IsR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFDO1FBQ3RDLElBQUksQ0FBQyxNQUFNLEdBQUcsSUFBSSxDQUFDLE1BQU0sSUFBSSxPQUFPLENBQUMsR0FBRyxDQUFDLFVBQVUsSUFBSSxPQUFPLENBQUMsR0FBRyxDQUFDLGtCQUFrQixDQUFDO1FBQ3RGLElBQUksQ0FBQyxRQUFRLEdBQUcsSUFBSSxDQUFDLFFBQVEsSUFBSSxPQUFPLENBQUMsR0FBRyxDQUFDLGdCQUFnQixDQUFDO0lBQ2hFLENBQUM7SUFFRDs7Ozs7OztPQU9HO0lBQ0gsS0FBSyxDQUFDLGNBQWMsQ0FBQyxLQUFhO1FBQ2hDLElBQUksQ0FBQyxLQUFLO1lBQUUsTUFBTSxJQUFJLEtBQUssQ0FBQyxvRUFBb0UsQ0FBQyxDQUFDO1FBRWxHLE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQ3JDLElBQUksTUFBTTtZQUFFLE9BQU8sTUFBTSxDQUFDO1FBRTFCLElBQUks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dCI6WyIvLyBDb3B5cmlnaHQgMjAyNiBQaXBlbGluZSBCdWlsZGVyIENvbnRyaWJ1dG9yc1xuLy8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFwYWNoZS0yLjBcblxuLyoqXG4gKiBQZXItb3JnIElBTSByb2xlIGFzc3VtcHRpb24gZm9yIGJ1aWxkIC8gcnVudGltZSBBV1MgQVBJIGNhbGxzLlxuICpcbiAqIFRoZSBzaGFyZWQgcG9zdHVyZSBmb3IgQVdTIGNhbGxzIHRvZGF5IGlzIFwidGhlIHNlcnZpY2UncyBJQU0gcm9sZSwgZnVsbFxuICogYmxhc3QgcmFkaXVzIGFjcm9zcyBldmVyeSBvcmcuXCIgVGhlIG9wZXJhdG9yLXNpZGUgbWl0aWdhdGlvbiBvcGVyYXRvcnNcbiAqIGFjdHVhbGx5IHdhbnQgaXM6IGVhY2ggY3VzdG9tZXIgb3JnIGdldHMgaXRzIG93biBJQU0gcm9sZSBpbiBpdHMgb3duXG4gKiBhY2NvdW50OyBidWlsZC9ydW50aW1lIEFXUyBjYWxscyBmb3IgdGhhdCBvcmcgYHN0czpBc3N1bWVSb2xlYCBpbnRvIHRoZVxuICogY3VzdG9tZXIncyByb2xlOyBhIGNvbXByb21pc2Ugb2Ygb25lIG9yZydzIHJvbGUgY2FuJ3QgZW51bWVyYXRlIGFub3RoZXJcbiAqIG9yZydzIFMzIGJ1Y2tldHMgLyBFQ1IgcmVwb3MuXG4gKlxuICogVGhpcyBtb2R1bGUgaXMgdGhlIGNyZWRlbnRpYWwtcHJvdmlkZXIgcHJpbWl0aXZlLiBJdCdzIHBsdWdnYWJsZSBvbiB0aGVcbiAqIG9yZy1jb25maWcgcmVzb2x2ZXIgc28gdGhlIHNhbWUgY29kZSBwYXRoIHdvcmtzIHdoZXRoZXIgY29uZmlnIGlzIHJlYWRcbiAqIGZyb20gTW9uZ28sIFBvc3RncmVzLCBvciBlbnYgdmFycy4gQ2FsbGVycyByZWNlaXZlIGEgc3RhbmRhcmQgU0RLIHYzXG4gKiBgQXdzQ3JlZGVudGlhbElkZW50aXR5UHJvdmlkZXJgIGFuZCBwYXNzIGl0IHRvIGFueSBTREsgY2xpZW50XG4gKiAoYG5ldyBDb2RlQnVpbGRDbGllbnQoeyBjcmVkZW50aWFscyB9KWAsIGV0Yy4pLlxuICpcbiAqIE5vIGdsb2JhbCBzdGF0ZSDigJQgY2FsbGVycyBjb25zdHJ1Y3Qgb25lIGBPcmdBd3NDcmVkZW50aWFsc01hbmFnZXJgIHBlclxuICogcHJvY2VzcyBhbmQgYGF3YWl0IG1hbmFnZXIuZ2V0Q3JlZGVudGlhbHMob3JnSWQpYCBiZWZvcmUgZWFjaCBBV1MgY2FsbC5cbiAqIFRoZSByZXR1cm5lZCBwcm92aWRlciBoYW5kbGVzIGNyZWRlbnRpYWwgcmVmcmVzaCBpbnRlcm5hbGx5ICh0aGVcbiAqIHVuZGVybHlpbmcgYGZyb21UZW1wb3JhcnlDcmVkZW50aWFsc2AgcmUtY2FsbHMgQXNzdW1lUm9sZSB+NSBtaW4gYmVmb3JlXG4gKiB0aGUgdGVtcG9yYXJ5IGNyZWRlbnRpYWxzIGV4cGlyZSksIHNvIGNhbGwgc2l0ZXMgZG9uJ3QgbWFuYWdlIFRUTC5cbiAqXG4gKiBTYWZldHkgcHJvcGVydGllczpcbiAqICAtIGBleHRlcm5hbElkYCBpcyBwbHVtYmVkIHRocm91Z2ggdG8gQXNzdW1lUm9sZS4gT3BlcmF0b3JzIGJha2UgdGhpc1xuICogICAgaW50byB0aGUgSUFNIHRydXN0IHBvbGljeSBhcyB0aGUgXCJjb25mdXNlZCBkZXB1dHlcIiBtaXRpZ2F0aW9uOyB0aGlzXG4gKiAgICBtb2R1bGUgbmV2ZXIgc2lsZW50bHkgb21pdHMgaXQuXG4gKiAgLSBPcmdzIHdpdGhvdXQgYSBjb25maWd1cmVkIHJvbGUgZmFsbCB0aHJvdWdoIHRvIHRoZSBzdXBwbGllZFxuICogICAgYGZhbGxiYWNrYCBwcm92aWRlciAodHlwaWNhbGx5IHRoZSBTREsgZGVmYXVsdCBjaGFpbikuIE1peGVkLW1vZGVcbiAqICAgIGRlcGxveW1lbnRzIHdoZXJlIHNvbWUgb3JncyBoYXZlIHBlci1vcmcgcm9sZXMgYW5kIG90aGVycyB1c2UgdGhlXG4gKiAgICBzaGFyZWQgcm9sZSBhcmUgZXhwbGljaXRseSBzdXBwb3J0ZWQuXG4gKiAgLSBgZXZpY3Qob3JnSWQpYCBkcm9wcyB0aGUgY2FjaGVkIHByb3ZpZGVyIHNvIHRoZSBuZXh0IGNhbGwgcmUtcmVzb2x2ZXNcbiAqICAgIGZyb20gdGhlIHJlc29sdmVyIOKAlCB1c2UgYWZ0ZXIgdGhlIG9wZXJhdG9yIGNoYW5nZXMgYW4gb3JnJ3Mgcm9sZS5cbiAqXG4gKiBJbnRlZ3JhdGlvbiBwYXR0ZXJuIGZvciBBV1MgU0RLIGNsaWVudHM6XG4gKlxuICogICBgYGB0c1xuICogICBpbXBvcnQgeyBTM0NsaWVudCB9IGZyb20gJ0Bhd3Mtc2RrL2NsaWVudC1zMyc7XG4gKiAgIGltcG9ydCB7IHdpdGhPcmdBd3NDcmVkZW50aWFscyB9IGZyb20gJ0BwaXBlbGluZS1idWlsZGVyL2FwaS1jb3JlJztcbiAqXG4gKiAgIGNvbnN0IG1hbmFnZXIgPSBuZXcgT3JnQXdzQ3JlZGVudGlhbHNNYW5hZ2VyKHsgcmVzb2x2ZXIgfSk7XG4gKlxuICogICBhc3luYyBmdW5jdGlvbiBzM0Zvck9yZyhvcmdJZDogc3RyaW5nKSB7XG4gKiAgICAgcmV0dXJuIHdpdGhPcmdBd3NDcmVkZW50aWFscyhtYW5hZ2VyLCBvcmdJZCwgKGNyZWRzKSA9PlxuICogICAgICAgbmV3IFMzQ2xpZW50KHsgY3JlZGVudGlhbHM6IGNyZWRzLCByZWdpb246ICd1cy13ZXN0LTInIH0pKTtcbiAqICAgfVxuICogICBgYGBcbiAqXG4gKiBUb2RheSdzIGNvZGViYXNlOiBubyBwbGF0Zm9ybS1zaWRlIHNlcnZpY2UgbWFrZXMgQVdTIEFQSSBjYWxscyBzY29wZWQgdG9cbiAqIGEgY3VzdG9tZXIgb3JnIChidWlsZCBydW5uZXJzIHVzZSBidWlsZGtpdGQ7IEFXUyBMYW1iZGEgaGFuZGxlcnMgcnVuIGluXG4gKiBjdXN0b21lciB0ZXJyaXRvcnkgd2l0aCB0aGVpciBvd24gSUFNKS4gVGhpcyBwcmltaXRpdmUgaXMgaW4gcGxhY2UgZm9yXG4gKiB3aGVuIHRoZSBhcmNoaXRlY3R1cmUgZ3Jvd3MgdG8gYWRkIHN1Y2ggY2FsbCBzaXRlcyDigJQgcGVyLW9yZyBTMyBidWNrZXRzLFxuICogcGVyLW9yZyBFQ1IgcmVwb3MsIHBlci1vcmcgQ29kZUJ1aWxkIHByb2plY3RzIOKAlCB3aXRob3V0IGZvcmNpbmcgYW5cbiAqIGluc2VjdXJlIGRlZmF1bHQuXG4gKi9cblxuLyoqIFN0cnVjdHVyYWwgc2hhcGUgb2YgYW4gQVdTIGNyZWRlbnRpYWwuIE1hdGNoZXMgYEBzbWl0aHkvdHlwZXMjQXdzQ3JlZGVudGlhbElkZW50aXR5YFxuICogIGV4YWN0bHkg4oCUIGRlZmluZWQgbG9jYWxseSBzbyBhcGktY29yZSBkb2Vzbid0IG5lZWQgdG8gZGVjbGFyZSBAc21pdGh5L3R5cGVzXG4gKiAgYXMgYSBkaXJlY3QgZGVwIChpdCdzIGEgdHJhbnNpdGl2ZSBvZiBldmVyeSBBV1MgU0RLIGNsaWVudCB3ZSB1c2UpLiAqL1xuZXhwb3J0IGludGVyZmFjZSBBd3NDcmVkZW50aWFsSWRlbnRpdHkge1xuICBhY2Nlc3NLZXlJZDogc3RyaW5nO1xuICBzZWNyZXRBY2Nlc3NLZXk6IHN0cmluZztcbiAgc2Vzc2lvblRva2VuPzogc3RyaW5nO1xuICBleHBpcmF0aW9uPzogRGF0ZTtcbiAgY3JlZGVudGlhbFNjb3BlPzogc3RyaW5nO1xuICBhY2NvdW50SWQ/OiBzdHJpbmc7XG59XG5cbi8qKiBTdGFuZGFyZCBjcmVkZW50aWFsLXByb3ZpZGVyIGNhbGxhYmxlLiBNYXRjaGVzIGBAc21pdGh5L3R5cGVzI0F3c0NyZWRlbnRpYWxJZGVudGl0eVByb3ZpZGVyYC4gKi9cbmV4cG9ydCB0eXBlIEF3c0NyZWRlbnRpYWxJZGVudGl0eVByb3ZpZGVyID0gKCkgPT4gUHJvbWlzZTxBd3NDcmVkZW50aWFsSWRlbnRpdHk+O1xuXG4vKiogT3BlcmF0b3Itc3VwcGxpZWQgcGVyLW9yZyBJQU0gcm9sZSArIHJlZ2lvbiBwaW5uaW5nLiAqL1xuZXhwb3J0IGludGVyZmFjZSBPcmdBd3NDb25maWcge1xuICAvKiogQVJOIG9mIHRoZSByb2xlIHRoaXMgb3JnJ3MgYnVpbGQvcnVudGltZSBjb2RlIHNob3VsZCBhc3N1bWUuICovXG4gIGFzc3VtZVJvbGVBcm46IHN0cmluZztcbiAgLyoqIEV4dGVybmFsIGlkIGJha2VkIGludG8gdGhlIHJvbGUncyB0cnVzdCBwb2xpY3kgKHJlY29tbWVuZGVkKS4gKi9cbiAgZXh0ZXJuYWxJZD86IHN0cmluZztcbiAgLyoqIFJlZ2lvbiB0byB1c2Ugd2hlbiB0aGUgY2FsbGluZyBjb2RlIGRvZXNuJ3QgcGluIG9uZS4gKi9cbiAgcmVnaW9uPzogc3RyaW5nO1xuICAvKiogQXNzdW1lUm9sZSBzZXNzaW9uIGR1cmF0aW9uIChzZWNvbmRzKS4gQVdTIGFsbG93cyA5MDAtNDMyMDA7IHRoZVxuICAgKiAgZWZmZWN0aXZlIGNlaWxpbmcgaXMgdGhlIHJvbGUncyBgTWF4U2Vzc2lvbkR1cmF0aW9uYC4gRGVmYXVsdCAzNjAwLiAqL1xuICBzZXNzaW9uRHVyYXRpb25TZWNvbmRzPzogbnVtYmVyO1xuICAvKiogU2Vzc2lvbiBuYW1lIGVtYmVkZGVkIGluIENsb3VkVHJhaWwuIFVzZWZ1bCBmb3IgaW5jaWRlbnQtcmVzcG9uc2VcbiAgICogIGF0dHJpYnV0aW9uLiBEZWZhdWx0IGBwaXBlbGluZS1idWlsZGVyLTxvcmdJZD5gLiAqL1xuICByb2xlU2Vzc2lvbk5hbWU/OiBzdHJpbmc7XG59XG5cbi8qKiBBc3luYyByZXNvbHZlcjogb3JnSWQg4oaSIGNvbmZpZyB8IG51bGwuIFJldHVybmluZyBudWxsIG1lYW5zIFwidGhpcyBvcmdcbiAqICBoYXMgbm8gcGVyLW9yZyByb2xlOyB1c2UgdGhlIGZhbGxiYWNrIHByb3ZpZGVyLlwiICovXG5leHBvcnQgdHlwZSBPcmdBd3NDb25maWdSZXNvbHZlciA9IChvcmdJZDogc3RyaW5nKSA9PiBQcm9taXNlPE9yZ0F3c0NvbmZpZyB8IG51bGw+O1xuXG4vKiogQ29uc3RydWN0b3Igb3B0aW9ucy4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgT3JnQXdzQ3JlZGVudGlhbHNNYW5hZ2VyT3B0aW9ucyB7XG4gIHJlc29sdmVyOiBPcmdBd3NDb25maWdSZXNvbHZlcjtcbiAgLyoqIFByb3ZpZGVyIHVzZWQgZm9yIG9yZ3Mgd2hvc2UgcmVzb2x2ZXIgcmV0dXJucyBudWxsLiBEZWZhdWx0OiB0aGUgU0RLXG4gICAqICBkZWZhdWx0IGNoYWluIHZpYSBgQGF3cy1zZGsvY3JlZGVudGlhbC1wcm92aWRlcnMjZnJvbU5vZGVQcm92aWRlckNoYWluYC4gKi9cbiAgZmFsbGJhY2s/OiBBd3NDcmVkZW50aWFsSWRlbnRpdHlQcm92aWRlcjtcbiAgLyoqIFJlZ2lvbiBwYXNzZWQgdG8gdGhlIGlubmVyIFNUUyBjbGllbnQgd2hlbiB0aGUgb3JnIGNvbmZpZyBkb2Vzbid0XG4gICAqICBwaW4gb25lLiBEZWZhdWx0OiBgQVdTX1JFR0lPTmAgLyBgQVdTX0RFRkFVTFRfUkVHSU9OYCBlbnYuICovXG4gIHJlZ2lvbj86IHN0cmluZztcbiAgLyoqIFNUUyBlbmRwb2ludCBvdmVycmlkZSAoTG9jYWxTdGFjaywgVlBDIGVuZHBvaW50KS4gRGVmYXVsdDogU0RLIGRlZmF1bHQuICovXG4gIGVuZHBvaW50Pzogc3RyaW5nO1xufVxuXG4vKipcbiAqIFBlci1wcm9jZXNzIG1hbmFnZXIgdGhhdCByZXNvbHZlcyBhbmQgY2FjaGVzIHBlci1vcmcgY3JlZGVudGlhbCBwcm92aWRlcnMuXG4gKiBPbmUgaW5zdGFuY2UgcGVyIHNlcnZpY2U7IHNoYXJlIGl0IGFjcm9zcyBoYW5kbGVycy5cbiAqL1xuZXhwb3J0IGNsYXNzIE9yZ0F3c0NyZWRlbnRpYWxzTWFuYWdlciB7XG4gIHByaXZhdGUgcmVhZG9ubHkgcmVzb2x2ZXI6IE9yZ0F3c0NvbmZpZ1Jlc29sdmVyO1xuICBwcml2YXRlIHJlYWRvbmx5IGZhbGxiYWNrT3ZlcnJpZGU/OiBBd3NDcmVkZW50aWFsSWRlbnRpdHlQcm92aWRlcjtcbiAgcHJpdmF0ZSByZWFkb25seSByZWdpb24/OiBzdHJpbmc7XG4gIHByaXZhdGUgcmVhZG9ubHkgZW5kcG9pbnQ/OiBzdHJpbmc7XG4gIHByaXZhdGUgcmVhZG9ubHkgY2FjaGUgPSBuZXcgTWFwPHN0cmluZywgQXdzQ3JlZGVudGlhbElkZW50aXR5UHJvdmlkZXI+KCk7XG4gIHByaXZhdGUgcmVhZG9ubHkgaW5GbGlnaHQgPSBuZXcgTWFwPHN0cmluZywgUHJvbWlzZTxBd3NDcmVkZW50aWFsSWRlbnRpdHlQcm92aWRlcj4+KCk7XG4gIC8qKiBMYXp5IGRlZmF1bHQgY2hhaW4uIEJ1aWx0IG9uY2UgcGVyIG1hbmFnZXIgc28gd2UgZG9uJ3QgaW1wb3J0IHRoZVxuICAgKiAgY3JlZGVudGlhbC1wcm92aWRlcnMgU0RLIGluIHRlc3QgZW52aXJvbm1lbnRzIHRoYXQgbmV2ZXIgdG91Y2ggdGhlXG4gICAqICBmYWxsYmFjayBwYXRoLiAqL1xuICBwcml2YXRlIGZhbGxiYWNrQ2FjaGU/OiBBd3NDcmVkZW50aWFsSWRlbnRpdHlQcm92aWRlcjtcblxuICBjb25zdHJ1Y3RvcihvcHRzOiBPcmdBd3NDcmVkZW50aWFsc01hbmFnZXJPcHRpb25zKSB7XG4gICAgdGhpcy5yZXNvbHZlciA9IG9wdHMucmVzb2x2ZXI7XG4gICAgdGhpcy5mYWxsYmFja092ZXJyaWRlID0gb3B0cy5mYWxsYmFjaztcbiAgICB0aGlzLnJlZ2lvbiA9IG9wdHMucmVnaW9uID8/IHByb2Nlc3MuZW52LkFXU19SRUdJT04gPz8gcHJvY2Vzcy5lbnYuQVdTX0RFRkFVTFRfUkVHSU9OO1xuICAgIHRoaXMuZW5kcG9pbnQgPSBvcHRzLmVuZHBvaW50ID8/IHByb2Nlc3MuZW52LkFXU19TVFNfRU5EUE9JTlQ7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJuIGFuIEF3c0NyZWRlbnRpYWxJZGVudGl0eVByb3ZpZGVyIHNjb3BlZCB0byBgb3JnSWRgLiBQYXNzIHRoZVxuICAgKiByZXR1cm5lZCB2YWx1ZSBpbnRvIGFueSBTREsgdjMgY2xpZW50J3MgYGNyZWRlbnRpYWxzYCBvcHRpb24uXG4gICAqXG4gICAqIENvbmN1cnJlbnQgZmlyc3QtdG91Y2ggY2FsbGVycyBzaGFyZSBvbmUgcmVzb2x2ZXIgaW52b2NhdGlvbjsgbGF0ZXJcbiAgICogY2FsbHMgaGl0IHRoZSBjYWNoZS4gVGhlIHByb3ZpZGVyIGl0c2VsZiBjYWNoZXMgYW5kIHJlZnJlc2hlc1xuICAgKiBBc3N1bWVSb2xlLWRlcml2ZWQgY3JlZGVudGlhbHMgaW50ZXJuYWxseS5cbiAgICovXG4gIGFzeW5jIGdldENyZWRlbnRpYWxzKG9yZ0lkOiBzdHJpbmcpOiBQcm9taXNlPEF3c0NyZWRlbnRpYWxJZGVudGl0eVByb3ZpZGVyPiB7XG4gICAgaWYgKCFvcmdJZCkgdGhyb3cgbmV3IEVycm9yKCdPcmdBd3NDcmVkZW50aWFsc01hbmFnZXIuZ2V0Q3JlZGVudGlhbHMgcmVxdWlyZXMgYSBub24tZW1wdHkgb3JnSWQnKTtcblxuICAgIGNvbnN0IGNhY2hlZCA9IHRoaXMuY2FjaGUuZ2V0KG9yZ0lkKTtcbiAgICBpZiAoY2FjaGVkKSByZXR1cm4gY2FjaGVkO1xuXG4gICAgbGV0IHBlbmRpbmcgPSB0aGlzLmluRmxpZ2h0LmdldChvcmdJZCk7XG4gICAgaWYgKCFwZW5kaW5nKSB7XG4gICAgICBwZW5kaW5nID0gdGhpcy5yZXNvbHZlQW5kQnVpbGQob3JnSWQpO1xuICAgICAgdGhpcy5pbkZsaWdodC5zZXQob3JnSWQsIHBlbmRpbmcpO1xuICAgICAgdm9pZCBwZW5kaW5nLmZpbmFsbHkoKCkgPT4ge1xuICAgICAgICBpZiAodGhpcy5pbkZsaWdodC5nZXQob3JnSWQpID09PSBwZW5kaW5nKSB0aGlzLmluRmxpZ2h0LmRlbGV0ZShvcmdJZCk7XG4gICAgICB9KTtcbiAgICB9XG4gICAgcmV0dXJuIHBlbmRpbmc7XG4gIH1cblxuICAvKiogRHJvcCB0aGUgY2FjaGVkIHByb3ZpZGVyIGZvciBhbiBvcmcuIENhbGwgYWZ0ZXIgdGhlIG9wZXJhdG9yIHJvdGF0ZXNcbiAgICogIHRoZSByb2xlIEFSTiBvciBleHRlcm5hbCBpZCBzbyB0aGUgbmV4dCByZXF1ZXN0IHJlYnVpbGRzLiAqL1xuICBldmljdChvcmdJZDogc3RyaW5nKTogdm9pZCB7XG4gICAgdGhpcy5jYWNoZS5kZWxldGUob3JnSWQpO1xuICB9XG5cbiAgLyoqIERyb3AgZXZlcnkgY2FjaGVkIHByb3ZpZGVyLiBVc2VmdWwgaW4gdGVzdHM7IHJhcmVseSBpbiBwcm9kdWN0aW9uLiAqL1xuICBldmljdEFsbCgpOiB2b2lkIHtcbiAgICB0aGlzLmNhY2hlLmNsZWFyKCk7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIHJlc29sdmVBbmRCdWlsZChvcmdJZDogc3RyaW5nKTogUHJvbWlzZTxBd3NDcmVkZW50aWFsSWRlbnRpdHlQcm92aWRlcj4ge1xuICAgIGNvbnN0IGNmZyA9IGF3YWl0IHRoaXMucmVzb2x2ZXIob3JnSWQpO1xuICAgIGlmICghY2ZnIHx8ICFjZmcuYXNzdW1lUm9sZUFybikge1xuICAgICAgY29uc3QgZmFsbGJhY2sgPSBhd2FpdCB0aGlzLmdldEZhbGxiYWNrKCk7XG4gICAgICB0aGlzLmNhY2hlLnNldChvcmdJZCwgZmFsbGJhY2spO1xuICAgICAgcmV0dXJuIGZhbGxiYWNrO1xuICAgIH1cblxuICAgIGNvbnN0IHByb3ZpZGVyID0gYXdhaXQgdGhpcy5idWlsZEFzc3VtZVJvbGVQcm92aWRlcihvcmdJZCwgY2ZnKTtcbiAgICB0aGlzLmNhY2hlLnNldChvcmdJZCwgcHJvdmlkZXIpO1xuICAgIHJldHVybiBwcm92aWRlcjtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgZ2V0RmFsbGJhY2soKTogUHJvbWlzZTxBd3NDcmVkZW50aWFsSWRlbnRpdHlQcm92aWRlcj4ge1xuICAgIGlmICh0aGlzLmZhbGxiYWNrT3ZlcnJpZGUpIHJldHVybiB0aGlzLmZhbGxiYWNrT3ZlcnJpZGU7XG4gICAgaWYgKHRoaXMuZmFsbGJhY2tDYWNoZSkgcmV0dXJuIHRoaXMuZmFsbGJhY2tDYWNoZTtcbiAgICAvLyBMYXp5LWltcG9ydCBzbyB0ZXN0IGVudnMgdGhhdCBzdXBwbHkgdGhlaXIgb3duIHJlc29sdmVyL2ZhbGxiYWNrXG4gICAgLy8gZG9uJ3QgbG9hZCB0aGUgY3JlZGVudGlhbC1wcm92aWRlcnMgU0RLLlxuICAgIGNvbnN0IHsgZnJvbU5vZGVQcm92aWRlckNoYWluIH0gPSBhd2FpdCBpbXBvcnQoJ0Bhd3Mtc2RrL2NyZWRlbnRpYWwtcHJvdmlkZXJzJyk7XG4gICAgdGhpcy5mYWxsYmFja0NhY2hlID0gZnJvbU5vZGVQcm92aWRlckNoYWluKCk7XG4gICAgcmV0dXJuIHRoaXMuZmFsbGJhY2tDYWNoZTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgYnVpbGRBc3N1bWVSb2xlUHJvdmlkZXIob3JnSWQ6IHN0cmluZywgY2ZnOiBPcmdBd3NDb25maWcpOiBQcm9taXNlPEF3c0NyZWRlbnRpYWxJZGVudGl0eVByb3ZpZGVyPiB7XG4gICAgLy8gRHluYW1pYyBpbXBvcnQg4oCUIGNyZWRlbnRpYWwtcHJvdmlkZXJzIGlzIGhlYXZ5d2VpZ2h0IGFuZCBzZXJ2aWNlcyB0aGF0XG4gICAgLy8gbmV2ZXIgaGF2ZSBwZXItb3JnIHJvbGVzIGNvbmZpZ3VyZWQgc2hvdWxkbid0IGxvYWQgaXQuXG4gICAgY29uc3QgeyBmcm9tVGVtcG9yYXJ5Q3JlZGVudGlhbHMgfSA9IGF3YWl0IGltcG9ydCgnQGF3cy1zZGsvY3JlZGVudGlhbC1wcm92aWRlcnMnKTtcblxuICAgIGNvbnN0IG1hc3RlckNyZWRlbnRpYWxzID0gdGhpcy5mYWxsYmFja092ZXJyaWRlID8/IChhd2FpdCB0aGlzLmdldEZhbGxiYWNrKCkpO1xuXG4gICAgY29uc3Qgc2Vzc2lvbk5hbWUgPSBjZmcucm9sZVNlc3Npb25OYW1lID8/IGBwaXBlbGluZS1idWlsZGVyLSR7b3JnSWR9YC5zbGljZSgwLCA2NCk7XG4gICAgY29uc3QgcmVnaW9uID0gY2ZnLnJlZ2lvbiA/PyB0aGlzLnJlZ2lvbjtcblxuICAgIHJldHVybiBmcm9tVGVtcG9yYXJ5Q3JlZGVudGlhbHMoe1xuICAgICAgLy8gSW5uZXIgU1RTIGNsaWVudCB1c2VzIHRoZSBzZXJ2aWNlJ3Mgb3duIGNyZWRlbnRpYWxzICh0aGUgZmFsbGJhY2tcbiAgICAgIC8vIGNoYWluKS4gVGhvc2UgY3JlZHMgbmVlZCBgc3RzOkFzc3VtZVJvbGVgIG9uIHRoZSBvcmcncyByb2xlLlxuICAgICAgbWFzdGVyQ3JlZGVudGlhbHMsXG4gICAgICBjbGllbnRDb25maWc6IHtcbiAgICAgICAgcmVnaW9uLFxuICAgICAgICAuLi4odGhpcy5lbmRwb2ludCA/IHsgZW5kcG9pbnQ6IHRoaXMuZW5kcG9pbnQgfSA6IHt9KSxcbiAgICAgICAgLy8gQ2FzdCB0byB0aGUgZXhhY3QgY2xpZW50Q29uZmlnIHR5cGUgZnJvbVRlbXBvcmFyeUNyZWRlbnRpYWxzIGV4cGVjdHMuXG4gICAgICAgIC8vIEBhd3Mtc2RrIHNoaXBzIFNUU0NsaWVudENvbmZpZyBmcm9tIGJvdGggYGNsaWVudC1zdHNgIGFuZCB0aGVcbiAgICAgICAgLy8gYG5lc3RlZC1jbGllbnRzYCBTVFMgc3VibW9kdWxlIGF0IGluZGVwZW5kZW50bHktYnVtcGVkIHZlcnNpb25zLCBzbyBhXG4gICAgICAgIC8vIGB0eXBlb2YgU1RTQ2xpZW50YCBjYXN0IGNhbiByZXNvbHZlIHRvIHRoZSB3cm9uZyBvbmU7IGRlcml2aW5nIGl0IGZyb21cbiAgICAgICAgLy8gdGhlIGZ1bmN0aW9uJ3Mgb3duIFBhcmFtZXRlcnMga2VlcHMgdGhlbSBpbiBsb2Nrc3RlcC5cbiAgICAgIH0gYXMgdW5rbm93biBhcyBQYXJhbWV0ZXJzPHR5cGVvZiBmcm9tVGVtcG9yYXJ5Q3JlZGVudGlhbHM+WzBdWydjbGllbnRDb25maWcnXSxcbiAgICAgIHBhcmFtczoge1xuICAgICAgICBSb2xlQXJuOiBjZmcuYXNzdW1lUm9sZUFybixcbiAgICAgICAgUm9sZVNlc3Npb25OYW1lOiBzZXNzaW9uTmFtZSxcbiAgICAgICAgRHVyYXRpb25TZWNvbmRzOiBjZmcuc2Vzc2lvbkR1cmF0aW9uU2Vjb25kcyA/PyAzNjAwLFxuICAgICAgICAuLi4oY2ZnLmV4dGVybmFsSWQgPyB7IEV4dGVybmFsSWQ6IGNmZy5leHRlcm5hbElkIH0gOiB7fSksXG4gICAgICB9LFxuICAgIH0pO1xuICB9XG59XG5cbi8qKiBDb252ZW5pZW5jZTogZGlyZWN0bHkgcmVzb2x2ZSBjcmVkZW50aWFscyBmb3IgYSBzaW5nbGUgY2FsbC4gVGhlIG1hbmFnZXJcbiAqICBkb2Vzbid0IGNhY2hlIHdoZW4gY2FsbGVkIHRoaXMgd2F5IOKAlCB1c2VmdWwgaW4gQ0xJcyAvIG9uZS1zaG90IHNjcmlwdHMuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gcmVzb2x2ZU9yZ0NyZWRlbnRpYWxzT25jZShcbiAgb3JnSWQ6IHN0cmluZyxcbiAgcmVzb2x2ZXI6IE9yZ0F3c0NvbmZpZ1Jlc29sdmVyLFxuKTogUHJvbWlzZTxBd3NDcmVkZW50aWFsSWRlbnRpdHk+IHtcbiAgY29uc3QgbWFuYWdlciA9IG5ldyBPcmdBd3NDcmVkZW50aWFsc01hbmFnZXIoeyByZXNvbHZlciB9KTtcbiAgY29uc3QgcHJvdmlkZXIgPSBhd2FpdCBtYW5hZ2VyLmdldENyZWRlbnRpYWxzKG9yZ0lkKTtcbiAgcmV0dXJuIHByb3ZpZGVyKCk7XG59XG5cbi8qKlxuICogQWRhcHRlcjogcmVzb2x2ZSBwZXItb3JnIGNyZWRlbnRpYWxzIGFuZCBjb25zdHJ1Y3QgYW4gQVdTIFNESyBjbGllbnRcbiAqIHByZS1ib3VuZCB0byB0aGVtLiBUaGUgZmFjdG9yeSBpcyBhc3luYyBiZWNhdXNlIGNyZWRlbnRpYWwgcmVzb2x1dGlvbiBtYXlcbiAqIG5lZWQgdG8gbWFrZSBhIG5ldHdvcmsgY2FsbCAoZmV0Y2hpbmcgb3JnIGNvbmZpZyArIEFzc3VtZVJvbGUpLiBPbmNlXG4gKiByZXNvbHZlZCwgdGhlIHJldHVybmVkIGNsaWVudCBpcyByZWFkeSBmb3Igbm9ybWFsIFNESyBjYWxsczsgdGhlIHByb3ZpZGVyXG4gKiBpbnNpZGUgcmVmcmVzaGVzIGNyZWRlbnRpYWxzIGF1dG9tYXRpY2FsbHkgYmVmb3JlIHRoZXkgZXhwaXJlLlxuICpcbiAqIFR5cGljYWwgdXNhZ2U6XG4gKiAgIGBgYHRzXG4gKiAgIGNvbnN0IHMzID0gYXdhaXQgd2l0aE9yZ0F3c0NyZWRlbnRpYWxzKG1hbmFnZXIsIG9yZ0lkLCAoY3JlZHMpID0+XG4gKiAgICAgbmV3IFMzQ2xpZW50KHsgY3JlZGVudGlhbHM6IGNyZWRzLCByZWdpb246ICd1cy13ZXN0LTInIH0pKTtcbiAqICAgYXdhaXQgczMuc2VuZChuZXcgTGlzdE9iamVjdHNWMkNvbW1hbmQoeyBCdWNrZXQ6IGJ1Y2tldEZvcihvcmdJZCkgfSkpO1xuICogICBgYGBcbiAqXG4gKiBUaGUgZmFjdG9yeSBpcyBpbnZva2VkIGV4YWN0bHkgb25jZSBwZXIgY2FsbCDigJQgY2FsbGVycyB0aGF0IG5lZWQgYVxuICogbG9uZy1saXZlZCBjbGllbnQgc2hvdWxkIGNhY2hlIHRoZSByZXN1bHQgdGhlbXNlbHZlcyByYXRoZXIgdGhhbiByZWJ1aWxkaW5nXG4gKiBvbiBldmVyeSBvcGVyYXRpb24uIChSZS1yZXNvbHZpbmcgb24gZXZlcnkgb3AgaXMgZmluZSBmb3IgY29sZCBwYXRocyBhbmRcbiAqIGEgd2FzdGVkIGNvdXBsZSBvZiBvYmplY3QgYWxsb2NhdGlvbnMgb24gaG90IHBhdGhzLilcbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHdpdGhPcmdBd3NDcmVkZW50aWFsczxUQ2xpZW50PihcbiAgbWFuYWdlcjogT3JnQXdzQ3JlZGVudGlhbHNNYW5hZ2VyLFxuICBvcmdJZDogc3RyaW5nLFxuICBmYWN0b3J5OiAoY3JlZGVudGlhbHM6IEF3c0NyZWRlbnRpYWxJZGVudGl0eVByb3ZpZGVyKSA9PiBUQ2xpZW50LFxuKTogUHJvbWlzZTxUQ2xpZW50PiB7XG4gIGNvbnN0IGNyZWRlbnRpYWxzID0gYXdhaXQgbWFuYWdlci5nZXRDcmVkZW50aWFscyhvcmdJZCk7XG4gIHJldHVybiBmYWN0b3J5KGNyZWRlbnRpYWxzKTtcbn1cbiJdfQ==
|