@pipeline-builder/pipeline-data 4.1.15 → 4.1.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/api/access-control-builder.d.ts +18 -1
- package/lib/api/access-control-builder.js +19 -6
- package/lib/api/crud-service.d.ts +94 -36
- package/lib/api/crud-service.js +188 -166
- package/lib/api/plugin-resolution.d.ts +253 -0
- package/lib/api/plugin-resolution.js +649 -0
- package/lib/api/public-directory.d.ts +281 -0
- package/lib/api/public-directory.js +457 -0
- package/lib/api/query-builders.d.ts +13 -0
- package/lib/api/query-builders.js +74 -9
- package/lib/api/reporting/caches.js +4 -4
- package/lib/api/reporting/dora-scoring.d.ts +3 -3
- package/lib/api/reporting/dora-scoring.js +4 -4
- package/lib/api/reporting/dora.d.ts +6 -6
- package/lib/api/reporting/dora.js +97 -73
- package/lib/api/reporting/plugin-runtime.d.ts +25 -0
- package/lib/api/reporting/plugin-runtime.js +106 -0
- package/lib/api/reporting/query-scope.d.ts +8 -2
- package/lib/api/reporting/query-scope.js +16 -7
- package/lib/api/reporting/retention.d.ts +4 -10
- package/lib/api/reporting/retention.js +8 -11
- package/lib/api/reporting/sql-helpers.d.ts +4 -7
- package/lib/api/reporting/sql-helpers.js +8 -9
- package/lib/api/reporting/types.d.ts +55 -17
- package/lib/api/reporting/types.js +1 -1
- package/lib/api/reporting-service.d.ts +35 -26
- package/lib/api/reporting-service.js +245 -161
- package/lib/api/semver-range.d.ts +73 -0
- package/lib/api/semver-range.js +227 -0
- package/lib/api/soft-delete-sweep.js +8 -20
- package/lib/core/query-filters.d.ts +18 -3
- package/lib/core/query-filters.js +1 -1
- package/lib/database/drizzle-schema.d.ts +7790 -2461
- package/lib/database/drizzle-schema.js +29 -1
- package/lib/database/index.d.ts +4 -2
- package/lib/database/index.js +5 -3
- package/lib/database/pg-result.d.ts +19 -0
- package/lib/database/pg-result.js +32 -0
- package/lib/database/postgres-connection.js +14 -24
- package/lib/database/public-reader.d.ts +14 -0
- package/lib/database/public-reader.js +68 -0
- package/lib/database/retry-strategy.d.ts +3 -5
- package/lib/database/retry-strategy.js +4 -6
- package/lib/database/schema/compliance.d.ts +16 -34
- package/lib/database/schema/compliance.js +4 -4
- package/lib/database/schema/dashboard.js +4 -2
- package/lib/database/schema/ecosystem.d.ts +6586 -0
- package/lib/database/schema/ecosystem.js +709 -0
- package/lib/database/schema/message.d.ts +6 -12
- package/lib/database/schema/message.js +3 -1
- package/lib/database/schema/pipeline.d.ts +79 -5
- package/lib/database/schema/pipeline.js +46 -25
- package/lib/database/schema/plugin.d.ts +587 -3
- package/lib/database/schema/plugin.js +86 -14
- package/lib/database/tenancy.d.ts +6 -7
- package/lib/database/tenancy.js +13 -14
- package/lib/index.d.ts +7 -4
- package/lib/index.js +7 -4
- package/lib/testing/exports.json +146 -0
- package/package.json +44 -7
|
@@ -0,0 +1,457 @@
|
|
|
1
|
+
// Copyright 2026 Pipeline Builder Contributors
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
/**
|
|
4
|
+
* Queries behind the anonymous public plugin directory
|
|
5
|
+
* (docs/plugin-publishing.md).
|
|
6
|
+
*
|
|
7
|
+
* Every query here reads ONLY the `public_listings`, `public_listed_versions`,
|
|
8
|
+
* `public_advisories` and `public_reviews` views, through the `ecosystem_public_reader`
|
|
9
|
+
* connection ({@link getPublicReaderDb}). Those views already filter to public
|
|
10
|
+
* rows (listed/unmaintained listings of non-suspended publishers, non-paused
|
|
11
|
+
* versions, published advisories) and project public columns only, so nothing
|
|
12
|
+
* here needs — or has — a tenant context.
|
|
13
|
+
*
|
|
14
|
+
* Search: Postgres full-text (`search_vector`, weighted name A / keywords and
|
|
15
|
+
* category B / summary C / README D, `english` config) OR a trigram match on the
|
|
16
|
+
* name (typo tolerance), ranked by `ts_rank` + name similarity, blended with the
|
|
17
|
+
* Bayesian rating and install count when present. Paused listings are hidden.
|
|
18
|
+
*/
|
|
19
|
+
import { sql } from 'drizzle-orm';
|
|
20
|
+
import { advisoryRangeCovers } from './plugin-resolution.js';
|
|
21
|
+
import { compareSemver } from './semver-range.js';
|
|
22
|
+
import { resultRows } from '../database/pg-result.js';
|
|
23
|
+
import { getPublicReaderDb } from '../database/public-reader.js';
|
|
24
|
+
export const DIRECTORY_SORTS = ['relevance', 'rating', 'installs', 'updated', 'name', 'health'];
|
|
25
|
+
export const DIRECTORY_TIERS = ['official', 'verified', 'community', 'unverified'];
|
|
26
|
+
/** Minimum `word_similarity(query, name)` for a fuzzy name match (typo tolerance). */
|
|
27
|
+
export const FUZZY_NAME_THRESHOLD = 0.3;
|
|
28
|
+
/** Max query length accepted (longer is truncated, never an error). */
|
|
29
|
+
export const DIRECTORY_MAX_QUERY_LENGTH = 100;
|
|
30
|
+
export const DIRECTORY_DEFAULT_LIMIT = 24;
|
|
31
|
+
export const DIRECTORY_MAX_LIMIT = 60;
|
|
32
|
+
export const REVIEW_SORTS = ['helpful', 'recent', 'highest', 'lowest'];
|
|
33
|
+
export const REVIEWS_DEFAULT_LIMIT = 10;
|
|
34
|
+
export const REVIEWS_MAX_LIMIT = 50;
|
|
35
|
+
function num(v) {
|
|
36
|
+
const n = typeof v === 'number' ? v : Number.parseFloat(String(v ?? '0'));
|
|
37
|
+
return Number.isFinite(n) ? n : 0;
|
|
38
|
+
}
|
|
39
|
+
function iso(v) {
|
|
40
|
+
if (!v)
|
|
41
|
+
return '';
|
|
42
|
+
return v instanceof Date ? v.toISOString() : new Date(v).toISOString();
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* The icon fallback chain: uploaded (if the tier may upload) → curated
|
|
46
|
+
* vendor key (Official, and Verified publishers for marks they own — ownership
|
|
47
|
+
* is checked when the icon is approved) → monogram. Community and anonymous
|
|
48
|
+
* listings can never show a curated vendor mark.
|
|
49
|
+
*/
|
|
50
|
+
export function resolveListingIcon(row) {
|
|
51
|
+
const none = { iconUrl: null, iconKey: null, iconBadge: null, iconHex: null };
|
|
52
|
+
if (row.uploaded_icon?.key256) {
|
|
53
|
+
return { ...none, iconKind: 'uploaded', iconUrl: `/api/public/plugins/icons/${encodeURIComponent(row.uploaded_icon.key256)}` };
|
|
54
|
+
}
|
|
55
|
+
const curatedAllowed = row.publisher_tier === 'official' || row.publisher_tier === 'verified';
|
|
56
|
+
if (curatedAllowed && row.icon?.key) {
|
|
57
|
+
return { ...none, iconKind: 'vendor', iconKey: row.icon.key, iconBadge: row.icon.badge ?? null };
|
|
58
|
+
}
|
|
59
|
+
return { ...none, iconKind: 'monogram' };
|
|
60
|
+
}
|
|
61
|
+
export function toListingCard(row) {
|
|
62
|
+
const ratingCount = num(row.rating_count);
|
|
63
|
+
return {
|
|
64
|
+
publisher: { handle: row.publisher_handle, displayName: row.publisher_display_name, tier: row.publisher_tier },
|
|
65
|
+
name: row.name,
|
|
66
|
+
summary: row.summary ?? '',
|
|
67
|
+
category: row.category,
|
|
68
|
+
keywords: row.keywords ?? [],
|
|
69
|
+
latestVersion: row.latest_version ?? '',
|
|
70
|
+
license: row.license ?? '',
|
|
71
|
+
...resolveListingIcon(row),
|
|
72
|
+
rating: ratingCount > 0 && row.rating_bayes != null ? { score: Math.round(num(row.rating_bayes) * 100) / 100, count: ratingCount } : null,
|
|
73
|
+
installCount: num(row.install_count),
|
|
74
|
+
healthScore: row.health_score == null ? null : Math.round(num(row.health_score)),
|
|
75
|
+
updatedAt: iso(row.updated_at),
|
|
76
|
+
state: row.state,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
// -----------------------------------------------------------------------------
|
|
80
|
+
// Search
|
|
81
|
+
// -----------------------------------------------------------------------------
|
|
82
|
+
/** Normalize the user's query: collapse whitespace, cap the length. */
|
|
83
|
+
export function normalizeQuery(q) {
|
|
84
|
+
return (q ?? '').replace(/\s+/g, ' ').trim().slice(0, DIRECTORY_MAX_QUERY_LENGTH);
|
|
85
|
+
}
|
|
86
|
+
/** Search terms for highlighting: words of ≥ 2 characters, regex-escaped. */
|
|
87
|
+
function highlightTerms(q) {
|
|
88
|
+
return [...new Set(q.toLowerCase().split(/[^a-z0-9._-]+/).filter((t) => t.length >= 2))]
|
|
89
|
+
.map((t) => t.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'));
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Wrap matched terms in `<mark>`. The frontend renders everything except the
|
|
93
|
+
* `<mark>` markers as TEXT (never HTML), so the source text is not escaped here.
|
|
94
|
+
* Returns undefined when nothing matched (the card then renders plain text).
|
|
95
|
+
*/
|
|
96
|
+
export function highlightText(text, q) {
|
|
97
|
+
const terms = highlightTerms(q);
|
|
98
|
+
if (!text || terms.length === 0)
|
|
99
|
+
return undefined;
|
|
100
|
+
const re = new RegExp(`(${terms.join('|')})`, 'gi');
|
|
101
|
+
if (!re.test(text))
|
|
102
|
+
return undefined;
|
|
103
|
+
return text.replace(re, '<mark>$1</mark>');
|
|
104
|
+
}
|
|
105
|
+
/** Opaque cursor: an offset, base64url-encoded so clients don't depend on it. */
|
|
106
|
+
export function encodeOffsetCursor(offset) {
|
|
107
|
+
return Buffer.from(JSON.stringify({ o: offset })).toString('base64url');
|
|
108
|
+
}
|
|
109
|
+
export function decodeOffsetCursor(cursor) {
|
|
110
|
+
if (!cursor)
|
|
111
|
+
return 0;
|
|
112
|
+
try {
|
|
113
|
+
const o = JSON.parse(Buffer.from(cursor, 'base64url').toString('utf8')).o;
|
|
114
|
+
return typeof o === 'number' && Number.isInteger(o) && o >= 0 && o <= 10_000 ? o : 0;
|
|
115
|
+
}
|
|
116
|
+
catch {
|
|
117
|
+
return 0;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
function clampLimit(limit) {
|
|
121
|
+
if (!limit || !Number.isFinite(limit))
|
|
122
|
+
return DIRECTORY_DEFAULT_LIMIT;
|
|
123
|
+
return Math.min(Math.max(Math.trunc(limit), 1), DIRECTORY_MAX_LIMIT);
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* The filtered base set as a CTE body. Every search, facet and category query
|
|
127
|
+
* reads through this, so they can't disagree about what's visible.
|
|
128
|
+
*/
|
|
129
|
+
function baseQuery(params, q) {
|
|
130
|
+
const where = [sql `l.paused_at IS NULL`];
|
|
131
|
+
if (q) {
|
|
132
|
+
// Full text, OR a fuzzy match against the best-matching PART of the name
|
|
133
|
+
// (word_similarity: "terafrom" → terraform-plan scores 0.36, while unrelated
|
|
134
|
+
// words stay ≤ 0.2 — whole-name similarity() dilutes a long name below any
|
|
135
|
+
// useful threshold). Explicit function, not the `<%` operator, so the cut-off
|
|
136
|
+
// doesn't depend on a session GUC pgbouncer can't carry. A seq scan over the
|
|
137
|
+
// public listings (thousands of rows at most) is fine.
|
|
138
|
+
where.push(sql `(l.search_vector @@ websearch_to_tsquery('english', ${q}) OR word_similarity(${q}, l.name) >= ${FUZZY_NAME_THRESHOLD} OR l.name ILIKE ${`%${q.replace(/[\\%_]/g, '\\$&')}%`})`);
|
|
139
|
+
}
|
|
140
|
+
if (params.category)
|
|
141
|
+
where.push(sql `l.category = ${params.category}`);
|
|
142
|
+
if (params.tier)
|
|
143
|
+
where.push(sql `l.publisher_tier = ${params.tier}`);
|
|
144
|
+
if (params.license)
|
|
145
|
+
where.push(sql `l.license = ${params.license}`);
|
|
146
|
+
if (params.computeType)
|
|
147
|
+
where.push(sql `v.compute_type = ${params.computeType}`);
|
|
148
|
+
if (params.needsSecrets !== undefined) {
|
|
149
|
+
where.push(params.needsSecrets
|
|
150
|
+
? sql `jsonb_array_length(COALESCE(v.secrets, '[]'::jsonb)) > 0`
|
|
151
|
+
: sql `jsonb_array_length(COALESCE(v.secrets, '[]'::jsonb)) = 0`);
|
|
152
|
+
}
|
|
153
|
+
if (params.minRating !== undefined && Number.isFinite(params.minRating)) {
|
|
154
|
+
where.push(sql `l.rating_bayes >= ${params.minRating}`);
|
|
155
|
+
}
|
|
156
|
+
const rank = q
|
|
157
|
+
? sql `(ts_rank(l.search_vector, websearch_to_tsquery('english', ${q})) + word_similarity(${q}, l.name))`
|
|
158
|
+
: sql `0::real`;
|
|
159
|
+
return sql `
|
|
160
|
+
SELECT l.id, l.publisher_handle, l.publisher_display_name, l.publisher_tier, l.name, l.category,
|
|
161
|
+
l.summary, l.description, l.readme_html, l.license, l.homepage_url, l.source_url, l.icon,
|
|
162
|
+
l.uploaded_icon, l.keywords, l.latest_version, l.updated_at, l.rating_bayes, l.rating_count,
|
|
163
|
+
l.rating_dist, l.install_count, l.active_org_count, l.health_score, l.state,
|
|
164
|
+
v.compute_type,
|
|
165
|
+
(jsonb_array_length(COALESCE(v.secrets, '[]'::jsonb)) > 0) AS needs_secrets,
|
|
166
|
+
${rank} AS rank
|
|
167
|
+
FROM public_listings l
|
|
168
|
+
LEFT JOIN LATERAL (
|
|
169
|
+
SELECT pv.compute_type, pv.secrets
|
|
170
|
+
FROM public_listed_versions pv
|
|
171
|
+
WHERE pv.listing_id = l.id AND pv.version = l.latest_version AND NOT pv.yanked
|
|
172
|
+
LIMIT 1
|
|
173
|
+
) v ON true
|
|
174
|
+
WHERE ${sql.join(where, sql ` AND `)}`;
|
|
175
|
+
}
|
|
176
|
+
function orderBy(sort, hasQuery) {
|
|
177
|
+
switch (sort === 'relevance' && !hasQuery ? 'updated' : sort) {
|
|
178
|
+
case 'relevance':
|
|
179
|
+
// Text relevance first, nudged by rating and adoption so equal matches
|
|
180
|
+
// favour proven plugins.
|
|
181
|
+
return sql `(rank * (1 + COALESCE(rating_bayes, 0) / 10) + ln(1 + install_count) / 20) DESC, name ASC`;
|
|
182
|
+
case 'rating':
|
|
183
|
+
return sql `rating_bayes DESC NULLS LAST, rating_count DESC, name ASC`;
|
|
184
|
+
case 'installs':
|
|
185
|
+
return sql `install_count DESC, name ASC`;
|
|
186
|
+
case 'name':
|
|
187
|
+
return sql `name ASC, publisher_handle ASC`;
|
|
188
|
+
case 'health':
|
|
189
|
+
return sql `health_score DESC NULLS LAST, install_count DESC, name ASC`;
|
|
190
|
+
case 'updated':
|
|
191
|
+
default:
|
|
192
|
+
return sql `updated_at DESC, name ASC`;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
/** Search the directory: one page of cards, facet counts, total and next cursor. */
|
|
196
|
+
export async function searchPublicListings(params) {
|
|
197
|
+
const db = getPublicReaderDb();
|
|
198
|
+
const q = normalizeQuery(params.q);
|
|
199
|
+
const limit = clampLimit(params.limit);
|
|
200
|
+
const offset = decodeOffsetCursor(params.cursor);
|
|
201
|
+
const sort = params.sort && DIRECTORY_SORTS.includes(params.sort) ? params.sort : 'relevance';
|
|
202
|
+
const base = baseQuery(params, q);
|
|
203
|
+
const [pageRes, facetRes] = await Promise.all([
|
|
204
|
+
db.execute(sql `
|
|
205
|
+
WITH base AS (${base})
|
|
206
|
+
SELECT base.*, COUNT(*) OVER () AS total
|
|
207
|
+
FROM base
|
|
208
|
+
ORDER BY ${orderBy(sort, q !== '')}
|
|
209
|
+
LIMIT ${limit} OFFSET ${offset}`),
|
|
210
|
+
db.execute(sql `
|
|
211
|
+
WITH base AS (${base})
|
|
212
|
+
SELECT category, publisher_tier, license, compute_type, needs_secrets,
|
|
213
|
+
GROUPING(category) AS g_category, GROUPING(publisher_tier) AS g_tier,
|
|
214
|
+
GROUPING(license) AS g_license, GROUPING(compute_type) AS g_compute,
|
|
215
|
+
GROUPING(needs_secrets) AS g_secrets,
|
|
216
|
+
COUNT(*) AS n
|
|
217
|
+
FROM base
|
|
218
|
+
GROUP BY GROUPING SETS ((category), (publisher_tier), (license), (compute_type), (needs_secrets))`),
|
|
219
|
+
]);
|
|
220
|
+
const page = resultRows(pageRes);
|
|
221
|
+
const total = page.length > 0 ? num(page[0].total) : 0;
|
|
222
|
+
const items = page.map((row) => {
|
|
223
|
+
const card = toListingCard(row);
|
|
224
|
+
if (q) {
|
|
225
|
+
const highlight = { name: highlightText(card.name, q), summary: highlightText(card.summary, q) };
|
|
226
|
+
if (highlight.name || highlight.summary)
|
|
227
|
+
card.highlight = highlight;
|
|
228
|
+
}
|
|
229
|
+
return card;
|
|
230
|
+
});
|
|
231
|
+
const facets = {
|
|
232
|
+
category: {}, tier: {}, license: {}, computeType: {}, needsSecrets: { true: 0, false: 0 },
|
|
233
|
+
};
|
|
234
|
+
for (const r of resultRows(facetRes)) {
|
|
235
|
+
const n = num(r.n);
|
|
236
|
+
if (Number(r.g_category) === 0 && r.category)
|
|
237
|
+
facets.category[r.category] = n;
|
|
238
|
+
else if (Number(r.g_tier) === 0 && r.publisher_tier)
|
|
239
|
+
facets.tier[r.publisher_tier] = n;
|
|
240
|
+
else if (Number(r.g_license) === 0 && r.license)
|
|
241
|
+
facets.license[r.license] = n;
|
|
242
|
+
else if (Number(r.g_compute) === 0 && r.compute_type)
|
|
243
|
+
facets.computeType[r.compute_type] = n;
|
|
244
|
+
else if (Number(r.g_secrets) === 0 && r.needs_secrets !== null)
|
|
245
|
+
facets.needsSecrets[r.needs_secrets ? 'true' : 'false'] = n;
|
|
246
|
+
}
|
|
247
|
+
return {
|
|
248
|
+
items,
|
|
249
|
+
facets,
|
|
250
|
+
total,
|
|
251
|
+
nextCursor: offset + items.length < total ? encodeOffsetCursor(offset + items.length) : null,
|
|
252
|
+
};
|
|
253
|
+
}
|
|
254
|
+
// -----------------------------------------------------------------------------
|
|
255
|
+
// Categories
|
|
256
|
+
// -----------------------------------------------------------------------------
|
|
257
|
+
/** Every category with its live count and its top listings (by rating, then installs). */
|
|
258
|
+
export async function listPublicCategories(topPerCategory = 3) {
|
|
259
|
+
const db = getPublicReaderDb();
|
|
260
|
+
const res = await db.execute(sql `
|
|
261
|
+
WITH ranked AS (
|
|
262
|
+
SELECT l.*,
|
|
263
|
+
ROW_NUMBER() OVER (PARTITION BY l.category
|
|
264
|
+
ORDER BY l.rating_bayes DESC NULLS LAST, l.install_count DESC, l.name ASC) AS rn,
|
|
265
|
+
COUNT(*) OVER (PARTITION BY l.category) AS category_count
|
|
266
|
+
FROM public_listings l
|
|
267
|
+
WHERE l.paused_at IS NULL
|
|
268
|
+
)
|
|
269
|
+
SELECT * FROM ranked WHERE rn <= ${Math.max(0, Math.min(topPerCategory, 10))} ORDER BY category ASC, rn ASC`);
|
|
270
|
+
const byCategory = new Map();
|
|
271
|
+
for (const row of resultRows(res)) {
|
|
272
|
+
let summary = byCategory.get(row.category);
|
|
273
|
+
if (!summary) {
|
|
274
|
+
summary = { id: row.category, count: num(row.category_count), top: [] };
|
|
275
|
+
byCategory.set(row.category, summary);
|
|
276
|
+
}
|
|
277
|
+
summary.top.push(toListingCard(row));
|
|
278
|
+
}
|
|
279
|
+
return [...byCategory.values()];
|
|
280
|
+
}
|
|
281
|
+
/**
|
|
282
|
+
* One listing's page data, or null when it isn't public (unknown, suspended,
|
|
283
|
+
* transferred, paused by its publisher — or its publisher is suspended).
|
|
284
|
+
*/
|
|
285
|
+
export async function getPublicListing(publisherHandle, name) {
|
|
286
|
+
const db = getPublicReaderDb();
|
|
287
|
+
const listingRes = await db.execute(sql `
|
|
288
|
+
SELECT * FROM public_listings
|
|
289
|
+
WHERE publisher_handle = ${publisherHandle} AND name = ${name} AND paused_at IS NULL
|
|
290
|
+
LIMIT 1`);
|
|
291
|
+
const row = resultRows(listingRes)[0];
|
|
292
|
+
if (!row)
|
|
293
|
+
return null;
|
|
294
|
+
const [versionRes, advisoryRes] = await Promise.all([
|
|
295
|
+
db.execute(sql `SELECT * FROM public_listed_versions WHERE listing_id = ${row.id}`),
|
|
296
|
+
db.execute(sql `SELECT * FROM public_advisories WHERE listing_id = ${row.id} ORDER BY published_at DESC`),
|
|
297
|
+
]);
|
|
298
|
+
const versionRows = resultRows(versionRes).sort((a, b) => compareSemver(b.version, a.version));
|
|
299
|
+
const advisoryRows = resultRows(advisoryRes);
|
|
300
|
+
// The version the page describes: the listing's latest, else the newest non-yanked one.
|
|
301
|
+
const current = versionRows.find((v) => v.version === row.latest_version && !v.yanked)
|
|
302
|
+
?? versionRows.find((v) => !v.yanked)
|
|
303
|
+
?? null;
|
|
304
|
+
const dist = row.rating_dist ?? null;
|
|
305
|
+
const card = toListingCard(row);
|
|
306
|
+
return {
|
|
307
|
+
...card,
|
|
308
|
+
readmeHtml: row.readme_html ?? current?.readme_html ?? null,
|
|
309
|
+
description: row.description ?? '',
|
|
310
|
+
homepageUrl: row.homepage_url,
|
|
311
|
+
sourceUrl: row.source_url,
|
|
312
|
+
versions: versionRows.map((v) => ({
|
|
313
|
+
version: v.version,
|
|
314
|
+
publishedAt: iso(v.published_at),
|
|
315
|
+
breaking: v.breaking,
|
|
316
|
+
deprecated: v.deprecated_at != null,
|
|
317
|
+
deprecationMessage: v.deprecation_message,
|
|
318
|
+
yanked: v.yanked,
|
|
319
|
+
changelog: v.changelog,
|
|
320
|
+
vulnCritical: v.vuln_critical,
|
|
321
|
+
vulnHigh: v.vuln_high,
|
|
322
|
+
scannedAt: v.scanned_at ? iso(v.scanned_at) : null,
|
|
323
|
+
advisoryIds: advisoryRows.filter((a) => advisoryRangeCovers(a.affected_range, v.version)).map((a) => a.id),
|
|
324
|
+
})),
|
|
325
|
+
configuration: {
|
|
326
|
+
secrets: (current?.secrets ?? []).map((s) => ({ name: s.name, required: s.required, description: s.description ?? '' })),
|
|
327
|
+
requiredMetadata: current?.required_metadata ?? [],
|
|
328
|
+
requiredVars: current?.required_vars ?? [],
|
|
329
|
+
computeType: current?.compute_type ?? '',
|
|
330
|
+
primaryOutputDirectory: null,
|
|
331
|
+
networkEgress: current?.network_egress ?? [],
|
|
332
|
+
pluginType: current?.plugin_type ?? '',
|
|
333
|
+
},
|
|
334
|
+
supplyChain: {
|
|
335
|
+
// A listed version exists only after the platform re-signed it in public/*.
|
|
336
|
+
signed: current?.image_digest != null,
|
|
337
|
+
digest: current?.image_digest ?? null,
|
|
338
|
+
imageSource: current?.image_source ?? null,
|
|
339
|
+
scannedAt: current?.scanned_at ? iso(current.scanned_at) : null,
|
|
340
|
+
vulnCritical: current?.vuln_critical ?? null,
|
|
341
|
+
vulnHigh: current?.vuln_high ?? null,
|
|
342
|
+
sbomUrl: current?.image_digest
|
|
343
|
+
? `/api/public/plugins/${encodeURIComponent(row.publisher_handle)}/${encodeURIComponent(row.name)}/versions/${encodeURIComponent(current.version)}/sbom`
|
|
344
|
+
: null,
|
|
345
|
+
},
|
|
346
|
+
advisories: advisoryRows.map((a) => ({
|
|
347
|
+
id: a.id,
|
|
348
|
+
severity: a.severity,
|
|
349
|
+
summary: a.summary,
|
|
350
|
+
affectedRange: a.affected_range,
|
|
351
|
+
fixedVersion: a.fixed_version,
|
|
352
|
+
publishedAt: iso(a.published_at),
|
|
353
|
+
detailsHtml: a.details_html,
|
|
354
|
+
cveIds: a.cve_ids ?? [],
|
|
355
|
+
})),
|
|
356
|
+
ratingDistribution: dist
|
|
357
|
+
? { 1: num(dist['1']), 2: num(dist['2']), 3: num(dist['3']), 4: num(dist['4']), 5: num(dist['5']) }
|
|
358
|
+
: null,
|
|
359
|
+
recentRating: row.recent_rating == null ? null : Math.round(num(row.recent_rating) * 100) / 100,
|
|
360
|
+
activeOrgCount: row.active_org_count == null ? null : num(row.active_org_count),
|
|
361
|
+
healthBreakdown: row.health_breakdown ?? null,
|
|
362
|
+
successRate30d: row.success_rate_30d == null ? null : Math.round(num(row.success_rate_30d) * 1000) / 1000,
|
|
363
|
+
};
|
|
364
|
+
}
|
|
365
|
+
/** One listed version's public image identity (for the SBOM download), or null. */
|
|
366
|
+
export async function getPublicListedVersion(publisherHandle, name, version) {
|
|
367
|
+
const db = getPublicReaderDb();
|
|
368
|
+
const res = await db.execute(sql `
|
|
369
|
+
SELECT image_repository, image_digest FROM public_listed_versions
|
|
370
|
+
WHERE publisher_handle = ${publisherHandle} AND name = ${name} AND version = ${version} AND NOT yanked
|
|
371
|
+
AND listing_id IN (SELECT id FROM public_listings WHERE paused_at IS NULL)
|
|
372
|
+
LIMIT 1`);
|
|
373
|
+
const row = resultRows(res)[0];
|
|
374
|
+
if (!row?.image_repository || !row.image_digest)
|
|
375
|
+
return null;
|
|
376
|
+
return { imageRepository: row.image_repository, imageDigest: row.image_digest };
|
|
377
|
+
}
|
|
378
|
+
function reviewOrder(sort) {
|
|
379
|
+
switch (sort) {
|
|
380
|
+
case 'recent': return sql `created_at DESC, id ASC`;
|
|
381
|
+
case 'highest': return sql `rating DESC, helpful_count DESC, created_at DESC, id ASC`;
|
|
382
|
+
case 'lowest': return sql `rating ASC, helpful_count DESC, created_at DESC, id ASC`;
|
|
383
|
+
case 'helpful':
|
|
384
|
+
default:
|
|
385
|
+
// Verified use breaks ties: an org that runs the plugin knows it best.
|
|
386
|
+
return sql `helpful_count DESC, verified_use DESC, created_at DESC, id ASC`;
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
export function toPublicReview(row) {
|
|
390
|
+
return {
|
|
391
|
+
id: row.id,
|
|
392
|
+
rating: num(row.rating),
|
|
393
|
+
title: row.title,
|
|
394
|
+
bodyHtml: row.body_html,
|
|
395
|
+
version: row.version,
|
|
396
|
+
author: row.author_display_name ? { displayName: row.author_display_name } : null,
|
|
397
|
+
verifiedUse: row.verified_use === true,
|
|
398
|
+
helpfulCount: num(row.helpful_count),
|
|
399
|
+
edited: row.edited === true,
|
|
400
|
+
createdAt: iso(row.created_at),
|
|
401
|
+
updatedAt: iso(row.updated_at),
|
|
402
|
+
reply: row.reply_body_html
|
|
403
|
+
? {
|
|
404
|
+
bodyHtml: row.reply_body_html,
|
|
405
|
+
publisherDisplayName: row.publisher_display_name,
|
|
406
|
+
createdAt: iso(row.reply_created_at),
|
|
407
|
+
updatedAt: iso(row.reply_updated_at),
|
|
408
|
+
}
|
|
409
|
+
: null,
|
|
410
|
+
};
|
|
411
|
+
}
|
|
412
|
+
/**
|
|
413
|
+
* One page of a listing's published reviews (the directory's Reviews tab), or null
|
|
414
|
+
* when the listing isn't public. Held and removed reviews never reach the view.
|
|
415
|
+
*/
|
|
416
|
+
export async function listPublicReviews(publisherHandle, name, query = {}) {
|
|
417
|
+
const db = getPublicReaderDb();
|
|
418
|
+
const listing = resultRows(await db.execute(sql `
|
|
419
|
+
SELECT id FROM public_listings
|
|
420
|
+
WHERE publisher_handle = ${publisherHandle} AND name = ${name} AND paused_at IS NULL
|
|
421
|
+
LIMIT 1`))[0];
|
|
422
|
+
if (!listing)
|
|
423
|
+
return null;
|
|
424
|
+
const sort = query.sort && REVIEW_SORTS.includes(query.sort) ? query.sort : 'helpful';
|
|
425
|
+
const limit = !query.limit || !Number.isFinite(query.limit)
|
|
426
|
+
? REVIEWS_DEFAULT_LIMIT
|
|
427
|
+
: Math.min(Math.max(Math.trunc(query.limit), 1), REVIEWS_MAX_LIMIT);
|
|
428
|
+
const offset = decodeOffsetCursor(query.cursor);
|
|
429
|
+
const where = [sql `listing_id = ${listing.id}`];
|
|
430
|
+
if (query.rating !== undefined && Number.isInteger(query.rating) && query.rating >= 1 && query.rating <= 5) {
|
|
431
|
+
where.push(sql `rating = ${query.rating}`);
|
|
432
|
+
}
|
|
433
|
+
const rows = resultRows(await db.execute(sql `
|
|
434
|
+
SELECT id, version, rating, title, body_html, author_display_name, verified_use, helpful_count, edited,
|
|
435
|
+
created_at, updated_at, publisher_display_name, reply_body_html, reply_created_at, reply_updated_at,
|
|
436
|
+
COUNT(*) OVER () AS total
|
|
437
|
+
FROM public_reviews
|
|
438
|
+
WHERE ${sql.join(where, sql ` AND `)}
|
|
439
|
+
ORDER BY ${reviewOrder(sort)}
|
|
440
|
+
LIMIT ${limit} OFFSET ${offset}`));
|
|
441
|
+
const total = rows.length > 0 ? num(rows[0].total) : 0;
|
|
442
|
+
return {
|
|
443
|
+
reviews: rows.map(toPublicReview),
|
|
444
|
+
total,
|
|
445
|
+
nextCursor: offset + rows.length < total ? encodeOffsetCursor(offset + rows.length) : null,
|
|
446
|
+
};
|
|
447
|
+
}
|
|
448
|
+
/** Every public listing's URL parts + last update, for the sitemap. */
|
|
449
|
+
export async function listPublicListingsForSitemap(max = 5000) {
|
|
450
|
+
const db = getPublicReaderDb();
|
|
451
|
+
const res = await db.execute(sql `
|
|
452
|
+
SELECT publisher_handle, name, updated_at FROM public_listings
|
|
453
|
+
WHERE paused_at IS NULL ORDER BY updated_at DESC LIMIT ${Math.min(Math.max(max, 1), 50_000)}`);
|
|
454
|
+
return resultRows(res)
|
|
455
|
+
.map((r) => ({ publisher: r.publisher_handle, name: r.name, updatedAt: iso(r.updated_at) }));
|
|
456
|
+
}
|
|
457
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHVibGljLWRpcmVjdG9yeS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9hcGkvcHVibGljLWRpcmVjdG9yeS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSwrQ0FBK0M7QUFDL0Msc0NBQXNDO0FBRXRDOzs7Ozs7Ozs7Ozs7Ozs7R0FlRztBQUVILE9BQU8sRUFBRSxHQUFHLEVBQVksTUFBTSxhQUFhLENBQUM7QUFFNUMsT0FBTyxFQUFFLG1CQUFtQixFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFDN0QsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLG1CQUFtQixDQUFDO0FBQ2xELE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUN0RCxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSw4QkFBOEIsQ0FBQztBQVVqRSxNQUFNLENBQUMsTUFBTSxlQUFlLEdBQTZCLENBQUMsV0FBVyxFQUFFLFFBQVEsRUFBRSxVQUFVLEVBQUUsU0FBUyxFQUFFLE1BQU0sRUFBRSxRQUFRLENBQUMsQ0FBQztBQUkxSCxNQUFNLENBQUMsTUFBTSxlQUFlLEdBQWtDLENBQUMsVUFBVSxFQUFFLFVBQVUsRUFBRSxXQUFXLEVBQUUsWUFBWSxDQUFDLENBQUM7QUFFbEgsc0ZBQXNGO0FBQ3RGLE1BQU0sQ0FBQyxNQUFNLG9CQUFvQixHQUFHLEdBQUcsQ0FBQztBQUV4Qyx1RUFBdUU7QUFDdkUsTUFBTSxDQUFDLE1BQU0sMEJBQTBCLEdBQUcsR0FBRyxDQUFDO0FBQzlDLE1BQU0sQ0FBQyxNQUFNLHVCQUF1QixHQUFHLEVBQUUsQ0FBQztBQUMxQyxNQUFNLENBQUMsTUFBTSxtQkFBbUIsR0FBRyxFQUFFLENBQUM7QUFxSHRDLE1BQU0sQ0FBQyxNQUFNLFlBQVksR0FBMEIsQ0FBQyxTQUFTLEVBQUUsUUFBUSxFQUFFLFNBQVMsRUFBRSxRQUFRLENBQUMsQ0FBQztBQUM5RixNQUFNLENBQUMsTUFBTSxxQkFBcUIsR0FBRyxFQUFFLENB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Q0FBQztBQUVELHVFQUF1RTtBQUN2RSxNQUFNLENBQUMsS0FBSyxVQUFVLDRCQUE0QixDQUFDLEdBQUcsR0FBRyxJQUFJO0lBQzNELE1BQU0sRUFBRSxHQUFHLGlCQUFpQixFQUFFLENBQUM7SUFDL0IsTUFBTSxHQUFHLEdBQUcsTUFBTSxFQUFFLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQTs7OERBRTRCLElBQUksQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxDQUFDLEVBQUUsTUFBTSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQ2xHLE9BQU8sVUFBVSxDQUF3RSxHQUFHLENBQUM7U0FDMUYsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLEVBQUUsU0FBUyxFQUFFLENBQUMsQ0FBQyxnQkFBZ0IsRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDLElBQUksRUFBRSxTQUFTLEVBQUUsR0FBRyxDQUFDLENBQUMsQ0FBQyxVQUFVLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztBQUNqRyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQ29weXJpZ2h0IDIwMjYgUGlwZWxpbmUgQnVpbGRlciBDb250cmlidXRvcnNcbi8vIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBcGFjaGUtMi4wXG5cbi8qKlxuICogUXVlcmllcyBiZWhpbmQgdGhlIGFub255bW91cyBwdWJsaWMgcGx1Z2luIGRpcmVjdG9yeVxuICogKGRvY3MvcGx1Z2luLXB1Ymxpc2hpbmcubWQpLlxuICpcbiAqIEV2ZXJ5IHF1ZXJ5IGhlcmUgcmVhZHMgT05MWSB0aGUgYHB1YmxpY19saXN0aW5nc2AsIGBwdWJsaWNfbGlzdGVkX3ZlcnNpb25zYCxcbiAqIGBwdWJsaWNfYWR2aXNvcmllc2AgYW5kIGBwdWJsaWNfcmV2aWV3c2Agdmlld3MsIHRocm91Z2ggdGhlIGBlY29zeXN0ZW1fcHVibGljX3JlYWRlcmBcbiAqIGNvbm5lY3Rpb24gKHtAbGluayBnZXRQdWJsaWNSZWFkZXJEYn0pLiBUaG9zZSB2aWV3cyBhbHJlYWR5IGZpbHRlciB0byBwdWJsaWNcbiAqIHJvd3MgKGxpc3RlZC91bm1haW50YWluZWQgbGlzdGluZ3Mgb2Ygbm9uLXN1c3BlbmRlZCBwdWJsaXNoZXJzLCBub24tcGF1c2VkXG4gKiB2ZXJzaW9ucywgcHVibGlzaGVkIGFkdmlzb3JpZXMpIGFuZCBwcm9qZWN0IHB1YmxpYyBjb2x1bW5zIG9ubHksIHNvIG5vdGhpbmdcbiAqIGhlcmUgbmVlZHMg4oCUIG9yIGhhcyDigJQgYSB0ZW5hbnQgY29udGV4dC5cbiAqXG4gKiBTZWFyY2g6IFBvc3RncmVzIGZ1bGwtdGV4dCAoYHNlYXJjaF92ZWN0b3JgLCB3ZWlnaHRlZCBuYW1lIEEgLyBrZXl3b3JkcyBhbmRcbiAqIGNhdGVnb3J5IEIgLyBzdW1tYXJ5IEMgLyBSRUFETUUgRCwgYGVuZ2xpc2hgIGNvbmZpZykgT1IgYSB0cmlncmFtIG1hdGNoIG9uIHRoZVxuICogbmFtZSAodHlwbyB0b2xlcmFuY2UpLCByYW5rZWQgYnkgYHRzX3JhbmtgICsgbmFtZSBzaW1pbGFyaXR5LCBibGVuZGVkIHdpdGggdGhlXG4gKiBCYXllc2lhbiByYXRpbmcgYW5kIGluc3RhbGwgY291bnQgd2hlbiBwcmVzZW50LiBQYXVzZWQgbGlzdGluZ3MgYXJlIGhpZGRlbi5cbiAqL1xuXG5pbXBvcnQgeyBzcWwsIHR5cGUgU1FMIH0gZnJvbSAnZHJpenpsZS1vcm0nO1xuXG5pbXBvcnQgeyBhZHZpc29yeVJhbmdlQ292ZXJzIH0gZnJvbSAnLi9wbHVnaW4tcmVzb2x1dGlvbi5qcyc7XG5pbXBvcnQgeyBjb21wYXJlU2VtdmVyIH0gZnJvbSAnLi9zZW12ZXItcmFuZ2UuanMnO1xuaW1wb3J0IHsgcmVzdWx0Um93cyB9IGZyb20gJy4uL2RhdGFiYXNlL3BnLXJlc3VsdC5qcyc7XG5pbXBvcnQgeyBnZXRQdWJsaWNSZWFkZXJEYiB9IGZyb20gJy4uL2RhdGFiYXNlL3B1YmxpYy1yZWFkZXIuanMnO1xuXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuLy8gUHVibGljIGNvbnRyYWN0IChtaXJyb3JzIGZyb250ZW5kL3NyYy9saWIvcHVibGljLWRpcmVjdG9yeS90eXBlcy50cylcbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cbmV4cG9ydCB0eXBlIERpcmVjdG9yeVRydXN0VGllciA9ICdvZmZpY2lhbCcgfCAndmVyaWZpZWQnIHwgJ2NvbW11bml0eScgfCAndW52ZXJpZmllZCc7XG5leHBvcnQgdHlwZSBEaXJlY3RvcnlJY29uS2luZCA9ICd2ZW5kb3InIHwgJ3VwbG9hZGVkJyB8ICdtb25vZ3JhbScgfCAnY2F0ZWdvcnknO1xuZXhwb3J0IHR5cGUgRGlyZWN0b3J5U29ydCA9ICdyZWxldmFuY2UnIHwgJ3JhdGluZycgfCAnaW5zdGFsbHMnIHwgJ3VwZGF0ZWQnIHwgJ25hbWUnIHwgJ2hlYWx0aCc7XG5cbmV4cG9ydCBjb25zdCBESVJFQ1RPUllfU09SVFM6IHJlYWRvbmx5IERpcmVjdG9yeVNvcnRbXSA9IFsncmVsZXZhbmNlJywgJ3JhdGluZycsICdpbnN0YWxscycsICd1cGRhdGVkJywgJ25hbWUnLCAnaGVhbHRoJ107XG5cbi8qKiBQZXItY29tcG9uZW50IGhlYWx0aCBzY29yZXM6IGB7IHNjb3JlOiAwLi4xIHwgbnVsbCAobWlzc2luZyksIHdlaWdodCB9YC4gKi9cbmV4cG9ydCB0eXBlIERpcmVjdG9yeUhlYWx0aEJyZWFrZG93biA9IFJlY29yZDxzdHJpbmcsIHsgc2NvcmU6IG51bWJlciB8IG51bGw7IHdlaWdodDogbnVtYmVyIH0+O1xuZXhwb3J0IGNvbnN0IERJUkVDVE9SWV9USUVSUzogcmVhZG9ubHkgRGlyZWN0b3J5VHJ1c3RUaWVyW10gPSBbJ29mZmljaWFsJywgJ3ZlcmlmaWVkJywgJ2NvbW11bml0eScsICd1bnZlcmlmaWVkJ107XG5cbi8qKiBNaW5pbXVtIGB3b3JkX3NpbWlsYXJpdHkocXVlcnksIG5hbWUpYCBmb3IgYSBmdXp6eSBuYW1lIG1hdGNoICh0eXBvIHRvbGVyYW5jZSkuICovXG5leHBvcnQgY29uc3QgRlVaWllfTkFNRV9USFJFU0hPTEQgPSAwLjM7XG5cbi8qKiBNYXggcXVlcnkgbGVuZ3RoIGFjY2VwdGVkIChsb25nZXIgaXMgdHJ1bmNhdGVkLCBuZXZlciBhbiBlcnJvcikuICovXG5leHBvcnQgY29uc3QgRElSRUNUT1JZX01BWF9RVUVSWV9MRU5HVEggPSAxMDA7XG5leHBvcnQgY29uc3QgRElSRUNUT1JZX0RFRkFVTFRfTElNSVQgPSAyNDtcbmV4cG9ydCBjb25zdCBESVJFQ1RPUllfTUFYX0xJTUlUID0gNjA7XG5cbmV4cG9ydCBpbnRlcmZhY2UgRGlyZWN0b3J5U2VhcmNoUGFyYW1zIHtcbiAgcT86IHN0cmluZztcbiAgY2F0ZWdvcnk/OiBzdHJpbmc7XG4gIHRpZXI/OiBEaXJlY3RvcnlUcnVzdFRpZXI7XG4gIGxpY2Vuc2U/OiBzdHJpbmc7XG4gIGNvbXB1dGVUeXBlPzogc3RyaW5nO1xuICBuZWVkc1NlY3JldHM/OiBib29sZWFuO1xuICBtaW5SYXRpbmc/OiBudW1iZXI7XG4gIHNvcnQ/OiBEaXJlY3RvcnlTb3J0O1xuICBjdXJzb3I/OiBzdHJpbmc7XG4gIGxpbWl0PzogbnVtYmVyO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIERpcmVjdG9yeUxpc3RpbmdDYXJkIHtcbiAgcHVibGlzaGVyOiB7IGhhbmRsZTogc3RyaW5nOyBkaXNwbGF5TmFtZTogc3RyaW5nOyB0aWVyOiBEaXJlY3RvcnlUcnVzdFRpZXIgfTtcbiAgbmFtZTogc3RyaW5nO1xuICBzdW1tYXJ5OiBzdHJpbmc7XG4gIGNhdGVnb3J5OiBzdHJpbmc7XG4gIGtleXdvcmRzOiBzdHJpbmdbXTtcbiAgbGF0ZXN0VmVyc2lvbjogc3RyaW5nO1xuICBsaWNlbnNlOiBzdHJpbmc7XG4gIGljb25Vcmw6IHN0cmluZyB8IG51bGw7XG4gIGljb25LaW5kOiBEaXJlY3RvcnlJY29uS2luZDtcbiAgaWNvbktleTogc3RyaW5nIHwgbnVsbDtcbiAgaWNvbkhleDogc3RyaW5nIHwgbnVsbDtcbiAgaWNvbkJhZGdlOiBzdHJpbmcgfCBudWxsO1xuICByYXRpbmc6IHsgc2NvcmU6IG51bWJlcjsgY291bnQ6IG51bWJlciB9IHwgbnVsbDtcbiAgaW5zdGFsbENvdW50OiBudW1iZXI7XG4gIC8qKiAw4oCTMTAwIGhlYWx0aCBzY29yZTsgbnVsbCB3aGVuIGZld2VyIHRoYW4gdGhyZWUgY29tcG9uZW50cyBhcmUga25vd24uICovXG4gIGhlYWx0aFNjb3JlOiBudW1iZXIgfCBudWxsO1xuICB1cGRhdGVkQXQ6IHN0cmluZztcbiAgc3RhdGU6ICdsaXN0ZWQnIHwgJ3VubWFpbnRhaW5lZCc7XG4gIGhpZ2hsaWdodD86IHsgbmFtZT86IHN0cmluZzsgc3VtbWFyeT86IHN0cmluZyB9O1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIERpcmVjdG9yeVNlYXJjaFJlc3VsdCB7XG4gIGl0ZW1zOiBEaXJlY3RvcnlMaXN0aW5nQ2FyZFtdO1xuICBmYWNldHM6IHtcbiAgICBjYXRlZ29yeTogUmVjb3JkPHN0cmluZywgbnVtYmVyPjtcbiAgICB0aWVyOiBSZWNvcmQ8c3RyaW5nLCBudW1iZXI+O1xuICAgIGxpY2Vuc2U6IFJlY29yZDxzdHJpbmcsIG51bWJlcj47XG4gICAgY29tcHV0ZVR5cGU6IFJlY29yZDxzdHJpbmcsIG51bWJlcj47XG4gICAgbmVlZHNTZWNyZXRzOiB7IHRydWU6IG51bWJlcjsgZmFsc2U6IG51bWJlciB9O1xuICB9O1xuICB0b3RhbDogbnVtYmVyO1xuICBuZXh0Q3Vyc29yOiBzdHJpbmcgfCBudWxsO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIERpcmVjdG9yeUNhdGVnb3J5U3VtbWFyeSB7XG4gIGlkOiBzdHJpbmc7XG4gIGNvdW50OiBudW1iZXI7XG4gIHRvcDogRGlyZWN0b3J5TGlzdGluZ0NhcmRbXTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBEaXJlY3RvcnlMaXN0aW5nVmVyc2lvbiB7XG4gIHZlcnNpb246IHN0cmluZztcbiAgcHVibGlzaGVkQXQ6IHN0cmluZztcbiAgYnJlYWtpbmc6IGJvb2xlYW47XG4gIGRlcHJlY2F0ZWQ6IGJvb2xlYW47XG4gIGRlcHJlY2F0aW9uTWVzc2FnZTogc3RyaW5nIHwgbnVsbDtcbiAgeWFua2VkOiBib29sZWFuO1xuICBjaGFuZ2Vsb2c6IHN0cmluZyB8IG51bGw7XG4gIHZ1bG5Dcml0aWNhbDogbnVtYmVyIHwgbnVsbDtcbiAgdnVsbkhpZ2g6IG51bWJlciB8IG51bGw7XG4gIHNjYW5uZWRBdDogc3RyaW5nIHwgbnVsbDtcbiAgLyoqIElkcyBvZiB0aGUgcHVibGlzaGVkIGFkdmlzb3JpZXMgd2hvc2UgcmFuZ2UgY292ZXJzIHRoaXMgdmVyc2lvbi4gKi9cbiAgYWR2aXNvcnlJZHM6IHN0cmluZ1tdO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIERpcmVjdG9yeUxpc3RpbmdEZXRhaWwgZXh0ZW5kcyBEaXJlY3RvcnlMaXN0aW5nQ2FyZCB7XG4gIHJlYWRtZUh0bWw6IHN0cmluZyB8IG51bGw7XG4gIGRlc2NyaXB0aW9uOiBzdHJpbmc7XG4gIGhvbWVwYWdlVXJsOiBzdHJpbmcgfCBudWxsO1xuICBzb3VyY2VVcmw6IHN0cmluZyB8IG51bGw7XG4gIHZlcnNpb25zOiBEaXJlY3RvcnlMaXN0aW5nVmVyc2lvbltdO1xuICBjb25maWd1cmF0aW9uOiB7XG4gICAgc2VjcmV0czogeyBuYW1lOiBzdHJpbmc7IHJlcXVpcmVkOiBib29sZWFuOyBkZXNjcmlwdGlvbjogc3RyaW5nIH1bXTtcbiAgICByZXF1aXJlZE1ldGFkYXRhOiBzdHJpbmdbXTtcbiAgICByZXF1aXJlZFZhcnM6IHN0cmluZ1tdO1xuICAgIGNvbXB1dGVUeXBlOiBzdHJpbmc7XG4gICAgcHJpbWFyeU91dHB1dERpcmVjdG9yeTogc3RyaW5nIHwgbnVsbDtcbiAgICBuZXR3b3JrRWdyZXNzOiBzdHJpbmdbXTtcbiAgICBwbHVnaW5UeXBlOiBzdHJpbmc7XG4gIH07XG4gIHN1cHBseUNoYWluOiB7XG4gICAgc2lnbmVkOiBib29sZWFuO1xuICAgIGRpZ2VzdDogc3RyaW5nIHwgbnVsbDtcbiAgICBpbWFnZVNvdXJjZTogc3RyaW5nIHwgbnVsbDtcbiAgICBzY2FubmVkQXQ6IHN0cmluZyB8IG51bGw7XG4gICAgdnVsbkNyaXRpY2FsOiBudW1iZXIgfCBudWxsO1xuICAgIHZ1bG5IaWdoOiBudW1iZXIgfCBudWxsO1xuICAgIHNib21Vcmw6IHN0cmluZyB8IG51bGw7XG4gIH07XG4gIGFkdmlzb3JpZXM6IHtcbiAgICBpZDogc3RyaW5nO1xuICAgIHNldmVyaXR5OiBzdHJpbmc7XG4gICAgc3VtbWFyeTogc3RyaW5nO1xuICAgIGFmZmVjdGVkUmFuZ2U6IHN0cmluZztcbiAgICBmaXhlZFZlcnNpb246IHN0cmluZyB8IG51bGw7XG4gICAgcHVibGlzaGVkQXQ6IHN0cmluZztcbiAgICAvKiogU2VydmVyLXNhbml0aXplZCBIVE1MICh0aGUgc3RvcmVkIHJlbmRlciBvZiB0aGUgZGV0YWlscyBtYXJrZG93bikuICovXG4gICAgZGV0YWlsc0h0bWw6IHN0cmluZyB8IG51bGw7XG4gICAgY3ZlSWRzOiBzdHJpbmdbXTtcbiAgfVtdO1xuICByYXRpbmdEaXN0cmlidXRpb246IFJlY29yZDwnMScgfCAnMicgfCAnMycgfCAnNCcgfCAnNScsIG51bWJlcj4gfCBudWxsO1xuICAvKiogVGhlIEJheWVzaWFuIHJhdGluZyBvdmVyIHJldmlld3Mgb2YgdGhlIGxhc3QgdHdvIG1pbm9yIHZlcnNpb25zLiAqL1xuICByZWNlbnRSYXRpbmc6IG51bWJlciB8IG51bGw7XG4gIGFjdGl2ZU9yZ0NvdW50OiBudW1iZXIgfCBudWxsO1xuICAvKiogUGVyLWNvbXBvbmVudCBoZWFsdGggc2NvcmVzIGJlaGluZCB7QGxpbmsgRGlyZWN0b3J5TGlzdGluZ0NhcmQuaGVhbHRoU2NvcmV9LiAqL1xuICBoZWFsdGhCcmVha2Rvd246IERpcmVjdG9yeUhlYWx0aEJyZWFrZG93biB8IG51bGw7XG4gIC8qKiAzMC1kYXkgcnVudGltZSBzdWNjZXNzIHJhdGUgKDAuLjEpLCBvciBudWxsIHdpdGggbm8gcnVucy4gKi9cbiAgc3VjY2Vzc1JhdGUzMGQ6IG51bWJlciB8IG51bGw7XG59XG5cbmV4cG9ydCB0eXBlIFJldmlld1NvcnQgPSAnaGVscGZ1bCcgfCAncmVjZW50JyB8ICdoaWdoZXN0JyB8ICdsb3dlc3QnO1xuZXhwb3J0IGNvbnN0IFJFVklFV19TT1JUUzogcmVhZG9ubHkgUmV2aWV3U29ydFtdID0gWydoZWxwZnVsJywgJ3JlY2VudCcsICdoaWdoZXN0JywgJ2xvd2VzdCddO1xuZXhwb3J0IGNvbnN0IFJFVklFV1NfREVGQVVMVF9MSU1JVCA9IDEwO1xuZXhwb3J0IGNvbnN0IFJFVklFV1NfTUFYX0xJTUlUID0gNTA7XG5cbmV4cG9ydCBpbnRlcmZhY2UgUHVibGljUmV2aWV3UmVwbHkge1xuICBib2R5SHRtbDogc3RyaW5nO1xuICBwdWJsaXNoZXJEaXNwbGF5TmFtZTogc3RyaW5nO1xuICBjcmVhdGVkQXQ6IHN0cmluZztcbiAgdXBkYXRlZEF0OiBzdHJpbmc7XG59XG5cbi8qKiBPbmUgcHVibGlzaGVkIHJldmlldyBhcyB0aGUgZGlyZWN0b3J5IHNob3dzIGl0OiBkaXNwbGF5IG5hbWUgb25seSwgbmV2ZXIgYW4gb3JnLiAqL1xuZXhwb3J0IGludGVyZmFjZSBQdWJsaWNSZXZpZXdJdGVtIHtcbiAgaWQ6IHN0cmluZztcbiAgcmF0aW5nOiBudW1iZXI7XG4gIHRpdGxlOiBzdHJpbmcgfCBudWxsO1xuICBib2R5SHRtbDogc3RyaW5nIHwgbnVsbDtcbiAgdmVyc2lvbjogc3RyaW5nIHwgbnVsbDtcbiAgLyoqIE51bGwgb25jZSB0aGUgYXV0aG9yJ3MgYWNjb3VudCB3YXMgZGVsZXRlZCAodGhlIHJldmlldyBpcyBhbm9ueW1pemVkKS4gKi9cbiAgYXV0aG9yOiB7IGRpc3BsYXlOYW1lOiBzdHJpbmcgfSB8IG51bGw7XG4gIHZlcmlmaWVkVXNlOiBib29sZWFuO1xuICBoZWxwZnVsQ291bnQ6IG51bWJlcjtcbiAgZWRpdGVkOiBib29sZWFuO1xuICBjcmVhdGVkQXQ6IHN0cmluZztcbiAgdXBkYXRlZEF0OiBzdHJpbmc7XG4gIHJlcGx5OiBQdWJsaWNSZXZpZXdSZXBseSB8IG51bGw7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgUHVibGljUmV2aWV3UGFnZSB7XG4gIHJldmlld3M6IFB1YmxpY1Jldmlld0l0ZW1bXTtcbiAgdG90YWw6IG51bWJlcjtcbiAgbmV4dEN1cnNvcjogc3RyaW5nIHwgbnVsbDtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBQdWJsaWNSZXZpZXdRdWVyeSB7XG4gIHNvcnQ/OiBSZXZpZXdTb3J0O1xuICAvKiogT25seSByZXZpZXdzIHdpdGggZXhhY3RseSB0aGlzIG1hbnkgc3RhcnMuICovXG4gIHJhdGluZz86IG51bWJlcjtcbiAgY3Vyc29yPzogc3RyaW5nO1xuICBsaW1pdD86IG51bWJlcjtcbn1cblxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbi8vIFJvdyBtYXBwaW5nXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG4vKiogQSBgcHVibGljX2xpc3RpbmdzYCByb3cgYXMgdGhlIHJhdyBxdWVyaWVzIHJldHVybiBpdCAoc25ha2VfY2FzZSkuICovXG5leHBvcnQgaW50ZXJmYWNlIFB1YmxpY0xpc3RpbmdSb3cge1xuICBpZDogc3RyaW5nO1xuICBwdWJsaXNoZXJfaGFuZGxlOiBzdHJpbmc7XG4gIHB1Ymxpc2hlcl9kaXNwbGF5X25hbWU6IHN0cmluZztcbiAgcHVibGlzaGVyX3RpZXI6IERpcmVjdG9yeVRydXN0VGllcjtcbiAgbmFtZTogc3RyaW5nO1xuICBjYXRlZ29yeTogc3RyaW5nO1xuICBzdW1tYXJ5OiBzdHJpbmcgfCBudWxsO1xuICBkZXNjcmlwdGlvbjogc3RyaW5nIHwgbnVsbDtcbiAgcmVhZG1lX2h0bWw6IHN0cmluZyB8IG51bGw7XG4gIGxpY2Vuc2U6IHN0cmluZyB8IG51bGw7XG4gIGhvbWVwYWdlX3VybDogc3RyaW5nIHwgbnVsbDtcbiAgc291cmNlX3VybDogc3RyaW5nIHwgbnVsbDtcbiAgaWNvbjogeyBrZXk6IHN0cmluZzsgYmFkZ2U/OiBzdHJpbmcgfSB8IG51bGw7XG4gIHVwbG9hZGVkX2ljb246IHsga2V5MjU2OiBzdHJpbmc7IGtleTY0OiBzdHJpbmcgfSB8IG51bGw7XG4gIGtleXdvcmRzOiBzdHJpbmdbXSB8IG51bGw7XG4gIGxhdGVzdF92ZXJzaW9uOiBzdHJpbmcgfCBudWxsO1xuICB1cGRhdGVkX2F0OiBEYXRlIHwgc3RyaW5nO1xuICByYXRpbmdfYmF5ZXM6IG51bWJlciB8IHN0cmluZyB8IG51bGw7XG4gIHJhdGluZ19jb3VudDogbnVtYmVyIHwgc3RyaW5nO1xuICByYXRpbmdfZGlzdDogUmVjb3JkPHN0cmluZywgbnVtYmVyPiB8IG51bGw7XG4gIHJlY2VudF9yYXRpbmc/OiBudW1iZXIgfCBzdHJpbmcgfCBudWxsO1xuICBpbnN0YWxsX2NvdW50OiBudW1iZXIgfCBzdHJpbmc7XG4gIGFjdGl2ZV9vcmdfY291bnQ6IG51bWJlciB8IHN0cmluZyB8IG51bGw7XG4gIGhlYWx0aF9zY29yZT86IG51bWJlciB8IHN0cmluZyB8IG51bGw7XG4gIGhlYWx0aF9icmVha2Rvd24/OiBEaXJlY3RvcnlIZWFsdGhCcmVha2Rvd24gfCBudWxsO1xuICBzdWNjZXNzX3JhdGVfMzBkPzogbnVtYmVyIHwgc3RyaW5nIHwgbnVsbDtcbiAgc3RhdGU6ICdsaXN0ZWQnIHwgJ3VubWFpbnRhaW5lZCc7XG59XG5cbmZ1bmN0aW9uIG51bSh2OiBudW1iZXIgfCBzdHJpbmcgfCBudWxsIHwgdW5kZWZpbmVkKTogbnVtYmVyIHtcbiAgY29uc3QgbiA9IHR5cGVvZiB2ID09PSAnbnVtYmVyJyA/IHYgOiBOdW1iZXIucGFyc2VGbG9hdChTdHJpbmcodiA/PyAnMCcpKTtcbiAgcmV0dXJuIE51bWJlci5pc0Zpbml0ZShuKSA/IG4gOiAwO1xufVxuXG5mdW5jdGlvbiBpc28odjogRGF0ZSB8IHN0cmluZyB8IG51bGwgfCB1bmRlZmluZWQpOiBzdHJpbmcge1xuICBpZiAoIXYpIHJldHVybiAnJztcbiAgcmV0dXJuIHYgaW5zdGFuY2VvZiBEYXRlID8gdi50b0lTT1N0cmluZygpIDogbmV3IERhdGUodikudG9JU09TdHJpbmcoKTtcbn1cblxuLyoqXG4gKiBUaGUgaWNvbiBmYWxsYmFjayBjaGFpbjogdXBsb2FkZWQgKGlmIHRoZSB0aWVyIG1heSB1cGxvYWQpIOKGkiBjdXJhdGVkXG4gKiB2ZW5kb3Iga2V5IChPZmZpY2lhbCwgYW5kIFZlcmlmaWVkIHB1Ymxpc2hlcnMgZm9yIG1hcmtzIHRoZXkgb3duIOKAlCBvd25lcnNoaXBcbiAqIGlzIGNoZWNrZWQgd2hlbiB0aGUgaWNvbiBpcyBhcHByb3ZlZCkg4oaSIG1vbm9ncmFtLiBDb21tdW5pdHkgYW5kIGFub255bW91c1xuICogbGlzdGluZ3MgY2FuIG5ldmVyIHNob3cgYSBjdXJhdGVkIHZlbmRvciBtYXJrLlxuICovXG5leHBvcnQgZnVuY3Rpb24gcmVzb2x2ZUxpc3RpbmdJY29uKHJvdzogUGljazxQdWJsaWNMaXN0aW5nUm93LCAncHVibGlzaGVyX3RpZXInIHwgJ2ljb24nIHwgJ3VwbG9hZGVkX2ljb24nPik6IFBpY2s8XG4gIERpcmVjdG9yeUxpc3RpbmdDYXJkLCAnaWNvbktpbmQnIHwgJ2ljb25VcmwnIHwgJ2ljb25LZXknIHwgJ2ljb25CYWRnZScgfCAnaWNvbkhleCdcbj4ge1xuICBjb25zdCBub25lID0geyBpY29uVXJsOiBudWxsLCBpY29uS2V5OiBudWxsLCBpY29uQmFkZ2U6IG51bGwsIGljb25IZXg6IG51bGwgfTtcbiAgaWYgKHJvdy51cGxvYWRlZF9pY29uPy5rZXkyNTYpIHtcbiAgICByZXR1cm4geyAuLi5ub25lLCBpY29uS2luZDogJ3VwbG9hZGVkJywgaWNvblVybDogYC9hcGkvcHVibGljL3BsdWdpbnMvaWNvbnMvJHtlbmNvZGVVUklDb21wb25lbnQocm93LnVwbG9hZGVkX2ljb24ua2V5MjU2KX1gIH07XG4gIH1cbiAgY29uc3QgY3VyYXRlZEFsbG93ZWQgPSByb3cucHVibGlzaGVyX3RpZXIgPT09ICdvZmZpY2lhbCcgfHwgcm93LnB1Ymxpc2hlcl90aWVyID09PSAndmVyaWZpZWQnO1xuICBpZiAoY3VyYXRlZEFsbG93ZWQgJiYgcm93Lmljb24/LmtleSkge1xuICAgIHJldHVybiB7IC4uLm5vbmUsIGljb25LaW5kOiAndmVuZG9yJywgaWNvbktleTogcm93Lmljb24ua2V5LCBpY29uQmFkZ2U6IHJvdy5pY29uLmJhZGdlID8/IG51bGwgfTtcbiAgfVxuICByZXR1cm4geyAuLi5ub25lLCBpY29uS2luZDogJ21vbm9ncmFtJyB9O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gdG9MaXN0aW5nQ2FyZChyb3c6IFB1YmxpY0xpc3RpbmdSb3cpOiBEaXJlY3RvcnlMaXN0aW5nQ2FyZCB7XG4gIGNvbnN0IHJhdGluZ0NvdW50ID0gbnVtKHJvdy5yYXRpbmdfY291bnQpO1xuICByZXR1cm4ge1xuICAgIHB1Ymxpc2hlcjogeyBoYW5kbGU6IHJvdy5wdWJsaXNoZXJfaGFuZGxlLCBkaXNwbGF5TmFtZTogcm93LnB1Ymxpc2hlcl9kaXNwbGF5X25hbWUsIHRpZXI6IHJvdy5wdWJsaXNoZXJfdGllciB9LFxuICAgIG5hbWU6IHJvdy5uYW1lLFxuICAgIHN1bW1hcnk6IHJvdy5zdW1tYXJ5ID8/ICcnLFxuICAgIGNhdGVnb3J5OiByb3cuY2F0ZWdvcnksXG4gICAga2V5d29yZHM6IHJvdy5rZXl3b3JkcyA/PyBbXSxcbiAgICBsYXRlc3RWZXJzaW9uOiByb3cubGF0ZXN0X3ZlcnNpb24gPz8gJycsXG4gICAgbGljZW5zZTogcm93LmxpY2Vuc2UgPz8gJycsXG4gICAgLi4ucmVzb2x2ZUxpc3RpbmdJY29uKHJvdyksXG4gICAgcmF0aW5nOiByYXRpbmdDb3VudCA+IDAgJiYgcm93LnJhdGluZ19iYXllcyAhPSBudWxsID8geyBzY29yZTogTWF0aC5yb3VuZChudW0ocm93LnJhdGluZ19iYXllcykgKiAxMDApIC8gMTAwLCBjb3VudDogcmF0aW5nQ291bnQgfSA6IG51bGwsXG4gICAgaW5zdGFsbENvdW50OiBudW0ocm93Lmluc3RhbGxfY291bnQpLFxuICAgIGhlYWx0aFNjb3JlOiByb3cuaGVhbHRoX3Njb3JlID09IG51bGwgPyBudWxsIDogTWF0aC5yb3VuZChudW0ocm93LmhlYWx0aF9zY29yZSkpLFxuICAgIHVwZGF0ZWRBdDogaXNvKHJvdy51cGRhdGVkX2F0KSxcbiAgICBzdGF0ZTogcm93LnN0YXRlLFxuICB9O1xufVxuXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuLy8gU2VhcmNoXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG4vKiogTm9ybWFsaXplIHRoZSB1c2VyJ3MgcXVlcnk6IGNvbGxhcHNlIHdoaXRlc3BhY2UsIGNhcCB0aGUgbGVuZ3RoLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG5vcm1hbGl6ZVF1ZXJ5KHE6IHN0cmluZyB8IHVuZGVmaW5lZCk6IHN0cmluZyB7XG4gIHJldHVybiAocSA/PyAnJykucmVwbGFjZSgvXFxzKy9nLCAnICcpLnRyaW0oKS5zbGljZSgwLCBESVJFQ1RPUllfTUFYX1FVRVJZX0xFTkdUSCk7XG59XG5cbi8qKiBTZWFyY2ggdGVybXMgZm9yIGhpZ2hsaWdodGluZzogd29yZHMgb2Yg4omlIDIgY2hhcmFjdGVycywgcmVnZXgtZXNjYXBlZC4gKi9cbmZ1bmN0aW9uIGhpZ2hsaWdodFRlcm1zKHE6IHN0cmluZyk6IHN0cmluZ1tdIHtcbiAgcmV0dXJuIFsuLi5uZXcgU2V0KHEudG9Mb3dlckNhc2UoKS5zcGxpdCgvW15hLXowLTkuXy1dKy8pLmZpbHRlcigodCkgPT4gdC5sZW5ndGggPj0gMikpXVxuICAgIC5tYXAoKHQpID0+IHQucmVwbGFjZSgvWy4qKz9eJHt9KCl8W1xcXVxcXFxdL2csICdcXFxcJCYnKSk7XG59XG5cbi8qKlxuICogV3JhcCBtYXRjaGVkIHRlcm1zIGluIGA8bWFyaz5gLiBUaGUgZnJvbnRlbmQgcmVuZGVycyBldmVyeXRoaW5nIGV4Y2VwdCB0aGVcbiAqIGA8bWFyaz5gIG1hcmtlcnMgYXMgVEVYVCAobmV2ZXIgSFRNTCksIHNvIHRoZSBzb3VyY2UgdGV4dCBpcyBub3QgZXNjYXBlZCBoZXJlLlxuICogUmV0dXJucyB1bmRlZmluZWQgd2hlbiBub3RoaW5nIG1hdGNoZWQgKHRoZSBjYXJkIHRoZW4gcmVuZGVycyBwbGFpbiB0ZXh0KS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGhpZ2hsaWdodFRleHQodGV4dDogc3RyaW5nLCBxOiBzdHJpbmcpOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICBjb25zdCB0ZXJtcyA9IGhpZ2hsaWdodFRlcm1zKHEpO1xuICBpZiAoIXRleHQgfHwgdGVybXMubGVuZ3RoID09PSAwKSByZXR1cm4gdW5kZWZpbmVkO1xuICBjb25zdCByZSA9IG5ldyBSZWdFeHAoYCgke3Rlcm1zLmpvaW4oJ3wnKX0pYCwgJ2dpJyk7XG4gIGlmICghcmUudGVzdCh0ZXh0KSkgcmV0dXJuIHVuZGVmaW5lZDtcbiAgcmV0dXJuIHRleHQucmVwbGFjZShyZSwgJzxtYXJrPiQxPC9tYXJrPicpO1xufVxuXG4vKiogT3BhcXVlIGN1cnNvcjogYW4gb2Zmc2V0LCBiYXNlNjR1cmwtZW5jb2RlZCBzbyBjbGllbnRzIGRvbid0IGRlcGVuZCBvbiBpdC4gKi9cbmV4cG9ydCBmdW5jdGlvbiBlbmNvZGVPZmZzZXRDdXJzb3Iob2Zmc2V0OiBudW1iZXIpOiBzdHJpbmcge1xuICByZXR1cm4gQnVmZmVyLmZyb20oSlNPTi5zdHJpbmdpZnkoeyBvOiBvZmZzZXQgfSkpLnRvU3RyaW5nKCdiYXNlNjR1cmwnKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGRlY29kZU9mZnNldEN1cnNvcihjdXJzb3I6IHN0cmluZyB8IHVuZGVmaW5lZCk6IG51bWJlciB7XG4gIGlmICghY3Vyc29yKSByZXR1cm4gMDtcbiAgdHJ5IHtcbiAgICBjb25zdCBvID0gKEpTT04ucGFyc2UoQnVmZmVyLmZyb20oY3Vyc29yLCAnYmFzZTY0dXJsJykudG9TdHJpbmcoJ3V0ZjgnKSkgYXMgeyBvPzogdW5rbm93biB9KS5vO1xuICAgIHJldHVybiB0eXBlb2YgbyA9PT0gJ251bWJlcicgJiYgTnVtYmVyLmlzSW50ZWdlcihvKSAmJiBvID49IDAgJiYgbyA8PSAxMF8wMDAgPyBvIDogMDtcbiAgfSBjYXRjaCB7XG4gICAgcmV0dXJuIDA7XG4gIH1cbn1cblxuZnVuY3Rpb24gY2xhbXBMaW1pdChsaW1pdDogbnVtYmVyIHwgdW5kZWZpbmVkKTogbnVtYmVyIHtcbiAgaWYgKCFsaW1pdCB8fCAhTnVtYmVyLmlzRmluaXRlKGxpbWl0KSkgcmV0dXJuIERJUkVDVE9SWV9ERUZBVUxUX0xJTUlUO1xuICByZXR1cm4gTWF0aC5taW4oTWF0aC5tYXgoTWF0aC50cnVuYyhsaW1pdCksIDEpLCBESVJFQ1RPUllfTUFYX0xJTUlUKTtcbn1cblxuLyoqXG4gKiBUaGUgZmlsdGVyZWQgYmFzZSBzZXQgYXMgYSBDVEUgYm9keS4gRXZlcnkgc2VhcmNoLCBmYWNldCBhbmQgY2F0ZWdvcnkgcXVlcnlcbiAqIHJlYWRzIHRocm91Z2ggdGhpcywgc28gdGhleSBjYW4ndCBkaXNhZ3JlZSBhYm91dCB3aGF0J3MgdmlzaWJsZS5cbiAqL1xuZnVuY3Rpb24gYmFzZVF1ZXJ5KHBhcmFtczogRGlyZWN0b3J5U2VhcmNoUGFyYW1zLCBxOiBzdHJpbmcpOiBTUUwge1xuICBjb25zdCB3aGVyZTogU1FMW10gPSBbc3FsYGwucGF1c2VkX2F0IElTIE5VTExgXTtcbiAgaWYgKHEpIHtcbiAgICAvLyBGdWxsIHRleHQsIE9SIGEgZnV6enkgbWF0Y2ggYWdhaW5zdCB0aGUgYmVzdC1tYXRjaGluZyBQQVJUIG9mIHRoZSBuYW1lXG4gICAgLy8gKHdvcmRfc2ltaWxhcml0eTogXCJ0ZXJhZnJvbVwiIOKGkiB0ZXJyYWZvcm0tcGxhbiBzY29yZXMgMC4zNiwgd2hpbGUgdW5yZWxhdGVkXG4gICAgLy8gd29yZHMgc3RheSDiiaQgMC4yIOKAlCB3aG9sZS1uYW1lIHNpbWlsYXJpdHkoKSBkaWx1dGVzIGEgbG9uZyBuYW1lIGJlbG93IGFueVxuICAgIC8vIHVzZWZ1bCB0aHJlc2hvbGQpLiBFeHBsaWNpdCBmdW5jdGlvbiwgbm90IHRoZSBgPCVgIG9wZXJhdG9yLCBzbyB0aGUgY3V0LW9mZlxuICAgIC8vIGRvZXNuJ3QgZGVwZW5kIG9uIGEgc2Vzc2lvbiBHVUMgcGdib3VuY2VyIGNhbid0IGNhcnJ5LiBBIHNlcSBzY2FuIG92ZXIgdGhlXG4gICAgLy8gcHVibGljIGxpc3RpbmdzICh0aG91c2FuZHMgb2Ygcm93cyBhdCBtb3N0KSBpcyBmaW5lLlxuICAgIHdoZXJlLnB1c2goc3FsYChsLnNlYXJjaF92ZWN0b3IgQEAgd2Vic2VhcmNoX3RvX3RzcXVlcnkoJ2VuZ2xpc2gnLCAke3F9KSBPUiB3b3JkX3NpbWlsYXJpdHkoJHtxfSwgbC5uYW1lKSA+PSAke0ZVWlpZX05BTUVfVEhSRVNIT0xEfSBPUiBsLm5hbWUgSUxJS0UgJHtgJSR7cS5yZXBsYWNlKC9bXFxcXCVfXS9nLCAnXFxcXCQmJyl9JWB9KWApO1xuICB9XG4gIGlmIChwYXJhbXMuY2F0ZWdvcnkpIHdoZXJlLnB1c2goc3FsYGwuY2F0ZWdvcnkgPSAke3BhcmFtcy5jYXRlZ29yeX1gKTtcbiAgaWYgKHBhcmFtcy50aWVyKSB3aGVyZS5wdXNoKHNxbGBsLnB1Ymxpc2hlcl90aWVyID0gJHtwYXJhbXMudGllcn1gKTtcbiAgaWYgKHBhcmFtcy5saWNlbnNlKSB3aGVyZS5wdXNoKHNxbGBsLmxpY2Vuc2UgPSAke3BhcmFtcy5saWNlbnNlfWApO1xuICBpZiAocGFyYW1zLmNvbXB1dGVUeXBlKSB3aGVyZS5wdXNoKHNxbGB2LmNvbXB1dGVfdHlwZSA9ICR7cGFyYW1zLmNvbXB1dGVUeXBlfWApO1xuICBpZiAocGFyYW1zLm5lZWRzU2VjcmV0cyAhPT0gdW5kZWZpbmVkKSB7XG4gICAgd2hlcmUucHVzaChwYXJhbXMubmVlZHNTZWNyZXRzXG4gICAgICA/IHNxbGBqc29uYl9hcnJheV9sZW5ndGgoQ09BTEVTQ0Uodi5zZWNyZXRzLCAnW10nOjpqc29uYikpID4gMGBcbiAgICAgIDogc3FsYGpzb25iX2FycmF5X2xlbmd0aChDT0FMRVNDRSh2LnNlY3JldHMsICdbXSc6Ompzb25iKSkgPSAwYCk7XG4gIH1cbiAgaWYgKHBhcmFtcy5taW5SYXRpbmcgIT09IHVuZGVmaW5lZCAmJiBOdW1iZXIuaXNGaW5pdGUocGFyYW1zLm1pblJhdGluZykpIHtcbiAgICB3aGVyZS5wdXNoKHNxbGBsLnJhdGluZ19iYXllcyA+PSAke3BhcmFtcy5taW5SYXRpbmd9YCk7XG4gIH1cbiAgY29uc3QgcmFuayA9IHFcbiAgICA/IHNxbGAodHNfcmFuayhsLnNlYXJjaF92ZWN0b3IsIHdlYnNlYXJjaF90b190c3F1ZXJ5KCdlbmdsaXNoJywgJHtxfSkpICsgd29yZF9zaW1pbGFyaXR5KCR7cX0sIGwubmFtZSkpYFxuICAgIDogc3FsYDA6OnJlYWxgO1xuICByZXR1cm4gc3FsYFxuICAgIFNFTEVDVCBsLmlkLCBsLnB1Ymxpc2hlcl9oYW5kbGUsIGwucHVibGlzaGVyX2Rpc3BsYXlfbmFtZSwgbC5wdWJsaXNoZXJfdGllciwgbC5uYW1lLCBsLmNhdGVnb3J5LFxuICAgICAgICAgICBsLnN1bW1hcnksIGwuZGVzY3JpcHRpb24sIGwucmVhZG1lX2h0bWwsIGwubGljZW5zZSwgbC5ob21lcGFnZV91cmwsIGwuc291cmNlX3VybCwgbC5pY29uLFxuICAgICAgICAgICBsLnVwbG9hZGVkX2ljb24sIGwua2V5d29yZHMsIGwubGF0ZXN0X3ZlcnNpb24sIGwudXBkYXRlZF9hdCwgbC5yYXRpbmdfYmF5ZXMsIGwucmF0aW5nX2NvdW50LFxuICAgICAgICAgICBsLnJhdGluZ19kaXN0LCBsLmluc3RhbGxfY291bnQsIGwuYWN0aXZlX29yZ19jb3VudCwgbC5oZWFsdGhfc2NvcmUsIGwuc3RhdGUsXG4gICAgICAgICAgIHYuY29tcHV0ZV90eXBlLFxuICAgICAgICAgICAoanNvbmJfYXJyYXlfbGVuZ3RoKENPQUxFU0NFKHYuc2VjcmV0cywgJ1tdJzo6anNvbmIpKSA+IDApIEFTIG5lZWRzX3NlY3JldHMsXG4gICAgICAgICAgICR7cmFua30gQVMgcmFua1xuICAgICAgRlJPTSBwdWJsaWNfbGlzdGluZ3MgbFxuICAgICAgTEVGVCBKT0lOIExBVEVSQUwgKFxuICAgICAgICBTRUxFQ1QgcHYuY29tcHV0ZV90eXBlLCBwdi5zZWNyZXRzXG4gICAgICAgICAgRlJPTSBwdWJsaWNfbGlzdGVkX3ZlcnNpb25zIHB2XG4gICAgICAgICBXSEVSRSBwdi5saXN0aW5nX2lkID0gbC5pZCBBTkQgcHYudmVyc2lvbiA9IGwubGF0ZXN0X3ZlcnNpb24gQU5EIE5PVCBwdi55YW5rZWRcbiAgICAgICAgIExJTUlUIDFcbiAgICAgICkgdiBPTiB0cnVlXG4gICAgIFdIRVJFICR7c3FsLmpvaW4od2hlcmUsIHNxbGAgQU5EIGApfWA7XG59XG5cbmZ1bmN0aW9uIG9yZGVyQnkoc29ydDogRGlyZWN0b3J5U29ydCwgaGFzUXVlcnk6IGJvb2xlYW4pOiBTUUwge1xuICBzd2l0Y2ggKHNvcnQgPT09ICdyZWxldmFuY2UnICYmICFoYXNRdWVyeSA/ICd1cGRhdGVkJyA6IHNvcnQpIHtcbiAgICBjYXNlICdyZWxldmFuY2UnOlxuICAgICAgLy8gVGV4dCByZWxldmFuY2UgZmlyc3QsIG51ZGdlZCBieSByYXRpbmcgYW5kIGFkb3B0aW9uIHNvIGVxdWFsIG1hdGNoZXNcbiAgICAgIC8vIGZhdm91ciBwcm92ZW4gcGx1Z2lucy5cbiAgICAgIHJldHVybiBzcWxgKHJhbmsgKiAoMSArIENPQUxFU0NFKHJhdGluZ19iYXllcywgMCkgLyAxMCkgKyBsbigxICsgaW5zdGFsbF9jb3VudCkgLyAyMCkgREVTQywgbmFtZSBBU0NgO1xuICAgIGNhc2UgJ3JhdGluZyc6XG4gICAgICByZXR1cm4gc3FsYHJhdGluZ19iYXllcyBERVNDIE5VTExTIExBU1QsIHJhdGluZ19jb3VudCBERVNDLCBuYW1lIEFTQ2A7XG4gICAgY2FzZSAnaW5zdGFsbHMnOlxuICAgICAgcmV0dXJuIHNxbGBpbnN0YWxsX2NvdW50IERFU0MsIG5hbWUgQVNDYDtcbiAgICBjYXNlICduYW1lJzpcbiAgICAgIHJldHVybiBzcWxgbmFtZSBBU0MsIHB1Ymxpc2hlcl9oYW5kbGUgQVNDYDtcbiAgICBjYXNlICdoZWFsdGgnOlxuICAgICAgcmV0dXJuIHNxbGBoZWFsdGhfc2NvcmUgREVTQyBOVUxMUyBMQVNULCBpbnN0YWxsX2NvdW50IERFU0MsIG5hbWUgQVNDYDtcbiAgICBjYXNlICd1cGRhdGVkJzpcbiAgICBkZWZhdWx0OlxuICAgICAgcmV0dXJuIHNxbGB1cGRhdGVkX2F0IERFU0MsIG5hbWUgQVNDYDtcbiAgfVxufVxuXG4vKiogU2VhcmNoIHRoZSBkaXJlY3Rvcnk6IG9uZSBwYWdlIG9mIGNhcmRzLCBmYWNldCBjb3VudHMsIHRvdGFsIGFuZCBuZXh0IGN1cnNvci4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBzZWFyY2hQdWJsaWNMaXN0aW5ncyhwYXJhbXM6IERpcmVjdG9yeVNlYXJjaFBhcmFtcyk6IFByb21pc2U8RGlyZWN0b3J5U2VhcmNoUmVzdWx0PiB7XG4gIGNvbnN0IGRiID0gZ2V0UHVibGljUmVhZGVyRGIoKTtcbiAgY29uc3QgcSA9IG5vcm1hbGl6ZVF1ZXJ5KHBhcmFtcy5xKTtcbiAgY29uc3QgbGltaXQgPSBjbGFtcExpbWl0KHBhcmFtcy5saW1pdCk7XG4gIGNvbnN0IG9mZnNldCA9IGRlY29kZU9mZnNldEN1cnNvcihwYXJhbXMuY3Vyc29yKTtcbiAgY29uc3Qgc29ydCA9IHBhcmFtcy5zb3J0ICYmIERJUkVDVE9SWV9TT1JUUy5pbmNsdWRlcyhwYXJhbXMuc29ydCkgPyBwYXJhbXMuc29ydCA6ICdyZWxldmFuY2UnO1xuICBjb25zdCBiYXNlID0gYmFzZVF1ZXJ5KHBhcmFtcywgcSk7XG5cbiAgY29uc3QgW3BhZ2VSZXMsIGZhY2V0UmVzXSA9IGF3YWl0IFByb21pc2UuYWxsKFtcbiAgICBkYi5leGVjdXRlKHNxbGBcbiAgICAgIFdJVEggYmFzZSBBUyAoJHtiYXNlfSlcbiAgICAgIFNFTEVDVCBiYXNlLiosIENPVU5UKCopIE9WRVIgKCkgQVMgdG90YWxcbiAgICAgICAgRlJPTSBiYXNlXG4gICAgICAgT1JERVIgQlkgJHtvcmRlckJ5KHNvcnQsIHEgIT09ICcnKX1cbiAgICAgICBMSU1JVCAke2xpbWl0fSBPRkZTRVQgJHtvZmZzZXR9YCksXG4gICAgZGIuZXhlY3V0ZShzcWxgXG4gICAgICBXSVRIIGJhc2UgQVMgKCR7YmFzZX0pXG4gICAgICBTRUxFQ1QgY2F0ZWdvcnksIHB1Ymxpc2hlcl90aWVyLCBsaWNlbnNlLCBjb21wdXRlX3R5cGUsIG5lZWRzX3NlY3JldHMsXG4gICAgICAgICAgICAgR1JPVVBJTkcoY2F0ZWdvcnkpIEFTIGdfY2F0ZWdvcnksIEdST1VQSU5HKHB1Ymxpc2hlcl90aWVyKSBBUyBnX3RpZXIsXG4gICAgICAgICAgICAgR1JPVVBJTkcobGljZW5zZSkgQVMgZ19saWNlbnNlLCBHUk9VUElORyhjb21wdXRlX3R5cGUpIEFTIGdfY29tcHV0ZSxcbiAgICAgICAgICAgICBHUk9VUElORyhuZWVkc19zZWNyZXRzKSBBUyBnX3NlY3JldHMsXG4gICAgICAgICAgICAgQ09VTlQoKikgQVMgblxuICAgICAgICBGUk9NIGJhc2VcbiAgICAgICBHUk9VUCBCWSBHUk9VUElORyBTRVRTICgoY2F0ZWdvcnkpLCAocHVibGlzaGVyX3RpZXIpLCAobGljZW5zZSksIChjb21wdXRlX3R5cGUpLCAobmVlZHNfc2VjcmV0cykpYCksXG4gIF0pO1xuXG4gIGNvbnN0IHBhZ2UgPSByZXN1bHRSb3dzPFB1YmxpY0xpc3RpbmdSb3cgJiB7IHRvdGFsOiBudW1iZXIgfCBzdHJpbmcgfT4ocGFnZVJlcyk7XG4gIGNvbnN0IHRvdGFsID0gcGFnZS5sZW5ndGggPiAwID8gbnVtKHBhZ2VbMF0hLnRvdGFsKSA6IDA7XG4gIGNvbnN0IGl0ZW1zID0gcGFnZS5tYXAoKHJvdykgPT4ge1xuICAgIGNvbnN0IGNhcmQgPSB0b0xpc3RpbmdDYXJkKHJvdyk7XG4gICAgaWYgKHEpIHtcbiAgICAgIGNvbnN0IGhpZ2hsaWdodCA9IHsgbmFtZTogaGlnaGxpZ2h0VGV4dChjYXJkLm5hbWUsIHEpLCBzdW1tYXJ5OiBoaWdobGlnaHRUZXh0KGNhcmQuc3VtbWFyeSwgcSkgfTtcbiAgICAgIGlmIChoaWdobGlnaHQubmFtZSB8fCBoaWdobGlnaHQuc3VtbWFyeSkgY2FyZC5oaWdobGlnaHQgPSBoaWdobGlnaHQ7XG4gICAgfVxuICAgIHJldHVybiBjYXJkO1xuICB9KTtcblxuICBjb25zdCBmYWNldHM6IERpcmVjdG9yeVNlYXJjaFJlc3VsdFsnZmFjZXRzJ10gPSB7XG4gICAgY2F0ZWdvcnk6IHt9LCB0aWVyOiB7fSwgbGljZW5zZToge30sIGNvbXB1dGVUeXBlOiB7fSwgbmVlZHNTZWNyZXRzOiB7IHRydWU6IDAsIGZhbHNlOiAwIH0sXG4gIH07XG4gIHR5cGUgRmFjZXRSb3cgPSB7XG4gICAgY2F0ZWdvcnk6IHN0cmluZyB8IG51bGw7XG4gICAgcHVibGlzaGVyX3RpZXI6IHN0cmluZyB8IG51bGw7XG4gICAgbGljZW5zZTogc3RyaW5nIHwgbnVsbDtcbiAgICBjb21wdXRlX3R5cGU6IHN0cmluZyB8IG51bGw7XG4gICAgbmVlZHNfc2VjcmV0czogYm9vbGVhbiB8IG51bGw7XG4gICAgZ19jYXRlZ29yeTogbnVtYmVyO1xuICAgIGdfdGllcjogbnVtYmVyO1xuICAgIGdfbGljZW5zZTogbnVtYmVyO1xuICAgIGdfY29tcHV0ZTogbnVtYmVyO1xuICAgIGdfc2VjcmV0czogbnVtYmVyO1xuICAgIG46IG51bWJlciB8IHN0cmluZztcbiAgfTtcbiAgZm9yIChjb25zdCByIG9mIHJlc3VsdFJvd3M8RmFjZXRSb3c+KGZhY2V0UmVzKSkge1xuICAgIGNvbnN0IG4gPSBudW0oci5uKTtcbiAgICBpZiAoTnVtYmVyKHIuZ19jYXRlZ29yeSkgPT09IDAgJiYgci5jYXRlZ29yeSkgZmFjZXRzLmNhdGVnb3J5W3IuY2F0ZWdvcnldID0gbjtcbiAgICBlbHNlIGlmIChOdW1iZXIoci5nX3RpZXIpID09PSAwICYmIHIucHVibGlzaGVyX3RpZXIpIGZhY2V0cy50aWVyW3IucHVibGlzaGVyX3RpZXJdID0gbjtcbiAgICBlbHNlIGlmIChOdW1iZXIoci5nX2xpY2Vuc2UpID09PSAwICYmIHIubGljZW5zZSkgZmFjZXRzLmxpY2Vuc2Vbci5saWNlbnNlXSA9IG47XG4gICAgZWxzZSBpZiAoTnVtYmVyKHIuZ19jb21wdXRlKSA9PT0gMCAmJiByLmNvbXB1dGVfdHlwZSkgZmFjZXRzLmNvbXB1dGVUeXBlW3IuY29tcHV0ZV90eXBlXSA9IG47XG4gICAgZWxzZSBpZiAoTnVtYmVyKHIuZ19zZWNyZXRzKSA9PT0gMCAmJiByLm5lZWRzX3NlY3JldHMgIT09IG51bGwpIGZhY2V0cy5uZWVkc1NlY3JldHNbci5uZWVkc19zZWNyZXRzID8gJ3RydWUnIDogJ2ZhbHNlJ10gPSBuO1xuICB9XG5cbiAgcmV0dXJuIHtcbiAgICBpdGVtcyxcbiAgICBmYWNldHMsXG4gICAgdG90YWwsXG4gICAgbmV4dEN1cnNvcjogb2Zmc2V0ICsgaXRlbXMubGVuZ3RoIDwgdG90YWwgPyBlbmNvZGVPZmZzZXRDdXJzb3Iob2Zmc2V0ICsgaXRlbXMubGVuZ3RoKSA6IG51bGwsXG4gIH07XG59XG5cbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4vLyBDYXRlZ29yaWVzXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG4vKiogRXZlcnkgY2F0ZWdvcnkgd2l0aCBpdHMgbGl2ZSBjb3VudCBhbmQgaXRzIHRvcCBsaXN0aW5ncyAoYnkgcmF0aW5nLCB0aGVuIGluc3RhbGxzKS4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBsaXN0UHVibGljQ2F0ZWdvcmllcyh0b3BQZXJDYXRlZ29yeSA9IDMpOiBQcm9taXNlPERpcmVjdG9yeUNhdGVnb3J5U3VtbWFyeVtdPiB7XG4gIGNvbnN0IGRiID0gZ2V0UHVibGljUmVhZGVyRGIoKTtcbiAgY29uc3QgcmVzID0gYXdhaXQgZGIuZXhlY3V0ZShzcWxgXG4gICAgV0lUSCByYW5rZWQgQVMgKFxuICAgICAgU0VMRUNUIGwuKixcbiAgICAgICAgICAgICBST1dfTlVNQkVSKCkgT1ZFUiAoUEFSVElUSU9OIEJZIGwuY2F0ZWdvcnlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgT1JERVIgQlkgbC5yYXRpbmdfYmF5ZXMgREVTQyBOVUxMUyBMQVNULCBsLmluc3RhbGxfY291bnQgREVTQywgbC5uYW1lIEFTQykgQVMgcm4sXG4gICAgICAgICAgICAgQ09VTlQoKikgT1ZFUiAoUEFSVElUSU9OIEJZIGwuY2F0ZWdvcnkpIEFTIGNhdGVnb3J5X2NvdW50XG4gICAgICAgIEZST00gcHVibGljX2xpc3RpbmdzIGxcbiAgICAgICBXSEVSRSBsLnBhdXNlZF9hdCBJUyBOVUxMXG4gICAgKVxuICAgIFNFTEVDVCAqIEZST00gcmFua2VkIFdIRVJFIHJuIDw9ICR7TWF0aC5tYXgoMCwgTWF0aC5taW4odG9wUGVyQ2F0ZWdvcnksIDEwKSl9IE9SREVSIEJZIGNhdGVnb3J5IEFTQywgcm4gQVNDYCk7XG5cbiAgY29uc3QgYnlDYXRlZ29yeSA9IG5ldyBNYXA8c3RyaW5nLCBEaXJlY3RvcnlDYXRlZ29yeVN1bW1hcnk+KCk7XG4gIGZvciAoY29uc3Qgcm93IG9mIHJlc3VsdFJvd3M8UHVibGljTGlzdGluZ1JvdyAmIHsgY2F0ZWdvcnlfY291bnQ6IG51bWJlciB8IHN0cmluZyB9PihyZXMpKSB7XG4gICAgbGV0IHN1bW1hcnkgPSBieUNhdGVnb3J5LmdldChyb3cuY2F0ZWdvcnkpO1xuICAgIGlmICghc3VtbWFyeSkge1xuICAgICAgc3VtbWFyeSA9IHsgaWQ6IHJvdy5jYXRlZ29yeSwgY291bnQ6IG51bShyb3cuY2F0ZWdvcnlfY291bnQpLCB0b3A6IFtdIH07XG4gICAgICBieUNhdGVnb3J5LnNldChyb3cuY2F0ZWdvcnksIHN1bW1hcnkpO1xuICAgIH1cbiAgICBzdW1tYXJ5LnRvcC5wdXNoKHRvTGlzdGluZ0NhcmQocm93KSk7XG4gIH1cbiAgcmV0dXJuIFsuLi5ieUNhdGVnb3J5LnZhbHVlcygpXTtcbn1cblxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbi8vIE9uZSBsaXN0aW5nXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG50eXBlIFZlcnNpb25Sb3cgPSB7XG4gIHZlcnNpb246IHN0cmluZztcbiAgcHVibGlzaGVkX2F0OiBEYXRlIHwgc3RyaW5nO1xuICBicmVha2luZzogYm9vbGVhbjtcbiAgZGVwcmVjYXRlZF9hdDogRGF0ZSB8IHN0cmluZyB8IG51bGw7XG4gIGRlcHJlY2F0aW9uX21lc3NhZ2U6IHN0cmluZyB8IG51bGw7XG4gIHlhbmtlZDogYm9vbGVhbjtcbiAgY2hhbmdlbG9nOiBzdHJpbmcgfCBudWxsO1xuICB2dWxuX2NyaXRpY2FsOiBudW1iZXIgfCBudWxsO1xuICB2dWxuX2hpZ2g6IG51bWJlciB8IG51bGw7XG4gIHNjYW5uZWRfYXQ6IERhdGUgfCBzdHJpbmcgfCBudWxsO1xuICBpbWFnZV9kaWdlc3Q6IHN0cmluZyB8IG51bGw7XG4gIGltYWdlX3NvdXJjZTogc3RyaW5nIHwgbnVsbDtcbiAgcGx1Z2luX3R5cGU6IHN0cmluZyB8IG51bGw7XG4gIGNvbXB1dGVfdHlwZTogc3RyaW5nIHwgbnVsbDtcbiAgc2VjcmV0czogeyBuYW1lOiBzdHJpbmc7IHJlcXVpcmVkOiBib29sZWFuOyBkZXNjcmlwdGlvbj86IHN0cmluZyB9W10gfCBudWxsO1xuICByZXF1aXJlZF9tZXRhZGF0YTogc3RyaW5nW10gfCBudWxsO1xuICByZXF1aXJlZF92YXJzOiBzdHJpbmdbXSB8IG51bGw7XG4gIG5ldHdvcmtfZWdyZXNzOiBzdHJpbmdbXSB8IG51bGw7XG4gIHJlYWRtZV9odG1sOiBzdHJpbmcgfCBudWxsO1xufTtcblxudHlwZSBBZHZpc29yeVJvdyA9IHtcbiAgaWQ6IHN0cmluZztcbiAgc2V2ZXJpdHk6IHN0cmluZztcbiAgc3VtbWFyeTogc3RyaW5nO1xuICBhZmZlY3RlZF9yYW5nZTogc3RyaW5nO1xuICBmaXhlZF92ZXJzaW9uOiBzdHJpbmcgfCBudWxsO1xuICBwdWJsaXNoZWRfYXQ6IERhdGUgfCBzdHJpbmcgfCBudWxsO1xuICBkZXRhaWxzX2h0bWw6IHN0cmluZyB8IG51bGw7XG4gIGN2ZV9pZHM6IHN0cmluZ1tdIHwgbnVsbDtcbn07XG5cbi8qKlxuICogT25lIGxpc3RpbmcncyBwYWdlIGRhdGEsIG9yIG51bGwgd2hlbiBpdCBpc24ndCBwdWJsaWMgKHVua25vd24sIHN1c3BlbmRlZCxcbiAqIHRyYW5zZmVycmVkLCBwYXVzZWQgYnkgaXRzIHB1Ymxpc2hlciDigJQgb3IgaXRzIHB1Ymxpc2hlciBpcyBzdXNwZW5kZWQpLlxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZ2V0UHVibGljTGlzdGluZyhwdWJsaXNoZXJIYW5kbGU6IHN0cmluZywgbmFtZTogc3RyaW5nKTogUHJvbWlzZTxEaXJlY3RvcnlMaXN0aW5nRGV0YWlsIHwgbnVsbD4ge1xuICBjb25zdCBkYiA9IGdldFB1YmxpY1JlYWRlckRiKCk7XG4gIGNvbnN0IGxpc3RpbmdSZXMgPSBhd2FpdCBkYi5leGVjdXRlKHNxbGBcbiAgICBTRUxFQ1QgKiBGUk9NIHB1YmxpY19saXN0aW5nc1xuICAgICBXSEVSRSBwdWJsaXNoZXJfaGFuZGxlID0gJHtwdWJsaXNoZXJIYW5kbGV9IEFORCBuYW1lID0gJHtuYW1lfSBBTkQgcGF1c2VkX2F0IElTIE5VTExcbiAgICAgTElNSVQgMWApO1xuICBjb25zdCByb3cgPSByZXN1bHRSb3dzPFB1YmxpY0xpc3RpbmdSb3c+KGxpc3RpbmdSZXMpWzBdO1xuICBpZiAoIXJvdykgcmV0dXJuIG51bGw7XG5cbiAgY29uc3QgW3ZlcnNpb25SZXMsIGFkdmlzb3J5UmVzXSA9IGF3YWl0IFByb21pc2UuYWxsKFtcbiAgICBkYi5leGVjdXRlKHNxbGBTRUxFQ1QgKiBGUk9NIHB1YmxpY19saXN0ZWRfdmVyc2lvbnMgV0hFUkUgbGlzdGluZ19pZCA9ICR7cm93LmlkfWApLFxuICAgIGRiLmV4ZWN1dGUoc3FsYFNFTEVDVCAqIEZST00gcHVibGljX2Fkdmlzb3JpZXMgV0hFUkUgbGlzdGluZ19pZCA9ICR7cm93LmlkfSBPUkRFUiBCWSBwdWJsaXNoZWRfYXQgREVTQ2ApLFxuICBdKTtcbiAgY29uc3QgdmVyc2lvblJvd3MgPSByZXN1bHRSb3dzPFZlcnNpb25Sb3c+KHZlcnNpb25SZXMpLnNvcnQoKGEsIGIpID0+IGNvbXBhcmVTZW12ZXIoYi52ZXJzaW9uLCBhLnZlcnNpb24pKTtcbiAgY29uc3QgYWR2aXNvcnlSb3dzID0gcmVzdWx0Um93czxBZHZpc29yeVJvdz4oYWR2aXNvcnlSZXMpO1xuICAvLyBUaGUgdmVyc2lvbiB0aGUgcGFnZSBkZXNjcmliZXM6IHRoZSBsaXN0aW5nJ3MgbGF0ZXN0LCBlbHNlIHRoZSBuZXdlc3Qgbm9uLXlhbmtlZCBvbmUuXG4gIGNvbnN0IGN1cnJlbnQgPSB2ZXJzaW9uUm93cy5maW5kKCh2KSA9PiB2LnZlcnNpb24gPT09IHJvdy5sYXRlc3RfdmVyc2lvbiAmJiAhdi55YW5rZWQpXG4gICAgPz8gdmVyc2lvblJvd3MuZmluZCgodikgPT4gIXYueWFua2VkKVxuICAgID8/IG51bGw7XG5cbiAgY29uc3QgZGlzdCA9IHJvdy5yYXRpbmdfZGlzdCA/PyBudWxsO1xuICBjb25zdCBjYXJkID0gdG9MaXN0aW5nQ2FyZChyb3cpO1xuICByZXR1cm4ge1xuICAgIC4uLmNhcmQsXG4gICAgcmVhZG1lSHRtbDogcm93LnJlYWRtZV9odG1sID8/IGN1cnJlbnQ/LnJlYWRtZV9odG1sID8/IG51bGwsXG4gICAgZGVzY3JpcHRpb246IHJvdy5kZXNjcmlwdGlvbiA/PyAnJyxcbiAgICBob21lcGFnZVVybDogcm93LmhvbWVwYWdlX3VybCxcbiAgICBzb3VyY2VVcmw6IHJvdy5zb3VyY2VfdXJsLFxuICAgIHZlcnNpb25zOiB2ZXJzaW9uUm93cy5tYXAoKHYpID0+ICh7XG4gICAgICB2ZXJzaW9uOiB2LnZlcnNpb24sXG4gICAgICBwdWJsaXNoZWRBdDogaXNvKHYucHVibGlzaGVkX2F0KSxcbiAgICAgIGJyZWFraW5nOiB2LmJyZWFraW5nLFxuICAgICAgZGVwcmVjYXRlZDogdi5kZXByZWNhdGVkX2F0ICE9IG51bGwsXG4gICAgICBkZXByZWNhdGlvbk1lc3NhZ2U6IHYuZGVwcmVjYXRpb25fbWVzc2FnZSxcbiAgICAgIHlhbmtlZDogdi55YW5rZWQsXG4gICAgICBjaGFuZ2Vsb2c6IHYuY2hhbmdlbG9nLFxuICAgICAgdnVsbkNyaXRpY2FsOiB2LnZ1bG5fY3JpdGljYWwsXG4gICAgICB2dWxuSGlnaDogdi52dWxuX2hpZ2gsXG4gICAgICBzY2FubmVkQXQ6IHYuc2Nhbm5lZF9hdCA/IGlzbyh2LnNjYW5uZWRfYXQpIDogbnVsbCxcbiAgICAgIGFkdmlzb3J5SWRzOiBhZHZpc29yeVJvd3MuZmlsdGVyKChhKSA9PiBhZHZpc29yeVJhbmdlQ292ZXJzKGEuYWZmZWN0ZWRfcmFuZ2UsIHYudmVyc2lvbikpLm1hcCgoYSkgPT4gYS5pZCksXG4gICAgfSkpLFxuICAgIGNvbmZpZ3VyYXRpb246IHtcbiAgICAgIHNlY3JldHM6IChjdXJyZW50Py5zZWNyZXRzID8/IFtdKS5tYXAoKHMpID0+ICh7IG5hbWU6IHMubmFtZSwgcmVxdWlyZWQ6IHMucmVxdWlyZWQsIGRlc2NyaXB0aW9uOiBzLmRlc2NyaXB0aW9uID8/ICcnIH0pKSxcbiAgICAgIHJlcXVpcmVkTWV0YWRhdGE6IGN1cnJlbnQ/LnJlcXVpcmVkX21ldGFkYXRhID8/IFtdLFxuICAgICAgcmVxdWlyZWRWYXJzOiBjdXJyZW50Py5yZXF1aXJlZF92YXJzID8/IFtdLFxuICAgICAgY29tcHV0ZVR5cGU6IGN1cnJlbnQ/LmNvbXB1dGVfdHlwZSA/PyAnJyxcbiAgICAgIHByaW1hcnlPdXRwdXREaXJlY3Rvcnk6IG51bGwsXG4gICAgICBuZXR3b3JrRWdyZXNzOiBjdXJyZW50Py5uZXR3b3JrX2VncmVzcyA/PyBbXSxcbiAgICAgIHBsdWdpblR5cGU6IGN1cnJlbnQ/LnBsdWdpbl90eXBlID8/ICcnLFxuICAgIH0sXG4gICAgc3VwcGx5Q2hhaW46IHtcbiAgICAgIC8vIEEgbGlzdGVkIHZlcnNpb24gZXhpc3RzIG9ubHkgYWZ0ZXIgdGhlIHBsYXRmb3JtIHJlLXNpZ25lZCBpdCBpbiBwdWJsaWMvKi5cbiAgICAgIHNpZ25lZDogY3VycmVudD8uaW1hZ2VfZGlnZXN0ICE9IG51bGwsXG4gICAgICBkaWdlc3Q6IGN1cnJlbnQ/LmltYWdlX2RpZ2VzdCA/PyBudWxsLFxuICAgICAgaW1hZ2VTb3VyY2U6IGN1cnJlbnQ/LmltYWdlX3NvdXJjZSA/PyBudWxsLFxuICAgICAgc2Nhbm5lZEF0OiBjdXJyZW50Py5zY2FubmVkX2F0ID8gaXNvKGN1cnJlbnQuc2Nhbm5lZF9hdCkgOiBudWxsLFxuICAgICAgdnVsbkNyaXRpY2FsOiBjdXJyZW50Py52dWxuX2NyaXRpY2FsID8/IG51bGwsXG4gICAgICB2dWxuSGlnaDogY3VycmVudD8udnVsbl9oaWdoID8/IG51bGwsXG4gICAgICBzYm9tVXJsOiBjdXJyZW50Py5pbWFnZV9kaWdlc3RcbiAgICAgICAgPyBgL2FwaS9wdWJsaWMvcGx1Z2lucy8ke2VuY29kZVVSSUNvbXBvbmVudChyb3cucHVibGlzaGVyX2hhbmRsZSl9LyR7ZW5jb2RlVVJJQ29tcG9uZW50KHJvdy5uYW1lKX0vdmVyc2lvbnMvJHtlbmNvZGVVUklDb21wb25lbnQoY3VycmVudC52ZXJzaW9uKX0vc2JvbWBcbiAgICAgICAgOiBudWxsLFxuICAgIH0sXG4gICAgYWR2aXNvcmllczogYWR2aXNvcnlSb3dzLm1hcCgoYSkgPT4gKHtcbiAgICAgIGlkOiBhLmlkLFxuICAgICAgc2V2ZXJpdHk6IGEuc2V2ZXJpdHksXG4gICAgICBzdW1tYXJ5OiBhLnN1bW1hcnksXG4gICAgICBhZmZlY3RlZFJhbmdlOiBhLmFmZmVjdGVkX3JhbmdlLFxuICAgICAgZml4ZWRWZXJzaW9uOiBhLmZpeGVkX3ZlcnNpb24sXG4gICAgICBwdWJsaXNoZWRBdDogaXNvKGEucHVibGlzaGVkX2F0KSxcbiAgICAgIGRldGFpbHNIdG1sOiBhLmRldGFpbHNfaHRtbCxcbiAgICAgIGN2ZUlkczogYS5jdmVfaWRzID8/IFtdLFxuICAgIH0pKSxcbiAgICByYXRpbmdEaXN0cmlidXRpb246IGRpc3RcbiAgICAgID8geyAxOiBudW0oZGlzdFsnMSddKSwgMjogbnVtKGRpc3RbJzInXSksIDM6IG51bShkaXN0WyczJ10pLCA0OiBudW0oZGlzdFsnNCddKSwgNTogbnVtKGRpc3RbJzUnXSkgfVxuICAgICAgOiBudWxsLFxuICAgIHJlY2VudFJhdGluZzogcm93LnJlY2VudF9yYXRpbmcgPT0gbnVsbCA/IG51bGwgOiBNYXRoLnJvdW5kKG51bShyb3cucmVjZW50X3JhdGluZykgKiAxMDApIC8gMTAwLFxuICAgIGFjdGl2ZU9yZ0NvdW50OiByb3cuYWN0aXZlX29yZ19jb3VudCA9PSBudWxsID8gbnVsbCA6IG51bShyb3cuYWN0aXZlX29yZ19jb3VudCksXG4gICAgaGVhbHRoQnJlYWtkb3duOiByb3cuaGVhbHRoX2JyZWFrZG93biA/PyBudWxsLFxuICAgIHN1Y2Nlc3NSYXRlMzBkOiByb3cuc3VjY2Vzc19yYXRlXzMwZCA9PSBudWxsID8gbnVsbCA6IE1hdGgucm91bmQobnVtKHJvdy5zdWNjZXNzX3JhdGVfMzBkKSAqIDEwMDApIC8gMTAwMCxcbiAgfTtcbn1cblxuLyoqIE9uZSBsaXN0ZWQgdmVyc2lvbidzIHB1YmxpYyBpbWFnZSBpZGVudGl0eSAoZm9yIHRoZSBTQk9NIGRvd25sb2FkKSwgb3IgbnVsbC4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBnZXRQdWJsaWNMaXN0ZWRWZXJzaW9uKFxuICBwdWJsaXNoZXJIYW5kbGU6IHN0cmluZywgbmFtZTogc3RyaW5nLCB2ZXJzaW9uOiBzdHJpbmcsXG4pOiBQcm9taXNlPHsgaW1hZ2VSZXBvc2l0b3J5OiBzdHJpbmc7IGltYWdlRGlnZXN0OiBzdHJpbmcgfSB8IG51bGw+IHtcbiAgY29uc3QgZGIgPSBnZXRQdWJsaWNSZWFkZXJEYigpO1xuICBjb25zdCByZXMgPSBhd2FpdCBkYi5leGVjdXRlKHNxbGBcbiAgICBTRUxFQ1QgaW1hZ2VfcmVwb3NpdG9yeSwgaW1hZ2VfZGlnZXN0IEZST00gcHVibGljX2xpc3RlZF92ZXJzaW9uc1xuICAgICBXSEVSRSBwdWJsaXNoZXJfaGFuZGxlID0gJHtwdWJsaXNoZXJIYW5kbGV9IEFORCBuYW1lID0gJHtuYW1lfSBBTkQgdmVyc2lvbiA9ICR7dmVyc2lvbn0gQU5EIE5PVCB5YW5rZWRcbiAgICAgICBBTkQgbGlzdGluZ19pZCBJTiAoU0VMRUNUIGlkIEZST00gcHVibGljX2xpc3RpbmdzIFdIRVJFIHBhdXNlZF9hdCBJUyBOVUxMKVxuICAgICBMSU1JVCAxYCk7XG4gIGNvbnN0IHJvdyA9IHJlc3VsdFJvd3M8eyBpbWFnZV9yZXBvc2l0b3J5OiBzdHJpbmcgfCBudWxsOyBpbWFnZV9kaWdlc3Q6IHN0cmluZyB8IG51bGwgfT4ocmVzKVswXTtcbiAgaWYgKCFyb3c/LmltYWdlX3JlcG9zaXRvcnkgfHwgIXJvdy5pbWFnZV9kaWdlc3QpIHJldHVybiBudWxsO1xuICByZXR1cm4geyBpbWFnZVJlcG9zaXRvcnk6IHJvdy5pbWFnZV9yZXBvc2l0b3J5LCBpbWFnZURpZ2VzdDogcm93LmltYWdlX2RpZ2VzdCB9O1xufVxuXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuLy8gUmV2aWV3c1xuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxudHlwZSBSZXZpZXdSb3cgPSB7XG4gIGlkOiBzdHJpbmc7XG4gIHZlcnNpb246IHN0cmluZyB8IG51bGw7XG4gIHJhdGluZzogbnVtYmVyIHwgc3RyaW5nO1xuICB0aXRsZTogc3RyaW5nIHwgbnVsbDtcbiAgYm9keV9odG1sOiBzdHJpbmcgfCBudWxsO1xuICBhdXRob3JfZGlzcGxheV9uYW1lOiBzdHJpbmcgfCBudWxsO1xuICB2ZXJpZmllZF91c2U6IGJvb2xlYW47XG4gIGhlbHBmdWxfY291bnQ6IG51bWJlciB8IHN0cmluZztcbiAgZWRpdGVkOiBib29sZWFuO1xuICBjcmVhdGVkX2F0OiBEYXRlIHwgc3RyaW5nO1xuICB1cGRhdGVkX2F0OiBEYXRlIHwgc3RyaW5nO1xuICBwdWJsaXNoZXJfZGlzcGxheV9uYW1lOiBzdHJpbmc7XG4gIHJlcGx5X2JvZHlfaHRtbDogc3RyaW5nIHwgbnVsbDtcbiAgcmVwbHlfY3JlYXRlZF9hdDogRGF0ZSB8IHN0cmluZyB8IG51bGw7XG4gIHJlcGx5X3VwZGF0ZWRfYXQ6IERhdGUgfCBzdHJpbmcgfCBudWxsO1xuICB0b3RhbDogbnVtYmVyIHwgc3RyaW5nO1xufTtcblxuZnVuY3Rpb24gcmV2aWV3T3JkZXIoc29ydDogUmV2aWV3U29ydCk6IFNRTCB7XG4gIHN3aXRjaCAoc29ydCkge1xuICAgIGNhc2UgJ3JlY2VudCc6IHJldHVybiBzcWxgY3JlYXRlZF9hdCBERVNDLCBpZCBBU0NgO1xuICAgIGNhc2UgJ2hpZ2hlc3QnOiByZXR1cm4gc3FsYHJhdGluZyBERVNDLCBoZWxwZnVsX2NvdW50IERFU0MsIGNyZWF0ZWRfYXQgREVTQywgaWQgQVNDYDtcbiAgICBjYXNlICdsb3dlc3QnOiByZXR1cm4gc3FsYHJhdGluZyBBU0MsIGhlbHBmdWxfY291bnQgREVTQywgY3JlYXRlZF9hdCBERVNDLCBpZCBBU0NgO1xuICAgIGNhc2UgJ2hlbHBmdWwnOlxuICAgIGRlZmF1bHQ6XG4gICAgICAvLyBWZXJpZmllZCB1c2UgYnJlYWtzIHRpZXM6IGFuIG9yZyB0aGF0IHJ1bnMgdGhlIHBsdWdpbiBrbm93cyBpdCBiZXN0LlxuICAgICAgcmV0dXJuIHNxbGBoZWxwZnVsX2NvdW50IERFU0MsIHZlcmlmaWVkX3VzZSBERVNDLCBjcmVhdGVkX2F0IERFU0MsIGlkIEFTQ2A7XG4gIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHRvUHVibGljUmV2aWV3KHJvdzogT21pdDxSZXZpZXdSb3csICd0b3RhbCc+KTogUHVibGljUmV2aWV3SXRlbSB7XG4gIHJldHVybiB7XG4gICAgaWQ6IHJvdy5pZCxcbiAgICByYXRpbmc6IG51bShyb3cucmF0aW5nKSxcbiAgICB0aXRsZTogcm93LnRpdGxlLFxuICAgIGJvZHlIdG1sOiByb3cuYm9keV9odG1sLFxuICAgIHZlcnNpb246IHJvdy52ZXJzaW9uLFxuICAgIGF1dGhvcjogcm93LmF1dGhvcl9kaXNwbGF5X25hbWUgPyB7IGRpc3BsYXlOYW1lOiByb3cuYXV0aG9yX2Rpc3BsYXlfbmFtZSB9IDogbnVsbCxcbiAgICB2ZXJpZmllZFVzZTogcm93LnZlcmlmaWVkX3VzZSA9PT0gdHJ1ZSxcbiAgICBoZWxwZnVsQ291bnQ6IG51bShyb3cuaGVscGZ1bF9jb3VudCksXG4gICAgZWRpdGVkOiByb3cuZWRpdGVkID09PSB0cnVlLFxuICAgIGNyZWF0ZWRBdDogaXNvKHJvdy5jcmVhdGVkX2F0KSxcbiAgICB1cGRhdGVkQXQ6IGlzbyhyb3cudXBkYXRlZF9hdCksXG4gICAgcmVwbHk6IHJvdy5yZXBseV9ib2R5X2h0bWxcbiAgICAgID8ge1xuICAgICAgICBib2R5SHRtbDogcm93LnJlcGx5X2JvZHlfaHRtbCxcbiAgICAgICAgcHVibGlzaGVyRGlzcGxheU5hbWU6IHJvdy5wdWJsaXNoZXJfZGlzcGxheV9uYW1lLFxuICAgICAgICBjcmVhdGVkQXQ6IGlzbyhyb3cucmVwbHlfY3JlYXRlZF9hdCksXG4gICAgICAgIHVwZGF0ZWRBdDogaXNvKHJvdy5yZXBseV91cGRhdGVkX2F0KSxcbiAgICAgIH1cbiAgICAgIDogbnVsbCxcbiAgfTtcbn1cblxuLyoqXG4gKiBPbmUgcGFnZSBvZiBhIGxpc3RpbmcncyBwdWJsaXNoZWQgcmV2aWV3cyAodGhlIGRpcmVjdG9yeSdzIFJldmlld3MgdGFiKSwgb3IgbnVsbFxuICogd2hlbiB0aGUgbGlzdGluZyBpc24ndCBwdWJsaWMuIEhlbGQgYW5kIHJlbW92ZWQgcmV2aWV3cyBuZXZlciByZWFjaCB0aGUgdmlldy5cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGxpc3RQdWJsaWNSZXZpZXdzKHB1Ymxpc2hlckhhbmRsZTogc3RyaW5nLCBuYW1lOiBzdHJpbmcsIHF1ZXJ5OiBQdWJsaWNSZXZpZXdRdWVyeSA9IHt9KTogUHJvbWlzZTxQdWJsaWNSZXZpZXdQYWdlIHwgbnVsbD4ge1xuICBjb25zdCBkYiA9IGdldFB1YmxpY1JlYWRlckRiKCk7XG4gIGNvbnN0IGxpc3RpbmcgPSByZXN1bHRSb3dzPHsgaWQ6IHN0cmluZyB9Pihhd2FpdCBkYi5leGVjdXRlKHNxbGBcbiAgICBTRUxFQ1QgaWQgRlJPTSBwdWJsaWNfbGlzdGluZ3NcbiAgICAgV0hFUkUgcHVibGlzaGVyX2hhbmRsZSA9ICR7cHVibGlzaGVySGFuZGxlfSBBTkQgbmFtZSA9ICR7bmFtZX0gQU5EIHBhdXNlZF9hdCBJUyBOVUxMXG4gICAgIExJTUlUIDFgKSlbMF07XG4gIGlmICghbGlzdGluZykgcmV0dXJuIG51bGw7XG5cbiAgY29uc3Qgc29ydCA9IHF1ZXJ5LnNvcnQgJiYgUkVWSUVXX1NPUlRTLmluY2x1ZGVzKHF1ZXJ5LnNvcnQpID8gcXVlcnkuc29ydCA6ICdoZWxwZnVsJztcbiAgY29uc3QgbGltaXQgPSAhcXVlcnkubGltaXQgfHwgIU51bWJlci5pc0Zpbml0ZShxdWVyeS5saW1pdClcbiAgICA/IFJFVklFV1NfREVGQVVMVF9MSU1JVFxuICAgIDogTWF0aC5taW4oTWF0aC5tYXgoTWF0aC50cnVuYyhxdWVyeS5saW1pdCksIDEpLCBSRVZJRVdTX01BWF9MSU1JVCk7XG4gIGNvbnN0IG9mZnNldCA9IGRlY29kZU9mZnNldEN1cnNvcihxdWVyeS5jdXJzb3IpO1xuICBjb25zdCB3aGVyZTogU1FMW10gPSBbc3FsYGxpc3RpbmdfaWQgPSAke2xpc3RpbmcuaWR9YF07XG4gIGlmIChxdWVyeS5yYXRpbmcgIT09IHVuZGVmaW5lZCAmJiBOdW1iZXIuaXNJbnRlZ2VyKHF1ZXJ5LnJhdGluZykgJiYgcXVlcnkucmF0aW5nID49IDEgJiYgcXVlcnkucmF0aW5nIDw9IDUpIHtcbiAgICB3aGVyZS5wdXNoKHNxbGByYXRpbmcgPSAke3F1ZXJ5LnJhdGluZ31gKTtcbiAgfVxuICBjb25zdCByb3dzID0gcmVzdWx0Um93czxSZXZpZXdSb3c+KGF3YWl0IGRiLmV4ZWN1dGUoc3FsYFxuICAgIFNFTEVDVCBpZCwgdmVyc2lvbiwgcmF0aW5nLCB0aXRsZSwgYm9keV9odG1sLCBhdXRob3JfZGlzcGxheV9uYW1lLCB2ZXJpZmllZF91c2UsIGhlbHBmdWxfY291bnQsIGVkaXRlZCxcbiAgICAgICAgICAgY3JlYXRlZF9hdCwgdXBkYXRlZF9hdCwgcHVibGlzaGVyX2Rpc3BsYXlfbmFtZSwgcmVwbHlfYm9keV9odG1sLCByZXBseV9jcmVhdGVkX2F0LCByZXBseV91cGRhdGVkX2F0LFxuICAgICAgICAgICBDT1VOVCgqKSBPVkVSICgpIEFTIHRvdGFsXG4gICAgICBGUk9NIHB1YmxpY19yZXZpZXdzXG4gICAgIFdIRVJFICR7c3FsLmpvaW4od2hlcmUsIHNxbGAgQU5EIGApfVxuICAgICBPUkRFUiBCWSAke3Jldmlld09yZGVyKHNvcnQpfVxuICAgICBMSU1JVCAke2xpbWl0fSBPRkZTRVQgJHtvZmZzZXR9YCkpO1xuICBjb25zdCB0b3RhbCA9IHJvd3MubGVuZ3RoID4gMCA/IG51bShyb3dzWzBdIS50b3RhbCkgOiAwO1xuICByZXR1cm4ge1xuICAgIHJldmlld3M6IHJvd3MubWFwKHRvUHVibGljUmV2aWV3KSxcbiAgICB0b3RhbCxcbiAgICBuZXh0Q3Vyc29yOiBvZmZzZXQgKyByb3dzLmxlbmd0aCA8IHRvdGFsID8gZW5jb2RlT2Zmc2V0Q3Vyc29yKG9mZnNldCArIHJvd3MubGVuZ3RoKSA6IG51bGwsXG4gIH07XG59XG5cbi8qKiBFdmVyeSBwdWJsaWMgbGlzdGluZydzIFVSTCBwYXJ0cyArIGxhc3QgdXBkYXRlLCBmb3IgdGhlIHNpdGVtYXAuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gbGlzdFB1YmxpY0xpc3RpbmdzRm9yU2l0ZW1hcChtYXggPSA1MDAwKTogUHJvbWlzZTx7IHB1Ymxpc2hlcjogc3RyaW5nOyBuYW1lOiBzdHJpbmc7IHVwZGF0ZWRBdDogc3RyaW5nIH1bXT4ge1xuICBjb25zdCBkYiA9IGdldFB1YmxpY1JlYWRlckRiKCk7XG4gIGNvbnN0IHJlcyA9IGF3YWl0IGRiLmV4ZWN1dGUoc3FsYFxuICAgIFNFTEVDVCBwdWJsaXNoZXJfaGFuZGxlLCBuYW1lLCB1cGRhdGVkX2F0IEZST00gcHVibGljX2xpc3RpbmdzXG4gICAgIFdIRVJFIHBhdXNlZF9hdCBJUyBOVUxMIE9SREVSIEJZIHVwZGF0ZWRfYXQgREVTQyBMSU1JVCAke01hdGgubWluKE1hdGgubWF4KG1heCwgMSksIDUwXzAwMCl9YCk7XG4gIHJldHVybiByZXN1bHRSb3dzPHsgcHVibGlzaGVyX2hhbmRsZTogc3RyaW5nOyBuYW1lOiBzdHJpbmc7IHVwZGF0ZWRfYXQ6IERhdGUgfCBzdHJpbmcgfT4ocmVzKVxuICAgIC5tYXAoKHIpID0+ICh7IHB1Ymxpc2hlcjogci5wdWJsaXNoZXJfaGFuZGxlLCBuYW1lOiByLm5hbWUsIHVwZGF0ZWRBdDogaXNvKHIudXBkYXRlZF9hdCkgfSkpO1xufVxuIl19
|
|
@@ -14,6 +14,19 @@ import type { MessageFilter, PipelineFilter, PipelineTemplateFilter, PluginFilte
|
|
|
14
14
|
* @returns Array of SQL conditions
|
|
15
15
|
*/
|
|
16
16
|
export declare function buildPipelineConditions(filter: Partial<PipelineFilter>, orgId?: string, parentOrgId?: string): SQL[];
|
|
17
|
+
/**
|
|
18
|
+
* THE ranking for resolving one plugin ROW by name (`/plugins/lookup`,
|
|
19
|
+
* `/plugins/find`, the pipeline service's contract check) — one definition so
|
|
20
|
+
* synth and the contract check never pick different winners. Rows are only the
|
|
21
|
+
* org's own and its parent's: the Official catalog and every other publisher
|
|
22
|
+
* resolve as LISTINGS afterwards (plugin-resolution.ts).
|
|
23
|
+
* 1. owner — the caller's own org, then its parent org (a team reads the
|
|
24
|
+
* parent's shared rows), then anything else a superadmin can see;
|
|
25
|
+
* 2. the default version;
|
|
26
|
+
* 3. the highest semver (so `^1.2` resolves to the newest matching release);
|
|
27
|
+
* 4. `id`, a total tiebreak.
|
|
28
|
+
*/
|
|
29
|
+
export declare function pluginResolutionOrderBy(orgId?: string, parentOrgId?: string): SQL[];
|
|
17
30
|
/**
|
|
18
31
|
* Build SQL conditions for plugin queries
|
|
19
32
|
*
|