@pipeline-builder/pipeline-data 4.3.11 → 4.3.13

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.
Files changed (42) hide show
  1. package/lib/api/managed-toolchain.d.ts +195 -0
  2. package/lib/api/managed-toolchain.js +443 -0
  3. package/lib/api/public-directory.d.ts +4 -15
  4. package/lib/api/public-directory.js +1 -31
  5. package/lib/api/reporting/ingest.js +52 -12
  6. package/lib/api/reporting/stakeholder/compose.d.ts +3 -2
  7. package/lib/api/reporting/stakeholder/compose.js +1 -1
  8. package/lib/api/reporting/stakeholder/period.d.ts +5 -4
  9. package/lib/api/reporting/stakeholder/period.js +1 -1
  10. package/lib/api/reporting/stakeholder/sections.d.ts +4 -4
  11. package/lib/api/reporting/stakeholder/sections.js +1 -1
  12. package/lib/api/reporting/stakeholder/store.d.ts +3 -2
  13. package/lib/api/reporting/stakeholder/store.js +1 -1
  14. package/lib/api/reporting/toolchain-runs.d.ts +156 -0
  15. package/lib/api/reporting/toolchain-runs.js +267 -0
  16. package/lib/api/reporting/types.d.ts +20 -3
  17. package/lib/api/reporting/types.js +1 -1
  18. package/lib/api/support-cases.d.ts +50 -24
  19. package/lib/api/support-cases.js +96 -37
  20. package/lib/api/version-references.d.ts +2 -24
  21. package/lib/api/version-references.js +46 -7
  22. package/lib/core/query-filters.d.ts +6 -6
  23. package/lib/core/query-filters.js +1 -1
  24. package/lib/database/drizzle-schema.d.ts +698 -41
  25. package/lib/database/drizzle-schema.js +11 -1
  26. package/lib/database/index.d.ts +1 -1
  27. package/lib/database/index.js +2 -2
  28. package/lib/database/schema/alert.js +4 -4
  29. package/lib/database/schema/compliance.d.ts +29 -40
  30. package/lib/database/schema/compliance.js +10 -14
  31. package/lib/database/schema/ecosystem.d.ts +72 -0
  32. package/lib/database/schema/ecosystem.js +18 -2
  33. package/lib/database/schema/pipeline.d.ts +19 -0
  34. package/lib/database/schema/pipeline.js +17 -1
  35. package/lib/database/schema/reporting-stakeholder.d.ts +2 -1
  36. package/lib/database/schema/reporting-stakeholder.js +2 -27
  37. package/lib/database/schema/toolchain.d.ts +643 -0
  38. package/lib/database/schema/toolchain.js +102 -0
  39. package/lib/index.d.ts +4 -2
  40. package/lib/index.js +7 -3
  41. package/lib/testing/exports.json +39 -2
  42. package/package.json +2 -2
