@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.
- package/LICENSE +202 -0
- package/README.md +61 -0
- package/drizzle.config.ts +17 -0
- package/lib/api/access-control-builder.d.ts +148 -0
- package/lib/api/access-control-builder.js +199 -0
- package/lib/api/crud-service.d.ts +343 -0
- package/lib/api/crud-service.js +849 -0
- package/lib/api/query-builders.d.ts +82 -0
- package/lib/api/query-builders.js +460 -0
- package/lib/api/reporting-service.d.ts +685 -0
- package/lib/api/reporting-service.js +1564 -0
- package/lib/api/soft-delete-sweep.d.ts +65 -0
- package/lib/api/soft-delete-sweep.js +124 -0
- package/lib/api/viewer-context.d.ts +29 -0
- package/lib/api/viewer-context.js +63 -0
- package/lib/core/query-filters.d.ts +263 -0
- package/lib/core/query-filters.js +4 -0
- package/lib/database/drizzle-schema.d.ts +7357 -0
- package/lib/database/drizzle-schema.js +66 -0
- package/lib/database/index.d.ts +5 -0
- package/lib/database/index.js +8 -0
- package/lib/database/migrator.d.ts +20 -0
- package/lib/database/migrator.js +80 -0
- package/lib/database/postgres-connection.d.ts +201 -0
- package/lib/database/postgres-connection.js +413 -0
- package/lib/database/retry-strategy.d.ts +68 -0
- package/lib/database/retry-strategy.js +122 -0
- package/lib/database/schema/alert.d.ts +588 -0
- package/lib/database/schema/alert.js +130 -0
- package/lib/database/schema/compliance.d.ts +3319 -0
- package/lib/database/schema/compliance.js +377 -0
- package/lib/database/schema/dashboard.d.ts +474 -0
- package/lib/database/schema/dashboard.js +129 -0
- package/lib/database/schema/message-attachment.d.ts +183 -0
- package/lib/database/schema/message-attachment.js +40 -0
- package/lib/database/schema/message.d.ts +411 -0
- package/lib/database/schema/message.js +114 -0
- package/lib/database/schema/pipeline-template.d.ts +466 -0
- package/lib/database/schema/pipeline-template.js +80 -0
- package/lib/database/schema/pipeline.d.ts +1613 -0
- package/lib/database/schema/pipeline.js +332 -0
- package/lib/database/schema/plugin.d.ts +749 -0
- package/lib/database/schema/plugin.js +166 -0
- package/lib/database/tenancy.d.ts +103 -0
- package/lib/database/tenancy.js +167 -0
- package/lib/index.d.ts +32 -0
- package/lib/index.js +38 -0
- 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==
|