@pipeline-builder/pipeline-data 0.0.1

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 (48) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +61 -0
  3. package/drizzle.config.ts +17 -0
  4. package/lib/api/access-control-builder.d.ts +148 -0
  5. package/lib/api/access-control-builder.js +199 -0
  6. package/lib/api/crud-service.d.ts +343 -0
  7. package/lib/api/crud-service.js +849 -0
  8. package/lib/api/query-builders.d.ts +82 -0
  9. package/lib/api/query-builders.js +460 -0
  10. package/lib/api/reporting-service.d.ts +685 -0
  11. package/lib/api/reporting-service.js +1564 -0
  12. package/lib/api/soft-delete-sweep.d.ts +65 -0
  13. package/lib/api/soft-delete-sweep.js +124 -0
  14. package/lib/api/viewer-context.d.ts +29 -0
  15. package/lib/api/viewer-context.js +63 -0
  16. package/lib/core/query-filters.d.ts +263 -0
  17. package/lib/core/query-filters.js +4 -0
  18. package/lib/database/drizzle-schema.d.ts +7357 -0
  19. package/lib/database/drizzle-schema.js +66 -0
  20. package/lib/database/index.d.ts +5 -0
  21. package/lib/database/index.js +8 -0
  22. package/lib/database/migrator.d.ts +20 -0
  23. package/lib/database/migrator.js +80 -0
  24. package/lib/database/postgres-connection.d.ts +201 -0
  25. package/lib/database/postgres-connection.js +413 -0
  26. package/lib/database/retry-strategy.d.ts +68 -0
  27. package/lib/database/retry-strategy.js +122 -0
  28. package/lib/database/schema/alert.d.ts +588 -0
  29. package/lib/database/schema/alert.js +130 -0
  30. package/lib/database/schema/compliance.d.ts +3319 -0
  31. package/lib/database/schema/compliance.js +377 -0
  32. package/lib/database/schema/dashboard.d.ts +474 -0
  33. package/lib/database/schema/dashboard.js +129 -0
  34. package/lib/database/schema/message-attachment.d.ts +183 -0
  35. package/lib/database/schema/message-attachment.js +40 -0
  36. package/lib/database/schema/message.d.ts +411 -0
  37. package/lib/database/schema/message.js +114 -0
  38. package/lib/database/schema/pipeline-template.d.ts +466 -0
  39. package/lib/database/schema/pipeline-template.js +80 -0
  40. package/lib/database/schema/pipeline.d.ts +1613 -0
  41. package/lib/database/schema/pipeline.js +332 -0
  42. package/lib/database/schema/plugin.d.ts +749 -0
  43. package/lib/database/schema/plugin.js +166 -0
  44. package/lib/database/tenancy.d.ts +103 -0
  45. package/lib/database/tenancy.js +167 -0
  46. package/lib/index.d.ts +32 -0
  47. package/lib/index.js +38 -0
  48. package/package.json +161 -0