@@ -0,0 +1,443 @@
1
+ // Copyright 2026 Pipeline Builder Contributors
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ /**
4
+ * THE resolver for the managed toolchain (docs/plans/bootstrap-image-versioning.md
5
+ * §2). `pipeline-bootstrap@V` and `cdk-synth@V` are two SYSTEM-ORG plugin rows
6
+ * that share one release version `V`; every path that can resolve a managed
7
+ * name answers from here and nothing else may:
8
+ *
9
+ * release pin given → that release, if it EXISTS (yanked / deprecated /
10
+ * never-promoted still resolve, with a warning; deleted ⇒ 404)
11
+ * else org default → the NEAREST `org_toolchain_default` walking caller → … → root
12
+ * else canary → the NEAREST `toolchain_rollout` membership, served only
13
+ * while it passes the scan + metadata guards
14
+ * else platform → `toolchain_platform_default`
15
+ * else → 409 TOOLCHAIN_NO_DEFAULT (never "highest version", D11)
16
+ *
17
+ * - Reads are ELEVATED (`runWithTenantContext({ isSuperAdmin: true })`, as
18
+ * `versionReferences` does) and touch SYSTEM-ORG plugin rows only: the owner
19
+ * rank of `pluginResolutionOrderBy` is never consulted, so a same-named row in
20
+ * any other org is never a candidate.
21
+ * - Eligibility (D15) is a SET-time rule ({@link isEligibleRelease}); at resolve
22
+ * time a pin / org default only has to exist.
23
+ * - Both halves always come from ONE release (`TOOLCHAIN_PAIR_MISMATCH` otherwise).
24
+ * - The answer carries `resolvedVia` and nothing about any other org: no
25
+ * rollout membership, no ancestor's settings.
26
+ */
27
+ import { AppError, compareSemver, createLogger, envInt, ErrorCode, fetchParentOrgId, getStatusForErrorCode, isSystemOrgId, MANAGED_TOOLCHAIN, MANAGED_TOOLCHAIN_PLUGINS, MAX_ORG_DEPTH, SYSTEM_ORG_ID, TOOLCHAIN_RELEASE_VERSION_PATTERN, toolchainFromMetadata, toOrgIdString, } from '@pipeline-builder/api-core';
28
+ import { and, eq, inArray, isNull, sql } from 'drizzle-orm';
29
+ import { schema } from '../database/drizzle-schema.js';
30
+ import { runWithTenantContext, withTenantTx } from '../database/tenancy.js';
31
+ const logger = createLogger('managed-toolchain');
32
+ /** A resolver refusal: `code` is TOOLCHAIN_NO_DEFAULT, NOT_FOUND, TOOLCHAIN_PAIR_MISMATCH or VALIDATION_ERROR. */
33
+ export class ManagedToolchainError extends AppError {
34
+ constructor(code, message, details) {
35
+ super(getStatusForErrorCode(code), code, message, details);
36
+ this.name = 'ManagedToolchainError';
37
+ }
38
+ }
39
+ /** Whether `version` is a release version (`MAJOR.MINOR.PATCH`). */
40
+ export function isToolchainReleaseVersion(version) {
41
+ return typeof version === 'string' && TOOLCHAIN_RELEASE_VERSION_PATTERN.test(version);
42
+ }
43
+ const { bootstrap: BOOTSTRAP, synth: SYNTH } = MANAGED_TOOLCHAIN;
44
+ /** The release row and both SYSTEM-ORG halves of `releaseVersion` (deleted rows excluded). */
45
+ export async function loadReleaseHalves(db, releaseVersion) {
46
+ const [releases, rows] = await Promise.all([
47
+ db.select().from(schema.toolchainRelease).where(eq(schema.toolchainRelease.releaseVersion, releaseVersion)),
48
+ db.select().from(schema.plugin).where(and(eq(schema.plugin.orgId, SYSTEM_ORG_ID), inArray(schema.plugin.name, [...MANAGED_TOOLCHAIN_PLUGINS]), eq(schema.plugin.version, releaseVersion), isNull(schema.plugin.deletedAt))),
49
+ ]);
50
+ const plugins = rows;
51
+ return {
52
+ releaseVersion,
53
+ release: releases[0] ?? null,
54
+ bootstrap: plugins.find((p) => p.name === BOOTSTRAP) ?? null,
55
+ synth: plugins.find((p) => p.name === SYNTH) ?? null,
56
+ };
57
+ }
58
+ /** The NEAREST row of `table` (keyed by `org_id`) on `chain` (own org first). */
59
+ async function nearestOnChain(db, table, chain) {
60
+ if (chain.length === 0)
61
+ return null;
62
+ const rows = await db.select({ orgId: table.orgId, releaseVersion: table.releaseVersion })
63
+ .from(table)
64
+ .where(inArray(sql `lower(${table.orgId})`, [...chain]));
65
+ let best = null;
66
+ for (const r of rows) {
67
+ const depth = chain.indexOf(r.orgId.toLowerCase());
68
+ if (depth >= 0 && (!best || depth < best.depth))
69
+ best = { depth, releaseVersion: r.releaseVersion };
70
+ }
71
+ return best;
72
+ }
73
+ async function currentPlatformDefault(db) {
74
+ const rows = await db.select({ releaseVersion: schema.toolchainPlatformDefault.releaseVersion })
75
+ .from(schema.toolchainPlatformDefault).limit(1);
76
+ return rows[0]?.releaseVersion ?? null;
77
+ }
78
+ /** Whether `releaseVersion` has ever been (or is) the platform default. */
79
+ async function wasPlatformDefault(db, releaseVersion) {
80
+ const [history, current] = await Promise.all([
81
+ db.select({ id: schema.toolchainDefaultHistory.id }).from(schema.toolchainDefaultHistory)
82
+ .where(eq(schema.toolchainDefaultHistory.releaseVersion, releaseVersion)).limit(1),
83
+ currentPlatformDefault(db),
84
+ ]);
85
+ return history.length > 0 || current === releaseVersion;
86
+ }
87
+ /** Whether ANY org has an org default or a canary membership (else no walk is needed). */
88
+ async function anyOrgSettings(db) {
89
+ const [defaults, rollout] = await Promise.all([
90
+ db.select({ orgId: schema.orgToolchainDefault.orgId }).from(schema.orgToolchainDefault).limit(1),
91
+ db.select({ orgId: schema.toolchainRollout.orgId }).from(schema.toolchainRollout).limit(1),
92
+ ]);
93
+ return defaults.length > 0 || rollout.length > 0;
94
+ }
95
+ // -----------------------------------------------------------------------------
96
+ // The org chain (caller → … → root)
97
+ // -----------------------------------------------------------------------------
98
+ /**
99
+ * The caller's chain, own org first, lowercased: `[self, parent, …, root]`.
100
+ * The same parent walk as `org-reachability.ts` (platform's
101
+ * `GET /organization/:id/parent`), cycle-safe and capped at `MAX_ORG_DEPTH` like
102
+ * `reporting-retention.ts` — but FAIL-CLOSED: a lookup failure, a cycle or an
103
+ * over-deep chain throws rather than resolving the wrong org's toolchain.
104
+ */
105
+ export async function toolchainOrgChain(orgId, getParent) {
106
+ const self = orgId.toLowerCase();
107
+ const chain = [self];
108
+ if (isSystemOrgId(self))
109
+ return chain;
110
+ let current = self;
111
+ for (let depth = 0; depth < MAX_ORG_DEPTH; depth++) {
112
+ const parent = toOrgIdString(await getParent(current))?.toLowerCase();
113
+ if (!parent || parent === current)
114
+ return chain;
115
+ if (chain.includes(parent)) {
116
+ throw new ManagedToolchainError(ErrorCode.INTERNAL_ERROR, 'The organization hierarchy has a cycle; the toolchain release cannot be resolved.', { orgId: self });
117
+ }
118
+ chain.push(parent);
119
+ current = parent;
120
+ }
121
+ throw new ManagedToolchainError(ErrorCode.INTERNAL_ERROR, `The organization hierarchy is deeper than ${MAX_ORG_DEPTH}; the toolchain release cannot be resolved.`, { orgId: self });
122
+ }
123
+ /** Parent lookups are cached briefly: one synth makes several lookups for the same org. */
124
+ const PARENT_CACHE_TTL_MS = 30_000;
125
+ const PARENT_CACHE_MAX = 5_000;
126
+ const parentCache = new Map();
127
+ async function platformParent(orgId) {
128
+ const hit = parentCache.get(orgId);
129
+ if (hit && Date.now() - hit.at < PARENT_CACHE_TTL_MS)
130
+ return hit.parent;
131
+ // A system-scoped service token; a non-2xx THROWS (fail-closed, see toolchainOrgChain).
132
+ const parent = await fetchParentOrgId(orgId, { authOrgId: SYSTEM_ORG_ID, throwOnHttpError: true, timeout: 5_000 });
133
+ if (parentCache.size >= PARENT_CACHE_MAX)
134
+ parentCache.clear();
135
+ parentCache.set(orgId, { parent, at: Date.now() });
136
+ return parent;
137
+ }
138
+ const productionDeps = {
139
+ read: (fn) => runWithTenantContext({ isSuperAdmin: true }, () => withTenantTx((tx) => fn(tx))),
140
+ getParent: platformParent,
141
+ };
142
+ let defaultDeps = productionDeps;
143
+ /** Test hook: replace the resolver's reads and hierarchy (null restores production). */
144
+ export function setManagedToolchainDepsForTests(deps) {
145
+ defaultDeps = deps ?? productionDeps;
146
+ }
147
+ const isYanked = (p) => p.yankedAt !== null || p.lifecycle === 'yanked';
148
+ const isDeprecated = (p) => p.deprecatedAt !== null || p.lifecycle === 'deprecated';
149
+ /** Whether both halves are present (the release EXISTS). */
150
+ export function releaseExists(h) {
151
+ return h.release !== null && h.bootstrap !== null && h.synth !== null;
152
+ }
153
+ export function releaseLifecycleProblems(h) {
154
+ if (!releaseExists(h))
155
+ return ['missing'];
156
+ const halves = [h.bootstrap, h.synth];
157
+ const out = [];
158
+ if (halves.some((p) => !p.isActive))
159
+ out.push('inactive');
160
+ if (halves.some(isYanked))
161
+ out.push('yanked');
162
+ if (halves.some(isDeprecated))
163
+ out.push('deprecated');
164
+ return out;
165
+ }
166
+ /**
167
+ * The bootstrap half's toolchain metadata (`pipelineManager`, `awsCdk`, …), or
168
+ * null when it carries no complete, valid one. Upload persists it on the row's
169
+ * `metadata` as flat `toolchain.<field>` keys (api-core `toolchainMetadata`).
170
+ */
171
+ export function bootstrapToolchainOf(row) {
172
+ return row ? toolchainFromMetadata(row.metadata) : null;
173
+ }
174
+ /** `PLUGIN_VULN_MAX_FINDINGS` (default 0): the fixable-Critical floor a release must be within. */
175
+ function vulnFloor() {
176
+ return envInt('PLUGIN_VULN_MAX_FINDINGS', 0, { min: 0 });
177
+ }
178
+ /**
179
+ * The §8 candidate guards (pair, scan, metadata) a release fails, as their
180
+ * error codes — empty when it passes. The canary gate and concurrency are the
181
+ * platform-default service's; a canary is served only while this is empty.
182
+ */
183
+ export function toolchainCandidateProblems(h) {
184
+ if (!releaseExists(h) || releaseLifecycleProblems(h).length > 0)
185
+ return [ErrorCode.TOOLCHAIN_GUARD_PAIR_INCOMPLETE];
186
+ const out = [];
187
+ const halves = [h.bootstrap, h.synth];
188
+ if (halves.some((p) => !p.scannedAt))
189
+ out.push(ErrorCode.TOOLCHAIN_GUARD_UNSCANNED);
190
+ else if (halves.some((p) => (p.vulnCriticalFixable ?? 0) > vulnFloor()))
191
+ out.push(ErrorCode.TOOLCHAIN_GUARD_VULN_FLOOR);
192
+ if (!bootstrapToolchainOf(h.bootstrap))
193
+ out.push(ErrorCode.TOOLCHAIN_GUARD_METADATA);
194
+ return out;
195
+ }
196
+ /** Warnings for a release that EXISTS but is no longer (or never was) eligible. */
197
+ function standingWarnings(h, promoted, via) {
198
+ const ref = `Toolchain release ${h.releaseVersion}`;
199
+ const out = [];
200
+ const yanked = [h.bootstrap, h.synth].find(isYanked);
201
+ if (yanked) {
202
+ out.push({
203
+ code: 'TOOLCHAIN_RELEASE_YANKED',
204
+ severity: 'warning',
205
+ message: `${ref} is yanked${yanked.yankReason ? `: ${yanked.yankReason}` : ''}. It resolves only because it is selected exactly; move to a supported release.`,
206
+ });
207
+ }
208
+ const deprecated = [h.bootstrap, h.synth].find(isDeprecated);
209
+ if (deprecated) {
210
+ out.push({
211
+ code: 'TOOLCHAIN_RELEASE_DEPRECATED',
212
+ severity: 'warning',
213
+ message: `${ref} is deprecated${deprecated.deprecationMessage ? `: ${deprecated.deprecationMessage}` : ''}.`,
214
+ });
215
+ }
216
+ if ([h.bootstrap, h.synth].some((p) => !p.isActive)) {
217
+ out.push({ code: 'TOOLCHAIN_RELEASE_INACTIVE', severity: 'warning', message: `${ref} is inactive; move to a supported release.` });
218
+ }
219
+ if (!promoted && (via === 'pin' || via === 'org-default')) {
220
+ out.push({
221
+ code: 'TOOLCHAIN_RELEASE_NOT_PROMOTED',
222
+ severity: 'warning',
223
+ message: `${ref} was never the platform default and is not in a canary for your organization; it resolves only because it is selected exactly.`,
224
+ });
225
+ }
226
+ return out;
227
+ }
228
+ // -----------------------------------------------------------------------------
229
+ // Resolution
230
+ // -----------------------------------------------------------------------------
231
+ function pairOf(h, via) {
232
+ if (!releaseExists(h)) {
233
+ // A default (platform or org) whose halves are gone is a broken invariant
234
+ // (in-use protection counts defaults): refused, never served.
235
+ throw new ManagedToolchainError(ErrorCode.TOOLCHAIN_PAIR_MISMATCH, `Toolchain release ${h.releaseVersion} (${via}) is incomplete; it is never served.`, {
236
+ releaseVersion: h.releaseVersion,
237
+ missing: [...(h.bootstrap ? [] : [BOOTSTRAP]), ...(h.synth ? [] : [SYNTH]), ...(h.release ? [] : ['toolchain_release'])],
238
+ });
239
+ }
240
+ if (h.bootstrap.version !== h.releaseVersion || h.synth.version !== h.releaseVersion) {
241
+ throw new ManagedToolchainError(ErrorCode.TOOLCHAIN_PAIR_MISMATCH, `Toolchain halves disagree (${BOOTSTRAP}@${h.bootstrap.version}, ${SYNTH}@${h.synth.version}); never served.`, {
242
+ releaseVersion: h.releaseVersion,
243
+ });
244
+ }
245
+ return { bootstrap: h.bootstrap, synth: h.synth };
246
+ }
247
+ /** The resolution inside one elevated read, over a known chain. */
248
+ async function resolveOnChain(db, chain, releasePin) {
249
+ const canary = await nearestOnChain(db, schema.toolchainRollout, chain);
250
+ const answer = async (h, via) => {
251
+ const pair = pairOf(h, via);
252
+ const promoted = via === 'pin' || via === 'org-default'
253
+ ? (await wasPlatformDefault(db, h.releaseVersion)) || canary?.releaseVersion === h.releaseVersion
254
+ : true;
255
+ return { releaseVersion: h.releaseVersion, resolvedVia: via, ...pair, warnings: standingWarnings({ ...h, ...pair }, promoted, via) };
256
+ };
257
+ if (releasePin !== undefined) {
258
+ if (!isToolchainReleaseVersion(releasePin)) {
259
+ throw new ManagedToolchainError(ErrorCode.VALIDATION_ERROR, 'releasePin must be a release version (MAJOR.MINOR.PATCH, e.g. 1.4.2).', { releasePin });
260
+ }
261
+ const h = await loadReleaseHalves(db, releasePin);
262
+ if (!releaseExists(h)) {
263
+ throw new ManagedToolchainError(ErrorCode.NOT_FOUND, `Toolchain release ${releasePin} does not exist (or was deleted). Pin an eligible release, or remove toolchain.release to follow your organization's default.`, {
264
+ reason: 'toolchain_release_not_found', releaseVersion: releasePin,
265
+ });
266
+ }
267
+ return answer(h, 'pin');
268
+ }
269
+ const orgDefault = await nearestOnChain(db, schema.orgToolchainDefault, chain);
270
+ if (orgDefault)
271
+ return answer(await loadReleaseHalves(db, orgDefault.releaseVersion), 'org-default');
272
+ if (canary) {
273
+ const h = await loadReleaseHalves(db, canary.releaseVersion);
274
+ const problems = toolchainCandidateProblems(h);
275
+ if (problems.length === 0)
276
+ return answer(h, 'canary');
277
+ // Members fall through to the platform default. Logged, never returned:
278
+ // the answer must not reveal canary membership.
279
+ logger.warn('Canary toolchain release fails its guards; serving the platform default', { releaseVersion: canary.releaseVersion, problems });
280
+ }
281
+ const platform = await currentPlatformDefault(db);
282
+ if (!platform) {
283
+ throw new ManagedToolchainError(ErrorCode.TOOLCHAIN_NO_DEFAULT, 'No platform default toolchain release is set. An operator must set one (init-platform does this on a fresh install).');
284
+ }
285
+ return answer(await loadReleaseHalves(db, platform), 'default');
286
+ }
287
+ /** {@link resolveManagedToolchain} with injected reads and hierarchy (tests). */
288
+ export async function resolveManagedToolchainWith(deps, caller, opts = {}) {
289
+ const self = caller.orgId.toLowerCase();
290
+ // Walk the hierarchy only when some org has a setting (and outside the transaction).
291
+ const walk = await deps.read((db) => anyOrgSettings(db));
292
+ const chain = walk ? await toolchainOrgChain(self, deps.getParent) : [self];
293
+ return deps.read((db) => resolveOnChain(db, chain, opts.releasePin));
294
+ }
295
+ /**
296
+ * Resolve the managed toolchain release for `caller` (see the module doc).
297
+ * Throws {@link ManagedToolchainError}: TOOLCHAIN_NO_DEFAULT (409, no platform
298
+ * default), NOT_FOUND (404, a missing / deleted pin), TOOLCHAIN_PAIR_MISMATCH
299
+ * (500), VALIDATION_ERROR (400, a malformed pin).
300
+ */
301
+ export function resolveManagedToolchain(caller, opts = {}) {
302
+ return resolveManagedToolchainWith(defaultDeps, caller, opts);
303
+ }
304
+ /** {@link isEligibleRelease} with injected reads and hierarchy (tests). */
305
+ export async function isEligibleReleaseWith(deps, orgId, releaseVersion) {
306
+ if (!isToolchainReleaseVersion(releaseVersion))
307
+ return false;
308
+ const self = orgId.toLowerCase();
309
+ const halves = await deps.read((db) => loadReleaseHalves(db, releaseVersion));
310
+ if (releaseLifecycleProblems(halves).length > 0)
311
+ return false;
312
+ if (await deps.read((db) => wasPlatformDefault(db, releaseVersion)))
313
+ return true;
314
+ const walk = await deps.read((db) => anyOrgSettings(db));
315
+ if (!walk)
316
+ return false;
317
+ const chain = await toolchainOrgChain(self, deps.getParent);
318
+ const canary = await deps.read((db) => nearestOnChain(db, schema.toolchainRollout, chain));
319
+ return canary?.releaseVersion === releaseVersion;
320
+ }
321
+ /**
322
+ * D15: whether `orgId` may SET `releaseVersion` as a pipeline pin or its org
323
+ * default — both halves live (active, unyanked, not deprecated) AND either it
324
+ * has been the platform default or it is the caller's canary (nearest
325
+ * membership on its chain).
326
+ */
327
+ export function isEligibleRelease(orgId, releaseVersion) {
328
+ return isEligibleReleaseWith(defaultDeps, orgId, releaseVersion);
329
+ }
330
+ /** {@link readOrgToolchainOverview} with injected reads and hierarchy (tests). */
331
+ export async function readOrgToolchainOverviewWith(deps, orgId) {
332
+ const self = orgId.toLowerCase();
333
+ const walk = await deps.read((db) => anyOrgSettings(db));
334
+ const chain = walk ? await toolchainOrgChain(self, deps.getParent) : [self];
335
+ return deps.read(async (db) => {
336
+ const rows = await db.select().from(schema.orgToolchainDefault)
337
+ .where(inArray(sql `lower(${schema.orgToolchainDefault.orgId})`, chain));
338
+ const depthOf = (r) => chain.indexOf(r.orgId.toLowerCase());
339
+ const ownDefault = rows.find((r) => depthOf(r) === 0) ?? null;
340
+ const nearest = rows.filter((r) => depthOf(r) >= 0).sort((a, b) => depthOf(a) - depthOf(b))[0] ?? null;
341
+ const [canary, platformDefault, resolution] = await Promise.all([
342
+ nearestOnChain(db, schema.toolchainRollout, chain),
343
+ currentPlatformDefault(db),
344
+ resolveOnChain(db, chain),
345
+ ]);
346
+ return {
347
+ chain,
348
+ effective: { releaseVersion: resolution.releaseVersion, resolvedVia: resolution.resolvedVia, warnings: resolution.warnings },
349
+ ownDefault,
350
+ inheritedFrom: !ownDefault && nearest ? { orgId: nearest.orgId, releaseVersion: nearest.releaseVersion } : null,
351
+ canaryRelease: canary?.releaseVersion ?? null,
352
+ platformDefault,
353
+ };
354
+ });
355
+ }
356
+ /**
357
+ * The caller org's toolchain overview (elevated reads, the same chain walk and
358
+ * precedence as {@link resolveManagedToolchain}). Throws what the resolver
359
+ * throws — TOOLCHAIN_NO_DEFAULT (409) when nothing resolves at all.
360
+ */
361
+ export function readOrgToolchainOverview(orgId) {
362
+ return readOrgToolchainOverviewWith(defaultDeps, orgId);
363
+ }
364
+ /** {@link listEligibleReleases} with injected reads and hierarchy (tests). */
365
+ export async function listEligibleReleasesWith(deps, orgId) {
366
+ const self = orgId.toLowerCase();
367
+ const walk = await deps.read((db) => anyOrgSettings(db));
368
+ const chain = walk ? await toolchainOrgChain(self, deps.getParent) : [self];
369
+ return deps.read(async (db) => {
370
+ const [releases, rows, history, platformDefault, canary] = await Promise.all([
371
+ db.select().from(schema.toolchainRelease),
372
+ db.select().from(schema.plugin).where(and(eq(schema.plugin.orgId, SYSTEM_ORG_ID), inArray(schema.plugin.name, [...MANAGED_TOOLCHAIN_PLUGINS]), isNull(schema.plugin.deletedAt))),
373
+ db.select({ releaseVersion: schema.toolchainDefaultHistory.releaseVersion }).from(schema.toolchainDefaultHistory),
374
+ currentPlatformDefault(db),
375
+ nearestOnChain(db, schema.toolchainRollout, chain),
376
+ ]);
377
+ const promoted = new Set(history.map((h) => h.releaseVersion));
378
+ if (platformDefault)
379
+ promoted.add(platformDefault);
380
+ const out = [];
381
+ for (const release of releases) {
382
+ const v = release.releaseVersion;
383
+ const halves = {
384
+ releaseVersion: v,
385
+ release,
386
+ bootstrap: rows.find((p) => p.name === BOOTSTRAP && p.version === v) ?? null,
387
+ synth: rows.find((p) => p.name === SYNTH && p.version === v) ?? null,
388
+ };
389
+ if (!releaseExists(halves) || releaseLifecycleProblems(halves).length > 0)
390
+ continue;
391
+ const isCanary = canary?.releaseVersion === v;
392
+ if (!promoted.has(v) && !isCanary)
393
+ continue;
394
+ out.push({ releaseVersion: v, release, bootstrap: halves.bootstrap, synth: halves.synth, isPlatformDefault: platformDefault === v, isCanary });
395
+ }
396
+ out.sort((a, b) => compareSemver(b.releaseVersion, a.releaseVersion));
397
+ return { platformDefault, releases: out };
398
+ });
399
+ }
400
+ /**
401
+ * Every release `orgId` may SET as a pipeline pin or its org default (D15, the
402
+ * same rule as {@link isEligibleRelease}), newest first. Never another org's
403
+ * data: a canary appears only when it is the caller's own (nearest) membership.
404
+ */
405
+ export function listEligibleReleases(orgId) {
406
+ return listEligibleReleasesWith(defaultDeps, orgId);
407
+ }
408
+ // -----------------------------------------------------------------------------
409
+ // Caller helpers
410
+ // -----------------------------------------------------------------------------
411
+ /**
412
+ * Each resolver refusal code's step-resolution refusal (anything else is
413
+ * `toolchain_unresolved`). `details` rides along except for NO_DEFAULT, which
414
+ * carries none worth showing.
415
+ */
416
+ const REFUSAL_BY_CODE = {
417
+ [ErrorCode.NOT_FOUND]: { code: 'NOT_FOUND', reason: 'toolchain_release_not_found', details: true },
418
+ [ErrorCode.VALIDATION_ERROR]: { code: 'NOT_FOUND', reason: 'toolchain_release_invalid', details: true },
419
+ [ErrorCode.TOOLCHAIN_NO_DEFAULT]: { code: 'PLUGIN_UNAVAILABLE', reason: 'toolchain_no_default', details: false },
420
+ };
421
+ const UNRESOLVED_REFUSAL = { code: 'PLUGIN_UNAVAILABLE', reason: 'toolchain_unresolved', details: true };
422
+ /** The resolver's error as the refusal shape step resolution reports (contract check, declared side, facts). */
423
+ export function managedToolchainRefusal(err) {
424
+ const r = REFUSAL_BY_CODE[err.code] ?? UNRESOLVED_REFUSAL;
425
+ return { code: r.code, reason: r.reason, message: err.message, ...(r.details && err.details ? { details: err.details } : {}) };
426
+ }
427
+ /**
428
+ * Resolve ONE managed half for a step: the plugin row plus the resolution, or
429
+ * the refusal. Any non-resolver error (a database or hierarchy failure)
430
+ * propagates.
431
+ */
432
+ export async function resolveManagedToolchainHalf(caller, name, opts = {}) {
433
+ try {
434
+ const resolution = await resolveManagedToolchain(caller, opts);
435
+ return { plugin: name === BOOTSTRAP ? resolution.bootstrap : resolution.synth, resolution };
436
+ }
437
+ catch (err) {
438
+ if (err instanceof ManagedToolchainError)
439
+ return { refusal: managedToolchainRefusal(err), error: err };
440
+ throw err;
441
+ }
442
+ }
443
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWFuYWdlZC10b29sY2hhaW4uanMiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9hcGkvbWFuYWdlZC10b29sY2hhaW4udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsK0NBQStDO0FBQy9DLHNDQUFzQztBQUV0Qzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0F1Qkc7QUFFSCxPQUFPLEVBQ0wsUUFBUSxFQUFFLGFBQWEsRUFBRSxZQUFZLEVBQUUsTUFBTSxFQUFFLFNBQVMsRUFBRSxnQkFBZ0IsRUFBRSxxQkFBcUIsRUFBRSxhQUFhLEVBQ2hILGlCQUFpQixFQUFFLHlCQUF5QixFQUFFLGFBQWEsRUFBRSxhQUFhLEVBQUUsaUNBQWlDLEVBQUUscUJBQXFCLEVBQUUsYUFBYSxHQUVwSixNQUFNLDRCQUE0QixDQUFDO0FBQ3BDLE9BQU8sRUFBRSxHQUFHLEVBQUUsRUFBRSxFQUFFLE9BQU8sRUFBRSxNQUFNLEVBQUUsR0FBRyxFQUFFLE1BQU0sYUFBYSxDQUFDO0FBRzVELE9BQU8sRUFBRSxNQUFNLEVBQWdFLE1BQU0sK0JBQStCLENBQUM7QUFDckgsT0FBTyxFQUFFLG9CQUFvQixFQUFFLFlBQVksRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBRTVFLE1BQU0sTUFBTSxHQUFHLFlBQVksQ0FBQyxtQkFBbUIsQ0FBQyxDQUFDO0FBc0JqRCxrSEFBa0g7QUFDbEgsTUFBTSxPQUFPLHFCQUFzQixTQUFRLFFBQVE7SUFDakQsWUFBWSxJQUFlLEVBQUUsT0FBZSxFQUFFLE9BQWlDO1FBQzdFLEtBQUssQ0FBQyxxQkFBcUIsQ0FBQyxJQUFJLENBQUMsRUFBRSxJQUFJLEVBQUUsT0FBTyxFQUFFLE9BQU8sQ0FBQyxDQUFDO1FBQzNELElBQUksQ0FBQyxJQUFJLEdBQUcsdUJBQXVCLENBQUM7SUFDdEMsQ0FBQztDQUNGO0FBT0Qsb0VBQW9FO0FBQ3BFLE1BQU0sVUFBVSx5QkFBeUIsQ0FBQyxPQUFnQjtJQUN4RCxPQUFPLE9BQU8sT0FBTyxLQUFLLFFBQVEsSUFBSSxpQ0FB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QixDQUFDLEdBQTBCO0lBQ2hFLE1BQU0sQ0FBQyxHQUFHLGVBQWUsQ0FBQyxHQUFHLENBQUMsSUFBaUIsQ0FBQyxJQUFJLGtCQUFrQixDQUFDO0lBQ3ZFLE9BQU8sRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDLElBQUksRUFBRSxNQUFNLEVBQUUsQ0FBQyxDQUFDLE1BQU0sRUFBRSxPQUFPLEVBQUUsR0FBRyxDQUFDLE9BQU8sRUFBRSxHQUFHLENBQUMsQ0FBQyxDQUFDLE9BQU8sSUFBSSxHQUFHLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxFQUFFLE9BQU8sRUFBRSxHQUFHLENBQUMsT0FBTyxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUM7QUFDakksQ0FBQztBQUVEOzs7O0dBSUc7QUFDSCxNQUFNLENBQUMsS0FBSyxVQUFVLDJCQUEyQixDQUMvQyxNQUE4QixFQUM5QixJQUE0QixFQUM1QixJQUFJLEdBQTRCLEVBQUU7SUFFbEMsSUFBSSxDQUFDO1FBQ0gsTUFBTSxVQUFVLEdBQUcsTUFBTSx1QkFBdUIsQ0FBQyxNQUFNLEVBQUUsSUFBSSxDQUFDLENBQUM7UUFDL0QsT0FBTyxFQUFFLE1BQU0sRUFBRSxJQUFJLEtBQUssU0FBUyxDQUFDLENBQUMsQ0FBQyxVQUFVLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxVQUFVLENBQUMsS0FBSyxFQUFFLFVBQVUsRUFBRSxDQUFDO0lBQzlGLENBQUM7SUFBQyxPQUFPLEdBQUcsRUFBRSxDQUFDO1FBQ2IsSUFBSSxHQUFHLFlBQVkscUJBQXFCO1lBQUUsT0FBTyxFQUFFLE9BQU8sRUFBRSx1QkFBdUIsQ0FBQyxHQUFHLENBQUMsRUFBRSxLQUFLLEVBQUUsR0FBRyxFQUFFLENBQUM7UUFDdkcsTUFBTSxHQUFHLENBQUM7SUFDWixDQUFDO0FBQ0gsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8vIENvcHlyaWdodCAyMDI2IFBpcGVsaW5lIEJ1aWxkZXIgQ29udHJpYnV0b3JzXG4vLyBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQXBhY2hlLTIuMFxuXG4vKipcbiAqIFRIRSByZXNvbHZlciBmb3IgdGhlIG1hbmFnZWQgdG9vbGNoYWluIChkb2NzL3BsYW5zL2Jvb3RzdHJhcC1pbWFnZS12ZXJzaW9uaW5nLm1kXG4gKiDCpzIpLiBgcGlwZWxpbmUtYm9vdHN0cmFwQFZgIGFuZCBgY2RrLXN5bnRoQFZgIGFyZSB0d28gU1lTVEVNLU9SRyBwbHVnaW4gcm93c1xuICogdGhhdCBzaGFyZSBvbmUgcmVsZWFzZSB2ZXJzaW9uIGBWYDsgZXZlcnkgcGF0aCB0aGF0IGNhbiByZXNvbHZlIGEgbWFuYWdlZFxuICogbmFtZSBhbnN3ZXJzIGZyb20gaGVyZSBhbmQgbm90aGluZyBlbHNlIG1heTpcbiAqXG4gKiAgIHJlbGVhc2UgcGluIGdpdmVuIOKGkiB0aGF0IHJlbGVhc2UsIGlmIGl0IEVYSVNUUyAoeWFua2VkIC8gZGVwcmVjYXRlZCAvXG4gKiAgICAgICAgICAgICAgICAgICAgICAgbmV2ZXItcHJvbW90ZWQgc3RpbGwgcmVzb2x2ZSwgd2l0aCBhIHdhcm5pbmc7IGRlbGV0ZWQg4oeSIDQwNClcbiAqICAgZWxzZSBvcmcgZGVmYXVsdCAg4oaSIHRoZSBORUFSRVNUIGBvcmdfdG9vbGNoYWluX2RlZmF1bHRgIHdhbGtpbmcgY2FsbGVyIOKGkiDigKYg4oaSIHJvb3RcbiAqICAgZWxzZSBjYW5hcnkgICAgICAg4oaSIHRoZSBORUFSRVNUIGB0b29sY2hhaW5fcm9sbG91dGAgbWVtYmVyc2hpcCwgc2VydmVkIG9ubHlcbiAqICAgICAgICAgICAgICAgICAgICAgICB3aGlsZSBpdCBwYXNzZXMgdGhlIHNjYW4gKyBtZXRhZGF0YSBndWFyZHNcbiAqICAgZWxzZSBwbGF0Zm9ybSAgICAg4oaSIGB0b29sY2hhaW5fcGxhdGZvcm1fZGVmYXVsdGBcbiAqICAgZWxzZSAgICAgICAgICAgICAg4oaSIDQwOSBUT09MQ0hBSU5fTk9fREVGQVVMVCAobmV2ZXIgXCJoaWdoZXN0IHZlcnNpb25cIiwgRDExKVxuICpcbiAqIC0gUmVhZHMgYXJlIEVMRVZBVEVEIChgcnVuV2l0aFRlbmFudENvbnRleHQoeyBpc1N1cGVyQWRtaW46IHRydWUgfSlgLCBhc1xuICogICBgdmVyc2lvblJlZmVyZW5jZXNgIGRvZXMpIGFuZCB0b3VjaCBTWVNURU0tT1JHIHBsdWdpbiByb3dzIG9ubHk6IHRoZSBvd25lclxuICogICByYW5rIG9mIGBwbHVnaW5SZXNvbHV0aW9uT3JkZXJCeWAgaXMgbmV2ZXIgY29uc3VsdGVkLCBzbyBhIHNhbWUtbmFtZWQgcm93IGluXG4gKiAgIGFueSBvdGhlciBvcmcgaXMgbmV2ZXIgYSBjYW5kaWRhdGUuXG4gKiAtIEVsaWdpYmlsaXR5IChEMTUpIGlzIGEgU0VULXRpbWUgcnVsZSAoe0BsaW5rIGlzRWxpZ2libGVSZWxlYXNlfSk7IGF0IHJlc29sdmVcbiAqICAgdGltZSBhIHBpbiAvIG9yZyBkZWZhdWx0IG9ubHkgaGFzIHRvIGV4aXN0LlxuICogLSBCb3RoIGhhbHZlcyBhbHdheXMgY29tZSBmcm9tIE9ORSByZWxlYXNlIChgVE9PTENIQUlOX1BBSVJfTUlTTUFUQ0hgIG90aGVyd2lzZSkuXG4gKiAtIFRoZSBhbnN3ZXIgY2FycmllcyBgcmVzb2x2ZWRWaWFgIGFuZCBub3RoaW5nIGFib3V0IGFueSBvdGhlciBvcmc6IG5vXG4gKiAgIHJvbGxvdXQgbWVtYmVyc2hpcCwgbm8gYW5jZXN0b3IncyBzZXR0aW5ncy5cbiAqL1xuXG5pbXBvcnQge1xuICBBcHBFcnJvciwgY29tcGFyZVNlbXZlciwgY3JlYXRlTG9nZ2VyLCBlbnZJbnQsIEVycm9yQ29kZSwgZmV0Y2hQYXJlbnRPcmdJZCwgZ2V0U3RhdHVzRm9yRXJyb3JDb2RlLCBpc1N5c3RlbU9yZ0lkLFxuICBNQU5BR0VEX1RPT0xDSEFJTiwgTUFOQUdFRF9UT09MQ0hBSU5fUExVR0lOUywgTUFYX09SR19ERVBUSCwgU1lTVEVNX09SR19JRCwgVE9PTENIQUlOX1JFTEVBU0VfVkVSU0lPTl9QQVRURVJOLCB0b29sY2hhaW5Gcm9tTWV0YWRhdGEsIHRvT3JnSWRTdHJpbmcsXG4gIHR5cGUgR2V0UGFyZW50T3JnSWQsIHR5cGUgTWFuYWdlZFRvb2xjaGFpblBsdWdpbiwgdHlwZSBQbHVnaW5Ub29sY2hhaW4sIHR5cGUgVG9vbGNoYWluUmVzb2x2ZWRWaWEsXG59IGZyb20gJ0BwaXBlbGluZS1idWlsZGVyL2FwaS1jb3JlJztcbmltcG9ydCB7IGFuZCwgZXEsIGluQXJyYXksIGlzTnVsbCwgc3FsIH0gZnJvbSAnZHJpenpsZS1vcm0nO1xuaW1wb3J0IHR5cGUgeyBDcnVkVHggfSBmcm9tICcuL2NydWQtc2VydmljZS5qcyc7XG5pbXBvcnQgdHlwZSB7IFJlc29sdXRpb25SZWZ1c2FsIH0gZnJvbSAnLi9wbHVnaW4tcmVzb2x1dGlvbi5qcyc7XG5pbXBvcnQgeyBzY2hlbWEsIHR5cGUgT3JnVG9vbGNoYWluRGVmYXVsdCwgdHlwZSBQbHVnaW4sIHR5cGUgVG9vbGNoYWluUmVsZWFzZSB9IGZyb20gJy4uL2RhdGFiYXNlL2RyaXp6bGUtc2NoZW1hLmpzJztcbmltcG9ydCB7IHJ1bldpdGhUZW5hbnRDb250ZXh0LCB3aXRoVGVuYW50VHggfSBmcm9tICcuLi9kYXRhYmFzZS90ZW5hbmN5LmpzJztcblxuY29uc3QgbG9nZ2VyID0gY3JlYXRlTG9nZ2VyKCdtYW5hZ2VkLXRvb2xjaGFpbicpO1xuXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuLy8gUHVibGljIHNoYXBlc1xuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuLyoqIEEgbm9uLWZhdGFsIG5vdGUgb24gYSByZXNvbHZlZCByZWxlYXNlIChzeW50aCBwcmludHMgaXQpLiAqL1xuZXhwb3J0IGludGVyZmFjZSBNYW5hZ2VkVG9vbGNoYWluV2FybmluZyB7XG4gIGNvZGU6IHN0cmluZztcbiAgbWVzc2FnZTogc3RyaW5nO1xuICBzZXZlcml0eTogJ2luZm8nIHwgJ3dhcm5pbmcnIHwgJ2Vycm9yJztcbn1cblxuLyoqIE9uZSByZWxlYXNlLCBib3RoIGhhbHZlcy4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgTWFuYWdlZFRvb2xjaGFpblJlc29sdXRpb24ge1xuICByZWxlYXNlVmVyc2lvbjogc3RyaW5nO1xuICByZXNvbHZlZFZpYTogVG9vbGNoYWluUmVzb2x2ZWRWaWE7XG4gIGJvb3RzdHJhcDogUGx1Z2luO1xuICBzeW50aDogUGx1Z2luO1xuICB3YXJuaW5nczogTWFuYWdlZFRvb2xjaGFpbldhcm5pbmdbXTtcbn1cblxuLyoqIEEgcmVzb2x2ZXIgcmVmdXNhbDogYGNvZGVgIGlzIFRPT0xDSEFJTl9OT19ERUZBVUxULCBOT1RfRk9VTkQsIFRPT0xDSEFJTl9QQUlSX01JU01BVENIIG9yIFZBTElEQVRJT05fRVJST1IuICovXG5leHBvcnQgY2xhc3MgTWFuYWdlZFRvb2xjaGFpbkVycm9yIGV4dGVuZHMgQXBwRXJyb3Ige1xuICBjb25zdHJ1Y3Rvcihjb2RlOiBFcnJvckNvZGUsIG1lc3NhZ2U6IHN0cmluZywgZGV0YWlscz86IFJlY29yZDxzdHJpbmcsIHVua25vd24+KSB7XG4gICAgc3VwZXIoZ2V0U3RhdHVzRm9yRXJyb3JDb2RlKGNvZGUpLCBjb2RlLCBtZXNzYWdlLCBkZXRhaWxzKTtcbiAgICB0aGlzLm5hbWUgPSAnTWFuYWdlZFRvb2xjaGFpbkVycm9yJztcbiAgfVxufVxuXG4vKiogVGhlIGNhbGxlciBhIHJlc29sdXRpb24gcnVucyBmb3IuICovXG5leHBvcnQgaW50ZXJmYWNlIE1hbmFnZWRUb29sY2hhaW5DYWxsZXIge1xuICBvcmdJZDogc3RyaW5nO1xufVxuXG4vKiogV2hldGhlciBgdmVyc2lvbmAgaXMgYSByZWxlYXNlIHZlcnNpb24gKGBNQUpPUi5NSU5PUi5QQVRDSGApLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzVG9vbGNoYWluUmVsZWFzZVZlcnNpb24odmVyc2lvbjogdW5rbm93bik6IHZlcnNpb24gaXMgc3RyaW5nIHtcbiAgcmV0dXJuIHR5cGVvZiB2ZXJzaW9uID09PSAnc3RyaW5nJyAmJiBUT09MQ0hBSU5fUkVMRUFTRV9WRVJTSU9OX1BBVFRFUk4udGVzdCh2ZXJzaW9uKTtcbn1cblxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbi8vIERhdGEgYWNjZXNzIChzeXN0ZW0tb3JnIHJvd3MsIGVsZXZhdGVkKVxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuLyoqIFdoYXQgdGhlIHJlc29sdmVyIHJlYWRzIHdpdGg6IGEgZHJpenpsZSB0cmFuc2FjdGlvbiAob3IgYW55IGRyaXp6bGUgZGF0YWJhc2UgaW4gdGVzdHMpLiAqL1xuZXhwb3J0IHR5cGUgVG9vbGNoYWluRGIgPSBQaWNrPENydWRUeCwgJ3NlbGVjdCc+O1xuXG4vKiogSG93IHRoZSByZXNvbHZlciByZWFkcyBhbmQgd2Fsa3MgdGhlIG9yZyB0cmVlIChpbmplY3RhYmxlIGZvciB0ZXN0cykuICovXG5leHBvcnQgaW50ZXJmYWNlIE1hbmFnZWRUb29sY2hhaW5EZXBzIHtcbiAgLyoqIFJ1biBgZm5gIHdpdGggRUxFVkFURUQgcmVhZHMuICovXG4gIHJlYWQ8VD4oZm46IChkYjogVG9vbGNoYWluRGIpID0+IFByb21pc2U8VD4pOiBQcm9taXNlPFQ+O1xuICAvKiogQW4gb3JnJ3MgZGlyZWN0IHBhcmVudCwgb3IgdW5kZWZpbmVkIGZvciBhIHJvb3QuIFRocm93cyB3aGVuIGl0IGNhbid0IHRlbGwuICovXG4gIGdldFBhcmVudDogR2V0UGFyZW50T3JnSWQ7XG59XG5cbi8qKiBCb3RoIGhhbHZlcyBvZiBvbmUgcmVsZWFzZSBhcyBzdG9yZWQsIHdpdGggdGhlIHJlbGVhc2Ugcm93LiAqL1xuZXhwb3J0IGludGVyZmFjZSBSZWxlYXNlSGFsdmVzIHtcbiAgcmVsZWFzZVZlcnNpb246IHN0cmluZztcbiAgcmVsZWFzZTogVG9vbGNoYWluUmVsZWFzZSB8IG51bGw7XG4gIGJvb3RzdHJhcDogUGx1Z2luIHwgbnVsbDtcbiAgc3ludGg6IFBsdWdpbiB8IG51bGw7XG59XG5cbmNvbnN0IHsgYm9vdHN0cmFwOiBCT09UU1RSQVAsIHN5bnRoOiBTWU5USCB9ID0gTUFOQUdFRF9UT09MQ0hBSU47XG5cbi8qKiBUaGUgcmVsZWFzZSByb3cgYW5kIGJvdGggU1lTVEVNLU9SRyBoYWx2ZXMgb2YgYHJlbGVhc2VWZXJzaW9uYCAoZGVsZXRlZCByb3dzIGV4Y2x1ZGVkKS4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBsb2FkUmVsZWFzZUhhbHZlcyhkYjogVG9vbGNoYWluRGIsIHJlbGVhc2VWZXJzaW9uOiBzdHJpbmcpOiBQcm9taXNlPFJlbGVhc2VIYWx2ZXM+IHtcbiAgY29uc3QgW3JlbGVhc2VzLCByb3dzXSA9IGF3YWl0IFByb21pc2UuYWxsKFtcbiAgICBkYi5zZWxlY3QoKS5mcm9tKHNjaGVtYS50b29sY2hhaW5SZWxlYXNlKS53aGVyZShlcShzY2hlbWEudG9vbGNoYWluUmVsZWFzZS5yZWxlYXNlVmVyc2lvbiwgcmVsZWFzZVZlcnNpb24pKSxcbiAgICBkYi5zZWxlY3QoKS5mcm9tKHNjaGVtYS5wbHVnaW4pLndoZXJlKGFuZChcbiAgICAgIGVxKHNjaGVtYS5wbHVnaW4ub3JnSWQsIFNZU1RFTV9PUkdfSUQpLFxuICAgICAgaW5BcnJheShzY2hlbWEucGx1Z2luLm5hbWUsIFsuLi5NQU5BR0VEX1RPT0xDSEFJTl9QTFVHSU5TXSksXG4gICAgICBlcShzY2hlbWEucGx1Z2luLnZlcnNpb24sIHJlbGVhc2VWZXJzaW9uKSxcbiAgICAgIGlzTnVsbChzY2hlbWEucGx1Z2luLmRlbGV0ZWRBdCksXG4gICAgKSksXG4gIF0pO1xuICBjb25zdCBwbHVnaW5zID0gcm93cyBhcyBQbHVnaW5bXTtcbiAgcmV0dXJuIHtcbiAgICByZWxlYXNlVmVyc2lvbixcbiAgICByZWxlYXNlOiAocmVsZWFzZXMgYXMgVG9vbGNoYWluUmVsZWFzZVtdKVswXSA/PyBudWxsLFxuICAgIGJvb3RzdHJhcDogcGx1Z2lucy5maW5kKChwKSA9PiBwLm5hbWUgPT09IEJPT1RTVFJBUCkgPz8gbnVsbCxcbiAgICBzeW50aDogcGx1Z2lucy5maW5kKChwKSA9PiBwLm5hbWUgPT09IFNZTlRIKSA/PyBudWxsLFxuICB9O1xufVxuXG4vKiogQSBzZXR0aW5nIGZvdW5kIG9uIHRoZSBjYWxsZXIncyBjaGFpbjogd2hpY2ggY2hhaW4gaW5kZXgsIGFuZCBpdHMgcmVsZWFzZS4gKi9cbmludGVyZmFjZSBDaGFpblNldHRpbmcgeyBkZXB0aDogbnVtYmVyOyByZWxlYXNlVmVyc2lvbjogc3RyaW5nIH1cblxuLyoqIFRoZSBORUFSRVNUIHJvdyBvZiBgdGFibGVgIChrZXllZCBieSBgb3JnX2lkYCkgb24gYGNoYWluYCAob3duIG9yZyBmaXJzdCkuICovXG5hc3luYyBmdW5jdGlvbiBuZWFyZXN0T25DaGFpbihcbiAgZGI6IFRvb2xjaGFpbkRiLFxuICB0YWJsZTogdHlwZW9mIHNjaGVtYS5vcmdUb29sY2hhaW5EZWZhdWx0IHwgdHlwZW9mIHNjaGVtYS50b29sY2hhaW5Sb2xsb3V0LFxuICBjaGFpbjogcmVhZG9ubHkgc3RyaW5nW10sXG4pOiBQcm9taXNlPENoYWluU2V0dGluZyB8IG51bGw+IHtcbiAgaWYgKGNoYWluLmxlbmd0aCA9PT0gMCkgcmV0dXJuIG51bGw7XG4gIGNvbnN0IHJvd3MgPSBhd2FpdCBkYi5zZWxlY3QoeyBvcmdJZDogdGFibGUub3JnSWQsIHJlbGVhc2VWZXJzaW9uOiB0YWJsZS5yZWxlYXNlVmVyc2lvbiB9KVxuICAgIC5mcm9tKHRhYmxlKVxuICAgIC53aGVyZShpbkFycmF5KHNxbDxzdHJpbmc+YGxvd2VyKCR7dGFibGUub3JnSWR9KWAsIFsuLi5jaGFpbl0pKSBhcyBBcnJheTx7IG9yZ0lkOiBzdHJpbmc7IHJlbGVhc2VWZXJzaW9uOiBzdHJpbmcgfT47XG4gIGxldCBiZXN0OiBDaGFpblNldHRpbmcgfCBudWxsID0gbnVsbDtcbiAgZm9yIChjb25zdCByIG9mIHJvd3MpIHtcbiAgICBjb25zdCBkZXB0aCA9IGNoYWluLmluZGV4T2Yoci5vcmdJZC50b0xvd2VyQ2FzZSgpKTtcbiAgICBpZiAoZGVwdGggPj0gMCAmJiAoIWJlc3QgfHwgZGVwdGggPCBiZXN0LmRlcHRoKSkgYmVzdCA9IHsgZGVwdGgsIHJlbGVhc2VWZXJzaW9uOiByLnJlbGVhc2VWZXJzaW9uIH07XG4gIH1cbiAgcmV0dXJuIGJlc3Q7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGN1cnJlbnRQbGF0Zm9ybURlZmF1bHQoZGI6IFRvb2xjaGFpbkRiKTogUHJvbWlzZTxzdHJpbmcgfCBudWxsPiB7XG4gIGNvbnN0IHJvd3MgPSBhd2FpdCBkYi5zZWxlY3QoeyByZWxlYXNlVmVyc2lvbjogc2NoZW1hLnRvb2xjaGFpblBsYXRmb3JtRGVmYXVsdC5yZWxlYXNlVmVyc2lvbiB9KVxuICAgIC5mcm9tKHNjaGVtYS50b29sY2hhaW5QbGF0Zm9ybURlZmF1bHQpLmxpbWl0KDEpIGFzIEFycmF5PHsgcmVsZWFzZVZlcnNpb246IHN0cmluZyB9PjtcbiAgcmV0dXJuIHJvd3NbMF0/LnJlbGVhc2VWZXJzaW9uID8/IG51bGw7XG59XG5cbi8qKiBXaGV0aGVyIGByZWxlYXNlVmVyc2lvbmAgaGFzIGV2ZXIgYmVlbiAob3IgaXMpIHRoZSBwbGF0Zm9ybSBkZWZhdWx0LiAqL1xuYXN5bmMgZnVuY3Rpb24gd2FzUGxhdGZvcm1EZWZhdWx0KGRiOiBUb29sY2hhaW5EYiwgcmVsZWFzZVZlcnNpb246IHN0cmluZyk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICBjb25zdCBbaGlzdG9yeSwgY3VycmVudF0gPSBhd2FpdCBQcm9taXNlLmFsbChbXG4gICAgZGIuc2VsZWN0KHsgaWQ6IHNjaGVtYS50b29sY2hhaW5EZWZhdWx0SGlzdG9yeS5pZCB9KS5mcm9tKHNjaGVtYS50b29sY2hhaW5EZWZhdWx0SGlzdG9yeSlcbiAgICAgIC53aGVyZShlcShzY2hlbWEudG9vbGNoYWluRGVmYXVsdEhpc3RvcnkucmVsZWFzZVZlcnNpb24sIHJlbGVhc2VWZXJzaW9uKSkubGltaXQoMSksXG4gICAgY3VycmVudFBsYXRmb3JtRGVmYXVsdChkYiksXG4gIF0pO1xuICByZXR1cm4gKGhpc3RvcnkgYXMgdW5rbm93bltdKS5sZW5ndGggPiAwIHx8IGN1cnJlbnQgPT09IHJlbGVhc2VWZXJzaW9uO1xufVxuXG4vKiogV2hldGhlciBBTlkgb3JnIGhhcyBhbiBvcmcgZGVmYXVsdCBvciBhIGNhbmFyeSBtZW1iZXJzaGlwIChlbHNlIG5vIHdhbGsgaXMgbmVlZGVkKS4gKi9cbmFzeW5jIGZ1bmN0aW9uIGFueU9yZ1NldHRpbmdzKGRiOiBUb29sY2hhaW5EYik6IFByb21pc2U8Ym9vbGVhbj4ge1xuICBjb25zdCBbZGVmYXVsdHMsIHJvbGxvdXRdID0gYXdhaXQgUHJvbWlzZS5hbGwoW1xuICAgIGRiLnNlbGVjdCh7IG9yZ0lkOiBzY2hlbWEub3JnVG9vbGNoYWluRGVmYXVsdC5vcmdJZCB9KS5mcm9tKHNjaGVtYS5vcmdUb29sY2hhaW5EZWZhdWx0KS5saW1pdCgxKSxcbiAgICBkYi5zZWxlY3QoeyBvcmdJZDogc2NoZW1hLnRvb2xjaGFpblJvbGxvdXQub3JnSWQgfSkuZnJvbShzY2hlbWEudG9vbGNoYWluUm9sbG91dCkubGltaXQoMSksXG4gIF0pO1xuICByZXR1cm4gKGRlZmF1bHRzIGFzIHVua25vd25bXSkubGVuZ3RoID4gMCB8fCAocm9sbG91dCBhcyB1bmtub3duW10pLmxlbmd0aCA+IDA7XG59XG5cbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4vLyBUaGUgb3JnIGNoYWluIChjYWxsZXIg4oaSIOKApiDihpIgcm9vdClcbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cbi8qKlxuICogVGhlIGNhbGxlcidzIGNoYWluLCBvd24gb3JnIGZpcnN0LCBsb3dlcmNhc2VkOiBgW3NlbGYsIHBhcmVudCwg4oCmLCByb290XWAuXG4gKiBUaGUgc2FtZSBwYXJlbnQgd2FsayBhcyBgb3JnLXJlYWNoYWJpbGl0eS50c2AgKHBsYXRmb3JtJ3NcbiAqIGBHRVQgL29yZ2FuaXphdGlvbi86aWQvcGFyZW50YCksIGN5Y2xlLXNhZmUgYW5kIGNhcHBlZCBhdCBgTUFYX09SR19ERVBUSGAgbGlrZVxuICogYHJlcG9ydGluZy1yZXRlbnRpb24udHNgIOKAlCBidXQgRkFJTC1DTE9TRUQ6IGEgbG9va3VwIGZhaWx1cmUsIGEgY3ljbGUgb3IgYW5cbiAqIG92ZXItZGVlcCBjaGFpbiB0aHJvd3MgcmF0aGVyIHRoYW4gcmVzb2x2aW5nIHRoZSB3cm9uZyBvcmcncyB0b29sY2hhaW4uXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiB0b29sY2hhaW5PcmdDaGFpbihvcmdJZDogc3RyaW5nLCBnZXRQYXJlbnQ6IEdldFBhcmVudE9yZ0lkKTogUHJvbWlzZTxzdHJpbmdbXT4ge1xuICBjb25zdCBzZWxmID0gb3JnSWQudG9Mb3dlckNhc2UoKTtcbiAgY29uc3QgY2hhaW4gPSBbc2VsZl07XG4gIGlmIChpc1N5c3RlbU9yZ0lkKHNlbGYpKSByZXR1cm4gY2hhaW47XG4gIGxldCBjdXJyZW50ID0gc2VsZjtcbiAgZm9yIChsZXQgZGVwdGggPSAwOyBkZXB0aCA8IE1BWF9PUkdfREVQVEg7IGRlcHRoKyspIHtcbiAgICBjb25zdCBwYXJlbnQgPSB0b09yZ0lkU3RyaW5nKGF3YWl0IGdldFBhcmVudChjdXJyZW50KSk/LnRvTG93ZXJDYXNlKCk7XG4gICAgaWYgKCFwYXJlbnQgfHwgcGFyZW50ID09PSBjdXJyZW50KSByZXR1cm4gY2hhaW47XG4gICAgaWYgKGNoYWluLmluY2x1ZGVzKHBhcmVudCkpIHtcbiAgICAgIHRocm93IG5ldyBNYW5hZ2VkVG9vbGNoYWluRXJyb3IoRXJyb3JDb2RlLklOVEVSTkFMX0VSUk9SLCAnVGhlIG9yZ2FuaXphdGlvbiBoaWVyYXJjaHkgaGFzIGEgY3ljbGU7IHRoZSB0b29sY2hhaW4gcmVsZWFzZSBjYW5ub3QgYmUgcmVzb2x2ZWQuJywgeyBvcmdJZDogc2VsZiB9KTtcbiAgICB9XG4gICAgY2hhaW4ucHVzaChwYXJlbnQpO1xuICAgIGN1cnJlbnQgPSBwYXJlbnQ7XG4gIH1cbiAgdGhyb3cgbmV3IE1hbmFnZWRUb29sY2hhaW5FcnJvcihFcnJvckNvZGUuSU5URVJOQUxfRVJST1IsIGBUaGUgb3JnYW5pemF0aW9uIGhpZXJhcmNoeSBpcyBkZWVwZXIgdGhhbiAke01BWF9PUkdfREVQVEh9OyB0aGUgdG9vbGNoYWluIHJlbGVhc2UgY2Fubm90IGJlIHJlc29sdmVkLmAsIHsgb3JnSWQ6IHNlbGYgfSk7XG59XG5cbi8qKiBQYXJlbnQgbG9va3VwcyBhcmUgY2FjaGVkIGJyaWVmbHk6IG9uZSBzeW50aCBtYWtlcyBzZXZlcmFsIGxvb2t1cHMgZm9yIHRoZSBzYW1lIG9yZy4gKi9cbmNvbnN0IFBBUkVOVF9DQUNIRV9UVExfTVMgPSAzMF8wMDA7XG5jb25zdCBQQVJFTlRfQ0FDSEVfTUFYID0gNV8wMDA7XG5jb25zdCBwYXJlbnRDYWNoZSA9IG5ldyBNYXA8c3RyaW5nLCB7IHBhcmVudDogc3RyaW5nIHwgdW5kZWZpbmVkOyBhdDogbnVtYmVyIH0+KCk7XG5cbmFzeW5jIGZ1bmN0aW9uIHBsYXRmb3JtUGFyZW50KG9yZ0lkOiBzdHJpbmcpOiBQcm9taXNlPHN0cmluZyB8IHVuZGVmaW5lZD4ge1xuICBjb25zdCBoaXQgPSBwYXJlbnRDYWNoZS5nZXQob3JnSWQpO1xuICBpZiAoaGl0ICYmIERhdGUubm93KCkgLSBoaXQuYXQgPCBQQVJFTlRfQ0FDSEVfVFRMX01TKSByZXR1cm4gaGl0LnBhcmVudDtcbiAgLy8gQSBzeXN0ZW0tc2NvcGVkIHNlcnZpY2UgdG9rZW47IGEgbm9uLTJ4eCBUSFJPV1MgKGZhaWwtY2xvc2VkLCBzZWUgdG9vbGNoYWluT3JnQ2hhaW4pLlxuICBjb25zdCBwYXJlbnQgPSBhd2FpdCBmZXRjaFBhcmVudE9yZ0lkKG9yZ0lkLCB7IGF1dGhPcmdJZDogU1lTVEVNX09SR19JRCwgdGhyb3dPbkh0dHBFcnJvcjogdHJ1ZSwgdGltZW91dDogNV8wMDAgfSk7XG4gIGlmIChwYXJlbnRDYWNoZS5zaXplID49IFBBUkVOVF9DQUNIRV9NQVgpIHBhcmVudENhY2hlLmNsZWFyKCk7XG4gIHBhcmVudENhY2hlLnNldChvcmdJZCwgeyBwYXJlbnQsIGF0OiBEYXRlLm5vdygpIH0pO1xuICByZXR1cm4gcGFyZW50O1xufVxuXG5jb25zdCBwcm9kdWN0aW9uRGVwczogTWFuYWdlZFRvb2xjaGFpbkRlcHMgPSB7XG4gIHJlYWQ6IChmbikgPT4gcnVuV2l0aFRlbmFudENvbnRleHQoeyBpc1N1cGVyQWRtaW46IHRydWUgfSwgKCkgPT4gd2l0aFRlbmFudFR4KCh0eCkgPT4gZm4odHgpKSksXG4gIGdldFBhcmVudDogcGxhdGZvcm1QYXJlbnQsXG59O1xubGV0IGRlZmF1bHREZXBzOiBNYW5hZ2VkVG9vbGNoYWluRGVwcyA9IHByb2R1Y3Rpb25EZXBzO1xuXG4vKiogVGVzdCBob29rOiByZXBsYWNlIHRoZSByZXNvbHZlcidzIHJlYWRzIGFuZCBoaWVyYXJjaHkgKG51bGwgcmVzdG9yZXMgcHJvZHVjdGlvbikuICovXG5leHBvcnQgZnVuY3Rpb24gc2V0TWFuYWdlZFRvb2xjaGFpbkRlcHNGb3JUZXN0cyhkZXBzOiBNYW5hZ2VkVG9vbGNoYWluRGVwcyB8IG51bGwpOiB2b2lkIHtcbiAgZGVmYXVsdERlcHMgPSBkZXBzID8/IHByb2R1Y3Rpb25EZXBzO1xufVxuXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuLy8gTGlmZWN5Y2xlLCBlbGlnaWJpbGl0eSBhbmQgdGhlIGNhbmFyeSBndWFyZHNcbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cbi8qKiBXaHkgYSBzdG9yZWQgcmVsZWFzZSBpcyBub3QgTElWRSAoZW1wdHkgPSBsaXZlOiBib3RoIGhhbHZlcyBwcmVzZW50LCBhY3RpdmUsIHVueWFua2VkLCBub3QgZGVwcmVjYXRlZCkuICovXG5leHBvcnQgdHlwZSBSZWxlYXNlTGlmZWN5Y2xlUHJvYmxlbSA9ICdtaXNzaW5nJyB8ICdpbmFjdGl2ZScgfCAneWFua2VkJyB8ICdkZXByZWNhdGVkJztcblxuY29uc3QgaXNZYW5rZWQgPSAocDogUGx1Z2luKSA9PiBwLnlhbmtlZEF0ICE9PSBudWxsIHx8IHAubGlmZWN5Y2xlID09PSAneWFua2VkJztcbmNvbnN0IGlzRGVwcmVjYXRlZCA9IChwOiBQbHVnaW4pID0+IHAuZGVwcmVjYXRlZEF0ICE9PSBudWxsIHx8IHAubGlmZWN5Y2xlID09PSAnZGVwcmVjYXRlZCc7XG5cbi8qKiBXaGV0aGVyIGJvdGggaGFsdmVzIGFyZSBwcmVzZW50ICh0aGUgcmVsZWFzZSBFWElTVFMpLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlbGVhc2VFeGlzdHMoaDogUmVsZWFzZUhhbHZlcyk6IGggaXMgUmVsZWFzZUhhbHZlcyAmIHsgYm9vdHN0cmFwOiBQbHVnaW47IHN5bnRoOiBQbHVnaW4gfSB7XG4gIHJldHVybiBoLnJlbGVhc2UgIT09IG51bGwgJiYgaC5ib290c3RyYXAgIT09IG51bGwgJiYgaC5zeW50aCAhPT0gbnVsbDtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHJlbGVhc2VMaWZlY3ljbGVQcm9ibGVtcyhoOiBSZWxlYXNlSGFsdmVzKTogUmVsZWFzZUxpZmVjeWNsZVByb2JsZW1bXSB7XG4gIGlmICghcmVsZWFzZUV4aXN0cyhoKSkgcmV0dXJuIFsnbWlzc2luZyddO1xuICBjb25zdCBoYWx2ZXMgPSBbaC5ib290c3RyYXAsIGguc3ludGhdO1xuICBjb25zdCBvdXQ6IFJlbGVhc2VMaWZlY3ljbGVQcm9ibGVtW10gPSBbXTtcbiAgaWYgKGhhbHZlcy5zb21lKChwKSA9PiAhcC5pc0FjdGl2ZSkpIG91dC5wdXNoKCdpbmFjdGl2ZScpO1xuICBpZiAoaGFsdmVzLnNvbWUoaXNZYW5rZWQpKSBvdXQucHVzaCgneWFua2VkJyk7XG4gIGlmIChoYWx2ZXMuc29tZShpc0RlcHJlY2F0ZWQpKSBvdXQucHVzaCgnZGVwcmVjYXRlZCcpO1xuICByZXR1cm4gb3V0O1xufVxuXG4vKipcbiAqIFRoZSBib290c3RyYXAgaGFsZidzIHRvb2xjaGFpbiBtZXRhZGF0YSAoYHBpcGVsaW5lTWFuYWdlcmAsIGBhd3NDZGtgLCDigKYpLCBvclxuICogbnVsbCB3aGVuIGl0IGNhcnJpZXMgbm8gY29tcGxldGUsIHZhbGlkIG9uZS4gVXBsb2FkIHBlcnNpc3RzIGl0IG9uIHRoZSByb3cnc1xuICogYG1ldGFkYXRhYCBhcyBmbGF0IGB0b29sY2hhaW4uPGZpZWxkPmAga2V5cyAoYXBpLWNvcmUgYHRvb2xjaGFpbk1ldGFkYXRhYCkuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBib290c3RyYXBUb29sY2hhaW5PZihyb3c6IFBsdWdpbiB8IG51bGwgfCB1bmRlZmluZWQpOiBQbHVnaW5Ub29sY2hhaW4gfCBudWxsIHtcbiAgcmV0dXJuIHJvdyA/IHRvb2xjaGFpbkZyb21NZXRhZGF0YShyb3cubWV0YWRhdGEpIDogbnVsbDtcbn1cblxuLyoqIGBQTFVHSU5fVlVMTl9NQVhfRklORElOR1NgIChkZWZhdWx0IDApOiB0aGUgZml4YWJsZS1Dcml0aWNhbCBmbG9vciBhIHJlbGVhc2UgbXVzdCBiZSB3aXRoaW4uICovXG5mdW5jdGlvbiB2dWxuRmxvb3IoKTogbnVtYmVyIHtcbiAgcmV0dXJuIGVudkludCgnUExVR0lOX1ZVTE5fTUFYX0ZJTkRJTkdTJywgMCwgeyBtaW46IDAgfSk7XG59XG5cbi8qKlxuICogVGhlIMKnOCBjYW5kaWRhdGUgZ3VhcmRzIChwYWlyLCBzY2FuLCBtZXRhZGF0YSkgYSByZWxlYXNlIGZhaWxzLCBhcyB0aGVpclxuICogZXJyb3IgY29kZXMg4oCUIGVtcHR5IHdoZW4gaXQgcGFzc2VzLiBUaGUgY2FuYXJ5IGdhdGUgYW5kIGNvbmN1cnJlbmN5IGFyZSB0aGVcbiAqIHBsYXRmb3JtLWRlZmF1bHQgc2VydmljZSdzOyBhIGNhbmFyeSBpcyBzZXJ2ZWQgb25seSB3aGlsZSB0aGlzIGlzIGVtcHR5LlxuICovXG5leHBvcnQgZnVuY3Rpb24gdG9vbGNoYWluQ2FuZGlkYXRlUHJvYmxlbXMoaDogUmVsZWFzZUhhbHZlcyk6IEVycm9yQ29kZVtdIHtcbiAgaWYgKCFyZWxlYXNlRXhpc3RzKGgpIHx8IHJlbGVhc2VMaWZlY3ljbGVQcm9ibGVtcyhoKS5sZW5ndGggPiAwKSByZXR1cm4gW0Vycm9yQ29kZS5UT09MQ0hBSU5fR1VBUkRfUEFJUl9JTkNPTVBMRVRFXTtcbiAgY29uc3Qgb3V0OiBFcnJvckNvZGVbXSA9IFtdO1xuICBjb25zdCBoYWx2ZXMgPSBbaC5ib290c3RyYXAsIGguc3ludGhdO1xuICBpZiAoaGFsdmVzLnNvbWUoKHApID0+ICFwLnNjYW5uZWRBdCkpIG91dC5wdXNoKEVycm9yQ29kZS5UT09MQ0hBSU5fR1VBUkRfVU5TQ0FOTkVEKTtcbiAgZWxzZSBpZiAoaGFsdmVzLnNvbWUoKHApID0+IChwLnZ1bG5Dcml0aWNhbEZpeGFibGUgPz8gMCkgPiB2dWxuRmxvb3IoKSkpIG91dC5wdXNoKEVycm9yQ29kZS5UT09MQ0hBSU5fR1VBUkRfVlVMTl9GTE9PUik7XG4gIGlmICghYm9vdHN0cmFwVG9vbGNoYWluT2YoaC5ib290c3RyYXApKSBvdXQucHVzaChFcnJvckNvZGUuVE9PTENIQUlOX0dVQVJEX01FVEFEQVRBKTtcbiAgcmV0dXJuIG91dDtcbn1cblxuLyoqIFdhcm5pbmdzIGZvciBhIHJlbGVhc2UgdGhhdCBFWElTVFMgYnV0IGlzIG5vIGxvbmdlciAob3IgbmV2ZXIgd2FzKSBlbGlnaWJsZS4gKi9cbmZ1bmN0aW9uIHN0YW5kaW5nV2FybmluZ3MoaDogUmVsZWFzZUhhbHZlcyAmIHsgYm9vdHN0cmFwOiBQbHVnaW47IHN5bnRoOiBQbHVnaW4gfSwgcHJvbW90ZWQ6IGJvb2xlYW4sIHZpYTogVG9vbGNoYWluUmVzb2x2ZWRWaWEpOiBNYW5hZ2VkVG9vbGNoYWluV2FybmluZ1tdIHtcbiAgY29uc3QgcmVmID0gYFRvb2xjaGFpbiByZWxlYXNlICR7aC5yZWxlYXNlVmVyc2lvbn1gO1xuICBjb25zdCBvdXQ6IE1hbmFnZWRUb29sY2hhaW5XYXJuaW5nW10gPSBbXTtcbiAgY29uc3QgeWFua2VkID0gW2guYm9vdHN0cmFwLCBoLnN5bnRoXS5maW5kKGlzWWFua2VkKTtcbiAgaWYgKHlhbmtlZCkge1xuICAgIG91dC5wdXNoKHtcbiAgICAgIGNvZGU6ICdUT09MQ0hBSU5fUkVMRUFTRV9ZQU5LRUQnLFxuICAgICAgc2V2ZXJpdHk6ICd3YXJuaW5nJyxcbiAgICAgIG1lc3NhZ2U6IGAke3JlZn0gaXMgeWFua2VkJHt5YW5rZWQueWFua1JlYXNvbiA/IGA6ICR7eWFua2VkLnlhbmtSZWFzb259YCA6ICcnfS4gSXQgcmVzb2x2ZXMgb25seSBiZWNhdXNlIGl0IGlzIHNlbGVjdGVkIGV4YWN0bHk7IG1vdmUgdG8gYSBzdXBwb3J0ZWQgcmVsZWFzZS5gLFxuICAgIH0pO1xuICB9XG4gIGNvbnN0IGRlcHJlY2F0ZWQgPSBbaC5ib290c3RyYXAsIGguc3ludGhdLmZpbmQoaXNEZXByZWNhdGVkKTtcbiAgaWYgKGRlcHJlY2F0ZWQpIHtcbiAgICBvdXQucHVzaCh7XG4gICAgICBjb2RlOiAnVE9PTENIQUlOX1JFTEVBU0VfREVQUkVDQVRFRCcsXG4gICAgICBzZXZlcml0eTogJ3dhcm5pbmcnLFxuICAgICAgbWVzc2FnZTogYCR7cmVmfSBpcyBkZXByZWNhdGVkJHtkZXByZWNhdGVkLmRlcHJlY2F0aW9uTWVzc2FnZSA/IGA6ICR7ZGVwcmVjYXRlZC5kZXByZWNhdGlvbk1lc3NhZ2V9YCA6ICcnfS5gLFxuICAgIH0pO1xuICB9XG4gIGlmIChbaC5ib290c3RyYXAsIGguc3ludGhdLnNvbWUoKHApID0+ICFwLmlzQWN0aXZlKSkge1xuICAgIG91dC5wdXNoKHsgY29kZTogJ1RPT0xDSEFJTl9SRUxFQVNFX0lOQUNUSVZFJywgc2V2ZXJpdHk6ICd3YXJuaW5nJywgbWVzc2FnZTogYCR7cmVmfSBpcyBpbmFjdGl2ZTsgbW92ZSB0byBhIHN1cHBvcnRlZCByZWxlYXNlLmAgfSk7XG4gIH1cbiAgaWYgKCFwcm9tb3RlZCAmJiAodmlhID09PSAncGluJyB8fCB2aWEgPT09ICdvcmctZGVmYXVsdCcpKSB7XG4gICAgb3V0LnB1c2goe1xuICAgICAgY29kZTogJ1RPT0xDSEFJTl9SRUxFQVNFX05PVF9QUk9NT1RFRCcsXG4gICAgICBzZXZlcml0eTogJ3dhcm5pbmcnLFxuICAgICAgbWVzc2FnZTogYCR7cmVmfSB3YXMgbmV2ZXIgdGhlIHBsYXRmb3JtIGRlZmF1bHQgYW5kIGlzIG5vdCBpbiBhIGNhbmFyeSBmb3IgeW91ciBvcmdhbml6YXRpb247IGl0IHJlc29sdmVzIG9ubHkgYmVjYXVzZSBpdCBpcyBzZWxlY3RlZCBleGFjdGx5LmAsXG4gICAgfSk7XG4gIH1cbiAgcmV0dXJuIG91dDtcbn1cblxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbi8vIFJlc29sdXRpb25cbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cbmZ1bmN0aW9uIHBhaXJPZihoOiBSZWxlYXNlSGFsdmVzLCB2aWE6IFRvb2xjaGFpblJlc29sdmVkVmlhKTogeyBib290c3RyYXA6IFBsdWdpbjsgc3ludGg6IFBsdWdpbiB9IHtcbiAgaWYgKCFyZWxlYXNlRXhpc3RzKGgpKSB7XG4gICAgLy8gQSBkZWZhdWx0IChwbGF0Zm9ybSBvciBvcmcpIHdob3NlIGhhbHZlcyBhcmUgZ29uZSBpcyBhIGJyb2tlbiBpbnZhcmlhbnRcbiAgICAvLyAoaW4tdXNlIHByb3RlY3Rpb24gY291bnRzIGRlZmF1bHRzKTogcmVmdXNlZCwgbmV2ZXIgc2VydmVkLlxuICAgIHRocm93IG5ldyBNYW5hZ2VkVG9vbGNoYWluRXJyb3IoRXJyb3JDb2RlLlRPT0xDSEFJTl9QQUlSX01JU01BVENILCBgVG9vbGNoYWluIHJlbGVhc2UgJHtoLnJlbGVhc2VWZXJzaW9ufSAoJHt2aWF9KSBpcyBpbmNvbXBsZXRlOyBpdCBpcyBuZXZlciBzZXJ2ZWQuYCwge1xuICAgICAgcmVsZWFzZVZlcnNpb246IGgucmVsZWFzZVZlcnNpb24sXG4gICAgICBtaXNzaW5nOiBbLi4uKGguYm9vdHN0cmFwID8gW10gOiBbQk9PVFNUUkFQXSksIC4uLihoLnN5bnRoID8gW10gOiBbU1lOVEhdKSwgLi4uKGgucmVsZWFzZSA/IFtdIDogWyd0b29sY2hhaW5fcmVsZWFzZSddKV0sXG4gICAgfSk7XG4gIH1cbiAgaWYgKGguYm9vdHN0cmFwLnZlcnNpb24gIT09IGgucmVsZWFzZVZlcnNpb24gfHwgaC5zeW50aC52ZXJzaW9uICE9PSBoLnJlbGVhc2VWZXJzaW9uKSB7XG4gICAgdGhyb3cgbmV3IE1hbmFnZWRUb29sY2hhaW5FcnJvcihFcnJvckNvZGUuVE9PTENIQUlOX1BBSVJfTUlTTUFUQ0gsIGBUb29sY2hhaW4gaGFsdmVzIGRpc2FncmVlICgke0JPT1RTVFJBUH1AJHtoLmJvb3RzdHJhcC52ZXJzaW9ufSwgJHtTWU5USH1AJHtoLnN5bnRoLnZlcnNpb259KTsgbmV2ZXIgc2VydmVkLmAsIHtcbiAgICAgIHJlbGVhc2VWZXJzaW9uOiBoLnJlbGVhc2VWZXJzaW9uLFxuICAgIH0pO1xuICB9XG4gIHJldHVybiB7IGJvb3RzdHJhcDogaC5ib290c3RyYXAsIHN5bnRoOiBoLnN5bnRoIH07XG59XG5cbi8qKiBUaGUgcmVzb2x1dGlvbiBpbnNpZGUgb25lIGVsZXZhdGVkIHJlYWQsIG92ZXIgYSBrbm93biBjaGFpbi4gKi9cbmFzeW5jIGZ1bmN0aW9uIHJlc29sdmVPbkNoYWluKGRiOiBUb29sY2hhaW5EYiwgY2hhaW46IHJlYWRvbmx5IHN0cmluZ1tdLCByZWxlYXNlUGluPzogc3RyaW5nKTogUHJvbWlzZTxNYW5hZ2VkVG9vbGNoYWluUmVzb2x1dGlvbj4ge1xuICBjb25zdCBjYW5hcnkgPSBhd2FpdCBuZWFyZXN0T25DaGFpbihkYiwgc2NoZW1hLnRvb2xjaGFpblJvbGxvdXQsIGNoYWluKTtcbiAgY29uc3QgYW5zd2VyID0gYXN5bmMgKGg6IFJlbGVhc2VIYWx2ZXMsIHZpYTogVG9vbGNoYWluUmVzb2x2ZWRWaWEpOiBQcm9taXNlPE1hbmFnZWRUb29sY2hhaW5SZXNvbHV0aW9uPiA9PiB7XG4gICAgY29uc3QgcGFpciA9IHBhaXJPZihoLCB2aWEpO1xuICAgIGNvbnN0IHByb21vdGVkID0gdmlhID09PSAncGluJyB8fCB2aWEgPT09ICdvcmctZGVmYXVsdCdcbiAgICAgID8gKGF3YWl0IHdhc1BsYXRmb3JtRGVmYXVsdChkYiwgaC5yZWxlYXNlVmVyc2lvbikpIHx8IGNhbmFyeT8ucmVsZWFzZVZlcnNpb24gPT09IGgucmVsZWFzZVZlcnNpb25cbiAgICAgIDogdHJ1ZTtcbiAgICByZXR1cm4geyByZWxlYXNlVmVyc2lvbjogaC5yZWxlYXNlVmVyc2lvbiwgcmVzb2x2ZWRWaWE6IHZpYSwgLi4ucGFpciwgd2FybmluZ3M6IHN0YW5kaW5nV2FybmluZ3MoeyAuLi5oLCAuLi5wYWlyIH0sIHByb21vdGVkLCB2aWEpIH07XG4gIH07XG5cbiAgaWYgKHJlbGVhc2VQaW4gIT09IHVuZGVmaW5lZCkge1xuICAgIGlmICghaXNUb29sY2hhaW5SZWxlYXNlVmVyc2lvbihyZWxlYXNlUGluKSkge1xuICAgICAgdGhyb3cgbmV3IE1hbmFnZWRUb29sY2hhaW5FcnJvcihFcnJvckNvZGUuVkFMSURBVElPTl9FUlJPUiwgJ3JlbGVhc2VQaW4gbXVzdCBiZSBhIHJlbGVhc2UgdmVyc2lvbiAoTUFKT1IuTUlOT1IuUEFUQ0gsIGUuZy4gMS40LjIpLicsIHsgcmVsZWFzZVBpbiB9KTtcbiAgICB9XG4gICAgY29uc3QgaCA9IGF3YWl0IGxvYWRSZWxlYXNlSGFsdmVzKGRiLCByZWxlYXNlUGluKTtcbiAgICBpZiAoIXJlbGVhc2VFeGlzdHMoaCkpIHtcbiAgICAgIHRocm93IG5ldyBNYW5hZ2VkVG9vbGNoYWluRXJyb3IoRXJyb3JDb2RlLk5PVF9GT1VORCwgYFRvb2xjaGFpbiByZWxlYXNlICR7cmVsZWFzZVBpbn0gZG9lcyBub3QgZXhpc3QgKG9yIHdhcyBkZWxldGVkKS4gUGluIGFuIGVsaWdpYmxlIHJlbGVhc2UsIG9yIHJlbW92ZSB0b29sY2hhaW4ucmVsZWFzZSB0byBmb2xsb3cgeW91ciBvcmdhbml6YXRpb24ncyBkZWZhdWx0LmAsIHtcbiAgICAgICAgcmVhc29uOiAndG9vbGNoYWluX3JlbGVhc2Vfbm90X2ZvdW5kJywgcmVsZWFzZVZlcnNpb246IHJlbGVhc2VQaW4sXG4gICAgICB9KTtcbiAgICB9XG4gICAgcmV0dXJuIGFuc3dlcihoLCAncGluJyk7XG4gIH1cblxuICBjb25zdCBvcmdEZWZhdWx0ID0gYXdhaXQgbmVhcmVzdE9uQ2hhaW4oZGIsIHNjaGVtYS5vcmdUb29sY2hhaW5EZWZhdWx0LCBjaGFpbik7XG4gIGlmIChvcmdEZWZhdWx0KSByZXR1cm4gYW5zd2VyKGF3YWl0IGxvYWRSZWxlYXNlSGFsdmVzKGRiLCBvcmdEZWZhdWx0LnJlbGVhc2VWZXJzaW9uKSwgJ29yZy1kZWZhdWx0Jyk7XG5cbiAgaWYgKGNhbmFyeSkge1xuICAgIGNvbnN0IGggPSBhd2FpdCBsb2FkUmVsZWFzZUhhbHZlcyhkYiwgY2FuYXJ5LnJlbGVhc2VWZXJzaW9uKTtcbiAgICBjb25zdCBwcm9ibGVtcyA9IHRvb2xjaGFpbkNhbmRpZGF0ZVByb2JsZW1zKGgpO1xuICAgIGlmIChwcm9ibGVtcy5sZW5ndGggPT09IDApIHJldHVybiBhbnN3ZXIoaCwgJ2NhbmFyeScpO1xuICAgIC8vIE1lbWJlcnMgZmFsbCB0aHJvdWdoIHRvIHRoZSBwbGF0Zm9ybSBkZWZhdWx0LiBMb2dnZWQsIG5ldmVyIHJldHVybmVkOlxuICAgIC8vIHRoZSBhbnN3ZXIgbXVzdCBub3QgcmV2ZWFsIGNhbmFyeSBtZW1iZXJzaGlwLlxuICAgIGxvZ2dlci53YXJuKCdDYW5hcnkgdG9vbGNoYWluIHJlbGVhc2UgZmFpbHMgaXRzIGd1YXJkczsgc2VydmluZyB0aGUgcGxhdGZvcm0gZGVmYXVsdCcsIHsgcmVsZWFzZVZlcnNpb246IGNhbmFyeS5yZWxlYXNlVmVyc2lvbiwgcHJvYmxlbXMgfSk7XG4gIH1cblxuICBjb25zdCBwbGF0Zm9ybSA9IGF3YWl0IGN1cnJlbnRQbGF0Zm9ybURlZmF1bHQoZGIpO1xuICBpZiAoIXBsYXRmb3JtKSB7XG4gICAgdGhyb3cgbmV3IE1hbmFnZWRUb29sY2hhaW5FcnJvcihFcnJvckNvZGUuVE9PTENIQUlOX05PX0RFRkFVTFQsICdObyBwbGF0Zm9ybSBkZWZhdWx0IHRvb2xjaGFpbiByZWxlYXNlIGlzIHNldC4gQW4gb3BlcmF0b3IgbXVzdCBzZXQgb25lIChpbml0LXBsYXRmb3JtIGRvZXMgdGhpcyBvbiBhIGZyZXNoIGluc3RhbGwpLicpO1xuICB9XG4gIHJldHVybiBhbnN3ZXIoYXdhaXQgbG9hZFJlbGVhc2VIYWx2ZXMoZGIsIHBsYXRmb3JtKSwgJ2RlZmF1bHQnKTtcbn1cblxuLyoqIHtAbGluayByZXNvbHZlTWFuYWdlZFRvb2xjaGFpbn0gd2l0aCBpbmplY3RlZCByZWFkcyBhbmQgaGllcmFyY2h5ICh0ZXN0cykuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gcmVzb2x2ZU1hbmFnZWRUb29sY2hhaW5XaXRoKFxuICBkZXBzOiBNYW5hZ2VkVG9vbGNoYWluRGVwcyxcbiAgY2FsbGVyOiBNYW5hZ2VkVG9vbGNoYWluQ2FsbGVyLFxuICBvcHRzOiB7IHJlbGVhc2VQaW4/OiBzdHJpbmcgfSA9IHt9LFxuKTogUHJvbWlzZTxNYW5hZ2VkVG9vbGNoYWluUmVzb2x1dGlvbj4ge1xuICBjb25zdCBzZWxmID0gY2FsbGVyLm9yZ0lkLnRvTG93ZXJDYXNlKCk7XG4gIC8vIFdhbGsgdGhlIGhpZXJhcmNoeSBvbmx5IHdoZW4gc29tZSBvcmcgaGFzIGEgc2V0dGluZyAoYW5kIG91dHNpZGUgdGhlIHRyYW5zYWN0aW9uKS5cbiAgY29uc3Qgd2FsayA9IGF3YWl0IGRlcHMucmVhZCgoZGIpID0+IGFueU9yZ1NldHRpbmdzKGRiKSk7XG4gIGNvbnN0IGNoYWluID0gd2FsayA/IGF3YWl0IHRvb2xjaGFpbk9yZ0NoYWluKHNlbGYsIGRlcHMuZ2V0UGFyZW50KSA6IFtzZWxmXTtcbiAgcmV0dXJuIGRlcHMucmVhZCgoZGIpID0+IHJlc29sdmVPbkNoYWluKGRiLCBjaGFpbiwgb3B0cy5yZWxlYXNlUGluKSk7XG59XG5cbi8qKlxuICogUmVzb2x2ZSB0aGUgbWFuYWdlZCB0b29sY2hhaW4gcmVsZWFzZSBmb3IgYGNhbGxlcmAgKHNlZSB0aGUgbW9kdWxlIGRvYykuXG4gKiBUaHJvd3Mge0BsaW5rIE1hbmFnZWRUb29sY2hhaW5FcnJvcn06IFRPT0xDSEFJTl9OT19ERUZBVUxUICg0MDksIG5vIHBsYXRmb3JtXG4gKiBkZWZhdWx0KSwgTk9UX0ZPVU5EICg0MDQsIGEgbWlzc2luZyAvIGRlbGV0ZWQgcGluKSwgVE9PTENIQUlOX1BBSVJfTUlTTUFUQ0hcbiAqICg1MDApLCBWQUxJREFUSU9OX0VSUk9SICg0MDAsIGEgbWFsZm9ybWVkIHBpbikuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZXNvbHZlTWFuYWdlZFRvb2xjaGFpbihjYWxsZXI6IE1hbmFnZWRUb29sY2hhaW5DYWxsZXIsIG9wdHM6IHsgcmVsZWFzZVBpbj86IHN0cmluZyB9ID0ge30pOiBQcm9taXNlPE1hbmFnZWRUb29sY2hhaW5SZXNvbHV0aW9uPiB7XG4gIHJldHVybiByZXNvbHZlTWFuYWdlZFRvb2xjaGFpbldpdGgoZGVmYXVsdERlcHMsIGNhbGxlciwgb3B0cyk7XG59XG5cbi8qKiB7QGxpbmsgaXNFbGlnaWJsZVJlbGVhc2V9IHdpdGggaW5qZWN0ZWQgcmVhZHMgYW5kIGhpZXJhcmNoeSAodGVzdHMpLiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGlzRWxpZ2libGVSZWxlYXNlV2l0aChkZXBzOiBNYW5hZ2VkVG9vbGNoYWluRGVwcywgb3JnSWQ6IHN0cmluZywgcmVsZWFzZVZlcnNpb246IHN0cmluZyk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICBpZiAoIWlzVG9vbGNoYWluUmVsZWFzZVZlcnNpb24ocmVsZWFzZVZlcnNpb24pKSByZXR1cm4gZmFsc2U7XG4gIGNvbnN0IHNlbGYgPSBvcmdJZC50b0xvd2VyQ2FzZSgpO1xuICBjb25zdCBoYWx2ZXMgPSBhd2FpdCBkZXBzLnJlYWQoKGRiKSA9PiBsb2FkUmVsZWFzZUhhbHZlcyhkYiwgcmVsZWFzZVZlcnNpb24pKTtcbiAgaWYgKHJlbGVhc2VMaWZlY3ljbGVQcm9ibGVtcyhoYWx2ZXMpLmxlbmd0aCA+IDApIHJldHVybiBmYWxzZTtcbiAgaWYgKGF3YWl0IGRlcHMucmVhZCgoZGIpID0+IHdhc1BsYXRmb3JtRGVmYXVsdChkYiwgcmVsZWFzZVZlcnNpb24pKSkgcmV0dXJuIHRydWU7XG4gIGNvbnN0IHdhbGsgPSBhd2FpdCBkZXBzLnJlYWQoKGRiKSA9PiBhbnlPcmdTZXR0aW5ncyhkYikpO1xuICBpZiAoIXdhbGspIHJldHVybiBmYWxzZTtcbiAgY29uc3QgY2hhaW4gPSBhd2FpdCB0b29sY2hhaW5PcmdDaGFpbihzZWxmLCBkZXBzLmdldFBhcmVudCk7XG4gIGNvbnN0IGNhbmFyeSA9IGF3YWl0IGRlcHMucmVhZCgoZGIpID0+IG5lYXJlc3RPbkNoYWluKGRiLCBzY2hlbWEudG9vbGNoYWluUm9sbG91dCwgY2hhaW4pKTtcbiAgcmV0dXJuIGNhbmFyeT8ucmVsZWFzZVZlcnNpb24gPT09IHJlbGVhc2VWZXJzaW9uO1xufVxuXG4vKipcbiAqIEQxNTogd2hldGhlciBgb3JnSWRgIG1heSBTRVQgYHJlbGVhc2VWZXJzaW9uYCBhcyBhIHBpcGVsaW5lIHBpbiBvciBpdHMgb3JnXG4gKiBkZWZhdWx0IOKAlCBib3RoIGhhbHZlcyBsaXZlIChhY3RpdmUsIHVueWFua2VkLCBub3QgZGVwcmVjYXRlZCkgQU5EIGVpdGhlciBpdFxuICogaGFzIGJlZW4gdGhlIHBsYXRmb3JtIGRlZmF1bHQgb3IgaXQgaXMgdGhlIGNhbGxlcidzIGNhbmFyeSAobmVhcmVzdFxuICogbWVtYmVyc2hpcCBvbiBpdHMgY2hhaW4pLlxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNFbGlnaWJsZVJlbGVhc2Uob3JnSWQ6IHN0cmluZywgcmVsZWFzZVZlcnNpb246IHN0cmluZyk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICByZXR1cm4gaXNFbGlnaWJsZVJlbGVhc2VXaXRoKGRlZmF1bHREZXBzLCBvcmdJZCwgcmVsZWFzZVZlcnNpb24pO1xufVxuXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuLy8gVGhlIG9yZydzIG93biBwaWN0dXJlOiB0aGUgb3JnLWRlZmF1bHQgcGFuZWwgYW5kIHRoZSBlbGlnaWJsZS1yZWxlYXNlIGxpc3Rcbi8vIChkb2NzL3BsYW5zL2Jvb3RzdHJhcC1pbWFnZS12ZXJzaW9uaW5nLm1kIMKnNSwgUGhhc2UgNCwgRDE1KVxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuLyoqXG4gKiBXaGF0IHRoZSBvcmctZGVmYXVsdCBwYW5lbCBzaG93cyBhIGNhbGxlciBhYm91dCBJVFMgT1dOIG9yZzogbmV2ZXIgYW5vdGhlclxuICogb3JnJ3MgY2hvaWNlLCBhbmQgb2YgdGhlIGFuY2VzdG9ycyBvbmx5IHdoaWNoIG9uZSdzIGRlZmF1bHQgYXBwbGllcy5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBPcmdUb29sY2hhaW5PdmVydmlldyB7XG4gIC8qKiBUaGUgY2FsbGVyJ3MgY2hhaW4sIG93biBvcmcgZmlyc3QgKGxvd2VyY2FzZWQpLiAqL1xuICBjaGFpbjogc3RyaW5nW107XG4gIC8qKiBXaGF0IHRoZSBvcmcncyBVTlBJTk5FRCBwaXBlbGluZXMgcmVzb2x2ZSB0byBub3cuICovXG4gIGVmZmVjdGl2ZTogeyByZWxlYXNlVmVyc2lvbjogc3RyaW5nOyByZXNvbHZlZFZpYTogVG9vbGNoYWluUmVzb2x2ZWRWaWE7IHdhcm5pbmdzOiBNYW5hZ2VkVG9vbGNoYWluV2FybmluZ1tdIH07XG4gIC8qKiBUaGUgY2FsbGVyIG9yZydzIG93biBgb3JnX3Rvb2xjaGFpbl9kZWZhdWx0YCByb3csIGlmIGl0IHNldCBvbmUuICovXG4gIG93bkRlZmF1bHQ6IE9yZ1Rvb2xjaGFpbkRlZmF1bHQgfCBudWxsO1xuICAvKiogVGhlIGFuY2VzdG9yIHdob3NlIG9yZyBkZWZhdWx0IGFwcGxpZXMsIHdoZW4gdGhlIG9yZyBzZXQgbm9uZSBvZiBpdHMgb3duLiAqL1xuICBpbmhlcml0ZWRGcm9tOiB7IG9yZ0lkOiBzdHJpbmc7IHJlbGVhc2VWZXJzaW9uOiBzdHJpbmcgfSB8IG51bGw7XG4gIC8qKiBUaGUgY2FsbGVyJ3MgY2FuYXJ5IHJlbGVhc2UgKGl0cyBORUFSRVNUIG1lbWJlcnNoaXAgb24gdGhlIGNoYWluKSwgb3IgbnVsbC4gKi9cbiAgY2FuYXJ5UmVsZWFzZTogc3RyaW5nIHwgbnVsbDtcbiAgcGxhdGZvcm1EZWZhdWx0OiBzdHJpbmcgfCBudWxsO1xufVxuXG4vKioge0BsaW5rIHJlYWRPcmdUb29sY2hhaW5PdmVydmlld30gd2l0aCBpbmplY3RlZCByZWFkcyBhbmQgaGllcmFyY2h5ICh0ZXN0cykuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gcmVhZE9yZ1Rvb2xjaGFpbk92ZXJ2aWV3V2l0aChkZXBzOiBNYW5hZ2VkVG9vbGNoYWluRGVwcywgb3JnSWQ6IHN0cmluZyk6IFByb21pc2U8T3JnVG9vbGNoYWluT3ZlcnZpZXc+IHtcbiAgY29uc3Qgc2VsZiA9IG9yZ0lkLnRvTG93ZXJDYXNlKCk7XG4gIGNvbnN0IHdhbGsgPSBhd2FpdCBkZXBzLnJlYWQoKGRiKSA9PiBhbnlPcmdTZXR0aW5ncyhkYikpO1xuICBjb25zdCBjaGFpbiA9IHdhbGsgPyBhd2FpdCB0b29sY2hhaW5PcmdDaGFpbihzZWxmLCBkZXBzLmdldFBhcmVudCkgOiBbc2VsZl07XG4gIHJldHVybiBkZXBzLnJlYWQoYXN5bmMgKGRiKSA9PiB7XG4gICAgY29uc3Qgcm93cyA9IGF3YWl0IGRiLnNlbGVjdCgpLmZyb20oc2NoZW1hLm9yZ1Rvb2xjaGFpbkRlZmF1bHQpXG4gICAgICAud2hlcmUoaW5BcnJheShzcWw8c3RyaW5nPmBsb3dlcigke3NjaGVtYS5vcmdUb29sY2hhaW5EZWZhdWx0Lm9yZ0lkfSlgLCBjaGFpbikpIGFzIE9yZ1Rvb2xjaGFpbkRlZmF1bHRbXTtcbiAgICBjb25zdCBkZXB0aE9mID0gKHI6IE9yZ1Rvb2xjaGFpbkRlZmF1bHQpID0+IGNoYWluLmluZGV4T2Yoci5vcmdJZC50b0xvd2VyQ2FzZSgpKTtcbiAgICBjb25zdCBvd25EZWZhdWx0ID0gcm93cy5maW5kKChyKSA9PiBkZXB0aE9mKHIpID09PSAwKSA/PyBudWxsO1xuICAgIGNvbnN0IG5lYXJlc3QgPSByb3dzLmZpbHRlcigocikgPT4gZGVwdGhPZihyKSA+PSAwKS5zb3J0KChhLCBiKSA9PiBkZXB0aE9mKGEpIC0gZGVwdGhPZihiKSlbMF0gPz8gbnVsbDtcbiAgICBjb25zdCBbY2FuYXJ5LCBwbGF0Zm9ybURlZmF1bHQsIHJlc29sdXRpb25dID0gYXdhaXQgUHJvbWlzZS5hbGwoW1xuICAgICAgbmVhcmVzdE9uQ2hhaW4oZGIsIHNjaGVtYS50b29sY2hhaW5Sb2xsb3V0LCBjaGFpbiksXG4gICAgICBjdXJyZW50UGxhdGZvcm1EZWZhdWx0KGRiKSxcbiAgICAgIHJlc29sdmVPbkNoYWluKGRiLCBjaGFpbiksXG4gICAgXSk7XG4gICAgcmV0dXJuIHtcbiAgICAgIGNoYWluLFxuICAgICAgZWZmZWN0aXZlOiB7IHJlbGVhc2VWZXJzaW9uOiByZXNvbHV0aW9uLnJlbGVhc2VWZXJzaW9uLCByZXNvbHZlZFZpYTogcmVzb2x1dGlvbi5yZXNvbHZlZFZpYSwgd2FybmluZ3M6IHJlc29sdXRpb24ud2FybmluZ3MgfSxcbiAgICAgIG93bkRlZmF1bHQsXG4gICAgICBpbmhlcml0ZWRGcm9tOiAhb3duRGVmYXVsdCAmJiBuZWFyZXN0ID8geyBvcmdJZDogbmVhcmVzdC5vcmdJZCwgcmVsZWFzZVZlcnNpb246IG5lYXJlc3QucmVsZWFzZVZlcnNpb24gfSA6IG51bGwsXG4gICAgICBjYW5hcnlSZWxlYXNlOiBjYW5hcnk/LnJlbGVhc2VWZXJzaW9uID8/IG51bGwsXG4gICAgICBwbGF0Zm9ybURlZmF1bHQsXG4gICAgfTtcbiAgfSk7XG59XG5cbi8qKlxuICogVGhlIGNhbGxlciBvcmcncyB0b29sY2hhaW4gb3ZlcnZpZXcgKGVsZXZhdGVkIHJlYWRzLCB0aGUgc2FtZSBjaGFpbiB3YWxrIGFuZFxuICogcHJlY2VkZW5jZSBhcyB7QGxpbmsgcmVzb2x2ZU1hbmFnZWRUb29sY2hhaW59KS4gVGhyb3dzIHdoYXQgdGhlIHJlc29sdmVyXG4gKiB0aHJvd3Mg4oCUIFRPT0xDSEFJTl9OT19ERUZBVUxUICg0MDkpIHdoZW4gbm90aGluZyByZXNvbHZlcyBhdCBhbGwuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZWFkT3JnVG9vbGNoYWluT3ZlcnZpZXcob3JnSWQ6IHN0cmluZyk6IFByb21pc2U8T3JnVG9vbGNoYWluT3ZlcnZpZXc+IHtcbiAgcmV0dXJuIHJlYWRPcmdUb29sY2hhaW5PdmVydmlld1dpdGgoZGVmYXVsdERlcHMsIG9yZ0lkKTtcbn1cblxuLyoqIE9uZSByZWxlYXNlIHRoZSBjYWxsZXIgbWF5IHBpbiBvciBzZXQgKEQxNSksIHdpdGggd2hhdCB0aGUgc2VsZWN0b3JzIHNob3cuICovXG5leHBvcnQgaW50ZXJmYWNlIEVsaWdpYmxlVG9vbGNoYWluUmVsZWFzZSB7XG4gIHJlbGVhc2VWZXJzaW9uOiBzdHJpbmc7XG4gIHJlbGVhc2U6IFRvb2xjaGFpblJlbGVhc2U7XG4gIGJvb3RzdHJhcDogUGx1Z2luO1xuICBzeW50aDogUGx1Z2luO1xuICAvKiogVEhFIHBsYXRmb3JtIGRlZmF1bHQgbm93LiAqL1xuICBpc1BsYXRmb3JtRGVmYXVsdDogYm9vbGVhbjtcbiAgLyoqIFRoZSBjYWxsZXIncyBjYW5hcnkgcmVsZWFzZSAobmVhcmVzdCBtZW1iZXJzaGlwKS4gKi9cbiAgaXNDYW5hcnk6IGJvb2xlYW47XG59XG5cbi8qKiB7QGxpbmsgbGlzdEVsaWdpYmxlUmVsZWFzZXN9IHdpdGggaW5qZWN0ZWQgcmVhZHMgYW5kIGhpZXJhcmNoeSAodGVzdHMpLiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGxpc3RFbGlnaWJsZVJlbGVhc2VzV2l0aChkZXBzOiBNYW5hZ2VkVG9vbGNoYWluRGVwcywgb3JnSWQ6IHN0cmluZyk6IFByb21pc2U8eyBwbGF0Zm9ybURlZmF1bHQ6IHN0cmluZyB8IG51bGw7IHJlbGVhc2VzOiBFbGlnaWJsZVRvb2xjaGFpblJlbGVhc2VbXSB9PiB7XG4gIGNvbnN0IHNlbGYgPSBvcmdJZC50b0xvd2VyQ2FzZSgpO1xuICBjb25zdCB3YWxrID0gYXdhaXQgZGVwcy5yZWFkKChkYikgPT4gYW55T3JnU2V0dGluZ3MoZGIpKTtcbiAgY29uc3QgY2hhaW4gPSB3YWxrID8gYXdhaXQgdG9vbGNoYWluT3JnQ2hhaW4oc2VsZiwgZGVwcy5nZXRQYXJlbnQpIDogW3NlbGZdO1xuICByZXR1cm4gZGVwcy5yZWFkKGFzeW5jIChkYikgPT4ge1xuICAgIGNvbnN0IFtyZWxlYXNlcywgcm93cywgaGlzdG9yeSwgcGxhdGZvcm1EZWZhdWx0LCBjYW5hcnldID0gYXdhaXQgUHJvbWlzZS5hbGwoW1xuICAgICAgZGIuc2VsZWN0KCkuZnJvbShzY2hlbWEudG9vbGNoYWluUmVsZWFzZSkgYXMgUHJvbWlzZTxUb29sY2hhaW5SZWxlYXNlW10+LFxuICAgICAgZGIuc2VsZWN0KCkuZnJvbShzY2hlbWEucGx1Z2luKS53aGVyZShhbmQoXG4gICAgICAgIGVxKHNjaGVtYS5wbHVnaW4ub3JnSWQsIFNZU1RFTV9PUkdfSUQpLFxuICAgICAgICBpbkFycmF5KHNjaGVtYS5wbHVnaW4ubmFtZSwgWy4uLk1BTkFHRURfVE9PTENIQUlOX1BMVUdJTlNdKSxcbiAgICAgICAgaXNOdWxsKHNjaGVtYS5wbHVnaW4uZGVsZXRlZEF0KSxcbiAgICAgICkpIGFzIFByb21pc2U8UGx1Z2luW10+LFxuICAgICAgZGIuc2VsZWN0KHsgcmVsZWFzZVZlcnNpb246IHNjaGVtYS50b29sY2hhaW5EZWZhdWx0SGlzdG9yeS5yZWxlYXNlVmVyc2lvbiB9KS5mcm9tKHNjaGVtYS50b29sY2hhaW5EZWZhdWx0SGlzdG9yeSkgYXMgUHJvbWlzZTxBcnJheTx7IHJlbGVhc2VWZXJzaW9uOiBzdHJpbmcgfT4+LFxuICAgICAgY3VycmVudFBsYXRmb3JtRGVmYXVsdChkYiksXG4gICAgICBuZWFyZXN0T25DaGFpbihkYiwgc2NoZW1hLnRvb2xjaGFpblJvbGxvdXQsIGNoYWluKSxcbiAgICBdKTtcbiAgICBjb25zdCBwcm9tb3RlZCA9IG5ldyBTZXQoaGlzdG9yeS5tYXAoKGgpID0+IGgucmVsZWFzZVZlcnNpb24pKTtcbiAgICBpZiAocGxhdGZvcm1EZWZhdWx0KSBwcm9tb3RlZC5hZGQocGxhdGZvcm1EZWZhdWx0KTtcbiAgICBjb25zdCBvdXQ6IEVsaWdpYmxlVG9vbGNoYWluUmVsZWFzZVtdID0gW107XG4gICAgZm9yIChjb25zdCByZWxlYXNlIG9mIHJlbGVhc2VzKSB7XG4gICAgICBjb25zdCB2ID0gcmVsZWFzZS5yZWxlYXNlVmVyc2lvbjtcbiAgICAgIGNvbnN0IGhhbHZlczogUmVsZWFzZUhhbHZlcyA9IHtcbiAgICAgICAgcmVsZWFzZVZlcnNpb246IHYsXG4gICAgICAgIHJlbGVhc2UsXG4gICAgICAgIGJvb3RzdHJhcDogcm93cy5maW5kKChwKSA9PiBwLm5hbWUgPT09IEJPT1RTVFJBUCAmJiBwLnZlcnNpb24gPT09IHYpID8/IG51bGwsXG4gICAgICAgIHN5bnRoOiByb3dzLmZpbmQoKHApID0+IHAubmFtZSA9PT0gU1lOVEggJiYgcC52ZXJzaW9uID09PSB2KSA/PyBudWxsLFxuICAgICAgfTtcbiAgICAgIGlmICghcmVsZWFzZUV4aXN0cyhoYWx2ZXMpIHx8IHJlbGVhc2VMaWZlY3ljbGVQcm9ibGVtcyhoYWx2ZXMpLmxlbmd0aCA+IDApIGNvbnRpbnVlO1xuICAgICAgY29uc3QgaXNDYW5hcnkgPSBjYW5hcnk/LnJlbGVhc2VWZXJzaW9uID09PSB2O1xuICAgICAgaWYgKCFwcm9tb3RlZC5oYXModikgJiYgIWlzQ2FuYXJ5KSBjb250aW51ZTtcbiAgICAgIG91dC5wdXNoKHsgcmVsZWFzZVZlcnNpb246IHYsIHJlbGVhc2UsIGJvb3RzdHJhcDogaGFsdmVzLmJvb3RzdHJhcCwgc3ludGg6IGhhbHZlcy5zeW50aCwgaXNQbGF0Zm9ybURlZmF1bHQ6IHBsYXRmb3JtRGVmYXVsdCA9PT0gdiwgaXNDYW5hcnkgfSk7XG4gICAgfVxuICAgIG91dC5zb3J0KChhLCBiKSA9PiBjb21wYXJlU2VtdmVyKGIucmVsZWFzZVZlcnNpb24sIGEucmVsZWFzZVZlcnNpb24pKTtcbiAgICByZXR1cm4geyBwbGF0Zm9ybURlZmF1bHQsIHJlbGVhc2VzOiBvdXQgfTtcbiAgfSk7XG59XG5cbi8qKlxuICogRXZlcnkgcmVsZWFzZSBgb3JnSWRgIG1heSBTRVQgYXMgYSBwaXBlbGluZSBwaW4gb3IgaXRzIG9yZyBkZWZhdWx0IChEMTUsIHRoZVxuICogc2FtZSBydWxlIGFzIHtAbGluayBpc0VsaWdpYmxlUmVsZWFzZX0pLCBuZXdlc3QgZmlyc3QuIE5ldmVyIGFub3RoZXIgb3JnJ3NcbiAqIGRhdGE6IGEgY2FuYXJ5IGFwcGVhcnMgb25seSB3aGVuIGl0IGlzIHRoZSBjYWxsZXIncyBvd24gKG5lYXJlc3QpIG1lbWJlcnNoaXAuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBsaXN0RWxpZ2libGVSZWxlYXNlcyhvcmdJZDogc3RyaW5nKTogUHJvbWlzZTx7IHBsYXRmb3JtRGVmYXVsdDogc3RyaW5nIHwgbnVsbDsgcmVsZWFzZXM6IEVsaWdpYmxlVG9vbGNoYWluUmVsZWFzZVtdIH0+IHtcbiAgcmV0dXJuIGxpc3RFbGlnaWJsZVJlbGVhc2VzV2l0aChkZWZhdWx0RGVwcywgb3JnSWQpO1xufVxuXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuLy8gQ2FsbGVyIGhlbHBlcnNcbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cbi8qKlxuICogRWFjaCByZXNvbHZlciByZWZ1c2FsIGNvZGUncyBzdGVwLXJlc29sdXRpb24gcmVmdXNhbCAoYW55dGhpbmcgZWxzZSBpc1xuICogYHRvb2xjaGFpbl91bnJlc29sdmVkYCkuIGBkZXRhaWxzYCByaWRlcyBhbG9uZyBleGNlcHQgZm9yIE5PX0RFRkFVTFQsIHdoaWNoXG4gKiBjYXJyaWVzIG5vbmUgd29ydGggc2hvd2luZy5cbiAqL1xuY29uc3QgUkVGVVNBTF9CWV9DT0RFOiBQYXJ0aWFsPFJlY29yZDxFcnJvckNvZGUsIHsgY29kZTogUmVzb2x1dGlvblJlZnVzYWxbJ2NvZGUnXTsgcmVhc29uOiBzdHJpbmc7IGRldGFpbHM6IGJvb2xlYW4gfT4+ID0ge1xuICBbRXJyb3JDb2RlLk5PVF9GT1VORF06IHsgY29kZTogJ05PVF9GT1VORCcsIHJlYXNvbjogJ3Rvb2xjaGFpbl9yZWxlYXNlX25vdF9mb3VuZCcsIGRldGFpbHM6IHRydWUgfSxcbiAgW0Vycm9yQ29kZS5WQUxJREFUSU9OX0VSUk9SXTogeyBjb2RlOiAnTk9UX0ZPVU5EJywgcmVhc29uOiAndG9vbGNoYWluX3JlbGVhc2VfaW52YWxpZCcsIGRldGFpbHM6IHRydWUgfSxcbiAgW0Vycm9yQ29kZS5UT09MQ0hBSU5fTk9fREVGQVVMVF06IHsgY29kZTogJ1BMVUdJTl9VTkFWQUlMQUJMRScsIHJlYXNvbjogJ3Rvb2xjaGFpbl9ub19kZWZhdWx0JywgZGV0YWlsczogZmFsc2UgfSxcbn07XG5jb25zdCBVTlJFU09MVkVEX1JFRlVTQUwgPSB7IGNvZGU6ICdQTFVHSU5fVU5BVkFJTEFCTEUnLCByZWFzb246ICd0b29sY2hhaW5fdW5yZXNvbHZlZCcsIGRldGFpbHM6IHRydWUgfSBhcyBjb25zdDtcblxuLyoqIFRoZSByZXNvbHZlcidzIGVycm9yIGFzIHRoZSByZWZ1c2FsIHNoYXBlIHN0ZXAgcmVzb2x1dGlvbiByZXBvcnRzIChjb250cmFjdCBjaGVjaywgZGVjbGFyZWQgc2lkZSwgZmFjdHMpLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG1hbmFnZWRUb29sY2hhaW5SZWZ1c2FsKGVycjogTWFuYWdlZFRvb2xjaGFpbkVycm9yKTogUmVzb2x1dGlvblJlZnVzYWwge1xuICBjb25zdCByID0gUkVGVVNBTF9CWV9DT0RFW2Vyci5jb2RlIGFzIEVycm9yQ29kZV0gPz8gVU5SRVNPTFZFRF9SRUZVU0FMO1xuICByZXR1cm4geyBjb2RlOiByLmNvZGUsIHJlYXNvbjogci5yZWFzb24sIG1lc3NhZ2U6IGVyci5tZXNzYWdlLCAuLi4oci5kZXRhaWxzICYmIGVyci5kZXRhaWxzID8geyBkZXRhaWxzOiBlcnIuZGV0YWlscyB9IDoge30pIH07XG59XG5cbi8qKlxuICogUmVzb2x2ZSBPTkUgbWFuYWdlZCBoYWxmIGZvciBhIHN0ZXA6IHRoZSBwbHVnaW4gcm93IHBsdXMgdGhlIHJlc29sdXRpb24sIG9yXG4gKiB0aGUgcmVmdXNhbC4gQW55IG5vbi1yZXNvbHZlciBlcnJvciAoYSBkYXRhYmFzZSBvciBoaWVyYXJjaHkgZmFpbHVyZSlcbiAqIHByb3BhZ2F0ZXMuXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiByZXNvbHZlTWFuYWdlZFRvb2xjaGFpbkhhbGYoXG4gIGNhbGxlcjogTWFuYWdlZFRvb2xjaGFpbkNhbGxlcixcbiAgbmFtZTogTWFuYWdlZFRvb2xjaGFpblBsdWdpbixcbiAgb3B0czogeyByZWxlYXNlUGluPzogc3RyaW5nIH0gPSB7fSxcbik6IFByb21pc2U8eyBwbHVnaW46IFBsdWdpbjsgcmVzb2x1dGlvbjogTWFuYWdlZFRvb2xjaGFpblJlc29sdXRpb24gfSB8IHsgcmVmdXNhbDogUmVzb2x1dGlvblJlZnVzYWw7IGVycm9yOiBNYW5hZ2VkVG9vbGNoYWluRXJyb3IgfT4ge1xuICB0cnkge1xuICAgIGNvbnN0IHJlc29sdXRpb24gPSBhd2FpdCByZXNvbHZlTWFuYWdlZFRvb2xjaGFpbihjYWxsZXIsIG9wdHMpO1xuICAgIHJldHVybiB7IHBsdWdpbjogbmFtZSA9PT0gQk9PVFNUUkFQID8gcmVzb2x1dGlvbi5ib290c3RyYXAgOiByZXNvbHV0aW9uLnN5bnRoLCByZXNvbHV0aW9uIH07XG4gIH0gY2F0Y2ggKGVycikge1xuICAgIGlmIChlcnIgaW5zdGFuY2VvZiBNYW5hZ2VkVG9vbGNoYWluRXJyb3IpIHJldHVybiB7IHJlZnVzYWw6IG1hbmFnZWRUb29sY2hhaW5SZWZ1c2FsKGVyciksIGVycm9yOiBlcnIgfTtcbiAgICB0aHJvdyBlcnI7XG4gIH1cbn1cbiJdfQ==
@@ -26,22 +26,11 @@
26
26
  * name (typo tolerance), ranked by `ts_rank` + name similarity, blended with the
