velocious 1.0.503 → 1.0.504
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/build/application.js +2 -0
- package/build/configuration-types.js +8 -8
- package/build/configuration.js +2 -2
- package/build/src/application.d.ts.map +1 -1
- package/build/src/application.js +3 -1
- package/build/src/configuration-types.d.ts +17 -17
- package/build/src/configuration-types.d.ts.map +1 -1
- package/build/src/configuration-types.js +9 -9
- package/build/src/configuration.d.ts +4 -4
- package/build/src/configuration.d.ts.map +1 -1
- package/build/src/configuration.js +3 -3
- package/build/src/sync/sync-channel-name.d.ts +9 -0
- package/build/src/sync/sync-channel-name.d.ts.map +1 -0
- package/build/src/sync/sync-channel-name.js +10 -0
- package/build/src/sync/sync-client-types.d.ts +10 -7
- package/build/src/sync/sync-client-types.d.ts.map +1 -1
- package/build/src/sync/sync-client-types.js +1 -1
- package/build/src/sync/sync-client.d.ts +1 -1
- package/build/src/sync/sync-client.js +2 -2
- package/build/src/sync/sync-model-change-feed-service.d.ts +6 -1
- package/build/src/sync/sync-model-change-feed-service.d.ts.map +1 -1
- package/build/src/sync/sync-model-change-feed-service.js +15 -4
- package/build/src/sync/sync-publisher-types.d.ts +53 -21
- package/build/src/sync/sync-publisher-types.d.ts.map +1 -1
- package/build/src/sync/sync-publisher-types.js +1 -1
- package/build/src/sync/sync-publisher.d.ts +32 -9
- package/build/src/sync/sync-publisher.d.ts.map +1 -1
- package/build/src/sync/sync-publisher.js +170 -37
- package/build/src/sync/sync-realtime-bridge.d.ts +33 -10
- package/build/src/sync/sync-realtime-bridge.d.ts.map +1 -1
- package/build/src/sync/sync-realtime-bridge.js +51 -12
- package/build/src/sync/sync-scope-attributes.d.ts +15 -0
- package/build/src/sync/sync-scope-attributes.d.ts.map +1 -0
- package/build/src/sync/sync-scope-attributes.js +24 -0
- package/build/src/sync/sync-websocket-channel.d.ts +58 -0
- package/build/src/sync/sync-websocket-channel.d.ts.map +1 -0
- package/build/src/sync/sync-websocket-channel.js +131 -0
- package/build/sync/sync-channel-name.js +10 -0
- package/build/sync/sync-client-types.js +12 -6
- package/build/sync/sync-client.js +1 -1
- package/build/sync/sync-model-change-feed-service.js +17 -3
- package/build/sync/sync-publisher-types.js +32 -12
- package/build/sync/sync-publisher.js +192 -41
- package/build/sync/sync-realtime-bridge.js +56 -11
- package/build/sync/sync-scope-attributes.js +26 -0
- package/build/sync/sync-websocket-channel.js +146 -0
- package/build/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/application.js +2 -0
- package/src/configuration-types.js +8 -8
- package/src/configuration.js +2 -2
- package/src/sync/sync-channel-name.js +10 -0
- package/src/sync/sync-client-types.js +12 -6
- package/src/sync/sync-client.js +1 -1
- package/src/sync/sync-model-change-feed-service.js +17 -3
- package/src/sync/sync-publisher-types.js +32 -12
- package/src/sync/sync-publisher.js +192 -41
- package/src/sync/sync-realtime-bridge.js +56 -11
- package/src/sync/sync-scope-attributes.js +26 -0
- package/src/sync/sync-websocket-channel.js +146 -0
|
@@ -2,8 +2,10 @@
|
|
|
2
2
|
import Configuration from "../configuration.js";
|
|
3
3
|
import Logger from "../logger.js";
|
|
4
4
|
import restArgsError from "../utils/rest-args-error.js";
|
|
5
|
+
import { declaredSyncScopeAttributes } from "./sync-scope-attributes.js";
|
|
5
6
|
import { deliverDeclaredBroadcasts, upsertSyncRow } from "./sync-change-fanout.js";
|
|
6
7
|
import { isPublishingSuppressed } from "./sync-publish-suppression.js";
|
|
8
|
+
import { VELOCIOUS_SYNC_CHANNEL } from "./sync-channel-name.js";
|
|
7
9
|
/** @type {{create: "afterCreate", update: "afterUpdate", destroy: "afterDestroy"}} */
|
|
8
10
|
const PUBLISHED_CALLBACK_NAMES = { create: "afterCreate", destroy: "afterDestroy", update: "afterUpdate" };
|
|
9
11
|
/**
|
|
@@ -23,16 +25,23 @@ const startedPublishersByConfiguration = new WeakMap();
|
|
|
23
25
|
* Server models declare what to publish through `static sync`'s `publish`
|
|
24
26
|
* key, and Velocious writes every committed server-side change to the sync
|
|
25
27
|
* change feed (model-backed Sync-row upsert with server re-sequencing) and
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
+
* broadcasts the standard sync envelope (`{echoOrigin, syncs: [...]}`) on the
|
|
29
|
+
* framework sync channel ({@link VELOCIOUS_SYNC_CHANNEL}) scoped by the
|
|
30
|
+
* change's derived scope-partition values, so devices receive server-origin
|
|
31
|
+
* changes without app code declaring channels or calling manual
|
|
32
|
+
* upsert/broadcast helpers:
|
|
28
33
|
*
|
|
29
|
-
* static sync = {
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
34
|
+
* static sync = {publish: true} // default payload (attributes) + default scope partition
|
|
35
|
+
* static sync = {publish: {serialize: (record) => ({id: record.id(), pin: record.pin()})}}
|
|
36
|
+
*
|
|
37
|
+
* The scope partition comes from the sync model's `static
|
|
38
|
+
* syncScopeAttributes` declaration (for example `["eventId"]` or
|
|
39
|
+
* `["accountId"]` — Velocious has no built-in partition name): each declared
|
|
40
|
+
* scope attribute reads the record's attribute of the same name when the
|
|
41
|
+
* model has one, else the record's own id (scope-root models), overridable
|
|
42
|
+
* per model through `publish: {scopeAttributes: {accountId: "ownerId"}}`.
|
|
43
|
+
* The pre-framework-channel `broadcasts` list and the `eventId`
|
|
44
|
+
* string/resolver-function declaration forms keep working but are deprecated.
|
|
36
45
|
*
|
|
37
46
|
* Replayed device mutations never double-publish: the framework's routed
|
|
38
47
|
* replay apply marks its written records through `markServerApply(record)`
|
|
@@ -53,22 +62,22 @@ export default class SyncPublisher {
|
|
|
53
62
|
const { actorForeignKeyColumn = "authentication_token_id", broadcaster, configuration = Configuration.current(), onError, syncModel, ...restOptions } = options;
|
|
54
63
|
restArgsError(restOptions);
|
|
55
64
|
const modelClasses = configuration.getModelClasses();
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
for (const modelClass of Object.values(modelClasses)) {
|
|
59
|
-
const publish = publishDeclarationFor(modelClass);
|
|
60
|
-
if (!publish)
|
|
61
|
-
continue;
|
|
62
|
-
const resourceConfig = resourceConfigFromPublishDeclaration({ modelClass, publish });
|
|
63
|
-
resources[resourceConfig.resourceType] = resourceConfig;
|
|
64
|
-
}
|
|
65
|
-
if (Object.keys(resources).length === 0) {
|
|
65
|
+
const publishingModelClasses = Object.values(modelClasses).filter((modelClass) => publishDeclarationFor(modelClass));
|
|
66
|
+
if (publishingModelClasses.length === 0) {
|
|
66
67
|
throw new Error("SyncPublisher found no registered models declaring static sync publish - declare `static sync = {publish: {serialize}}` on the models whose server-side changes should publish to the sync feed");
|
|
67
68
|
}
|
|
68
69
|
const resolvedSyncModel = syncModel || modelClasses.Sync;
|
|
69
70
|
if (!resolvedSyncModel) {
|
|
70
71
|
throw new Error("SyncPublisher requires a registered \"Sync\" model for published sync change rows (or pass options.syncModel)");
|
|
71
72
|
}
|
|
73
|
+
const scopeAttributes = declaredSyncScopeAttributes(resolvedSyncModel);
|
|
74
|
+
/** @type {Record<string, import("./sync-publisher-types.js").SyncPublisherResourceConfig>} */
|
|
75
|
+
const resources = {};
|
|
76
|
+
for (const modelClass of publishingModelClasses) {
|
|
77
|
+
const publish = publishDeclarationFor(modelClass);
|
|
78
|
+
const resourceConfig = resourceConfigFromPublishDeclaration({ modelClass, publish, scopeAttributes, syncModel: resolvedSyncModel });
|
|
79
|
+
resources[resourceConfig.resourceType] = resourceConfig;
|
|
80
|
+
}
|
|
72
81
|
/** @type {{actorForeignKeyColumn: string, broadcaster: import("./sync-publisher-types.js").SyncPublisherOptions["broadcaster"], configuration: Configuration, onError: import("./sync-publisher-types.js").SyncPublisherOptions["onError"], resources: Record<string, import("./sync-publisher-types.js").SyncPublisherResourceConfig>, syncModel: ?}} */
|
|
73
82
|
this.config = { actorForeignKeyColumn, broadcaster, configuration, onError, resources, syncModel: resolvedSyncModel };
|
|
74
83
|
/** @type {Array<{callback: (record: ?) => Promise<void>, callbackName: "afterCreate" | "afterUpdate" | "afterDestroy", modelClass: ?}>} */
|
|
@@ -157,6 +166,7 @@ export default class SyncPublisher {
|
|
|
157
166
|
const data = await resourceConfig.serialize(record);
|
|
158
167
|
const resourceId = String(record.id());
|
|
159
168
|
const syncType = operation === "destroy" ? "delete" : "update";
|
|
169
|
+
const scopeValues = await this.publishedScopeValues({ record, resourceConfig });
|
|
160
170
|
/** @type {Record<string, ?>} */
|
|
161
171
|
const attributes = {
|
|
162
172
|
[this.config.actorForeignKeyColumn]: null,
|
|
@@ -164,15 +174,20 @@ export default class SyncPublisher {
|
|
|
164
174
|
data: JSON.stringify(data),
|
|
165
175
|
resource_id: resourceId,
|
|
166
176
|
resource_type: resourceConfig.resourceType,
|
|
167
|
-
sync_type: syncType
|
|
177
|
+
sync_type: syncType,
|
|
178
|
+
...scopeValues.columns
|
|
168
179
|
};
|
|
169
|
-
if (resourceConfig.eventId) {
|
|
170
|
-
const eventId = await resourceConfig.eventId(record);
|
|
171
|
-
attributes.event_id = eventId === undefined || eventId === null ? null : String(eventId);
|
|
172
|
-
}
|
|
173
180
|
await resourceConfig.modelClass.connection().afterCommit(async () => {
|
|
174
181
|
try {
|
|
175
182
|
const syncRow = await this.upsertPublishedSyncRow(attributes);
|
|
183
|
+
await this.broadcaster()({
|
|
184
|
+
body: {
|
|
185
|
+
echoOrigin: null,
|
|
186
|
+
syncs: [{ data, resourceId, resourceType: resourceConfig.resourceType, syncType }]
|
|
187
|
+
},
|
|
188
|
+
channel: VELOCIOUS_SYNC_CHANNEL,
|
|
189
|
+
params: { ...scopeValues.params, resourceType: resourceConfig.resourceType }
|
|
190
|
+
});
|
|
176
191
|
if (resourceConfig.broadcasts) {
|
|
177
192
|
await deliverDeclaredBroadcasts({
|
|
178
193
|
args: { data, operation, record, resourceId, resourceType: resourceConfig.resourceType, syncRow, syncType },
|
|
@@ -187,6 +202,38 @@ export default class SyncPublisher {
|
|
|
187
202
|
});
|
|
188
203
|
};
|
|
189
204
|
}
|
|
205
|
+
/**
|
|
206
|
+
* Resolves the scope-partition values for one published mutation from the
|
|
207
|
+
* resource's derived scope plan: each entry reads its record attribute (or
|
|
208
|
+
* the record's own id for scope-root models, or the deprecated resolver
|
|
209
|
+
* function). The values are persisted onto the sync row's partition columns
|
|
210
|
+
* and broadcast as the framework sync channel's scoping params.
|
|
211
|
+
* @param {{record: ?, resourceConfig: import("./sync-publisher-types.js").SyncPublisherResourceConfig}} args - Mutated record and resource config.
|
|
212
|
+
* @returns {Promise<{columns: Record<string, string | null>, params: Record<string, string | null>}>} Scope values keyed by sync-row column and by scope attribute.
|
|
213
|
+
*/
|
|
214
|
+
async publishedScopeValues({ record, resourceConfig }) {
|
|
215
|
+
/** @type {Record<string, string | null>} */
|
|
216
|
+
const columns = {};
|
|
217
|
+
/** @type {Record<string, string | null>} */
|
|
218
|
+
const params = {};
|
|
219
|
+
for (const scopePlanEntry of resourceConfig.scopePlan) {
|
|
220
|
+
/** @type {?} */
|
|
221
|
+
let rawValue;
|
|
222
|
+
if (scopePlanEntry.resolver) {
|
|
223
|
+
rawValue = await scopePlanEntry.resolver(record);
|
|
224
|
+
}
|
|
225
|
+
else if (scopePlanEntry.recordAttribute) {
|
|
226
|
+
rawValue = record.readAttribute(scopePlanEntry.recordAttribute);
|
|
227
|
+
}
|
|
228
|
+
else {
|
|
229
|
+
rawValue = record.id();
|
|
230
|
+
}
|
|
231
|
+
const value = rawValue === undefined || rawValue === null ? null : String(rawValue);
|
|
232
|
+
columns[scopePlanEntry.columnName] = value;
|
|
233
|
+
params[scopePlanEntry.scopeAttribute] = value;
|
|
234
|
+
}
|
|
235
|
+
return { columns, params };
|
|
236
|
+
}
|
|
190
237
|
/**
|
|
191
238
|
* Upserts the published server-origin sync row for a resource identity:
|
|
192
239
|
* server-origin rows carry a null actor column (no device to echo the
|
|
@@ -256,7 +303,7 @@ export default class SyncPublisher {
|
|
|
256
303
|
* Opted-out (`publish: false`) and undeclared models resolve to null; every
|
|
257
304
|
* other declared value flows into loud declaration validation.
|
|
258
305
|
* @param {?} modelClass - Registered model class.
|
|
259
|
-
* @returns {import("./sync-publisher-types.js").
|
|
306
|
+
* @returns {import("./sync-publisher-types.js").SyncPublishDeclaration | null} Active publish declaration, or null.
|
|
260
307
|
*/
|
|
261
308
|
function publishDeclarationFor(modelClass) {
|
|
262
309
|
const declaration = modelClass.sync;
|
|
@@ -266,22 +313,24 @@ function publishDeclarationFor(modelClass) {
|
|
|
266
313
|
}
|
|
267
314
|
/**
|
|
268
315
|
* Builds one published resource config from a model's `static sync` publish
|
|
269
|
-
* declaration.
|
|
270
|
-
*
|
|
316
|
+
* declaration. `publish: true` opts in with all defaults (attribute payload,
|
|
317
|
+
* derived scope partition, created/updated operations).
|
|
318
|
+
* @param {{modelClass: ?, publish: import("./sync-publisher-types.js").SyncPublishDeclaration | null, scopeAttributes: string[] | null, syncModel: ?}} args - Declaration args plus the sync model's declared scope attributes.
|
|
271
319
|
* @returns {import("./sync-publisher-types.js").SyncPublisherResourceConfig} Derived resource config.
|
|
272
320
|
*/
|
|
273
|
-
function resourceConfigFromPublishDeclaration({ modelClass, publish }) {
|
|
321
|
+
function resourceConfigFromPublishDeclaration({ modelClass, publish, scopeAttributes: syncScopeAttributes, syncModel }) {
|
|
274
322
|
const modelName = modelClass.getModelName();
|
|
275
|
-
|
|
276
|
-
|
|
323
|
+
const normalizedPublish = publish === true ? {} : publish;
|
|
324
|
+
if (!normalizedPublish || typeof normalizedPublish !== "object" || Array.isArray(normalizedPublish)) {
|
|
325
|
+
throw new Error(`${modelName} static sync publish must be true, false or a publish declaration object, got: ${String(publish)}`);
|
|
277
326
|
}
|
|
278
|
-
const { broadcasts, eventId, operations, resourceType, serialize, ...restDeclaration } =
|
|
327
|
+
const { broadcasts, eventId, operations, resourceType, scopeAttributes, serialize, ...restDeclaration } = normalizedPublish;
|
|
279
328
|
const unknownKeys = Object.keys(restDeclaration);
|
|
280
329
|
if (unknownKeys.length > 0) {
|
|
281
|
-
throw new Error(`${modelName} static sync publish received unknown keys: ${unknownKeys.join(", ")} (supported: broadcasts, eventId, operations, resourceType, serialize)`);
|
|
330
|
+
throw new Error(`${modelName} static sync publish received unknown keys: ${unknownKeys.join(", ")} (supported: broadcasts, eventId (deprecated), operations, resourceType, scopeAttributes, serialize)`);
|
|
282
331
|
}
|
|
283
|
-
if (typeof serialize !== "function") {
|
|
284
|
-
throw new Error(`${modelName} static sync publish
|
|
332
|
+
if (serialize !== undefined && typeof serialize !== "function") {
|
|
333
|
+
throw new Error(`${modelName} static sync publish serialize must be a function building the published payload, got: ${String(serialize)}`);
|
|
285
334
|
}
|
|
286
335
|
if (operations !== undefined) {
|
|
287
336
|
if (!Array.isArray(operations) || operations.length === 0) {
|
|
@@ -295,11 +344,95 @@ function resourceConfigFromPublishDeclaration({ modelClass, publish }) {
|
|
|
295
344
|
}
|
|
296
345
|
return {
|
|
297
346
|
broadcasts,
|
|
298
|
-
eventId,
|
|
299
347
|
modelClass,
|
|
300
348
|
operations: operations === undefined ? DEFAULT_PUBLISHED_OPERATIONS : operations,
|
|
301
349
|
resourceType: resourceType === undefined ? modelName : resourceType,
|
|
302
|
-
|
|
350
|
+
scopePlan: scopePlanFor({ eventId, modelClass, modelName, scopeAttributes, syncModel, syncScopeAttributes }),
|
|
351
|
+
serialize: serialize === undefined ? defaultSerializedAttributes : serialize
|
|
303
352
|
};
|
|
304
353
|
}
|
|
305
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3luYy1wdWJsaXNoZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvc3luYy9zeW5jLXB1Ymxpc2hlci5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxZQUFZO0FBRVosT0FBTyxhQUFhLE1BQU0scUJBQXFCLENBQUE7QUFDL0MsT0FBTyxNQUFNLE1BQU0sY0FBYyxDQUFBO0FBQ2pDLE9BQU8sYUFBYSxNQUFNLDZCQUE2QixDQUFBO0FBRXZELE9BQU8sRUFBQyx5QkFBeUIsRUFBRSxhQUFhLEVBQUMsTUFBTSx5QkFBeUIsQ0FBQTtBQUNoRixPQUFPLEVBQUMsc0JBQXNCLEVBQUMsTUFBTSwrQkFBK0IsQ0FBQTtBQUVwRSxzRkFBc0Y7QUFDdEYsTUFBTSx3QkFBd0IsR0FBRyxFQUFDLE1BQU0sRUFBRSxhQUFhLEVBQUUsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLEVBQUUsYUFBYSxFQUFDLENBQUE7QUFFeEc7Ozs7OztvREFNb0Q7QUFDcEQsTUFBTSw0QkFBNEIsR0FBRyxDQUFDLFFBQVEsRUFBRSxRQUFRLENBQUMsQ0FBQTtBQUV6RCxvREFBb0Q7QUFDcEQsTUFBTSxnQ0FBZ0MsR0FBRyxJQUFJLE9BQU8sRUFBRSxDQUFBO0FBRXREOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBc0JHO0FBQ0gsTUFBTSxDQUFDLE9BQU8sT0FBTyxhQUFhO0lBQ2hDOzs7Ozs7OztPQVFHO0lBQ0gsWUFBWSxPQUFPLEdBQUcsRUFBRTtRQUN0QixNQUFNLEVBQUMscUJBQXFCLEdBQUcseUJBQXlCLEVBQUUsV0FBVyxFQUFFLGFBQWEsR0FBRyxhQUFhLENBQUMsT0FBTyxFQUFFLEVBQUUsT0FBTyxFQUFFLFNBQVMsRUFBRSxHQUFHLFdBQVcsRUFBQyxHQUFHLE9BQU8sQ0FBQTtRQUU3SixhQUFhLENBQUMsV0FBVyxDQUFDLENBQUE7UUFFMUIsTUFBTSxZQUFZLEdBQUcsYUFBYSxDQUFDLGVBQWUsRUFBRSxDQUFBO1FBQ3BELDhGQUE4RjtR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LEVBQUUsQ0FBQztZQUNuQyxJQUFJLENBQUMsQ0FBQyxTQUFTLElBQUksd0JBQXdCLENBQUMsRUFBRSxDQUFDO2dCQUM3QyxNQUFNLElBQUksS0FBSyxDQUFDLEdBQUcsU0FBUyx1RUFBdUUsTUFBTSxDQUFDLFNBQVMsQ0FBQyxFQUFFLENBQUMsQ0FBQTtZQUN6SCxDQUFDO1FBQ0gsQ0FBQztJQUNILENBQUM7SUFFRCxPQUFPO1FBQ0wsVUFBVTtRQUNWLE9BQU87UUFDUCxVQUFVO1FBQ1YsVUFBVSxFQUFFLFVBQVUsS0FBSyxTQUFTLENBQUMsQ0FBQyxDQUFDLDRCQUE0QixDQUFDLENBQUMsQ0FBQyxVQUFVO1FBQ2hGLFlBQVksRUFBRSxZQUFZLEtBQUssU0FBUyxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLFlBQVk7UUFDbkUsU0FBUztLQUNWLENBQUE7QUFDSCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQHRzLWNoZWNrXG5cbmltcG9ydCBDb25maWd1cmF0aW9uIGZyb20gXCIuLi9jb25maWd1cmF0aW9uLmpzXCJcbmltcG9ydCBMb2dnZXIgZnJvbSBcIi4uL2xvZ2dlci5qc1wiXG5pbXBvcnQgcmVzdEFyZ3NFcnJvciBmcm9tIFwiLi4vdXRpbHMvcmVzdC1hcmdzLWVycm9yLmpzXCJcblxuaW1wb3J0IHtkZWxpdmVyRGVjbGFyZWRCcm9hZGNhc3RzLCB1cHNlcnRTeW5jUm93fSBmcm9tIFwiLi9zeW5jLWNoYW5nZS1mYW5vdXQuanNcIlxuaW1wb3J0IHtpc1B1Ymxpc2hpbmdTdXBwcmVzc2VkfSBmcm9tIFwiLi9zeW5jLXB1Ymxpc2gtc3VwcHJlc3Npb24uanNcIlxuXG4vKiogQHR5cGUge3tjcmVhdGU6IFwiYWZ0ZXJDcmVhdGVcIiwgdXBkYXRlOiBcImFmdGVyVXBkYXRlXCIsIGRlc3Ryb3k6IFwiYWZ0ZXJEZXN0cm95XCJ9fSAqL1xuY29uc3QgUFVCTElTSEVEX0NBTExCQUNLX05BTUVTID0ge2NyZWF0ZTogXCJhZnRlckNyZWF0ZVwiLCBkZXN0cm95OiBcImFmdGVyRGVzdHJveVwiLCB1cGRhdGU6IFwiYWZ0ZXJVcGRhdGVcIn1cblxuLyoqXG4gKiBPcGVyYXRpb25zIHB1Ymxpc2hlZCBieSBkZWZhdWx0IGZvciBtb2RlbHMgZGVjbGFyaW5nIGBzdGF0aWMgc3luY2AgcHVibGlzaFxuICogd2l0aG91dCBhbiBgb3BlcmF0aW9uc2Aga2V5OiBzZXJ2ZXItc2lkZSBjcmVhdGVzIGFuZCB1cGRhdGVzIHB1Ymxpc2hcbiAqIGF1dG9tYXRpY2FsbHkuIERlc3Ryb3lzIGFyZSBub3QgcHVibGlzaGVkIGJ5IGRlZmF1bHQgYmVjYXVzZSBhIHNlcnZlclxuICogZGVzdHJveSBpcyBvZnRlbiBjbGVhbnVwIHJhdGhlciB0aGFuIGEgc3luY2VkIGRlbGV0ZTsgb3B0IGluIHdpdGggYW5cbiAqIG9wZXJhdGlvbnMgbGlzdC5cbiAqIEB0eXBlIHtBcnJheTxcImNyZWF0ZVwiIHwgXCJ1cGRhdGVcIiB8IFwiZGVzdHJveVwiPn0gKi9cbmNvbnN0IERFRkFVTFRfUFVCTElTSEVEX09QRVJBVElPTlMgPSBbXCJjcmVhdGVcIiwgXCJ1cGRhdGVcIl1cblxuLyoqIEB0eXBlIHtXZWFrTWFwPENvbmZpZ3VyYXRpb24sIFN5bmNQdWJsaXNoZXI+fSAqL1xuY29uc3Qgc3RhcnRlZFB1Ymxpc2hlcnNCeUNvbmZpZ3VyYXRpb24gPSBuZXcgV2Vha01hcCgpXG5cbi8qKlxuICogRGVjbGFyYXRpdmUgc2VydmVyLXNpZGUgc3luYyBwdWJsaXNoZXIg4oCUIHRoZSBzZXJ2ZXIgbWlycm9yIG9mIHRoZSBjbGllbnQnc1xuICogdHJhY2stYnktZGVmYXVsdCBtdXRhdGlvbiB0cmFja2luZy5cbiAqXG4gKiBTZXJ2ZXIgbW9kZWxzIGRlY2xhcmUgd2hhdCB0byBwdWJsaXNoIHRocm91Z2ggYHN0YXRpYyBzeW5jYCdzIGBwdWJsaXNoYFxuICoga2V5LCBhbmQgVmVsb2Npb3VzIHdyaXRlcyBldmVyeSBjb21taXR0ZWQgc2VydmVyLXNpZGUgY2hhbmdlIHRvIHRoZSBzeW5jXG4gKiBjaGFuZ2UgZmVlZCAobW9kZWwtYmFja2VkIFN5bmMtcm93IHVwc2VydCB3aXRoIHNlcnZlciByZS1zZXF1ZW5jaW5nKSBhbmRcbiAqIGZhbnMgb3V0IHRoZSBkZWNsYXJlZCBicm9hZGNhc3RzLCBzbyBkZXZpY2VzIHJlY2VpdmUgc2VydmVyLW9yaWdpbiBjaGFuZ2VzXG4gKiB3aXRob3V0IGFwcCBjb2RlIGNhbGxpbmcgbWFudWFsIHVwc2VydC9icm9hZGNhc3QgaGVscGVyczpcbiAqXG4gKiAgICAgc3RhdGljIHN5bmMgPSB7XG4gKiAgICAgICBwdWJsaXNoOiB7XG4gKiAgICAgICAgIHNlcmlhbGl6ZTogKGV2ZW50KSA9PiAoe2lkOiBldmVudC5pZCgpLCBldmVudFBpbjogZXZlbnQuZXZlbnRQaW4oKX0pLFxuICogICAgICAgICBldmVudElkOiAoZXZlbnQpID0+IGV2ZW50LmlkKCksXG4gKiAgICAgICAgIGJyb2FkY2FzdHM6IFt7Y2hhbm5lbDogXCJ0aWNrZXQtc2NhbnNcIiwgYnJvYWRjYXN0UGFyYW1zOiAuLi4sIGJvZHk6IC4uLn1dXG4gKiAgICAgICB9XG4gKiAgICAgfVxuICpcbiAqIFJlcGxheWVkIGRldmljZSBtdXRhdGlvbnMgbmV2ZXIgZG91YmxlLXB1Ymxpc2g6IHRoZSBmcmFtZXdvcmsncyByb3V0ZWRcbiAqIHJlcGxheSBhcHBseSBtYXJrcyBpdHMgd3JpdHRlbiByZWNvcmRzIHRocm91Z2ggYG1hcmtTZXJ2ZXJBcHBseShyZWNvcmQpYFxuICogKHNlZSBzeW5jLXB1Ymxpc2gtc3VwcHJlc3Npb24uanMpLCBhbmQgYXBwIGNvZGUgYXBwbHlpbmcgYWxyZWFkeS1zeW5jZWRcbiAqIGRhdGEgY2FuIHVzZSBgbWFya1NlcnZlckFwcGx5YC9gd2l0aG91dFB1Ymxpc2hpbmdgIHRoZSBzYW1lIHdheS5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgU3luY1B1Ymxpc2hlciB7XG4gIC8qKlxuICAgKiBCdWlsZHMgdGhlIHN5bmMgcHVibGlzaGVyIGJ5IGRlcml2aW5nIHB1Ymxpc2hlZCByZXNvdXJjZXMgZnJvbSB0aGVcbiAgICogY29uZmlndXJhdGlvbidzIHJlZ2lzdGVyZWQgbW9kZWxzOiBldmVyeSBtb2RlbCBkZWNsYXJpbmcgYHN0YXRpYyBzeW5jYFxuICAgKiB3aXRoIGEgYHB1Ymxpc2hgIGRlY2xhcmF0aW9uIGJlY29tZXMgYSBwdWJsaXNoZWQgcmVzb3VyY2VcbiAgICogKGBwdWJsaXNoOiBmYWxzZWAgb3B0cyBvdXQpLiBUaGUgc3luYy9jaGFuZ2UgbW9kZWwgaXMgdGhlIHJlZ2lzdGVyZWRcbiAgICogXCJTeW5jXCIgbW9kZWwgYW5kIGJyb2FkY2FzdHMgZGVmYXVsdCB0byB0aGUgY29uZmlndXJhdGlvbidzIGNoYW5uZWxcbiAgICogYnJvYWRjYXN0LlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4vc3luYy1wdWJsaXNoZXItdHlwZXMuanNcIikuU3luY1B1Ymxpc2hlck9wdGlvbnN9IFtvcHRpb25zXSAtIE9wdGlvbmFsIG92ZXJyaWRlcy5cbiAgICovXG4gIGNvbnN0cnVjdG9yKG9wdGlvbnMgPSB7fSkge1xuICAgIGNvbnN0IHthY3RvckZvcmVpZ25LZXlDb2x1bW4gPSBcImF1dGhlbnRpY2F0aW9uX3Rva2VuX2lkXCIsIGJyb2FkY2FzdGVyLCBjb25maWd1cmF0aW9uID0gQ29uZmlndXJhdGlvbi5jdXJyZW50KCksIG9uRXJyb3IsIHN5bmNNb2RlbCwgLi4ucmVzdE9wdGlvbnN9ID0gb3B0aW9uc1xuXG4gICAgcmVzdEFyZ3NFcnJvcihyZXN0T3B0aW9ucylcblxuICAgIGNvbnN0IG1vZGVsQ2xhc3NlcyA9IGNvbmZpZ3VyYXRpb24uZ2V0TW9kZWxDbGFzc2VzKClcbiAgICAvKiogQHR5cGUge1JlY29yZDxzdHJpbmcsIGltcG9ydChcIi4vc3luYy1wdWJsaXNoZXItdHlwZXMuanNcIikuU3luY1B1Ymxpc2hlclJlc291cmNlQ29uZmlnPn0gKi9cbiAgICBjb25zdCByZXNvdXJjZXMgPSB7fVxuXG4gICAgZm9yIChjb25zdCBtb2RlbENsYXNzIG9mIE9iamVjdC52YWx1ZXMobW9kZWxDbGFzc2VzKSkge1xuICAgICAgY29uc3QgcHVibGlzaCA9IHB1Ymxpc2hEZWNsYXJhdGlvbkZvcihtb2RlbENsYXNzKVxuXG4gICAgICBpZiAoIXB1Ymxpc2gpIGNvbnRpbnVlXG5cbiAgICAgIGNvbnN0IHJlc291cmNlQ29uZmlnID0gcmVzb3VyY2VDb25maWdGcm9tUHVibGlzaERlY2xhcmF0aW9uKHttb2RlbENsYXNzLCBwdWJsaXNofSlcblxuICAgICAgcmVzb3VyY2VzW3Jlc291cmNlQ29uZmlnLnJlc291cmNlVHlwZV0gPSByZXNvdXJjZUNvbmZpZ1xuICAgIH1cblxuICAgIGlmIChPYmplY3Qua2V5cyhyZXNvdXJjZXMpLmxlbmd0aCA9PT0gMCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiU3luY1B1Ymxpc2hlciBmb3VuZCBubyByZWdpc3RlcmVkIG1vZGVscyBkZWNsYXJpbmcgc3RhdGljIHN5bmMgcHVibGlzaCAtIGRlY2xhcmUgYHN0YXRpYyBzeW5jID0ge3B1Ymxpc2g6IHtzZXJpYWxpemV9fWAgb24gdGhlIG1vZGVscyB3aG9zZSBzZXJ2ZXItc2lkZSBjaGFuZ2VzIHNob3VsZCBwdWJsaXNoIHRvIHRoZSBzeW5jIGZlZWRcIilcbiAgICB9XG5cbiAgICBjb25zdCByZXNvbHZlZFN5bmNNb2RlbCA9IHN5bmNNb2RlbCB8fCBtb2RlbENsYXNzZXMuU3luY1xuXG4gICAgaWYgKCFyZXNvbHZlZFN5bmNNb2RlbCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiU3luY1B1Ymxpc2hlciByZXF1aXJlcyBhIHJlZ2lzdGVyZWQgXFxcIlN5bmNcXFwiIG1vZGVsIGZvciBwdWJsaXNoZWQgc3luYyBjaGFuZ2Ugcm93cyAob3IgcGFzcyBvcHRpb25zLnN5bmNNb2RlbClcIilcbiAgICB9XG5cbiAgICAvKiogQHR5cGUge3thY3RvckZvcmVpZ25LZXlDb2x1bW46IHN0cmluZywgYnJvYWRjYXN0ZXI6IGltcG9ydChcIi4vc3luYy1wdWJsaXNoZXItdHlwZXMuanNcIikuU3luY1B1Ymxpc2hlck9wdGlvbnNbXCJicm9hZGNhc3RlclwiXSwgY29uZmlndXJhdGlvbjogQ29uZmlndXJhdGlvbiwgb25FcnJvcjogaW1wb3J0KFwiLi9zeW5jLXB1Ymxpc2hlci10eXBlcy5qc1wiKS5TeW5jUHVibGlzaGVyT3B0aW9uc1tcIm9uRXJyb3JcIl0sIHJlc291cmNlczogUmVjb3JkPHN0cmluZywgaW1wb3J0KFwiLi9zeW5jLXB1Ymxpc2hlci10eXBlcy5qc1wiKS5TeW5jUHVibGlzaGVyUmVzb3VyY2VDb25maWc+LCBzeW5jTW9kZWw6ID99fSAqL1xuICAgIHRoaXMuY29uZmlnID0ge2FjdG9yRm9yZWlnbktleUNvbHVtbiwgYnJvYWRjYXN0ZXIsIGNvbmZpZ3VyYXRpb24sIG9uRXJyb3IsIHJlc291cmNlcywgc3luY01vZGVsOiByZXNvbHZlZFN5bmNNb2RlbH1cbiAgICAvKiogQHR5cGUge0FycmF5PHtjYWxsYmFjazogKHJlY29yZDogPykgPT4gUHJvbWlzZTx2b2lkPiwgY2FsbGJhY2tOYW1lOiBcImFmdGVyQ3JlYXRlXCIgfCBcImFmdGVyVXBkYXRlXCIgfCBcImFmdGVyRGVzdHJveVwiLCBtb2RlbENsYXNzOiA/fT59ICovXG4gICAgdGhpcy5fcHVibGlzaGVkQ2FsbGJhY2tzID0gW11cbiAgICAvKiogQHR5cGUge0xvZ2dlciB8IG51bGx9ICovXG4gICAgdGhpcy5fbG9nZ2VyID0gbnVsbFxuICAgIHRoaXMuX3N0YXJ0ZWQgPSBmYWxzZVxuICB9XG5cbiAgLyoqXG4gICAqIEJ1aWxkcyBhIHN5bmMgcHVibGlzaGVyIGRlcml2ZWQgZnJvbSB0aGUgZ2l2ZW4gY29uZmlndXJhdGlvbi4gQWxpYXMgZm9yXG4gICAqIGBuZXcgU3luY1B1Ymxpc2hlcih7Y29uZmlndXJhdGlvbiwgLi4ub3B0aW9uc30pYC5cbiAgICogQHBhcmFtIHtDb25maWd1cmF0aW9ufSBbY29uZmlndXJhdGlvbl0gLSBDb25maWd1cmF0aW9uIG93bmluZyB0aGUgcmVnaXN0ZXJlZCBtb2RlbHMuIERlZmF1bHRzIHRvIHRoZSBjdXJyZW50IGNvbmZpZ3VyYXRpb24uXG4gICAqIEBwYXJhbSB7T21pdDxpbXBvcnQoXCIuL3N5bmMtcHVibGlzaGVyLXR5cGVzLmpzXCIpLlN5bmNQdWJsaXNoZXJPcHRpb25zLCBcImNvbmZpZ3VyYXRpb25cIj59IFtvcHRpb25zXSAtIE9wdGlvbmFsIG92ZXJyaWRlcy5cbiAgICogQHJldHVybnMge1N5bmNQdWJsaXNoZXJ9IFN5bmMgcHVibGlzaGVyIGRlcml2ZWQgZnJvbSB0aGUgY29uZmlndXJhdGlvbi5cbiAgICovXG4gIHN0YXRpYyBmcm9tQ29uZmlndXJhdGlvbihjb25maWd1cmF0aW9uID0gQ29uZmlndXJhdGlvbi5jdXJyZW50KCksIG9wdGlvbnMgPSB7fSkge1xuICAgIHJldHVybiBuZXcgU3luY1B1Ymxpc2hlcih7Li4ub3B0aW9ucywgY29uZmlndXJhdGlvbn0pXG4gIH1cblxuICAvKipcbiAgICogU3RhcnRzIChhbmQgbWVtb2l6ZXMgcGVyIGNvbmZpZ3VyYXRpb24pIHRoZSBzeW5jIHB1Ymxpc2hlciBmb3IgYSBzZXJ2ZXJcbiAgICogYm9vdDogbm8tb3Agd2hlbiBubyByZWdpc3RlcmVkIG1vZGVsIGRlY2xhcmVzIGEgcHVibGlzaCBjb25maWcsIGd1YXJkZWQgc29cbiAgICogcmVwZWF0ZWQgYm9vdHMgd2l0aCB0aGUgc2FtZSBjb25maWd1cmF0aW9uIHJlZ2lzdGVyIHRoZSBwdWJsaXNoIGNhbGxiYWNrc1xuICAgKiBvbmx5IG9uY2UuXG4gICAqIEBwYXJhbSB7Q29uZmlndXJhdGlvbn0gY29uZmlndXJhdGlvbiAtIENvbmZpZ3VyYXRpb24gb3duaW5nIHRoZSByZWdpc3RlcmVkIG1vZGVscy5cbiAgICogQHJldHVybnMge1Byb21pc2U8U3luY1B1Ymxpc2hlciB8IG51bGw+fSBTdGFydGVkIHB1Ymxpc2hlciwgb3IgbnVsbCB3aGVuIG5vIG1vZGVscyBkZWNsYXJlIHB1Ymxpc2guXG4gICAqL1xuICBzdGF0aWMgYXN5bmMgc3RhcnRGcm9tQ29uZmlndXJhdGlvbihjb25maWd1cmF0aW9uKSB7XG4gICAgY29uc3Qgc3RhcnRlZFB1Ymxpc2hlciA9IHN0YXJ0ZWRQdWJsaXNoZXJzQnlDb25maWd1cmF0aW9uLmdldChjb25maWd1cmF0aW9uKVxuXG4gICAgaWYgKHN0YXJ0ZWRQdWJsaXNoZXIpIHJldHVybiBzdGFydGVkUHVibGlzaGVyXG5cbiAgICBpZiAoIU9iamVjdC52YWx1ZXMoY29uZmlndXJhdGlvbi5nZXRNb2RlbENsYXNzZXMoKSkuc29tZSgobW9kZWxDbGFzcykgPT4gcHVibGlzaERlY2xhcmF0aW9uRm9yKG1vZGVsQ2xhc3MpKSkgcmV0dXJuIG51bGxcblxuICAgIGNvbnN0IHB1Ymxpc2hlciA9IG5ldyBTeW5jUHVibGlzaGVyKHtjb25maWd1cmF0aW9ufSlcblxuICAgIHN0YXJ0ZWRQdWJsaXNoZXJzQnlDb25maWd1cmF0aW9uLnNldChjb25maWd1cmF0aW9uLCBwdWJsaXNoZXIpXG4gICAgYXdhaXQgcHVibGlzaGVyLnN0YXJ0KClcblxuICAgIHJldHVybiBwdWJsaXNoZXJcbiAgfVxuXG4gIC8qKlxuICAgKiBSZWdpc3RlcnMgdGhlIHB1Ymxpc2ggY2FsbGJhY2tzIGZvciBldmVyeSBwdWJsaXNoZWQgcmVzb3VyY2U6IHNlcnZlci1zaWRlXG4gICAqIGNyZWF0ZXMgYW5kIHVwZGF0ZXMgKGRlc3Ryb3lzIHdoZW4gb3B0ZWQgaW4pIHVwc2VydCBhIHN5bmMgY2hhbmdlIHJvdyBhbmRcbiAgICogZmFuIG91dCB0aGUgZGVjbGFyZWQgYnJvYWRjYXN0cyBvbmNlIHRoZWlyIHRyYW5zYWN0aW9uIGNvbW1pdHMuXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fVxuICAgKi9cbiAgYXN5bmMgc3RhcnQoKSB7XG4gICAgaWYgKHRoaXMuX3N0YXJ0ZWQpIHJldHVyblxuXG4gICAgdGhpcy5fc3RhcnRlZCA9IHRydWVcblxuICAgIGZvciAoY29uc3QgcmVzb3VyY2VDb25maWcgb2YgT2JqZWN0LnZhbHVlcyh0aGlzLmNvbmZpZy5yZXNvdXJjZXMpKSB7XG4gICAgICBmb3IgKGNvbnN0IG9wZXJhdGlvbiBvZiByZXNvdXJjZUNvbmZpZy5vcGVyYXRpb25zKSB7XG4gICAgICAgIGNvbnN0IGNhbGxiYWNrTmFtZSA9IFBVQkxJU0hFRF9DQUxMQkFDS19OQU1FU1tvcGVyYXRpb25dXG4gICAgICAgIGNvbnN0IGNhbGxiYWNrID0gdGhpcy5wdWJsaXNoZWRNdXRhdGlvbkNhbGxiYWNrKHtvcGVyYXRpb24sIHJlc291cmNlQ29uZmlnfSlcblxuICAgICAgICByZXNvdXJjZUNvbmZpZy5tb2RlbENsYXNzW2NhbGxiYWNrTmFtZV0oY2FsbGJhY2spXG4gICAgICAgIHRoaXMuX3B1Ymxpc2hlZENhbGxiYWNrcy5wdXNoKHtjYWxsYmFjaywgY2FsbGJhY2tOYW1lLCBtb2RlbENsYXNzOiByZXNvdXJjZUNvbmZpZy5tb2RlbENsYXNzfSlcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogVW5yZWdpc3RlcnMgYWxsIHB1Ymxpc2ggY2FsbGJhY2tzICh0ZXN0cywgc2h1dGRvd24pLlxuICAgKiBAcmV0dXJucyB7dm9pZH1cbiAgICovXG4gIHN0b3AoKSB7XG4gICAgZm9yIChjb25zdCB7Y2FsbGJhY2ssIGNhbGxiYWNrTmFtZSwgbW9kZWxDbGFzc30gb2YgdGhpcy5fcHVibGlzaGVkQ2FsbGJhY2tzKSB7XG4gICAgICBtb2RlbENsYXNzLnVucmVnaXN0ZXJMaWZlY3ljbGVDYWxsYmFjayhjYWxsYmFja05hbWUsIGNhbGxiYWNrKVxuICAgIH1cblxuICAgIHRoaXMuX3B1Ymxpc2hlZENhbGxiYWNrcyA9IFtdXG4gICAgdGhpcy5fc3RhcnRlZCA9IGZhbHNlXG4gIH1cblxuICAvKipcbiAgICogQnVpbGRzIHRoZSBsaWZlY3ljbGUgY2FsbGJhY2sgcHVibGlzaGluZyBvbmUgc2VydmVyLXNpZGUgbXV0YXRpb24uIFRoZVxuICAgKiBwdWJsaXNoZWQgcGF5bG9hZCAoZGVjbGFyYXRpb24gYHNlcmlhbGl6ZWApLCBldmVudCBzY29wZSwgYW5kIHN5bmMgdHlwZVxuICAgKiBhcmUgc25hcHNob3R0ZWQgYXQgbXV0YXRpb24tY2FsbGJhY2sgdGltZSwgc28gYWZ0ZXJTYXZlIGhvb2tzIGFzc2lnbmluZ1xuICAgKiB1bnNhdmVkIGF0dHJpYnV0ZXMgKG9yIGFueSBsYXRlciBkcmlmdCBvbiB0aGUgcmVjb3JkKSBjYW5ub3QgY2hhbmdlIHdoYXRcbiAgICogZ2V0cyBwdWJsaXNoZWQgdnMgd2hhdCB3YXMgY29tbWl0dGVkLiBQZXJzaXN0aW5nIGFuZCBicm9hZGNhc3RpbmcgYXJlXG4gICAqIGRlZmVycmVkIHRocm91Z2ggdGhlIG1vZGVsIGNvbm5lY3Rpb24ncyBhZnRlckNvbW1pdCBob29rIHNvIHRoZXkgb25seSBydW5cbiAgICogb25jZSB0aGUgbXV0YXRpb24ncyB0cmFuc2FjdGlvbiBoYXMgY29tbWl0dGVkIChpbW1lZGlhdGVseSB3aGVuIG5vXG4gICAqIHRyYW5zYWN0aW9uIGlzIG9wZW4pIC0gcm9sbGVkLWJhY2sgbXV0YXRpb25zIG5ldmVyIHB1Ymxpc2guIFBvc3QtY29tbWl0XG4gICAqIHB1Ymxpc2ggZmFpbHVyZXMgYXJlIHJlcG9ydGVkIHdpdGhvdXQgcmV0aHJvd2luZyBpbnRvIHRoZSBkcml2ZXInc1xuICAgKiBhZnRlckNvbW1pdCBjaGFpbiAoc2VlIHJlcG9ydEFmdGVyQ29tbWl0RXJyb3IpLlxuICAgKiBAcGFyYW0ge3tvcGVyYXRpb246IFwiY3JlYXRlXCIgfCBcInVwZGF0ZVwiIHwgXCJkZXN0cm95XCIsIHJlc291cmNlQ29uZmlnOiBpbXBvcnQoXCIuL3N5bmMtcHVibGlzaGVyLXR5cGVzLmpzXCIpLlN5bmNQdWJsaXNoZXJSZXNvdXJjZUNvbmZpZ319IGFyZ3MgLSBPcGVyYXRpb24gYW5kIHJlc291cmNlIGNvbmZpZy5cbiAgICogQHJldHVybnMgeyhyZWNvcmQ6ID8pID0+IFByb21pc2U8dm9pZD59IExpZmVjeWNsZSBjYWxsYmFjay5cbiAgICovXG4gIHB1Ymxpc2hlZE11dGF0aW9uQ2FsbGJhY2soe29wZXJhdGlvbiwgcmVzb3VyY2VDb25maWd9KSB7XG4gICAgcmV0dXJuIGFzeW5jIChyZWNvcmQpID0+IHtcbiAgICAgIGlmIChpc1B1Ymxpc2hpbmdTdXBwcmVzc2VkKHJlY29yZCkpIHJldHVyblxuXG4gICAgICBjb25zdCBkYXRhID0gYXdhaXQgcmVzb3VyY2VDb25maWcuc2VyaWFsaXplKHJlY29yZClcbiAgICAgIGNvbnN0IHJlc291cmNlSWQgPSBTdHJpbmcocmVjb3JkLmlkKCkpXG4gICAgICBjb25zdCBzeW5jVHlwZSA9IG9wZXJhdGlvbiA9PT0gXCJkZXN0cm95XCIgPyBcImRlbGV0ZVwiIDogXCJ1cGRhdGVcIlxuICAgICAgLyoqIEB0eXBlIHtSZWNvcmQ8c3RyaW5nLCA/Pn0gKi9cbiAgICAgIGNvbnN0IGF0dHJpYnV0ZXMgPSB7XG4gICAgICAgIFt0aGlzLmNvbmZpZy5hY3RvckZvcmVpZ25LZXlDb2x1bW5dOiBudWxsLFxuICAgICAgICBjbGllbnRfdXBkYXRlZF9hdDogbmV3IERhdGUoKSxcbiAgICAgICAgZGF0YTogSlNPTi5zdHJpbmdpZnkoZGF0YSksXG4gICAgICAgIHJlc291cmNlX2lkOiByZXNvdXJjZUlkLFxuICAgICAgICByZXNvdXJjZV90eXBlOiByZXNvdXJjZUNvbmZpZy5yZXNvdXJjZVR5cGUsXG4gICAgICAgIHN5bmNfdHlwZTogc3luY1R5cGVcbiAgICAgIH1cblxuICAgICAgaWYgKHJlc291cmNlQ29uZmlnLmV2ZW50SWQpIHtcbiAgICAgICAgY29uc3QgZXZlbnRJZCA9IGF3YWl0IHJlc291cmNlQ29uZmlnLmV2ZW50SWQocmVjb3JkKVxuXG4gICAgICAgIGF0dHJpYnV0ZXMuZXZlbnRfaWQgPSBldmVudElkID09PSB1bmRlZmluZWQgfHwgZXZlbnRJZCA9PT0gbnVsbCA/IG51bGwgOiBTdHJpbmcoZXZlbnRJZClcbiAgICAgIH1cblxuICAgICAgYXdhaXQgcmVzb3VyY2VDb25maWcubW9kZWxDbGFzcy5jb25uZWN0aW9uKCkuYWZ0ZXJDb21taXQoYXN5bmMgKCkgPT4ge1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGNvbnN0IHN5bmNSb3cgPSBhd2FpdCB0aGlzLnVwc2VydFB1Ymxpc2hlZFN5bmNSb3coYXR0cmlidXRlcylcblxuICAgICAgICAgIGlmIChyZXNvdXJjZUNvbmZpZy5icm9hZGNhc3RzKSB7XG4gICAgICAgICAgICBhd2FpdCBkZWxpdmVyRGVjbGFyZWRCcm9hZGNhc3RzKHtcbiAgICAgICAgICAgICAgYXJnczoge2RhdGEsIG9wZXJhdGlvbiwgcmVjb3JkLCByZXNvdXJjZUlkLCByZXNvdXJjZVR5cGU6IHJlc291cmNlQ29uZmlnLnJlc291cmNlVHlwZSwgc3luY1Jvdywgc3luY1R5cGV9LFxuICAgICAgICAgICAgICBicm9hZGNhc3RlcjogdGhpcy5icm9hZGNhc3RlcigpLFxuICAgICAgICAgICAgICBicm9hZGNhc3RzOiByZXNvdXJjZUNvbmZpZy5icm9hZGNhc3RzXG4gICAgICAgICAgICB9KVxuICAgICAgICAgIH1cbiAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICBhd2FpdCB0aGlzLnJlcG9ydEFmdGVyQ29tbWl0RXJyb3IoLyoqIEB0eXBlIHtFcnJvcn0gKi8gKGVycm9yKSlcbiAgICAgICAgfVxuICAgICAgfSlcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogVXBzZXJ0cyB0aGUgcHVibGlzaGVkIHNlcnZlci1vcmlnaW4gc3luYyByb3cgZm9yIGEgcmVzb3VyY2UgaWRlbnRpdHk6XG4gICAqIHNlcnZlci1vcmlnaW4gcm93cyBjYXJyeSBhIG51bGwgYWN0b3IgY29sdW1uIChubyBkZXZpY2UgdG8gZWNobyB0aGVcbiAgICogY2hhbmdlIGJhY2sgdG8pLCBzbyByZXBlYXRlZCBzZXJ2ZXIgY2hhbmdlcyB0byBvbmUgcmVzb3VyY2UgcmV1c2UgYW5kXG4gICAqIHJlLXNlcXVlbmNlIG9uZSBmZWVkIHJvdy5cbiAgICogQHBhcmFtIHtSZWNvcmQ8c3RyaW5nLCA/Pn0gYXR0cmlidXRlcyAtIFNuYXBzaG90dGVkIHN5bmMgcm93IGF0dHJpYnV0ZXMuXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPD8+fSBVcHNlcnRlZCBzeW5jIHJvdy5cbiAgICovXG4gIGFzeW5jIHVwc2VydFB1Ymxpc2hlZFN5bmNSb3coYXR0cmlidXRlcykge1xuICAgIGNvbnN0IGV4aXN0aW5nU3luYyA9IGF3YWl0IHRoaXMuY29uZmlnLnN5bmNNb2RlbFxuICAgICAgLndoZXJlKHtcbiAgICAgICAgW3RoaXMuY29uZmlnLmFjdG9yRm9yZWlnbktleUNvbHVtbl06IG51bGwsXG4gICAgICAgIHJlc291cmNlX2lkOiBhdHRyaWJ1dGVzLnJlc291cmNlX2lkLFxuICAgICAgICByZXNvdXJjZV90eXBlOiBhdHRyaWJ1dGVzLnJlc291cmNlX3R5cGVcbiAgICAgIH0pXG4gICAgICAuZmlyc3QoKVxuXG4gICAgcmV0dXJuIGF3YWl0IHVwc2VydFN5bmNSb3coe2F0dHJpYnV0ZXMsIGV4aXN0aW5nU3luYywgc3luY01vZGVsOiB0aGlzLmNvbmZpZy5zeW5jTW9kZWx9KVxuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIGJyb2FkY2FzdGVyIGRlbGl2ZXJpbmcgZGVjbGFyZWQgYnJvYWRjYXN0czogdGhlIGluamVjdGVkIG9uZSxcbiAgICogb3IgdGhlIGNvbmZpZ3VyYXRpb24ncyBjaGFubmVsIGJyb2FkY2FzdCBhd2FpdGVkIHRocm91Z2ggdGhlIHBlbmRpbmdcbiAgICogYnJvYWRjYXN0IHF1ZXVlLlxuICAgKiBAcmV0dXJucyB7Tm9uTnVsbGFibGU8aW1wb3J0KFwiLi9zeW5jLXB1Ymxpc2hlci10eXBlcy5qc1wiKS5TeW5jUHVibGlzaGVyT3B0aW9uc1tcImJyb2FkY2FzdGVyXCJdPn0gQnJvYWRjYXN0IGRlbGl2ZXJlci5cbiAgICovXG4gIGJyb2FkY2FzdGVyKCkge1xuICAgIGlmICh0aGlzLmNvbmZpZy5icm9hZGNhc3RlcikgcmV0dXJuIHRoaXMuY29uZmlnLmJyb2FkY2FzdGVyXG5cbiAgICByZXR1cm4gYXN5bmMgKHtib2R5LCBjaGFubmVsLCBwYXJhbXN9KSA9PiB7XG4gICAgICB0aGlzLmNvbmZpZy5jb25maWd1cmF0aW9uLmJyb2FkY2FzdFRvQ2hhbm5lbChjaGFubmVsLCBwYXJhbXMsIGJvZHkpXG4gICAgICBhd2FpdCB0aGlzLmNvbmZpZy5jb25maWd1cmF0aW9uLmF3YWl0UGVuZGluZ0Jyb2FkY2FzdHMoKVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBSZXBvcnRzIGEgcG9zdC1jb21taXQgcHVibGlzaCBmYWlsdXJlLiBUaGUgdHJhbnNhY3Rpb24gaGFzIGFscmVhZHlcbiAgICogY29tbWl0dGVkIHdoZW4gYWZ0ZXJDb21taXQgY2FsbGJhY2tzIHJ1biwgc28gcmV0aHJvd2luZyBoZXJlIHdvdWxkIHBvaXNvblxuICAgKiB0aGUgZHJpdmVyJ3MgYXdhaXRlZCBhZnRlckNvbW1pdCBjaGFpbiAoYnJlYWtpbmcgdW5yZWxhdGVkIGNhbGxiYWNrcykgLVxuICAgKiBpbnN0ZWFkIHRoZSBmYWlsdXJlIGdvZXMgdG8gdGhlIGNvbmZpZ3VyZWQgb25FcnJvciBob29rLCBvciBpcyBlbWl0dGVkIG9uXG4gICAqIHRoZSBjb25maWd1cmF0aW9uJ3MgZnJhbWV3b3JrLWVycm9yL2FsbC1lcnJvciBjaGFubmVscyAoc28gcHJvZHVjdGlvbiBidWdcbiAgICogcmVwb3J0aW5nIHZpYSBgY29uZmlndXJhdGlvbi5nZXRFcnJvckV2ZW50cygpYCBzZWVzIGEgYnJva2VuIHB1Ymxpc2hcbiAgICogcGF0aCkgYW5kIGxvZ2dlZCBsb3VkbHkgdGhyb3VnaCB0aGUgcHVibGlzaGVyJ3MgbG9nZ2VyIHdoZW4gbm9uZSBpc1xuICAgKiBjb25maWd1cmVkLlxuICAgKiBAcGFyYW0ge0Vycm9yfSBlcnJvciAtIFBvc3QtY29tbWl0IHB1Ymxpc2ggZmFpbHVyZS5cbiAgICogQHJldHVybnMge1Byb21pc2U8dm9pZD59XG4gICAqL1xuICBhc3luYyByZXBvcnRBZnRlckNvbW1pdEVycm9yKGVycm9yKSB7XG4gICAgaWYgKHRoaXMuY29uZmlnLm9uRXJyb3IpIHtcbiAgICAgIHRoaXMuY29uZmlnLm9uRXJyb3IoZXJyb3IpXG5cbiAgICAgIHJldHVyblxuICAgIH1cblxuICAgIGNvbnN0IGVycm9yRXZlbnRzID0gdGhpcy5jb25maWcuY29uZmlndXJhdGlvbi5nZXRFcnJvckV2ZW50cygpXG4gICAgY29uc3QgcGF5bG9hZCA9IHtjb250ZXh0OiB7c3RhZ2U6IFwic3luYy1wdWJsaXNoLWFmdGVyLWNvbW1pdFwifSwgZXJyb3J9XG5cbiAgICBlcnJvckV2ZW50cy5lbWl0KFwiZnJhbWV3b3JrLWVycm9yXCIsIHBheWxvYWQpXG4gICAgZXJyb3JFdmVudHMuZW1pdChcImFsbC1lcnJvclwiLCB7Li4ucGF5bG9hZCwgZXJyb3JUeXBlOiBcImZyYW1ld29yay1lcnJvclwifSlcblxuICAgIGF3YWl0IHRoaXMubG9nZ2VyKCkuZXJyb3IoXCJTeW5jUHVibGlzaGVyIGZhaWxlZCB0byBwdWJsaXNoIGEgc2VydmVyLXNpZGUgc3luYyBjaGFuZ2UgYWZ0ZXIgY29tbWl0XCIsIGVycm9yKVxuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIGxhemlseSBidWlsdCBwdWJsaXNoZXIgbG9nZ2VyLlxuICAgKiBAcmV0dXJucyB7TG9nZ2VyfSBQdWJsaXNoZXIgbG9nZ2VyLlxuICAgKi9cbiAgbG9nZ2VyKCkge1xuICAgIHRoaXMuX2xvZ2dlciB8fD0gbmV3IExvZ2dlcihcIlN5bmNQdWJsaXNoZXJcIiwge2NvbmZpZ3VyYXRpb246IHRoaXMuY29uZmlnLmNvbmZpZ3VyYXRpb259KVxuXG4gICAgcmV0dXJuIHRoaXMuX2xvZ2dlclxuICB9XG59XG5cbi8qKlxuICogUmVzb2x2ZXMgYSBtb2RlbCBjbGFzcydzIGFjdGl2ZSBwdWJsaXNoIGRlY2xhcmF0aW9uIGZyb20gYHN0YXRpYyBzeW5jYC5cbiAqIE9wdGVkLW91dCAoYHB1Ymxpc2g6IGZhbHNlYCkgYW5kIHVuZGVjbGFyZWQgbW9kZWxzIHJlc29sdmUgdG8gbnVsbDsgZXZlcnlcbiAqIG90aGVyIGRlY2xhcmVkIHZhbHVlIGZsb3dzIGludG8gbG91ZCBkZWNsYXJhdGlvbiB2YWxpZGF0aW9uLlxuICogQHBhcmFtIHs/fSBtb2RlbENsYXNzIC0gUmVnaXN0ZXJlZCBtb2RlbCBjbGFzcy5cbiAqIEByZXR1cm5zIHtpbXBvcnQoXCIuL3N5bmMtcHVibGlzaGVyLXR5cGVzLmpzXCIpLlN5bmNQdWJsaXNoRGVjbGFyYXRpb25Db25maWcgfCBudWxsfSBBY3RpdmUgcHVibGlzaCBkZWNsYXJhdGlvbiwgb3IgbnVsbC5cbiAqL1xuZnVuY3Rpb24gcHVibGlzaERlY2xhcmF0aW9uRm9yKG1vZGVsQ2xhc3MpIHtcbiAgY29uc3QgZGVjbGFyYXRpb24gPSBtb2RlbENsYXNzLnN5bmNcblxuICBpZiAoIWRlY2xhcmF0aW9uIHx8IHR5cGVvZiBkZWNsYXJhdGlvbiAhPT0gXCJvYmplY3RcIiB8fCBkZWNsYXJhdGlvbi5wdWJsaXNoID09PSB1bmRlZmluZWQgfHwgZGVjbGFyYXRpb24ucHVibGlzaCA9PT0gZmFsc2UpIHJldHVybiBudWxsXG5cbiAgcmV0dXJuIGRlY2xhcmF0aW9uLnB1Ymxpc2hcbn1cblxuLyoqXG4gKiBCdWlsZHMgb25lIHB1Ymxpc2hlZCByZXNvdXJjZSBjb25maWcgZnJvbSBhIG1vZGVsJ3MgYHN0YXRpYyBzeW5jYCBwdWJsaXNoXG4gKiBkZWNsYXJhdGlvbi5cbiAqIEBwYXJhbSB7e21vZGVsQ2xhc3M6ID8sIHB1Ymxpc2g6IGltcG9ydChcIi4vc3luYy1wdWJsaXNoZXItdHlwZXMuanNcIikuU3luY1B1Ymxpc2hEZWNsYXJhdGlvbkNvbmZpZ319IGFyZ3MgLSBEZWNsYXJhdGlvbiBhcmdzLlxuICogQHJldHVybnMge2ltcG9ydChcIi4vc3luYy1wdWJsaXNoZXItdHlwZXMuanNcIikuU3luY1B1Ymxpc2hlclJlc291cmNlQ29uZmlnfSBEZXJpdmVkIHJlc291cmNlIGNvbmZpZy5cbiAqL1xuZnVuY3Rpb24gcmVzb3VyY2VDb25maWdGcm9tUHVibGlzaERlY2xhcmF0aW9uKHttb2RlbENsYXNzLCBwdWJsaXNofSkge1xuICBjb25zdCBtb2RlbE5hbWUgPSBtb2RlbENsYXNzLmdldE1vZGVsTmFtZSgpXG5cbiAgaWYgKCFwdWJsaXNoIHx8IHR5cGVvZiBwdWJsaXNoICE9PSBcIm9iamVjdFwiIHx8IEFycmF5LmlzQXJyYXkocHVibGlzaCkpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYCR7bW9kZWxOYW1lfSBzdGF0aWMgc3luYyBwdWJsaXNoIG11c3QgYmUgZmFsc2Ugb3IgYSBwdWJsaXNoIGRlY2xhcmF0aW9uIG9iamVjdCwgZ290OiAke1N0cmluZyhwdWJsaXNoKX1gKVxuICB9XG5cbiAgY29uc3Qge2Jyb2FkY2FzdHMsIGV2ZW50SWQsIG9wZXJhdGlvbnMsIHJlc291cmNlVHlwZSwgc2VyaWFsaXplLCAuLi5yZXN0RGVjbGFyYXRpb259ID0gcHVibGlzaFxuICBjb25zdCB1bmtub3duS2V5cyA9IE9iamVjdC5rZXlzKHJlc3REZWNsYXJhdGlvbilcblxuICBpZiAodW5rbm93bktleXMubGVuZ3RoID4gMCkge1xuICAgIHRocm93IG5ldyBFcnJvcihgJHttb2RlbE5hbWV9IHN0YXRpYyBzeW5jIHB1Ymxpc2ggcmVjZWl2ZWQgdW5rbm93biBrZXlzOiAke3Vua25vd25LZXlzLmpvaW4oXCIsIFwiKX0gKHN1cHBvcnRlZDogYnJvYWRjYXN0cywgZXZlbnRJZCwgb3BlcmF0aW9ucywgcmVzb3VyY2VUeXBlLCBzZXJpYWxpemUpYClcbiAgfVxuICBpZiAodHlwZW9mIHNlcmlhbGl6ZSAhPT0gXCJmdW5jdGlvblwiKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGAke21vZGVsTmFtZX0gc3RhdGljIHN5bmMgcHVibGlzaCByZXF1aXJlcyBhIHNlcmlhbGl6ZShyZWNvcmQpIGZ1bmN0aW9uIGJ1aWxkaW5nIHRoZSBwdWJsaXNoZWQgcGF5bG9hZGApXG4gIH1cbiAgaWYgKG9wZXJhdGlvbnMgIT09IHVuZGVmaW5lZCkge1xuICAgIGlmICghQXJyYXkuaXNBcnJheShvcGVyYXRpb25zKSB8fCBvcGVyYXRpb25zLmxlbmd0aCA9PT0gMCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGAke21vZGVsTmFtZX0gc3RhdGljIHN5bmMgcHVibGlzaCBvcGVyYXRpb25zIG11c3QgYmUgYSBub24tZW1wdHkgYXJyYXkgb2YgY3JlYXRlL3VwZGF0ZS9kZXN0cm95YClcbiAgICB9XG5cbiAgICBmb3IgKGNvbnN0IG9wZXJhdGlvbiBvZiBvcGVyYXRpb25zKSB7XG4gICAgICBpZiAoIShvcGVyYXRpb24gaW4gUFVCTElTSEVEX0NBTExCQUNLX05BTUVTKSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYCR7bW9kZWxOYW1lfSBzdGF0aWMgc3luYyBwdWJsaXNoIG9wZXJhdGlvbnMgbXVzdCBiZSBjcmVhdGUvdXBkYXRlL2Rlc3Ryb3ksIGdvdDogJHtTdHJpbmcob3BlcmF0aW9uKX1gKVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiB7XG4gICAgYnJvYWRjYXN0cyxcbiAgICBldmVudElkLFxuICAgIG1vZGVsQ2xhc3MsXG4gICAgb3BlcmF0aW9uczogb3BlcmF0aW9ucyA9PT0gdW5kZWZpbmVkID8gREVGQVVMVF9QVUJMSVNIRURfT1BFUkFUSU9OUyA6IG9wZXJhdGlvbnMsXG4gICAgcmVzb3VyY2VUeXBlOiByZXNvdXJjZVR5cGUgPT09IHVuZGVmaW5lZCA/IG1vZGVsTmFtZSA6IHJlc291cmNlVHlwZSxcbiAgICBzZXJpYWxpemVcbiAgfVxufVxuIl19
|
|
354
|
+
/**
|
|
355
|
+
* Derives the scope plan partitioning a published model's changes: one entry
|
|
356
|
+
* per scope attribute declared on the sync model (`static
|
|
357
|
+
* syncScopeAttributes`), each reading the record attribute named like the
|
|
358
|
+
* scope attribute (overridable through the declaration's `scopeAttributes`
|
|
359
|
+
* name map), or the record's own id when the model has no such attribute
|
|
360
|
+
* (scope-root models). The deprecated `eventId` declaration forms map to a
|
|
361
|
+
* fixed `eventId`/`event_id` plan for 1.0.503 compatibility.
|
|
362
|
+
* @param {{eventId: import("./sync-publisher-types.js").SyncPublishDeclarationConfig["eventId"], modelClass: ?, modelName: string, scopeAttributes: Record<string, string> | undefined, syncModel: ?, syncScopeAttributes: string[] | null}} args - Declaration and sync-model scope args.
|
|
363
|
+
* @returns {Array<import("./sync-publisher-types.js").SyncPublisherScopePlanEntry>} Derived scope plan.
|
|
364
|
+
*/
|
|
365
|
+
function scopePlanFor({ eventId, modelClass, modelName, scopeAttributes, syncModel, syncScopeAttributes }) {
|
|
366
|
+
const attributeNames = Object.values(modelClass.getColumnNameToAttributeNameMap());
|
|
367
|
+
if (eventId !== undefined) {
|
|
368
|
+
if (scopeAttributes !== undefined) {
|
|
369
|
+
throw new Error(`${modelName} static sync publish can't declare both scopeAttributes and the deprecated eventId form`);
|
|
370
|
+
}
|
|
371
|
+
if (typeof eventId === "function") {
|
|
372
|
+
return [{ columnName: "event_id", recordAttribute: null, resolver: eventId, scopeAttribute: "eventId" }];
|
|
373
|
+
}
|
|
374
|
+
if (typeof eventId !== "string") {
|
|
375
|
+
throw new Error(`${modelName} static sync publish eventId must be an attribute-name string (or a deprecated resolver function), got: ${String(eventId)}`);
|
|
376
|
+
}
|
|
377
|
+
if (!attributeNames.includes(eventId)) {
|
|
378
|
+
throw new Error(`${modelName} static sync publish eventId attribute doesn't exist on the model: ${eventId}`);
|
|
379
|
+
}
|
|
380
|
+
return [{ columnName: "event_id", recordAttribute: eventId, resolver: undefined, scopeAttribute: "eventId" }];
|
|
381
|
+
}
|
|
382
|
+
if (scopeAttributes !== undefined && !syncScopeAttributes) {
|
|
383
|
+
throw new Error(`${modelName} static sync publish declares scopeAttributes but the sync model declares no static syncScopeAttributes`);
|
|
384
|
+
}
|
|
385
|
+
if (!syncScopeAttributes)
|
|
386
|
+
return [];
|
|
387
|
+
if (scopeAttributes !== undefined && (typeof scopeAttributes !== "object" || Array.isArray(scopeAttributes))) {
|
|
388
|
+
throw new Error(`${modelName} static sync publish scopeAttributes must be an object mapping scope attributes to record attribute names, got: ${String(scopeAttributes)}`);
|
|
389
|
+
}
|
|
390
|
+
for (const scopeAttribute of Object.keys(scopeAttributes || {})) {
|
|
391
|
+
if (!syncScopeAttributes.includes(scopeAttribute)) {
|
|
392
|
+
throw new Error(`${modelName} static sync publish scopeAttributes received unknown scope attribute: ${scopeAttribute} (the sync model declares: ${syncScopeAttributes.join(", ")})`);
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
return syncScopeAttributes.map((scopeAttribute) => {
|
|
396
|
+
const declaredRecordAttribute = scopeAttributes?.[scopeAttribute];
|
|
397
|
+
if (declaredRecordAttribute !== undefined) {
|
|
398
|
+
if (typeof declaredRecordAttribute !== "string" || !attributeNames.includes(declaredRecordAttribute)) {
|
|
399
|
+
throw new Error(`${modelName} static sync publish scopeAttributes.${scopeAttribute} must name an existing record attribute, got: ${String(declaredRecordAttribute)}`);
|
|
400
|
+
}
|
|
401
|
+
return { columnName: syncScopeColumnName({ scopeAttribute, syncModel }), recordAttribute: declaredRecordAttribute, resolver: undefined, scopeAttribute };
|
|
402
|
+
}
|
|
403
|
+
return {
|
|
404
|
+
columnName: syncScopeColumnName({ scopeAttribute, syncModel }),
|
|
405
|
+
recordAttribute: attributeNames.includes(scopeAttribute) ? scopeAttribute : null,
|
|
406
|
+
resolver: undefined,
|
|
407
|
+
scopeAttribute
|
|
408
|
+
};
|
|
409
|
+
});
|
|
410
|
+
}
|
|
411
|
+
/**
|
|
412
|
+
* Resolves the sync-row column persisting a declared scope attribute.
|
|
413
|
+
* @param {{scopeAttribute: string, syncModel: ?}} args - Scope attribute and sync model.
|
|
414
|
+
* @returns {string} Sync-row column name.
|
|
415
|
+
*/
|
|
416
|
+
function syncScopeColumnName({ scopeAttribute, syncModel }) {
|
|
417
|
+
const columnName = syncModel.getAttributeNameToColumnNameMap()[scopeAttribute];
|
|
418
|
+
if (!columnName) {
|
|
419
|
+
throw new Error(`${syncModel.name} declares the sync scope attribute ${scopeAttribute} but has no matching column for it`);
|
|
420
|
+
}
|
|
421
|
+
return columnName;
|
|
422
|
+
}
|
|
423
|
+
/**
|
|
424
|
+
* Default publish serializer: the record's attributes with Date values
|
|
425
|
+
* serialized to ISO strings.
|
|
426
|
+
* @param {?} record - Mutated server model record.
|
|
427
|
+
* @returns {Record<string, ?>} Serialized attributes payload.
|
|
428
|
+
*/
|
|
429
|
+
function defaultSerializedAttributes(record) {
|
|
430
|
+
/** @type {Record<string, ?>} */
|
|
431
|
+
const attributes = { ...record.attributes() };
|
|
432
|
+
for (const [attributeName, value] of Object.entries(attributes)) {
|
|
433
|
+
if (value instanceof Date)
|
|
434
|
+
attributes[attributeName] = value.toISOString();
|
|
435
|
+
}
|
|
436
|
+
return attributes;
|
|
437
|
+
}
|
|
438
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3luYy1wdWJsaXNoZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvc3luYy9zeW5jLXB1Ymxpc2hlci5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxZQUFZO0FBRVosT0FBTyxhQUFhLE1BQU0scUJBQXFCLENBQUE7QUFDL0MsT0FBTyxNQUFNLE1BQU0sY0FBYyxDQUFBO0FBQ2pDLE9BQU8sYUFBYSxNQUFNLDZCQUE2QixDQUFBO0FBRXZELE9BQU8sRUFBQywyQkFBMkIsRUFBQyxNQUFNLDRCQUE0QixDQUFBO0FBQ3RFLE9BQU8sRUFBQyx5QkFBeUIsRUFBRSxhQUFhLEVBQUMsTUFBTSx5QkFBeUIsQ0FBQTtBQUNoRixPQUFPLEVBQUMsc0JBQXNCLEVBQUMsTUFBTSwrQkFBK0IsQ0FBQTtBQUNwRSxPQUFPLEVBQUMsc0JBQXNCLEVBQUMsTUFBTSx3QkFBd0IsQ0FBQTtBQUU3RCxzRkFBc0Y7QUFDdEYsTUFBTSx3QkFBd0IsR0FBRyxFQUFDLE1BQU0sRUFBRSxhQUFhLEVBQUUsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLEVBQUUsYUFBYSxFQUFDLENBQUE7QUFFeEc7Ozs7OztvREFNb0Q7QUFDcEQsTUFBTSw0QkFBNEIsR0FBRyxDQUFDLFFBQVEsRUFBRSxRQUFRLENBQUMsQ0FBQTtBQUV6RCxvREFBb0Q7QUFDcEQsTUFBTSxnQ0FBZ0MsR0FBRyxJQUFJLE9BQU8sRUFBRSxDQUFBO0FBRXREOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQTZCRztBQUNILE1BQU0sQ0FBQyxPQUFPLE9BQU8sYUFBYTtJQUNoQzs7Ozs7Ozs7T0FRRztJQUNILFlBQVksT0FBTyxHQUFHLEVBQUU7UUFDdEIsTUFBTSxFQUFDLHFCQUFxQixHQUFHLHlCQUF5QixFQUFFLFdBQVcsRUFBRSxhQUFhLEdBQUcsYUFBYSxDQUFDLE9BQU8sRUFBRSxFQUFFLE9BQU8sRUFBRSxTQUFTLEVBQUUsR0FBRyxXQUFXLEVBQUMsR0FBRyxPQUFP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QUFJLE1BQU0sQ0FBQyxPQUFPLENBQUMsVUFBVSxDQUFDLEVBQUUsQ0FBQztRQUNoRSxJQUFJLEtBQUssWUFBWSxJQUFJO1lBQUUsVUFBVSxDQUFDLGFBQWEsQ0FBQyxHQUFHLEtBQUssQ0FBQyxXQUFXLEVBQUUsQ0FBQTtJQUM1RSxDQUFDO0lBRUQsT0FBTyxVQUFVLENBQUE7QUFDbkIsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8vIEB0cy1jaGVja1xuXG5pbXBvcnQgQ29uZmlndXJhdGlvbiBmcm9tIFwiLi4vY29uZmlndXJhdGlvbi5qc1wiXG5pbXBvcnQgTG9nZ2VyIGZyb20gXCIuLi9sb2dnZXIuanNcIlxuaW1wb3J0IHJlc3RBcmdzRXJyb3IgZnJvbSBcIi4uL3V0aWxzL3Jlc3QtYXJncy1lcnJvci5qc1wiXG5cbmltcG9ydCB7ZGVjbGFyZWRTeW5jU2NvcGVBdHRyaWJ1dGVzfSBmcm9tIFwiLi9zeW5jLXNjb3BlLWF0dHJpYnV0ZXMuanNcIlxuaW1wb3J0IHtkZWxpdmVyRGVjbGFyZWRCcm9hZGNhc3RzLCB1cHNlcnRTeW5jUm93fSBmcm9tIFwiLi9zeW5jLWNoYW5nZS1mYW5vdXQuanNcIlxuaW1wb3J0IHtpc1B1Ymxpc2hpbmdTdXBwcmVzc2VkfSBmcm9tIFwiLi9zeW5jLXB1Ymxpc2gtc3VwcHJlc3Npb24uanNcIlxuaW1wb3J0IHtWRUxPQ0lPVVNfU1lOQ19DSEFOTkVMfSBmcm9tIFwiLi9zeW5jLWNoYW5uZWwtbmFtZS5qc1wiXG5cbi8qKiBAdHlwZSB7e2NyZWF0ZTogXCJhZnRlckNyZWF0ZVwiLCB1cGRhdGU6IFwiYWZ0ZXJVcGRhdGVcIiwgZGVzdHJveTogXCJhZnRlckRlc3Ryb3lcIn19ICovXG5jb25zdCBQVUJMSVNIRURfQ0FMTEJBQ0tfTkFNRVMgPSB7Y3JlYXRlOiBcImFmdGVyQ3JlYXRlXCIsIGRlc3Ryb3k6IFwiYWZ0ZXJEZXN0cm95XCIsIHVwZGF0ZTogXCJhZnRlclVwZGF0ZVwifVxuXG4vKipcbiAqIE9wZXJhdGlvbnMgcHVibGlzaGVkIGJ5IGRlZmF1bHQgZm9yIG1vZGVscyBkZWNsYXJpbmcgYHN0YXRpYyBzeW5jYCBwdWJsaXNoXG4gKiB3aXRob3V0IGFuIGBvcGVyYXRpb25zYCBrZXk6IHNlcnZlci1zaWRlIGNyZWF0ZXMgYW5kIHVwZGF0ZXMgcHVibGlzaFxuICogYXV0b21hdGljYWxseS4gRGVzdHJveXMgYXJlIG5vdCBwdWJsaXNoZWQgYnkgZGVmYXVsdCBiZWNhdXNlIGEgc2VydmVyXG4gKiBkZXN0cm95IGlzIG9mdGVuIGNsZWFudXAgcmF0aGVyIHRoYW4gYSBzeW5jZWQgZGVsZXRlOyBvcHQgaW4gd2l0aCBhblxuICogb3BlcmF0aW9ucyBsaXN0LlxuICogQHR5cGUge0FycmF5PFwiY3JlYXRlXCIgfCBcInVwZGF0ZVwiIHwgXCJkZXN0cm95XCI+fSAqL1xuY29uc3QgREVGQVVMVF9QVUJMSVNIRURfT1BFUkFUSU9OUyA9IFtcImNyZWF0ZVwiLCBcInVwZGF0ZVwiXVxuXG4vKiogQHR5cGUge1dlYWtNYXA8Q29uZmlndXJhdGlvbiwgU3luY1B1Ymxpc2hlcj59ICovXG5jb25zdCBzdGFydGVkUHVibGlzaGVyc0J5Q29uZmlndXJhdGlvbiA9IG5ldyBXZWFrTWFwKClcblxuLyoqXG4gKiBEZWNsYXJhdGl2ZSBzZXJ2ZXItc2lkZSBzeW5jIHB1Ymxpc2hlciDigJQgdGhlIHNlcnZlciBtaXJyb3Igb2YgdGhlIGNsaWVudCdzXG4gKiB0cmFjay1ieS1kZWZhdWx0IG11dGF0aW9uIHRyYWNraW5nLlxuICpcbiAqIFNlcnZlciBtb2RlbHMgZGVjbGFyZSB3aGF0IHRvIHB1Ymxpc2ggdGhyb3VnaCBgc3RhdGljIHN5bmNgJ3MgYHB1Ymxpc2hgXG4gKiBrZXksIGFuZCBWZWxvY2lvdXMgd3JpdGVzIGV2ZXJ5IGNvbW1pdHRlZCBzZXJ2ZXItc2lkZSBjaGFuZ2UgdG8gdGhlIHN5bmNcbiAqIGNoYW5nZSBmZWVkIChtb2RlbC1iYWNrZWQgU3luYy1yb3cgdXBzZXJ0IHdpdGggc2VydmVyIHJlLXNlcXVlbmNpbmcpIGFuZFxuICogYnJvYWRjYXN0cyB0aGUgc3RhbmRhcmQgc3luYyBlbnZlbG9wZSAoYHtlY2hvT3JpZ2luLCBzeW5jczogWy4uLl19YCkgb24gdGhlXG4gKiBmcmFtZXdvcmsgc3luYyBjaGFubmVsICh7QGxpbmsgVkVMT0NJT1VTX1NZTkNfQ0hBTk5FTH0pIHNjb3BlZCBieSB0aGVcbiAqIGNoYW5nZSdzIGRlcml2ZWQgc2NvcGUtcGFydGl0aW9uIHZhbHVlcywgc28gZGV2aWNlcyByZWNlaXZlIHNlcnZlci1vcmlnaW5cbiAqIGNoYW5nZXMgd2l0aG91dCBhcHAgY29kZSBkZWNsYXJpbmcgY2hhbm5lbHMgb3IgY2FsbGluZyBtYW51YWxcbiAqIHVwc2VydC9icm9hZGNhc3QgaGVscGVyczpcbiAqXG4gKiAgICAgc3RhdGljIHN5bmMgPSB7cHVibGlzaDogdHJ1ZX0gLy8gZGVmYXVsdCBwYXlsb2FkIChhdHRyaWJ1dGVzKSArIGRlZmF1bHQgc2NvcGUgcGFydGl0aW9uXG4gKiAgICAgc3RhdGljIHN5bmMgPSB7cHVibGlzaDoge3NlcmlhbGl6ZTogKHJlY29yZCkgPT4gKHtpZDogcmVjb3JkLmlkKCksIHBpbjogcmVjb3JkLnBpbigpfSl9fVxuICpcbiAqIFRoZSBzY29wZSBwYXJ0aXRpb24gY29tZXMgZnJvbSB0aGUgc3luYyBtb2RlbCdzIGBzdGF0aWNcbiAqIHN5bmNTY29wZUF0dHJpYnV0ZXNgIGRlY2xhcmF0aW9uIChmb3IgZXhhbXBsZSBgW1wiZXZlbnRJZFwiXWAgb3JcbiAqIGBbXCJhY2NvdW50SWRcIl1gIOKAlCBWZWxvY2lvdXMgaGFzIG5vIGJ1aWx0LWluIHBhcnRpdGlvbiBuYW1lKTogZWFjaCBkZWNsYXJlZFxuICogc2NvcGUgYXR0cmlidXRlIHJlYWRzIHRoZSByZWNvcmQncyBhdHRyaWJ1dGUgb2YgdGhlIHNhbWUgbmFtZSB3aGVuIHRoZVxuICogbW9kZWwgaGFzIG9uZSwgZWxzZSB0aGUgcmVjb3JkJ3Mgb3duIGlkIChzY29wZS1yb290IG1vZGVscyksIG92ZXJyaWRhYmxlXG4gKiBwZXIgbW9kZWwgdGhyb3VnaCBgcHVibGlzaDoge3Njb3BlQXR0cmlidXRlczoge2FjY291bnRJZDogXCJvd25lcklkXCJ9fWAuXG4gKiBUaGUgcHJlLWZyYW1ld29yay1jaGFubmVsIGBicm9hZGNhc3RzYCBsaXN0IGFuZCB0aGUgYGV2ZW50SWRgXG4gKiBzdHJpbmcvcmVzb2x2ZXItZnVuY3Rpb24gZGVjbGFyYXRpb24gZm9ybXMga2VlcCB3b3JraW5nIGJ1dCBhcmUgZGVwcmVjYXRlZC5cbiAqXG4gKiBSZXBsYXllZCBkZXZpY2UgbXV0YXRpb25zIG5ldmVyIGRvdWJsZS1wdWJsaXNoOiB0aGUgZnJhbWV3b3JrJ3Mgcm91dGVkXG4gKiByZXBsYXkgYXBwbHkgbWFya3MgaXRzIHdyaXR0ZW4gcmVjb3JkcyB0aHJvdWdoIGBtYXJrU2VydmVyQXBwbHkocmVjb3JkKWBcbiAqIChzZWUgc3luYy1wdWJsaXNoLXN1cHByZXNzaW9uLmpzKSwgYW5kIGFwcCBjb2RlIGFwcGx5aW5nIGFscmVhZHktc3luY2VkXG4gKiBkYXRhIGNhbiB1c2UgYG1hcmtTZXJ2ZXJBcHBseWAvYHdpdGhvdXRQdWJsaXNoaW5nYCB0aGUgc2FtZSB3YXkuXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFN5bmNQdWJsaXNoZXIge1xuICAvKipcbiAgICogQnVpbGRzIHRoZSBzeW5jIHB1Ymxpc2hlciBieSBkZXJpdmluZyBwdWJsaXNoZWQgcmVzb3VyY2VzIGZyb20gdGhlXG4gICAqIGNvbmZpZ3VyYXRpb24ncyByZWdpc3RlcmVkIG1vZGVsczogZXZlcnkgbW9kZWwgZGVjbGFyaW5nIGBzdGF0aWMgc3luY2BcbiAgICogd2l0aCBhIGBwdWJsaXNoYCBkZWNsYXJhdGlvbiBiZWNvbWVzIGEgcHVibGlzaGVkIHJlc291cmNlXG4gICAqIChgcHVibGlzaDogZmFsc2VgIG9wdHMgb3V0KS4gVGhlIHN5bmMvY2hhbmdlIG1vZGVsIGlzIHRoZSByZWdpc3RlcmVkXG4gICAqIFwiU3luY1wiIG1vZGVsIGFuZCBicm9hZGNhc3RzIGRlZmF1bHQgdG8gdGhlIGNvbmZpZ3VyYXRpb24ncyBjaGFubmVsXG4gICAqIGJyb2FkY2FzdC5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuL3N5bmMtcHVibGlzaGVyLXR5cGVzLmpzXCIpLlN5bmNQdWJsaXNoZXJPcHRpb25zfSBbb3B0aW9uc10gLSBPcHRpb25hbCBvdmVycmlkZXMuXG4gICAqL1xuICBjb25zdHJ1Y3RvcihvcHRpb25zID0ge30pIHtcbiAgICBjb25zdCB7YWN0b3JGb3JlaWduS2V5Q29sdW1uID0gXCJhdXRoZW50aWNhdGlvbl90b2tlbl9pZFwiLCBicm9hZGNhc3RlciwgY29uZmlndXJhdGlvbiA9IENvbmZpZ3VyYXRpb24uY3VycmVudCgpLCBvbkVycm9yLCBzeW5jTW9kZWwsIC4uLnJlc3RPcHRpb25zfSA9IG9wdGlvbnNcblxuICAgIHJlc3RBcmdzRXJyb3IocmVzdE9wdGlvbnMpXG5cbiAgICBjb25zdCBtb2RlbENsYXNzZXMgPSBjb25maWd1cmF0aW9uLmdldE1vZGVsQ2xhc3NlcygpXG4gICAgY29uc3QgcHVibGlzaGluZ01vZGVsQ2xhc3NlcyA9IE9iamVjdC52YWx1ZXMobW9kZWxDbGFzc2VzKS5maWx0ZXIoKG1vZGVsQ2xhc3MpID0+IHB1Ymxpc2hEZWNsYXJhdGlvbkZvcihtb2RlbENsYXNzKSlcblxuICAgIGlmIChwdWJsaXNoaW5nTW9kZWxDbGFzc2VzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiU3luY1B1Ymxpc2hlciBmb3VuZCBubyByZWdpc3RlcmVkIG1vZGVscyBkZWNsYXJpbmcgc3RhdGljIHN5bmMgcHVibGlzaCAtIGRlY2xhcmUgYHN0YXRpYyBzeW5jID0ge3B1Ymxpc2g6IHtzZXJpYWxpemV9fWAgb24gdGhlIG1vZGVscyB3aG9zZSBzZXJ2ZXItc2lkZSBjaGFuZ2VzIHNob3VsZCBwdWJsaXNoIHRvIHRoZSBzeW5jIGZlZWRcIilcbiAgICB9XG5cbiAgICBjb25zdCByZXNvbHZlZFN5bmNNb2RlbCA9IHN5bmNNb2RlbCB8fCBtb2RlbENsYXNzZXMuU3luY1xuXG4gICAgaWYgKCFyZXNvbHZlZFN5bmNNb2RlbCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiU3luY1B1Ymxpc2hlciByZXF1aXJlcyBhIHJlZ2lzdGVyZWQgXFxcIlN5bmNcXFwiIG1vZGVsIGZvciBwdWJsaXNoZWQgc3luYyBjaGFuZ2Ugcm93cyAob3IgcGFzcyBvcHRpb25zLnN5bmNNb2RlbClcIilcbiAgICB9XG5cbiAgICBjb25zdCBzY29wZUF0dHJpYnV0ZXMgPSBkZWNsYXJlZFN5bmNTY29wZUF0dHJpYnV0ZXMocmVzb2x2ZWRTeW5jTW9kZWwpXG4gICAgLyoqIEB0eXBlIHtSZWNvcmQ8c3RyaW5nLCBpbXBvcnQoXCIuL3N5bmMtcHVibGlzaGVyLXR5cGVzLmpzXCIpLlN5bmNQdWJsaXNoZXJSZXNvdXJjZUNvbmZpZz59ICovXG4gICAgY29uc3QgcmVzb3VyY2VzID0ge31cblxuICAgIGZvciAoY29uc3QgbW9kZWxDbGFzcyBvZiBwdWJsaXNoaW5nTW9kZWxDbGFzc2VzKSB7XG4gICAgICBjb25zdCBwdWJsaXNoID0gcHVibGlzaERlY2xhcmF0aW9uRm9yKG1vZGVsQ2xhc3MpXG4gICAgICBjb25zdCByZXNvdXJjZUNvbmZpZyA9IHJlc291cmNlQ29uZmlnRnJvbVB1Ymxpc2hEZWNsYXJhdGlvbih7bW9kZWxDbGFzcywgcHVibGlzaCwgc2NvcGVBdHRyaWJ1dGVzLCBzeW5jTW9kZWw6IHJlc29sdmVkU3luY01vZGVsfSlcblxuICAgICAgcmVzb3VyY2VzW3Jlc291cmNlQ29uZmlnLnJlc291cmNlVHlwZV0gPSByZXNvdXJjZUNvbmZpZ1xuICAgIH1cblxuICAgIC8qKiBAdHlwZSB7e2FjdG9yRm9yZWlnbktleUNvbHVtbjogc3RyaW5nLCBicm9hZGNhc3RlcjogaW1wb3J0KFwiLi9zeW5jLXB1Ymxpc2hlci10eXBlcy5qc1wiKS5TeW5jUHVibGlzaGVyT3B0aW9uc1tcImJyb2FkY2FzdGVyXCJdLCBjb25maWd1cmF0aW9uOiBDb25maWd1cmF0aW9uLCBvbkVycm9yOiBpbXBvcnQoXCIuL3N5bmMtcHVibGlzaGVyLXR5cGVzLmpzXCIpLlN5bmNQdWJsaXNoZXJPcHRpb25zW1wib25FcnJvclwiXSwgcmVzb3VyY2VzOiBSZWNvcmQ8c3RyaW5nLCBpbXBvcnQoXCIuL3N5bmMtcHVibGlzaGVyLXR5cGVzLmpzXCIpLlN5bmNQdWJsaXNoZXJSZXNvdXJjZUNvbmZpZz4sIHN5bmNNb2RlbDogP319ICovXG4gICAgdGhpcy5jb25maWcgPSB7YWN0b3JGb3JlaWduS2V5Q29sdW1uLCBicm9hZGNhc3RlciwgY29uZmlndXJhdGlvbiwgb25FcnJvciwgcmVzb3VyY2VzLCBzeW5jTW9kZWw6IHJlc29sdmVkU3luY01vZGVsfVxuICAgIC8qKiBAdHlwZSB7QXJyYXk8e2NhbGxiYWNrOiAocmVjb3JkOiA/KSA9PiBQcm9taXNlPHZvaWQ+LCBjYWxsYmFja05hbWU6IFwiYWZ0ZXJDcmVhdGVcIiB8IFwiYWZ0ZXJVcGRhdGVcIiB8IFwiYWZ0ZXJEZXN0cm95XCIsIG1vZGVsQ2xhc3M6ID99Pn0gKi9cbiAgICB0aGlzLl9wdWJsaXNoZWRDYWxsYmFja3MgPSBbXVxuICAgIC8qKiBAdHlwZSB7TG9nZ2VyIHwgbnVsbH0gKi9cbiAgICB0aGlzLl9sb2dnZXIgPSBudWxsXG4gICAgdGhpcy5fc3RhcnRlZCA9IGZhbHNlXG4gIH1cblxuICAvKipcbiAgICogQnVpbGRzIGEgc3luYyBwdWJsaXNoZXIgZGVyaXZlZCBmcm9tIHRoZSBnaXZlbiBjb25maWd1cmF0aW9uLiBBbGlhcyBmb3JcbiAgICogYG5ldyBTeW5jUHVibGlzaGVyKHtjb25maWd1cmF0aW9uLCAuLi5vcHRpb25zfSlgLlxuICAgKiBAcGFyYW0ge0NvbmZpZ3VyYXRpb259IFtjb25maWd1cmF0aW9uXSAtIENvbmZpZ3VyYXRpb24gb3duaW5nIHRoZSByZWdpc3RlcmVkIG1vZGVscy4gRGVmYXVsdHMgdG8gdGhlIGN1cnJlbnQgY29uZmlndXJhdGlvbi5cbiAgICogQHBhcmFtIHtPbWl0PGltcG9ydChcIi4vc3luYy1wdWJsaXNoZXItdHlwZXMuanNcIikuU3luY1B1Ymxpc2hlck9wdGlvbnMsIFwiY29uZmlndXJhdGlvblwiPn0gW29wdGlvbnNdIC0gT3B0aW9uYWwgb3ZlcnJpZGVzLlxuICAgKiBAcmV0dXJucyB7U3luY1B1Ymxpc2hlcn0gU3luYyBwdWJsaXNoZXIgZGVyaXZlZCBmcm9tIHRoZSBjb25maWd1cmF0aW9uLlxuICAgKi9cbiAgc3RhdGljIGZyb21Db25maWd1cmF0aW9uKGNvbmZpZ3VyYXRpb24gPSBDb25maWd1cmF0aW9uLmN1cnJlbnQoKSwgb3B0aW9ucyA9IHt9KSB7XG4gICAgcmV0dXJuIG5ldyBTeW5jUHVibGlzaGVyKHsuLi5vcHRpb25zLCBjb25maWd1cmF0aW9ufSlcbiAgfVxuXG4gIC8qKlxuICAgKiBTdGFydHMgKGFuZCBtZW1vaXplcyBwZXIgY29uZmlndXJhdGlvbikgdGhlIHN5bmMgcHVibGlzaGVyIGZvciBhIHNlcnZlclxuICAgKiBib290OiBuby1vcCB3aGVuIG5vIHJlZ2lzdGVyZWQgbW9kZWwgZGVjbGFyZXMgYSBwdWJsaXNoIGNvbmZpZywgZ3VhcmRlZCBzb1xuICAgKiByZXBlYXRlZCBib290cyB3aXRoIHRoZSBzYW1lIGNvbmZpZ3VyYXRpb24gcmVnaXN0ZXIgdGhlIHB1Ymxpc2ggY2FsbGJhY2tzXG4gICAqIG9ubHkgb25jZS5cbiAgICogQHBhcmFtIHtDb25maWd1cmF0aW9ufSBjb25maWd1cmF0aW9uIC0gQ29uZmlndXJhdGlvbiBvd25pbmcgdGhlIHJlZ2lzdGVyZWQgbW9kZWxzLlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTxTeW5jUHVibGlzaGVyIHwgbnVsbD59IFN0YXJ0ZWQgcHVibGlzaGVyLCBvciBudWxsIHdoZW4gbm8gbW9kZWxzIGRlY2xhcmUgcHVibGlzaC5cbiAgICovXG4gIHN0YXRpYyBhc3luYyBzdGFydEZyb21Db25maWd1cmF0aW9uKGNvbmZpZ3VyYXRpb24pIHtcbiAgICBjb25zdCBzdGFydGVkUHVibGlzaGVyID0gc3RhcnRlZFB1Ymxpc2hlcnNCeUNvbmZpZ3VyYXRpb24uZ2V0KGNvbmZpZ3VyYXRpb24pXG5cbiAgICBpZiAoc3RhcnRlZFB1Ymxpc2hlcikgcmV0dXJuIHN0YXJ0ZWRQdWJsaXNoZXJcblxuICAgIGlmICghT2JqZWN0LnZhbHVlcyhjb25maWd1cmF0aW9uLmdldE1vZGVsQ2xhc3NlcygpKS5zb21lKChtb2RlbENsYXNzKSA9PiBwdWJsaXNoRGVjbGFyYXRpb25Gb3IobW9kZWxDbGFzcykpKSByZXR1cm4gbnVsbFxuXG4gICAgY29uc3QgcHVibGlzaGVyID0gbmV3IFN5bmNQdWJsaXNoZXIoe2NvbmZpZ3VyYXRpb259KVxuXG4gICAgc3RhcnRlZFB1Ymxpc2hlcnNCeUNvbmZpZ3VyYXRpb24uc2V0KGNvbmZpZ3VyYXRpb24sIHB1Ymxpc2hlcilcbiAgICBhd2FpdCBwdWJsaXNoZXIuc3RhcnQoKVxuXG4gICAgcmV0dXJuIHB1Ymxpc2hlclxuICB9XG5cbiAgLyoqXG4gICAqIFJlZ2lzdGVycyB0aGUgcHVibGlzaCBjYWxsYmFja3MgZm9yIGV2ZXJ5IHB1Ymxpc2hlZCByZXNvdXJjZTogc2VydmVyLXNpZGVcbiAgICogY3JlYXRlcyBhbmQgdXBkYXRlcyAoZGVzdHJveXMgd2hlbiBvcHRlZCBpbikgdXBzZXJ0IGEgc3luYyBjaGFuZ2Ugcm93IGFuZFxuICAgKiBmYW4gb3V0IHRoZSBkZWNsYXJlZCBicm9hZGNhc3RzIG9uY2UgdGhlaXIgdHJhbnNhY3Rpb24gY29tbWl0cy5cbiAgICogQHJldHVybnMge1Byb21pc2U8dm9pZD59XG4gICAqL1xuICBhc3luYyBzdGFydCgpIHtcbiAgICBpZiAodGhpcy5fc3RhcnRlZCkgcmV0dXJuXG5cbiAgICB0aGlzLl9zdGFydGVkID0gdHJ1ZVxuXG4gICAgZm9yIChjb25zdCByZXNvdXJjZUNvbmZpZyBvZiBPYmplY3QudmFsdWVzKHRoaXMuY29uZmlnLnJlc291cmNlcykpIHtcbiAgICAgIGZvciAoY29uc3Qgb3BlcmF0aW9uIG9mIHJlc291cmNlQ29uZmlnLm9wZXJhdGlvbnMpIHtcbiAgICAgICAgY29uc3QgY2FsbGJhY2tOYW1lID0gUFVCTElTSEVEX0NBTExCQUNLX05BTUVTW29wZXJhdGlvbl1cbiAgICAgICAgY29uc3QgY2FsbGJhY2sgPSB0aGlzLnB1Ymxpc2hlZE11dGF0aW9uQ2FsbGJhY2soe29wZXJhdGlvbiwgcmVzb3VyY2VDb25maWd9KVxuXG4gICAgICAgIHJlc291cmNlQ29uZmlnLm1vZGVsQ2xhc3NbY2FsbGJhY2tOYW1lXShjYWxsYmFjaylcbiAgICAgICAgdGhpcy5fcHVibGlzaGVkQ2FsbGJhY2tzLnB1c2goe2NhbGxiYWNrLCBjYWxsYmFja05hbWUsIG1vZGVsQ2xhc3M6IHJlc291cmNlQ29uZmlnLm1vZGVsQ2xhc3N9KVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBVbnJlZ2lzdGVycyBhbGwgcHVibGlzaCBjYWxsYmFja3MgKHRlc3RzLCBzaHV0ZG93bikuXG4gICAqIEByZXR1cm5zIHt2b2lkfVxuICAgKi9cbiAgc3RvcCgpIHtcbiAgICBmb3IgKGNvbnN0IHtjYWxsYmFjaywgY2FsbGJhY2tOYW1lLCBtb2RlbENsYXNzfSBvZiB0aGlzLl9wdWJsaXNoZWRDYWxsYmFja3MpIHtcbiAgICAgIG1vZGVsQ2xhc3MudW5yZWdpc3RlckxpZmVjeWNsZUNhbGxiYWNrKGNhbGxiYWNrTmFtZSwgY2FsbGJhY2spXG4gICAgfVxuXG4gICAgdGhpcy5fcHVibGlzaGVkQ2FsbGJhY2tzID0gW11cbiAgICB0aGlzLl9zdGFydGVkID0gZmFsc2VcbiAgfVxuXG4gIC8qKlxuICAgKiBCdWlsZHMgdGhlIGxpZmVjeWNsZSBjYWxsYmFjayBwdWJsaXNoaW5nIG9uZSBzZXJ2ZXItc2lkZSBtdXRhdGlvbi4gVGhlXG4gICAqIHB1Ymxpc2hlZCBwYXlsb2FkIChkZWNsYXJhdGlvbiBgc2VyaWFsaXplYCksIGV2ZW50IHNjb3BlLCBhbmQgc3luYyB0eXBlXG4gICAqIGFyZSBzbmFwc2hvdHRlZCBhdCBtdXRhdGlvbi1jYWxsYmFjayB0aW1lLCBzbyBhZnRlclNhdmUgaG9va3MgYXNzaWduaW5nXG4gICAqIHVuc2F2ZWQgYXR0cmlidXRlcyAob3IgYW55IGxhdGVyIGRyaWZ0IG9uIHRoZSByZWNvcmQpIGNhbm5vdCBjaGFuZ2Ugd2hhdFxuICAgKiBnZXRzIHB1Ymxpc2hlZCB2cyB3aGF0IHdhcyBjb21taXR0ZWQuIFBlcnNpc3RpbmcgYW5kIGJyb2FkY2FzdGluZyBhcmVcbiAgICogZGVmZXJyZWQgdGhyb3VnaCB0aGUgbW9kZWwgY29ubmVjdGlvbidzIGFmdGVyQ29tbWl0IGhvb2sgc28gdGhleSBvbmx5IHJ1blxuICAgKiBvbmNlIHRoZSBtdXRhdGlvbidzIHRyYW5zYWN0aW9uIGhhcyBjb21taXR0ZWQgKGltbWVkaWF0ZWx5IHdoZW4gbm9cbiAgICogdHJhbnNhY3Rpb24gaXMgb3BlbikgLSByb2xsZWQtYmFjayBtdXRhdGlvbnMgbmV2ZXIgcHVibGlzaC4gUG9zdC1jb21taXRcbiAgICogcHVibGlzaCBmYWlsdXJlcyBhcmUgcmVwb3J0ZWQgd2l0aG91dCByZXRocm93aW5nIGludG8gdGhlIGRyaXZlcidzXG4gICAqIGFmdGVyQ29tbWl0IGNoYWluIChzZWUgcmVwb3J0QWZ0ZXJDb21taXRFcnJvcikuXG4gICAqIEBwYXJhbSB7e29wZXJhdGlvbjogXCJjcmVhdGVcIiB8IFwidXBkYXRlXCIgfCBcImRlc3Ryb3lcIiwgcmVzb3VyY2VDb25maWc6IGltcG9ydChcIi4vc3luYy1wdWJsaXNoZXItdHlwZXMuanNcIikuU3luY1B1Ymxpc2hlclJlc291cmNlQ29uZmlnfX0gYXJncyAtIE9wZXJhdGlvbiBhbmQgcmVzb3VyY2UgY29uZmlnLlxuICAgKiBAcmV0dXJucyB7KHJlY29yZDogPykgPT4gUHJvbWlzZTx2b2lkPn0gTGlmZWN5Y2xlIGNhbGxiYWNrLlxuICAgKi9cbiAgcHVibGlzaGVkTXV0YXRpb25DYWxsYmFjayh7b3BlcmF0aW9uLCByZXNvdXJjZUNvbmZpZ30pIHtcbiAgICByZXR1cm4gYXN5bmMgKHJlY29yZCkgPT4ge1xuICAgICAgaWYgKGlzUHVibGlzaGluZ1N1cHByZXNzZWQocmVjb3JkKSkgcmV0dXJuXG5cbiAgICAgIGNvbnN0IGRhdGEgPSBhd2FpdCByZXNvdXJjZUNvbmZpZy5zZXJpYWxpemUocmVjb3JkKVxuICAgICAgY29uc3QgcmVzb3VyY2VJZCA9IFN0cmluZyhyZWNvcmQuaWQoKSlcbiAgICAgIGNvbnN0IHN5bmNUeXBlID0gb3BlcmF0aW9uID09PSBcImRlc3Ryb3lcIiA/IFwiZGVsZXRlXCIgOiBcInVwZGF0ZVwiXG4gICAgICBjb25zdCBzY29wZVZhbHVlcyA9IGF3YWl0IHRoaXMucHVibGlzaGVkU2NvcGVWYWx1ZXMoe3JlY29yZCwgcmVzb3VyY2VDb25maWd9KVxuICAgICAgLyoqIEB0eXBlIHtSZWNvcmQ8c3RyaW5nLCA/Pn0gKi9cbiAgICAgIGNvbnN0IGF0dHJpYnV0ZXMgPSB7XG4gICAgICAgIFt0aGlzLmNvbmZpZy5hY3RvckZvcmVpZ25LZXlDb2x1bW5dOiBudWxsLFxuICAgICAgICBjbGllbnRfdXBkYXRlZF9hdDogbmV3IERhdGUoKSxcbiAgICAgICAgZGF0YTogSlNPTi5zdHJpbmdpZnkoZGF0YSksXG4gICAgICAgIHJlc291cmNlX2lkOiByZXNvdXJjZUlkLFxuICAgICAgICByZXNvdXJjZV90eXBlOiByZXNvdXJjZUNvbmZpZy5yZXNvdXJjZVR5cGUsXG4gICAgICAgIHN5bmNfdHlwZTogc3luY1R5cGUsXG4gICAgICAgIC4uLnNjb3BlVmFsdWVzLmNvbHVtbnNcbiAgICAgIH1cblxuICAgICAgYXdhaXQgcmVzb3VyY2VDb25maWcubW9kZWxDbGFzcy5jb25uZWN0aW9uKCkuYWZ0ZXJDb21taXQoYXN5bmMgKCkgPT4ge1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGNvbnN0IHN5bmNSb3cgPSBhd2FpdCB0aGlzLnVwc2VydFB1Ymxpc2hlZFN5bmNSb3coYXR0cmlidXRlcylcblxuICAgICAgICAgIGF3YWl0IHRoaXMuYnJvYWRjYXN0ZXIoKSh7XG4gICAgICAgICAgICBib2R5OiB7XG4gICAgICAgICAgICAgIGVjaG9PcmlnaW46IG51bGwsXG4gICAgICAgICAgICAgIHN5bmNzOiBbe2RhdGEsIHJlc291cmNlSWQsIHJlc291cmNlVHlwZTogcmVzb3VyY2VDb25maWcucmVzb3VyY2VUeXBlLCBzeW5jVHlwZX1dXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgY2hhbm5lbDogVkVMT0NJT1VTX1NZTkNfQ0hBTk5FTCxcbiAgICAgICAgICAgIHBhcmFtczogey4uLnNjb3BlVmFsdWVzLnBhcmFtcywgcmVzb3VyY2VUeXBlOiByZXNvdXJjZUNvbmZpZy5yZXNvdXJjZVR5cGV9XG4gICAgICAgICAgfSlcblxuICAgICAgICAgIGlmIChyZXNvdXJjZUNvbmZpZy5icm9hZGNhc3RzKSB7XG4gICAgICAgICAgICBhd2FpdCBkZWxpdmVyRGVjbGFyZWRCcm9hZGNhc3RzKHtcbiAgICAgICAgICAgICAgYXJnczoge2RhdGEsIG9wZXJhdGlvbiwgcmVjb3JkLCByZXNvdXJjZUlkLCByZXNvdXJjZVR5cGU6IHJlc291cmNlQ29uZmlnLnJlc291cmNlVHlwZSwgc3luY1Jvdywgc3luY1R5cGV9LFxuICAgICAgICAgICAgICBicm9hZGNhc3RlcjogdGhpcy5icm9hZGNhc3RlcigpLFxuICAgICAgICAgICAgICBicm9hZGNhc3RzOiByZXNvdXJjZUNvbmZpZy5icm9hZGNhc3RzXG4gICAgICAgICAgICB9KVxuICAgICAgICAgIH1cbiAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICBhd2FpdCB0aGlzLnJlcG9ydEFmdGVyQ29tbWl0RXJyb3IoLyoqIEB0eXBlIHtFcnJvcn0gKi8gKGVycm9yKSlcbiAgICAgICAgfVxuICAgICAgfSlcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUmVzb2x2ZXMgdGhlIHNjb3BlLXBhcnRpdGlvbiB2YWx1ZXMgZm9yIG9uZSBwdWJsaXNoZWQgbXV0YXRpb24gZnJvbSB0aGVcbiAgICogcmVzb3VyY2UncyBkZXJpdmVkIHNjb3BlIHBsYW46IGVhY2ggZW50cnkgcmVhZHMgaXRzIHJlY29yZCBhdHRyaWJ1dGUgKG9yXG4gICAqIHRoZSByZWNvcmQncyBvd24gaWQgZm9yIHNjb3BlLXJvb3QgbW9kZWxzLCBvciB0aGUgZGVwcmVjYXRlZCByZXNvbHZlclxuICAgKiBmdW5jdGlvbikuIFRoZSB2YWx1ZXMgYXJlIHBlcnNpc3RlZCBvbnRvIHRoZSBzeW5jIHJvdydzIHBhcnRpdGlvbiBjb2x1bW5zXG4gICAqIGFuZCBicm9hZGNhc3QgYXMgdGhlIGZyYW1ld29yayBzeW5jIGNoYW5uZWwncyBzY29waW5nIHBhcmFtcy5cbiAgICogQHBhcmFtIHt7cmVjb3JkOiA/LCByZXNvdXJjZUNvbmZpZzogaW1wb3J0KFwiLi9zeW5jLXB1Ymxpc2hlci10eXBlcy5qc1wiKS5TeW5jUHVibGlzaGVyUmVzb3VyY2VDb25maWd9fSBhcmdzIC0gTXV0YXRlZCByZWNvcmQgYW5kIHJlc291cmNlIGNvbmZpZy5cbiAgICogQHJldHVybnMge1Byb21pc2U8e2NvbHVtbnM6IFJlY29yZDxzdHJpbmcsIHN0cmluZyB8IG51bGw+LCBwYXJhbXM6IFJlY29yZDxzdHJpbmcsIHN0cmluZyB8IG51bGw+fT59IFNjb3BlIHZhbHVlcyBrZXllZCBieSBzeW5jLXJvdyBjb2x1bW4gYW5kIGJ5IHNjb3BlIGF0dHJpYnV0ZS5cbiAgICovXG4gIGFzeW5jIHB1Ymxpc2hlZFNjb3BlVmFsdWVzKHtyZWNvcmQsIHJlc291cmNlQ29uZmlnfSkge1xuICAgIC8qKiBAdHlwZSB7UmVjb3JkPHN0cmluZywgc3RyaW5nIHwgbnVsbD59ICovXG4gICAgY29uc3QgY29sdW1ucyA9IHt9XG4gICAgLyoqIEB0eXBlIHtSZWNvcmQ8c3RyaW5nLCBzdHJpbmcgfCBudWxsPn0gKi9cbiAgICBjb25zdCBwYXJhbXMgPSB7fVxuXG4gICAgZm9yIChjb25zdCBzY29wZVBsYW5FbnRyeSBvZiByZXNvdXJjZUNvbmZpZy5zY29wZVBsYW4pIHtcbiAgICAgIC8qKiBAdHlwZSB7P30gKi9cbiAgICAgIGxldCByYXdWYWx1ZVxuXG4gICAgICBpZiAoc2NvcGVQbGFuRW50cnkucmVzb2x2ZXIpIHtcbiAgICAgICAgcmF3VmFsdWUgPSBhd2FpdCBzY29wZVBsYW5FbnRyeS5yZXNvbHZlcihyZWNvcmQpXG4gICAgICB9IGVsc2UgaWYgKHNjb3BlUGxhbkVudHJ5LnJlY29yZEF0dHJpYnV0ZSkge1xuICAgICAgICByYXdWYWx1ZSA9IHJlY29yZC5yZWFkQXR0cmlidXRlKHNjb3BlUGxhbkVudHJ5LnJlY29yZEF0dHJpYnV0ZSlcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJhd1ZhbHVlID0gcmVjb3JkLmlkKClcbiAgICAgIH1cblxuICAgICAgY29uc3QgdmFsdWUgPSByYXdWYWx1ZSA9PT0gdW5kZWZpbmVkIHx8IHJhd1ZhbHVlID09PSBudWxsID8gbnVsbCA6IFN0cmluZyhyYXdWYWx1ZSlcblxuICAgICAgY29sdW1uc1tzY29wZVBsYW5FbnRyeS5jb2x1bW5OYW1lXSA9IHZhbHVlXG4gICAgICBwYXJhbXNbc2NvcGVQbGFuRW50cnkuc2NvcGVBdHRyaWJ1dGVdID0gdmFsdWVcbiAgICB9XG5cbiAgICByZXR1cm4ge2NvbHVtbnMsIHBhcmFtc31cbiAgfVxuXG4gIC8qKlxuICAgKiBVcHNlcnRzIHRoZSBwdWJsaXNoZWQgc2VydmVyLW9yaWdpbiBzeW5jIHJvdyBmb3IgYSByZXNvdXJjZSBpZGVudGl0eTpcbiAgICogc2VydmVyLW9yaWdpbiByb3dzIGNhcnJ5IGEgbnVsbCBhY3RvciBjb2x1bW4gKG5vIGRldmljZSB0byBlY2hvIHRoZVxuICAgKiBjaGFuZ2UgYmFjayB0byksIHNvIHJlcGVhdGVkIHNlcnZlciBjaGFuZ2VzIHRvIG9uZSByZXNvdXJjZSByZXVzZSBhbmRcbiAgICogcmUtc2VxdWVuY2Ugb25lIGZlZWQgcm93LlxuICAgKiBAcGFyYW0ge1JlY29yZDxzdHJpbmcsID8+fSBhdHRyaWJ1dGVzIC0gU25hcHNob3R0ZWQgc3luYyByb3cgYXR0cmlidXRlcy5cbiAgICogQHJldHVybnMge1Byb21pc2U8Pz59IFVwc2VydGVkIHN5bmMgcm93LlxuICAgKi9cbiAgYXN5bmMgdXBzZXJ0UHVibGlzaGVkU3luY1JvdyhhdHRyaWJ1dGVzKSB7XG4gICAgY29uc3QgZXhpc3RpbmdTeW5jID0gYXdhaXQgdGhpcy5jb25maWcuc3luY01vZGVsXG4gICAgICAud2hlcmUoe1xuICAgICAgICBbdGhpcy5jb25maWcuYWN0b3JGb3JlaWduS2V5Q29sdW1uXTogbnVsbCxcbiAgICAgICAgcmVzb3VyY2VfaWQ6IGF0dHJpYnV0ZXMucmVzb3VyY2VfaWQsXG4gICAgICAgIHJlc291cmNlX3R5cGU6IGF0dHJpYnV0ZXMucmVzb3VyY2VfdHlwZVxuICAgICAgfSlcbiAgICAgIC5maXJzdCgpXG5cbiAgICByZXR1cm4gYXdhaXQgdXBzZXJ0U3luY1Jvdyh7YXR0cmlidXRlcywgZXhpc3RpbmdTeW5jLCBzeW5jTW9kZWw6IHRoaXMuY29uZmlnLnN5bmNNb2RlbH0pXG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyB0aGUgYnJvYWRjYXN0ZXIgZGVsaXZlcmluZyBkZWNsYXJlZCBicm9hZGNhc3RzOiB0aGUgaW5qZWN0ZWQgb25lLFxuICAgKiBvciB0aGUgY29uZmlndXJhdGlvbidzIGNoYW5uZWwgYnJvYWRjYXN0IGF3YWl0ZWQgdGhyb3VnaCB0aGUgcGVuZGluZ1xuICAgKiBicm9hZGNhc3QgcXVldWUuXG4gICAqIEByZXR1cm5zIHtOb25OdWxsYWJsZTxpbXBvcnQoXCIuL3N5bmMtcHVibGlzaGVyLXR5cGVzLmpzXCIpLlN5bmNQdWJsaXNoZXJPcHRpb25zW1wiYnJvYWRjYXN0ZXJcIl0+fSBCcm9hZGNhc3QgZGVsaXZlcmVyLlxuICAgKi9cbiAgYnJvYWRjYXN0ZXIoKSB7XG4gICAgaWYgKHRoaXMuY29uZmlnLmJyb2FkY2FzdGVyKSByZXR1cm4gdGhpcy5jb25maWcuYnJvYWRjYXN0ZXJcblxuICAgIHJldHVybiBhc3luYyAoe2JvZHksIGNoYW5uZWwsIHBhcmFtc30pID0+IHtcbiAgICAgIHRoaXMuY29uZmlnLmNvbmZpZ3VyYXRpb24uYnJvYWRjYXN0VG9DaGFubmVsKGNoYW5uZWwsIHBhcmFtcywgYm9keSlcbiAgICAgIGF3YWl0IHRoaXMuY29uZmlnLmNvbmZpZ3VyYXRpb24uYXdhaXRQZW5kaW5nQnJvYWRjYXN0cygpXG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJlcG9ydHMgYSBwb3N0LWNvbW1pdCBwdWJsaXNoIGZhaWx1cmUuIFRoZSB0cmFuc2FjdGlvbiBoYXMgYWxyZWFkeVxuICAgKiBjb21taXR0ZWQgd2hlbiBhZnRlckNvbW1pdCBjYWxsYmFja3MgcnVuLCBzbyByZXRocm93aW5nIGhlcmUgd291bGQgcG9pc29uXG4gICAqIHRoZSBkcml2ZXIncyBhd2FpdGVkIGFmdGVyQ29tbWl0IGNoYWluIChicmVha2luZyB1bnJlbGF0ZWQgY2FsbGJhY2tzKSAtXG4gICAqIGluc3RlYWQgdGhlIGZhaWx1cmUgZ29lcyB0byB0aGUgY29uZmlndXJlZCBvbkVycm9yIGhvb2ssIG9yIGlzIGVtaXR0ZWQgb25cbiAgICogdGhlIGNvbmZpZ3VyYXRpb24ncyBmcmFtZXdvcmstZXJyb3IvYWxsLWVycm9yIGNoYW5uZWxzIChzbyBwcm9kdWN0aW9uIGJ1Z1xuICAgKiByZXBvcnRpbmcgdmlhIGBjb25maWd1cmF0aW9uLmdldEVycm9yRXZlbnRzKClgIHNlZXMgYSBicm9rZW4gcHVibGlzaFxuICAgKiBwYXRoKSBhbmQgbG9nZ2VkIGxvdWRseSB0aHJvdWdoIHRoZSBwdWJsaXNoZXIncyBsb2dnZXIgd2hlbiBub25lIGlzXG4gICAqIGNvbmZpZ3VyZWQuXG4gICAqIEBwYXJhbSB7RXJyb3J9IGVycm9yIC0gUG9zdC1jb21taXQgcHVibGlzaCBmYWlsdXJlLlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn1cbiAgICovXG4gIGFzeW5jIHJlcG9ydEFmdGVyQ29tbWl0RXJyb3IoZXJyb3IpIHtcbiAgICBpZiAodGhpcy5jb25maWcub25FcnJvcikge1xuICAgICAgdGhpcy5jb25maWcub25FcnJvcihlcnJvcilcblxuICAgICAgcmV0dXJuXG4gICAgfVxuXG4gICAgY29uc3QgZXJyb3JFdmVudHMgPSB0aGlzLmNvbmZpZy5jb25maWd1cmF0aW9uLmdldEVycm9yRXZlbnRzKClcbiAgICBjb25zdCBwYXlsb2FkID0ge2NvbnRleHQ6IHtzdGFnZTogXCJzeW5jLXB1Ymxpc2gtYWZ0ZXItY29tbWl0XCJ9LCBlcnJvcn1cblxuICAgIGVycm9yRXZlbnRzLmVtaXQoXCJmcmFtZXdvcmstZXJyb3JcIiwgcGF5bG9hZClcbiAgICBlcnJvckV2ZW50cy5lbWl0KFwiYWxsLWVycm9yXCIsIHsuLi5wYXlsb2FkLCBlcnJvclR5cGU6IFwiZnJhbWV3b3JrLWVycm9yXCJ9KVxuXG4gICAgYXdhaXQgdGhpcy5sb2dnZXIoKS5lcnJvcihcIlN5bmNQdWJsaXNoZXIgZmFpbGVkIHRvIHB1Ymxpc2ggYSBzZXJ2ZXItc2lkZSBzeW5jIGNoYW5nZSBhZnRlciBjb21taXRcIiwgZXJyb3IpXG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyB0aGUgbGF6aWx5IGJ1aWx0IHB1Ymxpc2hlciBsb2dnZXIuXG4gICAqIEByZXR1cm5zIHtMb2dnZXJ9IFB1Ymxpc2hlciBsb2dnZXIuXG4gICAqL1xuICBsb2dnZXIoKSB7XG4gICAgdGhpcy5fbG9nZ2VyIHx8PSBuZXcgTG9nZ2VyKFwiU3luY1B1Ymxpc2hlclwiLCB7Y29uZmlndXJhdGlvbjogdGhpcy5jb25maWcuY29uZmlndXJhdGlvbn0pXG5cbiAgICByZXR1cm4gdGhpcy5fbG9nZ2VyXG4gIH1cbn1cblxuLyoqXG4gKiBSZXNvbHZlcyBhIG1vZGVsIGNsYXNzJ3MgYWN0aXZlIHB1Ymxpc2ggZGVjbGFyYXRpb24gZnJvbSBgc3RhdGljIHN5bmNgLlxuICogT3B0ZWQtb3V0IChgcHVibGlzaDogZmFsc2VgKSBhbmQgdW5kZWNsYXJlZCBtb2RlbHMgcmVzb2x2ZSB0byBudWxsOyBldmVyeVxuICogb3RoZXIgZGVjbGFyZWQgdmFsdWUgZmxvd3MgaW50byBsb3VkIGRlY2xhcmF0aW9uIHZhbGlkYXRpb24uXG4gKiBAcGFyYW0gez99IG1vZGVsQ2xhc3MgLSBSZWdpc3RlcmVkIG1vZGVsIGNsYXNzLlxuICogQHJldHVybnMge2ltcG9ydChcIi4vc3luYy1wdWJsaXNoZXItdHlwZXMuanNcIikuU3luY1B1Ymxpc2hEZWNsYXJhdGlvbiB8IG51bGx9IEFjdGl2ZSBwdWJsaXNoIGRlY2xhcmF0aW9uLCBvciBudWxsLlxuICovXG5mdW5jdGlvbiBwdWJsaXNoRGVjbGFyYXRpb25Gb3IobW9kZWxDbGFzcykge1xuICBjb25zdCBkZWNsYXJhdGlvbiA9IG1vZGVsQ2xhc3Muc3luY1xuXG4gIGlmICghZGVjbGFyYXRpb24gfHwgdHlwZW9mIGRlY2xhcmF0aW9uICE9PSBcIm9iamVjdFwiIHx8IGRlY2xhcmF0aW9uLnB1Ymxpc2ggPT09IHVuZGVmaW5lZCB8fCBkZWNsYXJhdGlvbi5wdWJsaXNoID09PSBmYWxzZSkgcmV0dXJuIG51bGxcblxuICByZXR1cm4gZGVjbGFyYXRpb24ucHVibGlzaFxufVxuXG4vKipcbiAqIEJ1aWxkcyBvbmUgcHVibGlzaGVkIHJlc291cmNlIGNvbmZpZyBmcm9tIGEgbW9kZWwncyBgc3RhdGljIHN5bmNgIHB1Ymxpc2hcbiAqIGRlY2xhcmF0aW9uLiBgcHVibGlzaDogdHJ1ZWAgb3B0cyBpbiB3aXRoIGFsbCBkZWZhdWx0cyAoYXR0cmlidXRlIHBheWxvYWQsXG4gKiBkZXJpdmVkIHNjb3BlIHBhcnRpdGlvbiwgY3JlYXRlZC91cGRhdGVkIG9wZXJhdGlvbnMpLlxuICogQHBhcmFtIHt7bW9kZWxDbGFzczogPywgcHVibGlzaDogaW1wb3J0KFwiLi9zeW5jLXB1Ymxpc2hlci10eXBlcy5qc1wiKS5TeW5jUHVibGlzaERlY2xhcmF0aW9uIHwgbnVsbCwgc2NvcGVBdHRyaWJ1dGVzOiBzdHJpbmdbXSB8IG51bGwsIHN5bmNNb2RlbDogP319IGFyZ3MgLSBEZWNsYXJhdGlvbiBhcmdzIHBsdXMgdGhlIHN5bmMgbW9kZWwncyBkZWNsYXJlZCBzY29wZSBhdHRyaWJ1dGVzLlxuICogQHJldHVybnMge2ltcG9ydChcIi4vc3luYy1wdWJsaXNoZXItdHlwZXMuanNcIikuU3luY1B1Ymxpc2hlclJlc291cmNlQ29uZmlnfSBEZXJpdmVkIHJlc291cmNlIGNvbmZpZy5cbiAqL1xuZnVuY3Rpb24gcmVzb3VyY2VDb25maWdGcm9tUHVibGlzaERlY2xhcmF0aW9uKHttb2RlbENsYXNzLCBwdWJsaXNoLCBzY29wZUF0dHJpYnV0ZXM6IHN5bmNTY29wZUF0dHJpYnV0ZXMsIHN5bmNNb2RlbH0pIHtcbiAgY29uc3QgbW9kZWxOYW1lID0gbW9kZWxDbGFzcy5nZXRNb2RlbE5hbWUoKVxuICBjb25zdCBub3JtYWxpemVkUHVibGlzaCA9IHB1Ymxpc2ggPT09IHRydWUgPyB7fSA6IHB1Ymxpc2hcblxuICBpZiAoIW5vcm1hbGl6ZWRQdWJsaXNoIHx8IHR5cGVvZiBub3JtYWxpemVkUHVibGlzaCAhPT0gXCJvYmplY3RcIiB8fCBBcnJheS5pc0FycmF5KG5vcm1hbGl6ZWRQdWJsaXNoKSkge1xuICAgIHRocm93IG5ldyBFcnJvcihgJHttb2RlbE5hbWV9IHN0YXRpYyBzeW5jIHB1Ymxpc2ggbXVzdCBiZSB0cnVlLCBmYWxzZSBvciBhIHB1Ymxpc2ggZGVjbGFyYXRpb24gb2JqZWN0LCBnb3Q6ICR7U3RyaW5nKHB1Ymxpc2gpfWApXG4gIH1cblxuICBjb25zdCB7YnJvYWRjYXN0cywgZXZlbnRJZCwgb3BlcmF0aW9ucywgcmVzb3VyY2VUeXBlLCBzY29wZUF0dHJpYnV0ZXMsIHNlcmlhbGl6ZSwgLi4ucmVzdERlY2xhcmF0aW9ufSA9IG5vcm1hbGl6ZWRQdWJsaXNoXG4gIGNvbnN0IHVua25vd25LZXlzID0gT2JqZWN0LmtleXMocmVzdERlY2xhcmF0aW9uKVxuXG4gIGlmICh1bmtub3duS2V5cy5sZW5ndGggPiAwKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGAke21vZGVsTmFtZX0gc3RhdGljIHN5bmMgcHVibGlzaCByZWNlaXZlZCB1bmtub3duIGtleXM6ICR7dW5rbm93bktleXMuam9pbihcIiwgXCIpfSAoc3VwcG9ydGVkOiBicm9hZGNhc3RzLCBldmVudElkIChkZXByZWNhdGVkKSwgb3BlcmF0aW9ucywgcmVzb3VyY2VUeXBlLCBzY29wZUF0dHJpYnV0ZXMsIHNlcmlhbGl6ZSlgKVxuICB9XG4gIGlmIChzZXJpYWxpemUgIT09IHVuZGVmaW5lZCAmJiB0eXBlb2Ygc2VyaWFsaXplICE9PSBcImZ1bmN0aW9uXCIpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYCR7bW9kZWxOYW1lfSBzdGF0aWMgc3luYyBwdWJsaXNoIHNlcmlhbGl6ZSBtdXN0IGJlIGEgZnVuY3Rpb24gYnVpbGRpbmcgdGhlIHB1Ymxpc2hlZCBwYXlsb2FkLCBnb3Q6ICR7U3RyaW5nKHNlcmlhbGl6ZSl9YClcbiAgfVxuICBpZiAob3BlcmF0aW9ucyAhPT0gdW5kZWZpbmVkKSB7XG4gICAgaWYgKCFBcnJheS5pc0FycmF5KG9wZXJhdGlvbnMpIHx8IG9wZXJhdGlvbnMubGVuZ3RoID09PSAwKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYCR7bW9kZWxOYW1lfSBzdGF0aWMgc3luYyBwdWJsaXNoIG9wZXJhdGlvbnMgbXVzdCBiZSBhIG5vbi1lbXB0eSBhcnJheSBvZiBjcmVhdGUvdXBkYXRlL2Rlc3Ryb3lgKVxuICAgIH1cblxuICAgIGZvciAoY29uc3Qgb3BlcmF0aW9uIG9mIG9wZXJhdGlvbnMpIHtcbiAgICAgIGlmICghKG9wZXJhdGlvbiBpbiBQVUJMSVNIRURfQ0FMTEJBQ0tfTkFNRVMpKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgJHttb2RlbE5hbWV9IHN0YXRpYyBzeW5jIHB1Ymxpc2ggb3BlcmF0aW9ucyBtdXN0IGJlIGNyZWF0ZS91cGRhdGUvZGVzdHJveSwgZ290OiAke1N0cmluZyhvcGVyYXRpb24pfWApXG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHtcbiAgICBicm9hZGNhc3RzLFxuICAgIG1vZGVsQ2xhc3MsXG4gICAgb3BlcmF0aW9uczogb3BlcmF0aW9ucyA9PT0gdW5kZWZpbmVkID8gREVGQVVMVF9QVUJMSVNIRURfT1BFUkFUSU9OUyA6IG9wZXJhdGlvbnMsXG4gICAgcmVzb3VyY2VUeXBlOiByZXNvdXJjZVR5cGUgPT09IHVuZGVmaW5lZCA/IG1vZGVsTmFtZSA6IHJlc291cmNlVHlwZSxcbiAgICBzY29wZVBsYW46IHNjb3BlUGxhbkZvcih7ZXZlbnRJZCwgbW9kZWxDbGFzcywgbW9kZWxOYW1lLCBzY29wZUF0dHJpYnV0ZXMsIHN5bmNNb2RlbCwgc3luY1Njb3BlQXR0cmlidXRlc30pLFxuICAgIHNlcmlhbGl6ZTogc2VyaWFsaXplID09PSB1bmRlZmluZWQgPyBkZWZhdWx0U2VyaWFsaXplZEF0dHJpYnV0ZXMgOiBzZXJpYWxpemVcbiAgfVxufVxuXG4vKipcbiAqIERlcml2ZXMgdGhlIHNjb3BlIHBsYW4gcGFydGl0aW9uaW5nIGEgcHVibGlzaGVkIG1vZGVsJ3MgY2hhbmdlczogb25lIGVudHJ5XG4gKiBwZXIgc2NvcGUgYXR0cmlidXRlIGRlY2xhcmVkIG9uIHRoZSBzeW5jIG1vZGVsIChgc3RhdGljXG4gKiBzeW5jU2NvcGVBdHRyaWJ1dGVzYCksIGVhY2ggcmVhZGluZyB0aGUgcmVjb3JkIGF0dHJpYnV0ZSBuYW1lZCBsaWtlIHRoZVxuICogc2NvcGUgYXR0cmlidXRlIChvdmVycmlkYWJsZSB0aHJvdWdoIHRoZSBkZWNsYXJhdGlvbidzIGBzY29wZUF0dHJpYnV0ZXNgXG4gKiBuYW1lIG1hcCksIG9yIHRoZSByZWNvcmQncyBvd24gaWQgd2hlbiB0aGUgbW9kZWwgaGFzIG5vIHN1Y2ggYXR0cmlidXRlXG4gKiAoc2NvcGUtcm9vdCBtb2RlbHMpLiBUaGUgZGVwcmVjYXRlZCBgZXZlbnRJZGAgZGVjbGFyYXRpb24gZm9ybXMgbWFwIHRvIGFcbiAqIGZpeGVkIGBldmVudElkYC9gZXZlbnRfaWRgIHBsYW4gZm9yIDEuMC41MDMgY29tcGF0aWJpbGl0eS5cbiAqIEBwYXJhbSB7e2V2ZW50SWQ6IGltcG9ydChcIi4vc3luYy1wdWJsaXNoZXItdHlwZXMuanNcIikuU3luY1B1Ymxpc2hEZWNsYXJhdGlvbkNvbmZpZ1tcImV2ZW50SWRcIl0sIG1vZGVsQ2xhc3M6ID8sIG1vZGVsTmFtZTogc3RyaW5nLCBzY29wZUF0dHJpYnV0ZXM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gfCB1bmRlZmluZWQsIHN5bmNNb2RlbDogPywgc3luY1Njb3BlQXR0cmlidXRlczogc3RyaW5nW10gfCBudWxsfX0gYXJncyAtIERlY2xhcmF0aW9uIGFuZCBzeW5jLW1vZGVsIHNjb3BlIGFyZ3MuXG4gKiBAcmV0dXJucyB7QXJyYXk8aW1wb3J0KFwiLi9zeW5jLXB1Ymxpc2hlci10eXBlcy5qc1wiKS5TeW5jUHVibGlzaGVyU2NvcGVQbGFuRW50cnk+fSBEZXJpdmVkIHNjb3BlIHBsYW4uXG4gKi9cbmZ1bmN0aW9uIHNjb3BlUGxhbkZvcih7ZXZlbnRJZCwgbW9kZWxDbGFzcywgbW9kZWxOYW1lLCBzY29wZUF0dHJpYnV0ZXMsIHN5bmNNb2RlbCwgc3luY1Njb3BlQXR0cmlidXRlc30pIHtcbiAgY29uc3QgYXR0cmlidXRlTmFtZXMgPSBPYmplY3QudmFsdWVzKG1vZGVsQ2xhc3MuZ2V0Q29sdW1uTmFtZVRvQXR0cmlidXRlTmFtZU1hcCgpKVxuXG4gIGlmIChldmVudElkICE9PSB1bmRlZmluZWQpIHtcbiAgICBpZiAoc2NvcGVBdHRyaWJ1dGVzICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgJHttb2RlbE5hbWV9IHN0YXRpYyBzeW5jIHB1Ymxpc2ggY2FuJ3QgZGVjbGFyZSBib3RoIHNjb3BlQXR0cmlidXRlcyBhbmQgdGhlIGRlcHJlY2F0ZWQgZXZlbnRJZCBmb3JtYClcbiAgICB9XG4gICAgaWYgKHR5cGVvZiBldmVudElkID09PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgIHJldHVybiBbe2NvbHVtbk5hbWU6IFwiZXZlbnRfaWRcIiwgcmVjb3JkQXR0cmlidXRlOiBudWxsLCByZXNvbHZlcjogZXZlbnRJZCwgc2NvcGVBdHRyaWJ1dGU6IFwiZXZlbnRJZFwifV1cbiAgICB9XG4gICAgaWYgKHR5cGVvZiBldmVudElkICE9PSBcInN0cmluZ1wiKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYCR7bW9kZWxOYW1lfSBzdGF0aWMgc3luYyBwdWJsaXNoIGV2ZW50SWQgbXVzdCBiZSBhbiBhdHRyaWJ1dGUtbmFtZSBzdHJpbmcgKG9yIGEgZGVwcmVjYXRlZCByZXNvbHZlciBmdW5jdGlvbiksIGdvdDogJHtTdHJpbmcoZXZlbnRJZCl9YClcbiAgICB9XG4gICAgaWYgKCFhdHRyaWJ1dGVOYW1lcy5pbmNsdWRlcyhldmVudElkKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGAke21vZGVsTmFtZX0gc3RhdGljIHN5bmMgcHVibGlzaCBldmVudElkIGF0dHJpYnV0ZSBkb2Vzbid0IGV4aXN0IG9uIHRoZSBtb2RlbDogJHtldmVudElkfWApXG4gICAgfVxuXG4gICAgcmV0dXJuIFt7Y29sdW1uTmFtZTogXCJldmVudF9pZFwiLCByZWNvcmRBdHRyaWJ1dGU6IGV2ZW50SWQsIHJlc29sdmVyOiB1bmRlZmluZWQsIHNjb3BlQXR0cmlidXRlOiBcImV2ZW50SWRcIn1dXG4gIH1cblxuICBpZiAoc2NvcGVBdHRyaWJ1dGVzICE9PSB1bmRlZmluZWQgJiYgIXN5bmNTY29wZUF0dHJpYnV0ZXMpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYCR7bW9kZWxOYW1lfSBzdGF0aWMgc3luYyBwdWJsaXNoIGRlY2xhcmVzIHNjb3BlQXR0cmlidXRlcyBidXQgdGhlIHN5bmMgbW9kZWwgZGVjbGFyZXMgbm8gc3RhdGljIHN5bmNTY29wZUF0dHJpYnV0ZXNgKVxuICB9XG5cbiAgaWYgKCFzeW5jU2NvcGVBdHRyaWJ1dGVzKSByZXR1cm4gW11cblxuICBpZiAoc2NvcGVBdHRyaWJ1dGVzICE9PSB1bmRlZmluZWQgJiYgKHR5cGVvZiBzY29wZUF0dHJpYnV0ZXMgIT09IFwib2JqZWN0XCIgfHwgQXJyYXkuaXNBcnJheShzY29wZUF0dHJpYnV0ZXMpKSkge1xuICAgIHRocm93IG5ldyBFcnJvcihgJHttb2RlbE5hbWV9IHN0YXRpYyBzeW5jIHB1Ymxpc2ggc2NvcGVBdHRyaWJ1dGVzIG11c3QgYmUgYW4gb2JqZWN0IG1hcHBpbmcgc2NvcGUgYXR0cmlidXRlcyB0byByZWNvcmQgYXR0cmlidXRlIG5hbWVzLCBnb3Q6ICR7U3RyaW5nKHNjb3BlQXR0cmlidXRlcyl9YClcbiAgfVxuXG4gIGZvciAoY29uc3Qgc2NvcGVBdHRyaWJ1dGUgb2YgT2JqZWN0LmtleXMoc2NvcGVBdHRyaWJ1dGVzIHx8IHt9KSkge1xuICAgIGlmICghc3luY1Njb3BlQXR0cmlidXRlcy5pbmNsdWRlcyhzY29wZUF0dHJpYnV0ZSkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgJHttb2RlbE5hbWV9IHN0YXRpYyBzeW5jIHB1Ymxpc2ggc2NvcGVBdHRyaWJ1dGVzIHJlY2VpdmVkIHVua25vd24gc2NvcGUgYXR0cmlidXRlOiAke3Njb3BlQXR0cmlidXRlfSAodGhlIHN5bmMgbW9kZWwgZGVjbGFyZXM6ICR7c3luY1Njb3BlQXR0cmlidXRlcy5qb2luKFwiLCBcIil9KWApXG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHN5bmNTY29wZUF0dHJpYnV0ZXMubWFwKChzY29wZUF0dHJpYnV0ZSkgPT4ge1xuICAgIGNvbnN0IGRlY2xhcmVkUmVjb3JkQXR0cmlidXRlID0gc2NvcGVBdHRyaWJ1dGVzPy5bc2NvcGVBdHRyaWJ1dGVdXG5cbiAgICBpZiAoZGVjbGFyZWRSZWNvcmRBdHRyaWJ1dGUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgaWYgKHR5cGVvZiBkZWNsYXJlZFJlY29yZEF0dHJpYnV0ZSAhPT0gXCJzdHJpbmdcIiB8fCAhYXR0cmlidXRlTmFtZXMuaW5jbHVkZXMoZGVjbGFyZWRSZWNvcmRBdHRyaWJ1dGUpKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgJHttb2RlbE5hbWV9IHN0YXRpYyBzeW5jIHB1Ymxpc2ggc2NvcGVBdHRyaWJ1dGVzLiR7c2NvcGVBdHRyaWJ1dGV9IG11c3QgbmFtZSBhbiBleGlzdGluZyByZWNvcmQgYXR0cmlidXRlLCBnb3Q6ICR7U3RyaW5nKGRlY2xhcmVkUmVjb3JkQXR0cmlidXRlKX1gKVxuICAgICAgfVxuXG4gICAgICByZXR1cm4ge2NvbHVtbk5hbWU6IHN5bmNTY29wZUNvbHVtbk5hbWUoe3Njb3BlQXR0cmlidXRlLCBzeW5jTW9kZWx9KSwgcmVjb3JkQXR0cmlidXRlOiBkZWNsYXJlZFJlY29yZEF0dHJpYnV0ZSwgcmVzb2x2ZXI6IHVuZGVmaW5lZCwgc2NvcGVBdHRyaWJ1dGV9XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIGNvbHVtbk5hbWU6IHN5bmNTY29wZUNvbHVtbk5hbWUoe3Njb3BlQXR0cmlidXRlLCBzeW5jTW9kZWx9KSxcbiAgICAgIHJlY29yZEF0dHJpYnV0ZTogYXR0cmlidXRlTmFtZXMuaW5jbHVkZXMoc2NvcGVBdHRyaWJ1dGUpID8gc2NvcGVBdHRyaWJ1dGUgOiBudWxsLFxuICAgICAgcmVzb2x2ZXI6IHVuZGVmaW5lZCxcbiAgICAgIHNjb3BlQXR0cmlidXRlXG4gICAgfVxuICB9KVxufVxuXG4vKipcbiAqIFJlc29sdmVzIHRoZSBzeW5jLXJvdyBjb2x1bW4gcGVyc2lzdGluZyBhIGRlY2xhcmVkIHNjb3BlIGF0dHJpYnV0ZS5cbiAqIEBwYXJhbSB7e3Njb3BlQXR0cmlidXRlOiBzdHJpbmcsIHN5bmNNb2RlbDogP319IGFyZ3MgLSBTY29wZSBhdHRyaWJ1dGUgYW5kIHN5bmMgbW9kZWwuXG4gKiBAcmV0dXJucyB7c3RyaW5nfSBTeW5jLXJvdyBjb2x1bW4gbmFtZS5cbiAqL1xuZnVuY3Rpb24gc3luY1Njb3BlQ29sdW1uTmFtZSh7c2NvcGVBdHRyaWJ1dGUsIHN5bmNNb2RlbH0pIHtcbiAgY29uc3QgY29sdW1uTmFtZSA9IHN5bmNNb2RlbC5nZXRBdHRyaWJ1dGVOYW1lVG9Db2x1bW5OYW1lTWFwKClbc2NvcGVBdHRyaWJ1dGVdXG5cbiAgaWYgKCFjb2x1bW5OYW1lKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGAke3N5bmNNb2RlbC5uYW1lfSBkZWNsYXJlcyB0aGUgc3luYyBzY29wZSBhdHRyaWJ1dGUgJHtzY29wZUF0dHJpYnV0ZX0gYnV0IGhhcyBubyBtYXRjaGluZyBjb2x1bW4gZm9yIGl0YClcbiAgfVxuXG4gIHJldHVybiBjb2x1bW5OYW1lXG59XG5cbi8qKlxuICogRGVmYXVsdCBwdWJsaXNoIHNlcmlhbGl6ZXI6IHRoZSByZWNvcmQncyBhdHRyaWJ1dGVzIHdpdGggRGF0ZSB2YWx1ZXNcbiAqIHNlcmlhbGl6ZWQgdG8gSVNPIHN0cmluZ3MuXG4gKiBAcGFyYW0gez99IHJlY29yZCAtIE11dGF0ZWQgc2VydmVyIG1vZGVsIHJlY29yZC5cbiAqIEByZXR1cm5zIHtSZWNvcmQ8c3RyaW5nLCA/Pn0gU2VyaWFsaXplZCBhdHRyaWJ1dGVzIHBheWxvYWQuXG4gKi9cbmZ1bmN0aW9uIGRlZmF1bHRTZXJpYWxpemVkQXR0cmlidXRlcyhyZWNvcmQpIHtcbiAgLyoqIEB0eXBlIHtSZWNvcmQ8c3RyaW5nLCA/Pn0gKi9cbiAgY29uc3QgYXR0cmlidXRlcyA9IHsuLi5yZWNvcmQuYXR0cmlidXRlcygpfVxuXG4gIGZvciAoY29uc3QgW2F0dHJpYnV0ZU5hbWUsIHZhbHVlXSBvZiBPYmplY3QuZW50cmllcyhhdHRyaWJ1dGVzKSkge1xuICAgIGlmICh2YWx1ZSBpbnN0YW5jZW9mIERhdGUpIGF0dHJpYnV0ZXNbYXR0cmlidXRlTmFtZV0gPSB2YWx1ZS50b0lTT1N0cmluZygpXG4gIH1cblxuICByZXR1cm4gYXR0cmlidXRlc1xufVxuIl19
|
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
/** @typedef {import("../configuration-types.js").VelociousSyncRealtimeChannelDescriptor} VelociousSyncRealtimeChannelDescriptor */
|
|
2
2
|
/** @typedef {import("../configuration-types.js").VelociousSyncRealtimeWebsocketClient} VelociousSyncRealtimeWebsocketClient */
|
|
3
3
|
/**
|
|
4
|
-
* Derived realtime push bridge for the sync client. Subscribes
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
4
|
+
* Derived realtime push bridge for the sync client. Subscribes every declared
|
|
5
|
+
* pull scope to the framework sync channel ({@link VELOCIOUS_SYNC_CHANNEL})
|
|
6
|
+
* automatically — the subscribe params mirror the scope's
|
|
7
|
+
* `{resourceType, conditions}` so the server authorizes them through the same
|
|
8
|
+
* sync resource authorization as pulls — plus any deprecated legacy channels
|
|
9
|
+
* (config `sync.client.realtime.channels` callback and model-level
|
|
10
|
+
* `static sync = {realtime: {channel}}` declarations). Pushed changes apply
|
|
11
|
+
* through the same derived resource applier as pulls (with echo suppression
|
|
12
|
+
* against tracked re-queueing), own-device messages are dropped by echo
|
|
13
|
+
* origin, and a coalesced `pull()` fires when subscriptions become ready or
|
|
10
14
|
* resume so offline gaps close.
|
|
11
15
|
*/
|
|
12
16
|
export default class SyncRealtimeBridge {
|
|
@@ -40,7 +44,7 @@ export default class SyncRealtimeBridge {
|
|
|
40
44
|
* Subscribes the derived realtime channels (idempotent and single-flighted):
|
|
41
45
|
* an active subscription is kept as-is and a concurrent subscribe awaits the
|
|
42
46
|
* in-flight attempt. Call `unsubscribe()` first to change the context.
|
|
43
|
-
* @param {?} [context] - App context passed to the `sync.client.realtime.channels` callback (runtime values
|
|
47
|
+
* @param {?} [context] - App context passed to the deprecated `sync.client.realtime.channels` callback (runtime scope values).
|
|
44
48
|
* @returns {Promise<void>}
|
|
45
49
|
*/
|
|
46
50
|
subscribe(context?: unknown): Promise<void>;
|
|
@@ -85,12 +89,31 @@ export default class SyncRealtimeBridge {
|
|
|
85
89
|
*/
|
|
86
90
|
realtimeConfiguration(): import("../configuration-types.js").VelociousSyncClientRealtimeConfiguration;
|
|
87
91
|
/**
|
|
88
|
-
* Derives the channel descriptors to subscribe:
|
|
89
|
-
*
|
|
90
|
-
*
|
|
92
|
+
* Derives the channel descriptors to subscribe: one framework sync channel
|
|
93
|
+
* subscription per declared pull scope (the params mirror the scope's
|
|
94
|
+
* `{resourceType, conditions}`), plus the deprecated legacy paths —
|
|
95
|
+
* model-level static realtime declarations and the config channels callback.
|
|
96
|
+
* Fails loudly when nothing is subscribable.
|
|
97
|
+
* @param {?} context - App context passed to the deprecated channels callback.
|
|
91
98
|
* @returns {Promise<Array<VelociousSyncRealtimeChannelDescriptor>>} Channel descriptors.
|
|
92
99
|
*/
|
|
93
100
|
channelDescriptors(context: unknown): Promise<Array<VelociousSyncRealtimeChannelDescriptor>>;
|
|
101
|
+
/**
|
|
102
|
+
* Translates a persisted scope's condition keys to the model's attribute
|
|
103
|
+
* names so the framework channel subscription matches the publisher's
|
|
104
|
+
* attribute-named scoping params: `serializedScopeFromQuery` persists the
|
|
105
|
+
* query's model-normalized column names (for example `project_id`), while
|
|
106
|
+
* scope-partition broadcasts carry attribute names (`projectId`). Keys
|
|
107
|
+
* without a column mapping are already attribute names and pass through;
|
|
108
|
+
* scopes on models without a declared sync resource fail loudly because no
|
|
109
|
+
* attribute mapping exists for them.
|
|
110
|
+
* @param {{conditions: Record<string, ?>, resourceType: string}} scopeRow - Active scope row.
|
|
111
|
+
* @returns {Record<string, ?>} Attribute-named scope conditions.
|
|
112
|
+
*/
|
|
113
|
+
attributeNamedConditions(scopeRow: {
|
|
114
|
+
conditions: Record<string, unknown>;
|
|
115
|
+
resourceType: string;
|
|
116
|
+
}): Record<string, unknown>;
|
|
94
117
|
/**
|
|
95
118
|
* Chains one pushed message onto the serialized apply queue so changes apply
|
|
96
119
|
* in arrival order; failures go to the sync client's error reporting.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sync-realtime-bridge.d.ts","sourceRoot":"","sources":["../../../src/sync/sync-realtime-bridge.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"sync-realtime-bridge.d.ts","sourceRoot":"","sources":["../../../src/sync/sync-realtime-bridge.js"],"names":[],"mappings":"AAKA,mIAAmI;AACnI,+HAA+H;AAE/H;;;;;;;;;;;;GAYG;AACH;IACE;;;OAGG;IACH,4BAFW;QAAC,UAAU,EAAE,OAAO,kBAAkB,EAAE,OAAO,CAAA;KAAC,EAkB1D;IAfC,+CAA4B;IAC5B,yJAAyJ;IACzJ,WADW,KAAK,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,YAAY,EAAE,OAAO,2BAA2B,EAAE,iCAAiC,CAAA;KAAC,CAAC,CAClI;IACnB,0DAA0D;IAC1D,SADW,oCAAoC,GAAG,IAAI,CACnC;IACnB,4BAA4B;IAC5B,eADW,OAAO,CAAC,IAAI,CAAC,CACc;IACtC,uHAAuH;IACvH,aADW,MAAM,CACG;IACpB,mCAAmC;IACnC,gBADW,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CACL;IAC1B,mCAAmC;IACnC,mBADW,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CACF;IAC7B,4DAA4D;IAC5D,QADW,YAAY,GAAG,aAAa,GAAG,cAAc,CAC5B;IAG9B;;;;;;OAMG;IACH,oBAHW,OAAC,GACC,OAAO,CAAC,IAAI,CAAC,CAYzB;IAED;;;;;;;;;OASG;IACH,oBAHW,OAAC,GACC,OAAO,CAAC,IAAI,CAAC,CAgFzB;IAED;;;;;OAKG;IACH,eAFa,OAAO,CAAC,IAAI,CAAC,CAiBzB;IAED;;;OAGG;IACH,UAFa;QAAC,QAAQ,EAAE,KAAK,CAAC;YAAC,OAAO,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,OAAO,CAAC;YAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;SAAC,CAAC,CAAC;QAAC,KAAK,EAAE,YAAY,GAAG,aAAa,GAAG,cAAc,CAAA;KAAC,CAOnJ;IAED;;;OAGG;IACH,kBAFa,OAAO,CAAC,IAAI,CAAC,CAKzB;IAED;;;OAGG;IACH,yBAFa,OAAO,2BAA2B,EAAE,wCAAwC,CAUxF;IAED;;;;;;;;OAQG;IACH,4BAHW,OAAC,GACC,OAAO,CAAC,KAAK,CAAC,sCAAsC,CAAC,CAAC,CA6BlE;IAED;;;;;;;;;;;OAWG;IACH,mCAHW;QAAC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAC,CAAC,CAAC;QAAC,YAAY,EAAE,MAAM,CAAA;KAAC,GACnD,MAAM,CAAC,MAAM,EAAE,OAAC,CAAC,CAkB7B;IAED;;;;;OAKG;IACH,qCAHW;QAAC,IAAI,EAAE,OAAC,CAAC;QAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;KAAC,GACpC,IAAI,CAUhB;IAED;;;;;;OAMG;IACH,qCAHW;QAAC,IAAI,EAAE,OAAC,CAAC;QAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;KAAC,GACpC,OAAO,CAAC,IAAI,CAAC,CAuBzB;IAED;;;;;OAKG;IACH,gBAFa,IAAI,CAchB;CACF;qDAlVa,OAAO,2BAA2B,EAAE,sCAAsC;mDAC1E,OAAO,2BAA2B,EAAE,oCAAoC"}
|