@@ -0,0 +1,82 @@
1
+ import { SQL } from 'drizzle-orm';
2
+ import type { MessageFilter, PipelineFilter, PipelineTemplateFilter, PluginFilter, CompliancePolicyFilter, ComplianceRuleFilter, ComplianceExemptionFilter, ComplianceAuditFilter, ComplianceScanFilter } from '../core/query-filters.js';
3
+ /**
4
+ * Build SQL conditions for pipeline queries
5
+ *
6
+ * Access control is the shared three-rung `visibility` ladder — see
7
+ * `AccessControlQueryBuilder.buildAccessControl` for the full predicate.
8
+ * `parentOrgId` (org → team hierarchy) widens the catalog view so a team org
9
+ * also sees its parent's public pipelines.
10
+ *
11
+ * @param filter - Pipeline filter criteria
12
+ * @param orgId - User's organization ID (optional — anonymous gets system public only)
13
+ * @param parentOrgId - Parent org ID when the caller is a team (optional)
14
+ * @returns Array of SQL conditions
15
+ */
16
+ export declare function buildPipelineConditions(filter: Partial<PipelineFilter>, orgId?: string, parentOrgId?: string): SQL[];
17
+ /**
18
+ * Build SQL conditions for plugin queries
19
+ *
20
+ * Access control is the shared three-rung `visibility` ladder — see
21
+ * `AccessControlQueryBuilder.buildAccessControl`.
22
+ *
23
+ * @param filter - Plugin filter criteria
24
+ * @param orgId - User's organization ID (optional — anonymous gets system public only)
25
+ * @returns Array of SQL conditions
26
+ */
27
+ export declare function buildPluginConditions(filter: Partial<PluginFilter>, orgId?: string, parentOrgId?: string): SQL[];
28
+ /**
29
+ * Build SQL conditions for pipeline-template queries.
30
+ *
31
+ * Templates were briefly the only entity on the three-rung ladder and needed a
32
+ * bespoke predicate; now that every catalog entity shares it, they are back on
33
+ * the SAME `AccessControlQueryBuilder` as pipelines and plugins. Visibility
34
+ * semantics live in one place — see `buildAccessControl`.
35
+ */
36
+ export declare function buildPipelineTemplateConditions(filter: Partial<PipelineTemplateFilter>, orgId?: string, parentOrgId?: string): SQL[];
37
+ /**
38
+ * Build SQL conditions for message queries.
39
+ *
40
+ * Custom access control for messages:
41
+ * - Messages are visible to the sender org (orgId) OR the recipient org (recipientOrgId)
42
+ * - Broadcast announcements (recipientOrgId = '*') are visible to all orgs
43
+ * - System org can see all messages
44
+ *
45
+ * @param filter - Message filter criteria
46
+ * @param orgId - User's organization ID
47
+ * @returns Array of SQL conditions
48
+ */
49
+ export declare function buildMessageConditions(filter: Partial<MessageFilter>, orgId: string): SQL[];
50
+ /**
51
+ * Build SQL conditions for compliance policy queries.
52
+ *
53
+ * Visibility:
54
+ * - The requesting org's own policies, AND
55
+ * - The system org's policy templates (so the shared catalog is always visible).
56
+ */
57
+ export declare function buildCompliancePolicyConditions(filter: Partial<CompliancePolicyFilter>, orgId?: string): SQL[];
58
+ /**
59
+ * Build SQL conditions for compliance rule queries.
60
+ *
61
+ * Visibility:
62
+ * - The requesting org's own rules (any scope), AND
63
+ * - The system org's published rules (so the global catalog is always visible).
64
+ */
65
+ export declare function buildComplianceRuleConditions(filter: Partial<ComplianceRuleFilter>, orgId?: string): SQL[];
66
+ /**
67
+ * Build SQL conditions for browsing the published rules catalog.
68
+ * Only returns system-org published rules.
69
+ */
70
+ export declare function buildPublishedRuleCatalogConditions(filter: Partial<ComplianceRuleFilter>): SQL[];
71
+ /**
72
+ * Build SQL conditions for compliance exemption queries.
73
+ */
74
+ export declare function buildComplianceExemptionConditions(filter: Partial<ComplianceExemptionFilter>, orgId?: string): SQL[];
75
+ /**
76
+ * Build SQL conditions for compliance audit log queries.
77
+ */
78
+ export declare function buildComplianceAuditConditions(filter: Partial<ComplianceAuditFilter>, orgId?: string): SQL[];
79
+ /**
80
+ * Build SQL conditions for compliance scan queries.
81
+ */
82
+ export declare function buildComplianceScanConditions(filter: Partial<ComplianceScanFilter>, orgId?: string): SQL[];
@@ -0,0 +1,460 @@
1
+ // Copyright 2026 Pipeline Builder Contributors
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ import { SYSTEM_ORG_ID } from '@pipeline-builder/api-core';
4
+ import { and, eq, ilike, isNull, not, or, gte, lte, sql, SQL } from 'drizzle-orm';
5
+ import { AccessControlQueryBuilder, buildJsonbKeywordCondition, escapeLikeWildcards, normalizeStringFilter, parseBooleanFilter, } from './access-control-builder.js';
6
+ import { schema, } from '../database/drizzle-schema.js';
7
+ // Query builder instances
8
+ const pipelineBuilder = new AccessControlQueryBuilder(schema.pipeline);
9
+ const pluginBuilder = new AccessControlQueryBuilder(schema.plugin);
10
+ const pipelineTemplateBuilder = new AccessControlQueryBuilder(schema.pipelineTemplate);
11
+ /**
12
+ * Equality predicate for a filter's `id` (a single string, or the first id of a
13
+ * list). An EMPTY list carries no valid id, so instead of producing a malformed
14
+ * `eq(col, undefined)` (which Postgres would reject / treat unpredictably) it
15
+ * yields the fail-closed IMPOSSIBLE predicate — an empty id filter matches no
16
+ * rows, consistent with "no id given ⇒ nothing selected".
17
+ */
18
+ function idEquals(col, id) {
19
+ if (Array.isArray(id)) {
20
+ return id.length > 0 ? eq(col, id[0]) : IMPOSSIBLE;
21
+ }
22
+ return eq(col, id);
23
+ }
24
+ /**
25
+ * Push the shared "isActive" condition:
26
+ * - explicit `isActive` → `eq(col, bool)`;
27
+ * - otherwise default to active-only, EXCEPT single-entity lookups by id so a
28
+ * `findById` of an inactive row still returns it. Pass `hasId=false` to always
29
+ * default (e.g. the published-catalog browse, which never keys off id).
30
+ */
31
+ function activeDefault(conditions, col, isActive, hasId) {
32
+ if (isActive !== undefined) {
33
+ conditions.push(eq(col, parseBooleanFilter(isActive)));
34
+ }
35
+ else if (!hasId) {
36
+ conditions.push(eq(col, true));
37
+ }
38
+ }
39
+ /**
40
+ * Fail-closed org guard for compliance builders whose only tenancy gate is the
41
+ * app-layer `orgId` predicate. When `orgId` is absent we emit an impossible
42
+ * predicate so the query returns zero rows rather than leaking across tenants
43
+ * (mirrors the anonymous fallback in access-control-builder.ts).
44
+ */
45
+ const IMPOSSIBLE = sql `false`;
46
+ /**
47
+ * Build SQL conditions for pipeline queries
48
+ *
49
+ * Access control is the shared three-rung `visibility` ladder — see
50
+ * `AccessControlQueryBuilder.buildAccessControl` for the full predicate.
51
+ * `parentOrgId` (org → team hierarchy) widens the catalog view so a team org
52
+ * also sees its parent's public pipelines.
53
+ *
54
+ * @param filter - Pipeline filter criteria
55
+ * @param orgId - User's organization ID (optional — anonymous gets system public only)
56
+ * @param parentOrgId - Parent org ID when the caller is a team (optional)
57
+ * @returns Array of SQL conditions
58
+ */
59
+ export function buildPipelineConditions(filter, orgId, parentOrgId) {
60
+ // Use generic builder for common conditions (access control, ID, booleans, visibility)
61
+ const conditions = pipelineBuilder.buildCommonConditions(filter, orgId, parentOrgId);
62
+ // Add pipeline-specific filters
63
+ if (filter.project !== undefined) {
64
+ conditions.push(eq(schema.pipeline.project, normalizeStringFilter(filter.project)));
65
+ }
66
+ if (filter.organization !== undefined) {
67
+ conditions.push(eq(schema.pipeline.organization, normalizeStringFilter(filter.organization)));
68
+ }
69
+ // Exact-match name filter (mirrors the sibling `project`/`organization`
70
+ // predicates). The CLI's `--pipeline-name` is documented as an exact filter,
71
+ // so this uses `eq` rather than an ILIKE contains. Null-safe: absent
72
+ // pipelineName ⇒ no predicate.
73
+ if (filter.pipelineName !== undefined) {
74
+ conditions.push(eq(schema.pipeline.pipelineName, normalizeStringFilter(filter.pipelineName)));
75
+ }
76
+ if (filter.keyword !== undefined) {
77
+ conditions.push(buildJsonbKeywordCondition(schema.pipeline.keywords, normalizeStringFilter(filter.keyword)));
78
+ }
79
+ // Developer-portal catalog filters (owner / lifecycle).
80
+ if (filter.ownerId !== undefined) {
81
+ conditions.push(eq(schema.pipeline.ownerId, filter.ownerId));
82
+ }
83
+ if (filter.lifecycle !== undefined) {
84
+ conditions.push(eq(schema.pipeline.lifecycle, filter.lifecycle));
85
+ }
86
+ return conditions;
87
+ }
88
+ /**
89
+ * Build SQL conditions for plugin queries
90
+ *
91
+ * Access control is the shared three-rung `visibility` ladder — see
92
+ * `AccessControlQueryBuilder.buildAccessControl`.
93
+ *
94
+ * @param filter - Plugin filter criteria
95
+ * @param orgId - User's organization ID (optional — anonymous gets system public only)
96
+ * @returns Array of SQL conditions
97
+ */
98
+ export function buildPluginConditions(filter, orgId, parentOrgId) {
99
+ // Use generic builder for common conditions (access control, ID, booleans, visibility)
100
+ const conditions = pluginBuilder.buildCommonConditions(filter, orgId, parentOrgId);
101
+ // Add plugin-specific filters
102
+ if (filter.orgId !== undefined) {
103
+ conditions.push(eq(schema.plugin.orgId, normalizeStringFilter(filter.orgId)));
104
+ }
105
+ if (filter.name !== undefined) {
106
+ conditions.push(ilike(schema.plugin.name, `%${escapeLikeWildcards(normalizeStringFilter(filter.name))}%`));
107
+ }
108
+ if (filter.version !== undefined) {
109
+ conditions.push(eq(schema.plugin.version, filter.version));
110
+ }
111
+ if (filter.keyword !== undefined) {
112
+ conditions.push(buildJsonbKeywordCondition(schema.plugin.keywords, normalizeStringFilter(filter.keyword)));
113
+ }
114
+ if (filter.category !== undefined) {
115
+ conditions.push(eq(schema.plugin.category, filter.category));
116
+ }
117
+ // Developer-portal catalog filters (owner / lifecycle).
118
+ if (filter.ownerId !== undefined) {
119
+ conditions.push(eq(schema.plugin.ownerId, filter.ownerId));
120
+ }
121
+ if (filter.lifecycle !== undefined) {
122
+ conditions.push(eq(schema.plugin.lifecycle, filter.lifecycle));
123
+ }
124
+ return conditions;
125
+ }
126
+ /**
127
+ * Build SQL conditions for pipeline-template queries.
128
+ *
129
+ * Templates were briefly the only entity on the three-rung ladder and needed a
130
+ * bespoke predicate; now that every catalog entity shares it, they are back on
131
+ * the SAME `AccessControlQueryBuilder` as pipelines and plugins. Visibility
132
+ * semantics live in one place — see `buildAccessControl`.
133
+ */
134
+ export function buildPipelineTemplateConditions(filter, orgId, parentOrgId) {
135
+ const conditions = pipelineTemplateBuilder.buildCommonConditions(filter, orgId, parentOrgId);
136
+ // Optional narrowing to a specific org within the caller's visibility (mirrors
137
+ // the plugin builder). Access control above still bounds what's visible.
138
+ if (filter.orgId !== undefined) {
139
+ conditions.push(eq(schema.pipelineTemplate.orgId, normalizeStringFilter(filter.orgId)));
140
+ }
141
+ if (filter.name !== undefined) {
142
+ conditions.push(ilike(schema.pipelineTemplate.name, `%${escapeLikeWildcards(normalizeStringFilter(filter.name))}%`));
143
+ }
144
+ // Verbatim match, consistent with the plugin builder (categories are stored as-is).
145
+ if (filter.category !== undefined) {
146
+ conditions.push(eq(schema.pipelineTemplate.category, filter.category));
147
+ }
148
+ if (filter.keyword !== undefined) {
149
+ conditions.push(buildJsonbKeywordCondition(schema.pipelineTemplate.keywords, normalizeStringFilter(filter.keyword)));
150
+ }
151
+ if (filter.ownerId !== undefined) {
152
+ conditions.push(eq(schema.pipelineTemplate.ownerId, filter.ownerId));
153
+ }
154
+ if (filter.lifecycle !== undefined) {
155
+ conditions.push(eq(schema.pipelineTemplate.lifecycle, filter.lifecycle));
156
+ }
157
+ return conditions;
158
+ }
159
+ /**
160
+ * Build SQL conditions for message queries.
161
+ *
162
+ * Custom access control for messages:
163
+ * - Messages are visible to the sender org (orgId) OR the recipient org (recipientOrgId)
164
+ * - Broadcast announcements (recipientOrgId = '*') are visible to all orgs
165
+ * - System org can see all messages
166
+ *
167
+ * @param filter - Message filter criteria
168
+ * @param orgId - User's organization ID
169
+ * @returns Array of SQL conditions
170
+ */
171
+ export function buildMessageConditions(filter, orgId) {
172
+ const conditions = [];
173
+ const normalizedOrgId = orgId.toLowerCase();
174
+ // Custom access control: sender OR recipient OR broadcast.
175
+ //
176
+ // Per-user targeting: a row with `recipient_user_id` set is private to that
177
+ // user WITHIN the recipient org. The recipient-side branch therefore admits a
178
+ // targeted row only when the viewer IS that user (`filter.viewerUserId`);
179
+ // org-wide rows (recipient_user_id IS NULL) stay visible to everyone in the
180
+ // org. Absent a viewer id, the recipient side sees org-wide rows only, so a
181
+ // targeted message never leaks to other members (it stays visible to its
182
+ // target, the sender org, and the system org). The SENDER branch is
183
+ // unconditional — you always see what you sent, targeted or not.
184
+ if (normalizedOrgId === SYSTEM_ORG_ID) {
185
+ // System org can see all messages
186
+ }
187
+ else {
188
+ const recipientVisible = filter.viewerUserId
189
+ ? or(isNull(schema.message.recipientUserId), eq(schema.message.recipientUserId, filter.viewerUserId))
190
+ : isNull(schema.message.recipientUserId);
191
+ conditions.push(or(eq(schema.message.orgId, normalizedOrgId), and(eq(schema.message.recipientOrgId, normalizedOrgId), recipientVisible),
192
+ // Broadcast (announcements). Self-defending: only ever org-wide rows —
193
+ // a mis-created '*' + per-user row can't leak to every org.
194
+ and(eq(schema.message.recipientOrgId, '*'), isNull(schema.message.recipientUserId))));
195
+ }
196
+ // Active filter (default to active only)
197
+ if (filter.isActive !== undefined) {
198
+ conditions.push(eq(schema.message.isActive, parseBooleanFilter(filter.isActive)));
199
+ }
200
+ else {
201
+ conditions.push(eq(schema.message.isActive, true));
202
+ }
203
+ // Thread filter (null = root messages only via IS NULL)
204
+ if (filter.threadId !== undefined) {
205
+ if (filter.threadId === null) {
206
+ conditions.push(isNull(schema.message.threadId));
207
+ }
208
+ else {
209
+ conditions.push(eq(schema.message.threadId, filter.threadId));
210
+ }
211
+ }
212
+ // Recipient org filter
213
+ if (filter.recipientOrgId !== undefined) {
214
+ conditions.push(eq(schema.message.recipientOrgId, normalizeStringFilter(filter.recipientOrgId)));
215
+ }
216
+ // Recipient user filter (explicit): null → org-wide rows only; a value →
217
+ // rows targeted at that user. Distinct from `viewerUserId`, which widens
218
+ // visibility rather than narrowing it.
219
+ if (filter.recipientUserId !== undefined) {
220
+ if (filter.recipientUserId === null) {
221
+ conditions.push(isNull(schema.message.recipientUserId));
222
+ }
223
+ else {
224
+ // Compare the raw user id — case-preserving, matching how it's stored and
225
+ // how `viewerUserId` is compared (do NOT lowercase via normalizeStringFilter).
226
+ conditions.push(eq(schema.message.recipientUserId, filter.recipientUserId));
227
+ }
228
+ }
229
+ // Message type filter
230
+ if (filter.messageType !== undefined) {
231
+ conditions.push(eq(schema.message.messageType, filter.messageType));
232
+ }
233
+ // Priority filter
234
+ if (filter.priority !== undefined) {
235
+ conditions.push(eq(schema.message.priority, filter.priority));
236
+ }
237
+ // Channel filter (null = no channel / org-to-org messages)
238
+ if (filter.channel !== undefined) {
239
+ if (filter.channel === null) {
240
+ conditions.push(isNull(schema.message.channel));
241
+ }
242
+ else {
243
+ conditions.push(eq(schema.message.channel, normalizeStringFilter(filter.channel)));
244
+ }
245
+ }
246
+ // Read-state filter — JSONB key-existence check against `read_by`.
247
+ // We use jsonb_exists(read_by, $orgId) rather than the `?` operator
248
+ // because postgres-js / drizzle's parameter binding treats `?` as a
249
+ // placeholder, which would conflict with the JSONB `?` operator.
250
+ if (filter.isRead !== undefined) {
251
+ const keyExists = sql `jsonb_exists(${schema.message.readBy}, ${normalizedOrgId})`;
252
+ conditions.push(filter.isRead ? keyExists : not(keyExists));
253
+ }
254
+ // ID filter
255
+ if (filter.id !== undefined) {
256
+ conditions.push(idEquals(schema.message.id, filter.id));
257
+ }
258
+ // Free-text inbox search — case-insensitive substring over subject OR content.
259
+ // Wildcards in the term are escaped so a literal `%`/`_` is matched literally;
260
+ // an all-whitespace term is ignored (no-op) rather than matching everything.
261
+ if (filter.search !== undefined) {
262
+ const term = normalizeStringFilter(filter.search).trim();
263
+ if (term) {
264
+ const like = `%${escapeLikeWildcards(term)}%`;
265
+ conditions.push(or(ilike(schema.message.subject, like), ilike(schema.message.content, like)));
266
+ }
267
+ }
268
+ return conditions;
269
+ }
270
+ // ========================================
271
+ // Compliance Query Builders
272
+ // ========================================
273
+ /**
274
+ * Build SQL conditions for compliance policy queries.
275
+ *
276
+ * Visibility:
277
+ * - The requesting org's own policies, AND
278
+ * - The system org's policy templates (so the shared catalog is always visible).
279
+ */
280
+ export function buildCompliancePolicyConditions(filter, orgId) {
281
+ const conditions = [];
282
+ if (orgId) {
283
+ const normalizedOrgId = orgId.toLowerCase();
284
+ if (normalizedOrgId === SYSTEM_ORG_ID) {
285
+ conditions.push(eq(schema.compliancePolicy.orgId, normalizedOrgId));
286
+ }
287
+ else {
288
+ conditions.push(or(eq(schema.compliancePolicy.orgId, normalizedOrgId), and(eq(schema.compliancePolicy.orgId, SYSTEM_ORG_ID), eq(schema.compliancePolicy.isTemplate, true))));
289
+ }
290
+ }
291
+ else {
292
+ // Fail-closed: no org context ⇒ no rows (never leak every tenant's policies).
293
+ conditions.push(IMPOSSIBLE);
294
+ }
295
+ if (filter.id !== undefined) {
296
+ conditions.push(idEquals(schema.compliancePolicy.id, filter.id));
297
+ }
298
+ if (filter.name !== undefined) {
299
+ conditions.push(ilike(schema.compliancePolicy.name, `%${escapeLikeWildcards(normalizeStringFilter(filter.name))}%`));
300
+ }
301
+ if (filter.isTemplate !== undefined) {
302
+ conditions.push(eq(schema.compliancePolicy.isTemplate, parseBooleanFilter(filter.isTemplate)));
303
+ }
304
+ // Default to active=true for list queries, not single-entity lookups by ID
305
+ // (otherwise findById of an inactive policy returns nothing).
306
+ activeDefault(conditions, schema.compliancePolicy.isActive, filter.isActive, filter.id !== undefined);
307
+ return conditions;
308
+ }
309
+ /**
310
+ * Build SQL conditions for compliance rule queries.
311
+ *
312
+ * Visibility:
313
+ * - The requesting org's own rules (any scope), AND
314
+ * - The system org's published rules (so the global catalog is always visible).
315
+ */
316
+ export function buildComplianceRuleConditions(filter, orgId) {
317
+ const conditions = [];
318
+ if (orgId) {
319
+ const normalizedOrgId = orgId.toLowerCase();
320
+ if (normalizedOrgId === SYSTEM_ORG_ID) {
321
+ conditions.push(eq(schema.complianceRule.orgId, normalizedOrgId));
322
+ }
323
+ else {
324
+ conditions.push(or(eq(schema.complianceRule.orgId, normalizedOrgId), and(eq(schema.complianceRule.orgId, SYSTEM_ORG_ID), eq(schema.complianceRule.scope, 'published'))));
325
+ }
326
+ }
327
+ else {
328
+ // Fail-closed: no org context ⇒ no rows (never leak every tenant's rules).
329
+ conditions.push(IMPOSSIBLE);
330
+ }
331
+ if (filter.id !== undefined) {
332
+ conditions.push(idEquals(schema.complianceRule.id, filter.id));
333
+ }
334
+ if (filter.name !== undefined) {
335
+ conditions.push(ilike(schema.complianceRule.name, `%${escapeLikeWildcards(normalizeStringFilter(filter.name))}%`));
336
+ }
337
+ if (filter.policyId !== undefined) {
338
+ conditions.push(eq(schema.complianceRule.policyId, filter.policyId));
339
+ }
340
+ if (filter.target !== undefined) {
341
+ conditions.push(eq(schema.complianceRule.target, filter.target));
342
+ }
343
+ if (filter.severity !== undefined) {
344
+ conditions.push(eq(schema.complianceRule.severity, filter.severity));
345
+ }
346
+ if (filter.scope !== undefined) {
347
+ conditions.push(eq(schema.complianceRule.scope, filter.scope));
348
+ }
349
+ if (filter.tag !== undefined) {
350
+ conditions.push(buildJsonbKeywordCondition(schema.complianceRule.tags, normalizeStringFilter(filter.tag)));
351
+ }
352
+ // Default to active=true for list queries, not single-entity lookups by ID.
353
+ activeDefault(conditions, schema.complianceRule.isActive, filter.isActive, filter.id !== undefined);
354
+ return conditions;
355
+ }
356
+ /**
357
+ * Build SQL conditions for browsing the published rules catalog.
358
+ * Only returns system-org published rules.
359
+ */
360
+ export function buildPublishedRuleCatalogConditions(filter) {
361
+ const conditions = [];
362
+ // Only scope='published' is needed — the create endpoint already enforces
363
+ // that only the system org can create published rules, so filtering by orgId
364
+ // is redundant and breaks when the system org's DB ID differs from SYSTEM_ORG_ID.
365
+ conditions.push(eq(schema.complianceRule.scope, 'published'));
366
+ if (filter.name !== undefined) {
367
+ conditions.push(ilike(schema.complianceRule.name, `%${escapeLikeWildcards(normalizeStringFilter(filter.name))}%`));
368
+ }
369
+ if (filter.target !== undefined) {
370
+ conditions.push(eq(schema.complianceRule.target, filter.target));
371
+ }
372
+ if (filter.severity !== undefined) {
373
+ conditions.push(eq(schema.complianceRule.severity, filter.severity));
374
+ }
375
+ if (filter.tag !== undefined) {
376
+ conditions.push(buildJsonbKeywordCondition(schema.complianceRule.tags, normalizeStringFilter(filter.tag)));
377
+ }
378
+ // The catalog is always active-only (no single-id exemption here).
379
+ activeDefault(conditions, schema.complianceRule.isActive, filter.isActive, false);
380
+ return conditions;
381
+ }
382
+ /**
383
+ * Build SQL conditions for compliance exemption queries.
384
+ */
385
+ export function buildComplianceExemptionConditions(filter, orgId) {
386
+ const conditions = [];
387
+ if (orgId) {
388
+ conditions.push(eq(schema.complianceExemption.orgId, orgId.toLowerCase()));
389
+ }
390
+ else {
391
+ conditions.push(IMPOSSIBLE);
392
+ }
393
+ if (filter.ruleId !== undefined) {
394
+ conditions.push(eq(schema.complianceExemption.ruleId, filter.ruleId));
395
+ }
396
+ if (filter.entityType !== undefined) {
397
+ conditions.push(eq(schema.complianceExemption.entityType, filter.entityType));
398
+ }
399
+ if (filter.entityId !== undefined) {
400
+ conditions.push(eq(schema.complianceExemption.entityId, filter.entityId));
401
+ }
402
+ if (filter.status !== undefined) {
403
+ conditions.push(eq(schema.complianceExemption.status, filter.status));
404
+ }
405
+ return conditions;
406
+ }
407
+ /**
408
+ * Build SQL conditions for compliance audit log queries.
409
+ */
410
+ export function buildComplianceAuditConditions(filter, orgId) {
411
+ const conditions = [];
412
+ if (orgId) {
413
+ conditions.push(eq(schema.complianceAuditLog.orgId, orgId.toLowerCase()));
414
+ }
415
+ else {
416
+ conditions.push(IMPOSSIBLE);
417
+ }
418
+ if (filter.target !== undefined) {
419
+ conditions.push(eq(schema.complianceAuditLog.target, filter.target));
420
+ }
421
+ if (filter.action !== undefined) {
422
+ conditions.push(eq(schema.complianceAuditLog.action, filter.action));
423
+ }
424
+ if (filter.result !== undefined) {
425
+ conditions.push(eq(schema.complianceAuditLog.result, filter.result));
426
+ }
427
+ if (filter.scanId !== undefined) {
428
+ conditions.push(eq(schema.complianceAuditLog.scanId, filter.scanId));
429
+ }
430
+ if (filter.dateFrom !== undefined) {
431
+ conditions.push(gte(schema.complianceAuditLog.createdAt, new Date(filter.dateFrom)));
432
+ }
433
+ if (filter.dateTo !== undefined) {
434
+ conditions.push(lte(schema.complianceAuditLog.createdAt, new Date(filter.dateTo)));
435
+ }
436
+ return conditions;
437
+ }
438
+ /**
439
+ * Build SQL conditions for compliance scan queries.
440
+ */
441
+ export function buildComplianceScanConditions(filter, orgId) {
442
+ const conditions = [];
443
+ if (orgId) {
444
+ conditions.push(eq(schema.complianceScan.orgId, orgId.toLowerCase()));
445
+ }
446
+ else {
447
+ conditions.push(IMPOSSIBLE);
448
+ }
449
+ if (filter.target !== undefined) {
450
+ conditions.push(eq(schema.complianceScan.target, filter.target));
451
+ }
452
+ if (filter.status !== undefined) {
453
+ conditions.push(eq(schema.complianceScan.status, filter.status));
454
+ }
455
+ if (filter.triggeredBy !== undefined) {
456
+ conditions.push(eq(schema.complianceScan.triggeredBy, filter.triggeredBy));
457
+ }
458
+ return conditions;
459
+ }
460
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicXVlcnktYnVpbGRlcnMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvYXBpL3F1ZXJ5LWJ1aWxkZXJzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLCtDQUErQztBQUMvQyxzQ0FBc0M7QUFFdEMsT0FBTyxFQUFFLGFBQWEsRUFBa0IsTUFBTSw0QkFBNEIsQ0FBQztBQUMzRSxPQUFPLEVBQUUsR0FBRyxFQUFFLEVBQUUsRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFFLEdBQUcsRUFBRSxFQUFFLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLE1BQU0sYUFBYSxDQUFDO0FBRWxGLE9BQU8sRUFDTCx5QkFBeUIsRUFDekIsMEJBQTBCLEVBQzFCLG1CQUFtQixFQUNuQixxQkFBcUIsRUFDckIsa0JBQWtCLEdBQ25CLE1BQU0sNkJBQTZCLENBQUM7QUFZckMsT0FBTyxFQUNMLE1BQU0sR0FNUCxNQUFNLCtCQUErQixDQUFDO0FBRXZDLDBCQUEwQjtBQUMxQixNQUFNLGVBQWUsR0FBRyxJQUFJLHlCQUF5QixDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsQ0FBQztBQUN2RSxNQUFNLGFBQWEsR0FBRyxJQUFJLHlCQUF5QixDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQztBQUNuRSxNQUFNLHVCQUF1QixHQUFHLElBQUkseUJBQXlCLENBQUMsTUFBTSxDQUFDLGdCQUFnQixDQUFDLENBQUM7QUFFdkY7Ozs7OztHQU1HO0FBQ0gsU0FBUyxRQUFRLENBQUMsR0FBYyxFQUFFLEVBQXFCO0lBQ3JELElBQUksS0FBSyxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDO1FBQ3RCLE9BQU8sRUFBRSxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxHQUFHLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQztJQUNy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QUFDLFVBQVUsQ0FBQyxDQUFDO0lBQzlCLENBQUM7SUFFRCxJQUFJLE1BQU0sQ0FBQyxFQUFFLEtBQUssU0FBUyxFQUFFLENBQUM7UUFDNUIsVUFBVSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLGNBQWMsQ0FBQyxFQUFFLEVBQUUsTUFBTSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDakUsQ0FBQztJQUVELElBQUksTUFBTSxDQUFDLElBQUksS0FBSyxTQUFTLEVBQUUsQ0FBQztRQUM5QixVQUFVLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsY0FBYyxDQUFDLElBQUksRUFBRSxJQUFJLG1CQUFtQixDQUFDLHFCQUFxQixDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO0lBQ3JILENBQUM7SUFFRCxJQUFJLE1BQU0sQ0FBQyxRQUFRLEtBQUssU0FBUyxFQUFFLENBQUM7UUFDbEMsVUFBVSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsTUFBTSxDQUFDLGNBQWMsQ0FBQyxRQUFRLEVBQUUsTUFBTSxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUM7SUFDdkUsQ0FBQztJQUVELElBQUksTUFBTSxDQUFDLE1BQU0sS0FBSyxTQUFTLEVBQUUsQ0FBQztRQUNoQyxVQUFVLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxNQUFNLENBQUMsY0FBYyxDQUFDLE1BQU0sRUFBRSxNQUFNLENBQUMsTUFBb0IsQ0FBQyxDQUFDLENBQUM7SUFDakYsQ0FBQztJQUVELElBQUksTUFBTSxDQUFDLFFBQVEsS0FBSyxTQUFTLEVBQUUsQ0FBQztRQUNsQyxVQUFVLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxNQUFNLENBQUMsY0FBYyxDQUFDLFFBQVEsRUFBRSxNQUFNLENBQUMsUUFBd0IsQ0FBQyxDQUFDLENBQUM7SUFDdkYsQ0FBQztJQUVELElBQUksTUFBTSxDQUFDLEtBQUssS0FBSyxTQUFTLEVBQUUsQ0FBQztRQUMvQixVQUFVLENBQUMsSUFB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O0lBQ3JGLENBQUM7SUFFRCxPQUFPLFVBQVUsQ0FBQztBQUNwQixDQUFDO0FBRUQ7O0dBRUc7QUFDSCxNQUFNLFVBQVUsNkJBQTZCLENBQzNDLE1BQXFDLEVBQ3JDLEtBQWM7SUFFZCxNQUFNLFVBQVUsR0FBVSxFQUFFLENBQUM7SUFFN0IsSUFBSSxLQUFLLEVBQUUsQ0FBQztRQUNWLFVBQVUsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLE1BQU0sQ0FBQyxjQUFjLENBQUMsS0FBSyxFQUFFLEtBQUssQ0FBQyxXQUFXLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDeEUsQ0FBQztTQUFNLENBQUM7UUFDTixVQUFVLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxDQUFDO0lBQzlCLENBQUM7SUFFRCxJQUFJLE1BQU0sQ0FBQyxNQUFNLEtBQUssU0FBUyxFQUFFLENBQUM7UUFDaEMsVUFBVSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsTUFBTSxDQUFDLGNBQWMsQ0FBQyxNQUFNLEVBQUUsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUM7SUFDbkUsQ0FBQztJQUVELElBQUksTUFBTSxDQUFDLE1BQU0sS0FBSyxTQUFTLEVBQUUsQ0FBQztRQUNoQyxVQUFVLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxNQUFNLENBQUMsY0FBYyxDQUFDLE1BQU0sRUFBRSxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQztJQUNuRSxDQUFDO0lBRUQsSUFBSSxNQUFNLENBQUMsV0FBVyxLQUFLLFNBQVMsRUFBRSxDQUFDO1FBQ3JDLFVBQVUsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLE1BQU0sQ0FBQyxjQUFjLENBQUMsV0FBVyxFQUFFLE1BQU0sQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDO0lBQzdFLENBQUM7SUFFRCxPQUFPLFVBQVUsQ0FBQztBQUNwQixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQ29weXJpZ2h0IDIwMjYgUGlwZWxpbmUgQnVpbGRlciBDb250cmlidXRvcnNcbi8vIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBcGFjaGUtMi4wXG5cbmltcG9ydCB7IFNZU1RFTV9PUkdfSUQsIHR5cGUgTGlmZWN5Y2xlIH0gZnJvbSAnQHBpcGVsaW5lLWJ1aWxkZXIvYXBpLWNvcmUnO1xuaW1wb3J0IHsgYW5kLCBlcSwgaWxpa2UsIGlzTnVsbCwgbm90LCBvciwgZ3RlLCBsdGUsIHNxbCwgU1FMIH0gZnJvbSAnZHJpenpsZS1vcm0nO1xuaW1wb3J0IHR5cGUgeyBBbnlDb2x1bW4gfSBmcm9tICdkcml6emxlLW9ybS9jb2x1bW4nO1xuaW1wb3J0IHtcbiAgQWNjZXNzQ29udHJvbFF1ZXJ5QnVpbGRlcixcbiAgYnVpbGRKc29uYktleXdvcmRDb25kaXRpb24sXG4gIGVzY2FwZUxpa2VXaWxkY2FyZHMsXG4gIG5vcm1hbGl6ZVN0cmluZ0ZpbHRlcixcbiAgcGFyc2VCb29sZWFuRmlsdGVyLFxufSBmcm9tICcuL2FjY2Vzcy1jb250cm9sLWJ1aWxkZXIuanMnO1xuaW1wb3J0IHR5cGUge1xuICBNZXNzYWdlRmlsdGVyLFxuICBQaXBlbGluZUZpbHRlcixcbiAgUGlwZWxpbmVUZW1wbGF0ZUZpbHRlcixcbiAgUGx1Z2luRmlsdGVyLFxuICBDb21wbGlhbmNlUG9saWN5RmlsdGVyLFxuICBDb21wbGlhbmNlUnVsZUZpbHRlcixcbiAgQ29tcGxpYW5jZUV4ZW1wdGlvbkZpbHRlcixcbiAgQ29tcGxpYW5jZUF1ZGl0RmlsdGVyLFxuICBDb21wbGlhbmNlU2NhbkZpbHRlcixcbn0gZnJvbSAnLi4vY29yZS9xdWVyeS1maWx0ZXJzLmpzJztcbmltcG9ydCB7XG4gIHNjaGVtYSxcbiAgdHlwZSBNZXNzYWdlUHJpb3JpdHksXG4gIHR5cGUgTWVzc2FnZVR5cGUsXG4gIHR5cGUgUnVsZVRhcmdldCxcbiAgdHlwZSBSdWxlU2V2ZXJpdHksXG4gIHR5cGUgUnVsZVNjb3BlLFxufSBmcm9tICcuLi9kYXRhYmFzZS9kcml6emxlLXNjaGVtYS5qcyc7XG5cbi8vIFF1ZXJ5IGJ1aWxkZXIgaW5zdGFuY2VzXG5jb25zdCBwaXBlbGluZUJ1aWxkZXIgPSBuZXcgQWNjZXNzQ29udHJvbFF1ZXJ5QnVpbGRlcihzY2hlbWEucGlwZWxpbmUpO1xuY29uc3QgcGx1Z2luQnVpbGRlciA9IG5ldyBBY2Nlc3NDb250cm9sUXVlcnlCdWlsZGVyKHNjaGVtYS5wbHVnaW4pO1xuY29uc3QgcGlwZWxpbmVUZW1wbGF0ZUJ1aWxkZXIgPSBuZXcgQWNjZXNzQ29udHJvbFF1ZXJ5QnVpbGRlcihzY2hlbWEucGlwZWxpbmVUZW1wbGF0ZSk7XG5cbi8qKlxuICogRXF1YWxpdHkgcHJlZGljYXRlIGZvciBhIGZpbHRlcidzIGBpZGAgKGEgc2luZ2xlIHN0cmluZywgb3IgdGhlIGZpcnN0IGlkIG9mIGFcbiAqIGxpc3QpLiBBbiBFTVBUWSBsaXN0IGNhcnJpZXMgbm8gdmFsaWQgaWQsIHNvIGluc3RlYWQgb2YgcHJvZHVjaW5nIGEgbWFsZm9ybWVkXG4gKiBgZXEoY29sLCB1bmRlZmluZWQpYCAod2hpY2ggUG9zdGdyZXMgd291bGQgcmVqZWN0IC8gdHJlYXQgdW5wcmVkaWN0YWJseSkgaXRcbiAqIHlpZWxkcyB0aGUgZmFpbC1jbG9zZWQgSU1QT1NTSUJMRSBwcmVkaWNhdGUg4oCUIGFuIGVtcHR5IGlkIGZpbHRlciBtYXRjaGVzIG5vXG4gKiByb3dzLCBjb25zaXN0ZW50IHdpdGggXCJubyBpZCBnaXZlbiDih5Igbm90aGluZyBzZWxlY3RlZFwiLlxuICovXG5mdW5jdGlvbiBpZEVxdWFscyhjb2w6IEFueUNvbHVtbiwgaWQ6IHN0cmluZyB8IHN0cmluZ1tdKTogU1FMIHtcbiAgaWYgKEFycmF5LmlzQXJyYXkoaWQpKSB7XG4gICAgcmV0dXJuIGlkLmxlbmd0aCA+IDAgPyBlcShjb2wsIGlkWzBdKSA6IElNUE9TU0lCTEU7XG4gIH1cbiAgcmV0dXJuIGVxKGNvbCwgaWQpO1xufVxuXG4vKipcbiAqIFB1c2ggdGhlIHNoYXJlZCBcImlzQWN0aXZlXCIgY29uZGl0aW9uOlxuICogLSBleHBsaWNpdCBgaXNBY3RpdmVgIOKGkiBgZXEoY29sLCBib29sKWA7XG4gKiAtIG90aGVyd2lzZSBkZWZhdWx0IHRvIGFjdGl2ZS1vbmx5LCBFWENFUFQgc2luZ2xlLWVudGl0eSBsb29rdXBzIGJ5IGlkIHNvIGFcbiAqICAgYGZpbmRCeUlkYCBvZiBhbiBpbmFjdGl2ZSByb3cgc3RpbGwgcmV0dXJucyBpdC4gUGFzcyBgaGFzSWQ9ZmFsc2VgIHRvIGFsd2F5c1xuICogICBkZWZhdWx0IChlLmcuIHRoZSBwdWJsaXNoZWQtY2F0YWxvZyBicm93c2UsIHdoaWNoIG5ldmVyIGtleXMgb2ZmIGlkKS5cbiAqL1xuZnVuY3Rpb24gYWN0aXZlRGVmYXVsdChjb25kaXRpb25zOiBTUUxbXSwgY29sOiBBbnlDb2x1bW4sIGlzQWN0aXZlOiB1bmtub3duLCBoYXNJZDogYm9vbGVhbik6IHZvaWQge1xuICBpZiAoaXNBY3RpdmUgIT09IHVuZGVmaW5lZCkge1xuICAgIGNvbmRpdGlvbnMucHVzaChlcShjb2wsIHBhcnNlQm9vbGVhbkZpbHRlcihpc0FjdGl2ZSkpKTtcbiAgfSBlbHNlIGlmICghaGFzSWQpIHtcbiAgICBjb25kaXRpb25zLnB1c2goZXEoY29sLCB0cnVlKSk7XG4gIH1cbn1cblxuLyoqXG4gKiBGYWlsLWNsb3NlZCBvcmcgZ3VhcmQgZm9yIGNvbXBsaWFuY2UgYnVpbGRlcnMgd2hvc2Ugb25seSB0ZW5hbmN5IGdhdGUgaXMgdGhlXG4gKiBhcHAtbGF5ZXIgYG9yZ0lkYCBwcmVkaWNhdGUuIFdoZW4gYG9yZ0lkYCBpcyBhYnNlbnQgd2UgZW1pdCBhbiBpbXBvc3NpYmxlXG4gKiBwcmVkaWNhdGUgc28gdGhlIHF1ZXJ5IHJldHVybnMgemVybyByb3dzIHJhdGhlciB0aGFuIGxlYWtpbmcgYWNyb3NzIHRlbmFudHNcbiAqIChtaXJyb3JzIHRoZSBhbm9ueW1vdXMgZmFsbGJhY2sgaW4gYWNjZXNzLWNvbnRyb2wtYnVpbGRlci50cykuXG4gKi9cbmNvbnN0IElNUE9TU0lCTEU6IFNRTCA9IHNxbGBmYWxzZWA7XG5cbi8qKlxuICogQnVpbGQgU1FMIGNvbmRpdGlvbnMgZm9yIHBpcGVsaW5lIHF1ZXJpZXNcbiAqXG4gKiBBY2Nlc3MgY29udHJvbCBpcyB0aGUgc2hhcmVkIHRocmVlLXJ1bmcgYHZpc2liaWxpdHlgIGxhZGRlciDigJQgc2VlXG4gKiBgQWNjZXNzQ29udHJvbFF1ZXJ5QnVpbGRlci5idWlsZEFjY2Vzc0NvbnRyb2xgIGZvciB0aGUgZnVsbCBwcmVkaWNhdGUuXG4gKiBgcGFyZW50T3JnSWRgIChvcmcg4oaSIHRlYW0gaGllcmFyY2h5KSB3aWRlbnMgdGhlIGNhdGFsb2cgdmlldyBzbyBhIHRlYW0gb3JnXG4gKiBhbHNvIHNlZXMgaXRzIHBhcmVudCdzIHB1YmxpYyBwaXBlbGluZXMuXG4gKlxuICogQHBhcmFtIGZpbHRlciAtIFBpcGVsaW5lIGZpbHRlciBjcml0ZXJpYVxuICogQHBhcmFtIG9yZ0lkIC0gVXNlcidzIG9yZ2FuaXphdGlvbiBJRCAob3B0aW9uYWwg4oCUIGFub255bW91cyBnZXRzIHN5c3RlbSBwdWJsaWMgb25seSlcbiAqIEBwYXJhbSBwYXJlbnRPcmdJZCAtIFBhcmVudCBvcmcgSUQgd2hlbiB0aGUgY2FsbGVyIGlzIGEgdGVhbSAob3B0aW9uYWwpXG4gKiBAcmV0dXJucyBBcnJheSBvZiBTUUwgY29uZGl0aW9uc1xuICovXG5leHBvcnQgZnVuY3Rpb24gYnVpbGRQaXBlbGluZUNvbmRpdGlvbnMoXG4gIGZpbHRlcjogUGFydGlhbDxQaXBlbGluZUZpbHRlcj4sXG4gIG9yZ0lkPzogc3RyaW5nLFxuICBwYXJlbnRPcmdJZD86IHN0cmluZyxcbik6IFNRTFtdIHtcbiAgLy8gVXNlIGdlbmVyaWMgYnVpbGRlciBmb3IgY29tbW9uIGNvbmRpdGlvbnMgKGFjY2VzcyBjb250cm9sLCBJRCwgYm9vbGVhbnMsIHZpc2liaWxpdHkpXG4gIGNvbnN0IGNvbmRpdGlvbnMgPSBwaXBlbGluZUJ1aWxkZXIuYnVpbGRDb21tb25Db25kaXRpb25zKGZpbHRlciwgb3JnSWQsIHBhcmVudE9yZ0lkKTtcblxuICAvLyBBZGQgcGlwZWxpbmUtc3BlY2lmaWMgZmlsdGVyc1xuICBpZiAoZmlsdGVyLnByb2plY3QgIT09IHVuZGVmaW5lZCkge1xuICAgIGNvbmRpdGlvbnMucHVzaChlcShzY2hlbWEucGlwZWxpbmUucHJvamVjdCwgbm9ybWFsaXplU3RyaW5nRmlsdGVyKGZpbHRlci5wcm9qZWN0KSkpO1xuICB9XG5cbiAgaWYgKGZpbHRlci5vcmdhbml6YXRpb24gIT09IHVuZGVmaW5lZCkge1xuICAgIGNvbmRpdGlvbnMucHVzaChlcShzY2hlbWEucGlwZWxpbmUub3JnYW5pemF0aW9uLCBub3JtYWxpemVTdHJpbmdGaWx0ZXIoZmlsdGVyLm9yZ2FuaXphdGlvbikpKTtcbiAgfVxuXG4gIC8vIEV4YWN0LW1hdGNoIG5hbWUgZmlsdGVyIChtaXJyb3JzIHRoZSBzaWJsaW5nIGBwcm9qZWN0YC9gb3JnYW5pemF0aW9uYFxuICAvLyBwcmVkaWNhdGVzKS4gVGhlIENMSSdzIGAtLXBpcGVsaW5lLW5hbWVgIGlzIGRvY3VtZW50ZWQgYXMgYW4gZXhhY3QgZmlsdGVyLFxuICAvLyBzbyB0aGlzIHVzZXMgYGVxYCByYXRoZXIgdGhhbiBhbiBJTElLRSBjb250YWlucy4gTnVsbC1zYWZlOiBhYnNlbnRcbiAgLy8gcGlwZWxpbmVOYW1lIOKHkiBubyBwcmVkaWNhdGUuXG4gIGlmIChmaWx0ZXIucGlwZWxpbmVOYW1lICE9PSB1bmRlZmluZWQpIHtcbiAgICBjb25kaXRpb25zLnB1c2goZXEoc2NoZW1hLnBpcGVsaW5lLnBpcGVsaW5lTmFtZSwgbm9ybWFsaXplU3RyaW5nRmlsdGVyKGZpbHRlci5waXBlbGluZU5hbWUpKSk7XG4gIH1cblxuICBpZiAoZmlsdGVyLmtleXdvcmQgIT09IHVuZGVmaW5lZCkge1xuICAgIGNvbmRpdGlvbnMucHVzaChidWlsZEpzb25iS2V5d29yZENvbmRpdGlvbihzY2hlbWEucGlwZWxpbmUua2V5d29yZHMsIG5vcm1hbGl6ZVN0cmluZ0ZpbHRlcihmaWx0ZXIua2V5d29yZCkpKTtcbiAgfVxuXG4gIC8vIERldmVsb3Blci1wb3J0YWwgY2F0YWxvZyBmaWx0ZXJzIChvd25lciAvIGxpZmVjeWNsZSkuXG4gIGlmIChmaWx0ZXIub3duZXJJZCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgY29uZGl0aW9ucy5wdXNoKGVxKHNjaGVtYS5waXBlbGluZS5vd25lcklkLCBmaWx0ZXIub3duZXJJZCkpO1xuICB9XG5cbiAgaWYgKGZpbHRlci5saWZlY3ljbGUgIT09IHVuZGVmaW5lZCkge1xuICAgIGNvbmRpdGlvbnMucHVzaChlcShzY2hlbWEucGlwZWxpbmUubGlmZWN5Y2xlLCBmaWx0ZXIubGlmZWN5Y2xlIGFzIExpZmVjeWNsZSkpO1xuICB9XG5cbiAgcmV0dXJuIGNvbmRpdGlvbnM7XG59XG5cbi8qKlxuICogQnVpbGQgU1FMIGNvbmRpdGlvbnMgZm9yIHBsdWdpbiBxdWVyaWVzXG4gKlxuICogQWNjZXNzIGNvbnRyb2wgaXMgdGhlIHNoYXJlZCB0aHJlZS1ydW5nIGB2aXNpYmlsaXR5YCBsYWRkZXIg4oCUIHNlZVxuICogYEFjY2Vzc0NvbnRyb2xRdWVyeUJ1aWxkZXIuYnVpbGRBY2Nlc3NDb250cm9sYC5cbiAqXG4gKiBAcGFyYW0gZmlsdGVyIC0gUGx1Z2luIGZpbHRlciBjcml0ZXJpYVxuICogQHBhcmFtIG9yZ0lkIC0gVXNlcidzIG9yZ2FuaXphdGlvbiBJRCAob3B0aW9uYWwg4oCUIGFub255bW91cyBnZXRzIHN5c3RlbSBwdWJsaWMgb25seSlcbiAqIEByZXR1cm5zIEFycmF5IG9mIFNRTCBjb25kaXRpb25zXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBidWlsZFBsdWdpbkNvbmRpdGlvbnMoXG4gIGZpbHRlcjogUGFydGlhbDxQbHVnaW5GaWx0ZXI+LFxuICBvcmdJZD86IHN0cmluZyxcbiAgcGFyZW50T3JnSWQ/OiBzdHJpbmcsXG4pOiBTUUxbXSB7XG4gIC8vIFVzZSBnZW5lcmljIGJ1aWxkZXIgZm9yIGNvbW1vbiBjb25kaXRpb25zIChhY2Nlc3MgY29udHJvbCwgSUQsIGJvb2xlYW5zLCB2aXNpYmlsaXR5KVxuICBjb25zdCBjb25kaXRpb25zID0gcGx1Z2luQnVpbGRlci5idWlsZENvbW1vbkNvbmRpdGlvbnMoZmlsdGVyLCBvcmdJZCwgcGFyZW50T3JnSWQpO1xuXG4gIC8vIEFkZCBwbHVnaW4tc3BlY2lmaWMgZmlsdGVyc1xuICBpZiAoZmlsdGVyLm9yZ0lkICE9PSB1bmRlZmluZWQpIHtcbiAgICBjb25kaXRpb25zLnB1c2goZXEoc2NoZW1hLnBsdWdpbi5vcmdJZCwgbm9ybWFsaXplU3RyaW5nRmlsdGVyKGZpbHRlci5vcmdJZCkpKTtcbiAgfVxuXG4gIGlmIChmaWx0ZXIubmFtZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgY29uZGl0aW9ucy5wdXNoKGlsaWtlKHNjaGVtYS5wbHVnaW4ubmFtZSwgYCUke2VzY2FwZUxpa2VXaWxkY2FyZHMobm9ybWFsaXplU3RyaW5nRmlsdGVyKGZpbHRlci5uYW1lKSl9JWApKTtcbiAgfVxuXG4gIGlmIChmaWx0ZXIudmVyc2lvbiAhPT0gdW5kZWZpbmVkKSB7XG4gICAgY29uZGl0aW9ucy5wdXNoKGVxKHNjaGVtYS5wbHVnaW4udmVyc2lvbiwgZmlsdGVyLnZlcnNpb24gYXMgc3RyaW5nKSk7XG4gIH1cblxuICBpZiAoZmlsdGVyLmtleXdvcmQgIT09IHVuZGVmaW5lZCkge1xuICAgIGNvbmRpdGlvbnMucHVzaChidWlsZEpzb25iS2V5d29yZENvbmRpdGlvbihzY2hlbWEucGx1Z2luLmtleXdvcmRzLCBub3JtYWxpemVTdHJpbmdGaWx0ZXIoZmlsdGVyLmtleXdvcmQpKSk7XG4gIH1cblxuICBpZiAoZmlsdGVyLmNhdGVnb3J5ICE9PSB1bmRlZmluZWQpIHtcbiAgICBjb25kaXRpb25zLnB1c2goZXEoc2NoZW1hLnBsdWdpbi5jYXRlZ29yeSwgZmlsdGVyLmNhdGVnb3J5IGFzIHN0cmluZykpO1xuICB9XG5cbiAgLy8gRGV2ZWxvcGVyLXBvcnRhbCBjYXRhbG9nIGZpbHRlcnMgKG93bmVyIC8gbGlmZWN5Y2xlKS5cbiAgaWYgKGZpbHRlci5vd25lcklkICE9PSB1bmRlZmluZWQpIHtcbiAgICBjb25kaXRpb25zLnB1c2goZXEoc2NoZW1hLnBsdWdpbi5vd25lcklkLCBmaWx0ZXIub3duZXJJZCkpO1xuICB9XG5cbiAgaWYgKGZpbHRlci5saWZlY3ljbGUgIT09IHVuZGVmaW5lZCkge1xuICAgIGNvbmRpdGlvbnMucHVzaChlcShzY2hlbWEucGx1Z2luLmxpZmVjeWNsZSwgZmlsdGVyLmxpZmVjeWNsZSBhcyBMaWZlY3ljbGUpKTtcbiAgfVxuXG4gIHJldHVybiBjb25kaXRpb25zO1xufVxuXG4vKipcbiAqIEJ1aWxkIFNRTCBjb25kaXRpb25zIGZvciBwaXBlbGluZS10ZW1wbGF0ZSBxdWVyaWVzLlxuICpcbiAqIFRlbXBsYXRlcyB3ZXJlIGJyaWVmbHkgdGhlIG9ubHkgZW50aXR5IG9uIHRoZSB0aHJlZS1ydW5nIGxhZGRlciBhbmQgbmVlZGVkIGFcbiAqIGJlc3Bva2UgcHJlZGljYXRlOyBub3cgdGhhdCBldmVyeSBjYXRhbG9nIGVudGl0eSBzaGFyZXMgaXQsIHRoZXkgYXJlIGJhY2sgb25cbiAqIHRoZSBTQU1FIGBBY2Nlc3NDb250cm9sUXVlcnlCdWlsZGVyYCBhcyBwaXBlbGluZXMgYW5kIHBsdWdpbnMuIFZpc2liaWxpdHlcbiAqIHNlbWFudGljcyBsaXZlIGluIG9uZSBwbGFjZSDigJQgc2VlIGBidWlsZEFjY2Vzc0NvbnRyb2xgLlxuICovXG5leHBvcnQgZnVuY3Rpb24gYnVpbGRQaXBlbGluZVRlbXBsYXRlQ29uZGl0aW9ucyhcbiAgZmlsdGVyOiBQYXJ0aWFsPFBpcGVsaW5lVGVtcGxhdGVGaWx0ZXI+LFxuICBvcmdJZD86IHN0cmluZyxcbiAgcGFyZW50T3JnSWQ/OiBzdHJpbmcsXG4pOiBTUUxbXSB7XG4gIGNvbnN0IGNvbmRpdGlvbnMgPSBwaXBlbGluZVRlbXBsYXRlQnVpbGRlci5idWlsZENvbW1vbkNvbmRpdGlvbnMoZmlsdGVyLCBvcmdJZCwgcGFyZW50T3JnSWQpO1xuXG4gIC8vIE9wdGlvbmFsIG5hcnJvd2luZyB0byBhIHNwZWNpZmljIG9yZyB3aXRoaW4gdGhlIGNhbGxlcidzIHZpc2liaWxpdHkgKG1pcnJvcnNcbiAgLy8gdGhlIHBsdWdpbiBidWlsZGVyKS4gQWNjZXNzIGNvbnRyb2wgYWJvdmUgc3RpbGwgYm91bmRzIHdoYXQncyB2aXNpYmxlLlxuICBpZiAoZmlsdGVyLm9yZ0lkICE9PSB1bmRlZmluZWQpIHtcbiAgICBjb25kaXRpb25zLnB1c2goZXEoc2NoZW1hLnBpcGVsaW5lVGVtcGxhdGUub3JnSWQsIG5vcm1hbGl6ZVN0cmluZ0ZpbHRlcihmaWx0ZXIub3JnSWQgYXMgc3RyaW5nKSkpO1xuICB9XG5cbiAgaWYgKGZpbHRlci5uYW1lICE9PSB1bmRlZmluZWQpIHtcbiAgICBjb25kaXRpb25zLnB1c2goaWxpa2Uoc2NoZW1hLnBpcGVsaW5lVGVtcGxhdGUubmFtZSwgYCUke2VzY2FwZUxpa2VXaWxkY2FyZHMobm9ybWFsaXplU3RyaW5nRmlsdGVyKGZpbHRlci5uYW1lKSl9JWApKTtcbiAgfVxuXG4gIC8vIFZlcmJhdGltIG1hdGNoLCBjb25zaXN0ZW50IHdpdGggdGhlIHBsdWdpbiBidWlsZGVyIChjYXRlZ29yaWVzIGFyZSBzdG9yZWQgYXMtaXMpLlxuICBpZiAoZmlsdGVyLmNhdGVnb3J5ICE9PSB1bmRlZmluZWQpIHtcbiAgICBjb25kaXRpb25zLnB1c2goZXEoc2NoZW1hLnBpcGVsaW5lVGVtcGxhdGUuY2F0ZWdvcnksIGZpbHRlci5jYXRlZ29yeSBhcyBzdHJpbmcpKTtcbiAgfVxuXG4gIGlmIChmaWx0ZXIua2V5d29yZCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgY29uZGl0aW9ucy5wdXNoKGJ1aWxkSnNvbmJLZXl3b3JkQ29uZGl0aW9uKHNjaGVtYS5waXBlbGluZVRlbXBsYXRlLmtleXdvcmRzLCBub3JtYWxpemVTdHJpbmdGaWx0ZXIoZmlsdGVyLmtleXdvcmQpKSk7XG4gIH1cblxuICBpZiAoZmlsdGVyLm93bmVySWQgIT09IHVuZGVmaW5lZCkge1xuICAgIGNvbmRpdGlvbnMucHVzaChlcShzY2hlbWEucGlwZWxpbmVUZW1wbGF0ZS5vd25lcklkLCBmaWx0ZXIub3duZXJJZCkpO1xuICB9XG5cbiAgaWYgKGZpbHRlci5saWZlY3ljbGUgIT09IHVuZGVmaW5lZCkge1xuICAgIGNvbmRpdGlvbnMucHVzaChlcShzY2hlbWEucGlwZWxpbmVUZW1wbGF0ZS5saWZlY3ljbGUsIGZpbHRlci5saWZlY3ljbGUgYXMgTGlmZWN5Y2xlKSk7XG4gIH1cblxuICByZXR1cm4gY29uZGl0aW9ucztcbn1cblxuLyoqXG4gKiBCdWlsZCBTUUwgY29uZGl0aW9ucyBmb3IgbWVzc2FnZSBxdWVyaWVzLlxuICpcbiAqIEN1c3RvbSBhY2Nlc3MgY29udHJvbCBmb3IgbWVzc2FnZXM6XG4gKiAtIE1lc3NhZ2VzIGFyZSB2aXNpYmxlIHRvIHRoZSBzZW5kZXIgb3JnIChvcmdJZCkgT1IgdGhlIHJlY2lwaWVudCBvcmcgKHJlY2lwaWVudE9yZ0lkKVxuICogLSBCcm9hZGNhc3QgYW5ub3VuY2VtZW50cyAocmVjaXBpZW50T3JnSWQgPSAnKicpIGFyZSB2aXNpYmxlIHRvIGFsbCBvcmdzXG4gKiAtIFN5c3RlbSBvcmcgY2FuIHNlZSBhbGwgbWVzc2FnZXNcbiAqXG4gKiBAcGFyYW0gZmlsdGVyIC0gTWVzc2FnZSBmaWx0ZXIgY3JpdGVyaWFcbiAqIEBwYXJhbSBvcmdJZCAtIFVzZXIncyBvcmdhbml6YXRpb24gSURcbiAqIEByZXR1cm5zIEFycmF5IG9mIFNRTCBjb25kaXRpb25zXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBidWlsZE1lc3NhZ2VDb25kaXRpb25zKFxuICBmaWx0ZXI6IFBhcnRpYWw8TWVzc2FnZUZpbHRlcj4sXG4gIG9yZ0lkOiBzdHJpbmcsXG4pOiBTUUxbXSB7XG4gIGNvbnN0IGNvbmRpdGlvbnM6IFNRTFtdID0gW107XG4gIGNvbnN0IG5vcm1hbGl6ZWRPcmdJZCA9IG9yZ0lkLnRvTG93ZXJDYXNlKCk7XG5cbiAgLy8gQ3VzdG9tIGFjY2VzcyBjb250cm9sOiBzZW5kZXIgT1IgcmVjaXBpZW50IE9SIGJyb2FkY2FzdC5cbiAgLy9cbiAgLy8gUGVyLXVzZXIgdGFyZ2V0aW5nOiBhIHJvdyB3aXRoIGByZWNpcGllbnRfdXNlcl9pZGAgc2V0IGlzIHByaXZhdGUgdG8gdGhhdFxuICAvLyB1c2VyIFdJVEhJTiB0aGUgcmVjaXBpZW50IG9yZy4gVGhlIHJlY2lwaWVudC1zaWRlIGJyYW5jaCB0aGVyZWZvcmUgYWRtaXRzIGFcbiAgLy8gdGFyZ2V0ZWQgcm93IG9ubHkgd2hlbiB0aGUgdmlld2VyIElTIHRoYXQgdXNlciAoYGZpbHRlci52aWV3ZXJVc2VySWRgKTtcbiAgLy8gb3JnLXdpZGUgcm93cyAocmVjaXBpZW50X3VzZXJfaWQgSVMgTlVMTCkgc3RheSB2aXNpYmxlIHRvIGV2ZXJ5b25lIGluIHRoZVxuICAvLyBvcmcuIEFic2VudCBhIHZpZXdlciBpZCwgdGhlIHJlY2lwaWVudCBzaWRlIHNlZXMgb3JnLXdpZGUgcm93cyBvbmx5LCBzbyBhXG4gIC8vIHRhcmdldGVkIG1lc3NhZ2UgbmV2ZXIgbGVha3MgdG8gb3RoZXIgbWVtYmVycyAoaXQgc3RheXMgdmlzaWJsZSB0byBpdHNcbiAgLy8gdGFyZ2V0LCB0aGUgc2VuZGVyIG9yZywgYW5kIHRoZSBzeXN0ZW0gb3JnKS4gVGhlIFNFTkRFUiBicmFuY2ggaXNcbiAgLy8gdW5jb25kaXRpb25hbCDigJQgeW91IGFsd2F5cyBzZWUgd2hhdCB5b3Ugc2VudCwgdGFyZ2V0ZWQgb3Igbm90LlxuICBpZiAobm9ybWFsaXplZE9yZ0lkID09PSBTWVNURU1fT1JHX0lEKSB7XG4gICAgLy8gU3lzdGVtIG9yZyBjYW4gc2VlIGFsbCBtZXNzYWdlc1xuICB9IGVsc2Uge1xuICAgIGNvbnN0IHJlY2lwaWVudFZpc2libGUgPSBmaWx0ZXIudmlld2VyVXNlcklkXG4gICAgICA/IG9yKFxuICAgICAgICBpc051bGwoc2NoZW1hLm1lc3NhZ2UucmVjaXBpZW50VXNlcklkKSxcbiAgICAgICAgZXEoc2NoZW1hLm1lc3NhZ2UucmVjaXBpZW50VXNlcklkLCBmaWx0ZXIudmlld2VyVXNlcklkKSxcbiAgICAgICkhXG4gICAgICA6IGlzTnVsbChzY2hlbWEubWVzc2FnZS5yZWNpcGllbnRVc2VySWQpO1xuICAgIGNvbmRpdGlvbnMucHVzaChcbiAgICAgIG9yKFxuICAgICAgICBlcShzY2hlbWEubWVzc2FnZS5vcmdJZCwgbm9ybWFsaXplZE9yZ0lkKSxcbiAgICAgICAgYW5kKGVxKHNjaGVtYS5tZXNzYWdlLnJlY2lwaWVudE9yZ0lkLCBub3JtYWxpemVkT3JnSWQpLCByZWNpcGllbnRWaXNpYmxlKSEsXG4gICAgICAgIC8vIEJyb2FkY2FzdCAoYW5ub3VuY2VtZW50cykuIFNlbGYtZGVmZW5kaW5nOiBvbmx5IGV2ZXIgb3JnLXdpZGUgcm93cyDigJRcbiAgICAgICAgLy8gYSBtaXMtY3JlYXRlZCAnKicgKyBwZXItdXNlciByb3cgY2FuJ3QgbGVhayB0byBldmVyeSBvcmcuXG4gICAgICAgIGFuZChlcShzY2hlbWEubWVzc2FnZS5yZWNpcGllbnRPcmdJZCwgJyonKSwgaXNOdWxsKHNjaGVtYS5tZXNzYWdlLnJlY2lwaWVudFVzZXJJZCkpISxcbiAgICAgICkhLFxuICAgICk7XG4gIH1cblxuICAvLyBBY3RpdmUgZmlsdGVyIChkZWZhdWx0IHRvIGFjdGl2ZSBvbmx5KVxuICBpZiAoZmlsdGVyLmlzQWN0aXZlICE9PSB1bmRlZmluZWQpIHtcbiAgICBjb25kaXRpb25zLnB1c2goZXEoc2NoZW1hLm1lc3NhZ2UuaXNBY3RpdmUsIHBhcnNlQm9vbGVhbkZpbHRlcihmaWx0ZXIuaXNBY3RpdmUpKSk7XG4gIH0gZWxzZSB7XG4gICAgY29uZGl0aW9ucy5wdXNoKGVxKHNjaGVtYS5tZXNzYWdlLmlzQWN0aXZlLCB0cnVlKSk7XG4gIH1cblxuICAvLyBUaHJlYWQgZmlsdGVyIChudWxsID0gcm9vdCBtZXNzYWdlcyBvbmx5IHZpYSBJUyBOVUxMKVxuICBpZiAoZmlsdGVyLnRocmVhZElkICE9PSB1bmRlZmluZWQpIHtcbiAgICBpZiAoZmlsdGVyLnRocmVhZElkID09PSBudWxsKSB7XG4gICAgICBjb25kaXRpb25zLnB1c2goaXNOdWxsKHNjaGVtYS5tZXNzYWdlLnRocmVhZElkKSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbmRpdGlvbnMucHVzaChlcShzY2hlbWEubWVzc2FnZS50aHJlYWRJZCwgZmlsdGVyLnRocmVhZElkKSk7XG4gICAgfVxuICB9XG5cbiAgLy8gUmVjaXBpZW50IG9yZyBmaWx0ZXJcbiAgaWYgKGZpbHRlci5yZWNpcGllbnRPcmdJZCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgY29uZGl0aW9ucy5wdXNoKGVxKHNjaGVtYS5tZXNzYWdlLnJlY2lwaWVudE9yZ0lkLCBub3JtYWxpemVTdHJpbmdGaWx0ZXIoZmlsdGVyLnJlY2lwaWVudE9yZ0lkKSkpO1xuICB9XG5cbiAgLy8gUmVjaXBpZW50IHVzZXIgZmlsdGVyIChleHBsaWNpdCk6IG51bGwg4oaSIG9yZy13aWRlIHJvd3Mgb25seTsgYSB2YWx1ZSDihpJcbiAgLy8gcm93cyB0YXJnZXRlZCBhdCB0aGF0IHVzZXIuIERpc3RpbmN0IGZyb20gYHZpZXdlclVzZXJJZGAsIHdoaWNoIHdpZGVuc1xuICAvLyB2aXNpYmlsaXR5IHJhdGhlciB0aGFuIG5hcnJvd2luZyBpdC5cbiAgaWYgKGZpbHRlci5yZWNpcGllbnRVc2VySWQgIT09IHVuZGVmaW5lZCkge1xuICAgIGlmIChmaWx0ZXIucmVjaXBpZW50VXNlcklkID09PSBudWxsKSB7XG4gICAgICBjb25kaXRpb25zLnB1c2goaXNOdWxsKHNjaGVtYS5tZXNzYWdlLnJlY2lwaWVudFVzZXJJZCkpO1xuICAgIH0gZWxzZSB7XG4gICAgICAvLyBDb21wYXJlIHRoZSByYXcgdXNlciBpZCDigJQgY2FzZS1wcmVzZXJ2aW5nLCBtYXRjaGluZyBob3cgaXQncyBzdG9yZWQgYW5kXG4gICAgICAvLyBob3cgYHZpZXdlclVzZXJJZGAgaXMgY29tcGFyZWQgKGRvIE5PVCBsb3dlcmNhc2UgdmlhIG5vcm1hbGl6ZVN0cmluZ0ZpbHRlcikuXG4gICAgICBjb25kaXRpb25zLnB1c2goZXEoc2NoZW1hLm1lc3NhZ2UucmVjaXBpZW50VXNlcklkLCBmaWx0ZXIucmVjaXBpZW50VXNlcklkKSk7XG4gICAgfVxuICB9XG5cbiAgLy8gTWVzc2FnZSB0eXBlIGZpbHRlclxuICBpZiAoZmlsdGVyLm1lc3NhZ2VUeXBlICE9PSB1bmRlZmluZWQpIHtcbiAgICBjb25kaXRpb25zLnB1c2goZXEoc2NoZW1hLm1lc3NhZ2UubWVzc2FnZVR5cGUsIGZpbHRlci5tZXNzYWdlVHlwZSBhcyBNZXNzYWdlVHlwZSkpO1xuICB9XG5cbiAgLy8gUHJpb3JpdHkgZmlsdGVyXG4gIGlmIChmaWx0ZXIucHJpb3JpdHkgIT09IHVuZGVmaW5lZCkge1xuICAgIGNvbmRpdGlvbnMucHVzaChlcShzY2hlbWEubWVzc2FnZS5wcmlvcml0eSwgZmlsdGVyLnByaW9yaXR5IGFzIE1lc3NhZ2VQcmlvcml0eSkpO1xuICB9XG5cbiAgLy8gQ2hhbm5lbCBmaWx0ZXIgKG51bGwgPSBubyBjaGFubmVsIC8gb3JnLXRvLW9yZyBtZXNzYWdlcylcbiAgaWYgKGZpbHRlci5jaGFubmVsICE9PSB1bmRlZmluZWQpIHtcbiAgICBpZiAoZmlsdGVyLmNoYW5uZWwgPT09IG51bGwpIHtcbiAgICAgIGNvbmRpdGlvbnMucHVzaChpc051bGwoc2NoZW1hLm1lc3NhZ2UuY2hhbm5lbCkpO1xuICAgIH0gZWxzZSB7XG4gICAgICBjb25kaXRpb25zLnB1c2goZXEoc2NoZW1hLm1lc3NhZ2UuY2hhbm5lbCwgbm9ybWFsaXplU3RyaW5nRmlsdGVyKGZpbHRlci5jaGFubmVsKSkpO1xuICAgIH1cbiAgfVxuXG4gIC8vIFJlYWQtc3RhdGUgZmlsdGVyIOKAlCBKU09OQiBrZXktZXhpc3RlbmNlIGNoZWNrIGFnYWluc3QgYHJlYWRfYnlgLlxuICAvLyBXZSB1c2UganNvbmJfZXhpc3RzKHJlYWRfYnksICRvcmdJZCkgcmF0aGVyIHRoYW4gdGhlIGA/YCBvcGVyYXRvclxuICAvLyBiZWNhdXNlIHBvc3RncmVzLWpzIC8gZHJpenpsZSdzIHBhcmFtZXRlciBiaW5kaW5nIHRyZWF0cyBgP2AgYXMgYVxuICAvLyBwbGFjZWhvbGRlciwgd2hpY2ggd291bGQgY29uZmxpY3Qgd2l0aCB0aGUgSlNPTkIgYD9gIG9wZXJhdG9yLlxuICBpZiAoZmlsdGVyLmlzUmVhZCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgY29uc3Qga2V5RXhpc3RzID0gc3FsYGpzb25iX2V4aXN0cygke3NjaGVtYS5tZXNzYWdlLnJlYWRCeX0sICR7bm9ybWFsaXplZE9yZ0lkfSlgO1xuICAgIGNvbmRpdGlvbnMucHVzaChmaWx0ZXIuaXNSZWFkID8ga2V5RXhpc3RzIDogbm90KGtleUV4aXN0cykpO1xuICB9XG5cbiAgLy8gSUQgZmlsdGVyXG4gIGlmIChmaWx0ZXIuaWQgIT09IHVuZGVmaW5lZCkge1xuICAgIGNvbmRpdGlvbnMucHVzaChpZEVxdWFscyhzY2hlbWEubWVzc2FnZS5pZCwgZmlsdGVyLmlkKSk7XG4gIH1cblxuICAvLyBGcmVlLXRleHQgaW5ib3ggc2VhcmNoIOKAlCBjYXNlLWluc2Vuc2l0aXZlIHN1YnN0cmluZyBvdmVyIHN1YmplY3QgT1IgY29udGVudC5cbiAgLy8gV2lsZGNhcmRzIGluIHRoZSB0ZXJtIGFyZSBlc2NhcGVkIHNvIGEgbGl0ZXJhbCBgJWAvYF9gIGlzIG1hdGNoZWQgbGl0ZXJhbGx5O1xuICAvLyBhbiBhbGwtd2hpdGVzcGFjZSB0ZXJtIGlzIGlnbm9yZWQgKG5vLW9wKSByYXRoZXIgdGhhbiBtYXRjaGluZyBldmVyeXRoaW5nLlxuICBpZiAoZmlsdGVyLnNlYXJjaCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgY29uc3QgdGVybSA9IG5vcm1hbGl6ZVN0cmluZ0ZpbHRlcihmaWx0ZXIuc2VhcmNoKS50cmltKCk7XG4gICAgaWYgKHRlcm0pIHtcbiAgICAgIGNvbnN0IGxpa2UgPSBgJSR7ZXNjYXBlTGlrZVdpbGRjYXJkcyh0ZXJtKX0lYDtcbiAgICAgIGNvbmRpdGlvbnMucHVzaChcbiAgICAgICAgb3IoXG4gICAgICAgICAgaWxpa2Uoc2NoZW1hLm1lc3NhZ2Uuc3ViamVjdCwgbGlrZSksXG4gICAgICAgICAgaWxpa2Uoc2NoZW1hLm1lc3NhZ2UuY29udGVudCwgbGlrZSksXG4gICAgICAgICkhLFxuICAgICAgKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gY29uZGl0aW9ucztcbn1cblxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuLy8gQ29tcGxpYW5jZSBRdWVyeSBCdWlsZGVyc1xuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG4vKipcbiAqIEJ1aWxkIFNRTCBjb25kaXRpb25zIGZvciBjb21wbGlhbmNlIHBvbGljeSBxdWVyaWVzLlxuICpcbiAqIFZpc2liaWxpdHk6XG4gKiAtIFRoZSByZXF1ZXN0aW5nIG9yZydzIG93biBwb2xpY2llcywgQU5EXG4gKiAtIFRoZSBzeXN0ZW0gb3JnJ3MgcG9saWN5IHRlbXBsYXRlcyAoc28gdGhlIHNoYXJlZCBjYXRhbG9nIGlzIGFsd2F5cyB2aXNpYmxlKS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGJ1aWxkQ29tcGxpYW5jZVBvbGljeUNvbmRpdGlvbnMoXG4gIGZpbHRlcjogUGFydGlhbDxDb21wbGlhbmNlUG9saWN5RmlsdGVyPixcbiAgb3JnSWQ/OiBzdHJpbmcsXG4pOiBTUUxbXSB7XG4gIGNvbnN0IGNvbmRpdGlvbnM6IFNRTFtdID0gW107XG5cbiAgaWYgKG9yZ0lkKSB7XG4gICAgY29uc3Qgbm9ybWFsaXplZE9yZ0lkID0gb3JnSWQudG9Mb3dlckNhc2UoKTtcbiAgICBpZiAobm9ybWFsaXplZE9yZ0lkID09PSBTWVNURU1fT1JHX0lEKSB7XG4gICAgICBjb25kaXRpb25zLnB1c2goZXEoc2NoZW1hLmNvbXBsaWFuY2VQb2xpY3kub3JnSWQsIG5vcm1hbGl6ZWRPcmdJZCkpO1xuICAgIH0gZWxzZSB7XG4gICAgICBjb25kaXRpb25zLnB1c2goXG4gICAgICAgIG9yKFxuICAgICAgICAgIGVxKHNjaGVtYS5jb21wbGlhbmNlUG9saWN5Lm9yZ0lkLCBub3JtYWxpemVkT3JnSWQpLFxuICAgICAgICAgIGFuZChcbiAgICAgICAgICAgIGVxKHNjaGVtYS5jb21wbGlhbmNlUG9saWN5Lm9yZ0lkLCBTWVNURU1fT1JHX0lEKSxcbiAgICAgICAgICAgIGVxKHNjaGVtYS5jb21wbGlhbmNlUG9saWN5LmlzVGVtcGxhdGUsIHRydWUpLFxuICAgICAgICAgICkhLFxuICAgICAgICApISxcbiAgICAgICk7XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIC8vIEZhaWwtY2xvc2VkOiBubyBvcmcgY29udGV4dCDih5Igbm8gcm93cyAobmV2ZXIgbGVhayBldmVyeSB0ZW5hbnQncyBwb2xpY2llcykuXG4gICAgY29uZGl0aW9ucy5wdXNoKElNUE9TU0lCTEUpO1xuICB9XG5cbiAgaWYgKGZpbHRlci5pZCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgY29uZGl0aW9ucy5wdXNoKGlkRXF1YWxzKHNjaGVtYS5jb21wbGlhbmNlUG9saWN5LmlkLCBmaWx0ZXIuaWQpKTtcbiAgfVxuXG4gIGlmIChmaWx0ZXIubmFtZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgY29uZGl0aW9ucy5wdXNoKGlsaWtlKHNjaGVtYS5jb21wbGlhbmNlUG9saWN5Lm5hbWUsIGAlJHtlc2NhcGVMaWtlV2lsZGNhcmRzKG5vcm1hbGl6ZVN0cmluZ0ZpbHRlcihmaWx0ZXIubmFtZSkpfSVgKSk7XG4gIH1cblxuICBpZiAoZmlsdGVyLmlzVGVtcGxhdGUgIT09IHVuZGVmaW5lZCkge1xuICAgIGNvbmRpdGlvbnMucHVzaChlcShzY2hlbWEuY29tcGxpYW5jZVBvbGljeS5pc1RlbXBsYXRlLCBwYXJzZUJvb2xlYW5GaWx0ZXIoZmlsdGVyLmlzVGVtcGxhdGUpKSk7XG4gIH1cblxuICAvLyBEZWZhdWx0IHRvIGFjdGl2ZT10cnVlIGZvciBsaXN0IHF1ZXJpZXMsIG5vdCBzaW5nbGUtZW50aXR5IGxvb2t1cHMgYnkgSURcbiAgLy8gKG90aGVyd2lzZSBmaW5kQnlJZCBvZiBhbiBpbmFjdGl2ZSBwb2xpY3kgcmV0dXJucyBub3RoaW5nKS5cbiAgYWN0aXZlRGVmYXVsdChjb25kaXRpb25zLCBzY2hlbWEuY29tcGxpYW5jZVBvbGljeS5pc0FjdGl2ZSwgZmlsdGVyLmlzQWN0aXZlLCBmaWx0ZXIuaWQgIT09IHVuZGVmaW5lZCk7XG5cbiAgcmV0dXJuIGNvbmRpdGlvbnM7XG59XG5cbi8qKlxuICogQnVpbGQgU1FMIGNvbmRpdGlvbnMgZm9yIGNvbXBsaWFuY2UgcnVsZSBxdWVyaWVzLlxuICpcbiAqIFZpc2liaWxpdHk6XG4gKiAtIFRoZSByZXF1ZXN0aW5nIG9yZydzIG93biBydWxlcyAoYW55IHNjb3BlKSwgQU5EXG4gKiAtIFRoZSBzeXN0ZW0gb3JnJ3MgcHVibGlzaGVkIHJ1bGVzIChzbyB0aGUgZ2xvYmFsIGNhdGFsb2cgaXMgYWx3YXlzIHZpc2libGUpLlxuICovXG5leHBvcnQgZnVuY3Rpb24gYnVpbGRDb21wbGlhbmNlUnVsZUNvbmRpdGlvbnMoXG4gIGZpbHRlcjogUGFydGlhbDxDb21wbGlhbmNlUnVsZUZpbHRlcj4sXG4gIG9yZ0lkPzogc3RyaW5nLFxuKTogU1FMW10ge1xuICBjb25zdCBjb25kaXRpb25zOiBTUUxbXSA9IFtdO1xuXG4gIGlmIChvcmdJZCkge1xuICAgIGNvbnN0IG5vcm1hbGl6ZWRPcmdJZCA9IG9yZ0lkLnRvTG93ZXJDYXNlKCk7XG4gICAgaWYgKG5vcm1hbGl6ZWRPcmdJZCA9PT0gU1lTVEVNX09SR19JRCkge1xuICAgICAgY29uZGl0aW9ucy5wdXNoKGVxKHNjaGVtYS5jb21wbGlhbmNlUnVsZS5vcmdJZCwgbm9ybWFsaXplZE9yZ0lkKSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbmRpdGlvbnMucHVzaChcbiAgICAgICAgb3IoXG4gICAgICAgICAgZXEoc2NoZW1hLmNvbXBsaWFuY2VSdWxlLm9yZ0lkLCBub3JtYWxpemVkT3JnSWQpLFxuICAgICAgICAgIGFuZChcbiAgICAgICAgICAgIGVxKHNjaGVtYS5jb21wbGlhbmNlUnVsZS5vcmdJZCwgU1lTVEVNX09SR19JRCksXG4gICAgICAgICAgICBlcShzY2hlbWEuY29tcGxpYW5jZVJ1bGUuc2NvcGUsICdwdWJsaXNoZWQnIGFzIFJ1bGVTY29wZSksXG4gICAgICAgICAgKSEsXG4gICAgICAgICkhLFxuICAgICAgKTtcbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgLy8gRmFpbC1jbG9zZWQ6IG5vIG9yZyBjb250ZXh0IOKHkiBubyByb3dzIChuZXZlciBsZWFrIGV2ZXJ5IHRlbmFudCdzIHJ1bGVzKS5cbiAgICBjb25kaXRpb25zLnB1c2goSU1QT1NTSUJMRSk7XG4gIH1cblxuICBpZiAoZmlsdGVyLmlkICE9PSB1bmRlZmluZWQpIHtcbiAgICBjb25kaXRpb25zLnB1c2goaWRFcXVhbHMoc2NoZW1hLmNvbXBsaWFuY2VSdWxlLmlkLCBmaWx0ZXIuaWQpKTtcbiAgfVxuXG4gIGlmIChmaWx0ZXIubmFtZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgY29uZGl0aW9ucy5wdXNoKGlsaWtlKHNjaGVtYS5jb21wbGlhbmNlUnVsZS5uYW1lLCBgJSR7ZXNjYXBlTGlrZVdpbGRjYXJkcyhub3JtYWxpemVTdHJpbmdGaWx0ZXIoZmlsdGVyLm5hbWUpKX0lYCkpO1xuICB9XG5cbiAgaWYgKGZpbHRlci5wb2xpY3lJZCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgY29uZGl0aW9ucy5wdXNoKGVxKHNjaGVtYS5jb21wbGlhbmNlUnVsZS5wb2xpY3lJZCwgZmlsdGVyLnBvbGljeUlkKSk7XG4gIH1cblxuICBpZiAoZmlsdGVyLnRhcmdldCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgY29uZGl0aW9ucy5wdXNoKGVxKHNjaGVtYS5jb21wbGlhbmNlUnVsZS50YXJnZXQsIGZpbHRlci50YXJnZXQgYXMgUnVsZVRhcmdldCkpO1xuICB9XG5cbiAgaWYgKGZpbHRlci5zZXZlcml0eSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgY29uZGl0aW9ucy5wdXNoKGVxKHNjaGVtYS5jb21wbGlhbmNlUnVsZS5zZXZlcml0eSwgZmlsdGVyLnNldmVyaXR5IGFzIFJ1bGVTZXZlcml0eSkpO1xuICB9XG5cbiAgaWYgKGZpbHRlci5zY29wZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgY29uZGl0aW9ucy5wdXNoKGVxKHNjaGVtYS5jb21wbGlhbmNlUnVsZS5zY29wZSwgZmlsdGVyLnNjb3BlIGFzIFJ1bGVTY29wZSkpO1xuICB9XG5cbiAgaWYgKGZpbHRlci50YWcgIT09IHVuZGVmaW5lZCkge1xuICAgIGNvbmRpdGlvbnMucHVzaChidWlsZEpzb25iS2V5d29yZENvbmRpdGlvbihzY2hlbWEuY29tcGxpYW5jZVJ1bGUudGFncywgbm9ybWFsaXplU3RyaW5nRmlsdGVyKGZpbHRlci50YWcpKSk7XG4gIH1cblxuICAvLyBEZWZhdWx0IHRvIGFjdGl2ZT10cnVlIGZvciBsaXN0IHF1ZXJpZXMsIG5vdCBzaW5nbGUtZW50aXR5IGxvb2t1cHMgYnkgSUQuXG4gIGFjdGl2ZURlZmF1bHQoY29uZGl0aW9ucywgc2NoZW1hLmNvbXBsaWFuY2VSdWxlLmlzQWN0aXZlLCBmaWx0ZXIuaXNBY3RpdmUsIGZpbHRlci5pZCAhPT0gdW5kZWZpbmVkKTtcblxuICByZXR1cm4gY29uZGl0aW9ucztcbn1cblxuLyoqXG4gKiBCdWlsZCBTUUwgY29uZGl0aW9ucyBmb3IgYnJvd3NpbmcgdGhlIHB1Ymxpc2hlZCBydWxlcyBjYXRhbG9nLlxuICogT25seSByZXR1cm5zIHN5c3RlbS1vcmcgcHVibGlzaGVkIHJ1bGVzLlxuICovXG5leHBvcnQgZnVuY3Rpb24gYnVpbGRQdWJsaXNoZWRSdWxlQ2F0YWxvZ0NvbmRpdGlvbnMoXG4gIGZpbHRlcjogUGFydGlhbDxDb21wbGlhbmNlUnVsZUZpbHRlcj4sXG4pOiBTUUxbXSB7XG4gIGNvbnN0IGNvbmRpdGlvbnM6IFNRTFtdID0gW107XG5cbiAgLy8gT25seSBzY29wZT0ncHVibGlzaGVkJyBpcyBuZWVkZWQg4oCUIHRoZSBjcmVhdGUgZW5kcG9pbnQgYWxyZWFkeSBlbmZvcmNlc1xuICAvLyB0aGF0IG9ubHkgdGhlIHN5c3RlbSBvcmcgY2FuIGNyZWF0ZSBwdWJsaXNoZWQgcnVsZXMsIHNvIGZpbHRlcmluZyBieSBvcmdJZFxuICAvLyBpcyByZWR1bmRhbnQgYW5kIGJyZWFrcyB3aGVuIHRoZSBzeXN0ZW0gb3JnJ3MgREIgSUQgZGlmZmVycyBmcm9tIFNZU1RFTV9PUkdfSUQuXG4gIGNvbmRpdGlvbnMucHVzaChlcShzY2hlbWEuY29tcGxpYW5jZVJ1bGUuc2NvcGUsICdwdWJsaXNoZWQnIGFzIFJ1bGVTY29wZSkpO1xuXG4gIGlmIChmaWx0ZXIubmFtZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgY29uZGl0aW9ucy5wdXNoKGlsaWtlKHNjaGVtYS5jb21wbGlhbmNlUnVsZS5uYW1lLCBgJSR7ZXNjYXBlTGlrZVdpbGRjYXJkcyhub3JtYWxpemVTdHJpbmdGaWx0ZXIoZmlsdGVyLm5hbWUpKX0lYCkpO1xuICB9XG5cbiAgaWYgKGZpbHRlci50YXJnZXQgIT09IHVuZGVmaW5lZCkge1xuICAgIGNvbmRpdGlvbnMucHVzaChlcShzY2hlbWEuY29tcGxpYW5jZVJ1bGUudGFyZ2V0LCBmaWx0ZXIudGFyZ2V0IGFzIFJ1bGVUYXJnZXQpKTtcbiAgfVxuXG4gIGlmIChmaWx0ZXIuc2V2ZXJpdHkgIT09IHVuZGVmaW5lZCkge1xuICAgIGNvbmRpdGlvbnMucHVzaChlcShzY2hlbWEuY29tcGxpYW5jZVJ1bGUuc2V2ZXJpdHksIGZpbHRlci5zZXZlcml0eSBhcyBSdWxlU2V2ZXJpdHkpKTtcbiAgfVxuXG4gIGlmIChmaWx0ZXIudGFnICE9PSB1bmRlZmluZWQpIHtcbiAgICBjb25kaXRpb25zLnB1c2goYnVpbGRKc29uYktleXdvcmRDb25kaXRpb24oc2NoZW1hLmNvbXBsaWFuY2VSdWxlLnRhZ3MsIG5vcm1hbGl6ZVN0cmluZ0ZpbHRlcihmaWx0ZXIudGFnKSkpO1xuICB9XG5cbiAgLy8gVGhlIGNhdGFsb2cgaXMgYWx3YXlzIGFjdGl2ZS1vbmx5IChubyBzaW5nbGUtaWQgZXhlbXB0aW9uIGhlcmUpLlxuICBhY3RpdmVEZWZhdWx0KGNvbmRpdGlvbnMsIHNjaGVtYS5jb21wbGlhbmNlUnVsZS5pc0FjdGl2ZSwgZmlsdGVyLmlzQWN0aXZlLCBmYWxzZSk7XG5cbiAgcmV0dXJuIGNvbmRpdGlvbnM7XG59XG5cbi8qKlxuICogQnVpbGQgU1FMIGNvbmRpdGlvbnMgZm9yIGNvbXBsaWFuY2UgZXhlbXB0aW9uIHF1ZXJpZXMuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBidWlsZENvbXBsaWFuY2VFeGVtcHRpb25Db25kaXRpb25zKFxuICBmaWx0ZXI6IFBhcnRpYWw8Q29tcGxpYW5jZUV4ZW1wdGlvbkZpbHRlcj4sXG4gIG9yZ0lkPzogc3RyaW5nLFxuKTogU1FMW10ge1xuICBjb25zdCBjb25kaXRpb25zOiBTUUxbXSA9IFtdO1xuXG4gIGlmIChvcmdJZCkge1xuICAgIGNvbmRpdGlvbnMucHVzaChlcShzY2hlbWEuY29tcGxpYW5jZUV4ZW1wdGlvbi5vcmdJZCwgb3JnSWQudG9Mb3dlckNhc2UoKSkpO1xuICB9IGVsc2Uge1xuICAgIGNvbmRpdGlvbnMucHVzaChJTVBPU1NJQkxFKTtcbiAgfVxuXG4gIGlmIChmaWx0ZXIucnVsZUlkICE9PSB1bmRlZmluZWQpIHtcbiAgICBjb25kaXRpb25zLnB1c2goZXEoc2NoZW1hLmNvbXBsaWFuY2VFeGVtcHRpb24ucnVsZUlkLCBmaWx0ZXIucnVsZUlkKSk7XG4gIH1cblxuICBpZiAoZmlsdGVyLmVudGl0eVR5cGUgIT09IHVuZGVmaW5lZCkge1xuICAgIGNvbmRpdGlvbnMucHVzaChlcShzY2hlbWEuY29tcGxpYW5jZUV4ZW1wdGlvbi5lbnRpdHlUeXBlLCBmaWx0ZXIuZW50aXR5VHlwZSBhcyBSdWxlVGFyZ2V0KSk7XG4gIH1cblxuICBpZiAoZmlsdGVyLmVudGl0eUlkICE9PSB1bmRlZmluZWQpIHtcbiAgICBjb25kaXRpb25zLnB1c2goZXEoc2NoZW1hLmNvbXBsaWFuY2VFeGVtcHRpb24uZW50aXR5SWQsIGZpbHRlci5lbnRpdHlJZCkpO1xuICB9XG5cbiAgaWYgKGZpbHRlci5zdGF0dXMgIT09IHVuZGVmaW5lZCkge1xuICAgIGNvbmRpdGlvbnMucHVzaChlcShzY2hlbWEuY29tcGxpYW5jZUV4ZW1wdGlvbi5zdGF0dXMsIGZpbHRlci5zdGF0dXMpKTtcbiAgfVxuXG4gIHJldHVybiBjb25kaXRpb25zO1xufVxuXG4vKipcbiAqIEJ1aWxkIFNRTCBjb25kaXRpb25zIGZvciBjb21wbGlhbmNlIGF1ZGl0IGxvZyBxdWVyaWVzLlxuICovXG5leHBvcnQgZnVuY3Rpb24gYnVpbGRDb21wbGlhbmNlQXVkaXRDb25kaXRpb25zKFxuICBmaWx0ZXI6IFBhcnRpYWw8Q29tcGxpYW5jZUF1ZGl0RmlsdGVyPixcbiAgb3JnSWQ/OiBzdHJpbmcsXG4pOiBTUUxbXSB7XG4gIGNvbnN0IGNvbmRpdGlvbnM6IFNRTFtdID0gW107XG5cbiAgaWYgKG9yZ0lkKSB7XG4gICAgY29uZGl0aW9ucy5wdXNoKGVxKHNjaGVtYS5jb21wbGlhbmNlQXVkaXRMb2cub3JnSWQsIG9yZ0lkLnRvTG93ZXJDYXNlKCkpKTtcbiAgfSBlbHNlIHtcbiAgICBjb25kaXRpb25zLnB1c2goSU1QT1NTSUJMRSk7XG4gIH1cblxuICBpZiAoZmlsdGVyLnRhcmdldCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgY29uZGl0aW9ucy5wdXNoKGVxKHNjaGVtYS5jb21wbGlhbmNlQXVkaXRMb2cudGFyZ2V0LCBmaWx0ZXIudGFyZ2V0IGFzIFJ1bGVUYXJnZXQpKTtcbiAgfVxuXG4gIGlmIChmaWx0ZXIuYWN0aW9uICE9PSB1bmRlZmluZWQpIHtcbiAgICBjb25kaXRpb25zLnB1c2goZXEoc2NoZW1hLmNvbXBsaWFuY2VBdWRpdExvZy5hY3Rpb24sIGZpbHRlci5hY3Rpb24pKTtcbiAgfVxuXG4gIGlmIChmaWx0ZXIucmVzdWx0ICE9PSB1bmRlZmluZWQpIHtcbiAgICBjb25kaXRpb25zLnB1c2goZXEoc2NoZW1hLmNvbXBsaWFuY2VBdWRpdExvZy5yZXN1bHQsIGZpbHRlci5yZXN1bHQpKTtcbiAgfVxuXG4gIGlmIChmaWx0ZXIuc2NhbklkICE9PSB1bmRlZmluZWQpIHtcbiAgICBjb25kaXRpb25zLnB1c2goZXEoc2NoZW1hLmNvbXBsaWFuY2VBdWRpdExvZy5zY2FuSWQsIGZpbHRlci5zY2FuSWQpKTtcbiAgfVxuXG4gIGlmIChmaWx0ZXIuZGF0ZUZyb20gIT09IHVuZGVmaW5lZCkge1xuICAgIGNvbmRpdGlvbnMucHVzaChndGUoc2NoZW1hLmNvbXBsaWFuY2VBdWRpdExvZy5jcmVhdGVkQXQsIG5ldyBEYXRlKGZpbHRlci5kYXRlRnJvbSkpKTtcbiAgfVxuXG4gIGlmIChmaWx0ZXIuZGF0ZVRvICE9PSB1bmRlZmluZWQpIHtcbiAgICBjb25kaXRpb25zLnB1c2gobHRlKHNjaGVtYS5jb21wbGlhbmNlQXVkaXRMb2cuY3JlYXRlZEF0LCBuZXcgRGF0ZShmaWx0ZXIuZGF0ZVRvKSkpO1xuICB9XG5cbiAgcmV0dXJuIGNvbmRpdGlvbnM7XG59XG5cbi8qKlxuICogQnVpbGQgU1FMIGNvbmRpdGlvbnMgZm9yIGNvbXBsaWFuY2Ugc2NhbiBxdWVyaWVzLlxuICovXG5leHBvcnQgZnVuY3Rpb24gYnVpbGRDb21wbGlhbmNlU2NhbkNvbmRpdGlvbnMoXG4gIGZpbHRlcjogUGFydGlhbDxDb21wbGlhbmNlU2NhbkZpbHRlcj4sXG4gIG9yZ0lkPzogc3RyaW5nLFxuKTogU1FMW10ge1xuICBjb25zdCBjb25kaXRpb25zOiBTUUxbXSA9IFtdO1xuXG4gIGlmIChvcmdJZCkge1xuICAgIGNvbmRpdGlvbnMucHVzaChlcShzY2hlbWEuY29tcGxpYW5jZVNjYW4ub3JnSWQsIG9yZ0lkLnRvTG93ZXJDYXNlKCkpKTtcbiAgfSBlbHNlIHtcbiAgICBjb25kaXRpb25zLnB1c2goSU1QT1NTSUJMRSk7XG4gIH1cblxuICBpZiAoZmlsdGVyLnRhcmdldCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgY29uZGl0aW9ucy5wdXNoKGVxKHNjaGVtYS5jb21wbGlhbmNlU2Nhbi50YXJnZXQsIGZpbHRlci50YXJnZXQpKTtcbiAgfVxuXG4gIGlmIChmaWx0ZXIuc3RhdHVzICE9PSB1bmRlZmluZWQpIHtcbiAgICBjb25kaXRpb25zLnB1c2goZXEoc2NoZW1hLmNvbXBsaWFuY2VTY2FuLnN0YXR1cywgZmlsdGVyLnN0YXR1cykpO1xuICB9XG5cbiAgaWYgKGZpbHRlci50cmlnZ2VyZWRCeSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgY29uZGl0aW9ucy5wdXNoKGVxKHNjaGVtYS5jb21wbGlhbmNlU2Nhbi50cmlnZ2VyZWRCeSwgZmlsdGVyLnRyaWdnZXJlZEJ5KSk7XG4gIH1cblxuICByZXR1cm4gY29uZGl0aW9ucztcbn1cbiJdfQ==