27
27
  * Bayesian rating and install count when present. Paused listings are hidden.
28
28
  */
29
- import { type PublisherTier } from '@pipeline-builder/api-core';
29
+ import type { PublisherTier } from '@pipeline-builder/api-core';
30
30
  import type { HealthBreakdown } from '../database/drizzle-schema.js';
31
- /**
32
- * DERIVED from api-core's canonical `PUBLISHER_TIERS`, not restated.
33
- *
34
- * This was a hand-written copy of the same four values, and the copy is what
35
- * the public route's zod enum validated — while the view types in the same
36
- * package already used `PublisherTier`. A fifth tier would have been stored and
37
- * displayed and then silently unfilterable, because the filter would still only
38
- * accept the four this list remembered.
39
- */
40
- export type DirectoryTrustTier = PublisherTier;
41
31
  export type DirectoryIconKind = 'vendor' | 'uploaded' | 'monogram' | 'category';
42
32
  export type DirectorySort = 'relevance' | 'rating' | 'installs' | 'updated' | 'name' | 'health';
43
33
  export declare const DIRECTORY_SORTS: readonly DirectorySort[];
44
- export declare const DIRECTORY_TIERS: readonly DirectoryTrustTier[];
45
34
  /** Minimum `word_similarity(query, name)` for a fuzzy name match (typo tolerance). */
46
35
  export declare const FUZZY_NAME_THRESHOLD = 0.3;
47
36
  /** Max query length accepted (longer is truncated, never an error). */
@@ -51,7 +40,7 @@ export declare const DIRECTORY_MAX_LIMIT = 60;
51
40
  export interface DirectorySearchParams {
52
41
  q?: string;
53
42
  category?: string;
54
- tier?: DirectoryTrustTier;
43
+ tier?: PublisherTier;
55
44
  license?: string;
56
45
  computeType?: string;
57
46
  needsSecrets?: boolean;
@@ -64,7 +53,7 @@ export interface DirectoryListingCard {
64
53
  publisher: {
65
54
  handle: string;
66
55
  displayName: string;
67
- tier: DirectoryTrustTier;
56
+ tier: PublisherTier;
68
57
  };
69
58
  name: string;
70
59
  summary: string;
@@ -248,7 +237,7 @@ export interface PublicListingRow {
248
237
  id: string;
249
238
  publisher_handle: string;
250
239
  publisher_display_name: string;
251
- publisher_tier: DirectoryTrustTier;
240
+ publisher_tier: PublisherTier;
252
241
  name: string;
253
242
  category: string;
254
243
  summary: string | null;